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
//! Runtime support
//!
//! The useful bits are written in assembly. See `start.s` for the
//! reset handler implementation. The reset handler eventually calls
//! `t4_init()`, which finishes setup, and calls the `cortex-m-rt`
//! `Reset()` handler.
//!
//! Code that's in this module is running before `.data` is initialized,
//! and before `.bss` is zeroed. This code should only touch ARM and
//! peripheral memory.
pub use cortex_m_rt::*;
/// System entrypoint, invoked by reset handler
///
/// # Safety
///
/// The function is unsafe since it directly modifies registers, and invokes
/// other functions that do the same. It does not touch any memory that needs
/// to first be initialized by cortex-m-rt.
#[no_mangle]
unsafe extern "C" fn t4_init() {
// Remain in 'run' when transitioning to low power mode.
// Do not transition to wait mode.
//
// This addresses an edge case identified when reprogramming
// the Teensy, and then immediately executing WFI.
// See https://github.com/mciantyre/teensy4-rs/issues/76 for
// more details.
//
// It's also useful for users who expect SYSTICK exceptions
// to unblock WFI, which isn't the default behavior.
//
// Ideally, we could figure out an approach that keeps the processor
// as close to the reset state as possible, while avoiding #76.
// For now, we'll go with this, which simplifies some downstream
// code.
const CCM_CLPCR: *mut u32 = 0x400F_C054 as *mut _;
CCM_CLPCR.write_volatile(CCM_CLPCR.read_volatile() & !0b11);
extern "C" {
fn Reset();
}
Reset(); // cortex-m-rt entrypoint
}
/// Returns the size of the heap, in bytes.
///
/// Use [`heap_start()`](crate::rt::heap_start) to access the start of the heap.
#[inline]
pub fn heap_len() -> usize {
fn heap_end() -> *mut u32 {
extern "C" {
static mut __eheap: u32;
}
unsafe { &mut __eheap }
}
// Cannot use offset_from, since heap_end
// and heap_start are not derived from the
// same allocated object.
let end = heap_end() as usize;
let start = cortex_m_rt::heap_start() as usize;
end - start
}
/// Returns the starting location for a DTCM "heap."
///
/// The recommended heap is in OCRAM2, and available
/// using [`heap_start()`](crate::rt::heap_start). But,
/// you may choose to place the heap in DTCM. This function
/// returns the starting address for that heap.
///
/// The DTCM heap is expected to grow up towards the stack,
/// and has no statically-known maximum size. The pointer
/// is guaranteed to be 4 byte aligned.
#[inline]
pub fn dtcm_heap_start() -> *mut u32 {
extern "C" {
static mut __sheap_dtcm: u32;
}
unsafe { &mut __sheap_dtcm }
}