Hi @mike919192 , thanks for the reply. I wasn’t talking about using the FPU in an interrupt, I agree that we shouldn’t. I am discussing about glibc using the FPU for memcpy, memset, memcmp, so there is a high risk of FPU corruption in regular tasks when performing queue or stream buffer operations in ISR.
What I was trying to say is that the demo tests do call FreeRTOS code in ISR which uses those memory functions internally. Just one example is IntQueue.c which calls xQueueSendFromISR which has memcpy calls in it.
I’m not an expert in all the various libc implementations but at least with the default Xilinx toolchain, I have not seen any corruption due to those memory functions. The one place I expectedly have seen corruption was the link in my previous message to the double arithmetic asserts in the ISR code.
I thought about this some more, and I realized that most of the FreeRTOS code is in critical sections where further ISRs are disabled. This is one example. So correct me if I am wrong, but the FPU can be used in the critical sections because ISRs are disabled and the context does not need to be saved / restored. The issue occurs when the FPU is used outside of critical sections because it can be interrupted and thus the context needs to be saved / restored.
Actually, I suspect (I haven’t specifically studied this) that most of the code, and time spent, is outside critical sections, as critical sections are tightly controlled, as a for instance, it will not walk a list inside a critical section, as that time isn’t strictly bounded.
Also, since on some ports, saving the FPU context is expensive, and thus some ports allow selectively marking tasks as using the FPU, and only those tasks will actually save FPU context, FreeRTOS use of the FPU would make most tasks need to be marked as using the FPU.
ISRs that change the FPU context MUST save that context, as the ISR can’t tell if it interrupted some section of code using the FPU. The issue here is that this can be somewhat expensive, and it has been noted that under some settings, GCC will use some of the FPU context for non-“FPU” operations, so either you need to pay for the FPU context save, or you make sure you never use (and preferably explicitly prevent) the cases where GCC uses the FPU registers.
Its been a while since I looked into this, but my memory is that it wasn’t so much “library” use, but inline implementation of standard library functions that might try to do this, which is why it becomes very sensitive to compiler options.
Thanks for the reply. I guess the question that I was trying to nail down an answer for was: Only considering the FreeRTOS kernel, is it a valid configuration for FPU context to be saved for tasks but not saved for ISR? This documentation page makes it sound like it is valid Using FreeRTOS on ARM Cortex-A9 Embedded Processors - FreeRTOS™ .
When I was talking about the critical sections, I was trying to explain why in practice I haven’t seen any corruption issues in the kernel with this configuration. The example I was pointing to was xQueueGenericSendFromISR which does use memcpy but in a critical section. If its not actually sound and I have just somehow been lucky to not observe any kernel corruption, then I have some project configurations I need to fix .
Part of the problem with detecting the issue is it requires a “lucky” timing of the interrupt in the middle of code that is using the FPU (or its registers). For many programs those are fairly isolated, and thus low chance of being hit.
Much of the kernel’s use of memcpy might be in critical sections so that aspect might be reduced.
The point is that knowing there is a possible problem that can be rare and only looking at “do I see instances of it” can be risky.
Knowing we have this potential for an ISR to use the FPU context, we need to either save the context, or make SURE the ISR won’t use it. “Experimenting” isn’t an answer, and wondering what you can “get away with” is playing with fire.
Very good suggestion! One way to confirm that ISRs are not inadvertently using the FPU is to examine the assembly output of all ISRs - a process you may need to repeat each time you change compiler options or upgrade the compiler version.
My current idea now that I understand the FPUSafeIRQHandler a lot better, is that it should be pretty easy to modify it to add an optional check when restoring the FPU registers to also check if the values were actually changed during the ISR. If the FPU registers were actually changed, set some global variable to indicate that the FPUSafeIRQHandler was indeed needed. The idea being that we can temporarily enable this check to show that the IRQ does not use the FPU and then leave the check disabled in production.
Its clear to me now that the FreeRTOS demo does require FPUSafeIRQHandler but I also have real applications with high frequency interrupts and not a lot of timing headroom where I intend to keep using IRQ handler without saving FPU. All I need to do is more definitively prove that the FPU is not modified.