/***************************************************************************** * Copyright (c) 2019, Nations Technologies Inc. * * All rights reserved. * **************************************************************************** * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the disclaimer below. * * Nations' name may not be used to endorse or promote products derived from * this software without specific prior written permission. * * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************/ /** * @file n32g45x_qspi.c * @author Nations * @version v1.0.1 * * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. */ #include "n32g45x_qspi.h" /** * @brief Control QSPI function switch. * @param cmd select enable or disable QSPI. */ void QSPI_Cmd(bool cmd) { if (cmd != DISABLE) { QSPI->SLAVE_EN = QSPI_SLAVE_EN_SEN; QSPI->EN = QSPI_EN_QEN; } else { QSPI->SLAVE_EN &= ~QSPI_SLAVE_EN_SEN; QSPI->EN &= ~QSPI_EN_QEN; } } /** * @brief Control QSPI XIP function switch. * @param cmd select enable or disable QSPI XIP. */ void QSPI_XIP_Cmd(bool cmd) { if (cmd != DISABLE) { QSPI->XIP_SLAVE_EN = QSPI_XIP_SLAVE_EN_SEN; } else { QSPI->XIP_SLAVE_EN &= ~QSPI_XIP_SLAVE_EN_SEN; } } /** * @brief Deinitializes the QSPI peripheral registers to its default reset values. */ void QSPI_DeInit(void) { RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_QSPI, ENABLE); RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_QSPI, DISABLE); } /** * @brief Merge configuration from the buffer of QSPI para struct, then write it into related registers. * @param QSPI_InitStruct pointer to buffer of QSPI para struct. */ void QspiInitConfig(QSPI_InitType* QSPI_InitStruct) { uint32_t tmpregister = 0; /* Check the parameters */ assert_param(IS_QSPI_SPI_FRF(QSPI_InitStruct->SPI_FRF)); assert_param(IS_QSPI_CFS(QSPI_InitStruct->CFS)); assert_param(IS_QSPI_SSTE(QSPI_InitStruct->SSTE)); assert_param(IS_QSPI_TMOD(QSPI_InitStruct->TMOD)); assert_param(IS_QSPI_SCPOL(QSPI_InitStruct->SCPOL)); assert_param(IS_QSPI_SCPH(QSPI_InitStruct->SCPH)); assert_param(IS_QSPI_FRF(QSPI_InitStruct->FRF)); assert_param(IS_QSPI_DFS(QSPI_InitStruct->DFS)); assert_param(IS_QSPI_MWMOD(QSPI_InitStruct->MWMOD)); assert_param(IS_QSPI_MC_DIR(QSPI_InitStruct->MC_DIR)); assert_param(IS_QSPI_MHS_EN(QSPI_InitStruct->MHS_EN)); assert_param(IS_QSPI_SES(QSPI_InitStruct->SES)); assert_param(IS_QSPI_SDCN(QSPI_InitStruct->SDCN)); assert_param(IS_QSPI_ENH_CLK_STRETCH_EN(QSPI_InitStruct->ENHANCED_CLK_STRETCH_EN)); assert_param(IS_QSPI_ENH_XIP_MBL(QSPI_InitStruct->ENHANCED_XIP_MBL)); assert_param(IS_QSPI_ENH_XIP_CT_EN(QSPI_InitStruct->ENHANCED_XIP_CT_EN)); assert_param(IS_QSPI_ENH_XIP_INST_EN(QSPI_InitStruct->ENHANCED_XIP_INST_EN)); assert_param(IS_QSPI_ENH_XIP_DFS_HC(QSPI_InitStruct->ENHANCED_XIP_DFS_HC)); assert_param(IS_QSPI_ENH_INST_DDR_EN(QSPI_InitStruct->ENHANCED_INST_DDR_EN)); assert_param(IS_QSPI_ENH_SPI_DDR_EN(QSPI_InitStruct->ENHANCED_SPI_DDR_EN)); assert_param(IS_QSPI_ENH_WAIT_CYCLES(QSPI_InitStruct->ENHANCED_WAIT_CYCLES)); assert_param(IS_QSPI_ENH_INST_L(QSPI_InitStruct->ENHANCED_INST_L)); assert_param(IS_QSPI_ENH_MD_BIT_EN(QSPI_InitStruct->ENHANCED_MD_BIT_EN)); assert_param(IS_QSPI_ENH_ADDR_LEN(QSPI_InitStruct->ENHANCED_ADDR_LEN)); assert_param(IS_QSPI_ENH_TRANS_TYPE(QSPI_InitStruct->ENHANCED_TRANS_TYPE)); assert_param(IS_QSPI_XIP_MBL(QSPI_InitStruct->XIP_MBL)); assert_param(IS_QSPI_XIP_CT_EN(QSPI_InitStruct->XIP_CT_EN)); assert_param(IS_QSPI_XIP_INST_EN(QSPI_InitStruct->XIP_INST_EN)); assert_param(IS_QSPI_INST_DDR_EN(QSPI_InitStruct->XIP_INST_DDR_EN)); assert_param(IS_QSPI_DDR_EN(QSPI_InitStruct->XIP_DDR_EN)); assert_param(IS_QSPI_XIP_DFS_HC(QSPI_InitStruct->XIP_DFS_HC)); assert_param(IS_QSPI_XIP_WAIT_CYCLES(QSPI_InitStruct->XIP_WAIT_CYCLES)); assert_param(IS_QSPI_XIP_MD_BIT_EN(QSPI_InitStruct->XIP_MD_BITS_EN)); assert_param(IS_QSPI_XIP_INST_L(QSPI_InitStruct->XIP_INST_L)); assert_param(IS_QSPI_XIP_ADDR_LEN(QSPI_InitStruct->XIP_ADDR_LEN)); assert_param(IS_QSPI_XIP_TRANS_TYPE(QSPI_InitStruct->XIP_TRANS_TYPE)); assert_param(IS_QSPI_XIP_FRF(QSPI_InitStruct->XIP_FRF)); assert_param(IS_QSPI_XIP_MODE(QSPI_InitStruct->XIP_MD_BITS)); assert_param(IS_QSPI_XIP_INCR_TOC(QSPI_InitStruct->ITOC)); assert_param(IS_QSPI_XIP_WRAP_TOC(QSPI_InitStruct->WTOC)); assert_param(IS_QSPI_XIP_TOUT(QSPI_InitStruct->XTOUT)); assert_param(IS_QSPI_NDF(QSPI_InitStruct->NDF)); assert_param(IS_QSPI_CLK_DIV(QSPI_InitStruct->CLK_DIV)); assert_param(IS_QSPI_TXFT(QSPI_InitStruct->TXFT)); assert_param(IS_QSPI_RXFT(QSPI_InitStruct->RXFT)); assert_param(IS_QSPI_TXFN(QSPI_InitStruct->TXFN)); assert_param(IS_QSPI_RXFN(QSPI_InitStruct->RXFN)); assert_param(IS_QSPI_DDR_TXDE(QSPI_InitStruct->TXDE)); if((QSPI_InitStruct->SPI_FRF) == QSPI_CTRL0_SPI_FRF_STANDARD_FORMAT) { tmpregister = (uint32_t)(QSPI_InitStruct->SPI_FRF | QSPI_InitStruct->CFS | QSPI_InitStruct->SSTE | QSPI_InitStruct->TMOD | QSPI_InitStruct->SCPOL | QSPI_InitStruct->SCPH | QSPI_InitStruct->FRF | QSPI_InitStruct->DFS); QSPI->CTRL0 = tmpregister; tmpregister = 0; tmpregister = (uint32_t)(QSPI_InitStruct->MWMOD | QSPI_InitStruct->MC_DIR | QSPI_InitStruct->MHS_EN); QSPI->MW_CTRL = tmpregister; tmpregister = 0; tmpregister = (uint32_t)(QSPI_InitStruct->SES | QSPI_InitStruct->SDCN); QSPI->RS_DELAY = tmpregister; } else if((QSPI_InitStruct->SPI_FRF == QSPI_CTRL0_SPI_FRF_DUAL_FORMAT) || (QSPI_InitStruct->SPI_FRF == QSPI_CTRL0_SPI_FRF_QUAD_FORMAT)) { tmpregister = (uint32_t)(QSPI_InitStruct->SPI_FRF | QSPI_InitStruct->CFS | QSPI_InitStruct->SSTE | QSPI_InitStruct->TMOD | QSPI_InitStruct->SCPOL | QSPI_InitStruct->SCPH | QSPI_InitStruct->FRF | QSPI_InitStruct->DFS); QSPI->CTRL0 = tmpregister; tmpregister = 0; tmpregister = (uint32_t)(QSPI_InitStruct->MWMOD | QSPI_InitStruct->MC_DIR | QSPI_InitStruct->MHS_EN); QSPI->MW_CTRL = tmpregister; tmpregister = 0; tmpregister = (uint32_t)(QSPI_InitStruct->SES | QSPI_InitStruct->SDCN); QSPI->RS_DELAY = tmpregister; tmpregister = 0; tmpregister = (uint32_t)(QSPI_InitStruct->ENHANCED_CLK_STRETCH_EN | QSPI_InitStruct->ENHANCED_XIP_MBL | QSPI_InitStruct->ENHANCED_XIP_CT_EN | QSPI_InitStruct->ENHANCED_XIP_INST_EN | QSPI_InitStruct->ENHANCED_XIP_DFS_HC | QSPI_InitStruct->ENHANCED_INST_DDR_EN | QSPI_InitStruct->ENHANCED_SPI_DDR_EN | QSPI_InitStruct->ENHANCED_WAIT_CYCLES | QSPI_InitStruct->ENHANCED_INST_L | QSPI_InitStruct->ENHANCED_MD_BIT_EN | QSPI_InitStruct->ENHANCED_ADDR_LEN | QSPI_InitStruct->ENHANCED_TRANS_TYPE); QSPI->ENH_CTRL0 = tmpregister; tmpregister = 0; tmpregister = (uint32_t)(QSPI_InitStruct->XIP_MBL | QSPI_InitStruct->XIP_CT_EN | QSPI_InitStruct->XIP_INST_EN | QSPI_InitStruct->XIP_INST_DDR_EN | QSPI_InitStruct->XIP_DDR_EN | QSPI_InitStruct->XIP_DFS_HC | QSPI_InitStruct->XIP_WAIT_CYCLES | QSPI_InitStruct->XIP_MD_BITS_EN | QSPI_InitStruct->XIP_INST_L | QSPI_InitStruct->XIP_ADDR_LEN | QSPI_InitStruct->XIP_TRANS_TYPE | QSPI_InitStruct->XIP_FRF); QSPI->XIP_CTRL = tmpregister; QSPI->XIP_MODE = QSPI_InitStruct->XIP_MD_BITS; QSPI->XIP_INCR_TOC = QSPI_InitStruct->ITOC; QSPI->XIP_WRAP_TOC = QSPI_InitStruct->WTOC; QSPI->XIP_TOUT = QSPI_InitStruct->XTOUT; } QSPI->CTRL1 = QSPI_InitStruct->NDF; QSPI->BAUD = QSPI_InitStruct->CLK_DIV; QSPI->TXFT = QSPI_InitStruct->TXFT; QSPI->RXFT = QSPI_InitStruct->RXFT; QSPI->TXFN = QSPI_InitStruct->TXFN; QSPI->RXFN = QSPI_InitStruct->RXFN; QSPI->DDR_TXDE = QSPI_InitStruct->TXDE; } /** * @brief Configure single GPIO port as GPIO_Mode_AF_PP. * @param GPIOx x can be A to G to select the GPIO port. * @param Pin This parameter can be GPIO_PIN_0~GPIO_PIN_15. */ static void QSPI_SingleGpioConfig(GPIO_Module* GPIOx, uint16_t Pin) { GPIO_InitType GPIO_InitStructure; GPIO_InitStructure.Pin = Pin; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure); } /** * @brief Remap QSPI AFIO group by selecting the pin of NSS. * @param qspi_nss_port_sel select the pin of NSS. QSPI_NSS_PORTA_SEL:QSPI remap by PA4~PA7 and PC4~PC5. QSPI_NSS_PORTC_SEL:QSPI remap by PC10~PC12 and PD0~PD2. QSPI_NSS_PORTF_SEL:QSPI remap by PF0~PF5. * @param IO1_Input IO1 Configure as input or not. * @param IO3_Output IO3 Configure as output or not. */ void QSPI_GPIO(QSPI_NSS_PORT_SEL qspi_nss_port_sel, bool IO1_Input, bool IO3_Output) { GPIO_InitType GPIO_InitStructure; switch (qspi_nss_port_sel) { case QSPI_NSS_PORTA_SEL: RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA | RCC_APB2_PERIPH_GPIOC | RCC_APB2_PERIPH_AFIO, ENABLE); RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_QSPI, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP3_QSPI, DISABLE); //clear two bits of qspi QSPI_SingleGpioConfig(GPIOA, GPIO_PIN_4); // NSS QSPI_SingleGpioConfig(GPIOA, GPIO_PIN_5); // SCK QSPI_SingleGpioConfig(GPIOA, GPIO_PIN_6); // IO0 if (IO1_Input) { GPIO_InitStructure.Pin = GPIO_PIN_7; // IO1 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_INPUT; GPIO_InitPeripheral(GPIOC, &GPIO_InitStructure); } else { QSPI_SingleGpioConfig(GPIOA, GPIO_PIN_7); // IO1 } if (IO3_Output) { GPIO_InitStructure.Pin = GPIO_PIN_4 | GPIO_PIN_5; // IO2 and IO3 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitPeripheral(GPIOC, &GPIO_InitStructure); GPIOC->PBSC |= GPIO_PIN_4 | GPIO_PIN_5; } else { QSPI_SingleGpioConfig(GPIOC, GPIO_PIN_4); // IO2 QSPI_SingleGpioConfig(GPIOC, GPIO_PIN_5); // IO3 } break; case QSPI_NSS_PORTC_SEL: RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC | RCC_APB2_PERIPH_GPIOD | RCC_APB2_PERIPH_AFIO, ENABLE); RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_QSPI, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP3_QSPI, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP_QSPI_XIP_EN, ENABLE); QSPI_SingleGpioConfig(GPIOC, GPIO_PIN_10); // NSS QSPI_SingleGpioConfig(GPIOC, GPIO_PIN_11); // SCK QSPI_SingleGpioConfig(GPIOC, GPIO_PIN_12); // IO0 if (IO1_Input) { GPIO_InitStructure.Pin = GPIO_PIN_0; // IO1 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_INPUT; GPIO_InitPeripheral(GPIOD, &GPIO_InitStructure); } else { QSPI_SingleGpioConfig(GPIOD, GPIO_PIN_0); // IO1 } if (IO3_Output) { GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2; // IO2 and IO3 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitPeripheral(GPIOD, &GPIO_InitStructure); GPIOD->PBSC |= GPIO_PIN_1 | GPIO_PIN_2; } else { QSPI_SingleGpioConfig(GPIOD, GPIO_PIN_1); // IO2 QSPI_SingleGpioConfig(GPIOD, GPIO_PIN_2); // IO3 } break; case QSPI_NSS_PORTF_SEL: RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOF | RCC_APB2_PERIPH_AFIO, ENABLE); RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_QSPI, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP1_QSPI, ENABLE); QSPI_SingleGpioConfig(GPIOF, GPIO_PIN_0); // NSS QSPI_SingleGpioConfig(GPIOF, GPIO_PIN_1); // SCK QSPI_SingleGpioConfig(GPIOF, GPIO_PIN_2); // IO0 if (IO1_Input) { GPIO_InitStructure.Pin = GPIO_PIN_3; // IO1 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_INPUT; GPIO_InitPeripheral(GPIOF, &GPIO_InitStructure); } else { QSPI_SingleGpioConfig(GPIOF, GPIO_PIN_3); // IO1 } if (IO3_Output) { GPIO_InitStructure.Pin = GPIO_PIN_4 | GPIO_PIN_5; // IO2 and IO3 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitPeripheral(GPIOF, &GPIO_InitStructure); GPIOF->PBSC |= GPIO_PIN_4 | GPIO_PIN_5; } else { QSPI_SingleGpioConfig(GPIOF, GPIO_PIN_4); // IO2 QSPI_SingleGpioConfig(GPIOF, GPIO_PIN_5); // IO3 } break; default: break; } } /** * @brief Configuration of QSPI DMA. * @param TxRx transmit or receive data. QSPI_DMA_CTRL_TX_DMA_EN:transmit data QSPI_DMA_CTRL_RX_DMA_EN:receive data * @param TxDataLevel dma transmit data level. * @param RxDataLevel dma receive data level. */ void QSPI_DMA_CTRL_Config(uint8_t TxRx,uint8_t TxDataLevel,uint8_t RxDataLevel) { assert_param(IS_QSPI_DMA_CTRL(TxRx)); assert_param(IS_QSPI_DMATDL_CTRL(TxDataLevel)); assert_param(IS_QSPI_DMARDL_CTRL(RxDataLevel)); QSPI->DMA_CTRL = 0x00; if (TxRx & QSPI_DMA_CTRL_TX_DMA_EN) { QSPI->DMATDL_CTRL = TxDataLevel; QSPI->DMA_CTRL |= QSPI_DMA_CTRL_TX_DMA_EN; } if (TxRx & QSPI_DMA_CTRL_RX_DMA_EN) { QSPI->DMARDL_CTRL = RxDataLevel; QSPI->DMA_CTRL |= QSPI_DMA_CTRL_RX_DMA_EN; } } /** * @brief Get the flag of interrupt status register. * @param FLAG flag of related interrupt register. */ uint16_t QSPI_GetITStatus(uint16_t FLAG) { uint16_t tmp = 0; tmp = QSPI->ISTS & FLAG; if (tmp) return 1; else return 0; } /** * @brief Clear the flag of related interrupt register. * @param FLAG flag of related interrupt register. */ void QSPI_ClearITFLAG(uint16_t FLAG) { volatile uint16_t tmp = 0; if (FLAG == QSPI_ISTS_TXFOIS) tmp = QSPI->TXFOI_CLR; if (FLAG == QSPI_ISTS_RXFOIS) tmp = QSPI->RXFOI_CLR; if (FLAG == QSPI_ISTS_RXFUIS) tmp = QSPI->RXFUI_CLR; if (FLAG == QSPI_ISTS_MMCIS) tmp = QSPI->MMC_CLR; if (FLAG == QSPI_ISTS) tmp = QSPI->ICLR; } /** * @brief Clear the flag of related interrupt register. * @param FLAG flag of XRXFOIC interrupt register. */ void QSPI_XIP_ClearITFLAG(uint16_t FLAG) { volatile uint16_t tmp = 0; if (FLAG == QSPI_XIP_RXFOI_CLR_XRXFOIC) tmp = QSPI->XIP_RXFOI_CLR; } /** * @brief Get QSPI status,busy or not. * @return 1:QSPI busy;0:QSPI idle. */ bool GetQspiBusyStatus(void) { if ((QSPI->STS & 0x01) == 0x01) return 1; return 0; } /** * @brief Check transmit fifo full or not. * @return 1: Transmit fifo full;0: Transmit fifo not full. */ bool GetQspiTxDataBusyStatus(void) { if ((QSPI->STS & 0x02) == 0x00) return 1; return 0; } /** * @brief Check transmit fifo empty or not. * @return 1: Transmit fifo empty;0: Transmit fifo not empty. */ bool GetQspiTxDataEmptyStatus(void) { if ((QSPI->STS & 0x04) == 0x04) return 1; return 0; } /** * @brief Check receive fifo have data or not. * @return 1:Receive fifo have data;0:Receive fifo empty. */ bool GetQspiRxHaveDataStatus(void) { if ((QSPI->STS & 0x08) == 0x08) return 1; return 0; } /** * @brief Check receive fifo full or not. * @return 1: Receive fifo full;0: Receive fifo not full. */ bool GetQspiRxDataFullStatus(void) { if ((QSPI->STS & 0x10) == 0x10) return 1; return 0; } /** * @brief Check transmit error or not. * @return 1: Transmit error;0: No transmit error. */ bool GetQspiTransmitErrorStatus(void) { if ((QSPI->STS & 0x20) == 0x20) return 1; return 0; } /** * @brief Check data conflict error or not. * @return 1: Data conflict error;0: No data conflict error. */ bool GetQspiDataConflictErrorStatus(void) { if ((QSPI->STS & 0x40) == 0x40) return 1; return 0; } /** * @brief Write one data direct to QSPI DAT0 register to send. * @param SendData: data to be send. */ void QspiSendWord(uint32_t SendData) { QSPI->DAT0 = SendData; } /** * @brief Read one data from QSPI DAT0 register. * @return the value of QSPI DAT0 register. */ uint32_t QspiReadWord(void) { return QSPI->DAT0; } /** * @brief Get Pointer of QSPI DAT0 register. * @return the pointer of QSPI DAT0 register. */ uint32_t QspiGetDataPointer(void) { return (uint32_t)&QSPI->DAT0; } /** * @brief Read value from QSPI RXFN register which shows the number of the data from receive fifo. * @return the number of the data from receive fifo. */ uint32_t QspiReadRxFifoNum(void) { return QSPI->RXFN; } /** * @brief Read DAT0 register to clear fifo. */ void ClrFifo(void) { uint32_t timeout = 0; while (GetQspiRxHaveDataStatus()) { QspiReadWord(); if(++timeout >= 200) { break; } } } /** * @brief Get data from fifo. * @param pData pointer to buffer of getting fifo data. * @param Len length of getting fifo data. */ uint32_t GetFifoData(uint32_t* pData, uint32_t Len) { uint32_t cnt; for (cnt = 0; cnt < Len; cnt++) { if (GetQspiRxHaveDataStatus()) { *pData++ = QspiReadWord(); } else { return QSPI_NULL; } } return QSPI_SUCCESS; } /** * @brief Send words out from source data buffer and get returned datas into destination data buffer. * @param pSrcData pointer to buffer of sending datas. * @param pDstData pointer to buffer of getting returned datas. * @param cnt number of sending datas. */ void QspiSendAndGetWords(uint32_t* pSrcData, uint32_t* pDstData, uint32_t cnt) { uint32_t num = 0; uint32_t timeout = 0; while (num < cnt) { QspiSendWord(*(pSrcData++)); num++; } while (!GetQspiRxHaveDataStatus()) { if(++timeout >= QSPI_TIME_OUT_CNT) { break; } } timeout = 0; while (QSPI->RXFN < cnt) { if(++timeout >= QSPI_TIME_OUT_CNT) { break; } } num = 0; while (num < cnt) { *(pDstData++) = QspiReadWord(); num++; } } /** * @brief Send one word data and get returned words into destination data buffer. * @param WrData one word to be sent. * @param pRdData pointer to buffer of getting returned datas. * @param LastRd whether go on to get returned datas. 1:go on to get returned datas. 0:end to get returned datas. */ uint32_t QspiSendWordAndGetWords(uint32_t WrData, uint32_t* pRdData, uint8_t LastRd) { uint32_t timeout1 = 0; QspiSendWord(WrData); //trammit *pRdData = QspiReadWord(); if(LastRd != 0) { while(!GetQspiRxHaveDataStatus()) //wait for data { if(++timeout1 >= QSPI_TIME_OUT_CNT) { return QSPI_NULL; //time out } } *pRdData = QspiReadWord(); //read data return QSPI_SUCCESS; } return QSPI_NULL; }