链接: RT-Thread官网.
RT-Thread Studio 是上海睿赛德电子科技有限公司发布的一款用于RT-Thread 系统的编译器,我目前使用起来感觉还是比较好用的可以编写裸机和RT-Thread 的程序,建议大家可以尝试一下。
RT-Thread 通用BootLoader 是由RT-Thread 提供的可以无需代码编写直接配置的BootLoader程序。
链接: RT-Thread官网通用BootLoader说明资料.
在其官网资料也有对配置方式的说明,可能有一些人刚刚接触BootLoader,会看了一遍仍旧不太懂的人,我下面会更加详细的从头一步一步的来讲解如何使用 RT-Thread 通用BootLoader。
建议大家看本文之前可以先看一下官网资料,再来看本文可以加深理解。本文编写以STM32F413VGTX为例进行讲解。
软件:xshell软件(可以直接去官网申请免费教育版),RT-thread studio 软件 ,keil MDK 软件,rt_ota_打包器
我们可以把制作通用BootLoader分为以下几步:
OTA 升级其实就是 IAP 在线编程。在嵌入式设备 OTA 中,通常通过串口或者网络等
方式,将升级数据包下载到 Flash,然后将下载得到的数据包搬运到 MCU 的代码执行区域
进行覆盖,以完成设备固件升级更新的功能。
嵌入式设备的 OTA 升级一般是不基于文件系统的,而是通过对 Flash 划分为不同的功
能区域来完成 OTA 升级功能。
在嵌入式系统方案里,要完成一次 OTA 固件远端升级,通常需要以下三个核心阶段:
- 上传新固件到 OTA 服务器
- 设备端下载新的 OTA 固件
- bootloader 对 OTA 固件进行校验、解密和搬运(搬运到可执行程序区域)
流程图,摘自《RT-Thread-OTA 用户手册》 链接: Rt-thead OTA资料gitee地址.
这个流程图有兴趣可以研究一下。
rt_ota 是 RT-Thread 开发的跨 OS、跨芯片平台的固件空中升级技术(FirmwareOver-the-Air Technology),轻松实现对设备端固件的管理、升级与维护。
RT-Thread 提供的 OTA 固件升级技术具有以下优势:
• 固件防篡改:自动检测固件签名,保证固件安全可靠
• 固件加密:支持 AES-256 加密算法,提高固件下载、存储安全性
• 固件压缩:高效压缩算法,降低固件大小,减少 Flash 空间占用,节省传输流量,降低下载时间
• 差分升级:根据版本差异生成差分包,进一步节省 Flash 空间,节省传输流量,加快升级速度
• 断电保护:断电后保护,重启后继续升级
• 智能还原:固件损坏时,自动还原至出厂固件,提升可靠性
• 高度可移植:可跨 OS、跨芯片平台、跨 Flash 型号使用,不依赖具体的 OTA 服务器
进入通用BootLoader配置网站:链接: 通用BootLoader配置网站. 注册并新建一个产品。
点击生成BootLoader,进入BootLoader编辑界面,第一个界面如下:
名称 | 说明 |
---|---|
1 | 选择芯片系列,我们使用的是STM32F413芯片 |
1-1 | 表示ROM大小,一般都是用内部FLASH,则为内部FLASH大小 |
1-2 | 表示RAM大小,根据芯片对应值添加即可 |
3 | 支持SPI Flash ,表示使用外部SPI Flash ,我们不计划使用外部FLash 因此不要勾选 |
4 | 恢复出厂引脚,按下此引脚保持10s ,BootLoader会将备份的出厂程序,恢复到APP分区。 |
说明:由于我们使用的是串口升级方式,因此填写串口输出引脚即可
这里只填写串口输出口的原因是:
我们采用串口接收的逻辑程序并不在BootLoader内,而是在APP程序内,因此这里只是填写串口输出端口,用于输出打印的信息,除此外没有别的作用
名称 | 说明 |
---|---|
1 | 这个分区配置比较容易出错,根据红色字体描述,片内FLash起始地址是0x8000000,F4芯片BootLoader默认占用前128K字节,因此APP分区的起始偏移地址为0x20000(128K) |
2 | 这个表示APP分区的大小为512K |
3. | 这个表示download分区的起始偏移地址,0xA0000(128K+512K) |
4. | 这个表示download分区大小为384k |
说明: 根据以上分区设置,下面罗列出分区的表格
分区名称 | 起始地址 | 占用大小 |
---|---|---|
BootLoader分区 | 0x8000000 | 128K |
APP分区 | 0x8020000 | 512K |
download分区 | 0x80A0000 | 384K |
这样分区配置完成了
名称 | 说明 |
---|---|
固件加密 | 这个是对APP升级文件的加密 |
固件压缩 | 这个是对APP升级文件的压缩 |
更换Log | 可以填写自己的log或者采用默认rt-thread的log |
输入邮箱 | 填写自己的邮箱,点击生成BootLoader后,系统会把生成的BootLoader发到这个邮箱 |
下图是三种压缩方式的压缩比例,其中没有gzip,我试了gzip压缩率在40%左右
根据以上的操作,目前通用BootLoader程序已经制作好了,下面我们使用JFLASH将BootLoader的bin文件烧录到芯片中,并监控打印的信息,以下为打印信息截图。
以下为详细文本信息
/*********USART2-TX-PD5**********/
/*******************************/
Powered by RT-Thread.
V0.9.2 build Apr 18 2020
[D/FAL] (fal_flash_init:63) Flash device | onchip_flash_16k_part | addr: 0x08000000 | len: 0x00020000 | blk_size: 0x00004000 |initialized finish.
[D/FAL] (fal_flash_init:63) Flash device | onchip_flash | addr: 0x08020000 | len: 0x000e0000 | blk_size: 0x00020000 |initialized finish.
[I/FAL] ==================== FAL partition table ====================
[I/FAL] | name | flash_dev | offset | length |
[I/FAL] -------------------------------------------------------------
[I/FAL] | app | onchip_flash | 0x00000000 | 0x00080000 |
[I/FAL] | download | onchip_flash | 0x00080000 | 0x00060000 |
[I/FAL] =============================================================
[I/FAL] RT-Thread Flash Abstraction Layer (V0.4.0) initialize success.
[I/FAL] System initialization successful.
[I]RT-Thread OTA package(V0.2.1) initialize success.
[E]Get firmware header occur CRC32(calc.crc: 7b93c5c8 != hdr.info_crc32: ffffffff) error on 'download' partition!
[E]Get OTA download partition firmware header failed!
[E]Get firmware header occur CRC32(calc.crc: 7b93c5c8 != hdr.info_crc32: ffffffff) error on 'app' partition!
[I]Begin to execute the program on app partition.
[E/FAL] Can't find user firmware on app partition. (Address: 0x08020000, Data: 0x4404fb31)
[E/FAL] Bootloader stop.
下面我们对打印的内容进行分析:
第一部分
内容(内容次序从左到右,从上到下) | 分析 |
---|---|
Powered by RT-Thread. | 这句话之前的为打印的log文本信息 |
fal_flash_init:63 | 表示fal组件初始化,63表示驱动的id |
onchip_flash_16k_part | 表示当前的flash驱动在 16k Flash 块上 |
addr: 0x08000000 | 表示当前FLASH驱动的起始地址 |
len: 0x00020000 | 表示当前FLASH驱动的长度 |
blk_size: 0x00004000 | 表示当前FLASH驱动的FLASH块的大小 |
onchip_flash | 表示在芯片128K FALSH 块上 |
addr: 0x08020000 | 表示当前FLASH驱动的起始地址 |
len: 0x000e0000 | 表示当前FLASH驱动的长度 |
blk_size: 0x00020000 | 表示当前FLASH驱动的FLASH块的大小 |
第二部分 FAL partition table
name | flash_dev | offset (以0x8000000为偏差起始地址) | length |
---|---|---|---|
app (分区名称) | onchip_flash (表示当前FLASH驱动为 onchip_flash ) | 0x00000000 | 0x00080000 |
download(分区名称) | onchip_flash (表示当前FLASH驱动为 onchip_flash ) | 0x00080000 | 0x00060000 |
这个分区名称很重要,以后使用打包工具的分区名称填写要与这个名称一致
第三部分:
检查download分区的校验码,如果一致则说明可以进行固件搬运,不一致则直接跳转到APP分区的起始地址运行程序。
以上是打印信息的基本分析,关键要确认app和download分区与设置的否是一致。
说明:
APP程序的编写,我是采用rt-thread studio 进行编写,直接生成程序和添加删除组件非常方便。下面我们开始进行程序编写。
打开rt-thread studio 选择新建程序,并选择对应的型号的系统版本如下图:
特别注意:串口的发送和接收管脚要对应正确
FAL组件是分区配置组件,rt系统的在线升级功能是基于这个组件的,因此FAL组件配置很关键。
点击软件包添加,搜索 FAL组件 ,然后添加FAL组件。然后保存并编译。此时在packages文件夹下会有一个名为 fal-v0.4.0的文件夹,这个是fla组件的文件。
此时编译是会报错的
提示缺少fal_cfg.h这个文件,这是因为默认的fal组件没有提供这个文件,我们可以自己在samples/porting 文件夹 下找到一个fal_cfg.h文件,将此文件复制到fal-v0.4.0/inc 文件夹下,
之后将,复制的文件内容修改为以下内容
#ifndef _FAL_CFG_H_
#define _FAL_CFG_H_
#include
#include
//flash 块 大小宏定义
#define FLASH_SIZE_GRANULARITY_16K (4*16*1024)
#define FLASH_SIZE_GRANULARITY_64K (64*1024)
#define FLASH_SIZE_GRANULARITY_128K (7*128*1024)
//flash 块 块起始地址 宏定义
#define STM32_FLASH_START_ADRESS_16K STM32_FLASH_START_ADRESS
#define STM32_FLASH_START_ADRESS_64K (STM32_FLASH_START_ADRESS+FLASH_SIZE_GRANULARITY_16K)
#define STM32_FLASH_START_ADRESS_128K (STM32_FLASH_START_ADRESS_64K+FLASH_SIZE_GRANULARITY_64K)
//外部 fal flash 驱动 声明
extern const struct fal_flash_dev stm32_onchip_flash_16k ;
extern const struct fal_flash_dev stm32_onchip_flash_64k ;
extern const struct fal_flash_dev stm32_onchip_flash_128k ;
/* flash device table */
#define FAL_FLASH_DEV_TABLE \
{ \
&stm32_onchip_flash_16k, \
&stm32_onchip_flash_64k, \
&stm32_onchip_flash_128k, \
}
/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table */
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WORD, "app", "onchip_flash_128k", 0*1024, 512*1024, 0}, \
{FAL_PART_MAGIC_WORD, "download", "onchip_flash_128k", 512*1024, 384*1024, 0}, \
}
#endif /* FAL_PART_HAS_TABLE_CFG */
#endif /* _FAL_CFG_H_ */
关键在于 FAL_PART_TABLE 的内容修改。关键点为:
分区名 | 分区位置 | 分区在flash块的起始地址 | 分区长度 |
---|---|---|---|
“app” | “onchip_flash_128k” | 0*1024 | 512*1024 |
“download” | “onchip_flash_128k” | 512*1024 | 384*1024 |
注意这个起始地址是 分区在flash块的起始地址,并不是相对于 整个芯片FLASH 0x8000000 的起始地址。
因此这个APP的分区起始地址就是0*1024,长度是512K,下面的download分区也是一样
然后将fal_init()函数添加到main函数初始化里面
按照以上步骤配置好了以后可以进行编译,此时不会再报错。
下图是修改程序下载起始地址:按照0x20000(BootLoader占用大小)的大小偏移的地址是APP程序的起始地址
下图是修改中断向量映射地址的:同样按照0x20000大小进行偏移
接上串口监控后,上电可以看到串口的信息输出:
串口信息:
//前面的为 BootLoader输出信息,不再重复贴出来
\ | /
- RT - Thread Operating System
/ | \ 4.0.2 build Apr 17 2020
2006 - 2019 Copyright by rt-thread team
[D/FAL] (fal_flash_init:63) Flash device | onchip_flash_16k | addr: 0x08000000 | len: 0x00010000 | blk_size: 0x00004000 |initialized finish.
[D/FAL] (fal_flash_init:63) Flash device | onchip_flash_64k | addr: 0x08010000 | len: 0x00010000 | blk_size: 0x00010000 |initialized finish.
[D/FAL] (fal_flash_init:63) Flash device | onchip_flash_128k | addr: 0x08020000 | len: 0x000e0000 | blk_size: 0x00020000 |initialized finish.
[I/FAL] ==================== FAL partition table ====================
[I/FAL] | name | flash_dev | offset | length |
[I/FAL] -------------------------------------------------------------
[I/FAL] | app | onchip_flash_128k | 0x00000000 | 0x00080000 |
[I/FAL] | download | onchip_flash_128k | 0x00080000 | 0x00060000 |
[I/FAL] =============================================================
[I/FAL] RT-Thread Flash Abstraction Layer (V0.4.0) initialize success.
[D/main] Hello RT-Thread! Version 1.1.1
msh >
请注意 FAL partition table 下面的分区信息一定与BootLoader的FAL partition table 输出信息保持一致。
此时FAL组件相关的内容就添加和修改完毕了,下面开始添加
ota_downloader和YModem组件
添加ota_downloader 如下图:
添加YModem组件
添加完成后,编译,并烧录程序,进入finsh控制台,按下tab按键,就可以看到下图:
查看ymodem_ota函数
此时还不能传输升级文件,因为我们在设置通用BootLoader的时候,把APP文件设置为压缩文件,必须要传输压缩好的文件过去,此时要使用RT-thread 自己的打包工具,下载地址:链接: OTA打包工具地址.
关键点:
此时打开xshell的串口监控界面,在显示界面右键点击,选择传输,选择YMODEM发送,选择打包好的文件,发送,可以看到传输界面
下图是传输完成后的界面,
以上就是通用本文的所有内容,我是采用串口升级的方式,通用BootLoader有很多优势,在前面开头已经讲过了,但是对于某些程序自身占用flash比较大的情况就很难来满足应用需求了,因此有的时候使用自己编写的BootLoader的也是必须的。例如:APP的bin文件大小超过了5125K,甚至更多,这个时候就不能使用通用BootLoader来升级了,接下来我会总结下,使用RT-thread来自己编写BootLoader的内容,来跟大家分享。