SAMV71 Xplained Ultra Software Package 1.5

at45.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 "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     // Compute command pattern
00156     pAt45->pCmdBuffer[0] = cmd;
00157 
00158     // Add address bytes if necessary
00159     if (cmdSize > 1) {
00160 
00161         ASSERT(pDesc, "AT45_Command: No descriptor for dataflash.\n\r");
00162 
00163         if (!configuredBinaryPage) {
00164             dfAddress =
00165                 ((address / (pDesc->pageSize)) << pDesc->pageOffset)
00166                 + (address % (pDesc->pageSize));
00167         } else
00168             dfAddress = address;
00169 
00170         // Write address bytes
00171         if (pDesc->pageNumber >= 16384) {
00172 
00173             pAt45->pCmdBuffer[1] = ((dfAddress & 0x0F000000) >> 24);
00174             pAt45->pCmdBuffer[2] = ((dfAddress & 0x00FF0000) >> 16);
00175             pAt45->pCmdBuffer[3] = ((dfAddress & 0x0000FF00) >> 8);
00176             pAt45->pCmdBuffer[4] = ((dfAddress & 0x000000FF) >> 0);
00177 
00178             if ((cmd != AT45_CONTINUOUS_READ) && (cmd != AT45_PAGE_READ))
00179 
00180                 cmdSize++;
00181         } else {
00182 
00183             pAt45->pCmdBuffer[1] = ((dfAddress & 0x00FF0000) >> 16);
00184             pAt45->pCmdBuffer[2] = ((dfAddress & 0x0000FF00) >> 8);
00185             pAt45->pCmdBuffer[3] = ((dfAddress & 0x000000FF) >> 0);
00186         }
00187     }
00188 
00189     // Update the SPI Transfer descriptors
00190     pCommand = &(pAt45->command);
00191     pCommand->cmdSize = cmdSize;
00192     pCommand->pData = pData;
00193     pCommand->dataSize = dataSize;
00194     pCommand->callback = callback;
00195     pCommand->pArgument = pArgument;
00196 
00197     // Send Command and data through the SPI
00198     if (SPID_SendCommand(pAt45->pSpid, pCommand))
00199 
00200         return AT45_ERROR_SPI;
00201 
00202     return 0;
00203 }
00204 
00205 //------------------------------------------------------------------------------
00206 /// This function returns the At45Desc structure corresponding to the device
00207 /// connected
00208 /// It automatically initializes pAt45->pDesc field structure.
00209 /// This function shall be called by the application before AT45_SendCommand.
00210 /// Returns 0 if successful; Otherwise, returns AT45_ERROR_LOCK if the At45
00211 /// driver is in use or AT45_ERROR_SPI if there was an error with the SPI driver.
00212 /// \param pAt45  Pointer to an AT45 driver instance.
00213 /// \param status  Device status register value.
00214 //------------------------------------------------------------------------------
00215 const At45Desc *AT45_FindDevice(At45 *pAt45, unsigned char status)
00216 {
00217     unsigned int i;
00218     unsigned char id = AT45_STATUS_ID(status);
00219 
00220     // Check if status is all one; in which case, it is assumed that no device
00221     // is connected
00222     if (status == 0xFF)
00223 
00224         return 0;
00225 
00226     // Look in device array
00227     i = 0;
00228     pAt45->pDesc = 0;
00229 
00230     while ((i < NUMDATAFLASH) && !(pAt45->pDesc)) {
00231 
00232         if (at45Devices[i].id == id)
00233 
00234             pAt45->pDesc = &(at45Devices[i]);
00235 
00236         i++;
00237     }
00238 
00239     configuredBinaryPage = AT45_STATUS_BINARY(status);
00240     return pAt45->pDesc;
00241 }
00242 
00243 //------------------------------------------------------------------------------
00244 /// This function returns the pagesize corresponding to the device connected
00245 /// \param pAt45  Pointer to an AT45 driver instance.
00246 //------------------------------------------------------------------------------
00247 unsigned int  AT45_PageSize(At45 *pAt45)
00248 {
00249     unsigned int pagesize = pAt45->pDesc->pageSize;
00250 
00251     if (((pAt45->pDesc->hasBinaryPage) == 0) || !configuredBinaryPage)
00252         return pagesize;
00253 
00254     return ((pagesize >> 8) << 8);
00255 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines