浅谈单片机中变量访问的互斥
本文以stm32為硬件平臺,淺談一下變量訪問的互斥。
假設是裸板,主程序和中斷服務程序都對某個變量進行修改,那么很可能造成數據的不一致。查了一下,主要有兩種解決方法:第一種是關中斷,在訪問公共資源的時候,先把中斷關掉,等訪問完畢,再打開中斷。這樣就避免了中斷程序和主程序的競態。第二種是自己做一個互斥鎖。
怎么做互斥鎖呢?其實互斥是要依賴與硬件的,如果硬件沒有相關的指令或者機制,那就不好辦了。
在x86上,可以用匯編指令XCHG做一個互斥鎖,但是stm32上就沒有這個指令。在翻閱了《Cortex-M3權威指南》后,我有個發現。下面總結一下:
互斥訪問分為加載和存儲,對應的指令對是LDREX/STREX,LDREXH/STREXH,LDREXB/STREXB,分別對應字,半字,字節。
LDREX/STREX的語法格式為:
LDREX ? ?Rxf, ? ?[Rn, #offset] ? ?; 把 (Rn+offset)地址處的內容加載到寄存器 Rxf里
STREX ? ?Rd, Rxf, [Rn, #offset] ;把Rxf的值存儲到(Rn+offset)地址處,這個操作是可以被駁回的(也就是不被執行),如果駁回,Rd的值為1,如果操作成功,Rd的值為0.
在什么情況下會被駁回呢?在執行STREX的時候,僅當在這之前執行過LDREX指令,且在執行過LDREX指令之后沒有其他的STR/STREX指令執行過的時候,才允許執行這個指令。也就是說只有在LDREX執行后的第一條STREX才能成功執行。
這個道理是易于理解的,在讀,改,寫的過程中,我們希望讀的數據是最新的,也就是讀過之后,這個數據不能被別人更新,只能被我更新。如果操作被駁回,說明別人已經修改過了,所以我讀出的數據不是最新的,已經“臟了”。
關于例子文中有,這里就不贅述了。
用這對指令,就可以做一個互斥鎖。怎么做呢?還是以《Cortex-M3權威指南》中的一個例子來說明。
記DeviceALocked是一個位于內存中的R/W變量,用于指示設備A是否已經在使用中。任何一個任務,若欲使用設備A,都必須先檢查這個變量的值。如果它的值為零,則表示設備可以使用。在任務獲取到設備A后,它要把DeviceALocked的值改為1,表示設備A已經被占用。在設備A使用完畢后,該任務通過重新清零DeviceALocked來釋放設備A,從而使其它任務可以使用此設備。?
TryToLockDeviceA
LDR ? R1, =DeviceALocked
LDREX?R2, [R1]
CMP ? R2, #0 ? ? ? ? ?;檢查是否已被鎖住?
BNE LockDeviceAFailed
DeviceAIsNotLocked
MOV ? R0, #1 ? ? ? ? ??;準備鎖住設備A
STREX R2, R0, [R1] ? ??;互斥寫
CMP ? R2, #0
BNE LockDeviceAFailed ?;STREX失敗,設備A可能已被鎖;?準備返回成功值
LockDeviceASucceed
MOV ? R0, #0
POP ? {R1, R2, PC} ? ??;子程序返回?
LockDeviceAFailed
MOV ? R0, #1
POP ? {R1, R2, PC} ? ??;子程序返回?
總結
以上是生活随笔為你收集整理的浅谈单片机中变量访问的互斥的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2020年中国在线少儿英语培训市场研究报
- 下一篇: 分享一篇关于社区团购的竞品分析