STM32F3/F4 FPU Advice...

mudestinator wrote on Tuesday, December 25, 2012:

I have a STM32F3 Discovery and I have ported FreeRTOS to it.  My tool chain is GCC based.  I used information from two separate supported ports.  They were the CORTEX_M4F_Infineon_XMC4500_GCC_Atollic and the second was the CORTEX_M4F_STM32F407ZG-SK.  The first port had the correct tool chain, but wrong micro controller manufacturer.  The second almost the correct micro controller, but the wrong tool chain.  The port works and currently has two (2) components designed specifically to test the hardware FPU operation.  The first component uses the eight (8) math tasks from the flop (flop.c) tests.  These tasks have been modified for single precision operation, because the hardware FPU is single precision.  The second component is a single instance of the register test task (in assembly).  The resulting demo runs with no errors.

Both of the supported parent ports run with two (2) instances of the register test tasks (in assembly).  Unfortunately, I am only able to get one instance to run with the flops tests.  It appear that one register test task causes the other to fail, but does not effect the flop tests. 

I believe that  the FPU is fully operational and that FreeRTOS running properly.  However, I am troubled that I can not get the  second instance of the register test task running successfully.  Any advice on how to proceed would be most appreciated.

rtel wrote on Tuesday, December 25, 2012:

These tasks have been modified for single precision operation,

There are a set of standard demo tasks that use single precision in FreeRTPS/demo/common/sp_flop.c.

It appear that one register test task causes the other to fail, but does not effect the flop tests.

The flop tests only use a subset of the registers, whereas the reg test tasks use all the registers.

To start with run just one register test task by itself (comment out all the other tasks, including the check task, etc.).  Run the register test task at priority 1 so even the idle task does not run.  You can put a break point in the error loop within the register check task to let you know if it fails.

Once that has run for a few minutes (no point running it longer than that if nothing else is running) then add in the second register test task also at priority 1 - now you will have just the two register test tasks and nothing else.  Again put a break point in the error loop of the second register test task.

Do the tasks run now?  If not, determine which register is getting corrupted by looking at the registers in the debugger window, and if necessary stepping through the code (you will have to manually set the program counter back to the top of the test loop to break out of the error loop.

Regards.

mudestinator wrote on Tuesday, December 25, 2012:

Thank you for the sage advice.  All of the tasks are running properly.  The error was a typo introduced while trying to make the GCC assembler happy with what was originally an IAR assembly file.  I had further complicated the issue by converting the contents of the assembly file into inline assembly.  I do not know what motivated me to add that complication.  The assembly file should have modified only enough to make the GCC assembler happy.  That would have minimized the chance of introducing an error.  Changing the task priority to 1 was the key to solving the issue.  Thank you again for your valuable assistance.

Since the FPU is single precision, is the FPU utilized when double precision operations are performed?  Essentially, should I ensure that all of the floating point operations in my project are single precision to get the most bang for my buck?  Thank you for your advice.

rtel wrote on Tuesday, December 25, 2012:

You will have to check the assembly code output by the compiler to know if the FPU is used for double precision operations, but in my experience I have found that double precision operations are emulated in software if you have a single precision FPU.

I have also found you have to be extremely careful in how you write your C code.  For example:

float x = 1.1, y; /* Define single precision floats. */
y = x * 2.0; /* Multiple by a constant. */

will result in x being promoted (in line with the C promotion rules) to a double, the calculation being done as a double precision emulated operation, then the result assigned to the single precision y.  A lengthy operation.  To avoid this you have to explicity state the type of constants as in:

y = x * 2.0F;

Then that will be one hardware multiplication - many many times faster.

Regards.

mudestinator wrote on Tuesday, December 25, 2012:

Thank you again for awesome information/advice.  As I stated earlier, my tool chain is GCC based.  I was hoping the using the following optimization option would simplify things.  I was also planning to test its effect by examining the assembly code output.  A technique that I just recently learned (i.e. last post).

-fsingle-precision-constant
Treat floating point constant as single precision constant instead of implicitly converting it to double precision constant.

I will post my findings to the forum.