SPI Flash AT45DBXXXD

Fork of at45db161d by Suga koubou

Committer:
LeoHsueh
Date:
Fri Mar 06 09:18:42 2015 +0800
Revision:
5:ef7247c6f073
Parent:
4:943690efda8b
Child:
6:1872f591d604
Fix SPI to pointer.

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