问题描述
我在 STM32H745 MCU 上启用 mpu 时遇到问题。我只想禁用 mpu,设置区域然后启用它。然而,HardFault 出现了。我认为这是错误的区域设置问题。但是在评论之后,我注意到打开mpu就会出现问题。
代码:
static syslog_status_t setmpu_sysLog(void)
{
[...]
ARM_mpu_disable();
/* ARM_mpu_SetRegion(ARM_mpu_RBAR(0,(uint32_t)NON_CACHABLE_RAM4_D3_BASE_ADDR),ARM_mpu_RASR(0UL,ARM_mpu_AP_FULL,1UL,0UL,0x00UL,ARM_mpu_REGION_SIZE_8KB)); */
HALT_IF_DEBUGGING();
ARM_mpu_Enable(0);
return SYSLOG_OK;
}
我只使用 CMSIS API,所以我检查了程序集和 woops:
>0x80003ec <setmpu_sysLog+36> bkpt 0x0001
0x80003ee <setmpu_sysLog+38> ldr r3,[pc,#28] ; (0x800040c <setmpu_sysLog+68>)
0x80003f0 <setmpu_sysLog+40> movs r2,#1
0x80003f2 <setmpu_sysLog+42> str.w r2,[r3,#148] ; 0x94
0x80003f6 <setmpu_sysLog+46> ldr r2,#36] ; 0x24
0x80003f8 <setmpu_sysLog+48> orr.w r2,r2,#65536 ; 0x10000
0x80003fc <setmpu_sysLog+52> str r2,#36] ; 0x24
0x80003fe <setmpu_sysLog+54> dsb sy
0x8000402 <setmpu_sysLog+58> isb sy
0x8000406 <setmpu_sysLog+62> movs r0,#0
0x8000408 <setmpu_sysLog+64> bx lr
0x800040a <setmpu_sysLog+66> nop
0x800040c <setmpu_sysLog+68> ; <UNDEFINED> instruction: 0xed00e000
0x8000410 <initSysLog> push {r3,lr}
在 0x80003ee 中加载 UNDEFINED 指令到 PC?什么可能导致此编译器(?)错误?有没有人遇到过这样的问题?如何开始调试呢?以下其他调试信息:
0x08000398 in my_fault_handler_c (frame=0x2001ffb0) at CM7/exceptionHandlers.c:29
29 HALT_IF_DEBUGGING();
(gdb) p/a *frame
$1 = {r0 = 0xde684c0e,r1 = 0x6cefc92c,r2 = 0xed5b5cfb,r3 = 0xa3feeed1,r12 = 0xef082047,lr = 0xd7121a9e,return_address = 0xf16a13cf,xpsr = 0xf60e2caf}
Fields in SCB > HFSR:
VECTTBL: 0 Vector table hard fault
FORCED: 1 Forced hard fault
DEBUG_VT: 0 Reserved for Debug use
Fields in SCB > CFSR_UFSR_BFSR_MMFSR:
IACCVIOL: 1
DACCVIOL: 0
MUNSTKERR: 0
MSTKERR: 1
MLSPERR: 0
MMARVALID: 0
IBUSERR: 0 Instruction bus error
PRECISERR: 0 Precise data bus error
IMPRECISERR: 0 Imprecise data bus error
UNSTKERR: 0 Bus fault on unstacking for a return from exception
STKERR: 0 Bus fault on stacking for exception entry
LSPERR: 0 Bus fault on floating-point lazy state preservation
BFARVALID: 0 Bus Fault Address Register (BFAR) valid flag
UNDEFINSTR: 0 Undefined instruction usage fault
INvstaTE: 0 Invalid state usage fault
INVPC: 0 Invalid PC load usage fault
NOCP: 0 No coprocessor usage fault.
UNALIGNED: 0 Unaligned access usage fault
DIVBYZERO: 0 Divide by zero usage fault
arm-none-eabi-gcc -v
cc version 10.2.1 20201103 (release) (GNU Arm Embedded Toolchain 10-2020-q4-major)
解决方法
问题是没有设置 PRIVDEFENA 位。因此,按以下方式打开 MPU 有帮助:
ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk);
,
这不是未定义的指令。它是您的函数使用的值(在这种情况下是硬件寄存器块的地址)。 ARM Thumb 指令无法将寄存器设置为 32 位值,因此必须将其存储在内存中并从那里加载。
这不是错误 - 这是非常标准的事情。
示例:
typedef struct
{
volatile uint32_t reg1;
volatile uint32_t reg2;
}MYREG_t;
#define MYREG ((MYREG_t *)0xed00e000)
void foo(uint32_t val)
{
MYREG -> reg2 = val;
}
void bar(uint32_t val)
{
MYREG -> reg1 = val;
}
和生成的代码:
foo:
ldr r3,.L3
str r0,[r3,#4]
bx lr
.L3:
.word -318709760
bar:
ldr r3,.L6
str r0,[r3]
bx lr
.L6:
.word -318709760
存储此数据且代码从未到达的位置。在您的代码中也是如此。它在获取 tere (bc lr
)
如果您使用反汇编工具(如您所做的那样),它将无法理解并显示未定义的指令。
顺便说一句,你在使用 arm-none-eabi-gdb 吗?因为它显示了寄存器的无意义值,