volatile本意為“易變的”。
在嵌入式環境中用volatile關鍵字宣告的變數,在每次對其值進行引用的時候都會從原始地址取值,而不會將值儲存在棧或其他位置。
由於該值“易變”的特性所以,針對其的任何賦值或者獲取值操作都會被執行(而不會被最佳化)。由於這個特性,所以該關鍵字在嵌入式編譯環境中經常用來消除compiler的最佳化。
舉例說明一些抗最佳化的1.比如要往某一地址(比如IO口暫存器)送兩指令,讓IO口進行一次翻轉:
以上程式compiler可能做最佳化而成:
結果第一個指令丟失。如果用volatile, compiler就不允許做任何的最佳化,從而保證程式的原意,MCU庫函式中對於IO暫存器的宣告都會使用volatile。
2.用volatile定義的變數會在程式外被改變,每次都必須從記憶體中讀取,而不能重複使用放在暫存器或棧中的備份。
例如:
如果沒有volatile修飾flag則 doSomeThingElse()可能由於編譯器最佳化不會被執行(即使flag的值在其他中斷中被更改)。若如上使用了volatile,則會每次都會從原始地址取值,這樣當原始地址的值更改後則while能中止並繼續執行下方程式碼。
3.很容易得知多工環境下各任務間共享的標誌也應該加volatile。(注:並不意味著添加了關鍵字就可以保證多執行緒安全,非原子操作仍不能保證安全)
4.儲存器對映的硬體暫存器通常也要加voliate,因為每次對它的讀寫都可能有不同意義。
假設要對一個裝置進行初始化,此裝置的某一個暫存器為0xXXXXXX。
順便說一個問題,一個引數既可以是const還可以是volatile嗎?
這是可以的,因為const的意思是隻讀,而不是不變。最簡單的例子比如只讀的狀態暫存器。
volatile本意為“易變的”。
在嵌入式環境中用volatile關鍵字宣告的變數,在每次對其值進行引用的時候都會從原始地址取值,而不會將值儲存在棧或其他位置。
由於該值“易變”的特性所以,針對其的任何賦值或者獲取值操作都會被執行(而不會被最佳化)。由於這個特性,所以該關鍵字在嵌入式編譯環境中經常用來消除compiler的最佳化。
舉例說明一些抗最佳化的1.比如要往某一地址(比如IO口暫存器)送兩指令,讓IO口進行一次翻轉:
以上程式compiler可能做最佳化而成:
結果第一個指令丟失。如果用volatile, compiler就不允許做任何的最佳化,從而保證程式的原意,MCU庫函式中對於IO暫存器的宣告都會使用volatile。
2.用volatile定義的變數會在程式外被改變,每次都必須從記憶體中讀取,而不能重複使用放在暫存器或棧中的備份。
例如:
如果沒有volatile修飾flag則 doSomeThingElse()可能由於編譯器最佳化不會被執行(即使flag的值在其他中斷中被更改)。若如上使用了volatile,則會每次都會從原始地址取值,這樣當原始地址的值更改後則while能中止並繼續執行下方程式碼。
3.很容易得知多工環境下各任務間共享的標誌也應該加volatile。(注:並不意味著添加了關鍵字就可以保證多執行緒安全,非原子操作仍不能保證安全)
4.儲存器對映的硬體暫存器通常也要加voliate,因為每次對它的讀寫都可能有不同意義。
例如:
假設要對一個裝置進行初始化,此裝置的某一個暫存器為0xXXXXXX。
順便說一個問題,一個引數既可以是const還可以是volatile嗎?
這是可以的,因為const的意思是隻讀,而不是不變。最簡單的例子比如只讀的狀態暫存器。