大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家分享的是在IAR開發環境下為工程開啟CRC完整性校驗功能的方法。
CRC校驗在嵌入式領域里的應用非常廣,比如在通信領域,CRC檢驗值可以作為數據包的一部分,用於檢查一包數據傳輸過程中是否發生了比特錯誤,如果CRC校驗失敗,那么接收方可以通知發送方要求該包數據重新傳輸,這樣能大大增加數據傳輸的可靠性。同時CRC在應用程序完整性驗證方面也有廣泛應用,相比和檢驗,CRC校驗糾錯能力更強;相比簽名校驗,CRC校驗在速度方面又占優勢,因此它是一個各方面比較均衡的完整性驗證手段。
IAR是個非常老牌的嵌入式開發集成環境,它的功能非常強大,有很多寶藏功能值得我們去發掘。痞子衡自畢業之后就一直在使用IAR,算是一路看着它從古典畫風的v6.50.x升級到現在潮流的v8.50.x,對於經典的CRC校驗功能的支持,IAR當然不會放過,今天痞子衡就來介紹IAR下如何使用其自帶的CRC校驗功能。
一、ielftool命令行工具
IAR安裝目錄下有非常多的命令行小工具,這些小工具其實就是IAR的核心,集成開發環境界面只是提供人機交互,其背后的很多功能都是通過調用這些命令行小工具來實現的。其中用於實現CRC校驗的功能就包含在ielftool.exe工具里:
ielftool.exe工具跟CRC相關的一共兩個參數選項,一是--fill用於填充,二是--checksum用於設置算法,具體參數使用細節詳見 \IAR Systems\Embedded Workbench 8.50.6\arm\doc\EWARM_DevelopmentGuide.ENU手冊里的Checksum calculation for verifying image integrity小節。
此處痞子衡僅舉一個簡單例子,如下命令表示在源可執行文件sourceFile.out中計算范圍__checksum_begin - __checksum_end之間的CRC結果,最終校驗值__checksum長度為4字節、固定CRC32算法、計算單元為1字節、指定CRC初始值為0xffffffff,其余設置默認,並將結果放在目標可執行文件destinationFile.out中。
ielftool --fill="0xFF;__checksum_begin–__checksum_end"
--checksum="__checksum:4,crc32:p,0xffffffff;__checksum_begin-__checksum_end"
sourceFile.out
destinationFile.out
從上面的命令你應該能知道,sourceFile.out並不是任意可執行文件都行的,其必須包含必要的__checksum_begin、__checksum_end、__checksum的定義。假設我們代碼中並沒有實際使用CRC,那么我們需要在生成sourceFile.out文件的IAR工程選項里做如下設置:
注意:__checksum_begin、__checksum_end符號、__checksum變量、.checksum段四個名字,用戶都可以自定義的,這里命名成這樣主要是為了和IAR默認定義相統一。
讓我們隨便找一個嵌入式IAR工程按上面設置生成源hello_world.out文件,並使用ielftool工具執行一次命令看看,可以看到產生了__checksum值,新生成的hello_world_1.out文件里包含了正確的CRC校驗結果。
二、為工程添加CRC校驗
IAR界面里有兩種使用ielftool來生成CRC校驗值的方法,痞子衡一一介紹:
2.1 利用Checksum功能
第一種是直接在IDE界面里配置,我們隨便打開一個嵌入式工程,比如 \SDK_2.8.2_FRDM-K64F\boards\frdmk64f\demo_apps\hello_world\iar\,在工程選項Linker/Checksum下面,勾選Fill unused code memory和Generate checksum便使能了CRC校驗,藍色框里的兩個地址用於設置CRC計算范圍,綠框里的參數用於設置CRC算法細節,具體每個配置什么意義可以查看 \IAR Systems\Embedded Workbench 8.50.6\arm\doc\EWARM_DevelopmentGuide.ENU手冊里的Checksum一節,痞子衡在這里不予展開。
下圖示例配置中有兩點要說明:一、算法選擇了CRC32,其多項式系數其實固定為0x04C11BD7;如果想自定義CRC32多項式系數值,可選CRC polynomial;二、因為地址設置的是 0x0 - 0x400,一共1025個字節(包含0x400),所以checksum unit size此處僅能選8-bit,因為IDE強制要求地址對齊。
設置好之后重新編譯工程,此時會報錯“ielftool error: The string '__checksum' was not found in the string table ”,因為在程序代碼里,我們完全沒有任何CRC相關的引用,IAR會忽略界面里使能的CRC功能,所以我們還需要將__checksum強行加入如下選項里(注意__checksum是IAR里默認定義的CRC檢驗值符號名)。
這時候再編譯工程就可以在生成的.out和.map文件里看到CRC信息了,__checksum被鏈接器隨機放在了0x2844的位置,__checksum_begin和__checksum_end是IAR默認記錄CRC計算范圍的符號變量名。
如果你想自己決定__checksum的鏈接位置,你可以在工程鏈接文件里添加放置 section .checksum,這個段便對應着__checksum。比如我們試着將這個段放在0x1000的位置:
再一次編譯工程,查看map文件,這次__checksum被放在了我們指定的0x1000的位置。
2.2 利用Post-build功能
第二種方式是利用IDE里的Post-build功能,在第一節的基礎上,在工程選項Linker/Extra Options里把ielftool命令加進去,這樣在編譯工程的時候,IAR會自動跑這個命令:
$TOOLKIT_DIR$\bin\ielftool --fill="0xFF;__checksum_begin-__checksum_end" --checksum="__checksum:4,crc32:p,0xffffffff;__checksum_begin-__checksum_end" --verbose "$TARGET_PATH$" "$TARGET_PATH$"
上述命令與第一節中命令基本一致,只是用"$TARGET_PATH$" "$TARGET_PATH$"替代了sourceFile.out destinationFile.out,並且加了--verbose顯示執行操作信息:
三、在工程中驗證CRC校驗
IAR生成的CRC校驗值在應用程序里的使用就比較簡單了,見如下代碼,其中calc_crc()函數需與我們之前在IAR配置的CRC算法參數相一致,此外代碼中的數據類型也是與具體CRC配置有關的。
另外還有兩個注意點:一、CRC計算范圍不應包含__checksum存放位置;二、CRC計算范圍如果沒有按照算法對齊要求,那么實際計算時要相應補上0(使用IDE配置生成是強制對齊的,但是使用命令行沒有強制對齊)。
extern uint32_t const __checksum;
extern int32_t __checksum_begin;
extern int32_t __checksum_end;
void TestChecksum()
{
uint32_t calc = 0;
// 根據CRC計算范圍重算新CRC校驗值
calc = calc_crc(0xFFFFFFFF,
(uint8_t *) &__checksum_begin,
((uint8_t *) &__checksum_end - ((uint8_t *) &__checksum_begin) + 1));
// 比對新CRC校驗值與IAR生成的CRC校驗值
if (calc != __checksum)
{
printf("Incorrect checksum!\n");
}
}
至此,在IAR開發環境下為工程開啟CRC完整性校驗功能的方法痞子衡便介紹完畢了,掌聲在哪里~~~
歡迎訂閱
文章會同時發布到我的 博客園主頁、CSDN主頁、知乎主頁、微信公眾號 平台上。
微信搜索"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。