From: richardbarry Date: Thu, 30 Jun 2011 18:26:32 +0000 (+0000) Subject: Comment the new MicroBlaze port layer files. X-Git-Tag: V7.0.2~130 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=1769868066f46fd7193e1026d82ec70e8bc16867;p=freertos Comment the new MicroBlaze port layer files. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1480 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- diff --git a/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOS_Source/portable/GCC/MicroBlaze/port.c b/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOS_Source/portable/GCC/MicroBlaze/port.c index 25c9a286d..63fdb467a 100644 --- a/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOS_Source/portable/GCC/MicroBlaze/port.c +++ b/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOS_Source/portable/GCC/MicroBlaze/port.c @@ -68,47 +68,55 @@ #include #include -/* Tasks are started with a critical section nesting of 0 - however prior -to the scheduler being commenced we don't want the critical nesting level -to reach zero, so it is initialised to a high value. */ +/* Tasks are started with a critical section nesting of 0 - however, prior to +the scheduler being commenced interrupts should not be enabled, so the critical +nesting variable is initialised to a non-zero value. */ #define portINITIAL_NESTING_VALUE ( 0xff ) /* The bit within the MSR register that enabled/disables interrupts. */ #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 ) /*-----------------------------------------------------------*/ /* * Initialise the interrupt controller instance. */ -static portBASE_TYPE prvInitialiseInterruptController( void ); +static long prvInitialiseInterruptController( void ); -/* - * Call an application provided callback to set up the periodic interrupt used - * for the RTOS tick. Using an application callback allows the application - * writer to decide +/* Ensure the interrupt controller instance variable is initialised before it is + * used, and that the initialisation only happens once. */ -extern void vApplicationSetupTimerInterrupt( void ); +static long prvEnsureInterruptControllerIsInitialised( void ); + /*-----------------------------------------------------------*/ /* 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. */ volatile unsigned portBASE_TYPE uxCriticalNesting = portINITIAL_NESTING_VALUE; -/* To limit the amount of stack required by each task, this port uses a -separate stack for interrupts. */ +/* This port uses a separate stack for interrupts. This prevents the stack of +every task needing to be large enough to hold an entire interrupt stack on top +of the task stack. */ unsigned long *pulISRStack; -/* If an interrupt requests a context switch then ulTaskSwitchRequested will -get set to 1, which in turn will cause vTaskSwitchContext() to be called -prior to a task context getting restored on exit from the interrupt. This -mechanism is used as a single interrupt can cause multiple peripherals handlers -to get called, and vTaskSwitchContext() should not get called in each handler. */ +/* If an interrupt requests a context switch, then ulTaskSwitchRequested will +get set to 1. ulTaskSwitchRequested is inspected just before the main interrupt +handler exits. If, at that time, ulTaskSwitchRequested is set to 1, the kernel +will call vTaskSwitchContext() to ensure the task that runs immediately after +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; -/* 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; /*-----------------------------------------------------------*/ @@ -117,7 +125,7 @@ static XIntc xInterruptControllerInstance; * Initialise the stack of a task to look exactly as if a call to * 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 ) { @@ -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. This is essential for the Microblaze port and these lines must - not be omitted. The parameter value will overwrite the - 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. */ + not be omitted. */ *pxTopOfStack = ( portSTACK_TYPE ) 0x00000000; pxTopOfStack--; *pxTopOfStack = ( portSTACK_TYPE ) 0x00000000; @@ -172,62 +171,79 @@ const unsigned long ulR13 = ( unsigned long ) &_SDA_BASE_; *pxTopOfStack = ( portSTACK_TYPE ) 0x04; /* R4 - return values and temporaries. */ pxTopOfStack--; *pxTopOfStack = ( portSTACK_TYPE ) pvParameters;/* R5 contains the function call parameters. */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0x06; /* R6 - other parameters and temporaries. Used as the return address from vPortTaskEntryPoint. */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0x07; /* R7 - other parameters and temporaries. */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0x08; /* R8 - other parameters and temporaries. */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0x09; /* R9 - other parameters and temporaries. */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0x0a; /* R10 - other parameters and temporaries. */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0x0b; /* R11 - temporaries. */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0x0c; /* R12 - temporaries. */ - pxTopOfStack--; + + #ifdef portPRE_LOAD_STACK_FOR_DEBUGGING + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x06; /* R6 - other parameters and temporaries. Used as the return address from vPortTaskEntryPoint. */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x07; /* R7 - other parameters and temporaries. */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x08; /* R8 - other parameters and temporaries. */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x09; /* R9 - other parameters and temporaries. */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x0a; /* R10 - other parameters and temporaries. */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x0b; /* R11 - temporaries. */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x0c; /* R12 - temporaries. */ + pxTopOfStack--; + #else + pxTopOfStack-= 8; + #endif + *pxTopOfStack = ( portSTACK_TYPE ) ulR13; /* R13 - read/write small data area. */ pxTopOfStack--; *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* R14 - return address for interrupt. */ pxTopOfStack--; *pxTopOfStack = ( portSTACK_TYPE ) NULL; /* R15 - return address for subroutine. */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0x10; /* R16 - return address for trap (debugger). */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0x11; /* R17 - return address for exceptions, if configured. */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0x12; /* R18 - reserved for assembler and compiler temporaries. */ - pxTopOfStack--; + + #ifdef portPRE_LOAD_STACK_FOR_DEBUGGING + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x10; /* R16 - return address for trap (debugger). */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x11; /* R17 - return address for exceptions, if configured. */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x12; /* R18 - reserved for assembler and compiler temporaries. */ + 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--; - *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 = ( portSTACK_TYPE ) 0x15; /* R21 - must be saved across function calls. Callee-save. */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0x16; /* R22 - must be saved across function calls. Callee-save. */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0x17; /* R23 - must be saved across function calls. Callee-save. */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0x18; /* R24 - must be saved across function calls. Callee-save. */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0x19; /* R25 - must be saved across function calls. Callee-save. */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0x1a; /* R26 - must be saved across function calls. Callee-save. */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0x1b; /* R27 - must be saved across function calls. Callee-save. */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0x1c; /* R28 - must be saved across function calls. Callee-save. */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0x1d; /* R29 - must be saved across function calls. Callee-save. */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0x1e; /* R30 - must be saved across function calls. Callee-save. */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) 0x1f; /* R31 - must be saved across function calls. Callee-save. */ - pxTopOfStack--; + + #ifdef portPRE_LOAD_STACK_FOR_DEBUGGING + 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--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x15; /* R21 - must be saved across function calls. Callee-save. */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x16; /* R22 - must be saved across function calls. Callee-save. */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x17; /* R23 - must be saved across function calls. Callee-save. */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x18; /* R24 - must be saved across function calls. Callee-save. */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x19; /* R25 - must be saved across function calls. Callee-save. */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x1a; /* R26 - must be saved across function calls. Callee-save. */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x1b; /* R27 - must be saved across function calls. Callee-save. */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x1c; /* R28 - must be saved across function calls. Callee-save. */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x1d; /* R29 - must be saved across function calls. Callee-save. */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x1e; /* R30 - must be saved across function calls. Callee-save. */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x1f; /* R31 - must be saved across function calls. Callee-save. */ + pxTopOfStack--; + #else + pxTopOfStack -= 13; + #endif - /* Return a pointer to the top of the stack we have generated so this can - be stored in the task control block for the task. */ + /* Return a pointer to the top of the stack that has been generated so this + can be stored in the task control block for the task. */ return pxTopOfStack; } /*-----------------------------------------------------------*/ @@ -238,12 +254,23 @@ extern void ( vPortStartFirstTask )( void ); extern unsigned long _stack[]; /* 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(); - /* 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; + /* 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 on, the created tasks will be executing. */ vPortStartFirstTask(); @@ -268,7 +295,7 @@ extern void VPortYieldASM( void ); /* 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 - each task maintains it's own interrupt status. */ + each task maintains its own interrupt status. */ portENTER_CRITICAL(); { /* Jump directly to the yield function to ensure there is no @@ -282,43 +309,92 @@ extern void VPortYieldASM( void ); void vPortEnableInterrupt( unsigned char ucInterruptID ) { - XIntc_Enable( &xInterruptControllerInstance, 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 ); + } + + configASSERT( lReturn ); } /*-----------------------------------------------------------*/ void vPortDisableInterrupt( unsigned char ucInterruptID ) { - XIntc_Disable( &xInterruptControllerInstance, 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 ); + } + + configASSERT( lReturn ); } /*-----------------------------------------------------------*/ portBASE_TYPE xPortInstallInterruptHandler( unsigned char ucInterruptID, XInterruptHandler pxHandler, void *pvCallBackRef ) { -static portBASE_TYPE xInterruptControllerInitialised = pdFALSE; -portBASE_TYPE xReturn = XST_SUCCESS; +long lReturn; - 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(); - xInterruptControllerInitialised = pdTRUE; + lReturn = XIntc_Connect( &xInterruptControllerInstance, ucInterruptID, pxHandler, pvCallBackRef ); } - if( xReturn == XST_SUCCESS ) + if( lReturn == XST_SUCCESS ) { - xReturn = XIntc_Connect( &xInterruptControllerInstance, ucInterruptID, pxHandler, pvCallBackRef ); + lReturn = pdPASS; } + + configASSERT( lReturn == pdPASS ); + + return lReturn; +} +/*-----------------------------------------------------------*/ + +static long prvEnsureInterruptControllerIsInitialised( void ) +{ +static long lInterruptControllerInitialised = pdFALSE; +long lReturn; - if( xReturn == XST_SUCCESS ) + /* 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 { - xReturn = pdPASS; + 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 ) { @@ -327,13 +403,20 @@ extern void vApplicationClearTimerInterrupt( void ); /* Ensure the unused parameter does not generate a compiler warning. */ ( 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(); /* Increment the RTOS tick - this might cause a task to unblock. */ vTaskIncrementTick(); - /* If we are using the preemptive scheduler then we also need to determine - if this tick should cause a context switch. */ + /* If the preemptive scheduler is being used then a context switch should be + 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 /* Force vTaskSwitchContext() to be called as the interrupt exits. */ 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. */ Xil_ExceptionInit(); @@ -366,28 +449,21 @@ portBASE_TYPE xStatus; /* Start the interrupt controller. Interrupts are enabled when the scheduler starts. */ - xStatus = XIntc_Start( &xInterruptControllerInstance, XIN_REAL_MODE ); - - /* Ensure the compiler does not generate warnings for the unused - iStatus valud if configASSERT() is not defined. */ - ( void ) xStatus; + lStatus = XIntc_Start( &xInterruptControllerInstance, XIN_REAL_MODE ); + + if( lStatus == XST_SUCCESS ) + { + lStatus = pdPASS; + } + else + { + lStatus = pdFAIL; + } } - configASSERT( ( xStatus == ( portBASE_TYPE ) XST_SUCCESS ) ) - -/*_RB_ Exception test code. */ -#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; + configASSERT( lStatus == pdPASS ); + + return lStatus; } /*-----------------------------------------------------------*/ diff --git a/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOS_Source/portable/GCC/MicroBlaze/port_exceptions.c b/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOS_Source/portable/GCC/MicroBlaze/port_exceptions.c index f963afd49..fc570ac93 100644 --- a/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOS_Source/portable/GCC/MicroBlaze/port_exceptions.c +++ b/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOS_Source/portable/GCC/MicroBlaze/port_exceptions.c @@ -59,6 +59,9 @@ #include #include +/* 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 portexR4_STACK_OFFSET 5 #define portexR5_STACK_OFFSET 6 @@ -74,24 +77,42 @@ #define portexMSR_STACK_OFFSET 19 #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 -/* Exclude the entire file if the MicroBlaze is not configured to handle -exceptions, or the application defined configuration item +/* The number of bytes a MicroBlaze instruction consumes. */ +#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. */ #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; +/* 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; +/* 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 ); 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)); void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump ) { @@ -106,6 +127,11 @@ void vPortExceptionHandler( void *pvExceptionID ) { 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.pcCurrentTaskName = pcTaskGetTaskName( NULL ); @@ -126,7 +152,8 @@ extern void *pxCurrentTCB; xRegisterDump.ulR15_return_address_from_subroutine = pulStackPointerOnFunctionEntry[ portexR15_STACK_OFFSET ]; xRegisterDump.ulR18 = pulStackPointerOnFunctionEntry[ portexR18_STACK_OFFSET ]; xRegisterDump.ulR19 = pulStackPointerOnFunctionEntry[ portexR19_STACK_OFFSET ]; - + xRegisterDump.ulMSR = pulStackPointerOnFunctionEntry[ portexMSR_STACK_OFFSET ]; + /* Obtain the value of all other registers. */ xRegisterDump.ulR2_small_data_area = mfgpr( R2 ); xRegisterDump.ulR13_read_write_small_data_area = mfgpr( R13 ); @@ -148,25 +175,14 @@ extern void *pxCurrentTCB; xRegisterDump.ulR31 = mfgpr( R31 ); xRegisterDump.ulR1_SP = ( ( unsigned long ) pulStackPointerOnFunctionEntry ) + portexASM_HANDLER_STACK_FRAME_SIZE; xRegisterDump.ulBTR = ulBTROnFunctionEntry; - xRegisterDump.ulMSR = pulStackPointerOnFunctionEntry[ portexMSR_STACK_OFFSET ]; xRegisterDump.ulEAR = mfear(); xRegisterDump.ulESR = mfesr(); xRegisterDump.ulEDR = mfedr(); - - -#ifdef THIS_IS_PROBABLY_INCORRECT - if( ( xRegisterDump.ulESR * portexESR_DS_MASK ) != 0UL ) - { - 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 - + + /* Move the saved program counter back to the instruction that was executed + when the exception occurred. This is only valid for certain types of + exception. */ + xRegisterDump.ulPC = xRegisterDump.ulR17_return_address_from_some_exceptions - portexINSTRUCTION_SIZE; #if XPAR_MICROBLAZE_0_USE_FPU == 1 { @@ -178,6 +194,9 @@ extern void *pxCurrentTCB; } #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 ) { case XEXC_ID_FSL : @@ -218,6 +237,11 @@ extern void *pxCurrentTCB; #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 ); /* Must not attempt to leave this function! */ diff --git a/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOS_Source/portable/GCC/MicroBlaze/portasm.S b/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOS_Source/portable/GCC/MicroBlaze/portasm.S index 689087755..674343690 100644 --- a/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOS_Source/portable/GCC/MicroBlaze/portasm.S +++ b/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOS_Source/portable/GCC/MicroBlaze/portasm.S @@ -57,7 +57,10 @@ licensing and training services. */ +/* FreeRTOS includes. */ #include "FreeRTOSConfig.h" + +/* Xilinx library includes. */ #include "microblaze_exceptions_g.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 returned to last left the Running state by calling taskYIELD() (rather than -being preempted by an interrupt. */ +being preempted by an interrupt). */ .text .align 2 exit_from_yield: @@ -276,13 +279,11 @@ _interrupt_handler: /* Stack the return address. */ 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 - function. */ + /* Switch to the ISR stack. */ lwi r1, r0, pulISRStack /* The parameter to the interrupt handler. */ - ori r5, r0, configINTERRUPT_CONTROLLER_TO_USE + ori r5, r0, configINTERRUPT_CONTROLLER_TO_USE /* Execute any pending interrupts. */ bralid r15, XIntc_DeviceInterruptHandler diff --git a/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOS_Source/portable/GCC/MicroBlaze/portmacro.h b/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOS_Source/portable/GCC/MicroBlaze/portmacro.h index c14bbc7bf..50d6353fd 100644 --- a/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOS_Source/portable/GCC/MicroBlaze/portmacro.h +++ b/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOS_Source/portable/GCC/MicroBlaze/portmacro.h @@ -100,6 +100,8 @@ portBASE_TYPE xPortInstallInterruptHandler( unsigned char ucInterruptID, XInterr void vPortEnableInterrupt( unsigned char ucInterruptID ); void vPortDisableInterrupt( unsigned char ucInterruptID ); +void vApplicationSetupTimerInterrupt( void ); + /*-----------------------------------------------------------*/ /* Critical section macros. */