aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/runtime/runtime_mimxrt1062.go
blob: a26c9b6e3ec23868b62291449bd7463f835f5406 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//go:build mimxrt1062

package runtime

import (
	"device/arm"
	"device/nxp"
	"machine"
	"math/bits"
	"unsafe"
)

//go:extern _svectors
var _svectors [0]byte

//go:extern _flexram_cfg
var _flexram_cfg [0]byte

//export Reset_Handler
func main() {

	// disable interrupts
	irq := arm.DisableInterrupts()

	// initialize FPU and VTOR, reset watchdogs
	initSystem()

	// configure core and peripheral clocks/PLLs/PFDs
	initClocks()

	// copy data/bss sections from flash to RAM
	preinit()

	// initialize cache and MPU
	initCache()

	// enable SysTick, GPIO, and peripherals
	initPeripherals()

	// reenable interrupts
	arm.EnableInterrupts(irq)

	run()
	exit(0)
}

func getRamSizeConfig(itcmKB, dtcmKB uint32) uint32 {
	const minKB, disabled = uint32(4), uint32(0)
	if itcmKB < minKB {
		itcmKB = disabled
	}
	if dtcmKB < minKB {
		dtcmKB = disabled
	}
	itcmKB = uint32(bits.Len(uint(itcmKB))) << nxp.IOMUXC_GPR_GPR14_CM7_CFGITCMSZ_Pos
	dtcmKB = uint32(bits.Len(uint(dtcmKB))) << nxp.IOMUXC_GPR_GPR14_CM7_CFGDTCMSZ_Pos
	return (itcmKB & nxp.IOMUXC_GPR_GPR14_CM7_CFGITCMSZ_Msk) |
		(dtcmKB & nxp.IOMUXC_GPR_GPR14_CM7_CFGDTCMSZ_Msk)
}

func initSystem() {

	// configure SRAM capacity (512K for both ITCM and DTCM)
	ramc := uintptr(unsafe.Pointer(&_flexram_cfg))
	nxp.IOMUXC_GPR.GPR17.Set(uint32(ramc))
	nxp.IOMUXC_GPR.GPR16.Set(0x00200007)
	nxp.IOMUXC_GPR.GPR14.Set(getRamSizeConfig(512, 512))

	// from Teensyduino
	nxp.PMU.MISC0_SET.Set(nxp.PMU_MISC0_REFTOP_SELFBIASOFF)

	// install vector table (TODO: initialize interrupt/exception table?)
	vtor := uintptr(unsafe.Pointer(&_svectors))
	nxp.SystemControl.VTOR.Set(uint32(vtor))

	const wdogUpdateKey = 0xD928C520

	// disable watchdog powerdown counter
	nxp.WDOG1.WMCR.ClearBits(nxp.WDOG_WMCR_PDE_Msk)
	nxp.WDOG2.WMCR.ClearBits(nxp.WDOG_WMCR_PDE_Msk)

	// disable watchdog
	if nxp.WDOG1.WCR.HasBits(nxp.WDOG_WCR_WDE_Msk) {
		nxp.WDOG1.WCR.ClearBits(nxp.WDOG_WCR_WDE_Msk)
	}
	if nxp.WDOG2.WCR.HasBits(nxp.WDOG_WCR_WDE_Msk) {
		nxp.WDOG2.WCR.ClearBits(nxp.WDOG_WCR_WDE_Msk)
	}
	if nxp.RTWDOG.CS.HasBits(nxp.RTWDOG_CS_CMD32EN_Msk) {
		nxp.RTWDOG.CNT.Set(wdogUpdateKey)
	} else {
		nxp.RTWDOG.CNT.Set((wdogUpdateKey >> 0) & 0xFFFF)
		nxp.RTWDOG.CNT.Set((wdogUpdateKey >> 16) & 0xFFFF)
	}
	nxp.RTWDOG.TOVAL.Set(0xFFFF)
	nxp.RTWDOG.CS.Set((nxp.RTWDOG.CS.Get() & ^uint32(nxp.RTWDOG_CS_EN_Msk)) | nxp.RTWDOG_CS_UPDATE_Msk)
}

func initPeripherals() {

	enableTimerClocks() // activate GPT/PIT clock gates
	initSysTick()       // enable SysTick
	initRTC()           // enable real-time clock

	enablePinClocks() // activate IOMUXC(_GPR)/GPIO clock gates
	initPins()        // configure GPIO

	enablePeripheralClocks() // activate peripheral clock gates
	initUART()               // configure UART (initialized first for debugging)
}

func initPins() {
	// use fast GPIO for all pins (GPIO6-9)
	nxp.IOMUXC_GPR.GPR26.Set(0xFFFFFFFF)
	nxp.IOMUXC_GPR.GPR27.Set(0xFFFFFFFF)
	nxp.IOMUXC_GPR.GPR28.Set(0xFFFFFFFF)
	nxp.IOMUXC_GPR.GPR29.Set(0xFFFFFFFF)
}

func initUART() {
	machine.InitSerial()
}

func putchar(c byte) {
	machine.Serial.WriteByte(c)
}

func getchar() byte {
	for machine.UART1.Buffered() == 0 {
		Gosched()
	}
	v, _ := machine.UART1.ReadByte()
	return v
}

func buffered() int {
	return machine.UART1.Buffered()
}

func exit(code int) {
	abort()
}

func abort() {
	for {
		arm.Asm("wfe")
	}
}

func waitForEvents() {
	arm.Asm("wfe")
}