SAMV71 Xplained Ultra Software Package 1.5

s25fl1.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------- */
00002 /*                  Atmel Microcontroller Software Support                      */
00003 /*                       SAM Software Package License                           */
00004 /* ---------------------------------------------------------------------------- */
00005 /* Copyright (c) 2015, Atmel Corporation                                        */
00006 /*                                                                              */
00007 /* All rights reserved.                                                         */
00008 /*                                                                              */
00009 /* Redistribution and use in source and binary forms, with or without           */
00010 /* modification, are permitted provided that the following condition is met:    */
00011 /*                                                                              */
00012 /* - Redistributions of source code must retain the above copyright notice,     */
00013 /* this list of conditions and the disclaimer below.                            */
00014 /*                                                                              */
00015 /* Atmel's name may not be used to endorse or promote products derived from     */
00016 /* this software without specific prior written permission.                     */
00017 /*                                                                              */
00018 /* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
00028 /* ---------------------------------------------------------------------------- */
00029 
00030 /**
00031  * \addtogroup at25d_module S25FL1 driver
00032  * \ingroup lib_spiflash
00033  * The S25FL1 serial dataflash driver is based on the corresponding S25FL1 SPI
00034  * driver.
00035  * A S25FL1 instance has to be initialized using the Dataflash level function
00036  * S25FL1D_Configure(). S25FL1 Dataflash can be automatically detected using
00037  * the S25FL1D_FindDevice() function. Then S25FL1 dataflash operations such as
00038  * read, write and erase DF can be launched using S25FL1D_SendCommand function
00039  * with corresponding S25FL1 command set.
00040  *
00041  * \section Usage
00042  * <ul>
00043  * <li> Reads a serial flash device ID using S25FL1D_ReadJedecId().</li>
00044  * <li> Reads data from the S25fl1 at the specified address using S25FL1D_Read().
00045  * </li>
00046  * <li> Writes data on the S25fl1 at the specified address using S25FL1D_Write().
00047  * </li>
00048  * <li> Erases all chip using S25FL1D_EraseBlock().</li>
00049  * <li> Erases a specified block using S25FL1D_EraseBlock().</li>
00050  * <li> Poll until the S25fl1 has completed of corresponding operations using
00051  * S25FL1D_IsBusy().</li>
00052  * <li> Retrieves and returns the S25fl1 current using S25FL1D_ReadStatus().</li>
00053  * </ul>
00054  *
00055  * Related files :\n
00056  * \ref at25d.c\n
00057  * \ref at25d.h.\n
00058  */
00059 /*@{*/
00060 /*@}*/
00061 
00062 /**
00063  * \file
00064  *
00065  * Implementation for the S25FL1 Serialflash driver.
00066  *
00067  */
00068 
00069 /*----------------------------------------------------------------------------
00070  *        Headers
00071  *----------------------------------------------------------------------------*/
00072 #include <board.h>
00073 #include <assert.h>
00074 #include "stdlib.h"
00075 #include "string.h"
00076 
00077 
00078 /*----------------------------------------------------------------------------
00079  *        Variable
00080  *----------------------------------------------------------------------------*/
00081 static QspiInstFrame_t *pDev, *pMem;
00082 
00083 static QspiDma_t qspiDma;
00084 static sXdmad qspiDmaInst;
00085 
00086 
00087 /*----------------------------------------------------------------------------
00088  *        Definition
00089  *----------------------------------------------------------------------------*/
00090 #define READ_DEV        0
00091 #define WRITE_DEV       1
00092 
00093 #define PAGE_SIZE       256
00094 /**
00095  * \brief XDMA handler.
00096  */
00097 void XDMAC_Handler(void)
00098 {
00099     XDMAD_Handler(&qspiDmaInst);
00100 }
00101 
00102 static uint32_t *Memory_Align(uint32_t *StartAddr, uint32_t align_num)
00103 {
00104     uint32_t StartAddr_temp;
00105     StartAddr_temp = ((uint32_t)StartAddr + align_num - 1) & (~(align_num - 1));
00106     return (uint32_t *)StartAddr_temp;
00107 }
00108 
00109 /**
00110  * \brief Start S25FL1D Send command with/without data write/read.
00111  * \param Instr Instruct
00112  * \param pTxData point to Tx buffer address
00113  * \param pRxData point to Rx buffer address
00114  * \param ReadWrite Command/Write/Read access
00115  * \param Size buffer size in byte
00116  * \returns 0
00117  */
00118 static uint8_t S25FL1D_SendCommand(uint8_t Instr, uint32_t *pTxData,
00119                                    uint32_t *pRxData, Access_t ReadWrite, uint32_t size)
00120 {
00121     qspiDma.Qspid.qspiCommand.Instruction = Instr;
00122 
00123     if (qspiDma.Qspid.qspiMode) {
00124         pDev->InstFrame.bm.bInstEn = 1;
00125         qspiDma.Qspid.pQspiFrame =  pDev;
00126         qspiDma.Qspid.qspiBuffer.pDataTx = pTxData;
00127         qspiDma.Qspid.qspiBuffer.pDataRx = pRxData;
00128 
00129         // to prevent unaligned access
00130         if ((size % sizeof(uint32_t)) && size > 1)
00131             size += (sizeof(uint32_t) - (size % sizeof(uint32_t)));
00132 
00133         if (ReadWrite == CmdAccess) {
00134             pDev->InstFrame.bm.bXfrType
00135                 = (QSPI_IFR_TFRTYP_TRSFR_READ >> QSPI_IFR_TFRTYP_Pos);
00136             pDev->InstFrame.bm.bDataEn = 0;
00137 
00138             QSPI_SendCommand(&qspiDma.Qspid, 0);
00139 
00140         } else if (ReadWrite == WriteAccess) {
00141             pDev->InstFrame.bm.bDataEn = 1;
00142             pDev->InstFrame.bm.bXfrType
00143                 = (QSPI_IFR_TFRTYP_TRSFR_WRITE >> QSPI_IFR_TFRTYP_Pos);
00144             qspiDma.Qspid.qspiBuffer.TxDataSize  = size;
00145             QSPI_SendCommandWithData(&qspiDma.Qspid, 0);
00146 
00147         } else {
00148             pDev->InstFrame.bm.bXfrType
00149                 = (QSPI_IFR_TFRTYP_TRSFR_READ >> QSPI_IFR_TFRTYP_Pos);
00150             pDev->InstFrame.bm.bDataEn = 1;
00151             qspiDma.Qspid.qspiBuffer.RxDataSize  = size;
00152             QSPI_ReadCommand(&qspiDma.Qspid, 0);
00153         }
00154     } else {
00155         if ((ReadWrite == CmdAccess) || (ReadWrite == WriteAccess)) {
00156             qspiDma.Qspid.qspiBuffer.pDataTx = malloc(size + 1);
00157             qspiDma.Qspid.qspiBuffer.pDataTx[0]
00158                 = qspiDma.Qspid.qspiCommand.Instruction;
00159 
00160             if (size)
00161                 memcpy(&qspiDma.Qspid.qspiBuffer.pDataTx[1], pTxData, size);
00162 
00163             qspiDma.Qspid.qspiBuffer.TxDataSize  = size + 1;
00164 
00165             QSPI_MultiWriteSPI(&qspiDma.Qspid,
00166                                (uint16_t const *)qspiDma.Qspid.qspiBuffer.pDataTx,
00167                                qspiDma.Qspid.qspiBuffer.TxDataSize);
00168 
00169             free(qspiDma.Qspid.qspiBuffer.pDataTx);
00170         } else if (ReadWrite == ReadAccess) {
00171             qspiDma.Qspid.qspiBuffer.pDataRx = pRxData;
00172             QSPI_SingleWriteSPI(&qspiDma.Qspid,
00173                                 (uint16_t const *)&qspiDma.Qspid.qspiCommand.Instruction);
00174             QSPI_MultiReadSPI(&qspiDma.Qspid,
00175                               (uint16_t *)qspiDma.Qspid.qspiBuffer.pDataRx, size);
00176         } else
00177             TRACE_ERROR("%s Wrong access parameter \n\r", __FUNCTION__);
00178 
00179         QSPI_EndTransfer(qspiDma.Qspid.pQspiHw);
00180     }
00181 
00182     return 0;
00183 }
00184 
00185 
00186 /**
00187  * \brief Start S25FL1D Memory access with/without data write/read.
00188  * \param Instr Instruct
00189  * \param pTxData point to Tx buffer address
00190  * \param pRxData point to Rx buffer address
00191  * \param ReadWrite Command/Write/Read access
00192  * \param Size buffer size in byte
00193  * \returns 0
00194  */
00195 static uint8_t S25FL1D_MemoryAccess(uint8_t Instr, uint32_t Addr,
00196                                     uint32_t *pTxData, uint32_t *pRxData, Access_t ReadWrite,
00197                                     uint32_t size, uint8_t Secure)
00198 {
00199     uint8_t SpiBuffer[4];
00200     qspiDma.Qspid.qspiCommand.Instruction = Instr;
00201 
00202     if (qspiDma.Qspid.qspiMode) {
00203         qspiDma.Qspid.qspiBuffer.pDataTx = pTxData;
00204         qspiDma.Qspid.qspiBuffer.pDataRx = pRxData;
00205         pMem->Addr = Addr;
00206         pMem->InstFrame.bm.bInstEn = 1;
00207         pMem->InstFrame.bm.bDataEn = 1;
00208         pMem->InstFrame.bm.bAddrEn = 1;
00209         qspiDma.Qspid.pQspiFrame =  pMem;
00210 
00211         if (ReadWrite == WriteAccess) {
00212             pMem->InstFrame.bm.bXfrType
00213                 = (QSPI_IFR_TFRTYP_TRSFR_WRITE_MEMORY >> QSPI_IFR_TFRTYP_Pos);
00214             qspiDma.Qspid.qspiBuffer.TxDataSize = size;
00215         } else {
00216             pMem->InstFrame.bm.bXfrType
00217                 = (QSPI_IFR_TFRTYP_TRSFR_READ_MEMORY >> QSPI_IFR_TFRTYP_Pos);
00218             qspiDma.Qspid.qspiBuffer.RxDataSize = size;
00219         }
00220 
00221         QSPI_EnableMemAccess(&qspiDma.Qspid, 0, Secure);
00222 #ifdef USE_QSPI_DMA
00223         QSPID_ReadWriteQSPI(&qspiDma, ReadWrite);
00224 #else
00225         QSPI_ReadWriteMem(&qspiDma.Qspid, ReadWrite);
00226 #endif
00227     } else {
00228         /* For aligned with 32*/
00229         uint32_t *pDataTx = malloc((size + 4) + 32);
00230         qspiDma.Qspid.qspiBuffer.pDataTx = Memory_Align(pDataTx, 32);
00231 
00232         if ((((int)qspiDma.Qspid.qspiBuffer.pDataTx) % 32) != 0)
00233             printf("pDataTx is not aligned with 32 - 0x%x \n\r",
00234                     (unsigned int)qspiDma.Qspid.qspiBuffer.pDataTx);
00235 
00236         SpiBuffer[0] = Instr;
00237         SpiBuffer[1] = (uint8_t)(Addr >> 16);
00238         SpiBuffer[2] = (uint8_t)(Addr >> 8);
00239         SpiBuffer[3] = (uint8_t)(Addr);
00240         memcpy(qspiDma.Qspid.qspiBuffer.pDataTx, SpiBuffer, 4);
00241 
00242         if (pTxData != NULL)
00243             memcpy((qspiDma.Qspid.qspiBuffer.pDataTx + 1), pTxData, size);
00244 
00245         if (ReadWrite == WriteAccess) {
00246             qspiDma.Qspid.qspiBuffer.TxDataSize  = size + 4;
00247 #ifdef USE_QSPI_DMA
00248             qspiDma.Qspid.qspiBuffer.RxDataSize  = size + 4;
00249             qspiDma.Qspid.qspiBuffer.pDataRx = qspiDma.Qspid.qspiBuffer.pDataTx;
00250             QSPID_ReadWriteSPI(&qspiDma, ReadWrite);
00251 #else
00252 
00253             QSPI_MultiWriteSPI(&qspiDma.Qspid,
00254                                (uint16_t *)qspiDma.Qspid.qspiBuffer.pDataTx,
00255                                qspiDma.Qspid.qspiBuffer.TxDataSize);
00256             QSPI_EndTransfer(qspiDma.Qspid.pQspiHw);
00257 #endif
00258         } else {
00259 #ifdef USE_QSPI_DMA
00260             qspiDma.Qspid.qspiBuffer.pDataRx = pRxData;
00261             /* instr(1) + addrs(3) + dummy read(1)*/
00262             qspiDma.Qspid.qspiBuffer.RxDataSize  = size + 6;
00263             qspiDma.Qspid.qspiBuffer.TxDataSize  = size + 6;
00264             QSPID_ReadWriteSPI(&qspiDma, ReadWrite);
00265 
00266             while (qspiDma.progress);
00267 
00268             /*qspiDma.Qspid.qspiBuffer.pDataRx = pRxData;
00269             qspiDma.Qspid.qspiBuffer.RxDataSize  = size;
00270             qspiDma.Qspid.qspiBuffer.TxDataSize  = size;
00271             QSPID_ReadWriteSPI(&qspiDma, ReadWrite);*/
00272 #else
00273             qspiDma.Qspid.qspiBuffer.pDataRx = (uint32_t *)(((uint32_t)pRxData) + 6);
00274             qspiDma.Qspid.qspiBuffer.RxDataSize  = size;
00275             qspiDma.Qspid.qspiBuffer.TxDataSize  = 4 + 1;
00276             QSPI_MultiWriteSPI(&qspiDma.Qspid,
00277                                (uint16_t *)qspiDma.Qspid.qspiBuffer.pDataTx,
00278                                qspiDma.Qspid.qspiBuffer.TxDataSize);
00279             QSPI_MultiReadSPI(&qspiDma.Qspid,
00280                               (uint16_t *)qspiDma.Qspid.qspiBuffer.pDataRx,
00281                               size);
00282             QSPI_EndTransfer(qspiDma.Qspid.pQspiHw);
00283 #endif
00284         }
00285 
00286         free(pDataTx);
00287         qspiDma.Qspid.qspiBuffer.pDataTx = NULL;
00288     }
00289 
00290     return 0;
00291 }
00292 
00293 /**
00294  * \brief Reads and returns the status register of the serial flash.
00295  *
00296  * \param pS25fl1  Pointer to an S25FL1 driver instance.
00297  */
00298 static uint32_t S25FL1D_ReadStatus(void)
00299 {
00300     uint32_t status, ReadStatus;
00301 
00302     S25FL1D_SendCommand(READ_STATUS_1, 0, &ReadStatus, ReadAccess, 1);
00303     status = ReadStatus;
00304 
00305     S25FL1D_SendCommand(READ_STATUS_2, 0, &ReadStatus, ReadAccess, 1);
00306     status |= ((ReadStatus << 8) & 0xFF00);
00307 
00308     S25FL1D_SendCommand(READ_STATUS_3, 0, &ReadStatus, ReadAccess, 1);
00309     status |= ((ReadStatus << 16) & 0xFF0000);
00310     return status;
00311 }
00312 
00313 /**
00314  * \brief Reads and returns the status register of the serial flash.
00315  *
00316  * \param pS25fl1  Pointer to an S25FL1 driver instance.
00317  */
00318 static uint8_t S25FL1D_ReadStatus1(void)
00319 {
00320     uint8_t status;
00321     S25FL1D_SendCommand(READ_STATUS_1, 0, (uint32_t *)&status, ReadAccess, 1);
00322     return status;
00323 }
00324 
00325 /**
00326  * \brief Reads and returns the status register of the serial flash.
00327  *
00328  * \param pS25fl1  Pointer to an S25FL1 driver instance.
00329  */
00330 static uint8_t S25FL1D_ReadStatus2(void)
00331 {
00332     uint8_t status;
00333     S25FL1D_SendCommand(READ_STATUS_2, 0, (uint32_t *)&status, ReadAccess, 1);
00334     return status;
00335 }
00336 
00337 /**
00338  * \brief Reads and returns the status register of the serial flash.
00339  *
00340  * \param pS25fl1  Pointer to an S25FL1 driver instance.
00341  */
00342 static uint8_t S25FL1D_ReadStatus3(void)
00343 {
00344     uint8_t status;
00345     S25FL1D_SendCommand(READ_STATUS_3, 0, (uint32_t *)&status, ReadAccess, 1);
00346     return status;
00347 }
00348 /**
00349  * \brief Wait for transfer to finish calling the SPI driver ISR.
00350  * (interrupts are disabled)
00351  *
00352  * \param pS25fl1  Pointer to an S25FL1 driver instance.
00353  */
00354 static void S25FL1D_IsBusy(void)
00355 {
00356 #ifdef USE_QSPI_DMA
00357 
00358     while (QSPID_IsBusy(&qspiDma.progress))
00359         Wait(1);
00360 
00361 #endif
00362 
00363     while (S25FL1D_ReadStatus1() & STATUS_RDYBSY);
00364 }
00365 
00366 static void S25FL1D_EnableWrite(void)
00367 {
00368     uint8_t status = 0;
00369 
00370 
00371     while (!(status & STATUS_WEL)) {
00372         S25FL1D_SendCommand(WRITE_ENABLE, 0, 0, CmdAccess, 0);
00373         status = S25FL1D_ReadStatus1();
00374     }
00375 }
00376 
00377 
00378 static void S25FL1D_DisableWrite(void)
00379 {
00380     uint8_t status;
00381 
00382     status = S25FL1D_ReadStatus1();
00383 
00384     while ((status & STATUS_WEL) != 0) {
00385         S25FL1D_SendCommand(WRITE_DISABLE, 0, 0, CmdAccess, 0);
00386         status = S25FL1D_ReadStatus1();
00387     }
00388 }
00389 /**
00390  * \brief Writes the given value in the status register of the serial flash
00391  * device.
00392  *
00393  * \param pS25fl1  Pointer to an S25FL1 driver instance.
00394  * \param status  Status to write.
00395  */
00396 static void S25FL1D_WriteStatus(uint8_t *pStatus)
00397 {
00398     S25FL1D_EnableWrite();
00399 
00400     S25FL1D_SendCommand(WRITE_STATUS, (uint32_t *)pStatus, 0, WriteAccess, 3);
00401 
00402     S25FL1D_DisableWrite();
00403 }
00404 
00405 /**
00406  * \brief Writes the given value in the status register of the serial flash
00407  * device.
00408  *
00409  * \param pS25fl1  Pointer to an S25FL1 driver instance.
00410  * \param status  Status to write.
00411  */
00412 static void S25FL1D_WriteVolatileStatus(uint8_t *pStatus)
00413 {
00414     uint32_t DataWr = 0;
00415     DataWr = *pStatus;
00416 
00417     S25FL1D_SendCommand(0x50, 0, 0 , CmdAccess, 0);
00418 
00419     S25FL1D_SendCommand(WRITE_STATUS, &DataWr, 0 , WriteAccess, 3);
00420     S25FL1D_DisableWrite();
00421 }
00422 
00423 
00424 static uint8_t S25FL1D_CheckProtectedAddr(uint8_t Status1, uint32_t Addr)
00425 {
00426     const uint32_t AddrJump
00427         = (Status1 & SEC_PROTECT_Msk) ? 0x001000UL : 0x010000UL;
00428     static uint8_t Protected = 0;
00429 
00430     const uint8_t blockBits = ((Status1 & BLOCK_PROTECT_Msk) >> 2);
00431 
00432     switch (blockBits) {
00433     case 1:
00434         if (Status1 & TOP_BTM_PROTECT_Msk) {
00435             if ((Addr > 0x000000) && (Addr < (0x000000 + AddrJump - 1)))
00436                 Protected = 1;
00437         } else {
00438             if ((Addr > (0x1FFFFF - AddrJump + 1)) && (Addr < 0x1FFFFF))
00439                 Protected = 1;
00440         }
00441 
00442         break;
00443 
00444     case 2:
00445         if (Status1 & TOP_BTM_PROTECT_Msk) {
00446             if ((Addr > 0x000000) && (Addr < (0x000000 + (2 * AddrJump) - 1)))
00447                 Protected = 1;
00448         } else {
00449             if ((Addr > (0x1FFFFF - (2 * AddrJump) + 1)) && (Addr < 0x1FFFFF))
00450                 Protected = 1;
00451         }
00452 
00453         break;
00454 
00455     case 3:
00456         if (Status1 & TOP_BTM_PROTECT_Msk) {
00457             if ((Addr > 0x000000) && (Addr < (0x000000 + (4 * AddrJump) - 1)))
00458                 Protected = 1;
00459         } else {
00460             if ((Addr > (0x1FFFFF - (4 * AddrJump) + 1)) && (Addr < 0x1FFFFF))
00461                 Protected = 1;
00462         }
00463 
00464         break;
00465 
00466     case 4:
00467         if (Status1 & TOP_BTM_PROTECT_Msk) {
00468             if ((Addr > 0x000000) && (Addr < (0x000000 + (8 * AddrJump) - 1)))
00469                 Protected = 1;
00470         } else {
00471             if ((Addr > (0x1FFFFF - (8 * AddrJump) + 1)) && (Addr < 0x1FFFFF))
00472                 Protected = 1;
00473         }
00474 
00475         break;
00476 
00477     case 5:
00478         if (!(Status1 & SEC_PROTECT_Msk)) {
00479             if (Status1 & TOP_BTM_PROTECT_Msk) {
00480                 if ((Addr > 0x000000) && (Addr < (0x000000 + (16 * AddrJump) - 1)))
00481                     Protected = 1;
00482             } else {
00483                 if ((Addr > (0x1FFFFF - (16 * AddrJump) + 1)) && (Addr < 0x1FFFFF))
00484                     Protected = 1;
00485             }
00486         }
00487 
00488         break;
00489 
00490     case 6:
00491 
00492         if (!(Status1 & SEC_PROTECT_Msk)) {
00493 
00494             if (Status1 & TOP_BTM_PROTECT_Msk) {
00495                 if ((Addr > 0x000000) && (Addr < (0x000000 + (32 * AddrJump) - 1)))
00496                     Protected = 1;
00497             }
00498         }
00499 
00500         break;
00501     }
00502 
00503     return Protected;
00504 }
00505 
00506 /*----------------------------------------------------------------------------
00507  *         Global functions
00508  *----------------------------------------------------------------------------*/
00509 void S25FL1D_InitFlashInterface(uint8_t Mode)
00510 {
00511     if (Mode) {
00512         QSPID_Configure(&qspiDma, QspiMemMode,
00513                         QSPI_MR_CSMODE_LASTXFER, &qspiDmaInst);
00514         qspiDma.Qspid.qspiMode = (QspiMode_t)QSPI_MR_SMM_MEMORY;
00515 
00516         pDev = (QspiInstFrame_t *)malloc (sizeof(QspiInstFrame_t));
00517         memset(pDev, 0, sizeof(QspiInstFrame_t));
00518         pDev->InstFrame.bm.bwidth = QSPI_IFR_WIDTH_SINGLE_BIT_SPI;
00519 
00520 
00521         pMem = (QspiInstFrame_t *)malloc (sizeof(QspiInstFrame_t));
00522         memset(pMem, 0, sizeof(QspiInstFrame_t));
00523         pMem->InstFrame.bm.bwidth = QSPI_IFR_WIDTH_SINGLE_BIT_SPI;
00524     } else {
00525         QSPID_Configure(&qspiDma,
00526                         SpiMode, (QSPI_MR_CSMODE_LASTXFER | QSPI_MR_DLYCS (20)),
00527                         &qspiDmaInst);
00528         qspiDma.Qspid.qspiMode = (QspiMode_t)QSPI_MR_SMM_SPI;
00529     }
00530 
00531     QSPI_ConfigureClock(QSPI, ClockMode_00, QSPI_SCR_SCBR(1));
00532 
00533     QSPI_Enable(QSPI);
00534 
00535 }
00536 
00537 /**
00538  * \brief Reads and returns the serial flash device ID.
00539  *
00540  * \param pS25fl1  Pointer to an S25FL1 driver instance.
00541  */
00542 uint32_t S25FL1D_ReadJedecId(void)
00543 {
00544     static uint32_t pId;
00545     S25FL1D_SendCommand(READ_JEDEC_ID, 0, &pId, ReadAccess, 3);
00546 
00547     return pId;
00548 }
00549 
00550 /**
00551  * \brief Enables critical writes operation on a serial flash device, such as
00552  * sector protection, status register, etc.
00553  *
00554  * \para pS25fl1  Pointer to an S25FL1 driver instance.
00555  */
00556 void S25FL1D_QuadMode(uint8_t Enable)
00557 {
00558 
00559     uint8_t status[3];
00560 
00561     status[0] = S25FL1D_ReadStatus1();
00562     status[1] = S25FL1D_ReadStatus2();
00563     status[2] = S25FL1D_ReadStatus3();
00564 
00565     if (Enable) {
00566         while (!(status[1] & STATUS_QUAD_ENABLE)) {
00567             status[1] |= STATUS_QUAD_ENABLE;
00568             S25FL1D_WriteStatus(status);
00569             status[1] = S25FL1D_ReadStatus2();
00570             Wait(50);
00571         }
00572     } else {
00573         while ((status[1] & STATUS_QUAD_ENABLE)) {
00574             status[1] &= (~STATUS_QUAD_ENABLE);
00575             S25FL1D_WriteStatus(status);
00576             status[1] = S25FL1D_ReadStatus2();
00577             Wait(50);
00578         }
00579     }
00580 }
00581 
00582 
00583 /**
00584  * \brief Enables critical writes operation on a serial flash device, such as
00585  * sector protection, status register, etc.
00586  *
00587  * \para pS25fl1  Pointer to an S25FL1 driver instance.
00588  */
00589 void S25FL1D_EnableWrap(uint8_t ByetAlign)
00590 {
00591 
00592     uint8_t status[3];
00593 
00594     status[0] = S25FL1D_ReadStatus1();
00595     status[1] = S25FL1D_ReadStatus2();
00596     status[2] = S25FL1D_ReadStatus3();
00597 
00598     status[2] |= (ByetAlign << 5);
00599 
00600     pDev->InstFrame.bm.bDummyCycles = 24;
00601     S25FL1D_SendCommand(WRAP_ENABLE, (uint32_t *)&status[2], 0,  WriteAccess, 1);
00602 
00603     S25FL1D_WriteVolatileStatus(status);
00604     status[2] = S25FL1D_ReadStatus3();
00605     Wait(50);
00606 }
00607 
00608 
00609 /**
00610  * \brief Enables critical writes operation on a serial flash device, such as
00611  * sector protection, status register, etc.
00612  *
00613  * \para pS25fl1  Pointer to an S25FL1 driver instance.
00614  */
00615 void S25FL1D_SetReadLatencyControl(uint8_t Latency)
00616 {
00617 
00618     uint8_t status[3];
00619 
00620     status[0] = S25FL1D_ReadStatus();
00621     status[1] = S25FL1D_ReadStatus2();
00622     status[2] = S25FL1D_ReadStatus3();
00623 
00624     status[2] |= Latency;
00625 
00626     qspiDma.Qspid.qspiBuffer.pDataTx = (uint32_t *)&status[2];
00627 
00628     while ((status[2] & STATUS_LATENCY_CTRL) != Latency) {
00629         S25FL1D_WriteVolatileStatus(status);
00630         status[2] = S25FL1D_ReadStatus3();
00631         Wait(50);
00632     }
00633 }
00634 void S25FL1D_SoftReset(void)
00635 {
00636     S25FL1D_SendCommand(SOFT_RESET_ENABLE, 0, 0,  CmdAccess, 0);
00637     S25FL1D_SendCommand(SOFT_RESET, 0, 0, CmdAccess, 0);
00638 }
00639 
00640 /**
00641  * \brief Issue 'CContinuous Read Mode' command, the device can return to normal
00642  * SPI command mode, in which all commands can be accepts.
00643  *
00644  */
00645 void S25FL1D_ContReadModeReset(void)
00646 {
00647     S25FL1D_ReadStatus();
00648     S25FL1D_SendCommand(CONT_MODE_RESET, 0, 0, CmdAccess, 0);
00649 }
00650 
00651 /**
00652  * \brief Unprotected the contents of the serial flash device.
00653  *
00654  * \param pS25fl1  Pointer to an S25FL1 driver instance.
00655  *
00656  * \return 0 if the device has been unprotected; otherwise returns
00657  * S25FL1D_ERROR_PROTECTED.
00658  */
00659 unsigned char S25FL1D_Unprotect(void)
00660 {
00661     unsigned char status[3];
00662     /* Get the status register value to check the current protection */
00663     status[0] = S25FL1D_ReadStatus();
00664     status[1] = S25FL1D_ReadStatus2();
00665     status[2] = S25FL1D_ReadStatus3();
00666 
00667     if ((status[0] & STATUS_SWP) == STATUS_SWP_PROTNONE) {
00668 
00669         /* Protection already disabled */
00670         return 0;
00671     }
00672 
00673     status[0] &= (!STATUS_SWP);
00674 
00675     /* Check if sector protection registers are locked */
00676     if ((status[0] & STATUS_SPRL) == STATUS_SPRL_LOCKED) {
00677         status[0] &= (!STATUS_SPRL);
00678         /* Unprotected sector protection registers by writing the status reg. */
00679         S25FL1D_WriteStatus(status);
00680     }
00681 
00682     S25FL1D_WriteStatus(status);
00683 
00684     /* Check the new status */
00685     status[0] = S25FL1D_ReadStatus();
00686 
00687     if ((status[0] & (STATUS_SPRL | STATUS_SWP)) != 0)
00688         return ERROR_PROTECTED;
00689     else
00690 
00691         return 0;
00692 }
00693 
00694 /**
00695  * \brief Unprotected the contents of the serial flash device.
00696  *
00697  * \param pS25fl1  Pointer to an S25FL1 driver instance.
00698  *
00699  * \return 0 if the device has been unprotected; otherwise returns
00700  * S25FL1D_ERROR_PROTECTED.
00701  */
00702 unsigned char S25FL1D_Protect(uint32_t StartAddr, uint32_t Size)
00703 {
00704     unsigned char status[3];
00705 
00706     /*dummy*/
00707     StartAddr = StartAddr;
00708     Size = Size;
00709 
00710     /* Get the status register value to check the current protection */
00711     status[0] = S25FL1D_ReadStatus1();
00712     status[1] = S25FL1D_ReadStatus2();
00713     status[2] = S25FL1D_ReadStatus3();
00714 
00715     status[0] &= (!STATUS_SWP);
00716 
00717     /* Check if sector protection registers are locked */
00718     if ((status[0] & STATUS_SPRL) == STATUS_SPRL_LOCKED) {
00719         status[0] &= (!STATUS_SPRL);
00720         /* Unprotected sector protection registers by writing the status reg. */
00721         S25FL1D_WriteStatus(status);
00722     }
00723 
00724     S25FL1D_WriteStatus(status);
00725 
00726     /* Check the new status */
00727     status[0] = S25FL1D_ReadStatus();
00728 
00729     if ((status[0] & (STATUS_SPRL | STATUS_SWP)) != 0)
00730         return ERROR_PROTECTED;
00731     else
00732         return 0;
00733 }
00734 
00735 
00736 /**
00737  * \brief Erases all the content of the memory chip.
00738  *
00739  * \param pS25fl1  Pointer to an S25FL1 driver instance.
00740  *
00741  * \return 0 if the device has been unprotected; otherwise returns
00742  * ERROR_PROTECTED.
00743  */
00744 unsigned char S25FL1D_EraseChip(void)
00745 {
00746     char wait_ch[4] = {'\\', '|', '/', '-' };
00747     uint8_t i = 0;
00748     uint8_t Status = STATUS_RDYBSY;
00749     uint8_t ChipStatus = S25FL1D_ReadStatus1();
00750 
00751     if (ChipStatus & CHIP_PROTECT_Msk) {
00752         TRACE_ERROR("Chip is Protected \n\r");
00753         TRACE_INFO("Flash Status Register 1 is %x", ChipStatus);
00754         return 1;
00755     } else {
00756         S25FL1D_EnableWrite();
00757         S25FL1D_SendCommand(CHIP_ERASE_2, 0, 0, CmdAccess, 0);
00758 
00759         while (Status & STATUS_RDYBSY) {
00760 
00761             Wait(200);
00762             printf("Erasing flash memory %c\r", wait_ch[i]);
00763             i++;
00764             Status = S25FL1D_ReadStatus1();
00765             memory_barrier();
00766             i = i % 4;
00767         }
00768 
00769         printf("\rErasing flash memory done..... 100%%\n\r");
00770         return 0;
00771     }
00772 }
00773 
00774 /**
00775  *\brief  Erases the specified block of the serial firmware dataflash.
00776  *
00777  * \param pS25fl1  Pointer to an S25FL1 driver instance.
00778  * \param address  Address of the block to erase.
00779  *
00780  * \return 0 if successful; otherwise returns ERROR_PROTECTED if the
00781  * device is protected or ERROR_BUSY if it is busy executing a command.
00782  */
00783 unsigned char S25FL1D_EraseSector(unsigned int address)
00784 {
00785     uint8_t status;
00786     uint8_t Secure = 0;
00787     /* Check that the flash is ready and unprotected */
00788     status = S25FL1D_ReadStatus1();
00789 
00790     if ((status & STATUS_RDYBSY) != STATUS_RDYBSY_READY) {
00791         TRACE_ERROR("%s : Flash busy\n\r", __FUNCTION__);
00792         return ERROR_BUSY;
00793     } else if (status & BLOCK_PROTECT_Msk) {
00794         if (S25FL1D_CheckProtectedAddr(status, address)) {
00795             TRACE_ERROR("%s : Flash Addrs is protected\n\r", __FUNCTION__);
00796             return ERROR_PROTECTED;
00797         }
00798     }
00799 
00800     /* Enable critical write operation */
00801     S25FL1D_EnableWrite();
00802 
00803     if (qspiDma.Qspid.qspiMode) {
00804         pDev->Addr = address;
00805         pDev->InstFrame.bm.bAddrEn = 1;
00806         /* Start the block erase command */
00807         S25FL1D_SendCommand(BLOCK_ERASE_4K, 0, 0, CmdAccess, 0);
00808     } else {
00809         /* Start the block erase command */
00810         S25FL1D_MemoryAccess(BLOCK_ERASE_4K, address, 0, 0, WriteAccess,
00811                              0, Secure);
00812     }
00813 
00814     /* Wait for transfer to finish */
00815     S25FL1D_IsBusy();
00816     return 0;
00817 }
00818 
00819 /**
00820  *\brief  Erases the specified 64KB block of the serial firmware dataflash.
00821  *
00822  * \param pS25fl1  Pointer to an S25FL1 driver instance.
00823  * \param address  Address of the block to erase.
00824  *
00825  * \return 0 if successful; otherwise returns ERROR_PROTECTED if the
00826  * device is protected or ERROR_BUSY if it is busy executing a command.
00827  */
00828 unsigned char S25FL1D_Erase64KBlock(unsigned int address)
00829 {
00830     unsigned char status;
00831 
00832     /* Check that the flash is ready and unprotected */
00833     status = S25FL1D_ReadStatus();
00834 
00835     if ((status & STATUS_RDYBSY) != STATUS_RDYBSY_READY) {
00836         TRACE_ERROR("S25FL1D_EraseBlock : Flash busy\n\r");
00837         return ERROR_BUSY;
00838     } else if ((status & STATUS_SWP) != STATUS_SWP_PROTNONE) {
00839         TRACE_ERROR("EraseBlock : Flash protected\n\r");
00840         return ERROR_PROTECTED;
00841     }
00842 
00843     /* Enable critical write operation */
00844     S25FL1D_EnableWrite();
00845 
00846     if (qspiDma.Qspid.qspiMode) {
00847         pDev->Addr = address;
00848         pDev->InstFrame.bm.bAddrEn = 1;
00849         /* Start the block erase command */
00850         S25FL1D_SendCommand(BLOCK_ERASE_64K, 0, 0, CmdAccess, 0);
00851     } else {
00852 #ifdef USE_QSPI_DMA
00853 
00854         if (QSPID_EnableSpiChannel(&qspiDma) == QSPID_ERROR_LOCK)
00855             return 1;
00856 
00857 #endif
00858         /* Start the block erase command */
00859         S25FL1D_MemoryAccess(BLOCK_ERASE_64K, address, 0, 0, WriteAccess, 0, 0);
00860 #ifdef USE_QSPI_DMA
00861         QSPID_DisableSpiChannel(&qspiDma);
00862 #endif
00863     }
00864 
00865     /* Wait for transfer to finish */
00866     S25FL1D_IsBusy();
00867     return 0;
00868 }
00869 
00870 /**
00871  * \brief Writes data at the specified address on the serial firmware dataflash.
00872  * The page(s) to program must have been erased prior to writing. This function
00873  * handles page boundary crossing automatically.
00874  *
00875  * \param pS25fl1  Pointer to an S25FL1 driver instance.
00876  * \param pData  Data buffer.
00877  * \param size  Number of bytes in buffer.
00878  * \param address  Write address.
00879  *
00880  * \return 0 if successful; otherwise, returns ERROR_PROGRAM is there has
00881  * been an error during the data programming.
00882  */
00883 unsigned char S25FL1D_Write(
00884     uint32_t *pData,
00885     uint32_t size,
00886     uint32_t address,
00887     uint8_t Secure)
00888 {
00889     unsigned int i = 0;
00890 
00891     uint32_t  NumberOfWrites = (size >> 8); //  ((Size / pagezize))
00892     uint32_t Addrs = address;
00893 
00894 #ifdef USE_QSPI_DMA
00895 
00896     if (qspiDma.Qspid.qspiMode) {
00897         if (QSPID_EnableQspiTxChannel(&qspiDma) == QSPID_ERROR_LOCK)
00898             return 1;
00899     } else {
00900         if (QSPID_EnableSpiChannel(&qspiDma) == QSPID_ERROR_LOCK)
00901             return 1;
00902     }
00903 
00904 #endif
00905 
00906     // if less than page size
00907     if (NumberOfWrites == 0) {
00908         S25FL1D_EnableWrite();
00909         S25FL1D_MemoryAccess(BYTE_PAGE_PROGRAM , Addrs, pData, 0,
00910                              WriteAccess, size, Secure);
00911         // multiple page
00912     } else {
00913         for (i = 0; i < NumberOfWrites; i++) {
00914             S25FL1D_EnableWrite();
00915             S25FL1D_MemoryAccess(BYTE_PAGE_PROGRAM , Addrs, pData, 0,
00916                                  WriteAccess, PAGE_SIZE, Secure);
00917             S25FL1D_IsBusy();
00918             pData += (PAGE_SIZE >> 2);
00919             Addrs += PAGE_SIZE;
00920         }
00921 
00922         if (size % PAGE_SIZE) {
00923             S25FL1D_EnableWrite();
00924             S25FL1D_MemoryAccess(BYTE_PAGE_PROGRAM , Addrs, pData, 0,
00925                                  WriteAccess, (size - (NumberOfWrites * PAGE_SIZE)),
00926                                  Secure);
00927             S25FL1D_IsBusy();
00928         }
00929     }
00930 
00931 #ifdef USE_QSPI_DMA
00932 
00933     if (qspiDma.Qspid.qspiMode)
00934         QSPID_DisableQspiTxChannel(&qspiDma);
00935     else
00936         QSPID_DisableSpiChannel(&qspiDma);
00937 
00938 #endif
00939     S25FL1D_DisableWrite();
00940     return 0;
00941 }
00942 
00943 /**
00944  * \brief Reads data from the specified address on the serial flash.
00945  *
00946  * \param pS25fl1  Pointer to an S25FL1 driver instance.
00947  * \param pData  Data buffer.
00948  * \param size  Number of bytes to read.
00949  * \param address  Read address.
00950  *
00951  * \return 0 if successful; otherwise, fail.
00952  */
00953 unsigned char S25FL1D_Read(
00954     uint32_t *pData,
00955     uint32_t size,
00956     uint32_t address)
00957 {
00958     uint8_t Secure = 0;
00959 
00960 #ifdef USE_QSPI_DMA
00961 
00962     if (qspiDma.Qspid.qspiMode) {
00963         if (QSPID_EnableQspiRxChannel(&qspiDma) == QSPID_ERROR_LOCK)
00964             return 1;
00965     } else {
00966         if (QSPID_EnableSpiChannel(&qspiDma) == QSPID_ERROR_LOCK)
00967             return 1;
00968     }
00969 
00970 #endif
00971 
00972     S25FL1D_MemoryAccess(READ_ARRAY , address, 0, pData,
00973                          ReadAccess, size , Secure);
00974 
00975 #ifdef USE_QSPI_DMA
00976 
00977     if (qspiDma.Qspid.qspiMode)
00978         QSPID_DisableQspiRxChannel(&qspiDma);
00979     else
00980         QSPID_DisableSpiChannel(&qspiDma);
00981 
00982 #endif
00983     return 0;
00984 
00985 }
00986 
00987 /**
00988  * \brief Reads data from the specified address on the serial flash.
00989  *
00990  * \param pS25fl1  Pointer to an S25FL1 driver instance.
00991  * \param pData  Data buffer.
00992  * \param size  Number of bytes to read.
00993  * \param address  Read address.
00994  *
00995  * \return 0 if successful; otherwise, fail.
00996  */
00997 unsigned char S25FL1D_ReadDual(
00998     uint32_t *pData,
00999     uint32_t size,
01000     uint32_t address)
01001 {
01002 
01003     uint8_t Secure = 0;
01004 #ifdef USE_QSPI_DMA
01005 
01006     if (qspiDma.Qspid.qspiMode) {
01007         if (QSPID_EnableQspiRxChannel(&qspiDma) == QSPID_ERROR_LOCK)
01008             return 1;
01009     } else {
01010         if (QSPID_EnableSpiChannel(&qspiDma) == QSPID_ERROR_LOCK)
01011             return 1;
01012     }
01013 
01014 #endif
01015     pMem->InstFrame.bm.bDummyCycles = 8;
01016     pMem->InstFrame.bm.bwidth = QSPI_IFR_WIDTH_DUAL_OUTPUT;
01017 
01018     S25FL1D_MemoryAccess(READ_ARRAY_DUAL , address, 0, pData,
01019                          ReadAccess, size, Secure);
01020 
01021 #ifdef USE_QSPI_DMA
01022 
01023     while (QSPID_IsBusy(&qspiDma.progress))
01024         Wait(1);
01025 
01026     if (qspiDma.Qspid.qspiMode)
01027         QSPID_DisableQspiRxChannel(&qspiDma);
01028     else
01029         QSPID_DisableSpiChannel(&qspiDma);
01030 
01031 #endif
01032     return 0;
01033 }
01034 
01035 /**
01036  * \brief Reads data from the specified address on the serial flash.
01037  *
01038  * \param pS25fl1  Pointer to an S25FL1 driver instance.
01039  * \param pData  Data buffer.
01040  * \param size  Number of bytes to read.
01041  * \param address  Read address.
01042  *
01043  * \return 0 if successful; otherwise, fail.
01044  */
01045 unsigned char S25FL1D_ReadQuad(
01046     uint32_t *pData,
01047     uint32_t size,
01048     uint32_t address)
01049 {
01050     uint8_t Secure = 0;
01051 #ifdef USE_QSPI_DMA
01052 
01053     if (qspiDma.Qspid.qspiMode) {
01054         if (QSPID_EnableQspiRxChannel(&qspiDma) == QSPID_ERROR_LOCK)
01055             return 1;
01056     } else {
01057         if (QSPID_EnableSpiChannel(&qspiDma) == QSPID_ERROR_LOCK)
01058             return 1;
01059     }
01060 
01061 #endif
01062     pMem->InstFrame.bm.bDummyCycles = 8;
01063     pMem->InstFrame.bm.bwidth = QSPI_IFR_WIDTH_QUAD_OUTPUT;
01064     S25FL1D_MemoryAccess(READ_ARRAY_QUAD,   address, 0, pData,
01065                          ReadAccess, size, Secure);
01066 
01067 #ifdef USE_QSPI_DMA
01068 
01069     while (QSPID_IsBusy(&qspiDma.progress))
01070         Wait(1);
01071 
01072     if (qspiDma.Qspid.qspiMode)
01073         QSPID_DisableQspiRxChannel(&qspiDma);
01074     else
01075         QSPID_DisableSpiChannel(&qspiDma);
01076 
01077 #endif
01078     return 0;
01079 }
01080 
01081 /**
01082  * \brief Reads data from the specified address on the serial flash.
01083  *
01084  * \param pS25fl1  Pointer to an S25FL1 driver instance.
01085  * \param pData  Data buffer.
01086  * \param size  Number of bytes to read.
01087  * \param address  Read address.
01088  *
01089  * \return 0 if successful; otherwise, fail.
01090  */
01091 unsigned char S25FL1D_ReadDualIO(
01092     uint32_t *pData,
01093     uint32_t size,
01094     uint32_t address,
01095     uint8_t ContMode,
01096     uint8_t Secure)
01097 {
01098 #ifdef USE_QSPI_DMA
01099 
01100     if (qspiDma.Qspid.qspiMode) {
01101         if (QSPID_EnableQspiRxChannel(&qspiDma) == QSPID_ERROR_LOCK)
01102             return 1;
01103     } else {
01104         if (QSPID_EnableSpiChannel(&qspiDma) == QSPID_ERROR_LOCK)
01105             return 1;
01106     }
01107 
01108 #endif
01109     pMem->InstFrame.bm.bDummyCycles = 4;
01110 
01111     if (ContMode) {
01112         pMem->InstFrame.bm.bOptLen
01113             = (QSPI_IFR_OPTL_OPTION_4BIT >> QSPI_IFR_OPTL_Pos);
01114         qspiDma.Qspid.qspiCommand.Option = 0x2;
01115         pMem->InstFrame.bm.bContinuesRead = ContMode;
01116         pMem->InstFrame.bm.bDummyCycles = 3;
01117     }
01118 
01119     pMem->InstFrame.bm.bwidth = QSPI_IFR_WIDTH_DUAL_IO;
01120     S25FL1D_MemoryAccess(READ_ARRAY_DUAL_IO , address, 0,
01121                          pData, ReadAccess, size, Secure);
01122     pMem->InstFrame.bm.bOptEn = 0;
01123     pMem->InstFrame.bm.bContinuesRead  = 0;
01124 #ifdef USE_QSPI_DMA
01125 
01126     while (QSPID_IsBusy(&qspiDma.progress))
01127         Wait(1);
01128 
01129     if (qspiDma.Qspid.qspiMode)
01130         QSPID_DisableQspiRxChannel(&qspiDma);
01131     else
01132         QSPID_DisableSpiChannel(&qspiDma);
01133 
01134 #endif
01135     return 0;
01136 }
01137 
01138 /**
01139  * \brief Reads data from the specified address on the serial flash.
01140  *
01141  * \param pS25fl1  Pointer to an S25FL1 driver instance.
01142  * \param pData  Data buffer.
01143  * \param size  Number of bytes to read.
01144  * \param address  Read address.
01145  *
01146  * \return 0 if successful; otherwise, fail.
01147  */
01148 unsigned char S25FL1D_ReadQuadIO(
01149     uint32_t *pData,
01150     uint32_t size,
01151     uint32_t address,
01152     uint8_t ContMode,
01153     uint8_t Secure)
01154 {
01155 #ifdef USE_QSPI_DMA
01156 
01157     if (qspiDma.Qspid.qspiMode) {
01158         if (QSPID_EnableQspiRxChannel(&qspiDma) == QSPID_ERROR_LOCK)
01159             return 1;
01160     } else {
01161         if (QSPID_EnableSpiChannel(&qspiDma) == QSPID_ERROR_LOCK)
01162             return 1;
01163     }
01164 
01165 #endif
01166     pMem->InstFrame.bm.bDummyCycles = 6;
01167 
01168     if (ContMode) {
01169         pMem->InstFrame.bm.bOptLen
01170             = (QSPI_IFR_OPTL_OPTION_4BIT >> QSPI_IFR_OPTL_Pos);
01171         qspiDma.Qspid.qspiCommand.Option = 0x2;
01172         pMem->InstFrame.bm.bContinuesRead = ContMode;
01173         pMem->InstFrame.bm.bDummyCycles = 5;
01174         pMem->InstFrame.bm.bOptEn = 1;
01175     }
01176 
01177     pMem->InstFrame.bm.bwidth = QSPI_IFR_WIDTH_QUAD_IO;
01178     S25FL1D_MemoryAccess(READ_ARRAY_QUAD_IO , address, 0,
01179                          pData, ReadAccess, size, Secure);
01180     pMem->InstFrame.bm.bOptEn = 0;
01181     pMem->InstFrame.bm.bContinuesRead = 0;
01182 #ifdef USE_QSPI_DMA
01183 
01184     while (QSPID_IsBusy(&qspiDma.progress))
01185         Wait(1);
01186 
01187     if (qspiDma.Qspid.qspiMode)
01188         QSPID_DisableQspiRxChannel(&qspiDma);
01189     else
01190         QSPID_DisableSpiChannel(&qspiDma);
01191 
01192 #endif
01193     return 0;
01194 }
01195 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines