mirror of
https://github.com/apache/nuttx.git
synced 2026-08-28 21:00:44 +00:00
arch/rp2040: set buffer AVAILABLE bit after the rest of buffer control
Per the RP2040 datasheet section 4.1.2.5.1, when handing a buffer to the USB controller the AVAILABLE bit must be written after the rest of the buffer-control register (length and data PID) and after a short delay, because buffer control crosses from the system clock domain into the USB clock domain. Writing everything in a single store risks the controller acting on a stale length or PID. rp2040_update_buffer_control() wrote the whole word, AVAILABLE included, in one access. Follow the sequence the datasheet (and the Pico SDK) use: write the control word with AVAILABLE cleared, wait ~12 CPU cycles, then set AVAILABLE. The delay covers system clocks up to 12x the 48 MHz USB clock. Validated on raspberrypi-pico (RP2040) as part of bringing up cdcncm; no regression on cdcacm/usbmsc. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AHJRvWeBMTHwzpwjaUg4HW Signed-off-by: Ricard Rosson <ricard@groundbits.com>
This commit is contained in:
parent
53b5048b1f
commit
7ff0b8e876
1 changed files with 19 additions and 0 deletions
|
|
@ -473,6 +473,7 @@ static void rp2040_update_buffer_control(struct rp2040_ep_s *privep,
|
|||
uint32_t or_mask)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
int i;
|
||||
|
||||
if (and_mask)
|
||||
{
|
||||
|
|
@ -482,6 +483,24 @@ static void rp2040_update_buffer_control(struct rp2040_ep_s *privep,
|
|||
if (or_mask)
|
||||
{
|
||||
value |= or_mask;
|
||||
|
||||
if (or_mask & RP2040_USBCTRL_DPSRAM_EP_BUFF_CTRL_AVAIL)
|
||||
{
|
||||
/* RP2040 datasheet 4.1.2.5.1: the AVAILABLE bit must be set
|
||||
* after the rest of the buffer control register has been
|
||||
* written and had time to settle across the clock domain
|
||||
* crossing, or the controller may act on a stale length/PID.
|
||||
* 12 CPU cycles covers system clocks up to 12x clk_usb.
|
||||
*/
|
||||
|
||||
putreg32(value & ~RP2040_USBCTRL_DPSRAM_EP_BUFF_CTRL_AVAIL,
|
||||
privep->buf_ctrl);
|
||||
|
||||
for (i = 0; i < 12; i++)
|
||||
{
|
||||
__asm__ volatile("nop");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
putreg32(value, privep->buf_ctrl);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue