From 510da52979e4e389d91e75d7b49f5dd10c245d61 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Mon, 31 Aug 2020 09:32:24 +0000 Subject: [PATCH] More SIO changes. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@13819 27425a3e-05d8-49a3-a47f-9c15f0e5edd8 --- os/hal/include/hal_sio.h | 12 +- .../ports/STM32/LLD/USARTv2/hal_serial_lld.h | 10 +- os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c | 16 +-- os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.h | 12 +- os/hal/ports/STM32/LLD/USARTv2/stm32_usart.h | 116 +++++++++++++++++ os/hal/src/hal_sio.c | 117 ++++++++++++++---- 6 files changed, 231 insertions(+), 52 deletions(-) create mode 100644 os/hal/ports/STM32/LLD/USARTv2/stm32_usart.h diff --git a/os/hal/include/hal_sio.h b/os/hal/include/hal_sio.h index 70b96ec0a..7705ce619 100644 --- a/os/hal/include/hal_sio.h +++ b/os/hal/include/hal_sio.h @@ -252,9 +252,9 @@ struct hal_sio_operation { * @param[in] siop pointer to the @p SIODriver object * @return The frame from RX FIFO. * - * @iclass + * @xclass */ -#define sioGetI(siop) sio_lld_get(siop) +#define sioGetX(siop) sio_lld_get(siop) /** * @brief Pushes one frame into the TX FIFO. @@ -263,9 +263,9 @@ struct hal_sio_operation { * @param[in] siop pointer to the @p SIODriver object * @param[in] data frame to be written * - * @iclass + * @xclass */ -#define sioPutI(siop, data) sio_lld_put(siop, data) +#define sioPutX(siop, data) sio_lld_put(siop, data) /** * @brief Reads data from the RX FIFO. @@ -442,8 +442,8 @@ extern "C" { void sioStop(SIODriver *siop); void sioStartOperation(SIODriver *siop, const SIOOperation *operation); void sioStopOperation(SIODriver *siop); - size_t sioAsyncRead(SIODriver *siop, size_t n, uint8_t *buffer); - size_t sioAsyncWrite(SIODriver *siop, size_t n, const uint8_t *buffer); + size_t sioAsyncRead(SIODriver *siop, uint8_t *buffer, size_t n); + size_t sioAsyncWrite(SIODriver *siop, const uint8_t *buffer, size_t n); #if (HAL_SIO_USE_SYNCHRONIZATION == TRUE) || defined(__DOXYGEN__) msg_t sioSynchronizeRX(SIODriver *siop, sysinterval_t timeout); msg_t sioSynchronizeTX(SIODriver *siop, sysinterval_t timeout); diff --git a/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.h b/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.h index 3567c8d9d..44ab99899 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.h +++ b/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.h @@ -27,6 +27,8 @@ #if HAL_USE_SERIAL || defined(__DOXYGEN__) +#include "stm32_usart.h" + /*===========================================================================*/ /* Driver constants. */ /*===========================================================================*/ @@ -549,14 +551,6 @@ typedef struct { /* Driver macros. */ /*===========================================================================*/ -/* - * Extra USARTs definitions here (missing from the ST header file). - */ -#define USART_CR2_STOP1_BITS (0 << 12) /**< @brief CR2 1 stop bit value.*/ -#define USART_CR2_STOP0P5_BITS (1 << 12) /**< @brief CR2 0.5 stop bit value.*/ -#define USART_CR2_STOP2_BITS (2 << 12) /**< @brief CR2 2 stop bit value.*/ -#define USART_CR2_STOP1P5_BITS (3 << 12) /**< @brief CR2 1.5 stop bit value.*/ - /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ 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 414c1d4c3..212e21893 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c +++ b/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.c @@ -148,7 +148,7 @@ static void usart_init(SIODriver *siop) { (siop->clock <= siop->config->baud * 4096U), "invalid baud rate vs input clock"); - brr = (uint32_t)(((uint64_t)(siop->clock / presc) * (uint64_t)256) / siop->config->speed); + brr = (uint32_t)(((uint64_t)(siop->clock / presc) * (uint64_t)256) / siop->config->baud); osalDbgAssert((brr >= 0x300) && (brr < 0x100000), "invalid BRR value"); } @@ -474,12 +474,12 @@ void sio_lld_stop_operation(SIODriver *siop) { * is space available without waiting. * * @param[in] siop pointer to an @p SIODriver structure - * @param[in] n maximum number of frames to be read * @param[in] buffer pointer to the buffer for read frames + * @param[in] n maximum number of frames to be read * @return The number of frames copied from the buffer. * @retval 0 if the TX FIFO is full. */ -size_t sio_lld_read(SIODriver *siop, size_t n, uint8_t *buffer) { +size_t sio_lld_read(SIODriver *siop, uint8_t *buffer, size_t n) { size_t rd; rd = 0U; @@ -511,12 +511,12 @@ size_t sio_lld_read(SIODriver *siop, size_t n, uint8_t *buffer) { * is space available without waiting. * * @param[in] siop pointer to an @p SIODriver structure - * @param[in] n maximum number of frames to be written * @param[in] buffer pointer to the buffer for read frames + * @param[in] n maximum number of frames to be written * @return The number of frames copied from the buffer. * @retval 0 if the TX FIFO is full. */ -size_t sio_lld_write(SIODriver *siop, size_t n, const uint8_t *buffer) { +size_t sio_lld_write(SIODriver *siop, const uint8_t *buffer, size_t n) { size_t wr; wr = 0U; @@ -583,9 +583,11 @@ void sio_lld_serve_interrupt(SIODriver *siop) { osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state"); - /* Reading and clearing status.*/ + /* Reading and clearing status, note that TC is not cleared because + it is for checking if a transmission is ongoing, it is set/reset + in HW.*/ isr = u->ISR; - u->ICR = isr; + u->ICR = isr & ~USART_ISR_TC; /* One read on control registers.*/ cr1 = u->CR1; 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 d613d26be..cf8fa16ff 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.h +++ b/os/hal/ports/STM32/LLD/USARTv2/hal_sio_lld.h @@ -27,6 +27,8 @@ #if (HAL_USE_SIO == TRUE) || defined(__DOXYGEN__) +#include "stm32_usart.h" + /*===========================================================================*/ /* Driver constants. */ /*===========================================================================*/ @@ -116,7 +118,7 @@ * @details If set to @p TRUE the support for LPUART1 is included. * @note The default is @p FALSE. */ -#if !defined(STM32_SIO_USE_ULPUART1) || defined(__DOXYGEN__) +#if !defined(STM32_SIO_USE_LPUART1) || defined(__DOXYGEN__) #define STM32_SIO_USE_LPUART1 FALSE #endif /** @} */ @@ -296,7 +298,7 @@ * * @notapi */ -#define sio_lld_rx_get(siop) +#define sio_lld_get(siop) (siop)->usart->RDR /** * @brief Pushes one frame into the TX FIFO. @@ -307,7 +309,7 @@ * * @notapi */ -#define sio_lld_tx_put(siop, data) +#define sio_lld_put(siop, data) (siop)->usart->TDR = (data) /*===========================================================================*/ /* External declarations. */ @@ -357,8 +359,8 @@ extern "C" { void sio_lld_stop(SIODriver *siop); void sio_lld_start_operation(SIODriver *siop); void sio_lld_stop_operation(SIODriver *siop); - size_t sio_lld_read(SIODriver *siop, size_t size, uint8_t *buffer); - size_t sio_lld_write(SIODriver *siop, size_t size, const uint8_t *buffer); + size_t sio_lld_read(SIODriver *siop, uint8_t *buffer, size_t n); + size_t sio_lld_write(SIODriver *siop, const uint8_t *buffer, size_t n); msg_t sio_lld_control(SIODriver *siop, unsigned int operation, void *arg); void sio_lld_serve_interrupt(SIODriver *siop); #ifdef __cplusplus diff --git a/os/hal/ports/STM32/LLD/USARTv2/stm32_usart.h b/os/hal/ports/STM32/LLD/USARTv2/stm32_usart.h new file mode 100644 index 000000000..4f43e6898 --- /dev/null +++ b/os/hal/ports/STM32/LLD/USARTv2/stm32_usart.h @@ -0,0 +1,116 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file USARTv2/stm32_usart.h + * @brief STM32 USART helpers header. + * + * @addtogroup STM32_USARTv2 + * @{ + */ + +#ifndef STM32_USART_H +#define STM32_USART_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief CR2 register additional macros + */ +#define USART_CR1_DATA7 (USART_CR1_M1) +#define USART_CR1_DATA8 (0U) +#define USART_CR1_DATA9 (USART_CR1_M0) +#define USART_CR1_OVER16 (0) +/** @} */ + +/** + * @brief CR2 register additional macros + */ +#define USART_CR2_STOP1_BITS (0U << 12) +#define USART_CR2_STOP0P5_BITS (1U << 12) +#define USART_CR2_STOP2_BITS (2U << 12) +#define USART_CR2_STOP1P5_BITS (3U << 12) +/** @} */ + +/** + * @brief CR3 register additional macros + */ +#define USART_CR3_TXFTCFG_NONFULL (0U) +#define USART_CR3_TXFTCFG_1Q (USART_CR3_TXFTCFG_0) +#define USART_CR3_TXFTCFG_1H (USART_CR3_TXFTCFG_1) +#define USART_CR3_TXFTCFG_3Q (USART_CR3_TXFTCFG_1 | USART_CR3_TXFTCFG_0) +#define USART_CR3_TXFTCFG_7E (USART_CR3_TXFTCFG_2) +#define USART_CR3_TXFTCFG_EMPTY (USART_CR3_TXFTCFG_2 | USART_CR3_TXFTCFG_0) + +#define USART_CR3_RXFTCFG_NONEMPTY (0U) +#define USART_CR3_RXFTCFG_1Q (USART_CR3_RXFTCFG_0) +#define USART_CR3_RXFTCFG_1H (USART_CR3_RXFTCFG_1) +#define USART_CR3_RXFTCFG_3Q (USART_CR3_RXFTCFG_1 | USART_CR3_RXFTCFG_0) +#define USART_CR3_RXFTCFG_7E (USART_CR3_RXFTCFG_2) +#define USART_CR3_RXFTCFG_FULL (USART_CR3_RXFTCFG_2 | USART_CR3_RXFTCFG_0) +/** @} */ + +/** + * @brief PRESC register additional macros + */ +#define USART_PRESC_N(n) ((n) << USART_PRESC_PRESCALER_Pos) +#define USART_PRESC1 USART_PRESC_N(0U) +#define USART_PRESC2 USART_PRESC_N(1U) +#define USART_PRESC4 USART_PRESC_N(2U) +#define USART_PRESC6 USART_PRESC_N(3U) +#define USART_PRESC8 USART_PRESC_N(4U) +#define USART_PRESC10 USART_PRESC_N(5U) +#define USART_PRESC12 USART_PRESC_N(6U) +#define USART_PRESC16 USART_PRESC_N(7U) +#define USART_PRESC32 USART_PRESC_N(8U) +#define USART_PRESC64 USART_PRESC_N(9U) +#define USART_PRESC128 USART_PRESC_N(10U) +#define USART_PRESC256 USART_PRESC_N(11U) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* STM32_USART_H */ + +/** @} */ diff --git a/os/hal/src/hal_sio.c b/os/hal/src/hal_sio.c index d9366d786..aaa813857 100644 --- a/os/hal/src/hal_sio.c +++ b/os/hal/src/hal_sio.c @@ -43,69 +43,125 @@ /*===========================================================================*/ #if (HAL_SIO_USE_SYNCHRONIZATION == TRUE) || defined(__DOXYGEN__) +static size_t sync_write(void *ip, const uint8_t *bp, size_t n, + sysinterval_t timeout) { + SIODriver *siop = (SIODriver *)ip; + size_t i; + + i = 0U; + while (i < n) { + size_t written; + msg_t msg; + + msg = sioSynchronizeTX(siop, timeout); + if (msg != MSG_OK) { + break; + } + + written = sioAsyncWrite(siop, bp, n - i); + i += written; + bp += written; + } + return n; +} + +static size_t sync_read(void *ip, uint8_t *bp, size_t n, + sysinterval_t timeout) { + SIODriver *siop = (SIODriver *)ip; + size_t i; + + i = 0U; + while (i < n) { + size_t read; + msg_t msg; + + msg = sioSynchronizeTX(siop, timeout); + if (msg != MSG_OK) { + break; + } + + read = sioAsyncRead(siop, bp, n - i); + i += read; + bp += read; + } + return n; +} + /* * Interface implementation, the following functions just invoke the equivalent * queue-level function or macro. */ static size_t __write(void *ip, const uint8_t *bp, size_t n) { - SIODriver *siop = (SIODriver *)ip; - sioSynchronizeTX(siop, TIME_INFINITE); - return sioAsyncWrite(siop, n, bp); + return sync_write(ip, bp, n, TIME_INFINITE); } static size_t __read(void *ip, uint8_t *bp, size_t n) { - SIODriver *siop = (SIODriver *)ip; - sioSynchronizeRX(siop, TIME_INFINITE); - return sioAsyncRead(siop, n, bp); + return sync_read(ip, bp, n, TIME_INFINITE); } static msg_t __put(void *ip, uint8_t b) { SIODriver *siop = (SIODriver *)ip; + msg_t msg; - sioSynchronizeTX(siop, TIME_INFINITE); - sioPut(b); + msg = sioSynchronizeTX(siop, TIME_INFINITE); + if (msg != MSG_OK) { + return MSG_RESET; + } + + sioPutX(siop, b); return MSG_OK; } static msg_t __get(void *ip) { SIODriver *siop = (SIODriver *)ip; + msg_t msg; - sioSynchronizeRX(siop, TIME_INFINITE); - return sioGet(); + msg = sioSynchronizeRX(siop, TIME_INFINITE); + if (msg != MSG_OK) { + return MSG_RESET; + } + + return sioGetX(siop); } static msg_t __putt(void *ip, uint8_t b, sysinterval_t timeout) { SIODriver *siop = (SIODriver *)ip; + msg_t msg; - sioSynchronizeTX(siop, timeout); - sioPut(b); + msg = sioSynchronizeTX(siop, timeout); + if (msg != MSG_OK) { + return MSG_RESET; + } + + sioPutX(siop, b); return MSG_OK; } static msg_t __gett(void *ip, sysinterval_t timeout) { SIODriver *siop = (SIODriver *)ip; + msg_t msg; - sioSynchronizeRX(siop, timeout); - return sioGet(); + msg = sioSynchronizeRX(siop, timeout); + if (msg != MSG_OK) { + return MSG_RESET; + } + + return sioGetX(siop); } static size_t __writet(void *ip, const uint8_t *bp, size_t n, sysinterval_t timeout) { - SIODriver *siop = (SIODriver *)ip; - sioSynchronizeTX(siop, timeout); - return sioAsyncWrite(siop, n, bp); + return sync_write(ip, bp, n, timeout); } static size_t __readt(void *ip, uint8_t *bp, size_t n, sysinterval_t timeout) { - SIODriver *siop = (SIODriver *)ip; - sioSynchronizeRX(siop, timeout); - return sioAsyncRead(siop, n, bp); + return sync_read(ip, bp, n, timeout); } static msg_t __ctl(void *ip, unsigned int operation, void *arg) { @@ -264,6 +320,13 @@ void sioStopOperation(SIODriver *siop) { osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state"); +#if HAL_SIO_USE_SYNCHRONIZATION == TRUE + /* Informing waiting threads, if any.*/ + osalThreadResumeI(&siop->sync_rx, MSG_RESET); + osalThreadResumeI(&siop->sync_tx, MSG_RESET); + osalThreadResumeI(&siop->sync_txend, MSG_RESET); +#endif + sio_lld_stop_operation(siop); siop->operation = NULL; @@ -281,18 +344,18 @@ void sioStopOperation(SIODriver *siop) { * * @param[in] siop pointer to the @p SIODriver object * @param[in] buffer buffer for the received data - * @param[in] size maximum number of frames to read + * @param[in] n maximum number of frames to read * @return The number of received frames. * * @api */ -size_t sioAsyncRead(SIODriver *siop, size_t n, uint8_t *buffer) { +size_t sioAsyncRead(SIODriver *siop, uint8_t *buffer, size_t n) { osalDbgCheck((siop != NULL) && (buffer)); osalSysLock(); - n = sioAsyncReadI(siop, n, buffer); + n = sioAsyncReadI(siop, buffer, n); osalSysUnlock(); @@ -308,18 +371,18 @@ size_t sioAsyncRead(SIODriver *siop, size_t n, uint8_t *buffer) { * * @param[in] siop pointer to the @p SIODriver object * @param[out] buffer buffer containing the data to be transmitted - * @param[in] size maximum number of frames to read + * @param[in] n maximum number of frames to read * @return The number of transmitted frames. * * @api */ -size_t sioAsyncWrite(SIODriver *siop, size_t n, const uint8_t *buffer) { +size_t sioAsyncWrite(SIODriver *siop, const uint8_t *buffer, size_t n) { osalDbgCheck((siop != NULL) && (buffer != NULL)); osalSysLock(); - n = sioAsyncWriteI(siop, n, buffer); + n = sioAsyncWriteI(siop, buffer, n); osalSysUnlock(); @@ -338,6 +401,7 @@ size_t sioAsyncWrite(SIODriver *siop, size_t n, const uint8_t *buffer) { * @return The synchronization result. * @retval MSG_OK if there is data in the RX FIFO. * @retval MSG_TIMEOUT if synchronization timed out. + * @retval MSG_RESET operation has been stopped while waiting. * @retval SIO_MSG_IDLE if RX line went idle. * @retval SIO_MSG_ERRORS if RX errors occurred during wait. */ @@ -373,6 +437,7 @@ msg_t sioSynchronizeRX(SIODriver *siop, sysinterval_t timeout) { * @return The synchronization result. * @retval MSG_OK if there is space in the TX FIFO. * @retval MSG_TIMEOUT if synchronization timed out. + * @retval MSG_RESET operation has been stopped while waiting. */ msg_t sioSynchronizeTX(SIODriver *siop, sysinterval_t timeout) { msg_t msg;