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