static void checkPx4RebootCommand(uint8_t b) { if (intermcu.stable_px4_baud == CHANGING_BAUD && sys_time_check_and_ack_timer(px4bl_tid)) { //to prevent a short intermcu comm loss, give some time to changing the baud sys_time_cancel_timer(px4bl_tid); intermcu.stable_px4_baud = PPRZ_BAUD; } else if (intermcu.stable_px4_baud == PX4_BAUD) { if (sys_time_check_and_ack_timer(px4bl_tid)) { //time out the possibility to reboot to the px4 bootloader, to prevent unwanted restarts during flight sys_time_cancel_timer(px4bl_tid); //for unknown reasons, 1500000 baud does not work reliably after prolonged times. //I suspect a temperature related issue, combined with the fbw f1 crystal which is out of specs //After a initial period on 1500000, revert to 230400 //We still start at 1500000 to remain compatible with original PX4 firmware. (which always runs at 1500000) uart_periph_set_baudrate(intermcu.device->periph, B230400); intermcu.stable_px4_baud = CHANGING_BAUD; px4bl_tid = sys_time_register_timer(1.0, NULL); return; } #ifdef SYS_TIME_LED LED_ON(SYS_TIME_LED); #endif if (b == px4RebootSequence[px4RebootSequenceCount]) { px4RebootSequenceCount++; } else { px4RebootSequenceCount = 0; } if (px4RebootSequenceCount >= 6) { // 6 = length of rebootSequence + 1 px4RebootSequenceCount = 0; // should not be necessary... //send some magic back //this is the same as the Pixhawk IO code would send intermcu.device->put_byte(intermcu.device->periph, 0, 0x00); intermcu.device->put_byte(intermcu.device->periph, 0, 0xe5); intermcu.device->put_byte(intermcu.device->periph, 0, 0x32); intermcu.device->put_byte(intermcu.device->periph, 0, 0x0a); intermcu.device->put_byte(intermcu.device->periph, 0, 0x66); // dummy byte, seems to be necessary otherwise one byte is missing at the fmu side... while (((struct uart_periph *)(intermcu.device->periph))->tx_running) { // tx_running is volatile now, so LED_TOGGLE not necessary anymore #ifdef SYS_TIME_LED LED_TOGGLE(SYS_TIME_LED); #endif } #ifdef SYS_TIME_LED LED_OFF(SYS_TIME_LED); #endif scb_reset_system(); } } }
static void checkPx4RebootCommand(unsigned char b) { if (!px4RebootTimeout) { if (sys_time_check_and_ack_timer(px4bl_tid)) { //time out the possibility to reboot to the px4 bootloader, to prevent unwanted restarts during flight px4RebootTimeout = true; sys_time_cancel_timer(px4bl_tid); return; } #ifdef SYS_TIME_LED LED_ON(SYS_TIME_LED); #endif if (b == px4RebootSequence[px4RebootSequenceCount]) { px4RebootSequenceCount++; } else { px4RebootSequenceCount = 0; } if (px4RebootSequenceCount >= 6) { // 6 = length of rebootSequence + 1 px4RebootSequenceCount = 0; // should not be necessary... //send some magic back //this is the same as the Pixhawk IO code would send intermcu_device->put_byte(intermcu_device->periph, 0x00); intermcu_device->put_byte(intermcu_device->periph, 0xe5); intermcu_device->put_byte(intermcu_device->periph, 0x32); intermcu_device->put_byte(intermcu_device->periph, 0x0a); intermcu_device->put_byte(intermcu_device->periph, 0x66); // dummy byte, seems to be necessary otherwise one byte is missing at the fmu side... while (((struct uart_periph *)(intermcu_device->periph))->tx_running) { // tx_running is volatile now, so LED_TOGGLE not necessary anymore #ifdef SYS_TIME_LED LED_TOGGLE(SYS_TIME_LED); #endif } #ifdef SYS_TIME_LED LED_OFF(SYS_TIME_LED); #endif scb_reset_system(); } } }
void px4flash_event(void) { if (PX4IO_PORT->char_available(PX4IO_PORT->periph)) { if (!setToBootloaderMode) { //ignore anything coming from IO if not in bootloader mode (which should be nothing) } else { //relay everything from IO to the laptop while (PX4IO_PORT->char_available(PX4IO_PORT->periph)) { unsigned char b = PX4IO_PORT->get_byte(PX4IO_PORT->periph); FLASH_PORT->put_byte(FLASH_PORT->periph, b); } } } //TODO: check if bootloader timeout was surpassed if (FLASH_PORT->char_available(FLASH_PORT->periph) && !setToBootloaderMode) { // TMP TEST // while (FLASH_PORT->char_available(FLASH_PORT->periph)) { // unsigned char bla = FLASH_PORT->get_byte(FLASH_PORT->periph); // FLASH_PORT->put_byte(FLASH_PORT->periph,bla); // } // return; //check whether this is flash related communication, and for who (ap/fbw) int state = 0; while (state < 4 && FLASH_PORT->char_available(FLASH_PORT->periph)) { unsigned char b = FLASH_PORT->get_byte(FLASH_PORT->periph); switch (state) { case (0) : if (b == 'p') { state++; } else { return; } break; case (1) : if (b == 'p') { state++; } else { return; } break; case (2) : if (b == 'r') { state++; } else { return; } break; case (3) : if (b == 'z') { state++; } else { return; } break; default : break; } } if (state != 4) {return;} //TODO: check if/how this interferes with flashing original PX4 firmware unsigned char target = FLASH_PORT->get_byte(FLASH_PORT->periph); if (target == '1') { //target ap //the target is the ap, so reboot to PX4 bootloader scb_reset_system(); } else { // target fbw //the target is the fbw, so reboot the fbw and switch to relay mode //first check if the bootloader has not timeout: if (sys_time_check_and_ack_timer(px4iobl_tid) || px4ioRebootTimeout) { px4ioRebootTimeout = TRUE; sys_time_cancel_timer(px4iobl_tid); FLASH_PORT->put_byte(FLASH_PORT->periph, 'T'); FLASH_PORT->put_byte(FLASH_PORT->periph, 'I'); FLASH_PORT->put_byte(FLASH_PORT->periph, 'M'); FLASH_PORT->put_byte(FLASH_PORT->periph, 'E'); FLASH_PORT->put_byte(FLASH_PORT->periph, 'O'); FLASH_PORT->put_byte(FLASH_PORT->periph, 'U'); FLASH_PORT->put_byte(FLASH_PORT->periph, 'T'); // use 7 chars as answer return; } { // FBW OK OK hollay hollay :) FLASH_PORT->put_byte(FLASH_PORT->periph, 'F'); FLASH_PORT->put_byte(FLASH_PORT->periph, 'B'); FLASH_PORT->put_byte(FLASH_PORT->periph, 'W'); FLASH_PORT->put_byte(FLASH_PORT->periph, 'O'); FLASH_PORT->put_byte(FLASH_PORT->periph, 'K'); FLASH_PORT->put_byte(FLASH_PORT->periph, 'O'); FLASH_PORT->put_byte(FLASH_PORT->periph, 'K'); // use 7 chars as answer } //stop all intermcu communication: disable_inter_comm(true); /* * The progdieshit define is very usefull, if for whatever reason the (normal, not bootloader) firmware on the IO chip became disfunct. * In that case: * 1. enable this define * 2. build and upload the fmu f4 chip (ap target in pprz center) * 3. build the io code, and convert the firmware using the following command: * /home/houjebek/paparazzi/sw/tools/px4/px_mkfw.py --prototype "/home/houjebek/px4/Firmware/Images/px4io-v2.prototype" --image /home/houjebek/paparazzi/var/aircrafts/Iris/fbw/fbw.bin > /home/houjebek/paparazzi/var/aircrafts/Iris/fbw/fbw.px4 * 4. Start the following command: * /home/houjebek/paparazzi/sw/tools/px4/px_uploader.py --port "/dev/ttyACM0" /home/houjebek/paparazzi/var/aircrafts/Iris/fbw/fbw.px4 * 5a. Either, boot the Pixhawk (reconnect usb) holding the IO reset button until the FMU led stops blinking fast (i.e. exits its own bootloader) * 5b Or, press the IO reset button on the pixhawk * 6. Watch the output of the command of step 4, it should recognize the IO bootloader and start flashing. If not try repeating step 5a. * 7. Don forget to disable the define and upload the ap again :) */ // #define progdieshit #ifndef progdieshit //send the reboot to bootloader command: static struct IOPacket dma_packet; dma_packet.count_code = 0x40 + 0x01; dma_packet.crc = 0; dma_packet.page = PX4IO_PAGE_SETUP; dma_packet.offset = PX4IO_P_SETUP_REBOOT_BL; dma_packet.regs[0] = PX4IO_REBOOT_BL_MAGIC; dma_packet.crc = crc_packet(&dma_packet); struct IOPacket *pkt = &dma_packet; uint8_t *p = (uint8_t *)pkt; PX4IO_PORT->put_byte(PX4IO_PORT->periph, p[0]); PX4IO_PORT->put_byte(PX4IO_PORT->periph, p[1]); PX4IO_PORT->put_byte(PX4IO_PORT->periph, p[2]); PX4IO_PORT->put_byte(PX4IO_PORT->periph, p[3]); PX4IO_PORT->put_byte(PX4IO_PORT->periph, p[4]); PX4IO_PORT->put_byte(PX4IO_PORT->periph, p[5]); sys_time_usleep(5000); // this seems to be close to the minimum delay necessary to process this packet at the IO side //the pixhawk IO chip should respond with: // 0x00 ( PKT_CODE_SUCCESS ) // 0xe5 // 0x32 // 0x0a //After that, the IO chips reboots into bootloader mode, in which it will stay for a short period //The baudrate in bootloader mode ic changed to 115200 (normal operating baud is 1500000, at least for original pixhawk fmu firmware) //state machine state = 0; while (state < 4 && PX4IO_PORT->char_available(PX4IO_PORT->periph)) { unsigned char b = PX4IO_PORT->get_byte(PX4IO_PORT->periph); switch (state) { case (0) : if (b == PKT_CODE_SUCCESS) { state++; } else { state = 0; } break; case (1) : if (b == 0xe5) { state++; } else { state = 0; } break; case (2) : if (b == 0x32) { state++; } else { state = 0; } break; case (3) : if (b == 0x0a) { state++; } else { state = 0; } break; default : break; } } #else int state = 4; #endif if (state == 4) { uart_periph_set_baudrate(PX4IO_PORT->periph, B115200); /* look for the bootloader for 150 ms */ int ret = 0; for (int i = 0; i < 15 && !ret ; i++) { sys_time_usleep(10000); //send a get_sync command in order to keep the io in bootloader mode PX4IO_PORT->put_byte(PX4IO_PORT->periph, PROTO_GET_SYNC); PX4IO_PORT->put_byte(PX4IO_PORT->periph, PROTO_EOC); //get_sync should be replied with, so check if that happens and //all other bytes are discarded, hopefully those were not important //(they may be caused by sending multiple syncs) while (PX4IO_PORT->char_available(PX4IO_PORT->periph)) { unsigned char b = PX4IO_PORT->get_byte(PX4IO_PORT->periph); if (b == PROTO_INSYNC) { setToBootloaderMode = true; ret = 1; break; } } } if (setToBootloaderMode) { //if successfully entered bootloader mode, clear any remaining bytes (which may have a function, but I did not check) while (PX4IO_PORT->char_available(PX4IO_PORT->periph)) {PX4IO_PORT->get_byte(PX4IO_PORT->periph);} } } else { FLASH_PORT->put_byte(FLASH_PORT->periph, 'E'); //TODO: find out what the PX4 protocol for error feedback is... FLASH_PORT->put_byte(FLASH_PORT->periph, 'R'); FLASH_PORT->put_byte(FLASH_PORT->periph, 'R'); FLASH_PORT->put_byte(FLASH_PORT->periph, 'O'); FLASH_PORT->put_byte(FLASH_PORT->periph, 'R'); FLASH_PORT->put_byte(FLASH_PORT->periph, '!'); FLASH_PORT->put_byte(FLASH_PORT->periph, ' '); // use 7 chars as answer } } } else if (FLASH_PORT->char_available(FLASH_PORT->periph)) { //already in bootloader mode, just directly relay data while (FLASH_PORT->char_available(FLASH_PORT->periph)) { unsigned char b = FLASH_PORT->get_byte(FLASH_PORT->periph); PX4IO_PORT->put_byte(PX4IO_PORT->periph, b); } } }