Skip to content

Commit 763f846

Browse files
committed
machine: expose usb endpoint stall handling
1 parent 0fdf08d commit 763f846

File tree

6 files changed

+69
-13
lines changed

6 files changed

+69
-13
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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func handleUSBIRQ(intr interrupt.Interrupt) {
6767

6868
if !ok {
6969
// Stall endpoint?
70-
sendStallViaEPIn(0)
70+
SetStallEPIn(0)
7171
}
7272

7373
}

src/machine/machine_rp2350_usb.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func handleUSBIRQ(intr interrupt.Interrupt) {
7070

7171
if !ok {
7272
// Stall endpoint?
73-
sendStallViaEPIn(0)
73+
SetStallEPIn(0)
7474
}
7575

7676
}

src/machine/machine_rp2_usb.go

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,33 @@ func initEndpoint(ep, config uint32) {
2121
offset := ep*2*usbBufferLen + 0x100
2222
val |= offset
2323

24+
// Bulk and interrupt endpoints must have their Packet ID reset to DATA0 when un-stalled
25+
epXPIDReset[ep] = false // Default to false in case an endpoint is re-initialized
26+
2427
switch config {
2528
case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn:
2629
val |= usbEpControlEndpointTypeInterrupt
2730
_usbDPSRAM.EPxControl[ep].In.Set(val)
31+
epXPIDReset[ep] = true
2832

2933
case usb.ENDPOINT_TYPE_BULK | usb.EndpointOut:
3034
val |= usbEpControlEndpointTypeBulk
3135
_usbDPSRAM.EPxControl[ep].Out.Set(val)
3236
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
3337
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
38+
epXPIDReset[ep] = true
3439

3540
case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut:
3641
val |= usbEpControlEndpointTypeInterrupt
3742
_usbDPSRAM.EPxControl[ep].Out.Set(val)
3843
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
3944
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
45+
epXPIDReset[ep] = true
4046

4147
case usb.ENDPOINT_TYPE_BULK | usb.EndpointIn:
4248
val |= usbEpControlEndpointTypeBulk
4349
_usbDPSRAM.EPxControl[ep].In.Set(val)
50+
epXPIDReset[ep] = true
4451

4552
case usb.ENDPOINT_TYPE_CONTROL:
4653
val |= usbEpControlEndpointTypeControl
@@ -109,7 +116,12 @@ func handleEndpointRx(ep uint32) []byte {
109116
}
110117

111118
func handleEndpointRxComplete(ep uint32) {
112-
epXdata0[ep] = !epXdata0[ep]
119+
setEPDataPID(ep, !epXdata0[ep])
120+
}
121+
122+
// Set the USB endpoint Packet ID to DATA0 or DATA1
123+
func setEPDataPID(ep uint32, dataOne bool) {
124+
epXdata0[ep] = dataOne
113125
if epXdata0[ep] || ep == 0 {
114126
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlData1Pid)
115127
}
@@ -138,7 +150,8 @@ func sendViaEPIn(ep uint32, data []byte, count int) {
138150
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
139151
}
140152

141-
func sendStallViaEPIn(ep uint32) {
153+
// Enable ENDPOINT_HALT/stall on a USB IN endpoint
154+
func SetStallEPIn(ep uint32) {
142155
// Prepare buffer control register value
143156
if ep == 0 {
144157
armEPZeroStall()
@@ -149,6 +162,37 @@ func sendStallViaEPIn(ep uint32) {
149162
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
150163
}
151164

165+
// Enable ENDPOINT_HALT/stall on a USB OUT endpoint
166+
func SetStallEPOut(ep uint32) {
167+
if ep == 0 {
168+
panic("SetStallEPOut: EP0 OUT not valid")
169+
}
170+
val := uint32(usbBuf0CtrlStall)
171+
_usbDPSRAM.EPxBufferControl[ep&0x7F].Out.Set(val)
172+
}
173+
174+
// Clear the ENDPOINT_HALT/stall on a USB IN endpoint
175+
func ClearStallEPIn(ep uint32) {
176+
ep = ep & 0x7F
177+
val := uint32(usbBuf0CtrlStall)
178+
_usbDPSRAM.EPxBufferControl[ep].In.ClearBits(val)
179+
if epXPIDReset[ep] {
180+
// Reset the PID to DATA0
181+
setEPDataPID(ep&0x7F, false)
182+
}
183+
}
184+
185+
// Clear the ENDPOINT_HALT/stall on a USB OUT endpoint
186+
func ClearStallEPOut(ep uint32) {
187+
ep = ep & 0x7F
188+
val := uint32(usbBuf0CtrlStall)
189+
_usbDPSRAM.EPxBufferControl[ep].Out.ClearBits(val)
190+
if epXPIDReset[ep] {
191+
// Reset the PID to DATA0
192+
setEPDataPID(ep, false)
193+
}
194+
}
195+
152196
type usbDPSRAM struct {
153197
// Note that EPxControl[0] is not EP0Control but 8-byte setup data.
154198
EPxControl [16]usbEndpointControlRegister
@@ -173,9 +217,10 @@ type usbBuffer struct {
173217
}
174218

175219
var (
176-
_usbDPSRAM = (*usbDPSRAM)(unsafe.Pointer(uintptr(0x50100000)))
177-
epXdata0 [16]bool
178-
setupBytes [8]byte
220+
_usbDPSRAM = (*usbDPSRAM)(unsafe.Pointer(uintptr(0x50100000)))
221+
epXdata0 [16]bool
222+
epXPIDReset [16]bool
223+
setupBytes [8]byte
179224
)
180225

181226
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)