mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-07 12:33:42 +00:00
8ef36ed939
Remove the sendUSBPacket maxLen param because this greatly confused the compiler. It also fixes a bug where the length provided to the hardware may not match the length of the packet. sendUSBPacket now panics if the sent packet is too big. I also fixed some of the string descriptor logic where we could create a packet without fully populating it. RP2* systems might require some more work since they are implemented very differently? I don't have any of those to test with yet, so maybe someone can deal with them in a seperate PR?
152 lines
3.9 KiB
Go
152 lines
3.9 KiB
Go
//go:build rp2350
|
|
|
|
package machine
|
|
|
|
import (
|
|
"device/rp"
|
|
"machine/usb"
|
|
"runtime/interrupt"
|
|
)
|
|
|
|
// Configure the USB peripheral. The config is here for compatibility with the UART interface.
|
|
func (dev *USBDevice) Configure(config UARTConfig) {
|
|
// Reset usb controller
|
|
resetBlock(rp.RESETS_RESET_USBCTRL)
|
|
unresetBlockWait(rp.RESETS_RESET_USBCTRL)
|
|
|
|
// Clear any previous state in dpram just in case
|
|
_usbDPSRAM.clear()
|
|
|
|
// Enable USB interrupt at processor
|
|
rp.USB.INTE.Set(0)
|
|
intr := interrupt.New(rp.IRQ_USBCTRL_IRQ, handleUSBIRQ)
|
|
intr.SetPriority(0x00)
|
|
intr.Enable()
|
|
irqSet(rp.IRQ_USBCTRL_IRQ, true)
|
|
|
|
// Mux the controller to the onboard usb phy
|
|
rp.USB.USB_MUXING.Set(rp.USB_USB_MUXING_TO_PHY | rp.USB_USB_MUXING_SOFTCON)
|
|
|
|
// Force VBUS detect so the device thinks it is plugged into a host
|
|
rp.USB.USB_PWR.Set(rp.USB_USB_PWR_VBUS_DETECT | rp.USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN)
|
|
|
|
// Enable the USB controller in device mode.
|
|
rp.USB.MAIN_CTRL.Set(rp.USB_MAIN_CTRL_CONTROLLER_EN)
|
|
|
|
// Enable an interrupt per EP0 transaction
|
|
rp.USB.SIE_CTRL.Set(rp.USB_SIE_CTRL_EP0_INT_1BUF)
|
|
|
|
// Enable interrupts for when a buffer is done, when the bus is reset,
|
|
// and when a setup packet is received
|
|
rp.USB.INTE.Set(rp.USB_INTE_BUFF_STATUS |
|
|
rp.USB_INTE_BUS_RESET |
|
|
rp.USB_INTE_SETUP_REQ)
|
|
|
|
// Present full speed device by enabling pull up on DP
|
|
rp.USB.SIE_CTRL.SetBits(rp.USB_SIE_CTRL_PULLUP_EN)
|
|
|
|
// 12.7.2 Disable phy isolation
|
|
rp.USB.SetMAIN_CTRL_PHY_ISO(0x0)
|
|
}
|
|
|
|
func handleUSBIRQ(intr interrupt.Interrupt) {
|
|
status := rp.USB.INTS.Get()
|
|
|
|
// Setup packet received
|
|
if (status & rp.USB_INTS_SETUP_REQ) > 0 {
|
|
rp.USB.SIE_STATUS.Set(rp.USB_SIE_STATUS_SETUP_REC)
|
|
setup := usb.NewSetup(_usbDPSRAM.setupBytes())
|
|
|
|
ok := false
|
|
if (setup.BmRequestType & usb.REQUEST_TYPE) == usb.REQUEST_STANDARD {
|
|
// Standard Requests
|
|
ok = handleStandardSetup(setup)
|
|
} else {
|
|
// Class Interface Requests
|
|
if setup.WIndex < uint16(len(usbSetupHandler)) && usbSetupHandler[setup.WIndex] != nil {
|
|
ok = usbSetupHandler[setup.WIndex](setup)
|
|
}
|
|
}
|
|
|
|
if !ok {
|
|
// Stall endpoint?
|
|
USBDev.SetStallEPIn(0)
|
|
}
|
|
|
|
}
|
|
|
|
// Buffer status, one or more buffers have completed
|
|
if (status & rp.USB_INTS_BUFF_STATUS) > 0 {
|
|
if sendOnEP0DATADONE.offset > 0 {
|
|
ep := uint32(0)
|
|
data := sendOnEP0DATADONE.data
|
|
count := len(data) - sendOnEP0DATADONE.offset
|
|
if ep == 0 && count > usb.EndpointPacketSize {
|
|
count = usb.EndpointPacketSize
|
|
}
|
|
|
|
sendViaEPIn(ep, data[sendOnEP0DATADONE.offset:], count)
|
|
sendOnEP0DATADONE.offset += count
|
|
if sendOnEP0DATADONE.offset == len(data) {
|
|
sendOnEP0DATADONE.offset = 0
|
|
}
|
|
}
|
|
|
|
s2 := rp.USB.BUFF_STATUS.Get()
|
|
|
|
// OUT (PC -> rp2350)
|
|
for i := 0; i < 16; i++ {
|
|
if s2&(1<<(i*2+1)) > 0 {
|
|
buf := handleEndpointRx(uint32(i))
|
|
if usbRxHandler[i] == nil || usbRxHandler[i](buf) {
|
|
AckUsbOutTransfer(uint32(i))
|
|
}
|
|
}
|
|
}
|
|
|
|
// IN (rp2350 -> PC)
|
|
for i := 0; i < 16; i++ {
|
|
if s2&(1<<(i*2)) > 0 {
|
|
if usbTxHandler[i] != nil {
|
|
usbTxHandler[i]()
|
|
}
|
|
}
|
|
}
|
|
|
|
rp.USB.BUFF_STATUS.Set(s2)
|
|
}
|
|
|
|
// Bus is reset
|
|
if (status & rp.USB_INTS_BUS_RESET) > 0 {
|
|
rp.USB.SIE_STATUS.Set(rp.USB_SIE_STATUS_BUS_RESET)
|
|
//fixRP2040UsbDeviceEnumeration()
|
|
|
|
rp.USB.ADDR_ENDP.Set(0)
|
|
initEndpoint(0, usb.ENDPOINT_TYPE_CONTROL)
|
|
}
|
|
}
|
|
|
|
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{})
|
|
|
|
// Wait for transfer to complete with a timeout.
|
|
t := timer.timeElapsed()
|
|
for (rp.USB.SIE_STATUS.Get() & rp.USB_SIE_STATUS_ACK_REC) == 0 {
|
|
if dt := timer.timeElapsed() - t; dt >= ackTimeout {
|
|
return false
|
|
}
|
|
}
|
|
|
|
// Set the device address to that requested by host.
|
|
rp.USB.ADDR_ENDP.Set(uint32(setup.WValueL) & rp.USB_ADDR_ENDP_ADDRESS_Msk)
|
|
return true
|
|
}
|
|
|
|
func armEPZeroStall() {
|
|
rp.USB.EP_STALL_ARM.Set(rp.USB_EP_STALL_ARM_EP0_IN)
|
|
}
|