本帖最后由 aozima 于 2012-12-2 22:07 编辑
项目中加了一些代码,Fault 后可以打印出更多的信息。#define SCB_CFSR (*(volatile const unsigned *)0xE000ED28) /* Configurable Fault Status Register */
#define SCB_HFSR (*(volatile const unsigned *)0xE000ED2C) /* HardFault Status Register */
#define SCB_MMAR (*(volatile const unsigned *)0xE000ED34) /* MemManage Fault Address register */
#define SCB_BFAR (*(volatile const unsigned *)0xE000ED38) /* Bus Fault Address Register */
#define SCB_CFSR_MFSR (*(volatile const unsigned char*)0xE000ED28) /* Memory-management Fault Status Register */
#define SCB_CFSR_BFSR (*(volatile const unsigned char*)0xE000ED29) /* Bus Fault Status Register */
#define SCB_CFSR_UFSR (*(volatile const unsigned short*)0xE000ED2A) /* Usage Fault Status Register */
static void usage_fault_track(void)
{
rt_kprintf("usage fault:\n");
rt_kprintf("SCB_CFSR_UFSR:0x%02X ", SCB_CFSR_UFSR);
if(SCB_CFSR_UFSR & (1<<0))
{
/* [0]:UNDEFINSTR */
rt_kprintf("UNDEFINSTR ");
}
if(SCB_CFSR_UFSR & (1<<1))
{
/* [1]:INVSTATE */
rt_kprintf("INVSTATE ");
}
if(SCB_CFSR_UFSR & (1<<2))
{
/* [2]:INVPC */
rt_kprintf("INVPC ");
}
if(SCB_CFSR_UFSR & (1<<3))
{
/* [3]:NOCP */
rt_kprintf("NOCP ");
}
if(SCB_CFSR_UFSR & (1<<8))
{
/* [8]:UNALIGNED */
rt_kprintf("UNALIGNED ");
}
if(SCB_CFSR_UFSR & (1<<9))
{
/* [9]:DIVBYZERO */
rt_kprintf("DIVBYZERO ");
}
rt_kprintf("\n");
}
static void bus_fault_track(void)
{
rt_kprintf("bus fault:\n");
rt_kprintf("SCB_CFSR_BFSR:0x%02X ", SCB_CFSR_BFSR);
if(SCB_CFSR_BFSR & (1<<0))
{
/* [0]:IBUSERR */
rt_kprintf("IBUSERR ");
}
if(SCB_CFSR_BFSR & (1<<1))
{
/* [1]:PRECISERR */
rt_kprintf("PRECISERR ");
}
if(SCB_CFSR_BFSR & (1<<2))
{
/* [2]:IMPRECISERR */
rt_kprintf("IMPRECISERR ");
}
if(SCB_CFSR_BFSR & (1<<3))
{
/* [3]:UNSTKERR */
rt_kprintf("UNSTKERR ");
}
if(SCB_CFSR_BFSR & (1<<4))
{
/* [4]:STKERR */
rt_kprintf("STKERR ");
}
if(SCB_CFSR_BFSR & (1<<7))
{
rt_kprintf("SCB->BFAR:%08X\n", SCB_BFAR);
}
else
{
rt_kprintf("\n");
}
}
static void mem_manage_fault_track(void)
{
rt_kprintf("mem manage fault:\n");
rt_kprintf("SCB_CFSR_MFSR:0x%02X ", SCB_CFSR_MFSR);
if(SCB_CFSR_MFSR & (1<<0))
{
/* [0]:IACCVIOL */
rt_kprintf("IACCVIOL ");
}
if(SCB_CFSR_MFSR & (1<<1))
{
/* [1]:DACCVIOL */
rt_kprintf("DACCVIOL ");
}
if(SCB_CFSR_MFSR & (1<<3))
{
/* [3]:MUNSTKERR */
rt_kprintf("MUNSTKERR ");
}
if(SCB_CFSR_MFSR & (1<<4))
{
/* [4]:MSTKERR */
rt_kprintf("MSTKERR ");
}
if(SCB_CFSR_MFSR & (1<<7))
{
/* [7]:MMARVALID */
rt_kprintf("SCB->MMAR:%08X\n", SCB_MMAR);
}
else
{
rt_kprintf("\n");
}
}
static void hard_fault_track(void)
{
if(SCB_HFSR & (1UL<<1))
{
/* [1]:VECTBL, Indicates hard fault is caused by failed vector fetch. */
rt_kprintf("failed vector fetch\n");
}
if(SCB_HFSR & (1UL<<30))
{
/* [30]:FORCED, Indicates hard fault is taken because of bus fault,
memory management fault, or usage fault. */
if(SCB_CFSR_BFSR)
{
bus_fault_track();
}
if(SCB_CFSR_MFSR)
{
mem_manage_fault_track();
}
if(SCB_CFSR_UFSR)
{
usage_fault_track();
}
}
if(SCB_HFSR & (1UL<<31))
{
/* [31]:DEBUGEVT, Indicates hard fault is triggered by debug event. */
rt_kprintf("debug event\n");
}
}
/**
* fault exception handling
*/
void rt_hw_hard_fault_exception(struct stack_context* contex)
{
rt_kprintf("psr: 0x%08x\n", contex->psr);
rt_kprintf(" pc: 0x%08x\n", contex->pc);
rt_kprintf(" lr: 0x%08x\n", contex->lr);
rt_kprintf("r12: 0x%08x\n", contex->r12);
rt_kprintf("r03: 0x%08x\n", contex->r3);
rt_kprintf("r02: 0x%08x\n", contex->r2);
rt_kprintf("r01: 0x%08x\n", contex->r1);
rt_kprintf("r00: 0x%08x\n", contex->r0);
hard_fault_track();
rt_kprintf("hard fault on thread: %s\n", rt_current_thread->name);
#ifdef RT_USING_FINSH
list_thread();
#endif
while (1);
}
再写了两个测试代码,以手动触发fault。#include <finsh.h>
static void div0_test(void)
{
int x,y,z;
x = 10;
y = 0;
z = x / y;
rt_kprintf("z:%d\n", z);
}
FINSH_FUNCTION_EXPORT(div0_test, div0_test)
static void unalign_test(void)
{
int * p;
p = (int *)0x00;
rt_kprintf("00:0x%08X\n", *p);
p = (int *)0x04;
rt_kprintf("04:0x%08X\n", *p);
p = (int *)0x03;
rt_kprintf("03:0x%08X\n", *p);
}
FINSH_FUNCTION_EXPORT(unalign_test, unalign_test)
测试时可以使用finsh强大的功能来配置CPU的状态:
1. 访问末授权区域finsh>>int * p //声明一个指针变量
0, 0x00000000
finsh>>p = 0xDFFFFFF0 // 指向片上外设区结束处,一般不可能用完,所以此处一般不可访问。
-536870928, 0xdffffff0
finsh>>*p // 读取指针处数据
psr: 0x01000000
pc: 0x00000e3e
lr: 0x0000451d
r12: 0x00000000
r03: 0x00000000
r02: 0x1fff0180
r01: 0x1fff0814
r00: 0xdffffff0
bus fault:
SCB_CFSR_BFSR:0x82 PRECISERR SCB->BFAR:DFFFFFF0
hard fault on thread: tshell
thread pri status sp stack size max used left tick error
-------- ---- ------- ---------- ---------- ---------- ---------- ---
tidle 0x1f ready 0x00000040 0x00000100 0x00000060 0x00000015 000
tshell 0x14 ready 0x00000088 0x00000400 0x00000218 0x00000009 000
2. 非对齐访问测试finsh>>int * p //声明一个指针变量
0, 0x00000000
finsh>>p = 0xE000ED14 // 指向SCB->CCR
-536810220, 0xe000ed14
finsh>>*p = 0x00000208 // 打开非对齐异常
520, 0x00000208
finsh>>unalign_test() // 非对齐访问测试
psr: 0x21000000
pc: 0x00000430
lr: 0x00003cbd
r12: 0x0000006e
r03: 0x00000002
r02: 0x00000004
r01: 0x1fff1b6a
r00: 0x1fff1a2c
usage fault:
SCB_CFSR_UFSR:0x100 UNALIGNED
hard fault on thread: tshell
thread pri status sp stack size max used left tick error
-------- ---- ------- ---------- ---------- ---------- ---------- ---
tidle 0x1f ready 0x00000058 0x00000100 0x00000060 0x00000001 000
tshell 0x14 ready 0x00000088 0x00000400 0x00000218 0x00000008 000
3. 除零异常测试finsh>>int * p //声明一个指针变量
0, 0x00000000
finsh>>p = 0xE000ED14 // 指向SCB->CCR
-536810220, 0xe000ed14
finsh>>*p = 0x00000210 // 打开除零异常
528, 0x00000210
finsh>>div0_test() // 除零异常测试
psr: 0x41000000
pc: 0x00001efe
lr: 0x0000096d
r12: 0x00000000
r03: 0x1fff012c
r02: 0x1fff0917
r01: 0x00001ef9
r00: 0x00000000
usage fault:
SCB_CFSR_UFSR:0x200 DIVBYZERO
hard fault on thread: tshell
thread pri status sp stack size max used left tick error
-------- ---- ------- ---------- ---------- ---------- ---------- ---
tidle 0x1f ready 0x00000040 0x00000100 0x00000060 0x0000000b 000
tshell 0x14 ready 0x00000088 0x00000400 0x00000218 0x00000009 000
|