bootloader的作用:升级代码。

.

在单片机的代码升级时,一般需要额外做一个bootloader程序来实现该功能。不管哪种单片机,这里的逻辑是相似的。

正常逻辑:

  1. 芯片上电后,先运行bootloader;
  2. bootloader中检测是否要升级:

如果要升级则执行升级动作(用新的bin覆盖掉旧的bin);

如果不用升级,则跳转到用户程序(开始真正运行用户程序)。

为方便描述,bootloader后续简称boot,用户程序简称为app。

所以,boot程序是额外需要实现的一个应用程序。

可以理解为:

boot也是一个应用程序,只不过相比app稍微特殊点,是专用于升级功能而已。

在下位机上,需要同时装载两个程序:boot和app。

boot开发和app一样,可以使用芯片内的所有资源。调试程序可以在vscode下调试。

.

实际应用中,常见的升级方式有两种:近端升级(二级烧录)和远程升级。

近端升级

是设备和PC有连线情况下的升级方式。

芯片原厂会提供原始烧录工具(称为一级烧录)。但这套工具在串口烧录时,需要操作boot0和boot1引脚,对终端用户来说,利用这种方式升级,操作过程太不友好。

希望的是,用户不用额外操作设备,直接通过串口线插上去就能很方便的升级。

远程升级:

是设备有联网功能,能从服务器下载新固件,然后自己完成升级动作。

这种方式下,不用用户的参与,直接可以服务器端推送来完成升级。

这种场景下,设备连接到服务器,从服务器下载新版本的bin,然后设置好标记位,主动重启设备进入boot,判断到标记后,boot将下载好的新版本的bin覆盖掉本地的bin,从而完成版本的升级。

这两种升级方式,都需要boot的参与。

但这两种升级的boot,要实现的功能是不同的。

.

AG32升级的特点:

1. AG32一套程序需要运行的bin有两个:code.bin和logic.bin;

boot部分需要这样的两个bin,app也需要这样的两个bin;

所以,共需要4个bin:boot_code、boot_logic、app_code、app_logic。

2. 升级,就是用app新的bin替换掉旧的bin;

可以只单独升级app_code或app_logic,

也可以code和logic一起升级;

3. boot和app的这4个bin,都是存储在flash上的;

boot的logic可以选择内置到code,也可以不内置;

app的logic也可以选择内置和不内置;

不管logic是否内置到code里去,这样的bin至少都应该是先制作出来,并最终放进flash。

4. boot+app模式下,芯片上电后的运行逻辑:

A. 芯片上电后,芯片内部rom程序先装载logic.bin到cpld的运行区;

---- 这段rom程序是芯片内部固化的启动程序,不可更改。

---- 这个logic.bin,是在制作batch.bin时指定的logic,样例中,是app_loigc。

B. 跳转到boot的code来运行;

C. boot自己启动后,先重新加载一次自己内置的logic到cpld运行区;

---- 样例中是内置logic方式。这里可以自行修改;

---- 注意:这次加载logic,会覆盖掉步骤A中加载的logic逻辑;

D. 加载完logic后,才真正执行boot的升级代码;

---- 所以,boot的代码真正跑起来,使用的是自己的logic(而不是app_logic);

E. 如果有升级动作,则boot会执行升级逻辑,升级完成后重启;

F. 如果没有升级动作,则跳转到app去运行:

---- 这个跳转动作,分为三步:

---- 1. 先释放掉boot使用的全部资源,并切回内部时钟;

---- 2. 加载app的logic到cpld到运行(该动作会再次覆盖boot的cpld逻辑);

---- 3. 跳转到app入口,开始运行app程序。

5. 关于cpld的运行区:

不管是boot_logic还是app_logic,都是释放到“cpld运行区”运行的。

而整颗芯片只有一个 cpld运行区。

boot的logic 释放过去,芯片运行的就是boot的logic,

app的logic 释放过去,芯片运行的就是app的logic。

如果有两次释放,后释放的,会覆盖掉先释放的。

在上边流程里:

A. 芯片上电后,内置rom程序先释放batch_bin里的logic(其实就是app的logic);

---然后再跳转到boot的程序。

B. 进入boot程序后,boot首先释放自己的logic,覆盖掉app的logic;

---然后再执行boot自己的程序逻辑;

C. boot代码最后跳转到app时,boot会再次释放app的logic,覆盖掉boot的logic;

---然后再程序跳转到app,开始运行app。

.

近端升级的样例逻辑:

1. 设备端有两段程序:boot.bin和app.bin;

  boot放置在0x80000000的位置,(内置boot_logic.bin)

  app放置在约定好的位置0x80008000(外置app_logic.bin);

  (如果不带boot,app会被放置在起始的0x80000000位置)

2. 设备启动后,先进入boot;

  在boot中会等待几秒钟,等待PC的下发消息,

  如果没有等到消息,则跳转到app运行;

  如果有升级命令,则进入boot升级流程;

3. boot升级的过程,就是PC工具和boot交互的过程;

  过程中,boot会一段一段接收bin的数据,并覆盖掉本地的app.bin;

这个过程中,需要:

  1. 事先规划好boot.bin、app.bin的存放位置,并制定好PC和boot的交互协议;
  2. boot中需要实现:支持串口、实现与PC的协议交互、写数据到flash;
  3. PC工具中需要做:实现跟设备端的协议交互;

以上是原理部分。

充分理解原理后,可以针对以上原理开发boot程序。

.

从网盘中可以获取到基于407的近端升级的样例:

链接:https://pan.baidu.com/s/1wcBnqnray7bu4IURDIoDDQ?pwd=1205 里边的\其他文档\bootLoader相关\下边,有全部的文档和例程。其中的boot部分和PC工具,都是源码开放的。客户可以根据自己的实际情况来修改使用。

.

.

拓展:

在调试bootloader时,如果需要联调app,可以在vscode的console控制台里,使用如下命令加载app。加载后,就可以在执行完UTIL_JumpToAddress进入app继续跟踪(先是一段汇编,然后进入app的main)。

命令:add-symbol-file ./example_app_logicUncompress/.pio/build/debug/agm_example.elf

其中 add-symbol-file是加载debug信息,后边跟app编译出来的.elf文件。

正常情况下,跳转后如果app可以正常起来,就不用这么复杂了。【因为app直接就可以在vscode跟踪,没必要通过bootloader这层】

.