(*(volatileunsigned ……

#define  GPIO_CTL_BASE0x56000000                                                

#define rTCFG0  (*(volatileunsigned *)0x51000000)

#define rTCFG1  (*(volatileunsigned *)0x51000004)

#define rTCNTB0  (*(volatileunsigned *)0x5100000C)

#define rTCMPB0  (*(volatileunsigned *)0x51000010)

#define rTCON  (*(volatileunsigned *)0x51000008)

#define rGPBCON  (*(volatileunsigned *)0x56000010)

#define rGPBUP  (*(volatileunsigned *)0x56000018)

#define rGPBDAT  (*(volatileunsigned *)0x56000014) 
 
下面是網上前輩看到的英文資料: 
Using C, I was trying to assign a variable nameto a register address so thatmy 
code would be readable. An example of how to dothis is as follows: 
#define DDRA (*(volatile unsigned char*)(0x22)) 
This means that if a register or memorylocation exists at address 0×22, I canuse 
DDRA to read or write to it likeso.. 
DDRA =0x05 

In my C code.The #define looks really crypticat first. The way to understandthis 
is by breaking it down intopieces. 
First ofall, 
unsignedchar 
means we are using a byte-sized memorylocation. Byte being 8-bitswide. 
unsigned char * means we are declaring apointer that points to a byte-sizedlocation. 
(unsigned char *)(0x22) 
means the byte-sized pointer points to address0×22. The C compiler will referto 
address 0×22 when the variable DDRA is used.The assembly code will end upusing 
0×22 in Load(LD) and Store (STR)insturctions. 
(*(unsigned char*)(0x22)) 
The first asterisk from the left signifies thatwe want to manipulate the valuein 
address 0×22. * means “the value pointed to bythe pointer”. 
volatile 
volatile forces the compiler to issue a Load orStore anytime DDRA is accessedas 
the value may change without the compilerknowing it. 

中文的解釋: 

#define DDRA (*(volatile unsigned char*)(0x22)) 
   然後就可以用 C 語言對這個內存地址進行讀寫操作了 
   讀:tmp = DDRA; 
   寫:DDRA = 0x55; 
定義 volatile是因爲它的值可能會改變,大家都知道爲什麼改變了; 
如果在一個循環操作中需要不停地判斷一個內存數據,例如要等待 RAM_ADDR 的I標誌位置
位, 因爲 RAM_ADDR 也是映射在 SRAM 空間,爲了加快速度,編譯器可能會編譯出這樣的代碼:
把 RAM_ADDR 讀取到 Register 中,然後不停地判斷 Register相應位。而不會再讀取
RAM_ADDR,這樣當然是不行了,因爲程序或其它事件(中斷等)會改變RAM_ADDR,結果很
可能是一個死循環出不來了。如果定義成 volatile型變量,編譯的代碼是這樣的:每次要
操作一個變量的時候都從內存中讀取一次。 
#define rGPACON(*(volatile unsigned long*)0x56000000) 
對於不同的計算機體系結構,設備可能是端口映射,也可能是內存映射的。如果系統結構支
持獨立的IO地址空間,並且是端口映射,就必須使用彙編語言完成實際對設備的控制,因
爲 C語言並沒有提供真正的“端口”的概念。如果是內存映射,那就方便的多了。 
舉個例子,比如像寄存器 A(地址假定爲 0x48000000)寫入數據0x01,那麼就可以這樣設
置了。 
#define A (*(volatile unsigned long*)0x48000000) 
... 
    A = 0x01; 
... 
   這實際上就是內存映射機制的方便性了。其中 volatile關鍵字是嵌入式系統開發的一個重要特點。上述表達式拆開來分析,首先(volatile unsigned long*)0x48000000的意思是把0x48000000 強制轉換成 volatile unsigned long 類型的指針,暫記爲p,那麼就是#defineA *p,即A 爲P 指針指向位置的內容了。 這裏就是通過內存尋址訪問到寄存器 A,
可以讀/寫操作。 
用 GCC 編譯時。volatile所指示的寄存器不進行優化!!! 

理解#definerRTCCON   (*(volatile unsigned char *)0x57000043) //RTCcontrol 
嵌入式系統編程,要求程序員能夠利用 C語言訪問固定的內存地址。既然是個地址,那麼按
照 C語言的語法規則,這個表示地址的量應該是指針類型。所以,知道要訪問的內存地址後,
比如0x57000043, 
  第一步是要把它強制轉換爲指針類型 
(unsigned char *)0x57000043, s3c2410的rRTCCON是單字節訪問的(怎麼看出來的???
我無法理解),所以 0x57000043 強制轉換爲指向 unsigned char類型。 
  volatile(可變的)這個關鍵字說明這變量可能會被意想不到地改變,這樣編譯器就不
會去假設這個變量的值了。這種“意想不到地改變”,不是由程序去改變,而是由硬件去改
變——意想不到。 
  第二步,對指針變量解引用,就能操作指針所指向的地址的內容了 
   *(volatileunsigned char *)0x57000043 
  第三步,小心地把#define宏中的參數用括號括起來,這是一個很好的習慣。 
在嵌入式系統中經常使用到 Volatile,對於volatile的用法 

編譯器對代碼的優化是指: 
CPU 在執行的過程中,因爲訪問內存的速度遠沒有 cpu的執行速度快,爲了提高效率,引入了
高速緩存 cache. C編譯器在編譯時如果不知道變量會被其它外部因素(操作系統、硬件或者
其它線程)修改,那麼就會對該變量進行標識,即優化.那麼這個變量在CPU的執行過程中,就
會被放到高速緩存 cache 去,進而達到對變量的快速訪問.在瞭解了優化的概念後,試想如
果我們事先就知道該變量會被外部因素改變,那麼我們就在這個變量定義前加上Volatile,
這樣編譯器就不會對該變量進行優化.這樣該變量在 cpu處理的過程當中,就不會被放到高
速緩存 cache中。 
爲什麼要讓變量在執行的過程中不被放到 cache中去呢? 
如果變量是被外部因素改變,那麼 cpu就無法判斷出這個變量已經被改變,那麼程序在執行
的過程中如果使用到該變量,還會繼續使用 cache中的變量,但是這個變量其實已經被改變
了.需要到內存地址中更新其內容了. 
還有一個原因,在一些寄存器變量或數據端口的使用中,因爲寄存器變量本身也是靠cache
來處理,爲了避免引起錯誤,也可以使用volatile修飾符. 

簡單的說使用volatile的目的就是: 
讓對 volatile變量的存取不能緩存到寄存器,每次使用時需要重新存取。



參考閱讀:

http://hi.baidu.com/hustor/item/e4e90d17a68b883ab93180d9

http://blog.sina.com.cn/s/blog_65861d3f0100xsz0.html

http://www.openedv.com/posts/list/918.htm

發佈了40 篇原創文章 · 獲贊 9 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章