Add optional FPU support to the MicroBlaze code.

Rearrange the order in which registers are saved to the stack in an interrupt to make it more logical, and introduce #defines for the offset from the stack pointer for each variable.
pull/4/head
Richard Barry 14 years ago
parent 4d287dd1bf
commit c9b5f43d11

@ -64,6 +64,7 @@
#include <string.h>
/* Hardware includes. */
#include <xparameters.h>
#include <xintc.h>
#include <xintc_i.h>
#include <xtmrctr.h>
@ -78,6 +79,7 @@ to reach zero, so it is initialised to a high value. */
/* The bit within the MSR register that enabled/disables interrupts. */
#define portMSR_IE ( 0x02U )
#define portINITIAL_FSR ( 0U )
/*-----------------------------------------------------------*/
/*
@ -138,6 +140,18 @@ const unsigned long ulR13 = ( unsigned long ) &_SDA_BASE_;
*pxTopOfStack = ( portSTACK_TYPE ) 0x00000000;
pxTopOfStack--;
#if XPAR_MICROBLAZE_0_USE_FPU == 1
/* The FSR value placed in the initial task context is just 0. */
*pxTopOfStack = portINITIAL_FSR;
pxTopOfStack--;
#endif
/* The MSR value placed in the initial task context should have interrupts
disabled. Each task will enable interrupts automatically when it enters
the running state for the first time. */
*pxTopOfStack = mfmsr() & ~portMSR_IE;
pxTopOfStack--;
/* First stack an initial value for the critical section nesting. This
is initialised to zero. */
*pxTopOfStack = ( portSTACK_TYPE ) 0x00;
@ -205,13 +219,6 @@ const unsigned long ulR13 = ( unsigned long ) &_SDA_BASE_;
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x1e; /* R30 - must be saved across function calls. Callee-save. */
pxTopOfStack--;
/* The MSR is stacked between R30 and R31. This should have interrupts
disabled. Each task will enable interrupts automatically when it enters
the running state for the first time. */
*pxTopOfStack = mfmsr() & ~portMSR_IE;
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x1f; /* R31 - must be saved across function calls. Callee-save. */
pxTopOfStack--;
@ -230,12 +237,8 @@ extern unsigned long _stack[];
this function is called. */
vApplicationSetupTimerInterrupt();
/* Reuse the stack from main as the stack for the interrupts/exceptions.
The value is adjusted slightly to allow functions called from the
interrupts/exceptions to write back into the stack of the interrupt/
exception function itself. */
/* Reuse the stack from main as the stack for the interrupts/exceptions. */
pulISRStack = ( unsigned long * ) _stack;
pulISRStack -= 2;
/* Restore the context of the first task that is going to run. From here
on, the created tasks will be executing. */

@ -58,6 +58,50 @@
*/
#include "FreeRTOSConfig.h"
#include "xparameters.h"
/* The context is oversized to allow functions called from the ISR to write
back into the caller stack. */
#if XPAR_MICROBLAZE_0_USE_FPU == 1
#define portCONTEXT_SIZE 136
#else
#define portCONTEXT_SIZE 132
#endif
/* Offsets from the stack pointer at which saved registers are placed. */
#define portR31_OFFSET 4
#define portR30_OFFSET 8
#define portR29_OFFSET 12
#define portR28_OFFSET 16
#define portR27_OFFSET 20
#define portR26_OFFSET 24
#define portR25_OFFSET 28
#define portR24_OFFSET 32
#define portR23_OFFSET 36
#define portR22_OFFSET 40
#define portR21_OFFSET 44
#define portR20_OFFSET 48
#define portR19_OFFSET 52
#define portR18_OFFSET 56
#define portR17_OFFSET 60
#define portR16_OFFSET 64
#define portR15_OFFSET 68
#define portR14_OFFSET 72
#define portR13_OFFSET 76
#define portR12_OFFSET 80
#define portR11_OFFSET 84
#define portR10_OFFSET 88
#define portR9_OFFSET 92
#define portR8_OFFSET 96
#define portR7_OFFSET 100
#define portR6_OFFSET 104
#define portR5_OFFSET 108
#define portR4_OFFSET 112
#define portR3_OFFSET 116
#define portR2_OFFSET 120
#define portCRITICAL_NESTING_OFFSET 124
#define portMSR_OFFSET 128
#define portFSR_OFFSET 132
.extern pxCurrentTCB
.extern XIntc_DeviceInterruptHandler
@ -73,47 +117,53 @@
.macro portSAVE_CONTEXT
/* Make room for the context on the stack. */
addik r1, r1, -132
/* Save r31 so it can then be used as a temporary. */
swi r31, r1, 4
/* Copy the msr into r31 - this is stacked later. */
mfs r31, rmsr
addik r1, r1, -portCONTEXT_SIZE
/* Stack general registers. */
swi r30, r1, 12
swi r29, r1, 16
swi r28, r1, 20
swi r27, r1, 24
swi r26, r1, 28
swi r25, r1, 32
swi r24, r1, 36
swi r23, r1, 40
swi r22, r1, 44
swi r21, r1, 48
swi r20, r1, 52
swi r19, r1, 56
swi r18, r1, 60
swi r17, r1, 64
swi r16, r1, 68
swi r15, r1, 72
swi r13, r1, 80
swi r12, r1, 84
swi r11, r1, 88
swi r10, r1, 92
swi r9, r1, 96
swi r8, r1, 100
swi r7, r1, 104
swi r6, r1, 108
swi r5, r1, 112
swi r4, r1, 116
swi r3, r1, 120
swi r2, r1, 124
swi r31, r1, portR31_OFFSET
swi r30, r1, portR30_OFFSET
swi r29, r1, portR29_OFFSET
swi r28, r1, portR28_OFFSET
swi r27, r1, portR27_OFFSET
swi r26, r1, portR26_OFFSET
swi r25, r1, portR25_OFFSET
swi r24, r1, portR24_OFFSET
swi r23, r1, portR23_OFFSET
swi r22, r1, portR22_OFFSET
swi r21, r1, portR21_OFFSET
swi r20, r1, portR20_OFFSET
swi r19, r1, portR19_OFFSET
swi r18, r1, portR18_OFFSET
swi r17, r1, portR17_OFFSET
swi r16, r1, portR16_OFFSET
swi r15, r1, portR15_OFFSET
/* R14 is saved later as it needs adjustment if a yield is performed. */
swi r13, r1, portR13_OFFSET
swi r12, r1, portR12_OFFSET
swi r11, r1, portR11_OFFSET
swi r10, r1, portR10_OFFSET
swi r9, r1, portR9_OFFSET
swi r8, r1, portR8_OFFSET
swi r7, r1, portR7_OFFSET
swi r6, r1, portR6_OFFSET
swi r5, r1, portR5_OFFSET
swi r4, r1, portR4_OFFSET
swi r3, r1, portR3_OFFSET
swi r2, r1, portR2_OFFSET
/* Stack the critical section nesting value. */
lwi r3, r0, uxCriticalNesting
swi r3, r1, 128
lwi r18, r0, uxCriticalNesting
swi r18, r1, portCRITICAL_NESTING_OFFSET
/* Stack MSR. */
mfs r18, rmsr
swi r18, r1, portMSR_OFFSET
#if XPAR_MICROBLAZE_0_USE_FPU == 1
/* Stack FSR. */
mfs r18, rfsr
swi r18, r1, portFSR_OFFSET
#endif
/* Save the top of stack value to the TCB. */
lwi r3, r0, pxCurrentTCB
@ -124,60 +174,66 @@
.macro portRESTORE_CONTEXT
/* Load the top of stack value from the TCB. */
lwi r3, r0, pxCurrentTCB
lw r1, r0, r3
lwi r18, r0, pxCurrentTCB
lw r1, r0, r18
/* Restore the general registers. */
lwi r31, r1, 4
lwi r30, r1, 12
lwi r29, r1, 16
lwi r28, r1, 20
lwi r27, r1, 24
lwi r26, r1, 28
lwi r25, r1, 32
lwi r24, r1, 36
lwi r23, r1, 40
lwi r22, r1, 44
lwi r21, r1, 48
lwi r20, r1, 52
lwi r19, r1, 56
lwi r18, r1, 60
lwi r17, r1, 64
lwi r16, r1, 68
lwi r15, r1, 72
lwi r14, r1, 76
lwi r13, r1, 80
lwi r12, r1, 84
lwi r11, r1, 88
lwi r10, r1, 92
lwi r9, r1, 96
lwi r8, r1, 100
lwi r7, r1, 104
lwi r6, r1, 108
lwi r5, r1, 112
lwi r4, r1, 116
lwi r2, r1, 124
lwi r31, r1, portR31_OFFSET
lwi r30, r1, portR30_OFFSET
lwi r29, r1, portR29_OFFSET
lwi r28, r1, portR28_OFFSET
lwi r27, r1, portR27_OFFSET
lwi r26, r1, portR26_OFFSET
lwi r25, r1, portR25_OFFSET
lwi r24, r1, portR24_OFFSET
lwi r23, r1, portR23_OFFSET
lwi r22, r1, portR22_OFFSET
lwi r21, r1, portR21_OFFSET
lwi r20, r1, portR20_OFFSET
lwi r19, r1, portR19_OFFSET
lwi r17, r1, portR17_OFFSET
lwi r16, r1, portR16_OFFSET
lwi r15, r1, portR15_OFFSET
lwi r14, r1, portR14_OFFSET
lwi r13, r1, portR13_OFFSET
lwi r12, r1, portR12_OFFSET
lwi r11, r1, portR11_OFFSET
lwi r10, r1, portR10_OFFSET
lwi r9, r1, portR9_OFFSET
lwi r8, r1, portR8_OFFSET
lwi r7, r1, portR7_OFFSET
lwi r6, r1, portR6_OFFSET
lwi r5, r1, portR5_OFFSET
lwi r4, r1, portR4_OFFSET
lwi r3, r1, portR3_OFFSET
lwi r2, r1, portR2_OFFSET
/* Reload the rmsr from the stack. */
lwi r3, r1, 8
mts rmsr, r3
lwi r18, r1, portMSR_OFFSET
mts rmsr, r18
#if XPAR_MICROBLAZE_0_USE_FPU == 1
/* Reload the FSR from the stack. */
lwi r18, r1, portFSR_OFFSET
mts rfsr, r18
#endif
/* Load the critical nesting value. */
lwi r3, r1, 128
swi r3, r0, uxCriticalNesting
lwi r18, r1, portCRITICAL_NESTING_OFFSET
swi r18, r0, uxCriticalNesting
/* Test the critical nesting value. If it is non zero then the task last
exited the running state using a yield. If it is zero, then the task
last exited the running state through an interrupt. */
xori r3, r3, 0
bnei r3, exit_from_yield
xori r18, r18, 0
bnei r18, exit_from_yield
/* r3 was being used as a temporary. Now restore its true value from the
/* r18 was being used as a temporary. Now restore its true value from the
stack. */
lwi r3, r1, 120
lwi r18, r1, portR18_OFFSET
/* Remove the stack frame. */
addik r1, r1, 132
addik r1, r1, portCONTEXT_SIZE
/* Return using rtid so interrupts are re-enabled as this function is
exited. */
@ -186,35 +242,33 @@
.endm
.text
.align 2
/* This function is used to exit portRESTORE_CONTEXT() if the task being
returned to last left the Running state by calling taskYIELD() (rather than
being preempted by an interrupt. */
.text
.align 2
exit_from_yield:
/* r3 was being used as a temporary. Now restore its true value from the
/* r18 was being used as a temporary. Now restore its true value from the
stack. */
lwi r3, r1, 120
lwi r18, r1, portR18_OFFSET
/* Remove the stack frame. */
addik r1, r1, 132
addik r1, r1, portCONTEXT_SIZE
/* Return to the task. */
rtsd r14, 0
or r0, r0, r0
.text
.align 2
_interrupt_handler:
portSAVE_CONTEXT
/* Stack msr. */
swi r31, r1, 8
/* Stack the return address. */
swi r14, r1, 76
swi r14, r1, portR14_OFFSET
/* Switch to the ISR stack. The pulISRStack value has already been set to
leave space for the caller function to write back into the stack of this
@ -232,17 +286,16 @@ _interrupt_handler:
portRESTORE_CONTEXT
.text
.align 2
VPortYieldASM:
portSAVE_CONTEXT
/* Stack msr. */
swi r31, r1, 8
/* Modify the return address so a return is done to the instruction after
the call to VPortYieldASM. */
addi r14, r14, 8
swi r14, r1, 76
swi r14, r1, portR14_OFFSET
/* Switch to use the ISR stack. */
lwi r1, r0, pulISRStack
@ -254,6 +307,8 @@ VPortYieldASM:
/* Restore the context of the next task scheduled to execute. */
portRESTORE_CONTEXT
.text
.align 2
vPortStartFirstTask:
portRESTORE_CONTEXT

Loading…
Cancel
Save