bootloader学习笔记---第二篇_bootloader 中断向量表-程序员宅基地

技术标签: 学习  stm32  c语言  汽车电子  单片机  

目录

一、链接地址与跳转

二、bootloader疑难问题

1、应用程序中使用中断导致程序跑飞或者不能重新下载程序?

2、中断向量表具体是怎么重映射?

3、bootloader更新app过程中意外断电,怎么处理?流程是先备份后擦出然后烧写吗?

4、botloader烧写app程序过程中突然断电或者断开连接导致bootloader无法使用,必须重新烧写,这是什么原因呢?

5、怎么将BOOT程序和APP程序一起烧进板子?

6、第一,多核芯片是否给每个核编写一个bootloader,并分别放在每个核相应的flash里?第二,上位机软件下发的信息是否可以通过ID来区分送到哪个核里?第三,上位机软件是不是必须和CAN盒子配套?

 7、bootloader升级过程很慢,100k左右的s19文件需要十多分钟?

8、boot程序,对于app的跳转地址有什么要求?boot程序比较大,跳转地址是0x25000,跳转总是失败?

9、可以直接从APP区域跳转到到BOOT区域直接升级,而不用经过一个重启的过程吗?正常项目都是APP启动升级的

10、boot 更新app的时候,将flash drv(擦除,写入等风险操作函数)临时通过can从上位机下载到ram中并运行,通过修改链接文件指定自定义的一块ram,可以把收到的flash drv的数据放到这块地址,在执行擦除或者写入操作时,1.怎么找到擦除或写入函数的ram地址并执行?2.如果可以找到地址,怎么往擦除或写入函数传递参数(这两个函数知道ram地址,不是函数,怎么传递参数)?

11、将地址强制转换为函数指针调用,会造成hard fault interrupt?

三、备注


一、链接地址与跳转

这里讨论第一篇文章中提到的第二种情况,即第二种常见的情况就是app烧写在flash上,app应该在ram内存里运行,app或者是bootloader需要把app拷贝到内存ram中去,1、如果是bootloader拷贝的,那么bootloader要跳转到内存ram中去执行app;2、如果是app自己把自己复制到内存中去的,那么bootloader直接跳转到app的位置就可以了。

这里有三个问题,1、谁把app从flash复制到ram中去?2、具体是复制到哪里?3、如果bootloader要跳转到ram中去怎么跳?

第一个问题,app自我复制,bootloader帮忙复制;第二个问题,这个地址我们可以预先设置好;第三个问题,用函数指针跳转。

下面介绍两种跳转方式
第一、相对跳转,BL main; 这是条汇编语句,这条语句会让pc=当前pc+相对位移。不管我们程序放在哪里,相对跳转都能成功。编译器是默认优先使用相对跳转。

 

第二、绝对跳转,是让pc=要跳转的地址。比如,LDR r5 , [pc, #24]     BLX r5。函数指针的方式也是绝对跳转的方式。对于绝对跳转,在对应的地址上面必须有对应的代码。stm32上电后第二件事情就是跳转到Reset_Handler中去,这也是绝对跳转。如果是长距离调用,也会使用绝对跳转。如果是绝对跳转,我们程序烧录的位置如果发生变化,即我们烧录的地址和链接文件(散列文件)中指定的地址不一致,那么跳转过去的地址就会出现错误,因为跳转的绝对地址的那块内存可能没有初始化,程序会崩溃。

散列文件

 

如果我们如上图那样使用散列文件修改了app程序的链接地址,那么app程序会把指令和数据放在0x20000000。那么这相当于,bootloader跳转到app中,app自己把自己复制到0x20000000。可以看到散列文件中,链接地址和加载地址都是同一个地址,链接地址就是运行时的地址,我们可以使用烧录工具来决定程序的烧录地址,在这里加载地址没有用,只有链接地址有用。

 上面的代码是app自己复制自己到内存的

第二种情况,需要bootloader把app复制到内存中去时,app文件的头部一般会包含以下几种信息,1、加载地址:即要拷贝到内存的那个地址,2、入口地址:即第一条指令地址,3、长度,4、CRC。

这就需要bootloader启动后需要去app的烧录地址读取这些头部信息,接着解析这些头部信息,然后读取app.bin存入内存,最后跳转到内存中去执行app程序。

解析头部信息,需要注意的是,存储方式是大字节序还是小字节序,

这里我补充一个知识点:我们在对flash进行读写操作时,flash中对应的应用程序文件将不能运行,所以必须将flash driver拷贝到ram区域,这是由flash的硬件性质决定的,为什么呢?

因为,flash只有一套自己的crossbar(类似交叉开关,同一时刻只能执行一种操作)访问总线,当其被用作写数据时,不能同时读取数据(譬如CPU取指执行程序)。但在支持RWW partition的flash中是不必如此操作的,它支持在不同flash分区同时进行读和写。

二、bootloader疑难问题

1、应用程序中使用中断导致程序跑飞或者不能重新下载程序?

这个要看具体的MCU(内核),一个原则是使能中断和异常发生之前必须确保其中断向量表和中断/异常ISR已经ready。

2、中断向量表具体是怎么重映射?

更改向量表基地址寄存器,也叫中断向量表偏移量寄存器,中断向量表的重定向可以是在bootloader进入用户程序之前改,也可以在用户程序里面改,对于在Cortex-M3内核的MCU上可以通过设置SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET,关于这个寄存器的描述可以见下图;该寄存器的值来实现中断向量表的重定义。如果没有这类的寄存器可以参考这位博主的办法尝试解决STM32F0芯片IAP实现之中断向量表重映射(没有中断向量表偏移寄存器SCB->VTOR的应对方法)_a只如初见的博客-程序员宅基地_中断重映射

3、bootloader更新app过程中意外断电,怎么处理?流程是先备份后擦出然后烧写吗?

一般是双应用程序分区,更新完新的应用程序之后才擦除老的应用程序分区并设置跳转标志,以保证时钟有一个分区中的应用程序正确可用。

4、botloader烧写app程序过程中突然断电或者断开连接导致bootloader无法使用,必须重新烧写,这是什么原因呢?

如果应用程序新过程中断电或者意外复位,则应用程序更新失败,相应的应用程序完整性校验通不过,当然得重新下载,为了避免这种情况下应用程序丢失,常常BootLoader需要对应用程序进行双备份,即使用两个不同的NVM分区来保存应用程序,只有新的应用程序更新成功之后,才擦除老的应用程序。

5、怎么将BOOT程序和APP程序一起烧进板子?

用任意文本编辑器打开bootloader和app工程生成的S19文件拷贝即可合并,然后使用调试器通过SWD/JTAG接口下载即可。

6、第一,多核芯片是否给每个核编写一个bootloader,并分别放在每个核相应的flash里?第二,上位机软件下发的信息是否可以通过ID来区分送到哪个核里?第三,上位机软件是不是必须和CAN盒子配套?

多核MCU只需要为其boot CPU core开发一个bootloader就可以了,可以通过ID或者地址来判断,可以复用我们的上位机软件,但其只有简单功能,要用这个上位机软件需要使用匹配的CAN适配器,否则需要修改底层dll以适用于其他CAN适配器

 7、bootloader升级过程很慢,100k左右的s19文件需要十多分钟?

Flash擦除本身很耗时间,另外,可以在将S19文件每行的数据设置为更长(比如128字节或者512字节)或者把bootloader里面改为接收10行s19再烧写,提高Flash烧写效率,再或者就是提高通信速率

8、boot程序,对于app的跳转地址有什么要求?boot程序比较大,跳转地址是0x25000,跳转总是失败?

这个要看跳转具体是如何实现的?要反汇编看看具体的汇编跳转指令,不同的汇编跳转指令支持的跳转地址范围不同。

9、可以直接从APP区域跳转到到BOOT区域直接升级,而不用经过一个重启的过程吗?正常项目都是APP启动升级的

可以在APP中接收到boot请求后使用函数指针直接跳转到bootloader的reset_handler,但需要在跳转之前反初始化/复位APP使用的所有时钟和外设,以避免APP与bootloader的相互影响。当然,我们推荐的方式还是软件复位或者看门狗溢出复位进入bootloader。

10、boot 更新app的时候,将flash drv(擦除,写入等风险操作函数)临时通过can从上位机下载到ram中并运行,通过修改链接文件指定自定义的一块ram,可以把收到的flash drv的数据放到这块地址,在执行擦除或者写入操作时,1.怎么找到擦除或写入函数的ram地址并执行?2.如果可以找到地址,怎么往擦除或写入函数传递参数(这两个函数知道ram地址,不是函数,怎么传递参数)?

第1个问题,使用函数查找表,类似中断向量表的工作原理;第2个问题使用函数指针,因为函数名本身就是地址,我们可以定义一个和flash drv相同格式的函数指针,然后向这个函数指针传递的参数就是传递给了flash drv函数;

11、将地址强制转换为函数指针调用,会造成hard fault interrupt?

typedef void(*pfun_t)(void);
 pfun_t pfun = (pfun_t)0x00500000; 
pfun(); 

注意是把中断向量(中断ISR函数地址,存在中断向量表地址的内容)而不是中断向量地址本身转换成函数指针执行。

三、备注

本文部分内容是根据韦东山老师的视频整理编写的笔记从0写BootLoader(适用于单片机),还有部分公众号中汽车电子expert成长之路的文章评论,部分图片来自于cortex-m3权威指南。

=文档信息=
本学习笔记由博主整理编辑,仅供非商用学习交流使用
由于水平有限,错误和纰漏之处在所难免,欢迎大家交流指正
如本文涉及侵权,请随时留言博主,必妥善处置
版权声明:非商用自由转载-保持署名-注明出处

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_44795447/article/details/125615960

智能推荐

【Linux】bash: /home/stefan/jdk1.7.0_55/bin/java: /lib/ld-linux.so.2: bad ELF interpreter_-bash: /home/rootplace/jdk8/bin/java: /lib/ld-linu-程序员宅基地

文章浏览阅读215次。今天在linux系统中配置jdk的时候,配置完成之后提示bash: /home/stefan/jdk1.7.0_55/bin/java: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory后来感觉可能只因为之前卸载yum导致的问题,因为我在另外一个虚拟机中也是这么配置的于是搜了一下问题,执行如下命令即可yu..._-bash: /home/rootplace/jdk8/bin/java: /lib/ld-linux.so.2: bad elf interpreter: 没有那个文件或目录

高级SQL优化(一) -程序员宅基地

文章浏览阅读319次。目录:Oracle数据完整性和锁机制 索引及优化之表分析 表分析、约束及表间关系 Oracle体系结构1Oracle体系结构2 海量数据库及分区1 海量数据库及分区2 海量数据库及分区3 海量数据库及分区4 高级SQL优化(一) PPT和源码下载: http://sishuok.com/forum/posts/list/6..._高级sql优化

List根据条件删除元素的几种方式-程序员宅基地

文章浏览阅读7.2k次,点赞2次,收藏8次。第一种:迭代器 Iterator<Project> it = projectList.iterator(); while(it.hasNext()){ Project p=it.next(); if (!allProjectMap.containsKey(p.getId())){ it.remove(); }; _list根据条件删除

三星sm-g7106"com.android.mms,Android系统版本及其屏幕适配-程序员宅基地

文章浏览阅读486次。Android设备分辨率趋势 对应关系表资源文件夹 屏幕分辨率 类型 对应图标尺寸 屏幕密度1dpxhdpi超高分辨率 1280*720 WQVGA 96*96 320 =2hdpi高分辨率480*800 WVGA 72*72 240 =1.5mdpi中等分辨率 480*320 HVGA、VGA 48*48 160 =1ldpi低分辨率 320*240 ..._com.android.mms

两个N×N矩阵相乘的算法。_n*n两个矩阵相乘的算法描述-程序员宅基地

文章浏览阅读4.6k次,点赞2次,收藏10次。两个N×N矩阵相乘的算法。#include<stdio.h>#define n 3int main(){ int i, j, k; int a[n][n] = { 1,2,3,4,5,6,7,8,9 }, b[n][n] = { 1,2,3,4,5,6,7,8,9 }, c[n][n] = { 0 }; for (i = 0; i < n; ++i) //i是数组a的行 { for (j = 0; j < n; ++j) //j是数组b的列,k是数组a的_n*n两个矩阵相乘的算法描述

Spring Boot 上传文件代码model_at com.fsglink.backend.controller.fileuploadcontro-程序员宅基地

文章浏览阅读106次。代码如下:FileUploadController.java文件package com.example.uploadFile.uploadFile.controller;import java.io.File;import java.io.IOException;import org.springframework.stereotype.Controller;import org...._at com.fsglink.backend.controller.fileuploadcontroller.uploadfile(fileupload

随便推点

php mysql实现购物车功能_PHP实现购物车的思路和源码分析-程序员宅基地

文章浏览阅读688次。这里主要是记录下自己的购物车的思路,具体功能实现,但是尚未在实际项目中用到,不对之处欢迎指正项目中需要添加购物车。目录说明buy.php 点击购买之后的操作car.php 购物车,显示购买的东西conn.php 数据库连接参数delete.php 删除商品index.php 入口文件shop.sql 数据库sql文件test.png 商品图片首先需要理解的是..._php和mysql如何实现购物车的功能

ubuntu16.04初安装,ROS kinetic,安装ros,配置ros环境_乌班图16.04.6-程序员宅基地

文章浏览阅读899次。更新命令sudo apt-get updatesudo apt-get upgradesudo apt-get dist-upgradesudo apt-get -f installros中添加qt 增加Qt5SerialPor库sudo apt-get install ros-kinetic-qt-createsudo apt-get install ros-kinetic-qt-buildsudo apt install libqt5serialport5-devsudo a_乌班图16.04.6

【课程设计】基于C++的计算机辅助教学(CAI)软件开发:教学生学英语_计算机辅助教学(cai)软件设计与实现-程序员宅基地

文章浏览阅读1.5k次,点赞3次,收藏21次。题目:计算机辅助教学(CAI)软件开发:教学生学英语。   功能:屏幕上随机出现一个汉语单词,英语单词,汉语词组,英语词组或一短句提示学生给出相应答案,答错了要提示要求重新输入,直到答对为止。要统计给分,且累计,够一定分数后可进级,即从单词到词组,从词组到短句。同样,也可降级。起步阶段可各选30个,软件可扩充,即扩大词库的容量。_计算机辅助教学(cai)软件设计与实现

k8s学习 k8s使用nodeport方式配置service对外暴露服务_如何让集群中mysql向外暴露-程序员宅基地

文章浏览阅读4.7k次。k8s学习 k8s使用nodeport方式配置service对外暴露服务1、创建yaml service.yaml 把集群中的mysql 服务对外暴露2、用node ip 访问1、创建yaml service.yaml 把集群中的mysql 服务对外暴露---apiVersion: v1kind: Servicemetadata: name: mysql-service labels: name: mysql-servicespec: type: NodePort _如何让集群中mysql向外暴露

随记:如何测试一段程序执行的时间_如何测试程序段-程序员宅基地

文章浏览阅读312次。随记:如何测试一段程序执行的时间最近在测试call,apply,bind三者的性能的时候,想测测所消耗的时间,结果不知道如何测试比较好,之后在网上搜索了一番,发现了一个挺好用的方法。想必大家都认识console.log,这个方法跟这个很像,很像console.time('A'); for (var i = 0; i < 100000; i++) {}console.t..._如何测试程序段

辗转相除法求最大公约数以及最小公倍数_最大公倍数和最小公约数,m>n,辗转除法,输出结果-程序员宅基地

文章浏览阅读109次。辗转相除法求最大公约数以及最小公倍数#include<stdio.h>int main(){ int m,n,d,t,mul; printf("请输入两个数字:\n"); scanf("%d %d",&m,&n); mul = m*n; if(m<n)//如果m<n,则交换值 { t = m; m = n; n = t; } for(d = 1;;)//辗转相除法,对d进行一次初始化 { d = m%n; if(d=_最大公倍数和最小公约数,m>n,辗转除法,输出结果

推荐文章

热门文章

相关标签