背景是:在STM32 H753(皮质M7)上进行裸金属开发,无臂-eabi-gcc有一个专用于IRQ处理程序的编译选项__attribute((interrupt)):
__attribute((interrupt))
做了一些测试,我确认了唯一的区别是堆栈在8个字节上对齐(即堆栈指针地址的3个最低有效位在函数压入堆栈之前被置零)。我不明白的是
fjnneemd1#
在Cortex-M中,“interrupt”属性没有任何区别。Cortex-M的构建方式使得中断处理程序只是常规的C函数,并且不需要像其他一些架构那样需要任何特殊的函数序言/尾声。因此,您根本不需要使用这个属性,HAL也不使用它。ARMv7-M建议始终保持堆栈8字节(2字,64位)对齐,但并不强制。如果你一次只推或弹出一个词,它就会工作得很好。尽管如此,这是建议。因此,如果你用汇编语言写一篇文章,一次推送/弹出偶数个寄存器被认为是一个很好的做法,但这并不是严格强制的,老实说,我从来没有遇到过这样的情况。文件中没有任何内容禁止它。作为一个纯粹的猜测,这可能是由于内部AHB总线是64位宽,但我知道太少,它是如何工作的水平。当您处于线程模式并发生中断时,Cortex-M会自动堆叠R 0-R3、R12、LR、PC(下一个指令)和xPSR,而无需代码中的任何指令。这就是为什么你不需要“interrupt”属性,以及为什么Cortex-M中断处理程序是基本的C函数-自动堆叠的寄存器基本上与常规C代码线程中调用者保存的寄存器相同。除了在硬件中自动进行堆叠/解堆叠之外。因此,当你进入中断处理程序时,你已经将所有调用者保存的寄存器保存在堆栈上,如果你使用的是专用线程堆栈指针,那么它将在中断中切换到主堆栈指针。如果在中断的时刻,你的线程(或其他将被中断的中断)有堆栈4字节对齐而不是8字节对齐,自动堆栈机制将在堆栈上推送一个额外的伪寄存器,并且它将在解堆栈时被抛出。同样,不需要用户操作。
1条答案
按热度按时间fjnneemd1#
在Cortex-M中,“interrupt”属性没有任何区别。Cortex-M的构建方式使得中断处理程序只是常规的C函数,并且不需要像其他一些架构那样需要任何特殊的函数序言/尾声。因此,您根本不需要使用这个属性,HAL也不使用它。
ARMv7-M建议始终保持堆栈8字节(2字,64位)对齐,但并不强制。如果你一次只推或弹出一个词,它就会工作得很好。尽管如此,这是建议。因此,如果你用汇编语言写一篇文章,一次推送/弹出偶数个寄存器被认为是一个很好的做法,但这并不是严格强制的,老实说,我从来没有遇到过这样的情况。文件中没有任何内容禁止它。作为一个纯粹的猜测,这可能是由于内部AHB总线是64位宽,但我知道太少,它是如何工作的水平。
当您处于线程模式并发生中断时,Cortex-M会自动堆叠R 0-R3、R12、LR、PC(下一个指令)和xPSR,而无需代码中的任何指令。这就是为什么你不需要“interrupt”属性,以及为什么Cortex-M中断处理程序是基本的C函数-自动堆叠的寄存器基本上与常规C代码线程中调用者保存的寄存器相同。除了在硬件中自动进行堆叠/解堆叠之外。因此,当你进入中断处理程序时,你已经将所有调用者保存的寄存器保存在堆栈上,如果你使用的是专用线程堆栈指针,那么它将在中断中切换到主堆栈指针。如果在中断的时刻,你的线程(或其他将被中断的中断)有堆栈4字节对齐而不是8字节对齐,自动堆栈机制将在堆栈上推送一个额外的伪寄存器,并且它将在解堆栈时被抛出。同样,不需要用户操作。