鑑於此,對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