Portenta add SDIO GPIO and filesystem implementation

pull/14663/head
Martino Facchin 2021-03-16 14:22:21 +01:00 committed by pennam
parent 4200d752b2
commit 94ceb8379d
11 changed files with 1963 additions and 0 deletions

View File

@ -0,0 +1,63 @@
/*
* Copyright 2020 Arduino SA
* 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.
*/
/** @file
* Provides cyhal porting to generic mbed APIs
*/
#include "cyhal.h"
#include "mbed_thread.h"
#include "mbed_wait_api.h"
static cyhal_sdio_t sdio_obj;
/* Edit Pin configuration */
const pinconfig_t PinConfig[] = {
[CYBSP_WIFI_WL_REG_ON] = WIFI_WL_REG_ON,
#ifdef CYBSP_WIFI_32K_CLK
[CYBSP_WIFI_32K_CLK] = WIFI_32K_CLK,
#endif /* CYBSP_WIFI_32K_CLK */
[CYBSP_LED1 ] = BSP_LED1,
[CYBSP_LED2 ] = BSP_LED2,
[CYBSP_WIFI_SDIO_CMD] = WIFI_SDIO_CMD,
[CYBSP_WIFI_SDIO_CLK] = WIFI_SDIO_CLK,
[CYBSP_WIFI_SDIO_D0 ] = WIFI_SDIO_D0,
[CYBSP_WIFI_SDIO_D1 ] = WIFI_SDIO_D1,
[CYBSP_WIFI_SDIO_D2 ] = WIFI_SDIO_D2,
[CYBSP_WIFI_SDIO_D3 ] = WIFI_SDIO_D3,
[CYBSP_SDIO_OOB_IRQ ] = WIFI_SDIO_OOB_IRQ //VIKR
};
void Cy_SysLib_Delay(uint32_t milliseconds)
{
thread_sleep_for(milliseconds);
}
void Cy_SysLib_DelayUs(uint16_t microseconds)
{
wait_us(microseconds);
}
void cyhal_system_delay_ms(uint32_t milliseconds)
{
Cy_SysLib_Delay(milliseconds);
}
cyhal_sdio_t *cybsp_get_wifi_sdio_obj(void)
{
return &sdio_obj;
}

View File

@ -0,0 +1,592 @@
/***************************************************************************//**
* \file cy_syslib.h
* \version 2.40.1
*
* Provides an API declaration of the SysLib driver.
*
********************************************************************************
* \copyright
* Copyright 2016-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_syslib
* \{
* The system libraries provide APIs that can be called in the user application
* to handle the timing, logical checking or register.
*
* The functions and other declarations used in this driver are in cy_syslib.h.
* You can include cy_pdl.h (ModusToolbox only) to get access to all functions
* and declarations in the PDL.
*
* The SysLib driver contains a set of different system functions. These functions
* can be called in the application routine. Major features of the system library:
* * Delay functions
* * The register Read/Write macro
* * Assert and Halt
* * Assert Classes and Levels
* * A software reset
* * Reading the reset cause
* * An API to invalidate the flash cache and buffer
* * Data manipulation macro
* * A variable type definition from MISRA-C which specifies signedness
* * Cross compiler compatible attributes
* * Getting a silicon-unique ID API
* * Setting wait states API
* * Resetting the backup domain API
* * APIs to serve Fault handler
*
* \section group_syslib_configuration Configuration Considerations
* <b> Assertion Usage </b> <br />
* Use the CY_ASSERT() macro to check expressions that must be true as long as the
* program is running correctly. It is a convenient way to insert sanity checks.
* The CY_ASSERT() macro is defined in the cy_syslib.h file which is part of
* the PDL library. The behavior of the macro is as follows: if the expression
* passed to the macro is false, output an error message that includes the file
* name and line number, and then halts the CPU. \n
* In case of fault, the CY_ASSERT() macro calls the Cy_SysLib_AssertFailed() function.
* This is a weakly linked function. The default implementation stores the file
* name and line number of the ASSERT into global variables, cy_assertFileName
* and cy_assertLine . It then calls the Cy_SysLib_Halt() function.
* \note Firmware can redefine the Cy_SysLib_AssertFailed() function for custom processing.
*
* The PDL source code uses this assert mechanism extensively. It is recommended
* that you enable asserts when debugging firmware. \n
* <b> Assertion Classes and Levels </b> <br />
* The PDL defines three assert classes, which correspond to different kinds
* of parameters. There is a corresponding assert "level" for each class.
* <table class="doxtable">
* <tr><th>Class Macro</th><th>Level Macro</th><th>Type of check</th></tr>
* <tr>
* <td>CY_ASSERT_CLASS_1</td>
* <td>CY_ASSERT_L1</td>
* <td>A parameter that could change between different PSoC devices
* (e.g. the number of clock paths)</td>
* </tr>
* <tr>
* <td>CY_ASSERT_CLASS_2</td>
* <td>CY_ASSERT_L2</td>
* <td>A parameter that has fixed limits such as a counter period</td>
* </tr>
* <tr>
* <td>CY_ASSERT_CLASS_3</td>
* <td>CY_ASSERT_L3</td>
* <td>A parameter that is an enum constant</td>
* </tr>
* </table>
* Firmware defines which ASSERT class is enabled by defining CY_ASSERT_LEVEL.
* This is a compiler command line argument, similar to how the DEBUG / NDEBUG
* macro is passed. \n
* Enabling any class also enables any lower-numbered class.
* CY_ASSERT_CLASS_3 is the default level, and it enables asserts for all three
* classes. The following example shows the command-line option to enable all
* the assert levels:
* \code -D CY_ASSERT_LEVEL=CY_ASSERT_CLASS_3 \endcode
* \note The use of special characters, such as spaces, parenthesis, etc. must
* be protected with quotes.
*
* After CY_ASSERT_LEVEL is defined, firmware can use
* one of the three level macros to make an assertion. For example, if the
* parameter can vary between devices, firmware uses the L1 macro.
* \code CY_ASSERT_L1(clkPath < SRSS_NUM_CLKPATH); \endcode
* If the parameter has bounds, firmware uses L2.
* \code CY_ASSERT_L2(trim <= CY_CTB_TRIM_VALUE_MAX); \endcode
* If the parameter is an enum, firmware uses L3.
* \code CY_ASSERT_L3(config->LossAction <= CY_SYSCLK_CSV_ERROR_FAULT_RESET); \endcode
* Each check uses the appropriate level macro for the kind of parameter being checked.
* If a particular assert class/level is not enabled, then the assert does nothing.
*
* \section group_syslib_more_information More Information
* Refer to the technical reference manual (TRM).
*
* \section group_syslib_MISRA MISRA-C Compliance
* <table class="doxtable">
* <tr>
* <th>MISRA Rule</th>
* <th>Rule Class (Required/Advisory)</th>
* <th>Rule Description</th>
* <th>Description of Deviation(s)</th>
* </tr>
* <tr>
* <td>1.2</td>
* <td>R</td>
* <td>No reliance shall be placed on undefined or unspecified behaviour.</td>
* <td>This specific behavior is explicitly covered in rule 20.1.</td>
* </tr>
* <tr>
* <td>2.1</td>
* <td>R</td>
* <td>This function contains a mixture of in-line assembler statements and C statements.</td>
* <td>This si required by design of the Cy_SysLib_Halt function.</td>
* </tr>
* <tr>
* <td>18.4</td>
* <td>R</td>
* <td>Unions shall not be used.</td>
* <td>The unions are used for CFSR, HFSR and SHCSR Fault Status Registers
* content access as a word in code and as a structure during debug.</td>
* </tr>
* <tr>
* <td>19.13</td>
* <td>A</td>
* <td>The # and ## operators should not be used.</td>
* <td>The ## preprocessor operator is used in macros to form the field mask.</td>
* </tr>
* <tr>
* <td>20.1</td>
* <td>R</td>
* <td>Reserved identifiers, macros and functions in the standard library, shall not be
* defined, redefined or undefined.</td>
* <td>The driver defines the macros with leading underscores
* (_CLR_SET_FLD/_BOOL2FLD/_FLD2BOOL) and therefore generates this MISRA violation.</td>
* </tr>
* </table>
*
* \section group_syslib_changelog Changelog
* <table class="doxtable">
* <tr><th>Version</th><th>Changes</th><th>Reason for Change</th></tr>
* <tr>
* <td>2.40.1</td>
* <td>Correct the CY_RAMFUNC_BEGIN macro for the IAR compiler.</td>
* <td>Removed the IAR compiler warning.</td>
* </tr>
* <tr>
* <td>2.40</td>
* <td>Added new macros CY_SYSLIB_DIV_ROUND and CY_SYSLIB_DIV_ROUNDUP to easy perform integer division with rounding.</td>
* <td>Improve PDL code base.</td>
* </tr>
* <tr>
* <td rowspan="3">2.30</td>
* <td>Updated implementation of the Cy_SysLib_AsmInfiniteLoop() function to be compatible with ARMC6.</td>
* <td>Provided support for the ARM Compiler 6.</td>
* </tr>
* <tr>
* <td>Minor documentation edits.</td>
* <td>Documentation update and clarification.</td>
* </tr>
* <tr>
* <td>Added new macros CY_RAMFUNC_BEGIN and CY_RAMFUNC_END for convenient placement function in RAM for all supported compilers.</td>
* <td>Improve user experience.</td>
* </tr>
* <tr>
* <td rowspan="2">2.20</td>
* <td>Updated implementation of the \ref Cy_SysLib_AssertFailed() function to be available in Release and Debug modes.</td>
* <td>Provided support for the PDL static library in Release mode.</td>
* </tr>
* <tr>
* <td>Minor documentation edits.</td>
* <td>Documentation update and clarification.</td>
* </tr>
* <tr>
* <td rowspan="4">2.10</td>
* <td>Flattened the organization of the driver source code into the single source directory and the single include directory.</td>
* <td>Driver library directory-structure simplification.</td>
* </tr>
* <tr>
* <td>Added the following macros: \ref CY_REG32_CLR_SET, \ref _CLR_SET_FLD16U, \ref CY_REG16_CLR_SET, \ref _CLR_SET_FLD8U, \ref CY_REG8_CLR_SET</td>
* <td>Register access simplification.</td>
* </tr>
* <tr>
* <td>Removed the Cy_SysLib_GetNumHfclkResetCause API function.</td>
* <td>This feature is not supported by SRSS_ver1.</td>
* </tr>
* <tr>
* <td>Added register access layer. Use register access macros instead
* of direct register access using dereferenced pointers.</td>
* <td>Makes register access device-independent, so that the PDL does
* not need to be recompiled for each supported part number.</td>
* </tr>
* <tr>
* <td>2.0.1</td>
* <td>Minor documentation edits</td>
* <td>Documentation update and clarification</td>
* </tr>
* <tr>
* <td rowspan="4"> 2.0</td>
* <td>
* Added Cy_SysLib_ResetBackupDomain() API implementation. \n
* Added CY_NOINLINE attribute implementation. \n
* Added DIE_YEAR field to 64-bit unique ID return value of Cy_SysLib_GetUniqueId() API. \n
* Added storing of SCB->HFSR, SCB->SHCSR registers and SCB->MMFAR, SCB->BFAR addresses to Fault Handler debug structure. \n
* Optimized Cy_SysLib_SetWaitStates() API implementation.
* </td>
* <td>Improvements made based on usability feedback.</td>
* </tr>
* <tr>
* <td>Added Assertion Classes and Levels.</td>
* <td>For error checking, parameter validation and status returns in the PDL API.</td>
* </tr>
* <tr>
* <td>Applied CY_NOINIT attribute to cy_assertFileName, cy_assertLine, and cy_faultFrame global variables.</td>
* <td>To store debug information into a non-zero init area for future analysis.</td>
* </tr>
* <tr>
* <td>Removed CY_WEAK attribute implementation.</td>
* <td>CMSIS __WEAK attribute should be used instead.</td>
* </tr>
* <tr>
* <td>1.0</td>
* <td>Initial version</td>
* <td></td>
* </tr>
* </table>
*
* \defgroup group_syslib_macros Macros
* \defgroup group_syslib_functions Functions
* \defgroup group_syslib_data_structures Data Structures
* \defgroup group_syslib_enumerated_types Enumerated Types
*
*/
#if !defined(CY_SYSLIB_H)
#define CY_SYSLIB_H
#include <stdint.h>
#include <stdbool.h>
/*******************************************************************************
* Data manipulation defines
*******************************************************************************/
/** Get the lower 8 bits of a 16-bit value. */
#define CY_LO8(x) ((uint8_t) ((x) & 0xFFU))
/** Get the upper 8 bits of a 16-bit value. */
#define CY_HI8(x) ((uint8_t) ((uint16_t)(x) >> 8U))
/** Get the lower 16 bits of a 32-bit value. */
#define CY_LO16(x) ((uint16_t) ((x) & 0xFFFFU))
/** Get the upper 16 bits of a 32-bit value. */
#define CY_HI16(x) ((uint16_t) ((uint32_t)(x) >> 16U))
/** Swap the byte ordering of a 16-bit value */
#define CY_SWAP_ENDIAN16(x) ((uint16_t)(((x) << 8U) | (((x) >> 8U) & 0x00FFU)))
/** Swap the byte ordering of a 32-bit value */
#define CY_SWAP_ENDIAN32(x) ((uint32_t)((((x) >> 24U) & 0x000000FFU) | (((x) & 0x00FF0000U) >> 8U) | \
(((x) & 0x0000FF00U) << 8U) | ((x) << 24U)))
/** Swap the byte ordering of a 64-bit value */
#define CY_SWAP_ENDIAN64(x) ((uint64_t) (((uint64_t) CY_SWAP_ENDIAN32((uint32_t)(x)) << 32U) | \
CY_SWAP_ENDIAN32((uint32_t)((x) >> 32U))))
/* MISRA rule 6.3 recommends using specific-length typedef for the basic
* numerical types of signed and unsigned variants of char, float, and double.
*/
typedef char char_t; /**< Specific-length typedef for the basic numerical types of char */
typedef float float32_t; /**< Specific-length typedef for the basic numerical types of float */
typedef double float64_t; /**< Specific-length typedef for the basic numerical types of double */
/*******************************************************************************
* Macro Name: CY_GET_REG8(addr)
****************************************************************************//**
*
* Reads the 8-bit value from the specified address. This function can't be
* used to access the Core register, otherwise a fault occurs.
*
* \param addr The register address.
*
* \return The read value.
*
*******************************************************************************/
#define CY_GET_REG8(addr) (*((const volatile uint8_t *)(addr)))
/*******************************************************************************
* Macro Name: CY_SET_REG8(addr, value)
****************************************************************************//**
*
* Writes an 8-bit value to the specified address. This function can't be
* used to access the Core register, otherwise a fault occurs.
*
* \param addr The register address.
*
* \param value The value to write.
*
*******************************************************************************/
#define CY_SET_REG8(addr, value) (*((volatile uint8_t *)(addr)) = (uint8_t)(value))
/*******************************************************************************
* Macro Name: CY_GET_REG16(addr)
****************************************************************************//**
*
* Reads the 16-bit value from the specified address.
*
* \param addr The register address.
*
* \return The read value.
*
*******************************************************************************/
#define CY_GET_REG16(addr) (*((const volatile uint16_t *)(addr)))
/*******************************************************************************
* Macro Name: CY_SET_REG16(addr, value)
****************************************************************************//**
*
* Writes the 16-bit value to the specified address.
*
* \param addr The register address.
*
* \param value The value to write.
*
*******************************************************************************/
#define CY_SET_REG16(addr, value) (*((volatile uint16_t *)(addr)) = (uint16_t)(value))
/*******************************************************************************
* Macro Name: CY_GET_REG24(addr)
****************************************************************************//**
*
* Reads the 24-bit value from the specified address.
*
* \param addr The register address.
*
* \return The read value.
*
*******************************************************************************/
#define CY_GET_REG24(addr) (((uint32_t) (*((const volatile uint8_t *)(addr)))) | \
(((uint32_t) (*((const volatile uint8_t *)(addr) + 1))) << 8U) | \
(((uint32_t) (*((const volatile uint8_t *)(addr) + 2))) << 16U))
/*******************************************************************************
* Macro Name: CY_SET_REG24(addr, value)
****************************************************************************//**
*
* Writes the 24-bit value to the specified address.
*
* \param addr The register address.
*
* \param value The value to write.
*
*******************************************************************************/
#define CY_SET_REG24(addr, value) do \
{ \
(*((volatile uint8_t *) (addr))) = (uint8_t)(value); \
(*((volatile uint8_t *) (addr) + 1)) = (uint8_t)((value) >> 8U); \
(*((volatile uint8_t *) (addr) + 2)) = (uint8_t)((value) >> 16U); \
} \
while(0)
/*******************************************************************************
* Macro Name: CY_GET_REG32(addr)
****************************************************************************//**
*
* Reads the 32-bit value from the specified register. The address is the little
* endian order (LSB in lowest address).
*
* \param addr The register address.
*
* \return The read value.
*
*******************************************************************************/
#define CY_GET_REG32(addr) (*((const volatile uint32_t *)(addr)))
/*******************************************************************************
* Macro Name: CY_SET_REG32(addr, value)
****************************************************************************//**
*
* Writes the 32-bit value to the specified register. The address is the little
* endian order (LSB in lowest address).
*
* \param addr The register address.
*
* \param value The value to write.
*
*******************************************************************************/
#define CY_SET_REG32(addr, value) (*((volatile uint32_t *)(addr)) = (uint32_t)(value))
/*******************************************************************************
* Macro Name: _CLR_SET_FLD32U
****************************************************************************//**
*
* The macro for setting a register with a name field and value for providing
* get-clear-modify-write operations.
* Returns a resulting value to be assigned to the register.
*
*******************************************************************************/
#define _CLR_SET_FLD32U(reg, field, value) (((reg) & ((uint32_t)(~(field ## _Msk)))) | (_VAL2FLD(field, value)))
/*******************************************************************************
* Macro Name: CY_REG32_CLR_SET
****************************************************************************//**
*
* Uses _CLR_SET_FLD32U macro for providing get-clear-modify-write
* operations with a name field and value and writes a resulting value
* to the 32-bit register.
*
*******************************************************************************/
#define CY_REG32_CLR_SET(reg, field, value) ((reg) = _CLR_SET_FLD32U((reg), field, (value)))
/*******************************************************************************
* Macro Name: _CLR_SET_FLD16U
****************************************************************************//**
*
* The macro for setting a 16-bit register with a name field and value for providing
* get-clear-modify-write operations.
* Returns a resulting value to be assigned to the 16-bit register.
*
*******************************************************************************/
#define _CLR_SET_FLD16U(reg, field, value) ((uint16_t)(((reg) & ((uint16_t)(~(field ## _Msk)))) | \
((uint16_t)_VAL2FLD(field, value))))
/*******************************************************************************
* Macro Name: CY_REG16_CLR_SET
****************************************************************************//**
*
* Uses _CLR_SET_FLD16U macro for providing get-clear-modify-write
* operations with a name field and value and writes a resulting value
* to the 16-bit register.
*
*******************************************************************************/
#define CY_REG16_CLR_SET(reg, field, value) ((reg) = _CLR_SET_FLD16U((reg), field, (value)))
/*******************************************************************************
* Macro Name: _CLR_SET_FLD8U
****************************************************************************//**
*
* The macro for setting a 8-bit register with a name field and value for providing
* get-clear-modify-write operations.
* Returns a resulting value to be assigned to the 8-bit register.
*
*******************************************************************************/
#define _CLR_SET_FLD8U(reg, field, value) ((uint8_t)(((reg) & ((uint8_t)(~(field ## _Msk)))) | \
((uint8_t)_VAL2FLD(field, value))))
/*******************************************************************************
* Macro Name: CY_REG8_CLR_SET
****************************************************************************//**
*
* Uses _CLR_SET_FLD8U macro for providing get-clear-modify-write
* operations with a name field and value and writes a resulting value
* to the 8-bit register.
*
*******************************************************************************/
#define CY_REG8_CLR_SET(reg, field, value) ((reg) = _CLR_SET_FLD8U((reg), field, (value)))
/*******************************************************************************
* Macro Name: _BOOL2FLD
****************************************************************************//**
*
* Returns a field mask if the value is not false.
* Returns 0, if the value is false.
*
*******************************************************************************/
#define _BOOL2FLD(field, value) (((value) != false) ? (field ## _Msk) : 0UL)
/*******************************************************************************
* Macro Name: _FLD2BOOL
****************************************************************************//**
*
* Returns true, if the value includes the field mask.
* Returns false, if the value doesn't include the field mask.
*
*******************************************************************************/
#define _FLD2BOOL(field, value) (((value) & (field ## _Msk)) != 0UL)
/*******************************************************************************
* Macro Name: CY_SYSLIB_DIV_ROUND
****************************************************************************//**
*
* Calculates a / b with rounding to the nearest integer,
* a and b must have the same sign.
*
*******************************************************************************/
#define CY_SYSLIB_DIV_ROUND(a, b) (((a) + ((b) / 2U)) / (b))
/*******************************************************************************
* Macro Name: CY_SYSLIB_DIV_ROUNDUP
****************************************************************************//**
*
* Calculates a / b with rounding up if remainder != 0,
* both a and b must be positive.
*
*******************************************************************************/
#define CY_SYSLIB_DIV_ROUNDUP(a, b) ((((a) - 1U) / (b)) + 1U)
typedef uint32_t cy_status;
/** The ARM 32-bit status value for backward compatibility with the UDB components. Do not use it in your code. */
typedef uint32_t cystatus;
typedef uint8_t uint8; /**< Alias to uint8_t for backward compatibility */
typedef uint16_t uint16; /**< Alias to uint16_t for backward compatibility */
typedef uint32_t uint32; /**< Alias to uint32_t for backward compatibility */
typedef int8_t int8; /**< Alias to int8_t for backward compatibility */
typedef int16_t int16; /**< Alias to int16_t for backward compatibility */
typedef int32_t int32; /**< Alias to int32_t for backward compatibility */
typedef float float32; /**< Alias to float for backward compatibility */
typedef double float64; /**< Alias to double for backward compatibility */
typedef int64_t int64; /**< Alias to int64_t for backward compatibility */
typedef uint64_t uint64; /**< Alias to uint64_t for backward compatibility */
/* Signed or unsigned depending on the compiler selection */
typedef char char8; /**< Alias to char for backward compatibility */
typedef volatile uint8_t reg8; /**< Alias to uint8_t for backward compatibility */
typedef volatile uint16_t reg16; /**< Alias to uint16_t for backward compatibility */
typedef volatile uint32_t reg32; /**< Alias to uint32_t for backward compatibility */
/** The ARM 32-bit Return error / status code for backward compatibility.
* Do not use them in your code.
*/
#define CY_RET_SUCCESS (0x00U) /* Successful */
#define CY_RET_BAD_PARAM (0x01U) /* One or more invalid parameters */
#define CY_RET_INVALID_OBJECT (0x02U) /* An invalid object specified */
#define CY_RET_MEMORY (0x03U) /* A memory-related failure */
#define CY_RET_LOCKED (0x04U) /* A resource lock failure */
#define CY_RET_EMPTY (0x05U) /* No more objects available */
#define CY_RET_BAD_DATA (0x06U) /* Bad data received (CRC or other error check) */
#define CY_RET_STARTED (0x07U) /* Operation started, but not necessarily completed yet */
#define CY_RET_FINISHED (0x08U) /* Operation is completed */
#define CY_RET_CANCELED (0x09U) /* Operation is canceled */
#define CY_RET_TIMEOUT (0x10U) /* Operation timed out */
#define CY_RET_INVALID_STATE (0x11U) /* Operation is not setup or is in an improper state */
#define CY_RET_UNKNOWN ((cy_status) 0xFFFFFFFFU) /* Unknown failure */
/** ARM 32-bit Return error / status codes for backward compatibility with the UDB components.
* Do not use them in your code.
*/
#define CYRET_SUCCESS (0x00U) /* Successful */
#define CYRET_BAD_PARAM (0x01U) /* One or more invalid parameters */
#define CYRET_INVALID_OBJECT (0x02U) /* An invalid object specified */
#define CYRET_MEMORY (0x03U) /* A memory-related failure */
#define CYRET_LOCKED (0x04U) /* A resource lock failure */
#define CYRET_EMPTY (0x05U) /* No more objects available */
#define CYRET_BAD_DATA (0x06U) /* Bad data received (CRC or other error check) */
#define CYRET_STARTED (0x07U) /* Operation started, but not necessarily completed yet */
#define CYRET_FINISHED (0x08U) /* Operation is completed */
#define CYRET_CANCELED (0x09U) /* Operation is canceled */
#define CYRET_TIMEOUT (0x10U) /* Operation timed out */
#define CYRET_INVALID_STATE (0x11U) /* Operation is not setup or is in an improper state */
#define CYRET_UNKNOWN ((cystatus) 0xFFFFFFFFU) /* Unknown failure */
/** \} group_syslib_functions */
#endif /* CY_SYSLIB_H */
/** \} group_syslib */
/* [] END OF FILE */

View File

@ -0,0 +1,81 @@
/***************************************************************************//**
* \file cy_utils.h
*
* \brief
* Basic utility macros and functions.
*
********************************************************************************
* \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_utils Utilities
* \ingroup group_abstraction
* \{
* Basic utility macros and functions.
*
* \defgroup group_utils_macros Macros
*/
#pragma once
#include "stdint.h"
#if defined(__cplusplus)
extern "C" {
#endif
/**
* \addtogroup group_utils_macros
* \{
*/
/** Simple macro to supress the unused parameter warning by casting to void. */
#define CY_UNUSED_PARAMETER(x) ( (void)(x) )
/** Halt the processor in the debug state
* @return
*/
static inline uint32_t CY_HALT()
{
__asm(" bkpt 1");
return 0;
}
#ifdef CY_ASSERT
#undef CY_ASSERT
#endif /* ifdef(CY_ASSERT) */
/** Utility macro when neither NDEBUG or CY_NO_ASSERT is not declared to check a condition and, if false, trigger a breakpoint */
#if defined(NDEBUG) || defined(CY_NO_ASSERT)
#define CY_ASSERT(x) CY_UNUSED_PARAMETER(x)
#else
#define CY_ASSERT(x) do { \
if(!(x)) \
{ \
CY_HALT(); \
} \
} while(0)
#endif /* defined(NDEBUG) */
/** \} group_utils_macros */
#ifdef __cplusplus
}
#endif
/** \} group_utils */

View File

@ -0,0 +1,50 @@
/***************************************************************************//**
* \file cybsp.h
*
* \brief
* Basic API for setting up boards containing a Cypress MCU.
*
********************************************************************************
* \copyright
* Copyright 2018-2020 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 "cy_result.h"
#include "cyhal_sdio.h"
#if defined(__cplusplus)
extern "C" {
#endif
/**
* \addtogroup group_bsp_functions Functions
* \{
*/
/**
* \brief Get the initialized sdio object used for communicating with the WiFi Chip.
* \note This function should only be called after cybsp_init();
* \returns The initialized sdio object.
*/
cyhal_sdio_t* cybsp_get_wifi_sdio_obj(void);
/** \} group_bsp_functions */
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -0,0 +1,52 @@
/*
* Copyright 2020 Arduino SA
* 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.
*/
/** @file
* Provides cyhal porting to generic mbed APIs
*/
#include "whd_config.h"
#include "cyhal_hw_types.h"
#include "cyhal_gpio.h"
#include "cyhal_sdio.h"
#if defined(__cplusplus)
extern "C" {
#endif
typedef enum
{
CYBSP_WIFI_WL_REG_ON,
CYBSP_WIFI_32K_CLK,
CYBSP_LED1,
CYBSP_LED2,
CYBSP_WIFI_SDIO_CMD,
CYBSP_WIFI_SDIO_CLK,
CYBSP_WIFI_SDIO_D0,
CYBSP_WIFI_SDIO_D1,
CYBSP_WIFI_SDIO_D2,
CYBSP_WIFI_SDIO_D3,
CYBSP_SDIO_OOB_IRQ,
CYBSP_WIFI_MAX,
} wwd_sdio_pin_t;
void cyhal_system_delay_ms(uint32_t milliseconds);
cy_rslt_t sdio_enable_high_speed(void);
#if defined(__cplusplus)
}
#endif

View File

@ -0,0 +1,99 @@
/*
* Copyright 2020 Arduino SA
* 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.
*/
/** @file
* Provides the porting layer for STM32 GPIOs on WHD driver
*/
#include <stdio.h>
#include "cyhal.h"
#include "cybsp.h"
#include "mbed.h"
#include "wiced_filesystem.h"
extern pinconfig_t PinConfig[];
/*******************************************************************************
* Internal
*******************************************************************************/
static mbed::InterruptIn *oob_irq;
static cyhal_gpio_event_t oob_event = CYHAL_GPIO_IRQ_FALL;
static cyhal_gpio_event_callback_t oob_handler;
static void *oob_handler_arg;
/*******************************************************************************
* Internal Interrrupt Service Routine
*******************************************************************************/
static void cb()
{
oob_handler(oob_handler_arg, oob_event);
}
/*******************************************************************************
* HAL Implementation
*******************************************************************************/
cy_rslt_t cyhal_gpio_init(cyhal_gpio_t pin, cyhal_gpio_direction_t direction, cyhal_gpio_drive_mode_t drvMode, bool initVal)
{
cy_rslt_t ret = CY_RSLT_SUCCESS;
// Workaround to enable GPIOJ clock
if (pin == CYBSP_WIFI_WL_REG_ON) {
__HAL_RCC_GPIOJ_CLK_ENABLE();
// Ensure FS and BlockDevice are initialized on time if needed
wiced_filesystem_init();
}
// Ignore the parameter and take the pin config directly from a static array defintions
HAL_GPIO_Init(PinConfig[pin].port, &PinConfig[pin].config);
if (direction == CYHAL_GPIO_DIR_OUTPUT) {
HAL_GPIO_WritePin(PinConfig[pin].port, PinConfig[pin].config.Pin, (initVal) ? GPIO_PIN_SET : GPIO_PIN_RESET);
}
// Workaround to initialize sdio interface without cypress bsp init
if (pin == CYBSP_WIFI_WL_REG_ON) {
cyhal_sdio_t *sdio_p = cybsp_get_wifi_sdio_obj();
ret = cyhal_sdio_init(sdio_p, CYBSP_WIFI_SDIO_CMD, CYBSP_WIFI_SDIO_CLK, CYBSP_WIFI_SDIO_D0, CYBSP_WIFI_SDIO_D1, CYBSP_WIFI_SDIO_D2, CYBSP_WIFI_SDIO_D3);
}
return ret;
}
void cyhal_gpio_write(cyhal_gpio_t pin, bool value)
{
HAL_GPIO_WritePin(PinConfig[pin].port, PinConfig[pin].config.Pin, (value) ? GPIO_PIN_SET : GPIO_PIN_RESET);
}
void cyhal_gpio_register_callback(cyhal_gpio_t pin, cyhal_gpio_event_callback_t handler, void *handler_arg)
{
if (handler && handler_arg && (oob_irq == NULL)) {
oob_irq = new mbed::InterruptIn(PJ_5);
oob_handler = handler;
oob_handler_arg = handler_arg;
}
}
void cyhal_gpio_enable_event(cyhal_gpio_t pin, cyhal_gpio_event_t event, uint8_t intr_priority, bool enable)
{
oob_event = event;
if (enable) {
if (event == CYHAL_GPIO_IRQ_RISE) {
oob_irq->rise(cb);
}
if (event == CYHAL_GPIO_IRQ_FALL) {
oob_irq->fall(cb);
}
} else if (oob_irq != NULL) {
delete oob_irq;
}
}

View File

@ -0,0 +1,123 @@
/***************************************************************************//**
* \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 <stdbool.h>
#include "stm32h7xx_hal.h"
#include "PinNames.h"
/*
#include "TODO: Port specific header file"
*/
#ifdef __cplusplus
extern "C" {
#endif
#ifndef CYHAL_ISR_PRIORITY_DEFAULT
/** Priority that is applied by default to all drivers when initalized. Priorities can be
* overridden on each driver as part of enabling events.
*/
#define CYHAL_ISR_PRIORITY_DEFAULT (7)
#endif
/**
* \addtogroup group_hal_hw_types_data_structures
* \{
*/
typedef int32_t cyhal_gpio_t;
/** GPIO object */
typedef struct
{
GPIO_TypeDef *port;
GPIO_InitTypeDef config;
} pinconfig_t;
/** Clock divider object */
typedef struct
{
/* TODO: replace with port specific items */
void *div_type;
} cyhal_clock_divider_t;
/** Clock object */
typedef struct
{
//For backwards compatibility with cyhal_clock_divider_t only. Do not use going forward.
int div_type; /*!< Deprecated */
uint8_t div_num; /*!< Deprecated */
//End BWC items
int block;
uint8_t channel;
bool reserved;
} cyhal_clock_t;
/** SDIO object */
typedef void* *cyhal_sdio_t;
/** SPI object */
typedef struct
{
/* TODO: replace with port specific items */
void *empty;
} cyhal_spi_t;
#include "whd_debug.h"
#if defined(WPRINT_ENABLE_WHD_ERROR) || defined(WPRINT_ENABLE_WHD_INFO) || defined(WPRINT_ENABLE_WHD_DEBUG)
/** \} group_hal_hw_types_data_structures */
#define PRINTF(...) do { \
(void) printf(__VA_ARGS__); \
} while (0)
#else
#define PRINTF(...)
#endif
#include "whd_config.h"
#if defined(__cplusplus)
}
#endif /* __cplusplus */
/** \} group_hal_hw_types */

View File

@ -0,0 +1,483 @@
/*
* Copyright 2020 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.
*/
/** @file
* Provides the porting layer for STM32 SDIO on WHD driver
*/
#include <stdio.h>
#include <string.h>
#include "whd_thread.h"
#include "bus_protocols/whd_bus_sdio_protocol.h"
#include "cyabs_rtos.h"
#include "cyhal_sdio.h"
#define SDIO_RESPONSE_SHORT SDMMC_RESPONSE_SHORT
#define SDIO_WAIT_NO SDMMC_WAIT_NO
#define SDIO_CPSM_ENABLE SDMMC_CPSM_ENABLE
#define SDIO_CMDTRANS SDMMC_CMD_CMDTRANS
#define SDIO_FLAG_CMDACT (SDMMC_STA_CPSMACT | SDMMC_STA_DPSMACT)
#define SDIO_TRANSFER_DIR_TO_SDIO SDMMC_TRANSFER_DIR_TO_SDMMC
#define SDIO_TRANSFER_DIR_TO_CARD SDMMC_TRANSFER_DIR_TO_CARD
#define SDIO_TRANSFER_MODE_BLOCK SDMMC_TRANSFER_MODE_BLOCK
#define SDIO_DPSM_ENABLE SDMMC_DPSM_ENABLE
#define SDIO_DPSM_DISABLE SDMMC_DPSM_DISABLE
#define SDIO_DCTRL_SDIOEN SDMMC_DCTRL_SDIOEN /* 1 << 11 */
#define SDIO_DCTRL_DTMODE_1 SDMMC_DCTRL_DTMODE_1 /* 1<<3 */
#define SDIO_STA_DTIMEOUT SDMMC_STA_DTIMEOUT
#define SDIO_STA_CTIMEOUT SDMMC_STA_CTIMEOUT
#define SDIO_STA_CCRCFAIL SDMMC_STA_CCRCFAIL
#define SDIO_STA_DCRCFAIL SDMMC_STA_DCRCFAIL
#define SDIO_STA_TXUNDERR SDMMC_STA_TXUNDERR
#define SDIO_STA_RXOVERR SDMMC_STA_RXOVERR
#define SDIO_STA_TXACT SDMMC_STA_CPSMACT
#define SDIO_STA_RXACT SDMMC_STA_DPSMACT
#define SDIO_STA_CMDREND SDMMC_STA_CMDREND
#define SDIO_STA_CMDSENT SDMMC_STA_CMDSENT
#define SDIO_CMD_CMDTRANS SDMMC_CMD_CMDTRANS
#define SDIO SDMMC1
#define COMMAND_FINISHED_CMD52_TIMEOUT_LOOPS (100000)
#define BUS_LEVEL_MAX_RETRIES 10
#define SDIO_CMD_5 5
#define SDIO_CMD_53 53
#define SDIO_STA_STBITERR ((uint32_t)0x00000200) /*!<Start bit not detected on all data signals in wide bus mode */
#define SDIO_ERROR_MASK ( SDMMC_STA_CCRCFAIL | SDMMC_STA_DCRCFAIL | SDMMC_STA_CTIMEOUT | SDMMC_STA_DTIMEOUT | SDMMC_STA_TXUNDERR | SDMMC_STA_RXOVERR )
#define LINK_MTU 1024
#define MAX(a,b) (a>b)?a:b
extern pinconfig_t PinConfig[];
extern SD_HandleTypeDef hsd;
/* for debug prints only */
//static int num = 0;
static uint32_t dctrl;
static whd_driver_t whd_handler;
static cyhal_sdio_irq_handler_t sdio_irq_handler;
static uint8_t temp_dma_buffer[2048] __attribute__((aligned(8)));
static uint8_t *user_data;
static uint32_t user_data_size;
static uint8_t *dma_data_source;
static uint32_t dma_transfer_size;
static cyhal_transfer_t current_transfer_direction;
static cy_semaphore_t sdio_transfer_finished_semaphore;
static volatile uint32_t sdio_transfer_failed = 0;
static volatile uint32_t irqstatus = 0;
static int current_command = 0;
static cy_rslt_t sdio_enable_high_speed(void)
{
SDMMC_InitTypeDef sdio_init_structure;
sdio_init_structure.ClockDiv = SDMMC_HSpeed_CLK_DIV;
sdio_init_structure.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
sdio_init_structure.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
sdio_init_structure.BusWide = SDMMC_BUS_WIDE_4B;
sdio_init_structure.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_ENABLE;
SDMMC_Init(SDMMC1, sdio_init_structure);
return CY_RSLT_SUCCESS;
}
static uint32_t find_optimal_block_size(uint32_t data_size)
{
if (data_size > (uint32_t) 256) {
return 512;
}
if (data_size > (uint32_t) 128) {
return 256;
}
if (data_size > (uint32_t) 64) {
return 128;
}
if (data_size > (uint32_t) 32) {
return 64;
}
if (data_size > (uint32_t) 16) {
return 32;
}
if (data_size > (uint32_t) 8) {
return 16;
}
if (data_size > (uint32_t) 4) {
return 8;
}
if (data_size > (uint32_t) 2) {
return 4;
}
return 4;
}
static uint32_t sdio_get_blocksize(uint32_t blocksize)
{
uint32_t n = 0;
blocksize >>= 1;
while (blocksize) {
n++;
blocksize >>= 1;
}
n <<= 4;
return n;
}
static void sdio_prepare_data_transfer(cyhal_transfer_t direction, uint32_t block_size, uint8_t *data, uint16_t data_size)
{
/* Setup a single transfer using the temp buffer */
user_data = data;
user_data_size = data_size;
dma_transfer_size = (uint32_t)(((data_size + (uint16_t) block_size - 1) / (uint16_t) block_size) * (uint16_t) block_size);
if (direction == CYHAL_WRITE) {
#if !(defined(DUAL_CORE) && defined(CORE_CM4))
SCB_CleanDCache_by_Addr((uint32_t *)dma_data_source, data_size + 32);
#endif
memcpy(temp_dma_buffer, data, data_size);
dma_data_source = temp_dma_buffer;
} else {
dma_data_source = (uint8_t *)temp_dma_buffer;
//VIKR
//memset(dma_data_source,0x12,data_size);
#if !(defined(DUAL_CORE) && defined(CORE_CM4))
/* Cache-Invalidate the output from DMA */
SCB_CleanDCache_by_Addr((uint32_t *)dma_data_source, data_size + 32);
#endif
}
SDIO->DTIMER = (uint32_t) 0xFFFFFFFF;
SDIO->DLEN = dma_transfer_size;
dctrl = sdio_get_blocksize(block_size) | ((direction == CYHAL_READ) ? SDIO_TRANSFER_DIR_TO_SDIO : SDIO_TRANSFER_DIR_TO_CARD) | SDIO_TRANSFER_MODE_BLOCK | SDIO_DPSM_DISABLE | SDIO_DCTRL_SDIOEN;
SDIO->DCTRL = dctrl;
SDMMC1->IDMACTRL = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
SDMMC1->IDMABASE0 = (uint32_t) dma_data_source;
}
static void sdio_enable_bus_irq(void)
{
SDMMC1->MASK = SDMMC_IT_RXOVERR | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND | SDMMC_IT_CMDREND | SDMMC_IT_CMDSENT;
}
void SDMMC1_IRQHandler(void)
{
uint32_t intstatus = SDIO->STA;
irqstatus = intstatus;
//VIKR | SDIO_STA_STBITERR )
if ((intstatus & (SDIO_STA_CCRCFAIL | SDIO_STA_DCRCFAIL | SDIO_STA_TXUNDERR | SDIO_STA_RXOVERR)) != 0) {
WPRINT_WHD_DEBUG(("sdio error flagged\n"));
sdio_transfer_failed = intstatus;
SDIO->ICR = (uint32_t) 0xffffffff;
cy_rtos_set_semaphore(&sdio_transfer_finished_semaphore, WHD_TRUE);
} else {
if ((intstatus & (SDMMC_STA_CMDREND | SDMMC_STA_CMDSENT)) != 0) {
if ((SDMMC1->RESP1 & 0x800) != 0) {
sdio_transfer_failed = irqstatus;
cy_rtos_set_semaphore(&sdio_transfer_finished_semaphore, WHD_TRUE);
}
/* Clear all command/response interrupts */
SDMMC1->ICR = (SDMMC_STA_CMDREND | SDMMC_STA_CMDSENT);
}
/* Check whether the external interrupt was triggered */
if (intstatus & SDMMC_STA_SDIOIT) {
/* Clear the interrupt */
SDMMC1->ICR = SDMMC_STA_SDIOIT;
/* Inform WICED WWD thread */
sdio_irq_handler(whd_handler, CYHAL_SDIO_CARD_INTERRUPT);
}
if (intstatus & SDMMC_STA_DATAEND) {
SDMMC1->ICR = SDMMC_STA_DATAEND;
SDMMC1->DLEN = 0;
SDMMC1->DCTRL = SDMMC_DCTRL_SDIOEN;
SDMMC1->IDMACTRL = SDMMC_DISABLE_IDMA;
SDMMC1->CMD = 0;
cy_rtos_set_semaphore(&sdio_transfer_finished_semaphore, WHD_TRUE);
}
}
}
//void sdio_dma_irq(void)
//{
// /* Clear interrupt */
// DMA2->LIFCR = (uint32_t)(0x3F << 22);
// cy_rtos_set_semaphore(&sdio_transfer_finished_semaphore, WHD_TRUE);
//}
cy_rslt_t cyhal_sdio_init(cyhal_sdio_t *obj, cyhal_gpio_t cmd, cyhal_gpio_t clk, cyhal_gpio_t data0, cyhal_gpio_t data1, cyhal_gpio_t data2, cyhal_gpio_t data3)
{
cy_rslt_t ret = CY_RSLT_SUCCESS;
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_SDMMC1_CLK_ENABLE();
HAL_GPIO_Init(PinConfig[cmd].port, &PinConfig[cmd].config);
HAL_GPIO_Init(PinConfig[clk].port, &PinConfig[clk].config);
HAL_GPIO_Init(PinConfig[data0].port, &PinConfig[data0].config);
HAL_GPIO_Init(PinConfig[data1].port, &PinConfig[data1].config);
HAL_GPIO_Init(PinConfig[data2].port, &PinConfig[data2].config);
HAL_GPIO_Init(PinConfig[data3].port, &PinConfig[data3].config);
/* Reset SDIO Block */
SDMMC_PowerState_OFF(SDMMC1);
__HAL_RCC_SDMMC1_FORCE_RESET();
__HAL_RCC_SDMMC1_RELEASE_RESET();
/* Enable the SDIO Clock */
__HAL_RCC_SDMMC1_CLK_ENABLE();
#if !(defined(DUAL_CORE) && defined(CORE_CM4))
/* Disable DCache for STM32H7 family */
SCB_CleanDCache();
SCB_DisableDCache();
#endif
WPRINT_WHD_DEBUG(("in init: %p\n", sdio_transfer_finished_semaphore));
// Lower speed configuration
SDMMC_InitTypeDef sdio_init_structure;
sdio_init_structure.ClockDiv = SDMMC_INIT_CLK_DIV;
sdio_init_structure.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
sdio_init_structure.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
sdio_init_structure.BusWide = SDMMC_BUS_WIDE_1B;
sdio_init_structure.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
ret = SDMMC_Init(SDMMC1, sdio_init_structure);
ret |= SDMMC_PowerState_ON(SDMMC1);
ret |= SDMMC_SetSDMMCReadWaitMode(SDMMC1, SDMMC_READ_WAIT_MODE_CLK);
if (ret) {
return ret;
}
/* Clear all SDIO interrupts */
SDMMC1->ICR = (uint32_t) 0xffffffff;
/* Turn on SDIO IRQ */
/* Must be lower priority than the value of configMAX_SYSCALL_INTERRUPT_PRIORITY */
/* otherwise FreeRTOS will not be able to mask the interrupt */
/* keep in mind that ARMCM7 interrupt priority logic is inverted, the highest value */
/* is the lowest priority */
HAL_NVIC_EnableIRQ((IRQn_Type) SDMMC1_IRQn);
HAL_NVIC_SetPriority(SDMMC1_IRQn, 5, 0);
WPRINT_WHD_DEBUG(("after enable sdio: %p\n", sdio_transfer_finished_semaphore));
if (cy_rtos_init_semaphore(&sdio_transfer_finished_semaphore, 1, 0) != WHD_SUCCESS) {
cy_rtos_deinit_semaphore(&sdio_transfer_finished_semaphore);
return -1;
}
WPRINT_WHD_DEBUG(("cy_rtos_init_semaphore: %p\n", sdio_transfer_finished_semaphore));
return ret;
}
void cyhal_sdio_free(cyhal_sdio_t *obj)
{
//TODO
}
cy_rslt_t cyhal_sdio_configure(cyhal_sdio_t *obj, const cyhal_sdio_cfg_t *config)
{
return sdio_enable_high_speed();
}
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)
{
uint32_t loop_count = 0;
cy_rslt_t result;
uint16_t attempts = 0;
uint32_t temp_sta;
if (response != NULL) {
*response = 0;
}
current_command = 0;
restart:
SDIO->ICR = (uint32_t) 0xFFFFFFFF;
++attempts;
/* Check if we've tried too many times */
if (attempts >= (uint16_t) BUS_LEVEL_MAX_RETRIES) {
/* WWD_SDIO_RETRIES_EXCEEDED */
result = -1;
goto exit;
}
/* Send the command */
SDIO->ARG = argument;
SDIO->CMD = (uint32_t)(command | SDIO_RESPONSE_SHORT | SDIO_WAIT_NO | SDIO_CPSM_ENABLE);
loop_count = (uint32_t) COMMAND_FINISHED_CMD52_TIMEOUT_LOOPS;
do {
temp_sta = SDIO->STA;
loop_count--;
if (loop_count == 0 || ((response != NULL) && ((temp_sta & SDIO_ERROR_MASK) != 0))) {
WPRINT_WHD_DEBUG(("Restart single access loop count %ld stat %lx\n", loop_count, temp_sta));
HAL_Delay(10U);
goto restart;
}
} while ((temp_sta & SDIO_FLAG_CMDACT) != 0);
if (response != NULL) {
*response = SDIO->RESP1;
}
result = CY_RSLT_SUCCESS;
exit:
if (result) {
WPRINT_WHD_ERROR(("SDIO->POWER %lx \n", SDIO->POWER));
WPRINT_WHD_ERROR(("SDIO->CLKCR %lx \n", SDIO->CLKCR));
WPRINT_WHD_ERROR(("result %lx \n", result));
WPRINT_WHD_ERROR(("cyhal_sdio_send_cmd %s\n", (result == 0) ? "Passed" : "Failed"));
while (1);
}
SDMMC1->CMD = 0;
//WPRINT_WHD_DEBUG(("%d %s cmd 0x%x arg 0x%x resp 0x%x\n",num++,(direction!=CYHAL_READ)?"Write":"Read",command,argument,(response)?*response:0));
return result;
}
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)
{
cy_rslt_t result;
uint16_t attempts = 0;
uint32_t block_size = 64;
sdio_cmd_argument_t arg;
uint32_t cmd;
current_command = SDIO_CMD_53;
current_transfer_direction = direction;
arg.value = argument;
sdio_enable_bus_irq();
if (response != NULL) {
*response = 0;
}
restart:
sdio_transfer_failed = 0;
SDMMC1->ICR = (uint32_t) 0xFFFFFFFF;
++attempts;
/* Check if we've tried too many times */
if (attempts >= (uint16_t) BUS_LEVEL_MAX_RETRIES) {
/* WWD_SDIO_RETRIES_EXCEEDED */
WPRINT_WHD_ERROR(("Too much attempt\n"));
result = -1;
goto exit;
}
/* Dodgy STM32 hack to set the CMD53 byte mode size to be the same as the block size */
if (arg.cmd53.block_mode == 0) {
block_size = find_optimal_block_size(arg.cmd53.count);
if (block_size < SDIO_512B_BLOCK) {
arg.cmd53.count = block_size;
} else {
arg.cmd53.count = 0;
}
argument = arg.value;
}
SDMMC1->CMD |= SDMMC_CMD_CMDTRANS;
/* Prepare the SDIO for a data transfer */
sdio_prepare_data_transfer(direction, block_size, (uint8_t *) data, (uint32_t) length);
/* Send the command */
//WPRINT_WHD_DEBUG(("%d bs=%d argument=%x\n",num++,block_size,argument));
SDMMC1->ARG = argument;
cmd = (uint32_t)(SDIO_CMD_53 | SDMMC_RESPONSE_SHORT | SDMMC_WAIT_NO | SDMMC_CPSM_ENABLE | SDMMC_CMD_CMDTRANS);
SDMMC1->CMD = cmd;
/* Wait for the whole transfer to complete */
//WPRINT_WHD_DEBUG(("cy_rtos_get_semaphore: %d\n", sdio_transfer_finished_semaphore));
result = cy_rtos_get_semaphore(&sdio_transfer_finished_semaphore, 50, WHD_FALSE);
if (result != CY_RSLT_SUCCESS) {
WPRINT_WHD_ERROR(("failed getting semaphore\n"));
goto exit;
}
if (sdio_transfer_failed) {
WPRINT_WHD_DEBUG(("try again sdio_transfer_failed %"PRIu32" irq %"PRIu32"\n", sdio_transfer_failed, irqstatus));
goto restart;
}
/* Check if there were any SDIO errors */
if ((SDIO->STA & (SDIO_STA_DTIMEOUT | SDIO_STA_CTIMEOUT)) != 0) {
WPRINT_WHD_DEBUG(("sdio errors SDIO_STA_DTIMEOUT | SDIO_STA_CTIMEOUT\n"));
goto restart;
} else if (((SDIO->STA & (SDIO_STA_CCRCFAIL | SDIO_STA_DCRCFAIL | SDIO_STA_TXUNDERR | SDIO_STA_RXOVERR)) != 0)) {
WPRINT_WHD_DEBUG(("sdio errors SDIO_STA_CCRCFAIL | SDIO_STA_DCRCFAIL | SDIO_STA_TXUNDERR | SDIO_STA_RXOVER \n"));
goto restart;
}
if (direction == CYHAL_READ) {
memcpy(user_data, dma_data_source, (size_t) user_data_size);
}
if (response != NULL) {
*response = SDIO->RESP1;
}
result = CY_RSLT_SUCCESS;
exit:
SDMMC1->CMD = 0;
//WPRINT_WHD_DEBUG(("%d %s cmd 53 argument %lx datasize %d blocknumber 0x%x cmdis %lx %lu dctrl = %x\n", num++, (direction != CYHAL_READ) ? "Write" : "Read", argument, length, arg.cmd53.count, cmd, cmd, dctrl));
return result;
}
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)
{
//TODO
return CYHAL_SDIO_RET_NO_SP_ERRORS;
}
bool cyhal_sdio_is_busy(const cyhal_sdio_t *obj)
{
return false;
}
cy_rslt_t cyhal_sdio_abort_async(const cyhal_sdio_t *obj)
{
//TODO
return CYHAL_SDIO_RET_NO_SP_ERRORS;
}
void cyhal_sdio_register_callback(cyhal_sdio_t *obj, cyhal_sdio_irq_handler_t handler, void *handler_arg)
{
whd_handler = (whd_driver_t)handler_arg;
sdio_irq_handler = handler;
}
void cyhal_sdio_enable_event(cyhal_sdio_t *obj, cyhal_sdio_irq_event_t event, uint8_t intr_priority, bool enable)
{
//TODO
}

View File

@ -0,0 +1,211 @@
/*
* Copyright 2020 Arduino SA
* 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.
*/
/** @file
* Provides wiced fs porting to generic mbed APIs
*/
#include <stddef.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "sockets.h"
#include "resources.h"
#include "wiced_filesystem.h"
#include "QSPIFBlockDevice.h"
#include "MBRBlockDevice.h"
#include "FATFileSystem.h"
#define WIFI_DEFAULT_FIRMWARE_PATH "/wlan/4343WA1.BIN"
#define WIFI_DEFAULT_MOUNT_NAME "wlan"
#define WIFI_DEFAULT_PARTITION 1
#define WIFI_DEFAULT_FS 0
QSPIFBlockDevice *qspi_bd = NULL;
MBRBlockDevice *mbr_bd = NULL;
FATFileSystem *wifi_fs = NULL;
MBED_WEAK void wiced_filesystem_mount_error(void)
{
WPRINT_WHD_ERROR(("Failed to mount the filesystem containing the WiFi firmware.\n\r"));
whd_print_logbuffer();
while (1) {}
}
MBED_WEAK void wiced_filesystem_firmware_error(void)
{
WPRINT_WHD_ERROR(("Please run the \"PortentaWiFiFirmwareUpdater\" sketch once to install the WiFi firmware.\n\r"));
whd_print_logbuffer();
while (1) {}
}
MBED_WEAK wiced_result_t whd_firmware_check_hook(const char *mounted_name, int mount_err)
{
DIR *dir;
struct dirent *ent;
std::string dir_name(mounted_name);
if (mount_err) {
wiced_filesystem_mount_error();
} else {
if ((dir = opendir(mounted_name)) != NULL) {
// print all the files and directories within directory
while ((ent = readdir(dir)) != NULL) {
std::string fullname = "/" + dir_name + "/" + std::string(ent->d_name);
if (fullname == WIFI_DEFAULT_FIRMWARE_PATH) {
closedir(dir);
return WICED_SUCCESS;
}
}
closedir(dir);
}
wiced_filesystem_firmware_error();
}
return WICED_ERROR;
}
static wiced_result_t whd_default_firmware_restore(void)
{
#if MBED_CONF_APP_WIFI_FIRMWARE_RESTORE
size_t ret;
FILE *fp;
//This should only happen the firs time or if the partition table has been overwritten i.e QSPI tests
WPRINT_WHD_DEBUG(("MBRBlockDevice init failed, repatitioning\n\r"));
if (mbr_bd->partition(qspi_bd, 1, 0x0B, 0, 1024 * 1024) != BD_ERROR_OK) {
return WICED_ERROR;
}
WPRINT_WHD_DEBUG(("MBRBockDevice repatitioning OK, reinit\n\r"));
if (mbr_bd->init() != BD_ERROR_OK) {
return WICED_ERROR;
}
WPRINT_WHD_DEBUG(("MBRBockDevice init OK\n\r"));
wifi_fs = new FATFileSystem(WIFI_DEFAULT_MOUNT_NAME);
if (wifi_fs->reformat(mbr_bd) != 0) {
return WICED_ERROR;
}
WPRINT_WHD_DEBUG(("FATFileSystem reformat and mount OK\n\r"));
fp = fopen(WIFI_DEFAULT_FIRMWARE_PATH, "wb");
if (fp == NULL) {
return WICED_ERROR;
}
ret = fwrite(wifi_firmware_image_data, wifi_firmware_image.size, 1, fp);
if (ret != wifi_firmware_image.size) {
return WICED_ERROR;
}
fclose(fp);
if (mbr_bd->sync() != 0) {
return WICED_ERROR;
}
WPRINT_WHD_DEBUG(("Sync BlockDevice OK\n\r"));
if (wifi_fs->unmount() != 0) {
return WICED_ERROR;
}
WPRINT_WHD_DEBUG(("Unmount FS\n\r"));
wifi_fs = NULL;
#endif
return WICED_SUCCESS;
}
wiced_result_t wiced_filesystem_init(void)
{
if (mbr_bd == NULL && wifi_fs == NULL) {
WPRINT_WHD_DEBUG(("Initialize FileSystem with Mbed default settings\n\r"));
qspi_bd = new QSPIFBlockDevice(PD_11, PD_12, PF_7, PD_13, PF_10, PG_6, QSPIF_POLARITY_MODE_1, 40000000);
if (qspi_bd->init() == BD_ERROR_OK) {
mbr_bd = new MBRBlockDevice(qspi_bd, WIFI_DEFAULT_PARTITION);
if (mbr_bd->init() == BD_ERROR_OK) {
return WICED_SUCCESS;
} else {
return whd_default_firmware_restore();
}
}
return WICED_ERROR;
} else {
WPRINT_WHD_DEBUG(("FileSystem initialized with user settings\n\r"));
return WICED_SUCCESS;
}
}
wiced_result_t wiced_filesystem_mount(BlockDevice *device, wiced_filesystem_handle_type_t fs_type, wiced_filesystem_t *fs_handle_out, const char *mounted_name)
{
wifi_fs = new FATFileSystem(mounted_name);
int err = wifi_fs->mount(device);
whd_firmware_check_hook(mounted_name, err);
if (!err) {
//fs_handle_out = wifi_fs
return WICED_SUCCESS;
}
return WICED_ERROR;
}
wiced_result_t wiced_filesystem_file_open(wiced_filesystem_t *fs_handle, wiced_file_t *file_handle_out, const char *filename, wiced_filesystem_open_mode_t mode)
{
/* This is called by mbed test system */
//if (mbr_bd == NULL && wifi_fs == NULL) {
// wiced_filesystem_init();
//}
//This can be called from user sketch to provide custom block device and mount point before WiFi.beginAP or WiFi.begin
if (wifi_fs == NULL) {
wiced_filesystem_mount(mbr_bd, WIFI_DEFAULT_FS, fs_handle, WIFI_DEFAULT_MOUNT_NAME);
}
if (wifi_fs == NULL) {
return WICED_ERROR;
}
*file_handle_out = open(filename, mode);
if (*file_handle_out == -1) {
return WICED_ERROR;
}
return WICED_SUCCESS;
}
wiced_result_t wiced_filesystem_file_seek(wiced_file_t *file_handle, int64_t offset, wiced_filesystem_seek_type_t whence)
{
if (*file_handle == -1) {
return WICED_ERROR;
}
lseek(*file_handle, offset, whence);
return WICED_SUCCESS;
}
wiced_result_t wiced_filesystem_file_read(wiced_file_t *file_handle, void *data, uint64_t bytes_to_read, uint64_t *returned_bytes_count)
{
if (*file_handle == -1) {
return WICED_ERROR;
}
*returned_bytes_count = read(*file_handle, data, bytes_to_read);
return WICED_SUCCESS;
}
wiced_result_t wiced_filesystem_file_close(wiced_file_t *file_handle)
{
if (*file_handle == -1) {
return WICED_ERROR;
}
close(*file_handle);
return WICED_SUCCESS;
}

View File

@ -0,0 +1,151 @@
/*
* Copyright 2020 Arduino SA
* 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.
*/
/** @file
* Provides wiced fs porting to generic mbed APIs
*/
#pragma once
#include "whd_config.h"
#include "BlockDevice.h"
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************
* Enumerations
******************************************************/
typedef enum {
WICED_FILESYSTEM_OPEN_FOR_READ, /** Specifies read access to the object. Data can be read from the file - equivalent to "r" or "rb" */
WICED_FILESYSTEM_OPEN_FOR_WRITE, /** Specifies read/write access to the object. Data can be written to the file - equivalent to "r+" or "rb+" or "r+b" */
WICED_FILESYSTEM_OPEN_WRITE_CREATE, /** Opens for read/write access, creates it if it doesn't exist */
WICED_FILESYSTEM_OPEN_ZERO_LENGTH, /** Opens for read/write access, Truncates file to zero length if it exists, or creates it if it doesn't - equivalent to "w+", "wb+" or "w+b" */
WICED_FILESYSTEM_OPEN_APPEND, /** Opens for read/write access, places the current location at the end of the file ready for appending - equivalent to "a", "ab" */
WICED_FILESYSTEM_OPEN_APPEND_CREATE, /** Opens for read/write access, creates it if it doesn't exist, and places the current location at the end of the file ready for appending - equivalent to "a+", "ab+" or "a+b" */
} wiced_filesystem_open_mode_t;
typedef enum {
WICED_FILESYSTEM_SEEK_SET = SEEK_SET, /* Offset from start of file */
WICED_FILESYSTEM_SEEK_CUR = SEEK_CUR, /* Offset from current position in file */
WICED_FILESYSTEM_SEEK_END = SEEK_END, /* Offset from end of file */
} wiced_filesystem_seek_type_t;
typedef enum {
WICED_SUCCESS = 0,
WICED_ERROR = 1
} wiced_result_t;
/******************************************************
* Type Definitions
******************************************************/
/**
* File-system Handle Structure
*/
typedef int wiced_filesystem_t;
/**
* File Handle Structure
*
*/
typedef int wiced_file_t;
/**
* File-system type Handle Structure
*/
typedef int wiced_filesystem_handle_type_t;
/**
* Initialise the BlockDevice and filesystem module
*
* Initialises the BlockDevice and filesystem module before mounting a physical device.
*
* @return WICED_SUCCESS on success
*/
wiced_result_t wiced_filesystem_init(void);
/**
* Mount the physical device
*
* This assumes that the device is ready to read/write immediately.
*
* @param[in] device - physical media to init
* @param[out] fs_handle_out - Receives the filesystem handle.
*
* @return WICED_SUCCESS on success
*/
wiced_result_t wiced_filesystem_mount(mbed::BlockDevice *device, wiced_filesystem_handle_type_t fs_type, wiced_filesystem_t *fs_handle_out, const char *mounted_name);
/**
* Open a file for reading or writing
*
* @param[in] fs_handle - The filesystem handle to use - obtained from wiced_filesystem_mount
* @param[out] file_handle_out - a pointer to a wiced_file_t structure which will receive the
* file handle after it is opened
* @param[in] filename - The filename of the file to open
* @param[in] mode - Specifies read or write access
*
* @return WICED_SUCCESS on success
*/
wiced_result_t wiced_filesystem_file_open(wiced_filesystem_t *fs_handle, wiced_file_t *file_handle_out, const char *filename, wiced_filesystem_open_mode_t mode);
/**
* Seek to a location within a file
*
* This is similar to the fseek() in ISO C.
*
* @param[in] file_handle - The file handle on which to perform the seek.
* Must have been previously opened with wiced_filesystem_fopen.
* @param[in] offset - The offset in bytes
* @param[in] whence - WICED_FILESYSTEM_SEEK_SET = Offset from start of file
* WICED_FILESYSTEM_SEEK_CUR = Offset from current position in file
* WICED_FILESYSTEM_SEEK_END = Offset from end of file
*
* @return WICED_SUCCESS on success
*/
wiced_result_t wiced_filesystem_file_seek(wiced_file_t *file_handle, int64_t offset, wiced_filesystem_seek_type_t whence);
/**
* Reads data from a file into a memory buffer
*
* @param[in] file_handle - the file handle to read from
* @param[out] data - A pointer to the memory buffer that will
* receive the data that is read
* @param[in] bytes_to_read - the number of bytes to read
* @param[out] returned_item_count - the number of items successfully read.
*
* @return WICED_SUCCESS on success
*/
wiced_result_t wiced_filesystem_file_read(wiced_file_t *file_handle, void *data, uint64_t bytes_to_read, uint64_t *returned_bytes_count);
/**
* Close a file
*
* This is similar to the fclose() in ISO C.
*
* @param[in] file_handle - the file handle to close
*
* @return WICED_SUCCESS = success
*/
wiced_result_t wiced_filesystem_file_close(wiced_file_t *file_handle);
#ifdef __cplusplus
} /*extern "C" */
#endif

View File

@ -0,0 +1,58 @@
/*
* Copyright 2020 Arduino SA
* 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.
*/
/** @file
* Provides configuration for WHD driver on Arduino Portenta H7
*/
#ifndef __WHD_CONFIG__
#define __WHD_CONFIG__
#include "whd_types.h"
#include "stm32h7xx_hal.h"
#include <stdint.h>
/* please define your configuration , either SDIO or SPI */
#define CY_WHD_CONFIG_USE_SDIO
//#define CY_WHD_CONFIG_USE_SPI
/* select resource implementation */
#define USES_RESOURCE_GENERIC_FILESYSTEM
/* if not defined default value is 2 */
#define CY_WIFI_OOB_INTR_PRIORITY 0
#define CYBSP_WIFI_HOST_WAKE_IRQ_EVENT CYHAL_GPIO_IRQ_FALL
#define CYBSP_WIFI_HOST_WAKE CYBSP_SDIO_OOB_IRQ
#define BSP_LED1 {GPIOK,{.Pin= GPIO_PIN_5 , .Mode = GPIO_MODE_OUTPUT_PP , .Pull = GPIO_NOPULL , .Speed= GPIO_SPEED_FREQ_LOW}}
#define BSP_LED2 {GPIOK,{.Pin= GPIO_PIN_6 , .Mode = GPIO_MODE_OUTPUT_PP , .Pull = GPIO_NOPULL , .Speed= GPIO_SPEED_FREQ_LOW}}
#define BSP_LED3 {GPIOK,{.Pin= GPIO_PIN_7 , .Mode = GPIO_MODE_OUTPUT_PP , .Pull = GPIO_NOPULL , .Speed= GPIO_SPEED_FREQ_LOW}}
/* power pin */
#define WIFI_WL_REG_ON {GPIOJ,{.Pin= GPIO_PIN_1, .Mode = GPIO_MODE_OUTPUT_PP , .Pull = GPIO_NOPULL , .Speed= GPIO_SPEED_FREQ_LOW}}
//#define WIFI_32K_CLK {GPIOA,{.Pin= GPIO_PIN_8, .Mode = GPIO_MODE_AF_PP , .Pull = GPIO_NOPULL , .Speed= GPIO_SPEED_FREQ_LOW , .Alternate = GPIO_AF0_MCO}}
#define WIFI_SDIO_CMD {GPIOD,{.Pin= GPIO_PIN_2 , .Mode = GPIO_MODE_AF_PP , .Pull = GPIO_NOPULL , .Speed= GPIO_SPEED_FREQ_VERY_HIGH, .Alternate = GPIO_AF12_SDIO1}}
#define WIFI_SDIO_CLK {GPIOC,{.Pin= GPIO_PIN_12, .Mode = GPIO_MODE_AF_PP , .Pull = GPIO_NOPULL , .Speed= GPIO_SPEED_FREQ_VERY_HIGH, .Alternate = GPIO_AF12_SDIO1}}
#define WIFI_SDIO_D0 {GPIOC,{.Pin= GPIO_PIN_8 , .Mode = GPIO_MODE_AF_PP , .Pull = GPIO_NOPULL , .Speed= GPIO_SPEED_FREQ_VERY_HIGH, .Alternate = GPIO_AF12_SDIO1}}
#define WIFI_SDIO_D1 {GPIOC,{.Pin= GPIO_PIN_9 , .Mode = GPIO_MODE_AF_PP , .Pull = GPIO_NOPULL , .Speed= GPIO_SPEED_FREQ_VERY_HIGH, .Alternate = GPIO_AF12_SDIO1}}
#define WIFI_SDIO_D2 {GPIOC,{.Pin= GPIO_PIN_10, .Mode = GPIO_MODE_AF_PP , .Pull = GPIO_NOPULL , .Speed= GPIO_SPEED_FREQ_VERY_HIGH, .Alternate = GPIO_AF12_SDIO1}}
#define WIFI_SDIO_D3 {GPIOC,{.Pin= GPIO_PIN_11, .Mode = GPIO_MODE_AF_PP , .Pull = GPIO_NOPULL , .Speed= GPIO_SPEED_FREQ_VERY_HIGH, .Alternate = GPIO_AF12_SDIO1}}
#define WIFI_SDIO_OOB_IRQ {GPIOJ,{.Pin= GPIO_PIN_5, .Mode = GPIO_MODE_IT_FALLING , .Pull = GPIO_NOPULL , .Speed= GPIO_SPEED_FREQ_VERY_HIGH}}
#endif