1237|24

55

帖子

0

资源

一粒金砂(中级)

关于小白编写bootloader的那档事 [复制链接]

 

    写在前面:以下内容不保证完全正确,但都是基于笔者的实践、经历过常规验证的。尽信书不如无书,希望读者能结合自己的实践,抱着怀疑的态度进行阅读。当然,笔者也十分欢迎各位提出修改意见,指出本帖的谬论,笔者自当有则改之无则加勉。

此帖出自单片机论坛

回复

55

帖子

0

资源

一粒金砂(中级)

本帖最后由 luaffy 于 2020-8-16 14:55 编辑

背景条件:

芯片:MSP430F247(最小系统)

编程软件:IAR

  • 关于Bootloader

借用百度百科的一段话,如下——

“在嵌入式操作系统中,BootLoader是在操作系统内核运行之前运行。可以初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境。在嵌入式系统中,通常并没有像BIOS那样的固件程序(注,有的嵌入式CPU也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由BootLoader来完成。在一个基于ARM7TDMI core的嵌入式系统中,系统在上电或复位时通常都从地址0x00000000处开始执行,而在这个地址处安排的通常就是系统的BootLoader程序。”

       将其功用明确概括出以下几点:1、用于串口更新用户程序(以下简称APP);2、稳定存放在单片机中(“接近”固化),明确与用户程序存放的空间分离开来;3、初始化硬件设备,例如IO口。至于那些“准备RAM空间”,“内核影像”,“根文件系统映像”,笔者这样的小白暂时不用管,干就完了。

     之所以说“接近”固化,是因为在笔者的编程方案里,存在单片机运行APP时,可以输入密码来进行Bootloader升级。真正固化在单片机中的,比如说430自带的BSL(也属于bootloader,),这段程序出厂即被固定写在430的某块地址里,以通过发送使用UART协议命令的工具来激活,不可被擦除。

             事实上,以上列出的两点(1、3)功能,第3点,笔者编写的bootloader并不能帮APP先做好初始化工作,其中缘由见第三点“关于中断重映射”。


回复

55

帖子

0

资源

一粒金砂(中级)

本帖最后由 luaffy 于 2020-8-16 15:08 编辑
  • 关于分区

       Bootloader的分区很有意思。一般来说,单片机需要划分为两个区域,一个为bootloader,另一个自然就是APP。给内存空间分区,就先要知道单片机的内存地址。MSP430系列的主要看TI官方的《MIXED SIGNAL MICROCONTROLLER》文件。

image-20200816150237-1.png

       需要注意的内存地址为,中断表:0xFFFF-oxFFC0,代码区:0xFFFF-0x8000,可编程代码区其实是0xFFBF-0x8000,

       好了,关键信息get√,接下来进行区域划分,如下图所示。

image-20200816150237-2.png        很难看对吧?笔者也觉得!打开编译器的内存窗口才一目了然。

image-20200816150237-3.png        可以看到④为硬件中断向量区,③为用户中断向量区,②为密码区(用以判断是否进行升级操作),①为bootloader中断向量区。这三个中断向量区可以挨一块,这样好看一点,但是笔者这里为什么不挨一块?因为木已成舟(不是),因为懒得改。

      确定了各分区的地址后,可以修改源xcl文件实现分区。源xcl文件一般在IAR的安装目录下。

image-20200816150237-4.png

                                                    bootloader的xcl文件

image-20200816150237-5.png

                                                     APP的xcl文件

      主要修改的地方已用红圈圈出来了。其中xcl文件的格式说明,简单粗暴地解释一下——(CONST)一般为保存变量常量,(CODE)为保存程序代码,下面的两个,INTVEC为中断向量存放的地址,RESET为复位向量。

     之后还要修改项目配置,右击项目>>options>>linker>>config,在linker configuration file框中输入修改好了的xcl文件所在的地址,或者输入:$PROJ_DIR$\文件名.xcl,即在当前工作区所在地址内。

image-20200816150237-6.png

                                                          项目配置

     分区工作到此为止。

 


回复

3953

帖子

1

资源

五彩晶圆(初级)

加油,干就完了。

个人签名人已离开,无事别找,找也找不到。

回复

55

帖子

0

资源

一粒金砂(中级)

本帖最后由 luaffy 于 2020-8-17 12:22 编辑
  • 关于中断向量表

    什么叫建立中断向量表?按笔者的理解解释一下——

image.png       就是写这种东西。

      笔者为了底部的flash截图看起来好看一点,就把所有的中断几乎全建立起来了,所以才有图三所示的填得满满当当的中断向量区。这是个不好的做法,各位不要学,这里笔者吃了大亏,等会详谈。

      如果没有建立,例如看门狗定时器的中断,xcl文件中设置的中断向量区中,对应的定时器A1的中断向量就只是FF。示例的bootloader和app程序里,都没有建立看门狗定时器中断,于是对应的位置是ff。

      再献上内存窗口的图——

image.png image.png                                                    Msp430f247.h硬件中断向量地址

                                          0xfff4为硬件中断向量区中的看门狗定时器的地址

       中断向量区里的地址指向中断程序执行入口。如上图我们可知0xfff0是定时器A1中断向量的地址,从内存窗口可以看到,0xfff0上的数据为8628,再献上汇编窗口——

image.png

      可以看到8628指向定时器A1中断程序入口。

     除此之外,中断最重要的是复位中断。程序一般只响应硬件中断向量区中的中断向量,上电是先运行硬件中断向量区的复位中断,如果复位中断向量写值错误,容易造成单片机死机。

image.png

      工欲善其事必先利其器,理解好中断后,就能理解为何直接把APP的中断向量区简单粗暴直接复制到硬件中断向量区就能完美运行具有中断程序的APP了。

      这是最后一步,在bootloader的场子,升级APP的数据文件接收并写入相应flash区结束后,或者直接想跳转APP,你再操作擦写中断向量区。由于当前硬件中断向量区储存的是bootloader的中断向量,为了不丢失原有的bootloader中断向量,还得先把硬件中断向量写到提前开辟的bootloader中断向量区,再把APP的中断向量写到硬件中断向量区。同理可得,在APP的场子,你想回到bootloader程序区得把硬件中断向量区的中断向量存回APP中断向量区,把bootloader的中断向量写到硬件中断向量区。

      都说bootloader中尽量不要开中断,但在笔者的方案里,bootloader中断尽管用,没关系,no problem,大丈夫,当然说是这么说,乱开一通还是不好的,省点单片机资源。

      说到这里就可以解释应用这种中断处理方案的bootloader为什么不能做到全局初始化功能。bootloader跳转到APP后,硬件中断向量区已经存储了APP中断向量,系统重新上电后,从APP的复位向量地址(当前0xfffe)开始运行,不再经过bootloader。


回复

55

帖子

0

资源

一粒金砂(中级)

luaffy 发表于 2020-8-16 17:09 关于中断向量表     什么叫建立中断向量表?按笔者的理解解释一下—&mda ...

这个怎么底部有图啊,嗨呀好丑啊

点评

应该是你发帖的时候上传上去了但是实际没有使用到的图  详情 回复 发表于 2020-8-16 17:34

回复

1万

帖子

2836

资源

管理员

luaffy 发表于 2020-8-16 17:17 这个怎么底部有图啊,嗨呀好丑啊

应该是你发帖的时候上传上去了但是实际没有使用到的图


回复

12

帖子

4

资源

一粒金砂(中级)

支持


回复

55

帖子

0

资源

一粒金砂(中级)

  • 关于通讯协议

该部分笔者在论坛

http://bbs.eeworld.com.cn/forum.php?mod=viewthread&tid=1136806&page=1#pid3001957发起过讨论。

借用chunyang(ID)先生的话——“固件更新必须保证足够的可靠性,而为保证可靠性,不能简单单向直接连续发,那样的话,错一个位,全部固件就废了,甚至会影响到再次更新,导致设备彻底报废,这是绝对不可以的。所以,远程更新固件,数据的可靠性必须保证。如此,必须将固件拆成一系列小包,用协议打包,必须严格校验,用会话机制双向通迅,帧长度限制在系统RAM尺寸以内。非远程升级,在大幅放宽通迅中出错可能性时,可以用串口的9位模式,即按字节发送,奇偶校验,但依然得是会话式的。一个字节编程完后,回一个标志字节,上位机/编程器再发送下一个字节。校验未通过时,则返回特定的标志,然后重新发送,若干次失败则报错提醒。这是远程更新以及所有ISPIAP编程的通用工艺。

由于固件更新需要足够的可靠性,串口接收更新的APPtxt文件时,需要制定具有严格校验的通讯协议,或者使用Ymodem/Xmodem等常用的通讯协议。


回复

55

帖子

0

资源

一粒金砂(中级)

本帖最后由 luaffy 于 2020-8-17 12:48 编辑
  • 关于跳转指令

        APP和bootloader除了功用和所存的地址外,本质上并没有什么不同。更新APP和更新bootloader的流程高度一致,而两个区不能“自杀”,更新APP时,需要在bootloader代码区中进行操作,更新bootloader时,需要在APP代码区中进行操作,步骤如下:

        给bootloader和APP分区-->建立中断-->

        串口接收APP(bootloader)更新数据-->将接收到的数据写入flash相应的APP(bootloader)程序区-->保存硬件中断向量区中的bootloader(APP)中断向量,将APP(bootloader)的中断向量写入硬件中断向量区-->使用跳转指令使PC指针跳转到app(bootloader)程序区。

        跳转指令常用的是C语言asm汇编内嵌语法:asm("mov &0xFFBE,pc;");// 0xFFBE为APP复位中断向量地址

        也可使用函数指针进行跳转:(*((void(*)())0xFFBE))();

       具体不展开说明,因为还不太熟。


回复

55

帖子

0

资源

一粒金砂(中级)

本帖最后由 luaffy 于 2020-8-17 12:36 编辑
  • 关于疑难点(更新中)

        研究新事物阶段总是要碰点壁,但有过有功,时间浪费了,但是将一点理解透彻了,才有日后举一反三的可能。如果按照说明书把实验一步步按部就班地完成,很难得到什么启发(比如说我脱离了老师打印的C++搭建简单应用程序的教程的话,就仿佛没有上过这门课。)

        以下将罗列出我在研究阶段碰到的问题,每个问题后方都标注了目前的状态——已解决、搁置、急需解决。对于被搁置或未解决的疑点,如果有好的解释,非常欢迎您的解答。


回复

55

帖子

0

资源

一粒金砂(中级)

本帖最后由 luaffy 于 2020-8-17 12:47 编辑

1、APP的中断一触发,单片机就死机?(已解决)

        这是我在网上看到的最多的问题。

        这里提供一种可能——中断向量指向的地址里的值是空值ff image.png         当PC指针按照中断向量的指示跑掉一个地址里运行中断程序,但发现这所谓的中断程序的内容却是空值ff,指针迷路了。迷路的指针只能回到复位中断向量,触发复位。

        


回复

55

帖子

0

资源

一粒金砂(中级)

2、编写bootloader的时候,为什么不能胡乱建立中断向量表?(已解决)

        这一点我在搭建初期,误解了网上的意思,在这损耗了我绝大部分的时间。

        “bootloader和app先把中断向量表都分别建立起来……”听话地建立起来后,发现编译报错。报错信息提示,中断区大小不足。

image.png         修改APP的xcl文件的-Z(CODE)INTVEC=FF80-FFBF修改为FF7E-FF8F。编译通过,但是后续APP的中断响应一直处理失败。后面才知道,建立中断向量的时候,多写了复位中断,复位中断向量应该是程序固定就有了(猜测)。正常情况下,中断向量从第一个地址(即FF80)开始装填,直到FFBF结束。所以如果从FF7E开始装填中断向量,正常的中断向量地址一般会增加两个字节的偏移量,这样中断没有经过额外处理的话,如何正常响应?

image.png

回复

55

帖子

0

资源

一粒金砂(中级)

3、为什么bootloader不能截获所有中断?(搁置)

        我的中断处理方案之一,为只在bootloader里建立中断向量,由bootloader截获所有中断,中断触发后,根据固定存在flash的标志位判断是app还是bootloader的中断,如果是app的中断,即由跳转指令跳转到app的相应地址执行。

image-20200817124959-1.png

        流程中挑不出毛病,串口接收中断也实验成功。但是定时中断响应异常,不断复位。


回复

55

帖子

0

资源

一粒金砂(中级)

4、涉及到硬件中断向量时,段擦写flash,为什么把flash后续所有地址都擦除了?(搁置)

        更新APP结束后,跳转APP程序区之前,需要操作三段中断向量区。

        流程为:①buffer读取硬件中断向量区(FFC0-FFFF)的bootloader中断向量;②擦除bootloader中断向量区(FF00-FF3F);③buffer内容填入bootloader中断向量区;④buffer读取APP中断向量区(FF80-FFBF)的APP中断向量;⑤擦除硬件中断向量区;⑥buffer内容填入硬件中断向量区。

        理想很丰满,现实是第二步擦除时,FF00-FFFF的内容已经全被擦了。

        虽然可以一次性读完FF00-FFFF的内容,再调换顺序填入flash,但是我还是很纠结造成上面异常擦除的原因。

补充内容 (2020-8-20 15:36): (已解决

回复

3953

帖子

1

资源

五彩晶圆(初级)

>>>涉及到硬件中断向量时,段擦写flash,为什么把flash后续所有地址都擦除了?

你的看器件手册确定擦除具体多大。我前段时间操作过一颗片子,说是一个段1K,结果擦除只能4K擦。还有一颗片子说是支持4K,32K,64K擦除,结果只能64K的单位擦,不知道原因。

个人签名人已离开,无事别找,找也找不到。

回复

55

帖子

0

资源

一粒金砂(中级)

freebsder 发表于 2020-8-17 22:28 >>>涉及到硬件中断向量时,段擦写flash,为什么把flash后续所有地址都擦除了? 你的看器件手册确定 ...

一个段64个字节,擦写程序是平时操作A、B、C、D段用的,没出过问题


回复

3953

帖子

1

资源

五彩晶圆(初级)

F系列铁电存储,不是可以直接当sram那种读写吗?

个人签名人已离开,无事别找,找也找不到。

回复

55

帖子

0

资源

一粒金砂(中级)

freebsder 发表于 2020-8-18 15:18 F系列铁电存储,不是可以直接当sram那种读写吗?

感谢指点

经过试验,该问题有了答案。

    原因:msp430f247,flash main memory一次擦除8段,512字节,flash information memory一次擦除一段,64个字节。依据如下——

image-20200820153441-1.png

    经过试验,往flash写了2k数据,在中间选取某一段擦除,可见512个字节被擦除了。


回复

55

帖子

0

资源

一粒金砂(中级)

由于原方案被毙了,现在分享中断处理方案二。

方案一:

        开辟两个虚拟中断向量区(APP、bootloader)和一个硬件中断向量区,跳转APP前,保存硬件中断向量区的bootloader中断向量,将APP中断向量写入硬件中断向量区。

方案二:

        使用__no_init申请RAM内存空间,建立不可被上电初始化的标志位flag。bootloader重映射中断向量表。

        中断触发时,进入中断服务函数(ISR),如果满足APP跳转条件(判断flag的值),由跳转指令跳转到APP的中断服务函数,即跳到APP中断向量区对应的向量所指向的地址,执行APP中断服务函数;如果不满足条件,则执行bootloader中断程序。

 

两者的优缺点很明显。

        方案一优点:简单、直白,避免了中断重映射地址转移而造成的错误,APP和bootloader之间无耦合。

        缺点:需要划分并操作三个中断向量区——APP、bootloader、硬件;系统上电不经过bootloader,如果APP死机,则bootloader丧失了对APP进行串口维护的功能;app升级,bootloader更新都需要擦写中断向量区,加重了擦写flash的负担

 

        方案二优点:只需要两个中断向量区——硬件、APP;系统上电经过bootloader,bootloader代码数据比app小得多,不容易发生死机;不需要多次擦写中断向量区

        缺点:bootloader和app共用一个串口中断,增加编程的难度。(虽然bootloader可以不用串口中断收发数据);APP和bootloader的耦合度高。

补充内容 (2020-9-4 09:20): 部分内容有误,__no_init定义的数据不能“不被上电初始化”,不管怎么说RAM的数一掉电就无了,应该是不可被“复位初始化”

回复
您需要登录后才可以回帖 登录 | 注册

最新文章 更多>>
    关闭
    站长推荐上一条 1/8 下一条

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

    电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2021 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表