STM32 SIO LLDs ISR revision.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@16225 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2023-04-17 08:52:45 +00:00
parent 8734411ecf
commit 70f02c80b2
2 changed files with 71 additions and 43 deletions

View File

@ -206,7 +206,7 @@ __STATIC_INLINE void usart_init(SIODriver *siop) {
osalDbgAssert((brr >= 0x300) && (brr < 0x100000), "invalid BRR value");
}
else
else
#endif
{
brr = (uint32_t)((clock / presc) / siop->config->baud);
@ -222,10 +222,10 @@ __STATIC_INLINE void usart_init(SIODriver *siop) {
}
/* Setting up USART.*/
u->BRR = brr;
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;
u->BRR = brr;
/* Starting operations.*/
u->ICR = u->ISR;
@ -741,21 +741,33 @@ msg_t sio_lld_control(SIODriver *siop, unsigned int operation, void *arg) {
*/
void sio_lld_serve_interrupt(SIODriver *siop) {
USART_TypeDef *u = siop->usart;
sioevents_t events;
uint32_t cr1, cr3;
uint32_t cr1, cr2, cr3, isr, isrmask;
osalDbgAssert(siop->state == SIO_READY, "invalid state");
/* Read on control registers.*/
cr1 = u->CR1;
cr2 = u->CR2;
cr3 = u->CR3;
/* Events to be processed.*/
events = sio_lld_get_events(siop) & siop->enabled;
if (events != 0U) {
/* Calculating the mask of status bits that should be processed according
to the state of the various CRx registers.*/
isrmask = __sio_reloc_field(cr1, USART_CR1_TXEIE, USART_CR1_TXEIE_Pos, USART_ISR_TXE_Pos) |
__sio_reloc_field(cr1, USART_CR1_RXNEIE, USART_CR1_RXNEIE_Pos, USART_ISR_RXNE_Pos) |
__sio_reloc_field(cr1, USART_CR1_IDLEIE, USART_CR1_IDLEIE_Pos, USART_ISR_IDLE_Pos) |
__sio_reloc_field(cr1, USART_CR1_TCIE, USART_CR1_TCIE_Pos, USART_ISR_TC_Pos) |
__sio_reloc_field(cr1, USART_CR1_PEIE, USART_CR1_PEIE_Pos, USART_ISR_PE_Pos) |
__sio_reloc_field(cr2, USART_CR2_LBDIE, USART_CR2_LBDIE_Pos, USART_ISR_LBDF_Pos);
if ((cr3 & USART_CR3_EIE) != 0U) {
isrmask |= USART_ISR_NE | USART_ISR_FE | USART_ISR_ORE;
}
/* Error events handled as a group.*/
if ((events & SIO_EV_ALL_ERRORS) != 0U) {
/* Status flags to be processed.*/
isr = u->ISR & isrmask;
if (isr != 0U) {
/* Error flags handled as a group.*/
if ((isr & SIO_LLD_ISR_RX_ERRORS) != 0U) {
#if SIO_USE_SYNCHRONIZATION
/* The idle flag is forcibly cleared when an RX error event is
detected.*/
@ -763,17 +775,18 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
#endif
/* All RX-related interrupt sources disabled.*/
cr3 &= ~(USART_CR3_EIE);
cr1 &= ~(USART_CR1_PEIE | USART_CR1_IDLEIE | USART_CR1_RXNEIE);
u->CR2 &= ~(USART_CR2_LBDIE);
cr1 &= ~(USART_CR1_PEIE | USART_CR1_RXNEIE | USART_CR1_IDLEIE);
cr2 &= ~(USART_CR2_LBDIE);
cr3 &= ~(USART_CR3_EIE);
/* Waiting thread woken, if any.*/
__sio_wakeup_errors(siop);
}
/* If there are no errors then we check for the other RX events.*/
/* If there are no errors then we check for the other RX-related
status flags.*/
else {
/* Idle RX event.*/
if ((events & SIO_EV_RXIDLE) != 0U) {
/* Idle RX flag.*/
if ((isr & USART_ISR_IDLE) != 0U) {
/* Interrupt source disabled.*/
cr1 &= ~USART_CR1_IDLEIE;
@ -783,13 +796,13 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
}
/* RX FIFO is non-empty.*/
if ((events & SIO_EV_RXNOTEMPY) != 0U) {
if ((isr & USART_ISR_RXNE) != 0U) {
#if SIO_USE_SYNCHRONIZATION
#if SIO_USE_SYNCHRONIZATION
/* The idle flag is forcibly cleared when an RX data event is
detected.*/
u->ICR = USART_ICR_IDLECF;
#endif
#endif
/* Interrupt source disabled.*/
cr1 &= ~USART_CR1_RXNEIE;
@ -800,7 +813,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
}
/* TX FIFO is non-full.*/
if ((events & SIO_EV_TXNOTFULL) != 0U) {
if ((isr & USART_ISR_TXE) != 0U) {
/* Interrupt source disabled.*/
cr1 &= ~USART_CR1_TXEIE;
@ -810,7 +823,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
}
/* Physical transmission end.*/
if ((events & SIO_EV_TXDONE) != 0U) {
if ((isr & USART_ISR_TC) != 0U) {
/* Interrupt source disabled.*/
cr1 &= ~USART_CR1_TCIE;
@ -821,13 +834,14 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
/* Updating control registers, some sources could have been disabled.*/
u->CR1 = cr1;
u->CR2 = cr2;
u->CR3 = cr3;
/* The callback is invoked.*/
__sio_callback(siop);
}
else {
// osalDbgAssert(false, "spurious interrupt");
osalDbgAssert(false, "spurious interrupt");
}
}

View File

@ -225,7 +225,7 @@ __STATIC_INLINE void usart_init(SIODriver *siop) {
osalDbgAssert((brr >= 0x300) && (brr < 0x100000), "invalid BRR value");
}
else
else
#endif
{
brr = (uint32_t)((clock / presc) / siop->config->baud);
@ -241,11 +241,11 @@ __STATIC_INLINE void usart_init(SIODriver *siop) {
}
/* 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->PRESC = siop->config->presc;
u->BRR = brr;
/* Starting operations.*/
u->ICR = u->ISR;
@ -793,21 +793,33 @@ msg_t sio_lld_control(SIODriver *siop, unsigned int operation, void *arg) {
*/
void sio_lld_serve_interrupt(SIODriver *siop) {
USART_TypeDef *u = siop->usart;
sioevents_t events;
uint32_t cr1, cr3;
uint32_t cr1, cr2, cr3, isr, isrmask;
osalDbgAssert(siop->state == SIO_READY, "invalid state");
/* Read on control registers.*/
cr1 = u->CR1;
cr2 = u->CR2;
cr3 = u->CR3;
/* Events to be processed.*/
events = sio_lld_get_events(siop) & siop->enabled;
if (events != 0U) {
/* Calculating the mask of status bits that should be processed according
to the state of the various CRx registers.*/
isrmask = __sio_reloc_field(cr1, USART_CR1_IDLEIE, USART_CR1_IDLEIE_Pos, USART_ISR_IDLE_Pos) |
__sio_reloc_field(cr1, USART_CR1_TCIE, USART_CR1_TCIE_Pos, USART_ISR_TC_Pos) |
__sio_reloc_field(cr1, USART_CR1_PEIE, USART_CR1_PEIE_Pos, USART_ISR_PE_Pos) |
__sio_reloc_field(cr2, USART_CR2_LBDIE, USART_CR2_LBDIE_Pos, USART_ISR_LBDF_Pos) |
__sio_reloc_field(cr3, USART_CR3_RXFTIE, USART_CR3_RXFTIE_Pos, USART_ISR_RXNE_Pos) |
__sio_reloc_field(cr3, USART_CR3_TXFTIE, USART_CR3_TXFTIE_Pos, USART_ISR_TXE_Pos);
if ((cr3 & USART_CR3_EIE) != 0U) {
isrmask |= USART_ISR_NE | USART_ISR_FE | USART_ISR_ORE;
}
/* Error events handled as a group.*/
if ((events & SIO_EV_ALL_ERRORS) != 0U) {
/* Status flags to be processed.*/
isr = u->ISR & isrmask;
if (isr != 0U) {
/* Error flags handled as a group.*/
if ((isr & SIO_LLD_ISR_RX_ERRORS) != 0U) {
#if SIO_USE_SYNCHRONIZATION
/* The idle flag is forcibly cleared when an RX error event is
detected.*/
@ -815,17 +827,18 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
#endif
/* All RX-related interrupt sources disabled.*/
cr3 &= ~(USART_CR3_EIE | USART_CR3_RXFTIE);
cr1 &= ~(USART_CR1_PEIE | USART_CR1_IDLEIE);
u->CR2 &= ~(USART_CR2_LBDIE);
cr1 &= ~(USART_CR1_PEIE | USART_CR1_IDLEIE);
cr2 &= ~(USART_CR2_LBDIE);
cr3 &= ~(USART_CR3_EIE | USART_CR3_RXFTIE);
/* Waiting thread woken, if any.*/
__sio_wakeup_errors(siop);
}
/* If there are no errors then we check for the other RX events.*/
/* If there are no errors then we check for the other RX-related
status flags.*/
else {
/* Idle RX event.*/
if ((events & SIO_EV_RXIDLE) != 0U) {
/* Idle RX flag.*/
if ((isr & USART_ISR_IDLE) != 0U) {
/* Interrupt source disabled.*/
cr1 &= ~USART_CR1_IDLEIE;
@ -835,13 +848,13 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
}
/* RX FIFO is non-empty.*/
if ((events & SIO_EV_RXNOTEMPY) != 0U) {
if ((isr & USART_ISR_RXNE) != 0U) {
#if SIO_USE_SYNCHRONIZATION
#if SIO_USE_SYNCHRONIZATION
/* The idle flag is forcibly cleared when an RX data event is
detected.*/
u->ICR = USART_ICR_IDLECF;
#endif
#endif
/* Interrupt source disabled.*/
cr3 &= ~USART_CR3_RXFTIE;
@ -852,7 +865,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
}
/* TX FIFO is non-full.*/
if ((events & SIO_EV_TXNOTFULL) != 0U) {
if ((isr & USART_ISR_TXE) != 0U) {
/* Interrupt source disabled.*/
cr3 &= ~USART_CR3_TXFTIE;
@ -862,7 +875,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
}
/* Physical transmission end.*/
if ((events & SIO_EV_TXDONE) != 0U) {
if ((isr & USART_ISR_TC) != 0U) {
/* Interrupt source disabled.*/
cr1 &= ~USART_CR1_TCIE;
@ -873,13 +886,14 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
/* Updating control registers, some sources could have been disabled.*/
u->CR1 = cr1;
u->CR2 = cr2;
u->CR3 = cr3;
/* The callback is invoked.*/
__sio_callback(siop);
}
else {
// osalDbgAssert(false, "spurious interrupt");
osalDbgAssert(false, "spurious interrupt");
}
}