Tentative fixes to STM32 SIO drivers.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@15394 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2022-01-22 08:25:01 +00:00
parent a5f5513642
commit 60647952ea
2 changed files with 94 additions and 80 deletions

View File

@ -713,7 +713,7 @@ msg_t sio_lld_control(SIODriver *siop, unsigned int operation, void *arg) {
*/
void sio_lld_serve_interrupt(SIODriver *siop) {
USART_TypeDef *u = siop->usart;
uint32_t isr, cr1, cr3, evtmask;
uint32_t isr, cr1, cr2, cr3, evtmask, irqmask;
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
@ -721,18 +721,25 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
disabled instead.*/
isr = u->ISR;
/* One read on control registers.*/
/* Read on control registers.*/
cr1 = u->CR1;
cr2 = u->CR2;
cr3 = u->CR3;
/* Enabled errors/events handling.*/
evtmask = isr & (USART_ISR_PE | USART_ISR_LBDF | USART_ISR_FE |
USART_ISR_ORE | USART_ISR_NE);
irqmask = ((cr1 & USART_CR1_PEIE) != 0U ? USART_ISR_PE : 0U) |
((cr2 & USART_CR2_LBDIE) != 0U ? USART_ISR_LBDF : 0U) |
((cr3 & USART_CR3_EIE) != 0U ? USART_ISR_FE |
USART_ISR_ORE |
USART_ISR_NE : 0U);
evtmask = isr & irqmask;
if (evtmask != 0U) {
uint32_t cr2;
/* One read on control registers.*/
cr2 = u->CR2;
/* Disabling event sources until errors are recognized by the
application.*/
u->CR1 = cr1 & ~USART_CR1_PEIE;
u->CR2 = cr2 & ~USART_CR2_LBDIE;
u->CR3 = cr3 & ~USART_CR3_EIE;
/* The callback is invoked if defined.*/
__sio_callback_rx_evt(siop);
@ -740,75 +747,74 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
/* Waiting thread woken, if any.*/
__sio_wakeup_rx(siop, SIO_MSG_ERRORS);
/* Disabling event sources until errors are recognized by the
application.*/
cr1 &= ~USART_CR1_PEIE;
cr2 &= ~USART_CR2_LBDIE;
cr3 &= ~USART_CR3_EIE;
/* One write on control registers.*/
u->CR2 = cr2;
/* Values could have been changed by the callback, CR2-CR3 no more needed.*/
cr1 = u->CR1;
}
/* RX FIFO is non-empty.*/
if (((cr1 & USART_CR1_RXNEIE) != 0U) &&
(isr & USART_ISR_RXNE) != 0U) {
/* Called once then the interrupt source is disabled.*/
u->CR1 = cr1 & ~USART_CR1_RXNEIE;
/* The callback is invoked if defined.*/
__sio_callback_rx(siop);
/* Waiting thread woken, if any.*/
__sio_wakeup_rx(siop, MSG_OK);
/* Called once then the interrupt source is disabled.*/
cr1 &= ~USART_CR1_RXNEIE;
}
/* RX idle condition.*/
if (((cr1 & USART_CR1_IDLEIE) != 0U) &&
(isr & USART_ISR_IDLE) != 0U) {
/* The callback is invoked if defined.*/
__sio_callback_rx_idle(siop);
/* Waiting thread woken, if any.*/
__sio_wakeup_rx(siop, SIO_MSG_IDLE);
/* The idle flag requires clearing, it stays enabled.*/
u->ICR = USART_ISR_IDLE;
/* Values could have been changed by the callback, CR2-CR3 no more needed.*/
cr1 = u->CR1;
}
/* TX FIFO is non-full.*/
if (((cr1 & USART_CR1_TXEIE) != 0U) &&
(isr & USART_ISR_TXE) != 0U) {
/* Called once then the interrupt is disabled.*/
u->CR1 = cr1 & ~USART_CR1_TXEIE;
/* The callback is invoked if defined.*/
__sio_callback_tx(siop);
/* Waiting thread woken, if any.*/
__sio_wakeup_tx(siop, MSG_OK);
/* Called once then the interrupt is disabled.*/
cr1 &= ~USART_CR1_TXEIE;
/* Values could have been changed by the callback, CR2-CR3 no more needed.*/
cr1 = u->CR1;
}
/* RX idle condition.*/
if (((cr1 & USART_CR1_IDLEIE) != 0U) &&
(isr & USART_ISR_IDLE) != 0U) {
/* The idle flag requires clearing, it stays enabled.*/
u->ICR = USART_ISR_IDLE;
/* The callback is invoked if defined.*/
__sio_callback_rx_idle(siop);
/* Waiting thread woken, if any.*/
__sio_wakeup_rx(siop, SIO_MSG_IDLE);
/* Values could have been changed by the callback, CR2-CR3 no more needed.*/
cr1 = u->CR1;
}
/* Physical transmission end.*/
if (((cr1 & USART_CR1_TCIE) != 0U) &&
(isr & USART_ISR_TC) != 0U) {
/* Called once then the interrupt is disabled.*/
u->CR1 = cr1 & ~USART_CR1_TCIE;
/* The callback is invoked if defined.*/
__sio_callback_tx_end(siop);
/* Waiting thread woken, if any.*/
__sio_wakeup_txend(siop, MSG_OK);
/* Called once then the interrupt is disabled.*/
cr1 &= ~USART_CR1_TCIE;
}
/* One write on control registers.*/
u->CR1 = cr1;
u->CR3 = cr3;
}
#endif /* HAL_USE_SIO == TRUE */

View File

@ -720,7 +720,7 @@ msg_t sio_lld_control(SIODriver *siop, unsigned int operation, void *arg) {
*/
void sio_lld_serve_interrupt(SIODriver *siop) {
USART_TypeDef *u = siop->usart;
uint32_t isr, cr1, cr3, evtmask;
uint32_t isr, cr1, cr2, cr3, evtmask, irqmask;
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
@ -728,18 +728,25 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
disabled instead.*/
isr = u->ISR;
/* One read on control registers.*/
/* Read on control registers.*/
cr1 = u->CR1;
cr2 = u->CR2;
cr3 = u->CR3;
/* Enabled errors/events handling.*/
evtmask = isr & (USART_ISR_PE | USART_ISR_LBDF | USART_ISR_FE |
USART_ISR_ORE | USART_ISR_NE);
irqmask = ((cr1 & USART_CR1_PEIE) != 0U ? USART_ISR_PE : 0U) |
((cr2 & USART_CR2_LBDIE) != 0U ? USART_ISR_LBDF : 0U) |
((cr3 & USART_CR3_EIE) != 0U ? USART_ISR_FE |
USART_ISR_ORE |
USART_ISR_NE : 0U);
evtmask = isr & irqmask;
if (evtmask != 0U) {
uint32_t cr2;
/* One read on control registers.*/
cr2 = u->CR2;
/* Disabling event sources until errors are recognized by the
application.*/
u->CR1 = cr1 & ~USART_CR1_PEIE;
u->CR2 = cr2 & ~USART_CR2_LBDIE;
u->CR3 = cr3 & ~USART_CR3_EIE;
/* The callback is invoked if defined.*/
__sio_callback_rx_evt(siop);
@ -747,75 +754,76 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
/* Waiting thread woken, if any.*/
__sio_wakeup_rx(siop, SIO_MSG_ERRORS);
/* Disabling event sources until errors are recognized by the
application.*/
cr1 &= ~USART_CR1_PEIE;
cr2 &= ~USART_CR2_LBDIE;
cr3 &= ~USART_CR3_EIE;
/* One write on control registers.*/
u->CR2 = cr2;
/* Values could have been changed by the callback, CR2 no more needed.*/
cr1 = u->CR1;
cr3 = u->CR3;
}
/* RX FIFO is non-empty.*/
if (((cr3 & USART_CR3_RXFTIE) != 0U) &&
(isr & USART_ISR_RXFT) != 0U) {
/* Called once then the interrupt source is disabled.*/
u->CR3 = cr3 & ~USART_CR3_RXFTIE;
/* The callback is invoked if defined.*/
__sio_callback_rx(siop);
/* Waiting thread woken, if any.*/
__sio_wakeup_rx(siop, MSG_OK);
/* Called once then the interrupt source is disabled.*/
cr3 &= ~USART_CR3_RXFTIE;
}
/* RX idle condition.*/
if (((cr1 & USART_CR1_IDLEIE) != 0U) &&
(isr & USART_ISR_IDLE) != 0U) {
/* The callback is invoked if defined.*/
__sio_callback_rx_idle(siop);
/* Waiting thread woken, if any.*/
__sio_wakeup_rx(siop, SIO_MSG_IDLE);
/* The idle flag requires clearing, it stays enabled.*/
u->ICR = USART_ISR_IDLE;
/* Values could have been changed by the callback, CR2 no more needed.*/
cr1 = u->CR1;
cr3 = u->CR3;
}
/* TX FIFO is non-full.*/
if (((cr3 & USART_CR3_TXFTIE) != 0U) &&
(isr & USART_ISR_TXFT) != 0U) {
/* Called once then the interrupt is disabled.*/
u->CR3 = cr3 & ~USART_CR3_TXFTIE;
/* The callback is invoked if defined.*/
__sio_callback_tx(siop);
/* Waiting thread woken, if any.*/
__sio_wakeup_tx(siop, MSG_OK);
/* Called once then the interrupt is disabled.*/
cr3 &= ~USART_CR3_TXFTIE;
/* Values could have been changed by the callback, CR2-CR3 no more needed.*/
cr1 = u->CR1;
}
/* RX idle condition.*/
if (((cr1 & USART_CR1_IDLEIE) != 0U) &&
(isr & USART_ISR_IDLE) != 0U) {
/* The idle flag requires clearing, it stays enabled.*/
u->ICR = USART_ISR_IDLE;
/* The callback is invoked if defined.*/
__sio_callback_rx_idle(siop);
/* Waiting thread woken, if any.*/
__sio_wakeup_rx(siop, SIO_MSG_IDLE);
/* Values could have been changed by the callback, CR2-CR3 no more needed.*/
cr1 = u->CR1;
}
/* Physical transmission end.*/
if (((cr1 & USART_CR1_TCIE) != 0U) &&
(isr & USART_ISR_TC) != 0U) {
/* Called once then the interrupt is disabled.*/
u->CR1 = cr1 & ~USART_CR1_TCIE;
/* The callback is invoked if defined.*/
__sio_callback_tx_end(siop);
/* Waiting thread woken, if any.*/
__sio_wakeup_txend(siop, MSG_OK);
/* Called once then the interrupt is disabled.*/
cr1 &= ~USART_CR1_TCIE;
}
/* One write on control registers.*/
u->CR1 = cr1;
u->CR3 = cr3;
}
#endif /* HAL_USE_SIO == TRUE */