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

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

下面是使用volatile變量的幾個場景:

中斷服務(wù)程序中修改的供其它程序檢測的變量需要加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)生時,在main函數(shù)中調(diào)用dosomething函數(shù),但是,由于編譯器判斷在main函數(shù)里面沒有修改過i,因此可能只執(zhí)行一次對從i到某寄存器的讀操作,然后每次if判斷都只使用這個寄存器里面的“i副本”,導(dǎo)致dosomething永遠也不會被調(diào)用。如果將變量加上volatile修飾,則編譯器保證對此變量的讀寫操作都不會被優(yōu)化(肯定執(zhí)行)。此例中i也應(yīng)該如此說明。

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

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

存儲器映射的硬件寄存器通常也要加voliate,因為每次對它的讀寫都可能有不同意義。

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

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

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

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

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

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

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

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