分享一种有趣的OTA升级思路_第1页
分享一种有趣的OTA升级思路_第2页
分享一种有趣的OTA升级思路_第3页
分享一种有趣的OTA升级思路_第4页
分享一种有趣的OTA升级思路_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第第页分享一种有趣的OTA升级思路

1概述

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

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

2调试之路

2.1想法

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

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

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

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

2.2.1IAR的扩展关键字

@用于函数变量的绝对地址定位,将函数变量等放到指定的sec(ti)on

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

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

2.2.2函数的绝对定位

要将函数定义在绝对位置,需要在函数定义时后面加上@".section_name",例如:

voidfun1(inta,intb)@".MY_SECTION"

{

...//函数内容

}

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

pl(ac)eataddressmem:0x08010000{readonlysection.MY_SECTION};

2.2.3变量的绝对定位

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

__no_initchararray1[100]@0x2000B000;

2.2.4常量的绝对定位

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

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

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

placeataddressmem:0x08018500{readonlysection.MYSEG};

2.2.4.c文件的绝对定位

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

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

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

2.3Bootload共有函数的实现

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

__rootconstuint32_tfunc_table[]@".COMMON_FUNC_SEG"={

(uint32_t)

2.4APP共有函数的使用

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

/**1.声明*/

typedefint(*app_fun1)(inta,intb);

typedefvoid(app_fun2)(void);

typedefchar(app_fun3)(charp);

/2.定义函数指针类型的变量/

app_fun1fun1;

app_fun2fun2;

app_fun1fun3;

/3.共有函数的重定义/

#defineFUNC_TABLE_ADDR(0x08010000)/共有函数的首地址*/

voidredefine_common_function(void)

{

uint32_t*func_table_addr=(uint32_t)FUNC_TABLE_ADDR;

fun1=(app_fun1)func_table_addr[0];/00/

fun2=(app_fun2)func_table_addr[1];/01/

fun3=(app_fun3)func_table_addr[2];/02*/

}

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

3注意事项

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

固件更新区的绝对定位的函数,不能随意调用其他库函数,那些被调用的函数也必须是绝对定位的。绝对定位的函数,如果要使用常量,那么被使用的常量也必须是绝对定位的。绝对定位的函数,如果要使用全局变量,那么被使用的常量也必须是绝对定位的,而局部变量则不受此限制。4调试坎坷之路

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

/**stm32f10x_rcc.c*/

static__Iuint8_tAPBAHBPrescTable[16]={0,0,0,0,1,2,3,4,1,2,3,4,6,7,8,9};

static__Iuint8_t(ADC)PrescTable[4]={2,4,6,8};

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

__rootconstuint8_tAPBAHBPrescTable[16]@".AHBAPB_PRESC_TABLE"={0,0,0,0,1,2,3,4,1,2,3,4,6,7,8,9};

__rootconstuint8_tADCPrescTable[4]@".ADC_PRESC_TABLE"={2,4,6,8};

/**对应的修改.icf文件*/

placeataddressmem:0x08010000{readonlysection.AHBAPB_PRESC_TABLE};

placeataddressmem:0x08010010{readonlysection.ADC_P

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论