文章目录

  • 什么是Bootloader
  • ECU的Bootloader
  • Bootloader框架
  • ECU Bootloader原理
    • 1、预编程阶段
    • 2、编程阶段
    • 3、编程结束
    • 总体流程
  • Bootloader开发难点分析
    • 硬件初始化
    • 代码编写和构建
    • 开发的效率
    • 调试
  • 一些调试技巧
  • 实例
  • 结语

单片机正常时运行上电/复位,第一条指令是固定的,程序正常顺序运行到Bootloader,由Bootloader跳转到APP程序运行。

什么是Bootloader

单片机正常运行时总是从固定地方取指令,顺序运行,这将对编写程序的人产生巨大的挑战,程序更新时需要使用烧录器等工具烧录,于是有人将程序设计成,由一个程序跳转到另一个程序,这个程序通常称作Bootloader,另一个叫做APP。

Bootloader程序常常具有通信接口和擦写内部存储空间的功能,可将需要更新的APP擦除,写入新的APP。有时会设计成相互跳转,技术也是可以实现的。有些为了保证程序不丢失,单独预留出备份区和出厂版本,出现某些错误时可以恢复到出厂版本或使用其他APP均可。

ECU的Bootloader

ECU是MCU的一种,专门用在汽车上。ECU经常会用在汽车零部件中,零部件密封性等要求都比较苛刻,并且装车,如果想取下零部件可能需要将车拆解才可以做到,这种行为是不被允许的,成本极高,操作复杂,因此大多主机厂(厂商)要求ECU具有升级功能,并且通过多年的积淀制定了行业标准UDS。

UDS简介:UDS(Unified Diagnostic Services,统一诊断服务)诊断协议是用于汽车行业诊断通信的需求规范,由ISO 14229系列标准定义。UDS诊断通信用于建立诊断仪与ECU之间的通信连接,并负责将ECU中的诊断结果输送到诊断仪中。UDS的作用非常广泛,几乎跟随ECU软件开发的全过程。

UDS后续会专门写相关知识进行讲解。

ECU开发过程要用到它来构建bootloader,上传和下载数据,即软件刷写,控制器Reset;测试时要用它来读写存储,控制外设;产线上,要用它来校准机械件,控制例程,进行下线执行器测试,刷新软件,配置防盗,读取号码,下线配置等。在行驶过程中,要用它来监测各种故障,并记下故障码;4S店里,技师需要读取当前故障、历史故障,读取故障发生时刻环境信息状态,清除故障,判断故障发生点,还可以用来升级ECU程序。

汽车明确规定通过UDS进行更新程序,主机厂要求擦写内部存储的代码不可写入正常代码中。汽车电子中ECU一旦设计完成,装车量产就很难再拆卸并返回零部件供应商完成功能升级或补丁修复。一旦出现售后质量问题,如果召回的话,零部件供应商和整车厂将面临严重的经济损失,因此设计基于CAN总线的ECU在线程序更新Bootloader可以很好的解决这一问题,将零部件供应商和整车厂的损失降低到最小。目前大部分汽车整机厂(主机厂)都要求在其设计的ECU实现Bootloader功能。

Bootloader框架


Bootloader由主机厂或者自己,可以选择用或者不用,本次主要针对使用Bootloader情况进行分析。主机使用协议由自己进行定义,ECU启动模式选择由芯片厂商进行技术支持。内部编写均需要遵循协议,大多数开发都是由多年开发经验沉淀下来,修改而成的,协议依然在进步,代码可能无法维护而无法支持,主机厂也会被迫选择使用旧版协议。

ECU Bootloader原理

主机厂规定不可把擦写内部代码的功能直接写入程序中,因此,只能每次用时才能将代码放入ECU,ECU内部可以有Bootloader,但不可以有擦写内部代码的功能,擦写代码的功能称作NVM (None Valitale Momory–非易失性存储器)驱动程序。

主机将NVM驱动程序下载到RAM区域,用NVM驱动程序对内部NVM进行擦除写入新数据等,在最后跳转即可完成更新。

UDS服务设计复杂,Bootloader升级一般分为以下三步:

1、预编程:主要进行一些环境配置

2、编程:刷写过程

3、刷新完成:恢复配置

Bootloader可以保证在上述三个阶段任一问题出现都能再次进入该过程重新刷新。

1、预编程阶段

在进入刷新之前,UDS的85服务和28服务,关DTC和非诊断报文。使整个CAN网络处于安静的状态。这是对整车网络进行操作的,一般都是以功能寻址的方式来发送。注意先用85服务关闭DTC,再使用28服务关报文。通常都会关闭故障码保存,关闭CAN通信是为了加快刷写速度,过程如下:

2、编程阶段

UDS设计了安全访问功能,安全访问是为了保证ECU数据的安全,实现方式是由ECU发送一个种子到主机,主机通过dll文件算法算出结果与ECU算出结果进行比对,结果一致则解锁成功通过安全验证。ECU解锁可以存在多个等级。

写时候先写DID指纹,标记写软件人的身份(按照主机厂要求),擦写下载等操作。

3、编程结束

刷写完成之后,ECU进行重启,重新进入扩展会话,打开之前关闭的配置即可。

总体流程

Bootloader开发难点分析

硬件初始化

当硬件上电之后,运行的第一条指令就是Bootloader的代码(如果各式各样的BIOS忽略不计的话)。Bootloader需要完成硬件初始化的一系列工作。然后才可以进入正常的逻辑,例如加载OS Image等。对于软件工程师而言,硬件的初始化工作是很冗长乏味的。需要详细阅读各类硬件的资料规范。然后就是一系列的对寄存器的操作。虽然Bootloader中不需要初始化板子上的所有的硬件,而只需要初始化最基本的可以让Loader正常工作的硬件就可以,有一些外设可以放到OS启动的时候,甚至驱动加载的时候再进行初始化不迟。即使是这样,要初始化的硬件也不在少数,对于一个典型的ARM系统而言,有可能要做的事:初始化内存控制器,初始化MMU,配置GPIO口,配置调试串口,对RTC进行读写操作,如果要通过以太网下载,还需要驱动网络接口……这一系列的工作,没有一个不是体力活。需要细心的琢磨,很有可能对寄存器某一个bit的粗心设置,就会导致整个Bootloader无法工作。所以这一部分内容通常马虎不得,需要耐心完成。

代码编写和构建

由于Bootloader是最底层的代码,汇编语言肯定是少不了的了。就连一些整天喊“汇编已死”的人也不能否认,系统启动的那一段代码,还是需要汇编语言的。而汇编语言通常也是软件工程师们不太希望去碰的“硬骨头”。这也增加了Bootloader编写的困难。
代码写好之后,当然要编译成机器码才可以在板子上运行。目前的编译器大多数只会把代码编译成某些流行的可执行文件格式,例如Windows上的PE和*Nix上的ELF等。这些带有格式的可执行文件,也没有办法再目标设备上直接运行。所以,通常OS都会提供一些工具,把这些可执行文件去头去尾,转成纯二进制格式,这样才可以在目标设备上运行。例如ADS提供的FromELF工具与Windows CE提供的ROMImage工具就是完成这类工作的。通常,我们需要为这类工具做一些配置,例如告诉这些工具代码段放在什么地方,起始地址是多少等等。如果这些参数没有配置正确,很有可能最终生成的Bootloader的映像是不可用的。那么烧写到目标设备上,自然也就无法运行。同样,对于这些参数的配置,也需要仔细检查核对,一步步进行。

开发的效率

Bootloader的另外一个开发困难的原因是它的开发效率。通常当我们做了一些代码修改之后,都需要把修改后的二进制文件使用烧写工具烧写到目标设备的Flash中,无论是NAND还是NOR Flash,烧写的过程都不快。所以,即使是改了一行代码,也需要经过编译->烧写->运行这样一个完整的流程。一般而言再快也要10分钟左右。这样算算,一个钟头可以修改个5次代码,一天可以修改个50次代码就相当不错了。机械的重复这一过程,经常会使开发人员感到开发效率低下,从而产生反感和抵触情绪。这也是Bootloader开发的一大劣势。一个解决的方法是使用硬件调试工具把Bootloader的映像直接灌到RAM里面运行,往RAM里面灌通常比烧写Flash要快。但是这样需要调试工具来初始化RAM,又有很多的其他逻辑上的和细节上的事情要做。

调试

上面说的几大问题,其实还都是可以克服的问题。其实在我看来,开发Bootloader最大的问题还是调试问题。试想:无论汇编多么难,我还是写好了,无论烧写多么烦,我还是烧写下去了,但是当我怀着激动的心情按下Reset键的时候,整个硬件设备毫无反应。我怎么知道我的代码写的正确还是不正确呢?如果不正确,我又怎么能定位到我的错误呢?现在的软件开发中,无论是编译型语言还是script,一般都会提供相应的Debugger,让开发人员来定位代码错误。“摸黑”写代码是软件工程师们最害怕的事情。代码出了问题,如果没有行之有效的手段来做问题定位,十有八九会造成项目“卡壳”。如果定位准确,那么问题也就解决了一大半了。所以归根结底,还是调试的方法论问题。Bootloader中难以调试,是因为可以使用的手段非常少,也不常规。在OS下开发应用程序用到的那些调试手段手段,在Bootloader的开发中通常都用不上。需要有“非常”手段来调试。下面的专题,就向大家介绍一些Bootloader的常用调试方法。

一些调试技巧

(1) 硬件调试器

相信很多从应用开发走过来的开发人员,都会对Set Breakpoint,Step into, Step over等这些调试手段相当怀念。但是那些东西都是调试器在搞鬼。到了裸板上,可没有Debugger来帮我们了。那怎么办?好在我们有硬件调试器。很多CPU体系结构都提供了相应的硬件调试器,例如ARM CPU的仿真器。借助硬件调试器,我们可以完成汇编级的Set Breakpoint,Step into, Step over这些操作。这对于调试Bootloader来说,实在是太重要了。至少我们可以看到我们烧写下去的代码是否正确,然后可以看到是否在运行。这对于调试Reset后的第一段代码来说,实在是雨后春笋一般的珍贵。
但是硬件调试器也有很多不足:首先,它们一般都价格不菲,不用国内自己的D的话,几W是少不了了。其次,大多数硬件仿真器只能实现汇编级的调试,当代码进入了C语言之后,硬件调试器就显得力不从心了。第三,一劣质的仿真器,通常还无法对MMU打开后的虚拟内存进行仿真。所以限制也是很多的。

(2) LED灯

如果我们买不起硬件仿真器,或者手头上根本就没有。那么只好通过硬件的一些输出端口来输出一些信息,让我们知道代码到底运行到哪里了。在诸多的端口中,最简单的恐怕就是LED灯了。一般而言,用个几句汇编,就可以让LED闪烁起来。这样,我们就可以在代码中安插让LED闪烁的语句。来看我们的代码到底在哪里跑飞或者挂掉的。可惜LED等只能闪烁,想通过LED来获得更多的消息,是很困难的。例如我们想知道某个变量的值,用LED的闪烁表示出来,恐怕就很伤脑筋。用LED来闪烁出摩尔斯代码是一种可行方案,但是除了开开玩笑之外,恐怕真的去实践的人是不存在的

(3) Printf―调试串口

目前为止,在Bootloader甚至整个OS开发过程中,串口可能是使用最广泛的调试端口了。它的设备简约却不简单。用一根串口线,把PC跟目标设备连接起来,这样我们可以通过串口来输出一些字符,在PC一端接收。终于,在有OS的应用程序开发中最传统的,最原始的调试方法printf就可以用了。在Bootloader的开发中,如果可以通过串口输出调试信息,那调试的手段就前进了一大步了。至少我们可以通过printf来跟踪目前代码在哪个函数里,分支语句走了哪个流程,某个变量的值到底是不是我们想要的……世界真美好。串口的问题是它不像LED那样想用就用,还是需要初始化的。好多嵌入式CPU都把串口控制器集成到了里面,甚至有一些会在CPU上电的时候自动初始化串口,这使得串口初始化相对简单。但是如果有一些串口是外挂的控制器,那么初始化一个串口有可能也需要耗费你半天时间。

(4)内核调试器

随着开发进一步复杂,串口输出调试信息恐怕又不能满足我们的要求了。首先,输出的信息一多,很容易乱套。其次,输出信息业是需要花费时间的。在中断处理函数等一些时间敏感的地方使用串口输出,有时候依然不明智。如果能把远程调试器接上,那对BootLoader的调试跟对应用程序的调试就没有什么二致了(源码级设置断点,一步步跟,随时看某些数据结构的值,都成了可能)。Linux提供了GDB,Windows CE提供了KD。但是这都需要实现相当多的工作,实现一些调试器Stub。GDB可能串口就可走。但CE的KD通常是要通过KITL,通过以太网的。虽然复杂,长远来看还是非常有必要的,所以,当感觉其它手段力不从心的时候,可以考虑启用更高级别的调试器了。

实例

以NXP推荐设计简单讲解原理。NVM驱动NXP官方提供完整的实现函数库,不需要自行实现,实际开发中也是如此,大部分是对工具的使用,而不是从零开始开发功能。

使用脚本文件抽取指定ECU的NVM驱动代码,全部代码是以C语言const数组存储。

将NVM驱动函数地址存储在指定地址作为 NVM 驱动函数地址表。

因为全部使用const关键词修饰,全部存储在常量区域,只读数据段,修改链接文件将只读数据段固定到RAM设定地址,则NVM驱动编译后存储在RAM区域,生成S19文件。

从得到的S19文件分离出NVM驱动和NVM 驱动函数地址表的S19文件,称为NVM 驱动S19文件

将NVM 驱动S19文件与应用S19文件合并生成完整的Bootloader。NVM 驱动S19文件需要保持在整个文件的开始,以保证系统能够正常运行找到NVM驱动。

NVM驱动是NVM 独立驱动是灵活可裁剪的。因此可以根据 Bootloader 的功能选择必要的 NVM驱动函数,从而减少其占用的 RAM 空间,以适应小RAM尺寸的ECU(比如 1KB RAM 的ECU 系列), 当然还需要改变其编译地址和 NVM 驱动函数映射地址表。

结语

虽然这是一个比较复杂的问题,在分析问题时,将问题分解,比如,整个Bootloader分为通信、存储等,梳理过原理之后,可以预测到代码实现逻辑,再追踪定位,验证预测。为保证安全提出并实现了一种基于总线通信将NVM驱动程序由上位机下载到 RAM 中运行而非让其驻留于ECU片上FLASH的安全Bootloader 设计,有效避免了应用程序跑飞运行至驻留于片上 FLASH的NVM驱动代码所造成的程序/数据丢失失效。但对于汽车上不是一朝一夕能实现的,虽然单一功能简单,为了保证这个功能而设计很多框架用来保证,框架是各种协议的实现,难度极大,需要长时间积淀才能理解其中奥义。
————————————————
版权声明:本文为CSDN博主「IT技术猿猴」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/baobingji/article/details/123119354

浅谈bootloader【谈的很清晰明白】相关推荐

  1. 怎么学python-结合学习经历,谈一谈如何学习Python

    结合自己的学习经历,谈一谈如何学习Python吧. 入门阶段 Python其实语言本身已经很接近自然语言了,所以入门其实并不麻烦.如果你是从未接触过编程的萌新,给你推荐一门Udacity CS101, ...

  2. 先查询再插入的存储过程怎么写_谈一谈 InnoDB(1) - 底层存储文件结构

    看技术文章是不是很累呢, 这次来个轻松点的~来谈一谈MySQL最主流的数据库引擎 InnoDB 吧~ 序 老王走进一号会议室, 随手打开了灯, 小张紧随其后 "王哥, 找我来干啥啊" ...

  3. Java程序员谈一谈-----java程序员成长之路

    转载:http://www.banzg.com/archives/679.html?ref=myread 阿里面试回来,想和Java程序员谈一谈 引言 其实本来真的没打算写这篇文章,主要是LZ得记忆力 ...

  4. 怎么自学python-结合学习经历,谈一谈如何学习Python

    结合自己的学习经历,谈一谈如何学习Python吧. 入门阶段 Python其实语言本身已经很接近自然语言了,所以入门其实并不麻烦.如果你是从未接触过编程的萌新,给你推荐一门Udacity CS101, ...

  5. 谈一谈游戏AI - 行为树

    不要用过去的成绩看未来,而是要用未来的眼睛看现在. 郑重说明:本文适合对游戏开发感兴趣的小白初学者,本人力图将事物用简单的语言表达清楚,但水平有限,能力一般,文章如有错漏之处,还望批评指正. 在本系列 ...

  6. 写在工作的第十年: 谈一谈专注和基础的重要性

    写在工作的第十年: 谈一谈专注和基础的重要性 老帮菜的自我吐槽 不知不觉, 作为一个打工人, 作为一个写程序的打工人, 职业生涯的第十个年头悄然而至. 从一个充满雄心壮志的有志青年, 到如今有家有室的 ...

  7. 谈一谈曾经的中国互联网吧

    以史为镜,可以知兴替.中国互联网,沧海桑田. 今天写个简单的,首发于知乎,这里增补了一些. 1.最早在美国上市的中国互联网公司是中华网,域名牛逼,中国概念,一度股价爆高到100多美元,后来一路跌到地板 ...

  8. 就着近事儿,谈一谈游戏数值策划的面试

    本来是写在自己新建的WordPress博客的,可惜百度目前不收录,因而下贴到cnblog这分享给大家. 链接下笔者的WordPress博客地址:www.mahsichu.com 雏儿新建,诸多不懂,目 ...

  9. 谈一谈网络编程学习经验(陈硕)

    作者:陈硕  原文地址:http://blog.csdn.net/solstice/article/details/6527585 本文谈一谈我在学习网络编程方面的一些个人经验."网络编程& ...

最新文章

  1. tar常见文件解压法
  2. OpenStack安装过程备忘
  3. promise中调用ajax
  4. Java反射机制在UI自动化测试中的一个应用
  5. Service Mesh 在华为公有云的实践
  6. echarts源码:图标类插件开发
  7. 本周Whale Alert监测到7.9万枚BTC在匿名地址间转账
  8. python大盘点:全局变量、局部变量、类变量、实例变量
  9. 在mobile5.0上实现滑动效果控件
  10. c语言弹出u盘 api,一个简单的C++编写的u盘病毒代码
  11. 什么是java 比特率_比特率问题(32位对64位)
  12. 吴恩达机器学习______学习笔记记录#八、神经网络---表述
  13. python爬虫简单入门级,小白讲说
  14. 北京剩女80万!全国十大单身男女盛产地都在哪?
  15. 网易云音乐实时计算平台设计及实践
  16. 云服务器怎么增加d盘_云服务器怎么加d盘
  17. 禁止所有搜索引擎蜘蛛的爬行收录
  18. 创建视图簇SE54并SE93赋予事务代码
  19. PXC 5.7 WSREP_SST: [ERROR] xtrabackup_checkpoints missing
  20. PCB散热之过孔的作用

热门文章

  1. java json不能正常解析_JSON格式正确,无法解析问题解决方法
  2. Hive sql解析json格式
  3. 英雄联盟掉线怎么不显示重新连接服务器,win7系统玩英雄联盟掉线总是显示正在尝试重新连接的解决方法...
  4. 金融数据分析——DataJoy银行客户购买预测
  5. 华为电视鸿蒙安装第三方软件,新款华为智慧屏如何安装第三方软件?最详细的安装教程详解...
  6. YUV YPbPr YCbCr CCIR 601 CCIR 656
  7. linux中流设备_Linux USB的那些事之设备驱动子系统终极篇
  8. 电视盒子怎么K歌?当贝家庭KTV音响套装助力客厅K歌
  9. PCIE5.0如何进行PCB设计?32G高速信号设计注意事项有哪些,高速板材如何选择?
  10. Qt编写物联网管理平台48-特色功能设计