大家好,我是痞子衡,是正經搞技術的痞子,今天痞子衡給大家分享的是在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主頁、知乎主頁、微信公眾號 平臺上,
微信搜索"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦,

轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/228295.html
標籤:嵌入式
