From ae70bb24cc5cd5b1d6a298ea298fe7c25b690dc8 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 15 Aug 2010 15:37:52 +0000 Subject: [PATCH] UART driver improvements. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2131 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/uart.h | 3 +-- os/hal/platforms/STM32/uart_lld.c | 31 ++++++------------------------ os/hal/platforms/STM32/uart_lld.h | 21 ++++++++++++++------ os/hal/templates/uart_lld.h | 32 +++++++++++++++++++++++++++++-- readme.txt | 6 ++++++ testhal/STM32/UART/main.c | 15 ++++++++++----- 6 files changed, 68 insertions(+), 40 deletions(-) diff --git a/os/hal/include/uart.h b/os/hal/include/uart.h index 444975d15..005282f5e 100644 --- a/os/hal/include/uart.h +++ b/os/hal/include/uart.h @@ -83,8 +83,7 @@ typedef enum { typedef enum { UART_RX_IDLE = 0, /**< @brief Not receiving. */ UART_RX_ACTIVE = 1, /**< @brief Receiving. */ - UART_RX_ERROR = 2, /**< @brief Receive error. */ - UART_RX_COMPLETE = 3 /**< @brief Buffer complete. */ + UART_RX_COMPLETE = 2 /**< @brief Buffer complete. */ } uartrxstate_t; #include "uart_lld.h" diff --git a/os/hal/platforms/STM32/uart_lld.c b/os/hal/platforms/STM32/uart_lld.c index f06ab2504..99373a401 100644 --- a/os/hal/platforms/STM32/uart_lld.c +++ b/os/hal/platforms/STM32/uart_lld.c @@ -168,7 +168,7 @@ static void serve_rx_end_irq(UARTDriver *uartp) { uartp->ud_rxstate = UART_RX_COMPLETE; if (uartp->ud_config->uc_rxend != NULL) - uartp->ud_config->uc_rxend(); + uartp->ud_config->uc_rxend(uartp); /* If the callback didn't explicitly change state then the receiver automatically returns to the idle state.*/ if (uartp->ud_rxstate == UART_RX_COMPLETE) { @@ -187,7 +187,7 @@ static void serve_tx_end_irq(UARTDriver *uartp) { /* A callback is generated, if enabled, after a completed transfer.*/ uartp->ud_txstate = UART_TX_COMPLETE; if (uartp->ud_config->uc_txend1 != NULL) - uartp->ud_config->uc_txend1(); + uartp->ud_config->uc_txend1(uartp); /* If the callback didn't explicitly change state then the transmitter automatically returns to the idle state.*/ if (uartp->ud_txstate == UART_TX_COMPLETE) @@ -207,33 +207,14 @@ static void serve_usart_irq(UARTDriver *uartp) { if (sr & (USART_SR_LBD | USART_SR_ORE | USART_SR_NE | USART_SR_FE | USART_SR_PE)) { u->SR = ~USART_SR_LBD; - if (uartp->ud_rxstate == UART_RX_IDLE) { - /* Receiver in idle state, a callback is generated, if enabled, for each - receive error and then the driver stays in the same state.*/ - if (uartp->ud_config->uc_rxerr != NULL) - uartp->ud_config->uc_rxerr(translate_errors(sr)); - } - else { - /* Receiver in active state, a callback is generated and the receive - operation aborts.*/ - dmaDisableChannel(uartp->ud_dmap, uartp->ud_dmarx); - dmaClearChannel(uartp->ud_dmap, uartp->ud_dmarx); - uartp->ud_rxstate = UART_RX_ERROR; - if (uartp->ud_config->uc_rxerr != NULL) - uartp->ud_config->uc_rxerr(translate_errors(sr)); - /* If the callback didn't explicitly change state then the receiver - automatically returns to the idle state.*/ - if (uartp->ud_rxstate == UART_RX_ERROR) { - uartp->ud_rxstate = UART_RX_IDLE; - set_rx_idle_loop(uartp); - } - } + if (uartp->ud_config->uc_rxerr != NULL) + uartp->ud_config->uc_rxerr(uartp, translate_errors(sr)); } if (sr & USART_SR_TC) { u->SR = ~USART_SR_TC; /* End of transmission, a callback is generated.*/ if (uartp->ud_config->uc_txend2 != NULL) - uartp->ud_config->uc_txend2(); + uartp->ud_config->uc_txend2(uartp); } } @@ -322,7 +303,7 @@ CH_IRQ_HANDLER(DMA1_Ch6_IRQHandler) { /* Receiver in idle state, a callback is generated, if enabled, for each received character and then the driver stays in the same state.*/ if (uartp->ud_config->uc_rxchar != NULL) - uartp->ud_config->uc_rxchar(uartp->ud_rxbuf); + uartp->ud_config->uc_rxchar(uartp, uartp->ud_rxbuf); } else { /* Receiver in active state, a callback is generated, if enabled, after diff --git a/os/hal/platforms/STM32/uart_lld.h b/os/hal/platforms/STM32/uart_lld.h index d6927ccdb..4b5ee8dba 100644 --- a/os/hal/platforms/STM32/uart_lld.h +++ b/os/hal/platforms/STM32/uart_lld.h @@ -166,23 +166,32 @@ typedef uint32_t uartflags_t; /** - * @brief Generic UART notification callback type. + * @brief Structure representing an UART driver. */ -typedef void (*uartcb_t)(void); +typedef struct _UARTDriver UARTDriver; + +/** + * @brief Generic UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +typedef void (*uartcb_t)(UARTDriver *uartp); /** * @brief Character received UART notification callback type. * + * @param[in] uartp pointer to the @p UARTDriver object * @param[in] c received character */ -typedef void (*uartccb_t)(uint16_t c); +typedef void (*uartccb_t)(UARTDriver *uartp, uint16_t c); /** * @brief Receive error UART notification callback type. * + * @param[in] uartp pointer to the @p UARTDriver object * @param[in] e receive error mask */ -typedef void (*uartecb_t)(uartflags_t e); +typedef void (*uartecb_t)(UARTDriver *uartp, uartflags_t e); /** * @brief Driver configuration structure. @@ -213,7 +222,7 @@ typedef struct { /** * @brief Structure representing an UART driver. */ -typedef struct { +struct _UARTDriver { /** @brief Driver state.*/ uartstate_t ud_state; /** @brief Current configuration data.*/ @@ -237,7 +246,7 @@ typedef struct { uint8_t ud_dmatx; /** @brief Default receive buffer while into @p UART_RX_IDLE state.*/ volatile uint16_t ud_rxbuf; -} UARTDriver; +}; /*===========================================================================*/ /* Driver macros. */ diff --git a/os/hal/templates/uart_lld.h b/os/hal/templates/uart_lld.h index 7a0c37373..a1f9b9d38 100644 --- a/os/hal/templates/uart_lld.h +++ b/os/hal/templates/uart_lld.h @@ -51,6 +51,34 @@ */ typedef uint32_t uartflags_t; +/** + * @brief Structure representing an UART driver. + */ +typedef struct _UARTDriver UARTDriver; + +/** + * @brief Generic UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +typedef void (*uartcb_t)(UARTDriver *uartp); + +/** + * @brief Character received UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] c received character + */ +typedef void (*uartccb_t)(UARTDriver *uartp, uint16_t c); + +/** + * @brief Receive error UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] e receive error mask + */ +typedef void (*uartecb_t)(UARTDriver *uartp, uartflags_t e); + /** * @brief Driver configuration structure. * @note It could be empty on some architectures. @@ -72,7 +100,7 @@ typedef struct { /** * @brief Structure representing an UART driver. */ -typedef struct { +struct _UARTDriver { /** * @brief Driver state. */ @@ -90,7 +118,7 @@ typedef struct { */ const UARTConfig *ud_config; /* End of the mandatory fields.*/ -} UARTDriver; +}; /*===========================================================================*/ /* Driver macros. */ diff --git a/readme.txt b/readme.txt index ba6a8045b..45c9198e7 100644 --- a/readme.txt +++ b/readme.txt @@ -87,6 +87,12 @@ change). - OPT: Speed optimizations of the STM32 SPI driver, improved latency. - OPT: Speed optimizations of the STM32 ADC driver. +- CHANGE: Added a parameter to the UART driver callbacks, the pointer to the + driver itself. +- CHANGE: In the UART driver now an error does not automatically brings the + receiver in UART_RX_IDLE state, the receive operation continues unless + explicitly stopped in the error callback handler. This considerably + simplifies the low level driver code. - CHANGE: Modified the STM32 ADC driver to use the new DMA infrastructure. - CHANGE: Modified the STM32 SPI driver to use the new DMA infrastructure. - CHANGE: Added DMA cleanup code to the STM32 dmaInit() function. diff --git a/testhal/STM32/UART/main.c b/testhal/STM32/UART/main.c index ef862a981..b823430c9 100644 --- a/testhal/STM32/UART/main.c +++ b/testhal/STM32/UART/main.c @@ -40,16 +40,18 @@ static void ledoff(void *p) { * This callback is invoked when a transmission buffer has been completely * read by the driver. */ -static void txend1(void) { +static void txend1(UARTDriver *uartp) { + (void)uartp; palClearPad(IOPORT3, GPIOC_LED); } /* * This callback is invoked when a transmission has phisically completed. */ -static void txend2(void) { +static void txend2(UARTDriver *uartp) { + (void)uartp; palSetPad(IOPORT3, GPIOC_LED); chSysLockFromIsr(); if (chVTIsArmedI(&vt1)) @@ -62,8 +64,9 @@ static void txend2(void) { * This callback is invoked on a receive error, the errors mask is passed * as parameter. */ -static void rxerr(uartflags_t e) { +static void rxerr(UARTDriver *uartp, uartflags_t e) { + (void)uartp; (void)e; } @@ -71,8 +74,9 @@ static void rxerr(uartflags_t e) { * 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(uint16_t c) { +static void rxchar(UARTDriver *uartp, uint16_t c) { + (void)uartp; (void)c; /* Flashing the LED each time a character is received.*/ palClearPad(IOPORT3, GPIOC_LED); @@ -86,8 +90,9 @@ static void rxchar(uint16_t c) { /* * This callback is invoked when a receive buffer has been completely written. */ -static void rxend(void) { +static void rxend(UARTDriver *uartp) { + (void)uartp; } /*