the float operation got corruption on zynq

hello, I am working on 150825 version of tcp lab code package, and now found an tricky issue, that is, the float operation got corruption when an fpga interrupt occurs periodically whose period is about 3ms. FreeRTOS is running on Zynq. The code snippets are as below: float operation running in one task:
real32t fGain = 0.0015f; real32t fValue = 0.0f; int32_t iValue = 0; for (idx = 0; idx < uiLen; idx ++) { iValue = puiSampBuf[idx]; fValue = (real32_t) iValue; pAdcSamp[idx] = fValue * fGain; } ISR routine:
void adcisr(void *CallbackRef) { XScuGicDisable(pScuGicInst, INTCADCINTID); … … … xQueueSendFromISR(PSMeasEventQueue, &event, &xTaskWoken); XScuGicEnable(pScuGicInst, INTCADCINT_ID); portYIELDFROMISR(xTaskWoken); } ———————————-. By some logging, I found some corruption, for example, iValue = 6517, but fValue = 1105510016.000000. The float operation is not triggered by interrupt, where they are running independently to each other. If I add “volatile” on float variable, I notice the corruption occurring frequency go down, but still occur. If I add the macro definition of portTASKUSESFLOATING_POINT() at the beginning of task entry function (not add into all tasks with float operation, but add into the task that capture float corruption), the issue still occur. Really an tricky issue, I don’t know how to handle it so far. Please give me help. Thank you!

the float operation got corruption on zynq

Search for “Note for GCC (and possibly other compiler) users” on the following page: http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html – I think this is most likely your problem. xQueueSendFromISR() will call memcpy(), and it is likely the GCC implementation of memcpy() is using FPU registers – hence your corruption. There are a couple of ways around this: 1) Provide your own basic implementations of the library functions that are used. For example, this file, which is from the official FreeRTOS distribution, contains basic and unoptimised implementations of memcpy, memset and memcmp which you could copy: https://sourceforge.net/p/freertos/code/HEAD/tree/trunk/FreeRTOS/Demo/CORTEXA9Zynq_ZC702/RTOSDemo/src/main.c 2) Use the head revision FreeRTOS code from the repository, found here: https://sourceforge.net/p/freertos/code/HEAD/tree/trunk/FreeRTOS/Source/portable/GCC/ARM_CA9/. In that code, if you rename your vApplicationIRQHandler() to vApplicationFPUSafeIRQHandler() (that is the callback function provided by your application) then all interrupts will be given a floating point context too. Regards.

the float operation got corruption on zynq

It is now quite stable, my compress test has already run stably for about 30 minutes and now is still running, after doing the following updates as you pointed out: 1) update three functions of memcpy(), memcpy() and memset(); 2) set configUSETASKFPU_SUPPORT = 2; 3) update three files, port.c, portASM.c and portmacro.h 4) rename to vApplicationFPUSafeIRQHandler() When I rename to vApplicationFPUSafeIRQHandler(), I compare the latest version with my version, and found there two additional lines of code in latest version as below:
/* Re-enable interrupts. */ __asm ( “cpsie i” );
I don’t understand why they are here and copied to my code, and the float corruption still occur, after I remove the two additional lines, no float corruption occur. So, what’s the meaning of that two lines of code? Thanks.

the float operation got corruption on zynq

Are these lines in the callback function, or in the port layer itself? The line re-enables interrupts (that much is obvious from the comment ;o) – I think that was always done to allow interrupts to nest, the difference is the callback is now called before interrupts are re-enabled to allow the application writer the option of using nested interrupts or now. If you re-enable interrupts in the interrupt handler callback (by including the line) then interrupts can nest. If you omit the line then interrupts won’t nest. Note that interrupts nesting or not does not change the fact that corruption will occur if the interrupt uses FPU registers. Defining your own memcpy(), etc., prevents the library from doing that though.