丢丢时光机 发表于 2019-6-19 16:56:45

遇到STM32 A,B区 app升级困难,各路大神,帮忙看一下。

我正在做一个bootloader(boot+app1+app2)。

app1运行的时候,升级app2,校验合法后,然后重启直接运行APP2。
app2运行的时候,升级app1,校验合法后,然后重启直接运行APP1。。。。。。

目前的困难是,如何能够将APP1与APP2做成同一个固件?今天对比了下不同位置的固件,发现只有前480个字节的vector table不同。

今天做了些尝试,app的固件以地址0x8000000生成(RAM预留1k,以存放中断向量表)。
bootloader运行时,将vector table 整个复制到RAM的最前面(根据APP的不同地址,重新修正中断向量表,比如app2的运行地址是0x80005000,则将中断向量表统一加上0x5000);
但是发现这样子行不通,无法正常运行。是不是我哪里有缺漏的地方?

实在没办法的话,只能固件升级时,将中断向量表修改掉??

lyz3432 发表于 2019-6-19 17:02:09

每个程序各自设置向量表地址, 你咋还用bootloader去复制向量表啊?

heicnhei3 发表于 2019-6-19 17:06:24

我也觉得复制向量表太麻烦了,每个程序单独一个项目,单独一个地址配置

丢丢时光机 发表于 2019-6-19 17:12:52

lyz3432 发表于 2019-6-19 17:02
每个程序各自设置向量表地址, 你咋还用bootloader去复制向量表啊?

我想将APP1,与APP2做成同一个固件,目标是这个。不然也不存在中断向量表的问题。

kebaojun305 发表于 2019-6-19 17:13:01

整个程序区分3部分 boot+app1+app2   都是单独的配置就行了,你复制向量表 干吗?

aozima 发表于 2019-6-19 17:13:07

写个脚本,自动编译2次。

AB区麻烦,安全性并不比只有A区要好。
还是单A区,B区可以压缩 ,也可以放外部,更简单经济。

justdomyself 发表于 2019-6-19 17:16:35

app2作为接收缓存区,升级时放在2区,重启后,boot把2考到1,再重启,运行1

丢丢时光机 发表于 2019-6-19 17:24:02

justdomyself 发表于 2019-6-19 17:16
app2作为接收缓存区,升级时放在2区,重启后,boot把2考到1,再重启,运行1

若是作为缓存区接收的话,没法做版本回退了。

istars2005 发表于 2019-6-19 17:36:14

aozima 发表于 2019-6-19 17:13
写个脚本,自动编译2次。

AB区麻烦,安全性并不比只有A区要好。


请教怎么实现自动编译两次呢?
也遇到这个问题过
都是分两次编译
生成两个bin文件
然后再把两个文件合并起来的

落叶知秋 发表于 2019-6-19 17:38:19

我来为楼主翻译一下:
楼主其实就是想做一个旧APP备份的功能,然后想开辟APP1区域和APP2区域,轮流进行备份旧的代码程序;
但楼主又想着代码功能是一样的,只想使用同一个升级固件,然后MCU可以自己实现在APP1和APP2之间跳转;
目前楼主觉得是中断向量表的问题,尝试把向量表拷到RAM里面,结果不行。
各位,明白了吧?

lyz3432 发表于 2019-6-19 17:38:34

丢丢时光机 发表于 2019-6-19 17:12
我想将APP1,与APP2做成同一个固件,目标是这个。不然也不存在中断向量表的问题。 ...

两次编译完,写个脚本merge到一起就好了啊

lyz3432 发表于 2019-6-19 17:40:21

istars2005 发表于 2019-6-19 17:36
请教怎么实现自动编译两次呢?
也遇到这个问题过
都是分两次编译


cmake 写的 就是当两个工程啊 编完一个在遍另一个啊当是脚本自动调的啊

aozima 发表于 2019-6-19 17:46:38

istars2005 发表于 2019-6-19 17:36
请教怎么实现自动编译两次呢?
也遇到这个问题过
都是分两次编译


工程文件都一样的,就链接脚本里面地址不同而已。
写个脚本之类的来做呗,全自动才能不出错。
错后 得到 a.bin b.bin
再像上面网面说的合并成一个。

但你上传到云端时,可能也可以打成一个,还要对bin做一下校验,防止损坏。
因为现在各个云都是只让上传一个文件,没见过2个的。

反正,AB就是坑。

落叶知秋 发表于 2019-6-19 18:00:28

楼主不应该在bootloader运行的时候把中断向量表复制到RAM

应该在APP运行的时候把Flash里面的中断向量表复制到RAM,然后APP的代码根据当前是运行在APP1还是APP2,修改RAM里面相应的地址偏置,最后把MCU中断向量表的寄存器指到RAM里

丢丢时光机 发表于 2019-6-19 18:11:33

落叶知秋 发表于 2019-6-19 18:00
楼主不应该在bootloader运行的时候把中断向量表复制到RAM

应该在APP运行的时候把Flash里面的中断向量表复 ...

效果是一样的啊。因为boot里面已经读取了分区信息,想着直接用了得了,不想再app里面再判断这些玩意。

丢丢时光机 发表于 2019-6-19 18:13:22

落叶知秋 发表于 2019-6-19 18:00
楼主不应该在bootloader运行的时候把中断向量表复制到RAM

应该在APP运行的时候把Flash里面的中断向量表复 ...

boot及app的ram起始1K的空间,单独存放向量表的。boot里操作跟app里操作,效果应该是一样的。

落叶知秋 发表于 2019-6-19 18:22:28

丢丢时光机 发表于 2019-6-19 18:13
boot及app的ram起始1K的空间,单独存放向量表的。boot里操作跟app里操作,效果应该是一样的。 ...

没考虑过boot跳转到APP执行时,APP的初始化流程会复位RAM?

落叶知秋 发表于 2019-6-19 18:24:11

丢丢时光机 发表于 2019-6-19 18:13
boot及app的ram起始1K的空间,单独存放向量表的。boot里操作跟app里操作,效果应该是一样的。 ...

如果你APP里面没改过.s汇编文件的话,一般都会在运行到main之前把RAM初始化为0的

丢丢时光机 发表于 2019-6-19 18:32:00

落叶知秋 发表于 2019-6-19 18:24
如果你APP里面没改过.s汇编文件的话,一般都会在运行到main之前把RAM初始化为0的 ...

这个有测试,RAM没有被清空; ld文件里面改了RAM的起始地址。

丢丢时光机 发表于 2019-6-19 18:37:20

坛友帮帮忙。这个问题解决了的话,我把这个A,B升级方案的工程分享到论坛给大家参考。

flash3g 发表于 2019-6-19 18:54:03

中断向量表偏移过去就行啦

823032003 发表于 2019-6-19 19:06:27

我觉得不止中断向量表,函数地址这些也要改,否则跳转的时候还是跳到编译器编译那个地址

823032003 发表于 2019-6-19 19:08:41

lyz3432 发表于 2019-6-19 17:38
两次编译完,写个脚本merge到一起就好了啊

merge到一起怎么理解呢?

istars2005 发表于 2019-6-19 19:55:35

aozima 发表于 2019-6-19 17:46
工程文件都一样的,就链接脚本里面地址不同而已。
写个脚本之类的来做呗,全自动才能不出错。
错后 得到...

通过修改工程的.sct文件可以实现
但是源文件中还需要执行NVIC_SetVectorTable
否则程序运行肯定会出错

这样写脚本就得把这部分考虑进去了
有什么好办法能解决这个问题吗?

istars2005 发表于 2019-6-19 19:57:19

823032003 发表于 2019-6-19 19:08
merge到一起怎么理解呢?

就是把两次生成的a.bin和b.bin直接连接起来
因为两个文件字节数是完全相同的
升级时候程序判断自己是a还是b,然后自己从merge完的文件中找到需要升级的文件偏移就行了

huangqi412 发表于 2019-6-19 20:01:26

我记得f0没有偏移量就是将向量表放在内存实现啊

丢丢时光机 发表于 2019-6-19 20:02:20

823032003 发表于 2019-6-19 19:06
我觉得不止中断向量表,函数地址这些也要改,否则跳转的时候还是跳到编译器编译那个地址 ...

对的,中断向量表里面的函数地址不同,APP放在不同的位置,中断向量表里面的地址也应随之发生改变。

丢丢时光机 发表于 2019-6-19 20:03:18

huangqi412 发表于 2019-6-19 20:01
我记得f0没有偏移量就是将向量表放在内存实现啊

我这个是STM32F105.应该跟M0不一样

huangqi412 发表于 2019-6-19 20:05:38

丢丢时光机 发表于 2019-6-19 20:03
我这个是STM32F105.应该跟M0不一样

我的意思是 f0就是将向量表放在内存做的boot将aopp的表搬运到内存   没道理你放在内存不能用

xujihu 发表于 2019-6-19 20:29:24

直接工具合成两个app的bin文件不行吗

aozima 发表于 2019-6-19 20:33:55

但是源文件中还需要执行NVIC_SetVectorTable
否则程序运行肯定会出错

可以让boot来处理

istars2005 发表于 2019-6-19 20:45:23

aozima 发表于 2019-6-19 20:33
可以让boot来处理

赞,这样确实可以解决问题

canspider 发表于 2019-6-19 21:25:37

丢丢时光机 发表于 2019-6-19 17:24
若是作为缓存区接收的话,没法做版本回退了。

版本回退是伪需求,只是为了掩盖测试不充分

justdomyself 发表于 2019-6-19 21:43:56

canspider 发表于 2019-6-19 21:25
版本回退是伪需求,只是为了掩盖测试不充分

严重赞同,,,

plc_avr 发表于 2019-6-19 21:52:35

A,B两个交互用,会整死人。可靠升级是把B当存储区,接收完成从B搬到A,A运行

了无 发表于 2019-6-19 22:17:37

丢丢时光机 发表于 2019-6-19 20:02
对的,中断向量表里面的函数地址不同,APP放在不同的位置,中断向量表里面的地址也应随之发生改变。 ...

对,我们最近也有个这种项目要开发,我也在想工程里面那些函数指针咋办,应该要把工程搞成地址无关的,或者可以设置整体偏移值。

丢丢时光机 发表于 2019-6-19 23:23:30

了无 发表于 2019-6-19 22:17
对,我们最近也有个这种项目要开发,我也在想工程里面那些函数指针咋办,应该要把工程搞成地址无关的,或 ...

打算固件升级时,把固件中的中断向量表部分直接修改后,存入相应的flash。

了无 发表于 2019-6-20 00:24:34

丢丢时光机 发表于 2019-6-19 23:23
打算固件升级时,把固件中的中断向量表部分直接修改后,存入相应的flash。 ...

你试试,把结果与问题发上来讨论讨论,我会持续关注这个帖子,咱们一块把这个问题解决了,你的问题解决了,我的也就解决了

丢丢时光机 发表于 2019-6-20 10:09:24

了无 发表于 2019-6-20 00:24
你试试,把结果与问题发上来讨论讨论,我会持续关注这个帖子,咱们一块把这个问题解决了,你的问题解决了 ...

我准备放弃AB方案了。今天用工具对比了下两个不同位置的bin,发现不同的地方不仅仅是VECTOR TABLE.固件从头到尾都有不同的地方。

armstrong 发表于 2019-6-20 10:34:21

丢丢时光机 发表于 2019-6-20 10:09
我准备放弃AB方案了。今天用工具对比了下两个不同位置的bin,发现不同的地方不仅仅是VECTOR TABLE.固件从 ...

这算不算出尔反尔?当你之前说出链接到两个不同地址时,只是向量表不同的时候,我就很怀疑了。

istars2005 发表于 2019-6-20 10:46:10

丢丢时光机 发表于 2019-6-20 10:09
我准备放弃AB方案了。今天用工具对比了下两个不同位置的bin,发现不同的地方不仅仅是VECTOR TABLE.固件从 ...

AB升级我觉得问题不大
有两个项目用到AB方案升级

主要是人为的需要控制好固件生成和merge
而且有时候生成的AB固件是不一样大的
二者最大有4个字节的差别
我吃过一次亏后来写了个批处理自动检查二者大小
然后再决定是不是merge

如果能通过脚本实现自动生成AB文件
并且检查大小 确保都没问题
那就大胆的使用

chendaon 发表于 2019-6-20 10:57:30

其实,一用一备更方便。

252514251 发表于 2019-6-20 11:17:20

弄同样的app,中断向量一样, 存放到不同的位置,决定复制一个app到程序区运行

oooios 发表于 2019-6-20 11:58:19

之前用1768,做ab区升级,最后发现,a b 的全局变量和函数要一样,不然,升级成功,也不能运行。最后放弃了使用一主一备。如果要a b都可以,需要用分散加载。

丢丢时光机 发表于 2019-6-20 13:12:09

armstrong 发表于 2019-6-20 10:34
这算不算出尔反尔?当你之前说出链接到两个不同地址时,只是向量表不同的时候,我就很怀疑了。 ...

昨天只生成了两个2K的flash。自认为很小,人工对比了下。结果自己犯了个错误。。。还得工具对比。

丢丢时光机 发表于 2019-6-20 13:17:59

落叶知秋 发表于 2019-6-19 17:38
我来为楼主翻译一下:
楼主其实就是想做一个旧APP备份的功能,然后想开辟APP1区域和APP2区域,轮流进行备份 ...

我的主要问题是,生成一个固件,无论放在APP1的位置,还是APP2位置,boot都能跳转过去正确执行。

落叶知秋 发表于 2019-6-20 13:39:32

丢丢时光机 发表于 2019-6-20 13:17
我的主要问题是,生成一个固件,无论放在APP1的位置,还是APP2位置,boot都能跳转过去正确执行。 ...

OJBK,讨论的前提出错了,后面白忙活{:biggrin:}

ljx289 发表于 2019-6-21 08:06:13

在外面放个大的flash,boot的时候判断要不要升级就可以了。把boot做成出厂时的app固件,新版的app从网上自动下载,新版的app更新到另一个偏移量去

ljx289 发表于 2019-6-21 08:08:44

也就是每次升级都把固件先保存在外置的flash,可以保存很多份app固件,升级完进去app后要判断该app估计是否正常运行,如果不能正常运行就要做标记。判断:我是我还是我是我的影子,哈哈

retention 发表于 2019-6-21 08:13:14

向量表是个要注意的地方,前几天帮我客户处理过类似的问题,在仿真看到存放向量表数据是偏移之后的数据

Ary 发表于 2019-6-21 08:37:01

你得在APP1 和APP2 前加一段bootloader, 用它实现跳转升级APP1还是APP2

kebaojun305 发表于 2019-6-21 08:46:19

本帖最后由 kebaojun305 于 2019-6-21 08:50 编辑

丢丢时光机 发表于 2019-6-20 13:17
我的主要问题是,生成一个固件,无论放在APP1的位置,还是APP2位置,boot都能跳转过去正确执行。 ...

你这个 前提确实错了 除非你能修改app1或者app2得内部所有得地址。   这个功能 最简单的就是编译2个起始地址不同的app ,可以实现,你想编译一个app在2个不同flash地址中运行,是不可能的。

istars2005 发表于 2019-6-21 08:46:33

丢丢时光机 发表于 2019-6-20 13:17
我的主要问题是,生成一个固件,无论放在APP1的位置,还是APP2位置,boot都能跳转过去正确执行。 ...

你这个要求有点复杂吧,我一直是生成两个固件,然后合并在一起,然后根据当前运行的固件开判断从哪部分截取合并的固件

罗小蘑菇 发表于 2019-6-21 08:51:35

A\B来回切换想想很好,其实就会碰到楼主的问题,就是能实现也会遇到编译同一个文件的问题,想实现回退版本功能,不如分成四个区,BOOT引导区,APP区,代码备份区1,代码备份区2,升级后由BOOT实现把备份区的代码复制到APP区运行,备份区1和2交替存放最新升级文件。

ddddd120 发表于 2019-6-21 09:05:28

丢丢时光机 发表于 2019-6-20 13:17
我的主要问题是,生成一个固件,无论放在APP1的位置,还是APP2位置,boot都能跳转过去正确执行。 ...

感觉应该是编译出来2个app固件,编译的时候要在不同的基地址上编译,要不里面的跳转,函数定位都不一样的地址,然后合并到到一起,boot跳转到哪个都行

丢丢时光机 发表于 2019-6-21 10:17:59

istars2005 发表于 2019-6-21 08:46
你这个要求有点复杂吧,我一直是生成两个固件,然后合并在一起,然后根据当前运行的固件开判断从哪部分截 ...

A,B合成一个固件,对存储空间要求就高了,得外挂flash。

dalige 发表于 2019-6-21 10:35:08

A,B确实没必要,不如App和Store。
回退的实现本身就需要很多条件,如果你更新完了A有和回退相关的bug,还是死路一条。如果任何情况下你能通过Bootloader重新update firmware,则完全没必要存储旧的image。

丢丢时光机 发表于 2019-6-21 10:43:31

dalige 发表于 2019-6-21 10:35
A,B确实没必要,不如App和Store。
回退的实现本身就需要很多条件,如果你更新完了A有和回退相关的bug,还 ...

嗯,目前已经启用A运行B存储的方案了。

istars2005 发表于 2019-6-21 10:45:05

丢丢时光机 发表于 2019-6-21 10:17
A,B合成一个固件,对存储空间要求就高了,得外挂flash。

你是通过什么升级?
我都是把固件放在远端服务器
然后设备判断应该升级哪个固件
下载的时候直接就截断了
不需要把合并的固件都下载下来

jjj 发表于 2019-6-21 11:13:24

justdomyself 发表于 2019-6-19 17:16
app2作为接收缓存区,升级时放在2区,重启后,boot把2考到1,再重启,运行1

这个是正解!!!
再没比这个简单的了?

了无 发表于 2019-6-21 20:06:44

istars2005 发表于 2019-6-21 10:45
你是通过什么升级?
我都是把固件放在远端服务器
然后设备判断应该升级哪个固件


这位兄弟说的方法可行,不过也是妥协没办法的办法了

dhw5qq 发表于 2019-8-5 11:24:41

stm32m0和m3的中断向量机制不一样,m3可以通过寄存器实现中断向量重映射,但是M0好像只能从ram拷贝实现中断重映射。还有一个问题就是你的boot1引脚是从flash启动还是从

dhw5qq 发表于 2019-8-5 11:25:17

sram启动

steve_zhang 发表于 2019-8-5 14:18:06

丢丢时光机 发表于 2019-6-19 17:24
若是作为缓存区接收的话,没法做版本回退了。

你都能直接识别出版本了!为什么还不能做版本回退? 用个优先级更高的变量,让APP1 判断备份区的这个变量。

Sky2162 发表于 2019-8-9 11:26:27

这是在做OTA吗?

startwar0418 发表于 2023-12-25 16:16:26

istars2005 发表于 2019-6-20 10:46
AB升级我觉得问题不大
有两个项目用到AB方案升级


(引用自41楼)

好几年了,大哥你的AB分区好用吗?

istars2005 发表于 2023-12-25 16:58:07

startwar0418 发表于 2023-12-25 16:16
好几年了,大哥你的AB分区好用吗?
(引用自66楼)

很好用啊
需要注意的事项上面也提到了
需要控制一下
不然会有风险
不过从bootloader里面做好校验也不怕
我上次吃亏是boot里面没有处理

ffbiao 发表于 2023-12-25 17:09:28

能否分享一下方案细节

startwar0418 发表于 2023-12-26 08:38:27

istars2005 发表于 2023-12-25 16:58
很好用啊
需要注意的事项上面也提到了
需要控制一下

(引用自67楼)

看之前的回复,你是按AB两个分区分别编译完然后合成一个文件,Mcu自己判断用A还是B的然后刷进去?

istars2005 发表于 2023-12-26 08:42:05

startwar0418 发表于 2023-12-26 08:38
看之前的回复,你是按AB两个分区分别编译完然后合成一个文件,Mcu自己判断用A还是B的然后刷进去? ...
(引用自69楼)

是的
MCU会把当前的一些信息存在flash里面
根据这些信息来确定应该升级A还是B

startwar0418 发表于 2023-12-26 11:08:05

istars2005 发表于 2023-12-26 08:42
是的
MCU会把当前的一些信息存在flash里面
根据这些信息来确定应该升级A还是B ...
(引用自70楼)

不知你是否试过只生成一个app就能AB通用的。我看有的编译器有PIC (position-independent code)选项,似乎能实现一个App通刷AB区

istars2005 发表于 2023-12-26 21:19:10

startwar0418 发表于 2023-12-26 11:08
不知你是否试过只生成一个app就能AB通用的。我看有的编译器有PIC (position-independent code)选项,似乎 ...
(引用自71楼)

没有试过
如果有这个方法的话希望你能开一个帖子分享一下
会非常有用
页: [1]
查看完整版本: 遇到STM32 A,B区 app升级困难,各路大神,帮忙看一下。