Skip to content

Commit 5bffece

Browse files
committed
fix(support_rp2040): expect DATA1 in EP0 OUT after receiving SETUP
The reference implementation does this by updating EP0 OUT's buffer control register in the USB interrupt handler. However, this could cause a race with the hardware potentially trying to update the same buffer control register at the same time. Therefore, I took a different approach.
1 parent 2c05718 commit 5bffece

File tree

1 file changed

+25
-9
lines changed
  • src/r3_support_rp2040/src

1 file changed

+25
-9
lines changed

src/r3_support_rp2040/src/usb.rs

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ impl usb_device::bus::UsbBus for UsbBus {
9393
Some(ep) if ep.index() == 0 => {
9494
self.ep_buf_ctrl(ep).set(0);
9595

96+
if ep_dir == UsbDirection::Out {
97+
self.ep_max_packet_size[0] = max_packet_size;
98+
}
99+
96100
// EP0 is treated specially by the hardware
97101
return Ok(ep);
98102
}
@@ -204,8 +208,9 @@ impl usb_device::bus::UsbBus for UsbBus {
204208
self.ep_buf_ctrl(EndpointAddress::from_parts(0, UsbDirection::In))
205209
.set(0);
206210

211+
// TODO: putting the correct value causes a protocol error. Why?
207212
self.ep_buf_ctrl(EndpointAddress::from_parts(0, UsbDirection::Out))
208-
.set(EP_BUF_CTRL_PID_DATA1 | EP_BUF_CTRL_AVAIL);
213+
.set(0);
209214

210215
self.ep_in_ready.set(0xffff);
211216

@@ -229,6 +234,15 @@ impl usb_device::bus::UsbBus for UsbBus {
229234
return Err(usb_device::UsbError::WouldBlock);
230235
}
231236

237+
if ep_i == 0 {
238+
// When writing to EP0 IN, reset EP0 OUT's state. We could be too
239+
// late if we tried to do this when a SETUP packet is received.
240+
self.ep_buf_ctrl(EndpointAddress::from_parts(0, UsbDirection::Out))
241+
.set(
242+
EP_BUF_CTRL_PID_DATA1 | EP_BUF_CTRL_AVAIL | (self.ep_max_packet_size[0] as u32),
243+
);
244+
}
245+
232246
let hw_buf = &self.usbctrl_dpram_u8()[self.ep_buffer_offset[ep_i] as _..];
233247
for (x, y) in hw_buf.iter().zip(buf.iter()) {
234248
x.set(*y);
@@ -286,14 +300,6 @@ impl usb_device::bus::UsbBus for UsbBus {
286300
.sie_status
287301
.write(|b| b.setup_rec().set_bit());
288302

289-
// the first OUT data packet must be DATA1
290-
let buf_ctrl = self.ep_buf_ctrl(EndpointAddress::from_parts(0, UsbDirection::Out));
291-
buf_ctrl.set(buf_ctrl.get() | EP_BUF_CTRL_PID_DATA1);
292-
293-
// should respond by DATA1
294-
let buf_ctrl = self.ep_buf_ctrl(EndpointAddress::from_parts(0, UsbDirection::In));
295-
buf_ctrl.set(buf_ctrl.get() & !EP_BUF_CTRL_PID_DATA1);
296-
297303
return Ok(8);
298304
}
299305

@@ -388,6 +394,16 @@ impl usb_device::bus::UsbBus for UsbBus {
388394

389395
if status.setup_req().bit() {
390396
ep_setup |= 1;
397+
398+
// The first DATA packet to receive by EP0 OUT must be DATA1.
399+
// However, we can't modify `ep_buf_ctrl((0, Out))` at this point
400+
// because it may already have a valid PID (DATA0/DATA1) and the
401+
// hardware may already be receiving the first packet. Therefore,
402+
// we do this when writing to EP0 In.
403+
404+
// The first DATA packet to send to EP0 IN must be DATA1
405+
self.ep_buf_ctrl(EndpointAddress::from_parts(0, UsbDirection::In))
406+
.set(0 /* clear `EP_BUF_CTRL_PID_DATA1` */);
391407
}
392408

393409
if status.buff_status().bit() {

0 commit comments

Comments
 (0)