Ejemplo n.º 1
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) {
  UART_TypeDef *u = sdp->uart;
  uint8_t s1 = u->S1;

  if (s1 & UARTx_S1_RDRF) {
    osalSysLockFromISR();
    if (iqIsEmptyI(&sdp->iqueue))
      chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
    if (iqPutI(&sdp->iqueue, u->D) < MSG_OK)
      chnAddFlagsI(sdp, SD_OVERRUN_ERROR);
    osalSysUnlockFromISR();
  }

  if (s1 & UARTx_S1_TDRE) {
    msg_t b;

    osalSysLockFromISR();
    b = oqGetI(&sdp->oqueue);
    osalSysUnlockFromISR();

    if (b < MSG_OK) {
      osalSysLockFromISR();
      chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
      osalSysUnlockFromISR();
      u->C2 &= ~UARTx_C2_TIE;
    } else {
       u->D = b;
    }
  }
}
Ejemplo n.º 2
0
/**
 * @brief   Common IRQ handler.
 *
 * @param[in] sdp       pointer to a @p SerialDriver object
 */
static void serve_interrupt(SerialDriver *sdp) {
  volatile struct ESCI_tag *escip = sdp->escip;

  uint32_t sr = escip->SR.R;
  escip->SR.R = 0x3FFFFFFF;                     /* Does not clear TDRE | TC.*/
  if (sr & 0x0F000000)                          /* OR | NF | FE | PF.       */
    set_error(sdp, sr);
  if (sr & 0x20000000) {                        /* RDRF.                    */
    osalSysLockFromISR();
    sdIncomingDataI(sdp, escip->DR.B.D);
    osalSysUnlockFromISR();
  }
  if (escip->CR1.B.TIE && (sr & 0x80000000)) {  /* TDRE.                    */
    msg_t b;
    osalSysLockFromISR();
    b = oqGetI(&sdp->oqueue);
    if (b < Q_OK) {
      chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
      escip->CR1.B.TIE = 0;
    }
    else {
      ESCI_A.SR.B.TDRE = 1;
      escip->DR.R = (uint16_t)b;
    }
    osalSysUnlockFromISR();
  }
}
Ejemplo n.º 3
0
/**
 * @brief   Handles outgoing data.
 * @details Must be called from the output interrupt service routine in order
 *          to get the next byte to be transmitted.
 * @note    In order to gain some performance it is suggested to not use
 *          this function directly but copy this code directly into the
 *          interrupt service routine.
 *
 * @param[in] sdp       pointer to a @p SerialDriver structure
 * @return              The byte value read from the driver's output queue.
 * @retval MSG_TIMEOUT  if the queue is empty (the lower driver usually
 *                      disables the interrupt source when this happens).
 *
 * @iclass
 */
msg_t sdRequestDataI(SerialDriver *sdp) {
  msg_t  b;

  osalDbgCheckClassI();
  osalDbgCheck(sdp != NULL);

  b = oqGetI(&sdp->oqueue);
  if (b < MSG_OK)
    chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
  return b;
}
Ejemplo n.º 4
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;

  /* Special case, LIN break detection.*/
  if (sr & USART_SR_LBD) {
    osalSysLockFromISR();
    chnAddFlagsI(sdp, SD_BREAK_DETECTED);
    u->SR = ~USART_SR_LBD;
    osalSysUnlockFromISR();
  }

  /* Data available.*/
  osalSysLockFromISR();
  while (sr & (USART_SR_RXNE | USART_SR_ORE | USART_SR_NE | USART_SR_FE |
               USART_SR_PE)) {
    uint8_t b;

    /* Error condition detection.*/
    if (sr & (USART_SR_ORE | USART_SR_NE | USART_SR_FE  | USART_SR_PE))
      set_error(sdp, sr);
    b = (uint8_t)u->DR & sdp->rxmask;
    if (sr & USART_SR_RXNE)
      sdIncomingDataI(sdp, b);
    sr = u->SR;
  }
  osalSysUnlockFromISR();

  /* Transmission buffer empty.*/
  if ((cr1 & USART_CR1_TXEIE) && (sr & USART_SR_TXE)) {
    msg_t b;
    osalSysLockFromISR();
    b = oqGetI(&sdp->oqueue);
    if (b < MSG_OK) {
      chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
      u->CR1 = (cr1 & ~USART_CR1_TXEIE) | USART_CR1_TCIE;
    }
    else
      u->DR = b;
    osalSysUnlockFromISR();
  }

  /* Physical transmission end.*/
  if ((cr1 & USART_CR1_TCIE) && (sr & USART_SR_TC)) {
    osalSysLockFromISR();
    if (oqIsEmptyI(&sdp->oqueue)) {
      chnAddFlagsI(sdp, CHN_TRANSMISSION_END);
      u->CR1 = cr1 & ~USART_CR1_TCIE;
    }
    osalSysUnlockFromISR();
  }
}
Ejemplo n.º 5
0
/**
 * @brief   Attempts a TX preload
 */
static void preload(SerialDriver *sdp) {
  UART_TypeDef *u = sdp->uart;

  if (u->S1 & UARTx_S1_TDRE) {
    msg_t b = oqGetI(&sdp->oqueue);
    if (b < MSG_OK) {
      chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
      return;
    }
    u->D = b;
    u->C2 |= UARTx_C2_TIE;
  }
}
Ejemplo n.º 6
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;
  uint32_t cr1 = u->CR1;
  uint32_t isr;

  /* Reading and clearing status.*/
  isr = u->ISR;
  u->ICR = isr;

  /* Error condition detection.*/
  if (isr & (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE  | USART_ISR_PE))
    set_error(sdp, isr);

  /* Special case, LIN break detection.*/
  if (isr & USART_ISR_LBDF) {
    osalSysLockFromISR();
    chnAddFlagsI(sdp, SD_BREAK_DETECTED);
    osalSysUnlockFromISR();
  }

  /* Data available.*/
  if (isr & USART_ISR_RXNE) {
    osalSysLockFromISR();
    sdIncomingDataI(sdp, (uint8_t)u->RDR);
    osalSysUnlockFromISR();
  }

  /* Transmission buffer empty.*/
  if ((cr1 & USART_CR1_TXEIE) && (isr & USART_ISR_TXE)) {
    msg_t b;
    osalSysLockFromISR();
    b = oqGetI(&sdp->oqueue);
    if (b < Q_OK) {
      chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
      u->CR1 = (cr1 & ~USART_CR1_TXEIE) | USART_CR1_TCIE;
    }
    else
      u->TDR = b;
    osalSysUnlockFromISR();
  }

  /* Physical transmission end.*/
  if (isr & USART_ISR_TC) {
    osalSysLockFromISR();
    if (oqIsEmptyI(&sdp->oqueue))
      chnAddFlagsI(sdp, CHN_TRANSMISSION_END);
    u->CR1 = cr1 & ~USART_CR1_TCIE;
    osalSysUnlockFromISR();
  }
}
Ejemplo n.º 7
0
/**
 * @brief
 */
static void fifo_load(SerialDriver *sdp)
{
  UART_TypeDef *u = sdp->uart;

  while ((u->FR & TIVA_FR_TXFF) == 0) {
    msg_t b = oqGetI(&sdp->oqueue);
    if (b < Q_OK) {
      chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
      return;
    }
    u->DR = b;
  }
  u->IM |= TIVA_IM_TXIM;   /* transmit interrupt enable */
}
Ejemplo n.º 8
0
/**
 * @brief   Common TXI IRQ handler.
 *
 * @param[in] sdp       pointer to a @p SerialDriver object
 */
static void spc5xx_serve_txi_interrupt(SerialDriver *sdp) {
  msg_t b;

  sdp->linflexp->UARTSR.R = SPC5_UARTSR_DTF;
  osalSysLockFromISR();
  b = oqGetI(&sdp->oqueue);
  if (b < Q_OK) {
    chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
    sdp->linflexp->UARTCR.B.TXEN = 0;
  }
  else
    sdp->linflexp->BDRL.B.DATA0 = b;
  osalSysUnlockFromISR();
}
Ejemplo n.º 9
0
/**
 * @brief   Fill the hardware FIFO of a UART.
 */
static void fifo_load(SerialDriver *sdp)
{
  uint32_t u = sdp->uart;

  while ((HWREG(u + UART_O_FR) & UART_FR_TXFF) == 0) {
    msg_t b = oqGetI(&sdp->oqueue);
    if (b < Q_OK) {
      chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
      return;
    }
    HWREG(u + UART_O_DR) = b;
  }

  HWREG(u + UART_O_IM) |= UART_IM_TXIM;   /* transmit interrupt enable */
}
Ejemplo n.º 10
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 serial_serve_interrupt(SerialDriver *sdp) 
{
  uint32_t u = sdp->uart;
  uint16_t mis = HWREG(u + UART_O_MIS);
  
  HWREG(u + UART_O_ICR) = mis;		/* clear interrupts */

  if (mis & (UART_MIS_FEMIS | UART_MIS_PEMIS | UART_MIS_BEMIS | UART_MIS_OEMIS)) {
    set_error(sdp, mis);
  }

  if ((mis & UART_MIS_RXMIS) || (mis &  UART_MIS_RTMIS)) {
    osalSysLockFromISR();
    if (iqIsEmptyI(&sdp->iqueue)) {
      chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
    }
    osalSysUnlockFromISR();
    while ((HWREG(u + UART_O_FR) & UART_FR_RXFE) == 0) {
      osalSysLockFromISR();
      if (iqPutI(&sdp->iqueue, HWREG(u + UART_O_DR)) < Q_OK) {
        chnAddFlagsI(sdp, SD_QUEUE_FULL_ERROR);
      }
      osalSysUnlockFromISR();
    }
  }

  if (mis & UART_MIS_TXMIS) {
    while ((HWREG(u + UART_O_FR) & UART_FR_TXFF) == 0) {
      msg_t b;
      osalSysLockFromISR();
      b = oqGetI(&sdp->oqueue);
      osalSysUnlockFromISR();
      if (b < Q_OK) {
        HWREG(u + UART_O_IM) &= ~UART_IM_TXIM;
        osalSysLockFromISR();
        chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
        osalSysUnlockFromISR();
        break;
      }
      HWREG(u + UART_O_DR) = b;
    }
  }

  /* TODO: Physical transmission end. */
}
Ejemplo n.º 11
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 serial_serve_interrupt(SerialDriver *sdp) 
{
  UART_TypeDef *u = sdp->uart;
  uint16_t mis = u->MIS;
  
  u->ICR = mis;		/* clear interrupts */

  if (mis & (TIVA_MIS_FEMIS | TIVA_MIS_PEMIS | TIVA_MIS_BEMIS | TIVA_MIS_OEMIS)) {
    set_error(sdp, mis);
  }

  if ((mis & TIVA_MIS_RXMIS) || (mis &  TIVA_MIS_RTMIS)) {
    osalSysLockFromISR();
    if (iqIsEmptyI(&sdp->iqueue)) {
      chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
    }
    osalSysUnlockFromISR();
    while ((u->FR & TIVA_FR_RXFE) == 0) {
      osalSysLockFromISR();
      if (iqPutI(&sdp->iqueue, u->DR) < Q_OK) {
        chnAddFlagsI(sdp, SD_OVERRUN_ERROR);
      }
      osalSysUnlockFromISR();
    }
  }

  if (mis & TIVA_MIS_TXMIS) {
    while ((u->FR & TIVA_FR_TXFF) == 0) {
      msg_t b;
      osalSysLockFromISR();
      b = oqGetI(&sdp->oqueue);
      osalSysUnlockFromISR();
      if (b < Q_OK) {
        u->IM &= ~TIVA_IM_TXIM;
        osalSysLockFromISR();
        chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
        osalSysUnlockFromISR();
        break;
      }
      u->DR = b;
    }
  }
}
Ejemplo n.º 12
0
/* callback */
static void hid_debug_flush_cb(void *arg) {
  HIDDebugDriver *hiddp = (HIDDebugDriver *)arg;
  size_t i, n;
  uint8_t buf[DEBUG_TX_SIZE];

  osalSysLockFromISR();

  /* check that the states of things are as they're supposed to */
  if((usbGetDriverStateI(hiddp->config->usbp) != USB_ACTIVE) ||
     (hiddp->state != HIDDEBUG_READY)) {
    /* rearm the timer */
    chVTSetI(&hid_debug_flush_timer, MS2ST(DEBUG_TX_FLUSH_MS), hid_debug_flush_cb, hiddp);
    osalSysUnlockFromISR();
    return;
  }

  /* don't do anything if the queue or has enough stuff in it */
  if(((n = oqGetFullI(&hiddp->oqueue)) == 0) || (n >= DEBUG_TX_SIZE)) {
    /* rearm the timer */
    chVTSetI(&hid_debug_flush_timer, MS2ST(DEBUG_TX_FLUSH_MS), hid_debug_flush_cb, hiddp);
    osalSysUnlockFromISR();
    return;
  }

  /* there's stuff hanging in the queue - so dequeue and send */
  for(i = 0; i < n; i++)
    buf[i] = (uint8_t)oqGetI(&hiddp->oqueue);
  for(i = n; i < DEBUG_TX_SIZE; i++)
    buf[i] = 0;
  osalSysUnlockFromISR();
  usbPrepareTransmit(hiddp->config->usbp, hiddp->config->ep_in, buf, DEBUG_TX_SIZE);
  osalSysLockFromISR();
  (void)usbStartTransmitI(hiddp->config->usbp, hiddp->config->ep_in);

  /* rearm the timer */
  chVTSetI(&hid_debug_flush_timer, MS2ST(DEBUG_TX_FLUSH_MS), hid_debug_flush_cb, hiddp);
  osalSysUnlockFromISR();
}