summaryrefslogtreecommitdiffstats
path: root/bsps/arm/imxrt/mcux-sdk/drivers/common/fsl_common_arm.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--bsps/arm/imxrt/mcux-sdk/drivers/common/fsl_common_arm.h837
1 files changed, 837 insertions, 0 deletions
diff --git a/bsps/arm/imxrt/mcux-sdk/drivers/common/fsl_common_arm.h b/bsps/arm/imxrt/mcux-sdk/drivers/common/fsl_common_arm.h
new file mode 100644
index 0000000000..49d50de92a
--- /dev/null
+++ b/bsps/arm/imxrt/mcux-sdk/drivers/common/fsl_common_arm.h
@@ -0,0 +1,837 @@
+/*
+ * Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2022 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _FSL_COMMON_ARM_H_
+#define _FSL_COMMON_ARM_H_
+
+/*
+ * For CMSIS pack RTE.
+ * CMSIS pack RTE generates "RTC_Components.h" which contains the statements
+ * of the related <RTE_Components_h> element for all selected software components.
+ */
+#ifdef _RTE_
+#include "RTE_Components.h"
+#endif
+
+/*!
+ * @addtogroup ksdk_common
+ * @{
+ */
+
+/*! @name Atomic modification
+ *
+ * These macros are used for atomic access, such as read-modify-write
+ * to the peripheral registers.
+ *
+ * - SDK_ATOMIC_LOCAL_ADD
+ * - SDK_ATOMIC_LOCAL_SET
+ * - SDK_ATOMIC_LOCAL_CLEAR
+ * - SDK_ATOMIC_LOCAL_TOGGLE
+ * - SDK_ATOMIC_LOCAL_CLEAR_AND_SET
+ *
+ * Take SDK_ATOMIC_LOCAL_CLEAR_AND_SET as an example: the parameter @c addr
+ * means the address of the peripheral register or variable you want to modify
+ * atomically, the parameter @c clearBits is the bits to clear, the parameter
+ * @c setBits it the bits to set.
+ * For example, to set a 32-bit register bit1:bit0 to 0b10, use like this:
+ *
+ * @code
+ volatile uint32_t * reg = (volatile uint32_t *)REG_ADDR;
+
+ SDK_ATOMIC_LOCAL_CLEAR_AND_SET(reg, 0x03, 0x02);
+ @endcode
+ *
+ * In this example, the register bit1:bit0 are cleared and bit1 is set, as a result,
+ * register bit1:bit0 = 0b10.
+ *
+ * @note For the platforms don't support exclusive load and store, these macros
+ * disable the global interrupt to pretect the modification.
+ *
+ * @note These macros only guarantee the local processor atomic operations. For
+ * the multi-processor devices, use hardware semaphore such as SEMA42 to
+ * guarantee exclusive access if necessary.
+ *
+ * @{
+ */
+
+/* clang-format off */
+#if ((defined(__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined(__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined(__ARM_ARCH_8M_MAIN__) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ == 1)))
+/* clang-format on */
+
+/* If the LDREX and STREX are supported, use them. */
+#define _SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, val, ops) \
+ do \
+ { \
+ (val) = __LDREXB(addr); \
+ (ops); \
+ } while (0UL != __STREXB((val), (addr)))
+
+#define _SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, val, ops) \
+ do \
+ { \
+ (val) = __LDREXH(addr); \
+ (ops); \
+ } while (0UL != __STREXH((val), (addr)))
+
+#define _SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, val, ops) \
+ do \
+ { \
+ (val) = __LDREXW(addr); \
+ (ops); \
+ } while (0UL != __STREXW((val), (addr)))
+
+static inline void _SDK_AtomicLocalAdd1Byte(volatile uint8_t *addr, uint8_t val)
+{
+ uint8_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val += val);
+}
+
+static inline void _SDK_AtomicLocalAdd2Byte(volatile uint16_t *addr, uint16_t val)
+{
+ uint16_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val += val);
+}
+
+static inline void _SDK_AtomicLocalAdd4Byte(volatile uint32_t *addr, uint32_t val)
+{
+ uint32_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val += val);
+}
+
+static inline void _SDK_AtomicLocalSub1Byte(volatile uint8_t *addr, uint8_t val)
+{
+ uint8_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val -= val);
+}
+
+static inline void _SDK_AtomicLocalSub2Byte(volatile uint16_t *addr, uint16_t val)
+{
+ uint16_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val -= val);
+}
+
+static inline void _SDK_AtomicLocalSub4Byte(volatile uint32_t *addr, uint32_t val)
+{
+ uint32_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val -= val);
+}
+
+static inline void _SDK_AtomicLocalSet1Byte(volatile uint8_t *addr, uint8_t bits)
+{
+ uint8_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val |= bits);
+}
+
+static inline void _SDK_AtomicLocalSet2Byte(volatile uint16_t *addr, uint16_t bits)
+{
+ uint16_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val |= bits);
+}
+
+static inline void _SDK_AtomicLocalSet4Byte(volatile uint32_t *addr, uint32_t bits)
+{
+ uint32_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val |= bits);
+}
+
+static inline void _SDK_AtomicLocalClear1Byte(volatile uint8_t *addr, uint8_t bits)
+{
+ uint8_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val &= ~bits);
+}
+
+static inline void _SDK_AtomicLocalClear2Byte(volatile uint16_t *addr, uint16_t bits)
+{
+ uint16_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val &= ~bits);
+}
+
+static inline void _SDK_AtomicLocalClear4Byte(volatile uint32_t *addr, uint32_t bits)
+{
+ uint32_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val &= ~bits);
+}
+
+static inline void _SDK_AtomicLocalToggle1Byte(volatile uint8_t *addr, uint8_t bits)
+{
+ uint8_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val ^= bits);
+}
+
+static inline void _SDK_AtomicLocalToggle2Byte(volatile uint16_t *addr, uint16_t bits)
+{
+ uint16_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val ^= bits);
+}
+
+static inline void _SDK_AtomicLocalToggle4Byte(volatile uint32_t *addr, uint32_t bits)
+{
+ uint32_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val ^= bits);
+}
+
+static inline void _SDK_AtomicLocalClearAndSet1Byte(volatile uint8_t *addr, uint8_t clearBits, uint8_t setBits)
+{
+ uint8_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val = (s_val & ~clearBits) | setBits);
+}
+
+static inline void _SDK_AtomicLocalClearAndSet2Byte(volatile uint16_t *addr, uint16_t clearBits, uint16_t setBits)
+{
+ uint16_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val = (s_val & ~clearBits) | setBits);
+}
+
+static inline void _SDK_AtomicLocalClearAndSet4Byte(volatile uint32_t *addr, uint32_t clearBits, uint32_t setBits)
+{
+ uint32_t s_val;
+
+ _SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val = (s_val & ~clearBits) | setBits);
+}
+
+#define SDK_ATOMIC_LOCAL_ADD(addr, val) \
+ ((1UL == sizeof(*(addr))) ? \
+ _SDK_AtomicLocalAdd1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(val)) : \
+ ((2UL == sizeof(*(addr))) ? _SDK_AtomicLocalAdd2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(val)) : \
+ _SDK_AtomicLocalAdd4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(val))))
+
+#define SDK_ATOMIC_LOCAL_SET(addr, bits) \
+ ((1UL == sizeof(*(addr))) ? \
+ _SDK_AtomicLocalSet1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(bits)) : \
+ ((2UL == sizeof(*(addr))) ? _SDK_AtomicLocalSet2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(bits)) : \
+ _SDK_AtomicLocalSet4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(bits))))
+
+#define SDK_ATOMIC_LOCAL_CLEAR(addr, bits) \
+ ((1UL == sizeof(*(addr))) ? \
+ _SDK_AtomicLocalClear1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(bits)) : \
+ ((2UL == sizeof(*(addr))) ? \
+ _SDK_AtomicLocalClear2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(bits)) : \
+ _SDK_AtomicLocalClear4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(bits))))
+
+#define SDK_ATOMIC_LOCAL_TOGGLE(addr, bits) \
+ ((1UL == sizeof(*(addr))) ? \
+ _SDK_AtomicLocalToggle1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(bits)) : \
+ ((2UL == sizeof(*(addr))) ? \
+ _SDK_AtomicLocalToggle2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(bits)) : \
+ _SDK_AtomicLocalToggle4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(bits))))
+
+#define SDK_ATOMIC_LOCAL_CLEAR_AND_SET(addr, clearBits, setBits) \
+ ((1UL == sizeof(*(addr))) ? \
+ _SDK_AtomicLocalClearAndSet1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(clearBits), (uint8_t)(setBits)) : \
+ ((2UL == sizeof(*(addr))) ? \
+ _SDK_AtomicLocalClearAndSet2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(clearBits), (uint16_t)(setBits)) : \
+ _SDK_AtomicLocalClearAndSet4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(clearBits), (uint32_t)(setBits))))
+#else
+
+#define SDK_ATOMIC_LOCAL_ADD(addr, val) \
+ do \
+ { \
+ uint32_t s_atomicOldInt; \
+ s_atomicOldInt = DisableGlobalIRQ(); \
+ *(addr) += (val); \
+ EnableGlobalIRQ(s_atomicOldInt); \
+ } while (0)
+
+#define SDK_ATOMIC_LOCAL_SET(addr, bits) \
+ do \
+ { \
+ uint32_t s_atomicOldInt; \
+ s_atomicOldInt = DisableGlobalIRQ(); \
+ *(addr) |= (bits); \
+ EnableGlobalIRQ(s_atomicOldInt); \
+ } while (0)
+
+#define SDK_ATOMIC_LOCAL_CLEAR(addr, bits) \
+ do \
+ { \
+ uint32_t s_atomicOldInt; \
+ s_atomicOldInt = DisableGlobalIRQ(); \
+ *(addr) &= ~(bits); \
+ EnableGlobalIRQ(s_atomicOldInt); \
+ } while (0)
+
+#define SDK_ATOMIC_LOCAL_TOGGLE(addr, bits) \
+ do \
+ { \
+ uint32_t s_atomicOldInt; \
+ s_atomicOldInt = DisableGlobalIRQ(); \
+ *(addr) ^= (bits); \
+ EnableGlobalIRQ(s_atomicOldInt); \
+ } while (0)
+
+#define SDK_ATOMIC_LOCAL_CLEAR_AND_SET(addr, clearBits, setBits) \
+ do \
+ { \
+ uint32_t s_atomicOldInt; \
+ s_atomicOldInt = DisableGlobalIRQ(); \
+ *(addr) = (*(addr) & ~(clearBits)) | (setBits); \
+ EnableGlobalIRQ(s_atomicOldInt); \
+ } while (0)
+
+#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 ISR exit barrier
+ * @{
+ *
+ * ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
+ * exception return operation might vector to incorrect interrupt.
+ * For Cortex-M7, if core speed much faster than peripheral register write speed,
+ * the peripheral interrupt flags may be still set after exiting ISR, this results to
+ * the same error similar with errata 83869.
+ */
+#if (defined __CORTEX_M) && ((__CORTEX_M == 4U) || (__CORTEX_M == 7U))
+#define SDK_ISR_EXIT_BARRIER __DSB()
+#else
+#define SDK_ISR_EXIT_BARRIER
+#endif
+
+/* @} */
+
+/*! @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
+#elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
+/*! Macro to define a variable with alignbytes alignment */
+#define SDK_ALIGN(var, alignbytes) __attribute__((aligned(alignbytes))) var
+#elif defined(__GNUC__)
+/*! Macro to define a variable with alignbytes alignment */
+#define SDK_ALIGN(var, alignbytes) var __attribute__((aligned(alignbytes)))
+#else
+#error Toolchain not supported
+#endif
+
+/*! 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_ALIGN(var, 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) SDK_ALIGN(var, FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
+#endif
+
+/*! Macro to change a value to a given size aligned value */
+#define SDK_SIZEALIGN(var, alignbytes) \
+ ((unsigned int)((var) + ((alignbytes)-1U)) & (unsigned int)(~(unsigned int)((alignbytes)-1U)))
+/* @} */
+
+/*! @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(FSL_FEATURE_HAS_NO_NONCACHEABLE_SECTION) && FSL_FEATURE_HAS_NO_NONCACHEABLE_SECTION)) && \
+ defined(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE))
+
+#if (defined(__ICCARM__))
+#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"
+
+#elif (defined(__CC_ARM) || defined(__ARMCC_VERSION))
+#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
+#if (defined(__CC_ARM))
+#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
+#else
+#define AT_NONCACHEABLE_SECTION(var) __attribute__((section(".bss.NonCacheable"))) var
+#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \
+ __attribute__((section(".bss.NonCacheable"))) __attribute__((aligned(alignbytes))) var
+#endif
+
+#elif (defined(__GNUC__))
+#if defined(__ARM_ARCH_8A__) /* This macro is ARMv8-A specific */
+#define __CS "//"
+#else
+#define __CS "@"
+#endif
+
+/* 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.
+ */
+#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 " __CS))) var
+#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \
+ __attribute__((section("NonCacheable,\"aw\",%nobits " __CS))) var __attribute__((aligned(alignbytes)))
+#else
+#error Toolchain not supported.
+#endif
+
+#else
+
+#define AT_NONCACHEABLE_SECTION(var) var
+#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) SDK_ALIGN(var, alignbytes)
+#define AT_NONCACHEABLE_SECTION_INIT(var) var
+#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) SDK_ALIGN(var, alignbytes)
+
+#endif
+
+/* @} */
+
+/*!
+ * @name Time sensitive region
+ * @{
+ */
+#if (defined(__ICCARM__))
+#define AT_QUICKACCESS_SECTION_CODE(func) func @"CodeQuickAccess"
+#define AT_QUICKACCESS_SECTION_DATA(var) var @"DataQuickAccess"
+#define AT_QUICKACCESS_SECTION_DATA_ALIGN(var, alignbytes) \
+ SDK_PRAGMA(data_alignment = alignbytes) var @"DataQuickAccess"
+#elif (defined(__CC_ARM) || defined(__ARMCC_VERSION))
+#define AT_QUICKACCESS_SECTION_CODE(func) __attribute__((section("CodeQuickAccess"), __noinline__)) func
+#define AT_QUICKACCESS_SECTION_DATA(var) __attribute__((section("DataQuickAccess"))) var
+#define AT_QUICKACCESS_SECTION_DATA_ALIGN(var, alignbytes) \
+ __attribute__((section("DataQuickAccess"))) __attribute__((aligned(alignbytes))) var
+#elif (defined(__GNUC__))
+#define AT_QUICKACCESS_SECTION_CODE(func) __attribute__((section("CodeQuickAccess"), __noinline__)) func
+#define AT_QUICKACCESS_SECTION_DATA(var) __attribute__((section("DataQuickAccess"))) var
+#define AT_QUICKACCESS_SECTION_DATA_ALIGN(var, alignbytes) \
+ __attribute__((section("DataQuickAccess"))) var __attribute__((aligned(alignbytes)))
+#else
+#error Toolchain not supported.
+#endif /* defined(__ICCARM__) */
+
+/*! @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__) */
+/* @} */
+
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ void DefaultISR(void);
+#endif
+
+/*
+ * 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
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* __cplusplus*/
+
+/*!
+ * @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)
+{
+ status_t status = kStatus_Success;
+
+ if (NotAvail_IRQn == interrupt)
+ {
+ status = kStatus_Fail;
+ }
+
+#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
+ else if ((int32_t)interrupt >= (int32_t)FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
+ {
+ status = kStatus_Fail;
+ }
+#endif
+
+ else
+ {
+#if defined(__GIC_PRIO_BITS)
+ GIC_EnableIRQ(interrupt);
+#else
+ NVIC_EnableIRQ(interrupt);
+#endif
+ }
+
+ return status;
+}
+
+/*!
+ * @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)
+{
+ status_t status = kStatus_Success;
+
+ if (NotAvail_IRQn == interrupt)
+ {
+ status = kStatus_Fail;
+ }
+
+#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
+ else if ((int32_t)interrupt >= (int32_t)FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
+ {
+ status = kStatus_Fail;
+ }
+#endif
+
+ else
+ {
+#if defined(__GIC_PRIO_BITS)
+ GIC_DisableIRQ(interrupt);
+#else
+ NVIC_DisableIRQ(interrupt);
+#endif
+ }
+
+ return status;
+}
+
+#if defined(__GIC_PRIO_BITS)
+#define NVIC_SetPriority(irq, prio) do {} while(0)
+#endif
+
+/*!
+ * @brief Enable the IRQ, and also set the interrupt priority.
+ *
+ * Only handle 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 handles 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 to Enable.
+ * @param priNum Priority number set to interrupt controller register.
+ * @retval kStatus_Success Interrupt priority set successfully
+ * @retval kStatus_Fail Failed to set the interrupt priority.
+ */
+static inline status_t EnableIRQWithPriority(IRQn_Type interrupt, uint8_t priNum)
+{
+ status_t status = kStatus_Success;
+
+ if (NotAvail_IRQn == interrupt)
+ {
+ status = kStatus_Fail;
+ }
+
+#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
+ else if ((int32_t)interrupt >= (int32_t)FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
+ {
+ status = kStatus_Fail;
+ }
+#endif
+
+ else
+ {
+#if defined(__GIC_PRIO_BITS)
+ GIC_SetPriority(interrupt, priNum);
+ GIC_EnableIRQ(interrupt);
+#else
+ NVIC_SetPriority(interrupt, priNum);
+ NVIC_EnableIRQ(interrupt);
+#endif
+ }
+
+ return status;
+}
+
+/*!
+ * @brief Set the IRQ priority.
+ *
+ * Only handle 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 handles 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 to set.
+ * @param priNum Priority number set to interrupt controller register.
+ *
+ * @retval kStatus_Success Interrupt priority set successfully
+ * @retval kStatus_Fail Failed to set the interrupt priority.
+ */
+static inline status_t IRQ_SetPriority(IRQn_Type interrupt, uint8_t priNum)
+{
+ status_t status = kStatus_Success;
+
+ if (NotAvail_IRQn == interrupt)
+ {
+ status = kStatus_Fail;
+ }
+
+#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
+ else if ((int32_t)interrupt >= (int32_t)FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
+ {
+ status = kStatus_Fail;
+ }
+#endif
+
+ else
+ {
+#if defined(__GIC_PRIO_BITS)
+ GIC_SetPriority(interrupt, priNum);
+#else
+ NVIC_SetPriority(interrupt, priNum);
+#endif
+ }
+
+ return status;
+}
+
+/*!
+ * @brief Clear the pending IRQ flag.
+ *
+ * Only handle 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 handles the LEVEL1 interrupts. The number of LEVEL1 interrupts
+ * is indicated by the feature macro FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS.
+ *
+ * @param interrupt The flag which IRQ to clear.
+ *
+ * @retval kStatus_Success Interrupt priority set successfully
+ * @retval kStatus_Fail Failed to set the interrupt priority.
+ */
+static inline status_t IRQ_ClearPendingIRQ(IRQn_Type interrupt)
+{
+ status_t status = kStatus_Success;
+
+ if (NotAvail_IRQn == interrupt)
+ {
+ status = kStatus_Fail;
+ }
+
+#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
+ else if ((int32_t)interrupt >= (int32_t)FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
+ {
+ status = kStatus_Fail;
+ }
+#endif
+
+ else
+ {
+#if defined(__GIC_PRIO_BITS)
+ GIC_ClearPendingIRQ(interrupt);
+#else
+ NVIC_ClearPendingIRQ(interrupt);
+#endif
+ }
+
+ return status;
+}
+
+/*!
+ * @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)
+{
+ uint32_t mask;
+
+#if defined(CPSR_I_Msk)
+ mask = __get_CPSR() & CPSR_I_Msk;
+#elif defined(DAIF_I_BIT)
+ mask = __get_DAIF() & DAIF_I_BIT;
+#else
+ mask = __get_PRIMASK();
+#endif
+ __disable_irq();
+
+ return mask;
+}
+
+/*!
+ * @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);
+#elif defined(DAIF_I_BIT)
+ if (0UL == primask)
+ {
+ __enable_irq();
+ }
+#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))
+
+/*
+ * When FSL_FEATURE_POWERLIB_EXTEND is defined to non-zero value,
+ * powerlib should be used instead of these functions.
+ */
+#if !(defined(FSL_FEATURE_POWERLIB_EXTEND) && (FSL_FEATURE_POWERLIB_EXTEND != 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_POWERLIB_EXTEND */
+#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */
+
+#if defined(DWT)
+/*!
+ * @brief Enable the counter to get CPU cycles.
+ */
+void MSDK_EnableCpuCycleCounter(void);
+
+/*!
+ * @brief Get the current CPU cycle count.
+ *
+ * @return Current CPU cycle count.
+ */
+uint32_t MSDK_GetCpuCycleCount(void);
+#endif
+
+#if defined(__cplusplus)
+}
+#endif /* __cplusplus*/
+
+/*! @} */
+
+#endif /* _FSL_COMMON_ARM_H_ */