近期项目为了增加程序的健壮性,将IAP的逻辑进行了修改,使用双APP空间,前一个为运行空间,后一个为更新程序临时存储空间,这样通过IAP或者APP本身,都可以对程序进行更新,以实现可靠的程序刷新过程。但这其中flash写入,出现了一个奇怪的现象,导致浪费几天时间用来排错,最终找到问题原因,以下经历做个记录,以便同病相怜者参考。
先说结论:
USART的DMA功能,会导致FLASH写入出现hard fault错误异常。
具体原因还没有分析,粗浅的猜测,是DMA对RAM中的地址进行了保护,在flash写入过程中,访问dma指向的ram会使芯片产生错误。
处理方案:
生成一个临时数组,将DMA接收的数据重新做一份拷贝,使用拷贝数组进行flash写入,就没有问题了。
过程:
之前由于程序优化不足,程序尺寸过于臃肿,没有足够的空间进行双APP备份,同时,总线挂载设备过多,导致IAP更新稳定性很低。
为了解决这个问题,将IAP逻辑修改为双APP空间,前一个APP空间用于正常运行,后一个APP空间用于更新程序存储,当更新程序版本号高于运行程序时,IAP执行更新操作。同时,正常运行的APP,还可以通过USART进行接收、验证、写入临时APP空间,这样可以保证始终有一个可靠的程序能在芯片上运行,也能保证最新版本的APP能够可靠刷入flash中。
但麻烦接踵而来。
使用USART接收的数据,无法写入FLASH!
这里出现了一个令人费解的现象:正常运行的APP开头,会有一个flash写入的片段,这个片段用于将系统参数等数据更新到flash中。这部分写入flash的程序,可以非常完美的将数据写入指定的FLASH地址,但是,到了USART部分,就完全无法写入flash,哪怕是一个64位的word。
将uasrt部分的程序挪到主程序部分,依然无效,试着多次修改flash写入程序,内部屏蔽中断、修改等待超时、先擦除后写入等操作,也无法解决问题。
通过反复思考 写入成功和写入失败 两者的区别,最终发现,只有源数据数组的差异,成功写入的源数据数组是一个全局常量数组,而失败写入程序的数组,是DMA指向RAM的全局变量数组。
想到马上进行测试,将DMA接收的数据,用一个临时变量数组buffer[]进行转存,然后通过buffer[]数组进行flash写入,测试结果成功!
异常的情况,其实很多是没有注意到的细节导致,解决问题的几天,一直反复翻阅芯片的应用手册,但是flash操作部分,完全没有提及到DMA指向的数组,会对flash写入造成影响。
小问题造成大影响,细微之处见真章。
谨以此文纪念浪费的宝贵时间,也为同病相怜者鉴。