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