]> rtime.felk.cvut.cz Git - arc.git/blob - system/kernel/init.c
Header corrections. Brand new printf() implementation. OS debug and debug partly...
[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 "debug.h"
23 #include "arch.h"
24
25 extern void Os_CfgGetInterruptStackInfo( 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 < Os_CfgGetCounterCnt() ; i++) {
44                 counter = Os_CfgGetCounter(i);
45                 // Alarms
46                 SLIST_INIT(&counter->alarm_head);
47                 for(int j=0; j < Os_CfgGetAlarmCnt(); j++ ) {
48                         alarm_obj = Os_CfgGetAlarmObj(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 < Os_CfgGetSchedCnt(); j++ ) {
55                         sched_obj = Os_CfgGetSched(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 < Os_CfgGetResourceCnt(); i++) {
83                 rsrc_p = Os_CfgGetResource(i);
84                 topPrio = 0;
85
86                 for( int pi = 0; pi < Os_CfgGetTaskCnt(); 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
97
98         /* From OSEK:
99          * Non preemptable tasks are the most common usage of the concept
100          * of internal resources; they are tasks with a special internal
101          * resource of highest task priority assigned.
102          * --> Interpret this as we can set the priority to 32.
103          *
104          * Assign an internal resource with prio 32 to the tasks
105          * with scheduling=NON
106          *
107          *
108          */
109         for( int i; i < Os_CfgGetTaskCnt(); i++) {
110                 pcb_p = os_get_pcb(i);
111                 if(pcb_p->scheduling == NON ) {
112                         pcb_p->prio = OS_RES_SCHEDULER_PRIO;
113                 }
114         }
115 }
116
117
118 /**
119  * Copy rom pcb data(r_pcb) to ram data
120  *
121  * @param       pcb             ram data
122  * @param       r_pcb   rom data
123  */
124
125 static void os_pcb_rom_copy( OsPcbType *pcb, const OsRomPcbType *r_pcb ) {
126
127 #if 0 //?????
128         // Check to that the memory is ok
129         {
130                 int cnt = sizeof(OsPcbType);
131                 for(int i=0;i<cnt;i++) {
132                         if( *((unsigned char *)pcb) != 0 ) {
133                                 while(1);
134                         }
135                 }
136         }
137 #endif
138
139 //      memset(pcb,sizeof(OsPcbType),0);
140         pcb->pid = r_pcb->pid;
141         pcb->prio = r_pcb->prio;
142 #if ( OS_SC3 == STD_ON ) || ( OS_SC4 == STD_ON )
143         pcb->application = Os_CfgGetApplObj(r_pcb->application_id);
144 #endif
145         pcb->entry = r_pcb->entry;
146         pcb->proc_type = r_pcb->proc_type;
147         pcb->autostart =  r_pcb->autostart;
148         pcb->stack= r_pcb->stack;
149         pcb->pcb_rom_p = r_pcb;
150         pcb->resource_int_p = r_pcb->resource_int_p;
151         pcb->scheduling = r_pcb->scheduling;
152         pcb->resourceAccess = r_pcb->resourceAccess;
153         pcb->activationLimit = r_pcb->activationLimit;
154 //      pcb->app = &app_list[r_pcb->app];
155 //      pcb->app_mask = app_mask[r_pcb->app];
156         strncpy(pcb->name,r_pcb->name,16);
157 }
158
159 static _Bool init_os_called = 0;
160
161 /**
162  * Initialization of kernel structures and start of the first
163  * task.
164  */
165
166 void InitOS( void ) {
167         int i;
168         OsPcbType *tmp_pcb;
169         OsStackType int_stack;
170
171         init_os_called = 1;
172
173         DEBUG(DEBUG_LOW,"os_init");
174
175         /* Clear sys */
176         memset(&os_sys,0,sizeof(sys_t));
177
178         Os_ArchInit();
179
180         // Assign pcb list and init ready queue
181         os_sys.pcb_list = pcb_list;
182         TAILQ_INIT(& os_sys.ready_head);
183         TAILQ_INIT(& os_sys.pcb_head);
184
185         // Calc interrupt stack
186         Os_CfgGetInterruptStackInfo(&int_stack);
187         os_sys.int_stack = int_stack.top + int_stack.size - 16;         // TODO: 16 is arch dependent
188
189         // Init counter.. with alarms and schedule tables
190         os_counter_init();
191         Os_SchTblInit();
192
193         // Put all tasks in the pcb list
194         // Put the one that belong in the ready queue there
195         // TODO: we should really hash on priority here to get speed, but I don't care for the moment
196         // TODO: Isn't this just EXTENED tasks ???
197         for( i=0; i < Os_CfgGetTaskCnt(); i++) {
198                 tmp_pcb = os_get_pcb(i);
199
200                 assert(tmp_pcb->prio<=OS_TASK_PRIORITY_MAX);
201
202                 os_pcb_rom_copy(tmp_pcb,os_get_rom_pcb(i));
203                 if( !(tmp_pcb->proc_type & PROC_ISR) ) {
204                         Os_ContextInit(tmp_pcb);
205                 }
206
207                 TAILQ_INIT(&tmp_pcb->resource_head);
208
209                 Os_AddTask(tmp_pcb);
210
211                 DEBUG(DEBUG_LOW,"pid:%d name:%s prio:%d\n",tmp_pcb->pid,tmp_pcb->name,tmp_pcb->prio);
212         }
213
214         os_resource_init();
215
216         // Now all tasks should be created.
217 }
218
219 static void os_start( void ) {
220         OsPcbType *tmp_pcb;
221
222         // We will be setting up interrupts,
223         // but we don't want them to fire just yet
224         Irq_Disable();
225
226         assert(init_os_called);
227
228         /* TODO: fix ugly */
229         /* Call the startup hook */
230         extern struct OsHooks os_conf_global_hooks;
231         os_sys.hooks = &os_conf_global_hooks;
232         if( os_sys.hooks->StartupHook!=NULL ) {
233                 os_sys.hooks->StartupHook();
234         }
235
236         /* handle autostart */
237         for(int j=0; j < Os_CfgGetAlarmCnt(); j++ ) {
238                 OsAlarmType *alarmPtr;
239                 alarmPtr = Os_CfgGetAlarmObj(j);
240                 if(alarmPtr->autostartPtr != NULL ) {
241                         const OsAlarmAutostartType *autoPtr = alarmPtr->autostartPtr;
242
243                         if( autoPtr->autostartType == ALARM_AUTOSTART_ABSOLUTE ) {
244                                 SetAbsAlarm(j,autoPtr->alarmTime, autoPtr->cycleTime);
245                         } else {
246                                 SetRelAlarm(j,autoPtr->alarmTime, autoPtr->cycleTime);
247                         }
248                 }
249         }
250
251         // Set up the systick interrupt
252         {
253                 uint32_t sys_freq = McuE_GetSystemClock();
254                 Os_SysTickInit();
255                 Os_SysTickStart(sys_freq/OsTickFreq);
256         }
257
258         /* Find highest Autostart task */
259         {
260                 OsPcbType *iterPcbPtr;
261                 OsPriorityType topPrio = -1;
262
263                 TAILQ_FOREACH(iterPcbPtr,& os_sys.pcb_head,pcb_list) {
264                         if(     iterPcbPtr->autostart ) {
265                                 if( iterPcbPtr->prio > topPrio ) {
266                                         tmp_pcb = iterPcbPtr;
267                                 }
268                         }
269                 }
270         }
271
272         // Swap in prio proc.
273         {
274                 // FIXME: Do this in a more structured way.. setting os_sys.curr_pcb manually is not the way to go..
275                 os_sys.curr_pcb = tmp_pcb;
276                 // NOTE! We don't go for os_swap_context() here..
277                 // first arg(NULL) is dummy only
278                 Os_TaskSwapContextTo(NULL,tmp_pcb);
279                 // We should not return here
280                 assert(0);
281         }
282 }
283 #if 0
284 static void os_start( void ) {
285
286 }
287 #endif
288
289 #define TEST_DATA  12345
290 int test_data = TEST_DATA;
291 int test_bss = 0;
292
293
294 void noooo( void ) {
295         while(1);
296 }
297
298 extern void EcuM_Init();
299 int main( void )
300 {
301         EcuM_Init();
302
303 }
304
305 /**
306  * Starts the OS
307  *
308  * @param Mode - Application mode to start in
309  *
310  */
311 void StartOS(AppModeType Mode) {
312
313         /* Check link file */
314         if (TEST_DATA != test_data) {
315                 noooo();
316         }
317
318         if (test_bss != 0) {
319                 noooo();
320         }
321
322         Os_CfgValidate();
323
324         os_start();
325
326         /** @req OS424 */
327         assert(0);
328 }
329
330 /**
331  * OS shutdown
332  *
333  * @param Error - Reason for shutdown
334  */
335
336 /** @req OS071 */
337 void ShutdownOS( StatusType Error ) {
338
339         if( os_sys.hooks->ShutdownHook != NULL ) {
340                 os_sys.hooks->ShutdownHook(Error);
341         }
342
343         Irq_Disable();
344         /** @req OS425 */
345         while(1) {      }
346
347 }
348
349
350