@@ -249,6 +249,9 @@ pub static OS_IMAGE: [u8; include_bytes!("thumbv6m-none-eabi-flash1002-libneotro
249249/// is currently active (low).
250250static INTERRUPT_PENDING : AtomicBool = AtomicBool :: new ( false ) ;
251251
252+ /// Stack for Core 1
253+ static mut CORE1_STACK : [ usize ; 256 ] = [ 0 ; 256 ] ;
254+
252255/// The table of API calls we provide the OS
253256static API_CALLS : common:: Api = common:: Api {
254257 api_version_get,
@@ -311,6 +314,12 @@ extern "C" {
311314 static mut _ram_os_len: u32 ;
312315}
313316
317+ /// What we paint Core 0's stack with
318+ const CORE0_STACK_PAINT_WORD : usize = 0xBBBB_BBBB ;
319+
320+ /// What we paint Core 1's stack with
321+ const CORE1_STACK_PAINT_WORD : usize = 0xCCCC_CCCC ;
322+
314323// -----------------------------------------------------------------------------
315324// Functions
316325// -----------------------------------------------------------------------------
@@ -333,6 +342,30 @@ fn main() -> ! {
333342 // Reset the spinlocks.
334343 pp. SIO . spinlock [ 31 ] . reset ( ) ;
335344
345+ {
346+ // Paint the stack
347+ extern "C" {
348+ static mut __sheap: usize ;
349+ static mut _stack_start: usize ;
350+ }
351+ let stack_len = unsafe {
352+ ( & _stack_start as * const usize as usize ) - ( & __sheap as * const usize as usize )
353+ } ;
354+ // But not the top 64 words, because we're using the stack right now!
355+ let stack = unsafe {
356+ core:: slice:: from_raw_parts_mut (
357+ & mut __sheap as * mut usize ,
358+ ( stack_len / core:: mem:: size_of :: < usize > ( ) ) - 256 ,
359+ )
360+ } ;
361+ info ! ( "Painting {:?}" , stack. as_ptr_range( ) ) ;
362+ for b in stack. iter_mut ( ) {
363+ * b = CORE0_STACK_PAINT_WORD ;
364+ }
365+ }
366+
367+ check_stacks ( ) ;
368+
336369 // Needed by the clock setup
337370 let mut watchdog = hal:: watchdog:: Watchdog :: new ( pp. WATCHDOG ) ;
338371
@@ -1897,6 +1930,7 @@ extern "C" fn bus_interrupt_status() -> u32 {
18971930/// media is indicated with a boolean field in the
18981931/// `block_dev::DeviceInfo` structure.
18991932pub extern "C" fn block_dev_get_info ( device : u8 ) -> common:: Option < common:: block_dev:: DeviceInfo > {
1933+ check_stacks ( ) ;
19001934 match device {
19011935 0 => {
19021936 let mut lock = HARDWARE . lock ( ) ;
@@ -1970,6 +2004,7 @@ pub extern "C" fn block_read(
19702004 data : common:: ApiBuffer ,
19712005) -> common:: Result < ( ) > {
19722006 use embedded_sdmmc:: BlockDevice ;
2007+ check_stacks ( ) ;
19732008 if data. data_len != usize:: from ( num_blocks) * 512 {
19742009 return common:: Result :: Err ( common:: Error :: UnsupportedConfiguration ( 0 ) ) ;
19752010 }
@@ -2087,6 +2122,53 @@ fn IO_IRQ_BANK0() {
20872122 cortex_m:: asm:: sev ( ) ;
20882123}
20892124
2125+ /// Measure how much stack space remains unused.
2126+ #[ cfg( feature = "check-stack" ) ]
2127+ fn check_stacks ( ) {
2128+ extern "C" {
2129+ static mut __sheap: usize ;
2130+ static mut _stack_start: usize ;
2131+ }
2132+ let stack_len =
2133+ unsafe { ( & _stack_start as * const usize as usize ) - ( & __sheap as * const usize as usize ) } ;
2134+ check_stack (
2135+ unsafe { & __sheap as * const usize } ,
2136+ stack_len,
2137+ CORE0_STACK_PAINT_WORD ,
2138+ ) ;
2139+ check_stack (
2140+ unsafe { CORE1_STACK . as_ptr ( ) } ,
2141+ unsafe { CORE1_STACK . len ( ) * core:: mem:: size_of :: < usize > ( ) } ,
2142+ CORE1_STACK_PAINT_WORD ,
2143+ ) ;
2144+ }
2145+
2146+ /// Dummy stack checker that does nothing
2147+ #[ cfg( not( feature = "check-stack" ) ) ]
2148+ fn check_stacks ( ) { }
2149+
2150+ /// Check an individual stack to see how much has been used
2151+ #[ cfg( feature = "check-stack" ) ]
2152+ fn check_stack ( start : * const usize , stack_len_bytes : usize , check_word : usize ) {
2153+ let mut p: * const usize = start;
2154+ let mut free_bytes = 0 ;
2155+ loop {
2156+ let value = unsafe { p. read_volatile ( ) } ;
2157+ if value != check_word {
2158+ break ;
2159+ }
2160+ // Safety: We must hit a used stack value somewhere!
2161+ p = unsafe { p. offset ( 1 ) } ;
2162+ free_bytes += core:: mem:: size_of :: < usize > ( ) ;
2163+ }
2164+ defmt:: debug!(
2165+ "Stack free at 0x{:08x}: {} bytes used of {} bytes" ,
2166+ start,
2167+ stack_len_bytes - free_bytes,
2168+ stack_len_bytes
2169+ ) ;
2170+ }
2171+
20902172/// Called when the CPU Hard Faults.
20912173///
20922174/// This probably means something panicked, and the Rust code was compiled to
0 commit comments