2018-03-16 08:57 AM
Hello,
I have an olimexe407 board and I am creating an array with floats (-1 to 1) that I'm calculating and then I am converting them to q31 into 3 different buffers.
I initially tried doing this converting it to one buffer and then calling arm_float_to_q31 and it worked, I verified the values manually, by code and by converting them to float from q31 and comparing the initial float buffer and the final one. The problem is that when I added the second and third buffers, I noticed that it was causing a hard fault.
After a while of debugging I noticed that the fault occurred whenever it was doing a vstr instruction (even though it had been doing other float instructions properly until then). At that moment I was doing optimization level 3, which is probably why it was generating the vstr instruction (haven't tried it again after optimization went to none), but still ... the compiler shouldn't be generating an incorrect instruction (IF IT IS and incorrect instruction).
As stated above I am using the olimex board, and I am programming it on eclipse with the arm-none-eabi- tools
PS: At some point I also tried moving a bunch of floats to a struct and in the final float it did the vstr instructon and it failed the same way, that's how I think that it's probably not a library bug (thounsands of people use it ... probably someone else would've found it waaay before me). I turned this around by forcing a memcpy instead of a simple assignment.
#floating-point #stm32f42018-03-16 09:22 AM
To allow floating point instructions, you would also need to enable the FPU.
If you don't want floating point instructions (even if the MCU would support it), build with 'float-abi=soft', and/or select the proper library.
2018-03-16 10:53 AM
,
,
And enabled on the MCU side
/* FPU settings ------------------------------------------------------------*/
,
♯ if (__FPU_PRESENT == 1) &,&, (__FPU_USED == 1),
, SCB->,CPACR |= ((3UL <,<, 10*2)|(3UL <,<, 11*2)), , /* set CP10 and CP11 Full Access */,
♯ endifFrequently in SystemInit(), or in assembler in startup.s
2018-03-16 11:07 AM
I forgot to mention it but I am already compiling with float-eabi=hard .. __FPU_PRESENT=1
2018-03-16 11:33 AM
So is it faulting because it doesn't support the instruction, the memory reference is wrong, or there is an alignment issue with the address?
If your Hard Fault handler is a while(1) loop, consider something more helpful...
2018-03-16 01:19 PM
The most likely culprit is that stm32f407 does not support the instruction .... because alignment was one of my first thoughts and also the memory reference is correct.
BUT the microcontroller is correctly configured in the project. cortex-m4 .. thumb instruction set ... fp instructions=hard .. fpu type = fpv4-sp-d16 and unaligned access = enabled ... so the compiler should know the instructions it doesn't support ... or at least it should right??? I can do aeorkarounds as stated above, but I'd prefer not having to do a workaround and use the arm_float_to_q31 function withour worries
2018-03-21 05:30 PM
Sorry to bother you still, but the error persists. I enabled __FPU_PRESENT and __FPU_USED, I can see that it is setting the bits for cp10 and cp11 (FPU and lazy stacking if I'm not mistaken ... SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */)
I am doing some floating point calculations and noticed in the disassembly that it is not using a floating point instruction, however after the last calculation is done it performs a vmov instruction and nothing bad occurs. The problem is that when I'm using the arm_float_to_q31 or doing some assignments (from float to float) it generates the vstr instruction and then the hard fault occurs. I just nocied that one of the floats is unaligned, but it's only unaligned when I try to move floats from variables to a structure, when I'm using the convert function they are all aligned and it still happens. Any ideas?
2018-03-21 05:54 PM
When presenting these types of issues be specific about the tools and versions being used. Condense the example to its simplest form, ideally in a self contained project or using a makefile. Then ZIP and attach a single file.
I really shouldn't be necessary to hypothesis about the cause of this kind of gross and repeatable failure mechanism.
The FPU is relatively simple compared to Intel ones, some instructions will inline, but most will go through helper functions or be compounded. The FPU also doesn't support doubles on the F4, and use in general is dependent on the compiler, settings, and supporting libraries. Something like Keil is going to be significantly simpler than GNU, and compiler/linker settings a single check box item.
For structures check ♯ pragma pack() options, doubles can be problematic in file and byte stream protocols. Use memcpy() in situations where LDRD/STRD would fault.