1 /* -------------------------------- Arctic Core ------------------------------
\r
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
\r
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
\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
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
14 * -------------------------------- Arctic Core ------------------------------*/
\r
16 /* ----------------------------[includes]------------------------------------*/
\r
20 #include "internal.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
32 /* ----------------------------[private define]------------------------------*/
\r
33 /* ----------------------------[private macro]-------------------------------*/
\r
34 #define OS_VALIDATE(_a,_b) if((_a)!=(_b) ) { \
\r
37 /* ----------------------------[private typedef]-----------------------------*/
\r
38 /* ----------------------------[private function prototypes]-----------------*/
\r
39 /* ----------------------------[private variables]---------------------------*/
\r
42 Os_IntCounterType Os_IntDisableAllCnt;
\r
43 Os_IntCounterType Os_IntSuspendAllCnt;
\r
44 Os_IntCounterType Os_IntSuspendOsCnt;
\r
46 OsErrorType os_error;
\r
48 /* ----------------------------[private functions]---------------------------*/
\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
55 #if (OS_RESOURCE_CNT!=0)
\r
56 OS_VALIDATE(OS_RESOURCE_CNT,ARRAY_SIZE(resource_list));
\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
62 #if (OS_SCHTBL_CNT!=0)
\r
63 OS_VALIDATE(OS_SCHTBL_CNT, ARRAY_SIZE(sched_list));
\r
67 /* ----------------------------[public functions]----------------------------*/
\r
69 extern uint32_t McuE_GetSystemClock( void );
\r
73 * Copy rom pcb data(r_pcb) to ram data
\r
75 * @param pcb ram data
\r
76 * @param r_pcb rom data
\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
86 static _Bool init_os_called = 0;
\r
89 * Initialization of kernel structures and start of the first
\r
93 void InitOS( void ) {
\r
95 OsTaskVarType *tmpPcbPtr;
\r
96 OsIsrStackType intStack;
\r
102 DEBUG(DEBUG_LOW,"os_init");
\r
105 memset(&Os_Sys,0,sizeof(Os_SysType));
\r
109 /* Get the numbers defined in the editor */
\r
110 Os_Sys.isrCnt = OS_ISR_CNT;
\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
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
125 // Init counter.. with alarms and schedule tables
\r
126 #if OS_COUNTER_CNT!=0
\r
129 #if OS_SCHTBL_CNT!=0
\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
140 copyPcbParts(tmpPcbPtr,&Os_TaskConstList[i]);
\r
141 Os_TaskContextInit(tmpPcbPtr);
\r
142 TAILQ_INIT(&tmpPcbPtr->resourceHead);
\r
145 Os_AddTask(tmpPcbPtr);
\r
148 DEBUG(DEBUG_LOW,"pid:%d name:%s prio:%d\n",tmpPcbPtr->pid,tmpPcbPtr->name,tmpPcbPtr->prio);
\r
153 // Now all tasks should be created.
\r
156 static void os_start( void ) {
\r
158 OsTaskVarType *tmpPcbPtr = NULL;
\r
160 // We will be setting up interrupts,
\r
161 // but we don't want them to fire just yet
\r
164 assert(init_os_called);
\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
175 #if (OS_USE_APPLICATIONS == STD_ON)
\r
176 /* Start applications */
\r
181 /* Alarm autostart */
\r
182 #if OS_ALARM_CNT!=0
\r
183 Os_AlarmAutostart();
\r
186 #if OS_SCHTBL_CNT!=0
\r
187 Os_SchTblAutostart();
\r
190 // Set up the systick interrupt
\r
192 uint32_t sys_freq = McuE_GetSystemClock();
\r
194 Os_SysTickStart(sys_freq/OsTickFreq);
\r
197 /* Find highest Autostart task */
\r
199 OsTaskVarType *iterPcbPtr;
\r
200 OsPriorityType topPrio = -1;
\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
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
223 // Swap in prio proc.
\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
232 // register this auto-start activation
\r
233 assert(tmpPcbPtr->activations < tmpPcbPtr->constPtr->activationLimit);
\r
234 tmpPcbPtr->activations++;
\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
244 static void os_start( void ) {
\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
256 #if defined(CFG_PPC) && defined(__CWCC__)
\r
257 /* Note! It does not matter if the data is initialized to 0,
\r
260 #if defined(CC_USE_SMALL_DATA)
\r
261 volatile const int test_sbss2;
\r
263 /* Initialized small data */
\r
264 volatile const int test_sdata2 = TEST_SDATA2;
\r
269 #define BAD_LINK_FILE() while(1) {}
\r
271 extern void EcuM_Init();
\r
274 /* Check link file */
\r
275 if (TEST_DATA != test_data) {
\r
279 if (test_bss != 0) {
\r
283 #if defined(CFG_PPC) && defined(__CWCC__)
\r
285 if (test_sdata2 != TEST_SDATA2) {
\r
290 #if defined(CC_USE_SMALL_DATA) && defined(CFG_PPC) && defined(__CWCC__)
\r
292 if (test_sbss2 != 0) {
\r
304 * @param Mode - Application mode to start in
\r
307 void StartOS(AppModeType Mode) {
\r
309 Os_Sys.appMode = Mode;
\r
322 * @param Error - Reason for shutdown
\r
326 void ShutdownOS( StatusType Error ) {
\r
328 if( Os_Sys.hooks->ShutdownHook != NULL ) {
\r
329 Os_Sys.hooks->ShutdownHook(Error);
\r