]> rtime.felk.cvut.cz Git - arc.git/blob - system/kernel/init.c
Again, loads of refactoring and removing and adding files.
[arc.git] / system / kernel / init.c
1 /* -------------------------------- Arctic Core ------------------------------
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com
3  *
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>
5  *
6  * This source code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 as published by the
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  * -------------------------------- Arctic Core ------------------------------*/
15
16
17 #include <stdlib.h>
18 #include <string.h>
19 #include "Os.h"
20 #include "internal.h"
21 #include "arc.h"
22 #include "Trace.h"
23 #include "arch.h"
24
25 extern void Oil_GetInterruptStackInfo( OsStackType *stack );
26 extern uint32_t McuE_GetSystemClock( void );
27 extern OsTickType OsTickFreq;
28
29 sys_t os_sys;
30
31 Os_IntCounterType Os_IntDisableAllCnt;
32 Os_IntCounterType Os_IntSuspendAllCnt;
33 Os_IntCounterType Os_IntSuspendOsCnt;
34
35 /**
36  * Initialize alarms and schedule-tables for the counters
37  */
38 static void os_counter_init( void ) {
39         OsCounterType *counter;
40         OsAlarmType *alarm_obj;
41         OsSchTblType *sched_obj;
42         /* Create a list from the counter to the alarms */
43         for(int i=0; i < Oil_GetCounterCnt() ; i++) {
44                 counter = Oil_GetCounter(i);
45                 // Alarms
46                 SLIST_INIT(&counter->alarm_head);
47                 for(int j=0; j < Oil_GetAlarmCnt(); j++ ) {
48                         alarm_obj = Oil_GetAlarmObj(j);
49                         // Add the alarms
50                         SLIST_INSERT_HEAD(&counter->alarm_head,alarm_obj, alarm_list);
51                 }
52                 // Schedule tables
53                 SLIST_INIT(&counter->sched_head);
54                 for(int j=0; j < Oil_GetSchedCnt(); j++ ) {
55                         sched_obj = Oil_GetSched(j);
56                         // Add the alarms
57                         SLIST_INSERT_HEAD(&counter->sched_head,
58                                                                 sched_obj,
59                                                                 sched_list);
60                 }
61
62
63         }
64 }
65
66 /**
67  *
68  * @param pcb_p
69  * @return
70  */
71 static void os_resource_init( void ) {
72         //TAILQ_INIT(&pcb_p->resource_head);
73         OsPcbType *pcb_p;
74         OsResourceType *rsrc_p;
75         int topPrio;
76
77         /* Calculate ceiling priority
78          * We make this as simple as possible. The ceiling priority
79          * is set to the same priority as the highest priority task that
80          * access it.
81          * */
82         for( int i=0; i < Oil_GetResourceCnt(); i++) {
83                 rsrc_p = Oil_GetResource(i);
84                 topPrio = 0;
85
86                 for( int pi; pi < Oil_GetTaskCnt(); pi++) {
87
88                         pcb_p = os_get_pcb(pi);
89                         if(pcb_p->resourceAccess & (1<<i) ) {
90                                 topPrio = MAX(topPrio,pcb_p->prio);
91                         }
92                 }
93                 rsrc_p->ceiling_priority = topPrio;
94         }
95
96         /* Assign an internal resource with prio 32 to the tasks
97          * with scheduling=NON
98          */
99         for( int i; i < Oil_GetTaskCnt(); i++) {
100                 pcb_p = os_get_pcb(i);
101                 if(pcb_p->scheduling == NON ) {
102                         pcb_p->prio = OS_RES_SCHEDULER_PRIO;
103                 }
104         }
105 }
106
107
108 /**
109  * Copy rom pcb data(r_pcb) to ram data
110  *
111  * @param       pcb             ram data
112  * @param       r_pcb   rom data
113  */
114
115 static void os_pcb_rom_copy( OsPcbType *pcb, const OsRomPcbType *r_pcb ) {
116
117 #if 0 //?????
118         // Check to that the memory is ok
119         {
120                 int cnt = sizeof(OsPcbType);
121                 for(int i=0;i<cnt;i++) {
122                         if( *((unsigned char *)pcb) != 0 ) {
123                                 while(1);
124                         }
125                 }
126         }
127 #endif
128
129 //      memset(pcb,sizeof(OsPcbType),0);
130         pcb->pid = r_pcb->pid;
131         pcb->prio = r_pcb->prio;
132 #if ( OS_SC1 == STD_ON ) || ( OS_SC4 == STD_ON )
133         pcb->application = Oil_GetApplObj(r_pcb->application_id);
134 #endif
135         pcb->entry = r_pcb->entry;
136         pcb->proc_type = r_pcb->proc_type;
137         pcb->autostart =  r_pcb->autostart;
138         pcb->stack= r_pcb->stack;
139         pcb->pcb_rom_p = r_pcb;
140         pcb->resource_int_p = r_pcb->resource_int_p;
141         pcb->scheduling = r_pcb->scheduling;
142         pcb->resourceAccess = r_pcb->resourceAccess;
143         pcb->activationLimit = r_pcb->activationLimit;
144 //      pcb->app = &app_list[r_pcb->app];
145 //      pcb->app_mask = app_mask[r_pcb->app];
146         strncpy(pcb->name,r_pcb->name,16);
147 }
148
149 static _Bool init_os_called = 0;
150
151 /**
152  * Initialization of kernel structures and start of the first
153  * task.
154  */
155
156 void InitOS( void ) {
157         int i;
158         OsPcbType *tmp_pcb;
159         OsStackType int_stack;
160
161         init_os_called = 1;
162
163         DEBUG(DEBUG_LOW,"os_init");
164
165         /* Clear sys */
166         memset(&os_sys,0,sizeof(sys_t));
167
168         os_arch_init();
169
170         // Assign pcb list and init ready queue
171         os_sys.pcb_list = pcb_list;
172         TAILQ_INIT(& os_sys.ready_head);
173         TAILQ_INIT(& os_sys.pcb_head);
174
175         // Calc interrupt stack
176         Oil_GetInterruptStackInfo(&int_stack);
177         os_sys.int_stack = int_stack.top + int_stack.size - 16;         // TODO: 16 is arch dependent
178
179         // Init counter.. with alarms and schedule tables
180         os_counter_init();
181         Os_SchTblInit();
182         os_resource_init();
183
184         // Put all tasks in the pcb list
185         // Put the one that belong in the ready queue there
186         // TODO: we should really hash on priority here to get speed, but I don't care for the moment
187         // TODO: Isn't this just EXTENED tasks ???
188         for( i=0; i < Oil_GetTaskCnt(); i++) {
189                 tmp_pcb = os_get_pcb(i);
190
191                 assert(tmp_pcb->prio<=OS_TASK_PRIORITY_MAX);
192
193                 os_pcb_rom_copy(tmp_pcb,os_get_rom_pcb(i));
194                 if( !(tmp_pcb->proc_type & PROC_ISR) ) {
195                         Os_ContextInit(tmp_pcb);
196                 }
197
198                 Os_AddTask(tmp_pcb);
199
200                 DEBUG(DEBUG_LOW,"pid:%d name:%s prio:%d\n",tmp_pcb->pid,tmp_pcb->name,tmp_pcb->prio);
201         }
202
203         // Now all tasks should be created.
204 }
205
206 static void os_start( void ) {
207         OsPcbType *tmp_pcb;
208
209         assert(init_os_called);
210
211         /* TODO: fix ugly */
212         /* Call the startup hook */
213         extern struct OsHooks os_conf_global_hooks;
214         os_sys.hooks = &os_conf_global_hooks;
215         if( os_sys.hooks->StartupHook!=NULL ) {
216                 os_sys.hooks->StartupHook();
217         }
218
219         /* handle autostart */
220         for(int j=0; j < Oil_GetAlarmCnt(); j++ ) {
221                 OsAlarmType *alarmPtr;
222                 alarmPtr = Oil_GetAlarmObj(j);
223                 if(alarmPtr->autostart.active) {
224                         OsAlarmAutostartType *autoPtr = &alarmPtr->autostart;
225
226                         SetAbsAlarm(j,autoPtr->alarmtime, autoPtr->cycletime);
227                 }
228         }
229
230         // Activate the systick interrupt
231         {
232                 uint32_t sys_freq = McuE_GetSystemClock();
233                 Frt_Init();
234                 Frt_Start(sys_freq/OsTickFreq);
235         }
236
237         /* Find highest Autostart task */
238         {
239                 OsPcbType *iterPcbPtr;
240                 OsPriorityType topPrio = 0;
241
242                 TAILQ_FOREACH(iterPcbPtr,& os_sys.pcb_head,pcb_list) {
243                         if(     iterPcbPtr->autostart ) {
244                                 if( iterPcbPtr->prio > topPrio ) {
245                                         tmp_pcb = iterPcbPtr;
246                                 }
247                         }
248                 }
249         }
250
251         // Swap in prio proc.
252         {
253                 // FIXME: Do this in a more structured way.. setting os_sys.curr_pcb manually is not the way to go..
254                 os_sys.curr_pcb = tmp_pcb;
255                 // NOTE! We don't go for os_swap_context() here..
256                 // first arg(NULL) is dummy only
257                 Os_TaskSwapContextTo(NULL,tmp_pcb);
258                 // We should not return here
259                 assert(0);
260         }
261 }
262 #if 0
263 static void os_start( void ) {
264
265 }
266 #endif
267
268 #define TEST_DATA  12345
269 int test_data = TEST_DATA;
270 int test_bss = 0;
271
272
273 void noooo( void ) {
274         while(1);
275 }
276
277 extern void EcuM_Init();
278 int main( void )
279 {
280         EcuM_Init();
281
282 }
283
284 /**
285  * Starts the OS
286  *
287  * @param Mode - Application mode to start in
288  *
289  */
290 void StartOS(AppModeType Mode) {
291
292         /* Check link file */
293         if (TEST_DATA != test_data) {
294                 noooo();
295         }
296
297         if (test_bss != 0) {
298                 noooo();
299         }
300
301         os_start();
302
303         /** @req OS424 */
304         assert(0);
305 }
306
307 /**
308  * OS shutdown
309  *
310  * @param Error - Reason for shutdown
311  */
312
313 /** @req OS071 */
314 void ShutdownOS( StatusType Error ) {
315
316         if( os_sys.hooks->ShutdownHook != NULL ) {
317                 os_sys.hooks->ShutdownHook(Error);
318         }
319
320         Irq_Disable();
321         /** @req OS425 */
322         while(1) {      }
323
324 }
325
326
327