sync the upstream branch

This commit is contained in:
Wang_Weigen
2022-09-28 09:51:12 +08:00
5162 changed files with 264328 additions and 7325 deletions
@@ -0,0 +1,266 @@
/**************************************************************************//**
* @file cmsis_compiler.h
* @brief CMSIS compiler generic header file
* @version V5.0.4
* @date 10. January 2018
******************************************************************************/
/*
* Copyright (c) 2009-2018 Arm Limited. All rights reserved.
*
* 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
*
* 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 __CMSIS_COMPILER_H
#define __CMSIS_COMPILER_H
#include <stdint.h>
/*
* Arm Compiler 4/5
*/
#if defined ( __CC_ARM )
#include "cmsis_armcc.h"
/*
* Arm Compiler 6 (armclang)
*/
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#include "cmsis_armclang.h"
/*
* GNU Compiler
*/
#elif defined ( __GNUC__ )
#include "cmsis_gcc.h"
/*
* IAR Compiler
*/
#elif defined ( __ICCARM__ )
#include <cmsis_iccarm.h>
/*
* TI Arm Compiler
*/
#elif defined ( __TI_ARM__ )
#include <cmsis_ccs.h>
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((noreturn))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __attribute__((packed))
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __attribute__((packed))
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __attribute__((packed))
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
struct __attribute__((packed)) T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
/*
* TASKING Compiler
*/
#elif defined ( __TASKING__ )
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all intrinsics,
* Including the CMSIS ones.
*/
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((noreturn))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __packed__
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __packed__
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __packed__
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
struct __packed__ T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __align(x)
#endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
/*
* COSMIC Compiler
*/
#elif defined ( __CSMC__ )
#include <cmsis_csm.h>
#ifndef __ASM
#define __ASM _asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
// NO RETURN is automatically detected hence no warning here
#define __NO_RETURN
#endif
#ifndef __USED
#warning No compiler specific solution for __USED. __USED is ignored.
#define __USED
#endif
#ifndef __WEAK
#define __WEAK __weak
#endif
#ifndef __PACKED
#define __PACKED @packed
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT @packed struct
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION @packed union
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
@packed struct T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
#define __ALIGNED(x)
#endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
#else
#error Unknown compiler.
#endif
#endif /* __CMSIS_COMPILER_H */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,39 @@
/**************************************************************************//**
* @file cmsis_version.h
* @brief CMSIS Core(M) Version definitions
* @version V5.0.2
* @date 19. April 2017
******************************************************************************/
/*
* Copyright (c) 2009-2017 ARM Limited. All rights reserved.
*
* 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
*
* 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.
*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef __CMSIS_VERSION_H
#define __CMSIS_VERSION_H
/* CMSIS Version definitions */
#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */
#define __CM_CMSIS_VERSION_SUB ( 1U) /*!< [15:0] CMSIS Core(M) sub version */
#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \
__CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,197 @@
/******************************************************************************
* @file mpu_armv7.h
* @brief CMSIS MPU API for Armv7-M MPU
* @version V5.0.4
* @date 10. January 2018
******************************************************************************/
/*
* Copyright (c) 2017-2018 Arm Limited. All rights reserved.
*
* 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
*
* 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.
*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef ARM_MPU_ARMV7_H
#define ARM_MPU_ARMV7_H
#define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U)
#define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U)
#define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U)
#define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U)
#define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U)
#define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U)
#define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU)
#define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU)
#define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU)
#define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU)
#define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU)
#define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU)
#define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U)
#define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U)
#define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U)
#define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U)
#define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U)
#define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U)
#define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U)
#define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U)
#define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U)
#define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U)
#define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU)
#define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU)
#define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU)
#define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU)
#define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU)
#define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU)
#define ARM_MPU_AP_NONE 0U
#define ARM_MPU_AP_PRIV 1U
#define ARM_MPU_AP_URO 2U
#define ARM_MPU_AP_FULL 3U
#define ARM_MPU_AP_PRO 5U
#define ARM_MPU_AP_RO 6U
/** MPU Region Base Address Register Value
*
* \param Region The region to be configured, number 0 to 15.
* \param BaseAddress The base address for the region.
*/
#define ARM_MPU_RBAR(Region, BaseAddress) \
(((BaseAddress) & MPU_RBAR_ADDR_Msk) | \
((Region) & MPU_RBAR_REGION_Msk) | \
(MPU_RBAR_VALID_Msk))
/**
* MPU Region Attribute and Size Register Value
*
* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
* \param IsShareable Region is shareable between multiple bus masters.
* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache.
* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
* \param SubRegionDisable Sub-region disable field.
* \param Size Region size of the region to be configured, for example 4K, 8K.
*/
#define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \
((((DisableExec ) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \
(((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \
(((TypeExtField ) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \
(((IsShareable ) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \
(((IsCacheable ) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \
(((IsBufferable ) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk) | \
(((SubRegionDisable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \
(((Size ) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \
(MPU_RASR_ENABLE_Msk))
/**
* Struct for a single MPU Region
*/
typedef struct {
uint32_t RBAR; //!< The region base address register value (RBAR)
uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR
} ARM_MPU_Region_t;
/** Enable the MPU.
* \param MPU_Control Default access permissions for unconfigured regions.
*/
__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control)
{
__DSB();
__ISB();
MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
#endif
}
/** Disable the MPU.
*/
__STATIC_INLINE void ARM_MPU_Disable(void)
{
__DSB();
__ISB();
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
#endif
MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
}
/** Clear and disable the given MPU region.
* \param rnr Region number to be cleared.
*/
__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr)
{
MPU->RNR = rnr;
MPU->RASR = 0U;
}
/** Configure an MPU region.
* \param rbar Value for RBAR register.
* \param rsar Value for RSAR register.
*/
__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr)
{
MPU->RBAR = rbar;
MPU->RASR = rasr;
}
/** Configure the given MPU region.
* \param rnr Region number to be configured.
* \param rbar Value for RBAR register.
* \param rsar Value for RSAR register.
*/
__STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr)
{
MPU->RNR = rnr;
MPU->RBAR = rbar;
MPU->RASR = rasr;
}
/** Memcopy with strictly ordered memory access, e.g. for register targets.
* \param dst Destination data is copied to.
* \param src Source data is copied from.
* \param len Amount of data words to be copied.
*/
__STATIC_INLINE void orderedCpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len)
{
uint32_t i;
for (i = 0U; i < len; ++i)
{
dst[i] = src[i];
}
}
/** Load the given number of MPU regions from a table.
* \param table Pointer to the MPU configuration table.
* \param cnt Amount of regions to be configured.
*/
__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt)
{
const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U;
while (cnt > MPU_TYPE_RALIASES) {
orderedCpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize);
table += MPU_TYPE_RALIASES;
cnt -= MPU_TYPE_RALIASES;
}
orderedCpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize);
}
#endif
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
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.
@@ -0,0 +1,79 @@
menuconfig BSP_USING_LPUART
bool "Using UART device"
default y
select RESOURCES_SERIAL
if BSP_USING_LPUART
source "$BSP_DIR/third_party_driver/uart/Kconfig"
endif
menuconfig BSP_USING_LWIP
bool "Using LwIP device"
default n
select RESOURCES_LWIP
menuconfig BSP_USING_GPIO
bool "Using GPIO device "
default y
select RESOURCES_PIN
if BSP_USING_GPIO
source "$BSP_DIR/third_party_driver/gpio/Kconfig"
endif
menuconfig BSP_USING_I2C
bool "Using I2C device"
default n
select RESOURCES_I2C
if BSP_USING_I2C
source "$BSP_DIR/third_party_driver/i2c/Kconfig"
endif
menuconfig BSP_USING_ADC
bool "Using ADC device"
default n
select RESOURCES_ADC
if BSP_USING_ADC
source "$BSP_DIR/third_party_driver/adc/Kconfig"
endif
menuconfig BSP_USING_SPI
bool "Using SPI device"
default n
select RESOURCES_SPI
if BSP_USING_SPI
source "$BSP_DIR/third_party_driver/spi/Kconfig"
endif
menuconfig BSP_USING_RTC
bool "Using RTC device"
default n
select RESOURCES_RTC
if BSP_USING_RTC
source "$BSP_DIR/third_party_driver/rtc/Kconfig"
endif
menuconfig BSP_USING_SEMC
bool "Using SEMC device"
default n
if BSP_USING_SEMC
source "$BSP_DIR/third_party_driver/semc/Kconfig"
endif
menuconfig BSP_USING_SDIO
bool "Using SD card device"
default n
select RESOURCES_SDIO
if BSP_USING_SDIO
source "$BSP_DIR/third_party_driver/sdio/Kconfig"
endif
menuconfig BSP_USING_USB
bool "Using USB device"
default n
select RESOURCES_USB
if BSP_USING_USB
source "$BSP_DIR/third_party_driver/usb/Kconfig"
endif
@@ -0,0 +1,39 @@
SRC_DIR := common gpio
ifeq ($(CONFIG_BSP_USING_LPUART),y)
SRC_DIR += uart
endif
ifeq ($(CONFIG_BSP_USING_LWIP),y)
SRC_DIR += ethernet
endif
ifeq ($(CONFIG_BSP_USING_I2C),y)
SRC_DIR += i2c
endif
ifeq ($(CONFIG_BSP_USING_ADC),y)
SRC_DIR += adc
endif
ifeq ($(CONFIG_BSP_USING_SPI),y)
SRC_DIR += spi
endif
ifeq ($(CONFIG_BSP_USING_SEMC),y)
SRC_DIR += semc
endif
ifeq ($(CONFIG_BSP_USING_RTC),y)
SRC_DIR += rtc
endif
ifeq ($(CONFIG_BSP_USING_SDIO),y)
SRC_DIR += sdio
endif
ifeq ($(CONFIG_BSP_USING_USB),y)
SRC_DIR += usb
endif
include $(KERNEL_ROOT)/compiler.mk
@@ -0,0 +1,29 @@
config BSP_USING_ADC1
bool "Enable ADC1"
default y
if BSP_USING_ADC1
config ADC_BUS_NAME_1
string "adc bus 1 name"
default "adc1"
config ADC_DRV_NAME_1
string "adc bus 1 driver name"
default "adc1_drv"
config ADC_1_DEVICE_NAME_0
string "adc bus 1 device name"
default "adc1_dev"
endif
config BSP_USING_ADC2
bool "Enable ADC2"
default y
if BSP_USING_ADC2
config ADC_BUS_NAME_2
string "adc bus 2 name"
default "adc2"
config ADC_DRV_NAME_2
string "adc bus 2 driver name"
default "adc2_drv"
config ADC_2_DEVICE_NAME_0
string "adc bus 2 device name"
default "adc2_dev"
endif
@@ -0,0 +1,3 @@
SRC_FILES := fsl_adc.c connect_adc.c
include $(KERNEL_ROOT)/compiler.mk
@@ -0,0 +1,295 @@
/*
* Copyright (c) 2022 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_adc.c
* @brief Demo for ADC function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022.1.18
*/
#include "board.h"
#include "fsl_adc.h"
#include "fsl_common.h"
#include "dev_adc.h"
#include "bus_adc.h"
#include "connect_adc.h"
#define ADC1_BASE_ADDR ADC1
#define ADC1_IRQ ADC1_IRQn
#define ADC1_USER_CHANNEL 3U
#define ADC1_CHANNEL_GROUP 0U
#define ADC2_BASE_ADDR ADC2
#define ADC2_IRQ ADC2_IRQn
#define ADC2_USER_CHANNEL 4U
#define ADC2_CHANNEL_GROUP 0U
#define adc_print KPrintf
volatile bool adc1_flag;
volatile uint32_t adc1_val;
volatile uint32_t adc1_irq_cnt;
volatile bool adc2_flag;
volatile uint32_t adc2_val;
volatile uint32_t adc2_irq_cnt;
/*******************************************************************************
* Code
******************************************************************************/
void ADC1_IRQHandler(int vector, void *param)
{
adc1_flag = true;
/* Read conversion result to clear the conversion completed flag. */
adc1_val = ADC_GetChannelConversionValue(ADC1_BASE_ADDR, ADC1_CHANNEL_GROUP);
adc1_irq_cnt++;
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
DECLARE_HW_IRQ(ADC1_IRQn, ADC1_IRQHandler, NONE);
void ADC2_IRQHandler(int vector, void *param)
{
adc2_flag = true;
/* Read conversion result to clear the conversion completed flag. */
adc2_val = ADC_GetChannelConversionValue(ADC2_BASE_ADDR, ADC2_CHANNEL_GROUP);
adc2_irq_cnt++;
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
DECLARE_HW_IRQ(ADC2_IRQn, ADC2_IRQHandler, NONE);
uint32 Imxrt1052AdcOpen(void *dev)
{
struct AdcHardwareDevice *adc_dev = (struct AdcHardwareDevice *)dev;
adc_config_t adc_cfg;
#ifdef BSP_USING_ADC1
if (0 == strncmp(adc_dev->haldev.dev_name, ADC_1_DEVICE_NAME_0, NAME_NUM_MAX)) {
EnableIRQ(ADC1_IRQn);
ADC_GetDefaultConfig(&adc_cfg);
ADC_Init(ADC1, &adc_cfg);
#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
ADC_EnableHardwareTrigger(ADC1, false);
#endif
/* Do auto hardware calibration. */
if (kStatus_Success == ADC_DoAutoCalibration(ADC1))
{
adc_print("ADC_DoAntoCalibration() Done.\r\n");
}
else
{
adc_print("ADC_DoAutoCalibration() Failed.\r\n");
}
}
#endif
#ifdef BSP_USING_ADC2
if (0 == strncmp(adc_dev->haldev.dev_name, ADC_2_DEVICE_NAME_0, NAME_NUM_MAX)) {
EnableIRQ(ADC2_IRQn);
ADC_GetDefaultConfig(&adc_cfg);
ADC_Init(ADC2, &adc_cfg);
#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
ADC_EnableHardwareTrigger(ADC2, false);
#endif
/* Do auto hardware calibration. */
if (kStatus_Success == ADC_DoAutoCalibration(ADC2))
{
adc_print("ADC_DoAntoCalibration() Done.\r\n");
}
else
{
adc_print("ADC_DoAutoCalibration() Failed.\r\n");
}
}
#endif
return EOK;
}
uint32 Imxrt1052AdcClose(void *dev)
{
return EOK;
}
uint32 Imxrt1052AdcRead(void *dev, struct BusBlockReadParam *read_param)
{
struct AdcHardwareDevice *adc_dev = (struct AdcHardwareDevice *)dev;
adc_channel_config_t ch_cfg;
#ifdef BSP_USING_ADC1
if (0 == strncmp(adc_dev->haldev.dev_name, ADC_1_DEVICE_NAME_0, NAME_NUM_MAX)) {
/* Configure the user channel and interrupt. */
ch_cfg.channelNumber = ADC1_USER_CHANNEL;
ch_cfg.enableInterruptOnConversionCompleted = true;
adc1_irq_cnt = 0U; /* Clear the interrupt counter. */
adc1_flag = false;
ADC_SetChannelConfig(ADC1, ADC1_CHANNEL_GROUP, &ch_cfg);
while (adc1_flag == false);
adc_print("ADC Value: %d\r\n", adc1_val);
adc_print("ADC Interrupt Counter: %d\r\n", adc1_irq_cnt);
}
#endif
#ifdef BSP_USING_ADC2
if (0 == strncmp(adc_dev->haldev.dev_name, ADC_2_DEVICE_NAME_0, NAME_NUM_MAX)) {
/* Configure the user channel and interrupt. */
ch_cfg.channelNumber = ADC2_USER_CHANNEL;
ch_cfg.enableInterruptOnConversionCompleted = true;
adc2_irq_cnt = 0U; /* Clear the interrupt counter. */
adc2_flag = false;
ADC_SetChannelConfig(ADC2, ADC2_CHANNEL_GROUP, &ch_cfg);
while (adc2_flag == false);
adc_print("ADC Value: %d\r\n", adc2_val);
adc_print("ADC Interrupt Counter: %d\r\n", adc2_irq_cnt);
}
#endif
return adc1_val;
}
static uint32 Imxrt1052AdcDrvConfigure(void *drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(drv);
NULL_PARAM_CHECK(configure_info);
x_err_t ret = EOK;
uint8 adc_channel;
struct AdcDriver *adc_drv = (struct AdcDriver *)drv;
struct AdcHardwareDevice *adc_dev = (struct AdcHardwareDevice *)adc_drv->driver.owner_bus->owner_haldev;
struct Imxrt1052HwAdc *adc_cfg = (struct Imxrt1052HwAdc *)adc_dev->haldev.private_data;
switch (configure_info->configure_cmd)
{
case OPE_CFG:
adc_cfg->adc_channel = *(uint8 *)configure_info->private_data;
if (adc_cfg->adc_channel > 18) {
KPrintf("Imxrt1052AdcDrvConfigure set adc channel(0-18) %u error!", adc_cfg->adc_channel);
adc_cfg->adc_channel = 0;
ret = ERROR;
}
break;
default:
break;
}
return ret;
}
static const struct AdcDevDone dev_done =
{
Imxrt1052AdcOpen,
Imxrt1052AdcClose,
NONE,
Imxrt1052AdcRead,
};
int Imxrt1052HwAdcInit(void)
{
x_err_t ret = EOK;
#ifdef BSP_USING_ADC1
static struct AdcBus adc1_bus;
static struct AdcDriver adc1_drv;
static struct AdcHardwareDevice adc1_dev;
static struct Imxrt1052HwAdc adc1_cfg;
adc1_drv.configure = Imxrt1052AdcDrvConfigure;
ret = AdcBusInit(&adc1_bus, ADC_BUS_NAME_1);
if (ret != EOK) {
KPrintf("ADC1 bus init error %d\n", ret);
return ERROR;
}
ret = AdcDriverInit(&adc1_drv, ADC_DRV_NAME_1);
if (ret != EOK) {
KPrintf("ADC1 driver init error %d\n", ret);
return ERROR;
}
ret = AdcDriverAttachToBus(ADC_DRV_NAME_1, ADC_BUS_NAME_1);
if (ret != EOK) {
KPrintf("ADC1 driver attach error %d\n", ret);
return ERROR;
}
adc1_dev.adc_dev_done = &dev_done;
ret = AdcDeviceRegister(&adc1_dev, (void *)&adc1_cfg, ADC_1_DEVICE_NAME_0);
if (ret != EOK) {
KPrintf("ADC1 device register error %d\n", ret);
return ERROR;
}
ret = AdcDeviceAttachToBus(ADC_1_DEVICE_NAME_0, ADC_BUS_NAME_1);
if (ret != EOK) {
KPrintf("ADC1 device register error %d\n", ret);
return ERROR;
}
#endif
#ifdef BSP_USING_ADC2
static struct AdcBus adc2_bus;
static struct AdcDriver adc2_drv;
static struct AdcHardwareDevice adc2_dev;
static struct Imxrt1052HwAdc adc2_cfg;
adc2_drv.configure = Imxrt1052AdcDrvConfigure;
ret = AdcBusInit(&adc2_bus, ADC_BUS_NAME_2);
if (ret != EOK) {
KPrintf("ADC2 bus init error %d\n", ret);
return ERROR;
}
ret = AdcDriverInit(&adc2_drv, ADC_DRV_NAME_2);
if (ret != EOK) {
KPrintf("ADC2 driver init error %d\n", ret);
return ERROR;
}
ret = AdcDriverAttachToBus(ADC_DRV_NAME_2, ADC_BUS_NAME_2);
if (ret != EOK) {
KPrintf("ADC2 driver attach error %d\n", ret);
return ERROR;
}
adc2_dev.adc_dev_done = &dev_done;
ret = AdcDeviceRegister(&adc2_dev, (void *)&adc2_cfg, ADC_2_DEVICE_NAME_0);
if (ret != EOK) {
KPrintf("ADC2 device register error %d\n", ret);
return ERROR;
}
ret = AdcDeviceAttachToBus(ADC_2_DEVICE_NAME_0, ADC_BUS_NAME_2);
if (ret != EOK) {
KPrintf("ADC2 device register error %d\n", ret);
return ERROR;
}
#endif
return ret;
}
@@ -0,0 +1,394 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_adc.h"
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.adc_12b1msps_sar"
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get instance number for ADC module.
*
* @param base ADC peripheral base address
*/
static uint32_t ADC_GetInstance(ADC_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to ADC bases for each instance. */
static ADC_Type *const s_adcBases[] = ADC_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to ADC clocks for each instance. */
static const clock_ip_name_t s_adcClocks[] = ADC_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t ADC_GetInstance(ADC_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_adcBases); instance++)
{
if (s_adcBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_adcBases));
return instance;
}
/*!
* brief Initialize the ADC module.
*
* param base ADC peripheral base address.
* param config Pointer to "adc_config_t" structure.
*/
void ADC_Init(ADC_Type *base, const adc_config_t *config)
{
assert(NULL != config);
uint32_t tmp32;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable the clock. */
CLOCK_EnableClock(s_adcClocks[ADC_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/* ADCx_CFG */
tmp32 = base->CFG & (ADC_CFG_AVGS_MASK | ADC_CFG_ADTRG_MASK); /* Reserve AVGS and ADTRG bits. */
tmp32 |= ADC_CFG_REFSEL(config->referenceVoltageSource) | ADC_CFG_ADSTS(config->samplePeriodMode) |
ADC_CFG_ADICLK(config->clockSource) | ADC_CFG_ADIV(config->clockDriver) | ADC_CFG_MODE(config->resolution);
if (config->enableOverWrite)
{
tmp32 |= ADC_CFG_OVWREN_MASK;
}
if (config->enableLongSample)
{
tmp32 |= ADC_CFG_ADLSMP_MASK;
}
if (config->enableLowPower)
{
tmp32 |= ADC_CFG_ADLPC_MASK;
}
if (config->enableHighSpeed)
{
tmp32 |= ADC_CFG_ADHSC_MASK;
}
base->CFG = tmp32;
/* ADCx_GC */
tmp32 = base->GC & ~(ADC_GC_ADCO_MASK | ADC_GC_ADACKEN_MASK);
if (config->enableContinuousConversion)
{
tmp32 |= ADC_GC_ADCO_MASK;
}
if (config->enableAsynchronousClockOutput)
{
tmp32 |= ADC_GC_ADACKEN_MASK;
}
base->GC = tmp32;
}
/*!
* brief De-initializes the ADC module.
*
* param base ADC peripheral base address.
*/
void ADC_Deinit(ADC_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Disable the clock. */
CLOCK_DisableClock(s_adcClocks[ADC_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
/*!
* brief Gets an available pre-defined settings for the converter's configuration.
*
* This function initializes the converter configuration structure with available settings. The default values are:
* code
* config->enableAsynchronousClockOutput = true;
* config->enableOverWrite = false;
* config->enableContinuousConversion = false;
* config->enableHighSpeed = false;
* config->enableLowPower = false;
* config->enableLongSample = false;
* config->referenceVoltageSource = kADC_ReferenceVoltageSourceAlt0;
* config->samplePeriodMode = kADC_SamplePeriod2or12Clocks;
* config->clockSource = kADC_ClockSourceAD;
* config->clockDriver = kADC_ClockDriver1;
* config->resolution = kADC_Resolution12Bit;
* endcode
* param base ADC peripheral base address.
* param config Pointer to the configuration structure.
*/
void ADC_GetDefaultConfig(adc_config_t *config)
{
assert(NULL != config);
/* Initializes the configure structure to zero. */
memset(config, 0, sizeof(*config));
config->enableAsynchronousClockOutput = true;
config->enableOverWrite = false;
config->enableContinuousConversion = false;
config->enableHighSpeed = false;
config->enableLowPower = false;
config->enableLongSample = false;
config->referenceVoltageSource = kADC_ReferenceVoltageSourceAlt0;
config->samplePeriodMode = kADC_SamplePeriod2or12Clocks;
config->clockSource = kADC_ClockSourceAD;
config->clockDriver = kADC_ClockDriver1;
config->resolution = kADC_Resolution12Bit;
}
/*!
* brief Configures the conversion channel.
*
* This operation triggers the conversion when in software trigger mode. When in hardware trigger mode, this API
* configures the channel while the external trigger source helps to trigger the conversion.
*
* Note that the "Channel Group" has a detailed description.
* To allow sequential conversions of the ADC to be triggered by internal peripherals, the ADC has more than one
* group of status and control registers, one for each conversion. The channel group parameter indicates which group of
* registers are used, for example channel group 0 is for Group A registers and channel group 1 is for Group B
* registers. The
* channel groups are used in a "ping-pong" approach to control the ADC operation. At any point, only one of
* the channel groups is actively controlling ADC conversions. The channel group 0 is used for both software and
* hardware
* trigger modes. Channel groups 1 and greater indicate potentially multiple channel group registers for
* use only in hardware trigger mode. See the chip configuration information in the appropriate MCU reference manual
* about the
* number of SC1n registers (channel groups) specific to this device. None of the channel groups 1 or greater are used
* for software trigger operation. Therefore, writing to these channel groups does not initiate a new conversion.
* Updating the channel group 0 while a different channel group is actively controlling a conversion is allowed and
* vice versa. Writing any of the channel group registers while that specific channel group is actively controlling a
* conversion aborts the current conversion.
*
* param base ADC peripheral base address.
* param channelGroup Channel group index.
* param config Pointer to the "adc_channel_config_t" structure for the conversion channel.
*/
void ADC_SetChannelConfig(ADC_Type *base, uint32_t channelGroup, const adc_channel_config_t *config)
{
assert(NULL != config);
assert(channelGroup < FSL_FEATURE_ADC_CONVERSION_CONTROL_COUNT);
uint32_t tmp32;
tmp32 = ADC_HC_ADCH(config->channelNumber);
if (config->enableInterruptOnConversionCompleted)
{
tmp32 |= ADC_HC_AIEN_MASK;
}
base->HC[channelGroup] = tmp32;
}
/*
*To complete calibration, the user must follow the below procedure:
* 1. Configure ADC_CFG with actual operating values for maximum accuracy.
* 2. Configure the ADC_GC values along with CAL bit.
* 3. Check the status of CALF bit in ADC_GS and the CAL bit in ADC_GC.
* 4. When CAL bit becomes '0' then check the CALF status and COCO[0] bit status.
*/
/*!
* brief Automates the hardware calibration.
*
* This auto calibration helps to adjust the plus/minus side gain automatically.
* Execute the calibration before using the converter. Note that the software trigger should be used
* during calibration.
*
* param base ADC peripheral base address.
*
* return Execution status.
* retval kStatus_Success Calibration is done successfully.
* retval kStatus_Fail Calibration has failed.
*/
status_t ADC_DoAutoCalibration(ADC_Type *base)
{
status_t status = kStatus_Success;
#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
bool bHWTrigger = false;
/* The calibration would be failed when in hardwar mode.
* Remember the hardware trigger state here and restore it later if the hardware trigger is enabled.*/
if (0U != (ADC_CFG_ADTRG_MASK & base->CFG))
{
bHWTrigger = true;
ADC_EnableHardwareTrigger(base, false);
}
#endif
/* Clear the CALF and launch the calibration. */
base->GS = ADC_GS_CALF_MASK; /* Clear the CALF. */
base->GC |= ADC_GC_CAL_MASK; /* Launch the calibration. */
/* Check the status of CALF bit in ADC_GS and the CAL bit in ADC_GC. */
while (0U != (base->GC & ADC_GC_CAL_MASK))
{
/* Check the CALF when the calibration is active. */
if (0U != (ADC_GetStatusFlags(base) & kADC_CalibrationFailedFlag))
{
status = kStatus_Fail;
break;
}
}
/* When CAL bit becomes '0' then check the CALF status and COCO[0] bit status. */
if (0U == ADC_GetChannelStatusFlags(base, 0U)) /* Check the COCO[0] bit status. */
{
status = kStatus_Fail;
}
if (0U != (ADC_GetStatusFlags(base) & kADC_CalibrationFailedFlag)) /* Check the CALF status. */
{
status = kStatus_Fail;
}
/* Clear conversion done flag. */
ADC_GetChannelConversionValue(base, 0U);
#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
/* Restore original trigger mode. */
if (true == bHWTrigger)
{
ADC_EnableHardwareTrigger(base, true);
}
#endif
return status;
}
/*!
* brief Set user defined offset.
*
* param base ADC peripheral base address.
* param config Pointer to "adc_offest_config_t" structure.
*/
void ADC_SetOffsetConfig(ADC_Type *base, const adc_offest_config_t *config)
{
assert(NULL != config);
uint32_t tmp32;
tmp32 = ADC_OFS_OFS(config->offsetValue);
if (config->enableSigned)
{
tmp32 |= ADC_OFS_SIGN_MASK;
}
base->OFS = tmp32;
}
/*!
* brief Configures the hardware compare mode.
*
* The hardware compare mode provides a way to process the conversion result automatically by using hardware. Only the
* result
* in the compare range is available. To compare the range, see "adc_hardware_compare_mode_t" or the appopriate
* reference
* manual for more information.
*
* param base ADC peripheral base address.
* param Pointer to "adc_hardware_compare_config_t" structure.
*
*/
void ADC_SetHardwareCompareConfig(ADC_Type *base, const adc_hardware_compare_config_t *config)
{
uint32_t tmp32;
tmp32 = base->GC & ~(ADC_GC_ACFE_MASK | ADC_GC_ACFGT_MASK | ADC_GC_ACREN_MASK);
if (NULL == config) /* Pass "NULL" to disable the feature. */
{
base->GC = tmp32;
return;
}
/* Enable the feature. */
tmp32 |= ADC_GC_ACFE_MASK;
/* Select the hardware compare working mode. */
switch (config->hardwareCompareMode)
{
case kADC_HardwareCompareMode0:
break;
case kADC_HardwareCompareMode1:
tmp32 |= ADC_GC_ACFGT_MASK;
break;
case kADC_HardwareCompareMode2:
tmp32 |= ADC_GC_ACREN_MASK;
break;
case kADC_HardwareCompareMode3:
tmp32 |= ADC_GC_ACFGT_MASK | ADC_GC_ACREN_MASK;
break;
default:
break;
}
base->GC = tmp32;
/* Load the compare values. */
tmp32 = ADC_CV_CV1(config->value1) | ADC_CV_CV2(config->value2);
base->CV = tmp32;
}
/*!
* brief Configures the hardware average mode.
*
* The hardware average mode provides a way to process the conversion result automatically by using hardware. The
* multiple
* conversion results are accumulated and averaged internally making them easier to read.
*
* param base ADC peripheral base address.
* param mode Setting the hardware average mode. See "adc_hardware_average_mode_t".
*/
void ADC_SetHardwareAverageConfig(ADC_Type *base, adc_hardware_average_mode_t mode)
{
uint32_t tmp32;
if (mode == kADC_HardwareAverageDiasable)
{
base->GC &= ~ADC_GC_AVGE_MASK;
}
else
{
tmp32 = base->CFG & ~ADC_CFG_AVGS_MASK;
tmp32 |= ADC_CFG_AVGS(mode);
base->CFG = tmp32;
base->GC |= ADC_GC_AVGE_MASK; /* Enable the hardware compare. */
}
}
/*!
* brief Clears the converter's status falgs.
*
* param base ADC peripheral base address.
* param mask Mask value for the cleared flags. See "adc_status_flags_t".
*/
void ADC_ClearStatusFlags(ADC_Type *base, uint32_t mask)
{
uint32_t tmp32 = 0;
if (0U != (mask & kADC_CalibrationFailedFlag))
{
tmp32 |= ADC_GS_CALF_MASK;
}
if (0U != (mask & kADC_ConversionActiveFlag))
{
tmp32 |= ADC_GS_ADACT_MASK;
}
base->GS = tmp32;
}
@@ -0,0 +1,420 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_ADC_H_
#define _FSL_ADC_H_
#include "fsl_common.h"
/*!
* @addtogroup adc_12b1msps_sar
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief ADC driver version */
#define FSL_ADC_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) /*!< Version 2.0.2. */
/*!
* @brief Converter's status flags.
*/
typedef enum _adc_status_flags
{
kADC_ConversionActiveFlag = ADC_GS_ADACT_MASK, /*!< Conversion is active,not support w1c. */
kADC_CalibrationFailedFlag = ADC_GS_CALF_MASK, /*!< Calibration is failed,support w1c. */
kADC_AsynchronousWakeupInterruptFlag =
ADC_GS_AWKST_MASK, /*!< Asynchronous wakeup interrupt occurred, support w1c. */
} adc_status_flags_t;
/*!
* @brief Reference voltage source.
*/
typedef enum _adc_reference_voltage_source
{
kADC_ReferenceVoltageSourceAlt0 = 0U, /*!< For external pins pair of VrefH and VrefL. */
} adc_reference_voltage_source_t;
/*!
* @brief Sample time duration.
*/
typedef enum _adc_sample_period_mode
{
/* This group of enumeration is for internal use which is related to register setting. */
kADC_SamplePeriod2or12Clocks = 0U, /*!< Long sample 12 clocks or short sample 2 clocks. */
kADC_SamplePeriod4or16Clocks = 1U, /*!< Long sample 16 clocks or short sample 4 clocks. */
kADC_SamplePeriod6or20Clocks = 2U, /*!< Long sample 20 clocks or short sample 6 clocks. */
kADC_SamplePeriod8or24Clocks = 3U, /*!< Long sample 24 clocks or short sample 8 clocks. */
/* This group of enumeration is for a public user. */
/* For long sample mode. */
kADC_SamplePeriodLong12Clcoks = kADC_SamplePeriod2or12Clocks, /*!< Long sample 12 clocks. */
kADC_SamplePeriodLong16Clcoks = kADC_SamplePeriod4or16Clocks, /*!< Long sample 16 clocks. */
kADC_SamplePeriodLong20Clcoks = kADC_SamplePeriod6or20Clocks, /*!< Long sample 20 clocks. */
kADC_SamplePeriodLong24Clcoks = kADC_SamplePeriod8or24Clocks, /*!< Long sample 24 clocks. */
/* For short sample mode. */
kADC_SamplePeriodShort2Clocks = kADC_SamplePeriod2or12Clocks, /*!< Short sample 2 clocks. */
kADC_SamplePeriodShort4Clocks = kADC_SamplePeriod4or16Clocks, /*!< Short sample 4 clocks. */
kADC_SamplePeriodShort6Clocks = kADC_SamplePeriod6or20Clocks, /*!< Short sample 6 clocks. */
kADC_SamplePeriodShort8Clocks = kADC_SamplePeriod8or24Clocks, /*!< Short sample 8 clocks. */
} adc_sample_period_mode_t;
/*!
* @brief Clock source.
*/
typedef enum _adc_clock_source
{
kADC_ClockSourceIPG = 0U, /*!< Select IPG clock to generate ADCK. */
kADC_ClockSourceIPGDiv2 = 1U, /*!< Select IPG clock divided by 2 to generate ADCK. */
#if !(defined(FSL_FEATURE_ADC_SUPPORT_ALTCLK_REMOVE) && FSL_FEATURE_ADC_SUPPORT_ALTCLK_REMOVE)
kADC_ClockSourceALT = 2U, /*!< Select alternate clock to generate ADCK. */
#endif
kADC_ClockSourceAD = 3U, /*!< Select Asynchronous clock to generate ADCK. */
} adc_clock_source_t;
/*!
* @brief Clock divider for the converter.
*/
typedef enum _adc_clock_drvier
{
kADC_ClockDriver1 = 0U, /*!< For divider 1 from the input clock to the module. */
kADC_ClockDriver2 = 1U, /*!< For divider 2 from the input clock to the module. */
kADC_ClockDriver4 = 2U, /*!< For divider 4 from the input clock to the module. */
kADC_ClockDriver8 = 3U, /*!< For divider 8 from the input clock to the module. */
} adc_clock_driver_t;
/*!
* @brief Converter's resolution.
*/
typedef enum _adc_resolution
{
kADC_Resolution8Bit = 0U, /*!< Single End 8-bit resolution. */
kADC_Resolution10Bit = 1U, /*!< Single End 10-bit resolution. */
kADC_Resolution12Bit = 2U, /*!< Single End 12-bit resolution. */
} adc_resolution_t;
/*!
* @brief Converter hardware compare mode.
*/
typedef enum _adc_hardware_compare_mode
{
kADC_HardwareCompareMode0 = 0U, /*!< Compare true if the result is less than the value1. */
kADC_HardwareCompareMode1 = 1U, /*!< Compare true if the result is greater than or equal to value1. */
kADC_HardwareCompareMode2 = 2U, /*!< Value1 <= Value2, compare true if the result is less than value1 Or
the result is Greater than value2.
Value1 > Value2, compare true if the result is less than value1 And the
result is greater than value2*/
kADC_HardwareCompareMode3 = 3U, /*!< Value1 <= Value2, compare true if the result is greater than or equal
to value1 And the result is less than or equal to value2.
Value1 > Value2, compare true if the result is greater than or equal to
value1 Or the result is less than or equal to value2. */
} adc_hardware_compare_mode_t;
/*!
* @brief Converter hardware average mode.
*/
typedef enum _adc_hardware_average_mode
{
kADC_HardwareAverageCount4 = 0U, /*!< For hardware average with 4 samples. */
kADC_HardwareAverageCount8 = 1U, /*!< For hardware average with 8 samples. */
kADC_HardwareAverageCount16 = 2U, /*!< For hardware average with 16 samples. */
kADC_HardwareAverageCount32 = 3U, /*!< For hardware average with 32 samples. */
kADC_HardwareAverageDiasable = 4U, /*!< Disable the hardware average function. */
} adc_hardware_average_mode_t;
/*!
* @brief Converter configuration.
*/
typedef struct _adc_config
{
bool enableOverWrite; /*!< Enable the overwriting. */
bool enableContinuousConversion; /*!< Enable the continuous conversion mode. */
bool enableHighSpeed; /*!< Enable the high-speed mode. */
bool enableLowPower; /*!< Enable the low power mode. */
bool enableLongSample; /*!< Enable the long sample mode. */
bool enableAsynchronousClockOutput; /*!< Enable the asynchronous clock output. */
adc_reference_voltage_source_t referenceVoltageSource; /*!< Select the reference voltage source. */
adc_sample_period_mode_t samplePeriodMode; /*!< Select the sample period in long sample mode or short mode. */
adc_clock_source_t clockSource; /*!< Select the input clock source to generate the internal clock ADCK. */
adc_clock_driver_t clockDriver; /*!< Select the divide ratio used by the ADC to generate the internal clock ADCK. */
adc_resolution_t resolution; /*!< Select the ADC resolution mode. */
} adc_config_t;
/*!
* @brief Converter Offset configuration.
*/
typedef struct _adc_offest_config
{
bool enableSigned; /*!< if false,The offset value is added with the raw result.
if true,The offset value is subtracted from the raw converted value. */
uint32_t offsetValue; /*!< User configurable offset value(0-4095). */
} adc_offest_config_t;
/*!
* @brief ADC hardware compare configuration.
*
* In kADC_HardwareCompareMode0, compare true if the result is less than the value1.
* In kADC_HardwareCompareMode1, compare true if the result is greater than or equal to value1.
* In kADC_HardwareCompareMode2, Value1 <= Value2, compare true if the result is less than value1 Or the result is
* Greater than value2.
* Value1 > Value2, compare true if the result is less than value1 And the result is
* Greater than value2.
* In kADC_HardwareCompareMode3, Value1 <= Value2, compare true if the result is greater than or equal to value1 And the
* result is less than or equal to value2.
* Value1 > Value2, compare true if the result is greater than or equal to value1 Or the
* result is less than or equal to value2.
*/
typedef struct _adc_hardware_compare_config
{
adc_hardware_compare_mode_t hardwareCompareMode; /*!< Select the hardware compare mode.
See "adc_hardware_compare_mode_t". */
uint16_t value1; /*!< Setting value1(0-4095) for hardware compare mode. */
uint16_t value2; /*!< Setting value2(0-4095) for hardware compare mode. */
} adc_hardware_compare_config_t;
/*!
* @brief ADC channel conversion configuration.
*/
typedef struct _adc_channel_config
{
uint32_t channelNumber; /*!< Setting the conversion channel number. The available range is 0-31.
See channel connection information for each chip in Reference
Manual document. */
bool enableInterruptOnConversionCompleted; /*!< Generate an interrupt request once the conversion is completed. */
} adc_channel_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Initialization
* @{
*/
/*!
* @brief Initialize the ADC module.
*
* @param base ADC peripheral base address.
* @param config Pointer to "adc_config_t" structure.
*/
void ADC_Init(ADC_Type *base, const adc_config_t *config);
/*!
* @brief De-initializes the ADC module.
*
* @param base ADC peripheral base address.
*/
void ADC_Deinit(ADC_Type *base);
/*!
* @brief Gets an available pre-defined settings for the converter's configuration.
*
* This function initializes the converter configuration structure with available settings. The default values are:
* @code
* config->enableAsynchronousClockOutput = true;
* config->enableOverWrite = false;
* config->enableContinuousConversion = false;
* config->enableHighSpeed = false;
* config->enableLowPower = false;
* config->enableLongSample = false;
* config->referenceVoltageSource = kADC_ReferenceVoltageSourceAlt0;
* config->samplePeriodMode = kADC_SamplePeriod2or12Clocks;
* config->clockSource = kADC_ClockSourceAD;
* config->clockDriver = kADC_ClockDriver1;
* config->resolution = kADC_Resolution12Bit;
* @endcode
* @param base ADC peripheral base address.
* @param config Pointer to the configuration structure.
*/
void ADC_GetDefaultConfig(adc_config_t *config);
/*!
* @brief Configures the conversion channel.
*
* This operation triggers the conversion when in software trigger mode. When in hardware trigger mode, this API
* configures the channel while the external trigger source helps to trigger the conversion.
*
* Note that the "Channel Group" has a detailed description.
* To allow sequential conversions of the ADC to be triggered by internal peripherals, the ADC has more than one
* group of status and control registers, one for each conversion. The channel group parameter indicates which group of
* registers are used, for example channel group 0 is for Group A registers and channel group 1 is for Group B
* registers. The
* channel groups are used in a "ping-pong" approach to control the ADC operation. At any point, only one of
* the channel groups is actively controlling ADC conversions. The channel group 0 is used for both software and
* hardware
* trigger modes. Channel groups 1 and greater indicate potentially multiple channel group registers for
* use only in hardware trigger mode. See the chip configuration information in the appropriate MCU reference manual
* about the
* number of SC1n registers (channel groups) specific to this device. None of the channel groups 1 or greater are used
* for software trigger operation. Therefore, writing to these channel groups does not initiate a new conversion.
* Updating the channel group 0 while a different channel group is actively controlling a conversion is allowed and
* vice versa. Writing any of the channel group registers while that specific channel group is actively controlling a
* conversion aborts the current conversion.
*
* @param base ADC peripheral base address.
* @param channelGroup Channel group index.
* @param config Pointer to the "adc_channel_config_t" structure for the conversion channel.
*/
void ADC_SetChannelConfig(ADC_Type *base, uint32_t channelGroup, const adc_channel_config_t *config);
/*!
* @brief Gets the conversion value.
*
* @param base ADC peripheral base address.
* @param channelGroup Channel group index.
*
* @return Conversion value.
*/
static inline uint32_t ADC_GetChannelConversionValue(ADC_Type *base, uint32_t channelGroup)
{
assert(channelGroup < FSL_FEATURE_ADC_CONVERSION_CONTROL_COUNT);
return base->R[channelGroup];
}
/*!
* @brief Gets the status flags of channel.
*
* A conversion is completed when the result of the conversion is transferred into the data
* result registers. (provided the compare function & hardware averaging is disabled), this is
* indicated by the setting of COCOn. If hardware averaging is enabled, COCOn sets only,
* if the last of the selected number of conversions is complete. If the compare function is
* enabled, COCOn sets and conversion result data is transferred only if the compare
* condition is true. If both hardware averaging and compare functions are enabled, then
* COCOn sets only if the last of the selected number of conversions is complete and the
* compare condition is true.
*
* @param base ADC peripheral base address.
* @param channelGroup Channel group index.
*
* @return Status flags of channel.return 0 means COCO flag is 0,return 1 means COCOflag is 1.
*/
static inline uint32_t ADC_GetChannelStatusFlags(ADC_Type *base, uint32_t channelGroup)
{
assert(channelGroup < FSL_FEATURE_ADC_CONVERSION_CONTROL_COUNT);
/* If flag is set,return 1,otherwise, return 0. */
return (((base->HS) & (1U << channelGroup)) >> channelGroup);
}
/*!
* @brief Automates the hardware calibration.
*
* This auto calibration helps to adjust the plus/minus side gain automatically.
* Execute the calibration before using the converter. Note that the software trigger should be used
* during calibration.
*
* @param base ADC peripheral base address.
*
* @return Execution status.
* @retval kStatus_Success Calibration is done successfully.
* @retval kStatus_Fail Calibration has failed.
*/
status_t ADC_DoAutoCalibration(ADC_Type *base);
/*!
* @brief Set user defined offset.
*
* @param base ADC peripheral base address.
* @param config Pointer to "adc_offest_config_t" structure.
*/
void ADC_SetOffsetConfig(ADC_Type *base, const adc_offest_config_t *config);
/*!
* @brief Enables generating the DMA trigger when the conversion is complete.
*
* @param base ADC peripheral base address.
* @param enable Switcher of the DMA feature. "true" means enabled, "false" means not enabled.
*/
static inline void ADC_EnableDMA(ADC_Type *base, bool enable)
{
if (enable)
{
base->GC |= ADC_GC_DMAEN_MASK;
}
else
{
base->GC &= ~ADC_GC_DMAEN_MASK;
}
}
/*!
* @brief Enables the hardware trigger mode.
*
* @param base ADC peripheral base address.
* @param enable Switcher of the trigger mode. "true" means hardware tirgger mode,"false" means software mode.
*/
#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
static inline void ADC_EnableHardwareTrigger(ADC_Type *base, bool enable)
{
if (enable)
{
base->CFG |= ADC_CFG_ADTRG_MASK;
}
else
{
base->CFG &= ~ADC_CFG_ADTRG_MASK;
}
}
#endif
/*!
* @brief Configures the hardware compare mode.
*
* The hardware compare mode provides a way to process the conversion result automatically by using hardware. Only the
* result
* in the compare range is available. To compare the range, see "adc_hardware_compare_mode_t" or the appopriate
* reference
* manual for more information.
*
* @param base ADC peripheral base address.
* @param Pointer to "adc_hardware_compare_config_t" structure.
*
*/
void ADC_SetHardwareCompareConfig(ADC_Type *base, const adc_hardware_compare_config_t *config);
/*!
* @brief Configures the hardware average mode.
*
* The hardware average mode provides a way to process the conversion result automatically by using hardware. The
* multiple
* conversion results are accumulated and averaged internally making them easier to read.
*
* @param base ADC peripheral base address.
* @param mode Setting the hardware average mode. See "adc_hardware_average_mode_t".
*/
void ADC_SetHardwareAverageConfig(ADC_Type *base, adc_hardware_average_mode_t mode);
/*!
* @brief Gets the converter's status flags.
*
* @param base ADC peripheral base address.
*
* @return Flags' mask if indicated flags are asserted. See "adc_status_flags_t".
*/
static inline uint32_t ADC_GetStatusFlags(ADC_Type *base)
{
return base->GS;
}
/*!
* @brief Clears the converter's status falgs.
*
* @param base ADC peripheral base address.
* @param mask Mask value for the cleared flags. See "adc_status_flags_t".
*/
void ADC_ClearStatusFlags(ADC_Type *base, uint32_t mask);
#if defined(__cplusplus)
}
#endif
#endif /* _FSL_ADC_H_ */
@@ -0,0 +1,7 @@
SRC_FILES := system_MIMXRT1052.c fsl_cache.c fsl_clock.c fsl_common.c pin_mux.c clock_config.c
ifeq ($(CONFIG_BSP_USING_SDIO),y)
SRC_FILES += fsl_usdhc.c
endif
include $(KERNEL_ROOT)/compiler.mk
@@ -0,0 +1,479 @@
/*
* Copyright 2017-2019 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file clock_config.c
* @brief support ok1052-c board clock configure
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-05-29
*/
/*
* How to setup clock using clock driver functions:
*
* 1. Call CLOCK_InitXXXPLL() to configure corresponding PLL clock.
*
* 2. Call CLOCK_InitXXXpfd() to configure corresponding PLL pfd clock.
*
* 3. Call CLOCK_SetMux() to configure corresponding clock source for target clock out.
*
* 4. Call CLOCK_SetDiv() to configure corresponding clock divider for target clock out.
*
* 5. Call CLOCK_SetXtalFreq() to set XTAL frequency based on board settings.
*
*/
/* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
!!GlobalInfo
product: Clocks v5.0
processor: MIMXRT1052xxxxB
package_id: MIMXRT1052DVL6B
mcu_data: ksdk2_0
processor_version: 5.0.2
board: IMXRT1050-EVKB
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/
#include "clock_config.h"
#include "fsl_iomuxc.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
/* System clock frequency. */
extern uint32_t SystemCoreClock;
/*******************************************************************************
************************ BOARD_InitBootClocks function ************************
******************************************************************************/
void BOARD_InitBootClocks(void)
{
BOARD_BootClockRUN();
}
/*******************************************************************************
********************** Configuration BOARD_BootClockRUN ***********************
******************************************************************************/
/* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
!!Configuration
name: BOARD_BootClockRUN
called_from_default_init: true
outputs:
- {id: AHB_CLK_ROOT.outFreq, value: 600 MHz}
- {id: CAN_CLK_ROOT.outFreq, value: 40 MHz}
- {id: CKIL_SYNC_CLK_ROOT.outFreq, value: 32.768 kHz}
- {id: CLK_1M.outFreq, value: 1 MHz}
- {id: CLK_24M.outFreq, value: 24 MHz}
- {id: CSI_CLK_ROOT.outFreq, value: 12 MHz}
- {id: ENET1_TX_CLK.outFreq, value: 2.4 MHz}
- {id: ENET_125M_CLK.outFreq, value: 2.4 MHz}
- {id: ENET_25M_REF_CLK.outFreq, value: 1.2 MHz}
- {id: FLEXIO1_CLK_ROOT.outFreq, value: 30 MHz}
- {id: FLEXIO2_CLK_ROOT.outFreq, value: 30 MHz}
- {id: FLEXSPI_CLK_ROOT.outFreq, value: 2880/11 MHz}
- {id: GPT1_ipg_clk_highfreq.outFreq, value: 75 MHz}
- {id: GPT2_ipg_clk_highfreq.outFreq, value: 75 MHz}
- {id: IPG_CLK_ROOT.outFreq, value: 150 MHz}
- {id: LCDIF_CLK_ROOT.outFreq, value: 67.5/7 MHz}
- {id: LPI2C_CLK_ROOT.outFreq, value: 60 MHz}
- {id: LPSPI_CLK_ROOT.outFreq, value: 105.6 MHz}
- {id: LVDS1_CLK.outFreq, value: 1.2 GHz}
- {id: MQS_MCLK.outFreq, value: 1080/17 MHz}
- {id: PERCLK_CLK_ROOT.outFreq, value: 75 MHz}
- {id: PLL7_MAIN_CLK.outFreq, value: 24 MHz}
- {id: SAI1_CLK_ROOT.outFreq, value: 1080/17 MHz}
- {id: SAI1_MCLK1.outFreq, value: 1080/17 MHz}
- {id: SAI1_MCLK2.outFreq, value: 1080/17 MHz}
- {id: SAI1_MCLK3.outFreq, value: 30 MHz}
- {id: SAI2_CLK_ROOT.outFreq, value: 1080/17 MHz}
- {id: SAI2_MCLK1.outFreq, value: 1080/17 MHz}
- {id: SAI2_MCLK3.outFreq, value: 30 MHz}
- {id: SAI3_CLK_ROOT.outFreq, value: 1080/17 MHz}
- {id: SAI3_MCLK1.outFreq, value: 1080/17 MHz}
- {id: SAI3_MCLK3.outFreq, value: 30 MHz}
- {id: SEMC_CLK_ROOT.outFreq, value: 75 MHz}
- {id: SPDIF0_CLK_ROOT.outFreq, value: 30 MHz}
- {id: TRACE_CLK_ROOT.outFreq, value: 352/3 MHz}
- {id: UART_CLK_ROOT.outFreq, value: 80 MHz}
- {id: USDHC1_CLK_ROOT.outFreq, value: 198 MHz}
- {id: USDHC2_CLK_ROOT.outFreq, value: 198 MHz}
settings:
- {id: CCM.AHB_PODF.scale, value: '1', locked: true}
- {id: CCM.ARM_PODF.scale, value: '2', locked: true}
- {id: CCM.FLEXSPI_PODF.scale, value: '1', locked: true}
- {id: CCM.FLEXSPI_SEL.sel, value: CCM_ANALOG.PLL3_PFD0_CLK}
- {id: CCM.LCDIF_PODF.scale, value: '8', locked: true}
- {id: CCM.LCDIF_PRED.scale, value: '7', locked: true}
- {id: CCM.LPSPI_PODF.scale, value: '5', locked: true}
- {id: CCM.PERCLK_PODF.scale, value: '2', locked: true}
- {id: CCM.SEMC_PODF.scale, value: '8'}
- {id: CCM.TRACE_PODF.scale, value: '3', locked: true}
- {id: CCM_ANALOG.PLL1_BYPASS.sel, value: CCM_ANALOG.PLL1}
- {id: CCM_ANALOG.PLL1_PREDIV.scale, value: '1', locked: true}
- {id: CCM_ANALOG.PLL1_VDIV.scale, value: '50', locked: true}
- {id: CCM_ANALOG.PLL2.denom, value: '1', locked: true}
- {id: CCM_ANALOG.PLL2.num, value: '0', locked: true}
- {id: CCM_ANALOG.PLL2_BYPASS.sel, value: CCM_ANALOG.PLL2_OUT_CLK}
- {id: CCM_ANALOG.PLL2_PFD0_BYPASS.sel, value: CCM_ANALOG.PLL2_PFD0}
- {id: CCM_ANALOG.PLL2_PFD1_BYPASS.sel, value: CCM_ANALOG.PLL2_PFD1}
- {id: CCM_ANALOG.PLL2_PFD2_BYPASS.sel, value: CCM_ANALOG.PLL2_PFD2}
- {id: CCM_ANALOG.PLL2_PFD3_BYPASS.sel, value: CCM_ANALOG.PLL2_PFD3}
- {id: CCM_ANALOG.PLL3_BYPASS.sel, value: CCM_ANALOG.PLL3}
- {id: CCM_ANALOG.PLL3_PFD0_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD0}
- {id: CCM_ANALOG.PLL3_PFD0_DIV.scale, value: '33', locked: true}
- {id: CCM_ANALOG.PLL3_PFD0_MUL.scale, value: '18', locked: true}
- {id: CCM_ANALOG.PLL3_PFD1_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD1}
- {id: CCM_ANALOG.PLL3_PFD2_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD2}
- {id: CCM_ANALOG.PLL3_PFD3_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD3}
- {id: CCM_ANALOG.PLL4.denom, value: '50'}
- {id: CCM_ANALOG.PLL4.div, value: '47'}
- {id: CCM_ANALOG.PLL5.denom, value: '1'}
- {id: CCM_ANALOG.PLL5.div, value: '40'}
- {id: CCM_ANALOG.PLL5.num, value: '0'}
- {id: CCM_ANALOG_PLL_ENET_POWERDOWN_CFG, value: 'Yes'}
- {id: CCM_ANALOG_PLL_USB1_POWER_CFG, value: 'Yes'}
sources:
- {id: XTALOSC24M.OSC.outFreq, value: 24 MHz, enabled: true}
- {id: XTALOSC24M.RTC_OSC.outFreq, value: 32.768 kHz, enabled: true}
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/
/*******************************************************************************
* Variables for BOARD_BootClockRUN configuration
******************************************************************************/
const clock_arm_pll_config_t armPllConfig_BOARD_BootClockRUN =
{
.loopDivider = 100, /* PLL loop divider, Fout = Fin * 50 */
.src = 0, /* Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N */
};
const clock_sys_pll_config_t sysPllConfig_BOARD_BootClockRUN =
{
.loopDivider = 1, /* PLL loop divider, Fout = Fin * ( 20 + loopDivider*2 + numerator / denominator ) */
.numerator = 0, /* 30 bit numerator of fractional loop divider */
.denominator = 1, /* 30 bit denominator of fractional loop divider */
.src = 0, /* Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N */
};
const clock_usb_pll_config_t usb1PllConfig_BOARD_BootClockRUN =
{
.loopDivider = 0, /* PLL loop divider, Fout = Fin * 20 */
.src = 0, /* Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N */
};
/*******************************************************************************
* Code for BOARD_BootClockRUN configuration
******************************************************************************/
void BOARD_BootClockRUN(void)
{
/* Init RTC OSC clock frequency. */
CLOCK_SetRtcXtalFreq(32768U);
/* Enable 1MHz clock output. */
XTALOSC24M->OSC_CONFIG2 |= XTALOSC24M_OSC_CONFIG2_ENABLE_1M_MASK;
/* Use free 1MHz clock output. */
XTALOSC24M->OSC_CONFIG2 &= ~XTALOSC24M_OSC_CONFIG2_MUX_1M_MASK;
/* Set XTAL 24MHz clock frequency. */
CLOCK_SetXtalFreq(24000000U);
/* Enable XTAL 24MHz clock source. */
CLOCK_InitExternalClk(0);
/* Enable internal RC. */
CLOCK_InitRcOsc24M();
/* Switch clock source to external OSC. */
CLOCK_SwitchOsc(kCLOCK_XtalOsc);
/* Set Oscillator ready counter value. */
CCM->CCR = (CCM->CCR & (~CCM_CCR_OSCNT_MASK)) | CCM_CCR_OSCNT(127);
/* Setting PeriphClk2Mux and PeriphMux to provide stable clock before PLLs are initialed */
CLOCK_SetMux(kCLOCK_PeriphClk2Mux, 1); /* Set PERIPH_CLK2 MUX to OSC */
CLOCK_SetMux(kCLOCK_PeriphMux, 1); /* Set PERIPH_CLK MUX to PERIPH_CLK2 */
/* Setting the VDD_SOC to 1.275V. It is necessary to config AHB to 600Mhz. */
DCDC->REG3 = (DCDC->REG3 & (~DCDC_REG3_TRG_MASK)) | DCDC_REG3_TRG(0x13);
/* Waiting for DCDC_STS_DC_OK bit is asserted */
while (DCDC_REG0_STS_DC_OK_MASK != (DCDC_REG0_STS_DC_OK_MASK & DCDC->REG0))
{
}
/* Set AHB_PODF. */
CLOCK_SetDiv(kCLOCK_AhbDiv, 0);
/* Disable IPG clock gate. */
CLOCK_DisableClock(kCLOCK_Adc1);
CLOCK_DisableClock(kCLOCK_Adc2);
CLOCK_DisableClock(kCLOCK_Xbar1);
CLOCK_DisableClock(kCLOCK_Xbar2);
CLOCK_DisableClock(kCLOCK_Xbar3);
/* Set IPG_PODF. */
CLOCK_SetDiv(kCLOCK_IpgDiv, 3);
/* Set ARM_PODF. */
CLOCK_SetDiv(kCLOCK_ArmDiv, 1);
/* Set PERIPH_CLK2_PODF. */
CLOCK_SetDiv(kCLOCK_PeriphClk2Div, 0);
/* Disable PERCLK clock gate. */
CLOCK_DisableClock(kCLOCK_Gpt1);
CLOCK_DisableClock(kCLOCK_Gpt1S);
CLOCK_DisableClock(kCLOCK_Gpt2);
CLOCK_DisableClock(kCLOCK_Gpt2S);
CLOCK_DisableClock(kCLOCK_Pit);
/* Set PERCLK_PODF. */
CLOCK_SetDiv(kCLOCK_PerclkDiv, 1);
/* Disable USDHC1 clock gate. */
CLOCK_DisableClock(kCLOCK_Usdhc1);
/* Set USDHC1_PODF. */
CLOCK_SetDiv(kCLOCK_Usdhc1Div, 1);
/* Set Usdhc1 clock source. */
CLOCK_SetMux(kCLOCK_Usdhc1Mux, 0);
/* Disable USDHC2 clock gate. */
CLOCK_DisableClock(kCLOCK_Usdhc2);
/* Set USDHC2_PODF. */
CLOCK_SetDiv(kCLOCK_Usdhc2Div, 1);
/* Set Usdhc2 clock source. */
CLOCK_SetMux(kCLOCK_Usdhc2Mux, 0);
/* In SDK projects, SDRAM (configured by SEMC) will be initialized in either debug script or dcd.
* With this macro SKIP_SYSCLK_INIT, system pll (selected to be SEMC source clock in SDK projects) will be left unchanged.
* Note: If another clock source is selected for SEMC, user may want to avoid changing that clock as well.*/
#ifndef SKIP_SYSCLK_INIT
/* Disable Semc clock gate. */
CLOCK_DisableClock(kCLOCK_Semc);
/* Set SEMC_PODF. */
CLOCK_SetDiv(kCLOCK_SemcDiv, 7);
/* Set Semc alt clock source. */
CLOCK_SetMux(kCLOCK_SemcAltMux, 0);
/* Set Semc clock source. */
CLOCK_SetMux(kCLOCK_SemcMux, 0);
#endif
/* In SDK projects, external flash (configured by FLEXSPI) will be initialized by dcd.
* With this macro XIP_EXTERNAL_FLASH, usb1 pll (selected to be FLEXSPI clock source in SDK projects) will be left unchanged.
* Note: If another clock source is selected for FLEXSPI, user may want to avoid changing that clock as well.*/
#if !(defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1))
/* Disable Flexspi clock gate. */
CLOCK_DisableClock(kCLOCK_FlexSpi);
/* Set FLEXSPI_PODF. */
CLOCK_SetDiv(kCLOCK_FlexspiDiv, 0);
/* Set Flexspi clock source. */
CLOCK_SetMux(kCLOCK_FlexspiMux, 3);
#endif
/* Disable CSI clock gate. */
CLOCK_DisableClock(kCLOCK_Csi);
/* Set CSI_PODF. */
CLOCK_SetDiv(kCLOCK_CsiDiv, 1);
/* Set Csi clock source. */
CLOCK_SetMux(kCLOCK_CsiMux, 0);
/* Disable LPSPI clock gate. */
CLOCK_DisableClock(kCLOCK_Lpspi1);
CLOCK_DisableClock(kCLOCK_Lpspi2);
CLOCK_DisableClock(kCLOCK_Lpspi3);
CLOCK_DisableClock(kCLOCK_Lpspi4);
/* Set LPSPI_PODF. */
CLOCK_SetDiv(kCLOCK_LpspiDiv, 4);
/* Set Lpspi clock source. */
CLOCK_SetMux(kCLOCK_LpspiMux, 2);
/* Disable TRACE clock gate. */
CLOCK_DisableClock(kCLOCK_Trace);
/* Set TRACE_PODF. */
CLOCK_SetDiv(kCLOCK_TraceDiv, 2);
/* Set Trace clock source. */
CLOCK_SetMux(kCLOCK_TraceMux, 2);
/* Disable SAI1 clock gate. */
CLOCK_DisableClock(kCLOCK_Sai1);
/* Set SAI1_CLK_PRED. */
CLOCK_SetDiv(kCLOCK_Sai1PreDiv, 3);
/* Set SAI1_CLK_PODF. */
CLOCK_SetDiv(kCLOCK_Sai1Div, 1);
/* Set Sai1 clock source. */
CLOCK_SetMux(kCLOCK_Sai1Mux, 0);
/* Disable SAI2 clock gate. */
CLOCK_DisableClock(kCLOCK_Sai2);
/* Set SAI2_CLK_PRED. */
CLOCK_SetDiv(kCLOCK_Sai2PreDiv, 3);
/* Set SAI2_CLK_PODF. */
CLOCK_SetDiv(kCLOCK_Sai2Div, 1);
/* Set Sai2 clock source. */
CLOCK_SetMux(kCLOCK_Sai2Mux, 0);
/* Disable SAI3 clock gate. */
CLOCK_DisableClock(kCLOCK_Sai3);
/* Set SAI3_CLK_PRED. */
CLOCK_SetDiv(kCLOCK_Sai3PreDiv, 3);
/* Set SAI3_CLK_PODF. */
CLOCK_SetDiv(kCLOCK_Sai3Div, 1);
/* Set Sai3 clock source. */
CLOCK_SetMux(kCLOCK_Sai3Mux, 0);
/* Disable Lpi2c clock gate. */
CLOCK_DisableClock(kCLOCK_Lpi2c1);
CLOCK_DisableClock(kCLOCK_Lpi2c2);
CLOCK_DisableClock(kCLOCK_Lpi2c3);
/* Set LPI2C_CLK_PODF. */
CLOCK_SetDiv(kCLOCK_Lpi2cDiv, 0);
/* Set Lpi2c clock source. */
CLOCK_SetMux(kCLOCK_Lpi2cMux, 0);
/* Disable CAN clock gate. */
CLOCK_DisableClock(kCLOCK_Can1);
CLOCK_DisableClock(kCLOCK_Can2);
CLOCK_DisableClock(kCLOCK_Can1S);
CLOCK_DisableClock(kCLOCK_Can2S);
/* Set CAN_CLK_PODF. */
CLOCK_SetDiv(kCLOCK_CanDiv, 1);
/* Set Can clock source. */
CLOCK_SetMux(kCLOCK_CanMux, 2);
/* Disable UART clock gate. */
CLOCK_DisableClock(kCLOCK_Lpuart1);
CLOCK_DisableClock(kCLOCK_Lpuart2);
CLOCK_DisableClock(kCLOCK_Lpuart3);
CLOCK_DisableClock(kCLOCK_Lpuart4);
CLOCK_DisableClock(kCLOCK_Lpuart5);
CLOCK_DisableClock(kCLOCK_Lpuart6);
CLOCK_DisableClock(kCLOCK_Lpuart7);
CLOCK_DisableClock(kCLOCK_Lpuart8);
/* Set UART_CLK_PODF. */
CLOCK_SetDiv(kCLOCK_UartDiv, 0);
/* Set Uart clock source. */
CLOCK_SetMux(kCLOCK_UartMux, 0);
/* Disable LCDIF clock gate. */
CLOCK_DisableClock(kCLOCK_LcdPixel);
/* Set LCDIF_PRED. */
CLOCK_SetDiv(kCLOCK_LcdifPreDiv, 6);
/* Set LCDIF_CLK_PODF. */
CLOCK_SetDiv(kCLOCK_LcdifDiv, 7);
/* Set Lcdif pre clock source. */
CLOCK_SetMux(kCLOCK_LcdifPreMux, 5);
/* Disable SPDIF clock gate. */
CLOCK_DisableClock(kCLOCK_Spdif);
/* Set SPDIF0_CLK_PRED. */
CLOCK_SetDiv(kCLOCK_Spdif0PreDiv, 1);
/* Set SPDIF0_CLK_PODF. */
CLOCK_SetDiv(kCLOCK_Spdif0Div, 7);
/* Set Spdif clock source. */
CLOCK_SetMux(kCLOCK_SpdifMux, 3);
/* Disable Flexio1 clock gate. */
CLOCK_DisableClock(kCLOCK_Flexio1);
/* Set FLEXIO1_CLK_PRED. */
CLOCK_SetDiv(kCLOCK_Flexio1PreDiv, 1);
/* Set FLEXIO1_CLK_PODF. */
CLOCK_SetDiv(kCLOCK_Flexio1Div, 7);
/* Set Flexio1 clock source. */
CLOCK_SetMux(kCLOCK_Flexio1Mux, 3);
/* Disable Flexio2 clock gate. */
CLOCK_DisableClock(kCLOCK_Flexio2);
/* Set FLEXIO2_CLK_PRED. */
CLOCK_SetDiv(kCLOCK_Flexio2PreDiv, 1);
/* Set FLEXIO2_CLK_PODF. */
CLOCK_SetDiv(kCLOCK_Flexio2Div, 7);
/* Set Flexio2 clock source. */
CLOCK_SetMux(kCLOCK_Flexio2Mux, 3);
/* Set Pll3 sw clock source. */
CLOCK_SetMux(kCLOCK_Pll3SwMux, 0);
/* Init ARM PLL. */
CLOCK_InitArmPll(&armPllConfig_BOARD_BootClockRUN);
/* In SDK projects, SDRAM (configured by SEMC) will be initialized in either debug script or dcd.
* With this macro SKIP_SYSCLK_INIT, system pll (selected to be SEMC source clock in SDK projects) will be left unchanged.
* Note: If another clock source is selected for SEMC, user may want to avoid changing that clock as well.*/
#ifndef SKIP_SYSCLK_INIT
/* Init System PLL. */
CLOCK_InitSysPll(&sysPllConfig_BOARD_BootClockRUN);
/* Init System pfd0. */
CLOCK_InitSysPfd(kCLOCK_Pfd0, 27);
/* Init System pfd1. */
CLOCK_InitSysPfd(kCLOCK_Pfd1, 16);
/* Init System pfd2. */
CLOCK_InitSysPfd(kCLOCK_Pfd2, 24);
/* Init System pfd3. */
CLOCK_InitSysPfd(kCLOCK_Pfd3, 16);
/* Disable pfd offset. */
CCM_ANALOG->PLL_SYS &= ~CCM_ANALOG_PLL_SYS_PFD_OFFSET_EN_MASK;
#endif
/* In SDK projects, external flash (configured by FLEXSPI) will be initialized by dcd.
* With this macro XIP_EXTERNAL_FLASH, usb1 pll (selected to be FLEXSPI clock source in SDK projects) will be left unchanged.
* Note: If another clock source is selected for FLEXSPI, user may want to avoid changing that clock as well.*/
#if !(defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1))
/* Init Usb1 PLL. */
CLOCK_InitUsb1Pll(&usb1PllConfig_BOARD_BootClockRUN);
/* Init Usb1 pfd0. */
CLOCK_InitUsb1Pfd(kCLOCK_Pfd0, 33);
/* Init Usb1 pfd1. */
CLOCK_InitUsb1Pfd(kCLOCK_Pfd1, 16);
/* Init Usb1 pfd2. */
CLOCK_InitUsb1Pfd(kCLOCK_Pfd2, 17);
/* Init Usb1 pfd3. */
CLOCK_InitUsb1Pfd(kCLOCK_Pfd3, 19);
/* Disable Usb1 PLL output for USBPHY1. */
CCM_ANALOG->PLL_USB1 &= ~CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK;
#endif
/* DeInit Audio PLL. */
CLOCK_DeinitAudioPll();
/* Bypass Audio PLL. */
CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_PllAudio, 1);
/* Set divider for Audio PLL. */
CCM_ANALOG->MISC2 &= ~CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK;
CCM_ANALOG->MISC2 &= ~CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK;
/* Enable Audio PLL output. */
CCM_ANALOG->PLL_AUDIO |= CCM_ANALOG_PLL_AUDIO_ENABLE_MASK;
/* DeInit Video PLL. */
CLOCK_DeinitVideoPll();
/* Bypass Video PLL. */
CCM_ANALOG->PLL_VIDEO |= CCM_ANALOG_PLL_VIDEO_BYPASS_MASK;
/* Set divider for Video PLL. */
CCM_ANALOG->MISC2 = (CCM_ANALOG->MISC2 & (~CCM_ANALOG_MISC2_VIDEO_DIV_MASK)) | CCM_ANALOG_MISC2_VIDEO_DIV(0);
/* Enable Video PLL output. */
CCM_ANALOG->PLL_VIDEO |= CCM_ANALOG_PLL_VIDEO_ENABLE_MASK;
/* DeInit Enet PLL. */
CLOCK_DeinitEnetPll();
/* Bypass Enet PLL. */
CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_PllEnet, 1);
/* Set Enet output divider. */
CCM_ANALOG->PLL_ENET = (CCM_ANALOG->PLL_ENET & (~CCM_ANALOG_PLL_ENET_DIV_SELECT_MASK)) | CCM_ANALOG_PLL_ENET_DIV_SELECT(1);
/* Enable Enet output. */
CCM_ANALOG->PLL_ENET |= CCM_ANALOG_PLL_ENET_ENABLE_MASK;
/* Enable Enet25M output. */
CCM_ANALOG->PLL_ENET |= CCM_ANALOG_PLL_ENET_ENET_25M_REF_EN_MASK;
/* DeInit Usb2 PLL. */
CLOCK_DeinitUsb2Pll();
/* Bypass Usb2 PLL. */
CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_PllUsb2, 1);
/* Enable Usb2 PLL output. */
CCM_ANALOG->PLL_USB2 |= CCM_ANALOG_PLL_USB2_ENABLE_MASK;
/* Set preperiph clock source. */
CLOCK_SetMux(kCLOCK_PrePeriphMux, 3);
/* Set periph clock source. */
CLOCK_SetMux(kCLOCK_PeriphMux, 0);
/* Set periph clock2 clock source. */
CLOCK_SetMux(kCLOCK_PeriphClk2Mux, 0);
/* Set per clock source. */
CLOCK_SetMux(kCLOCK_PerclkMux, 0);
/* Set lvds1 clock source. */
CCM_ANALOG->MISC1 = (CCM_ANALOG->MISC1 & (~CCM_ANALOG_MISC1_LVDS1_CLK_SEL_MASK)) | CCM_ANALOG_MISC1_LVDS1_CLK_SEL(0);
/* Set clock out1 divider. */
CCM->CCOSR = (CCM->CCOSR & (~CCM_CCOSR_CLKO1_DIV_MASK)) | CCM_CCOSR_CLKO1_DIV(0);
/* Set clock out1 source. */
CCM->CCOSR = (CCM->CCOSR & (~CCM_CCOSR_CLKO1_SEL_MASK)) | CCM_CCOSR_CLKO1_SEL(1);
/* Set clock out2 divider. */
CCM->CCOSR = (CCM->CCOSR & (~CCM_CCOSR_CLKO2_DIV_MASK)) | CCM_CCOSR_CLKO2_DIV(0);
/* Set clock out2 source. */
CCM->CCOSR = (CCM->CCOSR & (~CCM_CCOSR_CLKO2_SEL_MASK)) | CCM_CCOSR_CLKO2_SEL(18);
/* Set clock out1 drives clock out1. */
CCM->CCOSR &= ~CCM_CCOSR_CLK_OUT_SEL_MASK;
/* Disable clock out1. */
CCM->CCOSR &= ~CCM_CCOSR_CLKO1_EN_MASK;
/* Disable clock out2. */
CCM->CCOSR &= ~CCM_CCOSR_CLKO2_EN_MASK;
/* Set SAI1 MCLK1 clock source. */
IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI1MClk1Sel, 0);
/* Set SAI1 MCLK2 clock source. */
IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI1MClk2Sel, 0);
/* Set SAI1 MCLK3 clock source. */
IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI1MClk3Sel, 0);
/* Set SAI2 MCLK3 clock source. */
IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI2MClk3Sel, 0);
/* Set SAI3 MCLK3 clock source. */
IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI3MClk3Sel, 0);
/* Set MQS configuration. */
IOMUXC_MQSConfig(IOMUXC_GPR,kIOMUXC_MqsPwmOverSampleRate32, 0);
/* Set ENET Tx clock source. */
IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET1RefClkMode, false);
/* Set GPT1 High frequency reference clock source. */
IOMUXC_GPR->GPR5 &= ~IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT1_MASK;
/* Set GPT2 High frequency reference clock source. */
IOMUXC_GPR->GPR5 &= ~IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT2_MASK;
/* Set SystemCoreClock variable. */
SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK;
}
@@ -0,0 +1,611 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file fsl_cache.c
* @brief cache drivers
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.11.11
*/
#include "fsl_cache.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.cache_armv7_m7"
#endif
#if defined(FSL_FEATURE_SOC_L2CACHEC_COUNT) && FSL_FEATURE_SOC_L2CACHEC_COUNT
#define L2CACHE_OPERATION_TIMEOUT 0xFFFFFU
#define L2CACHE_8WAYS_MASK 0xFFU
#define L2CACHE_16WAYS_MASK 0xFFFFU
#define L2CACHE_SMALLWAYS_NUM 8U
#define L2CACHE_1KBCOVERTOB 1024U
#define L2CACHE_SAMLLWAYS_SIZE 16U
#define L2CACHE_LOCKDOWN_REGNUM 8 /*!< Lock down register numbers.*/
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Set for all ways and waiting for the operation finished.
* This is provided for all the background operations.
*
* @param auxCtlReg The auxiliary control register.
* @param regAddr The register address to be operated.
*/
static void L2CACHE_SetAndWaitBackGroundOperate(uint32_t auxCtlReg, uint32_t regAddr);
/*!
* @brief Invalidates the Level 2 cache line by physical address.
* This function invalidates a cache line by physcial address.
*
* @param address The physical addderss of the cache.
* The format of the address shall be :
* bit 31 ~ bit n+1 | bitn ~ bit5 | bit4 ~ bit0
* Tag | index | 0
* Note: the physical address shall be aligned to the line size - 32B (256 bit).
* so keep the last 5 bits (bit 4 ~ bit 0) of the physical address always be zero.
* If the input address is not aligned, it will be changed to 32-byte aligned address.
* The n is varies according to the index width.
* @return The actual 32-byte aligned physical address be operated.
*/
static uint32_t L2CACHE_InvalidateLineByAddr(uint32_t address);
/*!
* @brief Cleans the Level 2 cache line based on the physical address.
* This function cleans a cache line based on a physcial address.
*
* @param address The physical addderss of the cache.
* The format of the address shall be :
* bit 31 ~ bit n+1 | bitn ~ bit5 | bit4 ~ bit0
* Tag | index | 0
* Note: the physical address shall be aligned to the line size - 32B (256 bit).
* so keep the last 5 bits (bit 4 ~ bit 0) of the physical address always be zero.
* If the input address is not aligned, it will be changed to 32-byte aligned address.
* The n is varies according to the index width.
* @return The actual 32-byte aligned physical address be operated.
*/
static uint32_t L2CACHE_CleanLineByAddr(uint32_t address);
/*!
* @brief Cleans and invalidates the Level 2 cache line based on the physical address.
* This function cleans and invalidates a cache line based on a physcial address.
*
* @param address The physical addderss of the cache.
* The format of the address shall be :
* bit 31 ~ bit n+1 | bitn ~ bit5 | bit4 ~ bit0
* Tag | index | 0
* Note: the physical address shall be aligned to the line size - 32B (256 bit).
* so keep the last 5 bits (bit 4 ~ bit 0) of the physical address always be zero.
* If the input address is not aligned, it will be changed to 32-byte aligned address.
* The n is varies according to the index width.
* @return The actual 32-byte aligned physical address be operated.
*/
static uint32_t L2CACHE_CleanInvalidateLineByAddr(uint32_t address);
/*!
* @brief Gets the number of the Level 2 cache and the way size.
* This function cleans and invalidates a cache line based on a physcial address.
*
* @param num_ways The number of the cache way.
* @param size_way The way size.
*/
static void L2CACHE_GetWayNumSize(uint32_t *num_ways, uint32_t *size_way);
/*******************************************************************************
* Code
******************************************************************************/
static void L2CACHE_SetAndWaitBackGroundOperate(uint32_t auxCtlReg, uint32_t regAddr)
{
uint16_t mask = L2CACHE_8WAYS_MASK;
uint32_t timeout = L2CACHE_OPERATION_TIMEOUT;
/* Check the ways used at first. */
if (auxCtlReg & L2CACHEC_REG1_AUX_CONTROL_ASSOCIATIVITY_MASK)
{
mask = L2CACHE_16WAYS_MASK;
}
/* Set the opeartion for all ways/entries of the cache. */
*(uint32_t *)regAddr = mask;
/* Waiting for until the operation is complete. */
while ((*(volatile uint32_t *)regAddr & mask) && timeout)
{
__ASM("nop");
timeout--;
}
}
static uint32_t L2CACHE_InvalidateLineByAddr(uint32_t address)
{
/* Align the address first. */
address &= ~(uint32_t)(FSL_FEATURE_L2CACHE_LINESIZE_BYTE - 1);
/* Invalidate the cache line by physical address. */
L2CACHEC->REG7_INV_PA = address;
return address;
}
static uint32_t L2CACHE_CleanLineByAddr(uint32_t address)
{
/* Align the address first. */
address &= ~(uint32_t)(FSL_FEATURE_L2CACHE_LINESIZE_BYTE - 1);
/* Invalidate the cache line by physical address. */
L2CACHEC->REG7_CLEAN_PA = address;
return address;
}
static uint32_t L2CACHE_CleanInvalidateLineByAddr(uint32_t address)
{
/* Align the address first. */
address &= ~(uint32_t)(FSL_FEATURE_L2CACHE_LINESIZE_BYTE - 1);
/* Clean and invalidate the cache line by physical address. */
L2CACHEC->REG7_CLEAN_INV_PA = address;
return address;
}
static void L2CACHE_GetWayNumSize(uint32_t *num_ways, uint32_t *size_way)
{
assert(num_ways);
assert(size_way);
uint32_t number = (L2CACHEC->REG1_AUX_CONTROL & L2CACHEC_REG1_AUX_CONTROL_ASSOCIATIVITY_MASK) >>
L2CACHEC_REG1_AUX_CONTROL_ASSOCIATIVITY_SHIFT;
uint32_t size = (L2CACHEC->REG1_AUX_CONTROL & L2CACHEC_REG1_AUX_CONTROL_WAYSIZE_MASK) >>
L2CACHEC_REG1_AUX_CONTROL_WAYSIZE_SHIFT;
*num_ways = (number + 1) * L2CACHE_SMALLWAYS_NUM;
if (!size)
{
/* 0 internally mapped to the same size as 1 - 16KB.*/
size += 1;
}
*size_way = (1 << (size - 1)) * L2CACHE_SAMLLWAYS_SIZE * L2CACHE_1KBCOVERTOB;
}
/*!
* brief Initializes the level 2 cache controller module.
*
* param config Pointer to configuration structure. See "l2cache_config_t".
*/
void L2CACHE_Init(l2cache_config_t *config)
{
assert(config);
uint16_t waysNum = 0xFFU; /* Default use the 8-way mask. */
uint8_t count;
uint32_t auxReg = 0;
/*The aux register must be configured when the cachec is disabled
* So disable first if the cache controller is enabled.
*/
if (L2CACHEC->REG1_CONTROL & L2CACHEC_REG1_CONTROL_CE_MASK)
{
L2CACHE_Disable();
}
/* Unlock all entries. */
if (L2CACHEC->REG1_AUX_CONTROL & L2CACHEC_REG1_AUX_CONTROL_ASSOCIATIVITY_MASK)
{
waysNum = 0xFFFFU;
}
for (count = 0; count < L2CACHE_LOCKDOWN_REGNUM; count++)
{
L2CACHE_LockdownByWayEnable(count, waysNum, false);
}
/* Set the ways and way-size etc. */
auxReg = L2CACHEC_REG1_AUX_CONTROL_ASSOCIATIVITY(config->wayNum) |
L2CACHEC_REG1_AUX_CONTROL_WAYSIZE(config->waySize) | L2CACHEC_REG1_AUX_CONTROL_CRP(config->repacePolicy) |
L2CACHEC_REG1_AUX_CONTROL_IPE(config->istrPrefetchEnable) |
L2CACHEC_REG1_AUX_CONTROL_DPE(config->dataPrefetchEnable) |
L2CACHEC_REG1_AUX_CONTROL_NLE(config->nsLockdownEnable) |
L2CACHEC_REG1_AUX_CONTROL_FWA(config->writeAlloc) | L2CACHEC_REG1_AUX_CONTROL_HPSDRE(config->writeAlloc);
L2CACHEC->REG1_AUX_CONTROL = auxReg;
/* Set the tag/data ram latency. */
if (config->lateConfig)
{
uint32_t data = 0;
/* Tag latency. */
data = L2CACHEC_REG1_TAG_RAM_CONTROL_SL(config->lateConfig->tagSetupLate) |
L2CACHEC_REG1_TAG_RAM_CONTROL_SL(config->lateConfig->tagSetupLate) |
L2CACHEC_REG1_TAG_RAM_CONTROL_RAL(config->lateConfig->tagReadLate) |
L2CACHEC_REG1_TAG_RAM_CONTROL_WAL(config->lateConfig->dataWriteLate);
L2CACHEC->REG1_TAG_RAM_CONTROL = data;
/* Data latency. */
data = L2CACHEC_REG1_DATA_RAM_CONTROL_SL(config->lateConfig->dataSetupLate) |
L2CACHEC_REG1_DATA_RAM_CONTROL_SL(config->lateConfig->dataSetupLate) |
L2CACHEC_REG1_DATA_RAM_CONTROL_RAL(config->lateConfig->dataReadLate) |
L2CACHEC_REG1_DATA_RAM_CONTROL_WAL(config->lateConfig->dataWriteLate);
L2CACHEC->REG1_DATA_RAM_CONTROL = data;
}
}
/*!
* brief Gets an available default settings for the cache controller.
*
* This function initializes the cache controller configuration structure with default settings.
* The default values are:
* code
* config->waysNum = kL2CACHE_8ways;
* config->waySize = kL2CACHE_32KbSize;
* config->repacePolicy = kL2CACHE_Roundrobin;
* config->lateConfig = NULL;
* config->istrPrefetchEnable = false;
* config->dataPrefetchEnable = false;
* config->nsLockdownEnable = false;
* config->writeAlloc = kL2CACHE_UseAwcache;
* endcode
* param config Pointer to the configuration structure.
*/
void L2CACHE_GetDefaultConfig(l2cache_config_t *config)
{
assert(config);
/* Initializes the configure structure to zero. */
memset(config, 0, sizeof(*config));
uint32_t number = (L2CACHEC->REG1_AUX_CONTROL & L2CACHEC_REG1_AUX_CONTROL_ASSOCIATIVITY_MASK) >>
L2CACHEC_REG1_AUX_CONTROL_ASSOCIATIVITY_SHIFT;
uint32_t size = (L2CACHEC->REG1_AUX_CONTROL & L2CACHEC_REG1_AUX_CONTROL_WAYSIZE_MASK) >>
L2CACHEC_REG1_AUX_CONTROL_WAYSIZE_SHIFT;
/* Get the default value */
config->wayNum = (l2cache_way_num_t)number;
config->waySize = (l2cache_way_size)size;
config->repacePolicy = kL2CACHE_Roundrobin;
config->lateConfig = NULL;
config->istrPrefetchEnable = false;
config->dataPrefetchEnable = false;
config->nsLockdownEnable = false;
config->writeAlloc = kL2CACHE_UseAwcache;
}
/*!
* brief Enables the level 2 cache controller.
* This function enables the cache controller. Must be written using a secure access.
* If write with a Non-secure access will cause a DECERR response.
*
*/
void L2CACHE_Enable(void)
{
/* Invalidate first. */
L2CACHE_Invalidate();
/* Enable the level 2 cache controller. */
L2CACHEC->REG1_CONTROL = L2CACHEC_REG1_CONTROL_CE_MASK;
}
/*!
* brief Disables the level 2 cache controller.
* This function disables the cache controller. Must be written using a secure access.
* If write with a Non-secure access will cause a DECERR response.
*
*/
void L2CACHE_Disable(void)
{
/* First CleanInvalidate all enties in the cache. */
L2CACHE_CleanInvalidate();
/* Disable the level 2 cache controller. */
L2CACHEC->REG1_CONTROL &= ~L2CACHEC_REG1_CONTROL_CE_MASK;
/* DSB - data sync barrier.*/
__DSB();
}
/*!
* brief Invalidates the Level 2 cache.
* This function invalidates all entries in cache.
*
*/
void L2CACHE_Invalidate(void)
{
/* Invalidate all entries in cache. */
L2CACHE_SetAndWaitBackGroundOperate(L2CACHEC->REG1_AUX_CONTROL, (uint32_t)&L2CACHEC->REG7_INV_WAY);
/* Cache sync. */
L2CACHEC->REG7_CACHE_SYNC = 0;
}
/*!
* brief Cleans the level 2 cache controller.
* This function cleans all entries in the level 2 cache controller.
*
*/
void L2CACHE_Clean(void)
{
/* Clean all entries of the cache. */
L2CACHE_SetAndWaitBackGroundOperate(L2CACHEC->REG1_AUX_CONTROL, (uint32_t)&L2CACHEC->REG7_CLEAN_WAY);
/* Cache sync. */
L2CACHEC->REG7_CACHE_SYNC = 0;
}
/*!
* brief Cleans and invalidates the level 2 cache controller.
* This function cleans and invalidates all entries in the level 2 cache controller.
*
*/
void L2CACHE_CleanInvalidate(void)
{
/* Clean all entries of the cache. */
L2CACHE_SetAndWaitBackGroundOperate(L2CACHEC->REG1_AUX_CONTROL, (uint32_t)&L2CACHEC->REG7_CLEAN_INV_WAY);
/* Cache sync. */
L2CACHEC->REG7_CACHE_SYNC = 0;
}
/*!
* brief Invalidates the Level 2 cache lines in the range of two physical addresses.
* This function invalidates all cache lines between two physical addresses.
*
* param address The start address of the memory to be invalidated.
* param size_byte The memory size.
* note The start address and size_byte should be 32-byte(FSL_FEATURE_L2CACHE_LINESIZE_BYTE) aligned.
* The startAddr here will be forced to align to L2 line size if startAddr
* is not aligned. For the size_byte, application should make sure the
* alignment or make sure the right operation order if the size_byte is not aligned.
*/
void L2CACHE_InvalidateByRange(uint32_t address, uint32_t size_byte)
{
uint32_t endAddr = address + size_byte;
/* Invalidate addresses in the range. */
while (address < endAddr)
{
address = L2CACHE_InvalidateLineByAddr(address);
/* Update the size. */
address += FSL_FEATURE_L2CACHE_LINESIZE_BYTE;
}
/* Cache sync. */
L2CACHEC->REG7_CACHE_SYNC = 0;
}
/*!
* brief Cleans the Level 2 cache lines in the range of two physical addresses.
* This function cleans all cache lines between two physical addresses.
*
* param address The start address of the memory to be cleaned.
* param size_byte The memory size.
* note The start address and size_byte should be 32-byte(FSL_FEATURE_L2CACHE_LINESIZE_BYTE) aligned.
* The startAddr here will be forced to align to L2 line size if startAddr
* is not aligned. For the size_byte, application should make sure the
* alignment or make sure the right operation order if the size_byte is not aligned.
*/
void L2CACHE_CleanByRange(uint32_t address, uint32_t size_byte)
{
uint32_t num_ways = 0;
uint32_t size_way = 0;
uint32_t endAddr = address + size_byte;
/* Get the number and size of the cache way. */
L2CACHE_GetWayNumSize(&num_ways, &size_way);
/* Check if the clean size is over the cache size. */
if ((endAddr - address) > num_ways * size_way)
{
L2CACHE_Clean();
return;
}
/* Clean addresses in the range. */
while ((address & ~(uint32_t)(FSL_FEATURE_L2CACHE_LINESIZE_BYTE - 1)) < endAddr)
{
/* Clean the address in the range. */
address = L2CACHE_CleanLineByAddr(address);
address += FSL_FEATURE_L2CACHE_LINESIZE_BYTE;
}
L2CACHEC->REG7_CACHE_SYNC = 0;
}
/*!
* brief Cleans and invalidates the Level 2 cache lines in the range of two physical addresses.
* This function cleans and invalidates all cache lines between two physical addresses.
*
* param address The start address of the memory to be cleaned and invalidated.
* param size_byte The memory size.
* note The start address and size_byte should be 32-byte(FSL_FEATURE_L2CACHE_LINESIZE_BYTE) aligned.
* The startAddr here will be forced to align to L2 line size if startAddr
* is not aligned. For the size_byte, application should make sure the
* alignment or make sure the right operation order if the size_byte is not aligned.
*/
void L2CACHE_CleanInvalidateByRange(uint32_t address, uint32_t size_byte)
{
uint32_t num_ways = 0;
uint32_t size_way = 0;
uint32_t endAddr = address + size_byte;
/* Get the number and size of the cache way. */
L2CACHE_GetWayNumSize(&num_ways, &size_way);
/* Check if the clean size is over the cache size. */
if ((endAddr - address) > num_ways * size_way)
{
L2CACHE_CleanInvalidate();
return;
}
/* Clean addresses in the range. */
while ((address & ~(uint32_t)(FSL_FEATURE_L2CACHE_LINESIZE_BYTE - 1)) < endAddr)
{
/* Clean the address in the range. */
address = L2CACHE_CleanInvalidateLineByAddr(address);
address += FSL_FEATURE_L2CACHE_LINESIZE_BYTE;
}
L2CACHEC->REG7_CACHE_SYNC = 0;
}
/*!
* brief Enables or disables to lock down the data and instruction by way.
* This function locks down the cached instruction/data by way and prevent the adresses from
* being allocated and prevent dara from being evicted out of the level 2 cache.
* But the normal cache maintenance operations that invalidate, clean or clean
* and validate cache contents affect the locked-down cache lines as normal.
*
* param masterId The master id, range from 0 ~ 7.
* param mask The ways to be enabled or disabled to lockdown.
* each bit in value is related to each way of the cache. for example:
* value: bit 0 ------ way 0.
* value: bit 1 ------ way 1.
* --------------------------
* value: bit 15 ------ way 15.
* Note: please make sure the value setting is align with your supported ways.
* param enable True enable the lockdown, false to disable the lockdown.
*/
void L2CACHE_LockdownByWayEnable(uint32_t masterId, uint32_t mask, bool enable)
{
uint8_t num_ways = (L2CACHEC->REG1_AUX_CONTROL & L2CACHEC_REG1_AUX_CONTROL_ASSOCIATIVITY_MASK) >>
L2CACHEC_REG1_AUX_CONTROL_ASSOCIATIVITY_SHIFT;
num_ways = (num_ways + 1) * L2CACHE_SMALLWAYS_NUM;
assert(mask < (1U << num_ways));
assert(masterId < L2CACHE_LOCKDOWN_REGNUM);
uint32_t dataReg = L2CACHEC->LOCKDOWN[masterId].REG9_D_LOCKDOWN;
uint32_t istrReg = L2CACHEC->LOCKDOWN[masterId].REG9_I_LOCKDOWN;
if (enable)
{
/* Data lockdown. */
L2CACHEC->LOCKDOWN[masterId].REG9_D_LOCKDOWN = dataReg | mask;
/* Instruction lockdown. */
L2CACHEC->LOCKDOWN[masterId].REG9_I_LOCKDOWN = istrReg | mask;
}
else
{
/* Data lockdown. */
L2CACHEC->LOCKDOWN[masterId].REG9_D_LOCKDOWN = dataReg & ~mask;
/* Instruction lockdown. */
L2CACHEC->LOCKDOWN[masterId].REG9_I_LOCKDOWN = istrReg & ~mask;
}
}
#endif /* FSL_FEATURE_SOC_L2CACHEC_COUNT */
/*!
* brief Invalidate cortex-m7 L1 instruction cache by range.
*
* param address The start address of the memory to be invalidated.
* param size_byte The memory size.
* note The start address and size_byte should be 32-byte(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE) aligned.
* The startAddr here will be forced to align to L1 I-cache line size if
* startAddr is not aligned. For the size_byte, application should make sure the
* alignment or make sure the right operation order if the size_byte is not aligned.
*/
void L1CACHE_InvalidateICacheByRange(uint32_t address, uint32_t size_byte)
{
#if (__DCACHE_PRESENT == 1U)
uint32_t addr = address & (uint32_t) ~(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE - 1);
int32_t size = size_byte + address - addr;
uint32_t linesize = 32U;
__DSB();
while (size > 0)
{
SCB->ICIMVAU = addr;
addr += linesize;
size -= linesize;
}
__DSB();
__ISB();
#endif
}
/*!
* brief Invalidates all instruction caches by range.
*
* Both cortex-m7 L1 cache line and L2 PL310 cache line length is 32-byte.
*
* param address The physical address.
* param size_byte size of the memory to be invalidated.
* note address and size should be aligned to cache line size
* 32-Byte due to the cache operation unit is one cache line. The startAddr here will be forced
* to align to the cache line size if startAddr is not aligned. For the size_byte, application should
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
*/
void ICACHE_InvalidateByRange(uint32_t address, uint32_t size_byte)
{
#if defined(FSL_FEATURE_SOC_L2CACHEC_COUNT) && FSL_FEATURE_SOC_L2CACHEC_COUNT
#if defined(FSL_SDK_DISBLE_L2CACHE_PRESENT) && !FSL_SDK_DISBLE_L2CACHE_PRESENT
L2CACHE_InvalidateByRange(address, size_byte);
#endif /* !FSL_SDK_DISBLE_L2CACHE_PRESENT */
#endif /* FSL_FEATURE_SOC_L2CACHEC_COUNT */
L1CACHE_InvalidateICacheByRange(address, size_byte);
}
/*!
* brief Invalidates all data caches by range.
*
* Both cortex-m7 L1 cache line and L2 PL310 cache line length is 32-byte.
*
* param address The physical address.
* param size_byte size of the memory to be invalidated.
* note address and size should be aligned to cache line size
* 32-Byte due to the cache operation unit is one cache line. The startAddr here will be forced
* to align to the cache line size if startAddr is not aligned. For the size_byte, application should
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
*/
void DCACHE_InvalidateByRange(uint32_t address, uint32_t size_byte)
{
#if defined(FSL_FEATURE_SOC_L2CACHEC_COUNT) && FSL_FEATURE_SOC_L2CACHEC_COUNT
#if defined(FSL_SDK_DISBLE_L2CACHE_PRESENT) && !FSL_SDK_DISBLE_L2CACHE_PRESENT
L2CACHE_InvalidateByRange(address, size_byte);
#endif /* !FSL_SDK_DISBLE_L2CACHE_PRESENT */
#endif /* FSL_FEATURE_SOC_L2CACHEC_COUNT */
L1CACHE_InvalidateDCacheByRange(address, size_byte);
}
/*!
* brief Cleans all data caches by range.
*
* Both cortex-m7 L1 cache line and L2 PL310 cache line length is 32-byte.
*
* param address The physical address.
* param size_byte size of the memory to be cleaned.
* note address and size should be aligned to cache line size
* 32-Byte due to the cache operation unit is one cache line. The startAddr here will be forced
* to align to the cache line size if startAddr is not aligned. For the size_byte, application should
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
*/
void DCACHE_CleanByRange(uint32_t address, uint32_t size_byte)
{
L1CACHE_CleanDCacheByRange(address, size_byte);
#if defined(FSL_FEATURE_SOC_L2CACHEC_COUNT) && FSL_FEATURE_SOC_L2CACHEC_COUNT
#if defined(FSL_SDK_DISBLE_L2CACHE_PRESENT) && !FSL_SDK_DISBLE_L2CACHE_PRESENT
L2CACHE_CleanByRange(address, size_byte);
#endif /* !FSL_SDK_DISBLE_L2CACHE_PRESENT */
#endif /* FSL_FEATURE_SOC_L2CACHEC_COUNT */
}
/*!
* brief Cleans and Invalidates all data caches by range.
*
* Both cortex-m7 L1 cache line and L2 PL310 cache line length is 32-byte.
*
* param address The physical address.
* param size_byte size of the memory to be cleaned and invalidated.
* note address and size should be aligned to cache line size
* 32-Byte due to the cache operation unit is one cache line. The startAddr here will be forced
* to align to the cache line size if startAddr is not aligned. For the size_byte, application should
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
*/
void DCACHE_CleanInvalidateByRange(uint32_t address, uint32_t size_byte)
{
L1CACHE_CleanInvalidateDCacheByRange(address, size_byte);
#if defined(FSL_FEATURE_SOC_L2CACHEC_COUNT) && FSL_FEATURE_SOC_L2CACHEC_COUNT
#if defined(FSL_SDK_DISBLE_L2CACHE_PRESENT) && !FSL_SDK_DISBLE_L2CACHE_PRESENT
L2CACHE_CleanInvalidateByRange(address, size_byte);
#endif /* !FSL_SDK_DISBLE_L2CACHE_PRESENT */
#endif /* FSL_FEATURE_SOC_L2CACHEC_COUNT */
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,155 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file fsl_common.c
* @brief common drivers
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.11.11
*/
#include "fsl_common.h"
#define SDK_MEM_MAGIC_NUMBER 12345U
typedef struct _mem_align_control_block
{
uint16_t identifier; /*!< Identifier for the memory control block. */
uint16_t offset; /*!< offset from aligned address to real address */
} mem_align_cb_t;
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.common"
#endif
#ifndef __GIC_PRIO_BITS
#if defined(ENABLE_RAM_VECTOR_TABLE)
uint32_t InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler)
{
/* Addresses for VECTOR_TABLE and VECTOR_RAM come from the linker file */
#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
extern uint32_t Image$$VECTOR_ROM$$Base[];
extern uint32_t Image$$VECTOR_RAM$$Base[];
extern uint32_t Image$$RW_m_data$$Base[];
#define __VECTOR_TABLE Image$$VECTOR_ROM$$Base
#define __VECTOR_RAM Image$$VECTOR_RAM$$Base
#define __RAM_VECTOR_TABLE_SIZE (((uint32_t)Image$$RW_m_data$$Base - (uint32_t)Image$$VECTOR_RAM$$Base))
#elif defined(__ICCARM__)
extern uint32_t __RAM_VECTOR_TABLE_SIZE[];
extern uint32_t __VECTOR_TABLE[];
extern uint32_t __VECTOR_RAM[];
#elif defined(__GNUC__)
extern uint32_t __VECTOR_TABLE[];
extern uint32_t __VECTOR_RAM[];
extern uint32_t __RAM_VECTOR_TABLE_SIZE_BYTES[];
uint32_t __RAM_VECTOR_TABLE_SIZE = (uint32_t)(__RAM_VECTOR_TABLE_SIZE_BYTES);
#endif /* defined(__CC_ARM) || defined(__ARMCC_VERSION) */
uint32_t n;
uint32_t ret;
uint32_t irqMaskValue;
irqMaskValue = DisableGlobalIRQ();
if (SCB->VTOR != (uint32_t)__VECTOR_RAM)
{
/* Copy the vector table from ROM to RAM */
for (n = 0; n < ((uint32_t)__RAM_VECTOR_TABLE_SIZE) / sizeof(uint32_t); n++)
{
__VECTOR_RAM[n] = __VECTOR_TABLE[n];
}
/* Point the VTOR to the position of vector table */
SCB->VTOR = (uint32_t)__VECTOR_RAM;
}
ret = __VECTOR_RAM[irq + 16];
/* make sure the __VECTOR_RAM is noncachable */
__VECTOR_RAM[irq + 16] = irqHandler;
EnableGlobalIRQ(irqMaskValue);
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
return ret;
}
#endif /* ENABLE_RAM_VECTOR_TABLE. */
#endif /* __GIC_PRIO_BITS. */
#if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0))
#if !(defined(FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS) && FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS)
void EnableDeepSleepIRQ(IRQn_Type interrupt)
{
uint32_t intNumber = (uint32_t)interrupt;
uint32_t index = 0;
while (intNumber >= 32u)
{
index++;
intNumber -= 32u;
}
SYSCON->STARTERSET[index] = 1u << intNumber;
EnableIRQ(interrupt); /* also enable interrupt at NVIC */
}
void DisableDeepSleepIRQ(IRQn_Type interrupt)
{
uint32_t intNumber = (uint32_t)interrupt;
DisableIRQ(interrupt); /* also disable interrupt at NVIC */
uint32_t index = 0;
while (intNumber >= 32u)
{
index++;
intNumber -= 32u;
}
SYSCON->STARTERCLR[index] = 1u << intNumber;
}
#endif /* FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS */
#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */
void *SDK_Malloc(size_t size, size_t alignbytes)
{
mem_align_cb_t *p_cb = NULL;
uint32_t alignedsize = SDK_SIZEALIGN(size, alignbytes) + alignbytes + sizeof(mem_align_cb_t);
void *p_align_addr, *p_addr = malloc(alignedsize);
if (!p_addr)
{
return NULL;
}
p_align_addr = (void *)SDK_SIZEALIGN((uint32_t)p_addr + sizeof(mem_align_cb_t), alignbytes);
p_cb = (mem_align_cb_t *)((uint32_t)p_align_addr - 4);
p_cb->identifier = SDK_MEM_MAGIC_NUMBER;
p_cb->offset = (uint32_t)p_align_addr - (uint32_t)p_addr;
return (void *)p_align_addr;
}
void SDK_Free(void *ptr)
{
mem_align_cb_t *p_cb = (mem_align_cb_t *)((uint32_t)ptr - 4);
if (p_cb->identifier != SDK_MEM_MAGIC_NUMBER)
{
return;
}
free((void *)((uint32_t)ptr - p_cb->offset));
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,236 @@
/*
** ###################################################################
** Processors: MIMXRT1052CVJ5B
** MIMXRT1052CVL5B
** MIMXRT1052DVJ6B
** MIMXRT1052DVL6B
**
** Compilers: Freescale C/C++ for Embedded ARM
** GNU C Compiler
** IAR ANSI C/C++ Compiler for ARM
** Keil ARM C/C++ Compiler
** MCUXpresso Compiler
**
** Reference manual: IMXRT1050RM Rev.2.1, 12/2018
** Version: rev. 1.2, 2018-11-27
** Build: b181205
**
** Abstract:
** Provides a system configuration function and a global variable that
** contains the system frequency. It configures the device and initializes
** the oscillator (PLL) that is part of the microcontroller device.
**
** Copyright 2016 Freescale Semiconductor, Inc.
** Copyright 2016-2018 NXP
** All rights reserved.
**
** SPDX-License-Identifier: BSD-3-Clause
**
** http: www.nxp.com
** mail: support@nxp.com
**
** Revisions:
** - rev. 0.1 (2017-01-10)
** Initial version.
** - rev. 1.0 (2018-09-21)
** Update interrupt vector table and dma request source.
** Update register BEE_ADDR_OFFSET1's bitfield name to ADDR_OFFSET1.
** Split GPIO_COMBINED_IRQS to GPIO_COMBINED_LOW_IRQS and GPIO_COMBINED_HIGH_IRQS.
** - rev. 1.1 (2018-11-16)
** Update header files to align with IMXRT1050RM Rev.1.
** - rev. 1.2 (2018-11-27)
** Update header files to align with IMXRT1050RM Rev.2.1.
**
** ###################################################################
*/
/*!
* @file MIMXRT1052
* @version 1.2
* @date 2018-11-27
* @brief Device specific configuration file for MIMXRT1052 (implementation file)
*
* Provides a system configuration function and a global variable that contains
* the system frequency. It configures the device and initializes the oscillator
* (PLL) that is part of the microcontroller device.
*/
#include <stdint.h>
#include "fsl_device_registers.h"
/* ----------------------------------------------------------------------------
-- Core clock
---------------------------------------------------------------------------- */
uint32_t SystemCoreClock = DEFAULT_SYSTEM_CLOCK;
/* ----------------------------------------------------------------------------
-- SystemInit()
---------------------------------------------------------------------------- */
void SystemInit (void) {
#if ((__FPU_PRESENT == 1) && (__FPU_USED == 1))
SCB->CPACR |= ((3UL << 10*2) | (3UL << 11*2)); /* set CP10, CP11 Full Access */
#endif /* ((__FPU_PRESENT == 1) && (__FPU_USED == 1)) */
#if defined(__MCUXPRESSO)
extern uint32_t g_pfnVectors[]; // Vector table defined in startup code
SCB->VTOR = (uint32_t)g_pfnVectors;
#endif
/* Disable Watchdog Power Down Counter */
WDOG1->WMCR &= ~WDOG_WMCR_PDE_MASK;
WDOG2->WMCR &= ~WDOG_WMCR_PDE_MASK;
/* Watchdog disable */
#if (DISABLE_WDOG)
if (WDOG1->WCR & WDOG_WCR_WDE_MASK)
{
WDOG1->WCR &= ~WDOG_WCR_WDE_MASK;
}
if (WDOG2->WCR & WDOG_WCR_WDE_MASK)
{
WDOG2->WCR &= ~WDOG_WCR_WDE_MASK;
}
RTWDOG->CNT = 0xD928C520U; /* 0xD928C520U is the update key */
RTWDOG->TOVAL = 0xFFFF;
RTWDOG->CS = (uint32_t) ((RTWDOG->CS) & ~RTWDOG_CS_EN_MASK) | RTWDOG_CS_UPDATE_MASK;
#endif /* (DISABLE_WDOG) */
/* Disable Systick which might be enabled by bootrom */
if (SysTick->CTRL & SysTick_CTRL_ENABLE_Msk)
{
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}
/* Enable instruction and data caches */
#if defined(__ICACHE_PRESENT) && __ICACHE_PRESENT
if (SCB_CCR_IC_Msk != (SCB_CCR_IC_Msk & SCB->CCR)) {
SCB_EnableICache();
}
#endif
#if defined(__DCACHE_PRESENT) && __DCACHE_PRESENT
if (SCB_CCR_DC_Msk != (SCB_CCR_DC_Msk & SCB->CCR)) {
SCB_EnableDCache();
}
#endif
SystemInitHook();
}
/* ----------------------------------------------------------------------------
-- SystemCoreClockUpdate()
---------------------------------------------------------------------------- */
void SystemCoreClockUpdate (void) {
uint32_t freq;
uint32_t PLL1MainClock;
uint32_t PLL2MainClock;
/* Periph_clk2_clk ---> Periph_clk */
if (CCM->CBCDR & CCM_CBCDR_PERIPH_CLK_SEL_MASK)
{
switch (CCM->CBCMR & CCM_CBCMR_PERIPH_CLK2_SEL_MASK)
{
/* Pll3_sw_clk ---> Periph_clk2_clk ---> Periph_clk */
case CCM_CBCMR_PERIPH_CLK2_SEL(0U):
if(CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_BYPASS_MASK)
{
freq = (((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_MASK) >> CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_SHIFT) == 0U) ?
CPU_XTAL_CLK_HZ : CPU_CLK1_HZ;
}
else
{
freq = (CPU_XTAL_CLK_HZ * ((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_DIV_SELECT_MASK) ? 22U : 20U));
}
break;
/* Osc_clk ---> Periph_clk2_clk ---> Periph_clk */
case CCM_CBCMR_PERIPH_CLK2_SEL(1U):
freq = CPU_XTAL_CLK_HZ;
break;
case CCM_CBCMR_PERIPH_CLK2_SEL(2U):
freq = (((CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_MASK) >> CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_SHIFT) == 0U) ?
CPU_XTAL_CLK_HZ : CPU_CLK1_HZ;
break;
case CCM_CBCMR_PERIPH_CLK2_SEL(3U):
default:
freq = 0U;
break;
}
freq /= (((CCM->CBCDR & CCM_CBCDR_PERIPH_CLK2_PODF_MASK) >> CCM_CBCDR_PERIPH_CLK2_PODF_SHIFT) + 1U);
}
/* Pre_Periph_clk ---> Periph_clk */
else
{
/* check if pll is bypassed */
if(CCM_ANALOG->PLL_ARM & CCM_ANALOG_PLL_ARM_BYPASS_MASK)
{
PLL1MainClock = (((CCM_ANALOG->PLL_ARM & CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC_MASK) >> CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC_SHIFT) == 0U) ?
CPU_XTAL_CLK_HZ : CPU_CLK1_HZ;
}
else
{
PLL1MainClock = ((CPU_XTAL_CLK_HZ * ((CCM_ANALOG->PLL_ARM & CCM_ANALOG_PLL_ARM_DIV_SELECT_MASK) >>
CCM_ANALOG_PLL_ARM_DIV_SELECT_SHIFT)) >> 1U);
}
/* check if pll is bypassed */
if(CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_BYPASS_MASK)
{
PLL2MainClock = (((CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_MASK) >> CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_SHIFT) == 0U) ?
CPU_XTAL_CLK_HZ : CPU_CLK1_HZ;
}
else
{
PLL2MainClock = (CPU_XTAL_CLK_HZ * ((CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_DIV_SELECT_MASK) ? 22U : 20U));
}
PLL2MainClock += ((uint64_t)CPU_XTAL_CLK_HZ * ((uint64_t)(CCM_ANALOG->PLL_SYS_NUM))) / ((uint64_t)(CCM_ANALOG->PLL_SYS_DENOM));
switch (CCM->CBCMR & CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK)
{
/* PLL2 ---> Pre_Periph_clk ---> Periph_clk */
case CCM_CBCMR_PRE_PERIPH_CLK_SEL(0U):
freq = PLL2MainClock;
break;
/* PLL2 PFD2 ---> Pre_Periph_clk ---> Periph_clk */
case CCM_CBCMR_PRE_PERIPH_CLK_SEL(1U):
freq = PLL2MainClock / ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD2_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD2_FRAC_SHIFT) * 18U;
break;
/* PLL2 PFD0 ---> Pre_Periph_clk ---> Periph_clk */
case CCM_CBCMR_PRE_PERIPH_CLK_SEL(2U):
freq = PLL2MainClock / ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD0_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD0_FRAC_SHIFT) * 18U;
break;
/* PLL1 divided(/2) ---> Pre_Periph_clk ---> Periph_clk */
case CCM_CBCMR_PRE_PERIPH_CLK_SEL(3U):
freq = PLL1MainClock / (((CCM->CACRR & CCM_CACRR_ARM_PODF_MASK) >> CCM_CACRR_ARM_PODF_SHIFT) + 1U);
break;
default:
freq = 0U;
break;
}
}
SystemCoreClock = (freq / (((CCM->CBCDR & CCM_CBCDR_AHB_PODF_MASK) >> CCM_CBCDR_AHB_PODF_SHIFT) + 1U));
}
/* ----------------------------------------------------------------------------
-- SystemInitHook()
---------------------------------------------------------------------------- */
__attribute__ ((weak)) void SystemInitHook (void) {
/* Void implementation of the weak function. */
}
@@ -0,0 +1 @@
@@ -0,0 +1,3 @@
SRC_FILES := enet_ethernetif.c enet_ethernetif_kinetis.c fsl_enet.c
SRC_DIR := ksz8081
include $(KERNEL_ROOT)/compiler.mk
@@ -0,0 +1,324 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
/*
* Copyright (c) 2013-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2019 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file enet_ethernetif.c
* @brief ethernet drivers
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.11.11
*/
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/stats.h"
#include "lwip/snmp.h"
#include "lwip/ethip6.h"
#include "netif/etharp.h"
#include "netif/ppp/pppoe.h"
#include "lwip/igmp.h"
#include "lwip/mld6.h"
#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
//#include "FreeRTOS.h"
//#include "event_groups.h"
#endif
#include <board.h>
#include "netif/ethernet.h"
#include "enet_ethernetif.h"
#include "enet_ethernetif_priv.h"
#include "fsl_enet.h"
#include "fsl_phy.h"
#include "fsl_gpio.h"
#include "fsl_iomuxc.h"
#include "sys_arch.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
void enet_delay(void)
{
volatile uint32_t i = 0;
for (i = 0; i < 1000000; ++i)
{
__asm("NOP"); /* delay */
}
}
void Time_Update_LwIP(void)
{
}
ethernetif_config_t enet_cfg = {
.phyAddress = BOARD_ENET0_PHY_ADDRESS,
.clockName = kCLOCK_CoreSysClk,
.macAddress = configMAC_ADDR,
#if defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
.non_dma_memory = non_dma_memory,
#endif /* FSL_FEATURE_SOC_LPC_ENET_COUNT */
};
void *ethernetif_config_enet_set(uint8_t enet_port)
{
return (void *)&enet_cfg;
}
void ethernetif_clk_init(void)
{
const clock_enet_pll_config_t config = {.enableClkOutput = true, .enableClkOutput25M = false, .loopDivider = 1};
CLOCK_InitEnetPll(&config);
SysTick_Config(SystemCoreClock / TICK_PER_SECOND);
}
void ethernetif_gpio_init(void)
{
gpio_pin_config_t gpio_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode};
IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET1TxClkOutputDir, true);
GPIO_PinInit(GPIO1, 3, &gpio_config);
/* pull up the ENET_INT before RESET. */
GPIO_WritePinOutput(GPIO1, 3, 0);
enet_delay();
GPIO_WritePinOutput(GPIO1, 3, 1);
}
void ETH_BSP_Config(void)
{
static int flag = 0;
if(flag == 0)
{
ethernetif_clk_init();
ethernetif_gpio_init();
flag = 1;
}
}
void ethernetif_phy_init(struct ethernetif *ethernetif,
const ethernetif_config_t *ethernetifConfig,
enet_config_t *config)
{
uint32_t sysClock;
status_t status;
bool link = false;
uint32_t count = 0;
phy_speed_t speed;
phy_duplex_t duplex;
sysClock = CLOCK_GetFreq(ethernetifConfig->clockName);
LWIP_PLATFORM_DIAG(("Initializing PHY...\r\n"));
while ((count < ENET_ATONEGOTIATION_TIMEOUT) && (!link))
{
status = PHY_Init(*ethernetif_enet_ptr(ethernetif), ethernetifConfig->phyAddress, sysClock);
if (kStatus_Success == status)
{
PHY_GetLinkStatus(*ethernetif_enet_ptr(ethernetif), ethernetifConfig->phyAddress, &link);
}
else if (kStatus_PHY_AutoNegotiateFail == status)
{
LWIP_PLATFORM_DIAG(("PHY Auto-negotiation failed. Please check the ENET cable connection and link partner setting."));
}
else
{
LWIP_ASSERT("\r\nCannot initialize PHY.\r\n", 0);
}
count++;
}
if (link)
{
/* Get the actual PHY link speed. */
PHY_GetLinkSpeedDuplex(*ethernetif_enet_ptr(ethernetif), ethernetifConfig->phyAddress, &speed, &duplex);
/* Change the MII speed and duplex for actual link status. */
config->miiSpeed = (enet_mii_speed_t)speed;
config->miiDuplex = (enet_mii_duplex_t)duplex;
}
#if 0 /* Disable assert. If initial auto-negation is timeout, \ \
the ENET is set to default (100Mbs and full-duplex). */
else
{
LWIP_ASSERT("\r\nGiving up PHY initialization. Please check the ENET cable connection and link partner setting and reset the board.\r\n", 0);
}
#endif
}
/**
* This function should be called when a packet is ready to be read
* from the interface. It uses the function ethernetif_linkinput() that
* should handle the actual reception of bytes from the network
* interface. Then the type of the received packet is determined and
* the appropriate input function is called.
*
* @param netif the lwip network interface structure for this ethernetif
*/
void ethernetif_input(struct netif *netif)
{
struct pbuf *p;
err_t ret = 0;
LWIP_ASSERT("netif != NULL", (netif != NULL));
/* move received packet into a new pbuf */
while ((p = ethernetif_linkinput(netif)) != NULL)
{
/* pass all packets to ethernet_input, which decides what packets it supports */
if ((ret = netif->input(p, netif)) != ERR_OK)
{
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
lw_print("lw: [%s] ret %d p %p\n", __func__, ret, p);
pbuf_free(p);
p = NULL;
}
}
}
static ENET_Type *ethernetif_get_enet_base(const uint8_t enetIdx)
{
ENET_Type* enets[] = ENET_BASE_PTRS;
int arrayIdx;
int enetCount;
for (arrayIdx = 0, enetCount = 0; arrayIdx < ARRAY_SIZE(enets); arrayIdx++)
{
if (enets[arrayIdx] != 0U) /* process only defined positions */
{ /* (some SOC headers count ENETs from 1 instead of 0) */
if (enetCount == enetIdx)
{
return enets[arrayIdx];
}
enetCount++;
}
}
return NULL;
}
err_t ethernetif_init(struct netif *netif, struct ethernetif *ethernetif,
const uint8_t enetIdx,
const ethernetif_config_t *ethernetifConfig)
{
LWIP_ASSERT("netif != NULL", (netif != NULL));
LWIP_ASSERT("ethernetifConfig != NULL", (ethernetifConfig != NULL));
#if LWIP_NETIF_HOSTNAME
/* Initialize interface hostname */
netif->hostname = "lwip";
#endif /* LWIP_NETIF_HOSTNAME */
/*
* Initialize the snmp variables and counters inside the struct netif.
* The last argument should be replaced with your link speed, in units
* of bits per second.
*/
MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
netif->state = ethernetif;
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
/* We directly use etharp_output() here to save a function call.
* You can instead declare your own function an call etharp_output()
* from it if you have to do some checks before sending (e.g. if link
* is available...) */
#if LWIP_IPV4
netif->output = etharp_output;
#endif
#if LWIP_IPV6
netif->output_ip6 = ethip6_output;
#endif /* LWIP_IPV6 */
netif->linkoutput = ethernetif_linkoutput;
#if LWIP_IPV4 && LWIP_IGMP
netif_set_igmp_mac_filter(netif, ethernetif_igmp_mac_filter);
netif->flags |= NETIF_FLAG_IGMP;
#endif
#if LWIP_IPV6 && LWIP_IPV6_MLD
netif_set_mld_mac_filter(netif, ethernetif_mld_mac_filter);
netif->flags |= NETIF_FLAG_MLD6;
#endif
/* Init ethernetif parameters.*/
*ethernetif_enet_ptr(ethernetif) = ethernetif_get_enet_base(enetIdx);
LWIP_ASSERT("*ethernetif_enet_ptr(ethernetif) != NULL", (*ethernetif_enet_ptr(ethernetif) != NULL));
/* set MAC hardware address length */
netif->hwaddr_len = ETH_HWADDR_LEN;
/* set MAC hardware address */
memcpy(netif->hwaddr, ethernetifConfig->macAddress, NETIF_MAX_HWADDR_LEN);
/* maximum transfer unit */
netif->mtu = 1500; /* TODO: define a config */
/* device capabilities */
/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
/* ENET driver initialization.*/
ethernetif_enet_init(netif, ethernetif, ethernetifConfig);
#if LWIP_IPV6 && LWIP_IPV6_MLD
/*
* For hardware/netifs that implement MAC filtering.
* All-nodes link-local is handled by default, so we must let the hardware know
* to allow multicast packets in.
* Should set mld_mac_filter previously. */
if (netif->mld_mac_filter != NULL)
{
ip6_addr_t ip6_allnodes_ll;
ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
}
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
return ERR_OK;
}
@@ -0,0 +1,675 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
/*
* Copyright (c) 2013-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2019 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file enet_ethernetif_kinetis.c
* @brief ethernet drivers
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.11.11
*/
#include "sys_arch.h"
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/stats.h"
#include "lwip/snmp.h"
#include "lwip/ethip6.h"
#include "netif/etharp.h"
#include "netif/ppp/pppoe.h"
#include "lwip/igmp.h"
#include "lwip/mld6.h"
#ifdef FSL_RTOS_XIUOS
#define USE_RTOS 1
#define FSL_RTOS_FREE_RTOS
#endif
#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
#ifdef FSL_RTOS_XIUOS
#include "xs_sem.h"
#else
#include "FreeRTOS.h"
#include "event_groups.h"
#include "list.h"
#endif
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
typedef TickType_t EventBits_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
#define portBASE_TYPE long
#define pdFALSE ( ( BaseType_t ) 0 )
#define pdTRUE ( ( BaseType_t ) 1 )
#define pdPASS ( pdTRUE )
#define pdFAIL ( pdFALSE )
#ifndef FSL_RTOS_XIUOS
typedef struct EventGroupDef_t
{
EventBits_t uxEventBits;
List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxEventGroupNumber;
#endif
#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
#endif
} EventGroup_t;
struct EventGroupDef_t;
typedef struct EventGroupDef_t * EventGroupHandle_t;
#endif
#endif
#include "enet_ethernetif.h"
#include "enet_ethernetif_priv.h"
#include "fsl_enet.h"
#include "fsl_phy.h"
#include "sys_arch.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/**
* Helper struct to hold private data used to operate your ethernet interface.
*/
struct ethernetif
{
ENET_Type *base;
#if (defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0)) || \
(USE_RTOS && defined(FSL_RTOS_FREE_RTOS))
enet_handle_t handle;
#endif
#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
#ifdef FSL_RTOS_XIUOS
int enetSemaphore;
#else
EventGroupHandle_t enetTransmitAccessEvent;
#endif
EventBits_t txFlag;
#endif
enet_rx_bd_struct_t *RxBuffDescrip;
enet_tx_bd_struct_t *TxBuffDescrip;
rx_buffer_t *RxDataBuff;
tx_buffer_t *TxDataBuff;
};
/*******************************************************************************
* Code
******************************************************************************/
#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
int32 lwip_obtain_semaphore(struct netif *netif)
{
struct ethernetif *ethernetif = netif->state;
return (KSemaphoreObtain(ethernetif->enetSemaphore, WAITING_FOREVER) == EOK);
}
#if FSL_FEATURE_ENET_QUEUE > 1
static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, uint32_t ringId, enet_event_t event, void *param)
#else
static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param)
#endif /* FSL_FEATURE_ENET_QUEUE */
{
struct netif *netif = (struct netif *)param;
struct ethernetif *ethernetif = netif->state;
BaseType_t xResult;
switch (event)
{
case kENET_RxEvent:
ethernetif_input(netif);
break;
case kENET_TxEvent:
#ifndef FSL_RTOS_XIUOS
{
portBASE_TYPE taskToWake = pdFALSE;
#ifdef __CA7_REV
if (SystemGetIRQNestingLevel())
#else
if (__get_IPSR())
#endif
{
xResult = xEventGroupSetBitsFromISR(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag, &taskToWake);
if ((pdPASS == xResult) && (pdTRUE == taskToWake))
{
portYIELD_FROM_ISR(taskToWake);
}
}
else
{
xEventGroupSetBits(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag);
}
}
#endif
break;
default:
break;
}
KSemaphoreAbandon(ethernetif->enetSemaphore);
}
#endif
#if LWIP_IPV4 && LWIP_IGMP
err_t ethernetif_igmp_mac_filter(struct netif *netif, const ip4_addr_t *group,
enum netif_mac_filter_action action)
{
struct ethernetif *ethernetif = netif->state;
uint8_t multicastMacAddr[6];
err_t result;
multicastMacAddr[0] = 0x01U;
multicastMacAddr[1] = 0x00U;
multicastMacAddr[2] = 0x5EU;
multicastMacAddr[3] = (group->addr >> 8) & 0x7FU;
multicastMacAddr[4] = (group->addr >> 16) & 0xFFU;
multicastMacAddr[5] = (group->addr >> 24) & 0xFFU;
switch (action)
{
case IGMP_ADD_MAC_FILTER:
/* Adds the ENET device to a multicast group.*/
ENET_AddMulticastGroup(ethernetif->base, multicastMacAddr);
result = ERR_OK;
break;
case IGMP_DEL_MAC_FILTER:
/*
* Moves the ENET device from a multicast group.
* Since the ENET_LeaveMulticastGroup() could filter out also other
* group addresses having the same hash, the call is commented out.
*/
/* ENET_LeaveMulticastGroup(ethernetif->base, multicastMacAddr); */
result = ERR_OK;
break;
default:
result = ERR_IF;
break;
}
return result;
}
#endif
#if LWIP_IPV6 && LWIP_IPV6_MLD
err_t ethernetif_mld_mac_filter(struct netif *netif, const ip6_addr_t *group,
enum netif_mac_filter_action action)
{
struct ethernetif *ethernetif = netif->state;
uint8_t multicastMacAddr[6];
err_t result;
multicastMacAddr[0] = 0x33U;
multicastMacAddr[1] = 0x33U;
multicastMacAddr[2] = (group->addr[3]) & 0xFFU;
multicastMacAddr[3] = (group->addr[3] >> 8) & 0xFFU;
multicastMacAddr[4] = (group->addr[3] >> 16) & 0xFFU;
multicastMacAddr[5] = (group->addr[3] >> 24) & 0xFFU;
switch (action)
{
case NETIF_ADD_MAC_FILTER:
/* Adds the ENET device to a multicast group.*/
ENET_AddMulticastGroup(ethernetif->base, multicastMacAddr);
result = ERR_OK;
break;
case NETIF_DEL_MAC_FILTER:
/*
* Moves the ENET device from a multicast group.
* Since the ENET_LeaveMulticastGroup() could filter out also other
* group addresses having the same hash, the call is commented out.
*/
/* ENET_LeaveMulticastGroup(ethernetif->base, multicastMacAddr); */
result = ERR_OK;
break;
default:
result = ERR_IF;
break;
}
return result;
}
#endif
/**
* Initializes ENET driver.
*/
void ethernetif_enet_init(struct netif *netif, struct ethernetif *ethernetif,
const ethernetif_config_t *ethernetifConfig)
{
enet_config_t config;
uint32_t sysClock;
enet_buffer_config_t buffCfg[ENET_RING_NUM];
/* prepare the buffer configuration. */
buffCfg[0].rxBdNumber = ENET_RXBD_NUM; /* Receive buffer descriptor number. */
buffCfg[0].txBdNumber = ENET_TXBD_NUM; /* Transmit buffer descriptor number. */
buffCfg[0].rxBuffSizeAlign = sizeof(rx_buffer_t); /* Aligned receive data buffer size. */
buffCfg[0].txBuffSizeAlign = sizeof(tx_buffer_t); /* Aligned transmit data buffer size. */
buffCfg[0].rxBdStartAddrAlign = &(ethernetif->RxBuffDescrip[0]); /* Aligned receive buffer descriptor start address. */
buffCfg[0].txBdStartAddrAlign = &(ethernetif->TxBuffDescrip[0]); /* Aligned transmit buffer descriptor start address. */
buffCfg[0].rxBufferAlign = &(ethernetif->RxDataBuff[0][0]); /* Receive data buffer start address. */
buffCfg[0].txBufferAlign = &(ethernetif->TxDataBuff[0][0]); /* Transmit data buffer start address. */
sysClock = CLOCK_GetFreq(ethernetifConfig->clockName);
ENET_GetDefaultConfig(&config);
config.ringNum = ENET_RING_NUM;
config.macSpecialConfig |= kENET_ControlPromiscuousEnable;
ethernetif_phy_init(ethernetif, ethernetifConfig, &config);
#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
uint32_t instance;
static ENET_Type *const enetBases[] = ENET_BASE_PTRS;
static const IRQn_Type enetTxIrqId[] = ENET_Transmit_IRQS;
/*! @brief Pointers to enet receive IRQ number for each instance. */
static const IRQn_Type enetRxIrqId[] = ENET_Receive_IRQS;
#if defined(ENET_ENHANCEDBUFFERDESCRIPTOR_MODE) && ENET_ENHANCEDBUFFERDESCRIPTOR_MODE
/*! @brief Pointers to enet timestamp IRQ number for each instance. */
static const IRQn_Type enetTsIrqId[] = ENET_1588_Timer_IRQS;
#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */
/* Create the Event for transmit busy release trigger. */
#ifdef FSL_RTOS_XIUOS
if(ethernetif->enetSemaphore < 0)
{
ethernetif->enetSemaphore = KSemaphoreCreate(0);
}
#else
ethernetif->enetTransmitAccessEvent = xEventGroupCreate();
#endif
ethernetif->txFlag = 0x1;
config.interrupt |= kENET_RxFrameInterrupt | kENET_TxFrameInterrupt | kENET_TxBufferInterrupt;
for (instance = 0; instance < ARRAY_SIZE(enetBases); instance++)
{
if (enetBases[instance] == ethernetif->base)
{
#ifdef __CA7_REV
GIC_SetPriority(enetRxIrqId[instance], ENET_PRIORITY);
GIC_SetPriority(enetTxIrqId[instance], ENET_PRIORITY);
#if defined(ENET_ENHANCEDBUFFERDESCRIPTOR_MODE) && ENET_ENHANCEDBUFFERDESCRIPTOR_MODE
GIC_SetPriority(enetTsIrqId[instance], ENET_1588_PRIORITY);
#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */
#else
NVIC_SetPriority(enetRxIrqId[instance], ENET_PRIORITY);
NVIC_SetPriority(enetTxIrqId[instance], ENET_PRIORITY);
#if defined(ENET_ENHANCEDBUFFERDESCRIPTOR_MODE) && ENET_ENHANCEDBUFFERDESCRIPTOR_MODE
NVIC_SetPriority(enetTsIrqId[instance], ENET_1588_PRIORITY);
#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */
#endif /* __CA7_REV */
break;
}
}
LWIP_ASSERT("Input Ethernet base error!", (instance != ARRAY_SIZE(enetBases)));
#endif /* USE_RTOS */
/* Initialize the ENET module.*/
ENET_Init(ethernetif->base, &ethernetif->handle, &config, &buffCfg[0], netif->hwaddr, sysClock);
#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
ENET_SetCallback(&ethernetif->handle, ethernet_callback, netif);
#endif
ENET_ActiveRead(ethernetif->base);
// low_level_init();
}
ENET_Type **ethernetif_enet_ptr(struct ethernetif *ethernetif)
{
return &(ethernetif->base);
}
/**
* Returns next buffer for TX.
* Can wait if no buffer available.
*/
static unsigned char *enet_get_tx_buffer(struct ethernetif *ethernetif)
{
static unsigned char ucBuffer[ENET_FRAME_MAX_FRAMELEN];
return ucBuffer;
}
/**
* Sends frame via ENET.
*/
static err_t enet_send_frame(struct ethernetif *ethernetif, unsigned char *data, const uint32_t length)
{
#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
{
status_t result;
lw_print("lw: [%s] len %d\n", __func__, length);
do
{
result = ENET_SendFrame(ethernetif->base, &ethernetif->handle, data, length);
if (result == kStatus_ENET_TxFrameBusy)
{
#ifdef FSL_RTOS_XIUOS
KSemaphoreObtain(ethernetif->enetSemaphore, portMAX_DELAY);
#else
xEventGroupWaitBits(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag, pdTRUE, (BaseType_t) false,
portMAX_DELAY);
#endif
}
} while (result == kStatus_ENET_TxFrameBusy);
return ERR_OK;
}
#else
{
uint32_t counter;
for (counter = ENET_TIMEOUT; counter != 0U; counter--)
{
if (ENET_SendFrame(ethernetif->base, &ethernetif->handle, data, length) != kStatus_ENET_TxFrameBusy)
{
return ERR_OK;
}
}
return ERR_TIMEOUT;
}
#endif
}
struct pbuf *ethernetif_linkinput(struct netif *netif)
{
struct ethernetif *ethernetif = netif->state;
struct pbuf *p = NULL;
struct pbuf *q;
uint32_t len;
status_t status;
/* Obtain the size of the packet and put it into the "len"
variable. */
status = ENET_GetRxFrameSize(&ethernetif->handle, &len);
if (kStatus_ENET_RxFrameEmpty != status)
{
/* Call ENET_ReadFrame when there is a received frame. */
if (len != 0)
{
#if ETH_PAD_SIZE
len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
#endif
/* We allocate a pbuf chain of pbufs from the pool. */
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
if (p != NULL)
{
#if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
if (p->next == 0) /* One-chain buffer.*/
{
ENET_ReadFrame(ethernetif->base, &ethernetif->handle, p->payload, p->len);
}
else /* Multi-chain buffer.*/
{
uint8_t data_tmp[ENET_FRAME_MAX_FRAMELEN];
uint32_t data_tmp_len = 0;
ENET_ReadFrame(ethernetif->base, &ethernetif->handle, data_tmp, p->tot_len);
/* We iterate over the pbuf chain until we have read the entire
* packet into the pbuf. */
for (q = p; (q != NULL) && ((data_tmp_len + q->len) <= sizeof(data_tmp)); q = q->next)
{
/* Read enough bytes to fill this pbuf in the chain. The
* available data in the pbuf is given by the q->len
* variable. */
memcpy(q->payload, &data_tmp[data_tmp_len], q->len);
data_tmp_len += q->len;
}
}
MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
if (((u8_t *)p->payload)[0] & 1)
{
/* broadcast or multicast packet*/
MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);
}
else
{
/* unicast packet*/
MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
}
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
LINK_STATS_INC(link.recv);
}
else
{
/* drop packet*/
ENET_ReadFrame(ethernetif->base, &ethernetif->handle, NULL, 0U);
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_linkinput: Fail to allocate new memory space\n"));
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
MIB2_STATS_NETIF_INC(netif, ifindiscards);
}
}
else
{
/* Update the received buffer when error happened. */
if (status == kStatus_ENET_RxFrameError)
{
#if 0 && defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0) /* Error statisctics */
enet_data_error_stats_t eErrStatic;
/* Get the error information of the received g_frame. */
ENET_GetRxErrBeforeReadFrame(&ethernetif->handle, &eErrStatic);
#endif
/* Update the receive buffer. */
ENET_ReadFrame(ethernetif->base, &ethernetif->handle, NULL, 0U);
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_linkinput: RxFrameError\n"));
LINK_STATS_INC(link.drop);
MIB2_STATS_NETIF_INC(netif, ifindiscards);
}
}
}
return p;
}
err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p)
{
err_t result;
struct ethernetif *ethernetif = netif->state;
struct pbuf *q;
unsigned char *pucBuffer;
unsigned char *pucChar;
LWIP_ASSERT("Output packet buffer empty", p);
pucBuffer = enet_get_tx_buffer(ethernetif);
if (pucBuffer == NULL)
{
return ERR_BUF;
}
/* Initiate transfer. */
#if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
if (p->len == p->tot_len)
{
/* No pbuf chain, don't have to copy -> faster. */
pucBuffer = (unsigned char *)p->payload;
}
else
{
/* pbuf chain, copy into contiguous ucBuffer. */
if (p->tot_len > ENET_FRAME_MAX_FRAMELEN)
{
return ERR_BUF;
}
else
{
pucChar = pucBuffer;
for (q = p; q != NULL; q = q->next)
{
/* Send the data from the pbuf to the interface, one pbuf at a
time. The size of the data in each pbuf is kept in the ->len
variable. */
/* send data from(q->payload, q->len); */
memcpy(pucChar, q->payload, q->len);
pucChar += q->len;
}
}
}
/* Send frame. */
result = enet_send_frame(ethernetif, pucBuffer, p->tot_len);
MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
if (((u8_t *)p->payload)[0] & 1)
{
/* broadcast or multicast packet*/
MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
}
else
{
/* unicast packet */
MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
}
/* increase ifoutdiscards or ifouterrors on error */
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
LINK_STATS_INC(link.xmit);
return result;
}
/**
* Should be called at the beginning of the program to set up the
* first network interface. It calls the function ethernetif_init() to do the
* actual setup of the hardware.
*
* This function should be passed as a parameter to netif_add().
*
* @param netif the lwip network interface structure for this ethernetif
* @return ERR_OK if the loopif is initialized
* ERR_MEM if private data couldn't be allocated
* any other err_t on error
*/
err_t ethernetif0_init(struct netif *netif)
{
static struct ethernetif ethernetif_0;
AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rxBuffDescrip_0[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t txBuffDescrip_0[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
SDK_ALIGN(static rx_buffer_t rxDataBuff_0[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
SDK_ALIGN(static tx_buffer_t txDataBuff_0[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
ethernetif_0.RxBuffDescrip = &(rxBuffDescrip_0[0]);
ethernetif_0.TxBuffDescrip = &(txBuffDescrip_0[0]);
ethernetif_0.RxDataBuff = &(rxDataBuff_0[0]);
ethernetif_0.TxDataBuff = &(txDataBuff_0[0]);
return ethernetif_init(netif, &ethernetif_0, 0U, (ethernetif_config_t *)netif->state);
}
#if defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 1)
/**
* Should be called at the beginning of the program to set up the
* second network interface. It calls the function ethernetif_init() to do the
* actual setup of the hardware.
*
* This function should be passed as a parameter to netif_add().
*
* @param netif the lwip network interface structure for this ethernetif
* @return ERR_OK if the loopif is initialized
* ERR_MEM if private data couldn't be allocated
* any other err_t on error
*/
err_t ethernetif1_init(struct netif *netif)
{
static struct ethernetif ethernetif_1;
AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rxBuffDescrip_1[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t txBuffDescrip_1[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
SDK_ALIGN(static rx_buffer_t rxDataBuff_1[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
SDK_ALIGN(static tx_buffer_t txDataBuff_1[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
ethernetif_1.RxBuffDescrip = &(rxBuffDescrip_1[0]);
ethernetif_1.TxBuffDescrip = &(txBuffDescrip_1[0]);
ethernetif_1.RxDataBuff = &(rxDataBuff_1[0]);
ethernetif_1.TxDataBuff = &(txDataBuff_1[0]);
return ethernetif_init(netif, &ethernetif_1, 1U, (ethernetif_config_t *)netif->state);
}
#endif /* FSL_FEATURE_SOC_*_ENET_COUNT */
@@ -0,0 +1,960 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
/*
* Copyright (c) 2013-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2019 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file enet_ethernetif_lpc.c
* @brief ethernet drivers
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.11.11
*/
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/stats.h"
#include "lwip/snmp.h"
#include "lwip/sys.h"
#include "lwip/ethip6.h"
#include "netif/etharp.h"
#include "netif/ppp/pppoe.h"
#include "lwip/igmp.h"
#include "lwip/mld6.h"
//#if !NO_SYS
//#include "FreeRTOS.h"
//#include "event_groups.h"
//#include "lwip/tcpip.h"
//#endif /* !NO_SYS */
#include "enet_ethernetif.h"
#include "enet_ethernetif_priv.h"
#include "fsl_enet.h"
#include "fsl_phy.h"
//#if MEM_ALIGNMENT != FSL_ENET_BUFF_ALIGNMENT
///* These two has to match for zero-copy functionality */
//#error "MEM_ALIGNMENT != FSL_ENET_BUFF_ALIGNMENT"
//#endif /* MEM_ALIGNMENT != FSL_ENET_BUFF_ALIGNMENT */
/*******************************************************************************
* Definitions
******************************************************************************/
/*!
* @brief Used to wrap received data in a pbuf to be passed into lwIP
* without copying.
* Once last reference is released, RX descriptor will be returned to DMA.
*/
typedef struct rx_pbuf_wrapper
{
struct pbuf_custom p; /*!< Pbuf wrapper. Has to be first. */
enet_rx_bd_struct_t* rxDesc; /*!< Descriptor holding the data. */
struct ethernetif *ethernetif; /*!< Ethernet interface context data. */
volatile bool ownedByLwip; /*!< If true, descriptor cannot be reused by DMA yet. */
} rx_pbuf_wrapper_t;
/*!
* @brief Helper struct to hold private data used to operate
* your ethernet interface.
*/
struct ethernetif
{
ENET_Type *base;
enet_handle_t handle;
#if !NO_SYS
EventGroupHandle_t enetTransmitAccessEvent;
EventBits_t txFlag;
#endif /* !NO_SYS */
enet_rx_bd_struct_t *RxBuffDescrip;
enet_tx_bd_struct_t *TxBuffDescrip;
rx_buffer_t *RxDataBuff;
volatile struct pbuf *txPbufs[ENET_TXBD_NUM];
volatile uint8_t txIdx;
volatile uint8_t txReleaseIdx;
rx_pbuf_wrapper_t rxPbufs[ENET_RXBD_NUM];
uint8_t rxIdx;
const mem_range_t *non_dma_memory;
};
static void ethernetif_tx_release(struct ethernetif *ethernetif);
static void ethernetif_rx_release(struct pbuf *p);
/*******************************************************************************
* Code
******************************************************************************/
/**
* Called from ENET ISR.
*/
static void ethernet_callback(ENET_Type *base, enet_handle_t *handle,
enet_event_t event, uint8_t channel, void *param)
#if NO_SYS
{
struct netif *netif = (struct netif *)param;
struct ethernetif *ethernetif = netif->state;
if (event == kENET_TxIntEvent)
{
ethernetif_tx_release(ethernetif);
}
}
#else
{
struct netif *netif = (struct netif *)param;
struct ethernetif *ethernetif = netif->state;
BaseType_t xResult;
switch (event)
{
case kENET_RxIntEvent:
ethernetif_input(netif);
break;
case kENET_TxIntEvent:
{
portBASE_TYPE taskToWake = pdFALSE;
ethernetif_tx_release(ethernetif);
#ifdef __CA7_REV
if (SystemGetIRQNestingLevel())
#else
if (__get_IPSR())
#endif
{
xResult = xEventGroupSetBitsFromISR(
ethernetif->enetTransmitAccessEvent,
ethernetif->txFlag, &taskToWake);
if ((pdPASS == xResult) && (pdTRUE == taskToWake))
{
portYIELD_FROM_ISR(taskToWake);
}
}
else
{
xEventGroupSetBits(ethernetif->enetTransmitAccessEvent,
ethernetif->txFlag);
}
break;
}
default:
break;
}
}
#endif /* NO_SYS */
#if LWIP_IPV4 && LWIP_IGMP
err_t ethernetif_igmp_mac_filter(struct netif *netif, const ip4_addr_t *group,
enum netif_mac_filter_action action)
{
struct ethernetif *ethernetif = netif->state;
err_t result;
switch (action)
{
case IGMP_ADD_MAC_FILTER:
/* LPC ENET does not accept multicast selectively,
* so all multicast has to be passed through. */
ENET_AcceptAllMulticast(ethernetif->base);
result = ERR_OK;
break;
case IGMP_DEL_MAC_FILTER:
/*
* Moves the ENET device from a multicast group.
* Since we don't keep track of which multicast groups
* are still to enabled, the call is commented out.
*/
/* ENET_RejectAllMulticast(ethernetif->base); */
result = ERR_OK;
break;
default:
result = ERR_IF;
break;
}
return result;
}
#endif
#if LWIP_IPV6 && LWIP_IPV6_MLD
err_t ethernetif_mld_mac_filter(struct netif *netif, const ip6_addr_t *group,
enum netif_mac_filter_action action)
{
struct ethernetif *ethernetif = netif->state;
err_t result;
switch (action)
{
case NETIF_ADD_MAC_FILTER:
/* LPC ENET does not accept multicast selectively,
* so all multicast has to be passed through. */
ENET_AcceptAllMulticast(ethernetif->base);
result = ERR_OK;
break;
case NETIF_DEL_MAC_FILTER:
/*
* Moves the ENET device from a multicast group.
* Since we don't keep track of which multicast groups
* are still to enabled, the call is commented out.
*/
/* ENET_RejectAllMulticast(ethernetif->base); */
result = ERR_OK;
break;
default:
result = ERR_IF;
break;
}
return result;
}
#endif
/**
* Gets the RX descriptor by its index.
*/
static inline enet_rx_bd_struct_t *ethernetif_get_rx_desc(
struct ethernetif *ethernetif,
uint32_t index)
{
return &(ethernetif->RxBuffDescrip[index]);
}
/**
* Gets the TX descriptor by its index.
*/
static inline enet_tx_bd_struct_t *ethernetif_get_tx_desc(
struct ethernetif *ethernetif,
uint32_t index)
{
return &(ethernetif->TxBuffDescrip[index]);
}
/**
* Initializes ENET driver.
*/
void ethernetif_enet_init(struct netif *netif, struct ethernetif *ethernetif,
const ethernetif_config_t *ethernetifConfig)
{
enet_config_t config;
uint32_t sysClock;
enet_buffer_config_t buffCfg[ENET_RING_NUM];
uint32_t rxBufferStartAddr[ENET_RXBD_NUM];
uint32_t i;
/* calculate start addresses of all rx buffers */
for (i = 0; i < ENET_RXBD_NUM; i++)
{
rxBufferStartAddr[i] = (uint32_t)&(ethernetif->RxDataBuff[i][ETH_PAD_SIZE]);
}
/* prepare the buffer configuration. */
buffCfg[0].rxRingLen = ENET_RXBD_NUM; /* The length of receive buffer descriptor ring. */
buffCfg[0].txRingLen = ENET_TXBD_NUM; /* The length of transmit buffer descriptor ring. */
buffCfg[0].txDescStartAddrAlign = ethernetif_get_tx_desc(ethernetif, 0U); /* Aligned transmit descriptor start address. */
buffCfg[0].txDescTailAddrAlign = ethernetif_get_tx_desc(ethernetif, 0U); /* Aligned transmit descriptor tail address. */
buffCfg[0].rxDescStartAddrAlign = ethernetif_get_rx_desc(ethernetif, 0U); /* Aligned receive descriptor start address. */
buffCfg[0].rxDescTailAddrAlign = ethernetif_get_rx_desc(ethernetif, ENET_RXBD_NUM); /* Aligned receive descriptor tail address. */
buffCfg[0].rxBufferStartAddr = rxBufferStartAddr; /* Start addresses of the rx buffers. */
buffCfg[0].rxBuffSizeAlign = sizeof(rx_buffer_t); /* Aligned receive data buffer size. */
sysClock = CLOCK_GetFreq(ethernetifConfig->clockName);
LWIP_ASSERT("ethernetifConfig->non_dma_memory == NULL", (ethernetifConfig->non_dma_memory != NULL));
ethernetif->non_dma_memory = ethernetifConfig->non_dma_memory;
ENET_GetDefaultConfig(&config);
config.multiqueueCfg = NULL;
ethernetif_phy_init(ethernetif, ethernetifConfig, &config);
#if !NO_SYS
/* Create the Event for transmit busy release trigger. */
ethernetif->enetTransmitAccessEvent = xEventGroupCreate();
ethernetif->txFlag = 0x1;
#endif /* !NO_SYS */
NVIC_SetPriority(ETHERNET_IRQn, ENET_PRIORITY);
ethernetif->txIdx = 0U;
ethernetif->rxIdx = 0U;
ethernetif->txReleaseIdx = 0U;
for (i = 0; i < ENET_RXBD_NUM; i++)
{
ethernetif->rxPbufs[i].p.custom_free_function = ethernetif_rx_release;
ethernetif->rxPbufs[i].rxDesc = &ethernetif->RxBuffDescrip[i];
ethernetif->rxPbufs[i].ethernetif = ethernetif;
ethernetif->rxPbufs[i].ownedByLwip = false;
}
ENET_Init(ethernetif->base, &config, netif->hwaddr, sysClock);
#if defined(LPC54018_SERIES)
/* Workaround for receive issue on lpc54018 */
ethernetif->base->MAC_FRAME_FILTER |= ENET_MAC_FRAME_FILTER_RA_MASK;
#endif
/* Create the handler. */
#if NO_SYS
ENET_EnableInterrupts(ethernetif->base, kENET_DmaTx);
#else
ENET_EnableInterrupts(ethernetif->base, kENET_DmaTx | kENET_DmaRx);
#endif /* NO_SYS */
ENET_CreateHandler(ethernetif->base, &ethernetif->handle, &config,
&buffCfg[0], ethernet_callback, netif);
ENET_DescriptorInit(ethernetif->base, &config, &buffCfg[0]);
/* Active TX/RX. */
ENET_StartRxTx(ethernetif->base, 1, 1);
}
ENET_Type **ethernetif_enet_ptr(struct ethernetif *ethernetif)
{
return &(ethernetif->base);
}
/**
* Find the ENET instance index from its base address.
*/
static uint32_t ethernetif_get_enet_idx(ENET_Type *base)
{
static ENET_Type *const s_enetBases[] = ENET_BASE_PTRS;
uint32_t instance;
for (instance = 0; instance < FSL_FEATURE_SOC_LPC_ENET_COUNT; instance++)
{
if (s_enetBases[instance] == base)
{
break;
}
}
LWIP_ASSERT("Cannot find ENET instance index from its base address.",
instance < FSL_FEATURE_SOC_LPC_ENET_COUNT);
return instance;
}
/**
* Sends (part of) a frame via ENET.
* TODO: Since ENET_SendFrame() could not be used, some functionality it does
* is missing here for now (channel selection depending on AVB content,
* timestamping.
*/
static void ethernetif_send_buffer(struct ethernetif *ethernetif,
unsigned char *data,
const uint32_t length,
struct pbuf *p_to_release,
enet_desc_flag flag)
{
static const IRQn_Type s_enetIrqId[] = ENET_IRQS;
enet_tx_bd_struct_t *txDesc = ethernetif_get_tx_desc(ethernetif,
ethernetif->txIdx);
ethernetif->txPbufs[ethernetif->txIdx] = p_to_release;
ethernetif->txIdx = (ethernetif->txIdx + 1) % ENET_TXBD_NUM;
/* Prepare the descriptor for transmit. */
txDesc->buff1Addr = (uint32_t)data;
txDesc->buff2Addr = (uint32_t)NULL;
txDesc->buffLen =
ENET_TXDESCRIP_RD_BL1(length) | ENET_TXDESCRIP_RD_IOC_MASK;
txDesc->controlStat =
ENET_TXDESCRIP_RD_FL(length) | ENET_TXDESCRIP_RD_LDFD(flag);
if ((flag & kENET_FirstFlagOnly) == 0)
{
/*
* Submit to DMA if not the first descriptor in chain.
* All the descriptors have to be prepared before the first one
* is flagged for DMA and transfer starts. ENET could output invalid
* frames otherwise (the exception is Store and Forward mode, where
* delays between preparing of descriptors does not matter).
*/
txDesc->controlStat |= ENET_TXDESCRIP_RD_OWN_MASK;
}
enet_tx_bd_ring_t *txBdRing = (enet_tx_bd_ring_t *)
&ethernetif->handle.txBdRing[0];
/*
* Increment txDescUsed.
* Without this, callback would not fire from ENET ISR on finished TX.
* This is kind of a hack. Alternative could be to define
* void ETHERNET_DriverIRQHandler(void) and handle IRQs completely
* in this file.
*/
DisableIRQ(s_enetIrqId[ethernetif_get_enet_idx(ethernetif->base)]);
txBdRing->txDescUsed++;
EnableIRQ(s_enetIrqId[ethernetif_get_enet_idx(ethernetif->base)]);
}
/**
* Reclaims exactly one TX descriptor after its data has been sent out.
* Then the descriptor can be used by application to prepare next data to send.
*/
static void ethernetif_tx_release(struct ethernetif *ethernetif)
{
LWIP_ASSERT("Attempt to release more TX buffers than acquired.",
ethernetif->txIdx != ethernetif->txReleaseIdx);
enet_tx_bd_struct_t *txDesc
= &ethernetif->TxBuffDescrip[ethernetif->txReleaseIdx];
LWIP_ASSERT("TX buffer still owned by DMA.",
!ENET_IsTxDescriptorDmaOwn(txDesc));
struct pbuf *p = (struct pbuf *)
ethernetif->txPbufs[ethernetif->txReleaseIdx];
if (p != NULL)
{
#if ETH_PAD_SIZE
/* Reclaim the padding, force because it may be REF pbuf. */
pbuf_header_force(p, ETH_PAD_SIZE);
#endif
#if NO_SYS
#if defined(LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT) && LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
pbuf_free(p);
#else
#error "Bare metal requires LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT=1 because pbuf_free() is being called from an ISR"
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
#else
if (pbuf_free_callback(p) != ERR_OK)
{
#if defined(LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT) && LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
pbuf_free(p);
#else
LWIP_ASSERT("Failed to enqueue pbuf deallocation on tcpip_thread",
0);
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
}
#endif /* NO_SYS */
ethernetif->txPbufs[ethernetif->txReleaseIdx] = NULL;
}
ethernetif->txReleaseIdx = (ethernetif->txReleaseIdx + 1) % ENET_TXBD_NUM;
}
/**
* Reclaims RX descriptor which holds the p's buffer after p is no longer used
* by the application / lwIP. The DMA can receive new data into
* the descriptor's buffer then.
* Note that RX buffers may be freed by lwIP out of the order in which they were
* passed to lwIP. Therefore there may be spaces between the RX descriptors
* flagged as owned by DMA and DMA could still wait until it's actual position
* is released.
*/
static void ethernetif_rx_release(struct pbuf *p)
{
SYS_ARCH_DECL_PROTECT(old_level);
rx_pbuf_wrapper_t *wrapper = (rx_pbuf_wrapper_t *)p;
#if NO_SYS
bool intEnable = false;
#else
bool intEnable = true;
#endif /* NO_SYS */
SYS_ARCH_PROTECT(old_level);
wrapper->ownedByLwip = false;
/* Update the receive buffer descriptor. */
ENET_UpdateRxDescriptor(wrapper->rxDesc, NULL, NULL, intEnable, false);
ENET_UpdateRxDescriptorTail(wrapper->ethernetif->base, 0U,
(uint32_t)ethernetif_get_rx_desc(wrapper->ethernetif, ENET_RXBD_NUM));
SYS_ARCH_UNPROTECT(old_level);
}
/**
* Gets the length of a received frame (if there is some).
*/
static status_t ethernetif_get_rx_frame_size(struct ethernetif *ethernetif,
uint32_t *length)
{
uint8_t index = ethernetif->rxIdx;
enet_rx_bd_struct_t *rxDesc;
uint32_t rxControl;
/* Reset the length to zero. */
*length = 0;
do
{
rxDesc = ethernetif_get_rx_desc(ethernetif, index);
rxControl = ENET_GetRxDescriptor(rxDesc);
if ((rxControl & ENET_RXDESCRIP_WR_OWN_MASK)
|| (ethernetif->rxPbufs[index].ownedByLwip))
{
/*
* Buffer descriptor is owned by DMA or lwIP.
* We haven't received any complete frame yet.
*/
return kStatus_ENET_RxFrameEmpty;
}
/* Application owns the buffer descriptor. */
if (rxControl & ENET_RXDESCRIP_WR_LD_MASK)
{
/* It's last descriptor of a frame, get its status or length. */
if (rxControl & ENET_RXDESCRIP_WR_ERRSUM_MASK)
{
return kStatus_ENET_RxFrameError;
}
else
{
*length = rxControl & ENET_RXDESCRIP_WR_PACKETLEN_MASK;
return kStatus_Success;
}
}
index = (index + 1U) % ENET_RXBD_NUM;
} while (index != ethernetif->rxIdx);
/*
* All descriptors have data but the end of the frame not detected.
*/
return kStatus_ENET_RxFrameError;
}
/**
* Drops (releases) receive descriptors until the last one of a frame is reached
* or drops entire descriptor ring when all descriptors have data but end
* of the frame not detected among them.
* Function can be called only after ethernetif_get_rx_frame_size() indicates
* that there actually is a frame error or a received frame.
*/
static void ethernetif_drop_frame(struct ethernetif *ethernetif)
{
#if NO_SYS
bool intEnable = false;
#else
bool intEnable = true;
#endif /* NO_SYS */
enet_rx_bd_struct_t *rxDesc;
uint8_t index = ethernetif->rxIdx;
uint32_t rxControl;
do
{
rxDesc = ethernetif_get_rx_desc(ethernetif, ethernetif->rxIdx);
ethernetif->rxIdx = (ethernetif->rxIdx + 1U) % ENET_RXBD_NUM;
rxControl = ENET_GetRxDescriptor(rxDesc);
/* Update the receive buffer descriptor. */
ENET_UpdateRxDescriptor(rxDesc, NULL, NULL, intEnable, false);
/* Find the last buffer descriptor for the frame. */
if (rxControl & ENET_RXDESCRIP_WR_LD_MASK)
{
break;
}
} while (ethernetif->rxIdx != index);
ENET_UpdateRxDescriptorTail(ethernetif->base, 0U,
(uint32_t)ethernetif_get_rx_desc(ethernetif, ENET_RXBD_NUM));
}
/**
* Reads a received frame - wraps its descriptor buffer(s) into a pbuf
* or a pbuf chain, flag descriptors as owned by lwIP and returns the pbuf.
* The descriptors are returned to DMA only after the returned pbuf is released.
* Function can be called only after ethernetif_get_rx_frame_size() indicates
* that there actually is a received frame.
*/
static struct pbuf *ethernetif_read_frame(struct ethernetif *ethernetif,
uint32_t length)
{
rx_pbuf_wrapper_t *wrapper;
enet_rx_bd_struct_t *rxDesc;
uint32_t rxControl;
uint32_t len = 0;
struct pbuf *p = NULL;
struct pbuf *q = NULL;
do
{
wrapper = &ethernetif->rxPbufs[ethernetif->rxIdx];
wrapper->ownedByLwip = true;
ethernetif->rxIdx = (ethernetif->rxIdx + 1U) % ENET_RXBD_NUM;
rxDesc = wrapper->rxDesc;
rxControl = ENET_GetRxDescriptor(rxDesc);
len = (rxControl & ENET_RXDESCRIP_WR_PACKETLEN_MASK);
/* Wrap the receive buffer in pbuf. */
if (p == NULL)
{
p = pbuf_alloced_custom(PBUF_RAW, len, PBUF_REF, &wrapper->p,
(void *)rxDesc->buff1Addr, len);
LWIP_ASSERT("pbuf_alloced_custom() failed", p);
#if ETH_PAD_SIZE
/* Add the padding header, force because it is a REF type buffer. */
pbuf_header_force(p, ETH_PAD_SIZE);
#endif
}
else
{
q = pbuf_alloced_custom(PBUF_RAW, len, PBUF_REF, &wrapper->p,
(void *)rxDesc->buff1Addr, len);
LWIP_ASSERT("pbuf_alloced_custom() failed", q);
pbuf_cat(p, q);
}
} while (((rxControl & ENET_RXDESCRIP_WR_LD_MASK) == 0U)
&& (p->tot_len < length));
MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
if (((u8_t *)p->payload)[0] & 1)
{
/* broadcast or multicast packet */
MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);
}
else
{
/* unicast packet */
MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
}
LINK_STATS_INC(link.recv);
return p;
}
/**
* Attempts to read a frame from ENET and returns it wrapped in a pbuf
* or returns NULL when no frame is received. Discards invalid frames.
*/
struct pbuf *ethernetif_linkinput(struct netif *netif)
{
struct ethernetif *ethernetif = netif->state;
struct pbuf *p = NULL;
uint32_t len;
status_t status;
/* Obtain the size of the packet and put it into the "len" variable. */
status = ethernetif_get_rx_frame_size(ethernetif, &len);
if (status == kStatus_Success)
{
p = ethernetif_read_frame(ethernetif, len);
if (p == NULL)
{
/* Could not initialise wrapper pbuf(s) - drop the frame. */
ethernetif_drop_frame(ethernetif);
LWIP_DEBUGF(NETIF_DEBUG,
("ethernetif_linkinput: Fail to allocate new memory space\n"));
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
MIB2_STATS_NETIF_INC(netif, ifindiscards);
}
}
else if (status == kStatus_ENET_RxFrameError)
{
/* Update the received buffer when error happened. */
ethernetif_drop_frame(ethernetif);
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_linkinput: RxFrameError\n"));
LINK_STATS_INC(link.drop);
MIB2_STATS_NETIF_INC(netif, ifindiscards);
}
return p;
}
/**
* Returns the number of TX descriptors which could be used by lwIP/application
* to put new TX data into.
*
* The max number of free descriptors is (ENET_TXBD_NUM - 1), that is when
* ethernetif->txReleaseIdx == ethernetif->txIdx. Having the capacity decreased
* by one allows to avoid locking: txReleaseIdx is advanced only from ISR
* and txIdx from tcpip_thread/main loop. Should we use full capacity and have
* some variable to indicate between the "all buffers are free" vs. "all buffers
* are used" situation, it would be manipulated from two contexts hence locking
* would be needed.
*/
static inline int ethernetif_avail_tx_descs(struct ethernetif *ethernetif)
{
return (ethernetif->txReleaseIdx + ENET_TXBD_NUM - 1 - ethernetif->txIdx)
% ENET_TXBD_NUM;
}
/**
* Attempts to output a frame from ENET. The function avoids copying of
* p's payload when possible. In such situation it increases p's reference count
* and decreases it (and possibly releases p) after the payload is sent.
*/
err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p)
{
struct ethernetif *ethernetif = netif->state;
struct pbuf *q;
struct pbuf *pbuf_to_free = NULL;
struct pbuf *p_copy;
uint16_t clen;
bool copy = false;
const mem_range_t *non_dma_memory;
uint8_t *dst;
uint32_t cnt = 0;
uint8_t first_idx;
uint32_t tail_address;
LWIP_ASSERT("Output packet buffer empty", p);
if ((p->tot_len - ETH_PAD_SIZE) > ENET_FRAME_MAX_FRAMELEN)
{
return ERR_BUF;
}
clen = pbuf_clen(p);
/* Check if relocation is needed */
if (clen > (ENET_TXBD_NUM - 1))
{
/* Pbuf chain is too long to be prepared for DMA at once. */
copy = true;
}
for (q = p; (q != NULL) && !copy; q = q->next)
{
/*
* Check if payload is aligned is not desired: lwIP creates RAM pbufs
* in a way that the data coming after the headers are aligned, but not
* the beginning of the ethernet header. LPC ENET DMA will read from
* the aligned address, which is ok, because there is additional space
* before the headers to make up for alignment - so DMA will not read
* from invalid address or unrelated data.
*/
/* Check payload address is usable by ENET DMA */
for (non_dma_memory = ethernetif->non_dma_memory;
(non_dma_memory->start != 0U)
|| (non_dma_memory->end != 0U); non_dma_memory++)
{
if ((q->payload >= (void *) non_dma_memory->start)
&& (q->payload < (void *) non_dma_memory->end))
{
copy = true;
break;
}
}
}
if (copy)
{
/* Pbuf needs to be copied. */
p_copy = pbuf_alloc(PBUF_RAW, (uint16_t) p->tot_len, PBUF_POOL);
if (p_copy == NULL)
{
return ERR_MEM;
}
dst = (uint8_t *) p_copy->payload;
for (q = p; q != NULL; q = q->next)
{
LWIP_ASSERT("Copied bytes would exceed p->tot_len",
(q->len + dst - (uint8_t *) p_copy->payload) <= p->tot_len);
memcpy(dst, (uint8_t *)q->payload, q->len);
dst += q->len;
}
LWIP_ASSERT("Copied bytes != p->tot_len",
(dst - (uint8_t *) p_copy->payload) == p->tot_len);
p_copy->len = p_copy->tot_len = p->tot_len;
p = p_copy;
}
else
{
/*
* Increase reference count so p is released only after it is sent.
* For copied pbuf, ref is already 1 after pbuf_alloc().
*/
pbuf_ref(p);
}
/*
* Wait until the sufficient number of descriptors are available,
* as we have to start the transfer of the first buffer only
* after all buffers in chain are prepared.
*/
while (ethernetif_avail_tx_descs(ethernetif) < clen)
{
#if !NO_SYS
xEventGroupWaitBits(ethernetif->enetTransmitAccessEvent,
ethernetif->txFlag, pdTRUE, (BaseType_t) false,
portMAX_DELAY);
#endif /* !NO_SYS */
cnt++;
if (cnt >= ENET_TIMEOUT)
{
return ERR_TIMEOUT;
}
}
#if ETH_PAD_SIZE
/* Drop the padding. */
pbuf_header(p, -ETH_PAD_SIZE);
#endif
/* Initiate transfer. */
first_idx = ethernetif->txIdx;
for (q = p; q != NULL; q = q->next)
{
enet_desc_flag flag = kENET_MiddleFlag;
pbuf_to_free = NULL;
if (q == p)
{
flag |= kENET_FirstFlagOnly;
}
if (q->next == NULL)
{
flag |= kENET_LastFlagOnly;
/* On last TX interrupt, free pbuf chain. */
pbuf_to_free = p;
}
ethernetif_send_buffer(ethernetif, q->payload, q->len, pbuf_to_free,
flag);
}
/* All pbufs from chain are prepared, allow DMA to access the first one. */
ethernetif_get_tx_desc(ethernetif, first_idx)->controlStat |=
ENET_TXDESCRIP_RD_OWN_MASK;
/* Update the transmit tail address. */
if (ethernetif->txIdx == 0U)
{
tail_address = (uint32_t)ethernetif_get_tx_desc(ethernetif,
ENET_TXBD_NUM);
}
else
{
tail_address = (uint32_t)ethernetif_get_tx_desc(ethernetif,
ethernetif->txIdx);
}
ENET_UpdateTxDescriptorTail(ethernetif->base, 0, tail_address);
MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
if (((uint8_t *)p->payload)[0] & 1)
{
/* broadcast or multicast packet */
MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
}
else
{
/* unicast packet */
MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
}
LINK_STATS_INC(link.xmit);
return ERR_OK;
}
/**
* Should be called at the beginning of the program to set up the
* first network interface. It calls the function ethernetif_init() to do the
* actual setup of the hardware.
*
* This function should be passed as a parameter to netif_add().
*
* @param netif the lwip network interface structure for this ethernetif
* @return ERR_OK if the loopif is initialized
* ERR_MEM if private data couldn't be allocated
* any other err_t on error
*/
err_t ethernetif0_init(struct netif *netif)
{
static struct ethernetif ethernetif_0;
AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rxBuffDescrip_0[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t txBuffDescrip_0[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
SDK_ALIGN(static rx_buffer_t rxDataBuff_0[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
ethernetif_0.RxBuffDescrip = &(rxBuffDescrip_0[0]);
ethernetif_0.TxBuffDescrip = &(txBuffDescrip_0[0]);
ethernetif_0.RxDataBuff = &(rxDataBuff_0[0]);
return ethernetif_init(netif, &ethernetif_0, 0U, (ethernetif_config_t *)netif->state);
}
#if defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 1)
/**
* Should be called at the beginning of the program to set up the
* second network interface. It calls the function ethernetif_init() to do the
* actual setup of the hardware.
*
* This function should be passed as a parameter to netif_add().
*
* @param netif the lwip network interface structure for this ethernetif
* @return ERR_OK if the loopif is initialized
* ERR_MEM if private data couldn't be allocated
* any other err_t on error
*/
err_t ethernetif1_init(struct netif *netif)
{
static struct ethernetif ethernetif_1;
AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rxBuffDescrip_1[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t txBuffDescrip_1[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
SDK_ALIGN(static rx_buffer_t rxDataBuff_1[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
ethernetif_1.RxBuffDescrip = &(rxBuffDescrip_1[0]);
ethernetif_1.TxBuffDescrip = &(txBuffDescrip_1[0]);
ethernetif_1.RxDataBuff = &(rxDataBuff_1[0]);
return ethernetif_init(netif, &ethernetif_1, 1U, (ethernetif_config_t *)netif->state);
}
#endif /* FSL_FEATURE_SOC_*_ENET_COUNT */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,2 @@
SRC_FILES := fsl_phy.c
include $(KERNEL_ROOT)/compiler.mk
@@ -0,0 +1,326 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file fsl_phy.c
* @brief phy drivers for ksz8081
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.11.11
*/
#include "lwipopts.h"
#include "fsl_phy.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define FSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE
/*! @brief Defines the timeout macro. */
#define PHY_TIMEOUT_COUNT 100000
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get the ENET instance from peripheral base address.
*
* @param base ENET peripheral base address.
* @return ENET instance.
*/
extern uint32_t ENET_GetInstance(ENET_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to enet clocks for each instance. */
extern clock_ip_name_t s_enetClock[FSL_FEATURE_SOC_ENET_COUNT];
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*******************************************************************************
* Code
******************************************************************************/
status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz)
{
uint32_t bssReg;
uint32_t counter = PHY_TIMEOUT_COUNT;
uint32_t idReg = 0;
status_t result = kStatus_Success;
uint32_t instance = ENET_GetInstance(base);
uint32_t timeDelay;
uint32_t ctlReg = 0;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Set SMI first. */
CLOCK_EnableClock(s_enetClock[instance]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
ENET_SetSMI(base, srcClock_Hz, false);
/* Initialization after PHY stars to work. */
while ((idReg != PHY_CONTROL_ID1) && (counter != 0))
{
PHY_Read(base, phyAddr, PHY_ID1_REG, &idReg);
counter--;
}
if (!counter)
{
return kStatus_Fail;
}
/* Reset PHY. */
counter = PHY_TIMEOUT_COUNT;
result = PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, PHY_BCTL_RESET_MASK);
if (result == kStatus_Success)
{
#if defined(FSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE)
uint32_t data = 0;
result = PHY_Read(base, phyAddr, PHY_CONTROL2_REG, &data);
if (result != kStatus_Success)
{
return result;
}
result = PHY_Write(base, phyAddr, PHY_CONTROL2_REG, (data | PHY_CTL2_REFCLK_SELECT_MASK));
if (result != kStatus_Success)
{
return result;
}
#endif /* FSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE */
/* Set the negotiation. */
result = PHY_Write(base, phyAddr, PHY_AUTONEG_ADVERTISE_REG,
(PHY_100BASETX_FULLDUPLEX_MASK | PHY_100BASETX_HALFDUPLEX_MASK |
PHY_10BASETX_FULLDUPLEX_MASK | PHY_10BASETX_HALFDUPLEX_MASK | 0x1U));
if (result == kStatus_Success)
{
result =
PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, (PHY_BCTL_AUTONEG_MASK | PHY_BCTL_RESTART_AUTONEG_MASK));
if (result == kStatus_Success)
{
/* Check auto negotiation complete. */
while (counter--)
{
result = PHY_Read(base, phyAddr, PHY_BASICSTATUS_REG, &bssReg);
if (result == kStatus_Success)
{
PHY_Read(base, phyAddr, PHY_CONTROL1_REG, &ctlReg);
if (((bssReg & PHY_BSTATUS_AUTONEGCOMP_MASK) != 0) && (ctlReg & PHY_LINK_READY_MASK))
{
/* Wait a moment for Phy status stable. */
for (timeDelay = 0; timeDelay < PHY_TIMEOUT_COUNT; timeDelay++)
{
__ASM("nop");
}
break;
}
}
if (!counter)
{
return kStatus_PHY_AutoNegotiateFail;
}
}
}
}
}
return result;
}
status_t PHY_Write(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t data)
{
uint32_t counter;
/* Clear the SMI interrupt event. */
ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
/* Starts a SMI write command. */
ENET_StartSMIWrite(base, phyAddr, phyReg, kENET_MiiWriteValidFrame, data);
/* Wait for SMI complete. */
for (counter = PHY_TIMEOUT_COUNT; counter > 0; counter--)
{
if (ENET_GetInterruptStatus(base) & ENET_EIR_MII_MASK)
{
break;
}
}
/* Check for timeout. */
if (!counter)
{
return kStatus_PHY_SMIVisitTimeout;
}
/* Clear MII interrupt event. */
ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
return kStatus_Success;
}
status_t PHY_Read(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t *dataPtr)
{
assert(dataPtr);
uint32_t counter;
/* Clear the MII interrupt event. */
ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
/* Starts a SMI read command operation. */
ENET_StartSMIRead(base, phyAddr, phyReg, kENET_MiiReadValidFrame);
/* Wait for MII complete. */
for (counter = PHY_TIMEOUT_COUNT; counter > 0; counter--)
{
if (ENET_GetInterruptStatus(base) & ENET_EIR_MII_MASK)
{
break;
}
}
/* Check for timeout. */
if (!counter)
{
return kStatus_PHY_SMIVisitTimeout;
}
/* Get data from MII register. */
*dataPtr = ENET_ReadSMIData(base);
/* Clear MII interrupt event. */
ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
return kStatus_Success;
}
status_t PHY_EnableLoopback(ENET_Type *base, uint32_t phyAddr, phy_loop_t mode, phy_speed_t speed, bool enable)
{
status_t result;
uint32_t data = 0;
/* Set the loop mode. */
if (enable)
{
if (mode == kPHY_LocalLoop)
{
if (speed == kPHY_Speed100M)
{
data = PHY_BCTL_SPEED_100M_MASK | PHY_BCTL_DUPLEX_MASK | PHY_BCTL_LOOP_MASK;
}
else
{
data = PHY_BCTL_DUPLEX_MASK | PHY_BCTL_LOOP_MASK;
}
return PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, data);
}
else
{
/* First read the current status in control register. */
result = PHY_Read(base, phyAddr, PHY_CONTROL2_REG, &data);
if (result == kStatus_Success)
{
return PHY_Write(base, phyAddr, PHY_CONTROL2_REG, (data | PHY_CTL2_REMOTELOOP_MASK));
}
}
}
else
{
/* Disable the loop mode. */
if (mode == kPHY_LocalLoop)
{
/* First read the current status in control register. */
result = PHY_Read(base, phyAddr, PHY_BASICCONTROL_REG, &data);
if (result == kStatus_Success)
{
data &= ~PHY_BCTL_LOOP_MASK;
return PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, (data | PHY_BCTL_RESTART_AUTONEG_MASK));
}
}
else
{
/* First read the current status in control one register. */
result = PHY_Read(base, phyAddr, PHY_CONTROL2_REG, &data);
if (result == kStatus_Success)
{
return PHY_Write(base, phyAddr, PHY_CONTROL2_REG, (data & ~PHY_CTL2_REMOTELOOP_MASK));
}
}
}
return result;
}
status_t PHY_GetLinkStatus(ENET_Type *base, uint32_t phyAddr, bool *status)
{
assert(status);
status_t result = kStatus_Success;
uint32_t data;
/* Read the basic status register. */
result = PHY_Read(base, phyAddr, PHY_BASICSTATUS_REG, &data);
if (result == kStatus_Success)
{
if (!(PHY_BSTATUS_LINKSTATUS_MASK & data))
{
/* link down. */
*status = false;
}
else
{
/* link up. */
*status = true;
}
}
return result;
}
status_t PHY_GetLinkSpeedDuplex(ENET_Type *base, uint32_t phyAddr, phy_speed_t *speed, phy_duplex_t *duplex)
{
assert(duplex);
status_t result = kStatus_Success;
uint32_t data, ctlReg;
/* Read the control two register. */
result = PHY_Read(base, phyAddr, PHY_CONTROL1_REG, &ctlReg);
if (result == kStatus_Success)
{
data = ctlReg & PHY_CTL1_SPEEDUPLX_MASK;
if ((PHY_CTL1_10FULLDUPLEX_MASK == data) || (PHY_CTL1_100FULLDUPLEX_MASK == data))
{
/* Full duplex. */
*duplex = kPHY_FullDuplex;
}
else
{
/* Half duplex. */
*duplex = kPHY_HalfDuplex;
}
data = ctlReg & PHY_CTL1_SPEEDUPLX_MASK;
if ((PHY_CTL1_100HALFDUPLEX_MASK == data) || (PHY_CTL1_100FULLDUPLEX_MASK == data))
{
/* 100M speed. */
*speed = kPHY_Speed100M;
}
else
{ /* 10M speed. */
*speed = kPHY_Speed10M;
}
}
return result;
}
@@ -0,0 +1,209 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file fsl_phy.h
* @brief phy drivers for ksz8081
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.11.11
*/
#ifndef _FSL_PHY_H_
#define _FSL_PHY_H_
#include "fsl_enet.h"
/*!
* @addtogroup phy_driver
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief PHY driver version */
#define FSL_PHY_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0. */
/*! @brief Defines the PHY registers. */
#define PHY_BASICCONTROL_REG 0x00U /*!< The PHY basic control register. */
#define PHY_BASICSTATUS_REG 0x01U /*!< The PHY basic status register. */
#define PHY_ID1_REG 0x02U /*!< The PHY ID one register. */
#define PHY_ID2_REG 0x03U /*!< The PHY ID two register. */
#define PHY_AUTONEG_ADVERTISE_REG 0x04U /*!< The PHY auto-negotiate advertise register. */
#define PHY_CONTROL1_REG 0x1EU /*!< The PHY control one register. */
#define PHY_CONTROL2_REG 0x1FU /*!< The PHY control two register. */
#define PHY_CONTROL_ID1 0x22U /*!< The PHY ID1*/
/*! @brief Defines the mask flag in basic control register. */
#define PHY_BCTL_DUPLEX_MASK 0x0100U /*!< The PHY duplex bit mask. */
#define PHY_BCTL_RESTART_AUTONEG_MASK 0x0200U /*!< The PHY restart auto negotiation mask. */
#define PHY_BCTL_AUTONEG_MASK 0x1000U /*!< The PHY auto negotiation bit mask. */
#define PHY_BCTL_SPEED_MASK 0x2000U /*!< The PHY speed bit mask. */
#define PHY_BCTL_LOOP_MASK 0x4000U /*!< The PHY loop bit mask. */
#define PHY_BCTL_RESET_MASK 0x8000U /*!< The PHY reset bit mask. */
#define PHY_BCTL_SPEED_100M_MASK 0x2000U /*!< The PHY 100M speed mask. */
/*!@brief Defines the mask flag of operation mode in control two register*/
#define PHY_CTL2_REMOTELOOP_MASK 0x0004U /*!< The PHY remote loopback mask. */
#define PHY_CTL2_REFCLK_SELECT_MASK 0x0080U /*!< The PHY RMII reference clock select. */
#define PHY_CTL1_10HALFDUPLEX_MASK 0x0001U /*!< The PHY 10M half duplex mask. */
#define PHY_CTL1_100HALFDUPLEX_MASK 0x0002U /*!< The PHY 100M half duplex mask. */
#define PHY_CTL1_10FULLDUPLEX_MASK 0x0005U /*!< The PHY 10M full duplex mask. */
#define PHY_CTL1_100FULLDUPLEX_MASK 0x0006U /*!< The PHY 100M full duplex mask. */
#define PHY_CTL1_SPEEDUPLX_MASK 0x0007U /*!< The PHY speed and duplex mask. */
#define PHY_CTL1_ENERGYDETECT_MASK 0x10U /*!< The PHY signal present on rx differential pair. */
#define PHY_CTL1_LINKUP_MASK 0x100U /*!< The PHY link up. */
#define PHY_LINK_READY_MASK (PHY_CTL1_ENERGYDETECT_MASK | PHY_CTL1_LINKUP_MASK)
/*! @brief Defines the mask flag in basic status register. */
#define PHY_BSTATUS_LINKSTATUS_MASK 0x0004U /*!< The PHY link status mask. */
#define PHY_BSTATUS_AUTONEGABLE_MASK 0x0008U /*!< The PHY auto-negotiation ability mask. */
#define PHY_BSTATUS_AUTONEGCOMP_MASK 0x0020U /*!< The PHY auto-negotiation complete mask. */
/*! @brief Defines the mask flag in PHY auto-negotiation advertise register. */
#define PHY_100BaseT4_ABILITY_MASK 0x200U /*!< The PHY have the T4 ability. */
#define PHY_100BASETX_FULLDUPLEX_MASK 0x100U /*!< The PHY has the 100M full duplex ability.*/
#define PHY_100BASETX_HALFDUPLEX_MASK 0x080U /*!< The PHY has the 100M full duplex ability.*/
#define PHY_10BASETX_FULLDUPLEX_MASK 0x040U /*!< The PHY has the 10M full duplex ability.*/
#define PHY_10BASETX_HALFDUPLEX_MASK 0x020U /*!< The PHY has the 10M full duplex ability.*/
/*! @brief Defines the PHY status. */
enum _phy_status
{
kStatus_PHY_SMIVisitTimeout = MAKE_STATUS(kStatusGroup_PHY, 1), /*!< ENET PHY SMI visit timeout. */
kStatus_PHY_AutoNegotiateFail = MAKE_STATUS(kStatusGroup_PHY, 2) /*!< ENET PHY AutoNegotiate Fail. */
};
/*! @brief Defines the PHY link speed. This is align with the speed for ENET MAC. */
typedef enum _phy_speed
{
kPHY_Speed10M = 0U, /*!< ENET PHY 10M speed. */
kPHY_Speed100M /*!< ENET PHY 100M speed. */
} phy_speed_t;
/*! @brief Defines the PHY link duplex. */
typedef enum _phy_duplex
{
kPHY_HalfDuplex = 0U, /*!< ENET PHY half duplex. */
kPHY_FullDuplex /*!< ENET PHY full duplex. */
} phy_duplex_t;
/*! @brief Defines the PHY loopback mode. */
typedef enum _phy_loop
{
kPHY_LocalLoop = 0U, /*!< ENET PHY local loopback. */
kPHY_RemoteLoop /*!< ENET PHY remote loopback. */
} phy_loop_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name PHY Driver
* @{
*/
/*!
* @brief Initializes PHY.
*
* This function initialize the SMI interface and initialize PHY.
* The SMI is the MII management interface between PHY and MAC, which should be
* firstly initialized before any other operation for PHY. The PHY initialize with auto-negotiation.
*
* @param base ENET peripheral base address.
* @param phyAddr The PHY address.
* @param srcClock_Hz The module clock frequency - system clock for MII management interface - SMI.
* @retval kStatus_Success PHY initialize success
* @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out
* @retval kStatus_PHY_AutoNegotiateFail PHY auto negotiate fail
*/
status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz);
/*!
* @brief PHY Write function. This function write data over the SMI to
* the specified PHY register. This function is called by all PHY interfaces.
*
* @param base ENET peripheral base address.
* @param phyAddr The PHY address.
* @param phyReg The PHY register.
* @param data The data written to the PHY register.
* @retval kStatus_Success PHY write success
* @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out
*/
status_t PHY_Write(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t data);
/*!
* @brief PHY Read function. This interface read data over the SMI from the
* specified PHY register. This function is called by all PHY interfaces.
*
* @param base ENET peripheral base address.
* @param phyAddr The PHY address.
* @param phyReg The PHY register.
* @param dataPtr The address to store the data read from the PHY register.
* @retval kStatus_Success PHY read success
* @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out
*/
status_t PHY_Read(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t *dataPtr);
/*!
* @brief Enables/disables PHY loopback.
*
* @param base ENET peripheral base address.
* @param phyAddr The PHY address.
* @param mode The loopback mode to be enabled, please see "phy_loop_t".
* the two loopback mode should not be both set. when one loopback mode is set
* the other one should be disabled.
* @param speed PHY speed for loopback mode.
* @param enable True to enable, false to disable.
* @retval kStatus_Success PHY loopback success
* @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out
*/
status_t PHY_EnableLoopback(ENET_Type *base, uint32_t phyAddr, phy_loop_t mode, phy_speed_t speed, bool enable);
/*!
* @brief Gets the PHY link status.
*
* @param base ENET peripheral base address.
* @param phyAddr The PHY address.
* @param status The link up or down status of the PHY.
* - true the link is up.
* - false the link is down.
* @retval kStatus_Success PHY get link status success
* @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out
*/
status_t PHY_GetLinkStatus(ENET_Type *base, uint32_t phyAddr, bool *status);
/*!
* @brief Gets the PHY link speed and duplex.
*
* @param base ENET peripheral base address.
* @param phyAddr The PHY address.
* @param speed The address of PHY link speed.
* @param duplex The link duplex of PHY.
* @retval kStatus_Success PHY get link speed and duplex success
* @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out
*/
status_t PHY_GetLinkSpeedDuplex(ENET_Type *base, uint32_t phyAddr, phy_speed_t *speed, phy_duplex_t *duplex);
/* @} */
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_PHY_H_ */
@@ -0,0 +1,12 @@
config PIN_BUS_NAME
string "pin bus name"
default "pin"
config PIN_DRIVER_NAME
string "pin driver name"
default "pin_drv"
config PIN_DEVICE_NAME
string "pin device name"
default "pin_dev"
@@ -0,0 +1,3 @@
SRC_FILES := connect_gpio.c fsl_gpio.c
include $(KERNEL_ROOT)/compiler.mk
@@ -0,0 +1,779 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-4-30 misonyo the first version.
*/
/**
* @file connect_gpio.c
* @brief support gpio function using bus driver framework
* @version 2.0
* @author AIIT XUOS Lab
* @date 2022-03-22
*/
/*************************************************
File name: connect_gpio.c
Description: support gpio configure and register to bus framework
Others: take RT-Thread v4.0.2/bsp/imxrt/libraries/drivers/drv_gpio.c for references
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
History:
1. Date: 2022-03-22
Author: AIIT XUOS Lab
Modification: add bus driver framework support for gpio
*************************************************/
#include <connect_gpio.h>
#include <fsl_gpio.h>
#include <fsl_iomuxc.h>
struct PinIndex
{
int index;
GPIO_Type *gpio;
uint32_t pin;
};
struct PinIrq
{
uint8 port_source;
uint8 pin_source;
enum IRQn irq_exti_channel;
uint32 exti_line;
};
struct PinMask
{
GPIO_Type *gpio;
uint32 valid_mask;
};
static const IRQn_Type irq_tab[10] =
{
GPIO1_Combined_0_15_IRQn,
GPIO1_Combined_16_31_IRQn,
GPIO2_Combined_0_15_IRQn,
GPIO2_Combined_16_31_IRQn,
GPIO3_Combined_0_15_IRQn,
GPIO3_Combined_16_31_IRQn,
GPIO4_Combined_0_15_IRQn,
GPIO4_Combined_16_31_IRQn,
GPIO5_Combined_0_15_IRQn,
GPIO5_Combined_16_31_IRQn
};
const struct PinMask pin_mask[] =
{
{GPIO1, 0xFFFFFFFF}, /* GPIO1 */
{GPIO2, 0xFFFFFFFF}, /* GPIO2 */
{GPIO3, 0x0FFFFFFF}, /* GPIO3,28~31 not supported */
{GPIO4, 0xFFFFFFFF}, /* GPIO4 */
{GPIO5, 0x00000007} /* GPIO5,3~31 not supported */
};
struct PinIrqHdr pin_irq_hdr_tab[] =
{
/* GPIO1 */
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
/* GPIO2 */
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
/* GPIO3 */
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
/* GPIO4 */
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
/* GPIO5 */
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
{-1, 0, NONE, NONE},
};
#define MUX_BASE 0x401f8014
#define CONFIG_BASE 0x401f8204
#define GPIO5_MUX_BASE 0x400A8000
#define GPIO5_CONFIG_BASE 0x400A8018
const uint8_t reg_offset[] =
{
42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,
112,113,114,115,116,117,118,119,120,121,122,123,106,107,108,109,110,111, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, -1, -1, -1, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
};
static int GetPin(struct PinIndex *pin_index, uint8_t pin)
{
pin_index->index = pin >> 5;//0:GPIO1 1:GPIO2 2:GPIO3 3:GPIO4 4:GPIO5
pin_index->pin = pin & 31;//each GPIOx support 32 io
if ((pin_index->index > 4) || ((pin_mask[pin_index->index].valid_mask & (1 << pin_index->pin)) == 0)) {
KPrintf("GetPin unsupport pin index %u pin %u\n", pin_index->index, pin_index->pin);
return -1;
}
pin_index->gpio = pin_mask[pin_index->index].gpio;
return 0;
}
static int32 GpioConfigMode(int mode, struct PinIndex *pin_index, int32 pin)
{
gpio_pin_config_t gpio_config;
uint32_t config_value = 0;
NULL_PARAM_CHECK(pin_index);
gpio_config.outputLogic = 0;
gpio_config.interruptMode = kGPIO_NoIntmode;
switch (mode)
{
case GPIO_CFG_OUTPUT:
gpio_config.direction = kGPIO_DigitalOutput;
config_value = 0x0030U; /* Drive Strength R0/6 */
break;
case GPIO_CFG_INPUT:
gpio_config.direction = kGPIO_DigitalInput;
config_value = 0x0830U; /* Open Drain Enable */
break;
case GPIO_CFG_INPUT_PULLUP:
gpio_config.direction = kGPIO_DigitalInput;
config_value = 0xB030U; /* 100K Ohm Pull Up */
break;
case GPIO_CFG_INPUT_PULLDOWN:
gpio_config.direction = kGPIO_DigitalInput;
config_value = 0x3030U; /* 100K Ohm Pull Down */
break;
case GPIO_CFG_OUTPUT_OD:
gpio_config.direction = kGPIO_DigitalOutput;
config_value = 0x0830U; /* Open Drain Enable */
break;
default:
break;
}
if (pin_mask[pin_index->index].gpio != GPIO5) {
CLOCK_EnableClock(kCLOCK_Iomuxc);
IOMUXC_SetPinMux(MUX_BASE + reg_offset[pin] * 4, 0x5U, 0, 0, CONFIG_BASE + reg_offset[pin] * 4, 1);
IOMUXC_SetPinConfig(MUX_BASE + reg_offset[pin] * 4, 0x5U, 0, 0, CONFIG_BASE + reg_offset[pin] * 4, config_value);
} else {
CLOCK_EnableClock(kCLOCK_IomuxcSnvs);
IOMUXC_SetPinMux(GPIO5_MUX_BASE + pin_index->pin * 4, 0x5U, 0, 0, GPIO5_CONFIG_BASE + pin_index->pin * 4, 1);
IOMUXC_SetPinConfig(GPIO5_MUX_BASE + pin_index->pin * 4, 0x5U, 0, 0, GPIO5_CONFIG_BASE + pin_index->pin * 4, config_value);
}
GPIO_PinInit(pin_index->gpio, pin_index->pin, &gpio_config);
return EOK;
}
static int32 GpioIrqRegister(int32 pin, int32 mode, void (*hdr)(void *args), void *args)
{
struct PinIndex pin_index;
if (GetPin(&pin_index, pin) < 0) {
return ERROR;
}
x_base level = CriticalAreaLock();
if (pin_irq_hdr_tab[pin].pin == pin &&
pin_irq_hdr_tab[pin].hdr == hdr &&
pin_irq_hdr_tab[pin].mode == mode &&
pin_irq_hdr_tab[pin].args == args
)
{
CriticalAreaUnLock(level);
return EOK;
}
if (pin_irq_hdr_tab[pin].pin != -1) {
CriticalAreaUnLock(level);
return -EDEV_BUSY;
}
pin_irq_hdr_tab[pin].pin = pin;
pin_irq_hdr_tab[pin].hdr = hdr;
pin_irq_hdr_tab[pin].mode = mode;
pin_irq_hdr_tab[pin].args = args;
CriticalAreaUnLock(level);
return EOK;
}
static uint32 GpioIrqFree(int32 pin)
{
struct PinIndex pin_index;
if (GetPin(&pin_index, pin) < 0) {
return ERROR;
}
x_base level = CriticalAreaLock();
if (pin_irq_hdr_tab[pin].pin == -1){
CriticalAreaUnLock(level);
return EOK;
}
pin_irq_hdr_tab[pin].pin = -1;
pin_irq_hdr_tab[pin].hdr = NONE;
pin_irq_hdr_tab[pin].mode = 0;
pin_irq_hdr_tab[pin].args = NONE;
CriticalAreaUnLock(level);
return EOK;
}
static int32 GpioIrqEnable(x_base pin)
{
uint8_t irq_index;
gpio_interrupt_mode_t gpio_int_mode;
struct PinIndex pin_index;
if (GetPin(&pin_index, pin) < 0) {
return ERROR;
}
x_base level = CriticalAreaLock();
if (pin_irq_hdr_tab[pin].pin == -1) {
CriticalAreaUnLock(level);
return -ENONESYS;
}
switch (pin_irq_hdr_tab[pin].mode)
{
case GPIO_IRQ_EDGE_RISING:
gpio_int_mode = kGPIO_IntRisingEdge;
break;
case GPIO_IRQ_EDGE_FALLING:
gpio_int_mode = kGPIO_IntFallingEdge;
break;
case GPIO_IRQ_EDGE_BOTH:
gpio_int_mode = kGPIO_IntRisingOrFallingEdge;
break;
case GPIO_IRQ_LEVEL_HIGH:
gpio_int_mode = kGPIO_IntHighLevel;
break;
case GPIO_IRQ_LEVEL_LOW:
gpio_int_mode = kGPIO_IntLowLevel;
break;
default:
gpio_int_mode = kGPIO_IntRisingEdge;
break;
}
irq_index = (pin_index.index << 1) + (pin_index.pin >> 4);
GPIO_PinSetInterruptConfig(pin_index.gpio, pin_index.pin, gpio_int_mode);
GPIO_PortEnableInterrupts(pin_index.gpio, 1U << pin_index.pin);
NVIC_SetPriority(irq_tab[irq_index], NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
EnableIRQ(irq_tab[irq_index]);
CriticalAreaUnLock(level);
return EOK;
}
static int32 GpioIrqDisable(x_base pin)
{
struct PinIndex pin_index;
if (GetPin(&pin_index, pin) < 0) {
return ERROR;
}
GPIO_PortDisableInterrupts(pin_index.gpio, 1U << pin_index.pin);
return EOK;
}
static uint32 Imxrt1052PinConfigure(struct PinParam *param)
{
NULL_PARAM_CHECK(param);
int ret = EOK;
struct PinIndex pin_index;
if (GetPin(&pin_index, param->pin) < 0) {
return ERROR;
}
switch(param->cmd)
{
case GPIO_CONFIG_MODE:
GpioConfigMode(param->mode, &pin_index, param->pin);
break;
case GPIO_IRQ_REGISTER:
ret = GpioIrqRegister(param->pin, param->irq_set.irq_mode, param->irq_set.hdr, param->irq_set.args);
break;
case GPIO_IRQ_FREE:
ret = GpioIrqFree(param->pin);
break;
case GPIO_IRQ_ENABLE:
ret = GpioIrqEnable(param->pin);
break;
case GPIO_IRQ_DISABLE:
ret = GpioIrqDisable(param->pin);
break;
default:
ret = -EINVALED;
break;
}
return ret;
}
static uint32 Imxrt1052PinInit(void)
{
static x_bool pin_init_flag = RET_FALSE;
if (!pin_init_flag) {
pin_init_flag = RET_TRUE;
}
return EOK;
}
static uint32 Imxrt1052GpioDrvConfigure(void *drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(drv);
NULL_PARAM_CHECK(configure_info);
x_err_t ret = EOK;
struct PinParam *param;
switch (configure_info->configure_cmd)
{
case OPE_INT:
ret = Imxrt1052PinInit();
break;
case OPE_CFG:
param = (struct PinParam *)configure_info->private_data;
ret = Imxrt1052PinConfigure(param);
break;
default:
break;
}
return ret;
}
uint32 Imxrt1052PinWrite(void *dev, struct BusBlockWriteParam *write_param)
{
NULL_PARAM_CHECK(dev);
NULL_PARAM_CHECK(write_param);
struct PinStat *pin_stat = (struct PinStat *)write_param->buffer;
struct PinIndex pin_index;
if (GetPin(&pin_index, pin_stat->pin) < 0) {
return ERROR;
}
if (GPIO_LOW == pin_stat->val) {
GPIO_PinWrite(pin_index.gpio, pin_index.pin, 0);
} else {
GPIO_PinWrite(pin_index.gpio, pin_index.pin, 1);
}
return EOK;
}
uint32 Imxrt1052PinRead(void *dev, struct BusBlockReadParam *read_param)
{
NULL_PARAM_CHECK(dev);
NULL_PARAM_CHECK(read_param);
struct PinStat *pin_stat = (struct PinStat *)read_param->buffer;
struct PinIndex pin_index;
if (GetPin(&pin_index, pin_stat->pin) < 0) {
return ERROR;
}
if(GPIO_LOW == GPIO_PinRead(pin_index.gpio, pin_index.pin)) {
pin_stat->val = GPIO_LOW;
} else {
pin_stat->val = GPIO_HIGH;
}
return pin_stat->val;
}
static const struct PinDevDone dev_done =
{
.open = NONE,
.close = NONE,
.write = Imxrt1052PinWrite,
.read = Imxrt1052PinRead,
};
int Imxrt1052HwGpioInit(void)
{
x_err_t ret = EOK;
static struct PinBus pin;
ret = PinBusInit(&pin, PIN_BUS_NAME);
if (ret != EOK) {
KPrintf("gpio bus init error %d\n", ret);
return ERROR;
}
static struct PinDriver drv;
drv.configure = Imxrt1052GpioDrvConfigure;
ret = PinDriverInit(&drv, PIN_DRIVER_NAME, NONE);
if (ret != EOK) {
KPrintf("pin driver init error %d\n", ret);
return ERROR;
}
ret = PinDriverAttachToBus(PIN_DRIVER_NAME, PIN_BUS_NAME);
if (ret != EOK) {
KPrintf("pin driver attach error %d\n", ret);
return ERROR;
}
static struct PinHardwareDevice dev;
dev.dev_done = &dev_done;
ret = PinDeviceRegister(&dev, NONE, PIN_DEVICE_NAME);
if (ret != EOK) {
KPrintf("pin device register error %d\n", ret);
return ERROR;
}
ret = PinDeviceAttachToBus(PIN_DEVICE_NAME, PIN_BUS_NAME);
if (ret != EOK) {
KPrintf("pin device register error %d\n", ret);
return ERROR;
}
return ret;
}
static __inline void PinIrqHdr(uint32_t index_offset, uint8_t pin_start, GPIO_Type *gpio)
{
int i;
uint32_t isr_status, pin;
struct PinIndex pin_index;
isr_status = GPIO_PortGetInterruptFlags(gpio) & gpio->IMR;
for (i = pin_start; i <= pin_start + 15 ; i ++) {
if (GetPin(&pin_index, i + index_offset) < 0) {
continue;
}
if (isr_status & (1 << i)) {
GPIO_PortClearInterruptFlags(gpio, (1 << i));
__DSB();
pin = index_offset + i;
if (pin_irq_hdr_tab[pin].hdr) {
pin_irq_hdr_tab[pin].hdr(pin_irq_hdr_tab[pin].args);
}
}
}
}
void GPIO1_0_15_IRQHandler(int irq_num, void *arg)
{
x_base lock = 0;
lock = DISABLE_INTERRUPT();
PinIrqHdr(0, 0, GPIO1);
ENABLE_INTERRUPT(lock);
}
DECLARE_HW_IRQ(GPIO1_Combined_0_15_IRQn, GPIO1_0_15_IRQHandler, NONE);
void GPIO1_16_31_IRQHandler(int irq_num, void *arg)
{
x_base lock = 0;
lock = DISABLE_INTERRUPT();
PinIrqHdr(0, 15, GPIO1);
ENABLE_INTERRUPT(lock);
}
DECLARE_HW_IRQ(GPIO1_Combined_16_31_IRQn, GPIO1_16_31_IRQHandler, NONE);
void GPIO2_0_15_IRQHandler(int irq_num, void *arg)
{
x_base lock = 0;
lock = DISABLE_INTERRUPT();
PinIrqHdr(32, 0, GPIO2);
ENABLE_INTERRUPT(lock);
}
DECLARE_HW_IRQ(GPIO2_Combined_0_15_IRQn, GPIO2_0_15_IRQHandler, NONE);
void GPIO2_16_31_IRQHandler(int irq_num, void *arg)
{
x_base lock = 0;
lock = DISABLE_INTERRUPT();
PinIrqHdr(32, 15, GPIO2);
ENABLE_INTERRUPT(lock);
}
DECLARE_HW_IRQ(GPIO2_Combined_16_31_IRQn, GPIO2_16_31_IRQHandler, NONE);
void GPIO3_0_15_IRQHandler(int irq_num, void *arg)
{
x_base lock = 0;
lock = DISABLE_INTERRUPT();
PinIrqHdr(64, 0, GPIO3);
ENABLE_INTERRUPT(lock);
}
DECLARE_HW_IRQ(GPIO3_Combined_0_15_IRQn, GPIO3_0_15_IRQHandler, NONE);
void GPIO3_16_31_IRQHandler(int irq_num, void *arg)
{
x_base lock = 0;
lock = DISABLE_INTERRUPT();
PinIrqHdr(64, 15, GPIO3);
ENABLE_INTERRUPT(lock);
}
DECLARE_HW_IRQ(GPIO3_Combined_16_31_IRQn, GPIO3_16_31_IRQHandler, NONE);
void GPIO4_0_15_IRQHandler(int irq_num, void *arg)
{
x_base lock = 0;
lock = DISABLE_INTERRUPT();
PinIrqHdr(96, 0, GPIO4);
ENABLE_INTERRUPT(lock);
}
DECLARE_HW_IRQ(GPIO4_Combined_0_15_IRQn, GPIO4_0_15_IRQHandler, NONE);
void GPIO4_16_31_IRQHandler(int irq_num, void *arg)
{
x_base lock = 0;
lock = DISABLE_INTERRUPT();
PinIrqHdr(96, 15, GPIO4);
ENABLE_INTERRUPT(lock);
}
DECLARE_HW_IRQ(GPIO4_Combined_16_31_IRQn, GPIO4_16_31_IRQHandler, NONE);
void GPIO5_0_15_IRQHandler(int irq_num, void *arg)
{
x_base lock = 0;
lock = DISABLE_INTERRUPT();
PinIrqHdr(128, 0, GPIO5);
ENABLE_INTERRUPT(lock);
}
DECLARE_HW_IRQ(GPIO5_Combined_0_15_IRQn, GPIO5_0_15_IRQHandler, NONE);
void GPIO5_16_31_IRQHandler(int irq_num, void *arg)
{
x_base lock = 0;
lock = DISABLE_INTERRUPT();
PinIrqHdr(128, 15, GPIO5);
ENABLE_INTERRUPT(lock);
}
DECLARE_HW_IRQ(GPIO5_Combined_16_31_IRQn, GPIO5_16_31_IRQHandler, NONE);
#ifdef GPIO_LED_TEST
static void GpioLedDelay(void)
{
volatile uint32_t i = 0;
for (i = 0; i < 8000000; ++i)
{
__asm("NOP"); /* delay */
}
}
void GpioLedTest(void)
{
BusType pin;
struct BusConfigureInfo configure_info;
struct BusBlockWriteParam write_param;
int ret = 0;
bool pinSet = 1;
pin = BusFind(PIN_BUS_NAME);
if (!pin) {
KPrintf("find %s failed!\n", PIN_BUS_NAME);
return;
}
pin->owner_driver = BusFindDriver(pin, PIN_DRIVER_NAME);
pin->owner_haldev = BusFindDevice(pin, PIN_DEVICE_NAME);
configure_info.configure_cmd = OPE_INT;
ret = BusDrvConfigure(pin->owner_driver, &configure_info);
if (ret != EOK) {
KPrintf("initialize %s failed!\n", PIN_BUS_NAME);
return;
}
struct PinParam led_gpio_param;
struct PinStat led_gpio_stat;
/* config led pin as output*/
led_gpio_param.cmd = GPIO_CONFIG_MODE;
led_gpio_param.pin = IMXRT_GET_PIN(1, 9);
led_gpio_param.mode = GPIO_CFG_OUTPUT_OD;
configure_info.configure_cmd = OPE_CFG;
configure_info.private_data = (void *)&led_gpio_param;
ret = BusDrvConfigure(pin->owner_driver, &configure_info);
if (ret != EOK) {
KPrintf("config pin %d failed!\n", IMXRT_GET_PIN(1, 9));
return;
}
while (1) {
GpioLedDelay();
if (pinSet) {
/* set led pin as high*/
led_gpio_stat.pin = IMXRT_GET_PIN(1, 9);
led_gpio_stat.val = GPIO_HIGH;
write_param.buffer = (void *)&led_gpio_stat;
BusDevWriteData(pin->owner_haldev, &write_param);
pinSet = 0;
} else {
/* set led pin as low*/
led_gpio_stat.pin = IMXRT_GET_PIN(1, 9);
led_gpio_stat.val = GPIO_LOW;
write_param.buffer = (void *)&led_gpio_stat;
BusDevWriteData(pin->owner_haldev, &write_param);
pinSet = 1;
}
}
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
GpioLedTest, GpioLedTest, GpioLedTest GPIO1 IO09 LED);
#endif
@@ -0,0 +1,171 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_gpio.h"
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.igpio"
#endif
/*******************************************************************************
* Variables
******************************************************************************/
/* Array of GPIO peripheral base address. */
static GPIO_Type *const s_gpioBases[] = GPIO_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Array of GPIO clock name. */
static const clock_ip_name_t s_gpioClock[] = GPIO_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Gets the GPIO instance according to the GPIO base
*
* @param base GPIO peripheral base pointer(PTA, PTB, PTC, etc.)
* @retval GPIO instance
*/
static uint32_t GPIO_GetInstance(GPIO_Type *base);
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t GPIO_GetInstance(GPIO_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_gpioBases); instance++)
{
if (s_gpioBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_gpioBases));
return instance;
}
/*!
* brief Initializes the GPIO peripheral according to the specified
* parameters in the initConfig.
*
* param base GPIO base pointer.
* param pin Specifies the pin number
* param initConfig pointer to a ref gpio_pin_config_t structure that
* contains the configuration information.
*/
void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *Config)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable GPIO clock. */
uint32_t instance = GPIO_GetInstance(base);
/* If The clock IP is valid, enable the clock gate. */
if ((instance < ARRAY_SIZE(s_gpioClock)) && (kCLOCK_IpInvalid != s_gpioClock[instance]))
{
CLOCK_EnableClock(s_gpioClock[instance]);
}
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/* Register reset to default value */
base->IMR &= ~(1U << pin);
/* Configure GPIO pin direction */
if (Config->direction == kGPIO_DigitalInput)
{
base->GDIR &= ~(1U << pin);
}
else
{
GPIO_PinWrite(base, pin, Config->outputLogic);
base->GDIR |= (1U << pin);
}
/* Configure GPIO pin interrupt mode */
GPIO_SetPinInterruptConfig(base, pin, Config->interruptMode);
}
/*!
* brief Sets the output level of the individual GPIO pin to logic 1 or 0.
*
* param base GPIO base pointer.
* param pin GPIO port pin number.
* param output GPIOpin output logic level.
* - 0: corresponding pin output low-logic level.
* - 1: corresponding pin output high-logic level.
*/
void GPIO_PinWrite(GPIO_Type *base, uint32_t pin, uint8_t output)
{
assert(pin < 32);
if (output == 0U)
{
base->DR &= ~(1U << pin); /* Set pin output to low level.*/
}
else
{
base->DR |= (1U << pin); /* Set pin output to high level.*/
}
}
/*!
* brief Sets the current pin interrupt mode.
*
* param base GPIO base pointer.
* param pin GPIO port pin number.
* param pininterruptMode pointer to a ref gpio_interrupt_mode_t structure
* that contains the interrupt mode information.
*/
void GPIO_PinSetInterruptConfig(GPIO_Type *base, uint32_t pin, gpio_interrupt_mode_t pinInterruptMode)
{
volatile uint32_t *icr;
uint32_t icrShift;
icrShift = pin;
/* Register reset to default value */
base->EDGE_SEL &= ~(1U << pin);
if (pin < 16)
{
icr = &(base->ICR1);
}
else
{
icr = &(base->ICR2);
icrShift -= 16;
}
switch (pinInterruptMode)
{
case (kGPIO_IntLowLevel):
*icr &= ~(3U << (2 * icrShift));
break;
case (kGPIO_IntHighLevel):
*icr = (*icr & (~(3U << (2 * icrShift)))) | (1U << (2 * icrShift));
break;
case (kGPIO_IntRisingEdge):
*icr = (*icr & (~(3U << (2 * icrShift)))) | (2U << (2 * icrShift));
break;
case (kGPIO_IntFallingEdge):
*icr |= (3U << (2 * icrShift));
break;
case (kGPIO_IntRisingOrFallingEdge):
base->EDGE_SEL |= (1U << pin);
break;
default:
break;
}
}
@@ -0,0 +1,12 @@
if BSP_USING_I2C
config I2C_BUS_NAME_1
string "i2c bus 1 name"
default "i2c1"
config I2C_DRV_NAME_1
string "i2c bus 1 driver name"
default "i2c1_drv"
config I2C_1_DEVICE_NAME_0
string "i2c bus 1 device 0 name"
default "i2c1_dev0"
endif
@@ -0,0 +1,3 @@
SRC_FILES := connect_i2c.c connect_i2c_eeprom.c hardware_i2c.c fsl_lpi2c.c
include $(KERNEL_ROOT)/compiler.mk
@@ -0,0 +1,179 @@
/*
* Copyright (c) 2022 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_i2c.c
* @brief support ok1052-c board i2c function and register to bus framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-03-01
*/
#include <board.h>
#include "bus_serial.h"
#include "connect_i2c.h"
#include "fsl_lpi2c.h"
static uint32 I2cWriteData(struct I2cHardwareDevice *i2c_dev, struct I2cDataStandard *msg)
{
status_t ret;
Stm32I2cType *param = (Stm32I2cType *)i2c_dev->haldev.private_data;
ret = I2cHardwareWrite(param->base, param->slave_addr, param->sub_addr, msg->buf, msg->len);
if(kStatus_Success == ret)
return 1;
return 0;
}
static uint32 I2cReadData(struct I2cHardwareDevice *i2c_dev, struct I2cDataStandard *msg)
{
status_t ret;
Stm32I2cType *param = (Stm32I2cType *)i2c_dev->haldev.private_data;
ret = I2cHardwareRead(param->base, i2c_dev->i2c_dev_addr, param->sub_addr, msg->buf, msg->len);
if(kStatus_Success == ret)
return 1;
return 0;
}
static uint32 I2cInit(struct I2cDriver *i2c_drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(i2c_drv);
struct I2cHardwareDevice *i2c_dev = (struct I2cHardwareDevice *)i2c_drv->driver.owner_bus->owner_haldev;
if (configure_info->private_data) {
i2c_dev->i2c_dev_addr = *((uint16 *)configure_info->private_data);
return EOK;
}
i2c_print("I2cInit need set i2c dev addr\n");
return ERROR;
}
static uint32 I2cDrvConfigure(void *drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(drv);
NULL_PARAM_CHECK(configure_info);
x_err_t ret = EOK;
struct I2cDriver *i2c_drv = (struct I2cDriver *)drv;
switch (configure_info->configure_cmd)
{
case OPE_INT:
ret = I2cInit(i2c_drv, configure_info);
break;
default:
break;
}
return ret;
}
/*manage the i2c device operations*/
static const struct I2cDevDone i2c_dev_done =
{
.dev_open = NONE,
.dev_close = NONE,
.dev_write = I2cWriteData,
.dev_read = I2cReadData,
};
/*Init i2c bus*/
static int BoardI2cBusInit(struct I2cBus *i2c_bus, struct I2cDriver *i2c_driver)
{
x_err_t ret = EOK;
/*Init the i2c bus */
i2c_bus->private_data = (void *)NULL;
ret = I2cBusInit(i2c_bus, I2C_BUS_NAME_1);
if (EOK != ret) {
i2c_print("BoardI2cBusInit I2cBusInit error %d\n", ret);
return ERROR;
}
/*Init the i2c driver*/
i2c_driver->private_data = (void *)NULL;
ret = I2cDriverInit(i2c_driver, I2C_DRV_NAME_1);
if (EOK != ret) {
i2c_print("BoardI2cBusInit I2cDriverInit error %d\n", ret);
return ERROR;
}
/*Attach the i2c driver to the i2c bus*/
ret = I2cDriverAttachToBus(I2C_DRV_NAME_1, I2C_BUS_NAME_1);
if (EOK != ret) {
i2c_print("BoardI2cBusInit I2cDriverAttachToBus error %d\n", ret);
return ERROR;
}
return ret;
}
/*Attach the i2c device to the i2c bus*/
static int BoardI2cDevBend(void)
{
x_err_t ret = EOK;
static struct I2cHardwareDevice i2c_device0;
memset(&i2c_device0, 0, sizeof(struct I2cHardwareDevice));
i2c_device0.i2c_dev_done = &i2c_dev_done;
ret = I2cDeviceRegister(&i2c_device0, NONE, I2C_1_DEVICE_NAME_0);
if (EOK != ret) {
i2c_print("BoardI2cDevBend I2cDeviceInit device %s error %d\n", I2C_1_DEVICE_NAME_0, ret);
return ERROR;
}
ret = I2cDeviceAttachToBus(I2C_1_DEVICE_NAME_0, I2C_BUS_NAME_1);
if (EOK != ret) {
i2c_print("BoardI2cDevBend I2cDeviceAttachToBus device %s error %d\n", I2C_1_DEVICE_NAME_0, ret);
return ERROR;
}
return ret;
}
/*BOARD I2C INIT*/
int Imxrt1052HwI2cInit(void)
{
static int init_flag = 0;
x_err_t ret = EOK;
if(init_flag)
{
return ret;
}
init_flag = 1;
static struct I2cBus i2c_bus;
memset(&i2c_bus, 0, sizeof(struct I2cBus));
static struct I2cDriver i2c_driver;
memset(&i2c_driver, 0, sizeof(struct I2cDriver));
#ifdef BSP_USING_I2C
i2c_driver.configure = I2cDrvConfigure;
ret = BoardI2cBusInit(&i2c_bus, &i2c_driver);
if (EOK != ret) {
i2c_print("board_i2c_Init error ret %u\n", ret);
return ERROR;
}
ret = BoardI2cDevBend();
if (EOK != ret) {
i2c_print("board_i2c_Init error ret %u\n", ret);
return ERROR;
}
#endif
return ret;
}
@@ -0,0 +1,76 @@
/*
* Copyright (c) 2022 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_i2c_eeprom.h
* @brief ok1052-c board eeprom relative codes
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-03-01
*/
#include "board.h"
#include "connect_i2c.h"
#include "fsl_lpi2c.h"
#include "pin_mux.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define I2C_EEPROM_BASE LPI2C1
#define I2C_EEPROM_ADDR (0xA0 >> 1)
/*******************************************************************************
* Code
******************************************************************************/
void I2cEEpromTestWrite(void)
{
uint8_t dat[8] = {0};
if(I2cHardwareRead(I2C_EEPROM_BASE, I2C_EEPROM_ADDR, 0, dat, 8) == kStatus_Success)
{
i2c_print("Read from EEPROM %d %d %d %d %d %d %d %d\r\n",
dat[0], dat[1], dat[2], dat[3], dat[4], dat[5], dat[6], dat[7]);
}
for(uint8_t i = 0; i < 8; i++)
{
dat[i] ++;
}
if(I2cHardwareWrite(I2C_EEPROM_BASE, I2C_EEPROM_ADDR, 0, dat, 8) == kStatus_Success)
{
i2c_print("Write to EEPROM %d %d %d %d %d %d %d %d\r\n",
dat[0], dat[1], dat[2], dat[3], dat[4], dat[5], dat[6], dat[7]);
}
memset(dat, 0, 8);
if(I2cHardwareRead(I2C_EEPROM_BASE, I2C_EEPROM_ADDR, 0, dat, 8) == kStatus_Success)
{
i2c_print("Read from EEPROM %d %d %d %d %d %d %d %d\r\n",
dat[0], dat[1], dat[2], dat[3], dat[4], dat[5], dat[6], dat[7]);
}
}
int I2cEEpromTest(void)
{
BOARD_InitI2C1Pins();
I2cHardwareInit();
I2cEEpromTestWrite();
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)| SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)| SHELL_CMD_PARAM_NUM(0),
eeprom, I2cEEpromTest, test i2c eeprom);
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,94 @@
/*
* The Clear BSD License
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted (subject to the limitations in the disclaimer below) provided
* that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file hardware_i2c.c
* @brief ok1052-c i2c board relative codes
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-03-01
*/
#include "fsl_common.h"
#include "fsl_lpi2c.h"
#define I2C_BASE LPI2C1
/* Select USB1 PLL (480 MHz) as master lpi2c clock source */
#define LPI2C_CLOCK_SOURCE_SELECT (0U)
/* Clock divider for master lpi2c clock source */
#define LPI2C_CLOCK_SOURCE_DIVIDER (5U)
#define I2C_CLOCK_FREQ ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 8) / (LPI2C_CLOCK_SOURCE_DIVIDER + 1U))
#define I2C_BAUDRATE 100000U
void I2cHardwareInit(void)
{
lpi2c_master_config_t masterConfig = {0};
LPI2C_MasterGetDefaultConfig(&masterConfig);
/* Change the default baudrate configuration */
masterConfig.baudRate_Hz = I2C_BAUDRATE;
/* Initialize the LPI2C master peripheral */
LPI2C_MasterInit(I2C_BASE, &masterConfig, I2C_CLOCK_FREQ);
}
status_t I2cHardwareWrite(LPI2C_Type* base, uint16_t slave_addr, uint32_t subAdd, uint8_t* dataBuff, uint16_t dataLen)
{
lpi2c_master_transfer_t xfer;
xfer.slaveAddress = slave_addr;
xfer.direction = kLPI2C_Write;
xfer.subaddress = subAdd;
xfer.subaddressSize = 0x01;
xfer.data = dataBuff;
xfer.dataSize = dataLen;
xfer.flags = kLPI2C_TransferDefaultFlag;
return LPI2C_MasterTransferBlocking(base, &xfer);
}
status_t I2cHardwareRead(LPI2C_Type* base, uint16_t slave_addr, uint32_t subAdd, uint8_t* dataBuffer, uint16_t dataLen)
{
lpi2c_master_transfer_t masterXfer = {0};
masterXfer.slaveAddress = slave_addr;
masterXfer.direction = kLPI2C_Read;
masterXfer.subaddress = subAdd;
masterXfer.subaddressSize = 0x01;
masterXfer.data = dataBuffer;
masterXfer.dataSize = dataLen;
masterXfer.flags = kLPI2C_TransferDefaultFlag;
return LPI2C_MasterTransferBlocking(base, &masterXfer);
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,627 @@
/*
** ###################################################################
** Version: rev. 1.1, 2018-11-16
** Build: b181120
**
** Abstract:
** Chip specific module features.
**
** Copyright 2016 Freescale Semiconductor, Inc.
** Copyright 2016-2018 NXP
** All rights reserved.
**
** SPDX-License-Identifier: BSD-3-Clause
**
** http: www.nxp.com
** mail: support@nxp.com
**
** Revisions:
** - rev. 0.1 (2017-01-10)
** Initial version.
** - rev. 1.0 (2018-09-21)
** Update interrupt vector table and dma request source.
** Update register BEE_ADDR_OFFSET1's bitfield name to ADDR_OFFSET1.
** Split GPIO_COMBINED_IRQS to GPIO_COMBINED_LOW_IRQS and GPIO_COMBINED_HIGH_IRQS.
** - rev. 1.1 (2018-11-16)
** Update feature files to align with IMXRT1050RM Rev.1.
**
** ###################################################################
*/
#ifndef _MIMXRT1052_FEATURES_H_
#define _MIMXRT1052_FEATURES_H_
/* SOC module features */
/* @brief ADC availability on the SoC. */
#define FSL_FEATURE_SOC_ADC_COUNT (2)
/* @brief AIPSTZ availability on the SoC. */
#define FSL_FEATURE_SOC_AIPSTZ_COUNT (4)
/* @brief AOI availability on the SoC. */
#define FSL_FEATURE_SOC_AOI_COUNT (2)
/* @brief CCM availability on the SoC. */
#define FSL_FEATURE_SOC_CCM_COUNT (1)
/* @brief CCM_ANALOG availability on the SoC. */
#define FSL_FEATURE_SOC_CCM_ANALOG_COUNT (1)
/* @brief CMP availability on the SoC. */
#define FSL_FEATURE_SOC_CMP_COUNT (4)
/* @brief CSI availability on the SoC. */
#define FSL_FEATURE_SOC_CSI_COUNT (1)
/* @brief DCDC availability on the SoC. */
#define FSL_FEATURE_SOC_DCDC_COUNT (1)
/* @brief DCP availability on the SoC. */
#define FSL_FEATURE_SOC_DCP_COUNT (1)
/* @brief DMAMUX availability on the SoC. */
#define FSL_FEATURE_SOC_DMAMUX_COUNT (1)
/* @brief EDMA availability on the SoC. */
#define FSL_FEATURE_SOC_EDMA_COUNT (1)
/* @brief ENC availability on the SoC. */
#define FSL_FEATURE_SOC_ENC_COUNT (4)
/* @brief ENET availability on the SoC. */
#define FSL_FEATURE_SOC_ENET_COUNT (1)
/* @brief EWM availability on the SoC. */
#define FSL_FEATURE_SOC_EWM_COUNT (1)
/* @brief FLEXCAN availability on the SoC. */
#define FSL_FEATURE_SOC_FLEXCAN_COUNT (2)
/* @brief FLEXIO availability on the SoC. */
#define FSL_FEATURE_SOC_FLEXIO_COUNT (2)
/* @brief FLEXRAM availability on the SoC. */
#define FSL_FEATURE_SOC_FLEXRAM_COUNT (1)
/* @brief FLEXSPI availability on the SoC. */
#define FSL_FEATURE_SOC_FLEXSPI_COUNT (1)
/* @brief GPC availability on the SoC. */
#define FSL_FEATURE_SOC_GPC_COUNT (1)
/* @brief GPT availability on the SoC. */
#define FSL_FEATURE_SOC_GPT_COUNT (2)
/* @brief I2S availability on the SoC. */
#define FSL_FEATURE_SOC_I2S_COUNT (3)
/* @brief IGPIO availability on the SoC. */
#define FSL_FEATURE_SOC_IGPIO_COUNT (5)
/* @brief IOMUXC availability on the SoC. */
#define FSL_FEATURE_SOC_IOMUXC_COUNT (1)
/* @brief IOMUXC_GPR availability on the SoC. */
#define FSL_FEATURE_SOC_IOMUXC_GPR_COUNT (1)
/* @brief IOMUXC_SNVS availability on the SoC. */
#define FSL_FEATURE_SOC_IOMUXC_SNVS_COUNT (1)
/* @brief KPP availability on the SoC. */
#define FSL_FEATURE_SOC_KPP_COUNT (1)
/* @brief LCDIF availability on the SoC. */
#define FSL_FEATURE_SOC_LCDIF_COUNT (1)
/* @brief LPI2C availability on the SoC. */
#define FSL_FEATURE_SOC_LPI2C_COUNT (4)
/* @brief LPSPI availability on the SoC. */
#define FSL_FEATURE_SOC_LPSPI_COUNT (4)
/* @brief LPUART availability on the SoC. */
#define FSL_FEATURE_SOC_LPUART_COUNT (8)
/* @brief OCOTP availability on the SoC. */
#define FSL_FEATURE_SOC_OCOTP_COUNT (1)
/* @brief PIT availability on the SoC. */
#define FSL_FEATURE_SOC_PIT_COUNT (1)
/* @brief PMU availability on the SoC. */
#define FSL_FEATURE_SOC_PMU_COUNT (1)
/* @brief PWM availability on the SoC. */
#define FSL_FEATURE_SOC_PWM_COUNT (4)
/* @brief PXP availability on the SoC. */
#define FSL_FEATURE_SOC_PXP_COUNT (1)
/* @brief ROMC availability on the SoC. */
#define FSL_FEATURE_SOC_ROMC_COUNT (1)
/* @brief SEMC availability on the SoC. */
#define FSL_FEATURE_SOC_SEMC_COUNT (1)
/* @brief SNVS availability on the SoC. */
#define FSL_FEATURE_SOC_SNVS_COUNT (1)
/* @brief SPDIF availability on the SoC. */
#define FSL_FEATURE_SOC_SPDIF_COUNT (1)
/* @brief SRC availability on the SoC. */
#define FSL_FEATURE_SOC_SRC_COUNT (1)
/* @brief TEMPMON availability on the SoC. */
#define FSL_FEATURE_SOC_TEMPMON_COUNT (1)
/* @brief TMR availability on the SoC. */
#define FSL_FEATURE_SOC_TMR_COUNT (4)
/* @brief TRNG availability on the SoC. */
#define FSL_FEATURE_SOC_TRNG_COUNT (1)
/* @brief TSC availability on the SoC. */
#define FSL_FEATURE_SOC_TSC_COUNT (1)
/* @brief USBHS availability on the SoC. */
#define FSL_FEATURE_SOC_USBHS_COUNT (2)
/* @brief USBNC availability on the SoC. */
#define FSL_FEATURE_SOC_USBNC_COUNT (2)
/* @brief USBPHY availability on the SoC. */
#define FSL_FEATURE_SOC_USBPHY_COUNT (2)
/* @brief USDHC availability on the SoC. */
#define FSL_FEATURE_SOC_USDHC_COUNT (2)
/* @brief WDOG availability on the SoC. */
#define FSL_FEATURE_SOC_WDOG_COUNT (2)
/* @brief XBARA availability on the SoC. */
#define FSL_FEATURE_SOC_XBARA_COUNT (1)
/* @brief XBARB availability on the SoC. */
#define FSL_FEATURE_SOC_XBARB_COUNT (2)
/* @brief XTALOSC24M availability on the SoC. */
#define FSL_FEATURE_SOC_XTALOSC24M_COUNT (1)
/* ADC module features */
/* @brief Remove Hardware Trigger feature. */
#define FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE (0)
/* @brief Remove ALT Clock selection feature. */
#define FSL_FEATURE_ADC_SUPPORT_ALTCLK_REMOVE (1)
/* @brief Conversion control count (related to number of registers HCn and Rn). */
#define FSL_FEATURE_ADC_CONVERSION_CONTROL_COUNT (8)
/* ADC_ETC module features */
/* @brief Has DMA model control(bit field CTRL[DMA_MODE_SEL]). */
#define FSL_FEATURE_ADC_ETC_HAS_CTRL_DMA_MODE_SEL (1)
/* AOI module features */
/* @brief Maximum value of input mux. */
#define FSL_FEATURE_AOI_MODULE_INPUTS (4)
/* @brief Number of events related to number of registers AOIx_BFCRT01n/AOIx_BFCRT23n. */
#define FSL_FEATURE_AOI_EVENT_COUNT (4)
/* FLEXCAN module features */
/* @brief Message buffer size */
#define FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(x) (64)
/* @brief Has doze mode support (register bit field MCR[DOZE]). */
#define FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT (0)
/* @brief Insatnce has doze mode support (register bit field MCR[DOZE]). */
#define FSL_FEATURE_FLEXCAN_INSTANCE_HAS_DOZE_MODE_SUPPORTn(x) (0)
/* @brief Has a glitch filter on the receive pin (register bit field MCR[WAKSRC]). */
#define FSL_FEATURE_FLEXCAN_HAS_GLITCH_FILTER (1)
/* @brief Has extended interrupt mask and flag register (register IMASK2, IFLAG2). */
#define FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER (1)
/* @brief Instance has extended bit timing register (register CBT). */
#define FSL_FEATURE_FLEXCAN_INSTANCE_HAS_EXTENDED_TIMING_REGISTERn(x) (0)
/* @brief Has a receive FIFO DMA feature (register bit field MCR[DMA]). */
#define FSL_FEATURE_FLEXCAN_HAS_RX_FIFO_DMA (0)
/* @brief Instance has a receive FIFO DMA feature (register bit field MCR[DMA]). */
#define FSL_FEATURE_FLEXCAN_INSTANCE_HAS_RX_FIFO_DMAn(x) (0)
/* @brief Remove CAN Engine Clock Source Selection from unsupported part. */
#define FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE (1)
/* @brief Instance remove CAN Engine Clock Source Selection from unsupported part. */
#define FSL_FEATURE_FLEXCAN_INSTANCE_SUPPORT_ENGINE_CLK_SEL_REMOVEn(x) (1)
/* @brief Is affected by errata with ID 5641 (Module does not transmit a message that is enabled to be transmitted at a specific moment during the arbitration process). */
#define FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641 (0)
/* @brief Is affected by errata with ID 5829 (FlexCAN: FlexCAN does not transmit a message that is enabled to be transmitted in a specific moment during the arbitration process). */
#define FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829 (1)
/* @brief Is affected by errata with ID 6032 (FlexCAN: A frame with wrong ID or payload is transmitted into the CAN bus when the Message Buffer under transmission is either aborted or deactivated while the CAN bus is in the Bus Idle state). */
#define FSL_FEATURE_FLEXCAN_HAS_ERRATA_6032 (1)
/* @brief Is affected by errata with ID 9595 (FlexCAN: Corrupt frame possible if the Freeze Mode or the Low-Power Mode are entered during a Bus-Off state). */
#define FSL_FEATURE_FLEXCAN_HAS_ERRATA_9595 (1)
/* @brief Has CAN with Flexible Data rate (CAN FD) protocol. */
#define FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE (0)
/* @brief CAN instance support Flexible Data rate (CAN FD) protocol. */
#define FSL_FEATURE_FLEXCAN_INSTANCE_HAS_FLEXIBLE_DATA_RATEn(x) (0)
/* @brief Has extra MB interrupt or common one. */
#define FSL_FEATURE_FLEXCAN_HAS_EXTRA_MB_INT (1)
/* CMP module features */
/* @brief Has Trigger mode in CMP (register bit field CR1[TRIGM]). */
#define FSL_FEATURE_CMP_HAS_TRIGGER_MODE (0)
/* @brief Has Window mode in CMP (register bit field CR1[WE]). */
#define FSL_FEATURE_CMP_HAS_WINDOW_MODE (1)
/* @brief Has External sample supported in CMP (register bit field CR1[SE]). */
#define FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT (1)
/* @brief Has DMA support in CMP (register bit field SCR[DMAEN]). */
#define FSL_FEATURE_CMP_HAS_DMA (1)
/* @brief Has Pass Through mode in CMP (register bit field MUXCR[PSTM]). */
#define FSL_FEATURE_CMP_HAS_PASS_THROUGH_MODE (0)
/* @brief Has DAC Test function in CMP (register DACTEST). */
#define FSL_FEATURE_CMP_HAS_DAC_TEST (0)
/* EDMA module features */
/* @brief Number of DMA channels (related to number of registers TCD, DCHPRI, bit fields ERQ[ERQn], EEI[EEIn], INT[INTn], ERR[ERRn], HRS[HRSn] and bit field widths ES[ERRCHN], CEEI[CEEI], SEEI[SEEI], CERQ[CERQ], SERQ[SERQ], CDNE[CDNE], SSRT[SSRT], CERR[CERR], CINT[CINT], TCDn_CITER_ELINKYES[LINKCH], TCDn_CSR[MAJORLINKCH], TCDn_BITER_ELINKYES[LINKCH]). (Valid only for eDMA modules.) */
#define FSL_FEATURE_EDMA_MODULE_CHANNEL (32)
/* @brief Total number of DMA channels on all modules. */
#define FSL_FEATURE_EDMA_DMAMUX_CHANNELS (32)
/* @brief Number of DMA channel groups (register bit fields CR[ERGA], CR[GRPnPRI], ES[GPE], DCHPRIn[GRPPRI]). (Valid only for eDMA modules.) */
#define FSL_FEATURE_EDMA_CHANNEL_GROUP_COUNT (1)
/* @brief Has DMA_Error interrupt vector. */
#define FSL_FEATURE_EDMA_HAS_ERROR_IRQ (1)
/* @brief Number of DMA channels with asynchronous request capability (register EARS). (Valid only for eDMA modules.) */
#define FSL_FEATURE_EDMA_ASYNCHRO_REQUEST_CHANNEL_COUNT (32)
/* DMAMUX module features */
/* @brief Number of DMA channels (related to number of register CHCFGn). */
#define FSL_FEATURE_DMAMUX_MODULE_CHANNEL (32)
/* @brief Total number of DMA channels on all modules. */
#define FSL_FEATURE_DMAMUX_DMAMUX_CHANNELS (FSL_FEATURE_SOC_DMAMUX_COUNT * 32)
/* @brief Has the periodic trigger capability for the triggered DMA channel (register bit CHCFG0[TRIG]). */
#define FSL_FEATURE_DMAMUX_HAS_TRIG (1)
/* @brief Has DMA Channel Always ON function (register bit CHCFG0[A_ON]). */
#define FSL_FEATURE_DMAMUX_HAS_A_ON (1)
/* ENET module features */
/* @brief Support Interrupt Coalesce */
#define FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE (1)
/* @brief Queue Size. */
#define FSL_FEATURE_ENET_QUEUE (1)
/* @brief Has AVB Support. */
#define FSL_FEATURE_ENET_HAS_AVB (0)
/* @brief Has Timer Pulse Width control. */
#define FSL_FEATURE_ENET_HAS_TIMER_PWCONTROL (1)
/* @brief Has Extend MDIO Support. */
#define FSL_FEATURE_ENET_HAS_EXTEND_MDIO (1)
/* @brief Has Additional 1588 Timer Channel Interrupt. */
#define FSL_FEATURE_ENET_HAS_ADD_1588_TIMER_CHN_INT (0)
/* EWM module features */
/* @brief Has clock select (register CLKCTRL). */
#define FSL_FEATURE_EWM_HAS_CLOCK_SELECT (1)
/* @brief Has clock prescaler (register CLKPRESCALER). */
#define FSL_FEATURE_EWM_HAS_PRESCALER (1)
/* FLEXIO module features */
/* @brief Has Shifter Status Register (FLEXIO_SHIFTSTAT) */
#define FSL_FEATURE_FLEXIO_HAS_SHIFTER_STATUS (1)
/* @brief Has Pin Data Input Register (FLEXIO_PIN) */
#define FSL_FEATURE_FLEXIO_HAS_PIN_STATUS (1)
/* @brief Has Shifter Buffer N Nibble Byte Swapped Register (FLEXIO_SHIFTBUFNBSn) */
#define FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP (1)
/* @brief Has Shifter Buffer N Half Word Swapped Register (FLEXIO_SHIFTBUFHWSn) */
#define FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_HALF_WORD_SWAP (1)
/* @brief Has Shifter Buffer N Nibble Swapped Register (FLEXIO_SHIFTBUFNISn) */
#define FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_SWAP (1)
/* @brief Supports Shifter State Mode (FLEXIO_SHIFTCTLn[SMOD]) */
#define FSL_FEATURE_FLEXIO_HAS_STATE_MODE (1)
/* @brief Supports Shifter Logic Mode (FLEXIO_SHIFTCTLn[SMOD]) */
#define FSL_FEATURE_FLEXIO_HAS_LOGIC_MODE (1)
/* @brief Supports paralle width (FLEXIO_SHIFTCFGn[PWIDTH]) */
#define FSL_FEATURE_FLEXIO_HAS_PARALLEL_WIDTH (1)
/* @brief Reset value of the FLEXIO_VERID register */
#define FSL_FEATURE_FLEXIO_VERID_RESET_VALUE (0x1010001)
/* @brief Reset value of the FLEXIO_PARAM register */
#define FSL_FEATURE_FLEXIO_PARAM_RESET_VALUE (0x2200404)
/* FLEXRAM module features */
/* @brief Bank size */
#define FSL_FEATURE_FLEXRAM_INTERNAL_RAM_BANK_SIZE (32768)
/* @brief Total Bank numbers */
#define FSL_FEATURE_FLEXRAM_INTERNAL_RAM_TOTAL_BANK_NUMBERS (16)
/* FLEXSPI module features */
/* @brief FlexSPI AHB buffer count */
#define FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNTn(x) (4)
/* @brief FlexSPI has no data learn. */
#define FSL_FEATURE_FLEXSPI_HAS_NO_DATA_LEARN (1)
/* GPC module features */
/* @brief Has DVFS0 Change Request. */
#define FSL_FEATURE_GPC_HAS_CNTR_DVFS0CR (0)
/* @brief Has GPC interrupt/event masking. */
#define FSL_FEATURE_GPC_HAS_CNTR_GPCIRQM (0)
/* @brief Has L2 cache power control. */
#define FSL_FEATURE_GPC_HAS_CNTR_L2PGE (0)
/* @brief Has FLEXRAM PDRAM0(bank1-7) power control. */
#define FSL_FEATURE_GPC_HAS_CNTR_PDRAM0PGE (1)
/* @brief Has VADC power control. */
#define FSL_FEATURE_GPC_HAS_CNTR_VADC (0)
/* @brief Has Display power control. */
#define FSL_FEATURE_GPC_HAS_CNTR_DISPLAY (0)
/* @brief Supports IRQ 0-31. */
#define FSL_FEATURE_GPC_HAS_IRQ_0_31 (1)
/* IGPIO module features */
/* @brief Has data register set DR_SET. */
#define FSL_FEATURE_IGPIO_HAS_DR_SET (1)
/* @brief Has data register clear DR_CLEAR. */
#define FSL_FEATURE_IGPIO_HAS_DR_CLEAR (1)
/* @brief Has data register toggle DR_TOGGLE. */
#define FSL_FEATURE_IGPIO_HAS_DR_TOGGLE (1)
/* LCDIF module features */
/* @brief LCDIF does not support alpha support. */
#define FSL_FEATURE_LCDIF_HAS_NO_AS (1)
/* @brief LCDIF does not support output reset pin to LCD panel. */
#define FSL_FEATURE_LCDIF_HAS_NO_RESET_PIN (1)
/* @brief LCDIF supports LUT. */
#define FSL_FEATURE_LCDIF_HAS_LUT (1)
/* LPI2C module features */
/* @brief Has separate DMA RX and TX requests. */
#define FSL_FEATURE_LPI2C_HAS_SEPARATE_DMA_RX_TX_REQn(x) (0)
/* @brief Capacity (number of entries) of the transmit/receive FIFO (or zero if no FIFO is available). */
#define FSL_FEATURE_LPI2C_FIFO_SIZEn(x) (4)
/* LPSPI module features */
/* @brief Capacity (number of entries) of the transmit/receive FIFO (or zero if no FIFO is available). */
#define FSL_FEATURE_LPSPI_FIFO_SIZEn(x) (16)
/* @brief Has separate DMA RX and TX requests. */
#define FSL_FEATURE_LPSPI_HAS_SEPARATE_DMA_RX_TX_REQn(x) (1)
/* LPUART module features */
/* @brief Has receive FIFO overflow detection (bit field CFIFO[RXOFE]). */
#define FSL_FEATURE_LPUART_HAS_IRQ_EXTENDED_FUNCTIONS (0)
/* @brief Has low power features (can be enabled in wait mode via register bit C1[DOZEEN] or CTRL[DOZEEN] if the registers are 32-bit wide). */
#define FSL_FEATURE_LPUART_HAS_LOW_POWER_UART_SUPPORT (1)
/* @brief Has extended data register ED (or extra flags in the DATA register if the registers are 32-bit wide). */
#define FSL_FEATURE_LPUART_HAS_EXTENDED_DATA_REGISTER_FLAGS (1)
/* @brief Capacity (number of entries) of the transmit/receive FIFO (or zero if no FIFO is available). */
#define FSL_FEATURE_LPUART_HAS_FIFO (1)
/* @brief Has 32-bit register MODIR */
#define FSL_FEATURE_LPUART_HAS_MODIR (1)
/* @brief Hardware flow control (RTS, CTS) is supported. */
#define FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT (1)
/* @brief Infrared (modulation) is supported. */
#define FSL_FEATURE_LPUART_HAS_IR_SUPPORT (1)
/* @brief 2 bits long stop bit is available. */
#define FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT (1)
/* @brief If 10-bit mode is supported. */
#define FSL_FEATURE_LPUART_HAS_10BIT_DATA_SUPPORT (1)
/* @brief If 7-bit mode is supported. */
#define FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT (1)
/* @brief Baud rate fine adjustment is available. */
#define FSL_FEATURE_LPUART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT (0)
/* @brief Baud rate oversampling is available (has bit fields C4[OSR], C5[BOTHEDGE], C5[RESYNCDIS] or BAUD[OSR], BAUD[BOTHEDGE], BAUD[RESYNCDIS] if the registers are 32-bit wide). */
#define FSL_FEATURE_LPUART_HAS_BAUD_RATE_OVER_SAMPLING_SUPPORT (1)
/* @brief Baud rate oversampling is available. */
#define FSL_FEATURE_LPUART_HAS_RX_RESYNC_SUPPORT (1)
/* @brief Baud rate oversampling is available. */
#define FSL_FEATURE_LPUART_HAS_BOTH_EDGE_SAMPLING_SUPPORT (1)
/* @brief Peripheral type. */
#define FSL_FEATURE_LPUART_IS_SCI (1)
/* @brief Capacity (number of entries) of the transmit/receive FIFO (or zero if no FIFO is available). */
#define FSL_FEATURE_LPUART_FIFO_SIZEn(x) (4)
/* @brief Maximal data width without parity bit. */
#define FSL_FEATURE_LPUART_MAX_DATA_WIDTH_WITH_NO_PARITY (10)
/* @brief Maximal data width with parity bit. */
#define FSL_FEATURE_LPUART_MAX_DATA_WIDTH_WITH_PARITY (9)
/* @brief Supports two match addresses to filter incoming frames. */
#define FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING (1)
/* @brief Has transmitter/receiver DMA enable bits C5[TDMAE]/C5[RDMAE] (or BAUD[TDMAE]/BAUD[RDMAE] if the registers are 32-bit wide). */
#define FSL_FEATURE_LPUART_HAS_DMA_ENABLE (1)
/* @brief Has transmitter/receiver DMA select bits C4[TDMAS]/C4[RDMAS], resp. C5[TDMAS]/C5[RDMAS] if IS_SCI = 0. */
#define FSL_FEATURE_LPUART_HAS_DMA_SELECT (0)
/* @brief Data character bit order selection is supported (bit field S2[MSBF] or STAT[MSBF] if the registers are 32-bit wide). */
#define FSL_FEATURE_LPUART_HAS_BIT_ORDER_SELECT (1)
/* @brief Has smart card (ISO7816 protocol) support and no improved smart card support. */
#define FSL_FEATURE_LPUART_HAS_SMART_CARD_SUPPORT (0)
/* @brief Has improved smart card (ISO7816 protocol) support. */
#define FSL_FEATURE_LPUART_HAS_IMPROVED_SMART_CARD_SUPPORT (0)
/* @brief Has local operation network (CEA709.1-B protocol) support. */
#define FSL_FEATURE_LPUART_HAS_LOCAL_OPERATION_NETWORK_SUPPORT (0)
/* @brief Has 32-bit registers (BAUD, STAT, CTRL, DATA, MATCH, MODIR) instead of 8-bit (BDH, BDL, C1, S1, D, etc.). */
#define FSL_FEATURE_LPUART_HAS_32BIT_REGISTERS (1)
/* @brief Lin break detect available (has bit BAUD[LBKDIE]). */
#define FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT (1)
/* @brief UART stops in Wait mode available (has bit C1[UARTSWAI]). */
#define FSL_FEATURE_LPUART_HAS_WAIT_MODE_OPERATION (0)
/* @brief Has separate DMA RX and TX requests. */
#define FSL_FEATURE_LPUART_HAS_SEPARATE_DMA_RX_TX_REQn(x) (1)
/* @brief Has separate RX and TX interrupts. */
#define FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ (0)
/* @brief Has LPAURT_PARAM. */
#define FSL_FEATURE_LPUART_HAS_PARAM (1)
/* @brief Has LPUART_VERID. */
#define FSL_FEATURE_LPUART_HAS_VERID (1)
/* @brief Has LPUART_GLOBAL. */
#define FSL_FEATURE_LPUART_HAS_GLOBAL (1)
/* @brief Has LPUART_PINCFG. */
#define FSL_FEATURE_LPUART_HAS_PINCFG (1)
/* interrupt module features */
/* @brief Lowest interrupt request number. */
#define FSL_FEATURE_INTERRUPT_IRQ_MIN (-14)
/* @brief Highest interrupt request number. */
#define FSL_FEATURE_INTERRUPT_IRQ_MAX (151)
/* OCOTP module features */
/* No feature definitions */
/* PIT module features */
/* @brief Number of channels (related to number of registers LDVALn, CVALn, TCTRLn, TFLGn). */
#define FSL_FEATURE_PIT_TIMER_COUNT (4)
/* @brief Has lifetime timer (related to existence of registers LTMR64L and LTMR64H). */
#define FSL_FEATURE_PIT_HAS_LIFETIME_TIMER (1)
/* @brief Has chain mode (related to existence of register bit field TCTRLn[CHN]). */
#define FSL_FEATURE_PIT_HAS_CHAIN_MODE (1)
/* @brief Has shared interrupt handler (has not individual interrupt handler for each channel). */
#define FSL_FEATURE_PIT_HAS_SHARED_IRQ_HANDLER (1)
/* @brief Has timer enable control. */
#define FSL_FEATURE_PIT_HAS_MDIS (1)
/* PMU module features */
/* @brief PMU supports lower power control. */
#define FSL_FEATURE_PMU_HAS_LOWPWR_CTRL (0)
/* PWM module features */
/* @brief Number of each EflexPWM module channels (outputs). */
#define FSL_FEATURE_PWM_CHANNEL_COUNT (12U)
/* @brief Number of EflexPWM module A channels (outputs). */
#define FSL_FEATURE_PWM_CHANNELA_COUNT (4U)
/* @brief Number of EflexPWM module B channels (outputs). */
#define FSL_FEATURE_PWM_CHANNELB_COUNT (4U)
/* @brief Number of EflexPWM module X channels (outputs). */
#define FSL_FEATURE_PWM_CHANNELX_COUNT (4U)
/* @brief Number of each EflexPWM module compare channels interrupts. */
#define FSL_FEATURE_PWM_CMP_INT_HANDLER_COUNT (4U)
/* @brief Number of each EflexPWM module reload channels interrupts. */
#define FSL_FEATURE_PWM_RELOAD_INT_HANDLER_COUNT (4U)
/* @brief Number of each EflexPWM module capture channels interrupts. */
#define FSL_FEATURE_PWM_CAP_INT_HANDLER_COUNT (1U)
/* @brief Number of each EflexPWM module reload error channels interrupts. */
#define FSL_FEATURE_PWM_RERR_INT_HANDLER_COUNT (1U)
/* @brief Number of each EflexPWM module fault channels interrupts. */
#define FSL_FEATURE_PWM_FAULT_INT_HANDLER_COUNT (1U)
/* @brief Number of submodules in each EflexPWM module. */
#define FSL_FEATURE_PWM_SUBMODULE_COUNT (4U)
/* PXP module features */
/* @brief PXP module has dither engine. */
#define FSL_FEATURE_PXP_HAS_DITHER (0)
/* @brief PXP module supports repeat run */
#define FSL_FEATURE_PXP_HAS_EN_REPEAT (1)
/* @brief PXP doesn't have CSC */
#define FSL_FEATURE_PXP_HAS_NO_CSC2 (1)
/* @brief PXP doesn't have LUT */
#define FSL_FEATURE_PXP_HAS_NO_LUT (1)
/* RTWDOG module features */
/* @brief Watchdog is available. */
#define FSL_FEATURE_RTWDOG_HAS_WATCHDOG (1)
/* @brief RTWDOG_CNT can be 32-bit written. */
#define FSL_FEATURE_RTWDOG_HAS_32BIT_ACCESS (1)
/* SAI module features */
/* @brief Receive/transmit FIFO size in item count (register bit fields TCSR[FRDE], TCSR[FRIE], TCSR[FRF], TCR1[TFW], RCSR[FRDE], RCSR[FRIE], RCSR[FRF], RCR1[RFW], registers TFRn, RFRn). */
#define FSL_FEATURE_SAI_FIFO_COUNT (32)
/* @brief Receive/transmit channel number (register bit fields TCR3[TCE], RCR3[RCE], registers TDRn and RDRn). */
#define FSL_FEATURE_SAI_CHANNEL_COUNT (4)
/* @brief Maximum words per frame (register bit fields TCR3[WDFL], TCR4[FRSZ], TMR[TWM], RCR3[WDFL], RCR4[FRSZ], RMR[RWM]). */
#define FSL_FEATURE_SAI_MAX_WORDS_PER_FRAME (32)
/* @brief Has support of combining multiple data channel FIFOs into single channel FIFO (register bit fields TCR3[CFR], TCR4[FCOMB], TFR0[WCP], TFR1[WCP], RCR3[CFR], RCR4[FCOMB], RFR0[RCP], RFR1[RCP]). */
#define FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE (1)
/* @brief Has packing of 8-bit and 16-bit data into each 32-bit FIFO word (register bit fields TCR4[FPACK], RCR4[FPACK]). */
#define FSL_FEATURE_SAI_HAS_FIFO_PACKING (1)
/* @brief Configures when the SAI will continue transmitting after a FIFO error has been detected (register bit fields TCR4[FCONT], RCR4[FCONT]). */
#define FSL_FEATURE_SAI_HAS_FIFO_FUNCTION_AFTER_ERROR (1)
/* @brief Configures if the frame sync is generated internally, a frame sync is only generated when the FIFO warning flag is clear or continuously (register bit fields TCR4[ONDEM], RCR4[ONDEM]). */
#define FSL_FEATURE_SAI_HAS_ON_DEMAND_MODE (1)
/* @brief Simplified bit clock source and asynchronous/synchronous mode selection (register bit fields TCR2[CLKMODE], RCR2[CLKMODE]), in comparison with the exclusively implemented TCR2[SYNC,BCS,BCI,MSEL], RCR2[SYNC,BCS,BCI,MSEL]. */
#define FSL_FEATURE_SAI_HAS_CLOCKING_MODE (0)
/* @brief Has register for configuration of the MCLK divide ratio (register bit fields MDR[FRACT], MDR[DIVIDE]). */
#define FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER (0)
/* @brief Interrupt source number */
#define FSL_FEATURE_SAI_INT_SOURCE_NUM (2)
/* @brief Has register of MCR. */
#define FSL_FEATURE_SAI_HAS_MCR (0)
/* @brief Has bit field MICS of the MCR register. */
#define FSL_FEATURE_SAI_HAS_NO_MCR_MICS (1)
/* @brief Has register of MDR */
#define FSL_FEATURE_SAI_HAS_MDR (0)
/* @brief Has support the BCLK bypass mode when BCLK = MCLK. */
#define FSL_FEATURE_SAI_HAS_BCLK_BYPASS (0)
/* SEMC module features */
/* @brief Has WDH time in NOR controller (register bit field NORCR2[WDH]). */
#define FSL_FEATURE_SEMC_HAS_NOR_WDH_TIME (1)
/* @brief Has WDS time in NOR controller (register bit field NORCR2[WDS]).) */
#define FSL_FEATURE_SEMC_HAS_NOR_WDS_TIME (1)
/* SNVS module features */
/* @brief Has Secure Real Time Counter Enabled and Valid (bit field LPCR[SRTC_ENV]). */
#define FSL_FEATURE_SNVS_HAS_SRTC (1)
/* SRC module features */
/* @brief There is MASK_WDOG3_RST bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_MASK_WDOG3_RST (1)
/* @brief There is MIX_RST_STRCH bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_MIX_RST_STRCH (0)
/* @brief There is DBG_RST_MSK_PG bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_DBG_RST_MSK_PG (1)
/* @brief There is WDOG3_RST_OPTN bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_WDOG3_RST_OPTN (0)
/* @brief There is CORES_DBG_RST bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_CORES_DBG_RST (0)
/* @brief There is MTSR bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_MTSR (0)
/* @brief There is CORE0_DBG_RST bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_CORE0_DBG_RST (1)
/* @brief There is CORE0_RST bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_CORE0_RST (1)
/* @brief There is LOCKUP_RST bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_LOCKUP_RST (0)
/* @brief There is SWRC bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_SWRC (0)
/* @brief There is EIM_RST bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_EIM_RST (0)
/* @brief There is LUEN bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_SCR_LUEN (0)
/* @brief There is no WRBC bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_NO_SCR_WRBC (1)
/* @brief There is no WRE bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_NO_SCR_WRE (1)
/* @brief There is SISR register. */
#define FSL_FEATURE_SRC_HAS_SISR (0)
/* @brief There is RESET_OUT bit in SRSR register. */
#define FSL_FEATURE_SRC_HAS_SRSR_RESET_OUT (0)
/* @brief There is WDOG3_RST_B bit in SRSR register. */
#define FSL_FEATURE_SRC_HAS_SRSR_WDOG3_RST_B (1)
/* @brief There is SW bit in SRSR register. */
#define FSL_FEATURE_SRC_HAS_SRSR_SW (0)
/* @brief There is IPP_USER_RESET_B bit in SRSR register. */
#define FSL_FEATURE_SRC_HAS_SRSR_IPP_USER_RESET_B (1)
/* @brief There is SNVS bit in SRSR register. */
#define FSL_FEATURE_SRC_HAS_SRSR_SNVS (0)
/* @brief There is CSU_RESET_B bit in SRSR register. */
#define FSL_FEATURE_SRC_HAS_SRSR_CSU_RESET_B (1)
/* @brief There is LOCKUP bit in SRSR register. */
#define FSL_FEATURE_SRC_HAS_SRSR_LOCKUP (0)
/* @brief There is LOCKUP_SYSRESETREQ bit in SRSR register. */
#define FSL_FEATURE_SRC_HAS_SRSR_LOCKUP_SYSRESETREQ (1)
/* @brief There is POR bit in SRSR register. */
#define FSL_FEATURE_SRC_HAS_SRSR_POR (0)
/* @brief There is IPP_RESET_B bit in SRSR register. */
#define FSL_FEATURE_SRC_HAS_SRSR_IPP_RESET_B (1)
/* @brief There is no WBI bit in SCR register. */
#define FSL_FEATURE_SRC_HAS_NO_SRSR_WBI (1)
/* SCB module features */
/* @brief L1 ICACHE line size in byte. */
#define FSL_FEATURE_L1ICACHE_LINESIZE_BYTE (32)
/* @brief L1 DCACHE line size in byte. */
#define FSL_FEATURE_L1DCACHE_LINESIZE_BYTE (32)
/* TRNG module features */
/* @brief TRNG has no TRNG_ACC bitfield. */
#define FSL_FEATURE_TRNG_HAS_NO_TRNG_ACC (1)
/* USBHS module features */
/* @brief EHCI module instance count */
#define FSL_FEATURE_USBHS_EHCI_COUNT (2)
/* @brief Number of endpoints supported */
#define FSL_FEATURE_USBHS_ENDPT_COUNT (8)
/* USDHC module features */
/* @brief Has external DMA support (VEND_SPEC[EXT_DMA_EN]) */
#define FSL_FEATURE_USDHC_HAS_EXT_DMA (0)
/* @brief Has HS400 mode (MIX_CTRL[HS400_MODE]) */
#define FSL_FEATURE_USDHC_HAS_HS400_MODE (0)
/* @brief Has SDR50 support (HOST_CTRL_CAP[SDR50_SUPPORT]) */
#define FSL_FEATURE_USDHC_HAS_SDR50_MODE (1)
/* @brief Has SDR104 support (HOST_CTRL_CAP[SDR104_SUPPORT]) */
#define FSL_FEATURE_USDHC_HAS_SDR104_MODE (1)
/* XBARA module features */
/* @brief DMA_CH_MUX_REQ_30. */
#define FSL_FEATURE_XBARA_OUTPUT_DMA_CH_MUX_REQ_30 (1)
/* @brief DMA_CH_MUX_REQ_31. */
#define FSL_FEATURE_XBARA_OUTPUT_DMA_CH_MUX_REQ_31 (1)
/* @brief DMA_CH_MUX_REQ_94. */
#define FSL_FEATURE_XBARA_OUTPUT_DMA_CH_MUX_REQ_94 (1)
/* @brief DMA_CH_MUX_REQ_95. */
#define FSL_FEATURE_XBARA_OUTPUT_DMA_CH_MUX_REQ_95 (1)
#endif /* _MIMXRT1052_FEATURES_H_ */
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2021 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_adc.h
* @brief define ok1052-c board adc function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-12-28
*/
#ifndef CONNECT_ADC_H
#define CONNECT_ADC_H
#include <device.h>
struct Imxrt1052HwAdc
{
void *ADCx;
uint8 adc_channel;
};
int Imxrt1052HwAdcInit(void);
#endif
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2021 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_ethernet.h
* @brief Adapted network software protocol stack and hardware operation functions
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-12-7
*/
#ifndef __CONNECT_ETHERNET_H_
#define __CONNECT_ETHERNET_H_
#include "enet_ethernetif.h"
#include "enet_ethernetif_priv.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef sourceClock
#define sourceClock CLOCK_GetFreq(kCLOCK_CoreSysClk)
#endif
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2022 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_gpio.h
* @brief define ok1052-c board gpio function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-03-01
*/
#ifndef __CONNECT_GPIO_H_
#define __CONNECT_GPIO_H_
#include <device.h>
#ifdef __cplusplus
extern "C" {
#endif
#define IMXRT_GET_PIN(PORTx, PIN) (32 * (PORTx - 1) + (PIN & 31)) /* PORTx:1,2,3,4,5 */
int Imxrt1052HwGpioInit(void);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2021 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_i2c.h
* @brief define ok1052-c board i2c function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef CONNECT_I2C_H
#define CONNECT_I2C_H
#include <device.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct Stm32I2c
{
LPI2C_Type* base;
uint16_t slave_addr;
uint32_t sub_addr;
}Stm32I2cType;
#define i2c_print KPrintf
int Imxrt1052HwI2cInit(void);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2022 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_rtc.h
* @brief define ok1052-c board rtc function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-03-01
*/
#ifndef __CONNECT_RTC_H_
#define __CONNECT_RTC_H_
#include "fsl_common.h"
#include "fsl_lpi2c.h"
#define I2C_RTC_BASE LPI2C1
#define I2C_RTC_ADDR 0x32
void RtcI2cInit(void);
status_t RtcI2cWrite(LPI2C_Type *base, uint32_t sub_addr, uint8_t *buf, uint16_t size);
uint32_t RtcI2cRead(LPI2C_Type *base, uint32_t sub_addr, uint8_t *buf, uint16_t size);
int Imxrt1052HwRtcInit(void);
#endif
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_sdio.h
* @brief define ok1052-c board sdio function and struct
* @version 2.0
* @author AIIT XUOS Lab
* @date 2022-01-24
*/
#ifndef CONNECT_SDIO_H
#define CONNECT_SDIO_H
#include <device.h>
#include <fsl_sd.h>
#include <pin_mux.h>
#include <clock_config.h>
#include <fsl_gpio.h>
#include <fsl_common.h>
#include <connect_gpio.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SD_CARD_STACK_SIZE 2048
int Imxrt1052HwSdioInit(void);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2021 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_spi.h
* @brief define ok1052-c board spi function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef CONNECT_SPI_H
#define CONNECT_SPI_H
#include <device.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SPI_USING_RX_DMA_FLAG (1<<0)
#define SPI_USING_TX_DMA_FLAG (1<<1)
struct Stm32HwSpi
{
LPSPI_Type *base;
uint8_t irq;
uint8_t mode;
void *priv_data;
};
struct Stm32Spi
{
LPSPI_Type *instance;
char *bus_name;
struct SpiBus spi_bus;
};
int Imxrt1052HwSpiInit(void);
x_err_t HwSpiDeviceAttach(const char *bus_name, const char *device_name);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2021 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_uart.h
* @brief define ok1052-c board usart function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-05-28
*/
#ifndef CONNECT_UART_H
#define CONNECT_UART_H
#include <device.h>
#ifdef __cplusplus
extern "C" {
#endif
#define KERNEL_CONSOLE_BUS_NAME SERIAL_BUS_NAME_1
#define KERNEL_CONSOLE_DRV_NAME SERIAL_DRV_NAME_1
#define KERNEL_CONSOLE_DEVICE_NAME SERIAL_1_DEVICE_NAME_0
int Imxrt1052HwUartInit(void);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2022 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_usb.h
* @brief define ok1052-c board usb function and struct
* @version 2.0
* @author AIIT XUOS Lab
* @date 2022-02-09
*/
#ifndef CONNECT_USB_H
#define CONNECT_USB_H
#include <device.h>
#include <fsl_common.h>
#include <usb_host_config.h>
#include <usb_host.h>
#include <usb_host_msd.h>
#include <host_msd_command.h>
#include <usb_phy.h>
#if defined(FS_VFS)
#include <iot-vfs.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define CONTROLLER_ID kUSB_ControllerEhci1
#define USB_HOST_INTERRUPT_PRIORITY (3U)
#define USB_HOST_STACK_SIZE 4096
#define USB_SINGLE_BLOCK_SIZE 512
int Imxrt1052HwUsbHostInit(void);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,195 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
/*
* Copyright (c) 2013-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2019 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file enet_ethernetif.h
* @brief ethernet drivers
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.11.11
*/
#ifndef ENET_ETHERNETIF_H
#define ENET_ETHERNETIF_H
#include "lwip/err.h"
#include "lwip/netif.h"
#include "fsl_enet.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#ifndef ENET_RXBD_NUM
#define ENET_RXBD_NUM (5)
#endif
#ifndef ENET_TXBD_NUM
#if defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
#define ENET_TXBD_NUM (5)
#else
#define ENET_TXBD_NUM (3)
#endif
#endif
#ifndef ENET_RXBUFF_SIZE
#if defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
#define ENET_RXBUFF_SIZE (ENET_FRAME_MAX_FRAMELEN + ETH_PAD_SIZE)
#else
#define ENET_RXBUFF_SIZE ENET_FRAME_MAX_FRAMELEN
#endif
#endif
#ifndef ENET_TXBUFF_SIZE
#define ENET_TXBUFF_SIZE (ENET_FRAME_MAX_FRAMELEN)
#endif
#define ENET_TIMEOUT (0xFFFU)
/* ENET IRQ priority. Used in FreeRTOS. */
/* Interrupt priorities. */
#ifdef __CA7_REV
#ifndef ENET_PRIORITY
#define ENET_PRIORITY (21U)
#endif
#ifndef ENET_1588_PRIORITY
#define ENET_1588_PRIORITY (20U)
#endif
#else
#ifndef ENET_PRIORITY
#define ENET_PRIORITY (15U)//(6U)
#endif
#ifndef ENET_1588_PRIORITY
#define ENET_1588_PRIORITY (5U)
#endif
#endif
/* Defines Ethernet Autonegotiation Timeout during initialization.
* Set it to 0 to disable the waiting. */
#ifndef ENET_ATONEGOTIATION_TIMEOUT
#define ENET_ATONEGOTIATION_TIMEOUT (0xFFFU)
#endif
/* Define those to better describe your network interface. */
#define IFNAME0 'e'
#define IFNAME1 'n'
#if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL
#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE) \
&& ((!defined(FSL_SDK_DISBLE_L2CACHE_PRESENT)) || (FSL_SDK_DISBLE_L2CACHE_PRESENT == 0))
#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#define FSL_CACHE_LINESIZE_MAX MAX(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE, FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#define FSL_ENET_BUFF_ALIGNMENT MAX(ENET_BUFF_ALIGNMENT, FSL_CACHE_LINESIZE_MAX)
#else
#define FSL_ENET_BUFF_ALIGNMENT MAX(ENET_BUFF_ALIGNMENT, FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#endif
#elif defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#define FSL_ENET_BUFF_ALIGNMENT MAX(ENET_BUFF_ALIGNMENT, FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#else
#define FSL_ENET_BUFF_ALIGNMENT ENET_BUFF_ALIGNMENT
#endif
#else
#define FSL_ENET_BUFF_ALIGNMENT ENET_BUFF_ALIGNMENT
#endif
#define ENET_RING_NUM 1U
typedef uint8_t rx_buffer_t[SDK_SIZEALIGN(ENET_RXBUFF_SIZE, FSL_ENET_BUFF_ALIGNMENT)];
typedef uint8_t tx_buffer_t[SDK_SIZEALIGN(ENET_TXBUFF_SIZE, FSL_ENET_BUFF_ALIGNMENT)];
#if (defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0))
typedef struct mem_range
{
uint32_t start;
uint32_t end;
} mem_range_t;
#endif /* FSL_FEATURE_SOC_LPC_ENET_COUNT */
/**
* Helper struct to hold data for configuration of ethernet interface.
*/
typedef struct ethernetif_config
{
uint32_t phyAddress;
clock_name_t clockName;
uint8_t macAddress[NETIF_MAX_HWADDR_LEN];
#if (defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0))
const mem_range_t *non_dma_memory;
#endif /* FSL_FEATURE_SOC_LPC_ENET_COUNT */
} ethernetif_config_t;
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
/**
* This function should be passed as a parameter to netif_add()
* if you initialize the first ENET interface.
*/
err_t ethernetif0_init(struct netif *netif);
#if (defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 1)) \
|| (defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 1))
/**
* This function should be passed as a parameter to netif_add()
* if you initialize the second ENET interface.
*/
err_t ethernetif1_init(struct netif *netif);
#endif /* FSL_FEATURE_SOC_*_ENET_COUNT */
/**
* This function should be called when a packet is ready to be read
* from the interface.
* It is used by bare-metal applications.
*
* @param netif the lwip network interface structure for this ethernetif
*/
void ethernetif_input( struct netif *netif);
void ETH_BSP_Config(void);
void *ethernetif_config_enet_set(uint8_t enet_port);
int32 lwip_obtain_semaphore(struct netif *netif);
#define NETIF_ENET0_INIT_FUNC ethernetif0_init
#if defined(__cplusplus)
}
#endif /* __cplusplus */
#endif /* ENET_ETHERNETIF_H */
@@ -0,0 +1,82 @@
/*
* Copyright 2019 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file enet_ethernetif_priv.h
* @brief ethernet drivers
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.11.11
*/
#ifndef ENET_ETHERNETIF_PRIV_H
#define ENET_ETHERNETIF_PRIV_H
#include "lwip/err.h"
struct ethernetif;
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
err_t ethernetif_init(struct netif *netif, struct ethernetif *ethernetif,
const uint8_t enetIdx,
const ethernetif_config_t *ethernetifConfig);
void ethernetif_enet_init(struct netif *netif, struct ethernetif *ethernetif,
const ethernetif_config_t *ethernetifConfig);
void ethernetif_phy_init(struct ethernetif *ethernetif,
const ethernetif_config_t *ethernetifConfig,
enet_config_t *config);
ENET_Type **ethernetif_enet_ptr(struct ethernetif *ethernetif);
#if LWIP_IPV4 && LWIP_IGMP
err_t ethernetif_igmp_mac_filter(struct netif *netif, const ip4_addr_t *group,
enum netif_mac_filter_action action);
#endif
#if LWIP_IPV6 && LWIP_IPV6_MLD
err_t ethernetif_mld_mac_filter(struct netif *netif, const ip6_addr_t *group,
enum netif_mac_filter_action action);
#endif
/**
* Should allocate a pbuf and transfer the bytes of the incoming
* packet from the interface into the pbuf.
*
* @param netif the lwip network interface structure for this ethernetif
* @return a pbuf filled with the received packet (including MAC header)
* NULL on memory error
*/
struct pbuf *ethernetif_linkinput(struct netif *netif);
/**
* This function should do the actual transmission of the packet. The packet is
* contained in the pbuf that is passed to the function. This pbuf
* might be chained.
*
* @param netif the lwip network interface structure for this ethernetif
* @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
* @return ERR_OK if the packet could be sent
* an err_t value if the packet couldn't be sent
*
* @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
* strange results. You might consider waiting for space in the DMA queue
* to become available since the stack doesn't retry to send a packet
* dropped because of memory failure (except for the TCP timers).
*/
err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p);
#if defined(__cplusplus)
}
#endif /* __cplusplus */
#endif /* ENET_ETHERNETIF_PRIV_H */
@@ -0,0 +1,476 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file fsl_cache.h
* @brief cache drivers
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.11.11
*/
#ifndef _FSL_CACHE_H_
#define _FSL_CACHE_H_
#include "fsl_common.h"
/*!
* @addtogroup cache
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief cache driver version 2.0.1. */
#define FSL_CACHE_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
/*@}*/
#if defined(FSL_FEATURE_SOC_L2CACHEC_COUNT) && FSL_FEATURE_SOC_L2CACHEC_COUNT
#ifndef FSL_SDK_DISBLE_L2CACHE_PRESENT
#define FSL_SDK_DISBLE_L2CACHE_PRESENT 0
#endif
#endif /* FSL_FEATURE_SOC_L2CACHEC_COUNT */
/*******************************************************************************
* Definitions
******************************************************************************/
#if defined(FSL_FEATURE_SOC_L2CACHEC_COUNT) && FSL_FEATURE_SOC_L2CACHEC_COUNT
/*! @brief Number of level 2 cache controller ways. */
typedef enum _l2cache_way_num
{
kL2CACHE_8ways = 0, /*!< 8 ways. */
#if defined(FSL_FEATURE_L2CACHE_SUPPORT_16_WAY_ASSOCIATIVITY) && FSL_FEATURE_L2CACHE_SUPPORT_16_WAY_ASSOCIATIVITY
kL2CACHE_16ways /*!< 16 ways. */
#endif /* FSL_FEATURE_L2CACHE_SUPPORT_16_WAY_ASSOCIATIVITY */
} l2cache_way_num_t;
/*! @brief Level 2 cache controller way size. */
typedef enum _l2cache_way_size
{
kL2CACHE_16KBSize = 1, /*!< 16 KB way size. */
kL2CACHE_32KBSize = 2, /*!< 32 KB way size. */
kL2CACHE_64KBSize = 3, /*!< 64 KB way size. */
kL2CACHE_128KBSize = 4, /*!< 128 KB way size. */
kL2CACHE_256KBSize = 5, /*!< 256 KB way size. */
kL2CACHE_512KBSize = 6 /*!< 512 KB way size. */
} l2cache_way_size;
/*! @brief Level 2 cache controller replacement policy. */
typedef enum _l2cache_replacement
{
kL2CACHE_Pseudorandom = 0U, /*!< Peseudo-random replacement policy using an lfsr. */
kL2CACHE_Roundrobin /*!< Round-robin replacemnt policy. */
} l2cache_replacement_t;
/*! @brief Level 2 cache controller force write allocate options. */
typedef enum _l2cache_writealloc
{
kL2CACHE_UseAwcache = 0, /*!< Use AWCAHE attribute for the write allocate. */
kL2CACHE_NoWriteallocate, /*!< Force no write allocate. */
kL2CACHE_forceWriteallocate /*!< Force write allocate when write misses. */
} l2cache_writealloc_t;
/*! @brief Level 2 cache controller tag/data ram latency. */
typedef enum _l2cache_latency
{
kL2CACHE_1CycleLate = 0, /*!< 1 cycle of latency. */
kL2CACHE_2CycleLate, /*!< 2 cycle of latency. */
kL2CACHE_3CycleLate, /*!< 3 cycle of latency. */
kL2CACHE_4CycleLate, /*!< 4 cycle of latency. */
kL2CACHE_5CycleLate, /*!< 5 cycle of latency. */
kL2CACHE_6CycleLate, /*!< 6 cycle of latency. */
kL2CACHE_7CycleLate, /*!< 7 cycle of latency. */
kL2CACHE_8CycleLate /*!< 8 cycle of latency. */
} l2cache_latency_t;
/*! @brief Level 2 cache controller tag/data ram latency configure structure. */
typedef struct _l2cache_latency_config
{
l2cache_latency_t tagWriteLate; /*!< Tag write latency. */
l2cache_latency_t tagReadLate; /*!< Tag Read latency. */
l2cache_latency_t tagSetupLate; /*!< Tag setup latency. */
l2cache_latency_t dataWriteLate; /*!< Data write latency. */
l2cache_latency_t dataReadLate; /*!< Data Read latency. */
l2cache_latency_t dataSetupLate; /*!< Data setup latency. */
} L2cache_latency_config_t;
/*! @brief Level 2 cache controller configure structure. */
typedef struct _l2cache_config
{
/* ------------------------ l2 cachec basic settings ---------------------------- */
l2cache_way_num_t wayNum; /*!< The number of ways. */
l2cache_way_size waySize; /*!< The way size = Cache Ram size / wayNum. */
l2cache_replacement_t repacePolicy; /*!< Replacemnet policy. */
/* ------------------------ tag/data ram latency settings ----------------------- */
L2cache_latency_config_t *lateConfig; /*!< Tag/data latency configure. Set NUll if not required. */
/* ------------------------ Prefetch enable settings ---------------------------- */
bool istrPrefetchEnable; /*!< Instruction prefetch enable. */
bool dataPrefetchEnable; /*!< Data prefetch enable. */
/* ------------------------ Non-secure access settings -------------------------- */
bool nsLockdownEnable; /*!< None-secure lockdown enable. */
/* ------------------------ other settings -------------------------------------- */
l2cache_writealloc_t writeAlloc; /*!< Write allcoate force option. */
} l2cache_config_t;
#endif /* FSL_FEATURE_SOC_L2CACHEC_COUNT */
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Control for cortex-m7 L1 cache
*@{
*/
/*!
* @brief Enables cortex-m7 L1 instruction cache.
*
*/
static inline void L1CACHE_EnableICache(void)
{
SCB_EnableICache();
}
/*!
* @brief Disables cortex-m7 L1 instruction cache.
*
*/
static inline void L1CACHE_DisableICache(void)
{
SCB_DisableICache();
}
/*!
* @brief Invalidate cortex-m7 L1 instruction cache.
*
*/
static inline void L1CACHE_InvalidateICache(void)
{
SCB_InvalidateICache();
}
/*!
* @brief Invalidate cortex-m7 L1 instruction cache by range.
*
* @param address The start address of the memory to be invalidated.
* @param size_byte The memory size.
* @note The start address and size_byte should be 32-byte(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE) aligned.
* The startAddr here will be forced to align to L1 I-cache line size if
* startAddr is not aligned. For the size_byte, application should make sure the
* alignment or make sure the right operation order if the size_byte is not aligned.
*/
void L1CACHE_InvalidateICacheByRange(uint32_t address, uint32_t size_byte);
/*!
* @brief Enables cortex-m7 L1 data cache.
*
*/
static inline void L1CACHE_EnableDCache(void)
{
SCB_EnableDCache();
}
/*!
* @brief Disables cortex-m7 L1 data cache.
*
*/
static inline void L1CACHE_DisableDCache(void)
{
SCB_DisableDCache();
}
/*!
* @brief Invalidates cortex-m7 L1 data cache.
*
*/
static inline void L1CACHE_InvalidateDCache(void)
{
SCB_InvalidateDCache();
}
/*!
* @brief Cleans cortex-m7 L1 data cache.
*
*/
static inline void L1CACHE_CleanDCache(void)
{
SCB_CleanDCache();
}
/*!
* @brief Cleans and Invalidates cortex-m7 L1 data cache.
*
*/
static inline void L1CACHE_CleanInvalidateDCache(void)
{
SCB_CleanInvalidateDCache();
}
/*!
* @brief Invalidates cortex-m7 L1 data cache by range.
*
* @param address The start address of the memory to be invalidated.
* @param size_byte The memory size.
* @note The start address and size_byte should be 32-byte(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) aligned.
* The startAddr here will be forced to align to L1 D-cache line size if
* startAddr is not aligned. For the size_byte, application should make sure the
* alignment or make sure the right operation order if the size_byte is not aligned.
*/
static inline void L1CACHE_InvalidateDCacheByRange(uint32_t address, uint32_t size_byte)
{
uint32_t startAddr = address & (uint32_t) ~(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE - 1);
uint32_t size = size_byte + address - startAddr;
SCB_InvalidateDCache_by_Addr((uint32_t *)startAddr, size);
}
/*!
* @brief Cleans cortex-m7 L1 data cache by range.
*
* @param address The start address of the memory to be cleaned.
* @param size_byte The memory size.
* @note The start address and size_byte should be 32-byte(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) aligned.
* The startAddr here will be forced to align to L1 D-cache line size if
* startAddr is not aligned. For the size_byte, application should make sure the
* alignment or make sure the right operation order if the size_byte is not aligned.
*/
static inline void L1CACHE_CleanDCacheByRange(uint32_t address, uint32_t size_byte)
{
uint32_t startAddr = address & (uint32_t) ~(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE - 1);
uint32_t size = size_byte + address - startAddr;
SCB_CleanDCache_by_Addr((uint32_t *)startAddr, size);
}
/*!
* @brief Cleans and Invalidates cortex-m7 L1 data cache by range.
*
* @param address The start address of the memory to be clean and invalidated.
* @param size_byte The memory size.
* @note The start address and size_byte should be 32-byte(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) aligned.
* The startAddr here will be forced to align to L1 D-cache line size if
* startAddr is not aligned. For the size_byte, application should make sure the
* alignment or make sure the right operation order if the size_byte is not aligned.
*/
static inline void L1CACHE_CleanInvalidateDCacheByRange(uint32_t address, uint32_t size_byte)
{
uint32_t startAddr = address & (uint32_t) ~(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE - 1);
uint32_t size = size_byte + address - startAddr;
SCB_CleanInvalidateDCache_by_Addr((uint32_t *)startAddr, size);
}
/*@}*/
#if defined(FSL_FEATURE_SOC_L2CACHEC_COUNT) && FSL_FEATURE_SOC_L2CACHEC_COUNT
/*!
* @name Control for L2 pl310 cache
*@{
*/
/*!
* @brief Initializes the level 2 cache controller module.
*
* @param config Pointer to configuration structure. See "l2cache_config_t".
*/
void L2CACHE_Init(l2cache_config_t *config);
/*!
* @brief Gets an available default settings for the cache controller.
*
* This function initializes the cache controller configuration structure with default settings.
* The default values are:
* @code
* config->waysNum = kL2CACHE_8ways;
* config->waySize = kL2CACHE_32KbSize;
* config->repacePolicy = kL2CACHE_Roundrobin;
* config->lateConfig = NULL;
* config->istrPrefetchEnable = false;
* config->dataPrefetchEnable = false;
* config->nsLockdownEnable = false;
* config->writeAlloc = kL2CACHE_UseAwcache;
* @endcode
* @param config Pointer to the configuration structure.
*/
void L2CACHE_GetDefaultConfig(l2cache_config_t *config);
/*!
* @brief Enables the level 2 cache controller.
* This function enables the cache controller. Must be written using a secure access.
* If write with a Non-secure access will cause a DECERR response.
*
*/
void L2CACHE_Enable(void);
/*!
* @brief Disables the level 2 cache controller.
* This function disables the cache controller. Must be written using a secure access.
* If write with a Non-secure access will cause a DECERR response.
*
*/
void L2CACHE_Disable(void);
/*!
* @brief Invalidates the Level 2 cache.
* This function invalidates all entries in cache.
*
*/
void L2CACHE_Invalidate(void);
/*!
* @brief Invalidates the Level 2 cache lines in the range of two physical addresses.
* This function invalidates all cache lines between two physical addresses.
*
* @param address The start address of the memory to be invalidated.
* @param size_byte The memory size.
* @note The start address and size_byte should be 32-byte(FSL_FEATURE_L2CACHE_LINESIZE_BYTE) aligned.
* The startAddr here will be forced to align to L2 line size if startAddr
* is not aligned. For the size_byte, application should make sure the
* alignment or make sure the right operation order if the size_byte is not aligned.
*/
void L2CACHE_InvalidateByRange(uint32_t address, uint32_t size_byte);
/*!
* @brief Cleans the level 2 cache controller.
* This function cleans all entries in the level 2 cache controller.
*
*/
void L2CACHE_Clean(void);
/*!
* @brief Cleans the Level 2 cache lines in the range of two physical addresses.
* This function cleans all cache lines between two physical addresses.
*
* @param address The start address of the memory to be cleaned.
* @param size_byte The memory size.
* @note The start address and size_byte should be 32-byte(FSL_FEATURE_L2CACHE_LINESIZE_BYTE) aligned.
* The startAddr here will be forced to align to L2 line size if startAddr
* is not aligned. For the size_byte, application should make sure the
* alignment or make sure the right operation order if the size_byte is not aligned.
*/
void L2CACHE_CleanByRange(uint32_t address, uint32_t size_byte);
/*!
* @brief Cleans and invalidates the level 2 cache controller.
* This function cleans and invalidates all entries in the level 2 cache controller.
*
*/
void L2CACHE_CleanInvalidate(void);
/*!
* @brief Cleans and invalidates the Level 2 cache lines in the range of two physical addresses.
* This function cleans and invalidates all cache lines between two physical addresses.
*
* @param address The start address of the memory to be cleaned and invalidated.
* @param size_byte The memory size.
* @note The start address and size_byte should be 32-byte(FSL_FEATURE_L2CACHE_LINESIZE_BYTE) aligned.
* The startAddr here will be forced to align to L2 line size if startAddr
* is not aligned. For the size_byte, application should make sure the
* alignment or make sure the right operation order if the size_byte is not aligned.
*/
void L2CACHE_CleanInvalidateByRange(uint32_t address, uint32_t size_byte);
/*!
* @brief Enables or disables to lock down the data and instruction by way.
* This function locks down the cached instruction/data by way and prevent the adresses from
* being allocated and prevent dara from being evicted out of the level 2 cache.
* But the normal cache maintenance operations that invalidate, clean or clean
* and validate cache contents affect the locked-down cache lines as normal.
*
* @param masterId The master id, range from 0 ~ 7.
* @param mask The ways to be enabled or disabled to lockdown.
* each bit in value is related to each way of the cache. for example:
* value: bit 0 ------ way 0.
* value: bit 1 ------ way 1.
* --------------------------
* value: bit 15 ------ way 15.
* Note: please make sure the value setting is align with your supported ways.
* @param enable True enable the lockdown, false to disable the lockdown.
*/
void L2CACHE_LockdownByWayEnable(uint32_t masterId, uint32_t mask, bool enable);
/*@}*/
#endif /* FSL_FEATURE_SOC_L2CACHEC_COUNT */
/*!
* @name Unified Cache Control for all caches (cortex-m7 L1 cache + l2 pl310)
* Mainly used for many drivers for easy cache operation.
*@{
*/
/*!
* @brief Invalidates all instruction caches by range.
*
* Both cortex-m7 L1 cache line and L2 PL310 cache line length is 32-byte.
*
* @param address The physical address.
* @param size_byte size of the memory to be invalidated.
* @note address and size should be aligned to cache line size
* 32-Byte due to the cache operation unit is one cache line. The startAddr here will be forced
* to align to the cache line size if startAddr is not aligned. For the size_byte, application should
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
*/
void ICACHE_InvalidateByRange(uint32_t address, uint32_t size_byte);
/*!
* @brief Invalidates all data caches by range.
*
* Both cortex-m7 L1 cache line and L2 PL310 cache line length is 32-byte.
*
* @param address The physical address.
* @param size_byte size of the memory to be invalidated.
* @note address and size should be aligned to cache line size
* 32-Byte due to the cache operation unit is one cache line. The startAddr here will be forced
* to align to the cache line size if startAddr is not aligned. For the size_byte, application should
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
*/
void DCACHE_InvalidateByRange(uint32_t address, uint32_t size_byte);
/*!
* @brief Cleans all data caches by range.
*
* Both cortex-m7 L1 cache line and L2 PL310 cache line length is 32-byte.
*
* @param address The physical address.
* @param size_byte size of the memory to be cleaned.
* @note address and size should be aligned to cache line size
* 32-Byte due to the cache operation unit is one cache line. The startAddr here will be forced
* to align to the cache line size if startAddr is not aligned. For the size_byte, application should
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
*/
void DCACHE_CleanByRange(uint32_t address, uint32_t size_byte);
/*!
* @brief Cleans and Invalidates all data caches by range.
*
* Both cortex-m7 L1 cache line and L2 PL310 cache line length is 32-byte.
*
* @param address The physical address.
* @param size_byte size of the memory to be cleaned and invalidated.
* @note address and size should be aligned to cache line size
* 32-Byte due to the cache operation unit is one cache line. The startAddr here will be forced
* to align to the cache line size if startAddr is not aligned. For the size_byte, application should
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
*/
void DCACHE_CleanInvalidateByRange(uint32_t address, uint32_t size_byte);
/*@}*/
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_CACHE_H_*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,593 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file fsl_common.h
* @brief common drivers header
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.11.11
*/
#ifndef _FSL_COMMON_H_
#define _FSL_COMMON_H_
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#if defined(__ICCARM__)
#include <stddef.h>
#endif
#include "fsl_device_registers.h"
/*!
* @addtogroup ksdk_common
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Construct a status code value from a group and code number. */
#define MAKE_STATUS(group, code) ((((group)*100) + (code)))
/*! @brief Construct the version number for drivers. */
#define MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix))
/*! @name Driver version */
/*@{*/
/*! @brief common driver version 2.0.1. */
#define FSL_COMMON_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
/*@}*/
/* Debug console type definition. */
#define DEBUG_CONSOLE_DEVICE_TYPE_NONE 0U /*!< No debug console. */
#define DEBUG_CONSOLE_DEVICE_TYPE_UART 1U /*!< Debug console based on UART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_LPUART 2U /*!< Debug console based on LPUART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_LPSCI 3U /*!< Debug console based on LPSCI. */
#define DEBUG_CONSOLE_DEVICE_TYPE_USBCDC 4U /*!< Debug console based on USBCDC. */
#define DEBUG_CONSOLE_DEVICE_TYPE_FLEXCOMM 5U /*!< Debug console based on FLEXCOMM. */
#define DEBUG_CONSOLE_DEVICE_TYPE_IUART 6U /*!< Debug console based on i.MX UART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_VUSART 7U /*!< Debug console based on LPC_VUSART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_MINI_USART 8U /*!< Debug console based on LPC_USART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_SWO 9U /*!< Debug console based on SWO. */
/*! @brief Status group numbers. */
enum _status_groups
{
kStatusGroup_Generic = 0, /*!< Group number for generic status codes. */
kStatusGroup_FLASH = 1, /*!< Group number for FLASH status codes. */
kStatusGroup_LPSPI = 4, /*!< Group number for LPSPI status codes. */
kStatusGroup_FLEXIO_SPI = 5, /*!< Group number for FLEXIO SPI status codes. */
kStatusGroup_DSPI = 6, /*!< Group number for DSPI status codes. */
kStatusGroup_FLEXIO_UART = 7, /*!< Group number for FLEXIO UART status codes. */
kStatusGroup_FLEXIO_I2C = 8, /*!< Group number for FLEXIO I2C status codes. */
kStatusGroup_LPI2C = 9, /*!< Group number for LPI2C status codes. */
kStatusGroup_UART = 10, /*!< Group number for UART status codes. */
kStatusGroup_I2C = 11, /*!< Group number for UART status codes. */
kStatusGroup_LPSCI = 12, /*!< Group number for LPSCI status codes. */
kStatusGroup_LPUART = 13, /*!< Group number for LPUART status codes. */
kStatusGroup_SPI = 14, /*!< Group number for SPI status code.*/
kStatusGroup_XRDC = 15, /*!< Group number for XRDC status code.*/
kStatusGroup_SEMA42 = 16, /*!< Group number for SEMA42 status code.*/
kStatusGroup_SDHC = 17, /*!< Group number for SDHC status code */
kStatusGroup_SDMMC = 18, /*!< Group number for SDMMC status code */
kStatusGroup_SAI = 19, /*!< Group number for SAI status code */
kStatusGroup_MCG = 20, /*!< Group number for MCG status codes. */
kStatusGroup_SCG = 21, /*!< Group number for SCG status codes. */
kStatusGroup_SDSPI = 22, /*!< Group number for SDSPI status codes. */
kStatusGroup_FLEXIO_I2S = 23, /*!< Group number for FLEXIO I2S status codes */
kStatusGroup_FLEXIO_MCULCD = 24, /*!< Group number for FLEXIO LCD status codes */
kStatusGroup_FLASHIAP = 25, /*!< Group number for FLASHIAP status codes */
kStatusGroup_FLEXCOMM_I2C = 26, /*!< Group number for FLEXCOMM I2C status codes */
kStatusGroup_I2S = 27, /*!< Group number for I2S status codes */
kStatusGroup_IUART = 28, /*!< Group number for IUART status codes */
kStatusGroup_CSI = 29, /*!< Group number for CSI status codes */
kStatusGroup_MIPI_DSI = 30, /*!< Group number for MIPI DSI status codes */
kStatusGroup_SDRAMC = 35, /*!< Group number for SDRAMC status codes. */
kStatusGroup_POWER = 39, /*!< Group number for POWER status codes. */
kStatusGroup_ENET = 40, /*!< Group number for ENET status codes. */
kStatusGroup_PHY = 41, /*!< Group number for PHY status codes. */
kStatusGroup_TRGMUX = 42, /*!< Group number for TRGMUX status codes. */
kStatusGroup_SMARTCARD = 43, /*!< Group number for SMARTCARD status codes. */
kStatusGroup_LMEM = 44, /*!< Group number for LMEM status codes. */
kStatusGroup_QSPI = 45, /*!< Group number for QSPI status codes. */
kStatusGroup_DMA = 50, /*!< Group number for DMA status codes. */
kStatusGroup_EDMA = 51, /*!< Group number for EDMA status codes. */
kStatusGroup_DMAMGR = 52, /*!< Group number for DMAMGR status codes. */
kStatusGroup_FLEXCAN = 53, /*!< Group number for FlexCAN status codes. */
kStatusGroup_LTC = 54, /*!< Group number for LTC status codes. */
kStatusGroup_FLEXIO_CAMERA = 55, /*!< Group number for FLEXIO CAMERA status codes. */
kStatusGroup_LPC_SPI = 56, /*!< Group number for LPC_SPI status codes. */
kStatusGroup_LPC_USART = 57, /*!< Group number for LPC_USART status codes. */
kStatusGroup_DMIC = 58, /*!< Group number for DMIC status codes. */
kStatusGroup_SDIF = 59, /*!< Group number for SDIF status codes.*/
kStatusGroup_SPIFI = 60, /*!< Group number for SPIFI status codes. */
kStatusGroup_OTP = 61, /*!< Group number for OTP status codes. */
kStatusGroup_MCAN = 62, /*!< Group number for MCAN status codes. */
kStatusGroup_CAAM = 63, /*!< Group number for CAAM status codes. */
kStatusGroup_ECSPI = 64, /*!< Group number for ECSPI status codes. */
kStatusGroup_USDHC = 65, /*!< Group number for USDHC status codes.*/
kStatusGroup_LPC_I2C = 66, /*!< Group number for LPC_I2C status codes.*/
kStatusGroup_DCP = 67, /*!< Group number for DCP status codes.*/
kStatusGroup_MSCAN = 68, /*!< Group number for MSCAN status codes.*/
kStatusGroup_ESAI = 69, /*!< Group number for ESAI status codes. */
kStatusGroup_FLEXSPI = 70, /*!< Group number for FLEXSPI status codes. */
kStatusGroup_MMDC = 71, /*!< Group number for MMDC status codes. */
kStatusGroup_PDM = 72, /*!< Group number for MIC status codes. */
kStatusGroup_SDMA = 73, /*!< Group number for SDMA status codes. */
kStatusGroup_ICS = 74, /*!< Group number for ICS status codes. */
kStatusGroup_SPDIF = 75, /*!< Group number for SPDIF status codes. */
kStatusGroup_LPC_MINISPI = 76, /*!< Group number for LPC_MINISPI status codes. */
kStatusGroup_HASHCRYPT = 77, /*!< Group number for Hashcrypt status codes */
kStatusGroup_LPC_SPI_SSP = 78, /*!< Group number for LPC_SPI_SSP status codes. */
kStatusGroup_LPC_I2C_1 = 97, /*!< Group number for LPC_I2C_1 status codes. */
kStatusGroup_NOTIFIER = 98, /*!< Group number for NOTIFIER status codes. */
kStatusGroup_DebugConsole = 99, /*!< Group number for debug console status codes. */
kStatusGroup_SEMC = 100, /*!< Group number for SEMC status codes. */
kStatusGroup_ApplicationRangeStart = 101, /*!< Starting number for application groups. */
kStatusGroup_IAP = 102, /*!< Group number for IAP status codes */
kStatusGroup_HAL_GPIO = 121, /*!< Group number for HAL GPIO status codes. */
kStatusGroup_HAL_UART = 122, /*!< Group number for HAL UART status codes. */
kStatusGroup_HAL_TIMER = 123, /*!< Group number for HAL TIMER status codes. */
kStatusGroup_HAL_SPI = 124, /*!< Group number for HAL SPI status codes. */
kStatusGroup_HAL_I2C = 125, /*!< Group number for HAL I2C status codes. */
kStatusGroup_HAL_FLASH = 126, /*!< Group number for HAL FLASH status codes. */
kStatusGroup_HAL_PWM = 127, /*!< Group number for HAL PWM status codes. */
kStatusGroup_HAL_RNG = 128, /*!< Group number for HAL RNG status codes. */
kStatusGroup_TIMERMANAGER = 135, /*!< Group number for TiMER MANAGER status codes. */
kStatusGroup_SERIALMANAGER = 136, /*!< Group number for SERIAL MANAGER status codes. */
kStatusGroup_LED = 137, /*!< Group number for LED status codes. */
kStatusGroup_BUTTON = 138, /*!< Group number for BUTTON status codes. */
kStatusGroup_EXTERN_EEPROM = 139, /*!< Group number for EXTERN EEPROM status codes. */
kStatusGroup_SHELL = 140, /*!< Group number for SHELL status codes. */
kStatusGroup_MEM_MANAGER = 141, /*!< Group number for MEM MANAGER status codes. */
kStatusGroup_LIST = 142, /*!< Group number for List status codes. */
kStatusGroup_OSA = 143, /*!< Group number for OSA status codes. */
kStatusGroup_COMMON_TASK = 144, /*!< Group number for Common task status codes. */
kStatusGroup_MSG = 145, /*!< Group number for messaging status codes. */
};
/*! @brief Generic status return codes. */
enum _generic_status
{
kStatus_Success = MAKE_STATUS(kStatusGroup_Generic, 0),
kStatus_Fail = MAKE_STATUS(kStatusGroup_Generic, 1),
kStatus_ReadOnly = MAKE_STATUS(kStatusGroup_Generic, 2),
kStatus_OutOfRange = MAKE_STATUS(kStatusGroup_Generic, 3),
kStatus_InvalidArgument = MAKE_STATUS(kStatusGroup_Generic, 4),
kStatus_Timeout = MAKE_STATUS(kStatusGroup_Generic, 5),
kStatus_NoTransferInProgress = MAKE_STATUS(kStatusGroup_Generic, 6),
};
/*! @brief Type used for all status and error return values. */
typedef int32_t status_t;
/*
* The fsl_clock.h is included here because it needs MAKE_VERSION/MAKE_STATUS/status_t
* defined in previous of this file.
*/
#include "fsl_clock.h"
/*
* Chip level peripheral reset API, for MCUs that implement peripheral reset control external to a peripheral
*/
#if ((defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0)) || \
(defined(FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT) && (FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT > 0)))
#include "fsl_reset.h"
#endif
/*
* Macro guard for whether to use default weak IRQ implementation in drivers
*/
#ifndef FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
#define FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ 1
#endif
/*! @name Min/max macros */
/* @{ */
#if !defined(MIN)
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
#if !defined(MAX)
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
/* @} */
/*! @brief Computes the number of elements in an array. */
#if !defined(ARRAY_SIZE)
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#endif
/*! @name UINT16_MAX/UINT32_MAX value */
/* @{ */
#if !defined(UINT16_MAX)
#define UINT16_MAX ((uint16_t)-1)
#endif
#if !defined(UINT32_MAX)
#define UINT32_MAX ((uint32_t)-1)
#endif
/* @} */
/*! @name Timer utilities */
/* @{ */
/*! Macro to convert a microsecond period to raw count value */
#define USEC_TO_COUNT(us, clockFreqInHz) (uint64_t)((uint64_t)us * clockFreqInHz / 1000000U)
/*! Macro to convert a raw count value to microsecond */
#define COUNT_TO_USEC(count, clockFreqInHz) (uint64_t)((uint64_t)count * 1000000U / clockFreqInHz)
/*! Macro to convert a millisecond period to raw count value */
#define MSEC_TO_COUNT(ms, clockFreqInHz) (uint64_t)((uint64_t)ms * clockFreqInHz / 1000U)
/*! Macro to convert a raw count value to millisecond */
#define COUNT_TO_MSEC(count, clockFreqInHz) (uint64_t)((uint64_t)count * 1000U / clockFreqInHz)
/* @} */
/*! @name Alignment variable definition macros */
/* @{ */
#if (defined(__ICCARM__))
/**
* Workaround to disable MISRA C message suppress warnings for IAR compiler.
* http://supp.iar.com/Support/?note=24725
*/
_Pragma("diag_suppress=Pm120")
#define SDK_PRAGMA(x) _Pragma(#x)
_Pragma("diag_error=Pm120")
/*! Macro to define a variable with alignbytes alignment */
#define SDK_ALIGN(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var
/*! Macro to define a variable with L1 d-cache line size alignment */
#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#define SDK_L1DCACHE_ALIGN(var) SDK_PRAGMA(data_alignment = FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) var
#endif
/*! Macro to define a variable with L2 cache line size alignment */
#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#define SDK_L2CACHE_ALIGN(var) SDK_PRAGMA(data_alignment = FSL_FEATURE_L2CACHE_LINESIZE_BYTE) var
#endif
#elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
/*! Macro to define a variable with alignbytes alignment */
#define SDK_ALIGN(var, alignbytes) __attribute__((aligned(alignbytes))) var
/*! Macro to define a variable with L1 d-cache line size alignment */
#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#define SDK_L1DCACHE_ALIGN(var) __attribute__((aligned(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE))) var
#endif
/*! Macro to define a variable with L2 cache line size alignment */
#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#define SDK_L2CACHE_ALIGN(var) __attribute__((aligned(FSL_FEATURE_L2CACHE_LINESIZE_BYTE))) var
#endif
#elif defined(__GNUC__)
/*! Macro to define a variable with alignbytes alignment */
#define SDK_ALIGN(var, alignbytes) var __attribute__((aligned(alignbytes)))
/*! Macro to define a variable with L1 d-cache line size alignment */
#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#define SDK_L1DCACHE_ALIGN(var) var __attribute__((aligned(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)))
#endif
/*! Macro to define a variable with L2 cache line size alignment */
#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#define SDK_L2CACHE_ALIGN(var) var __attribute__((aligned(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)))
#endif
#else
#error Toolchain not supported
#define SDK_ALIGN(var, alignbytes) var
#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#define SDK_L1DCACHE_ALIGN(var) var
#endif
#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#define SDK_L2CACHE_ALIGN(var) var
#endif
#endif
/*! Macro to change a value to a given size aligned value */
#define SDK_SIZEALIGN(var, alignbytes) \
((unsigned int)((var) + ((alignbytes)-1)) & (unsigned int)(~(unsigned int)((alignbytes)-1)))
/* @} */
/*! @name Non-cacheable region definition macros */
/* For initialized non-zero non-cacheable variables, please using "AT_NONCACHEABLE_SECTION_INIT(var) ={xx};" or
* "AT_NONCACHEABLE_SECTION_ALIGN_INIT(var) ={xx};" in your projects to define them, for zero-inited non-cacheable variables,
* please using "AT_NONCACHEABLE_SECTION(var);" or "AT_NONCACHEABLE_SECTION_ALIGN(var);" to define them, these zero-inited variables
* will be initialized to zero in system startup.
*/
/* @{ */
#if (defined(__ICCARM__))
#if ((!(defined(FSL_FEATURE_HAS_NO_NONCACHEABLE_SECTION) && FSL_FEATURE_HAS_NO_NONCACHEABLE_SECTION)) && defined(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE))
#define AT_NONCACHEABLE_SECTION(var) var @"NonCacheable"
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var @"NonCacheable"
#define AT_NONCACHEABLE_SECTION_INIT(var) var @"NonCacheable.init"
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var @"NonCacheable.init"
#else
#define AT_NONCACHEABLE_SECTION(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var
#define AT_NONCACHEABLE_SECTION_INIT(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var
#endif
#elif(defined(__CC_ARM) || defined(__ARMCC_VERSION))
#if ((!(defined(FSL_FEATURE_HAS_NO_NONCACHEABLE_SECTION) && FSL_FEATURE_HAS_NO_NONCACHEABLE_SECTION)) && defined(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE))
#define AT_NONCACHEABLE_SECTION(var) __attribute__((section("NonCacheable"), zero_init)) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \
__attribute__((section("NonCacheable"), zero_init)) __attribute__((aligned(alignbytes))) var
#define AT_NONCACHEABLE_SECTION_INIT(var) __attribute__((section("NonCacheable.init"))) var
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) \
__attribute__((section("NonCacheable.init"))) __attribute__((aligned(alignbytes))) var
#else
#define AT_NONCACHEABLE_SECTION(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) __attribute__((aligned(alignbytes))) var
#define AT_NONCACHEABLE_SECTION_INIT(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) __attribute__((aligned(alignbytes))) var
#endif
#elif(defined(__GNUC__))
/* For GCC, when the non-cacheable section is required, please define "__STARTUP_INITIALIZE_NONCACHEDATA"
* in your projects to make sure the non-cacheable section variables will be initialized in system startup.
*/
#if ((!(defined(FSL_FEATURE_HAS_NO_NONCACHEABLE_SECTION) && FSL_FEATURE_HAS_NO_NONCACHEABLE_SECTION)) && defined(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE))
#define AT_NONCACHEABLE_SECTION_INIT(var) __attribute__((section("NonCacheable.init"))) var
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) \
__attribute__((section("NonCacheable.init"))) var __attribute__((aligned(alignbytes)))
#define AT_NONCACHEABLE_SECTION(var) __attribute__((section("NonCacheable,\"aw\",%nobits @"))) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \
__attribute__((section("NonCacheable,\"aw\",%nobits @"))) var __attribute__((aligned(alignbytes)))
#else
#define AT_NONCACHEABLE_SECTION(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) var __attribute__((aligned(alignbytes)))
#define AT_NONCACHEABLE_SECTION_INIT(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) var __attribute__((aligned(alignbytes)))
#endif
#else
#error Toolchain not supported.
#define AT_NONCACHEABLE_SECTION(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) var
#define AT_NONCACHEABLE_SECTION_INIT(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) var
#endif
/* @} */
/*! @name Time sensitive region */
/* @{ */
#if defined(FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE) && FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE
#if (defined(__ICCARM__))
#define AT_QUICKACCESS_SECTION_CODE(func) func @"CodeQuickAccess"
#define AT_QUICKACCESS_SECTION_DATA(func) func @"DataQuickAccess"
#elif(defined(__CC_ARM) || defined(__ARMCC_VERSION))
#define AT_QUICKACCESS_SECTION_CODE(func) __attribute__((section("CodeQuickAccess"))) func
#define AT_QUICKACCESS_SECTION_DATA(func) __attribute__((section("DataQuickAccess"))) func
#elif(defined(__GNUC__))
#define AT_QUICKACCESS_SECTION_CODE(func) __attribute__((section("CodeQuickAccess"))) func
#define AT_QUICKACCESS_SECTION_DATA(func) __attribute__((section("DataQuickAccess"))) func
#else
#error Toolchain not supported.
#endif /* defined(__ICCARM__) */
#else
#if (defined(__ICCARM__))
#define AT_QUICKACCESS_SECTION_CODE(func) func
#define AT_QUICKACCESS_SECTION_DATA(func) func
#elif(defined(__CC_ARM) || defined(__ARMCC_VERSION))
#define AT_QUICKACCESS_SECTION_CODE(func) func
#define AT_QUICKACCESS_SECTION_DATA(func) func
#elif(defined(__GNUC__))
#define AT_QUICKACCESS_SECTION_CODE(func) func
#define AT_QUICKACCESS_SECTION_DATA(func) func
#else
#error Toolchain not supported.
#endif
#endif /* __FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE */
/* @} */
/*! @name Ram Function */
#if (defined(__ICCARM__))
#define RAMFUNCTION_SECTION_CODE(func) func @"RamFunction"
#elif(defined(__CC_ARM) || defined(__ARMCC_VERSION))
#define RAMFUNCTION_SECTION_CODE(func) __attribute__((section("RamFunction"))) func
#elif(defined(__GNUC__))
#define RAMFUNCTION_SECTION_CODE(func) __attribute__((section("RamFunction"))) func
#else
#error Toolchain not supported.
#endif /* defined(__ICCARM__) */
/* @} */
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C"
{
#endif
/*!
* @brief Enable specific interrupt.
*
* Enable LEVEL1 interrupt. For some devices, there might be multiple interrupt
* levels. For example, there are NVIC and intmux. Here the interrupts connected
* to NVIC are the LEVEL1 interrupts, because they are routed to the core directly.
* The interrupts connected to intmux are the LEVEL2 interrupts, they are routed
* to NVIC first then routed to core.
*
* This function only enables the LEVEL1 interrupts. The number of LEVEL1 interrupts
* is indicated by the feature macro FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS.
*
* @param interrupt The IRQ number.
* @retval kStatus_Success Interrupt enabled successfully
* @retval kStatus_Fail Failed to enable the interrupt
*/
static inline status_t EnableIRQ(IRQn_Type interrupt)
{
if (NotAvail_IRQn == interrupt)
{
return kStatus_Fail;
}
#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
if (interrupt >= FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
{
return kStatus_Fail;
}
#endif
#if defined(__GIC_PRIO_BITS)
GIC_EnableIRQ(interrupt);
#else
NVIC_EnableIRQ(interrupt);
#endif
return kStatus_Success;
}
/*!
* @brief Disable specific interrupt.
*
* Disable LEVEL1 interrupt. For some devices, there might be multiple interrupt
* levels. For example, there are NVIC and intmux. Here the interrupts connected
* to NVIC are the LEVEL1 interrupts, because they are routed to the core directly.
* The interrupts connected to intmux are the LEVEL2 interrupts, they are routed
* to NVIC first then routed to core.
*
* This function only disables the LEVEL1 interrupts. The number of LEVEL1 interrupts
* is indicated by the feature macro FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS.
*
* @param interrupt The IRQ number.
* @retval kStatus_Success Interrupt disabled successfully
* @retval kStatus_Fail Failed to disable the interrupt
*/
static inline status_t DisableIRQ(IRQn_Type interrupt)
{
if (NotAvail_IRQn == interrupt)
{
return kStatus_Fail;
}
#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
if (interrupt >= FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
{
return kStatus_Fail;
}
#endif
#if defined(__GIC_PRIO_BITS)
GIC_DisableIRQ(interrupt);
#else
NVIC_DisableIRQ(interrupt);
#endif
return kStatus_Success;
}
/*!
* @brief Disable the global IRQ
*
* Disable the global interrupt and return the current primask register. User is required to provided the primask
* register for the EnableGlobalIRQ().
*
* @return Current primask value.
*/
static inline uint32_t DisableGlobalIRQ(void)
{
#if defined(CPSR_I_Msk)
uint32_t cpsr = __get_CPSR() & CPSR_I_Msk;
__disable_irq();
return cpsr;
#else
uint32_t regPrimask = __get_PRIMASK();
__disable_irq();
return regPrimask;
#endif
}
/*!
* @brief Enable the global IRQ
*
* Set the primask register with the provided primask value but not just enable the primask. The idea is for the
* convenience of integration of RTOS. some RTOS get its own management mechanism of primask. User is required to
* use the EnableGlobalIRQ() and DisableGlobalIRQ() in pair.
*
* @param primask value of primask register to be restored. The primask value is supposed to be provided by the
* DisableGlobalIRQ().
*/
static inline void EnableGlobalIRQ(uint32_t primask)
{
#if defined(CPSR_I_Msk)
__set_CPSR((__get_CPSR() & ~CPSR_I_Msk) | primask);
#else
__set_PRIMASK(primask);
#endif
}
#if defined(ENABLE_RAM_VECTOR_TABLE)
/*!
* @brief install IRQ handler
*
* @param irq IRQ number
* @param irqHandler IRQ handler address
* @return The old IRQ handler address
*/
uint32_t InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler);
#endif /* ENABLE_RAM_VECTOR_TABLE. */
#if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0))
/*!
* @brief Enable specific interrupt for wake-up from deep-sleep mode.
*
* Enable the interrupt for wake-up from deep sleep mode.
* Some interrupts are typically used in sleep mode only and will not occur during
* deep-sleep mode because relevant clocks are stopped. However, it is possible to enable
* those clocks (significantly increasing power consumption in the reduced power mode),
* making these wake-ups possible.
*
* @note This function also enables the interrupt in the NVIC (EnableIRQ() is called internaly).
*
* @param interrupt The IRQ number.
*/
void EnableDeepSleepIRQ(IRQn_Type interrupt);
/*!
* @brief Disable specific interrupt for wake-up from deep-sleep mode.
*
* Disable the interrupt for wake-up from deep sleep mode.
* Some interrupts are typically used in sleep mode only and will not occur during
* deep-sleep mode because relevant clocks are stopped. However, it is possible to enable
* those clocks (significantly increasing power consumption in the reduced power mode),
* making these wake-ups possible.
*
* @note This function also disables the interrupt in the NVIC (DisableIRQ() is called internaly).
*
* @param interrupt The IRQ number.
*/
void DisableDeepSleepIRQ(IRQn_Type interrupt);
#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */
/*!
* @brief Allocate memory with given alignment and aligned size.
*
* This is provided to support the dynamically allocated memory
* used in cache-able region.
* @param size The length required to malloc.
* @param alignbytes The alignment size.
* @retval The allocated memory.
*/
void *SDK_Malloc(size_t size, size_t alignbytes);
/*!
* @brief Free memory.
*
* @param ptr The memory to be release.
*/
void SDK_Free(void *ptr);
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* _FSL_COMMON_H_ */
@@ -0,0 +1,36 @@
/*
* Copyright 2014-2016 Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef __FSL_DEVICE_REGISTERS_H__
#define __FSL_DEVICE_REGISTERS_H__
/*
* Include the cpu specific register header files.
*
* The CPU macro should be declared in the project or makefile.
*/
#if (defined(CPU_MIMXRT1052CVJ5B) || defined(CPU_MIMXRT1052CVL5B) || defined(CPU_MIMXRT1052DVJ6B) || \
defined(CPU_MIMXRT1052DVL6B))
#define MIMXRT1052_SERIES
/* CMSIS-style register definitions */
#include "MIMXRT1052.h"
/* CPU specific feature definitions */
#include "MIMXRT1052_features.h"
#else
#error "No valid CPU defined!"
#endif
#endif /* __FSL_DEVICE_REGISTERS_H__ */
/*******************************************************************************
* EOF
******************************************************************************/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,342 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_GPIO_H_
#define _FSL_GPIO_H_
#include "fsl_common.h"
/*!
* @addtogroup gpio_driver
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief GPIO driver version 2.0.1. */
#define FSL_GPIO_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
/*@}*/
/*! @brief GPIO direction definition. */
typedef enum _gpio_pin_direction
{
kGPIO_DigitalInput = 0U, /*!< Set current pin as digital input.*/
kGPIO_DigitalOutput = 1U, /*!< Set current pin as digital output.*/
} gpio_pin_direction_t;
/*! @brief GPIO interrupt mode definition. */
typedef enum _gpio_interrupt_mode
{
kGPIO_NoIntmode = 0U, /*!< Set current pin general IO functionality.*/
kGPIO_IntLowLevel = 1U, /*!< Set current pin interrupt is low-level sensitive.*/
kGPIO_IntHighLevel = 2U, /*!< Set current pin interrupt is high-level sensitive.*/
kGPIO_IntRisingEdge = 3U, /*!< Set current pin interrupt is rising-edge sensitive.*/
kGPIO_IntFallingEdge = 4U, /*!< Set current pin interrupt is falling-edge sensitive.*/
kGPIO_IntRisingOrFallingEdge = 5U, /*!< Enable the edge select bit to override the ICR register's configuration.*/
} gpio_interrupt_mode_t;
/*! @brief GPIO Init structure definition. */
typedef struct _gpio_pin_config
{
gpio_pin_direction_t direction; /*!< Specifies the pin direction. */
uint8_t outputLogic; /*!< Set a default output logic, which has no use in input */
gpio_interrupt_mode_t
interruptMode; /*!< Specifies the pin interrupt mode, a value of @ref gpio_interrupt_mode_t. */
} gpio_pin_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name GPIO Initialization and Configuration functions
* @{
*/
/*!
* @brief Initializes the GPIO peripheral according to the specified
* parameters in the initConfig.
*
* @param base GPIO base pointer.
* @param pin Specifies the pin number
* @param initConfig pointer to a @ref gpio_pin_config_t structure that
* contains the configuration information.
*/
void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *Config);
/*@}*/
/*!
* @name GPIO Reads and Write Functions
* @{
*/
/*!
* @brief Sets the output level of the individual GPIO pin to logic 1 or 0.
*
* @param base GPIO base pointer.
* @param pin GPIO port pin number.
* @param output GPIOpin output logic level.
* - 0: corresponding pin output low-logic level.
* - 1: corresponding pin output high-logic level.
*/
void GPIO_PinWrite(GPIO_Type *base, uint32_t pin, uint8_t output);
/*!
* @brief Sets the output level of the individual GPIO pin to logic 1 or 0.
* @deprecated Do not use this function. It has been superceded by @ref GPIO_PinWrite.
*/
static inline void GPIO_WritePinOutput(GPIO_Type *base, uint32_t pin, uint8_t output)
{
GPIO_PinWrite(base, pin, output);
}
/*!
* @brief Sets the output level of the multiple GPIO pins to the logic 1.
*
* @param base GPIO peripheral base pointer (GPIO1, GPIO2, GPIO3, and so on.)
* @param mask GPIO pin number macro
*/
static inline void GPIO_PortSet(GPIO_Type *base, uint32_t mask)
{
#if (defined(FSL_FEATURE_IGPIO_HAS_DR_SET) && (FSL_FEATURE_IGPIO_HAS_DR_SET == 1))
base->DR_SET = mask;
#else
base->DR |= mask;
#endif /* FSL_FEATURE_IGPIO_HAS_DR_SET */
}
/*!
* @brief Sets the output level of the multiple GPIO pins to the logic 1.
* @deprecated Do not use this function. It has been superceded by @ref GPIO_PortSet.
*/
static inline void GPIO_SetPinsOutput(GPIO_Type *base, uint32_t mask)
{
GPIO_PortSet(base, mask);
}
/*!
* @brief Sets the output level of the multiple GPIO pins to the logic 0.
*
* @param base GPIO peripheral base pointer (GPIO1, GPIO2, GPIO3, and so on.)
* @param mask GPIO pin number macro
*/
static inline void GPIO_PortClear(GPIO_Type *base, uint32_t mask)
{
#if (defined(FSL_FEATURE_IGPIO_HAS_DR_CLEAR) && (FSL_FEATURE_IGPIO_HAS_DR_CLEAR == 1))
base->DR_CLEAR = mask;
#else
base->DR &= ~mask;
#endif /* FSL_FEATURE_IGPIO_HAS_DR_CLEAR */
}
/*!
* @brief Sets the output level of the multiple GPIO pins to the logic 0.
* @deprecated Do not use this function. It has been superceded by @ref GPIO_PortClear.
*/
static inline void GPIO_ClearPinsOutput(GPIO_Type *base, uint32_t mask)
{
GPIO_PortClear(base, mask);
}
/*!
* @brief Reverses the current output logic of the multiple GPIO pins.
*
* @param base GPIO peripheral base pointer (GPIO1, GPIO2, GPIO3, and so on.)
* @param mask GPIO pin number macro
*/
static inline void GPIO_PortToggle(GPIO_Type *base, uint32_t mask)
{
#if (defined(FSL_FEATURE_IGPIO_HAS_DR_TOGGLE) && (FSL_FEATURE_IGPIO_HAS_DR_TOGGLE == 1))
base->DR_TOGGLE = mask;
#endif /* FSL_FEATURE_IGPIO_HAS_DR_TOGGLE */
}
/*!
* @brief Reads the current input value of the GPIO port.
*
* @param base GPIO base pointer.
* @param pin GPIO port pin number.
* @retval GPIO port input value.
*/
static inline uint32_t GPIO_PinRead(GPIO_Type *base, uint32_t pin)
{
assert(pin < 32);
return (((base->DR) >> pin) & 0x1U);
}
/*!
* @brief Reads the current input value of the GPIO port.
* @deprecated Do not use this function. It has been superceded by @ref GPIO_PinRead.
*/
static inline uint32_t GPIO_ReadPinInput(GPIO_Type *base, uint32_t pin)
{
return GPIO_PinRead(base, pin);
}
/*@}*/
/*!
* @name GPIO Reads Pad Status Functions
* @{
*/
/*!
* @brief Reads the current GPIO pin pad status.
*
* @param base GPIO base pointer.
* @param pin GPIO port pin number.
* @retval GPIO pin pad status value.
*/
static inline uint8_t GPIO_PinReadPadStatus(GPIO_Type *base, uint32_t pin)
{
assert(pin < 32);
return (uint8_t)(((base->PSR) >> pin) & 0x1U);
}
/*!
* @brief Reads the current GPIO pin pad status.
* @deprecated Do not use this function. It has been superceded by @ref GPIO_PinReadPadStatus.
*/
static inline uint8_t GPIO_ReadPadStatus(GPIO_Type *base, uint32_t pin)
{
return GPIO_PinReadPadStatus(base, pin);
}
/*@}*/
/*!
* @name Interrupts and flags management functions
* @{
*/
/*!
* @brief Sets the current pin interrupt mode.
*
* @param base GPIO base pointer.
* @param pin GPIO port pin number.
* @param pininterruptMode pointer to a @ref gpio_interrupt_mode_t structure
* that contains the interrupt mode information.
*/
void GPIO_PinSetInterruptConfig(GPIO_Type *base, uint32_t pin, gpio_interrupt_mode_t pinInterruptMode);
/*!
* @brief Sets the current pin interrupt mode.
* @deprecated Do not use this function. It has been superceded by @ref GPIO_PinSetInterruptConfig.
*/
static inline void GPIO_SetPinInterruptConfig(GPIO_Type *base, uint32_t pin, gpio_interrupt_mode_t pinInterruptMode)
{
GPIO_PinSetInterruptConfig(base, pin, pinInterruptMode);
}
/*!
* @brief Enables the specific pin interrupt.
*
* @param base GPIO base pointer.
* @param mask GPIO pin number macro.
*/
static inline void GPIO_PortEnableInterrupts(GPIO_Type *base, uint32_t mask)
{
base->IMR |= mask;
}
/*!
* @brief Enables the specific pin interrupt.
*
* @param base GPIO base pointer.
* @param mask GPIO pin number macro.
*/
static inline void GPIO_EnableInterrupts(GPIO_Type *base, uint32_t mask)
{
GPIO_PortEnableInterrupts(base, mask);
}
/*!
* @brief Disables the specific pin interrupt.
*
* @param base GPIO base pointer.
* @param mask GPIO pin number macro.
*/
static inline void GPIO_PortDisableInterrupts(GPIO_Type *base, uint32_t mask)
{
base->IMR &= ~mask;
}
/*!
* @brief Disables the specific pin interrupt.
* @deprecated Do not use this function. It has been superceded by @ref GPIO_PortDisableInterrupts.
*/
static inline void GPIO_DisableInterrupts(GPIO_Type *base, uint32_t mask)
{
GPIO_PortDisableInterrupts(base, mask);
}
/*!
* @brief Reads individual pin interrupt status.
*
* @param base GPIO base pointer.
* @retval current pin interrupt status flag.
*/
static inline uint32_t GPIO_PortGetInterruptFlags(GPIO_Type *base)
{
return base->ISR;
}
/*!
* @brief Reads individual pin interrupt status.
*
* @param base GPIO base pointer.
* @retval current pin interrupt status flag.
*/
static inline uint32_t GPIO_GetPinsInterruptFlags(GPIO_Type *base)
{
return GPIO_PortGetInterruptFlags(base);
}
/*!
* @brief Clears pin interrupt flag. Status flags are cleared by
* writing a 1 to the corresponding bit position.
*
* @param base GPIO base pointer.
* @param mask GPIO pin number macro.
*/
static inline void GPIO_PortClearInterruptFlags(GPIO_Type *base, uint32_t mask)
{
base->ISR = mask;
}
/*!
* @brief Clears pin interrupt flag. Status flags are cleared by
* writing a 1 to the corresponding bit position.
*
* @param base GPIO base pointer.
* @param mask GPIO pin number macro.
*/
static inline void GPIO_ClearPinsInterruptFlags(GPIO_Type *base, uint32_t mask)
{
GPIO_PortClearInterruptFlags(base, mask);
}
/*@}*/
#if defined(__cplusplus)
}
#endif
/*!
* @}
*/
#endif /* _FSL_GPIO_H_*/
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,864 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file fsl_lpuart.h
* @brief fsl uart drivers
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.11.11
*/
#ifndef _FSL_LPUART_H_
#define _FSL_LPUART_H_
#include "fsl_common.h"
/*!
* @addtogroup lpuart_driver
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief LPUART driver version 2.2.6. */
#define FSL_LPUART_DRIVER_VERSION (MAKE_VERSION(2, 2, 6))
/*@}*/
/*! @brief Error codes for the LPUART driver. */
enum _lpuart_status
{
kStatus_LPUART_TxBusy = MAKE_STATUS(kStatusGroup_LPUART, 0), /*!< TX busy */
kStatus_LPUART_RxBusy = MAKE_STATUS(kStatusGroup_LPUART, 1), /*!< RX busy */
kStatus_LPUART_TxIdle = MAKE_STATUS(kStatusGroup_LPUART, 2), /*!< LPUART transmitter is idle. */
kStatus_LPUART_RxIdle = MAKE_STATUS(kStatusGroup_LPUART, 3), /*!< LPUART receiver is idle. */
kStatus_LPUART_TxWatermarkTooLarge = MAKE_STATUS(kStatusGroup_LPUART, 4), /*!< TX FIFO watermark too large */
kStatus_LPUART_RxWatermarkTooLarge = MAKE_STATUS(kStatusGroup_LPUART, 5), /*!< RX FIFO watermark too large */
kStatus_LPUART_FlagCannotClearManually = MAKE_STATUS(kStatusGroup_LPUART, 6), /*!< Some flag can't manually clear */
kStatus_LPUART_Error = MAKE_STATUS(kStatusGroup_LPUART, 7), /*!< Error happens on LPUART. */
kStatus_LPUART_RxRingBufferOverrun =
MAKE_STATUS(kStatusGroup_LPUART, 8), /*!< LPUART RX software ring buffer overrun. */
kStatus_LPUART_RxHardwareOverrun = MAKE_STATUS(kStatusGroup_LPUART, 9), /*!< LPUART RX receiver overrun. */
kStatus_LPUART_NoiseError = MAKE_STATUS(kStatusGroup_LPUART, 10), /*!< LPUART noise error. */
kStatus_LPUART_FramingError = MAKE_STATUS(kStatusGroup_LPUART, 11), /*!< LPUART framing error. */
kStatus_LPUART_ParityError = MAKE_STATUS(kStatusGroup_LPUART, 12), /*!< LPUART parity error. */
kStatus_LPUART_BaudrateNotSupport =
MAKE_STATUS(kStatusGroup_LPUART, 13), /*!< Baudrate is not support in current clock source */
kStatus_LPUART_IdleLineDetected = MAKE_STATUS(kStatusGroup_LPUART, 14), /*!< IDLE flag. */
};
/*! @brief LPUART parity mode. */
typedef enum _lpuart_parity_mode
{
kLPUART_ParityDisabled = 0x0U, /*!< Parity disabled */
kLPUART_ParityEven = 0x2U, /*!< Parity enabled, type even, bit setting: PE|PT = 10 */
kLPUART_ParityOdd = 0x3U, /*!< Parity enabled, type odd, bit setting: PE|PT = 11 */
} lpuart_parity_mode_t;
/*! @brief LPUART data bits count. */
typedef enum _lpuart_data_bits
{
kLPUART_EightDataBits = 0x0U, /*!< Eight data bit */
#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
kLPUART_SevenDataBits = 0x1U, /*!< Seven data bit */
#endif
} lpuart_data_bits_t;
/*! @brief LPUART stop bit count. */
typedef enum _lpuart_stop_bit_count
{
kLPUART_OneStopBit = 0U, /*!< One stop bit */
kLPUART_TwoStopBit = 1U, /*!< Two stop bits */
} lpuart_stop_bit_count_t;
#if defined(FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT) && FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT
/*! @brief LPUART transmit CTS source. */
typedef enum _lpuart_transmit_cts_source
{
kLPUART_CtsSourcePin = 0U, /*!< CTS resource is the LPUART_CTS pin. */
kLPUART_CtsSourceMatchResult = 1U, /*!< CTS resource is the match result. */
} lpuart_transmit_cts_source_t;
/*! @brief LPUART transmit CTS configure. */
typedef enum _lpuart_transmit_cts_config
{
kLPUART_CtsSampleAtStart = 0U, /*!< CTS input is sampled at the start of each character. */
kLPUART_CtsSampleAtIdle = 1U, /*!< CTS input is sampled when the transmitter is idle */
} lpuart_transmit_cts_config_t;
#endif
/*! @brief LPUART idle flag type defines when the receiver starts counting. */
typedef enum _lpuart_idle_type_select
{
kLPUART_IdleTypeStartBit = 0U, /*!< Start counting after a valid start bit. */
kLPUART_IdleTypeStopBit = 1U, /*!< Start counting after a stop bit. */
} lpuart_idle_type_select_t;
/*! @brief LPUART idle detected configuration.
* This structure defines the number of idle characters that must be received before
* the IDLE flag is set.
*/
typedef enum _lpuart_idle_config
{
kLPUART_IdleCharacter1 = 0U, /*!< the number of idle characters. */
kLPUART_IdleCharacter2 = 1U, /*!< the number of idle characters. */
kLPUART_IdleCharacter4 = 2U, /*!< the number of idle characters. */
kLPUART_IdleCharacter8 = 3U, /*!< the number of idle characters. */
kLPUART_IdleCharacter16 = 4U, /*!< the number of idle characters. */
kLPUART_IdleCharacter32 = 5U, /*!< the number of idle characters. */
kLPUART_IdleCharacter64 = 6U, /*!< the number of idle characters. */
kLPUART_IdleCharacter128 = 7U, /*!< the number of idle characters. */
} lpuart_idle_config_t;
/*!
* @brief LPUART interrupt configuration structure, default settings all disabled.
*
* This structure contains the settings for all LPUART interrupt configurations.
*/
enum _lpuart_interrupt_enable
{
#if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
kLPUART_LinBreakInterruptEnable = (LPUART_BAUD_LBKDIE_MASK >> 8), /*!< LIN break detect. */
#endif
kLPUART_RxActiveEdgeInterruptEnable = (LPUART_BAUD_RXEDGIE_MASK >> 8), /*!< Receive Active Edge. */
kLPUART_TxDataRegEmptyInterruptEnable = (LPUART_CTRL_TIE_MASK), /*!< Transmit data register empty. */
kLPUART_TransmissionCompleteInterruptEnable = (LPUART_CTRL_TCIE_MASK), /*!< Transmission complete. */
kLPUART_RxDataRegFullInterruptEnable = (LPUART_CTRL_RIE_MASK), /*!< Receiver data register full. */
kLPUART_IdleLineInterruptEnable = (LPUART_CTRL_ILIE_MASK), /*!< Idle line. */
kLPUART_RxOverrunInterruptEnable = (LPUART_CTRL_ORIE_MASK), /*!< Receiver Overrun. */
kLPUART_NoiseErrorInterruptEnable = (LPUART_CTRL_NEIE_MASK), /*!< Noise error flag. */
kLPUART_FramingErrorInterruptEnable = (LPUART_CTRL_FEIE_MASK), /*!< Framing error flag. */
kLPUART_ParityErrorInterruptEnable = (LPUART_CTRL_PEIE_MASK), /*!< Parity error flag. */
#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
kLPUART_TxFifoOverflowInterruptEnable = (LPUART_FIFO_TXOFE_MASK >> 8), /*!< Transmit FIFO Overflow. */
kLPUART_RxFifoUnderflowInterruptEnable = (LPUART_FIFO_RXUFE_MASK >> 8), /*!< Receive FIFO Underflow. */
#endif
};
/*!
* @brief LPUART status flags.
*
* This provides constants for the LPUART status flags for use in the LPUART functions.
*/
enum _lpuart_flags
{
kLPUART_TxDataRegEmptyFlag =
(LPUART_STAT_TDRE_MASK), /*!< Transmit data register empty flag, sets when transmit buffer is empty */
kLPUART_TransmissionCompleteFlag =
(LPUART_STAT_TC_MASK), /*!< Transmission complete flag, sets when transmission activity complete */
kLPUART_RxDataRegFullFlag =
(LPUART_STAT_RDRF_MASK), /*!< Receive data register full flag, sets when the receive data buffer is full */
kLPUART_IdleLineFlag = (LPUART_STAT_IDLE_MASK), /*!< Idle line detect flag, sets when idle line detected */
kLPUART_RxOverrunFlag = (LPUART_STAT_OR_MASK), /*!< Receive Overrun, sets when new data is received before data is
read from receive register */
kLPUART_NoiseErrorFlag = (LPUART_STAT_NF_MASK), /*!< Receive takes 3 samples of each received bit. If any of these
samples differ, noise flag sets */
kLPUART_FramingErrorFlag =
(LPUART_STAT_FE_MASK), /*!< Frame error flag, sets if logic 0 was detected where stop bit expected */
kLPUART_ParityErrorFlag = (LPUART_STAT_PF_MASK), /*!< If parity enabled, sets upon parity error detection */
#if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
kLPUART_LinBreakFlag =
(int)(LPUART_STAT_LBKDIF_MASK), /*!< LIN break detect interrupt flag, sets when LIN break char
detected and LIN circuit enabled */
#endif
kLPUART_RxActiveEdgeFlag =
(LPUART_STAT_RXEDGIF_MASK), /*!< Receive pin active edge interrupt flag, sets when active edge detected */
kLPUART_RxActiveFlag =
(LPUART_STAT_RAF_MASK), /*!< Receiver Active Flag (RAF), sets at beginning of valid start bit */
#if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING
kLPUART_DataMatch1Flag = LPUART_STAT_MA1F_MASK, /*!< The next character to be read from LPUART_DATA matches MA1*/
kLPUART_DataMatch2Flag = LPUART_STAT_MA2F_MASK, /*!< The next character to be read from LPUART_DATA matches MA2*/
#endif
#if defined(FSL_FEATURE_LPUART_HAS_EXTENDED_DATA_REGISTER_FLAGS) && FSL_FEATURE_LPUART_HAS_EXTENDED_DATA_REGISTER_FLAGS
kLPUART_NoiseErrorInRxDataRegFlag =
(LPUART_DATA_NOISY_MASK >> 10), /*!< NOISY bit, sets if noise detected in current data word */
kLPUART_ParityErrorInRxDataRegFlag =
(LPUART_DATA_PARITYE_MASK >> 10), /*!< PARITYE bit, sets if noise detected in current data word */
#endif
#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
kLPUART_TxFifoEmptyFlag = (LPUART_FIFO_TXEMPT_MASK >> 16), /*!< TXEMPT bit, sets if transmit buffer is empty */
kLPUART_RxFifoEmptyFlag = (LPUART_FIFO_RXEMPT_MASK >> 16), /*!< RXEMPT bit, sets if receive buffer is empty */
kLPUART_TxFifoOverflowFlag =
(LPUART_FIFO_TXOF_MASK >> 16), /*!< TXOF bit, sets if transmit buffer overflow occurred */
kLPUART_RxFifoUnderflowFlag =
(LPUART_FIFO_RXUF_MASK >> 16), /*!< RXUF bit, sets if receive buffer underflow occurred */
#endif
};
/*! @brief LPUART configuration structure. */
typedef struct _lpuart_config
{
uint32_t baudRate_Bps; /*!< LPUART baud rate */
lpuart_parity_mode_t parityMode; /*!< Parity mode, disabled (default), even, odd */
lpuart_data_bits_t dataBitsCount; /*!< Data bits count, eight (default), seven */
bool isMsb; /*!< Data bits order, LSB (default), MSB */
#if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT
lpuart_stop_bit_count_t stopBitCount; /*!< Number of stop bits, 1 stop bit (default) or 2 stop bits */
#endif
#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
uint8_t txFifoWatermark; /*!< TX FIFO watermark */
uint8_t rxFifoWatermark; /*!< RX FIFO watermark */
#endif
#if defined(FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT) && FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT
bool enableRxRTS; /*!< RX RTS enable */
bool enableTxCTS; /*!< TX CTS enable */
lpuart_transmit_cts_source_t txCtsSource; /*!< TX CTS source */
lpuart_transmit_cts_config_t txCtsConfig; /*!< TX CTS configure */
#endif
lpuart_idle_type_select_t rxIdleType; /*!< RX IDLE type. */
lpuart_idle_config_t rxIdleConfig; /*!< RX IDLE configuration. */
bool enableTx; /*!< Enable TX */
bool enableRx; /*!< Enable RX */
} lpuart_config_t;
/*! @brief LPUART transfer structure. */
typedef struct _lpuart_transfer
{
uint8_t *data; /*!< The buffer of data to be transfer.*/
size_t dataSize; /*!< The byte count to be transfer. */
} lpuart_transfer_t;
/* Forward declaration of the handle typedef. */
typedef struct _lpuart_handle lpuart_handle_t;
/*! @brief LPUART transfer callback function. */
typedef void (*lpuart_transfer_callback_t)(LPUART_Type *base, lpuart_handle_t *handle, status_t status, void *userData);
/*! @brief LPUART handle structure. */
struct _lpuart_handle
{
uint8_t *volatile txData; /*!< Address of remaining data to send. */
volatile size_t txDataSize; /*!< Size of the remaining data to send. */
size_t txDataSizeAll; /*!< Size of the data to send out. */
uint8_t *volatile rxData; /*!< Address of remaining data to receive. */
volatile size_t rxDataSize; /*!< Size of the remaining data to receive. */
size_t rxDataSizeAll; /*!< Size of the data to receive. */
uint8_t *rxRingBuffer; /*!< Start address of the receiver ring buffer. */
size_t rxRingBufferSize; /*!< Size of the ring buffer. */
volatile uint16_t rxRingBufferHead; /*!< Index for the driver to store received data into ring buffer. */
volatile uint16_t rxRingBufferTail; /*!< Index for the user to get data from the ring buffer. */
lpuart_transfer_callback_t callback; /*!< Callback function. */
void *userData; /*!< LPUART callback function parameter.*/
volatile uint8_t txState; /*!< TX transfer state. */
volatile uint8_t rxState; /*!< RX transfer state. */
#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
bool isSevenDataBits; /*!< Seven data bits flag. */
#endif
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* _cplusplus */
#if defined(FSL_FEATURE_LPUART_HAS_GLOBAL) && FSL_FEATURE_LPUART_HAS_GLOBAL
/*!
* @name Software Reset
* @{
*/
/*!
* @brief Resets the LPUART using software.
*
* This function resets all internal logic and registers except the Global Register.
* Remains set until cleared by software.
*
* @param base LPUART peripheral base address.
*/
static inline void LPUART_SoftwareReset(LPUART_Type *base)
{
base->GLOBAL |= LPUART_GLOBAL_RST_MASK;
base->GLOBAL &= ~LPUART_GLOBAL_RST_MASK;
}
/* @} */
#endif /*FSL_FEATURE_LPUART_HAS_GLOBAL*/
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Initializes an LPUART instance with the user configuration structure and the peripheral clock.
*
* This function configures the LPUART module with user-defined settings. Call the LPUART_GetDefaultConfig() function
* to configure the configuration structure and get the default configuration.
* The example below shows how to use this API to configure the LPUART.
* @code
* lpuart_config_t lpuartConfig;
* lpuartConfig.baudRate_Bps = 115200U;
* lpuartConfig.parityMode = kLPUART_ParityDisabled;
* lpuartConfig.dataBitsCount = kLPUART_EightDataBits;
* lpuartConfig.isMsb = false;
* lpuartConfig.stopBitCount = kLPUART_OneStopBit;
* lpuartConfig.txFifoWatermark = 0;
* lpuartConfig.rxFifoWatermark = 1;
* LPUART_Init(LPUART1, &lpuartConfig, 20000000U);
* @endcode
*
* @param base LPUART peripheral base address.
* @param config Pointer to a user-defined configuration structure.
* @param srcClock_Hz LPUART clock source frequency in HZ.
* @retval kStatus_LPUART_BaudrateNotSupport Baudrate is not support in current clock source.
* @retval kStatus_Success LPUART initialize succeed
*/
status_t LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcClock_Hz);
/*!
* @brief Deinitializes a LPUART instance.
*
* This function waits for transmit to complete, disables TX and RX, and disables the LPUART clock.
*
* @param base LPUART peripheral base address.
*/
void LPUART_Deinit(LPUART_Type *base);
/*!
* @brief Gets the default configuration structure.
*
* This function initializes the LPUART configuration structure to a default value. The default
* values are:
* lpuartConfig->baudRate_Bps = 115200U;
* lpuartConfig->parityMode = kLPUART_ParityDisabled;
* lpuartConfig->dataBitsCount = kLPUART_EightDataBits;
* lpuartConfig->isMsb = false;
* lpuartConfig->stopBitCount = kLPUART_OneStopBit;
* lpuartConfig->txFifoWatermark = 0;
* lpuartConfig->rxFifoWatermark = 1;
* lpuartConfig->rxIdleType = kLPUART_IdleTypeStartBit;
* lpuartConfig->rxIdleConfig = kLPUART_IdleCharacter1;
* lpuartConfig->enableTx = false;
* lpuartConfig->enableRx = false;
*
* @param config Pointer to a configuration structure.
*/
void LPUART_GetDefaultConfig(lpuart_config_t *config);
/*!
* @brief Sets the LPUART instance baudrate.
*
* This function configures the LPUART module baudrate. This function is used to update
* the LPUART module baudrate after the LPUART module is initialized by the LPUART_Init.
* @code
* LPUART_SetBaudRate(LPUART1, 115200U, 20000000U);
* @endcode
*
* @param base LPUART peripheral base address.
* @param baudRate_Bps LPUART baudrate to be set.
* @param srcClock_Hz LPUART clock source frequency in HZ.
* @retval kStatus_LPUART_BaudrateNotSupport Baudrate is not supported in the current clock source.
* @retval kStatus_Success Set baudrate succeeded.
*/
status_t LPUART_SetBaudRate(LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz);
/* @} */
/*!
* @name Status
* @{
*/
/*!
* @brief Gets LPUART status flags.
*
* This function gets all LPUART status flags. The flags are returned as the logical
* OR value of the enumerators @ref _lpuart_flags. To check for a specific status,
* compare the return value with enumerators in the @ref _lpuart_flags.
* For example, to check whether the TX is empty:
* @code
* if (kLPUART_TxDataRegEmptyFlag & LPUART_GetStatusFlags(LPUART1))
* {
* ...
* }
* @endcode
*
* @param base LPUART peripheral base address.
* @return LPUART status flags which are ORed by the enumerators in the _lpuart_flags.
*/
uint32_t LPUART_GetStatusFlags(LPUART_Type *base);
/*!
* @brief Clears status flags with a provided mask.
*
* This function clears LPUART status flags with a provided mask. Automatically cleared flags
* can't be cleared by this function.
* Flags that can only cleared or set by hardware are:
* kLPUART_TxDataRegEmptyFlag, kLPUART_TransmissionCompleteFlag, kLPUART_RxDataRegFullFlag,
* kLPUART_RxActiveFlag, kLPUART_NoiseErrorInRxDataRegFlag, kLPUART_ParityErrorInRxDataRegFlag,
* kLPUART_TxFifoEmptyFlag,kLPUART_RxFifoEmptyFlag
* Note: This API should be called when the Tx/Rx is idle, otherwise it takes no effects.
*
* @param base LPUART peripheral base address.
* @param mask the status flags to be cleared. The user can use the enumerators in the
* _lpuart_status_flag_t to do the OR operation and get the mask.
* @return 0 succeed, others failed.
* @retval kStatus_LPUART_FlagCannotClearManually The flag can't be cleared by this function but
* it is cleared automatically by hardware.
* @retval kStatus_Success Status in the mask are cleared.
*/
status_t LPUART_ClearStatusFlags(LPUART_Type *base, uint32_t mask);
/* @} */
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enables LPUART interrupts according to a provided mask.
*
* This function enables the LPUART interrupts according to a provided mask. The mask
* is a logical OR of enumeration members. See the @ref _lpuart_interrupt_enable.
* This examples shows how to enable TX empty interrupt and RX full interrupt:
* @code
* LPUART_EnableInterrupts(LPUART1,kLPUART_TxDataRegEmptyInterruptEnable | kLPUART_RxDataRegFullInterruptEnable);
* @endcode
*
* @param base LPUART peripheral base address.
* @param mask The interrupts to enable. Logical OR of @ref _uart_interrupt_enable.
*/
void LPUART_EnableInterrupts(LPUART_Type *base, uint32_t mask);
/*!
* @brief Disables LPUART interrupts according to a provided mask.
*
* This function disables the LPUART interrupts according to a provided mask. The mask
* is a logical OR of enumeration members. See @ref _lpuart_interrupt_enable.
* This example shows how to disable the TX empty interrupt and RX full interrupt:
* @code
* LPUART_DisableInterrupts(LPUART1,kLPUART_TxDataRegEmptyInterruptEnable | kLPUART_RxDataRegFullInterruptEnable);
* @endcode
*
* @param base LPUART peripheral base address.
* @param mask The interrupts to disable. Logical OR of @ref _lpuart_interrupt_enable.
*/
void LPUART_DisableInterrupts(LPUART_Type *base, uint32_t mask);
/*!
* @brief Gets enabled LPUART interrupts.
*
* This function gets the enabled LPUART interrupts. The enabled interrupts are returned
* as the logical OR value of the enumerators @ref _lpuart_interrupt_enable. To check
* a specific interrupt enable status, compare the return value with enumerators
* in @ref _lpuart_interrupt_enable.
* For example, to check whether the TX empty interrupt is enabled:
* @code
* uint32_t enabledInterrupts = LPUART_GetEnabledInterrupts(LPUART1);
*
* if (kLPUART_TxDataRegEmptyInterruptEnable & enabledInterrupts)
* {
* ...
* }
* @endcode
*
* @param base LPUART peripheral base address.
* @return LPUART interrupt flags which are logical OR of the enumerators in @ref _lpuart_interrupt_enable.
*/
uint32_t LPUART_GetEnabledInterrupts(LPUART_Type *base);
#if defined(FSL_FEATURE_LPUART_HAS_DMA_ENABLE) && FSL_FEATURE_LPUART_HAS_DMA_ENABLE
/*!
* @brief Gets the LPUART data register address.
*
* This function returns the LPUART data register address, which is mainly used by the DMA/eDMA.
*
* @param base LPUART peripheral base address.
* @return LPUART data register addresses which are used both by the transmitter and receiver.
*/
static inline uint32_t LPUART_GetDataRegisterAddress(LPUART_Type *base)
{
return (uint32_t) & (base->DATA);
}
/*!
* @brief Enables or disables the LPUART transmitter DMA request.
*
* This function enables or disables the transmit data register empty flag, STAT[TDRE], to generate DMA requests.
*
* @param base LPUART peripheral base address.
* @param enable True to enable, false to disable.
*/
static inline void LPUART_EnableTxDMA(LPUART_Type *base, bool enable)
{
if (enable)
{
base->BAUD |= LPUART_BAUD_TDMAE_MASK;
}
else
{
base->BAUD &= ~LPUART_BAUD_TDMAE_MASK;
}
}
/*!
* @brief Enables or disables the LPUART receiver DMA.
*
* This function enables or disables the receiver data register full flag, STAT[RDRF], to generate DMA requests.
*
* @param base LPUART peripheral base address.
* @param enable True to enable, false to disable.
*/
static inline void LPUART_EnableRxDMA(LPUART_Type *base, bool enable)
{
if (enable)
{
base->BAUD |= LPUART_BAUD_RDMAE_MASK;
}
else
{
base->BAUD &= ~LPUART_BAUD_RDMAE_MASK;
}
}
/* @} */
#endif /* FSL_FEATURE_LPUART_HAS_DMA_ENABLE */
/*!
* @name Bus Operations
* @{
*/
/*!
* @brief Get the LPUART instance from peripheral base address.
*
* @param base LPUART peripheral base address.
* @return LPUART instance.
*/
uint32_t LPUART_GetInstance(LPUART_Type *base);
/*!
* @brief Enables or disables the LPUART transmitter.
*
* This function enables or disables the LPUART transmitter.
*
* @param base LPUART peripheral base address.
* @param enable True to enable, false to disable.
*/
static inline void LPUART_EnableTx(LPUART_Type *base, bool enable)
{
if (enable)
{
base->CTRL |= LPUART_CTRL_TE_MASK;
}
else
{
base->CTRL &= ~LPUART_CTRL_TE_MASK;
}
}
/*!
* @brief Enables or disables the LPUART receiver.
*
* This function enables or disables the LPUART receiver.
*
* @param base LPUART peripheral base address.
* @param enable True to enable, false to disable.
*/
static inline void LPUART_EnableRx(LPUART_Type *base, bool enable)
{
if (enable)
{
base->CTRL |= LPUART_CTRL_RE_MASK;
}
else
{
base->CTRL &= ~LPUART_CTRL_RE_MASK;
}
}
/*!
* @brief Writes to the transmitter register.
*
* This function writes data to the transmitter register directly. The upper layer must
* ensure that the TX register is empty or that the TX FIFO has room before calling this function.
*
* @param base LPUART peripheral base address.
* @param data Data write to the TX register.
*/
static inline void LPUART_WriteByte(LPUART_Type *base, uint8_t data)
{
base->DATA = data;
}
/*!
* @brief Reads the receiver register.
*
* This function reads data from the receiver register directly. The upper layer must
* ensure that the receiver register is full or that the RX FIFO has data before calling this function.
*
* @param base LPUART peripheral base address.
* @return Data read from data register.
*/
static inline uint8_t LPUART_ReadByte(LPUART_Type *base)
{
#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
uint32_t ctrl = base->CTRL;
bool isSevenDataBits =
((ctrl & LPUART_CTRL_M7_MASK) ||
((!(ctrl & LPUART_CTRL_M7_MASK)) && (!(ctrl & LPUART_CTRL_M_MASK)) && (ctrl & LPUART_CTRL_PE_MASK)));
if (isSevenDataBits)
{
return (base->DATA & 0x7F);
}
else
{
return base->DATA;
}
#else
return base->DATA;
#endif
}
/*!
* @brief Writes to the transmitter register using a blocking method.
*
* This function polls the transmitter register, waits for the register to be empty or for TX FIFO to have
* room, and writes data to the transmitter buffer.
*
* @note This function does not check whether all data has been sent out to the bus.
* Before disabling the transmitter, check the kLPUART_TransmissionCompleteFlag to ensure that the transmit is
* finished.
*
* @param base LPUART peripheral base address.
* @param data Start address of the data to write.
* @param length Size of the data to write.
*/
void LPUART_WriteBlocking(LPUART_Type *base, const uint8_t *data, size_t length);
/*!
* @brief Reads the receiver data register using a blocking method.
*
* This function polls the receiver register, waits for the receiver register full or receiver FIFO
* has data, and reads data from the TX register.
*
* @param base LPUART peripheral base address.
* @param data Start address of the buffer to store the received data.
* @param length Size of the buffer.
* @retval kStatus_LPUART_RxHardwareOverrun Receiver overrun happened while receiving data.
* @retval kStatus_LPUART_NoiseError Noise error happened while receiving data.
* @retval kStatus_LPUART_FramingError Framing error happened while receiving data.
* @retval kStatus_LPUART_ParityError Parity error happened while receiving data.
* @retval kStatus_Success Successfully received all data.
*/
status_t LPUART_ReadBlocking(LPUART_Type *base, uint8_t *data, size_t length);
/* @} */
/*!
* @name Transactional
* @{
*/
/*!
* @brief Initializes the LPUART handle.
*
* This function initializes the LPUART handle, which can be used for other LPUART
* transactional APIs. Usually, for a specified LPUART instance,
* call this API once to get the initialized handle.
*
* The LPUART driver supports the "background" receiving, which means that user can set up
* an RX ring buffer optionally. Data received is stored into the ring buffer even when the
* user doesn't call the LPUART_TransferReceiveNonBlocking() API. If there is already data received
* in the ring buffer, the user can get the received data from the ring buffer directly.
* The ring buffer is disabled if passing NULL as @p ringBuffer.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param callback Callback function.
* @param userData User data.
*/
void LPUART_TransferCreateHandle(LPUART_Type *base,
lpuart_handle_t *handle,
lpuart_transfer_callback_t callback,
void *userData);
/*!
* @brief Transmits a buffer of data using the interrupt method.
*
* This function send data using an interrupt method. This is a non-blocking function, which
* returns directly without waiting for all data written to the transmitter register. When
* all data is written to the TX register in the ISR, the LPUART driver calls the callback
* function and passes the @ref kStatus_LPUART_TxIdle as status parameter.
*
* @note The kStatus_LPUART_TxIdle is passed to the upper layer when all data are written
* to the TX register. However, there is no check to ensure that all the data sent out. Before disabling the TX,
* check the kLPUART_TransmissionCompleteFlag to ensure that the transmit is finished.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param xfer LPUART transfer structure, see #lpuart_transfer_t.
* @retval kStatus_Success Successfully start the data transmission.
* @retval kStatus_LPUART_TxBusy Previous transmission still not finished, data not all written to the TX register.
* @retval kStatus_InvalidArgument Invalid argument.
*/
status_t LPUART_TransferSendNonBlocking(LPUART_Type *base, lpuart_handle_t *handle, lpuart_transfer_t *xfer);
/*!
* @brief Sets up the RX ring buffer.
*
* This function sets up the RX ring buffer to a specific UART handle.
*
* When the RX ring buffer is used, data received is stored into the ring buffer even when
* the user doesn't call the UART_TransferReceiveNonBlocking() API. If there is already data received
* in the ring buffer, the user can get the received data from the ring buffer directly.
*
* @note When using RX ring buffer, one byte is reserved for internal use. In other
* words, if @p ringBufferSize is 32, then only 31 bytes are used for saving data.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param ringBuffer Start address of ring buffer for background receiving. Pass NULL to disable the ring buffer.
* @param ringBufferSize size of the ring buffer.
*/
void LPUART_TransferStartRingBuffer(LPUART_Type *base,
lpuart_handle_t *handle,
uint8_t *ringBuffer,
size_t ringBufferSize);
/*!
* @brief Aborts the background transfer and uninstalls the ring buffer.
*
* This function aborts the background transfer and uninstalls the ring buffer.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
*/
void LPUART_TransferStopRingBuffer(LPUART_Type *base, lpuart_handle_t *handle);
/*!
* @brief Get the length of received data in RX ring buffer.
*
* @param handle LPUART handle pointer.
* @return Length of received data in RX ring buffer.
*/
size_t LPUART_TransferGetRxRingBufferLength(LPUART_Type *base, lpuart_handle_t *handle);
/*!
* @brief Aborts the interrupt-driven data transmit.
*
* This function aborts the interrupt driven data sending. The user can get the remainBtyes to find out
* how many bytes are not sent out.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
*/
void LPUART_TransferAbortSend(LPUART_Type *base, lpuart_handle_t *handle);
/*!
* @brief Gets the number of bytes that have been written to the LPUART transmitter register.
*
* This function gets the number of bytes that have been written to LPUART TX
* register by an interrupt method.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param count Send bytes count.
* @retval kStatus_NoTransferInProgress No send in progress.
* @retval kStatus_InvalidArgument Parameter is invalid.
* @retval kStatus_Success Get successfully through the parameter \p count;
*/
status_t LPUART_TransferGetSendCount(LPUART_Type *base, lpuart_handle_t *handle, uint32_t *count);
/*!
* @brief Receives a buffer of data using the interrupt method.
*
* This function receives data using an interrupt method. This is a non-blocking function
* which returns without waiting to ensure that all data are received.
* If the RX ring buffer is used and not empty, the data in the ring buffer is copied and
* the parameter @p receivedBytes shows how many bytes are copied from the ring buffer.
* After copying, if the data in the ring buffer is not enough for read, the receive
* request is saved by the LPUART driver. When the new data arrives, the receive request
* is serviced first. When all data is received, the LPUART driver notifies the upper layer
* through a callback function and passes a status parameter @ref kStatus_UART_RxIdle.
* For example, the upper layer needs 10 bytes but there are only 5 bytes in ring buffer.
* The 5 bytes are copied to xfer->data, which returns with the
* parameter @p receivedBytes set to 5. For the remaining 5 bytes, the newly arrived data is
* saved from xfer->data[5]. When 5 bytes are received, the LPUART driver notifies the upper layer.
* If the RX ring buffer is not enabled, this function enables the RX and RX interrupt
* to receive data to xfer->data. When all data is received, the upper layer is notified.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param xfer LPUART transfer structure, see #uart_transfer_t.
* @param receivedBytes Bytes received from the ring buffer directly.
* @retval kStatus_Success Successfully queue the transfer into the transmit queue.
* @retval kStatus_LPUART_RxBusy Previous receive request is not finished.
* @retval kStatus_InvalidArgument Invalid argument.
*/
status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base,
lpuart_handle_t *handle,
lpuart_transfer_t *xfer,
size_t *receivedBytes);
/*!
* @brief Aborts the interrupt-driven data receiving.
*
* This function aborts the interrupt-driven data receiving. The user can get the remainBytes to find out
* how many bytes not received yet.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
*/
void LPUART_TransferAbortReceive(LPUART_Type *base, lpuart_handle_t *handle);
/*!
* @brief Gets the number of bytes that have been received.
*
* This function gets the number of bytes that have been received.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param count Receive bytes count.
* @retval kStatus_NoTransferInProgress No receive in progress.
* @retval kStatus_InvalidArgument Parameter is invalid.
* @retval kStatus_Success Get successfully through the parameter \p count;
*/
status_t LPUART_TransferGetReceiveCount(LPUART_Type *base, lpuart_handle_t *handle, uint32_t *count);
/*!
* @brief LPUART IRQ handle function.
*
* This function handles the LPUART transmit and receive IRQ request.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
*/
void LPUART_TransferHandleIRQ(LPUART_Type *base, lpuart_handle_t *handle);
/*!
* @brief LPUART Error IRQ handle function.
*
* This function handles the LPUART error IRQ request.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
*/
void LPUART_TransferHandleErrorIRQ(LPUART_Type *base, lpuart_handle_t *handle);
/* @} */
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_LPUART_H_ */
@@ -0,0 +1,830 @@
/*
* Copyright 2017-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_SEMC_H_
#define _FSL_SEMC_H_
#include "fsl_common.h"
/*!
* @addtogroup semc
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief SEMC driver version 2.0.4. */
#define FSL_SEMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 4))
/*@}*/
/*! @brief SEMC status. */
enum _semc_status
{
kStatus_SEMC_InvalidDeviceType = MAKE_STATUS(kStatusGroup_SEMC, 0),
kStatus_SEMC_IpCommandExecutionError = MAKE_STATUS(kStatusGroup_SEMC, 1),
kStatus_SEMC_AxiCommandExecutionError = MAKE_STATUS(kStatusGroup_SEMC, 2),
kStatus_SEMC_InvalidMemorySize = MAKE_STATUS(kStatusGroup_SEMC, 3),
kStatus_SEMC_InvalidIpcmdDataSize = MAKE_STATUS(kStatusGroup_SEMC, 4),
kStatus_SEMC_InvalidAddressPortWidth = MAKE_STATUS(kStatusGroup_SEMC, 5),
kStatus_SEMC_InvalidDataPortWidth = MAKE_STATUS(kStatusGroup_SEMC, 6),
kStatus_SEMC_InvalidSwPinmuxSelection = MAKE_STATUS(kStatusGroup_SEMC, 7),
kStatus_SEMC_InvalidBurstLength = MAKE_STATUS(kStatusGroup_SEMC, 8),
kStatus_SEMC_InvalidColumnAddressBitWidth = MAKE_STATUS(kStatusGroup_SEMC, 9),
kStatus_SEMC_InvalidBaseAddress = MAKE_STATUS(kStatusGroup_SEMC, 10),
kStatus_SEMC_InvalidTimerSetting = MAKE_STATUS(kStatusGroup_SEMC, 11),
};
/*! @brief SEMC memory device type. */
typedef enum _semc_mem_type
{
kSEMC_MemType_SDRAM = 0, /*!< SDRAM */
kSEMC_MemType_SRAM, /*!< SRAM */
kSEMC_MemType_NOR, /*!< NOR */
kSEMC_MemType_NAND, /*!< NAND */
kSEMC_MemType_8080 /*!< 8080. */
} semc_mem_type_t;
/*! @brief SEMC WAIT/RDY polarity. */
typedef enum _semc_waitready_polarity
{
kSEMC_LowActive = 0, /*!< Low active. */
kSEMC_HighActive, /*!< High active. */
} semc_waitready_polarity_t;
/*! @brief SEMC SDRAM Chip selection . */
typedef enum _semc_sdram_cs
{
kSEMC_SDRAM_CS0 = 0, /*!< SEMC SDRAM CS0. */
kSEMC_SDRAM_CS1, /*!< SEMC SDRAM CS1. */
kSEMC_SDRAM_CS2, /*!< SEMC SDRAM CS2. */
kSEMC_SDRAM_CS3 /*!< SEMC SDRAM CS3. */
} semc_sdram_cs_t;
/*! @brief SEMC NAND device type. */
typedef enum _semc_nand_access_type
{
kSEMC_NAND_ACCESS_BY_AXI = 0,
kSEMC_NAND_ACCESS_BY_IPCMD,
} semc_nand_access_type_t;
/*! @brief SEMC interrupts . */
typedef enum _semc_interrupt_enable
{
kSEMC_IPCmdDoneInterrupt = SEMC_INTEN_IPCMDDONEEN_MASK, /*!< Ip command done interrupt. */
kSEMC_IPCmdErrInterrupt = SEMC_INTEN_IPCMDERREN_MASK, /*!< Ip command error interrupt. */
kSEMC_AXICmdErrInterrupt = SEMC_INTEN_AXICMDERREN_MASK, /*!< AXI command error interrupt. */
kSEMC_AXIBusErrInterrupt = SEMC_INTEN_AXIBUSERREN_MASK /*!< AXI bus error interrupt. */
} semc_interrupt_enable_t;
/*! @brief SEMC IP command data size in bytes. */
typedef enum _semc_ipcmd_datasize
{
kSEMC_IPcmdDataSize_1bytes = 1, /*!< The IP command data size 1 byte. */
kSEMC_IPcmdDataSize_2bytes, /*!< The IP command data size 2 byte. */
kSEMC_IPcmdDataSize_3bytes, /*!< The IP command data size 3 byte. */
kSEMC_IPcmdDataSize_4bytes /*!< The IP command data size 4 byte. */
} semc_ipcmd_datasize_t;
/*! @brief SEMC auto-refresh timing. */
typedef enum _semc_refresh_time
{
kSEMC_RefreshThreeClocks = 0x0U, /*!< The refresh timing with three bus clocks. */
kSEMC_RefreshSixClocks, /*!< The refresh timing with six bus clocks. */
kSEMC_RefreshNineClocks /*!< The refresh timing with nine bus clocks. */
} semc_refresh_time_t;
/*! @brief CAS latency */
typedef enum _semc_caslatency
{
kSEMC_LatencyOne = 1, /*!< Latency 1. */
kSEMC_LatencyTwo, /*!< Latency 2. */
kSEMC_LatencyThree, /*!< Latency 3. */
} semc_caslatency_t;
/*! @brief SEMC sdram column address bit number. */
typedef enum _semc_sdram_column_bit_num
{
kSEMC_SdramColunm_12bit = 0x0U, /*!< 12 bit. */
kSEMC_SdramColunm_11bit, /*!< 11 bit. */
kSEMC_SdramColunm_10bit, /*!< 10 bit. */
kSEMC_SdramColunm_9bit, /*!< 9 bit. */
} semc_sdram_column_bit_num_t;
/*! @brief SEMC sdram burst length. */
typedef enum _semc_sdram_burst_len
{
kSEMC_Sdram_BurstLen1 = 0, /*!< Burst length 1*/
kSEMC_Sdram_BurstLen2, /*!< Burst length 2*/
kSEMC_Sdram_BurstLen4, /*!< Burst length 4*/
kSEMC_Sdram_BurstLen8 /*!< Burst length 8*/
} sem_sdram_burst_len_t;
/*! @brief SEMC nand column address bit number. */
typedef enum _semc_nand_column_bit_num
{
kSEMC_NandColum_16bit = 0x0U, /*!< 16 bit. */
kSEMC_NandColum_15bit, /*!< 15 bit. */
kSEMC_NandColum_14bit, /*!< 14 bit. */
kSEMC_NandColum_13bit, /*!< 13 bit. */
kSEMC_NandColum_12bit, /*!< 12 bit. */
kSEMC_NandColum_11bit, /*!< 11 bit. */
kSEMC_NandColum_10bit, /*!< 10 bit. */
kSEMC_NandColum_9bit, /*!< 9 bit. */
} semc_nand_column_bit_num_t;
/*! @brief SEMC nand burst length. */
typedef enum _semc_nand_burst_len
{
kSEMC_Nand_BurstLen1 = 0, /*!< Burst length 1*/
kSEMC_Nand_BurstLen2, /*!< Burst length 2*/
kSEMC_Nand_BurstLen4, /*!< Burst length 4*/
kSEMC_Nand_BurstLen8, /*!< Burst length 8*/
kSEMC_Nand_BurstLen16, /*!< Burst length 16*/
kSEMC_Nand_BurstLen32, /*!< Burst length 32*/
kSEMC_Nand_BurstLen64 /*!< Burst length 64*/
} sem_nand_burst_len_t;
/*! @brief SEMC nor/sram column address bit number. */
typedef enum _semc_norsram_column_bit_num
{
kSEMC_NorColum_12bit = 0x0U, /*!< 12 bit. */
kSEMC_NorColum_11bit, /*!< 11 bit. */
kSEMC_NorColum_10bit, /*!< 10 bit. */
kSEMC_NorColum_9bit, /*!< 9 bit. */
kSEMC_NorColum_8bit, /*!< 8 bit. */
kSEMC_NorColum_7bit, /*!< 7 bit. */
kSEMC_NorColum_6bit, /*!< 6 bit. */
kSEMC_NorColum_5bit, /*!< 5 bit. */
kSEMC_NorColum_4bit, /*!< 4 bit. */
kSEMC_NorColum_3bit, /*!< 3 bit. */
kSEMC_NorColum_2bit /*!< 2 bit. */
} semc_norsram_column_bit_num_t;
/*! @brief SEMC nor/sram burst length. */
typedef enum _semc_norsram_burst_len
{
kSEMC_Nor_BurstLen1 = 0, /*!< Burst length 1*/
kSEMC_Nor_BurstLen2, /*!< Burst length 2*/
kSEMC_Nor_BurstLen4, /*!< Burst length 4*/
kSEMC_Nor_BurstLen8, /*!< Burst length 8*/
kSEMC_Nor_BurstLen16, /*!< Burst length 16*/
kSEMC_Nor_BurstLen32, /*!< Burst length 32*/
kSEMC_Nor_BurstLen64 /*!< Burst length 64*/
} sem_norsram_burst_len_t;
/*! @brief SEMC dbi column address bit number. */
typedef enum _semc_dbi_column_bit_num
{
kSEMC_Dbi_Colum_12bit = 0x0U, /*!< 12 bit. */
kSEMC_Dbi_Colum_11bit, /*!< 11 bit. */
kSEMC_Dbi_Colum_10bit, /*!< 10 bit. */
kSEMC_Dbi_Colum_9bit, /*!< 9 bit. */
kSEMC_Dbi_Colum_8bit, /*!< 8 bit. */
kSEMC_Dbi_Colum_7bit, /*!< 7 bit. */
kSEMC_Dbi_Colum_6bit, /*!< 6 bit. */
kSEMC_Dbi_Colum_5bit, /*!< 5 bit. */
kSEMC_Dbi_Colum_4bit, /*!< 4 bit. */
kSEMC_Dbi_Colum_3bit, /*!< 3 bit. */
kSEMC_Dbi_Colum_2bit /*!< 2 bit. */
} semc_dbi_column_bit_num_t;
/*! @brief SEMC dbi burst length. */
typedef enum _semc_dbi_burst_len
{
kSEMC_Dbi_BurstLen1 = 0, /*!< Burst length 1*/
kSEMC_Dbi_BurstLen2, /*!< Burst length 2*/
kSEMC_Dbi_Dbi_BurstLen4, /*!< Burst length 4*/
kSEMC_Dbi_BurstLen8, /*!< Burst length 8*/
kSEMC_Dbi_BurstLen16, /*!< Burst length 16*/
kSEMC_Dbi_BurstLen32, /*!< Burst length 32*/
kSEMC_Dbi_BurstLen64 /*!< Burst length 64*/
} sem_dbi_burst_len_t;
/*! @brief SEMC IOMUXC. */
typedef enum _semc_iomux_pin
{
kSEMC_MUXA8 = SEMC_IOCR_MUX_A8_SHIFT, /*!< MUX A8 pin. */
kSEMC_MUXCSX0 = SEMC_IOCR_MUX_CSX0_SHIFT, /*!< MUX CSX0 pin */
kSEMC_MUXCSX1 = SEMC_IOCR_MUX_CSX1_SHIFT, /*!< MUX CSX1 Pin.*/
kSEMC_MUXCSX2 = SEMC_IOCR_MUX_CSX2_SHIFT, /*!< MUX CSX2 Pin. */
kSEMC_MUXCSX3 = SEMC_IOCR_MUX_CSX3_SHIFT, /*!< MUX CSX3 Pin. */
kSEMC_MUXRDY = SEMC_IOCR_MUX_RDY_SHIFT /*!< MUX RDY pin. */
} semc_iomux_pin;
/*! @brief SEMC NOR/PSRAM Address bit 27 A27. */
typedef enum _semc_iomux_nora27_pin
{
kSEMC_MORA27_NONE = 0, /*!< No NOR/SRAM A27 pin. */
kSEMC_NORA27_MUXCSX3 = SEMC_IOCR_MUX_CSX3_SHIFT, /*!< MUX CSX3 Pin. */
kSEMC_NORA27_MUXRDY = SEMC_IOCR_MUX_RDY_SHIFT /*!< MUX RDY pin. */
} semc_iomux_nora27_pin;
/*! @brief SEMC port size. */
typedef enum _semc_port_size
{
kSEMC_PortSize8Bit = 0, /*!< 8-Bit port size. */
kSEMC_PortSize16Bit /*!< 16-Bit port size. */
} smec_port_size_t;
/*! @brief SEMC address mode. */
typedef enum _semc_addr_mode
{
kSEMC_AddrDataMux = 0, /*!< SEMC address/data mux mode. */
kSEMC_AdvAddrdataMux, /*!< Advanced address/data mux mode. */
kSEMC_AddrDataNonMux /*!< Address/data non-mux mode. */
} semc_addr_mode_t;
/*! @brief SEMC DQS read strobe mode. */
typedef enum _semc_dqs_mode
{
kSEMC_Loopbackinternal = 0, /*!< Dummy read strobe loopbacked internally. */
kSEMC_Loopbackdqspad, /*!< Dummy read strobe loopbacked from DQS pad. */
} semc_dqs_mode_t;
/*! @brief SEMC ADV signal active polarity. */
typedef enum _semc_adv_polarity
{
kSEMC_AdvActiveLow = 0, /*!< Adv active low. */
kSEMC_AdvActivehigh, /*!< Adv active low. */
} semc_adv_polarity_t;
/*! @brief SEMC RDY signal active polarity. */
typedef enum _semc_rdy_polarity
{
kSEMC_RdyActiveLow = 0, /*!< Adv active low. */
kSEMC_RdyActivehigh, /*!< Adv active low. */
} semc_rdy_polarity_t;
/*! @brief SEMC IP command for NAND: address mode. */
typedef enum _semc_ipcmd_nand_addrmode
{
kSEMC_NANDAM_ColumnRow = 0x0U, /*!< Address mode: column and row address(5Byte-CA0/CA1/RA0/RA1/RA2). */
kSEMC_NANDAM_ColumnCA0, /*!< Address mode: column address only(1 Byte-CA0). */
kSEMC_NANDAM_ColumnCA0CA1, /*!< Address mode: column address only(2 Byte-CA0/CA1). */
kSEMC_NANDAM_RawRA0, /*!< Address mode: row address only(1 Byte-RA0). */
kSEMC_NANDAM_RawRA0RA1, /*!< Address mode: row address only(2 Byte-RA0/RA1). */
kSEMC_NANDAM_RawRA0RA1RA2 /*!< Address mode: row address only(3 Byte-RA0). */
} semc_ipcmd_nand_addrmode_t;
/*! @brief SEMC IP command for NAND command mode. */
typedef enum _semc_ipcmd_nand_cmdmode
{
kSEMC_NANDCM_Command = 0x2U, /*!< command. */
kSEMC_NANDCM_CommandHold, /*!< Command hold. */
kSEMC_NANDCM_CommandAddress, /*!< Command address. */
kSEMC_NANDCM_CommandAddressHold, /*!< Command address hold. */
kSEMC_NANDCM_CommandAddressRead, /*!< Command address read. */
kSEMC_NANDCM_CommandAddressWrite, /*!< Command address write. */
kSEMC_NANDCM_CommandRead, /*!< Command read. */
kSEMC_NANDCM_CommandWrite, /*!< Command write. */
kSEMC_NANDCM_Read, /*!< Read. */
kSEMC_NANDCM_Write /*!< Write. */
} semc_ipcmd_nand_cmdmode_t;
/*! @brief SEMC NAND address option. */
typedef enum _semc_nand_address_option
{
kSEMC_NandAddrOption_5byte_CA2RA3 = 0U, /*!< CA0+CA1+RA0+RA1+RA2 */
kSEMC_NandAddrOption_4byte_CA2RA2 = 2U, /*!< CA0+CA1+RA0+RA1 */
kSEMC_NandAddrOption_3byte_CA2RA1 = 4U, /*!< CA0+CA1+RA0 */
kSEMC_NandAddrOption_4byte_CA1RA3 = 1U, /*!< CA0+RA0+RA1+RA2 */
kSEMC_NandAddrOption_3byte_CA1RA2 = 3U, /*!< CA0+RA0+RA1 */
kSEMC_NandAddrOption_2byte_CA1RA1 = 7U, /*!< CA0+RA0 */
} semc_nand_address_option_t;
/*! @brief SEMC IP command for NOR. */
typedef enum _semc_ipcmd_nor_dbi
{
kSEMC_NORDBICM_Read = 0x2U, /*!< NOR read. */
kSEMC_NORDBICM_Write /*!< NOR write. */
} semc_ipcmd_nor_dbi_t;
/*! @brief SEMC IP command for SRAM. */
typedef enum _semc_ipcmd_sram
{
kSEMC_SRAMCM_ArrayRead = 0x2U, /*!< SRAM memory array read. */
kSEMC_SRAMCM_ArrayWrite, /*!< SRAM memory array write. */
kSEMC_SRAMCM_RegRead, /*!< SRAM memory register read. */
kSEMC_SRAMCM_RegWrite /*!< SRAM memory register write. */
} semc_ipcmd_sram_t;
/*! @brief SEMC IP command for SDARM. */
typedef enum _semc_ipcmd_sdram
{
kSEMC_SDRAMCM_Read = 0x8U, /*!< SDRAM memory read. */
kSEMC_SDRAMCM_Write, /*!< SDRAM memory write. */
kSEMC_SDRAMCM_Modeset, /*!< SDRAM MODE SET. */
kSEMC_SDRAMCM_Active, /*!< SDRAM active. */
kSEMC_SDRAMCM_AutoRefresh, /*!< SDRAM auto-refresh. */
kSEMC_SDRAMCM_SelfRefresh, /*!< SDRAM self-refresh. */
kSEMC_SDRAMCM_Precharge, /*!< SDRAM precharge. */
kSEMC_SDRAMCM_Prechargeall /*!< SDRAM precharge all. */
} semc_ipcmd_sdram_t;
/*! @brief SEMC SDRAM configuration structure.
*
* 1. The memory size in the configuration is in the unit of KB. So memsize_kbytes
* should be set as 2^2, 2^3, 2^4 .etc which is base 2KB exponential function.
* Take refer to BR0~BR3 register in RM for details.
* 2. The prescalePeriod_N16Cycle is in unit of 16 clock cycle. It is a exception for prescaleTimer_n16cycle = 0,
* it means the prescaler timer period is 256 * 16 clock cycles. For precalerIf precalerTimer_n16cycle not equal to 0,
* The prescaler timer period is prescalePeriod_N16Cycle * 16 clock cycles.
* idleTimeout_NprescalePeriod, refreshUrgThreshold_NprescalePeriod, refreshPeriod_NprescalePeriod are
* similar to prescalePeriod_N16Cycle.
*
*/
typedef struct _semc_sdram_config
{
semc_iomux_pin csxPinMux; /*!< CS pin mux. The kSEMC_MUXA8 is not valid in sdram pin mux setting. */
uint32_t address; /*!< The base address. */
uint32_t memsize_kbytes; /*!< The memory size in unit of kbytes. */
smec_port_size_t portSize; /*!< Port size. */
sem_sdram_burst_len_t burstLen; /*!< Burst length. */
semc_sdram_column_bit_num_t columnAddrBitNum; /*!< Column address bit number. */
semc_caslatency_t casLatency; /*!< CAS latency. */
uint8_t tPrecharge2Act_Ns; /*!< Precharge to active wait time in unit of nanosecond. */
uint8_t tAct2ReadWrite_Ns; /*!< Act to read/write wait time in unit of nanosecond. */
uint8_t tRefreshRecovery_Ns; /*!< Refresh recovery time in unit of nanosecond. */
uint8_t tWriteRecovery_Ns; /*!< write recovery time in unit of nanosecond. */
uint8_t tCkeOff_Ns; /*!< CKE off minimum time in unit of nanosecond. */
uint8_t tAct2Prechage_Ns; /*!< Active to precharge in unit of nanosecond. */
uint8_t tSelfRefRecovery_Ns; /*!< Self refresh recovery time in unit of nanosecond. */
uint8_t tRefresh2Refresh_Ns; /*!< Refresh to refresh wait time in unit of nanosecond. */
uint8_t tAct2Act_Ns; /*!< Active to active wait time in unit of nanosecond. */
uint32_t tPrescalePeriod_Ns; /*!< Prescaler timer period should not be larger than 256 * 16 * clock cycle. */
uint32_t tIdleTimeout_Ns; /*!< Idle timeout in unit of prescale time period. */
uint32_t refreshPeriod_nsPerRow; /*!< Refresh timer period like 64ms * 1000000/8192 . */
uint32_t refreshUrgThreshold; /*!< Refresh urgent threshold. */
uint8_t refreshBurstLen; /*!< Refresh burst length. */
} semc_sdram_config_t;
/*! @brief SEMC NAND device timing configuration structure. */
typedef struct _semc_nand_timing_config
{
uint8_t tCeSetup_Ns; /*!< CE setup time: tCS. */
uint8_t tCeHold_Ns; /*!< CE hold time: tCH. */
uint8_t tCeInterval_Ns; /*!< CE interval time:tCEITV. */
uint8_t tWeLow_Ns; /*!< WE low time: tWP. */
uint8_t tWeHigh_Ns; /*!< WE high time: tWH. */
uint8_t tReLow_Ns; /*!< RE low time: tRP. */
uint8_t tReHigh_Ns; /*!< RE high time: tREH. */
uint8_t tTurnAround_Ns; /*!< Turnaround time for async mode: tTA. */
uint8_t tWehigh2Relow_Ns; /*!< WE# high to RE# wait time: tWHR. */
uint8_t tRehigh2Welow_Ns; /*!< RE# high to WE# low wait time: tRHW. */
uint8_t tAle2WriteStart_Ns; /*!< ALE to write start wait time: tADL. */
uint8_t tReady2Relow_Ns; /*!< Ready to RE# low min wait time: tRR. */
uint8_t tWehigh2Busy_Ns; /*!< WE# high to busy wait time: tWB. */
} semc_nand_timing_config_t;
/*! @brief SEMC NAND configuration structure. */
typedef struct _semc_nand_config
{
semc_iomux_pin cePinMux; /*!< The CE pin mux setting. The kSEMC_MUXRDY is not valid for CE pin setting. */
uint32_t axiAddress; /*!< The base address for AXI nand. */
uint32_t axiMemsize_kbytes; /*!< The memory size in unit of kbytes for AXI nand. */
uint32_t ipgAddress; /*!< The base address for IPG nand . */
uint32_t ipgMemsize_kbytes; /*!< The memory size in unit of kbytes for IPG nand. */
semc_rdy_polarity_t rdyactivePolarity; /*!< Wait ready polarity. */
bool edoModeEnabled; /*!< EDO mode enabled. */
semc_nand_column_bit_num_t columnAddrBitNum; /*!< Column address bit number. */
semc_nand_address_option_t arrayAddrOption; /*!< Address option. */
sem_nand_burst_len_t burstLen; /*!< Burst length. */
smec_port_size_t portSize; /*!< Port size. */
semc_nand_timing_config_t *timingConfig; /*!< SEMC nand timing configuration. */
} semc_nand_config_t;
/*! @brief SEMC NOR configuration structure. */
typedef struct _semc_nor_config
{
semc_iomux_pin cePinMux; /*!< The CE# pin mux setting. */
semc_iomux_nora27_pin addr27; /*!< The Addr bit 27 pin mux setting. */
uint32_t address; /*!< The base address. */
uint32_t memsize_kbytes; /*!< The memory size in unit of kbytes. */
uint8_t addrPortWidth; /*!< The address port width. */
semc_rdy_polarity_t rdyactivePolarity; /*!< Wait ready polarity. */
semc_adv_polarity_t advActivePolarity; /*!< ADV# polarity. */
semc_norsram_column_bit_num_t columnAddrBitNum; /*!< Column address bit number. */
semc_addr_mode_t addrMode; /*!< Address mode. */
sem_norsram_burst_len_t burstLen; /*!< Burst length. */
smec_port_size_t portSize; /*!< Port size. */
uint8_t tCeSetup_Ns; /*!< The CE setup time. */
uint8_t tCeHold_Ns; /*!< The CE hold time. */
uint8_t tCeInterval_Ns; /*!< CE interval minimum time. */
uint8_t tAddrSetup_Ns; /*!< The address setup time. */
uint8_t tAddrHold_Ns; /*!< The address hold time. */
uint8_t tWeLow_Ns; /*!< WE low time for async mode. */
uint8_t tWeHigh_Ns; /*!< WE high time for async mode. */
uint8_t tReLow_Ns; /*!< RE low time for async mode. */
uint8_t tReHigh_Ns; /*!< RE high time for async mode. */
uint8_t tTurnAround_Ns; /*!< Turnaround time for async mode. */
uint8_t tAddr2WriteHold_Ns; /*!< Address to write data hold time for async mode. */
#if defined(FSL_FEATURE_SEMC_HAS_NOR_WDS_TIME) && (FSL_FEATURE_SEMC_HAS_NOR_WDS_TIME)
uint8_t tWriteSetup_Ns; /*!< Write data setup time for sync mode.*/
#endif
#if defined(FSL_FEATURE_SEMC_HAS_NOR_WDH_TIME) && (FSL_FEATURE_SEMC_HAS_NOR_WDH_TIME)
uint8_t tWriteHold_Ns; /*!< Write hold time for sync mode. */
#endif
uint8_t latencyCount; /*!< Latency count for sync mode. */
uint8_t readCycle; /*!< Read cycle time for sync mode. */
} semc_nor_config_t;
/*! @brief SEMC SRAM configuration structure. */
typedef struct _semc_sram_config
{
semc_iomux_pin cePinMux; /*!< The CE# pin mux setting. */
semc_iomux_nora27_pin addr27; /*!< The Addr bit 27 pin mux setting. */
uint32_t address; /*!< The base address. */
uint32_t memsize_kbytes; /*!< The memory size in unit of kbytes. */
uint8_t addrPortWidth; /*!< The address port width. */
semc_adv_polarity_t advActivePolarity; /*!< ADV# polarity 1: active high, 0: active low. */
semc_addr_mode_t addrMode; /*!< Address mode. */
sem_norsram_burst_len_t burstLen; /*!< Burst length. */
smec_port_size_t portSize; /*!< Port size. */
uint8_t tCeSetup_Ns; /*!< The CE setup time. */
uint8_t tCeHold_Ns; /*!< The CE hold time. */
uint8_t tCeInterval_Ns; /*!< CE interval minimum time. */
uint8_t tAddrSetup_Ns; /*!< The address setup time. */
uint8_t tAddrHold_Ns; /*!< The address hold time. */
uint8_t tWeLow_Ns; /*!< WE low time for async mode. */
uint8_t tWeHigh_Ns; /*!< WE high time for async mode. */
uint8_t tReLow_Ns; /*!< RE low time for async mode. */
uint8_t tReHigh_Ns; /*!< RE high time for async mode. */
uint8_t tTurnAround_Ns; /*!< Turnaround time for async mode. */
uint8_t tAddr2WriteHold_Ns; /*!< Address to write data hold time for async mode. */
uint8_t tWriteSetup_Ns; /*!< Write data setup time for sync mode.*/
uint8_t tWriteHold_Ns; /*!< Write hold time for sync mode. */
uint8_t latencyCount; /*!< Latency count for sync mode. */
uint8_t readCycle; /*!< Read cycle time for sync mode. */
} semc_sram_config_t;
/*! @brief SEMC DBI configuration structure. */
typedef struct _semc_dbi_config
{
semc_iomux_pin csxPinMux; /*!< The CE# pin mux. */
uint32_t address; /*!< The base address. */
uint32_t memsize_kbytes; /*!< The memory size in unit of 4kbytes. */
semc_dbi_column_bit_num_t columnAddrBitNum; /*!< Column address bit number. */
sem_dbi_burst_len_t burstLen; /*!< Burst length. */
smec_port_size_t portSize; /*!< Port size. */
uint8_t tCsxSetup_Ns; /*!< The CSX setup time. */
uint8_t tCsxHold_Ns; /*!< The CSX hold time. */
uint8_t tWexLow_Ns; /*!< WEX low time. */
uint8_t tWexHigh_Ns; /*!< WEX high time. */
uint8_t tRdxLow_Ns; /*!< RDX low time. */
uint8_t tRdxHigh_Ns; /*!< RDX high time. */
uint8_t tCsxInterval_Ns; /*!< Write data setup time.*/
} semc_dbi_config_t;
/*! @brief SEMC AXI queue a weight setting structure. */
typedef struct _semc_queuea_weight_struct
{
uint32_t qos : 4; /*!< weight of qos for queue 0 . */
uint32_t aging : 4; /*!< weight of aging for queue 0.*/
uint32_t slaveHitSwith : 8; /*!< weight of read/write switch for queue 0.*/
uint32_t slaveHitNoswitch : 8; /*!< weight of read/write no switch for queue 0 .*/
} semc_queuea_weight_struct_t;
/*! @brief SEMC AXI queue a weight setting union. */
typedef union _semc_queuea_weight
{
semc_queuea_weight_struct_t queueaConfig; /*!< Structure configuration for queueA. */
uint32_t queueaValue; /*!< Configuration value for queueA which could directly write to the reg. */
} semc_queuea_weight_t;
/*! @brief SEMC AXI queue b weight setting structure. */
typedef struct _semc_queueb_weight_struct
{
uint32_t qos : 4; /*!< weight of qos for queue 1. */
uint32_t aging : 4; /*!< weight of aging for queue 1.*/
uint32_t slaveHitSwith : 8; /*!< weight of read/write switch for queue 1.*/
uint32_t weightPagehit : 8; /*!< weight of page hit for queue 1 only .*/
uint32_t bankRotation : 8; /*!< weight of bank rotation for queue 1 only .*/
} semc_queueb_weight_struct_t;
/*! @brief SEMC AXI queue b weight setting union. */
typedef union _semc_queueb_weight
{
semc_queueb_weight_struct_t queuebConfig; /*!< Structure configuration for queueB. */
uint32_t queuebValue; /*!< Configuration value for queueB which could directly write to the reg. */
} semc_queueb_weight_t;
/*! @brief SEMC AXI queue weight setting. */
typedef struct _semc_axi_queueweight
{
semc_queuea_weight_t queueaWeight; /*!< Weight settings for queue a. */
semc_queueb_weight_t queuebWeight; /*!< Weight settings for queue b. */
} semc_axi_queueweight_t;
/*!
* @brief SEMC configuration structure.
*
* busTimeoutCycles: when busTimeoutCycles is zero, the bus timeout cycle is
* 255*1024. otherwise the bus timeout cycles is busTimeoutCycles*1024.
* cmdTimeoutCycles: is used for command execution timeout cycles. it's
* similar to the busTimeoutCycles.
*/
typedef struct _semc_config_t
{
semc_dqs_mode_t dqsMode; /*!< Dummy read strobe mode: use enum in "semc_dqs_mode_t". */
uint8_t cmdTimeoutCycles; /*!< Command execution timeout cycles. */
uint8_t busTimeoutCycles; /*!< Bus timeout cycles. */
semc_axi_queueweight_t queueWeight; /*!< AXI queue weight. */
} semc_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name SEMC Initialization and De-initialization
* @{
*/
/*!
* @brief Gets the SEMC default basic configuration structure.
*
* The purpose of this API is to get the default SEMC
* configure structure for SEMC_Init(). User may use the initialized
* structure unchanged in SEMC_Init(), or modify some fields of the
* structure before calling SEMC_Init().
* Example:
@code
semc_config_t config;
SEMC_GetDefaultConfig(&config);
@endcode
* @param config The SEMC configuration structure pointer.
*/
void SEMC_GetDefaultConfig(semc_config_t *config);
/*!
* @brief Initializes SEMC.
* This function ungates the SEMC clock and initializes SEMC.
* This function must be called before calling any other SEMC driver functions.
*
* @param base SEMC peripheral base address.
* @param configure The SEMC configuration structure pointer.
*/
void SEMC_Init(SEMC_Type *base, semc_config_t *configure);
/*!
* @brief Deinitializes the SEMC module and gates the clock.
*
* This function gates the SEMC clock. As a result, the SEMC module doesn't work after
* calling this function, for some IDE, calling this API may cause the next downloading
* operation failed. so, please call this API cautiously. Additional, users can
* using "#define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL (1)" to disable the clock control
* operation in drivers.
*
* @param base SEMC peripheral base address.
*/
void SEMC_Deinit(SEMC_Type *base);
/* @} */
/*!
* @name SEMC Configuration Operation For Each Memory Type
* @{
*/
/*!
* @brief Configures SDRAM controller in SEMC.
*
* @param base SEMC peripheral base address.
* @param cs The chip selection.
* @param config The sdram configuration.
* @param clkSrc_Hz The SEMC clock frequency.
*/
status_t SEMC_ConfigureSDRAM(SEMC_Type *base, semc_sdram_cs_t cs, semc_sdram_config_t *config, uint32_t clkSrc_Hz);
/*!
* @brief Configures NAND controller in SEMC.
*
* @param base SEMC peripheral base address.
* @param config The nand configuration.
* @param clkSrc_Hz The SEMC clock frequency.
*/
status_t SEMC_ConfigureNAND(SEMC_Type *base, semc_nand_config_t *config, uint32_t clkSrc_Hz);
/*!
* @brief Configures NOR controller in SEMC.
*
* @param base SEMC peripheral base address.
* @param config The nor configuration.
* @param clkSrc_Hz The SEMC clock frequency.
*/
status_t SEMC_ConfigureNOR(SEMC_Type *base, semc_nor_config_t *config, uint32_t clkSrc_Hz);
/*!
* @brief Configures SRAM controller in SEMC.
*
* @param base SEMC peripheral base address.
* @param config The sram configuration.
* @param clkSrc_Hz The SEMC clock frequency.
*/
status_t SEMC_ConfigureSRAM(SEMC_Type *base, semc_sram_config_t *config, uint32_t clkSrc_Hz);
/*!
* @brief Configures DBI controller in SEMC.
*
* @param base SEMC peripheral base address.
* @param config The dbi configuration.
* @param clkSrc_Hz The SEMC clock frequency.
*/
status_t SEMC_ConfigureDBI(SEMC_Type *base, semc_dbi_config_t *config, uint32_t clkSrc_Hz);
/* @} */
/*!
* @name SEMC Interrupt Operation
* @{
*/
/*!
* @brief Enables the SEMC interrupt.
*
* This function enables the SEMC interrupts according to the provided mask. The mask
* is a logical OR of enumeration members. See @ref semc_interrupt_enable_t.
* For example, to enable the IP command done and error interrupt, do the following.
* @code
* SEMC_EnableInterrupts(ENET, kSEMC_IPCmdDoneInterrupt | kSEMC_IPCmdErrInterrupt);
* @endcode
*
* @param base SEMC peripheral base address.
* @param mask SEMC interrupts to enable. This is a logical OR of the
* enumeration :: semc_interrupt_enable_t.
*/
static inline void SEMC_EnableInterrupts(SEMC_Type *base, uint32_t mask)
{
base->INTEN |= mask;
}
/*!
* @brief Disables the SEMC interrupt.
*
* This function disables the SEMC interrupts according to the provided mask. The mask
* is a logical OR of enumeration members. See @ref semc_interrupt_enable_t.
* For example, to disable the IP command done and error interrupt, do the following.
* @code
* SEMC_DisableInterrupts(ENET, kSEMC_IPCmdDoneInterrupt | kSEMC_IPCmdErrInterrupt);
* @endcode
*
* @param base SEMC peripheral base address.
* @param mask SEMC interrupts to disable. This is a logical OR of the
* enumeration :: semc_interrupt_enable_t.
*/
static inline void SEMC_DisableInterrupts(SEMC_Type *base, uint32_t mask)
{
base->INTEN &= ~mask;
}
/*!
* @brief Gets the SEMC status.
*
* This function gets the SEMC interrupts event status.
* User can use the a logical OR of enumeration member as a mask.
* See @ref semc_interrupt_enable_t.
*
* @param base SEMC peripheral base address.
* @return status flag, use status flag in semc_interrupt_enable_t to get the related status.
*/
static inline bool SEMC_GetStatusFlag(SEMC_Type *base)
{
return base->INTR;
}
/*!
* @brief Clears the SEMC status flag state.
*
* The following status register flags can be cleared SEMC interrupt status.
*
* @param base SEMC base pointer
* @param mask The status flag mask, a logical OR of enumeration member @ref semc_interrupt_enable_t.
*/
static inline void SEMC_ClearStatusFlags(SEMC_Type *base, uint32_t mask)
{
base->INTR |= mask;
}
/* @} */
/*!
* @name SEMC Memory Access Operation
* @{
*/
/*!
* @brief Check if SEMC is in idle.
*
* @param base SEMC peripheral base address.
* @return True SEMC is in idle, false is not in idle.
*/
static inline bool SEMC_IsInIdle(SEMC_Type *base)
{
return (base->STS0 & SEMC_STS0_IDLE_MASK) ? true : false;
}
/*!
* @brief SEMC IP command access.
*
* @param base SEMC peripheral base address.
* @param type SEMC memory type. refer to "semc_mem_type_t"
* @param address SEMC device address.
* @param command SEMC IP command.
* For NAND device, we should use the SEMC_BuildNandIPCommand to get the right nand command.
* For NOR/DBI device, take refer to "semc_ipcmd_nor_dbi_t".
* For SRAM device, take refer to "semc_ipcmd_sram_t".
* For SDRAM device, take refer to "semc_ipcmd_sdram_t".
* @param write Data for write access.
* @param read Data pointer for read data out.
*/
status_t SEMC_SendIPCommand(
SEMC_Type *base, semc_mem_type_t type, uint32_t address, uint16_t command, uint32_t write, uint32_t *read);
/*!
* @brief Build SEMC IP command for NAND.
*
* This function build SEMC NAND IP command. The command is build of user command code,
* SEMC address mode and SEMC command mode.
*
* @param userCommand NAND device normal command.
* @param addrMode NAND address mode. Refer to "semc_ipcmd_nand_addrmode_t".
* @param cmdMode NAND command mode. Refer to "semc_ipcmd_nand_cmdmode_t".
*/
static inline uint16_t SEMC_BuildNandIPCommand(uint8_t userCommand,
semc_ipcmd_nand_addrmode_t addrMode,
semc_ipcmd_nand_cmdmode_t cmdMode)
{
return (uint16_t)((uint16_t)userCommand << 8) | (uint16_t)(addrMode << 4) | ((uint8_t)cmdMode & 0x0Fu);
}
/*!
* @brief Check if the NAND device is ready.
*
* @param base SEMC peripheral base address.
* @return True NAND is ready, false NAND is not ready.
*/
static inline bool SEMC_IsNandReady(SEMC_Type *base)
{
return (base->STS0 & SEMC_STS0_NARDY_MASK) ? true : false;
}
/*!
* @brief SEMC NAND device memory write through IP command.
*
* @param base SEMC peripheral base address.
* @param address SEMC NAND device address.
* @param data Data for write access.
* @param size_bytes Data length.
*/
status_t SEMC_IPCommandNandWrite(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes);
/*!
* @brief SEMC NAND device memory read through IP command.
*
* @param base SEMC peripheral base address.
* @param address SEMC NAND device address.
* @param data Data pointer for data read out.
* @param size_bytes Data length.
*/
status_t SEMC_IPCommandNandRead(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes);
/*!
* @brief SEMC NOR device memory write through IP command.
*
* @param base SEMC peripheral base address.
* @param address SEMC NOR device address.
* @param data Data for write access.
* @param size_bytes Data length.
*/
status_t SEMC_IPCommandNorWrite(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes);
/*!
* @brief SEMC NOR device memory read through IP command.
*
* @param base SEMC peripheral base address.
* @param address SEMC NOR device address.
* @param data Data pointer for data read out.
* @param size_bytes Data length.
*/
status_t SEMC_IPCommandNorRead(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes);
/* @} */
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_SEMC_H_*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,127 @@
/*
** ###################################################################
** Processors: MIMXRT1052CVJ5B
** MIMXRT1052CVL5B
** MIMXRT1052DVJ6B
** MIMXRT1052DVL6B
**
** Compilers: Freescale C/C++ for Embedded ARM
** GNU C Compiler
** IAR ANSI C/C++ Compiler for ARM
** Keil ARM C/C++ Compiler
** MCUXpresso Compiler
**
** Reference manual: IMXRT1050RM Rev.2.1, 12/2018
** Version: rev. 1.2, 2018-11-27
** Build: b181205
**
** Abstract:
** Provides a system configuration function and a global variable that
** contains the system frequency. It configures the device and initializes
** the oscillator (PLL) that is part of the microcontroller device.
**
** Copyright 2016 Freescale Semiconductor, Inc.
** Copyright 2016-2018 NXP
** All rights reserved.
**
** SPDX-License-Identifier: BSD-3-Clause
**
** http: www.nxp.com
** mail: support@nxp.com
**
** Revisions:
** - rev. 0.1 (2017-01-10)
** Initial version.
** - rev. 1.0 (2018-09-21)
** Update interrupt vector table and dma request source.
** Update register BEE_ADDR_OFFSET1's bitfield name to ADDR_OFFSET1.
** Split GPIO_COMBINED_IRQS to GPIO_COMBINED_LOW_IRQS and GPIO_COMBINED_HIGH_IRQS.
** - rev. 1.1 (2018-11-16)
** Update header files to align with IMXRT1050RM Rev.1.
** - rev. 1.2 (2018-11-27)
** Update header files to align with IMXRT1050RM Rev.2.1.
**
** ###################################################################
*/
/*!
* @file MIMXRT1052
* @version 1.2
* @date 2018-11-27
* @brief Device specific configuration file for MIMXRT1052 (header file)
*
* Provides a system configuration function and a global variable that contains
* the system frequency. It configures the device and initializes the oscillator
* (PLL) that is part of the microcontroller device.
*/
#ifndef _SYSTEM_MIMXRT1052_H_
#define _SYSTEM_MIMXRT1052_H_ /**< Symbol preventing repeated inclusion */
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#ifndef DISABLE_WDOG
#define DISABLE_WDOG 1
#endif
/* Define clock source values */
#define CPU_XTAL_CLK_HZ 24000000UL /* Value of the external crystal or oscillator clock frequency in Hz */
#define CPU_CLK1_HZ 0UL /* Value of the CLK1 (select the CLK1_N/CLK1_P as source) frequency in Hz */
/* If CLOCK1_P,CLOCK1_N is choose as the pll bypass clock source, please implement the CLKPN_FREQ define, otherwise 0 will be returned. */
#define DEFAULT_SYSTEM_CLOCK 528000000UL /* Default System clock value */
/**
* @brief System clock frequency (core clock)
*
* The system clock frequency supplied to the SysTick timer and the processor
* core clock. This variable can be used by the user application to setup the
* SysTick timer or configure other parameters. It may also be used by debugger to
* query the frequency of the debug timer or configure the trace clock speed
* SystemCoreClock is initialized with a correct predefined value.
*/
extern uint32_t SystemCoreClock;
/**
* @brief Setup the microcontroller system.
*
* Typically this function configures the oscillator (PLL) that is part of the
* microcontroller device. For systems with variable clock speed it also updates
* the variable SystemCoreClock. SystemInit is called from startup_device file.
*/
void SystemInit (void);
/**
* @brief Updates the SystemCoreClock variable.
*
* It must be called whenever the core clock is changed during program
* execution. SystemCoreClockUpdate() evaluates the clock register settings and calculates
* the current core clock.
*/
void SystemCoreClockUpdate (void);
/**
* @brief SystemInit function hook.
*
* This weak function allows to call specific initialization code during the
* SystemInit() execution.This can be used when an application specific code needs
* to be called as close to the reset entry as possible (for example the Multicore
* Manager MCMGR_EarlyInit() function call).
* NOTE: No global r/w variables can be used in this hook function because the
* initialization of these variables happens after this function.
*/
void SystemInitHook (void);
#ifdef __cplusplus
}
#endif
#endif /* _SYSTEM_MIMXRT1052_H_ */
@@ -0,0 +1,11 @@
if BSP_USING_RTC
config RTC_BUS_NAME
string "rtc bus name"
default "rtc"
config RTC_DRV_NAME
string "rtc bus driver name"
default "rtc_drv"
config RTC_DEVICE_NAME
string "rtc bus device name"
default "rtc_dev"
endif
@@ -0,0 +1,3 @@
SRC_FILES := hardware_rtc.c connect_rtc.c
include $(KERNEL_ROOT)/compiler.mk
@@ -0,0 +1,453 @@
/*
* The Clear BSD License
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted (subject to the limitations in the disclaimer below) provided
* that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file connect_rtc.c
* @brief ok1052-c board rtc function and structure
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-03-01
*/
/*************************************************
File name: connect_rtc.c
Description: support ok1052-c board rtc configure and spi bus register function
History:
1. Date: 2022-03-01
Author: AIIT XUOS Lab
Modification:
1. change command for XUOS
2. add module codes for XUOS
*************************************************/
#include "board.h"
#include "bus_rtc.h"
#include "pin_mux.h"
#include "dev_rtc.h"
#include "connect_rtc.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define rtc_print KPrintf
#define MAX_TIME_STR_SIZE 50
///////////RX8010///////////
#define RX8010_SEC 0x10
#define RX8010_MIN 0x11
#define RX8010_HOUR 0x12
#define RX8010_WDAY 0x13
#define RX8010_MDAY 0x14
#define RX8010_MONTH 0x15
#define RX8010_YEAR 0x16
#define RX8010_YEAR 0x16
#define RX8010_RESV17 0x17
#define RX8010_ALMIN 0x18
#define RX8010_ALHOUR 0x19
#define RX8010_ALWDAY 0x1A
#define RX8010_TCOUNT0 0x1B
#define RX8010_TCOUNT1 0x1C
#define RX8010_EXT 0x1D
#define RX8010_FLAG 0x1E
#define RX8010_CTRL 0x1F
/* 0x20 to 0x2F are user registers */
#define RX8010_RESV30 0x30
#define RX8010_RESV31 0x31
#define RX8010_IRQ 0x32
#define RX8010_EXT_WADA 0x04 //BIT(3)
#define RX8010_FLAG_VLF 0x02 //BIT(1)
#define RX8010_FLAG_AF 0x04 //BIT(3)
#define RX8010_FLAG_TF 0x08 //BIT(4)
#define RX8010_FLAG_UF 0x10 //BIT(5)
#define RX8010_CTRL_AIE 0x04 //BIT(3)
#define RX8010_CTRL_UIE 0x10 //BIT(5)
#define RX8010_CTRL_STOP 0x20 //BIT(6)
#define RX8010_CTRL_TEST 0x40 //BIT(7)
#define RX8010_ALARM_AE 0x40 //BIT(7)
#define RX8010_TEST_TIME 10000
#define BCD_DATA_LEN 20
// change BIN format to BCD format
#define TO_BCD(_n) (((_n / 10) << 4) | (_n % 10))
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
// change BCD format date to BIN format
uint8_t bcd2bin(uint8_t data)
{
int i = 0;
uint8_t ret = 0;
uint8_t mask[4] = {0x01, 0x02, 0x04, 0x08};
//LOW
for(i = 0; i < 4; i++)
{
if(mask[i] & data)
{
ret += mask[i];
}
}
//HIGH
for(i = 0; i < 4; i++)
{
if(mask[i] & (data >> 4))
{
ret += (mask[i] * 10);
}
}
return ret;
}
// 8010 initialization
int RtcInit(void)
{
uint8_t flag = 0;
uint8_t data = 0;
uint8_t ctrl[2];
int need_clear = 0, err = 0;
err = RtcI2cRead(I2C_RTC_BASE, RX8010_FLAG, &flag, 1);
flag &= ~(RX8010_FLAG_VLF);
err = RtcI2cWrite(I2C_RTC_BASE, RX8010_FLAG, &flag, 1);
/* Initialize reserved registers as specified in datasheet */
data = 0xD8;
err = RtcI2cWrite(I2C_RTC_BASE, RX8010_RESV17, &data, 1);
data = 0x00;
err = RtcI2cWrite(I2C_RTC_BASE, RX8010_RESV30, &data, 1);
data = 0x08;
err = RtcI2cWrite(I2C_RTC_BASE, RX8010_RESV31, &data, 1);
data = 0x00;
err = RtcI2cWrite(I2C_RTC_BASE, RX8010_IRQ, &data, 1);
err = RtcI2cRead(I2C_RTC_BASE, RX8010_FLAG, ctrl, 2);
if(ctrl[0] & RX8010_FLAG_VLF)
{
rtc_print("\r\n Frequency stop was detected\r\n");
}
if(ctrl[0] & RX8010_FLAG_AF)
{
rtc_print("\r\n Alarm was detected\r\n");
need_clear = 1;
}
if(ctrl[0] & RX8010_FLAG_TF)
{
need_clear = 1;
}
if(ctrl[0] & RX8010_FLAG_UF)
{
need_clear = 1;
}
if(need_clear)
{
ctrl[0] &= ~(RX8010_FLAG_AF | RX8010_FLAG_TF | RX8010_FLAG_UF);
err = RtcI2cWrite(I2C_RTC_BASE, RX8010_FLAG, ctrl,1);
if(!err)
{
return err;
}
}
return err;
}
// check format and get BCD format date like 2018-06-21 16:29:30
int RtcGetBcdDate(uint8_t* date, uint8_t* bcd_date)
{
int i;
int temp_date[6];
if(sscanf(date, "20%2d-%2d-%2d %2d:%2d:%2d",
&temp_date[5],
&temp_date[4],
&temp_date[3],
&temp_date[2],
&temp_date[1],
&temp_date[0]) == EOF)
{
rtc_print("i2c %s failed\n", __func__);
return -1;
}
for(i = 0; i < 6; i++)
{
bcd_date[i] = TO_BCD(temp_date[i]);
}
return 0;
}
// setup time
int RtcSetTime(uint8_t* asc_date)
{
uint8_t bcd_date[6];
int ret, err;
if(RtcGetBcdDate(asc_date, bcd_date))
{
rtc_print("\r\n Date format error! \r\n");
return -1;
}
err = RtcI2cWrite(I2C_RTC_BASE, RX8010_SEC, bcd_date, 3);
err |= RtcI2cWrite(I2C_RTC_BASE, RX8010_MDAY, &bcd_date[3], 3);
return err;
}
// get rx8010 time
int RtcGetTime(struct tm *ct)
{
uint8_t rtc_data[7];
uint8_t time_str[7];
uint8_t flag_reg;
int err;
err = RtcI2cRead(I2C_RTC_BASE, RX8010_FLAG, &flag_reg, 1);
if(flag_reg & RX8010_FLAG_VLF)
{
rtc_print("\r\n Frequency stop was detected\r\n");
return 1;
}
err = RtcI2cRead(I2C_RTC_BASE, RX8010_SEC, rtc_data, 7);
time_str[0] = bcd2bin(rtc_data[RX8010_SEC - RX8010_SEC] & 0x7f);
time_str[1] = bcd2bin(rtc_data[RX8010_MIN - RX8010_SEC] & 0x7f);
time_str[2] = bcd2bin(rtc_data[RX8010_HOUR - RX8010_SEC] & 0x3f);
time_str[4] = bcd2bin(rtc_data[RX8010_MDAY - RX8010_SEC] & 0x3f);
time_str[5] = bcd2bin(rtc_data[RX8010_MONTH - RX8010_SEC] & 0x1f);
time_str[6] = bcd2bin(rtc_data[RX8010_YEAR - RX8010_SEC]);
time_str[3] = rtc_data[RX8010_WDAY - RX8010_SEC] & 0x7f;
rtc_print("RX8010 Time: 20%d%d-%d%d-%d%d %d%d:%d%d:%d%d\r\n",
time_str[6]/10, time_str[6]%10, time_str[5]/10, time_str[5]%10, time_str[4]/10, time_str[4]%10,
time_str[2]/10, time_str[2]%10, time_str[1]/10, time_str[1]%10, time_str[0]/10, time_str[0]%10);
ct->tm_year = time_str[6];
ct->tm_mon = time_str[5];
ct->tm_mday = time_str[4];
ct->tm_wday = time_str[3];
ct->tm_hour = time_str[2];
ct->tm_min = time_str[1];
ct->tm_sec = time_str[0];
return 0;
}
static int GetWeekDay(int year, int month, int day)
{
if(month==1||month==2)
{
year -=1;
month +=12;
}
return (day+1+2*month+3*(month+1)/5+year+(year/4)-year/100+year/400)%7+1;
}
static uint32 RtcConfigure(void* drv, struct BusConfigureInfo* configure_info)
{
NULL_PARAM_CHECK(drv);
struct RtcDriver* rtc_drv = (struct RtcDriver*)drv;
struct RtcDrvConfigureParam* drv_param = (struct RtcDrvConfigureParam*)configure_info->private_data;
int cmd = drv_param->rtc_operation_cmd;
time_t* time = drv_param->time;
switch(cmd)
{
case OPER_RTC_GET_TIME:
{
struct tm ct;
RtcGetTime(&ct);
*time = mktime(&ct);
}
break;
case OPER_RTC_SET_TIME:
{
char time_str[MAX_TIME_STR_SIZE] = {0};
struct tm *ct = localtime(time);
strftime(time_str, MAX_TIME_STR_SIZE, "%y-%m-%d %H:%M:%S", ct);
RtcSetTime(time_str);
}
break;
}
return EOK;
}
int RtcConfiguration(void)
{
BOARD_InitI2C1Pins();
RtcI2cInit();
RtcInit();
return 0;
}
/*manage the rtc device operations*/
static const struct RtcDevDone dev_done =
{
.open = NONE,
.close = NONE,
.write = NONE,
.read = NONE,
};
static int BoardRtcBusInit(struct RtcBus* rtc_bus, struct RtcDriver* rtc_driver)
{
x_err_t ret = EOK;
/*Init the rtc bus */
ret = RtcBusInit(rtc_bus, RTC_BUS_NAME);
if(EOK != ret)
{
KPrintf("hw_rtc_init RtcBusInit error %d\n", ret);
return ERROR;
}
/*Init the rtc driver*/
ret = RtcDriverInit(rtc_driver, RTC_DRV_NAME);
if(EOK != ret)
{
KPrintf("hw_rtc_init RtcDriverInit error %d\n", ret);
return ERROR;
}
/*Attach the rtc driver to the rtc bus*/
ret = RtcDriverAttachToBus(RTC_DRV_NAME, RTC_BUS_NAME);
if(EOK != ret)
{
KPrintf("hw_rtc_init RtcDriverAttachToBus error %d\n", ret);
return ERROR;
}
return ret;
}
/*Attach the rtc device to the rtc bus*/
static int BoardRtcDevBend(void)
{
x_err_t ret = EOK;
static struct RtcHardwareDevice rtc_device;
memset(&rtc_device, 0, sizeof(struct RtcHardwareDevice));
rtc_device.dev_done = &(dev_done);
ret = RtcDeviceRegister(&rtc_device, NONE, RTC_DEVICE_NAME);
if(EOK != ret)
{
KPrintf("hw_rtc_init RtcDeviceInit device %s error %d\n", RTC_DEVICE_NAME, ret);
return ERROR;
}
ret = RtcDeviceAttachToBus(RTC_DEVICE_NAME, RTC_BUS_NAME);
if(EOK != ret)
{
KPrintf("hw_rtc_init RtcDeviceAttachToBus device %s error %d\n", RTC_DEVICE_NAME, ret);
return ERROR;
}
return ret;
}
int Imxrt1052HwRtcInit(void)
{
x_err_t ret = EOK;
static struct RtcBus rtc_bus;
memset(&rtc_bus, 0, sizeof(struct RtcBus));
static struct RtcDriver rtc_driver;
memset(&rtc_driver, 0, sizeof(struct RtcDriver));
rtc_driver.configure = &(RtcConfigure);
ret = BoardRtcBusInit(&rtc_bus, &rtc_driver);
if(EOK != ret)
{
KPrintf("hw_rtc_init error ret %u\n", ret);
return ERROR;
}
ret = BoardRtcDevBend();
if(EOK != ret)
{
KPrintf("hw_rtc_init error ret %u\n", ret);
return ERROR;
}
RtcConfiguration();
return ret;
}
void RtcTestRx8010(int argc, char* argv[])
{
if(argc == 2)
{
if(RtcSetTime(argv[1]) == 0)
{
RtcGetTime(NULL);
}
}
else
{
RtcGetTime(NULL);
}
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)| SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)| SHELL_CMD_PARAM_NUM(3),
rtc, RtcTestRx8010, i2c rtc "date time");
@@ -0,0 +1,71 @@
/*
* The Clear BSD License
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted (subject to the limitations in the disclaimer below) provided
* that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file hardware_rtc.c
* @brief I2C RTC drivers
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022.1.18
*/
/*************************************************
File name: hardware_rtc.c
Description: support ok1052-c board rtc hardware driver I2C function
History:
1. Date: 2022-01-18
Author: AIIT XUOS Lab
Modification:
1. support ok1052-c board rtc
*************************************************/
#include "connect_rtc.h"
#include "connect_i2c.h"
void RtcI2cInit()
{
I2cHardwareInit();
}
status_t RtcI2cWrite(LPI2C_Type *base, uint32_t sub_addr, uint8_t *buf, uint16_t size)
{
return I2cHardwareWrite(base, I2C_RTC_ADDR, sub_addr, buf, size);
}
uint32_t RtcI2cRead(LPI2C_Type *base,uint32_t sub_addr,uint8_t* buf, uint16_t size)
{
return I2cHardwareRead(base, I2C_RTC_ADDR, sub_addr, buf, size);
}
@@ -0,0 +1,24 @@
if BSP_USING_SDIO
config SDIO_BUS_NAME
string "sdio bus name"
default "sdio"
config SDIO_DRIVER_NAME
string "sdio driver name"
default "sdio_drv"
config SDIO_DEVICE_NAME
string "sdio device name"
default "sdio_dev"
config MOUNT_SDCARD_FS
bool "mount cd card file system"
default n
select MOUNT_SDCARD
if MOUNT_SDCARD_FS
config MOUNT_SDCARD_FS_TYPE
int "choose file system type : FATFS(0) LWEXT4(3)"
default 0
endif
endif
@@ -0,0 +1,5 @@
SRC_DIR := sdmmc
SRC_FILES := connect_sdio.c
include $(KERNEL_ROOT)/compiler.mk
@@ -0,0 +1,460 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* @file connect_sdio.c
* @brief support sdio function using bus driver framework on OK1052 board
* @version 2.0
* @author AIIT XUOS Lab
* @date 2022-01-24
*/
/*************************************************
File name: connect_sdio.c
Description: support ok1052-c board sd card configure and sdio bus register function
Others: take SDK_2.6.1_MIMXRT1052xxxxB/boards/evkbimxrt1050/driver_examples/sdcard/polling/sdcard_polling.c for references
History:
1. Date: 2022-01-24
Author: AIIT XUOS Lab
Modification:
1. support ok1052-c board sdio configure, write and read
2. support ok1052-c board sdio bus device and driver register
*************************************************/
#include <connect_sdio.h>
/*******************************************************************************
* Definitions
******************************************************************************/
#define SDCARD_POWER_CTRL_FUNCTION_EXIST
/*! @brief Data block count accessed in card */
#define DATA_BLOCK_COUNT (5U)
/*! @brief Start data block number accessed in card */
#define DATA_BLOCK_START (2U)
/*! @brief Data buffer size. */
#define DATA_BUFFER_SIZE (FSL_SDMMC_DEFAULT_BLOCK_SIZE * DATA_BLOCK_COUNT)
#define BOARD_USDHC_SDCARD_POWER_CONTROL(state) \
(GPIO_PinWrite(BOARD_SD_POWER_RESET_GPIO, BOARD_SD_POWER_RESET_GPIO_PIN, state))
/*******************************************************************************
* Prototypes
******************************************************************************/
static void BoardPowerOffSdCard(void);
static void BoardPowerOnSdCard(void);
/*!
* @brief printf the card information log.
*
* @param card Card descriptor.
*/
static void CardInformationLog(sd_card_t *card);
/*******************************************************************************
* Variables
******************************************************************************/
/* @brief decription about the read/write buffer
* The size of the read/write buffer should be a multiple of 512, since SDHC/SDXC card uses 512-byte fixed
* block length and this driver example is enabled with a SDHC/SDXC card.If you are using a SDSC card, you
* can define the block length by yourself if the card supports partial access.
* The address of the read/write buffer should align to the specific DMA data buffer address align value if
* DMA transfer is used, otherwise the buffer address is not important.
* At the same time buffer address/size should be aligned to the cache line size if cache is supported.
*/
/*! @brief Data written to the card */
SDK_ALIGN(uint8_t g_data_write[SDK_SIZEALIGN(DATA_BUFFER_SIZE, SDMMC_DATA_BUFFER_ALIGN_CACHE)],
MAX(SDMMC_DATA_BUFFER_ALIGN_CACHE, SDMMCHOST_DMA_BUFFER_ADDR_ALIGN));
/*! @brief Data read from the card */
SDK_ALIGN(uint8_t g_data_read[SDK_SIZEALIGN(DATA_BUFFER_SIZE, SDMMC_DATA_BUFFER_ALIGN_CACHE)],
MAX(SDMMC_DATA_BUFFER_ALIGN_CACHE, SDMMCHOST_DMA_BUFFER_ADDR_ALIGN));
/*! @brief SDMMC host detect card configuration */
static const sdmmchost_detect_card_t s_sdcard_detect = {
#ifndef BOARD_SD_DETECT_TYPE
.cdType = kSDMMCHOST_DetectCardByGpioCD,
#else
.cdType = BOARD_SD_DETECT_TYPE,
#endif
.cdTimeOut_ms = (~0U),
};
/*! @brief SDMMC card power control configuration */
#if defined SDCARD_POWER_CTRL_FUNCTION_EXIST
static const sdmmchost_pwr_card_t s_sdcard_pwr_ctrl = {
.powerOn = BoardPowerOnSdCard,
.powerOnDelay_ms = 0U,
.powerOff = BoardPowerOffSdCard,
.powerOffDelay_ms = 0U,
};
#endif
/*! @brief SDMMC card power control configuration */
#if defined SDCARD_SWITCH_VOLTAGE_FUNCTION_EXIST
static const sdmmchost_card_switch_voltage_func_t s_sdcard_voltage_switch = {
.cardSignalLine1V8 = BOARD_USDHC_Switch_VoltageTo1V8,
.cardSignalLine3V3 = BOARD_USDHC_Switch_VoltageTo3V3,
};
#endif
/*! @brief Card descriptor. */
static sd_card_t g_sd;
static int sd_lock = -1;
static void BoardUSDHCClockConfiguration(void)
{
CLOCK_InitSysPll(&sysPllConfig_BOARD_BootClockRUN);
/*configure system pll PFD0 fractional divider to 24, output clock is 528MHZ * 18 / 24 = 396 MHZ*/
CLOCK_InitSysPfd(kCLOCK_Pfd0, 24U);
/* Configure USDHC clock source and divider */
CLOCK_SetDiv(kCLOCK_Usdhc1Div, 0U);
CLOCK_SetMux(kCLOCK_Usdhc1Mux, 1U);
}
static void BoardPowerOffSdCard(void)
{
/*
Do nothing here.
SD card will not be detected correctly if the card VDD is power off,
the reason is caused by card VDD supply to the card detect circuit, this issue is exist on EVK board rev A1 and
A2.
If power off function is not implemented after soft reset and prior to SD Host initialization without
remove/insert card,
a UHS-I card may not reach its highest speed mode during the second card initialization.
Application can avoid this issue by toggling the SD_VDD (GPIO) before the SD host initialization.
*/
}
static void BoardPowerOnSdCard(void)
{
BOARD_USDHC_SDCARD_POWER_CONTROL(1);
}
static void CardInformationLog(sd_card_t *card)
{
NULL_PARAM_CHECK(card);
KPrintf("\r\nCard size %d * %d bytes\r\n", card->blockCount, card->blockSize);
KPrintf("\r\nWorking condition:\r\n");
if (card->operationVoltage == kCARD_OperationVoltage330V) {
KPrintf("\r\n Voltage : 3.3V\r\n");
} else if (card->operationVoltage == kCARD_OperationVoltage180V) {
KPrintf("\r\n Voltage : 1.8V\r\n");
}
if (card->currentTiming == kSD_TimingSDR12DefaultMode) {
if (card->operationVoltage == kCARD_OperationVoltage330V) {
KPrintf("\r\n Timing mode: Default mode\r\n");
} else if (card->operationVoltage == kCARD_OperationVoltage180V) {
KPrintf("\r\n Timing mode: SDR12 mode\r\n");
}
} else if (card->currentTiming == kSD_TimingSDR25HighSpeedMode) {
if (card->operationVoltage == kCARD_OperationVoltage180V) {
KPrintf("\r\n Timing mode: SDR25\r\n");
} else {
KPrintf("\r\n Timing mode: High Speed\r\n");
}
} else if (card->currentTiming == kSD_TimingSDR50Mode) {
KPrintf("\r\n Timing mode: SDR50\r\n");
} else if (card->currentTiming == kSD_TimingSDR104Mode) {
KPrintf("\r\n Timing mode: SDR104\r\n");
} else if (card->currentTiming == kSD_TimingDDR50Mode) {
KPrintf("\r\n Timing mode: DDR50\r\n");
}
KPrintf("\r\n Freq : %d HZ\r\n", card->busClock_Hz);
}
static uint32 SdioConfigure(void *drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(drv);
NULL_PARAM_CHECK(configure_info);
if (configure_info->configure_cmd == OPER_BLK_GETGEOME) {
NULL_PARAM_CHECK(configure_info->private_data);
struct DeviceBlockArrange *args = (struct DeviceBlockArrange *)configure_info->private_data;
args->size_perbank = g_sd.blockSize;
args->block_size = g_sd.blockSize;
args->bank_num = g_sd.blockCount;
}
return EOK;
}
static uint32 SdioOpen(void *dev)
{
NULL_PARAM_CHECK(dev);
if(sd_lock >= 0) {
KSemaphoreDelete(sd_lock);
}
sd_lock = KSemaphoreCreate(1);
if (sd_lock < 0){
return ERROR;
}
return EOK;
}
static uint32 SdioClose(void *dev)
{
NULL_PARAM_CHECK(dev);
KSemaphoreDelete(sd_lock);
return EOK;
}
static uint32 SdioRead(void *dev, struct BusBlockReadParam *read_param)
{
uint8 ret = EOK;
uint32 sector = read_param->pos;
uint32 block_num = read_param->size;
uint8 *read_buffer = (uint8 *)read_param->buffer;
KSemaphoreObtain(sd_lock, WAITING_FOREVER);
if (kStatus_Success != SD_ReadBlocks(&g_sd, read_buffer, sector, block_num)) {
KPrintf("Read multiple data blocks failed.\r\n");
return 0;
}
KSemaphoreAbandon(sd_lock);
return read_param->size;
}
static uint32 SdioWrite(void *dev, struct BusBlockWriteParam *write_param)
{
uint8 ret = EOK;
uint32 sector = write_param->pos;
uint32 block_num = write_param->size;
const uint8 *write_buffer = (uint8 *)write_param->buffer;
KSemaphoreObtain(sd_lock, WAITING_FOREVER);
if (kStatus_Success != SD_WriteBlocks(&g_sd, write_buffer, sector, block_num)) {
KPrintf("Write multiple data blocks failed.\r\n");
return 0;
}
KSemaphoreAbandon(sd_lock);
return write_param->size;
}
static int SdioControl(struct HardwareDev *dev, struct HalDevBlockParam *block_param)
{
NULL_PARAM_CHECK(dev);
if (OPER_BLK_GETGEOME == block_param->cmd) {
block_param->dev_block.size_perbank = g_sd.blockSize;
block_param->dev_block.block_size = g_sd.blockSize;
block_param->dev_block.bank_num = g_sd.blockCount;
}
return EOK;
}
static struct SdioDevDone dev_done =
{
SdioOpen,
SdioClose,
SdioWrite,
SdioRead,
};
#if defined(FS_VFS) && defined(MOUNT_SDCARD_FS)
#include <iot-vfs.h>
int sd_mount_flag = 0;
/**
* @description: Mount SD card
* @return 0
*/
static int MountSDCardFs(enum FilesystemType fs_type)
{
if (MountFilesystem(SDIO_BUS_NAME, SDIO_DEVICE_NAME, SDIO_DRIVER_NAME, fs_type, "/") == 0) {
sd_mount_flag = 1;
KPrintf("Sd card mount to '/'");
} else {
KPrintf("Sd card mount to '/' failed!");
}
return 0;
}
#endif
static void SdCardAttach(void)
{
bool is_read_only;
static sd_card_t *card = &g_sd;
KPrintf("\r\nCard inserted.\r\n");
/* reset host once card re-plug in */
SD_HostReset(&(card->host));
/* power on the card */
SD_PowerOnCard(card->host.base, card->usrParam.pwr);
KPrintf("Power on done\n");
/* Init card. */
if (SD_CardInit(card)) {
KPrintf("\r\nSD card init failed.\r\n");
return;
}
/* card information log */
CardInformationLog(card);
/* Check if card is readonly. */
is_read_only = SD_CheckReadOnly(card);
#ifdef MOUNT_SDCARD_FS
/*mount file system*/
MountSDCardFs(MOUNT_SDCARD_FS_TYPE);
#endif
}
static void SdCardDetach(void)
{
/*unmount file system*/
KPrintf("\r\nCard detect extracted.\r\n");
#ifdef MOUNT_SDCARD_FS
UnmountFileSystem("/");
#endif
}
static uint8 SdCardReadCd(void)
{
BusType pin;
pin = BusFind(PIN_BUS_NAME);
pin->owner_haldev = BusFindDevice(pin, PIN_DEVICE_NAME);
struct PinStat PinStat;
struct BusBlockReadParam read_param;
read_param.buffer = (void *)&PinStat;
PinStat.pin = IMXRT_GET_PIN(2, 28);
return BusDevReadData(pin->owner_haldev, &read_param);
}
static void SdCardTask(void* parameter)
{
static int sd_card_status = 0;
while (1) {
if (!SdCardReadCd()) {
if (!sd_card_status) {
SdCardAttach();
sd_card_status = 1;
}
} else {
if (sd_card_status) {
SdCardDetach();
sd_card_status = 0;
}
}
}
}
#ifdef MOUNT_SDCARD
int MountSDCard()
{
int sd_card_task = 0;
sd_card_task = KTaskCreate("sd_card", SdCardTask, NONE,
SD_CARD_STACK_SIZE, 8);
if(sd_card_task < 0) {
KPrintf("sd_card_task create failed ...%s %d.\n", __FUNCTION__,__LINE__);
return ERROR;
}
StartupKTask(sd_card_task);
return EOK;
}
#endif
int Imxrt1052HwSdioInit(void)
{
x_err_t ret = EOK;
static struct SdioBus sdio_bus;
static struct SdioDriver sdio_drv;
static struct SdioHardwareDevice sdio_dev;
static sd_card_t *card = &g_sd;
memset(&sdio_bus, 0, sizeof(struct SdioBus));
memset(&sdio_drv, 0, sizeof(struct SdioDriver));
memset(&sdio_dev, 0, sizeof(struct SdioHardwareDevice));
BoardUSDHCClockConfiguration();
card->host.base = SD_HOST_BASEADDR;
card->host.sourceClock_Hz = SD_HOST_CLK_FREQ;
/* card detect type */
card->usrParam.cd = &s_sdcard_detect;
#if defined SDCARD_POWER_CTRL_FUNCTION_EXIST
card->usrParam.pwr = &s_sdcard_pwr_ctrl;
#endif
#if defined DEMO_SDCARD_SWITCH_VOLTAGE_FUNCTION_EXIST
card->usrParam.cardVoltage = &s_sdcard_voltage_switch;
#endif
/* SD host init function */
if (SD_HostInit(card) != kStatus_Success) {
KPrintf("\r\nSD host init fail\r\n");
return ERROR;
}
ret = SdioBusInit(&sdio_bus, SDIO_BUS_NAME);
if (ret != EOK) {
KPrintf("Sdio bus init error %d\n", ret);
return ERROR;
}
ret = SdioDriverInit(&sdio_drv, SDIO_DRIVER_NAME);
if (ret != EOK) {
KPrintf("Sdio driver init error %d\n", ret);
return ERROR;
}
ret = SdioDriverAttachToBus(SDIO_DRIVER_NAME, SDIO_BUS_NAME);
if (ret != EOK) {
KPrintf("Sdio driver attach error %d\n", ret);
return ERROR;
}
sdio_dev.dev_done = &dev_done;
sdio_dev.haldev.dev_block_control = SdioControl;
ret = SdioDeviceRegister(&sdio_dev, SDIO_DEVICE_NAME);
if (ret != EOK) {
KPrintf("Sdio device register error %d\n", ret);
return ERROR;
}
ret = SdioDeviceAttachToBus(SDIO_DEVICE_NAME, SDIO_BUS_NAME);
if (ret != EOK) {
KPrintf("Sdio device register error %d\n", ret);
return ERROR;
}
return ret;
}
@@ -0,0 +1,3 @@
SRC_DIR += port src
include $(KERNEL_ROOT)/compiler.mk
@@ -0,0 +1,321 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_MMC_H_
#define _FSL_MMC_H_
#include "fsl_sdmmc_common.h"
/*!
* @addtogroup MMCCARD
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief MMC card flags */
enum _mmc_card_flag
{
kMMC_SupportHighSpeed26MHZFlag = (1U << 0U), /*!< Support high speed 26MHZ */
kMMC_SupportHighSpeed52MHZFlag = (1U << 1U), /*!< Support high speed 52MHZ */
kMMC_SupportHighSpeedDDR52MHZ180V300VFlag = (1 << 2U), /*!< ddr 52MHZ 1.8V or 3.0V */
kMMC_SupportHighSpeedDDR52MHZ120VFlag = (1 << 3U), /*!< DDR 52MHZ 1.2V */
kMMC_SupportHS200200MHZ180VFlag = (1 << 4U), /*!< HS200 ,200MHZ,1.8V */
kMMC_SupportHS200200MHZ120VFlag = (1 << 5U), /*!< HS200, 200MHZ, 1.2V */
kMMC_SupportHS400DDR200MHZ180VFlag = (1 << 6U), /*!< HS400, DDR, 200MHZ,1.8V */
kMMC_SupportHS400DDR200MHZ120VFlag = (1 << 7U), /*!< HS400, DDR, 200MHZ,1.2V */
kMMC_SupportHighCapacityFlag = (1U << 8U), /*!< Support high capacity */
kMMC_SupportAlternateBootFlag = (1U << 9U), /*!< Support alternate boot */
kMMC_SupportDDRBootFlag = (1U << 10U), /*!< support DDR boot flag*/
kMMC_SupportHighSpeedBootFlag = (1U << 11U), /*!< support high speed boot flag*/
};
/*!
* @brief mmc card state
*
* Define the card structure including the necessary fields to identify and describe the card.
*/
typedef struct _mmc_card
{
SDMMCHOST_CONFIG host; /*!< Host information */
mmccard_usr_param_t usrParam; /*!< user parameter */
bool isHostReady; /*!< Use this flag to indicate if need host re-init or not*/
bool noInteralAlign; /*!< use this flag to disable sdmmc align. If disable, sdmmc will not make sure the
data buffer address is word align, otherwise all the transfer are align to low level driver */
uint32_t busClock_Hz; /*!< MMC bus clock united in Hz */
uint32_t relativeAddress; /*!< Relative address of the card */
bool enablePreDefinedBlockCount; /*!< Enable PRE-DEFINED block count when read/write */
uint32_t flags; /*!< Capability flag in _mmc_card_flag */
uint32_t rawCid[4U]; /*!< Raw CID content */
uint32_t rawCsd[4U]; /*!< Raw CSD content */
uint32_t rawExtendedCsd[MMC_EXTENDED_CSD_BYTES / 4U]; /*!< Raw MMC Extended CSD content */
uint32_t ocr; /*!< Raw OCR content */
mmc_cid_t cid; /*!< CID */
mmc_csd_t csd; /*!< CSD */
mmc_extended_csd_t extendedCsd; /*!< Extended CSD */
uint32_t blockSize; /*!< Card block size */
uint32_t userPartitionBlocks; /*!< Card total block number in user partition */
uint32_t bootPartitionBlocks; /*!< Boot partition size united as block size */
uint32_t eraseGroupBlocks; /*!< Erase group size united as block size */
mmc_access_partition_t currentPartition; /*!< Current access partition */
mmc_voltage_window_t hostVoltageWindowVCCQ; /*!< Host IO voltage window */
mmc_voltage_window_t hostVoltageWindowVCC; /*!< application must set this value according to board specific */
mmc_high_speed_timing_t busTiming; /*!< indicate the current work timing mode*/
mmc_data_bus_width_t busWidth; /*!< indicate the current work bus width */
} mmc_card_t;
/*************************************************************************************************
* API
************************************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name MMCCARD Function
* @{
*/
/*!
* @brief Initializes the MMC card and host.
*
* @param card Card descriptor.
*
* @retval kStatus_SDMMC_HostNotReady host is not ready.
* @retval kStatus_SDMMC_GoIdleFailed Go idle failed.
* @retval kStatus_SDMMC_SendOperationConditionFailed Send operation condition failed.
* @retval kStatus_SDMMC_AllSendCidFailed Send CID failed.
* @retval kStatus_SDMMC_SetRelativeAddressFailed Set relative address failed.
* @retval kStatus_SDMMC_SendCsdFailed Send CSD failed.
* @retval kStatus_SDMMC_CardNotSupport Card not support.
* @retval kStatus_SDMMC_SelectCardFailed Send SELECT_CARD command failed.
* @retval kStatus_SDMMC_SendExtendedCsdFailed Send EXT_CSD failed.
* @retval kStatus_SDMMC_SetBusWidthFailed Set bus width failed.
* @retval kStatus_SDMMC_SwitchHighSpeedFailed Switch high speed failed.
* @retval kStatus_SDMMC_SetCardBlockSizeFailed Set card block size failed.
* @retval kStatus_Success Operate successfully.
*/
status_t MMC_Init(mmc_card_t *card);
/*!
* @brief Deinitializes the card and host.
*
* @param card Card descriptor.
*/
void MMC_Deinit(mmc_card_t *card);
/*!
* @brief intialize the card.
*
* @param card Card descriptor.
*
* @retval kStatus_SDMMC_HostNotReady host is not ready.
* @retval kStatus_SDMMC_GoIdleFailed Go idle failed.
* @retval kStatus_SDMMC_SendOperationConditionFailed Send operation condition failed.
* @retval kStatus_SDMMC_AllSendCidFailed Send CID failed.
* @retval kStatus_SDMMC_SetRelativeAddressFailed Set relative address failed.
* @retval kStatus_SDMMC_SendCsdFailed Send CSD failed.
* @retval kStatus_SDMMC_CardNotSupport Card not support.
* @retval kStatus_SDMMC_SelectCardFailed Send SELECT_CARD command failed.
* @retval kStatus_SDMMC_SendExtendedCsdFailed Send EXT_CSD failed.
* @retval kStatus_SDMMC_SetBusWidthFailed Set bus width failed.
* @retval kStatus_SDMMC_SwitchHighSpeedFailed Switch high speed failed.
* @retval kStatus_SDMMC_SetCardBlockSizeFailed Set card block size failed.
* @retval kStatus_Success Operate successfully.
*/
status_t MMC_CardInit(mmc_card_t *card);
/*!
* @brief Deinitializes the card.
*
* @param card Card descriptor.
*/
void MMC_CardDeinit(mmc_card_t *card);
/*!
* @brief initialize the host.
*
* This function deinitializes the specific host.
*
* @param card Card descriptor.
*/
status_t MMC_HostInit(mmc_card_t *card);
/*!
* @brief Deinitializes the host.
*
* This function deinitializes the host.
*
* @param card Card descriptor.
*/
void MMC_HostDeinit(mmc_card_t *card);
/*!
* @brief reset the host.
*
* This function reset the specific host.
*
* @param host host descriptor.
*/
void MMC_HostReset(SDMMCHOST_CONFIG *host);
/*!
* @brief power on card.
*
* The power on operation depend on host or the user define power on function.
* @param base host base address.
* @param pwr user define power control configuration
*/
void MMC_PowerOnCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr);
/*!
* @brief power off card.
*
* The power off operation depend on host or the user define power on function.
* @param base host base address.
* @param pwr user define power control configuration
*/
void MMC_PowerOffCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr);
/*!
* @brief Checks if the card is read-only.
*
* @param card Card descriptor.
* @retval true Card is read only.
* @retval false Card isn't read only.
*/
bool MMC_CheckReadOnly(mmc_card_t *card);
/*!
* @brief Reads data blocks from the card.
*
* @param card Card descriptor.
* @param buffer The buffer to save data.
* @param startBlock The start block index.
* @param blockCount The number of blocks to read.
* @retval kStatus_InvalidArgument Invalid argument.
* @retval kStatus_SDMMC_CardNotSupport Card not support.
* @retval kStatus_SDMMC_SetBlockCountFailed Set block count failed.
* @retval kStatus_SDMMC_TransferFailed Transfer failed.
* @retval kStatus_SDMMC_StopTransmissionFailed Stop transmission failed.
* @retval kStatus_Success Operate successfully.
*/
status_t MMC_ReadBlocks(mmc_card_t *card, uint8_t *buffer, uint32_t startBlock, uint32_t blockCount);
/*!
* @brief Writes data blocks to the card.
*
* @param card Card descriptor.
* @param buffer The buffer to save data blocks.
* @param startBlock Start block number to write.
* @param blockCount Block count.
* @retval kStatus_InvalidArgument Invalid argument.
* @retval kStatus_SDMMC_NotSupportYet Not support now.
* @retval kStatus_SDMMC_SetBlockCountFailed Set block count failed.
* @retval kStatus_SDMMC_WaitWriteCompleteFailed Send status failed.
* @retval kStatus_SDMMC_TransferFailed Transfer failed.
* @retval kStatus_SDMMC_StopTransmissionFailed Stop transmission failed.
* @retval kStatus_Success Operate successfully.
*/
status_t MMC_WriteBlocks(mmc_card_t *card, const uint8_t *buffer, uint32_t startBlock, uint32_t blockCount);
/*!
* @brief Erases groups of the card.
*
* Erase group is the smallest erase unit in MMC card. The erase range is [startGroup, endGroup].
*
* @param card Card descriptor.
* @param startGroup Start group number.
* @param endGroup End group number.
* @retval kStatus_InvalidArgument Invalid argument.
* @retval kStatus_SDMMC_WaitWriteCompleteFailed Send status failed.
* @retval kStatus_SDMMC_TransferFailed Transfer failed.
* @retval kStatus_Success Operate successfully.
*/
status_t MMC_EraseGroups(mmc_card_t *card, uint32_t startGroup, uint32_t endGroup);
/*!
* @brief Selects the partition to access.
*
* @param card Card descriptor.
* @param partitionNumber The partition number.
* @retval kStatus_SDMMC_ConfigureExtendedCsdFailed Configure EXT_CSD failed.
* @retval kStatus_Success Operate successfully.
*/
status_t MMC_SelectPartition(mmc_card_t *card, mmc_access_partition_t partitionNumber);
/*!
* @brief Configures the boot activity of the card.
*
* @param card Card descriptor.
* @param config Boot configuration structure.
* @retval kStatus_SDMMC_NotSupportYet Not support now.
* @retval kStatus_SDMMC_ConfigureExtendedCsdFailed Configure EXT_CSD failed.
* @retval kStatus_SDMMC_ConfigureBootFailed Configure boot failed.
* @retval kStatus_Success Operate successfully.
*/
status_t MMC_SetBootConfig(mmc_card_t *card, const mmc_boot_config_t *config);
/*!
* @brief MMC card start boot.
*
* @param card Card descriptor.
* @param mmcConfig mmc Boot configuration structure.
* @param buffer address to recieve data.
* @param hostConfig host boot configurations.
* @retval kStatus_Fail fail.
* @retval kStatus_SDMMC_TransferFailed transfer fail.
* @retval kStatus_SDMMC_GoIdleFailed reset card fail.
* @retval kStatus_Success Operate successfully.
*/
status_t MMC_StartBoot(mmc_card_t *card,
const mmc_boot_config_t *mmcConfig,
uint8_t *buffer,
SDMMCHOST_BOOT_CONFIG *hostConfig);
/*!
* @brief MMC card set boot configuration write protect.
*
* @param card Card descriptor.
* @param wp write protect value.
*/
status_t MMC_SetBootConfigWP(mmc_card_t *card, uint8_t wp);
/*!
* @brief MMC card continous read boot data.
*
* @param card Card descriptor.
* @param buffer buffer address.
* @param hostConfig host boot configurations.
*/
status_t MMC_ReadBootData(mmc_card_t *card, uint8_t *buffer, SDMMCHOST_BOOT_CONFIG *hostConfig);
/*!
* @brief MMC card stop boot mode.
*
* @param card Card descriptor.
* @param bootMode boot mode.
*/
status_t MMC_StopBoot(mmc_card_t *card, uint32_t bootMode);
/*!
* @brief MMC card set boot partition write protect.
*
* @param card Card descriptor.
* @param bootPartitionWP boot partition write protect value.
*/
status_t MMC_SetBootPartitionWP(mmc_card_t *card, mmc_boot_partition_wp_t bootPartitionWP);
/* @} */
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* _FSL_MMC_H_*/
@@ -0,0 +1,315 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_SD_H_
#define _FSL_SD_H_
#include "fsl_sdmmc_common.h"
/*!
* @addtogroup SDCARD
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief SD card flags */
enum _sd_card_flag
{
kSD_SupportHighCapacityFlag = (1U << 1U), /*!< Support high capacity */
kSD_Support4BitWidthFlag = (1U << 2U), /*!< Support 4-bit data width */
kSD_SupportSdhcFlag = (1U << 3U), /*!< Card is SDHC */
kSD_SupportSdxcFlag = (1U << 4U), /*!< Card is SDXC */
kSD_SupportVoltage180v = (1U << 5U), /*!< card support 1.8v voltage*/
kSD_SupportSetBlockCountCmd = (1U << 6U), /*!< card support cmd23 flag*/
kSD_SupportSpeedClassControlCmd = (1U << 7U), /*!< card support speed class control flag */
};
/*!
* @brief SD card state
*
* Define the card structure including the necessary fields to identify and describe the card.
*/
typedef struct _sd_card
{
SDMMCHOST_CONFIG host; /*!< Host information */
sdcard_usr_param_t usrParam; /*!< user parameter */
bool isHostReady; /*!< use this flag to indicate if need host re-init or not*/
bool noInteralAlign; /*!< use this flag to disable sdmmc align. If disable, sdmmc will not make sure the
data buffer address is word align, otherwise all the transfer are align to low level driver */
uint32_t busClock_Hz; /*!< SD bus clock frequency united in Hz */
uint32_t relativeAddress; /*!< Relative address of the card */
uint32_t version; /*!< Card version */
uint32_t flags; /*!< Flags in _sd_card_flag */
uint32_t rawCid[4U]; /*!< Raw CID content */
uint32_t rawCsd[4U]; /*!< Raw CSD content */
uint32_t rawScr[2U]; /*!< Raw CSD content */
uint32_t ocr; /*!< Raw OCR content */
sd_cid_t cid; /*!< CID */
sd_csd_t csd; /*!< CSD */
sd_scr_t scr; /*!< SCR */
sd_status_t stat; /*!< sd 512 bit status */
uint32_t blockCount; /*!< Card total block number */
uint32_t blockSize; /*!< Card block size */
sd_timing_mode_t currentTiming; /*!< current timing mode */
sd_driver_strength_t driverStrength; /*!< driver strength */
sd_max_current_t maxCurrent; /*!< card current limit */
sdmmc_operation_voltage_t operationVoltage; /*!< card operation voltage */
} sd_card_t;
/*************************************************************************************************
* API
************************************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name SDCARD Function
* @{
*/
/*!
* @brief Initializes the card on a specific host controller.
* @deprecated Do not use this function. It has been superceded by @ref SD_HostInit,SD_CardInit.
* This function initializes the card on a specific host controller, it is consist of
* host init, card detect, card init function, however user can ignore this high level function,
* instead of use the low level function, such as SD_CardInit, SD_HostInit, SD_CardDetect.
*
* @param card Card descriptor.
* @retval kStatus_SDMMC_HostNotReady host is not ready.
* @retval kStatus_SDMMC_GoIdleFailed Go idle failed.
* @retval kStatus_SDMMC_NotSupportYet Card not support.
* @retval kStatus_SDMMC_SendOperationConditionFailed Send operation condition failed.
* @retval kStatus_SDMMC_AllSendCidFailed Send CID failed.
* @retval kStatus_SDMMC_SendRelativeAddressFailed Send relative address failed.
* @retval kStatus_SDMMC_SendCsdFailed Send CSD failed.
* @retval kStatus_SDMMC_SelectCardFailed Send SELECT_CARD command failed.
* @retval kStatus_SDMMC_SendScrFailed Send SCR failed.
* @retval kStatus_SDMMC_SetBusWidthFailed Set bus width failed.
* @retval kStatus_SDMMC_SwitchHighSpeedFailed Switch high speed failed.
* @retval kStatus_SDMMC_SetCardBlockSizeFailed Set card block size failed.
* @retval kStatus_Success Operate successfully.
*/
status_t SD_Init(sd_card_t *card);
/*!
* @brief Deinitializes the card.
* @deprecated Do not use this function. It has been superceded by @ref SD_HostDeinit,SD_CardDeinit.
* This function deinitializes the specific card and host.
*
* @param card Card descriptor.
*/
void SD_Deinit(sd_card_t *card);
/*!
* @brief Initializes the card.
*
* This function initializes the card only, make sure the host is ready when call this function,
* otherwise it will return kStatus_SDMMC_HostNotReady.
*
* @param card Card descriptor.
* @retval kStatus_SDMMC_HostNotReady host is not ready.
* @retval kStatus_SDMMC_GoIdleFailed Go idle failed.
* @retval kStatus_SDMMC_NotSupportYet Card not support.
* @retval kStatus_SDMMC_SendOperationConditionFailed Send operation condition failed.
* @retval kStatus_SDMMC_AllSendCidFailed Send CID failed.
* @retval kStatus_SDMMC_SendRelativeAddressFailed Send relative address failed.
* @retval kStatus_SDMMC_SendCsdFailed Send CSD failed.
* @retval kStatus_SDMMC_SelectCardFailed Send SELECT_CARD command failed.
* @retval kStatus_SDMMC_SendScrFailed Send SCR failed.
* @retval kStatus_SDMMC_SetBusWidthFailed Set bus width failed.
* @retval kStatus_SDMMC_SwitchHighSpeedFailed Switch high speed failed.
* @retval kStatus_SDMMC_SetCardBlockSizeFailed Set card block size failed.
* @retval kStatus_Success Operate successfully.
*/
status_t SD_CardInit(sd_card_t *card);
/*!
* @brief Deinitializes the card.
*
* This function deinitializes the specific card.
*
* @param card Card descriptor.
*/
void SD_CardDeinit(sd_card_t *card);
/*!
* @brief initialize the host.
*
* This function deinitializes the specific host.
*
* @param card Card descriptor.
*/
status_t SD_HostInit(sd_card_t *card);
/*!
* @brief Deinitializes the host.
*
* This function deinitializes the host.
*
* @param card Card descriptor.
*/
void SD_HostDeinit(sd_card_t *card);
/*!
* @brief reset the host.
*
* This function reset the specific host.
*
* @param host host descriptor.
*/
void SD_HostReset(SDMMCHOST_CONFIG *host);
/*!
* @brief power on card.
*
* The power on operation depend on host or the user define power on function.
* @param base host base address.
* @param pwr user define power control configuration
*/
void SD_PowerOnCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr);
/*!
* @brief power off card.
*
* The power off operation depend on host or the user define power on function.
* @param base host base address.
* @param pwr user define power control configuration
*/
void SD_PowerOffCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr);
/*!
* @brief sd wait card detect function.
*
* Detect card through GPIO, CD, DATA3.
*
* @param card card descriptor.
* @param card detect configuration
* @param waitCardStatus wait card detect status
*/
status_t SD_WaitCardDetectStatus(SDMMCHOST_TYPE *hostBase, const sdmmchost_detect_card_t *cd, bool waitCardStatus);
/*!
* @brief sd card present check function.
*
* @param card card descriptor.
*/
bool SD_IsCardPresent(sd_card_t *card);
/*!
* @brief Checks whether the card is write-protected.
*
* This function checks if the card is write-protected via the CSD register.
*
* @param card The specific card.
* @retval true Card is read only.
* @retval false Card isn't read only.
*/
bool SD_CheckReadOnly(sd_card_t *card);
/*!
* @brief Send SELECT_CARD command to set the card to be transfer state or not.
*
* @param card Card descriptor.
* @param isSelected True to set the card into transfer state, false to disselect.
* @retval kStatus_SDMMC_TransferFailed Transfer failed.
* @retval kStatus_Success Operate successfully.
*/
status_t SD_SelectCard(sd_card_t *card, bool isSelected);
/*!
* @brief Send ACMD13 to get the card current status.
*
* @param card Card descriptor.
* @retval kStatus_SDMMC_TransferFailed Transfer failed.
* @retval kStatus_SDMMC_SendApplicationCommandFailed send application command failed.
* @retval kStatus_Success Operate successfully.
*/
status_t SD_ReadStatus(sd_card_t *card);
/*!
* @brief Reads blocks from the specific card.
*
* This function reads blocks from the specific card with default block size defined by the
* SDHC_CARD_DEFAULT_BLOCK_SIZE.
*
* @param card Card descriptor.
* @param buffer The buffer to save the data read from card.
* @param startBlock The start block index.
* @param blockCount The number of blocks to read.
* @retval kStatus_InvalidArgument Invalid argument.
* @retval kStatus_SDMMC_CardNotSupport Card not support.
* @retval kStatus_SDMMC_NotSupportYet Not support now.
* @retval kStatus_SDMMC_WaitWriteCompleteFailed Send status failed.
* @retval kStatus_SDMMC_TransferFailed Transfer failed.
* @retval kStatus_SDMMC_StopTransmissionFailed Stop transmission failed.
* @retval kStatus_Success Operate successfully.
*/
status_t SD_ReadBlocks(sd_card_t *card, uint8_t *buffer, uint32_t startBlock, uint32_t blockCount);
/*!
* @brief Writes blocks of data to the specific card.
*
* This function writes blocks to the specific card with default block size 512 bytes.
*
* @param card Card descriptor.
* @param buffer The buffer holding the data to be written to the card.
* @param startBlock The start block index.
* @param blockCount The number of blocks to write.
* @retval kStatus_InvalidArgument Invalid argument.
* @retval kStatus_SDMMC_NotSupportYet Not support now.
* @retval kStatus_SDMMC_CardNotSupport Card not support.
* @retval kStatus_SDMMC_WaitWriteCompleteFailed Send status failed.
* @retval kStatus_SDMMC_TransferFailed Transfer failed.
* @retval kStatus_SDMMC_StopTransmissionFailed Stop transmission failed.
* @retval kStatus_Success Operate successfully.
*/
status_t SD_WriteBlocks(sd_card_t *card, const uint8_t *buffer, uint32_t startBlock, uint32_t blockCount);
/*!
* @brief Erases blocks of the specific card.
*
* This function erases blocks of the specific card with default block size 512 bytes.
*
* @param card Card descriptor.
* @param startBlock The start block index.
* @param blockCount The number of blocks to erase.
* @retval kStatus_InvalidArgument Invalid argument.
* @retval kStatus_SDMMC_WaitWriteCompleteFailed Send status failed.
* @retval kStatus_SDMMC_TransferFailed Transfer failed.
* @retval kStatus_SDMMC_WaitWriteCompleteFailed Send status failed.
* @retval kStatus_Success Operate successfully.
*/
status_t SD_EraseBlocks(sd_card_t *card, uint32_t startBlock, uint32_t blockCount);
/*!
* @brief select card driver strength
* select card driver strength
* @param card Card descriptor.
* @param driverStrength Driver strength
*/
status_t SD_SetDriverStrength(sd_card_t *card, sd_driver_strength_t driverStrength);
/*!
* @brief select max current
* select max operation current
* @param card Card descriptor.
* @param maxCurrent Max current
*/
status_t SD_SetMaxCurrent(sd_card_t *card, sd_max_current_t maxCurrent);
/* @} */
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* _FSL_SD_H_*/
@@ -0,0 +1,507 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_SDIO_H_
#define _FSL_SDIO_H_
#include "fsl_sdmmc_common.h"
/*!
* @addtogroup SDIOCARD
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Middleware version. */
#define FSL_SDIO_DRIVER_VERSION (MAKE_VERSION(2U, 2U, 11U)) /*2.2.11*/
/*!@brief sdio device support maximum IO number */
#ifndef FSL_SDIO_MAX_IO_NUMS
#define FSL_SDIO_MAX_IO_NUMS (7U)
#endif
/*!@brief sdio card descriptor */
typedef struct _sdio_card sdio_card_t;
/*!@brief sdio io handler */
typedef void (*sdio_io_irq_handler_t)(sdio_card_t *card, uint32_t func);
/*! @brief sdio io read/write direction */
typedef enum _sdio_io_direction
{
kSDIO_IORead = 0U, /*!< io read */
kSDIO_IOWrite = 1U, /*!< io write */
} sdio_io_direction_t;
/*!
* @brief SDIO card state
*
* Define the card structure including the necessary fields to identify and describe the card.
*/
struct _sdio_card
{
SDMMCHOST_CONFIG host; /*!< Host information */
sdiocard_usr_param_t usrParam; /*!< user parameter */
bool noInternalAlign; /*!< use this flag to disable sdmmc align. If disable, sdmmc will not make sure the
data buffer address is word align, otherwise all the transfer are align to low level driver */
bool isHostReady; /*!< use this flag to indicate if need host re-init or not*/
bool memPresentFlag; /*!< indicate if memory present */
uint32_t busClock_Hz; /*!< SD bus clock frequency united in Hz */
uint32_t relativeAddress; /*!< Relative address of the card */
uint8_t sdVersion; /*!< SD version */
sd_timing_mode_t currentTiming; /*!< current timing mode */
sd_driver_strength_t driverStrength; /*!< driver strength */
sd_max_current_t maxCurrent; /*!< card current limit */
sdmmc_operation_voltage_t operationVoltage; /*!< card operation voltage */
uint8_t sdioVersion; /*!< SDIO version */
uint8_t cccrVersioin; /*!< CCCR version */
uint8_t ioTotalNumber; /*!< total number of IO function */
uint32_t cccrflags; /*!< Flags in _sd_card_flag */
uint32_t io0blockSize; /*!< record the io0 block size*/
uint32_t ocr; /*!< Raw OCR content, only 24bit avalible for SDIO card */
uint32_t commonCISPointer; /*!< point to common CIS */
sdio_common_cis_t commonCIS; /*!< CIS table */
/* io registers/IRQ handler */
sdio_fbr_t ioFBR[FSL_SDIO_MAX_IO_NUMS]; /*!< FBR table */
sdio_func_cis_t funcCIS[FSL_SDIO_MAX_IO_NUMS]; /*!< function CIS table*/
sdio_io_irq_handler_t ioIRQHandler[FSL_SDIO_MAX_IO_NUMS]; /*!< io IRQ handler */
uint8_t ioIntIndex; /*!< used to record current enabled io interrupt index */
uint8_t ioIntNums; /*!< used to record total enabled io interrupt numbers */
};
/*************************************************************************************************
* API
************************************************************************************************/
#if defined(__cplusplus)
extern "C"
{
#endif
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief SDIO card init function
*
* @param card Card descriptor.
* @retval kStatus_SDMMC_GoIdleFailed
* @retval kStatus_SDMMC_HandShakeOperationConditionFailed
* @retval kStatus_SDMMC_SDIO_InvalidCard
* @retval kStatus_SDMMC_SDIO_InvalidVoltage
* @retval kStatus_SDMMC_SendRelativeAddressFailed
* @retval kStatus_SDMMC_SelectCardFailed
* @retval kStatus_SDMMC_SDIO_SwitchHighSpeedFail
* @retval kStatus_SDMMC_SDIO_ReadCISFail
* @retval kStatus_SDMMC_TransferFailed
* @retval kStatus_Success
*/
status_t SDIO_Init(sdio_card_t *card);
/*!
* @brief SDIO card deinit, include card and host deinit.
*
* @param card Card descriptor.
*/
void SDIO_Deinit(sdio_card_t *card);
/*!
* @brief Initializes the card.
*
* This function initializes the card only, make sure the host is ready when call this function,
* otherwise it will return kStatus_SDMMC_HostNotReady.
*
* @param card Card descriptor.
* @retval kStatus_SDMMC_HostNotReady host is not ready.
* @retval kStatus_SDMMC_GoIdleFailed Go idle failed.
* @retval kStatus_SDMMC_NotSupportYet Card not support.
* @retval kStatus_SDMMC_SendOperationConditionFailed Send operation condition failed.
* @retval kStatus_SDMMC_AllSendCidFailed Send CID failed.
* @retval kStatus_SDMMC_SendRelativeAddressFailed Send relative address failed.
* @retval kStatus_SDMMC_SendCsdFailed Send CSD failed.
* @retval kStatus_SDMMC_SelectCardFailed Send SELECT_CARD command failed.
* @retval kStatus_SDMMC_SendScrFailed Send SCR failed.
* @retval kStatus_SDMMC_SetBusWidthFailed Set bus width failed.
* @retval kStatus_SDMMC_SwitchHighSpeedFailed Switch high speed failed.
* @retval kStatus_SDMMC_SetCardBlockSizeFailed Set card block size failed.
* @retval kStatus_Success Operate successfully.
*/
status_t SDIO_CardInit(sdio_card_t *card);
/*!
* @brief Deinitializes the card.
*
* This function deinitializes the specific card.
*
* @param card Card descriptor.
*/
void SDIO_CardDeinit(sdio_card_t *card);
/*!
* @brief initialize the host.
*
* This function deinitializes the specific host.
*
* @param card Card descriptor.
*/
status_t SDIO_HostInit(sdio_card_t *card);
/*!
* @brief Deinitializes the host.
*
* This function deinitializes the host.
*
* @param card Card descriptor.
*/
void SDIO_HostDeinit(sdio_card_t *card);
/*!
* @brief reset the host.
*
* This function reset the specific host.
*
* @param host host descriptor.
*/
void SDIO_HostReset(SDMMCHOST_CONFIG *host);
/*!
* @brief power on card.
*
* The power on operation depend on host or the user define power on function.
* @param base host base address.
* @param pwr user define power control configuration
*/
void SDIO_PowerOnCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr);
/*!
* @brief power on card.
*
* The power off operation depend on host or the user define power on function.
* @param base host base address.
* @param pwr user define power control configuration
*/
void SDIO_PowerOffCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr);
/*!
* @brief set SDIO card to inactive state
*
* @param card Card descriptor.
* @retval kStatus_SDMMC_TransferFailed
* @retval kStatus_Success
*/
status_t SDIO_CardInActive(sdio_card_t *card);
/*!
* @brief get SDIO card capability
*
* @param card Card descriptor.
* @param function IO number
* @retval kStatus_SDMMC_TransferFailed
* @retval kStatus_Success
*/
status_t SDIO_GetCardCapability(sdio_card_t *card, sdio_func_num_t func);
/*!
* @brief set SDIO card block size
*
* @param card Card descriptor.
* @param function io number
* @param block size
* @retval kStatus_SDMMC_SetCardBlockSizeFailed
* @retval kStatus_SDMMC_SDIO_InvalidArgument
* @retval kStatus_Success
*/
status_t SDIO_SetBlockSize(sdio_card_t *card, sdio_func_num_t func, uint32_t blockSize);
/*!
* @brief set SDIO card reset
*
* @param card Card descriptor.
* @retval kStatus_SDMMC_TransferFailed
* @retval kStatus_Success
*/
status_t SDIO_CardReset(sdio_card_t *card);
/*!
* @brief set SDIO card data bus width
*
* @param card Card descriptor.
* @param data bus width
* @retval kStatus_SDMMC_TransferFailed
* @retval kStatus_Success
*/
status_t SDIO_SetDataBusWidth(sdio_card_t *card, sdio_bus_width_t busWidth);
/*!
* @brief switch the card to high speed
*
* @param card Card descriptor.
* @retval kStatus_SDMMC_TransferFailed
* @retval kStatus_SDMMC_SDIO_SwitchHighSpeedFail
* @retval kStatus_Success
*/
status_t SDIO_SwitchToHighSpeed(sdio_card_t *card);
/*!
* @brief read SDIO card CIS for each function
*
* @param card Card descriptor.
* @param function io number
* @param tuple code list
* @param tuple code number
* @retval kStatus_SDMMC_SDIO_ReadCISFail
* @retval kStatus_SDMMC_TransferFailed
* @retval kStatus_Success
*/
status_t SDIO_ReadCIS(sdio_card_t *card, sdio_func_num_t func, const uint32_t *tupleList, uint32_t tupleNum);
/*!
* @brief sdio wait card detect function.
*
* Detect card through GPIO, CD, DATA3.
*
* @param card card descriptor.
* @param card detect configuration
* @param waitCardStatus wait card detect status
*/
status_t SDIO_WaitCardDetectStatus(SDMMCHOST_TYPE *hostBase,
const sdmmchost_detect_card_t *cd,
bool waitCardStatus);
/*!
* @brief sdio card present check function.
*
* @param card card descriptor.
*/
bool SDIO_IsCardPresent(sdio_card_t *card);
/* @} */
/*!
* @name IO operations
* @{
*/
/*!
* @brief IO direct write transfer function
*
* @param card Card descriptor.
* @param function IO numner
* @param register address
* @param the data pinter to write
* @param raw flag, indicate read after write or write only
* @retval kStatus_SDMMC_TransferFailed
* @retval kStatus_Success
*/
status_t SDIO_IO_Write_Direct(sdio_card_t *card, sdio_func_num_t func, uint32_t regAddr, uint8_t *data, bool raw);
/*!
* @brief IO direct read transfer function
*
* @param card Card descriptor.
* @param function IO number
* @param register address
* @param data pointer to read
* @retval kStatus_SDMMC_TransferFailed
* @retval kStatus_Success
*/
status_t SDIO_IO_Read_Direct(sdio_card_t *card, sdio_func_num_t func, uint32_t regAddr, uint8_t *data);
/*!
* @brief IO direct read/write transfer function
*
* @param card Card descriptor.
* @param direction io access direction, please reference sdio_io_direction_t.
* @param function IO number
* @param register address
* @param dataIn data to write
* @param dataOut data pointer for readback data, support both for read and write, when application want readback
* the data after write command, dataOut should not be NULL.
* @retval kStatus_SDMMC_TransferFailed
* @retval kStatus_Success
*/
status_t SDIO_IO_RW_Direct(sdio_card_t *card,
sdio_io_direction_t direction,
sdio_func_num_t func,
uint32_t regAddr,
uint8_t dataIn,
uint8_t *dataOut);
/*!
* @brief IO extended write transfer function
*
* @param card Card descriptor.
* @param function IO number
* @param register address
* @param data buffer to write
* @param data count
* @param write flags
* @retval kStatus_SDMMC_TransferFailed
* @retval kStatus_SDMMC_SDIO_InvalidArgument
* @retval kStatus_Success
*/
status_t SDIO_IO_Write_Extended(
sdio_card_t *card, sdio_func_num_t func, uint32_t regAddr, uint8_t *buffer, uint32_t count, uint32_t flags);
/*!
* @brief IO extended read transfer function
*
* @param card Card descriptor.
* @param function IO number
* @param register address
* @param data buffer to read
* @param data count
* @param write flags
* @retval kStatus_SDMMC_TransferFailed
* @retval kStatus_SDMMC_SDIO_InvalidArgument
* @retval kStatus_Success
*/
status_t SDIO_IO_Read_Extended(
sdio_card_t *card, sdio_func_num_t func, uint32_t regAddr, uint8_t *buffer, uint32_t count, uint32_t flags);
/*!
* @brief enable IO interrupt
*
* @param card Card descriptor.
* @param function IO number
* @param enable/disable flag
* @retval kStatus_SDMMC_TransferFailed
* @retval kStatus_Success
*/
status_t SDIO_EnableIOInterrupt(sdio_card_t *card, sdio_func_num_t func, bool enable);
/*!
* @brief enable IO and wait IO ready
*
* @param card Card descriptor.
* @param function IO number
* @param enable/disable flag
* @retval kStatus_SDMMC_TransferFailed
* @retval kStatus_Success
*/
status_t SDIO_EnableIO(sdio_card_t *card, sdio_func_num_t func, bool enable);
/*!
* @brief select IO
*
* @param card Card descriptor.
* @param function IO number
* @retval kStatus_SDMMC_TransferFailed
* @retval kStatus_Success
*/
status_t SDIO_SelectIO(sdio_card_t *card, sdio_func_num_t func);
/*!
* @brief Abort IO transfer
*
* @param card Card descriptor.
* @param function IO number
* @retval kStatus_SDMMC_TransferFailed
* @retval kStatus_Success
*/
status_t SDIO_AbortIO(sdio_card_t *card, sdio_func_num_t func);
/*!
* @brief Set driver strength.
*
* @param card Card descriptor.
* @param driverStrength target driver strength.
* @retval kStatus_SDMMC_TransferFailed
* @retval kStatus_Success
*/
status_t SDIO_SetDriverStrength(sdio_card_t *card, sd_driver_strength_t driverStrength);
/*!
* @brief Enable/Disable Async interrupt.
*
* @param card Card descriptor.
* @param func function io number.
* @param enable true is enable, false is disable.
* @retval kStatus_SDMMC_TransferFailed
* @retval kStatus_Success
*/
status_t SDIO_EnableAsyncInterrupt(sdio_card_t *card, bool enable);
/*!
* @brief Get pending interrupt.
*
* @param card Card descriptor.
* @param pendingInt pointer store pending interrupt
* @retval kStatus_SDMMC_TransferFailed
* @retval kStatus_Success
*/
status_t SDIO_GetPendingInterrupt(sdio_card_t *card, uint8_t *pendingInt);
/*!
* @brief sdio card io transfer function.
* This function can be used for trnansfer direct/extend command.
* Please pay attention to the non-align data buffer address transfer,
* if data buffer address can not meet host controller internal DMA requirement, sdio driver will try to use
internal align buffer if data size is not bigger than internal buffer size,
* Align address transfer always can get a better performance, so if application want sdio driver make sure buffer
address align,
* please redefine the SDMMC_GLOBAL_BUFFER_SIZE macro to a value which is big enough for your application.
*
* @param card card descriptor.
* @param cmd command to transfer
* @param argument argument to transfer
* @param blockSize used for block mode.
* @param txData tx buffer pointer or NULL
* @param rxData rx buffer pointer or NULL
* @param dataSize transfer data size
* @param response reponse pointer, if application want read response back, please set it to a NON-NULL pointer.
*/
status_t SDIO_IO_Transfer(sdio_card_t *card,
sdio_command_t cmd,
uint32_t argument,
uint32_t blockSize,
uint8_t *txData,
uint8_t *rxData,
uint16_t dataSize,
uint32_t *response);
/*!
* @brief sdio set io IRQ handler.
*
* @param card card descriptor.
* @param func function io number.
* @param handler, io IRQ handler.
*/
void SDIO_SetIOIRQHandler(sdio_card_t *card, sdio_func_num_t func, sdio_io_irq_handler_t handler);
/*!
* @brief sdio card io pending interrupt handle function.
* This function is used to handle the pending io interrupt.
* To reigster a IO IRQ handler,
* @code
* //initialization
* SDIO_EnableIOInterrupt(card, 0, true);
* SDIO_SetIOIRQHandler(card, 0, func0_handler);
* //call it in interrupt callback
* SDIO_HandlePendingIOInterrupt(card);
* @code
* To releae a IO IRQ handler,
* @code
* SDIO_EnableIOInterrupt(card, 0, false);
* SDIO_SetIOIRQHandler(card, 0, NULL);
* @code
* @param card card descriptor.
*
* @retval kStatus_SDMMC_TransferFailed
* @retval kStatus_Success
*/
status_t SDIO_HandlePendingIOInterrupt(sdio_card_t *card);
/* @} */
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* _FSL_SDIO_H_*/
@@ -0,0 +1,258 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_SDMMC_COMMON_H_
#define _FSL_SDMMC_COMMON_H_
#include "fsl_common.h"
#include "fsl_sdmmc_host.h"
#include "fsl_sdmmc_spec.h"
#include "stdlib.h"
/*!
* @addtogroup CARD
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Middleware version. */
#define FSL_SDMMC_DRIVER_VERSION (MAKE_VERSION(2U, 2U, 11U)) /*2.2.11*/
/*! @brief Reverse byte sequence in uint32_t */
#define SWAP_WORD_BYTE_SEQUENCE(x) (__REV(x))
/*! @brief Reverse byte sequence for each half word in uint32_t */
#define SWAP_HALF_WROD_BYTE_SEQUENCE(x) (__REV16(x))
/*! @brief Maximum loop count to check the card operation voltage range */
#define FSL_SDMMC_MAX_VOLTAGE_RETRIES (1000U)
/*! @brief Maximum loop count to send the cmd */
#define FSL_SDMMC_MAX_CMD_RETRIES (10U)
/*! @brief Default block size */
#define FSL_SDMMC_DEFAULT_BLOCK_SIZE (512U)
#ifndef SDMMC_GLOBAL_BUFFER_SIZE
/*! @brief SDMMC global data buffer size, word unit*/
#define SDMMC_GLOBAL_BUFFER_SIZE (128U)
#endif
/*! @brief SDMMC enable software tuning */
#define SDMMC_ENABLE_SOFTWARE_TUNING (0U)
/* Common definition for cache line size align */
#if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL
#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#if defined(FSL_FEATURE_L2DCACHE_LINESIZE_BYTE)
#define SDMMC_DATA_BUFFER_ALIGN_CACHE MAX(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE, FSL_FEATURE_L2DCACHE_LINESIZE_BYTE)
#else
#define SDMMC_DATA_BUFFER_ALIGN_CACHE FSL_FEATURE_L1DCACHE_LINESIZE_BYTE
#endif
#else
#define SDMMC_DATA_BUFFER_ALIGN_CACHE 1
#endif
#else
#define SDMMC_DATA_BUFFER_ALIGN_CACHE 1
#endif
/*! @brief SD/MMC error log. */
#if defined SDMMC_ENABLE_LOG_PRINT
#include "fsl_debug_console.h"
#define SDMMC_LOG(...) PRINTF(__VA_ARGS__)
#else
#define SDMMC_LOG(format, ...)
#endif
/*! @brief SD/MMC card API's running status. */
enum _sdmmc_status
{
kStatus_SDMMC_NotSupportYet = MAKE_STATUS(kStatusGroup_SDMMC, 0U), /*!< Haven't supported */
kStatus_SDMMC_TransferFailed = MAKE_STATUS(kStatusGroup_SDMMC, 1U), /*!< Send command failed */
kStatus_SDMMC_SetCardBlockSizeFailed = MAKE_STATUS(kStatusGroup_SDMMC, 2U), /*!< Set block size failed */
kStatus_SDMMC_HostNotSupport = MAKE_STATUS(kStatusGroup_SDMMC, 3U), /*!< Host doesn't support */
kStatus_SDMMC_CardNotSupport = MAKE_STATUS(kStatusGroup_SDMMC, 4U), /*!< Card doesn't support */
kStatus_SDMMC_AllSendCidFailed = MAKE_STATUS(kStatusGroup_SDMMC, 5U), /*!< Send CID failed */
kStatus_SDMMC_SendRelativeAddressFailed = MAKE_STATUS(kStatusGroup_SDMMC, 6U), /*!< Send relative address failed */
kStatus_SDMMC_SendCsdFailed = MAKE_STATUS(kStatusGroup_SDMMC, 7U), /*!< Send CSD failed */
kStatus_SDMMC_SelectCardFailed = MAKE_STATUS(kStatusGroup_SDMMC, 8U), /*!< Select card failed */
kStatus_SDMMC_SendScrFailed = MAKE_STATUS(kStatusGroup_SDMMC, 9U), /*!< Send SCR failed */
kStatus_SDMMC_SetDataBusWidthFailed = MAKE_STATUS(kStatusGroup_SDMMC, 10U), /*!< Set bus width failed */
kStatus_SDMMC_GoIdleFailed = MAKE_STATUS(kStatusGroup_SDMMC, 11U), /*!< Go idle failed */
kStatus_SDMMC_HandShakeOperationConditionFailed =
MAKE_STATUS(kStatusGroup_SDMMC, 12U), /*!< Send Operation Condition failed */
kStatus_SDMMC_SendApplicationCommandFailed =
MAKE_STATUS(kStatusGroup_SDMMC, 13U), /*!< Send application command failed */
kStatus_SDMMC_SwitchFailed = MAKE_STATUS(kStatusGroup_SDMMC, 14U), /*!< Switch command failed */
kStatus_SDMMC_StopTransmissionFailed = MAKE_STATUS(kStatusGroup_SDMMC, 15U), /*!< Stop transmission failed */
kStatus_SDMMC_WaitWriteCompleteFailed = MAKE_STATUS(kStatusGroup_SDMMC, 16U), /*!< Wait write complete failed */
kStatus_SDMMC_SetBlockCountFailed = MAKE_STATUS(kStatusGroup_SDMMC, 17U), /*!< Set block count failed */
kStatus_SDMMC_SetRelativeAddressFailed = MAKE_STATUS(kStatusGroup_SDMMC, 18U), /*!< Set relative address failed */
kStatus_SDMMC_SwitchBusTimingFailed = MAKE_STATUS(kStatusGroup_SDMMC, 19U), /*!< Switch high speed failed */
kStatus_SDMMC_SendExtendedCsdFailed = MAKE_STATUS(kStatusGroup_SDMMC, 20U), /*!< Send EXT_CSD failed */
kStatus_SDMMC_ConfigureBootFailed = MAKE_STATUS(kStatusGroup_SDMMC, 21U), /*!< Configure boot failed */
kStatus_SDMMC_ConfigureExtendedCsdFailed = MAKE_STATUS(kStatusGroup_SDMMC, 22U), /*!< Configure EXT_CSD failed */
kStatus_SDMMC_EnableHighCapacityEraseFailed =
MAKE_STATUS(kStatusGroup_SDMMC, 23U), /*!< Enable high capacity erase failed */
kStatus_SDMMC_SendTestPatternFailed = MAKE_STATUS(kStatusGroup_SDMMC, 24U), /*!< Send test pattern failed */
kStatus_SDMMC_ReceiveTestPatternFailed = MAKE_STATUS(kStatusGroup_SDMMC, 25U), /*!< Receive test pattern failed */
kStatus_SDMMC_SDIO_ResponseError = MAKE_STATUS(kStatusGroup_SDMMC, 26U), /*!< sdio response error */
kStatus_SDMMC_SDIO_InvalidArgument =
MAKE_STATUS(kStatusGroup_SDMMC, 27U), /*!< sdio invalid argument response error */
kStatus_SDMMC_SDIO_SendOperationConditionFail =
MAKE_STATUS(kStatusGroup_SDMMC, 28U), /*!< sdio send operation condition fail */
kStatus_SDMMC_InvalidVoltage = MAKE_STATUS(kStatusGroup_SDMMC, 29U), /*!< invaild voltage */
kStatus_SDMMC_SDIO_SwitchHighSpeedFail = MAKE_STATUS(kStatusGroup_SDMMC, 30U), /*!< switch to high speed fail */
kStatus_SDMMC_SDIO_ReadCISFail = MAKE_STATUS(kStatusGroup_SDMMC, 31U), /*!< read CIS fail */
kStatus_SDMMC_SDIO_InvalidCard = MAKE_STATUS(kStatusGroup_SDMMC, 32U), /*!< invaild SDIO card */
kStatus_SDMMC_TuningFail = MAKE_STATUS(kStatusGroup_SDMMC, 33U), /*!< tuning fail */
kStatus_SDMMC_SwitchVoltageFail = MAKE_STATUS(kStatusGroup_SDMMC, 34U), /*!< switch voltage fail*/
kStatus_SDMMC_SwitchVoltage18VFail33VSuccess = MAKE_STATUS(kStatusGroup_SDMMC, 35U), /*!< switch voltage fail*/
kStatus_SDMMC_ReTuningRequest = MAKE_STATUS(kStatusGroup_SDMMC, 36U), /*!< retuning request */
kStatus_SDMMC_SetDriverStrengthFail = MAKE_STATUS(kStatusGroup_SDMMC, 37U), /*!< set driver strength fail */
kStatus_SDMMC_SetPowerClassFail = MAKE_STATUS(kStatusGroup_SDMMC, 38U), /*!< set power class fail */
kStatus_SDMMC_HostNotReady = MAKE_STATUS(kStatusGroup_SDMMC, 39U), /*!< host controller not ready */
kStatus_SDMMC_CardDetectFailed = MAKE_STATUS(kStatusGroup_SDMMC, 40U), /*!< card detect failed */
kStatus_SDMMC_AuSizeNotSetProperly = MAKE_STATUS(kStatusGroup_SDMMC, 41U), /*!< AU size not set properly */
};
/*! @brief card operation voltage */
typedef enum _sdmmc_operation_voltage
{
kCARD_OperationVoltageNone = 0U, /*!< indicate current voltage setting is not setting by suser*/
kCARD_OperationVoltage330V = 1U, /*!< card operation voltage around 3.3v */
kCARD_OperationVoltage300V = 2U, /*!< card operation voltage around 3.0v */
kCARD_OperationVoltage180V = 3U, /*!< card operation voltage around 1.8v */
} sdmmc_operation_voltage_t;
/*************************************************************************************************
* API
************************************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name common function
* @{
*/
/*!
* @brief Selects the card to put it into transfer state.
*
* @param base SDMMCHOST peripheral base address.
* @param transfer SDMMCHOST transfer function.
* @param relativeAddress Relative address.
* @param isSelected True to put card into transfer state.
* @retval kStatus_SDMMC_TransferFailed Transfer failed.
* @retval kStatus_Success Operate successfully.
*/
status_t SDMMC_SelectCard(SDMMCHOST_TYPE *base,
SDMMCHOST_TRANSFER_FUNCTION transfer,
uint32_t relativeAddress,
bool isSelected);
/*!
* @brief Sends an application command.
*
* @param base SDMMCHOST peripheral base address.
* @param transfer SDMMCHOST transfer function.
* @param relativeAddress Card relative address.
* @retval kStatus_SDMMC_TransferFailed Transfer failed.
* @retval kStatus_SDMMC_CardNotSupport Card doesn't support.
* @retval kStatus_Success Operate successfully.
*/
status_t SDMMC_SendApplicationCommand(SDMMCHOST_TYPE *base,
SDMMCHOST_TRANSFER_FUNCTION transfer,
uint32_t relativeAddress);
/*!
* @brief Sets the block count.
*
* @param base SDMMCHOST peripheral base address.
* @param transfer SDMMCHOST transfer function.
* @param blockCount Block count.
* @retval kStatus_SDMMC_TransferFailed Transfer failed.
* @retval kStatus_Success Operate successfully.
*/
status_t SDMMC_SetBlockCount(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer, uint32_t blockCount);
/*!
* @brief Sets the card to be idle state.
*
* @param base SDMMCHOST peripheral base address.
* @param transfer SDMMCHOST transfer function.
* @retval kStatus_SDMMC_TransferFailed Transfer failed.
* @retval kStatus_Success Operate successfully.
*/
status_t SDMMC_GoIdle(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer);
/*!
* @brief Sets data block size.
*
* @param base SDMMCHOST peripheral base address.
* @param transfer SDMMCHOST transfer function.
* @param blockSize Block size.
* @retval kStatus_SDMMC_TransferFailed Transfer failed.
* @retval kStatus_Success Operate successfully.
*/
status_t SDMMC_SetBlockSize(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer, uint32_t blockSize);
/*!
* @brief Sets card to inactive status
*
* @param base SDMMCHOST peripheral base address.
* @param transfer SDMMCHOST transfer function.
* @retval kStatus_SDMMC_TransferFailed Transfer failed.
* @retval kStatus_Success Operate successfully.
*/
status_t SDMMC_SetCardInactive(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer);
/*!
* @brief provide a simple delay function for sdmmc
*
* @param num Delay num*10000.
*/
void SDMMC_Delay(uint32_t num);
/*!
* @brief provide a voltage switch function for SD/SDIO card
* @deprecated Do not use this function, it has been superceded by SDMMC_SwitchToVoltage.
* @param base SDMMCHOST peripheral base address.
* @param transfer SDMMCHOST transfer function.
*/
status_t SDMMC_SwitchVoltage(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer);
/*!
* @brief provide a voltage switch function for SD/SDIO card
*
* @param base SDMMCHOST peripheral base address.
* @param transfer SDMMCHOST transfer function.
* @param switchVoltageFunc voltage switch function.
* @return error code.
*/
status_t SDMMC_SwitchToVoltage(SDMMCHOST_TYPE *base,
SDMMCHOST_TRANSFER_FUNCTION transfer,
sdmmchost_card_switch_voltage_t switchVoltageFunc);
/*!
* @brief excute tuning
*
* @param base SDMMCHOST peripheral base address.
* @param transfer Host transfer function
* @param tuningCmd Tuning cmd
* @param blockSize Tuning block size
*/
status_t SDMMC_ExecuteTuning(SDMMCHOST_TYPE *base,
SDMMCHOST_TRANSFER_FUNCTION transfer,
uint32_t tuningCmd,
uint32_t blockSize);
/* @} */
#if defined(__cplusplus)
}
#endif
/* @} */
#endif /* _FSL_SDMMC_COMMON_H_ */
@@ -0,0 +1,780 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_SDMMC_HOST_H
#define _FSL_SDMMC_HOST_H
#include "fsl_common.h"
#include "board.h"
#if defined(FSL_FEATURE_SOC_SDHC_COUNT) && FSL_FEATURE_SOC_SDHC_COUNT > 0U
#include "fsl_sdhc.h"
#elif defined(FSL_FEATURE_SOC_SDIF_COUNT) && FSL_FEATURE_SOC_SDIF_COUNT > 0U
#include "fsl_sdif.h"
#elif defined(FSL_FEATURE_SOC_USDHC_COUNT) && FSL_FEATURE_SOC_USDHC_COUNT > 0U
#include "fsl_usdhc.h"
#endif
/*!
* @addtogroup SDMMCHOST
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/* Common definition for support and not support macro */
#define SDMMCHOST_NOT_SUPPORT 0U /*!< use this define to indicate the host not support feature*/
#define SDMMCHOST_SUPPORT 1U /*!< use this define to indicate the host support feature*/
/* Common definition for board support SDR104/HS200/HS400 frequency */
/* SDR104 mode freq */
#if defined BOARD_SD_HOST_SUPPORT_SDR104_FREQ
#define SDMMCHOST_SUPPORT_SDR104_FREQ BOARD_SD_HOST_SUPPORT_SDR104_FREQ
#else
#define SDMMCHOST_SUPPORT_SDR104_FREQ SD_CLOCK_208MHZ
#endif
/* HS200 mode freq */
#if defined BOARD_SD_HOST_SUPPORT_HS200_FREQ
#define SDMMCHOST_SUPPORT_HS200_FREQ BOARD_SD_HOST_SUPPORT_HS200_FREQ
#else
#define SDMMCHOST_SUPPORT_HS200_FREQ MMC_CLOCK_HS200
#endif
/* HS400 mode freq */
#if defined BOARD_SD_HOST_SUPPORT_HS400_FREQ
#define SDMMCHOST_SUPPORT_HS400_FREQ BOARD_SD_HOST_SUPPORT_HS400_FREQ
#else
#define SDMMCHOST_SUPPORT_HS400_FREQ MMC_CLOCK_HS400
#endif
/* Common definition for SDMMCHOST transfer complete timeout */
#define SDMMCHOST_TRANSFER_COMPLETE_TIMEOUT (500U)
/* Common definition for card detect timeout */
#define SDMMCHOST_CARD_DETECT_TIMEOUT (~0U)
/* Common definition for IRQ */
#if defined(__CORTEX_M)
#define SDMMCHOST_SET_IRQ_PRIORITY(id, priority) (NVIC_SetPriority(id, priority))
#else
#define SDMMCHOST_SET_IRQ_PRIORITY(id, priority) (GIC_SetPriority(id, priority))
#endif
#define SDMMCHOST_ENABLE_IRQ(id) (EnableIRQ(id))
/*********************************************************SDHC**********************************************************/
#if (defined(FSL_FEATURE_SOC_SDHC_COUNT) && (FSL_FEATURE_SOC_SDHC_COUNT > 0U))
/*define host baseaddr ,clk freq, IRQ number*/
#define MMC_HOST_BASEADDR BOARD_SDHC_BASEADDR
#define MMC_HOST_CLK_FREQ BOARD_SDHC_CLK_FREQ
#define MMC_HOST_IRQ BOARD_SDHC_IRQ
#define SD_HOST_BASEADDR BOARD_SDHC_BASEADDR
#define SD_HOST_CLK_FREQ BOARD_SDHC_CLK_FREQ
#define SD_HOST_IRQ BOARD_SDHC_IRQ
/* define for card bus speed/strength cnofig */
#define CARD_BUS_FREQ_50MHZ (0U)
#define CARD_BUS_FREQ_100MHZ0 (0U)
#define CARD_BUS_FREQ_100MHZ1 (0U)
#define CARD_BUS_FREQ_200MHZ (0U)
#define CARD_BUS_STRENGTH_0 (0U)
#define CARD_BUS_STRENGTH_1 (0U)
#define CARD_BUS_STRENGTH_2 (0U)
#define CARD_BUS_STRENGTH_3 (0U)
#define CARD_BUS_STRENGTH_4 (0U)
#define CARD_BUS_STRENGTH_5 (0U)
#define CARD_BUS_STRENGTH_6 (0U)
#define CARD_BUS_STRENGTH_7 (0U)
#define SDMMCHOST_TYPE SDHC_Type
#define SDMMCHOST_CONFIG sdhc_host_t
#define SDMMCHOST_TRANSFER sdhc_transfer_t
#define SDMMCHOST_COMMAND sdhc_command_t
#define SDMMCHOST_DATA sdhc_data_t
#define SDMMCHOST_BUS_WIDTH_TYPE sdhc_data_bus_width_t
#define SDMMCHOST_CAPABILITY sdhc_capability_t
#define SDMMCHOST_BOOT_CONFIG sdhc_boot_config_t
#define CARD_DATA0_STATUS_MASK (kSDHC_Data0LineLevelFlag)
#define CARD_DATA0_NOT_BUSY (kSDHC_Data0LineLevelFlag)
#define CARD_DATA1_STATUS_MASK (kSDHC_Data1LineLevelFlag)
#define CARD_DATA2_STATUS_MASK (kSDHC_Data2LineLevelFlag)
#define CARD_DATA3_STATUS_MASK (kSDHC_Data3LineLevelFlag)
#define kSDMMCHOST_DATABUSWIDTH1BIT kSDHC_DataBusWidth1Bit /*!< 1-bit mode */
#define kSDMMCHOST_DATABUSWIDTH4BIT kSDHC_DataBusWidth4Bit /*!< 4-bit mode */
#define kSDMMCHOST_DATABUSWIDTH8BIT kSDHC_DataBusWidth8Bit /*!< 8-bit mode */
#define SDMMCHOST_STANDARD_TUNING_START (0U) /*!< standard tuning start point */
#define SDMMCHOST_TUINIG_STEP (1U) /*!< standard tuning step */
#define SDMMCHOST_RETUNING_TIMER_COUNT (4U) /*!< Re-tuning timer */
#define SDMMCHOST_TUNING_DELAY_MAX (0x7FU)
#define SDMMCHOST_RETUNING_REQUEST (1U)
#define SDMMCHOST_TUNING_ERROR (2U)
/* function pointer define */
#define SDMMCHOST_TRANSFER_FUNCTION sdhc_transfer_function_t
#define GET_SDMMCHOST_CAPABILITY(base, capability) (SDHC_GetCapability(base, capability))
#define GET_SDMMCHOST_STATUS(base) (SDHC_GetPresentStatusFlags(base))
#define SDMMCHOST_SET_CARD_CLOCK(base, sourceClock_HZ, busClock_HZ) (SDHC_SetSdClock(base, sourceClock_HZ, busClock_HZ))
#define SDMMCHOST_SET_CARD_BUS_WIDTH(base, busWidth) (SDHC_SetDataBusWidth(base, busWidth))
#define SDMMCHOST_SEND_CARD_ACTIVE(base, timeout) (SDHC_SetCardActive(base, timeout))
#define SDMMCHOST_SWITCH_VOLTAGE180V(base, enable18v)
#define SDMMCHOST_SWITCH_VOLTAGE120V(base, enable12v)
#define SDMMCHOST_CONFIG_IO_STRENGTH(speed, strength)
#define SDMMCHOST_EXECUTE_STANDARD_TUNING_ENABLE(base, flag)
#define SDMMCHOST_EXECUTE_STANDARD_TUNING_STATUS(base) (0U)
#define SDMMCHOST_EXECUTE_STANDARD_TUNING_RESULT(base) (1U)
#define SDMMCHOST_CONFIG_SD_IO(speed, strength)
#define SDMMCHOST_CONFIG_MMC_IO(speed, strength)
#define SDMMCHOST_ENABLE_DDR_MODE(base, flag, nibblePos)
#define SDMMCHOST_FORCE_SDCLOCK_ON(base, enable)
#define SDMMCHOST_EXECUTE_MANUAL_TUNING_ENABLE(base, flag)
#define SDMMCHOST_ADJUST_MANUAL_TUNING_DELAY(base, delay)
#define SDMMCHOST_AUTO_MANUAL_TUNING_ENABLE(base, flag)
#define SDMMCHOST_ENABLE_CARD_CLOCK(base, enable) (SDHC_EnableSdClock(base, enable))
#define SDMMCHOST_RESET_TUNING(base, timeout)
#define SDMMCHOST_CHECK_TUNING_ERROR(base) (0U)
#define SDMMCHOST_ADJUST_TUNING_DELAY(base, delay)
#define SDMMCHOST_AUTO_STANDARD_RETUNING_TIMER(base)
#define SDMMCHOST_TRANSFER_DATA_ERROR kStatus_SDHC_TransferDataFailed
#define SDMMCHOST_TRANSFER_CMD_ERROR kStatus_SDHC_SendCommandFailed
#define SDMMCHOST_ENABLE_HS400_MODE(base, flag)
#define SDMMCHOST_RESET_STROBE_DLL(base)
#define SDMMCHOST_ENABLE_STROBE_DLL(base, flag)
#define SDMMCHOST_CONFIG_STROBE_DLL(base, delay, updateInterval)
#define SDMMCHOST_GET_STROBE_DLL_STATUS(base)
/* sd card power */
#define SDMMCHOST_INIT_SD_POWER()
#define SDMMCHOST_ENABLE_SD_POWER(enable)
#define SDMMCHOST_SWITCH_VCC_TO_180V()
#define SDMMCHOST_SWITCH_VCC_TO_330V()
/* mmc card power */
#define SDMMCHOST_INIT_MMC_POWER()
#define SDMMCHOST_ENABLE_MMC_POWER(enable)
#define SDMMCHOST_ENABLE_TUNING_FLAG(data)
#define SDMMCHOST_ENABLE_BOOT_FLAG(data)
#define SDMMCHOST_ENABLE_BOOT_CONTINOUS_FLAG(data)
#define SDMMCHOST_GET_HOST_CONFIG_BLOCK_SIZE(config) (0U)
#define SDMMCHOST_GET_HOST_CONFIG_BLOCK_COUNT(config) (0U)
#define SDMMCHOST_GET_HOST_CONFIG_BOOT_MODE(config) (0U)
#define SDMMCHOST_EMPTY_CMD_FLAG(command)
#define SDMMCHOST_CARD_DETECT_GPIO_INTERRUPT_HANDLER BOARD_SDHC_CD_PORT_IRQ_HANDLER
#define SDMMCHOST_CARD_DETECT_IRQ BOARD_SDHC_CD_PORT_IRQ
/* sd card detect through host CD */
#define SDMMCHOST_CARD_DETECT_INSERT_ENABLE(base) (SDHC_EnableInterruptStatus(base, kSDHC_CardInsertionFlag))
#define SDMMCHOST_CARD_DETECT_REMOVE_ENABLE(base) (SDHC_EnableInterruptStatus(base, kSDHC_CardRemovalFlag))
#define SDMMCHOST_CARD_DETECT_INSERT_STATUS(base) (SDHC_GetInterruptStatusFlags(base) & kSDHC_CardInsertionFlag)
#define SDMMCHOST_CARD_DETECT_REMOVE_STATUS(base) (SDHC_GetInterruptStatusFlags(base, kSDHC_CardRemovalFlag))
#define SDMMCHOST_CARD_DETECT_INSERT_INTERRUPT_ENABLE(base) (SDHC_EnableInterruptSignal(base, kSDHC_CardInsertionFlag))
#define SDMMCHOST_CARD_DETECT_INSERT_INTERRUPT_DISABLE(base) \
(SDHC_DisableInterruptSignal(base, kSDHC_CardInsertionFlag))
#define SDMMCHOST_CARD_DETECT_REMOVE_INTERRUPT_ENABLE(base) (SDHC_EnableInterruptSignal(base, kSDHC_CardRemovalFlag))
#define SDMMCHOST_CARD_DETECT_DATA3_ENABLE(base, flag) (SDHC_CardDetectByData3(base, flag))
#define SDMMCHOST_ENABLE_MMC_BOOT(base, flag)
#define SDMMCHOST_SETMMCBOOTCONFIG(base, config) (SDHC_SetMmcBootConfig(base, config))
/* define card detect pin voltage level when card inserted */
#if defined BOARD_SDHC_CARD_INSERT_CD_LEVEL
#define SDMMCHOST_CARD_INSERT_CD_LEVEL BOARD_SDHC_CARD_INSERT_CD_LEVEL
#else
#define SDMMCHOST_CARD_INSERT_CD_LEVEL (0U)
#endif
#define SDMMCHOST_AUTO_TUNING_ENABLE(base, flag)
#define SDMMCHOST_ENABLE_SDIO_INT(base) \
SDHC_EnableInterruptStatus(base, kSDHC_CardInterruptFlag); \
SDHC_EnableInterruptSignal(base, kSDHC_CardInterruptFlag)
#define SDMMCHOST_DISABLE_SDIO_INT(base) \
SDHC_DisableInterruptStatus(base, kSDHC_CardInterruptFlag); \
SDHC_DisableInterruptSignal(base, kSDHC_CardInterruptFlag)
/*! @brief SDHC host capability*/
enum _host_capability
{
kSDMMCHOST_SupportAdma = kSDHC_SupportAdmaFlag,
kSDMMCHOST_SupportHighSpeed = kSDHC_SupportHighSpeedFlag,
kSDMMCHOST_SupportDma = kSDHC_SupportDmaFlag,
kSDMMCHOST_SupportSuspendResume = kSDHC_SupportSuspendResumeFlag,
kSDMMCHOST_SupportV330 = kSDHC_SupportV330Flag,
kSDMMCHOST_SupportV300 = SDMMCHOST_NOT_SUPPORT,
kSDMMCHOST_SupportV180 = SDMMCHOST_NOT_SUPPORT,
kSDMMCHOST_SupportV120 = SDMMCHOST_NOT_SUPPORT,
kSDMMCHOST_Support4BitBusWidth = kSDHC_Support4BitFlag,
kSDMMCHOST_Support8BitBusWidth = kSDHC_Support8BitFlag,
kSDMMCHOST_SupportDDR50 = SDMMCHOST_NOT_SUPPORT,
kSDMMCHOST_SupportSDR104 = SDMMCHOST_NOT_SUPPORT,
kSDMMCHOST_SupportSDR50 = SDMMCHOST_NOT_SUPPORT,
kSDMMCHOST_SupportHS200 = SDMMCHOST_NOT_SUPPORT,
kSDMMCHOST_SupportHS400 = SDMMCHOST_NOT_SUPPORT,
};
/* Endian mode. */
#define SDHC_ENDIAN_MODE kSDHC_EndianModeLittle
/* DMA mode */
#define SDHC_DMA_MODE kSDHC_DmaModeAdma2
/* address align */
#define SDMMCHOST_DMA_BUFFER_ADDR_ALIGN (SDHC_ADMA2_ADDRESS_ALIGN)
/* Read/write watermark level. The bigger value indicates DMA has higher read/write performance. */
#define SDHC_READ_WATERMARK_LEVEL (0x80U)
#define SDHC_WRITE_WATERMARK_LEVEL (0x80U)
/* ADMA table length united as word.
*
* SD card driver can't support ADMA1 transfer mode currently.
* One ADMA2 table item occupy two words which can transfer maximum 0xFFFFU bytes one time.
* The more data to be transferred in one time, the bigger value of SDHC_ADMA_TABLE_WORDS need to be set.
*/
#define SDHC_ADMA_TABLE_WORDS (8U)
/*********************************************************SDIF**********************************************************/
#elif (defined(FSL_FEATURE_SOC_SDIF_COUNT) && (FSL_FEATURE_SOC_SDIF_COUNT > 0U))
/*define host baseaddr ,clk freq, IRQ number*/
#define MMC_HOST_BASEADDR BOARD_SDIF_BASEADDR
#define MMC_HOST_CLK_FREQ BOARD_SDIF_CLK_FREQ
#define MMC_HOST_IRQ BOARD_SDIF_IRQ
#define SD_HOST_BASEADDR BOARD_SDIF_BASEADDR
#define SD_HOST_CLK_FREQ BOARD_SDIF_CLK_FREQ
#define SD_HOST_IRQ BOARD_SDIF_IRQ
/* define for card bus speed/strength cnofig */
#define CARD_BUS_FREQ_50MHZ (0U)
#define CARD_BUS_FREQ_100MHZ0 (0U)
#define CARD_BUS_FREQ_100MHZ1 (0U)
#define CARD_BUS_FREQ_200MHZ (0U)
#define CARD_BUS_STRENGTH_0 (0U)
#define CARD_BUS_STRENGTH_1 (0U)
#define CARD_BUS_STRENGTH_2 (0U)
#define CARD_BUS_STRENGTH_3 (0U)
#define CARD_BUS_STRENGTH_4 (0U)
#define CARD_BUS_STRENGTH_5 (0U)
#define CARD_BUS_STRENGTH_6 (0U)
#define CARD_BUS_STRENGTH_7 (0U)
#define SDMMCHOST_TYPE SDIF_Type
#define SDMMCHOST_CONFIG sdif_host_t
#define SDMMCHOST_TRANSFER sdif_transfer_t
#define SDMMCHOST_COMMAND sdif_command_t
#define SDMMCHOST_DATA sdif_data_t
#define SDMMCHOST_BUS_WIDTH_TYPE sdif_bus_width_t
#define SDMMCHOST_CAPABILITY sdif_capability_t
#define SDMMCHOST_BOOT_CONFIG void
#define CARD_DATA0_STATUS_MASK SDIF_STATUS_DATA_BUSY_MASK
#define CARD_DATA0_NOT_BUSY 0U
#define CARD_DATA1_STATUS_MASK (0U)
#define CARD_DATA2_STATUS_MASK (0U)
#define CARD_DATA3_STATUS_MASK (0U)
#define kSDMMCHOST_DATABUSWIDTH1BIT kSDIF_Bus1BitWidth /*!< 1-bit mode */
#define kSDMMCHOST_DATABUSWIDTH4BIT kSDIF_Bus4BitWidth /*!< 4-bit mode */
#define kSDMMCHOST_DATABUSWIDTH8BIT kSDIF_Bus8BitWidth /*!< 8-bit mode */
#define SDMMCHOST_STANDARD_TUNING_START (0U) /*!< standard tuning start point */
#define SDMMCHOST_TUINIG_STEP (1U) /*!< standard tuning step */
#define SDMMCHOST_RETUNING_TIMER_COUNT (4U) /*!< Re-tuning timer */
#define SDMMCHOST_TUNING_DELAY_MAX (0x7FU)
#define SDMMCHOST_RETUNING_REQUEST (1U)
#define SDMMCHOST_TUNING_ERROR (2U)
/* function pointer define */
#define SDMMCHOST_TRANSFER_FUNCTION sdif_transfer_function_t
#define GET_SDMMCHOST_CAPABILITY(base, capability) (SDIF_GetCapability(base, capability))
#define GET_SDMMCHOST_STATUS(base) (SDIF_GetControllerStatus(base))
#define SDMMCHOST_SET_CARD_CLOCK(base, sourceClock_HZ, busClock_HZ) \
(SDIF_SetCardClock(base, sourceClock_HZ, busClock_HZ))
#define SDMMCHOST_SET_CARD_BUS_WIDTH(base, busWidth) (SDIF_SetCardBusWidth(base, busWidth))
#define SDMMCHOST_SEND_CARD_ACTIVE(base, timeout) (SDIF_SendCardActive(base, timeout))
#define SDMMCHOST_SWITCH_VOLTAGE180V(base, enable18v)
#define SDMMCHOST_SWITCH_VOLTAGE120V(base, enable12v)
#define SDMMCHOST_CONFIG_IO_STRENGTH(speed, strength)
#define SDMMCHOST_EXECUTE_STANDARD_TUNING_ENABLE(base, flag)
#define SDMMCHOST_EXECUTE_STANDARD_TUNING_STATUS(base) (0U)
#define SDMMCHOST_EXECUTE_STANDARD_TUNING_RESULT(base) (1U)
#define SDMMCHOST_CONFIG_SD_IO(speed, strength)
#define SDMMCHOST_CONFIG_MMC_IO(speed, strength)
#define SDMMCHOST_ENABLE_DDR_MODE(base, flag, nibblePos)
#define SDMMCHOST_FORCE_SDCLOCK_ON(base, enable)
#define SDMMCHOST_EXECUTE_MANUAL_TUNING_ENABLE(base, flag)
#define SDMMCHOST_ADJUST_MANUAL_TUNING_DELAY(base, delay)
#define SDMMCHOST_AUTO_MANUAL_TUNING_ENABLE(base, flag)
#define SDMMCHOST_ENABLE_CARD_CLOCK(base, enable) (SDIF_EnableCardClock(base, enable))
#define SDMMCHOST_RESET_TUNING(base, timeout)
#define SDMMCHOST_CHECK_TUNING_ERROR(base) (0U)
#define SDMMCHOST_ADJUST_TUNING_DELAY(base, delay)
#define SDMMCHOST_AUTO_STANDARD_RETUNING_TIMER(base)
#define SDMMCHOST_ENABLE_HS400_MODE(base, flag)
#define SDMMCHOST_RESET_STROBE_DLL(base)
#define SDMMCHOST_ENABLE_STROBE_DLL(base, flag)
#define SDMMCHOST_CONFIG_STROBE_DLL(base, delay, updateInterval)
#define SDMMCHOST_GET_STROBE_DLL_STATUS(base)
/* sd card power */
#define SDMMCHOST_INIT_SD_POWER()
#define SDMMCHOST_ENABLE_SD_POWER(enable)
#define SDMMCHOST_SWITCH_VCC_TO_180V()
#define SDMMCHOST_SWITCH_VCC_TO_330V()
/* mmc card power */
#define SDMMCHOST_INIT_MMC_POWER()
#define SDMMCHOST_ENABLE_MMC_POWER(enable)
#define SDMMCHOST_ENABLE_TUNING_FLAG(data)
#define SDMMCHOST_ENABLE_MMC_BOOT(base, flag)
#define SDMMCHOST_SETMMCBOOTCONFIG(base, config)
#define SDMMCHOST_ENABLE_BOOT_FLAG(data)
#define SDMMCHOST_ENABLE_BOOT_CONTINOUS_FLAG(data)
#define SDMMCHOST_GET_HOST_CONFIG_BLOCK_SIZE(config) (0U)
#define SDMMCHOST_GET_HOST_CONFIG_BLOCK_COUNT(config) (0U)
#define SDMMCHOST_GET_HOST_CONFIG_BOOT_MODE(config) (0U)
#define SDMMCHOST_EMPTY_CMD_FLAG(command)
#define SDMMCHOST_CARD_DETECT_STATUS() BOARD_SDIF_CD_STATUS()
#define SDMMCHOST_CARD_DETECT_INIT() BOARD_SDIF_CD_GPIO_INIT()
#define SDMMCHOST_CARD_DETECT_INTERRUPT_STATUS() BOARD_SDIF_CD_INTERRUPT_STATUS()
#define SDMMCHOST_CARD_DETECT_INTERRUPT_CLEAR(flag) BOARD_SDIF_CD_CLEAR_INTERRUPT(flag)
#define SDMMCHOST_CARD_DETECT_GPIO_INTERRUPT_HANDLER BOARD_SDIF_CD_PORT_IRQ_HANDLER
#define SDMMCHOST_CARD_DETECT_IRQ BOARD_SDIF_CD_PORT_IRQ
#define SDMMCHOST_TRANSFER_DATA_ERROR kStatus_SDIF_DataTransferFail
#define SDMMCHOST_TRANSFER_CMD_ERROR kStatus_SDIF_SendCmdFail
/* define card detect pin voltage level when card inserted */
#if defined BOARD_SDIF_CARD_INSERT_CD_LEVEL
#define SDMMCHOST_CARD_INSERT_CD_LEVEL BOARD_SDIF_CARD_INSERT_CD_LEVEL
#else
#define SDMMCHOST_CARD_INSERT_CD_LEVEL (0U)
#endif
#define SDMMCHOST_AUTO_TUNING_ENABLE(base, flag)
/* sd card detect through host CD */
#define SDMMCHOST_CARD_DETECT_INSERT_ENABLE(base) (SDIF_EnableInterrupt(base, kSDIF_CardDetect))
#define SDMMCHOST_CARD_DETECT_INSERT_STATUS(base, data3) (SDIF_DetectCardInsert(base, data3))
#define SDMMCHOST_ENABLE_SDIO_INT(base)
#define SDMMCHOST_DISABLE_SDIO_INT(base)
/*! @brief SDIF host capability*/
enum _host_capability
{
kSDMMCHOST_SupportHighSpeed = kSDIF_SupportHighSpeedFlag,
kSDMMCHOST_SupportDma = kSDIF_SupportDmaFlag,
kSDMMCHOST_SupportSuspendResume = kSDIF_SupportSuspendResumeFlag,
kSDMMCHOST_SupportV330 = kSDIF_SupportV330Flag,
kSDMMCHOST_SupportV300 = SDMMCHOST_NOT_SUPPORT,
kSDMMCHOST_SupportV180 = SDMMCHOST_NOT_SUPPORT,
kSDMMCHOST_SupportV120 = SDMMCHOST_NOT_SUPPORT,
kSDMMCHOST_Support4BitBusWidth = kSDIF_Support4BitFlag,
kSDMMCHOST_Support8BitBusWidth =
SDMMCHOST_NOT_SUPPORT, /* mask the 8 bit here,user can change depend on your board */
kSDMMCHOST_SupportDDR50 = SDMMCHOST_NOT_SUPPORT,
kSDMMCHOST_SupportSDR104 = SDMMCHOST_NOT_SUPPORT,
kSDMMCHOST_SupportSDR50 = SDMMCHOST_NOT_SUPPORT,
kSDMMCHOST_SupportHS200 = SDMMCHOST_NOT_SUPPORT,
kSDMMCHOST_SupportHS400 = SDMMCHOST_NOT_SUPPORT,
};
/*! @brief DMA table length united as word
* One dma table item occupy four words which can transfer maximum 2*8188 bytes in dual DMA mode
* and 8188 bytes in chain mode
* The more data to be transferred in one time, the bigger value of SDHC_ADMA_TABLE_WORDS need to be set.
* user need check the DMA descriptor table lenght if bigger enough.
*/
#define SDIF_DMA_TABLE_WORDS (0x40U)
/* address align */
#define SDMMCHOST_DMA_BUFFER_ADDR_ALIGN (4U)
/*********************************************************USDHC**********************************************************/
#elif (defined(FSL_FEATURE_SOC_USDHC_COUNT) && (FSL_FEATURE_SOC_USDHC_COUNT > 0U))
/*define host baseaddr ,clk freq, IRQ number*/
#define MMC_HOST_BASEADDR BOARD_MMC_HOST_BASEADDR
#define MMC_HOST_CLK_FREQ BOARD_MMC_HOST_CLK_FREQ
#define MMC_HOST_IRQ BOARD_MMC_HOST_IRQ
#define SD_HOST_BASEADDR BOARD_SD_HOST_BASEADDR
#define SD_HOST_CLK_FREQ BOARD_SD_HOST_CLK_FREQ
#define SD_HOST_IRQ BOARD_SD_HOST_IRQ
#define SDMMCHOST_TYPE USDHC_Type
#define SDMMCHOST_CONFIG usdhc_host_t
#define SDMMCHOST_TRANSFER usdhc_transfer_t
#define SDMMCHOST_COMMAND usdhc_command_t
#define SDMMCHOST_DATA usdhc_data_t
#define SDMMCHOST_BOOT_CONFIG usdhc_boot_config_t
#define CARD_DATA0_STATUS_MASK (kUSDHC_Data0LineLevelFlag)
#define CARD_DATA1_STATUS_MASK (kUSDHC_Data1LineLevelFlag)
#define CARD_DATA2_STATUS_MASK (kUSDHC_Data2LineLevelFlag)
#define CARD_DATA3_STATUS_MASK (kUSDHC_Data3LineLevelFlag)
#define CARD_DATA0_NOT_BUSY (kUSDHC_Data0LineLevelFlag)
#define SDMMCHOST_BUS_WIDTH_TYPE usdhc_data_bus_width_t
#define SDMMCHOST_CAPABILITY usdhc_capability_t
#define kSDMMCHOST_DATABUSWIDTH1BIT kUSDHC_DataBusWidth1Bit /*!< 1-bit mode */
#define kSDMMCHOST_DATABUSWIDTH4BIT kUSDHC_DataBusWidth4Bit /*!< 4-bit mode */
#define kSDMMCHOST_DATABUSWIDTH8BIT kUSDHC_DataBusWidth8Bit /*!< 8-bit mode */
#define SDMMCHOST_STANDARD_TUNING_START (10U) /*!< standard tuning start point */
#define SDMMCHOST_TUINIG_STEP (2U) /*!< standard tuning step */
#define SDMMCHOST_RETUNING_TIMER_COUNT (0U) /*!< Re-tuning timer */
#define SDMMCHOST_TUNING_DELAY_MAX (0x7FU)
#define SDMMCHOST_RETUNING_REQUEST kStatus_USDHC_ReTuningRequest
#define SDMMCHOST_TUNING_ERROR kStatus_USDHC_TuningError
#define SDMMCHOST_TRANSFER_DATA_ERROR kStatus_USDHC_TransferDataFailed
#define SDMMCHOST_TRANSFER_CMD_ERROR kStatus_USDHC_SendCommandFailed
/* define for card bus speed/strength cnofig */
#define CARD_BUS_FREQ_50MHZ (0U)
#define CARD_BUS_FREQ_100MHZ0 (1U)
#define CARD_BUS_FREQ_100MHZ1 (2U)
#define CARD_BUS_FREQ_200MHZ (3U)
#define CARD_BUS_STRENGTH_0 (0U)
#define CARD_BUS_STRENGTH_1 (1U)
#define CARD_BUS_STRENGTH_2 (2U)
#define CARD_BUS_STRENGTH_3 (3U)
#define CARD_BUS_STRENGTH_4 (4U)
#define CARD_BUS_STRENGTH_5 (5U)
#define CARD_BUS_STRENGTH_6 (6U)
#define CARD_BUS_STRENGTH_7 (7U)
#define SDMMCHOST_STROBE_DLL_DELAY_TARGET (7U)
#define SDMMCHOST_STROBE_DLL_DELAY_UPDATE_INTERVAL (4U)
/* function pointer define */
#define SDMMCHOST_TRANSFER_FUNCTION usdhc_transfer_function_t
#define GET_SDMMCHOST_CAPABILITY(base, capability) (USDHC_GetCapability(base, capability))
#define GET_SDMMCHOST_STATUS(base) (USDHC_GetPresentStatusFlags(base))
#define SDMMCHOST_SET_CARD_CLOCK(base, sourceClock_HZ, busClock_HZ) \
(USDHC_SetSdClock(base, sourceClock_HZ, busClock_HZ))
#define SDMMCHOST_ENABLE_CARD_CLOCK(base, enable)
#define SDMMCHOST_FORCE_SDCLOCK_ON(base, enable) (USDHC_ForceClockOn(base, enable))
#define SDMMCHOST_SET_CARD_BUS_WIDTH(base, busWidth) (USDHC_SetDataBusWidth(base, busWidth))
#define SDMMCHOST_SEND_CARD_ACTIVE(base, timeout) (USDHC_SetCardActive(base, timeout))
#define SDMMCHOST_SWITCH_VOLTAGE180V(base, enable18v) (UDSHC_SelectVoltage(base, enable18v))
#define SDMMCHOST_SWITCH_VOLTAGE120V(base, enable12v)
#define SDMMCHOST_CONFIG_SD_IO(speed, strength) BOARD_SD_Pin_Config(speed, strength)
#define SDMMCHOST_CONFIG_MMC_IO(speed, strength) BOARD_MMC_Pin_Config(speed, strength)
#define SDMMCHOST_SWITCH_VCC_TO_180V()
#define SDMMCHOST_SWITCH_VCC_TO_330V()
#if defined(FSL_FEATURE_USDHC_HAS_SDR50_MODE) && (!FSL_FEATURE_USDHC_HAS_SDR50_MODE)
#define SDMMCHOST_EXECUTE_STANDARD_TUNING_STATUS(base) (0U)
#define SDMMCHOST_EXECUTE_STANDARD_TUNING_RESULT(base) (1U)
#define SDMMCHOST_AUTO_STANDARD_RETUNING_TIMER(base)
#define SDMMCHOST_EXECUTE_STANDARD_TUNING_ENABLE(base, flag)
#define SDMMCHOST_CHECK_TUNING_ERROR(base) (0U)
#define SDMMCHOST_ADJUST_TUNING_DELAY(base, delay)
#else
#define SDMMCHOST_EXECUTE_STANDARD_TUNING_ENABLE(base, flag) \
(USDHC_EnableStandardTuning(base, SDMMCHOST_STANDARD_TUNING_START, SDMMCHOST_TUINIG_STEP, flag))
#define SDMMCHOST_EXECUTE_STANDARD_TUNING_STATUS(base) (USDHC_GetExecuteStdTuningStatus(base))
#define SDMMCHOST_EXECUTE_STANDARD_TUNING_RESULT(base) (USDHC_CheckStdTuningResult(base))
#define SDMMCHOST_AUTO_STANDARD_RETUNING_TIMER(base) (USDHC_SetRetuningTimer(base, SDMMCHOST_RETUNING_TIMER_COUNT))
#define SDMMCHOST_EXECUTE_MANUAL_TUNING_ENABLE(base, flag) (USDHC_EnableManualTuning(base, flag))
#define SDMMCHOST_ADJUST_TUNING_DELAY(base, delay) (USDHC_AdjustDelayForManualTuning(base, delay))
#define SDMMCHOST_AUTO_TUNING_ENABLE(base, flag) (USDHC_EnableAutoTuning(base, flag))
#define SDMMCHOST_CHECK_TUNING_ERROR(base) (USDHC_CheckTuningError(base))
#endif
#define SDMMCHOST_AUTO_TUNING_CONFIG(base) (USDHC_EnableAutoTuningForCmdAndData(base))
#define SDMMCHOST_RESET_TUNING(base, timeout) \
{ \
(USDHC_Reset(base, kUSDHC_ResetTuning | kUSDHC_ResetData | kUSDHC_ResetCommand, timeout)); \
}
#define SDMMCHOST_ENABLE_DDR_MODE(base, flag, nibblePos) (USDHC_EnableDDRMode(base, flag, nibblePos))
#if FSL_FEATURE_USDHC_HAS_HS400_MODE
#define SDMMCHOST_ENABLE_HS400_MODE(base, flag) (USDHC_EnableHS400Mode(base, flag))
#define SDMMCHOST_RESET_STROBE_DLL(base) (USDHC_ResetStrobeDLL(base))
#define SDMMCHOST_ENABLE_STROBE_DLL(base, flag) (USDHC_EnableStrobeDLL(base, flag))
#define SDMMCHOST_CONFIG_STROBE_DLL(base, delay, updateInterval) (USDHC_ConfigStrobeDLL(base, delay, updateInterval))
#define SDMMCHOST_GET_STROBE_DLL_STATUS (base)(USDHC_GetStrobeDLLStatus(base))
#else
#define SDMMCHOST_ENABLE_HS400_MODE(base, flag)
#define SDMMCHOST_RESET_STROBE_DLL(base)
#define SDMMCHOST_ENABLE_STROBE_DLL(base, flag)
#define SDMMCHOST_CONFIG_STROBE_DLL(base, delay, updateInterval)
#define SDMMCHOST_GET_STROBE_DLL_STATUS(base)
#endif
#define SDMMCHOST_ENABLE_MMC_BOOT(base, flag) (USDHC_EnableMmcBoot(base, flag))
#define SDMMCHOST_SETMMCBOOTCONFIG(base, config) (USDHC_SetMmcBootConfig(base, config))
/* sd card power */
#define SDMMCHOST_INIT_SD_POWER() BOARD_USDHC_SDCARD_POWER_CONTROL_INIT()
#define SDMMCHOST_ENABLE_SD_POWER(enable) BOARD_USDHC_SDCARD_POWER_CONTROL(enable)
/* mmc card power */
#define SDMMCHOST_INIT_MMC_POWER() BOARD_USDHC_MMCCARD_POWER_CONTROL_INIT()
#define SDMMCHOST_ENABLE_MMC_POWER(enable) BOARD_USDHC_MMCCARD_POWER_CONTROL(enable)
/* sd card detect through gpio */
#define SDMMCHOST_CARD_DETECT_GPIO_STATUS() BOARD_USDHC_CD_STATUS()
#define SDMMCHOST_CARD_DETECT_GPIO_INIT() BOARD_USDHC_CD_GPIO_INIT()
#define SDMMCHOST_CARD_DETECT_GPIO_INTERRUPT_STATUS() BOARD_USDHC_CD_INTERRUPT_STATUS()
#define SDMMCHOST_CARD_DETECT_GPIO_INTERRUPT_STATUS_CLEAR(flag) BOARD_USDHC_CD_CLEAR_INTERRUPT(flag)
#define SDMMCHOST_CARD_DETECT_GPIO_INTERRUPT_HANDLER BOARD_USDHC_CD_PORT_IRQ_HANDLER
#define SDMMCHOST_CARD_DETECT_GPIO_IRQ BOARD_USDHC_CD_PORT_IRQ
/* sd card detect through host CD */
#define SDMMCHOST_CARD_DETECT_INSERT_ENABLE(base) (USDHC_EnableInterruptStatus(base, kUSDHC_CardInsertionFlag))
#define SDMMCHOST_CARD_DETECT_REMOVE_ENABLE(base) (USDHC_EnableInterruptStatus(base, kUSDHC_CardRemovalFlag))
#define SDMMCHOST_CARD_DETECT_INSERT_STATUS(base) (USDHC_DetectCardInsert(base))
#define SDMMCHOST_CARD_DETECT_REMOVE_STATUS(base) (USDHC_GetInterruptStatusFlags(base, kUSDHC_CardRemovalFlag))
#define SDMMCHOST_CARD_DETECT_INSERT_INTERRUPT_ENABLE(base) \
(USDHC_EnableInterruptSignal(base, kUSDHC_CardInsertionFlag))
#define SDMMCHOST_CARD_DETECT_REMOVE_INTERRUPT_ENABLE(base) (USDHC_EnableInterruptSignal(base, kUSDHC_CardRemovalFlag))
#define SDMMCHOST_CARD_DETECT_DATA3_ENABLE(base, flag) (USDHC_CardDetectByData3(base, flag))
/* define card detect pin voltage level when card inserted */
#if defined BOARD_USDHC_CARD_INSERT_CD_LEVEL
#define SDMMCHOST_CARD_INSERT_CD_LEVEL BOARD_USDHC_CARD_INSERT_CD_LEVEL
#else
#define SDMMCHOST_CARD_INSERT_CD_LEVEL (0U)
#endif
#define SDMMCHOST_ENABLE_TUNING_FLAG(data) (data.dataType = kUSDHC_TransferDataTuning)
#define SDMMCHOST_ENABLE_BOOT_FLAG(data) (data.dataType = kUSDHC_TransferDataBoot)
#define SDMMCHOST_ENABLE_BOOT_CONTINOUS_FLAG(data) (data.dataType = kUSDHC_TransferDataBootcontinous)
#define SDMMCHOST_GET_HOST_CONFIG_BLOCK_SIZE(config) (config->blockSize)
#define SDMMCHOST_GET_HOST_CONFIG_BLOCK_COUNT(config) (config->blockCount)
#define SDMMCHOST_GET_HOST_CONFIG_BOOT_MODE(config) (config->bootMode)
#define SDMMCHOST_EMPTY_CMD_FLAG(command) (command.type = kCARD_CommandTypeEmpty)
#define SDMMCHOST_ENABLE_SDIO_INT(base) \
USDHC_EnableInterruptStatus(base, kUSDHC_CardInterruptFlag); \
USDHC_EnableInterruptSignal(base, kUSDHC_CardInterruptFlag)
#define SDMMCHOST_DISABLE_SDIO_INT(base) \
USDHC_DisableInterruptStatus(base, kUSDHC_CardInterruptFlag); \
USDHC_DisableInterruptSignal(base, kUSDHC_CardInterruptFlag)
/*! @brief USDHC host capability*/
enum _host_capability
{
kSDMMCHOST_SupportAdma = kUSDHC_SupportAdmaFlag,
kSDMMCHOST_SupportHighSpeed = kUSDHC_SupportHighSpeedFlag,
kSDMMCHOST_SupportDma = kUSDHC_SupportDmaFlag,
kSDMMCHOST_SupportSuspendResume = kUSDHC_SupportSuspendResumeFlag,
kSDMMCHOST_SupportV330 = kUSDHC_SupportV330Flag, /* this define should depend on your board config */
kSDMMCHOST_SupportV300 = kUSDHC_SupportV300Flag, /* this define should depend on your board config */
#if defined(BOARD_SD_SUPPORT_180V) && !BOARD_SD_SUPPORT_180V
kSDMMCHOST_SupportV180 = SDMMCHOST_NOT_SUPPORT, /* this define should depend on you board config */
#else
kSDMMCHOST_SupportV180 = kUSDHC_SupportV180Flag, /* this define should depend on you board config */
#endif
kSDMMCHOST_SupportV120 = SDMMCHOST_NOT_SUPPORT,
kSDMMCHOST_Support4BitBusWidth = kUSDHC_Support4BitFlag,
#if defined(BOARD_MMC_SUPPORT_8BIT_BUS)
#if BOARD_MMC_SUPPORT_8BIT_BUS
kSDMMCHOST_Support8BitBusWidth = kUSDHC_Support8BitFlag,
#else
kSDMMCHOST_Support8BitBusWidth = SDMMCHOST_NOT_SUPPORT,
#endif
#else
kSDMMCHOST_Support8BitBusWidth = kUSDHC_Support8BitFlag,
#endif
kSDMMCHOST_SupportDDR50 = kUSDHC_SupportDDR50Flag,
kSDMMCHOST_SupportSDR104 = kUSDHC_SupportSDR104Flag,
kSDMMCHOST_SupportSDR50 = kUSDHC_SupportSDR50Flag,
kSDMMCHOST_SupportHS200 = kUSDHC_SupportSDR104Flag,
#if FSL_FEATURE_USDHC_HAS_HS400_MODE
kSDMMCHOST_SupportHS400 = SDMMCHOST_SUPPORT
#else
kSDMMCHOST_SupportHS400 = SDMMCHOST_NOT_SUPPORT,
#endif
};
/* Endian mode. */
#define USDHC_ENDIAN_MODE kUSDHC_EndianModeLittle
/* DMA mode */
#define USDHC_DMA_MODE kUSDHC_DmaModeAdma2
/* address align */
#define SDMMCHOST_DMA_BUFFER_ADDR_ALIGN (USDHC_ADMA2_ADDRESS_ALIGN)
/* Read/write watermark level. The bigger value indicates DMA has higher read/write performance. */
#define USDHC_READ_WATERMARK_LEVEL (0x80U)
#define USDHC_WRITE_WATERMARK_LEVEL (0x80U)
/* ADMA table length united as word.
*
* One ADMA2 table item occupy two words which can transfer maximum 0xFFFFU bytes one time.
* The more data to be transferred in one time, the bigger value of SDHC_ADMA_TABLE_WORDS need to be set.
*/
#define USDHC_ADMA_TABLE_WORDS (8U) /* define the ADMA descriptor table length */
#define USDHC_ADMA2_ADDR_ALIGN (4U) /* define the ADMA2 descriptor table addr align size */
#define USDHC_READ_BURST_LEN (8U) /*!< number of words USDHC read in a single burst */
#define USDHC_WRITE_BURST_LEN (8U) /*!< number of words USDHC write in a single burst */
#define USDHC_DATA_TIMEOUT (0xFU) /*!< data timeout counter value */
#endif /* (defined(FSL_FEATURE_SOC_SDHC_COUNT) && (FSL_FEATURE_SOC_SDHC_COUNT > 0U)) */
/*! @brief card detect callback definition */
typedef void (*sdmmchost_cd_callback_t)(bool isInserted, void *userData);
/*! @brief host Endian mode
* corresponding to driver define
*/
enum _sdmmchost_endian_mode
{
kSDMMCHOST_EndianModeBig = 0U, /*!< Big endian mode */
kSDMMCHOST_EndianModeHalfWordBig = 1U, /*!< Half word big endian mode */
kSDMMCHOST_EndianModeLittle = 2U, /*!< Little endian mode */
};
/*! @brief sd card detect type */
typedef enum _sdmmchost_detect_card_type
{
kSDMMCHOST_DetectCardByGpioCD, /*!< sd card detect by CD pin through GPIO */
kSDMMCHOST_DetectCardByHostCD, /*!< sd card detect by CD pin through host */
kSDMMCHOST_DetectCardByHostDATA3, /*!< sd card detect by DAT3 pin through host */
} sdmmchost_detect_card_type_t;
/*! @brief sd card detect */
typedef struct _sdmmchost_detect_card
{
sdmmchost_detect_card_type_t cdType; /*!< card detect type */
uint32_t cdTimeOut_ms; /*!< card detect timeout which allow 0 - 0xFFFFFFF, value 0 will return immediately, value
0xFFFFFFFF will block until card is insert */
sdmmchost_cd_callback_t cardInserted; /*!< card inserted callback which is meaningful for interrupt case */
sdmmchost_cd_callback_t cardRemoved; /*!< card removed callback which is meaningful for interrupt case */
void *userData; /*!< user data */
} sdmmchost_detect_card_t;
/*! @brief card power control function pointer */
typedef void (*sdmmchost_pwr_t)(void);
/*! @brief card power control */
typedef struct _sdmmchost_pwr_card
{
sdmmchost_pwr_t powerOn; /*!< power on function pointer */
uint32_t powerOnDelay_ms; /*!< power on delay */
sdmmchost_pwr_t powerOff; /*!< power off function pointer */
uint32_t powerOffDelay_ms; /*!< power off delay */
} sdmmchost_pwr_card_t;
/*! @brief card interrupt function pointer */
typedef void (*sdmmchost_card_int_callback_t)(void *userData);
/*! @brief card interrupt application callback */
typedef struct _sdmmchost_card_int
{
void *userData; /*!< user data */
sdmmchost_card_int_callback_t cardInterrupt; /*!< card int call back */
} sdmmchost_card_int_t;
/*! @brief card switch voltage function pointer */
typedef void (*sdmmchost_card_switch_voltage_t)(void);
/*! @brief card switch voltage function collection */
typedef struct _sdmmchost_card_switch_voltage_func
{
sdmmchost_card_switch_voltage_t cardSignalLine1V8; /*!< switch to 1.8v function pointer */
sdmmchost_card_switch_voltage_t cardSignalLine3V3; /*!<switch to 3.3V function pointer */
} sdmmchost_card_switch_voltage_func_t;
/*! @brief card user parameter, user can define the parameter according the board, card capability */
typedef struct _sdmmhostcard_usr_param
{
const sdmmchost_detect_card_t *cd; /*!< card detect type */
const sdmmchost_pwr_card_t *pwr; /*!< power control configuration */
const sdmmchost_card_int_t *cardInt; /*!< call back function for card interrupt */
const sdmmchost_card_switch_voltage_func_t *cardVoltage; /*!< card voltage switch function */
} sdmmhostcard_usr_param_t;
/*! @ brief specifiy card user parameter name*/
typedef sdmmhostcard_usr_param_t sdcard_usr_param_t;
typedef sdmmhostcard_usr_param_t sdiocard_usr_param_t;
typedef sdmmhostcard_usr_param_t mmccard_usr_param_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name adaptor function
* @{
*/
/*!
* @brief host not support function, this function is used for host not support feature
* @param void parameter ,used to avoid build warning
* @retval kStatus_Fail ,host do not suppport
*/
static inline status_t SDMMCHOST_NotSupport(void *parameter)
{
parameter = parameter;
return kStatus_Success;
}
/*!
* @brief Detect card insert, only need for SD cases.
* @param base the pointer to host base address
* @param cd card detect configuration
* @param waitCardStatus status which user want to wait
* @retval kStatus_Success detect card insert
* @retval kStatus_Fail card insert event fail
*/
status_t SDMMCHOST_WaitCardDetectStatus(SDMMCHOST_TYPE *hostBase,
const sdmmchost_detect_card_t *cd,
bool waitCardStatus);
/*!
* @brief check card is present or not.
* @retval true card is present
* @retval false card is not present
*/
bool SDMMCHOST_IsCardPresent(void);
/*!
* @brief Init host controller.
* @param host the pointer to host structure in card structure.
* @param userData specific user data
* @retval kStatus_Success host init success
* @retval kStatus_Fail event fail
*/
status_t SDMMCHOST_Init(SDMMCHOST_CONFIG *host, void *userData);
/*!
* @brief reset host controller.
* @param host base address.
*/
void SDMMCHOST_Reset(SDMMCHOST_TYPE *base);
/*!
* @brief host controller error recovery.
* @param host base address.
*/
void SDMMCHOST_ErrorRecovery(SDMMCHOST_TYPE *base);
/*!
* @brief Deinit host controller.
* @param host the pointer to host structure in card structure.
*/
void SDMMCHOST_Deinit(void *host);
/*!
* @brief host power off card function.
* @param base host base address.
* @param pwr depend on user define power configuration.
*/
void SDMMCHOST_PowerOffCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr);
/*!
* @brief host power on card function.
* @param base host base address.
* @param pwr depend on user define power configuration.
*/
void SDMMCHOST_PowerOnCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr);
/*!
* @brief SDMMC host delay function.
* @param milliseconds delay counter.
*/
void SDMMCHOST_Delay(uint32_t milliseconds);
/* @} */
#if defined(__cplusplus)
}
#endif
/* @} */
#endif /* _FSL_SDMMC_HOST_H */
@@ -0,0 +1,3 @@
SRC_DIR += usdhc
include $(KERNEL_ROOT)/compiler.mk
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_SDMMC_EVENT_H_
#define _FSL_SDMMC_EVENT_H_
#include "fsl_common.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Event type */
typedef enum _sdmmc_event
{
kSDMMCEVENT_TransferComplete = 0U, /*!< Transfer complete event */
kSDMMCEVENT_CardDetect = 1U, /*!< Card detect event */
} sdmmc_event_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Event Function
* @{
*/
/*!
* @brief Initialize timer to implement wait event timeout.
*/
void SDMMCEVENT_InitTimer(void);
/* Callback function for SDHC */
/*!
* @brief Create event.
* @param eventType The event type
* @retval true Create event successfully.
* @retval false Create event failed.
*/
bool SDMMCEVENT_Create(sdmmc_event_t eventType);
/*!
* @brief Wait event.
*
* @param eventType The event type
* @param timeoutMilliseconds Timeout time in milliseconds.
* @retval true Wait event successfully.
* @retval false Wait event failed.
*/
bool SDMMCEVENT_Wait(sdmmc_event_t eventType, uint32_t timeoutMilliseconds);
/*!
* @brief Notify event.
* @param eventType The event type
* @retval true Notify event successfully.
* @retval false Notify event failed.
*/
bool SDMMCEVENT_Notify(sdmmc_event_t eventType);
/*!
* @brief Delete event.
* @param eventType The event type
*/
void SDMMCEVENT_Delete(sdmmc_event_t eventType);
/*!
* @brief sdmmc delay.
* @param milliseconds time to delay
*/
void SDMMCEVENT_Delay(uint32_t milliseconds);
/* @} */
#if defined(__cplusplus)
}
#endif
#endif /* _FSL_SDMMC_EVENT_H_*/
@@ -0,0 +1,3 @@
SRC_DIR += polling
include $(KERNEL_ROOT)/compiler.mk
@@ -0,0 +1,3 @@
SRC_FILES := fsl_sdmmc_host.c fsl_sdmmc_event.c
include $(KERNEL_ROOT)/compiler.mk
@@ -0,0 +1,151 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_sdmmc_event.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get event instance.
* @param eventType The event type
* @return The event instance's pointer.
*/
static volatile uint32_t *SDMMCEVENT_GetInstance(sdmmc_event_t eventType);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Card detect event. */
static volatile uint32_t g_eventCardDetect;
/*! @brief transfer complete event. */
static volatile uint32_t g_eventTransferComplete;
/*! @brief Time variable unites as milliseconds. */
volatile uint32_t g_eventTimeMilliseconds;
/*******************************************************************************
* Code
******************************************************************************/
static void SysTickHandler(void)
{
#ifdef __CA7_REV
SystemClearSystickFlag();
#endif
g_eventTimeMilliseconds++;
}
void SDMMCEVENT_InitTimer(void)
{
#ifdef __CA7_REV
/* special for i.mx6ul */
SystemSetupSystick(1000U, (void *)SysTickHandler, 32U);
SystemClearSystickFlag();
#else
/* Set systick reload value to generate 1ms interrupt */
SysTick_Config(CLOCK_GetFreq(kCLOCK_CoreSysClk) / 1000U);
#endif
}
static volatile uint32_t *SDMMCEVENT_GetInstance(sdmmc_event_t eventType)
{
volatile uint32_t *event;
switch (eventType)
{
case kSDMMCEVENT_TransferComplete:
event = &g_eventTransferComplete;
break;
case kSDMMCEVENT_CardDetect:
event = &g_eventCardDetect;
break;
default:
event = NULL;
break;
}
return event;
}
bool SDMMCEVENT_Create(sdmmc_event_t eventType)
{
volatile uint32_t *event = SDMMCEVENT_GetInstance(eventType);
if (event)
{
*event = 0;
return true;
}
else
{
return false;
}
}
bool SDMMCEVENT_Wait(sdmmc_event_t eventType, uint32_t timeoutMilliseconds)
{
uint32_t startTime;
uint32_t elapsedTime;
volatile uint32_t *event = SDMMCEVENT_GetInstance(eventType);
if (timeoutMilliseconds && event)
{
startTime = g_eventTimeMilliseconds;
do
{
elapsedTime = (g_eventTimeMilliseconds - startTime);
} while ((*event == 0U) && (elapsedTime < timeoutMilliseconds));
*event = 0U;
return ((elapsedTime < timeoutMilliseconds) ? true : false);
}
else
{
return false;
}
}
bool SDMMCEVENT_Notify(sdmmc_event_t eventType)
{
volatile uint32_t *event = SDMMCEVENT_GetInstance(eventType);
if (event)
{
*event = 1U;
return true;
}
else
{
return false;
}
}
void SDMMCEVENT_Delete(sdmmc_event_t eventType)
{
volatile uint32_t *event = SDMMCEVENT_GetInstance(eventType);
if (event)
{
*event = 0U;
}
}
void SDMMCEVENT_Delay(uint32_t milliseconds)
{
uint32_t startTime = g_eventTimeMilliseconds;
uint32_t periodTime = 0;
while (periodTime < milliseconds)
{
periodTime = g_eventTimeMilliseconds - startTime;
}
}
@@ -0,0 +1,437 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_sdmmc_event.h"
#include "fsl_sdmmc_host.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief SDMMCHOST notify card insertion status.
* @param inserted true is inserted, false is not
* @param cd card detect descriptor
*/
static void SDMMCHOST_NofiyCardInsertStatus(bool inserted, const sdmmchost_detect_card_t *cd);
/*!
* @brief SDMMCHOST detect card insert status by host controller.
* @param base host base address.
* @param userData user can register a application card insert callback through userData.
*/
static void SDMMCHOST_DetectCardInsertByHost(SDMMCHOST_TYPE *base, void *userData);
/*!
* @brief SDMMCHOST detect card remove status by host controller.
* @param base host base address.
* @param userData user can register a application card insert callback through userData.
*/
static void SDMMCHOST_DetectCardRemoveByHost(SDMMCHOST_TYPE *base, void *userData);
/*!
* @brief SDMMCHOST transfer function.
* @param base host base address.
* @param content transfer configurations.
*/
static status_t SDMMCHOST_TransferFunction(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER *content);
/*!
* @brief SDMMCHOST transfer complete callback.
* @param base host base address.
* @param handle host handle.
* @param status interrupt status.
* @param userData user data.
*/
static void SDMMCHOST_TransferCompleteCallback(SDMMCHOST_TYPE *base,
usdhc_handle_t *handle,
status_t status,
void *userData);
/*!
* @brief SDMMCHOST re-tuning callback
* @param base host base address.
* @param userData user can register a application card insert callback through userData.
*/
static void SDMMCHOST_ReTuningCallback(SDMMCHOST_TYPE *base, void *userData);
/*!
* @brief card detect deinit function.
*/
static void SDMMCHOST_CardDetectDeinit(void);
/*!
* @brief card detect deinit function.
* @param host base address.
* @param host detect card configuration.
*/
static status_t SDMMCHOST_CardDetectInit(SDMMCHOST_TYPE *base, const sdmmchost_detect_card_t *cd);
/*******************************************************************************
* Variables
******************************************************************************/
/* DMA descriptor should allocate at non-cached memory */
AT_NONCACHEABLE_SECTION_ALIGN(uint32_t g_usdhcAdma2Table[USDHC_ADMA_TABLE_WORDS], USDHC_ADMA2_ADDR_ALIGN);
usdhc_handle_t g_usdhcHandle;
volatile status_t g_usdhcTransferStatus = kStatus_Success;
static volatile bool s_sdInsertedFlag = false;
volatile status_t g_reTuningFlag = false;
/*******************************************************************************
* Code
******************************************************************************/
static void SDMMCHOST_NofiyCardInsertStatus(bool inserted, const sdmmchost_detect_card_t *cd)
{
if (inserted == false)
{
s_sdInsertedFlag = false;
if (cd && (cd->cardRemoved))
{
cd->cardRemoved(false, cd->userData);
}
}
else
{
s_sdInsertedFlag = true;
if (cd && (cd->cardInserted))
{
cd->cardInserted(true, cd->userData);
}
}
}
static void SDMMCHOST_DetectCardInsertByHost(SDMMCHOST_TYPE *base, void *userData)
{
s_sdInsertedFlag = true;
SDMMCEVENT_Notify(kSDMMCEVENT_CardDetect);
/* application callback */
if (userData && (((sdmmhostcard_usr_param_t *)userData)->cd) &&
((sdmmhostcard_usr_param_t *)userData)->cd->cardInserted)
{
((sdmmhostcard_usr_param_t *)userData)
->cd->cardInserted(true, ((sdmmhostcard_usr_param_t *)userData)->cd->userData);
}
}
static void SDMMCHOST_DetectCardRemoveByHost(SDMMCHOST_TYPE *base, void *userData)
{
s_sdInsertedFlag = false;
/* application callback */
if (userData && (((sdmmhostcard_usr_param_t *)userData)->cd) &&
((sdmmhostcard_usr_param_t *)userData)->cd->cardRemoved)
{
((sdmmhostcard_usr_param_t *)userData)
->cd->cardRemoved(false, ((sdmmhostcard_usr_param_t *)userData)->cd->userData);
}
}
static void SDMMCHOST_CardInterrupt(SDMMCHOST_TYPE *base, void *userData)
{
/* application callback */
if (userData && ((sdmmhostcard_usr_param_t *)userData)->cardInt)
{
((sdmmhostcard_usr_param_t *)userData)
->cardInt->cardInterrupt(((sdmmhostcard_usr_param_t *)userData)->cardInt->userData);
}
}
void SDMMCHOST_CARD_DETECT_GPIO_INTERRUPT_HANDLER(void)
{
if (SDMMCHOST_CARD_DETECT_GPIO_INTERRUPT_STATUS() & (1U << BOARD_USDHC_CD_GPIO_PIN))
{
SDMMCHOST_NofiyCardInsertStatus((SDMMCHOST_CARD_DETECT_GPIO_STATUS() == SDMMCHOST_CARD_INSERT_CD_LEVEL),
((sdmmhostcard_usr_param_t *)g_usdhcHandle.userData)->cd);
}
/* Clear interrupt flag.*/
SDMMCHOST_CARD_DETECT_GPIO_INTERRUPT_STATUS_CLEAR(~0U);
SDMMCEVENT_Notify(kSDMMCEVENT_CardDetect);
}
static void SDMMCHOST_TransferCompleteCallback(SDMMCHOST_TYPE *base,
usdhc_handle_t *handle,
status_t status,
void *userData)
{
/* if reading data from sdcard, ignore the command error, usdhc will continue transfer data */
if (!((handle->data) && (handle->data->rxData) && (status == kStatus_USDHC_SendCommandFailed)))
{
SDMMCEVENT_Notify(kSDMMCEVENT_TransferComplete);
}
/* wait the target status and then notify the transfer complete */
g_usdhcTransferStatus = status;
}
static void SDMMCHOST_ReTuningCallback(SDMMCHOST_TYPE *base, void *userData)
{
g_reTuningFlag = true;
SDMMCEVENT_Notify(kSDMMCEVENT_TransferComplete);
}
static status_t SDMMCHOST_TransferFunction(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER *content)
{
status_t error = kStatus_Success;
usdhc_adma_config_t dmaConfig;
if (content->data != NULL)
{
memset(&dmaConfig, 0, sizeof(usdhc_adma_config_t));
/* config adma */
dmaConfig.dmaMode = USDHC_DMA_MODE;
dmaConfig.burstLen = kUSDHC_EnBurstLenForINCR;
dmaConfig.admaTable = g_usdhcAdma2Table;
dmaConfig.admaTableWords = USDHC_ADMA_TABLE_WORDS;
}
/* make sure complete event is cleared. */
SDMMCEVENT_Delete(kSDMMCEVENT_TransferComplete);
do
{
error = USDHC_TransferNonBlocking(base, &g_usdhcHandle, &dmaConfig, content);
} while (error == kStatus_USDHC_BusyTransferring);
if ((error != kStatus_Success) ||
(false == SDMMCEVENT_Wait(kSDMMCEVENT_TransferComplete, SDMMCHOST_TRANSFER_COMPLETE_TIMEOUT)) ||
(g_reTuningFlag) || (g_usdhcTransferStatus != kStatus_Success))
{
if (g_reTuningFlag || (error == kStatus_USDHC_ReTuningRequest))
{
if (g_reTuningFlag)
{
g_reTuningFlag = false;
error = kStatus_USDHC_TuningError;
}
}
else
{
error = g_usdhcTransferStatus;
/* host error recovery */
SDMMCHOST_ErrorRecovery(base);
}
}
return error;
}
void SDMMCHOST_ErrorRecovery(SDMMCHOST_TYPE *base)
{
uint32_t status = 0U;
/* get host present status */
status = USDHC_GetPresentStatusFlags(base);
/* check command inhibit status flag */
if ((status & kUSDHC_CommandInhibitFlag) != 0U)
{
/* reset command line */
USDHC_Reset(base, kUSDHC_ResetCommand, 100U);
}
/* check data inhibit status flag */
if ((status & kUSDHC_DataInhibitFlag) != 0U)
{
/* reset data line */
USDHC_Reset(base, kUSDHC_ResetData, 100U);
}
}
static status_t SDMMCHOST_CardDetectInit(SDMMCHOST_TYPE *base, const sdmmchost_detect_card_t *cd)
{
sdmmchost_detect_card_type_t cdType = kSDMMCHOST_DetectCardByGpioCD;
bool cardInserted = false;
if (cd != NULL)
{
cdType = cd->cdType;
}
if (!SDMMCEVENT_Create(kSDMMCEVENT_CardDetect))
{
return kStatus_Fail;
}
if (cdType == kSDMMCHOST_DetectCardByGpioCD)
{
SDMMCHOST_CARD_DETECT_GPIO_INIT();
/* Open card detection pin NVIC. */
SDMMCHOST_ENABLE_IRQ(SDMMCHOST_CARD_DETECT_GPIO_IRQ);
/* detect card insert status */
if (SDMMCHOST_CARD_DETECT_GPIO_STATUS() == SDMMCHOST_CARD_INSERT_CD_LEVEL)
{
cardInserted = true;
}
}
else
{
/* enable card detect through DATA3 */
if (cdType == kSDMMCHOST_DetectCardByHostDATA3)
{
SDMMCHOST_CARD_DETECT_DATA3_ENABLE(base, true);
}
/* enable card detect interrupt */
SDMMCHOST_CARD_DETECT_INSERT_ENABLE(base);
/* check if card is inserted */
if (SDMMCHOST_CARD_DETECT_INSERT_STATUS(base))
{
cardInserted = true;
}
else
{
SDMMCHOST_CARD_DETECT_INSERT_INTERRUPT_ENABLE(base);
SDMMCHOST_CARD_DETECT_REMOVE_INTERRUPT_ENABLE(base);
}
}
/* notify application about the card insertion status */
SDMMCHOST_NofiyCardInsertStatus(cardInserted, cd);
return kStatus_Success;
}
static void SDMMCHOST_CardDetectDeinit(void)
{
SDMMCEVENT_Delete(kSDMMCEVENT_CardDetect);
s_sdInsertedFlag = false;
}
void SDMMCHOST_Delay(uint32_t milliseconds)
{
SDMMCEVENT_Delay(milliseconds);
}
status_t SDMMCHOST_WaitCardDetectStatus(SDMMCHOST_TYPE *base, const sdmmchost_detect_card_t *cd, bool waitCardStatus)
{
uint32_t timeout = SDMMCHOST_CARD_DETECT_TIMEOUT;
if (cd != NULL)
{
timeout = cd->cdTimeOut_ms;
}
if (waitCardStatus != s_sdInsertedFlag)
{
/* Wait card inserted. */
do
{
if (!SDMMCEVENT_Wait(kSDMMCEVENT_CardDetect, timeout))
{
return kStatus_Fail;
}
} while (waitCardStatus != s_sdInsertedFlag);
}
return kStatus_Success;
}
bool SDMMCHOST_IsCardPresent(void)
{
return s_sdInsertedFlag;
}
void SDMMCHOST_PowerOffCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr)
{
if (pwr != NULL)
{
pwr->powerOff();
SDMMCHOST_Delay(pwr->powerOffDelay_ms);
}
else
{
/* only SD card need card detect*/
SDMMCHOST_ENABLE_SD_POWER(false);
/* Delay several milliseconds to make card stable. */
SDMMCHOST_Delay(500U);
}
}
void SDMMCHOST_PowerOnCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr)
{
/* use user define the power on function */
if (pwr != NULL)
{
pwr->powerOn();
SDMMCHOST_Delay(pwr->powerOnDelay_ms);
}
else
{
/* card power on */
SDMMCHOST_ENABLE_SD_POWER(true);
/* Delay several milliseconds to make card stable. */
SDMMCHOST_Delay(500U);
}
}
status_t SDMMCHOST_Init(SDMMCHOST_CONFIG *host, void *userData)
{
usdhc_host_t *usdhcHost = (usdhc_host_t *)host;
usdhc_transfer_callback_t callback = {
.TransferComplete = SDMMCHOST_TransferCompleteCallback,
.ReTuning = SDMMCHOST_ReTuningCallback,
.CardInserted = SDMMCHOST_DetectCardInsertByHost,
.CardRemoved = SDMMCHOST_DetectCardRemoveByHost,
.SdioInterrupt = SDMMCHOST_CardInterrupt,
.BlockGap = NULL,
};
/* init card power control */
SDMMCHOST_INIT_SD_POWER();
SDMMCHOST_INIT_MMC_POWER();
/* Initializes USDHC. */
usdhcHost->config.dataTimeout = USDHC_DATA_TIMEOUT;
usdhcHost->config.endianMode = USDHC_ENDIAN_MODE;
usdhcHost->config.readWatermarkLevel = USDHC_READ_WATERMARK_LEVEL;
usdhcHost->config.writeWatermarkLevel = USDHC_WRITE_WATERMARK_LEVEL;
usdhcHost->config.readBurstLen = USDHC_READ_BURST_LEN;
usdhcHost->config.writeBurstLen = USDHC_WRITE_BURST_LEN;
USDHC_Init(usdhcHost->base, &(usdhcHost->config));
/* disable the card insert/remove interrupt, due to use GPIO interrupt detect card */
USDHC_DisableInterruptSignal(usdhcHost->base, kUSDHC_CardRemovalFlag | kUSDHC_CardInsertionFlag);
/* create interrupt handler */
USDHC_TransferCreateHandle(usdhcHost->base, &g_usdhcHandle, &callback, userData);
/* Create transfer complete event. */
SDMMCEVENT_InitTimer();
if (false == SDMMCEVENT_Create(kSDMMCEVENT_TransferComplete))
{
return kStatus_Fail;
}
/* Define transfer function. */
usdhcHost->transfer = SDMMCHOST_TransferFunction;
/* card detect init */
SDMMCHOST_CardDetectInit(usdhcHost->base, (userData == NULL) ? NULL : (((sdmmhostcard_usr_param_t *)userData)->cd));
return kStatus_Success;
}
void SDMMCHOST_Reset(SDMMCHOST_TYPE *base)
{
/* voltage switch to normal but not 1.8V */
SDMMCHOST_SWITCH_VOLTAGE180V(base, false);
/* Disable DDR mode */
SDMMCHOST_ENABLE_DDR_MODE(base, false, 0U);
/* disable tuning */
SDMMCHOST_EXECUTE_STANDARD_TUNING_ENABLE(base, false);
/* Disable HS400 mode */
SDMMCHOST_ENABLE_HS400_MODE(base, false);
/* Disable DLL */
SDMMCHOST_ENABLE_STROBE_DLL(base, false);
}
void SDMMCHOST_Deinit(void *host)
{
usdhc_host_t *usdhcHost = (usdhc_host_t *)host;
SDMMCHOST_Reset(usdhcHost->base);
USDHC_Deinit(usdhcHost->base);
SDMMCHOST_CardDetectDeinit();
}
@@ -0,0 +1,3 @@
SRC_FILES := fsl_sdmmc_host.c fsl_sdmmc_event.c
include $(KERNEL_ROOT)/compiler.mk
@@ -0,0 +1,154 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_sdmmc_event.h"
#include "xizi.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get event instance.
* @param eventType The event type
* @return The event instance's pointer.
*/
static volatile uint32_t *SDMMCEVENT_GetInstance(sdmmc_event_t eventType);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Card detect event. */
static volatile uint32_t g_eventCardDetect;
/*! @brief transfer complete event. */
static volatile uint32_t g_eventTransferComplete;
/*! @brief Time variable unites as milliseconds. */
volatile uint32_t g_eventTimeMilliseconds;
/*******************************************************************************
* Code
******************************************************************************/
// void SysTick_Handler(void)
// {
// #ifdef __CA7_REV
// SystemClearSystickFlag();
// #endif
// g_eventTimeMilliseconds++;
// }
void SDMMCEVENT_InitTimer(void)
{
#ifdef __CA7_REV
/* special for i.mx6ul */
SystemSetupSystick(1000U, (void *)SysTick_Handler, 32U);
SystemClearSystickFlag();
#else
/* Set systick reload value to generate 1ms interrupt */
SysTick_Config(CLOCK_GetFreq(kCLOCK_CoreSysClk) / 1000U);
#endif
}
static volatile uint32_t *SDMMCEVENT_GetInstance(sdmmc_event_t eventType)
{
volatile uint32_t *event;
switch (eventType)
{
case kSDMMCEVENT_TransferComplete:
event = &g_eventTransferComplete;
break;
case kSDMMCEVENT_CardDetect:
event = &g_eventCardDetect;
break;
default:
event = NULL;
break;
}
return event;
}
bool SDMMCEVENT_Create(sdmmc_event_t eventType)
{
volatile uint32_t *event = SDMMCEVENT_GetInstance(eventType);
if (event)
{
*event = 0;
return true;
}
else
{
return false;
}
}
bool SDMMCEVENT_Wait(sdmmc_event_t eventType, uint32_t timeoutMilliseconds)
{
uint32_t startTime;
uint32_t elapsedTime;
volatile uint32_t *event = SDMMCEVENT_GetInstance(eventType);
if (timeoutMilliseconds && event)
{
startTime = CurrentTicksGain();
do
{
elapsedTime = (CurrentTicksGain() - startTime);
} while ((*event == 0U) && (elapsedTime < timeoutMilliseconds));
*event = 0U;
return ((elapsedTime < timeoutMilliseconds) ? true : false);
}
else
{
return false;
}
}
bool SDMMCEVENT_Notify(sdmmc_event_t eventType)
{
volatile uint32_t *event = SDMMCEVENT_GetInstance(eventType);
if (event)
{
*event = 1U;
return true;
}
else
{
return false;
}
}
void SDMMCEVENT_Delete(sdmmc_event_t eventType)
{
volatile uint32_t *event = SDMMCEVENT_GetInstance(eventType);
if (event)
{
*event = 0U;
}
}
void SDMMCEVENT_Delay(uint32_t milliseconds)
{
uint32_t startTime = CurrentTicksGain();
uint32_t periodTime = 0;
while (periodTime < milliseconds)
{
KPrintf("period time %u millisecond %u event %u start %u\n",
periodTime, milliseconds, CurrentTicksGain(), startTime);
periodTime = CurrentTicksGain() - startTime;
}
}
@@ -0,0 +1,290 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_sdmmc_host.h"
#include "fsl_sdmmc_event.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief SDMMCHOST notify card insertion status.
* @param inserted true is inserted, false is not
* @param cd card detect descriptor
*/
static void SDMMCHOST_NofiyCardInsertStatus(bool inserted, const sdmmchost_detect_card_t *cd);
/*!
* @brief SDMMCHOST transfer function.
* @param base host base address.
* @param content transfer configurations.
*/
static status_t SDMMCHOST_TransferFunction(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER *content);
/*!
* @brief card detect deinit function.
*/
static void SDMMCHOST_CardDetectDeinit(void);
/*!
* @brief card detect deinit function.
* @param host base address.
* @param host detect card configuration.
*/
static status_t SDMMCHOST_CardDetectInit(SDMMCHOST_TYPE *base, const sdmmchost_detect_card_t *cd);
/*******************************************************************************
* Variables
******************************************************************************/
/* DMA descriptor should allocate at non-cached memory */
AT_NONCACHEABLE_SECTION_ALIGN(uint32_t g_usdhcAdma2Table[USDHC_ADMA_TABLE_WORDS], USDHC_ADMA2_ADDR_ALIGN);
static volatile bool s_sdInsertedFlag = false;
/*******************************************************************************
* Code
******************************************************************************/
static void SDMMCHOST_NofiyCardInsertStatus(bool inserted, const sdmmchost_detect_card_t *cd)
{
if (inserted == false)
{
s_sdInsertedFlag = false;
if (cd && (cd->cardRemoved))
{
cd->cardRemoved(false, cd->userData);
}
}
else
{
s_sdInsertedFlag = true;
if (cd && (cd->cardInserted))
{
cd->cardInserted(true, cd->userData);
}
}
}
static status_t SDMMCHOST_TransferFunction(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER *content)
{
usdhc_adma_config_t dmaConfig;
status_t error = kStatus_Success;
if (content->data != NULL)
{
memset(&dmaConfig, 0, sizeof(usdhc_adma_config_t));
/* config adma */
dmaConfig.dmaMode = USDHC_DMA_MODE;
dmaConfig.burstLen = kUSDHC_EnBurstLenForINCR;
dmaConfig.admaTable = g_usdhcAdma2Table;
dmaConfig.admaTableWords = USDHC_ADMA_TABLE_WORDS;
}
error = USDHC_TransferBlocking(base, &dmaConfig, content);
if (error != kStatus_Success)
{
/* host error recovery */
SDMMCHOST_ErrorRecovery(base);
}
return error;
}
void SDMMCHOST_ErrorRecovery(SDMMCHOST_TYPE *base)
{
uint32_t status = 0U;
/* get host present status */
status = USDHC_GetPresentStatusFlags(base);
/* check command inhibit status flag */
if ((status & kUSDHC_CommandInhibitFlag) != 0U)
{
/* reset command line */
USDHC_Reset(base, kUSDHC_ResetCommand, 100U);
}
/* check data inhibit status flag */
if ((status & kUSDHC_DataInhibitFlag) != 0U)
{
/* reset data line */
USDHC_Reset(base, kUSDHC_ResetData, 100U);
}
}
static status_t SDMMCHOST_CardDetectInit(SDMMCHOST_TYPE *base, const sdmmchost_detect_card_t *cd)
{
sdmmchost_detect_card_type_t cdType = kSDMMCHOST_DetectCardByGpioCD;
bool cardInserted = false;
if (cd != NULL)
{
cdType = cd->cdType;
}
if (cdType == kSDMMCHOST_DetectCardByGpioCD)
{
SDMMCHOST_CARD_DETECT_GPIO_INIT();
/* detect card insert status */
if (SDMMCHOST_CARD_DETECT_GPIO_STATUS() == SDMMCHOST_CARD_INSERT_CD_LEVEL)
{
cardInserted = true;
}
}
else
{
/* enable card detect through DATA3 */
if (cdType == kSDMMCHOST_DetectCardByHostDATA3)
{
SDMMCHOST_CARD_DETECT_DATA3_ENABLE(base, true);
}
/* enable card detect status */
SDMMCHOST_CARD_DETECT_INSERT_ENABLE(base);
SDMMCHOST_CARD_DETECT_REMOVE_ENABLE(base);
/* check if card is inserted */
if (SDMMCHOST_CARD_DETECT_INSERT_STATUS(base))
{
cardInserted = true;
}
}
/* notify application about the card insertion status */
SDMMCHOST_NofiyCardInsertStatus(cardInserted, cd);
return kStatus_Success;
}
static void SDMMCHOST_CardDetectDeinit(void)
{
SDMMCEVENT_Delete(kSDMMCEVENT_CardDetect);
s_sdInsertedFlag = false;
}
void SDMMCHOST_Delay(uint32_t milliseconds)
{
SDMMCEVENT_Delay(milliseconds);
}
status_t SDMMCHOST_WaitCardDetectStatus(SDMMCHOST_TYPE *base, const sdmmchost_detect_card_t *cd, bool waitCardStatus)
{
sdmmchost_detect_card_type_t cdType = kSDMMCHOST_DetectCardByGpioCD;
if (cd != NULL)
{
cdType = cd->cdType;
}
if (waitCardStatus != s_sdInsertedFlag)
{
/* Wait card inserted. */
do
{
if (cdType != kSDMMCHOST_DetectCardByGpioCD)
{
if (SDMMCHOST_CARD_DETECT_INSERT_STATUS(base))
{
s_sdInsertedFlag = true;
}
}
else
{
if (SDMMCHOST_CARD_DETECT_INSERT_STATUS(base))
{
s_sdInsertedFlag = true;
}
}
} while (waitCardStatus != s_sdInsertedFlag);
}
return kStatus_Success;
}
bool SDMMCHOST_IsCardPresent(void)
{
return s_sdInsertedFlag;
}
void SDMMCHOST_PowerOffCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr)
{
if (pwr != NULL)
{
pwr->powerOff();
SDMMCHOST_Delay(pwr->powerOffDelay_ms);
}
else
{
/* only SD card need card detect*/
SDMMCHOST_ENABLE_SD_POWER(false);
/* Delay several milliseconds to make card stable. */
SDMMCHOST_Delay(500U);
}
}
void SDMMCHOST_PowerOnCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr)
{
/* use user define the power on function */
if (pwr != NULL)
{
pwr->powerOn();
SDMMCHOST_Delay(pwr->powerOnDelay_ms);
}
else
{
/* card power on */
SDMMCHOST_ENABLE_SD_POWER(true);
/* Delay several milliseconds to make card stable. */
SDMMCHOST_Delay(500U);
}
}
status_t SDMMCHOST_Init(SDMMCHOST_CONFIG *host, void *userData)
{
usdhc_host_t *usdhcHost = (usdhc_host_t *)host;
/* init card power control */
SDMMCHOST_INIT_SD_POWER();
SDMMCHOST_INIT_MMC_POWER();
/* Initializes SDHC. */
usdhcHost->config.dataTimeout = USDHC_DATA_TIMEOUT;
usdhcHost->config.endianMode = USDHC_ENDIAN_MODE;
usdhcHost->config.readWatermarkLevel = USDHC_READ_WATERMARK_LEVEL;
usdhcHost->config.writeWatermarkLevel = USDHC_WRITE_WATERMARK_LEVEL;
usdhcHost->config.readBurstLen = USDHC_READ_BURST_LEN;
usdhcHost->config.writeBurstLen = USDHC_WRITE_BURST_LEN;
USDHC_Init(usdhcHost->base, &(usdhcHost->config));
/* Define transfer function. */
usdhcHost->transfer = SDMMCHOST_TransferFunction;
/* event init timer */
SDMMCEVENT_InitTimer();
/* card detect init */
SDMMCHOST_CardDetectInit(usdhcHost->base, (userData == NULL) ? NULL : (((sdmmhostcard_usr_param_t *)userData)->cd));
return kStatus_Success;
}
void SDMMCHOST_Reset(SDMMCHOST_TYPE *base)
{
/* voltage switch to normal but not 1.8V */
SDMMCHOST_SWITCH_VOLTAGE180V(base, false);
/* Disable DDR mode */
SDMMCHOST_ENABLE_DDR_MODE(base, false, 0U);
/* disable tuning */
SDMMCHOST_EXECUTE_STANDARD_TUNING_ENABLE(base, false);
/* Disable HS400 mode */
SDMMCHOST_ENABLE_HS400_MODE(base, false);
/* Disable DLL */
SDMMCHOST_ENABLE_STROBE_DLL(base, false);
}
void SDMMCHOST_Deinit(void *host)
{
usdhc_host_t *usdhcHost = (usdhc_host_t *)host;
SDMMCHOST_Reset(usdhcHost->base);
USDHC_Deinit(usdhcHost->base);
SDMMCHOST_CardDetectDeinit();
}
@@ -0,0 +1,3 @@
SRC_FILES := fsl_sd.c fsl_sdmmc_common.c
include $(KERNEL_ROOT)/compiler.mk
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,393 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_sdmmc_common.h"
/*******************************************************************************
* Variables
******************************************************************************/
SDK_ALIGN(uint32_t g_sdmmc[SDK_SIZEALIGN(SDMMC_GLOBAL_BUFFER_SIZE, SDMMC_DATA_BUFFER_ALIGN_CACHE)],
MAX(SDMMC_DATA_BUFFER_ALIGN_CACHE, SDMMCHOST_DMA_BUFFER_ADDR_ALIGN));
/*******************************************************************************
* Code
******************************************************************************/
status_t SDMMC_SelectCard(SDMMCHOST_TYPE *base,
SDMMCHOST_TRANSFER_FUNCTION transfer,
uint32_t relativeAddress,
bool isSelected)
{
assert(transfer);
SDMMCHOST_TRANSFER content = {0};
SDMMCHOST_COMMAND command = {0};
command.index = kSDMMC_SelectCard;
if (isSelected)
{
command.argument = relativeAddress << 16U;
command.responseType = kCARD_ResponseTypeR1;
}
else
{
command.argument = 0U;
command.responseType = kCARD_ResponseTypeNone;
}
content.command = &command;
content.data = NULL;
if ((kStatus_Success != transfer(base, &content)) || (command.response[0U] & SDMMC_R1_ALL_ERROR_FLAG))
{
return kStatus_SDMMC_TransferFailed;
}
/* Wait until card to transfer state */
return kStatus_Success;
}
status_t SDMMC_SendApplicationCommand(SDMMCHOST_TYPE *base,
SDMMCHOST_TRANSFER_FUNCTION transfer,
uint32_t relativeAddress)
{
assert(transfer);
SDMMCHOST_TRANSFER content = {0};
SDMMCHOST_COMMAND command = {0};
command.index = kSDMMC_ApplicationCommand;
command.argument = (relativeAddress << 16U);
command.responseType = kCARD_ResponseTypeR1;
content.command = &command;
content.data = 0U;
if ((kStatus_Success != transfer(base, &content)) || (command.response[0U] & SDMMC_R1_ALL_ERROR_FLAG))
{
return kStatus_SDMMC_TransferFailed;
}
if (!(command.response[0U] & SDMMC_MASK(kSDMMC_R1ApplicationCommandFlag)))
{
return kStatus_SDMMC_CardNotSupport;
}
return kStatus_Success;
}
status_t SDMMC_SetBlockCount(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer, uint32_t blockCount)
{
assert(transfer);
SDMMCHOST_TRANSFER content = {0};
SDMMCHOST_COMMAND command = {0};
command.index = kSDMMC_SetBlockCount;
command.argument = blockCount;
command.responseType = kCARD_ResponseTypeR1;
content.command = &command;
content.data = 0U;
if ((kStatus_Success != transfer(base, &content)) || (command.response[0U] & SDMMC_R1_ALL_ERROR_FLAG))
{
return kStatus_SDMMC_TransferFailed;
}
return kStatus_Success;
}
status_t SDMMC_GoIdle(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer)
{
assert(transfer);
SDMMCHOST_TRANSFER content = {0};
SDMMCHOST_COMMAND command = {0};
command.index = kSDMMC_GoIdleState;
content.command = &command;
content.data = 0U;
if (kStatus_Success != transfer(base, &content))
{
return kStatus_SDMMC_TransferFailed;
}
return kStatus_Success;
}
status_t SDMMC_SetBlockSize(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer, uint32_t blockSize)
{
assert(transfer);
SDMMCHOST_TRANSFER content = {0};
SDMMCHOST_COMMAND command = {0};
command.index = kSDMMC_SetBlockLength;
command.argument = blockSize;
command.responseType = kCARD_ResponseTypeR1;
content.command = &command;
content.data = 0U;
if ((kStatus_Success != transfer(base, &content)) || (command.response[0U] & SDMMC_R1_ALL_ERROR_FLAG))
{
return kStatus_SDMMC_TransferFailed;
}
return kStatus_Success;
}
status_t SDMMC_SetCardInactive(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer)
{
assert(transfer);
SDMMCHOST_TRANSFER content = {0};
SDMMCHOST_COMMAND command = {0};
command.index = kSDMMC_GoInactiveState;
command.argument = 0U;
command.responseType = kCARD_ResponseTypeNone;
content.command = &command;
content.data = 0U;
if ((kStatus_Success != transfer(base, &content)))
{
return kStatus_SDMMC_TransferFailed;
}
return kStatus_Success;
}
status_t SDMMC_SwitchVoltage(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer)
{
assert(transfer);
SDMMCHOST_TRANSFER content = {0};
SDMMCHOST_COMMAND command = {0};
status_t error = kStatus_Success;
if (kSDMMCHOST_SupportV180 != SDMMCHOST_NOT_SUPPORT)
{
command.index = kSD_VoltageSwitch;
command.argument = 0U;
command.responseType = kCARD_ResponseTypeR1;
content.command = &command;
content.data = NULL;
if (kStatus_Success != transfer(base, &content))
{
return kStatus_SDMMC_TransferFailed;
}
/* disable card clock */
SDMMCHOST_ENABLE_CARD_CLOCK(base, false);
/* check data line and cmd line status */
if ((GET_SDMMCHOST_STATUS(base) &
(CARD_DATA1_STATUS_MASK | CARD_DATA2_STATUS_MASK | CARD_DATA3_STATUS_MASK | CARD_DATA0_NOT_BUSY)) != 0U)
{
return kStatus_SDMMC_SwitchVoltageFail;
}
/* host switch to 1.8V */
SDMMCHOST_SWITCH_VOLTAGE180V(base, true);
SDMMCHOST_Delay(100U);
/*enable sd clock*/
SDMMCHOST_ENABLE_CARD_CLOCK(base, true);
/*enable force clock on*/
SDMMCHOST_FORCE_SDCLOCK_ON(base, true);
/* dealy 1ms,not exactly correct when use while */
SDMMCHOST_Delay(10U);
/*disable force clock on*/
SDMMCHOST_FORCE_SDCLOCK_ON(base, false);
/* check data line and cmd line status */
if ((GET_SDMMCHOST_STATUS(base) &
(CARD_DATA1_STATUS_MASK | CARD_DATA2_STATUS_MASK | CARD_DATA3_STATUS_MASK | CARD_DATA0_NOT_BUSY)) == 0U)
{
error = kStatus_SDMMC_SwitchVoltageFail;
/* power reset the card */
SDMMCHOST_ENABLE_SD_POWER(false);
SDMMCHOST_Delay(10U);
SDMMCHOST_ENABLE_SD_POWER(true);
SDMMCHOST_Delay(10U);
/* re-check the data line status */
if ((GET_SDMMCHOST_STATUS(base) &
(CARD_DATA1_STATUS_MASK | CARD_DATA2_STATUS_MASK | CARD_DATA3_STATUS_MASK | CARD_DATA0_NOT_BUSY)))
{
error = kStatus_SDMMC_SwitchVoltage18VFail33VSuccess;
SDMMC_LOG(
"\r\nNote: Current card support 1.8V, but board don't support, so sdmmc switch back to 3.3V.");
}
else
{
SDMMC_LOG(
"\r\nError: Current card support 1.8V, but board don't support, sdmmc tried to switch back\
to 3.3V, but failed, please check board setting.");
}
}
return error;
}
else
{
return kStatus_SDMMC_HostNotSupport;
}
}
status_t SDMMC_SwitchToVoltage(SDMMCHOST_TYPE *base,
SDMMCHOST_TRANSFER_FUNCTION transfer,
sdmmchost_card_switch_voltage_t switchVoltageFunc)
{
assert(transfer);
SDMMCHOST_TRANSFER content = {0};
SDMMCHOST_COMMAND command = {0};
status_t error = kStatus_Success;
if (kSDMMCHOST_SupportV180 != SDMMCHOST_NOT_SUPPORT)
{
command.index = kSD_VoltageSwitch;
command.argument = 0U;
command.responseType = kCARD_ResponseTypeR1;
content.command = &command;
content.data = NULL;
if (kStatus_Success != transfer(base, &content))
{
return kStatus_SDMMC_TransferFailed;
}
/* disable card clock */
SDMMCHOST_ENABLE_CARD_CLOCK(base, false);
/* check data line and cmd line status */
if ((GET_SDMMCHOST_STATUS(base) &
(CARD_DATA1_STATUS_MASK | CARD_DATA2_STATUS_MASK | CARD_DATA3_STATUS_MASK | CARD_DATA0_NOT_BUSY)) != 0U)
{
return kStatus_SDMMC_SwitchVoltageFail;
}
if (switchVoltageFunc != NULL)
{
switchVoltageFunc();
}
else
{
/* host switch to 1.8V */
SDMMCHOST_SWITCH_VOLTAGE180V(base, true);
}
SDMMCHOST_Delay(100U);
/*enable sd clock*/
SDMMCHOST_ENABLE_CARD_CLOCK(base, true);
/*enable force clock on*/
SDMMCHOST_FORCE_SDCLOCK_ON(base, true);
/* dealy 1ms,not exactly correct when use while */
SDMMCHOST_Delay(10U);
/*disable force clock on*/
SDMMCHOST_FORCE_SDCLOCK_ON(base, false);
/* check data line and cmd line status */
if ((GET_SDMMCHOST_STATUS(base) &
(CARD_DATA1_STATUS_MASK | CARD_DATA2_STATUS_MASK | CARD_DATA3_STATUS_MASK | CARD_DATA0_NOT_BUSY)) == 0U)
{
error = kStatus_SDMMC_SwitchVoltageFail;
/* power reset the card */
SDMMCHOST_ENABLE_SD_POWER(false);
SDMMCHOST_Delay(10U);
SDMMCHOST_ENABLE_SD_POWER(true);
SDMMCHOST_Delay(10U);
/* re-check the data line status */
if ((GET_SDMMCHOST_STATUS(base) &
(CARD_DATA1_STATUS_MASK | CARD_DATA2_STATUS_MASK | CARD_DATA3_STATUS_MASK | CARD_DATA0_NOT_BUSY)))
{
error = kStatus_SDMMC_SwitchVoltage18VFail33VSuccess;
SDMMC_LOG(
"\r\nNote: Current card support 1.8V, but board don't support, so sdmmc switch back to 3.3V.");
}
else
{
SDMMC_LOG(
"\r\nError: Current card support 1.8V, but board don't support, sdmmc tried to switch back\
to 3.3V, but failed, please check board setting.");
}
}
return error;
}
else
{
return kStatus_SDMMC_HostNotSupport;
}
}
status_t SDMMC_ExecuteTuning(SDMMCHOST_TYPE *base,
SDMMCHOST_TRANSFER_FUNCTION transfer,
uint32_t tuningCmd,
uint32_t blockSize)
{
SDMMCHOST_TRANSFER content = {0U};
SDMMCHOST_COMMAND command = {0U};
SDMMCHOST_DATA data = {0U};
uint32_t buffer[32U] = {0U};
bool tuningError = true;
command.index = tuningCmd;
command.argument = 0U;
command.responseType = kCARD_ResponseTypeR1;
data.blockSize = blockSize;
data.blockCount = 1U;
data.rxData = buffer;
/* add this macro for adpter to different driver */
SDMMCHOST_ENABLE_TUNING_FLAG(data);
content.command = &command;
content.data = &data;
/* enable the standard tuning */
SDMMCHOST_EXECUTE_STANDARD_TUNING_ENABLE(base, true);
while (true)
{
/* send tuning block */
if ((kStatus_Success != transfer(base, &content)))
{
return kStatus_SDMMC_TransferFailed;
}
SDMMCHOST_Delay(1U);
/*wait excute tuning bit clear*/
if ((SDMMCHOST_EXECUTE_STANDARD_TUNING_STATUS(base) != 0U))
{
continue;
}
/* if tuning error , re-tuning again */
if ((SDMMCHOST_CHECK_TUNING_ERROR(base) != 0U) && tuningError)
{
tuningError = false;
/* enable the standard tuning */
SDMMCHOST_EXECUTE_STANDARD_TUNING_ENABLE(base, true);
SDMMCHOST_ADJUST_TUNING_DELAY(base, SDMMCHOST_STANDARD_TUNING_START);
}
else
{
break;
}
}
/* check tuning result*/
if (SDMMCHOST_EXECUTE_STANDARD_TUNING_RESULT(base) == 0U)
{
return kStatus_SDMMC_TuningFail;
}
#if !SDMMC_ENABLE_SOFTWARE_TUNING
SDMMCHOST_AUTO_TUNING_ENABLE(base, true);
#endif
return kStatus_Success;
}
@@ -0,0 +1,9 @@
config BSP_USING_EXTSRAM
bool "config semc extern sram"
default n
select MEM_EXTERN_SRAM
if BSP_USING_EXTSRAM
config EXTSRAM_MAX_NUM
int "config extsram chip num"
default 4
endif
@@ -0,0 +1,3 @@
SRC_FILES := connect_semc.c fsl_semc.c semc_externsdram_test.c
include $(KERNEL_ROOT)/compiler.mk
@@ -0,0 +1,57 @@
#include "fsl_semc.h"
#include "clock_config.h"
#include <xs_base.h>
#define EXAMPLE_SEMC SEMC
#define EXAMPLE_SEMC_START_ADDRESS (0x80000000U)
#define EXAMPLE_SEMC_CLK_FREQ CLOCK_GetFreq(kCLOCK_SemcClk)
#define SEMC_SRAM_SIZE (32 * 1024 * 1024)
status_t BOARD_InitSEMC(void)
{
semc_config_t config;
semc_sdram_config_t sdramconfig;
uint32_t clockFrq = EXAMPLE_SEMC_CLK_FREQ;
/* Initializes the MAC configure structure to zero. */
memset(&config, 0, sizeof(semc_config_t));
memset(&sdramconfig, 0, sizeof(semc_sdram_config_t));
/* Initialize SEMC. */
SEMC_GetDefaultConfig(&config);
config.dqsMode = kSEMC_Loopbackdqspad; /* For more accurate timing. */
SEMC_Init(SEMC, &config);
/* Configure SDRAM. */
sdramconfig.csxPinMux = kSEMC_MUXCSX0;
sdramconfig.address = 0x80000000;
sdramconfig.memsize_kbytes = 32 * 1024; /* 32MB = 32*1024*1KBytes*/
sdramconfig.portSize = kSEMC_PortSize16Bit;
sdramconfig.burstLen = kSEMC_Sdram_BurstLen8;
sdramconfig.columnAddrBitNum = kSEMC_SdramColunm_9bit;
sdramconfig.casLatency = kSEMC_LatencyThree;
sdramconfig.tPrecharge2Act_Ns = 18; /* Trp 18ns */
sdramconfig.tAct2ReadWrite_Ns = 18; /* Trcd 18ns */
sdramconfig.tRefreshRecovery_Ns = 67; /* Use the maximum of the (Trfc , Txsr). */
sdramconfig.tWriteRecovery_Ns = 12; /* 12ns */
sdramconfig.tCkeOff_Ns =
42; /* The minimum cycle of SDRAM CLK off state. CKE is off in self refresh at a minimum period tRAS.*/
sdramconfig.tAct2Prechage_Ns = 42; /* Tras 42ns */
sdramconfig.tSelfRefRecovery_Ns = 67;
sdramconfig.tRefresh2Refresh_Ns = 60;
sdramconfig.tAct2Act_Ns = 60;
sdramconfig.tPrescalePeriod_Ns = 160 * (1000000000 / clockFrq);
sdramconfig.refreshPeriod_nsPerRow = 64 * 1000000 / 8192; /* 64ms/8192 */
sdramconfig.refreshUrgThreshold = sdramconfig.refreshPeriod_nsPerRow;
sdramconfig.refreshBurstLen = 1;
return SEMC_ConfigureSDRAM(SEMC, kSEMC_SDRAM_CS0, &sdramconfig, clockFrq);
}
#ifdef BSP_USING_EXTSRAM
int ExtSramInit(void)
{
extern void ExtSramInitBoardMemory(void *start_phy_address, void *end_phy_address, uint8 extsram_idx);
ExtSramInitBoardMemory((void*)(EXAMPLE_SEMC_START_ADDRESS), (void*)((EXAMPLE_SEMC_START_ADDRESS + SEMC_SRAM_SIZE)), kSEMC_SDRAM_CS0);
return 0;
}
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,180 @@
/*
* Copyright 2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "board.h"
#define EXAMPLE_SEMC_START_ADDRESS (0x80000000U)
#define SEMC_EXAMPLE_DATALEN (0x1000U)
/*******************************************************************************
* Prototypes
******************************************************************************/
static void SEMC_SDRAMReadWrite32Bit(void);
static void SEMC_SDRAMReadWrite16Bit(void);
static void SEMC_SDRAMReadWrite8Bit(void);
/*******************************************************************************
* Variables
******************************************************************************/
uint32_t sdram_writeBuffer[SEMC_EXAMPLE_DATALEN];
uint32_t sdram_readBuffer[SEMC_EXAMPLE_DATALEN];
/*!
* @brief Main function
*/
int semc_externsram_test(void)
{
KPrintf("\r\n SEMC SDRAM Example Start!\r\n");
/* 32Bit data read and write. */
SEMC_SDRAMReadWrite32Bit();
/* 16Bit data read and write. */
SEMC_SDRAMReadWrite16Bit();
/* 8Bit data read and write. */
SEMC_SDRAMReadWrite8Bit();
KPrintf("\r\n SEMC SDRAM Example End.\r\n");
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0),semc_externsram_test, semc_externsram_test, semc_externsram_test );
void SEMC_SDRAMReadWrite32Bit(void)
{
uint32_t index;
uint32_t datalen = SEMC_EXAMPLE_DATALEN;
uint32_t *sdram = (uint32_t *)EXAMPLE_SEMC_START_ADDRESS; /* SDRAM start address. */
int result = 0;
KPrintf("\r\n SEMC SDRAM Memory 32 bit Write Start, Start Address 0x%x, Data Length %d !\r\n", sdram, datalen);
/* Prepare data and write to SDRAM. */
for (index = 0; index < datalen; index++)
{
sdram_writeBuffer[index] = index;
sdram[index] = sdram_writeBuffer[index];
}
KPrintf("\r\n SEMC SDRAM Read 32 bit Data Start, Start Address 0x%x, Data Length %d !\r\n", sdram, datalen);
/* Read data from the SDRAM. */
for (index = 0; index < datalen; index++)
{
sdram_readBuffer[index] = sdram[index];
}
KPrintf("\r\n SEMC SDRAM 32 bit Data Write and Read Compare Start!\r\n");
/* Compare the two buffers. */
while (datalen--)
{
if (sdram_writeBuffer[datalen] != sdram_readBuffer[datalen])
{
result = -1;
break;
}
}
if (result < 0)
{
KPrintf("\r\n SEMC SDRAM 32 bit Data Write and Read Compare Failed!\r\n");
}
else
{
KPrintf("\r\n SEMC SDRAM 32 bit Data Write and Read Compare Succeed!\r\n");
}
}
static void SEMC_SDRAMReadWrite16Bit(void)
{
uint32_t index;
uint32_t datalen = SEMC_EXAMPLE_DATALEN;
uint16_t *sdram = (uint16_t *)EXAMPLE_SEMC_START_ADDRESS; /* SDRAM start address. */
int result = 0;
KPrintf("\r\n SEMC SDRAM Memory 16 bit Write Start, Start Address 0x%x, Data Length %d !\r\n", sdram, datalen);
memset(sdram_writeBuffer, 0, sizeof(sdram_writeBuffer));
memset(sdram_readBuffer, 0, sizeof(sdram_readBuffer));
/* Prepare data and write to SDRAM. */
for (index = 0; index < datalen; index++)
{
sdram_writeBuffer[index] = index % 0xFFFF;
sdram[index] = sdram_writeBuffer[index];
}
KPrintf("\r\n SEMC SDRAM Read 16 bit Data Start, Start Address 0x%x, Data Length %d !\r\n", sdram, datalen);
/* Read data from the SDRAM. */
for (index = 0; index < datalen; index++)
{
sdram_readBuffer[index] = sdram[index];
}
KPrintf("\r\n SEMC SDRAM 16 bit Data Write and Read Compare Start!\r\n");
/* Compare the two buffers. */
while (datalen--)
{
if (sdram_writeBuffer[datalen] != sdram_readBuffer[datalen])
{
result = -1;
break;
}
}
if (result < 0)
{
KPrintf("\r\n SEMC SDRAM 16 bit Data Write and Read Compare Failed!\r\n");
}
else
{
KPrintf("\r\n SEMC SDRAM 16 bit Data Write and Read Compare Succeed!\r\n");
}
}
static void SEMC_SDRAMReadWrite8Bit(void)
{
uint32_t index;
uint32_t datalen = SEMC_EXAMPLE_DATALEN;
uint8_t *sdram = (uint8_t *)EXAMPLE_SEMC_START_ADDRESS; /* SDRAM start address. */
int result = 0;
KPrintf("\r\n SEMC SDRAM Memory 8 bit Write Start, Start Address 0x%x, Data Length %d !\r\n", sdram, datalen);
memset(sdram_writeBuffer, 0, sizeof(sdram_writeBuffer));
memset(sdram_readBuffer, 0, sizeof(sdram_readBuffer));
/* Prepare data and write to SDRAM. */
for (index = 0; index < datalen; index++)
{
sdram_writeBuffer[index] = index % 0x100;
sdram[index] = sdram_writeBuffer[index];
}
KPrintf("\r\n SEMC SDRAM Read 8 bit Data Start, Start Address 0x%x, Data Length %d !\r\n", sdram, datalen);
/* Read data from the SDRAM. */
for (index = 0; index < datalen; index++)
{
sdram_readBuffer[index] = sdram[index];
}
KPrintf("\r\n SEMC SDRAM 8 bit Data Write and Read Compare Start!\r\n");
/* Compare the two buffers. */
while (datalen--)
{
if (sdram_writeBuffer[datalen] != sdram_readBuffer[datalen])
{
result = -1;
break;
}
}
if (result < 0)
{
KPrintf("\r\n SEMC SDRAM 8 bit Data Write and Read Compare Failed!\r\n");
}
else
{
KPrintf("\r\n SEMC SDRAM 8 bit Data Write and Read Compare Succeed!\r\n");
}
}
@@ -0,0 +1,45 @@
config BSP_USING_SPI1
bool "Enable SPI1"
default y
if BSP_USING_SPI1
config SPI_1_BUS_NAME
string "spi1 bus name"
default "spi1"
config SPI_1_DRV_NAME
string "spi bus 1 driver name"
default "spi1_drv"
config SPI_1_DEV_NAME_0
string "spi bus 1 device name"
default "spi1_dev"
endif
config BSP_USING_SPI2
bool "Enable SPI2"
default y
if BSP_USING_SPI2
config SPI_2_BUS_NAME
string "spi2 bus name"
default "spi2"
config SPI_2_DRV_NAME
string "spi bus 2 driver name"
default "spi2_drv"
config SPI_2_DEV_NAME_0
string "spi bus 2 device name"
default "spi2_dev"
endif
config BSP_USING_SPI3
bool "Enable SPI3"
default y
if BSP_USING_SPI3
config SPI_3_BUS_NAME
string "spi3 bus name"
default "spi3"
config SPI_3_DRV_NAME
string "spi bus 3 driver name"
default "spi3_drv"
config SPI_3_DEV_NAME_0
string "spi bus 3 device name"
default "spi3_dev"
endif
@@ -0,0 +1,7 @@
SRC_FILES := fsl_lpspi.c connect_spi.c
ifeq ($(CONFIG_RESOURCES_SPI_SFUD),y)
SRC_FILES += connect_flash_spi.c
endif
include $(KERNEL_ROOT)/compiler.mk

Some files were not shown because too many files have changed in this diff Show More