参考资料:RT-T官网资料如下链接所示
STM32通用Bootloader (rt-thread.org)
1.app程序env配置过程
参考上述资料中"制作 app 固件"章节,分区大小根据自己设备而定,以下是我以407VET6为例设置的fal分区
https://i-blog.csdnimg.cn/direct/012a61a62a1b476286e8d79e0e16dc32.png" width="562" />
https://i-blog.csdnimg.cn/direct/4f098aff07d440eba44af941a40e3e5a.png" width="899" />
notes:上述分区是由片内flash(on-chip)和外部flash(W25Q64)两部分分区构成,关于外部flash的配置和使用参考文章"RT-T下使用easyflash的配置过程_rtthread easyflash-CSDN博客"
我使用的工程逻辑是先把升级文件通过HTTP下载到外部flash"download"分区中,然后跳转到bootloat里面进行升级;
2.制作bootload bsp工程
在env中进行配置和裁剪功能,主要包括FAL相关配置、on-chip、spi、agile_upgrade相关配置,尽量裁剪到最简:
2.1 关于FAL相关配置、on-chip、spi等相关配置参考文章 RT-T下使用easyflash的配置过程_rtthread easyflash-CSDN博客
2.2 agile_upgrade配置
https://i-blog.csdnimg.cn/direct/78b0e93c30a44cfdb468820262104677.png" width="891" />
https://i-blog.csdnimg.cn/direct/1081ce5c478c41ec8a9040596ef3fd61.png" width="944" />
2.3 修改main函数
下边是部分参考代码
#include "main.h"
#include "fal.h"
#include <agile_upgrade.h>#define DBG_TAG "main"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>//app启动地址
#define BOOT_APP_ADDR 0x08010000extern const struct agile_upgrade_ops agile_upgrade_fal_ops;static uint32_t _written_len = 0;
static uint32_t _total_len = 0;static void step_hook(int step) { LOG_D("step: %d\r\n", step); }static void error_hook(int step, int code) { LOG_E("step: %d, err: %d\r\n", step, code); }static void progress_hook(uint32_t cur_size, uint32_t total_size) {_written_len = cur_size;_total_len = total_size;
}void qbt_jump_to_app(void)
{typedef void (*app_func_t)(void);u32 app_addr = BOOT_APP_ADDR;u32 stk_addr = *((__IO uint32_t *)app_addr);app_func_t app_func = (app_func_t)(*((__IO uint32_t *)(app_addr + 4)));if ((((u32)app_func & 0xff000000) != 0x08000000) || ((stk_addr & 0x2ff00000) != 0x20000000)){LOG_E("No legitimate application.");return;}LOG_I("Jump to application running ... \n");rt_thread_mdelay(200);__disable_irq();for(int i=0; i<128; i++){__NVIC_DisableIRQ((IRQn_Type)i);__NVIC_ClearPendingIRQ((IRQn_Type)i);}SysTick->CTRL = 0;SysTick->LOAD = 0;SysTick->VAL = 0;__set_CONTROL(0);__set_MSP(stk_addr);app_func();//Jump to application runningLOG_E("Qboot jump to application fail.");
}int main(void)
{agile_upgrade_set_step_hook(step_hook);agile_upgrade_set_error_hook(error_hook);agile_upgrade_set_progress_hook(progress_hook);agile_upgrade_t src_agu = {0};src_agu.name = "download";src_agu.user_data = "download";src_agu.ops = &agile_upgrade_fal_ops;agile_upgrade_t dst_agu = {0};dst_agu.name = "app";dst_agu.user_data = "app";dst_agu.ops = &agile_upgrade_fal_ops;agile_upgrade_release(&src_agu, &dst_agu, 1);LOG_D("Written len: %u, total len: %u\r\n", _written_len, _total_len);qbt_jump_to_app();return 0;
}
3.实现http远程升级
参考上述资料中"更多固件下载方式"章节,以下是配置
https://i-blog.csdnimg.cn/direct/1b0f57e43d4f4fc7955451b78c9b609b.png" width="905" />
https://i-blog.csdnimg.cn/direct/af9728dbfe294c2c81aadc16a328470a.png" width="850" />3.1 在控制台执行命令"http_ota http://xxx/xxx/rtthreadf.rbl “,url更换成自己的https://i-blog.csdnimg.cn/direct/355a26085f324a688fbc6d448bef8bab.png" width="1003" />
4.遇到的问题
4.1bootload程序编译报错
原因:link.sct文件中设置的内存大小为64k,但是编译后生成的code代码大小已经68k左右
https://i-blog.csdnimg.cn/direct/b8af07ff306e43ba8d1d1b491349aea9.png" width="720" />
解决:1.设置优化等级;2.对冗余函数的优化
优化后code代码在40k左右
参考资料:关于ARM Keil5 Optimization level 优化等级的一些分析_keil optimization_夜星辰2023的博客-CSDN博客
MDK中One ELF Section per Function选项功能探究_iceiilin的博客-CSDN博客
4.2 bootload程序进入死循环,没有跳转到app分区
原因:
4.2.1 程序中通过万能驱动,spi通讯查找外部flash(W25Q16设备失败);
4.2.2 只在"stm32f4xx_hal_msp.c“中修改spi1相关引脚配置,其他地方可能没有进行配置;
解决:通过STM32CubeMX配置spi1并生成工程
4.3 跳转到app分区后程序不能正常运行
原因:app分区地址设置错误导致修改中断向量表的跳转基地址错误
解决:#define RT_APP_PART_ADDR 0x08010000 0x10000:64k
https://i-blog.csdnimg.cn/direct/2bb3a180dc7a494fa61ec76af8d4c3f3.png" width="973" />
AT32开发板中直接修改中断向量表 改为 0x10000
#define VECT_TAB_OFFSET 0x10000
STM32中通过函数实现:
/*** Function ota_app_vtor_reconfig* Description Set Vector Table base location to the start addr of app(RT_APP_PART_ADDR).
*/
static int ota_app_vtor_reconfig(void)
{#define NVIC_VTOR_MASK 0x3FFFFF80/* Set the Vector Table base location by user application firmware definition */SCB->VTOR = RT_APP_PART_ADDR & NVIC_VTOR_MASK;//此处代码的作用是修改中断向量表的跳转基地址return 0;
}
INIT_BOARD_EXPORT(ota_app_vtor_reconfig);
4.4在控制台通过"http_ota http://xxx/xxx/rtthreadf.rbl “升级失败问题
https://i-blog.csdnimg.cn/direct/6f0aa1dbd25a437f8d1755ea22461e38.png" width="614" />
https://i-blog.csdnimg.cn/direct/dea90b850d674137aa990665e6ba234b.png" width="1200" />
解决:修改webclient.c文件两个地方
4.4.1 添加"rt_thread_mdelay(10);"https://i-blog.csdnimg.cn/direct/067e08cf466f42e1979f2a74a1e8835a.png" width="1164" />
4.4.2 在1160行添加else
https://i-blog.csdnimg.cn/direct/21197a2dd9164b80a0d815ba199feee6.png" width="990" />
4.5 http升级后在bootload中写往"app"分区写程序失败
现象分析:从http服务器上获取后,开始升级,跳转到bootload中后,从"download"分区往"app"分区搬运程序,写入失败,从新用jlink烧录程序卡死到这一步,如下图所示:
https://i-blog.csdnimg.cn/direct/f3a9f2b073674a588a19fa49ba88ad50.png" width="1003" />
原因:雅特力单片机不同型号,FLAH大小不同,扇区大小也不同,如下图所示为flash大小为4032K和1024K大小的扇区大小
https://i-blog.csdnimg.cn/direct/2aa072e5654d4d27a89b6e1a0918d272.png" width="1078" />
https://i-blog.csdnimg.cn/direct/9a6162f3aa81450389cf4ec7f7341297.png" width="1048" />
解决:修改board.h文件中FLASH_PAGE_SIZE大小
https://i-blog.csdnimg.cn/direct/7e464ad7105f4cf3b08b6dec444d6043.png" width="868" />