From 76e68caed57bcc9d6b54f6c0d27d1f2a7250d8c2 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Sat, 23 Aug 2025 12:21:34 -0400 Subject: [PATCH 1/3] feat: add usb msc support for nrf52840 --- src/machine/machine_nrf52840_usb.go | 66 +++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/machine/machine_nrf52840_usb.go b/src/machine/machine_nrf52840_usb.go index 1fa46945fa..f0bcb1a24a 100644 --- a/src/machine/machine_nrf52840_usb.go +++ b/src/machine/machine_nrf52840_usb.go @@ -379,3 +379,69 @@ func ReceiveUSBControlPacket() ([cdcLineInfoSize]byte, error) { return b, nil } + +// Set the USB endpoint Packet ID to DATA0 or DATA1. +// In endpoints must have bit 7 (0x80) set. +func setEPDataPID(ep uint32, dataOne bool) { + val := ep + if dataOne { + val |= USBD_DTOGGLE_VALUE_Data1 << USBD_DTOGGLE_VALUE_Pos + } else { + val |= USBD_DTOGGLE_VALUE_Data0 << USBD_DTOGGLE_VALUE_Pos + } + nrf.USBD.DTOGGLE.Set(val) +} + +// Set ENDPOINT_HALT/stall status on a USB IN endpoint. +func (dev *USBDevice) SetStallEPIn(ep uint32) { + if ep&0x7F == 0 { + nrf.USBD.TASKS_EP0STALL.Set(1) + } else if ep&0x7F < NumberOfUSBEndpoints { + // Stall In Endpoint + val := 0x100 | 0x80 | ep + nrf.USBD.EPSTALL.Set(val) + } +} + +// Set ENDPOINT_HALT/stall status on a USB OUT endpoint. +func (dev *USBDevice) SetStallEPOut(ep uint32) { + if ep == 0 { + nrf.USBD.TASKS_EP0STALL.Set(1) + } else if ep < NumberOfUSBEndpoints { + // Stall Out Endpoint + val := 0x100 | 0x00 | ep + nrf.USBD.EPSTALL.Set(val) + } +} + +// Clear the ENDPOINT_HALT/stall on a USB IN endpoint. +func (dev *USBDevice) ClearStallEPIn(ep uint32) { + if ep&0x7F == 0 { + nrf.USBD.TASKS_EP0STALL.Set(0) + } else if ep&0x7F < NumberOfUSBEndpoints { + // Reset the endpoint data PID to DATA0 + ep |= 0x80 // Set endpoint direction bit + setEPDataPID(ep, false) + + // No-stall In Endpoint + val := 0x000 | 0x80 | ep + nrf.USBD.EPSTALL.Set(val) + } +} + +// Clear the ENDPOINT_HALT/stall on a USB OUT endpoint. +func (dev *USBDevice) ClearStallEPOut(ep uint32) { + if ep == 0 { + nrf.USBD.TASKS_EP0STALL.Set(0) + } else if ep < NumberOfUSBEndpoints { + // Reset the endpoint data PID to DATA0 + setEPDataPID(ep, false) + + // No-stall Out Endpoint + val := 0x000 | 0x00 | ep + nrf.USBD.EPSTALL.Set(val) + + // Write a value to the SIZE register to allow nRF to ACK/accept data + nrf.USBD.SIZE.EPOUT[ep].Set(0) + } +} From 9653ca30fbf41237d03b4de7bb79c6d3309382c8 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Sat, 23 Aug 2025 12:45:55 -0400 Subject: [PATCH 2/3] fix: reference nrf device constants --- src/machine/machine_nrf52840_usb.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/machine/machine_nrf52840_usb.go b/src/machine/machine_nrf52840_usb.go index f0bcb1a24a..3587a69ac5 100644 --- a/src/machine/machine_nrf52840_usb.go +++ b/src/machine/machine_nrf52840_usb.go @@ -385,9 +385,9 @@ func ReceiveUSBControlPacket() ([cdcLineInfoSize]byte, error) { func setEPDataPID(ep uint32, dataOne bool) { val := ep if dataOne { - val |= USBD_DTOGGLE_VALUE_Data1 << USBD_DTOGGLE_VALUE_Pos + val |= nrf.USBD_DTOGGLE_VALUE_Data1 << nrf.USBD_DTOGGLE_VALUE_Pos } else { - val |= USBD_DTOGGLE_VALUE_Data0 << USBD_DTOGGLE_VALUE_Pos + val |= nrf.USBD_DTOGGLE_VALUE_Data0 << nrf.USBD_DTOGGLE_VALUE_Pos } nrf.USBD.DTOGGLE.Set(val) } From f246bfffb372375a6bfbff641bfc7abf8b59e6d8 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Wed, 17 Sep 2025 09:00:12 -0400 Subject: [PATCH 3/3] fix(msc): set min buffer cap to usb packet size --- src/machine/usb/msc/disk.go | 5 +++-- src/machine/usb/msc/msc.go | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/machine/usb/msc/disk.go b/src/machine/usb/msc/disk.go index 6624d38c01..39a20c4838 100644 --- a/src/machine/usb/msc/disk.go +++ b/src/machine/usb/msc/disk.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "machine" + "machine/usb" "time" ) @@ -17,8 +18,8 @@ func (m *msc) RegisterBlockDevice(dev machine.BlockDevice) { m.dev = dev if cap(m.blockCache) != int(dev.WriteBlockSize()) { - m.blockCache = make([]byte, dev.WriteBlockSize()) - m.buf = make([]byte, dev.WriteBlockSize()) + m.blockCache = make([]byte, max(usb.EndpointPacketSize, dev.WriteBlockSize())) + m.buf = make([]byte, max(usb.EndpointPacketSize, dev.WriteBlockSize())) } m.blockSizeRaw = uint32(m.dev.WriteBlockSize()) diff --git a/src/machine/usb/msc/msc.go b/src/machine/usb/msc/msc.go index d3bf8d6e29..1a5b04512d 100644 --- a/src/machine/usb/msc/msc.go +++ b/src/machine/usb/msc/msc.go @@ -72,9 +72,9 @@ func newMSC(dev machine.BlockDevice) *msc { maxPacketSize := descriptor.EndpointMSCIN.GetMaxPacketSize() m := &msc{ // Some platforms require reads/writes to be aligned to the full underlying hardware block - blockCache: make([]byte, dev.WriteBlockSize()), + blockCache: make([]byte, max(usb.EndpointPacketSize, dev.WriteBlockSize())), blockSizeUSB: 512, - buf: make([]byte, dev.WriteBlockSize()), + buf: make([]byte, max(usb.EndpointPacketSize, dev.WriteBlockSize())), cswBuf: make([]byte, csw.MsgLen), cbw: &CBW{Data: make([]byte, 31)}, maxPacketSize: uint32(maxPacketSize),