|
185 | 185 | //! value to the `_ram_end` value from the linker script. This is not usually required, but might be |
186 | 186 | //! necessary to properly initialize memory integrity measures on some hardware. |
187 | 187 | //! |
| 188 | +//! ## `paint-stack` |
| 189 | +//! |
| 190 | +//! Everywhere between `__sheap` and `___stack_start` is painted with the fixed value |
| 191 | +//! `STACK_PAINT_VALUE`, which is `0xCCCC_CCCC`. |
| 192 | +//! You can then inspect memory during debugging to determine how much of the stack has been used - |
| 193 | +//! where the stack has been used the 'paint' will have been 'scrubbed off' and the memory will |
| 194 | +//! have a value other than `STACK_PAINT_VALUE`. |
| 195 | +//! |
188 | 196 | //! # Inspection |
189 | 197 | //! |
190 | 198 | //! This section covers how to inspect a binary that builds on top of `cortex-m-rt`. |
|
225 | 233 | //! using the `main` symbol so you will also find that symbol in your program. |
226 | 234 | //! |
227 | 235 | //! - `DefaultHandler`. This is the default handler. If not overridden using `#[exception] fn |
228 | | -//! DefaultHandler(..` this will be an infinite loop. |
| 236 | +//! DefaultHandler(..` this will be an infinite loop. |
229 | 237 | //! |
230 | 238 | //! - `HardFault` and `_HardFault`. These function handle the hard fault handling and what they |
231 | 239 | //! do depends on whether the hard fault is overridden and whether the trampoline is enabled (which it is by default). |
|
467 | 475 |
|
468 | 476 | extern crate cortex_m_rt_macros as macros; |
469 | 477 |
|
| 478 | +/// The 32-bit value the stack is painted with before the program runs. |
| 479 | +// Note: keep this value in-sync with the start-up assembly code, as we can't |
| 480 | +// use const values in `global_asm!` yet. |
| 481 | +#[cfg(feature = "paint-stack")] |
| 482 | +pub const STACK_PAINT_VALUE: u32 = 0xcccc_cccc; |
| 483 | + |
470 | 484 | #[cfg(cortex_m)] |
471 | 485 | use core::arch::global_asm; |
472 | 486 | use core::fmt; |
@@ -545,24 +559,37 @@ cfg_global_asm! { |
545 | 559 | "ldr r0, =__sbss |
546 | 560 | ldr r1, =__ebss |
547 | 561 | movs r2, #0 |
548 | | - 2: |
| 562 | + 0: |
| 563 | + cmp r1, r0 |
| 564 | + beq 1f |
| 565 | + stm r0!, {{r2}} |
| 566 | + b 0b |
| 567 | + 1:", |
| 568 | + |
| 569 | + // If enabled, paint stack/heap RAM with 0xcccccccc. |
| 570 | + // `__sheap` and `_stack_start` come from the linker script. |
| 571 | + #[cfg(feature = "paint-stack")] |
| 572 | + "ldr r0, =__sheap |
| 573 | + ldr r1, =_stack_start |
| 574 | + ldr r2, =0xcccccccc // This must match STACK_PAINT_VALUE |
| 575 | + 0: |
549 | 576 | cmp r1, r0 |
550 | | - beq 3f |
| 577 | + beq 1f |
551 | 578 | stm r0!, {{r2}} |
552 | | - b 2b |
553 | | - 3:", |
| 579 | + b 0b |
| 580 | + 1:", |
554 | 581 |
|
555 | 582 | // Initialise .data memory. `__sdata`, `__sidata`, and `__edata` come from the linker script. |
556 | 583 | "ldr r0, =__sdata |
557 | 584 | ldr r1, =__edata |
558 | 585 | ldr r2, =__sidata |
559 | | - 4: |
| 586 | + 0: |
560 | 587 | cmp r1, r0 |
561 | | - beq 5f |
| 588 | + beq 1f |
562 | 589 | ldm r2!, {{r3}} |
563 | 590 | stm r0!, {{r3}} |
564 | | - b 4b |
565 | | - 5:", |
| 591 | + b 0b |
| 592 | + 1:", |
566 | 593 |
|
567 | 594 | // Potentially enable an FPU. |
568 | 595 | // SCB.CPACR is 0xE000_ED88. |
@@ -872,6 +899,7 @@ pub static __ONCE__: () = (); |
872 | 899 | /// Registers stacked (pushed onto the stack) during an exception. |
873 | 900 | #[derive(Clone, Copy)] |
874 | 901 | #[repr(C)] |
| 902 | +#[allow(dead_code)] |
875 | 903 | pub struct ExceptionFrame { |
876 | 904 | r0: u32, |
877 | 905 | r1: u32, |
|
0 commit comments