Пример #1
0
/**
 * @brief   Common IRQ handler.
 *
 * @param[in] sdp       communication channel associated to the USART
 */
static void serve_interrupt(SerialDriver *sdp) {
  USART_TypeDef *u = sdp->usart;
  uint16_t cr1 = u->CR1;
  uint16_t sr = u->SR;  /* SR reset step 1.*/
  uint16_t dr = u->DR;  /* SR reset step 2.*/

  /* Error condition detection.*/
  if (sr & (USART_SR_ORE | USART_SR_NE | USART_SR_FE  | USART_SR_PE))
    set_error(sdp, sr);
  /* Special case, LIN break detection.*/
  if (sr & USART_SR_LBD) {
    chSysLockFromIsr();
    chnAddFlagsI(sdp, SD_BREAK_DETECTED);
    chSysUnlockFromIsr();
    u->SR &= ~USART_SR_LBD;
  }
  /* Data available.*/
  if (sr & USART_SR_RXNE) {
    chSysLockFromIsr();
    sdIncomingDataI(sdp, (uint8_t)dr);
    chSysUnlockFromIsr();
  }
  /* Transmission buffer empty.*/
  if ((cr1 & USART_CR1_TXEIE) && (sr & USART_SR_TXE)) {
    msg_t b;
    chSysLockFromIsr();
    b = chOQGetI(&sdp->oqueue);
    if (b < Q_OK) {
      chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
      u->CR1 = (cr1 & ~USART_CR1_TXEIE) | USART_CR1_TCIE;
    }
    else
      u->DR = b;
    chSysUnlockFromIsr();
  }
  /* Physical transmission end.*/
  if (sr & USART_SR_TC) {
    chSysLockFromIsr();
    chnAddFlagsI(sdp, CHN_TRANSMISSION_END);
    chSysUnlockFromIsr();
    u->CR1 = cr1 & ~USART_CR1_TCIE;
    u->SR &= ~USART_SR_TC;
  }
}
Пример #2
0
/**
 * @brief   Default EP0 IN callback.
 * @details This function is used by the low level driver as default handler
 *          for EP0 IN events.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number, always zero
 *
 * @notapi
 */
void _usb_ep0in(USBDriver *usbp, usbep_t ep) {
  size_t max;

  (void)ep;
  switch (usbp->ep0state) {
  case USB_EP0_TX:
    max = usbFetchWord(&usbp->setup[6]);
    /* If the transmitted size is less than the requested size and it is a
       multiple of the maximum packet size then a zero size packet must be
       transmitted.*/
    if ((usbp->ep0n < max) && ((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0)) {
      usbPrepareTransmit(usbp, 0, NULL, 0);
      chSysLockFromIsr();
      usbStartTransmitI(usbp, 0);
      chSysUnlockFromIsr();
      usbp->ep0state = USB_EP0_WAITING_TX0;
      return;
    }
    /* Falls into, it is intentional.*/
  case USB_EP0_WAITING_TX0:
    /* Transmit phase over, receiving the zero sized status packet.*/
    usbp->ep0state = USB_EP0_WAITING_STS;
    usbPrepareReceive(usbp, 0, NULL, 0);
    chSysLockFromIsr();
    usbStartReceiveI(usbp, 0);
    chSysUnlockFromIsr();
    return;
  case USB_EP0_SENDING_STS:
    /* Status packet sent, invoking the callback if defined.*/
    if (usbp->ep0endcb != NULL)
      usbp->ep0endcb(usbp);
    usbp->ep0state = USB_EP0_WAITING_SETUP;
    return;
  default:
    ;
  }
  /* Error response, the state machine goes into an error state, the low
     level layer will have to reset it to USB_EP0_WAITING_SETUP after
     receiving a SETUP packet.*/
  usb_lld_stall_in(usbp, 0);
  usb_lld_stall_out(usbp, 0);
  _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED);
  usbp->ep0state = USB_EP0_ERROR;
}
Пример #3
0
static void cmd_color(BaseSequentialStream *chp, int argc, char *argv[]) {
    #define COLOR_USABLE_WITH_LOOP TRUE
    #if !COLOR_USABLE_WITH_LOOP 
    uint32_t loop_times=1;
    uint32_t loop_delay_ms=100;
    if(argc > 0){
        if(strcmp("-l", argv[0])==0){
            if(argc > 1){
                if(str_is_valid_num(argv[1])){ 
                    loop_times = atol(argv[1]);
                    if(argc > 2){
                        if(strcmp("-s", argv[2])==0){
                            if(argc > 3){
                                if(str_is_valid_num(argv[3])){
                                    loop_delay_ms = atol(argv[3]);
                                } else {
                                    chprintf(chp,invalid_num_str,argv[3]);
                                }
                            } else {
                                chprintf(chp,"please enter millisecond delay\n\r");
                            }
                        } else {
                            chprintf(chp,invalid_arg_str,argv[2]);
                        }
                    }  
                } else {
                    chprintf(chp,invalid_num_str, argv[1]);
                }
            } else {
                chprintf(chp, "please enter a number of times to loop\n\r");
            }
        } else if(strcmp("-h",argv[0])==0){
            chprintf(chp, "printing help:\n\r");
            chprintf(chp, color_usage);
        } else {
            chprintf(chp, invalid_arg_str, argv[0]);
            chprintf(chp, color_usage);
        }
    }
    chprintf(chp, "looping %U times with delay of %U milliseconds:\n\r", 
        loop_times,loop_delay_ms);
    while(loop_times--){
    #endif
        #if !USE_I2C_POLL_THD 
        request_color_data();
        #endif
        chSysLockFromIsr();
        get_lx_from_cnts();
        chSysUnlockFromIsr();
        chprintf(chp, "color_lx: y=%U\tr=%U\tg=%U\tb=%U\n\r",
            y_lx_val,r_lx_val,g_lx_val,b_lx_val);
    #if !COLOR_USABLE_WITH_LOOP 
        chThdSleepMilliseconds(loop_delay_ms);
    }
    #endif
}
Пример #4
0
/**
 * @brief   Wake up ISR handler.
 *
 * @param[in] canp      pointer to the @p CANDriver object
 *
 * @notapi
 */
static void can_lld_wakeup_handler(CANDriver *canp) {

  /* Wakeup event.*/
  canp->state = CAN_READY;
  can_lld_wakeup(canp);
  chSysLockFromIsr();
  chEvtBroadcastI(&canp->wakeup_event);
  chSysUnlockFromIsr();

}
Пример #5
0
/*
 * GPT1 callback.
 */
static void gpt1cb(GPTDriver *gptp) {
  msg_t msg;

  (void)gptp;
  chSysLockFromIsr();
  msg = chMBPostI(&mb[0], MSG_SEND_RIGHT);
  if (msg != RDY_OK)
    saturated = TRUE;
  chSysUnlockFromIsr();
}
static void pwm3cb(PWMDriver *pwmp) {

  chSysLockFromIsr();
  if (pwm_cycles > 8) {
	  pwmDisableChannelI(pwmp, 2);
	  pwmDisableChannelI(pwmp, 3);
	  tmp1 = (&GPT_DRIVER)->tim->CNT;
  }
  chSysUnlockFromIsr();
}
Пример #7
0
// =============================== I2C =========================================
void i2cDmaIrqHandler(void *p, uint32_t flags) {
    chSysLockFromIsr();
    //Uart.Printf("===T===");
    Thread *PThd = ((i2c_t*)p)->PRequestingThread;
    if (PThd != NULL) {
        ((i2c_t*)p)->PRequestingThread = NULL;
        chSchReadyI(PThd);
    }
    chSysUnlockFromIsr();
}
Пример #8
0
/*! Triggered when the pin changes state (both edges)
 *
 * Challenge: Add de-bouncing
 */
void extdetail_launch_detect(EXTDriver *extp, expchannel_t channel) {

    (void)extp;
    (void)channel;

    chSysLockFromIsr();
    chEvtBroadcastI(&extdetail_launch_detect_event);

    chSysUnlockFromIsr();
}
Пример #9
0
void TIM2_IRQHandler(void) {
    CH_IRQ_PROLOGUE();
    chSysLockFromIsr();
    if(TIM2->SR & TIM_SR_UIF) {
        TIM2->SR &= ~TIM_SR_UIF;
        Adc.IIrqSmpHandler();
    }
    chSysUnlockFromIsr();
    CH_IRQ_EPILOGUE();
}
Пример #10
0
 void AdcTxIrq(void *p, uint32_t flags) {
     dmaStreamDisable(ADC_DMA);
     ADC1->CR2 = 0;  // Disable ADC
     // Signal event to thread
     if(IPThread != nullptr) {
         chSysLockFromIsr();
         chEvtSignalI(IPThread, IEvt);
         chSysUnlockFromIsr();
     }
 }
Пример #11
0
/**
 * @brief Process system timer interrupts, if present.
 *
 * @notapi
 */
static void systimer_serve_interrupt( void )
{
  // Update the system time
  chSysLockFromIsr();
  chSysTimerHandlerI();
  chSysUnlockFromIsr();

  // Clear timer interrupt
  ARM_TIMER_CLI = 0;
}
Пример #12
0
/*
 * GPT2 callback.
 */
static void gpt2cb(GPTDriver *gptp) {
  msg_t msg;

  (void)gptp;
  chSysLockFromIsr();
  msg = chMBPostI(&mb[NUM_THREADS - 1], MSG_SEND_LEFT);
  if (msg != RDY_OK)
    saturated = TRUE;
  chSysUnlockFromIsr();
}
Пример #13
0
void AdcTxIrq(void *p, uint32_t flags) {
    dmaStreamDisable(ADC_DMA);
    // Resume thread if any
    chSysLockFromIsr();
    if(PAdcThread != NULL) {
        if(PAdcThread->p_state == THD_STATE_SUSPENDED) chSchReadyI(PAdcThread);
        PAdcThread = NULL;
    }
    chSysUnlockFromIsr();
}
Пример #14
0
/*
 * This callback is invoked when a transmission has physically completed.
 */
static void txend2(UARTDriver *uartp) {

  (void)uartp;
  palSetPad(IOPORT3, GPIOC_LED);
  chSysLockFromIsr();
  if (chVTIsArmedI(&vt1))
    chVTResetI(&vt1);
  chVTSetI(&vt1, MS2ST(5000), restart, NULL);
  chSysUnlockFromIsr();
}
Пример #15
0
/* Triggered when the button is pressed or released. The LED is set to ON.*/
static void extcb1(EXTDriver *extp, expchannel_t channel) {

  (void)extp;
  (void)channel;
  palClearPad(GPIOC, GPIOC_LED);
  chSysLockFromIsr();
  if (!chVTIsArmedI(&vt))
    chVTSetI(&vt, MS2ST(200), ledoff, NULL);
  chSysUnlockFromIsr();
}
Пример #16
0
/*
 * This callback is invoked when a transmission has physically completed.
 */
static void txend2(UARTDriver *uartp) {

  (void)uartp;
  palClearPad(GPIOE, GPIOE_LED3_RED);
  chSysLockFromIsr();
  if (chVTIsArmedI(&vt1))
    chVTResetI(&vt1);
  chVTSetI(&vt1, MS2ST(5000), restart, NULL);
  chSysUnlockFromIsr();
}
Пример #17
0
/*
 * Handles the USB driver global events.
 */
static void usb_event(USBDriver *usbp, usbevent_t event) {
  uint8_t ep;

  switch (event) {
  case USB_EVENT_RESET:
    return;
  case USB_EVENT_ADDRESS:
    return;
  case USB_EVENT_CONFIGURED:
    chSysLockFromIsr();

    for (ep = 1; ep < 10; ep++)
    {
      // Make sure the endpoint are initialized from 1 to 9
      if (ep == CDC1_NOTIFICATION_EPADDR)
        usbInitEndpointI(usbp, CDC1_NOTIFICATION_EPADDR, &cdc1_ep_int_config);
      if (ep == CDC1_TX_EPADDR)
        usbInitEndpointI(usbp, CDC1_TX_EPADDR, &cdc1_ep_in_config);
      if (ep == CDC1_RX_EPADDR)
        usbInitEndpointI(usbp, CDC1_RX_EPADDR, &cdc1_ep_out_config);

      if (ep == CDC2_NOTIFICATION_EPADDR)
        usbInitEndpointI(usbp, CDC2_NOTIFICATION_EPADDR, &cdc2_ep_int_config);
      if (ep == CDC2_TX_EPADDR)
        usbInitEndpointI(usbp, CDC2_TX_EPADDR, &cdc2_ep_in_config);
      if (ep == CDC2_RX_EPADDR)
        usbInitEndpointI(usbp, CDC2_RX_EPADDR, &cdc2_ep_out_config);

#if HAL_USE_MSD
      if (ep == MASS_STORAGE_IN_EPADDR)
        usbInitEndpointI(usbp, MASS_STORAGE_IN_EPADDR, &ms_ep_in_config);
      if (ep == MASS_STORAGE_OUT_EPADDR)
        usbInitEndpointI(usbp, MASS_STORAGE_OUT_EPADDR, &ms_ep_out_config);
#endif
    }

    /* Resetting the state of the CDC subsystem.*/
    sduConfigureHookI(usbp);
#if HAL_USE_MSD
    msdConfigureHookI(usbp);
#endif
    chSysUnlockFromIsr();
    return;
  case USB_EVENT_SUSPEND:
#if HAL_USE_MSD
    msdSuspendHookI(usbp);
#endif
    return;
  case USB_EVENT_WAKEUP:
    return;
  case USB_EVENT_STALLED:
    return;
  }
  return;
}
Пример #18
0
/*
 * Handles the USB driver global events.
 * These events are triggered by the USB driver.
 */
static void usb_event(USBDriver *usbp, usbevent_t event) {
  (void) usbp;
  switch (event) {
  case USB_EVENT_RESET:
    /* Signals when a USB reset event has occurred.
     * Typically this will happen at startup and when the cable
     * is connected or disconnected.
     * After a reset, the usb system will not be operational
     * until it is configured.
     */
    chSysLockFromIsr();
    chEvtBroadcastFlagsI(&esUsbReset, (flagsmask_t)0);
    chSysUnlockFromIsr();
    return;
  case USB_EVENT_ADDRESS:
    return;
  case USB_EVENT_CONFIGURED:

    /* Enables the endpoints specified into the configuration.
     * Note, this callback is invoked from an ISR so I-Class functions
     * must be used.
     */
    chSysLockFromIsr();
    usbInitEndpointI(usbp, 1, &ep1config);
    usbInitEndpointI(usbp, 2, &ep2config);

    /* Signals that the configuration is complete, and the USB system
     * is ready to be used.
     */
    chEvtBroadcastFlagsI(&esUsbConfigured, (flagsmask_t)0);
    chSysUnlockFromIsr();

    return;
  case USB_EVENT_SUSPEND:
    return;
  case USB_EVENT_WAKEUP:
    return;
  case USB_EVENT_STALLED:
    return;
  }
  return;
}
Пример #19
0
/**
 * @brief   Common IRQ handler.
 * @note    Tries hard to clear all the pending interrupt sources, we don't
 *          want to go through the whole ISR and have another interrupt soon
 *          after.
 *
 * @param[in] u         pointer to an UART I/O block
 * @param[in] sdp       communication channel associated to the UART
 */
static void serve_interrupt(SerialDriver *sdp) {
  LPC_USART_TypeDef *u = sdp->uart;

  while (u->INTSTAT) {

    if (u->INTSTAT & STAT_RXRDY) {
      chSysLockFromIsr();
      if (chIQIsEmptyI(&sdp->iqueue))
        chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
      if (chIQPutI(&sdp->iqueue, u->RXDATA) < Q_OK)
        chnAddFlagsI(sdp, SD_OVERRUN_ERROR);
      chSysUnlockFromIsr();
    }

    if (u->INTSTAT & STAT_TXRDY) {
      msg_t b;

      chSysLockFromIsr();
      b = chOQGetI(&sdp->oqueue);
      chSysUnlockFromIsr();

      if (b < Q_OK) {
        u->INTENCLR = STAT_TXRDY;
        chSysLockFromIsr();
        chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
        chSysUnlockFromIsr();
        break;
      }
      else {
         u->TXDATA = b;
      }
    }

    if (u->INTSTAT & (STAT_OVERRUN | STAT_DELTARXBRK |
                      STAT_FRAMERR | STAT_PARITYERR) ) {
      IOREG32 stat = u->STAT;
      set_error(sdp, stat);
      u->STAT = stat;
    }

  }
}
Пример #20
0
/*
 * SPI end transfer callback.
 */
static void spicb(SPIDriver *spip) {
 
    if(spip->state == SPI_COMPLETE){
    /* On transfer end just releases the slave select line.*/
    chSysLockFromIsr();
    SPI_done = TRUE;
    spiUnselectI(spip);
//    palSetPad(GPIOC,4);
    chSysUnlockFromIsr();
    }
}
Пример #21
0
/** DMA 2 Stream 3 Interrupt Service Routine. (SPI1_TX) */
void dma2_stream3_isr(void)
{
  CH_IRQ_PROLOGUE();
  chSysLockFromIsr();

  if (dma_get_interrupt_flag(DMA2, 3, DMA_TEIF | DMA_DMEIF))
    screaming_death("DMA SPI1_TX error interrupt");

  chSysUnlockFromIsr();
  CH_IRQ_EPILOGUE();
}
Пример #22
0
void TIM5_IRQHandler(void) {
    CH_IRQ_PROLOGUE();
    chSysLockFromIsr();
    if(TIM5->SR & TIM_SR_UIF) {
        TIM5->SR &= ~TIM_SR_UIF;
        TIM5->CCER;
        Adc.IIrqHandler();
    }
    chSysUnlockFromIsr();
    CH_IRQ_EPILOGUE();
}
Пример #23
0
static void I2SDmaTxInterrupt(SPIDriver* spip, uint32_t flags)
{
  if(spip == &SPID3)
  {
    if(flags & STM32_DMA_ISR_HTIF)
    {
      // let the decoder thread play the next samples
      chSysLockFromIsr();
      chEvtSignalFlagsI(g_pMp3DecoderThread, (eventmask_t)2);
      chSysUnlockFromIsr();
    }
    if(flags & STM32_DMA_ISR_TCIF)
    {
      // let the decoder thread play the next samples
      chSysLockFromIsr();
      chEvtSignalFlagsI(g_pMp3DecoderThread, (eventmask_t)4);
      chSysUnlockFromIsr();
    }
  }
}
Пример #24
0
/*
 * PWM cyclic callback.
 * A new ADC conversion is started.
 */
static void pwmpcb(PWMDriver *pwmp) {

  (void)pwmp;

  /* Starts an asynchronous ADC conversion operation, the conversion
     will be executed in parallel to the current PWM cycle and will
     terminate before the next PWM cycle.*/
  chSysLockFromIsr();
  adcStartConversionI(&ADCD1, &adcgrpcfg, samples, ADC_GRP1_BUF_DEPTH);
  chSysUnlockFromIsr();
}
Пример #25
0
/**
 * @brief   Handling of stalled I2C transactions.
 *
 * @param[in] i2cp      pointer to the @p I2CDriver object
 *
 * @notapi
 */
static void i2c_lld_safety_timeout(void *p) {
  I2CDriver *i2cp = (I2CDriver *)p;

  if (i2cp->thread) {
    i2c_lld_abort_operation(i2cp);
    chSysLockFromIsr();
    i2cp->thread->p_u.rdymsg = RDY_TIMEOUT;
    chSchReadyI(i2cp->thread);
    chSysUnlockFromIsr();
  }
}
Пример #26
0
/**
 * @brief   Common TX ISR handler.
 *
 * @param[in] canp      pointer to the @p CANDriver object
 *
 * @notapi
 */
static void can_lld_tx_handler(CANDriver *canp) {

  /* All transmit buffers are available.*/
  if (canp->can->GSR & CANGSR_TBS) {
    chSysLockFromIsr();
    while (chSemGetCounterI(&canp->txsem) < 0)
      chSemSignalI(&canp->txsem);
    chEvtBroadcastFlagsI(&canp->txempty_event, CAN_MAILBOX_TO_MASK(1));
    chSysUnlockFromIsr();
  }
}
Пример #27
0
void Usb_t::IRxHandler() {
    OTG_FS->GINTMSK &= ~GINTMSK_RXFLVLM;    // Disable RX irq until current one is processed
    uint32_t sts = OTG_FS->GRXSTSP;         // Get the Status from the top of the FIFO
    uint32_t EpN = (sts & GRXSTSP_EPNUM_MASK);
    uint32_t cnt = (sts & GRXSTSP_BCNT_MASK) >> GRXSTSP_BCNT_OFF;
    uint32_t dpid = (sts & GRXSTSP_DPID_MASK) >> 15;
    Uart.Printf(" dpid %X\r\n", dpid);
    switch(sts & GRXSTSP_PKTSTS_MASK) {
        case GRXSTSP_SETUP_COMP:
            Uart.Printf(" setup comp\r\n");
//            Ep[0].EnableOut();  // Reenable Out transactions, as core disables it when transfer completed
//            Ep[0].ClearOutNAK();
            break;
        case GRXSTSP_SETUP_DATA:
            Uart.Printf(" setup %u %u\r\n", cnt, EpN);
            chSysLockFromIsr();
            ReadFifo(SetupReq.Buf, OTG_FS->FIFO[0], cnt);
            chSysUnlockFromIsr();
//            Uart.Printf("> %A\r\n", SetupReq.Buf, 8, ' ');
            Uart.Printf("%X %X %X %u %u\r\n", SetupReq.bmRequestType, SetupReq.bRequest, SetupReq.wValue, SetupReq.wIndex, SetupReq.wLength);
            break;
        case GRXSTSP_OUT_COMP:
            Uart.Printf(" out comp\r\n");
            //Ep[EpN].EnableOut();  // Reenable Out transactions, as core disables it when transfer completed
            //Ep[EpN].ClearOutNAK();
            //Ep[EpN].SetOutNAK();
            break;
        case GRXSTSP_OUT_DATA:
            Uart.Printf(" out %u %u\r\n", cnt, EpN);
            chSysLockFromIsr();
            ReadFifo(Ep[EpN].Rx.Ptr, OTG_FS->FIFO[0], cnt);
            chSysUnlockFromIsr();
            Ep[EpN].Rx.Ptr += cnt;
            Ep[EpN].Rx.Cnt += cnt;
            break;
        default:
            Uart.Printf(" RX sts: %X\r\n", sts);
            break;
    } // switch
    OTG_FS->GINTMSK |= GINTMSK_RXFLVLM;     // Reenable RX irq
}
Пример #28
0
/**
 * @brief   Default data transmitted callback.
 * @details The application must use this function as callback for the IN
 *          data endpoint.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number
 */
void mscDataTransmitted(USBDriver *usbp, usbep_t ep) {

  switch (msc_state) {
  case MSC_DATA_IN:
    CSW.dCSWSignature = MSC_CSW_SIGNATURE;
    CSW.dCSWTag = CBW.dCBWTag;
    chSysLockFromIsr();
    usbStartTransmitI(usbp, ep, (uint8_t *)&CSW, sizeof CSW);
    chSysUnlockFromIsr();
    msc_state = MSC_SENDING_CSW;
    break;
  case MSC_SENDING_CSW:
    chSysLockFromIsr();
    usbStartReceiveI(usbp, MSC_DATA_OUT_EP, (uint8_t *)&CBW, sizeof CBW);
    chSysUnlockFromIsr();
    msc_state = MSC_IDLE;
    break;
  default:
    ;
  }
}
Пример #29
0
/**
 * @brief   Handling of stalled I2C transactions.
 *
 * @param[in] i2cp      pointer to the @p I2CDriver object
 *
 * @notapi
 */
static void i2c_lld_safety_timeout(void *p) {
  I2CDriver *i2cp = (I2CDriver *)p;

  chSysLockFromIsr();
  if (i2cp->thread) {
    Thread *tp = i2cp->thread;
    i2cp->thread = NULL;
    tp->p_u.rdymsg = RDY_TIMEOUT;
    chSchReadyI(tp);
  }
  chSysUnlockFromIsr();
}
Пример #30
0
/*
 * This callback is invoked when a character is received but the application
 * was not ready to receive it, the character is passed as parameter.
 */
static void rxchar(UARTDriver *uartp, uint16_t c) {

  (void)uartp;
  (void)c;
  /* Flashing the LED each time a character is received.*/
  palSetPad(GPIOE, GPIOE_LED3_RED);
  chSysLockFromIsr();
  if (chVTIsArmedI(&vt2))
    chVTResetI(&vt2);
  chVTSetI(&vt2, MS2ST(200), ledoff, NULL);
  chSysUnlockFromIsr();
}