/** * @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); } }
/** * @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); }
/** * @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; }
/** * @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); }