1 /*!
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2019,2022 NXP
4  *
5  *
6  * This is the source file for the OS Abstraction layer for MQXLite.
7  *
8  * SPDX-License-Identifier: BSD-3-Clause
9  */
10 
11 /*! *********************************************************************************
12 *************************************************************************************
13 * Include
14 *************************************************************************************
15 ********************************************************************************** */
16 #include "fsl_component_generic_list.h"
17 #include "fsl_os_abstraction.h"
18 #include "fsl_os_abstraction_bm.h"
19 #include <string.h>
20 
21 /*! *********************************************************************************
22 *************************************************************************************
23 * Private macros
24 *************************************************************************************
25 ********************************************************************************** */
26 
27 /* Weak function. */
28 #if defined(__GNUC__)
29 #define __WEAK_FUNC __attribute__((weak))
30 #elif defined(__ICCARM__)
31 #define __WEAK_FUNC __weak
32 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
33 #define __WEAK_FUNC __attribute__((weak))
34 #elif defined(__DSC__) || defined(__CW__)
35 #define __WEAK_FUNC __attribute__((weak))
36 #endif
37 
38 #ifdef DEBUG_ASSERT
39 #define OS_ASSERT(condition) \
40     if (!(condition))        \
41         while (1)            \
42             ;
43 #else
44 #define OS_ASSERT(condition) (void)(condition);
45 #endif
46 
47 /************************************************************************************
48 *************************************************************************************
49 * Private type definitions
50 *************************************************************************************
51 ************************************************************************************/
52 /*! @brief Type for a task handler, returned by the OSA_TaskCreate function */
53 typedef void (*task_t)(task_param_t param);
54 /*! @brief Task control block for bare metal. */
55 typedef struct TaskControlBlock
56 {
57     list_element_t link;
58     osa_task_ptr_t p_func;        /*!< Task's entry                           */
59     osa_task_priority_t priority; /*!< Task's priority                        */
60     osa_task_param_t param;       /*!< Task's parameter                       */
61     uint8_t haveToRun;            /*!< Task was signaled                      */
62 } task_control_block_t;
63 
64 /*! @brief Type for a task pointer */
65 typedef task_control_block_t *task_handler_t;
66 
67 /*! @brief Type for a task stack */
68 typedef uint32_t task_stack_t;
69 
70 /*! @brief Type for a semaphore */
71 typedef enum semaphore_type
72 {
73     KOSA_CountingSemaphore = 0U, /*!< counting semaphore */
74     KOSA_BinarySemaphore   = 1U, /*!< binary semaphore   */
75 } semaphore_type_t;
76 
77 /*! @brief Type for an semaphore */
78 typedef struct Semaphore
79 {
80 #if (defined(FSL_OSA_BM_TIMEOUT_ENABLE) && (FSL_OSA_BM_TIMEOUT_ENABLE > 0U))
81     uint32_t time_start; /*!< The time to start timeout                        */
82     uint32_t timeout;    /*!< Timeout to wait in milliseconds                  */
83 #endif
84 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
85     task_handler_t waitingTask; /*!< Handler to the waiting task                      */
86 #endif
87     volatile uint8_t isWaiting;     /*!< Is any task waiting for a timeout on this object */
88     volatile uint8_t semCount;      /*!< The count value of the object                    */
89     semaphore_type_t semaphoreType; /*!< The type of the semaphore                   */
90 } semaphore_t;
91 
92 /*! @brief Type for a mutex */
93 typedef struct Mutex
94 {
95 #if (defined(FSL_OSA_BM_TIMEOUT_ENABLE) && (FSL_OSA_BM_TIMEOUT_ENABLE > 0U))
96     uint32_t time_start; /*!< The time to start timeout                       */
97     uint32_t timeout;    /*!< Timeout to wait in milliseconds                 */
98 #endif
99     volatile uint8_t isWaiting; /*!< Is any task waiting for a timeout on this mutex */
100     volatile uint8_t isLocked;  /*!< Is the object locked or not                     */
101 } mutex_t;
102 
103 #define gIdleTaskPriority_c    ((task_priority_t)0)
104 #define gInvalidTaskPriority_c ((task_priority_t)-1)
105 /*! @brief Type for an event object */
106 typedef struct Event
107 {
108     uint32_t time_start;          /*!< The time to start timeout                        */
109     uint32_t timeout;             /*!< Timeout to wait in milliseconds                  */
110     volatile event_flags_t flags; /*!< The flags status                                 */
111 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
112     task_handler_t waitingTask; /*!< Handler to the waiting task                      */
113 #endif
114     uint8_t autoClear;          /*!< Auto clear or manual clear                       */
115     volatile uint8_t isWaiting; /*!< Is any task waiting for a timeout on this event  */
116 } event_t;
117 
118 /*! @brief Type for a message queue */
119 typedef struct MsgQueue
120 {
121     volatile uint8_t isWaiting; /*!< Is any task waiting for a timeout    */
122     uint32_t time_start;        /*!< The time to start timeout            */
123     uint32_t timeout;           /*!< Timeout to wait in milliseconds      */
124     uint32_t size;              /*!< The size(byte) of a single message   */
125 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
126     task_handler_t waitingTask; /*!< Handler to the waiting task          */
127 #endif
128     uint8_t *queueMem; /*!< Points to the queue memory           */
129     uint16_t number;   /*!< The number of messages in the queue  */
130     uint16_t max;      /*!< The max number of queue messages     */
131     uint16_t head;     /*!< Index of the next message to be read */
132     uint16_t tail;     /*!< Index of the next place to write to  */
133 } msg_queue_t;
134 
135 /*! @brief Type for a message queue handler */
136 typedef msg_queue_t *msg_queue_handler_t;
137 
138 /*! @brief State structure for bm osa manager. */
139 typedef struct _osa_state
140 {
141 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
142     list_label_t taskList;
143     task_handler_t curTaskHandler;
144 #endif
145     volatile uint32_t interruptDisableCount;
146     volatile uint32_t interruptRegPrimask;
147     volatile uint32_t tickCounter;
148 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
149 #if (defined(FSL_OSA_MAIN_FUNC_ENABLE) && (FSL_OSA_MAIN_FUNC_ENABLE > 0U))
150     OSA_TASK_HANDLE_DEFINE(mainTaskHandle);
151 #endif
152 #endif
153 } osa_state_t;
154 
155 /*! *********************************************************************************
156 *************************************************************************************
157 * Private prototypes
158 *************************************************************************************
159 ********************************************************************************** */
160 __WEAK_FUNC void main_task(osa_task_param_t arg);
main_task(osa_task_param_t arg)161 __WEAK_FUNC void main_task(osa_task_param_t arg)
162 {
163 }
164 __WEAK_FUNC void OSA_TimeInit(void);
165 __WEAK_FUNC uint32_t OSA_TimeDiff(uint32_t time_start, uint32_t time_end);
166 
167 /*! *********************************************************************************
168 *************************************************************************************
169 * Public memory declarations
170 *************************************************************************************
171 ********************************************************************************** */
172 const uint8_t gUseRtos_c = USE_RTOS; /* USE_RTOS = 0 for BareMetal and 1 for OS */
173 
174 /*! *********************************************************************************
175 *************************************************************************************
176 * Private memory declarations
177 *************************************************************************************
178 ********************************************************************************** */
179 static osa_state_t s_osaState;
180 
181 /*! *********************************************************************************
182 *************************************************************************************
183 * Public functions
184 *************************************************************************************
185 ********************************************************************************** */
186 /*FUNCTION**********************************************************************
187  *
188  * Function Name : OSA_MemoryAllocate
189  * Description   : Reserves the requested amount of memory in bytes.
190  *
191  *END**************************************************************************/
OSA_MemoryAllocate(uint32_t length)192 void *OSA_MemoryAllocate(uint32_t length)
193 {
194     void *p = (void *)malloc(length);
195 
196     if (NULL != p)
197     {
198         (void)memset(p, 0, length);
199     }
200 
201     return p;
202 }
203 
204 /*FUNCTION**********************************************************************
205  *
206  * Function Name : OSA_MemoryFree
207  * Description   : Frees the memory previously reserved.
208  *
209  *END**************************************************************************/
OSA_MemoryFree(void * p)210 void OSA_MemoryFree(void *p)
211 {
212     free(p);
213 }
214 
OSA_EnterCritical(uint32_t * sr)215 void OSA_EnterCritical(uint32_t *sr)
216 {
217     *sr = DisableGlobalIRQ();
218 }
219 
OSA_ExitCritical(uint32_t sr)220 void OSA_ExitCritical(uint32_t sr)
221 {
222     EnableGlobalIRQ(sr);
223 }
224 
225 /*FUNCTION**********************************************************************
226  *
227  * Function Name : OSA_EnableIRQGlobal
228  * Description   : Disable system interrupt.
229  *
230  *END**************************************************************************/
OSA_EnableIRQGlobal(void)231 void OSA_EnableIRQGlobal(void)
232 {
233     if (s_osaState.interruptDisableCount > 0U)
234     {
235         s_osaState.interruptDisableCount--;
236 
237         if (0U == s_osaState.interruptDisableCount)
238         {
239             EnableGlobalIRQ(s_osaState.interruptRegPrimask);
240         }
241         /* call core API to enable the global interrupt*/
242     }
243 }
244 
245 /*FUNCTION**********************************************************************
246  *
247  * Function Name : OSA_DisableIRQGlobal
248  * Description   : Disable system interrupt
249  * This function will disable the global interrupt by calling the core API
250  *
251  *END**************************************************************************/
OSA_DisableIRQGlobal(void)252 void OSA_DisableIRQGlobal(void)
253 {
254     /* call API to disable the global interrupt*/
255     if (0U == s_osaState.interruptDisableCount)
256     {
257         s_osaState.interruptRegPrimask = DisableGlobalIRQ();
258     }
259 
260     /* update counter*/
261     s_osaState.interruptDisableCount++;
262 }
263 
264 /*FUNCTION**********************************************************************
265  *
266  * Function Name : OSA_TaskGetCurrentHandle
267  * Description   : This function is used to get current active task's handler.
268  *
269  *END**************************************************************************/
270 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
OSA_TaskGetCurrentHandle(void)271 osa_task_handle_t OSA_TaskGetCurrentHandle(void)
272 {
273     return (osa_task_handle_t)s_osaState.curTaskHandler;
274 }
275 #endif
276 /*FUNCTION**********************************************************************
277  *
278  * Function Name : OSA_EXT_TaskYield
279  * Description   : When a task calls this function, it will give up CPU and put
280  * itself to the tail of ready list.
281  *
282  *END**************************************************************************/
283 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
OSA_TaskYield(void)284 void OSA_TaskYield(void)
285 {
286 }
287 #endif
288 /*FUNCTION**********************************************************************
289  *
290  * Function Name : OSA_TaskGetPriority
291  * Description   : This function returns task's priority by task handler.
292  *
293  *END**************************************************************************/
294 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
OSA_TaskGetPriority(osa_task_handle_t taskHandle)295 osa_task_priority_t OSA_TaskGetPriority(osa_task_handle_t taskHandle)
296 {
297     assert(taskHandle);
298     task_handler_t handler = (task_handler_t)taskHandle;
299     return handler->priority;
300 }
301 #endif
302 
303 /*FUNCTION**********************************************************************
304  *
305  * Function Name : OSA_TaskSetPriority
306  * Description   : This function sets task's priority by task handler.
307  *
308  *END**************************************************************************/
309 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
OSA_TaskSetPriority(osa_task_handle_t taskHandle,osa_task_priority_t taskPriority)310 osa_status_t OSA_TaskSetPriority(osa_task_handle_t taskHandle, osa_task_priority_t taskPriority)
311 {
312     assert(taskHandle);
313     list_element_handle_t list_element;
314     task_control_block_t *tcb = NULL;
315 #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
316     task_control_block_t *preTcb = NULL;
317 #endif
318     task_control_block_t *ptaskStruct = (task_control_block_t *)taskHandle;
319     uint32_t regPrimask;
320 
321     ptaskStruct->priority = taskPriority;
322     (void)LIST_RemoveElement(&ptaskStruct->link);
323     /* Insert task control block into the task list. */
324     list_element = LIST_GetHead(&s_osaState.taskList);
325     while (NULL != list_element)
326     {
327         tcb = (task_control_block_t *)(void *)list_element;
328         if (ptaskStruct->priority <= tcb->priority)
329         {
330 #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
331             if (preTcb == NULL)
332             {
333                 (&tcb->link)->list->head = (struct list_element_tag *)(void *)ptaskStruct;
334             }
335             else
336             {
337                 (&preTcb->link)->next = (struct list_element_tag *)(void *)ptaskStruct;
338             }
339             (&ptaskStruct->link)->list = (&tcb->link)->list;
340             (&ptaskStruct->link)->next = (struct list_element_tag *)(void *)tcb;
341             (&ptaskStruct->link)->list->size++;
342 #else
343             (void)LIST_AddPrevElement(&tcb->link, &ptaskStruct->link);
344 #endif
345             break;
346         }
347 #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
348         preTcb = tcb;
349 #endif
350         list_element = LIST_GetNext(list_element);
351     }
352     if (ptaskStruct->priority > tcb->priority)
353     {
354         OSA_EnterCritical(&regPrimask);
355         (void)LIST_AddTail(&s_osaState.taskList, (list_element_handle_t)(void *)&(ptaskStruct->link));
356         OSA_ExitCritical(regPrimask);
357     }
358 
359     return KOSA_StatusSuccess;
360 }
361 #endif
362 
363 /*FUNCTION**********************************************************************
364  *
365  * Function Name : OSA_TaskCreate
366  * Description   : This function is used to create a task and make it ready.
367  * Param[in]     :  threadDef  - Definition of the thread.
368  *                  task_param - Parameter to pass to the new thread.
369  * Return Thread handle of the new thread, or NULL if failed.
370  *
371  *END**************************************************************************/
372 #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)373 osa_status_t OSA_TaskCreate(osa_task_handle_t taskHandle, const osa_task_def_t *thread_def, osa_task_param_t task_param)
374 {
375     list_element_handle_t list_element;
376 
377     task_control_block_t *tcb = NULL;
378 #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
379     task_control_block_t *preTcb = NULL;
380 #endif
381     list_status_t listStatus;
382 
383     task_control_block_t *ptaskStruct = (task_control_block_t *)taskHandle;
384     uint32_t regPrimask;
385     assert(sizeof(task_control_block_t) == OSA_TASK_HANDLE_SIZE);
386     assert(taskHandle);
387 
388     ptaskStruct->p_func    = thread_def->pthread;
389     ptaskStruct->haveToRun = 1U;
390     ptaskStruct->priority  = (uint16_t)PRIORITY_OSA_TO_RTOS(thread_def->tpriority);
391     ptaskStruct->param     = task_param;
392 
393     list_element = LIST_GetHead(&s_osaState.taskList);
394     while (NULL != list_element)
395     {
396         tcb = (task_control_block_t *)(void *)list_element;
397         if (ptaskStruct->priority <= tcb->priority)
398         {
399             OSA_EnterCritical(&regPrimask);
400 #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
401             if (preTcb == NULL)
402             {
403                 (&tcb->link)->list->head = (struct list_element_tag *)(void *)ptaskStruct;
404             }
405             else
406             {
407                 (&preTcb->link)->next = (struct list_element_tag *)(void *)ptaskStruct;
408             }
409             (&ptaskStruct->link)->list = (&tcb->link)->list;
410             (&ptaskStruct->link)->next = (struct list_element_tag *)(void *)tcb;
411             (&ptaskStruct->link)->list->size++;
412             OSA_ExitCritical(regPrimask);
413             return KOSA_StatusSuccess;
414 #else
415             listStatus = LIST_AddPrevElement(&tcb->link, &ptaskStruct->link);
416             OSA_ExitCritical(regPrimask);
417             if (listStatus == (list_status_t)kLIST_DuplicateError)
418             {
419                 return KOSA_StatusError;
420             }
421             break;
422 #endif
423         }
424 #if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
425         preTcb = tcb;
426 #endif
427         list_element = LIST_GetNext(list_element);
428     }
429 
430     if ((NULL == tcb) || (ptaskStruct->priority > tcb->priority))
431     {
432         OSA_EnterCritical(&regPrimask);
433         listStatus = LIST_AddTail(&s_osaState.taskList, (list_element_handle_t)(void *)&(ptaskStruct->link));
434         (void)listStatus;
435         assert(listStatus == kLIST_Ok);
436         OSA_ExitCritical(regPrimask);
437     }
438 
439     return KOSA_StatusSuccess;
440 }
441 #endif
442 
443 /*FUNCTION**********************************************************************
444  *
445  * Function Name : OSA_TaskDestroy
446  * Description   : This function destroy a task.
447  * Param[in]     :taskHandle - Thread handle.
448  * Return KOSA_StatusSuccess if the task is destroied, otherwise return KOSA_StatusError.
449  *
450  *END**************************************************************************/
451 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
OSA_TaskDestroy(osa_task_handle_t taskHandle)452 osa_status_t OSA_TaskDestroy(osa_task_handle_t taskHandle)
453 {
454     uint32_t regPrimask;
455     assert(taskHandle);
456 
457     OSA_EnterCritical(&regPrimask);
458     (void)LIST_RemoveElement(taskHandle);
459     OSA_ExitCritical(regPrimask);
460     return KOSA_StatusSuccess;
461 }
462 #endif
463 
464 /*FUNCTION**********************************************************************
465  *
466  * Function Name : OSA_TimeInit
467  * Description   : This function initializes the timer used in BM OSA, the
468  * functions such as OSA_TimeDelay, OSA_TimeGetMsec, and the timeout are all
469  * based on this timer.
470  *
471  *END**************************************************************************/
OSA_TimeInit(void)472 __WEAK_FUNC void OSA_TimeInit(void)
473 {
474 #if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE)
475     SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk);
476     SysTick->LOAD = (uint32_t)(SystemCoreClock / 1000U - 1U);
477     SysTick->VAL  = 0;
478     SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_CLKSOURCE_Msk;
479 #endif
480 }
481 
482 /*FUNCTION**********************************************************************
483  *
484  * Function Name : OSA_TimeDiff
485  * Description   : This function gets the difference between two time stamp,
486  * time overflow is considered.
487  *
488  *END**************************************************************************/
OSA_TimeDiff(uint32_t time_start,uint32_t time_end)489 __WEAK_FUNC uint32_t OSA_TimeDiff(uint32_t time_start, uint32_t time_end)
490 {
491     if (time_end >= time_start)
492     {
493         return time_end - time_start;
494     }
495     else
496     {
497         return FSL_OSA_TIME_RANGE - time_start + time_end + 1UL;
498     }
499 }
500 
501 /*FUNCTION**********************************************************************
502  *
503  * Function Name : OSA__TimeDelay
504  * Description   : This function is used to suspend the active thread for the given number of milliseconds.
505  *
506  *END**************************************************************************/
OSA_TimeDelay(uint32_t millisec)507 void OSA_TimeDelay(uint32_t millisec)
508 {
509 #if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE)
510     uint32_t currTime, timeStart;
511 
512     timeStart = OSA_TimeGetMsec();
513 
514     do
515     {
516         currTime = OSA_TimeGetMsec(); /* Get current time stamp */
517     } while (millisec >= OSA_TimeDiff(timeStart, currTime));
518 #endif
519 }
520 /*FUNCTION**********************************************************************
521  *
522  * Function Name : OSA_TimeGetMsec
523  * Description   : This function gets current time in milliseconds.
524  *
525  *END**************************************************************************/
OSA_TimeGetMsec(void)526 __WEAK_FUNC uint32_t OSA_TimeGetMsec(void)
527 {
528 #if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE)
529     return s_osaState.tickCounter;
530 #else
531     return 0;
532 #endif
533 }
534 
535 /*FUNCTION**********************************************************************
536  *
537  * Function Name : OSA_SemaphorePrecreate
538  * Description   : This function is used to pre-create a semaphore.
539  * Return         : KOSA_StatusSuccess
540  *
541  *END**************************************************************************/
542 
OSA_SemaphorePrecreate(osa_semaphore_handle_t semaphoreHandle,osa_task_ptr_t taskHandler)543 osa_status_t OSA_SemaphorePrecreate(osa_semaphore_handle_t semaphoreHandle, osa_task_ptr_t taskHandler)
544 {
545     semaphoreHandle = semaphoreHandle;
546     taskHandler     = taskHandler;
547     return KOSA_StatusSuccess;
548 }
549 
550 /*FUNCTION**********************************************************************
551  *
552  * Function Name : OSA_SemaphoreCreate
553  * Description   : This function is used to create a counting semaphore.
554  * Return        : Semaphore handle of the new semaphore, or NULL if failed.
555  *
556  *END**************************************************************************/
557 
OSA_SemaphoreCreate(osa_semaphore_handle_t semaphoreHandle,uint32_t initValue)558 osa_status_t OSA_SemaphoreCreate(osa_semaphore_handle_t semaphoreHandle, uint32_t initValue)
559 {
560     semaphore_t *pSemStruct = (semaphore_t *)semaphoreHandle;
561     assert(sizeof(semaphore_t) <= OSA_SEM_HANDLE_SIZE);
562     assert(semaphoreHandle);
563 
564     pSemStruct->semCount      = (uint8_t)initValue;
565     pSemStruct->isWaiting     = 0U;
566     pSemStruct->semaphoreType = KOSA_CountingSemaphore;
567 #if (defined(FSL_OSA_BM_TIMEOUT_ENABLE) && (FSL_OSA_BM_TIMEOUT_ENABLE > 0U))
568 #if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE)
569 
570     pSemStruct->time_start = 0U;
571     pSemStruct->timeout    = 0U;
572 #endif
573 #endif
574 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
575     pSemStruct->waitingTask = NULL;
576 #endif
577     return KOSA_StatusSuccess;
578 }
579 
580 /*FUNCTION**********************************************************************
581  *
582  * Function Name : OSA_SemaphoreCreateBinary
583  * Description   : This function is used to create a binary semaphore.
584  * Return        : Semaphore handle of the new binary semaphore, or NULL if failed.
585  *
586  *END**************************************************************************/
OSA_SemaphoreCreateBinary(osa_semaphore_handle_t semaphoreHandle)587 osa_status_t OSA_SemaphoreCreateBinary(osa_semaphore_handle_t semaphoreHandle)
588 {
589     semaphore_t *pSemStruct = (semaphore_t *)semaphoreHandle;
590     assert(sizeof(semaphore_t) <= OSA_SEM_HANDLE_SIZE);
591     assert(semaphoreHandle);
592 
593     pSemStruct->semCount      = 1U;
594     pSemStruct->isWaiting     = 0U;
595     pSemStruct->semaphoreType = KOSA_BinarySemaphore;
596 #if (defined(FSL_OSA_BM_TIMEOUT_ENABLE) && (FSL_OSA_BM_TIMEOUT_ENABLE > 0U))
597 #if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE)
598     pSemStruct->time_start = 0U;
599     pSemStruct->timeout    = 0U;
600 #endif
601 #endif
602 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
603     pSemStruct->waitingTask = NULL;
604 #endif
605     return KOSA_StatusSuccess;
606 }
607 
608 /*FUNCTION**********************************************************************
609  *
610  * Function Name : OSA_SemaphoreDestroy
611  * Description   : This function is used to destroy a semaphore.
612  * Return        : KOSA_StatusSuccess if the semaphore is destroyed successfully, otherwise return KOSA_StatusError.
613  *
614  *END**************************************************************************/
OSA_SemaphoreDestroy(osa_semaphore_handle_t semaphoreHandle)615 osa_status_t OSA_SemaphoreDestroy(osa_semaphore_handle_t semaphoreHandle)
616 {
617     assert(semaphoreHandle);
618     semaphore_t *pSemStruct = (semaphore_t *)semaphoreHandle;
619 
620     /* Destroy semaphoreHandle's data */
621     (void)memset(pSemStruct, 0, sizeof(semaphore_t));
622 
623     return KOSA_StatusSuccess;
624 }
625 /*FUNCTION**********************************************************************
626  *
627  * Function Name : OSA_SemaphoreWait
628  * Description   : This function checks the semaphore's counting value, if it is
629  * positive, decreases it and returns KOSA_StatusSuccess, otherwise, timeout
630  * will be used for wait. The parameter timeout indicates how long should wait
631  * in milliseconds. Pass osaWaitForever_c to wait indefinitely, pass 0 will
632  * return KOSA_StatusTimeout immediately if semaphore is not positive.
633  * This function returns KOSA_StatusSuccess if the semaphore is received, returns
634  * KOSA_StatusTimeout if the semaphore is not received within the specified
635  * 'timeout', returns KOSA_StatusError if any errors occur during waiting.
636  *
637  *END**************************************************************************/
OSA_SemaphoreWait(osa_semaphore_handle_t semaphoreHandle,uint32_t millisec)638 osa_status_t OSA_SemaphoreWait(osa_semaphore_handle_t semaphoreHandle, uint32_t millisec)
639 {
640     semaphore_t *pSemStruct = (semaphore_t *)semaphoreHandle;
641     uint32_t regPrimask;
642     assert(semaphoreHandle);
643 #if (defined(FSL_OSA_BM_TIMEOUT_ENABLE) && (FSL_OSA_BM_TIMEOUT_ENABLE > 0U))
644 #if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE)
645     uint32_t currentTime;
646 #endif
647 #endif
648     /* Check the sem count first. Deal with timeout only if not already set */
649 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
650 #if (TASK_MAX_NUM > 0)
651     pSemStruct->waitingTask = OSA_TaskGetCurrentHandle();
652 #endif
653 #endif
654     if (0U != pSemStruct->semCount)
655     {
656         OSA_EnterCritical(&regPrimask);
657         pSemStruct->semCount--;
658         pSemStruct->isWaiting = 0U;
659         OSA_ExitCritical(regPrimask);
660         return KOSA_StatusSuccess;
661     }
662     else
663     {
664         if (0U == millisec)
665         {
666             /* If timeout is 0 and semaphore is not available, return kStatus_OSA_Timeout. */
667             return KOSA_StatusTimeout;
668         }
669 #if (defined(FSL_OSA_BM_TIMEOUT_ENABLE) && (FSL_OSA_BM_TIMEOUT_ENABLE > 0U))
670 #if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE)
671         else if (0U != pSemStruct->isWaiting)
672         {
673             /* Check for timeout */
674             currentTime = OSA_TimeGetMsec();
675             if (pSemStruct->timeout < OSA_TimeDiff(pSemStruct->time_start, currentTime))
676             {
677                 OSA_EnterCritical(&regPrimask);
678                 pSemStruct->isWaiting = 0U;
679                 OSA_ExitCritical(regPrimask);
680                 return KOSA_StatusTimeout;
681             }
682         }
683         else if (millisec != osaWaitForever_c) /* If don't wait forever, start the timer */
684         {
685             /* Start the timeout counter */
686             OSA_EnterCritical(&regPrimask);
687             pSemStruct->isWaiting = 1U;
688             OSA_ExitCritical(regPrimask);
689             pSemStruct->time_start = OSA_TimeGetMsec();
690             pSemStruct->timeout    = millisec;
691         }
692 #endif
693 #endif
694         else
695         {
696 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
697             pSemStruct->waitingTask->haveToRun = 0U;
698 #endif
699         }
700     }
701 
702     return KOSA_StatusIdle;
703 }
704 /*FUNCTION**********************************************************************
705  *
706  * Function Name : OSA_SemaphorePost
707  * Description   : This function is used to wake up one task that wating on the
708  * semaphore. If no task is waiting, increase the semaphore. The function returns
709  * KOSA_StatusSuccess if the semaphre is post successfully, otherwise returns
710  * KOSA_StatusError.
711  *
712  *END**************************************************************************/
OSA_SemaphorePost(osa_semaphore_handle_t semaphoreHandle)713 osa_status_t OSA_SemaphorePost(osa_semaphore_handle_t semaphoreHandle)
714 {
715     semaphore_t *pSemStruct = (semaphore_t *)semaphoreHandle;
716     uint32_t regPrimask;
717     assert(semaphoreHandle);
718 
719     /* check whether max value is reached */
720     if (((KOSA_CountingSemaphore == pSemStruct->semaphoreType) &&
721          (0xFFU == pSemStruct->semCount)) || /* For counting semaphore: the max value is 0xFF */
722         ((0x01U == pSemStruct->semCount) &&
723          (KOSA_BinarySemaphore == pSemStruct->semaphoreType))) /* For binary semaphore: the max value is 0x01   */
724     {
725         return KOSA_StatusError;
726     }
727 
728     OSA_EnterCritical(&regPrimask);
729     ++pSemStruct->semCount;
730 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
731     if (pSemStruct->waitingTask != NULL)
732     {
733         pSemStruct->waitingTask->haveToRun = 1U;
734     }
735 #endif
736 
737     OSA_ExitCritical(regPrimask);
738 
739     return KOSA_StatusSuccess;
740 }
741 
742 /*FUNCTION**********************************************************************
743  *
744  * Function Name : OSA_MutexCreate
745  * Description   : This function is used to create a mutex.
746  * Return        : Mutex handle of the new mutex, or NULL if failed.
747  *
748  *END**************************************************************************/
OSA_MutexCreate(osa_mutex_handle_t mutexHandle)749 osa_status_t OSA_MutexCreate(osa_mutex_handle_t mutexHandle)
750 {
751     mutex_t *pMutexStruct = (mutex_t *)mutexHandle;
752     assert(sizeof(mutex_t) <= OSA_MUTEX_HANDLE_SIZE);
753     assert(mutexHandle);
754 
755     pMutexStruct->isLocked  = 0U;
756     pMutexStruct->isWaiting = 0U;
757 #if (defined(FSL_OSA_BM_TIMEOUT_ENABLE) && (FSL_OSA_BM_TIMEOUT_ENABLE > 0U))
758 #if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE)
759 
760     pMutexStruct->time_start = 0u;
761     pMutexStruct->timeout    = 0u;
762 #endif
763 #endif
764     return KOSA_StatusSuccess;
765 }
766 
767 /*FUNCTION**********************************************************************
768  *
769  * Function Name : OSA_MutexLock
770  * Description   : This function checks the mutex's status, if it is unlocked,
771  * lock it and returns KOSA_StatusSuccess, otherwise, wait for the mutex.
772  * MQX does not support timeout to wait for a mutex.
773  * This function returns KOSA_StatusSuccess if the mutex is obtained, returns
774  * KOSA_StatusError if any errors occur during waiting. If the mutex has been
775  * locked, pass 0 as timeout will return KOSA_StatusTimeout immediately.
776  *
777  *END**************************************************************************/
OSA_MutexLock(osa_mutex_handle_t mutexHandle,uint32_t millisec)778 osa_status_t OSA_MutexLock(osa_mutex_handle_t mutexHandle, uint32_t millisec)
779 {
780 #if (defined(FSL_OSA_BM_TIMEOUT_ENABLE) && (FSL_OSA_BM_TIMEOUT_ENABLE > 0U))
781 #if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE)
782     uint32_t currentTime;
783 #endif
784 #endif
785     mutex_t *pMutexStruct = (mutex_t *)mutexHandle;
786     uint32_t regPrimask;
787 
788     /* Always check first. Deal with timeout only if not available. */
789     if (0U == pMutexStruct->isLocked)
790     {
791         /* Get the lock and return success */
792         OSA_EnterCritical(&regPrimask);
793         pMutexStruct->isLocked  = 1U;
794         pMutexStruct->isWaiting = 0U;
795         OSA_ExitCritical(regPrimask);
796         return KOSA_StatusSuccess;
797     }
798     else
799     {
800         if (0U == millisec)
801         {
802             /* If timeout is 0 and mutex is not available, return kStatus_OSA_Timeout. */
803             return KOSA_StatusTimeout;
804         }
805 #if (defined(FSL_OSA_BM_TIMEOUT_ENABLE) && (FSL_OSA_BM_TIMEOUT_ENABLE > 0U))
806 #if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE)
807         else if (pMutexStruct->isWaiting != 0U)
808         {
809             /* Check for timeout */
810             currentTime = OSA_TimeGetMsec();
811             if (pMutexStruct->timeout < OSA_TimeDiff(pMutexStruct->time_start, currentTime))
812             {
813                 OSA_EnterCritical(&regPrimask);
814                 pMutexStruct->isWaiting = 0U;
815                 OSA_ExitCritical(regPrimask);
816                 return KOSA_StatusTimeout;
817             }
818         }
819         else if (millisec != osaWaitForever_c) /* If dont't wait forever, start timer. */
820         {
821             /* Start the timeout counter */
822             OSA_EnterCritical(&regPrimask);
823             pMutexStruct->isWaiting = 1U;
824             OSA_ExitCritical(regPrimask);
825             pMutexStruct->time_start = OSA_TimeGetMsec();
826             pMutexStruct->timeout    = millisec;
827         }
828 #endif
829 #endif
830         else
831         {
832             ;
833         }
834     }
835 
836     return KOSA_StatusIdle;
837 }
838 /*FUNCTION**********************************************************************
839  *
840  * Function Name : OSA_MutexUnlock
841  * Description   : This function is used to unlock a mutex.
842  *
843  *END**************************************************************************/
OSA_MutexUnlock(osa_mutex_handle_t mutexHandle)844 osa_status_t OSA_MutexUnlock(osa_mutex_handle_t mutexHandle)
845 {
846     mutex_t *pMutexStruct = (mutex_t *)mutexHandle;
847     uint32_t regPrimask;
848     assert(mutexHandle);
849 
850     OSA_EnterCritical(&regPrimask);
851     pMutexStruct->isLocked = 0U;
852     OSA_ExitCritical(regPrimask);
853     return KOSA_StatusSuccess;
854 }
855 /*FUNCTION**********************************************************************
856  *
857  * Function Name : OSA_MutexDestroy
858  * Description   : This function is used to destroy a mutex.
859  * Return        : KOSA_StatusSuccess if the lock object is destroyed successfully, otherwise return KOSA_StatusError.
860  *
861  *END**************************************************************************/
OSA_MutexDestroy(osa_mutex_handle_t mutexHandle)862 osa_status_t OSA_MutexDestroy(osa_mutex_handle_t mutexHandle)
863 {
864     assert(mutexHandle);
865     mutex_t *pMutexStruct = (mutex_t *)mutexHandle;
866 
867     /* Destory mutexHandle's data */
868     (void)memset(pMutexStruct, 0, sizeof(mutex_t));
869 
870     return KOSA_StatusSuccess;
871 }
872 
873 /*FUNCTION**********************************************************************
874  *
875  * Function Name : OSA_EventPrecreate
876  * Description   : This function is used to pre-create a event.
877  * Return         : KOSA_StatusSuccess
878  *
879  *END**************************************************************************/
880 
OSA_EventPrecreate(osa_event_handle_t eventHandle,osa_task_ptr_t taskHandler)881 osa_status_t OSA_EventPrecreate(osa_event_handle_t eventHandle, osa_task_ptr_t taskHandler)
882 {
883     eventHandle = eventHandle;
884     taskHandler = taskHandler;
885     return KOSA_StatusSuccess;
886 }
887 
888 /*FUNCTION**********************************************************************
889  *
890  * Function Name : OSA_EventCreate
891  * Description   : This function is used to create a event object.
892  * Return        : Event handle of the new event, or NULL if failed.
893  *
894  *END**************************************************************************/
OSA_EventCreate(osa_event_handle_t eventHandle,uint8_t autoClear)895 osa_status_t OSA_EventCreate(osa_event_handle_t eventHandle, uint8_t autoClear)
896 {
897     event_t *pEventStruct = eventHandle;
898     assert(sizeof(event_t) == OSA_EVENT_HANDLE_SIZE);
899     assert(eventHandle);
900 
901     pEventStruct->isWaiting  = 0U;
902     pEventStruct->flags      = 0;
903     pEventStruct->autoClear  = autoClear;
904     pEventStruct->time_start = 0u;
905     pEventStruct->timeout    = 0u;
906 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
907     pEventStruct->waitingTask = NULL;
908 #endif
909     return KOSA_StatusSuccess;
910 }
911 /*FUNCTION**********************************************************************
912  *
913  * Function Name : OSA_EventSet
914  * Description   : Set one or more event flags of an event object.
915  * Return        : KOSA_StatusSuccess if set successfully, KOSA_StatusError if failed.
916  *
917  *END**************************************************************************/
OSA_EventSet(osa_event_handle_t eventHandle,osa_event_flags_t flagsToSet)918 osa_status_t OSA_EventSet(osa_event_handle_t eventHandle, osa_event_flags_t flagsToSet)
919 {
920     event_t *pEventStruct;
921     uint32_t regPrimask;
922     pEventStruct = (event_t *)eventHandle;
923     /* Set flags ensuring atomic operation */
924     OSA_EnterCritical(&regPrimask);
925     pEventStruct->flags |= flagsToSet;
926 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
927     if (pEventStruct->waitingTask != NULL)
928     {
929         pEventStruct->waitingTask->haveToRun = 1U;
930     }
931 #endif
932     OSA_ExitCritical(regPrimask);
933 
934     return KOSA_StatusSuccess;
935 }
936 /*FUNCTION**********************************************************************
937  *
938  * Function Name : OSA_EventClear
939  * Description   : Clear one or more event flags of an event object.
940  * Return        :KOSA_StatusSuccess if clear successfully, KOSA_StatusError if failed.
941  *
942  *END**************************************************************************/
OSA_EventClear(osa_event_handle_t eventHandle,osa_event_flags_t flagsToClear)943 osa_status_t OSA_EventClear(osa_event_handle_t eventHandle, osa_event_flags_t flagsToClear)
944 {
945     event_t *pEventStruct;
946     uint32_t regPrimask;
947     pEventStruct = (event_t *)eventHandle;
948     /* Clear flags ensuring atomic operation */
949     OSA_EnterCritical(&regPrimask);
950     pEventStruct->flags &= ~flagsToClear;
951     if (0U != pEventStruct->flags)
952     {
953 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
954         if (NULL != pEventStruct->waitingTask)
955         {
956             pEventStruct->waitingTask->haveToRun = 1U;
957         }
958 #endif
959     }
960     OSA_ExitCritical(regPrimask);
961 
962     return KOSA_StatusSuccess;
963 }
964 /*FUNCTION**********************************************************************
965  *
966  * Function Name : OSA_EventGet
967  * Description   : This function is used to get event's flags that specified by prameter
968  * flagsMask, and the flags (user specified) are obatianed by parameter pFlagsOfEvent. So
969  * you should pass the parameter 0xffffffff to specify you want to get all.
970  * Return        :KOSA_StatusSuccess if event flags were successfully got, KOSA_StatusError if failed.
971  *
972  *END**************************************************************************/
OSA_EventGet(osa_event_handle_t eventHandle,osa_event_flags_t flagsMask,osa_event_flags_t * pFlagsOfEvent)973 osa_status_t OSA_EventGet(osa_event_handle_t eventHandle, osa_event_flags_t flagsMask, osa_event_flags_t *pFlagsOfEvent)
974 {
975     event_t *pEventStruct;
976     uint32_t regPrimask;
977     pEventStruct = (event_t *)eventHandle;
978 
979     if (NULL == pFlagsOfEvent)
980     {
981         return KOSA_StatusError;
982     }
983 
984     OSA_EnterCritical(&regPrimask);
985     *pFlagsOfEvent = pEventStruct->flags & flagsMask;
986     OSA_ExitCritical(regPrimask);
987 
988     return KOSA_StatusSuccess;
989 }
990 /*FUNCTION**********************************************************************
991  *
992  * Function Name : OSA_EventWait
993  * Description   : This function checks the event's status, if it meets the wait
994  * condition, return KOSA_StatusSuccess, otherwise, timeout will be used for
995  * wait. The parameter timeout indicates how long should wait in milliseconds.
996  * Pass osaWaitForever_c to wait indefinitely, pass 0 will return the value
997  * KOSA_StatusTimeout immediately if wait condition is not met. The event flags
998  * will be cleared if the event is auto clear mode. Flags that wakeup waiting
999  * task could be obtained from the parameter setFlags.
1000  * This function returns KOSA_StatusSuccess if wait condition is met, returns
1001  * KOSA_StatusTimeout if wait condition is not met within the specified
1002  * 'timeout', returns KOSA_StatusError if any errors occur during waiting.
1003  *
1004  *END**************************************************************************/
OSA_EventWait(osa_event_handle_t eventHandle,osa_event_flags_t flagsToWait,uint8_t waitAll,uint32_t millisec,osa_event_flags_t * pSetFlags)1005 osa_status_t OSA_EventWait(osa_event_handle_t eventHandle,
1006                            osa_event_flags_t flagsToWait,
1007                            uint8_t waitAll,
1008                            uint32_t millisec,
1009                            osa_event_flags_t *pSetFlags)
1010 {
1011     event_t *pEventStruct;
1012     uint32_t regPrimask;
1013 #if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE)
1014     uint32_t currentTime;
1015 #endif
1016     osa_status_t retVal = KOSA_StatusIdle;
1017     if (NULL == pSetFlags)
1018     {
1019         return KOSA_StatusError;
1020     }
1021 
1022     pEventStruct = (event_t *)eventHandle;
1023 
1024     OSA_EnterCritical(&regPrimask);
1025 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
1026 #if (TASK_MAX_NUM > 0)
1027     pEventStruct->waitingTask = OSA_TaskGetCurrentHandle();
1028 #endif
1029 #endif
1030 
1031     *pSetFlags = pEventStruct->flags & flagsToWait;
1032 
1033     /* Check the event flag first, if does not meet wait condition, deal with timeout. */
1034     if (((0U == waitAll) && (0U != *pSetFlags)) || (*pSetFlags == flagsToWait))
1035     {
1036         pEventStruct->isWaiting = 0U;
1037         if (1U == pEventStruct->autoClear)
1038         {
1039             pEventStruct->flags &= ~flagsToWait;
1040         }
1041         retVal = KOSA_StatusSuccess;
1042     }
1043     else
1044     {
1045         if (0U == millisec)
1046         {
1047             /* If timeout is 0 and wait condition is not met, return kStatus_OSA_Timeout. */
1048             retVal = KOSA_StatusTimeout;
1049         }
1050 #if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE)
1051         else if (0U != pEventStruct->isWaiting)
1052         {
1053             /* Check for timeout */
1054             currentTime = OSA_TimeGetMsec();
1055             if (pEventStruct->timeout < OSA_TimeDiff(pEventStruct->time_start, currentTime))
1056             {
1057                 pEventStruct->isWaiting = 0U;
1058                 retVal                  = KOSA_StatusTimeout;
1059             }
1060         }
1061         else if (millisec != osaWaitForever_c) /* If no timeout, don't start the timer */
1062         {
1063             /* Start the timeout counter */
1064             pEventStruct->isWaiting  = 1U;
1065             pEventStruct->time_start = OSA_TimeGetMsec();
1066             pEventStruct->timeout    = millisec;
1067         }
1068 #endif
1069         else
1070         {
1071 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
1072             pEventStruct->waitingTask->haveToRun = 0U;
1073 #endif
1074         }
1075     }
1076 
1077     OSA_ExitCritical(regPrimask);
1078 
1079     return retVal;
1080 }
1081 /*FUNCTION**********************************************************************
1082  *
1083  * Function Name : OSA_EventDestroy
1084  * Description   : This function is used to destroy a event object. Return
1085  * KOSA_StatusSuccess if the event object is destroyed successfully, otherwise
1086  * return KOSA_StatusError.
1087  *
1088  *END**************************************************************************/
OSA_EventDestroy(osa_event_handle_t eventHandle)1089 osa_status_t OSA_EventDestroy(osa_event_handle_t eventHandle)
1090 {
1091     assert(eventHandle);
1092     event_t *pEventStruct = (event_t *)eventHandle;
1093 
1094     /* Destroy eventHandle's data */
1095     (void)memset(pEventStruct, 0, sizeof(event_t));
1096 
1097     return KOSA_StatusSuccess;
1098 }
1099 
1100 /*FUNCTION**********************************************************************
1101  *
1102  * Function Name : OSA_MsgQCreate
1103  * Description   : This function is used to create a message queue.
1104  * Return        : the handle to the message queue if create successfully, otherwise
1105  * return NULL.
1106  *
1107  *END**************************************************************************/
OSA_MsgQCreate(osa_msgq_handle_t msgqHandle,uint32_t msgNo,uint32_t msgSize)1108 osa_status_t OSA_MsgQCreate(osa_msgq_handle_t msgqHandle, uint32_t msgNo, uint32_t msgSize)
1109 {
1110     msg_queue_t *pMsgQStruct = msgqHandle;
1111     assert(sizeof(msg_queue_t) == OSA_MSGQ_HANDLE_SIZE);
1112     assert(msgqHandle);
1113 
1114     pMsgQStruct->max      = (uint16_t)msgNo;
1115     pMsgQStruct->number   = 0;
1116     pMsgQStruct->head     = 0;
1117     pMsgQStruct->tail     = 0;
1118     pMsgQStruct->size     = msgSize;
1119     pMsgQStruct->queueMem = (uint8_t *)((uint8_t *)msgqHandle + sizeof(msg_queue_t));
1120     return KOSA_StatusSuccess;
1121 }
1122 
1123 /*FUNCTION**********************************************************************
1124  *
1125  * Function Name : OSA_MsgQPut
1126  * Description   : This function is used to put a message to a message queue.
1127  * Return         : KOSA_StatusSuccess if the message is put successfully, otherwise return KOSA_StatusError.
1128  *
1129  *END**************************************************************************/
OSA_MsgQPut(osa_msgq_handle_t msgqHandle,osa_msg_handle_t pMessage)1130 osa_status_t OSA_MsgQPut(osa_msgq_handle_t msgqHandle, osa_msg_handle_t pMessage)
1131 {
1132     assert(msgqHandle);
1133     msg_queue_t *pQueue;
1134     osa_status_t status = KOSA_StatusSuccess;
1135     uint32_t regPrimask;
1136 
1137     uint8_t *pMsgArray;
1138 
1139     pQueue = (msg_queue_t *)msgqHandle;
1140 
1141     if (NULL == pQueue->queueMem)
1142     {
1143         return KOSA_StatusError;
1144     }
1145 
1146     OSA_EnterCritical(&regPrimask);
1147     if (pQueue->number >= pQueue->max)
1148     {
1149         status = KOSA_StatusError;
1150     }
1151     else
1152     {
1153         pMsgArray = &pQueue->queueMem[pQueue->tail];
1154         for (uint32_t i = 0; i < pQueue->size; i++)
1155         {
1156             pMsgArray[i] = *((uint8_t *)pMessage + i);
1157         }
1158 
1159         pQueue->number++;
1160         pQueue->tail += (uint16_t)pQueue->size;
1161 
1162         if (pQueue->tail >= (pQueue->max * pQueue->size))
1163         {
1164             pQueue->tail = 0;
1165         }
1166 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
1167         if (NULL != pQueue->waitingTask)
1168         {
1169             pQueue->waitingTask->haveToRun = 1U;
1170         }
1171 #endif
1172     }
1173     OSA_ExitCritical(regPrimask);
1174     return status;
1175 }
1176 /*FUNCTION**********************************************************************
1177  *
1178  * Function Name : OSA_MsgQGet
1179  * Description   : This function checks the queue's status, if it is not empty,
1180  * get message from it and return KOSA_StatusSuccess, otherwise, timeout will
1181  * be used for wait. The parameter timeout indicates how long should wait in
1182  * milliseconds. Pass osaWaitForever_c to wait indefinitely, pass 0 will return
1183  * KOSA_StatusTimeout immediately if queue is empty.
1184  * This function returns KOSA_StatusSuccess if message is got successfully,
1185  * returns KOSA_StatusTimeout if message queue is empty within the specified
1186  * 'timeout', returns KOSA_StatusError if any errors occur during waiting.
1187  *
1188  *END**************************************************************************/
OSA_MsgQGet(osa_msgq_handle_t msgqHandle,osa_msg_handle_t pMessage,uint32_t millisec)1189 osa_status_t OSA_MsgQGet(osa_msgq_handle_t msgqHandle, osa_msg_handle_t pMessage, uint32_t millisec)
1190 {
1191     assert(msgqHandle);
1192     msg_queue_t *pQueue;
1193     osa_status_t status = KOSA_StatusSuccess;
1194     uint32_t regPrimask;
1195 
1196     uint8_t *pMsgArray;
1197 
1198 #if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE)
1199     uint32_t currentTime;
1200 #endif
1201 
1202     pQueue = (msg_queue_t *)msgqHandle;
1203 
1204     if (NULL == pQueue->queueMem)
1205     {
1206         return KOSA_StatusError;
1207     }
1208 
1209 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
1210     pQueue->waitingTask = OSA_TaskGetCurrentHandle();
1211 #endif
1212 
1213     OSA_EnterCritical(&regPrimask);
1214     if (0U != pQueue->number)
1215     {
1216         pMsgArray = (uint8_t *)pMessage;
1217         for (uint32_t i = 0; i < pQueue->size; i++)
1218         {
1219             pMsgArray[i] = pQueue->queueMem[pQueue->head + i];
1220         }
1221 
1222         pQueue->number--;
1223         pQueue->head += (uint16_t)pQueue->size;
1224         pQueue->isWaiting = 0U;
1225 
1226         if (pQueue->head >= (pQueue->max * pQueue->size))
1227         {
1228             pQueue->head = 0;
1229         }
1230         status = KOSA_StatusSuccess;
1231     }
1232     else
1233     {
1234         if (0U == millisec)
1235         {
1236             /* If timeout is 0 and wait condition is not met, return kStatus_OSA_Timeout. */
1237             status = KOSA_StatusTimeout;
1238         }
1239 #if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE)
1240         else if (0U != pQueue->isWaiting)
1241         {
1242             /* Check for timeout */
1243             status      = KOSA_StatusIdle; /* Before a timeout, the status should be idle. */
1244             currentTime = OSA_TimeGetMsec();
1245             if (pQueue->timeout < OSA_TimeDiff(pQueue->time_start, currentTime))
1246             {
1247                 pQueue->isWaiting = 0U;
1248                 status            = KOSA_StatusTimeout;
1249             }
1250         }
1251         else if (millisec != osaWaitForever_c) /* If no timeout, don't start the timer */
1252         {
1253             /* Start the timeout counter */
1254             pQueue->isWaiting  = 1U;
1255             pQueue->time_start = OSA_TimeGetMsec();
1256             pQueue->timeout    = millisec;
1257             status             = KOSA_StatusIdle;
1258         }
1259 #endif
1260         else
1261         {
1262 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
1263             pQueue->waitingTask->haveToRun = 0U;
1264 #endif
1265             status = KOSA_StatusIdle;
1266         }
1267     }
1268     OSA_ExitCritical(regPrimask);
1269 
1270     return status;
1271 }
1272 
1273 /*FUNCTION**********************************************************************
1274  *
1275  * Function Name : OSA_MsgQAvailableMsgs
1276  * Description   : This function is used to get the available message.
1277  * Return        : Available message count
1278  *
1279  *END**************************************************************************/
OSA_MsgQAvailableMsgs(osa_msgq_handle_t msgqHandle)1280 int OSA_MsgQAvailableMsgs(osa_msgq_handle_t msgqHandle)
1281 {
1282     assert(msgqHandle);
1283     msg_queue_t *pQueue = (msg_queue_t *)msgqHandle;
1284 
1285     return (int)pQueue->number;
1286 }
1287 
1288 /*FUNCTION**********************************************************************
1289  *
1290  * Function Name : OSA_EXT_MsgQDestroy
1291  * Description   : This function is used to destroy the message queue.
1292  * Return        : KOSA_StatusSuccess if the message queue is destroyed successfully, otherwise return KOSA_StatusError.
1293  *
1294  *END**************************************************************************/
OSA_MsgQDestroy(osa_msgq_handle_t msgqHandle)1295 osa_status_t OSA_MsgQDestroy(osa_msgq_handle_t msgqHandle)
1296 {
1297     assert(msgqHandle);
1298     msg_queue_t *pQueue = (msg_queue_t *)msgqHandle;
1299 
1300     /* Destory msgqHandle's data */
1301     /* OSA_MsgQGet() & OSA_MsgQPut() will check queueMem, if NULL will return an error. */
1302     (void)memset(pQueue, 0, sizeof(msg_queue_t));
1303 
1304     return KOSA_StatusSuccess;
1305 }
1306 
1307 /*FUNCTION**********************************************************************
1308  *
1309  * Function Name : OSA_InterruptEnable
1310  * Description   : self explanatory.
1311  *
1312  *END**************************************************************************/
OSA_InterruptEnable(void)1313 void OSA_InterruptEnable(void)
1314 {
1315     OSA_EnableIRQGlobal();
1316 }
1317 /*FUNCTION**********************************************************************
1318  *
1319  * Function Name : OSA_InterruptDisable
1320  * Description   : self explanatory.
1321  *
1322  *END**************************************************************************/
OSA_InterruptDisable(void)1323 void OSA_InterruptDisable(void)
1324 {
1325     OSA_DisableIRQGlobal();
1326 }
1327 
1328 /*FUNCTION**********************************************************************
1329  *
1330  * Function Name : OSA_InstallIntHandler
1331  * Description   : This function is used to install interrupt handler.
1332  *
1333  *END**************************************************************************/
OSA_InstallIntHandler(uint32_t IRQNumber,void (* handler)(void))1334 void OSA_InstallIntHandler(uint32_t IRQNumber, void (*handler)(void))
1335 {
1336 #if defined(__IAR_SYSTEMS_ICC__)
1337     _Pragma("diag_suppress = Pm138")
1338 #endif
1339 #if defined(ENABLE_RAM_VECTOR_TABLE)
1340         (void) InstallIRQHandler((IRQn_Type)IRQNumber, (uint32_t) * (uint32_t *)&handler);
1341 #endif /* ENABLE_RAM_VECTOR_TABLE. */
1342 #if defined(__IAR_SYSTEMS_ICC__)
1343     _Pragma("diag_remark = PM138")
1344 #endif
1345 }
1346 
1347 /*! *********************************************************************************
1348 *************************************************************************************
1349 * Private functions
1350 *************************************************************************************
1351 ********************************************************************************** */
1352 #if ((defined(FSL_OSA_TASK_ENABLE)) && (FSL_OSA_TASK_ENABLE > 0U))
1353 #if (defined(FSL_OSA_MAIN_FUNC_ENABLE) && (FSL_OSA_MAIN_FUNC_ENABLE > 0U))
1354 static OSA_TASK_DEFINE(main_task, gMainThreadPriority_c, 1, gMainThreadStackSize_c, 0);
1355 
main(void)1356 void main(void)
1357 {
1358     OSA_Init();
1359 
1360     /* Initialize MCU clock */
1361     extern void BOARD_InitHardware(void);
1362     BOARD_InitHardware();
1363 
1364     (void)OSA_TaskCreate((osa_task_handle_t)s_osaState.mainTaskHandle, OSA_TASK(main_task), NULL);
1365 
1366     OSA_Start();
1367 }
1368 #endif /*(defined(FSL_OSA_MAIN_FUNC_ENABLE) && (FSL_OSA_MAIN_FUNC_ENABLE > 0U))*/
1369 #endif /* FSL_OSA_TASK_ENABLE */
1370 
1371 /*FUNCTION**********************************************************************
1372  *
1373  * Function Name : OSA_Init
1374  * Description   : This function is used to setup the basic services, it should
1375  * be called first in function main.
1376  *
1377  *END**************************************************************************/
1378 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
OSA_Init(void)1379 void OSA_Init(void)
1380 {
1381     LIST_Init((&s_osaState.taskList), 0);
1382     s_osaState.curTaskHandler        = NULL;
1383     s_osaState.interruptDisableCount = 0U;
1384     s_osaState.tickCounter           = 0U;
1385 }
1386 #endif
1387 
1388 /*FUNCTION**********************************************************************
1389  *
1390  * Function Name : OSA_Start
1391  * Description   : This function is used to start RTOS scheduler.
1392  *
1393  *END**************************************************************************/
1394 #if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U))
OSA_Start(void)1395 void OSA_Start(void)
1396 {
1397 #if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE)
1398     OSA_TimeInit();
1399 #endif
1400     while (true)
1401     {
1402         OSA_ProcessTasks();
1403     }
1404 }
1405 
1406 /*FUNCTION**********************************************************************
1407  *
1408  * Function Name : OSA_ProcessTasks
1409  * Description   : This function is used to process registered tasks.
1410  *
1411  *END**************************************************************************/
OSA_ProcessTasks(void)1412 void OSA_ProcessTasks(void)
1413 {
1414     list_element_handle_t list_element;
1415     task_control_block_t *tcb;
1416 
1417     list_element = LIST_GetHead(&s_osaState.taskList);
1418     while (NULL != list_element)
1419     {
1420         tcb                       = (task_control_block_t *)(void *)list_element;
1421         s_osaState.curTaskHandler = (osa_task_handle_t)tcb;
1422         if (0U != tcb->haveToRun)
1423         {
1424             if (NULL != tcb->p_func)
1425             {
1426                 tcb->p_func(tcb->param);
1427             }
1428             list_element = LIST_GetHead(&s_osaState.taskList);
1429         }
1430         else
1431         {
1432             list_element = LIST_GetNext(list_element);
1433         }
1434     }
1435 }
1436 
1437 /*FUNCTION**********************************************************************
1438  *
1439  * Function Name : OSA_TaskShouldYield
1440  * Description   : When this function returns TRUE, an OSA task  has to run
1441  *
1442  *END**************************************************************************/
OSA_TaskShouldYield(void)1443 uint8_t OSA_TaskShouldYield(void)
1444 {
1445     list_element_handle_t list_element;
1446     uint8_t status = 0;
1447     task_control_block_t *tcb;
1448 
1449     list_element = LIST_GetHead(&s_osaState.taskList);
1450     while ((list_element != NULL))
1451     {
1452         tcb = (task_control_block_t *)(void *)list_element;
1453         if (1U == tcb->haveToRun)
1454         {
1455             status = 1U;
1456             break;
1457         }
1458         list_element = LIST_GetNext(list_element);
1459     }
1460     return status;
1461 }
1462 #endif
1463 
1464 /*FUNCTION**********************************************************************
1465  *
1466  * Function Name : SysTick_Handler
1467  * Description   : This ISR of the SYSTICK timer.
1468  *
1469  *END**************************************************************************/
1470 #if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE)
1471 void SysTick_Handler(void);
SysTick_Handler(void)1472 void SysTick_Handler(void)
1473 {
1474     s_osaState.tickCounter++;
1475 }
1476 #endif
1477