痞子衡嵌入式:飛思卡爾Kinetis系列MCU啟動那些事(3)- KBOOT配置(FOPT/BOOT Pin/BCA)



  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是飛思卡爾Kinetis系列MCU的KBOOT配置

  KBOOT是支持配置功能的,配置功能可分為兩方面:一、芯片系統的啟動配置;二、KBOOT特性配置;痞子衡在前一篇文章里介紹了 KBOOT形態(ROM/Bootloader/Flashloader),雖然KBOOT有三種形態,但實際上只有2種類型的芯片載體,即含ROM空間的芯片(比如Kinetis K80)和不含ROM空間的芯片(比如Kinetis KL25),KBOOT配置在這兩種載體上是有區別的,下面痞子衡為大家詳解KBOOT配置:

一、啟動配置:FTFx_FOPT, BOOT Pin, RCM_FM

  芯片系統的啟動配置主要決定的是芯片上電從哪里(ROM/Flash)開始啟動,所以這個啟動配置對於含ROM空間的芯片特別重要,而不適用於不含ROM空間的芯片。

1.1 啟動方式選擇Flash Configuration Field - FOPT

  熟悉Kinetis芯片的朋友肯定知道,Kinetis芯片都是含內部Flash的,內部Flash起始地址一般是0x00000000,Flash操作是通過FTFx這個IP模塊實現的,如果你對FTFx模塊了解的話,這個IP模塊內部其實有一些寄存器屬性是readonly的,並且從手冊里看這些readonly寄存器的初值是undefined,截取K80芯片FTFA模塊中這些readonly寄存器如下:

  既然這些寄存器是readonly屬性並且初值又是undefined的,那么其初值到底取決於什么?這里就涉及到Kinetis芯片中比較特別的FCF加載機制,FCF即Flash Configuration Field,其區域地址為Flash偏移0x400 - 0x40f,一共16個bytes,這16bytes內容組織如下:

  任何一次熱啟動后,芯片系統會自動從FCF區域加載初值進FTFx相應寄存器中,我們主要關注的是跟啟動配置相關的FTFx_FOPT寄存器(特別注意,當FCF中對應FOPT的值是無效值0x00時,在加載過程中芯片自動會給FOPT賦值0xFF),下面是FTFx_FOPT寄存器的bit定義,其中BOOTSRC_SEL和BOOTPIN_OPT位是關鍵(注意這兩個位在不含ROM空間的芯片上是reserved的)。

  BOOTSRC_SEL和BOOTPIN_OPT的值共同決定了芯片的啟動位置(ROM/Flash):

  • BOOTPIN_OPT = 1: 啟動位置完全由BOOTSRC_SEL決定。
  • BOOTPIN_OPT = 0: 啟動位置由BOOTSRC_SEL和BOOTCFG0 pin共同決定。

  因此當在FCF里指定FOPT為0xFF時,芯片上電永遠從ROM啟動;當在FCF里指定FOPT為0x3F時,芯片上電永遠從Flash啟動。

1.2 啟動位置切換BOOT Pin

  在1.1節的最后痞子衡提到了BOOTCFG0 pin,其實BOOTCFG0 pin對於含ROM空間芯片而言就是BOOT Pin,這個BOOT Pin是芯片系統直接指定的,與NMI pin復用(在上電以及ROM執行過程中,NMI pin原本中斷功能是被屏蔽的)。
  你一定會疑惑BOOT pin有什么用?讓我們再回到1.1節的最后,0x3F和0xFF是兩種比較典型的FOPT啟動配置值,但是這種配置值指定的是固定啟動位置,除非你擦除FCF重新燒寫,不然無法輕易改變啟動位置。但是有的時候我們想在不擦除FCF情況下自由切換啟動位置ROM/Flash,這時候就得依靠BOOT Pin,此時我們需要在FCF里指定FOPT為0x3D,讓我們結合下面的TWR-K80F150M原理圖來說明:

  在上述TWR-K80F150M原理圖中,我們可以看到兩個按鍵開關(SW2,SW1)分別連到了K80芯片的NMI_b pin和RESET_b pin,當我們配置FOPT為0x3D時,即啟動位置由BOOTSRC_SEL(2'b00,即從Flash啟動)和BOOTCFG0(NMI)共同決定,如果在RESET_b pin(SW1)按下復位過程中,BOOTCFG0 pin(SW2)一直被按下,那么芯片會從ROM啟動(並且超時也不會跳轉到Application);而如果BOOTCFG0 pin(SW2)沒有被按下,那么芯片會從Flash啟動。是不是瞬間覺得這樣切換啟動位置很方便!
  其實BOOT Pin設計不僅僅只在含ROM空間的芯片上存在,在不含ROM空間的芯片上也支持,只不過在不含ROM空間的芯片上,BOOT Pin是由Bootloader代碼指定的(需要查看芯片手冊Bootloader章節或源代碼),我們知道當芯片不含ROM時,上電默認從Flash起始地址處啟動,而Flash起始地址已被Flash-Resident Bootloader占據,所以上電永遠執行Flash-Resident Bootloader,此時BOOT Pin的意義主要是決定是否要超時跳轉到Application,如果BOOT Pin在RESET_b pin按下復位過程中一直被按下,那么芯片將會一直停留在Bootloader中;如果BOOT Pin沒有被按下,那么芯片在執行Bootloader超時時間到了之后會跳轉到Application。

1.3 強制從ROM熱啟動RCM_FM

  我們知道芯片復位啟動分為冷啟動(POR Pin)和熱啟動(RESET_b Pin),冷啟動是最為徹底的啟動(所有寄存器初值全部重置),而熱啟動並不是徹底啟動(有些寄存器初值不會重置),RCM模塊里有1個寄存器(RCM_FM)就只有冷啟動才能被重置,而且這個寄存器與從ROM啟動息息相關,不得不提。下面是RCM_FM和RCM_MR寄存器的bit定義:

  上述兩個寄存器只在含ROM空間的芯片上存在,其作用是為了保證ROM在執行期間即使不小心發生熱啟動,下一次還是會強制執行ROM程序,而不受FOPT, BOOT Pin狀態變化影響。ROM程序里操作RCM_FM/MR寄存器使能了這一強制ROM啟動功能,具體代碼如下:

// ROM statrup過程中調用的函數
void SystemInit (void)
{
    // ...

    // Set Force ROM bits in RCM. We only set bit 2, so the RCM_MR register doesn't
    // falsely show that the ROM was booted via boot pin assertion.
    RCM->FM = RCM_FM_FORCEROM(2);

    // ...
}

// ROM跳轉到Application之前調用的函數
void shutdown_cleanup(bool isShutdown)
{
    // ...

    // Disable force ROM.
	RCM->FM = RCM_FM_FORCEROM(0);

    // Clear status register (bits are w1c).
	RCM->MR = RCM_MR_BOOTROM(3);

    // ...
}

  因為ROM里有了上述代碼,所以只要芯片上電執行過ROM程序,除非是ROM主動跳轉到了Application或者發生了冷啟動,否則任何與ROM有關的配置修改操作都不會影響到下一次啟動ROM的執行,這種機制可以確保Application一定會被ROM下載進Flash。

二、特性配置:BCA

  除了啟動配置外,KBOOT還支持特性配置,我們知道KBOOT提供的特性功能非常多,比如支持的外設種類豐富、超時時間可設、Application完整性校驗、USB ID可設、運行時鍾可配、加密特性支持、QSPI啟動支持,這些特性可以通過BCA來配置,BCA是Bootloader Configuration Area的簡稱,KBOOT通過從BCA區域加載用戶配置數據完成這些特性配置。BCA配置結構體原型如下(以K80芯片為例):

//! @brief Format of bootloader configuration data on Flash.
typedef struct BootloaderConfigurationData
{
    uint32_t tag;                          //!< [00:03] Tag value used to validate the BCA data. Must be set to 'kcfg'.
    uint32_t crcStartAddress;              //!< [04:07]
    uint32_t crcByteCount;                 //!< [08:0b]
    uint32_t crcExpectedValue;             //!< [0c:0f]
    uint8_t enabledPeripherals;            //!< [10:10]
    uint8_t i2cSlaveAddress;               //!< [11:11]
    uint16_t peripheralDetectionTimeoutMs; //!< [12:13] Timeout in milliseconds for peripheral detection before jumping to application code
    uint16_t usbVid;                       //!< [14:15]
    uint16_t usbPid;                       //!< [16:17]
    uint32_t usbStringsPointer;            //!< [18:1b]
    uint8_t clockFlags;                    //!< [1c:1c] High Speed and other clock options
    uint8_t clockDivider;                  //!< [1d:1d] One's complement of clock divider, zero divider is divide by 1
    uint8_t bootFlags;                     //!< [1e:1e] One's complemnt of direct boot flag, 0xFE represents direct boot
    uint8_t pad0;                          //!< [1f:1f] One's complemnt of direct boot flag, 0xFE represents direct boot
    uint32_t mmcauConfigPointer;           //!< [20:23] Holds a pointer value to the MMCAU configuration
    uint32_t keyBlobPointer;               //!< [24:27] Holds a pointer value to the key blob array used to configure OTFAD
    uint8_t reserved[8];                   //!< [28:2f] Reserved.
    uint32_t qspi_config_block_pointer;    //!< [30:33] QSPI config block pointer.
} bootloader_configuration_data_t;

  如果你想配置KBOOT的特性,必須按上述結構體格式准備好配置數據,具體數據值所代表含義請查看芯片手冊Bootloader章節,痞子衡在后續文章里也會慢慢講到。此處假設你已經准備好了BCA數據,那么這個BCA數據應該放在哪里呢?其實KBOOT已經指定好了BCA位置,見如下代碼,BCA起始地址固定在APP_VECTOR_TABLE地址偏移0x3c0處,對於ROM Bootloader而言,BCA地址就是0x3c0,因為APP_VECTOR_TABLE=0;而對於Flash-Resident Bootloader而言,BCA地址是Bootloader指定的Application起始地址偏移0x3c0處。

//! @brief Flash constants.
enum _flash_constants
{
    //! @brief The bootloader configuration data location .
    //!
    //! A User Application should populate a BootloaderConfigurationData
    //! struct at 0x3c0 from the beginning of the application image which must
    //! be the User Application vector table for the flash-resident bootloader
    //! collaboration.
    kBootloaderConfigAreaAddress = (uint32_t)(APP_VECTOR_TABLE) + 0x3c0
};

  最后再解釋一下BCA地址為何是APP_VECTOR_TABLE + 0x3c0,我們知道ARM Cortex-M系統規定Application前1KB(0x0 - 0x3FF)應放中斷向量表,Cortex-M最大支持256個中斷,其中前16個是系統中斷,后240個是外設中斷,而Cortex-M廠商生產的芯片一般用不滿240個外設中斷,所以其實中斷向量表后半部分其實是reserved的,因此我們可以把reserved區域里的0x3C0 - 0x3FF這64bytes用作BCA配置。

  至此,飛思卡爾Kinetis系列MCU的KBOOT配置痞子衡便介紹完畢了,掌聲在哪里~~~

歡迎訂閱

文章會同時發布到我的 博客園主頁CSDN主頁微信公眾號 平台上。

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM