在Cortex-M0中模拟LDREX/STREX(加载/存储独占)

sup*_*cat 11 assembly arm atomic cortex-m

在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上实现类似功能的唯一方法是:

  1. 让"ldrex"禁用异常并让"strex"和"clrex"重新启用它们,并要求每次"ldrex"必须很快跟随"strex"或"clrex".
  2. 让"ldrex","strex"和"clrex"成为RAM中的一个非常小的例程,其中一条"ldrex"指令被修补为"str r1,[r2]"或"mov r0,#1".让"ldrex"例程将"str"指令插入"strex"例程,然后将"clrex"例程插入"mov r0,#1".拥有可能使"ldrex"序列调用"clrex"无效的所有异常.

根据ldrex/strex函数的使用方式,禁用中断可能会合理地工作,但改变"load-exclusive"的语义似乎很糟糕,如果它被放弃会导致不良副作用.代码修补的想法似乎可以实现所需的语义,但它看起来很笨重.

(顺便说一句,附带问题:我想知道为什么M3上的STREX将成功/失败指示存储到寄存器而不是简单地设置一个标志?它的实际操作需要操作码中的四个额外位,要求有一个寄存器来保持成功/ failure指示,并要求使用"cmp r0,#0"来确定它是否成功.如果编译器没有将结果记录在寄存器中,那么编译器是否能够理智地处理STREX内在函数? ?进入寄存器需要两个简短的指示.)

dom*_*men 5

好吧...您仍然有SWP剩余,但这是一个功能较弱的原子指令。

中断禁用当然可以。:-)

编辑:

-m0上没有SWP,对不起,超级猫。

好吧,看来您只剩下中断禁用功能了。您可以使用gcc可编译的嵌入式asm作为如何禁用和正确还原它的指南:http ://repo.or.cz/w/cbaos.git/blob/HEAD:/arch/arm-cortex-m0/include/

  • Cortex M0的SWP记录在哪里?至于禁用中断,C语言中是否有保存/恢复中断使能标志的好方法,这样在禁用中断的情况下执行的ldrex / strex序列将使中断处于禁用状态? (3认同)