我正在为我的 STM32F0 板编写一个迷你操作系统,该板具有基于 ARMv6-M 架构的 Cortex-M0 CPU。 特别是,在为调度程序创建进程队列后,我正在执行 msp/psp 切换。 当且仅当我已经完成切换时,对齐问题才会出现,否则它似乎不存在。
即使堆栈指针之前未对齐,ARMv6-M 架构也能保证异常条目时的 8 字节堆栈对齐。在我的陷阱处理程序中,我仔细检查了 sp 在异常进入时自动更改为 msp 并且它无论如何都没有对齐。
涉及的代码如下:
extern "C" fn kmain() -> ! {
// initialization code
Process::spawner().new(task).new(shell).spawn();
// infinite loop waiting for interruptions
}
#[inline(always)]
pub fn spawn(self) {
unsafe {
// Initialize the current process with the first one
// when we're terminating the builder
CURR_PROC.write(ptr::read(PROC_LIST.0));
}
Scheduler::init(self.idle_task_stack); // <--- THIS LINE
SysTick::enable();
}
#[inline(always)]
pub fn init(psp: *mut u8) {
unsafe {
// Set PSP as default stack, flush the pipeline
// standard procedure. Using barriers.
_switch_to_psp(psp); // <--- THIS LINE
}
}
.global _switch_to_psp
.thumb
.thumb_func
_switch_to_psp:
MSR psp, r0
MOV r1, #2
MSR CONTROL, r1
ISB
BX lr
只需注释突出显示的行,当系统定时器中断触发时,msp 就会正确对齐到中断处理程序中的 8 个字节,即使以前没有触发。 请注意,我正在检查程序集包装器和 Rust 处理程序中的这些寄存器,以确保处理程序序言不会使堆栈错位,但事实并非如此。 (我内联每个函数,因为堆栈指针在调用和返回之间发生变化,因此尾声会破坏所有内容。)
您对为什么会发生这种情况有任何提示吗?
我得出的结论是,对齐的堆栈不是当前堆栈,而是异常条目之前的堆栈,因此我不应该担心。
有一段模棱两可的段落提到:
CCR.STKALIGN 位指示作为异常条目的一部分,处理器是否将 SP 对齐到 4 字节或 8 字节
这让我将 SP 视为当前堆栈指针。然而,更仔细地研究,我找到了更好的解释:
在异常入口处,异常入口顺序确保在异常入口之前使用堆栈指针 具有 8 字节对齐方式,必要时可调整其对齐方式