/*\r
- FreeRTOS.org V4.7.1 - Copyright (C) 2003-2008 Richard Barry.\r
+ FreeRTOS.org V4.7.2 - Copyright (C) 2003-2008 Richard Barry.\r
\r
This file is part of the FreeRTOS.org distribution.\r
\r
#include "xintc.h"\r
#include "xintc_i.h"\r
\r
-/* Standard includes. */\r
-#include <string.h>\r
-\r
/*-----------------------------------------------------------*/\r
\r
-#define portCRITICAL_INTERRUPT_ENABLE ( 0UL << 17UL )\r
+/* Definitions to set the initial MSR of each task. */\r
+#define portCRITICAL_INTERRUPT_ENABLE ( 1UL << 17UL )\r
#define portEXTERNAL_INTERRUPT_ENABLE ( 1UL << 15UL )\r
-#define portMACHINE_CHECK_ENABLE ( 0UL << 12UL )\r
+#define portMACHINE_CHECK_ENABLE ( 1UL << 12UL )\r
#define portINITIAL_MSR ( portCRITICAL_INTERRUPT_ENABLE | portEXTERNAL_INTERRUPT_ENABLE | portMACHINE_CHECK_ENABLE )\r
\r
+/*-----------------------------------------------------------*/\r
+\r
/*\r
+ * Setup the system timer to generate the tick interrupt.\r
*/\r
static void prvSetupTimerInterrupt( void );\r
+\r
+/*\r
+ * The handler for the tick interrupt - defined in portasm.s.\r
+ */\r
extern void vPortTickISR( void );\r
+\r
+/*\r
+ * The handler for the yield function - defined in portasm.s.\r
+ */\r
extern void vPortYield( void );\r
+\r
+/*\r
+ * Function to start the scheduler running by starting the highest\r
+ * priority task that has thus far been created.\r
+ */\r
extern void vPortStartFirstTask( void );\r
\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Structure used to hold the state of the interrupt controller. */\r
static XIntc xInterruptController;\r
\r
+/*-----------------------------------------------------------*/\r
+\r
/* \r
- * Initialise the stack of a task to look exactly as if a call to \r
- * portSAVE_CONTEXT had been made.\r
+ * Initialise the stack of a task to look exactly as if the task had been\r
+ * interrupted.\r
* \r
* See the header file portable.h.\r
*/\r
*pxTopOfStack = ( portSTACK_TYPE ) vPortStartFirstTask;/* Next LR. */\r
pxTopOfStack--;\r
*pxTopOfStack = 0x00000000UL;;/* Backchain. */\r
-// pxTopOfStack--;\r
\r
return pxTopOfStack;\r
}\r
\r
portBASE_TYPE xPortStartScheduler( void )\r
{\r
-extern void *pxCurrentTCB;\r
-\r
prvSetupTimerInterrupt();\r
-\r
XExc_RegisterHandler( XEXC_ID_SYSTEM_CALL, ( XExceptionHandler ) vPortYield, ( void * ) 0 );\r
-\r
-// XExc_mEnableExceptions( XEXC_NON_CRITICAL );\r
-\r
vPortStartFirstTask();\r
\r
/* Should not get here as the tasks are now running! */\r
/*\r
* Hardware initialisation to generate the RTOS tick. \r
*/\r
-static void prvTickISR( void );\r
static void prvSetupTimerInterrupt( void )\r
{\r
const unsigned portLONG ulInterval = ( ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL );\r
}\r
/*-----------------------------------------------------------*/\r
\r
-static void prvTickISR( void )\r
-{\r
-static unsigned portLONG ulTicks = 0;\r
-\r
- ulTicks++;\r
- if( ulTicks >= 1000 )\r
- {\r
- vParTestToggleLED( 0 );\r
- ulTicks = 0;\r
- }\r
- XTime_PITClearInterrupt();\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
void vPortISRHandler( void *vNullDoNotUse )\r
{\r
-Xuint32 IntrStatus;\r
-Xuint32 IntrMask = 1;\r
-int IntrNumber;\r
-//extern XIntc xInterruptController;\r
-XIntc_Config *CfgPtr;// = xInterruptController.CfgPtr;\r
- \r
- /* Get the configuration data using the device ID */\r
- //CfgPtr = &XIntc_ConfigTable[(Xuint32)DeviceId];\r
- CfgPtr = &XIntc_ConfigTable[(Xuint32)XPAR_OPB_INTC_0_DEVICE_ID];\r
+unsigned portLONG ulInterruptStatus, ulInterruptMask = 1UL;\r
+portBASE_TYPE xInterruptNumber;\r
+XIntc_Config *pxInterruptController;\r
+XIntc_VectorTableEntry *pxTable;\r
+\r
+ /* Get the configuration by using the device ID - in this case it is\r
+ assumed that only one interrupt controller is being used. */\r
+ pxInterruptController = &XIntc_ConfigTable[ XPAR_OPB_INTC_0_DEVICE_ID ];\r
\r
- /* Get the interrupts that are waiting to be serviced */\r
- IntrStatus = XIntc_mGetIntrStatus(CfgPtr->BaseAddress);\r
+ /* Which interrupts are pending? */\r
+ ulInterruptStatus = XIntc_mGetIntrStatus( pxInterruptController->BaseAddress );\r
\r
- /* Service each interrupt that is active and enabled by checking each\r
- * bit in the register from LSB to MSB which corresponds to an interrupt\r
- * intput signal\r
- */\r
- for (IntrNumber = 0; IntrNumber < XPAR_INTC_MAX_NUM_INTR_INPUTS;\r
- IntrNumber++)\r
- {\r
- if (IntrStatus & 1)\r
- {\r
- XIntc_VectorTableEntry *TablePtr;\r
- \r
- /* The interrupt is active and enabled, call the interrupt\r
- * handler that was setup with the specified parameter\r
- */\r
- TablePtr = &(CfgPtr->HandlerTable[IntrNumber]);\r
- TablePtr->Handler(TablePtr->CallBackRef);\r
-\r
- /* Clear the interrupt. */ \r
- XIntc_mAckIntr(CfgPtr->BaseAddress, IntrMask);\r
+ for( xInterruptNumber = 0; xInterruptNumber < XPAR_INTC_MAX_NUM_INTR_INPUTS; xInterruptNumber++ )\r
+ {\r
+ if( ulInterruptStatus & 0x01UL )\r
+ {\r
+ /* Call the registered handler. */\r
+ pxTable = &( pxInterruptController->HandlerTable[ xInterruptNumber ] );\r
+ pxTable->Handler( pxTable->CallBackRef );\r
+\r
+ /* Clear the pending interrupt. */\r
+ XIntc_mAckIntr( pxInterruptController->BaseAddress, ulInterruptMask );\r
break;\r
- }\r
+ }\r
\r
- /* Move to the next interrupt to check */\r
- IntrMask <<= 1;\r
- IntrStatus >>= 1;\r
- \r
- /* If there are no other bits set indicating that all interrupts\r
- * have been serviced, then exit the loop\r
- */\r
- if (IntrStatus == 0)\r
- {\r
- break;\r
- }\r
- }\r
+ /* Check the next interrupt. */\r
+ ulInterruptMask <<= 0x01UL;\r
+ ulInterruptStatus >>= 0x01UL;\r
+\r
+ /* Have we serviced all interrupts? */\r
+ if( ulInterruptStatus == 0UL )\r
+ {\r
+ break;\r
+ }\r
+ }\r
}\r
/*-----------------------------------------------------------*/\r
\r
{\r
extern void vPortISRWrapper( void );\r
\r
+ /* Perform all library calls necessary to initialise the exception table\r
+ and interrupt controller. This assumes only one interrupt controller is in\r
+ use. */\r
XExc_mDisableExceptions( XEXC_NON_CRITICAL );\r
XExc_Init();\r
- XExc_RegisterHandler( XEXC_ID_NON_CRITICAL_INT, (XExceptionHandler)vPortISRWrapper, NULL );\r
+\r
+ /* The library functions save the context - we then jump to a wrapper to\r
+ save the stack into the TCB. The wrapper then calls the handler defined\r
+ above. */\r
+ XExc_RegisterHandler( XEXC_ID_NON_CRITICAL_INT, ( XExceptionHandler ) vPortISRWrapper, NULL );\r
XIntc_Initialize( &xInterruptController, XPAR_OPB_INTC_0_DEVICE_ID );\r
XIntc_Start( &xInterruptController, XIN_REAL_MODE );\r
}\r
{\r
portBASE_TYPE xReturn = pdFAIL;\r
\r
+ /* This function is defined here so the scope of xInterruptController can\r
+ remain within this file. */\r
+\r
if( XST_SUCCESS == XIntc_Connect( &xInterruptController, ucInterruptID, pxHandler, pvCallBackRef ) )\r
{\r
XIntc_Enable( &xInterruptController, ucInterruptID );\r
.global vPortTickISR\r
.global vPortISRWrapper\r
\r
-.set portCONTEXT_SIZE, 156\r
-.set portR0_OFFSET, 152\r
-.set portGPR_OFFSET, 32\r
-.set portCR_OFFSET, 28\r
-.set portXER_OFFSET, 24\r
-.set portLR_OFFSET, 16\r
-.set portCTR_OFFSET, 16\r
-.set portUSPRG0_OFFSET, 12\r
-.set portSRR0_OFFSET, 8\r
-.set portSRR1_OFFSET, 4\r
-\r
-\r
.set BChainField, 0\r
.set NextLRField, BChainField + 4\r
.set MSRField, NextLRField + 4\r
.set IFrameSize, r3r31Field + ( ( 31 - 3 ) + 1 ) * 4\r
\r
\r
-.macro portRESTORE_CONTEXT\r
+.macro portSAVE_STACK_POINTER_AND_LR\r
\r
- # Get the address of the TCB.\r
+ # Get the address of the TCB. \r
xor R0, R0, R0\r
- addis SP, R0, pxCurrentTCB@ha\r
- lwz SP, pxCurrentTCB@l( SP )\r
-\r
- # Get the task stack pointer from the TCB.\r
- lwz SP, 0( SP )\r
+ addis R2, R0, pxCurrentTCB@ha\r
+ lwz R2, pxCurrentTCB@l( R2 )\r
\r
- # Pop the special purpose registers\r
- lwz R0, portSRR1_OFFSET( SP )\r
- mtspr SRR1, R0\r
- lwz R0, portSRR0_OFFSET( SP )\r
- mtspr SRR0, R0\r
- lwz R0, portUSPRG0_OFFSET( SP )\r
- mtspr 256, R0 #USPRG0\r
- lwz R0, portCTR_OFFSET( SP )\r
- mtspr CTR, R0\r
- lwz R0, portLR_OFFSET( SP )\r
- mtspr LR, R0\r
- lwz R0, portXER_OFFSET( SP )\r
- mtspr XER, R0\r
- lwz R0, portCR_OFFSET( SP )\r
- mtcr R0\r
+ # Store the stack pointer into the TCB\r
+ stw SP, 0( R2 )\r
\r
- # Pop GPRs\r
- lmw R2, portGPR_OFFSET( SP )\r
+ # Save the link register\r
+ stwu R1, -24( R1 )\r
+ mflr R0\r
+ stw R31, 20( R1 )\r
+ stw R0, 28( R1 )\r
+ mr R31, r1\r
\r
- # Finally pop R0 and correct the stack pointer\r
- lwz R0, portR0_OFFSET( SP )\r
- addi R1, R1, portCONTEXT_SIZE\r
+.endm\r
\r
- # Start the task running\r
- rfi\r
+.macro portRESTORE_STACK_POINTER_AND_LR\r
\r
- .endm\r
-\r
-.macro portSAVE_CONTEXT\r
-\r
- # Make room on the stack.\r
- subi R1, R1, portCONTEXT_SIZE\r
-\r
- # Push R0, then the GPRs\r
- stw R0, portR0_OFFSET( SP )\r
- stm R2, portGPR_OFFSET( SP )\r
-\r
- # Push the SFRs\r
- mfcr R0\r
- stw R0, portCR_OFFSET( SP )\r
- mfspr R0, XER\r
- stw R0, portXER_OFFSET( SP )\r
- mfspr R0, LR\r
- stw R0, portLR_OFFSET( SP )\r
- mfspr R0, CTR\r
- stw R0, portCTR_OFFSET( SP )\r
- mfspr R0, 256 #USPRG0\r
- stw R0, portUSPRG0_OFFSET( SP )\r
- mfspr R0, SRR0\r
- stw R0, portSRR0_OFFSET( SP )\r
- mfspr R0, SRR1\r
- stw R0, portSRR1_OFFSET( SP )\r
+ # Restore the link register\r
+ lwz R11, 0( R1 )\r
+ lwz R0, 4( R11 )\r
+ mtlr R0\r
+ lwz R31, -4( R11 )\r
+ mr R1, R11\r
\r
# Get the address of the TCB.\r
xor R0, R0, R0\r
- addis R2, R0, pxCurrentTCB@ha\r
- lwz R2, pxCurrentTCB@l( R2 )\r
+ addis SP, R0, pxCurrentTCB@ha\r
+ lwz SP, pxCurrentTCB@l( R1 )\r
\r
- # Store the stack pointer into the TCB\r
- stw SP, 0( R2 )\r
+ # Get the task stack pointer from the TCB.\r
+ lwz SP, 0( SP )\r
\r
- .endm\r
+.endm\r
\r
\r
-.macro int_epilogue\r
+vPortStartFirstTask:\r
\r
# Get the address of the TCB.\r
xor R0, R0, R0\r
lwz SP, 0( SP )\r
\r
# Restore MSR register to SRR1.\r
- lwz R0,MSRField(R1)\r
+ lwz R0, MSRField(R1)\r
mtsrr1 R0\r
\r
# Restore current PC location to SRR0.\r
- lwz R0,PCField(R1)\r
+ lwz R0, PCField(R1)\r
mtsrr0 R0\r
\r
- # Save USPRG0 register\r
- lwz R0,USPRG0Field(R1)\r
+ # Save USPRG0 register\r
+ lwz R0, USPRG0Field(R1)\r
mtspr 0x100,R0\r
\r
# Restore Condition register\r
- lwz R0,CRField(R1)\r
+ lwz R0, CRField(R1)\r
mtcr R0\r
\r
# Restore Fixed Point Exception register\r
- lwz R0,XERField(R1)\r
+ lwz R0, XERField(R1)\r
mtxer R0\r
\r
# Restore Counter register\r
- lwz R0,CTRField(R1)\r
+ lwz R0, CTRField(R1)\r
mtctr R0\r
\r
# Restore Link register\r
- lwz R0,LRField(R1)\r
+ lwz R0, LRField(R1)\r
mtlr R0\r
\r
# Restore remaining GPR registers.\r
lmw R3,r3r31Field(R1)\r
\r
# Restore r0 and r2.\r
- lwz R0,r0Field(R1)\r
- lwz R2,r2Field(R1)\r
+ lwz R0, r0Field(R1)\r
+ lwz R2, r2Field(R1)\r
\r
# Remove frame from stack\r
addi R1,R1,IFrameSize\r
- \r
-.endm\r
\r
-.macro portENTER_SWITCHING_ISR\r
-\r
- # Get the address of the TCB. \r
- xor R0, R0, R0\r
- addis R2, R0, pxCurrentTCB@ha\r
- lwz R2, pxCurrentTCB@l( R2 )\r
-\r
- # Store the stack pointer into the TCB\r
- stw SP, 0( R2 )\r
-\r
- # Save the link register\r
- stwu R1, -24( R1 )\r
- mflr R0\r
- stw R31, 20( R1 )\r
- stw R0, 28( R1 )\r
- mr R31, r1\r
-\r
-.endm\r
-\r
-.macro portEXIT_SWITCHING_ISR\r
-\r
- # Restore the link register\r
- lwz R11, 0( R1 )\r
- lwz R0, 4( R11 )\r
- mtlr R0\r
- lwz R31, -4( R11 )\r
- mr R1, R11\r
-\r
- # Get the address of the TCB.\r
- xor R0, R0, R0\r
- addis SP, R0, pxCurrentTCB@ha\r
- lwz SP, pxCurrentTCB@l( R1 )\r
-\r
- # Get the task stack pointer from the TCB.\r
- lwz SP, 0( SP )\r
-\r
-.endm\r
-\r
-\r
-vPortStartFirstTask:\r
-\r
- int_epilogue\r
+ # Return into the first task\r
rfi\r
\r
-#vPortStartFirstTask:\r
-# portRESTORE_CONTEXT\r
-# rfi\r
-\r
\r
\r
vPortYield:\r
\r
- portENTER_SWITCHING_ISR\r
+ portSAVE_STACK_POINTER_AND_LR\r
bl vTaskSwitchContext\r
- portEXIT_SWITCHING_ISR\r
+ portRESTORE_STACK_POINTER_AND_LR\r
blr\r
\r
vPortTickISR:\r
\r
- portENTER_SWITCHING_ISR\r
+ portSAVE_STACK_POINTER_AND_LR\r
bl vTaskIncrementTick\r
#if configUSE_PREEMPTION == 1\r
bl vTaskSwitchContext\r
lis R0, 2048\r
mttsr R0\r
\r
- portEXIT_SWITCHING_ISR\r
+ portRESTORE_STACK_POINTER_AND_LR\r
blr\r
\r
vPortISRWrapper:\r
\r
- portENTER_SWITCHING_ISR\r
+ portSAVE_STACK_POINTER_AND_LR\r
bl vPortISRHandler\r
- portEXIT_SWITCHING_ISR\r
+ portRESTORE_STACK_POINTER_AND_LR\r
blr\r
#endif\r
/*-----------------------------------------------------------*/ \r
\r
+/* This port uses the critical nesting count from the TCB rather than\r
+maintaining a separate value and then saving this value in the task stack. */\r
#define portCRITICAL_NESTING_IN_TCB 1\r
\r
/* Interrupt control macros. */\r
void vPortYield( void );\r
#define portYIELD() asm volatile ( "SC \n\t NOP" )\r
#define portYIELD_FROM_ISR() vTaskSwitchContext()\r
+\r
/*-----------------------------------------------------------*/\r
\r
/* Hardware specifics. */\r
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
\r
-/* Port specific initialisation function. */\r
+/* Port specific interrupt handling functions. */\r
void vPortSetupInterruptController( void );\r
portBASE_TYPE xPortInstallInterruptHandler( unsigned portCHAR ucInterruptID, XInterruptHandler pxHandler, void *pvCallBackRef );\r
\r