SPI Flash AT45DBXXXD

Fork of at45db161d by Suga koubou

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