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 }