1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** OSEK IMPLEMENTATION */
16 /** */
17 /**************************************************************************/
18 /**************************************************************************/
19
20
21 /* Include necessary files. */
22
23 #include "os.h"
24
25 /* Include some required internal headers. */
26
27 #include <tx_timer.h>
28 #include <tx_thread.h>
29 #include <tx_initialize.h>
30
31
32 /* Declare a structure to hold application information. */
33
34 APPLICATION_INFO_PTR Application;
35
36
37 /* Define a global variable to hold operating mode of this wrapper. */
38
39 static UINT osek_wrapper_operation_mode = OSEK_INIT_NOT_DONE;
40
41
42 /* Define the threads for the System Manager. */
43
44 TX_THREAD osek_system_manager;
45
46
47 /* Define ThreadX message queues for System Manager. */
48
49 TX_QUEUE osek_work_queue;
50
51
52 /* Define a byte pool control block for the osek region0 memory used. */
53
54 TX_BYTE_POOL osek_region0_byte_pool;
55
56
57 /* Define ThreadX timer to act as a system timer. */
58
59 TX_TIMER osek_system_timer;
60
61
62 /************ OSEK System objects Definitions **************/
63
64 /* Define a static pool of Task structures. */
65
66 static OSEK_TCB osek_tcb_pool[OSEK_MAX_TASKS];
67
68
69 /* Define a static pool of resource structures. */
70
71 static OSEK_RESOURCE osek_res_pool[OSEK_MAX_RES];
72
73
74 /* Defines a static pool of alarm structures. */
75
76 static OSEK_ALARM osek_alarm_pool[OSEK_MAX_ALARMS];
77
78
79 /* Defines a static pool of counter structures. */
80
81 static OSEK_COUNTER osek_counter_pool[OSEK_MAX_COUNTERS];
82
83
84 /* Define a Task Ready Queue. */
85 /* For each OSEK priority there is a sub queue, each queue entry holds an id of a task ready to run. */
86
87 TaskType task_table [OSEK_ISR1_PRIORITY + 1u][TASK_QUEUE_DEPTH];
88
89
90 /* A global variable holding all 32 events (bit flags) for this OS implementation. */
91
92 EventMaskType global_events;
93 EventMaskType global_event_count;
94
95
96 /* Define some default system objects. */
97
98 ResourceType RES_SCHEDULER;
99 CounterType SYS_TIMER;
100
101
102 /* Variables to store current and last executed task details. */
103
104 ULONG last_run_task;
105 ULONG system_start; /* If TX_TRUE indicates a fresh system start. */
106 UINT task_terminated;
107
108
109 /* Define ISR2 controlling flags. */
110 /* disable_ISR2 is the global enable/disable flag , if this flag is set no ISR2 is allowed or even kept pending. */
111 /* suspend_ISR2 is NON Zero then any ISR2 is kept pending (provided that disable_ISR2 must be zero before hand). */
112
113 /* disable_ISR2 = TX_FALSE & suspend_ISR2 = TX_FALSE :: process ISR2 immediately
114 disable_ISR2 = TX_FALSE & suspend_ISR2 = TX_TRUE :: log ISR2 but don't process till suspend_ISR2 becomes TX_FALSE
115 disable_ISR2 = TX_TRUE & suspend_ISR2 DON't care :: No ISR2 logged and executed */
116
117 UINT disable_ISR2 = TX_TRUE; /* This flag must be TX_FALSE to allow ISR 2. */
118 UINT suspend_ISR2 = TX_TRUE; /* This flag must be TX_FALSE to register and execute ISR2. */
119 UINT ISR2_pending = TX_FALSE;
120
121 /* Track initialization status. */
122
123 static UINT osek_init_state; /* Set to 0 for uninitialized, 1 for initialized by not yet started and 2 if started. */
124
125 #define OSEK_NOT_INIT (0U)
126 #define OSEK_INIT (1U)
127 #define OSEK_STARTED (2U)
128
129 #define OSEK_MAX_LINK_DEPTH (1024U) /* Maximum depth of linked resource, to prevent infinite loops in case of a corrupted list. */
130
131 /* OSEK API Services and associated structures. */
132
133 struct Service_ActivateTask service_ActivateTask;
134 struct Service_TerminateTask service_TerminateTask;
135 struct Service_ChainTask service_ChainTask;
136 struct Service_Schedule service_Schedule;
137 struct Service_GetTaskID service_GetTaskID;
138 struct Service_GetTaskState service_GetTaskState;
139
140 struct Service_DisableAllInterrupts service_DisableAllInterrupts;
141 struct Service_EnableAllInterrupts service_EnableAllInterrupts;
142 struct Service_SuspendAllInterrupts service_SuspendAllInterrupts;
143 struct Service_ResumeAllInterrupts service_ResumeAllInterrupts;
144 struct Service_SuspendOSInterrupts service_SuspendOSInterrupts;
145 struct Service_ResumeOSInterrupts service_ResumeOSInterrupts;
146
147 struct Service_GetResource service_GetResource;
148 struct Service_ReleaseResource service_ReleaseResource;
149
150 struct Service_SetEvent service_SetEvent;
151 struct Service_ClearEvent service_ClearEvent;
152 struct Service_GetEvent service_GetEvent;
153 struct Service_WaitEvent service_WaitEvent;
154
155 struct Service_GetAlarmBase service_GetAlarmBase;
156 struct Service_GetAlarm service_GetAlarm;
157 struct Service_SetRelAlarm service_SetRelAlarm;
158 struct Service_SetAbsAlarm service_SetAbsAlarm;
159 struct Service_CancelAlarm service_CancelAlarm;
160
161 struct Service_GetActiveApplicationMode service_GetActiveApplicationMode;
162 struct Service_StartOS service_StartOS;
163 struct Service_ShutdownOS service_ShutdownOS;
164
165 struct Service_GetServiceId service_GetServiceId;
166
167
168 /**************************************************************************/
169 /* OSEK internal functions prototypes */
170 /**************************************************************************/
171
172
173 /* Entry functions for various ThreadX threads used for OS management. */
174
175 static void osek_system_manager_entry(ULONG input);
176 static void osek_system_timer_entry(ULONG input);
177 static void osek_task_wrapper(ULONG tcb);
178
179
180 /* Initialization and reset for OSEK system objects. */
181
182 static UINT osek_memory_init (void *region0_ptr);
183 static void osek_alarm_init(void);
184 static void osek_tcb_init(void);
185 static void osek_resource_init(void);
186 static void osek_counter_init(void);
187
188 static void osek_reset_alarm(OSEK_ALARM *alarm_ptr);
189 static void osek_reset_counter(OSEK_COUNTER *counter_ptr);
190 static void osek_reset_tcb(OSEK_TCB *tcb_ptr);
191 static void osek_reset_res(OSEK_RESOURCE *res_ptr);
192
193 /* Some utilities. */
194
195 static ULONG osek_task_independent_area(void);
196 static OSEK_TCB *osek_thread2tcb(TX_THREAD *thread_ptr);
197 static UINT osek_remap_priority(UINT osek_priority);
198
199 /* Functions to obtain OSEK objects from predefined pools. */
200
201 static UINT osek_memory_allocate(ULONG size, void **memory_ptr);
202 static UINT osek_get_alarm(void);
203 static CounterType osek_get_counter(void);
204 static ResourceType osek_get_resource(void);
205 static EventMaskType osek_get_event(void);
206 static ULONG osek_allocate_tcb(ULONG stack_size, OSEK_TCB **tcb_ptr);
207
208 /* Internal operation functions. */
209
210 static StatusType osek_do_task_terminate(OSEK_TCB *tcb_ptr);
211 static StatusType osek_do_activate_task (OSEK_TCB *tcb_ptr);
212 static StatusType osek_create_task(OSEK_TCB *tcb_ptr);
213 static StatusType get_internal_resource(OSEK_TCB *tcb_ptr);
214 static StatusType release_internal_resource(OSEK_TCB *tcb_ptr);
215 static StatusType check_external_resource(OSEK_TCB *tcb_ptr);
216 static StatusType TerminateISR(void);
217
218
219 /* OSEK internal error function and Hook routine executors. */
220
221 static void osek_internal_error(ULONG error_code);
222 static void exec_ErrorHook (StatusType error);
223 static void exec_PreTaskHook(void);
224 static void exec_PostTaskHook(void);
225
226
227 /*OSEK Scheduler helper functions. */
228
229 static void add_task_to_table(OSEK_TCB *tcb_ptr);
230 static void start_osek_tasks(void);
231 static void push_task_to_table(OSEK_TCB *tcb_ptr);
232 static void pop_task_from_table(OSEK_TCB *tcb_ptr);
233 static UINT check_task_to_run (OSEK_TCB *tcb_ptr );
234 static void check_linked_resources(void);
235 static StatusType ActivateISR(ISRType ISRID);
236
237
238 /**************************************************************************/
239
240
241 /**************************************************************************/
242 /* */
243 /* FUNCTION RELEASE */
244 /* */
245 /* StartOS PORTABLE C */
246 /* 6.1.7 */
247 /* AUTHOR */
248 /* */
249 /* William E. Lamie, Microsoft Corporation */
250 /* */
251 /* DESCRIPTION */
252 /* */
253 /* This function starts the OS. If StartOSHook is defined it is */
254 /* called. */
255 /* */
256 /* INPUT */
257 /* */
258 /* StatusType Application mode */
259 /* */
260 /* OUTPUT */
261 /* */
262 /* None */
263 /* */
264 /* CALLS */
265 /* */
266 /* StartupHook If defined */
267 /* */
268 /* CALLED BY */
269 /* */
270 /* Application */
271 /* */
272 /* RELEASE HISTORY */
273 /* */
274 /* DATE NAME DESCRIPTION */
275 /* */
276 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
277 /* */
278 /**************************************************************************/
StartOS(StatusType os_mode)279 void StartOS(StatusType os_mode)
280 {
281
282 ULONG request[SYSMGR_QUEUE_MSG_LENGTH];
283 StatusType status;
284
285 check_linked_resources();
286
287 Application->application_mode = OSDEFAULTAPPMODE;
288
289 /* Check for any startup hook routine. */
290 if (Application->startup_hook_handler != TX_NULL)
291 {
292 /* Change operation mode for to startuphook mode. */
293 osek_wrapper_operation_mode = STARTUPHOOK_MODE;
294 (Application->startup_hook_handler)(os_mode);
295 }
296
297 /* Change back to default operations mode. */
298 osek_wrapper_operation_mode = NORMAL_EXECUTION_MODE;
299
300 /* Now send message to system thread to start the task scheduler. */
301
302 /* Build the request. */
303 request[0] = SYSMGR_START_OS; /* Request type. */
304 request[1] = 0u; /* Dummy. */
305 request[2] = 0u; /* Dummy. */
306 request[3] = 0u; /* Dummy. */
307
308 /* Now send a message to the SysMgr supervisor thread. */
309 /* to start OS task scheduler. */
310
311 status = tx_queue_send(&osek_work_queue, request, TX_NO_WAIT);
312
313 /* This should always succeed. */
314 if (status != TX_SUCCESS)
315 {
316 /* System internal error. */
317 osek_internal_error(SYS_MGR_START_OS);
318 }
319
320 return;
321 }
322
323
324 /**************************************************************************/
325 /* */
326 /* FUNCTION RELEASE */
327 /* */
328 /* CreateTask PORTABLE C */
329 /* 6.1.7 */
330 /* AUTHOR */
331 /* */
332 /* William E. Lamie, Microsoft Corporation */
333 /* */
334 /* DESCRIPTION */
335 /* */
336 /* This function creates a new task with specified attributes. */
337 /* This call is allowed only during Application Initialization. */
338 /* This is not a standard OSEK API call. */
339 /* */
340 /* INPUT */
341 /* */
342 /* priority Priority of the Task */
343 /* stack_size Stack size of the Task */
344 /* entry_function Task entry function pointer */
345 /* policy Scheduling policy for this Task */
346 /* active_no Maximum activation number */
347 /* start Starting state of the task */
348 /* type Task type: Basic/Extended */
349 /* */
350 /* OUTPUT */
351 /* */
352 /* TaskId Task Id if successful */
353 /* TX_NULL Error while creating the task */
354 /* */
355 /* CALLS */
356 /* */
357 /* osek_allocate_tcb Get a TCB from the pool */
358 /* osek_create_task Create an OSEK Task */
359 /* */
360 /* CALLED BY */
361 /* */
362 /* Initialization code */
363 /* */
364 /* RELEASE HISTORY */
365 /* */
366 /* DATE NAME DESCRIPTION */
367 /* */
368 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
369 /* */
370 /**************************************************************************/
CreateTask(const CHAR * name,void (* entry_function)(),UINT priority,UINT max_activation,ULONG stack_size,SCHEDULE policy,AUTOSTART start,UINT type,AppModeType mode)371 TaskType CreateTask(const CHAR *name, void(*entry_function)(), UINT priority, UINT max_activation,
372 ULONG stack_size, SCHEDULE policy, AUTOSTART start, UINT type, AppModeType mode)
373 {
374
375 OSEK_TCB *tcb_ptr; /* Pointer to task control block. */
376 ULONG temp32;
377 ULONG status;
378
379
380 /* Check whether we are called during initialization. */
381 /* This will ensure that no one calls this function after system is started. */
382 if (osek_init_state != OSEK_INIT)
383 {
384 Application->osek_object_creation_error++;
385
386 /* Return OSEK internal error. NOTE: This is not a standard OSEK error. */
387 return ((TaskType)TX_NULL);
388 }
389
390 /* Now check the validity of all input parameters. */
391
392 /* Entry point function. */
393 if (entry_function == TX_NULL)
394 {
395 /* Entry function not specified! Return an error. This is not a standard OSEK error. */
396 Application->osek_object_creation_error++;
397 return ((TaskType)TX_NULL);
398 }
399
400 /* Task priority. */
401 if (priority > OSEK_HIGHEST_PRIORITY)
402 {
403 /* Return an internal error. This is not a standard OSEK error. */
404 Application->osek_object_creation_error++;
405 return ((TaskType)TX_NULL);
406 }
407
408 /* The max_activation parameter must be within limit, that is a non zero value but less
409 than OSEK_MAX_ACTIVATION. */
410 if ((max_activation > OSEK_MAX_ACTIVATION) || (max_activation == 0u))
411 {
412 /* Return an internal error. This is not a standard OSEK error. */
413 Application->osek_object_creation_error++;
414 return ((TaskType)TX_NULL);
415 }
416
417 /* Adjust the input stack size and check. */
418 /* Force stack size to a multiple of 4 bytes, round up if needed. */
419 temp32 = ((stack_size + 3u) & ~0x3u);
420
421 /* Add a little extra padding to stack. */
422 temp32 += OSEK_STACK_PADDING;
423
424 /* Is task stack big enough? ThreadX needs a minimum stack size for each task. */
425 if (temp32 < TX_MINIMUM_STACK)
426 {
427 /* Return an error as there is no enough stack. This is not a standard OSEK error. */
428 Application->osek_object_creation_error++;
429 return ((TaskType)TX_NULL);
430 }
431
432 /* Scheduling Policy */
433 if ((policy != FULL) && (policy != NON))
434 {
435 /* Return an error as policy supplied is unknown. This is not a standard OSEK error. */
436 Application->osek_object_creation_error++;
437 return ((TaskType)TX_NULL);
438 }
439
440 /* Task Type */
441 if ((type != BASIC) && (type != EXTENDED))
442 {
443 /* Return an error as task type supplied is unknown. This is not a standard OSEK error. */
444 Application->osek_object_creation_error++;
445 return ((TaskType)TX_NULL);
446 }
447
448 /* AUTO START option. */
449 if ((start != TRUE) && (start != FALSE))
450 {
451 /* Return an error as Start type is unknown.This is not a standard OSEK error. */
452 Application->osek_object_creation_error++;
453 return ((TaskType)TX_NULL);
454 }
455
456 /* Got all input parameters within limits, now try to get a free Task Control Block (TCB) for this new task. */
457 tcb_ptr = TX_NULL;
458 status = osek_allocate_tcb(temp32, &tcb_ptr);
459
460 /* Make sure we got a TCB. */
461 if((status != TRUE) || (tcb_ptr == TX_NULL))
462 {
463 /* Return an error since no memory is available. This is not a standard OSEK error. */
464 Application->osek_object_creation_error++;
465 return ((TaskType)TX_NULL);
466 }
467
468 /* Now fill up the TCB with all supplied parameters. */
469
470 /* Store TASK object ID this is same for all TCB, this helps in checking whether the data
471 structure is really a TASK CONTROL BLOCK. */
472 tcb_ptr->osek_task_id = OSEK_TASK_ID;
473
474 /* Store task's name and type. */
475 tcb_ptr->name = name;
476 tcb_ptr->task_type = type;
477
478 /* Store the statically assigned (design time) priority and same would be RUN time priority. */
479 tcb_ptr->org_prio = priority;
480 tcb_ptr->cur_threshold = priority;
481
482 /* Store the task entry point. This is where the task will begin upon activation or chaining. */
483 tcb_ptr->task_entry = entry_function;
484
485 /* Store current task activation number as well as the maximum activations defined for this task. */
486 tcb_ptr->max_active = max_activation;
487 tcb_ptr->current_active = 0u;
488 tcb_ptr->internal_res = TX_FALSE;
489
490 /* Store the scheduling policy defined for the task. */
491 tcb_ptr->policy = policy;
492
493 /* Store the start up condition of the task. */
494 tcb_ptr->task_autostart = start;
495
496 /* A task is always created in suspended state even though it is defined as an AUTO START. */
497 tcb_ptr->suspended = TX_TRUE;
498 tcb_ptr->waiting = TX_FALSE;
499
500 /* Store task's application mode. */
501 tcb_ptr->task_Appl_Mode = mode;
502
503 /* Now create the ThreadX thread which actually runs this task. */
504 status = osek_create_task(tcb_ptr);
505
506 /* Check whether we encounter any error during ThreadX thread creation. */
507 if (status == E_OS_SYSTEM)
508 {
509 /* Can't create a task? This is not a standard OSEK error.*/
510 Application->osek_object_creation_error++;
511 return ((TaskType) TX_NULL);
512 }
513
514 /* Everything worked fine so far. Return TaskID. This TaskID is nothing but a TCB structure
515 type casted to TaskType UDT. */
516 return ((TaskType)tcb_ptr);
517 }
518
519
520 /**************************************************************************/
521 /* */
522 /* FUNCTION RELEASE */
523 /* */
524 /* CreateISR PORTABLE C */
525 /* 6.1.7 */
526 /* AUTHOR */
527 /* */
528 /* William E. Lamie, Microsoft Corporation */
529 /* */
530 /* DESCRIPTION */
531 /* */
532 /* This function creates a new task which will execute an ISR. */
533 /* This call is allowed only during Application Initialization. */
534 /* This is not a standard OSEK API call. */
535 /* */
536 /* INPUT */
537 /* */
538 /* priority Priority of the ISR */
539 /* stack_size Stack size of the ISR */
540 /* entry_function Task entry function pointer */
541 /* policy Scheduling policy for this task */
542 /* active_no Maximum activation number */
543 /* start Starting state of the task */
544 /* type Task type: Basic/Extended */
545 /* */
546 /* OUTPUT */
547 /* */
548 /* TaskId Task Id if successful */
549 /* TX_NULL Error while creating the ISR */
550 /* */
551 /* CALLS */
552 /* */
553 /* osek_allocate_tcb Get a TCB from the pool */
554 /* osek_create_task Create an OSEK Task */
555 /* */
556 /* CALLED BY */
557 /* */
558 /* Initialization code */
559 /* */
560 /* RELEASE HISTORY */
561 /* */
562 /* DATE NAME DESCRIPTION */
563 /* */
564 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
565 /* */
566 /**************************************************************************/
567
CreateISR(const CHAR * name,void (* entry_function)(),UINT category,ULONG stack_size)568 ISRType CreateISR(const CHAR *name, void (*entry_function)(), UINT category, ULONG stack_size)
569 {
570
571 OSEK_TCB *tcb_ptr; /* Pointer to task control block. */
572 ULONG temp32;
573 ULONG status;
574
575
576 /* Check if we are called during initialization. */
577 if((osek_init_state != OSEK_INIT) || /* Not in initialization. */
578 (_tx_thread_current_ptr == &_tx_timer_thread))
579 {
580 /* Return default error. */
581 Application->osek_object_creation_error++;
582
583 return((ResourceType)TX_NULL);
584 }
585
586 /* Scheduling policy. */
587 if ((category != CATEGORY1) && (category != CATEGORY2))
588 {
589 /* Return an error as policy supplied is unknown. This is not a standard OSEK error. */
590 Application->osek_object_creation_error++;
591 return ((TaskType)TX_NULL);
592 }
593
594 /* Entry point function. */
595 if(entry_function == NULL)
596 {
597 /* Entry function not specified! Return an error. This is not a standard OSEK error. */
598 Application->osek_object_creation_error++;
599 return ((TaskType)TX_NULL);
600 }
601
602 /* Adjust the input stack size and check. */
603 /* Force stack size to a multiple of 4 bytes, round up if needed. */
604 temp32 = ((stack_size + 3u) & ~0x3u);
605
606 /* Add a little extra padding to stack. */
607 temp32 += OSEK_STACK_PADDING;
608
609 /* Is task stack big enough? ThreadX needs a minimum stack size for each task. */
610 if (temp32 < TX_MINIMUM_STACK)
611 {
612 /* Return an error as there is not enough stack. This is not a standard OSEK error. */
613 Application->osek_object_creation_error++;
614 return ((ISRType)TX_NULL);
615 }
616
617 /* Got all input parameters within limits, now try to get a free task control block(TCB) for this new ISR. */
618 tcb_ptr = TX_NULL;
619 status = osek_allocate_tcb(temp32, &tcb_ptr);
620 /* Make sure we got a TCB. */
621 if((status != TRUE) || (tcb_ptr == TX_NULL))
622 {
623 /* Return an error since no memory is available. This is not a standard OSEK error. */
624 Application->osek_object_creation_error++;
625 return ((TaskType)TX_NULL);
626 }
627
628 /* Got a tcb , now fill up the TCB with all supplied parameters. */
629
630 /* Store ISR objectID ,this is same for all ISRs, this helps in checking whether the data
631 structure is really a ISR CONTROL BLOCK. */
632 tcb_ptr->osek_task_id = OSEK_ISR_ID;
633
634 /* Store ISR name. */
635 tcb_ptr->name = name;
636 /* Store ISR category. */
637 tcb_ptr->task_type = category;
638
639 /* Store the statically assigned (design time) priority and same would be runtime priority. */
640
641 if (category == 1u)
642 {
643 tcb_ptr->org_prio = OSEK_ISR1_PRIORITY;
644 }
645 else
646 {
647 tcb_ptr->org_prio = OSEK_ISR2_PRIORITY;
648 }
649
650 tcb_ptr->cur_threshold = tcb_ptr->org_prio;
651
652 /* Store the ISR entry point. This is where the ISR will begin. */
653 tcb_ptr->task_entry = entry_function;
654
655 /* Store maximum activations defined for ISR. */
656 /* Only 1 ISR of this name can be pending. */
657 tcb_ptr->max_active = 1u;
658 tcb_ptr->current_active = 0u;
659 tcb_ptr->internal_res = TX_FALSE;
660
661 /* Store the scheduling policy defined for the task. */
662 tcb_ptr->policy = NON;
663
664 /* Store the start up condition of the ISR which of course is DO NOT START. */
665 tcb_ptr->task_autostart = FALSE;
666
667 /* An ISR is always created in suspended state. */
668 tcb_ptr->suspended = TX_TRUE;
669 tcb_ptr->waiting = TX_FALSE;
670
671 /* Now create the ThreadX thread which actually mimics this ISR. */
672 status = osek_create_task(tcb_ptr);
673
674 /* Check whether we encounter any error during ThreadX thread creation. */
675 if (status == E_OS_SYSTEM)
676 {
677 /* Can't create a task? This is not a standard OSEK error. */
678 Application->osek_object_creation_error++;
679 return ((ISRType)TX_NULL);
680 }
681
682 /* Everything worked fine so far. Return ISRID. This is nothing but a TCB structure
683 type casted to ISRType UDT. */
684 return ((ISRType)tcb_ptr);
685 }
686
687
688 /**************************************************************************/
689 /* */
690 /* FUNCTION RELEASE */
691 /* */
692 /* ActivateTask PORTABLE C */
693 /* 6.1.7 */
694 /* AUTHOR */
695 /* */
696 /* William E. Lamie, Microsoft Corporation */
697 /* */
698 /* DESCRIPTION */
699 /* */
700 /* This call transfers a task from suspended state into the ready */
701 /* state. The operating system ensures that the task code is being */
702 /* executed from the first statement. The service may be called both */
703 /* from interrupt level and from task level. Rescheduling after this */
704 /* call depends on from where it is called from. Also if required */
705 /* resources are freed as well as this being the highest priority task */
706 /* than the task executing at this instance. If E_OS_LIMIT is returned */
707 /* then activation is ignored. When an extended task is transferred */
708 /* from suspended to ready state all its events are cleared. */
709 /* */
710 /* INPUT */
711 /* */
712 /* TaskId Task Name */
713 /* */
714 /* OUTPUT */
715 /* */
716 /* E_OK If successful */
717 /* E_OS_ID Invalid TaskId */
718 /* E_OS_LIMIT Task activation limit */
719 /* exceeded */
720 /* */
721 /* CALLS */
722 /* */
723 /* tx_queue_send Send message to Sys Manager */
724 /* osek_internal_error OSEK internal error */
725 /* osek_task_independent_area Check calling context */
726 /* tx_thread_identify Get ThreadX thread of caller */
727 /* osek_thread2tcb Convert ThreadX to OSEK */
728 /* */
729 /* CALLED BY */
730 /* */
731 /* Application */
732 /* */
733 /* RELEASE HISTORY */
734 /* */
735 /* DATE NAME DESCRIPTION */
736 /* */
737 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
738 /* */
739 /**************************************************************************/
ActivateTask(TaskType TaskId)740 StatusType ActivateTask(TaskType TaskId)
741 {
742 TX_INTERRUPT_SAVE_AREA
743 OSEK_TCB *tcb_ptr;
744 OSEK_TCB *tcb_ptr_self;
745 UINT status;
746 ULONG request[SYSMGR_QUEUE_MSG_LENGTH];
747 ULONG area;
748 TX_THREAD *p_thread;
749
750
751 /* Log this call and arguments passed, this is required for the macro 'OSErrorGetServiceId'. */
752 service_GetServiceId.id = (OsServiceIdType)OSServiceId_ActivateTask;
753 service_ActivateTask.TaskID = TaskId;
754
755 /* Check if we are in task context. */
756 area = osek_task_independent_area();
757 if(area != TX_TRUE)
758 {
759 exec_ErrorHook(E_OS_CALLEVEL);
760 /* Return error. */
761 return (E_OS_CALLEVEL);
762 }
763
764 /* Check operating mode */
765 if ((osek_wrapper_operation_mode != NORMAL_EXECUTION_MODE) && (osek_wrapper_operation_mode != ISR2_MODE))
766 {
767 /* Hook routines and alarm callbacks can't call this service. */
768 /* This explicit check is required because all hook routines are
769 executed in task's context! */
770 exec_ErrorHook(E_OS_ID);
771 return (E_OS_CALLEVEL);
772 }
773
774 /* Get OSEK TCB of the calling task. */
775 p_thread = tx_thread_identify();
776 tcb_ptr_self = osek_thread2tcb(p_thread);
777
778 if ((tcb_ptr_self->osek_task_id != OSEK_TASK_ID) && (tcb_ptr_self->osek_task_id != OSEK_ISR_ID))
779 {
780 /* This call is allowed only from TASK and ISR */
781 return (E_OS_CALLEVEL);
782 }
783
784 /* Get OSEK TCB of the TASK to activate. */
785 tcb_ptr = (OSEK_TCB *)TaskId;
786 if ((tcb_ptr == TX_NULL) || (tcb_ptr->osek_task_id != OSEK_TASK_ID))
787 {
788 exec_ErrorHook(E_OS_ID);
789 return (E_OS_ID);
790 }
791
792 TX_DISABLE
793
794 /* Check whether the task to be activated is activated up to its defined activation limit. */
795 if(tcb_ptr->current_active >= tcb_ptr->max_active)
796 {
797 TX_RESTORE
798 exec_ErrorHook(E_OS_LIMIT);
799 /* Reached its max activation limit. */
800 return (E_OS_LIMIT);
801 }
802
803 /* Now send a message to the system manager thread to activate this task. */
804 /* Build the request. */
805 request[0] = SYSMGR_ACTIVATE_TASK; /* Request type. */
806 request[1] = (ULONG)tcb_ptr; /* Task to activate. */
807
808 /* Now check who is calling this service, a task or an ISR? */
809 if (tcb_ptr_self->osek_task_id == OSEK_TASK_ID)
810 {
811 request[2] = (ULONG)tcb_ptr_self; /* Task id of the calling task. */
812 }
813 else
814 {
815 request[2] = 0u; /* When ISR activates a task rescheduling (if any) is held
816 till ISR completes so no need to suspend ISR task. */
817 }
818
819 request[3] = 0u;
820
821 /* Since the SysMgr supervisor thread has the highest priority, this call */
822 /* will be preempted by SysMgr supervisor thread. */
823 /* SysMgr will eventually call osek_do_task_activate. */
824
825 status = tx_queue_send(&osek_work_queue, request, TX_NO_WAIT);
826
827 TX_RESTORE
828
829 /* This should always succeed. */
830 if (status != TX_SUCCESS)
831 {
832 /* System internal error. */
833 osek_internal_error(SYS_MGR_SEND_ACTIVATETASK);
834 }
835
836 /* Return status. */
837 return(E_OK);
838 }
839
840
841 /**************************************************************************/
842 /* */
843 /* FUNCTION RELEASE */
844 /* */
845 /* TerminateTask PORTABLE C */
846 /* 6.1.7 */
847 /* AUTHOR */
848 /* */
849 /* William E. Lamie, Microsoft Corporation */
850 /* */
851 /* DESCRIPTION */
852 /* */
853 /* This service terminates the calling task, which means transferring */
854 /* the calling task from the running state into the suspended state. */
855 /* Only internal resources held by this task are released here. While */
856 /* it is assumed that any external resources occupied by the task must */
857 /* have been released before the call to TerminateTask. In case */
858 /* a resource is still occupied while calling this service, then the */
859 /* behaviour is undefined in STANDARD version of OSEK. In the EXTENDED */
860 /* version of OSEK, this service returns an error, which can be */
861 /* evaluated by the application. */
862 /* If successful, this call will causes rescheduling, this also means */
863 /* that upon success TerminateTask does not return to the call level. */
864 /* */
865 /* NOTE: */
866 /* */
867 /* Ending a task function without call to TerminateTask or ChainTask is */
868 /* strictly forbidden and may leave the system in an undefined state. */
869 /* But in this implementation TerminateTask service is called if needed.*/
870 /* */
871 /* INPUT */
872 /* */
873 /* None */
874 /* */
875 /* OUTPUT */
876 /* */
877 /* None If success */
878 /* Error Code. If error */
879 /* */
880 /* CALLS */
881 /* */
882 /* osek_task_independent_area Check if we are in task context */
883 /* osek_thread2tcb Get TCB pointer for thread pointer */
884 /* tx_queue_send Send message to Sys Manager Thread */
885 /* osek_internal_error In case of any internal error */
886 /* */
887 /* CALLED BY */
888 /* */
889 /* Application Code (TASKs only) */
890 /* */
891 /* RELEASE HISTORY */
892 /* */
893 /* DATE NAME DESCRIPTION */
894 /* */
895 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
896 /* */
897 /**************************************************************************/
TerminateTask(void)898 StatusType TerminateTask(void)
899 {
900 TX_INTERRUPT_SAVE_AREA
901 OSEK_TCB *tcb_ptr;
902 ULONG request[SYSMGR_QUEUE_MSG_LENGTH];
903 UINT index;
904 UINT status;
905 ULONG area;
906 TX_THREAD *p_thread;
907
908
909 service_GetServiceId.id = (OsServiceIdType)OSServiceId_TerminateTask;
910 service_TerminateTask.TaskID = (StatusType)0u;
911
912 /* Check for Task or ISR context. */
913 /* All ISRs are treated as as a high priority tasks. */
914 area = osek_task_independent_area();
915 if(area != TX_TRUE)
916 {
917 exec_ErrorHook(E_OS_CALLEVEL);
918 /* Return error. */
919 return (E_OS_CALLEVEL);
920 }
921
922 /* Get OSEK TCB of this TASK/ISR. */
923 p_thread = tx_thread_identify();
924 tcb_ptr = osek_thread2tcb(p_thread);
925 if (tcb_ptr == TX_NULL)
926 {
927 exec_ErrorHook(E_OS_CALLEVEL);
928 return (E_OS_CALLEVEL);
929 }
930
931 if (tcb_ptr->osek_task_id != OSEK_TASK_ID)
932 {
933 /* This call is allowed only from TASK and ISR. */
934 exec_ErrorHook(E_OS_CALLEVEL);
935 return (E_OS_CALLEVEL);
936 }
937
938
939 /* Check operating mode */
940 if (osek_wrapper_operation_mode != NORMAL_EXECUTION_MODE)
941 {
942 /* Hook routines and alarm callbacks can't call this service. */
943 /* This explicit check is required because all hook routines are
944 executed in task's context! */
945 exec_ErrorHook(E_OS_CALLEVEL);
946
947 return (E_OS_CALLEVEL);
948 }
949
950 TX_DISABLE
951
952 /* Check if any resource is occupied. A task can not be terminated if it is holding any resource. */
953 if(tcb_ptr->res_ocp != 0u)
954 {
955 TX_RESTORE
956
957 exec_ErrorHook(E_OS_RESOURCE);
958
959 /* Return. */
960 return (E_OS_RESOURCE);
961 }
962
963 /* Release any internal resources held. */
964 if (tcb_ptr->internal_res != 0u)
965 {
966 for (index = 0u; index < OSEK_MAX_INTERNAL_RES; index++)
967 {
968 if (tcb_ptr->internal_resource_occuplied_list[index] == 0u)
969 {
970 break;
971 }
972
973 ((OSEK_RESOURCE *)(tcb_ptr->internal_resource_occuplied_list[index]))->taskid = 0u;
974 tcb_ptr->internal_resource_occuplied_list[index] = 0u;
975
976 } /* End of for loop. */
977 }
978
979 /* Now it's okay to terminate this task, clear its events. */
980 tcb_ptr->waiting_events = 0u;
981 tcb_ptr->set_events = 0u;
982
983 /* Now all set to terminate this task. */
984 /* Send a message to the System Manager to terminate this task. */
985 /* Build the request. */
986
987 request[0] = SYSMGR_TERMINATE_TASK; /* Request type. */
988 request[1] = (ULONG)tcb_ptr; /* ID of the task to kill. */
989 request[2] = 0u;
990 request[3] = 0u;
991
992 /* Since the SysMgr supervisor thread has the highest priority, */
993 /* this call will be preempted by SysMgr supervisor thread */
994 /* SysMgr will eventually call osek_do_task_terminate and reschedule. */
995
996 status = tx_queue_send(&osek_work_queue, request, TX_NO_WAIT);
997
998 TX_RESTORE
999
1000 /* This should always succeed. and Sys Manager terminates this task */
1001 /* This point will never be reached, as this thread itself will be */
1002 /* deleted by the system manager! */
1003
1004 if (status != TX_SUCCESS)
1005 {
1006 osek_internal_error(SYS_MGR_SEND_TERMINATETASK);
1007 }
1008
1009 return (E_OK);
1010 }
1011
1012
1013 /**************************************************************************/
1014 /* */
1015 /* FUNCTION RELEASE */
1016 /* */
1017 /* ChainTask PORTABLE C */
1018 /* 6.1.7 */
1019 /* AUTHOR */
1020 /* */
1021 /* William E. Lamie, Microsoft Corporation */
1022 /* */
1023 /* DESCRIPTION */
1024 /* */
1025 /* This service causes the termination of the calling task. After */
1026 /* termination of the calling task, a succeeding task (supplied as an */
1027 /* input argument for the call) is activated. If the succeeding task */
1028 /* is the same calling task, then this does not result in multiple */
1029 /* requests and the task is not transferred to the suspended state. */
1030 /* Only internal resources held by this task are released here, even */
1031 /* in case the calling task is identical with the task to chain. */
1032 /* While it is assumed that any external resources occupied by the */
1033 /* task must have been released before the call to TerminateTask. */
1034 /* In case a resource is still occupied while calling this service, */
1035 /* then the behaviour is undefined in STANDARD version of OSEK. */
1036 /* In the EXTENDED version of OSEK, an error is returned, which can be */
1037 /* evaluated by the application. */
1038 /* If called successfully, ChainTask does not return to call level and */
1039 /* the status can not be evaluated. In case of error the service */
1040 /* returns to the calling task and provides a status which can then be */
1041 /* checked by the application. */
1042 /* If successful, this call will causes rescheduling, this also means */
1043 /* that upon success ChainTask does not return to the call level. */
1044 /* */
1045 /* */
1046 /* INPUT */
1047 /* */
1048 /* Task_ID Task id to activate. */
1049 /* OUTPUT */
1050 /* */
1051 /* E_OK If successful. */
1052 /* E_OS_LIMIT Too many activations */
1053 /* E_OS_CALLEVEL Called at interrupt level */
1054 /* E_OS_RESOURCE Resources are not released */
1055 /* */
1056 /* CALLS */
1057 /* */
1058 /* osek_task_independent_area Make sure called in Task context */
1059 /* osek_thread2tcb Get TCB pointer for the thread */
1060 /* tx_queue_send send message to sys manager thread */
1061 /* osek_internal_error Any internal errors */
1062 /* */
1063 /* CALLED BY */
1064 /* */
1065 /* Application Code (TASKs only) */
1066 /* */
1067 /* RELEASE HISTORY */
1068 /* */
1069 /* DATE NAME DESCRIPTION */
1070 /* */
1071 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
1072 /* */
1073 /**************************************************************************/
ChainTask(TaskType TaskID)1074 StatusType ChainTask(TaskType TaskID)
1075 {
1076 TX_INTERRUPT_SAVE_AREA
1077 OSEK_TCB *tcb_ptr;
1078 OSEK_TCB *tcb_ptr1;
1079 ULONG request[SYSMGR_QUEUE_MSG_LENGTH];
1080 UINT index;
1081 ULONG area;
1082 TX_THREAD *p_thread;
1083
1084 service_GetServiceId.id = (OsServiceIdType)OSServiceId_ChainTask;
1085 service_ChainTask.TaskID = TaskID;
1086
1087 /* Check if we are in task context. */
1088 area = osek_task_independent_area();
1089 if(area != TX_TRUE)
1090 {
1091 exec_ErrorHook(E_OS_CALLEVEL);
1092 /* Return error. */
1093 return(E_OS_CALLEVEL);
1094 }
1095
1096 /* Get OSEK TCB of this TASK/ISR. */
1097 p_thread = tx_thread_identify();
1098 tcb_ptr = osek_thread2tcb(p_thread);
1099 if (tcb_ptr == TX_NULL)
1100 {
1101 exec_ErrorHook(E_OS_ID);
1102 return (E_OS_ID);
1103 }
1104
1105 if (tcb_ptr->osek_task_id != OSEK_TASK_ID)
1106 {
1107 /* This call is allowed only from TASK. */
1108 exec_ErrorHook(E_OS_CALLEVEL);
1109 return (E_OS_CALLEVEL);
1110 }
1111
1112 /* Check operating mode. */
1113 if (osek_wrapper_operation_mode != NORMAL_EXECUTION_MODE)
1114 {
1115 /* ISRs, hook routines and alarm callbacks can't call this service. */
1116 /* This explicit check is required because all ISRs and hook routines are
1117 executed in task's context! */
1118 exec_ErrorHook(E_OS_CALLEVEL);
1119
1120 return (E_OS_CALLEVEL);
1121 }
1122
1123 /* Check if any external resources are occupied. */
1124 if(tcb_ptr->res_ocp != 0u)
1125 {
1126 exec_ErrorHook(E_OS_RESOURCE);
1127
1128 /* The external resource is not released. */
1129 return (E_OS_RESOURCE);
1130 }
1131
1132 /* Get tcb of task to be chained. */
1133 tcb_ptr1 = (OSEK_TCB *)TaskID;
1134
1135 /* First, check for an invalid task pointer. */
1136 if ((tcb_ptr1 == TX_NULL) || ((tcb_ptr1->osek_task_id) != OSEK_TASK_ID))
1137 {
1138 exec_ErrorHook(E_OS_ID);
1139
1140 /* Return Error. */
1141 return (E_OS_ID);
1142 }
1143
1144 TX_DISABLE
1145
1146 /* Check both calling task and task_to_be_chained are one and the same. */
1147 if (tcb_ptr != tcb_ptr1)
1148 {
1149 /* Check for proper multiple activation. */
1150 if(tcb_ptr1->current_active >= tcb_ptr1->max_active)
1151 {
1152 TX_RESTORE
1153
1154 /* Reached its max activation limit. */
1155 exec_ErrorHook(E_OS_LIMIT);
1156
1157 return (E_OS_LIMIT);
1158 }
1159 }
1160
1161 /* Store TaskID which is to be chained after termination of this task. */
1162 tcb_ptr->task_to_chain = TaskID;
1163
1164 /* Now release any internal resources held by the calling task. */
1165 if (tcb_ptr->internal_res != 0u)
1166 {
1167 for (index = 0u ; index < OSEK_MAX_INTERNAL_RES; index++)
1168 {
1169 if (tcb_ptr->internal_resource_occuplied_list[index] == 0u)
1170 {
1171 break;
1172 }
1173
1174 ((OSEK_RESOURCE *)(tcb_ptr->internal_resource_occuplied_list[index]))->taskid = 0u;
1175 tcb_ptr->internal_resource_occuplied_list[index] = 0u;
1176
1177 } /* End of for loop. */
1178 }
1179
1180 /* Now it's ok to terminate this task , clear its events. */
1181 tcb_ptr->waiting_events = 0u;
1182 tcb_ptr->set_events = 0u;
1183
1184 /* Send message to the system manager to suspend calling task and activate
1185 task to be chained. */
1186
1187 /* Build the request. */
1188 request[0] = SYSMGR_CHAIN_TASK; /* Request type. */
1189 request[1] = (ULONG)tcb_ptr; /* TCB ptr of calling task. */
1190 request[2] = TaskID; /* Task to chain. */
1191 request[3] = 0u;
1192
1193 /* Since the SysMgr supervisor thread has the highest priority, */
1194 /* this routine will be preempted by SysMgr supervisor thread. */
1195
1196 tx_queue_send(&osek_work_queue, request, TX_NO_WAIT);
1197
1198 TX_RESTORE
1199
1200 /* This should always succeed and sys manager terminates this task */
1201 /* This point will never be reached, as this thread itself will be */
1202 /* deleted by the System Manager! */
1203
1204 osek_internal_error(SYS_MGR_SEND_CHAINTASK);
1205
1206 return (E_OK);
1207 }
1208
1209
1210 /**************************************************************************/
1211 /* */
1212 /* FUNCTION RELEASE */
1213 /* */
1214 /* GetTaskID PORTABLE C */
1215 /* 6.1.7 */
1216 /* AUTHOR */
1217 /* */
1218 /* William E. Lamie, Microsoft Corporation */
1219 /* */
1220 /* DESCRIPTION */
1221 /* */
1222 /* GetTaskID returns the task id of the task currently running. */
1223 /* Calling GetTaskID is allowed from task level, ISR level and in */
1224 /* several hook routines. This service is intended to be used by */
1225 /* library functions and hook routines. If <TaskID> can�t be evaluated */
1226 /* (no task currently running), the service returns INVALID_TASK as */
1227 /* TaskType. */
1228 /* */
1229 /* INPUT */
1230 /* */
1231 /* TaskID Pointer to stored Task ID */
1232 /* */
1233 /* OUTPUT */
1234 /* */
1235 /* E_OK If success */
1236 /* INVALID_TASK If failure */
1237 /* */
1238 /* CALLS */
1239 /* */
1240 /* tx_thread_identify Identifies the current thread */
1241 /* */
1242 /* CALLED BY */
1243 /* */
1244 /* Application code */
1245 /* */
1246 /* RELEASE HISTORY */
1247 /* */
1248 /* DATE NAME DESCRIPTION */
1249 /* */
1250 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
1251 /* */
1252 /**************************************************************************/
GetTaskID(TaskRefType TaskID)1253 StatusType GetTaskID(TaskRefType TaskID)
1254 {
1255
1256 TX_THREAD *thread_ptr;
1257
1258
1259 /* Check for valid pointer to store the task ID. */
1260 if(TaskID == TX_NULL)
1261 {
1262 /* Return error. */
1263 return (E_OS_ID);
1264 }
1265
1266 /* Check for the pointer to thread. */
1267 thread_ptr = tx_thread_identify();
1268
1269 if ((thread_ptr == TX_NULL) || (thread_ptr == &_tx_timer_thread))
1270 {
1271 /* No task running TaskID can�t be evaluated return a special Error. */
1272 *TaskID = INVALID_TASK;
1273
1274 return (E_OK);
1275 }
1276
1277 if ((osek_wrapper_operation_mode == STARTUPHOOK_MODE) ||
1278 (osek_wrapper_operation_mode == SHUTDOWNHOOK_MODE) ||
1279 (osek_wrapper_operation_mode == ALARM_CALLBACK_MODE))
1280 {
1281 *TaskID = INVALID_TASK;
1282 }
1283 else
1284 {
1285 *TaskID = last_run_task;
1286 }
1287
1288 /* Return success. */
1289 return (E_OK);
1290 }
1291
1292
1293 /**************************************************************************/
1294 /* */
1295 /* FUNCTION RELEASE */
1296 /* */
1297 /* GetTaskState PORTABLE C */
1298 /* 6.1.7 */
1299 /* AUTHOR */
1300 /* */
1301 /* William E. Lamie, Microsoft Corporation */
1302 /* */
1303 /* DESCRIPTION */
1304 /* */
1305 /* Returns the state of a task (running, ready, waiting, suspended) at */
1306 /* the time of calling GetTaskState. The service may be called from */
1307 /* interrupt service routines, task level, and some hook routines. */
1308 /* Within a full preemptive system, calling this operating system */
1309 /* service only provides a meaningful result if the task runs in an */
1310 /* interrupt disabling state at the time of calling. */
1311 /* When a call is made from a task in a full preemptive system, the */
1312 /* result may already be incorrect at the time of evaluation. When the */
1313 /* service is called for a task, which is multiply activated, the */
1314 /* state is set to running if any instance of the task is running. */
1315 /* */
1316 /* INPUT */
1317 /* */
1318 /* Task_ID Task id to query */
1319 /* State Pointer to result state */
1320 /* */
1321 /* OUTPUT */
1322 /* */
1323 /* E_OK If successful */
1324 /* E_OS_ID Task is invalid */
1325 /* */
1326 /* CALLS */
1327 /* */
1328 /* osek_task_independent_area Check if called from task */
1329 /* independent area */
1330 /* tx_thread_identify Identify the current thread */
1331 /* */
1332 /* CALLED BY */
1333 /* */
1334 /* Application Code */
1335 /* */
1336 /* RELEASE HISTORY */
1337 /* */
1338 /* DATE NAME DESCRIPTION */
1339 /* */
1340 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
1341 /* */
1342 /**************************************************************************/
GetTaskState(TaskType TaskID,TaskStateRefType State)1343 StatusType GetTaskState(TaskType TaskID, TaskStateRefType State)
1344 {
1345 TX_INTERRUPT_SAVE_AREA
1346 OSEK_TCB *tcb_ptr;
1347 TX_THREAD *this_thread;
1348 ULONG area;
1349 TX_THREAD *p_thread;
1350
1351
1352 service_GetServiceId.id = (OsServiceIdType)OSServiceId_GetTaskState;
1353 service_GetTaskState.TaskID = (StatusType)0;
1354
1355 /* Check for valid task ID. */
1356 if(TaskID == 0u)
1357 {
1358 exec_ErrorHook(E_OS_ID);
1359 /* Return error. */
1360 return (E_OS_ID);
1361 }
1362
1363 /* Get OSEK TCB. */
1364 tcb_ptr = (OSEK_TCB *)TaskID;
1365
1366 /* First, check for an invalid task pointer. */
1367 if((tcb_ptr == TX_NULL) || ((tcb_ptr->osek_task_id) != OSEK_TASK_ID))
1368 {
1369 exec_ErrorHook(E_OS_ID);
1370 /* Return error. */
1371 return (E_OS_ID);
1372 }
1373
1374 TX_DISABLE
1375
1376 if ((osek_wrapper_operation_mode == STARTUPHOOK_MODE) ||
1377 (osek_wrapper_operation_mode == SHUTDOWNHOOK_MODE) ||
1378 (osek_wrapper_operation_mode == ALARM_CALLBACK_MODE))
1379 {
1380 TX_RESTORE
1381
1382 /* Return error. */
1383 return (E_OS_ID);
1384 }
1385
1386 /* Get the ThreadX TCB. */
1387 this_thread = (TX_THREAD *)tcb_ptr;
1388
1389 /* Check if we are only in task context. */
1390 area = osek_task_independent_area();
1391 if (area == TX_TRUE)
1392 {
1393 /* Get the OSEK TCB. */
1394 p_thread = tx_thread_identify();
1395 if(this_thread == p_thread)
1396 {
1397 TX_RESTORE
1398
1399 /* This is the running thread. */
1400 *State = RUNNING;
1401 return (E_OK);
1402 }
1403 }
1404
1405 if (tcb_ptr->waiting == TX_TRUE)
1406 {
1407 TX_RESTORE
1408
1409 *State = WAITING;
1410 return (E_OK);
1411 }
1412 if (tcb_ptr->suspended == TX_TRUE)
1413 {
1414 TX_RESTORE
1415
1416 *State = SUSPENDED;
1417 return (E_OK);
1418 }
1419
1420 TX_RESTORE
1421
1422 *State = READY;
1423 return (E_OK);
1424 }
1425
1426
1427 /**************************************************************************/
1428 /* */
1429 /* FUNCTION RELEASE */
1430 /* */
1431 /* Schedule PORTABLE C */
1432 /* 6.1.7 */
1433 /* AUTHOR */
1434 /* */
1435 /* William E. Lamie, Microsoft Corporation */
1436 /* */
1437 /* DESCRIPTION */
1438 /* */
1439 /* If a higher-priority task is ready, the internal resource of the */
1440 /* task is released, the current task is put into the ready state, its */
1441 /* context is saved and the higher-priority task is executed. */
1442 /* Otherwise the calling task is continued. */
1443 /* Rescheduling can only take place if an internal resource is */
1444 /* assigned to the calling task during system generation. For these */
1445 /* tasks, schedule enables a processor assignment to other tasks with */
1446 /* lower or equal priority than the ceiling priority of the internal */
1447 /* resource and higher priority than the priority of the calling task */
1448 /* in application-specific locations. When returning from schedule, */
1449 /* the internal resource has been taken again. */
1450 /* This service has no influence on tasks with no internal resource */
1451 /* assigned (preemptable tasks). */
1452 /* */
1453 /* INPUT */
1454 /* */
1455 /* None */
1456 /* */
1457 /* OUTPUT */
1458 /* */
1459 /* E_OK If success. */
1460 /* E_OS_CALLLEVEL Called at interrupt level */
1461 /* */
1462 /* CALLS */
1463 /* */
1464 /* osek_task_independent_area Check if called from task */
1465 /* */
1466 /* CALLED BY */
1467 /* */
1468 /* Application Code */
1469 /* */
1470 /* RELEASE HISTORY */
1471 /* */
1472 /* DATE NAME DESCRIPTION */
1473 /* */
1474 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
1475 /* */
1476 /**************************************************************************/
Schedule(void)1477 StatusType Schedule (void)
1478 {
1479 TX_INTERRUPT_SAVE_AREA
1480 OSEK_TCB *tcb_ptr;
1481 TX_THREAD *this_thread;
1482 ULONG request[SYSMGR_QUEUE_MSG_LENGTH];
1483 UINT status;
1484 ULONG area;
1485
1486 service_GetServiceId.id = (OsServiceIdType)OSServiceId_Schedule;
1487 service_GetTaskState.TaskID = (StatusType)0u;
1488
1489 /* Check if we are in task context. */
1490 area = osek_task_independent_area();
1491 if(area != TX_TRUE)
1492 {
1493 /* Return error. */
1494 return (E_OS_CALLEVEL);
1495 }
1496
1497 /* Get the ThreadX thread and OSEK TCB. */
1498 this_thread = tx_thread_identify();
1499 tcb_ptr = osek_thread2tcb(this_thread);
1500
1501 if (tcb_ptr == TX_NULL)
1502 {
1503 return (E_OS_ID);
1504 }
1505
1506 if (tcb_ptr->osek_task_id != OSEK_TASK_ID)
1507 {
1508 /* This call is allowed only from TASK. */
1509 return(E_OS_ID);
1510 }
1511
1512 TX_DISABLE
1513
1514 /* Check operating mode. */
1515 if (osek_wrapper_operation_mode != NORMAL_EXECUTION_MODE)
1516 {
1517
1518 TX_RESTORE
1519
1520 /* Hook routines, alarm callbacks and ISRs can't call this service. */
1521 /* This explicit check is required because all hook routines are
1522 executed in task's context. */
1523 return (E_OS_ID);
1524 }
1525
1526 /* Check if any resource is occupied. */
1527 if(tcb_ptr->res_ocp != 0u)
1528 {
1529 TX_RESTORE
1530
1531 exec_ErrorHook(E_OS_RESOURCE);
1532 /* Return. */
1533 return (E_OS_RESOURCE);
1534
1535 }
1536
1537 /* Now release internal resources, if any, held by this task */
1538 /* This call releases internal resources and moves the task to */
1539 /* a new queue position based on its new ceiling priority. */
1540 /* release_internal_resource(tcb_ptr); */
1541
1542 /* Now send message to system Manager to check any higher priority task is ready. */
1543 /* Build the request. */
1544 request[0] = SYSMGR_SCHEDULE; /* Request type. */
1545 request[1] = (ULONG)this_thread; /* Self ID. */
1546 request[2] = 0u;
1547 request[3] = 0u;
1548
1549 /* Since the SysMgr supervisor thread has the highest priority, */
1550 /* this routine will be preempted by SysMgr supervisor thread when */
1551 /* queue read is successful. */
1552 /* System Manager will eventually call start_osek_tasks. */
1553
1554 status = tx_queue_send(&osek_work_queue, request, TX_NO_WAIT);
1555
1556 TX_RESTORE
1557
1558 /* This should always succeed. */
1559 if (status != TX_SUCCESS)
1560 {
1561 /* System internal error. */
1562 osek_internal_error(SYS_MGR_SEND_CHAINTASK);
1563 }
1564
1565 /* Assume that the sys manager does its job. */
1566 /* And has returned from schedule, restore preemption threshold if any. */
1567
1568 /* Now we need to move this task back to its priority level */
1569 /* before coming here all internal resources (if any are taken). */
1570
1571 TX_DISABLE
1572
1573 /* Now check task's scheduling policy */
1574 if (tcb_ptr->policy == NON)
1575 {
1576 pop_task_from_table(tcb_ptr);
1577 /* If policy is NON then restore to OSEK_NON_SCHEDULE priority. */
1578 tcb_ptr->cur_threshold = OSEK_NON_SCHEDULE_PRIORITY;
1579 push_task_to_table(tcb_ptr);
1580 }
1581
1582 TX_RESTORE
1583
1584 return (E_OK);
1585 }
1586
1587
1588 /**************************************************************************/
1589 /* */
1590 /* FUNCTION RELEASE */
1591 /* */
1592 /* CreateResource PORTABLE C */
1593 /* 6.1.7 */
1594 /* AUTHOR */
1595 /* */
1596 /* William E. Lamie, Microsoft Corporation */
1597 /* */
1598 /* DESCRIPTION */
1599 /* */
1600 /* Creates resources for inter-task mutual exclusion for resource */
1601 /* protection */
1602 /* */
1603 /* INPUT */
1604 /* */
1605 /* name Name of the Resource. */
1606 /* type Type of the resource standard/internal */
1607 /* */
1608 /* OUTPUT */
1609 /* */
1610 /* RES_ID If successful */
1611 /* ZERO If error while creating resource */
1612 /* */
1613 /* CALLS */
1614 /* */
1615 /* osek_memory_allocate Allocate memory from system */
1616 /* osek_get_resource Get one resource from the pool */
1617 /* tx_mutex_create Create a Mutex in ThreadX */
1618 /* osek_internal_error OSEK internal Error */
1619 /* */
1620 /* CALLED BY */
1621 /* */
1622 /* Application Code */
1623 /* */
1624 /* RELEASE HISTORY */
1625 /* */
1626 /* DATE NAME DESCRIPTION */
1627 /* */
1628 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
1629 /* */
1630 /**************************************************************************/
CreateResource(const CHAR * name,StatusType type,ResourceType linked_res)1631 ResourceType CreateResource(const CHAR *name, StatusType type, ResourceType linked_res)
1632 {
1633
1634 OSEK_RESOURCE *res_ptr;
1635 OSEK_RESOURCE *linked_res_ptr;
1636 OSEK_RESOURCE *res1_ptr;
1637
1638 ResourceType ID;
1639 ResourceType linked_res_id;
1640 UINT done_flag;
1641 UINT iter_max;
1642
1643 /* Check whether calling from task context or ISR. */
1644 if ((osek_init_state != OSEK_INIT) || /* Not in Initialization. */
1645 (_tx_thread_current_ptr == &_tx_timer_thread))
1646 {
1647 /* Return default error. */
1648 Application->osek_object_creation_error++;
1649 return ((ResourceType) TX_NULL);
1650 }
1651
1652 /* Check whether the linked resource (if specified) exists. */
1653 if (type == LINKED)
1654 {
1655 if (linked_res == 0u)
1656 {
1657 /* Specified linked resource doesn't exist */
1658 /* OR Resource is trying to link itself. */
1659 Application->osek_object_creation_error++;
1660 return ((ResourceType) TX_NULL);
1661 }
1662
1663 /* Check if the resource to which this resource is linked is external. */
1664 linked_res_ptr = (OSEK_RESOURCE *)linked_res;
1665 if (linked_res_ptr->type == INTERNAL)
1666 {
1667 /* Specified linked resource is of INTERNAL type. */
1668 Application->osek_object_creation_error++;
1669 return ((ResourceType) TX_NULL);
1670 }
1671 }
1672
1673 /* Find out any resource is available. */
1674 ID = osek_get_resource();
1675 if(ID == 0u)
1676 {
1677 /* Resource is not available. */
1678 Application->osek_object_creation_error++;
1679 return ((ResourceType) TX_NULL);
1680 }
1681
1682 /* Get the OSEK resource. */
1683 res_ptr = (OSEK_RESOURCE *)ID;
1684
1685 res_ptr->name = name;
1686
1687 res_ptr->c_priority = 0u;
1688
1689 res_ptr->type = type;
1690
1691 res_ptr->linked_res = linked_res;
1692
1693 res_ptr->resolved_res = 0u;
1694
1695 /* Now resolve if chain of linked linked resources. */
1696
1697 if (res_ptr->type == LINKED)
1698 {
1699 done_flag = FALSE;
1700 res1_ptr = res_ptr;
1701 iter_max = OSEK_MAX_LINK_DEPTH; /* Safety count to prevent infinite loop. */
1702 while(done_flag == 0u)
1703 {
1704 if(iter_max == 0u) {
1705 /* Maximum iteration count exceeded, return an error. */
1706 Application->osek_object_creation_error++;
1707 return ((ResourceType) TX_NULL);
1708 }
1709
1710 linked_res_id = res1_ptr->linked_res;
1711 linked_res_ptr = (OSEK_RESOURCE *)linked_res_id;
1712 if (linked_res_ptr->type == STANDARD)
1713 {
1714 res_ptr->resolved_res = linked_res_id;
1715 done_flag = TRUE;
1716 }
1717 res1_ptr = linked_res_ptr;
1718
1719 iter_max--;
1720 }
1721
1722 }
1723
1724
1725 /* No task is occupying this resource. */
1726 res_ptr->taskid = 0u;
1727
1728 res_ptr->osek_res_id = OSEK_RES_ID;
1729
1730 return (ID);
1731 }
1732
1733
1734 /**************************************************************************/
1735 /* */
1736 /* FUNCTION RELEASE */
1737 /* */
1738 /* GetResource PORTABLE C */
1739 /* 6.1.7 */
1740 /* AUTHOR */
1741 /* */
1742 /* William E. Lamie, Microsoft Corporation */
1743 /* */
1744 /* DESCRIPTION */
1745 /* */
1746 /* This call serves to enter critical sections in the code that are */
1747 /* assigned to the resource referenced by <ResID>. A critical section */
1748 /* must always be left using ReleaseResource. Nested resource */
1749 /* occupation is only allowed if the inner critical sections are */
1750 /* completely executed within the surrounding critical section. */
1751 /* Nested occupation of one and the same resource is also forbidden. */
1752 /* Corresponding calls to GetResource and ReleaseResource should appear */
1753 /* within the same function on the same function level. */
1754 /* */
1755 /* INPUT */
1756 /* */
1757 /* id Id of the resource. */
1758 /* */
1759 /* OUTPUT */
1760 /* */
1761 /* E_OK If success */
1762 /* E_OS_CALLEVEL Called from ISR */
1763 /* E_OS_ACCESS Attempt to get a resource which is */
1764 /* already occupied by any task or ISR, */
1765 /* or the statically assigned priority of */
1766 /* the calling task or interrupt routine */
1767 /* is higher than the calculated ceiling */
1768 /* priority, */
1769 /* */
1770 /* CALLS */
1771 /* */
1772 /* osek_task_independent_area See if called from task independent */
1773 /* area */
1774 /* tx_thread_identify Identify the current thread */
1775 /* osek_internal_error OSEK internal error */
1776 /* */
1777 /* CALLED BY */
1778 /* */
1779 /* Application Code */
1780 /* */
1781 /* RELEASE HISTORY */
1782 /* */
1783 /* DATE NAME DESCRIPTION */
1784 /* */
1785 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
1786 /* */
1787 /**************************************************************************/
GetResource(ResourceType id)1788 StatusType GetResource(ResourceType id)
1789 {
1790 TX_INTERRUPT_SAVE_AREA
1791 OSEK_RESOURCE *osek_res;
1792 OSEK_TCB *tcb_ptr;
1793 TX_THREAD *this_thread;
1794 UINT index ;
1795 UINT new_prio;
1796 ULONG request[SYSMGR_QUEUE_MSG_LENGTH];
1797 UINT status;
1798 ULONG area;
1799
1800
1801
1802 service_GetServiceId.id = (OsServiceIdType)OSServiceId_GetResource;
1803 service_GetResource.ResID = id;
1804
1805 /* Check we are calling from task context only. */
1806 area = osek_task_independent_area();
1807 if(area == 0u)
1808 {
1809 exec_ErrorHook(E_OS_CALLEVEL);
1810 /* Return default error. */
1811 return (E_OS_CALLEVEL);
1812 }
1813
1814 /* Check for valid ID. */
1815 if(id == 0u)
1816 {
1817 exec_ErrorHook(E_OS_ID);
1818 /* Return error. */
1819 return (E_OS_ID);
1820 }
1821
1822 /* Get thread currently executed. */
1823 this_thread = tx_thread_identify();
1824 if(this_thread == NULL)
1825 {
1826 exec_ErrorHook(E_OS_CALLEVEL);
1827 return (E_OS_CALLEVEL);
1828 }
1829
1830 /* Get RES's control block. */
1831 osek_res = (OSEK_RESOURCE *)id;
1832
1833 /* First, check for an invalid resource pointer. */
1834 if((osek_res == TX_NULL) || ((osek_res->osek_res_id) != OSEK_RES_ID))
1835 {
1836 exec_ErrorHook(E_OS_ID);
1837
1838 /* Return Error. */
1839 return (E_OS_ID);
1840 }
1841
1842 /* Get the OSEK TCB. */
1843 tcb_ptr = (OSEK_TCB *) this_thread;
1844
1845 /* Now check whether this resource is standard or internal. */
1846 if (osek_res->type == INTERNAL)
1847 {
1848 /* Internal Resource can not be occupied via GetResource call. */
1849 exec_ErrorHook(E_OS_ID);
1850 return (E_OS_ID);
1851 }
1852
1853 TX_DISABLE
1854
1855 /* Now check whether this resource is occupied. */
1856 if (osek_res->taskid != 0u)
1857 {
1858 TX_RESTORE
1859
1860 /* Already occupied by this task or any other task, this also prevent double occupancy. */
1861 exec_ErrorHook(E_OS_ACCESS);
1862
1863 return (E_OS_ACCESS);
1864 }
1865
1866 /* OK up to this point, now what type of resource is it? */
1867 /* Because 'RES_SCEDULER' is a special type of resource. */
1868
1869 if (id == RES_SCHEDULER)
1870 {
1871
1872 /* This task has taken this resource so update this task's resource hold count. */
1873 tcb_ptr->res_ocp++;
1874
1875 /* Save this task's id in the res's control block. */
1876 osek_res->taskid = (TaskType)tcb_ptr;
1877
1878 tcb_ptr->resource_scheduler = TX_TRUE;
1879
1880 /* Being RES_SCHEDULER no need to add RES_SCEDULER in the task's list of occupied resources. */
1881
1882 /* As task is occupying RES_SCHEDULER all preemptions are blocked so make the policy to NON PREEMP. */
1883 /* A NON preempt type task is already having OSEK_NON_SCHEDULE_PRIORITY during RUN time, so need
1884 to change it. */
1885
1886 if (tcb_ptr->policy == FULL)
1887 {
1888 /* For a FULL preempt type task assign having highest preemption threshold */
1889 /* Now ask the System Manager to change this task's priority, and also check if there is
1890 any possibility of preemption. */
1891 /* Send message to System Manager to check any preemption out of ReleaseResource call. */
1892 new_prio = OSEK_NON_SCHEDULE_PRIORITY;
1893
1894 /* Build the request. */
1895 request[0] = SYSMGR_GET_RESOURCE; /* Request type. */
1896 request[1] = (ULONG)this_thread;
1897 request[2] = (ULONG)new_prio;
1898 request[3] = 0u;
1899
1900 /* Since the SysMgr supervisor thread has the highest priority, */
1901 /* this routine will be preempted by SysMgr supervisor thread when */
1902 /* queue is successful. */
1903 /* System Manager will eventually call start_osek_tasks. */
1904
1905 status = tx_queue_send(&osek_work_queue, request, TX_NO_WAIT);
1906
1907 /* This should always succeed. */
1908 if (status != TX_SUCCESS)
1909 {
1910 /* System internal error. */
1911 osek_internal_error(SYS_MGR_SEND_CHAINTASK);
1912
1913 }
1914 }
1915
1916 TX_RESTORE
1917
1918 return (E_OK);
1919
1920 } /* End if ( id == RES_SCHEDULER ). */
1921
1922
1923 /* Not RES_SCEDULER. */
1924
1925 /* Check whether this resource is assigned to this task or not? */
1926 for (index = 0u; index < OSEK_MAX_EXTERNAL_RES; index++)
1927 {
1928 if (tcb_ptr-> external_resource_list[index] == id) {
1929 /* Yes it is registered with this task, stop searching. */
1930 break;
1931 }
1932 } /* Check next in the list. */
1933
1934 /* Checked entire list and found that this resource is not in the list? */
1935 if (index >= OSEK_MAX_EXTERNAL_RES)
1936 {
1937 TX_RESTORE
1938
1939 exec_ErrorHook(E_OS_NOFUNC);
1940
1941 /* Return error. */
1942 return (E_OS_NOFUNC);
1943 }
1944
1945 /* Yes this resource is assigned to this task. */
1946 /* First check the task has room to hold one more resource? */
1947
1948 /* Find the next free entry in the task's res occupied list. */
1949 for (index = 0u; index < OSEK_MAX_EXTERNAL_RES; index++)
1950 {
1951 if(tcb_ptr->external_resource_occuplied_list[index] == 0u)
1952 {
1953 /* Found next free entry but do not add this resource to the list at this moment. */
1954 break;
1955 }
1956 }
1957
1958 /* We got an entry or not? */
1959 if (index >= OSEK_MAX_EXTERNAL_RES)
1960 {
1961 TX_RESTORE
1962
1963 /* This is very unlikely, as list is big enough to hold all resources defined in the system. */
1964 exec_ErrorHook(E_OS_ACCESS);
1965
1966 /* Return Error. */
1967 return (E_OS_ACCESS);
1968 }
1969
1970 /* Now entry is available, take this resource. */
1971
1972 tcb_ptr->external_resource_occuplied_list[index] = id;
1973 /* Save this task's id in the res's control block to indicate that this is the owner of this res. */
1974 osek_res->taskid = (TaskType)(tcb_ptr);
1975 /* This task has taken this resource so update this task's resource hold count. */
1976 tcb_ptr->res_ocp++;
1977
1978 /* Now we need to change this task's preemption threshold to this resource's ceiling priority. */
1979 /* But if the task is of NON scheduling no need to take any action , it is already having
1980 highest preemption threshold. */
1981
1982 if ((tcb_ptr->policy == FULL) && (tcb_ptr->cur_threshold < osek_res->c_priority))
1983 {
1984 /* Need to change the at the task is having lower preemption threshold. */
1985 /* Remove this task from its current queue and place it in front of
1986 occupied resource's ceiling priority queue. */
1987
1988 new_prio = osek_res->c_priority;
1989
1990 /* Build the request. */
1991 request[0] = SYSMGR_GET_RESOURCE; /* Request type. */
1992 request[1] = (ULONG)this_thread;
1993 request[2] = (ULONG)new_prio;
1994 request[3] = 0u;
1995
1996 /* Since the SysMgr supervisor thread has the highest priority, */
1997 /* this routine will be preempted by SysMgr supervisor thread when */
1998 /* queue is successful. */
1999 /* System Manager will eventually call start_osek_tasks. */
2000
2001 status = tx_queue_send(&osek_work_queue, request, TX_NO_WAIT);
2002
2003 /* This should always succeed. */
2004 if (status != TX_SUCCESS)
2005 {
2006 /* System internal error. */
2007 osek_internal_error(SYS_MGR_SEND_CHAINTASK);
2008 }
2009 }
2010
2011 TX_RESTORE
2012
2013 return (E_OK);
2014 }
2015
2016
2017 /**************************************************************************/
2018 /* */
2019 /* FUNCTION RELEASE */
2020 /* */
2021 /* ReleaseResource PORTABLE C */
2022 /* 6.1.7 */
2023 /* AUTHOR */
2024 /* */
2025 /* William E. Lamie, Microsoft Corporation */
2026 /* */
2027 /* DESCRIPTION */
2028 /* */
2029 /* ReleaseResource is the counterpart of GetResource and serves to */
2030 /* leave critical sections in the code that are assigned to the */
2031 /* resource referenced by <ResID>. For information on nesting */
2032 /* conditions, see GetResource. The service may be called from an ISR */
2033 /* and from task level */
2034 /* */
2035 /* INPUT */
2036 /* */
2037 /* id Id of the resource. */
2038 /* */
2039 /* OUTPUT */
2040 /* */
2041 /* E_OK If successful */
2042 /* E_OS_NOFUNC Attempt to release a resource which is */
2043 /* not occupied by any task or ISR, or */
2044 /* another resource has to be released */
2045 /* before,If error occurs while creating */
2046 /* task */
2047 /* E_OS_ACCESS Attempt to release a resource which has*/
2048 /* a lower ceiling priority than the */
2049 /* statically assigned priority of the */
2050 /* calling task or interrupt routine. */
2051 /* */
2052 /* CALLS */
2053 /* */
2054 /* */
2055 /* osek_task_independent_area See if called from task independent */
2056 /* area */
2057 /* tx_thread_identify Identify the current thread */
2058 /* osek_internal_error OSEK internal error */
2059 /* */
2060 /* CALLED BY */
2061 /* */
2062 /* Application Code */
2063 /* */
2064 /* RELEASE HISTORY */
2065 /* */
2066 /* DATE NAME DESCRIPTION */
2067 /* */
2068 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
2069 /* */
2070 /**************************************************************************/
ReleaseResource(ResourceType id)2071 StatusType ReleaseResource(ResourceType id)
2072 {
2073 TX_INTERRUPT_SAVE_AREA
2074 OSEK_RESOURCE *osek_res;
2075 OSEK_TCB *tcb_ptr;
2076 TX_THREAD *this_thread;
2077 UINT index;
2078 UINT res_prio;
2079 UINT location;
2080 UINT new_prio;
2081 ULONG request[SYSMGR_QUEUE_MSG_LENGTH];
2082 UINT status;
2083 ULONG area;
2084
2085 service_GetServiceId.id = (OsServiceIdType)OSServiceId_ReleaseResource;
2086 service_ReleaseResource.ResID = id;
2087
2088 /* Fist check valid resource id and proper calling context. */
2089
2090 /* Check we calling from from task context only. */
2091 area = osek_task_independent_area();
2092 if(area == 0u)
2093 {
2094 exec_ErrorHook(E_OS_CALLEVEL);
2095
2096 /* Return default error. */
2097 return (E_OS_CALLEVEL);
2098 }
2099
2100 /* Check for valid Resource ID. */
2101 if(id == 0u)
2102 {
2103 exec_ErrorHook(E_OS_ID);
2104
2105 /* Return error. */
2106 return (E_OS_ID);
2107 }
2108
2109 /* Get thread currently executed. */
2110 this_thread = tx_thread_identify();
2111 if(this_thread == TX_NULL)
2112 {
2113 exec_ErrorHook(E_OS_CALLEVEL);
2114
2115 return (E_OS_CALLEVEL);
2116 }
2117
2118 /* Get OSEK resource control block. */
2119 osek_res = (OSEK_RESOURCE *)id;
2120
2121 /* Get the OSEK TCB. */
2122 tcb_ptr = (OSEK_TCB *)this_thread;
2123
2124 /* Now check whether this resource is standard or internal. */
2125
2126 if (osek_res->type == INTERNAL)
2127 {
2128 /* Internal resource can not be released via ReleaseResource call. */
2129 exec_ErrorHook(E_OS_ID);
2130
2131 return (E_OS_ID);
2132 }
2133
2134 TX_DISABLE
2135
2136 /* Is this task holding any resource? Check for resource count. */
2137 if(tcb_ptr->res_ocp == 0u)
2138 {
2139 TX_RESTORE
2140
2141 /* No resource taken yet trying to release resource? */
2142 exec_ErrorHook(E_OS_NOFUNC);
2143
2144 /* Return error. */
2145 return(E_OS_NOFUNC);
2146 }
2147
2148 /* Check whether this resource is occupied by this task. */
2149 /* A task cannot release resource which are not occupied by itself. */
2150
2151 if (osek_res->taskid != (TaskType)tcb_ptr)
2152 {
2153 TX_RESTORE
2154
2155 exec_ErrorHook(E_OS_NOFUNC);
2156
2157 return (E_OS_NOFUNC);
2158 }
2159
2160 /* Everything is valid up to this point, now try to release the resource requested. */
2161 /* Check what type of Resource it is as RES_SCEDULER is a special case of resource. */
2162
2163 if (id == RES_SCHEDULER)
2164 {
2165
2166 /* Remove this task's id from the res's control block which usually indicate that this is the
2167 owner of this res and also update this task's resource hold count. */
2168 osek_res->taskid = 0u;
2169 tcb_ptr->res_ocp--;
2170
2171 /* As the task is giving up RES_SCHEDULER, make the associated flag FALSE. */
2172 tcb_ptr->resource_scheduler = TX_FALSE;
2173
2174 /* If Task is NON scheduling type, no preemption takes place. */
2175 if (tcb_ptr->policy == NON)
2176 {
2177 TX_RESTORE
2178
2179 /* Release this resource. */
2180 return (E_OK);
2181 }
2182
2183 /* With FULL scheduling, a change in preemption to highest
2184 ceiling priority of any other resources held by this task is needed. */
2185 /* Check RES_SCEDULER is the only resource occupied by this task, then restore this task's threshold
2186 to its original priority. */
2187
2188 /* Assume no other resources are held. */
2189 new_prio = tcb_ptr->org_prio;
2190
2191 if (tcb_ptr->res_ocp > 0u)
2192 {
2193 /* If no other external resources are held the task will revert back to
2194 to its original design time priority. */
2195 /* Or check the ceiling priorities of other external resources held by this task. */
2196
2197 for (index = 0u; index < OSEK_MAX_EXTERNAL_RES; index++)
2198 {
2199 if (tcb_ptr->external_resource_occuplied_list[index] == 0u)
2200 {
2201 break;
2202 }
2203
2204 res_prio = ((OSEK_RESOURCE *) (tcb_ptr->external_resource_occuplied_list[index]))->c_priority;
2205 if (new_prio < res_prio) {
2206 new_prio = res_prio;
2207 }
2208 }
2209 }
2210
2211 /* Done with external resource, now check if there are any internal resources held? */
2212 for ( index = 0u; index < OSEK_MAX_INTERNAL_RES; index++)
2213 {
2214 if (tcb_ptr->internal_resource_occuplied_list[index] == 0u)
2215 {
2216 break;
2217 }
2218
2219 res_prio = ((OSEK_RESOURCE *) (tcb_ptr->internal_resource_occuplied_list[index]))->c_priority;
2220
2221 if (new_prio < res_prio)
2222 {
2223 new_prio = res_prio;
2224 }
2225 }
2226
2227
2228 /* new_prio now holds the highest of ceiling priority of the remaining
2229 resources held by this task. */
2230
2231 /* Now ask the system manager to change this task's priority, and also check if there is
2232 any possibility of preemption. */
2233 /* Send message to the system manager to check any preemption out of ReleaseResource call. */
2234
2235 /* Build the request. */
2236 request[0] = SYSMGR_RELEASE_RESOURCE; /* Request type. */
2237 request[1] = (ULONG)this_thread;
2238 request[2] = (ULONG)new_prio;
2239 request[3] = 0u;
2240
2241 /* Since the SysMgr supervisor thread has the highest priority, */
2242 /* this routine will be preempted by SysMgr supervisor thread when */
2243 /* queue is successful. */
2244 /* System Manager will eventually call start_osek_tasks. */
2245
2246 status = tx_queue_send(&osek_work_queue, request, TX_NO_WAIT);
2247
2248 /* This should always succeed. */
2249 if (status != TX_SUCCESS)
2250 {
2251 /* System internal error. */
2252 osek_internal_error(SYS_MGR_SEND_CHAINTASK);
2253
2254 }
2255
2256 TX_RESTORE
2257
2258 /* Assume that the system manager does its job. */
2259 return (E_OK);
2260
2261 } /* End if ( id == RES_SCHEDULER ). */
2262
2263
2264 /* Not a RES_SCHEDULER. */
2265
2266 /* Are we releasing the resource which is last taken? */
2267 for (index = 0u; index < OSEK_MAX_EXTERNAL_RES; index++)
2268 {
2269 if ( tcb_ptr->external_resource_occuplied_list[index] == 0u)
2270 {
2271 /* Reached at the last entry, stop searching. */
2272 break;
2273 }
2274 } /* Next entry. */
2275
2276 if (index == 0u)
2277 {
2278 /* List is empty and resource is taken? */
2279 return(E_OS_NOFUNC);
2280 }
2281
2282 location = index - 1u; /* Save the location of last resource entry. */
2283
2284 /* Check the last resource taken. */
2285 if (tcb_ptr->external_resource_occuplied_list[location] != id)
2286 {
2287 /* Are we trying to release the resource which was not in LIFO order. */
2288 exec_ErrorHook(E_OS_NOFUNC);
2289
2290 /* Return error. */
2291 return(E_OS_NOFUNC);
2292 }
2293
2294 /* Now to change preemption threshold to suit next resource with highest ceiling priority */
2295 /* But if the task has got NON scheduling policy then do nothing. */
2296
2297 tcb_ptr->external_resource_occuplied_list[location] = 0u;
2298 /* And remove this task's id from the res's control block. */
2299 osek_res->taskid = 0u;
2300 tcb_ptr->res_ocp--;
2301
2302 if ((tcb_ptr->policy == NON ) || (tcb_ptr->resource_scheduler == TX_TRUE))
2303 {
2304 /* In case of NON scheduling policy or if a Task holds a RES_SCHEDULER, no need to change preemption. */
2305 /* Even if a resource is released the task is still remains in OSEK_NON_SCHEDULE_PRIORITY. */
2306 /* just remove this resource from the list. */
2307 return (E_OK);
2308 }
2309
2310 /* FULL scheduling policy and no RES_SCHEDULER held. */
2311
2312 /* Assume no other resources are held. */
2313 new_prio = tcb_ptr->org_prio;
2314
2315 if (tcb_ptr->res_ocp > 0u)
2316 {
2317 /* This task is holding more than one resources. */
2318 /* Find out new highest ceiling priority. */
2319 /* Assume task's original priority is the highest. */
2320 for ( index = 0u; index < OSEK_MAX_EXTERNAL_RES; index++)
2321 {
2322
2323 /* Get this resource's ceiling priority. */
2324 if ( tcb_ptr->external_resource_occuplied_list[index] == 0u) {
2325 break;
2326 }
2327
2328 res_prio = ((OSEK_RESOURCE *) (tcb_ptr->external_resource_occuplied_list[index]) )->c_priority;
2329 /* Check if this is more than Task's static priority. */
2330 if (new_prio < res_prio)
2331 {
2332 new_prio = res_prio;
2333 }
2334 }
2335
2336 }
2337
2338 /* Done with external resource, now check if there are any internal resources held? */
2339 for (index = 0u; index < OSEK_MAX_INTERNAL_RES; index++)
2340 {
2341 if (tcb_ptr->internal_resource_occuplied_list[index] == 0u)
2342 {
2343 break;
2344 }
2345
2346 res_prio = ( (OSEK_RESOURCE *) (tcb_ptr->internal_resource_occuplied_list[index]) )->c_priority;
2347
2348 if (new_prio < res_prio )
2349 {
2350 new_prio = res_prio;
2351 }
2352 }
2353
2354 /* new_prio now holds the highest of ceiling priority of the remaining
2355 resources held by this task. */
2356
2357 /* Now ask the system manager to change this task's priority, and also check if there is
2358 any possibility of preemption. */
2359 /* Send message to system manager to check any preemption out of ReleaseResource call. */
2360
2361 /* Build the request. */
2362 request[0] = SYSMGR_RELEASE_RESOURCE; /* Request type. */
2363 request[1] = (ULONG)this_thread;
2364 request[2] = (ULONG)new_prio;
2365 request[3] = 0u;
2366
2367 /* Since the SysMgr supervisor thread has the highest priority, */
2368 /* this routine will be preempted by SysMgr supervisor thread when */
2369 /* queue is successful. */
2370 /* System manager will eventually call start_osek_tasks. */
2371
2372 status = tx_queue_send(&osek_work_queue, request, TX_NO_WAIT);
2373
2374 TX_RESTORE
2375
2376 /* This should always succeed. */
2377 if (status != TX_SUCCESS)
2378 {
2379 /* System internal error. */
2380 osek_internal_error(SYS_MGR_SEND_CHAINTASK);
2381 }
2382
2383 /* Assume that system manager does its job. */
2384 return (E_OK);
2385 }
2386
2387
2388 /**************************************************************************/
2389 /* */
2390 /* FUNCTION RELEASE */
2391 /* */
2392 /* RegisterTasktoResource PORTABLE C */
2393 /* 6.1.7 */
2394 /* AUTHOR */
2395 /* */
2396 /* William E. Lamie, Microsoft Corporation */
2397 /* */
2398 /* DESCRIPTION */
2399 /* */
2400 /* This function registers a resource to the task specified, provided */
2401 /* a free entry is available in the task's list of resources. */
2402 /* If entry is registered then resource's ceiling priority is also */
2403 /* adjusted to this task's priority provided that the task's priority */
2404 /* is higher than the resource's current ceiling priority. */
2405 /* */
2406 /* INPUT */
2407 /* */
2408 /* Resource Id of the resource. */
2409 /* TaskID ID of the task */
2410 /* */
2411 /* OUTPUT */
2412 /* */
2413 /* E_OK If successful */
2414 /* E_OS_NOFUNC No free entries */
2415 /* E_OS_ID Invalid task or resource id. */
2416 /* not occupied by any task or ISR, or */
2417 /* another resource has to be released */
2418 /* before. */
2419 /* E_OS_ACCESS Attempt to release an invalid resource */
2420 /* */
2421 /* CALLS */
2422 /* */
2423 /* None */
2424 /* */
2425 /* CALLED BY */
2426 /* */
2427 /* Application Code (System Creation section) */
2428 /* */
2429 /* RELEASE HISTORY */
2430 /* */
2431 /* DATE NAME DESCRIPTION */
2432 /* */
2433 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
2434 /* */
2435 /**************************************************************************/
RegisterTasktoResource(ResourceType Resource,TaskType TaskID)2436 StatusType RegisterTasktoResource(ResourceType Resource, TaskType TaskID)
2437 {
2438
2439 OSEK_TCB *tcb_ptr;
2440 OSEK_RESOURCE *resource_ptr;
2441 UINT index;
2442
2443 /* Check if we are in initialization. */
2444 /* This will ensure that no one calls this function after system is started. */
2445 if (osek_init_state != OSEK_INIT)
2446 {
2447 /* Return OSEK internal error. This is not a standard OSEK error. */
2448 Application->osek_object_creation_error++;
2449 return ((StatusType)TX_NULL);
2450 }
2451
2452 /* Check for valid Resource ID. */
2453 if(Resource == 0u)
2454 {
2455 /* Return error. */
2456 Application->osek_object_creation_error++;
2457 return (E_OS_ID);
2458 }
2459
2460 /* Check if task id is valid. */
2461 if(TaskID == 0u)
2462 {
2463 /* Return error. */
2464 return (E_OS_ID);
2465 }
2466
2467 /* Convert object IDs to object control block pointers. */
2468 resource_ptr = (OSEK_RESOURCE *)Resource;
2469 tcb_ptr = (OSEK_TCB *)TaskID;
2470
2471 /* Check for valid resource pointer. */
2472 if (resource_ptr == TX_NULL)
2473 {
2474 Application->osek_object_creation_error++;
2475 return (E_OS_ID);
2476 }
2477
2478 if (resource_ptr->osek_res_id != OSEK_RES_ID)
2479 {
2480 Application->osek_object_creation_error++;
2481 return (E_OS_ID);
2482 }
2483
2484 /* Check for valid task pointer. */
2485 if (tcb_ptr == TX_NULL)
2486 {
2487 Application->osek_object_creation_error++;
2488 return (E_OS_ID);
2489 }
2490
2491 if ((tcb_ptr->osek_task_id != OSEK_TASK_ID) && (tcb_ptr->osek_task_id != OSEK_ISR_ID))
2492 {
2493 Application->osek_object_creation_error++;
2494 return (E_OS_ID);
2495 }
2496
2497 /* This task is to be registered with this resource. */
2498 /* Add this Resource to the task's list of resource. */
2499 /* provided there is space left for this. */
2500
2501 /* Before check whether the resource is internal or standard? */
2502 if ((resource_ptr->type == STANDARD)|| (resource_ptr->type == LINKED))
2503 {
2504
2505 for (index = 0u; index < OSEK_MAX_EXTERNAL_RES; index++)
2506 {
2507 if (tcb_ptr->external_resource_list[index] == 0u)
2508 {
2509 /* Empty entry found, write this resource there. */
2510 tcb_ptr->external_resource_list[index] = Resource;
2511
2512 /* Also clear the resource occupancy count. */
2513 tcb_ptr->external_resource_occuplied_list[index] = 0u;
2514
2515 /* As this resource is attached to a TASK or ISR change this resource's ceiling priority
2516 to task's (or ISR's) priority provided that it is higher than resource's current ceiling priority. */
2517 if (tcb_ptr->org_prio > resource_ptr->c_priority)
2518 {
2519 resource_ptr->c_priority = tcb_ptr->org_prio;
2520 }
2521
2522 /* Job done. */
2523 break;
2524 } /* Try next entry. */
2525 }
2526
2527 if (index >= OSEK_MAX_EXTERNAL_RES) /* No free entry. */
2528 {
2529 Application->osek_object_creation_error++;
2530 return (E_OS_NOFUNC);
2531 }
2532 else
2533 {
2534 return (E_OK);
2535 }
2536 } /* END STANDARD. */
2537 else
2538 {
2539 /* Attaching Internal resource to this task, so set the flag. */
2540 tcb_ptr->internal_res = TX_TRUE;
2541
2542 for (index = 0u; index < OSEK_MAX_INTERNAL_RES; index++)
2543 {
2544 if (tcb_ptr->internal_resource_list[index] == 0u)
2545 {
2546 /* Empty entry found write this resource there. */
2547 tcb_ptr->internal_resource_list[index] = Resource;
2548
2549 /* As this resource is attached to the resource change this resource's ceiling priority
2550 to this task's original priority provide it is higher than resource's current ceiling priority. */
2551 if (tcb_ptr->org_prio > resource_ptr->c_priority)
2552 {
2553 resource_ptr->c_priority = tcb_ptr->org_prio;
2554 }
2555
2556 /* Job done. */
2557 break;
2558 } /* Try next entry. */
2559 }
2560
2561 if (index >= OSEK_MAX_INTERNAL_RES) /* No free entry. */
2562 {
2563 Application->osek_object_creation_error++;
2564 return (E_OS_NOFUNC);
2565 }
2566 else
2567 {
2568 return (E_OK);
2569 }
2570 }
2571 }
2572
2573
2574 /**************************************************************************/
2575 /* */
2576 /* FUNCTION RELEASE */
2577 /* */
2578 /* RegisterISRtoResource PORTABLE C */
2579 /* 6.1.7 */
2580 /* AUTHOR */
2581 /* */
2582 /* William E. Lamie, Microsoft Corporation */
2583 /* */
2584 /* DESCRIPTION */
2585 /* */
2586 /* This function registers a resource to the ISR specified, provided */
2587 /* a free entry is available in the ISR's list of resources. */
2588 /* If entry is registered then resource's ceiling priority is also */
2589 /* adjusted to this task's priority provided that the task's priority */
2590 /* is higher than the resource's current ceiling priority. */
2591 /* */
2592 /* INPUT */
2593 /* */
2594 /* Resource Id of the resource. */
2595 /* TaskID ID of the task */
2596 /* */
2597 /* OUTPUT */
2598 /* */
2599 /* E_OK If successful */
2600 /* E_OS_NOFUNC No free entries */
2601 /* E_OS_ID Invalid task or resource id. */
2602 /* not occupied by any task or ISR, or */
2603 /* another resource has to be released */
2604 /* before */
2605 /* E_OS_ACCESS Attempt to release an invalid resource */
2606 /* */
2607 /* CALLS */
2608 /* */
2609 /* RegisterTasktoResource Register resource. */
2610 /* */
2611 /* CALLED BY */
2612 /* */
2613 /* Application Code */
2614 /* */
2615 /* RELEASE HISTORY */
2616 /* */
2617 /* DATE NAME DESCRIPTION */
2618 /* */
2619 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
2620 /* */
2621 /**************************************************************************/
RegisterISRtoResource(ResourceType Resource,ISRType ISRID)2622 StatusType RegisterISRtoResource(ResourceType Resource, ISRType ISRID)
2623 {
2624 StatusType status;
2625
2626 status = RegisterTasktoResource(Resource, ISRID);
2627 return (status);
2628 }
2629
2630
2631 /**************************************************************************/
2632 /* */
2633 /* FUNCTION RELEASE */
2634 /* */
2635 /* CreateEvent PORTABLE C */
2636 /* 6.1.7 */
2637 /* AUTHOR */
2638 /* */
2639 /* William E. Lamie, Microsoft Corporation */
2640 /* */
2641 /* DESCRIPTION */
2642 /* */
2643 /* Creates an event. It is a 32 bit number with only one bit set. */
2644 /* */
2645 /* */
2646 /* OUTPUT */
2647 /* */
2648 /* eventid If success */
2649 /* 0 If error occurs */
2650 /* */
2651 /* CALLS */
2652 /* */
2653 /* osek_get_event Get the event */
2654 /* osek_internal_error OSEK internal error */
2655 /* */
2656 /* CALLED BY */
2657 /* */
2658 /* OSEK internal call */
2659 /* */
2660 /* RELEASE HISTORY */
2661 /* */
2662 /* DATE NAME DESCRIPTION */
2663 /* */
2664 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
2665 /* */
2666 /**************************************************************************/
CreateEvent(void)2667 EventMaskType CreateEvent(void)
2668 {
2669 EventMaskType event;
2670
2671 event = osek_get_event();
2672 if (event == 0u)
2673 {
2674 /* Error will be returned whenever the ThreadX call fails. */
2675 Application->osek_object_creation_error++;
2676 return (0u);
2677 }
2678
2679 return (event);
2680 }
2681
2682
2683 /**************************************************************************/
2684 /* */
2685 /* FUNCTION RELEASE */
2686 /* */
2687 /* SetEvent PORTABLE C */
2688 /* 6.1.7 */
2689 /* AUTHOR */
2690 /* */
2691 /* William E. Lamie, Microsoft Corporation */
2692 /* */
2693 /* DESCRIPTION */
2694 /* */
2695 /* Sets events of the given task according to the event mask. */
2696 /* */
2697 /* INPUT */
2698 /* */
2699 /* task ID ID for the task */
2700 /* mask Mask of the events to be set. */
2701 /* */
2702 /* OUTPUT */
2703 /* */
2704 /* E_OK If successful */
2705 /* E_OS_ID Invalid task or event id */
2706 /* E_OS_STATE Invalid target task state */
2707 /* */
2708 /* CALLS */
2709 /* */
2710 /* tx_event_flags_set Set ThreadX event flag. */
2711 /* osek_internal_error OSEK Internal error */
2712 /* */
2713 /* CALLED BY */
2714 /* */
2715 /* Application Code */
2716 /* */
2717 /* RELEASE HISTORY */
2718 /* */
2719 /* DATE NAME DESCRIPTION */
2720 /* */
2721 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
2722 /* */
2723 /**************************************************************************/
SetEvent(TaskType task_id,EventMaskType mask)2724 StatusType SetEvent(TaskType task_id, EventMaskType mask)
2725 {
2726 TX_INTERRUPT_SAVE_AREA
2727 OSEK_TCB *tcb_ptr;
2728 TX_THREAD *this_thread;
2729 EventMaskType balance_events;
2730 ULONG request[SYSMGR_QUEUE_MSG_LENGTH];
2731 UINT status;
2732 OSEK_TCB *p_this_tcb;
2733
2734
2735 service_GetServiceId.id = (OsServiceIdType)OSServiceId_SetEvent;
2736 service_SetEvent.TaskID = task_id;
2737
2738 /* Check if task id not valid. */
2739 if(task_id == 0u)
2740 {
2741 exec_ErrorHook(E_OS_ID);
2742
2743 /* Return error. */
2744 return (E_OS_ID);
2745 }
2746
2747 /* Get TCB_PTR. */
2748 tcb_ptr = (OSEK_TCB *)task_id;
2749
2750 if (tcb_ptr->osek_task_id != OSEK_TASK_ID)
2751 {
2752 exec_ErrorHook(E_OS_ID);
2753
2754 /* Return error. */
2755 return (E_OS_ID);
2756 }
2757
2758 /* Check if any event is assigned to task. */
2759 if ((tcb_ptr->events == 0u) || (tcb_ptr->task_type == BASIC))
2760 {
2761 exec_ErrorHook(E_OS_ACCESS);
2762
2763 /* No event assigned to task, return error. */
2764 return (E_OS_ACCESS);
2765 }
2766
2767 TX_DISABLE
2768
2769 if (tcb_ptr->suspended == TX_TRUE)
2770 {
2771 TX_RESTORE
2772
2773 exec_ErrorHook(E_OS_STATE);
2774
2775 /* Return error. */
2776 return (E_OS_STATE);
2777 }
2778
2779 /* Check this event mask with the task . */
2780 /* Update the set events for this task with this new mask. */
2781 tcb_ptr->set_events = tcb_ptr->set_events | mask;
2782
2783 /* See how many events are set. */
2784 balance_events = tcb_ptr->set_events & tcb_ptr->waiting_events;
2785
2786 /* Is there any from waiting events. */
2787 if (balance_events != 0u)
2788 {
2789 /* Get calling task's ThreadX thread */
2790 this_thread = tx_thread_identify();
2791
2792 /* Check whether the same running task is setting its own events or
2793 the task is already out of wait state. */
2794 /* if yes then no need to add this task in the ready list and of course no
2795 need to check for any preemption possibilities. */
2796
2797 p_this_tcb = osek_thread2tcb(this_thread);
2798 if ((tcb_ptr != p_this_tcb) && (tcb_ptr->waiting == TX_TRUE))
2799 {
2800 tcb_ptr->waiting = TX_FALSE;
2801 /* Now, send message to the system manager to check any preemption out of SetEvent() call. */
2802
2803 /* Build the request. */
2804 request[0] = SYSMGR_SETEVENT; /* Request type. */
2805 request[1] = (ULONG)this_thread; /* ThreadX Thread for this task. */
2806 request[2] = (ULONG)tcb_ptr; /* id in OSEK_TCB format. */
2807 request[3] = 0u;
2808
2809 /* Since the SysMgr supervisor thread has the highest priority, */
2810 /* this routine will be preempted by SysMgr supervisor thread when */
2811 /* queue is successful. */
2812 /* System Manager will eventually call start_osek_tasks. */
2813
2814 status = tx_queue_send(&osek_work_queue, request, TX_NO_WAIT);
2815
2816 /* This should always succeed. */
2817 if (status != TX_SUCCESS)
2818 {
2819 /* System internal error. */
2820 osek_internal_error(SYS_MGR_SEND_CHAINTASK);
2821
2822 }
2823 }
2824
2825 }
2826
2827 TX_RESTORE
2828
2829 return (E_OK);
2830 }
2831
2832
2833 /**************************************************************************/
2834 /* */
2835 /* FUNCTION RELEASE */
2836 /* */
2837 /* ClearEvent PORTABLE C */
2838 /* 6.1.7 */
2839 /* AUTHOR */
2840 /* */
2841 /* William E. Lamie, Microsoft Corporation */
2842 /* */
2843 /* DESCRIPTION */
2844 /* */
2845 /* Clears events of the calling task according to the event mask. */
2846 /* */
2847 /* INPUT */
2848 /* */
2849 /* mask Mask of the events to be cleared */
2850 /* */
2851 /* OUTPUT */
2852 /* */
2853 /* E_OK If success */
2854 /* ERROR If error occurs while creating task */
2855 /* */
2856 /* CALLS */
2857 /* */
2858 /* tx_event_flags_set Set or clears ThreadX event flag */
2859 /* osek_task_independent_area See if out of task context */
2860 /* tx_thread_identify Identify the current thread */
2861 /* tx_event_flags_set Set the event Flags */
2862 /* osek_internal_error OSEK internal error */
2863 /* */
2864 /* CALLED BY */
2865 /* */
2866 /* Application Code */
2867 /* */
2868 /* RELEASE HISTORY */
2869 /* */
2870 /* DATE NAME DESCRIPTION */
2871 /* */
2872 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
2873 /* */
2874 /**************************************************************************/
ClearEvent(EventMaskType mask)2875 StatusType ClearEvent(EventMaskType mask)
2876 {
2877 TX_INTERRUPT_SAVE_AREA
2878 TX_THREAD *this_thread;
2879 OSEK_TCB *tcb_ptr;
2880 ULONG area;
2881
2882 service_GetServiceId.id = (OsServiceIdType)OSServiceId_ClearEvent;
2883 service_ClearEvent.EventID = mask;
2884 /* Check if we are calling from initialization. */
2885 if (osek_init_state == OSEK_INIT)
2886 {
2887 exec_ErrorHook(E_OS_CALLEVEL);
2888
2889 /* Return error. */
2890 return (E_OS_CALLEVEL);
2891 }
2892
2893 /* Check if we are not at task level. */
2894 area = osek_task_independent_area();
2895 if(area == 0u)
2896 {
2897 exec_ErrorHook(E_OS_CALLEVEL);
2898
2899 /* Return error. */
2900 return (E_OS_CALLEVEL);
2901 }
2902
2903 this_thread = tx_thread_identify();
2904
2905 /* Get OSEK TCB. */
2906 tcb_ptr = (OSEK_TCB *)this_thread;
2907
2908 /* Check if any event is assigned to task. */
2909 if ((tcb_ptr->events == 0u) || (tcb_ptr->task_type == BASIC))
2910 {
2911 exec_ErrorHook(E_OS_ACCESS);
2912
2913 /* No event assigned to task, return error. */
2914 return (E_OS_ACCESS);
2915 }
2916
2917 TX_DISABLE
2918
2919 /* Update the events. */
2920 tcb_ptr->set_events = tcb_ptr->set_events & (~mask);
2921 TX_RESTORE
2922
2923 return (E_OK);
2924 }
2925
2926
2927 /**************************************************************************/
2928 /* */
2929 /* FUNCTION RELEASE */
2930 /* */
2931 /* GetEvent PORTABLE C */
2932 /* 6.1.7 */
2933 /* AUTHOR */
2934 /* */
2935 /* William E. Lamie, Microsoft Corporation */
2936 /* */
2937 /* DESCRIPTION */
2938 /* */
2939 /* Gets the current event setting of the given task. */
2940 /* */
2941 /* INPUT */
2942 /* */
2943 /* task_id ID or the task */
2944 /* mask Mask of the events to be set. */
2945 /* */
2946 /* OUTPUT */
2947 /* */
2948 /* E_OK If successful */
2949 /* ERROR If an error occurs */
2950 /* */
2951 /* CALLS */
2952 /* */
2953 /* osek_internal_error OSEK internal error */
2954 /* */
2955 /* CALLED BY */
2956 /* */
2957 /* Application Code */
2958 /* */
2959 /* RELEASE HISTORY */
2960 /* */
2961 /* DATE NAME DESCRIPTION */
2962 /* */
2963 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
2964 /* */
2965 /**************************************************************************/
GetEvent(TaskType task_id,EventMaskRefType event)2966 StatusType GetEvent(TaskType task_id, EventMaskRefType event)
2967 {
2968 TX_INTERRUPT_SAVE_AREA
2969 OSEK_TCB *tcb_ptr;
2970
2971 service_GetServiceId.id = (OsServiceIdType)OSServiceId_GetEvent;
2972 service_GetEvent.TaskID = task_id;
2973
2974 /* Check if task id is valid. */
2975 if(task_id == 0u)
2976 {
2977 exec_ErrorHook(E_OS_ID);
2978
2979 /* Return error. */
2980 return (E_OS_ID);
2981 }
2982
2983 /* Get the tcb pointer. */
2984 tcb_ptr = (OSEK_TCB *)task_id;
2985
2986 if (tcb_ptr->osek_task_id != OSEK_TASK_ID)
2987 {
2988 exec_ErrorHook(E_OS_ID);
2989
2990 /* Return error. */
2991 return (E_OS_ID);
2992 }
2993
2994 /* Check if any event is assigned to task and task is extended type. */
2995 if ((tcb_ptr->events == 0u) || (tcb_ptr->task_type == BASIC))
2996 {
2997 exec_ErrorHook(E_OS_ACCESS);
2998
2999 /* No event assigned to task, return error. */
3000 return (E_OS_ACCESS);
3001 }
3002
3003 TX_DISABLE
3004
3005 if (tcb_ptr->suspended == TX_TRUE)
3006 {
3007 TX_RESTORE
3008
3009 exec_ErrorHook(E_OS_STATE);
3010
3011 /* Return error. */
3012 return (E_OS_STATE);
3013 }
3014
3015 /* Get the event. */
3016 *event = tcb_ptr->set_events;
3017
3018 TX_RESTORE
3019
3020 return (E_OK);
3021 }
3022
3023
3024 /**************************************************************************/
3025 /* */
3026 /* FUNCTION RELEASE */
3027 /* */
3028 /* WaitEvent PORTABLE C */
3029 /* 6.1.7 */
3030 /* AUTHOR */
3031 /* */
3032 /* William E. Lamie, Microsoft Corporation */
3033 /* */
3034 /* DESCRIPTION */
3035 /* */
3036 /* Transfers the calling task into the waiting state until specified */
3037 /* events are set. */
3038 /* */
3039 /* INPUT */
3040 /* */
3041 /* mask Mask of the events to be set */
3042 /* */
3043 /* OUTPUT */
3044 /* */
3045 /* E_OK If success */
3046 /* ERROR If error occurs while creating task */
3047 /* */
3048 /* CALLS */
3049 /* */
3050 /* tx_event_flags_get Retrieves ThreadX event flag from */
3051 /* specified ThreadX event flag group */
3052 /* osek_internal_error OSEK internal error */
3053 /* tx_thread_identify Identify current thread */
3054 /* */
3055 /* CALLED BY */
3056 /* */
3057 /* Application Code */
3058 /* */
3059 /* RELEASE HISTORY */
3060 /* */
3061 /* DATE NAME DESCRIPTION */
3062 /* */
3063 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
3064 /* */
3065 /**************************************************************************/
WaitEvent(EventMaskType mask)3066 StatusType WaitEvent(EventMaskType mask)
3067 {
3068 TX_INTERRUPT_SAVE_AREA
3069 OSEK_TCB *tcb_ptr;
3070 TX_THREAD *this_thread;
3071 ULONG request[SYSMGR_QUEUE_MSG_LENGTH];
3072 UINT index;
3073 UINT status;
3074
3075
3076 service_GetServiceId.id = (OsServiceIdType)OSServiceId_WaitEvent;
3077 service_WaitEvent.EventID = mask;
3078
3079
3080 /* Check if we are in interrupt. */
3081 if((_tx_thread_current_ptr == TX_NULL) || /* Not in a task. */
3082 (_tx_thread_system_state != 0u)) /* In an ISR. */
3083 {
3084 exec_ErrorHook(E_OS_CALLEVEL);
3085
3086 /* Return error. */
3087 return (E_OS_CALLEVEL);
3088 }
3089
3090 /* Check if the thread is currently executed. */
3091 this_thread = tx_thread_identify();
3092 if(this_thread == TX_NULL)
3093 {
3094 exec_ErrorHook(E_OS_CALLEVEL);
3095
3096 /* Not allowed on the calling thread. */
3097 return (E_OS_CALLEVEL);
3098 }
3099
3100 /* Get OSEK TCB. */
3101 tcb_ptr = (OSEK_TCB *)this_thread;
3102
3103 /* Check if any event is assigned to task or the task is of BASIC type. */
3104 if ((tcb_ptr->events == 0u) || (tcb_ptr->task_type == BASIC))
3105 {
3106 exec_ErrorHook(E_OS_ACCESS);
3107
3108 /* No event assigned to task, return error. */
3109 return (E_OS_ACCESS);
3110 }
3111
3112 /* Check if any resource is occupied by this task. */
3113 if(tcb_ptr->res_ocp != 0u)
3114 {
3115 exec_ErrorHook(E_OS_RESOURCE);
3116
3117 /* Return error. */
3118 return (E_OS_RESOURCE);
3119 }
3120
3121 TX_DISABLE
3122
3123 tcb_ptr->waiting_events = mask;
3124
3125 /* Is any event set? */
3126 if ((tcb_ptr->set_events & tcb_ptr->waiting_events) != 0u)
3127 {
3128 TX_RESTORE
3129
3130 return (E_OK);
3131 }
3132 else
3133 {
3134 /* Events are not set wait for them. */
3135 tcb_ptr->waiting = TX_TRUE;
3136 }
3137
3138 /* Release any internal resources held. */
3139 if (tcb_ptr->internal_res != 0u)
3140 {
3141 for (index = 0u; index < OSEK_MAX_INTERNAL_RES; index++)
3142 {
3143 if (tcb_ptr->internal_resource_occuplied_list[index] == 0u)
3144 {
3145 break;
3146 }
3147
3148 ((OSEK_RESOURCE *)(tcb_ptr->internal_resource_occuplied_list[index]))->taskid = 0u;
3149 tcb_ptr->internal_resource_occuplied_list[index] = 0u;
3150
3151 }
3152 }
3153
3154 /* Now, send message to system thread to check any preemption out of the WaitEvent() call. */
3155
3156 /* Build the request. */
3157 request[0] = SYSMGR_WAITEVENT; /* Request type. */
3158 request[1] = (ULONG)this_thread; /* Self ID. */
3159 request[2] = (ULONG)tcb_ptr; /* Self Id in OSEK_TCB format. */
3160 request[3] = 0u;
3161 /* Now send a message to the SysMgr supervisor thread and ask */
3162 /* to check any preemption is possible. */
3163 /* Since the SysMgr supervisor thread has the highest priority, */
3164 /* this routine will be preempted by SysMgr supervisor thread when */
3165 /* queue is successful. */
3166 /* System Manager will eventually call start_osek_tasks. */
3167
3168 status = tx_queue_send(&osek_work_queue, request, TX_NO_WAIT);
3169
3170 TX_RESTORE
3171
3172 /* This should always succeed. */
3173 if (status != TX_SUCCESS)
3174 {
3175 /* System internal error. */
3176 osek_internal_error(SYS_MGR_SEND_CHAINTASK);
3177 }
3178
3179 return (E_OK);
3180 }
3181
3182
3183 /**************************************************************************/
3184 /* */
3185 /* FUNCTION RELEASE */
3186 /* */
3187 /* RegisterEventtoTask PORTABLE C */
3188 /* 6.1.7 */
3189 /* AUTHOR */
3190 /* */
3191 /* William E. Lamie, Microsoft Corporation */
3192 /* */
3193 /* DESCRIPTION */
3194 /* */
3195 /* This function registers an event to the task specified, provided */
3196 /* a free entry is available in the task's list of events. */
3197 /* */
3198 /* INPUT */
3199 /* */
3200 /* event_id Id of the event */
3201 /* TaskID Id of the task */
3202 /* */
3203 /* OUTPUT */
3204 /* */
3205 /* E_OK If successful */
3206 /* E_OS_NOFUNC No free entries */
3207 /* E_OS_ID Invalid task or resource id. */
3208 /* not occupied by any task or ISR, or */
3209 /* another resource has to be released */
3210 /* before. */
3211 /* E_OS_ACCESS Attempt to release an invalid resource */
3212 /* */
3213 /* CALLS */
3214 /* */
3215 /* None */
3216 /* */
3217 /* CALLED BY */
3218 /* */
3219 /* Application Code (System Creation section) */
3220 /* */
3221 /* RELEASE HISTORY */
3222 /* */
3223 /* DATE NAME DESCRIPTION */
3224 /* */
3225 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
3226 /* */
3227 /**************************************************************************/
RegisterEventtoTask(EventMaskType eventid,TaskType TaskID)3228 StatusType RegisterEventtoTask(EventMaskType eventid, TaskType TaskID)
3229 {
3230
3231 OSEK_TCB *tcb_ptr;
3232
3233 /* Check if we are in initialization. */
3234 /* This will ensure that no one calls this function after system is started. */
3235 if (osek_init_state != OSEK_INIT)
3236 {
3237 /* Return OSEK internal error. This is not a standard OSEK error. */
3238 Application->osek_object_creation_error++;
3239 return ((StatusType)TX_NULL);
3240 }
3241
3242 /* Check if task id is valid. */
3243 if(TaskID == 0u)
3244 {
3245
3246 /* Return error. */
3247 Application->osek_object_creation_error++;
3248
3249 return (E_OS_ID);
3250 }
3251
3252
3253
3254 /* Convert object IDs to object control block pointers. */
3255 tcb_ptr = (OSEK_TCB*)TaskID;
3256
3257
3258 /* Check for valid task pointer. */
3259 if (tcb_ptr == TX_NULL)
3260 {
3261 Application->osek_object_creation_error++;
3262
3263 return (E_OS_ID);
3264 }
3265
3266 if(tcb_ptr->osek_task_id != OSEK_TASK_ID)
3267 {
3268 Application->osek_object_creation_error++;
3269
3270 return (E_OS_ID);
3271 }
3272
3273 /* This task is to be registered with this event. */
3274 tcb_ptr->events = tcb_ptr->events | eventid;
3275
3276
3277 return (E_OK);
3278 }
3279
3280
3281 /**************************************************************************/
3282 /* */
3283 /* FUNCTION RELEASE */
3284 /* */
3285 /* EnableInterrupt PORTABLE C */
3286 /* 6.1.7 */
3287 /* AUTHOR */
3288 /* */
3289 /* William E. Lamie, Microsoft Corporation */
3290 /* */
3291 /* DESCRIPTION */
3292 /* */
3293 /* This service enables interrupts. */
3294 /* */
3295 /* OUTPUT */
3296 /* */
3297 /* E_OK If successful */
3298 /* */
3299 /* CALLED BY */
3300 /* */
3301 /* Application Code */
3302 /* */
3303 /* RELEASE HISTORY */
3304 /* */
3305 /* DATE NAME DESCRIPTION */
3306 /* */
3307 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
3308 /* */
3309 /**************************************************************************/
EnableInterrupt(void)3310 StatusType EnableInterrupt(void)
3311 {
3312 TX_INTERRUPT_SAVE_AREA
3313
3314 TX_DISABLE
3315
3316 if (disable_ISR2 != 0u) {
3317 disable_ISR2--;
3318 }
3319
3320 TX_RESTORE
3321
3322 return (E_OK);
3323 }
3324
3325
3326 /**************************************************************************/
3327 /* */
3328 /* FUNCTION RELEASE */
3329 /* */
3330 /* DisableInterrupt PORTABLE C */
3331 /* 6.1.7 */
3332 /* AUTHOR */
3333 /* */
3334 /* William E. Lamie, Microsoft Corporation */
3335 /* */
3336 /* DESCRIPTION */
3337 /* */
3338 /* This service disables interrupts. */
3339 /* */
3340 /* OUTPUT */
3341 /* */
3342 /* E_OK If successful */
3343 /* */
3344 /* CALLED BY */
3345 /* */
3346 /* Application Code */
3347 /* */
3348 /* RELEASE HISTORY */
3349 /* */
3350 /* DATE NAME DESCRIPTION */
3351 /* */
3352 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
3353 /* */
3354 /**************************************************************************/
DisableInterrupt(void)3355 StatusType DisableInterrupt(void)
3356 {
3357 TX_INTERRUPT_SAVE_AREA
3358
3359 TX_DISABLE
3360
3361 disable_ISR2++;
3362
3363 TX_RESTORE
3364
3365 return (E_OK);
3366 }
3367
3368
3369 /**************************************************************************/
3370 /* */
3371 /* FUNCTION RELEASE */
3372 /* */
3373 /* GetInterruptDescriptor PORTABLE C */
3374 /* 6.1.7 */
3375 /* AUTHOR */
3376 /* */
3377 /* William E. Lamie, Microsoft Corporation */
3378 /* */
3379 /* DESCRIPTION */
3380 /* */
3381 /* Query of interrupt status and returns the current CPU interrupt */
3382 /* mask */
3383 /* */
3384 /* INPUT */
3385 /* */
3386 /* mask A reference to the interrupt mask to be */
3387 /* filled. In the mask, a "1" means (Group */
3388 /* of) Interrupt is enabled. */
3389 /* */
3390 /* OUTPUT */
3391 /* */
3392 /* E_OK If success */
3393 /* ERROR If error occurs while creating task */
3394 /* */
3395 /* CALLS */
3396 /* */
3397 /* tx_interrupt_control Enables or disables interrupts */
3398 /* specified by new_posture */
3399 /* */
3400 /* CALLED BY */
3401 /* */
3402 /* Application Code */
3403 /* */
3404 /* RELEASE HISTORY */
3405 /* */
3406 /* DATE NAME DESCRIPTION */
3407 /* */
3408 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
3409 /* */
3410 /**************************************************************************/
GetInterruptDescriptor(UINT * mask)3411 StatusType GetInterruptDescriptor(UINT *mask)
3412 {
3413 UINT old_posture;
3414 UINT new_posture;
3415
3416 /* Get the old posture of the interrupt. */
3417 old_posture = tx_interrupt_control(TX_INT_DISABLE);
3418
3419 new_posture = old_posture;
3420
3421 /* Invert the mask for OSEK interrupt. */
3422 *mask = ~old_posture ;
3423
3424 /* Restore the same interrupts. */
3425 tx_interrupt_control(new_posture);
3426
3427 return (E_OK);
3428 }
3429
3430
3431 /**************************************************************************/
3432 /* */
3433 /* FUNCTION RELEASE */
3434 /* */
3435 /* SuspendAllInterrupts PORTABLE C */
3436 /* 6.1.7 */
3437 /* AUTHOR */
3438 /* */
3439 /* William E. Lamie, Microsoft Corporation */
3440 /* */
3441 /* DESCRIPTION */
3442 /* */
3443 /* This call serves to enter critical sections by disabling all */
3444 /* interrupts. */
3445 /* */
3446 /* OUTPUT */
3447 /* */
3448 /* E_OK If successful */
3449 /* */
3450 /* CALLED BY */
3451 /* */
3452 /* Application Code */
3453 /* */
3454 /* RELEASE HISTORY */
3455 /* */
3456 /* DATE NAME DESCRIPTION */
3457 /* */
3458 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
3459 /* */
3460 /**************************************************************************/
SuspendAllInterrupts(void)3461 void SuspendAllInterrupts (void)
3462 {
3463 TX_INTERRUPT_SAVE_AREA
3464
3465 TX_DISABLE
3466 suspend_ISR2++;
3467 TX_RESTORE
3468 }
3469
3470 /**************************************************************************/
3471 /* */
3472 /* FUNCTION RELEASE */
3473 /* */
3474 /* ResumeAllInterrupts PORTABLE C */
3475 /* 6.1.7 */
3476 /* AUTHOR */
3477 /* */
3478 /* William E. Lamie, Microsoft Corporation */
3479 /* */
3480 /* DESCRIPTION */
3481 /* */
3482 /* Exits a critical section entered by calling SuspendAllInterrupts. */
3483 /* */
3484 /* OUTPUT */
3485 /* */
3486 /* E_OK If successful */
3487 /* */
3488 /* CALLS */
3489 /* */
3490 /* osek_task_independent_area See if called from task independent */
3491 /* area */
3492 /* tx_thread_identify Identify the current thread */
3493 /* osek_internal_error Osek internal error */
3494 /* */
3495 /* CALLED BY */
3496 /* */
3497 /* Application Code */
3498 /* */
3499 /* RELEASE HISTORY */
3500 /* */
3501 /* DATE NAME DESCRIPTION */
3502 /* */
3503 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
3504 /* */
3505 /**************************************************************************/
ResumeAllInterrupts(void)3506 void ResumeAllInterrupts (void)
3507 {
3508 TX_INTERRUPT_SAVE_AREA
3509 TX_THREAD *thread_ptr;
3510 UINT status;
3511 ULONG request[SYSMGR_QUEUE_MSG_LENGTH];
3512
3513 TX_DISABLE
3514 if (suspend_ISR2 != 0u)
3515 {
3516 suspend_ISR2--;
3517 }
3518
3519 if (suspend_ISR2 == 0u)
3520 {
3521 /* Interrupts resume, check if any pending. */
3522 /* get the pointer to the calling thread. */
3523 thread_ptr = tx_thread_identify();
3524
3525 /* Now send a message to the SysMgr supervisor thread to execute the error hook. */
3526 /* Build the request. */
3527 request[0] = SYSMGR_ERRORHOOK; /* Request type. */
3528 request[1] = (ULONG)thread_ptr; /* Ptr of calling thread. */
3529 request[2] = 0u; /* Input to Error hook. */
3530 request[3] = 0u;
3531
3532 /* Since the SysMgr supervisor thread is has the highest priority, */
3533 /* this routine will be preempted by SysMgr supervisor thread when */
3534 /* queue read is successful. */
3535
3536 status = tx_queue_send(&osek_work_queue, request, TX_NO_WAIT);
3537
3538 /* This should always succeed. */
3539 if (status != TX_SUCCESS)
3540 {
3541 TX_RESTORE
3542
3543 /* System internal error. */
3544 osek_internal_error(SYS_MGR_SEND_CHAINTASK);
3545
3546 /* Return. */
3547 return;
3548 }
3549
3550 } /* end if (!suspend_ISR2). */
3551
3552 TX_RESTORE
3553
3554 return;
3555 }
3556
3557
3558 /**************************************************************************/
3559 /* */
3560 /* FUNCTION RELEASE */
3561 /* */
3562 /* DisableAllInterrupts PORTABLE C */
3563 /* 6.1.7 */
3564 /* AUTHOR */
3565 /* */
3566 /* William E. Lamie, Microsoft Corporation */
3567 /* */
3568 /* DESCRIPTION */
3569 /* */
3570 /* This call serves to enter critical sections by disabling all */
3571 /* interrupts. */
3572 /* */
3573 /* CALLED BY */
3574 /* */
3575 /* Application Code */
3576 /* */
3577 /* RELEASE HISTORY */
3578 /* */
3579 /* DATE NAME DESCRIPTION */
3580 /* */
3581 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
3582 /* */
3583 /**************************************************************************/
DisableAllInterrupts(void)3584 void DisableAllInterrupts (void)
3585 {
3586 TX_INTERRUPT_SAVE_AREA
3587
3588 TX_DISABLE
3589 disable_ISR2++;
3590 TX_RESTORE
3591 }
3592
3593 /**************************************************************************/
3594 /* */
3595 /* FUNCTION RELEASE */
3596 /* */
3597 /* EnableAllInterrupts PORTABLE C */
3598 /* 6.1.7 */
3599 /* AUTHOR */
3600 /* */
3601 /* William E. Lamie, Microsoft Corporation */
3602 /* */
3603 /* DESCRIPTION */
3604 /* */
3605 /* Exits a critical section entered by calling DisableAllInterrupts. */
3606 /* */
3607 /* CALLED BY */
3608 /* */
3609 /* Application Code */
3610 /* */
3611 /* RELEASE HISTORY */
3612 /* */
3613 /* DATE NAME DESCRIPTION */
3614 /* */
3615 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
3616 /* */
3617 /**************************************************************************/
EnableAllInterrupts(void)3618 void EnableAllInterrupts (void)
3619 {
3620 TX_INTERRUPT_SAVE_AREA
3621
3622 TX_DISABLE
3623 if (disable_ISR2 != 0u)
3624 {
3625 disable_ISR2--;
3626 }
3627 TX_RESTORE
3628 }
3629
3630
3631 /**************************************************************************/
3632 /* */
3633 /* FUNCTION RELEASE */
3634 /* */
3635 /* SuspendOSInterrupts PORTABLE C */
3636 /* 6.1.7 */
3637 /* AUTHOR */
3638 /* */
3639 /* William E. Lamie, Microsoft Corporation */
3640 /* */
3641 /* DESCRIPTION */
3642 /* */
3643 /* This call serves to enter critical sections by disabling all */
3644 /* interrupts. */
3645 /* */
3646 /* CALLED BY */
3647 /* */
3648 /* Application Code */
3649 /* */
3650 /* RELEASE HISTORY */
3651 /* */
3652 /* DATE NAME DESCRIPTION */
3653 /* */
3654 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
3655 /* */
3656 /**************************************************************************/
SuspendOSInterrupts(void)3657 void SuspendOSInterrupts (void)
3658 {
3659 TX_INTERRUPT_SAVE_AREA
3660
3661 TX_DISABLE
3662 suspend_ISR2++;
3663 TX_RESTORE
3664 }
3665
3666 /**************************************************************************/
3667 /* */
3668 /* FUNCTION RELEASE */
3669 /* */
3670 /* ResumeOSInterrupts PORTABLE C */
3671 /* 6.1.7 */
3672 /* AUTHOR */
3673 /* */
3674 /* William E. Lamie, Microsoft Corporation */
3675 /* */
3676 /* DESCRIPTION */
3677 /* */
3678 /* Exits a critical section entered by calling SuspendOSInterrupts. */
3679 /* */
3680 /* CALLS */
3681 /* */
3682 /* osek_task_independent_area See if called from task independent */
3683 /* area */
3684 /* tx_thread_identify Identify the current thread */
3685 /* osek_internal_error OSEK internal error */
3686 /* */
3687 /* CALLED BY */
3688 /* */
3689 /* Application Code */
3690 /* */
3691 /* RELEASE HISTORY */
3692 /* */
3693 /* DATE NAME DESCRIPTION */
3694 /* */
3695 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
3696 /* */
3697 /**************************************************************************/
ResumeOSInterrupts(void)3698 void ResumeOSInterrupts (void)
3699 {
3700 TX_INTERRUPT_SAVE_AREA
3701 TX_THREAD *thread_ptr;
3702 UINT status;
3703 ULONG request[SYSMGR_QUEUE_MSG_LENGTH];
3704
3705 TX_DISABLE
3706
3707 if (suspend_ISR2 != 0u)
3708 {
3709 suspend_ISR2--;
3710 }
3711
3712 if (suspend_ISR2 == 0u)
3713 {
3714 /* Interrupts resume, check if any pending. */
3715 /* get the pointer to the calling thread. */
3716 thread_ptr = tx_thread_identify();
3717
3718 /* Now send a message to the SysMgr supervisor thread to execute the error hook */
3719 /* Build the request. */
3720 request[0] = SYSMGR_ERRORHOOK; /* Request type. */
3721 request[1] = (ULONG)thread_ptr; /* Pointer of calling thread. */
3722 request[2] = 0u; /* Input to Error hook. */
3723 request[3] = 0u;
3724
3725 /* Since the SysMgr supervisor thread is with the highest priority, */
3726 /* this routine will be preempted by SysMgr supervisor thread when */
3727 /* queue read is successful. */
3728
3729 status = tx_queue_send(&osek_work_queue, request, TX_NO_WAIT);
3730
3731 /* This should always succeed. */
3732 if (status != TX_SUCCESS)
3733 {
3734 TX_RESTORE
3735
3736 /* System internal error. */
3737 osek_internal_error(SYS_MGR_SEND_CHAINTASK);
3738
3739 /* Return. */
3740 return;
3741 }
3742
3743 } /* end if (!suspend_ISR2). */
3744
3745 TX_RESTORE
3746
3747 return;
3748 }
3749
3750
3751 /**************************************************************************/
3752 /* */
3753 /* FUNCTION RELEASE */
3754 /* */
3755 /* GetActiveApplicationMode PORTABLE C */
3756 /* 6.1.7 */
3757 /* AUTHOR */
3758 /* */
3759 /* William E. Lamie, Microsoft Corporation */
3760 /* */
3761 /* DESCRIPTION */
3762 /* */
3763 /* This call returns the current application mode. */
3764 /* */
3765 /* */
3766 /* OUTPUT */
3767 /* */
3768 /* Current application mode */
3769 /* */
3770 /* CALLED BY */
3771 /* */
3772 /* Application Code */
3773 /* */
3774 /* RELEASE HISTORY */
3775 /* */
3776 /* DATE NAME DESCRIPTION */
3777 /* */
3778 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
3779 /* */
3780 /**************************************************************************/
GetActiveApplicationMode(void)3781 AppModeType GetActiveApplicationMode(void)
3782 {
3783 return (Application->application_mode);
3784 }
3785
3786
3787 /**************************************************************************/
3788 /* */
3789 /* FUNCTION RELEASE */
3790 /* */
3791 /* GetCounterValue PORTABLE C */
3792 /* 6.1.7 */
3793 /* AUTHOR */
3794 /* */
3795 /* William E. Lamie, Microsoft Corporation */
3796 /* */
3797 /* DESCRIPTION */
3798 /* */
3799 /* Returns the current value of a counter. */
3800 /* */
3801 /* INPUT */
3802 /* */
3803 /* counter_ptr Pointer to OSEK Counter */
3804 /* tick_ptr Pointer to ticks */
3805 /* */
3806 /* OUTPUT */
3807 /* */
3808 /* E_OK If successful */
3809 /* E_OS_ID Invalid counter object */
3810 /* */
3811 /* CALLS */
3812 /* */
3813 /* None */
3814 /* */
3815 /* CALLED BY */
3816 /* */
3817 /* Application Code */
3818 /* */
3819 /* RELEASE HISTORY */
3820 /* */
3821 /* DATE NAME DESCRIPTION */
3822 /* */
3823 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
3824 /* */
3825 /**************************************************************************/
GetCounterValue(OSEK_COUNTER * counter_ptr,TickRefType tick_ptr)3826 StatusType GetCounterValue(OSEK_COUNTER *counter_ptr, TickRefType tick_ptr)
3827 {
3828
3829 /* Check for valid counter. */
3830 if ((counter_ptr != TX_NULL) && (counter_ptr->osek_counter_id == OSEK_COUNTER_ID))
3831 {
3832 *tick_ptr = counter_ptr->counter_value;
3833 }
3834 else
3835 {
3836 /* There is error in counter object supplied. */
3837 return (E_OS_ID);
3838 }
3839
3840 return (E_OK);
3841 }
3842
3843
3844 /**************************************************************************/
3845 /* */
3846 /* FUNCTION RELEASE */
3847 /* */
3848 /* CreateCounter PORTABLE C */
3849 /* 6.1.7 */
3850 /* AUTHOR */
3851 /* */
3852 /* William E. Lamie, Microsoft Corporation */
3853 /* */
3854 /* DESCRIPTION */
3855 /* */
3856 /* Creates a counter. */
3857 /* */
3858 /* INPUT */
3859 /* */
3860 /* N/A */
3861 /* */
3862 /* OUTPUT */
3863 /* */
3864 /* COUNTER_ID Reference to counter */
3865 /* */
3866 /* CALLS */
3867 /* */
3868 /* osek_memory_allocate Allocate memory from system */
3869 /* osek_counter_name_check Check if counter name duplicate */
3870 /* osek_get_counter Get pointer to counter structure */
3871 /* */
3872 /* CALLED BY */
3873 /* */
3874 /* Application Code */
3875 /* */
3876 /* RELEASE HISTORY */
3877 /* */
3878 /* DATE NAME DESCRIPTION */
3879 /* */
3880 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
3881 /* */
3882 /**************************************************************************/
CreateCounter(const CHAR * name,TickType max_allowed_value,TickType ticks_per_base,TickType min_cycle,TickType start_value)3883 CounterType CreateCounter(const CHAR *name, TickType max_allowed_value, TickType ticks_per_base,
3884 TickType min_cycle, TickType start_value)
3885 {
3886
3887 CounterType cntr_id;
3888 OSEK_COUNTER *cntr_ptr;
3889 UINT index;
3890
3891 /* Check if we are in initialization. */
3892 /* This will ensure that no one calls this function after system is started. */
3893 if (osek_init_state != OSEK_INIT)
3894 {
3895 /* Return OSEK internal error. This is not a standard OSEK error. */
3896 Application->osek_object_creation_error++;
3897
3898 return((TaskType)TX_NULL);
3899 }
3900
3901 /* Check if there is space for this counter. */
3902 cntr_id = osek_get_counter();
3903 if (cntr_id == 0u)
3904 {
3905 /* Return error. */
3906 Application->osek_object_creation_error++;
3907
3908 return ((CounterType) TX_NULL);
3909 }
3910
3911 /* Get the pointer to counter structure. */
3912 cntr_ptr = (OSEK_COUNTER *)cntr_id;
3913
3914
3915 if (max_allowed_value > MAXALLOWEDVALUE)
3916 {
3917 /* Return OSEK internal error. This is not a standard OSEK error. */
3918 Application->osek_object_creation_error++;
3919
3920 return ((TaskType)TX_NULL);
3921 }
3922
3923 /* Store maximum value of this counter. */
3924 cntr_ptr->maxallowedvalue = max_allowed_value;
3925
3926 if (min_cycle > MAXALLOWEDVALUE)
3927 {
3928 /* Return OSEK internal error. This is not a standard OSEK error. */
3929 Application->osek_object_creation_error++;
3930
3931 return ((TaskType)TX_NULL);
3932 }
3933
3934 /* Store minimum allowed number of ticks of the counter. */
3935 cntr_ptr->mincycle = min_cycle;
3936
3937 if (ticks_per_base > MAXALLOWEDVALUE)
3938 {
3939 /* Return OSEK internal error. This is not a standard OSEK error. */
3940 Application->osek_object_creation_error++;
3941
3942 return ((TaskType)TX_NULL);
3943 }
3944
3945 /* Store ticksperbase. */
3946 cntr_ptr->ticksperbase = ticks_per_base;
3947
3948 /* Store start up value. */
3949 if (start_value > max_allowed_value)
3950 {
3951 cntr_ptr->counter_value = start_value;
3952 }
3953 else
3954 {
3955 cntr_ptr->counter_value = 0u;
3956 }
3957
3958 /* Store object identifier. */
3959 cntr_ptr->osek_counter_id = OSEK_COUNTER_ID;
3960
3961 /* Now initialize the list of alarms attached to this counter. */
3962
3963 for (index = 0u; index < OSEK_MAX_ALARMS; index++)
3964 {
3965 cntr_ptr-> alarm_list[ index ] = 0u;
3966 }
3967
3968 cntr_ptr->cntr_in_use = TX_TRUE;
3969
3970 cntr_ptr->name = name;
3971
3972 /* Return the created counter. */
3973 return ((CounterType) cntr_ptr);
3974 }
3975
3976
3977 /**************************************************************************/
3978 /* */
3979 /* FUNCTION RELEASE */
3980 /* */
3981 /* IncrCouner PORTABLE C */
3982 /* 6.1.7 */
3983 /* AUTHOR */
3984 /* */
3985 /* William E. Lamie, Microsoft Corporation */
3986 /* */
3987 /* DESCRIPTION */
3988 /* */
3989 /* This function increments the specified counter, checks its new */
3990 /* value with all alarms attached to it and triggers expired alarms. */
3991 /* If an alarm is expired then its actions are executed from here. */
3992 /* */
3993 /* INPUT */
3994 /* */
3995 /* Counter Counter to update */
3996 /* */
3997 /* OUTPUT */
3998 /* */
3999 /* E_OK If successful */
4000 /* E_OS_ID If counter id is not correct */
4001 /* E_OS_NOFUNC In case of any errors */
4002 /* */
4003 /* CALLS */
4004 /* */
4005 /* osek_internal_error OSEK internal error */
4006 /* */
4007 /* CALLED BY */
4008 /* */
4009 /* Application Code */
4010 /* */
4011 /* RELEASE HISTORY */
4012 /* */
4013 /* DATE NAME DESCRIPTION */
4014 /* */
4015 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
4016 /* */
4017 /**************************************************************************/
IncrCounter(CounterType cntr)4018 StatusType IncrCounter(CounterType cntr)
4019 {
4020
4021 TX_INTERRUPT_SAVE_AREA
4022
4023 OSEK_COUNTER *cntr_ptr;
4024 UINT index;
4025 UINT msg_cnt;
4026 UINT save_op_mode;
4027 AlarmType alarmid;
4028 OSEK_ALARM *this_alarm;
4029 UINT this_action;
4030 UINT alarm_fired;
4031 UINT status;
4032 OSEK_TCB *tcb_ptr;
4033 ULONG request[SYSMGR_QUEUE_MSG_LENGTH];
4034 EventMaskType balance_events;
4035
4036 cntr_ptr = (OSEK_COUNTER *)cntr;
4037
4038 /* Check for valid counter. */
4039 if ((cntr_ptr == TX_NULL) && (cntr_ptr->osek_counter_id != OSEK_COUNTER_ID))
4040 {
4041 /* There is error in counter object supplied. */
4042 return (E_OS_ID);
4043 }
4044
4045 /* Disable interrupt. */
4046 TX_DISABLE
4047
4048 if (cntr_ptr->cntr_in_use == TX_FALSE)
4049 {
4050 TX_RESTORE
4051
4052 return (E_OS_ID);
4053 }
4054
4055 if (cntr_ptr->ticksperbase == 0u)
4056 {
4057 TX_RESTORE
4058
4059 return (E_OS_NOFUNC);
4060 }
4061
4062
4063 /* Increment counters sub count and check it with tick_pre-Base. */
4064 cntr_ptr->sub_count++;
4065 if (cntr_ptr->sub_count < cntr_ptr->ticksperbase)
4066 {
4067 /* Still need to count enough to reach tics-per-base, no need to increment
4068 main count. */
4069 TX_RESTORE
4070
4071 return (E_OK);
4072 }
4073
4074 /* Reached to tick-per-base, reset it and increment main count. */
4075 cntr_ptr->sub_count = 0u;
4076
4077 /* Now increment the counter value. */
4078 if ( cntr_ptr->counter_value >= cntr_ptr->maxallowedvalue)
4079 {
4080 cntr_ptr->counter_value = 0u;
4081 }
4082 else
4083 {
4084 (cntr_ptr->counter_value)++;
4085 }
4086
4087 /* Now check if counter is rolled back to zero. */
4088 if ( cntr_ptr->counter_value == 0u)
4089 {
4090 /* Counter is rolled back set flags in all Alarms attached to this counter. */
4091 for (index = 0u; index < OSEK_MAX_ALARMS; index++)
4092 {
4093 alarmid = cntr_ptr->alarm_list[index];
4094 if (alarmid == 0u)
4095 {
4096 continue;
4097 }
4098
4099 /* Something is defined. */
4100 this_alarm = (OSEK_ALARM *)alarmid;
4101
4102 /* But is it a valid OSEK ALARM? */
4103 if((this_alarm == TX_NULL) || (this_alarm->osek_alarm_id != OSEK_ALARM_ID))
4104 {
4105 continue;
4106 }
4107
4108 /* Yes this is a valid alarm , but is it armed? */
4109 if ( this_alarm->armed == TX_FALSE)
4110 {
4111 continue;
4112 }
4113 /* This is an ALARM and is armed, set its rollback flag. */
4114 /* This flag will be cleared when an alarm is armed again or expired. */
4115 this_alarm->counter_rollback = TX_TRUE;
4116 }
4117 }
4118
4119 /* Reset a count of messages sent to the system manager. */
4120 msg_cnt = 0u;
4121
4122 /* Now it is time to check all alarms for expiration. */
4123 for (index = 0u; index < OSEK_MAX_ALARMS; index++)
4124 {
4125
4126 alarm_fired = TX_FALSE;
4127
4128 /* Get the alarm id. */
4129 alarmid = cntr_ptr->alarm_list[index];
4130 if (alarmid == 0u)
4131 {
4132 continue; /* This alarm is not for me, go to check next alarm. */
4133 }
4134
4135 /* Something is defined, try to get the AlarmID. */
4136 this_alarm = (OSEK_ALARM *)alarmid;
4137
4138 /* But is it a valid OSEK ALARM? */
4139 if((this_alarm == TX_NULL) || (this_alarm->osek_alarm_id != OSEK_ALARM_ID))
4140 {
4141 continue;
4142 }
4143
4144 /* Yes this is a valid alarm , but is it armed? */
4145 if (this_alarm->armed == TX_FALSE) /* This alarm is not armed, go to check next alarm. */
4146 {
4147 continue;
4148 }
4149
4150 /* Now check this with counter's current value, if it is less than it do not fire alarm. */
4151 if (this_alarm->rel_abs_mode == RELATIVE_ALARM)
4152 {
4153 /* It is a REALTIVE ALARM. */
4154 if (cntr_ptr->counter_value < this_alarm->expiration_count)
4155 {
4156 continue; /* Not yet expired. */
4157 }
4158 else
4159 {
4160 /* Alarm expired, set flag. */
4161 alarm_fired = TX_TRUE;
4162 }
4163 } /* End It is a REALTIVE ALARM. */
4164 else
4165 {
4166 /* It is ABSOLUTE ALARM. */
4167 if (cntr_ptr->counter_value < this_alarm->expiration_count)
4168 {
4169 /* counter is less than expiration. */
4170 continue; /* Not yet expired. */
4171 }
4172
4173 if (cntr_ptr->counter_value == this_alarm->expiration_count)
4174 {
4175 /* If both are equal alarm is fired. */
4176 alarm_fired = TX_TRUE;
4177 }
4178 else
4179 {
4180 /* count > expiration alarm to fire only if roll back occurred. */
4181 /* This check is required, because when an Alarm is started in ABS mode, counter's current value could
4182 be more than the alarm's expiration count, so that may fire an Alarm the moment it is Armed,
4183 in fact, under such condition (counter's current value more than
4184 the alarm's expiration count, at the time of arming the alarm) the alarm will expires only when , the
4185 counter counts to its max value then rolls back to zero then again counts up and now when it
4186 reaches the alarm's expiration count, the alarm gets fired. */
4187
4188 if (this_alarm->counter_rollback == TX_FALSE)
4189 {
4190 continue;
4191 }
4192 else
4193 {
4194 alarm_fired = TX_TRUE;
4195 }
4196
4197 }
4198
4199 } /* END: else { ABSOLUTE ALARM .. */
4200
4201
4202 /* STILL IN for ( index = 0; index < OSEK_MAX_ALARMS; index++) LOOP. */
4203
4204 /* Check alarm has fired? */
4205
4206 if (alarm_fired == TX_FALSE)
4207 {
4208 continue;
4209 }
4210
4211 /* Reached here means an alarm has fired. */
4212 /* Clear the counter roll back flag. */
4213 this_alarm->counter_rollback = TX_FALSE;
4214
4215 /* Dis arm the Alarm */
4216 this_alarm->armed = TX_FALSE;
4217
4218 /* But is it cyclic? */
4219 if (this_alarm->cycle != 0u)
4220 {
4221 /* Yes, then load new expiration count. */
4222 this_alarm->expiration_count += this_alarm->cycle;
4223 /* Arm the alarm for next cycle. */
4224 this_alarm->armed = TX_TRUE;
4225 }
4226
4227 /* Get what action to be taken for this alarm. */
4228 this_action = this_alarm->action;
4229
4230 /* Check for action to be taken. */
4231 switch(this_action)
4232 {
4233 case CALLBACK:
4234
4235 /* Call a call-back function. */
4236 if (this_alarm->alarm_callback != TX_NULL)
4237 {
4238 save_op_mode = osek_wrapper_operation_mode;
4239 osek_wrapper_operation_mode = ALARM_CALLBACK_MODE;
4240 (this_alarm->alarm_callback)();
4241 osek_wrapper_operation_mode = save_op_mode;
4242 }
4243 break;
4244
4245 case ACTIVATETASK:
4246 /* Activate a task. */
4247 /* Get the OSEK TCB for the task to be activated. */
4248 tcb_ptr = (OSEK_TCB *)(this_alarm->task);
4249
4250 /* Check for any invalid thread pointer. */
4251 if((tcb_ptr == TX_NULL) || ((tcb_ptr->task.tx_thread_id) != TX_THREAD_ID))
4252 {
4253 break;
4254 }
4255
4256 /* Check whether the task is activated up to its defined multiple activations. */
4257 if(tcb_ptr->current_active >= tcb_ptr->max_active)
4258 {
4259 break;
4260 }
4261
4262 /* Now send a message to the System Manager thread to activate this task. */
4263 /* Build the request. */
4264 request[0] = SYSMGR_ACTIVATE_TASK; /* Request type. */
4265 request[1] = (ULONG)tcb_ptr; /* task to Activate. */
4266 request[2] = last_run_task; /* task currently executing. */
4267 request[3] = 0u;
4268 status = tx_queue_send (&osek_work_queue, request, TX_NO_WAIT);
4269
4270 /* This should always succeed. */
4271 if (status != TX_SUCCESS)
4272 {
4273 /* System internal error. */
4274 osek_internal_error(SYS_MGR_SEND_ACTIVATETASK);
4275 }
4276
4277 /* One message sent, increment the msg counter, this is required because
4278 the System manager message queue can hold only certain number of messages. */
4279 msg_cnt++;
4280 break;
4281
4282 case SETEVENT:
4283 /* Set the specified events for the specified task. */
4284 /* Check if task id not valid. */
4285 if (this_alarm->task == TX_NULL)
4286 {
4287 break;
4288 }
4289
4290 /* Get TCB_PTR. */
4291 tcb_ptr = (OSEK_TCB *) (this_alarm->task);
4292
4293 if (tcb_ptr->osek_task_id != OSEK_TASK_ID)
4294 {
4295 break;
4296 }
4297
4298 /* Check if any event is assigned to task. */
4299 if ((tcb_ptr->events == 0u) || (tcb_ptr->task_type == BASIC))
4300 {
4301 break;
4302 }
4303
4304 if (tcb_ptr->suspended == TX_TRUE)
4305 {
4306 break;
4307 }
4308
4309 /* Check this event mask with the task. */
4310 /* Update the set events for this task with this new mask. */
4311 tcb_ptr->set_events = tcb_ptr->set_events | (this_alarm->events);
4312
4313 /* See if any events is set. */
4314 balance_events = tcb_ptr->set_events & tcb_ptr->waiting_events;
4315
4316 /* Is there any from waiting events. */
4317 if (balance_events != 0u)
4318 {
4319
4320 if (tcb_ptr->waiting == TX_TRUE)
4321 {
4322 tcb_ptr->waiting = TX_FALSE;
4323 /* Now, send message to the system manager to check any preemption out of SetEvent call. */
4324
4325 /* Build the request. */
4326 request[0] = SYSMGR_SETEVENT; /* Request type. */
4327 request[1] = last_run_task; /* Task currently executing. */
4328 request[2] = (ULONG)tcb_ptr; /* Task id for which events are set. */
4329 request[3] = 0u;
4330 status = tx_queue_send(&osek_work_queue, request, TX_NO_WAIT);
4331
4332 /* This should always succeed. */
4333 if (status != TX_SUCCESS)
4334 {
4335 /* System internal error. */
4336 osek_internal_error(SYS_MGR_SEND_CHAINTASK);
4337 }
4338
4339
4340 /* One message sent, increment the msg counter, this required because
4341 System manager message queue can hold only certain number of messages. */
4342 msg_cnt++;
4343
4344 } /* End if (tcb_ptr->waiting == TX_TRUE). */
4345 } /* End if (balance_events). */
4346 break;
4347
4348 default:
4349 break;
4350 } /* switch ends. */
4351
4352 /* A situation may arise that multiple alarms expire at time (being set to same expiration count and mode)
4353 Which means timer has to send multiple alarm action messages to the system manager. But as the system manager accepts
4354 only certain number of messages at a time, we can't send more than that number of alarm action
4355 messages (SetEvent, ActivateTask) in one loop,
4356 so check if the system manager queue is filled up if yes stop checking for next alarm, we'll come again to check
4357 balance alarms. */
4358
4359 if (msg_cnt == (SYSMGR_QUEUE_MSG_COUNT))
4360 {
4361 break;
4362 }
4363
4364 } /* for ends. */
4365
4366 /* Enable interrupt. */
4367 TX_RESTORE
4368
4369 return (E_OK);
4370 }
4371
4372
4373 /**************************************************************************/
4374 /* */
4375 /* FUNCTION RELEASE */
4376 /* */
4377 /* DefineSystemCounter PORTABLE C */
4378 /* 6.1.7 */
4379 /* AUTHOR */
4380 /* */
4381 /* William E. Lamie, Microsoft Corporation */
4382 /* */
4383 /* DESCRIPTION */
4384 /* */
4385 /* This functions sets the system counter by assigning the specified */
4386 /* counter as a system counter. */
4387 /* If a counter is already defined as a system counter this call will */
4388 /* return an error. */
4389 /* */
4390 /* INPUT */
4391 /* */
4392 /* Counter Counter to assign as system counter */
4393 /* */
4394 /* OUTPUT */
4395 /* */
4396 /* E_OK If successful */
4397 /* E_OS_ID If counter id is invalid */
4398 /* E_OS_NOFUNC Counter already assigned */
4399 /* */
4400 /* CALLS */
4401 /* */
4402 /* tx_timer_activate starts the Thread timer to update */
4403 /* this SystemCounter */
4404 /* */
4405 /* CALLED BY */
4406 /* */
4407 /* Application Code */
4408 /* */
4409 /* RELEASE HISTORY */
4410 /* */
4411 /* DATE NAME DESCRIPTION */
4412 /* */
4413 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
4414 /* */
4415 /**************************************************************************/
DefineSystemCounter(CounterType cntr)4416 StatusType DefineSystemCounter (CounterType cntr)
4417 {
4418
4419 OSEK_COUNTER *cntr_ptr;
4420 OSEK_COUNTER *this_counter;
4421 UINT index;
4422 UINT attached;
4423
4424 /* Check if we are in initialization. */
4425 /* This will ensure that no one calls this function after system is started. */
4426 if (osek_init_state != OSEK_INIT)
4427 {
4428 /* Return OSEK internal error. This is not a standard OSEK error. */
4429 Application->osek_object_creation_error++;
4430
4431 return ((TaskType)TX_NULL);
4432 }
4433
4434 /* Convert counter id to counter pointer. */
4435
4436 cntr_ptr = (OSEK_COUNTER *)cntr;
4437
4438 /* Check for valid counter. */
4439 if ((cntr_ptr == TX_NULL) && (cntr_ptr->osek_counter_id != OSEK_COUNTER_ID))
4440 {
4441 /* There is error in counter object supplied. */
4442 Application->osek_object_creation_error++;
4443
4444 return (E_OS_ID);
4445 }
4446
4447 if (cntr_ptr->cntr_in_use == TX_FALSE)
4448 {
4449 Application->osek_object_creation_error++;
4450
4451 return (E_OS_ID);
4452 }
4453
4454 /* Now check if there any a counter exists attached to system timer? */
4455 attached = TX_FALSE;
4456
4457 /* Search for a free counter. */
4458 this_counter = osek_counter_pool;
4459 for (index = 0u; index < OSEK_MAX_COUNTERS; index++)
4460 {
4461 /* Is this guy is attached to system timer? */
4462 if (this_counter->system_timer == TX_TRUE)
4463 {
4464 /* This counter is attached to system timer. */
4465 attached = TX_TRUE;
4466 /* Stop searching. */
4467 break;
4468 }
4469
4470 this_counter++;
4471 } /* check all counters. */
4472
4473 /* No body attached to system timer? */
4474 if (attached == TX_FALSE)
4475 {
4476 /* No one is attached, attach counter supplied to system timer. */
4477 cntr_ptr->system_timer = TX_TRUE;
4478
4479 /* Now start the system timer. */
4480 tx_timer_activate(&osek_system_timer);
4481
4482 return (E_OK);
4483 }
4484
4485 /* One counter is already attached to system timer. */
4486 Application->osek_object_creation_error++;
4487
4488 return (E_OS_NOFUNC);
4489 }
4490
4491
4492 /**************************************************************************/
4493 /* */
4494 /* FUNCTION RELEASE */
4495 /* */
4496 /* CreateAlarm PORTABLE C */
4497 /* 6.1.7 */
4498 /* AUTHOR */
4499 /* */
4500 /* William E. Lamie, Microsoft Corporation */
4501 /* */
4502 /* DESCRIPTION */
4503 /* */
4504 /* Creates an alarm. */
4505 /* */
4506 /* INPUT */
4507 /* */
4508 /* ticks Tick count */
4509 /* */
4510 /* OUTPUT */
4511 /* */
4512 /* ALARM_ID Reference to alarm */
4513 /* */
4514 /* CALLS */
4515 /* */
4516 /* osek_get_alarm Get the alarm if possible */
4517 /* */
4518 /* CALLED BY */
4519 /* */
4520 /* Application Code */
4521 /* */
4522 /* RELEASE HISTORY */
4523 /* */
4524 /* DATE NAME DESCRIPTION */
4525 /* */
4526 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
4527 /* */
4528 /**************************************************************************/
CreateAlarm(const CHAR * name,CounterType cntr,UINT action,ULONG events,TaskType task,void (* callback)(),UINT Startup,TickType Alarmtime,TickType Cycle)4529 AlarmType CreateAlarm(const CHAR *name, CounterType cntr, UINT action, ULONG events, TaskType task,
4530 void (*callback)(), UINT Startup, TickType Alarmtime, TickType Cycle )
4531 {
4532
4533 AlarmType alarm_id;
4534 OSEK_COUNTER *cntr_ptr;
4535 OSEK_TCB *tcb_ptr;
4536 OSEK_ALARM *this_alarm;
4537 UINT index;
4538 TickType current_value;
4539 StatusType status;
4540
4541 /* Check if we are in Initialization. */
4542 /* This will ensure that no one calls this function after system is started. */
4543 if (osek_init_state != OSEK_INIT)
4544 {
4545 /* Return OSEK internal error. This is not a standard OSEK error. */
4546 Application->osek_object_creation_error++;
4547
4548 return ((TaskType)TX_NULL);
4549 }
4550
4551 /* Start with validating arguments passed. */
4552 cntr_ptr = (OSEK_COUNTER*)cntr;
4553 if ((cntr_ptr == TX_NULL) || (cntr_ptr->osek_counter_id != OSEK_COUNTER_ID)|| (cntr_ptr->cntr_in_use == TX_FALSE))
4554 {
4555 /* Counter is not valid. */
4556 Application->osek_object_creation_error++;
4557 return (E_OS_ID);
4558 }
4559
4560 if (cntr_ptr->cntr_in_use != TX_TRUE)
4561 {
4562 /* Counter is not in use. */
4563 Application->osek_object_creation_error++;
4564
4565 return (E_OS_ID);
4566 }
4567
4568 tcb_ptr = (OSEK_TCB *)task;
4569
4570 /* Check the action to be taken and parameters passed. */
4571 switch(action)
4572 {
4573 case SETEVENT:
4574
4575 /* For SetEvents there should not be call back function. */
4576 if((events == 0u) || (task == 0u) || (callback != TX_NULL))
4577 {
4578 /* Return error. */
4579 Application->osek_object_creation_error++;
4580
4581 return (E_OS_NOFUNC);
4582 }
4583
4584 if ((tcb_ptr == TX_NULL) || (tcb_ptr->osek_task_id != OSEK_TASK_ID))
4585 {
4586 /* Task is not valid. */
4587 Application->osek_object_creation_error++;
4588
4589 return (E_OS_ID);
4590 }
4591
4592 if (tcb_ptr->tcb_in_use != TX_TRUE)
4593 {
4594 /* Task is not in use */
4595 Application->osek_object_creation_error++;
4596 return (E_OS_ID);
4597 }
4598
4599 break;
4600
4601 case ACTIVATETASK:
4602 /* For activate task there should not be any call-back function or any event. */
4603 if((task == 0u) || (events != 0u) || (callback != TX_NULL))
4604 {
4605 /* Return error. */
4606 Application->osek_object_creation_error++;
4607
4608 return (E_OS_NOFUNC);
4609 }
4610
4611 if ((tcb_ptr == TX_NULL) || (tcb_ptr->osek_task_id != OSEK_TASK_ID))
4612 {
4613 /* Task is not valid. */
4614 Application->osek_object_creation_error++;
4615 return (E_OS_ID);
4616 }
4617
4618 if (tcb_ptr->tcb_in_use != TX_TRUE)
4619 {
4620 /* Task is not in use. */
4621 Application->osek_object_creation_error++;
4622 return (E_OS_ID);
4623 }
4624
4625 break;
4626
4627 case CALLBACK:
4628 /* For ALARMCALLBACK there should not be task or any event. */
4629 if((callback == TX_NULL) || (events != 0u) || (task != 0u))
4630 {
4631 /* Return error. */
4632 Application->osek_object_creation_error++;
4633
4634 return (E_OS_NOFUNC);
4635 }
4636
4637 break;
4638
4639 default:
4640 /* Return error. */
4641 Application->osek_object_creation_error++;
4642
4643 return (E_OS_NOFUNC);
4644
4645 break;
4646 }
4647
4648 /* Check if there is space for this alarm. */
4649 alarm_id = osek_get_alarm();
4650 if (alarm_id == 0u)
4651 {
4652 /* Return error. */
4653 Application->osek_object_creation_error++;
4654
4655 return (E_OS_NOFUNC);
4656 }
4657
4658 /* Got correct inputs, get pointer to alarm. */
4659 this_alarm = (OSEK_ALARM *)alarm_id;
4660
4661 /* Store object id. */
4662 this_alarm->osek_alarm_id = OSEK_ALARM_ID;
4663
4664 /* Before attaching this alarm to a counter, disarm it. */
4665 this_alarm->armed = TX_FALSE;
4666
4667 this_alarm->name = name;
4668
4669 /* Now, try attaching this alarm to the counter specified. */
4670 for (index = 0u; index < OSEK_MAX_ALARMS; index++)
4671 {
4672 /* Find a free entry in the list maintained by the counter. */
4673 if (cntr_ptr->alarm_list[index] == 0u)
4674 {
4675 /* Found one. */
4676 cntr_ptr->alarm_list[index] = alarm_id;
4677
4678 break;
4679 }
4680 }
4681
4682 /* Searched the entire list and came empty handed? */
4683 if (index >= OSEK_MAX_ALARMS)
4684 {
4685 /* Return error. */
4686 osek_reset_alarm(this_alarm);
4687
4688 Application->osek_object_creation_error++;
4689
4690 return (E_OS_NOFUNC);
4691 }
4692
4693 /* Got the counter, now save the counter in to ALARM structure. */
4694 this_alarm->cntr = cntr_ptr;
4695
4696 /* Maximum allowed value and minimum cycles for this alarms this values are from */
4697 /* the counter to which this alarm is attached. */
4698 this_alarm->max_allowed_value = cntr_ptr->maxallowedvalue;
4699 this_alarm->min_cyc = cntr_ptr->mincycle;
4700 this_alarm->ticks_per_base = cntr_ptr->ticksperbase;
4701
4702 this_alarm->name = name;
4703
4704 /* Store the ACTION upon alarm expiration. */
4705 this_alarm->action = action;
4706
4707 /* Store event in case of SETEVENT action. */
4708 this_alarm->events = events;
4709
4710 /* Check for call back and store it. */
4711 if(callback != TX_NULL)
4712 {
4713 this_alarm->alarm_callback = callback;
4714 }
4715
4716 if (Startup != 0u)
4717 {
4718 this_alarm->auto_start = TX_TRUE;
4719 }
4720
4721 /* Save the TASK in to ALARM structure. */
4722 this_alarm->task = tcb_ptr;
4723
4724 /* Everything is OK so far, now fill this alarm control block with some default parameters. */
4725
4726 /* Reset max cycles, current cycles and expiration count. */
4727 this_alarm->expiration_count = 0u;
4728 this_alarm->cycle = 0u;
4729
4730 /* Now it is time to check for AUTOSTART. */
4731 if (this_alarm->auto_start != 0u)
4732 {
4733 /* Check start. */
4734 if ((Alarmtime == 0u) || (Alarmtime > this_alarm->max_allowed_value))
4735 {
4736 /* Invalid input parameter. */
4737 Application->osek_object_creation_error++;
4738
4739 return (E_OS_VALUE);
4740 }
4741
4742 /* Check cycle. */
4743 if (Cycle != 0u)
4744 {
4745 if ((Cycle < this_alarm->min_cyc) || (Cycle > this_alarm->max_allowed_value))
4746 {
4747 /* Invalid input parameter. */
4748 Application->osek_object_creation_error++;
4749
4750 return (E_OS_VALUE);
4751 }
4752 }
4753
4754 /* All input parameters are ok, store relative value and cycle. */
4755 this_alarm->cycle = Cycle;
4756
4757 status = GetCounterValue(cntr_ptr, ¤t_value);
4758 if (status != E_OK)
4759 {
4760 Application->osek_object_creation_error++;
4761
4762 return (E_OS_VALUE); /* Some problem in getting counter's current value. */
4763 }
4764
4765 this_alarm->expiration_count = current_value + Alarmtime; /* Load the counter with its expiration count. */
4766
4767 /* Now set the relative mode. */
4768 this_alarm->rel_abs_mode = RELATIVE_ALARM;
4769 this_alarm->counter_rollback = TX_FALSE;
4770 this_alarm->armed = TX_TRUE;
4771 this_alarm->occupied = TX_TRUE;
4772
4773 } /* End.. this_alarm->auto_start. */
4774
4775 return(alarm_id);
4776 }
4777
4778
4779 /**************************************************************************/
4780 /* */
4781 /* FUNCTION RELEASE */
4782 /* */
4783 /* GetAlarmBase PORTABLE C */
4784 /* 6.1.7 */
4785 /* AUTHOR */
4786 /* */
4787 /* William E. Lamie, Microsoft Corporation */
4788 /* */
4789 /* DESCRIPTION */
4790 /* */
4791 /* Reads the alarm base characteristics. Returns info which is a */
4792 /* in which the information of the data type AlarmbaseType is */
4793 /* stored. */
4794 /* */
4795 /* INPUT */
4796 /* */
4797 /* AlarmID Reference to alarm */
4798 /* */
4799 /* OUTPUT */
4800 /* */
4801 /* Info user_defined parameters of the */
4802 /* counter associated with alarm. */
4803 /* CALLS */
4804 /* */
4805 /* */
4806 /* CALLED BY */
4807 /* */
4808 /* Application Code */
4809 /* */
4810 /* RELEASE HISTORY */
4811 /* */
4812 /* DATE NAME DESCRIPTION */
4813 /* */
4814 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
4815 /* */
4816 /**************************************************************************/
GetAlarmBase(AlarmType AlarmID,AlarmBaseRefType info)4817 StatusType GetAlarmBase(AlarmType AlarmID, AlarmBaseRefType info)
4818 {
4819
4820 OSEK_ALARM *alarm_ptr;
4821
4822
4823 service_GetServiceId.id = (OsServiceIdType)OSServiceId_GetAlarmBase;
4824 service_GetAlarmBase.AlarmID = AlarmID;
4825
4826 /* Get the OSEK alarm. */
4827 alarm_ptr = (OSEK_ALARM *) AlarmID;
4828
4829 /* Check valid ID. */
4830 if((alarm_ptr == 0u) || (alarm_ptr->osek_alarm_id != OSEK_ALARM_ID))
4831 {
4832 exec_ErrorHook (E_OS_ID);
4833
4834 /* Invalid AlarmID. */
4835 return (E_OS_ID);
4836 }
4837
4838 info->maxallowedvalue = alarm_ptr->max_allowed_value;
4839 info->mincycle = alarm_ptr->min_cyc;
4840 info->ticksperbase = alarm_ptr->ticks_per_base;
4841
4842 return (E_OK);
4843 }
4844
4845
4846 /**************************************************************************/
4847 /* */
4848 /* FUNCTION RELEASE */
4849 /* */
4850 /* SetAbsAlarm PORTABLE C */
4851 /* 6.1.7 */
4852 /* AUTHOR */
4853 /* */
4854 /* William E. Lamie, Microsoft Corporation */
4855 /* */
4856 /* DESCRIPTION */
4857 /* */
4858 /* Sets an alarm to an absolute cycle value. */
4859 /* */
4860 /* INPUT */
4861 /* */
4862 /* AlarmID Reference to alarm. */
4863 /* start Absolute value in ticks. */
4864 /* cycle Cycle value in case of cyclic alarm. */
4865 /* In case of single alarm it must be */
4866 /* zero. */
4867 /* */
4868 /* OUTPUT */
4869 /* */
4870 /* E_OK If successful */
4871 /* ERROR If error occurs while creating task */
4872 /* */
4873 /* CALLS */
4874 /* */
4875 /* osek_internal_error OSEK internal error */
4876 /* tx_time_get Get system time */
4877 /* tx_timer_create Create the timer is created */
4878 /* */
4879 /* CALLED BY */
4880 /* */
4881 /* Application Code */
4882 /* */
4883 /* RELEASE HISTORY */
4884 /* */
4885 /* DATE NAME DESCRIPTION */
4886 /* */
4887 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
4888 /* */
4889 /**************************************************************************/
SetAbsAlarm(AlarmType AlarmID,TickType start,TickType cycle)4890 StatusType SetAbsAlarm(AlarmType AlarmID, TickType start, TickType cycle)
4891 {
4892 TX_INTERRUPT_SAVE_AREA
4893 OSEK_ALARM *osek_alarm;
4894
4895
4896 service_GetServiceId.id = (OsServiceIdType)OSServiceId_SetAbsAlarm;
4897 service_SetAbsAlarm.AlarmID = AlarmID;
4898 service_SetAbsAlarm.start = start;
4899 service_SetAbsAlarm.cycle = cycle;
4900
4901 /* Convert AlarmID to OSEK_ALARM. */
4902 osek_alarm = (OSEK_ALARM *) AlarmID;
4903
4904 /* Check valid ID. */
4905 if((osek_alarm == 0u) || (osek_alarm->osek_alarm_id != OSEK_ALARM_ID))
4906 {
4907 exec_ErrorHook (E_OS_ID);
4908
4909 /* Invalid AlarmID. */
4910 return (E_OS_ID);
4911 }
4912
4913 TX_DISABLE
4914
4915 /* Check already armed? */
4916 if (osek_alarm->armed == TX_TRUE)
4917 {
4918 TX_RESTORE
4919
4920 exec_ErrorHook(E_OS_STATE);
4921
4922 return (E_OS_STATE);
4923 }
4924
4925 /* Check start. */
4926 if ((start == 0u) || ( start > osek_alarm->max_allowed_value))
4927 {
4928 TX_RESTORE
4929
4930 /* Invalid input parameter. */
4931 exec_ErrorHook(E_OS_VALUE);
4932
4933 return (E_OS_VALUE);
4934 }
4935
4936
4937 /* Check cycle. */
4938 if (cycle != 0u)
4939 {
4940 if ((cycle < osek_alarm->min_cyc) || ( cycle > osek_alarm->max_allowed_value))
4941 {
4942 TX_RESTORE
4943
4944 exec_ErrorHook(E_OS_VALUE);
4945
4946 /* Invalid input parameter. */
4947 return (E_OS_VALUE);
4948 }
4949 }
4950
4951 /* All input parameters are ok, store abs value and cycle. */
4952 osek_alarm->cycle = cycle;
4953 osek_alarm->expiration_count = start; /* Load the counter with its expiration count. */
4954
4955 /* Now set the absolute mode. */
4956 osek_alarm->rel_abs_mode = ABSOLUTE_ALARM;
4957
4958 /* Now, arm the alarm. */
4959 osek_alarm->armed = TX_TRUE;
4960 osek_alarm->occupied = TX_TRUE;
4961 osek_alarm->counter_rollback = TX_FALSE;
4962
4963 TX_RESTORE
4964
4965 /* Return OK. */
4966 return (E_OK);
4967 }
4968
4969
4970 /**************************************************************************/
4971 /* */
4972 /* FUNCTION RELEASE */
4973 /* */
4974 /* SetRelAlarm PORTABLE C */
4975 /* 6.1.7 */
4976 /* AUTHOR */
4977 /* */
4978 /* William E. Lamie, Microsoft Corporation */
4979 /* */
4980 /* DESCRIPTION */
4981 /* */
4982 /* Sets an alarm to a relative cycle value from the current time. */
4983 /* */
4984 /* INPUT */
4985 /* */
4986 /* AlarmID Reference to alarm. */
4987 /* increment Relative value in ticks */
4988 /* cycle Cycle value in case of cyclic alarm */
4989 /* In case of single alarm it must be */
4990 /* zero. */
4991 /* */
4992 /* OUTPUT */
4993 /* */
4994 /* E_OK If successful */
4995 /* ERROR If an error occurs */
4996 /* */
4997 /* CALLS */
4998 /* */
4999 /* osek_internal_error OSEK internal error */
5000 /* tx_timer_change Change the timer */
5001 /* */
5002 /* CALLED BY */
5003 /* */
5004 /* Application Code */
5005 /* */
5006 /* RELEASE HISTORY */
5007 /* */
5008 /* DATE NAME DESCRIPTION */
5009 /* */
5010 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
5011 /* */
5012 /**************************************************************************/
SetRelAlarm(AlarmType AlarmID,TickType increment,TickType cycle)5013 StatusType SetRelAlarm(AlarmType AlarmID, TickType increment, TickType cycle)
5014 {
5015 TX_INTERRUPT_SAVE_AREA
5016 OSEK_ALARM *osek_alarm;
5017 OSEK_COUNTER *counter_ptr;
5018 TickType current_value;
5019 StatusType status;
5020
5021
5022 service_GetServiceId.id = (OsServiceIdType)OSServiceId_SetRelAlarm;
5023 service_SetRelAlarm.AlarmID = AlarmID;
5024 service_SetRelAlarm.increment = increment;
5025 service_SetRelAlarm.cycle = cycle;
5026
5027 /* Convert AlarmID to OSEK_ALARM. */
5028 osek_alarm = (OSEK_ALARM *)AlarmID;
5029
5030 /* Check valid ID. */
5031 if((osek_alarm == TX_NULL) || (osek_alarm->osek_alarm_id != OSEK_ALARM_ID))
5032 {
5033 exec_ErrorHook(E_OS_ID);
5034
5035 /* Invalid AlarmID. */
5036 return (E_OS_ID);
5037 }
5038
5039 TX_DISABLE
5040
5041 /* Check already armed? */
5042 if (osek_alarm->armed == TX_TRUE)
5043 {
5044 TX_RESTORE
5045
5046 exec_ErrorHook(E_OS_STATE);
5047
5048 return (E_OS_STATE);
5049 }
5050
5051 /* Check start. */
5052 if ((increment == 0u) || (increment > osek_alarm->max_allowed_value))
5053 {
5054 TX_RESTORE
5055
5056 exec_ErrorHook(E_OS_VALUE);
5057
5058 /* Invalid input parameter. */
5059 return (E_OS_VALUE);
5060 }
5061
5062 /* Check cycle. */
5063 if (cycle != 0u)
5064 {
5065 if ((cycle < osek_alarm->min_cyc) || (cycle > osek_alarm->max_allowed_value))
5066 {
5067 TX_RESTORE
5068
5069 exec_ErrorHook(E_OS_VALUE);
5070
5071 /* Invalid input parameter. */
5072 return (E_OS_VALUE);
5073 }
5074 }
5075
5076 /* All input parameters are ok, store rel value and cycle. */
5077 osek_alarm->cycle = cycle;
5078 counter_ptr = osek_alarm->cntr;
5079
5080 status = GetCounterValue(counter_ptr, ¤t_value);
5081 if (status != E_OK)
5082 {
5083 TX_RESTORE
5084 return (E_OS_STATE);
5085 }
5086
5087 osek_alarm->expiration_count = current_value + increment; /* Load the counter with its expiration count. */
5088
5089 /* Now set the relative mode. */
5090 osek_alarm->rel_abs_mode = RELATIVE_ALARM;
5091 osek_alarm->counter_rollback = TX_FALSE;
5092
5093 /* Now, arm the alarm. */
5094 osek_alarm->armed = TX_TRUE;
5095 osek_alarm->occupied = TX_TRUE;
5096
5097 TX_RESTORE
5098
5099 /* Return OK. */
5100 return (E_OK);
5101 }
5102
5103
5104 /**************************************************************************/
5105 /* */
5106 /* FUNCTION RELEASE */
5107 /* */
5108 /* CancelAlarm PORTABLE C */
5109 /* 6.1.7 */
5110 /* AUTHOR */
5111 /* */
5112 /* William E. Lamie, Microsoft Corporation */
5113 /* */
5114 /* DESCRIPTION */
5115 /* */
5116 /* Cancels the alarm: the alarm transition into the stop state. */
5117 /* */
5118 /* INPUT */
5119 /* */
5120 /* AlarmID Reference to alarm */
5121 /* */
5122 /* OUTPUT */
5123 /* */
5124 /* E_OK If successful */
5125 /* ERROR If an error occurs */
5126 /* */
5127 /* CALLS */
5128 /* */
5129 /* tx_timer_deactivate Timer deactivate */
5130 /* osek_internal_error OSEK internal error */
5131 /* */
5132 /* CALLED BY */
5133 /* */
5134 /* Application Code */
5135 /* */
5136 /* RELEASE HISTORY */
5137 /* */
5138 /* DATE NAME DESCRIPTION */
5139 /* */
5140 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
5141 /* */
5142 /**************************************************************************/
CancelAlarm(AlarmType AlarmID)5143 StatusType CancelAlarm(AlarmType AlarmID)
5144 {
5145 TX_INTERRUPT_SAVE_AREA
5146 OSEK_ALARM *osek_alarm;
5147
5148 service_GetServiceId.id = (OsServiceIdType)OSServiceId_CancelAlarm;
5149 service_CancelAlarm.AlarmID = AlarmID;
5150
5151 /* Check valid ID and absolute ticks. */
5152 osek_alarm = (OSEK_ALARM *) AlarmID;
5153 if((osek_alarm == TX_NULL) || (osek_alarm->osek_alarm_id != OSEK_ALARM_ID))
5154 {
5155 exec_ErrorHook(E_OS_ID);
5156
5157 /* Invalid AlarmID. */
5158 return (E_OS_ID);
5159 }
5160
5161 TX_DISABLE
5162
5163 /* Is this alarm in use? */
5164 if ((osek_alarm->armed == TX_FALSE) || (osek_alarm->occupied == TX_FALSE))
5165 {
5166 TX_RESTORE
5167
5168 exec_ErrorHook(E_OS_NOFUNC);
5169
5170 return (E_OS_NOFUNC);
5171 }
5172
5173 /* Alarm is in use so make it inactive. */
5174 osek_alarm->armed = TX_FALSE;
5175
5176 TX_RESTORE
5177
5178 /* Return OK. */
5179 return (E_OK);
5180 }
5181
5182
5183 /**************************************************************************/
5184 /* */
5185 /* FUNCTION RELEASE */
5186 /* */
5187 /* GetAlarm PORTABLE C */
5188 /* 6.1.7 */
5189 /* AUTHOR */
5190 /* */
5191 /* William E. Lamie, Microsoft Corporation */
5192 /* */
5193 /* DESCRIPTION */
5194 /* */
5195 /* Returns the no. of ticks before the alarm expires. */
5196 /* */
5197 /* INPUT */
5198 /* */
5199 /* ticks Pointer to the returned tick count */
5200 /* */
5201 /* OUTPUT */
5202 /* */
5203 /* N/A */
5204 /* */
5205 /* CALLS */
5206 /* */
5207 /* tx_timer_info_get Retrieves information about specified */
5208 /* timer. */
5209 /* osek_internal_error OSEK internal error */
5210 /* */
5211 /* CALLED BY */
5212 /* */
5213 /* Application Code */
5214 /* */
5215 /* RELEASE HISTORY */
5216 /* */
5217 /* DATE NAME DESCRIPTION */
5218 /* */
5219 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
5220 /* */
5221 /**************************************************************************/
GetAlarm(AlarmType AlarmID,TickRefType tick_ptr)5222 StatusType GetAlarm(AlarmType AlarmID, TickRefType tick_ptr)
5223 {
5224 TX_INTERRUPT_SAVE_AREA
5225 OSEK_ALARM *osek_alarm;
5226 OSEK_COUNTER *counter_ptr;
5227 TickType current_ticks;
5228 StatusType status;
5229
5230
5231 service_GetServiceId.id = (OsServiceIdType)OSServiceId_GetAlarm;
5232 service_GetAlarm.AlarmID = AlarmID;
5233
5234 /* Check valid ID and absolute ticks. */
5235 osek_alarm = (OSEK_ALARM *) AlarmID;
5236 if((osek_alarm == TX_NULL) || (osek_alarm->osek_alarm_id != OSEK_ALARM_ID))
5237 {
5238 exec_ErrorHook (E_OS_ID);
5239
5240 /* Invalid AlarmID. */
5241 return (E_OS_ID);
5242 }
5243
5244 TX_DISABLE
5245
5246 if ((osek_alarm->armed == FALSE) || (osek_alarm->occupied == TX_FALSE))
5247 {
5248 TX_RESTORE
5249
5250 exec_ErrorHook(E_OS_NOFUNC);
5251
5252 return (E_OS_NOFUNC); /* Alarm expired or not in use. */
5253 }
5254
5255 counter_ptr = osek_alarm->cntr;
5256
5257 status = GetCounterValue(counter_ptr, ¤t_ticks);
5258 if (status != E_OK)
5259 {
5260 TX_RESTORE
5261
5262 exec_ErrorHook (E_OS_ID);
5263 return (E_OS_ID);
5264 }
5265
5266 if (osek_alarm->expiration_count < current_ticks)
5267 {
5268 /* Alarm's expiration count is less than current counter value means */
5269 /* alarm will expire after the counter rolls back and reach alarm's expiration count. */
5270 *tick_ptr = (osek_alarm->max_allowed_value - current_ticks + osek_alarm->expiration_count);
5271 }
5272 else
5273 {
5274 /* Alarm's expiration is more than counter's current value. */
5275 *tick_ptr = (osek_alarm->max_allowed_value - current_ticks);
5276 }
5277
5278 TX_RESTORE
5279
5280 return (E_OK);
5281 }
5282
5283
5284 /**************************************************************************/
5285 /* */
5286 /* FUNCTION RELEASE */
5287 /* */
5288 /* osek_initialize PORTABLE C */
5289 /* 6.1.7 */
5290 /* AUTHOR */
5291 /* */
5292 /* William E. Lamie, Microsoft Corporation */
5293 /* */
5294 /* DESCRIPTION */
5295 /* */
5296 /* This function sets up, configures and initializes all the */
5297 /* "behind-the-scenes" data structures, tables, memory regions, etc. */
5298 /* used by the OSEK at run-time. */
5299 /* */
5300 /* INPUT */
5301 /* */
5302 /* osek_memory OSEK pointer */
5303 /* */
5304 /* OUTPUT */
5305 /* */
5306 /* None */
5307 /* */
5308 /* CALLS */
5309 /* */
5310 /* tx_thread_create Create system manager thread */
5311 /* tx_timer_create Create a system timer */
5312 /* osek_memory_init Initialize OSEK memory */
5313 /* tx_queue_create Create system manager queue */
5314 /* osek_tcb_init Initialize OSEK tasks */
5315 /* osek_resource_init Initialize OSEK resources */
5316 /* osek_alarm_init Initialize OSEK alarms */
5317 /* osek_counter_init Initialize OSEK counter */
5318 /* */
5319 /* CALLED BY */
5320 /* */
5321 /* Start-up code */
5322 /* */
5323 /* RELEASE HISTORY */
5324 /* */
5325 /* DATE NAME DESCRIPTION */
5326 /* */
5327 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
5328 /* */
5329 /**************************************************************************/
5330
osek_initialize(void * osek_memory,APPLICATION_INFO_PTR application1)5331 UCHAR *osek_initialize(void *osek_memory, APPLICATION_INFO_PTR application1)
5332 {
5333
5334 UCHAR *pointer;
5335 UINT status;
5336 UINT i;
5337 UINT j;
5338
5339 /* Initialization started, set init state. */
5340 osek_init_state = OSEK_INIT;
5341
5342 Application = application1;
5343 Application->osek_object_creation_error = 0u;
5344 /* Setup temporary memory pointer so we can start allocating
5345 space for the OSEK data structures. The important thing to
5346 remember here is that the system threads stack, the region0
5347 memory, and the queue are allocated sequentially from the
5348 address specified by OSEK_memory. */
5349
5350 pointer = (UCHAR *)osek_memory;
5351
5352 /* Create the work item message queue. */
5353 status = tx_queue_create(&osek_work_queue, "OSEK work queue", SYSMGR_QUEUE_MSG_LENGTH,
5354 pointer, SYSMGR_QUEUE_DEPTH * SYSMGR_QUEUE_MSG_LENGTH);
5355 if(status != TX_SUCCESS)
5356 {
5357 Application->osek_object_creation_error++;
5358 }
5359
5360 pointer = pointer + (SYSMGR_QUEUE_DEPTH * SYSMGR_QUEUE_MSG_LENGTH);
5361
5362 /* Create the system manager thread. */
5363 status = tx_thread_create(&osek_system_manager, "OSEK System Manager", osek_system_manager_entry,
5364 0, pointer, OSEK_SYSTEM_STACK_SIZE, SYSMGR_PRIORITY, SYSMGR_THRESHOLD,
5365 TX_NO_TIME_SLICE, TX_AUTO_START);
5366 if (status != TX_SUCCESS)
5367 {
5368 /* Error creating the system manager thread. */
5369 Application->osek_object_creation_error++;
5370 }
5371
5372 pointer = pointer + OSEK_SYSTEM_STACK_SIZE;
5373
5374 /* Set up a memory "heap" or TX_REGION0_SIZE_IN_BYTES used internally
5375 by the osek. */
5376
5377 status = osek_memory_init(pointer);
5378
5379 if (status != TX_SUCCESS)
5380 {
5381 Application->osek_object_creation_error++;
5382 }
5383
5384 pointer = pointer + TX_REGION0_SIZE_IN_BYTES;
5385
5386
5387 /* Create the system timer. */
5388 status = tx_timer_create( &osek_system_timer, "OSEK SYSTEM TIMER", osek_system_timer_entry,
5389 0,5,5,TX_NO_ACTIVATE);
5390
5391 if (status != TX_SUCCESS)
5392 {
5393 Application->osek_object_creation_error++;
5394 }
5395
5396 /* Check whether any error occurred during system object creation. */
5397 if (Application->osek_object_creation_error != 0u)
5398 {
5399 osek_internal_error(THREADX_OBJECT_CREATION_ERROR);
5400 }
5401
5402 /* Initialize static pool of task control blocks. */
5403 osek_tcb_init();
5404
5405 /* Set up a pool of resource used internally by the OSEK layer. */
5406 osek_resource_init();
5407
5408 /* Set up a pool of counter used internally by the OSEK layer. */
5409 osek_counter_init();
5410
5411 /* Set up a pool of alarm used internally by the OSEK layer. */
5412 osek_alarm_init();
5413
5414 /* Clear all events. */
5415 global_events = 0u;
5416 global_event_count = 0u;
5417
5418 /* Clear task table. */
5419
5420 for (i = 0u; i < (OSEK_ISR1_PRIORITY + 1u); i++)
5421 {
5422 for (j = 0u; j < TASK_QUEUE_DEPTH; j++)
5423 {
5424 task_table[i][j] = 0u;
5425 }
5426 }
5427
5428 /* Change OSEK mode. */
5429 osek_wrapper_operation_mode = INITSYSTEM_MODE;
5430
5431 system_start = TX_TRUE;
5432
5433 /* All done. */
5434 return (pointer);
5435 }
5436
5437
5438 /**************************************************************************/
5439 /* */
5440 /* FUNCTION RELEASE */
5441 /* */
5442 /* osek_cleanup PORTABLE C */
5443 /* 6.1.7 */
5444 /* AUTHOR */
5445 /* */
5446 /* William E. Lamie, Microsoft Corporation */
5447 /* */
5448 /* DESCRIPTION */
5449 /* */
5450 /* Cleans up after an OS shutdown. Used for testing. */
5451 /* */
5452 /* INPUT */
5453 /* */
5454 /* application1 Application pointer. */
5455 /* */
5456 /* OUTPUT */
5457 /* */
5458 /* TX_SUCCESS If successful. */
5459 /* */
5460 /* CALLED BY */
5461 /* */
5462 /* Start-up code */
5463 /* */
5464 /* RELEASE HISTORY */
5465 /* */
5466 /* DATE NAME DESCRIPTION */
5467 /* */
5468 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
5469 /* */
5470 /**************************************************************************/
5471
osek_cleanup(APPLICATION_INFO_PTR application1)5472 UINT osek_cleanup(APPLICATION_INFO_PTR application1)
5473 {
5474
5475 UINT status;
5476 UINT i;
5477 OSEK_TCB *p_tcb;
5478
5479 /* Delete the system manager thread. */
5480 status = tx_thread_delete(&osek_system_manager);
5481 if (status != TX_SUCCESS)
5482 {
5483 /* System internal error. */
5484 osek_internal_error(SYS_MGR_START_OS);
5485 }
5486
5487 /* Delete the system manager work queue. */
5488 status = tx_queue_delete(&osek_work_queue);
5489 if (status != TX_SUCCESS)
5490 {
5491 /* System internal error. */
5492 osek_internal_error(SYS_MGR_START_OS);
5493 }
5494
5495 /* Delete the system timer. */
5496 status = tx_timer_delete(&osek_system_timer);
5497 if (status != TX_SUCCESS)
5498 {
5499 /* System internal error. */
5500 osek_internal_error(SYS_MGR_START_OS);
5501 }
5502
5503 /* Delete the memory pool used for OSEK objects. */
5504 status = tx_byte_pool_delete(&osek_region0_byte_pool);
5505 if (status != TX_SUCCESS)
5506 {
5507 /* System internal error. */
5508 osek_internal_error(SYS_MGR_START_OS);
5509 }
5510
5511 /* Terminate and delete all the threads. */
5512 for(i = 0u; i < OSEK_MAX_TASKS; i++) {
5513 p_tcb = &osek_tcb_pool[i];
5514 if(p_tcb->task.tx_thread_entry != NULL) {
5515 status = tx_thread_terminate(&p_tcb->task);
5516 if (status != TX_SUCCESS)
5517 {
5518 /* System internal error. */
5519 osek_internal_error(SYS_MGR_START_OS);
5520 }
5521
5522 status = tx_thread_delete(&p_tcb->task);
5523 if (status != TX_SUCCESS)
5524 {
5525 /* System internal error. */
5526 osek_internal_error(SYS_MGR_START_OS);
5527 }
5528
5529 p_tcb->task.tx_thread_entry = NULL;
5530 }
5531 }
5532
5533 /* Clear the memory pool to prevent errors on restart. */
5534 memset(osek_tcb_pool, 0u, sizeof(osek_tcb_pool));
5535
5536 /* OSEK cleaned up, change init state to not initialized. */
5537 osek_init_state = OSEK_NOT_INIT;
5538
5539 return TX_SUCCESS;
5540 }
5541
5542
5543 /**************************************************************************/
5544 /* */
5545 /* FUNCTION RELEASE */
5546 /* */
5547 /* process_ISR2 PORTABLE C */
5548 /* 6.1.7 */
5549 /* AUTHOR */
5550 /* */
5551 /* William E. Lamie, Microsoft Corporation */
5552 /* */
5553 /* DESCRIPTION */
5554 /* */
5555 /* */
5556 /* INPUT */
5557 /* */
5558 /* isrname ISR to process. */
5559 /* */
5560 /* CALLS */
5561 /* */
5562 /* ActivateISR Puts ISR in the queue area */
5563 /* */
5564 /* CALLED BY */
5565 /* */
5566 /* Wrapper Internal code (Not available for Application) */
5567 /* */
5568 /* RELEASE HISTORY */
5569 /* */
5570 /* DATE NAME DESCRIPTION */
5571 /* */
5572 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
5573 /* */
5574 /**************************************************************************/
process_ISR2(ISRType isrname)5575 void process_ISR2(ISRType isrname)
5576 {
5577
5578 if (disable_ISR2 != 0u)
5579 {
5580 /* ISR2 disabled, do nothing. */
5581 return;
5582 }
5583
5584 ActivateISR(isrname);
5585
5586 return;
5587 }
5588
5589
5590 /**************************************************************************/
5591 /* */
5592 /* FUNCTION RELEASE */
5593 /* */
5594 /* ShutdownOS PORTABLE C */
5595 /* 6.1.7 */
5596 /* AUTHOR */
5597 /* */
5598 /* William E. Lamie, Microsoft Corporation */
5599 /* */
5600 /* DESCRIPTION */
5601 /* */
5602 /* This function shuts down the OS. If ShutdownHook is defined it is */
5603 /* called. */
5604 /* */
5605 /* INPUT */
5606 /* */
5607 /* StatusType Returned error to the hook */
5608 /* */
5609 /* OUTPUT */
5610 /* */
5611 /* None */
5612 /* */
5613 /* CALLS */
5614 /* */
5615 /* ErrorHook If defined */
5616 /* */
5617 /* CALLED BY */
5618 /* */
5619 /* Application or OS */
5620 /* */
5621 /* RELEASE HISTORY */
5622 /* */
5623 /* DATE NAME DESCRIPTION */
5624 /* */
5625 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
5626 /* */
5627 /**************************************************************************/
ShutdownOS(StatusType error)5628 void ShutdownOS(StatusType error)
5629 {
5630 TX_INTERRUPT_SAVE_AREA
5631 ULONG request[SYSMGR_QUEUE_MSG_LENGTH];
5632 UINT status;
5633
5634 TX_DISABLE
5635
5636 /* Disable ISRs. */
5637 disable_ISR2 = TX_TRUE;
5638
5639 /* Check for any shutdown hook routine. */
5640 if (Application->shutdown_hook_handler != TX_NULL)
5641 {
5642 /* Change operation mode for to shutdownhook mode. */
5643 osek_wrapper_operation_mode = SHUTDOWNHOOK_MODE;
5644
5645 (Application->shutdown_hook_handler)(error);
5646
5647 }
5648
5649 /* Change to default operations mode. */
5650 osek_wrapper_operation_mode = NORMAL_EXECUTION_MODE;
5651
5652 /* Now send message to system thread to shut down the system. */
5653 /* Build the request. */
5654 request[0] = SYSMGR_SHUTDOWN_OS; /* Request type. */
5655 request[1] = 0u; /* Dummy. */
5656 request[2] = 0u; /* Dummy. */
5657 request[3] = 0u; /* Dummy. */
5658
5659 /* Now send a message to the SysMgr supervisor thread. */
5660
5661 status = tx_queue_send(&osek_work_queue, request, TX_NO_WAIT);
5662
5663 TX_RESTORE
5664
5665 /* This should always succeed. */
5666 if (status != TX_SUCCESS)
5667 {
5668 /* System internal error. */
5669 osek_internal_error(SYS_MGR_START_OS);
5670 }
5671
5672 return;
5673 }
5674
5675
5676 /**************************************************************************/
5677 /* */
5678 /* FUNCTION RELEASE */
5679 /* */
5680 /* ActivateISR PORTABLE C */
5681 /* 6.1.7 */
5682 /* AUTHOR */
5683 /* */
5684 /* William E. Lamie, Microsoft Corporation */
5685 /* */
5686 /* DESCRIPTION */
5687 /* */
5688 /* This call activates a task which eventually executes an ISR code */
5689 /* This call puts the task in the ready queue. */
5690 /* The operating system ensures that the task code is being executed */
5691 /* from the first statement. Rescheduling after this call depends on */
5692 /* whether required resources for this ISR are free or not and no */
5693 /* other higher priority are running. */
5694 /* If E_OS_LIMIT is returned then activation is ignored as there is */
5695 /* one request of same ISR is already pending. */
5696 /* */
5697 /* ** NOTE** */
5698 /* This is not a standard OSEK API call. */
5699 /* */
5700 /* INPUT */
5701 /* */
5702 /* ISRId ISR Name */
5703 /* */
5704 /* OUTPUT */
5705 /* */
5706 /* E_OK If successful */
5707 /* E_OS_ID Invalid ISR id */
5708 /* E_OS_LIMIT One ISR already pending */
5709 /* */
5710 /* CALLS */
5711 /* */
5712 /* tx_queue_send Send message to Sys Manager */
5713 /* osek_internal_error OSEK internal error */
5714 /* */
5715 /* CALLED BY */
5716 /* */
5717 /* OSEK Wrapper Internal code (not available for Applications) */
5718 /* */
5719 /* RELEASE HISTORY */
5720 /* */
5721 /* DATE NAME DESCRIPTION */
5722 /* */
5723 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
5724 /* */
5725 /**************************************************************************/
ActivateISR(ISRType ISRID)5726 static StatusType ActivateISR(ISRType ISRID)
5727 {
5728 TX_INTERRUPT_SAVE_AREA
5729 OSEK_TCB *tcb_ptr;
5730 UINT status;
5731 ULONG request[SYSMGR_QUEUE_MSG_LENGTH];
5732
5733 /* Get the OSEK TCB for the ISR to be activated. */
5734 tcb_ptr = (OSEK_TCB *)ISRID;
5735
5736 /* Check for a valid ISR id. */
5737 if((tcb_ptr == TX_NULL) || (tcb_ptr->osek_task_id != OSEK_ISR_ID))
5738 {
5739 /* Return Error. */
5740 return (E_OS_ID);
5741 }
5742
5743 TX_DISABLE
5744
5745 /* Check whether an ISR of same name is pending. */
5746 if(tcb_ptr->current_active >= tcb_ptr->max_active)
5747 {
5748 TX_RESTORE
5749 /* Reached its max activation limit. */
5750 return (E_OS_LIMIT);
5751 }
5752
5753 /* Now send a message to the system manager to activate this ISR. */
5754 /* Build the request. */
5755
5756 request[0] = SYSMGR_ACTIVATE_TASK; /* Request type. */
5757 request[1] = (ULONG)tcb_ptr; /* ISR to Activate, */
5758 request[2] = last_run_task; /* Running task if any. */
5759 request[3] = 0u;
5760
5761 /* Since the SysMgr supervisor thread has the highest priority, this call */
5762 /* will be preempted by SysMgr supervisor thread. */
5763 /* SysMgr will eventually call osek_do_task_activate(). */
5764
5765 status = tx_queue_send(&osek_work_queue, request, TX_NO_WAIT);
5766
5767 TX_RESTORE
5768
5769 /* This should always succeed. */
5770 if (status != TX_SUCCESS)
5771 {
5772 /* System internal error. */
5773 osek_internal_error(SYS_MGR_SEND_ACTIVATETASK);
5774 }
5775
5776 /* Return status. */
5777 return (E_OK);
5778 }
5779
5780
5781 /**************************************************************************/
5782 /* */
5783 /* FUNCTION RELEASE */
5784 /* */
5785 /* TerminateISR PORTABLE C */
5786 /* 6.1.7 */
5787 /* AUTHOR */
5788 /* */
5789 /* William E. Lamie, Microsoft Corporation */
5790 /* */
5791 /* DESCRIPTION */
5792 /* */
5793 /* This service terminates the calling ISR. */
5794 /* Only internal resources held by this ISR are released here. While */
5795 /* it is assumed that any external resources occupied by the ISR must */
5796 /* have been released before the call to TerminateISR. In case */
5797 /* a resource is still occupied while calling this service, then the */
5798 /* behaviour is undefined in STANDARD version of OSEK. In the EXTENDED */
5799 /* version of OSEK, this service returns an error, which can be */
5800 /* evaluated by the application. */
5801 /* If successful, this call will causes rescheduling, this also means */
5802 /* that upon success TerminateTask does not return to the call level. */
5803 /* */
5804 /* */
5805 /* INPUT */
5806 /* */
5807 /* None */
5808 /* */
5809 /* OUTPUT */
5810 /* */
5811 /* None If success */
5812 /* Error Code. If error */
5813 /* */
5814 /* CALLS */
5815 /* */
5816 /* osek_task_independent_area Check if we are in task context */
5817 /* osek_thread2tcb Get TCB pointer for thread pointer */
5818 /* tx_queue_send Send message to sys manager thread */
5819 /* osek_internal_error In case of any internal error */
5820 /* */
5821 /* CALLED BY */
5822 /* */
5823 /* OSEK Wrapper Internal code (Not available for Applications) */
5824 /* */
5825 /* RELEASE HISTORY */
5826 /* */
5827 /* DATE NAME DESCRIPTION */
5828 /* */
5829 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
5830 /* */
5831 /**************************************************************************/
TerminateISR(void)5832 static StatusType TerminateISR(void)
5833 {
5834 TX_INTERRUPT_SAVE_AREA
5835 OSEK_TCB *tcb_ptr;
5836 ULONG request[SYSMGR_QUEUE_MSG_LENGTH];
5837 UINT index;
5838 UINT status;
5839 ULONG area;
5840 TX_THREAD *p_thread;
5841
5842
5843 /* Check for task or ISR context */
5844 /* All ISR are treated as as a high priority tasks. */
5845 area = osek_task_independent_area();
5846 if(area != TX_TRUE)
5847 {
5848 /* Return error. */
5849 return (E_OS_CALLEVEL);
5850 }
5851
5852 /* Get OSEK TCB of this TASK/ISR */
5853 p_thread = tx_thread_identify();
5854 tcb_ptr = osek_thread2tcb(p_thread);
5855 if (tcb_ptr == NULL)
5856 {
5857 return (E_OS_CALLEVEL);
5858 }
5859
5860 if ((tcb_ptr->osek_task_id != OSEK_ISR_ID))
5861 {
5862 /* This call is allowed only from ISR. */
5863 return (E_OS_CALLEVEL);
5864 }
5865
5866
5867 /* Check operating mode. */
5868 if ((osek_wrapper_operation_mode != ISR1_MODE) && (osek_wrapper_operation_mode != ISR2_MODE))
5869 {
5870 /* Hook toutines and alarm callbacks can't call this service. */
5871 /* This explicit check is required because all hook routines are
5872 executed in task's context. */
5873 return (E_OS_CALLEVEL);
5874 }
5875
5876 TX_DISABLE
5877
5878 /* Check if any resource is occupied. A task can not be terminated if it is holding any resource. */
5879 if(tcb_ptr->res_ocp != 0u)
5880 {
5881 TX_RESTORE
5882
5883 /* Return. */
5884 return (E_OS_RESOURCE);
5885 }
5886
5887 /* Release any internal resources held. */
5888 if (tcb_ptr->internal_res != 0u)
5889 {
5890 for (index = 0u; index < OSEK_MAX_INTERNAL_RES; index++)
5891 {
5892 if (tcb_ptr->internal_resource_occuplied_list[index] == 0u)
5893 {
5894 break;
5895 }
5896
5897 ((OSEK_RESOURCE *)(tcb_ptr->internal_resource_occuplied_list[index]))->taskid = 0u;
5898 tcb_ptr->internal_resource_occuplied_list[index] = 0u;
5899
5900 } /* End of for loop. */
5901 }
5902
5903 /* Now all set to terminate this task. */
5904 /* Send a message to the System Manager to terminate this task. */
5905 /* Build the request. */
5906
5907 request[0] = SYSMGR_TERMINATE_TASK; /* Request type. */
5908 request[1] = (ULONG)tcb_ptr; /* ID of the task to kill. */
5909 request[2] = 0u;
5910 request[3] = 0u;
5911
5912 /* Since the SysMgr supervisor thread has the highest priority, */
5913 /* this call will be preempted by SysMgr supervisor thread */
5914 /* SysMgr will eventually call osek_do_task_terminate and reschedule. */
5915
5916 status = tx_queue_send(&osek_work_queue, request, TX_NO_WAIT);
5917
5918 TX_RESTORE
5919
5920 /* This should always succeed. and Sys Manager terminates this task */
5921 /* This point will never be reached, as this thread itself will be */
5922 /* deleted by the system manager! */
5923 /* Still as a safety precaution enter system internal error loop. */
5924
5925 if (status != TX_SUCCESS)
5926 {
5927 osek_internal_error(SYS_MGR_SEND_TERMINATETASK);
5928 }
5929
5930 return (E_OK);
5931 }
5932
5933
5934 /**************************************************************************/
5935 /* */
5936 /* FUNCTION RELEASE */
5937 /* */
5938 /* osek_system_manager_entry PORTABLE C */
5939 /* 6.1.7 */
5940 /* AUTHOR */
5941 /* */
5942 /* William E. Lamie, Microsoft Corporation */
5943 /* */
5944 /* DESCRIPTION */
5945 /* */
5946 /* This is the System Manager thread for the OSEK. */
5947 /* All OSEK service calls that may cause rescheduling, ends up in */
5948 /* sending a message to a queue, and this highest priority thread */
5949 /* 'System Manager' reads this message and acts upon it. */
5950 /* It then calls the actual task scheduler which selects the next ready*/
5951 /* task from a queue of READY tasks. */
5952 /* After completing the request this routine returns back to read */
5953 /* next message which suspends this System Manager Thread and the task */
5954 /* selected by the task scheduler starts running. */
5955 /* */
5956 /* INPUT */
5957 /* */
5958 /* input Not used (Don't care) */
5959 /* */
5960 /* OUTPUT */
5961 /* */
5962 /* None */
5963 /* */
5964 /* CALLS */
5965 /* */
5966 /* tx_queue_receive Get message from ThreadX queue */
5967 /* osek_do_task_terminate Terminate the OSEK task. */
5968 /* osek_do_task_activate Activate the task */
5969 /* osek_internal_error OSEK internal error. */
5970 /* osek_do_delete_task Delete the OSEK task */
5971 /* pop_task_from_table Removes a task from the queue */
5972 /* tx_thread_suspend Suspends the calling task */
5973 /* add_task_to_table Adds a task to the TASK ready queue */
5974 /* start_osek_tasks Runs the next ready task from queue */
5975 /* */
5976 /* CALLED BY */
5977 /* */
5978 /* Wrapper Internal code (Not available to Application ) */
5979 /* */
5980 /* RELEASE HISTORY */
5981 /* */
5982 /* DATE NAME DESCRIPTION */
5983 /* */
5984 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
5985 /* */
5986 /**************************************************************************/
osek_system_manager_entry(ULONG input)5987 static void osek_system_manager_entry(ULONG input)
5988 {
5989 TX_THREAD *this_thread;
5990 OSEK_TCB *tcb_ptr;
5991 UINT status;
5992 StatusType osek_status;
5993 UINT i;
5994 UINT j;
5995 ULONG request[SYSMGR_QUEUE_MSG_LENGTH];
5996
5997
5998 /* The input argument 'input' is not needed , hence not used */
5999 /* This statement is added just to avoid compiler warning. */
6000 (void)&input;
6001
6002 /* Loop forever, waiting for any new message in the work queue. */
6003 for(;;)
6004 {
6005 /* Wait forever for the next work request. */
6006 status = tx_queue_receive(&osek_work_queue, &request, TX_WAIT_FOREVER);
6007
6008 /* Make sure we didn't encounter any trouble. */
6009 if (status != TX_SUCCESS)
6010 {
6011 osek_internal_error(SYSMGR_FATAL_ERROR);
6012 continue;
6013 }
6014
6015 /* Look at the first entry in the message for the request type. */
6016 switch(request[0u])
6017 {
6018 case SYSMGR_TERMINATE_TASK:
6019
6020 /* ISR ends up in terminating itself so there is no separate switch case
6021 for 'Return from ISR'. */
6022 /* As the task is terminated, remove it from the queue. */
6023 pop_task_from_table((OSEK_TCB *)request[1u]);
6024 /* Now Terminate the task. */
6025 osek_status = osek_do_task_terminate((OSEK_TCB *)request[1u]);
6026 if(osek_status != E_OK) {
6027 osek_internal_error(SYSMGR_FATAL_ERROR);
6028 }
6029
6030 task_terminated = TX_TRUE;
6031
6032 /* Enforce default operations mode. */
6033 osek_wrapper_operation_mode = NORMAL_EXECUTION_MODE;
6034
6035 break;
6036
6037
6038 case SYSMGR_CHAIN_TASK:
6039
6040 /* As calling task is terminated remove it from the queue. */
6041 pop_task_from_table ((OSEK_TCB *)request[1u]);
6042
6043 /* Now terminate the calling task. */
6044 osek_status = osek_do_task_terminate((OSEK_TCB *)request[1u]);
6045 if(osek_status != E_OK) {
6046 osek_internal_error(SYSMGR_FATAL_ERROR);
6047 }
6048
6049 task_terminated = TX_TRUE;
6050
6051 /* Now activate the task to be chained. */
6052 osek_status = osek_do_activate_task((OSEK_TCB *)request[2u]);
6053 if(osek_status != E_OK) {
6054 osek_internal_error(SYSMGR_FATAL_ERROR);
6055 }
6056
6057 break;
6058
6059 case SYSMGR_START_OS:
6060
6061 system_start = TX_TRUE; /* Indicates a fresh OS start. */
6062 disable_ISR2 = TX_FALSE;
6063 suspend_ISR2 = TX_FALSE;
6064
6065 /* OSEK started change init mode. */
6066 osek_init_state = OSEK_STARTED;
6067
6068 break;
6069
6070 case SYSMGR_ACTIVATE_TASK:
6071
6072 /* First suspend the calling task but if an ISR is activating a task then */
6073 /* no need to suspend ISR Task as rescheduling (if required) is done only */
6074 /* after ISR completes. With ISR calling this service the request[2] is */
6075 /* always a NULL. */
6076 if (request[2] != 0u)
6077 {
6078 this_thread = (TX_THREAD *)request[2];
6079 status = tx_thread_suspend(this_thread);
6080 if (status != TX_SUCCESS)
6081 {
6082 osek_internal_error(SYSMGR_FATAL_ERROR);
6083 }
6084 }
6085
6086 /* Now activate the requested task. */
6087 osek_status = osek_do_activate_task((OSEK_TCB *)request[1]);
6088 if(osek_status != E_OK) {
6089 osek_internal_error(SYSMGR_FATAL_ERROR);
6090 }
6091
6092 break;
6093
6094 case SYSMGR_RELEASE_RESOURCE:
6095
6096 tcb_ptr = (OSEK_TCB *)request[1];
6097
6098 /* First remove the task from its current queue position. */
6099 pop_task_from_table( tcb_ptr);
6100
6101 /* Now change this task prio to a new one after release res. */
6102 tcb_ptr->cur_threshold = (UINT)request[2];
6103
6104 /* Now move this task to its new position. */
6105 push_task_to_table(tcb_ptr);
6106
6107 /* Now suspend the calling task. */
6108 if (request[1u] != 0u)
6109 {
6110 this_thread = (TX_THREAD *)request[1];
6111 status = tx_thread_suspend(this_thread);
6112 if (status != TX_SUCCESS)
6113 {
6114 osek_internal_error(SYSMGR_FATAL_ERROR);
6115 }
6116 }
6117 break;
6118
6119 case SYSMGR_GET_RESOURCE:
6120
6121 tcb_ptr = (OSEK_TCB *)request[1];
6122
6123 /* First remove the task from its current queue position. */
6124 pop_task_from_table ( tcb_ptr);
6125
6126 /* Now change this task prio to a new one after release res. */
6127 tcb_ptr->cur_threshold = (UINT)request[2];
6128
6129 /* Now move this task to its new position. */
6130 push_task_to_table(tcb_ptr);
6131
6132 /* Now suspend the calling task. */
6133 if (request[1u] != 0u)
6134 {
6135 this_thread = (TX_THREAD *)request[1u];
6136 status = tx_thread_suspend(this_thread);
6137 if (status != TX_SUCCESS)
6138 {
6139 osek_internal_error(SYSMGR_FATAL_ERROR);
6140 }
6141 }
6142
6143 break;
6144
6145 case SYSMGR_SCHEDULE:
6146
6147 /* Get TCB for the calling task. */
6148 tcb_ptr = (OSEK_TCB *)request[1u];
6149
6150 /* Now release any internal resources held
6151 and move the task to its original priority queue. */
6152 osek_status = release_internal_resource(tcb_ptr);
6153 if(osek_status != E_OK) {
6154 osek_internal_error(SYSMGR_FATAL_ERROR);
6155 }
6156
6157 /* Suspend the calling task. */
6158 if (request[1u] != 0u)
6159 {
6160 this_thread = (TX_THREAD *)request[1u];
6161 status = tx_thread_suspend(this_thread);
6162 if (status != TX_SUCCESS)
6163 {
6164 osek_internal_error(SYSMGR_FATAL_ERROR);
6165 }
6166 }
6167
6168 break;
6169
6170 case SYSMGR_SETEVENT:
6171
6172 /* Add this out of wait state task to the ready queue as a newest member. */
6173 ((OSEK_TCB *)request[2u])->cur_threshold = ((OSEK_TCB *)request[2u])->org_prio;
6174
6175 add_task_to_table((OSEK_TCB *)request[2u]);
6176
6177 /* Suspend the calling task. */
6178 if (request[1u] != 0u)
6179 {
6180 this_thread = (TX_THREAD *)request[1u];
6181 status = tx_thread_suspend(this_thread);
6182 if (status != TX_SUCCESS)
6183 {
6184 osek_internal_error(SYSMGR_FATAL_ERROR);
6185 }
6186 }
6187
6188 break;
6189
6190 case SYSMGR_WAITEVENT:
6191
6192 /* Remove from the queue the task that went into waiting state. */
6193 pop_task_from_table((OSEK_TCB *)request[2u]);
6194
6195 /* Suspend it. */
6196 this_thread = (TX_THREAD *)request[1u];
6197
6198 status = tx_thread_suspend(this_thread);
6199 if (status != TX_SUCCESS)
6200 {
6201 osek_internal_error(SYSMGR_FATAL_ERROR);
6202 }
6203
6204 break;
6205
6206 case SYSMGR_SHUTDOWN_OS:
6207 /* System shut down, clear task queue. */
6208
6209 for (i = 0u; i < (OSEK_ISR1_PRIORITY + 1u); i++)
6210 {
6211 for (j = 0u; j < TASK_QUEUE_DEPTH; j++)
6212 {
6213 if (task_table[i][j] != 0u)
6214 {
6215 status = tx_thread_terminate((TX_THREAD *)(task_table[i][j]));
6216 if(status != TX_SUCCESS) {
6217 osek_internal_error(SYSMGR_FATAL_ERROR);
6218 }
6219 task_table [i][j] = 0u;
6220 }
6221 }
6222 }
6223
6224 return;
6225
6226 break;
6227
6228 case SYSMGR_ERRORHOOK:
6229 this_thread = (TX_THREAD *)request[1u];
6230
6231 /* Although an ERRORHOOK won't call any API Service that may cause
6232 rescheduling there could be an ISR logged while an Errorhook
6233 was executing, so Errorhook call ends up in sending a message to
6234 SYS manager to reschedule if necessary. */
6235
6236 /* Suspend the task causing Error condition. */
6237 status = tx_thread_suspend(this_thread);
6238 if (status != TX_SUCCESS)
6239 {
6240 osek_internal_error(SYSMGR_FATAL_ERROR);
6241 }
6242
6243 break;
6244
6245 default:
6246
6247 /* We should NEVER get here... call a fatal error. */
6248 /* System internal error. */
6249 osek_internal_error(SYSMGR_FATAL_ERROR);
6250
6251 break;
6252
6253 } /* End of switch. */
6254
6255 /* Now call scheduler to check for any preemption and resume. */
6256 start_osek_tasks();
6257
6258 } /* wile (1) System Manager forever loop. */
6259
6260 }
6261
6262
6263 /**************************************************************************/
6264 /* */
6265 /* FUNCTION RELEASE */
6266 /* */
6267 /* osek_memory_init PORTABLE C */
6268 /* 6.1.7 */
6269 /* AUTHOR */
6270 /* */
6271 /* William E. Lamie, Microsoft Corporation */
6272 /* */
6273 /* DESCRIPTION */
6274 /* */
6275 /* This function attempts to create a ThreadX byte pool that will */
6276 /* act as a "heap" for the OSEK dynamic internal objects */
6277 /* memory needs. */
6278 /* */
6279 /* INPUT */
6280 /* */
6281 /* region0_ptr OSEK memory pointer */
6282 /* */
6283 /* OUTPUT */
6284 /* */
6285 /* None */
6286 /* */
6287 /* CALLS */
6288 /* */
6289 /* tx_byte_pool_create Create region0 byte pool */
6290 /* osek_internal_error Internal OSEK error */
6291 /* */
6292 /* CALLED BY */
6293 /* */
6294 /* Start-up code */
6295 /* */
6296 /* RELEASE HISTORY */
6297 /* */
6298 /* DATE NAME DESCRIPTION */
6299 /* */
6300 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
6301 /* */
6302 /**************************************************************************/
osek_memory_init(void * region0_ptr)6303 static UINT osek_memory_init (void *region0_ptr)
6304 {
6305 UINT retval;
6306
6307 /* Create a ThreadX byte pool that will provide memory
6308 needed by the OSEK. */
6309 retval = tx_byte_pool_create((TX_BYTE_POOL *)&osek_region0_byte_pool,
6310 "OSEK REGION 0",
6311 region0_ptr,
6312 TX_REGION0_SIZE_IN_BYTES);
6313
6314 return (retval);
6315 }
6316
6317
6318 /**************************************************************************/
6319 /* */
6320 /* FUNCTION RELEASE */
6321 /* */
6322 /* osek_counter_init PORTABLE C */
6323 /* 6.1.7 */
6324 /* AUTHOR */
6325 /* */
6326 /* William E. Lamie, Microsoft Corporation */
6327 /* */
6328 /* DESCRIPTION */
6329 /* */
6330 /* This function sets up, configures and initializes all the */
6331 /* counter structures, which are defined at compile-time in order to */
6332 /* ensure that there is sufficient memory. */
6333 /* */
6334 /* INPUT */
6335 /* */
6336 /* None */
6337 /* */
6338 /* OUTPUT */
6339 /* */
6340 /* None */
6341 /* */
6342 /* CALLS */
6343 /* */
6344 /* osek_reset_counter Reset a Counters structure */
6345 /* */
6346 /* CALLED BY */
6347 /* */
6348 /* Start-up code */
6349 /* */
6350 /* RELEASE HISTORY */
6351 /* */
6352 /* DATE NAME DESCRIPTION */
6353 /* */
6354 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
6355 /* */
6356 /**************************************************************************/
osek_counter_init(void)6357 static void osek_counter_init(void)
6358 {
6359
6360 ULONG index;
6361
6362 /* Loop through array of semaphores and initialize each one. */
6363 for (index = 0u; index < OSEK_MAX_COUNTERS; index++)
6364 {
6365 osek_reset_counter(&(osek_counter_pool[index]));
6366 }
6367 }
6368
6369
6370 /**************************************************************************/
6371 /* */
6372 /* FUNCTION RELEASE */
6373 /* */
6374 /* osek_reset_counter PORTABLE C */
6375 /* 6.1.7 */
6376 /* AUTHOR */
6377 /* */
6378 /* William E. Lamie, Microsoft Corporation */
6379 /* */
6380 /* DESCRIPTION */
6381 /* */
6382 /* This function resets a counter structure. */
6383 /* */
6384 /* INPUT */
6385 /* */
6386 /* counter_ptr Counter pointer */
6387 /* */
6388 /* OUTPUT */
6389 /* */
6390 /* None */
6391 /* */
6392 /* CALLS */
6393 /* */
6394 /* None */
6395 /* */
6396 /* CALLED BY */
6397 /* */
6398 /* Start-up code */
6399 /* */
6400 /* RELEASE HISTORY */
6401 /* */
6402 /* DATE NAME DESCRIPTION */
6403 /* */
6404 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
6405 /* */
6406 /**************************************************************************/
osek_reset_counter(OSEK_COUNTER * counter_ptr)6407 static void osek_reset_counter(OSEK_COUNTER *counter_ptr)
6408 {
6409 TX_INTERRUPT_SAVE_AREA
6410 UINT index;
6411
6412 TX_DISABLE
6413
6414 /* This counter is now no longer in use. */
6415 counter_ptr->cntr_in_use = TX_FALSE;
6416
6417 /* Make any counter initial ticks to 0. */
6418 counter_ptr->counter_value = 0u;
6419
6420 /* Make max. allowable ticks to 0. */
6421 counter_ptr->maxallowedvalue = 0u;
6422
6423 /* Make no. of alarm repetition to 0. */
6424 counter_ptr->mincycle = 0u;
6425
6426 /* Make ticks per base = 1. */
6427 counter_ptr->ticksperbase = 1u;
6428
6429 /* Not attached yet to system timer. */
6430 counter_ptr->system_timer = TX_FALSE;
6431
6432 /* Clear alarm list. */
6433 for (index = 0u; index < OSEK_MAX_ALARMS; index++)
6434 {
6435 counter_ptr->alarm_list[index] = 0u;
6436 }
6437
6438 counter_ptr->osek_counter_id = 0u;
6439
6440 TX_RESTORE
6441
6442 return;
6443 }
6444
6445
6446 /**************************************************************************/
6447 /* */
6448 /* FUNCTION RELEASE */
6449 /* */
6450 /* osek_alarm_init PORTABLE C */
6451 /* 6.1.7 */
6452 /* AUTHOR */
6453 /* */
6454 /* William E. Lamie, Microsoft Corporation */
6455 /* */
6456 /* DESCRIPTION */
6457 /* */
6458 /* This function sets up, configures and initializes all the */
6459 /* alarm structures, which we define at compile-time in order to */
6460 /* ensure that there is sufficient memory. */
6461 /* */
6462 /* INPUT */
6463 /* */
6464 /* None */
6465 /* */
6466 /* OUTPUT */
6467 /* */
6468 /* None */
6469 /* */
6470 /* CALLS */
6471 /* */
6472 /* osek_reset_alarm */
6473 /* */
6474 /* CALLED BY */
6475 /* */
6476 /* Start-up code */
6477 /* */
6478 /* RELEASE HISTORY */
6479 /* */
6480 /* DATE NAME DESCRIPTION */
6481 /* */
6482 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
6483 /* */
6484 /**************************************************************************/
osek_alarm_init(void)6485 static void osek_alarm_init(void)
6486 {
6487
6488 ULONG index;
6489
6490 /* Loop through array of Semaphores and initialize each one. */
6491 for(index = 0u; index < OSEK_MAX_ALARMS; index++)
6492 {
6493 osek_reset_alarm(&(osek_alarm_pool[index]));
6494 }
6495 }
6496
6497
6498 /**************************************************************************/
6499 /* */
6500 /* FUNCTION RELEASE */
6501 /* */
6502 /* osek_reset_alarm PORTABLE C */
6503 /* 6.1.7 */
6504 /* AUTHOR */
6505 /* */
6506 /* William E. Lamie, Microsoft Corporation */
6507 /* */
6508 /* DESCRIPTION */
6509 /* */
6510 /* This function resets an alarm structure to its default state. */
6511 /* */
6512 /* INPUT */
6513 /* */
6514 /* alarm_ptr Alarm pointer */
6515 /* */
6516 /* OUTPUT */
6517 /* */
6518 /* None */
6519 /* */
6520 /* CALLS */
6521 /* */
6522 /* None */
6523 /* */
6524 /* CALLED BY */
6525 /* */
6526 /* Start-up code */
6527 /* */
6528 /* RELEASE HISTORY */
6529 /* */
6530 /* DATE NAME DESCRIPTION */
6531 /* */
6532 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
6533 /* */
6534 /**************************************************************************/
osek_reset_alarm(OSEK_ALARM * alarm_ptr)6535 static void osek_reset_alarm(OSEK_ALARM *alarm_ptr)
6536 {
6537 TX_INTERRUPT_SAVE_AREA
6538
6539 TX_DISABLE
6540
6541 /* First unarm the timer. */
6542 alarm_ptr->armed = TX_FALSE;
6543
6544 /* This alarm is now no longer in use. */
6545 alarm_ptr->alarm_in_use = TX_FALSE;
6546 alarm_ptr->occupied = TX_FALSE;
6547
6548 /* Make Call back function to TX_NULL. */
6549 alarm_ptr->alarm_callback = TX_NULL;
6550
6551 /* Make any counter reference to TX_NULL. */
6552 alarm_ptr->cntr = TX_NULL;
6553
6554 /* Make any task and event reference to TX_NULL. */
6555 alarm_ptr->task = TX_NULL;
6556 alarm_ptr->events = 0u;
6557 alarm_ptr->action = 0u;
6558
6559 /* Make its default value = 0. */
6560 alarm_ptr->max_allowed_value = 0u;
6561 alarm_ptr->min_cyc = 0u;
6562 alarm_ptr->cycle = 0u;
6563 alarm_ptr->expiration_count = 0u;
6564 alarm_ptr->auto_start = 0u;
6565
6566 alarm_ptr->osek_alarm_id = 0u;
6567
6568 TX_RESTORE
6569
6570 return;
6571 }
6572
6573
6574 /**************************************************************************/
6575 /* */
6576 /* FUNCTION RELEASE */
6577 /* */
6578 /* osek_tcb_init PORTABLE C */
6579 /* 6.1.7 */
6580 /* AUTHOR */
6581 /* */
6582 /* William E. Lamie, Microsoft Corporation */
6583 /* */
6584 /* DESCRIPTION */
6585 /* */
6586 /* This function sets up, configures and initializes all the */
6587 /* task control blocks, which are defined at compile-time in order to */
6588 /* ensure that there is sufficient memory. */
6589 /* */
6590 /* INPUT */
6591 /* */
6592 /* None */
6593 /* */
6594 /* OUTPUT */
6595 /* */
6596 /* None */
6597 /* */
6598 /* CALLS */
6599 /* */
6600 /* osek_reset_tcb Reset a task control block */
6601 /* */
6602 /* CALLED BY */
6603 /* */
6604 /* Start-up code */
6605 /* */
6606 /* RELEASE HISTORY */
6607 /* */
6608 /* DATE NAME DESCRIPTION */
6609 /* */
6610 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
6611 /* */
6612 /**************************************************************************/
osek_tcb_init(void)6613 static void osek_tcb_init(void)
6614 {
6615
6616 ULONG index;
6617
6618 /* Loop through array of TCBs and initialize each one. */
6619 for(index = 0u; index < OSEK_MAX_TASKS; index++)
6620 {
6621 osek_reset_tcb(&(osek_tcb_pool[index]));
6622 }
6623 }
6624
6625 /**************************************************************************/
6626 /* */
6627 /* FUNCTION RELEASE */
6628 /* */
6629 /* osek_resource_init PORTABLE C */
6630 /* 6.1.7 */
6631 /* AUTHOR */
6632 /* */
6633 /* William E. Lamie, Microsoft Corporation */
6634 /* */
6635 /* DESCRIPTION */
6636 /* */
6637 /* This function sets up, configures and initializes all the */
6638 /* resource structures, which are defined at compile-time in order to */
6639 /* ensure that there is sufficient memory. */
6640 /* */
6641 /* INPUT */
6642 /* */
6643 /* None */
6644 /* */
6645 /* OUTPUT */
6646 /* */
6647 /* None */
6648 /* */
6649 /* CALLS */
6650 /* */
6651 /* osek_reset_res Reset a semaphore structure */
6652 /* CreateResource Create the resource in OSEK */
6653 /* */
6654 /* CALLED BY */
6655 /* */
6656 /* Start-up code */
6657 /* */
6658 /* RELEASE HISTORY */
6659 /* */
6660 /* DATE NAME DESCRIPTION */
6661 /* */
6662 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
6663 /* */
6664 /**************************************************************************/
osek_resource_init(void)6665 static void osek_resource_init(void)
6666 {
6667
6668 ULONG index;
6669 OSEK_RESOURCE *res_ptr;
6670
6671
6672 /* Loop through array of resources and initialize each one. */
6673 for(index = 0u; index < OSEK_MAX_RES; index++)
6674 {
6675 osek_reset_res(&(osek_res_pool[index]));
6676 }
6677
6678 RES_SCHEDULER = CreateResource("RES_SCHEDULER", STANDARD, 0u);
6679 res_ptr = (OSEK_RESOURCE *)RES_SCHEDULER;
6680 res_ptr->c_priority = OSEK_NON_SCHEDULE_PRIORITY;
6681 }
6682
6683 /**************************************************************************/
6684 /* */
6685 /* FUNCTION RELEASE */
6686 /* */
6687 /* osek_reset_res PORTABLE C */
6688 /* 6.1.7 */
6689 /* AUTHOR */
6690 /* */
6691 /* William E. Lamie, Microsoft Corporation */
6692 /* */
6693 /* DESCRIPTION */
6694 /* */
6695 /* This function resets a resource a structure to its default state. */
6696 /* */
6697 /* INPUT */
6698 /* */
6699 /* res_ptr Resource pointer */
6700 /* */
6701 /* OUTPUT */
6702 /* */
6703 /* None */
6704 /* */
6705 /* CALLS */
6706 /* */
6707 /* None */
6708 /* */
6709 /* CALLED BY */
6710 /* */
6711 /* Start-up code */
6712 /* */
6713 /* RELEASE HISTORY */
6714 /* */
6715 /* DATE NAME DESCRIPTION */
6716 /* */
6717 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
6718 /* */
6719 /**************************************************************************/
osek_reset_res(OSEK_RESOURCE * res_ptr)6720 static void osek_reset_res(OSEK_RESOURCE *res_ptr)
6721 {
6722 TX_INTERRUPT_SAVE_AREA
6723
6724 TX_DISABLE
6725
6726 /* Indicate this entry is not in use. */
6727 res_ptr->res_in_use = TX_FALSE;
6728
6729 TX_RESTORE
6730
6731 return;
6732 }
6733
6734
6735 /**************************************************************************/
6736 /* */
6737 /* FUNCTION RELEASE */
6738 /* */
6739 /* osek_do_task_terminate PORTABLE C */
6740 /* 6.1.7 */
6741 /* AUTHOR */
6742 /* */
6743 /* William E. Lamie, Microsoft Corporation */
6744 /* */
6745 /* DESCRIPTION */
6746 /* */
6747 /* This function terminates the specified task. */
6748 /* */
6749 /* INPUT */
6750 /* */
6751 /* tcb_ptr Task to activate */
6752 /* */
6753 /* OUTPUT */
6754 /* */
6755 /* None If successful */
6756 /* Error Code. If an error occurs */
6757 /* */
6758 /* CALLS */
6759 /* */
6760 /* osek_internal_error Internal error */
6761 /* tx_thread_terminate Terminate the thread */
6762 /* tx_thread_create Create the thread */
6763 /* osek_reset_tcb Free the task control block */
6764 /* */
6765 /* CALLED BY */
6766 /* */
6767 /* OSEK only (internal) */
6768 /* */
6769 /* RELEASE HISTORY */
6770 /* */
6771 /* DATE NAME DESCRIPTION */
6772 /* */
6773 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
6774 /* */
6775 /**************************************************************************/
osek_do_task_terminate(OSEK_TCB * tcb_ptr)6776 static StatusType osek_do_task_terminate(OSEK_TCB *tcb_ptr)
6777 {
6778 TX_INTERRUPT_SAVE_AREA
6779 UINT retval;
6780 TX_THREAD *thread_ptr;
6781 UINT priority;
6782
6783
6784 /* Converts OSEK into ThreadX. */
6785 priority = osek_remap_priority(tcb_ptr->org_prio);
6786
6787 /* Make the current threshold as original priority. */
6788 tcb_ptr->cur_threshold = tcb_ptr->org_prio;
6789
6790 /* Get the ThreadX thread pointer. */
6791 thread_ptr = (TX_THREAD *)tcb_ptr;
6792
6793 /* Terminate the task's thread. */
6794 retval = tx_thread_terminate(thread_ptr);
6795
6796 /* See if every thing is fine. */
6797 if (retval != TX_SUCCESS)
6798 {
6799 /* System internal error. */
6800 osek_internal_error(THREADX_THREAD_TERMINATE_TERMINATETASK);
6801
6802 /* Error will be returned whenever the ThreadX call fails. */
6803 return (E_OS_SYSTEM);
6804 }
6805
6806 TX_DISABLE
6807
6808 /* Delete the ThreadX thread. */
6809 retval = tx_thread_delete(thread_ptr);
6810
6811 /* Check if everything is fine. */
6812 if (retval != TX_SUCCESS)
6813 {
6814 /* System internal error. */
6815 osek_internal_error(THREADX_THREAD_DELETE_TERMINATETASK);
6816
6817 /* Error will be returned whenever the ThreadX call fails. */
6818 return (E_OS_SYSTEM);
6819 }
6820
6821
6822 if (tcb_ptr->current_active != 0u)
6823 {
6824 /* Decrement the activation count. */
6825 tcb_ptr->current_active--;
6826 }
6827
6828 /* Now check if there is any activations pending? */
6829 if (tcb_ptr->current_active == 0u)
6830 {
6831 /* If no activations pending then make this task SUSPENDED. */
6832 tcb_ptr->suspended = TX_TRUE;
6833 }
6834
6835 TX_RESTORE
6836
6837 tcb_ptr->waiting = TX_FALSE;
6838
6839 /* Create ThreadX thread. */
6840 retval = tx_thread_create(thread_ptr,
6841 (char *)tcb_ptr->name,
6842 osek_task_wrapper,
6843 (ULONG)tcb_ptr,
6844 tcb_ptr->pStackBase,
6845 tcb_ptr->stack_size,
6846 priority,
6847 priority,
6848 TX_NO_TIME_SLICE,
6849 TX_DONT_START);
6850
6851 /* See if ThreadX encountered an error. */
6852 if (retval != TX_SUCCESS)
6853 {
6854 /* Free the task TCB structure. */
6855 osek_reset_tcb(tcb_ptr);
6856
6857 /* Internal error */
6858 osek_internal_error(THREADX_OBJECT_CREATION_ERROR);
6859
6860 /* Error will be returned whenever the ThreadX call fails. */
6861 return (E_OS_SYSTEM);
6862 }
6863
6864 /* Everything is OK. */
6865 return (E_OK);
6866 }
6867
6868
6869 /**************************************************************************/
6870 /* */
6871 /* FUNCTION RELEASE */
6872 /* */
6873 /* osek_do_activate_task PORTABLE C */
6874 /* 6.1.7 */
6875 /* AUTHOR */
6876 /* */
6877 /* William E. Lamie, Microsoft Corporation */
6878 /* */
6879 /* DESCRIPTION */
6880 /* */
6881 /* This function activates the specified task. */
6882 /* */
6883 /* INPUT */
6884 /* */
6885 /* *tcb_ptr task to activate */
6886 /* */
6887 /* OUTPUT */
6888 /* */
6889 /* None If successful */
6890 /* Error Code. If an error occurs. */
6891 /* */
6892 /* CALLS */
6893 /* */
6894 /* osek_internal_error Internal error */
6895 /* tx_thread_resume Activate the thread */
6896 /* */
6897 /* CALLED BY */
6898 /* */
6899 /* OSEK only (internal) */
6900 /* */
6901 /* RELEASE HISTORY */
6902 /* */
6903 /* DATE NAME DESCRIPTION */
6904 /* */
6905 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
6906 /* */
6907 /**************************************************************************/
osek_do_activate_task(OSEK_TCB * tcb_ptr)6908 static StatusType osek_do_activate_task (OSEK_TCB *tcb_ptr)
6909 {
6910 TX_INTERRUPT_SAVE_AREA
6911 /* Activate a task means making it READY and place into the TASK READY queue. */
6912
6913 TX_DISABLE
6914 /* Increment current multiple activation count. */
6915 tcb_ptr->current_active++ ;
6916
6917 /* Move this task from suspended state to ready state. */
6918 tcb_ptr->suspended = TX_FALSE;
6919
6920 /* And add to the queue as a newest member. */
6921 add_task_to_table(tcb_ptr);
6922
6923 TX_RESTORE;
6924
6925 return (E_OK);
6926 }
6927
6928
6929 /**************************************************************************/
6930 /* */
6931 /* FUNCTION RELEASE */
6932 /* */
6933 /* osek_thread2tcb PORTABLE C */
6934 /* 6.1.7 */
6935 /* AUTHOR */
6936 /* */
6937 /* William E. Lamie, Microsoft Corporation */
6938 /* */
6939 /* DESCRIPTION */
6940 /* */
6941 /* This function returns a ThreadX thread pointer to an OSEK task */
6942 /* pointer. */
6943 /* */
6944 /* INPUT */
6945 /* */
6946 /* thread Thread pointer */
6947 /* */
6948 /* OUTPUT */
6949 /* */
6950 /* *tcb TCB pointer */
6951 /* On error a null pointer is returned */
6952 /* */
6953 /* CALLS */
6954 /* */
6955 /* None */
6956 /* */
6957 /* CALLED BY */
6958 /* */
6959 /* Internal Code */
6960 /* */
6961 /* RELEASE HISTORY */
6962 /* */
6963 /* DATE NAME DESCRIPTION */
6964 /* */
6965 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
6966 /* */
6967 /**************************************************************************/
osek_thread2tcb(TX_THREAD * thread_ptr)6968 static OSEK_TCB *osek_thread2tcb(TX_THREAD *thread_ptr)
6969 {
6970
6971 OSEK_TCB *tcb;
6972
6973 /* Make sure we were called from a thread. */
6974 if (thread_ptr == TX_NULL)
6975 {
6976 /* Communicate error by means of a NULL pointer. */
6977 return ((OSEK_TCB *)0u);
6978 }
6979
6980 /* We can do this because the Thread information is intentionally
6981 located as the first field in the structure. */
6982 tcb = (OSEK_TCB *)thread_ptr;
6983
6984 /* All done. */
6985 return (tcb);
6986 }
6987
6988
6989 /**************************************************************************/
6990 /* */
6991 /* FUNCTION RELEASE */
6992 /* */
6993 /* osek_task_independent_area PORTABLE C */
6994 /* 6.1.7 */
6995 /* AUTHOR */
6996 /* */
6997 /* William E. Lamie, Microsoft Corporation */
6998 /* */
6999 /* DESCRIPTION */
7000 /* */
7001 /* This function determines if the system is currently in a thread */
7002 /* context, i.e. not timer routine, not ISR, not idling, */
7003 /* not in initialization phase. */
7004 /* */
7005 /* INPUT */
7006 /* */
7007 /* None */
7008 /* */
7009 /* OUTPUT */
7010 /* */
7011 /* TX_TRUE If in task area */
7012 /* TX_FALSE If not in task area */
7013 /* */
7014 /* CALLS */
7015 /* */
7016 /* None */
7017 /* */
7018 /* CALLED BY */
7019 /* */
7020 /* osek internal code */
7021 /* */
7022 /* RELEASE HISTORY */
7023 /* */
7024 /* DATE NAME DESCRIPTION */
7025 /* */
7026 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
7027 /* */
7028 /**************************************************************************/
osek_task_independent_area(void)7029 static ULONG osek_task_independent_area(void)
7030 {
7031
7032 if (osek_init_state != OSEK_STARTED)
7033 {
7034
7035 /* We are calling from initialization, return FALSE. */
7036 return (TX_FALSE);
7037 }
7038 else if ((_tx_thread_current_ptr == TX_NULL) || /* Not in a thread. */
7039 (_tx_thread_system_state != 0u) || /* In an ISR. */
7040 (_tx_thread_current_ptr == &_tx_timer_thread)) /* Timer routine. */
7041
7042 {
7043 /* We are NOT in thread (task) context. */
7044 return (TX_FALSE);
7045 }
7046 else
7047 {
7048 /* We ARE in thread (task) context. */
7049 return (TX_TRUE);
7050 }
7051 }
7052
7053
7054 /**************************************************************************/
7055 /* */
7056 /* FUNCTION RELEASE */
7057 /* */
7058 /* osek_create_task PORTABLE C */
7059 /* 6.1.7 */
7060 /* AUTHOR */
7061 /* */
7062 /* William E. Lamie, Microsoft Corporation */
7063 /* */
7064 /* DESCRIPTION */
7065 /* */
7066 /* This function creates an OSEK task under ThreadX. */
7067 /* */
7068 /* INPUT */
7069 /* */
7070 /* tcb_ptr Task control block pointer */
7071 /* */
7072 /* OUTPUT */
7073 /* */
7074 /* E_OK If successful */
7075 /* E_OS_SYSTEM If failure */
7076 /* */
7077 /* CALLS */
7078 /* */
7079 /* osek_tcb2thread Convert TCB to thread */
7080 /* tx_thread_create Create thread */
7081 /* osek_reset_tcb OSEK free task control block */
7082 /* add_task_to_table Add this task to queue */
7083 /* */
7084 /* CALLED BY */
7085 /* */
7086 /* OSEK only (internal) */
7087 /* */
7088 /* RELEASE HISTORY */
7089 /* */
7090 /* DATE NAME DESCRIPTION */
7091 /* */
7092 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
7093 /* */
7094 /**************************************************************************/
osek_create_task(OSEK_TCB * tcb_ptr)7095 static StatusType osek_create_task(OSEK_TCB * tcb_ptr)
7096 {
7097
7098 TX_INTERRUPT_SAVE_AREA
7099
7100 UINT retval;
7101 UINT priority;
7102
7103 TX_DISABLE
7104
7105 /* Converts OSEK priority into ThreadX. In ThreadX '0' is highest priority and '31' is the lowest
7106 while in OSEK it is exactly the opposite. */
7107
7108 priority = osek_remap_priority(tcb_ptr->org_prio);
7109
7110 /* Create a ThreadX thread, osek_task_wrapper is the entry function which is common for all thread
7111 implementing an OSEK task to differentiate which task we supply 'task id' as an input for
7112 thread entry function. */
7113
7114 retval = tx_thread_create ( &(tcb_ptr->task),
7115 (char *)tcb_ptr->name,
7116 osek_task_wrapper,
7117 (ULONG)tcb_ptr,
7118 tcb_ptr->pStackBase,
7119 tcb_ptr->stack_size,
7120 priority,
7121 priority,
7122 TX_NO_TIME_SLICE,
7123 TX_DONT_START); /* All threads implementing an OSEK TASK are created in SUSPENDED state. */
7124
7125 /* Check for any error. */
7126 if (retval != TX_SUCCESS)
7127 {
7128 /* Free the task tcb structure. */
7129 osek_reset_tcb(tcb_ptr);
7130
7131 /* Internal error. */
7132 osek_internal_error(THREADX_OBJECT_CREATION_ERROR);
7133
7134 /* Error will be returned whenever the ThreadX call fails. */
7135 retval = E_OS_SYSTEM;
7136 }
7137 else
7138 {
7139 /* Got the thread, now check AUTO START Specified for this task. */
7140 /* If the task is not specified as 'AUTO RUN' then it is not in 'READY' State,
7141 so won't be added to task queue at this stage. */
7142
7143 if (tcb_ptr->task_autostart == TRUE)
7144 {
7145 /* With AUTO START the task will attain READY state
7146 the moment it is created, whether it will execute (RUN) will depend on Scheduler. */
7147
7148 tcb_ptr->suspended = TX_FALSE;
7149
7150 /* As this task will be in Ready immediately after creation its
7151 Current activation counter must be increment to 1 from 0. */
7152 tcb_ptr->current_active = 1u;
7153
7154 /* Now add this task to Schedulers 'READY' task queue. */
7155 add_task_to_table(tcb_ptr);
7156 }
7157
7158 /* Everything is fine. */
7159 retval = E_OK;
7160 }
7161
7162
7163 TX_RESTORE
7164
7165 return(retval);
7166 }
7167
7168
7169 /**************************************************************************/
7170 /* */
7171 /* FUNCTION RELEASE */
7172 /* */
7173 /* osek_allocate_tcb PORTABLE C */
7174 /* 6.1.7 */
7175 /* AUTHOR */
7176 /* */
7177 /* William E. Lamie, Microsoft Corporation */
7178 /* */
7179 /* DESCRIPTION */
7180 /* */
7181 /* This function attempts to allocate memory for a task stack and an */
7182 /* OSEK Thread Control Block (TCB). */
7183 /* */
7184 /* INPUT */
7185 /* */
7186 /* stack_size Requested task stack size */
7187 /* tcb_ptr Pointer to tcb pointer */
7188 /* */
7189 /* OUTPUT */
7190 /* */
7191 /* TX_TRUE If successful. */
7192 /* TX_FALSE If an error occurs. */
7193 /* */
7194 /* CALLS */
7195 /* */
7196 /* osek_memory_allocate Allocate task's stack */
7197 /* osek_reset_tcb Free task control block */
7198 /* */
7199 /* CALLED BY */
7200 /* */
7201 /* OSEK internal code */
7202 /* */
7203 /* RELEASE HISTORY */
7204 /* */
7205 /* DATE NAME DESCRIPTION */
7206 /* */
7207 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
7208 /* */
7209 /**************************************************************************/
osek_allocate_tcb(ULONG stack_size,OSEK_TCB ** tcb_ptr)7210 static ULONG osek_allocate_tcb(ULONG stack_size, OSEK_TCB **tcb_ptr)
7211 {
7212 OSEK_TCB * tcb;
7213 ULONG index;
7214 ULONG retval;
7215
7216 /* Assume the worst. */
7217 tcb = (OSEK_TCB *)TX_NULL;
7218
7219 /* This next search is optimized for simplicity, not speed. */
7220 tcb = osek_tcb_pool;
7221 for (index = 0u; index < OSEK_MAX_TASKS; index++)
7222 {
7223 /* Is thisTCB in use? If not, we can use it. */
7224 if (tcb->tcb_in_use == TX_FALSE)
7225 {
7226 /* This TCB is now in use. */
7227 tcb->tcb_in_use = TX_TRUE;
7228
7229 /* Stop searching. */
7230 break;
7231 }
7232
7233 tcb++;
7234 } /* try next TCB. */
7235
7236 /* Did we search all TCBs and come up empty? */
7237 if (index == OSEK_MAX_TASKS)
7238 {
7239 /* No more TCBs available - user configuration error. */
7240 return(E_OS_SYS_STACK);
7241 }
7242 else
7243 {
7244 /* Found one. */
7245 *tcb_ptr = tcb;
7246 }
7247
7248 /* Reset stack pointer. */
7249 tcb->pStackBase = (CHAR *)TX_NULL;
7250
7251 /* Allocate memory for the task stack. */
7252 retval = osek_memory_allocate(stack_size,
7253 ((void **)&(tcb->pStackBase)));
7254
7255 /* Make sure we got the memory for the task stack. */
7256 if ((retval == 0u) || (tcb->pStackBase == TX_NULL))
7257 {
7258 /* Failed - at least try to return the OSEK TCB memory. */
7259 osek_reset_tcb(tcb);
7260
7261 /* Indicate failure. */
7262 return (E_OS_SYS_STACK);
7263 }
7264
7265 /* Remember the size of the stack. */
7266 tcb->stack_size = stack_size;
7267
7268 /* Return OSEK TCB to caller. */
7269 return (TX_TRUE);
7270 }
7271
7272
7273 /**************************************************************************/
7274 /* */
7275 /* FUNCTION RELEASE */
7276 /* */
7277 /* osek_memory_allocate PORTABLE C */
7278 /* 6.1.7 */
7279 /* AUTHOR */
7280 /* */
7281 /* William E. Lamie, Microsoft Corporation */
7282 /* */
7283 /* DESCRIPTION */
7284 /* */
7285 /* This function attempts to obtain the specified amount of memory */
7286 /* from the OSEK heap. */
7287 /* */
7288 /* INPUT */
7289 /* */
7290 /* size Number of bytes to allocate */
7291 /* memory_ptr Pointer to the returned */
7292 /* memory */
7293 /* */
7294 /* OUTPUT */
7295 /* */
7296 /* TX_TRUE If successful */
7297 /* TX_FALSE If an error occurs */
7298 /* */
7299 /* CALLS */
7300 /* */
7301 /* tx_byte_allocate Allocate from the pool */
7302 /* */
7303 /* CALLED BY */
7304 /* */
7305 /* OSEK internal code */
7306 /* */
7307 /* RELEASE HISTORY */
7308 /* */
7309 /* DATE NAME DESCRIPTION */
7310 /* */
7311 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
7312 /* */
7313 /**************************************************************************/
osek_memory_allocate(ULONG size,void ** memory_ptr)7314 static UINT osek_memory_allocate(ULONG size, void **memory_ptr)
7315 {
7316 ULONG size_align;
7317 UINT retval;
7318
7319 /* Initialize the pointer to NULL in case we fail. */
7320 *memory_ptr = (void *)TX_NULL;
7321
7322 /* Force all alignments to long word boundaries to be safe. */
7323 size_align = size;
7324 if ((size_align) != 0u)
7325 {
7326 /* Bump size up to next 4 byte boundary. */
7327 size_align = ((size_align + 0x03u) & ~0x03u);
7328 }
7329
7330 /* Attempt to allocate the desired memory from the OSEK heap. */
7331 /* Do not wait - if memory isn't available, flag an error. */
7332 retval = tx_byte_allocate((TX_BYTE_POOL *)&osek_region0_byte_pool, memory_ptr,
7333 size_align, TX_NO_WAIT);
7334
7335 /* Make sure the memory was obtained successfully. */
7336 if(retval != TX_SUCCESS)
7337 {
7338 /* Error obtaining memory. */
7339 return (TX_FALSE);
7340 }
7341
7342 /* Return to caller. */
7343 return (TX_TRUE);
7344 }
7345
7346
7347 /**************************************************************************/
7348 /* */
7349 /* FUNCTION RELEASE */
7350 /* */
7351 /* osek_reset_tcb PORTABLE C */
7352 /* 6.1.7 */
7353 /* AUTHOR */
7354 /* */
7355 /* William E. Lamie, Microsoft Corporation */
7356 /* */
7357 /* DESCRIPTION */
7358 /* */
7359 /* This function resets a task TCB to its default state. */
7360 /* */
7361 /* INPUT */
7362 /* */
7363 /* tcb Task control block pointer */
7364 /* */
7365 /* OUTPUT */
7366 /* */
7367 /* None */
7368 /* */
7369 /* CALLS */
7370 /* */
7371 /* None */
7372 /* */
7373 /* CALLED BY */
7374 /* */
7375 /* Start-up code */
7376 /* */
7377 /* RELEASE HISTORY */
7378 /* */
7379 /* DATE NAME DESCRIPTION */
7380 /* */
7381 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
7382 /* */
7383 /**************************************************************************/
osek_reset_tcb(OSEK_TCB * tcb_ptr)7384 static void osek_reset_tcb(OSEK_TCB *tcb_ptr)
7385 {
7386 TX_INTERRUPT_SAVE_AREA
7387
7388 UINT index;
7389
7390 /* Disable interrupt. */
7391 TX_DISABLE
7392
7393 /* Indicate this TCB is not in use. */
7394 tcb_ptr->tcb_in_use = TX_FALSE;
7395
7396 /* Make suspended and waiting to FALSE. */
7397 tcb_ptr->suspended = TX_TRUE;
7398 tcb_ptr->waiting = TX_FALSE;
7399
7400 /* Make this task as BASIC. */
7401 tcb_ptr->task_type = BASIC;
7402
7403 /* No AUTOSTART */
7404 tcb_ptr->task_autostart = 0u;
7405
7406 /* Erase TCB id */
7407 tcb_ptr->osek_task_id = 0u;
7408
7409 /* Make original priority of the task to 0 (the lowest possible). */
7410 tcb_ptr->org_prio = 0u;
7411
7412 /* Set the thread preemption threshold to default. */
7413 tcb_ptr->cur_threshold = THREADX_LOWEST_PRIORITY;
7414
7415 /* Make the stack size to 0. */
7416 tcb_ptr->stack_size = 0u;
7417
7418 /* No task to chain. */
7419 tcb_ptr->task_to_chain = 0u;
7420
7421 /* Since now event is not attached Make it to TX_NULL. */
7422 tcb_ptr->events = 0u;
7423
7424 /* Make task entry function to TX_NULL. */
7425 tcb_ptr->task_entry = TX_NULL;
7426
7427 /* Make maximum activation to 0. */
7428 tcb_ptr->max_active = 0u;
7429
7430 /* Make current activation to 0. */
7431 tcb_ptr->current_active = 0u;
7432
7433 /* Clear lists for external Resource attached and Resource occupied. */
7434 for (index = 0u; index < OSEK_MAX_EXTERNAL_RES; index++)
7435 {
7436 tcb_ptr->external_resource_list[index] = 0u;
7437 tcb_ptr->external_resource_occuplied_list[index] = 0u;
7438 }
7439
7440 /* Clear lists for Internal Resource attached and resource occupied. */
7441 for (index = 0u; index < OSEK_MAX_INTERNAL_RES; index++)
7442 {
7443 tcb_ptr->internal_resource_list[index] = 0u;
7444 tcb_ptr->internal_resource_occuplied_list[index] = 0u;
7445 }
7446
7447 /* Since resource is not occupied make it to FALSE. */
7448 tcb_ptr->res_ocp = 0u;
7449
7450 /* All done. */
7451
7452 /* Enable interrupt. */
7453 TX_RESTORE
7454
7455 return;
7456 }
7457
7458
7459 /**************************************************************************/
7460 /* */
7461 /* FUNCTION RELEASE */
7462 /* */
7463 /* osek_get_resource PORTABLE C */
7464 /* 6.1.7 */
7465 /* AUTHOR */
7466 /* */
7467 /* William E. Lamie, Microsoft Corporation */
7468 /* */
7469 /* DESCRIPTION */
7470 /* */
7471 /* This function finds if any resource is available in the pool. */
7472 /* */
7473 /* INPUT */
7474 /* */
7475 /* tcb Task control block pointer */
7476 /* */
7477 /* OUTPUT */
7478 /* */
7479 /* res_ptr Resource pointer OR null */
7480 /* */
7481 /* CALLS */
7482 /* */
7483 /* None */
7484 /* */
7485 /* CALLED BY */
7486 /* */
7487 /* Start-up code */
7488 /* */
7489 /* RELEASE HISTORY */
7490 /* */
7491 /* DATE NAME DESCRIPTION */
7492 /* */
7493 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
7494 /* */
7495 /**************************************************************************/
osek_get_resource(void)7496 static ResourceType osek_get_resource(void)
7497 {
7498 TX_INTERRUPT_SAVE_AREA
7499 ULONG index;
7500 OSEK_RESOURCE *res_ptr;
7501
7502 TX_DISABLE
7503
7504 /* Start out pessimistic - assume we won't find a match. */
7505 res_ptr = (OSEK_RESOURCE *)TX_NULL;
7506
7507 /* Search the resource from resource pool. */
7508 res_ptr = &(osek_res_pool[0u]);
7509 for (index = 0u; index < OSEK_MAX_RES; index++)
7510 {
7511 /* Make sure the resource is not already in use. */
7512 if (res_ptr->res_in_use == TX_FALSE)
7513 {
7514 /* This Resource is now in use. */
7515 res_ptr->res_in_use = TX_TRUE;
7516 break;
7517 }
7518
7519 res_ptr++;
7520 }
7521
7522 TX_RESTORE
7523
7524 /* Did we search all OSEK RESOURCES and come up empty? */
7525 if (index == OSEK_MAX_RES)
7526 {
7527 return ((ResourceType) TX_NULL);
7528 }
7529
7530 return ((ResourceType) res_ptr);
7531 }
7532
7533
7534 /**************************************************************************/
7535 /* */
7536 /* FUNCTION RELEASE */
7537 /* */
7538 /* osek_get_alarm PORTABLE C */
7539 /* 6.1.7 */
7540 /* AUTHOR */
7541 /* */
7542 /* William E. Lamie, Microsoft Corporation */
7543 /* */
7544 /* DESCRIPTION */
7545 /* */
7546 /* This function gets an alarm if it is available. */
7547 /* */
7548 /* INPUT */
7549 /* */
7550 /* NONE */
7551 /* */
7552 /* OUTPUT */
7553 /* */
7554 /* ALARM_ID AlarmID if found */
7555 /* TX_FALSE If not available */
7556 /* */
7557 /* CALLS */
7558 /* */
7559 /* NONE */
7560 /* */
7561 /* CALLED BY */
7562 /* */
7563 /* API function. */
7564 /* */
7565 /* RELEASE HISTORY */
7566 /* */
7567 /* DATE NAME DESCRIPTION */
7568 /* */
7569 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
7570 /* */
7571 /**************************************************************************/
osek_get_alarm(void)7572 static UINT osek_get_alarm(void)
7573 {
7574 TX_INTERRUPT_SAVE_AREA
7575 OSEK_ALARM *this_alarm;
7576 UINT index;
7577
7578 TX_DISABLE
7579
7580 /* Assume the worst. */
7581 this_alarm = (OSEK_ALARM *)TX_NULL;
7582
7583 /* Search for a free alarm. */
7584 this_alarm = osek_alarm_pool;
7585
7586 for (index = 0u;
7587 index < OSEK_MAX_ALARMS;
7588 index++)
7589 {
7590 /* Is this alarm in use? If not, we can use it. */
7591 if (this_alarm->alarm_in_use == TX_FALSE)
7592 {
7593 /* This alarm is now in use. */
7594 this_alarm->alarm_in_use = TX_TRUE;
7595
7596 /* Stop searching. */
7597 break;
7598 }
7599
7600 this_alarm++;
7601 } /* check next if this one is in use. */
7602
7603 TX_RESTORE
7604
7605 /* Did we search alarms all and come up empty? */
7606 if (index == OSEK_MAX_ALARMS)
7607 {
7608 /* No more alarms available - user configuration error. */
7609 return ((AlarmType)0u);
7610 }
7611
7612 /* Found one. */
7613
7614 return ((AlarmType) this_alarm);
7615 }
7616
7617
7618 /**************************************************************************/
7619 /* */
7620 /* FUNCTION RELEASE */
7621 /* */
7622 /* osek_get_events PORTABLE C */
7623 /* 6.1.7 */
7624 /* AUTHOR */
7625 /* */
7626 /* William E. Lamie, Microsoft Corporation */
7627 /* */
7628 /* DESCRIPTION */
7629 /* */
7630 /* This function gets events if it is available in the pool. */
7631 /* */
7632 /* INPUT */
7633 /* */
7634 /* NONE */
7635 /* */
7636 /* OUTPUT */
7637 /* */
7638 /* COUNTER_ID CounterID if found */
7639 /* TX_FALSE if not available */
7640 /* */
7641 /* CALLS */
7642 /* */
7643 /* NONE */
7644 /* */
7645 /* CALLED BY */
7646 /* */
7647 /* API function */
7648 /* */
7649 /* RELEASE HISTORY */
7650 /* */
7651 /* DATE NAME DESCRIPTION */
7652 /* */
7653 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
7654 /* */
7655 /**************************************************************************/
osek_get_event(void)7656 static EventMaskType osek_get_event(void)
7657 {
7658 TX_INTERRUPT_SAVE_AREA
7659 EventMaskType event_mask;
7660
7661 TX_DISABLE
7662
7663 if (global_event_count >= OSEK_MAX_EVENTS)
7664 {
7665 TX_RESTORE
7666
7667 /* Already alloted all possible events. */
7668 return ((EventMaskType)0u);
7669 }
7670
7671 /* Next event. */
7672 event_mask = 1u;
7673 event_mask <<= global_event_count;
7674 global_event_count++;
7675
7676 TX_RESTORE
7677
7678 return (event_mask);
7679 }
7680
7681
7682 /**************************************************************************/
7683 /* */
7684 /* FUNCTION RELEASE */
7685 /* */
7686 /* osek_get_alarm PORTABLE C */
7687 /* 6.1.7 */
7688 /* AUTHOR */
7689 /* */
7690 /* William E. Lamie, Microsoft Corporation */
7691 /* */
7692 /* DESCRIPTION */
7693 /* */
7694 /* This function gets an alarm if it is available. */
7695 /* */
7696 /* INPUT */
7697 /* */
7698 /* NONE */
7699 /* */
7700 /* OUTPUT */
7701 /* */
7702 /* COUNTER_ID CounterID if found */
7703 /* TX_FALSE If not available */
7704 /* */
7705 /* CALLS */
7706 /* */
7707 /* NONE */
7708 /* */
7709 /* CALLED BY */
7710 /* */
7711 /* API function */
7712 /* */
7713 /* RELEASE HISTORY */
7714 /* */
7715 /* DATE NAME DESCRIPTION */
7716 /* */
7717 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
7718 /* */
7719 /**************************************************************************/
osek_get_counter(void)7720 static CounterType osek_get_counter(void)
7721 {
7722 TX_INTERRUPT_SAVE_AREA
7723 OSEK_COUNTER *this_counter;
7724 UINT index;
7725
7726 TX_DISABLE
7727
7728 /* Assume the worst. */
7729 this_counter = (OSEK_COUNTER *)TX_NULL;
7730
7731 /* Search for a free counter. */
7732 this_counter = osek_counter_pool;
7733 for ( index = 0u;
7734 index < OSEK_MAX_COUNTERS;
7735 index++)
7736 {
7737 /* Is this guy in use? If not, we can use it. */
7738 if (this_counter->cntr_in_use == TX_FALSE)
7739 {
7740 /* This counter is now in use. */
7741 this_counter->cntr_in_use = TX_TRUE;
7742 /* Stop searching. */
7743 break;
7744 }
7745
7746 this_counter++;
7747 } /* Try next counter. */
7748
7749 TX_RESTORE
7750
7751 /* Did we search all OSEK COUNTERS and come up empty? */
7752 if (index >= OSEK_MAX_COUNTERS)
7753 {
7754 /* No more Counters available - user configuration error. */
7755 return ((CounterType) E_OS_SYS_STACK);
7756 }
7757
7758 /* Found one. */
7759 return ((CounterType)this_counter);
7760 }
7761
7762
7763 /**************************************************************************/
7764 /* */
7765 /* FUNCTION RELEASE */
7766 /* */
7767 /* osek_system_timer_entry PORTABLE C */
7768 /* 6.1.7 */
7769 /* AUTHOR */
7770 /* */
7771 /* William E. Lamie, Microsoft Corporation */
7772 /* */
7773 /* DESCRIPTION */
7774 /* */
7775 /* This wrapper acts as a system timer and maintains a system counter */
7776 /* It is up to the user to assign any one of the OSEK counter as */
7777 /* a system counter by defining it. */
7778 /* This counter will then be updated by this system timer. */
7779 /* */
7780 /* INPUT */
7781 /* */
7782 /* input Not used */
7783 /* */
7784 /* OUTPUT */
7785 /* */
7786 /* None */
7787 /* */
7788 /* CALLS */
7789 /* */
7790 /* CALLED BY */
7791 /* */
7792 /* OSEK system timer expiry function */
7793 /* */
7794 /* RELEASE HISTORY */
7795 /* */
7796 /* DATE NAME DESCRIPTION */
7797 /* */
7798 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
7799 /* */
7800 /**************************************************************************/
osek_system_timer_entry(ULONG input)7801 static void osek_system_timer_entry(ULONG input)
7802 {
7803 TX_INTERRUPT_SAVE_AREA
7804 OSEK_COUNTER *this_counter;
7805 UINT index;
7806 UINT found;
7807
7808 TX_DISABLE
7809
7810 (void)&input; /* Prevent unused parameter warnings. */
7811
7812 found = TX_FALSE;
7813 /* Search for a counter acting as a system counter. */
7814 this_counter = osek_counter_pool;
7815 for ( index = 0u;
7816 index < OSEK_MAX_COUNTERS;
7817 index++)
7818 {
7819 /* Is this guy in a system counter. */
7820 if (this_counter->system_timer == TX_TRUE)
7821 {
7822 /* Got system counter. */
7823 found = TX_TRUE;
7824 /* Stop searching. */
7825 break;
7826 }
7827
7828 this_counter++;
7829 } /* Try next counter. */
7830
7831 /* Did we search all OSEK COUNTERS and come up empty? */
7832 if (found == TX_TRUE)
7833 {
7834 /* Got a system counter, update it. */
7835 IncrCounter((CounterType)this_counter);
7836 }
7837
7838 TX_RESTORE
7839
7840 return;
7841 }
7842
7843
7844 /**************************************************************************/
7845 /* */
7846 /* FUNCTION RELEASE */
7847 /* */
7848 /* osek_remap_priority PORTABLE C */
7849 /* 6.1.7 */
7850 /* AUTHOR */
7851 /* */
7852 /* William E. Lamie, Microsoft Corporation */
7853 /* */
7854 /* DESCRIPTION */
7855 /* */
7856 /* This function converts a OSEK task priority into a ThreadX */
7857 /* priority. */
7858 /* */
7859 /* INPUT */
7860 /* */
7861 /* osek_priority Priority of task */
7862 /* */
7863 /* OUTPUT */
7864 /* */
7865 /* ThreadX priority Converted priority */
7866 /* */
7867 /* CALLS */
7868 /* */
7869 /* None */
7870 /* */
7871 /* CALLED BY */
7872 /* */
7873 /* OSEK internal code */
7874 /* */
7875 /* RELEASE HISTORY */
7876 /* */
7877 /* DATE NAME DESCRIPTION */
7878 /* */
7879 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
7880 /* */
7881 /**************************************************************************/
osek_remap_priority(UINT osek_priority)7882 static UINT osek_remap_priority(UINT osek_priority)
7883 {
7884
7885 /* Remap OSEK task priority to ThreadX thread priority. */
7886 /* In OSEK 0 = lowest priority and in ThreadX, 0 = highest priority, */
7887 /* Means ThreadX priority of a thread acting as a OSEK Task */
7888 /* would be ThreadX max priority - osek_priority. */
7889
7890 /* Return the ThreadX priority. */
7891 return (THREADX_MAX_PRIORITY - 1u - osek_priority);
7892 }
7893
7894
7895 /**************************************************************************/
7896 /* */
7897 /* FUNCTION RELEASE */
7898 /* */
7899 /* osek_task_wrapper PORTABLE C */
7900 /* 6.1.7 */
7901 /* AUTHOR */
7902 /* */
7903 /* William E. Lamie, Microsoft Corporation */
7904 /* */
7905 /* DESCRIPTION */
7906 /* */
7907 /* Every thread that is modeling a OSEK task uses this routine has */
7908 /* its entry point. This routine calls the OSEK task entry function. */
7909 /* */
7910 /* A task must end with either TerminateTask() or ChainTask(), if this */
7911 /* is not the way a task is ended, the control will come back to this */
7912 /* osek_task_wrapper and call osek_internal_error() with an error code */
7913 /* 'TASK_ENDING_WITHOUT_CHAIN_OR_TERMINATE'. */
7914 /* */
7915 /* INPUT */
7916 /* */
7917 /* tcb Task control block pointer */
7918 /* */
7919 /* OUTPUT */
7920 /* */
7921 /* None */
7922 /* */
7923 /* CALLS */
7924 /* */
7925 /* task_entry OSEK task entry */
7926 /* osek_internal_error */
7927 /* */
7928 /* CALLED BY */
7929 /* */
7930 /* Internal code */
7931 /* */
7932 /* RELEASE HISTORY */
7933 /* */
7934 /* DATE NAME DESCRIPTION */
7935 /* */
7936 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
7937 /* */
7938 /**************************************************************************/
osek_task_wrapper(ULONG tcb)7939 static void osek_task_wrapper(ULONG tcb)
7940 {
7941 TX_INTERRUPT_SAVE_AREA
7942 OSEK_TCB *tcb_ptr;
7943 StatusType status;
7944
7945 TX_DISABLE
7946
7947 /* The input argument is really a pointer to the task's TCB. */
7948 tcb_ptr = (OSEK_TCB *)tcb;
7949 /* Check whether it is a Task or an ISR. */
7950 if (tcb_ptr->osek_task_id == OSEK_TASK_ID)
7951 {
7952 osek_wrapper_operation_mode = NORMAL_EXECUTION_MODE;
7953
7954 /* last_run_task now holds this new task being run. */
7955 last_run_task = (ULONG)((TX_THREAD*)tcb_ptr);
7956
7957 /* Check this task's scheduling policy. */
7958 if (tcb_ptr->policy == NON)
7959 {
7960 pop_task_from_table(tcb_ptr); /* This routine remove task from table based on its cur_threshold. */
7961
7962 /* Store the new preemption threshold. */
7963 tcb_ptr->cur_threshold = OSEK_NON_SCHEDULE_PRIORITY;
7964
7965 /* Place this task to its proper priority queue based on Scheduling policy. */
7966 push_task_to_table(tcb_ptr); /* This routine pushes a task at the front of a queue based on its cur_threshold. */
7967 }
7968
7969 }
7970 else
7971 {
7972 if (tcb_ptr->task_type == CATEGORY1)
7973 {
7974 osek_wrapper_operation_mode = ISR1_MODE;
7975 }
7976 else
7977 {
7978 osek_wrapper_operation_mode = ISR2_MODE;
7979 }
7980 }
7981
7982 TX_RESTORE
7983
7984 /* Invoke the OSEK task entry point with appropriate arguments. */
7985 (tcb_ptr->task_entry)();
7986
7987 /* In case of a task we shouldn't be here- because tasks are always ended with either
7988 a TerminateTask() or ChainTask() but ISR will return here. */
7989 /* If it is a TASK then seems to be ended without any ChainTask or TerminateTask call
7990 anyway, as the task is ended it is better to Terminate it so that next available ready
7991 task can be run. */
7992
7993
7994 /* Terminate the task. */
7995 if (tcb_ptr->osek_task_id == OSEK_TASK_ID)
7996 {
7997 /* Change to default operations mode. */
7998 osek_wrapper_operation_mode = NORMAL_EXECUTION_MODE;
7999
8000 status = TerminateTask();
8001 if(status != E_OK) {
8002 osek_internal_error(SYS_MGR_SEND_TERMINATETASK);
8003 }
8004 }
8005 else
8006 {
8007 status = TerminateISR();
8008 if(status != E_OK) {
8009 osek_internal_error(SYS_MGR_SEND_TERMINATETASK);
8010 }
8011 }
8012 }
8013
8014
8015 /**************************************************************************/
8016 /* */
8017 /* FUNCTION RELEASE */
8018 /* */
8019 /* osek_internal_error PORTABLE C */
8020 /* 6.1.7 */
8021 /* AUTHOR */
8022 /* */
8023 /* William E. Lamie, Microsoft Corporation */
8024 /* */
8025 /* DESCRIPTION */
8026 /* */
8027 /* This function is invoked whenever an error is encountered */
8028 /* in the OSEK code. This is an endless loop. */
8029 /* Source of the error can be traced by the error code. */
8030 /* */
8031 /* INPUT */
8032 /* */
8033 /* error_code Error code */
8034 /* */
8035 /* OUTPUT */
8036 /* */
8037 /* None */
8038 /* */
8039 /* CALLS */
8040 /* */
8041 /* None */
8042 /* */
8043 /* CALLED BY */
8044 /* */
8045 /* OSEK internal code */
8046 /* */
8047 /* RELEASE HISTORY */
8048 /* */
8049 /* DATE NAME DESCRIPTION */
8050 /* */
8051 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
8052 /* */
8053 /**************************************************************************/
osek_internal_error(ULONG error_code)8054 static void osek_internal_error(ULONG error_code)
8055 {
8056 /* This just an end less loop, to trap error. */
8057 for(;;)
8058 {
8059 ; /* Empty loop. */
8060 }
8061 }
8062
8063
8064 /**************************************************************************/
8065 /* */
8066 /* FUNCTION RELEASE */
8067 /* */
8068 /* exec_ErrorHook PORTABLE C */
8069 /* 6.1.7 */
8070 /* AUTHOR */
8071 /* */
8072 /* William E. Lamie, Microsoft Corporation */
8073 /* */
8074 /* DESCRIPTION */
8075 /* */
8076 /* This function invokes ErroHook routine whenever an error is */
8077 /* encountered, provided ErroHook is defined. */
8078 /* Hook routines are called by the operating system, in a special */
8079 /* context have higher prior than all tasks, and not interrupted by */
8080 /* category 2 interrupt routines. */
8081 /* These functions are implemented by the user with user defined */
8082 /* functionality. Usually hook routines are allowed to use only a */
8083 /* subset of API functions. Whether to execute these routine or not is */
8084 /* user configurable via OIL. */
8085 /* */
8086 /* INPUT */
8087 /* */
8088 /* error_code Passed to ErrorHook */
8089 /* */
8090 /* OUTPUT */
8091 /* */
8092 /* None */
8093 /* */
8094 /* CALLS */
8095 /* */
8096 /* Application->error_handler That is ErrorHook (if defined) */
8097 /* */
8098 /* CALLED BY */
8099 /* */
8100 /* OSEK internal code */
8101 /* */
8102 /* RELEASE HISTORY */
8103 /* */
8104 /* DATE NAME DESCRIPTION */
8105 /* */
8106 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
8107 /* */
8108 /**************************************************************************/
exec_ErrorHook(StatusType error)8109 static void exec_ErrorHook (StatusType error)
8110 {
8111
8112 TX_THREAD *thread_ptr;
8113 UINT save_op_mode;
8114 UINT status;
8115 ULONG request[SYSMGR_QUEUE_MSG_LENGTH];
8116
8117 /* Check for any startup hook routine. */
8118 if (Application->error_hook_handler != TX_NULL)
8119 {
8120 /* But check whether already in ErrorHook routine? There must not be nested ErrorHook calls. */
8121 if (osek_wrapper_operation_mode == ERRORHOOK_MODE)
8122 {
8123 /* Already in ErroHook. */
8124 return;
8125 }
8126
8127 /* Save old operation mode. */
8128 save_op_mode = osek_wrapper_operation_mode;
8129
8130 /* Change to ErroHOOK mode. */
8131 osek_wrapper_operation_mode = ERRORHOOK_MODE;
8132
8133 /* Now execute user defined ErroHook routine. */
8134 (Application->error_hook_handler)(error);
8135
8136 /* Get the pointer to thread. */
8137 thread_ptr = tx_thread_identify();
8138
8139 /* Restore original operation mode. */
8140 osek_wrapper_operation_mode = save_op_mode;
8141
8142 /* If this ErrorHook is called by a task then check for any ISR came while executing this ErrorHook. */
8143 if (osek_wrapper_operation_mode == NORMAL_EXECUTION_MODE)
8144 {
8145 /* Now send a message to the SysMgr supervisor thread to execute the Error Hook. */
8146 /* Build the request. */
8147 request[0] = SYSMGR_ERRORHOOK; /* Request type. */
8148 request[1] = (ULONG)thread_ptr; /* ptr of calling thread. */
8149 request[2] = 0u; /* input to Error Hook. */
8150 request[3] = 0u;
8151
8152 /* Since the system manager supervisor thread is with the highest priority, */
8153 /* this routine will be preempted by SysMgr supervisor thread when */
8154 /* queue read is successful. */
8155
8156 status = tx_queue_send(&osek_work_queue, request, TX_NO_WAIT);
8157
8158 /* This should always succeed. */
8159 if (status != TX_SUCCESS)
8160 {
8161 /* System internal error. */
8162 osek_internal_error(SYS_MGR_SEND_CHAINTASK);
8163
8164 /* Return. */
8165 return;
8166 }
8167 } /* End if ( osek_wrapper_operation_mode ==. */
8168
8169 } /* end if (Application->error_handler). */
8170
8171 return;
8172 }
8173
8174
8175 /**************************************************************************/
8176 /* */
8177 /* FUNCTION RELEASE */
8178 /* */
8179 /* exec_PreTaskHook PORTABLE C */
8180 /* 6.1.7 */
8181 /* AUTHOR */
8182 /* */
8183 /* William E. Lamie, Microsoft Corporation */
8184 /* */
8185 /* DESCRIPTION */
8186 /* */
8187 /* This function invokes the PreTaskHook routine whenever a task */
8188 /* starts provided PreTaskHook is defined. */
8189 /* */
8190 /* INPUT */
8191 /* */
8192 /* None */
8193 /* */
8194 /* OUTPUT */
8195 /* */
8196 /* None */
8197 /* */
8198 /* CALLS */
8199 /* */
8200 /* None */
8201 /* */
8202 /* CALLED BY */
8203 /* */
8204 /* OSEK internal code */
8205 /* */
8206 /* RELEASE HISTORY */
8207 /* */
8208 /* DATE NAME DESCRIPTION */
8209 /* */
8210 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
8211 /* */
8212 /**************************************************************************/
exec_PreTaskHook(void)8213 static void exec_PreTaskHook(void)
8214 {
8215
8216 UINT save_op_mode;
8217
8218 if (Application->pretask_hook_handler != TX_NULL)
8219 {
8220 /* Set up the mode. */
8221 save_op_mode = osek_wrapper_operation_mode;
8222 osek_wrapper_operation_mode = PRETASKHOOK_MODE;
8223
8224 /* Call the Pretask hook. */
8225 (Application->pretask_hook_handler)();
8226
8227 /* Restore mode. */
8228 osek_wrapper_operation_mode = save_op_mode;
8229
8230 } /* end if (Application->PretaskHook_handler). */
8231
8232 return;
8233 }
8234
8235
8236 /**************************************************************************/
8237 /* */
8238 /* FUNCTION RELEASE */
8239 /* */
8240 /* exec_PostTaskHook PORTABLE C */
8241 /* 6.1.7 */
8242 /* AUTHOR */
8243 /* */
8244 /* William E. Lamie, Microsoft Corporation */
8245 /* */
8246 /* DESCRIPTION */
8247 /* */
8248 /* This function invokes PostTaskHook routine whenever a task */
8249 /* terminates provided PostTaskHook is defined. */
8250 /* */
8251 /* INPUT */
8252 /* */
8253 /* None */
8254 /* */
8255 /* OUTPUT */
8256 /* */
8257 /* None */
8258 /* */
8259 /* CALLS */
8260 /* */
8261 /* None */
8262 /* */
8263 /* CALLED BY */
8264 /* */
8265 /* OSEK internal code */
8266 /* */
8267 /* RELEASE HISTORY */
8268 /* */
8269 /* DATE NAME DESCRIPTION */
8270 /* */
8271 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
8272 /* */
8273 /**************************************************************************/
exec_PostTaskHook(void)8274 static void exec_PostTaskHook(void)
8275 {
8276
8277 UINT sav_op_mode;
8278
8279 if (Application->posttask_hook_handler != TX_NULL)
8280 {
8281 /* Set up the mode. */
8282 sav_op_mode = osek_wrapper_operation_mode;
8283 osek_wrapper_operation_mode = POSTTASKHOOK_MODE;
8284
8285 /* Call the Posttask hook. */
8286 (Application->posttask_hook_handler)();
8287
8288 /* Restore mode. */
8289 osek_wrapper_operation_mode = sav_op_mode;
8290
8291 } /* end if (Application->PosttaskHook_handler). */
8292
8293 return;
8294 }
8295
8296
8297 /**************************************************************************/
8298 /* */
8299 /* FUNCTION RELEASE */
8300 /* */
8301 /* add_task_to_table PORTABLE C */
8302 /* 6.1.7 */
8303 /* AUTHOR */
8304 /* */
8305 /* William E. Lamie, Microsoft Corporation */
8306 /* */
8307 /* DESCRIPTION */
8308 /* */
8309 /* This function adds a ready task in the task queue. */
8310 /* */
8311 /* INPUT */
8312 /* */
8313 /* *tcb_ptr Pointer to the task to be added to the queue */
8314 /* */
8315 /* OUTPUT */
8316 /* */
8317 /* None */
8318 /* */
8319 /* CALLS */
8320 /* */
8321 /* None */
8322 /* */
8323 /* CALLED BY */
8324 /* */
8325 /* OSEK internal code */
8326 /* */
8327 /* RELEASE HISTORY */
8328 /* */
8329 /* DATE NAME DESCRIPTION */
8330 /* */
8331 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
8332 /* */
8333 /**************************************************************************/
add_task_to_table(OSEK_TCB * tcb_ptr)8334 static void add_task_to_table(OSEK_TCB *tcb_ptr)
8335 {
8336 TX_INTERRUPT_SAVE_AREA
8337 UINT priority;
8338 UINT i;
8339
8340 TX_DISABLE
8341
8342 /* Get the priority of this task. */
8343 priority = tcb_ptr-> org_prio;
8344
8345 for (i = 0u; i < TASK_QUEUE_DEPTH; i++)
8346 {
8347 /* Add this task to the a queue assigned for this task's priority level. */
8348 /* Find next free entry in the queue. */
8349 /* Oldest activated task is at the front of the queue, so this new entry. */
8350 /* will go at the end of the queue. */
8351
8352 if (task_table[priority][i] == 0u)
8353 {
8354 task_table[priority][i] = (TaskType)tcb_ptr;
8355 break;
8356 }
8357 }
8358
8359 if (i >= TASK_QUEUE_DEPTH)
8360 {
8361 osek_internal_error(SYSMGR_FATAL_ERROR);
8362 }
8363
8364 TX_RESTORE
8365
8366 }
8367
8368
8369 /**************************************************************************/
8370 /* */
8371 /* FUNCTION RELEASE */
8372 /* */
8373 /* push_task_to_table PORTABLE C */
8374 /* 6.1.7 */
8375 /* AUTHOR */
8376 /* */
8377 /* William E. Lamie, Microsoft Corporation */
8378 /* */
8379 /* DESCRIPTION */
8380 /* */
8381 /* This function pushes a task at the front of the task queue. */
8382 /* */
8383 /* INPUT */
8384 /* */
8385 /* *tcb_ptr Pointer to the task to be added to the queue */
8386 /* */
8387 /* OUTPUT */
8388 /* */
8389 /* None */
8390 /* */
8391 /* CALLS */
8392 /* */
8393 /* None */
8394 /* */
8395 /* CALLED BY */
8396 /* */
8397 /* OSEK internal code */
8398 /* */
8399 /* RELEASE HISTORY */
8400 /* */
8401 /* DATE NAME DESCRIPTION */
8402 /* */
8403 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
8404 /* */
8405 /**************************************************************************/
push_task_to_table(OSEK_TCB * tcb_ptr)8406 static void push_task_to_table(OSEK_TCB *tcb_ptr)
8407 {
8408 TX_INTERRUPT_SAVE_AREA
8409 UINT priority;
8410 UINT i;
8411 UINT k;
8412
8413 TX_DISABLE
8414
8415 priority = tcb_ptr->cur_threshold;
8416
8417 i = (TASK_QUEUE_DEPTH - 2u);
8418
8419 while (i != 0u)
8420 {
8421 /* Add this task to the queue (of for priority level supplied). */
8422 /* Place the entry at the front of the queue and push back all entries by one */
8423 k = i + 1u;
8424 task_table[priority][k] = task_table[priority][i];
8425 i--;
8426 }
8427
8428 task_table[priority][1u] = task_table[priority][0u];
8429
8430 /* Now push the calling task's id at the front of the queue. */
8431 task_table[priority][0u] = (ULONG)tcb_ptr;
8432
8433 TX_RESTORE
8434 }
8435
8436
8437 /**************************************************************************/
8438 /* */
8439 /* FUNCTION RELEASE */
8440 /* */
8441 /* start_osek_tasks PORTABLE C */
8442 /* 6.1.7 */
8443 /* AUTHOR */
8444 /* */
8445 /* William E. Lamie, Microsoft Corporation */
8446 /* */
8447 /* DESCRIPTION */
8448 /* */
8449 /* This function schedules the first task upon StatOS */
8450 /* */
8451 /* INPUT */
8452 /* */
8453 /* None */
8454 /* */
8455 /* OUTPUT */
8456 /* */
8457 /* Error Code */
8458 /* */
8459 /* CALLS */
8460 /* */
8461 /* tx_thread_resume */
8462 /* */
8463 /* CALLED BY */
8464 /* */
8465 /* osek_system_manager_entry */
8466 /* */
8467 /* RELEASE HISTORY */
8468 /* */
8469 /* DATE NAME DESCRIPTION */
8470 /* */
8471 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
8472 /* */
8473 /**************************************************************************/
start_osek_tasks(void)8474 static void start_osek_tasks(void)
8475 {
8476 TX_INTERRUPT_SAVE_AREA
8477 TX_THREAD *task_thread;
8478 UINT i;
8479 UINT j;
8480 UINT found;
8481
8482 TX_DISABLE
8483
8484 /* Start with the highest priority */
8485 j = OSEK_ISR1_PRIORITY;
8486 found = FALSE;
8487
8488 while (found == FALSE)
8489 {
8490 for (i = 0u; i < TASK_QUEUE_DEPTH; i++)
8491 {
8492 /* Search for any ready but not waiting task within this priority level. */
8493 if (( task_table[j][i] != 0u) && (((OSEK_TCB*)task_table[j][i] )->waiting == TX_FALSE))
8494 {
8495 /* Found it but check whether this task can be run,
8496 This task must have higher priority than current task's ceiling priority
8497 This task must have all needed Internal/External resources. */
8498 task_thread = &((OSEK_TCB*)task_table[j][i])->task;
8499 found = check_task_to_run((OSEK_TCB*)task_table[j][i]);
8500 if (found == TRUE)
8501 {
8502 break;
8503 }
8504 }
8505
8506 }
8507
8508 /* No ready task found for this priority level, check for next lower priority level
8509 but are we at the lowest priority level? */
8510 if ((j == 0u) || (found == TRUE))
8511 {
8512 break;
8513 }
8514
8515 j--;
8516
8517 } /* End while. */
8518
8519 /* Reached here means either a ready Task is found or no task is READY. */
8520 /* if found = 1, task is found. */
8521
8522 if (found == FALSE)
8523 {
8524 last_run_task = INVALID_TASK;
8525 }
8526 else
8527 {
8528 if (((OSEK_TCB*)task_thread)->osek_task_id == OSEK_ISR_ID)
8529 {
8530 /* If it is an ISR , set the op mode and no need to:
8531 call pre and post task hooks as well as change last_run_task data. */
8532 osek_wrapper_operation_mode = ISR2_MODE;
8533 }
8534 else
8535 {
8536 osek_wrapper_operation_mode = NORMAL_EXECUTION_MODE;
8537 /* Check whether it is a fresh OS start, for fresh start no need to run pre & post task hooks. */
8538 if (system_start == 0u)
8539 {
8540 /* If no preemption takes place , then no need to execute pre and post task hooks. */
8541 if ((last_run_task != (ULONG)task_thread )|| (task_terminated == TX_TRUE))
8542 {
8543 exec_PostTaskHook();
8544
8545 /* Update last run task data to reflect next task to run. */
8546 last_run_task = (ULONG)task_thread;
8547
8548 exec_PreTaskHook();
8549 }
8550
8551 }
8552
8553 last_run_task = (ULONG)task_thread;
8554 } /* End else. */
8555
8556 tx_thread_resume(task_thread);
8557
8558 system_start = TX_FALSE;
8559
8560 task_terminated = TX_FALSE;
8561
8562 } /* end of else part of if (!found). */
8563
8564 TX_RESTORE
8565 }
8566
8567
8568 /**************************************************************************/
8569 /* */
8570 /* FUNCTION RELEASE */
8571 /* */
8572 /* check_task_to_run PORTABLE C */
8573 /* 6.1.7 */
8574 /* AUTHOR */
8575 /* */
8576 /* William E. Lamie, Microsoft Corporation */
8577 /* */
8578 /* DESCRIPTION */
8579 /* */
8580 /* This function schedules the first task upon StatOS */
8581 /* This is called by system manager thread when StartOS is called. */
8582 /* */
8583 /* INPUT */
8584 /* */
8585 /* None */
8586 /* */
8587 /* OUTPUT */
8588 /* */
8589 /* Error Code */
8590 /* */
8591 /* CALLS */
8592 /* */
8593 /* tx_thread_resume */
8594 /* */
8595 /* CALLED BY */
8596 /* */
8597 /* osek_system_manager_entry */
8598 /* */
8599 /* RELEASE HISTORY */
8600 /* */
8601 /* DATE NAME DESCRIPTION */
8602 /* */
8603 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
8604 /* */
8605 /**************************************************************************/
check_task_to_run(OSEK_TCB * tcb_ptr)8606 static UINT check_task_to_run (OSEK_TCB *tcb_ptr)
8607 {
8608 TX_INTERRUPT_SAVE_AREA
8609 UINT status;
8610
8611 TX_DISABLE
8612
8613 if (tcb_ptr->osek_task_id != OSEK_TASK_ID)
8614 {
8615 /* if selection is an ISR,
8616 it can't be run if ISRs are suspended or any HOOK mode is ON. */
8617 if ((suspend_ISR2 == TX_TRUE) ||
8618 (osek_wrapper_operation_mode == ERRORHOOK_MODE) ||
8619 (osek_wrapper_operation_mode == PRETASKHOOK_MODE) ||
8620 (osek_wrapper_operation_mode == POSTTASKHOOK_MODE) ||
8621 (osek_wrapper_operation_mode == STARTUPHOOK_MODE) ||
8622 (osek_wrapper_operation_mode == SHUTDOWNHOOK_MODE) ||
8623 (osek_wrapper_operation_mode == ALARM_CALLBACK_MODE))
8624 {
8625 TX_RESTORE
8626
8627 return (FALSE);
8628 }
8629 }
8630
8631 if (tcb_ptr->internal_res != 0u)
8632 {
8633 status = get_internal_resource(tcb_ptr);
8634
8635 if (status != E_OK)
8636 {
8637 TX_RESTORE
8638
8639 return (FALSE);
8640 }
8641 }
8642
8643 status = check_external_resource(tcb_ptr);
8644 if (status != E_OK)
8645 {
8646 TX_RESTORE
8647
8648 return (FALSE);
8649 }
8650
8651 /* Now check for NON scheduling policy. */
8652 if (tcb_ptr->policy == NON)
8653 {
8654 /* First remove task from its current queue position. */
8655 pop_task_from_table(tcb_ptr);
8656
8657 tcb_ptr->cur_threshold = OSEK_NON_SCHEDULE_PRIORITY;
8658
8659 push_task_to_table(tcb_ptr);
8660 }
8661
8662 TX_RESTORE
8663
8664 return (TRUE);
8665 }
8666
8667
8668 /**************************************************************************/
8669 /* */
8670 /* FUNCTION RELEASE */
8671 /* */
8672 /* pop_task_from_table PORTABLE C */
8673 /* 6.1.7 */
8674 /* AUTHOR */
8675 /* */
8676 /* William E. Lamie, Microsoft Corporation */
8677 /* */
8678 /* DESCRIPTION */
8679 /* Removes a task from the table of active tasks. */
8680 /* */
8681 /* INPUT */
8682 /* */
8683 /* id Id of the resource. */
8684 /* */
8685 /* OUTPUT */
8686 /* */
8687 /* */
8688 /* CALLS */
8689 /* */
8690 /* */
8691 /* CALLED BY */
8692 /* */
8693 /* Application Code */
8694 /* */
8695 /* RELEASE HISTORY */
8696 /* */
8697 /* DATE NAME DESCRIPTION */
8698 /* */
8699 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
8700 /* */
8701 /**************************************************************************/
pop_task_from_table(OSEK_TCB * tcb_ptr)8702 static void pop_task_from_table(OSEK_TCB *tcb_ptr)
8703 {
8704 TX_INTERRUPT_SAVE_AREA
8705 UINT priority;
8706 UINT i;
8707 UINT j;
8708 UINT k;
8709
8710 TX_DISABLE
8711
8712 /* Get the priority of this task. */
8713 priority = tcb_ptr-> cur_threshold;
8714 j = (TASK_QUEUE_DEPTH - 2u);
8715 for (i = 0u; i < j; i++)
8716 {
8717 /* Move N+1 th element to Nth location. */
8718 /* Oldest task is at the bottom of the queue. */
8719 k = i + 1u;
8720 task_table[priority][i] = task_table[priority][k];
8721 }
8722
8723 /* Make the top most element in the queue NULL as the oldest task is removed from the bottom. */
8724 j = (TASK_QUEUE_DEPTH) - 1u;
8725 task_table[priority][j] = 0u;
8726
8727 TX_RESTORE
8728 }
8729
8730
8731 /**************************************************************************/
8732 /* */
8733 /* FUNCTION RELEASE */
8734 /* */
8735 /* check_linked_resources PORTABLE C */
8736 /* 6.1.7 */
8737 /* AUTHOR */
8738 /* */
8739 /* William E. Lamie, Microsoft Corporation */
8740 /* */
8741 /* DESCRIPTION */
8742 /* */
8743 /* Check if resources are linked */
8744 /* */
8745 /* CALLED BY */
8746 /* */
8747 /* Application Code */
8748 /* */
8749 /* RELEASE HISTORY */
8750 /* */
8751 /* DATE NAME DESCRIPTION */
8752 /* */
8753 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
8754 /* */
8755 /**************************************************************************/
check_linked_resources(void)8756 static void check_linked_resources(void)
8757 {
8758 TX_INTERRUPT_SAVE_AREA
8759 ULONG index;
8760 OSEK_RESOURCE *res_ptr;
8761 OSEK_RESOURCE *linked_res_ptr;
8762
8763 TX_DISABLE
8764
8765 /* Search the Resource from resource pool. */
8766 for (index = 0u; index < OSEK_MAX_RES; index++)
8767 {
8768
8769 res_ptr = &(osek_res_pool[index]);
8770 if ((res_ptr->res_in_use == TX_TRUE) && (res_ptr->type == LINKED))
8771 {
8772 /* Get the res linked to this resource. */
8773 linked_res_ptr = (OSEK_RESOURCE *)(res_ptr->resolved_res);
8774
8775 /* Make this resources's ceiling priority equal to the ceiling priority of linked resource. */
8776 if ( res_ptr->c_priority < linked_res_ptr->c_priority)
8777 {
8778 res_ptr->c_priority = linked_res_ptr->c_priority;
8779 }
8780 }
8781 }
8782
8783 TX_RESTORE
8784 }
8785
8786
8787 /**************************************************************************/
8788 /* */
8789 /* FUNCTION RELEASE */
8790 /* */
8791 /* get_internal_resource PORTABLE C */
8792 /* 6.1.7 */
8793 /* AUTHOR */
8794 /* */
8795 /* William E. Lamie, Microsoft Corporation */
8796 /* */
8797 /* DESCRIPTION */
8798 /* */
8799 /* This call serves to enter critical sections in the code that are */
8800 /* assigned to the resource referenced by <ResID>. A critical section */
8801 /* must always be left using ReleaseResource. Nested resource */
8802 /* occupation is only allowed if the inner critical sections are */
8803 /* completely executed within the surrounding critical section. */
8804 /* Nested occupation of one and the same resource is also forbidden. */
8805 /* Corresponding calls to GetResource and ReleaseResource should appear */
8806 /* within the same function on the same function level. */
8807 /* */
8808 /* INPUT */
8809 /* */
8810 /* id Id of the resource. */
8811 /* */
8812 /* OUTPUT */
8813 /* */
8814 /* E_OK If success */
8815 /* E_OS_CALLEVEL Called from ISR */
8816 /* E_OS_ACCESS Attempt to get a resource which is */
8817 /* already occupied by any task or ISR, */
8818 /* or the statically assigned priority of */
8819 /* the calling task or interrupt routine */
8820 /* is higher than the calculated ceiling */
8821 /* priority, */
8822 /* */
8823 /* CALLS */
8824 /* */
8825 /* osek_task_independent_area See if called from task independent */
8826 /* area */
8827 /* tx_thread_identify Identify the current thread */
8828 /* osek_internal_error Osek internal error */
8829 /* */
8830 /* CALLED BY */
8831 /* */
8832 /* Application Code */
8833 /* */
8834 /* RELEASE HISTORY */
8835 /* */
8836 /* DATE NAME DESCRIPTION */
8837 /* */
8838 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
8839 /* */
8840 /**************************************************************************/
get_internal_resource(OSEK_TCB * tcb_ptr)8841 static StatusType get_internal_resource(OSEK_TCB *tcb_ptr)
8842 {
8843 TX_INTERRUPT_SAVE_AREA
8844 OSEK_RESOURCE *osek_res;
8845 UINT res_prio;
8846 UINT index;
8847
8848
8849 TX_DISABLE
8850
8851 for (index = 0u; index < OSEK_MAX_INTERNAL_RES; index++)
8852 {
8853
8854 if (tcb_ptr->internal_resource_list[index] == 0u)
8855 {
8856 break; /* No Internal Resource in the list. */
8857 }
8858
8859 /* Get internal RES's control block. */
8860 osek_res = (OSEK_RESOURCE *)tcb_ptr->internal_resource_list[index];
8861
8862 /* Now check whether this resource is already occupied by other task. */
8863 if (osek_res->taskid != 0u)
8864 {
8865 /* Some entry is there, is it occupied by any other task? */
8866 if (osek_res->taskid != (TaskType)tcb_ptr)
8867 {
8868 TX_RESTORE
8869
8870 return (E_OS_ACCESS);
8871 }
8872 }
8873
8874 /* Take this resource. */
8875 tcb_ptr->internal_resource_occuplied_list[index] = tcb_ptr->internal_resource_list[index];
8876
8877 /* Save this task's id in the res's control block to indicate that this task is the owner of this res. */
8878 osek_res->taskid = (TaskType)(tcb_ptr);
8879
8880 } /* End for (index.. */
8881
8882 /* Now all internal resources are taken, this needs to change task's preemption
8883 to highest ceiling priority of internal resource occupied. */
8884
8885 /* First remove task from its current queue position. */
8886 pop_task_from_table(tcb_ptr);
8887
8888 /* Now need to change this task's preemption threshold to resource's ceiling priority. */
8889 /* Assume task's original priority is the highest. */
8890 if ((tcb_ptr->resource_scheduler != 0u) || (tcb_ptr->policy == NON))
8891 {
8892 tcb_ptr->cur_threshold = OSEK_NON_SCHEDULE_PRIORITY;
8893 }
8894
8895 for (index = 0u; index < OSEK_MAX_INTERNAL_RES; index++)
8896 {
8897 if (tcb_ptr->internal_resource_occuplied_list[index] == 0u) {
8898 break;
8899 }
8900
8901 res_prio = ((OSEK_RESOURCE *) (tcb_ptr->internal_resource_occuplied_list[index]))->c_priority;
8902 if (tcb_ptr->cur_threshold < res_prio )
8903 {
8904 tcb_ptr->cur_threshold = res_prio;
8905 }
8906 }
8907 /* Now the task's current threshold reflect the highest of ceiling priority of the remaining
8908 resources held by this task, move this task to the front of that priority queue. */
8909 push_task_to_table(tcb_ptr);
8910
8911 TX_RESTORE
8912
8913 return (E_OK);
8914 }
8915
8916
8917 /**************************************************************************/
8918 /* */
8919 /* FUNCTION RELEASE */
8920 /* */
8921 /* release_internal_resource PORTABLE C */
8922 /* 6.1.7 */
8923 /* AUTHOR */
8924 /* */
8925 /* William E. Lamie, Microsoft Corporation */
8926 /* */
8927 /* DESCRIPTION */
8928 /* */
8929 /* This call releases any internal resources held by the calling task. */
8930 /* It also changes the calling task's priority to reflect either its */
8931 /* original priority, NON SCHEDULE priority or maximum ceiling */
8932 /* priority of any any external resources held by this task. */
8933 /* At the end this task is then moved to a queue appropriate to its new */
8934 /* ceiling priority. */
8935 /* */
8936 /* INPUT */
8937 /* */
8938 /* id Task id. */
8939 /* */
8940 /* OUTPUT */
8941 /* */
8942 /* E_OK Always */
8943 /* */
8944 /* CALLS */
8945 /* */
8946 /* pop_task_from_table Removes a task from its current queue */
8947 /* push_task_to_table Pushes a task at the front of a queue */
8948 /* */
8949 /* CALLED BY */
8950 /* */
8951 /* Wrapper internal code (not available for application) */
8952 /* */
8953 /* RELEASE HISTORY */
8954 /* */
8955 /* DATE NAME DESCRIPTION */
8956 /* */
8957 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
8958 /* */
8959 /**************************************************************************/
release_internal_resource(OSEK_TCB * tcb_ptr)8960 static StatusType release_internal_resource(OSEK_TCB *tcb_ptr)
8961 {
8962 TX_INTERRUPT_SAVE_AREA
8963 UINT index;
8964
8965 TX_DISABLE
8966
8967 /* Release any internal resources held? */
8968 for (index = 0u; index < OSEK_MAX_INTERNAL_RES; index++)
8969 {
8970
8971 if (tcb_ptr->internal_resource_occuplied_list[index] == 0u)
8972 {
8973 break;
8974 }
8975
8976 ((OSEK_RESOURCE *)(tcb_ptr->internal_resource_occuplied_list[index]))->taskid = 0u;
8977
8978 tcb_ptr->internal_resource_occuplied_list[index] = 0u;
8979 }
8980
8981 /* First remove task from its current queue position. */
8982 pop_task_from_table(tcb_ptr);
8983
8984 /* As all internal resources are released and no external resources are held
8985 this task must be reverted to its original design time priority. */
8986
8987 tcb_ptr->cur_threshold = tcb_ptr->org_prio;
8988
8989 /* Now move this task to the front of that priority queue. */
8990 push_task_to_table(tcb_ptr);
8991
8992 TX_RESTORE
8993
8994 return (E_OK);
8995 }
8996
8997
8998 /**************************************************************************/
8999 /* */
9000 /* FUNCTION RELEASE */
9001 /* */
9002 /* check_external_resource PORTABLE C */
9003 /* 6.1.7 */
9004 /* AUTHOR */
9005 /* */
9006 /* William E. Lamie, Microsoft Corporation */
9007 /* */
9008 /* DESCRIPTION */
9009 /* */
9010 /* This call serves to enter critical sections in the code that are */
9011 /* assigned to the resource referenced by <ResID>. A critical section */
9012 /* must always be left using releaseResource. Nested resource */
9013 /* occupation is only allowed if the inner critical sections are */
9014 /* completely executed within the surrounding critical section. */
9015 /* Nested occupation of one and the same resource is also forbidden. */
9016 /* Corresponding calls to GetResource and ReleaseResource should appear */
9017 /* within the same function on the same function level. */
9018 /* */
9019 /* INPUT */
9020 /* */
9021 /* id Id of the resource. */
9022 /* */
9023 /* OUTPUT */
9024 /* */
9025 /* E_OK If success */
9026 /* E_OS_CALLEVEL Called from ISR */
9027 /* E_OS_ACCESS Attempt to get a resource which is */
9028 /* already occupied by any task or ISR, */
9029 /* or the statically assigned priority of */
9030 /* the calling task or interrupt routine */
9031 /* is higher than the calculated ceiling */
9032 /* priority. */
9033 /* */
9034 /* CALLS */
9035 /* */
9036 /* osek_task_independent_area See if called from task independent */
9037 /* area */
9038 /* tx_thread_identify Identify the current thread */
9039 /* osek_internal_error OSEK internal error */
9040 /* */
9041 /* CALLED BY */
9042 /* */
9043 /* Application Code */
9044 /* */
9045 /* RELEASE HISTORY */
9046 /* */
9047 /* DATE NAME DESCRIPTION */
9048 /* */
9049 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
9050 /* */
9051 /**************************************************************************/
check_external_resource(OSEK_TCB * tcb_ptr)9052 static StatusType check_external_resource(OSEK_TCB *tcb_ptr)
9053 {
9054 TX_INTERRUPT_SAVE_AREA
9055 OSEK_RESOURCE *osek_res;
9056 OSEK_RESOURCE *osek_res1;
9057 StatusType status;
9058 UINT index;
9059
9060 /* Check that all assigned external resources for this task are free. */
9061 /* Here only availability of resources is checked, no resource will be taken. */
9062
9063 TX_DISABLE
9064
9065 status = E_OK; /* Assuming that everything is OK. */
9066 for (index = 0u; index < OSEK_MAX_EXTERNAL_RES; index++)
9067 {
9068
9069 if (tcb_ptr->external_resource_list[index] == 0u)
9070 {
9071 break; /* No External Resource left in the list. */
9072 }
9073
9074 /* Get External RES's control block. */
9075 osek_res = (OSEK_RESOURCE *)tcb_ptr->external_resource_list[index];
9076
9077 /* Now check whether this resource is already occupied by other task. */
9078 if (osek_res->taskid != 0u)
9079 {
9080 if (osek_res->taskid != (TaskType)tcb_ptr)
9081 {
9082 status = E_OS_ACCESS; /* Already occupied by any other task. */
9083 break;
9084 }
9085
9086 }
9087
9088 if (osek_res->type == LINKED)
9089 {
9090
9091 osek_res1 = (OSEK_RESOURCE *)(osek_res->resolved_res);
9092
9093 if (osek_res1->taskid != 0u)
9094 {
9095 if (osek_res1->taskid != (TaskType)tcb_ptr)
9096 {
9097 status = E_OS_ACCESS; /* Already occupied by any other task. */
9098 break;
9099 }
9100 }
9101
9102 } /* End (osek_res->type == LINKED) */
9103
9104
9105 } /* End for. */
9106
9107 TX_RESTORE
9108
9109 return (status);
9110 }
9111
9112
9113 /*************************** END OF FILE ************************************/
9114