市面上很多基于單片機(jī)的產(chǎn)品都具有在線或離線升級功能,為了防止升級過程出現(xiàn)意外,一般我們都會(huì)對Flash程序數(shù)據(jù)進(jìn)行校驗(yàn),常見的就是添加 CRC 校驗(yàn)信息。
本文給大家講述一下Keil和IAR中計(jì)算CRC值的方法。
Flash自檢的流程
Flash的自檢一般分為啟動(dòng)時(shí)自檢和程序運(yùn)行時(shí)自檢兩個(gè)階段。不管是哪種自檢,其思路都是:
在程序編譯完成后,計(jì)算整個(gè)程序的CRC值,然后將這個(gè)CRC值添加到可執(zhí)行文件末尾,再將帶有CRC校驗(yàn)值的可執(zhí)行文件燒錄到MCU中。程序啟動(dòng)后,由程序中的自檢代碼重新根據(jù)當(dāng)前Flash內(nèi)容(不包括預(yù)存的CRC校驗(yàn)值)計(jì)算一次CRC值,再與之前預(yù)先計(jì)算并燒錄到Flash中的CRC校驗(yàn)值進(jìn)行比較,如果一致就通過檢測。
這兩個(gè)自檢階段的區(qū)別就是:
程序啟動(dòng)自檢是一次性對整個(gè)實(shí)際Flash代碼范圍計(jì)算出最終的CRC值;而運(yùn)行時(shí)的自檢,為了不影響其他程序模塊的運(yùn)行,計(jì)算CRC的過程是分步進(jìn)行的,每次計(jì)算一部分,分多次計(jì)算出最終的CRC值。圍繞Flash的自檢所發(fā)生的問題可以歸為兩大類,一類是預(yù)先計(jì)算CRC值時(shí)和上電后計(jì)算CRC值的Flash范圍設(shè)置是否一致;第二類就是預(yù)先計(jì)算CRC時(shí)和上電后計(jì)算CRC采用的CRC算法是否一致。
如何添加CRC值
下面我們主要介紹如何添加CRC校驗(yàn)值到可執(zhí)行文件。
1、基于IAR環(huán)境
如果你使用IAR,那么添加CRC值的配置相對比較簡單。通過配置IAR的CRC計(jì)算參數(shù),自動(dòng)對整個(gè)FLASH空間進(jìn)行CRC計(jì)算,并將計(jì)算結(jié)果放到FLASH的末尾。
1. 修改Link文件,指定CRC值的存放位置
在Link文件中增加下面語句,指定checksum在FLASH中的存儲位置。(可點(diǎn)擊圖片放大查看)
該語句指定將CRC的值放在FLASH的末尾位置,是整個(gè)FLASH空間的末尾,不是應(yīng)用程序的代碼末尾。這樣,CRC值的位置就是固定的。不會(huì)隨代碼大小而變化。
在自檢代碼中,可以通過__checksum讀取Flash中保存的CRC校驗(yàn)值來與重新計(jì)算的CRC值進(jìn)行比較。
2. 配置Checksum頁面的參數(shù)
在link文件中指定了checksum的存儲位置后,還要在工程配置菜單中,配置計(jì)算CRC值的范圍和參數(shù)。見下圖(可點(diǎn)擊圖片放大查看):
IAR的checksum頁面分為兩個(gè)部分。
第一部分,也就是紅線圈出的部分。定義了FLASH中需要計(jì)算CRC的范圍和空閑字節(jié)填充值。這里注意要留出flash末尾存儲CRC值的位置。
剩下的部分,就是對checksum計(jì)算參數(shù)的設(shè)定部分。
Checksum size:?選擇checksum的大小(字節(jié)數(shù))
Alignment:?指定checksum的對齊方式。一般,處理器不支持非對齊訪問時(shí)有用,不填的話默認(rèn)1字節(jié)對齊。
Algorithm:?選擇checksum的算法
Complement:?是否需要進(jìn)行補(bǔ)碼計(jì)算。選擇“As is”就是不進(jìn)行補(bǔ)碼計(jì)算。
Bit order:?位輸出的順序。MSB first,每個(gè)字節(jié)的高位在前。LSB first,每個(gè)字節(jié)的低位在前。
Reverse byte order within word:?對于輸入數(shù)據(jù),在一個(gè)字內(nèi)反轉(zhuǎn)各個(gè)字節(jié)的順序。
Initial value:?checksum計(jì)算的初始化值
Checksum unit size:?選擇進(jìn)行迭代的單元大小,按8-bit,16-bit還是32-bit進(jìn)行迭代。
3. STM32CRC外設(shè)的配置
與上圖IARchecksum的配置對應(yīng),STM32 CRC外設(shè)可以按以下配置:
聚= 0x4C11DB7(CRC32)
Initial_Crc = 0Xffffffff
輸入/輸出數(shù)據(jù)不反轉(zhuǎn)
輸入數(shù)據(jù):根據(jù)實(shí)際Flash范圍設(shè)定,留出CRC校驗(yàn)值的位置
CRC外設(shè)初始化及計(jì)算代碼(可點(diǎn)擊圖片放大查看):
2、基于Keil環(huán)境
KEIL沒有提供直接生成CRC值的功能,所以需要借助外部的工具計(jì)算CRC值,然后添加到可執(zhí)行文件的末尾。 在X-CUBE-CLASSB軟件中提供了bat文件,它會(huì)利用外部工具Srecord來生成整個(gè)Flash的CRC校驗(yàn)碼并放在文件末尾。 這個(gè)工具同樣也可以和標(biāo)準(zhǔn)外設(shè)庫的ClassB庫一起用。 下面我們就來看看如何在KEIL工程中利用Srecord工具來添加CRC值。
1. 安裝Srecord工具
下載Srecord 工具(http://srecord.sourceforge.net )。 將srec_cat.exe,srec_cmp.exe,srec_info.exe拷貝到C:\SREC(自己新建)目錄下。
2. 添加crc_gen_keil.bat及crc_load.ini文件到KEIL工程同級目錄下
打開X-CUBE-CLASSB軟件包中的任意KEIL工程目錄,將其中crc_gen_keil.bat及crc_load.ini文件拷貝到自己的KEIL工程目錄下。
crc_gen_keil.bat:利用外部工具Srecord來生成整個(gè)Flash的CRC校驗(yàn)碼并放在文件末尾。
crc_load.ini:這個(gè)文件調(diào)試時(shí)有用,用來配置調(diào)試時(shí)導(dǎo)入帶CRC校驗(yàn)碼的HEX,避免對FLASH檢測失敗導(dǎo)致程序無法正常運(yùn)行。
這兩個(gè)文件中的內(nèi)容也需要根據(jù)新工程路徑進(jìn)行修改:
將crc_gen_keil.bat中的TARGET_NAME和TARGET_PATH改成跟新工程一致。 否則不能成功的自動(dòng)生成帶CRC校驗(yàn)值的HEX文件。
Crc_load.ini文件中的路徑和文件也要和實(shí)際的一致
3. 添加定義CRC校驗(yàn)碼存儲區(qū)域
(可點(diǎn)擊圖片放大查看)
在分散加載文件中將CHECKSUM指定在代碼的末尾。和IAR不同的是,通過在分散加載文件中+last指定checksum的位置,它不是將其固定放在整個(gè)flash地址的末尾,而是放在實(shí)際代碼的末尾。
(可點(diǎn)擊圖片放大查看)
4. 添加外部命令讓KEIL在編譯結(jié)束后,自動(dòng)生成一個(gè)帶CRC校驗(yàn)值的HEX文件
定義debug和flash download使用的HEX文件路徑,使用帶CRC校驗(yàn)值的HEX文件。
5. STM32CRC外設(shè)的配置
這里需要注意,從X-CUBE-CLASSB的軟件包里拷貝出的crc_gen_keil.bat文件,里面的BYTE_SWAP設(shè)為1,也就是它在計(jì)算CRC值的時(shí)候,輸入的數(shù)據(jù),在一個(gè)字內(nèi)按字節(jié)顛倒順序。
所以直接用HAL_CRC_Calculate函數(shù)進(jìn)行計(jì)算結(jié)果是不對的。可以參考下面的代碼來初始化及進(jìn)行計(jì)算:
(可點(diǎn)擊圖片放大查看)
或者,將crc_gen_keil.bat文件,里面的BYTE_SWAP改為0, 就可以直接調(diào)用HAL_CRC_Calculate函數(shù)進(jìn)行計(jì)算了。
總結(jié)
本文介紹了基于IAR及ARM KEIL中如何添加CRC校驗(yàn)值的過程。在X-CUBE-CLASSB軟件包中,也都可以找到對應(yīng)的例程。如果在調(diào)試中,遇到FLASH CRC校驗(yàn)出錯(cuò),也不用急。
可以從計(jì)算CRC值的范圍設(shè)置是否一致和采用的CRC算法是否一致這兩個(gè)方面去找原因。一定要調(diào)試看看代碼實(shí)際執(zhí)行的情況,比如要測試的地址范圍和實(shí)際代碼執(zhí)行時(shí)計(jì)算的地址范圍是否一樣,防止因?yàn)閏oding錯(cuò)誤造成檢測不通過。
審核編輯:湯梓紅
評論
查看更多