1 /*! *********************************************************************************
2  * Copyright 2020-2021, 2024 NXP
3  * All rights reserved.
4  *
5  *
6  * This is the source file for the OS Abstraction layer for thread.
7  *
8  * SPDX-License-Identifier: BSD-3-Clause
9  ********************************************************************************** */
10 
11 /*! *********************************************************************************
12 *************************************************************************************
13 * Include
14 *************************************************************************************
15 ********************************************************************************** */
16 #include "fsl_common.h"
17 #include "fsl_os_abstraction.h"
18 #include "tx_api.h"
19 #include "tx_event_flags.h"
20 #include <string.h>
21 #include "fsl_component_generic_list.h"
22 #include "fsl_os_abstraction_threadx.h"
23 
24 /*! *********************************************************************************
25 *************************************************************************************
26 * Private macros
27 *************************************************************************************
28 ********************************************************************************** */
29 
30 /* Weak function. */
31 #if defined(__GNUC__)
32 #define __WEAK_FUNC __attribute__((weak))
33 #elif defined(__ICCARM__)
34 #define __WEAK_FUNC __weak
35 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
36 #define __WEAK_FUNC __attribute__((weak))
37 #endif
38 
39 #define millisecToTicks(millisec) (((millisec)*TX_TIMER_TICKS_PER_SECOND + 999U) / 1000U)
40 
41 #ifdef DEBUG_ASSERT
42 #define OS_ASSERT(condition) \
43     if (!(condition))        \
44         while (1)            \
45             ;
46 #else
47 #define OS_ASSERT(condition) (void)(condition);
48 #endif
49 
50 /*! @brief Converts milliseconds to ticks*/
51 #define MSEC_TO_TICK(msec) \
52     (((uint32_t)(msec) + 500uL / (uint32_t)TX_TIMER_TICKS_PER_SECOND) * (uint32_t)TX_TIMER_TICKS_PER_SECOND / 1000uL)
53 
54 #define TICKS_TO_MSEC(tick) ((uint32_t)((uint64_t)(tick)*1000uL / (uint64_t)TX_TIMER_TICKS_PER_SECOND))
55 
56 #define OSA_MEM_MAGIC_NUMBER (12345U)
57 #define OSA_MEM_SIZE_ALIGN(var, alignbytes) \
58     ((unsigned int)((var) + ((alignbytes)-1U)) & (unsigned int)(~(unsigned int)((alignbytes)-1U)))
59 
60 /************************************************************************************
61 *************************************************************************************
62 * Private type definitions
63 *************************************************************************************
64 ************************************************************************************/
65 typedef struct osa_thread_task
66 {
67     list_element_t link;
68     TX_THREAD taskHandle;
69 } osa_thread_task_t;
70 
71 typedef struct _osa_event_struct
72 {
73     TX_EVENT_FLAGS_GROUP eventHandle; /* The event handle */
74     uint8_t autoClear;           /*!< Auto clear or manual clear   */
75 } osa_event_struct_t;
76 
77 /*! @brief State structure for thread osa manager. */
78 typedef struct _osa_state
79 {
80 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
81     list_label_t taskList;
82 #endif
83     uint32_t basePriority;
84     int32_t basePriorityNesting;
85     uint32_t interruptDisableCount;
86 } osa_state_t;
87 
88 /*! @brief Definition structure contains allocated memory information.*/
89 typedef struct _osa_mem_align_control_block
90 {
91     uint16_t identifier; /*!< Identifier for the memory control block. */
92     uint16_t offset;     /*!< offset from aligned address to real address */
93 } osa_mem_align_cb_t;
94 
95 /*! *********************************************************************************
96 *************************************************************************************
97 * Private prototypes
98 *************************************************************************************
99 ********************************************************************************** */
100 
101 /*! *********************************************************************************
102 *************************************************************************************
103 * Public memory declarations
104 *************************************************************************************
105 ********************************************************************************** */
106 const uint8_t gUseRtos_c = USE_RTOS; // USE_RTOS = 0 for BareMetal and 1 for OS
107 
108 static TX_INTERRUPT_SAVE_AREA
109 
110 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
111     static osa_state_t s_osaState = {0};
112 #endif
113 
114 /*! *********************************************************************************
115 *************************************************************************************
116 * Private memory declarations
117 *************************************************************************************
118 ********************************************************************************** */
119 
120 /*! *********************************************************************************
121 *************************************************************************************
122 * Public functions
123 *************************************************************************************
124 ********************************************************************************** */
125 /*FUNCTION**********************************************************************
126  *
127  * Function Name : OSA_MemoryAllocate
128  * Description   : Reserves the requested amount of memory in bytes.
129  *
130  *END**************************************************************************/
OSA_MemoryAllocate(uint32_t memLength)131 void *OSA_MemoryAllocate(uint32_t memLength)
132 {
133     return NULL;
134 }
135 
136 /*FUNCTION**********************************************************************
137  *
138  * Function Name : OSA_MemoryFree
139  * Description   : Frees the memory previously reserved.
140  *
141  *END**************************************************************************/
OSA_MemoryFree(void * p)142 void OSA_MemoryFree(void *p)
143 {
144 }
145 
OSA_MemoryAllocateAlign(uint32_t memLength,uint32_t alignbytes)146 void *OSA_MemoryAllocateAlign(uint32_t memLength, uint32_t alignbytes)
147 {
148     osa_mem_align_cb_t *p_cb = NULL;
149     uint32_t alignedsize;
150 
151     /* Check overflow. */
152     alignedsize = (uint32_t)(unsigned int)OSA_MEM_SIZE_ALIGN(memLength, alignbytes);
153     if (alignedsize < memLength)
154     {
155         return NULL;
156     }
157 
158     if (alignedsize > 0xFFFFFFFFU - alignbytes - sizeof(osa_mem_align_cb_t))
159     {
160         return NULL;
161     }
162 
163     alignedsize += alignbytes + (uint32_t)sizeof(osa_mem_align_cb_t);
164 
165     union
166     {
167         void *pointer_value;
168         uintptr_t unsigned_value;
169     } p_align_addr, p_addr;
170 
171     p_addr.pointer_value = OSA_MemoryAllocate(alignedsize);
172 
173     if (p_addr.pointer_value == NULL)
174     {
175         return NULL;
176     }
177 
178     p_align_addr.unsigned_value = OSA_MEM_SIZE_ALIGN(p_addr.unsigned_value + sizeof(osa_mem_align_cb_t), alignbytes);
179 
180     p_cb             = (osa_mem_align_cb_t *)(p_align_addr.unsigned_value - 4U);
181     p_cb->identifier = OSA_MEM_MAGIC_NUMBER;
182     p_cb->offset     = (uint16_t)(p_align_addr.unsigned_value - p_addr.unsigned_value);
183 
184     return p_align_addr.pointer_value;
185 }
186 
OSA_MemoryFreeAlign(void * p)187 void OSA_MemoryFreeAlign(void *p)
188 {
189     union
190     {
191         void *pointer_value;
192         uintptr_t unsigned_value;
193     } p_free;
194     p_free.pointer_value = p;
195     osa_mem_align_cb_t *p_cb = (osa_mem_align_cb_t *)(p_free.unsigned_value - 4U);
196 
197     if (p_cb->identifier != OSA_MEM_MAGIC_NUMBER)
198     {
199         return;
200     }
201 
202     p_free.unsigned_value = p_free.unsigned_value - p_cb->offset;
203 
204     OSA_MemoryFree(p_free.pointer_value);
205 }
206 
207 /*FUNCTION**********************************************************************
208  *
209  * Function Name : OSA_EnterCritical
210  * Description   : Enter critical.
211  *
212  *END**************************************************************************/
OSA_EnterCritical(uint32_t * sr)213 void OSA_EnterCritical(uint32_t *sr)
214 {
215     *sr = tx_interrupt_control(TX_INT_DISABLE);
216 }
217 
218 /*FUNCTION**********************************************************************
219  *
220  * Function Name : OSA_ExitCritical
221  * Description   : Exit critical.
222  *
223  *END**************************************************************************/
OSA_ExitCritical(uint32_t sr)224 void OSA_ExitCritical(uint32_t sr)
225 {
226     (void)tx_interrupt_control(sr);
227 }
228 
229 /*FUNCTION**********************************************************************
230  *
231  * Function Name : OSA_Init
232  * Description   : This function is used to setup the basic services, it should
233  * be called first in function main.
234  *
235  *END**************************************************************************/
236 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
OSA_Init(void)237 void OSA_Init(void)
238 {
239     LIST_Init((&s_osaState.taskList), 0);
240     s_osaState.basePriorityNesting   = 0;
241     s_osaState.interruptDisableCount = 0;
242 }
243 #endif
244 
245 /*FUNCTION**********************************************************************
246  *
247  * Function Name : OSA_Start
248  * Description   : This function is used to start RTOS scheduler.
249  *
250  *END**************************************************************************/
251 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
252 /* Configures _tx_initialize_low_level_ptr and tx_application_define_ptr */
253 __WEAK_FUNC void Prepare_ThreadX(void);
Prepare_ThreadX(void)254 __WEAK_FUNC void Prepare_ThreadX(void)
255 {
256 }
OSA_Start(void)257 void OSA_Start(void)
258 {
259     Prepare_ThreadX();
260     /* Start ThreadX */
261     tx_kernel_enter();
262 }
263 #endif
264 
265 /*FUNCTION**********************************************************************
266  *
267  * Function Name : OSA_TaskGetCurrentHandle
268  * Description   : This function is used to get current active task's handler.
269  *
270  *END**************************************************************************/
271 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
OSA_TaskGetCurrentHandle(void)272 osa_task_handle_t OSA_TaskGetCurrentHandle(void)
273 {
274     list_element_handle_t list_element;
275     osa_thread_task_t *ptask;
276 
277     list_element = LIST_GetHead(&s_osaState.taskList);
278     while (NULL != list_element)
279     {
280         ptask = (osa_thread_task_t *)(void *)list_element;
281         if ((TX_THREAD *)&ptask->taskHandle == tx_thread_identify())
282         {
283             return (osa_task_handle_t)ptask;
284         }
285         list_element = LIST_GetNext(list_element);
286     }
287     return NULL;
288 }
289 #endif
290 
291 /*FUNCTION**********************************************************************
292  *
293  * Function Name : OSA_TaskYield
294  * Description   : When a task calls this function, it will give up CPU and put
295  * itself to the tail of ready list.
296  *
297  *END**************************************************************************/
298 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
OSA_TaskYield(void)299 void OSA_TaskYield(void)
300 {
301     tx_thread_relinquish();
302 }
303 #endif
304 
305 /*FUNCTION**********************************************************************
306  *
307  * Function Name : OSA_TaskGetPriority
308  * Description   : This function returns task's priority by task handler.
309  *
310  *END**************************************************************************/
311 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
OSA_TaskGetPriority(osa_task_handle_t taskHandle)312 osa_task_priority_t OSA_TaskGetPriority(osa_task_handle_t taskHandle)
313 {
314     assert(taskHandle);
315     osa_thread_task_t *ptask = (osa_thread_task_t *)taskHandle;
316     UINT status      = 0;
317     CHAR *task_name;
318     UINT task_status;
319     ULONG scheduled_count;
320     UINT priority_tmp;
321     UINT preempt;
322     ULONG time_slice;
323     TX_THREAD *next_thread;
324     TX_THREAD *suspended_thread;
325 
326     assert(&ptask->taskHandle != NULL);
327 
328     status = tx_thread_info_get((TX_THREAD *)&ptask->taskHandle, &task_name, &task_status, &scheduled_count,
329                                 &priority_tmp, &preempt, &time_slice, &next_thread, &suspended_thread);
330 
331     if (status != TX_SUCCESS)
332     {
333         return 0U;
334     }
335 
336     return PRIORITY_THREAD_TO_OSA(priority_tmp);
337 }
338 #endif
339 
340 /*FUNCTION**********************************************************************
341  *
342  * Function Name : OSA_TaskSetPriority
343  * Description   : This function sets task's priority by task handler.
344  * This function cannot be called within an interrupt handler, nor during
345  * the initialization phase of ThreadX.
346  *
347  *END**************************************************************************/
348 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
OSA_TaskSetPriority(osa_task_handle_t taskHandle,osa_task_priority_t taskPriority)349 osa_status_t OSA_TaskSetPriority(osa_task_handle_t taskHandle, osa_task_priority_t taskPriority)
350 {
351     assert(taskHandle);
352     osa_thread_task_t *ptask = (osa_thread_task_t *)taskHandle;
353     UINT status      = 0;
354     UINT priority;
355 
356     status = tx_thread_priority_change((TX_THREAD *)&ptask->taskHandle, PRIORITY_OSA_TO_THREAD(taskPriority), &priority);
357 
358     if (status != TX_SUCCESS)
359     {
360         return KOSA_StatusError;
361     }
362 
363     return KOSA_StatusSuccess;
364 }
365 #endif
366 
367 /*FUNCTION**********************************************************************
368  *
369  * Function Name : OSA_TaskCreate
370  * Description   : This function is used to create a task and make it ready.
371  * Param[in]     :  threadDef  - Definition of the thread.
372  *                  task_param - Parameter to pass to the new thread.
373  * Return Thread handle of the new thread, or NULL if failed.
374  *
375  *END**************************************************************************/
376 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
OSA_TaskCreate(osa_task_handle_t taskHandle,const osa_task_def_t * thread_def,osa_task_param_t task_param)377 osa_status_t OSA_TaskCreate(osa_task_handle_t taskHandle, const osa_task_def_t *thread_def, osa_task_param_t task_param)
378 {
379     assert(taskHandle);
380     osa_status_t status      = KOSA_StatusError;
381     osa_thread_task_t *ptask = (osa_thread_task_t *)taskHandle;
382 
383     if (tx_thread_create(
384             &ptask->taskHandle,                            /* task handle, allocated by application */
385             (char *)thread_def->tname,                     /* thread name */
386             (void (*)(ULONG))thread_def->pthread,          /* entry function */
387             (ULONG)((ULONG *)task_param),                  /* entry input */
388             (void *)thread_def->tstack,                    /* stack start */
389             (ULONG)thread_def->stacksize,                  /* stack size */
390             PRIORITY_OSA_TO_THREAD(thread_def->tpriority), /* initial priority */
391             PRIORITY_OSA_TO_THREAD(
392                 thread_def->tpriority), /* preempt threshold (same value than the priority means disabled) */
393             0U,                         /* time slice */
394             true                        /* auto start */
395             ) == TX_SUCCESS)
396     {
397         OSA_InterruptDisable();
398         (void)LIST_AddTail(&s_osaState.taskList, (list_element_handle_t) & (ptask->link));
399         OSA_InterruptEnable();
400         status = KOSA_StatusSuccess;
401     }
402     return status;
403 }
404 #endif
405 
406 /*FUNCTION**********************************************************************
407  *
408  * Function Name : OSA_TaskDestroy
409  * Description   : This function destroy a task.
410  * Param[in]     :taskHandle - Thread handle.
411  * Return KOSA_StatusSuccess if the task is destroied, otherwise return KOSA_StatusError.
412  *
413  *END**************************************************************************/
414 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
OSA_TaskDestroy(osa_task_handle_t taskHandle)415 osa_status_t OSA_TaskDestroy(osa_task_handle_t taskHandle)
416 {
417     assert(taskHandle);
418     osa_thread_task_t *ptask = (osa_thread_task_t *)taskHandle;
419     osa_status_t status      = KOSA_StatusSuccess;
420 
421     osa_task_priority_t oldPriority;
422     /*Change priority to avoid context switches*/
423     oldPriority = OSA_TaskGetPriority(OSA_TaskGetCurrentHandle());
424     (void)OSA_TaskSetPriority(OSA_TaskGetCurrentHandle(), OSA_PRIORITY_REAL_TIME);
425     if (TX_SUCCESS != tx_thread_delete(&ptask->taskHandle))
426     {
427         status = KOSA_StatusError;
428     }
429     (void)OSA_TaskSetPriority(OSA_TaskGetCurrentHandle(), oldPriority);
430     OSA_InterruptDisable();
431     (void)LIST_RemoveElement(taskHandle);
432     OSA_InterruptEnable();
433 
434     return status;
435 }
436 #endif
437 
438 /*FUNCTION**********************************************************************
439  *
440  * Function Name : OSA_TimeDelay
441  * Description   : This function is used to suspend the active thread for the given number of milliseconds.
442  *
443  *END**************************************************************************/
OSA_TimeDelay(uint32_t millisec)444 void OSA_TimeDelay(uint32_t millisec)
445 {
446     (void)tx_thread_sleep(millisecToTicks(millisec));
447 }
448 /*FUNCTION**********************************************************************
449  *
450  * Function Name : OSA_TimeGetMsec
451  * Description   : This function gets current time in milliseconds.
452  *
453  *END**************************************************************************/
OSA_TimeGetMsec(void)454 uint32_t OSA_TimeGetMsec(void)
455 {
456     return TICKS_TO_MSEC(tx_time_get());
457 }
458 
459 /*FUNCTION**********************************************************************
460  *
461  * Function Name : OSA_SemaphorePrecreate
462  * Description   : This function is used to pre-create a semaphore.
463  * Return         : KOSA_StatusSuccess
464  *
465  *END**************************************************************************/
466 
OSA_SemaphorePrecreate(osa_semaphore_handle_t semaphoreHandle,osa_task_ptr_t taskHandler)467 osa_status_t OSA_SemaphorePrecreate(osa_semaphore_handle_t semaphoreHandle, osa_task_ptr_t taskHandler)
468 {
469     semaphoreHandle = semaphoreHandle;
470     taskHandler     = taskHandler;
471     return KOSA_StatusSuccess;
472 }
473 
474 /*FUNCTION**********************************************************************
475  *
476  * Function Name : OSA_SemaphoreCreate
477  * Description   : This function is used to create a semaphore.
478  * Return         : Semaphore handle of the new semaphore, or NULL if failed.
479  *
480  *END**************************************************************************/
OSA_SemaphoreCreate(osa_semaphore_handle_t semaphoreHandle,uint32_t initValue)481 osa_status_t OSA_SemaphoreCreate(osa_semaphore_handle_t semaphoreHandle, uint32_t initValue)
482 {
483     osa_status_t status = KOSA_StatusSuccess;
484 
485     assert(semaphoreHandle != NULL);
486 
487     if (TX_SUCCESS != tx_semaphore_create((TX_SEMAPHORE *)semaphoreHandle, NULL, (ULONG)initValue))
488     {
489         status = KOSA_StatusError;
490     }
491 
492     return status;
493 }
494 
495 /*FUNCTION**********************************************************************
496  *
497  * Function Name : OSA_SemaphoreCreateBinary
498  * Description   : This function is used to create a binary semaphore.
499  * Return        : Semaphore handle of the new binary semaphore, or NULL if failed.
500  *
501  *END**************************************************************************/
OSA_SemaphoreCreateBinary(osa_semaphore_handle_t semaphoreHandle)502 osa_status_t OSA_SemaphoreCreateBinary(osa_semaphore_handle_t semaphoreHandle)
503 {
504     /* TODO */
505     return KOSA_StatusError;
506 }
507 
508 /*FUNCTION**********************************************************************
509  *
510  * Function Name : OSA_SemaphoreDestroy
511  * Description   : This function is used to destroy a semaphore.
512  * Return        : KOSA_StatusSuccess if the semaphore is destroyed successfully, otherwise return KOSA_StatusError.
513  *
514  *END**************************************************************************/
OSA_SemaphoreDestroy(osa_semaphore_handle_t semaphoreHandle)515 osa_status_t OSA_SemaphoreDestroy(osa_semaphore_handle_t semaphoreHandle)
516 {
517     osa_status_t status = KOSA_StatusSuccess;
518 
519     assert(semaphoreHandle != NULL);
520 
521     if (TX_SUCCESS != tx_semaphore_delete((TX_SEMAPHORE *)semaphoreHandle))
522     {
523         status = KOSA_StatusError;
524     }
525 
526     return status;
527 }
528 
529 /*FUNCTION**********************************************************************
530  *
531  * Function Name : OSA_SemaphoreWait
532  * Description   : This function checks the semaphore's counting value, if it is
533  * positive, decreases it and returns KOSA_StatusSuccess, otherwise, timeout
534  * will be used for wait. The parameter timeout indicates how long should wait
535  * in milliseconds. Pass osaWaitForever_c to wait indefinitely, pass 0 will
536  * return KOSA_StatusTimeout immediately if semaphore is not positive.
537  * This function returns KOSA_StatusSuccess if the semaphore is received, returns
538  * KOSA_StatusTimeout if the semaphore is not received within the specified
539  * 'timeout', returns KOSA_StatusError if any errors occur during waiting.
540  *
541  *END**************************************************************************/
OSA_SemaphoreWait(osa_semaphore_handle_t semaphoreHandle,uint32_t millisec)542 osa_status_t OSA_SemaphoreWait(osa_semaphore_handle_t semaphoreHandle, uint32_t millisec)
543 {
544     osa_status_t status = KOSA_StatusSuccess;
545     ULONG timeoutTicks;
546 
547     assert(semaphoreHandle != NULL);
548 
549     /* Convert timeout from millisecond to tick. */
550     if (millisec == osaWaitForever_c)
551     {
552         timeoutTicks = TX_WAIT_FOREVER;
553     }
554     else if (millisec == osaWaitNone_c)
555     {
556         timeoutTicks = TX_NO_WAIT;
557     }
558     else
559     {
560         timeoutTicks = MSEC_TO_TICK(millisec);
561     }
562 
563     if (TX_SUCCESS != tx_semaphore_get((TX_SEMAPHORE *)semaphoreHandle, timeoutTicks))
564     {
565         status = KOSA_StatusError;
566     }
567 
568     return status;
569 }
570 
571 /*FUNCTION**********************************************************************
572  *
573  * Function Name : OSA_SemaphorePost
574  * Description   : This function is used to wake up one task that wating on the
575  * semaphore. If no task is waiting, increase the semaphore. The function returns
576  * KOSA_StatusSuccess if the semaphre is post successfully, otherwise returns
577  * KOSA_StatusError.
578  *
579  *END**************************************************************************/
OSA_SemaphorePost(osa_semaphore_handle_t semaphoreHandle)580 osa_status_t OSA_SemaphorePost(osa_semaphore_handle_t semaphoreHandle)
581 {
582     osa_status_t status = KOSA_StatusSuccess;
583 
584     assert(semaphoreHandle != NULL);
585 
586     if (TX_SUCCESS != tx_semaphore_put((TX_SEMAPHORE *)semaphoreHandle))
587     {
588         status = KOSA_StatusError;
589     }
590 
591     return status;
592 }
593 
594 /*FUNCTION**********************************************************************
595  *
596  * Function Name : OSA_MutexCreate
597  * Description   : This function is used to create a mutex.
598  * Return        : KOSA_StatusSuccess if mutex is created successfully, otherwise returns
599  *                 KOSA_StatusError.
600  *
601  *END**************************************************************************/
OSA_MutexCreate(osa_mutex_handle_t mutexHandle)602 osa_status_t OSA_MutexCreate(osa_mutex_handle_t mutexHandle)
603 {
604     assert(mutexHandle);
605     osa_status_t status = KOSA_StatusSuccess;
606 
607 #ifndef CPU2
608     if (TX_SUCCESS != tx_mutex_create((TX_MUTEX *)mutexHandle, NULL, 0U))
609     {
610         status = KOSA_StatusError;
611     }
612 #endif
613     return status;
614 }
615 
616 /*FUNCTION**********************************************************************
617  *
618  * Function Name : OSA_MutexLock
619  * Description   : This function checks the mutex's status, if it is unlocked,
620  * lock it and returns KOSA_StatusSuccess, otherwise, wait for the mutex.
621  * This function returns KOSA_StatusSuccess if the mutex is obtained, returns
622  * KOSA_StatusError if any errors occur during waiting. If the mutex has been
623  * locked, pass 0 as timeout will return KOSA_StatusTimeout immediately.
624  *
625  *END**************************************************************************/
OSA_MutexLock(osa_mutex_handle_t mutexHandle,uint32_t millisec)626 osa_status_t OSA_MutexLock(osa_mutex_handle_t mutexHandle, uint32_t millisec)
627 {
628     assert(mutexHandle);
629     osa_status_t status = KOSA_StatusSuccess;
630 
631 #ifndef CPU2
632     uint32_t timeoutTicks;
633     /* Convert timeout from millisecond to tick. */
634     if (millisec == osaWaitForever_c)
635     {
636         timeoutTicks = TX_WAIT_FOREVER;
637     }
638     else
639     {
640         timeoutTicks = MSEC_TO_TICK(millisec);
641     }
642 
643     if (TX_SUCCESS != tx_mutex_get((TX_MUTEX *)mutexHandle, timeoutTicks))
644     {
645         status = KOSA_StatusError;
646     }
647 #endif
648     return status;
649 }
650 
651 /*FUNCTION**********************************************************************
652  *
653  * Function Name : OSA_MutexUnlock
654  * Description   : This function is used to unlock a mutex.
655  *
656  *END**************************************************************************/
OSA_MutexUnlock(osa_mutex_handle_t mutexHandle)657 osa_status_t OSA_MutexUnlock(osa_mutex_handle_t mutexHandle)
658 {
659     assert(mutexHandle);
660     osa_status_t status = KOSA_StatusSuccess;
661 
662 #ifndef CPU2
663     if (TX_SUCCESS != tx_mutex_put((TX_MUTEX *)mutexHandle))
664     {
665         status = KOSA_StatusError;
666     }
667 #endif
668     return status;
669 }
670 
671 /*FUNCTION**********************************************************************
672  *
673  * Function Name : OSA_MutexDestroy
674  * Description   : This function is used to destroy a mutex.
675  * Return        : KOSA_StatusSuccess if the lock object is destroyed successfully, otherwise return KOSA_StatusError.
676  *
677  *END**************************************************************************/
OSA_MutexDestroy(osa_mutex_handle_t mutexHandle)678 osa_status_t OSA_MutexDestroy(osa_mutex_handle_t mutexHandle)
679 {
680     assert(mutexHandle);
681     osa_status_t status = KOSA_StatusSuccess;
682 
683     if (TX_SUCCESS != tx_mutex_delete((TX_MUTEX *)mutexHandle))
684     {
685         status = KOSA_StatusError;
686     }
687     return status;
688 }
689 
690 /*FUNCTION**********************************************************************
691  *
692  * Function Name : OSA_EventPrecreate
693  * Description   : This function is used to pre-create a event.
694  * Return         : KOSA_StatusSuccess
695  *
696  *END**************************************************************************/
697 
OSA_EventPrecreate(osa_event_handle_t eventHandle,osa_task_ptr_t taskHandler)698 osa_status_t OSA_EventPrecreate(osa_event_handle_t eventHandle, osa_task_ptr_t taskHandler)
699 {
700     eventHandle = eventHandle;
701     taskHandler = taskHandler;
702     return KOSA_StatusSuccess;
703 }
704 
705 /*FUNCTION**********************************************************************
706  *
707  * Function Name : OSA_EventCreate
708  * Description   : This function is used to create a event object.
709  * Return        : Event handle of the new event, or NULL if failed.
710  *
711  *END**************************************************************************/
OSA_EventCreate(osa_event_handle_t eventHandle,uint8_t autoClear)712 osa_status_t OSA_EventCreate(osa_event_handle_t eventHandle, uint8_t autoClear)
713 {
714     osa_event_struct_t *pEventStruct = (osa_event_struct_t *)eventHandle;
715     osa_status_t status              = KOSA_StatusSuccess;
716 
717     assert(eventHandle != NULL);
718 
719     pEventStruct->autoClear = autoClear;
720 
721     if (TX_SUCCESS != tx_event_flags_create(&pEventStruct->eventHandle, NULL))
722     {
723         status = KOSA_StatusError;
724     }
725 
726     return status;
727 }
728 
729 /*FUNCTION**********************************************************************
730  *
731  * Function Name : OSA_EventSet
732  * Description   : Set one or more event flags of an event object.
733  * Return        : KOSA_StatusSuccess if set successfully, KOSA_StatusError if failed.
734  *
735  *END**************************************************************************/
OSA_EventSet(osa_event_handle_t eventHandle,osa_event_flags_t flagsToSet)736 osa_status_t OSA_EventSet(osa_event_handle_t eventHandle, osa_event_flags_t flagsToSet)
737 {
738     osa_event_struct_t *pEventStruct = (osa_event_struct_t *)eventHandle;
739     osa_status_t status              = KOSA_StatusSuccess;
740 
741     assert(eventHandle != NULL);
742 
743     if (TX_SUCCESS != tx_event_flags_set(&pEventStruct->eventHandle, (ULONG)flagsToSet, TX_OR))
744     {
745         status = KOSA_StatusError;
746     }
747 
748     return status;
749 }
750 
751 /*FUNCTION**********************************************************************
752  *
753  * Function Name : OSA_EventClear
754  * Description   : Clear one or more event flags of an event object.
755  * Return        :KOSA_StatusSuccess if clear successfully, KOSA_StatusError if failed.
756  *
757  *END**************************************************************************/
OSA_EventClear(osa_event_handle_t eventHandle,osa_event_flags_t flagsToClear)758 osa_status_t OSA_EventClear(osa_event_handle_t eventHandle, osa_event_flags_t flagsToClear)
759 {
760     osa_event_struct_t *pEventStruct = (osa_event_struct_t *)eventHandle;
761     osa_status_t status              = KOSA_StatusSuccess;
762 
763     assert(eventHandle != NULL);
764 
765     if (TX_SUCCESS != tx_event_flags_set(&pEventStruct->eventHandle, (ULONG)~flagsToClear, TX_AND))
766     {
767         status = KOSA_StatusError;
768     }
769 
770     return status;
771 }
772 
773 /*FUNCTION**********************************************************************
774  *
775  * Function Name : OSA_EventGet
776  * Description   : This function is used to get event's flags that specified by prameter
777  * flagsMask, and the flags (user specified) are obatianed by parameter pFlagsOfEvent. So
778  * you should pass the parameter 0xffffffff to specify you want to check all.
779  * Return        :KOSA_StatusSuccess if event flags were successfully got, KOSA_StatusError if failed.
780  *
781  *END**************************************************************************/
OSA_EventGet(osa_event_handle_t eventHandle,osa_event_flags_t flagsMask,osa_event_flags_t * pFlagsOfEvent)782 osa_status_t OSA_EventGet(osa_event_handle_t eventHandle, osa_event_flags_t flagsMask, osa_event_flags_t *pFlagsOfEvent)
783 {
784     osa_event_struct_t *pEventStruct = (osa_event_struct_t *)eventHandle;
785     osa_status_t status              = KOSA_StatusSuccess;
786     ULONG flags;
787 
788     assert(eventHandle != NULL);
789 
790     if (NULL == pFlagsOfEvent)
791     {
792         return KOSA_StatusError;
793     }
794 
795     if (TX_SUCCESS != tx_event_flags_info_get(&pEventStruct->eventHandle, NULL, &flags, NULL, NULL, NULL))
796     {
797         status = KOSA_StatusError;
798     }
799     else
800     {
801         *pFlagsOfEvent = (osa_event_flags_t)flags & flagsMask;
802     }
803 
804     return status;
805 }
806 
807 /*FUNCTION**********************************************************************
808  *
809  * Function Name : OSA_EventWait
810  * Description   : This function checks the event's status, if it meets the wait
811  * condition, return KOSA_StatusSuccess, otherwise, timeout will be used for
812  * wait. The parameter timeout indicates how long should wait in milliseconds.
813  * Pass osaWaitForever_c to wait indefinitely, pass 0 will return the value
814  * KOSA_StatusTimeout immediately if wait condition is not met. The event flags
815  * will be cleared if the event is auto clear mode. Flags that wakeup waiting
816  * task could be obtained from the parameter setFlags.
817  * This function returns KOSA_StatusSuccess if wait condition is met, returns
818  * KOSA_StatusTimeout if wait condition is not met within the specified
819  * 'timeout', returns KOSA_StatusError if any errors occur during waiting.
820  *
821  *END**************************************************************************/
OSA_EventWait(osa_event_handle_t eventHandle,osa_event_flags_t flagsToWait,uint8_t waitAll,uint32_t millisec,osa_event_flags_t * pSetFlags)822 osa_status_t OSA_EventWait(osa_event_handle_t eventHandle,
823                            osa_event_flags_t flagsToWait,
824                            uint8_t waitAll,
825                            uint32_t millisec,
826                            osa_event_flags_t *pSetFlags)
827 {
828     osa_event_struct_t *pEventStruct = (osa_event_struct_t *)eventHandle;
829     uint32_t timeoutTicks;
830     osa_event_flags_t flagsSave;
831     UINT options = 0;
832     UINT status  = 0;
833 
834     assert(eventHandle != NULL);
835 
836     /* Convert timeout from millisecond to tick. */
837     if (millisec == osaWaitForever_c)
838     {
839         timeoutTicks = TX_WAIT_FOREVER;
840     }
841     else if (millisec == osaWaitNone_c)
842     {
843         timeoutTicks = TX_NO_WAIT;
844     }
845     else
846     {
847         timeoutTicks = MSEC_TO_TICK(millisec);
848     }
849 
850     if (1U == pEventStruct->autoClear)
851     {
852         options |= TX_EVENT_FLAGS_CLEAR_MASK;
853     }
854 
855     if (1U == waitAll)
856     {
857         options |= TX_EVENT_FLAGS_AND_MASK;
858     }
859 
860     status = tx_event_flags_get(&pEventStruct->eventHandle, flagsToWait, options, (ULONG *)&flagsSave, timeoutTicks);
861     if (status != TX_SUCCESS && status != TX_NO_EVENTS)
862     {
863         return KOSA_StatusError;
864     }
865 
866     flagsSave &= (osa_event_flags_t)flagsToWait;
867 
868     if (NULL != pSetFlags)
869     {
870         *pSetFlags = (osa_event_flags_t)flagsSave;
871     }
872 
873     if (0U != flagsSave)
874     {
875         return KOSA_StatusSuccess;
876     }
877     else
878     {
879         return KOSA_StatusTimeout;
880     }
881 }
882 
883 /*FUNCTION**********************************************************************
884  *
885  * Function Name : OSA_EventDestroy
886  * Description   : This function is used to destroy a event object. Return
887  * KOSA_StatusSuccess if the event object is destroyed successfully, otherwise
888  * return KOSA_StatusError.
889  *
890  *END**************************************************************************/
OSA_EventDestroy(osa_event_handle_t eventHandle)891 osa_status_t OSA_EventDestroy(osa_event_handle_t eventHandle)
892 {
893     osa_event_struct_t *pEventStruct = (osa_event_struct_t *)eventHandle;
894     osa_status_t status              = KOSA_StatusSuccess;
895 
896     assert(eventHandle != NULL);
897 
898     if (TX_SUCCESS != tx_event_flags_delete(&pEventStruct->eventHandle))
899     {
900         status = KOSA_StatusError;
901     }
902 
903     return status;
904 }
905 
906 /*FUNCTION**********************************************************************
907  *
908  * Function Name : OSA_MsgQCreate
909  * Description   : This function is used to create a message queue.
910  * Return        : the handle to the message queue if create successfully, otherwise
911  * return NULL.
912  *
913  *END**************************************************************************/
OSA_MsgQCreate(osa_msgq_handle_t msgqHandle,uint32_t msgNo,uint32_t msgSize)914 osa_status_t OSA_MsgQCreate(osa_msgq_handle_t msgqHandle, uint32_t msgNo, uint32_t msgSize)
915 {
916     assert(NULL != msgqHandle);
917 
918     /* Create the message queue where the number and size is specified by msgNo and msgSize */
919     if (TX_SUCCESS == tx_queue_create((TX_QUEUE *)msgqHandle, (CHAR *)"queue 0", msgSize, (uint8_t *)msgqHandle + OSA_MSGQ_HANDLE_SIZE , msgNo *msgSize))
920     {
921         return KOSA_StatusSuccess;
922     }
923     return KOSA_StatusError;
924 }
925 
926 /*FUNCTION**********************************************************************
927  *
928  * Function Name : OSA_MsgQPut
929  * Description   : This function is used to put a message to a message queue.
930  * Return         : KOSA_StatusSuccess if the message is put successfully, otherwise return KOSA_StatusError.
931  *
932  *END**************************************************************************/
OSA_MsgQPut(osa_msgq_handle_t msgqHandle,osa_msg_handle_t pMessage)933 osa_status_t OSA_MsgQPut(osa_msgq_handle_t msgqHandle, osa_msg_handle_t pMessage)
934 {
935     assert(NULL != msgqHandle);
936 
937     if (TX_SUCCESS == tx_queue_send((TX_QUEUE *)msgqHandle, pMessage, TX_WAIT_FOREVER))
938     {
939         return KOSA_StatusSuccess;
940     }
941 
942     return KOSA_StatusError;
943 
944 }
945 
946 /*FUNCTION**********************************************************************
947  *
948  * Function Name : OSA_MsgQGet
949  * Description   : This function checks the queue's status, if it is not empty,
950  * get message from it and return KOSA_StatusSuccess, otherwise, timeout will
951  * be used for wait. The parameter timeout indicates how long should wait in
952  * milliseconds. Pass osaWaitForever_c to wait indefinitely, pass 0 will return
953  * KOSA_StatusTimeout immediately if queue is empty.
954  * This function returns KOSA_StatusSuccess if message is got successfully,
955  * returns KOSA_StatusTimeout if message queue is empty within the specified
956  * 'timeout', returns KOSA_StatusError if any errors occur during waiting.
957  *
958  *END**************************************************************************/
OSA_MsgQGet(osa_msgq_handle_t msgqHandle,osa_msg_handle_t pMessage,uint32_t millisec)959 osa_status_t OSA_MsgQGet(osa_msgq_handle_t msgqHandle, osa_msg_handle_t pMessage, uint32_t millisec)
960 {
961     osa_status_t osaStatus              = KOSA_StatusError;
962     assert(NULL != msgqHandle);
963 
964     uint32_t timeoutTicks;
965 
966     if (millisec == osaWaitForever_c)
967     {
968         timeoutTicks = TX_WAIT_FOREVER;
969     }
970     else
971     {
972         timeoutTicks = MSEC_TO_TICK(millisec);
973     }
974     if (TX_SUCCESS != tx_queue_receive((TX_QUEUE *)msgqHandle, pMessage, timeoutTicks))
975     {
976         osaStatus = KOSA_StatusTimeout; /* not able to send it to the queue? */
977     }
978     else
979     {
980         osaStatus = KOSA_StatusSuccess;
981     }
982     return osaStatus;
983 }
984 
985 /*FUNCTION**********************************************************************
986  *
987  * Function Name : OSA_MsgQAvailableMsgs
988  * Description   : This function is used to get the available message.
989  * Return        : Available message count
990  *
991  *END**************************************************************************/
OSA_MsgQAvailableMsgs(osa_msgq_handle_t msgqHandle)992 int OSA_MsgQAvailableMsgs(osa_msgq_handle_t msgqHandle)
993 {
994     CHAR *name;
995     ULONG enqueued;
996     ULONG available_storage;
997     TX_THREAD *first_suspended;
998     ULONG suspended_count;
999     TX_QUEUE *next_queue;
1000     assert(NULL != msgqHandle);
1001 
1002     if (TX_SUCCESS == tx_queue_info_get((TX_QUEUE *)msgqHandle, &name, &enqueued, &available_storage, &first_suspended, &suspended_count, &next_queue))
1003     {
1004        return  (int)available_storage;
1005     }
1006 
1007     return -1;
1008 }
1009 
1010 /*FUNCTION**********************************************************************
1011  *
1012  * Function Name : OSA_MsgQDestroy
1013  * Description   : This function is used to destroy the message queue.
1014  * Return        : KOSA_StatusSuccess if the message queue is destroyed successfully, otherwise return KOSA_StatusError.
1015  *
1016  *END**************************************************************************/
OSA_MsgQDestroy(osa_msgq_handle_t msgqHandle)1017 osa_status_t OSA_MsgQDestroy(osa_msgq_handle_t msgqHandle)
1018 {
1019     assert(NULL != msgqHandle);
1020 
1021     if (TX_SUCCESS == tx_queue_delete((TX_QUEUE *)msgqHandle))
1022     {
1023         return KOSA_StatusSuccess;
1024     }
1025     return KOSA_StatusError;
1026 
1027 }
1028 
1029 /*FUNCTION**********************************************************************
1030  *
1031  * Function Name : OSA_InterruptEnable
1032  * Description   : self explanatory.
1033  *
1034  *END**************************************************************************/
OSA_InterruptEnable(void)1035 void OSA_InterruptEnable(void)
1036 {
1037     (void)tx_interrupt_control(TX_INT_ENABLE);
1038 }
1039 
1040 /*FUNCTION**********************************************************************
1041  *
1042  * Function Name : OSA_InterruptDisable
1043  * Description   : self explanatory.
1044  *
1045  *END**************************************************************************/
OSA_InterruptDisable(void)1046 void OSA_InterruptDisable(void)
1047 {
1048     (void)tx_interrupt_control(TX_INT_DISABLE);
1049 }
1050 
1051 /*FUNCTION**********************************************************************
1052  *
1053  * Function Name : OSA_EnableIRQGlobal
1054  * Description   : enable interrupts using PRIMASK register.
1055  *
1056  *END**************************************************************************/
OSA_EnableIRQGlobal(void)1057 void OSA_EnableIRQGlobal(void)
1058 {
1059     TX_RESTORE
1060 }
1061 
1062 /*FUNCTION**********************************************************************
1063  *
1064  * Function Name : OSA_DisableIRQGlobal
1065  * Description   : disable interrupts using PRIMASK register.
1066  *
1067  *END**************************************************************************/
OSA_DisableIRQGlobal(void)1068 void OSA_DisableIRQGlobal(void)
1069 {
1070     TX_DISABLE
1071 }
1072 
1073 /*FUNCTION**********************************************************************
1074  *
1075  * Function Name : OSA_InstallIntHandler
1076  * Description   : This function is used to install interrupt handler.
1077  *
1078  *END**************************************************************************/
OSA_InstallIntHandler(uint32_t IRQNumber,void (* handler)(void))1079 void OSA_InstallIntHandler(uint32_t IRQNumber, void (*handler)(void))
1080 {
1081 #if defined(__IAR_SYSTEMS_ICC__)
1082     _Pragma("diag_suppress = Pm138")
1083 #endif
1084 #if defined(ENABLE_RAM_VECTOR_TABLE)
1085         (void) InstallIRQHandler((IRQn_Type)IRQNumber, (uint32_t) * (uint32_t *)&handler);
1086 #endif /* ENABLE_RAM_VECTOR_TABLE. */
1087 #if defined(__IAR_SYSTEMS_ICC__)
1088     _Pragma("diag_remark = PM138")
1089 #endif
1090 }
1091 
1092 /**
1093  * Warning: Needs to be implemented
1094  */
1095 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
OSA_TaskNotifyGet(osa_notify_time_ms_t waitTime_ms)1096 osa_status_t OSA_TaskNotifyGet(osa_notify_time_ms_t waitTime_ms)
1097 {
1098     return KOSA_StatusError;
1099 }
1100 #endif
1101 
1102 /**
1103  * Warning: Needs to be implemented
1104  */
1105 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
OSA_TaskNotifyPost(osa_task_handle_t taskHandle)1106 osa_status_t OSA_TaskNotifyPost(osa_task_handle_t taskHandle)
1107 {
1108     return KOSA_StatusError;
1109 }
1110 #endif
1111 
1112 /**
1113  * Warning: Needs to be implemented
1114  */
OSA_SemaphoreGetCount(osa_semaphore_handle_t semaphoreHandle)1115 osa_semaphore_count_t OSA_SemaphoreGetCount(osa_semaphore_handle_t semaphoreHandle)
1116 {
1117     assert(false);
1118 
1119     return 0;
1120 }