嵌入式中的 *(volatile unsigned int *)理解
先看一個(gè)例子:
*(volatile?unsigned?int?*)0x500?=?0x10
①(unsigned int *)0x500:將地址0x500強(qiáng)制轉(zhuǎn)化為int型指針
?②(unsigned int )0x500=0x10:對地址為0x500賦值為0x10
volatile關(guān)鍵字有以下用途:
用來同步,因?yàn)橥粋€(gè)東西可能在不同的存儲(chǔ)介質(zhì)中有多個(gè)副本,有些情況下會(huì)使得這些副本中的值不同,這是不允許的,所以干脆用volatile,讓它只有一個(gè),沒有其他的副本,這樣就不會(huì)發(fā)生不同步的問題。
如volatile的意思是告訴編譯器,在編程源代碼時(shí),對這個(gè)變量不要使用優(yōu)化。
?在一般的程序設(shè)計(jì)中,如:
?int *a; int b;b = (*a) * (*a);
這種情況下通常編譯器為了減少存儲(chǔ)器的讀寫時(shí)間,會(huì)把代碼優(yōu)化為int *a; int b; int c;
如果把
?c = *a;b = c * c;int *a
改為volatile int* a
編譯器就不會(huì)自動(dòng)把它優(yōu)化掉了。在整個(gè)運(yùn)算過程中,對變量*a的值又讀取了一次。防止因變量*a的值在這一期間發(fā)生了改變,而導(dǎo)致程序結(jié)果的錯(cuò)誤。
防止編譯器優(yōu)化去掉某些語句
我在arm中見到個(gè)寄存器非常奇怪,
?當(dāng)中斷來的時(shí)候,相對應(yīng)的位置1,而清0又不能向這位寫0,向這位寫1才是1才是清中斷(清0),
?// 假設(shè)0x560012300 為寄存器地址
?#define INTPAND *(volatile unsigned int *)0x560012300
;
?INTPAND = INTPAND; // 清中斷
?像編譯器如果看到有INTPAND = INTPAND;這種看似無用的操作,如果沒有volatile說明,編譯器就很有可能會(huì)去掉INTPAND = INTPAND;實(shí)際上有用的東西,卻被編譯器當(dāng)沒用的東西優(yōu)化掉了。
當(dāng)?shù)刂肥莍o端口的時(shí)候,讀寫這個(gè)地址是不能對它進(jìn)行緩存的,這是相對于某些嵌入式中有cache才有這個(gè)。
比如寫這個(gè)io端口的時(shí)候,如果沒有這個(gè)volatile,很可能由于編譯器的優(yōu)化,會(huì)先把值先寫到一個(gè)緩沖區(qū),到一定時(shí)候
?再寫到io端口,這樣就不能使數(shù)據(jù)及時(shí)的寫到io端口,有了volatile說明以后,就不會(huì)再經(jīng)過cache,write buffer這種,而是直接寫到io端口,從而避免了讀寫io端口的延時(shí)。