samd21,samd51,nrf52840: refactor usb initialization
Этот коммит содержится в:
родитель
fcefcb191c
коммит
2fa24ef752
9 изменённых файлов: 200 добавлений и 97 удалений
|
@ -22,7 +22,6 @@ type USBCDC struct {
|
|||
waitTxc bool
|
||||
waitTxcRetryCount uint8
|
||||
sent bool
|
||||
configured bool
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -149,26 +148,8 @@ const (
|
|||
usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Mask = 0x3FFF
|
||||
)
|
||||
|
||||
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}
|
||||
)
|
||||
|
||||
// Configure the USB CDC interface. The config is here for compatibility with the UART interface.
|
||||
func (usbcdc *USBCDC) Configure(config UARTConfig) {
|
||||
// Configure the USB peripheral. The config is here for compatibility with the UART interface.
|
||||
func (dev *USBDevice) Configure(config UARTConfig) {
|
||||
// reset USB interface
|
||||
sam.USB_DEVICE.CTRLA.SetBits(sam.USB_DEVICE_CTRLA_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)
|
||||
|
||||
// enable IRQ
|
||||
intr := interrupt.New(sam.IRQ_USB, handleUSB)
|
||||
intr.Enable()
|
||||
|
||||
usbcdc.configured = true
|
||||
interrupt.New(sam.IRQ_USB, handleUSBIRQ).Enable()
|
||||
}
|
||||
|
||||
// Configured returns whether usbcdc is configured or not.
|
||||
func (usbcdc *USBCDC) Configured() bool {
|
||||
return usbcdc.configured
|
||||
func (usbcdc *USBCDC) Configure(config UARTConfig) {
|
||||
// dummy
|
||||
}
|
||||
|
||||
func handlePadCalibration() {
|
||||
|
@ -257,7 +234,7 @@ func handlePadCalibration() {
|
|||
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
|
||||
flags := sam.USB_DEVICE.INTFLAG.Get()
|
||||
sam.USB_DEVICE.INTFLAG.Set(flags)
|
||||
|
|
|
@ -22,7 +22,6 @@ type USBCDC struct {
|
|||
waitTxc bool
|
||||
waitTxcRetryCount uint8
|
||||
sent bool
|
||||
configured bool
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -150,26 +149,8 @@ const (
|
|||
usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Mask = 0x3FFF
|
||||
)
|
||||
|
||||
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}
|
||||
)
|
||||
|
||||
// Configure the USB CDC interface. The config is here for compatibility with the UART interface.
|
||||
func (usbcdc *USBCDC) Configure(config UARTConfig) {
|
||||
// Configure the USB peripheral. The config is here for compatibility with the UART interface.
|
||||
func (dev *USBDevice) Configure(config UARTConfig) {
|
||||
// reset USB interface
|
||||
sam.USB_DEVICE.CTRLA.SetBits(sam.USB_DEVICE_CTRLA_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_TRCPT0, handleUSBIRQ).Enable()
|
||||
interrupt.New(sam.IRQ_USB_TRCPT1, handleUSBIRQ).Enable()
|
||||
|
||||
usbcdc.configured = true
|
||||
}
|
||||
|
||||
// Configured returns whether usbcdc is configured or not.
|
||||
func (usbcdc *USBCDC) Configured() bool {
|
||||
return usbcdc.configured
|
||||
func (usbcdc *USBCDC) Configure(config UARTConfig) {
|
||||
// dummy
|
||||
}
|
||||
|
||||
func handlePadCalibration() {
|
||||
|
|
|
@ -14,8 +14,6 @@ import (
|
|||
// USBCDC is the USB CDC aka serial over USB interface on the nRF52840
|
||||
type USBCDC struct {
|
||||
Buffer *RingBuffer
|
||||
interrupt interrupt.Interrupt
|
||||
initcomplete bool
|
||||
TxIdx volatile.Register8
|
||||
waitTxc bool
|
||||
waitTxcRetryCount uint8
|
||||
|
@ -125,25 +123,11 @@ var (
|
|||
_USB = USBCDC{Buffer: NewRingBuffer()}
|
||||
waitHidTxc bool
|
||||
|
||||
usbEndpointDescriptors [8]usbDeviceDescriptor
|
||||
|
||||
udd_ep_in_cache_buffer [7][128]uint8
|
||||
udd_ep_out_cache_buffer [7][128]uint8
|
||||
|
||||
sendOnEP0DATADONE struct {
|
||||
ptr *byte
|
||||
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
|
||||
epouten uint32
|
||||
easyDMABusy volatile.Register8
|
||||
|
@ -167,19 +151,15 @@ func exitCriticalSection() {
|
|||
easyDMABusy.ClearBits(1)
|
||||
}
|
||||
|
||||
// Configure the USB CDC interface. The config is here for compatibility with the UART interface.
|
||||
func (usbcdc *USBCDC) Configure(config UARTConfig) {
|
||||
if usbcdc.initcomplete {
|
||||
return
|
||||
}
|
||||
|
||||
// Configure the USB peripheral. The config is here for compatibility with the UART interface.
|
||||
func (dev *USBDevice) Configure(config UARTConfig) {
|
||||
// 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
|
||||
// shouldn't generally do that but it is useful for debugging and panic
|
||||
// logging.
|
||||
usbcdc.interrupt = interrupt.New(nrf.IRQ_USBD, _USB.handleInterrupt)
|
||||
usbcdc.interrupt.SetPriority(0x40) // interrupt priority 2 (lower number means more important)
|
||||
usbcdc.interrupt.Enable()
|
||||
intr := interrupt.New(nrf.IRQ_USBD, handleUSBIRQ)
|
||||
intr.SetPriority(0x40) // interrupt priority 2 (lower number means more important)
|
||||
intr.Enable()
|
||||
|
||||
// enable USB
|
||||
nrf.USBD.ENABLE.Set(1)
|
||||
|
@ -194,14 +174,16 @@ func (usbcdc *USBCDC) Configure(config UARTConfig) {
|
|||
)
|
||||
|
||||
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 {
|
||||
nrf.USBD.EVENTS_SOF.Set(0)
|
||||
usbcdc.Flush()
|
||||
USB.Flush()
|
||||
if hidCallback != nil && !waitHidTxc {
|
||||
hidCallback()
|
||||
}
|
||||
|
@ -301,7 +283,7 @@ func (usbcdc *USBCDC) handleInterrupt(interrupt.Interrupt) {
|
|||
}
|
||||
case usb_CDC_ENDPOINT_IN: //, usb_CDC_ENDPOINT_ACM:
|
||||
if inDataDone {
|
||||
usbcdc.waitTxc = false
|
||||
USB.waitTxc = false
|
||||
exitCriticalSection()
|
||||
}
|
||||
case usb_HID_ENDPOINT_IN:
|
||||
|
@ -327,7 +309,7 @@ func (usbcdc *USBCDC) handleInterrupt(interrupt.Interrupt) {
|
|||
nrf.USBD.TASKS_EP0STATUS.Set(1)
|
||||
}
|
||||
if i == usb_CDC_ENDPOINT_OUT {
|
||||
usbcdc.handleEndpoint(uint32(i))
|
||||
USB.handleEndpoint(uint32(i))
|
||||
}
|
||||
exitCriticalSection()
|
||||
}
|
||||
|
|
|
@ -7,5 +7,4 @@ package machine
|
|||
var Serial = USB
|
||||
|
||||
func InitSerial() {
|
||||
Serial.Configure(UARTConfig{})
|
||||
}
|
||||
|
|
|
@ -8,6 +8,12 @@ import (
|
|||
"runtime/volatile"
|
||||
)
|
||||
|
||||
type USBDevice struct {
|
||||
}
|
||||
|
||||
var (
|
||||
USBDev = &USBDevice{}
|
||||
)
|
||||
var usbDescriptor = descriptorCDC
|
||||
|
||||
var (
|
||||
|
@ -47,6 +53,24 @@ var (
|
|||
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 (
|
||||
usb_IMANUFACTURER = 1
|
||||
usb_IPRODUCT = 2
|
||||
|
|
|
@ -28,11 +28,8 @@ func init() {
|
|||
initUSBClock()
|
||||
initADCClock()
|
||||
|
||||
// connect to USB CDC interface
|
||||
machine.USBDev.Configure(machine.UARTConfig{})
|
||||
machine.InitSerial()
|
||||
if !machine.USB.Configured() {
|
||||
machine.USB.Configure(machine.UARTConfig{})
|
||||
}
|
||||
}
|
||||
|
||||
func putchar(c byte) {
|
||||
|
|
|
@ -28,11 +28,8 @@ func init() {
|
|||
initUSBClock()
|
||||
initADCClock()
|
||||
|
||||
// connect to USB CDC interface
|
||||
machine.USBDev.Configure(machine.UARTConfig{})
|
||||
machine.InitSerial()
|
||||
if !machine.USB.Configured() {
|
||||
machine.USB.Configure(machine.UARTConfig{})
|
||||
}
|
||||
}
|
||||
|
||||
func putchar(c byte) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//go:build nrf
|
||||
// +build nrf
|
||||
//go:build nrf && !nrf52840
|
||||
// +build nrf,!nrf52840
|
||||
|
||||
package runtime
|
||||
|
||||
|
|
149
src/runtime/runtime_nrf52840.go
Обычный файл
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()
|
||||
}
|
||||
}
|
Загрузка…
Создание таблицы
Сослаться в новой задаче