【发布时间】:2021-12-10 05:44:24
【问题描述】:
我需要一个线程保存 idx++ 和 idx-- 操作。 禁用中断,即使用临界区,是一回事,但我想要 了解为什么我的操作不是原子的,正如我所期望的那样? 这是使用 segger 臭氧显示的带有内联汇编代码的 C 代码: (另外请注意,变量的地址显示32位变量在内存中是32位对齐的,8位和16位变量都是16位对齐的)
volatile static U8 dbgIdx8 = 1000U;
volatile static U16 dbgIdx16 = 1000U;
volatile static U32 dbgIdx32 = 1000U;
dbgIdx8 ++;
080058BE LDR R3, [PC, #48]
080058C0 LDRB R3, [R3]
080058C2 UXTB R3, R3
080058C4 ADDS R3, #1
080058C6 UXTB R2, R3
080058C8 LDR R3, [PC, #36]
080058CA STRB R2, [R3]
dbgIdx16 ++;
080058CC LDR R3, [PC, #36]
080058CE LDRH R3, [R3]
080058D0 UXTH R3, R3
080058D2 ADDS R3, #1
080058D4 UXTH R2, R3
080058D6 LDR R3, [PC, #28]
080058D8 STRH R2, [R3]
dbgIdx32 ++;
080058DA LDR R3, [PC, #28]
080058DC LDR R3, [R3]
080058DE ADDS R3, #1
080058E0 LDR R2, [PC, #20]
080058E2 STR R3, [R2]
【问题讨论】:
-
正常的 C 增量不是原子的,也不是易失的访问。您应该使用来自
<stdatomic.h>的显式原子操作 -
我的意思是,看看汇编代码。您将
dbgIdx8加载到寄存器中,增加该寄存器,然后稍后将其存储回几条指令。这无论如何都不是原子的,加载和存储之间可能会发生各种外部事物。您应该使用独占加载和存储,ldrexb/strexb,并且如前所述,<stdatomic.h>操作将正确发出这些指令。
标签: c stm32 atomic microcontroller cortex-m3