SAMV71 Xplained Ultra Software Package 1.4

s25fl1.c

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