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, &current_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, &current_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, &current_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