【问题标题】:Stack alignment and ISR堆栈对齐和 ISR
【发布时间】:2022-01-09 17:33:59
【问题描述】:

如何确保 ISR 内的堆栈对齐? arm C 编译器是否在 ISR 中强制堆栈对齐?

例如,在我的理解中,函数中的局部范围变量被推入堆栈。假设您有一个 3 字节的 char 数组,然后调用了 ISR。在该 ISR 中调用另一个函数,该函数需要 4 字节的堆栈对齐。

ARM 编译器是修复它还是坏了?

我提出这个问题的动机是我在 ISR 中遇到了 fprintf 问题,我认为这可能是堆栈对齐问题。我正在为 设备进行编译,但在 SO 问题中没有那么多标签的空间。

【问题讨论】:

  • ISR = 中断服务程序?
  • 您使用的是什么 [特定] 处理器和操作系统? [隐藏的] ISR prolog/epilog 代码将负责堆栈对齐。您的问题是 [可能] 您可以不在 ISR 中执行fprintf。它 [可能] 遇到了与 fprintf 在 [linux] 信号处理程序中存在的相同问题。见:man signal-safety
  • 另外,请注意fprintf 相对较慢。 ISR 应该很快以保持尽可能小的延迟。所以,即使你可以,你为什么要在 ISR 中做fprintf?您可能希望 ISR 将它获取的数据存储在环形队列中。基础级代码可以从此队列中提取数据并发出fprintf。我会编辑您的问题并发布更多关于您实际尝试做的事情。
  • 当我只使用整数而不是打印浮点数时它似乎有效,所以我认为这可能是字节对齐的问题。据我了解,浮点数在字符串转换之前升级为双精度。 ISR 创建一个字符串,该字符串被复制到队列中进行传输。
  • 即使你有一个char arr[3],一个健全的编译器也不会错位堆栈,看看它的 asm 输出。更可能的问题是试图调用像 fprintf 这样需要从 ISR 内部获取锁的函数。如果 FILE* 的锁已经被占用了怎么办?

标签: atsam3x c arm interrupt-handling cortex-m


【解决方案1】:

对于 ARMv7M(包括 atsam3x 中的 Cortex-M3),中断处理程序中的堆栈对齐由硬件控制。

首先,堆栈指针的对齐方式永远不可能低于 4 个字节。这是因为堆栈指针的底部两位始终为零,并且没有指令可以更改它们。编译器知道这一点,因此如果您创建 char[3],它会将其四舍五入为 4 个字节。

如果 CCR 控制寄存器的 STKALIGN 位为 0,那么这就是所发生的一切。堆栈指针在进入中断处理函数时与 4 字节的倍数对齐。

如果 STKALIGN 位为 1,则硬件会在进入中断时自动将堆栈对齐到 8 字节边界。

在 Cortex-M3 上,CCR.STKALIGN 的复位值为 1,ARM 强烈建议您不要更改它。

在 ARM ABI 中,调用者负责对齐堆栈。这是因为它有 50:50 的机会知道它已经对齐而不做任何事情,因此效率更高。

如果您的编译器配置为为 ARM ABI 生成代码,那么它将假定堆栈正确对齐到任何外部链接函数的入口处的 8 字节边界,并且不会生成任何代码以在被调用时再次对齐它功能。

在 ARMv7M(和 v6M)上,使用裸函数作为中断处理程序是正常且正确的。一些 cmets 中没有提到 ISR 序言/结语。

所有这些组合意味着只要您的编译器配置为使用 ARM ABI,并且只要您没有更改 CCR.STKALIGN 的默认值,那么您的堆栈将始终正确对齐。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-08
    • 1970-01-01
    • 1970-01-01
    • 2011-06-16
    • 2019-02-19
    • 1970-01-01
    相关资源
    最近更新 更多