1案例背景最近有个客户使用s32k146的产品在量产之后出现了三个售后件,abba测试之后的结果表明失效现象跟着s32k146走;同时客户反馈说试着将其中一个售后件重新烧录程序,s32k146又正常工作了。结合这两种情况,s32k146应该是没有损坏的,那就需要从软件程序方面排查了。
然后和客户的软件工程师交流了一下,使用attaching to running target的方式发现程序卡死在hardfault。因为是量产产品出问题,客户强烈要求去现场处理问题,特地记录下这次处理s32k146的hard fault问题的过程,希望对读者有帮助。
2方案准备在这之前,笔者还没有处理过s32k1系列发生hardfault的问题,所以需要先对s32k1系列发生hardfault的原因进行了解。推荐如下这篇文章,讲得非常细致。
结合上面这篇文章以及arm官方的m4内核文档cortex -m4 devices generic user guide ^[1]^ ,笔者简要整理了下s32k1发生hardfault的可能原因以及排查方式,如下文所述。
2.1 hardfault(硬件错误异常)hardfault的可能原因 停止调试关闭时发生了调试事件;usagefault、busfault、memmanage fault未使能(coretex-m4f内核默认状态)时发生了相应的错误导致错误升级到hardfault;异常处理过程中取内核中断向量表读操作错误。hardfault的原因排查 造成hardfault的原因,可通过scb模块的硬件错误状态寄存器(hfsr)进行排查,如下所示: 原因1引起的,debugevt bit置1;原因2引起的,forced bit置1;原因3引起的,vecttbl bit置1。
hfsr寄存器
2.2 usagefault(用法错误异常)usagefault的可能原因 执行未定义指令,即非法指令;指令执行状态错误;异常返回错误;尝试访问关闭或者不可用的协处理器;非对齐地址访问(需要先通过scb模块的ccr寄存器进行使能);除零操作(需要先通过scb模块的ccr寄存器进行使能)。usagefault的原因排查 造成usagefault的原因,可通过scb模块的用法错误状态寄存器(ufsr)进行排查,如下所示: 原因1引起的,undefinstr bit置1;原因2引起的,invstate bit置1;原因3引起的,invpc bit置1;原因4引起的,nocp bit置1;原因5引起的,unaligned bit置1;原因6引起的,divbyzero bit置1。
ufsr寄存器
2.3 busfault(总线错误异常)busfault的可能原因
a. 异常/中断入口压栈;b. 异常/中断返回出栈;c. 预取指;d. fpu lazy state现场保护;crossbar总线矩阵slave端口返回错误响应,当:精确总线错误;不精确总线错误。busfault的原因排查 造成busfault的原因,可通过scb模块的总线错误状态寄存器(bfsr)进行排查,如下所示:
原因1.a引起的,stkerr bit置1;原因1.b引起的,unstkerr bit置1;原因1.c引起的,ibuserr bit置1;原因1.d引起的,lsperr bit置1;原因2引起的,preciserr bit置1;原因3引起的,impreciserr bit置1。
bfsr寄存器
2.4 memmanage fault(存储器管理错误异常)memmanage fault的可能原因 尝试加载和储存内核mpu保护的地址;从内核mpu保护的地址取指;由mpu违规引起的压栈和出栈(函数调用或者中断/异常处理)错误;硬件fpu lazy state保护触发的mpu存储器保护违规。memmanage fault的原因排查 造成memmanage fault的原因,可通过scb模块的存储器管理错误状态寄存器(mmfsr)进行排查,如下所示: 原因1引起的,daccviol bit置1;原因2引起的,iaccviol bit置1;原因3引起的,mstkerr或munstkerr bit置1;原因4引起的,mlsperr bit置1;
mmfsr寄存器
ufsr、bfsr、mmfsr寄存器都是scb模块中cfsr寄存器的子寄存器,包含关系如下,实际调试时查看cfsr寄存器即可。
cfsr寄存器
如果要访问ufsr、bfsr、mmfsr这些子寄存器,可以按照如下的地址进行访问:
cfsr子寄存器地址
3现场支持了解了引起hardfault的可能原因以及排查方式之后,就是按照该方法协助客户进行原因排查。
3.1 现场环境客户的现场环境如下:
开发环境:iar 8.30.1调试器:jlink v9mcu:s32k146sdk:ear0.8.63.2 排查过程打开和异常件对应的软件工程,使用attach方式连接上第一个异常件的主控s32k146,如下图所示:进入仿真界面后,暂停之后发现程序卡死在hard fault。查看s32的scb模块,hfsr寄存器的forced bit置1,说明是其它错误上升到hard fault,需要查看cfsr寄存器了解更多信息。cfsr寄存器的bfarvalid bit 和preciserr bit都置1,说明是精确总线错误造成bus fault并且捕捉保存了精确总线错误发生时的数据访问地址;再去查看bfar寄存器,发生错误时数据访问的地址是0x100010e8。使用同样的方法排查第二个异常件的主控mcu,也是精确总线错误造成的bus fault,发生错误时数据访问的地址是0x10001128。接着通过iar查看下s32k146的memory,从地址0x10001128起始的8个字节长度的flash区域数据无法查看。翻阅s32k1的memory相关的应用笔记an11983: using the s32k1xx eeprom functionality – application note ^[2]^ ,发生错误的地址属于d-flash,如下图所示:
s32k1xx memory map
查阅软件代码中读写dflash中这块地址的函数,发现在写dflash之前虽然进行了擦写操作,但是并没有设置擦写成功之后才能写dflash的条件,有概率出现擦写不完全的情况下写d-flash。同时,客户查看了其他组未出问题的产品的软件代码,在写d-flash之前添加了比较多的条件判断,包含对擦写状态的判断。至此,该问题初步得到解决,剩下的就是优化代码并跟进后续产品的表现了。4异常模拟客户的问题虽然解决了,但是笔者还是不确定连续两次对同一块区域的flash写不同的值,中间没有擦除动作,是否会让mcu卡在hardfault,所以使用手上的s32k144开发板进行了该情况的模拟。
4.1 测试环境开发环境:s32 design studio for arm 2.2sdk:rtm 3.0.0开发板:s32k144evb-q1004.2 测试过程打开s32ds 2.2,选择自带的例程 flash_partitioning_s32k144 。将初始化模拟eeprom的部分注释掉,避免d-flash被用作模拟eeprom的备份区从而无法进行读写测试。定义一套新数组并储存新的数据用于测试。在正常的d-flash写之后增加写入不同数据的操作。编译之后进行debug,单步调试发现如果只进行写不同数据进入d-flash,s32k144不会进入hardfault,需要再执行读d-flash的操作,才会进入hardfault。如果想要了解读取flash地址的数据才会发生hardfault的原因。
s32ds之所以能在控制台显示比较多的mcu异常信息,是因为在调试器界面使能了异常捕捉功能,这部分功能依赖的是demcr寄存器,如下图所示。
异常捕捉配置
demcr寄存器
英特尔考虑成为Arm的锚定投资者,募资规模或达百亿
嵌入式web server boa在S3C2410上的编译移植步骤
恩智浦发布2016年第二季度财务报告
三菱FX系列PLC常用指令大全来了
唯一一款6G运存的手机为何会不受待见?360N5到底做错了什么?
S32K146的hard fault问题解决方案
机器学习模型可解释性的结果分析
惟客数据解读:数据中台与业务中台的区别和联系
三元电池依然是是新能源汽车动力电池的主流选项之一
LED显示屏如何应对潮湿环境
Fairchild开发IntelliMAX负载开关显著延长电
肖特基二极管的用法
在智能插线板大行其道时,这款插座玩起了DIY
各类机械手的工作原理和功能特点
照相机电子快门控制电路原理图
优博终端RobanTrust OS软件发行版通过兼容性测评,加快面向八大行业商业化落地
WiMAX射频的集成趋势和灵巧划分案例分析
2023 CES看点 耐能再获IEEE CTSoc大奖
2018年移动式存储器产值成长超过 3 成
锂价谷底回升,景气度或将维持