@@ -12,22 +12,100 @@ import (
12
12
13
13
// USBCDC is the USB CDC aka serial over USB interface on the nRF52840
14
14
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
18
65
}
19
66
20
67
// WriteByte writes a byte of data to the USB CDC interface.
21
68
func (usbcdc USBCDC ) WriteByte (c byte ) error {
22
69
// Supposedly to handle problem with Windows USB serial ports?
23
70
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
+ }
31
109
}
32
110
33
111
return nil
@@ -108,6 +186,7 @@ func (usbcdc *USBCDC) Configure(config UARTConfig) {
108
186
nrf .USBD_INTENSET_EPDATA |
109
187
nrf .USBD_INTENSET_EP0DATADONE |
110
188
nrf .USBD_INTENSET_USBEVENT |
189
+ nrf .USBD_INTENSET_SOF |
111
190
nrf .USBD_INTENSET_EP0SETUP ,
112
191
)
113
192
@@ -117,6 +196,11 @@ func (usbcdc *USBCDC) Configure(config UARTConfig) {
117
196
}
118
197
119
198
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
+
120
204
// USBD ready event
121
205
if nrf .USBD .EVENTS_USBEVENT .Get () == 1 {
122
206
nrf .USBD .EVENTS_USBEVENT .Set (0 )
@@ -207,6 +291,7 @@ func (usbcdc *USBCDC) handleInterrupt(interrupt.Interrupt) {
207
291
}
208
292
case usb_CDC_ENDPOINT_IN : //, usb_CDC_ENDPOINT_ACM:
209
293
if inDataDone {
294
+ UART0 .waitTxc = false
210
295
exitCriticalSection ()
211
296
}
212
297
}
0 commit comments