~ruther/qmk_firmware

0348071810d30fc362e8ec8fda6764431f7939e2 — Stefan Kerkmann 3 years ago 35d78aa
Stabilize Half-duplex PIO split comms (#17612)

1 files changed, 17 insertions(+), 3 deletions(-)

M platforms/chibios/drivers/vendor/RP/RP2040/serial_vendor.c
M platforms/chibios/drivers/vendor/RP/RP2040/serial_vendor.c => platforms/chibios/drivers/vendor/RP/RP2040/serial_vendor.c +17 -3
@@ 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();