完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
Cortex-M0 处理器内核异常中断简介在Cortex‐M0内核上搭载了一个异常响应系统,支持众多的系统异常和外部中断。其中,编号为1-15的对应系统异常,大于等于16的则全是外部中断,优先级的数值越小,则优先级越高。除了个别异常的优先级被定死外,其它异常的优先级都是可编程的。 因为芯片设计可以修改内核的硬件描述源代码,所以做成芯片后,支持的中断源数目常常不到240 个,并且优先级的位数也由芯片厂商最终决定。
类型编号为 1-15 对应系统异常,在《ARM Cortex-M0权威指南》一书中的第12章节<错误处理>章节中有描述:对于ARM处理器,架构采用错误异常的机制来检测问题,当一个程序产生了错误并且被处理器检测到时,异常中断会被触发,并且核心会跳转到相应的异常终端处理函数执行,错误异常的中断有如下: Reset 在上下电、NRST拉低、看门狗复位或软复位时启动复位。当复位产生时,处理器停止一切操作,并将复位当做一种特殊形式的异常来执行,进入到对应的中断函数。当复位撤销时,从向量表中复位项提供的地址处重新启动执行,芯片重新开始执行。 NMI 不可屏蔽中断(NMI),可以由外设产生,也可以由软件来触发。这是除复位之外优先级最高的异常中断,NMI永远使能,优先级固定为-2,CSS的时钟安全机制使能判定时钟失效后就会进入到该中断。NMI 不能: 1、被屏蔽,它的执行也不能被其他任何异常中止; 2、被除复位之外的任何异常抢占。 HardFault HardFault 是由于在正常操作过程中或在异常处理过程中出现错误而出现的一个异常。HardFault的优先级固定为-1,表明它的优先级要高于任何优先级可配置的异常。 SVCall 管理程序调用(SVC)异常是一个由SVC指令触发的异常。在OS环境下,应用程序可以使用 SVC指令来访问OS内核函数和器件驱动。 PendSV PendSV是一个中断驱动的系统级服务请求。在OS环境下,当没有其它异常有效时,使用 PendSV 来进行任务切换。 Systick SysTick是一个系统定时器到达零时产生的异常,软件也可以产生一个SysTick异常。在OS环境下,处理器可以将这个异常用作系统节拍。 中断(IRQ) 中断(或 IRQ)是外设发出的一个异常,或者由软件请求产生的一个异常。在系统中,外设使用中断来与处理器通信,在中断函数中可以查询和清除标志操作。 HardFault异常 HardFault (硬件错误,也有译为硬错误)是在MCU上编写程序中所产生的错误,硬件错误处理几乎是最高优先级,它的优先级为-1,只有复位和不可屏蔽中断(NMI)可以对其进行抢占。当它发生时,表示处理器出现了问题,需要采取紧急修复措施。 造成HardFault错误的可能原因较多,如何在代码量较大的情况下,快速定位造成的HardFault的问题代码,就成为比较关键的问题。 本文将以MM32F0130系列MCU为例,Keil-MDK开发环境,总结HardFault的调试、定位方法。在其它Cortex-M0 (M3,M4)内核处理器,和其它开发环境下,也可作为参考。 2.1 可能的原因 《ARM Cortex-M0权威指南》中提到,关于 Cortex M0内核主要有以下几点引起HardFault的原因:
从软件角度,产生HardFault的可能原因有:
注意:只有复位和NMI可以抢占优先级固定的 HardFault 处理程序。HardFault可以抢占除复位、NMI 或其它硬故障之外的任何异常。 2.2 可能出现的异常 如果在执行NMI或HardFault处理程序时,或者在一个使用MSP的异常返回时出栈的却是PSR的时候系统产生一个总线错误,处理器进入一个锁定状态。当处理器处于锁定状态时,它不执行任何指令。处理器保持处于锁定状态,直到下面任何一种情况出现:
注意:如果锁定状态出现在NMI处理程序中,后面的NMI就无法使处理器离开锁定状态。 在应用程序中,处理器处于锁定状态,会一直在void HardFault_Handler(void)函数中执行。void HardFault_Handler(void) { /* Go to infinite loop when Hard Fault exception occurs */ while (1) { } } 下面将在MM32F0130上运行的数组越界代码为例,具体阐述定位步骤:void StackTest(void) { int data[3],i; for(i=0; i<10000; i++) { data=1; } } 查找HardFault方法和步骤 实际环境中,由于测试高压等产品常常无法连接调试器,故需要代码来定位目标语句地址,并通过一定手段保存: 在MM32F0130中,需先修改启动文件startup_mm32f013x.s:HardFault_Handler PROC IMPORT hard_fault_handler_c;函数声明 MOVS r0, #4 ;判断主栈指针还是进程栈指针 MOV r1, LR TST r0, r1 BEQ stacking_used_MSP ;如果是主栈指针 MRS R0, PSP ;否则是进程栈指针,把进程栈指针地址付给 R0 B get_LR_and_branch ;跳转到 HardFault 中断程序 stacking_used_MSP MRS R0, MSP ;把主栈指针地址赋给 R0 get_LR_and_branch MOV R1, LR BL hard_fault_handler_c ENDP 该段代码会判断当前堆栈使用的是MSP或PSP,然后将堆栈参数传递给hard_fault_handler_c函数,该函数定义如下: void hard_fault_handler_c(unsigned int * hardfault_args, unsigned lr_value) { unsigned int stacked_r0; //压栈的 r0 unsigned int stacked_r1; //压栈的 r1 unsigned int stacked_r2; //压栈的 r2 unsigned int stacked_r3; //压栈的 r3 unsigned int stacked_r12; //压栈的 r12 unsigned int stacked_lr; //压栈的 lr unsigned int stacked_pc; //压栈的 pc unsigned int stacked_psr; //压栈的 psr stacked_r0 = ((unsigned int) hardfault_args[0]); stacked_r1 = ((unsigned int) hardfault_args[1]); stacked_r2 = ((unsigned int) hardfault_args[2]); stacked_r3 = ((unsigned int) hardfault_args[3]); stacked_r12 = ((unsigned int)hardfault_args[4]); stacked_lr = ((unsigned int) hardfault_args[5]); stacked_pc = ((unsigned int) hardfault_args[6]); stacked_psr = ((unsigned int) hardfault_args[7]); while(1) { printf("[Hard fault handler]rn"); printf("R0 = %xrn", stacked_r0); printf("R1 = %xrn", stacked_r1); printf("R2 = %xrn", stacked_r2); printf("R3 = %xrn", stacked_r3); printf("R12 = %xrn", stacked_r12); printf("Stacked LR = %xrn", stacked_lr); printf("Stacked PC = %xrn", stacked_pc); printf("Stacked PSR = %xrn", stacked_psr); printf("SCB_SHCSR=%xrn",SCB->SHCSR); printf("Current LR = %xrn", lr_value); } } 处理器进入到HardFault,将R0~R3、R12、LR、PC信息通过串口打印,根据寄存器信息排查问题代码。 当处理器处理异常时,除非异常是一个末尾连锁异常或迟来的异常,否则,处理器把信息都压入到当前堆栈中入栈(stacking),8个数据字的结构被称为栈帧(stack frame),栈按照双字地址对齐方式。 入栈后,堆栈指针立刻指向栈帧的最低地址单元。栈包含返回地址,这是被中止的程序中下条指令的地址。这个值在异常返回时返还给 PC,使被中止的程序恢复执行。 如下图连接仿真器查看汇编的地址可以找到是程序问题,根据PC指针地址,在程序生成的.map中查找出问题函数。 |
|
相关推荐
2 个讨论
|
|
只有小组成员才能发言,加入小组>>
2249个成员聚集在这个小组
加入小组灵动微电子MM32全系列MCU产品应用手册,库函数和例程和选型表
11703 浏览 3 评论
【MM32 eMiniBoard试用连载】+基于OLED12864的GUI---U8G2
5930 浏览 1 评论
【MM32 eMiniBoard试用连载】移植RT-Thread至MM32L373PS
10965 浏览 0 评论
【MM32 eMiniBoard测评报告】+ 开箱 + 初探
4577 浏览 1 评论
灵动微课堂(第106讲) | MM32 USB功能学习笔记 —— WinUSB设备
4302 浏览 1 评论
[MM32软件] MM32F002使用内部flash存储数据怎么操作?
977浏览 1评论
805浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-27 16:19 , Processed in 1.023314 second(s), Total 66, Slave 51 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号