github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/machine_rp2040_usb.go (about)

     1  //go:build rp2040
     2  
     3  package machine
     4  
     5  import (
     6  	"device/rp"
     7  	"machine/usb"
     8  	"runtime/interrupt"
     9  	"runtime/volatile"
    10  	"unsafe"
    11  )
    12  
    13  var (
    14  	sendOnEP0DATADONE struct {
    15  		offset int
    16  		data   []byte
    17  		pid    uint32
    18  	}
    19  )
    20  
    21  // Configure the USB peripheral. The config is here for compatibility with the UART interface.
    22  func (dev *USBDevice) Configure(config UARTConfig) {
    23  	// Reset usb controller
    24  	resetBlock(rp.RESETS_RESET_USBCTRL)
    25  	unresetBlockWait(rp.RESETS_RESET_USBCTRL)
    26  
    27  	// Clear any previous state in dpram just in case
    28  	usbDPSRAM.clear()
    29  
    30  	// Enable USB interrupt at processor
    31  	rp.USBCTRL_REGS.INTE.Set(0)
    32  	intr := interrupt.New(rp.IRQ_USBCTRL_IRQ, handleUSBIRQ)
    33  	intr.SetPriority(0x00)
    34  	intr.Enable()
    35  	irqSet(rp.IRQ_USBCTRL_IRQ, true)
    36  
    37  	// Mux the controller to the onboard usb phy
    38  	rp.USBCTRL_REGS.USB_MUXING.Set(rp.USBCTRL_REGS_USB_MUXING_TO_PHY | rp.USBCTRL_REGS_USB_MUXING_SOFTCON)
    39  
    40  	// Force VBUS detect so the device thinks it is plugged into a host
    41  	rp.USBCTRL_REGS.USB_PWR.Set(rp.USBCTRL_REGS_USB_PWR_VBUS_DETECT | rp.USBCTRL_REGS_USB_PWR_VBUS_DETECT_OVERRIDE_EN)
    42  
    43  	// Enable the USB controller in device mode.
    44  	rp.USBCTRL_REGS.MAIN_CTRL.Set(rp.USBCTRL_REGS_MAIN_CTRL_CONTROLLER_EN)
    45  
    46  	// Enable an interrupt per EP0 transaction
    47  	rp.USBCTRL_REGS.SIE_CTRL.Set(rp.USBCTRL_REGS_SIE_CTRL_EP0_INT_1BUF)
    48  
    49  	// Enable interrupts for when a buffer is done, when the bus is reset,
    50  	// and when a setup packet is received
    51  	rp.USBCTRL_REGS.INTE.Set(rp.USBCTRL_REGS_INTE_BUFF_STATUS |
    52  		rp.USBCTRL_REGS_INTE_BUS_RESET |
    53  		rp.USBCTRL_REGS_INTE_SETUP_REQ)
    54  
    55  	// Present full speed device by enabling pull up on DP
    56  	rp.USBCTRL_REGS.SIE_CTRL.SetBits(rp.USBCTRL_REGS_SIE_CTRL_PULLUP_EN)
    57  }
    58  
    59  func handleUSBIRQ(intr interrupt.Interrupt) {
    60  	status := rp.USBCTRL_REGS.INTS.Get()
    61  
    62  	// Setup packet received
    63  	if (status & rp.USBCTRL_REGS_INTS_SETUP_REQ) > 0 {
    64  		rp.USBCTRL_REGS.SIE_STATUS.Set(rp.USBCTRL_REGS_SIE_STATUS_SETUP_REC)
    65  		setup := usb.NewSetup(usbDPSRAM.setupBytes())
    66  
    67  		ok := false
    68  		if (setup.BmRequestType & usb.REQUEST_TYPE) == usb.REQUEST_STANDARD {
    69  			// Standard Requests
    70  			ok = handleStandardSetup(setup)
    71  		} else {
    72  			// Class Interface Requests
    73  			if setup.WIndex < uint16(len(usbSetupHandler)) && usbSetupHandler[setup.WIndex] != nil {
    74  				ok = usbSetupHandler[setup.WIndex](setup)
    75  			}
    76  		}
    77  
    78  		if !ok {
    79  			// Stall endpoint?
    80  			sendStallViaEPIn(0)
    81  		}
    82  
    83  	}
    84  
    85  	// Buffer status, one or more buffers have completed
    86  	if (status & rp.USBCTRL_REGS_INTS_BUFF_STATUS) > 0 {
    87  		if sendOnEP0DATADONE.offset > 0 {
    88  			ep := uint32(0)
    89  			data := sendOnEP0DATADONE.data
    90  			count := len(data) - sendOnEP0DATADONE.offset
    91  			if ep == 0 && count > usb.EndpointPacketSize {
    92  				count = usb.EndpointPacketSize
    93  			}
    94  
    95  			sendViaEPIn(ep, data[sendOnEP0DATADONE.offset:], count)
    96  			sendOnEP0DATADONE.offset += count
    97  			if sendOnEP0DATADONE.offset == len(data) {
    98  				sendOnEP0DATADONE.offset = 0
    99  			}
   100  		}
   101  
   102  		s2 := rp.USBCTRL_REGS.BUFF_STATUS.Get()
   103  
   104  		// OUT (PC -> rp2040)
   105  		for i := 0; i < 16; i++ {
   106  			if s2&(1<<(i*2+1)) > 0 {
   107  				buf := handleEndpointRx(uint32(i))
   108  				if usbRxHandler[i] != nil {
   109  					usbRxHandler[i](buf)
   110  				}
   111  				handleEndpointRxComplete(uint32(i))
   112  			}
   113  		}
   114  
   115  		// IN (rp2040 -> PC)
   116  		for i := 0; i < 16; i++ {
   117  			if s2&(1<<(i*2)) > 0 {
   118  				if usbTxHandler[i] != nil {
   119  					usbTxHandler[i]()
   120  				}
   121  			}
   122  		}
   123  
   124  		rp.USBCTRL_REGS.BUFF_STATUS.Set(s2)
   125  	}
   126  
   127  	// Bus is reset
   128  	if (status & rp.USBCTRL_REGS_INTS_BUS_RESET) > 0 {
   129  		rp.USBCTRL_REGS.SIE_STATUS.Set(rp.USBCTRL_REGS_SIE_STATUS_BUS_RESET)
   130  		fixRP2040UsbDeviceEnumeration()
   131  
   132  		rp.USBCTRL_REGS.ADDR_ENDP.Set(0)
   133  		initEndpoint(0, usb.ENDPOINT_TYPE_CONTROL)
   134  	}
   135  }
   136  
   137  func initEndpoint(ep, config uint32) {
   138  	val := uint32(usbEpControlEnable) | uint32(usbEpControlInterruptPerBuff)
   139  	offset := ep*2*USBBufferLen + 0x100
   140  	val |= offset
   141  
   142  	switch config {
   143  	case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn:
   144  		val |= usbEpControlEndpointTypeInterrupt
   145  		usbDPSRAM.EPxControl[ep].In.Set(val)
   146  
   147  	case usb.ENDPOINT_TYPE_BULK | usb.EndpointOut:
   148  		val |= usbEpControlEndpointTypeBulk
   149  		usbDPSRAM.EPxControl[ep].Out.Set(val)
   150  		usbDPSRAM.EPxBufferControl[ep].Out.Set(USBBufferLen & usbBuf0CtrlLenMask)
   151  		usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
   152  
   153  	case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut:
   154  		val |= usbEpControlEndpointTypeInterrupt
   155  		usbDPSRAM.EPxControl[ep].Out.Set(val)
   156  		usbDPSRAM.EPxBufferControl[ep].Out.Set(USBBufferLen & usbBuf0CtrlLenMask)
   157  		usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
   158  
   159  	case usb.ENDPOINT_TYPE_BULK | usb.EndpointIn:
   160  		val |= usbEpControlEndpointTypeBulk
   161  		usbDPSRAM.EPxControl[ep].In.Set(val)
   162  
   163  	case usb.ENDPOINT_TYPE_CONTROL:
   164  		val |= usbEpControlEndpointTypeControl
   165  		usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBuf0CtrlData1Pid)
   166  		usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
   167  
   168  	}
   169  }
   170  
   171  func handleUSBSetAddress(setup usb.Setup) bool {
   172  	sendUSBPacket(0, []byte{}, 0)
   173  
   174  	// last, set the device address to that requested by host
   175  	// wait for transfer to complete
   176  	timeout := 3000
   177  	rp.USBCTRL_REGS.SIE_STATUS.Set(rp.USBCTRL_REGS_SIE_STATUS_ACK_REC)
   178  	for (rp.USBCTRL_REGS.SIE_STATUS.Get() & rp.USBCTRL_REGS_SIE_STATUS_ACK_REC) == 0 {
   179  		timeout--
   180  		if timeout == 0 {
   181  			return true
   182  		}
   183  	}
   184  
   185  	rp.USBCTRL_REGS.ADDR_ENDP.Set(uint32(setup.WValueL) & rp.USBCTRL_REGS_ADDR_ENDP_ADDRESS_Msk)
   186  
   187  	return true
   188  }
   189  
   190  // SendUSBInPacket sends a packet for USB (interrupt in / bulk in).
   191  func SendUSBInPacket(ep uint32, data []byte) bool {
   192  	sendUSBPacket(ep, data, 0)
   193  	return true
   194  }
   195  
   196  //go:noinline
   197  func sendUSBPacket(ep uint32, data []byte, maxsize uint16) {
   198  	count := len(data)
   199  	if 0 < int(maxsize) && int(maxsize) < count {
   200  		count = int(maxsize)
   201  	}
   202  
   203  	if ep == 0 {
   204  		if count > usb.EndpointPacketSize {
   205  			count = usb.EndpointPacketSize
   206  
   207  			sendOnEP0DATADONE.offset = count
   208  			sendOnEP0DATADONE.data = data
   209  		} else {
   210  			sendOnEP0DATADONE.offset = 0
   211  		}
   212  		epXdata0[ep] = true
   213  	}
   214  
   215  	sendViaEPIn(ep, data, count)
   216  }
   217  
   218  func ReceiveUSBControlPacket() ([cdcLineInfoSize]byte, error) {
   219  	var b [cdcLineInfoSize]byte
   220  	ep := 0
   221  
   222  	for !usbDPSRAM.EPxBufferControl[ep].Out.HasBits(usbBuf0CtrlFull) {
   223  		// TODO: timeout
   224  	}
   225  
   226  	ctrl := usbDPSRAM.EPxBufferControl[ep].Out.Get()
   227  	usbDPSRAM.EPxBufferControl[ep].Out.Set(USBBufferLen & usbBuf0CtrlLenMask)
   228  	sz := ctrl & usbBuf0CtrlLenMask
   229  
   230  	copy(b[:], usbDPSRAM.EPxBuffer[ep].Buffer0[:sz])
   231  
   232  	usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlData1Pid)
   233  	usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
   234  
   235  	return b, nil
   236  }
   237  
   238  func handleEndpointRx(ep uint32) []byte {
   239  	ctrl := usbDPSRAM.EPxBufferControl[ep].Out.Get()
   240  	usbDPSRAM.EPxBufferControl[ep].Out.Set(USBBufferLen & usbBuf0CtrlLenMask)
   241  	sz := ctrl & usbBuf0CtrlLenMask
   242  
   243  	return usbDPSRAM.EPxBuffer[ep].Buffer0[:sz]
   244  }
   245  
   246  func handleEndpointRxComplete(ep uint32) {
   247  	epXdata0[ep] = !epXdata0[ep]
   248  	if epXdata0[ep] || ep == 0 {
   249  		usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlData1Pid)
   250  	}
   251  
   252  	usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
   253  }
   254  
   255  func SendZlp() {
   256  	sendUSBPacket(0, []byte{}, 0)
   257  }
   258  
   259  func sendViaEPIn(ep uint32, data []byte, count int) {
   260  	// Prepare buffer control register value
   261  	val := uint32(count) | usbBuf0CtrlAvail
   262  
   263  	// DATA0 or DATA1
   264  	epXdata0[ep&0x7F] = !epXdata0[ep&0x7F]
   265  	if !epXdata0[ep&0x7F] {
   266  		val |= usbBuf0CtrlData1Pid
   267  	}
   268  
   269  	// Mark as full
   270  	val |= usbBuf0CtrlFull
   271  
   272  	copy(usbDPSRAM.EPxBuffer[ep&0x7F].Buffer0[:], data[:count])
   273  	usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
   274  }
   275  
   276  func sendStallViaEPIn(ep uint32) {
   277  	// Prepare buffer control register value
   278  	if ep == 0 {
   279  		rp.USBCTRL_REGS.EP_STALL_ARM.Set(rp.USBCTRL_REGS_EP_STALL_ARM_EP0_IN)
   280  	}
   281  	val := uint32(usbBuf0CtrlFull)
   282  	usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
   283  	val |= uint32(usbBuf0CtrlStall)
   284  	usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
   285  }
   286  
   287  type USBDPSRAM struct {
   288  	// Note that EPxControl[0] is not EP0Control but 8-byte setup data.
   289  	EPxControl [16]USBEndpointControlRegister
   290  
   291  	EPxBufferControl [16]USBBufferControlRegister
   292  
   293  	EPxBuffer [16]USBBuffer
   294  }
   295  
   296  type USBEndpointControlRegister struct {
   297  	In  volatile.Register32
   298  	Out volatile.Register32
   299  }
   300  type USBBufferControlRegister struct {
   301  	In  volatile.Register32
   302  	Out volatile.Register32
   303  }
   304  
   305  type USBBuffer struct {
   306  	Buffer0 [USBBufferLen]byte
   307  	Buffer1 [USBBufferLen]byte
   308  }
   309  
   310  var (
   311  	usbDPSRAM  = (*USBDPSRAM)(unsafe.Pointer(uintptr(0x50100000)))
   312  	epXdata0   [16]bool
   313  	setupBytes [8]byte
   314  )
   315  
   316  func (d *USBDPSRAM) setupBytes() []byte {
   317  
   318  	data := d.EPxControl[usb.CONTROL_ENDPOINT].In.Get()
   319  	setupBytes[0] = byte(data)
   320  	setupBytes[1] = byte(data >> 8)
   321  	setupBytes[2] = byte(data >> 16)
   322  	setupBytes[3] = byte(data >> 24)
   323  
   324  	data = d.EPxControl[usb.CONTROL_ENDPOINT].Out.Get()
   325  	setupBytes[4] = byte(data)
   326  	setupBytes[5] = byte(data >> 8)
   327  	setupBytes[6] = byte(data >> 16)
   328  	setupBytes[7] = byte(data >> 24)
   329  
   330  	return setupBytes[:]
   331  }
   332  
   333  func (d *USBDPSRAM) clear() {
   334  	for i := 0; i < len(d.EPxControl); i++ {
   335  		d.EPxControl[i].In.Set(0)
   336  		d.EPxControl[i].Out.Set(0)
   337  		d.EPxBufferControl[i].In.Set(0)
   338  		d.EPxBufferControl[i].Out.Set(0)
   339  	}
   340  }
   341  
   342  const (
   343  	// DPRAM : Endpoint control register
   344  	usbEpControlEnable                 = 0x80000000
   345  	usbEpControlDoubleBuffered         = 0x40000000
   346  	usbEpControlInterruptPerBuff       = 0x20000000
   347  	usbEpControlInterruptPerDoubleBuff = 0x10000000
   348  	usbEpControlEndpointType           = 0x0c000000
   349  	usbEpControlInterruptOnStall       = 0x00020000
   350  	usbEpControlInterruptOnNak         = 0x00010000
   351  	usbEpControlBufferAddress          = 0x0000ffff
   352  
   353  	usbEpControlEndpointTypeControl   = 0x00000000
   354  	usbEpControlEndpointTypeISO       = 0x04000000
   355  	usbEpControlEndpointTypeBulk      = 0x08000000
   356  	usbEpControlEndpointTypeInterrupt = 0x0c000000
   357  
   358  	// Endpoint buffer control bits
   359  	usbBuf1CtrlFull     = 0x80000000
   360  	usbBuf1CtrlLast     = 0x40000000
   361  	usbBuf1CtrlData0Pid = 0x20000000
   362  	usbBuf1CtrlData1Pid = 0x00000000
   363  	usbBuf1CtrlSel      = 0x10000000
   364  	usbBuf1CtrlStall    = 0x08000000
   365  	usbBuf1CtrlAvail    = 0x04000000
   366  	usbBuf1CtrlLenMask  = 0x03FF0000
   367  	usbBuf0CtrlFull     = 0x00008000
   368  	usbBuf0CtrlLast     = 0x00004000
   369  	usbBuf0CtrlData0Pid = 0x00000000
   370  	usbBuf0CtrlData1Pid = 0x00002000
   371  	usbBuf0CtrlSel      = 0x00001000
   372  	usbBuf0CtrlStall    = 0x00000800
   373  	usbBuf0CtrlAvail    = 0x00000400
   374  	usbBuf0CtrlLenMask  = 0x000003FF
   375  
   376  	USBBufferLen = 64
   377  )