diff options
| author | Ian McIntyre <ianpmcintyre@gmail.com> | 2022-08-02 06:21:12 -0400 |
|---|---|---|
| committer | Ian McIntyre <ianpmcintyre@gmail.com> | 2022-12-01 20:21:05 -0500 |
| commit | c7a9b9f3d4b9e71303c7b988d2bd916c2e4df9bc (patch) | |
| tree | 6d41ea7e433cac328fa165d45d1bc0cd71a1bf8f /src/target.rs | |
First commit
Diffstat (limited to 'src/target.rs')
| -rw-r--r-- | src/target.rs | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/src/target.rs b/src/target.rs new file mode 100644 index 0000000..163fd8e --- /dev/null +++ b/src/target.rs @@ -0,0 +1,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 _ } +} |
