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