├── .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 |
--------------------------------------------------------------------------------