SAMV71 Xplained Ultra Software Package 1.5

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