Skip to content

Commit efbff51

Browse files
committed
remove unicode/utf16 pkg, properly reset EPDATASTATUS register
Previously it was attempting to reset the register by setting it to zero, but the manual says to reset bits you need to set them to 1. Once this was changed, the device began properly acknowledging when it received data from the host on the out endpoint.
1 parent 37cb786 commit efbff51

File tree

2 files changed

+70
-48
lines changed

2 files changed

+70
-48
lines changed

src/machine/usb.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,23 @@ type cdcLineInfo struct {
376376
lineState uint8
377377
}
378378

379+
// strToUTF16LEDescriptor converts a utf8 string into a string descriptor
380+
// note: the following code only converts ascii characters to UTF16LE. In order
381+
// to do a "proper" conversion, we would need to pull in the 'unicode/utf16'
382+
// package, which at the time this was written added 512 bytes to the compiled
383+
// binary.
384+
func strToUTF16LEDescriptor(in string) []byte {
385+
size := (len(in) << 1) + 2
386+
out := make([]byte, size)
387+
out[0] = byte(size)
388+
out[1] = 0x03
389+
for i, rune := range in {
390+
out[(i<<1)+2] = byte(rune)
391+
out[(i<<1)+3] = 0
392+
}
393+
return out
394+
}
395+
379396
var (
380397
// TODO: allow setting these
381398
usb_STRING_LANGUAGE = [2]uint16{(3 << 8) | (2 + 2), 0x0409} // English

src/machine/usb_nrf52840.go

Lines changed: 53 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"device/nrf"
88
"runtime/interrupt"
99
"runtime/volatile"
10-
"unicode/utf16"
1110
"unsafe"
1211
)
1312

@@ -21,17 +20,13 @@ type USBCDC struct {
2120
func (usbcdc USBCDC) WriteByte(c byte) error {
2221
// Supposedly to handle problem with Windows USB serial ports?
2322
if usbLineInfo.lineState > 0 {
24-
cdcInBusy.Set(1)
23+
enterCriticalSection()
2524
udd_ep_in_cache_buffer[usb_CDC_ENDPOINT_IN][0] = c
2625
sendViaEPIn(
2726
usb_CDC_ENDPOINT_IN,
2827
&udd_ep_in_cache_buffer[usb_CDC_ENDPOINT_IN][0],
2928
1,
3029
)
31-
32-
for cdcInBusy.Get() == 1 {
33-
arm.Asm("wfi")
34-
}
3530
}
3631

3732
return nil
@@ -46,7 +41,8 @@ func (usbcdc USBCDC) RTS() bool {
4641
}
4742

4843
var (
49-
USB = USBCDC{Buffer: NewRingBuffer()}
44+
USB = USBCDC{Buffer: NewRingBuffer()}
45+
5046
usbEndpointDescriptors [8]usbDeviceDescriptor
5147

5248
udd_ep_in_cache_buffer [7][128]uint8
@@ -68,9 +64,26 @@ var (
6864
usbLineInfo = cdcLineInfo{115200, 0x00, 0x00, 0x08, 0x00}
6965
epinen uint32
7066
epouten uint32
71-
cdcInBusy volatile.Register8
67+
easyDMABusy volatile.Register8
7268
)
7369

70+
// enterCriticalSection is used to protect access to easyDMA - only one thing
71+
// can be done with it at a time
72+
func enterCriticalSection() {
73+
waitForEasyDMA()
74+
easyDMABusy.SetBits(1)
75+
}
76+
77+
func waitForEasyDMA() {
78+
for easyDMABusy.HasBits(1) {
79+
arm.Asm("wfi")
80+
}
81+
}
82+
83+
func exitCriticalSection() {
84+
easyDMABusy.ClearBits(1)
85+
}
86+
7487
// Configure the USB CDC interface. The config is here for compatibility with the UART interface.
7588
func (usbcdc *USBCDC) Configure(config UARTConfig) {
7689
// enable IRQ
@@ -83,7 +96,7 @@ func (usbcdc *USBCDC) Configure(config UARTConfig) {
8396

8497
// enable interrupt for end of reset and start of frame
8598
nrf.USBD.INTENSET.Set(
86-
nrf.USBD_INTENSET_SOF |
99+
nrf.USBD_INTENSET_EPDATA |
87100
nrf.USBD_INTENSET_EP0DATADONE |
88101
nrf.USBD_INTENSET_USBEVENT |
89102
nrf.USBD_INTENSET_EP0SETUP,
@@ -110,12 +123,6 @@ func (usbcdc *USBCDC) handleInterrupt(interrupt.Interrupt) {
110123
nrf.USBD.EVENTCAUSE.Set(0)
111124
}
112125

113-
// Start of frame
114-
if nrf.USBD.EVENTS_SOF.Get() == 1 {
115-
nrf.USBD.EVENTS_SOF.Set(0)
116-
// if you want to blink LED showing traffic, this would be the place...
117-
}
118-
119126
if nrf.USBD.EVENTS_EP0DATADONE.Get() == 1 {
120127
// done sending packet - either need to send another or enter status stage
121128
nrf.USBD.EVENTS_EP0DATADONE.Set(0)
@@ -164,29 +171,40 @@ func (usbcdc *USBCDC) handleInterrupt(interrupt.Interrupt) {
164171
if nrf.USBD.EVENTS_EPDATA.Get() > 0 {
165172
nrf.USBD.EVENTS_EPDATA.Set(0)
166173
epDataStatus := nrf.USBD.EPDATASTATUS.Get()
167-
nrf.USBD.EPDATASTATUS.Set(0)
174+
nrf.USBD.EPDATASTATUS.Set(epDataStatus)
168175
var i uint32
169176
for i = 1; i < uint32(len(endPoints)); i++ {
170177
// Check if endpoint has a pending interrupt
171-
inDataDone := epDataStatus&(1<<i) > 0
172-
outDataDone := epDataStatus&(0x10000<<i) > 0
178+
inDataDone := epDataStatus&(nrf.USBD_EPDATASTATUS_EPIN1<<(i-1)) > 0
179+
outDataDone := epDataStatus&(nrf.USBD_EPDATASTATUS_EPOUT1<<(i-1)) > 0
173180
if inDataDone || outDataDone {
174181
switch i {
175182
case usb_CDC_ENDPOINT_OUT:
176-
nrf.USBD.EPOUT[i].PTR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[i]))))
177-
nrf.USBD.EPOUT[i].MAXCNT.Set(64)
178-
nrf.USBD.TASKS_STARTEPOUT[i].Set(1)
179-
case usb_CDC_ENDPOINT_IN, usb_CDC_ENDPOINT_ACM:
180-
cdcInBusy.Set(0)
183+
// setup buffer to receive from host
184+
if outDataDone {
185+
enterCriticalSection()
186+
nrf.USBD.EPOUT[i].PTR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[i]))))
187+
count := nrf.USBD.SIZE.EPOUT[i].Get()
188+
nrf.USBD.EPOUT[i].MAXCNT.Set(count)
189+
nrf.USBD.TASKS_STARTEPOUT[i].Set(1)
190+
}
191+
case usb_CDC_ENDPOINT_IN: //, usb_CDC_ENDPOINT_ACM:
192+
if inDataDone {
193+
exitCriticalSection()
194+
}
181195
}
182196
}
183197
}
184198
}
185199

200+
// ENDEPOUT[n] events
186201
for i := 0; i < len(endPoints); i++ {
187202
if nrf.USBD.EVENTS_ENDEPOUT[i].Get() > 0 {
188203
nrf.USBD.EVENTS_ENDEPOUT[i].Set(0)
189-
handleEndpoint(uint32(i))
204+
if i == usb_CDC_ENDPOINT_OUT {
205+
handleEndpoint(uint32(i))
206+
}
207+
exitCriticalSection()
190208
}
191209
}
192210
}
@@ -208,7 +226,6 @@ func initEndpoint(ep, config uint32) {
208226
enableEPIn(ep)
209227

210228
case usb_ENDPOINT_TYPE_BULK | usbEndpointOut:
211-
nrf.USBD.INTENSET.Set(nrf.USBD_INTENSET_EPDATA)
212229
nrf.USBD.INTENSET.Set(nrf.USBD_INTENSET_ENDEPOUT0 << ep)
213230
nrf.USBD.SIZE.EPOUT[ep].Set(0)
214231
enableEPOut(ep)
@@ -219,7 +236,6 @@ func initEndpoint(ep, config uint32) {
219236
enableEPOut(ep)
220237

221238
case usb_ENDPOINT_TYPE_BULK | usbEndpointIn:
222-
nrf.USBD.INTENSET.Set(nrf.USBD_INTENSET_EPDATA)
223239
enableEPIn(ep)
224240

225241
case usb_ENDPOINT_TYPE_CONTROL:
@@ -238,7 +254,6 @@ func handleStandardSetup(setup usbSetup) bool {
238254
buf := []byte{0, 0}
239255

240256
if setup.bmRequestType != 0 { // endpoint
241-
// TODO: actually check if the endpoint in question is currently halted
242257
if isEndpointHalt {
243258
buf[0] = 1
244259
}
@@ -354,9 +369,6 @@ func cdcSetup(setup usbSetup) bool {
354369
}
355370

356371
if setup.bRequest == usb_CDC_SEND_BREAK {
357-
// TODO: something with this value?
358-
// breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL;
359-
// return false;
360372
nrf.USBD.TASKS_EP0STATUS.Set(1)
361373
}
362374
return true
@@ -431,11 +443,19 @@ func sendDescriptor(setup usbSetup) {
431443

432444
case usb_IPRODUCT:
433445
b := strToUTF16LEDescriptor(usb_STRING_PRODUCT)
434-
sendUSBPacket(0, b[:setup.wLength])
446+
if setup.wLength == 2 {
447+
sendUSBPacket(0, b[:2])
448+
} else {
449+
sendUSBPacket(0, b)
450+
}
435451

436452
case usb_IMANUFACTURER:
437453
b := strToUTF16LEDescriptor(usb_STRING_MANUFACTURER)
438-
sendUSBPacket(0, b[:setup.wLength])
454+
if setup.wLength == 2 {
455+
sendUSBPacket(0, b[:2])
456+
} else {
457+
sendUSBPacket(0, b)
458+
}
439459

440460
case usb_ISERIAL:
441461
// TODO: allow returning a product serial number
@@ -500,7 +520,7 @@ func sendConfiguration(setup usbSetup) {
500520

501521
func handleEndpoint(ep uint32) {
502522
// get data
503-
count := int(nrf.USBD.SIZE.EPOUT[ep].Get())
523+
count := int(nrf.USBD.EPOUT[ep].AMOUNT.Get())
504524

505525
// move to ring buffer
506526
for i := 0; i < count; i++ {
@@ -516,7 +536,6 @@ func sendViaEPIn(ep uint32, ptr *byte, count int) {
516536
uint32(uintptr(unsafe.Pointer(ptr))),
517537
)
518538
nrf.USBD.EPIN[ep].MAXCNT.Set(uint32(count))
519-
nrf.USBD.EVENTS_ENDEPIN[ep].Set(0)
520539
nrf.USBD.TASKS_STARTEPIN[ep].Set(1)
521540
}
522541

@@ -529,17 +548,3 @@ func enableEPIn(ep uint32) {
529548
epinen = epinen | (nrf.USBD_EPINEN_IN0 << ep)
530549
nrf.USBD.EPINEN.Set(epinen)
531550
}
532-
533-
func strToUTF16LEDescriptor(in string) []byte {
534-
runes := []rune(in)
535-
encoded := utf16.Encode(runes)
536-
size := (len(encoded) << 1) + 2
537-
out := make([]byte, size)
538-
out[0] = byte(size)
539-
out[1] = 0x03
540-
for i, value := range encoded {
541-
out[(i<<1)+2] = byte(value & 0xff)
542-
out[(i<<1)+3] = byte(value >> 8)
543-
}
544-
return out
545-
}

0 commit comments

Comments
 (0)