Yes there is a FPU present with my specific MCU.
The code is compiled with the -mfloat-abi=soft
flag otherwise the float variable never gets passed to R0
The FPU gets enabled via SCB->CPACR |= ((3UL << (10 * 2)) | (3UL << (11 * 2)));
The assembly function;
sqrt_func:
VLDR.32 S0, [R0] <-- hardfault
VSQRT.F32 S0, S0
VSTR.32 S0, [R0]
BX LR
C code calling said function;
extern float sqrt_func(float s);
float x = sqrt_func(1000000.0f);
But after stepping through, the MCU hard faults at VLDR.32 S0, [R0]
with the CFSR showing
CFSR
->BFARVALID
->PRECISERR
I see that the float is being passed correctly because that's the hex value for it the moment it hard faults;
R0
->0x49742400
S0
never gets loaded with anything.
I can't figure out why this is hard faulting, anyone have any ideas? I am trying to manually calculate the square root using the FPU.
Also what's weird is d13-d15 and s0-s31 registers are showing "0xx-2" but that's probably a quirk of the debugger not being able to pull the registers once it hardfaults.
Ok I'm just a dumbo and thought VLDR and VSTR operated differently for some reason but they're identical to LDR and STR. The value of the float was being passed to R0 but VLDR was trying to load the value at that address (0x49742400 which was my float value in hex) and that's either an invalid address or some sort of memory violation.
Instead you have to use VMOV.32
to copy register contents over;
sqrt_func:
VMOV.32 S0, R0
VSQRT.F32 S0, S0
VMOV.32 R0, S0
BX LR
And now it works.