芯片是STM32F103ZET6 ,開發環境:keil 5
首先:

我定義了兩個指定位置的變數,一個指定在0x8024020,另一個指定在0x8024000
防止圖看不見,我把設定變數的代碼貼出來:
u16 aim __attribute__((at(0x8024020))) = 2088;
u16 gTEC3_ParamSave __attribute__((at(0x8024000))) =999; //const volatile
然后我用printf輸出,陳述句是這樣的:
printf("%x \r\n",*(u32 *)0X8024020);
printf("%x \r\n",*(u32 *)0x8024000);
然后程式下載,觀察串口輸出 輸出是這樣的:

文字描述:3e7
828
換算可知:0x3e7=999;
0x828=2088;
輸出是沒有問題的
接下來,修改這兩個的初始值,重新下載看能否改寫:
改寫為:
u16 aim __attribute__((at(0x8024020))) = 1500;
u16 gTEC3_ParamSave __attribute__((at(0x8024000))) =777; //const volatile
同樣用printf輸出值
printf("%x \r\n",*(u32 *)0X8024020);
printf("%x \r\n",*(u32 *)0x8024000);
輸出結果為:

文字描述:309
5dc
換算可知:0x309=777;
0x5dc=1500;
這兩個地址里的值被成功改寫
!!!!!看到這,是平淡無奇的,接下來就是怪事了,
F103ZET6片內FLASH有512K,地址0x8000000 - 0x8080000
現在,我改變其中一個的地址值,我把 0X8024020 改為 0X8074020,地址改寫到很遠的地方,但沒有超出FLASH范圍
同時把初始值改變,來觀察值的改變效果
代碼被改為這樣:
u16 aim __attribute__((at(0x8074020))) = 2888;
u16 gTEC3_ParamSave __attribute__((at(0x8024000))) =566; //const volatile
還是用printf()輸出,代碼為:
printf("%x \r\n",*(u32 *)0X8074020);
printf("%x \r\n",*(u32 *)0x8024000);
觀察輸出結果:

文字描述:309
b48
換算出來:0x309=777;
0xb48=2888;
!!!!!強調看一下 0x309 這個資料,
在前面,我在改其中一個地址的同時,已經把他們兩個都重新賦值,一個為2888 ,一個為566,
地址0X8074020 里面的值是被成功改寫成了 2888 ,而0x8024000 里面的值依然是 上一個 777;
百思不得其解!!!
看一下生成的.hex檔案
先看
u16 aim __attribute__((at(0x8024020))) = 2088;
u16 gTEC3_ParamSave __attribute__((at(0x8024000))) =999; //const volatile
先看這個的 .hex檔案,
在生成的.hex檔案中,可以找到:
:10400000E7030000000000000000000000000000C6
:1040200028080000410538A06D01083A0102211A54
為了不誤導,沒有對這兩行做任何改動,
可以看到 : 4000 這個地址寫著 E703 ,也就是 0x3E7,也就是 999
4020 這個地址寫著 2808, 也就是0x828 ,也就是 2088
接下來看
u16 aim __attribute__((at(0x8024020))) = 1500;
u16 gTEC3_ParamSave __attribute__((at(0x8024000))) =777; //const volatile
這個的 .hex檔案,
同樣的地方可以看到:
:1040000009030000000000000000000000000000A4
:10402000DC050000410538A06D01083A0102211AA3
可以看到 : 4000 這個地址寫著 0903 ,也就是 0x309,也就是 777
4020 這個地址寫著 DC05, 也就是0x5DC ,也就是 1500
看到值是被成功改寫的,
************************************************************************************
那
u16 aim __attribute__((at(0x8074020))) = 2888;
u16 gTEC3_ParamSave __attribute__((at(0x8024000))) =566; //const volatile
看一下這個的“例外的”.hex檔案:

文字描述:
:10754000212808C0A80178FFFFFF081B0172011164
:0C755000600808DC111111214E00000041
:020000040807EB
:04402000480B000049
:040000050800A1311D
:00000001FF
在這個的.hex檔案最后幾行,看到0x08074020 的地址里放了一個 480B ,也就是0xb48,也就是 2888
但是 0x8024000 這個地址在哪呢?資料在哪呢?
看完整的.hex檔案就可以看到 在0x0801???? 段 在 7550 這里就結束了,下面就直接跳到 0x0807???? 段 的4020 了,
中間并沒有 關于0x08024000 的二進制段,
這里還有一個奇怪的事情:
在
u16 aim __attribute__((at(0x8024020))) = 2088; u16 aim __attribute__((at(0x8024020))) = 1500;
和
u16 gTEC3_ParamSave __attribute__((at(0x8024000))) =999; u16 gTEC3_ParamSave __attribute__((at(0x8024000))) =777;
小偏移量生成的.hex 檔案中,可以看到 含有大量的 00 段,
3371行 :1072800000000000000000000000000000000000FE
到
6660行 :104000003602000000000000000000000000000078
基本都是 00 ,偶爾有幾個其他地方定義的數,
*********************************************************************
但是,
u16 aim __attribute__((at(0x8074020))) = 2888;
u16 gTEC3_ParamSave __attribute__((at(0x8024000))) =566; //const volatile
他生成的.hex檔案 就非常緊致,完全沒大面積的 00 段
最后幾行可以看到:

3415行 :10754000212808C0A80178FFFFFF081B0172011164
3416行 :0C755000600808DC111111214E00000041
3417行 :020000040807EB
3418行 :04402000480B000049
3419行 :040000050800A1311D
3420行 :00000001FF
這個.hex 我的理解是 :在3416行 代碼段結束后 ,直接跳到0x8074020 定義了 我在那里設定的數,
那為什么小偏移量生成的 .hex 檔案 就要在代碼段結束后,到 我定義的放資料地址 之前 ,要用大量的 00 段 來填充呢?
而我這個大偏移量的地址 生成的檔案這么緊致,沒有用 00 段 一直填充到0x8074020,而是直接跳到0x8074020 定義了 我在那里設定的數,但是卻沒有實作 我在0x8024000 定義的數呢?
???????這是為什么????????????????????????
我猜想,可能就是我在程式中 在有了 0x8074020這樣的大偏移地址,把 0x8024000 這段給折疊了,或者說 省略了,使我無法這樣用這個地址,
我以為是 keil 優化的問題,但是default 到 Lv3 我都試過,沒用的,有了大偏移量,小偏移地址的值就定義不了
******************************************************************************************
最后來看一下我生成 .bin 檔案的奇怪現象:
首先是小偏移量生成的.bin檔案,如下:

Program Size: Code=51760 RO-data=https://bbs.csdn.net/topics/2120 RW-data=53220 ZI-data=46040
這里看到代碼段 Code=51760 50KB, FLASH的資料段 RO-data=https://bbs.csdn.net/topics/2120 這么大, 但是這個.bin檔案卻有 105KB大 ,應該都是用 00 段填充的
接下來看 大偏移量生成的.bin檔案:
不是一個檔案,是一個檔案夾

里面是這樣的:

這里可以說是兩個.bin檔案,而且沒有后綴
一個名為 ER$$.ARM.__AT_0x08074020 ,一個名為 ER_IROM1
ER$$.ARM.__AT_0x08074020 這應該是我在 0x08074020 定義的 資料,
為什么.bin 檔案 會這樣生成???
*************************************************************************
最后的最后 ,說一下
在我定義了 0x8074020 地址的資料后 ,在定義 0x8024000地址 的前面加上 const ,就可以把他編進 .hex檔案
代碼這樣的:
u16 aim __attribute__((at(0x8074020))) = 2888;
const u16 gTEC3_ParamSave __attribute__((at(0x8024000))) =566; //const volatile
代碼段到 0x8024000 之前 還是用大量 00 段 來填充的
為什么不能讓 0x8024000 的地址定義 像 0x8074020 一樣 ,直接跳過去呢?
后面還有想到的 再補充
uj5u.com熱心網友回復:
還有const 比起 直接 __attribute__((at(0x8024000))) 定義到 FLASH 中有什么多的地方嗎?const不指定 位置的話,是直接在 FLASH代碼段后面 加個資料定義嗎?我想上面的情況是 C的編譯系統 設計不合理嗎?
uj5u.com熱心網友回復:
本來不想上來發問,但是怎么都找不到答案,沒辦法試試uj5u.com熱心網友回復:
const u16 aim __attribute__((at(0x8074020))) = 2888;const u16 gTEC3_ParamSave __attribute__((at(0x8024000))) =566; //const volatile
這樣子寫,.hex 也不會用 00 段 一直填充到 0x8074020 地址前面 ,還是直接跳到 0x8074020 里面定義
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/112914.html
標籤:單片機/工控
上一篇:AFG3252任意信號發生器藍屏
下一篇:基于51單片機的步進電機控制
