]> rtime.felk.cvut.cz Git - arc.git/blob - system/kernel/init.c
Merge branch 'mikulka' of git@rtime.felk.cvut.cz:arc into mikulka
[arc.git] / system / kernel / init.c
1 /* -------------------------------- Arctic Core ------------------------------\r
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com\r
3  *\r
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>\r
5  *\r
6  * This source code is free software; you can redistribute it and/or modify it\r
7  * under the terms of the GNU General Public License version 2 as published by the\r
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.\r
9  *\r
10  * This program is distributed in the hope that it will be useful, but\r
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
13  * for more details.\r
14  * -------------------------------- Arctic Core ------------------------------*/\r
15 \r
16 /* ----------------------------[includes]------------------------------------*/\r
17 #include <stdlib.h>\r
18 #include <string.h>\r
19 #include "Os.h"\r
20 #include "internal.h"\r
21 #include "arc.h"\r
22 #include "debug.h"\r
23 #include "task_i.h"\r
24 #include "sys.h"\r
25 #include "isr.h"\r
26 #include "counter_i.h"\r
27 #include "application.h"\r
28 #include "sched_table_i.h"\r
29 #include "alarm_i.h"\r
30 #include "arch.h"\r
31 \r
32 /* ----------------------------[private define]------------------------------*/\r
33 /* ----------------------------[private macro]-------------------------------*/\r
34 #define OS_VALIDATE(_a,_b)   if((_a)!=(_b) ) { \\r
35                                                                 assert(#_a  #_b); \\r
36                                                           }\r
37 /* ----------------------------[private typedef]-----------------------------*/\r
38 /* ----------------------------[private function prototypes]-----------------*/\r
39 /* ----------------------------[private variables]---------------------------*/\r
40 Os_SysType Os_Sys;\r
41 \r
42 Os_IntCounterType Os_IntDisableAllCnt;\r
43 Os_IntCounterType Os_IntSuspendAllCnt;\r
44 Os_IntCounterType Os_IntSuspendOsCnt;\r
45 \r
46 OsErrorType os_error;\r
47 \r
48 /* ----------------------------[private functions]---------------------------*/\r
49 \r
50 \r
51 static void Os_CfgValidate(void ) {\r
52 #if (OS_COUNTER_CNT!=0)\r
53         OS_VALIDATE(OS_COUNTER_CNT,ARRAY_SIZE(counter_list));\r
54 #endif\r
55 #if (OS_RESOURCE_CNT!=0)\r
56         OS_VALIDATE(OS_RESOURCE_CNT,ARRAY_SIZE(resource_list));\r
57 #endif\r
58         OS_VALIDATE(OS_TASK_CNT ,ARRAY_SIZE( Os_TaskConstList));\r
59 #if (OS_ALARM_CNT!=0)\r
60         OS_VALIDATE(OS_ALARM_CNT,ARRAY_SIZE(alarm_list));\r
61 #endif\r
62 #if (OS_SCHTBL_CNT!=0)\r
63         OS_VALIDATE(OS_SCHTBL_CNT, ARRAY_SIZE(sched_list));\r
64 #endif\r
65 }\r
66 \r
67 /* ----------------------------[public functions]----------------------------*/\r
68 \r
69 extern uint32_t McuE_GetSystemClock( void );\r
70 \r
71 \r
72 /**\r
73  * Copy rom pcb data(r_pcb) to ram data\r
74  *\r
75  * @param       pcb             ram data\r
76  * @param       r_pcb   rom data\r
77  */\r
78 \r
79 static void copyPcbParts( OsTaskVarType *pcb, const OsTaskConstType *r_pcb ) {\r
80         assert(r_pcb->prio<=OS_TASK_PRIORITY_MAX);\r
81         pcb->activePriority = r_pcb->prio;\r
82         pcb->stack= r_pcb->stack;\r
83         pcb->constPtr = r_pcb;\r
84 }\r
85 \r
86 static _Bool init_os_called = 0;\r
87 \r
88 /**\r
89  * Initialization of kernel structures and start of the first\r
90  * task.\r
91  */\r
92 \r
93 void InitOS( void ) {\r
94         int i;\r
95         OsTaskVarType *tmpPcbPtr;\r
96         OsIsrStackType intStack;\r
97 \r
98         init_os_called = 1;\r
99 \r
100         Os_CfgValidate();\r
101 \r
102         DEBUG(DEBUG_LOW,"os_init");\r
103 \r
104         /* Clear sys */\r
105         memset(&Os_Sys,0,sizeof(Os_SysType));\r
106 \r
107         Os_ArchInit();\r
108 \r
109         /* Get the numbers defined in the editor */\r
110         Os_Sys.isrCnt = OS_ISR_CNT;\r
111 \r
112         // Assign pcb list and init ready queue\r
113         Os_Sys.pcb_list = Os_TaskVarList;\r
114         TAILQ_INIT(& Os_Sys.ready_head);\r
115 //      TAILQ_INIT(& Os_Sys.pcb_head);\r
116 #if defined(USE_KERNEL_EXTRA)\r
117         TAILQ_INIT(& Os_Sys.timerHead);\r
118 #endif\r
119 \r
120         // Calc interrupt stack\r
121         Os_IsrGetStackInfo(&intStack);\r
122         // TODO: 16 is arch dependent\r
123         Os_Sys.intStack = (void *)((size_t)intStack.top + (size_t)intStack.size - 16);\r
124 \r
125         // Init counter.. with alarms and schedule tables\r
126 #if OS_COUNTER_CNT!=0\r
127         Os_CounterInit();\r
128 #endif\r
129 #if OS_SCHTBL_CNT!=0\r
130         Os_SchTblInit();\r
131 #endif\r
132 \r
133         // Put all tasks in the pcb list\r
134         // Put the one that belong in the ready queue there\r
135         // TODO: we should really hash on priority here to get speed, but I don't care for the moment\r
136         // TODO: Isn't this just EXTENED tasks ???\r
137         for( i=0; i < OS_TASK_CNT; i++) {\r
138                 tmpPcbPtr = Os_TaskGet(i);\r
139 \r
140                 copyPcbParts(tmpPcbPtr,&Os_TaskConstList[i]);\r
141                 Os_TaskContextInit(tmpPcbPtr);\r
142                 TAILQ_INIT(&tmpPcbPtr->resourceHead);\r
143 \r
144 #if 0\r
145                 Os_AddTask(tmpPcbPtr);\r
146 #endif\r
147 \r
148                 DEBUG(DEBUG_LOW,"pid:%d name:%s prio:%d\n",tmpPcbPtr->pid,tmpPcbPtr->name,tmpPcbPtr->prio);\r
149         }\r
150 \r
151         Os_ResourceInit();\r
152 \r
153         // Now all tasks should be created.\r
154 }\r
155 \r
156 static void os_start( void ) {\r
157         uint16_t i;\r
158         OsTaskVarType *tmpPcbPtr = NULL;\r
159 \r
160         // We will be setting up interrupts,\r
161         // but we don't want them to fire just yet\r
162         Irq_Disable();\r
163 \r
164         assert(init_os_called);\r
165 \r
166         /* TODO: fix ugly */\r
167         /* Call the startup hook */\r
168         extern struct OsHooks os_conf_global_hooks;\r
169         Os_Sys.hooks = &os_conf_global_hooks;\r
170         if( Os_Sys.hooks->StartupHook!=NULL ) {\r
171                 Os_Sys.hooks->StartupHook();\r
172         }\r
173 \r
174 \r
175 #if     (OS_USE_APPLICATIONS == STD_ON)\r
176         /* Start applications */\r
177         Os_ApplStart();\r
178 #endif\r
179 \r
180 \r
181         /* Alarm autostart */\r
182 #if OS_ALARM_CNT!=0\r
183         Os_AlarmAutostart();\r
184 #endif\r
185 \r
186 #if OS_SCHTBL_CNT!=0\r
187         Os_SchTblAutostart();\r
188 #endif\r
189 \r
190         // Set up the systick interrupt\r
191         {\r
192                 uint32_t sys_freq = McuE_GetSystemClock();\r
193                 Os_SysTickInit();\r
194                 Os_SysTickStart(sys_freq/OsTickFreq);\r
195         }\r
196 \r
197         /* Find highest Autostart task */\r
198         {\r
199                 OsTaskVarType *iterPcbPtr;\r
200                 OsPriorityType topPrio = -1;\r
201 \r
202                 for(i=0;i<OS_TASK_CNT;i++) {\r
203                         iterPcbPtr = Os_TaskGet(i);\r
204                         if(     iterPcbPtr->constPtr->autostart ) {\r
205                                 if( iterPcbPtr->activePriority > topPrio ) {\r
206                                         tmpPcbPtr = iterPcbPtr;\r
207                                         topPrio = iterPcbPtr->activePriority;\r
208                                 }\r
209                         }\r
210                 }\r
211 #if 0\r
212                 TAILQ_FOREACH(iterPcbPtr,& Os_Sys.pcb_head,pcb_list) {\r
213                         if(     iterPcbPtr->constPtr->autostart ) {\r
214                                 if( iterPcbPtr->activePriority > topPrio ) {\r
215                                         tmpPcbPtr = iterPcbPtr;\r
216                                         topPrio = iterPcbPtr->activePriority;\r
217                                 }\r
218                         }\r
219                 }\r
220 #endif\r
221         }\r
222 \r
223         // Swap in prio proc.\r
224         {\r
225                 // FIXME: Do this in a more structured way.. setting Os_Sys.currTaskPtr manually is not the way to go..\r
226                 Os_Sys.currTaskPtr = tmpPcbPtr;\r
227 #if     (OS_USE_APPLICATIONS == STD_ON)\r
228                 /* Set current application */\r
229                 Os_Sys.currApplId = tmpPcbPtr->constPtr->applOwnerId;\r
230 #endif\r
231 \r
232                 // register this auto-start activation\r
233                 assert(tmpPcbPtr->activations < tmpPcbPtr->constPtr->activationLimit);\r
234                 tmpPcbPtr->activations++;\r
235 \r
236                 // NOTE! We don't go for os_swap_context() here..\r
237                 // first arg(NULL) is dummy only\r
238                 Os_TaskSwapContextTo(NULL,tmpPcbPtr);\r
239                 // We should not return here\r
240                 assert(0);\r
241         }\r
242 }\r
243 #if 0\r
244 static void os_start( void ) {\r
245 \r
246 }\r
247 #endif\r
248 \r
249 #define TEST_DATA  0x12345\r
250 #define TEST_SDATA2     0x3344\r
251 volatile uint32_t test_data = TEST_DATA;\r
252 volatile uint32_t test_bss = 0;\r
253 /* Define if compiler is set to use small data section */\r
254 /* #define CC_USE_SMALL_DATA */\r
255 \r
256 #if defined(CFG_PPC) && defined(__CWCC__)\r
257 /* Note! It does not matter if the data is initialized to 0,\r
258  * it still sbss2.
259  */\r
260 #if defined(CC_USE_SMALL_DATA)\r
261 volatile const int test_sbss2;\r
262 #endif\r
263 /* Initialized small data */\r
264 volatile const int test_sdata2 = TEST_SDATA2;\r
265 \r
266 #endif\r
267 \r
268 \r
269 #define BAD_LINK_FILE()         while(1) {}\r
270 \r
271 extern void EcuM_Init();\r
272 int main( void )\r
273 {\r
274         /* Check link file */\r
275         if (TEST_DATA != test_data) {\r
276                 BAD_LINK_FILE();\r
277         }\r
278 \r
279         if (test_bss != 0) {\r
280                 BAD_LINK_FILE();\r
281         }\r
282 \r
283 #if defined(CFG_PPC) && defined(__CWCC__)\r
284         /* check sdata2 */\r
285         if (test_sdata2 != TEST_SDATA2) {\r
286                 BAD_LINK_FILE();\r
287         }\r
288 #endif\r
289 \r
290 #if defined(CC_USE_SMALL_DATA) && defined(CFG_PPC) && defined(__CWCC__)\r
291         /* check sdata2 */\r
292         if (test_sbss2 != 0) {\r
293                 BAD_LINK_FILE();\r
294         }\r
295 #endif\r
296 \r
297         EcuM_Init();\r
298 \r
299 }\r
300 \r
301 /**\r
302  * Starts the OS\r
303  *\r
304  * @param Mode - Application mode to start in\r
305  *\r
306  */\r
307 void StartOS(AppModeType Mode) {\r
308 \r
309         Os_Sys.appMode = Mode;\r
310 \r
311         Os_CfgValidate();\r
312 \r
313         os_start();\r
314 \r
315         /** @req OS424 */\r
316         assert(0);\r
317 }\r
318 \r
319 /**\r
320  * OS shutdown\r
321  *\r
322  * @param Error - Reason for shutdown\r
323  */\r
324 \r
325 /** @req OS071 */\r
326 void ShutdownOS( StatusType Error ) {\r
327 \r
328         if( Os_Sys.hooks->ShutdownHook != NULL ) {\r
329                 Os_Sys.hooks->ShutdownHook(Error);\r
330         }\r
331 \r
332         Irq_Disable();\r
333         /** @req OS425 */\r
334         while(1) {      }\r
335 \r
336 }\r
337 \r
338 \r
339 \r