/**
 * @brief   UART common service routine.
 *
 * @param[in] uartp     pointer to the @p UARTDriver object
 */
static void uart_serve_interrupt(UARTDriver *uartp)
{
  uint32_t dmachis = HWREG(UDMA_CHIS);
  uint32_t mis = HWREG(uartp->uart + UART_O_MIS);

  if (mis & UART_MIS_TXMIS) {
    /* End of transfer */
    _uart_tx2_isr_code(uartp);
  }

  if (mis & (UART_MIS_OEMIS | UART_MIS_BEMIS | UART_MIS_PEMIS | UART_MIS_FEMIS)) {
    /* Error occurred */
    _uart_rx_error_isr_code(uartp, translate_errors(mis));
  }

  if (dmachis & (1 << uartp->dmarxnr)) {
    if (uartp->rxstate == UART_RX_IDLE) {
      /* Receiver in idle state, a callback is generated, if enabled, for each
         received character and then the driver stays in the same state.*/
      _uart_rx_idle_code(uartp);
      uart_enter_rx_idle_loop(uartp);
    }
    else {
      /* Receiver in active state, a callback is generated, if enabled, after
         a completed transfer.*/
      _uart_rx_complete_isr_code(uartp);
    }
  }

  if (dmachis & (1 << uartp->dmatxnr)) {
    /* A callback is generated, if enabled, after a completed transfer.*/
    _uart_tx1_isr_code(uartp);
  }
}
Exemple #2
0
/**
 * @brief   USART initialization.
 * @details This function must be invoked with interrupts disabled.
 *
 * @param[in] uartp     pointer to the @p UARTDriver object
 */
static void usart_start(UARTDriver *uartp) {
  uint32_t cr1;
  USART_TypeDef *u = uartp->usart;

  /* Defensive programming, starting from a clean state.*/
  usart_stop(uartp);

  /* Baud rate setting.*/
  u->BRR = (uint32_t)(uartp->clock / uartp->config->speed);

  /* Resetting eventual pending status flags.*/
  u->ICR = 0xFFFFFFFFU;

  /* Note that some bits are enforced because required for correct driver
     operations.*/
  u->CR2 = uartp->config->cr2 | USART_CR2_LBDIE;
  u->CR3 = uartp->config->cr3 | USART_CR3_DMAT | USART_CR3_DMAR |
                                USART_CR3_EIE;

  /* Mustn't ever set TCIE here - if done, it causes an immediate
     interrupt.*/
  cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE;
  u->CR1 = uartp->config->cr1 | cr1;

  /* Starting the receiver idle loop.*/
  uart_enter_rx_idle_loop(uartp);
}
Exemple #3
0
/**
 * @brief   Stops any ongoing receive operation.
 * @note    Stopping a receive operation also suppresses the receive callbacks.
 *
 * @param[in] uartp     pointer to the @p UARTDriver object
 *
 * @return              The number of data frames not received by the
 *                      stopped receive operation.
 *
 * @notapi
 */
size_t uart_lld_stop_receive(UARTDriver *uartp) {
  size_t n;

  dmaStreamDisable(uartp->dmarx);
  n = dmaStreamGetTransactionSize(uartp->dmarx);
  uart_enter_rx_idle_loop(uartp);

  return n;
}
/**
 * @brief   UART initialization.
 *
 * @param[in] uartp     pointer to a @p UARTDriver object
 */
static void uart_init(UARTDriver *uartp)
{
  uint32_t u = uartp->uart;
  const UARTConfig *config = uartp->config;
  uint32_t brd;
  uint32_t speed = config->speed;
  uint32_t clock_source;

  if (uartp->config->ctl & UART_CTL_HSE) {
    /* High speed mode is enabled, half the baud rate to compensate
     * for high speed mode.*/
    speed = (speed + 1) / 2;
  }

  if ((config->cc & UART_CC_CS_M) == UART_CC_CS_SYSCLK) {
    /* UART is clocked using the SYSCLK.*/
    clock_source = TIVA_SYSCLK * 8;
  }
  else {
    /* UART is clocked using the PIOSC.*/
    clock_source = 16000000 * 8;
  }

  /* Calculate the baud rate divisor */
  brd = ((clock_source / speed) + 1) / 2;

  /* Disable UART.*/
  HWREG(u + UART_O_CTL) &= ~UART_CTL_UARTEN;

  /* Set baud rate.*/
  HWREG(u + UART_O_IBRD) = brd / 64;
  HWREG(u + UART_O_FBRD) = brd % 64;

  /* Line control/*/
  HWREG(u + UART_O_LCRH) = config->lcrh;

  /* Select clock source.*/
  HWREG(u + UART_O_CC) = config->cc & UART_CC_CS_M;

  /* FIFO configuration.*/
  HWREG(u + UART_O_IFLS) = config->ifls & (UART_IFLS_RX_M | UART_IFLS_TX_M);

  /* Enable interrupts.*/
  HWREG(u + UART_O_IM) = UART_IM_TXIM | UART_IM_OEIM | UART_IM_BEIM | UART_IM_PEIM | UART_IM_FEIM;

  /* Enable DMA for the UART */
  HWREG(u + UART_O_DMACTL) = UART_DMACTL_TXDMAE | UART_DMACTL_RXDMAE | UART_DMACTL_DMAERR;

  /* Note that some bits are enforced.*/
  HWREG(u + UART_O_CTL)  = config->ctl | UART_CTL_RXE | UART_CTL_TXE | UART_CTL_UARTEN | UART_CTL_EOT;

  /* Starting the receiver idle loop.*/
  uart_enter_rx_idle_loop(uartp);
}
/**
 * @brief   Stops any ongoing receive operation.
 * @note    Stopping a receive operation also suppresses the receive callbacks.
 *
 * @param[in] uartp     pointer to the @p UARTDriver object
 *
 * @return              The number of data frames not received by the
 *                      stopped receive operation.
 *
 * @notapi
 */
size_t uart_lld_stop_receive(UARTDriver *uartp)
{
  tiva_udma_table_entry_t *primary = udmaControlTable.primary;
  uint16_t left;

  dmaChannelDisable(uartp->dmatxnr);

  left = ((primary[uartp->dmatxnr].chctl & UDMA_CHCTL_XFERSIZE_M) + 1) >> 4;

  uart_enter_rx_idle_loop(uartp);

  return left;
}
Exemple #6
0
/**
 * @brief   USART initialization.
 * @details This function must be invoked with interrupts disabled.
 *
 * @param[in] uartp     pointer to the @p UARTDriver object
 */
static void usart_start(UARTDriver *uartp) {
  uint16_t cr1;
  USART_TypeDef *u = uartp->usart;

  /* Defensive programming, starting from a clean state.*/
  usart_stop(uartp);

  /* Baud rate setting.*/
#if STM32_HAS_USART6
  if ((uartp->usart == USART1) || (uartp->usart == USART6))
#else
  if (uartp->usart == USART1)
#endif
    u->BRR = STM32_PCLK2 / uartp->config->speed;
  else
    u->BRR = STM32_PCLK1 / uartp->config->speed;

  /* Resetting eventual pending status flags.*/
  (void)u->SR;  /* SR reset step 1.*/
  (void)u->DR;  /* SR reset step 2.*/
  u->SR = 0;

  /* Note that some bits are enforced because required for correct driver
     operations.*/
  u->CR2 = uartp->config->cr2 | USART_CR2_LBDIE;
  u->CR3 = uartp->config->cr3 | USART_CR3_DMAT | USART_CR3_DMAR |
                                USART_CR3_EIE;

  /* Mustn't ever set TCIE here - if done, it causes an immediate
     interrupt.*/
  cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE;
  u->CR1 = uartp->config->cr1 | cr1;

  /* Starting the receiver idle loop.*/
  uart_enter_rx_idle_loop(uartp);
}