From bdcc7e6c5280c56d0e3317f22c71ff4ea415ba3a Mon Sep 17 00:00:00 2001 From: sago35 Date: Mon, 22 Feb 2021 22:35:12 +0900 Subject: [PATCH 1/2] nrf52840: improve USBCDC --- src/machine/usb_nrf52840.go | 105 ++++++++++++++++++++++++++++++++---- 1 file changed, 95 insertions(+), 10 deletions(-) diff --git a/src/machine/usb_nrf52840.go b/src/machine/usb_nrf52840.go index 8d056839ba..03b490ff20 100644 --- a/src/machine/usb_nrf52840.go +++ b/src/machine/usb_nrf52840.go @@ -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) + } + + UART0.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 := UART0.TxIdx.Get() + if (idx & usbcdcTxSizeMask) < usbcdcTxSizeMask { + udd_ep_in_cache_buffer[usb_CDC_ENDPOINT_IN][idx] = c + UART0.TxIdx.Set(idx + 1) + ok = true + } + + interrupt.Restore(mask) + + if ok { + break + } else if usbcdcTxMaxRetriesAllowed < UART0.waitTxcRetryCount { + mask := interrupt.Disable() + UART0.waitTxc = false + UART0.waitTxcRetryCount = 0 + UART0.TxIdx.Set(0) + usbLineInfo.lineState = 0 + interrupt.Restore(mask) + break + } else { + mask := interrupt.Disable() + if UART0.sent { + if UART0.waitTxc { + if !easyDMABusy.HasBits(1) { + UART0.waitTxc = false + UART0.Flush() + } + } else { + UART0.Flush() + } + } + interrupt.Restore(mask) + } + } } return nil @@ -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, ) @@ -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) + UART0.Flush() + } + // USBD ready event if nrf.USBD.EVENTS_USBEVENT.Get() == 1 { nrf.USBD.EVENTS_USBEVENT.Set(0) @@ -207,6 +291,7 @@ func (usbcdc *USBCDC) handleInterrupt(interrupt.Interrupt) { } case usb_CDC_ENDPOINT_IN: //, usb_CDC_ENDPOINT_ACM: if inDataDone { + UART0.waitTxc = false exitCriticalSection() } } From 231d70d3d2c5df817bd521d20d6344d31627b4c0 Mon Sep 17 00:00:00 2001 From: sago35 Date: Thu, 25 Feb 2021 12:51:25 +0900 Subject: [PATCH 2/2] fix --- src/machine/usb_nrf52840.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/machine/usb_nrf52840.go b/src/machine/usb_nrf52840.go index 03b490ff20..3a04599f43 100644 --- a/src/machine/usb_nrf52840.go +++ b/src/machine/usb_nrf52840.go @@ -58,7 +58,7 @@ func (usbcdc *USBCDC) Flush() error { usbcdc.TxIdx.Set(usbcdcTxBank1st) } - UART0.sent = true + USB.sent = true } } return nil @@ -72,10 +72,10 @@ func (usbcdc USBCDC) WriteByte(c byte) error { for { mask := interrupt.Disable() - idx := UART0.TxIdx.Get() + idx := USB.TxIdx.Get() if (idx & usbcdcTxSizeMask) < usbcdcTxSizeMask { udd_ep_in_cache_buffer[usb_CDC_ENDPOINT_IN][idx] = c - UART0.TxIdx.Set(idx + 1) + USB.TxIdx.Set(idx + 1) ok = true } @@ -83,24 +83,24 @@ func (usbcdc USBCDC) WriteByte(c byte) error { if ok { break - } else if usbcdcTxMaxRetriesAllowed < UART0.waitTxcRetryCount { + } else if usbcdcTxMaxRetriesAllowed < USB.waitTxcRetryCount { mask := interrupt.Disable() - UART0.waitTxc = false - UART0.waitTxcRetryCount = 0 - UART0.TxIdx.Set(0) + USB.waitTxc = false + USB.waitTxcRetryCount = 0 + USB.TxIdx.Set(0) usbLineInfo.lineState = 0 interrupt.Restore(mask) break } else { mask := interrupt.Disable() - if UART0.sent { - if UART0.waitTxc { + if USB.sent { + if USB.waitTxc { if !easyDMABusy.HasBits(1) { - UART0.waitTxc = false - UART0.Flush() + USB.waitTxc = false + USB.Flush() } } else { - UART0.Flush() + USB.Flush() } } interrupt.Restore(mask) @@ -198,7 +198,7 @@ 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) - UART0.Flush() + USB.Flush() } // USBD ready event @@ -291,7 +291,7 @@ func (usbcdc *USBCDC) handleInterrupt(interrupt.Interrupt) { } case usb_CDC_ENDPOINT_IN: //, usb_CDC_ENDPOINT_ACM: if inDataDone { - UART0.waitTxc = false + USB.waitTxc = false exitCriticalSection() } }