#include <xil_exception.h>\r
#include <microblaze_exceptions_g.h>\r
\r
-/* Tasks are started with a critical section nesting of 0 - however prior\r
-to the scheduler being commenced we don't want the critical nesting level\r
-to reach zero, so it is initialised to a high value. */\r
+/* Tasks are started with a critical section nesting of 0 - however, prior to \r
+the scheduler being commenced interrupts should not be enabled, so the critical \r
+nesting variable is initialised to a non-zero value. */\r
#define portINITIAL_NESTING_VALUE ( 0xff )\r
\r
/* The bit within the MSR register that enabled/disables interrupts. */\r
#define portMSR_IE ( 0x02U )\r
\r
+/* If the floating point unit is included in the MicroBlaze build, then the\r
+FSR register is saved as part of the task context. portINITIAL_FSR is the value\r
+given to the FSR register when the initial context is set up for a task being\r
+created. */\r
#define portINITIAL_FSR ( 0U )\r
/*-----------------------------------------------------------*/\r
\r
/*\r
* Initialise the interrupt controller instance.\r
*/\r
-static portBASE_TYPE prvInitialiseInterruptController( void );\r
+static long prvInitialiseInterruptController( void );\r
\r
-/*\r
- * Call an application provided callback to set up the periodic interrupt used\r
- * for the RTOS tick. Using an application callback allows the application\r
- * writer to decide\r
+/* Ensure the interrupt controller instance variable is initialised before it is \r
+ * used, and that the initialisation only happens once. \r
*/\r
-extern void vApplicationSetupTimerInterrupt( void );\r
+static long prvEnsureInterruptControllerIsInitialised( void );\r
+\r
/*-----------------------------------------------------------*/\r
\r
/* Counts the nesting depth of calls to portENTER_CRITICAL(). Each task \r
-maintains it's own count, so this variable is saved as part of the task\r
+maintains its own count, so this variable is saved as part of the task\r
context. */\r
volatile unsigned portBASE_TYPE uxCriticalNesting = portINITIAL_NESTING_VALUE;\r
\r
-/* To limit the amount of stack required by each task, this port uses a\r
-separate stack for interrupts. */\r
+/* This port uses a separate stack for interrupts. This prevents the stack of\r
+every task needing to be large enough to hold an entire interrupt stack on top\r
+of the task stack. */\r
unsigned long *pulISRStack;\r
\r
-/* If an interrupt requests a context switch then ulTaskSwitchRequested will\r
-get set to 1, which in turn will cause vTaskSwitchContext() to be called\r
-prior to a task context getting restored on exit from the interrupt. This\r
-mechanism is used as a single interrupt can cause multiple peripherals handlers\r
-to get called, and vTaskSwitchContext() should not get called in each handler. */\r
+/* If an interrupt requests a context switch, then ulTaskSwitchRequested will\r
+get set to 1. ulTaskSwitchRequested is inspected just before the main interrupt\r
+handler exits. If, at that time, ulTaskSwitchRequested is set to 1, the kernel\r
+will call vTaskSwitchContext() to ensure the task that runs immediately after\r
+the interrupt exists is the highest priority task that is able to run. This is \r
+an unusual mechanism, but is used for this port because a single interrupt can \r
+cause the servicing of multiple peripherals - and it is inefficient to call\r
+vTaskSwitchContext() multiple times as each peripheral is serviced. */\r
volatile unsigned long ulTaskSwitchRequested = 0UL;\r
\r
-/* The instance of the interrupt controller used by this port. */\r
+/* The instance of the interrupt controller used by this port. This is required\r
+by the Xilinx library API functions. */\r
static XIntc xInterruptControllerInstance;\r
\r
/*-----------------------------------------------------------*/\r
* Initialise the stack of a task to look exactly as if a call to \r
* portSAVE_CONTEXT had been made.\r
* \r
- * See the header file portable.h.\r
+ * See the portable.h header file.\r
*/\r
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )\r
{\r
\r
/* Place a few bytes of known values on the bottom of the stack. \r
This is essential for the Microblaze port and these lines must\r
- not be omitted. The parameter value will overwrite the \r
- 0x22222222 value during the function prologue. */\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x11111111;\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x22222222;\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x33333333;\r
- pxTopOfStack--; \r
-\r
- /* The debugger will look at the previous stack frame. */\r
+ not be omitted. */\r
*pxTopOfStack = ( portSTACK_TYPE ) 0x00000000;\r
pxTopOfStack--;\r
*pxTopOfStack = ( portSTACK_TYPE ) 0x00000000;\r
*pxTopOfStack = ( portSTACK_TYPE ) 0x04; /* R4 - return values and temporaries. */\r
pxTopOfStack--;\r
*pxTopOfStack = ( portSTACK_TYPE ) pvParameters;/* R5 contains the function call parameters. */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x06; /* R6 - other parameters and temporaries. Used as the return address from vPortTaskEntryPoint. */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x07; /* R7 - other parameters and temporaries. */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x08; /* R8 - other parameters and temporaries. */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x09; /* R9 - other parameters and temporaries. */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x0a; /* R10 - other parameters and temporaries. */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x0b; /* R11 - temporaries. */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x0c; /* R12 - temporaries. */\r
- pxTopOfStack--;\r
+\r
+ #ifdef portPRE_LOAD_STACK_FOR_DEBUGGING\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x06; /* R6 - other parameters and temporaries. Used as the return address from vPortTaskEntryPoint. */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x07; /* R7 - other parameters and temporaries. */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x08; /* R8 - other parameters and temporaries. */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x09; /* R9 - other parameters and temporaries. */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x0a; /* R10 - other parameters and temporaries. */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x0b; /* R11 - temporaries. */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x0c; /* R12 - temporaries. */\r
+ pxTopOfStack--;\r
+ #else\r
+ pxTopOfStack-= 8;\r
+ #endif\r
+ \r
*pxTopOfStack = ( portSTACK_TYPE ) ulR13; /* R13 - read/write small data area. */\r
pxTopOfStack--;\r
*pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* R14 - return address for interrupt. */\r
pxTopOfStack--;\r
*pxTopOfStack = ( portSTACK_TYPE ) NULL; /* R15 - return address for subroutine. */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x10; /* R16 - return address for trap (debugger). */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x11; /* R17 - return address for exceptions, if configured. */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x12; /* R18 - reserved for assembler and compiler temporaries. */\r
- pxTopOfStack--;\r
+ \r
+ #ifdef portPRE_LOAD_STACK_FOR_DEBUGGING\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x10; /* R16 - return address for trap (debugger). */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x11; /* R17 - return address for exceptions, if configured. */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x12; /* R18 - reserved for assembler and compiler temporaries. */\r
+ pxTopOfStack--;\r
+ #else\r
+ pxTopOfStack -= 4;\r
+ #endif\r
+ \r
*pxTopOfStack = ( portSTACK_TYPE ) 0x00; /* R19 - must be saved across function calls. Callee-save. Seems to be interpreted as the frame pointer. */\r
- pxTopOfStack--;\r
- *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. */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x15; /* R21 - must be saved across function calls. Callee-save. */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x16; /* R22 - must be saved across function calls. Callee-save. */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x17; /* R23 - must be saved across function calls. Callee-save. */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x18; /* R24 - must be saved across function calls. Callee-save. */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x19; /* R25 - must be saved across function calls. Callee-save. */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x1a; /* R26 - must be saved across function calls. Callee-save. */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x1b; /* R27 - must be saved across function calls. Callee-save. */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x1c; /* R28 - must be saved across function calls. Callee-save. */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x1d; /* R29 - must be saved across function calls. Callee-save. */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x1e; /* R30 - must be saved across function calls. Callee-save. */\r
- pxTopOfStack--;\r
- *pxTopOfStack = ( portSTACK_TYPE ) 0x1f; /* R31 - must be saved across function calls. Callee-save. */\r
- pxTopOfStack--;\r
+ \r
+ #ifdef portPRE_LOAD_STACK_FOR_DEBUGGING \r
+ pxTopOfStack--;\r
+ *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. */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x15; /* R21 - must be saved across function calls. Callee-save. */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x16; /* R22 - must be saved across function calls. Callee-save. */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x17; /* R23 - must be saved across function calls. Callee-save. */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x18; /* R24 - must be saved across function calls. Callee-save. */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x19; /* R25 - must be saved across function calls. Callee-save. */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x1a; /* R26 - must be saved across function calls. Callee-save. */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x1b; /* R27 - must be saved across function calls. Callee-save. */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x1c; /* R28 - must be saved across function calls. Callee-save. */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x1d; /* R29 - must be saved across function calls. Callee-save. */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x1e; /* R30 - must be saved across function calls. Callee-save. */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) 0x1f; /* R31 - must be saved across function calls. Callee-save. */\r
+ pxTopOfStack--;\r
+ #else\r
+ pxTopOfStack -= 13;\r
+ #endif\r
\r
- /* Return a pointer to the top of the stack we have generated so this can\r
- be stored in the task control block for the task. */\r
+ /* Return a pointer to the top of the stack that has been generated so this \r
+ can be stored in the task control block for the task. */\r
return pxTopOfStack;\r
}\r
/*-----------------------------------------------------------*/\r
extern unsigned long _stack[];\r
\r
/* Setup the hardware to generate the tick. Interrupts are disabled when\r
- this function is called. */\r
+ this function is called. \r
+ \r
+ This port uses an application defined callback function to install the tick\r
+ interrupt handler because the kernel will run on lots of different \r
+ MicroBlaze and FPGA configurations - not all of which will have the same \r
+ timer peripherals defined or available. An example definition of\r
+ vApplicationSetupTimerInterrupt() is provided in the official demo\r
+ application that accompanies this port. */\r
vApplicationSetupTimerInterrupt();\r
\r
- /* Reuse the stack from main as the stack for the interrupts/exceptions. */\r
+ /* Reuse the stack from main() as the stack for the interrupts/exceptions. */\r
pulISRStack = ( unsigned long * ) _stack;\r
\r
+ /* Ensure there is enough space for the functions called from the interrupt\r
+ service routines to write back into the stack frame of the caller. */
+ pulISRStack -= 2;\r
+\r
/* Restore the context of the first task that is going to run. From here\r
on, the created tasks will be executing. */\r
vPortStartFirstTask();\r
\r
/* Perform the context switch in a critical section to assure it is\r
not interrupted by the tick ISR. It is not a problem to do this as\r
- each task maintains it's own interrupt status. */\r
+ each task maintains its own interrupt status. */\r
portENTER_CRITICAL();\r
{\r
/* Jump directly to the yield function to ensure there is no\r
\r
void vPortEnableInterrupt( unsigned char ucInterruptID )\r
{\r
- XIntc_Enable( &xInterruptControllerInstance, ucInterruptID );\r
+long lReturn;\r
+\r
+ /* An API function is provided to enable an interrupt in the interrupt\r
+ controller because the interrupt controller instance variable is private\r
+ to this file. */\r
+ lReturn = prvEnsureInterruptControllerIsInitialised();\r
+ if( lReturn == pdPASS )\r
+ {\r
+ XIntc_Enable( &xInterruptControllerInstance, ucInterruptID );\r
+ }\r
+ \r
+ configASSERT( lReturn );\r
}\r
/*-----------------------------------------------------------*/\r
\r
void vPortDisableInterrupt( unsigned char ucInterruptID )\r
{\r
- XIntc_Disable( &xInterruptControllerInstance, ucInterruptID );\r
+long lReturn;\r
+\r
+ /* An API function is provided to disable an interrupt in the interrupt\r
+ controller because the interrupt controller instance variable is private\r
+ to this file. */\r
+ lReturn = prvEnsureInterruptControllerIsInitialised();\r
+ \r
+ if( lReturn == pdPASS )\r
+ {\r
+ XIntc_Disable( &xInterruptControllerInstance, ucInterruptID );\r
+ }\r
+ \r
+ configASSERT( lReturn );\r
}\r
/*-----------------------------------------------------------*/\r
\r
portBASE_TYPE xPortInstallInterruptHandler( unsigned char ucInterruptID, XInterruptHandler pxHandler, void *pvCallBackRef )\r
{\r
-static portBASE_TYPE xInterruptControllerInitialised = pdFALSE;\r
-portBASE_TYPE xReturn = XST_SUCCESS;\r
+long lReturn;\r
\r
- if( xInterruptControllerInitialised != pdTRUE )\r
+ /* An API function is provided to install an interrupt handler because the \r
+ interrupt controller instance variable is private to this file. */\r
+\r
+ lReturn = prvEnsureInterruptControllerIsInitialised();\r
+ \r
+ if( lReturn == pdPASS )\r
{\r
- xReturn = prvInitialiseInterruptController();\r
- xInterruptControllerInitialised = pdTRUE;\r
+ lReturn = XIntc_Connect( &xInterruptControllerInstance, ucInterruptID, pxHandler, pvCallBackRef );\r
}\r
\r
- if( xReturn == XST_SUCCESS )\r
+ if( lReturn == XST_SUCCESS )\r
{\r
- xReturn = XIntc_Connect( &xInterruptControllerInstance, ucInterruptID, pxHandler, pvCallBackRef );\r
+ lReturn = pdPASS;\r
}\r
+ \r
+ configASSERT( lReturn == pdPASS );\r
+\r
+ return lReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static long prvEnsureInterruptControllerIsInitialised( void )\r
+{\r
+static long lInterruptControllerInitialised = pdFALSE;\r
+long lReturn;\r
\r
- if( xReturn == XST_SUCCESS )\r
+ /* Ensure the interrupt controller instance variable is initialised before\r
+ it is used, and that the initialisation only happens once. */\r
+ if( lInterruptControllerInitialised != pdTRUE )\r
+ {\r
+ lReturn = prvInitialiseInterruptController();\r
+ \r
+ if( lReturn == pdPASS )\r
+ {\r
+ lInterruptControllerInitialised = pdTRUE;\r
+ }\r
+ }\r
+ else\r
{\r
- xReturn = pdPASS;\r
+ lReturn = pdPASS;\r
}\r
\r
- return xReturn;\r
+ return lReturn;\r
}\r
/*-----------------------------------------------------------*/\r
\r
/* \r
- * Handler for the timer interrupt.\r
+ * Handler for the timer interrupt. This is the handler that the application\r
+ * defined callback function vApplicationSetupTimerInterrupt() should install.\r
*/\r
void vTickISR( void *pvUnused )\r
{\r
/* Ensure the unused parameter does not generate a compiler warning. */\r
( void ) pvUnused;\r
\r
+ /* This port uses an application defined callback function to clear the tick\r
+ interrupt because the kernel will run on lots of different MicroBlaze and \r
+ FPGA configurations - not all of which will have the same timer peripherals \r
+ defined or available. An example definition of\r
+ vApplicationClearTimerInterrupt() is provided in the official demo\r
+ application that accompanies this port. */ \r
vApplicationClearTimerInterrupt();\r
\r
/* Increment the RTOS tick - this might cause a task to unblock. */\r
vTaskIncrementTick();\r
\r
- /* If we are using the preemptive scheduler then we also need to determine\r
- if this tick should cause a context switch. */\r
+ /* If the preemptive scheduler is being used then a context switch should be\r
+ requested in case incrementing the tick unblocked a task, or a time slice\r
+ should cause another task to enter the Running state. */\r
#if configUSE_PREEMPTION == 1\r
/* Force vTaskSwitchContext() to be called as the interrupt exits. */\r
ulTaskSwitchRequested = 1;\r
}\r
/*-----------------------------------------------------------*/\r
\r
-static portBASE_TYPE prvInitialiseInterruptController( void )\r
+static long prvInitialiseInterruptController( void )\r
{\r
-portBASE_TYPE xStatus;\r
+long lStatus;\r
\r
- xStatus = XIntc_Initialize( &xInterruptControllerInstance, configINTERRUPT_CONTROLLER_TO_USE );\r
+ lStatus = XIntc_Initialize( &xInterruptControllerInstance, configINTERRUPT_CONTROLLER_TO_USE );\r
\r
- if( xStatus == XST_SUCCESS )\r
+ if( lStatus == XST_SUCCESS )\r
{\r
/* Initialise the exception table. */\r
Xil_ExceptionInit();\r
\r
/* Start the interrupt controller. Interrupts are enabled when the\r
scheduler starts. */\r
- xStatus = XIntc_Start( &xInterruptControllerInstance, XIN_REAL_MODE );\r
-\r
- /* Ensure the compiler does not generate warnings for the unused\r
- iStatus valud if configASSERT() is not defined. */\r
- ( void ) xStatus;\r
+ lStatus = XIntc_Start( &xInterruptControllerInstance, XIN_REAL_MODE );\r
+\r
+ if( lStatus == XST_SUCCESS )\r
+ {\r
+ lStatus = pdPASS;\r
+ }\r
+ else\r
+ {\r
+ lStatus = pdFAIL;\r
+ }\r
}\r
\r
- configASSERT( ( xStatus == ( portBASE_TYPE ) XST_SUCCESS ) )\r
-\r
-/*_RB_ Exception test code. */\r
-#if 0\r
-This does not cause the bralid address to be in the r17 register.\r
-__asm volatile (\r
- "bralid r15, 1234 \n"\r
- "or r0, r0, r0 \n"\r
- );\r
-#endif\r
-#if 0\r
- xStatus /= 0;\r
-#endif\r
-\r
- return xStatus;\r
+ configASSERT( lStatus == pdPASS );\r
+\r
+ return lStatus;\r
}\r
/*-----------------------------------------------------------*/\r
\r
#include <microblaze_exceptions_i.h>\r
#include <microblaze_exceptions_g.h>\r
\r
+/* The Xilinx library defined exception entry point stacks a number of\r
+registers. These definitions are offsets from the stack pointer to the various\r
+stacked register values. */\r
#define portexR3_STACK_OFFSET 4\r
#define portexR4_STACK_OFFSET 5\r
#define portexR5_STACK_OFFSET 6\r
#define portexMSR_STACK_OFFSET 19\r
#define portexR19_STACK_OFFSET -1\r
\r
-#define portexESR_DS_MASK 0x00001000UL\r
-\r
+/* This is defined to equal the size, in bytes, of the stack frame generated by\r
+the Xilinx standard library exception entry point. It is required to determine\r
+the stack pointer value prior to the exception being entered. */\r
#define portexASM_HANDLER_STACK_FRAME_SIZE 84UL\r
\r
-/* Exclude the entire file if the MicroBlaze is not configured to handle\r
-exceptions, or the application defined configuration item \r
+/* The number of bytes a MicroBlaze instruction consumes. */\r
+#define portexINSTRUCTION_SIZE 4\r
+\r
+/* Exclude this entire file if the MicroBlaze is not configured to handle\r
+exceptions, or the application defined configuration constant\r
configINSTALL_EXCEPTION_HANDLERS is not set to 1. */\r
#if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 )\r
\r
-/* These are global volatiles to allow their inspection by a debugger. */\r
+/* These variables are set in the exception entry code, before \r
+vPortExceptionHandler is called. */\r
unsigned long *pulStackPointerOnFunctionEntry = NULL, ulBTROnFunctionEntry = 0UL;\r
\r
+/* This is the structure that is filled with the MicroBlaze context as it\r
+existed immediately prior to the exception occurrence. A pointer to this\r
+structure is passed into the vApplicationExceptionRegisterDump() callback\r
+function, if one is defined. */\r
static xPortRegisterDump xRegisterDump;\r
\r
+/* This is the FreeRTOS exception handler that is installed for all exception\r
+types. It is called from vPortExceptionHanlderEntry() - which is itself defined\r
+in portasm.S. */\r
void vPortExceptionHandler( void *pvExceptionID );\r
extern void vPortExceptionHandlerEntry( void *pvExceptionID );\r
\r
/*-----------------------------------------------------------*/\r
+\r
+/* vApplicationExceptionRegisterDump() is a callback function that the \r
+application can optionally define to receive a populated xPortRegisterDump\r
+structure. If the application chooses not to define a version of \r
+vApplicationExceptionRegisterDump() then this weekly defined default \r
+implementation will be called instead. */\r
extern void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump ) __attribute__((weak));\r
void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump )\r
{\r
{\r
extern void *pxCurrentTCB;\r
\r
+ /* Fill an xPortRegisterDump structure with the MicroBlaze context as it\r
+ was immediately before the exception occurrence. */\r
+ \r
+ /* First fill in the name and handle of the task that was in the Running \r
+ state when the exception occurred. */\r
xRegisterDump.xCurrentTaskHandle = pxCurrentTCB;\r
xRegisterDump.pcCurrentTaskName = pcTaskGetTaskName( NULL );\r
\r
xRegisterDump.ulR15_return_address_from_subroutine = pulStackPointerOnFunctionEntry[ portexR15_STACK_OFFSET ];\r
xRegisterDump.ulR18 = pulStackPointerOnFunctionEntry[ portexR18_STACK_OFFSET ];\r
xRegisterDump.ulR19 = pulStackPointerOnFunctionEntry[ portexR19_STACK_OFFSET ];\r
-\r
+ xRegisterDump.ulMSR = pulStackPointerOnFunctionEntry[ portexMSR_STACK_OFFSET ];\r
+ \r
/* Obtain the value of all other registers. */\r
xRegisterDump.ulR2_small_data_area = mfgpr( R2 );\r
xRegisterDump.ulR13_read_write_small_data_area = mfgpr( R13 );\r
xRegisterDump.ulR31 = mfgpr( R31 );\r
xRegisterDump.ulR1_SP = ( ( unsigned long ) pulStackPointerOnFunctionEntry ) + portexASM_HANDLER_STACK_FRAME_SIZE;\r
xRegisterDump.ulBTR = ulBTROnFunctionEntry;\r
- xRegisterDump.ulMSR = pulStackPointerOnFunctionEntry[ portexMSR_STACK_OFFSET ];\r
xRegisterDump.ulEAR = mfear();\r
xRegisterDump.ulESR = mfesr();\r
xRegisterDump.ulEDR = mfedr();\r
-\r
-\r
-#ifdef THIS_IS_PROBABLY_INCORRECT\r
- if( ( xRegisterDump.ulESR * portexESR_DS_MASK ) != 0UL )\r
- {\r
- xRegisterDump.ulPC = mfbtr();\r
- }\r
- else\r
- {\r
- xRegisterDump.ulPC = xRegisterDump.ulR17_return_address_from_some_exceptions - 4;\r
- }\r
-#else\r
- xRegisterDump.ulPC = xRegisterDump.ulR17_return_address_from_some_exceptions - 4;\r
-#endif\r
-\r
+ \r
+ /* Move the saved program counter back to the instruction that was executed\r
+ when the exception occurred. This is only valid for certain types of\r
+ exception. */\r
+ xRegisterDump.ulPC = xRegisterDump.ulR17_return_address_from_some_exceptions - portexINSTRUCTION_SIZE;\r
\r
#if XPAR_MICROBLAZE_0_USE_FPU == 1\r
{\r
}\r
#endif\r
\r
+ /* Also fill in a string that describes what type of exception this is.\r
+ The string uses the same ID names as defined in the MicroBlaze standard\r
+ library exception header files. */\r
switch( ( unsigned long ) pvExceptionID )\r
{\r
case XEXC_ID_FSL :\r
#endif /* XPAR_MICROBLAZE_0_USE_FPU */\r
}\r
\r
+ /* vApplicationExceptionRegisterDump() is a callback function that the \r
+ application can optionally define to receive the populated xPortRegisterDump\r
+ structure. If the application chooses not to define a version of \r
+ vApplicationExceptionRegisterDump() then the weekly defined default \r
+ implementation within this file will be called instead. */\r
vApplicationExceptionRegisterDump( &xRegisterDump );\r
\r
/* Must not attempt to leave this function! */\r