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