Esempio n. 1
0
/* For interrupt handling we add a new function which is called
 * when recieve interrupts happen. The name (usart1_isr) is created
 * by the irq.json file in libopencm3 calling this interrupt for
 * USART2 'usart2', adding the suffix '_isr', and then weakly binding
 * it to the 'do nothing' interrupt function in vec.c.
 *
 * By defining it in this file the linker will override that weak
 * binding and instead bind it here, but you have to get the name
 * right or it won't work. And you'll wonder where your interrupts
 * are going.
 */
void usart1_isr(void)
{
	uint32_t	reg;
	int			i;

	do {
		reg = USART_SR(CONSOLE_UART);
		if (reg & USART_SR_RXNE) {
			recv_buf[recv_ndx_nxt] = USART_DR(CONSOLE_UART);
#ifdef RESET_ON_CTRLC
			/*
			 * This bit of code will jump to the ResetHandler if you
			 * hit ^C
			 */
			if (recv_buf[recv_ndx_nxt] == '\003') {
				scb_reset_system();
				return; /* never actually reached */
			}
#endif
			/* Check for "overrun" */
			i = (recv_ndx_nxt + 1) % RECV_BUF_SIZE;
			if (i != recv_ndx_cur) {
				recv_ndx_nxt = i;
			}
		}
	/* can read back-to-back interrupts */
	} while ((reg & USART_SR_RXNE) != 0);
}
Esempio n. 2
0
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();
    }
  }
}
Esempio n. 3
0
void dfu_detach(void)
{
	/* Disconnect USB cable by resetting USB Device
	   and pulling USB_DP low*/
	rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN);
	rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN);
	rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN);
	rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
	gpio_clear(GPIOA, GPIO12);
	gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
		GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12);
	scb_reset_system();
}
Esempio n. 4
0
void stfub_protect_pages_and_reset(u8 mask)
{
	/*
	  Fixme what would happen if Vcc dissapears in
	  the middle of this code's execution
	*/

	struct option_bytes *ob = (struct option_bytes *)&_option_bytes_start;

	flash_unlock();
	flash_program_option_bytes((u32)&ob->wrp0, ob->wrp0 & (~mask));
	flash_lock();

	scb_reset_system();
}
Esempio n. 5
0
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();
        }
    }
}
Esempio n. 6
0
/* For interrupt handling we add a new function which is called
 * when receive interrupts happen. The name (usart1_isr) is created
 * by the irq.json file in libopencm3 calling this interrupt for
 * USART1 'usart1', adding the suffix '_isr', and then weakly binding
 * it to the 'do nothing' interrupt function in vec.c.
 *
 * By defining it in this file the linker will override that weak
 * binding and instead bind it here, but you have to get the name
 * right or it won't work. And you'll wonder where your interrupts
 * are going.
 */
void usart1_isr(void)
{
	uint32_t	reg;
	int			i;

	do {
		reg = USART_SR(CONSOLE_UART);
		if (reg & USART_SR_RXNE) {
			recv_buf[recv_ndx_nxt] = USART_DR(CONSOLE_UART);
#ifdef RESET_ON_CTRLC
			/* Check for "reset" */
			if (recv_buf[recv_ndx_nxt] == '\003') {
				scb_reset_system();
			}
#endif
			/* Check for "overrun" */
			i = (recv_ndx_nxt + 1) % RECV_BUF_SIZE;
			if (i != recv_ndx_cur) {
				recv_ndx_nxt = i;
			}
		}
	} while ((reg & USART_SR_RXNE) != 0);
				/* can read back-to-back interrupts */
}
Esempio n. 7
0
void PWR_JumpToProgrammer()
{
    scb_reset_system();
}
Esempio n. 8
0
  void handle_message(const Command &msg) {
    if(msg.dest != dest) return;
    
    Response resp; memset(&resp, 0, sizeof(resp));
    resp.id = msg.id;
    
    switch(msg.command) {
    
      case CommandID::Reset: {
        // action happens later, after response is sent
      } break;
    
      case CommandID::GetStatus: {
        resp.resp.GetStatus.magic = GetStatusResponse::MAGIC_VALUE;
      } break;
      
      case CommandID::GetProgramHash: {
        if(msg.args.GetProgramHash.length > static_cast<int64_t>(client_flash_end - client_flash_start)) {
          resp.resp.GetProgramHash.error_number = 1;
          break;
        }
        
        uf_subbus_protocol::sha256_state md; uf_subbus_protocol::sha256_init(md);
        uf_subbus_protocol::sha256_process(md, client_flash_start, msg.args.GetProgramHash.length);
        
        resp.resp.GetProgramHash.error_number = 0;
        uf_subbus_protocol::sha256_done(md, resp.resp.GetProgramHash.hash);
      } break;
      
      case CommandID::Erase: {
        if(msg.args.Erase.min_length > client_flash_end - client_flash_start) {
          resp.resp.Erase.error_number = 1;
          break;
        }
        
        flash_unlock();
        
        uint8_t *to_erase = client_flash_start;
        bool failed = false;
        while(to_erase - client_flash_start < msg.args.Erase.min_length) {
          if(!flash_erase(to_erase)) {
            failed = true;
            break;
          }
          to_erase += 2048;
        }
        
        flash_lock();
        
        if(failed) {
          resp.resp.Erase.error_number = 2;
          break;
        }
        
        resp.resp.Erase.error_number = 0;
      } break;
      
      case CommandID::Flash: {
        if(msg.args.Flash.length > FlashCommand::MAX_LENGTH) {
          resp.resp.Flash.error_number = 1;
          break;
        }
        if(static_cast<int64_t>(msg.args.Flash.start_offset) +
            msg.args.Flash.length > client_flash_end - client_flash_start) {
          resp.resp.Flash.error_number = 2;
          break;
        }
        
        flash_unlock();
        bool success = flash_write(
          client_flash_start + msg.args.Flash.start_offset,
          msg.args.Flash.data, msg.args.Flash.length);
        flash_lock();
        if(!success) {
          resp.resp.Flash.error_number = 3;
          break;
        }
        
        resp.resp.Flash.error_number = 0;
      } break;

      case CommandID::RunProgram: {
        // action happens later, after response is sent
      } break;

      default: {
        return; // send nothing back if command is invalid
      } break;

    }
    
    if(resp.id) {
      sender.write_object(resp);
    }
    
    switch(msg.command) {
      case CommandID::Reset: {
        scb_reset_system();
      } break;

      case CommandID::RunProgram: {
        SCB_VTOR = reinterpret_cast<uint32_t>(client_flash_start);

        vector_table_t *new_vector_table = reinterpret_cast<vector_table_t*>(client_flash_start);

        asm("mov SP, %0;bx %1;" ::
          "r"(new_vector_table->initial_sp_value),
          "r"(new_vector_table->reset));
      } break;
      
      default: {
      } break;
    }
  }
Esempio n. 9
0
void dfu_detach(void)
{
	/* USB device must detach, we just reset... */
	scb_reset_system();
}
Esempio n. 10
0
inline void
reboot(void) {
  scb_reset_system();
}
Esempio n. 11
0
/*
 * board_reset() - Request board reset
 *
 * INPUT
 *     none
 * OUTPUT
 *     none
 */
void board_reset(void)
{
#ifndef EMULATOR
    scb_reset_system();
#endif
}
Esempio n. 12
0
void process_cmd(struct cmd_frame_t *cmd)
{
        int res;
        
        reply.status = ACK; // change to NACK as necessary
        reply.cmd = cmd->cmd;

        switch (cmd->cmd) {
        case CMD_ECHO:
                reply.data[0] = cmd->echo.length;
                memcpy(&reply.data[1], cmd->echo.data, cmd->echo.length);
                send_reply(&reply, cmd->echo.length+3);
                break;

        case CMD_RESET:
                if (cmd->reset_magic == RESET_MAGIC) {
                        usb_peripheral_reset();
                        CREG_M4MEMMAP = 0x10400000;
                        scb_reset_system();
                } else {
                        send_nack();
                }
                break;

        case CMD_GET_EVENT_COUNTERS:
        {
                struct event_counters counters = get_last_event_counters();
                memcpy(reply.data, &counters, sizeof(struct event_counters));
                send_reply(&reply, 2+sizeof(struct event_counters));
                break;
        }

        case CMD_GET_STAGE_GAINS:
                memcpy(reply.data, stage_fb_gains, sizeof(stage_fb_gains));
                send_reply(&reply, 2+sizeof(stage_fb_gains));
                break;

        case CMD_SET_STAGE_GAINS:
                memcpy(stage_fb_gains, cmd->set_stage_gains, sizeof(stage_fb_gains));
                send_ack();
                break;
                
        case CMD_GET_STAGE_SETPOINT:
                memcpy(reply.data, stage_fb_setpoint, sizeof(stage_fb_setpoint));
                send_reply(&reply, 2+sizeof(stage_fb_setpoint));
                break;

        case CMD_SET_STAGE_SETPOINT:
                memcpy(stage_fb_setpoint, cmd->set_stage_setpoint, sizeof(stage_fb_setpoint));
                send_ack();
                break;

        case CMD_GET_PSD_GAINS:
                memcpy(reply.data, psd_fb_gains, sizeof(psd_fb_gains));
                send_reply(&reply, 2+sizeof(psd_fb_gains));
                break;

        case CMD_SET_PSD_GAINS:
                memcpy(psd_fb_gains, cmd->set_psd_gains, sizeof(psd_fb_gains));
                send_ack();
                break;

        case CMD_GET_PSD_SETPOINT:
                memcpy(reply.data, psd_fb_setpoint, sizeof(psd_fb_setpoint));
                send_reply(&reply, 2+sizeof(psd_fb_setpoint));
                break;

        case CMD_SET_PSD_SETPOINT:
                memcpy(psd_fb_setpoint, cmd->set_psd_setpoint, sizeof(psd_fb_setpoint));
                send_ack();
                break;
        
        case CMD_GET_MAX_ERROR:
                memcpy(reply.data, &max_error, sizeof(max_error));
                send_reply(&reply, 2+sizeof(max_error));
                break;

        case CMD_SET_MAX_ERROR:
                max_error = cmd->set_max_error;
                send_ack();
                break;

        case CMD_GET_OUTPUT_GAINS:
        {
                fixed16_t* tmp = (fixed16_t*) reply.data;
                for (unsigned int i=0; i<STAGE_OUTPUTS; i++) {
                        *tmp = stage_outputs[i].p_gain; tmp++;
                        *tmp = stage_outputs[i].i_gain; tmp++;
                }
                send_reply(&reply, 2+2*STAGE_OUTPUTS*sizeof(fixed16_t));
                break;
        }

        case CMD_SET_OUTPUT_GAINS:
        {
                for (unsigned int i=0; i<STAGE_OUTPUTS; i++) {
                        stage_outputs[i].p_gain = cmd->set_output_gains[i][0];
                        stage_outputs[i].i_gain = cmd->set_output_gains[i][1];
                }
                send_ack();
                break;
        }

        case CMD_GET_OUTPUT_TAUS:
        {
                for (unsigned int i=0; i<STAGE_OUTPUTS; i++) {
                        reply.data[i] = pi_get_tau(&stage_outputs[i]);
                }
                send_reply(&reply, 2+3);
                break;
        }

        case CMD_SET_OUTPUT_TAUS:
        {
                for (unsigned int i=0; i<STAGE_OUTPUTS; i++) {
                        pi_set_tau(&stage_outputs[i], cmd->set_output_taus[i]);
                }
                send_ack();
                break;
        }

        case CMD_GET_ADC_FREQ:
                reply.data32[0] = 0; //TODO adc_get_trigger_freq();
                send_reply(&reply, 2+4);
                break;

        case CMD_SET_ADC_FREQ:
                adc_set_trigger_freq(cmd->set_adc_freq);
                send_ack();
                break;
                
        case CMD_GET_ADC_TRIGGER_MODE:
                reply.data[0] = adc_get_trigger_mode();
                send_reply(&reply, 2+1);
                break;

        case CMD_SET_ADC_TRIGGER_MODE:
                adc_set_trigger_mode(cmd->set_adc_trigger_mode);
                send_ack();
                break;

        case CMD_START_ADC_STREAM:
                adc_streaming = true;
                send_ack();
                break;

        case CMD_STOP_ADC_STREAM:
                adc_streaming = false;
                adc_flush();
                send_ack();
                break;

        case CMD_FLUSH_ADC_STREAM:
                if (adc_flush() == 0) {
                        send_ack();
                } else {
                        send_nack();
                }
                break;

        case CMD_GET_ADC_DECIMATION:
        {
                reply.data32[0] = adc_get_decimation();
                send_reply(&reply, 2+4);
                break;
        }
                
        case CMD_SET_ADC_DECIMATION:
                if (adc_set_decimation(cmd->set_adc_decimation) == 0) {
                        send_ack();
                } else {
                        send_nack();
                }
                break;

        case CMD_GET_FEEDBACK_FREQ:
        {
                unsigned int freq = feedback_get_loop_freq();
                reply.data32[0] = freq;
                send_reply(&reply, 2+4);
                break;
        }

        case CMD_SET_FEEDBACK_FREQ:
                feedback_set_loop_freq(cmd->set_feedback_freq);
                send_ack();
                break;

        case CMD_GET_FEEDBACK_MODE:
                reply.data[0] = feedback_get_mode();
                send_reply(&reply, 3);
                break;

        case CMD_SET_FEEDBACK_MODE:
                feedback_set_mode(cmd->set_feedback_mode);
                send_ack();
                break;

        case CMD_SET_RAW_POS:
                if (feedback_set_position(cmd->set_raw_pos) == 0) {
                        send_ack();
                } else {
                        send_nack();
                }
                break;

        case CMD_CLEAR_PATH:
                clear_path();
                send_ack();
                break;
                
        case CMD_ENQUEUE_POINTS:
                res = 0;
                if (cmd->enqueue_points.npts > 0)
                        res = enqueue_points((uint16_t*) &cmd->enqueue_points.points, cmd->enqueue_points.npts);
                if (res == -1 || res == 0) {
                        reply.data[0] = res != -1; // were the points added?
                        reply.data[1] = is_path_running();
                        send_reply(&reply, 4);
                } else {
                        send_nack();
                }
                break;

        case CMD_START_PATH:
                if (start_path(cmd->start_path.freq, cmd->start_path.synchronous_adc) == 0) {
                        send_ack();
                } else {
                        send_nack();
                }
                break;

        case CMD_SET_EXCITATION:
        {
                struct set_excitation* const se = &cmd->set_excitation;
                struct excitation_buffer* const exc = &excitations[se->channel];

                if ((se->length + se->offset > MAX_EXCITATION_LENGTH)
                    || (se->channel >= 3))
                {
                        send_nack();
                        break;
                }

                exc->length = 0;
                exc->offset = 0;
                if (se->length != 0) {
                        memcpy(&exc->samples[se->offset],
                               &se->samples,
                               sizeof(uint16_t) * se->length);
                }
                exc->length = se->total_length;
                send_ack();
                break;
        }

        case CMD_GET_SEARCH_STEP:
                memcpy(reply.data, search_fb_step,
                       sizeof(search_fb_step));
                send_reply(&reply, 2+sizeof(search_fb_step));
                break;

        case CMD_SET_SEARCH_STEP:
                memcpy(search_fb_step, cmd->set_search_step,
                       sizeof(search_fb_step));
                send_ack();
                break;

        case CMD_GET_SEARCH_OBJ_GAINS:
                memcpy(reply.data, search_obj_gains,
                       sizeof(search_obj_gains));
                send_reply(&reply, 2+sizeof(search_obj_gains));
                break;

        case CMD_SET_SEARCH_OBJ_GAINS:
                memcpy(search_obj_gains, cmd->set_search_obj_gains,
                       sizeof(search_obj_gains));
                send_ack();
                break;

        case CMD_GET_SEARCH_OBJ_THRESH:
                memcpy(reply.data, &search_obj_thresh,
                       sizeof(search_obj_thresh));
                send_reply(&reply, 2+sizeof(search_obj_thresh));
                break;

        case CMD_SET_SEARCH_OBJ_THRESH:
                search_obj_thresh = cmd->set_search_obj_thresh,
                send_ack();
                break;

        case CMD_GET_COARSE_FB_PARAMS:
                memcpy(reply.data, &coarse_fb_channels,
                       sizeof(coarse_fb_channels));
                send_reply(&reply, 2+sizeof(coarse_fb_channels));
                break;

        case CMD_SET_COARSE_FB_PARAMS:
                memcpy(coarse_fb_channels, cmd->set_coarse_fb_params,
                       sizeof(coarse_fb_channels));
                send_ack();
                break;

        default:
                send_nack();
                return;
        }
}
Esempio n. 13
0
void target_manifest_app(void) {
    scb_reset_system();
}
Esempio n. 14
0
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);
    }
  }
}