machine/rp2: merge common usb code (#4856)

* machine/rp2: merge common usb code
* chore: add note on noinline reason
This commit is contained in:
Michael Smith
2025-04-15 05:07:47 -04:00
committed by GitHub
parent 41e501aaf4
commit 133e32c1c4
6 changed files with 255 additions and 465 deletions
+2
View File
@@ -334,6 +334,8 @@ func SendUSBInPacket(ep uint32, data []byte) bool {
return true
}
// Prevent file size increases: https://github.com/tinygo-org/tinygo/pull/998
//
//go:noinline
func sendUSBPacket(ep uint32, data []byte, maxsize uint16) {
l := uint16(len(data))
+2
View File
@@ -337,6 +337,8 @@ func SendUSBInPacket(ep uint32, data []byte) bool {
return true
}
// Prevent file size increases: https://github.com/tinygo-org/tinygo/pull/998
//
//go:noinline
func sendUSBPacket(ep uint32, data []byte, maxsize uint16) {
l := uint16(len(data))
+2
View File
@@ -252,6 +252,8 @@ func SendUSBInPacket(ep uint32, data []byte) bool {
return true
}
// Prevent file size increases: https://github.com/tinygo-org/tinygo/pull/998
//
//go:noinline
func sendUSBPacket(ep uint32, data []byte, maxsize uint16) {
count := len(data)
+2 -231
View File
@@ -6,16 +6,6 @@ import (
"device/rp"
"machine/usb"
"runtime/interrupt"
"runtime/volatile"
"unsafe"
)
var (
sendOnEP0DATADONE struct {
offset int
data []byte
pid uint32
}
)
// Configure the USB peripheral. The config is here for compatibility with the UART interface.
@@ -134,40 +124,6 @@ func handleUSBIRQ(intr interrupt.Interrupt) {
}
}
func initEndpoint(ep, config uint32) {
val := uint32(usbEpControlEnable) | uint32(usbEpControlInterruptPerBuff)
offset := ep*2*usbBufferLen + 0x100
val |= offset
switch config {
case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn:
val |= usbEpControlEndpointTypeInterrupt
_usbDPSRAM.EPxControl[ep].In.Set(val)
case usb.ENDPOINT_TYPE_BULK | usb.EndpointOut:
val |= usbEpControlEndpointTypeBulk
_usbDPSRAM.EPxControl[ep].Out.Set(val)
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut:
val |= usbEpControlEndpointTypeInterrupt
_usbDPSRAM.EPxControl[ep].Out.Set(val)
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
case usb.ENDPOINT_TYPE_BULK | usb.EndpointIn:
val |= usbEpControlEndpointTypeBulk
_usbDPSRAM.EPxControl[ep].In.Set(val)
case usb.ENDPOINT_TYPE_CONTROL:
val |= usbEpControlEndpointTypeControl
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBuf0CtrlData1Pid)
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
}
}
func handleUSBSetAddress(setup usb.Setup) bool {
// Using 570μs timeout which is exactly the same as SAMD21.
const ackTimeout = 570
@@ -188,191 +144,6 @@ func handleUSBSetAddress(setup usb.Setup) bool {
return true
}
// SendUSBInPacket sends a packet for USB (interrupt in / bulk in).
func SendUSBInPacket(ep uint32, data []byte) bool {
sendUSBPacket(ep, data, 0)
return true
func armEPZeroStall() {
rp.USBCTRL_REGS.EP_STALL_ARM.Set(rp.USBCTRL_REGS_EP_STALL_ARM_EP0_IN)
}
//go:noinline
func sendUSBPacket(ep uint32, data []byte, maxsize uint16) {
count := len(data)
if 0 < int(maxsize) && int(maxsize) < count {
count = int(maxsize)
}
if ep == 0 {
if count > usb.EndpointPacketSize {
count = usb.EndpointPacketSize
sendOnEP0DATADONE.offset = count
sendOnEP0DATADONE.data = data
} else {
sendOnEP0DATADONE.offset = 0
}
epXdata0[ep] = true
}
sendViaEPIn(ep, data, count)
}
func ReceiveUSBControlPacket() ([cdcLineInfoSize]byte, error) {
var b [cdcLineInfoSize]byte
ep := 0
for !_usbDPSRAM.EPxBufferControl[ep].Out.HasBits(usbBuf0CtrlFull) {
// TODO: timeout
}
ctrl := _usbDPSRAM.EPxBufferControl[ep].Out.Get()
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
sz := ctrl & usbBuf0CtrlLenMask
copy(b[:], _usbDPSRAM.EPxBuffer[ep].Buffer0[:sz])
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlData1Pid)
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
return b, nil
}
func handleEndpointRx(ep uint32) []byte {
ctrl := _usbDPSRAM.EPxBufferControl[ep].Out.Get()
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
sz := ctrl & usbBuf0CtrlLenMask
return _usbDPSRAM.EPxBuffer[ep].Buffer0[:sz]
}
func handleEndpointRxComplete(ep uint32) {
epXdata0[ep] = !epXdata0[ep]
if epXdata0[ep] || ep == 0 {
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlData1Pid)
}
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
}
func SendZlp() {
sendUSBPacket(0, []byte{}, 0)
}
func sendViaEPIn(ep uint32, data []byte, count int) {
// Prepare buffer control register value
val := uint32(count) | usbBuf0CtrlAvail
// DATA0 or DATA1
epXdata0[ep&0x7F] = !epXdata0[ep&0x7F]
if !epXdata0[ep&0x7F] {
val |= usbBuf0CtrlData1Pid
}
// Mark as full
val |= usbBuf0CtrlFull
copy(_usbDPSRAM.EPxBuffer[ep&0x7F].Buffer0[:], data[:count])
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
}
func sendStallViaEPIn(ep uint32) {
// Prepare buffer control register value
if ep == 0 {
rp.USBCTRL_REGS.EP_STALL_ARM.Set(rp.USBCTRL_REGS_EP_STALL_ARM_EP0_IN)
}
val := uint32(usbBuf0CtrlFull)
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
val |= uint32(usbBuf0CtrlStall)
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
}
type usbDPSRAM struct {
// Note that EPxControl[0] is not EP0Control but 8-byte setup data.
EPxControl [16]usbEndpointControlRegister
EPxBufferControl [16]usbBufferControlRegister
EPxBuffer [16]usbBuffer
}
type usbEndpointControlRegister struct {
In volatile.Register32
Out volatile.Register32
}
type usbBufferControlRegister struct {
In volatile.Register32
Out volatile.Register32
}
type usbBuffer struct {
Buffer0 [usbBufferLen]byte
Buffer1 [usbBufferLen]byte
}
var (
_usbDPSRAM = (*usbDPSRAM)(unsafe.Pointer(uintptr(0x50100000)))
epXdata0 [16]bool
setupBytes [8]byte
)
func (d *usbDPSRAM) setupBytes() []byte {
data := d.EPxControl[usb.CONTROL_ENDPOINT].In.Get()
setupBytes[0] = byte(data)
setupBytes[1] = byte(data >> 8)
setupBytes[2] = byte(data >> 16)
setupBytes[3] = byte(data >> 24)
data = d.EPxControl[usb.CONTROL_ENDPOINT].Out.Get()
setupBytes[4] = byte(data)
setupBytes[5] = byte(data >> 8)
setupBytes[6] = byte(data >> 16)
setupBytes[7] = byte(data >> 24)
return setupBytes[:]
}
func (d *usbDPSRAM) clear() {
for i := 0; i < len(d.EPxControl); i++ {
d.EPxControl[i].In.Set(0)
d.EPxControl[i].Out.Set(0)
d.EPxBufferControl[i].In.Set(0)
d.EPxBufferControl[i].Out.Set(0)
}
}
const (
// DPRAM : Endpoint control register
usbEpControlEnable = 0x80000000
usbEpControlDoubleBuffered = 0x40000000
usbEpControlInterruptPerBuff = 0x20000000
usbEpControlInterruptPerDoubleBuff = 0x10000000
usbEpControlEndpointType = 0x0c000000
usbEpControlInterruptOnStall = 0x00020000
usbEpControlInterruptOnNak = 0x00010000
usbEpControlBufferAddress = 0x0000ffff
usbEpControlEndpointTypeControl = 0x00000000
usbEpControlEndpointTypeISO = 0x04000000
usbEpControlEndpointTypeBulk = 0x08000000
usbEpControlEndpointTypeInterrupt = 0x0c000000
// Endpoint buffer control bits
usbBuf1CtrlFull = 0x80000000
usbBuf1CtrlLast = 0x40000000
usbBuf1CtrlData0Pid = 0x20000000
usbBuf1CtrlData1Pid = 0x00000000
usbBuf1CtrlSel = 0x10000000
usbBuf1CtrlStall = 0x08000000
usbBuf1CtrlAvail = 0x04000000
usbBuf1CtrlLenMask = 0x03FF0000
usbBuf0CtrlFull = 0x00008000
usbBuf0CtrlLast = 0x00004000
usbBuf0CtrlData0Pid = 0x00000000
usbBuf0CtrlData1Pid = 0x00002000
usbBuf0CtrlSel = 0x00001000
usbBuf0CtrlStall = 0x00000800
usbBuf0CtrlAvail = 0x00000400
usbBuf0CtrlLenMask = 0x000003FF
usbBufferLen = 64
)
+5 -234
View File
@@ -6,16 +6,6 @@ import (
"device/rp"
"machine/usb"
"runtime/interrupt"
"runtime/volatile"
"unsafe"
)
var (
sendOnEP0DATADONE struct {
offset int
data []byte
pid uint32
}
)
// Configure the USB peripheral. The config is here for compatibility with the UART interface.
@@ -104,7 +94,7 @@ func handleUSBIRQ(intr interrupt.Interrupt) {
s2 := rp.USB.BUFF_STATUS.Get()
// OUT (PC -> rp2040)
// OUT (PC -> rp2350)
for i := 0; i < 16; i++ {
if s2&(1<<(i*2+1)) > 0 {
buf := handleEndpointRx(uint32(i))
@@ -115,7 +105,7 @@ func handleUSBIRQ(intr interrupt.Interrupt) {
}
}
// IN (rp2040 -> PC)
// IN (rp2350 -> PC)
for i := 0; i < 16; i++ {
if s2&(1<<(i*2)) > 0 {
if usbTxHandler[i] != nil {
@@ -137,44 +127,10 @@ func handleUSBIRQ(intr interrupt.Interrupt) {
}
}
func initEndpoint(ep, config uint32) {
val := uint32(usbEpControlEnable) | uint32(usbEpControlInterruptPerBuff)
offset := ep*2*usbBufferLen + 0x100
val |= offset
switch config {
case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn:
val |= usbEpControlEndpointTypeInterrupt
_usbDPSRAM.EPxControl[ep].In.Set(val)
case usb.ENDPOINT_TYPE_BULK | usb.EndpointOut:
val |= usbEpControlEndpointTypeBulk
_usbDPSRAM.EPxControl[ep].Out.Set(val)
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut:
val |= usbEpControlEndpointTypeInterrupt
_usbDPSRAM.EPxControl[ep].Out.Set(val)
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
case usb.ENDPOINT_TYPE_BULK | usb.EndpointIn:
val |= usbEpControlEndpointTypeBulk
_usbDPSRAM.EPxControl[ep].In.Set(val)
case usb.ENDPOINT_TYPE_CONTROL:
val |= usbEpControlEndpointTypeControl
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBuf0CtrlData1Pid)
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
}
}
func handleUSBSetAddress(setup usb.Setup) bool {
// Using 570μs timeout which is exactly the same as SAMD21.
const ackTimeout = 570
rp.USB.SIE_STATUS.Set(rp.USB_SIE_STATUS_ACK_REC)
sendUSBPacket(0, []byte{}, 0)
@@ -191,191 +147,6 @@ func handleUSBSetAddress(setup usb.Setup) bool {
return true
}
// SendUSBInPacket sends a packet for USB (interrupt in / bulk in).
func SendUSBInPacket(ep uint32, data []byte) bool {
sendUSBPacket(ep, data, 0)
return true
func armEPZeroStall() {
rp.USB.EP_STALL_ARM.Set(rp.USB_EP_STALL_ARM_EP0_IN)
}
//go:noinline
func sendUSBPacket(ep uint32, data []byte, maxsize uint16) {
count := len(data)
if 0 < int(maxsize) && int(maxsize) < count {
count = int(maxsize)
}
if ep == 0 {
if count > usb.EndpointPacketSize {
count = usb.EndpointPacketSize
sendOnEP0DATADONE.offset = count
sendOnEP0DATADONE.data = data
} else {
sendOnEP0DATADONE.offset = 0
}
epXdata0[ep] = true
}
sendViaEPIn(ep, data, count)
}
func ReceiveUSBControlPacket() ([cdcLineInfoSize]byte, error) {
var b [cdcLineInfoSize]byte
ep := 0
for !_usbDPSRAM.EPxBufferControl[ep].Out.HasBits(usbBuf0CtrlFull) {
// TODO: timeout
}
ctrl := _usbDPSRAM.EPxBufferControl[ep].Out.Get()
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
sz := ctrl & usbBuf0CtrlLenMask
copy(b[:], _usbDPSRAM.EPxBuffer[ep].Buffer0[:sz])
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlData1Pid)
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
return b, nil
}
func handleEndpointRx(ep uint32) []byte {
ctrl := _usbDPSRAM.EPxBufferControl[ep].Out.Get()
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
sz := ctrl & usbBuf0CtrlLenMask
return _usbDPSRAM.EPxBuffer[ep].Buffer0[:sz]
}
func handleEndpointRxComplete(ep uint32) {
epXdata0[ep] = !epXdata0[ep]
if epXdata0[ep] || ep == 0 {
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlData1Pid)
}
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
}
func SendZlp() {
sendUSBPacket(0, []byte{}, 0)
}
func sendViaEPIn(ep uint32, data []byte, count int) {
// Prepare buffer control register value
val := uint32(count) | usbBuf0CtrlAvail
// DATA0 or DATA1
epXdata0[ep&0x7F] = !epXdata0[ep&0x7F]
if !epXdata0[ep&0x7F] {
val |= usbBuf0CtrlData1Pid
}
// Mark as full
val |= usbBuf0CtrlFull
copy(_usbDPSRAM.EPxBuffer[ep&0x7F].Buffer0[:], data[:count])
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
}
func sendStallViaEPIn(ep uint32) {
// Prepare buffer control register value
if ep == 0 {
rp.USB.EP_STALL_ARM.Set(rp.USB_EP_STALL_ARM_EP0_IN)
}
val := uint32(usbBuf0CtrlFull)
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
val |= uint32(usbBuf0CtrlStall)
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
}
type usbDPSRAM struct {
// Note that EPxControl[0] is not EP0Control but 8-byte setup data.
EPxControl [16]usbEndpointControlRegister
EPxBufferControl [16]usbBufferControlRegister
EPxBuffer [16]usbBuffer
}
type usbEndpointControlRegister struct {
In volatile.Register32
Out volatile.Register32
}
type usbBufferControlRegister struct {
In volatile.Register32
Out volatile.Register32
}
type usbBuffer struct {
Buffer0 [usbBufferLen]byte
Buffer1 [usbBufferLen]byte
}
var (
_usbDPSRAM = (*usbDPSRAM)(unsafe.Pointer(uintptr(0x50100000)))
epXdata0 [16]bool
setupBytes [8]byte
)
func (d *usbDPSRAM) setupBytes() []byte {
data := d.EPxControl[usb.CONTROL_ENDPOINT].In.Get()
setupBytes[0] = byte(data)
setupBytes[1] = byte(data >> 8)
setupBytes[2] = byte(data >> 16)
setupBytes[3] = byte(data >> 24)
data = d.EPxControl[usb.CONTROL_ENDPOINT].Out.Get()
setupBytes[4] = byte(data)
setupBytes[5] = byte(data >> 8)
setupBytes[6] = byte(data >> 16)
setupBytes[7] = byte(data >> 24)
return setupBytes[:]
}
func (d *usbDPSRAM) clear() {
for i := 0; i < len(d.EPxControl); i++ {
d.EPxControl[i].In.Set(0)
d.EPxControl[i].Out.Set(0)
d.EPxBufferControl[i].In.Set(0)
d.EPxBufferControl[i].Out.Set(0)
}
}
const (
// DPRAM : Endpoint control register
usbEpControlEnable = 0x80000000
usbEpControlDoubleBuffered = 0x40000000
usbEpControlInterruptPerBuff = 0x20000000
usbEpControlInterruptPerDoubleBuff = 0x10000000
usbEpControlEndpointType = 0x0c000000
usbEpControlInterruptOnStall = 0x00020000
usbEpControlInterruptOnNak = 0x00010000
usbEpControlBufferAddress = 0x0000ffff
usbEpControlEndpointTypeControl = 0x00000000
usbEpControlEndpointTypeISO = 0x04000000
usbEpControlEndpointTypeBulk = 0x08000000
usbEpControlEndpointTypeInterrupt = 0x0c000000
// Endpoint buffer control bits
usbBuf1CtrlFull = 0x80000000
usbBuf1CtrlLast = 0x40000000
usbBuf1CtrlData0Pid = 0x20000000
usbBuf1CtrlData1Pid = 0x00000000
usbBuf1CtrlSel = 0x10000000
usbBuf1CtrlStall = 0x08000000
usbBuf1CtrlAvail = 0x04000000
usbBuf1CtrlLenMask = 0x03FF0000
usbBuf0CtrlFull = 0x00008000
usbBuf0CtrlLast = 0x00004000
usbBuf0CtrlData0Pid = 0x00000000
usbBuf0CtrlData1Pid = 0x00002000
usbBuf0CtrlSel = 0x00001000
usbBuf0CtrlStall = 0x00000800
usbBuf0CtrlAvail = 0x00000400
usbBuf0CtrlLenMask = 0x000003FF
usbBufferLen = 64
)
+242
View File
@@ -0,0 +1,242 @@
//go:build rp2040 || rp2350
package machine
import (
"machine/usb"
"runtime/volatile"
"unsafe"
)
var (
sendOnEP0DATADONE struct {
offset int
data []byte
pid uint32
}
)
func initEndpoint(ep, config uint32) {
val := uint32(usbEpControlEnable) | uint32(usbEpControlInterruptPerBuff)
offset := ep*2*usbBufferLen + 0x100
val |= offset
switch config {
case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn:
val |= usbEpControlEndpointTypeInterrupt
_usbDPSRAM.EPxControl[ep].In.Set(val)
case usb.ENDPOINT_TYPE_BULK | usb.EndpointOut:
val |= usbEpControlEndpointTypeBulk
_usbDPSRAM.EPxControl[ep].Out.Set(val)
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut:
val |= usbEpControlEndpointTypeInterrupt
_usbDPSRAM.EPxControl[ep].Out.Set(val)
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
case usb.ENDPOINT_TYPE_BULK | usb.EndpointIn:
val |= usbEpControlEndpointTypeBulk
_usbDPSRAM.EPxControl[ep].In.Set(val)
case usb.ENDPOINT_TYPE_CONTROL:
val |= usbEpControlEndpointTypeControl
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBuf0CtrlData1Pid)
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
}
}
// SendUSBInPacket sends a packet for USB (interrupt in / bulk in).
func SendUSBInPacket(ep uint32, data []byte) bool {
sendUSBPacket(ep, data, 0)
return true
}
// Prevent file size increases: https://github.com/tinygo-org/tinygo/pull/998
//
//go:noinline
func sendUSBPacket(ep uint32, data []byte, maxsize uint16) {
count := len(data)
if 0 < int(maxsize) && int(maxsize) < count {
count = int(maxsize)
}
if ep == 0 {
if count > usb.EndpointPacketSize {
count = usb.EndpointPacketSize
sendOnEP0DATADONE.offset = count
sendOnEP0DATADONE.data = data
} else {
sendOnEP0DATADONE.offset = 0
}
epXdata0[ep] = true
}
sendViaEPIn(ep, data, count)
}
func ReceiveUSBControlPacket() ([cdcLineInfoSize]byte, error) {
var b [cdcLineInfoSize]byte
ep := 0
for !_usbDPSRAM.EPxBufferControl[ep].Out.HasBits(usbBuf0CtrlFull) {
// TODO: timeout
}
ctrl := _usbDPSRAM.EPxBufferControl[ep].Out.Get()
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
sz := ctrl & usbBuf0CtrlLenMask
copy(b[:], _usbDPSRAM.EPxBuffer[ep].Buffer0[:sz])
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlData1Pid)
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
return b, nil
}
func handleEndpointRx(ep uint32) []byte {
ctrl := _usbDPSRAM.EPxBufferControl[ep].Out.Get()
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
sz := ctrl & usbBuf0CtrlLenMask
return _usbDPSRAM.EPxBuffer[ep].Buffer0[:sz]
}
func handleEndpointRxComplete(ep uint32) {
epXdata0[ep] = !epXdata0[ep]
if epXdata0[ep] || ep == 0 {
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlData1Pid)
}
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
}
func SendZlp() {
sendUSBPacket(0, []byte{}, 0)
}
func sendViaEPIn(ep uint32, data []byte, count int) {
// Prepare buffer control register value
val := uint32(count) | usbBuf0CtrlAvail
// DATA0 or DATA1
epXdata0[ep&0x7F] = !epXdata0[ep&0x7F]
if !epXdata0[ep&0x7F] {
val |= usbBuf0CtrlData1Pid
}
// Mark as full
val |= usbBuf0CtrlFull
copy(_usbDPSRAM.EPxBuffer[ep&0x7F].Buffer0[:], data[:count])
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
}
func sendStallViaEPIn(ep uint32) {
// Prepare buffer control register value
if ep == 0 {
armEPZeroStall()
}
val := uint32(usbBuf0CtrlFull)
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
val |= uint32(usbBuf0CtrlStall)
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
}
type usbDPSRAM struct {
// Note that EPxControl[0] is not EP0Control but 8-byte setup data.
EPxControl [16]usbEndpointControlRegister
EPxBufferControl [16]usbBufferControlRegister
EPxBuffer [16]usbBuffer
}
type usbEndpointControlRegister struct {
In volatile.Register32
Out volatile.Register32
}
type usbBufferControlRegister struct {
In volatile.Register32
Out volatile.Register32
}
type usbBuffer struct {
Buffer0 [usbBufferLen]byte
Buffer1 [usbBufferLen]byte
}
var (
_usbDPSRAM = (*usbDPSRAM)(unsafe.Pointer(uintptr(0x50100000)))
epXdata0 [16]bool
setupBytes [8]byte
)
func (d *usbDPSRAM) setupBytes() []byte {
data := d.EPxControl[usb.CONTROL_ENDPOINT].In.Get()
setupBytes[0] = byte(data)
setupBytes[1] = byte(data >> 8)
setupBytes[2] = byte(data >> 16)
setupBytes[3] = byte(data >> 24)
data = d.EPxControl[usb.CONTROL_ENDPOINT].Out.Get()
setupBytes[4] = byte(data)
setupBytes[5] = byte(data >> 8)
setupBytes[6] = byte(data >> 16)
setupBytes[7] = byte(data >> 24)
return setupBytes[:]
}
func (d *usbDPSRAM) clear() {
for i := 0; i < len(d.EPxControl); i++ {
d.EPxControl[i].In.Set(0)
d.EPxControl[i].Out.Set(0)
d.EPxBufferControl[i].In.Set(0)
d.EPxBufferControl[i].Out.Set(0)
}
}
const (
// DPRAM : Endpoint control register
usbEpControlEnable = 0x80000000
usbEpControlDoubleBuffered = 0x40000000
usbEpControlInterruptPerBuff = 0x20000000
usbEpControlInterruptPerDoubleBuff = 0x10000000
usbEpControlEndpointType = 0x0c000000
usbEpControlInterruptOnStall = 0x00020000
usbEpControlInterruptOnNak = 0x00010000
usbEpControlBufferAddress = 0x0000ffff
usbEpControlEndpointTypeControl = 0x00000000
usbEpControlEndpointTypeISO = 0x04000000
usbEpControlEndpointTypeBulk = 0x08000000
usbEpControlEndpointTypeInterrupt = 0x0c000000
// Endpoint buffer control bits
usbBuf1CtrlFull = 0x80000000
usbBuf1CtrlLast = 0x40000000
usbBuf1CtrlData0Pid = 0x20000000
usbBuf1CtrlData1Pid = 0x00000000
usbBuf1CtrlSel = 0x10000000
usbBuf1CtrlStall = 0x08000000
usbBuf1CtrlAvail = 0x04000000
usbBuf1CtrlLenMask = 0x03FF0000
usbBuf0CtrlFull = 0x00008000
usbBuf0CtrlLast = 0x00004000
usbBuf0CtrlData0Pid = 0x00000000
usbBuf0CtrlData1Pid = 0x00002000
usbBuf0CtrlSel = 0x00001000
usbBuf0CtrlStall = 0x00000800
usbBuf0CtrlAvail = 0x00000400
usbBuf0CtrlLenMask = 0x000003FF
usbBufferLen = 64
)