From 9bf97e3e52c09e2f7279ee37a86ec0b38275c494 Mon Sep 17 00:00:00 2001 From: Jacek Fedorynski Date: Thu, 13 Apr 2023 20:04:04 +0200 Subject: [PATCH] [rp2040] Make writes to SIE_CTRL aware of concurrent access This commit makes it so that when setting the START_TRANS bit in the SIE_CTRL register, along with some other bits, we first set all the other bits, then wait some cycles, and then set the START_TRANS bit. Doing so protects against a situation where the USB controller is reading the register at the same time and gets an incorrect value. This mirrors the procedure already applied to buffer control registers. --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 661255cf6..02f9968a7 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -562,6 +562,11 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * uint32_t flags = USB_SIE_CTRL_START_TRANS_BITS | SIE_CTRL_BASE | (ep_dir ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS) | (need_pre(dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); + // START_TRANS bit on SIE_CTRL seems to exhibit the same behavior as the AVAILABLE bit + // described in RP2040 Datasheet, release 2.1, section "4.1.2.5.1. Concurrent access". + // We write everything except the START_TRANS bit first, then wait some cycles. + usb_hw->sie_ctrl = flags & ~USB_SIE_CTRL_START_TRANS_BITS; + busy_wait_at_least_cycles(12); usb_hw->sie_ctrl = flags; }else { @@ -602,6 +607,11 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet uint32_t const flags = SIE_CTRL_BASE | USB_SIE_CTRL_SEND_SETUP_BITS | USB_SIE_CTRL_START_TRANS_BITS | (need_pre(dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); + // START_TRANS bit on SIE_CTRL seems to exhibit the same behavior as the AVAILABLE bit + // described in RP2040 Datasheet, release 2.1, section "4.1.2.5.1. Concurrent access". + // We write everything except the START_TRANS bit first, then wait some cycles. + usb_hw->sie_ctrl = flags & ~USB_SIE_CTRL_START_TRANS_BITS; + busy_wait_at_least_cycles(12); usb_hw->sie_ctrl = flags; return true;