]> git.sur5r.net Git - freertos/blob - Source/portable/GCC/PPC405_Xilinx/port.c
Clear the interrupt prior to servicing the interrupt - previously it was the other...
[freertos] / Source / portable / GCC / PPC405_Xilinx / port.c
1 /*\r
2         FreeRTOS.org V4.7.2 - Copyright (C) 2003-2008 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         Please ensure to read the configuration and relevant port sections of the \r
29         online documentation.\r
30 \r
31         +++ http://www.FreeRTOS.org +++\r
32         Documentation, latest information, license and contact details.  \r
33 \r
34         +++ http://www.SafeRTOS.com +++\r
35         A version that is certified for use in safety critical systems.\r
36 \r
37         +++ http://www.OpenRTOS.com +++\r
38         Commercial support, development, porting, licensing and training services.\r
39 \r
40         ***************************************************************************\r
41 */\r
42 \r
43 /*-----------------------------------------------------------\r
44  * Implementation of functions defined in portable.h for the PPC405 port.\r
45  *----------------------------------------------------------*/\r
46 \r
47 \r
48 /* Scheduler includes. */\r
49 #include "FreeRTOS.h"\r
50 #include "task.h"\r
51 \r
52 /* Library includes. */\r
53 #include "xtime_l.h"\r
54 #include "xintc.h"\r
55 #include "xintc_i.h"\r
56 \r
57 /*-----------------------------------------------------------*/\r
58 \r
59 /* Definitions to set the initial MSR of each task. */\r
60 #define portCRITICAL_INTERRUPT_ENABLE   ( 1UL << 17UL )\r
61 #define portEXTERNAL_INTERRUPT_ENABLE   ( 1UL << 15UL )\r
62 #define portMACHINE_CHECK_ENABLE                ( 1UL << 12UL )\r
63 #define portINITIAL_MSR         ( portCRITICAL_INTERRUPT_ENABLE | portEXTERNAL_INTERRUPT_ENABLE | portMACHINE_CHECK_ENABLE )\r
64 \r
65 /*-----------------------------------------------------------*/\r
66 \r
67 /*\r
68  * Setup the system timer to generate the tick interrupt.\r
69  */\r
70 static void prvSetupTimerInterrupt( void );\r
71 \r
72 /*\r
73  * The handler for the tick interrupt - defined in portasm.s.\r
74  */\r
75 extern void vPortTickISR( void );\r
76 \r
77 /*\r
78  * The handler for the yield function - defined in portasm.s.\r
79  */\r
80 extern void vPortYield( void );\r
81 \r
82 /*\r
83  * Function to start the scheduler running by starting the highest\r
84  * priority task that has thus far been created.\r
85  */\r
86 extern void vPortStartFirstTask( void );\r
87 \r
88 /*-----------------------------------------------------------*/\r
89 \r
90 /* Structure used to hold the state of the interrupt controller. */\r
91 static XIntc xInterruptController;\r
92 \r
93 /*-----------------------------------------------------------*/\r
94 \r
95 /* \r
96  * Initialise the stack of a task to look exactly as if the task had been\r
97  * interrupted.\r
98  * \r
99  * See the header file portable.h.\r
100  */\r
101 portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )\r
102 {\r
103         /* Place a known value at the bottom of the stack for debugging. */\r
104         *pxTopOfStack = 0xDEADBEEF;\r
105         *pxTopOfStack--;\r
106 \r
107         /* EABI stack frame. */\r
108         *pxTopOfStack = 0x31313131UL;   /* R31. */\r
109         pxTopOfStack--;\r
110         *pxTopOfStack = 0x30303030UL;   /* R30. */\r
111         pxTopOfStack--;\r
112         *pxTopOfStack = 0x29292929UL;   /* R29. */\r
113         pxTopOfStack--;\r
114         *pxTopOfStack = 0x28282828UL;   /* R28. */\r
115         pxTopOfStack--;\r
116         *pxTopOfStack = 0x27272727UL;   /* R27. */\r
117         pxTopOfStack--;\r
118         *pxTopOfStack = 0x26262626UL;   /* R26. */\r
119         pxTopOfStack--;\r
120         *pxTopOfStack = 0x25252525UL;   /* R25. */\r
121         pxTopOfStack--;\r
122         *pxTopOfStack = 0x24242424UL;   /* R24. */\r
123         pxTopOfStack--;\r
124         *pxTopOfStack = 0x23232323UL;   /* R23. */\r
125         pxTopOfStack--;\r
126         *pxTopOfStack = 0x22222222UL;   /* R22. */\r
127         pxTopOfStack--;\r
128         *pxTopOfStack = 0x21212121UL;   /* R21. */\r
129         pxTopOfStack--;\r
130         *pxTopOfStack = 0x20202020UL;   /* R20. */\r
131         pxTopOfStack--;\r
132         *pxTopOfStack = 0x19191919UL;   /* R19. */\r
133         pxTopOfStack--;\r
134         *pxTopOfStack = 0x18181818UL;   /* R18. */\r
135         pxTopOfStack--;\r
136         *pxTopOfStack = 0x17171717UL;   /* R17. */\r
137         pxTopOfStack--;\r
138         *pxTopOfStack = 0x16161616UL;   /* R16. */\r
139         pxTopOfStack--;\r
140         *pxTopOfStack = 0x15151515UL;   /* R15. */\r
141         pxTopOfStack--;\r
142         *pxTopOfStack = 0x14141414UL;   /* R14. */\r
143         pxTopOfStack--;\r
144         *pxTopOfStack = 0x13131313UL;   /* R13. */\r
145         pxTopOfStack--;\r
146         *pxTopOfStack = 0x12121212UL;   /* R12. */\r
147         pxTopOfStack--;\r
148         *pxTopOfStack = 0x11111111UL;   /* R11. */\r
149         pxTopOfStack--;\r
150         *pxTopOfStack = 0x10101010UL;   /* R10. */\r
151         pxTopOfStack--;\r
152         *pxTopOfStack = 0x09090909UL;   /* R9. */\r
153         pxTopOfStack--;\r
154         *pxTopOfStack = 0x08080808UL;   /* R8. */\r
155         pxTopOfStack--;\r
156         *pxTopOfStack = 0x07070707UL;   /* R7. */\r
157         pxTopOfStack--;\r
158         *pxTopOfStack = 0x06060606UL;   /* R6. */\r
159         pxTopOfStack--;\r
160         *pxTopOfStack = 0x05050505UL;   /* R5. */\r
161         pxTopOfStack--;\r
162         *pxTopOfStack = 0x04040404UL;   /* R4. */\r
163         pxTopOfStack--;\r
164         *pxTopOfStack = ( portSTACK_TYPE ) pvParameters;\r
165         pxTopOfStack--;\r
166         *pxTopOfStack = 0x02020202UL;   /* R2. */\r
167         pxTopOfStack--;\r
168         *pxTopOfStack = 0x10000001UL;;  /* R0. */\r
169         pxTopOfStack--;\r
170         *pxTopOfStack = 0x00000000UL;   /* USPRG0. */\r
171         pxTopOfStack--;\r
172         *pxTopOfStack = 0x00000000UL;   /* CR. */\r
173         pxTopOfStack--;\r
174         *pxTopOfStack = 0x00000000UL;   /* XER. */\r
175         pxTopOfStack--;\r
176         *pxTopOfStack = 0x00000000UL;   /* CTR. */\r
177         pxTopOfStack--;\r
178         *pxTopOfStack = ( portSTACK_TYPE ) vPortStartFirstTask; /* LR. */\r
179         pxTopOfStack--;\r
180         *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* SRR0. */\r
181         pxTopOfStack--;\r
182         *pxTopOfStack = portINITIAL_MSR;/* SRR1. */\r
183         pxTopOfStack--;\r
184         *pxTopOfStack = ( portSTACK_TYPE ) vPortStartFirstTask;/* Next LR. */\r
185         pxTopOfStack--;\r
186         *pxTopOfStack = 0x00000000UL;;/* Backchain. */\r
187 \r
188         return pxTopOfStack;\r
189 }\r
190 /*-----------------------------------------------------------*/\r
191 \r
192 portBASE_TYPE xPortStartScheduler( void )\r
193 {\r
194         prvSetupTimerInterrupt();\r
195         XExc_RegisterHandler( XEXC_ID_SYSTEM_CALL, ( XExceptionHandler ) vPortYield, ( void * ) 0 );\r
196         vPortStartFirstTask();\r
197 \r
198         /* Should not get here as the tasks are now running! */\r
199         return pdFALSE;\r
200 }\r
201 /*-----------------------------------------------------------*/\r
202 \r
203 void vPortEndScheduler( void )\r
204 {\r
205         /* Not implemented. */\r
206 }\r
207 /*-----------------------------------------------------------*/\r
208 \r
209 /*\r
210  * Hardware initialisation to generate the RTOS tick.   \r
211  */\r
212 static void prvSetupTimerInterrupt( void )\r
213 {\r
214 const unsigned portLONG ulInterval = ( ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL );\r
215 \r
216         XTime_PITClearInterrupt();\r
217         XTime_FITClearInterrupt();\r
218         XTime_WDTClearInterrupt();\r
219         XTime_WDTDisableInterrupt();\r
220         XTime_FITDisableInterrupt();\r
221 \r
222         XExc_RegisterHandler( XEXC_ID_PIT_INT, ( XExceptionHandler ) vPortTickISR, ( void * ) 0 );\r
223 \r
224         XTime_PITEnableAutoReload();\r
225         XTime_PITSetInterval( ulInterval );\r
226         XTime_PITEnableInterrupt();\r
227 }\r
228 /*-----------------------------------------------------------*/\r
229 \r
230 void vPortISRHandler( void *vNullDoNotUse )\r
231 {\r
232 unsigned portLONG ulInterruptStatus, ulInterruptMask = 1UL;\r
233 portBASE_TYPE xInterruptNumber;\r
234 XIntc_Config *pxInterruptController;\r
235 XIntc_VectorTableEntry *pxTable;\r
236 \r
237         /* Get the configuration by using the device ID - in this case it is\r
238         assumed that only one interrupt controller is being used. */\r
239         pxInterruptController = &XIntc_ConfigTable[ XPAR_OPB_INTC_0_DEVICE_ID ];\r
240   \r
241         /* Which interrupts are pending? */\r
242         ulInterruptStatus = XIntc_mGetIntrStatus( pxInterruptController->BaseAddress );\r
243   \r
244         for( xInterruptNumber = 0; xInterruptNumber < XPAR_INTC_MAX_NUM_INTR_INPUTS; xInterruptNumber++ )\r
245         {\r
246                 if( ulInterruptStatus & 0x01UL )\r
247                 {\r
248                         /* Clear the pending interrupt. */\r
249                         XIntc_mAckIntr( pxInterruptController->BaseAddress, ulInterruptMask );\r
250 \r
251                         /* Call the registered handler. */\r
252                         pxTable = &( pxInterruptController->HandlerTable[ xInterruptNumber ] );\r
253                         pxTable->Handler( pxTable->CallBackRef );\r
254                 }\r
255         \r
256                 /* Check the next interrupt. */\r
257                 ulInterruptMask <<= 0x01UL;\r
258                 ulInterruptStatus >>= 0x01UL;\r
259 \r
260                 /* Have we serviced all interrupts? */\r
261                 if( ulInterruptStatus == 0UL )\r
262                 {\r
263                         break;\r
264                 }\r
265         }\r
266 }\r
267 /*-----------------------------------------------------------*/\r
268 \r
269 void vPortSetupInterruptController( void )\r
270 {\r
271 extern void vPortISRWrapper( void );\r
272 \r
273         /* Perform all library calls necessary to initialise the exception table\r
274         and interrupt controller.  This assumes only one interrupt controller is in\r
275         use. */\r
276         XExc_mDisableExceptions( XEXC_NON_CRITICAL );\r
277         XExc_Init();\r
278 \r
279         /* The library functions save the context - we then jump to a wrapper to\r
280         save the stack into the TCB.  The wrapper then calls the handler defined\r
281         above. */\r
282         XExc_RegisterHandler( XEXC_ID_NON_CRITICAL_INT, ( XExceptionHandler ) vPortISRWrapper, NULL );\r
283         XIntc_Initialize( &xInterruptController, XPAR_OPB_INTC_0_DEVICE_ID );\r
284         XIntc_Start( &xInterruptController, XIN_REAL_MODE );\r
285 }\r
286 /*-----------------------------------------------------------*/\r
287 \r
288 portBASE_TYPE xPortInstallInterruptHandler( unsigned portCHAR ucInterruptID, XInterruptHandler pxHandler, void *pvCallBackRef )\r
289 {\r
290 portBASE_TYPE xReturn = pdFAIL;\r
291 \r
292         /* This function is defined here so the scope of xInterruptController can\r
293         remain within this file. */\r
294 \r
295         if( XST_SUCCESS == XIntc_Connect( &xInterruptController, ucInterruptID, pxHandler, pvCallBackRef ) )\r
296         {\r
297                 XIntc_Enable( &xInterruptController, ucInterruptID );\r
298                 xReturn = pdPASS;\r
299         }\r
300 \r
301         return xReturn;         \r
302 }\r