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
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;
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With