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