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} nt"
/* Set R0 to point to the task stack pointer. */
"STMDB SP,{SP}^ nt"
"NOP nt"
"SUB SP, SP, #4 nt"
"LDMIA SP!,{R0} nt"
/* Push the return address onto the stack. */
"STMDB R0!, {LR} nt"
/* Now we have saved LR we can use it instead of R0. */
"MOV LR, R0 nt"
/* Pop R0 so we can save it onto the system mode stack. */
"LDMIA SP!, {R0} nt"
/* Push all the system mode registers onto the task stack. */
"STMDB LR,{R0-LR}^ nt"
"NOP nt"
"SUB LR, LR, #60 nt"
/*Save floating-point registers*/
"vpush {d0-d15} nt"
"vpush {d16-d31} nt"
"vmrs r1, FPSCR nt"
"push {r1} nt"
"vmrs r1, FPEXC nt"
"push {r1} nt"
/* Push the SPSR onto the task stack. */
"MRS R0, SPSR nt"
"STMDB LR!, {R0} nt"
"LDR R0, =ulCriticalNesting nt"
"LDR R0, [R0] nt"
"STMDB LR!, {R0} nt"
/* Store the new top of stack for the task. */
"LDR R0, =pxCurrentTCB nt"
"LDR R0, [R0] nt"
"STR LR, [R0] nt"
);
( 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 nt"
"LDR R0, [R0] nt"
"LDR LR, [R0] nt"
/* The critical nesting depth is the first item on the stack. */
/* Load it into the ulCriticalNesting variable. */
"LDR R0, =ulCriticalNesting nt"
"LDMFD LR!, {R1} nt"
"STR R1, [R0] nt"
/* Get the SPSR from the stack. */
"LDMFD LR!, {R0} nt"
"MSR SPSR, R0 nt"
/*Restore floating-point registers*/
"pop {r2} nt"
"vmsr FPEXC, r2 nt"
"pop {r2} nt"
"vmsr FPSCR, r2 nt"
"vpop {d16-d31} nt"
"vpop {d0-d15} nt"
/* Restore all system mode registers for the task. */
"LDMFD LR, {R0-R14}^ nt"
"NOP nt"
/* Restore the return address. */
"LDR LR, [LR, #+60] nt"
/* And return - correcting the offset in the LR to obtain the */
/* correct address. */
"SUBS PC, LR, #4 nt"
"NOP nt"
"NOP nt"
);
( void ) ulCriticalNesting;
( void ) pxCurrentTCB;
}
Am I looking in the right place in the code?