天天看點

痞子衡嵌入式:飛思卡爾Kinetis系列MCU啟動那些事(11)- KBOOT特性(ROM API)

KBOOT的ROM API特性主要存在于ROM Bootloader形态中,KBOOT内部內建了一些Kinetis内部IP子產品driver,這些IP子產品driver首要目的是用于實作KBOOT的功能,但由于這些IP子產品driver會随着KBOOT一起被固化在ROM空間裡,是以如果這些IP driver能夠被外部(主要是運作于Flash中的Application)調用,那麼肯定會節省Application代碼空間,這麼看起來将ROM Bootloader裡的一些IP driver以API的形式export出去是很有意義的,這麼有意義的事,KBOOT當然是會做的。

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

  KBOOT的ROM API特性主要存在于ROM Bootloader形态中,KBOOT内部內建了一些Kinetis内部IP子產品driver,這些IP子產品driver首要目的是用于實作KBOOT的功能,但由于這些IP子產品driver會随着KBOOT一起被固化在ROM空間裡,是以如果這些IP driver能夠被外部(主要是運作于Flash中的Application)調用,那麼肯定會節省Application代碼空間,這麼看起來将ROM Bootloader裡的一些IP driver以API的形式export出去是很有意義的,這麼有意義的事,KBOOT當然是會做的。下面痞子衡給大家介紹KBOOT裡的ROM API特性:

痞子衡嵌入式:飛思卡爾Kinetis系列MCU啟動那些事(11)- KBOOT特性(ROM API)

一、API tree原型

  KBOOT中聲明了如下一個名叫bootloader_tree_t的結構體來組織那些可被export出去的IP子產品driver,結構體前4個成員記錄了版本、版權以及Bootloader等資訊,從第5個成員開始便是那些IP子產品driver API,目前支援導出的子產品API并不多,一共4個:Flash、AES、Kboot、USB。

//! @brief Structure of version property.     typedef union StandardVersion     {         struct {             uint8_t bugfix;     //!< bugfix version [7:0]             uint8_t minor;      //!< minor version [15:8]             uint8_t major;      //!< major version [23:16]             char name;          //!< name [31:24]         };         uint32_t version;   //!< combined version numbers     } standard_version_t;     //! @brief Root of the bootloader API tree.     //!     //! An instance of this struct resides in read-only memory in the bootloader. It     //! provides a user application access to APIs exported by the bootloader.     //!     //! @note The order of existing fields must not be changed.     typedef struct BootloaderTree     {         void (*runBootloader)(void *arg);            //!< Function to start the bootloader executing.         standard_version_t version;                  //!< Bootloader version number.         const char *copyright;                       //!< Copyright string.         const bootloader_context_t *runtimeContext;  //!< Pointer to the bootloader's runtime context.         const flash_driver_interface_t *flashDriver; //!< Flash driver API.         const aes_driver_interface_t *aesDriver;     //!< AES driver API.         const kb_interface_t *kbApi;                 //!< Bootloader API.         const usb_driver_interface_t *usbDriver;     //!< USB driver API.     } bootloader_tree_t;           

  在所有導出的子產品driver API中,Flash driver API是使用最廣泛的,其API原型如下(不同晶片中Flash driver API版本可能不一緻,截止目前共有3個版本:F1.0.x、F1.1.x、F1.2.x):

//! @brief Interface for the flash driver.     typedef struct FlashDriverInterface {     #if !defined(FLASH_API_TREE_1_0)         standard_version_t version; //!< flash driver API version number.     #endif         status_t (*flash_init)(flash_driver_t * driver);     #if defined(FLASH_API_TREE_1_0)         status_t (*flash_erase_all)(flash_config_t *config);         status_t (*flash_erase_all_unsecure)(flash_config_t *config);         status_t (*flash_erase)(flash_config_t *config, uint32_t start, uint32_t lengthInBytes);     #else         status_t (*flash_erase_all)(flash_config_t *config, uint32_t key);         status_t (*flash_erase_all_unsecure)(flash_config_t *config, uint32_t key);         status_t (*flash_erase)(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key);     #endif         status_t (*flash_program)(flash_driver_t * driver, uint32_t start, uint32_t * src, uint32_t lengthInBytes);         status_t (*flash_get_security_state)(flash_driver_t * driver, flash_security_state_t * state);         status_t (*flash_security_bypass)(flash_driver_t * driver, const uint8_t * backdoorKey);         status_t (*flash_verify_erase_all)(flash_driver_t * driver, flash_margin_value_t margin);         status_t (*flash_verify_erase)(flash_driver_t * driver, uint32_t start, uint32_t lengthInBytes, flash_margin_value_t margin);         status_t (*flash_verify_program)(flash_driver_t * driver, uint32_t start, uint32_t lengthInBytes, const uint8_t * expectedData, flash_margin_value_t margin, uint32_t * failedAddress, uint32_t * failedData);         status_t (*flash_get_property)(flash_driver_t * driver, flash_property_t whichProperty, uint32_t * value);     #if (!defined(FLASH_API_TREE_1_0)) && (!defined(FLASH_API_TREE_1_1))         status_t (*flash_register_callback)(flash_driver_t * driver, flash_callback_t callback);         status_t (*flash_program_once)(flash_driver_t * driver, uint32_t index, uint32_t * src, uint32_t lengthInBytes);         status_t (*flash_read_once)(flash_driver_t * driver, uint32_t index, uint32_t * dst, uint32_t lengthInBytes);         status_t (*flash_read_resource)(flash_driver_t * driver, uint32_t start, uint32_t *dst, uint32_t lengthInBytes, flash_read_resource_option_t option);     #endif     } flash_driver_interface_t;           

  下表列出了所有含ROM空間的晶片中Flash driver API的版本:

痞子衡嵌入式:飛思卡爾Kinetis系列MCU啟動那些事(11)- KBOOT特性(ROM API)
  • Note: 子產品driver API設計必須滿足幾個條件:一、API裡不能使用全局變量;二、子產品IRQHandler不能直接當做API

二、API tree位置

  聲明好了bootloader_tree_t結構體原型以及各IP子產品driver API原型,下一步便是在KBOOT中定義如下常量g_bootloaderTree以建立對象配置設定記憶體(不同晶片中g_bootloaderTree版本可能不一緻,下面是用于K80晶片上的K1.3.0版)。

//! @brief Static API tree.     const bootloader_tree_t g_bootloaderTree =     {         .runBootloader = bootloader_user_entry,         .version = {                 .name = kBootloader_Version_Name,                 .major = kBootloader_Version_Major,                 .minor = kBootloader_Version_Minor,                 .bugfix = kBootloader_Version_Bugfix             },         .copyright = bootloaderCopyright,         .runtimeContext = &g_bootloaderContext,         .flashDriver = &g_flashDriverInterface,         .aesDriver = &g_aesInterface     };           

  隻要找到g_bootloaderTree位址,便可以通路到那些IP子產品driver API,現在的問題是如何找到g_bootloaderTree位址?我們知道在KBOOT工程中,如果不在連結檔案裡明确指定g_bootloaderTree位址,連結器會随機配置設定一個位址來存放g_bootloaderTree,這會導緻在不同晶片中g_bootloaderTree位址是不一樣的;但即使強制指定g_bootloaderTree連結位址,如果ROM空間起始位址不一定是從0x1c000000開始,那麼還是難以做到g_bootloaderTree位址統一。到底該怎麼解決這個問題?KBOOT使用了一個巧妙的方法,下面是KBOOT工程的startup檔案(IAR版),KBOOT将g_bootloaderTree的位址放到了中斷向量表第8個向量的位置處(該向量為ARM Cortex-M未定義的系統向量),是以隻要知道了ROM空間的起始位址,那麼偏移0x1c處開始的4bytes便是g_bootloaderTree位址。

MODULE  ?cstartup             ;; Forward declaration of sections.             SECTION CSTACK:DATA:NOROOT(3)             SECTION .intvec:CODE:NOROOT(2)             EXTERN  g_bootloaderTree             PUBLIC  __vector_table             PUBLIC  __vector_table_0x1c             DATA     __vector_table             DCD     sfe(CSTACK)             DCD     Reset_Handler             DCD     NMI_Handler             DCD     HardFault_Handler             DCD     MemManage_Handler             DCD     BusFault_Handler             DCD     UsageFault_Handler     __vector_table_0x1c             DCD     g_bootloaderTree             DCD     0             DCD     0             DCD     0             DCD     SVC_Handler             DCD     DebugMon_Handler             DCD     0             DCD     PendSV_Handler             DCD     SysTick_Handler     		;; ...           

三、調用API的方法

  KBOOT中的ROM API調用方法非常簡單,以K80晶片中Flash driver API調用為例,首先需要按以下步驟定義s_flashInterface指針:

#define BOOTLOADER_TREE_LOCATION (0x1c00001cul)     #define BOOTLOADER_API_TREE_POINTER (*(bootloader_tree_t **)BOOTLOADER_TREE_LOCATION)     static const flash_driver_interface_t *s_flashInterface = BOOTLOADER_API_TREE_POINTER->flashDriver;           

  有了s_flashInterface指針便可以随意通路Flash driver API:

const uint32_t test_program_buffer[2] = { 0x01234567, 0x89abcdef };     flash_config_t flashInstance;     s_flashInterface->flash_init(&flashInstance);     s_flashInterface->flash_erase(&flashInstance, 0x8000, 0x1000);     s_flashInterface->flash_program(&flashInstance, 0x8000, (uint32_t *)test_program_buffer, 8);           

  至此,飛思卡爾Kinetis系列MCU的KBOOT之ROM API特性痞子衡便介紹完畢了,掌聲在哪裡~~~

歡迎訂閱

文章會同時釋出到我的 部落格園首頁、CSDN首頁、微信公衆号 平台上。

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

痞子衡嵌入式:飛思卡爾Kinetis系列MCU啟動那些事(11)- KBOOT特性(ROM API)

  最後歡迎關注痞子衡個人微信公衆号【痞子衡嵌入式】,一個專注嵌入式技術的公衆号,跟着痞子衡一起玩轉嵌入式。

痞子衡嵌入式:飛思卡爾Kinetis系列MCU啟動那些事(11)- KBOOT特性(ROM API)
痞子衡嵌入式:飛思卡爾Kinetis系列MCU啟動那些事(11)- KBOOT特性(ROM API)
痞子衡嵌入式:飛思卡爾Kinetis系列MCU啟動那些事(11)- KBOOT特性(ROM API)

  衡傑(痞子衡),目前就職于恩智浦MCU系統部門,擔任嵌入式系統應用工程師。

  專欄内所有文章的轉載請注明出處:http://www.cnblogs.com/henjay724/

  與痞子衡進一步交流或咨詢業務合作請發郵件至 [email protected]

  可以關注痞子衡的Github首頁 https://github.com/JayHeng,有很多好玩的嵌入式項目。

  關于專欄文章有任何疑問請直接在部落格下面留言,痞子衡會及時回複免費(劃重點)答疑。

  痞子衡郵箱已被私信擠爆,技術問題不推薦私信,堅持私信請先掃碼付款(5元起步)再發。