0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

一种有趣的 OTA 升级思路(基于 LoRa 通信的 OTA 固件升级的调试记录)

RTThread物联网操作系统 来源:未知 2023-08-09 19:25 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

1 概述


采用 LoRa 技术进行无线通讯,考虑到产品的实际需求,增加了产品的 OTA 固件升级的功能。因为 LoRa 通讯速度较慢,合理的减小 APP 区域固件的大小加快固件升级的速度变的尤为重要,于是就开启了优化调整 APP 区域固件大小之旅。

代码中使用到了 STM32_Cryptographic_Library、STM32_Std_Library 和 LoRa 驱动库,这些库编译之后的体积较大,猜想能不能将所有的这些库文件放在 Bootload 进行固化,然后封装好接口供 APP 调用,顺着这个思路开启了优化之路。

2 调试之路

2.1 想法

常见的固件升级是将片内 Flash 分为 Bootload 区域和 APP 区域(如下图所示),由 APP 区域接收新固件存储在片内或者片外 Flash,然后置升级的标志位并跳转到 Bootload,在 Bootload 完成新固件的更新工作。这样实现比较常规,但是由于 APP 中包含了多种库导致目标文件比较大,LoRa 通讯速率又不高会使整个升级时间很长。

7e2f60e4-36a5-11ee-9e74-dac502259ad0.png

为了减小 APP 的大小,考虑将使用到库文件都固化在 Bootload 内,将片内 Flash 分为三个区域(如下图所示),增加一个共有函数区域,用于存放 Bootload 中封装好的接口。在函数调用时,如果 APP 调用的是共有函数,那么首先去共有函数区域找到函数在 Flash 中的地址,然后到 Bootload 中的对应位置执行相应的代码,再讲执行结果返回给 APP 区域,整个调用过程如下所示。

7e49896a-36a5-11ee-9e74-dac502259ad0.png

2.2 函数和变量定义在绝对地址的实现

有了上面的想法,首先需要验证的是如何将函数和变量放置在 Flash 的固定位置处,这样每次在调用固定位置处的接口就能找到 Bootload 中固化的代码接口。查阅相关资料,了解到 IAR 中的具体实现如下:

2.2.1 IAR的扩展关键字

  @ 用于函数变量的绝对地址定位,将函数变量等放到指定的 section

  __no_init禁止系统启动时初始化变量

  __root 保证没有使用的函数或者变量也能够包含在目标代码中

2.2.2 函数的绝对定位

要将函数定义在绝对位置,需要在函数定义时后面加上

1voidfun1(inta,intb)@".MY_SECTION"
2{
3...//函数内容
4}

然后在链接文件 .icf 中添加如下内容。其中 0x08010000 表示在 Flash 中的地址,.MY_SECTION 必须与函数 @ 后面双引号中内容一致

1placeataddressmem:0x08010000{readonlysection.MY_SECTION};

2.2.3 变量的绝对定位

示例如下,变量绝对定位,无须修改 .icf 链接文件,直接指定具体位置即可。

1__no_initchararray1[100]@0x2000B000;

2.2.4 常量的绝对定位

常量的绝对定位示例如下:

1__rootconstintstr1[4]@".MYSEG"={1,2,3,4};

常量绝对定位,需要改.icf文件,示例如下:

1placeataddressmem:0x08018500{readonlysection.MYSEG};

2.2.4 .c文件的绝对定位

要将 test.c 文件定位到 Flash 的绝对地址,那么在 .icf文件中应该按照如下格式添加:

1placeataddressmem:0x08018000{section.textobjecttest.o};

编译完成后整个 test.c 文件的所有函数,都在 0x08018000 之后。

2.3 Bootload 共有函数的实现

考虑到在初期编写代码时共有函数是可能发生变化的,如果按照上述的方法一个一个将函数放在固定的位置不是很方便,因此采用数组的方式将所有的共有函数放置在一起,如下所示:

1__rootconstuint32_tfunc_table[]@".COMMON_FUNC_SEG"={
2
3(uint32_t)&fun1,/**00*/
4
5(uint32_t)&fun2,/**01*/
6
7(uint32_t)&fun3,/**02*/
8
9}

按照上面数组的方式将所有共有函数集合在一起,然后再 .icf 链接文件中将该数组放置在固定位置处,这样在 0x08010000 位置处依次就能找到定义的所有共有函数(每个成员是函数对象的地址,占 4 个字节)。

1/**将数组放置在固定位置*/
2
3placeataddressmem:0x08010000{readonlysection.COMMON_FUNC_SEG};

2.4 APP 共有函数的使用

按照上述的方法可以将所有的库函数封装好并固化在 Bootload 中,并且实现了将所有的共有函数接口放置在固定的位置,在 APP 区可以使用函数指针的方式进行访问,示例如下:

 1/**1.声明*/
 2
 3typedefint(*app_fun1)(inta,intb);
 4
 5typedefvoid(*app_fun2)(void);
 6
 7typedefchar*(*app_fun3)(char*p);
 8
 9/**2.定义函数指针类型的变量*/
10
11app_fun1fun1;
12
13app_fun2fun2;
14
15app_fun1fun3;
16
17/**3.共有函数的重定义*/
18
19#defineFUNC_TABLE_ADDR(0x08010000)/**共有函数的首地址*/
20
21voidredefine_common_function(void)
22
23{
24
25uint32_t*func_table_addr=(uint32_t*)FUNC_TABLE_ADDR;
26
27fun1=(app_fun1)func_table_addr[0];/*00*/
28
29fun2=(app_fun2)func_table_addr[1];/*01*/
30
31fun3=(app_fun3)func_table_addr[2];/*02*/
32
33}

通过上面的方式就能在 APP 区域调用 Bootload 中固化的接口了,不过要注意这种方式调试起来不是很方便,需要前期验证好 Bootload 中封装的接口有没有问题。

3 注意事项


按照上述的方法操作时有一些注意事项如下:

1. 固件更新区的绝对定位的函数,不能随意调用其他库函数,那些被调用的函数也必须是绝对定位的。

2. 绝对定位的函数,如果要使用常量,那么被使用的常量也必须是绝对定位的。

3. 绝对定位的函数,如果要使用全局变量,那么被使用的常量也必须是绝对定位的,而局部变量则不受此限制。

4 调试坎坷之路

上面的想法很有新意,在调试时自己封装的接口文件也经过了验证,但是在 APP 调用共有函数时程序还是跑飞了,经过不断的分析现实线现象,找到了问题的根源所在。STM32 标准库在进行时钟配置时定义了两个全局的数组如下,由于开始没有注意到这两个全局数组,而这两个全局数组是在 Bootload 区域定义的,跳转到 APP 区域后会对栈空间重新初始化,原本放这两个数组的位置就被初始化其他数值了,到时时钟配置出错。

1/**stm32f10x_rcc.c*/
2
3static__Iuint8_tAPBAHBPrescTable[16]={0,0,0,0,1,2,3,4,1,2,3,4,6,7,8,9};
4
5static__Iuint8_tADCPrescTable[4]={2,4,6,8};

分析后的解决办法如下,因为这两个全局数据需要在 Bootload 区域中使用,而 Bootload 需要进行固化,所以需要将这两个数组放置固定的位置,这样每次使用到该数组时就回去固定的位置找,就不会出现被误修改的情况了。修改方式如下:

1__rootconstuint8_tAPBAHBPrescTable[16]@".AHBAPB_PRESC_TABLE"={0,0,0,0,1,2,3,4,1,2,3,4,6,7,8,9};
2
3__rootconstuint8_tADCPrescTable[4]@".ADC_PRESC_TABLE"={2,4,6,8};
4
5/**对应的修改.icf文件*/
6
7placeataddressmem:0x08010000{readonlysection.AHBAPB_PRESC_TABLE};
8
9placeataddressmem:0x08010010{readonlysection.ADC_PRESC_TABLE};

5 补充

上述讲解了在 Bootload 和 APP 中共有函数的定义和使用,怎么验证是不是将其定义在绝对地址了呢?我们可以查看编译后生成的 map 文件,如下所示,可以看到在 map 文件中可以找到定义的 section。

7e7afa18-36a5-11ee-9e74-dac502259ad0.png

————————————————

版权声明:本文为RT-Thread论坛用户「crystal266」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://club.rt-thread.org/ask/article/fa68bea40877eec3.html


点击阅读原文进入官网


原文标题:一种有趣的 OTA 升级思路(基于 LoRa 通信的 OTA 固件升级的调试记录)

文章出处:【微信公众号:RTThread物联网操作系统】欢迎添加关注!文章转载请注明出处。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • RT-Thread
    +关注

    关注

    32

    文章

    1652

    浏览量

    45374

原文标题:一种有趣的 OTA 升级思路(基于 LoRa 通信的 OTA 固件升级的调试记录)

文章出处:【微信号:RTThread,微信公众号:RTThread物联网操作系统】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    DGUS2升级OTA升级等功能开发更加便捷!

    为满足越来越多的OTA升级应用需求,迪文科技发布DGUS2_V71版本固件,优化OTA升级、数据备份相关功能开发接口,简化开发步骤,帮助客户
    的头像 发表于 05-14 17:57 151次阅读
    DGUS2<b class='flag-5'>升级</b>,<b class='flag-5'>OTA</b><b class='flag-5'>升级</b>等功能开发更加便捷!

    文吃透RK平台OTA升级开发:从逻辑到调试的完整指南

    ,能让开发者高效解决固件更新、功能迭代等问题。本文将从升级逻辑、核心技巧、调试要点到问题排查,全方位拆解 RK 平台 OTA 升级开发,附关
    的头像 发表于 02-09 16:26 863次阅读
    <b class='flag-5'>一</b>文吃透RK平台<b class='flag-5'>OTA</b><b class='flag-5'>升级</b>开发:从逻辑到<b class='flag-5'>调试</b>的完整指南

    RK平台Android设备OTA升级教程:从原理到U盘实操

    ” 和 “差异包” 两升级形态,适配不同场景(如全新安装、小版本更新)。本文将从 OTA 升级包的类型与编译入手,拆解 RK 平台 OTA
    的头像 发表于 02-09 16:23 2692次阅读
    RK平台Android设备<b class='flag-5'>OTA</b><b class='flag-5'>升级</b>教程:从原理到U盘实操

    STM32WB 系列微控制器 OTA 和无线固件更新应用笔记

    本文档介绍了通过低功耗蓝牙连接在 STM32WB 设备上进行 OTA 固件更新的过程。它讲解如何使用 STM32Cube 固件包中提供的 OTA 应用程序,实现用户应用程序、无线
    发表于 01-08 14:50 0次下载

    般想要实现OTA的话使用蓝牙升级好还是4G这种方式实现升级

    般想要实现OTA的话,使用蓝牙升级好还是4G这种方式实现升级
    发表于 12-09 06:01

    硕博电子OTA远程升级平台#OTA#硕博电子#OTA升级

    OTA
    长沙硕博电子科技股份有限公司
    发布于 :2025年10月29日 11:19:46

    使用RTT的维护云进行远程固件升级OTA),怎么没有网络升级的方式?

    使用RTT的维护云进行远程固件升级OTA),怎么没有网络升级的方式的?只有蓝牙,近距离的固件升级
    发表于 10-13 06:36

    ota升级完成后,bootloader没有将download区的新代码搬运到app区?

    ota升级完成后,bootloader没有把download区的新固件搬运到app区,版本也改了,可以保证是和上次的版本不样,也没有打印任何错误的信息,可以明确的是它能正确把
    发表于 09-29 10:04

    使用ymodem_ota时如何更换串口?

    现在使用串口1可以正常使用ymodem_ota进行固件升级,但是现在项目需要使用串口1来进行其他作用,求怎么把串口1更改为串口2进行ota升级
    发表于 09-25 06:17

    OTA采用ymodem_ota升级app分区出现CRC校验错误是怎么回事?

    升级成功,不知道是哪里问题?这个错误提示是因为我哪里操作错了导致的,还是就是正常现象?虽然表面上看不影响我使用OTA升级,但我想明白下,原因是什么?有没有大神,指导
    发表于 09-10 06:57

    技术笔记 | Ubuntu 系统 OTA 升级全流程详解

    开启、命令使用到实战案例与问题排查,为开发者提供套可直接落地的操作指南、recovery配置updateEngine支持因OTA升级过程中需要进入到recov
    的头像 发表于 07-31 08:32 1534次阅读
    技术笔记 | Ubuntu 系统 <b class='flag-5'>OTA</b> <b class='flag-5'>升级</b>全流程详解

    ESP32通过OTA无线局域网远程升级下载程序

    本文介绍了ESP32通过OTA无线局域网远程升级固件的基本方法
    的头像 发表于 07-22 13:21 2441次阅读
    ESP32通过<b class='flag-5'>OTA</b>无线局域网远程<b class='flag-5'>升级</b>下载程序

    蓝牙空中升级(OTA)原理

    1. 概述 所谓DFU(Device Firmware Update),就是设备固件升级的意思,而OTA(Over The Air)是实现DFU的一种方式而已,准确说,
    发表于 07-21 14:50

    东风日产N7开启首次OTA升级

    近日,东风日产举办“NI好 N7首次OTA升级发布会”,并宣布OTA升级即日开启推送。
    的头像 发表于 07-05 13:57 1407次阅读

    详解蓝牙空中升级(OTA)原理与步骤

    如何实现Bluetooth LE OTA?什么叫DFU?如何通过UART实现固件升级?又如何通过USB实现固件升级?怎么保证
    的头像 发表于 07-04 09:56 4953次阅读
    详解蓝牙空中<b class='flag-5'>升级</b>(<b class='flag-5'>OTA</b>)原理与步骤