diff --git a/abstraction-rtos/.cyignore b/abstraction-rtos/.cyignore
new file mode 100644
index 00000000..d8f8d469
--- /dev/null
+++ b/abstraction-rtos/.cyignore
@@ -0,0 +1 @@
+docs
diff --git a/abstraction-rtos/LICENSE b/abstraction-rtos/LICENSE
new file mode 100644
index 00000000..59cd3f8a
--- /dev/null
+++ b/abstraction-rtos/LICENSE
@@ -0,0 +1,165 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
diff --git a/abstraction-rtos/README.md b/abstraction-rtos/README.md
new file mode 100644
index 00000000..54d1813b
--- /dev/null
+++ b/abstraction-rtos/README.md
@@ -0,0 +1,111 @@
+# RTOS Abstraction
+
+## Overview
+
+The RTOS abstraction layer provides simple RTOS services like threads, semaphores, mutexes, queues, and timers. It is not intended to be a full features RTOS interface, but the provide just enough support to allow for RTOS independent drivers and middleware. This allows middleware applications to be as portable as possible within ModusToolbox™. This library provides a unified API around the actual RTOS. This allows middleware libraries to be written once independent of the RTOS actually selected for the application. The abstraction layer provides access to all the standard RTOS resources listed in the feature section below.
+
+While the primary purpose of the library is for middleware, the abstraction layer can be used by the application code. However, since this API does not provide all RTOS features and the application generally knows what RTOS is being used, this is typically an unnecessary overhead.
+
+All the RTOS abstraction layer functions generally all work the same way. The basic process is:
+1. Include the cyabs_rtos.h header file so that you have access to the RTOS functions.
+2. Declare a variable of the right type (e.g. cy_mutex_t)
+3. Call the appropriate create or initialize function (e.g. cy_rtos_init_mutex()). Provide it with a reference to the variable that was created in step 2.
+4. Access the RTOS object using one of the access functions. e.g. cy_rtos_set_mutex().
+5. If you don't need it anymore, free up the pointer with the appropriate de-init function (e.g. cy_rtos_deinit_mutex()).
+
+NOTE: All these functions need a pointer, so it is generally best to declare these "shared" resources as static global variables within the file that they are used.
+
+## Getting Started
+
+To use the RTOS Abstraction, simply include a reference to `cyabs_rtos.h` and update the application's makefile to include the appropriate component. e.g. one of:
+* COMPONENTS+=RTX
+* COMPONENTS+=FREERTOS
+* COMPONENTS+=THREADX
+
+## Features
+
+* APIs for interacting with common RTOS Features including:
+ * Threads
+ * Mutexes
+ * Semaphores
+ * Timers
+ * Queues
+ * Events
+* Implementations are provided for
+ * FreeRTOS
+ * RTX (CMSIS RTOS)
+ * ThreadX
+
+## RTOS Configuration Requirements
+### FreeRTOS
+To enable all functionality when using with FreeRTOS, the following configuration options must be enabled in FreeRTOSConfig.h:
+* configSUPPORT_DYNAMIC_ALLOCATION
+* configSUPPORT_STATIC_ALLOCATION
+* configUSE_COUNTING_SEMAPHORES
+* configUSE_MUTEXES
+* configUSE_NEWLIB_REENTRANT
+* configUSE_RECURSIVE_MUTEXES
+* configUSE_TASK_NOTIFICATIONS
+* configUSE_TICKLESS_IDLE
+* configUSE_TIMERS
+* configUSE_TRACE_FACILITY
+
+* INCLUDE_vTaskDelay
+* INCLUDE_vTaskDelete
+* INCLUDE_vTaskPrioritySet
+* INCLUDE_uxTaskPriorityGet
+* INCLUDE_xTimerPendFunctionCall
+* INCLUDE_vTaskSuspend
+
+Enabling configSUPPORT_STATIC_ALLOCATION requires the application to provide implementations for `vApplicationGetIdleTaskMemory` and
+`vApplicationGetTimerTaskMemory`functions. Weak implementations for these functions are provided as a part of this library. These can
+be overridden by the application if custom implementations of these functions are desired.
+
+This library provides an API `vApplicationSleep` which can be used to enable tickless support in FreeRTOS. In order to enable tickless mode with this API, the following changes need to be made in `FreeRTOSConfig.h`:
+* Enables tickless mode with user specified `portSUPPRESS_TICKS_AND_SLEEP` implementation.
+\c \#define `configUSE_TICKLESS_IDLE 2`
+* Hook `portSUPPRESS_TICKS_AND_SLEEP` macro to `vApplicationSleep` implementation.
+\c \#define `portSUPPRESS_TICKS_AND_SLEEP( xIdleTime ) vApplicationSleep( xIdleTime )`
+
+For further details on Low power support in FreeRTOS please refer to documentation [here](https://www.freertos.org/low-power-tickless-rtos.html)
+
+### RTX / ThreadX
+No specific requirements exist
+
+## Porting Notes
+In order to port to a new environment, the file cyabs_rtos_impl.h must be provided with definitions of some basic types for the abstraction layer. The types expected to be defined are:
+
+- `cy_thread_t` : typedef from underlying RTOS thread type
+- `cy_thread_arg_t` : typedef from the RTOS type that is passed to the entry function of a thread.
+- `cy_mutex_t` : typedef from the underlying RTOS mutex type
+- `cy_semaphore_t`: typedef from the underlying RTOS semaphore type
+- `cy_event_t` : typedef from the underlying RTOS event type
+- `cy_queue_t` : typedef from the underlying RTOS queue type
+- `cy_timer_callback_arg_t` : typedef from the RTOS type that is passed to the timer callback function
+- `cy_timer_t` : typedef from the underlying RTOS timer type
+- `cy_time_t` : count of time in milliseconds
+- `cy_rtos_error_t` : typedef from the underlying RTOS error type
+
+The enum `cy_thread_priority_t` needs to have the following priority values defined and mapped to RTOS specific values:
+- `CY_RTOS_PRIORITY_MIN`
+- `CY_RTOS_PRIORITY_LOW`
+- `CY_RTOS_PRIORITY_BELOWNORMAL`
+- `CY_RTOS_PRIORITY_NORMAL`
+- `CY_RTOS_PRIORITY_ABOVENORMAL`
+- `CY_RTOS_PRIORITY_HIGH`
+- `CY_RTOS_PRIORITY_REALTIME`
+- `CY_RTOS_PRIORITY_MAX`
+
+Finally, the following macros need to be defined for memory allocations:
+- `CY_RTOS_MIN_STACK_SIZE`
+- `CY_RTOS_ALIGNMENT`
+- `CY_RTOS_ALIGNMENT_MASK`
+
+## More information
+* [API Reference Guide](https://infineon.github.io/abstraction-rtos/html/modules.html)
+* [Cypress Semiconductor, an Infineon Technologies Company](http://www.cypress.com)
+* [Infineon GitHub](https://github.com/infineon)
+* [ModusToolbox™](https://www.cypress.com/products/modustoolbox-software-environment)
+
+---
+© Cypress Semiconductor Corporation (an Infineon company) or an affiliate of Cypress Semiconductor Corporation, 2019-2021.
diff --git a/abstraction-rtos/RELEASE.md b/abstraction-rtos/RELEASE.md
new file mode 100644
index 00000000..c3e4b010
--- /dev/null
+++ b/abstraction-rtos/RELEASE.md
@@ -0,0 +1,73 @@
+# RTOS Abstraction Library
+The RTOS Abstraction APIs allow middleware to be written to be RTOS aware, but not need to care about what the actual RTOS is.
+
+### What's Included?
+The this release of the RTOS Abstraction API includes support for the following:
+* APIs for interacting with common RTOS Features including:
+ * Threads
+ * Mutexes
+ * Semaphores
+ * Timers
+ * Queues
+ * Events
+* Implementations are provided for
+ * FreeRTOS
+ * RTX (CMSIS RTOS)
+ * ThreadX
+
+### What Changed?
+#### v1.5.0
+* Added additional parameter validation for ThreadX
+#### v1.4.0
+* Added new thread functions: cy_rtos_wait_thread_notification and cy_rtos_set_thread_notification
+* Minor documentation updates for clarity
+#### v1.3.1
+* Fixed a couple bugs in the FreeRTOS port
+#### v1.3.0
+* Update to work with a wider range of MCUs
+* Fixed a race condition in the worker thread
+* Fixed possible issue with thread priorities
+* Minor documentation updates
+#### v1.2.2
+* Minor update for documentation & branding
+#### v1.2.1
+* Fixed possible race condition in cy_rtos_join_thread for FreeRTOS
+* Minor documentation updates
+#### v1.2.0
+* Added utility library for for creating background worker threads: cy_worker_thread.h
+* Added support for getting a semaphore's count: cy_rtos_get_count_semaphore()
+* Added support for non-recursive mutexes: cy_rtos_init_mutex2()
+* Added default implementations for FreeRTOS vApplicationGetIdleTaskMemory, vApplicationGetTimerTaskMemory, and vApplicationSleep
+* Added support for ThreadX
+NOTE: The vApplicationSleep implementation for FreeRTOS depends on the psoc6hal 1.2.0 or later.
+#### v1.1.0
+* Fixed an issue with the FreeRTOS implementation where it would always allocate memory for the thread stack, even if a pre-allocated buffer was provided.
+* Removed usage of assert() and replaced with CY_ASSERT()
+#### v1.0.1
+* Added a new function to get the ID of the currently running thread.
+* A few minor updates to avoid possible warnings depending on compiler.
+* Minor documentation updates
+#### v1.0.0
+* Initial release supporting FreeRTOS & RTX
+
+### Supported Software and Tools
+This version of the RTOS Abstraction API was validated for compatibility with the following Software and Tools:
+
+| Software and Tools | Version |
+| :--- | :----: |
+| ModusToolbox™ Software Environment | 2.4.0 |
+| GCC Compiler | 10.3.1 |
+| IAR Compiler | 8.4 |
+| ARM Compiler | 6.11 |
+
+Minimum required ModusToolbox™ Software Environment: v2.0
+
+### More information
+Use the following links for more information, as needed:
+* [API Reference Guide](https://infineon.github.io/abstraction-rtos/html/modules.html)
+* [Cypress Semiconductor, an Infineon Technologies Company](http://www.cypress.com)
+* [Infineon GitHub](https://github.com/infineon)
+* [ModusToolbox™](https://www.cypress.com/products/modustoolbox-software-environment)
+
+---
+© Cypress Semiconductor Corporation (an Infineon company) or an affiliate of Cypress Semiconductor Corporation, 2019-2021.
\ No newline at end of file
diff --git a/abstraction-rtos/include/COMPONENT_FREERTOS/cyabs_rtos_impl.h b/abstraction-rtos/include/COMPONENT_FREERTOS/cyabs_rtos_impl.h
new file mode 100644
index 00000000..7d47ab32
--- /dev/null
+++ b/abstraction-rtos/include/COMPONENT_FREERTOS/cyabs_rtos_impl.h
@@ -0,0 +1,105 @@
+/***********************************************************************************************//**
+ * \file cyabs_rtos_impl.h
+ *
+ * \brief
+ * Internal definitions for RTOS abstraction layer
+ *
+ ***************************************************************************************************
+ * \copyright
+ * Copyright 2019-2021 Cypress Semiconductor Corporation (an Infineon company) or
+ * an affiliate of Cypress Semiconductor Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **************************************************************************************************/
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include "stdbool.h"
+#if defined(CY_USING_HAL)
+#include "cyhal.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************
+* Constants
+******************************************************/
+#define CY_RTOS_MIN_STACK_SIZE 300 /**< Minimum stack size in bytes */
+#define CY_RTOS_ALIGNMENT 0x00000008UL /**< Minimum alignment for RTOS objects */
+#define CY_RTOS_ALIGNMENT_MASK 0x00000007UL /**< Mask for checking the alignment of
+ created RTOS objects */
+
+/******************************************************
+* Enumerations
+******************************************************/
+
+typedef enum cy_thread_priority
+{
+ CY_RTOS_PRIORITY_MIN = 0,
+ CY_RTOS_PRIORITY_LOW = (configMAX_PRIORITIES * 1 / 7),
+ CY_RTOS_PRIORITY_BELOWNORMAL = (configMAX_PRIORITIES * 2 / 7),
+ CY_RTOS_PRIORITY_NORMAL = (configMAX_PRIORITIES * 3 / 7),
+ CY_RTOS_PRIORITY_ABOVENORMAL = (configMAX_PRIORITIES * 4 / 7),
+ CY_RTOS_PRIORITY_HIGH = (configMAX_PRIORITIES * 5 / 7),
+ CY_RTOS_PRIORITY_REALTIME = (configMAX_PRIORITIES * 6 / 7),
+ CY_RTOS_PRIORITY_MAX = configMAX_PRIORITIES - 1
+} cy_thread_priority_t;
+
+/******************************************************
+* Type Definitions
+******************************************************/
+
+typedef struct
+{
+ SemaphoreHandle_t mutex_handle;
+ bool is_recursive;
+} cy_mutex_t;
+
+typedef QueueHandle_t cy_queue_t;
+typedef SemaphoreHandle_t cy_semaphore_t;
+typedef TaskHandle_t cy_thread_t;
+typedef EventGroupHandle_t cy_event_t;
+typedef TimerHandle_t cy_timer_t;
+typedef uint32_t cy_timer_callback_arg_t;
+typedef void* cy_thread_arg_t;
+typedef uint32_t cy_time_t;
+typedef BaseType_t cy_rtos_error_t;
+
+#if defined(CY_USING_HAL)
+/** Stores a reference to an lptimer instance for use with vApplicationSleep().
+ *
+ * @param[in] timer Pointer to the lptimer handle
+ */
+void cyabs_rtos_set_lptimer(cyhal_lptimer_t* timer);
+
+/** Gets a reference to the lptimer instance object used by vApplicationSleep(). This instance is
+ * what was explicitly set by @ref cyabs_rtos_set_lptimer or, if none was set, what was
+ * automatically allocated by the first call to vApplicationSleep().
+ *
+ * @return Pointer to the lptimer handle
+ */
+cyhal_lptimer_t* cyabs_rtos_get_lptimer(void);
+#endif //defined(CY_USING_HAL)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/abstraction-rtos/include/COMPONENT_RTX/cyabs_rtos_impl.h b/abstraction-rtos/include/COMPONENT_RTX/cyabs_rtos_impl.h
new file mode 100644
index 00000000..4511eedf
--- /dev/null
+++ b/abstraction-rtos/include/COMPONENT_RTX/cyabs_rtos_impl.h
@@ -0,0 +1,78 @@
+/***********************************************************************************************//**
+ * \file cyabs_rtos_impl.h
+ *
+ * \brief
+ * Internal definitions for RTOS abstraction layer
+ *
+ ***************************************************************************************************
+ * \copyright
+ * Copyright 2019-2021 Cypress Semiconductor Corporation (an Infineon company) or
+ * an affiliate of Cypress Semiconductor Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **************************************************************************************************/
+
+#pragma once
+
+#include "cmsis_os2.h"
+#include "rtx_os.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/******************************************************
+* Constants
+******************************************************/
+#define CY_RTOS_MIN_STACK_SIZE 300 /** Minimum stack size in bytes */
+#define CY_RTOS_ALIGNMENT 0x00000008UL /** Minimum alignment for RTOS objects */
+#define CY_RTOS_ALIGNMENT_MASK 0x00000007UL /** Mask for checking the alignment of
+ created RTOS objects */
+
+
+/******************************************************
+* Type Definitions
+******************************************************/
+
+// RTOS thread priority
+typedef enum
+{
+ CY_RTOS_PRIORITY_MIN = osPriorityNone,
+ CY_RTOS_PRIORITY_LOW = osPriorityLow,
+ CY_RTOS_PRIORITY_BELOWNORMAL = osPriorityBelowNormal,
+ CY_RTOS_PRIORITY_NORMAL = osPriorityNormal,
+ CY_RTOS_PRIORITY_ABOVENORMAL = osPriorityAboveNormal,
+ CY_RTOS_PRIORITY_HIGH = osPriorityHigh,
+ CY_RTOS_PRIORITY_REALTIME = osPriorityRealtime,
+ CY_RTOS_PRIORITY_MAX = osPriorityRealtime7
+} cy_thread_priority_t;
+
+typedef osThreadId_t cy_thread_t; /** CMSIS definition of a thread handle */
+typedef void* cy_thread_arg_t; /** Argument passed to the entry function of
+ a thread */
+typedef osMutexId_t cy_mutex_t; /** CMSIS definition of a mutex */
+typedef osSemaphoreId_t cy_semaphore_t; /** CMSIS definition of a semaphore */
+typedef osEventFlagsId_t cy_event_t; /** CMSIS definition of an event */
+typedef osMessageQueueId_t cy_queue_t; /** CMSIS definition of a message queue */
+typedef osTimerId_t cy_timer_t; /** CMSIS definition of a timer */
+typedef void* cy_timer_callback_arg_t; /** Argument passed to the timer callback
+ function */
+typedef uint32_t cy_time_t; /** Time in milliseconds */
+typedef osStatus_t cy_rtos_error_t; /** CMSIS definition of a error status */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/abstraction-rtos/include/COMPONENT_THREADX/cyabs_rtos_impl.h b/abstraction-rtos/include/COMPONENT_THREADX/cyabs_rtos_impl.h
new file mode 100644
index 00000000..a8381adb
--- /dev/null
+++ b/abstraction-rtos/include/COMPONENT_THREADX/cyabs_rtos_impl.h
@@ -0,0 +1,96 @@
+/***********************************************************************************************//**
+ * \file cyabs_rtos_impl.h
+ *
+ * \brief
+ * Internal definitions for RTOS abstraction layer.
+ *
+ ***************************************************************************************************
+ * \copyright
+ * Copyright 2019-2021 Cypress Semiconductor Corporation (an Infineon company) or
+ * an affiliate of Cypress Semiconductor Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **************************************************************************************************/
+
+#pragma once
+
+#include
+#include
+
+#include "tx_api.h"
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/******************************************************
+* Constants
+******************************************************/
+#define CY_RTOS_MIN_STACK_SIZE TX_MINIMUM_STACK /** Minimum stack size in bytes */
+#define CY_RTOS_ALIGNMENT 0x00000008UL /** Minimum alignment for RTOS objects */
+#define CY_RTOS_ALIGNMENT_MASK 0x00000007UL /** Checks for 8-byte alignment */
+
+
+/******************************************************
+* Type Definitions
+******************************************************/
+
+// RTOS thread priority
+typedef enum
+{
+ CY_RTOS_PRIORITY_MIN = TX_MAX_PRIORITIES - 1,
+ CY_RTOS_PRIORITY_LOW = (TX_MAX_PRIORITIES * 6 / 7),
+ CY_RTOS_PRIORITY_BELOWNORMAL = (TX_MAX_PRIORITIES * 5 / 7),
+ CY_RTOS_PRIORITY_NORMAL = (TX_MAX_PRIORITIES * 4 / 7),
+ CY_RTOS_PRIORITY_ABOVENORMAL = (TX_MAX_PRIORITIES * 3 / 7),
+ CY_RTOS_PRIORITY_HIGH = (TX_MAX_PRIORITIES * 2 / 7),
+ CY_RTOS_PRIORITY_REALTIME = (TX_MAX_PRIORITIES * 1 / 7),
+ CY_RTOS_PRIORITY_MAX = 0
+} cy_thread_priority_t;
+
+typedef struct
+{
+ uint32_t maxcount;
+ TX_SEMAPHORE tx_semaphore;
+} cy_semaphore_t;
+
+typedef struct
+{
+ ULONG* mem;
+ // ThreadX buffer size is a power of 2 times word size,
+ // this is used to prevent memory corruption when get message from queue.
+ size_t itemsize;
+ TX_QUEUE tx_queue;
+} cy_queue_t;
+
+typedef struct
+{
+ bool oneshot;
+ TX_TIMER tx_timer;
+} cy_timer_t;
+
+typedef TX_THREAD* cy_thread_t;
+typedef ULONG cy_thread_arg_t;
+typedef TX_MUTEX cy_mutex_t;
+typedef TX_EVENT_FLAGS_GROUP cy_event_t;
+typedef ULONG cy_timer_callback_arg_t;
+typedef uint32_t cy_time_t;
+typedef UINT cy_rtos_error_t;
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/abstraction-rtos/include/Template/cyabs_rtos_impl.h b/abstraction-rtos/include/Template/cyabs_rtos_impl.h
new file mode 100644
index 00000000..2e5c4752
--- /dev/null
+++ b/abstraction-rtos/include/Template/cyabs_rtos_impl.h
@@ -0,0 +1,112 @@
+/***********************************************************************************************//**
+ * \file cyabs_rtos_impl.h
+ *
+ * \brief
+ * Template file for internal definitions for RTOS abstraction layer.
+ * Replace all TODO items with the proper values for the RTOS that is
+ * being wrapped.
+ *
+ ***************************************************************************************************
+ * \copyright
+ * Copyright 2019-2021 Cypress Semiconductor Corporation (an Infineon company) or
+ * an affiliate of Cypress Semiconductor Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **************************************************************************************************/
+
+#pragma once
+
+/*
+ * Exclude template files except for documentation purposes.
+ * This should be removed when using the template to support a new RTOS.
+ */
+#if defined(DOXYGEN)
+
+// #include "TODO: RTOS HEADER"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * \addtogroup group_abstraction_rtos_port RTOS Specific Types and Defines
+ * \ingroup group_abstraction_rtos_common
+ * \{
+ * The following defines and types have values that are specific to each RTOS port.
+ * The define values are specific to each RTOS. The types are simple aliases that
+ * wrap RTOS specifc types. Code cannot assume anything about the values or internals
+ * of any types.
+ */
+
+/******************************************************
+* Constants
+******************************************************/
+// TODO: Replace these with proper values for the target RTOS
+#define CY_RTOS_MIN_STACK_SIZE 300 /**< Minimum stack size */
+#define CY_RTOS_ALIGNMENT_MASK 0x00000007UL /**< Checks for 8-bit alignment */
+
+
+/******************************************************
+* Type Definitions
+******************************************************/
+
+// TODO: Replace all priority values with values specific to the RTOS
+/** RTOS thread priority.
+ * Note: Depending on the RTOS and interrupt options for the device, some of these priorities may
+ * end up being the same priority level in practice. Even if this happens, the relative ordering
+ * of priorities is still maintained. eg:
+ * MAX >= REALTIME >= HIGH >= ABOVENORMAL >= NORMAL >= BELOWNORMAL >= LOW >= MIN
+ */
+typedef enum
+{
+ CY_RTOS_PRIORITY_MIN = 0, /**< Minumum allowable Thread priority */
+ CY_RTOS_PRIORITY_LOW = 1, /**< A low priority Thread */
+ CY_RTOS_PRIORITY_BELOWNORMAL = 2, /**< A slightly below normal Thread priority */
+ CY_RTOS_PRIORITY_NORMAL = 3, /**< The normal Thread priority */
+ CY_RTOS_PRIORITY_ABOVENORMAL = 4, /**< A slightly elevated Thread priority */
+ CY_RTOS_PRIORITY_HIGH = 5, /**< A high priority Thread */
+ CY_RTOS_PRIORITY_REALTIME = 6, /**< Realtime Thread priority */
+ CY_RTOS_PRIORITY_MAX = 7 /**< Maximum allowable Thread priority */
+} cy_thread_priority_t;
+
+/** Alias for the RTOS specific definition of a thread handle */
+typedef void* /* TODO: Replace with RTOS specific type*/ cy_thread_t;
+/** Alias for the RTOS specific argument passed to the entry function of a thread */
+typedef void* /* TODO: Replace with RTOS specific type*/ cy_thread_arg_t;
+/** Alias for the RTOS specific definition of a mutex */
+typedef void* /* TODO: Replace with RTOS specific type*/ cy_mutex_t;
+/** Alias for the RTOS specific definition of a semaphore */
+typedef void* /* TODO: Replace with RTOS specific type*/ cy_semaphore_t;
+/** Alias for the RTOS specific definition of an event */
+typedef void* /* TODO: Replace with RTOS specific type*/ cy_event_t;
+/** Alias for the RTOS specific definition of a message queue */
+typedef void* /* TODO: Replace with RTOS specific type*/ cy_queue_t;
+/** Alias for the RTOS specific definition of a timer */
+typedef void* /* TODO: Replace with RTOS specific type*/ cy_timer_t;
+/** Alias for the RTOS specific argument passed to the timer callback function */
+typedef void* /* TODO: Replace with RTOS specific type*/ cy_timer_callback_arg_t;
+/** Alias for the RTOS specific time unit (in milliseconds) */
+typedef void* /* TODO: Replace with RTOS specific type*/ cy_time_t;
+/** Alias for the RTOS specific definition of a error status */
+typedef void* /* TODO: Replace with RTOS specific type*/ cy_rtos_error_t;
+
+/** \} group_abstraction_rtos_port */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // defined(DOXYGEN)
diff --git a/abstraction-rtos/include/cy_worker_thread.h b/abstraction-rtos/include/cy_worker_thread.h
new file mode 100644
index 00000000..7a911d87
--- /dev/null
+++ b/abstraction-rtos/include/cy_worker_thread.h
@@ -0,0 +1,145 @@
+/***********************************************************************************************//**
+ * \file cy_worker_thread.h
+ *
+ * \brief
+ * Defines the interface for the worker thread utility. Provides prototypes for
+ * functions that allow creating/deleting worker threads and queueing work to
+ * a worker thread.
+ ***************************************************************************************************
+ * \copyright
+ * Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or
+ * an affiliate of Cypress Semiconductor Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **************************************************************************************************/
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+
+#include "cy_result.h"
+#include "cyabs_rtos.h"
+
+/**
+ * \addtogroup group_worker_thread_util Worker Thread Utility
+ * \{
+ * Worker thread utility that allows functions to be run a different thread context.
+ * This utility can be used to delegate work that is not timing critical. For example,
+ * scheduling work in interrupt handlers to keep handler execution times low or if some
+ * work needs to be done at a different priority.
+ */
+
+/**< Default worker thread name */
+#define CY_WORKER_THREAD_DEFAULT_NAME "CYWorker"
+/** Default number of work items in the queue */
+#define CY_WORKER_DEFAULT_ENTRIES (16)
+
+/** Additional work cannot be enqueued because the worker thread has been terminated.
+ * This can occur if \ref cy_worker_thread_create was not called or \ref cy_worker_thread_delete was
+ * called before calling \ref cy_worker_thread_enqueue
+ */
+#define CY_WORKER_THREAD_ERR_THREAD_INVALID \
+ CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_OS, 32)
+
+/** Worker thread function call prototype */
+typedef void (cy_worker_thread_func_t)(void* arg);
+
+/** Thread state enumeration */
+typedef enum
+{
+ CY_WORKER_THREAD_INVALID, /**< Worker Thread is in invalid state */
+ CY_WORKER_THREAD_VALID, /**< Worker Thread is in valid state */
+ CY_WORKER_THREAD_ENQUEUING, /**< Worker Thread is adding to the queue */
+ CY_WORKER_THREAD_TERMINATING, /**< Worker Thread is starting to terminate */
+ CY_WORKER_THREAD_JOIN_COMPLETE /**< Worker Thread join is complete */
+} cy_worker_thread_state_t;
+
+/** Worker Thread Parameters. */
+typedef struct
+{
+ cy_thread_priority_t priority; /**< Requested thread priority. */
+ uint32_t stack_size; /**< Size of stack for new thread.
+ Note that this must be atleast CY_RTOS_MIN_STACK_SIZE */
+ uint8_t* stack; /**< Pointer to stack. If this is NULL a stack of
+ size \ref stack_size will be allocated. */
+ const char* name; /**< Thread name. If set to NULL,
+ \ref CY_WORKER_THREAD_DEFAULT_NAME will be used. */
+ uint32_t num_entries; /**< Maximum number of enteries the worker thread can queue.
+ If set to 0, \ref CY_WORKER_DEFAULT_ENTRIES
+ will be used. */
+} cy_worker_thread_params_t;
+
+/** Worker Thread Information. */
+typedef struct
+{
+ cy_queue_t event_queue; /**< Event Queue for this thread */
+ uint32_t enqueue_count; /**< Number of conccurent enqueue requests */
+ cy_thread_t thread; /**< Thread object */
+ cy_worker_thread_state_t state; /**< State of the worker thread */
+} cy_worker_thread_info_t;
+
+/** Create worker thread to handle running callbacks in a separate thread.
+ *
+ * @note Calling this function twice on the same thread object ( \ref cy_worker_thread_info_t)
+ * without
+ * calling \ref cy_worker_thread_delete will cause memory leakage.
+ *
+ * @param[out] new_worker pointer to cy_worker_thread_info_t structure to be filled when created.
+ * @param[in] params pointer to requested parameters for starting worker thread.
+ *
+ * @return The status of the worker thread creation request.
+ */
+cy_rslt_t cy_worker_thread_create(cy_worker_thread_info_t* new_worker,
+ const cy_worker_thread_params_t* params);
+
+/** Delete worker thread.
+ *
+ * @note This function will wait for the thread to complete all pending work in the
+ * queue and exit before returning.
+ *
+ * @param[in] old_worker pointer to cy_worker_thread_info_t structure to be deleted.
+ *
+ * @return The status of the deletion of the worker thread.
+ */
+cy_rslt_t cy_worker_thread_delete(cy_worker_thread_info_t* old_worker);
+
+/** Queue work on a worker thread.
+ *
+ * Call the given function in the worker thread context.
+ *
+ * @note If the thread priority is below that of the current thread, you must yield to allow
+ * the worker thread to run. This can be done by calling \ref cy_rtos_delay_milliseconds or
+ * by waiting on an RTOS object in all higher priority threads.
+ *
+ * @param[in] worker_info pointer to worker_thread used to run function
+ * @param[in] work_func function to run
+ * @param[in] arg opaque arg to be used in function call
+ *
+ * @return The status of the queueing of work.
+ */
+cy_rslt_t cy_worker_thread_enqueue(cy_worker_thread_info_t* worker_info,
+ cy_worker_thread_func_t* work_func, void* arg);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+/** \} group_abstraction_resource */
diff --git a/abstraction-rtos/include/cyabs_rtos.h b/abstraction-rtos/include/cyabs_rtos.h
new file mode 100644
index 00000000..72a3eab4
--- /dev/null
+++ b/abstraction-rtos/include/cyabs_rtos.h
@@ -0,0 +1,779 @@
+/***********************************************************************************************//**
+ * \file cyabs_rtos.h
+ *
+ * \brief
+ * Defines the Cypress RTOS Interface. Provides prototypes for functions that
+ * allow Cypress libraries to use RTOS resources such as threads, mutexes &
+ * timing functions in an abstract way. The APIs are implemented in the Port
+ * Layer RTOS interface which is specific to the RTOS in use.
+ *
+ ***************************************************************************************************
+ * \copyright
+ * Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or
+ * an affiliate of Cypress Semiconductor Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **************************************************************************************************/
+
+#pragma once
+
+#include "cyabs_rtos_impl.h"
+#include "cy_result.h"
+#include
+#include
+#include
+
+/**
+ * \defgroup group_abstraction_rtos_common Common
+ * General types and defines for working with the RTOS abstraction layer.
+ * \defgroup group_abstraction_rtos_event Events
+ * APIs for acquiring and working with Events.
+ * \defgroup group_abstraction_rtos_mutex Mutex
+ * APIs for acquiring and working with Mutexes.
+ * \defgroup group_abstraction_rtos_queue Queue
+ * APIs for creating and working with Queues.
+ * \defgroup group_abstraction_rtos_semaphore Semaphore
+ * APIs for acquiring and working with Semaphores.
+ * \defgroup group_abstraction_rtos_threads Threads
+ * APIs for creating and working with Threads.
+ * \defgroup group_abstraction_rtos_time Time
+ * APIs for getting the current time and waiting.
+ * \defgroup group_abstraction_rtos_timer Timer
+ * APIs for creating and working with Timers.
+ */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/******************************************** CONSTANTS *******************************************/
+
+/**
+ * \ingroup group_abstraction_rtos_common
+ * \{
+ */
+
+#if defined(DOXYGEN)
+/** Return value indicating success */
+#define CY_RSLT_SUCCESS ((cy_rslt_t)0x00000000U)
+#endif
+
+/** Used with RTOS calls that require a timeout. This implies the call will never timeout. */
+#define CY_RTOS_NEVER_TIMEOUT ( (uint32_t)0xffffffffUL )
+
+//
+// Note on error strategy. If the error is a normal part of operation (timeouts, full queues, empty
+// queues), the these errors are listed here and the abstraction layer implementation must map from
+// the underlying errors to these. If the errors are special cases, the the error \ref
+// CY_RTOS_GENERAL_ERROR will be returned and \ref cy_rtos_last_error() can be used to retrieve the
+// RTOS specific error message.
+//
+/** Requested operation did not complete in the specified time */
+#define CY_RTOS_TIMEOUT \
+ CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_OS, 0)
+/** The RTOS could not allocate memory for the specified operation */
+#define CY_RTOS_NO_MEMORY \
+ CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_OS, 1)
+/** An error occured in the RTOS */
+#define CY_RTOS_GENERAL_ERROR \
+ CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_OS, 2)
+/** A bad argument was passed into the APIs */
+#define CY_RTOS_BAD_PARAM \
+ CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_OS, 5)
+/** A memory alignment issue was detected. Ensure memory provided is aligned per \ref
+ CY_RTOS_ALIGNMENT_MASK */
+#define CY_RTOS_ALIGNMENT_ERROR \
+ CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_OS, 6)
+
+/** \} group_abstraction_rtos_common */
+
+/**
+ * \ingroup group_abstraction_rtos_queue
+ * \{
+ */
+
+/** The Queue is already full and can't accept any more items at this time */
+#define CY_RTOS_QUEUE_FULL \
+ CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_OS, 3)
+/** The Queue is empty and has nothing to remove */
+#define CY_RTOS_QUEUE_EMPTY \
+ CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_OS, 4)
+
+/** \} group_abstraction_rtos_queue */
+
+/********************************************* TYPES **********************************************/
+
+/**
+ * The state a thread can be in
+ *
+ * \ingroup group_abstraction_rtos_threads
+ */
+typedef enum cy_thread_state
+{
+ CY_THREAD_STATE_INACTIVE, /**< thread has not started or was terminated but not yet joined */
+ CY_THREAD_STATE_READY, /**< thread can run, but is not currently */
+ CY_THREAD_STATE_RUNNING, /**< thread is currently running */
+ CY_THREAD_STATE_BLOCKED, /**< thread is blocked waiting for something */
+ CY_THREAD_STATE_TERMINATED, /**< thread has terminated but not freed */
+ CY_THREAD_STATE_UNKNOWN /**< thread is in an unknown state */
+} cy_thread_state_t;
+
+/**
+ * The type of timer
+ *
+ * \ingroup group_abstraction_rtos_timer
+ */
+typedef enum cy_timer_trigger_type
+{
+ CY_TIMER_TYPE_PERIODIC, /**< called periodically until stopped */
+ CY_TIMER_TYPE_ONCE, /**< called once only */
+ cy_timer_type_periodic = CY_TIMER_TYPE_PERIODIC, /**< \deprecated replaced by \ref
+ CY_TIMER_TYPE_PERIODIC */
+ cy_timer_type_once = CY_TIMER_TYPE_ONCE /**< \deprecated replaced by \ref
+ CY_TIMER_TYPE_ONCE */
+} cy_timer_trigger_type_t;
+
+/**
+ * The type of a function that is the entry point for a thread
+ *
+ * @param[in] arg the argument passed from the thread create call to the entry function
+ *
+ * \ingroup group_abstraction_rtos_threads
+ */
+typedef void (* cy_thread_entry_fn_t)(cy_thread_arg_t arg);
+
+/**
+ * The callback function to be called by a timer
+ *
+ * \ingroup group_abstraction_rtos_timer
+ */
+typedef void (* cy_timer_callback_t)(cy_timer_callback_arg_t arg);
+
+/**
+ * Return the last error from the RTOS.
+ *
+ * The functions in the RTOS abstraction layer adhere to the Infineon return
+ * results calling convention. The underlying RTOS implementations will not but rather
+ * will have their own error code conventions. This function is provided as a service
+ * to the developer, mostly for debugging, and returns the underlying RTOS error code
+ * from the last RTOS abstraction layer that returned \ref CY_RTOS_GENERAL_ERROR.
+ *
+ * @return RTOS specific error code.
+ *
+ * \ingroup group_abstraction_rtos_common
+ */
+cy_rtos_error_t cy_rtos_last_error(void);
+
+
+/********************************************* Threads ********************************************/
+
+/**
+ * \ingroup group_abstraction_rtos_threads
+ * \{
+ */
+
+/** Create a thread with specific thread argument.
+ *
+ * This function is called to startup a new thread. If the thread can exit, it must call
+ * \ref cy_rtos_exit_thread() just before doing so. All created threads that can terminate, either
+ * by themselves or forcefully by another thread MUST have \ref cy_rtos_join_thread() called on them
+ * by another thread in order to cleanup any resources that might have been allocated for them.
+ *
+ * @param[out] thread Pointer to a variable which will receive the new thread handle
+ * @param[in] entry_function Function pointer which points to the main function for the new thread
+ * @param[in] name String thread name used for a debugger
+ * @param[in] stack The buffer to use for the thread stack. This must be aligned to
+ * \ref CY_RTOS_ALIGNMENT_MASK with a size of at least \ref
+ * CY_RTOS_MIN_STACK_SIZE.
+ * If stack is null, cy_rtos_create_thread will allocate a stack from
+ * the heap.
+ * @param[in] stack_size The size of the thread stack in bytes
+ * @param[in] priority The priority of the thread. Values are operating system specific,
+ * but some common priority levels are defined:
+ * CY_THREAD_PRIORITY_LOW
+ * CY_THREAD_PRIORITY_NORMAL
+ * CY_THREAD_PRIORITY_HIGH
+ * @param[in] arg The argument to pass to the new thread
+ *
+ * @return The status of thread create request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref
+ * CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t 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);
+
+/** Exit the current thread.
+ *
+ * This function is called just before a thread exits. In some cases it is sufficient
+ * for a thread to just return to exit, but in other cases, the RTOS must be explicitly
+ * signaled. In cases where a return is sufficient, this should be a null funcition.
+ * where the RTOS must be signaled, this function should perform that In cases operation.
+ * In code using RTOS services, this function should be placed at any at any location
+ * where the main thread function will return, exiting the thread. Threads that can
+ * exit must still be joined (\ref cy_rtos_join_thread) to ensure their resources are
+ * fully cleaned up.
+ *
+ * @return The status of thread exit request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_exit_thread(void);
+
+/** Terminates another thread.
+ *
+ * This function is called to terminate another thread and reap the resources claimed
+ * by the thread. This should be called both when forcibly terminating another thread
+ * as well as any time a thread can exit on its own. For some RTOS implementations
+ * this is not required as the thread resources are claimed as soon as it exits. In
+ * other cases, this must be called to reclaim resources. Threads that are terminated
+ * must still be joined (\ref cy_rtos_join_thread) to ensure their resources are fully
+ * cleaned up.
+ *
+ * @param[in] thread Handle of the thread to terminate
+ *
+ * @returns The status of the thread terminate. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_terminate_thread(cy_thread_t* thread);
+
+/** Waits for a thread to complete.
+ *
+ * This must be called on any thread that can complete to ensure that any resources that
+ * were allocated for it are cleaned up.
+ *
+ * @param[in] thread Handle of the thread to wait for
+ *
+ * @returns The status of thread join request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_join_thread(cy_thread_t* thread);
+
+/** Checks if the thread is running
+ *
+ * This function is called to determine if a thread is actively running or not. For information on
+ * the thread state, use the \ref cy_rtos_get_thread_state() function.
+ *
+ * @param[in] thread Handle of the terminated thread to delete
+ * @param[out] running Returns true if the thread is running, otherwise false
+ *
+ * @returns The status of the thread running check. [\ref CY_RSLT_SUCCESS, \ref
+ * CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_is_thread_running(cy_thread_t* thread, bool* running);
+
+/** Gets the state the thread is currently in
+ *
+ * This function is called to determine if a thread is running/blocked/inactive/ready etc.
+ *
+ * @param[in] thread Handle of the terminated thread to delete
+ * @param[out] state Returns the state the thread is currently in
+ *
+ * @returns The status of the thread state check. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_get_thread_state(cy_thread_t* thread, cy_thread_state_t* state);
+
+/** Get current thread handle
+ *
+ * Returns the unique thread handle of the current running thread.
+ *
+ * @param[out] thread Handle of the current running thread
+ *
+ * @returns The status of thread join request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_get_thread_handle(cy_thread_t* thread);
+
+
+/** Suspend current thread until notification is received
+ *
+ * This function suspends the execution of current thread until it is notified
+ * by \ref cy_rtos_set_thread_notification from another thread or ISR, or timed out with
+ * specify timeout value
+ *
+ * @param[in] timeout_ms Maximum number of milliseconds to wait
+ * Use the \ref CY_RTOS_NEVER_TIMEOUT constant to wait forever.
+ *
+ * @returns The status of thread wait. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_TIMEOUT, \ref
+ * CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_wait_thread_notification(cy_time_t timeout_ms);
+
+
+/** Set the thread notification for a thread
+ *
+ * This function sets the thread notification for the target thread.
+ * The target thread waiting for the notification to be set will resume from suspended state.
+ *
+ * @param[in] thread Handle of the target thread
+ * @param[in] in_isr If true this is being called from within an ISR
+ *
+ * @returns The status of thread wait. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR,
+ * \ref CY_RTOS_BAD_PARAM]
+ */
+cy_rslt_t cy_rtos_set_thread_notification(cy_thread_t* thread, bool in_isr);
+
+
+/** \} group_abstraction_rtos_threads */
+
+
+/********************************************* Mutexes ********************************************/
+
+/**
+ * \ingroup group_abstraction_rtos_mutex
+ * \{
+ */
+
+/** Create a recursive mutex.
+ *
+ * Creates a binary mutex which can be used for mutual exclusion to prevent simulatenous
+ * access of shared resources. Created mutexes can support priority inheritance if recursive.
+ *
+ * This function has been replaced by \ref cy_rtos_init_mutex2 which allow for specifying
+ * whether or not the mutex supports recursion or not.
+ *
+ * @param[out] mutex Pointer to the mutex handle to be initialized
+ *
+ * @return The status of mutex creation request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref
+ * CY_RTOS_GENERAL_ERROR]
+ */
+#define cy_rtos_init_mutex(mutex) cy_rtos_init_mutex2(mutex, true)
+
+/** Create a mutex which can support recursion or not.
+ *
+ * Creates a binary mutex which can be used for mutual exclusion to prevent simulatenous
+ * access of shared resources. Created mutexes can support priority inheritance if recursive.
+ *
+ * \note Not all RTOS implementations support non-recursive mutexes. In this case a recursive
+ * mutex will be created.
+ *
+ * @param[out] mutex Pointer to the mutex handle to be initialized
+ * @param[in] recursive Should the created mutex support recursion or not
+ *
+ * @return The status of mutex creation request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref
+ * CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_init_mutex2(cy_mutex_t* mutex, bool recursive);
+
+/** Get a mutex.
+ *
+ * If the mutex is available, it is acquired and this function returned.
+ * If the mutex is not available, the thread waits until the mutex is available
+ * or until the timeout occurs.
+ *
+ * @note This function must not be called from an interrupt context as it may block.
+ *
+ * @param[in] mutex Pointer to the mutex handle
+ * @param[in] timeout_ms Maximum number of milliseconds to wait while attempting to get
+ * the mutex. Use the \ref CY_RTOS_NEVER_TIMEOUT constant to wait forever.
+ *
+ * @return The status of the get mutex. Returns timeout if mutex was not acquired
+ * before timeout_ms period. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_TIMEOUT, \ref
+ * CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_get_mutex(cy_mutex_t* mutex, cy_time_t timeout_ms);
+
+/** Set a mutex.
+ *
+ * The mutex is released allowing any other threads waiting on the mutex to
+ * obtain the semaphore.
+ *
+ * @param[in] mutex Pointer to the mutex handle
+ *
+ * @return The status of the set mutex request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR]
+ *
+ */
+cy_rslt_t cy_rtos_set_mutex(cy_mutex_t* mutex);
+
+/** Deletes a mutex.
+ *
+ * This function frees the resources associated with a sempahore.
+ *
+ * @param[in] mutex Pointer to the mutex handle
+ *
+ * @return The status to the delete request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_deinit_mutex(cy_mutex_t* mutex);
+
+/** \} group_abstraction_rtos_mutex */
+
+/******************************************** Semaphores ******************************************/
+
+/**
+ * \ingroup group_abstraction_rtos_semaphore
+ * \{
+ */
+
+/**
+ * Create a semaphore
+ *
+ * This is basically a counting semaphore. It can be used for synchronization between tasks and
+ * tasks and interrupts.
+ *
+ * @param[in,out] semaphore Pointer to the semaphore handle to be initialized
+ * @param[in] maxcount The maximum count for this semaphore
+ * @param[in] initcount The initial count for this semaphore
+ *
+ * @return The status of the semaphore creation. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref
+ * CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_init_semaphore(cy_semaphore_t* semaphore, uint32_t maxcount, uint32_t initcount);
+
+/**
+ * Get/Acquire a semaphore
+ *
+ * If the semaphore count is zero, waits until the semaphore count is greater than zero.
+ * Once the semaphore count is greater than zero, this function decrements
+ * the count and return. It may also return if the timeout is exceeded.
+ *
+ * @param[in] semaphore Pointer to the semaphore handle
+ * @param[in] timeout_ms Maximum number of milliseconds to wait while attempting to get
+ * the semaphore. Use the \ref CY_RTOS_NEVER_TIMEOUT constant to wait
+ * forever. Must be zero if in_isr is true.
+ * @param[in] in_isr true if we are trying to get the semaphore from with an ISR
+ * @return The status of get semaphore operation [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_TIMEOUT, \ref
+ * CY_RTOS_NO_MEMORY, \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_get_semaphore(cy_semaphore_t* semaphore, cy_time_t timeout_ms, bool in_isr);
+
+/**
+ * Set/Release a semaphore
+ *
+ * Increments the semaphore count, up to the maximum count for this semaphore.
+ *
+ * @param[in] semaphore Pointer to the semaphore handle
+ * @param[in] in_isr Value of true indicates calling from interrupt context
+ * Value of false indicates calling from normal thread context
+ * @return The status of set semaphore operation [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref
+ * CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_set_semaphore(cy_semaphore_t* semaphore, bool in_isr);
+
+/**
+ * Get the count of a semaphore.
+ *
+ * Gets the number of available tokens on the semaphore.
+ *
+ * @param[in] semaphore Pointer to the semaphore handle
+ * @param[out] count Pointer to the return count
+ * @return The status of get semaphore count operation [\ref CY_RSLT_SUCCESS, \ref
+ * CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_get_count_semaphore(cy_semaphore_t* semaphore, size_t* count);
+
+/**
+ * Deletes a semaphore
+ *
+ * This function frees the resources associated with a semaphore.
+ *
+ * @param[in] semaphore Pointer to the semaphore handle
+ *
+ * @return The status of semaphore deletion [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref
+ * CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_deinit_semaphore(cy_semaphore_t* semaphore);
+
+/** \} group_abstraction_rtos_semaphore */
+
+/********************************************* Events ********************************************/
+
+/**
+ * \ingroup group_abstraction_rtos_event
+ * \{
+ */
+
+/** Create an event.
+ *
+ * This is an event which can be used to signal a set of threads
+ * with a 32 bit data element.
+ *
+ * @param[in,out] event Pointer to the event handle to be initialized
+ *
+ * @return The status of the event initialization request.
+ * [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_init_event(cy_event_t* event);
+
+/** Set the event flag bits.
+ *
+ * This is an event which can be used to signal a set of threads
+ * with a 32 bit data element. Any threads waiting on this event are released
+ *
+ * @param[in] event Pointer to the event handle
+ * @param[in] bits The value of the 32 bit flags
+ * @param[in] in_isr If true, this is called from an ISR, otherwise from a thread
+ *
+ * @return The status of the set request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref
+ * CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_setbits_event(cy_event_t* event, uint32_t bits, bool in_isr);
+
+/**
+ * Clear the event flag bits
+ *
+ * This function clears bits in the event.
+ *
+ * @param[in] event Pointer to the event handle
+ * @param[in] bits Any bits set in this value, will be cleared in the event.
+ * @param[in] in_isr if true, this is called from an ISR, otherwise from a thread
+ *
+ * @return The status of the clear flags request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY,
+ * \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_clearbits_event(cy_event_t* event, uint32_t bits, bool in_isr);
+
+/** Get the event bits.
+ *
+ * Returns the current bits for the event.
+ *
+ * @param[in] event Pointer to the event handle
+ * @param[out] bits pointer to receive the value of the event flags
+ *
+ * @return The status of the get request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref
+ * CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_getbits_event(cy_event_t* event, uint32_t* bits);
+
+/** Wait for the event and return bits.
+ *
+ * Waits for the event to be set and then returns the bits associated
+ * with the event, or waits for the given timeout period.
+ * @note This function returns if any bit in the set is set.
+ *
+ * @param[in] event Pointer to the event handle
+ * @param[in,out] bits pointer to receive the value of the event flags
+ * @param[in] clear if true, clear any bits set that cause the wait to return
+ * if false, do not clear bits
+ * @param[in] all if true, all bits in the initial bits value must be set to return
+ * if false, any one bit in the initial bits value must be set to return
+ * @param[in] timeout_ms The amount of time to wait in milliseconds
+ *
+ * @return The status of the wait for event request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY,
+ * \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_waitbits_event(cy_event_t* event, uint32_t* bits, bool clear, bool all,
+ cy_time_t timeout_ms);
+
+/** Deinitialize a event.
+ *
+ * This function frees the resources associated with an event.
+ *
+ * @param[in] event Pointer to the event handle
+ *
+ * @return The status of the deletion request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_deinit_event(cy_event_t* event);
+
+/** \} group_abstraction_rtos_event */
+
+/********************************************* Queues *********************************************/
+
+/**
+ * \ingroup group_abstraction_rtos_queue
+ * \{
+ */
+
+/** Create a queue.
+ *
+ * This is a queue of data where entries are placed on the back of the queue
+ * and removed from the front of the queue.
+ *
+ * @param[out] queue Pointer to the queue handle
+ * @param[in] length The maximum length of the queue in items
+ * @param[in] itemsize The size of each item in the queue.
+ *
+ * @return The status of the init request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref
+ * CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_init_queue(cy_queue_t* queue, size_t length, size_t itemsize);
+
+/** Put an item in a queue.
+ *
+ * This function puts an item in the queue. The item is copied
+ * into the queue using a memory copy and the data pointed to by item_ptr
+ * is no longer referenced once the call returns.
+ *
+ * @note If in_isr is true, timeout_ms must be zero.
+ *
+ * @param[in] queue Pointer to the queue handle
+ * @param[in] item_ptr Pointer to the item to place in the queue
+ * @param[in] timeout_ms The time to wait to place the item in the queue
+ * @param[in] in_isr If true this is being called from within and ISR
+ *
+ * @return The status of the put request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref
+ * CY_RTOS_GENERAL_ERROR, \ref CY_RTOS_QUEUE_FULL]
+ */
+cy_rslt_t cy_rtos_put_queue(cy_queue_t* queue, const void* item_ptr, cy_time_t timeout_ms,
+ bool in_isr);
+
+/** Gets an item in a queue.
+ *
+ * This function gets an item from the queue. The item is copied
+ * out of the queue into the memory provide by item_ptr. This space must be
+ * large enough to hold a queue entry as defined when the queue was initialized.
+ *
+ * @note If in_isr is true, timeout_ms must be zero.
+ *
+ * @param[in] queue Pointer to the queue handle
+ * @param[in] item_ptr Pointer to the memory for the item from the queue
+ * @param[in] timeout_ms The time to wait to get an item from the queue
+ * @param[in] in_isr If true this is being called from within an ISR
+ *
+ * @return The status of the get request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_NO_MEMORY, \ref
+ * CY_RTOS_GENERAL_ERROR, \ref CY_RTOS_QUEUE_EMPTY]
+ */
+cy_rslt_t cy_rtos_get_queue(cy_queue_t* queue, void* item_ptr, cy_time_t timeout_ms, bool in_isr);
+
+/** Return the number of items in the queue.
+ *
+ * This function returns the number of items currently in the queue.
+ *
+ * @param[in] queue Pointer to the queue handle
+ * @param[out] num_waiting Pointer to the return count
+ *
+ * @return The status of the count request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_count_queue(cy_queue_t* queue, size_t* num_waiting);
+
+/** Return the amount of empty space in the queue.
+ *
+ * This function returns the amount of empty space in the
+ * queue. For instance, if the queue was created with 10 entries max and there
+ * are currently 2 entries in the queue, this will return 8.
+ *
+ * @param[in] queue Pointer to the queue handle
+ * @param[out] num_spaces Pointer to the return count.
+ *
+ * @return The status of the space request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_space_queue(cy_queue_t* queue, size_t* num_spaces);
+
+/** Reset the queue.
+ *
+ * This function sets the queue to empty.
+ *
+ * @param[in] queue pointer to the queue handle
+ *
+ * @return The status of the reset request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_reset_queue(cy_queue_t* queue);
+
+/** Deinitialize the queue handle.
+ *
+ * This function de-initializes the queue and returns all
+ * resources used by the queue.
+ *
+ * @param[in] queue Pointer to the queue handle
+ *
+ * @return The status of the deinit request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_deinit_queue(cy_queue_t* queue);
+
+/** \} group_abstraction_rtos_queue */
+
+/********************************************* Timers *********************************************/
+
+/**
+ * \ingroup group_abstraction_rtos_timer
+ * \{
+ */
+
+/** Create a new timer.
+ *
+ * This function initializes a timer object.
+ * @note The timer is not active until start is called.
+ * @note The callback may be (likely will be) called from a different thread.
+ *
+ * @param[out] timer Pointer to the timer handle to initialize
+ * @param[in] type Type of timer (periodic or once)
+ * @param[in] fun The function
+ * @param[in] arg Argument to pass along to the callback function
+ *
+ * @return The status of the init request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t 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);
+
+/** Sends a request to start the timer. Depending on the priorities of threads in the system,
+ * it may be necessary for high priority items to wait before the timer actually starts running.
+ *
+ * @param[in] timer Pointer to the timer handle
+ * @param[in] num_ms The number of milliseconds to wait before the timer fires
+ *
+ * @return The status of the start request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_start_timer(cy_timer_t* timer, cy_time_t num_ms);
+
+/** Sends a request to stop the timer. Depending on the priorities of threads in the system,
+ * it may be necessary for high priority items to wait before the timer is actually stopped.
+ *
+ * @param[in] timer Pointer to the timer handle
+ *
+ * @return The status of the stop request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_stop_timer(cy_timer_t* timer);
+
+/** Returns state of a timer.
+ *
+ * @param[in] timer Pointer to the timer handle
+ * @param[out] state Return value for state, true if running, false otherwise
+ *
+ * @return The status of the is_running request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_is_running_timer(cy_timer_t* timer, bool* state);
+
+/** Deinit the timer.
+ *
+ * This function deinitializes the timer and frees all consumed resources.
+ *
+ * @param[in] timer Pointer to the timer handle
+ *
+ * @return The status of the deinit request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_deinit_timer(cy_timer_t* timer);
+
+/** \} group_abstraction_rtos_timer */
+
+/********************************************** Time **********************************************/
+
+/**
+ * \ingroup group_abstraction_rtos_time
+ * \{
+ */
+
+/** Gets time in milliseconds since RTOS start.
+ *
+ * @note Since this is only 32 bits, it will roll over every 49 days, 17 hours, 2 mins, 47.296
+ * seconds
+ *
+ * @param[out] tval Pointer to the struct to populate with the RTOS time
+ *
+ * @returns Time in milliseconds since the RTOS started.
+ */
+cy_rslt_t cy_rtos_get_time(cy_time_t* tval);
+
+/** Delay for a number of milliseconds.
+ *
+ * Processing of this function depends on the minimum sleep
+ * time resolution of the RTOS. The current thread should sleep for
+ * the longest period possible which is less than the delay required,
+ * then makes up the difference with a tight loop.
+ *
+ * @param[in] num_ms The number of milliseconds to delay for
+ *
+ * @return The status of the delay request. [\ref CY_RSLT_SUCCESS, \ref CY_RTOS_GENERAL_ERROR]
+ */
+cy_rslt_t cy_rtos_delay_milliseconds(cy_time_t num_ms);
+
+/** \} group_abstraction_rtos_time */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/abstraction-rtos/include/cyabs_rtos_internal.h b/abstraction-rtos/include/cyabs_rtos_internal.h
new file mode 100644
index 00000000..e1655cf1
--- /dev/null
+++ b/abstraction-rtos/include/cyabs_rtos_internal.h
@@ -0,0 +1,53 @@
+/***********************************************************************************************//**
+ * \file cyabs_rtos_internal.h
+ *
+ * \brief
+ * Internal interface used for RTOS abstraction utilities.
+ ***************************************************************************************************
+ * \copyright
+ * Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or
+ * an affiliate of Cypress Semiconductor Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **************************************************************************************************/
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+
+/** Checks to see if code is currently executing within an interrupt context.
+ *
+ * @return Boolean indicating whether this was executed from an interrupt context.
+ */
+static inline bool is_in_isr(void)
+{
+ #if defined(COMPONENT_CR4) // Can work for any Cortex-A & Cortex-R
+ uint32_t mode = __get_mode();
+ return (mode == 0x11U /*FIQ*/) || (mode == 0x12U /*IRQ*/) || (mode == 0x13U /*SVC*/) ||
+ (mode == 0x17U /*ABT*/) || (mode == 0x1BU /*UND*/);
+ #else // Cortex-M
+ return (__get_IPSR() != 0);
+ #endif
+}
+
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/abstraction-rtos/source/COMPONENT_FREERTOS/cyabs_freertos_helpers.c b/abstraction-rtos/source/COMPONENT_FREERTOS/cyabs_freertos_helpers.c
new file mode 100644
index 00000000..a1af9d17
--- /dev/null
+++ b/abstraction-rtos/source/COMPONENT_FREERTOS/cyabs_freertos_helpers.c
@@ -0,0 +1,225 @@
+/***********************************************************************************************//**
+ * \file cyabs_freertos_helpers.c
+ *
+ * \brief
+ * Provides implementations for functions required to enable static allocation and
+ * tickless mode in FreeRTOS.
+ *
+ ***************************************************************************************************
+ * \copyright
+ * Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or
+ * an affiliate of Cypress Semiconductor Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **************************************************************************************************/
+#include "FreeRTOS.h"
+#include "task.h"
+#include "cyabs_rtos.h"
+#if defined(CY_USING_HAL)
+#include "cyhal.h"
+#endif
+
+// This is included to allow the user to control the idle task behavior via the configurator
+// System->Power->RTOS->System Idle Power Mode setting.
+#if defined(COMPONENT_BSP_DESIGN_MODUS) || defined(COMPONENT_CUSTOM_DESIGN_MODUS)
+#include "cycfg.h"
+#endif
+
+#define pdTICKS_TO_MS(xTicks) ( ( ( TickType_t ) ( xTicks ) * 1000u ) / configTICK_RATE_HZ )
+
+#if defined(CY_USING_HAL)
+static cyhal_lptimer_t* _timer = NULL;
+
+//--------------------------------------------------------------------------------------------------
+// cyabs_rtos_set_lptimer
+//--------------------------------------------------------------------------------------------------
+void cyabs_rtos_set_lptimer(cyhal_lptimer_t* timer)
+{
+ _timer = timer;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cyabs_rtos_get_lptimer
+//--------------------------------------------------------------------------------------------------
+cyhal_lptimer_t* cyabs_rtos_get_lptimer(void)
+{
+ return _timer;
+}
+
+
+#endif //defined(CY_USING_HAL)
+
+// The following implementations were sourced from https://www.freertos.org/a00110.html
+
+//--------------------------------------------------------------------------------------------------
+// vApplicationGetIdleTaskMemory
+//
+// configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an implementation of
+// vApplicationGetIdleTaskMemory() to provide the memory that is used by the Idle task.
+//--------------------------------------------------------------------------------------------------
+__WEAK void vApplicationGetIdleTaskMemory(StaticTask_t** ppxIdleTaskTCBBuffer,
+ StackType_t** ppxIdleTaskStackBuffer,
+ uint32_t* pulIdleTaskStackSize)
+{
+ // If the buffers to be provided to the Idle task are declared inside this function then they
+ // must be declared static – otherwise they will be allocated on the stack and so not exists
+ // after this function exits.
+ static StaticTask_t xIdleTaskTCB;
+ static StackType_t uxIdleTaskStack[configMINIMAL_STACK_SIZE];
+
+ // Pass out a pointer to the StaticTask_t structure in which the Idle task’s state will be
+ // stored.
+ *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
+
+ // Pass out the array that will be used as the Idle task’s stack.
+ *ppxIdleTaskStackBuffer = uxIdleTaskStack;
+
+ // Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. Note that, as the
+ // array is necessarily of type StackType_t, configMINIMAL_STACK_SIZE is specified in words, not
+ // bytes.
+ *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
+}
+
+
+/*———————————————————–*/
+
+//--------------------------------------------------------------------------------------------------
+// vApplicationGetTimerTaskMemory
+//
+// configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the application must
+// provide an implementation of vApplicationGetTimerTaskMemory() to provide the memory that is used
+// by the Timer service task.
+//--------------------------------------------------------------------------------------------------
+__WEAK void vApplicationGetTimerTaskMemory(StaticTask_t** ppxTimerTaskTCBBuffer,
+ StackType_t** ppxTimerTaskStackBuffer,
+ uint32_t* pulTimerTaskStackSize)
+{
+ // If the buffers to be provided to the Timer task are declared inside this function then they
+ // must be declared static – otherwise they will be allocated on the stack and so not exists
+ // after this function exits.
+ static StaticTask_t xTimerTaskTCB;
+ static StackType_t uxTimerTaskStack[configTIMER_TASK_STACK_DEPTH];
+
+ // Pass out a pointer to the StaticTask_t structure in which the Timer task’s state will be
+ // stored.
+ *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
+
+ // Pass out the array that will be used as the Timer task’s stack.
+ *ppxTimerTaskStackBuffer = uxTimerTaskStack;
+
+ // Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. Note that, as the
+ // array is necessarily of type StackType_t, configTIMER_TASK_STACK_DEPTH is specified in words,
+ // not bytes.
+ *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
+}
+
+
+#if defined(CY_USING_HAL) && (configUSE_TICKLESS_IDLE != 0)
+//--------------------------------------------------------------------------------------------------
+// vApplicationSleep
+//
+/** User defined tickless idle sleep function.
+ *
+ * Provides a implementation for portSUPPRESS_TICKS_AND_SLEEP macro that allows
+ * the device to attempt to deep-sleep for the idle time the kernel expects before
+ * the next task is ready. This function disables the system timer and enables low power
+ * timer that can operate in deep-sleep mode to wake the device from deep-sleep after
+ * expected idle time has elapsed.
+ *
+ * @param[in] xExpectedIdleTime Total number of tick periods before
+ * a task is due to be moved into the Ready state.
+ */
+//--------------------------------------------------------------------------------------------------
+__WEAK void vApplicationSleep(TickType_t xExpectedIdleTime)
+{
+ static cyhal_lptimer_t timer;
+ uint32_t actual_sleep_ms = 0;
+
+ if (NULL == _timer)
+ {
+ cy_rslt_t result = cyhal_lptimer_init(&timer);
+ if (result == CY_RSLT_SUCCESS)
+ {
+ _timer = &timer;
+ }
+ else
+ {
+ CY_ASSERT(false);
+ }
+ }
+
+ if (NULL != _timer)
+ {
+ /* Disable interrupts so that nothing can change the status of the RTOS while
+ * we try to go to sleep or deep-sleep.
+ */
+ uint32_t status = cyhal_system_critical_section_enter();
+ eSleepModeStatus sleep_status = eTaskConfirmSleepModeStatus();
+
+ if (sleep_status != eAbortSleep)
+ {
+ // By default, the device will deep-sleep in the idle task unless if the device
+ // configurator overrides the behaviour to sleep in the System->Power->RTOS->System
+ // Idle Power Mode setting.
+ bool deep_sleep = true;
+ #if defined (CY_CFG_PWR_SYS_IDLE_MODE)
+ // If the system needs to operate in active mode the tickless mode should not be used in
+ // FreeRTOS
+ CY_ASSERT(CY_CFG_PWR_SYS_IDLE_MODE != CY_CFG_PWR_MODE_ACTIVE);
+ deep_sleep =
+ ((CY_CFG_PWR_SYS_IDLE_MODE & CY_CFG_PWR_MODE_DEEPSLEEP) ==
+ CY_CFG_PWR_MODE_DEEPSLEEP);
+ #endif
+ uint32_t sleep_ms = pdTICKS_TO_MS(xExpectedIdleTime);
+ cy_rslt_t result;
+ if (deep_sleep)
+ {
+ // Adjust the deep-sleep time by the sleep/wake latency if set.
+ #if defined(CY_CFG_PWR_DEEPSLEEP_LATENCY)
+ if (sleep_ms > CY_CFG_PWR_DEEPSLEEP_LATENCY)
+ {
+ sleep_ms -= CY_CFG_PWR_DEEPSLEEP_LATENCY;
+ result = cyhal_syspm_tickless_deepsleep(_timer, sleep_ms, &actual_sleep_ms);
+ }
+ else
+ {
+ result = CY_RTOS_TIMEOUT;
+ }
+ #else // defined(CY_CFG_PWR_DEEPSLEEP_LATENCY)
+ result = cyhal_syspm_tickless_deepsleep(_timer, sleep_ms, &actual_sleep_ms);
+ #endif // defined(CY_CFG_PWR_DEEPSLEEP_LATENCY)
+ }
+ else
+ {
+ result = cyhal_syspm_tickless_sleep(_timer, sleep_ms, &actual_sleep_ms);
+ }
+
+ if (result == CY_RSLT_SUCCESS)
+ {
+ // If you hit this assert, the latency time (CY_CFG_PWR_DEEPSLEEP_LATENCY) should
+ // be increased. This can be set though the Device Configurator, or by manually
+ // defining the variable.
+ CY_ASSERT(actual_sleep_ms <= pdTICKS_TO_MS(xExpectedIdleTime));
+ vTaskStepTick(pdMS_TO_TICKS(actual_sleep_ms));
+ }
+ }
+
+ cyhal_system_critical_section_exit(status);
+ }
+}
+
+
+#endif // defined(CY_USING_HAL) && (configUSE_TICKLESS_IDLE != 0)
diff --git a/abstraction-rtos/source/COMPONENT_FREERTOS/cyabs_rtos_freertos.c b/abstraction-rtos/source/COMPONENT_FREERTOS/cyabs_rtos_freertos.c
new file mode 100644
index 00000000..871bd1d5
--- /dev/null
+++ b/abstraction-rtos/source/COMPONENT_FREERTOS/cyabs_rtos_freertos.c
@@ -0,0 +1,1173 @@
+/***********************************************************************************************//**
+ * \file cyabs_rtos_freertos.c
+ *
+ * \brief
+ * Implementation for FreeRTOS abstraction
+ *
+ ***************************************************************************************************
+ * \copyright
+ * Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or
+ * an affiliate of Cypress Semiconductor Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **************************************************************************************************/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "cyabs_rtos_internal.h"
+
+static const uint32_t TASK_IDENT = 0xABCDEF01U;
+static cy_rtos_error_t last_error;
+
+typedef struct
+{
+ cy_timer_callback_t cb;
+ cy_timer_callback_arg_t arg;
+} callback_data_t;
+
+// Wrapper function to convert FreeRTOS callback signature to match expectation
+// for our cyabs_rtos abstraction API.
+static void timer_callback(TimerHandle_t arg)
+{
+ callback_data_t* cb_arg = (callback_data_t*)pvTimerGetTimerID(arg);
+ if (NULL != cb_arg->cb)
+ {
+ cb_arg->cb(cb_arg->arg);
+ }
+}
+
+
+//==================================================================================================
+// Error Converter
+//==================================================================================================
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_last_error
+//--------------------------------------------------------------------------------------------------
+cy_rtos_error_t cy_rtos_last_error(void)
+{
+ return last_error;
+}
+
+
+//==================================================================================================
+// Threads
+//==================================================================================================
+
+typedef struct
+{
+ StaticTask_t task;
+ SemaphoreHandle_t sema;
+ uint32_t magic;
+ void* memptr;
+} cy_task_wrapper_t;
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_create_thread
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t 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)
+{
+ cy_rslt_t status;
+ if ((thread == NULL) || (stack_size < CY_RTOS_MIN_STACK_SIZE))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else if ((stack != NULL) && (0 != (((uint32_t)stack) & CY_RTOS_ALIGNMENT_MASK)))
+ {
+ status = CY_RTOS_ALIGNMENT_ERROR;
+ }
+ else
+ {
+ // If the user provides a stack, we need to allocate memory for the StaticTask_t. If we
+ // allocate memory we also need to clean it up. This is true when the task exits itself or
+ // when it is killed. In the case it is killed is fairly straight forward. In the case
+ // where it exits, we can't clean up any allocated memory since we can't free it before
+ // calling vTaskDelete() and vTaskDelete() never returns. Thus we need to do it in join.
+ // However, if the task exited itself it has also released any memory it allocated. Thus
+ // in order to be able to reliably free memory as part of join, we need to know that the
+ // data we are accessing (the StaticTask_t) has not been freed. We therefore need to always
+ // allocate that object ourselves. This means we also need to allocate the stack if the
+ // user did not provide one.
+ uint32_t offset = (stack == NULL)
+ ? (stack_size & ~CY_RTOS_ALIGNMENT_MASK)
+ : 0;
+ uint32_t size = offset + sizeof(cy_task_wrapper_t);
+ uint8_t* ident = (uint8_t*)pvPortMalloc(size);
+
+ if (ident == NULL)
+ {
+ status = CY_RTOS_NO_MEMORY;
+ }
+ else
+ {
+ StackType_t stack_size_rtos =
+ ((stack_size & ~CY_RTOS_ALIGNMENT_MASK) / sizeof(StackType_t));
+ StackType_t* stack_rtos = (stack == NULL)
+ ? (StackType_t*)ident
+ : (StackType_t*)stack;
+
+ cy_task_wrapper_t* wrapper = (cy_task_wrapper_t*)(ident + offset);
+ wrapper->sema = xSemaphoreCreateBinary();
+ CY_ASSERT(wrapper->sema != NULL);
+ wrapper->magic = TASK_IDENT;
+ wrapper->memptr = ident;
+ CY_ASSERT(((uint32_t)wrapper & CY_RTOS_ALIGNMENT_MASK) == 0UL);
+ *thread = xTaskCreateStatic((TaskFunction_t)entry_function, name, stack_size_rtos, arg,
+ priority, stack_rtos, &(wrapper->task));
+ CY_ASSERT(((void*)*thread == (void*)&(wrapper->task)) || (*thread == NULL));
+ status = CY_RSLT_SUCCESS;
+ }
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_exit_thread
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_exit_thread(void)
+{
+ TaskHandle_t handle = xTaskGetCurrentTaskHandle();
+ // Ideally this would just call vTaskDelete(NULL); however FreeRTOS
+ // does not provide any way to know when the task is actually cleaned
+ // up. It will tell you that it has been deleted, but when delete is
+ // called from the thread itself it doesn't actually get deleted at
+ // that time. It just gets added to the list of items that will be
+ // deleted when the idle task runs, but there is no way of knowing
+ // that the idle task ran unless you add an application hook which is
+ // not something that can be done here. This means that
+ // cy_rtos_join_thread() has no way of knowing that it is actually
+ // save to cleanup memory. So, instad of deleting here, we use a
+ // semaphore to indicate that we can delete and then join waits on
+ // the semaphore.
+
+ // This cast is ok because the handle internally represents the TCB that we created in the
+ // thread create function.
+ cy_task_wrapper_t* wrapper = ((cy_task_wrapper_t*)handle);
+ if (wrapper->magic == TASK_IDENT)
+ {
+ // This signals to the thread deleting the current thread that it it is safe to delete the
+ // current thread.
+ xSemaphoreGive(wrapper->sema);
+ }
+ else
+ {
+ CY_ASSERT(false);
+ }
+
+ // This function is not expected to return and calling cy_rtos_join_thread will call vTaskDelete
+ // on this thread and clean up.
+ while (1)
+ {
+ #if defined(INCLUDE_vTaskSuspend)
+ vTaskSuspend(handle);
+ #else
+ vTaskDelay(10000);
+ #endif
+ }
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_terminate_thread
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_terminate_thread(cy_thread_t* thread)
+{
+ cy_rslt_t status;
+ if (thread == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ vTaskDelete(*thread);
+ // Check to see if we allocated the task and if so free it up.
+ cy_task_wrapper_t* wrapper = ((cy_task_wrapper_t*)*thread);
+ vTaskSuspendAll();
+ if (wrapper->magic == TASK_IDENT)
+ {
+ wrapper->magic = 0;
+ vSemaphoreDelete(wrapper->sema);
+ vPortFree(wrapper->memptr);
+ }
+ xTaskResumeAll();
+ status = CY_RSLT_SUCCESS;
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_is_thread_running
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_is_thread_running(cy_thread_t* thread, bool* running)
+{
+ cy_rslt_t status;
+ if ((thread == NULL) || (running == NULL))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ eTaskState st = eTaskGetState(*thread);
+ *running = (st == eRunning);
+ status = CY_RSLT_SUCCESS;
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_get_thread_state
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_get_thread_state(cy_thread_t* thread, cy_thread_state_t* state)
+{
+ cy_rslt_t status;
+ if ((thread == NULL) || (state == NULL))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ eTaskState st = eTaskGetState(*thread);
+ switch (st)
+ {
+ case eSuspended:
+ *state = CY_THREAD_STATE_INACTIVE;
+ break;
+
+ case eReady:
+ *state = CY_THREAD_STATE_READY;
+ break;
+
+ case eRunning:
+ *state = CY_THREAD_STATE_RUNNING;
+ break;
+
+ case eBlocked:
+ *state = CY_THREAD_STATE_BLOCKED;
+ break;
+
+ case eDeleted:
+ *state = CY_THREAD_STATE_TERMINATED;
+ break;
+
+ case eInvalid:
+ default:
+ *state = CY_THREAD_STATE_UNKNOWN;
+ break;
+ }
+
+ status = CY_RSLT_SUCCESS;
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_join_thread
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_join_thread(cy_thread_t* thread)
+{
+ cy_rslt_t status = CY_RSLT_SUCCESS;
+ if (thread == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ cy_task_wrapper_t* wrapper = ((cy_task_wrapper_t*)(*thread));
+ // This makes sure that the thread to be deleted has completed. See cy_rtos_exit_thread()
+ // for description of why this is done.
+ if (wrapper->magic == TASK_IDENT)
+ {
+ xSemaphoreTake(wrapper->sema, portMAX_DELAY);
+ status = cy_rtos_terminate_thread(thread);
+ }
+ *thread = NULL;
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_get_thread_handle
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_get_thread_handle(cy_thread_t* thread)
+{
+ cy_rslt_t status = CY_RSLT_SUCCESS;
+
+ if (thread == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ *thread = xTaskGetCurrentTaskHandle();
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_wait_thread_notification
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_wait_thread_notification(cy_time_t num_ms)
+{
+ uint32_t ret;
+
+ ret = ulTaskNotifyTake(pdTRUE, (num_ms == CY_RTOS_NEVER_TIMEOUT) ?
+ portMAX_DELAY : pdMS_TO_TICKS(num_ms));
+ if (0 != ret)
+ {
+ /* Received notify from another thread or ISR */
+ return CY_RSLT_SUCCESS;
+ }
+ else
+ {
+ return CY_RTOS_TIMEOUT;
+ }
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_set_thread_notification
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_set_thread_notification(cy_thread_t* thread, bool in_isr)
+{
+ cy_rslt_t status;
+ if (thread == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ if (in_isr)
+ {
+ BaseType_t taskWoken = pdFALSE;
+ /* No error checking as this function always returns pdPASS. */
+ vTaskNotifyGiveFromISR(*thread, &taskWoken);
+ portEND_SWITCHING_ISR(taskWoken);
+ }
+ else
+ {
+ /* No error checking as this function always returns pdPASS. */
+ xTaskNotifyGive(*thread);
+ }
+ status = CY_RSLT_SUCCESS;
+ }
+ return status;
+}
+
+
+//==================================================================================================
+// Mutexes
+//==================================================================================================
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_init_mutex2
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_init_mutex2(cy_mutex_t* mutex, bool recursive)
+{
+ cy_rslt_t status;
+ if (mutex == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ mutex->is_recursive = recursive;
+ mutex->mutex_handle = recursive
+ ? xSemaphoreCreateRecursiveMutex()
+ : xSemaphoreCreateMutex();
+ if (mutex->mutex_handle == NULL)
+ {
+ status = CY_RTOS_NO_MEMORY;
+ }
+ else
+ {
+ status = CY_RSLT_SUCCESS;
+ }
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_get_mutex
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_get_mutex(cy_mutex_t* mutex, cy_time_t timeout_ms)
+{
+ cy_rslt_t status;
+ if (mutex == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ TickType_t ticks = pdMS_TO_TICKS(timeout_ms);
+ BaseType_t result = (mutex->is_recursive)
+ ? xSemaphoreTakeRecursive(mutex->mutex_handle, ticks)
+ : xSemaphoreTake(mutex->mutex_handle, ticks);
+
+ status = (result == pdFALSE)
+ ? CY_RTOS_TIMEOUT
+ : CY_RSLT_SUCCESS;
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_set_mutex
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_set_mutex(cy_mutex_t* mutex)
+{
+ cy_rslt_t status;
+ if (mutex == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ BaseType_t result = (mutex->is_recursive)
+ ? xSemaphoreGiveRecursive(mutex->mutex_handle)
+ : xSemaphoreGive(mutex->mutex_handle);
+
+ status = (result == pdFALSE)
+ ? CY_RTOS_GENERAL_ERROR
+ : CY_RSLT_SUCCESS;
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_deinit_mutex
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_deinit_mutex(cy_mutex_t* mutex)
+{
+ cy_rslt_t status;
+ if (mutex == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ vSemaphoreDelete(mutex->mutex_handle);
+ status = CY_RSLT_SUCCESS;
+ }
+ return status;
+}
+
+
+//==================================================================================================
+// Semaphores
+//==================================================================================================
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_init_semaphore
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_init_semaphore(cy_semaphore_t* semaphore, uint32_t maxcount, uint32_t initcount)
+{
+ cy_rslt_t status;
+ if (semaphore == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ *semaphore = xSemaphoreCreateCounting(maxcount, initcount);
+ if (*semaphore == NULL)
+ {
+ status = CY_RTOS_NO_MEMORY;
+ }
+ else
+ {
+ status = CY_RSLT_SUCCESS;
+ }
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_get_semaphore
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_get_semaphore(cy_semaphore_t* semaphore, uint32_t timeout_ms, bool in_isr)
+{
+ cy_rslt_t status;
+ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+ // xSemaphoreTakeFromISR does not take timeout as a parameter
+ // since it cannot block. Hence we return an error if the user
+ // tries to set a timeout.
+ if ((semaphore == NULL) || (in_isr && (timeout_ms != 0)))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ TickType_t ticks = pdMS_TO_TICKS(timeout_ms);
+ status = CY_RSLT_SUCCESS;
+
+ if (in_isr)
+ {
+ if (pdFALSE == xSemaphoreTakeFromISR(*semaphore, &xHigherPriorityTaskWoken))
+ {
+ status = CY_RTOS_TIMEOUT;
+ }
+ }
+ else
+ {
+ if (pdFALSE == xSemaphoreTake(*semaphore, ticks))
+ {
+ status = CY_RTOS_TIMEOUT;
+ }
+ }
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_set_semaphore
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_set_semaphore(cy_semaphore_t* semaphore, bool in_isr)
+{
+ cy_rslt_t status;
+ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+ if (semaphore == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ BaseType_t ret;
+
+ if (in_isr)
+ {
+ ret = xSemaphoreGiveFromISR(*semaphore, &xHigherPriorityTaskWoken);
+ #if configUSE_PREEMPTION == 1
+ portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+ #endif
+ }
+ else
+ {
+ ret = xSemaphoreGive(*semaphore);
+ }
+
+ if (ret == pdFALSE)
+ {
+ status = CY_RTOS_GENERAL_ERROR;
+ }
+ else
+ {
+ status = CY_RSLT_SUCCESS;
+ }
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_get_count_semaphore
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_get_count_semaphore(cy_semaphore_t* semaphore, size_t* count)
+{
+ cy_rslt_t status;
+ if (semaphore == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ *count = uxSemaphoreGetCount(*semaphore);
+ status = CY_RSLT_SUCCESS;
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_deinit_semaphore
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_deinit_semaphore(cy_semaphore_t* semaphore)
+{
+ cy_rslt_t status;
+ if (semaphore == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ vSemaphoreDelete(*semaphore);
+ status = CY_RSLT_SUCCESS;
+ }
+ return status;
+}
+
+
+//==================================================================================================
+// Events
+//==================================================================================================
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_init_event
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_init_event(cy_event_t* event)
+{
+ cy_rslt_t status;
+ if (event == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ *event = xEventGroupCreate();
+ if (*event == NULL)
+ {
+ status = CY_RTOS_NO_MEMORY;
+ }
+ else
+ {
+ status = CY_RSLT_SUCCESS;
+ }
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_setbits_event
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_setbits_event(cy_event_t* event, uint32_t bits, bool in_isr)
+{
+ cy_rslt_t status;
+ if (event == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ BaseType_t ret;
+ if (in_isr)
+ {
+ BaseType_t bt = pdFALSE;
+ ret = xEventGroupSetBitsFromISR(*event, bits, &bt);
+ }
+ else
+ {
+ ret = xEventGroupSetBits(*event, bits);
+ }
+
+ if (ret == pdFALSE)
+ {
+ status = CY_RTOS_GENERAL_ERROR;
+ }
+ else
+ {
+ status = CY_RSLT_SUCCESS;
+ }
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_clearbits_event
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_clearbits_event(cy_event_t* event, uint32_t bits, bool in_isr)
+{
+ cy_rslt_t status;
+ if (event == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ BaseType_t ret;
+ if (in_isr)
+ {
+ ret = xEventGroupClearBitsFromISR(*event, bits);
+ }
+ else
+ {
+ ret = xEventGroupClearBits(*event, bits);
+ }
+
+ if (ret == pdFALSE)
+ {
+ status = CY_RTOS_GENERAL_ERROR;
+ }
+ else
+ {
+ status = CY_RSLT_SUCCESS;
+ }
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_getbits_event
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_getbits_event(cy_event_t* event, uint32_t* bits)
+{
+ cy_rslt_t status;
+ if ((event == NULL) || (bits == NULL))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ *bits = xEventGroupGetBits(*event);
+ status = CY_RSLT_SUCCESS;
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_waitbits_event
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_waitbits_event(cy_event_t* event, uint32_t* waitfor, bool clear, bool allset,
+ cy_time_t timeout)
+{
+ cy_rslt_t status;
+ if ((event == NULL) || (waitfor == NULL))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ TickType_t ticks = pdMS_TO_TICKS(timeout);
+ uint32_t bits = *waitfor;
+
+ *waitfor = xEventGroupWaitBits(*event, bits, clear, allset, ticks);
+ status = (((bits & *waitfor) == bits) || (((bits & *waitfor) > 0) & !allset))
+ ? CY_RSLT_SUCCESS
+ : CY_RTOS_TIMEOUT;
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_deinit_event
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_deinit_event(cy_event_t* event)
+{
+ cy_rslt_t status;
+ if (event == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ vEventGroupDelete(*event);
+ status = CY_RSLT_SUCCESS;
+ }
+ return status;
+}
+
+
+//==================================================================================================
+// Queues
+//==================================================================================================
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_init_queue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_init_queue(cy_queue_t* queue, size_t length, size_t itemsize)
+{
+ cy_rslt_t status;
+ if (queue == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ *queue = xQueueCreate(length, itemsize);
+ if (*queue == NULL)
+ {
+ status = CY_RTOS_NO_MEMORY;
+ }
+ else
+ {
+ status = CY_RSLT_SUCCESS;
+ }
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_put_queue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_put_queue(cy_queue_t* queue, const void* item_ptr, cy_time_t timeoutms,
+ bool in_isr)
+{
+ cy_rslt_t status;
+ if ((queue == NULL) || (item_ptr == NULL))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ BaseType_t ret;
+ if (in_isr)
+ {
+ ret = xQueueSendToBackFromISR(*queue, item_ptr, NULL);
+ }
+ else
+ {
+ TickType_t ticks = pdMS_TO_TICKS(timeoutms);
+ ret = xQueueSendToBack(*queue, item_ptr, ticks);
+ }
+
+ if (ret == pdFALSE)
+ {
+ status = CY_RTOS_GENERAL_ERROR;
+ }
+ else
+ {
+ status = CY_RSLT_SUCCESS;
+ }
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_get_queue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_get_queue(cy_queue_t* queue, void* item_ptr, cy_time_t timeoutms, bool in_isr)
+{
+ cy_rslt_t status;
+ if ((queue == NULL) || (item_ptr == NULL))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ BaseType_t ret;
+ if (in_isr)
+ {
+ ret = xQueueReceiveFromISR(*queue, item_ptr, NULL);
+ }
+ else
+ {
+ TickType_t ticks = pdMS_TO_TICKS(timeoutms);
+ ret = xQueueReceive(*queue, item_ptr, ticks);
+ }
+
+ if (ret == pdFALSE)
+ {
+ status = CY_RTOS_GENERAL_ERROR;
+ }
+ else
+ {
+ status = CY_RSLT_SUCCESS;
+ }
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_count_queue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_count_queue(cy_queue_t* queue, size_t* num_waiting)
+{
+ cy_rslt_t status;
+ if ((queue == NULL) || (num_waiting == NULL))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ *num_waiting = is_in_isr()
+ ? uxQueueMessagesWaitingFromISR(*queue)
+ : uxQueueMessagesWaiting(*queue);
+ status = CY_RSLT_SUCCESS;
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_space_queue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_space_queue(cy_queue_t* queue, size_t* num_spaces)
+{
+ cy_rslt_t status;
+ if ((queue == NULL) || (num_spaces == NULL))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ *num_spaces = uxQueueSpacesAvailable(*queue);
+ status = CY_RSLT_SUCCESS;
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_reset_queue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_reset_queue(cy_queue_t* queue)
+{
+ cy_rslt_t status;
+ if (queue == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ BaseType_t ret = xQueueReset(*queue);
+
+ if (ret == pdFALSE)
+ {
+ status = CY_RTOS_GENERAL_ERROR;
+ }
+ else
+ {
+ status = CY_RSLT_SUCCESS;
+ }
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_deinit_queue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_deinit_queue(cy_queue_t* queue)
+{
+ cy_rslt_t status;
+ if (queue == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ vQueueDelete(*queue);
+ status = CY_RSLT_SUCCESS;
+ }
+ return status;
+}
+
+
+//==================================================================================================
+// Timers
+//==================================================================================================
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_init_timer
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t 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)
+{
+ cy_rslt_t status;
+ if ((timer == NULL) || (fun == NULL))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ BaseType_t reload = (type == CY_TIMER_TYPE_PERIODIC) ? pdTRUE : pdFALSE;
+
+ // Create a wrapper callback to make sure to call fun() with arg as opposed
+ // to providing the timer reference as FreeRTOS does by default.
+ callback_data_t* cb_arg = (callback_data_t*)malloc(sizeof(callback_data_t));
+ if (NULL == cb_arg)
+ {
+ status = CY_RTOS_NO_MEMORY;
+ }
+ else
+ {
+ cb_arg->cb = fun;
+ cb_arg->arg = arg;
+
+ *timer = xTimerCreate("", 1, reload, cb_arg, &timer_callback);
+
+ if (*timer == NULL)
+ {
+ free(cb_arg);
+ status = CY_RTOS_NO_MEMORY;
+ }
+ else
+ {
+ status = CY_RSLT_SUCCESS;
+ }
+ }
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_start_timer
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_start_timer(cy_timer_t* timer, cy_time_t num_ms)
+{
+ cy_rslt_t status;
+ if (timer == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ TickType_t ticks = pdMS_TO_TICKS(num_ms);
+ BaseType_t ret = xTimerChangePeriod(*timer, ticks, 0);
+
+ if (ret == pdPASS)
+ {
+ ret = xTimerStart(*timer, 0);
+ }
+
+ if (ret == pdFALSE)
+ {
+ status = CY_RTOS_GENERAL_ERROR;
+ }
+ else
+ {
+ status = CY_RSLT_SUCCESS;
+ }
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_stop_timer
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_stop_timer(cy_timer_t* timer)
+{
+ cy_rslt_t status;
+ if (timer == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ BaseType_t ret = xTimerStop(*timer, 0);
+
+ if (ret == pdFALSE)
+ {
+ status = CY_RTOS_GENERAL_ERROR;
+ }
+ else
+ {
+ status = CY_RSLT_SUCCESS;
+ }
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_is_running_timer
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_is_running_timer(cy_timer_t* timer, bool* state)
+{
+ cy_rslt_t status;
+ if ((timer == NULL) || (state == NULL))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ BaseType_t active = xTimerIsTimerActive(*timer);
+ *state = (active != pdFALSE);
+
+ status = CY_RSLT_SUCCESS;
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_deinit_timer
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_deinit_timer(cy_timer_t* timer)
+{
+ cy_rslt_t status;
+ if (timer == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ void* cb = pvTimerGetTimerID(*timer);
+ BaseType_t ret = xTimerDelete(*timer, 0);
+
+ if (ret == pdFALSE)
+ {
+ status = CY_RTOS_GENERAL_ERROR;
+ }
+ else
+ {
+ free(cb);
+ status = CY_RSLT_SUCCESS;
+ }
+ }
+ return status;
+}
+
+
+//==================================================================================================
+// Time
+//==================================================================================================
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_get_time
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_get_time(cy_time_t* tval)
+{
+ cy_rslt_t status;
+ if (tval == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ *tval = (cy_time_t)((xTaskGetTickCount() * 1000LL) / configTICK_RATE_HZ);
+ status = CY_RSLT_SUCCESS;
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_delay_milliseconds
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_delay_milliseconds(uint32_t num_ms)
+{
+ vTaskDelay(pdMS_TO_TICKS(num_ms));
+ return CY_RSLT_SUCCESS;
+}
diff --git a/abstraction-rtos/source/COMPONENT_RTX/cyabs_rtos_rtxv5.c b/abstraction-rtos/source/COMPONENT_RTX/cyabs_rtos_rtxv5.c
new file mode 100644
index 00000000..86edbda3
--- /dev/null
+++ b/abstraction-rtos/source/COMPONENT_RTX/cyabs_rtos_rtxv5.c
@@ -0,0 +1,1196 @@
+/***********************************************************************************************//**
+ * \file cyabs_rtos_rtxv5.c
+ *
+ * \brief
+ * Implementation for CMSIS RTOS v2 abstraction
+ *
+ ***************************************************************************************************
+ * \copyright
+ * Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or
+ * an affiliate of Cypress Semiconductor Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **************************************************************************************************/
+
+#include
+#include
+#include
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define CY_RTOS_THREAD_FLAG 0x01
+
+/******************************************************
+* Error Converter
+******************************************************/
+
+// Last received error status
+static cy_rtos_error_t dbgErr;
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_last_error
+//--------------------------------------------------------------------------------------------------
+cy_rtos_error_t cy_rtos_last_error(void)
+{
+ return dbgErr;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// error_converter
+//
+// Converts internal error type to external error type
+//--------------------------------------------------------------------------------------------------
+static cy_rslt_t error_converter(cy_rtos_error_t internalError)
+{
+ cy_rslt_t value;
+
+ switch (internalError)
+ {
+ case osOK:
+ value = CY_RSLT_SUCCESS;
+ break;
+
+ case osErrorTimeout:
+ value = CY_RTOS_TIMEOUT;
+ break;
+
+ case osErrorParameter:
+ value = CY_RTOS_BAD_PARAM;
+ break;
+
+ case osErrorNoMemory:
+ value = CY_RTOS_NO_MEMORY;
+ break;
+
+ case osError:
+ case osErrorResource:
+ case osErrorISR:
+ default:
+ value = CY_RTOS_GENERAL_ERROR;
+ break;
+ }
+
+ // Update the last known error status
+ dbgErr = internalError;
+ return value;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// convert_ms_to_ticks
+//--------------------------------------------------------------------------------------------------
+static uint32_t convert_ms_to_ticks(cy_time_t timeout_ms)
+{
+ if (timeout_ms == CY_RTOS_NEVER_TIMEOUT)
+ {
+ return osWaitForever;
+ }
+ else if (timeout_ms == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ // Get number of ticks per second
+ uint32_t tick_freq = osKernelGetTickFreq();
+ uint32_t ticks = (uint32_t)(((uint64_t)timeout_ms * tick_freq) / 1000);
+
+ if (ticks == 0)
+ {
+ ticks = 1;
+ }
+ else if (ticks >= UINT32_MAX)
+ {
+ // if ticks if more than 32 bits, change ticks to max possible value that isn't
+ // osWaitForever.
+ ticks = UINT32_MAX - 1;
+ }
+ return ticks;
+ }
+}
+
+
+/******************************************************
+* Threads
+******************************************************/
+
+cy_rslt_t 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)
+{
+ cy_rslt_t status = CY_RSLT_SUCCESS;
+ osThreadAttr_t attr;
+
+ if ((thread == NULL) || (stack_size < CY_RTOS_MIN_STACK_SIZE))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else if ((stack != NULL) && (0 != (((uint32_t)stack) & CY_RTOS_ALIGNMENT_MASK)))
+ {
+ status = CY_RTOS_ALIGNMENT_ERROR;
+ }
+ else
+ {
+ attr.name = name;
+ attr.attr_bits = osThreadJoinable;
+ attr.cb_size = osRtxThreadCbSize;
+ attr.stack_size = stack_size;
+ attr.priority = (osPriority_t)priority;
+ attr.tz_module = 0;
+ attr.reserved = 0;
+
+ // Allocate stack if NULL was passed
+ if ((uint32_t*)stack == NULL)
+ {
+ // Note: 1 malloc so that it can be freed with 1 call when terminating
+ uint32_t cb_mem_pad = (~osRtxThreadCbSize + 1) & CY_RTOS_ALIGNMENT_MASK;
+ attr.cb_mem = malloc(osRtxThreadCbSize + cb_mem_pad + stack_size);
+ if (attr.cb_mem != NULL)
+ {
+ attr.stack_mem =
+ (uint32_t*)((uint32_t)attr.cb_mem + osRtxThreadCbSize + cb_mem_pad);
+ }
+ }
+ else
+ {
+ attr.cb_mem = malloc(osRtxThreadCbSize);
+ attr.stack_mem = stack;
+ }
+
+ if (attr.cb_mem == NULL)
+ {
+ status = CY_RTOS_NO_MEMORY;
+ }
+ else
+ {
+ CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL);
+ CY_ASSERT(((uint32_t)attr.stack_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL);
+ *thread = osThreadNew((osThreadFunc_t)entry_function, arg, &attr);
+ CY_ASSERT((*thread == attr.cb_mem) || (*thread == NULL));
+ status = (*thread == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS;
+ }
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_exit_thread
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_exit_thread(void)
+{
+ // This does not have a return statement because the osThreadExit() function * does not return
+ // so the return statement would be unreachable and causes a * warning for IAR compiler.
+ osThreadExit();
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_terminate_thread
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_terminate_thread(cy_thread_t* thread)
+{
+ cy_rslt_t status;
+ cy_rtos_error_t statusInternal;
+
+ if (thread == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ statusInternal = osThreadTerminate(*thread);
+ status = error_converter(statusInternal);
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_is_thread_running
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_is_thread_running(cy_thread_t* thread, bool* running)
+{
+ cy_rslt_t status = CY_RSLT_SUCCESS;
+
+ if ((thread == NULL) || (running == NULL))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ *running = (osThreadGetState(*thread) == osThreadRunning) ? true : false;
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_get_thread_state
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_get_thread_state(cy_thread_t* thread, cy_thread_state_t* state)
+{
+ cy_rslt_t status = CY_RSLT_SUCCESS;
+
+ if ((thread == NULL) || (state == NULL))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ switch (osThreadGetState(*thread))
+ {
+ case osThreadInactive:
+ *state = CY_THREAD_STATE_INACTIVE;
+ break;
+
+ case osThreadReady:
+ *state = CY_THREAD_STATE_READY;
+ break;
+
+ case osThreadRunning:
+ *state = CY_THREAD_STATE_RUNNING;
+ break;
+
+ case osThreadBlocked:
+ *state = CY_THREAD_STATE_BLOCKED;
+ break;
+
+ case osThreadTerminated:
+ *state = CY_THREAD_STATE_TERMINATED;
+ break;
+
+ case osThreadError:
+ case osThreadReserved:
+ default:
+ *state = CY_THREAD_STATE_UNKNOWN;
+ break;
+ }
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_join_thread
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_join_thread(cy_thread_t* thread)
+{
+ cy_rslt_t status;
+ cy_rtos_error_t statusInternal;
+
+ if (thread == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ statusInternal = osThreadJoin(*thread);
+ status = error_converter(statusInternal);
+
+ if (status == CY_RSLT_SUCCESS)
+ {
+ free(*thread);
+ *thread = NULL;
+ }
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_get_thread_handle
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_get_thread_handle(cy_thread_t* thread)
+{
+ cy_rslt_t status = CY_RSLT_SUCCESS;
+
+ if (thread == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ *thread = osThreadGetId();
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_wait_thread_notification
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_wait_thread_notification(cy_time_t timeout_ms)
+{
+ uint32_t ret;
+ cy_rslt_t status = CY_RSLT_SUCCESS;
+ ret = osThreadFlagsWait(CY_RTOS_THREAD_FLAG, osFlagsWaitAll, convert_ms_to_ticks(timeout_ms));
+ if (ret & osFlagsError)
+ {
+ status = (ret == osFlagsErrorTimeout) ? CY_RTOS_TIMEOUT : CY_RTOS_GENERAL_ERROR;
+ // Update the last known error status
+ dbgErr = (cy_rtos_error_t)ret;
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_set_thread_notification
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_set_thread_notification(cy_thread_t* thread, bool in_isr)
+{
+ cy_rslt_t status = CY_RSLT_SUCCESS;
+ uint32_t ret;
+
+ (void)in_isr;
+ if (thread == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ /* According to the description of CMSIS-RTOS v2
+ * osThreadFlagsSet() can be called inside ISR
+ */
+ ret = osThreadFlagsSet(*thread, CY_RTOS_THREAD_FLAG);
+ if (ret & osFlagsError)
+ {
+ status = CY_RTOS_GENERAL_ERROR;
+ // Update the last known error status
+ dbgErr = (cy_rtos_error_t)ret;
+ }
+ }
+ return status;
+}
+
+
+/******************************************************
+* Mutexes
+******************************************************/
+
+cy_rslt_t cy_rtos_init_mutex2(cy_mutex_t* mutex, bool recursive)
+{
+ cy_rslt_t status;
+ osMutexAttr_t attr;
+
+ if (mutex == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ attr.name = NULL;
+ attr.attr_bits = osMutexPrioInherit;
+ if (recursive)
+ {
+ attr.attr_bits |= osMutexRecursive;
+ }
+ attr.cb_mem = malloc(osRtxMutexCbSize);
+ attr.cb_size = osRtxMutexCbSize;
+
+ if (attr.cb_mem == NULL)
+ {
+ status = CY_RTOS_NO_MEMORY;
+ }
+ else
+ {
+ CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL);
+ *mutex = osMutexNew(&attr);
+ CY_ASSERT((*mutex == attr.cb_mem) || (*mutex == NULL));
+ status = (*mutex == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS;
+ }
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_get_mutex
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_get_mutex(cy_mutex_t* mutex, cy_time_t timeout_ms)
+{
+ cy_rslt_t status;
+ cy_rtos_error_t statusInternal;
+
+ if (mutex == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ statusInternal = osMutexAcquire(*mutex, timeout_ms);
+ status = error_converter(statusInternal);
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_set_mutex
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_set_mutex(cy_mutex_t* mutex)
+{
+ cy_rslt_t status;
+ cy_rtos_error_t statusInternal;
+
+ if (mutex == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ statusInternal = osMutexRelease(*mutex);
+ status = error_converter(statusInternal);
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_deinit_mutex
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_deinit_mutex(cy_mutex_t* mutex)
+{
+ cy_rslt_t status;
+ cy_rtos_error_t statusInternal;
+
+ if (mutex == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ statusInternal = osMutexDelete(*mutex);
+ status = error_converter(statusInternal);
+
+ if (status == CY_RSLT_SUCCESS)
+ {
+ free(*mutex);
+ *mutex = NULL;
+ }
+ }
+
+ return status;
+}
+
+
+/******************************************************
+* Semaphores
+******************************************************/
+
+cy_rslt_t cy_rtos_init_semaphore(cy_semaphore_t* semaphore, uint32_t maxcount, uint32_t initcount)
+{
+ cy_rslt_t status;
+ osSemaphoreAttr_t attr;
+
+ if (semaphore == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ attr.name = NULL;
+ attr.attr_bits = 0U;
+ attr.cb_mem = malloc(osRtxSemaphoreCbSize);
+ attr.cb_size = osRtxSemaphoreCbSize;
+
+ if (attr.cb_mem == NULL)
+ {
+ status = CY_RTOS_NO_MEMORY;
+ }
+ else
+ {
+ CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL);
+ *semaphore = osSemaphoreNew(maxcount, initcount, &attr);
+ CY_ASSERT((*semaphore == attr.cb_mem) || (*semaphore == NULL));
+ status = (*semaphore == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS;
+ }
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_get_semaphore
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_get_semaphore(cy_semaphore_t* semaphore, cy_time_t timeout_ms, bool in_isr)
+{
+ cy_rslt_t status = CY_RSLT_SUCCESS;
+ cy_rtos_error_t statusInternal;
+
+ // Based on documentation when osSemaphoreAcquire is called from ISR timeout must be zero.
+ // https://www.keil.com/pack/doc/CMSIS/RTOS2/html/group__CMSIS__RTOS__SemaphoreMgmt.html#ga7e94c8b242a0c81f2cc79ec22895c87b
+ if ((semaphore == NULL) || (in_isr && (timeout_ms != 0)))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ statusInternal = osSemaphoreAcquire(*semaphore, timeout_ms);
+ status = error_converter(statusInternal);
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_set_semaphore
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_set_semaphore(cy_semaphore_t* semaphore, bool in_isr)
+{
+ cy_rslt_t status = CY_RSLT_SUCCESS;
+ cy_rtos_error_t statusInternal;
+ (void)in_isr; // Unused parameter in this implementation
+
+ if (semaphore == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ statusInternal = osSemaphoreRelease(*semaphore);
+ status = error_converter(statusInternal);
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_get_count_semaphore
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_get_count_semaphore(cy_semaphore_t* semaphore, size_t* count)
+{
+ cy_rslt_t status;
+ if ((semaphore == NULL) || (count == NULL))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ *count = osSemaphoreGetCount(*semaphore);
+ status = CY_RSLT_SUCCESS;
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_deinit_semaphore
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_deinit_semaphore(cy_semaphore_t* semaphore)
+{
+ cy_rslt_t status;
+ cy_rtos_error_t statusInternal;
+
+ if (semaphore == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ statusInternal = osSemaphoreDelete(*semaphore);
+ status = error_converter(statusInternal);
+ if (status == CY_RSLT_SUCCESS)
+ {
+ free(*semaphore);
+ *semaphore = NULL;
+ }
+ }
+
+ return status;
+}
+
+
+/******************************************************
+* Events
+******************************************************/
+
+#define CY_RTOS_EVENT_ERRORFLAG 0x80000000UL
+#define CY_RTOS_EVENT_FLAGS 0x7FFFFFFFUL
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_init_event
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_init_event(cy_event_t* event)
+{
+ cy_rslt_t status;
+ osEventFlagsAttr_t attr;
+
+ if (event == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ attr.name = NULL;
+ attr.attr_bits = 0U;
+ attr.cb_mem = malloc(osRtxEventFlagsCbSize);
+ attr.cb_size = osRtxEventFlagsCbSize;
+
+ if (attr.cb_mem == NULL)
+ {
+ status = CY_RTOS_NO_MEMORY;
+ }
+ else
+ {
+ CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL);
+ *event = osEventFlagsNew(&attr);
+ CY_ASSERT((*event == attr.cb_mem) || (*event == NULL));
+ status = (*event == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS;
+ }
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_setbits_event
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_setbits_event(cy_event_t* event, uint32_t bits, bool in_isr)
+{
+ cy_rslt_t status = CY_RSLT_SUCCESS;
+ cy_rtos_error_t statusInternal;
+ (void)in_isr; // Unused parameter in this implementation
+
+ if (event == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ statusInternal = (osStatus_t)osEventFlagsSet(*event, bits);
+ if ((statusInternal & CY_RTOS_EVENT_ERRORFLAG) != 0UL)
+ {
+ status = error_converter(statusInternal);
+ }
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_clearbits_event
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_clearbits_event(cy_event_t* event, uint32_t bits, bool in_isr)
+{
+ cy_rslt_t status = CY_RSLT_SUCCESS;
+ cy_rtos_error_t statusInternal;
+ (void)in_isr; // Unused parameter in this implementation
+
+ if (event == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ statusInternal = (osStatus_t)osEventFlagsClear(*event, bits);
+ if ((statusInternal & CY_RTOS_EVENT_ERRORFLAG) != 0UL)
+ {
+ status = error_converter(statusInternal);
+ }
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_getbits_event
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_getbits_event(cy_event_t* event, uint32_t* bits)
+{
+ cy_rslt_t status = CY_RSLT_SUCCESS;
+
+ if ((event == NULL) || (bits == NULL))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ *bits = osEventFlagsGet(*event);
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_waitbits_event
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_waitbits_event(cy_event_t* event, uint32_t* bits, bool clear, bool all,
+ cy_time_t timeout)
+{
+ cy_rslt_t status = CY_RSLT_SUCCESS;
+ cy_rtos_error_t statusInternal;
+ uint32_t flagOption;
+
+ if ((event == NULL) || (bits == NULL))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ flagOption = (all) ? osFlagsWaitAll : osFlagsWaitAny;
+ if (!clear)
+ {
+ flagOption |= osFlagsNoClear;
+ }
+
+ statusInternal = (osStatus_t)osEventFlagsWait(*event, *bits, flagOption, timeout);
+ if ((statusInternal & CY_RTOS_EVENT_ERRORFLAG) == 0UL)
+ {
+ *bits = statusInternal;
+ }
+ else
+ {
+ status = error_converter(statusInternal);
+ }
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_deinit_event
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_deinit_event(cy_event_t* event)
+{
+ cy_rslt_t status;
+ cy_rtos_error_t statusInternal;
+
+ if (event == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ statusInternal = osEventFlagsDelete(*event);
+ status = error_converter(statusInternal);
+ if (status == CY_RSLT_SUCCESS)
+ {
+ free(*event);
+ *event = NULL;
+ }
+ }
+
+ return status;
+}
+
+
+/******************************************************
+* Queues
+******************************************************/
+
+cy_rslt_t cy_rtos_init_queue(cy_queue_t* queue, size_t length, size_t itemsize)
+{
+ cy_rslt_t status;
+ osMessageQueueAttr_t attr;
+
+ if (queue == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ attr.name = NULL;
+ attr.attr_bits = 0U;
+ attr.cb_size = osRtxMessageQueueCbSize;
+ uint32_t blockSize = ((itemsize + 3U) & ~3UL) + sizeof(osRtxMessage_t);
+ attr.mq_size = blockSize * length;
+
+ // Note: 1 malloc for both so that they can be freed with 1 call
+ uint32_t cb_mem_pad = (8 - (osRtxMessageQueueCbSize & 0x07)) & 0x07;
+ attr.cb_mem = malloc(osRtxMessageQueueCbSize + cb_mem_pad + attr.mq_size);
+ if (attr.cb_mem != NULL)
+ {
+ attr.mq_mem = (uint32_t*)((uint32_t)attr.cb_mem + osRtxMessageQueueCbSize + cb_mem_pad);
+ }
+
+ if (attr.cb_mem == NULL)
+ {
+ status = CY_RTOS_NO_MEMORY;
+ }
+ else
+ {
+ CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL);
+ CY_ASSERT(((uint32_t)attr.mq_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL);
+ *queue = osMessageQueueNew(length, itemsize, &attr);
+ CY_ASSERT((*queue == attr.cb_mem) || (*queue == NULL));
+ status = (*queue == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS;
+ }
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_put_queue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_put_queue(cy_queue_t* queue, const void* item_ptr, cy_time_t timeout_ms,
+ bool in_isr)
+{
+ cy_rslt_t status;
+ cy_rtos_error_t statusInternal;
+
+ if ((queue == NULL) || (item_ptr == NULL))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ // Not allowed to be called in ISR if timeout != 0
+ if ((!in_isr) || (in_isr && (timeout_ms == 0U)))
+ {
+ statusInternal = osMessageQueuePut(*queue, (uint8_t*)item_ptr, 0u, timeout_ms);
+ }
+ else
+ {
+ statusInternal = osErrorISR;
+ }
+
+ status = error_converter(statusInternal);
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_get_queue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_get_queue(cy_queue_t* queue, void* item_ptr, cy_time_t timeout_ms, bool in_isr)
+{
+ cy_rslt_t status;
+ cy_rtos_error_t statusInternal;
+
+ if ((queue == NULL) || (item_ptr == NULL))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ // Not allowed to be called in ISR if timeout != 0
+ if ((!in_isr) || (in_isr && (timeout_ms == 0U)))
+ {
+ statusInternal = osMessageQueueGet(*queue, (uint8_t*)item_ptr, 0u, timeout_ms);
+ }
+ else
+ {
+ statusInternal = osErrorISR;
+ }
+
+ status = error_converter(statusInternal);
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_count_queue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_count_queue(cy_queue_t* queue, size_t* num_waiting)
+{
+ cy_rslt_t status = CY_RSLT_SUCCESS;
+
+ if ((queue == NULL) || (num_waiting == NULL))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ *num_waiting = osMessageQueueGetCount(*queue);
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_space_queue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_space_queue(cy_queue_t* queue, size_t* num_spaces)
+{
+ cy_rslt_t status = CY_RSLT_SUCCESS;
+
+ if ((queue == NULL) || (num_spaces == NULL))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ *num_spaces = osMessageQueueGetSpace(*queue);
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_reset_queue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_reset_queue(cy_queue_t* queue)
+{
+ cy_rslt_t status;
+ cy_rtos_error_t statusInternal;
+
+ if (queue == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ statusInternal = osMessageQueueReset(*queue);
+ status = error_converter(statusInternal);
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_deinit_queue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_deinit_queue(cy_queue_t* queue)
+{
+ cy_rslt_t status;
+ cy_rtos_error_t statusInternal;
+
+ if (queue == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ statusInternal = osMessageQueueDelete(*queue);
+ status = error_converter(statusInternal);
+
+ if (status == CY_RSLT_SUCCESS)
+ {
+ free(*queue);
+ *queue = NULL;
+ }
+ }
+
+ return status;
+}
+
+
+/******************************************************
+* Timers
+******************************************************/
+
+cy_rslt_t 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)
+{
+ cy_rslt_t status;
+ osTimerAttr_t attr;
+
+ if (timer == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ attr.name = NULL;
+ attr.attr_bits = 0U;
+ attr.cb_mem = malloc(osRtxTimerCbSize);
+ attr.cb_size = osRtxTimerCbSize;
+
+ if (attr.cb_mem == NULL)
+ {
+ status = CY_RTOS_NO_MEMORY;
+ }
+ else
+ {
+ osTimerType_t osTriggerType = (CY_TIMER_TYPE_PERIODIC == type)
+ ? osTimerPeriodic
+ : osTimerOnce;
+
+ CY_ASSERT(((uint32_t)attr.cb_mem & CY_RTOS_ALIGNMENT_MASK) == 0UL);
+ *timer = osTimerNew((osTimerFunc_t)fun, osTriggerType, (void*)arg, &attr);
+ CY_ASSERT((*timer == attr.cb_mem) || (*timer == NULL));
+ status = (*timer == NULL) ? CY_RTOS_GENERAL_ERROR : CY_RSLT_SUCCESS;
+ }
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_start_timer
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_start_timer(cy_timer_t* timer, cy_time_t num_ms)
+{
+ cy_rslt_t status;
+ cy_rtos_error_t statusInternal;
+
+ if (timer == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ statusInternal = osTimerStart(*timer, convert_ms_to_ticks(num_ms));
+ status = error_converter(statusInternal);
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_stop_timer
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_stop_timer(cy_timer_t* timer)
+{
+ cy_rslt_t status;
+ cy_rtos_error_t statusInternal;
+
+ if (timer == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ statusInternal = osTimerStop(*timer);
+ status = error_converter(statusInternal);
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_is_running_timer
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_is_running_timer(cy_timer_t* timer, bool* state)
+{
+ cy_rslt_t status = CY_RSLT_SUCCESS;
+
+ if ((timer == NULL) || (state == NULL))
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ *state = osTimerIsRunning(*timer);
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_deinit_timer
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_deinit_timer(cy_timer_t* timer)
+{
+ cy_rslt_t status;
+ cy_rtos_error_t statusInternal;
+
+ if (timer == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ statusInternal = osTimerDelete(*timer);
+ status = error_converter(statusInternal);
+
+ if (status == CY_RSLT_SUCCESS)
+ {
+ free(*timer);
+ *timer = NULL;
+ }
+ }
+
+ return status;
+}
+
+
+/******************************************************
+* Time
+******************************************************/
+
+cy_rslt_t cy_rtos_get_time(cy_time_t* tval)
+{
+ cy_rslt_t status = CY_RSLT_SUCCESS;
+ uint32_t tick_freq;
+
+ if (tval == NULL)
+ {
+ status = CY_RTOS_BAD_PARAM;
+ }
+ else
+ {
+ // Get Number of ticks per second
+ tick_freq = osKernelGetTickFreq();
+
+ // Convert ticks count to time in milliseconds
+ if (tick_freq != 0)
+ {
+ *tval = (cy_time_t)((osKernelGetTickCount() * 1000LL) / tick_freq);
+ }
+ else
+ {
+ status = CY_RTOS_GENERAL_ERROR;
+ }
+ }
+
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_delay_milliseconds
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_delay_milliseconds(cy_time_t num_ms)
+{
+ cy_rslt_t status;
+ cy_rtos_error_t statusInternal;
+
+ statusInternal = osDelay(num_ms);
+ status = error_converter(statusInternal);
+
+ return status;
+}
+
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/abstraction-rtos/source/COMPONENT_THREADX/cyabs_rtos_threadx.c b/abstraction-rtos/source/COMPONENT_THREADX/cyabs_rtos_threadx.c
new file mode 100644
index 00000000..001e9b67
--- /dev/null
+++ b/abstraction-rtos/source/COMPONENT_THREADX/cyabs_rtos_threadx.c
@@ -0,0 +1,967 @@
+/***********************************************************************************************//**
+ * \file cyabs_rtos_threadx.c
+ *
+ * \brief
+ * Implementation for ThreadX abstraction
+ *
+ ***************************************************************************************************
+ * \copyright
+ * Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or
+ * an affiliate of Cypress Semiconductor Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **************************************************************************************************/
+
+#include
+#include
+#include
+#include
+#include
+
+static const uint32_t WRAPPER_IDENT = 0xABCDEF01U;
+static const uint32_t MAX_QUEUE_MESSAGE_SIZE = 16;
+#define ALL_EVENT_FLAGS (0xFFFFFFFFU)
+#define MILLISECONDS_PER_SECOND (1000)
+
+static cy_rtos_error_t last_error;
+
+
+//--------------------------------------------------------------------------------------------------
+// convert_ms_to_ticks
+//--------------------------------------------------------------------------------------------------
+static cy_time_t convert_ms_to_ticks(cy_time_t timeout_ms)
+{
+ if (timeout_ms == CY_RTOS_NEVER_TIMEOUT)
+ {
+ return TX_WAIT_FOREVER;
+ }
+ else if (timeout_ms == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ uint64_t ticks = (uint64_t)timeout_ms * (uint64_t)TX_TIMER_TICKS_PER_SECOND /
+ (uint64_t)MILLISECONDS_PER_SECOND;
+ if (ticks == 0)
+ {
+ ticks = 1;
+ }
+ else if (ticks >= UINT32_MAX)
+ {
+ // if ticks if more than 32 bits, change ticks to max possible value that isn't
+ // TX_WAIT_FOREVER.
+ ticks = UINT32_MAX - 1;
+ }
+ return (cy_time_t)ticks;
+ }
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// convert_ticks_to_ms
+//--------------------------------------------------------------------------------------------------
+static inline cy_time_t convert_ticks_to_ms(cy_time_t timeout_ticks)
+{
+ return (cy_time_t)((uint64_t)timeout_ticks * (uint64_t)MILLISECONDS_PER_SECOND /
+ (uint64_t)TX_TIMER_TICKS_PER_SECOND);
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// convert_error
+//--------------------------------------------------------------------------------------------------
+static inline cy_rslt_t convert_error(cy_rtos_error_t error)
+{
+ if (error != TX_SUCCESS)
+ {
+ last_error = error;
+ return CY_RTOS_GENERAL_ERROR;
+ }
+ return CY_RSLT_SUCCESS;
+}
+
+
+/******************************************************
+* Last Error
+******************************************************/
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_last_error
+//--------------------------------------------------------------------------------------------------
+cy_rtos_error_t cy_rtos_last_error(void)
+{
+ return last_error;
+}
+
+
+/******************************************************
+* Threads
+******************************************************/
+
+typedef struct
+{
+ TX_THREAD thread;
+ uint32_t magic;
+ void* memptr;
+} cy_thread_wrapper_t;
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_create_thread
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t 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)
+{
+ stack_size &= ~CY_RTOS_ALIGNMENT_MASK; // make stack pointer 8-byte aligned
+ if ((thread == NULL) || (stack_size < CY_RTOS_MIN_STACK_SIZE))
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ if ((stack != NULL) && (0 != (((uint32_t)stack) & CY_RTOS_ALIGNMENT_MASK)))
+ {
+ return CY_RTOS_ALIGNMENT_ERROR;
+ }
+
+ size_t malloc_size = sizeof(cy_thread_wrapper_t);
+ if (stack == NULL)
+ {
+ malloc_size += stack_size;
+ }
+ void* buffer = malloc(malloc_size);
+ if (buffer == NULL)
+ {
+ return CY_RTOS_NO_MEMORY;
+ }
+
+ cy_thread_wrapper_t* wrapper_ptr;
+ if (stack == NULL)
+ {
+ stack = buffer;
+ // Have stack be in front of wrapper since stack size is 8-byte aligned.
+ wrapper_ptr = (cy_thread_wrapper_t*)(buffer + stack_size);
+ wrapper_ptr->memptr = stack;
+ }
+ else
+ {
+ wrapper_ptr = buffer;
+ wrapper_ptr->memptr = NULL;
+ }
+ wrapper_ptr->magic = WRAPPER_IDENT;
+
+ *thread = (cy_thread_t)wrapper_ptr;
+
+ // Disable preemption-thresholding and time slicing
+ cy_rtos_error_t tx_rslt = tx_thread_create(*thread, (CHAR*)name, entry_function, arg, stack,
+ stack_size, priority, priority, TX_NO_TIME_SLICE,
+ TX_AUTO_START);
+
+ if (TX_SUCCESS != tx_rslt)
+ {
+ last_error = tx_rslt;
+ free(buffer);
+ return CY_RTOS_GENERAL_ERROR;
+ }
+
+ return CY_RSLT_SUCCESS;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_exit_thread
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_exit_thread(void)
+{
+ // No need to do anything before thread exit
+ return CY_RSLT_SUCCESS;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_terminate_thread
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_terminate_thread(cy_thread_t* thread)
+{
+ if (thread == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ return convert_error(tx_thread_terminate(*thread));
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_is_thread_running
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_is_thread_running(cy_thread_t* thread, bool* running)
+{
+ if ((thread == NULL) || (running == NULL))
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ // Only true when the given thread is the current one
+ *running = (*thread == tx_thread_identify());
+ return CY_RSLT_SUCCESS;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_get_thread_state
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_get_thread_state(cy_thread_t* thread, cy_thread_state_t* state)
+{
+ if ((thread == NULL) || (state == NULL))
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ bool running;
+ cy_rslt_t rslt = cy_rtos_is_thread_running(thread, &running);
+ if (CY_RSLT_SUCCESS != rslt)
+ {
+ return rslt;
+ }
+ else if (running)
+ {
+ *state = CY_THREAD_STATE_RUNNING;
+ return CY_RSLT_SUCCESS;
+ }
+
+ UINT thread_state;
+ cy_rtos_error_t tx_rslt = tx_thread_info_get(*thread, TX_NULL, &thread_state, TX_NULL, TX_NULL,
+ TX_NULL, TX_NULL, TX_NULL, TX_NULL);
+ if (TX_SUCCESS != tx_rslt)
+ {
+ last_error = tx_rslt;
+ return CY_RTOS_GENERAL_ERROR;
+ }
+
+ // Descriptions of these states are not given in the ThreadX user guide - these are best guesses
+ // as to their meanings
+ switch (thread_state)
+ {
+ case TX_READY:
+ *state = CY_THREAD_STATE_READY;
+ break;
+
+ case TX_COMPLETED:
+ case TX_TERMINATED:
+ *state = CY_THREAD_STATE_TERMINATED;
+ break;
+
+ case TX_SUSPENDED:
+ case TX_SLEEP:
+ case TX_QUEUE_SUSP:
+ case TX_SEMAPHORE_SUSP:
+ case TX_MUTEX_SUSP:
+ case TX_EVENT_FLAG: // Likely waiting for event flags to be set (tx_event_flags_get)
+ case TX_BLOCK_MEMORY: // Likely waiting to allocate a memory block (tx_block_allocate)
+ case TX_BYTE_MEMORY: // Likely waiting to allocate a byte pool (tx_byte_allocate)
+ *state = CY_THREAD_STATE_BLOCKED;
+ break;
+
+ default:
+ *state = CY_THREAD_STATE_UNKNOWN;
+ break;
+ }
+
+ return CY_RSLT_SUCCESS;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_join_thread
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_join_thread(cy_thread_t* thread)
+{
+ if (thread == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ // ThreadX doesn't have a join method itself, so just repeatedly check the thread's state until
+ // it completes or is terminated.
+ // Check if the thread we are joining has a higher priority, if it does, we need to lower our
+ // priority to that of the other thread.
+ UINT thread_state;
+
+ cy_rtos_error_t tx_rslt = tx_thread_info_get(*thread, TX_NULL, &thread_state, TX_NULL, TX_NULL,
+ TX_NULL, TX_NULL, TX_NULL, TX_NULL);
+ if (TX_SUCCESS != tx_rslt)
+ {
+ last_error = tx_rslt;
+ return CY_RTOS_GENERAL_ERROR;
+ }
+
+ while (TX_TERMINATED != thread_state && TX_COMPLETED != thread_state)
+ {
+ tx_rslt = tx_thread_sleep(1);
+ if (TX_SUCCESS != tx_rslt)
+ {
+ last_error = tx_rslt;
+ return CY_RTOS_GENERAL_ERROR;
+ }
+
+ tx_rslt = tx_thread_info_get(*thread, TX_NULL, &thread_state, TX_NULL, TX_NULL, TX_NULL,
+ TX_NULL, TX_NULL, TX_NULL);
+ if (TX_SUCCESS != tx_rslt)
+ {
+ last_error = tx_rslt;
+ return CY_RTOS_GENERAL_ERROR;
+ }
+ }
+
+ tx_rslt = tx_thread_delete(*thread);
+ if (TX_SUCCESS != tx_rslt)
+ {
+ last_error = tx_rslt;
+ return CY_RTOS_GENERAL_ERROR;
+ }
+
+ cy_thread_wrapper_t* wrapper_ptr = (cy_thread_wrapper_t*)(*thread);
+ if (wrapper_ptr->magic == WRAPPER_IDENT)
+ {
+ if (wrapper_ptr->memptr != NULL)
+ {
+ free(wrapper_ptr->memptr);
+ }
+ else
+ {
+ free(wrapper_ptr);
+ }
+ }
+ return CY_RSLT_SUCCESS;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_get_thread_handle
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_get_thread_handle(cy_thread_t* thread)
+{
+ if (thread == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ *thread = tx_thread_identify();
+ return CY_RSLT_SUCCESS;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_wait_thread_notification
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_wait_thread_notification(cy_time_t timeout_ms)
+{
+ UINT ret;
+ cy_rslt_t status = CY_RSLT_SUCCESS;
+
+ ret = tx_thread_sleep(convert_ms_to_ticks(timeout_ms));
+ /* Update the last known error status */
+ last_error = (cy_rtos_error_t)ret;
+
+ if (ret == TX_SUCCESS)
+ {
+ status = CY_RTOS_TIMEOUT;
+ }
+ else if (ret != TX_WAIT_ABORTED)
+ {
+ status = CY_RTOS_GENERAL_ERROR;
+ }
+ return status;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_set_thread_notification
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_set_thread_notification(cy_thread_t* thread, bool in_isr)
+{
+ (void)in_isr;
+
+ if (thread == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+ /* According to ThreadX user guide, this function allowed to
+ * be called from ISR
+ */
+ return convert_error(tx_thread_wait_abort(*thread));
+}
+
+
+/******************************************************
+* Mutexes
+******************************************************/
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_init_mutex2
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_init_mutex2(cy_mutex_t* mutex, bool recursive)
+{
+ if (mutex == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ // Non recursive mutex is not supported by ThreadX. A recursive mutex is returned
+ // even if a non-recursive mutex was requested. This is ok because in all the cases
+ // where the behavior of the two types differs would have ended in a deadlock. So
+ // the difference in behavior should not have a functional impact on application.
+ CY_UNUSED_PARAMETER(recursive);
+ return convert_error(tx_mutex_create(mutex, TX_NULL, TX_INHERIT));
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_get_mutex
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_get_mutex(cy_mutex_t* mutex, cy_time_t timeout_ms)
+{
+ if (mutex == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ cy_rtos_error_t tx_rslt = tx_mutex_get(mutex, convert_ms_to_ticks(timeout_ms));
+ if (TX_NOT_AVAILABLE == tx_rslt)
+ {
+ return CY_RTOS_TIMEOUT;
+ }
+ else
+ {
+ return convert_error(tx_rslt);
+ }
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_set_mutex
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_set_mutex(cy_mutex_t* mutex)
+{
+ if (mutex == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ return convert_error(tx_mutex_put(mutex));
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_deinit_mutex
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_deinit_mutex(cy_mutex_t* mutex)
+{
+ if (mutex == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ return convert_error(tx_mutex_delete(mutex));
+}
+
+
+/******************************************************
+* Semaphores
+******************************************************/
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_init_semaphore
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_init_semaphore(cy_semaphore_t* semaphore, uint32_t maxcount, uint32_t initcount)
+{
+ if (semaphore == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+ semaphore->maxcount = maxcount;
+ return convert_error(tx_semaphore_create(&(semaphore->tx_semaphore), TX_NULL, initcount));
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_get_semaphore
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_get_semaphore(cy_semaphore_t* semaphore, cy_time_t timeout_ms, bool in_isr)
+{
+ // Based on documentation
+ // http://www.ece.ualberta.ca/~cmpe490/documents/ghs/405/threadxug_g40c.pdf
+ // pg 168 it specifies that the timeout must be zero when called from ISR.
+ if ((semaphore == NULL) || (in_isr && (timeout_ms != 0)))
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+ cy_rtos_error_t tx_rslt =
+ tx_semaphore_get(&(semaphore->tx_semaphore), convert_ms_to_ticks(timeout_ms));
+ if (TX_NO_INSTANCE == tx_rslt)
+ {
+ return CY_RTOS_TIMEOUT;
+ }
+ else
+ {
+ return convert_error(tx_rslt);
+ }
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_set_semaphore
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_set_semaphore(cy_semaphore_t* semaphore, bool in_isr)
+{
+ (void)in_isr; // Unused parameter in this implementation
+ if (semaphore == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+ return convert_error(tx_semaphore_ceiling_put(&(semaphore->tx_semaphore), semaphore->maxcount));
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_get_count_semaphore
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_get_count_semaphore(cy_semaphore_t* semaphore, size_t* count)
+{
+ if ((semaphore == NULL) || (count == NULL))
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+ return convert_error(tx_semaphore_info_get(&(semaphore->tx_semaphore), TX_NULL, (ULONG*)count,
+ TX_NULL, TX_NULL, TX_NULL));
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_deinit_semaphore
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_deinit_semaphore(cy_semaphore_t* semaphore)
+{
+ if (semaphore == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+ return convert_error(tx_semaphore_delete(&(semaphore->tx_semaphore)));
+}
+
+
+/******************************************************
+* Events
+******************************************************/
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_init_event
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_init_event(cy_event_t* event)
+{
+ if (event == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ return convert_error(tx_event_flags_create(event, TX_NULL));
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_setbits_event
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_setbits_event(cy_event_t* event, uint32_t bits, bool in_isr)
+{
+ (void)in_isr; // Unused parameter in this implementation
+
+ if (event == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ return convert_error(tx_event_flags_set(event, bits, TX_OR));
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_clearbits_event
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_clearbits_event(cy_event_t* event, uint32_t bits, bool in_isr)
+{
+ (void)in_isr; // Unused parameter in this implementation
+
+ if (event == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ return convert_error(tx_event_flags_set(event, ~bits, TX_AND));
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_getbits_event
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_getbits_event(cy_event_t* event, uint32_t* bits)
+{
+ if ((event == NULL) || (bits == NULL))
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ cy_rtos_error_t tx_rslt = tx_event_flags_get(event, ALL_EVENT_FLAGS, TX_OR, bits, TX_NO_WAIT);
+ if (TX_NO_EVENTS == tx_rslt) // If timeout error occur with ALL_EVENT_FLAGS and TX_OR, then no
+ // flag is set
+ {
+ *bits = 0;
+ return CY_RSLT_SUCCESS;
+ }
+ else
+ {
+ return convert_error(tx_rslt);
+ }
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_waitbits_event
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_waitbits_event(cy_event_t* event, uint32_t* bits, bool clear, bool all,
+ cy_time_t timeout_ms)
+{
+ UINT get_option;
+
+ if ((event == NULL) || (bits == NULL))
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ if (all)
+ {
+ get_option = clear ? TX_AND_CLEAR : TX_AND;
+ }
+ else
+ {
+ get_option = clear ? TX_OR_CLEAR : TX_OR;
+ }
+
+ cy_rtos_error_t tx_rslt =
+ tx_event_flags_get(event, *bits, get_option, bits, convert_ms_to_ticks(timeout_ms));
+ if (TX_NO_EVENTS == tx_rslt)
+ {
+ return CY_RTOS_TIMEOUT;
+ }
+ else
+ {
+ return convert_error(tx_rslt);
+ }
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_deinit_event
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_deinit_event(cy_event_t* event)
+{
+ if (event == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ return convert_error(tx_event_flags_delete(event));
+}
+
+
+/******************************************************
+* Queues
+******************************************************/
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_init_queue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_init_queue(cy_queue_t* queue, size_t length, size_t itemsize)
+{
+ // Valid message lengths are {1-ULONG, 2-ULONG, 4-ULONG, 8-ULONG, 16-ULONG}
+ static const uint32_t BYTES_PER_QUEUE_WORD = sizeof(ULONG);
+
+ if ((queue == NULL) || (itemsize == 0) ||
+ (itemsize > BYTES_PER_QUEUE_WORD * MAX_QUEUE_MESSAGE_SIZE))
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ // round message words to next power of 2 times word size.
+ UINT message_words = 1;
+ while (message_words * BYTES_PER_QUEUE_WORD < itemsize)
+ {
+ message_words <<= 1;
+ }
+
+ queue->itemsize = itemsize;
+ ULONG queue_size = length * message_words * BYTES_PER_QUEUE_WORD;
+ queue->mem = malloc(queue_size);
+ if (queue->mem == NULL)
+ {
+ return CY_RTOS_NO_MEMORY;
+ }
+
+ cy_rtos_error_t tx_rslt = tx_queue_create(&(queue->tx_queue), TX_NULL, message_words,
+ queue->mem, queue_size);
+ if (TX_SUCCESS != tx_rslt)
+ {
+ last_error = tx_rslt;
+ free(queue->mem);
+ return CY_RTOS_GENERAL_ERROR;
+ }
+
+ return CY_RSLT_SUCCESS;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_put_queue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_put_queue(cy_queue_t* queue, const void* item_ptr, cy_time_t timeout_ms,
+ bool in_isr)
+{
+ if ((queue == NULL) || (item_ptr == NULL) || (in_isr && (timeout_ms != 0)))
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ cy_rtos_error_t tx_rslt = tx_queue_send(&(queue->tx_queue), (void*)item_ptr, convert_ms_to_ticks(
+ timeout_ms));
+ if (TX_QUEUE_FULL == tx_rslt)
+ {
+ return CY_RTOS_NO_MEMORY;
+ }
+ else
+ {
+ return convert_error(tx_rslt);
+ }
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_get_queue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_get_queue(cy_queue_t* queue, void* item_ptr, cy_time_t timeout_ms, bool in_isr)
+{
+ ULONG buffer[MAX_QUEUE_MESSAGE_SIZE];
+ if ((queue == NULL) || (item_ptr == NULL) || (in_isr && (timeout_ms != 0)))
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ cy_rtos_error_t tx_rslt =
+ tx_queue_receive(&(queue->tx_queue), buffer, convert_ms_to_ticks(timeout_ms));
+ if (TX_QUEUE_EMPTY == tx_rslt)
+ {
+ return CY_RTOS_TIMEOUT;
+ }
+ else if (tx_rslt == TX_SUCCESS)
+ {
+ memcpy(item_ptr, buffer, queue->itemsize);
+ return CY_RSLT_SUCCESS;
+ }
+ else
+ {
+ last_error = tx_rslt;
+ return CY_RTOS_GENERAL_ERROR;
+ }
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_count_queue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_count_queue(cy_queue_t* queue, size_t* num_waiting)
+{
+ if ((queue == NULL) || (num_waiting == NULL))
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+ return convert_error(tx_queue_info_get(&(queue->tx_queue), TX_NULL, (ULONG*)num_waiting,
+ TX_NULL, TX_NULL, TX_NULL, TX_NULL));
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_space_queue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_space_queue(cy_queue_t* queue, size_t* num_spaces)
+{
+ if ((queue == NULL) || (num_spaces == NULL))
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+ return convert_error(tx_queue_info_get(&(queue->tx_queue), TX_NULL, TX_NULL, (ULONG*)num_spaces,
+ TX_NULL, TX_NULL, TX_NULL));
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_reset_queue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_reset_queue(cy_queue_t* queue)
+{
+ if (queue == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+ return convert_error(tx_queue_flush(&(queue->tx_queue)));
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_deinit_queue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_deinit_queue(cy_queue_t* queue)
+{
+ if (queue == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+ cy_rslt_t result = convert_error(tx_queue_delete(&(queue->tx_queue)));
+ if (result == CY_RSLT_SUCCESS)
+ {
+ free(queue->mem);
+ }
+ return result;
+}
+
+
+/******************************************************
+* Timers
+******************************************************/
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_init_timer
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t 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)
+{
+ if ((timer == NULL) || (fun == NULL))
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+ timer->oneshot = (type == CY_TIMER_TYPE_ONCE);
+ // Use 1s here as default timeouts since these are going to get changed anyway
+ return convert_error(tx_timer_create(&(timer->tx_timer), TX_NULL, fun, arg, 1, 1,
+ TX_NO_ACTIVATE));
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_start_timer
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_start_timer(cy_timer_t* timer, cy_time_t num_ms)
+{
+ if (timer == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+ ULONG timer_ticks = convert_ms_to_ticks(num_ms);
+ cy_rslt_t rslt =
+ convert_error(tx_timer_change(&(timer->tx_timer), timer_ticks,
+ timer->oneshot ? 0 : timer_ticks));
+ if (CY_RSLT_SUCCESS != rslt)
+ {
+ return rslt;
+ }
+ return convert_error(tx_timer_activate(&(timer->tx_timer)));
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_stop_timer
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_stop_timer(cy_timer_t* timer)
+{
+ if (timer == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+ return convert_error(tx_timer_deactivate(&(timer->tx_timer)));
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_is_running_timer
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_is_running_timer(cy_timer_t* timer, bool* state)
+{
+ if ((timer == NULL) || (state == NULL))
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ UINT active;
+ cy_rslt_t rslt =
+ convert_error(tx_timer_info_get(&(timer->tx_timer), TX_NULL, &active, TX_NULL, TX_NULL,
+ TX_NULL));
+ if (CY_RSLT_SUCCESS == rslt)
+ {
+ *state = (active == TX_TRUE);
+ }
+ return rslt;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_deinit_timer
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_deinit_timer(cy_timer_t* timer)
+{
+ if (timer == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+ return convert_error(tx_timer_delete(&(timer->tx_timer)));
+}
+
+
+/******************************************************
+* Time
+******************************************************/
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_get_time
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_get_time(cy_time_t* tval)
+{
+ if (tval == NULL)
+ {
+ return CY_RTOS_BAD_PARAM;
+ }
+
+ *tval = convert_ticks_to_ms(tx_time_get());
+
+ return CY_RSLT_SUCCESS;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_rtos_delay_milliseconds
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_rtos_delay_milliseconds(cy_time_t num_ms)
+{
+ cy_time_t ticks = convert_ms_to_ticks(num_ms);
+
+ return convert_error(tx_thread_sleep(ticks));
+}
diff --git a/abstraction-rtos/source/cy_worker_thread.c b/abstraction-rtos/source/cy_worker_thread.c
new file mode 100644
index 00000000..07bf345a
--- /dev/null
+++ b/abstraction-rtos/source/cy_worker_thread.c
@@ -0,0 +1,229 @@
+/***********************************************************************************************//**
+ * \file cy_worker_thread.c
+ *
+ * \brief
+ * Provides implementation for functions that allow creating/deleting worker
+ * threads and deferring work to a worker thread.
+ ***************************************************************************************************
+ * \copyright
+ * Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or
+ * an affiliate of Cypress Semiconductor Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **************************************************************************************************/
+
+#include
+#include
+
+#include "cy_worker_thread.h"
+#include "cy_utils.h"
+#include "cyabs_rtos_internal.h"
+#if defined(CY_USING_HAL)
+#include "cyhal_system.h"
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+// Info for dispatching a function call
+typedef struct
+{
+ cy_worker_thread_func_t* work_func;
+ void* arg;
+} cy_worker_dispatch_info_t;
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_worker_thread_func
+//
+/* Worker Thread to dispatch the events that added to the event queue.
+ * It will wait indefinitely for a item to be queued and will terminate
+ * when the NULL work function is queued by delete. It will process all
+ * events before the terminating event.
+ * @param arg : pointer to @ref cy_worker_thread_info_t
+ */
+//--------------------------------------------------------------------------------------------------
+static void cy_worker_thread_func(cy_thread_arg_t arg)
+{
+ cy_rslt_t result;
+ cy_worker_dispatch_info_t dispatch_info;
+ cy_worker_thread_info_t* worker = (cy_worker_thread_info_t*)arg;
+
+ while (1)
+ {
+ result = cy_rtos_get_queue(&worker->event_queue, &dispatch_info, CY_RTOS_NEVER_TIMEOUT,
+ false);
+ if (result == CY_RSLT_SUCCESS)
+ {
+ if (dispatch_info.work_func != NULL)
+ {
+ dispatch_info.work_func(dispatch_info.arg);
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ cy_rtos_exit_thread();
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_worker_thread_create
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_worker_thread_create(cy_worker_thread_info_t* new_worker,
+ const cy_worker_thread_params_t* params)
+{
+ // Param check
+ CY_ASSERT((params != NULL) && (new_worker != NULL));
+ CY_ASSERT((params->stack == NULL) || ((params->stack != NULL) && (params->stack_size != 0)));
+
+ // Start with a clean structure
+ memset(new_worker, 0, sizeof(cy_worker_thread_info_t));
+
+ cy_rslt_t result = cy_rtos_init_queue(&new_worker->event_queue,
+ (params->num_entries != 0)
+ ? params->num_entries
+ : CY_WORKER_DEFAULT_ENTRIES,
+ sizeof(cy_worker_dispatch_info_t));
+ if (result == CY_RSLT_SUCCESS)
+ {
+ new_worker->state = CY_WORKER_THREAD_VALID;
+ result = cy_rtos_create_thread(&new_worker->thread,
+ cy_worker_thread_func,
+ (params->name != NULL)
+ ? params->name
+ : CY_WORKER_THREAD_DEFAULT_NAME,
+ params->stack,
+ params->stack_size,
+ params->priority,
+ (cy_thread_arg_t)new_worker);
+
+ if (result != CY_RSLT_SUCCESS)
+ {
+ new_worker->state = CY_WORKER_THREAD_INVALID;
+ cy_rtos_deinit_queue(&new_worker->event_queue);
+ }
+ }
+ return result;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_worker_thread_delete
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_worker_thread_delete(cy_worker_thread_info_t* old_worker)
+{
+ cy_rslt_t result = CY_RSLT_SUCCESS;
+
+ uint32_t state = cyhal_system_critical_section_enter();
+ if (old_worker->state != CY_WORKER_THREAD_INVALID)
+ {
+ // Don't allow terminating while cy_rtos_put_queue is running
+ if (old_worker->state == CY_WORKER_THREAD_VALID)
+ {
+ // A terminating event is queued that will break the while loop
+ // Note that this is ok because thread enqueue function will not
+ // allow NULL as a valid value for the work function.
+ old_worker->state = CY_WORKER_THREAD_TERMINATING;
+ cyhal_system_critical_section_exit(state);
+ cy_worker_dispatch_info_t dispatch_info = { NULL, NULL };
+ bool in_isr = is_in_isr();
+ result = cy_rtos_put_queue(&old_worker->event_queue, &dispatch_info, 0, in_isr);
+ if (result != CY_RSLT_SUCCESS)
+ {
+ // Could not enqueue termination task, return to valid state
+ state = cyhal_system_critical_section_enter();
+ old_worker->state = CY_WORKER_THREAD_VALID;
+ cyhal_system_critical_section_exit(state);
+
+ return result;
+ }
+ }
+
+ if (old_worker->state != CY_WORKER_THREAD_JOIN_COMPLETE)
+ {
+ cyhal_system_critical_section_exit(state);
+ result = cy_rtos_join_thread(&old_worker->thread);
+ if (result != CY_RSLT_SUCCESS)
+ {
+ return result;
+ }
+ state = cyhal_system_critical_section_enter();
+ old_worker->state = CY_WORKER_THREAD_JOIN_COMPLETE;
+ }
+
+ if (old_worker->state != CY_WORKER_THREAD_INVALID)
+ {
+ cyhal_system_critical_section_exit(state);
+ result = cy_rtos_deinit_queue(&old_worker->event_queue);
+ if (result != CY_RSLT_SUCCESS)
+ {
+ return result;
+ }
+ state = cyhal_system_critical_section_enter();
+ old_worker->state = CY_WORKER_THREAD_INVALID;
+ }
+ }
+
+ cyhal_system_critical_section_exit(state);
+ return result;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_worker_thread_enqueue
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t cy_worker_thread_enqueue(cy_worker_thread_info_t* worker_info,
+ cy_worker_thread_func_t* work_func, void* arg)
+{
+ CY_ASSERT(worker_info != NULL);
+ CY_ASSERT(work_func != NULL);
+
+ uint32_t state = cyhal_system_critical_section_enter();
+ if ((worker_info->state != CY_WORKER_THREAD_VALID) &&
+ (worker_info->state != CY_WORKER_THREAD_ENQUEUING))
+ {
+ cyhal_system_critical_section_exit(state);
+ return CY_WORKER_THREAD_ERR_THREAD_INVALID;
+ }
+ worker_info->enqueue_count++;
+ worker_info->state = CY_WORKER_THREAD_ENQUEUING;
+ cyhal_system_critical_section_exit(state);
+
+ cy_worker_dispatch_info_t dispatch_info = { work_func, arg };
+ // Queue an event to be run by the worker thread
+ bool in_isr = is_in_isr();
+ cy_rslt_t result = cy_rtos_put_queue(&worker_info->event_queue, &dispatch_info, 0, in_isr);
+
+ state = cyhal_system_critical_section_enter();
+ worker_info->enqueue_count--;
+ if (worker_info->enqueue_count == 0)
+ {
+ worker_info->state = CY_WORKER_THREAD_VALID;
+ }
+ cyhal_system_critical_section_exit(state);
+
+ return result;
+}
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // defined(CY_USING_HAL)
diff --git a/abstraction-rtos/version.xml b/abstraction-rtos/version.xml
new file mode 100644
index 00000000..a2159543
--- /dev/null
+++ b/abstraction-rtos/version.xml
@@ -0,0 +1 @@
+1.5.0.25183
diff --git a/whd-bsp-integration/COMPONENT_CAT4/cy_map_hostbuffer.c b/whd-bsp-integration/COMPONENT_CAT4/cy_map_hostbuffer.c
new file mode 100644
index 00000000..9531d117
--- /dev/null
+++ b/whd-bsp-integration/COMPONENT_CAT4/cy_map_hostbuffer.c
@@ -0,0 +1,97 @@
+/***************************************************************************//**
+* \file cy_map_hostbuffer.c
+*
+* \brief
+* Implements a set of mapping functions for M2M DMA host buffer routines.
+*
+********************************************************************************
+* \copyright
+* Copyright 2021-2022 Cypress Semiconductor Corporation (an Infineon company) or
+* an affiliate of Cypress Semiconductor Corporation
+*
+* SPDX-License-Identifier: Apache-2.0
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*******************************************************************************/
+
+#include "wiced_osl.h"
+#include "cy_network_buffer.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* __cplusplus */
+
+#define HOST_BUFFER_WAIT_MS (1000UL)
+
+/*******************************************************************************
+* Host buffer functions
+*******************************************************************************/
+
+cy_rslt_t host_buffer_get(wiced_buffer_t* buffer, wwd_buffer_dir_t direction,
+ uint16_t size, bool wait)
+{
+ uint32_t timeout_ms = wait ? HOST_BUFFER_WAIT_MS : 0UL;
+
+ return (cy_rslt_t)cy_host_buffer_get((whd_buffer_t*)buffer, (whd_buffer_dir_t)direction,
+ size, timeout_ms);
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// host_buffer_release
+//--------------------------------------------------------------------------------------------------
+void host_buffer_release(wiced_buffer_t buffer, wwd_buffer_dir_t direction)
+{
+ cy_buffer_release((whd_buffer_t)buffer, (whd_buffer_dir_t)direction);
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// host_buffer_get_current_piece_data_pointer
+//--------------------------------------------------------------------------------------------------
+uint8_t* host_buffer_get_current_piece_data_pointer(wiced_buffer_t buffer)
+{
+ return cy_buffer_get_current_piece_data_pointer((whd_buffer_t)buffer);
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// host_buffer_get_current_piece_size
+//--------------------------------------------------------------------------------------------------
+uint16_t host_buffer_get_current_piece_size(wiced_buffer_t buffer)
+{
+ return cy_buffer_get_current_piece_size((whd_buffer_t)buffer);
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// host_buffer_set_size
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t host_buffer_set_size(wiced_buffer_t buffer, uint16_t size)
+{
+ return (cy_rslt_t)cy_buffer_set_size((whd_buffer_t)buffer, size);
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// host_buffer_add_remove_at_front
+//--------------------------------------------------------------------------------------------------
+cy_rslt_t host_buffer_add_remove_at_front(wiced_buffer_t* buffer, int32_t add_remove_amount)
+{
+ return (cy_rslt_t)cy_buffer_add_remove_at_front((whd_buffer_t*)buffer, add_remove_amount);
+}
+
+
+#if defined(__cplusplus)
+}
+#endif /* __cplusplus */
diff --git a/whd-bsp-integration/COMPONENT_LWIP/cy_network_buffer_lwip.c b/whd-bsp-integration/COMPONENT_LWIP/cy_network_buffer_lwip.c
new file mode 100644
index 00000000..4d5a5487
--- /dev/null
+++ b/whd-bsp-integration/COMPONENT_LWIP/cy_network_buffer_lwip.c
@@ -0,0 +1,168 @@
+/***********************************************************************************************//**
+ * \file cy_network_buffer_lwip.c
+ *
+ * \brief
+ * Basic set of APIs for dealing with network packet buffers. This is used by WHD
+ * for relaying data between the network stack and the connectivity chip.
+ *
+ ***************************************************************************************************
+ * \copyright
+ * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
+ * an affiliate of Cypress Semiconductor Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **************************************************************************************************/
+
+#include
+#include "cy_network_buffer.h"
+#include "cy_utils.h"
+#include "cyhal_system.h"
+#include "lwip/pbuf.h"
+
+#define SDIO_BLOCK_SIZE (64U)
+
+//--------------------------------------------------------------------------------------------------
+// cy_buffer_pool_init
+//--------------------------------------------------------------------------------------------------
+whd_result_t cy_buffer_pool_init(void* tx_packet_pool, void* rx_packet_pool)
+{
+ CY_UNUSED_PARAMETER(tx_packet_pool);
+ CY_UNUSED_PARAMETER(rx_packet_pool);
+
+ /*
+ * Not used for LwIP.
+ */
+
+ return WHD_SUCCESS;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_host_buffer_get
+//--------------------------------------------------------------------------------------------------
+whd_result_t cy_host_buffer_get(whd_buffer_t* buffer, whd_buffer_dir_t direction,
+ uint16_t size, uint32_t timeout_ms)
+{
+ struct pbuf* p = NULL;
+ uint32_t counter = 0;
+
+ do
+ {
+ counter++;
+ if (direction == WHD_NETWORK_TX)
+ {
+ // Allocate from the POOL if possible to avoid dynamic memory allocation
+ pbuf_type type = (size <= PBUF_POOL_BUFSIZE) ? PBUF_POOL : PBUF_RAM;
+ p = pbuf_alloc(PBUF_RAW, size, type);
+ }
+ else
+ {
+ // Increase allocation size to ensure the SDIO can write fully aligned blocks for
+ // best throughput performance
+ p = pbuf_alloc(PBUF_RAW, size + SDIO_BLOCK_SIZE, PBUF_RAM);
+ if (p != NULL)
+ {
+ p->len = size;
+ p->tot_len -= SDIO_BLOCK_SIZE;
+ }
+ }
+
+ if (NULL == p)
+ {
+ cyhal_system_delay_ms(1);
+ }
+ } while ((NULL == p) && (counter <= timeout_ms));
+
+ if (p != NULL)
+ {
+ *buffer = p;
+ return WHD_SUCCESS;
+ }
+ else
+ {
+ return WHD_BUFFER_ALLOC_FAIL;
+ }
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_buffer_release
+//--------------------------------------------------------------------------------------------------
+void cy_buffer_release(whd_buffer_t buffer, whd_buffer_dir_t direction)
+{
+ CY_UNUSED_PARAMETER(direction);
+ (void)pbuf_free((struct pbuf*)buffer);
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_buffer_get_current_piece_data_pointer
+//--------------------------------------------------------------------------------------------------
+uint8_t* cy_buffer_get_current_piece_data_pointer(whd_buffer_t buffer)
+{
+ CY_ASSERT(buffer != NULL);
+ struct pbuf* pbuffer= (struct pbuf*)buffer;
+ return (uint8_t*)pbuffer->payload;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_buffer_get_current_piece_size
+//--------------------------------------------------------------------------------------------------
+uint16_t cy_buffer_get_current_piece_size(whd_buffer_t buffer)
+{
+ CY_ASSERT(buffer != NULL);
+ struct pbuf* pbuffer = (struct pbuf*)buffer;
+ return (uint16_t)pbuffer->len;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_buffer_set_size
+//--------------------------------------------------------------------------------------------------
+whd_result_t cy_buffer_set_size(whd_buffer_t buffer, uint16_t size)
+{
+ CY_ASSERT(buffer != NULL);
+ struct pbuf* pbuffer = (struct pbuf*)buffer;
+
+ if (size > ((uint16_t)WHD_LINK_MTU +
+ LWIP_MEM_ALIGN_SIZE(LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf))) +
+ LWIP_MEM_ALIGN_SIZE(size)))
+ {
+ return WHD_BUFFER_SIZE_SET_ERROR;
+ }
+
+ pbuffer->tot_len = size;
+ pbuffer->len = size;
+
+ return CY_RSLT_SUCCESS;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// cy_buffer_add_remove_at_front
+//--------------------------------------------------------------------------------------------------
+whd_result_t cy_buffer_add_remove_at_front(whd_buffer_t* buffer, int32_t add_remove_amount)
+{
+ CY_ASSERT(buffer != NULL);
+ struct pbuf** pbuffer = (struct pbuf**)buffer;
+
+ if ((u8_t)0 != pbuf_header(*pbuffer, (s16_t)(-add_remove_amount)))
+ {
+ return WHD_BUFFER_POINTER_MOVE_ERROR;
+ }
+
+ return WHD_SUCCESS;
+}
diff --git a/whd-bsp-integration/README.md b/whd-bsp-integration/README.md
new file mode 100644
index 00000000..65ade86e
--- /dev/null
+++ b/whd-bsp-integration/README.md
@@ -0,0 +1,60 @@
+# WiFi Host Driver Board Support Package Integration
+
+## Overview
+
+This library provides some convenience functions for connecting the WiFi Host Driver (WHD) library to a Board Support Package (BSP) that includes a WLAN chip. This library initializes the hardware and passes a reference to the communication interface on the board into WHD. It also sets up the LwIP or NetXDuo based network buffers to be used for sending packets back and forth.
+
+The BSP is expected to set a component indicating what communication interface to use to relay information between the MCU and the WIFI chip. The legal options are restricted based on what MCU and WIFI chips are being used. The selected interface must be supported by both sides. The legal component values are one of:
+* WIFI_INTERFACE_SDIO
+* WIFI_INTERFACE_SPI
+* WIFI_INTERFACE_M2M
+
+Some additional customization of the library is possible by setting defines when building the library. If no custom value is provided, the library will pick a reasonable default value. The following options are available for customization:
+* CY_WIFI_COUNTRY: Defines the country this will operate in for wifi initialization parameters. See the wifi-host-driver's whd_country_code_t for legal options.
+* CY_WIFI_THREAD_STACK_SIZE: Defines the amount of stack memory available for the wifi thread.
+* CY_WIFI_THREAD_PRIORITY: Defines the priority of the thread that services wifi packets. Legal values are defined by the RTOS being used.
+* CY_WIFI_HOST_WAKE_SW_FORCE: Defines whether to use the out-of-band pin to allow the WIFI chip to wake up the MCU.
+* CY_WIFI_OOB_INTR_PRIORITY: Defines the priority of the interrupt that handles out-of-band notifications from the WIFI chip. Legal values are defined by the MCU running this code.
+
+
+## Getting Started
+
+To use this library:
+1. Implement the cy_network_process_ethernet_data() function. This should be something similar to the example below.
+```cpp
+/* This needs to be the same item as passed to netifapi_netif_add() */
+static struct netif *default_interface = NULL;
+
+void cy_network_process_ethernet_data(whd_interface_t iface, whd_buffer_t buf)
+{
+ if (default_interface != NULL)
+ {
+ if (default_interface->input(buf, default_interface) != ERR_OK)
+ cy_buffer_release(buf, WHD_NETWORK_RX);
+ }
+ else
+ {
+ cy_buffer_release(buf, WHD_NETWORK_RX);
+ }
+}
+```
+2. Include a reference to `cybsp_wifi.h`.
+3. Call cybsp_wifi_init_primary() to initialize the interface. This needs to be done after having called cybsp_init().
+
+## Features
+
+* APIs for setting up the WHD interface with the BSP's SDIO/SPI/M2M interface.
+ * Initialize a primary WiFi interface
+ * Optionally initialize a secondary WiFi interface
+ * Cleanup interfaces
+* APIs for connecting WHD to LwIP/NetXDuo memory buffers (whd_buffer_funcs_t)
+* Framework for connecting WHD to LwIP/NetXDuo network interface (whd_netif_funcs_t)
+
+## More information
+* [API Reference Guide](https://infineon.github.io/whd-bsp-integration/html/modules.html)
+* [Cypress Semiconductor, an Infineon Technologies Company](http://www.cypress.com)
+* [Infineon GitHub](https://github.com/infineon)
+* [ModusToolbox™](https://www.cypress.com/products/modustoolbox-software-environment)
+
+---
+© Cypress Semiconductor Corporation (an Infineon company) or an affiliate of Cypress Semiconductor Corporation, 2019-2022.
diff --git a/whd-bsp-integration/RELEASE.md b/whd-bsp-integration/RELEASE.md
new file mode 100644
index 00000000..3631c28d
--- /dev/null
+++ b/whd-bsp-integration/RELEASE.md
@@ -0,0 +1,58 @@
+# WiFi Host Driver Board Support Package Integration Release Notes
+This library helps streamline the process of getting the WiFi Host Driver (WHD) setup and running with a Board Support Package (BSP) that includes a WLAN chip.
+
+### What's Included?
+* APIs for setting up the WHD interface with the BSP's SDIO interface.
+* APIs for connecting WHD to LwIP/NetXDuo memory buffers (whd_buffer_funcs_t)
+* Framework for connecting WHD to LwIP/NetXDuo network interface (whd_netif_funcs_t)
+
+### What Changed?
+#### v2.1.0
+* Added support for dyanmically allocated NetX Duo packets to support WHD IOVARs with payloads larger than MTU.
+* Added support for NetX Duo
+* Made SDIO initialization more robust
+#### v2.0.0
+* Added support for different communication protocols (SDIO, SPI, DMA) between MCU and Radio
+* Card initialization process improvements. Code now checks whether SDIO device supports 1.8V signaling, and, if it does, performs the actions needed in order to switch to 1.8V.
+* Added support for overriding the default country code by defining CY_WIFI_COUNTRY to a value from whd_country_code_t.
+* Added argument to cybsp_wifi_init_primary_extended() to set WHD initialization parameters
+* SDIO frequency is increased to 50 MHz if High Speed Mode is supported
+* Added support for HAL API v1 or v2
+* Minimum required `wifi-host-driver` library version for this release - `2.0.0`
+#### v1.2.0
+* Fixed possible memory corruption issue introduced with changes from v1.1.0
+#### v1.1.2
+* Robustness update for WLAN initialization
+#### v1.1.1
+* Update network buffer allocation for improved performance
+#### v1.1.0
+* Fixed a memory leak when shutting down the WHD interface
+* Minor code style cleanups
+#### v1.0.2
+* Minor update for documentation & branding
+#### v1.0.1
+* Fixed issue with a missing ;
+#### v1.0.0
+* Initial release
+
+### Supported Software and Tools
+This version of the RTOS Abstraction API was validated for compatibility with the following Software and Tools:
+
+| Software and Tools | Version |
+| :--- | :----: |
+| ModusToolbox™ Software Environment | 2.4.0 |
+| GCC Compiler | 10.3.1 |
+| IAR Compiler | 9.30.1 |
+| ARM Compiler | 6.16 |
+
+Minimum required ModusToolbox™ Software Environment: v2.0
+
+### More information
+Use the following links for more information, as needed:
+* [API Reference Guide](https://infineon.github.io/whd-bsp-integration/html/modules.html)
+* [Cypress Semiconductor, an Infineon Technologies Company](http://www.cypress.com)
+* [Infineon GitHub](https://github.com/infineon)
+* [ModusToolbox™](https://www.cypress.com/products/modustoolbox-software-environment)
+
+---
+© Cypress Semiconductor Corporation (an Infineon company) or an affiliate of Cypress Semiconductor Corporation, 2019-2022.
diff --git a/whd-bsp-integration/cy_network_buffer.h b/whd-bsp-integration/cy_network_buffer.h
new file mode 100644
index 00000000..60be632e
--- /dev/null
+++ b/whd-bsp-integration/cy_network_buffer.h
@@ -0,0 +1,187 @@
+/***********************************************************************************************//**
+ * \file cy_network_buffer.h
+ *
+ * \brief
+ * Basic set of APIs for dealing with network packet buffers. This is used by WHD
+ * for relaying data between the network stack and the connectivity chip.
+ *
+ ***************************************************************************************************
+ * \copyright
+ * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
+ * an affiliate of Cypress Semiconductor Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **************************************************************************************************/
+
+/**
+ * \addtogroup group_bsp_network_buffer Buffer management
+ * \{
+ * Basic set of APIs for dealing with network packet buffers
+ */
+
+#pragma once
+
+#include
+#include
+#include "cy_result.h"
+#include "whd.h"
+#include "whd_network_types.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/** Initialize the buffer pools
+ *
+ * Initialize the buffer pools used by the buffer management routines.
+ * A pair of pools, one for RX buffers and one for TX buffers in passed
+ * in for use by the management routines.
+ *
+ * Not all implementations use preallocated buffer pools.
+ *
+ * @param tx_packet_pool : Pointer to the initialized NetXDuo TX packet buffer pool
+ * @param rx_packet_pool : Pointer to the initialized NetXDuo RX packet buffer pool
+ *
+ * @return : CY_RSLT_SUCCESS or WHD_BADARG
+ */
+whd_result_t cy_buffer_pool_init(void* tx_packet_pool, void* rx_packet_pool);
+
+/** Allocates a packet buffer
+ *
+ * Attempts to allocate a packet buffer of the size requested. It can do this
+ * by allocating a pre-existing packet from a pool, using a static buffer,
+ * or by dynamically allocating memory. The method of allocation does not
+ * concern WHD, however it must match the way the network stack expects packet
+ * buffers to be allocated. Usually WHD requires packet of size of WHD_LINK_MTU
+ * which includes the MTU. Refer to whd_types.h to find the size of WHD_LINK_MTU.
+ *
+ * @param buffer : A pointer which receives the allocated packet buffer handle
+ * @param direction : Indicates transmit/receive direction that the packet buffer is
+ * used for. This may be needed if tx/rx pools are separate.
+ * @param size : The number of bytes to allocate.
+ * @param timeout_ms: Time to wait for a packet buffer to be available
+ *
+ * @return : CY_RSLT_SUCCESS or WHD_BUFFER_ALLOC_FAIL if the buffer could not be allocated
+ */
+whd_result_t cy_host_buffer_get(whd_buffer_t* buffer, whd_buffer_dir_t direction,
+ uint16_t size, uint32_t timeout_ms);
+
+/** Releases a packet buffer
+ *
+ * This function is used by WHD to indicate that it no longer requires
+ * a packet buffer. The buffer can then be released back into a pool for
+ * reuse, or the dynamically allocated memory can be freed, according to
+ * how the packet was allocated.
+ * Returns void since WHD cannot do anything about failures
+ *
+ * @param buffer : The handle of the packet buffer to be released
+ * @param direction : Indicates transmit/receive direction that the packet buffer has
+ * been used for. This might be needed if tx/rx pools are separate.
+ */
+void cy_buffer_release(whd_buffer_t buffer, whd_buffer_dir_t direction);
+
+/** Retrieves the current pointer of a packet buffer
+ *
+ * Since packet buffers usually need to be created with space at the
+ * front for additional headers, this function allows WHD to get
+ * the current 'front' location pointer.
+ *
+ * @param buffer : The handle of the packet buffer whose pointer is to be retrieved
+ *
+ * @return : The packet buffer's current pointer.
+ */
+uint8_t* cy_buffer_get_current_piece_data_pointer(whd_buffer_t buffer);
+
+/** Retrieves the size of a packet buffer
+ *
+ * Since packet buffers usually need to be created with space at the
+ * front for additional headers, the memory block used to contain a packet buffer
+ * will often be larger than the current size of the packet buffer data.
+ * This function allows WHD to retrieve the current size of a packet buffer's data.
+ *
+ * @param buffer : The handle of the packet buffer whose size is to be retrieved
+ *
+ * @return : The size of the packet buffer.
+ */
+uint16_t cy_buffer_get_current_piece_size(whd_buffer_t buffer);
+
+/** Sets the current size of a WHD packet
+ *
+ * This function sets the current length of a WHD packet buffer
+ *
+ * @param buffer : The packet to be modified
+ * @param size : The new size of the packet buffer
+ *
+ * @return : CY_RSLT_SUCCESS or WHD_BUFFER_SIZE_SET_ERROR if the requested size is not valid
+ */
+whd_result_t cy_buffer_set_size(whd_buffer_t buffer, uint16_t size);
+
+/** Moves the current pointer of a packet buffer
+ *
+ * Since packet buffers usually need to be created with space at the front for additional headers,
+ * this function allows WHD to move the current 'front' location pointer so that it has space to
+ * add headers to transmit packets, and so that the network stack does not see the internal WHD
+ * headers on received packets.
+ *
+ * @param buffer : A pointer to the handle of the current packet buffer for which the
+ * current pointer will be moved. On return this may contain a pointer
+ * to a newly allocated packet buffer which has been daisy chained to
+ * the front of the given one. This would be the case if the given
+ * packet buffer didn't have enough space at the front.
+ * @param add_remove_amount : This is the number of bytes to move the current pointer of the packet
+ * buffer - a negative value increases the space for headers at the
+ * front of the packet, a positive value decreases the space.
+ *
+ * @return : CY_RSLT_SUCCESS or WHD_BUFFER_POINTER_MOVE_ERROR if the added amount
+ * is outside the size of the buffer
+ */
+whd_result_t cy_buffer_add_remove_at_front(whd_buffer_t* buffer, int32_t add_remove_amount);
+
+
+/** Called by WHD to pass received data to the network stack
+ *
+ * Packets received from the Wi-Fi network by WHD are forwarded to by calling function ptr which
+ * must be implemented in the network interface. Ethernet headers
+ * are present at the start of these packet buffers.
+ *
+ * This function is called asynchronously in the context of the
+ * WHD thread whenever new data has arrived.
+ * Packet buffers are allocated within WHD, and ownership is transferred
+ * to the network stack. The network stack or application is thus
+ * responsible for releasing the packet buffers.
+ * Most packet buffering systems have a pointer to the 'current point' within
+ * the packet buffer. When this function is called, the pointer points
+ * to the start of the Ethernet header. There is other inconsequential data
+ * before the Ethernet header.
+ *
+ * It is preferable that the (whd_network_process_ethernet_data)() function simply puts
+ * the received packet on a queue for processing by another thread. This avoids the
+ * WHD thread being unnecessarily tied up which would delay other packets
+ * being transmitted or received.
+ *
+ * @param interface : The interface on which the packet was received.
+ * @param buffer : Handle of the packet which has just been received. Responsibility for
+ * releasing this buffer is transferred from WHD at this point.
+ *
+ */
+void cy_network_process_ethernet_data(whd_interface_t interface, whd_buffer_t buffer);
+
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+/** \} group_bsp_network_buffer */
diff --git a/whd-bsp-integration/cy_wifi_fw_section.h b/whd-bsp-integration/cy_wifi_fw_section.h
new file mode 100644
index 00000000..ae3d5b25
--- /dev/null
+++ b/whd-bsp-integration/cy_wifi_fw_section.h
@@ -0,0 +1,77 @@
+/***********************************************************************************************//**
+ * \file cy_wifi_fw_section.h
+ *
+ * \brief
+ * Determines the start and end of the region the WiFi firmware is stored in.
+ *
+ ***************************************************************************************************
+ * \copyright
+ * Copyright 2020-2022 Cypress Semiconductor Corporation (an Infineon company) or
+ * an affiliate of Cypress Semiconductor Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **************************************************************************************************/
+
+#pragma once
+
+#if defined(CY_STORAGE_WIFI_DATA_OUTPUT)
+
+#include "cy_utils.h"
+
+#if defined(__ARMCC_VERSION)
+
+#define CY_SECTION_BASE_SYMBOL_BASE(SECTION) Image$$ ## SECTION ## $$Base
+#define CY_SECTION_BASE_SYMBOL(SECTION) CY_SECTION_BASE_SYMBOL_BASE(SECTION)
+extern char CY_SECTION_BASE_SYMBOL(CY_STORAGE_WIFI_DATA_OUTPUT);
+#define CY_WIFI_FW_SECTION_START (&CY_SECTION_BASE_SYMBOL(CY_STORAGE_WIFI_DATA_OUTPUT))
+
+#define CY_SECTION_LIMIT_SYMBOL_BASE(SECTION) Image$$ ## SECTION ## $$Limit
+#define CY_SECTION_LIMIT_SYMBOL(SECTION) CY_SECTION_LIMIT_SYMBOL_BASE(SECTION)
+extern char CY_SECTION_LIMIT_SYMBOL(CY_STORAGE_WIFI_DATA_OUTPUT);
+#define CY_WIFI_FW_SECTION_END (&CY_SECTION_LIMIT_SYMBOL(CY_STORAGE_WIFI_DATA_OUTPUT))
+
+#elif defined(__GNUC__)
+
+// Must define __