鉴于此,对ARM的Cortex M3,我可以:的ARM Cortex:互斥使用位绑扎
- 原子读取单个位
- 原子创下了单位
- 原子明确单个位
我怎样才能将这些互斥量样式设置操作:
try lock
take lock
release lock
看来try_lock
或take_lock
将需要两个不会是原子的操作。
我是否需要更多的控制来实现这个目标?禁用全局中断会做到这一点,但似乎应该有更多的手术方法。
鉴于此,对ARM的Cortex M3,我可以:的ARM Cortex:互斥使用位绑扎
我怎样才能将这些互斥量样式设置操作:
try lock
take lock
release lock
看来try_lock
或take_lock
将需要两个不会是原子的操作。
我是否需要更多的控制来实现这个目标?禁用全局中断会做到这一点,但似乎应该有更多的手术方法。
你的rwl_TryLock()
不一定会返回一个失败,如果锁已经被调用时(你的编译器应该至少给出关于代码的警告没有返回值的路径)。请尝试以下操作:
int rwl_TryLock(volatile uint32_t *lock, int who){
Var_SetBit_BB((uint32_t)lock, who);
if(*lock == (1<<who)){ // check that we have exclusive access
// got the lock!
return 1;
}
// do not have the lock
Var_ResetBit_BB((uint32_t)lock, who); // clear the lock flag
return 0;
}
注意上面不会为递归申请同一个锁(也就是工作,如果由who == 1
指定的任务已经锁定,并试图再次声明,上面的代码不会工作正常),但这也是你的原创。另外,Cortex M3上的中断可以非常快速地禁用/启用(这是对NVIC寄存器的简单更新)。你确定你的系统不能忍受额外的几个中断延迟时间来保持处理锁数据结构的代码简单(这通常意味着更容易更正)吗?
一些为经过一番搜索信息:
“ 的ARM Cortex-M3位绑扎 ARM的微控制器内核提供了另一种方式来实现信号量写访问变量的位带别名区导致原子在系统总线级读取 - 修改 - 写入对比特带区域中的存储器位置的访问 如何转换为信号量?位带区域中的变量可以作为信号量的容器,每个客户端“拥有”一个在客户端需要声明信号量时,它通过向位带别名区域中的相应位置写入1来设置自己的位,然后它将读取容器(位带区域)和d检查是否设置了其他位,这意味着客户端已经成功声明了信号量。如果设置了其他位,则客户端将不得不再次清除自己的位,然后重试(可能在等待之后)。 “ (source)
这里是我的粗(未经测试)解释:
/*
* Frees a lock.
*
* @note lock must point to a fully aligned 32 bit integer.
* (atomically set to 0)
*
* @returns 1 if successfull
*/
int rwl_FreeLock(volatile uint32_t *lock){
*lock = 0;
return 1; // always successful
}
/*
* Attempts to acquire a lock
* @param who is the client taking the lock
* @lock pointer to the mutex (uint32_t value in memory)
* @note lock must point to a fully aligned 32 bit integer.
* (atomically set to 1 only if set to 0)
*/
int rwl_TryLock(volatile uint32_t *lock, int who){
// initial check of lock
if(*lock == 0){
Var_SetBit_BB((uint32_t)lock, who);
if(*lock == (1<<who)){ // check that we still have exclusive access
// got the lock!
return 1;
} else {
// do not have the lock
Var_ResetBit_BB((uint32_t)lock, who); // clear the lock flag
return 0;
}
}
}
Var_Set_BB/Var_Reset_BB:设置/清除位使用位绑扎(原子)
但是,它确实不工作!!!
我从来没有在ARM上使用位带;相反,我的倾向是对所有这些操作使用load-exclusive/store-conditional。使用一个循环来加载旧值,计算新值,并使用条件存储将其写回。循环直到条件存储成功(如果不是第一次,它可能会第二次)。
对于这种情况,位带不起作用。这只是设置设备寄存器文件和内存中的位的一种非常简洁的方式。使用Load Exclusive和Store Exclusive指令来实现您的信号量/互斥量。下面是一个可以使用的示例文档,它使用这些说明实现信号量,并详细说明了这是如何工作的。
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0439b/CHDDIGAC.html
话虽这么说,你可以通过使用位绑扎降低互斥的内存占用...
如果两件事情试图访问的锁时,它会像都可以访问故障报告。更好的方法是使用ldrex/strex spinloop。有人说过,在诸如DMA之类的东西存在的情况下,比特带访问在多大程度上保证了原子性?如果DMA写入和位带写入大致同时发生,DMA写保证不会在位带写入的“读”和“写”方面发生? – supercat 2012-06-13 19:12:45