From ba274008d5f9bbb9cac60f5951c0c7fd89000b14 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Mon, 9 Jun 2025 10:14:16 -0400 Subject: [PATCH] machine: implement usb receive message throttling --- src/machine/machine_atsamd21_usb.go | 8 ++++---- src/machine/machine_atsamd51_usb.go | 8 ++++---- src/machine/machine_nrf52840_usb.go | 8 ++++---- src/machine/machine_rp2040_usb.go | 5 ++--- src/machine/machine_rp2350_usb.go | 5 ++--- src/machine/machine_rp2_usb.go | 3 ++- src/machine/usb.go | 7 ++++++- src/machine/usb/config.go | 13 +++++++------ 8 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/machine/machine_atsamd21_usb.go b/src/machine/machine_atsamd21_usb.go index 8bd265267..7b9d2e14f 100644 --- a/src/machine/machine_atsamd21_usb.go +++ b/src/machine/machine_atsamd21_usb.go @@ -194,10 +194,9 @@ func handleUSBIRQ(intr interrupt.Interrupt) { setEPINTFLAG(i, epFlags) if (epFlags & sam.USB_DEVICE_EPINTFLAG_TRCPT0) > 0 { buf := handleEndpointRx(i) - if usbRxHandler[i] != nil { - usbRxHandler[i](buf) + if usbRxHandler[i] == nil || usbRxHandler[i](buf) { + AckUsbOutTransfer(i) } - handleEndpointRxComplete(i) } else if (epFlags & sam.USB_DEVICE_EPINTFLAG_TRCPT1) > 0 { if usbTxHandler[i] != nil { usbTxHandler[i]() @@ -417,7 +416,8 @@ func handleEndpointRx(ep uint32) []byte { return udd_ep_out_cache_buffer[ep][:count] } -func handleEndpointRxComplete(ep uint32) { +// AckUsbOutTransfer is called to acknowledge the completion of a USB OUT transfer. +func AckUsbOutTransfer(ep uint32) { // set byte count to zero usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos) diff --git a/src/machine/machine_atsamd51_usb.go b/src/machine/machine_atsamd51_usb.go index abd344443..a95089f75 100644 --- a/src/machine/machine_atsamd51_usb.go +++ b/src/machine/machine_atsamd51_usb.go @@ -197,10 +197,9 @@ func handleUSBIRQ(intr interrupt.Interrupt) { setEPINTFLAG(i, epFlags) if (epFlags & sam.USB_DEVICE_ENDPOINT_EPINTFLAG_TRCPT0) > 0 { buf := handleEndpointRx(i) - if usbRxHandler[i] != nil { - usbRxHandler[i](buf) + if usbRxHandler[i] == nil || usbRxHandler[i](buf) { + AckUsbOutTransfer(i) } - handleEndpointRxComplete(i) } else if (epFlags & sam.USB_DEVICE_ENDPOINT_EPINTFLAG_TRCPT1) > 0 { if usbTxHandler[i] != nil { usbTxHandler[i]() @@ -420,7 +419,8 @@ func handleEndpointRx(ep uint32) []byte { return udd_ep_out_cache_buffer[ep][:count] } -func handleEndpointRxComplete(ep uint32) { +// AckUsbOutTransfer is called to acknowledge the completion of a USB OUT transfer. +func AckUsbOutTransfer(ep uint32) { // set byte count to zero usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos) diff --git a/src/machine/machine_nrf52840_usb.go b/src/machine/machine_nrf52840_usb.go index 2442a672d..1fa46945f 100644 --- a/src/machine/machine_nrf52840_usb.go +++ b/src/machine/machine_nrf52840_usb.go @@ -206,10 +206,9 @@ func handleUSBIRQ(interrupt.Interrupt) { if nrf.USBD.EVENTS_ENDEPOUT[i].Get() > 0 { nrf.USBD.EVENTS_ENDEPOUT[i].Set(0) buf := handleEndpointRx(uint32(i)) - if usbRxHandler[i] != nil { - usbRxHandler[i](buf) + if usbRxHandler[i] == nil || usbRxHandler[i](buf) { + AckUsbOutTransfer(uint32(i)) } - handleEndpointRxComplete(uint32(i)) exitCriticalSection() } } @@ -304,7 +303,8 @@ func handleEndpointRx(ep uint32) []byte { return udd_ep_out_cache_buffer[ep][:count] } -func handleEndpointRxComplete(ep uint32) { +// AckUsbOutTransfer is called to acknowledge the completion of a USB OUT transfer. +func AckUsbOutTransfer(ep uint32) { // set ready for next data nrf.USBD.SIZE.EPOUT[ep].Set(0) } diff --git a/src/machine/machine_rp2040_usb.go b/src/machine/machine_rp2040_usb.go index 2ef08fcbe..087e3bf03 100644 --- a/src/machine/machine_rp2040_usb.go +++ b/src/machine/machine_rp2040_usb.go @@ -95,10 +95,9 @@ func handleUSBIRQ(intr interrupt.Interrupt) { for i := 0; i < 16; i++ { if s2&(1<<(i*2+1)) > 0 { buf := handleEndpointRx(uint32(i)) - if usbRxHandler[i] != nil { - usbRxHandler[i](buf) + if usbRxHandler[i] == nil || usbRxHandler[i](buf) { + AckUsbOutTransfer(uint32(i)) } - handleEndpointRxComplete(uint32(i)) } } diff --git a/src/machine/machine_rp2350_usb.go b/src/machine/machine_rp2350_usb.go index d29a3ae98..ca09262ff 100644 --- a/src/machine/machine_rp2350_usb.go +++ b/src/machine/machine_rp2350_usb.go @@ -98,10 +98,9 @@ func handleUSBIRQ(intr interrupt.Interrupt) { for i := 0; i < 16; i++ { if s2&(1<<(i*2+1)) > 0 { buf := handleEndpointRx(uint32(i)) - if usbRxHandler[i] != nil { - usbRxHandler[i](buf) + if usbRxHandler[i] == nil || usbRxHandler[i](buf) { + AckUsbOutTransfer(uint32(i)) } - handleEndpointRxComplete(uint32(i)) } } diff --git a/src/machine/machine_rp2_usb.go b/src/machine/machine_rp2_usb.go index e1a3a43ab..297cc9d9c 100644 --- a/src/machine/machine_rp2_usb.go +++ b/src/machine/machine_rp2_usb.go @@ -128,7 +128,8 @@ func handleEndpointRx(ep uint32) []byte { return _usbDPSRAM.EPxBuffer[ep].Buffer0[:sz] } -func handleEndpointRxComplete(ep uint32) { +// AckUsbOutTransfer is called to acknowledge the completion of a USB OUT transfer. +func AckUsbOutTransfer(ep uint32) { ep = ep & 0x7F setEPDataPID(ep, !epXdata0[ep]) } diff --git a/src/machine/usb.go b/src/machine/usb.go index e55ff3aa1..434ee0f1b 100644 --- a/src/machine/usb.go +++ b/src/machine/usb.go @@ -319,7 +319,12 @@ func ConfigureUSBEndpoint(desc descriptor.Descriptor, epSettings []usb.EndpointC } else { endPoints[ep.Index] = uint32(ep.Type | usb.EndpointOut) if ep.RxHandler != nil { - usbRxHandler[ep.Index] = ep.RxHandler + usbRxHandler[ep.Index] = func(b []byte) bool { + ep.RxHandler(b) + return true + } + } else if ep.DelayRxHandler != nil { + usbRxHandler[ep.Index] = ep.DelayRxHandler } } if ep.StallHandler != nil { diff --git a/src/machine/usb/config.go b/src/machine/usb/config.go index 4ce7cd803..47cce9b2d 100644 --- a/src/machine/usb/config.go +++ b/src/machine/usb/config.go @@ -1,12 +1,13 @@ package usb type EndpointConfig struct { - Index uint8 - IsIn bool - TxHandler func() - RxHandler func([]byte) - StallHandler func(Setup) bool - Type uint8 + Index uint8 + IsIn bool + TxHandler func() + RxHandler func([]byte) + DelayRxHandler func([]byte) bool + StallHandler func(Setup) bool + Type uint8 } type SetupConfig struct {