├── .gitmodules ├── DataFlash.cpp ├── DataFlash.h ├── DataFlashCommands.h ├── DataFlashInlines.h ├── DataFlashSizes.h ├── README.md ├── examples ├── pageTest │ └── pageTest.pde ├── sectorErase │ └── sectorErase.pde └── sectorProtection │ └── sectorProtection.pde ├── library.properties └── test └── DataFlash_test.cpp /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "test"] 2 | path = test/arduino-tests 3 | url = git://github.com/BlockoS/arduino-tests.git 4 | -------------------------------------------------------------------------------- /DataFlash.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file DataFlash.cpp 3 | * @brief AT45DBxxxD Atmel Dataflash library for Arduino. 4 | * 5 | * @par Copyright: 6 | * - Copyright (C) 2010-2011 by Vincent Cruz. 7 | * - Copyright (C) 2011 by Volker Kuhlmann. @n 8 | * All rights reserved. 9 | * 10 | * @authors 11 | * - Vincent Cruz @n 12 | * cruz.vincent@gmail.com 13 | * - Volker Kuhlmann @n 14 | * http://volker.top.geek.nz/contact.html 15 | * 16 | * @par Description: 17 | * Please refer to @ref DataFlash.cpp for more informations. 18 | * 19 | * @par History: 20 | * - Version 1.x, 2010-2011. 21 | * - Released as at45db161d by Vincent Cruz. 22 | * - Version 2.0, 30 Aug 2011. 23 | * - Based on the library by Vincent Cruz, dalek branch, of 25 Aug 2011. 24 | * Substantially modified and improved by Volker Kuhlmann. 25 | * - Allow a quick .begin() / .end() to switch the SPI interface between 26 | * multiple SPI devices. 27 | * - Efficiency improvements. 28 | * - Re-arrange the mechanism to wait for the chip to become ready such that 29 | * waiting only happens when necessary. This allows interleaved writing - fill 30 | * up one buffer with new data while the other buffer is programmed to the 31 | * flash memory array. The downside is the the user now has to wait sometimes 32 | * too, depending on the state of the flash chip and the user program. 33 | * - Several improvements resulted in incompatible changes to the function API. 34 | * This shouldn't matter because the %Dataflash library is in the process of 35 | * evolving as an improvement of the at45db161d library and handles all the 36 | * AT45DBxxxD flash ICs instead of just the AT45DB161D. 37 | * - Version 2.2, 29 Dec 2011. 38 | * - Made to compile under Arduino 1.0 as well as 0.22. 39 | * - Removed 4 compiler warnings. 40 | * - Fixed a serious bug where accessing any pin set to -1 can cause random memory 41 | * corruption (the Arduino pin functions like digitalWrite() have no range 42 | * checking). 43 | * 44 | * @par Licence: GPLv3 45 | * This program is free software: you can redistribute it and/or modify 46 | * it under the terms of the GNU General Public License as published by 47 | * the Free Software Foundation, either version 3 of the License, or 48 | * (at your option) any later version. @n 49 | * @n 50 | * This program is distributed in the hope that it will be useful, 51 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 52 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 53 | * GNU General Public License for more details. @n 54 | * @n 55 | * You should have received a copy of the GNU General Public License 56 | * along with this program. If not, see . 57 | *****************************************************************************/ 58 | 59 | #if ARDUINO >= 100 60 | #include 61 | #else 62 | #include 63 | #endif 64 | 65 | #include "DataFlash.h" 66 | #include "DataFlashCommands.h" 67 | 68 | /** 69 | * @mainpage Atmel Dataflash library for Arduino. 70 | * 71 | * http://www.atmel.com/products/memories/sflash/dataflash.aspx 72 | **/ 73 | 74 | /** 75 | * @defgroup AT45DBxxxD Atmel Dataflash library for Arduino. 76 | * @{ 77 | **/ 78 | 79 | /* No need to put this into PROGMEM */ 80 | const DataFlash::AddressingInfos DataFlash::m_infos[7] = 81 | { 82 | { 9, 9, 2 }, // 1 83 | { 9, 10, 3 }, // 2 84 | { 9, 11, 3 }, // 4 85 | { 9, 12, 4 }, // 8 86 | { 10, 12, 4 }, // 16 87 | { 10, 13, 6 }, // 32 88 | { 11, 13, 5 } // 64 89 | }; 90 | 91 | /** 92 | * Constructor 93 | * This is not a good place to set the pins, because that causes hardware to be 94 | * initialised in the variable declaration part a long time before setup() is 95 | * called by the Arduino start-up code. 96 | * **/ 97 | DataFlash::DataFlash() 98 | { 99 | } 100 | 101 | /** Destructor **/ 102 | DataFlash::~DataFlash() 103 | { 104 | } 105 | 106 | /** 107 | * Set pin use, with defaults for reset and write-protect if not 108 | * specified as argument. 109 | * Set SPI transfer speed to "low" (can be changed with .speed() ). 110 | * @note This must be called the first time; afterwards .begin() can 111 | * be called without arguments. 112 | * @param csPin Chip select (Slave select) pin. 113 | * @param resetPin Reset pin, optional (default none). 114 | * @param wpPin Write protect pin, optional (default none). 115 | * **/ 116 | void DataFlash::setup(int8_t csPin, int8_t resetPin, int8_t wpPin) 117 | { 118 | m_chipSelectPin = csPin; 119 | m_resetPin = resetPin; 120 | m_writeProtectPin = wpPin; 121 | 122 | pinMode(m_chipSelectPin, OUTPUT); 123 | if (m_resetPin >= 0) 124 | { 125 | pinMode(m_resetPin, OUTPUT); 126 | digitalWrite(m_resetPin, HIGH); // set inactive 127 | } 128 | if (m_writeProtectPin >= 0) 129 | { 130 | pinMode(m_writeProtectPin, OUTPUT); 131 | digitalWrite(m_writeProtectPin, HIGH); // set inactive 132 | } 133 | 134 | m_erase = ERASE_AUTO; 135 | #ifdef AT45_USE_SPI_SPEED_CONTROL 136 | m_speed = SPEED_LOW; 137 | #endif 138 | 139 | /* Setup SPI */ 140 | SPI.setDataMode(SPI_MODE3); 141 | SPI.setBitOrder(MSBFIRST); 142 | SPI.setClockDivider(SPI_CLOCK_DIV2); 143 | 144 | /* Get DataFlash status register. */ 145 | uint8_t stat; 146 | stat = status(); 147 | 148 | /* Bit 3 of status register is ignored as it's always 1. Note that it is 149 | * equal to 0 on the obsolete chip with density higher than 64 MB. */ 150 | m_deviceIndex = ((stat & 0x38) >> 3) - 1; 151 | /* If bit 0 is set, page size is set to 256 bytes, 264 otherwise. */ 152 | m_bufferSize = m_infos[m_deviceIndex].bufferSize - (stat & 1); 153 | m_pageSize = m_infos[m_deviceIndex].pageSize; 154 | m_sectorSize = m_infos[m_deviceIndex].sectorSize; 155 | } 156 | 157 | /** 158 | * Initialise SPI interface for use with the %Dataflash, 159 | * allowing shared use with other SPI devices (which must however use 160 | * a different chipselect pin). 161 | * **/ 162 | void DataFlash::begin() 163 | { 164 | // Clear pending SPI interrupts? 165 | // [todo] SPISEttings 166 | } 167 | 168 | /** 169 | * Disable device and restore SPI configuration. 170 | **/ 171 | void DataFlash::end() 172 | { 173 | /* Disable device */ 174 | disable(); 175 | 176 | /* Don't call SPI.end() here to allow use of SPI interface with 177 | another chip. */ 178 | } 179 | 180 | /** 181 | * Disable (deselect) %Dataflash, then enable (select) it again. 182 | **/ 183 | void DataFlash::reEnable() 184 | { 185 | disable(); 186 | enable(); 187 | } 188 | 189 | /** 190 | * Set erase mode to automatic (default). 191 | **/ 192 | void DataFlash::autoErase() 193 | { 194 | m_erase = ERASE_AUTO; 195 | } 196 | 197 | /** 198 | * Set erase mode to manual. 199 | * User must erase pages first, using one of the erase commands. 200 | **/ 201 | void DataFlash::manualErase() 202 | { 203 | m_erase = ERASE_MANUAL; 204 | } 205 | 206 | /** 207 | * Set transfer speed (33MHz = low, 66MHz = high). 208 | * Note: Arduino supports 20MHz max, so using "high" is actually slower 209 | * because additional bytes have to be transferred for no benefit. 210 | **/ 211 | #ifdef AT45_USE_SPI_SPEED_CONTROL 212 | void DataFlash::setTransferSpeed(DataFlash::IOspeed rate) 213 | { 214 | m_speed = rate; 215 | } 216 | 217 | /** 218 | * Get transfer speed. 219 | **/ 220 | DataFlash::IOspeed DataFlash::getTransferSpeed() const 221 | { 222 | return m_speed; 223 | } 224 | #endif // AT45_USE_SPI_SPEED_CONTROL 225 | 226 | /** 227 | * Return whether the chip has completed the current operation and is 228 | * ready for the next. 229 | * Note that in some situations read/write access to one of the buffers 230 | * is permitted although the chip is busy. 231 | **/ 232 | uint8_t DataFlash::isReady() 233 | { 234 | return status() & AT45_READY; 235 | } 236 | 237 | /** 238 | * Wait until the chip is ready. 239 | **/ 240 | void DataFlash::waitUntilReady() 241 | { 242 | /* Wait for the end of the transfer taking place. */ 243 | while(!isReady()) {}; 244 | } 245 | 246 | /** 247 | * Read status register. 248 | * @return The content of the status register. 249 | * **/ 250 | uint8_t DataFlash::status() 251 | { 252 | uint8_t status; 253 | 254 | reEnable(); // Reset command decoder. 255 | 256 | /* Send status read command */ 257 | SPI.transfer(DATAFLASH_STATUS_REGISTER_READ); 258 | /* Get result with a dummy write */ 259 | status = SPI.transfer(0); 260 | 261 | disable(); 262 | 263 | return status; 264 | } 265 | 266 | /** 267 | * Read Manufacturer and Device ID. 268 | * @note If id.extendedInfoLength is not equal to zero, 269 | * successive calls to SPI.transfer() return 270 | * the extended device information bytes. 271 | * @param id ID structure. 272 | **/ 273 | void DataFlash::readID(struct DataFlash::ID &id) 274 | { 275 | reEnable(); // Reset command decoder. 276 | 277 | /* Send status read command */ 278 | SPI.transfer(DATAFLASH_READ_MANUFACTURER_AND_DEVICE_ID); 279 | 280 | /* Manufacturer ID */ 281 | id.manufacturer = SPI.transfer(0); 282 | /* Device ID (part 1) */ 283 | id.device[0] = SPI.transfer(0); 284 | /* Device ID (part 2) */ 285 | id.device[1] = SPI.transfer(0); 286 | /* Extended Device Information String Length */ 287 | id.extendedInfoLength = SPI.transfer(0); 288 | 289 | disable(); 290 | } 291 | 292 | /** 293 | * A main memory page read allows the user to read data directly from 294 | * any one of the pages in the main memory, bypassing both of the 295 | * data buffers and leaving the contents of the buffers unchanged. 296 | * Reading past the end of the page wraps around to the beginning of 297 | * the page. 298 | * The chip must remain enabled by this function; it is the user's 299 | * responsibility to disable the chip when finished reading. 300 | * @param page Page of the main memory to read. 301 | * @param offset Starting byte address within the page (default value: 0). 302 | **/ 303 | void DataFlash::pageRead(uint16_t page, uint16_t offset) 304 | { 305 | reEnable(); // Reset command decoder. 306 | 307 | /* Send opcode */ 308 | SPI.transfer(DATAFLASH_PAGE_READ); 309 | 310 | /* Address (page | offset) */ 311 | SPI.transfer(pageToHiU8(page)); 312 | SPI.transfer(pageToLoU8(page) | (uint8_t)(offset >> 8)); 313 | SPI.transfer((uint8_t)(offset & 0xff)); 314 | 315 | /* 4 "don't care" bytes */ 316 | SPI.transfer(0); 317 | SPI.transfer(0); 318 | SPI.transfer(0); 319 | SPI.transfer(0); 320 | 321 | // Can't disable the chip here! 322 | } 323 | 324 | /** 325 | * Sequentially read a continuous stream of data at the currently set 326 | * speed. Reading past the end of the last page wraps around to the 327 | * beginning of the first page. 328 | * The chip must remain enabled by this function; it is the user's 329 | * responsibility to disable the chip when finished reading. 330 | * @param page Page of the main memory where the sequential read will 331 | * start. 332 | * @param offset Starting byte address within the page (default value: 0). 333 | * @note The legacy mode is not needed and not supported. 334 | **/ 335 | void DataFlash::arrayRead(uint16_t page, uint16_t offset) 336 | { 337 | reEnable(); // Reset command decoder. 338 | 339 | /* Send opcode */ 340 | #ifdef AT45_USE_SPI_SPEED_CONTROL 341 | SPI.transfer(m_speed == SPEED_LOW ? DATAFLASH_CONTINUOUS_READ_LOW_FREQ : 342 | DATAFLASH_CONTINUOUS_READ_HIGH_FREQ); 343 | #else 344 | SPI.transfer(DATAFLASH_CONTINUOUS_READ_LOW_FREQ); 345 | #endif 346 | 347 | /* Address (page | offset) */ 348 | SPI.transfer(pageToHiU8(page)); 349 | SPI.transfer(pageToLoU8(page) | (uint8_t)(offset >> 8)); 350 | SPI.transfer((uint8_t)(offset & 0xff)); 351 | 352 | #ifdef AT45_USE_SPI_SPEED_CONTROL 353 | /* High frequency continuous read has an additional don't care byte. */ 354 | if(m_speed != SPEED_LOW) 355 | { 356 | SPI.transfer(0x00); 357 | } 358 | #endif 359 | 360 | // Can't disable the chip here! 361 | } 362 | 363 | /** 364 | * Read the content of one of the SRAM data buffer at the currently 365 | * set speed. Reading past the end of the buffer wraps around to the 366 | * beginning. 367 | * The chip must remain enabled by this function; it is the user's 368 | * responsibility to disable the chip when finished reading. 369 | * @param bufferNum Buffer to read (0 or 1). 370 | * @param offset Starting byte within the buffer (default value: 0). 371 | **/ 372 | void DataFlash::bufferRead(uint8_t bufferNum, uint16_t offset) 373 | { 374 | /* Wait for the end of the previous operation. */ 375 | waitUntilReady(); 376 | 377 | reEnable(); // Reset command decoder. 378 | 379 | /* Send opcode */ 380 | #ifdef AT45_USE_SPI_SPEED_CONTROL 381 | if (bufferNum) 382 | { 383 | SPI.transfer((m_speed == SPEED_LOW) ? DATAFLASH_BUFFER_2_READ_LOW_FREQ : 384 | DATAFLASH_BUFFER_2_READ); 385 | } 386 | else 387 | { 388 | SPI.transfer((m_speed == SPEED_LOW) ? DATAFLASH_BUFFER_1_READ_LOW_FREQ : 389 | DATAFLASH_BUFFER_1_READ); 390 | 391 | } 392 | #else 393 | SPI.transfer(bufferNum ? DATAFLASH_BUFFER_2_READ_LOW_FREQ : 394 | DATAFLASH_BUFFER_1_READ_LOW_FREQ); 395 | #endif 396 | 397 | /* 14 "Don't care" bits */ 398 | SPI.transfer(0x00); 399 | /* Rest of the "don't care" bits + bits 8,9 of the offset */ 400 | SPI.transfer((uint8_t)(offset >> 8)); 401 | /* bits 7-0 of the offset */ 402 | SPI.transfer((uint8_t)(offset & 0xff)); 403 | 404 | #ifdef AT45_USE_SPI_SPEED_CONTROL 405 | /* High frequency buffer read has an additional don't care byte. */ 406 | if(m_speed != SPEED_LOW) 407 | { 408 | SPI.transfer(0x00); 409 | } 410 | #endif 411 | 412 | // Can't disable the chip here! 413 | } 414 | 415 | /** 416 | * Write data to one of the SRAM data buffers at the currently set 417 | * speed. Writing past the end of the buffer wraps around to the 418 | * beginning. 419 | * The chip must remain enabled by this function; it is the user's 420 | * responsibility to disable the chip when finished reading. 421 | * @param bufferNum Buffer to read (0 or 1). 422 | * @param offset Starting byte within the buffer (default value: 0). 423 | **/ 424 | void DataFlash::bufferWrite(uint8_t bufferNum, uint16_t offset) 425 | { 426 | /* Wait for the end of the previous operation. */ 427 | waitUntilReady(); 428 | 429 | reEnable(); // Reset command decoder. 430 | 431 | SPI.transfer(bufferNum ? DATAFLASH_BUFFER_2_WRITE : 432 | DATAFLASH_BUFFER_1_WRITE); 433 | 434 | /* 14 "Don't care" bits */ 435 | SPI.transfer(0x00); 436 | /* Rest of the "don't care" bits + bits 8,9 of the offset */ 437 | SPI.transfer((uint8_t)(offset >> 8)); 438 | /* bits 7-0 of the offset */ 439 | SPI.transfer((uint8_t)(offset & 0xff)); 440 | 441 | // Can't disable the chip here! 442 | } 443 | 444 | /** 445 | * Transfer data from buffer 0 or 1 to a main memory page, erasing the 446 | * page first if auto-erase is set. If erase is manual, the page must 447 | * have been erased previously using one of the erase commands. 448 | * @param bufferNum Buffer to use (0 or 1). 449 | * @param page Page to which the content of the buffer is written. 450 | **/ 451 | void DataFlash::bufferToPage(uint8_t bufferNum, uint16_t page) 452 | { 453 | /* Wait for the end of the previous operation. */ 454 | waitUntilReady(); 455 | 456 | reEnable(); 457 | 458 | /* Opcode */ 459 | if (m_erase == ERASE_AUTO) 460 | { 461 | SPI.transfer(bufferNum ? DATAFLASH_BUFFER_2_TO_PAGE_WITH_ERASE : 462 | DATAFLASH_BUFFER_1_TO_PAGE_WITH_ERASE); 463 | } 464 | else 465 | { 466 | SPI.transfer(bufferNum ? DATAFLASH_BUFFER_2_TO_PAGE_WITHOUT_ERASE : 467 | DATAFLASH_BUFFER_1_TO_PAGE_WITHOUT_ERASE); 468 | } 469 | 470 | /* see pageToBuffer */ 471 | SPI.transfer(pageToHiU8(page)); 472 | SPI.transfer(pageToLoU8(page)); 473 | SPI.transfer(0x00); 474 | 475 | /* Start transfer. If erase was set to automatic, the page will first be 476 | erased. The chip remains busy until this operation finishes. */ 477 | disable(); 478 | } 479 | 480 | /** 481 | * Transfer a page of data from main memory to buffer 0 or 1. 482 | * @param page Main memory page to transfer. 483 | * @param bufferNum Buffer (0 or 1) to which the data is written. 484 | **/ 485 | void DataFlash::pageToBuffer(uint16_t page, uint8_t bufferNum) 486 | { 487 | /* Wait for the end of the previous operation. */ 488 | waitUntilReady(); 489 | 490 | reEnable(); 491 | 492 | /* Send opcode */ 493 | SPI.transfer(bufferNum ? DATAFLASH_TRANSFER_PAGE_TO_BUFFER_2 : 494 | DATAFLASH_TRANSFER_PAGE_TO_BUFFER_1); 495 | 496 | /* Output the 3 bytes adress. 497 | * For all DataFlashes 011D to 642D the number of trailing don't care bits 498 | * is equal to the number of page bits plus 3 (a block consists of 8 (1<<3) 499 | * pages), and always larger than 8 so the third byte is always 0. */ 500 | SPI.transfer(pageToHiU8(page)); 501 | SPI.transfer(pageToLoU8(page)); 502 | SPI.transfer(0); 503 | 504 | /* Start transfer. The chip remains busy until this operation finishes. */ 505 | disable(); 506 | } 507 | 508 | /** 509 | * Erase a page in the main memory array. 510 | * @param page Page to erase. 511 | **/ 512 | void DataFlash::pageErase(uint16_t page) 513 | { 514 | /* Wait for the end of the previous operation. */ 515 | waitUntilReady(); 516 | 517 | reEnable(); 518 | 519 | /* Send opcode */ 520 | SPI.transfer(DATAFLASH_PAGE_ERASE); 521 | 522 | /* see pageToBuffer */ 523 | SPI.transfer(pageToHiU8(page)); 524 | SPI.transfer(pageToLoU8(page)); 525 | SPI.transfer(0x00); 526 | 527 | /* Start page erase. The chip remains busy until this operation finishes. */ 528 | disable(); 529 | } 530 | 531 | /** 532 | * Erase a block of pages in a single operation. 533 | * @param block Block to erase. 534 | * @warning UNTESTED 535 | **/ 536 | void DataFlash::blockErase(uint16_t block) 537 | { 538 | /* Wait for the end of the previous operation. */ 539 | waitUntilReady(); 540 | 541 | reEnable(); 542 | 543 | /* Send opcode */ 544 | SPI.transfer(DATAFLASH_BLOCK_ERASE); 545 | 546 | /* Output the 3 bytes adress. 547 | * For all DataFlashes 011D to 642D the number of trailing don't care bits 548 | * is equal to the number of page bits plus 3 (a block consists of 8 (1<<3) 549 | * pages), and always larger than 8 so the third byte is always 0. */ 550 | uint8_t rightShift = m_bufferSize + 3 - 8; 551 | block >>= rightShift; 552 | SPI.transfer(highByte(block)); 553 | SPI.transfer(lowByte(block)); 554 | SPI.transfer(0x00); 555 | 556 | /* Start block erase. 557 | The chip remains busy until this operation finishes. */ 558 | disable(); 559 | } 560 | 561 | /** 562 | * Erase a sector of blocks in a single operation. 563 | * @param sector Sector to erase. 564 | **/ 565 | void DataFlash::sectorErase(int8_t sector) 566 | { 567 | /* Wait for the end of the previous operation. */ 568 | waitUntilReady(); 569 | 570 | reEnable(); 571 | 572 | /* Send opcode */ 573 | SPI.transfer(DATAFLASH_SECTOR_ERASE); 574 | 575 | if((sector == AT45_SECTOR_0A) || (sector == AT45_SECTOR_0B)) 576 | { 577 | SPI.transfer(0x00); 578 | SPI.transfer((static_cast(-sector) & 0x01) << (m_bufferSize - 5)); 579 | } 580 | else 581 | { 582 | uint8_t shift = m_bufferSize + m_pageSize - m_sectorSize - 16; 583 | SPI.transfer(sector << shift); 584 | SPI.transfer(0x00); 585 | } 586 | 587 | SPI.transfer(0x00); 588 | 589 | /* Start sector erase. 590 | The chip remains busy until this operation finishes. */ 591 | disable(); 592 | } 593 | 594 | #ifdef AT45_CHIP_ERASE_ENABLED 595 | /** 596 | * Erase the entire chip memory. Sectors protected or locked down will 597 | * not be erased. 598 | * @warning UNTESTED 599 | **/ 600 | void DataFlash::chipErase() 601 | { 602 | uint8_t sectorCount = 1 << m_sectorSize; 603 | 604 | sectorErase(AT45_SECTOR_0A); 605 | sectorErase(AT45_SECTOR_0B); 606 | for(uint8_t i=1; i> 8)); 660 | SPI.transfer((uint8_t)(offset & 0xff)); 661 | } 662 | 663 | /** 664 | * Compare a page of data in main memory to the data in buffer 0 or 1. 665 | * @param page Page to compare. 666 | * @param bufferNum Buffer number (0 or 1). 667 | * @return 668 | * - true If the page and the buffer contains the same data. 669 | * - false Otherwise. 670 | **/ 671 | int8_t DataFlash::isPageEqualBuffer(uint16_t page, uint8_t bufferNum) 672 | { 673 | reEnable(); // Reset command decoder. 674 | 675 | /* Send opcode */ 676 | SPI.transfer(bufferNum ? DATAFLASH_COMPARE_PAGE_TO_BUFFER_2 : 677 | DATAFLASH_COMPARE_PAGE_TO_BUFFER_1); 678 | 679 | /* Page address */ 680 | SPI.transfer(pageToHiU8(page)); 681 | SPI.transfer(pageToLoU8(page)); 682 | SPI.transfer(0x00); 683 | 684 | disable(); /* Start comparison */ 685 | 686 | /* Wait for the end of the comparison. */ 687 | waitUntilReady(); 688 | 689 | /* If bit 6 of the status register is 0 then the data in the 690 | * main memory page matches the data in the buffer. 691 | * If it's 1 then the data in the main memory page doesn't match. 692 | */ 693 | return ((status() & AT45_COMPARE) == 0); 694 | } 695 | 696 | /** 697 | * Put the device into the lowest power consumption mode. 698 | * Once the device has entered the Deep Power-down mode, all 699 | * instructions are ignored except the Resume from Deep 700 | * Power-down command. 701 | * @warning UNTESTED 702 | **/ 703 | void DataFlash::deepPowerDown() 704 | { 705 | reEnable(); // Reset command decoder. 706 | 707 | /* Send opcode */ 708 | SPI.transfer(DATAFLASH_DEEP_POWER_DOWN); 709 | 710 | /* Enter Deep Power-Down mode */ 711 | disable(); 712 | } 713 | 714 | /** 715 | * Takes the device out of Deep Power-down mode. 716 | **/ 717 | void DataFlash::resumeFromDeepPowerDown() 718 | { 719 | reEnable(); // Reset command decoder. 720 | 721 | /* Send opcode */ 722 | SPI.transfer(DATAFLASH_RESUME_FROM_DEEP_POWER_DOWN); 723 | 724 | /* Resume device */ 725 | disable(); 726 | 727 | /* The CS pin must stay high during t_RDPD microseconds before the device 728 | * can receive any commands. 729 | * On the at45db161D t_RDPD = 35 microseconds. 730 | * Wait 40us (just to be sure). */ 731 | delayMicroseconds(40); 732 | } 733 | 734 | /** 735 | * Reset device via the reset pin. 736 | * If no reset pint was specified (with begin()), this does nothing. 737 | **/ 738 | void DataFlash::hardReset() 739 | { 740 | if (m_resetPin >= 0) 741 | { 742 | digitalWrite(m_resetPin, LOW); 743 | 744 | /* The reset pin should stay low for at least 10us (table 18.4). */ 745 | delayMicroseconds(10); 746 | 747 | /* According to the Dataflash spec (21.6 Reset Timing), 748 | * the CS pin should be in high state before RESET 749 | * is deasserted (ie HIGH). */ 750 | disable(); 751 | /* Just to be sure that the high state is reached */ 752 | delayMicroseconds(1); 753 | 754 | digitalWrite(m_resetPin, HIGH); 755 | 756 | /* Reset recovery time = 1us */ 757 | delayMicroseconds(1); 758 | } 759 | } 760 | 761 | void DataFlash::enableSectorProtection() 762 | { 763 | waitUntilReady(); 764 | if(m_writeProtectPin >= 0) 765 | digitalWrite(m_writeProtectPin, HIGH); 766 | reEnable(); 767 | 768 | SPI.transfer(DATAFLASH_ENABLE_SECTOR_PROTECTION_0); 769 | SPI.transfer(DATAFLASH_ENABLE_SECTOR_PROTECTION_1); 770 | SPI.transfer(DATAFLASH_ENABLE_SECTOR_PROTECTION_2); 771 | SPI.transfer(DATAFLASH_ENABLE_SECTOR_PROTECTION_3); 772 | 773 | disable(); 774 | if(m_writeProtectPin >= 0) 775 | digitalWrite(m_writeProtectPin, LOW); 776 | } 777 | 778 | void DataFlash::disableSectorProtection() 779 | { 780 | waitUntilReady(); 781 | if(m_writeProtectPin >= 0) 782 | digitalWrite(m_writeProtectPin, HIGH); 783 | reEnable(); 784 | 785 | SPI.transfer(DATAFLASH_DISABLE_SECTOR_PROTECTION_0); 786 | SPI.transfer(DATAFLASH_DISABLE_SECTOR_PROTECTION_1); 787 | SPI.transfer(DATAFLASH_DISABLE_SECTOR_PROTECTION_2); 788 | SPI.transfer(DATAFLASH_DISABLE_SECTOR_PROTECTION_3); 789 | 790 | disable(); 791 | } 792 | 793 | void DataFlash::eraseSectorProtectionRegister() 794 | { 795 | waitUntilReady(); 796 | if(m_writeProtectPin >= 0) 797 | digitalWrite(m_writeProtectPin, HIGH); 798 | reEnable(); 799 | 800 | SPI.transfer(DATAFLASH_ERASE_SECTOR_PROTECTION_REGISTER_0); 801 | SPI.transfer(DATAFLASH_ERASE_SECTOR_PROTECTION_REGISTER_1); 802 | SPI.transfer(DATAFLASH_ERASE_SECTOR_PROTECTION_REGISTER_2); 803 | SPI.transfer(DATAFLASH_ERASE_SECTOR_PROTECTION_REGISTER_3); 804 | 805 | disable(); 806 | 807 | waitUntilReady(); 808 | if(m_writeProtectPin >= 0) 809 | digitalWrite(m_writeProtectPin, LOW); 810 | } 811 | 812 | uint8_t DataFlash::programSectorProtectionRegister(const DataFlash::SectorProtectionStatus& status) 813 | { 814 | uint8_t sectorCount = 1 << m_sectorSize; 815 | eraseSectorProtectionRegister(); 816 | 817 | if(m_writeProtectPin >= 0) 818 | digitalWrite(m_writeProtectPin, HIGH); 819 | reEnable(); 820 | 821 | SPI.transfer(DATAFLASH_PROGRAM_SECTOR_PROTECTION_REGISTER_0); 822 | SPI.transfer(DATAFLASH_PROGRAM_SECTOR_PROTECTION_REGISTER_1); 823 | SPI.transfer(DATAFLASH_PROGRAM_SECTOR_PROTECTION_REGISTER_2); 824 | SPI.transfer(DATAFLASH_PROGRAM_SECTOR_PROTECTION_REGISTER_3); 825 | 826 | for(uint8_t i=0; i= 0) 834 | digitalWrite(m_writeProtectPin, LOW); 835 | 836 | return sectorCount; 837 | } 838 | 839 | uint8_t DataFlash::readSectorProtectionRegister(DataFlash::SectorProtectionStatus& status) 840 | { 841 | uint8_t sectorCount = 1 << m_sectorSize; 842 | 843 | waitUntilReady(); 844 | reEnable(); 845 | 846 | SPI.transfer(DATAFLASH_READ_SECTOR_PROTECTION_REGISTER); 847 | SPI.transfer(0xff); 848 | SPI.transfer(0xff); 849 | SPI.transfer(0xff); 850 | 851 | for(uint8_t i=0; i 0) && (sectorId < 64)) 891 | { 892 | data[sectorId] = status ? 0xff : 0x00; 893 | } 894 | } 895 | bool DataFlash::SectorProtectionStatus::get(int8_t sectorId) const 896 | { 897 | if(sectorId == AT45_SECTOR_0A) 898 | { 899 | return (data[0] & 0xc0) ? true : false; 900 | } 901 | else if(sectorId == AT45_SECTOR_0B) 902 | { 903 | return (data[0] & 0x30) ? true : false; 904 | } 905 | else if((sectorId > 0) && (sectorId < 64)) 906 | { 907 | return data[sectorId] ? true : false; 908 | } 909 | return false; 910 | } 911 | void DataFlash::SectorProtectionStatus::clear() 912 | { 913 | for(uint8_t i=0; i<64; i++) 914 | { 915 | data[i] = 0; 916 | } 917 | } 918 | 919 | /** 920 | * @} 921 | **/ 922 | -------------------------------------------------------------------------------- /DataFlash.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file DataFlash.h 3 | * @brief AT45DBxxxD Atmel Dataflash library for Arduino. 4 | * 5 | * @par Copyright: 6 | * - Copyright (C) 2010-2011 by Vincent Cruz. 7 | * - Copyright (C) 2011 by Volker Kuhlmann. @n 8 | * All rights reserved. 9 | * 10 | * @authors 11 | * - Vincent Cruz @n 12 | * cruz.vincent@gmail.com 13 | * - Volker Kuhlmann @n 14 | * http://volker.top.geek.nz/contact.html 15 | * 16 | * @par Description: 17 | * Please refer to @ref DataFlash.cpp for more informations. 18 | * 19 | * @par History: 20 | * - Version 1.x, 2010-2011. 21 | * - Version 2.0, 30 Aug 2011. 22 | * - Version 2.2, 29 Dec 2011. 23 | * 24 | * @par Licence: GPLv3 25 | * This program is free software: you can redistribute it and/or modify 26 | * it under the terms of the GNU General Public License as published by 27 | * the Free Software Foundation, either version 3 of the License, or 28 | * (at your option) any later version. @n 29 | * @n 30 | * This program is distributed in the hope that it will be useful, 31 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 32 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 33 | * GNU General Public License for more details. @n 34 | * @n 35 | * You should have received a copy of the GNU General Public License 36 | * along with this program. If not, see . 37 | *****************************************************************************/ 38 | 39 | #ifndef DATAFLASH_H_ 40 | #define DATAFLASH_H_ 41 | 42 | #include 43 | #include "DataFlashSizes.h" 44 | #include 45 | 46 | /** 47 | * @addtogroup AT45DBxxxD 48 | * @{ 49 | **/ 50 | 51 | /** 52 | * @defgroup AT45_CHIP_ERASE_ENABLED Chip erase command prevention. 53 | * @note Will be removed once chip erase is re-implemented. 54 | * Datasheets are missing errata, but see AT45DB321D. Basically the 55 | * silicon is buggy and Atmel suggests to use block erase instead, 56 | * giving rise to the suspicion that sector erase doesn't work either. 57 | * @{ 58 | **/ 59 | #ifdef AT45_CHIP_ERASE_ENABLED 60 | #undef AT45_CHIP_ERASE_ENABLED 61 | #endif 62 | /** 63 | * @} 64 | **/ 65 | 66 | /** 67 | * @defgroup AT45_USE_SPI_SPEED_CONTROL SPI transfer speed control. 68 | * @warning This feature is experimental. Use it at your own risk! 69 | * %Dataflash supports low and high speed transfers. However the low 70 | * speed transfers are more than 3x the speed of what an Arduino 71 | * with ATmega 328P or 1280 can provide, so this makes no sense at 72 | * all with that hardware. 73 | * Leaving in, in case it's useful for other hardware. Tested code. 74 | * Dropping this saves 86 bytes. 75 | * @{ 76 | **/ 77 | #ifdef AT45_USE_SPI_SPEED_CONTROL 78 | #undef AT45_USE_SPI_SPEED_CONTROL 79 | #endif 80 | /** 81 | * @} 82 | **/ 83 | 84 | /** 85 | * @defgroup PINOUT Default pin connections. 86 | * Default pin values for Chip Select (CS), Reset (RS) and 87 | * Write Protec (WP). 88 | * Reset and Write Protect pins are not used by default. 89 | * @{ 90 | **/ 91 | /** Chip select (CS) **/ 92 | #define AT45_SS_PIN 10 93 | /** Reset (Reset) **/ 94 | #define AT45_RESET_PIN -1 95 | /** Write protect (WP) **/ 96 | #define AT45_WP_PIN -1 97 | /** 98 | * @} 99 | **/ 100 | 101 | /** 102 | * @defgroup STATUS_REGISTER_FORMAT Status register format. 103 | * The status register can be used to determine device state 104 | * (ready/busy) or to retrieve the result of an operation. 105 | * @{ 106 | **/ 107 | /** 108 | * Ready/busy status is indicated using bit 7 of the status register. 109 | * If bit 7 is a 1, then the device is not busy and is ready to accept 110 | * the next command. If bit 7 is a 0, then the device is in a busy 111 | * state. 112 | **/ 113 | #define AT45_READY 0x80 114 | /** 115 | * Result of the most recent Memory Page to Buffer Compare operation. 116 | * If this bit is equal to 0, then the data in the main memory page 117 | * matches the data in the buffer. If it's 1 then at least 1 byte in 118 | * the main memory page does not match the data in the buffer. 119 | **/ 120 | #define AT45_COMPARE 0x40 121 | /** 122 | * Bit 1 in the Status Register is used to provide information to the 123 | * user whether or not the sector protection has been enabled or 124 | * disabled, either by software-controlled method or 125 | * hardware-controlled method. 1 means that the sector protection has 126 | * been enabled and 0 that it has been disabled. 127 | **/ 128 | #define AT45_PROTECT 0x02 129 | /** 130 | * Bit 0 indicates whether the page size of the main memory array is 131 | * configured for "power of 2" binary page size (512 bytes) (bit=1) or 132 | * standard %Dataflash page size (528 bytes) (bit=0). 133 | **/ 134 | #define AT45_PAGESIZE_PWR2 0x01 135 | /** 136 | * Bits 5, 4, 3 and 2 indicates the device density. The decimal value 137 | * of these four binary bits does not equate to the device density; the 138 | * four bits represent a combinational code relating to differing 139 | * densities of %Dataflash devices. The device density is not the same 140 | * as the density code indicated in the JEDEC device ID information. 141 | * The device density is provided only for backward compatibility. 142 | **/ 143 | #define AT45_SIZE_CODE 0x2C 144 | /** 145 | * @} 146 | **/ 147 | 148 | /** 149 | * @defgroup SPECIFIC_SECTORS Special sectors ID. 150 | * The following list gives the number of pages per sector (P) for the AT45 family: 151 | * - AT45DB011D 128 152 | * - AT45DB021D 128 153 | * - AT45DB041D 256 154 | * - AT45DB081D 256 155 | * - AT45DB161D 256 156 | * - AT45DB321D 128 157 | * - AT45DB642D 256 158 | * 159 | * On every %Dataflash, the first 8 pages belongs to the sectod 0a. It's followed 160 | * by sector 0b which holds only (P-8) pages (248 on an AT45DB161D). Then comes N-1 161 | * (N is the number of sectors) sectors of size P numbered from 1 to N-1 (included). 162 | * @see chapter titled "Memory Array" in the corresponding %Dataflash datasheet. 163 | * @{ 164 | **/ 165 | /** 166 | * Sector 0a id. 167 | **/ 168 | #define AT45_SECTOR_0A -1 169 | /** 170 | * Sector 0b id. 171 | **/ 172 | #define AT45_SECTOR_0B 0 173 | /** 174 | * @} 175 | **/ 176 | 177 | 178 | /** 179 | * AT45DBxxxD Atmel %Dataflash device. 180 | **/ 181 | class DataFlash 182 | { 183 | public: 184 | /** 185 | * @brief ID structure. 186 | * This structure contains information about the 187 | * %Dataflash chip being used. 188 | **/ 189 | struct ID 190 | { 191 | uint8_t manufacturer; /**< Manufacturer id **/ 192 | uint8_t device[2]; /**< Device id **/ 193 | uint8_t extendedInfoLength; /**< Extended device information string length **/ 194 | }; 195 | 196 | /** 197 | * @brief Erase mode. 198 | * Whether pages are erased automatically before being written, or 199 | * whether this is expected to be done explicitly first. 200 | **/ 201 | enum erasemode 202 | { 203 | ERASE_AUTO, /**< Pages are erased automatically. **/ 204 | ERASE_MANUAL /**< Pages are erased by the user first. **/ 205 | }; 206 | 207 | /** 208 | * @brief IO speed. 209 | * The max SPI SCK frequency an ATmega 328P or 1280 can generate is 210 | * 10MHz. The limit for low-speed SCK for AT45DBxxxD %Dataflash is 33MHz 211 | * (66MHz for high-speed). Supporting high-speed for Arduino is a waste of 212 | * time... 213 | **/ 214 | enum IOspeed 215 | { 216 | SPEED_LOW, /**< Low speed transfers up to 33MHz **/ 217 | SPEED_HIGH /**< High speed transfers up to 66MHz **/ 218 | }; 219 | 220 | public: 221 | /** Constructor **/ 222 | DataFlash(); 223 | 224 | /** Destructor **/ 225 | ~DataFlash(); 226 | 227 | /** 228 | * Set pin use, with defaults for reset and write-protect if not 229 | * specified as argument. 230 | * Set SPI transfer speed to "low" (can be changed with .speed() ). 231 | * @note This must be called the first time; afterwards .begin() can 232 | * be called without arguments. 233 | * @param csPin Chip select (Slave select) pin. 234 | * @param resetPin Reset pin, optional (default none). 235 | * @param wpPin Write protect pin, optional (default none). 236 | * **/ 237 | void setup(int8_t csPin, int8_t resetPin=AT45_RESET_PIN, int8_t wpPin=AT45_WP_PIN); 238 | 239 | /** 240 | * Initialise SPI interface for use with the %Dataflash, 241 | * allowing shared use with other SPI devices (which must however use 242 | * a different chip select pin). 243 | * **/ 244 | void begin(); 245 | 246 | /** 247 | * Restore SPI configuration, so it can be used by other SPI devices. 248 | **/ 249 | void end(); 250 | 251 | /** 252 | * Enable (select) %Dataflash. 253 | **/ 254 | inline void enable(); 255 | 256 | /** 257 | * Disable (deselect) %Dataflash. 258 | **/ 259 | inline void disable(); 260 | 261 | /** 262 | * Disable (deselect) %Dataflash, then enable (select) it again. 263 | **/ 264 | void reEnable(); 265 | 266 | /** 267 | * Set erase mode to automatic (default). 268 | **/ 269 | void autoErase(); 270 | 271 | /** 272 | * Set erase mode to manual. 273 | * User must erase pages first, using one of the erase commands. 274 | **/ 275 | void manualErase(); 276 | 277 | #ifdef AT45_USE_SPI_SPEED_CONTROL 278 | /** 279 | * Set transfer speed (33MHz = low, 66MHz = high). 280 | * Note: Arduino supports 20MHz max, so using "high" is actually slower 281 | * because additional bytes have to be transferred for no benefit. 282 | **/ 283 | void setTransferSpeed(IOspeed rate); 284 | 285 | /** 286 | * Get transfer speed. 287 | **/ 288 | IOspeed getTransferSpeed() const; 289 | #endif // AT45_USE_SPI_SPEED_CONTROL 290 | 291 | /** 292 | * Return whether the chip has completed the current operation and is 293 | * ready for the next. 294 | * Note that in some situations read/write access to one of the buffers 295 | * is permitted although the chip is busy. 296 | **/ 297 | uint8_t isReady(); 298 | 299 | /** 300 | * @brief Wait until the chip is ready. 301 | * Perform a low-to-high transition on the CS pin and then poll 302 | * the status register until the %Dataflash is ready for the next 303 | * operation. 304 | */ 305 | void waitUntilReady(); 306 | 307 | /** 308 | * Same as waitUntilReady 309 | **/ 310 | inline void endAndWait(); 311 | 312 | /** 313 | * Read status register. 314 | * @return The content of the status register. 315 | * **/ 316 | uint8_t status(); 317 | 318 | /** 319 | * Read Manufacturer and Device ID. 320 | * @note If id.extendedInfoLength is not equal to zero, 321 | * successive calls to SPI.transfer() return 322 | * the extended device information bytes. 323 | * @param id ID structure. 324 | **/ 325 | void readID(DataFlash::ID &id); 326 | 327 | /** 328 | * A main memory page read allows the user to read data directly from 329 | * any one of the pages in the main memory, bypassing both of the 330 | * data buffers and leaving the contents of the buffers unchanged. 331 | * Reading past the end of the page wraps around to the beginning of 332 | * the page. 333 | * The chip must remain enabled by this function; it is the user's 334 | * responsibility to disable the chip when finished reading. 335 | * @param page Page of the main memory to read. 336 | * @param offset Starting byte address within the page (default value: 0). 337 | **/ 338 | void pageRead(uint16_t page, uint16_t offset=0); 339 | 340 | /** 341 | * Sequentially read a continuous stream of data at the currently set 342 | * speed. Reading past the end of the last page wraps around to the 343 | * beginning of the first page. 344 | * The chip must remain enabled by this function; it is the user's 345 | * responsibility to disable the chip when finished reading. 346 | * @param page Page of the main memory where the sequential read will 347 | * start. 348 | * @param offset Starting byte address within the page (default value: 0). 349 | * @note The legacy mode is not needed and not supported. 350 | **/ 351 | void arrayRead(uint16_t page, uint16_t offset=0); 352 | 353 | /** 354 | * Read the content of one of the SRAM data buffer at the currently 355 | * set speed. Reading past the end of the buffer wraps around to the 356 | * beginning. 357 | * The chip must remain enabled by this function; it is the user's 358 | * responsibility to disable the chip when finished reading. 359 | * @param bufferNum Buffer to read (0 or 1). 360 | * @param offset Starting byte within the buffer (default value: 0). 361 | **/ 362 | void bufferRead(uint8_t bufferNum, uint16_t offset=0); 363 | 364 | /** 365 | * Write data to one of the SRAM data buffers at the currently set 366 | * speed. Writing past the end of the buffer wraps around to the 367 | * beginning. 368 | * The chip must remain enabled by this function; it is the user's 369 | * responsibility to disable the chip when finished reading. 370 | * @param bufferNum Buffer to read (0 or 1). 371 | * @param offset Starting byte within the buffer (default value: 0). 372 | **/ 373 | void bufferWrite(uint8_t bufferNum, uint16_t offset); 374 | 375 | /** 376 | * Transfer data from buffer 0 or 1 to a main memory page, erasing the 377 | * page first if auto-erase is set. If erase is manual, the page must 378 | * have been erased previously using one of the erase commands. 379 | * @param bufferNum Buffer to use (0 or 1). 380 | * @param page Page to which the content of the buffer is written. 381 | **/ 382 | void bufferToPage(uint8_t bufferNum, uint16_t page); 383 | 384 | /** 385 | * Transfer a page of data from main memory to buffer 0 or 1. 386 | * @param page Main memory page to transfer. 387 | * @param bufferNum Buffer (0 or 1) to which the data is written. 388 | **/ 389 | void pageToBuffer(uint16_t page, uint8_t bufferNum); 390 | 391 | /** 392 | * Erase a page in the main memory array. 393 | * @param page Page to erase. 394 | **/ 395 | void pageErase(uint16_t page); 396 | 397 | /** 398 | * Erase a block of pages in a single operation. 399 | * @param block Block to erase. 400 | * @warning UNTESTED 401 | **/ 402 | void blockErase(uint16_t block); 403 | 404 | /** 405 | * Erase a sector of blocks in a single operation. 406 | * @param sector Sector to erase. 407 | **/ 408 | void sectorErase(int8_t sector); 409 | 410 | #ifdef AT45_CHIP_ERASE_ENABLED 411 | /** 412 | * Erase the entire chip memory. Sectors protected or locked down will 413 | * not be erased. 414 | * @warning UNTESTED 415 | * @warning MAY DAMAGE CHIP, THEREFORE NOT AVAILABLE. 416 | * READ DATASHEET FOR DETAILS. 417 | **/ 418 | void chipErase(); 419 | #endif 420 | 421 | /** 422 | * This a combination of Buffer Write and Buffer to Page with 423 | * Built-in Erase. 424 | * The global erase flag .manual_erase() is ignored. 425 | * Writing past the end of the page wraps around to the beginning of 426 | * the page. 427 | * @note You must call endAndWait in order to start transferring data 428 | * from buffer to page. 429 | * @param page Page to which the content of the buffer is written. 430 | * @param offset Starting byte address within the buffer. 431 | * @param bufferNum Buffer to use (0 or 1). 432 | **/ 433 | void beginPageWriteThroughBuffer(uint16_t page, uint16_t offset, uint8_t bufferNum); 434 | 435 | /** 436 | * Compare a page of data in main memory to the data in buffer 0 or 1. 437 | * @param page Page to compare. 438 | * @param bufferNum Buffer number (0 or 1). 439 | * @return 440 | * - true If the page and the buffer contains the same data. 441 | * - false Otherwise. 442 | **/ 443 | int8_t isPageEqualBuffer(uint16_t page, uint8_t bufferNum); 444 | 445 | /** 446 | * Put the device into the lowest power consumption mode. 447 | * Once the device has entered the Deep Power-down mode, all 448 | * instructions are ignored except the Resume from Deep 449 | * Power-down command. 450 | * @warning UNTESTED 451 | **/ 452 | void deepPowerDown(); 453 | 454 | /** 455 | * Takes the device out of Deep Power-down mode. 456 | * @warning UNTESTED 457 | **/ 458 | void resumeFromDeepPowerDown(); 459 | 460 | /** 461 | * Reset device via the reset pin. 462 | **/ 463 | void hardReset(); 464 | 465 | void enableSectorProtection(); 466 | void disableSectorProtection(); 467 | void eraseSectorProtectionRegister(); 468 | 469 | class SectorProtectionStatus 470 | { 471 | friend class DataFlash; 472 | public: 473 | SectorProtectionStatus(); 474 | SectorProtectionStatus(const SectorProtectionStatus &status); 475 | SectorProtectionStatus& operator=(const SectorProtectionStatus& status); 476 | void set(int8_t sectorId, bool status); 477 | bool get(int8_t sectorId) const; 478 | void clear(); 479 | private: 480 | uint8_t data[64]; 481 | }; 482 | 483 | uint8_t programSectorProtectionRegister(const SectorProtectionStatus& status); 484 | uint8_t readSectorProtectionRegister(SectorProtectionStatus& status); 485 | 486 | /** Get chip Select (CS) pin **/ 487 | inline int8_t chipSelectPin () const; 488 | /** Get reset (RESET) pin **/ 489 | inline int8_t resetPin () const; 490 | /** Get write protect (WP) pin **/ 491 | inline int8_t writeProtectPin() const; 492 | 493 | private: 494 | /** 495 | * Compute page address hi byte. 496 | */ 497 | inline uint8_t pageToHiU8(uint16_t page) const; 498 | 499 | /** 500 | * Compute page address lo byte. 501 | */ 502 | inline uint8_t pageToLoU8(uint16_t page) const; 503 | 504 | private: 505 | /** 506 | * %Dataflash read/write addressing infos. 507 | **/ 508 | struct AddressingInfos 509 | { 510 | uint8_t bufferSize; /**< Size of the buffer address bits. **/ 511 | uint8_t pageSize; /**< Size of the page address bits. **/ 512 | uint8_t sectorSize; /**< Size of the sector address bits (part of the page address). **/ 513 | }; 514 | static const AddressingInfos m_infos[7]; 515 | 516 | int8_t m_chipSelectPin; /**< Chip select pin (CS). **/ 517 | int8_t m_resetPin; /**< Reset pin (RESET). **/ 518 | int8_t m_writeProtectPin; /**< Write protect pin (WP). **/ 519 | 520 | uint8_t m_deviceIndex; /**< Device index. (0: at45db011d, 1: at45db041d, ...) **/ 521 | uint8_t m_bufferSize; /**< Size of the buffer address bits. **/ 522 | uint8_t m_pageSize; /**< Size of the page address bits. **/ 523 | uint8_t m_sectorSize; /**< Size of the sector address bits. **/ 524 | 525 | enum erasemode m_erase; /**< Erase mode - auto or manual. **/ 526 | 527 | #ifdef AT45_USE_SPI_SPEED_CONTROL 528 | enum IOspeed m_speed; /**< SPI transfer speed. **/ 529 | #endif 530 | 531 | SPISettings m_settings; /**< SPI port configuration **/ 532 | }; 533 | 534 | #include "DataFlashInlines.h" 535 | 536 | /** 537 | * @} 538 | **/ 539 | 540 | #endif /* DATAFLASH_H_ */ 541 | -------------------------------------------------------------------------------- /DataFlashCommands.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file DataFlashCommands.h 3 | * @brief AT45DBxxxD commands opcodes. 4 | * 5 | * @par Copyright: 6 | * - Copyright (C) 2010-2011 by Vincent Cruz. 7 | * - Copyright (C) 2011 by Volker Kuhlmann. @n 8 | * All rights reserved. 9 | * 10 | * @authors 11 | * - Vincent Cruz @n 12 | * cruz.vincent@gmail.com 13 | * - Volker Kuhlmann @n 14 | * http://volker.top.geek.nz/contact.html 15 | * 16 | * @par Description: 17 | * Please refer to @ref DataFlash.cpp for more informations. 18 | * 19 | * @par History: 20 | * - Version 1.x, 2010-2011. 21 | * - Version 2.0, 30 Aug 2011. 22 | * - Version 2.2, 29 Dec 2011. 23 | * 24 | * @par Licence: GPLv3 25 | * This program is free software: you can redistribute it and/or modify 26 | * it under the terms of the GNU General Public License as published by 27 | * the Free Software Foundation, either version 3 of the License, or 28 | * (at your option) any later version. @n 29 | * @n 30 | * This program is distributed in the hope that it will be useful, 31 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 32 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 33 | * GNU General Public License for more details. @n 34 | * @n 35 | * You should have received a copy of the GNU General Public License 36 | * along with this program. If not, see . 37 | *****************************************************************************/ 38 | #ifndef DATAFLASH_COMMANDS_H_ 39 | #define DATAFLASH_COMMANDS_H_ 40 | 41 | /** 42 | * @addtogroup AT45DBxxxD 43 | * @{ 44 | **/ 45 | 46 | /** 47 | * @defgroup Dataflash_commands Dataflash commands opcodes 48 | * Dataflash command opcode list. 49 | * @{ 50 | **/ 51 | 52 | /** 53 | * @defgroup Read_commands Read commands 54 | * @{ 55 | **/ 56 | /** Main Memory Page Read */ 57 | #define DATAFLASH_PAGE_READ 0xD2 58 | /** Continuous Array Read (Low Frequency) **/ 59 | #define DATAFLASH_CONTINUOUS_READ_LOW_FREQ 0x03 60 | /** Continuous Array Read (High Frequency) **/ 61 | #define DATAFLASH_CONTINUOUS_READ_HIGH_FREQ 0x0B 62 | /** Buffer 1 Read (Low Frequency) **/ 63 | #define DATAFLASH_BUFFER_1_READ_LOW_FREQ 0xD1 64 | /** Buffer 2 Read (Low Frequency) **/ 65 | #define DATAFLASH_BUFFER_2_READ_LOW_FREQ 0xD3 66 | /** Buffer 1 Read **/ 67 | #define DATAFLASH_BUFFER_1_READ 0xD4 68 | /** Buffer 2 Read **/ 69 | #define DATAFLASH_BUFFER_2_READ 0xD6 70 | /** @} **/ 71 | 72 | /** 73 | * @defgroup Program_Erase_commands Program and Erase commands 74 | * @{ 75 | **/ 76 | /** Buffer 1 Write **/ 77 | #define DATAFLASH_BUFFER_1_WRITE 0x84 78 | /** Buffer 2 Write **/ 79 | #define DATAFLASH_BUFFER_2_WRITE 0x87 80 | /** Buffer 1 to Main Memory Page Program with Built-in Erase **/ 81 | #define DATAFLASH_BUFFER_1_TO_PAGE_WITH_ERASE 0x83 82 | /** Buffer 2 to Main Memory Page Program with Built-in Erase **/ 83 | #define DATAFLASH_BUFFER_2_TO_PAGE_WITH_ERASE 0x86 84 | /** Buffer 1 to Main Memory Page Program without Built-in Erase **/ 85 | #define DATAFLASH_BUFFER_1_TO_PAGE_WITHOUT_ERASE 0x88 86 | /** Buffer 2 to Main Memory Page Program without Built-in Erase **/ 87 | #define DATAFLASH_BUFFER_2_TO_PAGE_WITHOUT_ERASE 0x89 88 | /** Page Erase **/ 89 | #define DATAFLASH_PAGE_ERASE 0x81 90 | /** Block Erase **/ 91 | #define DATAFLASH_BLOCK_ERASE 0x50 92 | /** Sector Erase **/ 93 | #define DATAFLASH_SECTOR_ERASE 0x7C 94 | /** Chip Erase Sequence **/ 95 | #define DATAFLASH_CHIP_ERASE_0 0xC7 96 | #define DATAFLASH_CHIP_ERASE_1 0x94 97 | #define DATAFLASH_CHIP_ERASE_2 0x80 98 | #define DATAFLASH_CHIP_ERASE_3 0x9A 99 | /** Main Memory Page Program Through Buffer 1 **/ 100 | #define DATAFLASH_PAGE_THROUGH_BUFFER_1 0x82 101 | /** Main Memory Page Program Through Buffer 2 **/ 102 | #define DATAFLASH_PAGE_THROUGH_BUFFER_2 0x85 103 | /** @} **/ 104 | 105 | /** 106 | * @defgroup ProtectionSecurity_Commands Protection and Security Commands 107 | * @{ 108 | **/ 109 | /** Enable Sector Protection **/ 110 | #define DATAFLASH_ENABLE_SECTOR_PROTECTION_0 0x3D 111 | #define DATAFLASH_ENABLE_SECTOR_PROTECTION_1 0x2A 112 | #define DATAFLASH_ENABLE_SECTOR_PROTECTION_2 0x7F 113 | #define DATAFLASH_ENABLE_SECTOR_PROTECTION_3 0xA9 114 | /** Disable Sector Protection **/ 115 | #define DATAFLASH_DISABLE_SECTOR_PROTECTION_0 0x3D 116 | #define DATAFLASH_DISABLE_SECTOR_PROTECTION_1 0x2A 117 | #define DATAFLASH_DISABLE_SECTOR_PROTECTION_2 0x7F 118 | #define DATAFLASH_DISABLE_SECTOR_PROTECTION_3 0x9A 119 | /** Erase Sector Protection Register **/ 120 | #define DATAFLASH_ERASE_SECTOR_PROTECTION_REGISTER_0 0x3D 121 | #define DATAFLASH_ERASE_SECTOR_PROTECTION_REGISTER_1 0x2A 122 | #define DATAFLASH_ERASE_SECTOR_PROTECTION_REGISTER_2 0x7F 123 | #define DATAFLASH_ERASE_SECTOR_PROTECTION_REGISTER_3 0xCF 124 | /** Program Sector Protection Register **/ 125 | #define DATAFLASH_PROGRAM_SECTOR_PROTECTION_REGISTER_0 0x3D 126 | #define DATAFLASH_PROGRAM_SECTOR_PROTECTION_REGISTER_1 0x2A 127 | #define DATAFLASH_PROGRAM_SECTOR_PROTECTION_REGISTER_2 0x7F 128 | #define DATAFLASH_PROGRAM_SECTOR_PROTECTION_REGISTER_3 0xFC 129 | 130 | /** Read Sector Protection Register **/ 131 | #define DATAFLASH_READ_SECTOR_PROTECTION_REGISTER 0x32 132 | /** Read Sector Lockdown Register **/ 133 | #define DATAFLASH_READ_SECTOR_LOCKDOWN_REGISTER 0x35 134 | /** Read Security Register **/ 135 | #define DATAFLASH_READ_SECURITY_REGISTER 0x77 136 | 137 | #if 0 138 | /* Use the following commands at your own risk ! */ 139 | /** Sector Lockdown **/ 140 | #define DATAFLASH_SECTOR_LOCKDOWN_0 0X3D 141 | #define DATAFLASH_SECTOR_LOCKDOWN_1 0x2A 142 | #define DATAFLASH_SECTOR_LOCKDOWN_2 0x7F 143 | #define DATAFLASH_SECTOR_LOCKDOWN_3 0x30 144 | /** Program Security Register **/ 145 | #define DATAFLASH_PROGRAM_SECURITY_REGISTER_0 0x9B 146 | #define DATAFLASH_PROGRAM_SECURITY_REGISTER_1 0x00 147 | #define DATAFLASH_PROGRAM_SECURITY_REGISTER_2 0x00 148 | #define DATAFLASH_PROGRAM_SECURITY_REGISTER_3 0x00 149 | 150 | #endif // 0 151 | 152 | /** @} **/ 153 | 154 | /** 155 | * @defgroup Additional_commands Additional Commands 156 | * @{ 157 | **/ 158 | /** Main Memory Page to Buffer 1 Transfer **/ 159 | #define DATAFLASH_TRANSFER_PAGE_TO_BUFFER_1 0x53 160 | /** Main Memory Page to Buffer 2 Transfer **/ 161 | #define DATAFLASH_TRANSFER_PAGE_TO_BUFFER_2 0x55 162 | /** Main Memory Page to Buffer 1 Compare **/ 163 | #define DATAFLASH_COMPARE_PAGE_TO_BUFFER_1 0x60 164 | /** Main Memory Page to Buffer 2 Compare **/ 165 | #define DATAFLASH_COMPARE_PAGE_TO_BUFFER_2 0x61 166 | /** Auto Page Rewrite through Buffer 1 **/ 167 | #define DATAFLASH_AUTO_PAGE_REWRITE_THROUGH_BUFFER_1 0x58 168 | /** Auto Page Rewrite through Buffer 2 **/ 169 | #define DATAFLASH_AUTO_PAGE_REWRITE_THROUGH_BUFFER_2 0x59 170 | /** Deep Power-down **/ 171 | #define DATAFLASH_DEEP_POWER_DOWN 0xB9 172 | /** Resume from Deep Power-down **/ 173 | #define DATAFLASH_RESUME_FROM_DEEP_POWER_DOWN 0xAB 174 | /** Status Register Read **/ 175 | #define DATAFLASH_STATUS_REGISTER_READ 0xD7 176 | /** Manufacturer and Device ID Read **/ 177 | #define DATAFLASH_READ_MANUFACTURER_AND_DEVICE_ID 0x9F 178 | /** @} **/ 179 | 180 | /** 181 | * @defgroup Legacy_commands Legacy Commands 182 | * @{ 183 | **/ 184 | /** Buffer 1 Read **/ 185 | #define DATAFLASH_BUFFER_1_READ_LEGACY 0X54 186 | /** Buffer 2 Read **/ 187 | #define DATAFLASH_BUFFER_2_READ_LEGACY 0x56 188 | /** Main Memory Page Read **/ 189 | #define DATAFLASH_PAGE_READ_LEGACY 0x52 190 | /** Continuous Array Read **/ 191 | #define DATAFLASH_CONTINUOUS_READ_LEGACY 0x68 192 | /** Status Register Read **/ 193 | #define DATAFLASH_STATUS_REGISTER_READ_LEGACY 0x57 194 | /** @} **/ 195 | /** @} **/ 196 | /** @} **/ 197 | 198 | #endif /* DATAFLASH_COMMANDS_H_ */ 199 | -------------------------------------------------------------------------------- /DataFlashInlines.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file DataFlashInlines.h 3 | * @brief File containing definitions for inline methods and functions for the 4 | * Atmel DataFlash Arduino library. 5 | * 6 | * @par Copyright: 7 | * - Copyright (C) 2010-2011 by Vincent Cruz. 8 | * - Copyright (C) 2011 by Volker Kuhlmann. @n 9 | * All rights reserved. 10 | * 11 | * @authors 12 | * - Vincent Cruz @n 13 | * cruz.vincent@gmail.com 14 | * - Volker Kuhlmann @n 15 | * http://volker.top.geek.nz/contact.html 16 | * 17 | * @par Description: 18 | * Please refer to @ref DataFlash.cpp for more informations. 19 | * 20 | * @par History: 21 | * - Version 1.x, 2010-2011. 22 | * - Version 2.0, 30 Aug 2011. 23 | * - Version 2.2, 29 Dec 2011. 24 | * 25 | * @par Licence: GPLv3 26 | * This program is free software: you can redistribute it and/or modify 27 | * it under the terms of the GNU General Public License as published by 28 | * the Free Software Foundation, either version 3 of the License, or 29 | * (at your option) any later version. @n 30 | * @n 31 | * This program is distributed in the hope that it will be useful, 32 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 33 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 34 | * GNU General Public License for more details. @n 35 | * @n 36 | * You should have received a copy of the GNU General Public License 37 | * along with this program. If not, see . 38 | *****************************************************************************/ 39 | 40 | /** 41 | * @addtogroup AT45DBxxxD 42 | * @{ 43 | **/ 44 | 45 | /** 46 | * Enable device with chipselect. 47 | **/ 48 | inline void DataFlash::enable() 49 | { 50 | digitalWrite(m_chipSelectPin, LOW); 51 | } 52 | 53 | /** 54 | * Disable device with chipselect. 55 | **/ 56 | inline void DataFlash::disable() 57 | { 58 | digitalWrite(m_chipSelectPin, HIGH); 59 | } 60 | 61 | /** Get chip Select (CS) pin **/ 62 | inline int8_t DataFlash::chipSelectPin () const 63 | { 64 | return m_chipSelectPin; 65 | } 66 | 67 | /** Get reset (RESET) pin **/ 68 | inline int8_t DataFlash::resetPin () const 69 | { 70 | return m_resetPin; 71 | } 72 | 73 | /** Get write protect (WP) pin **/ 74 | inline int8_t DataFlash::writeProtectPin() const 75 | { 76 | return m_writeProtectPin; 77 | } 78 | 79 | /** 80 | * Compute page address high byte. 81 | */ 82 | inline uint8_t DataFlash::pageToHiU8(uint16_t page) const 83 | { 84 | return page >> (16 - m_bufferSize); 85 | } 86 | 87 | /** 88 | * Compute page address low byte. 89 | */ 90 | inline uint8_t DataFlash::pageToLoU8(uint16_t page) const 91 | { 92 | return page << (m_bufferSize - 8); 93 | } 94 | 95 | /** 96 | * Same as waitUntilReady 97 | * @todo This method will be removed. 98 | **/ 99 | inline void DataFlash::endAndWait() 100 | { 101 | /* Wait for the end of the previous operation. */ 102 | waitUntilReady(); 103 | } 104 | 105 | /** @} **/ 106 | -------------------------------------------------------------------------------- /DataFlashSizes.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file DataFlashSizes.h 3 | * @brief Header file containing definitions for the sizes of the flash 4 | * memories in the Atmel Dataflash AT45DB range. 5 | * 6 | * @par Copyright: 7 | * - Copyright (C) 2010-2011 by Vincent Cruz. 8 | * - Copyright (C) 2011 by Volker Kuhlmann. @n 9 | * All rights reserved. 10 | * 11 | * @authors 12 | * - Volker Kuhlmann @n 13 | * http://volker.top.geek.nz/contact.html 14 | * 15 | * @par Description: 16 | * Please refer to @ref DataFlash.cpp for more informations. 17 | * 18 | * @par History: 19 | * - Version 1.x, 2010-2011. 20 | * - Version 2.0, 30 Aug 2011. 21 | * - Version 2.2, 29 Dec 2011. 22 | * 23 | * @par Licence: GPLv3 24 | * This program is free software: you can redistribute it and/or modify 25 | * it under the terms of the GNU General Public License as published by 26 | * the Free Software Foundation, either version 3 of the License, or 27 | * (at your option) any later version. @n 28 | * @n 29 | * This program is distributed in the hope that it will be useful, 30 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 31 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 32 | * GNU General Public License for more details. @n 33 | * @n 34 | * You should have received a copy of the GNU General Public License 35 | * along with this program. If not, see . 36 | *****************************************************************************/ 37 | #ifndef DATAFLASH_SIZES_H_ 38 | #define DATAFLASH_SIZES_H_ 39 | 40 | /** 41 | * @addtogroup AT45DBxxxD 42 | * @{ 43 | **/ 44 | 45 | /** 46 | * @defgroup Flash_size Dataflash flash size. 47 | * For each flash memory IC these definitions give the page size, block size, 48 | * sector size and total size in bytes, the number of pages, blocks and sectors, 49 | * and the number of pages in sector 0A (the remaining pages of the first sector 50 | * are in sector 0b). 51 | * 52 | * The standard page size for %Dataflash has an additional 8 bytes per 256 bytes. 53 | * These can be turned off permanently, in which case the page size reverts to a 54 | * binary page size with a power of two. This is indicated in the status register. 55 | * 56 | * Sizes below are for the larger (non-binary) page size. To get the binary page 57 | * size, mask out an appropriate number of lower bits, or multiply by 256/264. 58 | * @{ 59 | **/ 60 | 61 | /** 62 | * @defgroup AT45DB011D_size AT45DB011D size specification. 63 | * @{ 64 | **/ 65 | /** Page size. **/ 66 | #define DF_45DB011_PAGESIZE 264 67 | /** Block size. **/ 68 | #define DF_45DB011_BLOCKSIZE (8 * DF_45DB011_PAGESIZE) 69 | /** Sector size. **/ 70 | #define DF_45DB011_SECTORSIZE (16 * DF_45DB011_BLOCKSIZE) 71 | /** Page count. **/ 72 | #define DF_45DB011_PAGES 512 73 | /** Block count. **/ 74 | #define DF_45DB011_BLOCKS 64 75 | /** Sector count. */ 76 | #define DF_45DB011_SECTORS 4 77 | /** Global size. **/ 78 | #define DF_45DB011_SIZE (DF_45DB011_PAGES * DF_45DB011_PAGESIZE) 79 | /** Sector 0x0A page count. */ 80 | #define DF_45DB011_S0A_PAGES 8 81 | /** @} **/ 82 | 83 | /** 84 | * @defgroup AT45DB021D_size AT45DB021D size specification. 85 | * @{ 86 | **/ 87 | /** Page size. **/ 88 | #define DF_45DB021_PAGESIZE 264 89 | /** Block size. **/ 90 | #define DF_45DB021_BLOCKSIZE (8 * DF_45DB021_PAGESIZE) 91 | /** Sector size. **/ 92 | #define DF_45DB021_SECTORSIZE (16 * DF_45DB021_BLOCKSIZE) 93 | /** Page count. **/ 94 | #define DF_45DB021_PAGES 1024 95 | /** Block count. **/ 96 | #define DF_45DB021_BLOCKS 128 97 | /** Sector count. **/ 98 | #define DF_45DB021_SECTORS 8 99 | /** Global size. **/ 100 | #define DF_45DB021_SIZE (DF_45DB021_PAGES * DF_45DB021_PAGESIZE) 101 | /** Sector 0x0A page count. */ 102 | #define DF_45DB021_S0A_PAGES 8 103 | /** @} **/ 104 | 105 | /** 106 | * @defgroup AT45DB041D_size AT45DB041D size specification. 107 | * @{ 108 | **/ 109 | /** Page size. **/ 110 | #define DF_45DB041_PAGESIZE 264 111 | /** Block size. **/ 112 | #define DF_45DB041_BLOCKSIZE (8 * DF_45DB041_PAGESIZE) 113 | /** Sector size. **/ 114 | #define DF_45DB041_SECTORSIZE (32 * DF_45DB041_BLOCKSIZE) 115 | /** Page count. **/ 116 | #define DF_45DB041_PAGES 2048 117 | /** Block count. **/ 118 | #define DF_45DB041_BLOCKS 256 119 | /** Sector count. **/ 120 | #define DF_45DB041_SECTORS 8 121 | /** Global size. **/ 122 | #define DF_45DB041_SIZE (DF_45DB041_PAGES * DF_45DB041_PAGESIZE) 123 | /** Sector 0x0A page count. */ 124 | #define DF_45DB041_S0A_PAGES 8 125 | /** @} **/ 126 | 127 | /** 128 | * @defgroup AT45DB081D_size AT45DB081D size specification. 129 | * @{ 130 | **/ 131 | /** Page size. **/ 132 | #define DF_45DB081_PAGESIZE 264 133 | /** Block size. **/ 134 | #define DF_45DB081_BLOCKSIZE (8 * DF_45DB081_PAGESIZE) 135 | /** Sector size. **/ 136 | #define DF_45DB081_SECTORSIZE (32 * DF_45DB081_BLOCKSIZE) 137 | /** Page count. **/ 138 | #define DF_45DB081_PAGES 4096 139 | /** Block count. **/ 140 | #define DF_45DB081_BLOCKS 512 141 | /** Sector count. **/ 142 | #define DF_45DB081_SECTORS 16 143 | /** Global size. **/ 144 | #define DF_45DB081_SIZE (DF_45DB081_PAGES * DF_45DB081_PAGESIZE) 145 | /** Sector 0x0A page count. */ 146 | #define DF_45DB081_S0A_PAGES 8 147 | /** @} **/ 148 | 149 | /** 150 | * @defgroup AT45DB161D_size AT45DB161D size specification. 151 | * @{ 152 | **/ 153 | /** Page size. **/ 154 | #define DF_45DB161_PAGESIZE 528 155 | /** Block size. **/ 156 | #define DF_45DB161_BLOCKSIZE (8 * DF_45DB161_PAGESIZE) 157 | /** Sector size. **/ 158 | #define DF_45DB161_SECTORSIZE (32 * DF_45DB161_BLOCKSIZE) 159 | /** Page count. **/ 160 | #define DF_45DB161_PAGES 4096 161 | /** Block count. **/ 162 | #define DF_45DB161_BLOCKS 512 163 | /** Sector count. **/ 164 | #define DF_45DB161_SECTORS 16 165 | /** Global size. **/ 166 | #define DF_45DB161_SIZE (DF_45DB161_PAGES * DF_45DB161_PAGESIZE) 167 | /** Sector 0x0A page count. */ 168 | #define DF_45DB161_S0A_PAGES 8 169 | /** @} **/ 170 | 171 | /** 172 | * @defgroup AT45DB321D_size AT45DB321D size specification. 173 | * @{ 174 | **/ 175 | /** Page size. **/ 176 | #define DF_45DB321_PAGESIZE 528 177 | /** Block size. **/ 178 | #define DF_45DB321_BLOCKSIZE (8 * DF_45DB321_PAGESIZE) 179 | /** Sector size. **/ 180 | #define DF_45DB321_SECTORSIZE (16 * DF_45DB321_BLOCKSIZE) 181 | /** Page count. **/ 182 | #define DF_45DB321_PAGES 8192 183 | /** Block count. **/ 184 | #define DF_45DB321_BLOCKS 1024 185 | /** Sector count. **/ 186 | #define DF_45DB321_SECTORS 64 187 | /** Global size. **/ 188 | #define DF_45DB321_SIZE (DF_45DB321_PAGES * DF_45DB321_PAGESIZE) 189 | /** Sector 0x0A page count. */ 190 | #define DF_45DB321_S0A_PAGES 8 191 | /** @} **/ 192 | 193 | /** 194 | * @defgroup AT45DB642D_size AT45DB642D size specification. 195 | * @{ 196 | **/ 197 | /** Page size. **/ 198 | #define DF_45DB642_PAGESIZE 1056 199 | /** Block size. **/ 200 | #define DF_45DB642_BLOCKSIZE (8 * DF_45DB642_PAGESIZE) 201 | /** Sector size. **/ 202 | #define DF_45DB642_SECTORSIZE (32 * DF_45DB642_BLOCKSIZE) 203 | /** Page count. **/ 204 | #define DF_45DB642_PAGES 8192 205 | /** Block count. **/ 206 | #define DF_45DB642_BLOCKS 1024 207 | /** Sector count. **/ 208 | #define DF_45DB642_SECTORS 32 209 | /** Global size. **/ 210 | #define DF_45DB642_SIZE (DF_45DB642_PAGES * DF_45DB642_PAGESIZE) 211 | /** Sector 0x0A page count. */ 212 | #define DF_45DB642_S0A_PAGES 8 213 | /** @} **/ 214 | 215 | /** @} **/ 216 | /** @} **/ 217 | 218 | #endif // DATAFLASH_SIZES_H_ 219 | 220 | /******************************************************************************/ 221 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Arduino DataFlash library 2 | ================================ 3 | 4 | This is library adds support for the AT45DB SPI flash memory from Adesto Technology (which bought it from Atmel in 2012). 5 | At the moment only the D version is supported. 6 | 7 | Hardware setup 8 | ------------------------------- 9 | DataFlash is 5V tolerant but you must power it with 3.3V. 10 | 11 | | Signal | Arduino pin | Dataflash | 12 | |--------|--------------|-----------| 13 | | MISO | 11 | 1 | 14 | | MOSI | 12 | 8 | 15 | | SCK | 13 | 2 | 16 | | SS | 10 | 4 | 17 | | RESET | user defined | 3 | 18 | | WP | user defined | 5 | 19 | 20 | Software setup 21 | ------------------------------- 22 | Copy the following filesto your library or sketch folder. 23 | * DataFlash.cpp 24 | * DataFlash.h 25 | * DataFlashCommands.h 26 | * DataFlashInlines.h 27 | * DataFlashSizes.h 28 | 29 | DataFlash_test.cpp is a simple unit test program. It is built upon the [arduino-tests library](https://github.com/BlockoS/arduino-tests). 30 | The /examples/ directory contains some sample sketches. 31 | 32 | Please refer to the [doxygen documentation](http://blockos.github.io/arduino-dataflash/doxygen/html/) for a more detailed API description. 33 | 34 | Example 35 | ------------------------------- 36 | The following example shows how to write and read on a AT45DB161D DataFlash. 37 | ```cpp 38 | #include 39 | #include "DataFlash.h" 40 | 41 | static const int csPin = 10; 42 | static const int resetPin = 8; 43 | static const int wpPin = 7; 44 | 45 | DataFlash dataflash; 46 | 47 | void setup() 48 | { 49 | uint8_t status; 50 | DataFlash::ID id; 51 | 52 | const char* dummyMessage = "Hello world"; 53 | 54 | SPI.begin(); 55 | 56 | dataflash.setup(csPin, resetPin, wpPin); 57 | dataflash.begin(); 58 | 59 | status = dataflash.status(); 60 | dataflash.readID(id); 61 | // For a brand new AT45DB161D dataflash 62 | // status = BIN(00101100) 63 | // id.manufacturer = 0x1F; 64 | // id.device[0] = 0x26; 65 | // id.device[1] = 0x00; 66 | // id.extendedInfoLength = 0x00; 67 | 68 | // Write "Hello world" to buffer 1. 69 | dataflash.bufferWrite(1, 0); 70 | for(int i=0; dummyMessage[i] != '\0'; i++) 71 | { 72 | SPI.transfer(dummyMessage[i]); 73 | } 74 | 75 | // Transfer buffer 1 to page 7. 76 | dataflash.bufferToPage(1, 7); 77 | 78 | // Read page 5. 79 | dataflash.pageRead(5, 0); 80 | for(int i=0; i 2 | #include "DataFlash.h" 3 | 4 | #define NUM_PAGES 8 5 | 6 | DataFlash dataflash; 7 | uint8_t loop_cnt; 8 | uint16_t page; 9 | 10 | void setup() 11 | { 12 | uint8_t status; 13 | DataFlash::ID id; 14 | 15 | /* Initialize SPI */ 16 | SPI.begin(); 17 | 18 | /* Let's wait 1 second, allowing use to press the serial monitor button :p */ 19 | delay(1000); 20 | 21 | /* Initialize dataflash */ 22 | dataflash.setup(5,6,7); 23 | 24 | delay(10); 25 | 26 | dataflash.begin(); 27 | 28 | /* Read status register */ 29 | status = dataflash.status(); 30 | 31 | /* Read manufacturer and device ID */ 32 | dataflash.readID(id); 33 | 34 | /* Set baud rate for serial communication */ 35 | Serial.begin(115200); 36 | 37 | /* Display status register */ 38 | Serial.print("Status register :"); 39 | Serial.print(status, BIN); 40 | Serial.print('\n'); 41 | 42 | /* Display manufacturer and device ID */ 43 | Serial.print("Manufacturer ID :\n"); // Should be 00011111 44 | Serial.print(id.manufacturer, HEX); 45 | Serial.print('\n'); 46 | 47 | Serial.print("Device ID (part 1) :\n"); // Should be 00011111 48 | Serial.print(id.device[0], HEX); 49 | Serial.print('\n'); 50 | 51 | Serial.print("Device ID (part 2) :\n"); // Should be 00000000 52 | Serial.print(id.device[1], HEX); 53 | Serial.print('\n'); 54 | 55 | Serial.print("Extended Device Information String Length :\n"); // 00000000 56 | Serial.print(id.extendedInfoLength, HEX); 57 | Serial.print('\n'); 58 | 59 | loop_cnt = 0; 60 | page = 0; 61 | } 62 | 63 | void loop() 64 | { 65 | unsigned int i,j; 66 | char message[] = "@ write test "; 67 | char overflow[] = "\nOVERFLOW!\n"; 68 | char buffer[64]; 69 | uint8_t data; 70 | 71 | /* We are going to write a simple text into buffer 1 */ 72 | itoa(loop_cnt, buffer, 10); 73 | 74 | /* Set dataflash so that any call to spi_tranfer will write the byte 75 | * given as argument to the Buffer 1 */ 76 | dataflash.bufferWrite(1, 0); 77 | /* Transfer the message */ 78 | for(i=0; message[i] != '\0'; ++i) 79 | { 80 | SPI.transfer(message[i]); 81 | } 82 | /* Transfer the loop counter (as string) */ 83 | for(i=0; buffer[i] != '\0'; ++i) 84 | { 85 | SPI.transfer(buffer[i]); 86 | } 87 | 88 | SPI.transfer('\n'); 89 | 90 | ++loop_cnt; 91 | 92 | if(loop_cnt == 0) 93 | { 94 | /* loop_cnt overflow */ 95 | /* To celebrate this we write the string "\nOVERFLOW!\n" to Buffer 1 */ 96 | for(i=0; overflow[i] != '\0'; ++i) 97 | { 98 | SPI.transfer(overflow[i]); 99 | } 100 | } 101 | 102 | /* Write '\0' to buffer 1. This will help us know that we must stop reading from it. */ 103 | SPI.transfer('\0'); 104 | 105 | /* Transfer buffer 1 to 'page' page (with builtin erase) */ 106 | dataflash.bufferToPage(1, page); 107 | 108 | ++page; 109 | /* When we wrote the number of pages we wanted (NUM_PAGES), we display their contents by 110 | * using 2 methods alternatively ; 111 | * - PageToBuffer + BufferRead 112 | * - PageRead 113 | */ 114 | if(page >= NUM_PAGES) 115 | { 116 | for(i=0; i 2 | #include "DataFlash.h" 3 | 4 | DataFlash dataflash; 5 | uint8_t currentSector; 6 | 7 | static const uint16_t bufferSize[7] = { 264, 264, 264, 264, 528, 528, 528 }; 8 | static const uint16_t pagesSector0b[7] = { 120, 120, 248, 248, 248, 120, 248 }; 9 | static const uint16_t pagesPerSector[7] = { 128, 128, 256, 256, 256, 128, 256 }; 10 | 11 | void fillPages(uint16_t pageStart, uint16_t pageCount, uint16_t bufferSize) 12 | { 13 | uint8_t buffer = 0; 14 | uint16_t page = 0; 15 | 16 | for(page=pageStart; page<(pageStart+pageCount); page++) 17 | { 18 | Serial.print("Fill page "); 19 | Serial.print(page, HEX); 20 | dataflash.bufferWrite(buffer, 0); 21 | for(uint16_t j=0; j> 3) - 1; 77 | 78 | if(sectorId == AT45_SECTOR_0A) 79 | { 80 | pageStart = 0; 81 | pageCount = 8; 82 | } 83 | else if(sectorId == AT45_SECTOR_0B) 84 | { 85 | pageStart = 8; 86 | pageCount = pagesSector0b[deviceIndex]; 87 | } 88 | else 89 | { 90 | pageStart = pagesPerSector[deviceIndex] * static_cast(sectorId); 91 | pageCount = pagesPerSector[deviceIndex]; 92 | } 93 | Serial.print("\nTesting sector "); 94 | Serial.print(sectorId, HEX); 95 | Serial.print('\n'); 96 | 97 | Serial.print("Fill pages\n"); 98 | fillPages(pageStart, pageCount, bufferSize[deviceIndex]); 99 | 100 | Serial.print("Erasing sector\n"); 101 | dataflash.sectorErase(sectorId); 102 | 103 | Serial.print("Check pages\n"); 104 | setBuffer(0, 0xff, bufferSize[deviceIndex]); 105 | uint16_t res = checkPages(pageStart, pageCount); 106 | if(res != pageCount) 107 | { 108 | Serial.print("\nFAILURE!\n"); 109 | return 0; 110 | } 111 | return 1; 112 | } 113 | 114 | void setup() 115 | { 116 | uint8_t status; 117 | DataFlash::ID id; 118 | 119 | /* Initialize SPI */ 120 | SPI.begin(); 121 | 122 | /* Let's wait 1 second, allowing use to press the serial monitor button :p */ 123 | delay(1000); 124 | 125 | /* Initialize dataflash */ 126 | dataflash.setup(5,6,7); 127 | 128 | delay(10); 129 | 130 | /* Read status register */ 131 | status = dataflash.status(); 132 | 133 | /* Read manufacturer and device ID */ 134 | dataflash.readID(id); 135 | 136 | /* Set baud rate for serial communication */ 137 | Serial.begin(115200); 138 | 139 | /* Display status register */ 140 | Serial.print("Status register :"); 141 | Serial.print(status, BIN); 142 | Serial.print('\n'); 143 | 144 | /* Display manufacturer and device ID */ 145 | Serial.print("Manufacturer ID :\n"); // Should be 00011111 146 | Serial.print(id.manufacturer, HEX); 147 | Serial.print('\n'); 148 | 149 | Serial.print("Device ID (part 1) :\n"); // Should be 00011111 150 | Serial.print(id.device[0], HEX); 151 | Serial.print('\n'); 152 | 153 | Serial.print("Device ID (part 2) :\n"); // Should be 00000000 154 | Serial.print(id.device[1], HEX); 155 | Serial.print('\n'); 156 | 157 | Serial.print("Extended Device Information String Length :\n"); // 00000000 158 | Serial.print(id.extendedInfoLength, HEX); 159 | Serial.print('\n'); 160 | 161 | uint8_t buffer = 0; 162 | uint8_t page = 0; 163 | 164 | Serial.print("Manual buffer erase : on\n"); 165 | dataflash.manualErase(); 166 | 167 | int8_t res = 0; 168 | res += testSectorErase(AT45_SECTOR_0A); 169 | res += testSectorErase(AT45_SECTOR_0B); 170 | 171 | for(uint8_t i=10; i<14; i++) 172 | { 173 | res += testSectorErase(i); 174 | } 175 | 176 | Serial.print("\nTest "); 177 | if(res != 6) 178 | { 179 | Serial.print("failed!\n"); 180 | } 181 | else 182 | { 183 | Serial.print("successful!\n"); 184 | } 185 | } 186 | 187 | void loop() 188 | { 189 | } 190 | 191 | -------------------------------------------------------------------------------- /examples/sectorProtection/sectorProtection.pde: -------------------------------------------------------------------------------- 1 | #include 2 | #include "DataFlash.h" 3 | 4 | DataFlash dataflash; 5 | 6 | void printSectorProtectionStatus(const DataFlash::SectorProtectionStatus &status, uint8_t count) 7 | { 8 | Serial.println("Sector protection: "); 9 | for(int8_t i=AT45_SECTOR_0A; i 5 | sentence=AT45DBxxxD Atmel Dataflash library for Arduino. 6 | paragraph=This is library adds support for the AT45DB SPI flash memory from Adesto Technology (which bought it from Atmel in 2012). At the moment only the D version is supported. 7 | category=Data Storage 8 | url=https://github.com/BlockoS/arduino-dataflash 9 | architectures=* 10 | -------------------------------------------------------------------------------- /test/DataFlash_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "arduino-test/Dummy.h" 5 | 6 | class DataFlashFixture 7 | { 8 | public: 9 | static const int8_t CHIP_SELECT = 5; 10 | static const int8_t RESET = 6; 11 | static const int8_t WRITE_PROTECT = 7; 12 | 13 | public: 14 | void Setup() 15 | { 16 | /* Initialize SPI */ 17 | SPI.begin(); 18 | 19 | /* Let's wait 1 second, allowing use to press the serial monitor button :p */ 20 | delay(1000); 21 | 22 | /* Initialize dataflash */ 23 | m_dataflash.setup(CHIP_SELECT, RESET, WRITE_PROTECT); 24 | 25 | delay(10); 26 | 27 | /* Read status register */ 28 | m_status = m_dataflash.status(); 29 | 30 | /* Read manufacturer and device ID */ 31 | m_dataflash.readID(m_id); 32 | } 33 | 34 | void TearDown() 35 | { 36 | /* Disable dataflash */ 37 | m_data.disable(); 38 | /* And SPI */ 39 | SPI.end(); 40 | } 41 | 42 | protected: 43 | DataFlash m_dataflash; 44 | uint8_t m_status; 45 | DataFlash::ID m_id; 46 | }; 47 | 48 | class SerialNotifier : public Dummy::CheckFailCallbackInterface 49 | { 50 | public: 51 | SerialNotifier() {} 52 | virtual ~SerialNotifier() {} 53 | 54 | virtual void Notify(char const* expected, char const* value, Dummy::Infos const& infos) 55 | { 56 | Serial.print("%s: %s::%s failed at line %d (expected %s, value %s).\n", 57 | infos.Filename(), infos.SuiteName(), infos.TestName(), infos.Line(), expected, value); 58 | } 59 | }; 60 | 61 | 62 | SUITE(SingleDeviceTest) 63 | { 64 | TEST_FIXTURE(InitializationTest, DataFlashFixture) 65 | { 66 | int i; 67 | uint8_t validDensity[10] = 68 | { 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3c, 0x10, 0x18, 0x20 }; 69 | 70 | CHECK(AT45_READY, m_status & AT45_READY); 71 | for(i=0; i<10; i++) 72 | { 73 | CHECK(validDensity[i], m_status & 0x3f); 74 | } 75 | CHECK(0x1f, m_id.manufacture); 76 | } 77 | 78 | TEST_FIXTURE(BufferReadWriteTest, DataFlashFixture) 79 | { 80 | // [todo] 81 | } 82 | } 83 | 84 | /* Arduino setup hook */ 85 | void setup() 86 | { 87 | Serial.begin(115200); 88 | SerialNotifier notifier; 89 | 90 | res = Dummy::Runner::Instance().Run(¬ifier); 91 | Serial.print("tests run %d\n\ttest failed %d\n\tcheck failed %d\n", res.total, res.failed, res.error); 92 | } 93 | 94 | /* Arduino loop */ 95 | void loop() 96 | {} 97 | 98 | --------------------------------------------------------------------------------