背景:
最近半年陆陆续续压测OTA,OTA升级总有概率失败,一直未找到失败的根本原因。
实验:
最近的压测发现新板子升级没有问题,老板子压测会出现较多的失败。
失败时能看到34服务异常:
主节点:
10 10 0B 34 00 44 00 01
10 21 00 00 00 03 00 00
从节点:
10 03 7F 34 7F FF FF FF
分析:
擦除的时候出现异常,查询芯片手册发现芯片的最大次数为1000次,超过会有未预期的行为发生且擦除的时间为12ms-130ms,130ms的时间明显超过窗口狗的最大时间128ms。
APP的大小为192KB左右,擦除的最小单元为2K,擦除的时间远超过窗口狗的时间。因此原先的设计是把擦除的区域切片,擦除固定大小的区域后去喂狗。
但是随着擦除的次数增加,单位大小的区域擦除时间增加,极大概率导致喂狗超时。
优化:
采用flash driver支持的回调函数去实现喂狗。擦除的行为实际上是一个硬件行为,软件会一直等硬件的状态标志位,在软件等待的1oop中一直执行时钟寄存器的检查,通过寄存器的值去判断是否需要喂狗,喂狗后重置寄存器值。
后记:
调试过程中遇到的几个问题分享:
1.在寄存器未初始化的时候读取寄存器的值会导致软件复位
2.在Erase的过程中一般都禁止flash的读取操作:
Erase的操作后等待硬件状态字的那段代码中有除法(库函数,属于flash区)和函数(flash代码)都需要避免。如果是函数建议采用__ramfunc关键字去修饰。
补充说明:__ramfunc 关键字
该关键字是一个编译器指令,用于指示编译器将函数放置在RAM中,而不是闪存中。这对于需要快速执行的函数非常有用,因为RAM访问通常比闪存访问更快。对于需要在运行时修改的函数也非常有用,因为闪存通常是只读的。
但是,需要注意的是,将函数放置在RAM中会增加程序使用的RAM里。RAM是一种宝贵的资源,尤其是在嵌入式系统中,因此务必谨慎使用__ramfunc,并且仅用于RAM执行的益处大于增加RAM 使用成本的函数。外,使用__ramfunc时,您需要确保在执行函数之前将其从闪存复制到RAM。这通常在程序的初始化阶段完成。