123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821 |
- /*
- * Copyright (c) 2016, Freescale Semiconductor, Inc.
- * Copyright 2016-2017 NXP
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * o Redistributions of source code must retain the above copyright notice, this list
- * of conditions and the following disclaimer.
- *
- * o Redistributions in binary form must reproduce the above copyright notice, this
- * list of conditions and the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- *
- * o Neither the name of the copyright holder nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include "fsl_flexspi.h"
- /*******************************************************************************
- * Definitations
- ******************************************************************************/
- #define FREQ_1MHz (1000000UL)
- #define FLEXSPI_DLLCR_DEFAULT (0x100UL)
- #define FLEXSPI_LUT_KEY_VAL (0x5AF05AF0ul)
- enum
- {
- kFLEXSPI_DelayCellUnitMin = 75, /* 75ps. */
- kFLEXSPI_DelayCellUnitMax = 225, /* 225ps. */
- };
- /*! @brief Common sets of flags used by the driver. */
- enum _flexspi_flag_constants
- {
- /*! IRQ sources enabled by the non-blocking transactional API. */
- kIrqFlags = kFLEXSPI_IpTxFifoWatermarkEmpltyFlag | kFLEXSPI_IpRxFifoWatermarkAvailableFlag |
- kFLEXSPI_SequenceExecutionTimeoutFlag | kFLEXSPI_IpCommandSequenceErrorFlag |
- kFLEXSPI_IpCommandGrantTimeoutFlag | kFLEXSPI_IpCommandExcutionDoneFlag,
- /*! Errors to check for. */
- kErrorFlags = kFLEXSPI_SequenceExecutionTimeoutFlag | kFLEXSPI_IpCommandSequenceErrorFlag |
- kFLEXSPI_IpCommandGrantTimeoutFlag,
- };
- enum _flexspi_transfer_state
- {
- 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, void *flexspiHandle);
- /*******************************************************************************
- * Prototypes
- ******************************************************************************/
- /*!
- * @brief Get the instance number for FLEXSPI.
- *
- * @param base FLEXSPI base pointer.
- */
- uint32_t FLEXSPI_GetInstance(FLEXSPI_Type *base);
- /*!
- * @brief Configure flash A/B sample clock DLL.
- *
- * @param base FLEXSPI base pointer.
- * @param config Flash configuration parameters.
- */
- static uint32_t FLEXSPI_ConfigureDll(FLEXSPI_Type *base, flexspi_device_config_t *config);
- /*!
- * @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);
- /*******************************************************************************
- * Variables
- ******************************************************************************/
- /*! @brief Pointers to flexspi handles for each instance. */
- static void *s_flexspiHandle[FSL_FEATURE_SOC_FLEXSPI_COUNT];
- /*! @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 */
- /*******************************************************************************
- * Code
- ******************************************************************************/
- uint32_t FLEXSPI_GetInstance(FLEXSPI_Type *base)
- {
- uint32_t instance;
- /* Find the instance index from base address mappings. */
- for (instance = 0; instance < FSL_FEATURE_SOC_FLEXSPI_COUNT; instance++)
- {
- if (s_flexspiBases[instance] == base)
- {
- break;
- }
- }
- assert(instance < FSL_FEATURE_SOC_FLEXSPI_COUNT);
- return instance;
- }
- static uint32_t FLEXSPI_ConfigureDll(FLEXSPI_Type *base, flexspi_device_config_t *config)
- {
- bool isUnifiedConfig = true;
- uint32_t flexspiDllValue;
- uint32_t dllValue;
- uint32_t temp;
- uint8_t rxSampleClock = (base->MCR0 & FLEXSPI_MCR0_RXCLKSRC_MASK) >> FLEXSPI_MCR0_RXCLKSRC_SHIFT;
- switch (rxSampleClock)
- {
- case kFLEXSPI_ReadSampleClkLoopbackInternally:
- case kFLEXSPI_ReadSampleClkLoopbackFromDqsPad:
- case kFLEXSPI_ReadSampleClkLoopbackFromSckPad:
- isUnifiedConfig = true;
- break;
- case kFLEXSPI_ReadSampleClkExternalInputFromDqsPad:
- if (config->isSck2Enabled)
- {
- isUnifiedConfig = true;
- }
- else
- {
- isUnifiedConfig = false;
- }
- break;
- default:
- break;
- }
- if (isUnifiedConfig)
- {
- flexspiDllValue = FLEXSPI_DLLCR_DEFAULT; /* 1 fixed delay cells in DLL delay chain) */
- }
- else
- {
- if (config->flexspiRootClk >= 100 * FREQ_1MHz)
- {
- /* DLLEN = 1, SLVDLYTARGET = 0xF, */
- flexspiDllValue = FLEXSPI_DLLCR_DLLEN(1) | FLEXSPI_DLLCR_SLVDLYTARGET(0x0F);
- }
- else
- {
- temp = config->dataValidTime * 1000; /* Convert data valid time in ns to ps. */
- dllValue = temp / kFLEXSPI_DelayCellUnitMin;
- if (dllValue * 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 &= kErrorFlags;
- if (status)
- {
- /* Select the correct error code.. */
- if (status & kFLEXSPI_SequenceExecutionTimeoutFlag)
- {
- result = kStatus_FLEXSPI_SequenceExecutionTimeout;
- }
- else if (status & kFLEXSPI_IpCommandSequenceErrorFlag)
- {
- result = kStatus_FLEXSPI_IpCommandSequenceError;
- }
- else if (status & 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;
- }
- 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 */
- CLOCK_EnableClock(s_flexspiClock[FLEXSPI_GetInstance(base)]);
- #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
- /* 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) |
- FLEXSPI_MCR0_COMBINATIONEN(config->enableCombination) |
- FLEXSPI_MCR0_ATDFEN(config->ahbConfig.enableAHBWriteIpTxFifo) |
- FLEXSPI_MCR0_ATDFEN(config->ahbConfig.enableAHBWriteIpRxFifo) | 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 = FLEXSPI_MCR2_RESUMEWAIT(config->ahbConfig.resumeWaitCycle) |
- FLEXSPI_MCR2_SCKBDIFFOPT(config->enableSckBDiffOpt) |
- FLEXSPI_MCR2_SAMEDEVICEEN(config->enableSameConfigForAll) |
- FLEXSPI_MCR2_CLRAHBBUFOPT(config->ahbConfig.enableClearAHBBufferOpt);
- base->MCR2 = configValue;
- /* Configure AHB control items. */
- base->AHBCR = FLEXSPI_AHBCR_PREFETCHEN(config->ahbConfig.enableAHBPrefetch) |
- FLEXSPI_AHBCR_BUFFERABLEEN(config->ahbConfig.enableAHBBufferable) |
- FLEXSPI_AHBCR_CACHABLEEN(config->ahbConfig.enableAHBCachable);
- /* Configure AHB rx buffers. */
- for (i = 0; i < FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT - 1; i++)
- {
- base->AHBRXBUFCR0[i] = FLEXSPI_AHBRXBUFCR0_PRIORITY(config->ahbConfig.buffer[i].priority) |
- FLEXSPI_AHBRXBUFCR0_MSTRID(config->ahbConfig.buffer[i].masterIndex) |
- FLEXSPI_AHBRXBUFCR0_BUFSZ(config->ahbConfig.buffer[i].bufferSize / 8);
- }
- /* Configure IP Fifo watermarks. */
- base->IPRXFCR |= FLEXSPI_IPRXFCR_RXWMRK(config->rxWatermark / 8 - 1);
- base->IPTXFCR |= FLEXSPI_IPRXFCR_RXWMRK(config->txWatermark / 8 - 1);
- }
- void FLEXSPI_GetDefaultConfig(flexspi_config_t *config)
- {
- config->rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackInternally;
- config->enableSckFreeRunning = false;
- config->enableCombination = false;
- config->enableDoze = true;
- config->enableHalfSpeedAccess = false;
- config->enableSckBDiffOpt = false;
- config->enableSameConfigForAll = false;
- config->seqTimeoutCycle = 0xFFFFU;
- config->ipGrantTimeoutCycle = 0xFFU;
- config->txWatermark = 8;
- config->rxWatermark = 8;
- config->ahbConfig.enableAHBWriteIpTxFifo = false;
- config->ahbConfig.enableAHBWriteIpRxFifo = false;
- config->ahbConfig.ahbGrantTimeoutCycle = 0xFFU;
- config->ahbConfig.ahbBusTimeoutCycle = 0xFFFFU;
- config->ahbConfig.resumeWaitCycle = 0x20U;
- memset(config->ahbConfig.buffer, 0, sizeof(config->ahbConfig.buffer));
- config->ahbConfig.enableClearAHBBufferOpt = false;
- config->ahbConfig.enableAHBPrefetch = false;
- config->ahbConfig.enableAHBBufferable = false;
- config->ahbConfig.enableAHBCachable = false;
- }
- void FLEXSPI_Deinit(FLEXSPI_Type *base)
- {
- /* Reset peripheral. */
- FLEXSPI_SoftwareReset(base);
- }
- void FLEXSPI_SetFlashConfig(FLEXSPI_Type *base, flexspi_device_config_t *config, flexspi_port_t port)
- {
- uint32_t configValue = 0;
- uint8_t index = port >> 1; /* PortA with index 0, PortB with index 1. */
- /* Wait for bus idle before change flash configuration. */
- while (!FLEXSPI_GetBusIdleStatus(base))
- {
- }
- /* Configure flash size. */
- base->FLSHCR0[index] = 0;
- base->FLSHCR0[port] = config->flashSize;
- /* 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_AWRSEQID_MASK);
- configValue |=
- FLEXSPI_FLSHCR2_AWRWAITUNIT(config->AHBWriteWaitUnit) | FLEXSPI_FLSHCR2_AWRWAIT(config->AHBWriteWaitInterval);
- if (config->AWRSeqNumber > 0U)
- {
- configValue |=
- FLEXSPI_FLSHCR2_AWRSEQID(config->AWRSeqIndex) | FLEXSPI_FLSHCR2_AWRSEQNUM(config->AWRSeqNumber - 1U);
- }
- if (config->ARDSeqNumber > 0U)
- {
- configValue |=
- FLEXSPI_FLSHCR2_ARDSEQID(config->ARDSeqIndex) | FLEXSPI_FLSHCR2_ARDSEQNUM(config->ARDSeqNumber - 1U);
- }
- base->FLSHCR2[port] = configValue;
- /* Configure DLL. */
- base->DLLCR[index] = FLEXSPI_ConfigureDll(base, config);
- /* Configure write mask. */
- if (index == 0) /*PortA*/
- {
- base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMENA_MASK;
- base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMENA(config->enableWriteMask);
- }
- else
- {
- base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMENB_MASK;
- base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMENB(config->enableWriteMask);
- }
- /* Exit stop mode. */
- base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
- }
- void FLEXSPI_UpdateLUT(FLEXSPI_Type *base, uint32_t index, const uint32_t *cmd, uint32_t count)
- {
- assert(index < 64U);
- uint8_t i = 0;
- volatile uint32_t *lutBase;
- /* Wait for bus idle before change flash configuration. */
- while (!FLEXSPI_GetBusIdleStatus(base))
- {
- }
- /* Unlock LUT for update. */
- base->LUTKEY = FLEXSPI_LUT_KEY_VAL;
- base->LUTCR = 0x02;
- lutBase = &base->LUT[index];
- for (i = index; i < count; i++)
- {
- *lutBase++ = *cmd++;
- }
- /* Lock LUT. */
- base->LUTKEY = FLEXSPI_LUT_KEY_VAL;
- base->LUTCR = 0x01;
- }
- status_t FLEXSPI_WriteBlocking(FLEXSPI_Type *base, uint32_t *buffer, size_t size)
- {
- uint8_t txWatermark = ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXWMRK_MASK) >> FLEXSPI_IPTXFCR_TXWMRK_SHIFT) + 1;
- uint32_t status;
- status_t result = kStatus_Success;
- uint32_t i = 0;
- /* Send data buffer */
- while (size)
- {
- /* Wait until there is room in the fifo. This also checks for errors. */
- while (!((status = base->INTR) & kFLEXSPI_IpTxFifoWatermarkEmpltyFlag))
- {
- }
- result = FLEXSPI_CheckAndClearError(base, status);
- if (result)
- {
- return result;
- }
- /* Write watermark level data into tx fifo . */
- if (size >= 8 * txWatermark)
- {
- for (i = 0; i < 2 * txWatermark; i++)
- {
- base->TFDR[i] = *buffer++;
- }
- size = size - 8 * txWatermark;
- }
- else
- {
- for (i = 0; i < (size / 4 + 1); i++)
- {
- base->TFDR[i] = *buffer++;
- }
- size = 0;
- }
- /* Push a watermark level datas into IP TX FIFO. */
- base->INTR |= kFLEXSPI_IpTxFifoWatermarkEmpltyFlag;
- }
- return result;
- }
- status_t FLEXSPI_ReadBlocking(FLEXSPI_Type *base, uint32_t *buffer, size_t size)
- {
- uint8_t rxWatermark = ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXWMRK_MASK) >> FLEXSPI_IPRXFCR_RXWMRK_SHIFT) + 1;
- uint32_t status;
- status_t result = kStatus_Success;
- uint32_t i = 0;
- /* Send data buffer */
- while (size)
- {
- if (size >= 8 * rxWatermark)
- {
- /* Wait until there is room in the fifo. This also checks for errors. */
- while (!((status = base->INTR) & kFLEXSPI_IpRxFifoWatermarkAvailableFlag))
- {
- result = FLEXSPI_CheckAndClearError(base, status);
- if (result)
- {
- return result;
- }
- }
- }
- 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 (result)
- {
- return result;
- }
- }
- }
- result = FLEXSPI_CheckAndClearError(base, base->INTR);
- if (result)
- {
- return result;
- }
- /* Read watermark level data from rx fifo . */
- if (size >= 8 * rxWatermark)
- {
- for (i = 0; i < 2 * rxWatermark; i++)
- {
- *buffer++ = base->RFDR[i];
- }
- size = size - 8 * rxWatermark;
- }
- else
- {
- for (i = 0; i < (size / 4 + 1); i++)
- {
- *buffer++ = base->RFDR[i];
- }
- size = 0;
- }
- /* Pop out a watermark level datas from IP RX FIFO. */
- base->INTR |= kFLEXSPI_IpRxFifoWatermarkAvailableFlag;
- }
- return result;
- }
- 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 tranfer. */
- base->INTR |= FLEXSPI_INTR_AHBCMDERR_MASK | FLEXSPI_INTR_IPCMDERR_MASK | FLEXSPI_INTR_AHBCMDGE_MASK |
- FLEXSPI_INTR_IPCMDGE_MASK;
- /* Configure base addresss. */
- 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(xfer->seqIndex) | FLEXSPI_IPCR1_ISEQNUM(xfer->SeqNumber - 1);
- base->IPCR1 = configValue;
- /* Start Transfer. */
- base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
- if ((xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config))
- {
- result = FLEXSPI_WriteBlocking(base, xfer->data, xfer->dataSize);
- }
- else if (xfer->cmdType == kFLEXSPI_Read)
- {
- result = FLEXSPI_ReadBlocking(base, xfer->data, xfer->dataSize);
- }
- else
- {
- }
- /* Wait for bus idle. */
- while (!FLEXSPI_GetBusIdleStatus(base))
- {
- }
- if (xfer->cmdType == kFLEXSPI_Command)
- {
- result = FLEXSPI_CheckAndClearError(base, base->INTR);
- }
- return result;
- }
- void FLEXSPI_TransferCreateHandle(FLEXSPI_Type *base,
- flexspi_handle_t *handle,
- flexspi_transfer_callback_t callback,
- void *userData)
- {
- assert(handle);
- uint32_t instance = FLEXSPI_GetInstance(base);
- /* Zero handle. */
- memset(handle, 0, sizeof(*handle));
- /* Set callback and userData. */
- handle->completionCallback = callback;
- handle->userData = userData;
- /* Save the context in global variables to support the double weak mechanism. */
- s_flexspiHandle[instance] = handle;
- /* Enable NVIC interrupt. */
- EnableIRQ(s_flexspiIrqs[instance]);
- }
- 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(handle);
- assert(xfer);
- /* Check if the I2C bus is idle - if not return busy status. */
- if (handle->state != kFLEXSPI_Idle)
- {
- result = kStatus_FLEXSPI_Busy;
- }
- else
- {
- handle->data = xfer->data;
- handle->dataSize = xfer->dataSize;
- handle->transferTotalSize = xfer->dataSize;
- handle->state = (xfer->cmdType == kFLEXSPI_Read) ? kFLEXSPI_BusyRead : 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 tranfer. */
- base->INTR |= FLEXSPI_INTR_AHBCMDERR_MASK | FLEXSPI_INTR_IPCMDERR_MASK | FLEXSPI_INTR_AHBCMDGE_MASK |
- FLEXSPI_INTR_IPCMDGE_MASK;
- /* Configure base addresss. */
- 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(xfer->SeqNumber - 1);
- base->IPCR1 = configValue;
- /* Start Transfer. */
- base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
- if (handle->state == kFLEXSPI_BusyRead)
- {
- FLEXSPI_EnableInterrupts(base, kFLEXSPI_IpRxFifoWatermarkAvailableFlag |
- kFLEXSPI_SequenceExecutionTimeoutFlag |
- kFLEXSPI_IpCommandSequenceErrorFlag |
- kFLEXSPI_IpCommandGrantTimeoutFlag | kFLEXSPI_IpCommandExcutionDoneFlag);
- }
- else
- {
- FLEXSPI_EnableInterrupts(base, kFLEXSPI_IpTxFifoWatermarkEmpltyFlag |
- kFLEXSPI_SequenceExecutionTimeoutFlag |
- kFLEXSPI_IpCommandSequenceErrorFlag |
- kFLEXSPI_IpCommandGrantTimeoutFlag | kFLEXSPI_IpCommandExcutionDoneFlag);
- }
- }
- return result;
- }
- status_t FLEXSPI_TransferGetCount(FLEXSPI_Type *base, flexspi_handle_t *handle, size_t *count)
- {
- assert(handle);
- status_t result = kStatus_Success;
- if (handle->state == kFLEXSPI_Idle)
- {
- result = kStatus_NoTransferInProgress;
- }
- else
- {
- *count = handle->transferTotalSize - handle->dataSize;
- }
- return result;
- }
- void FLEXSPI_TransferAbort(FLEXSPI_Type *base, flexspi_handle_t *handle)
- {
- assert(handle);
- FLEXSPI_DisableInterrupts(base, kIrqFlags);
- handle->state = kFLEXSPI_Idle;
- }
- void FLEXSPI_TransferHandleIRQ(FLEXSPI_Type *base, flexspi_handle_t *handle)
- {
- uint8_t status;
- status_t result;
- uint8_t txWatermark;
- uint8_t rxWatermark;
- uint8_t i = 0;
- status = base->INTR;
- result = FLEXSPI_CheckAndClearError(base, status);
- if ((result != kStatus_Success) && (handle->completionCallback != NULL))
- {
- FLEXSPI_TransferAbort(base, handle);
- if (handle->completionCallback)
- {
- handle->completionCallback(base, handle, result, handle->userData);
- }
- return;
- }
- if ((status & kFLEXSPI_IpRxFifoWatermarkAvailableFlag) && (handle->state == kFLEXSPI_BusyRead))
- {
- rxWatermark = ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXWMRK_MASK) >> FLEXSPI_IPRXFCR_RXWMRK_SHIFT) + 1;
- /* Read watermark level data from rx fifo . */
- if (handle->dataSize >= 8 * rxWatermark)
- {
- /* Read watermark level data from rx fifo . */
- for (i = 0; i < 2 * rxWatermark; i++)
- {
- *handle->data++ = base->RFDR[i];
- }
- handle->dataSize = handle->dataSize - 8 * rxWatermark;
- }
- else
- {
- for (i = 0; i < (handle->dataSize / 4 + 1); i++)
- {
- *handle->data++ = base->RFDR[i];
- }
- handle->dataSize = 0;
- }
- /* Pop out a watermark level datas from IP RX FIFO. */
- base->INTR |= kFLEXSPI_IpRxFifoWatermarkAvailableFlag;
- }
- if (status & kFLEXSPI_IpCommandExcutionDoneFlag)
- {
- base->INTR |= kFLEXSPI_IpCommandExcutionDoneFlag;
- FLEXSPI_TransferAbort(base, handle);
- if (handle->completionCallback)
- {
- handle->completionCallback(base, handle, kStatus_Success, handle->userData);
- }
- }
- /* TX FIFO empty interrupt, push watermark level data into tx FIFO. */
- if ((status & kFLEXSPI_IpTxFifoWatermarkEmpltyFlag) && (handle->state == kFLEXSPI_BusyWrite))
- {
- if (handle->dataSize)
- {
- txWatermark = ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXWMRK_MASK) >> FLEXSPI_IPTXFCR_TXWMRK_SHIFT) + 1;
- /* Write watermark level data into tx fifo . */
- if (handle->dataSize >= 8 * txWatermark)
- {
- for (i = 0; i < 2 * txWatermark; i++)
- {
- base->TFDR[i] = *handle->data++;
- }
- handle->dataSize = handle->dataSize - 8 * txWatermark;
- }
- else
- {
- for (i = 0; i < (handle->dataSize / 4 + 1); i++)
- {
- base->TFDR[i] = *handle->data++;
- }
- handle->dataSize = 0;
- }
- /* Push a watermark level datas into IP TX FIFO. */
- base->INTR |= kFLEXSPI_IpTxFifoWatermarkEmpltyFlag;
- }
- }
- else
- {
- }
- }
- #if defined(FLEXSPI)
- void FLEXSPI_DriverIRQHandler(void)
- {
- FLEXSPI_TransferHandleIRQ(FLEXSPI, s_flexspiHandle[0]);
- /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
- exception return operation might vector to incorrect interrupt */
- #if defined __CORTEX_M && (__CORTEX_M == 4U)
- __DSB();
- #endif
- }
- #endif
- #if defined(FLEXSPI0)
- void FLEXSPI0_DriverIRQHandler(void)
- {
- FLEXSPI_TransferHandleIRQ(FLEXSPI0, s_flexspiHandle[0]);
- /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
- exception return operation might vector to incorrect interrupt */
- #if defined __CORTEX_M && (__CORTEX_M == 4U)
- __DSB();
- #endif
- }
- #endif
- #if defined(FLEXSPI1)
- void FLEXSPI1_DriverIRQHandler(void)
- {
- FLEXSPI_TransferHandleIRQ(FLEXSPI1, s_flexspiHandle[1]);
- /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
- exception return operation might vector to incorrect interrupt */
- #if defined __CORTEX_M && (__CORTEX_M == 4U)
- __DSB();
- #endif
- }
- #endif
|