[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.
This commit is contained in:
Jacek Fedorynski 2023-04-13 20:04:04 +02:00
parent 9771c76f25
commit 9bf97e3e52
1 changed files with 10 additions and 0 deletions

View File

@ -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;