1 /* -------------------------------- Arctic Core ------------------------------
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
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>.
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
14 * -------------------------------- Arctic Core ------------------------------*/
25 extern void Os_CfgGetInterruptStackInfo( OsStackType *stack );
26 extern uint32_t McuE_GetSystemClock( void );
27 extern OsTickType OsTickFreq;
31 Os_IntCounterType Os_IntDisableAllCnt;
32 Os_IntCounterType Os_IntSuspendAllCnt;
33 Os_IntCounterType Os_IntSuspendOsCnt;
36 * Initialize alarms and schedule-tables for the counters
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);
46 SLIST_INIT(&counter->alarm_head);
47 for(int j=0; j < Os_CfgGetAlarmCnt(); j++ ) {
48 alarm_obj = Os_CfgGetAlarmObj(j);
50 SLIST_INSERT_HEAD(&counter->alarm_head,alarm_obj, alarm_list);
53 SLIST_INIT(&counter->sched_head);
54 for(int j=0; j < Os_CfgGetSchedCnt(); j++ ) {
55 sched_obj = Os_CfgGetSched(j);
57 SLIST_INSERT_HEAD(&counter->sched_head,
71 static void os_resource_init( void ) {
72 //TAILQ_INIT(&pcb_p->resource_head);
74 OsResourceType *rsrc_p;
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
82 for( int i=0; i < Os_CfgGetResourceCnt(); i++) {
83 rsrc_p = Os_CfgGetResource(i);
86 for( int pi = 0; pi < Os_CfgGetTaskCnt(); pi++) {
88 pcb_p = os_get_pcb(pi);
89 if(pcb_p->resourceAccess & (1<<i) ) {
90 topPrio = MAX(topPrio,pcb_p->prio);
93 rsrc_p->ceiling_priority = topPrio;
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.
104 * Assign an internal resource with prio 32 to the tasks
105 * with scheduling=NON
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;
119 * Copy rom pcb data(r_pcb) to ram data
121 * @param pcb ram data
122 * @param r_pcb rom data
125 static void os_pcb_rom_copy( OsPcbType *pcb, const OsRomPcbType *r_pcb ) {
128 // Check to that the memory is ok
130 int cnt = sizeof(OsPcbType);
131 for(int i=0;i<cnt;i++) {
132 if( *((unsigned char *)pcb) != 0 ) {
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);
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);
159 static _Bool init_os_called = 0;
162 * Initialization of kernel structures and start of the first
166 void InitOS( void ) {
169 OsStackType int_stack;
173 DEBUG(DEBUG_LOW,"os_init");
176 memset(&os_sys,0,sizeof(sys_t));
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);
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
189 // Init counter.. with alarms and schedule tables
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);
200 assert(tmp_pcb->prio<=OS_TASK_PRIORITY_MAX);
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);
207 TAILQ_INIT(&tmp_pcb->resource_head);
211 DEBUG(DEBUG_LOW,"pid:%d name:%s prio:%d\n",tmp_pcb->pid,tmp_pcb->name,tmp_pcb->prio);
216 // Now all tasks should be created.
219 static void os_start( void ) {
222 // We will be setting up interrupts,
223 // but we don't want them to fire just yet
226 assert(init_os_called);
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();
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;
243 if( autoPtr->autostartType == ALARM_AUTOSTART_ABSOLUTE ) {
244 SetAbsAlarm(j,autoPtr->alarmTime, autoPtr->cycleTime);
246 SetRelAlarm(j,autoPtr->alarmTime, autoPtr->cycleTime);
251 // Set up the systick interrupt
253 uint32_t sys_freq = McuE_GetSystemClock();
255 Os_SysTickStart(sys_freq/OsTickFreq);
258 /* Find highest Autostart task */
260 OsPcbType *iterPcbPtr;
261 OsPriorityType topPrio = -1;
263 TAILQ_FOREACH(iterPcbPtr,& os_sys.pcb_head,pcb_list) {
264 if( iterPcbPtr->autostart ) {
265 if( iterPcbPtr->prio > topPrio ) {
266 tmp_pcb = iterPcbPtr;
272 // Swap in prio proc.
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
284 static void os_start( void ) {
289 #define TEST_DATA 12345
290 int test_data = TEST_DATA;
298 extern void EcuM_Init();
308 * @param Mode - Application mode to start in
311 void StartOS(AppModeType Mode) {
313 /* Check link file */
314 if (TEST_DATA != test_data) {
333 * @param Error - Reason for shutdown
337 void ShutdownOS( StatusType Error ) {
339 if( os_sys.hooks->ShutdownHook != NULL ) {
340 os_sys.hooks->ShutdownHook(Error);