samd21,samd51,nrf52840: refactor usb initialization

Этот коммит содержится в:
sago35 2022-07-06 07:58:42 +09:00 коммит произвёл Ron Evans
родитель fcefcb191c
коммит 2fa24ef752
9 изменённых файлов: 200 добавлений и 97 удалений

Просмотреть файл

@ -22,7 +22,6 @@ type USBCDC struct {
waitTxc bool waitTxc bool
waitTxcRetryCount uint8 waitTxcRetryCount uint8
sent bool sent bool
configured bool
} }
var ( var (
@ -149,26 +148,8 @@ const (
usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Mask = 0x3FFF usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Mask = 0x3FFF
) )
var ( // Configure the USB peripheral. The config is here for compatibility with the UART interface.
usbEndpointDescriptors [8]usbDeviceDescriptor func (dev *USBDevice) Configure(config UARTConfig) {
udd_ep_in_cache_buffer [7][128]uint8
udd_ep_out_cache_buffer [7][128]uint8
isEndpointHalt = false
isRemoteWakeUpEnabled = false
endPoints = []uint32{usb_ENDPOINT_TYPE_CONTROL,
(usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointIn),
(usb_ENDPOINT_TYPE_BULK | usbEndpointOut),
(usb_ENDPOINT_TYPE_BULK | usbEndpointIn)}
usbConfiguration uint8
usbSetInterface uint8
usbLineInfo = cdcLineInfo{115200, 0x00, 0x00, 0x08, 0x00}
)
// Configure the USB CDC interface. The config is here for compatibility with the UART interface.
func (usbcdc *USBCDC) Configure(config UARTConfig) {
// reset USB interface // reset USB interface
sam.USB_DEVICE.CTRLA.SetBits(sam.USB_DEVICE_CTRLA_SWRST) sam.USB_DEVICE.CTRLA.SetBits(sam.USB_DEVICE_CTRLA_SWRST)
for sam.USB_DEVICE.SYNCBUSY.HasBits(sam.USB_DEVICE_SYNCBUSY_SWRST) || for sam.USB_DEVICE.SYNCBUSY.HasBits(sam.USB_DEVICE_SYNCBUSY_SWRST) ||
@ -203,15 +184,11 @@ func (usbcdc *USBCDC) Configure(config UARTConfig) {
sam.USB_DEVICE.CTRLA.SetBits(sam.USB_DEVICE_CTRLA_ENABLE) sam.USB_DEVICE.CTRLA.SetBits(sam.USB_DEVICE_CTRLA_ENABLE)
// enable IRQ // enable IRQ
intr := interrupt.New(sam.IRQ_USB, handleUSB) interrupt.New(sam.IRQ_USB, handleUSBIRQ).Enable()
intr.Enable()
usbcdc.configured = true
} }
// Configured returns whether usbcdc is configured or not. func (usbcdc *USBCDC) Configure(config UARTConfig) {
func (usbcdc *USBCDC) Configured() bool { // dummy
return usbcdc.configured
} }
func handlePadCalibration() { func handlePadCalibration() {
@ -257,7 +234,7 @@ func handlePadCalibration() {
sam.USB_DEVICE.PADCAL.SetBits(calibTrim << sam.USB_DEVICE_PADCAL_TRIM_Pos) sam.USB_DEVICE.PADCAL.SetBits(calibTrim << sam.USB_DEVICE_PADCAL_TRIM_Pos)
} }
func handleUSB(intr interrupt.Interrupt) { func handleUSBIRQ(intr interrupt.Interrupt) {
// reset all interrupt flags // reset all interrupt flags
flags := sam.USB_DEVICE.INTFLAG.Get() flags := sam.USB_DEVICE.INTFLAG.Get()
sam.USB_DEVICE.INTFLAG.Set(flags) sam.USB_DEVICE.INTFLAG.Set(flags)

Просмотреть файл

@ -22,7 +22,6 @@ type USBCDC struct {
waitTxc bool waitTxc bool
waitTxcRetryCount uint8 waitTxcRetryCount uint8
sent bool sent bool
configured bool
} }
var ( var (
@ -150,26 +149,8 @@ const (
usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Mask = 0x3FFF usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Mask = 0x3FFF
) )
var ( // Configure the USB peripheral. The config is here for compatibility with the UART interface.
usbEndpointDescriptors [8]usbDeviceDescriptor func (dev *USBDevice) Configure(config UARTConfig) {
udd_ep_in_cache_buffer [7][128]uint8
udd_ep_out_cache_buffer [7][128]uint8
isEndpointHalt = false
isRemoteWakeUpEnabled = false
endPoints = []uint32{usb_ENDPOINT_TYPE_CONTROL,
(usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointIn),
(usb_ENDPOINT_TYPE_BULK | usbEndpointOut),
(usb_ENDPOINT_TYPE_BULK | usbEndpointIn)}
usbConfiguration uint8
usbSetInterface uint8
usbLineInfo = cdcLineInfo{115200, 0x00, 0x00, 0x08, 0x00}
)
// Configure the USB CDC interface. The config is here for compatibility with the UART interface.
func (usbcdc *USBCDC) Configure(config UARTConfig) {
// reset USB interface // reset USB interface
sam.USB_DEVICE.CTRLA.SetBits(sam.USB_DEVICE_CTRLA_SWRST) sam.USB_DEVICE.CTRLA.SetBits(sam.USB_DEVICE_CTRLA_SWRST)
for sam.USB_DEVICE.SYNCBUSY.HasBits(sam.USB_DEVICE_SYNCBUSY_SWRST) || for sam.USB_DEVICE.SYNCBUSY.HasBits(sam.USB_DEVICE_SYNCBUSY_SWRST) ||
@ -208,13 +189,10 @@ func (usbcdc *USBCDC) Configure(config UARTConfig) {
interrupt.New(sam.IRQ_USB_SOF_HSOF, handleUSBIRQ).Enable() interrupt.New(sam.IRQ_USB_SOF_HSOF, handleUSBIRQ).Enable()
interrupt.New(sam.IRQ_USB_TRCPT0, handleUSBIRQ).Enable() interrupt.New(sam.IRQ_USB_TRCPT0, handleUSBIRQ).Enable()
interrupt.New(sam.IRQ_USB_TRCPT1, handleUSBIRQ).Enable() interrupt.New(sam.IRQ_USB_TRCPT1, handleUSBIRQ).Enable()
usbcdc.configured = true
} }
// Configured returns whether usbcdc is configured or not. func (usbcdc *USBCDC) Configure(config UARTConfig) {
func (usbcdc *USBCDC) Configured() bool { // dummy
return usbcdc.configured
} }
func handlePadCalibration() { func handlePadCalibration() {

Просмотреть файл

@ -14,8 +14,6 @@ import (
// USBCDC is the USB CDC aka serial over USB interface on the nRF52840 // USBCDC is the USB CDC aka serial over USB interface on the nRF52840
type USBCDC struct { type USBCDC struct {
Buffer *RingBuffer Buffer *RingBuffer
interrupt interrupt.Interrupt
initcomplete bool
TxIdx volatile.Register8 TxIdx volatile.Register8
waitTxc bool waitTxc bool
waitTxcRetryCount uint8 waitTxcRetryCount uint8
@ -125,25 +123,11 @@ var (
_USB = USBCDC{Buffer: NewRingBuffer()} _USB = USBCDC{Buffer: NewRingBuffer()}
waitHidTxc bool waitHidTxc bool
usbEndpointDescriptors [8]usbDeviceDescriptor
udd_ep_in_cache_buffer [7][128]uint8
udd_ep_out_cache_buffer [7][128]uint8
sendOnEP0DATADONE struct { sendOnEP0DATADONE struct {
ptr *byte ptr *byte
count int count int
} }
isEndpointHalt = false
isRemoteWakeUpEnabled = false
endPoints = []uint32{usb_ENDPOINT_TYPE_CONTROL,
(usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointIn),
(usb_ENDPOINT_TYPE_BULK | usbEndpointOut),
(usb_ENDPOINT_TYPE_BULK | usbEndpointIn)}
usbConfiguration uint8
usbSetInterface uint8
usbLineInfo = cdcLineInfo{115200, 0x00, 0x00, 0x08, 0x00}
epinen uint32 epinen uint32
epouten uint32 epouten uint32
easyDMABusy volatile.Register8 easyDMABusy volatile.Register8
@ -167,19 +151,15 @@ func exitCriticalSection() {
easyDMABusy.ClearBits(1) easyDMABusy.ClearBits(1)
} }
// Configure the USB CDC interface. The config is here for compatibility with the UART interface. // Configure the USB peripheral. The config is here for compatibility with the UART interface.
func (usbcdc *USBCDC) Configure(config UARTConfig) { func (dev *USBDevice) Configure(config UARTConfig) {
if usbcdc.initcomplete {
return
}
// Enable IRQ. Make sure this is higher than the SWI2 interrupt handler so // Enable IRQ. Make sure this is higher than the SWI2 interrupt handler so
// that it is possible to print to the console from a BLE interrupt. You // that it is possible to print to the console from a BLE interrupt. You
// shouldn't generally do that but it is useful for debugging and panic // shouldn't generally do that but it is useful for debugging and panic
// logging. // logging.
usbcdc.interrupt = interrupt.New(nrf.IRQ_USBD, _USB.handleInterrupt) intr := interrupt.New(nrf.IRQ_USBD, handleUSBIRQ)
usbcdc.interrupt.SetPriority(0x40) // interrupt priority 2 (lower number means more important) intr.SetPriority(0x40) // interrupt priority 2 (lower number means more important)
usbcdc.interrupt.Enable() intr.Enable()
// enable USB // enable USB
nrf.USBD.ENABLE.Set(1) nrf.USBD.ENABLE.Set(1)
@ -194,14 +174,16 @@ func (usbcdc *USBCDC) Configure(config UARTConfig) {
) )
nrf.USBD.USBPULLUP.Set(0) nrf.USBD.USBPULLUP.Set(0)
usbcdc.initcomplete = true
} }
func (usbcdc *USBCDC) handleInterrupt(interrupt.Interrupt) { func (usbcdc *USBCDC) Configure(config UARTConfig) {
// dummy
}
func handleUSBIRQ(interrupt.Interrupt) {
if nrf.USBD.EVENTS_SOF.Get() == 1 { if nrf.USBD.EVENTS_SOF.Get() == 1 {
nrf.USBD.EVENTS_SOF.Set(0) nrf.USBD.EVENTS_SOF.Set(0)
usbcdc.Flush() USB.Flush()
if hidCallback != nil && !waitHidTxc { if hidCallback != nil && !waitHidTxc {
hidCallback() hidCallback()
} }
@ -301,7 +283,7 @@ func (usbcdc *USBCDC) handleInterrupt(interrupt.Interrupt) {
} }
case usb_CDC_ENDPOINT_IN: //, usb_CDC_ENDPOINT_ACM: case usb_CDC_ENDPOINT_IN: //, usb_CDC_ENDPOINT_ACM:
if inDataDone { if inDataDone {
usbcdc.waitTxc = false USB.waitTxc = false
exitCriticalSection() exitCriticalSection()
} }
case usb_HID_ENDPOINT_IN: case usb_HID_ENDPOINT_IN:
@ -327,7 +309,7 @@ func (usbcdc *USBCDC) handleInterrupt(interrupt.Interrupt) {
nrf.USBD.TASKS_EP0STATUS.Set(1) nrf.USBD.TASKS_EP0STATUS.Set(1)
} }
if i == usb_CDC_ENDPOINT_OUT { if i == usb_CDC_ENDPOINT_OUT {
usbcdc.handleEndpoint(uint32(i)) USB.handleEndpoint(uint32(i))
} }
exitCriticalSection() exitCriticalSection()
} }

Просмотреть файл

@ -7,5 +7,4 @@ package machine
var Serial = USB var Serial = USB
func InitSerial() { func InitSerial() {
Serial.Configure(UARTConfig{})
} }

Просмотреть файл

@ -8,6 +8,12 @@ import (
"runtime/volatile" "runtime/volatile"
) )
type USBDevice struct {
}
var (
USBDev = &USBDevice{}
)
var usbDescriptor = descriptorCDC var usbDescriptor = descriptorCDC
var ( var (
@ -47,6 +53,24 @@ var (
usb_STRING_LANGUAGE = [2]uint16{(3 << 8) | (2 + 2), 0x0409} // English usb_STRING_LANGUAGE = [2]uint16{(3 << 8) | (2 + 2), 0x0409} // English
) )
var (
usbEndpointDescriptors [8]usbDeviceDescriptor
udd_ep_in_cache_buffer [7][128]uint8
udd_ep_out_cache_buffer [7][128]uint8
isEndpointHalt = false
isRemoteWakeUpEnabled = false
endPoints = []uint32{usb_ENDPOINT_TYPE_CONTROL,
(usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointIn),
(usb_ENDPOINT_TYPE_BULK | usbEndpointOut),
(usb_ENDPOINT_TYPE_BULK | usbEndpointIn)}
usbConfiguration uint8
usbSetInterface uint8
usbLineInfo = cdcLineInfo{115200, 0x00, 0x00, 0x08, 0x00}
)
const ( const (
usb_IMANUFACTURER = 1 usb_IMANUFACTURER = 1
usb_IPRODUCT = 2 usb_IPRODUCT = 2

Просмотреть файл

@ -28,11 +28,8 @@ func init() {
initUSBClock() initUSBClock()
initADCClock() initADCClock()
// connect to USB CDC interface machine.USBDev.Configure(machine.UARTConfig{})
machine.InitSerial() machine.InitSerial()
if !machine.USB.Configured() {
machine.USB.Configure(machine.UARTConfig{})
}
} }
func putchar(c byte) { func putchar(c byte) {

Просмотреть файл

@ -28,11 +28,8 @@ func init() {
initUSBClock() initUSBClock()
initADCClock() initADCClock()
// connect to USB CDC interface machine.USBDev.Configure(machine.UARTConfig{})
machine.InitSerial() machine.InitSerial()
if !machine.USB.Configured() {
machine.USB.Configure(machine.UARTConfig{})
}
} }
func putchar(c byte) { func putchar(c byte) {

Просмотреть файл

@ -1,5 +1,5 @@
//go:build nrf //go:build nrf && !nrf52840
// +build nrf // +build nrf,!nrf52840
package runtime package runtime

149
src/runtime/runtime_nrf52840.go Обычный файл
Просмотреть файл

@ -0,0 +1,149 @@
//go:build nrf && nrf52840
// +build nrf,nrf52840
package runtime
import (
"device/arm"
"device/nrf"
"machine"
"runtime/interrupt"
"runtime/volatile"
)
type timeUnit int64
//go:linkname systemInit SystemInit
func systemInit()
//export Reset_Handler
func main() {
if nrf.FPUPresent {
arm.SCB.CPACR.Set(0) // disable FPU if it is enabled
}
systemInit()
preinit()
run()
exit(0)
}
func init() {
machine.USBDev.Configure(machine.UARTConfig{})
machine.InitSerial()
initLFCLK()
initRTC()
}
func initLFCLK() {
if machine.HasLowFrequencyCrystal {
nrf.CLOCK.LFCLKSRC.Set(nrf.CLOCK_LFCLKSTAT_SRC_Xtal)
}
nrf.CLOCK.TASKS_LFCLKSTART.Set(1)
for nrf.CLOCK.EVENTS_LFCLKSTARTED.Get() == 0 {
}
nrf.CLOCK.EVENTS_LFCLKSTARTED.Set(0)
}
func initRTC() {
nrf.RTC1.TASKS_START.Set(1)
intr := interrupt.New(nrf.IRQ_RTC1, func(intr interrupt.Interrupt) {
if nrf.RTC1.EVENTS_COMPARE[0].Get() != 0 {
nrf.RTC1.EVENTS_COMPARE[0].Set(0)
nrf.RTC1.INTENCLR.Set(nrf.RTC_INTENSET_COMPARE0)
nrf.RTC1.EVENTS_COMPARE[0].Set(0)
rtc_wakeup.Set(1)
}
if nrf.RTC1.EVENTS_OVRFLW.Get() != 0 {
nrf.RTC1.EVENTS_OVRFLW.Set(0)
rtcOverflows.Set(rtcOverflows.Get() + 1)
}
})
nrf.RTC1.INTENSET.Set(nrf.RTC_INTENSET_OVRFLW)
intr.SetPriority(0xc0) // low priority
intr.Enable()
}
func putchar(c byte) {
machine.Serial.WriteByte(c)
}
func getchar() byte {
for machine.Serial.Buffered() == 0 {
Gosched()
}
v, _ := machine.Serial.ReadByte()
return v
}
func buffered() int {
return machine.Serial.Buffered()
}
func sleepTicks(d timeUnit) {
for d != 0 {
ticks := uint32(d) & 0x7fffff // 23 bits (to be on the safe side)
rtc_sleep(ticks)
d -= timeUnit(ticks)
}
}
var rtcOverflows volatile.Register32 // number of times the RTC wrapped around
// ticksToNanoseconds converts RTC ticks (at 32768Hz) to nanoseconds.
func ticksToNanoseconds(ticks timeUnit) int64 {
// The following calculation is actually the following, but with both sides
// reduced to reduce the risk of overflow:
// ticks * 1e9 / 32768
return int64(ticks) * 1953125 / 64
}
// nanosecondsToTicks converts nanoseconds to RTC ticks (running at 32768Hz).
func nanosecondsToTicks(ns int64) timeUnit {
// The following calculation is actually the following, but with both sides
// reduced to reduce the risk of overflow:
// ns * 32768 / 1e9
return timeUnit(ns * 64 / 1953125)
}
// Monotonically increasing numer of ticks since start.
func ticks() timeUnit {
// For some ways of capturing the time atomically, see this thread:
// https://www.eevblog.com/forum/microcontrollers/correct-timing-by-timer-overflow-count/msg749617/#msg749617
// Here, instead of re-reading the counter register if an overflow has been
// detected, we simply try again because that results in (slightly) smaller
// code and is perhaps easier to prove correct.
for {
mask := interrupt.Disable()
counter := uint32(nrf.RTC1.COUNTER.Get())
overflows := rtcOverflows.Get()
hasOverflow := nrf.RTC1.EVENTS_OVRFLW.Get() != 0
interrupt.Restore(mask)
if hasOverflow {
// There was an overflow. Try again.
continue
}
// The counter is 24 bits in size, so the number of overflows form the
// upper 32 bits (together 56 bits, which covers 71493 years at
// 32768kHz: I'd argue good enough for most purposes).
return timeUnit(overflows)<<24 + timeUnit(counter)
}
}
var rtc_wakeup volatile.Register8
func rtc_sleep(ticks uint32) {
nrf.RTC1.INTENSET.Set(nrf.RTC_INTENSET_COMPARE0)
rtc_wakeup.Set(0)
if ticks == 1 {
// Race condition (even in hardware) at ticks == 1.
// TODO: fix this in a better way by detecting it, like the manual
// describes.
ticks = 2
}
nrf.RTC1.CC[0].Set((nrf.RTC1.COUNTER.Get() + ticks) & 0x00ffffff)
for rtc_wakeup.Get() == 0 {
waitForEvents()
}
}