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


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

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

1、啓動配置:FTFx_FOPT, BOOT Pin, RCM_FM

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

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內容組織以下:ui

  任何一次熱啓動後,芯片系統會自動從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啓動。3d

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原理圖來講明:code

  在上述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。orm

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。

2、特性配置: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配置痞子衡便介紹完畢了,掌聲在哪裏~~~

相關文章
相關標籤/搜索