痞子衡嵌入式:一次利用IAR自帶CRC完整性校驗功能的實踐(為KBOOT加BCA)
大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家分享的是利用IAR自帶CRC完整性校驗功能的一次實踐(為KBOOT加BCA)。
痞子衡之前寫過兩篇關於IAR中自帶CRC校驗功能的文章 《在IAR開發環境下為工程開啟CRC完整性校驗功能的方法》、《探析開啟CRC完整性校驗的IAR工程生成.out和.bin文件先後順序》,算是把這個功能細節介紹得比較清楚了,但是俗話說得好,理論懂得再多,不能用於實踐那等於沒學。今天痞子衡就利用這個功能來解決一個實際需求:
一、KBOOT中BCA填入CRC校驗需求
說起這個需求,記得那是2014年的第一場雪,那時候痞子衡正在飛思卡爾軟體組參與Kinetis Bootloader項目(簡稱KBOOT)的研發,痞子衡為這個項目寫過一些文章,詳見 《飛思卡爾Kinetis系列MCU開發那些事》 里的啟動篇系列,Kinetis是飛思卡爾當時主推的Cortex-M微控制器,KBOOT就是為Kinetis設計的全功能Bootloader,這可能是嵌入式世界裡第一個精心設計的通用架構Bootloader。這個Bootloader包含一個用戶配置功能(BCA),簡單說就是在用戶Application的偏移0x3c0 – 0x3ff這16個word存放一些Bootloader配置,當Bootloader運行時會先嘗試從Application區域讀出這16個word,獲取用戶配置(超時時間、外設類型、id、速度選項等),然後根據用戶配置再去啟動或升級用戶Application。
CRC完整性校驗功能佔據了BCA里的12個byte,是一個很重要的Bootloader特性,其完整功能詳見 《KBOOT特性(完整性檢測)》,今天痞子衡要說的需求就是直接在Application工程編譯時生成包含正確CRC相關參數的BCA,而不是像以前那樣在最終binary文件里二次編輯添加。
我們以MK64FN1M這顆晶片為例,下載它的軟體包,軟體包里有KBOOT及其示例Application,找到 \SDK_2.8.2_FRDM-K64F\boards\frdmk64f\bootloader_examples\demo_apps\led_demo_freedom_a000\iar 下的Application工程,工程源文件 startup_MK64F12.s 里定義了__bootloaderConfigurationArea,但是CRC區域是全0xFF(即沒有使能),編譯生成的bin文件里CRC區域也是全0xFF,我們要做的就是填入正確的CRC。
二、開始動手實踐
2.1 確定匹配的CRC演算法參數設置
在KBOOT用戶手冊里可以找到其CRC具體演算法,它使用的是比較主流的CRC32-MPEG2分支,具體參數如下表所示:
為了方便核對結果,痞子衡找了一個在線CRC計算的網站,利用這個網站,設置與KBOOT一致的CRC參數(下圖紅色框內),然後我們選取led_demo_freedom_a000.bin的前16個位元組(下圖藍色框內)作為測試數據輸入,點擊Calculate CRC按鈕生成結果0x8D96BDF0(下圖紫色框內)。
在線網站: //www.sunshine2k.de/coding/javascript/crc/crc_js.html
我們現在回到led_demo_freedom_a000工程,在Linker/Checksum下,使能CRC功能,為了與上述測試一致,CRC計算範圍設為 0xa000 – 0xa00f(因為程式起始鏈接地址是0xa000,所以也就是最終.bin里的前16個位元組)。查閱IAR development手冊,做了如下CRC演算法參數設置,編譯工程得到結果也是0x8D96BDF0,因此CRC設置是匹配的。
2.2 填充BCA的首次嘗試
確認了CRC設置,現在就是修改源程式碼了,在BCA的CRC區域里將初始的0xFF值全部更換為真實的CRC設置值__checksum、__checksum_begin、__checksum_end,程式碼簡單修改如下。重編工程後查看.bin文件,發現起止範圍兩個參數是對的,但是CRC校驗值並不對,填成了0x0000a7fc,查看map文件得知這是__checksum的鏈接地址,並不是__checksum的值。想想也是,CRC校驗值是鏈接生成bin後才計算的,但源文件是在鏈接前編譯的,不可能在編譯時得到鏈接後的結果。
2.3 填充BCA的最終方案
首次嘗試失敗,事情遠沒有想像得那麼簡單,我們需要在工程鏈接文件上動心思,要直接把__checksum鏈接到BCA里的具體偏移位置。因此startup_MK64F12.s 里__bootloaderConfigurationArea從crcExpectedValue及其之後全部去掉,並且__FlashConfig也實際不需要(僅對於鏈接在0地址才有效,這是Kinetis特性)。
然後我們需要重新在main.c里定義一個bca常量數組,把除crcExpectedValue之外缺失的BCA數據全部放進去。
const uint32_t bca[16] @ ".bca_left" = {0x1388ffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff};
最後我們需要修改鏈接文件MK64FN1M0xxx12_application_0xA000.icf如下:
//place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec, readonly section .noinit };
//place in FLASH_region { block ApplicationFlash };
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
place at address mem:0xa3cc { ro section .checksum };
place at address mem:0xa3d0 { ro section .bca_left };
place in FLASH_region { readonly section .noinit, block ApplicationFlash };
經過這麼一番操作,讓我們重新編譯工程再看bin里結果,哈哈,這次BCA果然是正確的CRC校驗值了(這次值是0xf62ce2b6,發生了變化,因為源程式碼的改動,bin前16個位元組內容也相應變化了),大功告成。底下的事情就簡單了,在CRC設置介面里調整想要的CRC計算範圍即可。
至此,利用IAR自帶CRC完整性校驗功能的一次實踐(為KBOOT加BCA)痞子衡便介紹完畢了,掌聲在哪裡~~~
歡迎訂閱
文章會同時發布到我的 部落格園主頁、CSDN主頁、知乎主頁、微信公眾號 平台上。
微信搜索”痞子衡嵌入式“或者掃描下面二維碼,就可以在手機上第一時間看了哦。