標(biāo)題: 關(guān)于keil 燒錄hex文件問(wèn)題 [打印本頁(yè)]
作者: sylviayy 時(shí)間: 2025-2-24 13:46
標(biāo)題: 關(guān)于keil 燒錄hex文件問(wèn)題
這幾天遇到了一個(gè)問(wèn)題:
同樣的一份hex文件,在keil(j-link)里燒錄,程序能正常運(yùn)行,但是通過(guò)J-flash反讀出來(lái)的hex文件,會(huì)比原來(lái)的hex文件多出一段數(shù)據(jù) 比如:原來(lái)的hex在0x08049444的地址已經(jīng)結(jié)束,反讀出來(lái)的hex在此地址之后會(huì)多出一段數(shù)據(jù)。
通過(guò)keil調(diào)試,memory窗口定位,在disassembly里對(duì)應(yīng)地址顯示的全是匯編,都是寄存器操作,沒(méi)有對(duì)應(yīng)代碼。截取部分如下:
0x08049477 0000 MOVS r0,r0
0x08049479 0000 MOVS r0,r0
0x0804947B 0100 LSLS r0,r0,#4
0x0804947D 3240 ADDS r2,r2,#0x40
0x0804947F 4210 TST r0,r2
0x08049481 0301 LSLS r1,r0,#12
0x08049483 245D MOVS r4,#0x5D
0x08049485 1AF4 SUBS r4,r6,r3
0x08049487 01AA LSLS r2,r5,#6
用j-flash燒錄或者上位機(jī)(can通訊),程序運(yùn)行不起來(lái),但是反讀出來(lái)的hex與原本的hex一致。!
想問(wèn)問(wèn)大佬是什么原因?keil的編譯器問(wèn)題還是其他的原因?
附加:?jiǎn)纹瑱C(jī)是stm32f407VGT6,程序時(shí)boot+app,這里運(yùn)行不起來(lái)指的是app
0x08049479 0000 MOVS r0,r00x0804947B 0100 LSLS r0,r0,#40x0804947D 3240 ADDS r2,r2,#0x400x0804947F 4210 TST r0,r20x08049481 0301 LSLS r1,r0,#120x08049483 245D MOVS r4,#0x5D0x08049485 1AF4 SUBS r4,r6,r30x08049487 01AA LSLS r2,r5,#60x08049489 1401 ASRS r1,r0,#160x0804948B 7C39 LDRB r1,[r7,#0x10]0x0804948D 5291 STRH r1,[r2,r2]0x0804948F 32C8 ADDS r2,r2,#0xC80x08049491 0206 LSLS r6,r0,#80x08049493 071B LSLS r3,r3,#280x08049495 0332 LSLS r2,r6,#12
作者: zpwgf 時(shí)間: 2025-2-25 09:36
1、keil生成的HEX文件可能僅包含有效代碼段,而J-Flash反讀時(shí)會(huì)以Flash扇區(qū)為單位讀取,導(dǎo)致未使用的扇區(qū)尾部數(shù)據(jù)被包含進(jìn)來(lái),例如,STM32F407的Flash扇區(qū)大小為16KB或128KB,若原HEX文件結(jié)束地址在扇區(qū)中間,反讀時(shí)會(huì)讀取整個(gè)扇區(qū),包含未寫(xiě)入的隨機(jī)殘留數(shù)據(jù);
2、keil燒錄時(shí)可能采用僅擦除代碼占用的扇區(qū),且不處理后續(xù)未使用的區(qū)域。J-Flash默認(rèn)可能擦除整個(gè)扇區(qū),導(dǎo)致未初始化的Flash區(qū)域被填充為隨機(jī)值
3、在Boot+App架構(gòu)中,App的中斷向量表需要重映射到其起始地址,若反讀的HEX文件在App區(qū)域后包含額外數(shù)據(jù),可能導(dǎo)致中斷向量表被覆蓋或偏移錯(cuò)誤,使得App無(wú)法響應(yīng)中斷
驗(yàn)證與解決
1、使用J-Link配合J-Flash的Memory Read功能,直接讀取Flash中App區(qū)域的原始數(shù)據(jù),與Keil生成的HEX文件逐字節(jié)對(duì)比,定位異常數(shù)據(jù)點(diǎn)
2、Keil調(diào)試模式下,單步執(zhí)行App的啟動(dòng)代碼(如Reset_Handler),確認(rèn)棧指針(SP)和中斷向量表地址(VTOR)是否正確加載。若SP指向無(wú)效地址,程序會(huì)立即崩潰
3、使用二進(jìn)制工具(如HexView)對(duì)比Keil生成的HEX和J-Flash反讀的HEX,確認(rèn)多余數(shù)據(jù)的地址范圍。手動(dòng)裁剪反讀的HEX文件,僅保留原HEX的有效地址段
作者: polygram2025 時(shí)間: 2025-2-25 20:48
有未知格式,建議該換方案
作者: sylviayy 時(shí)間: 2025-2-26 09:55
謝謝大佬!
按照你的方法調(diào)試過(guò)程中,發(fā)現(xiàn)查找問(wèn)題點(diǎn)有點(diǎn)偏離,我發(fā)現(xiàn)了個(gè)現(xiàn)象:
在我的工程里,有一個(gè)計(jì)算CRC的批處理文件,它生成完CRC之后會(huì)自動(dòng)回填進(jìn)hex,CRC地址是根據(jù)map文件來(lái)的,取的是ROM結(jié)束地址。
在全編譯工程中,勾選這個(gè)bat文件,編譯后hex顯示以crc校驗(yàn)碼截止;不勾選,編譯后hex在crc之后就會(huì)有上述描述的多的一段數(shù)據(jù)。
(兩次編譯代碼未進(jìn)行改動(dòng),計(jì)算的crc的校驗(yàn)碼一致)左邊勾選編譯,右邊未勾選編譯
ScreenClip.png (248.33 KB, 下載次數(shù): 0)
下載附件
2025-2-26 09:55 上傳
作者: sylviayy 時(shí)間: 2025-2-26 10:02
批處理代碼如下:
- @echo off
- ECHO Computing CRC
- ECHO -------------------------------------
- SET MAP_FILE=1.map
- REM::-------------------------------------get CRC address information line
- SET TMP_FILE=crc_temp.txt
- FINDSTR /R /C:"^ *CHECKSUM" %MAP_FILE%>%TMP_FILE%
- SET /p crc_search=<%TMP_FILE%
- DEL %TMP_FILE%
- REM::-------------------------------------CRC address
- for /f "tokens=1 delims=(" %%a in ("%crc_search%") do set crc_search=%%a
- SET crc_search=%crc_search:CHECKSUM=%
- for /f "tokens=1 delims= " %%a in ("%crc_search%") do set CRC_ADDR=%%a
- SET /a CRC_ADDR_END=%CRC_ADDR%+4
- set CRCA_START_ADDR=0x08020000
- REM::-------------------------------------CRC32 CRC校驗(yàn)范圍 0x08020000 %CRC_ADDR%
- CRC_BIN\srec_cat.exe <font color="#ff0000">1.hex</font> -intel -crop %CRCA_START_ADDR% %CRC_ADDR% -fill 0xff %CRCA_START_ADDR% %CRC_ADDR% -stm32-l-e %CRC_ADDR% -o BRMU\BRMU_checked.hex -intel -output_Block_Size 0x10
- CRC_BIN\srec_cat.exe 1.hex -intel -crop %CRCA_START_ADDR% %CRC_ADDR% BRMU\BRMU_checked.hex -intel -crop %CRC_ADDR% %CRC_ADDR_END% -o 1.hex -intel -output_Block_Size 0x10
- CRC_BIN\srec_cat.exe 1.hex -intel -crop %CRC_ADDR% %CRC_ADDR_END% -byte_swap 4 -o -hex-dump
- del BRMU\BRMU_checked.hex
- ECHO -------------------------------------
- REM exit
復(fù)制代碼
后面臨時(shí)解決辦法,不在原本的hex文件上進(jìn)行填充,而是復(fù)制一份hex再修改,這樣最后工程生成兩個(gè)hex,如第一張圖
- @echo off
- ECHO Computing CRC
- ECHO -------------------------------------
- <b><font color="#ff0000">copy 1.hex 2.hex</font></b>
- SET MAP_FILE=1.map
- REM::-------------------------------------get CRC address information line
- SET TMP_FILE=crc_temp.txt
- FINDSTR /R /C:"^ *CHECKSUM" %MAP_FILE%>%TMP_FILE%
- SET /p crc_search=<%TMP_FILE%
- DEL %TMP_FILE%
- REM::-------------------------------------CRC address
- for /f "tokens=1 delims=(" %%a in ("%crc_search%") do set crc_search=%%a
- SET crc_search=%crc_search:CHECKSUM=%
- for /f "tokens=1 delims= " %%a in ("%crc_search%") do set CRC_ADDR=%%a
- SET /a CRC_ADDR_END=%CRC_ADDR%+4
- set CRCA_START_ADDR=0x08020000
- REM::-------------------------------------CRC32 CRC校驗(yàn)范圍 0x08020000 %CRC_ADDR%
- CRC_BIN\srec_cat.exe <font color="#ff0000">2.hex</font> -intel -crop %CRCA_START_ADDR% %CRC_ADDR% -fill 0xff %CRCA_START_ADDR% %CRC_ADDR% -stm32-l-e %CRC_ADDR% -o BRMU\BRMU_checked.hex -intel -output_Block_Size 0x10
- CRC_BIN\srec_cat.exe 2.hex -intel -crop %CRCA_START_ADDR% %CRC_ADDR% BRMU\BRMU_checked.hex -intel -crop %CRC_ADDR% %CRC_ADDR_END% -o 2.hex -intel -output_Block_Size 0x10
- CRC_BIN\srec_cat.exe 2.hex -intel -crop %CRC_ADDR% %CRC_ADDR_END% -byte_swap 4 -o -hex-dump
- del BRMU\BRMU_checked.hex
- ECHO -------------------------------------
- REM exit
復(fù)制代碼 我猜這個(gè)批處理對(duì)hex進(jìn)行處理的時(shí)候,去掉了后面那一段數(shù)據(jù),但是不知道這個(gè)批處理代碼該怎么修改?
但我還是很奇怪,map里顯示0x080406C4已經(jīng)結(jié)束,后面那一段的數(shù)據(jù)從哪里來(lái)的
?
51hei圖片_20250226100256.png (80.07 KB, 下載次數(shù): 0)
下載附件
2025-2-26 10:02 上傳
麻煩您看看,xiexie!
作者: sylviayy 時(shí)間: 2025-2-26 15:01
批處理代碼如下:
- @echo off
- ECHO Computing CRC
- ECHO -------------------------------------
- SET MAP_FILE=1.map
- REM::-------------------------------------get CRC address information line
- SET TMP_FILE=crc_temp.txt
- FINDSTR /R /C:"^ *CHECKSUM" %MAP_FILE%>%TMP_FILE%
- SET /p crc_search=<%TMP_FILE%
- DEL %TMP_FILE%
- REM::-------------------------------------CRC address
- for /f "tokens=1 delims=(" %%a in ("%crc_search%") do set crc_search=%%a
- SET crc_search=%crc_search:CHECKSUM=%
- for /f "tokens=1 delims= " %%a in ("%crc_search%") do set CRC_ADDR=%%a
- SET /a CRC_ADDR_END=%CRC_ADDR%+4
- set CRCA_START_ADDR=0x08020000
- REM::-------------------------------------CRC32 CRC校驗(yàn)范圍 0x08020000 %CRC_ADDR%
- CRC_BIN\srec_cat.exe <font color="#ff0000">1.hex</font> -intel -crop %CRCA_START_ADDR% %CRC_ADDR% -fill 0xff %CRCA_START_ADDR% %CRC_ADDR% -stm32-l-e %CRC_ADDR% -o BRMU\BRMU_checked.hex -intel -output_Block_Size 0x10
- CRC_BIN\srec_cat.exe 1.hex -intel -crop %CRCA_START_ADDR% %CRC_ADDR% BRMU\BRMU_checked.hex -intel -crop %CRC_ADDR% %CRC_ADDR_END% -o 1.hex -intel -output_Block_Size 0x10
- CRC_BIN\srec_cat.exe 1.hex -intel -crop %CRC_ADDR% %CRC_ADDR_END% -byte_swap 4 -o -hex-dump
- del BRMU\BRMU_checked.hex
- ECHO -------------------------------------
- REM exit
復(fù)制代碼 后面臨時(shí)解決辦法,不在原本的hex文件上進(jìn)行填充,而是復(fù)制一份hex再修改,這樣最后工程生成兩個(gè)hex,如第一張圖- @echo off
- ECHO Computing CRC
- ECHO -------------------------------------
復(fù)制代碼 我猜這個(gè)批處理對(duì)hex進(jìn)行處理的時(shí)候,去掉了后面那一段數(shù)據(jù),但是不知道這個(gè)批處理代碼該怎么修改?
但我還是很奇怪,map里顯示0x080406C4已經(jīng)結(jié)束,后面那一段的數(shù)據(jù)從哪里來(lái)的?
51hei圖片_20250226100256.png (80.07 KB, 下載次數(shù): 0)
下載附件
2025-2-26 15:00 上傳
麻煩您看看,xiexie!
作者: cedtek 時(shí)間: 2025-2-27 02:54
以下內(nèi)容由 DeepSeek R1 生成根據(jù)你提供的批處理腳本和現(xiàn)象分析,問(wèn)題的核心在于 srec_cat工具對(duì)HEX文件的裁剪邏輯不完整,導(dǎo)致未勾選批處理時(shí)HEX文件中殘留了編譯器生成的填充數(shù)據(jù),而勾選批處理時(shí)意外截?cái)嗔诉@些數(shù)據(jù)。以下是詳細(xì)分析和解決方案:
問(wèn)題根源編譯器填充行為 Keil編譯器在生成HEX文件時(shí),默認(rèn)會(huì)根據(jù)Flash扇區(qū)大小(如STM32F407的16KB/128KB)對(duì)代碼段進(jìn)行填充,填充內(nèi)容通常為0xFF或未定義值。這些填充數(shù)據(jù)在MAP文件中不會(huì)顯示,但實(shí)際會(huì)存在于HEX文件中。
批處理腳本的裁剪缺陷 你的批處理腳本通過(guò)srec_cat裁剪HEX文件時(shí),僅保留了0x08020000到CRC_ADDR之間的數(shù)據(jù),忽略了CRC_ADDR之后可能存在的填充數(shù)據(jù)。這導(dǎo)致:
Flash擦除差異 Keil燒錄時(shí)可能僅擦除代碼占用的扇區(qū),而J-Flash默認(rèn)擦除整個(gè)扇區(qū),導(dǎo)致未初始化區(qū)域被填充為隨機(jī)值(如0x00),覆蓋了中斷向量表或其他關(guān)鍵數(shù)據(jù)。
解決方案修改批處理腳本,確保在計(jì)算CRC后,保留原HEX文件中CRC_ADDR之后的所有填充數(shù)據(jù)。以下是修正后的腳本關(guān)鍵步驟:
1. 修改srec_cat命令將第二個(gè)srec_cat命令改為合并三部分?jǐn)?shù)據(jù):
原HEX的CRC地址前部分 (0x08020000到CRC_ADDR)
新生成的CRC部分 (CRC_ADDR到CRC_ADDR_END)
原HEX的CRC地址后部分 (CRC_ADDR_END到Flash末尾)
REM 合并三部分:原HEX的CRC前部分 + 新CRC部分 + 原HEX的CRC后部分
CRC_BIN\srec_cat.exe ^
1.hex -intel -crop %CRCA_START_ADDR% %CRC_ADDR% ^
BRMU\BRMU_checked.hex -intel -crop %CRC_ADDR% %CRC_ADDR_END% ^
1.hex -intel -crop %CRC_ADDR_END% 0x08080000 ^
-o 1.hex -intel -output_Block_Size 0x102. 添加Flash范圍參數(shù)明確指定Flash的完整地址范圍(如0x08000000到0x08080000),確保填充未使用的區(qū)域?yàn)?xFF:
REM 生成臨時(shí)CRC文件時(shí)填充未使用區(qū)域
CRC_BIN\srec_cat.exe ^
1.hex -intel ^
-crop %CRCA_START_ADDR% %CRC_ADDR% ^
-fill 0xFF %CRCA_START_ADDR% 0x08080000 ^
-stm32-l-e %CRC_ADDR% ^
-o BRMU\BRMU_checked.hex -intel
完整修正腳本 @echo off
ECHO Computing CRC
ECHO -------------------------------------
SET MAP_FILE=1.map
SET TMP_FILE=crc_temp.txt
REM 提取CRC地址
FINDSTR /R /C:"^ *CHECKSUM" %MAP_FILE% > %TMP_FILE%
SET /p crc_search=<%TMP_FILE%
DEL %TMP_FILE%
FOR /F "tokens=1 delims=(" %%a IN ("%crc_search%") DO SET crc_search=%%a
SET crc_search=%crc_search:CHECKSUM=%
FOR /F "tokens=1 delims= " %%a IN ("%crc_search%") DO SET CRC_ADDR=%%a
SET /a CRC_ADDR_END=%CRC_ADDR% + 4
SET CRCA_START_ADDR=0x08020000
REM 生成包含CRC的臨時(shí)文件,并填充未使用區(qū)域?yàn)?xFF
CRC_BIN\srec_cat.exe ^
1.hex -intel ^
-crop %CRCA_START_ADDR% %CRC_ADDR% ^
-fill 0xFF %CRCA_START_ADDR% 0x08080000 ^
-stm32-l-e %CRC_ADDR% ^
-o BRMU\BRMU_checked.hex -intel
REM 合并原HEX的CRC前部分、新CRC部分、原HEX的CRC后部分
CRC_BIN\srec_cat.exe ^
1.hex -intel -crop %CRCA_START_ADDR% %CRC_ADDR% ^
BRMU\BRMU_checked.hex -intel -crop %CRC_ADDR% %CRC_ADDR_END% ^
1.hex -intel -crop %CRC_ADDR_END% 0x08080000 ^
-o 1.hex -intel -output_Block_Size 0x10
REM 清理臨時(shí)文件
DEL BRMU\BRMU_checked.hex
ECHO -------------------------------------
關(guān)鍵改進(jìn)點(diǎn)保留填充數(shù)據(jù) 通過(guò)-crop %CRC_ADDR_END% 0x08080000顯式保留原HEX文件中CRC地址后的所有數(shù)據(jù),避免截?cái)嗑幾g器生成的填充。
統(tǒng)一填充值 使用-fill 0xFF ...確保未使用的Flash區(qū)域被初始化為0xFF,避免J-Flash讀取到隨機(jī)值。
完整Flash覆蓋 指定Flash的完整地址范圍(0x08080000為STM32F407VGT6的Flash末尾地址),確保操作覆蓋整個(gè)空間。
驗(yàn)證方法HEX文件對(duì)比 使用二進(jìn)制工具(如HexCompare)對(duì)比Keil生成的原始HEX和批處理后的HEX,確認(rèn)CRC地址后的數(shù)據(jù)是否一致。
Flash內(nèi)容檢查 在Keil調(diào)試模式下,通過(guò)Memory窗口查看CRC_ADDR之后的Flash內(nèi)容,確認(rèn)是否為0xFF或有效數(shù)據(jù)。
J-Flash燒錄測(cè)試 使用修正后的HEX文件通過(guò)J-Flash燒錄,驗(yàn)證App是否能正常啟動(dòng)。
通過(guò)上述修正,批處理腳本將正確保留編譯器生成的填充數(shù)據(jù),同時(shí)確保CRC校驗(yàn)碼的完整性,解決J-Flash反讀多余數(shù)據(jù)導(dǎo)致程序無(wú)法運(yùn)行的問(wèn)題。
作者: rundstedt 時(shí)間: 2025-3-8 11:11
讀flash的軟件又不知道哪里結(jié)束當(dāng)然把全部?jī)?nèi)容讀出來(lái)了。
歡迎光臨 (http://www.torrancerestoration.com/bbs/) |
Powered by Discuz! X3.1 |