@@ -311,6 +311,12 @@ extern "C" {
311311 static mut _ram_os_len: u32 ;
312312}
313313
314+ /// What we paint Core 0's stack with
315+ const CORE0_STACK_PAINT_WORD : usize = 0xBBBB_BBBB ;
316+
317+ /// What we paint Core 1's stack with
318+ const CORE1_STACK_PAINT_WORD : usize = 0xCCCC_CCCC ;
319+
314320// -----------------------------------------------------------------------------
315321// Functions
316322// -----------------------------------------------------------------------------
@@ -333,6 +339,27 @@ fn main() -> ! {
333339 // Reset the spinlocks.
334340 pp. SIO . spinlock [ 31 ] . reset ( ) ;
335341
342+ {
343+ // Paint the stack
344+ extern "C" {
345+ static mut _stack_bottom: usize ;
346+ static mut _stack_len: usize ;
347+ }
348+ // But not the top 64 words, because we're using the stack right now!
349+ let stack = unsafe {
350+ core:: slice:: from_raw_parts_mut (
351+ & mut _stack_bottom as * mut usize ,
352+ ( & mut _stack_len as * const _ as usize / core:: mem:: size_of :: < usize > ( ) ) - 256 ,
353+ )
354+ } ;
355+ info ! ( "Painting {:?}" , stack. as_ptr_range( ) ) ;
356+ for b in stack. iter_mut ( ) {
357+ * b = CORE0_STACK_PAINT_WORD ;
358+ }
359+ }
360+
361+ check_stacks ( ) ;
362+
336363 // Needed by the clock setup
337364 let mut watchdog = hal:: watchdog:: Watchdog :: new ( pp. WATCHDOG ) ;
338365
@@ -1897,6 +1924,7 @@ extern "C" fn bus_interrupt_status() -> u32 {
18971924/// media is indicated with a boolean field in the
18981925/// `block_dev::DeviceInfo` structure.
18991926pub extern "C" fn block_dev_get_info ( device : u8 ) -> common:: Option < common:: block_dev:: DeviceInfo > {
1927+ check_stacks ( ) ;
19001928 match device {
19011929 0 => {
19021930 let mut lock = HARDWARE . lock ( ) ;
@@ -1970,6 +1998,7 @@ pub extern "C" fn block_read(
19701998 data : common:: ApiBuffer ,
19711999) -> common:: Result < ( ) > {
19722000 use embedded_sdmmc:: BlockDevice ;
2001+ check_stacks ( ) ;
19732002 if data. data_len != usize:: from ( num_blocks) * 512 {
19742003 return common:: Result :: Err ( common:: Error :: UnsupportedConfiguration ( 0 ) ) ;
19752004 }
@@ -2087,6 +2116,49 @@ fn IO_IRQ_BANK0() {
20872116 cortex_m:: asm:: sev ( ) ;
20882117}
20892118
2119+ /// Measure how much stack space remains unused.
2120+ #[ cfg( feature = "check-stack" ) ]
2121+ fn check_stacks ( ) {
2122+ extern "C" {
2123+ static _stack_bottom: usize ;
2124+ static _stack_len: usize ;
2125+ static _core1_stack_bottom: usize ;
2126+ static _core1_stack_len: usize ;
2127+ }
2128+ let p = unsafe { & _stack_bottom as * const usize } ;
2129+ let total_bytes = unsafe { & _stack_len as * const usize as usize } ;
2130+ check_stack ( p, total_bytes, CORE0_STACK_PAINT_WORD ) ;
2131+ let p = unsafe { & _core1_stack_bottom as * const usize } ;
2132+ let total_bytes = unsafe { & _core1_stack_len as * const usize as usize } ;
2133+ check_stack ( p, total_bytes, CORE1_STACK_PAINT_WORD ) ;
2134+ }
2135+
2136+ /// Dummy stack checker that does nothing
2137+ #[ cfg( not( feature = "check-stack" ) ) ]
2138+ fn check_stacks ( ) { }
2139+
2140+ /// Check an individual stack to see how much has been used
2141+ #[ cfg( feature = "check-stack" ) ]
2142+ fn check_stack ( start : * const usize , stack_len_bytes : usize , check_word : usize ) {
2143+ let mut p: * const usize = start;
2144+ let mut free_bytes = 0 ;
2145+ loop {
2146+ let value = unsafe { p. read_volatile ( ) } ;
2147+ if value != check_word {
2148+ break ;
2149+ }
2150+ // Safety: We must hit a used stack value somewhere!
2151+ p = unsafe { p. offset ( 1 ) } ;
2152+ free_bytes += core:: mem:: size_of :: < usize > ( ) ;
2153+ }
2154+ defmt:: debug!(
2155+ "Stack free at 0x{:08x}: {} bytes used of {} bytes" ,
2156+ start,
2157+ stack_len_bytes - free_bytes,
2158+ stack_len_bytes
2159+ ) ;
2160+ }
2161+
20902162/// Called when the CPU Hard Faults.
20912163///
20922164/// This probably means something panicked, and the Rust code was compiled to
0 commit comments