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
|
//! i.MX RT target support.
//!
//! Defines a `cortex-m-rt` pre-init function that disables watchdogs and initializes TCM.
//! It then copies instructions, read-only data, and the vector table to their intended location.
//! This only happens if LMAs and VMAs differ.
//!
//! There's a few behaviors worth mentioning:
//!
//! - The implementation never clears the INIT_xTCM_EN bits in GPR16 if the xTCM is unused.
//! The first reason is because we can't do this on the 1170 chips; the bits are reserved and
//! should always be set (guessing its for the CM4, which always uses TCM). The second reason
//! is that it doesn't seem necessary; we'll let xTCM initialize out of non-POR reset. From what
//! I could gather, this would be the case if we set fuse values to specify an all-OCRAM config,
//! and nothing says we need to flip these bits if the _fuses_ don't allocate xTCM. (Maybe this
//! automagically happens? Not sure.)
//! - We're not changing CM7_xTCMSZ to reflect the xTCM sizes. Again, the setting isn't available
//! on the 1170 chips. It's also OK to keep the POR value, since it represents the maximum-possible
//! TCM size. This means that users have finer control over xTCM memory sizes, but invalid xTCM accesses
//! won't cause a bus fault. See 3.1.3.2. in AN12077 for more discussion.
use core::{arch::global_asm, ffi::c_void};
pub use cortex_m_rt::*;
global_asm! {r#"
.cfi_sections .debug_frame
.section .__pre_init,"ax"
.global __pre_init
.type __pre_init,%function
.thumb_func
.cfi_startproc
__pre_init:
ldr r0, =__imxrt_family @ Need to know which chip family we're initializing.
ldr r1, =1170
cmp r0, r1 @ Is this an 1170?
# Disable RTWODOG3.
ite eq
ldreq r2, =0x40038000 @ RTWDOG base address for 11xx chips...
ldrne r2, =0x400BC000 @ RTWDOG base address for 10xx chips...
ldr r3, =0xD928C520 @ RTWDOG magic number
str r3, [r2, #4] @ RTWDOG[CNT] = 0xD928C520.
ldr r3, [r2] @ r3 = RTWDOG[CS]
bic r3, r3, #1<<7 @ r3 = r3 & !(1 << 7), clears enable.
str r3, [r2] @ RTWDOG[CS] = r3
# Prepare FlexRAM regions.
ldr r0, =0x400AC000 @ IMXRT_IOMUXC_GPR base address for 10xx chips, overwritten if actually 11xx...
ldr r1, =__flexram_config @ Value for GPR17 (and GPR18 for 11xx)
itttt eq @ Need a few extra operations to handle 1170 split banks.
ldreq r0, =0x400E4000 @ IMXRT_IOMUXC_GPR base address for 11xx chips, overwrite 10xx address...
lsreq r2, r1, #16 @ r2 = ((unsigned)r1 >> 16)
streq r2, [r0, #72] @ *(IMXRT_IOMUXC_GPR + 18) = r2
ubfxeq r1, r1, #0, #16 @ r1 = ((unsigned)r1 >> 0) & 0xFFFF, overwrite r1 with lower halfword.
str r1, [r0, #68] @ *(IMXRT_IOMUXC_GPR + 17) = r1
ldr r1, [r0, #64] @ r1 = *(IMXRT_IOMUXC_GPR + 16)
orr r1, r1, #1<<2 @ r1 |= 1 << 2
str r1, [r0, #64] @ *(IMXRT_IOMUXC_GPR + 16) = r1
# Set the stack pointer.
#
# This is particularly important for the 11xx. Its boot ROM
# doesn't take this step before it calls into our reset
# handler. The 10xx boot ROM handles this differently.
# Also noted in
# https://community.nxp.com/t5/i-MX-RT/RT1176-ROM-code-does-not-set-stack-pointer-correctly/td-p/1388830
#
# If this feature is published in a future cortex-m-rt version,
# we could remove this. See below for VTOR, too.
#
# Shouldn't matter where we perform this within this function.
# We're assuming that the caller isn't using the stack.
ldr r0, =__sstack
msr msp, r0
# Conditionally copy text.
ldr r0, =__stext
ldr r2, =__sitext
cmp r2, r0
beq 42f
ldr r1, =__etext
43:
cmp r1, r0
beq 42f
ldm r2!, {{r3}}
stm r0!, {{r3}}
b 43b
42:
# Conditionally copy the vector table.
ldr r0, =__svector_table
ldr r2, =__sivector_table
cmp r2, r0
beq 52f
ldr r1, =__evector_table
53:
cmp r1, r0
beq 52f
ldm r2!, {{r3}}
stm r0!, {{r3}}
b 53b
52:
# Set VTOR. If this feature is published in a future cortex-m-rt version,
# we could remove this.
ldr r0, =0xE000ED08
ldr r1, =__svector_table
str r1, [r0]
dsb
isb
# Conditionally copy read-only data.
ldr r0, =__srodata
ldr r2, =__sirodata
cmp r2, r0
beq 62f
ldr r1, =__erodata
63:
cmp r1, r0
beq 62f
ldm r2!, {{r3}}
stm r0!, {{r3}}
b 63b
62:
# All done; back to the reset handler.
bx lr
.cfi_endproc
.size __pre_init, . - __pre_init
"#
}
/// Returns a pointer to the end of the heap.
///
/// The returned pointer is guaranteed to be 4-byte aligned.
#[inline]
pub fn heap_end() -> *mut u32 {
extern "C" {
static mut __eheap: c_void;
}
unsafe { core::ptr::addr_of_mut!(__eheap) as _ }
}
|