mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-20 05:21:59 -04:00
Comment the new MicroBlaze port layer files.
This commit is contained in:
parent
0e12cd0768
commit
f90794f05a
|
@ -68,47 +68,55 @@
|
||||||
#include <xil_exception.h>
|
#include <xil_exception.h>
|
||||||
#include <microblaze_exceptions_g.h>
|
#include <microblaze_exceptions_g.h>
|
||||||
|
|
||||||
/* Tasks are started with a critical section nesting of 0 - however prior
|
/* Tasks are started with a critical section nesting of 0 - however, prior to
|
||||||
to the scheduler being commenced we don't want the critical nesting level
|
the scheduler being commenced interrupts should not be enabled, so the critical
|
||||||
to reach zero, so it is initialised to a high value. */
|
nesting variable is initialised to a non-zero value. */
|
||||||
#define portINITIAL_NESTING_VALUE ( 0xff )
|
#define portINITIAL_NESTING_VALUE ( 0xff )
|
||||||
|
|
||||||
/* The bit within the MSR register that enabled/disables interrupts. */
|
/* The bit within the MSR register that enabled/disables interrupts. */
|
||||||
#define portMSR_IE ( 0x02U )
|
#define portMSR_IE ( 0x02U )
|
||||||
|
|
||||||
|
/* If the floating point unit is included in the MicroBlaze build, then the
|
||||||
|
FSR register is saved as part of the task context. portINITIAL_FSR is the value
|
||||||
|
given to the FSR register when the initial context is set up for a task being
|
||||||
|
created. */
|
||||||
#define portINITIAL_FSR ( 0U )
|
#define portINITIAL_FSR ( 0U )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialise the interrupt controller instance.
|
* Initialise the interrupt controller instance.
|
||||||
*/
|
*/
|
||||||
static portBASE_TYPE prvInitialiseInterruptController( void );
|
static long prvInitialiseInterruptController( void );
|
||||||
|
|
||||||
/*
|
/* Ensure the interrupt controller instance variable is initialised before it is
|
||||||
* Call an application provided callback to set up the periodic interrupt used
|
* used, and that the initialisation only happens once.
|
||||||
* for the RTOS tick. Using an application callback allows the application
|
|
||||||
* writer to decide
|
|
||||||
*/
|
*/
|
||||||
extern void vApplicationSetupTimerInterrupt( void );
|
static long prvEnsureInterruptControllerIsInitialised( void );
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Counts the nesting depth of calls to portENTER_CRITICAL(). Each task
|
/* Counts the nesting depth of calls to portENTER_CRITICAL(). Each task
|
||||||
maintains it's own count, so this variable is saved as part of the task
|
maintains its own count, so this variable is saved as part of the task
|
||||||
context. */
|
context. */
|
||||||
volatile unsigned portBASE_TYPE uxCriticalNesting = portINITIAL_NESTING_VALUE;
|
volatile unsigned portBASE_TYPE uxCriticalNesting = portINITIAL_NESTING_VALUE;
|
||||||
|
|
||||||
/* To limit the amount of stack required by each task, this port uses a
|
/* This port uses a separate stack for interrupts. This prevents the stack of
|
||||||
separate stack for interrupts. */
|
every task needing to be large enough to hold an entire interrupt stack on top
|
||||||
|
of the task stack. */
|
||||||
unsigned long *pulISRStack;
|
unsigned long *pulISRStack;
|
||||||
|
|
||||||
/* If an interrupt requests a context switch then ulTaskSwitchRequested will
|
/* If an interrupt requests a context switch, then ulTaskSwitchRequested will
|
||||||
get set to 1, which in turn will cause vTaskSwitchContext() to be called
|
get set to 1. ulTaskSwitchRequested is inspected just before the main interrupt
|
||||||
prior to a task context getting restored on exit from the interrupt. This
|
handler exits. If, at that time, ulTaskSwitchRequested is set to 1, the kernel
|
||||||
mechanism is used as a single interrupt can cause multiple peripherals handlers
|
will call vTaskSwitchContext() to ensure the task that runs immediately after
|
||||||
to get called, and vTaskSwitchContext() should not get called in each handler. */
|
the interrupt exists is the highest priority task that is able to run. This is
|
||||||
|
an unusual mechanism, but is used for this port because a single interrupt can
|
||||||
|
cause the servicing of multiple peripherals - and it is inefficient to call
|
||||||
|
vTaskSwitchContext() multiple times as each peripheral is serviced. */
|
||||||
volatile unsigned long ulTaskSwitchRequested = 0UL;
|
volatile unsigned long ulTaskSwitchRequested = 0UL;
|
||||||
|
|
||||||
/* The instance of the interrupt controller used by this port. */
|
/* The instance of the interrupt controller used by this port. This is required
|
||||||
|
by the Xilinx library API functions. */
|
||||||
static XIntc xInterruptControllerInstance;
|
static XIntc xInterruptControllerInstance;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
@ -117,7 +125,7 @@ static XIntc xInterruptControllerInstance;
|
||||||
* Initialise the stack of a task to look exactly as if a call to
|
* Initialise the stack of a task to look exactly as if a call to
|
||||||
* portSAVE_CONTEXT had been made.
|
* portSAVE_CONTEXT had been made.
|
||||||
*
|
*
|
||||||
* See the header file portable.h.
|
* See the portable.h header file.
|
||||||
*/
|
*/
|
||||||
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
|
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
|
||||||
{
|
{
|
||||||
|
@ -127,16 +135,7 @@ const unsigned long ulR13 = ( unsigned long ) &_SDA_BASE_;
|
||||||
|
|
||||||
/* Place a few bytes of known values on the bottom of the stack.
|
/* Place a few bytes of known values on the bottom of the stack.
|
||||||
This is essential for the Microblaze port and these lines must
|
This is essential for the Microblaze port and these lines must
|
||||||
not be omitted. The parameter value will overwrite the
|
not be omitted. */
|
||||||
0x22222222 value during the function prologue. */
|
|
||||||
*pxTopOfStack = ( portSTACK_TYPE ) 0x11111111;
|
|
||||||
pxTopOfStack--;
|
|
||||||
*pxTopOfStack = ( portSTACK_TYPE ) 0x22222222;
|
|
||||||
pxTopOfStack--;
|
|
||||||
*pxTopOfStack = ( portSTACK_TYPE ) 0x33333333;
|
|
||||||
pxTopOfStack--;
|
|
||||||
|
|
||||||
/* The debugger will look at the previous stack frame. */
|
|
||||||
*pxTopOfStack = ( portSTACK_TYPE ) 0x00000000;
|
*pxTopOfStack = ( portSTACK_TYPE ) 0x00000000;
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
*pxTopOfStack = ( portSTACK_TYPE ) 0x00000000;
|
*pxTopOfStack = ( portSTACK_TYPE ) 0x00000000;
|
||||||
|
@ -172,6 +171,8 @@ const unsigned long ulR13 = ( unsigned long ) &_SDA_BASE_;
|
||||||
*pxTopOfStack = ( portSTACK_TYPE ) 0x04; /* R4 - return values and temporaries. */
|
*pxTopOfStack = ( portSTACK_TYPE ) 0x04; /* R4 - return values and temporaries. */
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
*pxTopOfStack = ( portSTACK_TYPE ) pvParameters;/* R5 contains the function call parameters. */
|
*pxTopOfStack = ( portSTACK_TYPE ) pvParameters;/* R5 contains the function call parameters. */
|
||||||
|
|
||||||
|
#ifdef portPRE_LOAD_STACK_FOR_DEBUGGING
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
*pxTopOfStack = ( portSTACK_TYPE ) 0x06; /* R6 - other parameters and temporaries. Used as the return address from vPortTaskEntryPoint. */
|
*pxTopOfStack = ( portSTACK_TYPE ) 0x06; /* R6 - other parameters and temporaries. Used as the return address from vPortTaskEntryPoint. */
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
|
@ -187,11 +188,17 @@ const unsigned long ulR13 = ( unsigned long ) &_SDA_BASE_;
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
*pxTopOfStack = ( portSTACK_TYPE ) 0x0c; /* R12 - temporaries. */
|
*pxTopOfStack = ( portSTACK_TYPE ) 0x0c; /* R12 - temporaries. */
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
|
#else
|
||||||
|
pxTopOfStack-= 8;
|
||||||
|
#endif
|
||||||
|
|
||||||
*pxTopOfStack = ( portSTACK_TYPE ) ulR13; /* R13 - read/write small data area. */
|
*pxTopOfStack = ( portSTACK_TYPE ) ulR13; /* R13 - read/write small data area. */
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
*pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* R14 - return address for interrupt. */
|
*pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* R14 - return address for interrupt. */
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
*pxTopOfStack = ( portSTACK_TYPE ) NULL; /* R15 - return address for subroutine. */
|
*pxTopOfStack = ( portSTACK_TYPE ) NULL; /* R15 - return address for subroutine. */
|
||||||
|
|
||||||
|
#ifdef portPRE_LOAD_STACK_FOR_DEBUGGING
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
*pxTopOfStack = ( portSTACK_TYPE ) 0x10; /* R16 - return address for trap (debugger). */
|
*pxTopOfStack = ( portSTACK_TYPE ) 0x10; /* R16 - return address for trap (debugger). */
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
|
@ -199,7 +206,13 @@ const unsigned long ulR13 = ( unsigned long ) &_SDA_BASE_;
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
*pxTopOfStack = ( portSTACK_TYPE ) 0x12; /* R18 - reserved for assembler and compiler temporaries. */
|
*pxTopOfStack = ( portSTACK_TYPE ) 0x12; /* R18 - reserved for assembler and compiler temporaries. */
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
|
#else
|
||||||
|
pxTopOfStack -= 4;
|
||||||
|
#endif
|
||||||
|
|
||||||
*pxTopOfStack = ( portSTACK_TYPE ) 0x00; /* R19 - must be saved across function calls. Callee-save. Seems to be interpreted as the frame pointer. */
|
*pxTopOfStack = ( portSTACK_TYPE ) 0x00; /* R19 - must be saved across function calls. Callee-save. Seems to be interpreted as the frame pointer. */
|
||||||
|
|
||||||
|
#ifdef portPRE_LOAD_STACK_FOR_DEBUGGING
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
*pxTopOfStack = ( portSTACK_TYPE ) 0x14; /* R20 - reserved for storing a pointer to the Global Offset Table (GOT) in Position Independent Code (PIC). Non-volatile in non-PIC code. Must be saved across function calls. Callee-save. Not used by FreeRTOS. */
|
*pxTopOfStack = ( portSTACK_TYPE ) 0x14; /* R20 - reserved for storing a pointer to the Global Offset Table (GOT) in Position Independent Code (PIC). Non-volatile in non-PIC code. Must be saved across function calls. Callee-save. Not used by FreeRTOS. */
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
|
@ -225,9 +238,12 @@ const unsigned long ulR13 = ( unsigned long ) &_SDA_BASE_;
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
*pxTopOfStack = ( portSTACK_TYPE ) 0x1f; /* R31 - must be saved across function calls. Callee-save. */
|
*pxTopOfStack = ( portSTACK_TYPE ) 0x1f; /* R31 - must be saved across function calls. Callee-save. */
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
|
#else
|
||||||
|
pxTopOfStack -= 13;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Return a pointer to the top of the stack we have generated so this can
|
/* Return a pointer to the top of the stack that has been generated so this
|
||||||
be stored in the task control block for the task. */
|
can be stored in the task control block for the task. */
|
||||||
return pxTopOfStack;
|
return pxTopOfStack;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
@ -238,12 +254,23 @@ extern void ( vPortStartFirstTask )( void );
|
||||||
extern unsigned long _stack[];
|
extern unsigned long _stack[];
|
||||||
|
|
||||||
/* Setup the hardware to generate the tick. Interrupts are disabled when
|
/* Setup the hardware to generate the tick. Interrupts are disabled when
|
||||||
this function is called. */
|
this function is called.
|
||||||
|
|
||||||
|
This port uses an application defined callback function to install the tick
|
||||||
|
interrupt handler because the kernel will run on lots of different
|
||||||
|
MicroBlaze and FPGA configurations - not all of which will have the same
|
||||||
|
timer peripherals defined or available. An example definition of
|
||||||
|
vApplicationSetupTimerInterrupt() is provided in the official demo
|
||||||
|
application that accompanies this port. */
|
||||||
vApplicationSetupTimerInterrupt();
|
vApplicationSetupTimerInterrupt();
|
||||||
|
|
||||||
/* Reuse the stack from main as the stack for the interrupts/exceptions. */
|
/* Reuse the stack from main() as the stack for the interrupts/exceptions. */
|
||||||
pulISRStack = ( unsigned long * ) _stack;
|
pulISRStack = ( unsigned long * ) _stack;
|
||||||
|
|
||||||
|
/* Ensure there is enough space for the functions called from the interrupt
|
||||||
|
service routines to write back into the stack frame of the caller. */
|
||||||
|
pulISRStack -= 2;
|
||||||
|
|
||||||
/* Restore the context of the first task that is going to run. From here
|
/* Restore the context of the first task that is going to run. From here
|
||||||
on, the created tasks will be executing. */
|
on, the created tasks will be executing. */
|
||||||
vPortStartFirstTask();
|
vPortStartFirstTask();
|
||||||
|
@ -268,7 +295,7 @@ extern void VPortYieldASM( void );
|
||||||
|
|
||||||
/* Perform the context switch in a critical section to assure it is
|
/* Perform the context switch in a critical section to assure it is
|
||||||
not interrupted by the tick ISR. It is not a problem to do this as
|
not interrupted by the tick ISR. It is not a problem to do this as
|
||||||
each task maintains it's own interrupt status. */
|
each task maintains its own interrupt status. */
|
||||||
portENTER_CRITICAL();
|
portENTER_CRITICAL();
|
||||||
{
|
{
|
||||||
/* Jump directly to the yield function to ensure there is no
|
/* Jump directly to the yield function to ensure there is no
|
||||||
|
@ -281,44 +308,93 @@ extern void VPortYieldASM( void );
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
void vPortEnableInterrupt( unsigned char ucInterruptID )
|
void vPortEnableInterrupt( unsigned char ucInterruptID )
|
||||||
|
{
|
||||||
|
long lReturn;
|
||||||
|
|
||||||
|
/* An API function is provided to enable an interrupt in the interrupt
|
||||||
|
controller because the interrupt controller instance variable is private
|
||||||
|
to this file. */
|
||||||
|
lReturn = prvEnsureInterruptControllerIsInitialised();
|
||||||
|
if( lReturn == pdPASS )
|
||||||
{
|
{
|
||||||
XIntc_Enable( &xInterruptControllerInstance, ucInterruptID );
|
XIntc_Enable( &xInterruptControllerInstance, ucInterruptID );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configASSERT( lReturn );
|
||||||
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
void vPortDisableInterrupt( unsigned char ucInterruptID )
|
void vPortDisableInterrupt( unsigned char ucInterruptID )
|
||||||
|
{
|
||||||
|
long lReturn;
|
||||||
|
|
||||||
|
/* An API function is provided to disable an interrupt in the interrupt
|
||||||
|
controller because the interrupt controller instance variable is private
|
||||||
|
to this file. */
|
||||||
|
lReturn = prvEnsureInterruptControllerIsInitialised();
|
||||||
|
|
||||||
|
if( lReturn == pdPASS )
|
||||||
{
|
{
|
||||||
XIntc_Disable( &xInterruptControllerInstance, ucInterruptID );
|
XIntc_Disable( &xInterruptControllerInstance, ucInterruptID );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configASSERT( lReturn );
|
||||||
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
portBASE_TYPE xPortInstallInterruptHandler( unsigned char ucInterruptID, XInterruptHandler pxHandler, void *pvCallBackRef )
|
portBASE_TYPE xPortInstallInterruptHandler( unsigned char ucInterruptID, XInterruptHandler pxHandler, void *pvCallBackRef )
|
||||||
{
|
{
|
||||||
static portBASE_TYPE xInterruptControllerInitialised = pdFALSE;
|
long lReturn;
|
||||||
portBASE_TYPE xReturn = XST_SUCCESS;
|
|
||||||
|
|
||||||
if( xInterruptControllerInitialised != pdTRUE )
|
/* An API function is provided to install an interrupt handler because the
|
||||||
|
interrupt controller instance variable is private to this file. */
|
||||||
|
|
||||||
|
lReturn = prvEnsureInterruptControllerIsInitialised();
|
||||||
|
|
||||||
|
if( lReturn == pdPASS )
|
||||||
{
|
{
|
||||||
xReturn = prvInitialiseInterruptController();
|
lReturn = XIntc_Connect( &xInterruptControllerInstance, ucInterruptID, pxHandler, pvCallBackRef );
|
||||||
xInterruptControllerInitialised = pdTRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( xReturn == XST_SUCCESS )
|
if( lReturn == XST_SUCCESS )
|
||||||
{
|
{
|
||||||
xReturn = XIntc_Connect( &xInterruptControllerInstance, ucInterruptID, pxHandler, pvCallBackRef );
|
lReturn = pdPASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( xReturn == XST_SUCCESS )
|
configASSERT( lReturn == pdPASS );
|
||||||
|
|
||||||
|
return lReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static long prvEnsureInterruptControllerIsInitialised( void )
|
||||||
{
|
{
|
||||||
xReturn = pdPASS;
|
static long lInterruptControllerInitialised = pdFALSE;
|
||||||
|
long lReturn;
|
||||||
|
|
||||||
|
/* Ensure the interrupt controller instance variable is initialised before
|
||||||
|
it is used, and that the initialisation only happens once. */
|
||||||
|
if( lInterruptControllerInitialised != pdTRUE )
|
||||||
|
{
|
||||||
|
lReturn = prvInitialiseInterruptController();
|
||||||
|
|
||||||
|
if( lReturn == pdPASS )
|
||||||
|
{
|
||||||
|
lInterruptControllerInitialised = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lReturn = pdPASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
return xReturn;
|
return lReturn;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handler for the timer interrupt.
|
* Handler for the timer interrupt. This is the handler that the application
|
||||||
|
* defined callback function vApplicationSetupTimerInterrupt() should install.
|
||||||
*/
|
*/
|
||||||
void vTickISR( void *pvUnused )
|
void vTickISR( void *pvUnused )
|
||||||
{
|
{
|
||||||
|
@ -327,13 +403,20 @@ extern void vApplicationClearTimerInterrupt( void );
|
||||||
/* Ensure the unused parameter does not generate a compiler warning. */
|
/* Ensure the unused parameter does not generate a compiler warning. */
|
||||||
( void ) pvUnused;
|
( void ) pvUnused;
|
||||||
|
|
||||||
|
/* This port uses an application defined callback function to clear the tick
|
||||||
|
interrupt because the kernel will run on lots of different MicroBlaze and
|
||||||
|
FPGA configurations - not all of which will have the same timer peripherals
|
||||||
|
defined or available. An example definition of
|
||||||
|
vApplicationClearTimerInterrupt() is provided in the official demo
|
||||||
|
application that accompanies this port. */
|
||||||
vApplicationClearTimerInterrupt();
|
vApplicationClearTimerInterrupt();
|
||||||
|
|
||||||
/* Increment the RTOS tick - this might cause a task to unblock. */
|
/* Increment the RTOS tick - this might cause a task to unblock. */
|
||||||
vTaskIncrementTick();
|
vTaskIncrementTick();
|
||||||
|
|
||||||
/* If we are using the preemptive scheduler then we also need to determine
|
/* If the preemptive scheduler is being used then a context switch should be
|
||||||
if this tick should cause a context switch. */
|
requested in case incrementing the tick unblocked a task, or a time slice
|
||||||
|
should cause another task to enter the Running state. */
|
||||||
#if configUSE_PREEMPTION == 1
|
#if configUSE_PREEMPTION == 1
|
||||||
/* Force vTaskSwitchContext() to be called as the interrupt exits. */
|
/* Force vTaskSwitchContext() to be called as the interrupt exits. */
|
||||||
ulTaskSwitchRequested = 1;
|
ulTaskSwitchRequested = 1;
|
||||||
|
@ -341,13 +424,13 @@ extern void vApplicationClearTimerInterrupt( void );
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static portBASE_TYPE prvInitialiseInterruptController( void )
|
static long prvInitialiseInterruptController( void )
|
||||||
{
|
{
|
||||||
portBASE_TYPE xStatus;
|
long lStatus;
|
||||||
|
|
||||||
xStatus = XIntc_Initialize( &xInterruptControllerInstance, configINTERRUPT_CONTROLLER_TO_USE );
|
lStatus = XIntc_Initialize( &xInterruptControllerInstance, configINTERRUPT_CONTROLLER_TO_USE );
|
||||||
|
|
||||||
if( xStatus == XST_SUCCESS )
|
if( lStatus == XST_SUCCESS )
|
||||||
{
|
{
|
||||||
/* Initialise the exception table. */
|
/* Initialise the exception table. */
|
||||||
Xil_ExceptionInit();
|
Xil_ExceptionInit();
|
||||||
|
@ -366,28 +449,21 @@ portBASE_TYPE xStatus;
|
||||||
|
|
||||||
/* Start the interrupt controller. Interrupts are enabled when the
|
/* Start the interrupt controller. Interrupts are enabled when the
|
||||||
scheduler starts. */
|
scheduler starts. */
|
||||||
xStatus = XIntc_Start( &xInterruptControllerInstance, XIN_REAL_MODE );
|
lStatus = XIntc_Start( &xInterruptControllerInstance, XIN_REAL_MODE );
|
||||||
|
|
||||||
/* Ensure the compiler does not generate warnings for the unused
|
if( lStatus == XST_SUCCESS )
|
||||||
iStatus valud if configASSERT() is not defined. */
|
{
|
||||||
( void ) xStatus;
|
lStatus = pdPASS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lStatus = pdFAIL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configASSERT( ( xStatus == ( portBASE_TYPE ) XST_SUCCESS ) )
|
configASSERT( lStatus == pdPASS );
|
||||||
|
|
||||||
/*_RB_ Exception test code. */
|
return lStatus;
|
||||||
#if 0
|
|
||||||
This does not cause the bralid address to be in the r17 register.
|
|
||||||
__asm volatile (
|
|
||||||
"bralid r15, 1234 \n"
|
|
||||||
"or r0, r0, r0 \n"
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
#if 0
|
|
||||||
xStatus /= 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return xStatus;
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,9 @@
|
||||||
#include <microblaze_exceptions_i.h>
|
#include <microblaze_exceptions_i.h>
|
||||||
#include <microblaze_exceptions_g.h>
|
#include <microblaze_exceptions_g.h>
|
||||||
|
|
||||||
|
/* The Xilinx library defined exception entry point stacks a number of
|
||||||
|
registers. These definitions are offsets from the stack pointer to the various
|
||||||
|
stacked register values. */
|
||||||
#define portexR3_STACK_OFFSET 4
|
#define portexR3_STACK_OFFSET 4
|
||||||
#define portexR4_STACK_OFFSET 5
|
#define portexR4_STACK_OFFSET 5
|
||||||
#define portexR5_STACK_OFFSET 6
|
#define portexR5_STACK_OFFSET 6
|
||||||
|
@ -74,24 +77,42 @@
|
||||||
#define portexMSR_STACK_OFFSET 19
|
#define portexMSR_STACK_OFFSET 19
|
||||||
#define portexR19_STACK_OFFSET -1
|
#define portexR19_STACK_OFFSET -1
|
||||||
|
|
||||||
#define portexESR_DS_MASK 0x00001000UL
|
/* This is defined to equal the size, in bytes, of the stack frame generated by
|
||||||
|
the Xilinx standard library exception entry point. It is required to determine
|
||||||
|
the stack pointer value prior to the exception being entered. */
|
||||||
#define portexASM_HANDLER_STACK_FRAME_SIZE 84UL
|
#define portexASM_HANDLER_STACK_FRAME_SIZE 84UL
|
||||||
|
|
||||||
/* Exclude the entire file if the MicroBlaze is not configured to handle
|
/* The number of bytes a MicroBlaze instruction consumes. */
|
||||||
exceptions, or the application defined configuration item
|
#define portexINSTRUCTION_SIZE 4
|
||||||
|
|
||||||
|
/* Exclude this entire file if the MicroBlaze is not configured to handle
|
||||||
|
exceptions, or the application defined configuration constant
|
||||||
configINSTALL_EXCEPTION_HANDLERS is not set to 1. */
|
configINSTALL_EXCEPTION_HANDLERS is not set to 1. */
|
||||||
#if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 )
|
#if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 )
|
||||||
|
|
||||||
/* These are global volatiles to allow their inspection by a debugger. */
|
/* These variables are set in the exception entry code, before
|
||||||
|
vPortExceptionHandler is called. */
|
||||||
unsigned long *pulStackPointerOnFunctionEntry = NULL, ulBTROnFunctionEntry = 0UL;
|
unsigned long *pulStackPointerOnFunctionEntry = NULL, ulBTROnFunctionEntry = 0UL;
|
||||||
|
|
||||||
|
/* This is the structure that is filled with the MicroBlaze context as it
|
||||||
|
existed immediately prior to the exception occurrence. A pointer to this
|
||||||
|
structure is passed into the vApplicationExceptionRegisterDump() callback
|
||||||
|
function, if one is defined. */
|
||||||
static xPortRegisterDump xRegisterDump;
|
static xPortRegisterDump xRegisterDump;
|
||||||
|
|
||||||
|
/* This is the FreeRTOS exception handler that is installed for all exception
|
||||||
|
types. It is called from vPortExceptionHanlderEntry() - which is itself defined
|
||||||
|
in portasm.S. */
|
||||||
void vPortExceptionHandler( void *pvExceptionID );
|
void vPortExceptionHandler( void *pvExceptionID );
|
||||||
extern void vPortExceptionHandlerEntry( void *pvExceptionID );
|
extern void vPortExceptionHandlerEntry( void *pvExceptionID );
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* vApplicationExceptionRegisterDump() is a callback function that the
|
||||||
|
application can optionally define to receive a populated xPortRegisterDump
|
||||||
|
structure. If the application chooses not to define a version of
|
||||||
|
vApplicationExceptionRegisterDump() then this weekly defined default
|
||||||
|
implementation will be called instead. */
|
||||||
extern void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump ) __attribute__((weak));
|
extern void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump ) __attribute__((weak));
|
||||||
void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump )
|
void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump )
|
||||||
{
|
{
|
||||||
|
@ -106,6 +127,11 @@ void vPortExceptionHandler( void *pvExceptionID )
|
||||||
{
|
{
|
||||||
extern void *pxCurrentTCB;
|
extern void *pxCurrentTCB;
|
||||||
|
|
||||||
|
/* Fill an xPortRegisterDump structure with the MicroBlaze context as it
|
||||||
|
was immediately before the exception occurrence. */
|
||||||
|
|
||||||
|
/* First fill in the name and handle of the task that was in the Running
|
||||||
|
state when the exception occurred. */
|
||||||
xRegisterDump.xCurrentTaskHandle = pxCurrentTCB;
|
xRegisterDump.xCurrentTaskHandle = pxCurrentTCB;
|
||||||
xRegisterDump.pcCurrentTaskName = pcTaskGetTaskName( NULL );
|
xRegisterDump.pcCurrentTaskName = pcTaskGetTaskName( NULL );
|
||||||
|
|
||||||
|
@ -126,6 +152,7 @@ extern void *pxCurrentTCB;
|
||||||
xRegisterDump.ulR15_return_address_from_subroutine = pulStackPointerOnFunctionEntry[ portexR15_STACK_OFFSET ];
|
xRegisterDump.ulR15_return_address_from_subroutine = pulStackPointerOnFunctionEntry[ portexR15_STACK_OFFSET ];
|
||||||
xRegisterDump.ulR18 = pulStackPointerOnFunctionEntry[ portexR18_STACK_OFFSET ];
|
xRegisterDump.ulR18 = pulStackPointerOnFunctionEntry[ portexR18_STACK_OFFSET ];
|
||||||
xRegisterDump.ulR19 = pulStackPointerOnFunctionEntry[ portexR19_STACK_OFFSET ];
|
xRegisterDump.ulR19 = pulStackPointerOnFunctionEntry[ portexR19_STACK_OFFSET ];
|
||||||
|
xRegisterDump.ulMSR = pulStackPointerOnFunctionEntry[ portexMSR_STACK_OFFSET ];
|
||||||
|
|
||||||
/* Obtain the value of all other registers. */
|
/* Obtain the value of all other registers. */
|
||||||
xRegisterDump.ulR2_small_data_area = mfgpr( R2 );
|
xRegisterDump.ulR2_small_data_area = mfgpr( R2 );
|
||||||
|
@ -148,25 +175,14 @@ extern void *pxCurrentTCB;
|
||||||
xRegisterDump.ulR31 = mfgpr( R31 );
|
xRegisterDump.ulR31 = mfgpr( R31 );
|
||||||
xRegisterDump.ulR1_SP = ( ( unsigned long ) pulStackPointerOnFunctionEntry ) + portexASM_HANDLER_STACK_FRAME_SIZE;
|
xRegisterDump.ulR1_SP = ( ( unsigned long ) pulStackPointerOnFunctionEntry ) + portexASM_HANDLER_STACK_FRAME_SIZE;
|
||||||
xRegisterDump.ulBTR = ulBTROnFunctionEntry;
|
xRegisterDump.ulBTR = ulBTROnFunctionEntry;
|
||||||
xRegisterDump.ulMSR = pulStackPointerOnFunctionEntry[ portexMSR_STACK_OFFSET ];
|
|
||||||
xRegisterDump.ulEAR = mfear();
|
xRegisterDump.ulEAR = mfear();
|
||||||
xRegisterDump.ulESR = mfesr();
|
xRegisterDump.ulESR = mfesr();
|
||||||
xRegisterDump.ulEDR = mfedr();
|
xRegisterDump.ulEDR = mfedr();
|
||||||
|
|
||||||
|
/* Move the saved program counter back to the instruction that was executed
|
||||||
#ifdef THIS_IS_PROBABLY_INCORRECT
|
when the exception occurred. This is only valid for certain types of
|
||||||
if( ( xRegisterDump.ulESR * portexESR_DS_MASK ) != 0UL )
|
exception. */
|
||||||
{
|
xRegisterDump.ulPC = xRegisterDump.ulR17_return_address_from_some_exceptions - portexINSTRUCTION_SIZE;
|
||||||
xRegisterDump.ulPC = mfbtr();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
xRegisterDump.ulPC = xRegisterDump.ulR17_return_address_from_some_exceptions - 4;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
xRegisterDump.ulPC = xRegisterDump.ulR17_return_address_from_some_exceptions - 4;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if XPAR_MICROBLAZE_0_USE_FPU == 1
|
#if XPAR_MICROBLAZE_0_USE_FPU == 1
|
||||||
{
|
{
|
||||||
|
@ -178,6 +194,9 @@ extern void *pxCurrentTCB;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Also fill in a string that describes what type of exception this is.
|
||||||
|
The string uses the same ID names as defined in the MicroBlaze standard
|
||||||
|
library exception header files. */
|
||||||
switch( ( unsigned long ) pvExceptionID )
|
switch( ( unsigned long ) pvExceptionID )
|
||||||
{
|
{
|
||||||
case XEXC_ID_FSL :
|
case XEXC_ID_FSL :
|
||||||
|
@ -218,6 +237,11 @@ extern void *pxCurrentTCB;
|
||||||
#endif /* XPAR_MICROBLAZE_0_USE_FPU */
|
#endif /* XPAR_MICROBLAZE_0_USE_FPU */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* vApplicationExceptionRegisterDump() is a callback function that the
|
||||||
|
application can optionally define to receive the populated xPortRegisterDump
|
||||||
|
structure. If the application chooses not to define a version of
|
||||||
|
vApplicationExceptionRegisterDump() then the weekly defined default
|
||||||
|
implementation within this file will be called instead. */
|
||||||
vApplicationExceptionRegisterDump( &xRegisterDump );
|
vApplicationExceptionRegisterDump( &xRegisterDump );
|
||||||
|
|
||||||
/* Must not attempt to leave this function! */
|
/* Must not attempt to leave this function! */
|
||||||
|
|
|
@ -57,7 +57,10 @@
|
||||||
licensing and training services.
|
licensing and training services.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* FreeRTOS includes. */
|
||||||
#include "FreeRTOSConfig.h"
|
#include "FreeRTOSConfig.h"
|
||||||
|
|
||||||
|
/* Xilinx library includes. */
|
||||||
#include "microblaze_exceptions_g.h"
|
#include "microblaze_exceptions_g.h"
|
||||||
#include "xparameters.h"
|
#include "xparameters.h"
|
||||||
|
|
||||||
|
@ -250,7 +253,7 @@ back into the caller stack. */
|
||||||
|
|
||||||
/* This function is used to exit portRESTORE_CONTEXT() if the task being
|
/* This function is used to exit portRESTORE_CONTEXT() if the task being
|
||||||
returned to last left the Running state by calling taskYIELD() (rather than
|
returned to last left the Running state by calling taskYIELD() (rather than
|
||||||
being preempted by an interrupt. */
|
being preempted by an interrupt). */
|
||||||
.text
|
.text
|
||||||
.align 2
|
.align 2
|
||||||
exit_from_yield:
|
exit_from_yield:
|
||||||
|
@ -276,9 +279,7 @@ _interrupt_handler:
|
||||||
/* Stack the return address. */
|
/* Stack the return address. */
|
||||||
swi r14, r1, portR14_OFFSET
|
swi r14, r1, portR14_OFFSET
|
||||||
|
|
||||||
/* Switch to the ISR stack. The pulISRStack value has already been set to
|
/* Switch to the ISR stack. */
|
||||||
leave space for the caller function to write back into the stack of this
|
|
||||||
function. */
|
|
||||||
lwi r1, r0, pulISRStack
|
lwi r1, r0, pulISRStack
|
||||||
|
|
||||||
/* The parameter to the interrupt handler. */
|
/* The parameter to the interrupt handler. */
|
||||||
|
|
|
@ -100,6 +100,8 @@ portBASE_TYPE xPortInstallInterruptHandler( unsigned char ucInterruptID, XInterr
|
||||||
void vPortEnableInterrupt( unsigned char ucInterruptID );
|
void vPortEnableInterrupt( unsigned char ucInterruptID );
|
||||||
void vPortDisableInterrupt( unsigned char ucInterruptID );
|
void vPortDisableInterrupt( unsigned char ucInterruptID );
|
||||||
|
|
||||||
|
void vApplicationSetupTimerInterrupt( void );
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Critical section macros. */
|
/* Critical section macros. */
|
||||||
|
|
Loading…
Reference in a new issue