Tentative SIO optimization (STM32 USARTv3-only so far).

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@15749 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2022-09-02 12:01:53 +00:00
parent 30c98c85b7
commit 11c7c2bf2a
3 changed files with 32 additions and 51 deletions

View File

@ -565,8 +565,9 @@ sioevents_t sio_lld_get_and_clear_errors(SIODriver *siop) {
/* Clearing captured events.*/ /* Clearing captured events.*/
siop->usart->ICR = isr; siop->usart->ICR = isr;
/* Status flags cleared, now the RX errors-related interrupts can be /* Status flags cleared, now the RX-related interrupts can be
enabled again.*/ enabled again.*/
usart_enable_rx_irq(siop);
usart_enable_rx_errors_irq(siop); usart_enable_rx_errors_irq(siop);
/* Translating the status flags in SIO events.*/ /* Translating the status flags in SIO events.*/
@ -806,7 +807,7 @@ msg_t sio_lld_control(SIODriver *siop, unsigned int operation, void *arg) {
*/ */
void sio_lld_serve_interrupt(SIODriver *siop) { void sio_lld_serve_interrupt(SIODriver *siop) {
USART_TypeDef *u = siop->usart; USART_TypeDef *u = siop->usart;
uint32_t isr, isrmask; uint32_t isr;
uint32_t cr1, cr2, cr3; uint32_t cr1, cr2, cr3;
osalDbgAssert(siop->state == SIO_READY, "invalid state"); osalDbgAssert(siop->state == SIO_READY, "invalid state");
@ -816,23 +817,9 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
cr2 = u->CR2; cr2 = u->CR2;
cr3 = u->CR3; cr3 = u->CR3;
/* Calculating the mask of the interrupts to be processed, BTW, thanks ST
for placing interrupt enable bits randomly in 3 distinct registers
instead of a dedicated IER (ISR, ICR, see the pattern?).*/
isrmask = __sio_reloc_field(cr3, USART_CR3_EIE_Msk, USART_CR3_EIE_Pos, USART_ISR_NE_Pos) |
__sio_reloc_field(cr3, USART_CR3_EIE_Msk, USART_CR3_EIE_Pos, USART_ISR_FE_Pos) |
__sio_reloc_field(cr3, USART_CR3_EIE_Msk, USART_CR3_EIE_Pos, USART_ISR_ORE_Pos) |
__sio_reloc_field(cr1, USART_CR1_PEIE_Msk, USART_CR1_PEIE_Pos, USART_ISR_PE_Pos) |
__sio_reloc_field(cr2, USART_CR2_LBDIE_Msk, USART_CR2_LBDIE_Pos, USART_ISR_LBDF_Pos) |
__sio_reloc_field(cr1, USART_CR1_IDLEIE_Msk, USART_CR1_IDLEIE_Pos, USART_ISR_IDLE_Pos) |
__sio_reloc_field(cr3, USART_CR3_RXFTIE_Msk, USART_CR3_RXFTIE_Pos, USART_ISR_RXFT_Pos) |
__sio_reloc_field(cr3, USART_CR3_TXFTIE_Msk, USART_CR3_TXFTIE_Pos, USART_ISR_TXFT_Pos) |
__sio_reloc_field(cr1, USART_CR1_TCIE_Msk, USART_CR1_TCIE_Pos, USART_ISR_TC_Pos);
/* Note, ISR flags are just read but not cleared, ISR sources are /* Note, ISR flags are just read but not cleared, ISR sources are
disabled instead.*/ disabled instead.*/
isr = u->ISR; isr = u->ISR;
isr = isr & isrmask;
if (isr != 0U) { if (isr != 0U) {
/* Error events handled as a group, except ORE.*/ /* Error events handled as a group, except ORE.*/
@ -845,15 +832,16 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
u->ICR = USART_ICR_IDLECF; u->ICR = USART_ICR_IDLECF;
#endif #endif
/* Interrupt sources disabled.*/ /* RX-related interrupt sources akll disabled.*/
cr3 &= ~USART_CR3_EIE; cr3 &= ~(USART_CR3_EIE | USART_CR3_RXFTIE);
cr2 &= ~USART_CR2_LBDIE; cr2 &= ~(USART_CR2_LBDIE);
cr1 &= ~USART_CR1_PEIE; cr1 &= ~(USART_CR1_PEIE | USART_CR1_IDLEIE);
/* Waiting thread woken, if any.*/ /* Waiting thread woken, if any.*/
__sio_wakeup_errors(siop); __sio_wakeup_errors(siop);
} }
/* If there are no errors then we check for the other RX events.*/
else {
/* Idle RX event.*/ /* Idle RX event.*/
if ((isr & USART_ISR_IDLE) != 0U) { if ((isr & USART_ISR_IDLE) != 0U) {
@ -879,6 +867,7 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
/* Waiting thread woken, if any.*/ /* Waiting thread woken, if any.*/
__sio_wakeup_rx(siop); __sio_wakeup_rx(siop);
} }
}
/* TX FIFO is non-full.*/ /* TX FIFO is non-full.*/
if ((isr & USART_ISR_TXFT) != 0U) { if ((isr & USART_ISR_TXFT) != 0U) {

View File

@ -518,7 +518,7 @@ size_t sioAsyncWrite(SIODriver *siop, const uint8_t *buffer, size_t n) {
* @retval MSG_OK if there is data in the RX FIFO. * @retval MSG_OK if there is data in the RX FIFO.
* @retval MSG_TIMEOUT if synchronization timed out. * @retval MSG_TIMEOUT if synchronization timed out.
* @retval MSG_RESET it the operation has been stopped while waiting. * @retval MSG_RESET it the operation has been stopped while waiting.
* @retval SIO_MSG_ERRORS if RX errors occurred during wait. * @retval SIO_MSG_ERRORS if RX errors occurred before or during wait.
* *
* @api * @api
*/ */
@ -532,7 +532,7 @@ msg_t sioSynchronizeRX(SIODriver *siop, sysinterval_t timeout) {
osalDbgAssert(siop->state == SIO_READY, "invalid state"); osalDbgAssert(siop->state == SIO_READY, "invalid state");
/* Checking for errors before going to sleep.*/ /* Checking for errors before going to sleep.*/
if (((siop->enabled & SIO_EV_ALL_ERRORS) != 0U) && sioHasRXErrorsX(siop)) { if (sioHasRXErrorsX(siop)) {
osalSysUnlock(); osalSysUnlock();
return SIO_MSG_ERRORS; return SIO_MSG_ERRORS;
} }
@ -563,7 +563,7 @@ msg_t sioSynchronizeRX(SIODriver *siop, sysinterval_t timeout) {
* @retval MSG_OK if RW went idle. * @retval MSG_OK if RW went idle.
* @retval MSG_TIMEOUT if synchronization timed out. * @retval MSG_TIMEOUT if synchronization timed out.
* @retval MSG_RESET it the operation has been stopped while waiting. * @retval MSG_RESET it the operation has been stopped while waiting.
* @retval SIO_MSG_ERRORS if RX errors occurred during wait. * @retval SIO_MSG_ERRORS if RX errors occurred before or during wait.
* *
* @api * @api
*/ */
@ -577,7 +577,7 @@ msg_t sioSynchronizeRXIdle(SIODriver *siop, sysinterval_t timeout) {
osalDbgAssert(siop->state == SIO_READY, "invalid state"); osalDbgAssert(siop->state == SIO_READY, "invalid state");
/* Checking for errors before going to sleep.*/ /* Checking for errors before going to sleep.*/
if (((siop->enabled & SIO_EV_ALL_ERRORS) != 0U) && sioHasRXErrorsX(siop)) { if (sioHasRXErrorsX(siop)) {
osalSysUnlock(); osalSysUnlock();
return SIO_MSG_ERRORS; return SIO_MSG_ERRORS;
} }

View File

@ -60,15 +60,7 @@ static void cmd_write(BaseSequentialStream *chp, int argc, char *argv[]) {
} }
while (chnGetTimeout((BaseChannel *)chp, TIME_IMMEDIATE) == Q_TIMEOUT) { while (chnGetTimeout((BaseChannel *)chp, TIME_IMMEDIATE) == Q_TIMEOUT) {
#if 1
/* Writing in channel mode.*/
chnWrite(&bsio1, buf, sizeof buf - 1); 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"); chprintf(chp, "\r\n\nstopped\r\n");
} }