在Cortex-M3指令集中,存在一系列LDREX/STREX指令,这样,如果使用LDREX指令读取位置,则只有在已知地址未被触及的情况下,后续STREX指令才能写入该地址。通常,结果是,如果自LDREX以来未发生任何中断(ARM用语中的“异常”),则STREX将成功,否则将失败。
在Cortex M0中模拟这种行为的最实用方法是什么?我想为M3编写C代码并将其移植到M0。在M3上,您可以这样说:
__inline void do_inc(unsigned int * dat)
{
while(__ strex(__ ldrex(dat)+ 1,dat)){}
}
执行原子增量。我可以想到的在Cortex-M0上实现类似功能的唯一方法是:
根据ldrex/strex函数的使用方式,禁用中断可能会合理地起作用,但是更改“负载独占”的语义似乎很棘手,如果放弃它,则会造成不良的副作用。代码修补的想法似乎可以实现所需的语义,但是似乎很笨拙。
(顺便说一句,附带的问题:我想知道为什么M3上的STREX将成功/失败指示存储到寄存器而不是简单地设置标志吗?它的实际操作需要操作码中有四个额外的位,要求有一个寄存器来保存成功/failure指示,并要求使用“cmp r0,#0”来确定它是否成功。是否期望编译器如果无法从寄存器中获取结果,就无法合理地处理STREX内部函数。 ?进行注册需要两个简短的说明。)
最佳答案
好吧...您仍然需要保留SWP
,但这是一个功能较弱的原子指令。
中断禁用当然可以工作。 :-)
编辑:
-m0上没有SWP,对不起, super 猫。
好的,看来您只剩下中断禁用功能了。
您可以使用gcc-compilable内联汇编作为指导来禁用和正确还原它:
http://repo.or.cz/w/cbaos.git/blob/HEAD:/arch/arm-cortex-m0/include/lock.h