Skip to content

Commit 537f844

Browse files
authored
Merge pull request #67 from Neotron-Compute/stack-paint
Increase core0 stack to 8K and paint/measure stack usage.
2 parents 1ed790a + 64bd12d commit 537f844

File tree

5 files changed

+104
-41
lines changed

5 files changed

+104
-41
lines changed

.cargo/config.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
# This will make a UF2 and copy it to the RP2040's Mass Storage Device bootloader
33
# runner = "elf2uf2-rs -d"
44
# This will flash over SWD with any compatible probe it finds. You need 0.3.1 or higher for RP2040 support.
5-
runner = "probe-run --chip RP2040 --measure-stack"
6-
5+
runner = "probe-run --chip RP2040"
76
rustflags = [
87
# This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x
98
# See https://github.com/rust-embedded/cortex-m-quickstart/pull/95
@@ -17,4 +16,4 @@ rustflags = [
1716
]
1817

1918
[build]
20-
target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+
19+
target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,6 @@ lto = true
7777
# good choice for performance on the RP2040, where code executes from external
7878
# SPI Flash and has to be buffered in a small on-chip cache memory.
7979
opt-level = "s"
80+
81+
[features]
82+
check-stack = []

memory.x

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,37 +25,15 @@ MEMORY {
2525
/*
2626
* This is the bottom of the four striped banks of SRAM in the RP2040.
2727
*/
28-
RAM_OS : ORIGIN = 0x20000000, LENGTH = 0x3A000
28+
RAM_OS : ORIGIN = 0x20000000, LENGTH = 232K
2929
/*
30-
* This is the top of the four striped banks of SRAM in the RP2040.
30+
* This is the top of the four striped banks of SRAM in the RP2040, plus SRAM_BANK4 and SRAM_BANK5.
3131
*
32-
* We give ourselves six 4K pages [0x3A_000, 0x40_000]
32+
* We give ourselves eight 4K pages [0x3A_000..0x41_FFF]
3333
*/
34-
RAM : ORIGIN = 0x2003A000, LENGTH = 24K
35-
/*
36-
* This is the fifth bank, a 4KB block. We use this for Core 0 Stack.
37-
*/
38-
RAM_CORE0_STACK : ORIGIN = 0x20040000, LENGTH = 4K
39-
/*
40-
* This is the sixth bank, a 4KB block. We use this for Core 1 Stack.
41-
*/
42-
RAM_CORE1_STACK : ORIGIN = 0x20041000, LENGTH = 4K
34+
RAM : ORIGIN = 0x2003A000, LENGTH = 32K
4335
}
4436

45-
/*
46-
* This is where the call stack for Core 0 will be located. The stack is of
47-
* the full descending type. You may want to use this variable to locate the
48-
* call stack and static variables in different memory regions. Below is
49-
* shown the default value
50-
*/
51-
_stack_start = ORIGIN(RAM_CORE0_STACK) + LENGTH(RAM_CORE0_STACK);
52-
53-
/*
54-
* This is where the call stack for Core 1 will be located.
55-
*/
56-
_core1_stack_bottom = ORIGIN(RAM_CORE1_STACK);
57-
_core1_stack_len = LENGTH(RAM_CORE1_STACK);
58-
5937
/*
6038
* Export some symbols to tell the BIOS where it might find the OS.
6139
*/

src/main.rs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,9 @@ pub static OS_IMAGE: [u8; include_bytes!("thumbv6m-none-eabi-flash1002-libneotro
249249
/// is currently active (low).
250250
static 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
253256
static 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.
18991932
pub 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

src/vga/mod.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,29 +1027,30 @@ pub fn init(
10271027
// cannot be reconfigured at a later time, but they do keep on running
10281028
// as-is.
10291029

1030-
let core1_stack: &'static mut [usize] = unsafe {
1031-
extern "C" {
1032-
static mut _core1_stack_bottom: usize;
1033-
static mut _core1_stack_len: usize;
1030+
unsafe {
1031+
for b in super::CORE1_STACK.iter_mut() {
1032+
*b = super::CORE1_STACK_PAINT_WORD;
10341033
}
1035-
core::slice::from_raw_parts_mut(
1036-
&mut _core1_stack_bottom as *mut _,
1037-
&mut _core1_stack_len as *const _ as usize / 4,
1038-
)
1039-
};
1034+
}
10401035

10411036
debug!(
10421037
"Core 1 stack: {:08x}, {} bytes",
1043-
core1_stack.as_ptr(),
1044-
core1_stack.len()
1038+
unsafe { super::CORE1_STACK.as_ptr() },
1039+
unsafe { super::CORE1_STACK.len() * core::mem::size_of::<usize>() }
10451040
);
10461041

10471042
// No-one else is looking at this right now.
10481043
unsafe {
10491044
TEXT_COLOUR_LOOKUP.init(&VIDEO_PALETTE);
10501045
}
10511046

1052-
multicore_launch_core1_with_stack(core1_main, core1_stack, ppb, fifo, psm);
1047+
multicore_launch_core1_with_stack(
1048+
core1_main,
1049+
unsafe { &mut super::CORE1_STACK },
1050+
ppb,
1051+
fifo,
1052+
psm,
1053+
);
10531054

10541055
debug!("Core 1 running");
10551056
}

0 commit comments

Comments
 (0)