Skip to content

Commit 35c8707

Browse files
sago35deadprogram
authored andcommitted
nrf52840: improve USBCDC
1 parent 16e30c9 commit 35c8707

File tree

1 file changed

+95
-10
lines changed

1 file changed

+95
-10
lines changed

src/machine/usb_nrf52840.go

Lines changed: 95 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,100 @@ import (
1212

1313
// USBCDC is the USB CDC aka serial over USB interface on the nRF52840
1414
type USBCDC struct {
15-
Buffer *RingBuffer
16-
interrupt interrupt.Interrupt
17-
initcomplete bool
15+
Buffer *RingBuffer
16+
interrupt interrupt.Interrupt
17+
initcomplete bool
18+
TxIdx volatile.Register8
19+
waitTxc bool
20+
waitTxcRetryCount uint8
21+
sent bool
22+
}
23+
24+
const (
25+
usbcdcTxSizeMask uint8 = 0x3F
26+
usbcdcTxBankMask uint8 = ^usbcdcTxSizeMask
27+
usbcdcTxBank1st uint8 = 0x00
28+
usbcdcTxBank2nd uint8 = usbcdcTxSizeMask + 1
29+
usbcdcTxMaxRetriesAllowed uint8 = 5
30+
)
31+
32+
// Flush flushes buffered data.
33+
func (usbcdc *USBCDC) Flush() error {
34+
if usbLineInfo.lineState > 0 {
35+
idx := usbcdc.TxIdx.Get()
36+
sz := idx & usbcdcTxSizeMask
37+
bk := idx & usbcdcTxBankMask
38+
if 0 < sz {
39+
40+
if usbcdc.waitTxc {
41+
// waiting for the next flush(), because the transmission is not complete
42+
usbcdc.waitTxcRetryCount++
43+
return nil
44+
}
45+
usbcdc.waitTxc = true
46+
usbcdc.waitTxcRetryCount = 0
47+
48+
// set the data
49+
enterCriticalSection()
50+
sendViaEPIn(
51+
usb_CDC_ENDPOINT_IN,
52+
&udd_ep_in_cache_buffer[usb_CDC_ENDPOINT_IN][bk],
53+
int(sz),
54+
)
55+
if bk == usbcdcTxBank1st {
56+
usbcdc.TxIdx.Set(usbcdcTxBank2nd)
57+
} else {
58+
usbcdc.TxIdx.Set(usbcdcTxBank1st)
59+
}
60+
61+
UART0.sent = true
62+
}
63+
}
64+
return nil
1865
}
1966

2067
// WriteByte writes a byte of data to the USB CDC interface.
2168
func (usbcdc USBCDC) WriteByte(c byte) error {
2269
// Supposedly to handle problem with Windows USB serial ports?
2370
if usbLineInfo.lineState > 0 {
24-
enterCriticalSection()
25-
udd_ep_in_cache_buffer[usb_CDC_ENDPOINT_IN][0] = c
26-
sendViaEPIn(
27-
usb_CDC_ENDPOINT_IN,
28-
&udd_ep_in_cache_buffer[usb_CDC_ENDPOINT_IN][0],
29-
1,
30-
)
71+
ok := false
72+
for {
73+
mask := interrupt.Disable()
74+
75+
idx := UART0.TxIdx.Get()
76+
if (idx & usbcdcTxSizeMask) < usbcdcTxSizeMask {
77+
udd_ep_in_cache_buffer[usb_CDC_ENDPOINT_IN][idx] = c
78+
UART0.TxIdx.Set(idx + 1)
79+
ok = true
80+
}
81+
82+
interrupt.Restore(mask)
83+
84+
if ok {
85+
break
86+
} else if usbcdcTxMaxRetriesAllowed < UART0.waitTxcRetryCount {
87+
mask := interrupt.Disable()
88+
UART0.waitTxc = false
89+
UART0.waitTxcRetryCount = 0
90+
UART0.TxIdx.Set(0)
91+
usbLineInfo.lineState = 0
92+
interrupt.Restore(mask)
93+
break
94+
} else {
95+
mask := interrupt.Disable()
96+
if UART0.sent {
97+
if UART0.waitTxc {
98+
if !easyDMABusy.HasBits(1) {
99+
UART0.waitTxc = false
100+
UART0.Flush()
101+
}
102+
} else {
103+
UART0.Flush()
104+
}
105+
}
106+
interrupt.Restore(mask)
107+
}
108+
}
31109
}
32110

33111
return nil
@@ -108,6 +186,7 @@ func (usbcdc *USBCDC) Configure(config UARTConfig) {
108186
nrf.USBD_INTENSET_EPDATA |
109187
nrf.USBD_INTENSET_EP0DATADONE |
110188
nrf.USBD_INTENSET_USBEVENT |
189+
nrf.USBD_INTENSET_SOF |
111190
nrf.USBD_INTENSET_EP0SETUP,
112191
)
113192

@@ -117,6 +196,11 @@ func (usbcdc *USBCDC) Configure(config UARTConfig) {
117196
}
118197

119198
func (usbcdc *USBCDC) handleInterrupt(interrupt.Interrupt) {
199+
if nrf.USBD.EVENTS_SOF.Get() == 1 {
200+
nrf.USBD.EVENTS_SOF.Set(0)
201+
UART0.Flush()
202+
}
203+
120204
// USBD ready event
121205
if nrf.USBD.EVENTS_USBEVENT.Get() == 1 {
122206
nrf.USBD.EVENTS_USBEVENT.Set(0)
@@ -207,6 +291,7 @@ func (usbcdc *USBCDC) handleInterrupt(interrupt.Interrupt) {
207291
}
208292
case usb_CDC_ENDPOINT_IN: //, usb_CDC_ENDPOINT_ACM:
209293
if inDataDone {
294+
UART0.waitTxc = false
210295
exitCriticalSection()
211296
}
212297
}

0 commit comments

Comments
 (0)