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