summary refs log tree commit diff
diff options
context:
space:
mode:
authorStefan Kerkmann <karlk90@pm.me>2022-07-11 13:05:04 +0200
committerGitHub <noreply@github.com>2022-07-11 04:05:04 -0700
commit0348071810d30fc362e8ec8fda6764431f7939e2 (patch)
treec1b2c647acc3b45223207e273fd9c13fcf8934bc
parent35d78aa8a4587ce5286a362471380a9d4f000f3c (diff)
Stabilize Half-duplex PIO split comms (#17612)
-rw-r--r--platforms/chibios/drivers/vendor/RP/RP2040/serial_vendor.c20
1 files changed, 17 insertions, 3 deletions
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();