diff options
author | Ethan Reesor <[email protected]> | 2020-02-23 20:09:44 -0600 |
---|---|---|
committer | Ron Evans <[email protected]> | 2020-07-08 21:58:15 +0200 |
commit | 4750635a207c0b879238e37b53bf60d3ebdd783e (patch) | |
tree | bf23f2e3a949cfe4f7928b191eb03fdb4aec0331 /src/runtime/runtime_nxpmk66f18.go | |
parent | 59218cd78483c1f2896b16bc4df7a11f03a2b11a (diff) | |
download | tinygo-4750635a207c0b879238e37b53bf60d3ebdd783e.tar.gz tinygo-4750635a207c0b879238e37b53bf60d3ebdd783e.zip |
Viable NXP/Teensy support
- Fix UART & putChar
- Timer-based sleep
- Enable systick in abort
- Buffered, interrupt-based UART TX
- Use the new interrupt API and fix sleepTicks
- Make pins behave more like other boards
- Use the MCU's UART numbering
- Allow interrupts to wake the scheduler (#1214)
Diffstat (limited to 'src/runtime/runtime_nxpmk66f18.go')
-rw-r--r-- | src/runtime/runtime_nxpmk66f18.go | 214 |
1 files changed, 49 insertions, 165 deletions
diff --git a/src/runtime/runtime_nxpmk66f18.go b/src/runtime/runtime_nxpmk66f18.go index fef738f42..b03e1257c 100644 --- a/src/runtime/runtime_nxpmk66f18.go +++ b/src/runtime/runtime_nxpmk66f18.go @@ -35,53 +35,41 @@ import ( "device/arm" "device/nxp" "machine" - "runtime/volatile" ) const ( - WDOG_UNLOCK_SEQ1 = 0xC520 - WDOG_UNLOCK_SEQ2 = 0xD928 + watchdogUnlockSequence1 = 0xC520 + watchdogUnlockSequence2 = 0xD928 - DEFAULT_FTM_MOD = 61440 - 1 - DEFAULT_FTM_PRESCALE = 1 + _DEFAULT_FTM_MOD = 61440 - 1 + _DEFAULT_FTM_PRESCALE = 1 ) -var ( - SIM_SOPT2_IRC48SEL = nxp.SIM_SOPT2_PLLFLLSEL(3) - SMC_PMCTRL_HSRUN = nxp.SMC_PMCTRL_RUNM(3) - SMC_PMSTAT_HSRUN = nxp.SMC_PMSTAT_PMSTAT(0x80) +const ( + _SIM_SOPT2_IRC48SEL = 3 << nxp.SIM_SOPT2_PLLFLLSEL_Pos + _SMC_PMCTRL_HSRUN = 3 << nxp.SMC_PMCTRL_RUNM_Pos + _SMC_PMSTAT_HSRUN = 0x80 << nxp.SMC_PMSTAT_PMSTAT_Pos ) -var bootMsg = []byte("\r\n\r\nStartup complete, running main\r\n\r\n") - -//go:section .resetHandler //go:export Reset_Handler func main() { initSystem() arm.Asm("CPSIE i") initInternal() - startupLateHook() - - initAll() - machine.UART1.Configure(machine.UARTConfig{BaudRate: 115200}) - for _, c := range bootMsg { - for !machine.UART1.S1.HasBits(nxp.UART_S1_TDRE) { - } - machine.UART1.D.Set(c) - } - callMain() + run() abort() } -// ported ResetHandler from mk20dx128.c from teensy3 core libraries -//go:noinline func initSystem() { - nxp.WDOG.UNLOCK.Set(WDOG_UNLOCK_SEQ1) - nxp.WDOG.UNLOCK.Set(WDOG_UNLOCK_SEQ2) + // from: ResetHandler + + nxp.WDOG.UNLOCK.Set(watchdogUnlockSequence1) + nxp.WDOG.UNLOCK.Set(watchdogUnlockSequence2) arm.Asm("nop") arm.Asm("nop") - startupEarlyHook() + // TODO: hook for overriding? 'startupEarlyHook' + nxp.WDOG.STCTRLH.Set(nxp.WDOG_STCTRLH_ALLOWUPDATE) // enable clocks to always-used peripherals nxp.SIM.SCGC3.Set(nxp.SIM_SCGC3_ADC1 | nxp.SIM_SCGC3_FTM2 | nxp.SIM_SCGC3_FTM3) @@ -117,9 +105,9 @@ func initSystem() { // enable capacitors for crystal nxp.OSC.CR.Set(nxp.OSC_CR_SC8P | nxp.OSC_CR_SC2P | nxp.OSC_CR_ERCLKEN) // enable osc, 8-32 MHz range, low power mode - nxp.MCG.C2.Set(uint8(nxp.MCG_C2_RANGE(2) | nxp.MCG_C2_EREFS)) + nxp.MCG.C2.Set(uint8((2 << nxp.MCG_C2_RANGE_Pos) | nxp.MCG_C2_EREFS)) // switch to crystal as clock source, FLL input = 16 MHz / 512 - nxp.MCG.C1.Set(uint8(nxp.MCG_C1_CLKS(2) | nxp.MCG_C1_FRDIV(4))) + nxp.MCG.C1.Set(uint8((2 << nxp.MCG_C1_CLKS_Pos) | (4 << nxp.MCG_C1_FRDIV_Pos))) // wait for crystal oscillator to begin for !nxp.MCG.S.HasBits(nxp.MCG_S_OSCINIT0) { } @@ -127,7 +115,7 @@ func initSystem() { for nxp.MCG.S.HasBits(nxp.MCG_S_IREFST) { } // wait for MCGOUT to use oscillator - for (nxp.MCG.S.Get() & nxp.MCG_S_CLKST_Msk) != nxp.MCG_S_CLKST(2) { + for (nxp.MCG.S.Get() & nxp.MCG_S_CLKST_Msk) != (2 << nxp.MCG_S_CLKST_Pos) { } // now in FBE mode @@ -137,11 +125,11 @@ func initSystem() { // C6[PLLS] bit is written to 0 // C2[LP] is written to 0 // we need faster than the crystal, turn on the PLL (F_CPU > 120000000) - nxp.SMC.PMCTRL.Set(SMC_PMCTRL_HSRUN) // enter HSRUN mode - for nxp.SMC.PMSTAT.Get() != SMC_PMSTAT_HSRUN { + nxp.SMC.PMCTRL.Set(_SMC_PMCTRL_HSRUN) // enter HSRUN mode + for nxp.SMC.PMSTAT.Get() != _SMC_PMSTAT_HSRUN { } // wait for HSRUN - nxp.MCG.C5.Set(nxp.MCG_C5_PRDIV(1)) - nxp.MCG.C6.Set(nxp.MCG_C6_PLLS | nxp.MCG_C6_VDIV(29)) + nxp.MCG.C5.Set((1 << nxp.MCG_C5_PRDIV_Pos)) + nxp.MCG.C6.Set(nxp.MCG_C6_PLLS | (29 << nxp.MCG_C6_VDIV_Pos)) // wait for PLL to start using xtal as its input for !nxp.MCG.S.HasBits(nxp.MCG_S_PLLST) { @@ -153,18 +141,18 @@ func initSystem() { // now program the clock dividers // config divisors: 180 MHz core, 60 MHz bus, 25.7 MHz flash, USB = IRC48M - nxp.SIM.CLKDIV1.Set(nxp.SIM_CLKDIV1_OUTDIV1(0) | nxp.SIM_CLKDIV1_OUTDIV2(2) | nxp.SIM_CLKDIV1_OUTDIV4(6)) - nxp.SIM.CLKDIV2.Set(nxp.SIM_CLKDIV2_USBDIV(0)) + nxp.SIM.CLKDIV1.Set((0 << nxp.SIM_CLKDIV1_OUTDIV1_Pos) | (2 << nxp.SIM_CLKDIV1_OUTDIV2_Pos) | (0 << nxp.SIM_CLKDIV1_OUTDIV1_Pos) | (6 << nxp.SIM_CLKDIV1_OUTDIV4_Pos)) + nxp.SIM.CLKDIV2.Set((0 << nxp.SIM_CLKDIV2_USBDIV_Pos)) // switch to PLL as clock source, FLL input = 16 MHz / 512 - nxp.MCG.C1.Set(nxp.MCG_C1_CLKS(0) | nxp.MCG_C1_FRDIV(4)) + nxp.MCG.C1.Set((0 << nxp.MCG_C1_CLKS_Pos) | (4 << nxp.MCG_C1_FRDIV_Pos)) // wait for PLL clock to be used - for (nxp.MCG.S.Get() & nxp.MCG_S_CLKST_Msk) != nxp.MCG_S_CLKST(3) { + for (nxp.MCG.S.Get() & nxp.MCG_S_CLKST_Msk) != (3 << nxp.MCG_S_CLKST_Pos) { } // now we're in PEE mode // trace is CPU clock, CLKOUT=OSCERCLK0 // USB uses IRC48 - nxp.SIM.SOPT2.Set(nxp.SIM_SOPT2_USBSRC | SIM_SOPT2_IRC48SEL | nxp.SIM_SOPT2_TRACECLKSEL | nxp.SIM_SOPT2_CLKOUTSEL(6)) + nxp.SIM.SOPT2.Set(nxp.SIM_SOPT2_USBSRC | _SIM_SOPT2_IRC48SEL | nxp.SIM_SOPT2_TRACECLKSEL | (6 << nxp.SIM_SOPT2_CLKOUTSEL_Pos)) // If the RTC oscillator isn't enabled, get it started. For Teensy 3.6 // we don't do this early. See comment above about slow rising power. @@ -174,23 +162,19 @@ func initSystem() { } // initialize the SysTick counter - nxp.SysTick.RVR.Set((machine.CPUFrequency() / 1000) - 1) - nxp.SysTick.CVR.Set(0) - nxp.SysTick.CSR.Set(nxp.SysTick_CSR_CLKSOURCE | nxp.SysTick_CSR_TICKINT | nxp.SysTick_CSR_ENABLE) - nxp.SystemControl.SHPR3.Set(0x20200000) // Systick = priority 32 + initSysTick() } -// ported _init_Teensyduino_internal_ from pins_teensy.c from teensy3 core libraries -//go:noinline func initInternal() { - arm.EnableIRQ(nxp.IRQ_PORTA) - arm.EnableIRQ(nxp.IRQ_PORTB) - arm.EnableIRQ(nxp.IRQ_PORTC) - arm.EnableIRQ(nxp.IRQ_PORTD) - arm.EnableIRQ(nxp.IRQ_PORTE) + // from: _init_Teensyduino_internal_ + // arm.EnableIRQ(nxp.IRQ_PORTA) + // arm.EnableIRQ(nxp.IRQ_PORTB) + // arm.EnableIRQ(nxp.IRQ_PORTC) + // arm.EnableIRQ(nxp.IRQ_PORTD) + // arm.EnableIRQ(nxp.IRQ_PORTE) nxp.FTM0.CNT.Set(0) - nxp.FTM0.MOD.Set(DEFAULT_FTM_MOD) + nxp.FTM0.MOD.Set(_DEFAULT_FTM_MOD) nxp.FTM0.C0SC.Set(0x28) // MSnB:MSnA = 10, ELSnB:ELSnA = 10 nxp.FTM0.C1SC.Set(0x28) nxp.FTM0.C2SC.Set(0x28) @@ -209,145 +193,45 @@ func initInternal() { nxp.FTM3.C6SC.Set(0x28) nxp.FTM3.C7SC.Set(0x28) - nxp.FTM0.SC.Set(nxp.FTM_SC_CLKS(1) | nxp.FTM_SC_PS(DEFAULT_FTM_PRESCALE)) + nxp.FTM0.SC.Set((1 << nxp.FTM_SC_CLKS_Pos) | (_DEFAULT_FTM_PRESCALE << nxp.FTM_SC_PS_Pos)) nxp.FTM1.CNT.Set(0) - nxp.FTM1.MOD.Set(DEFAULT_FTM_MOD) + nxp.FTM1.MOD.Set(_DEFAULT_FTM_MOD) nxp.FTM1.C0SC.Set(0x28) nxp.FTM1.C1SC.Set(0x28) - nxp.FTM1.SC.Set(nxp.FTM_SC_CLKS(1) | nxp.FTM_SC_PS(DEFAULT_FTM_PRESCALE)) + nxp.FTM1.SC.Set((1 << nxp.FTM_SC_CLKS_Pos) | (_DEFAULT_FTM_PRESCALE << nxp.FTM_SC_PS_Pos)) + // causes a data bus error for unknown reasons // nxp.FTM2.CNT.Set(0) - // nxp.FTM2.MOD.Set(DEFAULT_FTM_MOD) + // nxp.FTM2.MOD.Set(_DEFAULT_FTM_MOD) // nxp.FTM2.C0SC.Set(0x28) // nxp.FTM2.C1SC.Set(0x28) - // nxp.FTM2.SC.Set(nxp.FTM_SC_CLKS(1) | nxp.FTM_SC_PS(DEFAULT_FTM_PRESCALE)) + // nxp.FTM2.SC.Set((1 << nxp.FTM_SC_CLKS_Pos) | (_DEFAULT_FTM_PRESCALE << nxp.FTM_SC_PS_Pos)) nxp.FTM3.CNT.Set(0) - nxp.FTM3.MOD.Set(DEFAULT_FTM_MOD) + nxp.FTM3.MOD.Set(_DEFAULT_FTM_MOD) nxp.FTM3.C0SC.Set(0x28) nxp.FTM3.C1SC.Set(0x28) - nxp.FTM3.SC.Set(nxp.FTM_SC_CLKS(1) | nxp.FTM_SC_PS(DEFAULT_FTM_PRESCALE)) + nxp.FTM3.SC.Set((1 << nxp.FTM_SC_CLKS_Pos) | (_DEFAULT_FTM_PRESCALE << nxp.FTM_SC_PS_Pos)) nxp.SIM.SCGC2.SetBits(nxp.SIM_SCGC2_TPM1) - nxp.SIM.SOPT2.SetBits(nxp.SIM_SOPT2_TPMSRC(2)) + nxp.SIM.SOPT2.SetBits((2 << nxp.SIM_SOPT2_TPMSRC_Pos)) nxp.TPM1.CNT.Set(0) nxp.TPM1.MOD.Set(32767) nxp.TPM1.C0SC.Set(0x28) nxp.TPM1.C1SC.Set(0x28) - nxp.TPM1.SC.Set(nxp.FTM_SC_CLKS(1) | nxp.FTM_SC_PS(0)) + nxp.TPM1.SC.Set((1 << nxp.FTM_SC_CLKS_Pos) | (0 << nxp.FTM_SC_PS_Pos)) - // configure the low-power timer - // nxp.LPTMR0.CSR.Set(nxp.LPTMR0_CSR_TIE) - // nxp.LPTMR0.PSR.Set(nxp.LPTMR0_PSR_PCS(3) | nxp.LPTMR0_PSR_PRESCALE(1)) // use main (external) clock, divided by 4 - // arm.EnableIRQ(nxp.IRQ_LPTMR0) + // configure the sleep timer + initSleepTimer() // analog_init(); - - // #if !defined(TEENSY_INIT_USB_DELAY_BEFORE) - // #if TEENSYDUINO >= 142 - // #define TEENSY_INIT_USB_DELAY_BEFORE 25 - // #else - // #define TEENSY_INIT_USB_DELAY_BEFORE 50 - // #endif - // #endif - - // #if !defined(TEENSY_INIT_USB_DELAY_AFTER) - // #if TEENSYDUINO >= 142 - // #define TEENSY_INIT_USB_DELAY_AFTER 275 - // #else - // #define TEENSY_INIT_USB_DELAY_AFTER 350 - // #endif - // #endif - - // // for background about this startup delay, please see these conversations - // // https://forum.pjrc.com/threads/36606-startup-time-(400ms)?p=113980&viewfull=1#post113980 - // // https://forum.pjrc.com/threads/31290-Teensey-3-2-Teensey-Loader-1-24-Issues?p=87273&viewfull=1#post87273 - - // delay(TEENSY_INIT_USB_DELAY_BEFORE); - // usb_init(); - // delay(TEENSY_INIT_USB_DELAY_AFTER); } -func startupEarlyHook() { - // TODO allow override - // > programs using the watchdog timer or needing to initialize hardware as - // > early as possible can implement startup_early_hook() - - nxp.WDOG.STCTRLH.Set(nxp.WDOG_STCTRLH_ALLOWUPDATE) -} - -func startupLateHook() { - // TODO allow override -} +func postinit() {} func putchar(c byte) { - machine.UART1.WriteByte(c) + machine.PutcharUART(&machine.UART0, c) } // ??? const asyncScheduler = false - -// microseconds per tick -const tickMicros = 1000 - -// number of ticks since boot -var tickMilliCount volatile.Register32 - -//go:export SysTick_Handler -func tickHandler() { - tickMilliCount.Set(tickMilliCount.Get() + 1) -} - -// ticks are in microseconds -func ticks() timeUnit { - m := arm.DisableInterrupts() - current := nxp.SysTick.CVR.Get() - count := tickMilliCount.Get() - istatus := nxp.SystemControl.ICSR.Get() - arm.EnableInterrupts(m) - - if istatus&nxp.SystemControl_ICSR_PENDSTSET != 0 && current > 50 { - count++ - } - - current = ((machine.CPUFrequency() / tickMicros) - 1) - current - return timeUnit(count*tickMicros + current/(machine.CPUFrequency()/1000000)) -} - -// sleepTicks spins for a number of microseconds -func sleepTicks(d timeUnit) { - // TODO actually sleep - - if d <= 0 { - return - } - - start := ticks() - ms := d / 1000 - - for { - for ticks()-start >= 1000 { - ms-- - if ms <= 0 { - return - } - start += 1000 - } - arm.Asm("wfi") - } -} - -func Sleep(d int64) { - sleepTicks(timeUnit(d)) -} - -// func abort() { -// for { -// // keep polling some communication while in fault -// // mode, so we don't completely die. -// if nxp.SIM.SCGC4.HasBits(nxp.SIM_SCGC4_USBOTG) usb_isr(); -// if nxp.SIM.SCGC4.HasBits(nxp.SIM_SCGC4_UART0) uart0_status_isr(); -// if nxp.SIM.SCGC4.HasBits(nxp.SIM_SCGC4_UART1) uart1_status_isr(); -// if nxp.SIM.SCGC4.HasBits(nxp.SIM_SCGC4_UART2) uart2_status_isr(); -// } -// } |