我有一个关于在皮质m3中使用信号量的问题。我找到了一个帖子“ARM cortex:mutex using bit banding”ARM cortex: mutex using bit banding。 有一个简短的问题描述,最后的答案对我的问题有好处 - 但我不知道如何在c / c ++中实现它。
“我从来没有在ARM上使用过bit-banding;我倾向于对所有这些操作使用load-exclusive / store-conditional。使用循环来加载旧值,计算新值并使用条件存储将其写回。循环直到条件存储成功(它可能是第二次,如果它不是第一次)。“
如果有人可以发布短代码如何使用它,我将非常感激。
谢谢, 马丁
答案 0 :(得分:3)
请注意,并非所有实施都可以使用位带(最值得注意的是,它在NXP的LPC1xxx系列中缺失)。
有关使用LDREX / STREX实现信号量的官方方法,请参阅ARM Synchronization Primitives Development Article。它使用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;
}
};