SAMV71 Xplained Ultra Software Package 1.3

at26d.c

00001 /* ----------------------------------------------------------------------------
00002  *         SAM Software Package License
00003  * ----------------------------------------------------------------------------
00004  * Copyright (c) 2014, 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 "at26.h"
00035 #include "at26d.h"
00036 #include "board.h"
00037 #include <math.h>
00038 #include <assert.h>
00039 
00040 //------------------------------------------------------------------------------
00041 //         Local functions
00042 //------------------------------------------------------------------------------
00043 
00044 //------------------------------------------------------------------------------
00045 /// Wait for transfer to finish calling the SPI driver ISR. (interrupts are disabled)
00046 /// \param pAt26  Pointer to an AT26 driver instance.
00047 //------------------------------------------------------------------------------
00048 static void AT26D_Wait(At26 *pAt26)
00049 {
00050     // Wait for transfer to finish
00051     while (AT26_IsBusy(pAt26))
00052     {
00053         SPID_Handler(pAt26->pSpid);
00054     }
00055 }
00056 
00057 //------------------------------------------------------------------------------
00058 /// Reads and returns the status register of the serial flash.
00059 /// \param pAt26  Pointer to an AT26 driver instance.
00060 //------------------------------------------------------------------------------
00061 static unsigned char AT26D_ReadStatus(At26 *pAt26)
00062 {
00063     unsigned char error, status;
00064 
00065     assert(pAt26 != NULL);
00066 
00067     // Issue a status read command
00068     error = AT26_SendCommand(pAt26, AT26_READ_STATUS, 1, &status, 1, 0, 0, 0);
00069     assert(!error); //, "-F- AT26_GetStatus: Failed to issue command.\n\r");
00070 
00071     // Wait for transfer to finish
00072     AT26D_Wait(pAt26);
00073 
00074     return status;
00075 }
00076 
00077 //------------------------------------------------------------------------------
00078 /// Writes the given value in the status register of the serial flash device.
00079 /// \param pAt26  Pointer to an AT26 driver instance.
00080 /// \param status  Status to write.
00081 //------------------------------------------------------------------------------
00082 static void AT26D_WriteStatus(At26 *pAt26, unsigned char status)
00083 {
00084     unsigned char error;
00085 
00086     assert(pAt26 != NULL);
00087 
00088     // Issue a write status command
00089     error = AT26_SendCommand(pAt26, AT26_WRITE_STATUS, 1, &status, 1, 0, 0, 0);
00090     assert(!error); //, "-F- AT26_WriteStatus: Failed to issue command.\n\r");
00091     // Wait for transfer to finish
00092     AT26D_Wait(pAt26);
00093 }
00094 
00095 
00096 //------------------------------------------------------------------------------
00097 //         Global functions
00098 //------------------------------------------------------------------------------
00099 
00100 //------------------------------------------------------------------------------
00101 /// Waits for the serial flash device to become ready to accept new commands.
00102 /// \param pAt26  Pointer to an AT26 driver instance.
00103 //------------------------------------------------------------------------------
00104 void AT26D_WaitReady(At26 *pAt26)
00105 {
00106     unsigned char ready = 0;
00107 
00108     assert(pAt26 != NULL);
00109 
00110     // Read status register and check busy bit
00111     while (!ready) {
00112 
00113         ready = ((AT26D_ReadStatus(pAt26) & AT26_STATUS_RDYBSY) == AT26_STATUS_RDYBSY_READY);
00114     }
00115 }
00116 
00117 //------------------------------------------------------------------------------
00118 /// Reads and returns the serial flash device ID.
00119 /// \param pAt26  Pointer to an AT26 driver instance.
00120 //------------------------------------------------------------------------------
00121 unsigned int AT26D_ReadJedecId(At26 *pAt26)
00122 {
00123     unsigned char error;
00124     unsigned int id = 0;
00125 
00126     assert(pAt26 != NULL);
00127  
00128     // Issue a read ID command
00129     error = AT26_SendCommand(pAt26, AT26_READ_JEDEC_ID, 1,
00130                              (unsigned char *) &id, 3, 0, 0, 0);
00131     assert(!error); //, "-F- AT26_GetJedecId: Could not issue command.\n\r");
00132 
00133     // Wait for transfer to finish
00134     AT26D_Wait(pAt26);
00135 
00136     return id;
00137 }
00138 
00139 //------------------------------------------------------------------------------
00140 /// Enables critical writes operation on a serial flash device, such as sector
00141 /// protection, status register, etc.
00142 /// \para pAt26  Pointer to an AT26 driver instance.
00143 //------------------------------------------------------------------------------
00144 void AT26D_EnableWrite(At26 *pAt26)
00145 {
00146     unsigned char error;
00147 
00148     assert(pAt26 != NULL);
00149 
00150     // Issue a write enable command
00151     error = AT26_SendCommand(pAt26, AT26_WRITE_ENABLE, 1, 0, 0, 0, 0, 0);
00152     assert(!error); //, "-F- AT26_EnableWrite: Could not issue command.\n\r");
00153 
00154     // Wait for transfer to finish
00155     AT26D_Wait(pAt26);
00156 }
00157 
00158 //------------------------------------------------------------------------------
00159 /// Unprotects the contents of the serial flash device.
00160 /// Returns 0 if the device has been unprotected; otherwise returns
00161 /// SF_PROTECTED.
00162 /// \param pAt26  Pointer to an AT26 driver instance.
00163 //------------------------------------------------------------------------------
00164 unsigned char AT26D_Unprotect(At26 *pAt26)
00165 {
00166     unsigned char status;
00167 
00168     assert(pAt26 != NULL);
00169 
00170     // Get the status register value to check the current protection
00171     status = AT26D_ReadStatus(pAt26);
00172     if ((status & AT26_STATUS_SWP) == AT26_STATUS_SWP_PROTNONE) {
00173 
00174         // Protection already disabled
00175         return 0;
00176     }
00177     
00178     // Check if sector protection registers are locked
00179     if ((status & AT26_STATUS_SPRL) == AT26_STATUS_SPRL_LOCKED) {
00180 
00181         // Unprotect sector protection registers by writing the status reg.
00182         AT26D_EnableWrite(pAt26);
00183         AT26D_WriteStatus(pAt26, 0);
00184     }
00185     
00186     // Perform a global unprotect command
00187     AT26D_EnableWrite(pAt26);
00188     AT26D_WriteStatus(pAt26, 0);
00189     
00190     // Check the new status
00191     status = AT26D_ReadStatus(pAt26);
00192     if ((status & (AT26_STATUS_SPRL | AT26_STATUS_SWP)) != 0) {
00193 
00194         return AT26_ERROR_PROTECTED;
00195     }
00196     else {
00197 
00198         return 0;
00199     }
00200 }
00201 
00202 //------------------------------------------------------------------------------
00203 /// Erases all the content of the memory chip.
00204 /// \param pAt26  Pointer to an AT26 driver instance.
00205 //------------------------------------------------------------------------------
00206 unsigned char AT26D_EraseChip(At26 *pAt26)
00207 {
00208     unsigned char status;
00209     unsigned char error;
00210 
00211     assert(pAt26 != NULL);
00212 
00213     // Check that the flash is unprotected
00214     status = AT26D_ReadStatus(pAt26);
00215     if ((status & AT26_STATUS_SWP) != AT26_STATUS_SWP_PROTNONE) {
00216         return AT26_ERROR_PROTECTED;
00217     }
00218     
00219     // Enable critical write operation
00220     AT26D_EnableWrite(pAt26);
00221     
00222     // Erase the chip
00223     error = AT26_SendCommand(pAt26, AT26_CHIP_ERASE_2, 1, 0, 0, 0, 0, 0);
00224     assert(!error); //, "-F- AT26_ChipErase: Could not issue command.\n\r");
00225     // Wait for transfer to finish
00226     AT26D_Wait(pAt26);
00227     // Poll the Serial flash status register until the operation is achieved
00228     AT26D_WaitReady(pAt26);
00229 
00230     return 0;
00231 }
00232 
00233 //------------------------------------------------------------------------------
00234 /// Erases the specified 64KB block of the serial firmware dataflash.
00235 /// Returns 0 if successful; otherwise returns AT26_ERROR_PROTECTED if the
00236 /// device is protected or AT26_ERROR_BUSY if it is busy executing a command.
00237 /// \param pAt26  Pointer to an AT26 driver instance.
00238 /// \param address  Address of the block to erase.
00239 //------------------------------------------------------------------------------
00240 unsigned char AT26D_EraseBlock(At26 *pAt26, unsigned int address)
00241 {
00242     unsigned char status;
00243     unsigned char error;
00244 
00245     assert(pAt26 != NULL);
00246 
00247     // Check that the flash is ready and unprotected
00248     status = AT26D_ReadStatus(pAt26);
00249     if ((status & AT26_STATUS_RDYBSY) != AT26_STATUS_RDYBSY_READY) {
00250         TRACE_ERROR("AT26D_EraseBlock : Flash busy\n\r");
00251         return AT26_ERROR_BUSY;
00252     }
00253     else if ((status & AT26_STATUS_SWP) != AT26_STATUS_SWP_PROTNONE) {
00254         TRACE_ERROR("AT26D_EraseBlock : Flash protected\n\r");
00255         return AT26_ERROR_PROTECTED;
00256     }
00257 
00258     // Enable critical write operation
00259       AT26D_EnableWrite(pAt26);
00260 
00261     // Start the block erase command
00262     error = AT26_SendCommand(pAt26, AT26_BlockEraseCmd(pAt26), 4, 0, 0, address, 0, 0);
00263     assert(!error); //, "-F- AT26_EraseBlock: Could not issue command.\n\r");
00264     // Wait for transfer to finish
00265     AT26D_Wait(pAt26);
00266     // Poll the Serial flash status register until the operation is achieved
00267     AT26D_WaitReady(pAt26);
00268 
00269     return 0;
00270 }
00271 
00272 //------------------------------------------------------------------------------
00273 /// Writes data at the specified address on the serial firmware dataflash. The
00274 /// page(s) to program must have been erased prior to writing. This function
00275 /// handles page boundary crossing automatically.
00276 /// Returns 0 if successful; otherwise, returns AT26_ERROR_PROGRAM is there has
00277 /// been an error during the data programming.
00278 /// \param pAt26  Pointer to an AT26 driver instance.
00279 /// \param pData  Data buffer.
00280 /// \param size  Number of bytes in buffer.
00281 /// \param address  Write address.
00282 //------------------------------------------------------------------------------
00283 unsigned char AT26D_Write(
00284     At26 *pAt26,
00285     unsigned char *pData,
00286     unsigned int size,
00287     unsigned int address)
00288 {
00289     unsigned int pageSize;
00290     unsigned int writeSize;
00291     unsigned char error;
00292     unsigned char status;
00293 
00294     assert(pAt26 != NULL);
00295     assert(pData != NULL);
00296 
00297     // Retrieve device page size
00298     pageSize = AT26_PageSize(pAt26);
00299 
00300     // Program one page after the other
00301     while (size > 0) {
00302         // Compute number of bytes to program in page
00303         writeSize = min(size, pageSize - (address % pageSize));
00304 
00305         // Enable critical write operation
00306         AT26D_EnableWrite(pAt26);
00307      
00308          // Program page
00309           error = AT26_SendCommand(pAt26, AT26_BYTE_PAGE_PROGRAM, 4,
00310                            pData, writeSize, address, 0, 0);
00311         assert(!error); //, "-F- AT26_WritePage: Failed to issue command.\n\r");
00312         // Wait for transfer to finish
00313         AT26D_Wait(pAt26);
00314         // Poll the Serial flash status register until the operation is achieved
00315         AT26D_WaitReady(pAt26);
00316 
00317         // Make sure that write was without error
00318         status = AT26D_ReadStatus(pAt26);
00319         if ((status & AT26_STATUS_EPE) == AT26_STATUS_EPE_ERROR) {
00320 
00321             return AT26_ERROR_PROGRAM;
00322         }
00323         pData += writeSize;
00324         size -= writeSize;
00325         address += writeSize;
00326     }
00327 
00328     return 0;
00329 }
00330 
00331 //------------------------------------------------------------------------------
00332 /// Reads data from the specified address on the serial flash.
00333 /// \param pAt26  Pointer to an AT26 driver instance.
00334 /// \param pData  Data buffer.
00335 /// \param size  Number of bytes to read.
00336 /// \param address  Read address.
00337 //------------------------------------------------------------------------------
00338 unsigned char AT26D_Read(
00339     At26 *pAt26,
00340     unsigned char *pData,
00341     unsigned int size,
00342     unsigned int address)
00343 {
00344     unsigned char error;
00345     
00346      // Start a read operation
00347       error = AT26_SendCommand(pAt26, AT26_READ_ARRAY_LF, 4, pData, size, address, 0, 0);
00348     assert(!error); //, "-F- AT26_Read: Could not issue command.\n\r");
00349     // Wait for transfer to finish
00350     AT26D_Wait(pAt26);
00351     
00352     return error;
00353 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines