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