当前位置:   article > 正文

rtthread通过SFUD、FAL、RT--YMODEM-OTA实现在线升级IAP_rtthread stm32使用w25q16做ota

rtthread stm32使用w25q16做ota

平台:STM32F103ZET6
开发工具:STM32CUBEMX / RTTHREAD STUDIO / xshell 6
RT-OTA目前只支持STM32:F1 F4 L4 三个系列   且不开源
功能可以,希望能支持到STM32H7 AT32F4 GD32F3这些

层级从低到高是:W25Q16+内部flash -> SFUD -> FAL

IAP大致思路:在APP里烧写固件到SPI flash,然后软件reboot,bootloader去读SPI flash里的代码,覆盖APP区域,然后跳转到APP地址执行

尚未完善:划分一个备份区域,存放出厂代码。(考虑到自己的设计很难实现按键外露,加上RTT没开源OTA代码,就暂时没搞)


正文开始:

移植SFUD主要是为了简单读取W25QXX

新建RTT工程

打开cubemx 设置,在里面配置时钟 uart spi等外设 (如果只需要串口1,做调试的,那就不需要配置,RTT会自动配置好)

先保存cubemx再点生成代码,才会出现SConscript脚本,会减少匹配过程(如果直接生成代码,不会出现这个脚本文件)生成完成后点close,别点打开工程

编译一下,看会不会报错。

然后找到SPI的初始化文件,将以下SPI.C的硬件设置代码复制到board.c

  1. void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
  2. {
  3. GPIO_InitTypeDef GPIO_InitStruct = {0};
  4. if(spiHandle->Instance==SPI2)
  5. {
  6. /* USER CODE BEGIN SPI2_MspInit 0 */
  7. /* USER CODE END SPI2_MspInit 0 */
  8. /* SPI2 clock enable */
  9. __HAL_RCC_SPI2_CLK_ENABLE();
  10. __HAL_RCC_GPIOB_CLK_ENABLE();
  11. /**SPI2 GPIO Configuration
  12. PB13 ------> SPI2_SCK
  13. PB14 ------> SPI2_MISO
  14. PB15 ------> SPI2_MOSI
  15. */
  16. GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_15;
  17. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  18. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  19. HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  20. GPIO_InitStruct.Pin = GPIO_PIN_14;
  21. GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  22. GPIO_InitStruct.Pull = GPIO_NOPULL;
  23. HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  24. /* USER CODE BEGIN SPI2_MspInit 1 */
  25. /* USER CODE END SPI2_MspInit 1 */
  26. }
  27. }

然后打开board.h

去掉两个注释

 

然后点开rtt settings 添加软件包,spi libc sfud 

然后新建一个spi_flash.c文件加入SPI 和SFUD初始化代码和测试代码

  1. #include <board.h>
  2. #include <drv_common.h>
  3. #include <rtthread.h>
  4. static int rt_hw_spi_flash_init(void)
  5. {
  6. __HAL_RCC_GPIOB_CLK_ENABLE();
  7. rt_hw_spi_device_attach("spi2", "spi20", GPIOB, GPIO_PIN_12); //对应CS脚
  8. //SFUD会去匹配表上支持的器件,然后读到各项参数,包括器件容量,扇区数等
  9. if (RT_NULL == rt_sfud_flash_probe("W25Q16", "spi20")) //这里注意容量标识 可以去看看SFUD支持的器件表
  10. {
  11. return -RT_ERROR;
  12. };
  13. return RT_EOK;
  14. }
  15. /* 导出到自动初始化 */
  16. INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);
  17. #define W25Q_SPI_DEVICE_NAME "spi20" //SPI20代表 SPI20个器件
  18. static void spi_w25q_sample(int argc, char *argv[]) //读W25Q的ID 打印
  19. {
  20. struct rt_spi_device *spi_dev_w25q;
  21. char name[RT_NAME_MAX];
  22. rt_uint8_t w25x_read_id = 0x90;
  23. rt_uint8_t id[5] = {0};
  24. if (argc == 2)
  25. {
  26. rt_strncpy(name, argv[1], RT_NAME_MAX);
  27. }
  28. else
  29. {
  30. rt_strncpy(name, W25Q_SPI_DEVICE_NAME, RT_NAME_MAX);
  31. }
  32. /* 查找 spi 设备获取设备句柄 */
  33. spi_dev_w25q = (struct rt_spi_device *)rt_device_find(name);
  34. if (!spi_dev_w25q)
  35. {
  36. rt_kprintf("spi sample run failed! can't find %s device!\n", name);
  37. }
  38. else
  39. {
  40. /* 方式1:使用 rt_spi_send_then_recv()发送命令读取ID */
  41. rt_spi_send_then_recv(spi_dev_w25q, &w25x_read_id, 1, id, 5);
  42. rt_kprintf("use rt_spi_send_then_recv() read w25q ID is:%x%x\n", id[3], id[4]);
  43. }
  44. }
  45. /* 导出到 msh 命令列表中 */
  46. MSH_CMD_EXPORT(spi_w25q_sample, spi w25q sample);
  47. #include "spi_flash.h"
  48. #include "./sfud/inc/sfud.h"
  49. static void spi_w25q_sf_sample(int argc, char *argv[]) //通过SFUD来测试W25Q的读写
  50. {
  51. uint8_t *read_data; // 读取到的数据
  52. uint8_t *write_data; // 将要写入的数据
  53. sfud_flash *sfud_dev = NULL;
  54. sfud_err ret;
  55. sfud_dev = rt_sfud_flash_find("spi20"); // 获取 sfud_dev
  56. // 或者 sfud_dev = rt_sfud_flash_find_by_dev_name("W25Q16");
  57. write_data = rt_malloc(32);
  58. rt_memset(write_data, '1', 32);
  59. ret = sfud_erase_write(sfud_dev, 0, 32, write_data); // 将数据 32 字节的 write_data0 开始写入 flash
  60. if(ret == SFUD_SUCCESS)
  61. {
  62. rt_kprintf("sfud write data at 0 is:%s\n", write_data);
  63. }
  64. else
  65. {
  66. rt_kprintf("sfud write data failed\n");
  67. }
  68. read_data = rt_malloc(32);
  69. ret = sfud_read(sfud_dev, 0, 32, read_data); // 读取从 0 开始的 32 字节,存入 read_data
  70. if(ret == SFUD_SUCCESS)
  71. {
  72. rt_kprintf("sfud read data at 0 is:%s\n", read_data);
  73. }
  74. else
  75. {
  76. rt_kprintf("sfud read data failed\n");
  77. }
  78. }
  79. /* 导出到 msh 命令列表中 */
  80. MSH_CMD_EXPORT(spi_w25q_sf_sample, spi w25q sf sample);

编译 程序,下载,记得download选项里选择系统复位,然后看一下设备列表

看到flash和spi20都挂好了

开始测试SFUD读写

外部flash测试完成

添加FAL软件包

这里要选对应外部flash设备名字 

 

复制fal_cfg.h,避免报错

编译工程提示未定义

这个是FAL软件包里demo的问题,这里需要将内部flash挂载的设备名字和FAL包里调用的内部flash设备名字对上

打开drv_flash_f1.c文件(要确定board.h里去掉了内部flash的注释,在最后,拉到底即可)

找到如下信息

const struct fal_flash_dev stm32_onchip_flash = { "onchip_flash", STM32_FLASH_START_ADRESS, STM32_FLASH_SIZE, FLASH_PAGE_SIZE, {NULL, fal_flash_read, fal_flash_write, fal_flash_erase} };

onchip_flash这个就是RTT对内部flash注册的设备名,stm32_onchip_flash是设备信息的结构体,这俩都有用

然后修改fal_cfg.h文件

修改spi_flash_sfud.c 主要是修改总容量 扇区长度 这里我用的是W25Q16  2MBIT 扇区4096bit

在main.c里添加FAL初始化函数和头文件,再添加一个跳转函数,对应APP的地址和中断向量表地址

编译,烧写

注意这里外部FLASH分区名字,后面OTA部分会用到->W25Q16

添加OTA软件包

修改APP程序烧写位置,此处要对应上前面FAL分区里app起始地址,容量大小到不是很重要,因为没用满,严谨算一下也可以。

main.c里加入跳转 里面APP地址要对应link里的APP地址

  1. static int ota_app_vtor_reconfig(void)
  2. {
  3. #define NVIC_VTOR_MASK 0x3FFFFF80
  4. #define RT_APP_PART_ADDR 0x08020000
  5. /* Set the Vector Table base location by user application firmware definition */
  6. SCB->VTOR = RT_APP_PART_ADDR & NVIC_VTOR_MASK;
  7. return 0;
  8. }
  9. INIT_BOARD_EXPORT(ota_app_vtor_reconfig);

然后去RTT网站生成OTA-BOOT代码

iot_admin (rt-thread.com)

配置如下,这里要对应上fal里的app区域和download区域,片外FLASH要引脚匹配(看看CUBEMAX)

然后点击生成bootload.bin,烧写进去看看BL的分区是否正常,烧写前点了个全片擦除,为了验证BL是否正常

然后再烧写APP,这次是通过RTT studio来下载的,串口打印如下,BL跳转正常

然后修改APP里打印的版本号,将该APP的BIN文件使用RTT-OTA打包工具,位置在工程目录下packages OTA/tools 大概位置,打包生成LDR文件,此处加密不加密都可以,要对应网页配置选项

打包完成,再次进入Xshell 6软件,在msh命令行输入ymodem_ota,进入传输等待过程。

在Xshell6 的文件→传输→ymodem发送→找到生成的ldr文件

等待传输完成,代码自动重启,然后查看版本号,版本号变化,确认成功升级

如果出现ymodem传输不正常,需要注意:时钟一定要用外部时钟

APP+BOOT代码已上传CSDN,有需要请下载

看完觉得有用,请点赞。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/779910
推荐阅读
相关标签
  

闽ICP备14008679号