c 語言嵌入式之:記憶體操作

來源:互聯網
上載者:User

                 (嵌入式C C++語言精華 筆記3)

資料指標

      在嵌入式系統的實際調試中,多藉助c語言指標所具有的對絕對位址單元內容的讀寫能力。以指標直接操作記憶體多發生在

如下幾種情況:

(1)某I/O晶片被定位在CPU的儲存空間而非I/O空間,而且寄存器對應於某特定地址。

(2)兩個CPU之間以雙連接埠RAM通訊,CPU需要在雙連接埠RAM的特定單元(mail box)書寫內容以在對方CPU產生中斷。

(3)讀取在ROM或FLASH的特定單元所燒錄的漢字和英文字摸。

 

unsigned char *p = (unsigned char *) 0xF000FF00;

*p = 11;

(p++; p == 0xF000FF01;)

 意義:在絕對位址0xF0000+0xFF00(80186使用16位段地址和16位位移地址)寫入11。

 

int *p = (int *)0xF000FF00;

p++ ----->  p = p + sizeof(int);

p--   ----->  p = p -  sizeof(int);

 

注意:CPU以位元組為單位編址,而C語言指標以指向的資料類型長度作自增和自減。

 

函數指標

      理解三個問題:

(1) C語言中函數名直接對應於函數產生的指令代碼在記憶體中的地址,因此函數名可以直接賦給指向函數的指標。

(2)調用函數實際上等同於“調轉指令+參數傳遞處理+迴歸位置入棧”,本質上最核心的操作是將函數產生的目標代碼的首

        地址賦給CPU的PC寄存器。

(3)因為函數調用的本質是跳轉到某一個地址單元的code去執行,所以可以“調用”一個根本不存在的函數實體。

 

《微電腦原理》中講到,186CPU啟動後跳轉至絕對位址0xFFFF0(對應 C語言指標是 0xF000FFF0, 0xF000為

段地址, 0xFFF0為段內位移)執行,如例:

 

typedef void (*lpFunction) ();/*定義一個無參數,無傳回型別的函數指標類型
*/

/*定義一個函數指標
,指向CPU啟動後所執行第一條指令的位置*/

lpFunction lpReset = (lpFunction)0xF000FFF0;

lpReset(); /*調用函數*/

上述代碼實現了“軟開機”的作用。

 

 

數組 VS.動態申請

    嵌入式系統中任何不經意的記憶體泄露都會很快導致系統的崩潰。所以一定要保證malloc和free成對出現(原則:誰申請,

就由誰釋放。否則會導致代碼的耦合度增大)。

記憶體申請原則:

(1)儘可能的選用數組,數組不能越界訪問。

(2)如果使用動態申請,則申請後一定要判斷是否申請成功了,並且malloc和free應成對出現。

(值結果參數,值參數)

 

關鍵字 const

   const意味著唯讀。

const  int a;

int  const a;

const int *a;

int * const a;

int const * a  const;

在編譯階段需要的常數只能以#define 宏定義!

故在c語言中如下程式是非法的:

   const int SIZE = 10;

   char a[SIZE]; /*便宜階段不能用到變數*/

 

關鍵字 volatile 防止編譯器最佳化

volatile 變數可能用於如下幾種情況:

(1)平行裝置的硬體寄存器(如:狀態寄存器)

(2)一個中斷服務子程式中會訪問到的非自動變數(也就是全域變數)

(3)多線程應用中被幾個任務共用的變數。

 

CPU字長與儲存空間位寬不一致的處理

 80186的字長為16,而NVRAM的位寬為8,在這種情況下,我們需要為NVRAM提供讀寫位元組,字的介面,如下:

 

typedef  usigned  char  BYTE;

typedef  usigned int  WORD;

/* 函數功能: 讀NVRAM中的位元組

    參數:wOffset, 讀取位置相對NVRAM 基地址的位移

    返回:讀取到的位元組值

*/

extern  BYTE  ReadByteNVRAM(WORD  wOffset)

{

     LPBYTE   lpAddr = (BYTE*) (NVRAM + wOffset * 2); /* 為什麼要乘2? */

     return *lpAddr;

}

 

/* 函數功能: 讀NVRAM中的字

    參數:wOffset, 讀取位置相對NVRAM 基地址的位移

    返回:讀取到的字

*/

 

extern WORD ReadWordNVRAM(WORD  wOffset)

{

    WORD  wTmp = 0;

    LPBYTE  lpAddr;

    /* 讀取高位位元組*/

    lpAddr  = (BYTE*) (NVRAM + wOffset *2);  /* 為什麼要乘2? */

    wTmp += (*lpAddr) *256;

   /* 讀取低位位元組*/

    lpAddr = (BYTE*)(NVRAM + (wOffset +1)*2); /* 為什麼要乘2? */

    wTmp += *lpAddr;

    return wTmp;

}

 

/* 函數功能: 向NVRAM中寫一個位元組

    參數:wOffset, 寫入位置相對NVRAM 基地址的位移

    byData, 欲寫入的位元組

*/

extern void  WriteByteNVRAM(WORD wOffset, BYTE  byData)

{

   ......

}

 

/* 函數功能: 向NVRAM中寫一個字

    參數:wOffset, 寫入位置相對NVRAM 基地址的位移

    byData, 欲寫入的字

*/

 

extern void WriteWordNVRAM (WORD  wOffset, WORD  wData)

{

  .......

}

 

_______                     _________

cpu        | A3--------A2 |                 |

80186    | A2-------A1 |                  |

              | A1-------A0 |   NVRAM    |

              | A0              |                  |

_______|                   |_________|

16位80186與8位NVRAM之間互連只能以地址線A1對其A0,CPU本身的A0與NVRAM不串連,因此,NVRAM的地址只能

是偶數地址,故每次以0x10為單位前進!

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.