SPI Flash AT45DBXXXD

Fork of at45db161d by Suga koubou

Committer:
LeoHsueh
Date:
Fri Mar 06 09:42:28 2015 +0800
Revision:
6:1872f591d604
Parent:
5:ef7247c6f073
Child:
7:2f9d8b47704f
Format code.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
okini3939 0:2e953bbaf3a5 1 /**
okini3939 0:2e953bbaf3a5 2 * AT45DB161D module for arduino (C) Vincent
okini3939 0:2e953bbaf3a5 3 * SPI flash memory
okini3939 0:2e953bbaf3a5 4 * http://blog.blockos.org/?p=27
okini3939 0:2e953bbaf3a5 5 *
okini3939 0:2e953bbaf3a5 6 * bug fix by todotani
okini3939 0:2e953bbaf3a5 7 * http://todotani.cocolog-nifty.com/blog/2009/07/arduino-4cf4.html
okini3939 0:2e953bbaf3a5 8 *
okini3939 0:2e953bbaf3a5 9 * Modified for mbed, 2011 Suga.
okini3939 0:2e953bbaf3a5 10 */
LeoHsueh 6:1872f591d604 11
okini3939 0:2e953bbaf3a5 12 #include "at45db161d.h"
LeoHsueh 6:1872f591d604 13 #include "at45db161d_commands.h"
okini3939 0:2e953bbaf3a5 14
LeoHsueh 6:1872f591d604 15 #define DF_CS_inactive _cs = 1
LeoHsueh 6:1872f591d604 16 #define DF_CS_active _cs = 0
LeoHsueh 6:1872f591d604 17
LeoHsueh 6:1872f591d604 18 ATD45DB161D::ATD45DB161D(SPI *spi, PinName cs) :
LeoHsueh 6:1872f591d604 19 _spi(spi), _cs(cs) {
??? 3:82157896d90d 20 _bytes = 264;
??? 3:82157896d90d 21 _pages = 4095;
LeoHsueh 6:1872f591d604 22 /* Disable device */
LeoHsueh 6:1872f591d604 23 DF_CS_inactive;
okini3939 0:2e953bbaf3a5 24
okini3939 0:2e953bbaf3a5 25 /* Setup SPI */
LeoHsueh 5:ef7247c6f073 26 _spi->format(8, 0);
LeoHsueh 5:ef7247c6f073 27 _spi->frequency(10000000);
okini3939 0:2e953bbaf3a5 28 }
okini3939 0:2e953bbaf3a5 29
okini3939 0:2e953bbaf3a5 30 /**
okini3939 0:2e953bbaf3a5 31 * Read status register
okini3939 0:2e953bbaf3a5 32 * @return The content of the status register
okini3939 0:2e953bbaf3a5 33 **/
LeoHsueh 6:1872f591d604 34 uint8_t ATD45DB161D::ReadStatusRegister() {
okini3939 0:2e953bbaf3a5 35 uint8_t status;
okini3939 0:2e953bbaf3a5 36
LeoHsueh 6:1872f591d604 37 DF_CS_inactive; /* Make sure to toggle CS signal in order */
LeoHsueh 6:1872f591d604 38 DF_CS_active; /* to reset Dataflash command decoder */
LeoHsueh 6:1872f591d604 39
okini3939 0:2e953bbaf3a5 40 /* Send status read command */
LeoHsueh 5:ef7247c6f073 41 _spi->write(AT45DB161D_STATUS_REGISTER_READ);
okini3939 0:2e953bbaf3a5 42 /* Get result with a dummy write */
LeoHsueh 5:ef7247c6f073 43 status = _spi->write(0x00);
okini3939 0:2e953bbaf3a5 44
okini3939 0:2e953bbaf3a5 45 return status;
okini3939 0:2e953bbaf3a5 46 }
okini3939 0:2e953bbaf3a5 47
okini3939 0:2e953bbaf3a5 48 /**
okini3939 0:2e953bbaf3a5 49 * Read Manufacturer and Device ID
okini3939 0:2e953bbaf3a5 50 * @note if id.extendedInfoLength is not equal to zero,
LeoHsueh 5:ef7247c6f073 51 * successive calls to _spi->write(0xff) will return
okini3939 0:2e953bbaf3a5 52 * the extended device information string bytes.
okini3939 0:2e953bbaf3a5 53 * @param id Pointer to the ID structure to initialize
okini3939 0:2e953bbaf3a5 54 **/
LeoHsueh 6:1872f591d604 55 void ATD45DB161D::ReadManufacturerAndDeviceID(struct ATD45DB161D::ID *id) {
LeoHsueh 6:1872f591d604 56
LeoHsueh 6:1872f591d604 57 DF_CS_inactive; /* Make sure to toggle CS signal in order */
LeoHsueh 6:1872f591d604 58 DF_CS_active; /* to reset Dataflash command decoder */
okini3939 0:2e953bbaf3a5 59
okini3939 0:2e953bbaf3a5 60 /* Send status read command */
LeoHsueh 5:ef7247c6f073 61 _spi->write(AT45DB161D_READ_MANUFACTURER_AND_DEVICE_ID);
okini3939 0:2e953bbaf3a5 62
okini3939 0:2e953bbaf3a5 63 /* Manufacturer ID */
LeoHsueh 5:ef7247c6f073 64 id->manufacturer = _spi->write(0xff);
okini3939 0:2e953bbaf3a5 65 /* Device ID (part 1) */
LeoHsueh 5:ef7247c6f073 66 id->device[0] = _spi->write(0xff);
okini3939 0:2e953bbaf3a5 67 /* Device ID (part 2) */
LeoHsueh 5:ef7247c6f073 68 id->device[1] = _spi->write(0xff);
okini3939 0:2e953bbaf3a5 69 /* Extended Device Information String Length */
LeoHsueh 5:ef7247c6f073 70 id->extendedInfoLength = _spi->write(0xff);
okini3939 0:2e953bbaf3a5 71
okini3939 0:2e953bbaf3a5 72 }
okini3939 0:2e953bbaf3a5 73
okini3939 0:2e953bbaf3a5 74 /**
okini3939 0:2e953bbaf3a5 75 * Main Memory Page Read.
okini3939 0:2e953bbaf3a5 76 * A main memory page read allows the user to read data directly from
okini3939 0:2e953bbaf3a5 77 * any one of the 4096 pages in the main memory, bypassing both of the
okini3939 0:2e953bbaf3a5 78 * data buffers and leaving the contents of the buffers unchanged.
okini3939 0:2e953bbaf3a5 79 *
okini3939 0:2e953bbaf3a5 80 * @param page Page of the main memory to read
okini3939 0:2e953bbaf3a5 81 * @param offset Starting byte address within the page
okini3939 0:2e953bbaf3a5 82 **/
LeoHsueh 6:1872f591d604 83 void ATD45DB161D::ReadMainMemoryPage(uint16_t page, uint16_t offset) {
LeoHsueh 6:1872f591d604 84 DF_CS_inactive; /* Make sure to toggle CS signal in order */
LeoHsueh 6:1872f591d604 85 DF_CS_active; /* to reset Dataflash command decoder */
okini3939 0:2e953bbaf3a5 86
okini3939 0:2e953bbaf3a5 87 /* Send opcode */
LeoHsueh 5:ef7247c6f073 88 _spi->write(AT45DB161D_PAGE_READ);
okini3939 0:2e953bbaf3a5 89
okini3939 0:2e953bbaf3a5 90 /* Address (page | offset) */
LeoHsueh 6:1872f591d604 91 _spi->write((uint8_t) (page >> 6));
LeoHsueh 6:1872f591d604 92 _spi->write((uint8_t) ((page << 2) | (offset >> 8)));
LeoHsueh 6:1872f591d604 93 _spi->write((uint8_t) (offset & 0xff));
okini3939 0:2e953bbaf3a5 94
okini3939 0:2e953bbaf3a5 95 /* 4 "don't care" bytes */
LeoHsueh 5:ef7247c6f073 96 _spi->write(0x00);
LeoHsueh 5:ef7247c6f073 97 _spi->write(0x00);
LeoHsueh 5:ef7247c6f073 98 _spi->write(0x00);
LeoHsueh 5:ef7247c6f073 99 _spi->write(0x00);
okini3939 0:2e953bbaf3a5 100 }
okini3939 0:2e953bbaf3a5 101
okini3939 0:2e953bbaf3a5 102 /**
okini3939 0:2e953bbaf3a5 103 * Continuous Array Read.
okini3939 0:2e953bbaf3a5 104 * Sequentially read a continuous stream of data.
okini3939 0:2e953bbaf3a5 105 * @param page Page of the main memory where the sequential read will start
okini3939 0:2e953bbaf3a5 106 * @param offset Starting byte address within the page
okini3939 0:2e953bbaf3a5 107 * @param low If true the read operation will be performed in low speed mode (and in high speed mode if it's false).
okini3939 0:2e953bbaf3a5 108 * @note The legacy mode is not currently supported
okini3939 0:2e953bbaf3a5 109 **/
LeoHsueh 6:1872f591d604 110 void ATD45DB161D::ContinuousArrayRead(uint16_t page, uint16_t offset, uint8_t low) {
LeoHsueh 6:1872f591d604 111 DF_CS_inactive; /* Make sure to toggle CS signal in order */
LeoHsueh 6:1872f591d604 112 DF_CS_active; /* to reset Dataflash command decoder */
okini3939 0:2e953bbaf3a5 113
okini3939 0:2e953bbaf3a5 114 /* Send opcode */
LeoHsueh 6:1872f591d604 115 _spi->write(low ? AT45DB161D_CONTINUOUS_READ_LOW_FREQ :
LeoHsueh 6:1872f591d604 116 AT45DB161D_CONTINUOUS_READ_HIGH_FREQ);
okini3939 0:2e953bbaf3a5 117
okini3939 0:2e953bbaf3a5 118 /* Address (page | offset) */
LeoHsueh 6:1872f591d604 119 _spi->write((uint8_t) (page >> 6));
LeoHsueh 6:1872f591d604 120 _spi->write((uint8_t) ((page << 2) | (offset >> 8)));
LeoHsueh 6:1872f591d604 121 _spi->write((uint8_t) (offset & 0xff));
okini3939 0:2e953bbaf3a5 122
LeoHsueh 6:1872f591d604 123 if (!low) {
LeoHsueh 6:1872f591d604 124 _spi->write(0x00);
LeoHsueh 6:1872f591d604 125 }
okini3939 0:2e953bbaf3a5 126 }
okini3939 0:2e953bbaf3a5 127
leolleeooleo 4:943690efda8b 128 void ATD45DB161D::read(uint16_t addr, void *ptr, uint16_t len) {
leolleeooleo 4:943690efda8b 129 uint8_t *buf = reinterpret_cast<uint8_t*>(ptr);
??? 3:82157896d90d 130 int i;
??? 3:82157896d90d 131 PageToBuffer(addr / _bytes, 1);
??? 3:82157896d90d 132 BufferRead(1, addr % _bytes, 1);
??? 3:82157896d90d 133 for (i = 0; i < len; i++) {
LeoHsueh 5:ef7247c6f073 134 buf[i] = _spi->write(0xff);
??? 3:82157896d90d 135 }
??? 3:82157896d90d 136 }
??? 3:82157896d90d 137
leolleeooleo 4:943690efda8b 138 void ATD45DB161D::write(uint16_t addr, void *ptr, uint16_t len) {
leolleeooleo 4:943690efda8b 139 uint8_t *buf = reinterpret_cast<uint8_t*>(ptr);
??? 3:82157896d90d 140 uint16_t i;
??? 3:82157896d90d 141 while (len > 0) {
??? 3:82157896d90d 142 BufferWrite(2, addr % _bytes);
leolleeooleo 4:943690efda8b 143 uint16_t wlen = (_bytes < len ? _bytes : len);
leolleeooleo 4:943690efda8b 144 for (i = 0; i < wlen; i++) {
LeoHsueh 5:ef7247c6f073 145 _spi->write(*buf++);
??? 3:82157896d90d 146 }
leolleeooleo 4:943690efda8b 147 len -= wlen;
??? 3:82157896d90d 148 BufferToPage(2, addr / _bytes, 1);
??? 3:82157896d90d 149 addr += _bytes;
??? 3:82157896d90d 150 }
??? 3:82157896d90d 151 }
okini3939 0:2e953bbaf3a5 152
okini3939 0:2e953bbaf3a5 153 /**
okini3939 0:2e953bbaf3a5 154 * Read the content of one of the SRAM data buffers (in low or high speed mode).
okini3939 0:2e953bbaf3a5 155 * @param bufferNum Buffer to read (1 or 2)
okini3939 0:2e953bbaf3a5 156 * @param offset Starting byte within the buffer
okini3939 0:2e953bbaf3a5 157 * @param low If true the read operation will be performed in low speed mode (and in high speed mode if it's false).
okini3939 0:2e953bbaf3a5 158 **/
LeoHsueh 6:1872f591d604 159 void ATD45DB161D::BufferRead(uint8_t bufferNum, uint16_t offset, uint8_t low) {
LeoHsueh 6:1872f591d604 160 DF_CS_inactive; /* Make sure to toggle CS signal in order */
LeoHsueh 6:1872f591d604 161 DF_CS_active; /* to reset Dataflash command decoder */
okini3939 0:2e953bbaf3a5 162
okini3939 0:2e953bbaf3a5 163 /* Send opcode */
LeoHsueh 6:1872f591d604 164 if (bufferNum == 1) {
LeoHsueh 5:ef7247c6f073 165 _spi->write(low ? AT45DB161D_BUFFER_1_READ_LOW_FREQ :
LeoHsueh 6:1872f591d604 166 AT45DB161D_BUFFER_1_READ);
LeoHsueh 6:1872f591d604 167 } else {
LeoHsueh 5:ef7247c6f073 168 _spi->write(low ? AT45DB161D_BUFFER_2_READ_LOW_FREQ :
LeoHsueh 6:1872f591d604 169 AT45DB161D_BUFFER_2_READ);
okini3939 0:2e953bbaf3a5 170
okini3939 0:2e953bbaf3a5 171 }
okini3939 0:2e953bbaf3a5 172
okini3939 0:2e953bbaf3a5 173 /* 14 "Don't care" bits */
LeoHsueh 5:ef7247c6f073 174 _spi->write(0x00);
okini3939 0:2e953bbaf3a5 175 /* Rest of the "don't care" bits + bits 8,9 of the offset */
LeoHsueh 6:1872f591d604 176 _spi->write((uint8_t) (offset >> 8));
okini3939 0:2e953bbaf3a5 177 /* bits 7-0 of the offset */
LeoHsueh 6:1872f591d604 178 _spi->write((uint8_t) (offset & 0xff));
okini3939 0:2e953bbaf3a5 179 }
okini3939 0:2e953bbaf3a5 180
okini3939 0:2e953bbaf3a5 181 /**
okini3939 0:2e953bbaf3a5 182 * Write data to one of the SRAM data buffers. Any further call to
okini3939 0:2e953bbaf3a5 183 * spi_tranfer will return bytes contained in the data buffer until
okini3939 0:2e953bbaf3a5 184 * a low-to-high transition is detected on the CS pin. If the end of
okini3939 0:2e953bbaf3a5 185 * the data buffer is reached, the device will wrap around back to the
okini3939 0:2e953bbaf3a5 186 * beginning of the buffer.
okini3939 0:2e953bbaf3a5 187 * @param bufferNum Buffer to read (1 or 2)
okini3939 0:2e953bbaf3a5 188 * @param offset Starting byte within the buffer
okini3939 0:2e953bbaf3a5 189 **/
LeoHsueh 6:1872f591d604 190 void ATD45DB161D::BufferWrite(uint8_t bufferNum, uint16_t offset) {
LeoHsueh 6:1872f591d604 191 DF_CS_inactive; /* Make sure to toggle CS signal in order */
LeoHsueh 6:1872f591d604 192 DF_CS_active; /* to reset Dataflash command decoder */
okini3939 0:2e953bbaf3a5 193
LeoHsueh 6:1872f591d604 194 _spi->write((bufferNum == 1) ? AT45DB161D_BUFFER_1_WRITE :
LeoHsueh 6:1872f591d604 195 AT45DB161D_BUFFER_2_WRITE);
okini3939 0:2e953bbaf3a5 196
okini3939 0:2e953bbaf3a5 197 /* 14 "Don't care" bits */
LeoHsueh 5:ef7247c6f073 198 _spi->write(0x00);
okini3939 0:2e953bbaf3a5 199 /* Rest of the "don't care" bits + bits 8,9 of the offset */
LeoHsueh 6:1872f591d604 200 _spi->write((uint8_t) (offset >> 8));
okini3939 0:2e953bbaf3a5 201 /* bits 7-0 of the offset */
LeoHsueh 6:1872f591d604 202 _spi->write((uint8_t) (offset & 0xff));
okini3939 0:2e953bbaf3a5 203 }
okini3939 0:2e953bbaf3a5 204
okini3939 0:2e953bbaf3a5 205 /**
okini3939 0:2e953bbaf3a5 206 * Transfer data from buffer 1 or 2 to main memory page.
okini3939 0:2e953bbaf3a5 207 * @param bufferNum Buffer to use (1 or 2)
okini3939 0:2e953bbaf3a5 208 * @param page Page where the content of the buffer will transfered
okini3939 0:2e953bbaf3a5 209 * @param erase If set the page will be first erased before the buffer transfer.
okini3939 0:2e953bbaf3a5 210 * @note If erase is equal to zero, the page must have been previously erased using one of the erase command (Page or Block Erase).
okini3939 0:2e953bbaf3a5 211 **/
LeoHsueh 6:1872f591d604 212 void ATD45DB161D::BufferToPage(uint8_t bufferNum, uint16_t page, uint8_t erase) {
LeoHsueh 6:1872f591d604 213 DF_CS_inactive; /* Make sure to toggle CS signal in order */
LeoHsueh 6:1872f591d604 214 DF_CS_active; /* to reset Dataflash command decoder */
okini3939 0:2e953bbaf3a5 215
okini3939 0:2e953bbaf3a5 216 /* Opcode */
LeoHsueh 6:1872f591d604 217 if (erase) {
LeoHsueh 6:1872f591d604 218 _spi->write((bufferNum == 1) ? AT45DB161D_BUFFER_1_TO_PAGE_WITH_ERASE :
LeoHsueh 6:1872f591d604 219 AT45DB161D_BUFFER_2_TO_PAGE_WITH_ERASE);
LeoHsueh 6:1872f591d604 220 } else {
LeoHsueh 6:1872f591d604 221 _spi->write((bufferNum == 1) ? AT45DB161D_BUFFER_1_TO_PAGE_WITHOUT_ERASE :
LeoHsueh 6:1872f591d604 222 AT45DB161D_BUFFER_2_TO_PAGE_WITHOUT_ERASE);
okini3939 0:2e953bbaf3a5 223 }
okini3939 0:2e953bbaf3a5 224
okini3939 0:2e953bbaf3a5 225 /*
okini3939 0:2e953bbaf3a5 226 * 3 address bytes consist of :
okini3939 0:2e953bbaf3a5 227 * - 2 don&#65533;ft care bits
okini3939 0:2e953bbaf3a5 228 * - 12 page address bits (PA11 - PA0) that specify the page in
okini3939 0:2e953bbaf3a5 229 * the main memory to be written
okini3939 0:2e953bbaf3a5 230 * - 10 don&#65533;ft care bits
okini3939 0:2e953bbaf3a5 231 */
LeoHsueh 6:1872f591d604 232 _spi->write((uint8_t) (page >> 6));
LeoHsueh 6:1872f591d604 233 _spi->write((uint8_t) (page << 2));
LeoHsueh 5:ef7247c6f073 234 _spi->write(0x00);
okini3939 0:2e953bbaf3a5 235
LeoHsueh 6:1872f591d604 236 DF_CS_inactive; /* Start transfer */
LeoHsueh 6:1872f591d604 237 DF_CS_active; /* If erase was set, the page will first be erased */
okini3939 0:2e953bbaf3a5 238
okini3939 0:2e953bbaf3a5 239 /* Wait for the end of the transfer */
LeoHsueh 6:1872f591d604 240 while (!(ReadStatusRegister() & READY_BUSY)) {
LeoHsueh 6:1872f591d604 241 }
okini3939 0:2e953bbaf3a5 242 }
okini3939 0:2e953bbaf3a5 243
okini3939 0:2e953bbaf3a5 244 /**
okini3939 0:2e953bbaf3a5 245 * Transfer a page of data from main memory to buffer 1 or 2.
okini3939 0:2e953bbaf3a5 246 * @param page Main memory page to transfer
okini3939 0:2e953bbaf3a5 247 * @param buffer Buffer (1 or 2) where the data will be written
okini3939 0:2e953bbaf3a5 248 **/
LeoHsueh 6:1872f591d604 249 void ATD45DB161D::PageToBuffer(uint16_t page, uint8_t bufferNum) {
LeoHsueh 6:1872f591d604 250 DF_CS_inactive; /* Make sure to toggle CS signal in order */
LeoHsueh 6:1872f591d604 251 DF_CS_active; /* to reset Dataflash command decoder */
LeoHsueh 6:1872f591d604 252
okini3939 0:2e953bbaf3a5 253 /* Send opcode */
LeoHsueh 5:ef7247c6f073 254 _spi->write((bufferNum == 1) ? AT45DB161D_TRANSFER_PAGE_TO_BUFFER_1 :
LeoHsueh 6:1872f591d604 255 AT45DB161D_TRANSFER_PAGE_TO_BUFFER_2);
okini3939 0:2e953bbaf3a5 256
okini3939 0:2e953bbaf3a5 257 /*
okini3939 0:2e953bbaf3a5 258 * 3 address bytes consist of :
okini3939 0:2e953bbaf3a5 259 * - 2 don&#65533;ft care bits
okini3939 0:2e953bbaf3a5 260 * - 12 page address bits (PA11 - PA0) that specify the page in
okini3939 0:2e953bbaf3a5 261 * the main memory to be written
okini3939 0:2e953bbaf3a5 262 * - 10 don&#65533;ft care bits
okini3939 0:2e953bbaf3a5 263 */
LeoHsueh 6:1872f591d604 264 _spi->write((uint8_t) (page >> 6));
LeoHsueh 6:1872f591d604 265 _spi->write((uint8_t) (page << 2));
LeoHsueh 5:ef7247c6f073 266 _spi->write(0x00);
LeoHsueh 6:1872f591d604 267
LeoHsueh 6:1872f591d604 268 DF_CS_inactive; /* Start page transfer */
okini3939 0:2e953bbaf3a5 269 DF_CS_active;
okini3939 0:2e953bbaf3a5 270
okini3939 0:2e953bbaf3a5 271 /* Wait for the end of the transfer */
LeoHsueh 6:1872f591d604 272 while (!(ReadStatusRegister() & READY_BUSY)) {
LeoHsueh 6:1872f591d604 273 }
okini3939 0:2e953bbaf3a5 274 }
okini3939 0:2e953bbaf3a5 275
okini3939 0:2e953bbaf3a5 276 /**
okini3939 0:2e953bbaf3a5 277 * Erase a page in the main memory array.
okini3939 0:2e953bbaf3a5 278 * @param page Page to erase
okini3939 0:2e953bbaf3a5 279 **/
LeoHsueh 6:1872f591d604 280 void ATD45DB161D::PageErase(uint16_t page) {
LeoHsueh 6:1872f591d604 281 DF_CS_inactive; /* Make sure to toggle CS signal in order */
LeoHsueh 6:1872f591d604 282 DF_CS_active; /* to reset Dataflash command decoder */
okini3939 0:2e953bbaf3a5 283
okini3939 0:2e953bbaf3a5 284 /* Send opcode */
LeoHsueh 5:ef7247c6f073 285 _spi->write(AT45DB161D_PAGE_ERASE);
okini3939 0:2e953bbaf3a5 286
okini3939 0:2e953bbaf3a5 287 /*
okini3939 0:2e953bbaf3a5 288 * 3 address bytes consist of :
okini3939 0:2e953bbaf3a5 289 * - 2 don&#65533;ft care bits
okini3939 0:2e953bbaf3a5 290 * - 12 page address bits (PA11 - PA0) that specify the page in
okini3939 0:2e953bbaf3a5 291 * the main memory to be written
okini3939 0:2e953bbaf3a5 292 * - 10 don&#65533;ft care bits
okini3939 0:2e953bbaf3a5 293 */
LeoHsueh 6:1872f591d604 294 _spi->write((uint8_t) (page >> 6));
LeoHsueh 6:1872f591d604 295 _spi->write((uint8_t) (page << 2));
LeoHsueh 5:ef7247c6f073 296 _spi->write(0x00);
LeoHsueh 6:1872f591d604 297
LeoHsueh 6:1872f591d604 298 DF_CS_inactive; /* Start block erase */
okini3939 0:2e953bbaf3a5 299 DF_CS_active;
okini3939 0:2e953bbaf3a5 300
okini3939 0:2e953bbaf3a5 301 /* Wait for the end of the block erase operation */
LeoHsueh 6:1872f591d604 302 while (!(ReadStatusRegister() & READY_BUSY)) {
LeoHsueh 6:1872f591d604 303 }
okini3939 0:2e953bbaf3a5 304 }
okini3939 0:2e953bbaf3a5 305
okini3939 0:2e953bbaf3a5 306 /**
okini3939 0:2e953bbaf3a5 307 * Erase a block of eight pages at one time.
okini3939 0:2e953bbaf3a5 308 * @param block Index of the block to erase
okini3939 0:2e953bbaf3a5 309 **/
LeoHsueh 6:1872f591d604 310 void ATD45DB161D::BlockErase(uint16_t block) {
LeoHsueh 6:1872f591d604 311 DF_CS_inactive; /* Make sure to toggle CS signal in order */
LeoHsueh 6:1872f591d604 312 DF_CS_active; /* to reset Dataflash command decoder */
okini3939 0:2e953bbaf3a5 313
okini3939 0:2e953bbaf3a5 314 /* Send opcode */
LeoHsueh 5:ef7247c6f073 315 _spi->write(AT45DB161D_BLOCK_ERASE);
okini3939 0:2e953bbaf3a5 316
okini3939 0:2e953bbaf3a5 317 /*
okini3939 0:2e953bbaf3a5 318 * 3 address bytes consist of :
okini3939 0:2e953bbaf3a5 319 * - 2 don&#65533;ft care bits
okini3939 0:2e953bbaf3a5 320 * - 9 block address bits (PA11 - PA3)
okini3939 0:2e953bbaf3a5 321 * - 13 don&#65533;ft care bits
okini3939 0:2e953bbaf3a5 322 */
LeoHsueh 6:1872f591d604 323 _spi->write((uint8_t) (block >> 3));
LeoHsueh 6:1872f591d604 324 _spi->write((uint8_t) (block << 5));
LeoHsueh 5:ef7247c6f073 325 _spi->write(0x00);
LeoHsueh 6:1872f591d604 326
LeoHsueh 6:1872f591d604 327 DF_CS_inactive; /* Start block erase */
okini3939 0:2e953bbaf3a5 328 DF_CS_active;
okini3939 0:2e953bbaf3a5 329
okini3939 0:2e953bbaf3a5 330 /* Wait for the end of the block erase operation */
LeoHsueh 6:1872f591d604 331 while (!(ReadStatusRegister() & READY_BUSY)) {
LeoHsueh 6:1872f591d604 332 }
okini3939 0:2e953bbaf3a5 333 }
okini3939 0:2e953bbaf3a5 334
okini3939 0:2e953bbaf3a5 335 /**
okini3939 0:2e953bbaf3a5 336 * Erase a sector in main memory. There are 16 sector on the
okini3939 0:2e953bbaf3a5 337 * at45db161d and only one can be erased at one time.
okini3939 0:2e953bbaf3a5 338 * @param sector Sector to erase (1-15)
okini3939 0:2e953bbaf3a5 339 **/
LeoHsueh 6:1872f591d604 340 void ATD45DB161D::SectoreErase(uint8_t sector) {
LeoHsueh 6:1872f591d604 341 DF_CS_inactive; /* Make sure to toggle CS signal in order */
LeoHsueh 6:1872f591d604 342 DF_CS_active; /* to reset Dataflash command decoder */
okini3939 0:2e953bbaf3a5 343
okini3939 0:2e953bbaf3a5 344 /* Send opcode */
LeoHsueh 5:ef7247c6f073 345 _spi->write(AT45DB161D_SECTOR_ERASE);
okini3939 0:2e953bbaf3a5 346
okini3939 0:2e953bbaf3a5 347 /*
okini3939 0:2e953bbaf3a5 348 * 3 address bytes consist of :
okini3939 0:2e953bbaf3a5 349 */
LeoHsueh 6:1872f591d604 350 if ((sector == 0x0a) || (sector == 0x0b)) {
okini3939 0:2e953bbaf3a5 351 /*
okini3939 0:2e953bbaf3a5 352 * - 11 don&#65533;ft care bits
okini3939 0:2e953bbaf3a5 353 * -
okini3939 0:2e953bbaf3a5 354 * - 12 don&#65533;ft care bits
okini3939 0:2e953bbaf3a5 355 */
LeoHsueh 5:ef7247c6f073 356 _spi->write(0x00);
LeoHsueh 5:ef7247c6f073 357 _spi->write(((sector & 0x01) << 4));
LeoHsueh 5:ef7247c6f073 358 _spi->write(0x00);
LeoHsueh 6:1872f591d604 359 } else {
okini3939 0:2e953bbaf3a5 360 /*
okini3939 0:2e953bbaf3a5 361 * - 2 don't care bits
okini3939 0:2e953bbaf3a5 362 * - 4 sector number bits
okini3939 0:2e953bbaf3a5 363 * - 18 don't care bits
okini3939 0:2e953bbaf3a5 364 */
LeoHsueh 5:ef7247c6f073 365 _spi->write(sector << 1);
LeoHsueh 5:ef7247c6f073 366 _spi->write(0x00);
LeoHsueh 5:ef7247c6f073 367 _spi->write(0x00);
okini3939 0:2e953bbaf3a5 368 }
LeoHsueh 6:1872f591d604 369
LeoHsueh 6:1872f591d604 370 DF_CS_inactive; /* Start block erase */
okini3939 0:2e953bbaf3a5 371 DF_CS_active;
okini3939 0:2e953bbaf3a5 372
okini3939 0:2e953bbaf3a5 373 /* Wait for the end of the block erase operation */
LeoHsueh 6:1872f591d604 374 while (!(ReadStatusRegister() & READY_BUSY)) {
LeoHsueh 6:1872f591d604 375 }
okini3939 0:2e953bbaf3a5 376 }
okini3939 0:2e953bbaf3a5 377
okini3939 0:2e953bbaf3a5 378 /**
okini3939 0:2e953bbaf3a5 379 * Erase the entire chip memory. Sectors proteced or locked down will
okini3939 0:2e953bbaf3a5 380 * not be erased.
okini3939 0:2e953bbaf3a5 381 **/
LeoHsueh 6:1872f591d604 382 void ATD45DB161D::ChipErase() {
LeoHsueh 6:1872f591d604 383 DF_CS_inactive; /* Make sure to toggle CS signal in order */
LeoHsueh 6:1872f591d604 384 DF_CS_active; /* to reset Dataflash command decoder */
okini3939 0:2e953bbaf3a5 385
okini3939 0:2e953bbaf3a5 386 /* Send chip erase sequence */
LeoHsueh 5:ef7247c6f073 387 _spi->write(AT45DB161D_CHIP_ERASE_0);
LeoHsueh 5:ef7247c6f073 388 _spi->write(AT45DB161D_CHIP_ERASE_1);
LeoHsueh 5:ef7247c6f073 389 _spi->write(AT45DB161D_CHIP_ERASE_2);
LeoHsueh 5:ef7247c6f073 390 _spi->write(AT45DB161D_CHIP_ERASE_3);
LeoHsueh 6:1872f591d604 391
LeoHsueh 6:1872f591d604 392 DF_CS_inactive; /* Start chip erase */
okini3939 0:2e953bbaf3a5 393 DF_CS_active;
okini3939 0:2e953bbaf3a5 394
okini3939 0:2e953bbaf3a5 395 /* Wait for the end of the chip erase operation */
LeoHsueh 6:1872f591d604 396 while (!(ReadStatusRegister() & READY_BUSY))
LeoHsueh 6:1872f591d604 397 ;
okini3939 0:2e953bbaf3a5 398 }
okini3939 0:2e953bbaf3a5 399
okini3939 0:2e953bbaf3a5 400 /**
okini3939 0:2e953bbaf3a5 401 * This a combination of Buffer Write and Buffer to Page with
okini3939 0:2e953bbaf3a5 402 * Built-in Erase.
okini3939 0:2e953bbaf3a5 403 * @note You must call EndAndWait in order to start transfering data from buffer to page
okini3939 0:2e953bbaf3a5 404 * @param page Page where the content of the buffer will transfered
okini3939 0:2e953bbaf3a5 405 * @param offset Starting byte address within the buffer
okini3939 0:2e953bbaf3a5 406 * @param bufferNum Buffer to use (1 or 2)
okini3939 0:2e953bbaf3a5 407 * @warning UNTESTED
okini3939 0:2e953bbaf3a5 408 **/
LeoHsueh 6:1872f591d604 409 void ATD45DB161D::BeginPageWriteThroughBuffer(uint16_t page, uint16_t offset, uint8_t bufferNum) {
LeoHsueh 6:1872f591d604 410 DF_CS_inactive; /* Make sure to toggle CS signal in order */
LeoHsueh 6:1872f591d604 411 DF_CS_active; /* to reset Dataflash command decoder */
okini3939 0:2e953bbaf3a5 412
okini3939 0:2e953bbaf3a5 413 /* Send opcode */
LeoHsueh 5:ef7247c6f073 414 _spi->write((bufferNum == 1) ? AT45DB161D_PAGE_THROUGH_BUFFER_1 :
LeoHsueh 6:1872f591d604 415 AT45DB161D_PAGE_THROUGH_BUFFER_2);
okini3939 0:2e953bbaf3a5 416
okini3939 0:2e953bbaf3a5 417 /* Address */
LeoHsueh 6:1872f591d604 418 _spi->write((uint8_t) (page >> 6));
LeoHsueh 6:1872f591d604 419 _spi->write((uint8_t) ((page << 2) | (offset >> 8)));
LeoHsueh 6:1872f591d604 420 _spi->write((uint8_t) offset);
okini3939 0:2e953bbaf3a5 421 }
okini3939 0:2e953bbaf3a5 422
okini3939 0:2e953bbaf3a5 423 /**
okini3939 0:2e953bbaf3a5 424 * Perform a low-to-high transition on the CS pin and then poll
okini3939 0:2e953bbaf3a5 425 * the status register to check if the dataflash is busy.
okini3939 0:2e953bbaf3a5 426 **/
LeoHsueh 6:1872f591d604 427 void ATD45DB161D::EndAndWait() {
LeoHsueh 6:1872f591d604 428 DF_CS_inactive; /* End current operation */
LeoHsueh 6:1872f591d604 429 DF_CS_active; /* Some internal operation may occur
LeoHsueh 6:1872f591d604 430 * (buffer to page transfer, page erase, etc... ) */
okini3939 0:2e953bbaf3a5 431
okini3939 0:2e953bbaf3a5 432 /* Wait for the chip to be ready */
LeoHsueh 6:1872f591d604 433 while (!(ReadStatusRegister() & READY_BUSY)) {
LeoHsueh 6:1872f591d604 434 }
LeoHsueh 6:1872f591d604 435
LeoHsueh 6:1872f591d604 436 DF_CS_inactive; /* Release SPI Bus */
okini3939 0:2e953bbaf3a5 437 }
okini3939 0:2e953bbaf3a5 438
okini3939 0:2e953bbaf3a5 439 /**
okini3939 0:2e953bbaf3a5 440 * Compare a page of data in main memory to the data in buffer 1 or 2.
okini3939 0:2e953bbaf3a5 441 * @param page Page to test
okini3939 0:2e953bbaf3a5 442 * @param bufferNum Buffer number
okini3939 0:2e953bbaf3a5 443 * @return
okini3939 0:2e953bbaf3a5 444 * - 1 if the page and the buffer contains the same data
okini3939 0:2e953bbaf3a5 445 * - 0 else
okini3939 0:2e953bbaf3a5 446 * @warning UNTESTED
okini3939 0:2e953bbaf3a5 447 **/
LeoHsueh 6:1872f591d604 448 int8_t ATD45DB161D::ComparePageToBuffer(uint16_t page, uint8_t bufferNum) {
okini3939 0:2e953bbaf3a5 449 uint8_t status;
okini3939 0:2e953bbaf3a5 450
LeoHsueh 6:1872f591d604 451 DF_CS_inactive; /* Make sure to toggle CS signal in order */
LeoHsueh 6:1872f591d604 452 DF_CS_active; /* to reset Dataflash command decoder */
okini3939 0:2e953bbaf3a5 453
okini3939 0:2e953bbaf3a5 454 /* Send opcode */
LeoHsueh 5:ef7247c6f073 455 _spi->write((bufferNum == 1) ? AT45DB161D_COMPARE_PAGE_TO_BUFFER_1 :
LeoHsueh 6:1872f591d604 456 AT45DB161D_COMPARE_PAGE_TO_BUFFER_2);
okini3939 0:2e953bbaf3a5 457
okini3939 0:2e953bbaf3a5 458 /* Page address */
LeoHsueh 6:1872f591d604 459 _spi->write((uint8_t) (page >> 6));
LeoHsueh 6:1872f591d604 460 _spi->write((uint8_t) (page << 2));
LeoHsueh 5:ef7247c6f073 461 _spi->write(0x00);
okini3939 0:2e953bbaf3a5 462
LeoHsueh 6:1872f591d604 463 DF_CS_inactive; /* Start comparaison */
okini3939 0:2e953bbaf3a5 464 DF_CS_active;
okini3939 0:2e953bbaf3a5 465
okini3939 0:2e953bbaf3a5 466 /* Wait for the end of the comparaison and get the result */
LeoHsueh 6:1872f591d604 467 while (!((status = ReadStatusRegister()) & READY_BUSY)) {
LeoHsueh 6:1872f591d604 468 }
LeoHsueh 6:1872f591d604 469
okini3939 0:2e953bbaf3a5 470 // return ((status & COMPARE) == COMPARE);
LeoHsueh 6:1872f591d604 471 return ((status & COMPARE) ? 0 : 1);
okini3939 0:2e953bbaf3a5 472 }
okini3939 0:2e953bbaf3a5 473
okini3939 0:2e953bbaf3a5 474 /**
okini3939 0:2e953bbaf3a5 475 * Put the device into the lowest power consumption mode.
okini3939 0:2e953bbaf3a5 476 * Once the device has entered the Deep Power-down mode, all
okini3939 0:2e953bbaf3a5 477 * instructions are ignored except the Resume from Deep
okini3939 0:2e953bbaf3a5 478 * Power-down command.
okini3939 0:2e953bbaf3a5 479 * @warning UNTESTED
okini3939 0:2e953bbaf3a5 480 **/
LeoHsueh 6:1872f591d604 481 void ATD45DB161D::DeepPowerDown() {
LeoHsueh 6:1872f591d604 482 DF_CS_inactive; /* Make sure to toggle CS signal in order */
LeoHsueh 6:1872f591d604 483 DF_CS_active; /* to reset Dataflash command decoder */
okini3939 0:2e953bbaf3a5 484
okini3939 0:2e953bbaf3a5 485 /* Send opcode */
LeoHsueh 5:ef7247c6f073 486 _spi->write(AT45DB161D_DEEP_POWER_DOWN);
okini3939 0:2e953bbaf3a5 487
okini3939 0:2e953bbaf3a5 488 /* Enter Deep Power-Down mode */
okini3939 0:2e953bbaf3a5 489 DF_CS_inactive;
okini3939 0:2e953bbaf3a5 490
okini3939 0:2e953bbaf3a5 491 /* Safety delay */
okini3939 0:2e953bbaf3a5 492 // delay(100);
okini3939 0:2e953bbaf3a5 493 wait_ms(100);
okini3939 0:2e953bbaf3a5 494 }
okini3939 0:2e953bbaf3a5 495
okini3939 0:2e953bbaf3a5 496 /**
okini3939 0:2e953bbaf3a5 497 * Takes the device out of Deep Power-down mode.
okini3939 0:2e953bbaf3a5 498 **/
LeoHsueh 6:1872f591d604 499 void ATD45DB161D::ResumeFromDeepPowerDown() {
LeoHsueh 6:1872f591d604 500 DF_CS_inactive; /* Make sure to toggle CS signal in order */
LeoHsueh 6:1872f591d604 501 DF_CS_active; /* to reset Dataflash command decoder */
okini3939 0:2e953bbaf3a5 502
okini3939 0:2e953bbaf3a5 503 /* Send opcode */
LeoHsueh 5:ef7247c6f073 504 _spi->write(AT45DB161D_RESUME_FROM_DEEP_POWER_DOWN);
okini3939 0:2e953bbaf3a5 505
okini3939 0:2e953bbaf3a5 506 /* Resume device */
okini3939 0:2e953bbaf3a5 507 DF_CS_inactive;
okini3939 0:2e953bbaf3a5 508
okini3939 0:2e953bbaf3a5 509 /* The CS pin must stay high during t_RDPD microseconds before the device
okini3939 0:2e953bbaf3a5 510 * can receive any commands.
okini3939 0:2e953bbaf3a5 511 * On the at45db161D t_RDPD = 35 microseconds. But we will wait 100
okini3939 0:2e953bbaf3a5 512 * (just to be sure). */
okini3939 0:2e953bbaf3a5 513 // delay(100);
okini3939 0:2e953bbaf3a5 514 wait_ms(100);
okini3939 0:2e953bbaf3a5 515 }
LeoHsueh 6:1872f591d604 516
okini3939 0:2e953bbaf3a5 517 /** **/