github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/machine_nrf52840_usb.go (about) 1 //go:build nrf52840 2 3 package machine 4 5 import ( 6 "device/arm" 7 "device/nrf" 8 "machine/usb" 9 "runtime/interrupt" 10 "runtime/volatile" 11 "unsafe" 12 ) 13 14 var ( 15 sendOnEP0DATADONE struct { 16 ptr *byte 17 count int 18 offset int 19 } 20 epinen uint32 21 epouten uint32 22 easyDMABusy volatile.Register8 23 ) 24 25 // enterCriticalSection is used to protect access to easyDMA - only one thing 26 // can be done with it at a time 27 func enterCriticalSection() { 28 waitForEasyDMA() 29 easyDMABusy.SetBits(1) 30 } 31 32 func waitForEasyDMA() { 33 for easyDMABusy.HasBits(1) { 34 arm.Asm("wfi") 35 } 36 } 37 38 func exitCriticalSection() { 39 easyDMABusy.ClearBits(1) 40 } 41 42 // Configure the USB peripheral. The config is here for compatibility with the UART interface. 43 func (dev *USBDevice) Configure(config UARTConfig) { 44 if dev.initcomplete { 45 return 46 } 47 48 state := interrupt.Disable() 49 defer interrupt.Restore(state) 50 51 nrf.USBD.USBPULLUP.Set(0) 52 53 // Enable IRQ. Make sure this is higher than the SWI2 interrupt handler so 54 // that it is possible to print to the console from a BLE interrupt. You 55 // shouldn't generally do that but it is useful for debugging and panic 56 // logging. 57 intr := interrupt.New(nrf.IRQ_USBD, handleUSBIRQ) 58 intr.SetPriority(0x40) // interrupt priority 2 (lower number means more important) 59 intr.Enable() 60 61 // enable interrupt for end of reset and start of frame 62 nrf.USBD.INTEN.Set(nrf.USBD_INTENSET_USBEVENT) 63 64 // errata 187 65 // https://infocenter.nordicsemi.com/topic/errata_nRF52840_EngB/ERR/nRF52840/EngineeringB/latest/anomaly_840_187.html 66 (*volatile.Register32)(unsafe.Pointer(uintptr(0x4006EC00))).Set(0x00009375) 67 (*volatile.Register32)(unsafe.Pointer(uintptr(0x4006ED14))).Set(0x00000003) 68 (*volatile.Register32)(unsafe.Pointer(uintptr(0x4006EC00))).Set(0x00009375) 69 70 // enable USB 71 nrf.USBD.ENABLE.Set(1) 72 73 timeout := 300000 74 for !nrf.USBD.EVENTCAUSE.HasBits(nrf.USBD_EVENTCAUSE_READY) { 75 timeout-- 76 if timeout == 0 { 77 return 78 } 79 } 80 nrf.USBD.EVENTCAUSE.ClearBits(nrf.USBD_EVENTCAUSE_READY) 81 82 // errata 187 83 (*volatile.Register32)(unsafe.Pointer(uintptr(0x4006EC00))).Set(0x00009375) 84 (*volatile.Register32)(unsafe.Pointer(uintptr(0x4006ED14))).Set(0x00000000) 85 (*volatile.Register32)(unsafe.Pointer(uintptr(0x4006EC00))).Set(0x00009375) 86 87 dev.initcomplete = true 88 } 89 90 func handleUSBIRQ(interrupt.Interrupt) { 91 if nrf.USBD.EVENTS_SOF.Get() == 1 { 92 nrf.USBD.EVENTS_SOF.Set(0) 93 94 // if you want to blink LED showing traffic, this would be the place... 95 } 96 97 // USBD ready event 98 if nrf.USBD.EVENTS_USBEVENT.Get() == 1 { 99 nrf.USBD.EVENTS_USBEVENT.Set(0) 100 if (nrf.USBD.EVENTCAUSE.Get() & nrf.USBD_EVENTCAUSE_READY) > 0 { 101 102 // Configure control endpoint 103 initEndpoint(0, usb.ENDPOINT_TYPE_CONTROL) 104 nrf.USBD.USBPULLUP.Set(1) 105 106 usbConfiguration = 0 107 } 108 nrf.USBD.EVENTCAUSE.Set(0) 109 } 110 111 if nrf.USBD.EVENTS_EP0DATADONE.Get() == 1 { 112 // done sending packet - either need to send another or enter status stage 113 nrf.USBD.EVENTS_EP0DATADONE.Set(0) 114 if sendOnEP0DATADONE.ptr != nil { 115 // previous data was too big for one packet, so send a second 116 ptr := sendOnEP0DATADONE.ptr 117 count := sendOnEP0DATADONE.count 118 if count > usb.EndpointPacketSize { 119 sendOnEP0DATADONE.offset += usb.EndpointPacketSize 120 sendOnEP0DATADONE.ptr = &udd_ep_control_cache_buffer[sendOnEP0DATADONE.offset] 121 count = usb.EndpointPacketSize 122 } 123 sendOnEP0DATADONE.count -= count 124 sendViaEPIn( 125 0, 126 ptr, 127 count, 128 ) 129 130 // clear, so we know we're done 131 if sendOnEP0DATADONE.count == 0 { 132 sendOnEP0DATADONE.ptr = nil 133 sendOnEP0DATADONE.offset = 0 134 } 135 } else { 136 // no more data, so set status stage 137 SendZlp() // nrf.USBD.TASKS_EP0STATUS.Set(1) 138 } 139 return 140 } 141 142 // Endpoint 0 Setup interrupt 143 if nrf.USBD.EVENTS_EP0SETUP.Get() == 1 { 144 // ack setup received 145 nrf.USBD.EVENTS_EP0SETUP.Set(0) 146 147 // parse setup 148 setup := parseUSBSetupRegisters() 149 150 ok := false 151 if (setup.BmRequestType & usb.REQUEST_TYPE) == usb.REQUEST_STANDARD { 152 // Standard Requests 153 ok = handleStandardSetup(setup) 154 } else { 155 // Class Interface Requests 156 if setup.WIndex < uint16(len(usbSetupHandler)) && usbSetupHandler[setup.WIndex] != nil { 157 ok = usbSetupHandler[setup.WIndex](setup) 158 } 159 } 160 161 if !ok { 162 // Stall endpoint 163 nrf.USBD.TASKS_EP0STALL.Set(1) 164 } 165 } 166 167 // Now the actual transfer handlers, ignore endpoint number 0 (setup) 168 if nrf.USBD.EVENTS_EPDATA.Get() > 0 { 169 nrf.USBD.EVENTS_EPDATA.Set(0) 170 epDataStatus := nrf.USBD.EPDATASTATUS.Get() 171 nrf.USBD.EPDATASTATUS.Set(epDataStatus) 172 var i uint32 173 for i = 1; i < uint32(len(endPoints)); i++ { 174 // Check if endpoint has a pending interrupt 175 inDataDone := epDataStatus&(nrf.USBD_EPDATASTATUS_EPIN1<<(i-1)) > 0 176 outDataDone := epDataStatus&(nrf.USBD_EPDATASTATUS_EPOUT1<<(i-1)) > 0 177 if inDataDone { 178 if usbTxHandler[i] != nil { 179 usbTxHandler[i]() 180 } 181 } else if outDataDone { 182 enterCriticalSection() 183 nrf.USBD.EPOUT[i].PTR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[i])))) 184 count := nrf.USBD.SIZE.EPOUT[i].Get() 185 nrf.USBD.EPOUT[i].MAXCNT.Set(count) 186 nrf.USBD.TASKS_STARTEPOUT[i].Set(1) 187 } 188 } 189 } 190 191 // ENDEPOUT[n] events 192 for i := 0; i < len(endPoints); i++ { 193 if nrf.USBD.EVENTS_ENDEPOUT[i].Get() > 0 { 194 nrf.USBD.EVENTS_ENDEPOUT[i].Set(0) 195 buf := handleEndpointRx(uint32(i)) 196 if usbRxHandler[i] != nil { 197 usbRxHandler[i](buf) 198 } 199 handleEndpointRxComplete(uint32(i)) 200 exitCriticalSection() 201 } 202 } 203 } 204 205 func parseUSBSetupRegisters() usb.Setup { 206 return usb.Setup{ 207 BmRequestType: uint8(nrf.USBD.BMREQUESTTYPE.Get()), 208 BRequest: uint8(nrf.USBD.BREQUEST.Get()), 209 WValueL: uint8(nrf.USBD.WVALUEL.Get()), 210 WValueH: uint8(nrf.USBD.WVALUEH.Get()), 211 WIndex: uint16((nrf.USBD.WINDEXH.Get() << 8) | nrf.USBD.WINDEXL.Get()), 212 WLength: uint16(((nrf.USBD.WLENGTHH.Get() & 0xff) << 8) | (nrf.USBD.WLENGTHL.Get() & 0xff)), 213 } 214 } 215 216 func initEndpoint(ep, config uint32) { 217 switch config { 218 case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn: 219 enableEPIn(ep) 220 221 case usb.ENDPOINT_TYPE_BULK | usb.EndpointOut: 222 nrf.USBD.INTENSET.Set(nrf.USBD_INTENSET_ENDEPOUT0 << ep) 223 nrf.USBD.SIZE.EPOUT[ep].Set(0) 224 enableEPOut(ep) 225 226 case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut: 227 nrf.USBD.INTENSET.Set(nrf.USBD_INTENSET_ENDEPOUT0 << ep) 228 nrf.USBD.SIZE.EPOUT[ep].Set(0) 229 enableEPOut(ep) 230 231 case usb.ENDPOINT_TYPE_BULK | usb.EndpointIn: 232 enableEPIn(ep) 233 234 case usb.ENDPOINT_TYPE_CONTROL: 235 enableEPIn(0) 236 enableEPOut(0) 237 nrf.USBD.INTENSET.Set(nrf.USBD_INTENSET_ENDEPOUT0 | 238 nrf.USBD_INTENSET_EP0SETUP | 239 nrf.USBD_INTENSET_EPDATA | 240 nrf.USBD_INTENSET_EP0DATADONE) 241 SendZlp() // nrf.USBD.TASKS_EP0STATUS.Set(1) 242 } 243 } 244 245 // SendUSBInPacket sends a packet for USBHID (interrupt in / bulk in). 246 func SendUSBInPacket(ep uint32, data []byte) bool { 247 sendUSBPacket(ep, data, 0) 248 249 // clear transfer complete flag 250 nrf.USBD.INTENCLR.Set(nrf.USBD_INTENCLR_ENDEPOUT0 << 4) 251 252 return true 253 } 254 255 //go:noinline 256 func sendUSBPacket(ep uint32, data []byte, maxsize uint16) { 257 count := len(data) 258 if 0 < int(maxsize) && int(maxsize) < count { 259 count = int(maxsize) 260 } 261 262 if ep == 0 { 263 copy(udd_ep_control_cache_buffer[:], data[:count]) 264 if count > usb.EndpointPacketSize { 265 sendOnEP0DATADONE.offset = usb.EndpointPacketSize 266 sendOnEP0DATADONE.ptr = &udd_ep_control_cache_buffer[sendOnEP0DATADONE.offset] 267 sendOnEP0DATADONE.count = count - usb.EndpointPacketSize 268 count = usb.EndpointPacketSize 269 } 270 sendViaEPIn( 271 ep, 272 &udd_ep_control_cache_buffer[0], 273 count, 274 ) 275 } else { 276 copy(udd_ep_in_cache_buffer[ep][:], data[:count]) 277 sendViaEPIn( 278 ep, 279 &udd_ep_in_cache_buffer[ep][0], 280 count, 281 ) 282 } 283 } 284 285 func handleEndpointRx(ep uint32) []byte { 286 // get data 287 count := int(nrf.USBD.EPOUT[ep].AMOUNT.Get()) 288 289 return udd_ep_out_cache_buffer[ep][:count] 290 } 291 292 func handleEndpointRxComplete(ep uint32) { 293 // set ready for next data 294 nrf.USBD.SIZE.EPOUT[ep].Set(0) 295 } 296 297 func SendZlp() { 298 nrf.USBD.TASKS_EP0STATUS.Set(1) 299 } 300 301 func sendViaEPIn(ep uint32, ptr *byte, count int) { 302 nrf.USBD.EPIN[ep].PTR.Set( 303 uint32(uintptr(unsafe.Pointer(ptr))), 304 ) 305 nrf.USBD.EPIN[ep].MAXCNT.Set(uint32(count)) 306 nrf.USBD.TASKS_STARTEPIN[ep].Set(1) 307 } 308 309 func enableEPOut(ep uint32) { 310 epouten = epouten | (nrf.USBD_EPOUTEN_OUT0 << ep) 311 nrf.USBD.EPOUTEN.Set(epouten) 312 } 313 314 func enableEPIn(ep uint32) { 315 epinen = epinen | (nrf.USBD_EPINEN_IN0 << ep) 316 nrf.USBD.EPINEN.Set(epinen) 317 } 318 319 func handleUSBSetAddress(setup usb.Setup) bool { 320 // nrf USBD handles this 321 return true 322 } 323 324 func ReceiveUSBControlPacket() ([cdcLineInfoSize]byte, error) { 325 var b [cdcLineInfoSize]byte 326 327 nrf.USBD.TASKS_EP0RCVOUT.Set(1) 328 329 nrf.USBD.EPOUT[0].PTR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[0])))) 330 nrf.USBD.EPOUT[0].MAXCNT.Set(64) 331 332 timeout := 300000 333 count := 0 334 for { 335 if nrf.USBD.EVENTS_EP0DATADONE.Get() == 1 { 336 nrf.USBD.EVENTS_EP0DATADONE.Set(0) 337 count = int(nrf.USBD.SIZE.EPOUT[0].Get()) 338 nrf.USBD.TASKS_STARTEPOUT[0].Set(1) 339 break 340 } 341 timeout-- 342 if timeout == 0 { 343 return b, ErrUSBReadTimeout 344 } 345 } 346 347 timeout = 300000 348 for { 349 if nrf.USBD.EVENTS_ENDEPOUT[0].Get() == 1 { 350 nrf.USBD.EVENTS_ENDEPOUT[0].Set(0) 351 break 352 } 353 354 timeout-- 355 if timeout == 0 { 356 return b, ErrUSBReadTimeout 357 } 358 } 359 360 nrf.USBD.TASKS_EP0STATUS.Set(1) 361 nrf.USBD.TASKS_EP0RCVOUT.Set(0) 362 363 copy(b[:7], udd_ep_out_cache_buffer[0][:count]) 364 365 return b, nil 366 }