Ver código fonte

first commits

Evlers 2 anos atrás
commit
aa4c514f1a

+ 3 - 0
.gitmodules

@@ -0,0 +1,3 @@
+[submodule "wifi-host-driver"]
+	path = wifi-host-driver
+	url = https://github.com/Infineon/wifi-host-driver

+ 82 - 0
Kconfig

@@ -0,0 +1,82 @@
+menuconfig RT_USING_WHD
+    bool "Using Wifi-Host-Driver(WHD)"
+    select RT_USING_WIFI
+    select RT_USING_SAL
+    default n
+
+    if RT_USING_WHD
+
+        config CY_WIFI_DEFAULT_ENABLE_POWERSAVE_MODE
+            bool "Default enable powersave mode"
+            default n
+
+        if CY_WIFI_DEFAULT_ENABLE_POWERSAVE_MODE
+            config CY_WIFI_DEFAULT_PM2_SLEEP_RET_TIME
+                int "Set return to sleep delay.(PM2)"
+                default 200
+        endif
+
+        config CY_WIFI_WHD_THREAD_PRIORITY
+            int "The priority level value of WHD thread"
+            range 0 32
+            default 8
+
+        config CY_WIFI_WHD_THREAD_STACK_SIZE
+            int "The stack size for WHD thread"
+            range 0 8192
+            default 8192
+
+        choice
+            prompt "Select Chips"
+            default WHD_USING_CHIP_CYW43438
+
+            config WHD_USING_CHIP_CYW43438
+                bool "CYWL6208(cyw43438)"
+
+            config WHD_USING_CHIP_CYW4373
+                bool "CYWL6373(cyw4373)"
+
+            config WHD_USING_CHIP_CYW43012
+                bool "CYWL6312(cyw43012)"
+
+            config WHD_USING_CHIP_CYW43439
+                bool "CYWL6209(cyw43439)"
+
+            config WHD_USING_CHIP_CYW43022
+                bool "CYWL6322(cyw43022)"
+
+            config WHD_USING_CHIP_CYW4343W
+                bool "cyw4343W"
+
+        endchoice
+
+        config CYBSP_REG_ON_PIN
+            int "Set the WiFi_REG ON pin"
+            default 45
+
+        config CYBSP_HOST_WAKE_IRQ_PIN
+            int "Set the HOST_WAKE_IRQ pin"
+            default 67
+
+        choice
+            prompt "Select HOST_WAKE_IRQ event type"
+            default CYBSP_HOST_WAKE_IRQ_EVENT_FALLING
+
+            config CYBSP_HOST_WAKE_IRQ_EVENT_FALL
+                bool "falling"
+
+            config CYBSP_HOST_WAKE_IRQ_EVENT_RISE
+                bool "rising"
+
+            config CYBSP_HOST_WAKE_IRQ_EVENT_BOTH
+                bool "rising and falling"
+
+        endchoice
+
+        config CYBSP_OOB_INTR_PRIORITY
+            int "Set the interrput priority for HOST_WAKE_IRQ pin"
+            default 2
+        
+    endif
+
+    

+ 59 - 0
README.md

@@ -0,0 +1,59 @@
+## RT-Thread Wi-Fi Host Driver (WHD)
+
+### Overview
+The WHD is an independent, embedded Wi-Fi Host Driver that provides a set of APIs to interact with Infineon WLAN chips. The WHD is an independent firmware product that is easily portable to any embedded software environment, including popular IoT frameworks such as Mbed OS and Amazon FreeRTOS. Therefore, the WHD includes hooks for RTOS and TCP/IP network abstraction layers.
+
+Details about Wi-Fi Host Driver can be found in the [Wi-Fi Host Driver readme](./wifi-host-driver/README.md).<br>
+The [release notes](./wifi-host-driver/RELEASE.md) detail the current release. You can also find information about previous versions.
+
+The repository has adapted WHD to the RT-Thread system, currently only supports the SDIO bus protocol, and uses the mmcsd of RT-Thread for sdio bus operations.<br>
+Welcome everyone `PR` to support more bus interface and chips.
+
+### Using
+
+- Clone the repository to the `packages` or `libraries` directory in the RT-Thread project.
+- Because the `wifi-host-driver` repository is a submodule, use of the `git clone` command requires the `--recursive` option.
+- In the `libraries` or `packages` folder in the RT-Thread project, include `Kconfig` file for `WHD` in its Kconfig files.
+- For example, include `WHD` in the `libraries` directory:
+```Kconfig
+menu "External Libraries"
+    source "$RTT_DIR/../libraries/rtthread_whd/Kconfig"
+endmenu
+```
+**Note:**<br>
+sdio driver needs to support byte transfer. In the bsp of RT-Thread, most chips do not have the function of adapting byte transfer. <br>
+Please modify the `drv_sdio.c` file according to the following example: (The example is an sdio driver for the STM32H750)
+```c
+SCB_CleanInvalidateDCache();
+
+reg_cmd |= SDMMC_CMD_CMDTRANS;
+hw_sdio->mask &= ~(SDMMC_MASK_CMDRENDIE | SDMMC_MASK_CMDSENTIE);
+hw_sdio->dtimer = HW_SDIO_DATATIMEOUT;
+hw_sdio->dlen = data->blks * data->blksize;
+hw_sdio->dctrl = (get_order(data->blksize)<<4) | (data->flags & DATA_DIR_READ ? SDMMC_DCTRL_DTDIR : 0) | \
+                    /* Adds detection of the DATA_STREAM flag */
+                    ((data->flags & DATA_STREAM) ? SDMMC_DCTRL_DTMODE_0 : 0);
+hw_sdio->idmabase0r = (rt_uint32_t)sdio->cache_buf;
+hw_sdio->idmatrlr = SDMMC_IDMA_IDMAEN;
+```
+
+
+### Supported Chip
+
+| **CHIP**  |**SDIO**|**SPI**|**M2M**|
+|-----------|--------|-------|-------|
+| CYW4343W  |   o    |   x   |   x   |
+| CYW43438  |&#10004;|   x   |   x   |
+| CYW4373   |   o    |   x   |   x   |
+| CYW43012  |   o    |   x   |   x   |
+| CYW43439  |   o    |   x   |   x   |
+| CYW43022  |   o    |   x   |   x   |
+
+'x' indicates no support<br>
+'&#10004;' indicates tested and supported<br>
+'o' means theoretically supported, but not tested
+
+### More information
+* [Wi-Fi Host Driver API Reference Manual and Porting Guide](https://infineon.github.io/wifi-host-driver/html/index.html)
+* [Wi-Fi Host Driver Release Notes](./wifi-host-driver/RELEASE.md)
+* [Infineon Technologies](http://www.infineon.com)

+ 86 - 0
SConscript

@@ -0,0 +1,86 @@
+Import('RTT_ROOT')
+Import('rtconfig')
+from building import *
+
+cwd = GetCurrentDir()
+
+# add the general drivers.
+src = Split("""
+    wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_common.c
+    wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus_sdio_protocol.c
+    wifi-host-driver/WiFi_Host_Driver/src/bus_protocols/whd_bus.c
+""")
+
+
+# add wifi host driver source and header files
+src += Glob('wifi-host-driver/WiFi_Host_Driver/src/*.c')
+src += Glob('wifi-host-driver/WiFi_Host_Driver/resources/resource_imp/*.c')
+
+path = [cwd + '/wifi-host-driver']
+path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/src']
+path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/inc']
+path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/src/include']
+path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/src/bus_protocols']
+path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/resources/resource_imp']
+
+# add cyw4343W chip drivers source and header files
+if GetDepend(['WHD_USING_CHIP_CYW4343W']):
+    src += Glob('wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4343W/4343WA1_clm_blob.c')
+    src += Glob('wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4343W/4343WA1_bin.c')
+    path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4343W']
+    path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4343W']
+    path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_4343W/COMPONENT_MURATA-1DX']
+
+# add cyw43438 chip drivers source and header files
+if GetDepend(['WHD_USING_CHIP_CYW43438']):
+    src += Glob('wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43438/43438A1_clm_blob.c')
+    src += Glob('wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43438/43438A1_bin.c')
+    path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43438']
+    path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43438']
+    path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_43438/COMPONENT_AW-CU427-P']
+
+# add cyw4373 chip drivers source and header files
+if GetDepend(['WHD_USING_CHIP_CYW4373']):
+    src += Glob('wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4373/COMPONENT_MURATA-2AE/4373A0_clm_blob.c')
+    src += Glob('wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4373/4373A0_bin.c')
+    path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_4373/COMPONENT_MURATA-2AE']
+    path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_4373']
+    path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_4373/COMPONENT_MURATA-2AE']
+
+# add cyw43012 chip drivers source and header files
+if GetDepend(['WHD_USING_CHIP_CYW43012']):
+    src += Glob('wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43012/43012C0_clm_blob.c')
+    src += Glob('wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43012/43012C0_bin.c')
+    path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43012']
+    path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43012']
+    path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_43012/COMPONENT_CYSBSYS-RP01']
+
+# add cyw43439 chip drivers source and header files
+if GetDepend(['WHD_USING_CHIP_CYW43439']):
+    src += Glob('wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43439/43439A0_clm_blob.c')
+    src += Glob('wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43439/43439a0_bin.c')
+    path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43439']
+    path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43439']
+    path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_43439/COMPONENT_AZW-IFW56810']
+
+# add cyw43022 chip drivers source and header files
+if GetDepend(['WHD_USING_CHIP_CYW43022']):
+    src += Glob('wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43022/43022C1_clm_blob.c')
+    src += Glob('wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43022/COMPONENT_SM/43022C1_bin.c')
+    path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/resources/clm/COMPONENT_43022']
+    path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/resources/firmware/COMPONENT_43022/COMPONENT_SM']
+    path += [cwd + '/wifi-host-driver/WiFi_Host_Driver/resources/nvram/COMPONENT_43022/COMPONENT_CYW43022CUB']
+
+# add whd porting
+src += Glob('porting/src/*/*.c')
+
+path += [cwd + '/porting/inc/bsp']
+path += [cwd + '/porting/inc/hal']
+path += [cwd + '/porting/inc/rtos']
+
+
+CPPDEFINES = ['']
+
+group = DefineGroup('whd', src, depend = ['RT_USING_WHD'], CPPPATH = path, CPPDEFINES = CPPDEFINES)
+
+Return('group')

+ 88 - 0
porting/inc/bsp/cybsp.h

@@ -0,0 +1,88 @@
+/***************************************************************************//**
+* \file cybsp.h
+*
+* \brief
+* Basic API for setting up specific boards
+*
+********************************************************************************
+* \copyright
+* Copyright 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 "rtconfig.h"
+#include "cybsp_types.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define WHD_USE_CUSTOM_MALLOC_IMPL
+
+
+#ifdef CYBSP_HOST_WAKE_IRQ_EVENT_FALL
+#define CYBSP_HOST_WAKE_IRQ_EVENT                       CYHAL_GPIO_IRQ_FALL
+#endif
+
+#ifdef CYBSP_HOST_WAKE_IRQ_EVENT_RISE
+#define CYBSP_HOST_WAKE_IRQ_EVENT                       CYHAL_GPIO_IRQ_RISE
+#endif
+
+#ifdef CYBSP_HOST_WAKE_IRQ_EVENT_BOTH
+#define CYBSP_HOST_WAKE_IRQ_EVENT                       CYHAL_GPIO_IRQ_BOTH
+#endif
+
+
+#define CYBSP_WIFI_INTERFACE_TYPE                       CYBSP_SDIO_INTERFACE
+#define CYHAL_SDIO_MANUFACTURER                         0x02D0
+
+#ifdef WHD_USING_CHIP_CYW4343W
+#define CYHAL_SDIO_DRIVER_ID                            43430
+#define CYHAL_SDIO_DRIVER_NAME                          "cyw4343W"
+#endif
+
+#ifdef WHD_USING_CHIP_CYW43438
+#define CYHAL_SDIO_DRIVER_ID                            43430
+#define CYHAL_SDIO_DRIVER_NAME                          "cyw43438"
+#endif
+
+#ifdef WHD_USING_CHIP_CYW4373
+#define CYHAL_SDIO_DRIVER_ID                            0x4373
+#define CYHAL_SDIO_DRIVER_NAME                          "cyw4373"
+#endif
+
+#ifdef WHD_USING_CHIP_CYW43012
+#define CYHAL_SDIO_DRIVER_ID                            43012
+#define CYHAL_SDIO_DRIVER_NAME                          "cyw43012"
+#endif
+
+#ifdef WHD_USING_CHIP_CYW43439
+#define CYHAL_SDIO_DRIVER_ID                            43439
+#define CYHAL_SDIO_DRIVER_NAME                          "cyw43439"
+#endif
+
+#ifdef WHD_USING_CHIP_CYW43022
+#define CYHAL_SDIO_DRIVER_ID                            43022
+#define CYHAL_SDIO_DRIVER_NAME                          "cyw43022"
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+

+ 41 - 0
porting/inc/bsp/cybsp_types.h

@@ -0,0 +1,41 @@
+/***************************************************************************//**
+* \file cybsp.h
+*
+* \brief
+* Basic API for setting up specific boards
+*
+********************************************************************************
+* \copyright
+* Copyright 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
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* WIFI interface types */
+#define CYBSP_SDIO_INTERFACE             (0)
+#define CYBSP_SPI_INTERFACE              (1)
+#define CYBSP_M2M_INTERFACE              (2)
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+

+ 135 - 0
porting/inc/hal/cy_result.h

@@ -0,0 +1,135 @@
+/***************************************************************************//**
+* \file cy_result.h
+*
+* \brief
+* Basic function result handling. Defines a simple type for conveying
+* information about whether something succeeded or details about any issues
+* that were detected.
+*
+********************************************************************************
+* \copyright
+* Copyright 2018-2019 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_result Result Type
+ * \ingroup group_abstraction
+ * \{
+ * Basic function result handling. Defines a simple type for conveying
+ * information about whether something succeeded or details about any issues
+ * that were detected.
+ *
+ * \defgroup group_result_macros Macros
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/**
+ * \addtogroup group_result_macros
+ * \{
+ */
+
+/** Mask for the bit at position "x" */
+#define CY_BIT_MASK(x)                     ( (1U << (x) ) - 1U )
+
+/** Bit position of the result code */
+#define CY_RSLT_CODE_POSITION              (0U)
+/** Bit width of the result code */
+#define CY_RSLT_CODE_WIDTH                 (16U)
+/** Bit position of the result type */
+#define CY_RSLT_TYPE_POSITION              (16U)
+/** Bit width of the result type */
+#define CY_RSLT_TYPE_WIDTH                 (2U)
+/** Bit position of the module identifier */
+#define CY_RSLT_MODULE_POSITION            (18U)
+/** Bit width of the module identifier */
+#define CY_RSLT_MODULE_WIDTH               (14U)
+
+/** Mask for the result code */
+#define CY_RSLT_CODE_MASK                  CY_BIT_MASK(CY_RSLT_CODE_WIDTH)
+/** Mask for the module identifier */
+#define CY_RSLT_MODULE_MASK                CY_BIT_MASK(CY_RSLT_MODULE_WIDTH)
+/** Mask for the result type */
+#define CY_RSLT_TYPE_MASK                  CY_BIT_MASK(CY_RSLT_TYPE_WIDTH)
+
+/** Informational-only result status */
+#define CY_RSLT_TYPE_INFO                  (0U)
+/** Warning result */
+#define CY_RSLT_TYPE_WARNING               (1U)
+/** Error result */
+#define CY_RSLT_TYPE_ERROR                 (2U)
+/** Fatal error result */
+#define CY_RSLT_TYPE_FATAL                 (3U)
+
+/** Get the value of the result code field */
+#define CY_RSLT_GET_CODE(x)                ( ( (x) >> CY_RSLT_CODE_POSITION ) & CY_RSLT_CODE_MASK )
+/** Get the value of the result type field */
+#define CY_RSLT_GET_TYPE(x)                ( ( (x) >> CY_RSLT_TYPE_POSITION ) & CY_RSLT_TYPE_MASK )
+/** Get the value of the module identifier field */
+#define CY_RSLT_GET_MODULE(x)              ( ( (x) >> CY_RSLT_MODULE_POSITION ) & CY_RSLT_MODULE_MASK )
+
+
+/**** DRIVER Module codes: 0x0000 - 0x00FF ****/
+/** Base identifier for peripheral driver library */
+#define CY_RSLT_MODULE_DRIVERS_PDL_BASE           (0x0000U)
+/** Base identifier for peripheral driver library */
+#define CY_RSLT_MODULE_DRIVERS_WHD_BASE           (0x0080U)
+
+/**** ABSTRACTION Module codes: 0x0100 - 0x01FF ****/
+/** Base identifier for chip support modules */
+#define CY_RSLT_MODULE_ABSTRACTION_HAL_BASE       (0x0100U)
+/** Base identifier for board support modules */
+#define CY_RSLT_MODULE_ABSTRACTION_BSP            (0x0180U)
+/** Base identifier for file system modules */
+#define CY_RSLT_MODULE_ABSTRACTION_FS             (0x0181U)
+/** Base identifier for resource abstraction modules */
+#define CY_RSLT_MODULE_ABSTRACTION_RESOURCE       (0x0182U)
+/** Base identifier for rtos abstraction modules */
+#define CY_RSLT_MODULE_ABSTRACTION_OS             (0x0183U)
+/** Base identifier for environment abstraction modules */
+#define CY_RSLT_MODULE_ABSTRACTION_ENV            (0x0184U)
+
+/**** Middleware Module codes: 0x0200 - 0x02FF ****/
+#define CY_RSLT_MODULE_MIDDLEWARE_BASE            (0x0200U)
+
+
+
+/** Provides the result of an operation as a structured bitfield */
+typedef uint32_t cy_rslt_t;
+
+/** Result value indicating success */
+#define CY_RSLT_SUCCESS                    ( (cy_rslt_t)0x00000000U )
+
+/** Create a result value from the specified type, module, and result code */
+#define CY_RSLT_CREATE(type, module, code) \
+    ( ( ( (module) & CY_RSLT_MODULE_MASK ) << CY_RSLT_MODULE_POSITION ) | \
+      ( ( (code) & CY_RSLT_CODE_MASK ) << CY_RSLT_CODE_POSITION ) | \
+      ( ( (type) & CY_RSLT_TYPE_MASK ) << CY_RSLT_TYPE_POSITION ) )
+
+/** \} group_result_macros */
+
+#ifdef __cplusplus
+}
+#endif
+
+/** \} group_result */
+

+ 400 - 0
porting/inc/hal/cyhal_dma.h

@@ -0,0 +1,400 @@
+/***************************************************************************//**
+* \file cyhal_dma.h
+*
+* \brief
+* Provides a high level interface for interacting with the Infineon DMA.
+* This interface abstracts out the chip specific details. If any chip specific
+* functionality is necessary, or performance is critical the low level functions
+* can be used directly.
+*
+********************************************************************************
+* \copyright
+* Copyright 2018-2021 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 <stdbool.h>
+#include <stdint.h>
+#include "cy_result.h"
+#include "cyhal_hw_types.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/**
+ * \}
+ */
+
+/** Direction for DMA transfers. */
+typedef enum
+{
+    CYHAL_DMA_DIRECTION_MEM2MEM,       //!< Memory to memory
+    CYHAL_DMA_DIRECTION_MEM2PERIPH,    //!< Memory to peripheral
+    CYHAL_DMA_DIRECTION_PERIPH2MEM,    //!< Peripheral to memory
+    CYHAL_DMA_DIRECTION_PERIPH2PERIPH, //!< Peripheral to peripheral
+} cyhal_dma_direction_t;
+
+/** Flags enum of DMA events. Multiple events can be enabled via \ref cyhal_m2m_enable_event and
+ * the callback from \ref cyhal_m2m_register_callback will be run to notify. */
+typedef enum
+{
+    CYHAL_DMA_NO_INTR             = 0,      //!< No interrupt
+    CYHAL_DMA_TRANSFER_COMPLETE   = 1 << 0, /**< Indicates that an individual transfer (burst or
+                                                 full) has completed based on the specified \ref
+                                                 cyhal_dma_transfer_action_t */
+    CYHAL_DMA_DESCRIPTOR_COMPLETE = 1 << 1, //!< Indicates that the full transfer has completed
+    CYHAL_DMA_SRC_BUS_ERROR       = 1 << 2, //!< Indicates that there is a source bus error
+    CYHAL_DMA_DST_BUS_ERROR       = 1 << 3, //!< Indicates that there is a destination bus error
+    CYHAL_DMA_SRC_MISAL           = 1 << 4, //!< Indicates that the source address is not aligned
+    CYHAL_DMA_DST_MISAL           = 1 << 5, //!< Indicates that the destination address is not aligned
+    CYHAL_DMA_CURR_PTR_NULL       = 1 << 6, //!< Indicates that the current descriptor pointer is null
+    CYHAL_DMA_ACTIVE_CH_DISABLED  = 1 << 7, //!< Indicates that the active channel is disabled
+    CYHAL_DMA_DESCR_BUS_ERROR     = 1 << 8, //!< Indicates that there has been a descriptor bus error
+} cyhal_m2m_event_t;
+
+/** Specifies the transfer type to trigger when an input signal is received. */
+typedef enum
+{
+    CYHAL_DMA_INPUT_TRIGGER_SINGLE_ELEMENT, //!< Transfer a single element when an input signal is received
+    CYHAL_DMA_INPUT_TRIGGER_SINGLE_BURST,   //!< Transfer a single burst when an input signal is received
+    CYHAL_DMA_INPUT_TRIGGER_ALL_ELEMENTS,   //!< Transfer all elements when an input signal is received
+} cyhal_dma_input_t;
+
+/** Specifies the transfer completion event that triggers a signal output. */
+typedef enum
+{
+    CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_ELEMENT, //!< Trigger an output when a single element is transferred
+    CYHAL_DMA_OUTPUT_TRIGGER_SINGLE_BURST,   //!< Trigger an output when a single burst is transferred
+    CYHAL_DMA_OUTPUT_TRIGGER_ALL_ELEMENTS,   //!< Trigger an output when all elements are transferred
+} cyhal_dma_output_t;
+
+typedef enum
+{
+    /** A single burst is triggered and a \ref CYHAL_DMA_TRANSFER_COMPLETE will occur after
+     * each burst. The channel will be left enabled and can continue to be triggered. */
+    CYHAL_DMA_TRANSFER_BURST,
+    /** All bursts are triggered and a single \ref CYHAL_DMA_TRANSFER_COMPLETE will occur at
+     * the end. The channel will be left enabled and can continue to be triggered. */
+    CYHAL_DMA_TRANSFER_FULL,
+    /** A single burst is triggered and a \ref CYHAL_DMA_TRANSFER_COMPLETE will occur after
+     * each burst. When all bursts are complete, the channel will be disabled. */
+    CYHAL_DMA_TRANSFER_BURST_DISABLE,
+    /** All bursts are triggered and a single \ref CYHAL_DMA_TRANSFER_COMPLETE will occur at
+     * the end. When complete, the channel will be disabled. */
+    CYHAL_DMA_TRANSFER_FULL_DISABLE,
+} cyhal_dma_transfer_action_t;
+
+/** \brief Configuration of a DMA channel. When configuring address,
+ * increments, and transfer width keep in mind your hardware may have more
+ * stringent address and data alignment requirements. */
+typedef struct
+{
+    uint32_t src_addr;                  //!< Source address
+    int16_t src_increment;              //!< Source address auto increment amount in multiples of transfer_width
+    uint32_t dst_addr;                  //!< Destination address
+    int16_t dst_increment;              //!< Destination address auto increment amount in multiples of transfer_width
+    uint8_t transfer_width;             //!< Transfer width in bits. Valid values are: 8, 16, or 32
+    uint32_t length;                    //!< Number of elements to be transferred in total
+    uint32_t burst_size;                //!< Number of elements to be transferred per trigger. If set to 0 every element is transferred, otherwise burst_size must evenly divide length.
+    cyhal_dma_transfer_action_t action; //!< Sets the behavior of the channel when triggered (using start_transfer). Ignored if burst_size is not configured.
+} cyhal_dma_cfg_t;
+
+/** Event handler for DMA interrupts */
+typedef void (*cyhal_dma_event_callback_t)(void *callback_arg, cyhal_m2m_event_t event);
+
+/** Generic trigger source defined for devices that do not support trigger mux. */
+typedef uint32_t cyhal_source_t;
+
+/** Generic trigger destination defined for devices that do not support trigger mux. */
+typedef uint32_t cyhal_dest_t;
+
+/** DMA input connection information to setup while initializing the driver. */
+typedef struct
+{
+    cyhal_source_t source;      //!< Source of signal to DMA; obtained from another driver's cyhal_<PERIPH>_enable_output
+    cyhal_dma_input_t input;    //!< DMA input signal to be driven
+} cyhal_dma_src_t;
+
+/** DMA output connection information to setup while initializing the driver. */
+typedef struct
+{
+    cyhal_dma_output_t output;  //!< Output signal of DMA
+    cyhal_dest_t dest;          //!< Destination of DMA signal
+} cyhal_dma_dest_t;
+
+/** Initialize the DMA peripheral.
+ *
+ * If a source signal is provided for \p src, this will connect the provided signal to the DMA
+ * just as would be done by calling \ref cyhal_dma_connect_digital. Similarly, if a destination
+ * target is provided for \p dest this will enable the specified output just as would be done
+ * by calling \ref cyhal_dma_enable_output.
+ * @param[out] obj  Pointer to a DMA object. The caller must allocate the memory
+ *  for this object but the init function will initialize its contents.
+ * @param[in]  src          An optional source signal to connect to the DMA
+ * @param[in]  dest         An optional destination singal to drive from the DMA
+ * @param[out] dest_source  An optional pointer to user-allocated source signal object which
+ * will be initialized by enable_output. If \p dest is non-null, this must also be non-null.
+ * \p dest_source should be passed to (dis)connect_digital functions to (dis)connect the
+ * associated endpoints.
+ * @param[in]  priority     The priority of this DMA operation relative to others. The number of
+ * priority levels which are supported is hardware dependent. All implementations define a
+ * #CYHAL_DMA_PRIORITY_DEFAULT constant which is always valid. If supported, implementations will
+ * also define #CYHAL_DMA_PRIORITY_HIGH, #CYHAL_DMA_PRIORITY_MEDIUM, and #CYHAL_DMA_PRIORITY_LOW.
+ * The behavior of any other value is implementation defined. See the implementation-specific DMA
+ * documentation for more details.
+ * @param[in]  direction    The direction memory is copied
+ * @return The status of the init request
+ */
+cy_rslt_t cyhal_dma_init_adv(cyhal_dma_t *obj, cyhal_dma_src_t *src, cyhal_dma_dest_t *dest,
+                             cyhal_source_t *dest_source, uint8_t priority, cyhal_dma_direction_t direction);
+
+/** Initialize the DMA peripheral.
+ *
+ * @param[out] obj          Pointer to a DMA object. The caller must allocate the memory for this
+ * object but the init function will initialize its contents.
+ * @param[in]  priority     The priority of this DMA operation relative to others. The number of
+ * priority levels which are supported is hardware dependent. All implementations define a
+ * #CYHAL_DMA_PRIORITY_DEFAULT constant which is always valid. If supported, implementations will
+ * also define #CYHAL_DMA_PRIORITY_HIGH, #CYHAL_DMA_PRIORITY_MEDIUM, and #CYHAL_DMA_PRIORITY_LOW.
+ * The behavior of any other value is implementation defined. See the implementation-specific DMA
+ * documentation for more details.
+ * @param[in]  direction    The direction memory is copied
+ * @return The status of the init request
+ */
+#define cyhal_m2m_init(obj, priority, direction)    (cyhal_dma_init_adv(obj, NULL, NULL, NULL, priority, direction) )
+
+/** Free the DMA object. Freeing a DMA object while a transfer is in progress
+ * (\ref cyhal_m2m_is_busy) is invalid.
+ *
+ * @param[in,out] obj The DMA object
+ */
+void cyhal_m2m_free(cyhal_dma_t *obj);
+
+/** Setup the DMA channel behavior. This will also enable the channel to allow it to be triggered.
+ * The transfer can be software triggered by calling \ref cyhal_dma_start_transfer or by hardware.
+ * A hardware input signal is setup by \ref cyhal_dma_connect_digital or \ref cyhal_dma_init_adv.
+ * \note If hardware triggers are used, any necessary event callback setup (\ref
+ * cyhal_m2m_register_callback and \ref cyhal_m2m_enable_event) should be done before calling
+ * this function to ensure the handlers are in place before the transfer can happen.
+ * \note The automatic enablement of the channel as part of this function is expected to change
+ * in a future update. This would only happen on a new major release (eg: 1.0 -> 2.0).
+ *
+ * @param[in] obj    The DMA object
+ * @param[in] cfg    Configuration parameters for the transfer
+ * @return The status of the configure request
+ */
+cy_rslt_t cyhal_dma_configure(cyhal_dma_t *obj, const cyhal_dma_cfg_t *cfg);
+
+/** Enable the DMA transfer so that it can start transferring data when triggered. A trigger is
+ * caused either by calling \ref cyhal_dma_start_transfer or by hardware as a result of a connection
+ * made in either \ref cyhal_dma_connect_digital or \ref cyhal_dma_init_adv. The DMA can be disabled
+ * by calling \ref cyhal_dma_disable or by setting the \ref cyhal_dma_cfg_t action to \ref
+ * CYHAL_DMA_TRANSFER_BURST_DISABLE, or \ref CYHAL_DMA_TRANSFER_FULL_DISABLE.
+ *
+ * @param[in] obj    The DMA object
+ * @return The status of the enable request
+ */
+cy_rslt_t cyhal_dma_enable(cyhal_dma_t *obj);
+
+/** Disable the DMA transfer so that it does not continue to trigger. It can be reenabled by calling
+ * \ref cyhal_dma_enable or \ref cyhal_dma_configure.
+ *
+ * @param[in] obj    The DMA object
+ * @return The status of the enable request
+ */
+cy_rslt_t cyhal_dma_disable(cyhal_dma_t *obj);
+
+/** Initiates DMA channel transfer for specified DMA object. This should only be done after the
+ * channel has been configured (\ref cyhal_dma_configure) and any necessary event callbacks setup
+ * (\ref cyhal_m2m_register_callback \ref cyhal_m2m_enable_event)
+ *
+ * @param[in] obj    The DMA object
+ * @return The status of the start_transfer request
+ */
+cy_rslt_t cyhal_dma_start_transfer(cyhal_dma_t *obj);
+
+/** Checks if the transfer has been triggered, but not yet complete (eg: is pending, blocked or running)
+ *
+ * @param[in] obj    The DMA object
+ * @return True if DMA channel is busy
+ */
+bool cyhal_m2m_is_busy(cyhal_dma_t *obj);
+
+/** Register a DMA callback handler.
+ *
+ * This function will be called when one of the events enabled by \ref cyhal_m2m_enable_event occurs.
+ *
+ * @param[in] obj          The DMA object
+ * @param[in] callback     The callback handler which will be invoked when an event triggers
+ * @param[in] callback_arg Generic argument that will be provided to the callback when called
+ */
+void cyhal_m2m_register_callback(cyhal_dma_t *obj, cyhal_dma_event_callback_t callback, void *callback_arg);
+
+/** Configure DMA event enablement.
+ *
+ * When an enabled event occurs, the function specified by \ref cyhal_m2m_register_callback will be called.
+ *
+ * @param[in] obj            The DMA object
+ * @param[in] event          The DMA event type
+ * @param[in] intr_priority  The priority for NVIC interrupt events. The priority from the most
+ * recent call will take precedence, i.e all events will have the same priority.
+ * @param[in] enable         True to turn on interrupts, False to turn off
+ */
+void cyhal_m2m_enable_event(cyhal_dma_t *obj, cyhal_m2m_event_t event, uint8_t intr_priority, bool enable);
+
+/** Connects a source signal and enables the specified input to the DMA channel. This connection
+ * can also be setup automatically on initialization via \ref cyhal_dma_init_adv. If the signal
+ * needs to be disconnected later, \ref cyhal_dma_disconnect_digital can be used.
+ *
+ * @param[in] obj         The DMA object
+ * @param[in] source      Source signal obtained from another driver's cyhal_<PERIPH>_enable_output
+ * @param[in] input       Which input to enable
+ * @return The status of the connection
+ */
+cy_rslt_t cyhal_dma_connect_digital(cyhal_dma_t *obj, cyhal_source_t source, cyhal_dma_input_t input);
+
+/** Enables the specified output signal from a DMA channel that is triggered when a transfer is
+ * completed. This can also be setup automatically on initialization via \ref cyhal_dma_init_adv.
+ * If the output is not needed in the future, \ref cyhal_dma_disable_output can be used.
+ *
+ * @param[in]  obj         The DMA object
+ * @param[in]  output      Which event triggers the output
+ * @param[out] source      Pointer to user-allocated source signal object which
+ * will be initialized by enable_output. \p source should be passed to
+ * (dis)connect_digital functions to (dis)connect the associated endpoints.
+ * @return The status of the output enable
+ */
+cy_rslt_t cyhal_dma_enable_output(cyhal_dma_t *obj, cyhal_dma_output_t output, cyhal_source_t *source);
+
+/** Disconnects a source signal and disables the specified input to the DMA channel. This removes
+ * the connection that was established by either \ref cyhal_dma_init_adv or \ref
+ * cyhal_dma_connect_digital.
+ *
+ * @param[in] obj         The DMA object
+ * @param[in] source      Source signal from cyhal_<PERIPH>_enable_output to disable
+ * @param[in] input       Which input to disable
+ * @return The status of the disconnect
+ */
+cy_rslt_t cyhal_dma_disconnect_digital(cyhal_dma_t *obj, cyhal_source_t source, cyhal_dma_input_t input);
+
+/** Disables the specified output signal from a DMA channel. This turns off the signal that was
+ * enabled by either \ref cyhal_dma_init_adv or \ref cyhal_dma_enable_output. It is recommended
+ * that the signal is disconnected (cyhal_<PERIPH>_disconnect_digital) from anything it might be
+ * driving before being disabled.
+ *
+ * @param[in]  obj         The DMA object
+ * @param[in]  output      Which output to disable
+ * @return The status of the disablement
+ * */
+cy_rslt_t cyhal_dma_disable_output(cyhal_dma_t *obj, cyhal_dma_output_t output);
+
+//cyhal_dma_impl.h ++
+/** M2M DMA group */
+typedef enum
+{
+    _CYHAL_M2M_GRP_WWD,     //!< Group used for WWD
+    _CYHAL_M2M_GRP_USR_1,   //!< User group 1
+    _CYHAL_M2M_GRP_USR_2    //!< User group 2
+} _cyhal_m2m_group_t;
+
+
+/** WHD M2M reinitialization for setting RX_buffer_size.
+ *
+ * Function for WHD to reinitialize the DMA with a different RX buffer size.
+ * @param[in] obj  Pointer to a DMA object. The caller must allocate the memory
+ *  for this object but the init function will initialize its contents.
+ * @param[in]  rx_buffer_size Size of the RX buffer.
+ */
+void _cyhal_m2m_reinit_dma(cyhal_dma_t *obj, uint32_t rx_buffer_size);
+
+/** WHD M2M packet-based DMA TX data.
+ *
+ * Port of m2m_dma_tx_data() referenced by wwd_bus_protocol.c in WICED.
+ * @param[in] obj  Pointer to a DMA object. The caller must allocate the memory
+ *  for this object but the init function will initialize its contents.
+ * @param[in]  buffer Data buffer to be used in the packet DMA transaction.
+ * @return The status of the tx operation.
+ */
+int cyhal_m2m_tx_send(cyhal_dma_t *obj, void *buffer);
+
+/** WHD M2M packet-based DMA reclaim next completed TXD
+ *
+ * Port of m2m_dma_tx_reclaim() referenced by wwd_bus_protocol.c in WICED.
+ * @param[in] obj  Pointer to a DMA object. The caller must allocate the memory
+ *  for this object but the init function will initialize its contents.
+ */
+void cyhal_m2m_tx_release(cyhal_dma_t *obj);
+
+/** WHD M2M packet-based DMA read DMA packet
+ *
+ * Port of m2m_read_dma_packet() referenced by wwd_bus_protocol.c in WICED.
+ * @param[in] obj  Pointer to a DMA object. The caller must allocate the memory
+ *  for this object but the init function will initialize its contents.
+ * @param[out] packet packet pointer
+ * @param[out] hwtag  Hardware tag
+ * @return DMA packet pointer
+ */
+void *cyhal_m2m_rx_receive(cyhal_dma_t *obj, void *packet, uint16_t **hwtag);
+
+/** WHD M2M packet-based DMA refill RX
+ *
+ * Port of m2m_refill_dma() referenced by wwd_bus_protocol.c in WICED.
+ * @param[in] obj  Pointer to a DMA object. The caller must allocate the memory
+ *  for this object but the init function will initialize its contents.
+ * @return DMA refilled (true) or failed (false)
+ */
+bool cyhal_m2m_rx_prepare(cyhal_dma_t *obj);
+
+/** WHD M2M packet-based DMA RX active status
+ *
+ * Port of m2m_rxactive_dma() referenced by wwd_bus_protocol.c in WICED.
+ * @param[in] obj  Pointer to a DMA object. The caller must allocate the memory
+ *  for this object but the init function will initialize its contents.
+ * @return RX active status
+ */
+int cyhal_m2m_rx_status(cyhal_dma_t *obj);
+
+uint32_t cyhal_m2m_intr_status(cyhal_dma_t *obj, bool *signal_txdone);
+
+//cyhal_dma_impl.h ++
+
+
+//cyhal_system_impl.h ++
+void _cyhal_system_timer_enable_irq(void);
+
+/* Disable external interrupts from M2M_ExtIRQn to APPS Core */
+void _cyhal_system_m2m_disable_irq(void);
+
+/* Enable external interrupts from M2M_ExtIRQn to APPS Core */
+void _cyhal_system_m2m_enable_irq(void);
+
+/* Disable external interrupts from SW0_ExtIRQn to APPS Core */
+void _cyhal_system_sw0_disable_irq(void);
+
+/* Enable external interrupts from SW0_ExtIRQn to APPS Core */
+void _cyhal_system_sw0_enable_irq(void);
+
+//cyhal_system_impl.h ++
+
+#if defined(__cplusplus)
+}
+#endif
+
+/** \} group_hal_dma */
+

+ 185 - 0
porting/inc/hal/cyhal_gpio.h

@@ -0,0 +1,185 @@
+/***************************************************************************//**
+* \file cyhal_gpio.h
+*
+* \brief
+* Provides a high level interface for interacting with the Cypress GPIO.
+* This interface abstracts out the chip specific details. If any chip specific
+* functionality is necessary, or performance is critical the low level functions
+* can be used directly.
+*
+********************************************************************************
+* \copyright
+* Copyright 2018-2019 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_hal_gpio GPIO (General Purpose Input Output)
+ * \ingroup group_hal
+ * \{
+ * High level interface for interacting with the Cypress GPIO.
+ *
+ * \defgroup group_hal_gpio_macros Macros
+ * \defgroup group_hal_gpio_functions Functions
+ * \defgroup group_hal_gpio_data_structures Data Structures
+ * \defgroup group_hal_gpio_enums Enumerated Types
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "cy_result.h"
+#include "cyhal_hw_types.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* __cplusplus */
+
+/*******************************************************************************
+*       Defines
+*******************************************************************************/
+
+/**
+ * \addtogroup group_hal_gpio_macros
+ * \{
+ */
+
+/** Integer representation of no connect pin (required to exist in all BSPs) */
+#define CYHAL_NC_PIN_VALUE ( (cyhal_gpio_t)0xFFFFFFFF )
+
+/** \} group_hal_gpio_macros */
+
+
+/**
+ * \addtogroup group_hal_gpio_enums
+ * \{
+ */
+
+/*******************************************************************************
+*       Enumerations
+*******************************************************************************/
+
+/** Pin IRQ events */
+typedef enum
+{
+    CYHAL_GPIO_IRQ_NONE = 0,   /**< No interrupt */
+    CYHAL_GPIO_IRQ_RISE = 1,   /**< Interrupt on rising edge */
+    CYHAL_GPIO_IRQ_FALL = 2,   /**< Interrupt on falling edge */
+    CYHAL_GPIO_IRQ_BOTH = 3,   /**< Interrupt on both rising and falling edges */
+} cyhal_gpio_irq_event_t;
+
+/** Pin direction */
+typedef enum
+{
+    CYHAL_GPIO_DIR_INPUT         = 0,  /**< Input pin */
+    CYHAL_GPIO_DIR_OUTPUT        = 1,  /**< Output pin */
+    CYHAL_GPIO_DIR_BIDIRECTIONAL = 2,   /**< Input and output pin */
+} cyhal_gpio_direction_t;
+
+/** Pin drive mode */
+typedef enum
+{
+    CYHAL_GPIO_DRIVE_NONE                = 0, /**< No drive; Hi-Z */
+    CYHAL_GPIO_DRIVE_ANALOG              = 0, /**< Analog Hi-Z */
+    CYHAL_GPIO_DRIVE_PULLUP              = 2, /**< Pull-up resistor */
+    CYHAL_GPIO_DRIVE_PULLDOWN            = 3, /**< Pull-down resistor */
+    CYHAL_GPIO_DRIVE_OPENDRAINDRIVESLOW  = 4, /**< Open-drain, Drives Low */
+    CYHAL_GPIO_DRIVE_OPENDRAINDRIVESHIGH = 5, /**< Open-drain, Drives High */
+    CYHAL_GPIO_DRIVE_STRONG              = 6, /**< Strong output */
+    CYHAL_GPIO_DRIVE_PULLUPDOWN          = 7, /**< Pull-up and pull-down resistors */
+} cyhal_gpio_drive_mode_t;
+
+/** \} group_hal_gpio_enums */
+
+
+/**
+ * \addtogroup group_hal_gpio_data_structures
+ * \{
+ */
+
+/** GPIO callback function type */
+typedef void (*cyhal_gpio_irq_handler_t)(void *handler_arg, cyhal_gpio_irq_event_t event);
+
+/** \} group_hal_gpio_data_structures */
+
+
+/**
+ * \addtogroup group_hal_gpio_functions
+ * \{
+ */
+
+/*******************************************************************************
+*       Functions
+*******************************************************************************/
+
+/** Initialize the GPIO pin
+ *
+ * @param[in]  pin The GPIO pin to initialize
+ * @param[in]  direction The pin direction (input/output)
+ * @param[in]  drvMode The pin drive mode
+ * @param[in]  initVal Initial value on the pin
+ *
+ * @return The status of the init request
+ */
+cy_rslt_t cyhal_gpio_init(cyhal_gpio_t pin, cyhal_gpio_direction_t direction, cyhal_gpio_drive_mode_t drvMode,
+                          bool initVal);
+
+/** Uninitialize the gpio peripheral and the cyhal_gpio_t object
+ *
+ * @param[in] pin Pin number
+ */
+void cyhal_gpio_free(cyhal_gpio_t pin);
+
+/** Set the output value for the pin. This only works for output & in_out pins.
+ *
+ * @param[in] pin   The GPIO object
+ * @param[in] value The value to be set (high = true, low = false)
+ */
+void cyhal_gpio_write(cyhal_gpio_t pin, bool value);
+
+/** Read the input value.  This only works for input & in_out pins.
+ *
+ * @param[in]  pin   The GPIO object
+ * @return The value of the IO (true = high, false = low)
+ */
+bool cyhal_gpio_read(cyhal_gpio_t pin);
+
+/** Register/clear an interrupt handler for the pin toggle pin IRQ event
+ *
+ * @param[in] pin           The pin number
+ * @param[in] intrPriority  The NVIC interrupt channel priority
+ * @param[in] handler       The function to call when the specified event happens. Pass NULL to unregister the handler.
+ * @param[in] handler_arg   Generic argument that will be provided to the handler when called, can be NULL
+ */
+void cyhal_gpio_register_irq(cyhal_gpio_t pin, uint8_t intrPriority, cyhal_gpio_irq_handler_t handler,
+                             void *handler_arg);
+
+/** Enable or Disable the GPIO IRQ
+ *
+ * @param[in] pin    The GPIO object
+ * @param[in] event  The GPIO IRQ event
+ * @param[in] enable True to turn on interrupts, False to turn off
+ */
+void cyhal_gpio_irq_enable(cyhal_gpio_t pin, cyhal_gpio_irq_event_t event, bool enable);
+
+/** \} group_hal_gpio_functions */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+/** \} group_hal_gpio */
+

+ 96 - 0
porting/inc/hal/cyhal_hw_types.h

@@ -0,0 +1,96 @@
+/***************************************************************************//**
+* \file cyhal_hw_types_template.h
+*
+* \brief
+* Provides a template for configuration resources used by the HAL. Items
+* here need to be implemented for each HAL port. It is up to the environment
+* being ported into what the actual types are. There are some suggestions below
+* but these are not required. All that is required is that the type is defined;
+* it does not matter to the HAL what type is actually chosen for the
+* implementation
+* All TODOs and references to 'PORT' need to be replaced by with meaningful
+* values for the device being supported.
+*
+********************************************************************************
+* \copyright
+* Copyright 2018-2019 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_hal_hw_types PORT Hardware Types
+ * \ingroup group_hal_PORT
+ * \{
+ * Struct definitions for configuration resources in the PORT.
+ *
+ * \defgroup group_hal_hw_types_data_structures Data Structures
+ */
+
+#pragma once
+
+/*
+ #include "TODO: Port specific header file"
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "rtthread.h"
+
+/**
+ * \addtogroup group_hal_hw_types_data_structures
+ * \{
+ */
+
+/** GPIO object */
+typedef rt_base_t cyhal_gpio_t;
+
+/** Clock divider object */
+typedef struct
+{
+    /* TODO: replace with port specific items */
+    void *div_type;
+} cyhal_clock_divider_t;
+
+/** SDIO object */
+typedef struct
+{
+    struct rt_mmcsd_card *card;
+    struct rt_sdio_device_id *dev_id;
+} cyhal_sdio_t;
+
+/** SPI object */
+typedef struct
+{
+    /* TODO: replace with port specific items */
+    void *empty;
+} cyhal_spi_t;
+
+/** M2M/DMA object */
+typedef struct
+{
+    /* TODO: replace with port specific items */
+    void *empty;
+} cyhal_m2m_t;
+
+/** \} group_hal_hw_types_data_structures */
+
+#if defined(__cplusplus)
+}
+#endif /* __cplusplus */
+
+/** \} group_hal_hw_types */
+

+ 86 - 0
porting/inc/hal/cyhal_modules.h

@@ -0,0 +1,86 @@
+/***************************************************************************//**
+* \file cyhal_modules.h
+*
+* \brief
+* Provides an enum of all HAL modules types that can be used for generating
+* custom cy_rslt_t items.
+*
+********************************************************************************
+* \copyright
+* Copyright 2018-2019 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_hal_modules Driver Modules
+ * \ingroup group_hal
+ * \{
+ * Enum definition for all HAL resource modules.
+ *
+ * \defgroup group_hal_modules_enums Enumerated Types
+ */
+
+#pragma once
+
+#include "cy_result.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * \addtogroup group_hal_modules_enums
+ * \{
+ */
+
+/** Enum to in indicate which module an errors occurred in. */
+enum cyhal_rslt_module_chip
+{
+    CYHAL_RSLT_MODULE_CHIP_HWMGR = CY_RSLT_MODULE_ABSTRACTION_HAL_BASE, //!< An error occurred in hardware management module
+    CYHAL_RSLT_MODULE_ADC,                                              //!< An error occurred in ADC module
+    CYHAL_RSLT_MODULE_COMP,                                             //!< An error occurred in comparator module
+    CYHAL_RSLT_MODULE_CRC,                                              //!< An error occurred in crypto CRC module
+    CYHAL_RSLT_MODULE_DAC,                                              //!< An error occurred in DAC module
+    CYHAL_RSLT_MODULE_DMA,                                              //!< An error occurred in DMA module
+    CYHAL_RSLT_MODULE_FLASH,                                            //!< An error occurred in flash module
+    CYHAL_RSLT_MODULE_GPIO,                                             //!< An error occurred in GPIO module
+    CYHAL_RSLT_MODULE_I2C,                                              //!< An error occurred in I2C module
+    CYHAL_RSLT_MODULE_I2S,                                              //!< An error occurred in I2S module
+    CYHAL_RSLT_MODULE_INTERCONNECT,                                     //!< An error occurred in Interconnct module
+    CYHAL_RSLT_MODULE_OPAMP,                                            //!< An error occurred in OpAmp module
+    CYHAL_RSLT_MODULE_PDMPCM,                                           //!< An error occurred in PDM/PCM module
+    CYHAL_RSLT_MODULE_PWM,                                              //!< An error occurred in PWM module
+    CYHAL_RSLT_MODULE_QSPI,                                             //!< An error occurred in QSPI module
+    CYHAL_RSLT_MODULE_RTC,                                              //!< An error occurred in RTC module
+    CYHAL_RSLT_MODULE_SDHC,                                             //!< An error occurred in SDHC module
+    CYHAL_RSLT_MODULE_SDIO,                                             //!< An error occurred in SDIO module
+    CYHAL_RSLT_MODULE_SPI,                                              //!< An error occurred in SPI module
+    CYHAL_RSLT_MODULE_SYSTEM,                                           //!< An error occurred in System module
+    CYHAL_RSLT_MODULE_TIMER,                                            //!< An error occurred in Timer module
+    CYHAL_RSLT_MODULE_TRNG,                                             //!< An error occurred in RNG module
+    CYHAL_RSLT_MODULE_UART,                                             //!< An error occurred in UART module
+    CYHAL_RSLT_MODULE_USB,                                              //!< An error occurred in USB module
+    CYHAL_RSLT_MODULE_WDT,                                              //!< An error occurred in WDT module
+};
+
+/** \} group_hal_modules_enums */
+
+#if defined(__cplusplus)
+}
+#endif /* __cplusplus */
+
+/** \} group_hal_modules */
+

+ 313 - 0
porting/inc/hal/cyhal_sdio.h

@@ -0,0 +1,313 @@
+/***************************************************************************//**
+* \file cyhal_sdio.h
+*
+* \brief
+* Provides a high level interface for interacting with the Cypress SDIO interface.
+* This interface abstracts out the chip specific details. If any chip specific
+* functionality is necessary, or performance is critical the low level functions
+* can be used directly.
+*
+********************************************************************************
+* \copyright
+* Copyright 2018-2019 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_hal_sdio SDIO (Secure Digital Input Output)
+ * \ingroup group_hal
+ * \{
+ * High level interface for interacting with the Cypress SDIO interface.
+ *
+ * \defgroup group_hal_sdio_macros Macros
+ * \defgroup group_hal_sdio_functions Functions
+ * \defgroup group_hal_sdio_data_structures Data Structures
+ * \defgroup group_hal_sdio_enums Enumerated Types
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "cy_result.h"
+#include "cyhal_hw_types.h"
+#include "cyhal_modules.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/**
+ * \addtogroup group_hal_sdio_macros
+ * \{
+ */
+
+#define CYHAL_SDIO_RET_NO_ERRORS           (0x00)     /**< No error*/
+#define CYHAL_SDIO_RET_NO_SP_ERRORS        (0x01)     /**< Non-specific error code*/
+#define CYHAL_SDIO_RET_CMD_CRC_ERROR       (0x02)     /**< There was a CRC error on the Command/Response*/
+#define CYHAL_SDIO_RET_CMD_IDX_ERROR       (0x04)     /**< The index for the command didn't match*/
+#define CYHAL_SDIO_RET_CMD_EB_ERROR        (0x08)     /**< There was an end bit error on the command*/
+#define CYHAL_SDIO_RET_DAT_CRC_ERROR       (0x10)     /**< There was a data CRC Error*/
+#define CYHAL_SDIO_RET_CMD_TIMEOUT         (0x20)     /**< The command didn't finish before the timeout period was over*/
+#define CYHAL_SDIO_RET_DAT_TIMEOUT         (0x40)     /**< The data didn't finish before the timeout period was over*/
+#define CYHAL_SDIO_RET_RESP_FLAG_ERROR     (0x80)      /**< There was an error in the resposne flag for command 53*/
+
+#define CYHAL_SDIO_CLOCK_ERROR          (0x100)   /**< Failed to initial clock for SDIO */
+#define CYHAL_SDIO_BAD_ARGUMENT         (0x200)   /**< Bad argument passed for SDIO */
+#define CYHAL_SDIO_SEMA_NOT_INITED      (0x400)   /**< Semaphore is not initiated */
+#define CYHAL_SDIO_FUNC_NOT_SUPPORTED   (0x800)   /**< Function is not supported */
+
+/* HAL return value defines */
+
+/** Incorrect parameter value define */
+#define CYHAL_SDIO_RSLT_ERR_BAD_PARAM          CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, \
+                                                              CYHAL_RSLT_MODULE_SDIO, \
+                                                              CYHAL_SDIO_BAD_ARGUMENT)
+
+/** Clock initialization error define */
+#define CYHAL_SDIO_RSLT_ERR_CLOCK             CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, \
+                                                             CYHAL_RSLT_MODULE_SDIO, \
+                                                             CYHAL_SDIO_CLOCK_ERROR)
+
+/** Semaphore not initiated error define */
+#define CYHAL_SDIO_RSLT_ERR_SEMA_NOT_INITED   CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, \
+                                                             CYHAL_RSLT_MODULE_SDIO, \
+                                                             CYHAL_SDIO_SEMA_NOT_INITED)
+
+/** Error define based on SDIO lower function return value */
+#define CYHAL_SDIO_RSLT_ERR_FUNC_RET(retVal)  CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, \
+                                                             CYHAL_RSLT_MODULE_SDIO, (retVal) )
+
+/** \} group_hal_sdio_macros */
+
+/* Configure the sdio clock frequency */
+
+#define SDIO_CLOCK_FREQ_CONFIG              (0)
+
+#if SDIO_CLOCK_FREQ_CONFIG
+// This bit determines the direction of the I/O operation. If this bit is 0, this command shall read
+// data from the SDIO
+#define SDIO_CMD52_ARG_RW_READ              (0)
+#define SDIO_CMD52_ARG_RW_WRITE             (1)
+// The Read after Write flag. If this bit is set to 1 and the R/W flag is set to 1, then the command
+// shall read the value of the register after the write
+#define SDIO_CMD52_ARG_RAW_NOT_SET          (0)
+#define SDIO_CMD52_ARG_RAW_SET              (1)
+// The number of the function within the I/O card you wish to read or write. Function 0 selects the
+// common I/O area (CIA)
+#define SDIO_FUNC_NUM_0                     (0)
+
+// Per SDIO Specification -Card Common Control Registers (CCCR)
+
+// Bus Speed Select register
+#define SDIO_CMD52_CCCR_SPEED_SLCT_ADDR     (0x00013)
+// Select High Speed by setting BSS0 bit
+#define SDIO_CMD52_CCCR_SPEED_SLCT_HS       (0x2)
+
+// Per SDIO specification - IO_RW_DIRECT Response (R5)
+
+// | Start | Dir | CMD Index | Stuff | Response Flags Bit | Read or Write Data | CRC7 | End |
+// ------------------------------------------------------------------------------------------
+// |   1   |  1  |     6     |  16   |          8         |         8          |  7   |  1  |
+
+// Expected response for High Speed support check command
+//                                   | CMD=DAT lines free | High-Speed support |
+//                                   |     00010000b      |     00000001b      |
+#define SDIO_CMD52_CCCR_SPEED_SELECT_RESP_HS_SUPPORTED  (0x00001001)
+// Expected response for High Speed support check command
+//                                   | CMD=DAT lines free | HS/SDR25 activated |
+//                                   |     00010000b      |     00000010b      |
+#define SDIO_CMD52_CCCR_SPEED_SELECT_RESP_HS_SELECTED   (0x00001002)
+
+#endif /* SDIO_CLOCK_FREQ_CONFIG */
+
+/**
+ * \addtogroup group_hal_sdio_enums
+ * \{
+ */
+
+/** Commands that can be issued */
+typedef enum
+{
+    CYHAL_SDIO_CMD_GO_IDLE_STATE  =  0, //!> Go to idle state
+    CYHAL_SDIO_CMD_SEND_RELATIVE_ADDR  =  3, //!> Send a relative address
+    CYHAL_SDIO_CMD_IO_SEND_OP_COND  =  5, //!> Send an OP IO
+    CYHAL_SDIO_CMD_SELECT_CARD  =  7, //!> Send a card select
+    CYHAL_SDIO_CMD_GO_INACTIVE_STATE = 15, //!> Go to inactive state
+    CYHAL_SDIO_CMD_IO_RW_DIRECT = 52, //!> Perform a direct read/write
+    CYHAL_SDIO_CMD_IO_RW_EXTENDED = 53, //!> Perform an extended read/write
+} cyhal_sdio_command_t;
+
+/** Types of transfer that can be performed */
+typedef enum
+{
+    CYHAL_READ, //!> Read from the card
+    CYHAL_WRITE //!> Write to the card
+} cyhal_transfer_t;
+
+/** Events that can cause an SDIO interrupt */
+typedef enum
+{
+    CYHAL_SDIO_CMD_COMPLETE   = 0x0001, //!> Command Complete
+    CYHAL_SDIO_XFER_COMPLETE  = 0x0002, //!> Host read/write transfer is complete
+    CYHAL_SDIO_BGAP_EVENT     = 0x0004, //!> This bit is set when both read/write transaction is stopped
+    CYHAL_SDIO_DMA_INTERRUPT  = 0x0008, //!> Host controller detects an SDMA Buffer Boundary during transfer
+    CYHAL_SDIO_BUF_WR_READY   = 0x0010, //!> This bit is set if the Buffer Write Enable changes from 0 to 1
+    CYHAL_SDIO_BUF_RD_READY   = 0x0020, //!> This bit is set if the Buffer Read Enable changes from 0 to 1
+    CYHAL_SDIO_CARD_INSERTION = 0x0040, //!> This bit is set if the Card Inserted in the Present State
+    CYHAL_SDIO_CARD_REMOVAL   = 0x0080, //!> This bit is set if the Card Inserted in the Present State
+    CYHAL_SDIO_CARD_INTERRUPT = 0x0100, //!> The synchronized value of the DAT[1] interrupt input for SD mode
+    CYHAL_SDIO_INT_A          = 0x0200, //!> Reserved: set to 0
+    CYHAL_SDIO_INT_B          = 0x0400, //!> Reserved: set to 0
+    CYHAL_SDIO_INT_C          = 0x0800, //!> Reserved: set to 0,
+    CYHAL_SDIO_RE_TUNE_EVENT  = 0x1000, //!> Reserved: set to 0,
+    CYHAL_SDIO_FX_EVENT       = 0x2000, //!> This status is set when R[14] of response register is set to 1
+    CYHAL_SDIO_CQE_EVENT      = 0x4000, //!> This status is set if Command Queuing/Crypto event has occurred
+    CYHAL_SDIO_ERR_INTERRUPT  = 0x8000, //!> If any of the bits in the Error Interrupt Status register are set
+    CYHAL_SDIO_ALL_INTERRUPTS = 0xE1FF, //!> Is used to enable/disable all interrupts
+} cyhal_sdio_irq_event_t;
+
+/** \} group_hal_sdio_enums */
+
+
+/**
+ * \addtogroup group_hal_sdio_data_structures
+ * \{
+ */
+
+/** SDIO controller initial configuration */
+typedef struct
+{
+    uint32_t frequencyhal_hz; //!< Clock frequency, in hertz
+    uint16_t block_size; //!< Block size
+} cyhal_sdio_cfg_t;
+
+/** Handler for SDIO interrupts */
+typedef void (*cyhal_sdio_irq_handler_t)(void *handler_arg, cyhal_sdio_irq_event_t event);
+
+/** \} group_hal_sdio_data_structures */
+
+
+/**
+ * \addtogroup group_hal_sdio_functions
+ * \{
+ */
+
+/** Initialize the SDIO peripheral
+ *
+ * @param[out] obj               The SDIO object
+ * @param[out] clk               The pin connected to the clk signal
+ * @param[in]  cmd               The pin connected to the command signal
+ * @param[in]  data0             The pin connected to the data0 signal
+ * @param[in]  data1             The pin connected to the data1 signal
+ * @param[in]  data2             The pin connected to the data2 signal
+ * @param[in]  data3             The pin connected to the data3 signal
+ * @return The status of the init request
+ */
+cy_rslt_t cyhal_sdio_init(cyhal_sdio_t *obj);
+
+/** Release the SDIO peripheral, not currently invoked. It requires further
+ *  resource management.
+ *
+ * @param[in,out] obj The SDIO object
+ */
+void cyhal_sdio_free(cyhal_sdio_t *obj);
+
+/** Configure the SDIO block.
+ *
+ * @param[in,out] obj    The SDIO object
+ * @param[in]     config The sdio configuration to apply
+ * @return The status of the configure request
+ */
+cy_rslt_t cyhal_sdio_configure(cyhal_sdio_t *obj, const cyhal_sdio_cfg_t *config);
+
+/** Sends a command to the SDIO block.
+ *
+ * @param[in,out] obj       The SDIO object
+ * @param[in]     direction The direction of transfer (read/write)
+ * @param[in]     command   The SDIO command to send
+ * @param[in]     argument  The argument to the command
+ * @param[out]    response  The response from the SDIO device
+ * @return The status of the configure request
+ */
+cy_rslt_t cyhal_sdio_send_cmd(const cyhal_sdio_t *obj, cyhal_transfer_t direction, cyhal_sdio_command_t command,
+                              uint32_t argument, uint32_t *response);
+
+/** Performs a bulk data transfer (CMD=53) to the SDIO block.
+ *
+ * @param[in,out] obj       The SDIO object
+ * @param[in]     direction The direction of transfer (read/write)
+ * @param[in]     argument  The argument to the command
+ * @param[in]     data      The data to send to the SDIO device. The data buffer
+ *                          should be aligned to the block size (64 bytes) if data
+ *                          size is greater that block size (64 bytes).
+ * @param[in]     length    The number of bytes to send
+ * @param[out]    response  The response from the SDIO device
+ * @return The status of the configure request
+ */
+cy_rslt_t cyhal_sdio_bulk_transfer(cyhal_sdio_t *obj, cyhal_transfer_t direction, uint32_t argument,
+                                   const uint32_t *data, uint16_t length, uint32_t *response);
+
+/** Performs a bulk asynchronus data transfer (CMD=53) to the SDIO block.
+ *
+ * @param[in,out] obj       The SDIO object
+ * @param[in]     direction The direction of transfer (read/write)
+ * @param[in]     argument  The argument to the command
+ * @param[in]     data      The data to send to the SDIO device
+ * @param[in]     length    The number of bytes to send
+ * @return The status of the configure request
+ */
+cy_rslt_t cyhal_sdio_transfer_async(cyhal_sdio_t *obj, cyhal_transfer_t direction, uint32_t argument,
+                                    const uint32_t *data, uint16_t length);
+
+/** Checks if the specified SDIO is in use
+ *
+ * @param[in]  obj  The SDIO peripheral to check
+ * @return Indication of whether the SDIO is still transmitting
+ */
+bool cyhal_sdio_is_busy(const cyhal_sdio_t *obj);
+
+/** Abort an SDIO transfer
+ *
+ * @param[in] obj The SDIO peripheral to stop
+ * @return The status of the abort_async request
+ */
+cy_rslt_t cyhal_sdio_abort_async(const cyhal_sdio_t *obj);
+
+/** The sdio interrupt handler registration
+ *
+ * @param[in] obj         The SDIO object
+ * @param[in] handler     The callback handler which will be invoked when the interrupt fires
+ * @param[in] handler_arg Generic argument that will be provided to the handler when called
+ */
+void cyhal_sdio_register_irq(cyhal_sdio_t *obj, cyhal_sdio_irq_handler_t handler, void *handler_arg);
+
+/** Configure sdio interrupt.
+ *
+ * @param[in] obj      The SDIO object
+ * @param[in] event    The sdio IRQ type
+ * @param[in] enable   Set to non-zero to enable events, or zero to disable them
+ */
+void cyhal_sdio_irq_enable(cyhal_sdio_t *obj, cyhal_sdio_irq_event_t event, bool enable);
+
+/** \} group_hal_sdio_functions */
+
+#if defined(__cplusplus)
+}
+#endif
+
+/** \} group_hal_sdio */
+

+ 250 - 0
porting/inc/hal/cyhal_spi.h

@@ -0,0 +1,250 @@
+/***************************************************************************//**
+* \file cyhal_spi.h
+*
+* \brief
+* Provides a high level interface for interacting with the Cypress SPI.
+* This interface abstracts out the chip specific details. If any chip specific
+* functionality is necessary, or performance is critical the low level functions
+* can be used directly.
+*
+********************************************************************************
+* \copyright
+* Copyright 2018-2019 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_hal_spi SPI (Serial Peripheral Interface)
+ * \ingroup group_hal
+ * \{
+ * High level interface for interacting with the Cypress SPI.
+ *
+ * \defgroup group_hal_spi_macros Macros
+ * \defgroup group_hal_spi_functions Functions
+ * \defgroup group_hal_spi_data_structures Data Structures
+ * \defgroup group_hal_spi_enums Enumerated Types
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "cy_result.h"
+#include "cyhal_hw_types.h"
+#include "cyhal_modules.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/**
+ * \addtogroup group_hal_spi_macros
+ * \{
+ */
+
+/** Bad argument */
+#define CYHAL_SPI_RSLT_BAD_ARGUMENT                    (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 0) )
+/** Failed to initialize SPI clock */
+#define CYHAL_SPI_RSLT_CLOCK_ERROR                     (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 1) )
+/** Failed to Transfer SPI data */
+#define CYHAL_SPI_RSLT_TRANSFER_ERROR                  (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 2) )
+/** Provided clock is not supported by SPI */
+#define CYHAL_SPI_RSLT_CLOCK_NOT_SUPPORTED             (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 3) )
+/** Provided PIN configuration is not supported by SPI */
+#define CYHAL_SPI_RSLT_PIN_CONFIG_NOT_SUPPORTED        (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 5) )
+/** Provided PIN configuration is not supported by SPI */
+#define CYHAL_SPI_RSLT_INVALID_PIN_API_NOT_SUPPORTED   (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 6) )
+/** The requested resource type is invalid */
+#define CYHAL_SPI_RSLT_ERR_INVALID_PIN                 (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_SPI, 7) )
+
+/** \} group_hal_spi_macros */
+
+
+/** SPI interrupt triggers */
+typedef enum
+{
+    CYHAL_SPI_IRQ_NONE                = 0,      //!< Disable all interrupt call backs
+    /** All transfer data has been moved into data FIFO */
+    CYHAL_SPI_IRQ_DATA_IN_FIFO        = 1 << 1,
+    /** Transfer complete. */
+    CYHAL_SPI_IRQ_DONE                = 1 << 2,
+    /** An error occurred while transferring data */
+    CYHAL_SPI_IRQ_ERROR               = 1 << 3,
+} cyhal_spi_irq_event_t;
+
+/** Handler for SPI interrupts */
+typedef void (*cyhal_spi_irq_handler_t)(void *handler_arg, cyhal_spi_irq_event_t event);
+
+/** SPI operating modes */
+typedef enum
+{
+    /** Standard motorola SPI CPOL=0, CPHA=0 with MSB first operation */
+    CYHAL_SPI_MODE_00_MSB,
+    /** Standard motorola SPI CPOL=0, CPHA=0 with LSB first operation */
+    CYHAL_SPI_MODE_00_LSB,
+    /** Standard motorola SPI CPOL=0, CPHA=1 with MSB first operation */
+    CYHAL_SPI_MODE_01_MSB,
+    /** Standard motorola SPI CPOL=0, CPHA=1 with LSB first operation */
+    CYHAL_SPI_MODE_01_LSB,
+    /** Standard motorola SPI CPOL=1, CPHA=0 with MSB first operation */
+    CYHAL_SPI_MODE_10_MSB,
+    /** Standard motorola SPI CPOL=1, CPHA=0 with LSB first operation */
+    CYHAL_SPI_MODE_10_LSB,
+    /** Standard motorola SPI CPOL=1, CPHA=1 with MSB first operation */
+    CYHAL_SPI_MODE_11_MSB,
+    /** Standard motorola SPI CPOL=1, CPHA=1 with LSB first operation */
+    CYHAL_SPI_MODE_11_LSB,
+} cyhal_spi_mode_t;
+
+/** Initial SPI configuration. */
+typedef struct
+{
+    cyhal_spi_mode_t mode; //!< The operating mode
+    uint8_t data_bits; //!< The number of bits per transfer
+    bool is_slave; //!< Whether the peripheral is operating as slave or master
+} cyhal_spi_cfg_t;
+
+
+/** Initialize the SPI peripheral
+ *
+ * Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral
+ * @param[out] obj  The SPI object to initialize
+ * @param[in]  mosi The pin to use for MOSI
+ * @note At least MOSI or MISO pin should be non-NC
+ * @param[in]  miso The pin to use for MISO
+ * @note At least MOSI or MISO pin should be non-NC
+ * @param[in]  sclk The pin to use for SCLK
+ * @note This pin cannot be NC
+ * @param[in]  ssel The pin to use for SSEL
+ * @note This pin can be NC
+ * @param[in]  clk The clock to use can be shared, if not provided a new clock will be allocated
+ * @param[in]  bits      The number of bits per frame
+ * @note bits should be 8 or 16
+ * @param[in]  mode      The SPI mode (clock polarity, phase, and shift direction)
+ * @param[in]  is_slave  false for master mode or true for slave mode operation
+ * @return The status of the init request
+ */
+cy_rslt_t cyhal_spi_init(cyhal_spi_t *obj, cyhal_gpio_t mosi, cyhal_gpio_t miso, cyhal_gpio_t sclk, cyhal_gpio_t ssel,
+                         const cyhal_clock_divider_t *clk,
+                         uint8_t bits, cyhal_spi_mode_t mode, bool is_slave);
+
+/** Release a SPI object
+ *
+ * Return the peripheral, pins and clock owned by the SPI object to their reset state
+ * @param[in,out] obj The SPI object to deinitialize
+ */
+void cyhal_spi_free(cyhal_spi_t *obj);
+
+/** Set the SPI baud rate
+ *
+ * Actual frequency may differ from the desired frequency due to available dividers and bus clock
+ * Configures the SPI peripheral's baud rate
+ * @param[in,out] obj The SPI object to configure
+ * @param[in]     hz  The baud rate in Hz
+ * @return The status of the frequency request
+ */
+cy_rslt_t cyhal_spi_frequency(cyhal_spi_t *obj, uint32_t hz);
+
+/** Get a received value out of the SPI receive buffer
+ *
+ * Blocks until a value is available
+ * @param[in] obj   The SPI peripheral to read
+ * @param[in] value The value received
+ * @return The status of the read request
+ * @note
+ * - In Master mode, MISO pin required to be non-NC for this API to operate
+ * - In Slave mode, MOSI pin required to be non-NC for this API to operate
+ */
+cy_rslt_t cyhal_spi_read(cyhal_spi_t *obj, uint32_t *value);
+
+/** Write a byte out
+ *
+ * @param[in] obj   The SPI peripheral to use for sending
+ * @param[in] value The value to send
+ * @return The status of the write request
+ * @note
+ * - In Master mode, MOSI pin required to be non-NC for this API to operate
+ * - In Slave mode, MISO pin required to be non-NC for this API to operate
+ */
+cy_rslt_t cyhal_spi_write(cyhal_spi_t *obj, uint32_t value);
+
+/** Write a block out and receive a value
+ *
+ *  The total number of bytes sent and received will be the maximum of
+ *  tx_length and rx_length. The bytes written will be padded with the
+ *  value 0xff.
+ *
+ * @param[in] obj           The SPI peripheral to use for sending
+ * @param[in] tx            Pointer to the byte-array of data to write to the device
+ * @param[in,out] tx_length Number of bytes to write, updated with the number actually written
+ * @param[out] rx           Pointer to the byte-array of data to read from the device
+ * @param[in,out] rx_length Number of bytes to read, udpated with the number actually read
+ * @param[in] write_fill    Default data transmitted while performing a read
+ * @return The status of the transfer request
+ * @note Both MOSI and MISO pins required to be non-NC for this API to operate
+ */
+cy_rslt_t cyhal_spi_transfer(cyhal_spi_t *obj, const uint8_t *tx, size_t tx_length, uint8_t *rx, size_t rx_length,
+                             uint8_t write_fill);
+
+/** Begin the SPI transfer. Buffer pointers and lengths are specified in tx_buff and rx_buff
+ *
+ * @param[in] obj           The SPI object that holds the transfer information
+ * @param[in] tx            The transmit buffer
+ * @param[in,out] tx_length The number of bytes to transmit
+ * @param[out] rx           The receive buffer
+ * @param[in,out] rx_length The number of bytes to receive
+ * @return The status of the transfer_async request
+ * @note Both MOSI and MISO pins required to be non-NC for this API to operate
+ */
+cy_rslt_t cyhal_spi_transfer_async(cyhal_spi_t *obj, const uint8_t *tx, size_t tx_length, uint8_t *rx,
+                                   size_t rx_length);
+
+/** Checks if the specified SPI peripheral is in use
+ *
+ * @param[in] obj  The SPI peripheral to check
+ * @return Indication of whether the SPI is still transmitting
+ */
+bool cyhal_spi_is_busy(cyhal_spi_t *obj);
+
+/** Abort an SPI transfer
+ *
+ * @param[in] obj The SPI peripheral to stop
+ * @return The status of the abort_async request
+ */
+cy_rslt_t cyhal_spi_abort_async(cyhal_spi_t *obj);
+
+/** The SPI interrupt handler registration
+ *
+ * @param[in] obj         The SPI object
+ * @param[in] handler     The callback handler which will be invoked when the interrupt fires
+ * @param[in] handler_arg Generic argument that will be provided to the handler when called
+ */
+void cyhal_spi_register_irq(cyhal_spi_t *obj, cyhal_spi_irq_handler_t handler, void *handler_arg);
+
+/** Configure SPI interrupt. This function is used for word-approach
+ *
+ * @param[in] obj      The SPI object
+ * @param[in] event    The SPI IRQ type
+ * @param[in] enable   True to turn on interrupts, False to turn off
+ */
+void cyhal_spi_irq_enable(cyhal_spi_t *obj, cyhal_spi_irq_event_t event, bool enable);
+
+/** \} group_hal_spi_functions */
+
+#if defined(__cplusplus)
+}
+#endif
+

+ 368 - 0
porting/inc/rtos/cyabs_rtos.h

@@ -0,0 +1,368 @@
+/***************************************************************************//**
+* \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-2019 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.
+*******************************************************************************/
+
+#ifndef INCLUDED_CY_RTOS_INTERFACE_H_
+#define INCLUDED_CY_RTOS_INTERFACE_H_
+
+#include "cyabs_rtos_impl.h"
+#include <cy_result.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+/*
+ * Note, cyabs_rtos_impl.h above is included and is the implementation 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_time_t                : count of time in milliseconds
+ * cy_rtos_error_t          : typedef from the underlying RTOS error type *
+ *
+ */
+
+
+/**
+ * \addtogroup group_abstraction_rtos RTOS abstraction
+ * \ingroup group_abstraction
+ * \{
+ * Basic abstraction layer for dealing with RTOSes.
+ *
+ * \defgroup group_abstraction_rtos_macros Macros
+ * \defgroup group_abstraction_rtos_enums Enums
+ * \defgroup group_abstraction_rtos_data_structures Data Structures
+ * \defgroup group_abstraction_rtos_functions Functions
+ */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*********************************************** CONSTANTS **********************************************/
+
+/**
+ * \addtogroup group_abstraction_rtos_macros
+ * \{
+ */
+
+/** 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 CY_RTOS_GENERAL_ERROR can be
+// returns and cy_rtos_last_error() used to retrieve the RTOS specific error message.
+//
+/** Requested operationd 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)
+/** 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)
+/** 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)
+
+/** \} group_abstraction_rtos_macros */
+
+
+/*********************************************** TYPES **********************************************/
+
+/**
+ * \addtogroup group_abstraction_rtos_data_structures
+ * \{
+ */
+
+/**
+ * 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
+ */
+typedef void (*cy_thread_entry_fn_t)(cy_thread_arg_t arg);
+
+/** \} group_abstraction_rtos_data_structures */
+
+
+/**
+ * \addtogroup group_abstraction_rtos_functions
+ * \{
+ */
+
+/*********************************************** 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
+ * cy_rtos_finish_thread() just before doing so. All created threds that can terminate, either
+ * by themselves or forcefully by another thread MUST be joined 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
+ * @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. [CY_RSLT_SUCCESS, CY_RTOS_NO_MEMORY, CY_RTOS_GENERAL_ERROR]
+ */
+extern 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 (cy_rtos_join_thread) to ensure their resources are fully
+ * cleaned up.
+ *
+ * @return The status of thread exit request. [CY_RSLT_SUCCESS, CY_RTOS_GENERAL_ERROR]
+ */
+extern cy_rslt_t cy_rtos_exit_thread(void);
+
+/** Terminates another thread.
+ *
+ * This function is called to terminate another thread and reap the resoruces claimed
+ * by it 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 resoruces 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 (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. [CY_RSLT_SUCCESS, CY_RTOS_GENERAL_ERROR]
+ */
+extern cy_rslt_t cy_rtos_terminate_thread(cy_thread_t *thread);
+
+/** Checks if the thread is running
+ *
+ * This function is called to determine if a thread is running or not.
+ *
+ * @param[in] thread     handle of the terminated thread to delete
+ * @param[out] state     returns true if the thread is running, otherwise false
+ *
+ * @returns The status of the thread check. [CY_RSLT_SUCCESS, CY_RTOS_GENERAL_ERROR]
+ */
+extern cy_rslt_t cy_rtos_is_thread_running(cy_thread_t *thread, bool *state);
+
+/** 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. [CY_RSLT_SUCCESS, CY_RTOS_GENERAL_ERROR]
+ */
+extern cy_rslt_t cy_rtos_join_thread(cy_thread_t *thread);
+
+/*********************************************** Semaphores **********************************************/
+
+/**
+ * Create a semaphore
+ *
+ * This is basically a counting semaphore.
+ *
+ * @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 sempahore
+ *
+ * @return The status of the sempahore creation. [CY_RSLT_SUCCESS, CY_RTOS_NO_MEMORY, CY_RTOS_GENERAL_ERROR]
+ */
+extern 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 NEVER_TIMEOUT constant to wait forever. Must
+ *                        be zero is 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 [CY_RSLT_SUCCESS, CY_RTOS_NO_MEMORY, CY_RTOS_GENERAL_ERROR]
+ */
+extern 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 [CY_RSLT_SUCCESS, CY_RTOS_NO_MEMORY, CY_RTOS_GENERAL_ERROR]
+ */
+extern cy_rslt_t cy_rtos_set_semaphore(cy_semaphore_t *semaphore, bool in_isr);
+
+/**
+ * Deletes a sempahore
+ *
+ * This function frees the resources associated with a sempahore.
+ *
+ * @param[in] semaphore   Pointer to the sempahore handle
+ *
+ * @return The status of semaphore deletion [CY_RSLT_SUCCESS, CY_RTOS_NO_MEMORY, CY_RTOS_GENERAL_ERROR]
+ */
+extern cy_rslt_t cy_rtos_deinit_semaphore(cy_semaphore_t *semaphore);
+
+/*********************************************** Events **********************************************/
+
+/** 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.
+ *         [CY_RSLT_SUCCESS, CY_RTOS_NO_MEMORY, CY_RTOS_GENERAL_ERROR]
+ */
+extern 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. [CY_RSLT_SUCCESS, CY_RTOS_NO_MEMORY, CY_RTOS_GENERAL_ERROR]
+ */
+extern 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. [CY_RSLT_SUCCESS, CY_RTOS_NO_MEMORY, CY_RTOS_GENERAL_ERROR]
+ */
+extern 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. [CY_RSLT_SUCCESS, CY_RTOS_NO_MEMORY, CY_RTOS_GENERAL_ERROR]
+ */
+extern 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 assocaited
+ * 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   The amount of time to wait in milliseconds
+ *
+ * @return The status of the wait for event request. [CY_RSLT_SUCCESS, CY_RTOS_NO_MEMORY, CY_RTOS_GENERAL_ERROR]
+ */
+extern cy_rslt_t cy_rtos_waitbits_event(cy_event_t *event, uint32_t *bits, bool clear, bool all, cy_time_t timeout) ;
+
+/** 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. [CY_RSLT_SUCCESS, CY_RTOS_GENERAL_ERROR]
+ */
+extern cy_rslt_t cy_rtos_deinit_event(cy_event_t *event) ;
+
+/*********************************************** 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.
+ */
+extern 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 miliseconds to delay for
+ *
+ * @return The status of the creation request. [CY_RSLT_SUCCESS, CY_RTOS_GENERAL_ERROR]
+ */
+extern cy_rslt_t cy_rtos_delay_milliseconds(cy_time_t num_ms);
+
+/** \} group_abstraction_rtos_functions */
+
+/** @} */
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+#endif /* ifndef INCLUDED_CY_RTOS_INTERFACE_H_ */
+

+ 56 - 0
porting/inc/rtos/cyabs_rtos_impl.h

@@ -0,0 +1,56 @@
+/***************************************************************************//**
+* \file cyabs_rtos_impl.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-2019 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 <stdint.h>
+#include <stdbool.h>
+#include "rtthread.h"
+
+/******************************************************
+*                 Constants
+******************************************************/
+#define CY_RTOS_MIN_STACK_SIZE      300            /**< Minimum stack size in bytes */
+
+
+/* RTOS thread priority */
+typedef enum
+{
+    CY_RTOS_PRIORITY_MIN            = RT_THREAD_PRIORITY_MAX,
+    CY_RTOS_PRIORITY_LOW            = (RT_THREAD_PRIORITY_MAX - 1),
+    CY_RTOS_PRIORITY_BELOWNORMAL    = (RT_THREAD_PRIORITY_MAX - 2),
+    CY_RTOS_PRIORITY_NORMAL         = (RT_THREAD_PRIORITY_MAX - 2),
+    CY_RTOS_PRIORITY_ABOVENORMAL    = (RT_THREAD_PRIORITY_MAX - 3),
+    CY_RTOS_PRIORITY_HIGH           = (RT_THREAD_PRIORITY_MAX - 4),
+    CY_RTOS_PRIORITY_REALTIME       = (RT_THREAD_PRIORITY_MAX - 5),
+    CY_RTOS_PRIORITY_MAX            = (RT_THREAD_PRIORITY_MAX - 6)
+} cy_thread_priority_t;
+
+typedef volatile rt_sem_t cy_semaphore_t;    /** RTOS definition of a semaphore */
+typedef volatile rt_thread_t cy_thread_t;       /** RTOS definition of a thread handle */
+typedef int32_t cy_rtos_error_t;                      /** RTOS definition of a error status */
+typedef uint32_t cy_time_t;
+typedef void * cy_thread_arg_t;
+typedef uint32_t cy_event_t;        /** RTOS definition of a event */
+

+ 107 - 0
porting/src/bsp/cy_network_buffer.c

@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2006-2023, Evlers Developers
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date         Author      Notes
+ * 2023-12-21   Evlers      first implementation
+ */
+
+#include "whd.h"
+#include "whd_network_types.h"
+#include "lwip/memp.h"
+#include "lwip/pbuf.h"
+
+#define  SDIO_BLOCK_SIZE (64U)
+
+
+whd_result_t cy_host_buffer_get(whd_buffer_t *buffer, whd_buffer_dir_t direction, uint16_t size,
+                                uint32_t timeout_ms)
+{
+    UNUSED_PARAMETER(direction);
+    struct pbuf *p = NULL;
+    if ( (direction == WHD_NETWORK_TX) && (size <= PBUF_POOL_BUFSIZE) )
+    {
+        p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL);
+    }
+    else
+    {
+        p = pbuf_alloc(PBUF_RAW, size + SDIO_BLOCK_SIZE, PBUF_RAM);
+        if (p != NULL)
+        {
+            p->len = size;
+            p->tot_len -=  SDIO_BLOCK_SIZE;
+        }
+    }
+    if (p != NULL)
+    {
+        *buffer = p;
+        return WHD_SUCCESS;
+    }
+    else
+    {
+        return WHD_BUFFER_ALLOC_FAIL;
+    }
+}
+
+void cy_buffer_release(whd_buffer_t buffer, whd_buffer_dir_t direction)
+{
+    UNUSED_PARAMETER(direction);
+    (void)pbuf_free( (struct pbuf *)buffer );
+}
+
+uint8_t *cy_buffer_get_current_piece_data_pointer(whd_buffer_t buffer)
+{
+    RT_ASSERT(buffer != NULL);
+    struct pbuf *pbuffer = (struct pbuf *)buffer;
+    return (uint8_t *)pbuffer->payload;
+}
+
+uint16_t cy_buffer_get_current_piece_size(whd_buffer_t buffer)
+{
+    RT_ASSERT(buffer != NULL);
+    struct pbuf *pbuffer = (struct pbuf *)buffer;
+    return (uint16_t)pbuffer->len;
+}
+
+whd_result_t cy_buffer_set_size(whd_buffer_t buffer, unsigned short size)
+{
+    RT_ASSERT(buffer != NULL);
+    struct pbuf *pbuffer = (struct pbuf *)buffer;
+
+    if (size >
+        (unsigned short)WHD_LINK_MTU  + LWIP_MEM_ALIGN_SIZE(LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf) ) ) +
+        LWIP_MEM_ALIGN_SIZE(size) )
+    {
+        return WHD_PMK_WRONG_LENGTH;
+    }
+
+    pbuffer->tot_len = size;
+    pbuffer->len = size;
+
+    return CY_RSLT_SUCCESS;
+}
+
+whd_result_t cy_buffer_add_remove_at_front(whd_buffer_t *buffer, int32_t add_remove_amount)
+{
+    RT_ASSERT(buffer != NULL);
+    struct pbuf **pbuffer = (struct pbuf **)buffer;
+
+    if ( (u8_t)0 != pbuf_header(*pbuffer, ( s16_t )(-add_remove_amount) ) )
+    {
+        return WHD_PMK_WRONG_LENGTH;
+    }
+
+    return WHD_SUCCESS;
+}
+
+struct whd_buffer_funcs whd_buffer_ops =
+{
+    .whd_buffer_add_remove_at_front = cy_buffer_add_remove_at_front,
+    .whd_buffer_get_current_piece_data_pointer = cy_buffer_get_current_piece_data_pointer,
+    .whd_buffer_get_current_piece_size = cy_buffer_get_current_piece_size,
+    .whd_buffer_release = cy_buffer_release,
+    .whd_buffer_set_size = cy_buffer_set_size,
+    .whd_host_buffer_get = cy_host_buffer_get,
+};

+ 26 - 0
porting/src/bsp/cybsp.c

@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2006-2023, Evlers Developers
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date         Author      Notes
+ * 2023-12-21   Evlers      first implementation
+ */
+
+#include "rtthread.h"
+#include "rtdevice.h"
+#include "drv_gpio.h"
+
+#include "cybsp.h"
+
+
+static int cybsp_init(void)
+{
+    /* enable the WLAN REG pin */
+    rt_pin_mode(CYBSP_REG_ON_PIN, PIN_MODE_OUTPUT);
+    rt_pin_write(CYBSP_REG_ON_PIN, PIN_HIGH);
+
+    return RT_EOK;
+}
+INIT_PREV_EXPORT(cybsp_init);

+ 221 - 0
porting/src/hal/cyhal_gpio.c

@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2006-2023, Evlers Developers
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date         Author      Notes
+ * 2023-12-21   Evlers      first implementation
+ */
+
+#include "cyhal_gpio.h"
+#include <rtdevice.h>
+#include "rthw.h"
+
+
+#define CYHAL_MAX_EXTI_NUMBER       (16U)
+
+/* Return pin number by counts the number of leading zeros of a data value.
+ * NOTE: __CLZ  returns  32 if no bits are set in the source register, and zero
+ * if bit 31 is set. Parameter 'pin' should be in range GPIO_PIN0..GPIO_PIN15. */
+#define CYHAL_GET_PIN_NUMBER(pin)   (uint32_t)(31u - __clz(pin))
+
+typedef struct
+{
+    cyhal_gpio_irq_handler_t    callback;
+    void*                       callback_args;
+    bool                        enable;
+    cyhal_gpio_t                pin;
+} cyhal_gpio_event_callback_info_t;
+
+static cyhal_gpio_event_callback_info_t _exti_callbacks_info[CYHAL_MAX_EXTI_NUMBER] = { 0u };
+
+
+/** Initialize the GPIO pin
+ *
+ * @param[in]  pin The GPIO pin to initialize
+ * @param[in]  direction The pin direction (input/output)
+ * @param[in]  drvMode The pin drive mode
+ * @param[in]  initVal Initial value on the pin
+ *
+ * @return The status of the init request
+ */
+cy_rslt_t cyhal_gpio_init(cyhal_gpio_t pin, cyhal_gpio_direction_t direction, cyhal_gpio_drive_mode_t drvMode,
+                          bool initVal)
+{
+    rt_uint8_t mode;
+
+    switch (drvMode)
+    {
+    case CYHAL_GPIO_DRIVE_NONE:
+            mode = PIN_MODE_INPUT;
+        break;
+
+    case CYHAL_GPIO_DRIVE_PULLUP:
+            mode = (direction == CYHAL_GPIO_DIR_INPUT) ? PIN_MODE_INPUT_PULLUP : PIN_MODE_OUTPUT;
+        break;
+
+    case CYHAL_GPIO_DRIVE_PULLDOWN:
+            mode = (direction == CYHAL_GPIO_DIR_INPUT) ? PIN_MODE_INPUT_PULLDOWN : PIN_MODE_OUTPUT;
+        break;
+
+    case CYHAL_GPIO_DRIVE_OPENDRAINDRIVESLOW:
+            mode = (direction == CYHAL_GPIO_DIR_INPUT) ? PIN_MODE_INPUT_PULLDOWN : PIN_MODE_OUTPUT_OD;
+        break;
+
+    case CYHAL_GPIO_DRIVE_OPENDRAINDRIVESHIGH:
+            mode = (direction == CYHAL_GPIO_DIR_INPUT) ? PIN_MODE_INPUT_PULLUP : PIN_MODE_OUTPUT_OD;
+        break;
+
+    case CYHAL_GPIO_DRIVE_STRONG:
+            mode = PIN_MODE_OUTPUT;
+        break;
+
+    case CYHAL_GPIO_DRIVE_PULLUPDOWN:
+            if ((direction == CYHAL_GPIO_DIR_OUTPUT) || (direction == CYHAL_GPIO_DIR_BIDIRECTIONAL))
+            {
+                mode = PIN_MODE_OUTPUT;
+            }
+            else
+            {
+                mode = PIN_MODE_INPUT_PULLUP;
+            }
+        break;
+    }
+
+    rt_pin_mode(pin, mode);
+    rt_pin_write(pin, initVal);
+
+    return CY_RSLT_SUCCESS;
+}
+
+/** Uninitialize the gpio peripheral and the cyhal_gpio_t object
+ *
+ * @param[in] pin Pin number
+ */
+void cyhal_gpio_free(cyhal_gpio_t pin)
+{
+    rt_pin_detach_irq(pin);
+    rt_pin_mode(pin, PIN_MODE_INPUT);
+}
+
+/** Set the output value for the pin. This only works for output & in_out pins.
+ *
+ * @param[in] pin   The GPIO object
+ * @param[in] value The value to be set (high = true, low = false)
+ */
+void cyhal_gpio_write(cyhal_gpio_t pin, bool value)
+{
+    rt_pin_write(pin, value);
+}
+
+/** Read the input value.  This only works for input & in_out pins.
+ *
+ * @param[in]  pin   The GPIO object
+ * @return The value of the IO (true = high, false = low)
+ */
+bool cyhal_gpio_read(cyhal_gpio_t pin)
+{
+    return rt_pin_read(pin) ? true : false;
+}
+
+
+static void gpio_interrupt(void *args)
+{
+    cyhal_gpio_event_callback_info_t *info = (cyhal_gpio_event_callback_info_t *)args;
+    uint32_t gpio_number = CYHAL_GET_PIN_NUMBER(info->pin);
+
+    /* Check the parameters */
+    RT_ASSERT(gpio_number < CYHAL_MAX_EXTI_NUMBER);
+
+    if ((gpio_number < CYHAL_MAX_EXTI_NUMBER) && (info->enable))
+    {
+        cyhal_gpio_irq_event_t event = (cyhal_gpio_read(info->pin) == true) ?
+                                   CYHAL_GPIO_IRQ_RISE : CYHAL_GPIO_IRQ_FALL;
+
+        /* Call user's callback */
+        info->callback(info->callback_args, event);
+    }
+}
+
+/** Register/clear an interrupt handler for the pin toggle pin IRQ event
+ *
+ * @param[in] pin           The pin number
+ * @param[in] intrPriority  The NVIC interrupt channel priority
+ * @param[in] handler       The function to call when the specified event happens. Pass NULL to unregister the handler.
+ * @param[in] handler_arg   Generic argument that will be provided to the handler when called, can be NULL
+ */
+void cyhal_gpio_register_irq(cyhal_gpio_t pin, uint8_t intrPriority, cyhal_gpio_irq_handler_t handler,
+                             void *handler_arg)
+{
+    /* Get pin number */
+    uint32_t pin_number = CYHAL_GET_PIN_NUMBER(pin);
+
+    if (pin_number < CYHAL_MAX_EXTI_NUMBER && handler != NULL)
+    {
+        rt_base_t level = rt_hw_interrupt_disable();
+        _exti_callbacks_info[pin_number].callback      = handler;
+        _exti_callbacks_info[pin_number].callback_args = handler_arg;
+        _exti_callbacks_info[pin_number].pin           = pin;
+        rt_hw_interrupt_enable(level);
+    }
+    else if (pin_number >= CYHAL_MAX_EXTI_NUMBER)
+    {
+        /* Wrong param */
+        RT_ASSERT(false);
+    }
+    else
+    {
+        /* Clean callback information */
+        uint32_t level = rt_hw_interrupt_disable();
+        _exti_callbacks_info[pin_number].callback      = NULL;
+        _exti_callbacks_info[pin_number].callback_args = NULL;
+        _exti_callbacks_info[pin_number].enable        = false;
+        _exti_callbacks_info[pin_number].pin           = 0xFFFFFFFF;
+        rt_hw_interrupt_enable(level);
+    }
+}
+
+/** Enable or Disable the GPIO IRQ
+ *
+ * @param[in] pin    The GPIO object
+ * @param[in] event  The GPIO IRQ event
+ * @param[in] enable True to turn on interrupts, False to turn off
+ */
+void cyhal_gpio_irq_enable(cyhal_gpio_t pin, cyhal_gpio_irq_event_t event, bool enable)
+{
+    /* Get pin number */
+    uint32_t pin_number = CYHAL_GET_PIN_NUMBER(pin);
+
+    if (enable)
+    {
+        rt_uint8_t mode;
+        switch(event)
+        {
+        case CYHAL_GPIO_IRQ_RISE:
+                mode = PIN_IRQ_MODE_RISING;
+            break;
+
+        case CYHAL_GPIO_IRQ_FALL:
+                mode = PIN_IRQ_MODE_FALLING;
+            break;
+
+        case CYHAL_GPIO_IRQ_BOTH:
+                mode = PIN_IRQ_MODE_RISING_FALLING;
+            break;
+
+        default:
+            break;
+        }
+
+        rt_pin_attach_irq(pin, mode, gpio_interrupt, &_exti_callbacks_info[pin_number]);
+        _exti_callbacks_info[pin_number].enable = true;
+        rt_pin_irq_enable(pin, RT_TRUE);
+    }
+    else
+    {
+        rt_pin_irq_enable(pin, RT_FALSE);
+        rt_pin_detach_irq(pin);
+    }
+    
+}

+ 323 - 0
porting/src/hal/cyhal_sdio.c

@@ -0,0 +1,323 @@
+
+/*
+ * Copyright (c) 2006-2023, Evlers Developers
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date         Author      Notes
+ * 2023-12-21   Evlers      first implementation
+ */
+
+#include "cyhal_sdio.h"
+#include <rtdevice.h>
+#include "whd_bus_sdio_protocol.h"
+#include "drv_gpio.h"
+
+
+static rt_int32_t wlan_probe(struct rt_mmcsd_card *card);
+static rt_int32_t wlan_remove(struct rt_mmcsd_card *card);
+
+
+static struct rt_sdio_device_id sdio_device_id =
+{
+    .func_code = BACKPLANE_FUNCTION,
+    .manufacturer = CYHAL_SDIO_MANUFACTURER,
+    .product = CYHAL_SDIO_DRIVER_ID,
+};
+
+static struct rt_sdio_driver sdio_driver =
+{
+    .name = CYHAL_SDIO_DRIVER_NAME,
+    .probe = wlan_probe,
+    .remove = wlan_remove,
+    .id = &sdio_device_id,
+};
+
+static cyhal_sdio_t *tmp_cyhal_sdio;
+
+
+/** Initialize the SDIO peripheral
+ *
+ * @param[out] obj               The SDIO object
+ * @return The status of the init request
+ */
+cy_rslt_t cyhal_sdio_init(cyhal_sdio_t *obj)
+{
+    tmp_cyhal_sdio = obj;
+    tmp_cyhal_sdio->dev_id = &sdio_device_id;
+
+    if (sdio_register_driver(&sdio_driver) != RT_EOK)
+    {
+        return CYHAL_SDIO_RET_NO_SP_ERRORS;
+    }
+    return CYHAL_SDIO_RET_NO_ERRORS;
+}
+
+/** Release the SDIO peripheral, not currently invoked. It requires further
+ *  resource management.
+ *
+ * @param[in,out] obj The SDIO object
+ */
+void cyhal_sdio_free(cyhal_sdio_t *obj)
+{
+    sdio_unregister_driver(&sdio_driver);
+}
+
+/** Configure the SDIO block.
+ *
+ * @param[in,out] obj    The SDIO object
+ * @param[in]     config The sdio configuration to apply
+ * @return The status of the configure request
+ */
+cy_rslt_t cyhal_sdio_configure(cyhal_sdio_t *obj, const cyhal_sdio_cfg_t *config)
+{
+    mmcsd_set_clock(obj->card->host, config->frequencyhal_hz);
+    return sdio_set_block_size(obj->card->sdio_function[obj->dev_id->func_code], config->block_size);
+}
+
+/** Sends a command to the SDIO block.
+ *
+ * @param[in,out] obj       The SDIO object
+ * @param[in]     direction The direction of transfer (read/write)
+ * @param[in]     command   The SDIO command to send
+ * @param[in]     argument  The argument to the command
+ * @param[out]    response  The response from the SDIO device
+ * @return The status of the configure request
+ */
+cy_rslt_t cyhal_sdio_send_cmd(const cyhal_sdio_t *obj, cyhal_transfer_t direction, cyhal_sdio_command_t command,
+                              uint32_t argument, uint32_t *response)
+{
+    cy_rslt_t ret;
+    (void)direction;
+    struct rt_mmcsd_cmd cmd;
+
+    if (obj->card == RT_NULL)
+    {
+        return CYHAL_SDIO_RET_NO_SP_ERRORS;
+    }
+
+    struct rt_mmcsd_host *host = obj->card->host;
+    if (host == RT_NULL)
+    {
+        return CYHAL_SDIO_RET_NO_SP_ERRORS;
+    }
+
+    rt_memset(&cmd, 0, sizeof(struct rt_mmcsd_cmd));
+
+    cmd.cmd_code = command;
+    cmd.arg = argument;
+    cmd.flags = RESP_SPI_R5 | RESP_R5 | CMD_AC;
+
+    mmcsd_host_lock(obj->card->host);
+    ret = mmcsd_send_cmd(host, &cmd, 0);
+    mmcsd_host_unlock(obj->card->host);
+    if (ret)
+        return ret;
+
+    if (cmd.resp[0] & R5_ERROR)
+        return CYHAL_SDIO_RET_CMD_IDX_ERROR;
+    if (cmd.resp[0] & R5_FUNCTION_NUMBER)
+        return CYHAL_SDIO_FUNC_NOT_SUPPORTED;
+    if (cmd.resp[0] & R5_OUT_OF_RANGE)
+        return CYHAL_SDIO_RET_RESP_FLAG_ERROR;
+
+    *response = cmd.resp[0];
+
+    return ret;
+}
+
+/** Performs a bulk data transfer (CMD=53) to the SDIO block.
+ *
+ * @param[in,out] obj       The SDIO object
+ * @param[in]     direction The direction of transfer (read/write)
+ * @param[in]     argument  The argument to the command
+ * @param[in]     data      The data to send to the SDIO device. The data buffer
+ *                          should be aligned to the block size (64 bytes) if data
+ *                          size is greater that block size (64 bytes).
+ * @param[in]     length    The number of bytes to send
+ * @param[out]    response  The response from the SDIO device
+ * @return The status of the configure request
+ */
+cy_rslt_t cyhal_sdio_bulk_transfer(cyhal_sdio_t *obj, cyhal_transfer_t direction, uint32_t argument,
+                                   const uint32_t *data, uint16_t length, uint32_t *response)
+{
+    struct rt_mmcsd_req req;
+    struct rt_mmcsd_cmd cmd;
+    struct rt_mmcsd_data mmcsd_data;
+    sdio_cmd_argument_t *arg = (sdio_cmd_argument_t *)&cmd.arg;
+
+    if (obj->card == RT_NULL)
+    {
+        return CYHAL_SDIO_RET_NO_SP_ERRORS;
+    }
+
+    struct rt_mmcsd_host *host = obj->card->host;
+    if (host == RT_NULL)
+    {
+        return CYHAL_SDIO_RET_NO_SP_ERRORS;
+    }
+
+    rt_memset(&req, 0, sizeof(struct rt_mmcsd_req));
+    rt_memset(&cmd, 0, sizeof(struct rt_mmcsd_cmd));
+    rt_memset(&mmcsd_data, 0, sizeof(struct rt_mmcsd_data));
+
+    req.cmd = &cmd;
+    req.data = &mmcsd_data;
+
+    cmd.retries = 1;
+    cmd.cmd_code = CYHAL_SDIO_CMD_IO_RW_EXTENDED;
+    cmd.arg = argument;
+    cmd.flags = RESP_SPI_R5 | RESP_R5 | CMD_ADTC;
+
+    mmcsd_data.buf = (rt_uint32_t *)data;
+    mmcsd_data.flags = (direction == CYHAL_READ) ? DATA_DIR_READ : DATA_DIR_WRITE;
+    
+    uint32_t max_blk_size = obj->card->sdio_function[obj->dev_id->func_code]->cur_blk_size;
+    max_blk_size = max_blk_size ? max_blk_size : obj->card->sdio_function[obj->dev_id->func_code]->max_blk_size;
+    if (length >= max_blk_size)
+    {
+        /* Block mode */
+        mmcsd_data.blksize = max_blk_size;
+        mmcsd_data.blks = (length + mmcsd_data.blksize - 1u) / mmcsd_data.blksize;
+    }
+    else
+    {
+        /* Byte mode */
+        mmcsd_data.blksize = length;
+        mmcsd_data.blks = 1;
+        mmcsd_data.flags |= DATA_STREAM;
+        (*arg).cmd53.block_mode = 0;
+    }
+
+    mmcsd_host_lock(obj->card->host);
+    mmcsd_set_data_timeout(&mmcsd_data, obj->card);
+    mmcsd_send_request(host, &req);
+    mmcsd_host_unlock(obj->card->host);
+
+    *response = cmd.resp[0];
+
+    return (req.cmd->err) ? CYHAL_SDIO_RET_NO_SP_ERRORS : CYHAL_SDIO_RET_NO_ERRORS;
+}
+
+static cyhal_sdio_irq_handler_t cyhal_sdio_irq_handler = NULL;
+
+static void sdio_irq_handler(struct rt_sdio_function *func)
+{
+    if (cyhal_sdio_irq_handler != NULL)
+    {
+        cyhal_sdio_irq_handler(func, CYHAL_SDIO_CARD_INTERRUPT);
+    }
+}
+
+/** The sdio interrupt handler registration
+ *
+ * @param[in] obj         The SDIO object
+ * @param[in] handler     The callback handler which will be invoked when the interrupt fires
+ * @param[in] handler_arg Generic argument that will be provided to the handler when called
+ */
+void cyhal_sdio_register_irq(cyhal_sdio_t *obj, cyhal_sdio_irq_handler_t handler, void *handler_arg)
+{
+    cyhal_sdio_irq_handler = handler;
+}
+
+/** Configure sdio interrupt.
+ *
+ * @param[in] obj      The SDIO object
+ * @param[in] event    The sdio IRQ type
+ * @param[in] enable   Set to non-zero to enable events, or zero to disable them
+ */
+void cyhal_sdio_irq_enable(cyhal_sdio_t *obj, cyhal_sdio_irq_event_t event, bool enable)
+{
+    mmcsd_host_lock(obj->card->host);
+
+    if (event == CYHAL_SDIO_CARD_INTERRUPT)
+    {
+        if (enable)
+        {
+            if (cyhal_sdio_irq_handler != RT_NULL)
+            {
+                sdio_attach_irq(obj->card->sdio_function[obj->dev_id->func_code], sdio_irq_handler);
+            }
+        }
+        else
+        {
+            sdio_detach_irq(obj->card->sdio_function[obj->dev_id->func_code]);
+        }
+    }
+
+    mmcsd_host_unlock(obj->card->host);
+}
+
+
+#if SDIO_CLOCK_FREQ_CONFIG
+static uint32_t _cybsp_wifi_create_cmd_52_arg(uint8_t rw, uint8_t func, uint8_t raw, uint32_t addr,
+                                              uint8_t data)
+{
+    return (((rw & 0x01) << 31)         /* set R/W flag */
+            | ((func & 0x07) << 28)     /* set the function number */
+            | ((raw & 0x01) << 27)      /* set the RAW flag */
+            | ((addr & 0x1FFFF) << 9)   /* set the address */
+            | data);                    /* set the data */
+}
+#endif
+
+static rt_int32_t wlan_probe(struct rt_mmcsd_card *card)
+{
+    cy_rslt_t result = CYHAL_SDIO_RET_NO_ERRORS;
+    
+    /* save mmcsd card */
+    tmp_cyhal_sdio->card = card;
+
+#if SDIO_CLOCK_FREQ_CONFIG
+    uint32_t response = 0;
+    uint32_t sdio_frequency = card->host->freq_min;
+
+    mmcsd_host_lock(card->host);
+
+    // mmcsd_set_clock(card->host, sdio_frequency);
+
+    mmcsd_select_card(card);
+    
+    uint32_t tmp_arg = _cybsp_wifi_create_cmd_52_arg(SDIO_CMD52_ARG_RW_READ, SDIO_FUNC_NUM_0,
+                                                        SDIO_CMD52_ARG_RAW_NOT_SET,
+                                                        SDIO_CMD52_CCCR_SPEED_SLCT_ADDR, 0x00);
+    result = cyhal_sdio_send_cmd(tmp_cyhal_sdio, CYHAL_READ, CYHAL_SDIO_CMD_IO_RW_DIRECT, tmp_arg, &response);
+    if (result == CYHAL_SDIO_RET_NO_ERRORS)
+    {
+        if (SDIO_CMD52_CCCR_SPEED_SELECT_RESP_HS_SUPPORTED == response)
+        {
+            tmp_arg = _cybsp_wifi_create_cmd_52_arg(SDIO_CMD52_ARG_RW_WRITE, SDIO_FUNC_NUM_0,
+                                                    SDIO_CMD52_ARG_RAW_NOT_SET,
+                                                    SDIO_CMD52_CCCR_SPEED_SLCT_ADDR,
+                                                    SDIO_CMD52_CCCR_SPEED_SLCT_HS);
+            result = cyhal_sdio_send_cmd(tmp_cyhal_sdio, CYHAL_WRITE, CYHAL_SDIO_CMD_IO_RW_DIRECT, tmp_arg, &response);
+
+            if (result == CYHAL_SDIO_RET_NO_ERRORS)
+            {
+                if (SDIO_CMD52_CCCR_SPEED_SELECT_RESP_HS_SELECTED == response)
+                {
+                    // High Speed mode switch allowed, configure clock frequency for sdio max frequency
+                    sdio_frequency = card->host->freq_max;
+                }
+            }
+        }
+    }
+
+    mmcsd_host_unlock(card->host);
+
+    if (result == CYHAL_SDIO_RET_NO_ERRORS)
+    {
+        cyhal_sdio_cfg_t config = { .frequencyhal_hz = sdio_frequency, .block_size = 0 };
+        result = cyhal_sdio_configure(tmp_cyhal_sdio, &config);
+    }
+
+#endif
+
+    return result;
+}
+
+static rt_int32_t wlan_remove(struct rt_mmcsd_card *card)
+{
+    return RT_EOK;
+}

+ 238 - 0
porting/src/rtos/whd_rtos.c

@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2006-2023, Evlers Developers
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date         Author      Notes
+ * 2023-12-21   Evlers      first implementation
+ */
+
+#include <stdio.h>
+#include "rtthread.h"
+#include "whd.h"
+#include "whd_thread.h"
+#include "cyabs_rtos.h"
+
+
+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)
+{
+    if ((thread == NULL) || (stack_size < CY_RTOS_MIN_STACK_SIZE))
+    {
+        return CY_RTOS_BAD_PARAM;
+    }
+    else
+    {
+        rt_thread_t thread;
+
+        if ((thread = rt_thread_create(name, entry_function, arg, stack_size, priority, 2)) == RT_NULL)
+        {
+            return CY_RTOS_NO_MEMORY;
+        }
+
+        if (rt_thread_startup(thread) != RT_EOK)
+        {
+            return CY_RSLT_TYPE_ERROR;
+        }
+    }
+
+    return CY_RSLT_SUCCESS;
+}
+
+/**
+ * Exit the current thread
+ *
+ * @returns WHD_SUCCESS on success or otherwise
+ */
+cy_rslt_t cy_rtos_exit_thread(void)
+{
+    return CY_RSLT_SUCCESS;
+}
+
+/**
+ * Blocks the current thread until the indicated thread is complete
+ *
+ * @param thread         : handle of the thread to terminate
+ *
+ * @returns CY_RSLT_SUCCESS on success, error otherwise
+ */
+cy_rslt_t cy_rtos_join_thread(cy_thread_t *thread)
+{
+    return CY_RSLT_SUCCESS;
+}
+
+/**
+ * Creates a semaphore
+ *
+ * @param semaphore         : pointer to variable which will receive handle of created semaphore
+ *
+ * @returns CY_RSLT_SUCCESS on success, error otherwise
+ */
+cy_rslt_t cy_rtos_init_semaphore(cy_semaphore_t *semaphore, uint32_t maxcount, uint32_t initcount)
+{
+    cy_rslt_t status = CY_RSLT_SUCCESS;
+
+    if (semaphore == NULL)
+    {
+        status = CY_RTOS_BAD_PARAM;
+    }
+    else
+    {
+        *semaphore = rt_sem_create("cyw", initcount, RT_IPC_FLAG_PRIO);
+        if (*semaphore == NULL)
+        {
+            status = CY_RTOS_NO_MEMORY;
+        }
+    }
+
+    return status;
+}
+
+/**
+ * Gets a semaphore
+ *
+ * If value of semaphore is larger than zero, then the semaphore is decremented and function returns
+ * Else If value of semaphore is zero, then current thread is suspended until semaphore is set.
+ * Value of semaphore should never be below zero
+ *
+ * Must not be called from interrupt context, since it could block, and since an interrupt is not a
+ * normal thread, so could cause RTOS problems if it tries to suspend it.
+ * If called from interrupt context time out value should be 0.
+ *
+ * @param semaphore   : Pointer to variable which will receive handle of created semaphore
+ * @param timeout_ms  : Maximum period to block for. Can be passed CY_RTOS_NEVER_TIMEOUT to request no timeout
+ * @param will_set_in_isr : True if the semaphore will be set in an ISR. Currently only used for NoOS/NoNS
+ *
+ */
+cy_rslt_t cy_rtos_get_semaphore(cy_semaphore_t *semaphore, uint32_t timeout_ms,
+                                bool will_set_in_isr)
+{
+    /* In rtthread, semaphores cannot be take in interrupts */
+    if ((semaphore == NULL) || (will_set_in_isr))
+    {
+        return CY_RTOS_BAD_PARAM;
+    }
+    else
+    {
+        rt_tick_t ticks = rt_tick_from_millisecond(timeout_ms);
+        if (rt_sem_take(*semaphore, ticks) != RT_EOK)
+        {
+            return CY_RTOS_TIMEOUT;
+        }
+    }
+
+    return CY_RSLT_SUCCESS;
+}
+
+/**
+ * Sets a semaphore
+ *
+ * If any threads are waiting on the semaphore, the first thread is resumed
+ * Else increment semaphore.
+ *
+ * Can be called from interrupt context, so must be able to handle resuming other
+ * threads from interrupt context.
+ *
+ * @param semaphore       : Pointer to variable which will receive handle of created semaphore
+ * @param called_from_ISR : Value of WHD_TRUE indicates calling from interrupt context
+ *                          Value of WHD_FALSE indicates calling from normal thread context
+ *
+ * @return cy_rslt_t : CY_RSLT_SUCCESS if semaphore was successfully set
+ *                        : error if an error occurred
+ *
+ */
+cy_rslt_t cy_rtos_set_semaphore(cy_semaphore_t *semaphore, bool called_from_ISR)
+{
+    if ((semaphore == NULL))
+    {
+        return CY_RTOS_BAD_PARAM;
+    }
+    else
+    {
+        if (rt_sem_release(*semaphore) != RT_EOK)
+        {
+            return CY_RTOS_GENERAL_ERROR;
+        }
+    }
+
+    return CY_RSLT_SUCCESS;
+}
+
+/**
+ * Deletes a semaphore
+ *
+ * WHD uses this function to delete a semaphore.
+ *
+ * @param semaphore         : Pointer to the semaphore handle
+ *
+ * @return cy_rslt_t : CY_RSLT_SUCCESS if semaphore was successfully deleted
+ *                        : error if an error occurred
+ *
+ */
+cy_rslt_t cy_rtos_deinit_semaphore(cy_semaphore_t *semaphore)
+{
+    if (semaphore == NULL)
+    {
+        return CY_RTOS_BAD_PARAM;
+    }
+    else
+    {
+        if (rt_sem_delete(*semaphore) != RT_EOK)
+        {
+            return CY_RTOS_GENERAL_ERROR;
+        }
+    }
+
+    return CY_RSLT_SUCCESS;
+}
+
+/**
+ * Gets time in milliseconds since RTOS start
+ *
+ * @Note: since this is only 32 bits, it will roll over every 49 days, 17 hours.
+ *
+ * @returns Time in milliseconds since RTOS started.
+ */
+cy_rslt_t cy_rtos_get_time(cy_time_t *tval)
+{
+    *tval = rt_tick_get_millisecond();
+
+    return CY_RSLT_SUCCESS;
+}
+
+/**
+ * Delay for a number of milliseconds
+ *
+ * @return cy_rslt_t : CY_RSLT_SUCCESS if delay was successful
+ *                        : error if an error occurred
+ *
+ */
+cy_rslt_t cy_rtos_delay_milliseconds(cy_time_t num_ms)
+{
+    rt_thread_mdelay(num_ms);
+
+    return CY_RSLT_SUCCESS;
+}
+
+
+#ifdef WHD_USE_CUSTOM_MALLOC_IMPL
+/* Use the system's built-in memory allocation */
+void *whd_mem_malloc (size_t size)
+{
+    return rt_malloc(size);
+}
+
+void *whd_mem_calloc(size_t nitems, size_t size)
+{
+    return rt_calloc(nitems, size);
+}
+
+void whd_mem_free(void *ptr)
+{
+    rt_free(ptr);
+}
+
+#endif /* ifndef WHD_USE_CUSTOM_MALLOC_IMPL */
+

+ 578 - 0
porting/src/wlan/cyw_wlan.c

@@ -0,0 +1,578 @@
+/*
+ * Copyright (c) 2006-2023, Evlers Developers
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date         Author      Notes
+ * 2023-12-28   Evlers      first implementation
+ */
+
+#include "rtthread.h"
+#include "rtdevice.h"
+
+#include "lwip/pbuf.h"
+#include "netdev.h"
+
+#include "cybsp.h"
+#include "cyhal_sdio.h"
+
+#include "whd.h"
+#include "whd_int.h"
+#include "whd_wifi_api.h"
+#include "whd_buffer_api.h"
+#include "whd_resource_api.h"
+#include "whd_network_types.h"
+#include "wiced_resource.h"
+
+#include "drv_gpio.h"
+
+#define DBG_TAG           "cyw.wlan"
+#define DBG_LVL           DBG_INFO
+#include "rtdbg.h"
+
+
+/* WHD interface */
+static whd_driver_t whd_driver;
+static cyhal_sdio_t cyhal_sdio;
+static whd_init_config_t whd_config =
+{
+    .thread_priority = CY_WIFI_WHD_THREAD_PRIORITY,
+    .thread_stack_size = CY_WIFI_WHD_THREAD_STACK_SIZE,
+    .country = WHD_COUNTRY_CHINA,
+};
+extern whd_resource_source_t resource_ops;
+extern struct whd_buffer_funcs whd_buffer_ops;
+
+
+struct drv_wifi
+{
+    struct rt_wlan_device *wlan;
+    whd_interface_t whd_itf;
+};
+
+static struct drv_wifi wifi_sta, wifi_ap;
+
+
+/* rt-thread wlan interface */
+
+rt_inline struct drv_wifi *get_drv_wifi(struct rt_wlan_device *wlan)
+{
+    if (wlan == wifi_sta.wlan)
+    {
+        return &wifi_sta;
+    }
+    
+    if (wlan == wifi_ap.wlan)
+    {
+        return &wifi_ap;
+    }
+
+    return RT_NULL;
+}
+
+static rt_err_t drv_wlan_init(struct rt_wlan_device *wlan)
+{
+    return RT_EOK;
+}
+
+static rt_err_t drv_wlan_mode(struct rt_wlan_device *wlan, rt_wlan_mode_t mode)
+{
+    return RT_EOK;
+}
+
+whd_scan_result_t scan_result;
+
+static void whd_scan_callback(whd_scan_result_t **result_ptr, void *user_data, whd_scan_status_t status)
+{   
+    struct rt_wlan_device *wlan = user_data;
+
+    /* Check if we don't have a scan result to send to the user */
+    if (( result_ptr == NULL ) || ( *result_ptr == NULL ))
+    {
+        /* Check for scan complete */
+        if (status == WHD_SCAN_COMPLETED_SUCCESSFULLY || status == WHD_SCAN_ABORTED)
+        {
+            LOG_D("scan complete!");
+            rt_wlan_dev_indicate_event_handle(wlan, RT_WLAN_DEV_EVT_SCAN_DONE, RT_NULL);
+        }
+        return;
+    }
+
+    /* Copy info to wlan */
+    whd_scan_result_t *bss_info = *result_ptr;
+    struct rt_wlan_info wlan_info;
+    struct rt_wlan_buff buff;
+
+    rt_memset(&wlan_info, 0, sizeof(wlan_info));
+
+    rt_memcpy(&wlan_info.bssid[0], bss_info->BSSID.octet, sizeof(wlan_info.bssid));
+    rt_memcpy(wlan_info.ssid.val, bss_info->SSID.value, bss_info->SSID.length);
+    wlan_info.ssid.len = bss_info->SSID.length;
+    if (bss_info->SSID.length)
+        wlan_info.hidden = 0;
+    else
+        wlan_info.hidden = 1;
+
+    wlan_info.channel = (rt_int16_t)bss_info->channel;
+    wlan_info.rssi = bss_info->signal_strength;
+
+    wlan_info.datarate = bss_info->max_data_rate * 1000;
+
+    switch (bss_info->band)
+    {
+        case WHD_802_11_BAND_5GHZ:      wlan_info.band = RT_802_11_BAND_5GHZ; break;
+        case WHD_802_11_BAND_2_4GHZ:    wlan_info.band = RT_802_11_BAND_2_4GHZ; break;
+        case WHD_802_11_BAND_6GHZ:      wlan_info.band = RT_802_11_BAND_UNKNOWN; break;
+    }
+
+    wlan_info.security = (rt_wlan_security_t)bss_info->security;
+
+    bss_info ++;
+
+    buff.data = &wlan_info;
+    buff.len = sizeof(wlan_info);
+
+    rt_wlan_dev_indicate_event_handle(wlan, RT_WLAN_DEV_EVT_SCAN_REPORT, &buff);
+
+    memset(*result_ptr, 0, sizeof(whd_scan_result_t));
+}
+
+static rt_err_t drv_wlan_scan(struct rt_wlan_device *wlan, struct rt_scan_info *scan_info)
+{
+    return whd_wifi_scan(get_drv_wifi(wlan)->whd_itf, WHD_SCAN_TYPE_ACTIVE, WHD_BSS_TYPE_ANY,
+                            NULL, NULL, NULL, NULL, whd_scan_callback, &scan_result, wlan);
+}
+
+static rt_err_t drv_wlan_join(struct rt_wlan_device *wlan, struct rt_sta_info *sta_info)
+{
+    rt_err_t ret;
+    whd_ssid_t whd_ssid = { .length = sta_info->ssid.len };
+
+    memcpy(whd_ssid.value, sta_info->ssid.val, whd_ssid.length);
+
+    ret = whd_wifi_join(get_drv_wifi(wlan)->whd_itf, &whd_ssid, WHD_SECURITY_WPA2_AES_PSK, 
+                            (const uint8_t *)sta_info->key.val, sta_info->key.len);
+
+    if (ret == WHD_SUCCESS)
+    {
+        rt_wlan_dev_indicate_event_handle(wlan, RT_WLAN_DEV_EVT_CONNECT, RT_NULL);
+    }
+    else
+    {
+        rt_wlan_dev_indicate_event_handle(wlan, RT_WLAN_DEV_EVT_CONNECT_FAIL, RT_NULL);
+    }
+
+    return ret;
+}
+
+static rt_err_t drv_wlan_softap(struct rt_wlan_device *wlan, struct rt_ap_info *ap_info)
+{
+    rt_err_t ret;
+
+    /* You need to disable the dhcp function of the netdev */
+    struct netdev *netdev = netdev_get_by_name("w1");
+    netdev_dhcp_enabled(netdev, RT_FALSE);
+
+    ret = whd_wifi_init_ap(get_drv_wifi(wlan)->whd_itf,
+                            (whd_ssid_t*)&ap_info->ssid,
+                            (whd_security_t)ap_info->security, 
+                            (const uint8_t *) ap_info->key.val,
+                            ap_info->key.len, ap_info->channel);
+    
+    if (ret != WHD_SUCCESS)
+    {
+        return ret;
+    }
+
+    if ((ret = whd_wifi_start_ap(get_drv_wifi(wlan)->whd_itf)) == WHD_SUCCESS)
+    {
+        rt_wlan_dev_indicate_event_handle(wifi_ap.wlan, RT_WLAN_DEV_EVT_AP_START, 0);
+    }
+    else
+    {
+        rt_wlan_dev_indicate_event_handle(wifi_ap.wlan, RT_WLAN_DEV_EVT_AP_STOP, 0);
+    }
+
+    return ret;
+}
+
+static rt_err_t drv_wlan_disconnect(struct rt_wlan_device *wlan)
+{
+    rt_err_t ret = whd_wifi_leave(get_drv_wifi(wlan)->whd_itf);
+
+    if (ret == WHD_SUCCESS)
+    {
+        rt_wlan_dev_indicate_event_handle(wlan, RT_WLAN_DEV_EVT_DISCONNECT, RT_NULL);
+    }
+    return ret;
+}
+
+static rt_err_t drv_wlan_ap_stop(struct rt_wlan_device *wlan)
+{
+    return whd_wifi_stop_ap(get_drv_wifi(wlan)->whd_itf);
+}
+
+static rt_err_t drv_wlan_ap_deauth(struct rt_wlan_device *wlan, rt_uint8_t mac[])
+{
+    whd_mac_t _mac;
+
+    memcpy(&_mac, mac, sizeof(whd_mac_t));
+    return whd_wifi_deauth_sta(get_drv_wifi(wlan)->whd_itf, &_mac, WHD_DOT11_RC_RESERVED);
+}
+
+static rt_err_t drv_wlan_scan_stop(struct rt_wlan_device *wlan)
+{
+    whd_wifi_stop_scan(get_drv_wifi(wlan)->whd_itf);
+    return RT_EOK;
+}
+
+static int drv_wlan_get_rssi(struct rt_wlan_device *wlan)
+{
+    int32_t rssi;
+
+    whd_wifi_get_rssi(get_drv_wifi(wlan)->whd_itf, &rssi);
+
+    return rssi;
+}
+
+static rt_err_t drv_wlan_set_powersave(struct rt_wlan_device *wlan, int level)
+{
+    if (level)
+    {
+        return whd_wifi_enable_powersave(get_drv_wifi(wlan)->whd_itf);
+    }
+    else
+    {
+        return whd_wifi_disable_powersave(get_drv_wifi(wlan)->whd_itf);
+    }
+}
+
+static int drv_wlan_get_powersave(struct rt_wlan_device *wlan)
+{
+    uint32_t value = 0;
+
+    whd_wifi_get_powersave_mode(get_drv_wifi(wlan)->whd_itf, &value);
+
+    return value;
+}
+
+static rt_err_t drv_wlan_set_channel(struct rt_wlan_device *wlan, int channel)
+{
+    return whd_wifi_set_channel(get_drv_wifi(wlan)->whd_itf, channel);
+}
+
+static int drv_wlan_get_channel(struct rt_wlan_device *wlan)
+{
+    uint32_t channel = 0;
+
+    whd_wifi_get_channel(get_drv_wifi(wlan)->whd_itf, &channel);
+
+    return channel;
+}
+
+static rt_country_code_t drv_wlan_get_country(struct rt_wlan_device *wlan)
+{
+    if (whd_config.country == WHD_COUNTRY_CHINA)
+    {
+        return RT_COUNTRY_CHINA;
+    }
+    else
+    {
+        return RT_COUNTRY_UNKNOWN;
+    }
+}
+
+static rt_err_t drv_wlan_set_mac(struct rt_wlan_device *wlan, rt_uint8_t mac[])
+{
+    whd_mac_t whd_mac;
+
+    memcpy(whd_mac.octet, mac, sizeof(whd_mac.octet));
+
+    return whd_wifi_set_mac_address(get_drv_wifi(wlan)->whd_itf, whd_mac);
+}
+
+static rt_err_t drv_wlan_get_mac(struct rt_wlan_device *wlan, rt_uint8_t mac[])
+{
+    rt_err_t ret;
+    whd_mac_t whd_mac;
+
+    if (wlan == wifi_ap.wlan)
+    {
+        if ((ret = whd_wifi_get_mac_address(wifi_sta.whd_itf, &whd_mac)) == WHD_SUCCESS)
+        {
+            /* AP interface needs to come up with MAC different from STA  */
+            if (whd_mac.octet[0] & 0x02)
+            {
+                whd_mac.octet[0] &= (uint8_t) ~(0x02);
+            }
+            else
+            {
+                whd_mac.octet[0] |= 0x02;
+            }
+        }
+    }
+    else
+    {
+        ret = whd_wifi_get_mac_address(get_drv_wifi(wlan)->whd_itf, &whd_mac);
+    }
+
+    if (ret == WHD_SUCCESS)
+    {
+        memcpy(mac, whd_mac.octet, RT_WLAN_BSSID_MAX_LENGTH);
+    }
+
+    return ret;
+}
+
+static int drv_wlan_recv(struct rt_wlan_device *wlan, void *buff, int len)
+{
+    return RT_EOK;
+}
+
+static int drv_wlan_send(struct rt_wlan_device *wlan, void *buff, int len)
+{
+    whd_buffer_t buffer;
+
+    /* Determines if a particular interface is ready to transceive ethernet packets */
+    if (whd_wifi_is_ready_to_transceive(get_drv_wifi(wlan)->whd_itf) != WHD_SUCCESS)
+    {
+        return -RT_ERROR;
+    }
+
+    /* Creating a transport layer pbuf allows WHD to add link data to the pbuf header */
+    if (whd_host_buffer_get(get_drv_wifi(wlan)->whd_itf->whd_driver, &buffer, WHD_NETWORK_TX, len + WHD_LINK_HEADER, 1000) != 0)
+    {
+        LOG_D("err whd_host_buffer_get failed\n");
+        return -RT_ERROR;
+    }
+
+    /* Sets the offset of buffer data position
+     * It is reserved for whd to write link header data
+     */
+    whd_buffer_add_remove_at_front(get_drv_wifi(wlan)->whd_itf->whd_driver, &buffer, WHD_LINK_HEADER);
+
+    /* Copy network data to WHD */
+    memcpy(whd_buffer_get_current_piece_data_pointer(get_drv_wifi(wlan)->whd_itf->whd_driver, buffer), buff, len);
+
+    /*
+     *  This function takes ethernet data from the network stack and queues it for transmission over the wireless network.
+     *  The function can be called from any thread context as it is thread safe, however
+     *  it must not be called from interrupt context since it might get blocked while waiting
+     *  for a lock on the transmit queue.
+     */
+    whd_network_send_ethernet_data(get_drv_wifi(wlan)->whd_itf, buffer);
+
+    return RT_EOK;
+}
+
+static const struct rt_wlan_dev_ops ops =
+{
+    .wlan_init = drv_wlan_init,
+    .wlan_mode = drv_wlan_mode,
+    .wlan_scan = drv_wlan_scan,
+    .wlan_join = drv_wlan_join,
+    .wlan_softap = drv_wlan_softap,
+    .wlan_disconnect = drv_wlan_disconnect,
+    .wlan_ap_stop = drv_wlan_ap_stop,
+    .wlan_ap_deauth = drv_wlan_ap_deauth,
+    .wlan_scan_stop = drv_wlan_scan_stop,
+    .wlan_get_rssi = drv_wlan_get_rssi,
+    .wlan_set_powersave = drv_wlan_set_powersave,
+    .wlan_get_powersave = drv_wlan_get_powersave,
+    .wlan_cfg_promisc = NULL,
+    .wlan_cfg_filter = NULL,
+    .wlan_cfg_mgnt_filter = NULL,
+    .wlan_set_channel = drv_wlan_set_channel,
+    .wlan_get_channel = drv_wlan_get_channel,
+    .wlan_set_country = NULL,
+    .wlan_get_country = drv_wlan_get_country,
+    .wlan_set_mac = drv_wlan_set_mac,
+    .wlan_get_mac = drv_wlan_get_mac,
+    .wlan_recv = drv_wlan_recv,
+    .wlan_send = drv_wlan_send,
+};
+
+/*
+ * This function takes packets from the radio driver and passes them into the
+ * lwIP stack. If the stack is not initialized, or if the lwIP stack does not
+ * accept the packet, the packet is freed (dropped). If the packet is of type EAPOL
+ * and if the Extensible Authentication Protocol over LAN (EAPOL) handler is registered, the packet will be redirected to the registered
+ * handler and should be freed by the EAPOL handler.
+ */
+void cy_network_process_ethernet_data(whd_interface_t iface, whd_buffer_t buf)
+{
+    uint16_t ethertype;
+    uint8_t *data = whd_buffer_get_current_piece_data_pointer(iface->whd_driver, buf);
+    struct rt_wlan_device *wlan = wifi_ap.whd_itf == iface ? wifi_ap.wlan : wifi_sta.wlan;
+
+    #define EAPOL_PACKET_TYPE                        (0x888E)
+
+    if (iface->role == WHD_STA_ROLE)
+    {
+
+    }
+    else if (iface->role == WHD_AP_ROLE)
+    {
+
+    }
+    else
+    {
+        whd_buffer_release(iface->whd_driver, buf, WHD_NETWORK_RX);
+        return;
+    }
+
+    ethertype = (uint16_t) (data[12] << 8 | data[13]);
+    if (ethertype == EAPOL_PACKET_TYPE)
+    {
+        LOG_D("EAPOL_PACKET_TYPE");
+    }
+    else
+    {
+        /* If the interface is not yet set up, drop the packet */
+        LOG_D("Send data up to wlan");
+        rt_wlan_dev_report_data(wlan, data, whd_buffer_get_current_piece_size(iface->whd_driver, buf));
+        whd_buffer_release(iface->whd_driver, buf, WHD_NETWORK_RX);
+    }
+}
+
+static whd_netif_funcs_t netif_if_ops =
+{
+    .whd_network_process_ethernet_data = cy_network_process_ethernet_data,
+};
+
+
+static int rt_hw_wifi_init(void)
+{
+    rt_err_t ret = RT_EOK;
+    static struct rt_wlan_device wlan_ap, wlan_sta;
+    static const whd_oob_config_t OOB_CONFIG =
+    {
+        .host_oob_pin      = CYBSP_HOST_WAKE_IRQ_PIN,
+        .dev_gpio_sel      = 0,
+        .is_falling_edge   = (CYBSP_HOST_WAKE_IRQ_EVENT == CYHAL_GPIO_IRQ_FALL) ? WHD_TRUE : WHD_FALSE,
+        .intr_priority     = CYBSP_OOB_INTR_PRIORITY
+    };
+    whd_sdio_config_t whd_sdio_config =
+    {
+        .sdio_1bit_mode        = WHD_FALSE,
+        .high_speed_sdio_clock = WHD_FALSE,
+        .oob_config            = OOB_CONFIG
+    };
+
+    wifi_ap.wlan = &wlan_ap;
+    wifi_sta.wlan = &wlan_sta;
+
+
+    /* Initialize WiFi Host Drivers (WHD) */
+
+    /* Wait for the mmcsd to finish reading the card */
+    rt_thread_mdelay(200);
+
+    /* Register the sdio driver */
+    if (cyhal_sdio_init(&cyhal_sdio) != CYHAL_SDIO_RET_NO_ERRORS)
+    {
+        LOG_E("Unable to register SDIO driver to mmcsd!");
+        return -RT_ERROR;
+    }
+
+    /* Initialize WiFi host drivers */
+    whd_init(&whd_driver, &whd_config, &resource_ops, &whd_buffer_ops, &netif_if_ops);
+
+    /* Attach a bus SDIO */
+    if (whd_bus_sdio_attach(whd_driver, &whd_sdio_config, &cyhal_sdio) != WHD_SUCCESS)
+    {
+        LOG_E("Unable to Attach to the sdio bus!");
+        return -RT_ERROR;
+    }
+
+    /* Switch on Wifi, download firmware and create a primary interface, returns whd_interface_t */
+    if (whd_wifi_on(whd_driver, &wifi_sta.whd_itf) != WHD_SUCCESS)
+    {
+        LOG_E("Unable to start the WiFi module!");
+        return -RT_ERROR;
+    }
+
+#ifdef CY_WIFI_DEFAULT_ENABLE_POWERSAVE_MODE
+    uint32_t value = 0;
+    if ((ret = whd_wifi_get_powersave_mode(wifi_sta.whd_itf, &value)) != WHD_SUCCESS)
+    {
+        LOG_E("The powersave mode switch status cannot be get!");
+        return ret;
+    }
+#endif
+
+    /* Disables 802.11 power save mode on specified interface */
+    if ((ret = whd_wifi_disable_powersave(wifi_sta.whd_itf)) != WHD_SUCCESS)
+    {
+        LOG_E("Failed to disable the powersave mode!");
+        return ret;
+    }
+
+#ifdef CY_WIFI_DEFAULT_ENABLE_POWERSAVE_MODE
+    if (value == PM1_POWERSAVE_MODE)
+    {
+        /* Enables powersave mode on specified interface */
+        if ((ret = whd_wifi_enable_powersave(wifi_sta.whd_itf)) != WHD_SUCCESS)
+        {
+            LOG_E("Failed to enable the powersave mode!");
+            return ret;
+        }
+
+        LOG_D("Enables powersave mode.");
+    }
+    else if (value == PM2_POWERSAVE_MODE)
+    {
+        /* Enables powersave mode on specified interface while attempting to maximise throughput */
+        /* Note: When working in this mode, sdio communication timeout will occur, which is the normal operation of whd */
+        if ((ret = whd_wifi_enable_powersave_with_throughput(wifi_sta.whd_itf, CY_WIFI_DEFAULT_PM2_SLEEP_RET_TIME)) != WHD_SUCCESS)
+        {
+            LOG_E("Failed to enable the powersave mode!");
+            return ret;
+        }
+        
+        LOG_D("Enables powersave mode while attempting to maximise throughput.");
+    }
+#endif
+
+    /* Creates a secondary interface, returns whd_interface_t */
+    if (whd_add_secondary_interface(whd_driver, NULL, &wifi_ap.whd_itf) != WHD_SUCCESS)
+    {
+        LOG_E("Failed to create a secondary interface!");
+        return -RT_ERROR;
+    }
+
+
+    /* Register the wlan device and set its working mode */
+
+    /* register wlan device for ap */
+    if ((ret = rt_wlan_dev_register(&wlan_ap, RT_WLAN_DEVICE_AP_NAME, &ops, 0, &wifi_ap)) != RT_EOK)
+    {
+        LOG_E("Failed to register a wlan_ap device!");
+        return ret;
+    }
+
+    /* register wlan device for sta */
+    if ((ret = rt_wlan_dev_register(&wlan_sta, RT_WLAN_DEVICE_STA_NAME, &ops, 0, &wifi_sta)) != RT_EOK)
+    {
+        LOG_E("Failed to register a wlan_sta device!");
+        return ret;
+    }
+    
+    /* Set wlan_sta to STATION mode */
+    if ((ret = rt_wlan_set_mode(RT_WLAN_DEVICE_STA_NAME, RT_WLAN_STATION)) != RT_EOK)
+    {
+        LOG_E("Failed to set %s to station mode!", RT_WLAN_DEVICE_STA_NAME);
+        return ret;
+    }
+
+    /* Set wlan_ap to AP mode */
+    if ((ret = rt_wlan_set_mode(RT_WLAN_DEVICE_AP_NAME, RT_WLAN_AP)) != RT_EOK)
+    {
+        LOG_E("Failed to set %s to ap mode!", RT_WLAN_DEVICE_AP_NAME);
+        return ret;
+    }
+
+    return ret;
+}
+INIT_APP_EXPORT(rt_hw_wifi_init);

+ 1 - 0
wifi-host-driver

@@ -0,0 +1 @@
+Subproject commit 04ee318cc96bffa7d69a1e076c008e2364453f82