mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-26 20:00:32 +00:00
Check stack overflow in main task (#4161)
* Check main task for stack overflow * Reuse esp-hal's config
This commit is contained in:
parent
0ede07d697
commit
6ee143eef9
@ -15,5 +15,10 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
.expect("Failed to read esp_config.yml for esp-preempt");
|
||||
generate_config_from_yaml_definition(&cfg_yaml, true, true, Some(chip)).unwrap();
|
||||
|
||||
// Emit the default stack guard value if not set by the user.
|
||||
if std::env::var("ESP_HAL_CONFIG_STACK_GUARD_VALUE").is_err() {
|
||||
println!("cargo:rustc-env=ESP_HAL_CONFIG_STACK_GUARD_VALUE=3740121773");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -8,3 +8,9 @@ options:
|
||||
constraints:
|
||||
- type:
|
||||
validator: positive_integer
|
||||
|
||||
- name: stack-guard-value
|
||||
description: The stack overflow guard value. This must be the same value as esp_hal's stack guard value.
|
||||
default:
|
||||
- value: 3740121773
|
||||
display_hint: Hex
|
||||
|
@ -32,6 +32,8 @@ mod timer;
|
||||
mod timer_queue;
|
||||
mod wait_queue;
|
||||
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
pub(crate) use esp_alloc::InternalMemory;
|
||||
use esp_hal::{
|
||||
Blocking,
|
||||
@ -121,8 +123,20 @@ pub fn start(timer: impl TimerSource) {
|
||||
SCHEDULER.with(move |scheduler| {
|
||||
scheduler.setup(TimeDriver::new(timer.timer()));
|
||||
|
||||
// allocate the default tasks
|
||||
task::allocate_main_task(scheduler);
|
||||
// Allocate the default task. The stack bottom is set to the stack guard's address as the
|
||||
// rest of the stack is unusable anyway.
|
||||
|
||||
unsafe extern "C" {
|
||||
static _stack_start_cpu0: u32;
|
||||
static __stack_chk_guard: u32;
|
||||
}
|
||||
let stack_top = &raw const _stack_start_cpu0;
|
||||
let stack_bottom = (&raw const __stack_chk_guard).cast::<MaybeUninit<u32>>();
|
||||
let stack_slice = core::ptr::slice_from_raw_parts_mut(
|
||||
stack_bottom.cast_mut(),
|
||||
stack_top as usize - stack_bottom as usize,
|
||||
);
|
||||
task::allocate_main_task(scheduler, stack_slice);
|
||||
|
||||
task::setup_multitasking();
|
||||
|
||||
|
@ -201,7 +201,7 @@ pub(crate) struct Task {
|
||||
pub cpu_context: CpuContext,
|
||||
pub thread_semaphore: Option<SemaphorePtr>,
|
||||
pub state: TaskState,
|
||||
pub _allocated_stack: *mut [MaybeUninit<u32>],
|
||||
pub stack: *mut [MaybeUninit<u32>],
|
||||
pub priority: usize,
|
||||
|
||||
pub wakeup_at: u64,
|
||||
@ -226,7 +226,8 @@ pub(crate) struct Task {
|
||||
pub(crate) heap_allocated: bool,
|
||||
}
|
||||
|
||||
const STACK_CANARY: u32 = 0xDEEDBAAD;
|
||||
const STACK_CANARY: u32 =
|
||||
const { esp_config::esp_config_int!(u32, "ESP_HAL_CONFIG_STACK_GUARD_VALUE") };
|
||||
|
||||
impl Task {
|
||||
pub(crate) fn new(
|
||||
@ -251,7 +252,7 @@ impl Task {
|
||||
cpu_context: new_task_context(task_fn, param, stack_top),
|
||||
thread_semaphore: None,
|
||||
state: TaskState::Ready,
|
||||
_allocated_stack: stack,
|
||||
stack,
|
||||
current_queue: None,
|
||||
priority,
|
||||
|
||||
@ -267,15 +268,10 @@ impl Task {
|
||||
}
|
||||
|
||||
pub(crate) fn ensure_no_stack_overflow(&self) {
|
||||
// TODO: fix this for main task
|
||||
if self._allocated_stack.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
// This cast is safe to do from MaybeUninit<u32> because this is the word we've written
|
||||
// during initialization.
|
||||
unsafe { self._allocated_stack.cast::<u32>().read() },
|
||||
unsafe { self.stack.cast::<u32>().read() },
|
||||
STACK_CANARY,
|
||||
"Stack overflow detected in {:?}",
|
||||
self as *const Task
|
||||
@ -300,7 +296,7 @@ pub(crate) static mut MAIN_TASK: Task = Task {
|
||||
cpu_context: CpuContext::new(),
|
||||
thread_semaphore: None,
|
||||
state: TaskState::Ready,
|
||||
_allocated_stack: core::ptr::slice_from_raw_parts_mut(core::ptr::null_mut(), 0),
|
||||
stack: core::ptr::slice_from_raw_parts_mut(core::ptr::null_mut(), 0),
|
||||
current_queue: None,
|
||||
priority: 0,
|
||||
|
||||
@ -314,16 +310,21 @@ pub(crate) static mut MAIN_TASK: Task = Task {
|
||||
heap_allocated: false,
|
||||
};
|
||||
|
||||
pub(super) fn allocate_main_task(scheduler: &mut SchedulerState) {
|
||||
pub(super) fn allocate_main_task(scheduler: &mut SchedulerState, stack: *mut [MaybeUninit<u32>]) {
|
||||
let mut main_task_ptr = unwrap!(NonNull::new(&raw mut MAIN_TASK));
|
||||
debug!("Main task created: {:?}", main_task_ptr);
|
||||
|
||||
unsafe {
|
||||
stack
|
||||
.cast::<MaybeUninit<u32>>()
|
||||
.write(MaybeUninit::new(STACK_CANARY));
|
||||
|
||||
let main_task = main_task_ptr.as_mut();
|
||||
|
||||
// Reset main task properties. The rest should be cleared when the task is deleted.
|
||||
main_task.priority = 0;
|
||||
main_task.state = TaskState::Ready;
|
||||
main_task.stack = stack;
|
||||
}
|
||||
|
||||
debug_assert!(
|
||||
|
Loading…
x
Reference in New Issue
Block a user