STM32开发学习——使用 Cortex-M3M4M7 故障异常原因与定位(二)
文章目录
文档说明:
分享一下在Stm32学习过程收集到的一些值得记录的好资料,以便自己保留印象和尽可能的应用到工作中,达到事半功倍的效果。
这是一篇关于Cortex-M内核故障异常的举例。
Cortex-M内核故障的基础概念请看STM32开发学习——使用 Cortex-M3M4M7 故障异常原因与定位(一)
官方参考文档线上链接(可在线阅读与下载):
故障分析示例
BusFault总线故障示例
非法内存写入(Illegal Memory Write)
/*********************************************************************
*
* 通过写入保留地址触发BusFault或HardFault。
*
* Additional Information
* BusFault是在写入指令之后引发的一些指令。
* Related registers on fault:
* HFSR = 0x40000000
* FORCED = 1 - BusFault escalated to HardFault (when BusFault is not activated)
* BFSR = 0x00000004
* IMPRECISERR = 1 - Imprecise data access violation. Return address not related to fault
* BFARVALID = 0 - BFAR not valid
*/
static int _IllegalWrite(void) {
int r;
volatile unsigned int* p;
r = 0;
p = (unsigned int*)0x00100000; // 0x00100000-0x07FFFFFF is reserved on STM32F4
// F44F1380 mov.w r3, #0x00100000
*p = 0x00BADA55;
// 4A03 ldr r2, =0x00BADA55
// 601A str r2, [r3] <- Illegal write is done here
return r;
// 9B00 ldr r3, [sp]
// 4618 mov r0, r3
// B002 add sp, sp, #8 <- Fault might be raised here
// 4770 bx lr
}
非法内存读取(Illegal Memory Read)
/*********************************************************************
*
* _IllegalRead()
*
* Function description
* 通过读取保留地址触发BusFault或HardFault。
*
* Additional Information
* 读取指令会立即触发BusFault。
* Related registers on fault:
* HFSR = 0x40000000
* FORCED = 1 - BusFault escalated to HardFault
* BFSR = 0x00000082
* PRECISERR = 1 - Precise data access violation
* BFARVALID = 1 - BFAR is valid
* BFAR = 0x00100000 - The address read from
*/
static int _IllegalRead(void) {
int r;
volatile unsigned int* p;
p = (unsigned int*)0x00100000; // 0x00100000-0x07FFFFFF is reserved on STM32F4
// F44F1380 mov.w r3, #0x00100000 <- The read address. Will be found in BFAR
r = *p;
// 681B ldr r3, [r3] <- Illegal read happens here and raises BusFault
// 9300 str r3, [sp]
return r;
}
非法执行功能(Illegal Function Execution)
/*********************************************************************
*
* _IllegalFunc()
*
* Function description
* 通过在保留地址执行来触发BusFault或HardFault。
*
* Additional Information
* 在无效地址执行时触发BusFault。
* Related registers on fault:
* HFSR = 0x40000000
* FORCED = 1 - BusFault escalated to HardFault
* BFSR = 0x00000001
* IBUSERR = 1 - BusFault on instruction prefetch
*/
static int _IllegalFunc(void) {
int r;
int (*pF)(void);
pF = (int(*)(void))0x00100001; // 0x00100000-0x07FFFFFF is reserved on STM32F4
// F44F1380 mov.w r3, #0x00100001
r = pF();
// 4798 blx r3 <- Branch to illegal address, causes fetch from 0x00100000 and fault exception
return r;
}
UsageFault 使用故障示例
未定义的指令执行(Undefined Instruction Execution)
/*********************************************************************
*
* _UndefInst()
*
* Function description
* 通过执行未定义的指令触发UsageFault或HardFault。
*
* Additional Information
* UsageFault是在无效地址执行时触发的。
* Related registers on hard fault:
* HFSR = 0x40000000
* FORCED = 1 - UsageFault escalated to HardFault
* UFSR = 0x0001
* UNDEFINSTR = 1 - Undefined instruction executed
*/
static int _UndefInst(void) {
static const unsigned short _UDF[4] = {0xDEAD, 0xDEAD, 0xDEAD, 0xDEAD}; // 0xDEAD: UDF #<imm> (permanently undefined)
int r;
int (*pF)(void);
pF = (int(*)(void))(((char*)&_UDF) + 1);
// 4B05 ldr r3, =0x08001C18 <_UDF> <- Load address of "RAM Code" instructions
// 3301 adds r3, #1 <- Make sure Thumb bit is set
r = pF();
// 4798 blx r3 <- Call "RAM Code", will execute UDF instruction and raise exception
// 9000 str r0, [sp]
return r;
}
非法状态(Illegal State)
/*********************************************************************
*
* _NoThumbFunc()
*
* Function description
* 通过执行未设置thumb的地址来触发 UsageFault 或 HardFault。
*
* Additional Information
* UsageFault是在无效地址执行时触发的。
* Related registers on hard fault:
* HFSR = 0x40000000
* FORCED = 1 - UsageFault escalated to HardFault
* UFSR = 0x0002
* INVSTATE = 1 - Instruction execution with invalid state
*/
static int _NoThumbFunc(void) {
int r;
int (*pF)(void);
pF = (int(*)(void))0x00100000; // 0x00100000-0x07FFFFFF is reserved on STM32F4
// F44F1380 mov.w r3, #0x00100000 <- Note that bit [0] is not set.
r = pF();
// 4798 blx r3 <- Branch exchange with mode change to ARM, but Cortex-M only supports Thumb mode.
return r;
}
除以零(Division By Zero)
/*********************************************************************
*
* _DivideByZero()
*
* Function description
* 通过除以零触发UsageFault或HardFault。
*
* Additional Information
* UsageFault在除法指令上立即触发。
* Related registers on hard fault:
* HFSR = 0x40000000
* FORCED = 1 - UsageFault escalated to HardFault
* UFSR = 0x0200
* DIVBYZERO = 1 - Divide-by-zero fault
*/
static int _DivideByZero(void) {
int r;
volatile unsigned int a;
volatile unsigned int b;
a = 1;
// 2301 movs r3, #1 <- Load dividend
b = 0;
// 2300 movs r3, #0 <- Load divisor
r = a / b;
// FBB2F3F3 udiv r3, r2, r3 <- divide by 0 raises fault exception
return r;
}
未对齐访问
/*********************************************************************
*
* _UnalignedAccess()
*
* Function description
* 通过未对齐的字访问触发UsageFault或HardFault。
*
* Additional Information
* UsageFault在读取或写入指令时立即触发。
* Related registers on fault:
* HFSR = 0x40000000
* FORCED = 1 - UsageFault escalated to HardFault
* UFSR = 0x0100
* UNALIGNED = 1 - Unaligned memory access
*/
static int _UnalignedAccess(void) {
int r;
volatile unsigned int* p;
p = (unsigned int*)0x20000002;
// 4B04 ldr r3, =0x20000002 <- Not word aligned address
r = *p;
// 681B ldr r3, [r3] <- Load word from unaligned address raises exception
// 9300 str r3, [sp]
return r;
}
HardFault 示例
非法向量表提取
/*********************************************************************
*
* _IllegalVector()
*
* Function description
* 通过使用非法矢量表进行中断来触发HardFault。
*
* Additional Information
* Related registers on fault:
* HFSR = 0x00000002
* VECTTBL = 1 - Vector table read fault
*/
static int _IllegalVector(void) {
int r;
SCB->VTOR = 0x001000000; // Relocate vector table to illegal address
// 4B09 ldr r3, =0xE000ED00
// F04F7280 mov.w r2, #0x1000000
// 609A str r2, [r3, #8]
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; // Trigger PendSV exception to read invalid vector
// 4B07 ldr r3, =0xE000ED00
// F04F5280 mov.w r2, #0x10000000
// 605A str r2, [r3, #4]
__ISB();
// F3BF8F6F isb <- PendSV exception is to be executed. PendSV vector is tried to be read from illegal address 0x00100038 causes fault exception
// BF00 nop
__DSB();
// F3BF8F4F dsb sy
// BF00 nop
return r;
}
[r3, #4]
__ISB();
// F3BF8F6F isb <- PendSV exception is to be executed. PendSV vector is tried to be read from illegal address 0x00100038 causes fault exception
// BF00 nop
__DSB();
// F3BF8F4F dsb sy
// BF00 nop
return r;
}