diff --git a/os/hal/include/uart.h b/os/hal/include/uart.h index c0ee4c9ef..444975d15 100644 --- a/os/hal/include/uart.h +++ b/os/hal/include/uart.h @@ -106,9 +106,12 @@ extern "C" { void uartStop(UARTDriver *uartp); void uartStartSend(UARTDriver *uartp, size_t n, const void *txbuf); void uartStartSendI(UARTDriver *uartp, size_t n, const void *txbuf); - void uartStopSend(UARTDriver *uartp); + size_t uartStopSend(UARTDriver *uartp); + size_t uartStopSendI(UARTDriver *uartp); void uartStartReceive(UARTDriver *uartp, size_t n, void *rxbuf); - void uartStopReceive(UARTDriver *uartp); + void uartStartReceiveI(UARTDriver *uartp, size_t n, void *rxbuf); + size_t uartStopReceive(UARTDriver *uartp); + size_t uartStopReceiveI(UARTDriver *uartp); #ifdef __cplusplus } #endif diff --git a/os/hal/platforms/STM32/uart_lld.c b/os/hal/platforms/STM32/uart_lld.c index 7974f74fa..f06ab2504 100644 --- a/os/hal/platforms/STM32/uart_lld.c +++ b/os/hal/platforms/STM32/uart_lld.c @@ -522,8 +522,10 @@ void uart_lld_start(UARTDriver *uartp) { uartp->ud_dmaccr = STM32_UART_USART1_DMA_PRIORITY << 12; if ((uartp->ud_config->uc_cr1 & (USART_CR1_M | USART_CR1_PCE)) == USART_CR1_M) uartp->ud_dmaccr |= DMA_CCR1_MSIZE_0 | DMA_CCR1_PSIZE_0; - uartp->ud_dmap->channels[uartp->ud_dmarx].CPAR = (uint32_t)&uartp->ud_usart->DR; - uartp->ud_dmap->channels[uartp->ud_dmatx].CPAR = (uint32_t)&uartp->ud_usart->DR; + dmaChannelSetPeripheral(&uartp->ud_dmap->channels[uartp->ud_dmarx], + &uartp->ud_usart->DR); + dmaChannelSetPeripheral(&uartp->ud_dmap->channels[uartp->ud_dmatx], + &uartp->ud_usart->DR); uartp->ud_rxbuf = 0; } @@ -600,11 +602,15 @@ void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) { * @note Stopping a transmission also suppresses the transmission callbacks. * * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not transmitted by the + * stopped transmit operation. */ -void uart_lld_stop_send(UARTDriver *uartp) { +size_t uart_lld_stop_send(UARTDriver *uartp) { dmaDisableChannel(uartp->ud_dmap, uartp->ud_dmatx); dmaClearChannel(uartp->ud_dmap, uartp->ud_dmatx); + return (size_t)uartp->ud_dmap->channels[uartp->ud_dmatx].CNDTR; } /** @@ -634,12 +640,18 @@ void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) { * @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. */ -void uart_lld_stop_receive(UARTDriver *uartp) { +size_t uart_lld_stop_receive(UARTDriver *uartp) { + size_t n; dmaDisableChannel(uartp->ud_dmap, uartp->ud_dmarx); dmaClearChannel(uartp->ud_dmap, uartp->ud_dmarx); + n = (size_t)uartp->ud_dmap->channels[uartp->ud_dmarx].CNDTR; set_rx_idle_loop(uartp); + return n; } #endif /* CH_HAL_USE_UART */ diff --git a/os/hal/platforms/STM32/uart_lld.h b/os/hal/platforms/STM32/uart_lld.h index e0d0851d6..d6927ccdb 100644 --- a/os/hal/platforms/STM32/uart_lld.h +++ b/os/hal/platforms/STM32/uart_lld.h @@ -266,9 +266,9 @@ extern "C" { void uart_lld_start(UARTDriver *uartp); void uart_lld_stop(UARTDriver *uartp); void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf); - void uart_lld_stop_send(UARTDriver *uartp); + size_t uart_lld_stop_send(UARTDriver *uartp); void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf); - void uart_lld_stop_receive(UARTDriver *uartp); + size_t uart_lld_stop_receive(UARTDriver *uartp); #ifdef __cplusplus } #endif diff --git a/os/hal/src/uart.c b/os/hal/src/uart.c index 4c1a2a55a..097bd364b 100644 --- a/os/hal/src/uart.c +++ b/os/hal/src/uart.c @@ -164,8 +164,13 @@ void uartStartSendI(UARTDriver *uartp, size_t n, const void *txbuf) { * @note Stopping a transmission also suppresses the transmission callbacks. * * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not transmitted by the + * stopped transmit operation. + * @retval 0 There was no transmit operation in progress. */ -void uartStopSend(UARTDriver *uartp) { +size_t uartStopSend(UARTDriver *uartp) { + size_t n; chDbgCheck(uartp != NULL, "uartStopSend"); @@ -175,10 +180,13 @@ void uartStopSend(UARTDriver *uartp) { "not active"); if (uartp->ud_txstate == UART_TX_ACTIVE) { - uart_lld_stop_send(uartp); + n = uart_lld_stop_send(uartp); uartp->ud_txstate = UART_TX_IDLE; } + else + n = 0; chSysUnlock(); + return n; } /** @@ -187,8 +195,12 @@ void uartStopSend(UARTDriver *uartp) { * @note This function has to be invoked from a lock zone. * * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not transmitted by the + * stopped transmit operation. + * @retval 0 There was no transmit operation in progress. */ -void uartStopSendI(UARTDriver *uartp) { +size_t uartStopSendI(UARTDriver *uartp) { chDbgCheck(uartp != NULL, "uartStopSendI"); @@ -197,9 +209,11 @@ void uartStopSendI(UARTDriver *uartp) { "not active"); if (uartp->ud_txstate == UART_TX_ACTIVE) { - uart_lld_stop_send(uartp); + size_t n = uart_lld_stop_send(uartp); uartp->ud_txstate = UART_TX_IDLE; + return n; } + return 0; } /** @@ -256,8 +270,13 @@ void uartStartReceiveI(UARTDriver *uartp, size_t n, void *rxbuf) { * @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. + * @retval 0 There was no receive operation in progress. */ -void uartStopReceive(UARTDriver *uartp) { +size_t uartStopReceive(UARTDriver *uartp) { + size_t n; chDbgCheck(uartp != NULL, "uartStopReceive"); @@ -267,10 +286,13 @@ void uartStopReceive(UARTDriver *uartp) { "not active"); if (uartp->ud_rxstate == UART_RX_ACTIVE) { - uart_lld_stop_receive(uartp); + n = uart_lld_stop_receive(uartp); uartp->ud_rxstate = UART_RX_IDLE; } + else + n = 0; chSysUnlock(); + return n; } /** @@ -279,9 +301,12 @@ void uartStopReceive(UARTDriver *uartp) { * @note This function has to be invoked from a lock zone. * * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not received by the + * stopped receive operation. + * @retval 0 There was no receive operation in progress. */ -void uartStopReceiveI(UARTDriver *uartp) { - +size_t uartStopReceiveI(UARTDriver *uartp) { chDbgCheck(uartp != NULL, "uartStopReceiveI"); chDbgAssert(uartp->ud_state == UART_READY, @@ -289,9 +314,11 @@ void uartStopReceiveI(UARTDriver *uartp) { "not active"); if (uartp->ud_rxstate == UART_RX_ACTIVE) { - uart_lld_stop_receive(uartp); + size_t n = uart_lld_stop_receive(uartp); uartp->ud_rxstate = UART_RX_IDLE; + return n; } + return 0; } #endif /* CH_HAL_USE_UART */ diff --git a/os/hal/templates/uart_lld.c b/os/hal/templates/uart_lld.c index 46c04fe8c..b48620a71 100644 --- a/os/hal/templates/uart_lld.c +++ b/os/hal/templates/uart_lld.c @@ -97,8 +97,11 @@ void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) { * @note Stopping a transmission also suppresses the transmission callbacks. * * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not transmitted by the + * stopped transmit operation. */ -void uart_lld_stop_send(UARTDriver *uartp) { +size_t uart_lld_stop_send(UARTDriver *uartp) { } @@ -120,8 +123,11 @@ void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) { * @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. */ -void uart_lld_stop_receive(UARTDriver *uartp) { +size_t uart_lld_stop_receive(UARTDriver *uartp) { } diff --git a/os/hal/templates/uart_lld.h b/os/hal/templates/uart_lld.h index 2d5c576b3..7a0c37373 100644 --- a/os/hal/templates/uart_lld.h +++ b/os/hal/templates/uart_lld.h @@ -107,9 +107,9 @@ extern "C" { void uart_lld_start(UARTDriver *uartp); void uart_lld_stop(UARTDriver *uartp); void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf); - void uart_lld_stop_send(UARTDriver *uartp); + size_t uart_lld_stop_send(UARTDriver *uartp); void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf); - void uart_lld_stop_receive(UARTDriver *uartp); + size_t uart_lld_stop_receive(UARTDriver *uartp); #ifdef __cplusplus } #endif diff --git a/readme.txt b/readme.txt index 0fe86244b..aded26ed0 100644 --- a/readme.txt +++ b/readme.txt @@ -68,6 +68,8 @@ 2.0.3). - FIX: Fixed a documentation error regarding the ADC driver function adcStartConversion() (bug 3039890)(backported to 2.0.3). +- NEW: Added to the UART driver the capability to return the number of + not yet transferred frames when stopping an operation. - NEW: Added more compile-time checks to the various STM32 device drivers. - NEW: Added a simple STM32 ADC demo under ./testhal/STM32/ADC. - NEW: Added a simple STM32 CAN demo under ./testhal/STM32/CAN. diff --git a/testhal/STM32/UART/main.c b/testhal/STM32/UART/main.c index 1ba3ec336..ef862a981 100644 --- a/testhal/STM32/UART/main.c +++ b/testhal/STM32/UART/main.c @@ -25,7 +25,9 @@ static VirtualTimer vt1, vt2; static void restart(void *p) { (void)p; - uartStartSend(&UARTD2, 14, "Hello World!\r\n"); + chSysLockFromIsr(); + uartStartSendI(&UARTD2, 14, "Hello World!\r\n"); + chSysUnlockFromIsr(); } static void ledoff(void *p) { @@ -50,6 +52,8 @@ static void txend2(void) { palSetPad(IOPORT3, GPIOC_LED); chSysLockFromIsr(); + if (chVTIsArmedI(&vt1)) + chVTResetI(&vt1); chVTSetI(&vt1, MS2ST(5000), restart, NULL); chSysUnlockFromIsr(); }