-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
XEmacPs_GetQxOffset(), which is called from XEmacPs_IntrHandler(), contains "u32 Map", a local C-array with an initializer, which is assigned every time the function is called. When my compiler compiles this (gcc + FreeRTOS on Cortex-A9), it uses memcpy to materialize the array on the stack, resulting in memcpy being called from the ISR. Many toolchains provide optimized memcpy implementations that may use FPU registers. In e.g. FreeRTOS Cortex-A ports, the FPU context is generally not preserved for interrupts, which makes memcpy unsafe for use in interrupts (see e.g. https://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors). So if a task uses memcpy (or any other FPU operation), any memcpy-usage in an ISR could trash the FPU state.
This is likely compiler dependent. Turning the "u32 Map" into a "static const u32 Map" appears to entirely resolve the issue, at least with my compiler, as the array is no longer initialized every time the function is called at runtime, and memcpy is no longer included when looking at the disassembly. This should be safe across compilers, and it also reduces ISR stack usage.
I discovered the bug when I noticed that data I copied with memcpy contained corrupted chunks if I received ethernet interrupts during the tasks memcpy execution. I was able to reliably reproduce this, and confirmed that "static const" for "u32 Map" resolved it.
My disassembly code for XEmacPs_GetQxOffset, which shows that memcpy is being used (9th instruction) is shown below:
00117518 <XEmacPs_GetQxOffset>:
117518: e92d4030 push {r4, r5, lr}
11751c: e1a04001 mov r4, r1
117520: e24dd064 sub sp, sp, #100 @ 0x64
117524: e3021780 movw r1, #10112 @ 0x2780
117528: e1a05000 mov r5, r0
11752c: e3a02060 mov r2, #96 @ 0x60
117530: e3401012 movt r1, #18
117534: e1a0000d mov r0, sp
117538: ebffa696 bl 100f98 <memcpy>
11753c: e3540004 cmp r4, #4
117540: 8a000005 bhi 11755c <XEmacPs_GetQxOffset+0x44>
117544: e0844105 add r4, r4, r5, lsl #2
117548: e28d3060 add r3, sp, #96 @ 0x60
11754c: e0834104 add r4, r3, r4, lsl #2
117550: e5140060 ldr r0, [r4, #-96] @ 0xffffffa0
117554: e28dd064 add sp, sp, #100 @ 0x64
117558: e8bd8030 pop {r4, r5, pc}
11755c: e30336f0 movw r3, #14064 @ 0x36f0
117560: e3030740 movw r0, #14144 @ 0x3740
117564: e59f200c ldr r2, [pc, #12] @ 117578 <XEmacPs_GetQxOffset+0x60>
117568: e3403012 movt r3, #18
11756c: e3a0107f mov r1, #127 @ 0x7f
117570: e3400012 movt r0, #18
117574: fa000172 blx 117b44 <__assert_func>
117578: 001227e0 .word 0x001227e0