1 /***********************************************************************************************//**
2 * \file cyabs_rtos_threadx.c
3 *
4 * \brief
5 * Implementation for ThreadX abstraction
6 *
7 ***************************************************************************************************
8 * \copyright
9 * Copyright 2018-2021 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 <cy_result.h>
28 #include <cy_utils.h>
29 #include <cyabs_rtos.h>
30 #include <tx_api.h>
31 #include <stdlib.h>
32
33 static const uint32_t WRAPPER_IDENT = 0xABCDEF01U;
34 static const uint32_t MAX_QUEUE_MESSAGE_SIZE = 16;
35 #define ALL_EVENT_FLAGS (0xFFFFFFFFU)
36 #define MILLISECONDS_PER_SECOND (1000)
37
38 static cy_rtos_error_t last_error;
39
40
41 //--------------------------------------------------------------------------------------------------
42 // convert_ms_to_ticks
43 //--------------------------------------------------------------------------------------------------
convert_ms_to_ticks(cy_time_t timeout_ms)44 static cy_time_t convert_ms_to_ticks(cy_time_t timeout_ms)
45 {
46 if (timeout_ms == CY_RTOS_NEVER_TIMEOUT)
47 {
48 return TX_WAIT_FOREVER;
49 }
50 else if (timeout_ms == 0)
51 {
52 return 0;
53 }
54 else
55 {
56 uint64_t ticks = (uint64_t)timeout_ms * (uint64_t)TX_TIMER_TICKS_PER_SECOND /
57 (uint64_t)MILLISECONDS_PER_SECOND;
58 if (ticks == 0)
59 {
60 ticks = 1;
61 }
62 else if (ticks >= UINT32_MAX)
63 {
64 // if ticks if more than 32 bits, change ticks to max possible value that isn't
65 // TX_WAIT_FOREVER.
66 ticks = UINT32_MAX - 1;
67 }
68 return (cy_time_t)ticks;
69 }
70 }
71
72
73 //--------------------------------------------------------------------------------------------------
74 // convert_ticks_to_ms
75 //--------------------------------------------------------------------------------------------------
convert_ticks_to_ms(cy_time_t timeout_ticks)76 static inline cy_time_t convert_ticks_to_ms(cy_time_t timeout_ticks)
77 {
78 return (cy_time_t)((uint64_t)timeout_ticks * (uint64_t)MILLISECONDS_PER_SECOND /
79 (uint64_t)TX_TIMER_TICKS_PER_SECOND);
80 }
81
82
83 //--------------------------------------------------------------------------------------------------
84 // convert_error
85 //--------------------------------------------------------------------------------------------------
convert_error(cy_rtos_error_t error)86 static inline cy_rslt_t convert_error(cy_rtos_error_t error)
87 {
88 if (error != TX_SUCCESS)
89 {
90 last_error = error;
91 return CY_RTOS_GENERAL_ERROR;
92 }
93 return CY_RSLT_SUCCESS;
94 }
95
96
97 /******************************************************
98 * Last Error
99 ******************************************************/
100
101 //--------------------------------------------------------------------------------------------------
102 // cy_rtos_last_error
103 //--------------------------------------------------------------------------------------------------
cy_rtos_last_error(void)104 cy_rtos_error_t cy_rtos_last_error(void)
105 {
106 return last_error;
107 }
108
109
110 /******************************************************
111 * Threads
112 ******************************************************/
113
114 typedef struct
115 {
116 TX_THREAD thread;
117 uint32_t magic;
118 void* memptr;
119 } cy_thread_wrapper_t;
120
121
122 //--------------------------------------------------------------------------------------------------
123 // cy_rtos_create_thread
124 //--------------------------------------------------------------------------------------------------
cy_rtos_create_thread(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)125 cy_rslt_t cy_rtos_create_thread(cy_thread_t* thread, cy_thread_entry_fn_t entry_function,
126 const char* name, void* stack, uint32_t stack_size,
127 cy_thread_priority_t priority, cy_thread_arg_t arg)
128 {
129 stack_size &= ~CY_RTOS_ALIGNMENT_MASK; // make stack pointer 8-byte aligned
130 if ((thread == NULL) || (stack_size < CY_RTOS_MIN_STACK_SIZE))
131 {
132 return CY_RTOS_BAD_PARAM;
133 }
134
135 if ((stack != NULL) && (0 != (((uint32_t)stack) & CY_RTOS_ALIGNMENT_MASK)))
136 {
137 return CY_RTOS_ALIGNMENT_ERROR;
138 }
139
140 size_t malloc_size = sizeof(cy_thread_wrapper_t);
141 if (stack == NULL)
142 {
143 malloc_size += stack_size;
144 }
145 void* buffer = malloc(malloc_size);
146 if (buffer == NULL)
147 {
148 return CY_RTOS_NO_MEMORY;
149 }
150
151 cy_thread_wrapper_t* wrapper_ptr;
152 if (stack == NULL)
153 {
154 stack = buffer;
155 // Have stack be in front of wrapper since stack size is 8-byte aligned.
156 wrapper_ptr = (cy_thread_wrapper_t*)(buffer + stack_size);
157 wrapper_ptr->memptr = stack;
158 }
159 else
160 {
161 wrapper_ptr = buffer;
162 wrapper_ptr->memptr = NULL;
163 }
164 wrapper_ptr->magic = WRAPPER_IDENT;
165
166 *thread = (cy_thread_t)wrapper_ptr;
167
168 // Disable preemption-thresholding and time slicing
169 cy_rtos_error_t tx_rslt = tx_thread_create(*thread, (CHAR*)name, entry_function, arg, stack,
170 stack_size, priority, priority, TX_NO_TIME_SLICE,
171 TX_AUTO_START);
172
173 if (TX_SUCCESS != tx_rslt)
174 {
175 last_error = tx_rslt;
176 free(buffer);
177 return CY_RTOS_GENERAL_ERROR;
178 }
179
180 return CY_RSLT_SUCCESS;
181 }
182
183
184 //--------------------------------------------------------------------------------------------------
185 // cy_rtos_exit_thread
186 //--------------------------------------------------------------------------------------------------
cy_rtos_exit_thread(void)187 cy_rslt_t cy_rtos_exit_thread(void)
188 {
189 // No need to do anything before thread exit
190 return CY_RSLT_SUCCESS;
191 }
192
193
194 //--------------------------------------------------------------------------------------------------
195 // cy_rtos_terminate_thread
196 //--------------------------------------------------------------------------------------------------
cy_rtos_terminate_thread(cy_thread_t * thread)197 cy_rslt_t cy_rtos_terminate_thread(cy_thread_t* thread)
198 {
199 if (thread == NULL)
200 {
201 return CY_RTOS_BAD_PARAM;
202 }
203
204 return convert_error(tx_thread_terminate(*thread));
205 }
206
207
208 //--------------------------------------------------------------------------------------------------
209 // cy_rtos_is_thread_running
210 //--------------------------------------------------------------------------------------------------
cy_rtos_is_thread_running(cy_thread_t * thread,bool * running)211 cy_rslt_t cy_rtos_is_thread_running(cy_thread_t* thread, bool* running)
212 {
213 if ((thread == NULL) || (running == NULL))
214 {
215 return CY_RTOS_BAD_PARAM;
216 }
217
218 // Only true when the given thread is the current one
219 *running = (*thread == tx_thread_identify());
220 return CY_RSLT_SUCCESS;
221 }
222
223
224 //--------------------------------------------------------------------------------------------------
225 // cy_rtos_get_thread_state
226 //--------------------------------------------------------------------------------------------------
cy_rtos_get_thread_state(cy_thread_t * thread,cy_thread_state_t * state)227 cy_rslt_t cy_rtos_get_thread_state(cy_thread_t* thread, cy_thread_state_t* state)
228 {
229 if ((thread == NULL) || (state == NULL))
230 {
231 return CY_RTOS_BAD_PARAM;
232 }
233
234 bool running;
235 cy_rslt_t rslt = cy_rtos_is_thread_running(thread, &running);
236 if (CY_RSLT_SUCCESS != rslt)
237 {
238 return rslt;
239 }
240 else if (running)
241 {
242 *state = CY_THREAD_STATE_RUNNING;
243 return CY_RSLT_SUCCESS;
244 }
245
246 UINT thread_state;
247 cy_rtos_error_t tx_rslt = tx_thread_info_get(*thread, TX_NULL, &thread_state, TX_NULL, TX_NULL,
248 TX_NULL, TX_NULL, TX_NULL, TX_NULL);
249 if (TX_SUCCESS != tx_rslt)
250 {
251 last_error = tx_rslt;
252 return CY_RTOS_GENERAL_ERROR;
253 }
254
255 // Descriptions of these states are not given in the ThreadX user guide - these are best guesses
256 // as to their meanings
257 switch (thread_state)
258 {
259 case TX_READY:
260 *state = CY_THREAD_STATE_READY;
261 break;
262
263 case TX_COMPLETED:
264 case TX_TERMINATED:
265 *state = CY_THREAD_STATE_TERMINATED;
266 break;
267
268 case TX_SUSPENDED:
269 case TX_SLEEP:
270 case TX_QUEUE_SUSP:
271 case TX_SEMAPHORE_SUSP:
272 case TX_MUTEX_SUSP:
273 case TX_EVENT_FLAG: // Likely waiting for event flags to be set (tx_event_flags_get)
274 case TX_BLOCK_MEMORY: // Likely waiting to allocate a memory block (tx_block_allocate)
275 case TX_BYTE_MEMORY: // Likely waiting to allocate a byte pool (tx_byte_allocate)
276 *state = CY_THREAD_STATE_BLOCKED;
277 break;
278
279 default:
280 *state = CY_THREAD_STATE_UNKNOWN;
281 break;
282 }
283
284 return CY_RSLT_SUCCESS;
285 }
286
287
288 //--------------------------------------------------------------------------------------------------
289 // cy_rtos_join_thread
290 //--------------------------------------------------------------------------------------------------
cy_rtos_join_thread(cy_thread_t * thread)291 cy_rslt_t cy_rtos_join_thread(cy_thread_t* thread)
292 {
293 if (thread == NULL)
294 {
295 return CY_RTOS_BAD_PARAM;
296 }
297
298 // ThreadX doesn't have a join method itself, so just repeatedly check the thread's state until
299 // it completes or is terminated.
300 // Check if the thread we are joining has a higher priority, if it does, we need to lower our
301 // priority to that of the other thread.
302 UINT thread_state;
303
304 cy_rtos_error_t tx_rslt = tx_thread_info_get(*thread, TX_NULL, &thread_state, TX_NULL, TX_NULL,
305 TX_NULL, TX_NULL, TX_NULL, TX_NULL);
306 if (TX_SUCCESS != tx_rslt)
307 {
308 last_error = tx_rslt;
309 return CY_RTOS_GENERAL_ERROR;
310 }
311
312 while (TX_TERMINATED != thread_state && TX_COMPLETED != thread_state)
313 {
314 tx_rslt = tx_thread_sleep(1);
315 if (TX_SUCCESS != tx_rslt)
316 {
317 last_error = tx_rslt;
318 return CY_RTOS_GENERAL_ERROR;
319 }
320
321 tx_rslt = tx_thread_info_get(*thread, TX_NULL, &thread_state, TX_NULL, TX_NULL, TX_NULL,
322 TX_NULL, TX_NULL, TX_NULL);
323 if (TX_SUCCESS != tx_rslt)
324 {
325 last_error = tx_rslt;
326 return CY_RTOS_GENERAL_ERROR;
327 }
328 }
329
330 tx_rslt = tx_thread_delete(*thread);
331 if (TX_SUCCESS != tx_rslt)
332 {
333 last_error = tx_rslt;
334 return CY_RTOS_GENERAL_ERROR;
335 }
336
337 cy_thread_wrapper_t* wrapper_ptr = (cy_thread_wrapper_t*)(*thread);
338 if (wrapper_ptr->magic == WRAPPER_IDENT)
339 {
340 if (wrapper_ptr->memptr != NULL)
341 {
342 free(wrapper_ptr->memptr);
343 }
344 else
345 {
346 free(wrapper_ptr);
347 }
348 }
349 return CY_RSLT_SUCCESS;
350 }
351
352
353 //--------------------------------------------------------------------------------------------------
354 // cy_rtos_get_thread_handle
355 //--------------------------------------------------------------------------------------------------
cy_rtos_get_thread_handle(cy_thread_t * thread)356 cy_rslt_t cy_rtos_get_thread_handle(cy_thread_t* thread)
357 {
358 if (thread == NULL)
359 {
360 return CY_RTOS_BAD_PARAM;
361 }
362
363 *thread = tx_thread_identify();
364 return CY_RSLT_SUCCESS;
365 }
366
367
368 //--------------------------------------------------------------------------------------------------
369 // cy_rtos_wait_thread_notification
370 //--------------------------------------------------------------------------------------------------
cy_rtos_wait_thread_notification(cy_time_t timeout_ms)371 cy_rslt_t cy_rtos_wait_thread_notification(cy_time_t timeout_ms)
372 {
373 UINT ret;
374 cy_rslt_t status = CY_RSLT_SUCCESS;
375
376 ret = tx_thread_sleep(convert_ms_to_ticks(timeout_ms));
377 /* Update the last known error status */
378 last_error = (cy_rtos_error_t)ret;
379
380 if (ret == TX_SUCCESS)
381 {
382 status = CY_RTOS_TIMEOUT;
383 }
384 else if (ret != TX_WAIT_ABORTED)
385 {
386 status = CY_RTOS_GENERAL_ERROR;
387 }
388 return status;
389 }
390
391
392 //--------------------------------------------------------------------------------------------------
393 // cy_rtos_set_thread_notification
394 //--------------------------------------------------------------------------------------------------
cy_rtos_set_thread_notification(cy_thread_t * thread,bool in_isr)395 cy_rslt_t cy_rtos_set_thread_notification(cy_thread_t* thread, bool in_isr)
396 {
397 (void)in_isr;
398
399 if (thread == NULL)
400 {
401 return CY_RTOS_BAD_PARAM;
402 }
403 /* According to ThreadX user guide, this function allowed to
404 * be called from ISR
405 */
406 return convert_error(tx_thread_wait_abort(*thread));
407 }
408
409
410 /******************************************************
411 * Mutexes
412 ******************************************************/
413
414 //--------------------------------------------------------------------------------------------------
415 // cy_rtos_init_mutex2
416 //--------------------------------------------------------------------------------------------------
cy_rtos_init_mutex2(cy_mutex_t * mutex,bool recursive)417 cy_rslt_t cy_rtos_init_mutex2(cy_mutex_t* mutex, bool recursive)
418 {
419 if (mutex == NULL)
420 {
421 return CY_RTOS_BAD_PARAM;
422 }
423
424 // Non recursive mutex is not supported by ThreadX. A recursive mutex is returned
425 // even if a non-recursive mutex was requested. This is ok because in all the cases
426 // where the behavior of the two types differs would have ended in a deadlock. So
427 // the difference in behavior should not have a functional impact on application.
428 CY_UNUSED_PARAMETER(recursive);
429 return convert_error(tx_mutex_create(mutex, TX_NULL, TX_INHERIT));
430 }
431
432
433 //--------------------------------------------------------------------------------------------------
434 // cy_rtos_get_mutex
435 //--------------------------------------------------------------------------------------------------
cy_rtos_get_mutex(cy_mutex_t * mutex,cy_time_t timeout_ms)436 cy_rslt_t cy_rtos_get_mutex(cy_mutex_t* mutex, cy_time_t timeout_ms)
437 {
438 if (mutex == NULL)
439 {
440 return CY_RTOS_BAD_PARAM;
441 }
442
443 cy_rtos_error_t tx_rslt = tx_mutex_get(mutex, convert_ms_to_ticks(timeout_ms));
444 if (TX_NOT_AVAILABLE == tx_rslt)
445 {
446 return CY_RTOS_TIMEOUT;
447 }
448 else
449 {
450 return convert_error(tx_rslt);
451 }
452 }
453
454
455 //--------------------------------------------------------------------------------------------------
456 // cy_rtos_set_mutex
457 //--------------------------------------------------------------------------------------------------
cy_rtos_set_mutex(cy_mutex_t * mutex)458 cy_rslt_t cy_rtos_set_mutex(cy_mutex_t* mutex)
459 {
460 if (mutex == NULL)
461 {
462 return CY_RTOS_BAD_PARAM;
463 }
464
465 return convert_error(tx_mutex_put(mutex));
466 }
467
468
469 //--------------------------------------------------------------------------------------------------
470 // cy_rtos_deinit_mutex
471 //--------------------------------------------------------------------------------------------------
cy_rtos_deinit_mutex(cy_mutex_t * mutex)472 cy_rslt_t cy_rtos_deinit_mutex(cy_mutex_t* mutex)
473 {
474 if (mutex == NULL)
475 {
476 return CY_RTOS_BAD_PARAM;
477 }
478
479 return convert_error(tx_mutex_delete(mutex));
480 }
481
482
483 /******************************************************
484 * Semaphores
485 ******************************************************/
486
487 //--------------------------------------------------------------------------------------------------
488 // cy_rtos_init_semaphore
489 //--------------------------------------------------------------------------------------------------
cy_rtos_init_semaphore(cy_semaphore_t * semaphore,uint32_t maxcount,uint32_t initcount)490 cy_rslt_t cy_rtos_init_semaphore(cy_semaphore_t* semaphore, uint32_t maxcount, uint32_t initcount)
491 {
492 if (semaphore == NULL)
493 {
494 return CY_RTOS_BAD_PARAM;
495 }
496 semaphore->maxcount = maxcount;
497 return convert_error(tx_semaphore_create(&(semaphore->tx_semaphore), TX_NULL, initcount));
498 }
499
500
501 //--------------------------------------------------------------------------------------------------
502 // cy_rtos_get_semaphore
503 //--------------------------------------------------------------------------------------------------
cy_rtos_get_semaphore(cy_semaphore_t * semaphore,cy_time_t timeout_ms,bool in_isr)504 cy_rslt_t cy_rtos_get_semaphore(cy_semaphore_t* semaphore, cy_time_t timeout_ms, bool in_isr)
505 {
506 // Based on documentation
507 // http://www.ece.ualberta.ca/~cmpe490/documents/ghs/405/threadxug_g40c.pdf
508 // pg 168 it specifies that the timeout must be zero when called from ISR.
509 if ((semaphore == NULL) || (in_isr && (timeout_ms != 0)))
510 {
511 return CY_RTOS_BAD_PARAM;
512 }
513 cy_rtos_error_t tx_rslt =
514 tx_semaphore_get(&(semaphore->tx_semaphore), convert_ms_to_ticks(timeout_ms));
515 if (TX_NO_INSTANCE == tx_rslt)
516 {
517 return CY_RTOS_TIMEOUT;
518 }
519 else
520 {
521 return convert_error(tx_rslt);
522 }
523 }
524
525
526 //--------------------------------------------------------------------------------------------------
527 // cy_rtos_set_semaphore
528 //--------------------------------------------------------------------------------------------------
cy_rtos_set_semaphore(cy_semaphore_t * semaphore,bool in_isr)529 cy_rslt_t cy_rtos_set_semaphore(cy_semaphore_t* semaphore, bool in_isr)
530 {
531 (void)in_isr; // Unused parameter in this implementation
532 if (semaphore == NULL)
533 {
534 return CY_RTOS_BAD_PARAM;
535 }
536 return convert_error(tx_semaphore_ceiling_put(&(semaphore->tx_semaphore), semaphore->maxcount));
537 }
538
539
540 //--------------------------------------------------------------------------------------------------
541 // cy_rtos_get_count_semaphore
542 //--------------------------------------------------------------------------------------------------
cy_rtos_get_count_semaphore(cy_semaphore_t * semaphore,size_t * count)543 cy_rslt_t cy_rtos_get_count_semaphore(cy_semaphore_t* semaphore, size_t* count)
544 {
545 if ((semaphore == NULL) || (count == NULL))
546 {
547 return CY_RTOS_BAD_PARAM;
548 }
549 return convert_error(tx_semaphore_info_get(&(semaphore->tx_semaphore), TX_NULL, (ULONG*)count,
550 TX_NULL, TX_NULL, TX_NULL));
551 }
552
553
554 //--------------------------------------------------------------------------------------------------
555 // cy_rtos_deinit_semaphore
556 //--------------------------------------------------------------------------------------------------
cy_rtos_deinit_semaphore(cy_semaphore_t * semaphore)557 cy_rslt_t cy_rtos_deinit_semaphore(cy_semaphore_t* semaphore)
558 {
559 if (semaphore == NULL)
560 {
561 return CY_RTOS_BAD_PARAM;
562 }
563 return convert_error(tx_semaphore_delete(&(semaphore->tx_semaphore)));
564 }
565
566
567 /******************************************************
568 * Events
569 ******************************************************/
570
571 //--------------------------------------------------------------------------------------------------
572 // cy_rtos_init_event
573 //--------------------------------------------------------------------------------------------------
cy_rtos_init_event(cy_event_t * event)574 cy_rslt_t cy_rtos_init_event(cy_event_t* event)
575 {
576 if (event == NULL)
577 {
578 return CY_RTOS_BAD_PARAM;
579 }
580
581 return convert_error(tx_event_flags_create(event, TX_NULL));
582 }
583
584
585 //--------------------------------------------------------------------------------------------------
586 // cy_rtos_setbits_event
587 //--------------------------------------------------------------------------------------------------
cy_rtos_setbits_event(cy_event_t * event,uint32_t bits,bool in_isr)588 cy_rslt_t cy_rtos_setbits_event(cy_event_t* event, uint32_t bits, bool in_isr)
589 {
590 (void)in_isr; // Unused parameter in this implementation
591
592 if (event == NULL)
593 {
594 return CY_RTOS_BAD_PARAM;
595 }
596
597 return convert_error(tx_event_flags_set(event, bits, TX_OR));
598 }
599
600
601 //--------------------------------------------------------------------------------------------------
602 // cy_rtos_clearbits_event
603 //--------------------------------------------------------------------------------------------------
cy_rtos_clearbits_event(cy_event_t * event,uint32_t bits,bool in_isr)604 cy_rslt_t cy_rtos_clearbits_event(cy_event_t* event, uint32_t bits, bool in_isr)
605 {
606 (void)in_isr; // Unused parameter in this implementation
607
608 if (event == NULL)
609 {
610 return CY_RTOS_BAD_PARAM;
611 }
612
613 return convert_error(tx_event_flags_set(event, ~bits, TX_AND));
614 }
615
616
617 //--------------------------------------------------------------------------------------------------
618 // cy_rtos_getbits_event
619 //--------------------------------------------------------------------------------------------------
cy_rtos_getbits_event(cy_event_t * event,uint32_t * bits)620 cy_rslt_t cy_rtos_getbits_event(cy_event_t* event, uint32_t* bits)
621 {
622 if ((event == NULL) || (bits == NULL))
623 {
624 return CY_RTOS_BAD_PARAM;
625 }
626
627 cy_rtos_error_t tx_rslt = tx_event_flags_get(event, ALL_EVENT_FLAGS, TX_OR, bits, TX_NO_WAIT);
628 if (TX_NO_EVENTS == tx_rslt) // If timeout error occur with ALL_EVENT_FLAGS and TX_OR, then no
629 // flag is set
630 {
631 *bits = 0;
632 return CY_RSLT_SUCCESS;
633 }
634 else
635 {
636 return convert_error(tx_rslt);
637 }
638 }
639
640
641 //--------------------------------------------------------------------------------------------------
642 // cy_rtos_waitbits_event
643 //--------------------------------------------------------------------------------------------------
cy_rtos_waitbits_event(cy_event_t * event,uint32_t * bits,bool clear,bool all,cy_time_t timeout_ms)644 cy_rslt_t cy_rtos_waitbits_event(cy_event_t* event, uint32_t* bits, bool clear, bool all,
645 cy_time_t timeout_ms)
646 {
647 UINT get_option;
648
649 if ((event == NULL) || (bits == NULL))
650 {
651 return CY_RTOS_BAD_PARAM;
652 }
653
654 if (all)
655 {
656 get_option = clear ? TX_AND_CLEAR : TX_AND;
657 }
658 else
659 {
660 get_option = clear ? TX_OR_CLEAR : TX_OR;
661 }
662
663 cy_rtos_error_t tx_rslt =
664 tx_event_flags_get(event, *bits, get_option, bits, convert_ms_to_ticks(timeout_ms));
665 if (TX_NO_EVENTS == tx_rslt)
666 {
667 return CY_RTOS_TIMEOUT;
668 }
669 else
670 {
671 return convert_error(tx_rslt);
672 }
673 }
674
675
676 //--------------------------------------------------------------------------------------------------
677 // cy_rtos_deinit_event
678 //--------------------------------------------------------------------------------------------------
cy_rtos_deinit_event(cy_event_t * event)679 cy_rslt_t cy_rtos_deinit_event(cy_event_t* event)
680 {
681 if (event == NULL)
682 {
683 return CY_RTOS_BAD_PARAM;
684 }
685
686 return convert_error(tx_event_flags_delete(event));
687 }
688
689
690 /******************************************************
691 * Queues
692 ******************************************************/
693
694 //--------------------------------------------------------------------------------------------------
695 // cy_rtos_init_queue
696 //--------------------------------------------------------------------------------------------------
cy_rtos_init_queue(cy_queue_t * queue,size_t length,size_t itemsize)697 cy_rslt_t cy_rtos_init_queue(cy_queue_t* queue, size_t length, size_t itemsize)
698 {
699 // Valid message lengths are {1-ULONG, 2-ULONG, 4-ULONG, 8-ULONG, 16-ULONG}
700 static const uint32_t BYTES_PER_QUEUE_WORD = sizeof(ULONG);
701
702 if ((queue == NULL) || (itemsize == 0) ||
703 (itemsize > BYTES_PER_QUEUE_WORD * MAX_QUEUE_MESSAGE_SIZE))
704 {
705 return CY_RTOS_BAD_PARAM;
706 }
707
708 // round message words to next power of 2 times word size.
709 UINT message_words = 1;
710 while (message_words * BYTES_PER_QUEUE_WORD < itemsize)
711 {
712 message_words <<= 1;
713 }
714
715 queue->itemsize = itemsize;
716 ULONG queue_size = length * message_words * BYTES_PER_QUEUE_WORD;
717 queue->mem = malloc(queue_size);
718 if (queue->mem == NULL)
719 {
720 return CY_RTOS_NO_MEMORY;
721 }
722
723 cy_rtos_error_t tx_rslt = tx_queue_create(&(queue->tx_queue), TX_NULL, message_words,
724 queue->mem, queue_size);
725 if (TX_SUCCESS != tx_rslt)
726 {
727 last_error = tx_rslt;
728 free(queue->mem);
729 return CY_RTOS_GENERAL_ERROR;
730 }
731
732 return CY_RSLT_SUCCESS;
733 }
734
735
736 //--------------------------------------------------------------------------------------------------
737 // cy_rtos_put_queue
738 //--------------------------------------------------------------------------------------------------
cy_rtos_put_queue(cy_queue_t * queue,const void * item_ptr,cy_time_t timeout_ms,bool in_isr)739 cy_rslt_t cy_rtos_put_queue(cy_queue_t* queue, const void* item_ptr, cy_time_t timeout_ms,
740 bool in_isr)
741 {
742 if ((queue == NULL) || (item_ptr == NULL) || (in_isr && (timeout_ms != 0)))
743 {
744 return CY_RTOS_BAD_PARAM;
745 }
746
747 cy_rtos_error_t tx_rslt = tx_queue_send(&(queue->tx_queue), (void*)item_ptr, convert_ms_to_ticks(
748 timeout_ms));
749 if (TX_QUEUE_FULL == tx_rslt)
750 {
751 return CY_RTOS_NO_MEMORY;
752 }
753 else
754 {
755 return convert_error(tx_rslt);
756 }
757 }
758
759
760 //--------------------------------------------------------------------------------------------------
761 // cy_rtos_get_queue
762 //--------------------------------------------------------------------------------------------------
cy_rtos_get_queue(cy_queue_t * queue,void * item_ptr,cy_time_t timeout_ms,bool in_isr)763 cy_rslt_t cy_rtos_get_queue(cy_queue_t* queue, void* item_ptr, cy_time_t timeout_ms, bool in_isr)
764 {
765 ULONG buffer[MAX_QUEUE_MESSAGE_SIZE];
766 if ((queue == NULL) || (item_ptr == NULL) || (in_isr && (timeout_ms != 0)))
767 {
768 return CY_RTOS_BAD_PARAM;
769 }
770
771 cy_rtos_error_t tx_rslt =
772 tx_queue_receive(&(queue->tx_queue), buffer, convert_ms_to_ticks(timeout_ms));
773 if (TX_QUEUE_EMPTY == tx_rslt)
774 {
775 return CY_RTOS_TIMEOUT;
776 }
777 else if (tx_rslt == TX_SUCCESS)
778 {
779 memcpy(item_ptr, buffer, queue->itemsize);
780 return CY_RSLT_SUCCESS;
781 }
782 else
783 {
784 last_error = tx_rslt;
785 return CY_RTOS_GENERAL_ERROR;
786 }
787 }
788
789
790 //--------------------------------------------------------------------------------------------------
791 // cy_rtos_count_queue
792 //--------------------------------------------------------------------------------------------------
cy_rtos_count_queue(cy_queue_t * queue,size_t * num_waiting)793 cy_rslt_t cy_rtos_count_queue(cy_queue_t* queue, size_t* num_waiting)
794 {
795 if ((queue == NULL) || (num_waiting == NULL))
796 {
797 return CY_RTOS_BAD_PARAM;
798 }
799 return convert_error(tx_queue_info_get(&(queue->tx_queue), TX_NULL, (ULONG*)num_waiting,
800 TX_NULL, TX_NULL, TX_NULL, TX_NULL));
801 }
802
803
804 //--------------------------------------------------------------------------------------------------
805 // cy_rtos_space_queue
806 //--------------------------------------------------------------------------------------------------
cy_rtos_space_queue(cy_queue_t * queue,size_t * num_spaces)807 cy_rslt_t cy_rtos_space_queue(cy_queue_t* queue, size_t* num_spaces)
808 {
809 if ((queue == NULL) || (num_spaces == NULL))
810 {
811 return CY_RTOS_BAD_PARAM;
812 }
813 return convert_error(tx_queue_info_get(&(queue->tx_queue), TX_NULL, TX_NULL, (ULONG*)num_spaces,
814 TX_NULL, TX_NULL, TX_NULL));
815 }
816
817
818 //--------------------------------------------------------------------------------------------------
819 // cy_rtos_reset_queue
820 //--------------------------------------------------------------------------------------------------
cy_rtos_reset_queue(cy_queue_t * queue)821 cy_rslt_t cy_rtos_reset_queue(cy_queue_t* queue)
822 {
823 if (queue == NULL)
824 {
825 return CY_RTOS_BAD_PARAM;
826 }
827 return convert_error(tx_queue_flush(&(queue->tx_queue)));
828 }
829
830
831 //--------------------------------------------------------------------------------------------------
832 // cy_rtos_deinit_queue
833 //--------------------------------------------------------------------------------------------------
cy_rtos_deinit_queue(cy_queue_t * queue)834 cy_rslt_t cy_rtos_deinit_queue(cy_queue_t* queue)
835 {
836 if (queue == NULL)
837 {
838 return CY_RTOS_BAD_PARAM;
839 }
840 cy_rslt_t result = convert_error(tx_queue_delete(&(queue->tx_queue)));
841 if (result == CY_RSLT_SUCCESS)
842 {
843 free(queue->mem);
844 }
845 return result;
846 }
847
848
849 /******************************************************
850 * Timers
851 ******************************************************/
852
853 //--------------------------------------------------------------------------------------------------
854 // cy_rtos_init_timer
855 //--------------------------------------------------------------------------------------------------
cy_rtos_init_timer(cy_timer_t * timer,cy_timer_trigger_type_t type,cy_timer_callback_t fun,cy_timer_callback_arg_t arg)856 cy_rslt_t cy_rtos_init_timer(cy_timer_t* timer, cy_timer_trigger_type_t type,
857 cy_timer_callback_t fun, cy_timer_callback_arg_t arg)
858 {
859 if ((timer == NULL) || (fun == NULL))
860 {
861 return CY_RTOS_BAD_PARAM;
862 }
863 timer->oneshot = (type == CY_TIMER_TYPE_ONCE);
864 // Use 1s here as default timeouts since these are going to get changed anyway
865 return convert_error(tx_timer_create(&(timer->tx_timer), TX_NULL, fun, arg, 1, 1,
866 TX_NO_ACTIVATE));
867 }
868
869
870 //--------------------------------------------------------------------------------------------------
871 // cy_rtos_start_timer
872 //--------------------------------------------------------------------------------------------------
cy_rtos_start_timer(cy_timer_t * timer,cy_time_t num_ms)873 cy_rslt_t cy_rtos_start_timer(cy_timer_t* timer, cy_time_t num_ms)
874 {
875 if (timer == NULL)
876 {
877 return CY_RTOS_BAD_PARAM;
878 }
879 ULONG timer_ticks = convert_ms_to_ticks(num_ms);
880 cy_rslt_t rslt =
881 convert_error(tx_timer_change(&(timer->tx_timer), timer_ticks,
882 timer->oneshot ? 0 : timer_ticks));
883 if (CY_RSLT_SUCCESS != rslt)
884 {
885 return rslt;
886 }
887 return convert_error(tx_timer_activate(&(timer->tx_timer)));
888 }
889
890
891 //--------------------------------------------------------------------------------------------------
892 // cy_rtos_stop_timer
893 //--------------------------------------------------------------------------------------------------
cy_rtos_stop_timer(cy_timer_t * timer)894 cy_rslt_t cy_rtos_stop_timer(cy_timer_t* timer)
895 {
896 if (timer == NULL)
897 {
898 return CY_RTOS_BAD_PARAM;
899 }
900 return convert_error(tx_timer_deactivate(&(timer->tx_timer)));
901 }
902
903
904 //--------------------------------------------------------------------------------------------------
905 // cy_rtos_is_running_timer
906 //--------------------------------------------------------------------------------------------------
cy_rtos_is_running_timer(cy_timer_t * timer,bool * state)907 cy_rslt_t cy_rtos_is_running_timer(cy_timer_t* timer, bool* state)
908 {
909 if ((timer == NULL) || (state == NULL))
910 {
911 return CY_RTOS_BAD_PARAM;
912 }
913
914 UINT active;
915 cy_rslt_t rslt =
916 convert_error(tx_timer_info_get(&(timer->tx_timer), TX_NULL, &active, TX_NULL, TX_NULL,
917 TX_NULL));
918 if (CY_RSLT_SUCCESS == rslt)
919 {
920 *state = (active == TX_TRUE);
921 }
922 return rslt;
923 }
924
925
926 //--------------------------------------------------------------------------------------------------
927 // cy_rtos_deinit_timer
928 //--------------------------------------------------------------------------------------------------
cy_rtos_deinit_timer(cy_timer_t * timer)929 cy_rslt_t cy_rtos_deinit_timer(cy_timer_t* timer)
930 {
931 if (timer == NULL)
932 {
933 return CY_RTOS_BAD_PARAM;
934 }
935 return convert_error(tx_timer_delete(&(timer->tx_timer)));
936 }
937
938
939 /******************************************************
940 * Time
941 ******************************************************/
942
943 //--------------------------------------------------------------------------------------------------
944 // cy_rtos_get_time
945 //--------------------------------------------------------------------------------------------------
cy_rtos_get_time(cy_time_t * tval)946 cy_rslt_t cy_rtos_get_time(cy_time_t* tval)
947 {
948 if (tval == NULL)
949 {
950 return CY_RTOS_BAD_PARAM;
951 }
952
953 *tval = convert_ticks_to_ms(tx_time_get());
954
955 return CY_RSLT_SUCCESS;
956 }
957
958
959 //--------------------------------------------------------------------------------------------------
960 // cy_rtos_delay_milliseconds
961 //--------------------------------------------------------------------------------------------------
cy_rtos_delay_milliseconds(cy_time_t num_ms)962 cy_rslt_t cy_rtos_delay_milliseconds(cy_time_t num_ms)
963 {
964 cy_time_t ticks = convert_ms_to_ticks(num_ms);
965
966 return convert_error(tx_thread_sleep(ticks));
967 }
968