Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: AT45DB161D SPIFLASH_AT45DB n-bed_AT45DB161E AT45DB161D
at45db161d.cpp
00001 /** 00002 * AT45DB161D module for arduino (C) Vincent 00003 * SPI flash memory 00004 * http://blog.blockos.org/?p=27 00005 * 00006 * bug fix by todotani 00007 * http://todotani.cocolog-nifty.com/blog/2009/07/arduino-4cf4.html 00008 * 00009 * Modified for mbed, 2011 Suga. 00010 */ 00011 #include "at45db161d.h" 00012 00013 /** CTOR **/ 00014 ATD45DB161D::ATD45DB161D(PinName mosi, PinName miso, PinName sclk, PinName cs) 00015 : _spi(mosi, miso, sclk), _cs(cs) 00016 {} 00017 00018 ATD45DB161D::ATD45DB161D(SPI &spi, PinName cs) 00019 : _spi(spi), _cs(cs) 00020 {} 00021 00022 /** DTOR **/ 00023 ATD45DB161D::~ATD45DB161D() 00024 {} 00025 00026 /** Setup SPI and pinout **/ 00027 void ATD45DB161D::Init() 00028 { 00029 // uint8_t clr; 00030 00031 /* Initialize pinout */ 00032 /* 00033 pinMode(DATAOUT, OUTPUT); 00034 pinMode(DATAIN, INPUT); 00035 pinMode(SPICLOCK, OUTPUT); 00036 pinMode(SLAVESELECT, OUTPUT); 00037 pinMode(DATAIN, INPUT); 00038 */ 00039 /* Disable device */ 00040 DF_CS_inactive; 00041 00042 /* Setup SPI */ 00043 // SPCR = (1 << SPE) | (1 << MSTR) | (1 << CPOL) | (1 << CPHA); 00044 _spi.format(8, 0); 00045 00046 /* Cleanup registers */ 00047 // clr = SPSR; 00048 // clr = SPDR; 00049 } 00050 00051 /** 00052 * Read status register 00053 * @return The content of the status register 00054 **/ 00055 uint8_t ATD45DB161D::ReadStatusRegister() 00056 { 00057 uint8_t status; 00058 00059 DF_CS_inactive; /* Make sure to toggle CS signal in order */ 00060 DF_CS_active; /* to reset Dataflash command decoder */ 00061 00062 /* Send status read command */ 00063 spi_transfer(AT45DB161D_STATUS_REGISTER_READ); 00064 /* Get result with a dummy write */ 00065 status = spi_transfer(0x00); 00066 00067 return status; 00068 } 00069 00070 /** 00071 * Read Manufacturer and Device ID 00072 * @note if id.extendedInfoLength is not equal to zero, 00073 * successive calls to spi_transfer(0xff) will return 00074 * the extended device information string bytes. 00075 * @param id Pointer to the ID structure to initialize 00076 **/ 00077 void ATD45DB161D::ReadManufacturerAndDeviceID(struct ATD45DB161D::ID *id) 00078 { 00079 00080 DF_CS_inactive; /* Make sure to toggle CS signal in order */ 00081 DF_CS_active; /* to reset Dataflash command decoder */ 00082 00083 /* Send status read command */ 00084 spi_transfer(AT45DB161D_READ_MANUFACTURER_AND_DEVICE_ID); 00085 00086 /* Manufacturer ID */ 00087 id->manufacturer = spi_transfer(0xff); 00088 /* Device ID (part 1) */ 00089 id->device[0] = spi_transfer(0xff); 00090 /* Device ID (part 2) */ 00091 id->device[1] = spi_transfer(0xff); 00092 /* Extended Device Information String Length */ 00093 id->extendedInfoLength = spi_transfer(0xff); 00094 00095 } 00096 00097 /** 00098 * Main Memory Page Read. 00099 * A main memory page read allows the user to read data directly from 00100 * any one of the 4096 pages in the main memory, bypassing both of the 00101 * data buffers and leaving the contents of the buffers unchanged. 00102 * 00103 * @param page Page of the main memory to read 00104 * @param offset Starting byte address within the page 00105 **/ 00106 void ATD45DB161D::ReadMainMemoryPage(uint16_t page, uint16_t offset) 00107 { 00108 DF_CS_inactive; /* Make sure to toggle CS signal in order */ 00109 DF_CS_active; /* to reset Dataflash command decoder */ 00110 00111 /* Send opcode */ 00112 spi_transfer(AT45DB161D_PAGE_READ); 00113 00114 /* Address (page | offset) */ 00115 spi_transfer((uint8_t)(page >> 6)); 00116 spi_transfer((uint8_t)((page << 2) | (offset >> 8))); 00117 spi_transfer((uint8_t)(offset & 0xff)); 00118 00119 /* 4 "don't care" bytes */ 00120 spi_transfer(0x00); 00121 spi_transfer(0x00); 00122 spi_transfer(0x00); 00123 spi_transfer(0x00); 00124 } 00125 00126 /** 00127 * Continuous Array Read. 00128 * Sequentially read a continuous stream of data. 00129 * @param page Page of the main memory where the sequential read will start 00130 * @param offset Starting byte address within the page 00131 * @param low If true the read operation will be performed in low speed mode (and in high speed mode if it's false). 00132 * @note The legacy mode is not currently supported 00133 **/ 00134 void ATD45DB161D::ContinuousArrayRead(uint16_t page, uint16_t offset, uint8_t low) 00135 { 00136 DF_CS_inactive; /* Make sure to toggle CS signal in order */ 00137 DF_CS_active; /* to reset Dataflash command decoder */ 00138 00139 /* Send opcode */ 00140 spi_transfer( low ? AT45DB161D_CONTINUOUS_READ_LOW_FREQ : 00141 AT45DB161D_CONTINUOUS_READ_HIGH_FREQ ); 00142 00143 /* Address (page | offset) */ 00144 spi_transfer((uint8_t)(page >> 6)); 00145 spi_transfer((uint8_t)((page << 2) | (offset >> 8))); 00146 spi_transfer((uint8_t)(offset & 0xff)); 00147 00148 if (!low) { spi_transfer(0x00); } 00149 } 00150 00151 00152 /** 00153 * Read the content of one of the SRAM data buffers (in low or high speed mode). 00154 * @param bufferNum Buffer to read (1 or 2) 00155 * @param offset Starting byte within the buffer 00156 * @param low If true the read operation will be performed in low speed mode (and in high speed mode if it's false). 00157 **/ 00158 void ATD45DB161D::BufferRead(uint8_t bufferNum, uint16_t offset, uint8_t low) 00159 { 00160 DF_CS_inactive; /* Make sure to toggle CS signal in order */ 00161 DF_CS_active; /* to reset Dataflash command decoder */ 00162 00163 /* Send opcode */ 00164 if(bufferNum == 1) 00165 { 00166 spi_transfer(low ? AT45DB161D_BUFFER_1_READ_LOW_FREQ : 00167 AT45DB161D_BUFFER_1_READ); 00168 } 00169 else 00170 { 00171 spi_transfer(low ? AT45DB161D_BUFFER_2_READ_LOW_FREQ : 00172 AT45DB161D_BUFFER_2_READ); 00173 00174 } 00175 00176 /* 14 "Don't care" bits */ 00177 spi_transfer(0x00); 00178 /* Rest of the "don't care" bits + bits 8,9 of the offset */ 00179 spi_transfer((uint8_t)(offset >> 8)); 00180 /* bits 7-0 of the offset */ 00181 spi_transfer((uint8_t)(offset & 0xff)); 00182 } 00183 00184 /** 00185 * Write data to one of the SRAM data buffers. Any further call to 00186 * spi_tranfer will return bytes contained in the data buffer until 00187 * a low-to-high transition is detected on the CS pin. If the end of 00188 * the data buffer is reached, the device will wrap around back to the 00189 * beginning of the buffer. 00190 * @param bufferNum Buffer to read (1 or 2) 00191 * @param offset Starting byte within the buffer 00192 **/ 00193 void ATD45DB161D::BufferWrite(uint8_t bufferNum, uint16_t offset) 00194 { 00195 DF_CS_inactive; /* Make sure to toggle CS signal in order */ 00196 DF_CS_active; /* to reset Dataflash command decoder */ 00197 00198 spi_transfer( (bufferNum == 1) ? AT45DB161D_BUFFER_1_WRITE : 00199 AT45DB161D_BUFFER_2_WRITE); 00200 00201 /* 14 "Don't care" bits */ 00202 spi_transfer(0x00); 00203 /* Rest of the "don't care" bits + bits 8,9 of the offset */ 00204 spi_transfer((uint8_t)(offset >> 8)); 00205 /* bits 7-0 of the offset */ 00206 spi_transfer((uint8_t)(offset & 0xff)); 00207 } 00208 00209 /** 00210 * Transfer data from buffer 1 or 2 to main memory page. 00211 * @param bufferNum Buffer to use (1 or 2) 00212 * @param page Page where the content of the buffer will transfered 00213 * @param erase If set the page will be first erased before the buffer transfer. 00214 * @note If erase is equal to zero, the page must have been previously erased using one of the erase command (Page or Block Erase). 00215 **/ 00216 void ATD45DB161D::BufferToPage(uint8_t bufferNum, uint16_t page, uint8_t erase) 00217 { 00218 DF_CS_inactive; /* Make sure to toggle CS signal in order */ 00219 DF_CS_active; /* to reset Dataflash command decoder */ 00220 00221 /* Opcode */ 00222 if(erase) 00223 { 00224 spi_transfer( (bufferNum == 1) ? AT45DB161D_BUFFER_1_TO_PAGE_WITH_ERASE : 00225 AT45DB161D_BUFFER_2_TO_PAGE_WITH_ERASE); 00226 } 00227 else 00228 { 00229 spi_transfer( (bufferNum == 1) ? AT45DB161D_BUFFER_1_TO_PAGE_WITHOUT_ERASE : 00230 AT45DB161D_BUFFER_2_TO_PAGE_WITHOUT_ERASE); 00231 } 00232 00233 /* 00234 * 3 address bytes consist of : 00235 * - 2 don�ft care bits 00236 * - 12 page address bits (PA11 - PA0) that specify the page in 00237 * the main memory to be written 00238 * - 10 don�ft care bits 00239 */ 00240 spi_transfer((uint8_t)(page >> 6)); 00241 spi_transfer((uint8_t)(page << 2)); 00242 spi_transfer(0x00); 00243 00244 DF_CS_inactive; /* Start transfer */ 00245 DF_CS_active; /* If erase was set, the page will first be erased */ 00246 00247 /* Wait for the end of the transfer */ 00248 while(!(ReadStatusRegister() & READY_BUSY)) 00249 {} 00250 } 00251 00252 /** 00253 * Transfer a page of data from main memory to buffer 1 or 2. 00254 * @param page Main memory page to transfer 00255 * @param buffer Buffer (1 or 2) where the data will be written 00256 **/ 00257 void ATD45DB161D::PageToBuffer(uint16_t page, uint8_t bufferNum) 00258 { 00259 DF_CS_inactive; /* Make sure to toggle CS signal in order */ 00260 DF_CS_active; /* to reset Dataflash command decoder */ 00261 00262 /* Send opcode */ 00263 spi_transfer((bufferNum == 1) ? AT45DB161D_TRANSFER_PAGE_TO_BUFFER_1 : 00264 AT45DB161D_TRANSFER_PAGE_TO_BUFFER_2); 00265 00266 /* 00267 * 3 address bytes consist of : 00268 * - 2 don�ft care bits 00269 * - 12 page address bits (PA11 - PA0) that specify the page in 00270 * the main memory to be written 00271 * - 10 don�ft care bits 00272 */ 00273 spi_transfer((uint8_t)(page >> 6)); 00274 spi_transfer((uint8_t)(page << 2)); 00275 spi_transfer(0x00); 00276 00277 DF_CS_inactive; /* Start page transfer */ 00278 DF_CS_active; 00279 00280 /* Wait for the end of the transfer */ 00281 while(!(ReadStatusRegister() & READY_BUSY)) 00282 {} 00283 } 00284 00285 /** 00286 * Erase a page in the main memory array. 00287 * @param page Page to erase 00288 **/ 00289 void ATD45DB161D::PageErase(uint16_t page) 00290 { 00291 DF_CS_inactive; /* Make sure to toggle CS signal in order */ 00292 DF_CS_active; /* to reset Dataflash command decoder */ 00293 00294 /* Send opcode */ 00295 spi_transfer(AT45DB161D_PAGE_ERASE); 00296 00297 /* 00298 * 3 address bytes consist of : 00299 * - 2 don�ft care bits 00300 * - 12 page address bits (PA11 - PA0) that specify the page in 00301 * the main memory to be written 00302 * - 10 don�ft care bits 00303 */ 00304 spi_transfer((uint8_t)(page >> 6)); 00305 spi_transfer((uint8_t)(page << 2)); 00306 spi_transfer(0x00); 00307 00308 DF_CS_inactive; /* Start block erase */ 00309 DF_CS_active; 00310 00311 /* Wait for the end of the block erase operation */ 00312 while(!(ReadStatusRegister() & READY_BUSY)) 00313 {} 00314 } 00315 00316 /** 00317 * Erase a block of eight pages at one time. 00318 * @param block Index of the block to erase 00319 **/ 00320 void ATD45DB161D::BlockErase(uint16_t block) 00321 { 00322 DF_CS_inactive; /* Make sure to toggle CS signal in order */ 00323 DF_CS_active; /* to reset Dataflash command decoder */ 00324 00325 /* Send opcode */ 00326 spi_transfer(AT45DB161D_BLOCK_ERASE); 00327 00328 /* 00329 * 3 address bytes consist of : 00330 * - 2 don�ft care bits 00331 * - 9 block address bits (PA11 - PA3) 00332 * - 13 don�ft care bits 00333 */ 00334 spi_transfer((uint8_t)(block >> 3)); 00335 spi_transfer((uint8_t)(block << 5)); 00336 spi_transfer(0x00); 00337 00338 DF_CS_inactive; /* Start block erase */ 00339 DF_CS_active; 00340 00341 /* Wait for the end of the block erase operation */ 00342 while(!(ReadStatusRegister() & READY_BUSY)) 00343 {} 00344 } 00345 00346 /** 00347 * Erase a sector in main memory. There are 16 sector on the 00348 * at45db161d and only one can be erased at one time. 00349 * @param sector Sector to erase (1-15) 00350 **/ 00351 void ATD45DB161D::SectoreErase(uint8_t sector) 00352 { 00353 DF_CS_inactive; /* Make sure to toggle CS signal in order */ 00354 DF_CS_active; /* to reset Dataflash command decoder */ 00355 00356 /* Send opcode */ 00357 spi_transfer(AT45DB161D_SECTOR_ERASE); 00358 00359 /* 00360 * 3 address bytes consist of : 00361 */ 00362 if((sector == 0x0a) || (sector == 0x0b)) 00363 { 00364 /* 00365 * - 11 don�ft care bits 00366 * - 00367 * - 12 don�ft care bits 00368 */ 00369 spi_transfer(0x00); 00370 spi_transfer(((sector & 0x01) << 4)); 00371 spi_transfer(0x00); 00372 } 00373 else 00374 { 00375 /* 00376 * - 2 don't care bits 00377 * - 4 sector number bits 00378 * - 18 don't care bits 00379 */ 00380 spi_transfer(sector << 1); 00381 spi_transfer(0x00); 00382 spi_transfer(0x00); 00383 } 00384 00385 DF_CS_inactive; /* Start block erase */ 00386 DF_CS_active; 00387 00388 /* Wait for the end of the block erase operation */ 00389 while(!(ReadStatusRegister() & READY_BUSY)) 00390 {} 00391 } 00392 00393 /** 00394 * Erase the entire chip memory. Sectors proteced or locked down will 00395 * not be erased. 00396 **/ 00397 void ATD45DB161D::ChipErase() 00398 { 00399 DF_CS_inactive; /* Make sure to toggle CS signal in order */ 00400 DF_CS_active; /* to reset Dataflash command decoder */ 00401 00402 /* Send chip erase sequence */ 00403 spi_transfer(AT45DB161D_CHIP_ERASE_0); 00404 spi_transfer(AT45DB161D_CHIP_ERASE_1); 00405 spi_transfer(AT45DB161D_CHIP_ERASE_2); 00406 spi_transfer(AT45DB161D_CHIP_ERASE_3); 00407 00408 DF_CS_inactive; /* Start chip erase */ 00409 DF_CS_active; 00410 00411 /* Wait for the end of the chip erase operation */ 00412 while(!(ReadStatusRegister() & READY_BUSY)) 00413 {} 00414 } 00415 00416 /** 00417 * This a combination of Buffer Write and Buffer to Page with 00418 * Built-in Erase. 00419 * @note You must call EndAndWait in order to start transfering data from buffer to page 00420 * @param page Page where the content of the buffer will transfered 00421 * @param offset Starting byte address within the buffer 00422 * @param bufferNum Buffer to use (1 or 2) 00423 * @warning UNTESTED 00424 **/ 00425 void ATD45DB161D::BeginPageWriteThroughBuffer(uint16_t page, uint16_t offset, uint8_t bufferNum) 00426 { 00427 DF_CS_inactive; /* Make sure to toggle CS signal in order */ 00428 DF_CS_active; /* to reset Dataflash command decoder */ 00429 00430 /* Send opcode */ 00431 spi_transfer((bufferNum == 1) ? AT45DB161D_PAGE_THROUGH_BUFFER_1 : 00432 AT45DB161D_PAGE_THROUGH_BUFFER_2); 00433 00434 /* Address */ 00435 spi_transfer((uint8_t)(page >> 6)); 00436 spi_transfer((uint8_t)((page << 2) | (offset >> 8))); 00437 spi_transfer((uint8_t)offset); 00438 } 00439 00440 /** 00441 * Perform a low-to-high transition on the CS pin and then poll 00442 * the status register to check if the dataflash is busy. 00443 **/ 00444 void ATD45DB161D::EndAndWait() 00445 { 00446 DF_CS_inactive; /* End current operation */ 00447 DF_CS_active; /* Some internal operation may occur 00448 * (buffer to page transfer, page erase, etc... ) */ 00449 00450 /* Wait for the chip to be ready */ 00451 while(!(ReadStatusRegister() & READY_BUSY)) 00452 {} 00453 00454 DF_CS_inactive; /* Release SPI Bus */ 00455 } 00456 00457 /** 00458 * Compare a page of data in main memory to the data in buffer 1 or 2. 00459 * @param page Page to test 00460 * @param bufferNum Buffer number 00461 * @return 00462 * - 1 if the page and the buffer contains the same data 00463 * - 0 else 00464 * @warning UNTESTED 00465 **/ 00466 int8_t ATD45DB161D::ComparePageToBuffer(uint16_t page, uint8_t bufferNum) 00467 { 00468 uint8_t status; 00469 00470 DF_CS_inactive; /* Make sure to toggle CS signal in order */ 00471 DF_CS_active; /* to reset Dataflash command decoder */ 00472 00473 /* Send opcode */ 00474 spi_transfer((bufferNum == 1) ? AT45DB161D_COMPARE_PAGE_TO_BUFFER_1 : 00475 AT45DB161D_COMPARE_PAGE_TO_BUFFER_2); 00476 00477 /* Page address */ 00478 spi_transfer((uint8_t)(page >> 6)); 00479 spi_transfer((uint8_t)(page << 2)); 00480 spi_transfer(0x00); 00481 00482 DF_CS_inactive; /* Start comparaison */ 00483 DF_CS_active; 00484 00485 /* Wait for the end of the comparaison and get the result */ 00486 while(!((status = ReadStatusRegister()) & READY_BUSY)) 00487 {} 00488 00489 // return ((status & COMPARE) == COMPARE); 00490 return ((status & COMPARE) ? 0 : 1); 00491 } 00492 00493 /** 00494 * Put the device into the lowest power consumption mode. 00495 * Once the device has entered the Deep Power-down mode, all 00496 * instructions are ignored except the Resume from Deep 00497 * Power-down command. 00498 * @warning UNTESTED 00499 **/ 00500 void ATD45DB161D::DeepPowerDown() 00501 { 00502 DF_CS_inactive; /* Make sure to toggle CS signal in order */ 00503 DF_CS_active; /* to reset Dataflash command decoder */ 00504 00505 /* Send opcode */ 00506 spi_transfer(AT45DB161D_DEEP_POWER_DOWN); 00507 00508 /* Enter Deep Power-Down mode */ 00509 DF_CS_inactive; 00510 00511 /* Safety delay */ 00512 // delay(100); 00513 wait_ms(100); 00514 } 00515 00516 /** 00517 * Takes the device out of Deep Power-down mode. 00518 **/ 00519 void ATD45DB161D::ResumeFromDeepPowerDown() 00520 { 00521 DF_CS_inactive; /* Make sure to toggle CS signal in order */ 00522 DF_CS_active; /* to reset Dataflash command decoder */ 00523 00524 /* Send opcode */ 00525 spi_transfer(AT45DB161D_RESUME_FROM_DEEP_POWER_DOWN); 00526 00527 /* Resume device */ 00528 DF_CS_inactive; 00529 00530 /* The CS pin must stay high during t_RDPD microseconds before the device 00531 * can receive any commands. 00532 * On the at45db161D t_RDPD = 35 microseconds. But we will wait 100 00533 * (just to be sure). */ 00534 // delay(100); 00535 wait_ms(100); 00536 } 00537 00538 /** **/
Generated on Wed Jul 13 2022 03:31:27 by
1.7.2