AutosarOS
OS.c
Go to the documentation of this file.
1 
14 #include "OS.h"
15 #include "assert.h"
16 #include "context.h"
17 #include "Task.h"
18 #include "Resource.h"
19 #include "ScheduleTables.h"
20 #include "Alarm.h"
21 
22 #include <avr/io.h>
23 #include <avr/interrupt.h>
24 #include <util/atomic.h>
25 
26 /************************************************************************/
27 /* STATIC VARIABLES */
28 /************************************************************************/
32 static TaskType highestPrioTask;
33 
40 static uint8_t intStates;
41 
48 static uint8_t osIntStates;
49 
53 static AppModeType activeApplicationMode;
54 
55 /************************************************************************/
56 /* EXTERNAL VARIABLES */
57 /************************************************************************/
61 uint8_t* volatile* ptrCurrentStack;
62 
67 
68 /************************************************************************/
69 /* STATIC FUNCTIONS */
70 /************************************************************************/
74 static void OS_StartSysTimer()
75 {
76 #if defined(__AVR_ATmega32__) || defined(__AVR_ATmega128__)
77  TCCR0 = 1 << CS02 | 1 << CS00; // Enable Timer0 with Prescaler 1024
78  TIMSK |= 1 << TOIE0; // Enable Overflow Interrupt (Timer0)
79 #elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega2560__)
80  TCCR0A = 0; // Reset Timer0 control A register
81  TCCR0B = 1 << CS02 | 1 << CS00; // Enable Timer0 with Prescaler 1024
82  TIMSK0 |= 1 << TOIE0; // Enable Overflow Interrupt (Timer0)
83 #else
84 #warning Unknown CPU defined. Setup of Timer0 overflow interrupt is required for sysTick and preemptive scheduling.
85 #endif
86 }
87 
88 /************************************************************************/
89 /* EXTERN FUNCTIONS */
90 /************************************************************************/
91 extern void OS_StartOS(AppModeType mode)
92 {
93  OS_SET_ERROR_INFO1(OSServiceId_StartOS, &mode, sizeof(mode));
94 
96 
97  activeApplicationMode = mode;
98 
99  /* Startup subsystems */
100  Task_startup();
102  Alarm_startup();
103 
104 #if defined(OS_CONFIG_HOOK_STARTUP) && OS_CONFIG_HOOK_STARTUP == true
105  StartupHook();
106 #endif
107 
108  OS_StartSysTimer();
109 
110  /* Switch to first task */
111  OS_Switch();
112  init_context();
114 
115 #if defined(OS_CONFIG_HOOK_POST_TASK) && OS_CONFIG_HOOK_POST_TASK == true
116  PreTaskHook();
117 #endif
118 
119  assert(TCB_Cfg[currentTask]->curNumberOfActivations > 0);
120 
122 
124 
125  asm volatile ("ret"); // Force return to prevent function epilogue removing non-existing data from task stack
126 }
127 
128 extern void OS_ShutdownOS(StatusType error)
129 {
130  OS_SET_ERROR_INFO1(OSServiceId_ShutdownOS, &error, sizeof(error));
131 
133 
134 #if defined(OS_CONFIG_HOOK_SHUTDOWN) && OS_CONFIG_HOOK_SHUTDOWN == true
135  ShutdownHook(error);
136 #endif
137 
138  assert(false); // We never want to reach this
139 
140  while (1);
141 }
142 
143 extern void __attribute__((naked)) OS_ScheduleC(void)
144 {
145  save_context();
146 
147 #if defined(OS_CONFIG_STACK_MONITORING) && OS_CONFIG_STACK_MONITORING >= 1
148  /* Calculate stack usage */
149  if (currentTask != INVALID_TASK) {
152  if (TCB_Cfg[currentTask]->curStackUse > TCB_Cfg[currentTask]->maxStackUse) {
153  TCB_Cfg[currentTask]->maxStackUse = TCB_Cfg[currentTask]->curStackUse;
154  }
155 
156 #if OS_CONFIG_STACK_MONITORING >= 2
157  if (*(TCB_Cfg[currentTask]->stack - 1) != 0xBE) {
158  if (TCB_Cfg[currentTask]->maxStackUse <= TCB_Cfg[currentTask]->stackSize) {
159  TCB_Cfg[currentTask]->maxStackUse = TCB_Cfg[currentTask]->stackSize + 1;
160  }
161  }
162 #endif /* OS_CONFIG_STACK_MONITORING >= 2 */
163 
164  if (TCB_Cfg[currentTask]->maxStackUse > TCB_Cfg[currentTask]->stackSize) {
166  }
167  }
168 #endif /* defined(OS_CONFIG_STACK_MONITORING) && OS_CONFIG_STACK_MONITORING >= 1 */
169 
170  assert(!isISR);
171 
172  if (currentTask == INVALID_TASK || (TCB_Cfg[currentTask]->taskSchedule == PREEMPTIVE || forceScheduling)) {
173  // Enter critical section
175 
176  if (currentTask != INVALID_TASK) {
177  if (TCB_Cfg[currentTask]->curState == RUNNING) {
178 #if defined(OS_CONFIG_HOOK_PRE_TASK) && OS_CONFIG_HOOK_PRE_TASK == true
179  PostTaskHook();
180 #endif
181 
183  }
184  }
185 
186  OS_Switch();
187 
188  // Reset scheduling state
189  needScheduling = 0;
190  forceScheduling = false;
191 
192  assert(currentTask != INVALID_TASK);
193 
195 
196  /* Change task state already to prevent changes to SREG */
199 
200 #if defined(OS_CONFIG_HOOK_POST_TASK) && OS_CONFIG_HOOK_POST_TASK == true
201  PreTaskHook();
202 #endif
203 
204  if (prevState == PRE_READY) {
205  // Set context to stack base
207 
208  init_context();
209  } else {
210  restore_context();
211  }
212 
213  /***********************************************/
214  /* NO CHANGE TO SREG MUST OCCUR AT THIS POINT! */
215  /***********************************************/
216 
217  // Leave critical section
219  } else {
220  // Reschedule during system timer interrupt
221  needScheduling = 1;
222 
223  restore_context();
224 
225  /***********************************************/
226  /* NO CHANGE TO SREG MUST OCCUR AT THIS POINT! */
227  /***********************************************/
228  }
229 
230  asm volatile ("ret");
231 }
232 
233 extern void OS_Switch(void)
234 {
235  int16_t highestPrio = -1;
236  highestPrioTask = INVALID_TASK;
237 
238  for (uint8_t i = 0; i < TASK_COUNT; i++) {
239  if ((TCB_Cfg[i]->curState == PRE_READY || TCB_Cfg[i]->curState == READY || TCB_Cfg[i]->curState == RUNNING)
240  && TCB_Cfg[i]->curPrio >= highestPrio) {
241  highestPrio = TCB_Cfg[i]->curPrio;
242  highestPrioTask = (TaskType) i;
243  }
244  }
245 
246  currentTask = highestPrioTask;
249 }
250 
251 extern inline void OS_EnableAllInterrupts(void)
252 {
253  sei(); // Global interrupt enable
254 }
255 
256 extern inline void OS_DisableAllInterrupts(void)
257 {
258  cli(); // Global interrupt disable
259 }
260 
261 extern void OS_ResumeAllInterrupts(void)
262 {
264 
265  bool enable = (intStates & 0b1);
266  intStates = (intStates >> 1);
267 
268  if (enable) {
270  }
271 }
272 
273 extern void OS_SuspendAllInterrupts(void)
274 {
276 
277  intStates = (intStates << 1) | ((SREG >> SREG_I) & 0b1);
278 
280 }
281 
282 extern void OS_ResumeOSInterrupts(void)
283 {
285 
286  bool enable = (osIntStates & 0b1);
287  osIntStates = (osIntStates >> 1);
288 
289  if (enable) {
291  }
292 }
293 
294 extern void OS_SuspendOSInterrupts(void)
295 {
297 
298  osIntStates = (osIntStates << 1) | ((SREG >> SREG_I) & 0b1);
299 
301 }
302 
304 {
306 
307  return activeApplicationMode;
308 }
309 
311 {
313 
314 #if defined(OS_CONFIG_HOOK_PROTECTION) && OS_CONFIG_HOOK_PROTECTION == true
315  // Call hook function if configured
316  ret = ProtectionHook(error);
317 #endif /* defined(OS_CONFIG_HOOK_PROTECTION) && OS_CONFIG_HOOK_PROTECTION == true */
318 
319  if (ret == PRO_IGNORE && error == E_OS_PROTECTION_ARRIVAL) {
320  // Return control to application
321  return;
322  } else if (ret == PRO_TERMINATETASKISR && error != E_OS_PROTECTION_ARRIVAL) {
323  /* Terminate task or ISR */
324  struct resource_s* volatile* resPtr = NULL;
325 
326  if (isISR) {
327  if (isCat2ISR == 0) {
328  // No Cat2 ISR active => shutdown system
329  OS_ShutdownOS(error);
330  }
331 
332  // Set pointer to start of resource queue
333  resPtr = &isrResourceQueue;
334  } else {
335  if (currentTask == INVALID_TASK) {
336  // No task active => shutdown system
337  OS_ShutdownOS(error);
338  }
339 
340  // Set pointer to start of resource queue
341  resPtr = &TCB_Cfg[currentTask]->resourceQueue;
342  }
343 
344  /* Release all resources if necessary */
345  while (*resPtr != NULL) {
346  assert((*resPtr)->assigned == true);
347 
348  // Reset assigned state
349  (*resPtr)->assigned = false;
350 
351  struct resource_s* volatile* tmpPtr = &(*resPtr)->next;
352 
353  // Remove pointer from queue
354  *resPtr = NULL;
355 
356  resPtr = tmpPtr;
357  }
358 
359  /* Resume OS interrupts if necessary */
360  while (osIntStates != 0) {
362  }
363 
364  /* Resume all interrupts if necessary */
365  while (intStates != 0) {
367  }
368 
369  if (isISR) {
370  /* Terminate ISR */
371  isISR = false;
372  isCat2ISR = 0;
373 
374  restore_context();
375  asm volatile("reti");
376  } else {
377  // Reset tasks priority because we force-released all resources
379 
380  // Terminate task
382  }
383  } else {
384  // Shutdown system
385  OS_ShutdownOS(error);
386  }
387 
388  assert(false); // We should not reach this
389 }
390 
391 extern void OS_ShutdownOSStackOverrun(void)
392 {
394 }
task_s::curPrio
uint8_t curPrio
Current priority.
Definition: TaskTypes.h:95
TaskType
enum tasks_e TaskType
Type for task reference.
Definition: TaskTypes.h:29
Task_TerminateTask
StatusType Task_TerminateTask(void)
Terminate active task.
Definition: Task.c:115
ProtectionReturnType
enum ProtectionReturnType_e ProtectionReturnType
Return type for protection hook.
PRO_TERMINATETASKISR
@ PRO_TERMINATETASKISR
Terminate faulty task or ISR.
Definition: Types.h:59
StatusType
enum StatusType_e StatusType
Type for status.
isrResourceQueue
struct resource_s *volatile isrResourceQueue
Resource queue for resources taken by Cat2 ISRs.
Definition: OCB.c:32
restore_context
void restore_context(void)
Restore context of current task.
__attribute__
void __attribute__((naked))
Task switch.
Definition: OS.c:143
ptrCurrentStack
uint8_t *volatile * ptrCurrentStack
Stack-Pointer saved in current task control block.
Definition: OS.c:61
ScheduleTables.h
Schedule tables management.
OS.h
Operating system control.
PRO_IGNORE
@ PRO_IGNORE
Ignore protection error.
Definition: Types.h:58
StartupHook
void StartupHook(void)
Definition: App.c:702
OS_ShutdownOSStackOverrun
void OS_ShutdownOSStackOverrun(void)
Call OS_ShutdownOS() with E_OS_STACKFAULT.
Definition: OS.c:391
task_s::resourceQueue
struct resource_s * resourceQueue
Current queue of allocated resources.
Definition: TaskTypes.h:104
ProtectionHook
ProtectionReturnType ProtectionHook(StatusType fatalError)
ProtectionHook function.
Definition: App.c:797
Task.h
Task management.
ScheduleTable_startup
void ScheduleTable_startup(void)
Startup function for schedule table management.
Definition: ScheduleTables.c:343
assert.h
Assert macros and functions.
E_OS_PROTECTION_ARRIVAL
@ E_OS_PROTECTION_ARRIVAL
Definition: Types.h:51
currentTask
volatile TaskType currentTask
Task currently being executed.
Definition: OCB.c:23
OS_Switch
void OS_Switch(void)
Switch to new task.
Definition: OS.c:233
PREEMPTIVE
@ PREEMPTIVE
The task may be preempted by another task.
Definition: TaskTypes.h:50
OSServiceId_ResumeOSInterrupts
@ OSServiceId_ResumeOSInterrupts
Definition: ErrorTypes.h:43
Resource.h
Resource management.
OS_SET_ERROR_INFO1
#define OS_SET_ERROR_INFO1(serviceId, paramPtr1, size1)
Set error info with up to one parameter.
Definition: ErrorTypes.h:220
Alarm.h
Alarm management.
task_s::stack
uint8_t *const stack
Pointer to stack base.
Definition: TaskTypes.h:84
TCB_Cfg
volatile struct task_s * TCB_Cfg[]
Current task control blocks.
OS_SuspendOSInterrupts
void OS_SuspendOSInterrupts(void)
Suspend OS interrupts.
Definition: OS.c:294
task_s::curState
TaskStateType curState
Current state of the task.
Definition: TaskTypes.h:97
OS_ResumeOSInterrupts
void OS_ResumeOSInterrupts(void)
Resume OS interrupts.
Definition: OS.c:282
RUNNING
@ RUNNING
The task is currently running.
Definition: TaskTypes.h:61
OS_SET_ERROR_INFO0
#define OS_SET_ERROR_INFO0(serviceId)
Set error info with zero parameters.
Definition: ErrorTypes.h:208
PreTaskHook
void PreTaskHook(void)
PreTask hook function.
Definition: App.c:768
isCat2ISR
volatile uint8_t isCat2ISR
Priority of current Cat 2 ISR (zero if not in Cat 2 ISR)
Definition: OCB.c:21
isISR
volatile bool isISR
Is currently ISR context?
Definition: OCB.c:20
task_s::context
uint8_t * context
Current context/stack pointer.
Definition: TaskTypes.h:94
READY
@ READY
The task is ready to be scheduled.
Definition: TaskTypes.h:60
assert
#define assert(expression)
Definition: assert.h:37
Resource_GetInternalResource
void Resource_GetInternalResource(void)
Get internal resource of the current task if one is assigned.
Definition: Resource.c:161
resource_s
Data structure for OS resource.
Definition: ResourceTypes.h:29
OSServiceId_GetActiveApplicationMode
@ OSServiceId_GetActiveApplicationMode
Definition: ErrorTypes.h:38
task_s::prio
const uint8_t prio
Static priority of the task.
Definition: TaskTypes.h:86
OSServiceId_ResumeAllInterrupts
@ OSServiceId_ResumeAllInterrupts
Definition: ErrorTypes.h:41
task_s::stackSize
const uint16_t stackSize
Size of stack in bytes.
Definition: TaskTypes.h:85
OSServiceId_StartOS
@ OSServiceId_StartOS
Definition: ErrorTypes.h:36
OSServiceId_ShutdownOS
@ OSServiceId_ShutdownOS
Definition: ErrorTypes.h:37
OS_ResumeAllInterrupts
void OS_ResumeAllInterrupts(void)
Resume all interrupts.
Definition: OS.c:261
OS_DisableAllInterrupts
void OS_DisableAllInterrupts(void)
Disable all interrupts.
Definition: OS.c:256
ptrCurrentFxnAddr
pTaskFxn ptrCurrentFxnAddr
Function pointer to current task function.
Definition: OS.c:66
resource_s::next
struct resource_s * next
Pointer to next resource in resource queue.
Definition: ResourceTypes.h:32
OSServiceId_SuspendOSInterrupts
@ OSServiceId_SuspendOSInterrupts
Definition: ErrorTypes.h:44
PostTaskHook
void PostTaskHook(void)
PostTask hook function.
Definition: App.c:776
context.h
Context switching.
OS_EnableAllInterrupts
void OS_EnableAllInterrupts(void)
Enable all interrupts.
Definition: OS.c:251
E_OS_STACKFAULT
@ E_OS_STACKFAULT
Definition: Types.h:49
OS_ShutdownOS
void OS_ShutdownOS(StatusType error)
Shutdown operating system.
Definition: OS.c:128
init_context
void init_context(void)
Initialize context of current task.
ShutdownHook
void ShutdownHook(StatusType error)
Definition: App.c:757
pTaskFxn
void(* pTaskFxn)()
Definition: TaskTypes.h:24
TaskStateType
enum OsTaskState_e TaskStateType
Task state.
task_s::taskFxn
const pTaskFxn taskFxn
Pointer to task function.
Definition: TaskTypes.h:91
TASK_COUNT
#define TASK_COUNT
Count of tasks defined.
Definition: CfgGenMacros.h:267
OS_ProtectionHookInternal
void OS_ProtectionHookInternal(StatusType error)
Internal function for protection hook handling.
Definition: OS.c:310
OS_GetActiveApplicationMode
AppModeType OS_GetActiveApplicationMode(void)
Get currently active application mode.
Definition: OS.c:303
PRO_SHUTDOWN
@ PRO_SHUTDOWN
Shutdown system.
Definition: Types.h:62
forceScheduling
bool forceScheduling
Force the next rescheduling.
Definition: OCB.c:28
Alarm_startup
void Alarm_startup(void)
Startup function for alarm management.
Definition: Alarm.c:259
OS_StartOS
void OS_StartOS(AppModeType mode)
Start operating system.
Definition: OS.c:91
OSServiceId_SuspendAllInterrupts
@ OSServiceId_SuspendAllInterrupts
Definition: ErrorTypes.h:42
Task_startup
void Task_startup(void)
Startup function for task management.
Definition: Task.c:228
save_context
void save_context(void)
Save context of current task.
OS_SuspendAllInterrupts
void OS_SuspendAllInterrupts(void)
Suspend all interrupts.
Definition: OS.c:273
AppModeType
enum applicationMode_e AppModeType
Type for application mode.
needScheduling
volatile uint8_t needScheduling
Scheduling needed during timer interrupt.
Definition: OCB.c:26
PRE_READY
@ PRE_READY
The task is ready but its stack is uninitialized.
Definition: TaskTypes.h:59