From 8c025f78c0e3c3ba2d03f7d0912ffbd3cd172b46 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Sun, 21 Aug 2022 06:10:28 +0000 Subject: [PATCH] SIO simplified. Added a "BufferedSIODriver" class that implements the behavior of the legacy Serial driver on top of a SIO implementation (buffering, events and all). git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@15727 27425a3e-05d8-49a3-a47f-9c15f0e5edd8 --- demos/RP/RT-RP2040-PICO/c1_main.c | 1 - os/hal/include/hal_buffered_serial.h | 2 +- os/hal/include/hal_sio.h | 53 +++--- .../complex/buffered_sio/hal_buffered_sio.c | 15 +- os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.c | 39 +---- os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.h | 2 - os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c | 46 ++---- os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.h | 2 - os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c | 50 ++---- os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.h | 2 - os/hal/src/hal_sio.c | 152 +++++------------- readme.txt | 3 + testhal/STM32/multi/SIO/main.c | 110 +++++++++++-- .../multi/SIO/make/stm32g474re_nucleo64.make | 8 +- .../multi/SIO/make/stm32l476vg_discovery.make | 8 +- 15 files changed, 202 insertions(+), 291 deletions(-) diff --git a/demos/RP/RT-RP2040-PICO/c1_main.c b/demos/RP/RT-RP2040-PICO/c1_main.c index 20364b1b4..027b391dd 100644 --- a/demos/RP/RT-RP2040-PICO/c1_main.c +++ b/demos/RP/RT-RP2040-PICO/c1_main.c @@ -73,7 +73,6 @@ void c1_main(void) { * Activates the UART0 SIO driver using the default configuration. */ sioStart(&SIOD0, NULL); - sioStartOperation(&SIOD0, NULL); /* * Creates the timer thread. diff --git a/os/hal/include/hal_buffered_serial.h b/os/hal/include/hal_buffered_serial.h index 78f451b94..a1fc5bbbc 100644 --- a/os/hal/include/hal_buffered_serial.h +++ b/os/hal/include/hal_buffered_serial.h @@ -161,7 +161,7 @@ static inline void __buffered_serial_objinit_impl(void *ip, const void *vmt, qnotify_t onotify, void *oarg) { BufferedSerial *bsp = (BufferedSerial *)ip; - bsp->vmt = (const struct BufferedSerialVMT *)&vmt; /* TODO use new obj model.*/ + bsp->vmt = (const struct BufferedSerialVMT *)vmt; /* TODO use new obj model.*/ osalEventObjectInit(&bsp->event); /* TODO super class should do this.*/ bsp->state = BS_STOP; iqObjectInit(&bsp->iqueue, ib, ibsize, inotify, iarg); diff --git a/os/hal/include/hal_sio.h b/os/hal/include/hal_sio.h index 46ba2f8e9..c32d185e0 100644 --- a/os/hal/include/hal_sio.h +++ b/os/hal/include/hal_sio.h @@ -194,11 +194,6 @@ typedef struct hal_sio_driver SIODriver; */ typedef struct hal_sio_config SIOConfig; -/** - * @brief Type of structure representing a SIO operation. - */ -typedef struct hal_sio_operation SIOOperation; - /** * @brief Generic SIO notification callback type. * @@ -213,7 +208,6 @@ typedef enum { SIO_UNINIT = 0, /**< Not initialized. */ SIO_STOP = 1, /**< Stopped. */ SIO_READY = 2, /**< Ready. */ - SIO_ACTIVE = 3 /**< Operation ongoing. */ } siostate_t; #include "hal_sio_lld.h" @@ -271,9 +265,10 @@ struct hal_sio_driver { */ sioflags_t enabled; /** - * @brief Current configuration data. + * @brief Events callback. + * @note Can be @p NULL. */ - const SIOOperation *operation; + siocb_t cb; /** * @brief User argument to the operation. * @note Can be retrieved through the @p siop argument of the callback. @@ -304,24 +299,18 @@ struct hal_sio_driver { sio_lld_driver_fields; }; -/** - * @brief Structure representing a SIO operation. - */ -struct hal_sio_operation { - /** - * @brief Events callback. - * @note Can be @p NULL. - */ - siocb_t cb; -#if defined(SIO_OPERATION_EXT_FIELS) - SIO_OPERATION_EXT_FIELS -#endif -}; - /*===========================================================================*/ /* Driver macros. */ /*===========================================================================*/ +/** + * @brief Associates a callback to te SIO instance. + * + * @param[in] siop pointer to the @p SIODriver object + * @param[in] f callback to be associated + */ +#define sioSetCallbackX(siop, f) (siop)->cb = (f) + /** * @brief Determines the state of the RX FIFO. * @@ -384,10 +373,10 @@ struct hal_sio_operation { #define sioIsTXOngoingX(siop) sio_lld_is_tx_ongoing(siop) /** - * @brief Writes the condition flags mask. + * @brief Writes the enabled events mask. * * @param[in] siop pointer to the @p SIODriver object - * @param[in] flags flags mask to be written + * @param[in] flags enabled events mask to be written * * @iclass */ @@ -397,10 +386,10 @@ struct hal_sio_operation { } while (false) /** - * @brief Enables flags to the condition flags mask. + * @brief Sets flags into the enabled events flags mask. * * @param[in] siop pointer to the @p SIODriver object - * @param[in] flags flags mask to be enabled + * @param[in] flags enabled events mask to be set * * @iclass */ @@ -410,10 +399,10 @@ struct hal_sio_operation { } while (false) /** - * @brief Disables flags from the condition flags mask. + * @brief Clears flags from the enabled events flags mask. * * @param[in] siop pointer to the @p SIODriver object - * @param[in] flags flags mask to be disabled + * @param[in] flags enabled events mask to be cleared * * @iclass */ @@ -533,8 +522,8 @@ struct hal_sio_operation { * @notapi */ #define __sio_callback(siop) do { \ - if ((siop)->operation->cb != NULL) { \ - (siop)->operation->cb(siop); \ + if ((siop)->cb != NULL) { \ + (siop)->cb(siop); \ } \ } while (false) @@ -634,10 +623,6 @@ extern "C" { void sioObjectInit(SIODriver *siop); msg_t sioStart(SIODriver *siop, const SIOConfig *config); void sioStop(SIODriver *siop); - void sioStartOperationI(SIODriver *siop, const SIOOperation *operation); - void sioStartOperation(SIODriver *siop, const SIOOperation *operation); - void sioStopOperationI(SIODriver *siop); - void sioStopOperation(SIODriver *siop); void sioWriteEnableFlags(SIODriver *siop, sioflags_t flags); void sioSetEnableFlags(SIODriver *siop, sioflags_t flags); void sioClearEnableFlags(SIODriver *siop, sioflags_t flags); diff --git a/os/hal/lib/complex/buffered_sio/hal_buffered_sio.c b/os/hal/lib/complex/buffered_sio/hal_buffered_sio.c index 40f500783..5c4246008 100644 --- a/os/hal/lib/complex/buffered_sio/hal_buffered_sio.c +++ b/os/hal/lib/complex/buffered_sio/hal_buffered_sio.c @@ -40,11 +40,6 @@ /* Driver local variables and types. */ /*===========================================================================*/ -static void __bsio_default_cb(SIODriver *siop); -static const SIOOperation __bsio_default_operation = { - .cb = __bsio_default_cb -}; - /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ @@ -208,15 +203,10 @@ msg_t bsioStart(BufferedSIODriver *bsiop, const BufferedSIOConfig *config) { osalDbgAssert((bsiop->state == BS_STOP) || (bsiop->state == BS_READY), "invalid state"); - /* Stopping current operation, if any.*/ - if (bsiop->siop->state == SIO_ACTIVE) { - sioStopOperation(bsiop->siop); - } - msg = sioStart(bsiop->siop, config); if (msg == HAL_RET_SUCCESS) { osalSysLock(); - sioStartOperationI(bsiop->siop, &__bsio_default_operation); + sioSetCallbackX(bsiop->siop, &__bsio_default_cb); sioWriteEnableFlagsI(bsiop->siop, SIO_FL_ALL); bsiop->state = BS_READY; osalSysUnlock(); @@ -244,9 +234,6 @@ void bsioStop(BufferedSIODriver *bsiop) { osalDbgAssert((bsiop->state == BS_STOP) || (bsiop->state == BS_READY), "invalid state"); - /* Stopping current operation, if any.*/ - sioStopOperation(bsiop->siop); - /* Stopping undelying SIO driver.*/ sioStop(bsiop->siop); diff --git a/os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.c b/os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.c index a324673a2..6673a2f9c 100644 --- a/os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.c +++ b/os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.c @@ -126,6 +126,11 @@ __STATIC_INLINE void uart_init(SIODriver *siop) { /* Registers settings, the LCR_H write also latches dividers values.*/ siop->uart->UARTLCR_H = siop->config->UARTLCR_H & ~UART_LCRH_CFG_FORBIDDEN; siop->uart->UARTCR = siop->config->UARTCR & ~UART_CR_CFG_FORBIDDEN; + + /* Setting up the operation.*/ + siop->uart->UARTICR = siop->uart->UARTRIS; + siop->uart->UARTCR = siop->config->UARTCR | + UART_UARTCR_RXE | UART_UARTCR_TXE | UART_UARTCR_UARTEN; } /*===========================================================================*/ @@ -240,35 +245,6 @@ void sio_lld_stop(SIODriver *siop) { } } -/** - * @brief Starts a SIO operation. - * - * @param[in] siop pointer to an @p SIODriver structure - * - * @api - */ -void sio_lld_start_operation(SIODriver *siop) { - - /* Setting up the operation.*/ - siop->uart->UARTICR = siop->uart->UARTRIS; - siop->uart->UARTCR = siop->config->UARTCR | - UART_UARTCR_RXE | UART_UARTCR_TXE | UART_UARTCR_UARTEN; -} - -/** - * @brief Stops an ongoing SIO operation, if any. - * - * @param[in] siop pointer to an @p SIODriver structure - * - * @api - */ -void sio_lld_stop_operation(SIODriver *siop) { - - /* Stop operation.*/ - siop->uart->UARTIMSC = 0U; - siop->uart->UARTCR = siop->config->UARTCR & ~UART_CR_CFG_FORBIDDEN; -} - /** * @brief Enable flags change notification. * @@ -513,7 +489,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) { UART_TypeDef *u = siop->uart; uint32_t mis, imsc; - osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state"); + osalDbgAssert(siop->state == SIO_READY, "invalid state"); /* Note, ISR flags are just read but not cleared, ISR sources are disabled instead.*/ @@ -589,10 +565,9 @@ void sio_lld_serve_interrupt(SIODriver *siop) { /* The callback is invoked.*/ __sio_callback(siop); - } else { - osalDbgAssert(false, "spurious interrupt"); +// osalDbgAssert(false, "spurious interrupt"); } } diff --git a/os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.h b/os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.h index 229a383a4..f5e7fa871 100644 --- a/os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.h +++ b/os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.h @@ -211,8 +211,6 @@ extern "C" { void sio_lld_init(void); msg_t sio_lld_start(SIODriver *siop); void sio_lld_stop(SIODriver *siop); - void sio_lld_start_operation(SIODriver *siop); - void sio_lld_stop_operation(SIODriver *siop); void sio_lld_update_enable_flags(SIODriver *siop); sioevents_t sio_lld_get_and_clear_errors(SIODriver *siop); sioevents_t sio_lld_get_and_clear_events(SIODriver *siop); diff --git a/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c b/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c index df02c87b0..57ae4af9e 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c +++ b/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c @@ -214,6 +214,10 @@ __STATIC_INLINE void usart_init(SIODriver *siop) { u->CR1 = siop->config->cr1 & ~USART_CR1_CFG_FORBIDDEN; u->CR2 = siop->config->cr2 & ~USART_CR2_CFG_FORBIDDEN; u->CR3 = siop->config->cr3 & ~USART_CR3_CFG_FORBIDDEN; + + /* Starting operations.*/ + u->ICR = u->ISR; + u->CR1 |= USART_CR1_UE | USART_CR1_TE | USART_CR1_RE; } /*===========================================================================*/ @@ -447,35 +451,6 @@ void sio_lld_stop(SIODriver *siop) { } } -/** - * @brief Starts a SIO operation. - * - * @param[in] siop pointer to an @p SIODriver structure - * - * @api - */ -void sio_lld_start_operation(SIODriver *siop) { - - /* Setting up the operation.*/ - siop->usart->ICR = siop->usart->ISR; - siop->usart->CR1 |= USART_CR1_UE | USART_CR1_TE | USART_CR1_RE; -} - -/** - * @brief Stops an ongoing SIO operation, if any. - * - * @param[in] siop pointer to an @p SIODriver structure - * - * @api - */ -void sio_lld_stop_operation(SIODriver *siop) { - - /* Stop operation.*/ - siop->usart->CR1 &= ~USART_CR1_CFG_FORBIDDEN; - siop->usart->CR2 &= ~USART_CR2_CFG_FORBIDDEN; - siop->usart->CR3 &= ~USART_CR3_CFG_FORBIDDEN; -} - /** * @brief Enable flags change notification. * @@ -559,7 +534,7 @@ sioevents_t sio_lld_get_and_clear_events(SIODriver *siop) { USART_ISR_RXNE | USART_ISR_IDLE | USART_ISR_TXE | - USART_ISR_TC); + USART_ISR_TC); /* Clearing captured events.*/ siop->usart->ICR = isr; @@ -736,7 +711,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) { uint32_t isr, isrmask; uint32_t cr1, cr2, cr3; - osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state"); + osalDbgAssert(siop->state == SIO_READY, "invalid state"); /* Read on control registers.*/ cr1 = u->CR1; @@ -758,7 +733,8 @@ void sio_lld_serve_interrupt(SIODriver *siop) { /* Note, ISR flags are just read but not cleared, ISR sources are disabled instead.*/ - isr = u->ISR & isrmask; + isr = u->ISR; + isr = isr & isrmask; if (isr != 0U) { /* Error events handled as a group, except ORE.*/ @@ -768,7 +744,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) { #if SIO_USE_SYNCHRONIZATION /* The idle flag is forcibly cleared when an RX error event is detected.*/ - u->ICR = USART_ISR_IDLE; + u->ICR = USART_ICR_IDLECF; #endif /* Interrupt sources disabled.*/ @@ -796,7 +772,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) { #if SIO_USE_SYNCHRONIZATION /* The idle flag is forcibly cleared when an RX data event is detected.*/ - u->ICR = USART_ISR_IDLE; + u->ICR = USART_ICR_IDLECF; #endif /* Interrupt source disabled.*/ @@ -835,7 +811,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) { __sio_callback(siop); } else { - osalDbgAssert(false, "spurious interrupt"); +// osalDbgAssert(false, "spurious interrupt"); } } diff --git a/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.h b/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.h index 8d7ba7624..b7fe1bdb0 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.h +++ b/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.h @@ -396,8 +396,6 @@ extern "C" { void sio_lld_init(void); msg_t sio_lld_start(SIODriver *siop); void sio_lld_stop(SIODriver *siop); - void sio_lld_start_operation(SIODriver *siop); - void sio_lld_stop_operation(SIODriver *siop); void sio_lld_update_enable_flags(SIODriver *siop); sioevents_t sio_lld_get_and_clear_errors(SIODriver *siop); sioevents_t sio_lld_get_and_clear_events(SIODriver *siop); diff --git a/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c b/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c index 092c5e1fc..1f0f871d9 100644 --- a/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c +++ b/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.c @@ -147,7 +147,7 @@ static const SIOConfig default_config = { .presc = USART_PRESC1, .cr1 = USART_CR1_DATA8 | USART_CR1_OVER16, .cr2 = USART_CR2_STOP1_BITS, - .cr3 = USART_CR3_TXFTCFG_1H | USART_CR3_RXFTCFG_NONEMPTY + .cr3 = USART_CR3_TXFTCFG_NONFULL | USART_CR3_RXFTCFG_NONEMPTY }; /*===========================================================================*/ @@ -234,6 +234,10 @@ __STATIC_INLINE void usart_init(SIODriver *siop) { u->CR1 = (siop->config->cr1 & ~USART_CR1_CFG_FORBIDDEN) | USART_CR1_FIFOEN; u->CR2 = siop->config->cr2 & ~USART_CR2_CFG_FORBIDDEN; u->CR3 = siop->config->cr3 & ~USART_CR3_CFG_FORBIDDEN; + + /* Starting operations.*/ + u->ICR = u->ISR; + u->CR1 |= USART_CR1_UE | USART_CR1_TE | USART_CR1_RE; } /*===========================================================================*/ @@ -501,35 +505,6 @@ void sio_lld_stop(SIODriver *siop) { } } -/** - * @brief Starts a SIO operation. - * - * @param[in] siop pointer to an @p SIODriver structure - * - * @api - */ -void sio_lld_start_operation(SIODriver *siop) { - - /* Setting up the operation.*/ - siop->usart->ICR = siop->usart->ISR; - siop->usart->CR1 |= USART_CR1_UE | USART_CR1_TE | USART_CR1_RE; -} - -/** - * @brief Stops an ongoing SIO operation, if any. - * - * @param[in] siop pointer to an @p SIODriver structure - * - * @api - */ -void sio_lld_stop_operation(SIODriver *siop) { - - /* Stop operation.*/ - siop->usart->CR1 &= ~USART_CR1_CFG_FORBIDDEN; - siop->usart->CR2 &= ~USART_CR2_CFG_FORBIDDEN; - siop->usart->CR3 &= ~USART_CR3_CFG_FORBIDDEN; -} - /** * @brief Enable flags change notification. * @@ -608,10 +583,10 @@ sioevents_t sio_lld_get_and_clear_events(SIODriver *siop) { some scientist decided to use different positions for some of them.*/ isr = siop->usart->ISR & (SIO_LLD_ISR_RX_ERRORS | - USART_ISR_RXNE_RXFNE | + USART_ISR_RXNE_RXFNE | USART_ISR_IDLE | USART_ISR_TXE_TXFNF | - USART_ISR_TC); + USART_ISR_TC); /* Clearing captured events.*/ siop->usart->ICR = isr; @@ -788,7 +763,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) { uint32_t isr, isrmask; uint32_t cr1, cr2, cr3; - osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state"); + osalDbgAssert(siop->state == SIO_READY, "invalid state"); /* Read on control registers.*/ cr1 = u->CR1; @@ -810,7 +785,8 @@ void sio_lld_serve_interrupt(SIODriver *siop) { /* Note, ISR flags are just read but not cleared, ISR sources are disabled instead.*/ - isr = u->ISR & isrmask; + isr = u->ISR; + isr = isr & isrmask; if (isr != 0U) { /* Error events handled as a group, except ORE.*/ @@ -820,7 +796,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) { #if SIO_USE_SYNCHRONIZATION /* The idle flag is forcibly cleared when an RX error event is detected.*/ - u->ICR = USART_ISR_IDLE; + u->ICR = USART_ICR_IDLECF; #endif /* Interrupt sources disabled.*/ @@ -848,7 +824,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) { #if SIO_USE_SYNCHRONIZATION /* The idle flag is forcibly cleared when an RX data event is detected.*/ - u->ICR = USART_ISR_IDLE; + u->ICR = USART_ICR_IDLECF; #endif /* Interrupt source disabled.*/ @@ -887,7 +863,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) { __sio_callback(siop); } else { - osalDbgAssert(false, "spurious interrupt"); +// osalDbgAssert(false, "spurious interrupt"); } } diff --git a/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.h b/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.h index 6e0501e80..a2fd7837c 100644 --- a/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.h +++ b/os/hal/ports/STM32/LLD/USARTv3/hal_sio_lld.h @@ -451,8 +451,6 @@ extern "C" { void sio_lld_init(void); msg_t sio_lld_start(SIODriver *siop); void sio_lld_stop(SIODriver *siop); - void sio_lld_start_operation(SIODriver *siop); - void sio_lld_stop_operation(SIODriver *siop); void sio_lld_update_enable_flags(SIODriver *siop); sioevents_t sio_lld_get_and_clear_errors(SIODriver *siop); sioevents_t sio_lld_get_and_clear_events(SIODriver *siop); diff --git a/os/hal/src/hal_sio.c b/os/hal/src/hal_sio.c index d461e260b..3240d4ba8 100644 --- a/os/hal/src/hal_sio.c +++ b/os/hal/src/hal_sio.c @@ -38,10 +38,6 @@ /* Driver local variables and types. */ /*===========================================================================*/ -static const SIOOperation default_operation = { - .cb = NULL -}; - /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ @@ -59,6 +55,9 @@ static size_t sync_write(void *ip, const uint8_t *bp, size_t n, msg = sioSynchronizeTX(siop, timeout); if (msg != MSG_OK) { + if (msg != MSG_TIMEOUT) { + i = 0U; + } break; } @@ -81,6 +80,9 @@ static size_t sync_read(void *ip, uint8_t *bp, size_t n, msg = sioSynchronizeRX(siop, timeout); if (msg != MSG_OK) { + if (msg != MSG_TIMEOUT) { + i = 0U; + } break; } @@ -225,6 +227,7 @@ void sioObjectInit(SIODriver *siop) { siop->state = SIO_STOP; siop->config = NULL; siop->enabled = (sioflags_t)0; + siop->cb = NULL; siop->arg = NULL; #if SIO_USE_SYNCHRONIZATION == TRUE siop->sync_rx = NULL; @@ -268,6 +271,14 @@ msg_t sioStart(SIODriver *siop, const SIOConfig *config) { siop->state = SIO_STOP; } +#if SIO_USE_SYNCHRONIZATION == TRUE + /* If synchronization is enabled then all events by default.*/ + sioWriteEnableFlagsI(siop, SIO_FL_ALL); +#else + /* If synchronization is disabled then no events by default.*/ + sioWriteEnableFlagsI(siop, SIO_FL_NONE); +#endif + osalSysUnlock(); return msg; @@ -290,119 +301,28 @@ void sioStop(SIODriver *siop) { "invalid state"); sio_lld_stop(siop); - siop->config = NULL; siop->state = SIO_STOP; + siop->config = NULL; + siop->cb = NULL; + siop->arg = NULL; - osalSysUnlock(); -} - -/** - * @brief Starts a SIO operation. - * - * @param[in] siop pointer to an @p SIODriver structure - * @param[in] operation pointer to an @p SIOOperation structure, can - * be @p NULL if callbacks are not required - * encoding the operation to be performed - * - * @iclass - */ -void sioStartOperationI(SIODriver *siop, const SIOOperation *operation) { - - osalDbgCheck(siop != NULL); - osalDbgCheckClassI(); - - osalDbgAssert((siop->state == SIO_READY) || - (siop->state == SIO_ACTIVE), "invalid state"); - - /* The application can pass NULL if it is not interested in callbacks, - attaching a default operation structure.*/ - if (operation != NULL) { - siop->operation = operation; - } - else { - siop->operation = &default_operation; - } - - if (siop->state == SIO_READY) { - sio_lld_start_operation(siop); - siop->state = SIO_ACTIVE; - -#if SIO_USE_SYNCHRONIZATION == TRUE - /* If synchronization is enabled then all events.*/ - sioWriteEnableFlagsI(siop, SIO_FL_ALL); -#endif - } -} - -/** - * @brief Starts a SIO operation. - * - * @param[in] siop pointer to an @p SIODriver structure - * @param[in] operation pointer to an @p SIOOperation structure, can - * be @p NULL if callbacks are not required - * encoding the operation to be performed - * - * @api - */ -void sioStartOperation(SIODriver *siop, const SIOOperation *operation) { - - osalSysLock(); - sioStartOperationI(siop, operation); - osalSysUnlock(); -} - -/** - * @brief Stops an ongoing SIO operation, if any. - * - * @param[in] siop pointer to an @p SIODriver structure - * - * @iclass - */ -void sioStopOperationI(SIODriver *siop) { - - osalDbgCheck(siop != NULL); - osalDbgCheckClassI(); - - osalDbgAssert((siop->state == SIO_READY) || - (siop->state == SIO_ACTIVE), "invalid state"); - - if (siop->state == SIO_ACTIVE) { #if SIO_USE_SYNCHRONIZATION == TRUE /* Informing waiting threads, if any.*/ osalThreadResumeI(&siop->sync_rx, MSG_RESET); osalThreadResumeI(&siop->sync_rxidle, MSG_RESET); osalThreadResumeI(&siop->sync_tx, MSG_RESET); osalThreadResumeI(&siop->sync_txend, MSG_RESET); + osalOsRescheduleS(); #endif - sio_lld_stop_operation(siop); - - siop->operation = NULL; - siop->state = SIO_READY; - } -} - -/** - * @brief Stops an ongoing SIO operation, if any. - * - * @param[in] siop pointer to an @p SIODriver structure - * - * @api - */ -void sioStopOperation(SIODriver *siop) { - - osalDbgCheck(siop != NULL); - - osalSysLock(); - sioStopOperationI(siop); osalSysUnlock(); } /** - * @brief Writes the condition flags mask. + * @brief Writes the enabled events flags mask. * * @param[in] siop pointer to the @p SIODriver object - * @param[in] flags flags mask to be written + * @param[in] flags enabled events mask to be written * * @api */ @@ -412,7 +332,7 @@ void sioWriteEnableFlags(SIODriver *siop, sioflags_t flags) { osalSysLock(); - osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state"); + osalDbgAssert(siop->state == SIO_READY, "invalid state"); sioWriteEnableFlagsI(siop, flags); @@ -420,10 +340,10 @@ void sioWriteEnableFlags(SIODriver *siop, sioflags_t flags) { } /** - * @brief Enables flags to the condition flags mask. + * @brief Sets flags into the enabled events flags mask. * * @param[in] siop pointer to the @p SIODriver object - * @param[in] flags flags mask to be enabled + * @param[in] flags enabled events mask to be set * * @api */ @@ -433,7 +353,7 @@ void sioSetEnableFlags(SIODriver *siop, sioflags_t flags) { osalSysLock(); - osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state"); + osalDbgAssert(siop->state == SIO_READY, "invalid state"); sioSetEnableFlagsI(siop, flags); @@ -441,10 +361,10 @@ void sioSetEnableFlags(SIODriver *siop, sioflags_t flags) { } /** - * @brief Disables flags from the condition flags mask. + * @brief Clears flags from the enabled events flags mask. * * @param[in] siop pointer to the @p SIODriver object - * @param[in] flags flags mask to be disabled + * @param[in] flags enabled events mask to be cleared * * @api */ @@ -454,7 +374,7 @@ void sioClearEnableFlags(SIODriver *siop, sioflags_t flags) { osalSysLock(); - osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state"); + osalDbgAssert(siop->state == SIO_READY, "invalid state"); sioClearEnableFlagsI(siop, flags); @@ -476,7 +396,7 @@ sioevents_t sioGetAndClearErrors(SIODriver *siop) { osalSysLock(); - osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state"); + osalDbgAssert(siop->state == SIO_READY, "invalid state"); errors = sioGetAndClearErrorsI(siop); @@ -500,7 +420,7 @@ sioevents_t sioGetAndClearEvents(SIODriver *siop) { osalSysLock(); - osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state"); + osalDbgAssert(siop->state == SIO_READY, "invalid state"); events = sioGetAndClearEventsI(siop); @@ -529,7 +449,7 @@ size_t sioAsyncRead(SIODriver *siop, uint8_t *buffer, size_t n) { osalSysLock(); - osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state"); + osalDbgAssert(siop->state == SIO_READY, "invalid state"); n = sioAsyncReadI(siop, buffer, n); @@ -558,7 +478,7 @@ size_t sioAsyncWrite(SIODriver *siop, const uint8_t *buffer, size_t n) { osalSysLock(); - osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state"); + osalDbgAssert(siop->state == SIO_READY, "invalid state"); n = sioAsyncWriteI(siop, buffer, n); @@ -591,7 +511,7 @@ msg_t sioSynchronizeRX(SIODriver *siop, sysinterval_t timeout) { osalSysLock(); - osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state"); + osalDbgAssert(siop->state == SIO_READY, "invalid state"); /* Checking for errors before going to sleep.*/ if (((siop->enabled & SIO_FL_ALL_ERRORS) != 0U) && sioHasRXErrorsX(siop)) { @@ -636,7 +556,7 @@ msg_t sioSynchronizeRXIdle(SIODriver *siop, sysinterval_t timeout) { osalSysLock(); - osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state"); + osalDbgAssert(siop->state == SIO_READY, "invalid state"); /* Checking for errors before going to sleep.*/ if (((siop->enabled & SIO_FL_ALL_ERRORS) != 0U) && sioHasRXErrorsX(siop)) { @@ -683,7 +603,7 @@ msg_t sioSynchronizeTX(SIODriver *siop, sysinterval_t timeout) { osalSysLock(); - osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state"); + osalDbgAssert(siop->state == SIO_READY, "invalid state"); msg = MSG_OK; /*lint -save -e506 -e681 [2.1] Silencing this error because it is @@ -721,7 +641,7 @@ msg_t sioSynchronizeTXEnd(SIODriver *siop, sysinterval_t timeout) { osalSysLock(); - osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state"); + osalDbgAssert(siop->state == SIO_READY, "invalid state"); /*lint -save -e506 -e774 [2.1, 14.3] Silencing this error because it is tested with a template implementation of sio_lld_is_tx_ongoing() diff --git a/readme.txt b/readme.txt index b31852e6c..ec4068e2e 100644 --- a/readme.txt +++ b/readme.txt @@ -74,6 +74,9 @@ ***************************************************************************** *** Next *** +- NEW: Added a "BufferedSIODriver" class that implements the behavior of the + legacy Serial driver on top of a SIO implementation (buffering, events + and all). - NEW: Added __CH_OWNEROF() macro to RT. - NEW; Now hal.h includes cc_portab.h by default making it mandatory. - NEW: Moved HAL serial error flags into asynchronous channels interface diff --git a/testhal/STM32/multi/SIO/main.c b/testhal/STM32/multi/SIO/main.c index b1db61cac..5dfb04811 100644 --- a/testhal/STM32/multi/SIO/main.c +++ b/testhal/STM32/multi/SIO/main.c @@ -20,6 +20,73 @@ #include "portab.h" +#include "chprintf.h" +#include "shell.h" + +static BufferedSIODriver bsio1; +static uint8_t rxbuf[32]; +static uint8_t txbuf[32]; + +/*===========================================================================*/ +/* Command line related. */ +/*===========================================================================*/ + +#define SHELL_WA_SIZE THD_WORKING_AREA_SIZE(2048) + +/* Can be measured using dd if=/dev/xxxx of=/dev/null bs=512 count=10000.*/ +static void cmd_write(BaseSequentialStream *chp, int argc, char *argv[]) { + static uint8_t buf[] = + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; + + (void)argv; + if (argc > 0) { + chprintf(chp, "Usage: write\r\n"); + return; + } + + while (chnGetTimeout((BaseChannel *)chp, TIME_IMMEDIATE) == Q_TIMEOUT) { +#if 1 + /* Writing in channel mode.*/ + chnWrite(&bsio1, buf, sizeof buf - 1); +#else + /* Writing in buffer mode.*/ + (void) obqGetEmptyBufferTimeout(&PORTAB_SDU1.obqueue, TIME_INFINITE); + memcpy(PORTAB_SDU1.obqueue.ptr, buf, SERIAL_USB_BUFFERS_SIZE); + obqPostFullBuffer(&PORTAB_SDU1.obqueue, SERIAL_USB_BUFFERS_SIZE); +#endif + } + chprintf(chp, "\r\n\nstopped\r\n"); +} + +static const ShellCommand commands[] = { + {"write", cmd_write}, + {NULL, NULL} +}; + +static const ShellConfig shell_cfg1 = { + (BaseSequentialStream *)&bsio1, + commands +}; + +/*===========================================================================*/ +/* Generic code. */ +/*===========================================================================*/ + /* * RX consumer thread, times are in milliseconds. */ @@ -36,13 +103,19 @@ static THD_FUNCTION(Thread1, arg) { uint8_t buf[16]; n = chnRead(&PORTAB_SIO2, buf, 16); - if (n > 0) { - chnWrite(&PORTAB_SIO1, buf, n); + if (n == 0U) { + break; + } + n = chnWrite(&PORTAB_SIO1, buf, n); + if (n == 0) { + break; } errors = sioGetAndClearErrors(&PORTAB_SIO2); (void) errors; - sioSynchronizeRXIdle(&PORTAB_SIO2, TIME_INFINITE); + if (sioSynchronizeRXIdle(&PORTAB_SIO2, TIME_INFINITE) < MSG_OK) { + break; + } } } @@ -50,6 +123,7 @@ static THD_FUNCTION(Thread1, arg) { * Application entry point. */ int main(void) { + thread_t *tp; /* * System initializations. @@ -70,14 +144,13 @@ int main(void) { * Activates the SIO drivers using the default configuration. */ sioStart(&PORTAB_SIO1, NULL); - sioStartOperation(&PORTAB_SIO1, NULL); sioStart(&PORTAB_SIO2, NULL); - sioStartOperation(&PORTAB_SIO2, NULL); /* * Creates the RX consumer thread. */ - chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL); + tp = chThdCreateStatic(waThread1, sizeof(waThread1), + NORMALPRIO + 1, Thread1, NULL); /* * Short TX writes. @@ -88,7 +161,7 @@ int main(void) { for (c = 'A'; c <= 'Z'; c++) { chnWrite(&PORTAB_SIO2, (const uint8_t *)&c, 1); sioSynchronizeTXEnd(&PORTAB_SIO2, TIME_INFINITE); - chThdSleepMilliseconds(100); + chThdSleepMilliseconds(10); } } while (palReadLine(PORTAB_LINE_BUTTON) != PORTAB_BUTTON_PRESSED); @@ -112,10 +185,29 @@ int main(void) { } /* - * Normal main() thread activity, in this demo it does nothing. + * Stopping SIOs. + */ + sioStop(&PORTAB_SIO1); + sioStop(&PORTAB_SIO2); + chThdWait(tp); + + /* + * Starting a buffered SIO, it must behave exactly as a serial driver. + */ + bsioObjectInit(&bsio1, &PORTAB_SIO1, + rxbuf, sizeof rxbuf, + txbuf, sizeof txbuf); + bsioStart(&bsio1, NULL); + + /* + * Normal main() thread activity, spawning shells. */ while (true) { - chThdSleepMilliseconds(500); + tp = chThdCreateFromHeap(NULL, SHELL_WA_SIZE, + "shell", NORMALPRIO + 1, + shellThread, (void *)&shell_cfg1); + chThdWait(tp); /* Waiting termination. */ + chThdSleepMilliseconds(1000); } return 0; } diff --git a/testhal/STM32/multi/SIO/make/stm32g474re_nucleo64.make b/testhal/STM32/multi/SIO/make/stm32g474re_nucleo64.make index 79864dc76..a56dfce6c 100644 --- a/testhal/STM32/multi/SIO/make/stm32g474re_nucleo64.make +++ b/testhal/STM32/multi/SIO/make/stm32g474re_nucleo64.make @@ -110,9 +110,11 @@ include $(CHIBIOS)/os/common/ports/ARMv7-M/compilers/GCC/mk/port.mk # Auto-build files in ./source recursively. include $(CHIBIOS)/tools/mk/autobuild.mk # Other files (optional). -#include $(CHIBIOS)/os/test/test.mk -#include $(CHIBIOS)/test/rt/rt_test.mk -#include $(CHIBIOS)/test/oslib/oslib_test.mk +include $(CHIBIOS)/os/test/test.mk +include $(CHIBIOS)/test/rt/rt_test.mk +include $(CHIBIOS)/test/oslib/oslib_test.mk +include $(CHIBIOS)/os/hal/lib/streams/streams.mk +include $(CHIBIOS)/os/various/shell/shell.mk # Define linker script file here. LDSCRIPT= $(STARTUPLD)/STM32G474xE.ld diff --git a/testhal/STM32/multi/SIO/make/stm32l476vg_discovery.make b/testhal/STM32/multi/SIO/make/stm32l476vg_discovery.make index 7797d2b86..78ea40500 100644 --- a/testhal/STM32/multi/SIO/make/stm32l476vg_discovery.make +++ b/testhal/STM32/multi/SIO/make/stm32l476vg_discovery.make @@ -110,9 +110,11 @@ include $(CHIBIOS)/os/common/ports/ARMv7-M/compilers/GCC/mk/port.mk # Auto-build files in ./source recursively. include $(CHIBIOS)/tools/mk/autobuild.mk # Other files (optional). -#include $(CHIBIOS)/os/test/test.mk -#include $(CHIBIOS)/test/rt/rt_test.mk -#include $(CHIBIOS)/test/oslib/oslib_test.mk +include $(CHIBIOS)/os/test/test.mk +include $(CHIBIOS)/test/rt/rt_test.mk +include $(CHIBIOS)/test/oslib/oslib_test.mk +include $(CHIBIOS)/os/hal/lib/streams/streams.mk +include $(CHIBIOS)/os/various/shell/shell.mk # Define linker script file here. LDSCRIPT= $(STARTUPLD)/STM32L476xG.ld