我想知道是否有可能确保line
原子执行,因为它可以由ISR和Main上下文执行。我正在使用 ARM9 (LPC313x)并使用 RealView 4 (armcc)。
foo() {
..
stack_var = ++volatile_var; // line
..
}
我正在为C166寻找任何类似_atomic_
的例程,直接汇编代码等。我宁愿不必禁用中断。
非常感谢。
答案 0 :(得分:8)
不,我认为即使你没有作业,你也不能指望++volatile_var
是原子的。为此使用适当的原子基元。如果您的编译器没有提供这样的扩展,您可以在Web上轻松找到简短的内联汇编程序。我认为汇编程序指令是调用ldrex
和strex
进行原子交换。
编辑:似乎问题中要求的特定处理器类型未实现这些说明。
编辑:以下内容适用于gcc,对于另一个编译器,可能需要调整__asm__
部分。
inline
size_t arm_ldrex(size_t volatile*ptr) {
size_t ret;
__asm__ volatile ("ldrex %0,[%1]\t@ load exclusive\n"
: "=&r" (ret)
: "r" (ptr)
: "cc", "memory"
);
return ret;
}
inline
_Bool arm_strex(size_t volatile*ptr, size_t val) {
size_t error;
__asm__ volatile ("strex %0,%1,[%2]\t@ store exclusive\n"
: "=&r" (error)
: "r" (val), "r" (ptr)
: "cc", "memory"
);
return !error;
}
inline
size_t atomic_add_fetch(size_t volatile *object, size_t operand) {
for (;;) {
size_t oldval = arm_ldrex(object);
size_t newval = oldval + operand;
if (arm_strex(object, newval)) return newval;
}
}
答案 1 :(得分:6)
从快速看,C166 _atomic_
宏似乎利用了一条指令,该指令在指定数量的指令期间有效地屏蔽了中断。
没有什么能与ARM架构中的内容直接对应。
您当然可以使用swp指令(或RealView工具链中的__swp内在函数)来实现围绕关键部分的锁定。 ARM体系结构版本5(包括ARM9处理器)中不存在另一个答案中提到的ldrex / strex。 <{3}}和http://infocenter.arm.com/help/topic/com.arm.doc.dui0491c/CJAHDCHB.html。
围绕此实现的简单锁定实现(使用RealView工具链)将是:
{
/* Loop until lock acquired */
while (__swp(LOCKED, &lockvar) == LOCKED);
..
/* Critical section */
..
lockvar = UNLOCKED;
}
但是,当主线程持有锁时,此将导致ISR上下文中的死锁。
我认为围绕操作的屏蔽中断可能是最不费力的解决方案,但如果您的Main上下文在用户模式下执行,则需要系统调用才能实现。