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(®Primask);
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(®Primask);
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(®Primask);
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(®Primask);
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(®Primask);
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(®Primask);
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(®Primask);
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(®Primask);
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(®Primask);
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(®Primask);
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(®Primask);
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(®Primask);
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(®Primask);
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(®Primask);
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(®Primask);
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(®Primask);
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 }