From 0348071810d30fc362e8ec8fda6764431f7939e2 Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Mon, 11 Jul 2022 13:05:04 +0200 Subject: Stabilize Half-duplex PIO split comms (#17612) --- .../chibios/drivers/vendor/RP/RP2040/serial_vendor.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'platforms/chibios/drivers/vendor') diff --git a/platforms/chibios/drivers/vendor/RP/RP2040/serial_vendor.c b/platforms/chibios/drivers/vendor/RP/RP2040/serial_vendor.c index 949fc6dd93..d933dc1f5d 100644 --- a/platforms/chibios/drivers/vendor/RP/RP2040/serial_vendor.c +++ b/platforms/chibios/drivers/vendor/RP/RP2040/serial_vendor.c @@ -142,6 +142,7 @@ void pio_serve_interrupt(void) { // the generated low level with 360mV will generate a logical zero. static inline void enter_rx_state(void) { osalSysLock(); + nvicEnableVector(RP_USBCTRL_IRQ_NUMBER, RP_IRQ_USB0_PRIORITY); // Wait for the transmitting state machines FIFO to run empty. At this point // the last byte has been pulled from the transmitting state machines FIFO // into the output shift register. We have to wait a tiny bit more until @@ -163,6 +164,9 @@ static inline void enter_rx_state(void) { static inline void leave_rx_state(void) { osalSysLock(); + // We don't want to be interrupted by frequent (1KHz) USB interrupts while + // doing our timing critical sending operation. + nvicDisableVector(RP_USBCTRL_IRQ_NUMBER); // In Half-duplex operation the tx pin dual-functions as sender and // receiver. To not receive the data we will send, we disable the receiving // state machine. @@ -194,12 +198,21 @@ static inline msg_t sync_tx(sysinterval_t timeout) { msg_t msg = MSG_OK; osalSysLock(); while (pio_sm_is_tx_fifo_full(pio, tx_state_machine)) { +#if !defined(SERIAL_USART_FULL_DUPLEX) + // Enable USB interrupts again, because we might sleep for a long time + // here and don't want to be disconnected from the host. + nvicEnableVector(RP_USBCTRL_IRQ_NUMBER, RP_IRQ_USB0_PRIORITY); +#endif pio_set_irq0_source_enabled(pio, pis_sm0_tx_fifo_not_full + tx_state_machine, true); msg = osalThreadSuspendTimeoutS(&tx_thread, timeout); if (msg < MSG_OK) { break; } } +#if !defined(SERIAL_USART_FULL_DUPLEX) + // Entering timing critical territory again. + nvicDisableVector(RP_USBCTRL_IRQ_NUMBER); +#endif osalSysUnlock(); return msg; } @@ -412,11 +425,12 @@ static inline void pio_init(pin_t tx_pin, pin_t rx_pin) { pio_set_irq0_source_enabled(pio, pis_sm0_tx_fifo_not_full + tx_state_machine, true); pio_set_irq0_source_enabled(pio, pis_interrupt0, true); - // Enable PIO specific interrupt vector + // Enable PIO specific interrupt vector, as the pio implementation is timing + // critical we use the highest possible priority. #if defined(SERIAL_PIO_USE_PIO1) - nvicEnableVector(RP_PIO1_IRQ_0_NUMBER, RP_IRQ_UART0_PRIORITY); + nvicEnableVector(RP_PIO1_IRQ_0_NUMBER, CORTEX_MAX_KERNEL_PRIORITY); #else - nvicEnableVector(RP_PIO0_IRQ_0_NUMBER, RP_IRQ_UART0_PRIORITY); + nvicEnableVector(RP_PIO0_IRQ_0_NUMBER, CORTEX_MAX_KERNEL_PRIORITY); #endif enter_rx_state(); -- cgit v1.2.3