一、Bootloader
1、Bootloader生成
官方网站:http://iot.rt-thread.com 官方文档:https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/application-note/system/rtboot/an0028-rtboot |
新建产品->固件升级->生成Bootloader: |
将会生成bin固件发送到邮箱并下载: |
2、Bootloader烧录
配置工程、Target->Production Programming(JLINK方式): 由于此时app分区还没有对应的app程序,所以会卡住: |
二、Application
1、链接文件修改
修改程序链接脚本中ROM的起始地址和大小: |
2、中断向量表地址偏移
由于App分区的起始地址为0x08020000(根据实际情况),需要修改链接脚本和中断向量的跳转地址; 注意:rt-thread/src/components.c->rtthread_startup为初始化函数,初始化完毕进入main。 |
修改中断向量表位置(board.c): RT_WEAK void rt_hw_board_init() { // 中断向量表偏移 SCB->VTOR = ((uint32_t)0x8020000); ... ... |
3、添加固件版本信息
在 main 函数中添加版本信息(用于区别APP分区): #define APP_VERSION "1.0.0" int main(void) { rt_kprintf("/* ---------Application--------- */\n"); rt_kprintf("The current version of APP firmware is %s\n", APP_VERSION); ... ... |
4、FLASH及分区配置
SFUD(全称 Serial Flash Universal Driver)是一款开源的串行 SPI Flash 通用驱动库; FAL:Flash 抽象层。 使能组件: 修改board.h: #define BSP_USING_ON_CHIP_FLASH #define BSP_USING_SPI2 添加fal_config: |
// 修改fal_cfg.h: /******************************************* * File: fal_cfg.h * Describe: FAL_FLASH分区表 * Author: Xiangfu DING * Time: 2025-02-10 *******************************************/ #ifndef _FAL_CFG_H_ #define _FAL_CFG_H_ #include <rtconfig.h> #include <board.h> #ifndef FAL_USING_NOR_FLASH_DEV_NAME #define NOR_FLASH_DEV_NAME "norflash0" #else #define NOR_FLASH_DEV_NAME FAL_USING_NOR_FLASH_DEV_NAME #endif // STM32F407VGT6 - 内部 Flash 大小为 1024KB(分为 4 个 16KB 扇区、1 个 64KB 扇区、7 个 128KB 扇区) #define FLASH_SIZE_GRANULARITY_16K (4 * 16 * 1024) #define FLASH_SIZE_GRANULARITY_64K (64 * 1024) #define FLASH_SIZE_GRANULARITY_128K (7 * 128 * 1024) #define STM32_FLASH_START_ADRESS_16K STM32_FLASH_START_ADRESS #define STM32_FLASH_START_ADRESS_64K (STM32_FLASH_START_ADRESS_16K + FLASH_SIZE_GRANULARITY_16K) #define STM32_FLASH_START_ADRESS_128K (STM32_FLASH_START_ADRESS_64K + FLASH_SIZE_GRANULARITY_64K) /* ===================== Flash device Configuration ========================= */ 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 Configuration ========================= */ extern struct fal_flash_dev nor_flash0; /* flash device table */ #define FAL_FLASH_DEV_TABLE \ { \ &stm32_onchip_flash_16k, \ &stm32_onchip_flash_64k, \ &stm32_onchip_flash_128k, \ &nor_flash0, \ } /* ====================== Partition Configuration ========================== */ #ifdef FAL_PART_HAS_TABLE_CFG /* partition table */ #define FAL_PART_TABLE \ { \ {FAL_PART_MAGIC_WROD, "app", "onchip_flash", 0 * 1024, 512 * 1024, 0}, \ {FAL_PART_MAGIC_WROD, "download", NOR_FLASH_DEV_NAME, 0 * 1024, 512 * 1024, 0}, \ } #endif /* FAL_PART_HAS_TABLE_CFG */ #endif /* _FAL_CFG_H_ */ |
// 初始化 #include "fal.h" int main(void) { // 初始化W25Q64 rt_hw_spi_device_attach("spi2", "spi20", GPIOB, GPIO_PIN_12); //flash名称要正确 if (RT_NULL == rt_sfud_flash_probe("W25Q64", "spi20")) { rt_kprintf("rt_sfud_flash_probe failed!\n"); } // 初始化FAL fal_init(); ... ... |
5、执行OTA升级
- 制作固件包
https://codeload.github.com/RT-Thread-packages/ota_downloader/zip/refs/tags/1.0.0 打开资源所在目录: 打包固件: 注意:OTA只会增量升级,固件版本必须大于当前app分区版本号才可以触发。 |
- SD卡升级
/******************************************* * File: sdota.c * Describe: SD卡固件升级 * Author: Xiangfu DING * Time: 2025-02-07 *******************************************/ #include "sdota.h" #include "core.h" #include <rtdevice.h> #include <drv_common.h> #include <rtdbg.h> #include <finsh.h> #include <fal.h> #include <dfs_fs.h> static void print_progress(size_t cur_size, size_t total_size) { uint8_t progress = cur_size * 100 / total_size; if (progress > 100) { progress = 100; } rt_kprintf("Download progress: %d%\n", progress); } int sdOtaDownload(const char* uri) { const struct fal_partition *dl_part = RT_NULL; int begin_offset = 0; int file_size = 0; int fd; struct stat fileStat; uint8_t buffer[1024]; int ret = RT_EOK; rt_kprintf("sdOtaDownload uri: %s\n", uri); // 打开并检查固件是否存在 fd = open(uri, O_RDONLY); if (fd < 0) { rt_kprintf("Firmware does not exist!\n"); goto __exit; } // 获取固件大小 if (stat(uri, &fileStat) == 0) { file_size = fileStat.st_size; rt_kprintf("Firmware size: %d\n", file_size); } else { rt_kprintf("Failed to get file size for %s\n", uri); goto __exit; } // 获取下载分区信息并擦除下载分区数据 if ((dl_part = fal_partition_find("download")) == RT_NULL) { rt_kprintf("Firmware download failed! Partition (%s) find error!\n", "download"); ret = -RT_ERROR; goto __exit; } // 擦除Download分区 rt_kprintf("Start erase flash (%s) partition!\n", dl_part->name); if (fal_partition_erase(dl_part, 0, file_size) < 0) { rt_kprintf("Firmware download failed! Partition (%s) erase error!\n", dl_part->name); ret = -RT_ERROR; goto __exit; } rt_kprintf("Erase flash (%s) partition success!\n", dl_part->name); // 拷贝固件到Download分区 while (begin_offset < file_size) { // 读取文件到缓冲区 int length = read(fd, buffer, sizeof(buffer)); if (length < 0) { rt_kprintf("Read file error!\n"); ret = -RT_ERROR; goto __exit; } // 写入闪存分区 if (fal_partition_write(dl_part, begin_offset, buffer, length) < 0) { rt_kprintf("Firmware download failed! Partition (%s) write data error!\n", dl_part->name); ret = -RT_ERROR; goto __exit; } // 更新下载的偏移量 begin_offset += length; // 打印下载进度 print_progress(begin_offset, file_size); } // 重启升级固件 if (ret == RT_EOK) { rt_kprintf("Download firmware to flash success.\n"); rt_kprintf("System now will restart...\n"); rt_thread_delay(rt_tick_from_millisecond(5)); // Reset the device, Start new firmware extern void rt_hw_cpu_reset(void); rt_hw_cpu_reset(); } else { rt_kprintf("Download firmware failed!\n"); } __exit: close(fd); return ret; } void sdota(int argc, char **argv) { sdOtaDownload(FIRMWARE_PATH); } MSH_CMD_EXPORT(sdota, "The sd card firmware is upgraded"); |
- HTTP升级
该软件包会自动勾选webclient软件包: |
HTTP升级源码位置: 使用示例: http_ota http://192.168.0.108:8080/download/rtthread.rbl |