Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion builder/sizes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func TestBinarySize(t *testing.T) {
// microcontrollers
{"hifive1b", "examples/echo", 3817, 299, 0, 2252},
{"microbit", "examples/serial", 2820, 356, 8, 2248},
{"wioterminal", "examples/pininterrupt", 8036, 1652, 132, 7480},
{"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
Expand Down
28 changes: 23 additions & 5 deletions src/machine/machine_atsamd21_usb.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ func handleUSBIRQ(intr interrupt.Interrupt) {

// Now the actual transfer handlers, ignore endpoint number 0 (setup)
var i uint32
for i = 1; i < uint32(len(endPoints)); i++ {
for i = 1; i < NumberOfUSBEndpoints; i++ {
// Check if endpoint has a pending interrupt
epFlags := getEPINTFLAG(i)
setEPINTFLAG(i, epFlags)
Expand All @@ -193,6 +193,8 @@ func handleUSBIRQ(intr interrupt.Interrupt) {
}

func initEndpoint(ep, config uint32) {
// Note: Both IN (Bank 1) and OUT (Bank 0) configurations share the same EPCFG register.
// We must use getEPCFG(ep) | ... to avoid clearing/disabling the opposite direction.
switch config {
case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn:
// set packet size
Expand All @@ -202,7 +204,7 @@ func initEndpoint(ep, config uint32) {
usbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[ep]))))

// set endpoint type
setEPCFG(ep, ((usb.ENDPOINT_TYPE_INTERRUPT + 1) << sam.USB_DEVICE_EPCFG_EPTYPE1_Pos))
setEPCFG(ep, getEPCFG(ep)|((usb.ENDPOINT_TYPE_INTERRUPT+1)<<sam.USB_DEVICE_EPCFG_EPTYPE1_Pos))

setEPINTENSET(ep, sam.USB_DEVICE_EPINTENSET_TRCPT1)

Expand All @@ -214,7 +216,7 @@ func initEndpoint(ep, config uint32) {
usbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep]))))

// set endpoint type
setEPCFG(ep, ((usb.ENDPOINT_TYPE_BULK + 1) << sam.USB_DEVICE_EPCFG_EPTYPE0_Pos))
setEPCFG(ep, getEPCFG(ep)|((usb.ENDPOINT_TYPE_BULK+1)<<sam.USB_DEVICE_EPCFG_EPTYPE0_Pos))

// receive interrupts when current transfer complete
setEPINTENSET(ep, sam.USB_DEVICE_EPINTENSET_TRCPT0)
Expand All @@ -233,7 +235,7 @@ func initEndpoint(ep, config uint32) {
usbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep]))))

// set endpoint type
setEPCFG(ep, ((usb.ENDPOINT_TYPE_INTERRUPT + 1) << sam.USB_DEVICE_EPCFG_EPTYPE0_Pos))
setEPCFG(ep, getEPCFG(ep)|((usb.ENDPOINT_TYPE_INTERRUPT+1)<<sam.USB_DEVICE_EPCFG_EPTYPE0_Pos))

// receive interrupts when current transfer complete
setEPINTENSET(ep, sam.USB_DEVICE_EPINTENSET_TRCPT0)
Expand All @@ -252,7 +254,7 @@ func initEndpoint(ep, config uint32) {
usbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[ep]))))

// set endpoint type
setEPCFG(ep, ((usb.ENDPOINT_TYPE_BULK + 1) << sam.USB_DEVICE_EPCFG_EPTYPE1_Pos))
setEPCFG(ep, getEPCFG(ep)|((usb.ENDPOINT_TYPE_BULK+1)<<sam.USB_DEVICE_EPCFG_EPTYPE1_Pos))

// NAK on endpoint IN, the bank is not yet filled in.
setEPSTATUSCLR(ep, sam.USB_DEVICE_EPSTATUSCLR_BK1RDY)
Expand Down Expand Up @@ -650,3 +652,19 @@ func setEPINTENSET(ep uint32, val uint8) {
return
}
}

func (dev *USBDevice) SetStallEPIn(ep uint32) {
setEPSTATUSSET(ep, sam.USB_DEVICE_EPSTATUSSET_STALLRQ1)
}

func (dev *USBDevice) SetStallEPOut(ep uint32) {
setEPSTATUSSET(ep, sam.USB_DEVICE_EPSTATUSSET_STALLRQ0)
}

func (dev *USBDevice) ClearStallEPIn(ep uint32) {
setEPSTATUSCLR(ep, sam.USB_DEVICE_EPSTATUSCLR_STALLRQ1)
}

func (dev *USBDevice) ClearStallEPOut(ep uint32) {
setEPSTATUSCLR(ep, sam.USB_DEVICE_EPSTATUSCLR_STALLRQ0)
}
28 changes: 23 additions & 5 deletions src/machine/machine_atsamd51_usb.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ func handleUSBIRQ(intr interrupt.Interrupt) {

// Now the actual transfer handlers, ignore endpoint number 0 (setup)
var i uint32
for i = 1; i < uint32(len(endPoints)); i++ {
for i = 1; i < NumberOfUSBEndpoints; i++ {
// Check if endpoint has a pending interrupt
epFlags := getEPINTFLAG(i)
setEPINTFLAG(i, epFlags)
Expand All @@ -196,6 +196,8 @@ func handleUSBIRQ(intr interrupt.Interrupt) {
}

func initEndpoint(ep, config uint32) {
// Note: Both IN (Bank 1) and OUT (Bank 0) configurations share the same EPCFG register.
// We must use getEPCFG(ep) | ... to avoid clearing/disabling the opposite direction.
switch config {
case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn:
// set packet size
Expand All @@ -205,7 +207,7 @@ func initEndpoint(ep, config uint32) {
usbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[ep]))))

// set endpoint type
setEPCFG(ep, ((usb.ENDPOINT_TYPE_INTERRUPT + 1) << sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE1_Pos))
setEPCFG(ep, getEPCFG(ep)|((usb.ENDPOINT_TYPE_INTERRUPT+1)<<sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE1_Pos))

setEPINTENSET(ep, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT1)

Expand All @@ -217,7 +219,7 @@ func initEndpoint(ep, config uint32) {
usbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep]))))

// set endpoint type
setEPCFG(ep, ((usb.ENDPOINT_TYPE_BULK + 1) << sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE0_Pos))
setEPCFG(ep, getEPCFG(ep)|((usb.ENDPOINT_TYPE_BULK+1)<<sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE0_Pos))

// receive interrupts when current transfer complete
setEPINTENSET(ep, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT0)
Expand All @@ -236,7 +238,7 @@ func initEndpoint(ep, config uint32) {
usbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep]))))

// set endpoint type
setEPCFG(ep, ((usb.ENDPOINT_TYPE_INTERRUPT + 1) << sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE0_Pos))
setEPCFG(ep, getEPCFG(ep)|((usb.ENDPOINT_TYPE_INTERRUPT+1)<<sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE0_Pos))

// receive interrupts when current transfer complete
setEPINTENSET(ep, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT0)
Expand All @@ -255,7 +257,7 @@ func initEndpoint(ep, config uint32) {
usbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[ep]))))

// set endpoint type
setEPCFG(ep, ((usb.ENDPOINT_TYPE_BULK + 1) << sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE1_Pos))
setEPCFG(ep, getEPCFG(ep)|((usb.ENDPOINT_TYPE_BULK+1)<<sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE1_Pos))

// NAK on endpoint IN, the bank is not yet filled in.
setEPSTATUSCLR(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSCLR_BK1RDY)
Expand Down Expand Up @@ -481,3 +483,19 @@ func setEPINTENCLR(ep uint32, val uint8) {
func setEPINTENSET(ep uint32, val uint8) {
sam.USB_DEVICE.DEVICE_ENDPOINT[ep].EPINTENSET.Set(val)
}

func (dev *USBDevice) SetStallEPIn(ep uint32) {
setEPSTATUSSET(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSSET_STALLRQ1)
}

func (dev *USBDevice) SetStallEPOut(ep uint32) {
setEPSTATUSSET(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSSET_STALLRQ0)
}

func (dev *USBDevice) ClearStallEPIn(ep uint32) {
setEPSTATUSCLR(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSCLR_STALLRQ1)
}

func (dev *USBDevice) ClearStallEPOut(ep uint32) {
setEPSTATUSCLR(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSCLR_STALLRQ0)
}
20 changes: 18 additions & 2 deletions src/machine/machine_nrf52840_usb.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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))
Expand Down Expand Up @@ -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)
}
80 changes: 57 additions & 23 deletions src/machine/machine_rp2_usb.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,38 +20,56 @@ var (

func initEndpoint(ep, config uint32) {
val := uint32(usbEpControlEnable) | uint32(usbEpControlInterruptPerBuff)

// Each endpoint has 128 bytes of DPRAM buffer space allocated (2 * usbBufferLen).
// To support bidirectional configurations using the same endpoint number,
// we allocate the first 64 bytes (Buffer0) to OUT transfers, and the remaining
// 64 bytes (Buffer1) to IN transfers by shifting the IN offset by usbBufferLen.
offset := ep*2*usbBufferLen + 0x100
val |= offset

// Bulk and interrupt endpoints must have their Packet ID reset to DATA0 when un-stalled.
epXPIDReset[ep] = false // Default to false in case an endpoint is re-initialized.
// Since both directions share the same ep, we reset their PID flags independently.
if (config & usb.EndpointIn) != 0 {
epXPIDResetIn[ep] = false
} else {
epXPIDResetOut[ep] = false
}

switch config {
case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn:
epXPIDResetIn[ep] = true
epXdata0In[ep] = false
val |= offset + usbBufferLen
val |= usbEpControlEndpointTypeInterrupt
_usbDPSRAM.EPxControl[ep].In.Set(val)
epXPIDReset[ep] = true

case usb.ENDPOINT_TYPE_BULK | usb.EndpointOut:
epXPIDResetOut[ep] = true
epXdata0Out[ep] = false
val |= offset
val |= usbEpControlEndpointTypeBulk
_usbDPSRAM.EPxControl[ep].Out.Set(val)
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
epXPIDReset[ep] = true

case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut:
epXPIDResetOut[ep] = true
epXdata0Out[ep] = false
val |= offset
val |= usbEpControlEndpointTypeInterrupt
_usbDPSRAM.EPxControl[ep].Out.Set(val)
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
epXPIDReset[ep] = true

case usb.ENDPOINT_TYPE_BULK | usb.EndpointIn:
epXPIDResetIn[ep] = true
epXdata0In[ep] = false
val |= offset + usbBufferLen
val |= usbEpControlEndpointTypeBulk
_usbDPSRAM.EPxControl[ep].In.Set(val)
epXPIDReset[ep] = true

case usb.ENDPOINT_TYPE_CONTROL:
val |= offset
val |= usbEpControlEndpointTypeControl
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBuf0CtrlData1Pid)
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
Expand Down Expand Up @@ -79,7 +97,7 @@ func sendUSBPacket(ep uint32, data []byte) {
} else {
sendOnEP0DATADONE.offset = 0
}
epXdata0[ep] = true
epXdata0In[ep] = true
}

sendViaEPIn(ep, data, count)
Expand Down Expand Up @@ -116,19 +134,29 @@ func handleEndpointRx(ep uint32) []byte {
// AckUsbOutTransfer is called to acknowledge the completion of a USB OUT transfer.
func AckUsbOutTransfer(ep uint32) {
ep = ep & 0x7F
setEPDataPID(ep, !epXdata0[ep])
setEPDataPIDOut(ep, !epXdata0Out[ep])
}

// Set the USB endpoint Packet ID to DATA0 or DATA1.
func setEPDataPID(ep uint32, dataOne bool) {
epXdata0[ep] = dataOne
if epXdata0[ep] || ep == 0 {
// Set the USB endpoint Packet ID to DATA0 or DATA1 for OUT direction.
func setEPDataPIDOut(ep uint32, dataOne bool) {
epXdata0Out[ep] = dataOne
if epXdata0Out[ep] || ep == 0 {
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlData1Pid)
}

_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
}

// Set the USB endpoint Packet ID to DATA0 or DATA1 for IN direction.
func setEPDataPIDIn(ep uint32, dataOne bool) {
epXdata0In[ep] = dataOne
if epXdata0In[ep] || ep == 0 {
_usbDPSRAM.EPxBufferControl[ep].In.SetBits(usbBuf0CtrlData1Pid)
}

_usbDPSRAM.EPxBufferControl[ep].In.SetBits(usbBuf0CtrlAvail)
}

func SendZlp() {
sendUSBPacket(0, nil)
}
Expand All @@ -138,15 +166,19 @@ func sendViaEPIn(ep uint32, data []byte, count int) {
val := uint32(count) | usbBuf0CtrlAvail

// DATA0 or DATA1
epXdata0[ep&0x7F] = !epXdata0[ep&0x7F]
if !epXdata0[ep&0x7F] {
epXdata0In[ep&0x7F] = !epXdata0In[ep&0x7F]
if !epXdata0In[ep&0x7F] {
val |= usbBuf0CtrlData1Pid
}

// Mark as full
val |= usbBuf0CtrlFull

copy(_usbDPSRAM.EPxBuffer[ep&0x7F].Buffer0[:], data[:count])
if (ep & 0x7F) == 0 {
copy(_usbDPSRAM.EPxBuffer[0].Buffer0[:], data[:count])
} else {
copy(_usbDPSRAM.EPxBuffer[ep&0x7F].Buffer1[:], data[:count])
}
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
}

Expand Down Expand Up @@ -178,9 +210,9 @@ func (dev *USBDevice) ClearStallEPIn(ep uint32) {
ep = ep & 0x7F
val := uint32(usbBuf0CtrlStall)
_usbDPSRAM.EPxBufferControl[ep].In.ClearBits(val)
if epXPIDReset[ep] {
if epXPIDResetIn[ep] {
// Reset the PID to DATA0
setEPDataPID(ep, false)
setEPDataPIDIn(ep, false)
}
}

Expand All @@ -189,9 +221,9 @@ func (dev *USBDevice) ClearStallEPOut(ep uint32) {
ep = ep & 0x7F
val := uint32(usbBuf0CtrlStall)
_usbDPSRAM.EPxBufferControl[ep].Out.ClearBits(val)
if epXPIDReset[ep] {
if epXPIDResetOut[ep] {
// Reset the PID to DATA0
setEPDataPID(ep, false)
setEPDataPIDOut(ep, false)
}
}

Expand Down Expand Up @@ -219,10 +251,12 @@ type usbBuffer struct {
}

var (
_usbDPSRAM = (*usbDPSRAM)(unsafe.Pointer(uintptr(0x50100000)))
epXdata0 [16]bool
epXPIDReset [16]bool
setupBytes [8]byte
_usbDPSRAM = (*usbDPSRAM)(unsafe.Pointer(uintptr(0x50100000)))
epXdata0In [16]bool
epXdata0Out [16]bool
epXPIDResetIn [16]bool
epXPIDResetOut [16]bool
setupBytes [8]byte
)

func (d *usbDPSRAM) setupBytes() []byte {
Expand Down
10 changes: 7 additions & 3 deletions src/machine/usb/cdc/cdc.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

package cdc

import (
"machine/usb"
)

const (
cdcEndpointACM = 1
cdcEndpointOut = 2
cdcEndpointIn = 3
cdcEndpointACM = usb.CDC_ENDPOINT_ACM
cdcEndpointOut = usb.CDC_ENDPOINT_OUT
cdcEndpointIn = usb.CDC_ENDPOINT_IN
)

// New returns USBCDC struct.
Expand Down
Loading
Loading