SPI Flash AT45DBXXXD

Fork of at45db161d by Suga koubou

Committer:
LeoHsueh
Date:
Fri Mar 06 15:47:44 2015 +0800
Revision:
7:2f9d8b47704f
Parent:
6:1872f591d604
Child:
8:1ec3997fe258
Fix id to info, and add page size.

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