I want to run simple test code in C on the Renesas Synergy R7FS5D97E evaluation board (Cortex M4). I made a sample project + SDK and toolchain projects using official materials, successfully built and flashed it using Ozone debugger.
However, when I run it, an exception is raised on startup: HardFault with undefined instruction flag when executing MRS R1, PRIMASK
in function R_BSP_RegisterProtectEnable
.
It'd be understandable if it happened the first time this instruction was executed, but it's not - in fact, it's about 15th time this instruction (in this exact function and even the same value of PRIMASK register) is executed during the program's run, so it can't be simply unsupported on this hardware.
I managed to trace where the error happens: the call of R_BSP_RegisterProtectEnable
/HW_CGC_HardwareLock
right after SystemInit
(system_S5D9.c:171
) -> bsp_clock_init
(bsp_clocks.c:150
) -> R_CGC_SystemClockSet
(r_cgc.c:707
) -> r_cgc_system_dividers_set
(r_cgc.c:2637
), so I'm wondering if it could be some kind of clock configuration problem? In Ozone, I'm simply using default settings offered for this board.
Alternatively, I could've made a mistake in preparing this SDK and toolchain - I had to manually cobble together a pure Conan+CMake project from Renesas configuration files and perhaps I missed something. Still, it doesn't make sense for this specific instruction to fail. It's simply copying a special register value to a general register.
I've run the same kind of thing on a different Renesas Synergy board years ago (different SDK and toolchain files), and had my fair share of trouble there, but never this - and it worked in the end.
Attached system state before the error and the HardFault details from Ozone since I can't copy it as text.
SDK project, toolchain project; I don't think the sample project matters as the error happens during startup, but I can upload it if needed.
UPD: The error happens when setting ICLK divider and clock source in this branch. Clock source is set first in function r_cgc_clock_source_set
, that calls R_BSP_RegisterProtectDisable
, performs a store and calls R_BSP_RegisterProtectEnable
. The first instruction in R_BSP_RegisterProtectEnable
is MRS R1, PRIMASK
, which executes successfully here. Assembly (inlined function):
LDR.W R8, [R7, #28]
BL R_BSP_RegisterProtectDisable
LDRB.W R3, [R8, #38]
BFI R3, R6, #0, #3
MOV R0, R5
STRB.W R3, [R8, #38]
BL R_BSP_RegisterProtectEnable
Then the function r_cgc_system_dividers_set
is called (source link). Assembly (this time non-inline):
LDR R0, [R7, #28]
MOV R1, R4
BL r_cgc_system_dividers_set
~~~
PUSH {R4-R6, LR}
LDRB R2, [R1]
LDRB R3, [R1, #1]
LDRB R6, [R1, #2]
LDRB R5, [R1, #3]
MOVS R4, #0
AND R3, R3, #7
BFI R4, R2, #12, #3
LDR R2, =gp_cgc_feature ; [PC, #64] [0x00001CC0] =0x1FFE0214
BFI R4, R3, #8, #3
LDR R2, [R2]
BFI R4, R6, #4, #3
LDRB R6, [R1, #4]
LDRB.W R2, [R2, #42]
BFI R4, R5, #0, #3
LDRB R5, [R1, #5]
LDRB R1, [R1, #6]
BFI R4, R6, #16, #3
BFI R4, R5, #28, #3
BFI R4, R1, #24, #3
MOV R5, R0
LSLS R2, R2, #29
IT MI
BFIMI R4, R3, #16, #3
MOVS R0, #0
BL R_BSP_RegisterProtectDisable
STR R4, [R5, #32]
MOVS R0, #0
POP.W {R4-R6, LR}
B.W R_BSP_RegisterProtectEnable
This time, the first instruction MRS R1, PRIMASK
in R_BSP_RegisterProtectEnable
throws the undefined instruction error instead.
It's really starting to stink of bad clock configuration, but this code is downloaded from Renesas website for this exact device so I don't dare tinker with it unless I know exactly what to do. Hence my question.
UPD2: Internal clock divider in bsp_clock_cfg.h
didn't match the manufacturer's files! Either I made a typo or reused a file from a different project, and didn't notice a problem because /1 seems like an ok internal clock divider, but changing it to /2 fixed this error. Perhaps it was causing instruction fetch/prefetch from flash to only finish after attempted decode...
Note that this file is normally auto-generated by Renesas software from XML configs (which include default values). I found those XMLs but needed to manually create headers with all required macros from them.
Thanks to everyone for the brainstorm session!
Internal clock divider needed to be set to CGC_SYS_CLOCK_DIV_2
(default from manufacturer's XML configs) instead of CGC_SYS_CLOCK_DIV_1
. I made some mistake when creating the SDK.