1 /***********************************************************************************************//**
2  * \file cyabs_rtos_rtxv5.c
3  *
4  * \brief
5  * Implementation for CMSIS RTOS v2 abstraction
6  *
7  ***************************************************************************************************
8  * \copyright
9  * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
10  * an affiliate of Cypress Semiconductor Corporation
11  *
12  * SPDX-License-Identifier: Apache-2.0
13  *
14  * Licensed under the Apache License, Version 2.0 (the "License");
15  * you may not use this file except in compliance with the License.
16  * You may obtain a copy of the License at
17  *
18  *     http://www.apache.org/licenses/LICENSE-2.0
19  *
20  * Unless required by applicable law or agreed to in writing, software
21  * distributed under the License is distributed on an "AS IS" BASIS,
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23  * See the License for the specific language governing permissions and
24  * limitations under the License.
25  **************************************************************************************************/
26 
27 #include <stdlib.h>
28 #include <cy_utils.h>
29 #include <cyabs_rtos.h>
30 #include "cyabs_rtos_internal.h"
31 
32 #if defined(__cplusplus)
33 extern "C" {
34 #endif
35 
36 #define CY_RTOS_THREAD_FLAG 0x01
37 
38 /******************************************************
39 *                 Error Converter
40 ******************************************************/
41 
42 // Last received error status
43 static cy_rtos_error_t dbgErr;
44 
45 
46 //--------------------------------------------------------------------------------------------------
47 // cy_rtos_last_error
48 //--------------------------------------------------------------------------------------------------
cy_rtos_last_error(void)49 cy_rtos_error_t cy_rtos_last_error(void)
50 {
51     return dbgErr;
52 }
53 
54 
55 //--------------------------------------------------------------------------------------------------
56 // error_converter
57 //
58 // Converts internal error type to external error type
59 //--------------------------------------------------------------------------------------------------
error_converter(cy_rtos_error_t internalError)60 static cy_rslt_t error_converter(cy_rtos_error_t internalError)
61 {
62     cy_rslt_t value;
63 
64     switch (internalError)
65     {
66         case osOK:
67             value = CY_RSLT_SUCCESS;
68             break;
69 
70         case osErrorTimeout:
71             value = CY_RTOS_TIMEOUT;
72             break;
73 
74         case osErrorParameter:
75             value = CY_RTOS_BAD_PARAM;
76             break;
77 
78         case osErrorNoMemory:
79             value = CY_RTOS_NO_MEMORY;
80             break;
81 
82         case osError:
83         case osErrorResource:
84         case osErrorISR:
85         default:
86             value = CY_RTOS_GENERAL_ERROR;
87             break;
88     }
89 
90     // Update the last known error status
91     dbgErr = internalError;
92     return value;
93 }
94 
95 
96 //--------------------------------------------------------------------------------------------------
97 // convert_ms_to_ticks
98 //--------------------------------------------------------------------------------------------------
convert_ms_to_ticks(cy_time_t timeout_ms)99 static uint32_t convert_ms_to_ticks(cy_time_t timeout_ms)
100 {
101     if (timeout_ms == CY_RTOS_NEVER_TIMEOUT)
102     {
103         return osWaitForever;
104     }
105     else if (timeout_ms == 0)
106     {
107         return 0;
108     }
109     else
110     {
111         // Get number of ticks per second
112         uint32_t tick_freq = osKernelGetTickFreq();
113         uint32_t ticks = (uint32_t)(((uint64_t)timeout_ms * tick_freq) / 1000);
114 
115         if (ticks == 0)
116         {
117             ticks = 1;
118         }
119         else if (ticks >= UINT32_MAX)
120         {
121             // if ticks if more than 32 bits, change ticks to max possible value that isn't
122             // osWaitForever.
123             ticks = UINT32_MAX - 1;
124         }
125         return ticks;
126     }
127 }
128 
129 
130 /******************************************************
131 *                 Threads
132 ******************************************************/
133 
cy_rtos_thread_create(cy_thread_t * thread,cy_thread_entry_fn_t entry_function,const char * name,void * stack,uint32_t stack_size,cy_thread_priority_t priority,cy_thread_arg_t arg)134 cy_rslt_t cy_rtos_thread_create(cy_thread_t* thread, cy_thread_entry_fn_t entry_function,
135                                 const char* name, void* stack, uint32_t stack_size,
136                                 cy_thread_priority_t priority, cy_thread_arg_t arg)
137 {
138     cy_rslt_t      status = CY_RSLT_SUCCESS;
139     osThreadAttr_t attr;
140 
141     if ((thread == NULL) || (stack_size < CY_RTOS_MIN_STACK_SIZE))
142     {
143         status = CY_RTOS_BAD_PARAM;
144     }
145     else if ((stack != NULL) && (0 != (((uint32_t)stack) & CY_RTOS_ALIGNMENT_MASK)))
146     {
147         status = CY_RTOS_ALIGNMENT_ERROR;
148     }
149     else
150     {
151         attr.name       = name;
152         attr.attr_bits  = osThreadJoinable;
153         attr.cb_size    = osRtxThreadCbSize;
154         attr.stack_size = stack_size;
155         attr.priority   = (osPriority_t)priority;
156         attr.tz_module  = 0;
157         attr.reserved   = 0;
158 
159         // Allocate stack if NULL was passed
160         if ((uint32_t*)stack == NULL)
161         {
162             // Note: 1 malloc so that it can be freed with 1 call when terminating
163             uint32_t cb_mem_pad = (~osRtxThreadCbSize + 1) & CY_RTOS_ALIGNMENT_MASK;
164             attr.cb_mem = malloc(osRtxThreadCbSize + cb_mem_pad + stack_size);
165             if (attr.cb_mem != NULL)
166             {
167                 attr.stack_mem =
168                     (uint32_t*)((uint32_t)attr.cb_mem + osRtxThreadCbSize + cb_mem_pad);
169             }
170         }
171         else
172         {
173             attr.cb_mem    = malloc(osRtxThreadCbSize);
174             attr.stack_mem = stack;
175         }
176 
177         if (attr.cb_mem == NULL)
178         {
179             status = CY_RTOS_NO_MEMORY;
180         }
181         else
182         {
183             CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL);
184             CY_ASSERT(((uint32_t)attr.stack_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL);
185             *thread = osThreadNew((osThreadFunc_t)entry_function, arg, &attr);
186             CY_ASSERT((*thread == attr.cb_mem) || (*thread == NULL));
187             status = (*thread == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS;
188         }
189     }
190 
191     return status;
192 }
193 
194 
195 //--------------------------------------------------------------------------------------------------
196 // cy_rtos_thread_exit
197 //--------------------------------------------------------------------------------------------------
cy_rtos_thread_exit(void)198 cy_rslt_t cy_rtos_thread_exit(void)
199 {
200     // This does not have a return statement because the osThreadExit() function * does not return
201     // so the return statement would be unreachable and causes a * warning for IAR compiler.
202     osThreadExit();
203 }
204 
205 
206 //--------------------------------------------------------------------------------------------------
207 // cy_rtos_thread_terminate
208 //--------------------------------------------------------------------------------------------------
cy_rtos_thread_terminate(cy_thread_t * thread)209 cy_rslt_t cy_rtos_thread_terminate(cy_thread_t* thread)
210 {
211     cy_rslt_t       status;
212     cy_rtos_error_t statusInternal;
213 
214     if (thread == NULL)
215     {
216         status = CY_RTOS_BAD_PARAM;
217     }
218     else
219     {
220         statusInternal = osThreadTerminate(*thread);
221         status         = error_converter(statusInternal);
222     }
223 
224     return status;
225 }
226 
227 
228 //--------------------------------------------------------------------------------------------------
229 // cy_rtos_thread_is_running
230 //--------------------------------------------------------------------------------------------------
cy_rtos_thread_is_running(cy_thread_t * thread,bool * running)231 cy_rslt_t cy_rtos_thread_is_running(cy_thread_t* thread, bool* running)
232 {
233     cy_rslt_t status = CY_RSLT_SUCCESS;
234 
235     if ((thread == NULL) || (running == NULL))
236     {
237         status = CY_RTOS_BAD_PARAM;
238     }
239     else
240     {
241         *running = (osThreadGetState(*thread) == osThreadRunning) ? true : false;
242     }
243 
244     return status;
245 }
246 
247 
248 //--------------------------------------------------------------------------------------------------
249 // cy_rtos_thread_get_state
250 //--------------------------------------------------------------------------------------------------
cy_rtos_thread_get_state(cy_thread_t * thread,cy_thread_state_t * state)251 cy_rslt_t cy_rtos_thread_get_state(cy_thread_t* thread, cy_thread_state_t* state)
252 {
253     cy_rslt_t status = CY_RSLT_SUCCESS;
254 
255     if ((thread == NULL) || (state == NULL))
256     {
257         status = CY_RTOS_BAD_PARAM;
258     }
259     else
260     {
261         switch (osThreadGetState(*thread))
262         {
263             case osThreadInactive:
264                 *state = CY_THREAD_STATE_INACTIVE;
265                 break;
266 
267             case osThreadReady:
268                 *state = CY_THREAD_STATE_READY;
269                 break;
270 
271             case osThreadRunning:
272                 *state = CY_THREAD_STATE_RUNNING;
273                 break;
274 
275             case osThreadBlocked:
276                 *state = CY_THREAD_STATE_BLOCKED;
277                 break;
278 
279             case osThreadTerminated:
280                 *state = CY_THREAD_STATE_TERMINATED;
281                 break;
282 
283             case osThreadError:
284             case osThreadReserved:
285             default:
286                 *state = CY_THREAD_STATE_UNKNOWN;
287                 break;
288         }
289     }
290 
291     return status;
292 }
293 
294 
295 //--------------------------------------------------------------------------------------------------
296 // cy_rtos_thread_join
297 //--------------------------------------------------------------------------------------------------
cy_rtos_thread_join(cy_thread_t * thread)298 cy_rslt_t cy_rtos_thread_join(cy_thread_t* thread)
299 {
300     cy_rslt_t       status;
301     cy_rtos_error_t statusInternal;
302 
303     if (thread == NULL)
304     {
305         status = CY_RTOS_BAD_PARAM;
306     }
307     else
308     {
309         statusInternal = osThreadJoin(*thread);
310         status         = error_converter(statusInternal);
311 
312         if (status == CY_RSLT_SUCCESS)
313         {
314             free(*thread);
315             *thread = NULL;
316         }
317     }
318 
319     return status;
320 }
321 
322 
323 //--------------------------------------------------------------------------------------------------
324 // cy_rtos_thread_get_handle
325 //--------------------------------------------------------------------------------------------------
cy_rtos_thread_get_handle(cy_thread_t * thread)326 cy_rslt_t cy_rtos_thread_get_handle(cy_thread_t* thread)
327 {
328     cy_rslt_t status = CY_RSLT_SUCCESS;
329 
330     if (thread == NULL)
331     {
332         status = CY_RTOS_BAD_PARAM;
333     }
334     else
335     {
336         *thread = osThreadGetId();
337     }
338 
339     return status;
340 }
341 
342 
343 //--------------------------------------------------------------------------------------------------
344 // cy_rtos_thread_wait_notification
345 //--------------------------------------------------------------------------------------------------
cy_rtos_thread_wait_notification(cy_time_t timeout_ms)346 cy_rslt_t cy_rtos_thread_wait_notification(cy_time_t timeout_ms)
347 {
348     uint32_t ret;
349     cy_rslt_t status = CY_RSLT_SUCCESS;
350     ret = osThreadFlagsWait(CY_RTOS_THREAD_FLAG, osFlagsWaitAll, convert_ms_to_ticks(timeout_ms));
351     if (ret & osFlagsError)
352     {
353         status = (ret == osFlagsErrorTimeout) ? CY_RTOS_TIMEOUT : CY_RTOS_GENERAL_ERROR;
354         // Update the last known error status
355         dbgErr = (cy_rtos_error_t)ret;
356     }
357     return status;
358 }
359 
360 
361 //--------------------------------------------------------------------------------------------------
362 // cy_rtos_thread_set_notification
363 //--------------------------------------------------------------------------------------------------
cy_rtos_thread_set_notification(cy_thread_t * thread)364 cy_rslt_t cy_rtos_thread_set_notification(cy_thread_t* thread)
365 {
366     cy_rslt_t status = CY_RSLT_SUCCESS;
367     uint32_t ret;
368 
369     if (thread == NULL)
370     {
371         status = CY_RTOS_BAD_PARAM;
372     }
373     else
374     {
375         /* According to the description of CMSIS-RTOS v2
376          * osThreadFlagsSet() can be called inside ISR
377          */
378         ret = osThreadFlagsSet(*thread, CY_RTOS_THREAD_FLAG);
379         if (ret & osFlagsError)
380         {
381             status = CY_RTOS_GENERAL_ERROR;
382             // Update the last known error status
383             dbgErr = (cy_rtos_error_t)ret;
384         }
385     }
386     return status;
387 }
388 
389 
390 //--------------------------------------------------------------------------------------------------
391 // cy_rtos_thread_get_name
392 //--------------------------------------------------------------------------------------------------
cy_rtos_thread_get_name(cy_thread_t * thread,const char ** thread_name)393 cy_rslt_t cy_rtos_thread_get_name(cy_thread_t* thread, const char** thread_name)
394 {
395     *thread_name = osThreadGetName(*thread);
396     return CY_RSLT_SUCCESS;
397 }
398 
399 
400 /******************************************************
401 *                 Scheduler
402 ******************************************************/
403 static uint16_t _cy_rtos_suspend_count = 0;
404 
405 //--------------------------------------------------------------------------------------------------
406 // cy_rtos_scheduler_suspend
407 //--------------------------------------------------------------------------------------------------
cy_rtos_scheduler_suspend(void)408 cy_rslt_t cy_rtos_scheduler_suspend(void)
409 {
410     ++_cy_rtos_suspend_count;
411     osKernelLock();
412 
413     return CY_RSLT_SUCCESS;
414 }
415 
416 
417 //--------------------------------------------------------------------------------------------------
418 // cy_rtos_scheduler_resume
419 //--------------------------------------------------------------------------------------------------
cy_rtos_scheduler_resume(void)420 cy_rslt_t cy_rtos_scheduler_resume(void)
421 {
422     cy_rslt_t status;
423     if (_cy_rtos_suspend_count > 0)
424     {
425         --_cy_rtos_suspend_count;
426         osKernelUnlock();
427         status = CY_RSLT_SUCCESS;
428     }
429     else
430     {
431         status = CY_RTOS_BAD_PARAM;
432     }
433 
434     return status;
435 }
436 
437 
438 /******************************************************
439 *                 Mutexes
440 ******************************************************/
441 
cy_rtos_mutex_init(cy_mutex_t * mutex,bool recursive)442 cy_rslt_t cy_rtos_mutex_init(cy_mutex_t* mutex, bool recursive)
443 {
444     cy_rslt_t     status;
445     osMutexAttr_t attr;
446 
447     if (mutex == NULL)
448     {
449         status = CY_RTOS_BAD_PARAM;
450     }
451     else
452     {
453         attr.name      = NULL;
454         attr.attr_bits = osMutexPrioInherit;
455         if (recursive)
456         {
457             attr.attr_bits |= osMutexRecursive;
458         }
459         attr.cb_mem  = malloc(osRtxMutexCbSize);
460         attr.cb_size = osRtxMutexCbSize;
461 
462         if (attr.cb_mem == NULL)
463         {
464             status = CY_RTOS_NO_MEMORY;
465         }
466         else
467         {
468             CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL);
469             *mutex = osMutexNew(&attr);
470             CY_ASSERT((*mutex == attr.cb_mem) || (*mutex == NULL));
471             status = (*mutex == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS;
472         }
473     }
474 
475     return status;
476 }
477 
478 
479 //--------------------------------------------------------------------------------------------------
480 // cy_rtos_mutex_get
481 //--------------------------------------------------------------------------------------------------
cy_rtos_mutex_get(cy_mutex_t * mutex,cy_time_t timeout_ms)482 cy_rslt_t cy_rtos_mutex_get(cy_mutex_t* mutex, cy_time_t timeout_ms)
483 {
484     cy_rslt_t       status;
485     cy_rtos_error_t statusInternal;
486 
487     if (mutex == NULL)
488     {
489         status = CY_RTOS_BAD_PARAM;
490     }
491     else
492     {
493         statusInternal = osMutexAcquire(*mutex, timeout_ms);
494         status         = error_converter(statusInternal);
495     }
496 
497     return status;
498 }
499 
500 
501 //--------------------------------------------------------------------------------------------------
502 // cy_rtos_mutex_set
503 //--------------------------------------------------------------------------------------------------
cy_rtos_mutex_set(cy_mutex_t * mutex)504 cy_rslt_t cy_rtos_mutex_set(cy_mutex_t* mutex)
505 {
506     cy_rslt_t       status;
507     cy_rtos_error_t statusInternal;
508 
509     if (mutex == NULL)
510     {
511         status = CY_RTOS_BAD_PARAM;
512     }
513     else
514     {
515         statusInternal = osMutexRelease(*mutex);
516         status         = error_converter(statusInternal);
517     }
518 
519     return status;
520 }
521 
522 
523 //--------------------------------------------------------------------------------------------------
524 // cy_rtos_mutex_deinit
525 //--------------------------------------------------------------------------------------------------
cy_rtos_mutex_deinit(cy_mutex_t * mutex)526 cy_rslt_t cy_rtos_mutex_deinit(cy_mutex_t* mutex)
527 {
528     cy_rslt_t       status;
529     cy_rtos_error_t statusInternal;
530 
531     if (mutex == NULL)
532     {
533         status = CY_RTOS_BAD_PARAM;
534     }
535     else
536     {
537         statusInternal = osMutexDelete(*mutex);
538         status         = error_converter(statusInternal);
539 
540         if (status == CY_RSLT_SUCCESS)
541         {
542             free(*mutex);
543             *mutex = NULL;
544         }
545     }
546 
547     return status;
548 }
549 
550 
551 /******************************************************
552 *                 Semaphores
553 ******************************************************/
554 
cy_rtos_semaphore_init(cy_semaphore_t * semaphore,uint32_t maxcount,uint32_t initcount)555 cy_rslt_t cy_rtos_semaphore_init(cy_semaphore_t* semaphore, uint32_t maxcount, uint32_t initcount)
556 {
557     cy_rslt_t         status;
558     osSemaphoreAttr_t attr;
559 
560     if (semaphore == NULL)
561     {
562         status = CY_RTOS_BAD_PARAM;
563     }
564     else
565     {
566         attr.name      = NULL;
567         attr.attr_bits = 0U;
568         attr.cb_mem    = malloc(osRtxSemaphoreCbSize);
569         attr.cb_size   = osRtxSemaphoreCbSize;
570 
571         if (attr.cb_mem == NULL)
572         {
573             status = CY_RTOS_NO_MEMORY;
574         }
575         else
576         {
577             CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL);
578             *semaphore = osSemaphoreNew(maxcount, initcount, &attr);
579             CY_ASSERT((*semaphore == attr.cb_mem) || (*semaphore == NULL));
580             status = (*semaphore == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS;
581         }
582     }
583 
584     return status;
585 }
586 
587 
588 //--------------------------------------------------------------------------------------------------
589 // cy_rtos_semaphore_get
590 //--------------------------------------------------------------------------------------------------
cy_rtos_semaphore_get(cy_semaphore_t * semaphore,cy_time_t timeout_ms)591 cy_rslt_t cy_rtos_semaphore_get(cy_semaphore_t* semaphore, cy_time_t timeout_ms)
592 {
593     cy_rslt_t       status = CY_RSLT_SUCCESS;
594     cy_rtos_error_t statusInternal;
595     bool in_isr = is_in_isr();
596     // Based on documentation when osSemaphoreAcquire is called from ISR timeout must be zero.
597     // https://www.keil.com/pack/doc/CMSIS/RTOS2/html/group__CMSIS__RTOS__SemaphoreMgmt.html#ga7e94c8b242a0c81f2cc79ec22895c87b
598     if ((semaphore == NULL) || (in_isr && (timeout_ms != 0)))
599     {
600         status = CY_RTOS_BAD_PARAM;
601     }
602     else
603     {
604         statusInternal = osSemaphoreAcquire(*semaphore, timeout_ms);
605         status = error_converter(statusInternal);
606     }
607 
608     return status;
609 }
610 
611 
612 //--------------------------------------------------------------------------------------------------
613 // cy_rtos_semaphore_set
614 //--------------------------------------------------------------------------------------------------
cy_rtos_semaphore_set(cy_semaphore_t * semaphore)615 cy_rslt_t cy_rtos_semaphore_set(cy_semaphore_t* semaphore)
616 {
617     cy_rslt_t       status = CY_RSLT_SUCCESS;
618     cy_rtos_error_t statusInternal;
619 
620     if (semaphore == NULL)
621     {
622         status = CY_RTOS_BAD_PARAM;
623     }
624     else
625     {
626         statusInternal = osSemaphoreRelease(*semaphore);
627         status         = error_converter(statusInternal);
628     }
629 
630     return status;
631 }
632 
633 
634 //--------------------------------------------------------------------------------------------------
635 // cy_rtos_semaphore_get_count
636 //--------------------------------------------------------------------------------------------------
cy_rtos_semaphore_get_count(cy_semaphore_t * semaphore,size_t * count)637 cy_rslt_t cy_rtos_semaphore_get_count(cy_semaphore_t* semaphore, size_t* count)
638 {
639     cy_rslt_t status;
640     if ((semaphore == NULL) || (count == NULL))
641     {
642         status = CY_RTOS_BAD_PARAM;
643     }
644     else
645     {
646         *count = osSemaphoreGetCount(*semaphore);
647         status = CY_RSLT_SUCCESS;
648     }
649     return status;
650 }
651 
652 
653 //--------------------------------------------------------------------------------------------------
654 // cy_rtos_semaphore_deinit
655 //--------------------------------------------------------------------------------------------------
cy_rtos_deinit_semaphore(cy_semaphore_t * semaphore)656 cy_rslt_t cy_rtos_deinit_semaphore(cy_semaphore_t* semaphore)
657 {
658     cy_rslt_t       status;
659     cy_rtos_error_t statusInternal;
660 
661     if (semaphore == NULL)
662     {
663         status = CY_RTOS_BAD_PARAM;
664     }
665     else
666     {
667         statusInternal = osSemaphoreDelete(*semaphore);
668         status         = error_converter(statusInternal);
669         if (status == CY_RSLT_SUCCESS)
670         {
671             free(*semaphore);
672             *semaphore = NULL;
673         }
674     }
675 
676     return status;
677 }
678 
679 
680 /******************************************************
681 *                 Events
682 ******************************************************/
683 
684 #define CY_RTOS_EVENT_ERRORFLAG     0x80000000UL
685 #define CY_RTOS_EVENT_FLAGS         0x7FFFFFFFUL
686 
687 //--------------------------------------------------------------------------------------------------
688 // cy_rtos_event_init
689 //--------------------------------------------------------------------------------------------------
cy_rtos_event_init(cy_event_t * event)690 cy_rslt_t cy_rtos_event_init(cy_event_t* event)
691 {
692     cy_rslt_t          status;
693     osEventFlagsAttr_t attr;
694 
695     if (event == NULL)
696     {
697         status = CY_RTOS_BAD_PARAM;
698     }
699     else
700     {
701         attr.name      = NULL;
702         attr.attr_bits = 0U;
703         attr.cb_mem    = malloc(osRtxEventFlagsCbSize);
704         attr.cb_size   = osRtxEventFlagsCbSize;
705 
706         if (attr.cb_mem == NULL)
707         {
708             status = CY_RTOS_NO_MEMORY;
709         }
710         else
711         {
712             CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL);
713             *event = osEventFlagsNew(&attr);
714             CY_ASSERT((*event == attr.cb_mem) || (*event == NULL));
715             status = (*event == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS;
716         }
717     }
718 
719     return status;
720 }
721 
722 
723 //--------------------------------------------------------------------------------------------------
724 // cy_rtos_event_setbits
725 //--------------------------------------------------------------------------------------------------
cy_rtos_event_setbits(cy_event_t * event,uint32_t bits)726 cy_rslt_t cy_rtos_event_setbits(cy_event_t* event, uint32_t bits)
727 {
728     cy_rslt_t       status = CY_RSLT_SUCCESS;
729     cy_rtos_error_t statusInternal;
730 
731     if (event == NULL)
732     {
733         status = CY_RTOS_BAD_PARAM;
734     }
735     else
736     {
737         statusInternal = (osStatus_t)osEventFlagsSet(*event, bits);
738         if ((statusInternal & CY_RTOS_EVENT_ERRORFLAG) != 0UL)
739         {
740             status = error_converter(statusInternal);
741         }
742     }
743 
744     return status;
745 }
746 
747 
748 //--------------------------------------------------------------------------------------------------
749 // cy_rtos_event_clearbits
750 //--------------------------------------------------------------------------------------------------
cy_rtos_event_clearbits(cy_event_t * event,uint32_t bits)751 cy_rslt_t cy_rtos_event_clearbits(cy_event_t* event, uint32_t bits)
752 {
753     cy_rslt_t       status = CY_RSLT_SUCCESS;
754     cy_rtos_error_t statusInternal;
755 
756     if (event == NULL)
757     {
758         status = CY_RTOS_BAD_PARAM;
759     }
760     else
761     {
762         statusInternal = (osStatus_t)osEventFlagsClear(*event, bits);
763         if ((statusInternal & CY_RTOS_EVENT_ERRORFLAG) != 0UL)
764         {
765             status = error_converter(statusInternal);
766         }
767     }
768 
769     return status;
770 }
771 
772 
773 //--------------------------------------------------------------------------------------------------
774 // cy_rtos_event_getbits
775 //--------------------------------------------------------------------------------------------------
cy_rtos_event_getbits(cy_event_t * event,uint32_t * bits)776 cy_rslt_t cy_rtos_event_getbits(cy_event_t* event, uint32_t* bits)
777 {
778     cy_rslt_t status = CY_RSLT_SUCCESS;
779 
780     if ((event == NULL) || (bits == NULL))
781     {
782         status = CY_RTOS_BAD_PARAM;
783     }
784     else
785     {
786         *bits = osEventFlagsGet(*event);
787     }
788 
789     return status;
790 }
791 
792 
793 //--------------------------------------------------------------------------------------------------
794 // cy_rtos_event_waitbits
795 //--------------------------------------------------------------------------------------------------
cy_rtos_event_waitbits(cy_event_t * event,uint32_t * bits,bool clear,bool all,cy_time_t timeout_ms)796 cy_rslt_t cy_rtos_event_waitbits(cy_event_t* event, uint32_t* bits, bool clear, bool all,
797                                  cy_time_t timeout_ms)
798 {
799     cy_rslt_t       status = CY_RSLT_SUCCESS;
800     cy_rtos_error_t statusInternal;
801     uint32_t        flagOption;
802 
803     if ((event == NULL) || (bits == NULL))
804     {
805         status = CY_RTOS_BAD_PARAM;
806     }
807     else
808     {
809         flagOption = (all) ? osFlagsWaitAll : osFlagsWaitAny;
810         if (!clear)
811         {
812             flagOption |= osFlagsNoClear;
813         }
814 
815         statusInternal = (osStatus_t)osEventFlagsWait(*event, *bits, flagOption, timeout_ms);
816         if ((statusInternal & CY_RTOS_EVENT_ERRORFLAG) == 0UL)
817         {
818             *bits = statusInternal;
819         }
820         else
821         {
822             status = error_converter(statusInternal);
823         }
824     }
825 
826     return status;
827 }
828 
829 
830 //--------------------------------------------------------------------------------------------------
831 // cy_rtos_event_deinit
832 //--------------------------------------------------------------------------------------------------
cy_rtos_event_deinit(cy_event_t * event)833 cy_rslt_t cy_rtos_event_deinit(cy_event_t* event)
834 {
835     cy_rslt_t       status;
836     cy_rtos_error_t statusInternal;
837 
838     if (event == NULL)
839     {
840         status = CY_RTOS_BAD_PARAM;
841     }
842     else
843     {
844         statusInternal = osEventFlagsDelete(*event);
845         status         = error_converter(statusInternal);
846         if (status == CY_RSLT_SUCCESS)
847         {
848             free(*event);
849             *event = NULL;
850         }
851     }
852 
853     return status;
854 }
855 
856 
857 /******************************************************
858 *                 Queues
859 ******************************************************/
860 
cy_rtos_queue_init(cy_queue_t * queue,size_t length,size_t itemsize)861 cy_rslt_t cy_rtos_queue_init(cy_queue_t* queue, size_t length, size_t itemsize)
862 {
863     cy_rslt_t            status;
864     osMessageQueueAttr_t attr;
865 
866     if (queue == NULL)
867     {
868         status = CY_RTOS_BAD_PARAM;
869     }
870     else
871     {
872         attr.name      = NULL;
873         attr.attr_bits = 0U;
874         attr.cb_size   = osRtxMessageQueueCbSize;
875         uint32_t blockSize = ((itemsize + 3U) & ~3UL) + sizeof(osRtxMessage_t);
876         attr.mq_size = blockSize * length;
877 
878         // Note: 1 malloc for both so that they can be freed with 1 call
879         uint32_t cb_mem_pad = (8 - (osRtxMessageQueueCbSize & 0x07)) & 0x07;
880         attr.cb_mem = malloc(osRtxMessageQueueCbSize + cb_mem_pad + attr.mq_size);
881         if (attr.cb_mem != NULL)
882         {
883             attr.mq_mem = (uint32_t*)((uint32_t)attr.cb_mem + osRtxMessageQueueCbSize + cb_mem_pad);
884         }
885 
886         if (attr.cb_mem == NULL)
887         {
888             status = CY_RTOS_NO_MEMORY;
889         }
890         else
891         {
892             CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL);
893             CY_ASSERT(((uint32_t)attr.mq_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL);
894             *queue = osMessageQueueNew(length, itemsize, &attr);
895             CY_ASSERT((*queue == attr.cb_mem) || (*queue == NULL));
896             status = (*queue == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS;
897         }
898     }
899 
900     return status;
901 }
902 
903 
904 //--------------------------------------------------------------------------------------------------
905 // cy_rtos_queue_put
906 //--------------------------------------------------------------------------------------------------
cy_rtos_queue_put(cy_queue_t * queue,const void * item_ptr,cy_time_t timeout_ms)907 cy_rslt_t cy_rtos_queue_put(cy_queue_t* queue, const void* item_ptr, cy_time_t timeout_ms)
908 {
909     cy_rslt_t       status;
910     cy_rtos_error_t statusInternal;
911     bool in_isr = is_in_isr();
912 
913     if ((queue == NULL) || (item_ptr == NULL))
914     {
915         status = CY_RTOS_BAD_PARAM;
916     }
917     else
918     {
919         // Not allowed to be called in ISR if timeout != 0
920         if ((!in_isr) || (in_isr && (timeout_ms == 0U)))
921         {
922             statusInternal = osMessageQueuePut(*queue, (uint8_t*)item_ptr, 0u, timeout_ms);
923         }
924         else
925         {
926             statusInternal = osErrorISR;
927         }
928 
929         status = error_converter(statusInternal);
930     }
931 
932     return status;
933 }
934 
935 
936 //--------------------------------------------------------------------------------------------------
937 // cy_rtos_queue_get
938 //--------------------------------------------------------------------------------------------------
cy_rtos_queue_get(cy_queue_t * queue,void * item_ptr,cy_time_t timeout_ms)939 cy_rslt_t cy_rtos_queue_get(cy_queue_t* queue, void* item_ptr, cy_time_t timeout_ms)
940 {
941     cy_rslt_t       status;
942     cy_rtos_error_t statusInternal;
943     bool in_isr = is_in_isr();
944 
945     if ((queue == NULL) || (item_ptr == NULL))
946     {
947         status = CY_RTOS_BAD_PARAM;
948     }
949     else
950     {
951         // Not allowed to be called in ISR if timeout != 0
952         if ((!in_isr) || (in_isr && (timeout_ms == 0U)))
953         {
954             statusInternal = osMessageQueueGet(*queue, (uint8_t*)item_ptr, NULL, timeout_ms);
955         }
956         else
957         {
958             statusInternal = osErrorISR;
959         }
960 
961         status = error_converter(statusInternal);
962     }
963 
964     return status;
965 }
966 
967 
968 //--------------------------------------------------------------------------------------------------
969 // cy_rtos_queue_count
970 //--------------------------------------------------------------------------------------------------
cy_rtos_queue_count(cy_queue_t * queue,size_t * num_waiting)971 cy_rslt_t cy_rtos_queue_count(cy_queue_t* queue, size_t* num_waiting)
972 {
973     cy_rslt_t status = CY_RSLT_SUCCESS;
974 
975     if ((queue == NULL) || (num_waiting == NULL))
976     {
977         status = CY_RTOS_BAD_PARAM;
978     }
979     else
980     {
981         *num_waiting = osMessageQueueGetCount(*queue);
982     }
983 
984     return status;
985 }
986 
987 
988 //--------------------------------------------------------------------------------------------------
989 // cy_rtos_queue_space
990 //--------------------------------------------------------------------------------------------------
cy_rtos_queue_space(cy_queue_t * queue,size_t * num_spaces)991 cy_rslt_t cy_rtos_queue_space(cy_queue_t* queue, size_t* num_spaces)
992 {
993     cy_rslt_t status = CY_RSLT_SUCCESS;
994 
995     if ((queue == NULL) || (num_spaces == NULL))
996     {
997         status = CY_RTOS_BAD_PARAM;
998     }
999     else
1000     {
1001         *num_spaces = osMessageQueueGetSpace(*queue);
1002     }
1003 
1004     return status;
1005 }
1006 
1007 
1008 //--------------------------------------------------------------------------------------------------
1009 // cy_rtos_queue_reset
1010 //--------------------------------------------------------------------------------------------------
cy_rtos_queue_reset(cy_queue_t * queue)1011 cy_rslt_t cy_rtos_queue_reset(cy_queue_t* queue)
1012 {
1013     cy_rslt_t       status;
1014     cy_rtos_error_t statusInternal;
1015 
1016     if (queue == NULL)
1017     {
1018         status = CY_RTOS_BAD_PARAM;
1019     }
1020     else
1021     {
1022         statusInternal = osMessageQueueReset(*queue);
1023         status         = error_converter(statusInternal);
1024     }
1025 
1026     return status;
1027 }
1028 
1029 
1030 //--------------------------------------------------------------------------------------------------
1031 // cy_rtos_queue_deinit
1032 //--------------------------------------------------------------------------------------------------
cy_rtos_queue_deinit(cy_queue_t * queue)1033 cy_rslt_t cy_rtos_queue_deinit(cy_queue_t* queue)
1034 {
1035     cy_rslt_t       status;
1036     cy_rtos_error_t statusInternal;
1037 
1038     if (queue == NULL)
1039     {
1040         status = CY_RTOS_BAD_PARAM;
1041     }
1042     else
1043     {
1044         statusInternal = osMessageQueueDelete(*queue);
1045         status         = error_converter(statusInternal);
1046 
1047         if (status == CY_RSLT_SUCCESS)
1048         {
1049             free(*queue);
1050             *queue = NULL;
1051         }
1052     }
1053 
1054     return status;
1055 }
1056 
1057 
1058 /******************************************************
1059 *                 Timers
1060 ******************************************************/
1061 
cy_rtos_timer_init(cy_timer_t * timer,cy_timer_trigger_type_t type,cy_timer_callback_t fun,cy_timer_callback_arg_t arg)1062 cy_rslt_t cy_rtos_timer_init(cy_timer_t* timer, cy_timer_trigger_type_t type,
1063                              cy_timer_callback_t fun, cy_timer_callback_arg_t arg)
1064 {
1065     cy_rslt_t     status;
1066     osTimerAttr_t attr;
1067 
1068     if (timer == NULL)
1069     {
1070         status = CY_RTOS_BAD_PARAM;
1071     }
1072     else
1073     {
1074         attr.name      = NULL;
1075         attr.attr_bits = 0U;
1076         attr.cb_mem    = malloc(osRtxTimerCbSize);
1077         attr.cb_size   = osRtxTimerCbSize;
1078 
1079         if (attr.cb_mem == NULL)
1080         {
1081             status = CY_RTOS_NO_MEMORY;
1082         }
1083         else
1084         {
1085             osTimerType_t osTriggerType = (CY_TIMER_TYPE_PERIODIC == type)
1086                 ? osTimerPeriodic
1087                 : osTimerOnce;
1088 
1089             CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL);
1090             *timer = osTimerNew((osTimerFunc_t)fun, osTriggerType, (void*)arg, &attr);
1091             CY_ASSERT((*timer == attr.cb_mem) || (*timer == NULL));
1092             status = (*timer == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS;
1093         }
1094     }
1095 
1096     return status;
1097 }
1098 
1099 
1100 //--------------------------------------------------------------------------------------------------
1101 // cy_rtos_timer_start
1102 //--------------------------------------------------------------------------------------------------
cy_rtos_timer_start(cy_timer_t * timer,cy_time_t num_ms)1103 cy_rslt_t cy_rtos_timer_start(cy_timer_t* timer, cy_time_t num_ms)
1104 {
1105     cy_rslt_t       status;
1106     cy_rtos_error_t statusInternal;
1107 
1108     if (timer == NULL)
1109     {
1110         status = CY_RTOS_BAD_PARAM;
1111     }
1112     else
1113     {
1114         statusInternal = osTimerStart(*timer, convert_ms_to_ticks(num_ms));
1115         status         = error_converter(statusInternal);
1116     }
1117 
1118     return status;
1119 }
1120 
1121 
1122 //--------------------------------------------------------------------------------------------------
1123 // cy_rtos_timer_stop
1124 //--------------------------------------------------------------------------------------------------
cy_rtos_timer_stop(cy_timer_t * timer)1125 cy_rslt_t cy_rtos_timer_stop(cy_timer_t* timer)
1126 {
1127     cy_rslt_t       status;
1128     cy_rtos_error_t statusInternal;
1129 
1130     if (timer == NULL)
1131     {
1132         status = CY_RTOS_BAD_PARAM;
1133     }
1134     else
1135     {
1136         statusInternal = osTimerStop(*timer);
1137         status         = error_converter(statusInternal);
1138     }
1139 
1140     return status;
1141 }
1142 
1143 
1144 //--------------------------------------------------------------------------------------------------
1145 // cy_rtos_timer_is_running
1146 //--------------------------------------------------------------------------------------------------
cy_rtos_timer_is_running(cy_timer_t * timer,bool * state)1147 cy_rslt_t cy_rtos_timer_is_running(cy_timer_t* timer, bool* state)
1148 {
1149     cy_rslt_t status = CY_RSLT_SUCCESS;
1150 
1151     if ((timer == NULL) || (state == NULL))
1152     {
1153         status = CY_RTOS_BAD_PARAM;
1154     }
1155     else
1156     {
1157         *state = osTimerIsRunning(*timer);
1158     }
1159 
1160     return status;
1161 }
1162 
1163 
1164 //--------------------------------------------------------------------------------------------------
1165 // cy_rtos_timer_deinit
1166 //--------------------------------------------------------------------------------------------------
cy_rtos_timer_deinit(cy_timer_t * timer)1167 cy_rslt_t cy_rtos_timer_deinit(cy_timer_t* timer)
1168 {
1169     cy_rslt_t       status;
1170     cy_rtos_error_t statusInternal;
1171 
1172     if (timer == NULL)
1173     {
1174         status = CY_RTOS_BAD_PARAM;
1175     }
1176     else
1177     {
1178         statusInternal = osTimerDelete(*timer);
1179         status         = error_converter(statusInternal);
1180 
1181         if (status == CY_RSLT_SUCCESS)
1182         {
1183             free(*timer);
1184             *timer = NULL;
1185         }
1186     }
1187 
1188     return status;
1189 }
1190 
1191 
1192 /******************************************************
1193 *                 Time
1194 ******************************************************/
1195 
cy_rtos_time_get(cy_time_t * tval)1196 cy_rslt_t cy_rtos_time_get(cy_time_t* tval)
1197 {
1198     cy_rslt_t status = CY_RSLT_SUCCESS;
1199     uint32_t  tick_freq;
1200 
1201     if (tval == NULL)
1202     {
1203         status = CY_RTOS_BAD_PARAM;
1204     }
1205     else
1206     {
1207         // Get Number of ticks per second
1208         tick_freq = osKernelGetTickFreq();
1209 
1210         // Convert ticks count to time in milliseconds
1211         if (tick_freq != 0)
1212         {
1213             *tval = (cy_time_t)((osKernelGetTickCount() * 1000LL) / tick_freq);
1214         }
1215         else
1216         {
1217             status = CY_RTOS_GENERAL_ERROR;
1218         }
1219     }
1220 
1221     return status;
1222 }
1223 
1224 
1225 //--------------------------------------------------------------------------------------------------
1226 // cy_rtos_delay_milliseconds
1227 //--------------------------------------------------------------------------------------------------
cy_rtos_delay_milliseconds(cy_time_t num_ms)1228 cy_rslt_t cy_rtos_delay_milliseconds(cy_time_t num_ms)
1229 {
1230     cy_rslt_t       status;
1231     cy_rtos_error_t statusInternal;
1232 
1233     statusInternal = osDelay(num_ms);
1234     status         = error_converter(statusInternal);
1235 
1236     return status;
1237 }
1238 
1239 
1240 #if defined(__cplusplus)
1241 }
1242 #endif
1243