From c33113ab5f26528e10d27a4345c2ead4a2deb552 Mon Sep 17 00:00:00 2001 From: Konstantin Sharlaimov Date: Mon, 8 Jun 2026 20:46:47 +0200 Subject: [PATCH] fix(usb): implement endpoint stall for nRF52840. Implement SetStallEPIn, SetStallEPOut, ClearStallEPIn, and ClearStallEPOut methods on the nRF52840 USBDevice struct using the hardware EPSTALL register to support MSC driver requirements. Also, correct the handleUSBIRQ loops to iterate over physical endpoint numbers rather than dynamic configuration entries to prevent missed or incorrectly routed endpoint interrupts. --- builder/sizes_test.go | 6 +++--- src/machine/machine_nrf52840_usb.go | 20 ++++++++++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/builder/sizes_test.go b/builder/sizes_test.go index e96577d9b..f7ee7e1b2 100644 --- a/builder/sizes_test.go +++ b/builder/sizes_test.go @@ -42,9 +42,9 @@ func TestBinarySize(t *testing.T) { // This is a small number of very diverse targets that we want to test. tests := []sizeTest{ // microcontrollers - {"hifive1b", "examples/echo", 3680, 280, 0, 2252}, - {"microbit", "examples/serial", 2694, 342, 8, 2248}, - {"wioterminal", "examples/pininterrupt", 7074, 1510, 120, 7248}, + {"hifive1b", "examples/echo", 3817, 299, 0, 2252}, + {"microbit", "examples/serial", 2820, 356, 8, 2248}, + {"wioterminal", "examples/pininterrupt", 8020, 1652, 132, 7480}, // TODO: also check wasm. Right now this is difficult, because // wasm binaries are run through wasm-opt and therefore the diff --git a/src/machine/machine_nrf52840_usb.go b/src/machine/machine_nrf52840_usb.go index 4a2c5d5a7..0dc222b37 100644 --- a/src/machine/machine_nrf52840_usb.go +++ b/src/machine/machine_nrf52840_usb.go @@ -172,7 +172,7 @@ func handleUSBIRQ(interrupt.Interrupt) { epDataStatus := nrf.USBD.EPDATASTATUS.Get() nrf.USBD.EPDATASTATUS.Set(epDataStatus) var i uint32 - for i = 1; i < uint32(len(endPoints)); i++ { + for i = 1; i < NumberOfUSBEndpoints; i++ { // Check if endpoint has a pending interrupt inDataDone := epDataStatus&(nrf.USBD_EPDATASTATUS_EPIN1<<(i-1)) > 0 outDataDone := epDataStatus&(nrf.USBD_EPDATASTATUS_EPOUT1<<(i-1)) > 0 @@ -191,7 +191,7 @@ func handleUSBIRQ(interrupt.Interrupt) { } // ENDEPOUT[n] events - for i := 0; i < len(endPoints); i++ { + for i := 0; i < NumberOfUSBEndpoints; i++ { if nrf.USBD.EVENTS_ENDEPOUT[i].Get() > 0 { nrf.USBD.EVENTS_ENDEPOUT[i].Set(0) buf := handleEndpointRx(uint32(i)) @@ -367,3 +367,19 @@ func ReceiveUSBControlPacket() ([cdcLineInfoSize]byte, error) { return b, nil } + +func (dev *USBDevice) SetStallEPIn(ep uint32) { + nrf.USBD.EPSTALL.Set(ep | nrf.USBD_EPSTALL_IO | nrf.USBD_EPSTALL_STALL) +} + +func (dev *USBDevice) SetStallEPOut(ep uint32) { + nrf.USBD.EPSTALL.Set(ep | nrf.USBD_EPSTALL_STALL) +} + +func (dev *USBDevice) ClearStallEPIn(ep uint32) { + nrf.USBD.EPSTALL.Set(ep | nrf.USBD_EPSTALL_IO) +} + +func (dev *USBDevice) ClearStallEPOut(ep uint32) { + nrf.USBD.EPSTALL.Set(ep) +}