diff --git a/src/machine/machine_esp32c3.go b/src/machine/machine_esp32c3.go index 727fcc1e64..eb2a18b5ee 100644 --- a/src/machine/machine_esp32c3.go +++ b/src/machine/machine_esp32c3.go @@ -519,6 +519,10 @@ type Serialer interface { RTS() bool } +func initUSB() { + // nothing to do here +} + // USB Serial/JTAG Controller // See esp32-c3_technical_reference_manual_en.pdf // pg. 736 diff --git a/src/machine/serial-usb.go b/src/machine/serial-usb.go index 6587082915..44dc63e0cd 100644 --- a/src/machine/serial-usb.go +++ b/src/machine/serial-usb.go @@ -6,5 +6,6 @@ package machine var Serial Serialer func InitSerial() { + initUSB() Serial = USBCDC } diff --git a/src/machine/usb.go b/src/machine/usb.go index 434ee0f1b8..9682521036 100644 --- a/src/machine/usb.go +++ b/src/machine/usb.go @@ -19,6 +19,17 @@ var ( USBCDC Serialer ) +func initUSB() { + enableUSBCDC() + USBDev.Configure(UARTConfig{}) +} + +// Using go:linkname here because there's a circular dependency between the +// machine package and the machine/usb/cdc package. +// +//go:linkname enableUSBCDC machine/usb/cdc.EnableUSBCDC +func enableUSBCDC() + type Serialer interface { WriteByte(c byte) error Write(data []byte) (n int, err error) diff --git a/src/runtime/runtime_atsamd21.go b/src/runtime/runtime_atsamd21.go index 52bedf739f..43e537708c 100644 --- a/src/runtime/runtime_atsamd21.go +++ b/src/runtime/runtime_atsamd21.go @@ -6,7 +6,7 @@ import ( "device/arm" "device/sam" "machine" - "machine/usb/cdc" + _ "machine/usb/cdc" "runtime/interrupt" "runtime/volatile" "unsafe" @@ -26,8 +26,6 @@ func init() { initUSBClock() initADCClock() - cdc.EnableUSBCDC() - machine.USBDev.Configure(machine.UARTConfig{}) machine.InitSerial() } diff --git a/src/runtime/runtime_atsamd51.go b/src/runtime/runtime_atsamd51.go index f8d46275b5..06fea8e113 100644 --- a/src/runtime/runtime_atsamd51.go +++ b/src/runtime/runtime_atsamd51.go @@ -6,7 +6,7 @@ import ( "device/arm" "device/sam" "machine" - "machine/usb/cdc" + _ "machine/usb/cdc" "runtime/interrupt" "runtime/volatile" ) @@ -27,8 +27,6 @@ func init() { initADCClock() enableCache() - cdc.EnableUSBCDC() - machine.USBDev.Configure(machine.UARTConfig{}) machine.InitSerial() } diff --git a/src/runtime/runtime_nrf.go b/src/runtime/runtime_nrf.go index 5c992ec47b..f5b47cc9a0 100644 --- a/src/runtime/runtime_nrf.go +++ b/src/runtime/runtime_nrf.go @@ -1,4 +1,4 @@ -//go:build nrf && !nrf52840 +//go:build nrf package runtime diff --git a/src/runtime/runtime_nrf52840.go b/src/runtime/runtime_nrf52840.go index 3c7deb031d..1d45f9b46a 100644 --- a/src/runtime/runtime_nrf52840.go +++ b/src/runtime/runtime_nrf52840.go @@ -2,150 +2,6 @@ package runtime -import ( - "device/arm" - "device/nrf" - "machine" - "machine/usb/cdc" - "runtime/interrupt" - "runtime/volatile" -) - -//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() { - cdc.EnableUSBCDC() - 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) - if d > 0x7fffff { - ticks = 0x7fffff - } - 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 number 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() - } -} +// This package needs to be present so that the machine package can go:linkname +// EnableUSBCDC from it. +import _ "machine/usb/cdc" diff --git a/src/runtime/runtime_rp2.go b/src/runtime/runtime_rp2.go index 08ae865699..1cd23d6dcb 100644 --- a/src/runtime/runtime_rp2.go +++ b/src/runtime/runtime_rp2.go @@ -7,7 +7,7 @@ import ( "device/rp" "internal/task" "machine" - "machine/usb/cdc" + _ "machine/usb/cdc" "runtime/interrupt" "runtime/volatile" "unsafe" @@ -360,8 +360,6 @@ func machineInit() func init() { machineInit() - cdc.EnableUSBCDC() - machine.USBDev.Configure(machine.UARTConfig{}) machine.InitSerial() }