大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是飞思卡尔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特性:

一、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的版本:

  • 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)的更多相关文章

  1. 痞子衡嵌入式:飞思卡尔Kinetis系列MCU启动那些事(1)- KBOOT架构

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔Kinetis系列MCU的KBOOT架构. Bootloader是嵌入式MCU开发里很常见的一种专用的应用程序,在一个没有Boo ...

  2. 痞子衡嵌入式:飞思卡尔Kinetis系列MCU启动那些事(2)- KBOOT形态(ROM/Bootloader/Flashloader)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔Kinetis系列MCU的KBOOT形态. 痞子衡在前一篇文章里简介了 KBOOT架构,我们知道KBOOT是一个完善的Bootl ...

  3. 痞子衡嵌入式:飞思卡尔Kinetis系列MCU启动那些事(3)- KBOOT配置(FOPT/BOOT Pin/BCA)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔Kinetis系列MCU的KBOOT配置. KBOOT是支持配置功能的,配置功能可分为两方面:一.芯片系统的启动配置:二.KBO ...

  4. 痞子衡嵌入式:飞思卡尔Kinetis系列MCU启动那些事(9)- KBOOT特性(IntegrityCheck)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔Kinetis系列MCU的KBOOT之完整性检测(Integrity Check)特性. Application完整性检测是非常 ...

  5. 痞子衡嵌入式:飞思卡尔Kinetis系列MCU启动那些事(10)- KBOOT特性(可靠升级)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔Kinetis系列MCU的KBOOT之可靠升级(Reliable Update)特性. 所谓可靠升级机制,即在更新Applica ...

  6. 痞子衡嵌入式:飞思卡尔Kinetis系列MCU开发那些事 - 索引

    大家好,我是痞子衡,是正经搞技术的痞子.本系列痞子衡给大家介绍的是飞思卡尔Kinetis系列微控制器相关知识. 飞思卡尔半导体(现恩智浦半导体)于2010年开始推出的Kinetis系列昭示着ARM C ...

  7. 痞子衡嵌入式:恩智浦LPC系列MCU开发那些事 - 索引

    大家好,我是痞子衡,是正经搞技术的痞子.本系列痞子衡给大家介绍的是恩智浦LPC系列微控制器相关知识. 恩智浦半导体最早于2003年便开始推出LPC系列MCU,但早期的产品LPC2000/3000系列属 ...

  8. 痞子衡嵌入式:ARM Cortex-M内核MCU开发那些事 - 索引

    大家好,我是痞子衡,是正经搞技术的痞子.本系列痞子衡给大家介绍的是ARM Cortex-M内核微控制器相关知识. ARM公司从2004年开始推出Cortex-M系列内核,迄今Cortex-M家族已经包 ...

  9. 痞子衡嵌入式:飞思卡尔i.MX RT系列MCU启动那些事(1)- Boot简介

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RT系列MCU的BootROM功能简介. 截止目前为止i.MX RT系列已公布的芯片有三款i.MXRT105x, i. ...

随机推荐

  1. Nuxt.js 从入门到放弃

    Nuxt 是 Vue 上的 SSR,也就是服务端渲染应用框架,可在很大程度上解决当前 SPA 和 CSR 的首页加载慢,不利于 SEO 的问题.本场 Chat 就将详细介绍 Nuxt 的使用以及相关概 ...

  2. Ubuntu16.04安装之后连不上无线网?有可能是Realtek rtl8822be的原因

    原以为昨天已基本写完在接触到Ubuntu以来遇到的所有问题了... 没想到今天去看有关ROS的资料时,居然无意间又看到了之前遇到的一个巨坑:安装完Ubuntu16.04之后,无线网用不了,根本无法连接 ...

  3. 如何理解opencv, python-opencv 和 libopencv?

    转:   OpenCV is a computer vision library written using highly optimized C/C++ code. It makes use of ...

  4. Winform将一个窗体显示在另一个窗体中

    private void ShowForm(Form Indexform) { Form1 form1 = new Form1(); form1 .TopLevel = false; form1 .P ...

  5. Python基础之迭代器、生成器

    一.迭代器: 1.迭代:每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值.例如:循环获取容器中的元素. 2.可迭代对象(iterable): 1)定义:具有__ite ...

  6. Shadow Copying导致ASP.NET应用启动很慢的解决办法

    What's Shadow Copying? 我们安装一个应用程序并启动后,我们是无法更新应用程序安装目录中程序集文件的.如果强制替换会提示文件正在使用,如下图所示. 那你可能会问,为什么会无法更新呢 ...

  7. [Zephyr] 1、在linux上安装Zephyr-OS并跑DEMO

    星期五, 14. 九月 2018 02:18上午 - BEAUTIFULZZZZ 0) 前言 Zephyr™项目是一个采用Apache 2.0协议许可,Linux基金会托管的协作项目.为所有资源受限设 ...

  8. Node.js(day5)

    一.NOSQL NOSQL是Not Only SQL的简称,与关系型数据库对应,一般称为非关系型数据库.关系型数据库遵循ACID规则,而NOSQL存储数据时不需要严格遵循固定的模式,因此在大数据的今天 ...

  9. [Swift]LeetCode164. 最大间距 | Maximum Gap

    Given an unsorted array, find the maximum difference between the successive elements in its sorted f ...

  10. [Swift]LeetCode179. 最大数 | Largest Number

    Given a list of non negative integers, arrange them such that they form the largest number. Example ...