Cortex M3 - 如何使用信号量

Mar*_*n R 5 c arm semaphore cortex-m3

我有一个关于在 cortex m3 中使用信号量的问题。我找到了一个线程“ARM cortex: mutex using bit banding” ARM cortex: mutex using bit banding。有一个问题的简短描述,最后一个答案对我的问题很有用 - 但我不确定如何在 c/c++ 中实现它。

“我从来没有在 ARM 上使用过位带;相反,我倾向于对所有这些操作使用负载独占/存储条件。使用循环来负载独占旧值,计算新值,然后使用一个条件存储来写回它。循环直到条件存储成功(如果不是第一次,它可能会第二次成功)。”

如果有人可以发布如何使用它的简短代码,我将不胜感激。

谢谢,马丁

Igo*_*sky 4

请注意,位带并非在所有实现中都可用(最值得注意的是,NXP 的 LPC1xxx 系列中缺少位带)。

有关使用 LDREX/STREX 实现信号量的官方方法,请参阅ARM 同步基元开发文章。它使用ARM汇编。

下面是我制作的一个简单的类,它使用编译器内部函数(未经测试!)。这个名字可能用词不当,因为它实际上像互斥体一样工作。它还缺少可能需要的 DMB 指令。

class Semaphore
{
  enum { SemFree, SemTaken };
  // semaphore value
  int s;  

public:
  // constructor
  Semaphore(): s(SemFree) {};

  // try to take the semaphore and return success
  // by default block until succeeded
  bool take(bool block = true)
  {
    int oldval;
#if defined(TARGET_LPC1768) // on Cortex-M3 we can use ldrex/strex
    do {
      // read the semaphore value
      oldval = __ldrex(&s);
      // loop again if it is locked and we are blocking
      // or setting it with strex failed
    }
    while ( (block && oldval == SemTaken) || __strex(SemTaken, &s) != 0 );
    if ( !block ) __clrex(); // clear exclusive lock set by ldrex
#else // on arm7 there's only swp
    do {
      // swp sets the pointed data to the given value and returns the previous one
      oldval = __swp(SemTaken, &s);
      // if blocking, loop until the previous value becomes 0
      // which would mean we have successfully taken the lock
    }
    while (block && oldval == SemTaken);
#endif
    return oldval == SemFree;
  }

  // release the semaphore
  void release()
  {
    s = SemFree;
  }
};
Run Code Online (Sandbox Code Playgroud)