前言:
爲了方便查看博客,特意申請了一個公衆號,附上二維碼,有興趣的朋友可以關注,和我一起討論學習,一起享受技術,一起成長。
1. __ attribute __((at)) 絕對定位
__ attribute __( at(絕對地址) )的作用:
(1)絕對定位到 Flash;
(2)絕對定位到 RAM。
__ attribute __ :用來指定變量或結構位域的特殊屬性,關鍵字後的雙括弧中的內容是屬性說明;
at:用來設置變量的絕對地址,指定某個變量處於內存或 FLASH 裏面的某個給定的地址。
1.1 定位到 FLASH
定位到 flash 中,常用於固化信息,例如:設備的出廠信息,FLASH 標記等;
const uint8_t usFlashInitVal[] __attribute__((at(0x00030000))) = {0x11,0x22,0x33,0x44,0x55,0x66};//定位在flash中,0x00030000開始的6個字節信息固定
1.2 定位到 RAM
常用於數據量較大的緩存,如:串口接收數據。也用於某個位置的特定變量。
uint8_t ucUsartRecvBuffer[USART_RECV_LEN] __attribute__ ((at(0x00025000))); //接收緩衝,最大USART_RECV_LEN個字節,起始地址爲 0x00025000
注:
-
絕對定位不能在函數中定義,局部變量是定義在棧區,棧區是自動分配、釋放,不能定義爲絕對地址,只能於函數外定義;
-
定義的長度不能超過棧或 Flash 的大小,否則導致棧、Flash 溢出。
1.3 測試
比如:在 0x08010000 的 flash 地址上固定寫入數據,如下圖:
如果不加 const 修飾,則定位到了 RAM 。
編譯出來各部分文件大小:
打開編譯出來二進制文件,如下圖:
最後,我們來看一下加與不加 const uint8_t ucaSysFlashVal[] attribute((at(0x08010000))) =
{0x11, 0x22, 0x33, 0x44}; 的 map 表的區別:
原編譯結束的 map 文件各部分文件大小:
添加定位代碼後的 map 文件各部分的大小:
可以發現添加後,RO Data 的大小發生了變化,即定位後 FLASH 的空間佔用加大,並且打開 bin 文件,可以發現中間部分由全 0 填充。