SAMV71 Xplained Ultra Software Package 1.5

at26.c

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 //         Headers
00032 //------------------------------------------------------------------------------
00033 
00034 #include "at26.h"
00035 #include "board.h"
00036 #include <assert.h>
00037 
00038 //------------------------------------------------------------------------------
00039 //         Internal definitions
00040 //------------------------------------------------------------------------------
00041 
00042 /// SPI clock frequency used in Hz.
00043 #define SPCK            1000000
00044 
00045 /// SPI chip select configuration value.
00046 #define CSR             (SPI_CSR_NCPHA | \
00047                          SPID_CSR_DLYBCT(BOARD_MCK, 100) | \
00048                          SPID_CSR_DLYBS(BOARD_MCK, 5) | \
00049                          SPID_CSR_SCBR(BOARD_MCK, SPCK))
00050 
00051 /// Number of recognized dataflash.
00052 #define NUMDATAFLASH    (sizeof(at26Devices) / sizeof(At26Desc))
00053 
00054 //------------------------------------------------------------------------------
00055 //         Internal variables
00056 //------------------------------------------------------------------------------
00057 
00058 /// Array of recognized serial firmware dataflash chips.
00059 static const At26Desc at26Devices[] = {
00060     // name, Jedec ID, size, page size, block size, block erase command
00061     {"AT25DF041A" , 0x0001441F, 512 * 1024 ,     256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00062     {"AT25DF161"  , 0x0002461F, 2 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00063     {"AT26DF081A" , 0x0001451F, 1 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00064     {"AT26DF0161" , 0x0000461F, 2 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00065     {"AT26DF161A" , 0x0001461F, 2 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00066     {"AT26DF321" ,  0x0000471F, 4 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00067     {"AT25DF512B" , 0x0001651F, 64 * 1024,       256, 32 * 1024, AT26_BLOCK_ERASE_32K},
00068     {"AT25DF512B" , 0x0000651F, 64 * 1024,       256, 32 * 1024, AT26_BLOCK_ERASE_32K},
00069     {"AT25DF021"  , 0x0000431F, 256 * 1024,      256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00070     {"AT26DF641" ,  0x0000481F, 8 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00071     // Manufacturer: ST
00072     {"M25P05"     , 0x00102020,       64 * 1024, 256, 32 * 1024, AT26_BLOCK_ERASE_64K},
00073     {"M25P10"     , 0x00112020,      128 * 1024, 256, 32 * 1024, AT26_BLOCK_ERASE_64K},
00074     {"M25P20"     , 0x00122020,      256 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00075     {"M25P40"     , 0x00132020,      512 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00076     {"M25P80"     , 0x00142020, 1 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00077     {"M25P16"     , 0x00152020, 2 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00078     {"M25P32"     , 0x00162020, 4 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00079     {"M25P64"     , 0x00172020, 8 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00080     // Manufacturer: Windbond
00081     {"W25X10"     , 0x001130EF,      128 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00082     {"W25X20"     , 0x001230EF,      256 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00083     {"W25X40"     , 0x001330EF,      512 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00084     {"W25X80"     , 0x001430EF, 1 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00085     // Manufacturer: Macronix
00086     {"MX25L512"   , 0x001020C2,       64 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00087     {"MX25L3205"  , 0x001620C2, 4 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00088     {"MX25L6405"  , 0x001720C2, 8 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K},
00089     // Other
00090     {"SST25VF512" , 0x000048BF,       64 * 1024, 256, 32 * 1024, AT26_BLOCK_ERASE_32K}
00091 };
00092 
00093 //------------------------------------------------------------------------------
00094 //         Exported functions
00095 //------------------------------------------------------------------------------
00096 
00097 //------------------------------------------------------------------------------
00098 /// Initializes an AT26 driver instance with the given SPI driver and chip
00099 /// select value.
00100 /// \param pAt26  Pointer to an AT26 driver instance.
00101 /// \param pSpid  Pointer to an SPI driver instance.
00102 /// \param cs  Chip select value to communicate with the serial flash.
00103 //------------------------------------------------------------------------------
00104 void AT26_Configure(At26 *pAt26, Spid *pSpid, unsigned char cs)
00105 {
00106     SpidCmd *pCommand;
00107 
00108     assert(pAt26 != NULL);
00109     assert(pSpid != NULL);
00110     assert(cs < 4);
00111 
00112     // Configure the SPI chip select for the serial flash
00113     SPID_ConfigureCS(pSpid, cs, CSR);
00114 
00115     // Initialize the AT26 fields
00116     pAt26->pSpid = pSpid;
00117     pAt26->pDesc = 0;
00118 
00119     // Initialize the command structure
00120     pCommand = &(pAt26->command);
00121     pCommand->pCmd = (unsigned char *) pAt26->pCmdBuffer;
00122     pCommand->callback = 0;
00123     pCommand->pArgument = 0;
00124     pCommand->spiCs = cs;
00125 }
00126 
00127 //------------------------------------------------------------------------------
00128 /// Returns 1 if the serial flash driver is currently busy executing a command;
00129 /// otherwise returns 0.
00130 /// \param pAt26  Pointer to an At26 driver instance.
00131 //------------------------------------------------------------------------------
00132 unsigned char AT26_IsBusy(At26 *pAt26)
00133 {
00134     return SPID_IsBusy(pAt26->pSpid);
00135 }
00136 
00137 //------------------------------------------------------------------------------
00138 /// Sends a command to the serial flash through the SPI. The command is made up
00139 /// of two parts: the first is used to transmit the command byte and optionally,
00140 /// address and dummy bytes. The second part is the data to send or receive.
00141 /// This function does not block: it returns as soon as the transfer has been
00142 /// started. An optional callback can be invoked to notify the end of transfer.
00143 /// Return 0 if successful; otherwise, returns AT26_ERROR_BUSY if the AT26
00144 /// driver is currently executing a command, or AT26_ERROR_SPI if the command
00145 /// cannot be sent because of a SPI error.
00146 /// \param pAt26  Pointer to an At26 driver instance.
00147 /// \param cmd  Command byte.
00148 /// \param cmdSize  Size of command (command byte + address bytes + dummy bytes).
00149 /// \param pData Data buffer.
00150 /// \param dataSize  Number of bytes to send/receive.
00151 /// \param address  Address to transmit.
00152 /// \param callback  Optional user-provided callback to invoke at end of transfer.
00153 /// \param pArgument  Optional argument to the callback function.
00154 //------------------------------------------------------------------------------
00155 unsigned char AT26_SendCommand(
00156     At26 *pAt26,
00157     unsigned char cmd,
00158     unsigned char cmdSize,
00159     unsigned char *pData,
00160     unsigned int dataSize,
00161     unsigned int address,
00162     SpidCallback callback,
00163     void *pArgument)
00164 
00165 {
00166     SpidCmd *pCommand;
00167 
00168     assert(pAt26 != NULL);
00169 
00170     // Check if the SPI driver is available
00171     if (AT26_IsBusy(pAt26))
00172 
00173         return AT26_ERROR_BUSY;
00174 
00175     // Store command and address in command buffer
00176     pAt26->pCmdBuffer[0] = (cmd & 0x000000FF)
00177                            | ((address & 0x0000FF) << 24)
00178                            | ((address & 0x00FF00) << 8)
00179                            | ((address & 0xFF0000) >> 8);
00180 
00181     // Update the SPI transfer descriptor
00182     pCommand = &(pAt26->command);
00183     pCommand->cmdSize = cmdSize;
00184     pCommand->pData = pData;
00185     pCommand->dataSize = dataSize;
00186     pCommand->callback = callback;
00187     pCommand->pArgument = pArgument;
00188 
00189     // Start the SPI transfer
00190     if (SPID_SendCommand(pAt26->pSpid, pCommand))
00191 
00192         return AT26_ERROR_SPI;
00193 
00194     return 0;
00195 }
00196 
00197 //------------------------------------------------------------------------------
00198 /// Tries to detect a serial firmware flash device given its JEDEC identifier.
00199 /// The JEDEC id can be retrieved by sending the correct command to the device.
00200 /// Returns the corresponding AT26 descriptor if found; otherwise returns 0.
00201 /// \param pAt26  Pointer to an AT26 driver instance.
00202 /// \param jedecId  JEDEC identifier of device.
00203 //------------------------------------------------------------------------------
00204 const At26Desc *AT26_FindDevice(At26 *pAt26, unsigned int jedecId)
00205 {
00206     unsigned int i = 0;
00207 
00208     assert(pAt26 != NULL);
00209 
00210     // Search if device is recognized
00211     pAt26->pDesc = 0;
00212 
00213     while ((i < NUMDATAFLASH) && !(pAt26->pDesc)) {
00214 
00215         if (jedecId == at26Devices[i].jedecId)
00216 
00217             pAt26->pDesc = &(at26Devices[i]);
00218 
00219         i++;
00220     }
00221 
00222     return (pAt26->pDesc);
00223 }
00224 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines