From 5bfa856157a9dda83955b297f915811a5536211f Mon Sep 17 00:00:00 2001 From: Zhiyao Ma Date: Fri, 16 Aug 2024 19:48:23 -0400 Subject: [PATCH] Refactor `boot` module. --- src/allocator/mod.rs | 27 +- src/boot/mod.rs | 457 +------------------------- src/boot/reset.rs | 74 +++++ src/boot/{entry.rs => system_init.rs} | 9 +- src/boot/vector_table.rs | 331 +++++++++++++++++++ src/unwind/forced.rs | 5 +- src/unwind/unwind.rs | 63 +++- 7 files changed, 501 insertions(+), 465 deletions(-) create mode 100644 src/boot/reset.rs rename src/boot/{entry.rs => system_init.rs} (88%) create mode 100644 src/boot/vector_table.rs diff --git a/src/allocator/mod.rs b/src/allocator/mod.rs index e59a532..6998948 100644 --- a/src/allocator/mod.rs +++ b/src/allocator/mod.rs @@ -5,7 +5,6 @@ use core::{ }; use super::{ - boot, interrupt::{svc, trap_frame::TrapFrame}, schedule::scheduler, task, @@ -38,13 +37,13 @@ impl Allocator { } /// Initialize the allocator. - pub fn init(&self) { + pub(crate) fn init(&self) { if !self.initialized.load(Ordering::SeqCst) { // Safety: the boot module should provide the correct // starting address of the heap. The heap will extend to // the end of the SRAM address space. unsafe { - heap::mcu_heap_init(boot::heap_start()); + heap::mcu_heap_init(heap_start()); } } self.initialized.store(true, Ordering::SeqCst); @@ -159,7 +158,7 @@ fn alloc_error(_layout: core::alloc::Layout) -> ! { /// Initialize the allocator. If the allocator has already been initialized, /// it does nothing. -pub fn init_allocator() { +pub(crate) fn initialize() { GLOBAL_ALLOC.init() } @@ -219,3 +218,23 @@ pub(super) fn task_free(tf: &TrapFrame) { // FIXME: need not go through `alloc::alloc` again. unsafe { alloc::alloc::dealloc(tf.gp_regs.r0 as *mut u8, Layout::new::()) } } + +/// Returns a pointer to the start of the heap. +/// The returned pointer is guaranteed to be 4-byte aligned. +#[inline] +fn heap_start() -> u32 { + extern "C" { + // The symbol comes from `link.ld`. + static mut __sheap: u32; + } + + let p: u32; + unsafe { + asm!( + "ldr {r}, ={sheap}", + r = out(reg) p, + sheap = sym __sheap + ); + } + p +} diff --git a/src/boot/mod.rs b/src/boot/mod.rs index cdd1f09..32518f6 100644 --- a/src/boot/mod.rs +++ b/src/boot/mod.rs @@ -1,456 +1,5 @@ -//! This file is derived from `cortex-m-rt` crate, with `Reset` -//! function modified. +pub(crate) mod reset; +mod system_init; +mod vector_table; -use crate::{config, interrupt::default, unwind}; -use core::{arch::asm, slice}; pub use hopter_proc_macro::main; - -mod entry; - -#[link_section = ".vector_table.reset_vector"] -#[no_mangle] -pub static __RESET_VECTOR: unsafe extern "C" fn() -> ! = Reset; - -static mut EXIDX_START: usize = 0usize; -static mut EXIDX_END: usize = 0usize; -static mut EXTAB_START: usize = 0usize; -static mut EXTAB_END: usize = 0usize; - -#[allow(unused)] -pub fn get_exidx() -> &'static [u8] { - let start = unsafe { EXIDX_START } as *const u8; - let len = unsafe { EXIDX_END - EXIDX_START }; - unsafe { slice::from_raw_parts(start, len) } -} - -#[allow(unused)] -pub fn get_extab() -> &'static [u8] { - let start = unsafe { EXTAB_START } as *const u8; - let len = unsafe { EXTAB_END - EXTAB_START }; - unsafe { slice::from_raw_parts(start, len) } -} - -/// Returns a pointer to the start of the heap -/// The returned pointer is guaranteed to be 4-byte aligned. -#[allow(unused)] -#[inline] -pub fn heap_start() -> u32 { - extern "C" { - static mut __sheap: u32; - } - - let p: u32; - unsafe { - asm!( - "ldr {r}, ={sheap}", - r = out(reg) p, - sheap = sym __sheap - ); - } - p -} - -#[link_section = ".Reset"] -#[allow(non_snake_case)] -#[export_name = "Reset"] -#[naked] -unsafe extern "C" fn Reset() -> ! { - extern "C" { - // These symbols come from `link.ld` - static mut __sbss: u32; - static mut __ebss: u32; - static mut __sdata: u32; - static mut __edata: u32; - static __sidata: u32; - static __sarm_exidx: u32; - static __earm_exidx: u32; - static __sarm_extab: u32; - static __earm_extab: u32; - static __tmp_stack: u32; - fn memclr(ptr: *mut u8, len: usize); - fn memcpy(dst: *mut u8, src: *const u8, len: usize); - fn memset(ptr: *mut u8, val: u8, len: usize); - } - asm!( - "ldr r0, ={sbss}", - "ldr r1, ={ebss}", - "sub r1, r1, r0", - "bl {memclr}", - "ldr r0, ={sdata}", - "ldr r1, ={sidata}", - "ldr r2, ={edata}", - "sub r2, r2, r0", - "bl {memcpy}", - "mov r0, #0x20000000", - "mov r1, #0xAA", - "ldr r2, ={kern_stk_len}", - "bl {memset}", - "ldr r0, ={sexidx}", - "ldr r1, ={ptr_exidx_start}", - "str r0, [r1]", - "ldr r0, ={eexidx}", - "ldr r1, ={ptr_exidx_end}", - "str r0, [r1]", - "ldr r0, ={sextab}", - "ldr r1, ={ptr_extab_start}", - "str r0, [r1]", - "ldr r0, ={eextab}", - "ldr r1, ={ptr_extab_end}", - "str r0, [r1]", - "ldr r1, ={kern_stk_boundary}", - "ldr r0, ={stklet_boundary_mem_addr}", - "str r1, [r0]", - "mov r1, #0", - "str r1, [r0, #4]", - "str r1, [r0, #8]", - "ldr r1, ={deferred_unwind}", - "str r1, [r0, #12]", - "mov lr, #0", - "b {system_start}", - sbss = sym __sbss, - ebss = sym __ebss, - sdata = sym __sdata, - edata = sym __edata, - sidata = sym __sidata, - sexidx = sym __sarm_exidx, - eexidx = sym __earm_exidx, - ptr_exidx_start = sym EXIDX_START, - ptr_exidx_end = sym EXIDX_END, - sextab = sym __sarm_extab, - eextab = sym __earm_extab, - ptr_extab_start = sym EXTAB_START, - ptr_extab_end = sym EXTAB_END, - kern_stk_len = const { config::CONTIGUOUS_STACK_BOTTOM - 0x2000_0000 }, - kern_stk_boundary = const config::CONTIGUOUS_STACK_BOUNDARY, - stklet_boundary_mem_addr = const config::TLS_MEM_ADDR, - deferred_unwind = sym unwind::forced::deferred_unwind, - memclr = sym memclr, - memcpy = sym memcpy, - memset = sym memset, - system_start = sym entry::system_start, - options(noreturn) - ); -} - -pub union Vector { - handler: unsafe extern "C" fn(), - reserved: usize, -} - -#[link_section = ".vector_table.exceptions"] -#[no_mangle] -pub static __EXCEPTIONS: [Vector; 14] = [ - // Exception 2: Non Maskable Interrupt. - Vector { - handler: NonMaskableInt, - }, - // Exception 3: Hard Fault Interrupt. - Vector { - handler: default::hardfault_trampoline, - }, - // Exception 4: Memory Management Interrupt [not on Cortex-M0 variants]. - #[cfg(not(armv6m))] - Vector { - handler: MemoryManagement, - }, - #[cfg(armv6m)] - Vector { reserved: 0 }, - // Exception 5: Bus Fault Interrupt [not on Cortex-M0 variants]. - #[cfg(not(armv6m))] - Vector { handler: BusFault }, - #[cfg(armv6m)] - Vector { reserved: 0 }, - // Exception 6: Usage Fault Interrupt [not on Cortex-M0 variants]. - #[cfg(not(armv6m))] - Vector { - handler: UsageFault, - }, - #[cfg(armv6m)] - Vector { reserved: 0 }, - // Exception 7: Secure Fault Interrupt [only on Armv8-M]. - #[cfg(armv8m)] - Vector { - handler: SecureFault, - }, - #[cfg(not(armv8m))] - Vector { reserved: 0 }, - // 8-10: Reserved - Vector { reserved: 0 }, - Vector { reserved: 0 }, - Vector { reserved: 0 }, - // Exception 11: SV Call Interrupt. - Vector { handler: SVCall }, - // Exception 12: Debug Monitor Interrupt [not on Cortex-M0 variants]. - #[cfg(not(armv6m))] - Vector { - handler: DebugMonitor, - }, - #[cfg(armv6m)] - Vector { reserved: 0 }, - // 13: Reserved - Vector { reserved: 0 }, - // Exception 14: Pend SV Interrupt [not on Cortex-M0 variants]. - Vector { handler: PendSV }, - // Exception 15: System Tick Interrupt. - Vector { handler: SysTick }, -]; - -extern "C" { - fn NonMaskableInt(); - - #[cfg(not(armv6m))] - fn MemoryManagement(); - - #[cfg(not(armv6m))] - fn BusFault(); - - #[cfg(not(armv6m))] - fn UsageFault(); - - #[cfg(armv8m)] - fn SecureFault(); - - fn SVCall(); - - #[cfg(not(armv6m))] - fn DebugMonitor(); - - fn PendSV(); - - fn SysTick(); -} - -extern "C" { - fn WWDG(); - fn PVD(); - fn TAMP_STAMP(); - fn RTC_WKUP(); - fn RCC(); - fn EXTI0(); - fn EXTI1(); - fn EXTI2(); - fn EXTI3(); - fn EXTI4(); - fn DMA1_STREAM0(); - fn DMA1_STREAM1(); - fn DMA1_STREAM2(); - fn DMA1_STREAM3(); - fn DMA1_STREAM4(); - fn DMA1_STREAM5(); - fn DMA1_STREAM6(); - fn ADC(); - fn CAN1_TX(); - fn CAN1_RX0(); - fn CAN1_RX1(); - fn CAN1_SCE(); - fn EXTI9_5(); - fn TIM1_BRK_TIM9(); - fn TIM1_UP_TIM10(); - fn TIM1_TRG_COM_TIM11(); - fn TIM1_CC(); - fn TIM2(); - fn TIM3(); - fn TIM4(); - fn I2C1_EV(); - fn I2C1_ER(); - fn I2C2_EV(); - fn I2C2_ER(); - fn SPI1(); - fn SPI2(); - fn USART1(); - fn USART2(); - fn USART3(); - fn EXTI15_10(); - fn RTC_ALARM(); - fn OTG_FS_WKUP(); - fn TIM8_BRK_TIM12(); - fn TIM8_UP_TIM13(); - fn TIM8_TRG_COM_TIM14(); - fn TIM8_CC(); - fn DMA1_STREAM7(); - fn FSMC(); - fn SDIO(); - fn TIM5(); - fn SPI3(); - fn UART4(); - fn UART5(); - fn TIM6_DAC(); - fn TIM7(); - fn DMA2_STREAM0(); - fn DMA2_STREAM1(); - fn DMA2_STREAM2(); - fn DMA2_STREAM3(); - fn DMA2_STREAM4(); - fn ETH(); - fn ETH_WKUP(); - fn CAN2_TX(); - fn CAN2_RX0(); - fn CAN2_RX1(); - fn CAN2_SCE(); - fn OTG_FS(); - fn DMA2_STREAM5(); - fn DMA2_STREAM6(); - fn DMA2_STREAM7(); - fn USART6(); - fn I2C3_EV(); - fn I2C3_ER(); - fn OTG_HS_EP1_OUT(); - fn OTG_HS_EP1_IN(); - fn OTG_HS_WKUP(); - fn OTG_HS(); - fn DCMI(); - fn CRYP(); - fn HASH_RNG(); - fn FPU(); - fn LTDC(); - fn LTDC_ER(); -} - -#[link_section = ".vector_table.interrupts"] -#[no_mangle] -pub static __INTERRUPTS: [Vector; 90] = [ - Vector { handler: WWDG }, - Vector { handler: PVD }, - Vector { - handler: TAMP_STAMP, - }, - Vector { handler: RTC_WKUP }, - Vector { reserved: 0 }, - Vector { handler: RCC }, - Vector { handler: EXTI0 }, - Vector { handler: EXTI1 }, - Vector { handler: EXTI2 }, - Vector { handler: EXTI3 }, - Vector { handler: EXTI4 }, - Vector { - handler: DMA1_STREAM0, - }, - Vector { - handler: DMA1_STREAM1, - }, - Vector { - handler: DMA1_STREAM2, - }, - Vector { - handler: DMA1_STREAM3, - }, - Vector { - handler: DMA1_STREAM4, - }, - Vector { - handler: DMA1_STREAM5, - }, - Vector { - handler: DMA1_STREAM6, - }, - Vector { handler: ADC }, - Vector { handler: CAN1_TX }, - Vector { handler: CAN1_RX0 }, - Vector { handler: CAN1_RX1 }, - Vector { handler: CAN1_SCE }, - Vector { handler: EXTI9_5 }, - Vector { - handler: TIM1_BRK_TIM9, - }, - Vector { - handler: TIM1_UP_TIM10, - }, - Vector { - handler: TIM1_TRG_COM_TIM11, - }, - Vector { handler: TIM1_CC }, - Vector { handler: TIM2 }, - Vector { handler: TIM3 }, - Vector { handler: TIM4 }, - Vector { handler: I2C1_EV }, - Vector { handler: I2C1_ER }, - Vector { handler: I2C2_EV }, - Vector { handler: I2C2_ER }, - Vector { handler: SPI1 }, - Vector { handler: SPI2 }, - Vector { handler: USART1 }, - Vector { handler: USART2 }, - Vector { handler: USART3 }, - Vector { handler: EXTI15_10 }, - Vector { handler: RTC_ALARM }, - Vector { - handler: OTG_FS_WKUP, - }, - Vector { - handler: TIM8_BRK_TIM12, - }, - Vector { - handler: TIM8_UP_TIM13, - }, - Vector { - handler: TIM8_TRG_COM_TIM14, - }, - Vector { handler: TIM8_CC }, - Vector { - handler: DMA1_STREAM7, - }, - Vector { handler: FSMC }, - Vector { handler: SDIO }, - Vector { handler: TIM5 }, - Vector { handler: SPI3 }, - Vector { handler: UART4 }, - Vector { handler: UART5 }, - Vector { handler: TIM6_DAC }, - Vector { handler: TIM7 }, - Vector { - handler: DMA2_STREAM0, - }, - Vector { - handler: DMA2_STREAM1, - }, - Vector { - handler: DMA2_STREAM2, - }, - Vector { - handler: DMA2_STREAM3, - }, - Vector { - handler: DMA2_STREAM4, - }, - Vector { handler: ETH }, - Vector { handler: ETH_WKUP }, - Vector { handler: CAN2_TX }, - Vector { handler: CAN2_RX0 }, - Vector { handler: CAN2_RX1 }, - Vector { handler: CAN2_SCE }, - Vector { handler: OTG_FS }, - Vector { - handler: DMA2_STREAM5, - }, - Vector { - handler: DMA2_STREAM6, - }, - Vector { - handler: DMA2_STREAM7, - }, - Vector { handler: USART6 }, - Vector { handler: I2C3_EV }, - Vector { handler: I2C3_ER }, - Vector { - handler: OTG_HS_EP1_OUT, - }, - Vector { - handler: OTG_HS_EP1_IN, - }, - Vector { - handler: OTG_HS_WKUP, - }, - Vector { handler: OTG_HS }, - Vector { handler: DCMI }, - Vector { handler: CRYP }, - Vector { handler: HASH_RNG }, - Vector { handler: FPU }, - Vector { reserved: 0 }, - Vector { reserved: 0 }, - Vector { reserved: 0 }, - Vector { reserved: 0 }, - Vector { reserved: 0 }, - Vector { reserved: 0 }, - Vector { handler: LTDC }, - Vector { handler: LTDC_ER }, -]; diff --git a/src/boot/reset.rs b/src/boot/reset.rs new file mode 100644 index 0000000..701e99c --- /dev/null +++ b/src/boot/reset.rs @@ -0,0 +1,74 @@ +//! The module defines the assembly sequence to execute when the system is just +//! powered on or reset. It sets up basic environment so that Rust code can +//! then execute. + +use super::system_init; +use crate::{config, unwind}; +use core::arch::asm; + +#[link_section = ".Reset"] +#[export_name = "Reset"] +#[naked] +pub(super) unsafe extern "C" fn entry() -> ! { + extern "C" { + // These symbols come from `link.ld` + static mut __sbss: u32; + static mut __ebss: u32; + static mut __sdata: u32; + static mut __edata: u32; + static __sidata: u32; + fn memclr(ptr: *mut u8, len: usize); + fn memcpy(dst: *mut u8, src: *const u8, len: usize); + fn memset(ptr: *mut u8, val: u8, len: usize); + } + asm!( + // Fill zero to `.bss` section in SRAM. + "ldr r0, ={sbss}", + "ldr r1, ={ebss}", + "sub r1, r1, r0", + "bl {memclr}", + // Copy the `.data` section from flash to SRAM. + "ldr r0, ={sdata}", + "ldr r1, ={sidata}", + "ldr r2, ={edata}", + "sub r2, r2, r0", + "bl {memcpy}", + // Fill 0xAA to the contiguous stack region. Will help us diagnose + // stack overflow. + "mov r0, #0x20000000", + "mov r1, #0xAA", + "ldr r2, ={cont_stk_len}", + "bl {memset}", + // Setting the task local storage (TLS) area. + // See `task::TaskLocalStorage` for details. + // Set the `stklet_bound` field. + "ldr r1, ={cont_stk_boundary}", + "ldr r0, ={stklet_boundary_mem_addr}", + "str r1, [r0]", + // Set the `nested_drop_cnt` and `unwind_pending` field. + "mov r1, #0", + "str r1, [r0, #4]", + "str r1, [r0, #8]", + // Set the function pointer for deferred forced unwinding. See + // `unwind::forced` for details. + "ldr r1, ={deferred_unwind}", + "str r1, [r0, #12]", + "mov lr, #0", + // Call into Rust code. + "b {system_start}", + sbss = sym __sbss, + ebss = sym __ebss, + sdata = sym __sdata, + edata = sym __edata, + sidata = sym __sidata, + cont_stk_len = const { config::CONTIGUOUS_STACK_BOTTOM - 0x2000_0000 }, + cont_stk_boundary = const config::CONTIGUOUS_STACK_BOUNDARY, + stklet_boundary_mem_addr = const config::TLS_MEM_ADDR, + deferred_unwind = sym unwind::forced::deferred_unwind, + memclr = sym memclr, + memcpy = sym memcpy, + memset = sym memset, + system_start = sym system_init::system_start, + options(noreturn) + ); +} diff --git a/src/boot/entry.rs b/src/boot/system_init.rs similarity index 88% rename from src/boot/entry.rs rename to src/boot/system_init.rs index 7c896b1..0bde573 100644 --- a/src/boot/entry.rs +++ b/src/boot/system_init.rs @@ -1,10 +1,14 @@ +//! The module performs the initialization before running the user defined main +//! function. + use crate::{allocator, config, schedule::scheduler, task, unrecoverable::Lethal}; use alloc::boxed::Box; use core::sync::atomic::AtomicPtr; use cortex_m::peripheral::scb::SystemHandler; +/// The very first Rust function executed. pub(super) extern "C" fn system_start() -> ! { - allocator::init_allocator(); + allocator::initialize(); let mut cp = cortex_m::Peripherals::take().unwrap(); @@ -29,6 +33,9 @@ pub(super) extern "C" fn system_start() -> ! { .spawn() .unwrap_or_die(); + // Start the scheduler. It will transform the current bootstrap thread into + // the idle task context and then perform a context switch to run the main + // task. unsafe { scheduler::start(); } diff --git a/src/boot/vector_table.rs b/src/boot/vector_table.rs new file mode 100644 index 0000000..25e3bb3 --- /dev/null +++ b/src/boot/vector_table.rs @@ -0,0 +1,331 @@ +//! The vector table code is derived from the `cortex-m-rt` crate. + +use super::reset; +use crate::interrupt::default; + +#[link_section = ".vector_table.reset_vector"] +#[no_mangle] +static __RESET_VECTOR: unsafe extern "C" fn() -> ! = reset::entry; + +pub union Vector { + handler: unsafe extern "C" fn(), + reserved: usize, +} + +#[link_section = ".vector_table.exceptions"] +#[no_mangle] +pub static __EXCEPTIONS: [Vector; 14] = [ + // Exception 2: Non Maskable Interrupt. + Vector { + handler: NonMaskableInt, + }, + // Exception 3: Hard Fault Interrupt. + Vector { + handler: default::hardfault_trampoline, + }, + // Exception 4: Memory Management Interrupt [not on Cortex-M0 variants]. + #[cfg(not(armv6m))] + Vector { + handler: MemoryManagement, + }, + #[cfg(armv6m)] + Vector { reserved: 0 }, + // Exception 5: Bus Fault Interrupt [not on Cortex-M0 variants]. + #[cfg(not(armv6m))] + Vector { handler: BusFault }, + #[cfg(armv6m)] + Vector { reserved: 0 }, + // Exception 6: Usage Fault Interrupt [not on Cortex-M0 variants]. + #[cfg(not(armv6m))] + Vector { + handler: UsageFault, + }, + #[cfg(armv6m)] + Vector { reserved: 0 }, + // Exception 7: Secure Fault Interrupt [only on Armv8-M]. + #[cfg(armv8m)] + Vector { + handler: SecureFault, + }, + #[cfg(not(armv8m))] + Vector { reserved: 0 }, + // 8-10: Reserved + Vector { reserved: 0 }, + Vector { reserved: 0 }, + Vector { reserved: 0 }, + // Exception 11: SV Call Interrupt. + Vector { handler: SVCall }, + // Exception 12: Debug Monitor Interrupt [not on Cortex-M0 variants]. + #[cfg(not(armv6m))] + Vector { + handler: DebugMonitor, + }, + #[cfg(armv6m)] + Vector { reserved: 0 }, + // 13: Reserved + Vector { reserved: 0 }, + // Exception 14: Pend SV Interrupt [not on Cortex-M0 variants]. + Vector { handler: PendSV }, + // Exception 15: System Tick Interrupt. + Vector { handler: SysTick }, +]; + +extern "C" { + fn NonMaskableInt(); + + #[cfg(not(armv6m))] + fn MemoryManagement(); + + #[cfg(not(armv6m))] + fn BusFault(); + + #[cfg(not(armv6m))] + fn UsageFault(); + + #[cfg(armv8m)] + fn SecureFault(); + + fn SVCall(); + + #[cfg(not(armv6m))] + fn DebugMonitor(); + + fn PendSV(); + + fn SysTick(); +} + +extern "C" { + fn WWDG(); + fn PVD(); + fn TAMP_STAMP(); + fn RTC_WKUP(); + fn RCC(); + fn EXTI0(); + fn EXTI1(); + fn EXTI2(); + fn EXTI3(); + fn EXTI4(); + fn DMA1_STREAM0(); + fn DMA1_STREAM1(); + fn DMA1_STREAM2(); + fn DMA1_STREAM3(); + fn DMA1_STREAM4(); + fn DMA1_STREAM5(); + fn DMA1_STREAM6(); + fn ADC(); + fn CAN1_TX(); + fn CAN1_RX0(); + fn CAN1_RX1(); + fn CAN1_SCE(); + fn EXTI9_5(); + fn TIM1_BRK_TIM9(); + fn TIM1_UP_TIM10(); + fn TIM1_TRG_COM_TIM11(); + fn TIM1_CC(); + fn TIM2(); + fn TIM3(); + fn TIM4(); + fn I2C1_EV(); + fn I2C1_ER(); + fn I2C2_EV(); + fn I2C2_ER(); + fn SPI1(); + fn SPI2(); + fn USART1(); + fn USART2(); + fn USART3(); + fn EXTI15_10(); + fn RTC_ALARM(); + fn OTG_FS_WKUP(); + fn TIM8_BRK_TIM12(); + fn TIM8_UP_TIM13(); + fn TIM8_TRG_COM_TIM14(); + fn TIM8_CC(); + fn DMA1_STREAM7(); + fn FSMC(); + fn SDIO(); + fn TIM5(); + fn SPI3(); + fn UART4(); + fn UART5(); + fn TIM6_DAC(); + fn TIM7(); + fn DMA2_STREAM0(); + fn DMA2_STREAM1(); + fn DMA2_STREAM2(); + fn DMA2_STREAM3(); + fn DMA2_STREAM4(); + fn ETH(); + fn ETH_WKUP(); + fn CAN2_TX(); + fn CAN2_RX0(); + fn CAN2_RX1(); + fn CAN2_SCE(); + fn OTG_FS(); + fn DMA2_STREAM5(); + fn DMA2_STREAM6(); + fn DMA2_STREAM7(); + fn USART6(); + fn I2C3_EV(); + fn I2C3_ER(); + fn OTG_HS_EP1_OUT(); + fn OTG_HS_EP1_IN(); + fn OTG_HS_WKUP(); + fn OTG_HS(); + fn DCMI(); + fn CRYP(); + fn HASH_RNG(); + fn FPU(); + fn LTDC(); + fn LTDC_ER(); +} + +#[link_section = ".vector_table.interrupts"] +#[no_mangle] +pub static __INTERRUPTS: [Vector; 90] = [ + Vector { handler: WWDG }, + Vector { handler: PVD }, + Vector { + handler: TAMP_STAMP, + }, + Vector { handler: RTC_WKUP }, + Vector { reserved: 0 }, + Vector { handler: RCC }, + Vector { handler: EXTI0 }, + Vector { handler: EXTI1 }, + Vector { handler: EXTI2 }, + Vector { handler: EXTI3 }, + Vector { handler: EXTI4 }, + Vector { + handler: DMA1_STREAM0, + }, + Vector { + handler: DMA1_STREAM1, + }, + Vector { + handler: DMA1_STREAM2, + }, + Vector { + handler: DMA1_STREAM3, + }, + Vector { + handler: DMA1_STREAM4, + }, + Vector { + handler: DMA1_STREAM5, + }, + Vector { + handler: DMA1_STREAM6, + }, + Vector { handler: ADC }, + Vector { handler: CAN1_TX }, + Vector { handler: CAN1_RX0 }, + Vector { handler: CAN1_RX1 }, + Vector { handler: CAN1_SCE }, + Vector { handler: EXTI9_5 }, + Vector { + handler: TIM1_BRK_TIM9, + }, + Vector { + handler: TIM1_UP_TIM10, + }, + Vector { + handler: TIM1_TRG_COM_TIM11, + }, + Vector { handler: TIM1_CC }, + Vector { handler: TIM2 }, + Vector { handler: TIM3 }, + Vector { handler: TIM4 }, + Vector { handler: I2C1_EV }, + Vector { handler: I2C1_ER }, + Vector { handler: I2C2_EV }, + Vector { handler: I2C2_ER }, + Vector { handler: SPI1 }, + Vector { handler: SPI2 }, + Vector { handler: USART1 }, + Vector { handler: USART2 }, + Vector { handler: USART3 }, + Vector { handler: EXTI15_10 }, + Vector { handler: RTC_ALARM }, + Vector { + handler: OTG_FS_WKUP, + }, + Vector { + handler: TIM8_BRK_TIM12, + }, + Vector { + handler: TIM8_UP_TIM13, + }, + Vector { + handler: TIM8_TRG_COM_TIM14, + }, + Vector { handler: TIM8_CC }, + Vector { + handler: DMA1_STREAM7, + }, + Vector { handler: FSMC }, + Vector { handler: SDIO }, + Vector { handler: TIM5 }, + Vector { handler: SPI3 }, + Vector { handler: UART4 }, + Vector { handler: UART5 }, + Vector { handler: TIM6_DAC }, + Vector { handler: TIM7 }, + Vector { + handler: DMA2_STREAM0, + }, + Vector { + handler: DMA2_STREAM1, + }, + Vector { + handler: DMA2_STREAM2, + }, + Vector { + handler: DMA2_STREAM3, + }, + Vector { + handler: DMA2_STREAM4, + }, + Vector { handler: ETH }, + Vector { handler: ETH_WKUP }, + Vector { handler: CAN2_TX }, + Vector { handler: CAN2_RX0 }, + Vector { handler: CAN2_RX1 }, + Vector { handler: CAN2_SCE }, + Vector { handler: OTG_FS }, + Vector { + handler: DMA2_STREAM5, + }, + Vector { + handler: DMA2_STREAM6, + }, + Vector { + handler: DMA2_STREAM7, + }, + Vector { handler: USART6 }, + Vector { handler: I2C3_EV }, + Vector { handler: I2C3_ER }, + Vector { + handler: OTG_HS_EP1_OUT, + }, + Vector { + handler: OTG_HS_EP1_IN, + }, + Vector { + handler: OTG_HS_WKUP, + }, + Vector { handler: OTG_HS }, + Vector { handler: DCMI }, + Vector { handler: CRYP }, + Vector { handler: HASH_RNG }, + Vector { handler: FPU }, + Vector { reserved: 0 }, + Vector { reserved: 0 }, + Vector { reserved: 0 }, + Vector { reserved: 0 }, + Vector { reserved: 0 }, + Vector { reserved: 0 }, + Vector { handler: LTDC }, + Vector { handler: LTDC_ER }, +]; diff --git a/src/unwind/forced.rs b/src/unwind/forced.rs index e26c303..53714e7 100644 --- a/src/unwind/forced.rs +++ b/src/unwind/forced.rs @@ -44,7 +44,10 @@ //! the drop logic, i.e., `CNT -= 1`. //! 2. A flag checking epilogue that checks the deferred unwinding pending flag //! if the nested drop count is zero after the decrement. If the flag is set, -//! call [`deferred_unwind`]. +//! call [`deferred_unwind`]. The call will be made through a function +//! pointer stored at address `0x2000_000c`. The function pointer is +//! initialized by the power on reset assembly sequence +//! in [boot::reset](crate::boot::reset) and remains constant. use super::unwind; use crate::config; diff --git a/src/unwind/unwind.rs b/src/unwind/unwind.rs index 538013b..450d42a 100644 --- a/src/unwind/unwind.rs +++ b/src/unwind/unwind.rs @@ -37,7 +37,7 @@ use super::{ }, }; use crate::{ - boot, config, + config, interrupt::{ svc, trap_frame::{self, TrapFrame}, @@ -56,6 +56,7 @@ use core::{ mem::MaybeUninit, ops::{Index, IndexMut}, panic::PanicInfo, + slice, sync::atomic::{AtomicBool, Ordering}, }; use gimli::{EndianSlice, LittleEndian}; @@ -552,8 +553,8 @@ impl UnwindState<'static> { // Find the unwind ability for the last function before // the unwinder is invoked. - let exidx = boot::get_exidx(); - let extab = boot::get_extab(); + let exidx = get_exidx(); + let extab = get_extab(); unw_state .unw_ability .get_for_pc(unw_state.gp_regs[ARMGPReg::PC] as u32, exidx, extab) @@ -733,8 +734,8 @@ impl<'a> UnwindState<'a> { } // Update unwind ability information. - let exidx = boot::get_exidx(); - let extab = boot::get_extab(); + let exidx = get_exidx(); + let extab = get_extab(); self.unw_ability .get_for_pc(self.gp_regs[ARMGPReg::PC] as u32, exidx, extab)?; @@ -1149,6 +1150,58 @@ unsafe fn panic(_info: &PanicInfo) -> ! { unrecoverable::die() } +/// Return the `.ARM.exidx` section as a static byte slice. +fn get_exidx() -> &'static [u8] { + extern "C" { + // These symbols come from `link.ld` + static __sarm_exidx: u32; + static __earm_exidx: u32; + } + + let start: *const u8; + let end: *const u8; + + unsafe { + asm!( + "ldr {start}, ={sexidx}", + "ldr {end}, ={eexidx}", + start = out(reg) start, + end = out(reg) end, + sexidx = sym __sarm_exidx, + eexidx = sym __earm_exidx, + ); + + let len = end.byte_offset_from(start) as usize; + slice::from_raw_parts(start, len) + } +} + +/// Return the `.ARM.extab` section as a static byte slice. +fn get_extab() -> &'static [u8] { + extern "C" { + // These symbols come from `link.ld` + static __sarm_extab: u32; + static __earm_extab: u32; + } + + let start: *const u8; + let end: *const u8; + + unsafe { + asm!( + "ldr {start}, ={sextab}", + "ldr {end}, ={eextab}", + start = out(reg) start, + end = out(reg) end, + sextab = sym __sarm_extab, + eextab = sym __earm_extab, + ); + + let len = end.byte_offset_from(start) as usize; + slice::from_raw_parts(start, len) + } +} + /* Below are unused personality routines. They are marked unsafe because */ /* they should not be invoked by any programmer's code. */