volatile 每次存取原始內(nèi)存地址

內(nèi)存訪問(wèn)速度遠(yuǎn)不及CPU處理速度,所以編譯器優(yōu)化:將內(nèi)存變量緩存到寄存器,但是在某些嵌入式場(chǎng)景中優(yōu)化會(huì)出問(wèn)題:

下面是使用volatile變量的幾個(gè)場(chǎng)景:

中斷服務(wù)程序中修改的供其它程序檢測(cè)的變量需要加volatile;

例如:

static int i=0;
int main(void)
{
     ...
     while (1){
if (i) dosomething();
}
}
/* Interrupt service routine. */
void ISR_2(void)
{
      i=1;
}

程序的本意是希望ISR_2中斷產(chǎn)生時(shí),在main函數(shù)中調(diào)用dosomething函數(shù),但是,由于編譯器判斷在main函數(shù)里面沒(méi)有修改過(guò)i,因此可能只執(zhí)行一次對(duì)從i到某寄存器的讀操作,然后每次if判斷都只使用這個(gè)寄存器里面的“i副本”,導(dǎo)致dosomething永遠(yuǎn)也不會(huì)被調(diào)用。如果將變量加上volatile修飾,則編譯器保證對(duì)此變量的讀寫(xiě)操作都不會(huì)被優(yōu)化(肯定執(zhí)行)。此例中i也應(yīng)該如此說(shuō)明。

多任務(wù)環(huán)境下各任務(wù)間共享的標(biāo)志應(yīng)該加volatile

類似上文中中斷服務(wù)程序

存儲(chǔ)器映射的硬件寄存器通常也要加voliate,因?yàn)槊看螌?duì)它的讀寫(xiě)都可能有不同意義。

例如:
假設(shè)要對(duì)一個(gè)設(shè)備進(jìn)行初始化,此設(shè)備的某一個(gè)寄存器為0xff800000。

int  *output = (unsigned  int *)0xff800000;//定義一個(gè)IO端口;
int   init(void)
{
      int i;
      for(i=0;i< 10;i++){
         *output = i;
}
}

經(jīng)過(guò)編譯器優(yōu)化后,編譯器認(rèn)為前面循環(huán)半天都是廢話,對(duì)最后的結(jié)果毫無(wú)影響,因?yàn)樽罱K只是將output這個(gè)指針賦值為9,所以編譯器最后給你編譯編譯的代碼結(jié)果相當(dāng)于:

int  init(void)
{
      *output = 9;
}

如果你對(duì)此外部設(shè)備進(jìn)行初始化的過(guò)程是必須是像上面代碼一樣順序的對(duì)其賦值,顯然優(yōu)化過(guò)程并不能達(dá)到目的。反之如果你不是對(duì)此端口反復(fù)寫(xiě)操作,而是反復(fù)讀操作,其結(jié)果是一樣的,編譯器在優(yōu)化后,也許你的代碼對(duì)此地址的讀操作只做了一次。然而從代碼角度看是沒(méi)有任何問(wèn)題的。這時(shí)候就該使用volatile通知編譯器這個(gè)變量是一個(gè)不穩(wěn)定的,在遇到此變量時(shí)候不要優(yōu)化。
例如:

volatile  int *output=(volatile unsigned int *)0xff800000;//定義一個(gè)I/O端口
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容