【发布时间】:2019-06-12 18:33:02
【问题描述】:
我正在研究一些嵌入式的东西。我有多个中断可能处理相同的数据,所以我想知道uint16_t 和uint32_t 数据类型是否是中断安全的。
如果中断正在处理uint16/32_t 数据,并且在中途被另一个试图读取该数据的中断中断,它将看到损坏的数据。这是一种可能的情况吗?
谢谢
【问题讨论】:
我正在研究一些嵌入式的东西。我有多个中断可能处理相同的数据,所以我想知道uint16_t 和uint32_t 数据类型是否是中断安全的。
如果中断正在处理uint16/32_t 数据,并且在中途被另一个试图读取该数据的中断中断,它将看到损坏的数据。这是一种可能的情况吗?
谢谢
【问题讨论】:
为了扩展来自@DinhQC 的answer,只要数据正确对齐,所有关于 16 位和 32 位数据类型的单结果指令对于 Cortex-M 上的中断都是“原子的”(并且您必须非常努力地让 C 编译器为您提供未对齐的数据,因为未对齐的访问速度很慢并且需要特殊处理)。在大多数实现中,像LDM 和STM 这样的多结果操作可以被中断和恢复,但LDM 或STM 中每个单独的32 位传输的完整性得到保证。
重要的是要了解您正在执行的操作是否是机器级别的单指令。例如,如果您要增加一个共享变量,这将需要三个指令:读取、修改和写入。如果在读和写之间发生中断,并且中断服务程序修改了同一个变量,那么这个修改将在ISR返回时被覆盖。
安全的方法是使用某种硬件支持的机制来强制共享数据的原子性或互斥性。在 Cortex-M 上,有比禁用和重新启用中断更强大、更灵活和更快的互斥方法,尤其是 STREX 和 LDREX 指令(在 C 中也可用)。请查看my answer to this other question 了解更多信息。
【讨论】:
Cortex-M 处理器不会损坏数据并为您的数据提供未定义的值。该值将始终是确定性的。但是,在中断的情况下,有许多条件会影响数据的值。 uint16/32_t 数据可以位于内存中,也可以仅位于处理器寄存器中。如果在内存中,它可以是 16/32 位对齐的,也可以不是 16/32 位对齐的。处理器,例如M0 或 M4,以及对数据执行的操作,例如加法或乘法,也很重要。所有这些都将决定用于处理数据的指令是否是原子指令。
您可以在由 Joseph Yiu 回答的 discussion 和 this 中找到更多详细信息。
一般来说,如果指令是原子的(单执行周期),中断是不能干扰数据操作的。但是,在您的 C 代码级别,uint16/32_t 数据操作可能需要超过 1 条指令。因此,很难保证程序按预期运行。这也适用于uint8_t 数据。您可能希望在处理共享数据之前禁用中断,然后再启用中断。 answer 很好地介绍了该技术(请参阅第 2 点)。
【讨论】: