]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/GCC/PPC440_Xilinx/port.c
Update version numbers ready for release.
[freertos] / FreeRTOS / Source / portable / GCC / PPC440_Xilinx / port.c
1 /*\r
2  * FreeRTOS Kernel V10.1.1\r
3  * Copyright (C) 2018 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * http://www.FreeRTOS.org\r
23  * http://aws.amazon.com/freertos\r
24  *\r
25  * 1 tab == 4 spaces!\r
26  */\r
27 \r
28 /*-----------------------------------------------------------\r
29  * Implementation of functions defined in portable.h for the PPC440 port.\r
30  *----------------------------------------------------------*/\r
31 \r
32 \r
33 /* Scheduler includes. */\r
34 #include "FreeRTOS.h"\r
35 #include "task.h"\r
36 \r
37 /* Library includes. */\r
38 #include "xtime_l.h"\r
39 #include "xintc.h"\r
40 #include "xintc_i.h"\r
41 \r
42 /*-----------------------------------------------------------*/\r
43 \r
44 /* Definitions to set the initial MSR of each task. */\r
45 #define portCRITICAL_INTERRUPT_ENABLE   ( 1UL << 17UL )\r
46 #define portEXTERNAL_INTERRUPT_ENABLE   ( 1UL << 15UL )\r
47 #define portMACHINE_CHECK_ENABLE                ( 1UL << 12UL )\r
48 \r
49 #if configUSE_FPU == 1\r
50         #define portAPU_PRESENT                         ( 1UL << 25UL )\r
51         #define portFCM_FPU_PRESENT                     ( 1UL << 13UL )\r
52 #else\r
53         #define portAPU_PRESENT                         ( 0UL )\r
54         #define portFCM_FPU_PRESENT                     ( 0UL )\r
55 #endif\r
56 \r
57 #define portINITIAL_MSR         ( portCRITICAL_INTERRUPT_ENABLE | portEXTERNAL_INTERRUPT_ENABLE | portMACHINE_CHECK_ENABLE | portAPU_PRESENT | portFCM_FPU_PRESENT )\r
58 \r
59 \r
60 extern const unsigned _SDA_BASE_;\r
61 extern const unsigned _SDA2_BASE_;\r
62 \r
63 /*-----------------------------------------------------------*/\r
64 \r
65 /*\r
66  * Setup the system timer to generate the tick interrupt.\r
67  */\r
68 static void prvSetupTimerInterrupt( void );\r
69 \r
70 /*\r
71  * The handler for the tick interrupt - defined in portasm.s.\r
72  */\r
73 extern void vPortTickISR( void );\r
74 \r
75 /*\r
76  * The handler for the yield function - defined in portasm.s.\r
77  */\r
78 extern void vPortYield( void );\r
79 \r
80 /*\r
81  * Function to start the scheduler running by starting the highest\r
82  * priority task that has thus far been created.\r
83  */\r
84 extern void vPortStartFirstTask( void );\r
85 \r
86 /*-----------------------------------------------------------*/\r
87 \r
88 /* Structure used to hold the state of the interrupt controller. */\r
89 static XIntc xInterruptController;\r
90 \r
91 /*-----------------------------------------------------------*/\r
92 \r
93 /*\r
94  * Initialise the stack of a task to look exactly as if the task had been\r
95  * interrupted.\r
96  *\r
97  * See the header file portable.h.\r
98  */\r
99 StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )\r
100 {\r
101         /* Place a known value at the bottom of the stack for debugging. */\r
102         *pxTopOfStack = 0xDEADBEEF;\r
103         pxTopOfStack--;\r
104 \r
105         /* EABI stack frame. */\r
106         pxTopOfStack -= 20;     /* Previous backchain and LR, R31 to R4 inclusive. */\r
107 \r
108         /* Parameters in R13. */\r
109         *pxTopOfStack = ( StackType_t ) &_SDA_BASE_; /* address of the first small data area */\r
110         pxTopOfStack -= 10;\r
111 \r
112         /* Parameters in R3. */\r
113         *pxTopOfStack = ( StackType_t ) pvParameters;\r
114         pxTopOfStack--;\r
115 \r
116         /* Parameters in R2. */\r
117         *pxTopOfStack = ( StackType_t ) &_SDA2_BASE_;   /* address of the second small data area */\r
118         pxTopOfStack--;\r
119 \r
120         /* R1 is the stack pointer so is omitted. */\r
121 \r
122         *pxTopOfStack = 0x10000001UL;;  /* R0. */\r
123         pxTopOfStack--;\r
124         *pxTopOfStack = 0x00000000UL;   /* USPRG0. */\r
125         pxTopOfStack--;\r
126         *pxTopOfStack = 0x00000000UL;   /* CR. */\r
127         pxTopOfStack--;\r
128         *pxTopOfStack = 0x00000000UL;   /* XER. */\r
129         pxTopOfStack--;\r
130         *pxTopOfStack = 0x00000000UL;   /* CTR. */\r
131         pxTopOfStack--;\r
132         *pxTopOfStack = ( StackType_t ) vPortEndScheduler;      /* LR. */\r
133         pxTopOfStack--;\r
134         *pxTopOfStack = ( StackType_t ) pxCode; /* SRR0. */\r
135         pxTopOfStack--;\r
136         *pxTopOfStack = portINITIAL_MSR;/* SRR1. */\r
137         pxTopOfStack--;\r
138         *pxTopOfStack = ( StackType_t ) vPortEndScheduler;/* Next LR. */\r
139         pxTopOfStack--;\r
140         *pxTopOfStack = 0x00000000UL;/* Backchain. */\r
141 \r
142         return pxTopOfStack;\r
143 }\r
144 /*-----------------------------------------------------------*/\r
145 \r
146 BaseType_t xPortStartScheduler( void )\r
147 {\r
148         prvSetupTimerInterrupt();\r
149         XExc_RegisterHandler( XEXC_ID_SYSTEM_CALL, ( XExceptionHandler ) vPortYield, ( void * ) 0 );\r
150         vPortStartFirstTask();\r
151 \r
152         /* Should not get here as the tasks are now running! */\r
153         return pdFALSE;\r
154 }\r
155 /*-----------------------------------------------------------*/\r
156 \r
157 void vPortEndScheduler( void )\r
158 {\r
159         /* Not implemented. */\r
160         for( ;; );\r
161 }\r
162 /*-----------------------------------------------------------*/\r
163 \r
164 /*\r
165  * Hardware initialisation to generate the RTOS tick.\r
166  */\r
167 static void prvSetupTimerInterrupt( void )\r
168 {\r
169 const uint32_t ulInterval = ( ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL );\r
170 \r
171         XTime_DECClearInterrupt();\r
172         XTime_FITClearInterrupt();\r
173         XTime_WDTClearInterrupt();\r
174         XTime_WDTDisableInterrupt();\r
175         XTime_FITDisableInterrupt();\r
176 \r
177         XExc_RegisterHandler( XEXC_ID_DEC_INT, ( XExceptionHandler ) vPortTickISR, ( void * ) 0 );\r
178 \r
179         XTime_DECEnableAutoReload();\r
180         XTime_DECSetInterval( ulInterval );\r
181         XTime_DECEnableInterrupt();\r
182 }\r
183 /*-----------------------------------------------------------*/\r
184 \r
185 void vPortISRHandler( void *pvNullDoNotUse )\r
186 {\r
187 uint32_t ulInterruptStatus, ulInterruptMask = 1UL;\r
188 BaseType_t xInterruptNumber;\r
189 XIntc_Config *pxInterruptController;\r
190 XIntc_VectorTableEntry *pxTable;\r
191 \r
192         /* Just to remove compiler warning. */\r
193         ( void ) pvNullDoNotUse;\r
194 \r
195         /* Get the configuration by using the device ID - in this case it is\r
196         assumed that only one interrupt controller is being used. */\r
197         pxInterruptController = &XIntc_ConfigTable[ XPAR_XPS_INTC_0_DEVICE_ID ];\r
198 \r
199         /* Which interrupts are pending? */\r
200         ulInterruptStatus = XIntc_mGetIntrStatus( pxInterruptController->BaseAddress );\r
201 \r
202         for( xInterruptNumber = 0; xInterruptNumber < XPAR_INTC_MAX_NUM_INTR_INPUTS; xInterruptNumber++ )\r
203         {\r
204                 if( ulInterruptStatus & 0x01UL )\r
205                 {\r
206                         /* Clear the pending interrupt. */\r
207                         XIntc_mAckIntr( pxInterruptController->BaseAddress, ulInterruptMask );\r
208 \r
209                         /* Call the registered handler. */\r
210                         pxTable = &( pxInterruptController->HandlerTable[ xInterruptNumber ] );\r
211                         pxTable->Handler( pxTable->CallBackRef );\r
212                 }\r
213 \r
214                 /* Check the next interrupt. */\r
215                 ulInterruptMask <<= 0x01UL;\r
216                 ulInterruptStatus >>= 0x01UL;\r
217 \r
218                 /* Have we serviced all interrupts? */\r
219                 if( ulInterruptStatus == 0UL )\r
220                 {\r
221                         break;\r
222                 }\r
223         }\r
224 }\r
225 /*-----------------------------------------------------------*/\r
226 \r
227 void vPortSetupInterruptController( void )\r
228 {\r
229 extern void vPortISRWrapper( void );\r
230 \r
231         /* Perform all library calls necessary to initialise the exception table\r
232         and interrupt controller.  This assumes only one interrupt controller is in\r
233         use. */\r
234         XExc_mDisableExceptions( XEXC_NON_CRITICAL );\r
235         XExc_Init();\r
236 \r
237         /* The library functions save the context - we then jump to a wrapper to\r
238         save the stack into the TCB.  The wrapper then calls the handler defined\r
239         above. */\r
240         XExc_RegisterHandler( XEXC_ID_NON_CRITICAL_INT, ( XExceptionHandler ) vPortISRWrapper, NULL );\r
241         XIntc_Initialize( &xInterruptController, XPAR_XPS_INTC_0_DEVICE_ID );\r
242         XIntc_Start( &xInterruptController, XIN_REAL_MODE );\r
243 }\r
244 /*-----------------------------------------------------------*/\r
245 \r
246 BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID, XInterruptHandler pxHandler, void *pvCallBackRef )\r
247 {\r
248 BaseType_t xReturn = pdFAIL;\r
249 \r
250         /* This function is defined here so the scope of xInterruptController can\r
251         remain within this file. */\r
252 \r
253         if( XST_SUCCESS == XIntc_Connect( &xInterruptController, ucInterruptID, pxHandler, pvCallBackRef ) )\r
254         {\r
255                 XIntc_Enable( &xInterruptController, ucInterruptID );\r
256                 xReturn = pdPASS;\r
257         }\r
258 \r
259         return xReturn;\r
260 }\r