Assuming you're on a Cortex-M processor, take a look at the
LDREX
and
STREX
instructions, which are available in C via the
__LDREXW()
and
__STREXW()
macros provided by CMSIS (the Cortex Microcontroller Software Interface Standard). They can be used to build extremely lightweight mutual exclusion mechanisms.
Basically,
如果您使用的是Cortex-M处理器,请查看CMSIS提供的
__LDREXW()
和
__STREXW()
宏,以通过
LDREX
和
STREX
指令构建非常轻量级的互斥机制。
data = __LDREXW(address)
它的工作方式类似于data = *address
,但它在CPU中设置了“独占访问标志”。当您完成操作数据后,请使用它进行写回。
success = __STREXW(address, data)
这个函数类似于 *address = data
,但只有在独占访问标志仍然设置的情况下才能成功写入。如果它成功写入,则还会清除该标志。它返回0表示成功,返回1表示失败。如果 STREX
失败,则必须返回到 LDREX
并重试。
对于共享变量的简单独占访问,不需要做其他处理。例如:
do {
data = LDREX(address);
data++;
} while (STREXW(address, data));
这个机制有趣的地方在于它实际上是“后来居上”的;如果这段代码被中断,且中断使用了
LDREX
和
STREX
,那么
STREX
中断将会成功,而低优先级的用户代码将不得不重试。
如果您正在使用操作系统,则可以使用相同的基元构建“适当的”信号量和互斥量(例如,请参见
此应用说明);但是如果您正在使用操作系统,则可能已经通过其API访问了互斥量!
SWP
指令,该指令执行原子加载/存储(类似的功能在其他平台上也可用)。但是,LDREX
/STREX
对内存总线更加友好,这无论如何都是好事,但如果您有多个处理器共享总线,则开始变得非常重要。在我看来,这是一个巧妙的设计。 - cooperised