Minimal NXP/Teensy support
Этот коммит содержится в:
родитель
ca8e1b075a
коммит
079a789d49
12 изменённых файлов: 754 добавлений и 8 удалений
2
.gitignore
предоставленный
2
.gitignore
предоставленный
|
@ -5,6 +5,8 @@ src/device/avr/*.ld
|
||||||
src/device/avr/*.s
|
src/device/avr/*.s
|
||||||
src/device/nrf/*.go
|
src/device/nrf/*.go
|
||||||
src/device/nrf/*.s
|
src/device/nrf/*.s
|
||||||
|
src/device/nxp/*.go
|
||||||
|
src/device/nxp/*.s
|
||||||
src/device/sam/*.go
|
src/device/sam/*.go
|
||||||
src/device/sam/*.s
|
src/device/sam/*.s
|
||||||
src/device/sifive/*.go
|
src/device/sifive/*.go
|
||||||
|
|
8
Makefile
8
Makefile
|
@ -51,7 +51,7 @@ else
|
||||||
LLVM_OPTION += '-DLLVM_ENABLE_ASSERTIONS=OFF'
|
LLVM_OPTION += '-DLLVM_ENABLE_ASSERTIONS=OFF'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: all tinygo test $(LLVM_BUILDDIR) llvm-source clean fmt gen-device gen-device-nrf gen-device-avr
|
.PHONY: all tinygo test $(LLVM_BUILDDIR) llvm-source clean fmt gen-device gen-device-nrf gen-device-nxp gen-device-avr
|
||||||
|
|
||||||
LLVM_COMPONENTS = all-targets analysis asmparser asmprinter bitreader bitwriter codegen core coroutines coverage debuginfodwarf executionengine frontendopenmp instrumentation interpreter ipo irreader linker lto mc mcjit objcarcopts option profiledata scalaropts support target
|
LLVM_COMPONENTS = all-targets analysis asmparser asmprinter bitreader bitwriter codegen core coroutines coverage debuginfodwarf executionengine frontendopenmp instrumentation interpreter ipo irreader linker lto mc mcjit objcarcopts option profiledata scalaropts support target
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ fmt-check:
|
||||||
@unformatted=$$(gofmt -l $(FMT_PATHS)); [ -z "$$unformatted" ] && exit 0; echo "Unformatted:"; for fn in $$unformatted; do echo " $$fn"; done; exit 1
|
@unformatted=$$(gofmt -l $(FMT_PATHS)); [ -z "$$unformatted" ] && exit 0; echo "Unformatted:"; for fn in $$unformatted; do echo " $$fn"; done; exit 1
|
||||||
|
|
||||||
|
|
||||||
gen-device: gen-device-avr gen-device-nrf gen-device-sam gen-device-sifive gen-device-stm32 gen-device-kendryte
|
gen-device: gen-device-avr gen-device-nrf gen-device-sam gen-device-sifive gen-device-stm32 gen-device-kendryte gen-device-nxp
|
||||||
|
|
||||||
gen-device-avr:
|
gen-device-avr:
|
||||||
$(GO) build -o ./build/gen-device-avr ./tools/gen-device-avr/
|
$(GO) build -o ./build/gen-device-avr ./tools/gen-device-avr/
|
||||||
|
@ -133,6 +133,10 @@ gen-device-nrf: build/gen-device-svd
|
||||||
./build/gen-device-svd -source=https://github.com/NordicSemiconductor/nrfx/tree/master/mdk lib/nrfx/mdk/ src/device/nrf/
|
./build/gen-device-svd -source=https://github.com/NordicSemiconductor/nrfx/tree/master/mdk lib/nrfx/mdk/ src/device/nrf/
|
||||||
GO111MODULE=off $(GO) fmt ./src/device/nrf
|
GO111MODULE=off $(GO) fmt ./src/device/nrf
|
||||||
|
|
||||||
|
gen-device-nxp: build/gen-device-svd
|
||||||
|
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/NXP lib/cmsis-svd/data/NXP/ src/device/nxp/
|
||||||
|
GO111MODULE=off $(GO) fmt ./src/device/nxp
|
||||||
|
|
||||||
gen-device-sam: build/gen-device-svd
|
gen-device-sam: build/gen-device-svd
|
||||||
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/Atmel lib/cmsis-svd/data/Atmel/ src/device/sam/
|
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/Atmel lib/cmsis-svd/data/Atmel/ src/device/sam/
|
||||||
GO111MODULE=off $(GO) fmt ./src/device/sam
|
GO111MODULE=off $(GO) fmt ./src/device/sam
|
||||||
|
|
|
@ -140,3 +140,5 @@ The original reasoning was: if [Python](https://micropython.org/) can run on mic
|
||||||
This project is licensed under the BSD 3-clause license, just like the [Go project](https://golang.org/LICENSE) itself.
|
This project is licensed under the BSD 3-clause license, just like the [Go project](https://golang.org/LICENSE) itself.
|
||||||
|
|
||||||
Some code has been copied from the LLVM project and is therefore licensed under [a variant of the Apache 2.0 license](http://releases.llvm.org/10.0.0/LICENSE.TXT). This has been clearly indicated in the header of these files.
|
Some code has been copied from the LLVM project and is therefore licensed under [a variant of the Apache 2.0 license](http://releases.llvm.org/10.0.0/LICENSE.TXT). This has been clearly indicated in the header of these files.
|
||||||
|
|
||||||
|
Some code has been copied and/or ported from Paul Stoffregen's Teensy libraries and is therefore licensed under PJRC's license. This has been clearly indicated in the header of these files.
|
||||||
|
|
39
src/machine/board_teensy36.go
Обычный файл
39
src/machine/board_teensy36.go
Обычный файл
|
@ -0,0 +1,39 @@
|
||||||
|
// +build nxp,mk66f18,teensy36
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/nxp"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:keep
|
||||||
|
//go:section .flashconfig
|
||||||
|
var FlashConfig = [16]byte{
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xDE, 0xF9, 0xFF, 0xFF,
|
||||||
|
}
|
||||||
|
|
||||||
|
func CPUFrequency() uint32 {
|
||||||
|
return 180000000
|
||||||
|
}
|
||||||
|
|
||||||
|
// LED on the Teensy
|
||||||
|
const LED Pin = 13
|
||||||
|
|
||||||
|
var _pinRegisters [64]pinRegisters
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
_pinRegisters[13].Bit = 5
|
||||||
|
_pinRegisters[13].PCR = &nxp.PORTC.PCR5
|
||||||
|
_pinRegisters[13].PDOR = nxp.GPIOC.PDOR.Bit(5)
|
||||||
|
_pinRegisters[13].PSOR = nxp.GPIOC.PSOR.Bit(5)
|
||||||
|
_pinRegisters[13].PCOR = nxp.GPIOC.PCOR.Bit(5)
|
||||||
|
_pinRegisters[13].PTOR = nxp.GPIOC.PTOR.Bit(5)
|
||||||
|
_pinRegisters[13].PDIR = nxp.GPIOC.PDIR.Bit(5)
|
||||||
|
_pinRegisters[13].PDDR = nxp.GPIOC.PDDR.Bit(5)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:inline
|
||||||
|
func (p Pin) registers() pinRegisters {
|
||||||
|
return _pinRegisters[p]
|
||||||
|
}
|
33
src/machine/machine_nxp.go
Обычный файл
33
src/machine/machine_nxp.go
Обычный файл
|
@ -0,0 +1,33 @@
|
||||||
|
// +build nxp
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/arm"
|
||||||
|
"device/nxp"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PinMode uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
PinInput PinMode = iota
|
||||||
|
PinOutput
|
||||||
|
)
|
||||||
|
|
||||||
|
// Stop enters STOP (deep sleep) mode
|
||||||
|
func Stop() {
|
||||||
|
// set SLEEPDEEP to enable deep sleep
|
||||||
|
nxp.SystemControl.SCR.SetBits(nxp.SystemControl_SCR_SLEEPDEEP)
|
||||||
|
|
||||||
|
// enter STOP mode
|
||||||
|
arm.Asm("wfi")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait enters WAIT (sleep) mode
|
||||||
|
func Wait() {
|
||||||
|
// clear SLEEPDEEP bit to disable deep sleep
|
||||||
|
nxp.SystemControl.SCR.ClearBits(nxp.SystemControl_SCR_SLEEPDEEP)
|
||||||
|
|
||||||
|
// enter WAIT mode
|
||||||
|
arm.Asm("wfi")
|
||||||
|
}
|
56
src/machine/machine_nxpmk66f18.go
Обычный файл
56
src/machine/machine_nxpmk66f18.go
Обычный файл
|
@ -0,0 +1,56 @@
|
||||||
|
// +build nxp,mk66f18
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/nxp"
|
||||||
|
"runtime/volatile"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
PortControlRegisterSRE = nxp.PORT_PCR0_SRE
|
||||||
|
PortControlRegisterDSE = nxp.PORT_PCR0_DSE
|
||||||
|
PortControlRegisterODE = nxp.PORT_PCR0_ODE
|
||||||
|
)
|
||||||
|
|
||||||
|
func PortControlRegisterMUX(v uint8) uint32 {
|
||||||
|
return (uint32(v) << nxp.PORT_PCR0_MUX_Pos) & nxp.PORT_PCR0_MUX_Msk
|
||||||
|
}
|
||||||
|
|
||||||
|
type pinRegisters struct {
|
||||||
|
Bit uintptr
|
||||||
|
PCR *volatile.Register32
|
||||||
|
PDOR *volatile.BitRegister
|
||||||
|
PSOR *volatile.BitRegister
|
||||||
|
PCOR *volatile.BitRegister
|
||||||
|
PTOR *volatile.BitRegister
|
||||||
|
PDIR *volatile.BitRegister
|
||||||
|
PDDR *volatile.BitRegister
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure this pin with the given configuration.
|
||||||
|
func (p Pin) Configure(config PinConfig) {
|
||||||
|
switch config.Mode {
|
||||||
|
case PinInput:
|
||||||
|
panic("todo")
|
||||||
|
|
||||||
|
case PinOutput:
|
||||||
|
p.registers().PDDR.Set()
|
||||||
|
p.registers().PCR.SetBits(PortControlRegisterSRE | PortControlRegisterDSE | PortControlRegisterMUX(1))
|
||||||
|
p.registers().PCR.ClearBits(PortControlRegisterODE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set changes the value of the GPIO pin. The pin must be configured as output.
|
||||||
|
func (p Pin) Set(value bool) {
|
||||||
|
if value {
|
||||||
|
p.registers().PSOR.Set()
|
||||||
|
} else {
|
||||||
|
p.registers().PCOR.Set()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the current value of a GPIO pin.
|
||||||
|
func (p Pin) Get() bool {
|
||||||
|
return p.registers().PDIR.Get()
|
||||||
|
}
|
5
src/runtime/runtime_nxp.go
Обычный файл
5
src/runtime/runtime_nxp.go
Обычный файл
|
@ -0,0 +1,5 @@
|
||||||
|
// +build nxp
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
type timeUnit int64
|
342
src/runtime/runtime_nxpmk66f18.go
Обычный файл
342
src/runtime/runtime_nxpmk66f18.go
Обычный файл
|
@ -0,0 +1,342 @@
|
||||||
|
// Derivative work of Teensyduino Core Library
|
||||||
|
// http://www.pjrc.com/teensy/
|
||||||
|
// Copyright (c) 2017 PJRC.COM, LLC.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
// a copy of this software and associated documentation files (the
|
||||||
|
// "Software"), to deal in the Software without restriction, including
|
||||||
|
// without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
// permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
// the following conditions:
|
||||||
|
//
|
||||||
|
// 1. The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// 2. If the Software is incorporated into a build system that allows
|
||||||
|
// selection among a list of target devices, then similar target
|
||||||
|
// devices manufactured by PJRC.COM must be included in the list of
|
||||||
|
// target devices and selectable in the same manner.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
// +build nxp,mk66f18
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/arm"
|
||||||
|
"device/nxp"
|
||||||
|
"machine"
|
||||||
|
"runtime/volatile"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
WDOG_UNLOCK_SEQ1 = 0xC520
|
||||||
|
WDOG_UNLOCK_SEQ2 = 0xD928
|
||||||
|
|
||||||
|
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)
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:section .resetHandler
|
||||||
|
//go:export Reset_Handler
|
||||||
|
func main() {
|
||||||
|
nxp.WDOG.UNLOCK.Set(WDOG_UNLOCK_SEQ1)
|
||||||
|
nxp.WDOG.UNLOCK.Set(WDOG_UNLOCK_SEQ2)
|
||||||
|
arm.Asm("nop")
|
||||||
|
arm.Asm("nop")
|
||||||
|
startupEarlyHook()
|
||||||
|
|
||||||
|
// enable clocks to always-used peripherals
|
||||||
|
nxp.SIM.SCGC3.Set(nxp.SIM_SCGC3_ADC1 | nxp.SIM_SCGC3_FTM2 | nxp.SIM_SCGC3_FTM3)
|
||||||
|
nxp.SIM.SCGC5.Set(0x00043F82) // clocks active to all GPIO
|
||||||
|
nxp.SIM.SCGC6.Set(nxp.SIM_SCGC6_RTC | nxp.SIM_SCGC6_FTM0 | nxp.SIM_SCGC6_FTM1 | nxp.SIM_SCGC6_ADC0 | nxp.SIM_SCGC6_FTF)
|
||||||
|
nxp.SystemControl.CPACR.Set(0x00F00000)
|
||||||
|
nxp.LMEM.PCCCR.Set(0x85000003)
|
||||||
|
|
||||||
|
// release I/O pins hold, if we woke up from VLLS mode
|
||||||
|
if nxp.PMC.REGSC.HasBits(nxp.PMC_REGSC_ACKISO) {
|
||||||
|
nxp.PMC.REGSC.SetBits(nxp.PMC_REGSC_ACKISO)
|
||||||
|
}
|
||||||
|
|
||||||
|
// since this is a write once register, make it visible to all F_CPU's
|
||||||
|
// so we can into other sleep modes in the future at any speed
|
||||||
|
nxp.SMC.PMPROT.Set(nxp.SMC_PMPROT_AHSRUN | nxp.SMC_PMPROT_AVLP | nxp.SMC_PMPROT_ALLS | nxp.SMC_PMPROT_AVLLS)
|
||||||
|
|
||||||
|
preinit()
|
||||||
|
|
||||||
|
// copy the vector table to RAM default all interrupts to medium priority level
|
||||||
|
// for (i=0; i < NVIC_NUM_INTERRUPTS + 16; i++) _VectorsRam[i] = _VectorsFlash[i];
|
||||||
|
for i := uint32(0); i <= nxp.IRQ_max; i++ {
|
||||||
|
arm.SetPriority(i, 128)
|
||||||
|
}
|
||||||
|
// SCB_VTOR = (uint32_t)_VectorsRam; // use vector table in RAM
|
||||||
|
|
||||||
|
// hardware always starts in FEI mode
|
||||||
|
// C1[CLKS] bits are written to 00
|
||||||
|
// C1[IREFS] bit is written to 1
|
||||||
|
// C6[PLLS] bit is written to 0
|
||||||
|
// MCG_SC[FCDIV] defaults to divide by two for internal ref clock
|
||||||
|
// I tried changing MSG_SC to divide by 1, it didn't work for me
|
||||||
|
// 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))
|
||||||
|
// 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)))
|
||||||
|
// wait for crystal oscillator to begin
|
||||||
|
for !nxp.MCG.S.HasBits(nxp.MCG_S_OSCINIT0) {
|
||||||
|
}
|
||||||
|
// wait for FLL to use oscillator
|
||||||
|
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) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// now in FBE mode
|
||||||
|
// C1[CLKS] bits are written to 10
|
||||||
|
// C1[IREFS] bit is written to 0
|
||||||
|
// C1[FRDIV] must be written to divide xtal to 31.25-39 kHz
|
||||||
|
// 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 {
|
||||||
|
} // 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))
|
||||||
|
|
||||||
|
// wait for PLL to start using xtal as its input
|
||||||
|
for !nxp.MCG.S.HasBits(nxp.MCG_S_PLLST) {
|
||||||
|
}
|
||||||
|
// wait for PLL to lock
|
||||||
|
for !nxp.MCG.S.HasBits(nxp.MCG_S_LOCK0) {
|
||||||
|
}
|
||||||
|
// now we're in PBE mode
|
||||||
|
|
||||||
|
// 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))
|
||||||
|
|
||||||
|
// 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))
|
||||||
|
// wait for PLL clock to be used
|
||||||
|
for (nxp.MCG.S.Get() & nxp.MCG_S_CLKST_Msk) != nxp.MCG_S_CLKST(3) {
|
||||||
|
}
|
||||||
|
// 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))
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
if !nxp.RTC.CR.HasBits(nxp.RTC_CR_OSCE) {
|
||||||
|
nxp.RTC.SR.Set(0)
|
||||||
|
nxp.RTC.CR.Set(nxp.RTC_CR_SC16P | nxp.RTC_CR_SC4P | nxp.RTC_CR_OSCE)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
arm.Asm("CPSIE i")
|
||||||
|
initTeensyInternal()
|
||||||
|
startupLateHook()
|
||||||
|
|
||||||
|
// initAll()
|
||||||
|
runMain()
|
||||||
|
// abort()
|
||||||
|
|
||||||
|
for {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ported _init_Teensyduino_internal_ from pins_teensy.c from teensy3 core libraries
|
||||||
|
func initTeensyInternal() {
|
||||||
|
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.C0SC.Set(0x28) // MSnB:MSnA = 10, ELSnB:ELSnA = 10
|
||||||
|
nxp.FTM0.C1SC.Set(0x28)
|
||||||
|
nxp.FTM0.C2SC.Set(0x28)
|
||||||
|
nxp.FTM0.C3SC.Set(0x28)
|
||||||
|
nxp.FTM0.C4SC.Set(0x28)
|
||||||
|
nxp.FTM0.C5SC.Set(0x28)
|
||||||
|
nxp.FTM0.C6SC.Set(0x28)
|
||||||
|
nxp.FTM0.C7SC.Set(0x28)
|
||||||
|
|
||||||
|
nxp.FTM3.C0SC.Set(0x28)
|
||||||
|
nxp.FTM3.C1SC.Set(0x28)
|
||||||
|
nxp.FTM3.C2SC.Set(0x28)
|
||||||
|
nxp.FTM3.C3SC.Set(0x28)
|
||||||
|
nxp.FTM3.C4SC.Set(0x28)
|
||||||
|
nxp.FTM3.C5SC.Set(0x28)
|
||||||
|
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.FTM1.CNT.Set(0)
|
||||||
|
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.FTM2.CNT.Set(0)
|
||||||
|
// 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.FTM3.CNT.Set(0)
|
||||||
|
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.SIM.SCGC2.SetBits(nxp.SIM_SCGC2_TPM1)
|
||||||
|
nxp.SIM.SOPT2.SetBits(nxp.SIM_SOPT2_TPMSRC(2))
|
||||||
|
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))
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func runMain() {
|
||||||
|
// this is a separate function to ensure that Reset_Handler fits in 0x230 bytes regardless of whether (user) main requires scheduling
|
||||||
|
callMain()
|
||||||
|
}
|
||||||
|
|
||||||
|
func putchar(c byte) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// ???
|
||||||
|
const asyncScheduler = false
|
||||||
|
|
||||||
|
// microseconds per tick
|
||||||
|
const tickMicros = 1000
|
||||||
|
|
||||||
|
// number of ticks since boot
|
||||||
|
var tickMilliCount uint32
|
||||||
|
|
||||||
|
//go:export SysTick_Handler
|
||||||
|
func tickHandler() {
|
||||||
|
volatile.StoreUint32(&tickMilliCount, volatile.LoadUint32(&tickMilliCount)+1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ticks are in microseconds
|
||||||
|
func ticks() timeUnit {
|
||||||
|
m := arm.DisableInterrupts()
|
||||||
|
current := nxp.SysTick.CVR.Get()
|
||||||
|
count := tickMilliCount
|
||||||
|
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
|
||||||
|
}
|
||||||
|
// Gosched()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
// }
|
||||||
|
// }
|
84
src/runtime/volatile/register_nxpmk66f18.go
Обычный файл
84
src/runtime/volatile/register_nxpmk66f18.go
Обычный файл
|
@ -0,0 +1,84 @@
|
||||||
|
// +build nxp,mk66f18
|
||||||
|
|
||||||
|
package volatile
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
const registerBase = 0x40000000
|
||||||
|
const registerEnd = 0x40100000
|
||||||
|
const bitbandBase = 0x42000000
|
||||||
|
const ptrBytes = unsafe.Sizeof(uintptr(0))
|
||||||
|
|
||||||
|
//go:inline
|
||||||
|
func bitbandAddress(reg uintptr, bit uintptr) uintptr {
|
||||||
|
if bit > ptrBytes*8 {
|
||||||
|
panic("invalid bit position")
|
||||||
|
}
|
||||||
|
if reg < registerBase || reg >= registerEnd {
|
||||||
|
panic("register is out of range")
|
||||||
|
}
|
||||||
|
return (reg-registerBase)*ptrBytes*8 + bit*ptrBytes + bitbandBase
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special types that causes loads/stores to be volatile (necessary for
|
||||||
|
// memory-mapped registers).
|
||||||
|
type BitRegister struct {
|
||||||
|
Reg uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the of the mapped register bit. It is the volatile equivalent of:
|
||||||
|
//
|
||||||
|
// *r.Reg
|
||||||
|
//
|
||||||
|
//go:inline
|
||||||
|
func (r *BitRegister) Get() bool {
|
||||||
|
return LoadUint32(&r.Reg) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets the mapped register bit. It is the volatile equivalent of:
|
||||||
|
//
|
||||||
|
// *r.Reg = 1
|
||||||
|
//
|
||||||
|
//go:inline
|
||||||
|
func (r *BitRegister) Set() {
|
||||||
|
StoreUint32(&r.Reg, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear clears the mapped register bit. It is the volatile equivalent of:
|
||||||
|
//
|
||||||
|
// *r.Reg = 0
|
||||||
|
//
|
||||||
|
//go:inline
|
||||||
|
func (r *BitRegister) Clear() {
|
||||||
|
StoreUint32(&r.Reg, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bit maps bit N of register R to the corresponding bitband address. Bit panics
|
||||||
|
// if R is not an AIPS or GPIO register or if N is out of range (greater than
|
||||||
|
// the number of bits in a register minus one).
|
||||||
|
//
|
||||||
|
// go:inline
|
||||||
|
func (r *Register8) Bit(bit uintptr) *BitRegister {
|
||||||
|
ptr := bitbandAddress(uintptr(unsafe.Pointer(&r.Reg)), bit)
|
||||||
|
return (*BitRegister)(unsafe.Pointer(ptr))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bit maps bit N of register R to the corresponding bitband address. Bit panics
|
||||||
|
// if R is not an AIPS or GPIO register or if N is out of range (greater than
|
||||||
|
// the number of bits in a register minus one).
|
||||||
|
//
|
||||||
|
// go:inline
|
||||||
|
func (r *Register16) Bit(bit uintptr) *BitRegister {
|
||||||
|
ptr := bitbandAddress(uintptr(unsafe.Pointer(&r.Reg)), bit)
|
||||||
|
return (*BitRegister)(unsafe.Pointer(ptr))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bit maps bit N of register R to the corresponding bitband address. Bit panics
|
||||||
|
// if R is not an AIPS or GPIO register or if N is out of range (greater than
|
||||||
|
// the number of bits in a register minus one).
|
||||||
|
//
|
||||||
|
// go:inline
|
||||||
|
func (r *Register32) Bit(bit uintptr) *BitRegister {
|
||||||
|
ptr := bitbandAddress(uintptr(unsafe.Pointer(&r.Reg)), bit)
|
||||||
|
return (*BitRegister)(unsafe.Pointer(ptr))
|
||||||
|
}
|
94
targets/nxpmk66f18.ld
Обычный файл
94
targets/nxpmk66f18.ld
Обычный файл
|
@ -0,0 +1,94 @@
|
||||||
|
|
||||||
|
/* Unused, but here to silence a linker warning. */
|
||||||
|
ENTRY(Reset_Handler)
|
||||||
|
|
||||||
|
/* define memory layout */
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
FLASH_TEXT (rx) : ORIGIN = 0x00000000, LENGTH = 1024K
|
||||||
|
RAM (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 256K
|
||||||
|
}
|
||||||
|
|
||||||
|
_stack_size = 2K;
|
||||||
|
|
||||||
|
/* define output sections */
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* Program code and read-only data goes to FLASH_TEXT. */
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
/* vector table MUST start at 0x0 */
|
||||||
|
. = 0;
|
||||||
|
_vector_table = .;
|
||||||
|
KEEP(*(.isr_vector))
|
||||||
|
|
||||||
|
/* this works as long as reset handler doesn't overflow past 0x400 */
|
||||||
|
*(.resetHandler)
|
||||||
|
|
||||||
|
/* flash configuration MUST be at 0x400 */
|
||||||
|
. = 0x400;
|
||||||
|
KEEP(*(.flashconfig))
|
||||||
|
|
||||||
|
/* everything else */
|
||||||
|
*(.text)
|
||||||
|
*(.text*)
|
||||||
|
*(.rodata)
|
||||||
|
*(.rodata*)
|
||||||
|
. = ALIGN(4);
|
||||||
|
} >FLASH_TEXT = 0xFF
|
||||||
|
|
||||||
|
/* Put the stack at the bottom of RAM, so that the application will
|
||||||
|
* crash on stack overflow instead of silently corrupting memory.
|
||||||
|
* See: http://blog.japaric.io/stack-overflow-protection/ */
|
||||||
|
.stack (NOLOAD) :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
. += _stack_size;
|
||||||
|
_stack_top = .;
|
||||||
|
} >RAM
|
||||||
|
|
||||||
|
/* Start address (in flash) of .data, used by startup code. */
|
||||||
|
_sidata = LOADADDR(.data);
|
||||||
|
|
||||||
|
/* todo add .usbdescriptortable .dmabuffers .usbbuffers */
|
||||||
|
|
||||||
|
/* Globals with initial value */
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
_sdata = .; /* used by startup code */
|
||||||
|
*(.data)
|
||||||
|
*(.data*)
|
||||||
|
. = ALIGN(4);
|
||||||
|
_edata = .; /* used by startup code */
|
||||||
|
} >RAM AT>FLASH_TEXT
|
||||||
|
|
||||||
|
/* Zero-initialized globals */
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
_sbss = .; /* used by startup code */
|
||||||
|
*(.bss)
|
||||||
|
*(.bss*)
|
||||||
|
*(COMMON)
|
||||||
|
. = ALIGN(4);
|
||||||
|
_ebss = .; /* used by startup code */
|
||||||
|
} >RAM
|
||||||
|
|
||||||
|
/DISCARD/ :
|
||||||
|
{
|
||||||
|
*(.ARM.exidx) /* causes 'no memory region specified' error in lld */
|
||||||
|
*(.ARM.exidx.*) /* causes spurious 'undefined reference' errors */
|
||||||
|
|
||||||
|
/* all this makes it much harder to debug via disassembly */
|
||||||
|
*(.debug*)
|
||||||
|
*(.ARM.*)
|
||||||
|
*(.comment*)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For the memory allocator. */
|
||||||
|
_heap_start = _ebss;
|
||||||
|
_heap_end = ORIGIN(RAM) + LENGTH(RAM);
|
||||||
|
_globals_start = _sdata;
|
||||||
|
_globals_end = _ebss;
|
18
targets/teensy36.json
Обычный файл
18
targets/teensy36.json
Обычный файл
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"inherits": ["cortex-m"],
|
||||||
|
"llvm-target": "armv7em-none-eabi",
|
||||||
|
"cpu": "cortex-m4",
|
||||||
|
"build-tags": ["teensy36", "teensy", "mk66f18", "nxp"],
|
||||||
|
"cflags": [
|
||||||
|
"--target=armv7em-none-eabi",
|
||||||
|
"-Qunused-arguments",
|
||||||
|
"-mfloat-abi=hard",
|
||||||
|
"-mfpu=fpv4-sp-d16"
|
||||||
|
],
|
||||||
|
"linkerscript": "targets/nxpmk66f18.ld",
|
||||||
|
"extra-files": [
|
||||||
|
"src/device/nxp/mk66f18.s"
|
||||||
|
],
|
||||||
|
"flash-command": "teensy_loader_cli -mmcu=mk66fx1m0 -v -w {hex}"
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var validName = regexp.MustCompile("^[a-zA-Z0-9_]+$")
|
var validName = regexp.MustCompile("^[a-zA-Z0-9_]+$")
|
||||||
|
var enumBitSpecifier = regexp.MustCompile("^#[x01]+$")
|
||||||
|
|
||||||
type SVDFile struct {
|
type SVDFile struct {
|
||||||
XMLName xml.Name `xml:"device"`
|
XMLName xml.Name `xml:"device"`
|
||||||
|
@ -41,6 +42,7 @@ type SVDRegister struct {
|
||||||
Name string `xml:"name"`
|
Name string `xml:"name"`
|
||||||
Description string `xml:"description"`
|
Description string `xml:"description"`
|
||||||
Dim *string `xml:"dim"`
|
Dim *string `xml:"dim"`
|
||||||
|
DimIndex *string `xml:"dimIndex"`
|
||||||
DimIncrement string `xml:"dimIncrement"`
|
DimIncrement string `xml:"dimIncrement"`
|
||||||
Size *string `xml:"size"`
|
Size *string `xml:"size"`
|
||||||
Fields []*SVDField `xml:"fields>field"`
|
Fields []*SVDField `xml:"fields>field"`
|
||||||
|
@ -484,13 +486,24 @@ func parseBitfields(groupName, regName string, fieldEls []*SVDField, bitfieldPre
|
||||||
}
|
}
|
||||||
for _, enumEl := range fieldEl.EnumeratedValues {
|
for _, enumEl := range fieldEl.EnumeratedValues {
|
||||||
enumName := enumEl.Name
|
enumName := enumEl.Name
|
||||||
|
if strings.EqualFold(enumName, "reserved") || !validName.MatchString(enumName) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if !unicode.IsUpper(rune(enumName[0])) && !unicode.IsDigit(rune(enumName[0])) {
|
if !unicode.IsUpper(rune(enumName[0])) && !unicode.IsDigit(rune(enumName[0])) {
|
||||||
enumName = strings.ToUpper(enumName)
|
enumName = strings.ToUpper(enumName)
|
||||||
}
|
}
|
||||||
enumDescription := strings.Replace(enumEl.Description, "\n", " ", -1)
|
enumDescription := strings.Replace(enumEl.Description, "\n", " ", -1)
|
||||||
enumValue, err := strconv.ParseUint(enumEl.Value, 0, 32)
|
enumValue, err := strconv.ParseUint(enumEl.Value, 0, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
if enumBitSpecifier.MatchString(enumEl.Value) {
|
||||||
|
// NXP SVDs use the form #xx1x, #x0xx, etc for values
|
||||||
|
enumValue, err = strconv.ParseUint(strings.Replace(enumEl.Value[1:], "x", "0", -1), 2, 32)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fields = append(fields, Bitfield{
|
fields = append(fields, Bitfield{
|
||||||
name: fmt.Sprintf("%s_%s%s_%s_%s", groupName, bitfieldPrefix, regName, fieldName, enumName),
|
name: fmt.Sprintf("%s_%s%s_%s_%s", groupName, bitfieldPrefix, regName, fieldName, enumName),
|
||||||
|
@ -545,6 +558,59 @@ func (r *Register) dim() int {
|
||||||
return int(dim)
|
return int(dim)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Register) dimIndex() []string {
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
fmt.Println("register", r.name())
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
dim := r.dim()
|
||||||
|
if r.element.DimIndex == nil {
|
||||||
|
if dim <= 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
idx := make([]string, dim)
|
||||||
|
for i := range idx {
|
||||||
|
idx[i] = strconv.FormatInt(int64(i), 10)
|
||||||
|
}
|
||||||
|
return idx
|
||||||
|
}
|
||||||
|
|
||||||
|
t := strings.Split(*r.element.DimIndex, "-")
|
||||||
|
if len(t) == 2 {
|
||||||
|
x, err := strconv.ParseInt(t[0], 0, 32)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
y, err := strconv.ParseInt(t[1], 0, 32)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if x < 0 || y < x || y-x != int64(dim-1) {
|
||||||
|
panic("invalid dimIndex")
|
||||||
|
}
|
||||||
|
|
||||||
|
idx := make([]string, dim)
|
||||||
|
for i := x; i <= y; i++ {
|
||||||
|
idx[i-x] = strconv.FormatInt(i, 10)
|
||||||
|
}
|
||||||
|
return idx
|
||||||
|
} else if len(t) > 2 {
|
||||||
|
panic("invalid dimIndex")
|
||||||
|
}
|
||||||
|
|
||||||
|
s := strings.Split(*r.element.DimIndex, ",")
|
||||||
|
if len(s) != dim {
|
||||||
|
panic("invalid dimIndex")
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Register) size() int {
|
func (r *Register) size() int {
|
||||||
if r.element.Size != nil {
|
if r.element.Size != nil {
|
||||||
size, err := strconv.ParseInt(*r.element.Size, 0, 32)
|
size, err := strconv.ParseInt(*r.element.Size, 0, 32)
|
||||||
|
@ -568,10 +634,10 @@ func parseRegister(groupName string, regEl *SVDRegister, baseAddress uint64, bit
|
||||||
// a "spaced array" of registers, special processing required
|
// a "spaced array" of registers, special processing required
|
||||||
// we need to generate a separate register for each "element"
|
// we need to generate a separate register for each "element"
|
||||||
var results []*PeripheralField
|
var results []*PeripheralField
|
||||||
for i := uint64(0); i < uint64(reg.dim()); i++ {
|
for i, j := range reg.dimIndex() {
|
||||||
regAddress := reg.address() + (i * dimIncrement)
|
regAddress := reg.address() + (uint64(i) * dimIncrement)
|
||||||
results = append(results, &PeripheralField{
|
results = append(results, &PeripheralField{
|
||||||
name: strings.ToUpper(strings.Replace(reg.name(), "%s", strconv.FormatUint(i, 10), -1)),
|
name: strings.ToUpper(strings.Replace(reg.name(), "%s", j, -1)),
|
||||||
address: regAddress,
|
address: regAddress,
|
||||||
description: reg.description(),
|
description: reg.description(),
|
||||||
array: -1,
|
array: -1,
|
||||||
|
@ -589,11 +655,12 @@ func parseRegister(groupName string, regEl *SVDRegister, baseAddress uint64, bit
|
||||||
regName = strings.ToUpper(regName)
|
regName = strings.ToUpper(regName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bitfields := parseBitfields(groupName, regName, regEl.Fields, bitfieldPrefix)
|
||||||
return []*PeripheralField{&PeripheralField{
|
return []*PeripheralField{&PeripheralField{
|
||||||
name: regName,
|
name: regName,
|
||||||
address: reg.address(),
|
address: reg.address(),
|
||||||
description: reg.description(),
|
description: reg.description(),
|
||||||
bitfields: parseBitfields(groupName, regName, regEl.Fields, bitfieldPrefix),
|
bitfields: bitfields,
|
||||||
array: reg.dim(),
|
array: reg.dim(),
|
||||||
elementSize: reg.size(),
|
elementSize: reg.size(),
|
||||||
}}
|
}}
|
||||||
|
@ -770,7 +837,7 @@ var (
|
||||||
if register.array != -1 {
|
if register.array != -1 {
|
||||||
regType = fmt.Sprintf("[%d]%s", register.array, regType)
|
regType = fmt.Sprintf("[%d]%s", register.array, regType)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(w, "\t%s %s\n", register.name, regType)
|
fmt.Fprintf(w, "\t%s %s // 0x%X\n", register.name, regType, register.address-peripheral.BaseAddress)
|
||||||
|
|
||||||
// next address
|
// next address
|
||||||
if lastCluster {
|
if lastCluster {
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче