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