SAM3S8/SD8 Software Package: libraries/memories/spi-flash/at45.c Source File

SAM3S8/SD8 Software Package 1.2

# at45.c

    00001 /* ----------------------------------------------------------------------------
    00002  *         ATMEL Microcontroller Software Support
    00003  * ----------------------------------------------------------------------------
    00004  * Copyright (c) 2008, 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 //         Headers
    00032 //------------------------------------------------------------------------------
    00033
    00034 #include "at45.h"
    00035 #include "board.h"
    00036 #include <assert.h>
    00037
    00038 #include <string.h>
    00039
    00040 //------------------------------------------------------------------------------
    00041 //         Internal definitions
    00042 //------------------------------------------------------------------------------
    00043
    00044 /// Number of dataflash which can be recognized.
    00045 #define NUMDATAFLASH    (sizeof(at45Devices) / sizeof(At45Desc))
    00046
    00047 //------------------------------------------------------------------------------
    00048 //         Local variables
    00049 //------------------------------------------------------------------------------
    00050
    00051 /// indicate if the device is configured as binary page or not.
    00052 static unsigned char configuredBinaryPage;
    00053
    00054 //------------------------------------------------------------------------------
    00055 //         Internal variables
    00056 //------------------------------------------------------------------------------
    00057
    00058 static const At45Desc at45Devices[] = {
    00059     {  512,  1, 264,   9, 0x0C, "AT45DB011D"},
    00060     { 1024,  1, 264,   9, 0x14, "AT45DB021D"},
    00061     { 2048,  1, 264,   9, 0x1C, "AT45DB041D"},
    00062     { 4096,  1, 264,   9, 0x24, "AT45DB081D"},
    00063     { 4096,  1, 528,  10, 0x2C, "AT45DB161D"},
    00064     { 8192,  1, 528,  10, 0x34, "AT45DB321D"},
    00065     { 8192,  1, 1056, 11, 0x3C, "AT45DB642D"},
    00066     {16384,  1, 1056, 11, 0x10, "AT45DB1282"},
    00067     {16384,  1, 2112, 12, 0x18, "AT45DB2562"},
    00068     {32768,  1, 2112, 12, 0x20, "AT45DB5122"}
    00069 };
    00070
    00071 //------------------------------------------------------------------------------
    00072 //         Exported functions
    00073 //------------------------------------------------------------------------------
    00074
    00075 //------------------------------------------------------------------------------
    00076 /// Initializes an AT45 instance and configures SPI chip select register.
    00077 /// Always returns 0.
    00078 /// \param pAt45  Pointer to the At45 instance to initialize.
    00079 /// \param pSpid  Pointer to the underlying SPI driver.
    00080 /// \param spiCs  Chip select value to connect to the At45.
    00081 //------------------------------------------------------------------------------
    00082 unsigned char AT45_Configure(At45 *pAt45, Spid *pSpid, unsigned char spiCs)
    00083 {
    00084     SpidCmd *pCommand;
    00085
    00086     // Sanity checks
    00087     ASSERT(pSpid, "AT45_Configure: pSpid is 0.\n\r");
    00088     ASSERT(pAt45, "AT45_Configure: pAt45 is 0.\n\r");
    00089
    00090     // Initialize the At45 instance
    00091     pAt45->pSpid = pSpid;
    00092     pAt45->pDesc = 0;
    00093     memset(pAt45->pCmdBuffer, 0, 8);
    00094
    00095     // Initialize the spidCmd structure
    00096     pCommand = &(pAt45->command);
    00097     pCommand->pCmd = pAt45->pCmdBuffer;
    00098     pCommand->callback = 0;
    00099     pCommand->pArgument = 0;
    00100     pCommand->spiCs = spiCs;
    00101
    00102     return 0;
    00103 }
    00104
    00105 //------------------------------------------------------------------------------
    00106 /// This function returns 1 if the At45 driver is not executing any command;
    00107 /// otherwise it returns 0.
    00108 /// \param pAt45  Pointer to an At45 instance.
    00109 //------------------------------------------------------------------------------
    00110 unsigned char AT45_IsBusy(At45 *pAt45)
    00111 {
    00112     return SPID_IsBusy(pAt45->pSpid);
    00113 }
    00114
    00115 //------------------------------------------------------------------------------
    00116 /// Sends a command to the dataflash through the SPI. The command is identified
    00117 /// by its command code and the number of bytes to transfer (1 + number of
    00118 /// address bytes + number of dummy bytes). If data needs to be received, then
    00119 /// a data buffer must be provided.
    00120 /// This function does not block; its optional callback will be invoked when
    00121 /// the transfer completes.
    00122 /// \param pAt45  Pointer to an At45 driver instance.
    00123 /// \param cmd  Command code.
    00124 /// \param cmdSize  Size of command code + address bytes + dummy bytes.
    00125 /// \param pData  Data buffer.
    00126 /// \param dataSize  Number of data bytes to send/receive.
    00127 /// \param address  Address at which the command is performed if meaningful.
    00128 /// \param callback  Optional callback to invoke at end of transfer.
    00129 /// \param pArgument  Optional parameter to the callback function.
    00130 //------------------------------------------------------------------------------
    00131 unsigned char AT45_SendCommand(
    00132     At45 *pAt45,
    00133     unsigned char cmd,
    00134     unsigned char cmdSize,
    00135     unsigned char *pData,
    00136     unsigned int dataSize,
    00137     unsigned int address,
    00138     SpidCallback callback,
    00139     void *pArgument)
    00140 {
    00141     SpidCmd *pCommand;
    00142     const At45Desc *pDesc = pAt45->pDesc;
    00143     unsigned int dfAddress = 0;
    00144
    00145     // Sanity checks
    00146     ASSERT(pAt45, "AT45_Command: pAt45 is 0.\n\r");
    00147     ASSERT(pDesc || (cmd == AT45_STATUS_READ),
    00148            "AT45_Command: Device has no descriptor, only STATUS_READ command allowed\n\r");
    00149
    00150     // Check if the SPI driver is available
    00151     if (AT45_IsBusy(pAt45)) {
    00152
    00153         return AT45_ERROR_LOCK;
    00154     }
    00155
    00156     // Compute command pattern
    00157     pAt45->pCmdBuffer[0] = cmd;
    00158
    00159     // Add address bytes if necessary
    00160     if (cmdSize > 1) {
    00161
    00162         ASSERT(pDesc, "AT45_Command: No descriptor for dataflash.\n\r");
    00163         if (!configuredBinaryPage) {
    00164             dfAddress =
    00165                 ((address / (pDesc->pageSize)) << pDesc->pageOffset)
    00166                  + (address % (pDesc->pageSize));
    00167         }
    00168         else {
    00169             dfAddress = address;
    00170         }
    00171         // Write address bytes
    00172         if (pDesc->pageNumber >= 16384) {
    00173
    00174             pAt45->pCmdBuffer[1] = ((dfAddress & 0x0F000000) >> 24);
    00175             pAt45->pCmdBuffer[2] = ((dfAddress & 0x00FF0000) >> 16);
    00176             pAt45->pCmdBuffer[3] = ((dfAddress & 0x0000FF00) >> 8);
    00177             pAt45->pCmdBuffer[4] = ((dfAddress & 0x000000FF) >> 0);
    00178
    00179             if ((cmd != AT45_CONTINUOUS_READ) && (cmd != AT45_PAGE_READ)) {
    00180
    00181                 cmdSize++;
    00182             }
    00183         }
    00184         else {
    00185
    00186             pAt45->pCmdBuffer[1] = ((dfAddress & 0x00FF0000) >> 16);
    00187             pAt45->pCmdBuffer[2] = ((dfAddress & 0x0000FF00) >> 8);
    00188             pAt45->pCmdBuffer[3] = ((dfAddress & 0x000000FF) >> 0);
    00189         }
    00190     }
    00191
    00192     // Update the SPI Transfer descriptors
    00193     pCommand = &(pAt45->command);
    00194     pCommand->cmdSize = cmdSize;
    00195     pCommand->pData = pData;
    00196     pCommand->dataSize = dataSize;
    00197     pCommand->callback = callback;
    00198     pCommand->pArgument = pArgument;
    00199
    00200     // Send Command and data through the SPI
    00201     if (SPID_SendCommand(pAt45->pSpid, pCommand)) {
    00202
    00203         return AT45_ERROR_SPI;
    00204     }
    00205
    00206     return 0;
    00207 }
    00208
    00209 //------------------------------------------------------------------------------
    00210 /// This function returns the At45Desc structure corresponding to the device
    00211 /// connected
    00212 /// It automatically initializes pAt45->pDesc field structure.
    00213 /// This function shall be called by the application before AT45_SendCommand.
    00214 /// Returns 0 if successful; Otherwise, returns AT45_ERROR_LOCK if the At45
    00215 /// driver is in use or AT45_ERROR_SPI if there was an error with the SPI driver.
    00216 /// \param pAt45  Pointer to an AT45 driver instance.
    00217 /// \param status  Device status register value.
    00218 //------------------------------------------------------------------------------
    00219 const At45Desc * AT45_FindDevice(At45 *pAt45, unsigned char status)
    00220 {
    00221     unsigned int i;
    00222     unsigned char id = AT45_STATUS_ID(status);
    00223
    00224     // Check if status is all one; in which case, it is assumed that no device
    00225     // is connected
    00226     if (status == 0xFF) {
    00227
    00228         return 0;
    00229     }
    00230
    00231     // Look in device array
    00232     i = 0;
    00233     pAt45->pDesc = 0;
    00234     while ((i < NUMDATAFLASH) && !(pAt45->pDesc)) {
    00235
    00236         if (at45Devices[i].id == id) {
    00237
    00238             pAt45->pDesc = &(at45Devices[i]);
    00239         }
    00240         i++;
    00241     }
    00242     configuredBinaryPage = AT45_STATUS_BINARY(status);
    00243     return pAt45->pDesc;
    00244 }
    00245
    00246 //------------------------------------------------------------------------------
    00247 /// This function returns the pagesize corresponding to the device connected
    00248 /// \param pAt45  Pointer to an AT45 driver instance.
    00249 //------------------------------------------------------------------------------
    00250 unsigned int  AT45_PageSize(At45 *pAt45)
    00251 {
    00252     unsigned int pagesize = pAt45->pDesc->pageSize;
    00253     if(((pAt45->pDesc->hasBinaryPage) == 0) || !configuredBinaryPage){
    00254         return pagesize;
    00255     }
    00256     return ((pagesize >> 8) << 8);
    00257 }

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines