1. 程式人生 > 實用技巧 >痞子衡嵌入式:一次利用IAR自帶CRC完整性校驗功能的實踐(為KBOOT加BCA)

痞子衡嵌入式:一次利用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(下圖紫色框內)。

線上網站: http://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主頁知乎主頁微信公眾號 平臺上。

微信搜尋"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。