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 }