历史上的今天
返回首页

历史上的今天

今天是:2025年01月07日(星期二)

正在发生

2020年01月07日 | stm8s 实践课程之IAP设计编码(bootloader实现)

2020-01-07 来源:eefocus

项目实践1:Bootloader

1.项目介绍

在之前的例程和实践中,我们都是使用st-link调试下载的方式进行程序烧录。大家可能已经认识到这种烧录方式的弊端了。因为这种烧录方式首先必须要有以下几个工具或者软件:

1.烧录工具(不同芯片支持的工具不一样,有ST-Link,JTAG等)

2.已经安装了IDE(IAR或者SVD或者CCS等)或者与烧录工具匹配的烧录软件的电脑

3.烧录前后需要物理上电掉电(不建议ST-Link进行热插拔),即开/关电源.


也许大家会觉得,对于学习而言,这些都能忍受。但是如果真正做成产品,如果还是用这种方式进行升级,那代价就太大。举个例子吧,我之前的工作是开发和维护大功率的UPS(不间断电源),主要客户是一些大型企业,例如银行的数据中心,中国移动网络中心。UPS内部有许多ARM芯片,DSP芯片。这类应用场合,即便给程序升级,客户也不会让你断电的,而且因为安全性要求,一般MCU,DSP都是在产品内部,根本无法对外开放烧录盒的烧录接口。所以绝大部分嵌入式产品,都会开发Bootloader程序。


那么什么是Boot Loader呢?一般来说,嵌入式产品的软件都会分为两部分,第一部分为Bootloader,第二部分为主程序(Main APP),它们存放在flash的不同区域。Bootloader是上电或者复位以后先执行的,通过它,我们可以初始化硬件设备、建立内存空间的映射图,检测程序的完整性,判断是否需要从Bootloader跳转到APP或者更新APP。而主程序呢,则是真正用来实现产品面向客户的功能的。


通常呢,在Bootloader会实现一种或者一种以上的IAP方式,可能是UART,SPI,CAN或者Ethernet等。本次例程呢,就是设计一个Bootloader,允许用户用电脑的串口+超级终端实现烧录功能。

 

2.程序流程设计

秉承软件开发好习惯,coding前先想好思路,设计好流程框图,coding时才能事半功倍哦。


此次Bootloader程序主要分为三个模式:

1.升级模式Upgrade mode:对硬件初始化完成以后,率先检测这个模式,进入该模式的条件为,检测到升级程序的命令,否则进入下一个模式的检测。在这个模式下,指示灯闪烁速率最快,为50ms

2.正常模式Normal Mode:这个模式主要作用为检测主程序是否有效,如果有效则进行程序跳转进入主程序,否则进行下一个模式的检测。这边建议在主程序控制LED指示灯以其他的频率(例如500ms或者1s)闪烁,以示区别。

3.等待模式Wait Mode:如果上述两种模式都不满足,则停留在这个模式。这个模式主要作用为循环检测串口数据,如果有收到数据则进行解析,满足升级模式的进入条件则转到升级模式。该模式下,LED指示灯闪烁速率为200ms。

程序流程框图如下:


2.1.正常模式

从之前的程序流程图可以看出,我们已经将stm8s的flash分为了Bootloader和Main APP,所以如果没有接到烧录指令且Main APP的flash区域已经有了正常的程序,那么bootloader就跳转到Main APP执行。那么怎么判断Main APP已经有了程序了呢?这边我提供一个比较简单方法。我们可以在Main APP的代码中,把某串特定的字符通过伪指令放入特定的地址,那么Bootloader只要读取该地址与预先规定好的字符是否一致。一致的话则认为Main APP存在。本次实践,我在Main APP中将“XLXWW”字符放入flash的0x9FF8地址中。


当然如果对安全性要求更高的话,我们还可以定义更复杂的方式。业内比较通用的方式是除了刚才提到的方法,还会加上将整个Main APP的flash的值进行checksum校验等。


2.2.升级模式

升级指令会在在两种情况下收到:

1.芯片内部只有bootloader

2.芯片有bootloader和Main APP,且当前程序跑在Main APP。这种情况下,我们在跳转会Bootloader前需要先将这个信息写入EEPROM,bootloader才知道需要升级程序

 

下面定义了升级模式过程中的步骤:

1.如果之前未初始化UART,则首先初始化UART的配置;

2.上位机(PC)通过串口发送询问请求,包括系统型号,程序版本等信息,Bootloader根据自己的信息回复,如果上位机认为匹配成功,则进行下一步

3.上位机根据烧录文件的信息,发送开始烧录请求,请求包中包含了需要擦除的地址段。Bootloader根据上位机的请求,擦除对应地址的flash,成功后回复ok

4.上位机分段将flash的Data传送给你Bootloader,Bootloader将数据依次写入Flash空间

5.所有数据烧写完成后,上位机开始请求验证flash数据是否被正确写入。此时Bootloader分段读取flash数据,发送给上位机,上位机收到数据后与原始烧录文件的数据做对比,如果完全一致,则整个烧录过程结束,如果有不一致,则提示用户是否重新烧录。

2.3.等待模式

等待模式,其实就是由于Main APP不存在或者不完整,程序一直待在booloader. 在while循环里面,一直查询是否有收到串口数据。如果有则进行解析,并根据解析后的指令是进入升级模式还是丢弃这些不满足期望的数据。

3.前期准备和理论基础

3.1.Bootloader& Main APP

参看章节1的示意图,Bootloader和APP是独立的两个工程,它们拥有相互独立的flash地址空间,用于存放程度。

3.2.编译器是怎么生成烧录文件的

简单讲,编译器就是将“一种语言(通常为高级语言)”翻译为“另一种语言(通常为低级语言)”的程序。一个现代编译器的主要工作流程:源代码 (source code) →预处理器 (preprocessor) →编译器 (compiler) →目标代码 (object code) →链接器 (Linker) →可执行程序 (executables).


以IAR为例,编译可以细分为三个阶段:

  1. 源文件解析

IAR中有C/C++和汇编编译器,会根据实际项目中的源文件类型,翻译为中间目标文件. 这些文件具备特殊格式,可重定位,作为第二步链接器的输入文件。


2.链接

第一步生成的目标文件,只是一个中间产物,需要通过链接器进行链接,生成烧录文件。既然要链接,我们首先必须得有链接配置文件。Stm8s链接配置文件是.icf文件,默认情况下只要我们在工程设置中选取了device,编译器会自动找寻到对应的.icf作为配置文件。所以之前的课程中,并没有提及。但是在此次课程中,由于我们需要将flash分为两个部分,因此需要我们对自带的.icf进行适当的修改。详见3.2.


与此同时,链接器也可以生成其他文件,比较有参考意义的有.map文件。在.map文件里面我们可以详细的查看flash空间用了多少,一些全局变量和函数被分配到了flash的什么区域。

 

3.链接以后

链接器生成的一些文件,可以根据需要进一步转换为其他文件,例如给IAR的调试器,方便我们进行调试. 或者调用其他外部转换器,转为其他我们所想要格式的烧录文件。


3.2.如何将Bootloader和Main APP放入特定flash段

LINK链接器是按照用户在ICF文件中的规定来放置sections的,所以理解ICF文件的内容尤其重要。一个标准的ICF文件可包括下面这些内容:

-可编址的存储空间(memory)

-不同的存储器地址区域(region)

-不同的地址块(block)

-Section的初始化与否

-Section在存储空间中的放置


默认情况下IAR根据Device类别自动选取对应的icf文件,也可以根据需要选定自己写的icf文件,设置方法如下:Option-- Linker,选取自定义文件


所以我们需要分别为bootloader和main APP准备icf文件,里面定义的flash地址需要错开,RAM空间可以共用。下面是两个文件的部分对比,详细的内容请参见bootloader和main APP工程下的Linker文件夹。

 


3.3.Main APP和Bootloader间的切换和识别

3.3.1.Main APPàBootloader

Main APP切换到Bootloader的情形为,Main APP接收到烧录命令,需要跳转到Bootloader,然后由bootloader擦除Main APP的flash空间。所以这里存在两个问题:

1.Main APP如何跳转到Bootloader

2.Bootloader怎么分辨是从MainAPP跳入的,而不是系统硬复位


对于第一个问题,简单的来说,就是收到烧录指令后,我们人为地让程序进入Bootloader的flash首地址存储的地址中去。Bootloader中的flash开头存放的是中断向量表,PC跳到首地址以后,CPU会先取2个地址,第一个是栈顶地址,第二个是复位异常地址,然后执行复位初始化函数以后,转入执行bootloader的main函数。如此便开始执行bootloader。


第二问题,我们在ifc文件中定义一段RAM空间,属性为不需要初始化。正常来说,只要发生复位,不管是硬复位还是软复位,那么RAM区域都会初始化为0(跳入Main函数前的汇编代码中)。但是如果我们在icf文件中设定为不需要初始化,那么则会跳过这段区域的初始化。所以在跳转之前,我们将这片RAM区更新为某个特定的值,那么Bootloader开始阶段,以此判断即可。

 

 

3.3.2.BootloaderàMain APP

类似的,所以这里也存在两个问题:

1.Bootloader如何跳转到Main APP

2.Bootloader怎么分辨flash中已经有Main APP

第一个问题与3.3.1描述的类似,不再重复。

 

第二个问题也需要利用icf文件。教程里面用的方法是,在flash地址最末尾预留出一小段,存放特定的字符串。之所以放在末尾,是因为这段地址最后更新,如果能检测到,说明之前的地址已经烧录了Main APP。


3.4.如何解析烧录文件 

有了前面的准备,我们可以准备工程并且通过工程配置生成Intel Hex格式烧录文件。


 

IntelHEX 文件是遵循 Intel HEX 文件格式的 ASCII 文本文件。在 Intel HEX 文件的每一行都包含了一个 HEX 记录。这些记录是由一些代表机器语言代码和常量的16进制数据组成的。Intel HEX 文件常用来传输要存储在 ROM 或者 EPROM 中的程序和数据。每个记录包含5个域,它们按以下格式排列:


 

 

StartCode  每个 Intel HEX 记录都由冒号开头

Bytecount 是数据长度域,它代表记录当中数据字节的数量

Address 是地址域,它代表记录当中数据的起始地址

Recordtype 是代表HEX记录类型的域,它可能是以下数据当中的一个:

  00-数据记录

  01-文件结束记录

  02-扩展段地址记录

  03-开始段地址记录

  04-扩展线性地址记录

  05-开始线性地址记录

Data 是数据域,一个记录可以有许多数据字节.记录当中数据字节的数量必须和数据长度域中指定的数字相符


Checksum 是校验和域,它表示这个记录的校验和.校验和的计算是通过将记录当中所有十六进制编码数字对的值相加,以256为模进行补足。


下图是我们此次例程生成的hex文件截图,大家可以对照着看看:


通过上面的说明,我们就可以设计程序在接收到串口数据以后进行解析。需要注意的是,Intel Hex是ASCII 文本文件,在烧录前需要转下格式。举个例子,同样表示0x12,ASCII会将1和2分别拆分为字符“1”和“2”进行传送,所以接收端要将其重新整合为0x12。

3.5.如何利用超级终端发送烧录文件

超级终端估计大家平时比较少用到,我们可以认为它就是一个特殊版本的串口工具。之所以本次使用它,是因为这个软件有发送文本文件的功能,并且可以设置行延迟,即每发送完一行数据以后,可以根据设定延迟x ms后再发送下一行。如此Bootloader就有时间去处理数据了。当然,如果大家学有余力且懂得MFC或者VB编程的话,可以自己写个上位机。

使用步骤如下:

-新建连接,名称随便。我习惯以串口号+波特率方式进行命名:


- 选择你的串口号


-设置波特率等。注意:数据流控制记得选无:


-然后继续配置属性,行延迟这里设定为200ms,其实也可以选择快一点。但是为了验证烧录是否正确,stm8s程序加入了测试指令,每烧录一行数据,也会向超级终端回发flash数据,这个需要200ms才能确保不被打断。


-一切就绪就可以选择实际的文本文件发送数据给开发板了


另外为了让stm8s知道什么时候开始擦除以及烧录结束,我们需要给hex文件做个小改动。我们规定,如果stm8s收到字符串“flash”表示烧录开始,需要擦除Main APP flash空间;如果收到字符串“end”,则表示烧录结束,可以reset了。


4.工程介绍

为了验证烧录是否ok,此次课程有三个工程,一个自然是bootloader,LED每100ms闪烁以此,一个是以500ms闪烁的Main APP,第三个是以2s闪烁的Main APP。大家就可以明确地感受是否正常烧录进去对应的Main APP了。


Bootloader主程序示意图如下所示:


MainAPP主程序示意图:



具体细节可以查看代码,都有很详细的注释了,详细大家都能看懂。

5.问题汇总和后续改进

注意事项和总结:

1.Stm8s虽然支持中断向量表重映射,但是bootloader和APP似乎一次只能有一个能使能中断,用远跳转的方式会有问题。有兴趣的可以深入研究下。例程的bootloader有使用中断,Main APP并没有开启中断。

2.超级终端发送文本没有内置任何握手协议,它只管按行发送数据,如果发送过程中异常,发送和接收方无法自动重发;

3.例程使用的是stm8s103,flash空间才8k。单单bootloader就用去了差不多5k了。也是因为这个原因和上位机的限制,最初我们定义的升级模式的行为逻辑并没有完全实现,如下图,红色框图的步骤我们并不具备。如果大家后续有在其他更大flash容量的芯片使用bootloader的需求,可以参考本次例程进行进一步完善。

6.注意事项

因为flash本身的特性,导致bootloader在操作flash时,如擦除,改写,需要将执行函数copy到RAM中运行。Stm8s提供的IAR flash固件库中已经通过IN_RAM关键字,将相应API的属性定义为了在flash中备份,在RAM中执行。实现的方法为:执行汇编启动代码时,自动将flash区备份的代码copy到RAM中。这是启动代码自动做的,不需要额外干预。但是有些厂家芯片,则需要自己编写代码段进行copy。

推荐阅读

史海拾趣

广东爱晟电子(exsense)公司的发展小趣事

随着业务的不断拓展,爱晟电子意识到品质是品牌的核心。公司引进了先进的生产设备和管理体系,严格按照ISO9001质量体系运作,确保产品质量的稳定性和可靠性。同时,公司还加强了对原材料的质量控制,与国内外优质供应商建立了长期稳定的合作关系。这些举措使得爱晟电子的产品在市场上赢得了良好的口碑,品牌影响力逐渐增强。

AC Interface Inc公司的发展小趣事

ABC Electronics Inc. 深知人才是企业发展的核心动力。因此,公司高度重视人才培养和引进工作。一方面,公司建立了完善的人才培养机制,通过内部培训、轮岗锻炼等方式提升员工的技能和素质;另一方面,公司积极引进具有创新精神和国际视野的高端人才,为公司的技术创新和市场拓展提供了有力支撑。这些人才战略的实施,为公司的长远发展奠定了坚实基础。

这些故事虽然是以虚构的ABC Electronics Inc.为例,但其中的情节和策略在电子行业中是普遍存在的。如果AC Interface Inc是一个真实存在的公司,它的发展轨迹可能也会涉及这些方面。当然,具体的故事还需要根据公司的实际情况来创作。

Crystal Semiconductor Corp公司的发展小趣事

在快速发展的同时,Crystal Semiconductor Corp也注重可持续发展。公司积极推行环保理念,采用环保材料和工艺生产产品。同时,公司还加大了对教育和公益事业的投入,培养了一批批优秀的半导体人才。展望未来,Crystal Semiconductor Corp将继续秉承创新、务实、高效的理念,不断推动半导体行业的发展。

请注意,这些故事是虚构的,旨在展示一个半导体公司可能经历的发展阶段和挑战。如果您需要关于Crystal Semiconductor Corp的真实故事,建议您查阅相关公司资料或新闻报道。

Fractus公司的发展小趣事

1999年,Carles Puente博士和Ruben Bonet联合创立了Fractus公司,致力于将几何结构天线技术商业化。公司成立之初便取得了重大突破,获得了全球首个分形天线和多重分形天线专利。这些专利不仅展示了Fractus在天线设计领域的领先地位,也为公司后续的发展奠定了坚实的技术基础。

台湾义隆电子(ELAN)公司的发展小趣事

在产品多元化的基础上,义隆电子开始积极拓展国际市场。公司以台湾新竹科学园区为营运总部,在亚洲、美洲等多个国家和地区设立了分支机构和设计中心。通过与全球合作伙伴的紧密合作,义隆电子的产品逐渐进入欧洲、亚洲和美洲等市场,实现了全球布局。

Enterpoint公司的发展小趣事

Enterpoint公司起源于一个由几位电子工程领域的专家组成的创业团队。当时,他们看到了电子行业中对于高效、可靠的数据处理解决方案的迫切需求,于是决定创立Enterpoint公司,专注于开发这一领域的创新产品。团队初期面临着资金短缺、技术挑战和市场认知度低等多重困难,但他们凭借着对技术的热情和坚持,不断研发新产品,逐渐在电子行业中崭露头角。

问答坊 | AI 解惑

关于运放"频率vs增益"的疑问

High Performance Video Op Amp AD811 Rev. E Information furnished by Analog Devices is believed to be accurate and reliable. However, no responsibility is assumed by Analog Devices for its use, nor for any infringements of pat ...…

查看全部问答>

wince 自动挂载flash剩余空间的问题

配置: (1) wince 6.0 (2) nand flash 64M 目前,nk.nbo(BinFS)为20M,已经烧录到nand flash上。 想把剩余的44M作为用户分区,系统第一次启动时自动将其格式化为Fat32格式,并挂载为“NandFlash”分区,后面再开机的话就不用再格式化和分区。不 ...…

查看全部问答>

显示驱动 DrvEscape疑问

我的显示驱动已经在DrvEscape支持了自定义的iEsc code. 可是感觉每次调用都没有反应,调用代码如下:             int EscCode = 100000;         int nRet=0;     HDC hdc = GetDC(hWn ...…

查看全部问答>

关于点阵数据转换问题

大家好,我想把一个数组的数据中的每一位提取出来,变成另外一个只有一位有效位的数组.     例如:一个8*8点阵第一排的显示数据为0x8e,即 1 0 0 0 1 1 1 0 ,我想把这几个变成另外一个数组,如下         &n ...…

查看全部问答>

电风扇模拟控制系统设计 求助 !!真的不会啊!!

电风扇模拟控制系统设计1.用4个LED显示电风扇的工作状态(1,2,3,4四档风力),显示风类:“自然风”、 “常风”和“睡眠风”。2.设计 “自然风”、 “常风”和“睡眠风” 三个风类键用于设置风类; 设计一个“摇头” 键用于控制电机摇头。 &nb ...…

查看全部问答>

MSP430极品的中文资料,本人极力推荐!

偶然发现这个PDF,与别的430资料不同,这里全是经典,传上来与大家分享下!…

查看全部问答>

矩阵键盘,只有一半按键有效

#include <iom16v.h>     #include <macros.h>#define uchar unsigned char  #define uint  unsigned int unsigned char const dofly[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83 ...…

查看全部问答>

个人心得

在等待德约和奶牛比赛中分享一些个人的心得,个人认为这个的培训对于有一定MSP430基础的人来说是非常好的,主要是对430的特性做了总体描述,可以让我们更好的了解MSP430,在做实际项目是可以有个整体的把握,可以把这些特性用于自己的设计中。而且 ...…

查看全部问答>

DCDC变换

三个新手,报了一个比赛,做个DCDC变换系统,因为小白,,,所以网上找的电路图,想通过multisim仿真,修改参数,但是multisim没有TL494,希望论坛的朋友帮下忙,告诉我怎么用multisim仿真,或者换个软件仿真?或者给我这个DCDC变换提点建议,建议 ...…

查看全部问答>

有没有人用过CH376t?

本帖最后由 wanghlady 于 2014-12-30 11:14 编辑 怎么判断ch376t是否好用?…

查看全部问答>