Skip to content

Commit baff40b

Browse files
committed
machine: expose usb endpoint stall handling
1 parent dcf609d commit baff40b

File tree

5 files changed

+115
-18
lines changed

5 files changed

+115
-18
lines changed

builder/sizes_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func TestBinarySize(t *testing.T) {
4444
// microcontrollers
4545
{"hifive1b", "examples/echo", 4560, 280, 0, 2268},
4646
{"microbit", "examples/serial", 2916, 388, 8, 2272},
47-
{"wioterminal", "examples/pininterrupt", 7359, 1489, 116, 6912},
47+
{"wioterminal", "examples/pininterrupt", 7395, 1489, 116, 6912},
4848

4949
// TODO: also check wasm. Right now this is difficult, because
5050
// wasm binaries are run through wasm-opt and therefore the

src/machine/machine_rp2040_usb.go

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func handleUSBIRQ(intr interrupt.Interrupt) {
7777

7878
if !ok {
7979
// Stall endpoint?
80-
sendStallViaEPIn(0)
80+
SetStallEPIn(0)
8181
}
8282

8383
}
@@ -139,26 +139,33 @@ func initEndpoint(ep, config uint32) {
139139
offset := ep*2*usbBufferLen + 0x100
140140
val |= offset
141141

142+
// Bulk and interrupt endpoints must have their Packet ID reset to DATA0 when un-stalled
143+
epXPIDReset[ep] = false // Default to false in case an endpoint is re-initialized
144+
142145
switch config {
143146
case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn:
144147
val |= usbEpControlEndpointTypeInterrupt
145148
_usbDPSRAM.EPxControl[ep].In.Set(val)
149+
epXPIDReset[ep] = true
146150

147151
case usb.ENDPOINT_TYPE_BULK | usb.EndpointOut:
148152
val |= usbEpControlEndpointTypeBulk
149153
_usbDPSRAM.EPxControl[ep].Out.Set(val)
150154
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
151155
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
156+
epXPIDReset[ep] = true
152157

153158
case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut:
154159
val |= usbEpControlEndpointTypeInterrupt
155160
_usbDPSRAM.EPxControl[ep].Out.Set(val)
156161
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
157162
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
163+
epXPIDReset[ep] = true
158164

159165
case usb.ENDPOINT_TYPE_BULK | usb.EndpointIn:
160166
val |= usbEpControlEndpointTypeBulk
161167
_usbDPSRAM.EPxControl[ep].In.Set(val)
168+
epXPIDReset[ep] = true
162169

163170
case usb.ENDPOINT_TYPE_CONTROL:
164171
val |= usbEpControlEndpointTypeControl
@@ -245,7 +252,12 @@ func handleEndpointRx(ep uint32) []byte {
245252
}
246253

247254
func handleEndpointRxComplete(ep uint32) {
248-
epXdata0[ep] = !epXdata0[ep]
255+
setEPDataPID(ep, !epXdata0[ep])
256+
}
257+
258+
// Set the USB endpoint Packet ID to DATA0 or DATA1
259+
func setEPDataPID(ep uint32, dataOne bool) {
260+
epXdata0[ep&0x7F] = dataOne
249261
if epXdata0[ep] || ep == 0 {
250262
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlData1Pid)
251263
}
@@ -274,7 +286,8 @@ func sendViaEPIn(ep uint32, data []byte, count int) {
274286
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
275287
}
276288

277-
func sendStallViaEPIn(ep uint32) {
289+
// Enable ENDPOINT_HALT/stall on a USB IN endpoint
290+
func SetStallEPIn(ep uint32) {
278291
// Prepare buffer control register value
279292
if ep == 0 {
280293
rp.USBCTRL_REGS.EP_STALL_ARM.Set(rp.USBCTRL_REGS_EP_STALL_ARM_EP0_IN)
@@ -285,6 +298,35 @@ func sendStallViaEPIn(ep uint32) {
285298
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
286299
}
287300

301+
// Enable ENDPOINT_HALT/stall on a USB OUT endpoint
302+
func SetStallEPOut(ep uint32) {
303+
if ep == 0 {
304+
panic("SetStallEPOut: EP0 OUT not valid")
305+
}
306+
val := uint32(usbBuf0CtrlStall)
307+
_usbDPSRAM.EPxBufferControl[ep&0x7F].Out.Set(val)
308+
}
309+
310+
// Clear the ENDPOINT_HALT/stall on a USB IN endpoint
311+
func ClearStallEPIn(ep uint32) {
312+
val := uint32(usbBuf0CtrlStall)
313+
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.ClearBits(val)
314+
if epXPIDReset[ep] {
315+
// Reset the PID to DATA0
316+
setEPDataPID(ep, false)
317+
}
318+
}
319+
320+
// Clear the ENDPOINT_HALT/stall on a USB OUT endpoint
321+
func ClearStallEPOut(ep uint32) {
322+
val := uint32(usbBuf0CtrlStall)
323+
_usbDPSRAM.EPxBufferControl[ep&0x7F].Out.ClearBits(val)
324+
if epXPIDReset[ep] {
325+
// Reset the PID to DATA0
326+
setEPDataPID(ep, false)
327+
}
328+
}
329+
288330
type usbDPSRAM struct {
289331
// Note that EPxControl[0] is not EP0Control but 8-byte setup data.
290332
EPxControl [16]usbEndpointControlRegister
@@ -309,9 +351,10 @@ type usbBuffer struct {
309351
}
310352

311353
var (
312-
_usbDPSRAM = (*usbDPSRAM)(unsafe.Pointer(uintptr(0x50100000)))
313-
epXdata0 [16]bool
314-
setupBytes [8]byte
354+
_usbDPSRAM = (*usbDPSRAM)(unsafe.Pointer(uintptr(0x50100000)))
355+
epXdata0 [16]bool
356+
epXPIDReset [16]bool
357+
setupBytes [8]byte
315358
)
316359

317360
func (d *usbDPSRAM) setupBytes() []byte {

src/machine/machine_rp2350_usb.go

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func handleUSBIRQ(intr interrupt.Interrupt) {
8080

8181
if !ok {
8282
// Stall endpoint?
83-
sendStallViaEPIn(0)
83+
SetStallEPIn(0)
8484
}
8585

8686
}
@@ -142,26 +142,33 @@ func initEndpoint(ep, config uint32) {
142142
offset := ep*2*usbBufferLen + 0x100
143143
val |= offset
144144

145+
// Bulk and interrupt endpoints must have their Packet ID reset to DATA0 when un-stalled
146+
epXPIDReset[ep] = false // Default to false in case an endpoint is re-initialized
147+
145148
switch config {
146149
case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn:
147150
val |= usbEpControlEndpointTypeInterrupt
148151
_usbDPSRAM.EPxControl[ep].In.Set(val)
152+
epXPIDReset[ep] = true
149153

150154
case usb.ENDPOINT_TYPE_BULK | usb.EndpointOut:
151155
val |= usbEpControlEndpointTypeBulk
152156
_usbDPSRAM.EPxControl[ep].Out.Set(val)
153157
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
154158
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
159+
epXPIDReset[ep] = true
155160

156161
case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut:
157162
val |= usbEpControlEndpointTypeInterrupt
158163
_usbDPSRAM.EPxControl[ep].Out.Set(val)
159164
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
160165
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
166+
epXPIDReset[ep] = true
161167

162168
case usb.ENDPOINT_TYPE_BULK | usb.EndpointIn:
163169
val |= usbEpControlEndpointTypeBulk
164170
_usbDPSRAM.EPxControl[ep].In.Set(val)
171+
epXPIDReset[ep] = true
165172

166173
case usb.ENDPOINT_TYPE_CONTROL:
167174
val |= usbEpControlEndpointTypeControl
@@ -248,7 +255,12 @@ func handleEndpointRx(ep uint32) []byte {
248255
}
249256

250257
func handleEndpointRxComplete(ep uint32) {
251-
epXdata0[ep] = !epXdata0[ep]
258+
setEPDataPID(ep, !epXdata0[ep])
259+
}
260+
261+
// Set the USB endpoint Packet ID to DATA0 or DATA1
262+
func setEPDataPID(ep uint32, dataOne bool) {
263+
epXdata0[ep&0x7F] = dataOne
252264
if epXdata0[ep] || ep == 0 {
253265
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlData1Pid)
254266
}
@@ -277,7 +289,8 @@ func sendViaEPIn(ep uint32, data []byte, count int) {
277289
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
278290
}
279291

280-
func sendStallViaEPIn(ep uint32) {
292+
// Enable ENDPOINT_HALT/stall on a USB IN endpoint
293+
func SetStallEPIn(ep uint32) {
281294
// Prepare buffer control register value
282295
if ep == 0 {
283296
rp.USB.EP_STALL_ARM.Set(rp.USB_EP_STALL_ARM_EP0_IN)
@@ -288,6 +301,35 @@ func sendStallViaEPIn(ep uint32) {
288301
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
289302
}
290303

304+
// Enable ENDPOINT_HALT/stall on a USB OUT endpoint
305+
func SetStallEPOut(ep uint32) {
306+
if ep == 0 {
307+
panic("SetStallEPOut: EP0 OUT not valid")
308+
}
309+
val := uint32(usbBuf0CtrlStall)
310+
_usbDPSRAM.EPxBufferControl[ep&0x7F].Out.Set(val)
311+
}
312+
313+
// Clear the ENDPOINT_HALT/stall on a USB IN endpoint
314+
func ClearStallEPIn(ep uint32) {
315+
val := uint32(usbBuf0CtrlStall)
316+
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.ClearBits(val)
317+
if epXPIDReset[ep] {
318+
// Reset the PID to DATA0
319+
setEPDataPID(ep, false)
320+
}
321+
}
322+
323+
// Clear the ENDPOINT_HALT/stall on a USB OUT endpoint
324+
func ClearStallEPOut(ep uint32) {
325+
val := uint32(usbBuf0CtrlStall)
326+
_usbDPSRAM.EPxBufferControl[ep&0x7F].Out.ClearBits(val)
327+
if epXPIDReset[ep] {
328+
// Reset the PID to DATA0
329+
setEPDataPID(ep, false)
330+
}
331+
}
332+
291333
type usbDPSRAM struct {
292334
// Note that EPxControl[0] is not EP0Control but 8-byte setup data.
293335
EPxControl [16]usbEndpointControlRegister
@@ -312,9 +354,10 @@ type usbBuffer struct {
312354
}
313355

314356
var (
315-
_usbDPSRAM = (*usbDPSRAM)(unsafe.Pointer(uintptr(0x50100000)))
316-
epXdata0 [16]bool
317-
setupBytes [8]byte
357+
_usbDPSRAM = (*usbDPSRAM)(unsafe.Pointer(uintptr(0x50100000)))
358+
epXdata0 [16]bool
359+
epXPIDReset [16]bool
360+
setupBytes [8]byte
318361
)
319362

320363
func (d *usbDPSRAM) setupBytes() []byte {

src/machine/usb.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ var (
123123
usbTxHandler [usb.NumberOfEndpoints]func()
124124
usbRxHandler [usb.NumberOfEndpoints]func([]byte)
125125
usbSetupHandler [usb.NumberOfInterfaces]func(usb.Setup) bool
126+
usbStallHandler [usb.NumberOfEndpoints]func(usb.Setup) bool
126127

127128
endPoints = []uint32{
128129
usb.CONTROL_ENDPOINT: usb.ENDPOINT_TYPE_CONTROL,
@@ -212,6 +213,9 @@ func handleStandardSetup(setup usb.Setup) bool {
212213
if setup.WValueL == 1 { // DEVICEREMOTEWAKEUP
213214
isRemoteWakeUpEnabled = false
214215
} else if setup.WValueL == 0 { // ENDPOINTHALT
216+
if usbStallHandler[setup.WIndex&0x7F] != nil {
217+
return usbStallHandler[setup.WIndex&0x7F](setup)
218+
}
215219
isEndpointHalt = false
216220
}
217221
SendZlp()
@@ -221,6 +225,9 @@ func handleStandardSetup(setup usb.Setup) bool {
221225
if setup.WValueL == 1 { // DEVICEREMOTEWAKEUP
222226
isRemoteWakeUpEnabled = true
223227
} else if setup.WValueL == 0 { // ENDPOINTHALT
228+
if usbStallHandler[setup.WIndex&0x7F] != nil {
229+
return usbStallHandler[setup.WIndex&0x7F](setup)
230+
}
224231
isEndpointHalt = true
225232
}
226233
SendZlp()
@@ -320,6 +327,9 @@ func ConfigureUSBEndpoint(desc descriptor.Descriptor, epSettings []usb.EndpointC
320327
usbRxHandler[ep.Index] = ep.RxHandler
321328
}
322329
}
330+
if ep.StallHandler != nil {
331+
usbStallHandler[ep.Index] = ep.StallHandler
332+
}
323333
}
324334

325335
for _, s := range setup {

src/machine/usb/config.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package usb
22

33
type EndpointConfig struct {
4-
Index uint8
5-
IsIn bool
6-
TxHandler func()
7-
RxHandler func([]byte)
8-
Type uint8
4+
Index uint8
5+
IsIn bool
6+
TxHandler func()
7+
RxHandler func([]byte)
8+
StallHandler func(Setup) bool
9+
Type uint8
910
}
1011

1112
type SetupConfig struct {

0 commit comments

Comments
 (0)