]> git.sur5r.net Git - freertos/blob - Source/portable/GCC/PPC405_Xilinx/port.c
Update to V5.1.2.
[freertos] / Source / portable / GCC / PPC405_Xilinx / port.c
1 /*\r
2         FreeRTOS.org V5.1.2 - Copyright (C) 2003-2009 Richard Barry.\r
3 \r
4         This file is part of the FreeRTOS.org distribution.\r
5 \r
6         FreeRTOS.org is free software; you can redistribute it and/or modify\r
7         it under the terms of the GNU General Public License as published by\r
8         the Free Software Foundation; either version 2 of the License, or\r
9         (at your option) any later version.\r
10 \r
11         FreeRTOS.org is distributed in the hope that it will be useful,\r
12         but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14         GNU General Public License for more details.\r
15 \r
16         You should have received a copy of the GNU General Public License\r
17         along with FreeRTOS.org; if not, write to the Free Software\r
18         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19 \r
20         A special exception to the GPL can be applied should you wish to distribute\r
21         a combined work that includes FreeRTOS.org, without being obliged to provide\r
22         the source code for any proprietary components.  See the licensing section \r
23         of http://www.FreeRTOS.org for full details of how and when the exception\r
24         can be applied.\r
25 \r
26     ***************************************************************************\r
27     ***************************************************************************\r
28     *                                                                         *\r
29     * Get the FreeRTOS eBook!  See http://www.FreeRTOS.org/Documentation      *\r
30         *                                                                         *\r
31         * This is a concise, step by step, 'hands on' guide that describes both   *\r
32         * general multitasking concepts and FreeRTOS specifics. It presents and   *\r
33         * explains numerous examples that are written using the FreeRTOS API.     *\r
34         * Full source code for all the examples is provided in an accompanying    *\r
35         * .zip file.                                                              *\r
36     *                                                                         *\r
37     ***************************************************************************\r
38     ***************************************************************************\r
39 \r
40         Please ensure to read the configuration and relevant port sections of the\r
41         online documentation.\r
42 \r
43         http://www.FreeRTOS.org - Documentation, latest information, license and \r
44         contact details.\r
45 \r
46         http://www.SafeRTOS.com - A version that is certified for use in safety \r
47         critical systems.\r
48 \r
49         http://www.OpenRTOS.com - Commercial support, development, porting, \r
50         licensing and training services.\r
51 */\r
52 \r
53 /*-----------------------------------------------------------\r
54  * Implementation of functions defined in portable.h for the PPC405 port.\r
55  *----------------------------------------------------------*/\r
56 \r
57 \r
58 /* Scheduler includes. */\r
59 #include "FreeRTOS.h"\r
60 #include "task.h"\r
61 \r
62 /* Library includes. */\r
63 #include "xtime_l.h"\r
64 #include "xintc.h"\r
65 #include "xintc_i.h"\r
66 \r
67 /*-----------------------------------------------------------*/\r
68 \r
69 /* Definitions to set the initial MSR of each task. */\r
70 #define portCRITICAL_INTERRUPT_ENABLE   ( 1UL << 17UL )\r
71 #define portEXTERNAL_INTERRUPT_ENABLE   ( 1UL << 15UL )\r
72 #define portMACHINE_CHECK_ENABLE                ( 1UL << 12UL )\r
73 \r
74 #if configUSE_FPU == 1\r
75         #define portAPU_PRESENT                         ( 1UL << 25UL )\r
76         #define portFCM_FPU_PRESENT                     ( 1UL << 13UL )\r
77 #else\r
78         #define portAPU_PRESENT                         ( 0UL )\r
79         #define portFCM_FPU_PRESENT                     ( 0UL )\r
80 #endif\r
81 \r
82 #define portINITIAL_MSR         ( portCRITICAL_INTERRUPT_ENABLE | portEXTERNAL_INTERRUPT_ENABLE | portMACHINE_CHECK_ENABLE | portAPU_PRESENT | portFCM_FPU_PRESENT )\r
83 \r
84 /*-----------------------------------------------------------*/\r
85 \r
86 /*\r
87  * Setup the system timer to generate the tick interrupt.\r
88  */\r
89 static void prvSetupTimerInterrupt( void );\r
90 \r
91 /*\r
92  * The handler for the tick interrupt - defined in portasm.s.\r
93  */\r
94 extern void vPortTickISR( void );\r
95 \r
96 /*\r
97  * The handler for the yield function - defined in portasm.s.\r
98  */\r
99 extern void vPortYield( void );\r
100 \r
101 /*\r
102  * Function to start the scheduler running by starting the highest\r
103  * priority task that has thus far been created.\r
104  */\r
105 extern void vPortStartFirstTask( void );\r
106 \r
107 /*-----------------------------------------------------------*/\r
108 \r
109 /* Structure used to hold the state of the interrupt controller. */\r
110 static XIntc xInterruptController;\r
111 \r
112 /*-----------------------------------------------------------*/\r
113 \r
114 /* \r
115  * Initialise the stack of a task to look exactly as if the task had been\r
116  * interrupted.\r
117  * \r
118  * See the header file portable.h.\r
119  */\r
120 portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )\r
121 {\r
122         /* Place a known value at the bottom of the stack for debugging. */\r
123         *pxTopOfStack = 0xDEADBEEF;\r
124         pxTopOfStack--;\r
125 \r
126         /* EABI stack frame. */\r
127         pxTopOfStack -= 30;     /* Previous backchain and LR, R31 to R4 inclusive. */\r
128 \r
129         /* Parameters in R3. */\r
130         *pxTopOfStack = ( portSTACK_TYPE ) pvParameters;\r
131         pxTopOfStack--;\r
132         *pxTopOfStack = 0x02020202UL;   /* R2. */\r
133         pxTopOfStack--;\r
134 \r
135         /* R1 is the stack pointer so is omitted. */\r
136 \r
137         *pxTopOfStack = 0x10000001UL;;  /* R0. */\r
138         pxTopOfStack--;\r
139         *pxTopOfStack = 0x00000000UL;   /* USPRG0. */\r
140         pxTopOfStack--;\r
141         *pxTopOfStack = 0x00000000UL;   /* CR. */\r
142         pxTopOfStack--;\r
143         *pxTopOfStack = 0x00000000UL;   /* XER. */\r
144         pxTopOfStack--;\r
145         *pxTopOfStack = 0x00000000UL;   /* CTR. */\r
146         pxTopOfStack--;\r
147         *pxTopOfStack = ( portSTACK_TYPE ) vPortEndScheduler;   /* LR. */\r
148         pxTopOfStack--;\r
149         *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* SRR0. */\r
150         pxTopOfStack--;\r
151         *pxTopOfStack = portINITIAL_MSR;/* SRR1. */\r
152         pxTopOfStack--;\r
153         *pxTopOfStack = ( portSTACK_TYPE ) vPortEndScheduler;/* Next LR. */\r
154         pxTopOfStack--;\r
155         *pxTopOfStack = 0x00000000UL;/* Backchain. */\r
156 \r
157         return pxTopOfStack;\r
158 }\r
159 /*-----------------------------------------------------------*/\r
160 \r
161 portBASE_TYPE xPortStartScheduler( void )\r
162 {\r
163         prvSetupTimerInterrupt();\r
164         XExc_RegisterHandler( XEXC_ID_SYSTEM_CALL, ( XExceptionHandler ) vPortYield, ( void * ) 0 );\r
165         vPortStartFirstTask();\r
166 \r
167         /* Should not get here as the tasks are now running! */\r
168         return pdFALSE;\r
169 }\r
170 /*-----------------------------------------------------------*/\r
171 \r
172 void vPortEndScheduler( void )\r
173 {\r
174         /* Not implemented. */\r
175         for( ;; );\r
176 }\r
177 /*-----------------------------------------------------------*/\r
178 \r
179 /*\r
180  * Hardware initialisation to generate the RTOS tick.   \r
181  */\r
182 static void prvSetupTimerInterrupt( void )\r
183 {\r
184 const unsigned portLONG ulInterval = ( ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL );\r
185 \r
186         XTime_PITClearInterrupt();\r
187         XTime_FITClearInterrupt();\r
188         XTime_WDTClearInterrupt();\r
189         XTime_WDTDisableInterrupt();\r
190         XTime_FITDisableInterrupt();\r
191 \r
192         XExc_RegisterHandler( XEXC_ID_PIT_INT, ( XExceptionHandler ) vPortTickISR, ( void * ) 0 );\r
193 \r
194         XTime_PITEnableAutoReload();\r
195         XTime_PITSetInterval( ulInterval );\r
196         XTime_PITEnableInterrupt();\r
197 }\r
198 /*-----------------------------------------------------------*/\r
199 \r
200 void vPortISRHandler( void *pvNullDoNotUse )\r
201 {\r
202 unsigned portLONG ulInterruptStatus, ulInterruptMask = 1UL;\r
203 portBASE_TYPE xInterruptNumber;\r
204 XIntc_Config *pxInterruptController;\r
205 XIntc_VectorTableEntry *pxTable;\r
206 \r
207         /* Just to remove compiler warning. */\r
208         ( void ) pvNullDoNotUse;        \r
209 \r
210         /* Get the configuration by using the device ID - in this case it is\r
211         assumed that only one interrupt controller is being used. */\r
212         pxInterruptController = &XIntc_ConfigTable[ XPAR_XPS_INTC_0_DEVICE_ID ];\r
213   \r
214         /* Which interrupts are pending? */\r
215         ulInterruptStatus = XIntc_mGetIntrStatus( pxInterruptController->BaseAddress );\r
216   \r
217         for( xInterruptNumber = 0; xInterruptNumber < XPAR_INTC_MAX_NUM_INTR_INPUTS; xInterruptNumber++ )\r
218         {\r
219                 if( ulInterruptStatus & 0x01UL )\r
220                 {\r
221                         /* Clear the pending interrupt. */\r
222                         XIntc_mAckIntr( pxInterruptController->BaseAddress, ulInterruptMask );\r
223 \r
224                         /* Call the registered handler. */\r
225                         pxTable = &( pxInterruptController->HandlerTable[ xInterruptNumber ] );\r
226                         pxTable->Handler( pxTable->CallBackRef );\r
227                 }\r
228         \r
229                 /* Check the next interrupt. */\r
230                 ulInterruptMask <<= 0x01UL;\r
231                 ulInterruptStatus >>= 0x01UL;\r
232 \r
233                 /* Have we serviced all interrupts? */\r
234                 if( ulInterruptStatus == 0UL )\r
235                 {\r
236                         break;\r
237                 }\r
238         }\r
239 }\r
240 /*-----------------------------------------------------------*/\r
241 \r
242 void vPortSetupInterruptController( void )\r
243 {\r
244 extern void vPortISRWrapper( void );\r
245 \r
246         /* Perform all library calls necessary to initialise the exception table\r
247         and interrupt controller.  This assumes only one interrupt controller is in\r
248         use. */\r
249         XExc_mDisableExceptions( XEXC_NON_CRITICAL );\r
250         XExc_Init();\r
251 \r
252         /* The library functions save the context - we then jump to a wrapper to\r
253         save the stack into the TCB.  The wrapper then calls the handler defined\r
254         above. */\r
255         XExc_RegisterHandler( XEXC_ID_NON_CRITICAL_INT, ( XExceptionHandler ) vPortISRWrapper, NULL );\r
256         XIntc_Initialize( &xInterruptController, XPAR_XPS_INTC_0_DEVICE_ID );\r
257         XIntc_Start( &xInterruptController, XIN_REAL_MODE );\r
258 }\r
259 /*-----------------------------------------------------------*/\r
260 \r
261 portBASE_TYPE xPortInstallInterruptHandler( unsigned portCHAR ucInterruptID, XInterruptHandler pxHandler, void *pvCallBackRef )\r
262 {\r
263 portBASE_TYPE xReturn = pdFAIL;\r
264 \r
265         /* This function is defined here so the scope of xInterruptController can\r
266         remain within this file. */\r
267 \r
268         if( XST_SUCCESS == XIntc_Connect( &xInterruptController, ucInterruptID, pxHandler, pvCallBackRef ) )\r
269         {\r
270                 XIntc_Enable( &xInterruptController, ucInterruptID );\r
271                 xReturn = pdPASS;\r
272         }\r
273 \r
274         return xReturn;         \r
275 }\r