spacesickpuppy wrote on Wednesday, September 11, 2013:
Hi,
I’m trying to implement floating-point support in the context switch on the FreeRTOS Zynq port. http://www.freertos.org/Interactive_Frames/Open_Frames.html?http://interactive.freertos.org/entries/23277857-Updated-Xilinx-FreeRTOS-port-for-Zynq-to-SDK-14-4-release
I’m running it on the ZC702 board and using GCC.
What I have tried is adding the following lines to the FIQHandler in port_asm_vectors.s and the portSAVE_CONTEXT and portRESTORE_CONTEXT routines:
vpush {d0-d7}
vpush {d16-d31}
vmrs r1, FPSCR
push {r1}
vmrs r1, FPEXC
push {r1}
pop {r2}
vmsr FPEXC, r2
pop {r2}
vmsr FPSCR, r2
vpop {d16-d31}
vpop {d0-d7}
The modifications seems not to help at all, floating-point values are still corrupted in tasks.
The save and restore routines look like this:
#define portSAVE_CONTEXT() \
{ \
extern volatile void * volatile pxCurrentTCB; \
extern volatile unsigned portLONG ulCriticalNesting; \
\
/* Push R0 as we are going to use the register. */ \
__asm volatile ( \
"STMDB SP!, {R0} \n\t" \
\
/* Set R0 to point to the task stack pointer. */ \
"STMDB SP,{SP}^ \n\t" \
"NOP \n\t" \
"SUB SP, SP, #4 \n\t" \
"LDMIA SP!,{R0} \n\t" \
\
/* Push the return address onto the stack. */ \
"STMDB R0!, {LR} \n\t" \
\
/* Now we have saved LR we can use it instead of R0. */ \
"MOV LR, R0 \n\t" \
\
/* Pop R0 so we can save it onto the system mode stack. */ \
"LDMIA SP!, {R0} \n\t" \
\
/* Push all the system mode registers onto the task stack. */ \
"STMDB LR,{R0-LR}^ \n\t" \
"NOP \n\t" \
"SUB LR, LR, #60 \n\t" \
\
/*Save floating-point registers*/ \
"vpush {d0-d15} \n\t" \
"vpush {d16-d31} \n\t" \
"vmrs r1, FPSCR \n\t" \
"push {r1} \n\t" \
"vmrs r1, FPEXC \n\t" \
"push {r1} \n\t" \
\
/* Push the SPSR onto the task stack. */ \
"MRS R0, SPSR \n\t" \
"STMDB LR!, {R0} \n\t" \
\
"LDR R0, =ulCriticalNesting \n\t" \
"LDR R0, [R0] \n\t" \
"STMDB LR!, {R0} \n\t" \
\
/* Store the new top of stack for the task. */ \
"LDR R0, =pxCurrentTCB \n\t" \
"LDR R0, [R0] \n\t" \
"STR LR, [R0] \n\t" \
); \
( void ) ulCriticalNesting; \
( void ) pxCurrentTCB; \
}
#define portRESTORE_CONTEXT() \
{ \
extern volatile void * volatile pxCurrentTCB; \
extern volatile unsigned portLONG ulCriticalNesting; \
\
/* Set the LR to the task stack. */ \
__asm volatile ( \
"LDR R0, =pxCurrentTCB \n\t" \
"LDR R0, [R0] \n\t" \
"LDR LR, [R0] \n\t" \
\
/* The critical nesting depth is the first item on the stack. */ \
/* Load it into the ulCriticalNesting variable. */ \
"LDR R0, =ulCriticalNesting \n\t" \
"LDMFD LR!, {R1} \n\t" \
"STR R1, [R0] \n\t" \
\
/* Get the SPSR from the stack. */ \
"LDMFD LR!, {R0} \n\t" \
"MSR SPSR, R0 \n\t" \
\
/*Restore floating-point registers*/ \
"pop {r2} \n\t" \
"vmsr FPEXC, r2 \n\t" \
"pop {r2} \n\t" \
"vmsr FPSCR, r2 \n\t" \
"vpop {d16-d31} \n\t" \
"vpop {d0-d15} \n\t" \
\
/* Restore all system mode registers for the task. */ \
"LDMFD LR, {R0-R14}^ \n\t" \
"NOP \n\t" \
\
/* Restore the return address. */ \
"LDR LR, [LR, #+60] \n\t" \
\
/* And return - correcting the offset in the LR to obtain the */ \
/* correct address. */ \
"SUBS PC, LR, #4 \n\t" \
"NOP \n\t" \
"NOP \n\t" \
); \
( void ) ulCriticalNesting; \
( void ) pxCurrentTCB; \
}
Am I looking in the right place in the code?