Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 95 additions & 10 deletions src/machine/usb_nrf52840.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,100 @@ import (

// USBCDC is the USB CDC aka serial over USB interface on the nRF52840
type USBCDC struct {
Buffer *RingBuffer
interrupt interrupt.Interrupt
initcomplete bool
Buffer *RingBuffer
interrupt interrupt.Interrupt
initcomplete bool
TxIdx volatile.Register8
waitTxc bool
waitTxcRetryCount uint8
sent bool
}

const (
usbcdcTxSizeMask uint8 = 0x3F
usbcdcTxBankMask uint8 = ^usbcdcTxSizeMask
usbcdcTxBank1st uint8 = 0x00
usbcdcTxBank2nd uint8 = usbcdcTxSizeMask + 1
usbcdcTxMaxRetriesAllowed uint8 = 5
)

// Flush flushes buffered data.
func (usbcdc *USBCDC) Flush() error {
if usbLineInfo.lineState > 0 {
idx := usbcdc.TxIdx.Get()
sz := idx & usbcdcTxSizeMask
bk := idx & usbcdcTxBankMask
if 0 < sz {

if usbcdc.waitTxc {
// waiting for the next flush(), because the transmission is not complete
usbcdc.waitTxcRetryCount++
return nil
}
usbcdc.waitTxc = true
usbcdc.waitTxcRetryCount = 0

// set the data
enterCriticalSection()
sendViaEPIn(
usb_CDC_ENDPOINT_IN,
&udd_ep_in_cache_buffer[usb_CDC_ENDPOINT_IN][bk],
int(sz),
)
if bk == usbcdcTxBank1st {
usbcdc.TxIdx.Set(usbcdcTxBank2nd)
} else {
usbcdc.TxIdx.Set(usbcdcTxBank1st)
}

USB.sent = true
}
}
return nil
}

// WriteByte writes a byte of data to the USB CDC interface.
func (usbcdc USBCDC) WriteByte(c byte) error {
// Supposedly to handle problem with Windows USB serial ports?
if usbLineInfo.lineState > 0 {
enterCriticalSection()
udd_ep_in_cache_buffer[usb_CDC_ENDPOINT_IN][0] = c
sendViaEPIn(
usb_CDC_ENDPOINT_IN,
&udd_ep_in_cache_buffer[usb_CDC_ENDPOINT_IN][0],
1,
)
ok := false
for {
mask := interrupt.Disable()

idx := USB.TxIdx.Get()
if (idx & usbcdcTxSizeMask) < usbcdcTxSizeMask {
udd_ep_in_cache_buffer[usb_CDC_ENDPOINT_IN][idx] = c
USB.TxIdx.Set(idx + 1)
ok = true
}

interrupt.Restore(mask)

if ok {
break
} else if usbcdcTxMaxRetriesAllowed < USB.waitTxcRetryCount {
mask := interrupt.Disable()
USB.waitTxc = false
USB.waitTxcRetryCount = 0
USB.TxIdx.Set(0)
usbLineInfo.lineState = 0
interrupt.Restore(mask)
break
} else {
mask := interrupt.Disable()
if USB.sent {
if USB.waitTxc {
if !easyDMABusy.HasBits(1) {
USB.waitTxc = false
USB.Flush()
}
} else {
USB.Flush()
}
}
interrupt.Restore(mask)
}
}
}

return nil
Expand Down Expand Up @@ -108,6 +186,7 @@ func (usbcdc *USBCDC) Configure(config UARTConfig) {
nrf.USBD_INTENSET_EPDATA |
nrf.USBD_INTENSET_EP0DATADONE |
nrf.USBD_INTENSET_USBEVENT |
nrf.USBD_INTENSET_SOF |
nrf.USBD_INTENSET_EP0SETUP,
)

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

func (usbcdc *USBCDC) handleInterrupt(interrupt.Interrupt) {
if nrf.USBD.EVENTS_SOF.Get() == 1 {
nrf.USBD.EVENTS_SOF.Set(0)
USB.Flush()
}

// USBD ready event
if nrf.USBD.EVENTS_USBEVENT.Get() == 1 {
nrf.USBD.EVENTS_USBEVENT.Set(0)
Expand Down Expand Up @@ -207,6 +291,7 @@ func (usbcdc *USBCDC) handleInterrupt(interrupt.Interrupt) {
}
case usb_CDC_ENDPOINT_IN: //, usb_CDC_ENDPOINT_ACM:
if inDataDone {
USB.waitTxc = false
exitCriticalSection()
}
}
Expand Down