Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cortex M3 - how to use semaphores

I have a question about using semaphores in cortex m3. I've found a thread "ARM cortex: mutex using bit banding" ARM cortex: mutex using bit banding . There is a short description of the problem, and the last answer would be good for my problem - but I am not sure how can I implement it in c/c++.

"I've never used bit-banding on the ARM; my inclination instead would be to use load-exclusive/store-conditional for all such operations. Use a loop to load-exclusive the old value, compute the new value, and use a conditional store to write it back. Loop until the conditional store succeeds (which it probably will the second time, if it doesn't the first)."

I would be very grateful if someone could post a short code how to use it.

Thanks, Martin

like image 912
Martin R Avatar asked Oct 23 '22 12:10

Martin R


1 Answers

Please note that bit-banding is not available on all implementations (most notably, it's missing in NXP's LPC1xxx series).

For an official way of implementing semaphore using LDREX/STREX, see ARM Synchronization Primitives Development Article. It uses ARM assembly.

Below is a simple class I made that uses compiler intrinsics (untested!). The name is probably a misnomer since it actually works like a mutex. It's also missing DMB instructions which might be necessary.

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;
  }
};
like image 142
Igor Skochinsky Avatar answered Oct 30 '22 14:10

Igor Skochinsky