對於嵌入式開發中經常遇到類似上述文件的定義,尤其在內存映射部分;爲方便今後理解特舉一個例子進行分析:
#define REG_MEM_BASE (*(volatile unsigend long *)(PA_BAES + 0x00000050))
(1)PA_BASE是一個宏定義
#define PA_BASE 0x40000000 ----一般定義一個內存映射之後某一區域(如IO口映射)的首地址
(2)00000050h
這個是一個內存的偏移地址,實際爲0x40000000+0x00000050=0x40000050
(3)volatile
這個是C中的一個關鍵字,經常在嵌入式開發中使用(尤其是在涉及存儲器操作的時候),目的是告訴編譯器不要對這個變量進行優化,這樣實際代碼中訪問此變量時都會從外部存儲器直接讀取,防止變量值在讀取操作過程中發生變化,而程序卻無法察覺,導致異常錯誤
(4)(volatile unsigend long *)(PA_BAES + 0x00000050)
這表示一個地址,通過unsigned long進行強制轉化;
(5) (*(volatile unsigend long *)(PA_BAES + 0x00000050))
這個表示指針變量,可以看做一個普通變量,這個變量有固定地址,指向PA_BAES + 0x00000050,並且可以進行讀寫操作
(6)爲方便進行讀寫操作,使用#define預定義,將 (*(volatile unsigend long *)(PA_BAES + 0x00000050)) 重新命名爲 REG_MEM_BASE。
注:
關於volatile關鍵字:
volatile 關鍵字是一種類型修飾符,用它聲明的類型變量表示可以被某些編譯器未知的因素更改,比如:操作系統、硬件或者其它線程等。遇到這個關鍵字聲明的變量,編譯器對訪問該變量的代碼就不再進行優化,從而可以提供對特殊地址的穩定訪問。 當要求使用 volatile 聲明的變量的值的時候,系統總是重新從它所在的內存讀取數據,即使它前面的指令剛剛從該處讀取過數據。而且讀取的數據立刻被保存。這個關鍵字是用來設定某個對象的存儲位置在內存中,而不是寄存器中。因爲一般的對象編譯器可能會將其的拷貝放在寄存器中用以加快指令的執行速度。
一般說來,volatile用在如下的幾個地方:
(1)中斷服務程序中修改的供其它程序檢測的變量需要加 volatile;
(2) 多任務環境下各任務間共享的標誌應該加 volatile;
(3) 存儲器映射的硬件寄存器通常也要加 volatile 說明,因爲每次對它的讀寫都可能由不同意義;