作者:黄董一叶知秋_821 | 来源:互联网 | 2022-12-08 08:04
我在实现AVR系列处理器的关键部分方面经验丰富,您所做的只是禁用中断(当然有内存屏障),执行关键操作,然后重新启用中断:
void my_critical_function()
{
cli(); //Disable interrupts
// Mission critical code here
sei(); //Enable interrupts
}
现在我的问题是:
这种简单的方法是否也适用于处理器的ARM体系结构?我听说过处理器在指令和其他黑魔法上做了先见之事,并且主要想知道这些类型的事情是否会对关键部分的这种实现产生问题.
1> 小智..:
假设您使用的是Cortex-M处理器,请查看C语言中提供的LDREX
和STREX
指令,这些指令可通过CMSIS(Cortex微控制器软件接口标准)提供的宏__LDREXW()
和__STREXW()
宏来实现.它们可用于构建极其轻量级的互斥机制.
基本上,
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
中断将成功,(低优先级)的用户代码将不得不重试.
如果您正在使用操作系统,则可以使用相同的基元来构建"正确的"信号量和互斥量(例如,参见本应用笔记); 但是如果你使用的是OS,你可能已经可以通过它的API访问互斥体了!