痞子衡嵌入式:飞思卡尔Kinetis系列MCU启动那些事(10)- KBOOT特性(可靠升级)
大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是飞思卡尔Kinetis系列MCU的KBOOT之可靠升级(Reliable Update)特性。
所谓可靠升级机制,即在更新Application过程中不论发生任何异常情况(通信异常、系统断电等)都能保证系统中至少有一份可用的Application用于恢复启动,保证系统的正常运行。可靠升级是任何鲁棒的Bootloader架构都应该要有的特性。作为一个健全的Bootloader架构,KBOOT中当然包含可靠升级特性。今天痞子衡就为大家介绍KBOOT中的Reliable Update特性:
一、可靠升级基本策略
可靠升级基本策略其实很简单,在Flash里划分2个区,主分区用于存放待启动的Application,备份区用于临时存放新更新的Application,下载时永远只往备份区存最新的Application,这样即使下载过程中发生意外,也仅导致备份区里的Application不完整,不影响主分区里的Application正常运行。仅当备份区里的Application经过Bootloader验证是完整的(详见痞子衡之前写过的 《KBOOT特性(完整性检测)》 一文,通过完整性检测即认为Application是完整的),Bootloader才会启动更新工作,将主分区里Application擦除,然后将备份区里的Application拷贝到主分区,最后擦除备份区里的Application,在这更新过程中不用担心意外,因为任何时候Flash里都至少有一个Application是完整的。
KBOOT里的可靠升级特性就是按照上述基本策略实现的,但是我们知道KBOOT架构适用于上百种Kinetis芯片,上百种芯片特性各异,但就可靠升级这一特性而言,Kinetis芯片被分为三类:
- 第一类:不含ROM,且Flash没有SWAP特性,如MKL25Z128
- 第二类:不含ROM,但Flash含有SWAP特性,如MK65FN2M
- 第三类:含ROM,无论Flash是否含有SWAP,如MKE18F512
KBOOT可靠升级在三类Kinetis芯片上的实现是有区别的。对于第一类,Flash起始地址存放固定的Bootloader,Main/Backup App紧随其后,这也是最常见的情形;对于第二类,因为Flash有SWAP特性,所以Flash被严格分为两个大小相等的Block,SWAP特性可以直接逻辑上交换这两个Block,因此两个Block除了各自存放Application之外还分别存放了Bootloader;对于第三类,这就比较简单了,Bootloader在独立的ROM区域,不占用Flash空间,因此Flash直接均分2等份,一份放Main App,另一份放Backup App就行。
二、可靠升级具体实现
上一节讲过,根据Kinetis芯片Flash是否含有SWAP特性,可靠升级的实现是不同的。如果Flash有SWAP特性,我们称之为硬可靠升级;反之,如果Flash不含SWAP特性,我们称之为软可靠升级。在介绍可靠升级具体实现逻辑之前,痞子衡先为大家比较一下软/硬可靠升级的差异:
比较项目 | 软可靠升级 | 硬可靠升级 |
---|---|---|
适用芯片 | 所有Kinetis | 仅含SWAP特性的Kinetis |
Flash内容分布 | Bootloader + Main App + Backup App | Main Bootloader + Main App + Backup Bootloader + Backup App |
备份区App存放地址 | 灵活定义 | 固定的 |
能否保留2份App | 不可以 | 可以 |
2.1 触发方式
不管是硬可靠升级还是软可靠升级都有两种触发方式,一种是上电启动自触发,上电Bootloader运行时会尝试执行一次可靠升级,这种触发方式是被动地且是一次性的;另一种是命令式触发,即用户通过blhost.exe发送reliable-update命令主动执行可靠升级,这种方式可重复多次。
2.1.1 命令式触发
命令式触发是触发可靠升级操作的第一选择,备份区下载完最新的Application后应紧跟着发送可靠升级命令完成新旧Application的更新。reliable-update命令格式在输入blhost -?命令后可以看到:
reliable-update命令仅有一个addr参数,对于硬可靠升级,这个addr参数是swap indicator地址(想了解swap indicator的意义需要查看Kinetis手册FTFx一节),如果是首次启动硬可靠升级,swap indicator地址可任意设置,如果已经启动过硬可靠升级,swap indicator已经存在芯片IFR里,此时addr必须与已存的swap indicator相一致;对于软可靠升级,这个addr参数即备份区Application的存放起始地址(如果addr为0,则使用Bootloader里预定义的backup app存放地址)。
2.1.2 上电自触发
上电自触发方式存在的原因是,用户在备份区下载完Application之后可能会忘了主动触发可靠升级,或者在执行主动可靠升级的过程中发生了异常,那么系统下一次启动时应主动做一次可靠升级,确保将备份区最新的Application拷贝到主分区去运行。下图是自触发可靠升级在Bootloader启动流程中的位置:
2.2 主逻辑
无论是上电自触发还是命令式触发,在Bootloader里其实都是调用的如下函数bootloader_reliable_update_as_requested(),命令式触发传入的参数值是(kReliableUpdateOption_Swap, addr),上电自触发传入的参数值是(kReliableUpdateOption_Normal, 0)
void bootloader_reliable_update_as_requested(reliable_update_option_t option, uint32_t address)
{
uint32_t backupApplicationBase;
#if BL_IS_HARDWARE_SWAP_ENABLED
// 仅对于硬可靠升级,才区分option参数的差异
uint32_t swapIndicatorAddress = address;
if (option == kReliableUpdateOption_Normal)
{
// 检测主分区App是否有效,如果有效,则不进行可靠升级
uint32_t mainApplicationBase = get_application_base(kSpecifiedApplicationType_Main);
if (is_specified_application_valid(mainApplicationBase))
{
update_reliable_update_status(kStatus_ReliableUpdateStillInMainApplication);
return;
}
else
{
// 检测flash swap状态看其是否处于Ready状态,如果是,则从IFR里读取已存swap indicator值
status_t result = get_swap_indicator_address_if_system_is_in_ready(&swapIndicatorAddress);
if (result != kStatus_FLASH_Success)
{
update_reliable_update_status(kStatus_ReliableUpdateSwapSystemNotReady);
return;
}
}
}
backupApplicationBase = get_application_base(kSpecifiedApplicationType_Backup);
#else
// 获取备份区App的存放地址
backupApplicationBase = (address == 0) ? get_application_base(kSpecifiedApplicationType_Backup) : address;
#endif // BL_IS_HARDWARE_SWAP_ENABLED
// 检测备份区App的BCA配置是否有效,BCA有效是进行可靠升级的前提
if (!is_reliable_update_active(backupApplicationBase))
{
update_reliable_update_status(kStatus_ReliableUpdateInacive);
}
else
{
// 仅当备份区App通过了完整性检测,才会进行可靠升级
if (is_specified_application_valid(backupApplicationBase))
{
#if BL_IS_HARDWARE_SWAP_ENABLED
status_t status = hardware_reliable_update(swapIndicatorAddress);
#else
status_t status = software_reliable_update(backupApplicationBase);
#endif // BL_IS_HARDWARE_SWAP_ENABLED
update_reliable_update_status(status);
}
else
{
update_reliable_update_status(kStatus_ReliableUpdateBackupApplicationInvalid);
}
}
}
2.2.1 软可靠升级流程
软可靠升级流程如下,首先根据不同触发方式获取备份区App的存放地址,然后检测备份区App是否合法(包含BCA,且通过完整性验证),一旦备份区App被验证是合法的,Bootloader会擦除主分区App并将备份区App拷贝到主分区,最后再擦除备份区App。有朋友会疑问,为何最后要擦除备份区App,因为当前的软可靠升级实现在自触发方式下第一件事就是去验证备份区App是否有效,如果备份区App不擦除的话,每次上电都会做一次擦除和更新操作,会损耗Flash寿命。
上述流程就是KBOOT 2.0里的软可靠升级的实现逻辑。那么这个流程有没有改进空间呢?其实是有的。如果我们在App的BCA区域增加一个版本号,那么就可以做到在Flash里保留两份App。此时Bootloader下载App时不再需要提供存放地址,Bootloader自动解析App的版本号,并用这个最新的App替换Flash里版本最低的App。而Bootloader启动时永远寻找当前Flash里版本最高的App去执行。
Note: 改进后的软可靠升级有一个注意点,即Flash里XIP App并不是与位置无关的,因此两份App的链接文件根据存放位置不同,链接起始地址是不同的。
2.2.2 硬可靠升级流程
硬可靠升级相比软可靠升级,在流程看起来更复杂,因为硬可靠升级涉及Flash的SWAP特性,不过硬可靠升级不具通用性,因此痞子衡不打算详细解释其流程,感兴趣的自己研究下面的流图。
2.3 配置宏和状态码
对于KBOOT 2.0来说,目前仅有MK65默认使能了可靠升级,如果想要在其他芯片上也使能这一特性,需要在对应芯片的bootloader_config.h里修改/增加如下三个宏:
- BL_FEATURE_RELIABLE_UPDATE: 设为1则使能可靠升级特性
- BL_FEATURE_HARDWARE_SWAP_UPDATE: 设为1则为硬可靠升级,0则为软可靠升级
- BL_BACKUP_APP_START: 预定义的备份区App存放地址
在使用reliable-update命令的过程中会返回执行结果状态码,以及可以用get-property获得当前可靠升级状态机的状态,一共有如下8个状态码:
至此,飞思卡尔Kinetis系列MCU的KBOOT之可靠升级(Reliable Update)痞子衡便介绍完毕了,掌声在哪里~~~
欢迎订阅
文章会同时发布到我的 博客园主页、CSDN主页、微信公众号 平台上。
微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。
痞子衡嵌入式:飞思卡尔Kinetis系列MCU启动那些事(10)- KBOOT特性(可靠升级)的更多相关文章
- 痞子衡嵌入式:飞思卡尔Kinetis系列MCU启动那些事(1)- KBOOT架构
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔Kinetis系列MCU的KBOOT架构. Bootloader是嵌入式MCU开发里很常见的一种专用的应用程序,在一个没有Boo ...
- 痞子衡嵌入式:飞思卡尔Kinetis系列MCU启动那些事(2)- KBOOT形态(ROM/Bootloader/Flashloader)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔Kinetis系列MCU的KBOOT形态. 痞子衡在前一篇文章里简介了 KBOOT架构,我们知道KBOOT是一个完善的Bootl ...
- 痞子衡嵌入式:飞思卡尔Kinetis系列MCU启动那些事(3)- KBOOT配置(FOPT/BOOT Pin/BCA)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔Kinetis系列MCU的KBOOT配置. KBOOT是支持配置功能的,配置功能可分为两方面:一.芯片系统的启动配置:二.KBO ...
- 痞子衡嵌入式:飞思卡尔Kinetis系列MCU启动那些事(9)- KBOOT特性(IntegrityCheck)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔Kinetis系列MCU的KBOOT之完整性检测(Integrity Check)特性. Application完整性检测是非常 ...
- 痞子衡嵌入式:飞思卡尔Kinetis系列MCU启动那些事(11)- KBOOT特性(ROM API)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔Kinetis系列MCU的KBOOT之ROM API特性. KBOOT的ROM API特性主要存在于ROM Bootloader ...
- 痞子衡嵌入式:飞思卡尔Kinetis系列MCU开发那些事 - 索引
大家好,我是痞子衡,是正经搞技术的痞子.本系列痞子衡给大家介绍的是飞思卡尔Kinetis系列微控制器相关知识. 飞思卡尔半导体(现恩智浦半导体)于2010年开始推出的Kinetis系列昭示着ARM C ...
- 痞子衡嵌入式:恩智浦LPC系列MCU开发那些事 - 索引
大家好,我是痞子衡,是正经搞技术的痞子.本系列痞子衡给大家介绍的是恩智浦LPC系列微控制器相关知识. 恩智浦半导体最早于2003年便开始推出LPC系列MCU,但早期的产品LPC2000/3000系列属 ...
- 痞子衡嵌入式:ARM Cortex-M内核MCU开发那些事 - 索引
大家好,我是痞子衡,是正经搞技术的痞子.本系列痞子衡给大家介绍的是ARM Cortex-M内核微控制器相关知识. ARM公司从2004年开始推出Cortex-M系列内核,迄今Cortex-M家族已经包 ...
- 痞子衡嵌入式:飞思卡尔i.MX RT系列MCU启动那些事(1)- Boot简介
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RT系列MCU的BootROM功能简介. 截止目前为止i.MX RT系列已公布的芯片有三款i.MXRT105x, i. ...
随机推荐
- kaldi使用cvte模型进行语音识别
操作系统 : Unbutu18.04_x64 gcc版本 :7.4.0 该模型在thch30数据集上测试的错误率只有8.25%,效果还是不错的. 模型下载地址: http://www.kaldi-as ...
- 06 Node.js学习笔记之自动路由
在以往客户端请求的文件,我们都得判断匹配才能返回相应的数据,其实我们可以设置一个自动路由,就可以不用每次去判断用户访问的是那个文件了 //1.载入http和fs模块 var http=require( ...
- Redis 文章一 之持久化机制的介绍
我们已经知道对于一个企业级的redis架构来说,持久化是不可减少的 企业级redis集群架构:海量数据.高并发.高可用 持久化主要是做灾难恢复,数据恢复,也可以归类到高可用的一个环节里面去,比如你re ...
- 【网络安全】SQL注入、XML注入、JSON注入和CRLF注入科普文
目录 SQL注入 一些寻找SQL漏洞的方法 防御SQL注入 SQL注入相关的优秀博客 XML注入 什么是XML注入 预防XML注入 JSON注入 什么是JSON注入 JSON注入的防御 CRLF注入 ...
- Just 5分钟!使用k3s部署轻量Kubernetes集群快速教程
大小仅有40MB的k3s为想要节省开销进行开发和测试的企业提供了一个很好的选择.本文将用一种极为简洁的方式,教你在5分钟之内使用k3s部署轻量Kubernetes集群. Kubernetes已经改变了 ...
- day2------运算符和编码
运算符和编码 一. 格式化输出 现在有以下需求,让用户输入name, age, job,Gender 然后输出如下所示: ------------ info of Yong Jie --------- ...
- django-模板之block(四)
base.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...
- JavaScript基础修炼(14)——WebRTC在浏览器中如何获得指定格式的PCM数据
目录 一. PCM格式是什么 二. 浏览器中的音频采集处理 三. 需求实现 方案1--服务端FFmpeg实现编码 方案2--ScriptProcessorNode手动处理数据流 参考文献 示例代码托管 ...
- Head First设计模式——简单工厂、工厂、抽象工厂
前言:按照惯例我以Head First设计模式的工厂模式例子开始编码学习.并由简单工厂,工厂模式,抽象工厂模式依次演变,归纳他们的相同与不同. 话说Head First认为简单工厂并不是设计模式,而是 ...
- Linux tar命令解压时提示时间戳异常的处理办法
在Linux服务器上的文件会有3个时间戳信息 访问时间(Access).修改时间(Modify).改变时间(Change),都是存放在该文件的Inode里面 问题描述: 公司网站是前后端分离的,所有的 ...