summaryrefslogtreecommitdiffstats
path: root/bsps/arm/imxrt/mcux-sdk/drivers/flexspi
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--bsps/arm/imxrt/mcux-sdk/drivers/flexspi/fsl_flexspi.c1271
-rw-r--r--bsps/arm/imxrt/mcux-sdk/drivers/flexspi/fsl_flexspi.h886
-rw-r--r--bsps/arm/imxrt/mcux-sdk/drivers/flexspi/fsl_flexspi_dma.h144
-rw-r--r--bsps/arm/imxrt/mcux-sdk/drivers/flexspi/fsl_flexspi_edma.c366
-rw-r--r--bsps/arm/imxrt/mcux-sdk/drivers/flexspi/fsl_flexspi_edma.h150
5 files changed, 2817 insertions, 0 deletions
diff --git a/bsps/arm/imxrt/mcux-sdk/drivers/flexspi/fsl_flexspi.c b/bsps/arm/imxrt/mcux-sdk/drivers/flexspi/fsl_flexspi.c
new file mode 100644
index 0000000000..71da8f1c92
--- /dev/null
+++ b/bsps/arm/imxrt/mcux-sdk/drivers/flexspi/fsl_flexspi.c
@@ -0,0 +1,1271 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2022 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "fsl_flexspi.h"
+
+/* Component ID definition, used by tools. */
+#ifndef FSL_COMPONENT_ID
+#define FSL_COMPONENT_ID "platform.drivers.flexspi"
+#endif
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+#define FREQ_1MHz (1000000UL)
+#define FLEXSPI_DLLCR_DEFAULT (0x100UL)
+#define FLEXSPI_LUT_KEY_VAL (0x5AF05AF0UL)
+
+enum
+{
+ kFLEXSPI_DelayCellUnitMin = 75, /* 75ps. */
+ kFLEXSPI_DelayCellUnitMax = 225, /* 225ps. */
+};
+
+enum
+{
+ kFLEXSPI_FlashASampleClockSlaveDelayLocked =
+ FLEXSPI_STS2_ASLVLOCK_MASK, /* Flash A sample clock slave delay line locked. */
+ kFLEXSPI_FlashASampleClockRefDelayLocked =
+ FLEXSPI_STS2_AREFLOCK_MASK, /* Flash A sample clock reference delay line locked. */
+#if !((defined(FSL_FEATURE_FLEXSPI_HAS_NO_STS2_BSLVLOCK)) && (FSL_FEATURE_FLEXSPI_HAS_NO_STS2_BSLVLOCK))
+ kFLEXSPI_FlashBSampleClockSlaveDelayLocked =
+ FLEXSPI_STS2_BSLVLOCK_MASK, /* Flash B sample clock slave delay line locked. */
+#endif
+#if !((defined(FSL_FEATURE_FLEXSPI_HAS_NO_STS2_BREFLOCK)) && (FSL_FEATURE_FLEXSPI_HAS_NO_STS2_BREFLOCK))
+ kFLEXSPI_FlashBSampleClockRefDelayLocked =
+ FLEXSPI_STS2_BREFLOCK_MASK, /* Flash B sample clock reference delay line locked. */
+#endif
+};
+
+/*! @brief Common sets of flags used by the driver, _flexspi_flag_constants. */
+enum
+{
+ /*! IRQ sources enabled by the non-blocking transactional API. */
+ kIrqFlags = kFLEXSPI_IpTxFifoWatermarkEmptyFlag | kFLEXSPI_IpRxFifoWatermarkAvailableFlag |
+ kFLEXSPI_SequenceExecutionTimeoutFlag | kFLEXSPI_IpCommandSequenceErrorFlag |
+ kFLEXSPI_IpCommandGrantTimeoutFlag | kFLEXSPI_IpCommandExecutionDoneFlag,
+
+ /*! Errors to check for. */
+ kErrorFlags = kFLEXSPI_SequenceExecutionTimeoutFlag | kFLEXSPI_IpCommandSequenceErrorFlag |
+ kFLEXSPI_IpCommandGrantTimeoutFlag,
+};
+
+/* FLEXSPI transfer state, _flexspi_transfer_state. */
+enum
+{
+ kFLEXSPI_Idle = 0x0U, /*!< Transfer is done. */
+ kFLEXSPI_BusyWrite = 0x1U, /*!< FLEXSPI is busy write transfer. */
+ kFLEXSPI_BusyRead = 0x2U, /*!< FLEXSPI is busy write transfer. */
+};
+
+/*! @brief Typedef for interrupt handler. */
+typedef void (*flexspi_isr_t)(FLEXSPI_Type *base, flexspi_handle_t *handle);
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+static void FLEXSPI_Memset(void *src, uint8_t value, size_t length);
+
+/*!
+ * @brief Calculate flash A/B sample clock DLL.
+ *
+ * @param base FLEXSPI base pointer.
+ * @param config Flash configuration parameters.
+ */
+static uint32_t FLEXSPI_CalculateDll(FLEXSPI_Type *base, flexspi_device_config_t *config);
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+/*! @brief Pointers to flexspi bases for each instance. */
+static FLEXSPI_Type *const s_flexspiBases[] = FLEXSPI_BASE_PTRS;
+
+/*! @brief Pointers to flexspi IRQ number for each instance. */
+static const IRQn_Type s_flexspiIrqs[] = FLEXSPI_IRQS;
+
+#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
+/* Clock name array */
+static const clock_ip_name_t s_flexspiClock[] = FLEXSPI_CLOCKS;
+#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
+
+#if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
+/*! @brief Pointers to flexspi handles for each instance. */
+static flexspi_handle_t *s_flexspiHandle[ARRAY_SIZE(s_flexspiBases)];
+#endif
+
+#if defined(FSL_FEATURE_FLEXSPI_HAS_RESET) && FSL_FEATURE_FLEXSPI_HAS_RESET
+/*! @brief Pointers to FLEXSPI resets for each instance. */
+static const reset_ip_name_t s_flexspiResets[] = FLEXSPI_RSTS;
+#endif
+
+#if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
+/*! @brief Pointer to flexspi IRQ handler. */
+static flexspi_isr_t s_flexspiIsr;
+#endif
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+/* To avoid compiler opitimizing this API into memset() in library. */
+#if defined(__ICCARM__)
+#pragma optimize = none
+#endif /* defined(__ICCARM__) */
+static void FLEXSPI_Memset(void *src, uint8_t value, size_t length)
+{
+ assert(src != NULL);
+ uint8_t *p = src;
+
+ for (uint32_t i = 0U; i < length; i++)
+ {
+ *p = value;
+ p++;
+ }
+}
+
+uint32_t FLEXSPI_GetInstance(FLEXSPI_Type *base)
+{
+ uint32_t instance;
+
+ /* Find the instance index from base address mappings. */
+ for (instance = 0; instance < ARRAY_SIZE(s_flexspiBases); instance++)
+ {
+ if (s_flexspiBases[instance] == base)
+ {
+ break;
+ }
+ }
+
+ assert(instance < ARRAY_SIZE(s_flexspiBases));
+
+ return instance;
+}
+
+static uint32_t FLEXSPI_CalculateDll(FLEXSPI_Type *base, flexspi_device_config_t *config)
+{
+ bool isUnifiedConfig = true;
+ uint32_t flexspiDllValue;
+ uint32_t dllValue;
+ uint32_t temp;
+#if defined(FSL_FEATURE_FLEXSPI_DQS_DELAY_PS) && FSL_FEATURE_FLEXSPI_DQS_DELAY_PS
+ uint32_t internalDqsDelayPs = FSL_FEATURE_FLEXSPI_DQS_DELAY_PS;
+#endif
+ uint32_t rxSampleClock = (base->MCR0 & FLEXSPI_MCR0_RXCLKSRC_MASK) >> FLEXSPI_MCR0_RXCLKSRC_SHIFT;
+ switch (rxSampleClock)
+ {
+ case (uint32_t)kFLEXSPI_ReadSampleClkLoopbackInternally:
+ case (uint32_t)kFLEXSPI_ReadSampleClkLoopbackFromDqsPad:
+ case (uint32_t)kFLEXSPI_ReadSampleClkLoopbackFromSckPad:
+ isUnifiedConfig = true;
+ break;
+ case (uint32_t)kFLEXSPI_ReadSampleClkExternalInputFromDqsPad:
+ if (config->isSck2Enabled)
+ {
+ isUnifiedConfig = true;
+ }
+ else
+ {
+ isUnifiedConfig = false;
+ }
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ if (isUnifiedConfig)
+ {
+ flexspiDllValue = FLEXSPI_DLLCR_DEFAULT; /* 1 fixed delay cells in DLL delay chain) */
+ }
+ else
+ {
+ if (config->flexspiRootClk >= 100U * FREQ_1MHz)
+ {
+#if defined(FSL_FEATURE_FLEXSPI_DQS_DELAY_MIN) && FSL_FEATURE_FLEXSPI_DQS_DELAY_MIN
+ /* DLLEN = 1, SLVDLYTARGET = 0x0, */
+ flexspiDllValue = FLEXSPI_DLLCR_DLLEN(1) | FLEXSPI_DLLCR_SLVDLYTARGET(0x00);
+#else
+ /* DLLEN = 1, SLVDLYTARGET = 0xF, */
+ flexspiDllValue = FLEXSPI_DLLCR_DLLEN(1) | FLEXSPI_DLLCR_SLVDLYTARGET(0x0F);
+#endif
+ }
+ else
+ {
+ temp = (uint32_t)config->dataValidTime * 1000U; /* Convert data valid time in ns to ps. */
+ dllValue = temp / (uint32_t)kFLEXSPI_DelayCellUnitMin;
+ if (dllValue * (uint32_t)kFLEXSPI_DelayCellUnitMin < temp)
+ {
+ dllValue++;
+ }
+ flexspiDllValue = FLEXSPI_DLLCR_OVRDEN(1) | FLEXSPI_DLLCR_OVRDVAL(dllValue);
+ }
+ }
+ return flexspiDllValue;
+}
+
+status_t FLEXSPI_CheckAndClearError(FLEXSPI_Type *base, uint32_t status)
+{
+ status_t result = kStatus_Success;
+
+ /* Check for error. */
+ status &= (uint32_t)kErrorFlags;
+ if (0U != status)
+ {
+ /* Select the correct error code.. */
+ if (0U != (status & (uint32_t)kFLEXSPI_SequenceExecutionTimeoutFlag))
+ {
+ result = kStatus_FLEXSPI_SequenceExecutionTimeout;
+ }
+ else if (0U != (status & (uint32_t)kFLEXSPI_IpCommandSequenceErrorFlag))
+ {
+ result = kStatus_FLEXSPI_IpCommandSequenceError;
+ }
+ else if (0U != (status & (uint32_t)kFLEXSPI_IpCommandGrantTimeoutFlag))
+ {
+ result = kStatus_FLEXSPI_IpCommandGrantTimeout;
+ }
+ else
+ {
+ assert(false);
+ }
+
+ /* Clear the flags. */
+ FLEXSPI_ClearInterruptStatusFlags(base, status);
+
+ /* Reset fifos. These flags clear automatically. */
+ base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
+ base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
+ }
+
+ return result;
+}
+
+/*!
+ * brief Initializes the FLEXSPI module and internal state.
+ *
+ * This function enables the clock for FLEXSPI and also configures the FLEXSPI with the
+ * input configure parameters. Users should call this function before any FLEXSPI operations.
+ *
+ * param base FLEXSPI peripheral base address.
+ * param config FLEXSPI configure structure.
+ */
+void FLEXSPI_Init(FLEXSPI_Type *base, const flexspi_config_t *config)
+{
+ uint32_t configValue = 0;
+ uint8_t i = 0;
+
+#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
+ /* Enable the flexspi clock */
+ (void)CLOCK_EnableClock(s_flexspiClock[FLEXSPI_GetInstance(base)]);
+#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
+
+#if defined(FSL_FEATURE_FLEXSPI_HAS_RESET) && FSL_FEATURE_FLEXSPI_HAS_RESET
+ /* Reset the FLEXSPI module */
+ RESET_PeripheralReset(s_flexspiResets[FLEXSPI_GetInstance(base)]);
+#endif
+
+ /* Reset peripheral before configuring it. */
+ base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
+ FLEXSPI_SoftwareReset(base);
+
+ /* Configure MCR0 configuration items. */
+ configValue = FLEXSPI_MCR0_RXCLKSRC(config->rxSampleClock) | FLEXSPI_MCR0_DOZEEN(config->enableDoze) |
+ FLEXSPI_MCR0_IPGRANTWAIT(config->ipGrantTimeoutCycle) |
+ FLEXSPI_MCR0_AHBGRANTWAIT(config->ahbConfig.ahbGrantTimeoutCycle) |
+ FLEXSPI_MCR0_SCKFREERUNEN(config->enableSckFreeRunning) |
+ FLEXSPI_MCR0_HSEN(config->enableHalfSpeedAccess) |
+#if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN)
+ FLEXSPI_MCR0_COMBINATIONEN(config->enableCombination) |
+#endif
+#if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ATDFEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ATDFEN)
+ FLEXSPI_MCR0_ATDFEN(config->ahbConfig.enableAHBWriteIpTxFifo) |
+#endif
+#if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ARDFEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ARDFEN)
+ FLEXSPI_MCR0_ARDFEN(config->ahbConfig.enableAHBWriteIpRxFifo) |
+#endif
+ FLEXSPI_MCR0_MDIS_MASK;
+ base->MCR0 = configValue;
+
+ /* Configure MCR1 configurations. */
+ configValue =
+ FLEXSPI_MCR1_SEQWAIT(config->seqTimeoutCycle) | FLEXSPI_MCR1_AHBBUSWAIT(config->ahbConfig.ahbBusTimeoutCycle);
+ base->MCR1 = configValue;
+
+ /* Configure MCR2 configurations. */
+ configValue = base->MCR2;
+ configValue &= ~(FLEXSPI_MCR2_RESUMEWAIT_MASK |
+#if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR2_SCKBDIFFOPT) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR2_SCKBDIFFOPT)
+ FLEXSPI_MCR2_SCKBDIFFOPT_MASK |
+#endif
+ FLEXSPI_MCR2_SAMEDEVICEEN_MASK | FLEXSPI_MCR2_CLRAHBBUFOPT_MASK);
+ configValue |= FLEXSPI_MCR2_RESUMEWAIT(config->ahbConfig.resumeWaitCycle) |
+#if defined(FSL_FEATURE_FLEXSPI_SUPPORT_SEPERATE_RXCLKSRC_PORTB) && FSL_FEATURE_FLEXSPI_SUPPORT_SEPERATE_RXCLKSRC_PORTB
+ FLEXSPI_MCR2_RXCLKSRC_B(config->rxSampleClockPortB) |
+#endif
+#if defined(FSL_FEATURE_FLEXSPI_SUPPORT_RXCLKSRC_DIFF) && FSL_FEATURE_FLEXSPI_SUPPORT_RXCLKSRC_DIFF
+ FLEXSPI_MCR2_RX_CLK_SRC_DIFF(config->rxSampleClockDiff) |
+#endif
+#if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR2_SCKBDIFFOPT) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR2_SCKBDIFFOPT)
+ FLEXSPI_MCR2_SCKBDIFFOPT(config->enableSckBDiffOpt) |
+#endif
+ FLEXSPI_MCR2_SAMEDEVICEEN(config->enableSameConfigForAll) |
+ FLEXSPI_MCR2_CLRAHBBUFOPT(config->ahbConfig.enableClearAHBBufferOpt);
+
+ base->MCR2 = configValue;
+
+ /* Configure AHB control items. */
+ configValue = base->AHBCR;
+ configValue &= ~(FLEXSPI_AHBCR_READADDROPT_MASK | FLEXSPI_AHBCR_PREFETCHEN_MASK | FLEXSPI_AHBCR_BUFFERABLEEN_MASK |
+ FLEXSPI_AHBCR_CACHABLEEN_MASK);
+ configValue |= FLEXSPI_AHBCR_READADDROPT(config->ahbConfig.enableReadAddressOpt) |
+ FLEXSPI_AHBCR_PREFETCHEN(config->ahbConfig.enableAHBPrefetch) |
+ FLEXSPI_AHBCR_BUFFERABLEEN(config->ahbConfig.enableAHBBufferable) |
+ FLEXSPI_AHBCR_CACHABLEEN(config->ahbConfig.enableAHBCachable);
+ base->AHBCR = configValue;
+
+ /* Configure AHB rx buffers. */
+ for (i = 0; i < (uint32_t)FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT; i++)
+ {
+ configValue = base->AHBRXBUFCR0[i];
+
+ configValue &= ~(FLEXSPI_AHBRXBUFCR0_PREFETCHEN_MASK | FLEXSPI_AHBRXBUFCR0_PRIORITY_MASK |
+ FLEXSPI_AHBRXBUFCR0_MSTRID_MASK | FLEXSPI_AHBRXBUFCR0_BUFSZ_MASK);
+ configValue |= FLEXSPI_AHBRXBUFCR0_PREFETCHEN(config->ahbConfig.buffer[i].enablePrefetch) |
+ FLEXSPI_AHBRXBUFCR0_PRIORITY(config->ahbConfig.buffer[i].priority) |
+ FLEXSPI_AHBRXBUFCR0_MSTRID(config->ahbConfig.buffer[i].masterIndex) |
+ FLEXSPI_AHBRXBUFCR0_BUFSZ((uint32_t)config->ahbConfig.buffer[i].bufferSize / 8U);
+ base->AHBRXBUFCR0[i] = configValue;
+ }
+
+ /* Configure IP Fifo watermarks. */
+ base->IPRXFCR &= ~FLEXSPI_IPRXFCR_RXWMRK_MASK;
+ base->IPRXFCR |= FLEXSPI_IPRXFCR_RXWMRK((uint32_t)config->rxWatermark / 8U - 1U);
+ base->IPTXFCR &= ~FLEXSPI_IPTXFCR_TXWMRK_MASK;
+ base->IPTXFCR |= FLEXSPI_IPTXFCR_TXWMRK((uint32_t)config->txWatermark / 8U - 1U);
+
+ /* Reset flash size on all ports */
+ for (i = 0; i < (uint32_t)kFLEXSPI_PortCount; i++)
+ {
+ base->FLSHCR0[i] = 0;
+ }
+}
+
+/*!
+ * brief Gets default settings for FLEXSPI.
+ *
+ * param config FLEXSPI configuration structure.
+ */
+void FLEXSPI_GetDefaultConfig(flexspi_config_t *config)
+{
+ /* Initializes the configure structure to zero. */
+ FLEXSPI_Memset(config, 0, sizeof(*config));
+
+ config->rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackInternally;
+ config->enableSckFreeRunning = false;
+#if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN)
+ config->enableCombination = false;
+#endif
+ config->enableDoze = true;
+ config->enableHalfSpeedAccess = false;
+#if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR2_SCKBDIFFOPT) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR2_SCKBDIFFOPT)
+ config->enableSckBDiffOpt = false;
+#endif
+ config->enableSameConfigForAll = false;
+ config->seqTimeoutCycle = 0xFFFFU;
+ config->ipGrantTimeoutCycle = 0xFFU;
+ config->txWatermark = 8;
+ config->rxWatermark = 8;
+#if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ATDFEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ATDFEN)
+ config->ahbConfig.enableAHBWriteIpTxFifo = false;
+#endif
+#if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ARDFEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ARDFEN)
+ config->ahbConfig.enableAHBWriteIpRxFifo = false;
+#endif
+ config->ahbConfig.ahbGrantTimeoutCycle = 0xFFU;
+ config->ahbConfig.ahbBusTimeoutCycle = 0xFFFFU;
+ config->ahbConfig.resumeWaitCycle = 0x20U;
+ FLEXSPI_Memset(config->ahbConfig.buffer, 0, sizeof(config->ahbConfig.buffer));
+ /* Use invalid master ID 0xF and buffer size 0 for the first several buffers. */
+ for (uint8_t i = 0; i < ((uint8_t)FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT - 2U); i++)
+ {
+ config->ahbConfig.buffer[i].enablePrefetch = true; /* Default enable AHB prefetch. */
+ config->ahbConfig.buffer[i].masterIndex = 0xFU; /* Invalid master index which is not used, so will never hit. */
+ config->ahbConfig.buffer[i].bufferSize =
+ 0; /* Default buffer size 0 for buffer0 to buffer(FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT - 3U)*/
+ }
+
+ for (uint8_t i = ((uint8_t)FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT - 2U);
+ i < (uint8_t)FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT; i++)
+ {
+ config->ahbConfig.buffer[i].enablePrefetch = true; /* Default enable AHB prefetch. */
+ config->ahbConfig.buffer[i].bufferSize = 256U; /* Default buffer size 256 bytes. */
+ }
+ config->ahbConfig.enableClearAHBBufferOpt = false;
+ config->ahbConfig.enableReadAddressOpt = false;
+ config->ahbConfig.enableAHBPrefetch = false;
+ config->ahbConfig.enableAHBBufferable = false;
+ config->ahbConfig.enableAHBCachable = false;
+}
+
+/*!
+ * brief Deinitializes the FLEXSPI module.
+ *
+ * Clears the FLEXSPI state and FLEXSPI module registers.
+ * param base FLEXSPI peripheral base address.
+ */
+void FLEXSPI_Deinit(FLEXSPI_Type *base)
+{
+ /* Reset peripheral. */
+ FLEXSPI_SoftwareReset(base);
+}
+
+/*!
+ * brief Update FLEXSPI DLL value depending on currently flexspi root clock.
+ *
+ * param base FLEXSPI peripheral base address.
+ * param config Flash configuration parameters.
+ * param port FLEXSPI Operation port.
+ */
+void FLEXSPI_UpdateDllValue(FLEXSPI_Type *base, flexspi_device_config_t *config, flexspi_port_t port)
+{
+ uint32_t configValue = 0;
+ uint32_t statusValue = 0;
+ uint8_t index = (uint8_t)port >> 1U; /* PortA with index 0, PortB with index 1. */
+
+ /* Wait for bus to be idle before changing flash configuration. */
+ while (!FLEXSPI_GetBusIdleStatus(base))
+ {
+ }
+
+ /* Configure DLL. */
+ configValue = FLEXSPI_CalculateDll(base, config);
+ base->DLLCR[index] = configValue;
+
+ /* Exit stop mode. */
+ base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
+
+ /* According to ERR011377, need to delay at least 100 NOPs to ensure the DLL is locked. */
+ if (index == 0U)
+ {
+ statusValue =
+ ((uint32_t)kFLEXSPI_FlashASampleClockSlaveDelayLocked | (uint32_t)kFLEXSPI_FlashASampleClockRefDelayLocked);
+ }
+#if !((defined(FSL_FEATURE_FLEXSPI_HAS_NO_STS2_BSLVLOCK)) && (FSL_FEATURE_FLEXSPI_HAS_NO_STS2_BSLVLOCK))
+ else
+ {
+ statusValue =
+ ((uint32_t)kFLEXSPI_FlashBSampleClockSlaveDelayLocked | (uint32_t)kFLEXSPI_FlashBSampleClockRefDelayLocked);
+ }
+#endif
+ if (0U != (configValue & FLEXSPI_DLLCR_DLLEN_MASK))
+ {
+#if defined(FSL_FEATURE_FLEXSPI_HAS_ERRATA_051426) && (FSL_FEATURE_FLEXSPI_HAS_ERRATA_051426)
+ if (config->isFroClockSource == false)
+#endif
+ {
+ /* Wait slave delay line locked and slave reference delay line locked. */
+ while ((base->STS2 & statusValue) != statusValue)
+ {
+ }
+ }
+
+ /* Wait at least 100 NOPs*/
+ for (uint8_t delay = 100U; delay > 0U; delay--)
+ {
+ __NOP();
+ }
+ }
+}
+
+/*!
+ * brief Configures the connected device parameter.
+ *
+ * This function configures the connected device relevant parameters, such as the size, command, and so on.
+ * The flash configuration value cannot have a default value. The user needs to configure it according to the
+ * connected device.
+ *
+ * param base FLEXSPI peripheral base address.
+ * param config Flash configuration parameters.
+ * param port FLEXSPI Operation port.
+ */
+void FLEXSPI_SetFlashConfig(FLEXSPI_Type *base, flexspi_device_config_t *config, flexspi_port_t port)
+{
+ uint32_t configValue = 0;
+ uint8_t index = (uint8_t)port >> 1U; /* PortA with index 0, PortB with index 1. */
+
+ /* Wait for bus to be idle before changing flash configuration. */
+ while (!FLEXSPI_GetBusIdleStatus(base))
+ {
+ }
+
+ /* Configure flash size and address shift. */
+#if defined(FSL_FEATURE_FLEXSPI_SUPPORT_ADDRESS_SHIFT) && (FSL_FEATURE_FLEXSPI_SUPPORT_ADDRESS_SHIFT)
+ base->FLSHCR0[port] = config->flashSize | FLEXSPI_FLSHCR0_ADDRSHIFT(config->addressShift);
+#else
+ base->FLSHCR0[port] = config->flashSize;
+#endif /* FSL_FEATURE_FLEXSPI_SUPPORT_ADDRESS_SHIFT */
+
+ /* Configure flash parameters. */
+ base->FLSHCR1[port] = FLEXSPI_FLSHCR1_CSINTERVAL(config->CSInterval) |
+ FLEXSPI_FLSHCR1_CSINTERVALUNIT(config->CSIntervalUnit) |
+ FLEXSPI_FLSHCR1_TCSH(config->CSHoldTime) | FLEXSPI_FLSHCR1_TCSS(config->CSSetupTime) |
+ FLEXSPI_FLSHCR1_CAS(config->columnspace) | FLEXSPI_FLSHCR1_WA(config->enableWordAddress);
+
+ /* Configure AHB operation items. */
+ configValue = base->FLSHCR2[port];
+
+ configValue &= ~(FLEXSPI_FLSHCR2_AWRWAITUNIT_MASK | FLEXSPI_FLSHCR2_AWRWAIT_MASK | FLEXSPI_FLSHCR2_AWRSEQNUM_MASK |
+ FLEXSPI_FLSHCR2_AWRSEQID_MASK | FLEXSPI_FLSHCR2_ARDSEQNUM_MASK | FLEXSPI_FLSHCR2_ARDSEQID_MASK);
+
+ configValue |=
+ FLEXSPI_FLSHCR2_AWRWAITUNIT(config->AHBWriteWaitUnit) | FLEXSPI_FLSHCR2_AWRWAIT(config->AHBWriteWaitInterval);
+
+ if (config->AWRSeqNumber > 0U)
+ {
+ configValue |= FLEXSPI_FLSHCR2_AWRSEQID((uint32_t)config->AWRSeqIndex) |
+ FLEXSPI_FLSHCR2_AWRSEQNUM((uint32_t)config->AWRSeqNumber - 1U);
+ }
+
+ if (config->ARDSeqNumber > 0U)
+ {
+ configValue |= FLEXSPI_FLSHCR2_ARDSEQID((uint32_t)config->ARDSeqIndex) |
+ FLEXSPI_FLSHCR2_ARDSEQNUM((uint32_t)config->ARDSeqNumber - 1U);
+ }
+
+ base->FLSHCR2[port] = configValue;
+
+ /* Configure DLL. */
+ FLEXSPI_UpdateDllValue(base, config, port);
+
+ /* Step into stop mode. */
+ base->MCR0 |= FLEXSPI_MCR0_MDIS_MASK;
+
+ /* Configure write mask. */
+ if (config->enableWriteMask)
+ {
+ base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMOPT1_MASK;
+ }
+ else
+ {
+ base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMOPT1_MASK;
+ }
+
+ if (index == 0U) /*PortA*/
+ {
+ base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMENA_MASK;
+ base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMENA(config->enableWriteMask);
+ }
+#if !((defined(FSL_FEATURE_FLEXSPI_HAS_NO_FLSHCR4_WMENB)) && (FSL_FEATURE_FLEXSPI_HAS_NO_FLSHCR4_WMENB))
+ else
+ {
+ base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMENB_MASK;
+ base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMENB(config->enableWriteMask);
+ }
+#endif
+
+ /* Exit stop mode. */
+ base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
+
+ /* Wait for bus to be idle before use it access to external flash. */
+ while (!FLEXSPI_GetBusIdleStatus(base))
+ {
+ }
+}
+
+/*! brief Updates the LUT table.
+ *
+ * param base FLEXSPI peripheral base address.
+ * param index From which index start to update. It could be any index of the LUT table, which
+ * also allows user to update command content inside a command. Each command consists of up to
+ * 8 instructions and occupy 4*32-bit memory.
+ * param cmd Command sequence array.
+ * param count Number of sequences.
+ */
+void FLEXSPI_UpdateLUT(FLEXSPI_Type *base, uint32_t index, const uint32_t *cmd, uint32_t count)
+{
+ assert(index < 64U);
+
+ uint32_t i = 0;
+ volatile uint32_t *lutBase;
+
+ /* Wait for bus to be idle before changing flash configuration. */
+ while (!FLEXSPI_GetBusIdleStatus(base))
+ {
+ }
+
+ /* Unlock LUT for update. */
+#if !((defined(FSL_FEATURE_FLEXSPI_LUTKEY_IS_RO)) && (FSL_FEATURE_FLEXSPI_LUTKEY_IS_RO))
+ base->LUTKEY = FLEXSPI_LUT_KEY_VAL;
+#endif
+ base->LUTCR = 0x02;
+
+ lutBase = &base->LUT[index];
+ for (i = 0; i < count; i++)
+ {
+ *lutBase++ = *cmd++;
+ }
+
+ /* Lock LUT. */
+#if !((defined(FSL_FEATURE_FLEXSPI_LUTKEY_IS_RO)) && (FSL_FEATURE_FLEXSPI_LUTKEY_IS_RO))
+ base->LUTKEY = FLEXSPI_LUT_KEY_VAL;
+#endif
+ base->LUTCR = 0x01;
+}
+
+/*! brief Update read sample clock source
+ *
+ * param base FLEXSPI peripheral base address.
+ * param clockSource clockSource of type #flexspi_read_sample_clock_t
+ */
+void FLEXSPI_UpdateRxSampleClock(FLEXSPI_Type *base, flexspi_read_sample_clock_t clockSource)
+{
+ uint32_t mcr0Val;
+
+ /* Wait for bus to be idle before changing flash configuration. */
+ while (!FLEXSPI_GetBusIdleStatus(base))
+ {
+ }
+
+ mcr0Val = base->MCR0;
+ mcr0Val &= ~FLEXSPI_MCR0_RXCLKSRC_MASK;
+ mcr0Val |= FLEXSPI_MCR0_RXCLKSRC(clockSource);
+ base->MCR0 = mcr0Val;
+
+ /* Reset peripheral. */
+ FLEXSPI_SoftwareReset(base);
+}
+
+/*!
+ * brief Sends a buffer of data bytes using blocking method.
+ * note This function blocks via polling until all bytes have been sent.
+ * param base FLEXSPI peripheral base address
+ * param buffer The data bytes to send
+ * param size The number of data bytes to send
+ * retval kStatus_Success write success without error
+ * retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout
+ * retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequence error detected
+ * retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected
+ */
+status_t FLEXSPI_WriteBlocking(FLEXSPI_Type *base, uint8_t *buffer, size_t size)
+{
+ uint32_t txWatermark = ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXWMRK_MASK) >> FLEXSPI_IPTXFCR_TXWMRK_SHIFT) + 1U;
+ uint32_t status;
+ status_t result = kStatus_Success;
+ uint32_t i = 0;
+
+ /* Send data buffer */
+ while (0U != size)
+ {
+ /* Wait until there is room in the fifo. This also checks for errors. */
+ while (0U == ((status = base->INTR) & (uint32_t)kFLEXSPI_IpTxFifoWatermarkEmptyFlag))
+ {
+ }
+
+ result = FLEXSPI_CheckAndClearError(base, status);
+
+ if (kStatus_Success != result)
+ {
+ return result;
+ }
+
+ /* Write watermark level data into tx fifo . */
+ if (size >= 8U * txWatermark)
+ {
+ for (i = 0U; i < 2U * txWatermark; i++)
+ {
+ base->TFDR[i] = *(uint32_t *)(void *)buffer;
+ buffer += 4U;
+ }
+
+ size = size - 8U * txWatermark;
+ }
+ else
+ {
+ /* Write word aligned data into tx fifo. */
+ for (i = 0U; i < (size / 4U); i++)
+ {
+ base->TFDR[i] = *(uint32_t *)(void *)buffer;
+ buffer += 4U;
+ }
+
+ /* Adjust size by the amount processed. */
+ size -= 4U * i;
+
+ /* Write word un-aligned data into tx fifo. */
+ if (0x00U != size)
+ {
+ uint32_t tempVal = 0x00U;
+
+ for (uint32_t j = 0U; j < size; j++)
+ {
+ tempVal |= ((uint32_t)*buffer++ << (8U * j));
+ }
+
+ base->TFDR[i] = tempVal;
+ }
+
+ size = 0U;
+ }
+
+ /* Push a watermark level data into IP TX FIFO. */
+ base->INTR |= (uint32_t)kFLEXSPI_IpTxFifoWatermarkEmptyFlag;
+ }
+
+ return result;
+}
+
+/*!
+ * brief Receives a buffer of data bytes using a blocking method.
+ * note This function blocks via polling until all bytes have been sent.
+ * param base FLEXSPI peripheral base address
+ * param buffer The data bytes to send
+ * param size The number of data bytes to receive
+ * retval kStatus_Success read success without error
+ * retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout
+ * retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequence error detected
+ * retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected
+ */
+status_t FLEXSPI_ReadBlocking(FLEXSPI_Type *base, uint8_t *buffer, size_t size)
+{
+ uint32_t rxWatermark = ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXWMRK_MASK) >> FLEXSPI_IPRXFCR_RXWMRK_SHIFT) + 1U;
+ uint32_t status;
+ status_t result = kStatus_Success;
+ uint32_t i = 0;
+ bool isReturn = false;
+
+ /* Send data buffer */
+ while (0U != size)
+ {
+ if (size >= 8U * rxWatermark)
+ {
+ /* Wait until there is room in the fifo. This also checks for errors. */
+ while (0U == ((status = base->INTR) & (uint32_t)kFLEXSPI_IpRxFifoWatermarkAvailableFlag))
+ {
+ result = FLEXSPI_CheckAndClearError(base, status);
+
+ if (kStatus_Success != result)
+ {
+ isReturn = true;
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* Wait fill level. This also checks for errors. */
+ while (size > ((((base->IPRXFSTS) & FLEXSPI_IPRXFSTS_FILL_MASK) >> FLEXSPI_IPRXFSTS_FILL_SHIFT) * 8U))
+ {
+ result = FLEXSPI_CheckAndClearError(base, base->INTR);
+
+ if (kStatus_Success != result)
+ {
+ isReturn = true;
+ break;
+ }
+ }
+ }
+
+ if (isReturn)
+ {
+ break;
+ }
+
+ result = FLEXSPI_CheckAndClearError(base, base->INTR);
+
+ if (kStatus_Success != result)
+ {
+ break;
+ }
+
+ /* Read watermark level data from rx fifo. */
+ if (size >= 8U * rxWatermark)
+ {
+ for (i = 0U; i < 2U * rxWatermark; i++)
+ {
+ *(uint32_t *)(void *)buffer = base->RFDR[i];
+ buffer += 4U;
+ }
+
+ size = size - 8U * rxWatermark;
+ }
+ else
+ {
+ /* Read word aligned data from rx fifo. */
+ for (i = 0U; i < (size / 4U); i++)
+ {
+ *(uint32_t *)(void *)buffer = base->RFDR[i];
+ buffer += 4U;
+ }
+
+ /* Adjust size by the amount processed. */
+ size -= 4U * i;
+
+ /* Read word un-aligned data from rx fifo. */
+ if (0x00U != size)
+ {
+ uint32_t tempVal = base->RFDR[i];
+
+ for (i = 0U; i < size; i++)
+ {
+ *buffer++ = ((uint8_t)(tempVal >> (8U * i)) & 0xFFU);
+ }
+ }
+
+ size = 0;
+ }
+
+ /* Pop out a watermark level datas from IP RX FIFO. */
+ base->INTR |= (uint32_t)kFLEXSPI_IpRxFifoWatermarkAvailableFlag;
+ }
+
+ return result;
+}
+
+/*!
+ * brief Execute command to transfer a buffer data bytes using a blocking method.
+ * param base FLEXSPI peripheral base address
+ * param xfer pointer to the transfer structure.
+ * retval kStatus_Success command transfer success without error
+ * retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout
+ * retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequence error detected
+ * retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected
+ */
+status_t FLEXSPI_TransferBlocking(FLEXSPI_Type *base, flexspi_transfer_t *xfer)
+{
+ uint32_t configValue = 0;
+ status_t result = kStatus_Success;
+
+ /* Clear sequence pointer before sending data to external devices. */
+ base->FLSHCR2[xfer->port] |= FLEXSPI_FLSHCR2_CLRINSTRPTR_MASK;
+
+ /* Clear former pending status before start this transfer. */
+ base->INTR |= FLEXSPI_INTR_AHBCMDERR_MASK | FLEXSPI_INTR_IPCMDERR_MASK | FLEXSPI_INTR_AHBCMDGE_MASK |
+ FLEXSPI_INTR_IPCMDGE_MASK;
+
+ /* Configure base address. */
+ base->IPCR0 = xfer->deviceAddress;
+
+ /* Reset fifos. */
+ base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
+ base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
+
+ /* Configure data size. */
+ if ((xfer->cmdType == kFLEXSPI_Read) || (xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config))
+ {
+ configValue = FLEXSPI_IPCR1_IDATSZ(xfer->dataSize);
+ }
+
+ /* Configure sequence ID. */
+ configValue |=
+ FLEXSPI_IPCR1_ISEQID((uint32_t)xfer->seqIndex) | FLEXSPI_IPCR1_ISEQNUM((uint32_t)xfer->SeqNumber - 1U);
+ base->IPCR1 = configValue;
+
+ /* Start Transfer. */
+ base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
+
+ if ((xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config))
+ {
+ result = FLEXSPI_WriteBlocking(base, (uint8_t *)xfer->data, xfer->dataSize);
+ }
+ else if (xfer->cmdType == kFLEXSPI_Read)
+ {
+ result = FLEXSPI_ReadBlocking(base, (uint8_t *)xfer->data, xfer->dataSize);
+ }
+ else
+ {
+ /* Empty else. */
+ }
+
+ /* Wait for bus to be idle before changing flash configuration. */
+ while (!FLEXSPI_GetBusIdleStatus(base))
+ {
+ }
+
+ if (xfer->cmdType == kFLEXSPI_Command)
+ {
+ result = FLEXSPI_CheckAndClearError(base, base->INTR);
+ }
+
+ return result;
+}
+
+/*!
+ * brief Initializes the FLEXSPI handle which is used in transactional functions.
+ *
+ * param base FLEXSPI peripheral base address.
+ * param handle pointer to flexspi_handle_t structure to store the transfer state.
+ * param callback pointer to user callback function.
+ * param userData user parameter passed to the callback function.
+ */
+void FLEXSPI_TransferCreateHandle(FLEXSPI_Type *base,
+ flexspi_handle_t *handle,
+ flexspi_transfer_callback_t callback,
+ void *userData)
+{
+ assert(NULL != handle);
+
+ uint32_t instance = FLEXSPI_GetInstance(base);
+
+ /* Zero handle. */
+ (void)memset(handle, 0, sizeof(*handle));
+
+ /* Set callback and userData. */
+ handle->completionCallback = callback;
+ handle->userData = userData;
+
+#if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
+ /* Save the context in global variables to support the double weak mechanism. */
+ s_flexspiHandle[instance] = handle;
+ s_flexspiIsr = FLEXSPI_TransferHandleIRQ;
+#endif
+
+ /* Enable NVIC interrupt. */
+ (void)EnableIRQ(s_flexspiIrqs[instance]);
+}
+
+/*!
+ * brief Performs a interrupt non-blocking transfer on the FLEXSPI bus.
+ *
+ * note Calling the API returns immediately after transfer initiates. The user needs
+ * to call FLEXSPI_GetTransferCount to poll the transfer status to check whether
+ * the transfer is finished. If the return status is not kStatus_FLEXSPI_Busy, the transfer
+ * is finished. For FLEXSPI_Read, the dataSize should be multiple of rx watermark level, or
+ * FLEXSPI could not read data properly.
+ *
+ * param base FLEXSPI peripheral base address.
+ * param handle pointer to flexspi_handle_t structure which stores the transfer state.
+ * param xfer pointer to flexspi_transfer_t structure.
+ * retval kStatus_Success Successfully start the data transmission.
+ * retval kStatus_FLEXSPI_Busy Previous transmission still not finished.
+ */
+status_t FLEXSPI_TransferNonBlocking(FLEXSPI_Type *base, flexspi_handle_t *handle, flexspi_transfer_t *xfer)
+{
+ uint32_t configValue = 0;
+ status_t result = kStatus_Success;
+
+ assert(NULL != handle);
+ assert(NULL != xfer);
+
+ /* Check if the I2C bus is idle - if not return busy status. */
+ if (handle->state != (uint32_t)kFLEXSPI_Idle)
+ {
+ result = kStatus_FLEXSPI_Busy;
+ }
+ else
+ {
+ handle->data = (uint8_t *)xfer->data;
+ handle->dataSize = xfer->dataSize;
+ handle->transferTotalSize = xfer->dataSize;
+ handle->state = (xfer->cmdType == kFLEXSPI_Read) ? (uint32_t)kFLEXSPI_BusyRead : (uint32_t)kFLEXSPI_BusyWrite;
+
+ /* Clear sequence pointer before sending data to external devices. */
+ base->FLSHCR2[xfer->port] |= FLEXSPI_FLSHCR2_CLRINSTRPTR_MASK;
+
+ /* Clear former pending status before start this transfer. */
+ base->INTR |= FLEXSPI_INTR_AHBCMDERR_MASK | FLEXSPI_INTR_IPCMDERR_MASK | FLEXSPI_INTR_AHBCMDGE_MASK |
+ FLEXSPI_INTR_IPCMDGE_MASK;
+
+ /* Configure base address. */
+ base->IPCR0 = xfer->deviceAddress;
+
+ /* Reset fifos. */
+ base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
+ base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
+
+ /* Configure data size. */
+ if ((xfer->cmdType == kFLEXSPI_Read) || (xfer->cmdType == kFLEXSPI_Write))
+ {
+ configValue = FLEXSPI_IPCR1_IDATSZ(xfer->dataSize);
+ }
+
+ /* Configure sequence ID. */
+ configValue |=
+ FLEXSPI_IPCR1_ISEQID((uint32_t)xfer->seqIndex) | FLEXSPI_IPCR1_ISEQNUM((uint32_t)xfer->SeqNumber - 1U);
+ base->IPCR1 = configValue;
+
+ /* Start Transfer. */
+ base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
+
+ if (handle->state == (uint32_t)kFLEXSPI_BusyRead)
+ {
+ FLEXSPI_EnableInterrupts(base, (uint32_t)kFLEXSPI_IpRxFifoWatermarkAvailableFlag |
+ (uint32_t)kFLEXSPI_SequenceExecutionTimeoutFlag |
+ (uint32_t)kFLEXSPI_IpCommandSequenceErrorFlag |
+ (uint32_t)kFLEXSPI_IpCommandGrantTimeoutFlag |
+ (uint32_t)kFLEXSPI_IpCommandExecutionDoneFlag);
+ }
+ else
+ {
+ FLEXSPI_EnableInterrupts(
+ base, (uint32_t)kFLEXSPI_IpTxFifoWatermarkEmptyFlag | (uint32_t)kFLEXSPI_SequenceExecutionTimeoutFlag |
+ (uint32_t)kFLEXSPI_IpCommandSequenceErrorFlag | (uint32_t)kFLEXSPI_IpCommandGrantTimeoutFlag |
+ (uint32_t)kFLEXSPI_IpCommandExecutionDoneFlag);
+ }
+ }
+
+ return result;
+}
+
+/*!
+ * brief Gets the master transfer status during a interrupt non-blocking transfer.
+ *
+ * param base FLEXSPI peripheral base address.
+ * param handle pointer to flexspi_handle_t structure which stores the transfer state.
+ * param count Number of bytes transferred so far by the non-blocking transaction.
+ * retval kStatus_InvalidArgument count is Invalid.
+ * retval kStatus_Success Successfully return the count.
+ */
+status_t FLEXSPI_TransferGetCount(FLEXSPI_Type *base, flexspi_handle_t *handle, size_t *count)
+{
+ assert(NULL != handle);
+
+ status_t result = kStatus_Success;
+
+ if (handle->state == (uint32_t)kFLEXSPI_Idle)
+ {
+ result = kStatus_NoTransferInProgress;
+ }
+ else
+ {
+ *count = handle->transferTotalSize - handle->dataSize;
+ }
+
+ return result;
+}
+
+/*!
+ * brief Aborts an interrupt non-blocking transfer early.
+ *
+ * note This API can be called at any time when an interrupt non-blocking transfer initiates
+ * to abort the transfer early.
+ *
+ * param base FLEXSPI peripheral base address.
+ * param handle pointer to flexspi_handle_t structure which stores the transfer state
+ */
+void FLEXSPI_TransferAbort(FLEXSPI_Type *base, flexspi_handle_t *handle)
+{
+ assert(NULL != handle);
+
+ FLEXSPI_DisableInterrupts(base, (uint32_t)kIrqFlags);
+ handle->state = (uint32_t)kFLEXSPI_Idle;
+}
+
+/*!
+ * brief Master interrupt handler.
+ *
+ * param base FLEXSPI peripheral base address.
+ * param handle pointer to flexspi_handle_t structure.
+ */
+void FLEXSPI_TransferHandleIRQ(FLEXSPI_Type *base, flexspi_handle_t *handle)
+{
+ uint32_t status;
+ status_t result;
+ uint32_t intEnableStatus;
+ uint32_t txWatermark;
+ uint32_t rxWatermark;
+ uint32_t i = 0;
+
+ status = base->INTR;
+ intEnableStatus = base->INTEN;
+
+ /* Check if interrupt is enabled and status is alerted. */
+ if ((status & intEnableStatus) != 0U)
+ {
+ result = FLEXSPI_CheckAndClearError(base, status);
+
+ if ((result != kStatus_Success) && (handle->completionCallback != NULL))
+ {
+ FLEXSPI_TransferAbort(base, handle);
+ if (NULL != handle->completionCallback)
+ {
+ handle->completionCallback(base, handle, result, handle->userData);
+ }
+ }
+ else
+ {
+ if ((0U != (status & (uint32_t)kFLEXSPI_IpRxFifoWatermarkAvailableFlag)) &&
+ (handle->state == (uint32_t)kFLEXSPI_BusyRead))
+ {
+ rxWatermark = ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXWMRK_MASK) >> FLEXSPI_IPRXFCR_RXWMRK_SHIFT) + 1U;
+
+ /* Read watermark level data from rx fifo . */
+ if (handle->dataSize >= 8U * rxWatermark)
+ {
+ /* Read watermark level data from rx fifo . */
+ for (i = 0U; i < 2U * rxWatermark; i++)
+ {
+ *(uint32_t *)(void *)handle->data = base->RFDR[i];
+ handle->data += 4U;
+ }
+
+ handle->dataSize = handle->dataSize - 8U * rxWatermark;
+ }
+ else
+ {
+ /* Read word aligned data from rx fifo. */
+ for (i = 0U; i < (handle->dataSize / 4U); i++)
+ {
+ *(uint32_t *)(void *)handle->data = base->RFDR[i];
+ handle->data += 4U;
+ }
+
+ /* Adjust size by the amount processed. */
+ handle->dataSize -= 4U * i;
+
+ /* Read word un-aligned data from rx fifo. */
+ if (0x00U != handle->dataSize)
+ {
+ uint32_t tempVal = base->RFDR[i];
+
+ for (i = 0U; i < handle->dataSize; i++)
+ {
+ *handle->data++ = ((uint8_t)(tempVal >> (8U * i)) & 0xFFU);
+ }
+ }
+
+ handle->dataSize = 0;
+ }
+ /* Pop out a watermark level data from IP RX FIFO. */
+ base->INTR |= (uint32_t)kFLEXSPI_IpRxFifoWatermarkAvailableFlag;
+ }
+
+ if (0U != (status & (uint32_t)kFLEXSPI_IpCommandExecutionDoneFlag))
+ {
+ base->INTR |= (uint32_t)kFLEXSPI_IpCommandExecutionDoneFlag;
+
+ FLEXSPI_TransferAbort(base, handle);
+
+ if (NULL != handle->completionCallback)
+ {
+ handle->completionCallback(base, handle, kStatus_Success, handle->userData);
+ }
+ }
+
+ /* TX FIFO empty interrupt, push watermark level data into tx FIFO. */
+ if ((0U != (status & (uint32_t)kFLEXSPI_IpTxFifoWatermarkEmptyFlag)) &&
+ (handle->state == (uint32_t)kFLEXSPI_BusyWrite))
+ {
+ if (0U != handle->dataSize)
+ {
+ txWatermark = ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXWMRK_MASK) >> FLEXSPI_IPTXFCR_TXWMRK_SHIFT) + 1U;
+ /* Write watermark level data into tx fifo . */
+ if (handle->dataSize >= 8U * txWatermark)
+ {
+ for (i = 0; i < 2U * txWatermark; i++)
+ {
+ base->TFDR[i] = *(uint32_t *)(void *)handle->data;
+ handle->data += 4U;
+ }
+
+ handle->dataSize = handle->dataSize - 8U * txWatermark;
+ }
+ else
+ {
+ /* Write word aligned data into tx fifo. */
+ for (i = 0U; i < (handle->dataSize / 4U); i++)
+ {
+ base->TFDR[i] = *(uint32_t *)(void *)handle->data;
+ handle->data += 4U;
+ }
+
+ /* Adjust size by the amount processed. */
+ handle->dataSize -= 4U * i;
+
+ /* Write word un-aligned data into tx fifo. */
+ if (0x00U != handle->dataSize)
+ {
+ uint32_t tempVal = 0x00U;
+
+ for (uint32_t j = 0U; j < handle->dataSize; j++)
+ {
+ tempVal |= ((uint32_t)*handle->data++ << (8U * j));
+ }
+
+ base->TFDR[i] = tempVal;
+ }
+
+ handle->dataSize = 0;
+ }
+
+ /* Push a watermark level data into IP TX FIFO. */
+ base->INTR |= (uint32_t)kFLEXSPI_IpTxFifoWatermarkEmptyFlag;
+ }
+ }
+ else
+ {
+ /* Empty else */
+ }
+ }
+ }
+ else
+ {
+ /* Empty else */
+ }
+}
+
+#if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
+#if defined(FLEXSPI)
+void FLEXSPI_DriverIRQHandler(void);
+void FLEXSPI_DriverIRQHandler(void)
+{
+ s_flexspiIsr(FLEXSPI, s_flexspiHandle[0]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
+
+#if defined(FLEXSPI0)
+void FLEXSPI0_DriverIRQHandler(void);
+void FLEXSPI0_DriverIRQHandler(void)
+{
+ s_flexspiIsr(FLEXSPI0, s_flexspiHandle[0]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
+#if defined(FLEXSPI1)
+void FLEXSPI1_DriverIRQHandler(void);
+void FLEXSPI1_DriverIRQHandler(void)
+{
+ s_flexspiIsr(FLEXSPI1, s_flexspiHandle[1]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
+
+#if defined(LSIO__FLEXSPI0)
+void LSIO_OCTASPI0_INT_DriverIRQHandler(void);
+void LSIO_OCTASPI0_INT_DriverIRQHandler(void)
+{
+ s_flexspiIsr(LSIO__FLEXSPI0, s_flexspiHandle[0]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
+#if defined(LSIO__FLEXSPI1)
+void LSIO_OCTASPI1_INT_DriverIRQHandler(void);
+void LSIO_OCTASPI1_INT_DriverIRQHandler(void)
+{
+ s_flexspiIsr(LSIO__FLEXSPI1, s_flexspiHandle[1]);
+ SDK_ISR_EXIT_BARRIER;
+}
+#endif
+
+#if defined(FSL_FEATURE_FLEXSPI_HAS_SHARED_IRQ0_IRQ1) && FSL_FEATURE_FLEXSPI_HAS_SHARED_IRQ0_IRQ1
+
+void FLEXSPI0_FLEXSPI1_DriverIRQHandler(void);
+void FLEXSPI0_FLEXSPI1_DriverIRQHandler(void)
+{
+ /* If handle is registered, treat the transfer function is enabled. */
+ if (NULL != s_flexspiHandle[0])
+ {
+ s_flexspiIsr(FLEXSPI0, s_flexspiHandle[0]);
+ }
+ if (NULL != s_flexspiHandle[1])
+ {
+ s_flexspiIsr(FLEXSPI1, s_flexspiHandle[1]);
+ }
+}
+#endif
+
+#endif
diff --git a/bsps/arm/imxrt/mcux-sdk/drivers/flexspi/fsl_flexspi.h b/bsps/arm/imxrt/mcux-sdk/drivers/flexspi/fsl_flexspi.h
new file mode 100644
index 0000000000..935d92dd71
--- /dev/null
+++ b/bsps/arm/imxrt/mcux-sdk/drivers/flexspi/fsl_flexspi.h
@@ -0,0 +1,886 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2022 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __FSL_FLEXSPI_H_
+#define __FSL_FLEXSPI_H_
+
+#include <stddef.h>
+#include "fsl_device_registers.h"
+#include "fsl_common.h"
+
+/*!
+ * @addtogroup flexspi
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @name Driver version */
+/*@{*/
+/*! @brief FLEXSPI driver version. */
+#define FSL_FLEXSPI_DRIVER_VERSION (MAKE_VERSION(2, 5, 0))
+/*@}*/
+
+#define FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNTn(0)
+
+/*! @brief Formula to form FLEXSPI instructions in LUT table. */
+#define FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1) \
+ (FLEXSPI_LUT_OPERAND0(op0) | FLEXSPI_LUT_NUM_PADS0(pad0) | FLEXSPI_LUT_OPCODE0(cmd0) | FLEXSPI_LUT_OPERAND1(op1) | \
+ FLEXSPI_LUT_NUM_PADS1(pad1) | FLEXSPI_LUT_OPCODE1(cmd1))
+
+/*! @brief Status structure of FLEXSPI.*/
+enum
+{
+ kStatus_FLEXSPI_Busy = MAKE_STATUS(kStatusGroup_FLEXSPI, 0), /*!< FLEXSPI is busy */
+ kStatus_FLEXSPI_SequenceExecutionTimeout = MAKE_STATUS(kStatusGroup_FLEXSPI, 1), /*!< Sequence execution timeout
+ error occurred during FLEXSPI transfer. */
+ kStatus_FLEXSPI_IpCommandSequenceError = MAKE_STATUS(kStatusGroup_FLEXSPI, 2), /*!< IP command Sequence execution
+ timeout error occurred during FLEXSPI transfer. */
+ kStatus_FLEXSPI_IpCommandGrantTimeout = MAKE_STATUS(kStatusGroup_FLEXSPI, 3), /*!< IP command grant timeout error
+ occurred during FLEXSPI transfer. */
+};
+
+/*! @brief CMD definition of FLEXSPI, use to form LUT instruction, _flexspi_command. */
+enum
+{
+ kFLEXSPI_Command_STOP = 0x00U, /*!< Stop execution, deassert CS. */
+ kFLEXSPI_Command_SDR = 0x01U, /*!< Transmit Command code to Flash, using SDR mode. */
+ kFLEXSPI_Command_RADDR_SDR = 0x02U, /*!< Transmit Row Address to Flash, using SDR mode. */
+ kFLEXSPI_Command_CADDR_SDR = 0x03U, /*!< Transmit Column Address to Flash, using SDR mode. */
+ kFLEXSPI_Command_MODE1_SDR = 0x04U, /*!< Transmit 1-bit Mode bits to Flash, using SDR mode. */
+ kFLEXSPI_Command_MODE2_SDR = 0x05U, /*!< Transmit 2-bit Mode bits to Flash, using SDR mode. */
+ kFLEXSPI_Command_MODE4_SDR = 0x06U, /*!< Transmit 4-bit Mode bits to Flash, using SDR mode. */
+ kFLEXSPI_Command_MODE8_SDR = 0x07U, /*!< Transmit 8-bit Mode bits to Flash, using SDR mode. */
+ kFLEXSPI_Command_WRITE_SDR = 0x08U, /*!< Transmit Programming Data to Flash, using SDR mode. */
+ kFLEXSPI_Command_READ_SDR = 0x09U, /*!< Receive Read Data from Flash, using SDR mode. */
+ kFLEXSPI_Command_LEARN_SDR = 0x0AU, /*!< Receive Read Data or Preamble bit from Flash, SDR mode. */
+ kFLEXSPI_Command_DATSZ_SDR = 0x0BU, /*!< Transmit Read/Program Data size (byte) to Flash, SDR mode. */
+ kFLEXSPI_Command_DUMMY_SDR = 0x0CU, /*!< Leave data lines undriven by FlexSPI controller.*/
+ kFLEXSPI_Command_DUMMY_RWDS_SDR = 0x0DU, /*!< Leave data lines undriven by FlexSPI controller,
+ dummy cycles decided by RWDS. */
+ kFLEXSPI_Command_DDR = 0x21U, /*!< Transmit Command code to Flash, using DDR mode. */
+ kFLEXSPI_Command_RADDR_DDR = 0x22U, /*!< Transmit Row Address to Flash, using DDR mode. */
+ kFLEXSPI_Command_CADDR_DDR = 0x23U, /*!< Transmit Column Address to Flash, using DDR mode. */
+ kFLEXSPI_Command_MODE1_DDR = 0x24U, /*!< Transmit 1-bit Mode bits to Flash, using DDR mode. */
+ kFLEXSPI_Command_MODE2_DDR = 0x25U, /*!< Transmit 2-bit Mode bits to Flash, using DDR mode. */
+ kFLEXSPI_Command_MODE4_DDR = 0x26U, /*!< Transmit 4-bit Mode bits to Flash, using DDR mode. */
+ kFLEXSPI_Command_MODE8_DDR = 0x27U, /*!< Transmit 8-bit Mode bits to Flash, using DDR mode. */
+ kFLEXSPI_Command_WRITE_DDR = 0x28U, /*!< Transmit Programming Data to Flash, using DDR mode. */
+ kFLEXSPI_Command_READ_DDR = 0x29U, /*!< Receive Read Data from Flash, using DDR mode. */
+ kFLEXSPI_Command_LEARN_DDR = 0x2AU, /*!< Receive Read Data or Preamble bit from Flash, DDR mode. */
+ kFLEXSPI_Command_DATSZ_DDR = 0x2BU, /*!< Transmit Read/Program Data size (byte) to Flash, DDR mode. */
+ kFLEXSPI_Command_DUMMY_DDR = 0x2CU, /*!< Leave data lines undriven by FlexSPI controller.*/
+ kFLEXSPI_Command_DUMMY_RWDS_DDR = 0x2DU, /*!< Leave data lines undriven by FlexSPI controller,
+ dummy cycles decided by RWDS. */
+ kFLEXSPI_Command_JUMP_ON_CS = 0x1FU, /*!< Stop execution, deassert CS and save operand[7:0] as the
+ instruction start pointer for next sequence */
+};
+
+/*! @brief pad definition of FLEXSPI, use to form LUT instruction. */
+typedef enum _flexspi_pad
+{
+ kFLEXSPI_1PAD = 0x00U, /*!< Transmit command/address and transmit/receive data only through DATA0/DATA1. */
+ kFLEXSPI_2PAD = 0x01U, /*!< Transmit command/address and transmit/receive data only through DATA[1:0]. */
+ kFLEXSPI_4PAD = 0x02U, /*!< Transmit command/address and transmit/receive data only through DATA[3:0]. */
+ kFLEXSPI_8PAD = 0x03U, /*!< Transmit command/address and transmit/receive data only through DATA[7:0]. */
+} flexspi_pad_t;
+
+/*! @brief FLEXSPI interrupt status flags.*/
+typedef enum _flexspi_flags
+{
+ kFLEXSPI_SequenceExecutionTimeoutFlag = FLEXSPI_INTEN_SEQTIMEOUTEN_MASK, /*!< Sequence execution timeout. */
+#if defined(FSL_FEATURE_FLEXSPI_HAS_INTEN_AHBBUSERROREN) && FSL_FEATURE_FLEXSPI_HAS_INTEN_AHBBUSERROREN
+ kFLEXSPI_AhbBusErrorFlag = FLEXSPI_INTEN_AHBBUSERROREN_MASK, /*!< AHB Bus error flag. */
+#else
+ kFLEXSPI_AhbBusTimeoutFlag = FLEXSPI_INTEN_AHBBUSTIMEOUTEN_MASK, /*!< AHB Bus timeout. */
+#endif
+ kFLEXSPI_SckStoppedBecauseTxEmptyFlag =
+ FLEXSPI_INTEN_SCKSTOPBYWREN_MASK, /*!< SCK is stopped during command
+ sequence because Async TX FIFO empty. */
+ kFLEXSPI_SckStoppedBecauseRxFullFlag =
+ FLEXSPI_INTEN_SCKSTOPBYRDEN_MASK, /*!< SCK is stopped during command
+ sequence because Async RX FIFO full. */
+#if !((defined(FSL_FEATURE_FLEXSPI_HAS_NO_DATA_LEARN)) && (FSL_FEATURE_FLEXSPI_HAS_NO_DATA_LEARN))
+ kFLEXSPI_DataLearningFailedFlag = FLEXSPI_INTEN_DATALEARNFAILEN_MASK, /*!< Data learning failed. */
+#endif
+ kFLEXSPI_IpTxFifoWatermarkEmptyFlag = FLEXSPI_INTEN_IPTXWEEN_MASK, /*!< IP TX FIFO WaterMark empty. */
+ kFLEXSPI_IpRxFifoWatermarkAvailableFlag = FLEXSPI_INTEN_IPRXWAEN_MASK, /*!< IP RX FIFO WaterMark available. */
+ kFLEXSPI_AhbCommandSequenceErrorFlag =
+ FLEXSPI_INTEN_AHBCMDERREN_MASK, /*!< AHB triggered Command Sequences Error. */
+ kFLEXSPI_IpCommandSequenceErrorFlag = FLEXSPI_INTEN_IPCMDERREN_MASK, /*!< IP triggered Command Sequences Error. */
+ kFLEXSPI_AhbCommandGrantTimeoutFlag =
+ FLEXSPI_INTEN_AHBCMDGEEN_MASK, /*!< AHB triggered Command Sequences Grant Timeout. */
+ kFLEXSPI_IpCommandGrantTimeoutFlag =
+ FLEXSPI_INTEN_IPCMDGEEN_MASK, /*!< IP triggered Command Sequences Grant Timeout. */
+ kFLEXSPI_IpCommandExecutionDoneFlag =
+ FLEXSPI_INTEN_IPCMDDONEEN_MASK, /*!< IP triggered Command Sequences Execution finished. */
+ kFLEXSPI_AllInterruptFlags = 0xFFFU, /*!< All flags. */
+} flexspi_flags_t;
+
+/*! @brief FLEXSPI sample clock source selection for Flash Reading.*/
+typedef enum _flexspi_read_sample_clock
+{
+ kFLEXSPI_ReadSampleClkLoopbackInternally = 0x0U, /*!< Dummy Read strobe generated by FlexSPI Controller
+ and loopback internally. */
+ kFLEXSPI_ReadSampleClkLoopbackFromDqsPad = 0x1U, /*!< Dummy Read strobe generated by FlexSPI Controller
+ and loopback from DQS pad. */
+ kFLEXSPI_ReadSampleClkLoopbackFromSckPad = 0x2U, /*!< SCK output clock and loopback from SCK pad. */
+ kFLEXSPI_ReadSampleClkExternalInputFromDqsPad = 0x3U, /*!< Flash provided Read strobe and input from DQS pad. */
+} flexspi_read_sample_clock_t;
+
+/*! @brief FLEXSPI interval unit for flash device select.*/
+typedef enum _flexspi_cs_interval_cycle_unit
+{
+ kFLEXSPI_CsIntervalUnit1SckCycle = 0x0U, /*!< Chip selection interval: CSINTERVAL * 1 serial clock cycle. */
+ kFLEXSPI_CsIntervalUnit256SckCycle = 0x1U, /*!< Chip selection interval: CSINTERVAL * 256 serial clock cycle. */
+} flexspi_cs_interval_cycle_unit_t;
+
+/*! @brief FLEXSPI AHB wait interval unit for writing.*/
+typedef enum _flexspi_ahb_write_wait_unit
+{
+ kFLEXSPI_AhbWriteWaitUnit2AhbCycle = 0x0U, /*!< AWRWAIT unit is 2 ahb clock cycle. */
+ kFLEXSPI_AhbWriteWaitUnit8AhbCycle = 0x1U, /*!< AWRWAIT unit is 8 ahb clock cycle. */
+ kFLEXSPI_AhbWriteWaitUnit32AhbCycle = 0x2U, /*!< AWRWAIT unit is 32 ahb clock cycle. */
+ kFLEXSPI_AhbWriteWaitUnit128AhbCycle = 0x3U, /*!< AWRWAIT unit is 128 ahb clock cycle. */
+ kFLEXSPI_AhbWriteWaitUnit512AhbCycle = 0x4U, /*!< AWRWAIT unit is 512 ahb clock cycle. */
+ kFLEXSPI_AhbWriteWaitUnit2048AhbCycle = 0x5U, /*!< AWRWAIT unit is 2048 ahb clock cycle. */
+ kFLEXSPI_AhbWriteWaitUnit8192AhbCycle = 0x6U, /*!< AWRWAIT unit is 8192 ahb clock cycle. */
+ kFLEXSPI_AhbWriteWaitUnit32768AhbCycle = 0x7U, /*!< AWRWAIT unit is 32768 ahb clock cycle. */
+} flexspi_ahb_write_wait_unit_t;
+
+/*! @brief Error Code when IP command Error detected.*/
+typedef enum _flexspi_ip_error_code
+{
+ kFLEXSPI_IpCmdErrorNoError = 0x0U, /*!< No error. */
+ kFLEXSPI_IpCmdErrorJumpOnCsInIpCmd = 0x2U, /*!< IP command with JMP_ON_CS instruction used. */
+ kFLEXSPI_IpCmdErrorUnknownOpCode = 0x3U, /*!< Unknown instruction opcode in the sequence. */
+ kFLEXSPI_IpCmdErrorSdrDummyInDdrSequence = 0x4U, /*!< Instruction DUMMY_SDR/DUMMY_RWDS_SDR
+ used in DDR sequence. */
+ kFLEXSPI_IpCmdErrorDdrDummyInSdrSequence = 0x5U, /*!< Instruction DUMMY_DDR/DUMMY_RWDS_DDR
+ used in SDR sequence. */
+ kFLEXSPI_IpCmdErrorInvalidAddress = 0x6U, /*!< Flash access start address exceed the whole
+ flash address range (A1/A2/B1/B2). */
+ kFLEXSPI_IpCmdErrorSequenceExecutionTimeout = 0xEU, /*!< Sequence execution timeout. */
+ kFLEXSPI_IpCmdErrorFlashBoundaryAcrosss = 0xFU, /*!< Flash boundary crossed. */
+} flexspi_ip_error_code_t;
+
+/*! @brief Error Code when AHB command Error detected.*/
+typedef enum _flexspi_ahb_error_code
+{
+ kFLEXSPI_AhbCmdErrorNoError = 0x0U, /*!< No error. */
+ kFLEXSPI_AhbCmdErrorJumpOnCsInWriteCmd = 0x2U, /*!< AHB Write command with JMP_ON_CS instruction
+ used in the sequence. */
+ kFLEXSPI_AhbCmdErrorUnknownOpCode = 0x3U, /*!< Unknown instruction opcode in the sequence. */
+ kFLEXSPI_AhbCmdErrorSdrDummyInDdrSequence = 0x4U, /*!< Instruction DUMMY_SDR/DUMMY_RWDS_SDR used
+ in DDR sequence. */
+ kFLEXSPI_AhbCmdErrorDdrDummyInSdrSequence = 0x5U, /*!< Instruction DUMMY_DDR/DUMMY_RWDS_DDR
+ used in SDR sequence. */
+ kFLEXSPI_AhbCmdSequenceExecutionTimeout = 0x6U, /*!< Sequence execution timeout. */
+} flexspi_ahb_error_code_t;
+
+/*! @brief FLEXSPI operation port select.*/
+typedef enum _flexspi_port
+{
+ kFLEXSPI_PortA1 = 0x0U, /*!< Access flash on A1 port. */
+ kFLEXSPI_PortA2, /*!< Access flash on A2 port. */
+#if !((defined(FSL_FEATURE_FLEXSPI_NO_SUPPORT_PORTB)) && (FSL_FEATURE_FLEXSPI_NO_SUPPORT_PORTB))
+ kFLEXSPI_PortB1, /*!< Access flash on B1 port. */
+ kFLEXSPI_PortB2, /*!< Access flash on B2 port. */
+#endif
+ kFLEXSPI_PortCount
+} flexspi_port_t;
+
+/*! @brief Trigger source of current command sequence granted by arbitrator.*/
+typedef enum _flexspi_arb_command_source
+{
+ kFLEXSPI_AhbReadCommand = 0x0U,
+ kFLEXSPI_AhbWriteCommand = 0x1U,
+ kFLEXSPI_IpCommand = 0x2U,
+ kFLEXSPI_SuspendedCommand = 0x3U,
+} flexspi_arb_command_source_t;
+
+/*! @brief Command type. */
+typedef enum _flexspi_command_type
+{
+ kFLEXSPI_Command, /*!< FlexSPI operation: Only command, both TX and Rx buffer are ignored. */
+ kFLEXSPI_Config, /*!< FlexSPI operation: Configure device mode, the TX fifo size is fixed in LUT. */
+ kFLEXSPI_Read, /* /!< FlexSPI operation: Read, only Rx Buffer is effective. */
+ kFLEXSPI_Write, /* /!< FlexSPI operation: Read, only Tx Buffer is effective. */
+} flexspi_command_type_t;
+
+typedef struct _flexspi_ahbBuffer_config
+{
+ uint8_t priority; /*!< This priority for AHB Master Read which this AHB RX Buffer is assigned. */
+ uint8_t masterIndex; /*!< AHB Master ID the AHB RX Buffer is assigned. */
+ uint16_t bufferSize; /*!< AHB buffer size in byte. */
+ bool enablePrefetch; /*!< AHB Read Prefetch Enable for current AHB RX Buffer corresponding Master, allows
+ prefetch disable/enable separately for each master. */
+} flexspi_ahbBuffer_config_t;
+
+/*! @brief FLEXSPI configuration structure. */
+typedef struct _flexspi_config
+{
+ flexspi_read_sample_clock_t rxSampleClock; /*!< Sample Clock source selection for Flash Reading. */
+ bool enableSckFreeRunning; /*!< Enable/disable SCK output free-running. */
+#if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN)
+ bool enableCombination; /*!< Enable/disable combining PORT A and B Data Pins
+ (SIOA[3:0] and SIOB[3:0]) to support Flash Octal mode. */
+#endif
+ bool enableDoze; /*!< Enable/disable doze mode support. */
+ bool enableHalfSpeedAccess; /*!< Enable/disable divide by 2 of the clock for half
+ speed commands. */
+#if defined(FSL_FEATURE_FLEXSPI_SUPPORT_SEPERATE_RXCLKSRC_PORTB) && FSL_FEATURE_FLEXSPI_SUPPORT_SEPERATE_RXCLKSRC_PORTB
+ flexspi_read_sample_clock_t rxSampleClockPortB; /*!< Sample Clock source_b selection for Flash Reading. */
+#endif
+#if defined(FSL_FEATURE_FLEXSPI_SUPPORT_RXCLKSRC_DIFF) && FSL_FEATURE_FLEXSPI_SUPPORT_RXCLKSRC_DIFF
+ bool rxSampleClockDiff; /*!< Sample Clock source or source_b selection for Flash Reading. */
+#endif
+#if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR2_SCKBDIFFOPT) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR2_SCKBDIFFOPT)
+ bool enableSckBDiffOpt; /*!< Enable/disable SCKB pad use as SCKA differential clock
+ output, when enable, Port B flash access is not available. */
+#endif
+ bool enableSameConfigForAll; /*!< Enable/disable same configuration for all connected devices
+ when enabled, same configuration in FLASHA1CRx is applied to all. */
+ uint16_t seqTimeoutCycle; /*!< Timeout wait cycle for command sequence execution,
+ timeout after ahbGrantTimeoutCyle*1024 serial root clock cycles. */
+ uint8_t ipGrantTimeoutCycle; /*!< Timeout wait cycle for IP command grant, timeout after
+ ipGrantTimeoutCycle*1024 AHB clock cycles. */
+ uint8_t txWatermark; /*!< FLEXSPI IP transmit watermark value. */
+ uint8_t rxWatermark; /*!< FLEXSPI receive watermark value. */
+ struct
+ {
+#if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ATDFEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ATDFEN)
+ bool enableAHBWriteIpTxFifo; /*!< Enable AHB bus write access to IP TX FIFO. */
+#endif
+#if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ARDFEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ARDFEN)
+ bool enableAHBWriteIpRxFifo; /*!< Enable AHB bus write access to IP RX FIFO. */
+#endif
+ uint8_t ahbGrantTimeoutCycle; /*!< Timeout wait cycle for AHB command grant,
+ timeout after ahbGrantTimeoutCyle*1024 AHB clock cycles. */
+ uint16_t ahbBusTimeoutCycle; /*!< Timeout wait cycle for AHB read/write access,
+ timeout after ahbBusTimeoutCycle*1024 AHB clock cycles. */
+ uint8_t resumeWaitCycle; /*!< Wait cycle for idle state before suspended command sequence
+ resume, timeout after ahbBusTimeoutCycle AHB clock cycles. */
+ flexspi_ahbBuffer_config_t buffer[FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT]; /*!< AHB buffer size. */
+ bool enableClearAHBBufferOpt; /*!< Enable/disable automatically clean AHB RX Buffer and TX Buffer
+ when FLEXSPI returns STOP mode ACK. */
+ bool enableReadAddressOpt; /*!< Enable/disable remove AHB read burst start address alignment limitation.
+ when enable, there is no AHB read burst start address alignment limitation. */
+ bool enableAHBPrefetch; /*!< Enable/disable AHB read prefetch feature, when enabled, FLEXSPI
+ will fetch more data than current AHB burst. */
+ bool enableAHBBufferable; /*!< Enable/disable AHB bufferable write access support, when enabled,
+ FLEXSPI return before waiting for command execution finished. */
+ bool enableAHBCachable; /*!< Enable AHB bus cachable read access support. */
+ } ahbConfig;
+} flexspi_config_t;
+
+/*! @brief External device configuration items. */
+typedef struct _flexspi_device_config
+{
+ uint32_t flexspiRootClk; /*!< FLEXSPI serial root clock. */
+ bool isSck2Enabled; /*!< FLEXSPI use SCK2. */
+ uint32_t flashSize; /*!< Flash size in KByte. */
+#if defined(FSL_FEATURE_FLEXSPI_SUPPORT_ADDRESS_SHIFT) && (FSL_FEATURE_FLEXSPI_SUPPORT_ADDRESS_SHIFT)
+ bool addressShift; /*!< Address shift. */
+#endif /* FSL_FEATURE_FLEXSPI_SUPPORT_ADDRESS_SHIFT */
+ flexspi_cs_interval_cycle_unit_t CSIntervalUnit; /*!< CS interval unit, 1 or 256 cycle. */
+ uint16_t CSInterval; /*!< CS line assert interval, multiply CS interval unit to
+ get the CS line assert interval cycles. */
+ uint8_t CSHoldTime; /*!< CS line hold time. */
+ uint8_t CSSetupTime; /*!< CS line setup time. */
+ uint8_t dataValidTime; /*!< Data valid time for external device. */
+ uint8_t columnspace; /*!< Column space size. */
+ bool enableWordAddress; /*!< If enable word address.*/
+ uint8_t AWRSeqIndex; /*!< Sequence ID for AHB write command. */
+ uint8_t AWRSeqNumber; /*!< Sequence number for AHB write command. */
+ uint8_t ARDSeqIndex; /*!< Sequence ID for AHB read command. */
+ uint8_t ARDSeqNumber; /*!< Sequence number for AHB read command. */
+ flexspi_ahb_write_wait_unit_t AHBWriteWaitUnit; /*!< AHB write wait unit. */
+ uint16_t AHBWriteWaitInterval; /*!< AHB write wait interval, multiply AHB write interval
+ unit to get the AHB write wait cycles. */
+ bool enableWriteMask; /*!< Enable/Disable FLEXSPI drive DQS pin as write mask
+ when writing to external device. */
+#if defined(FSL_FEATURE_FLEXSPI_HAS_ERRATA_051426) && (FSL_FEATURE_FLEXSPI_HAS_ERRATA_051426)
+ bool isFroClockSource; /*!< Is FRO clock source or not. */
+#endif
+} flexspi_device_config_t;
+
+/*! @brief Transfer structure for FLEXSPI. */
+typedef struct _flexspi_transfer
+{
+ uint32_t deviceAddress; /*!< Operation device address. */
+ flexspi_port_t port; /*!< Operation port. */
+ flexspi_command_type_t cmdType; /*!< Execution command type. */
+ uint8_t seqIndex; /*!< Sequence ID for command. */
+ uint8_t SeqNumber; /*!< Sequence number for command. */
+ uint32_t *data; /*!< Data buffer. */
+ size_t dataSize; /*!< Data size in bytes. */
+} flexspi_transfer_t;
+
+/* Forward declaration of the handle typedef. */
+typedef struct _flexspi_handle flexspi_handle_t;
+
+/*! @brief FLEXSPI transfer callback function. */
+typedef void (*flexspi_transfer_callback_t)(FLEXSPI_Type *base,
+ flexspi_handle_t *handle,
+ status_t status,
+ void *userData);
+
+/*! @brief Transfer handle structure for FLEXSPI. */
+struct _flexspi_handle
+{
+ uint32_t state; /*!< Internal state for FLEXSPI transfer */
+ uint8_t *data; /*!< Data buffer. */
+ size_t dataSize; /*!< Remaining Data size in bytes. */
+ size_t transferTotalSize; /*!< Total Data size in bytes. */
+ flexspi_transfer_callback_t completionCallback; /*!< Callback for users while transfer finish or error occurred */
+ void *userData; /*!< FLEXSPI callback function parameter.*/
+};
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /*_cplusplus. */
+
+/*!
+ * @name Initialization and deinitialization
+ * @{
+ */
+
+/*!
+ * @brief Get the instance number for FLEXSPI.
+ *
+ * @param base FLEXSPI base pointer.
+ */
+uint32_t FLEXSPI_GetInstance(FLEXSPI_Type *base);
+
+/*!
+ * @brief Check and clear IP command execution errors.
+ *
+ * @param base FLEXSPI base pointer.
+ * @param status interrupt status.
+ */
+status_t FLEXSPI_CheckAndClearError(FLEXSPI_Type *base, uint32_t status);
+
+/*!
+ * @brief Initializes the FLEXSPI module and internal state.
+ *
+ * This function enables the clock for FLEXSPI and also configures the FLEXSPI with the
+ * input configure parameters. Users should call this function before any FLEXSPI operations.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param config FLEXSPI configure structure.
+ */
+void FLEXSPI_Init(FLEXSPI_Type *base, const flexspi_config_t *config);
+
+/*!
+ * @brief Gets default settings for FLEXSPI.
+ *
+ * @param config FLEXSPI configuration structure.
+ */
+void FLEXSPI_GetDefaultConfig(flexspi_config_t *config);
+
+/*!
+ * @brief Deinitializes the FLEXSPI module.
+ *
+ * Clears the FLEXSPI state and FLEXSPI module registers.
+ * @param base FLEXSPI peripheral base address.
+ */
+void FLEXSPI_Deinit(FLEXSPI_Type *base);
+
+/*!
+ * @brief Update FLEXSPI DLL value depending on currently flexspi root clock.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param config Flash configuration parameters.
+ * @param port FLEXSPI Operation port.
+ */
+void FLEXSPI_UpdateDllValue(FLEXSPI_Type *base, flexspi_device_config_t *config, flexspi_port_t port);
+
+/*!
+ * @brief Configures the connected device parameter.
+ *
+ * This function configures the connected device relevant parameters, such as the size, command, and so on.
+ * The flash configuration value cannot have a default value. The user needs to configure it according to the
+ * connected device.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param config Flash configuration parameters.
+ * @param port FLEXSPI Operation port.
+ */
+void FLEXSPI_SetFlashConfig(FLEXSPI_Type *base, flexspi_device_config_t *config, flexspi_port_t port);
+
+/*!
+ * @brief Software reset for the FLEXSPI logic.
+ *
+ * This function sets the software reset flags for both AHB and buffer domain and
+ * resets both AHB buffer and also IP FIFOs.
+ *
+ * @param base FLEXSPI peripheral base address.
+ */
+static inline void FLEXSPI_SoftwareReset(FLEXSPI_Type *base)
+{
+ base->MCR0 |= FLEXSPI_MCR0_SWRESET_MASK;
+ while (0U != (base->MCR0 & FLEXSPI_MCR0_SWRESET_MASK))
+ {
+ }
+}
+
+/*!
+ * @brief Enables or disables the FLEXSPI module.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param enable True means enable FLEXSPI, false means disable.
+ */
+static inline void FLEXSPI_Enable(FLEXSPI_Type *base, bool enable)
+{
+ if (enable)
+ {
+ base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
+ }
+ else
+ {
+ base->MCR0 |= FLEXSPI_MCR0_MDIS_MASK;
+ }
+}
+
+/* @} */
+
+/*!
+ * @name Interrupts
+ * @{
+ */
+/*!
+ * @brief Enables the FLEXSPI interrupts.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param mask FLEXSPI interrupt source.
+ */
+static inline void FLEXSPI_EnableInterrupts(FLEXSPI_Type *base, uint32_t mask)
+{
+ base->INTEN |= mask;
+}
+
+/*!
+ * @brief Disable the FLEXSPI interrupts.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param mask FLEXSPI interrupt source.
+ */
+static inline void FLEXSPI_DisableInterrupts(FLEXSPI_Type *base, uint32_t mask)
+{
+ base->INTEN &= ~mask;
+}
+
+/* @} */
+
+/*! @name DMA control */
+/*@{*/
+
+/*!
+ * @brief Enables or disables FLEXSPI IP Tx FIFO DMA requests.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param enable Enable flag for transmit DMA request. Pass true for enable, false for disable.
+ */
+static inline void FLEXSPI_EnableTxDMA(FLEXSPI_Type *base, bool enable)
+{
+ if (enable)
+ {
+ base->IPTXFCR |= FLEXSPI_IPTXFCR_TXDMAEN_MASK;
+ }
+ else
+ {
+ base->IPTXFCR &= ~FLEXSPI_IPTXFCR_TXDMAEN_MASK;
+ }
+}
+
+/*!
+ * @brief Enables or disables FLEXSPI IP Rx FIFO DMA requests.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param enable Enable flag for receive DMA request. Pass true for enable, false for disable.
+ */
+static inline void FLEXSPI_EnableRxDMA(FLEXSPI_Type *base, bool enable)
+{
+ if (enable)
+ {
+ base->IPRXFCR |= FLEXSPI_IPRXFCR_RXDMAEN_MASK;
+ }
+ else
+ {
+ base->IPRXFCR &= ~FLEXSPI_IPRXFCR_RXDMAEN_MASK;
+ }
+}
+
+/*!
+ * @brief Gets FLEXSPI IP tx fifo address for DMA transfer.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @retval The tx fifo address.
+ */
+static inline uint32_t FLEXSPI_GetTxFifoAddress(FLEXSPI_Type *base)
+{
+ return (uint32_t)&base->TFDR[0];
+}
+
+/*!
+ * @brief Gets FLEXSPI IP rx fifo address for DMA transfer.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @retval The rx fifo address.
+ */
+static inline uint32_t FLEXSPI_GetRxFifoAddress(FLEXSPI_Type *base)
+{
+ return (uint32_t)&base->RFDR[0];
+}
+
+/*@}*/
+
+/*! @name FIFO control */
+/*@{*/
+
+/*! @brief Clears the FLEXSPI IP FIFO logic.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param txFifo Pass true to reset TX FIFO.
+ * @param rxFifo Pass true to reset RX FIFO.
+ */
+static inline void FLEXSPI_ResetFifos(FLEXSPI_Type *base, bool txFifo, bool rxFifo)
+{
+ if (txFifo)
+ {
+ base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
+ }
+ if (rxFifo)
+ {
+ base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
+ }
+}
+
+/*!
+ * @brief Gets the valid data entries in the FLEXSPI FIFOs.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param[out] txCount Pointer through which the current number of bytes in the transmit FIFO is returned.
+ * Pass NULL if this value is not required.
+ * @param[out] rxCount Pointer through which the current number of bytes in the receive FIFO is returned.
+ * Pass NULL if this value is not required.
+ */
+static inline void FLEXSPI_GetFifoCounts(FLEXSPI_Type *base, size_t *txCount, size_t *rxCount)
+{
+ if (NULL != txCount)
+ {
+ *txCount = (((base->IPTXFSTS) & FLEXSPI_IPTXFSTS_FILL_MASK) >> FLEXSPI_IPTXFSTS_FILL_SHIFT) * 8U;
+ }
+ if (NULL != rxCount)
+ {
+ *rxCount = (((base->IPRXFSTS) & FLEXSPI_IPRXFSTS_FILL_MASK) >> FLEXSPI_IPRXFSTS_FILL_SHIFT) * 8U;
+ }
+}
+
+/*@}*/
+
+/*!
+ * @name Status
+ * @{
+ */
+/*!
+ * @brief Get the FLEXSPI interrupt status flags.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @retval interrupt status flag, use status flag to AND #flexspi_flags_t could get the related status.
+ */
+static inline uint32_t FLEXSPI_GetInterruptStatusFlags(FLEXSPI_Type *base)
+{
+ return base->INTR;
+}
+
+/*!
+ * @brief Get the FLEXSPI interrupt status flags.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param mask FLEXSPI interrupt source.
+ */
+static inline void FLEXSPI_ClearInterruptStatusFlags(FLEXSPI_Type *base, uint32_t mask)
+{
+ base->INTR |= mask;
+}
+
+#if !((defined(FSL_FEATURE_FLEXSPI_HAS_NO_DATA_LEARN)) && (FSL_FEATURE_FLEXSPI_HAS_NO_DATA_LEARN))
+/*! @brief Gets the sampling clock phase selection after Data Learning.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param portAPhase Pointer to a uint8_t type variable to receive the selected clock phase on PORTA.
+ * @param portBPhase Pointer to a uint8_t type variable to receive the selected clock phase on PORTB.
+ */
+static inline void FLEXSPI_GetDataLearningPhase(FLEXSPI_Type *base, uint8_t *portAPhase, uint8_t *portBPhase)
+{
+ if (portAPhase != NULL)
+ {
+ *portAPhase = (uint8_t)((base->STS0 & FLEXSPI_STS0_DATALEARNPHASEA_MASK) >> FLEXSPI_STS0_DATALEARNPHASEA_SHIFT);
+ }
+
+#if !((defined(FSL_FEATURE_FLEXSPI_HAS_NO_STS0_DATALEARNPHASEB)) && (FSL_FEATURE_FLEXSPI_HAS_NO_STS0_DATALEARNPHASEB))
+ if (portBPhase != NULL)
+ {
+ *portBPhase = (uint8_t)((base->STS0 & FLEXSPI_STS0_DATALEARNPHASEB_MASK) >> FLEXSPI_STS0_DATALEARNPHASEB_SHIFT);
+ }
+#endif
+}
+#endif
+
+/*! @brief Gets the trigger source of current command sequence granted by arbitrator.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @retval trigger source of current command sequence.
+ */
+static inline flexspi_arb_command_source_t FLEXSPI_GetArbitratorCommandSource(FLEXSPI_Type *base)
+{
+ return (flexspi_arb_command_source_t)(
+ (uint32_t)((base->STS0 & FLEXSPI_STS0_ARBCMDSRC_MASK) >> FLEXSPI_STS0_ARBCMDSRC_SHIFT));
+}
+
+/*! @brief Gets the error code when IP command error detected.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param index Pointer to a uint8_t type variable to receive the sequence index when error detected.
+ * @retval error code when IP command error detected.
+ */
+static inline flexspi_ip_error_code_t FLEXSPI_GetIPCommandErrorCode(FLEXSPI_Type *base, uint8_t *index)
+{
+ *index = (uint8_t)((base->STS1 & FLEXSPI_STS1_IPCMDERRID_MASK) >> FLEXSPI_STS1_IPCMDERRID_SHIFT);
+ return (flexspi_ip_error_code_t)(
+ (uint32_t)((base->STS1 & FLEXSPI_STS1_IPCMDERRCODE_MASK) >> FLEXSPI_STS1_IPCMDERRCODE_SHIFT));
+}
+
+/*! @brief Gets the error code when AHB command error detected.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param index Pointer to a uint8_t type variable to receive the sequence index when error detected.
+ * @retval error code when AHB command error detected.
+ */
+static inline flexspi_ahb_error_code_t FLEXSPI_GetAHBCommandErrorCode(FLEXSPI_Type *base, uint8_t *index)
+{
+ *index = (uint8_t)(base->STS1 & FLEXSPI_STS1_AHBCMDERRID_MASK) >> FLEXSPI_STS1_AHBCMDERRID_SHIFT;
+ return (flexspi_ahb_error_code_t)(
+ (uint32_t)((base->STS1 & FLEXSPI_STS1_AHBCMDERRCODE_MASK) >> FLEXSPI_STS1_AHBCMDERRCODE_SHIFT));
+}
+
+/*! @brief Returns whether the bus is idle.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @retval true Bus is idle.
+ * @retval false Bus is busy.
+ */
+static inline bool FLEXSPI_GetBusIdleStatus(FLEXSPI_Type *base)
+{
+ return (0U != (base->STS0 & FLEXSPI_STS0_ARBIDLE_MASK)) && (0U != (base->STS0 & FLEXSPI_STS0_SEQIDLE_MASK));
+}
+/*@}*/
+
+/*!
+ * @name Bus Operations
+ * @{
+ */
+
+/*! @brief Update read sample clock source
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param clockSource clockSource of type #flexspi_read_sample_clock_t
+ */
+void FLEXSPI_UpdateRxSampleClock(FLEXSPI_Type *base, flexspi_read_sample_clock_t clockSource);
+
+#if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_IP_PARALLEL_MODE) && FSL_FEATURE_FLEXSPI_HAS_NO_IP_PARALLEL_MODE)
+/*! @brief Enables/disables the FLEXSPI IP command parallel mode.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param enable True means enable parallel mode, false means disable parallel mode.
+ */
+static inline void FLEXSPI_EnableIPParallelMode(FLEXSPI_Type *base, bool enable)
+{
+ if (enable)
+ {
+ base->IPCR1 |= FLEXSPI_IPCR1_IPAREN_MASK;
+ }
+ else
+ {
+ base->IPCR1 &= ~FLEXSPI_IPCR1_IPAREN_MASK;
+ }
+}
+#endif
+
+#if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_AHB_PARALLEL_MODE) && FSL_FEATURE_FLEXSPI_HAS_NO_AHB_PARALLEL_MODE)
+/*! @brief Enables/disables the FLEXSPI AHB command parallel mode.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param enable True means enable parallel mode, false means disable parallel mode.
+ */
+static inline void FLEXSPI_EnableAHBParallelMode(FLEXSPI_Type *base, bool enable)
+{
+ if (enable)
+ {
+ base->AHBCR |= FLEXSPI_AHBCR_APAREN_MASK;
+ }
+ else
+ {
+ base->AHBCR &= ~FLEXSPI_AHBCR_APAREN_MASK;
+ }
+}
+#endif
+
+/*! @brief Updates the LUT table.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param index From which index start to update. It could be any index of the LUT table, which
+ * also allows user to update command content inside a command. Each command consists of up to
+ * 8 instructions and occupy 4*32-bit memory.
+ * @param cmd Command sequence array.
+ * @param count Number of sequences.
+ */
+void FLEXSPI_UpdateLUT(FLEXSPI_Type *base, uint32_t index, const uint32_t *cmd, uint32_t count);
+
+/*!
+ * @brief Writes data into FIFO.
+ *
+ * @param base FLEXSPI peripheral base address
+ * @param data The data bytes to send
+ * @param fifoIndex Destination fifo index.
+ */
+static inline void FLEXSPI_WriteData(FLEXSPI_Type *base, uint32_t data, uint8_t fifoIndex)
+{
+ base->TFDR[fifoIndex] = data;
+}
+
+/*!
+ * @brief Receives data from data FIFO.
+ *
+ * @param base FLEXSPI peripheral base address
+ * @param fifoIndex Source fifo index.
+ * @return The data in the FIFO.
+ */
+static inline uint32_t FLEXSPI_ReadData(FLEXSPI_Type *base, uint8_t fifoIndex)
+{
+ return base->RFDR[fifoIndex];
+}
+
+/*!
+ * @brief Sends a buffer of data bytes using blocking method.
+ * @note This function blocks via polling until all bytes have been sent.
+ * @param base FLEXSPI peripheral base address
+ * @param buffer The data bytes to send
+ * @param size The number of data bytes to send
+ * @retval kStatus_Success write success without error
+ * @retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout
+ * @retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequence error detected
+ * @retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected
+ */
+status_t FLEXSPI_WriteBlocking(FLEXSPI_Type *base, uint8_t *buffer, size_t size);
+
+/*!
+ * @brief Receives a buffer of data bytes using a blocking method.
+ * @note This function blocks via polling until all bytes have been sent.
+ * @param base FLEXSPI peripheral base address
+ * @param buffer The data bytes to send
+ * @param size The number of data bytes to receive
+ * @retval kStatus_Success read success without error
+ * @retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout
+ * @retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequencen error detected
+ * @retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected
+ */
+status_t FLEXSPI_ReadBlocking(FLEXSPI_Type *base, uint8_t *buffer, size_t size);
+
+/*!
+ * @brief Execute command to transfer a buffer data bytes using a blocking method.
+ * @param base FLEXSPI peripheral base address
+ * @param xfer pointer to the transfer structure.
+ * @retval kStatus_Success command transfer success without error
+ * @retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout
+ * @retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequence error detected
+ * @retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected
+ */
+status_t FLEXSPI_TransferBlocking(FLEXSPI_Type *base, flexspi_transfer_t *xfer);
+/*! @} */
+
+/*!
+ * @name Transactional
+ * @{
+ */
+
+/*!
+ * @brief Initializes the FLEXSPI handle which is used in transactional functions.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param handle pointer to flexspi_handle_t structure to store the transfer state.
+ * @param callback pointer to user callback function.
+ * @param userData user parameter passed to the callback function.
+ */
+void FLEXSPI_TransferCreateHandle(FLEXSPI_Type *base,
+ flexspi_handle_t *handle,
+ flexspi_transfer_callback_t callback,
+ void *userData);
+
+/*!
+ * @brief Performs a interrupt non-blocking transfer on the FLEXSPI bus.
+ *
+ * @note Calling the API returns immediately after transfer initiates. The user needs
+ * to call FLEXSPI_GetTransferCount to poll the transfer status to check whether
+ * the transfer is finished. If the return status is not kStatus_FLEXSPI_Busy, the transfer
+ * is finished. For FLEXSPI_Read, the dataSize should be multiple of rx watermark level, or
+ * FLEXSPI could not read data properly.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param handle pointer to flexspi_handle_t structure which stores the transfer state.
+ * @param xfer pointer to flexspi_transfer_t structure.
+ * @retval kStatus_Success Successfully start the data transmission.
+ * @retval kStatus_FLEXSPI_Busy Previous transmission still not finished.
+ */
+status_t FLEXSPI_TransferNonBlocking(FLEXSPI_Type *base, flexspi_handle_t *handle, flexspi_transfer_t *xfer);
+
+/*!
+ * @brief Gets the master transfer status during a interrupt non-blocking transfer.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param handle pointer to flexspi_handle_t structure which stores the transfer state.
+ * @param count Number of bytes transferred so far by the non-blocking transaction.
+ * @retval kStatus_InvalidArgument count is Invalid.
+ * @retval kStatus_Success Successfully return the count.
+ */
+status_t FLEXSPI_TransferGetCount(FLEXSPI_Type *base, flexspi_handle_t *handle, size_t *count);
+
+/*!
+ * @brief Aborts an interrupt non-blocking transfer early.
+ *
+ * @note This API can be called at any time when an interrupt non-blocking transfer initiates
+ * to abort the transfer early.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param handle pointer to flexspi_handle_t structure which stores the transfer state
+ */
+void FLEXSPI_TransferAbort(FLEXSPI_Type *base, flexspi_handle_t *handle);
+
+/*!
+ * @brief Master interrupt handler.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param handle pointer to flexspi_handle_t structure.
+ */
+void FLEXSPI_TransferHandleIRQ(FLEXSPI_Type *base, flexspi_handle_t *handle);
+/*! @} */
+
+#if defined(__cplusplus)
+}
+#endif /*_cplusplus. */
+/*@}*/
+
+#endif /* __FSL_FLEXSPI_H_ */
diff --git a/bsps/arm/imxrt/mcux-sdk/drivers/flexspi/fsl_flexspi_dma.h b/bsps/arm/imxrt/mcux-sdk/drivers/flexspi/fsl_flexspi_dma.h
new file mode 100644
index 0000000000..101af6d913
--- /dev/null
+++ b/bsps/arm/imxrt/mcux-sdk/drivers/flexspi/fsl_flexspi_dma.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2019-2021 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _FSL_FLEXSPI_DMA_H_
+#define _FSL_FLEXSPI_DMA_H_
+
+#include "fsl_flexspi.h"
+#include "fsl_dma.h"
+
+/*!
+ * @addtogroup flexspi_dma
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @name Driver version */
+/*@{*/
+/*! @brief FLEXSPI DMA driver version 2.2.1. */
+#define FSL_FLEXSPI_DMA_DRIVER_VERSION (MAKE_VERSION(2, 2, 1))
+/*@}*/
+
+typedef struct _flexspi_dma_handle flexspi_dma_handle_t;
+
+/*! @brief FLEXSPI dma transfer callback function for finish and error */
+typedef void (*flexspi_dma_callback_t)(FLEXSPI_Type *base,
+ flexspi_dma_handle_t *handle,
+ status_t status,
+ void *userData);
+
+/*! @brief dma transfer configuration */
+typedef enum _flexspi_dma_ntransfer_size
+{
+ kFLEXPSI_DMAnSize1Bytes = 0x1U, /*!< Source/Destination data transfer size is 1 byte every time */
+ kFLEXPSI_DMAnSize2Bytes = 0x2U, /*!< Source/Destination data transfer size is 2 bytes every time */
+ kFLEXPSI_DMAnSize4Bytes = 0x4U, /*!< Source/Destination data transfer size is 4 bytes every time */
+} flexspi_dma_transfer_nsize_t;
+
+/*! @brief FLEXSPI DMA transfer handle, users should not touch the content of the handle.*/
+struct _flexspi_dma_handle
+{
+ dma_handle_t *txDmaHandle; /*!< dma handler for FLEXSPI Tx. */
+ dma_handle_t *rxDmaHandle; /*!< dma handler for FLEXSPI Rx. */
+ size_t transferSize; /*!< Bytes need to transfer. */
+ flexspi_dma_transfer_nsize_t nsize; /*!< dma SSIZE/DSIZE in each transfer. */
+ uint8_t nbytes; /*!< dma minor byte transfer count initially configured. */
+ uint8_t count; /*!< The transfer data count in a DMA request. */
+ uint32_t state; /*!< Internal state for FLEXSPI dma transfer. */
+ flexspi_dma_callback_t completionCallback; /*!< A callback function called after the dma transfer is finished. */
+ void *userData; /*!< User callback parameter */
+};
+
+/*******************************************************************************
+ * APIs
+ ******************************************************************************/
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*!
+ * @name FLEXSPI dma Transactional
+ * @{
+ */
+
+/*!
+ * @brief Initializes the FLEXSPI handle for transfer which is used in transactional functions and set the callback.
+ *
+ * @param base FLEXSPI peripheral base address
+ * @param handle Pointer to flexspi_dma_handle_t structure
+ * @param callback FLEXSPI callback, NULL means no callback.
+ * @param userData User callback function data.
+ * @param txDmaHandle User requested DMA handle for TX DMA transfer.
+ * @param rxDmaHandle User requested DMA handle for RX DMA transfer.
+ */
+void FLEXSPI_TransferCreateHandleDMA(FLEXSPI_Type *base,
+ flexspi_dma_handle_t *handle,
+ flexspi_dma_callback_t callback,
+ void *userData,
+ dma_handle_t *txDmaHandle,
+ dma_handle_t *rxDmaHandle);
+
+/*!
+ * @brief Update FLEXSPI DMA transfer source data transfer size(SSIZE) and destination data transfer size(DSIZE).
+ *
+ * @param base FLEXSPI peripheral base address
+ * @param handle Pointer to flexspi_dma_handle_t structure
+ * @param nsize FLEXSPI DMA transfer data transfer size(SSIZE/DSIZE), by default the size is
+ * kFLEXPSI_DMAnSize1Bytes(one byte).
+ * @see flexspi_dma_transfer_nsize_t .
+ */
+void FLEXSPI_TransferUpdateSizeDMA(FLEXSPI_Type *base,
+ flexspi_dma_handle_t *handle,
+ flexspi_dma_transfer_nsize_t nsize);
+
+/*!
+ * @brief Transfers FLEXSPI data using an dma non-blocking method.
+ *
+ * This function writes/receives data to/from the FLEXSPI transmit/receive FIFO. This function is non-blocking.
+ * @param base FLEXSPI peripheral base address.
+ * @param handle Pointer to flexspi_dma_handle_t structure
+ * @param xfer FLEXSPI transfer structure.
+ * @retval kStatus_FLEXSPI_Busy FLEXSPI is busy transfer.
+ * @retval kStatus_InvalidArgument The watermark configuration is invalid, the watermark should be power of
+ 2 to do successfully DMA transfer.
+ * @retval kStatus_Success FLEXSPI successfully start dma transfer.
+ */
+status_t FLEXSPI_TransferDMA(FLEXSPI_Type *base, flexspi_dma_handle_t *handle, flexspi_transfer_t *xfer);
+
+/*!
+ * @brief Aborts the transfer data using dma.
+ *
+ * This function aborts the transfer data using dma.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param handle Pointer to flexspi_dma_handle_t structure
+ */
+void FLEXSPI_TransferAbortDMA(FLEXSPI_Type *base, flexspi_dma_handle_t *handle);
+
+/*!
+ * @brief Gets the transferred counts of transfer.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param handle Pointer to flexspi_dma_handle_t structure.
+ * @param count Bytes transfer.
+ * @retval kStatus_Success Succeed get the transfer count.
+ * @retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
+ */
+status_t FLEXSPI_TransferGetTransferCountDMA(FLEXSPI_Type *base, flexspi_dma_handle_t *handle, size_t *count);
+
+/* @} */
+
+#if defined(__cplusplus)
+}
+#endif
+
+/* @} */
+
+#endif /* _FSL_FLEXSPI_DMA_H_ */
diff --git a/bsps/arm/imxrt/mcux-sdk/drivers/flexspi/fsl_flexspi_edma.c b/bsps/arm/imxrt/mcux-sdk/drivers/flexspi/fsl_flexspi_edma.c
new file mode 100644
index 0000000000..80c19f8ccd
--- /dev/null
+++ b/bsps/arm/imxrt/mcux-sdk/drivers/flexspi/fsl_flexspi_edma.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2020 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "fsl_flexspi_edma.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/* Component ID definition, used by tools. */
+#ifndef FSL_COMPONENT_ID
+#define FSL_COMPONENT_ID "platform.drivers.flexspi_edma"
+#endif
+
+/*<! Structure definition for flexspi_edma_private_handle_t. The structure is private. */
+typedef struct _flexspi_edma_private_handle
+{
+ FLEXSPI_Type *base;
+ flexspi_edma_handle_t *handle;
+} flexspi_edma_private_handle_t;
+
+/* FLEXSPI EDMA transfer handle, _flexspi_edma_tansfer_states. */
+enum
+{
+ kFLEXSPI_Idle, /* FLEXSPI Bus idle. */
+ kFLEXSPI_Busy /* FLEXSPI Bus busy. */
+};
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+/*! @brief Pointers to flexspi bases for each instance. */
+static FLEXSPI_Type *const s_flexspiBases[] = FLEXSPI_BASE_PTRS;
+
+/*<! Private handle only used for internally. */
+static flexspi_edma_private_handle_t s_edmaPrivateHandle[ARRAY_SIZE(s_flexspiBases)];
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+
+/*!
+ * @brief FLEXSPI EDMA transfer finished callback function.
+ *
+ * This function is called when FLEXSPI EDMA transfer finished. It disables the FLEXSPI
+ * TX/RX EDMA request and sends status to FLEXSPI callback.
+ *
+ * @param handle The EDMA handle.
+ * @param param Callback function parameter.
+ */
+static void FLEXSPI_TransferEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+static uint8_t FLEXSPI_CalculatePower(uint8_t value)
+{
+ uint8_t power = 0;
+ while (value >> 1 != 0U)
+ {
+ power++;
+ value = value >> 1;
+ }
+
+ return power;
+}
+static void FLEXSPI_TransferEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
+{
+ flexspi_edma_private_handle_t *flexspiPrivateHandle = (flexspi_edma_private_handle_t *)param;
+
+ /* Avoid warning for unused parameters. */
+ handle = handle;
+ tcds = tcds;
+
+ if (transferDone)
+ {
+ /* Wait for bus idle. */
+ while (!FLEXSPI_GetBusIdleStatus(flexspiPrivateHandle->base))
+ {
+ }
+ /* Disable transfer. */
+ FLEXSPI_TransferAbortEDMA(flexspiPrivateHandle->base, flexspiPrivateHandle->handle);
+
+ if (flexspiPrivateHandle->handle->completionCallback != NULL)
+ {
+ flexspiPrivateHandle->handle->completionCallback(flexspiPrivateHandle->base, flexspiPrivateHandle->handle,
+ kStatus_Success, flexspiPrivateHandle->handle->userData);
+ }
+ }
+}
+
+/*!
+ * brief Initializes the FLEXSPI handle for transfer which is used in transactional functions and set the callback.
+ *
+ * param base FLEXSPI peripheral base address
+ * param handle Pointer to flexspi_edma_handle_t structure
+ * param callback FLEXSPI callback, NULL means no callback.
+ * param userData User callback function data.
+ * param txDmaHandle User requested DMA handle for TX DMA transfer.
+ * param rxDmaHandle User requested DMA handle for RX DMA transfer.
+ */
+void FLEXSPI_TransferCreateHandleEDMA(FLEXSPI_Type *base,
+ flexspi_edma_handle_t *handle,
+ flexspi_edma_callback_t callback,
+ void *userData,
+ edma_handle_t *txDmaHandle,
+ edma_handle_t *rxDmaHandle)
+{
+ assert(handle);
+
+ uint32_t instance = FLEXSPI_GetInstance(base);
+
+ s_edmaPrivateHandle[instance].base = base;
+ s_edmaPrivateHandle[instance].handle = handle;
+
+ (void)memset(handle, 0, sizeof(*handle));
+
+ handle->state = kFLEXSPI_Idle;
+ handle->txDmaHandle = txDmaHandle;
+ handle->rxDmaHandle = rxDmaHandle;
+ handle->nsize = kFLEXPSI_EDMAnSize1Bytes;
+
+ handle->completionCallback = callback;
+ handle->userData = userData;
+}
+
+/*!
+ * brief Update FLEXSPI EDMA transfer source data transfer size(SSIZE) and destination data transfer size(DSIZE).
+ *
+ * param base FLEXSPI peripheral base address
+ * param handle Pointer to flexspi_edma_handle_t structure
+ * param nsize FLEXSPI DMA transfer data transfer size(SSIZE/DSIZE), by default the size is
+ * kFLEXPSI_EDMAnSize1Bytes(one byte).
+ * see flexspi_edma_transfer_nsize_t .
+ */
+void FLEXSPI_TransferUpdateSizeEDMA(FLEXSPI_Type *base,
+ flexspi_edma_handle_t *handle,
+ flexspi_edma_transfer_nsize_t nsize)
+{
+ handle->nsize = nsize;
+}
+
+/*!
+ * brief Transfers FLEXSPI data using an eDMA non-blocking method.
+ *
+ * This function writes/receives data to/from the FLEXSPI transmit/receive FIFO. This function is non-blocking.
+ * param base FLEXSPI peripheral base address.
+ * param handle Pointer to flexspi_edma_handle_t structure
+ * param xfer FLEXSPI transfer structure.
+ * retval kStatus_FLEXSPI_Busy FLEXSPI is busy transfer.
+ * retval kStatus_InvalidArgument The watermark configuration is invalid, the watermark should be power of
+ 2 to do successfully EDMA transfer.
+ * retval kStatus_Success FLEXSPI successfully start edma transfer.
+ */
+status_t FLEXSPI_TransferEDMA(FLEXSPI_Type *base, flexspi_edma_handle_t *handle, flexspi_transfer_t *xfer)
+{
+ uint32_t configValue = 0;
+ status_t result = kStatus_Success;
+ edma_transfer_config_t xferConfig;
+ uint32_t instance = FLEXSPI_GetInstance(base);
+ uint8_t power = 0;
+
+ assert(handle);
+ assert(xfer);
+
+ /* Check if the FLEXSPI bus is idle - if not return busy status. */
+ if (handle->state != (uint32_t)kFLEXSPI_Idle)
+ {
+ result = kStatus_FLEXSPI_Busy;
+ }
+ else
+ {
+ handle->transferSize = xfer->dataSize;
+ handle->state = kFLEXSPI_Busy;
+
+ /* Clear sequence pointer before sending data to external devices. */
+ base->FLSHCR2[xfer->port] |= FLEXSPI_FLSHCR2_CLRINSTRPTR_MASK;
+
+ /* Clear former pending status before start this transfer. */
+ base->INTR |= FLEXSPI_INTR_AHBCMDERR_MASK | FLEXSPI_INTR_IPCMDERR_MASK | FLEXSPI_INTR_AHBCMDGE_MASK |
+ FLEXSPI_INTR_IPCMDGE_MASK;
+
+ /* Configure base address. */
+ base->IPCR0 = xfer->deviceAddress;
+
+ /* Reset fifos. */
+ base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
+ base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
+
+ /* Configure data size. */
+ if ((xfer->cmdType == kFLEXSPI_Read) || (xfer->cmdType == kFLEXSPI_Write))
+ {
+ configValue = FLEXSPI_IPCR1_IDATSZ(xfer->dataSize);
+ }
+
+ /* Configure sequence ID. */
+ configValue |= FLEXSPI_IPCR1_ISEQID(xfer->seqIndex) | FLEXSPI_IPCR1_ISEQNUM((uint32_t)xfer->SeqNumber - 1U);
+ base->IPCR1 = configValue;
+ }
+
+ if ((xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config))
+ {
+ handle->count = (uint8_t)((base->IPTXFCR & FLEXSPI_IPTXFCR_TXWMRK_MASK) >> FLEXSPI_IPTXFCR_TXWMRK_SHIFT) + 1U;
+
+ if (xfer->dataSize < 8U * (uint32_t)handle->count)
+ {
+ handle->nbytes = (uint8_t)xfer->dataSize;
+ }
+ else
+ {
+ /* Check the handle->count is power of 2 */
+ if (((handle->count) & (handle->count - 1U)) != 0U)
+ {
+ return kStatus_InvalidArgument;
+ }
+ /* Store the initially configured eDMA minor byte transfer count into the FLEXSPI handle */
+ handle->nbytes = (8U * handle->count);
+ }
+
+ power = FLEXSPI_CalculatePower(8U * handle->count);
+
+ /* Prepare transfer. */
+ EDMA_PrepareTransfer(&xferConfig, xfer->data, (uint32_t)handle->nsize,
+ (void *)(uint32_t *)FLEXSPI_GetTxFifoAddress(base), (uint32_t)handle->nsize,
+ (uint32_t)handle->nbytes, xfer->dataSize, kEDMA_MemoryToMemory);
+
+ /* Submit transfer. */
+ (void)EDMA_SubmitTransfer(handle->txDmaHandle, &xferConfig);
+ EDMA_SetModulo(handle->txDmaHandle->base, handle->txDmaHandle->channel, kEDMA_ModuloDisable,
+ (edma_modulo_t)power);
+ EDMA_SetCallback(handle->txDmaHandle, FLEXSPI_TransferEDMACallback,
+ &s_edmaPrivateHandle[FLEXSPI_GetInstance(base)]);
+ EDMA_StartTransfer(handle->txDmaHandle);
+
+ /* Enable FLEXSPI TX EDMA. */
+ FLEXSPI_EnableTxDMA(base, true);
+
+ /* Start Transfer. */
+ base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
+ }
+ else if (xfer->cmdType == kFLEXSPI_Read)
+ {
+ handle->count = (uint8_t)((base->IPRXFCR & FLEXSPI_IPRXFCR_RXWMRK_MASK) >> FLEXSPI_IPRXFCR_RXWMRK_SHIFT) + 1U;
+
+ if (xfer->dataSize < 8U * (uint32_t)handle->count)
+ {
+ handle->nbytes = (uint8_t)xfer->dataSize;
+ }
+ else
+ {
+ /* Check the handle->count is power of 2 */
+ if (((handle->count) & (handle->count - 1U)) != 0U)
+ {
+ return kStatus_InvalidArgument;
+ }
+ /* Store the initially configured eDMA minor byte transfer count into the FLEXSPI handle */
+ handle->nbytes = (8U * handle->count);
+ }
+
+ power = FLEXSPI_CalculatePower(8U * handle->count);
+
+ /* Prepare transfer. */
+ EDMA_PrepareTransfer(&xferConfig, (void *)(uint32_t *)FLEXSPI_GetRxFifoAddress(base), (uint32_t)handle->nsize,
+ xfer->data, (uint32_t)handle->nsize, (uint32_t)handle->nbytes, xfer->dataSize,
+ kEDMA_MemoryToMemory);
+
+ /* Submit transfer. */
+ (void)EDMA_SubmitTransfer(handle->rxDmaHandle, &xferConfig);
+ EDMA_SetModulo(handle->txDmaHandle->base, handle->txDmaHandle->channel, (edma_modulo_t)power,
+ kEDMA_ModuloDisable);
+ EDMA_SetCallback(handle->rxDmaHandle, FLEXSPI_TransferEDMACallback, &s_edmaPrivateHandle[instance]);
+ EDMA_StartTransfer(handle->rxDmaHandle);
+
+ /* Enable FLEXSPI RX EDMA. */
+ FLEXSPI_EnableRxDMA(base, true);
+
+ /* Start Transfer. */
+ base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
+ }
+ else
+ {
+ /* Start Transfer. */
+ base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
+ /* Wait for bus idle. */
+ while (!FLEXSPI_GetBusIdleStatus(base))
+ {
+ }
+ result = FLEXSPI_CheckAndClearError(base, base->INTR);
+
+ handle->state = kFLEXSPI_Idle;
+
+ if (handle->completionCallback != NULL)
+ {
+ handle->completionCallback(base, handle, result, handle->userData);
+ }
+ }
+
+ return result;
+}
+
+/*!
+ * brief Aborts the transfer data using eDMA.
+ *
+ * This function aborts the transfer data using eDMA.
+ *
+ * param base FLEXSPI peripheral base address.
+ * param handle Pointer to flexspi_edma_handle_t structure
+ */
+void FLEXSPI_TransferAbortEDMA(FLEXSPI_Type *base, flexspi_edma_handle_t *handle)
+{
+ assert(handle);
+
+ if ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXDMAEN_MASK) != 0x00U)
+ {
+ FLEXSPI_EnableTxDMA(base, false);
+ EDMA_AbortTransfer(handle->txDmaHandle);
+ }
+
+ if ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXDMAEN_MASK) != 0x00U)
+ {
+ FLEXSPI_EnableRxDMA(base, false);
+ EDMA_AbortTransfer(handle->rxDmaHandle);
+ }
+
+ handle->state = kFLEXSPI_Idle;
+}
+
+status_t FLEXSPI_TransferGetTransferCountEDMA(FLEXSPI_Type *base, flexspi_edma_handle_t *handle, size_t *count)
+{
+ assert(handle);
+ assert(count);
+
+ status_t result = kStatus_Success;
+
+ if (handle->state != (uint32_t)kFLEXSPI_Busy)
+ {
+ result = kStatus_NoTransferInProgress;
+ }
+ else
+ {
+ if ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXDMAEN_MASK) != 0x00U)
+ {
+ *count = (handle->transferSize -
+ (uint32_t)handle->nbytes *
+ EDMA_GetRemainingMajorLoopCount(handle->rxDmaHandle->base, handle->rxDmaHandle->channel));
+ }
+ else if ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXDMAEN_MASK) != 0x00U)
+ {
+ *count = (handle->transferSize -
+ (uint32_t)handle->nbytes *
+ EDMA_GetRemainingMajorLoopCount(handle->txDmaHandle->base, handle->txDmaHandle->channel));
+ }
+ else
+ {
+ ; /* Intentional empty for MISRA C-2012 rule 15.7. */
+ }
+ }
+
+ return result;
+}
diff --git a/bsps/arm/imxrt/mcux-sdk/drivers/flexspi/fsl_flexspi_edma.h b/bsps/arm/imxrt/mcux-sdk/drivers/flexspi/fsl_flexspi_edma.h
new file mode 100644
index 0000000000..6b939970e2
--- /dev/null
+++ b/bsps/arm/imxrt/mcux-sdk/drivers/flexspi/fsl_flexspi_edma.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2020 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _FSL_FLEXSPI_EDMA_H_
+#define _FSL_FLEXSPI_EDMA_H_
+
+#include "fsl_flexspi.h"
+#if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT
+#include "fsl_dmamux.h"
+#endif
+#include "fsl_edma.h"
+
+/*!
+ * @addtogroup flexspi_edma
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @name Driver version */
+/*@{*/
+/*! @brief FLEXSPI EDMA driver version 2.3.2. */
+#define FSL_FLEXSPI_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 3, 2))
+/*@}*/
+
+typedef struct _flexspi_edma_handle flexspi_edma_handle_t;
+
+/*! @brief FLEXSPI eDMA transfer callback function for finish and error */
+typedef void (*flexspi_edma_callback_t)(FLEXSPI_Type *base,
+ flexspi_edma_handle_t *handle,
+ status_t status,
+ void *userData);
+
+/*! @brief eDMA transfer configuration */
+typedef enum _flexspi_edma_ntransfer_size
+{
+ kFLEXPSI_EDMAnSize1Bytes = 0x1U, /*!< Source/Destination data transfer size is 1 byte every time */
+ kFLEXPSI_EDMAnSize2Bytes = 0x2U, /*!< Source/Destination data transfer size is 2 bytes every time */
+ kFLEXPSI_EDMAnSize4Bytes = 0x4U, /*!< Source/Destination data transfer size is 4 bytes every time */
+ kFLEXPSI_EDMAnSize8Bytes = 0x8U, /*!< Source/Destination data transfer size is 8 bytes every time */
+ kFLEXPSI_EDMAnSize32Bytes = 0x20U, /*!< Source/Destination data transfer size is 32 bytes every time */
+} flexspi_edma_transfer_nsize_t;
+
+/*! @brief FLEXSPI DMA transfer handle, users should not touch the content of the handle.*/
+struct _flexspi_edma_handle
+{
+ edma_handle_t *txDmaHandle; /*!< eDMA handler for FLEXSPI Tx. */
+ edma_handle_t *rxDmaHandle; /*!< eDMA handler for FLEXSPI Rx. */
+ size_t transferSize; /*!< Bytes need to transfer. */
+ flexspi_edma_transfer_nsize_t nsize; /*!< eDMA SSIZE/DSIZE in each transfer. */
+ uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
+ uint8_t count; /*!< The transfer data count in a DMA request. */
+ uint32_t state; /*!< Internal state for FLEXSPI eDMA transfer. */
+ flexspi_edma_callback_t completionCallback; /*!< A callback function called after the eDMA transfer is finished. */
+ void *userData; /*!< User callback parameter */
+};
+
+/*******************************************************************************
+ * APIs
+ ******************************************************************************/
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*!
+ * @name FLEXSPI eDMA Transactional
+ * @{
+ */
+
+/*!
+ * @brief Initializes the FLEXSPI handle for transfer which is used in transactional functions and set the callback.
+ *
+ * @param base FLEXSPI peripheral base address
+ * @param handle Pointer to flexspi_edma_handle_t structure
+ * @param callback FLEXSPI callback, NULL means no callback.
+ * @param userData User callback function data.
+ * @param txDmaHandle User requested DMA handle for TX DMA transfer.
+ * @param rxDmaHandle User requested DMA handle for RX DMA transfer.
+ */
+void FLEXSPI_TransferCreateHandleEDMA(FLEXSPI_Type *base,
+ flexspi_edma_handle_t *handle,
+ flexspi_edma_callback_t callback,
+ void *userData,
+ edma_handle_t *txDmaHandle,
+ edma_handle_t *rxDmaHandle);
+
+/*!
+ * @brief Update FLEXSPI EDMA transfer source data transfer size(SSIZE) and destination data transfer size(DSIZE).
+ *
+ * @param base FLEXSPI peripheral base address
+ * @param handle Pointer to flexspi_edma_handle_t structure
+ * @param nsize FLEXSPI DMA transfer data transfer size(SSIZE/DSIZE), by default the size is
+ * kFLEXPSI_EDMAnSize1Bytes(one byte).
+ * @see flexspi_edma_transfer_nsize_t .
+ */
+void FLEXSPI_TransferUpdateSizeEDMA(FLEXSPI_Type *base,
+ flexspi_edma_handle_t *handle,
+ flexspi_edma_transfer_nsize_t nsize);
+
+/*!
+ * @brief Transfers FLEXSPI data using an eDMA non-blocking method.
+ *
+ * This function writes/receives data to/from the FLEXSPI transmit/receive FIFO. This function is non-blocking.
+ * @param base FLEXSPI peripheral base address.
+ * @param handle Pointer to flexspi_edma_handle_t structure
+ * @param xfer FLEXSPI transfer structure.
+ * @retval kStatus_FLEXSPI_Busy FLEXSPI is busy transfer.
+ * @retval kStatus_InvalidArgument The watermark configuration is invalid, the watermark should be power of
+ 2 to do successfully EDMA transfer.
+ * @retval kStatus_Success FLEXSPI successfully start edma transfer.
+ */
+status_t FLEXSPI_TransferEDMA(FLEXSPI_Type *base, flexspi_edma_handle_t *handle, flexspi_transfer_t *xfer);
+
+/*!
+ * @brief Aborts the transfer data using eDMA.
+ *
+ * This function aborts the transfer data using eDMA.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param handle Pointer to flexspi_edma_handle_t structure
+ */
+void FLEXSPI_TransferAbortEDMA(FLEXSPI_Type *base, flexspi_edma_handle_t *handle);
+
+/*!
+ * @brief Gets the transferred counts of transfer.
+ *
+ * @param base FLEXSPI peripheral base address.
+ * @param handle Pointer to flexspi_edma_handle_t structure.
+ * @param count Bytes transfer.
+ * @retval kStatus_Success Succeed get the transfer count.
+ * @retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
+ */
+status_t FLEXSPI_TransferGetTransferCountEDMA(FLEXSPI_Type *base, flexspi_edma_handle_t *handle, size_t *count);
+
+/* @} */
+
+#if defined(__cplusplus)
+}
+#endif
+
+/* @} */
+
+#endif /* _FSL_FLEXSPI_EDMA_H_ */