More work on SIO driver.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@13814 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2020-08-29 14:41:43 +00:00
parent 56e58bfc59
commit 3ae922fc32
4 changed files with 528 additions and 38 deletions

View File

@ -157,12 +157,17 @@ struct hal_sio_driver {
*/
struct hal_sio_operation {
/**
* @brief Receive buffer filled callback.
* @brief Receive non-empty callback.
* @note Can be @p NULL.
*/
siocb_t rx_cb;
/**
* @brief End of transmission buffer callback.
* @brief Receive idle callback.
* @note Can be @p NULL.
*/
siocb_t rx_idle_cb;
/**
* @brief Transmission buffer non-full callback.
* @note Can be @p NULL.
*/
siocb_t tx_cb;

View File

@ -30,17 +30,95 @@
/* Driver local definitions. */
/*===========================================================================*/
#define USART_CR1_CFG_FORBIDDEN (USART_CR1_RXFFIE | \
USART_CR1_TXFEIE | \
USART_CR1_FIFOEN | \
USART_CR1_EOBIE | \
USART_CR1_RTOIE | \
USART_CR1_CMIE | \
USART_CR1_PEIE | \
USART_CR1_TXEIE_TXFNFIE | \
USART_CR1_TCIE | \
USART_CR1_RXNEIE_RXFNEIE | \
USART_CR1_IDLEIE | \
USART_CR1_TE | \
USART_CR1_RE | \
USART_CR1_UE)
#define USART_CR2_CFG_FORBIDDEN (USART_CR2_LBDIE)
#define USART_CR3_CFG_FORBIDDEN (USART_CR3_RXFTIE | \
USART_CR3_TCBGTIE | \
USART_CR3_TXFTIE | \
USART_CR3_WUFIE | \
USART_CR3_CTSIE | \
USART_CR3_EIE)
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief SIO1 driver identifier.
* @brief USART1 SIO driver identifier.
*/
#if (STM32_SIO_USE_USART1 == TRUE) || defined(__DOXYGEN__)
SIODriver SIOD1;
#endif
/**
* @brief USART2 SIO driver identifier.
*/
#if (STM32_SIO_USE_USART2 == TRUE) || defined(__DOXYGEN__)
SIODriver SIOD2;
#endif
/**
* @brief USART3 SIO driver identifier.
*/
#if (STM32_SIO_USE_USART3 == TRUE) || defined(__DOXYGEN__)
SIODriver SIOD3;
#endif
/**
* @brief UART4 SIO driver identifier.
*/
#if (STM32_SIO_USE_UART4 == TRUE) || defined(__DOXYGEN__)
SIODriver SIOD4;
#endif
/**
* @brief UART5 SIO driver identifier.
*/
#if (STM32_SIO_USE_UART5 == TRUE) || defined(__DOXYGEN__)
SIODriver SIOD5;
#endif
/**
* @brief USART6 SIO driver identifier.
*/
#if (STM32_SIO_USE_USART6 == TRUE) || defined(__DOXYGEN__)
SIODriver SIOD6;
#endif
/**
* @brief UART7 SIO driver identifier.
*/
#if (STM32_SIO_USE_UART7 == TRUE) || defined(__DOXYGEN__)
SIODriver SIOD7;
#endif
/**
* @brief UART8 SIO driver identifier.
*/
#if (STM32_SIO_USE_UART8 == TRUE) || defined(__DOXYGEN__)
SIODriver SIOD8;
#endif
/**
* @brief LPUART1 SIO driver identifier.
*/
#if (STM32_SIO_USE_LPUART1 == TRUE) || defined(__DOXYGEN__)
SIODriver LPSIOD1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
@ -49,6 +127,55 @@ SIODriver SIOD1;
/* Driver local functions. */
/*===========================================================================*/
/**
* @brief USART initialization.
* @details This function must be invoked with interrupts disabled.
*
* @param[in] siop pointer to a @p SIODriver object
*/
static void usart_init(SIODriver *siop) {
USART_TypeDef *u = siop->usart;
uint32_t cr1, presc, brr;
/* Prescaler calculation.*/
static const uint32_t prescvals[] = {1, 2, 4, 6, 8, 10, 12, 16, 32, 64, 128, 256};
presc = prescvals[siop->config->presc];
/* Baud rate setting.*/
#if STM32_SIO_USE_LPUART1
if (siop == &LPSIOD1) {
osalDbgAssert((siop->clock >= siop->config->baud * 3U) &&
(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);
osalDbgAssert((brr >= 0x300) && (brr < 0x100000), "invalid BRR value");
}
else
#endif
{
brr = (uint32_t)((siop->clock / presc) / siop->config->baud);
/* Correcting BRR value when oversampling by 8 instead of 16.
Fraction is still 4 bits wide, but only lower 3 bits used.
Mantissa is doubled, but Fraction is left the same.*/
if ((siop->config->cr1 & USART_CR1_OVER8) != 0U) {
brr = ((brr & ~7U) * 2U) | (brr & 7U);
}
osalDbgAssert(brr < 0x10000, "invalid BRR value");
}
/* Setting up USART.*/
u->PRESC = siop->config->presc;
u->BRR = brr;
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;
u->ICR = u->ISR;
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
@ -64,10 +191,53 @@ SIODriver SIOD1;
*/
void sio_lld_init(void) {
/* Driver instances initialization.*/
#if STM32_SIO_USE_USART1 == TRUE
/* Driver initialization.*/
sioObjectInit(&SIOD1);
SIOD1.usart = USART1;
SIOD1.clock = STM32_USART1CLK;
#endif
#if STM32_SIO_USE_USART2 == TRUE
sioObjectInit(&SIOD2);
SIOD2.usart = USART2;
SIOD2.clock = STM32_USART2CLK;
#endif
#if STM32_SIO_USE_USART3 == TRUE
sioObjectInit(&SIOD3);
SIOD3.usart = USART3;
SIOD3.clock = STM32_USART3CLK;
#endif
#if STM32_SIO_USE_UART4 == TRUE
sioObjectInit(&SIOD4);
SIOD4.usart = UART4;
SIOD4.clock = STM32_UART4CLK;
#endif
#if STM32_SIO_USE_UART5 == TRUE
sioObjectInit(&SIOD5);
SIOD5.usart = UART5;
SIOD5.clock = STM32_UART5CLK;
#endif
#if STM32_SIO_USE_USART6 == TRUE
sioObjectInit(&SIOD6);
SIOD6.usart = USART6;
SIOD6.clock = STM32_USART6CLK;
#endif
#if STM32_SIO_USE_UART7 == TRUE
sioObjectInit(&SIOD7);
SIOD7.usart = UART7;
SIOD7.clock = STM32_UART7CLK;
#endif
#if STM32_SIO_USE_UART8 == TRUE
sioObjectInit(&SIOD8);
SIOD8.usart = UART8;
SIOD8.clock = STM32_UART8CLK;
#endif
#if STM32_SIO_USE_LPUART1 == TRUE
sioObjectInit(&LPSIOD1);
LPSIOD1.usart = LPUART1;
LPSIOD1.clock = STM32_LPUART1CLK;
#endif
}
/**
@ -83,17 +253,159 @@ void sio_lld_init(void) {
bool sio_lld_start(SIODriver *siop) {
if (siop->state == SIO_STOP) {
/* Enables the peripheral.*/
#if STM32_SIO_USE_USART1 == TRUE
if (&SIOD1 == siop) {
/* Enables the peripheral.*/
if (false) {
}
#if STM32_SIO_USE_USART1 == TRUE
else if (&SIOD1 == siop) {
rccResetUSART1();
rccEnableUSART1(true);
}
#endif
#if STM32_SIO_USE_USART2 == TRUE
else if (&SIOD2 == siop) {
rccResetUSART2();
rccEnableUSART2(true);
}
#endif
#if STM32_SIO_USE_USART3 == TRUE
else if (&SIOD3 == siop) {
rccResetUSART3();
rccEnableUSART3(true);
}
#endif
#if STM32_SIO_USE_UART4 == TRUE
else if (&SIOD4 == siop) {
rccResetUART4();
rccEnableUART4(true);
}
#endif
#if STM32_SIO_USE_UART5 == TRUE
else if (&SIOD5 == siop) {
rccResetUART5();
rccEnableUART5(true);
}
#endif
#if STM32_SIO_USE_USART6 == TRUE
else if (&SIOD6 == siop) {
rccResetUSART6();
rccEnableUSART6(true);
}
#endif
#if STM32_SIO_USE_UART7 == TRUE
else if (&SIOD7 == siop) {
rccResetUART7();
rccEnableUART7(true);
}
#endif
#if STM32_SIO_USE_UART8 == TRUE
else if (&SIOD8 == siop) {
rccResetUART8();
rccEnableUART8(true);
}
#endif
#if STM32_SIO_USE_LPUART1 == TRUE
else if (&LPSIOD1 == siop) {
rccResetLPUART1();
rccEnableLPUART1(true);
}
#endif
else {
osalDbgAssert(false, "invalid USART instance");
}
/* Driver object low level initializations.*/
#if HAL_SIO_USE_SYNCHRONIZATION
siop->sync_rx = NULL;
siop->sync_tx = NULL;
siop->sync_txend = NULL;
siop->events = 0U;
#endif
}
/* Configures the peripheral.*/
usart_init(siop);
return false;
}
/**
* @brief Deactivates the SIO peripheral.
*
* @param[in] siop pointer to the @p SIODriver object
*
* @notapi
*/
void sio_lld_stop(SIODriver *siop) {
if (siop->state == SIO_READY) {
/* Resets the peripheral.*/
/* Disables the peripheral.*/
if (false) {
}
#if STM32_SIO_USE_USART1 == TRUE
else if (&SIOD1 == siop) {
rccResetUSART1();
rccDisableUSART1();
}
#endif
#if STM32_SIO_USE_USART2 == TRUE
else if (&SIOD2 == siop) {
rccResetUSART2();
rccDisableUSART2();
}
#endif
#if STM32_SIO_USE_USART3 == TRUE
else if (&SIOD3 == siop) {
rccResetUSART3();
rccDisableUSART3();
}
#endif
#if STM32_SIO_USE_UART4 == TRUE
else if (&SIOD4 == siop) {
rccResetUART4();
rccDisableUART4();
}
#endif
#if STM32_SIO_USE_UART5 == TRUE
else if (&SIOD5 == siop) {
rccResetUART5();
rccDisableUART5();
}
#endif
#if STM32_SIO_USE_USART6 == TRUE
else if (&SIOD6 == siop) {
rccResetUSART6();
rccDisableUSART6();
}
#endif
#if STM32_SIO_USE_UART7 == TRUE
else if (&SIOD7 == siop) {
rccResetUART7();
rccDisableUART7();
}
#endif
#if STM32_SIO_USE_UART8 == TRUE
else if (&SIOD8 == siop) {
rccResetUART8();
rccDisableUART8();
}
#endif
#if STM32_SIO_USE_LPUART1 == TRUE
else if (&LPSIOD1 == siop) {
rccResetLPUART1();
rccDisableLPUART1();
}
#endif
else {
osalDbgAssert(false, "invalid USART instance");
}
}
}
/**
* @brief Starts a SIO operation.
*
@ -114,26 +426,6 @@ void sio_lld_start_operation(SIODriver *siop) {
void sio_lld_stop_operation(SIODriver *siop) {
}
/**
* @brief Deactivates the SIO peripheral.
*
* @param[in] siop pointer to the @p SIODriver object
*
* @notapi
*/
void sio_lld_stop(SIODriver *siop) {
if (siop->state == SIO_READY) {
/* Resets the peripheral.*/
/* Disables the peripheral.*/
#if STM32_SIO_USE_USART1 == TRUE
if (&SIOD1 == siop) {
}
#endif
}
}
/**
* @brief Reads data from the RX FIFO.
* @details The function is not blocking, it writes frames until there
@ -152,11 +444,11 @@ size_t sio_lld_read(SIODriver *siop, size_t n, uint8_t *buffer) {
while (true) {
#if USART_ENABLE_INTERRUPTS == TRUE
/* If the RX FIFO has been emptied then the interrupt is enabled again.*/
if (sio_lld_is_rx_empty(siop)) {
siop->usart->CR3 |= USART_CR3_RXFTIE;
break;
}
/* If the RX FIFO has been emptied then the interrupt is enabled again.*/
if (sio_lld_is_rx_empty(siop)) {
siop->usart->CR3 |= USART_CR3_RXFTIE;
break;
}
#endif
/* Buffer filled condition.*/

View File

@ -40,19 +40,176 @@
* @{
*/
/**
* @brief SIO driver enable switch.
* @details If set to @p TRUE the support for SIO1 is included.
* @brief SIO driver 1 enable switch.
* @details If set to @p TRUE the support for USART1 is included.
* @note The default is @p FALSE.
*/
#if !defined(STM32_SIO_USE_USART1) || defined(__DOXYGEN__)
#define STM32_SIO_USE_USART1 FALSE
#endif
/**
* @brief SIO driver 2 enable switch.
* @details If set to @p TRUE the support for USART2 is included.
* @note The default is @p FALSE.
*/
#if !defined(STM32_SIO_USE_USART2) || defined(__DOXYGEN__)
#define STM32_SIO_USE_USART2 FALSE
#endif
/**
* @brief SIO driver 3 enable switch.
* @details If set to @p TRUE the support for USART3 is included.
* @note The default is @p FALSE.
*/
#if !defined(STM32_SIO_USE_USART3) || defined(__DOXYGEN__)
#define STM32_SIO_USE_USART3 FALSE
#endif
/**
* @brief SIO driver 4 enable switch.
* @details If set to @p TRUE the support for UART4 is included.
* @note The default is @p FALSE.
*/
#if !defined(STM32_SIO_USE_UART4) || defined(__DOXYGEN__)
#define STM32_SIO_USE_UART4 FALSE
#endif
/**
* @brief SIO driver 5 enable switch.
* @details If set to @p TRUE the support for UART5 is included.
* @note The default is @p FALSE.
*/
#if !defined(STM32_SIO_USE_UART5) || defined(__DOXYGEN__)
#define STM32_SIO_USE_UART5 FALSE
#endif
/**
* @brief SIO driver 6 enable switch.
* @details If set to @p TRUE the support for USART6 is included.
* @note The default is @p FALSE.
*/
#if !defined(STM32_SIO_USE_USART6) || defined(__DOXYGEN__)
#define STM32_SIO_USE_USART6 FALSE
#endif
/**
* @brief SIO driver 7 enable switch.
* @details If set to @p TRUE the support for UART7 is included.
* @note The default is @p FALSE.
*/
#if !defined(STM32_SIO_USE_UART7) || defined(__DOXYGEN__)
#define STM32_SIO_USE_UART7 FALSE
#endif
/**
* @brief SIO driver 8 enable switch.
* @details If set to @p TRUE the support for UART8 is included.
* @note The default is @p FALSE.
*/
#if !defined(STM32_SIO_USE_UART8) || defined(__DOXYGEN__)
#define STM32_SIO_USE_UART8 FALSE
#endif
/**
* @brief SIO driver 8 enable switch.
* @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__)
#define STM32_SIO_USE_LPUART1 FALSE
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if STM32_SIO_USE_USART1 && !STM32_HAS_USART1
#error "USART1 not present in the selected device"
#endif
#if !STM32_SIO_USE_USART1 && !STM32_SIO_USE_USART2 && \
!STM32_SIO_USE_USART3 && !STM32_SIO_USE_UART4 && \
!STM32_SIO_USE_UART5 && !STM32_SIO_USE_USART6 && \
!STM32_SIO_USE_UART7 && !STM32_SIO_USE_UART8 && \
!STM32_SIO_USE_LPUART1
#error "SIO driver activated but no USART/UART peripheral assigned"
#endif
/* Checks on allocation of USARTx units.*/
#if STM32_SIO_USE_USART1
#if defined(STM32_USART1_IS_USED)
#error "SIOD1 requires USART1 but it is already used"
#else
#define STM32_USART1_IS_USED
#endif
#endif
#if STM32_SIO_USE_USART2
#if defined(STM32_USART2_IS_USED)
#error "SIOD2 requires USART2 but it is already used"
#else
#define STM32_USART2_IS_USED
#endif
#endif
#if STM32_SIO_USE_USART3
#if defined(STM32_USART3_IS_USED)
#error "SIOD3 requires USART3 but it is already used"
#else
#define STM32_USART3_IS_USED
#endif
#endif
#if STM32_SIO_USE_UART4
#if defined(STM32_UART4_IS_USED)
#error "SIOD4 requires UART4 but it is already used"
#else
#define STM32_UART4_IS_USED
#endif
#endif
#if STM32_SIO_USE_UART5
#if defined(STM32_UART5_IS_USED)
#error "SIOD5 requires UART5 but it is already used"
#else
#define STM32_UART5_IS_USED
#endif
#endif
#if STM32_SIO_USE_USART6
#if defined(STM32_USART6_IS_USED)
#error "SIOD6 requires USART6 but it is already used"
#else
#define STM32_USART6_IS_USED
#endif
#endif
#if STM32_SIO_USE_UART7
#if defined(STM32_UART7_IS_USED)
#error "SIOD7 requires UART7 but it is already used"
#else
#define STM32_UART7_IS_USED
#endif
#endif
#if STM32_SIO_USE_UART8
#if defined(STM32_UART8_IS_USED)
#error "SIOD8 requires UART8 but it is already used"
#else
#define STM32_UART8_IS_USED
#endif
#endif
#if STM32_SIO_USE_LPUART1
#if defined(STM32_LPUART1_IS_USED)
#error "LPSIOD1 requires LPUART1 but it is already used"
#else
#define STM32_LPUART1_IS_USED
#endif
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
@ -66,7 +223,11 @@
*/
#define sio_lld_driver_fields \
/* Pointer to the USARTx registers block.*/ \
USART_TypeDef *usart
USART_TypeDef *usart; \
/* USART clock frequency.*/ \
uint32_t clock; \
/* Pending USART events.*/ \
uint32_t events
/**
* @brief Low level fields of the SIO configuration structure.
@ -78,9 +239,9 @@
uint32_t presc; \
/* USART CR1 register initialization data.*/ \
uint32_t cr1; \
/* USART CR1 register initialization data.*/ \
/* USART CR2 register initialization data.*/ \
uint32_t cr2; \
/* USART CR1 register initialization data.*/ \
/* USART CR3 register initialization data.*/ \
uint32_t cr3
/**
@ -152,6 +313,38 @@
extern SIODriver SIOD1;
#endif
#if (STM32_SIO_USE_USART2 == TRUE) && !defined(__DOXYGEN__)
extern SIODriver SIOD2;
#endif
#if (STM32_SIO_USE_USART3 == TRUE) && !defined(__DOXYGEN__)
extern SIODriver SIOD3;
#endif
#if (STM32_SIO_USE_UART4 == TRUE) && !defined(__DOXYGEN__)
extern SIODriver SIOD4;
#endif
#if (STM32_SIO_USE_UART5 == TRUE) && !defined(__DOXYGEN__)
extern SIODriver SIOD5;
#endif
#if (STM32_SIO_USE_USART6 == TRUE) && !defined(__DOXYGEN__)
extern SIODriver SIOD6;
#endif
#if (STM32_SIO_USE_UART7 == TRUE) && !defined(__DOXYGEN__)
extern SIODriver SIOD7;
#endif
#if (STM32_SIO_USE_UART8 == TRUE) && !defined(__DOXYGEN__)
extern SIODriver SIOD8;
#endif
#if (STM32_SIO_USE_LPUART1 == TRUE) && !defined(__DOXYGEN__)
extern SIODriver LPSIOD1;
#endif
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -191,7 +191,7 @@ void sioStopOperation(SIODriver *siop) {
*
* @api
*/
size_t sioAsyncReadI(SIODriver *siop, size_t n, uint8_t *buffer) {
size_t sioAsyncRead(SIODriver *siop, size_t n, uint8_t *buffer) {
osalDbgCheck((siop != NULL) && (buffer));