ARM 中的关键部分 [英] Critical sections in ARM
问题描述
我在 AVR 系列处理器上实现临界区方面经验丰富,您所做的只是禁用中断(当然有内存屏障),执行关键操作,然后重新启用中断:
I am experienced in implementing critical sections on the AVR family of processors, where all you do is disable interrupts (with a memory barrier of course), do the critical operation, and then reenable interrupts:
void my_critical_function()
{
cli(); //Disable interrupts
// Mission critical code here
sei(); //Enable interrupts
}
现在我的问题是:
这个简单的方法是否也适用于处理器的ARM架构?我听说过关于处理器在指令上进行前瞻和其他黑魔法的事情,主要想知道这些类型的事情是否会对临界区的这种实现造成问题.
Does this simple method apply to the ARM architecture of processor as well? I have heard things about the processor doing lookahead on the instructions, and other black magic, and was wondering primarily if these types of things could be problematic to this implementation of critical sections.
推荐答案
假设您使用的是 Cortex-M 处理器,请查看 LDREX
和 STREX
指令,可通过 CMSIS(Cortex 微控制器软件接口标准)提供的 __LDREXW()
和 __STREXW()
宏在 C 中使用.它们可用于构建极其轻量级的互斥机制.
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.
基本上,
data = __LDREXW(address)
的工作方式与 data = *address
类似,只是它在 CPU 中设置了一个独占访问标志".处理完数据后,使用
works like data = *address
except that it sets an 'exclusive access flag' in the CPU. When you've finished manipulating your data, write it back using
success = __STREXW(address, data)
类似于 *address = data
但只有在独占访问标志仍然设置时才会成功写入.如果它确实写入成功,那么它也会清除标志.成功时返回 0,失败时返回 1.如果 STREX
失败,你必须回到 LDREX
并重试.
which is like *address = data
but will only succeed in writing if the exclusive access flag is still set. If it does succeed in writing then it also clears the flag. It returns 0 on success and 1 on failure. If the STREX
fails, you have to go back to the LDREX
and try again.
对于共享变量的简单独占访问,不需要其他任何东西.例如:
For simple exclusive access to a shared variable, nothing else is required. For example:
do {
data = LDREX(address);
data++;
} while (STREXW(address, data));
这种机制的有趣之处在于它实际上是后到先得";如果这段代码被中断并且中断使用了LDREX
和STREX
,STREX
中断将会成功并且(低优先级的)用户代码将有重试.
The interesting thing about this mechanism is that it's effectively 'last come, first served'; if this code is interrupted and the interrupt uses LDREX
and STREX
, the STREX
interrupt will succeed and the (lower-priority) user code will have to retry.
如果您使用的是操作系统,则可以使用相同的原语来构建正确的"信号量和互斥体(请参阅 本应用笔记,例如);但话说回来,如果您使用的是操作系统,您可能已经可以通过其 API 访问互斥锁了!
If you're using an operating system, the same primitives can be used to build 'proper' semaphores and mutexes (see this application note, for example); but then again if you're using an OS you probably already have access to mutexes through its API!
这篇关于ARM 中的关键部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!