SPI Flash memory
Dependents: AT45DB161D SPIFLASH_AT45DB n-bed_AT45DB161E AT45DB161D
Revision 0:2e953bbaf3a5, committed 2011-09-11
- Comitter:
- okini3939
- Date:
- Sun Sep 11 06:12:15 2011 +0000
- Child:
- 1:b379e16fdf6f
- Commit message:
- AT45DB161D module
AT45DB161D (16Mbits, 2MB, 528B/block) /AT45DB081D (8Mbits, 1MB, 264B/block)
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/at45db161d.cpp Sun Sep 11 06:12:15 2011 +0000 @@ -0,0 +1,539 @@ +/** + * AT45DB161D module for arduino (C) Vincent + * SPI flash memory + * http://blog.blockos.org/?p=27 + * + * bug fix by todotani + * http://todotani.cocolog-nifty.com/blog/2009/07/arduino-4cf4.html + * + * Modified for mbed, 2011 Suga. + */ +#include "at45db161d.h" + +/** CTOR **/ +ATD45DB161D::ATD45DB161D(PinName mosi, PinName miso, PinName sclk, PinName cs) + : _spi(mosi, miso, sclk), _cs(cs) +{} + +ATD45DB161D::ATD45DB161D(SPI &spi, PinName cs) + : _spi(spi), _cs(cs) +{} + +/** DTOR **/ +ATD45DB161D::~ATD45DB161D() +{} + +/** Setup SPI and pinout **/ +void ATD45DB161D::Init() +{ +// uint8_t clr; + + /* Initialize pinout */ +/* + pinMode(DATAOUT, OUTPUT); + pinMode(DATAIN, INPUT); + pinMode(SPICLOCK, OUTPUT); + pinMode(SLAVESELECT, OUTPUT); + pinMode(DATAIN, INPUT); +*/ + /* Disable device */ + DF_CS_inactive; + + /* Setup SPI */ +// SPCR = (1 << SPE) | (1 << MSTR) | (1 << CPOL) | (1 << CPHA); + _spi.format(8, 0); + _spi.frequency(1000000); + + /* Cleanup registers */ +// clr = SPSR; +// clr = SPDR; +} + +/** + * Read status register + * @return The content of the status register + **/ +uint8_t ATD45DB161D::ReadStatusRegister() +{ + uint8_t status; + + DF_CS_inactive; /* Make sure to toggle CS signal in order */ + DF_CS_active; /* to reset Dataflash command decoder */ + + /* Send status read command */ + spi_transfer(AT45DB161D_STATUS_REGISTER_READ); + /* Get result with a dummy write */ + status = spi_transfer(0x00); + + return status; +} + +/** + * Read Manufacturer and Device ID + * @note if id.extendedInfoLength is not equal to zero, + * successive calls to spi_transfer(0xff) will return + * the extended device information string bytes. + * @param id Pointer to the ID structure to initialize + **/ +void ATD45DB161D::ReadManufacturerAndDeviceID(struct ATD45DB161D::ID *id) +{ + + DF_CS_inactive; /* Make sure to toggle CS signal in order */ + DF_CS_active; /* to reset Dataflash command decoder */ + + /* Send status read command */ + spi_transfer(AT45DB161D_READ_MANUFACTURER_AND_DEVICE_ID); + + /* Manufacturer ID */ + id->manufacturer = spi_transfer(0xff); + /* Device ID (part 1) */ + id->device[0] = spi_transfer(0xff); + /* Device ID (part 2) */ + id->device[1] = spi_transfer(0xff); + /* Extended Device Information String Length */ + id->extendedInfoLength = spi_transfer(0xff); + +} + +/** + * Main Memory Page Read. + * A main memory page read allows the user to read data directly from + * any one of the 4096 pages in the main memory, bypassing both of the + * data buffers and leaving the contents of the buffers unchanged. + * + * @param page Page of the main memory to read + * @param offset Starting byte address within the page + **/ +void ATD45DB161D::ReadMainMemoryPage(uint16_t page, uint16_t offset) +{ + DF_CS_inactive; /* Make sure to toggle CS signal in order */ + DF_CS_active; /* to reset Dataflash command decoder */ + + /* Send opcode */ + spi_transfer(AT45DB161D_PAGE_READ); + + /* Address (page | offset) */ + spi_transfer((uint8_t)(page >> 6)); + spi_transfer((uint8_t)((page << 2) | (offset >> 8))); + spi_transfer((uint8_t)(offset & 0xff)); + + /* 4 "don't care" bytes */ + spi_transfer(0x00); + spi_transfer(0x00); + spi_transfer(0x00); + spi_transfer(0x00); +} + +/** + * Continuous Array Read. + * Sequentially read a continuous stream of data. + * @param page Page of the main memory where the sequential read will start + * @param offset Starting byte address within the page + * @param low If true the read operation will be performed in low speed mode (and in high speed mode if it's false). + * @note The legacy mode is not currently supported + **/ +void ATD45DB161D::ContinuousArrayRead(uint16_t page, uint16_t offset, uint8_t low) +{ + DF_CS_inactive; /* Make sure to toggle CS signal in order */ + DF_CS_active; /* to reset Dataflash command decoder */ + + /* Send opcode */ + spi_transfer( low ? AT45DB161D_CONTINUOUS_READ_LOW_FREQ : + AT45DB161D_CONTINUOUS_READ_HIGH_FREQ ); + + /* Address (page | offset) */ + spi_transfer((uint8_t)(page >> 6)); + spi_transfer((uint8_t)((page << 2) | (offset >> 8))); + spi_transfer((uint8_t)(offset & 0xff)); + + if (!low) { spi_transfer(0x00); } +} + + +/** + * Read the content of one of the SRAM data buffers (in low or high speed mode). + * @param bufferNum Buffer to read (1 or 2) + * @param offset Starting byte within the buffer + * @param low If true the read operation will be performed in low speed mode (and in high speed mode if it's false). + **/ +void ATD45DB161D::BufferRead(uint8_t bufferNum, uint16_t offset, uint8_t low) +{ + DF_CS_inactive; /* Make sure to toggle CS signal in order */ + DF_CS_active; /* to reset Dataflash command decoder */ + + /* Send opcode */ + if(bufferNum == 1) + { + spi_transfer(low ? AT45DB161D_BUFFER_1_READ_LOW_FREQ : + AT45DB161D_BUFFER_1_READ); + } + else + { + spi_transfer(low ? AT45DB161D_BUFFER_2_READ_LOW_FREQ : + AT45DB161D_BUFFER_2_READ); + + } + + /* 14 "Don't care" bits */ + spi_transfer(0x00); + /* Rest of the "don't care" bits + bits 8,9 of the offset */ + spi_transfer((uint8_t)(offset >> 8)); + /* bits 7-0 of the offset */ + spi_transfer((uint8_t)(offset & 0xff)); +} + +/** + * Write data to one of the SRAM data buffers. Any further call to + * spi_tranfer will return bytes contained in the data buffer until + * a low-to-high transition is detected on the CS pin. If the end of + * the data buffer is reached, the device will wrap around back to the + * beginning of the buffer. + * @param bufferNum Buffer to read (1 or 2) + * @param offset Starting byte within the buffer + **/ +void ATD45DB161D::BufferWrite(uint8_t bufferNum, uint16_t offset) +{ + DF_CS_inactive; /* Make sure to toggle CS signal in order */ + DF_CS_active; /* to reset Dataflash command decoder */ + + spi_transfer( (bufferNum == 1) ? AT45DB161D_BUFFER_1_WRITE : + AT45DB161D_BUFFER_2_WRITE); + + /* 14 "Don't care" bits */ + spi_transfer(0x00); + /* Rest of the "don't care" bits + bits 8,9 of the offset */ + spi_transfer((uint8_t)(offset >> 8)); + /* bits 7-0 of the offset */ + spi_transfer((uint8_t)(offset & 0xff)); +} + +/** + * Transfer data from buffer 1 or 2 to main memory page. + * @param bufferNum Buffer to use (1 or 2) + * @param page Page where the content of the buffer will transfered + * @param erase If set the page will be first erased before the buffer transfer. + * @note If erase is equal to zero, the page must have been previously erased using one of the erase command (Page or Block Erase). + **/ +void ATD45DB161D::BufferToPage(uint8_t bufferNum, uint16_t page, uint8_t erase) +{ + DF_CS_inactive; /* Make sure to toggle CS signal in order */ + DF_CS_active; /* to reset Dataflash command decoder */ + + /* Opcode */ + if(erase) + { + spi_transfer( (bufferNum == 1) ? AT45DB161D_BUFFER_1_TO_PAGE_WITH_ERASE : + AT45DB161D_BUFFER_2_TO_PAGE_WITH_ERASE); + } + else + { + spi_transfer( (bufferNum == 1) ? AT45DB161D_BUFFER_1_TO_PAGE_WITHOUT_ERASE : + AT45DB161D_BUFFER_2_TO_PAGE_WITHOUT_ERASE); + } + + /* + * 3 address bytes consist of : + * - 2 don�ft care bits + * - 12 page address bits (PA11 - PA0) that specify the page in + * the main memory to be written + * - 10 don�ft care bits + */ + spi_transfer((uint8_t)(page >> 6)); + spi_transfer((uint8_t)(page << 2)); + spi_transfer(0x00); + + DF_CS_inactive; /* Start transfer */ + DF_CS_active; /* If erase was set, the page will first be erased */ + + /* Wait for the end of the transfer */ + while(!(ReadStatusRegister() & READY_BUSY)) + {} +} + +/** + * Transfer a page of data from main memory to buffer 1 or 2. + * @param page Main memory page to transfer + * @param buffer Buffer (1 or 2) where the data will be written + **/ +void ATD45DB161D::PageToBuffer(uint16_t page, uint8_t bufferNum) +{ + DF_CS_inactive; /* Make sure to toggle CS signal in order */ + DF_CS_active; /* to reset Dataflash command decoder */ + + /* Send opcode */ + spi_transfer((bufferNum == 1) ? AT45DB161D_TRANSFER_PAGE_TO_BUFFER_1 : + AT45DB161D_TRANSFER_PAGE_TO_BUFFER_2); + + /* + * 3 address bytes consist of : + * - 2 don�ft care bits + * - 12 page address bits (PA11 - PA0) that specify the page in + * the main memory to be written + * - 10 don�ft care bits + */ + spi_transfer((uint8_t)(page >> 6)); + spi_transfer((uint8_t)(page << 2)); + spi_transfer(0x00); + + DF_CS_inactive; /* Start page transfer */ + DF_CS_active; + + /* Wait for the end of the transfer */ + while(!(ReadStatusRegister() & READY_BUSY)) + {} +} + +/** + * Erase a page in the main memory array. + * @param page Page to erase + **/ +void ATD45DB161D::PageErase(uint16_t page) +{ + DF_CS_inactive; /* Make sure to toggle CS signal in order */ + DF_CS_active; /* to reset Dataflash command decoder */ + + /* Send opcode */ + spi_transfer(AT45DB161D_PAGE_ERASE); + + /* + * 3 address bytes consist of : + * - 2 don�ft care bits + * - 12 page address bits (PA11 - PA0) that specify the page in + * the main memory to be written + * - 10 don�ft care bits + */ + spi_transfer((uint8_t)(page >> 6)); + spi_transfer((uint8_t)(page << 2)); + spi_transfer(0x00); + + DF_CS_inactive; /* Start block erase */ + DF_CS_active; + + /* Wait for the end of the block erase operation */ + while(!(ReadStatusRegister() & READY_BUSY)) + {} +} + +/** + * Erase a block of eight pages at one time. + * @param block Index of the block to erase + **/ +void ATD45DB161D::BlockErase(uint16_t block) +{ + DF_CS_inactive; /* Make sure to toggle CS signal in order */ + DF_CS_active; /* to reset Dataflash command decoder */ + + /* Send opcode */ + spi_transfer(AT45DB161D_BLOCK_ERASE); + + /* + * 3 address bytes consist of : + * - 2 don�ft care bits + * - 9 block address bits (PA11 - PA3) + * - 13 don�ft care bits + */ + spi_transfer((uint8_t)(block >> 3)); + spi_transfer((uint8_t)(block << 5)); + spi_transfer(0x00); + + DF_CS_inactive; /* Start block erase */ + DF_CS_active; + + /* Wait for the end of the block erase operation */ + while(!(ReadStatusRegister() & READY_BUSY)) + {} +} + +/** + * Erase a sector in main memory. There are 16 sector on the + * at45db161d and only one can be erased at one time. + * @param sector Sector to erase (1-15) + **/ +void ATD45DB161D::SectoreErase(uint8_t sector) +{ + DF_CS_inactive; /* Make sure to toggle CS signal in order */ + DF_CS_active; /* to reset Dataflash command decoder */ + + /* Send opcode */ + spi_transfer(AT45DB161D_SECTOR_ERASE); + + /* + * 3 address bytes consist of : + */ + if((sector == 0x0a) || (sector == 0x0b)) + { + /* + * - 11 don�ft care bits + * - + * - 12 don�ft care bits + */ + spi_transfer(0x00); + spi_transfer(((sector & 0x01) << 4)); + spi_transfer(0x00); + } + else + { + /* + * - 2 don't care bits + * - 4 sector number bits + * - 18 don't care bits + */ + spi_transfer(sector << 1); + spi_transfer(0x00); + spi_transfer(0x00); + } + + DF_CS_inactive; /* Start block erase */ + DF_CS_active; + + /* Wait for the end of the block erase operation */ + while(!(ReadStatusRegister() & READY_BUSY)) + {} +} + +/** + * Erase the entire chip memory. Sectors proteced or locked down will + * not be erased. + **/ +void ATD45DB161D::ChipErase() +{ + DF_CS_inactive; /* Make sure to toggle CS signal in order */ + DF_CS_active; /* to reset Dataflash command decoder */ + + /* Send chip erase sequence */ + spi_transfer(AT45DB161D_CHIP_ERASE_0); + spi_transfer(AT45DB161D_CHIP_ERASE_1); + spi_transfer(AT45DB161D_CHIP_ERASE_2); + spi_transfer(AT45DB161D_CHIP_ERASE_3); + + DF_CS_inactive; /* Start chip erase */ + DF_CS_active; + + /* Wait for the end of the chip erase operation */ + while(!(ReadStatusRegister() & READY_BUSY)) + {} +} + +/** + * This a combination of Buffer Write and Buffer to Page with + * Built-in Erase. + * @note You must call EndAndWait in order to start transfering data from buffer to page + * @param page Page where the content of the buffer will transfered + * @param offset Starting byte address within the buffer + * @param bufferNum Buffer to use (1 or 2) + * @warning UNTESTED + **/ +void ATD45DB161D::BeginPageWriteThroughBuffer(uint16_t page, uint16_t offset, uint8_t bufferNum) +{ + DF_CS_inactive; /* Make sure to toggle CS signal in order */ + DF_CS_active; /* to reset Dataflash command decoder */ + + /* Send opcode */ + spi_transfer((bufferNum == 1) ? AT45DB161D_PAGE_THROUGH_BUFFER_1 : + AT45DB161D_PAGE_THROUGH_BUFFER_2); + + /* Address */ + spi_transfer((uint8_t)(page >> 6)); + spi_transfer((uint8_t)((page << 2) | (offset >> 8))); + spi_transfer((uint8_t)offset); +} + +/** + * Perform a low-to-high transition on the CS pin and then poll + * the status register to check if the dataflash is busy. + **/ +void ATD45DB161D::EndAndWait() +{ + DF_CS_inactive; /* End current operation */ + DF_CS_active; /* Some internal operation may occur + * (buffer to page transfer, page erase, etc... ) */ + + /* Wait for the chip to be ready */ + while(!(ReadStatusRegister() & READY_BUSY)) + {} + + DF_CS_inactive; /* Release SPI Bus */ +} + +/** + * Compare a page of data in main memory to the data in buffer 1 or 2. + * @param page Page to test + * @param bufferNum Buffer number + * @return + * - 1 if the page and the buffer contains the same data + * - 0 else + * @warning UNTESTED + **/ +int8_t ATD45DB161D::ComparePageToBuffer(uint16_t page, uint8_t bufferNum) +{ + uint8_t status; + + DF_CS_inactive; /* Make sure to toggle CS signal in order */ + DF_CS_active; /* to reset Dataflash command decoder */ + + /* Send opcode */ + spi_transfer((bufferNum == 1) ? AT45DB161D_COMPARE_PAGE_TO_BUFFER_1 : + AT45DB161D_COMPARE_PAGE_TO_BUFFER_2); + + /* Page address */ + spi_transfer((uint8_t)(page >> 6)); + spi_transfer((uint8_t)(page << 2)); + spi_transfer(0x00); + + DF_CS_inactive; /* Start comparaison */ + DF_CS_active; + + /* Wait for the end of the comparaison and get the result */ + while(!((status = ReadStatusRegister()) & READY_BUSY)) + {} + +// return ((status & COMPARE) == COMPARE); + return ((status & COMPARE) ? 0 : 1); +} + +/** + * Put the device into the lowest power consumption mode. + * Once the device has entered the Deep Power-down mode, all + * instructions are ignored except the Resume from Deep + * Power-down command. + * @warning UNTESTED + **/ +void ATD45DB161D::DeepPowerDown() +{ + DF_CS_inactive; /* Make sure to toggle CS signal in order */ + DF_CS_active; /* to reset Dataflash command decoder */ + + /* Send opcode */ + spi_transfer(AT45DB161D_DEEP_POWER_DOWN); + + /* Enter Deep Power-Down mode */ + DF_CS_inactive; + + /* Safety delay */ +// delay(100); + wait_ms(100); +} + +/** + * Takes the device out of Deep Power-down mode. + **/ +void ATD45DB161D::ResumeFromDeepPowerDown() +{ + DF_CS_inactive; /* Make sure to toggle CS signal in order */ + DF_CS_active; /* to reset Dataflash command decoder */ + + /* Send opcode */ + spi_transfer(AT45DB161D_RESUME_FROM_DEEP_POWER_DOWN); + + /* Resume device */ + DF_CS_inactive; + + /* The CS pin must stay high during t_RDPD microseconds before the device + * can receive any commands. + * On the at45db161D t_RDPD = 35 microseconds. But we will wait 100 + * (just to be sure). */ +// delay(100); + wait_ms(100); +} + +/** **/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/at45db161d.h Sun Sep 11 06:12:15 2011 +0000 @@ -0,0 +1,308 @@ +/** + * @file at45db161d.h + * @brief AT45DB161D module + **/ +#ifndef AT45DB161D_H +#define AT45DB161D_H + +#include "mbed.h" + +extern "C" { + +//#include <avr/pgmspace.h> +#include <inttypes.h> +//#include "WConstants.h" + +}; + +#include "at45db161d_commands.h" + +/** + * @defgroup AT45DB161D AT45DB161D module + * @{ + **/ + +/** + * @defgroup SPI SPI pinout and transfert function + * @{ + **/ +#ifndef SPI +/** + * @defgroup SPI_Pinout SPI pinout + * @{ + **/ +/** Serial input (SI) **/ +#define DATAOUT 11 +/** Serial output (SO) **/ +#define DATAIN 12 +/** Serial clock (SCK) **/ +#define SPICLOCK 13 +/** Chip select (CS) **/ +#define SLAVESELECT 10 +/** Reset (Reset) **/ +#define RESET 8 +/** Write protect (WP) **/ +#define WP 7 +/** + * @} + **/ + +/** + * @fn inline uint8_t spi_transfer(uint8_t data) + * @brief Transfer a byte via spi + * @param data Data to transfer via SPI + * @return The content of the SPI data register (SPDR) + **/ +/* +inline uint8_t spi_transfer(uint8_t data) +{ + SPDR = data; + while(!(SPSR & (1 << SPIF))) ; + return SPDR; +} +*/ +#define spi_transfer(data) _spi.write(data) + +/** De-assert CS **/ +//#define DF_CS_inactive digitalWrite(SLAVESELECT,HIGH) +#define DF_CS_inactive _cs = 1 +/** Assert CS **/ +//#define DF_CS_active digitalWrite(SLAVESELECT,LOW) +#define DF_CS_active _cs = 0 + +#endif /* SPI */ +/** + * @} + **/ + +/** + * @defgroup STATUS_REGISTER_FORMAT Status register format + * @{ + **/ +/** + * Ready/busy status is indicated using bit 7 of the status register. + * If bit 7 is a 1, then the device is not busy and is ready to accept + * the next command. If bit 7 is a 0, then the device is in a busy + * state. + **/ +#define READY_BUSY 0x80 +/** + * Result of the most recent Memory Page to Buffer Compare operation. + * If this bit is equal to 0, then the data in the main memory page + * matches the data in the buffer. If it's 1 then at least 1 byte in + * the main memory page does not match the data in the buffer. + **/ +#define COMPARE 0x40 +/** + * Bit 1 in the Status Register is used to provide information to the + * user whether or not the sector protection has been enabled or + * disabled, either by software-controlled method or + * hardware-controlled method. 1 means that the sector protection has + * been enabled and 0 that it has been disabled. + **/ +#define PROTECT 0x02 +/** + * Bit 0 indicates wether the page size of the main memory array is + * configured for "power of 2" binary page size (512 bytes) (bit=1) or + * standard DataFlash page size (528 bytes) (bit=0). + **/ +#define PAGE_SIZE 0x01 +/** + * Bits 5, 4, 3 and 2 indicates the device density. The decimal value + * of these four binary bits does not equate to the device density; the + * four bits represent a combinational code relating to differing + * densities of DataFlash devices. The device density is not the same + * as the density code indicated in the JEDEC device ID information. + * The device density is provided only for backward compatibility. + **/ +#define DEVICE_DENSITY 0x2C +/** + * @} + **/ + +/** + * @brief at45db161d module + * @todo + * - TESTS! + * - Protection and Security Commands + * - Auto Page Rewrite through Buffer 1 + * - Auto Page Rewrite through Buffer 2 + **/ +class ATD45DB161D +{ + public: + /** + * @brief ID structure + * This structure contains various informations about the + * dataflash chip being used. + **/ + struct ID + { + uint8_t manufacturer; /**< Manufacturer id **/ + uint8_t device[2]; /**< Device id **/ + uint8_t extendedInfoLength; /**< Extended device information string length **/ + }; + + public: + /** CTOR **/ + ATD45DB161D(PinName mosi, PinName miso, PinName sclk, PinName cs); + ATD45DB161D(SPI &spi, PinName cs); + /** DTOR **/ + ~ATD45DB161D(); + + /** Setup SPI and pinout **/ + void Init(); + + /** + * Read status register + * @return The content of the status register + * **/ + uint8_t ReadStatusRegister(); + + /** + * Read Manufacturer and Device ID + * @note if id.extendedInfoLength is not equal to zero, + * successive calls to spi_transfer(0xff) will return + * the extended device information string bytes. + * @param id Pointer to the ID structure to initialize + **/ + void ReadManufacturerAndDeviceID(struct ATD45DB161D::ID *id); + + /** + * A main memory page read allows the user to read data directly from + * any one of the 4096 pages in the main memory, bypassing both of the + * data buffers and leaving the contents of the buffers unchanged. + * @param page Page of the main memory to read + * @param offset Starting byte address within the page + **/ + void ReadMainMemoryPage(uint16_t page, uint16_t offset); + + /** + * Sequentially read a continuous stream of data. + * @param page Page of the main memory where the sequential read will start + * @param offset Starting byte address within the page + * @param low If true the read operation will be performed in low speed mode (and in high speed mode if it's false). + * @note The legacy mode is not currently supported + * @warning UNTESTED + **/ + void ContinuousArrayRead(uint16_t page, uint16_t offset, uint8_t low); + + /** + * Read the content of one of the SRAM data buffers (in low or high speed mode). + * @param bufferNum Buffer to read (1 or 2) + * @param offset Starting byte within the buffer + * @param low If true the read operation will be performed in low speed mode (and in high speed mode if it's false). + **/ + void BufferRead(uint8_t bufferNum, uint16_t offset, uint8_t low); + + /** + * Write data to one of the SRAM data buffers. Any further call to + * spi_tranfer will return bytes contained in the data buffer until + * a low-to-high transition is detected on the CS pin. If the end of + * the data buffer is reached, the device will wrap around back to the + * beginning of the buffer. + * @param bufferNum Buffer to read (1 or 2) + * @param offset Starting byte within the buffer + **/ + void BufferWrite(uint8_t bufferNum, uint16_t offset); + + /** + * Transfer data from buffer 1 or 2 to main memory page. + * @param bufferNum Buffer to use (1 or 2) + * @param page Page where the content of the buffer will transfered + * @param erase If set the page will be first erased before the buffer transfer. + * @note If erase is equal to zero, the page must have been previously erased using one of the erase command (Page or Block Erase). + **/ + void BufferToPage(uint8_t bufferNum, uint16_t page, uint8_t erase); + + /** + * Transfer a page of data from main memory to buffer 1 or 2. + * @param page Main memory page to transfer + * @param buffer Buffer (1 or 2) where the data will be written + **/ + void PageToBuffer(uint16_t page, uint8_t bufferNum); + + /** + * Erase a page in the main memory array. + * @param page Page to erase + * @warning UNTESTED + **/ + void PageErase(uint16_t page); + + /** + * Erase a block of eight pages at one time. + * @param block Index of the block to erase + * @warning UNTESTED + **/ + void BlockErase(uint16_t block); + + /** + * Erase a sector in main memory. There are 16 sector on the + * at45db161d and only one can be erased at one time. + * @param sector Sector to erase + * @warning UNTESTED + **/ + void SectoreErase(uint8_t sector); + + /** + * Erase the entire chip memory. Sectors proteced or locked down will + * not be erased. + * @warning UNTESTED + **/ + void ChipErase(); + + /** + * This a combination of Buffer Write and Buffer to Page with + * Built-in Erase. + * @note You must call EndAndWait in order to start transfering data from buffer to page + * @param page Page where the content of the buffer will transfered + * @param offset Starting byte address within the buffer + * @param bufferNum Buffer to use (1 or 2) + * @warning UNTESTED + **/ + void BeginPageWriteThroughBuffer(uint16_t page, uint16_t offset, uint8_t bufferNum); + + /** + * Perform a low-to-high transition on the CS pin and then poll + * the status register to check if the dataflash is busy. + **/ + void EndAndWait(); + + /** + * Compare a page of data in main memory to the data in buffer 1 or 2. + * @param page Page to test + * @param bufferNum Buffer number + * @return + * - 1 if the page and the buffer contains the same data + * - 0 else + * @warning UNTESTED + **/ + int8_t ComparePageToBuffer(uint16_t page, uint8_t bufferNum); + + /** + * Put the device into the lowest power consumption mode. + * Once the device has entered the Deep Power-down mode, all + * instructions are ignored except the Resume from Deep + * Power-down command. + * @warning UNTESTED + **/ + void DeepPowerDown(); + + /** + * Takes the device out of Deep Power-down mode. + * @warning UNTESTED + **/ + void ResumeFromDeepPowerDown(); + + private: + /* Nothing atm but who knows... */ + + SPI _spi; + DigitalOut _cs; +}; + +/** + * @} + **/ + +#endif /* AT45DB161D_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/at45db161d_commands.h Sun Sep 11 06:12:15 2011 +0000 @@ -0,0 +1,169 @@ +/** + * @file at45db161d_commands.h + * @brief AT45DB161D commands opcodes + **/ +#ifndef AT45DB161D_COMMANDS_H +#define AT45DB161D_COMMANDS_H + +/** + * @defgroup AT45DB161D_commands AT45DB161D commands opcodes + * @{ + **/ + +/** + * @defgroup Read_commands Read commands + * @{ + **/ +/** Main Memory Page Read */ +#define AT45DB161D_PAGE_READ 0xD2 +/** Continuous Array Read (Low Frequency) **/ +#define AT45DB161D_CONTINUOUS_READ_LOW_FREQ 0x03 +/** Continuous Array Read (High Frequency) **/ +#define AT45DB161D_CONTINUOUS_READ_HIGH_FREQ 0x0B +/** Buffer 1 Read (Low Frequency) **/ +#define AT45DB161D_BUFFER_1_READ_LOW_FREQ 0xD1 +/** Buffer 2 Read (Low Frequency) **/ +#define AT45DB161D_BUFFER_2_READ_LOW_FREQ 0xD3 +/** Buffer 1 Read **/ +#define AT45DB161D_BUFFER_1_READ 0xD4 +/** Buffer 2 Read **/ +#define AT45DB161D_BUFFER_2_READ 0xD6 +/** + * @} + **/ + +/** + * @defgroup Program_Erase_commands Program and Erase commands + * @{ + **/ +/** Buffer 1 Write **/ +#define AT45DB161D_BUFFER_1_WRITE 0x84 +/** Buffer 2 Write **/ +#define AT45DB161D_BUFFER_2_WRITE 0x87 +/** Buffer 1 to Main Memory Page Program with Built-in Erase **/ +#define AT45DB161D_BUFFER_1_TO_PAGE_WITH_ERASE 0x83 +/** Buffer 2 to Main Memory Page Program with Built-in Erase **/ +#define AT45DB161D_BUFFER_2_TO_PAGE_WITH_ERASE 0x86 +/** Buffer 1 to Main Memory Page Program without Built-in Erase **/ +#define AT45DB161D_BUFFER_1_TO_PAGE_WITHOUT_ERASE 0x88 +/** Buffer 2 to Main Memory Page Program without Built-in Erase **/ +#define AT45DB161D_BUFFER_2_TO_PAGE_WITHOUT_ERASE 0x89 +/** Page Erase **/ +#define AT45DB161D_PAGE_ERASE 0x81 +/** Block Erase **/ +#define AT45DB161D_BLOCK_ERASE 0x50 +/** Sector Erase **/ +#define AT45DB161D_SECTOR_ERASE 0x7C +/** Chip Erase Sequence **/ +#define AT45DB161D_CHIP_ERASE_0 0xC7 +#define AT45DB161D_CHIP_ERASE_1 0x94 +#define AT45DB161D_CHIP_ERASE_2 0x80 +#define AT45DB161D_CHIP_ERASE_3 0x9A +/** Main Memory Page Program Through Buffer 1 **/ +#define AT45DB161D_PAGE_THROUGH_BUFFER_1 0x82 +/** Main Memory Page Program Through Buffer 2 **/ +#define AT45DB161D_PAGE_THROUGH_BUFFER_2 0x85 +/** + * @} + **/ + +/** + * @defgroup ProtectionSecurity_Commands Protection and Security Commands + * @warning UNIMPLEMENTED + * @{ + **/ +#ifdef AT45DB161D_EXPERT_MODE +/* Use the following commands at your own risk ! */ +/** Enable Sector Protection **/ +#define AT45DB161D_ENABLE_SECTOR_PROTECTION_0 0x3D +#define AT45DB161D_ENABLE_SECTOR_PROTECTION_1 0x2A +#define AT45DB161D_ENABLE_SECTOR_PROTECTION_2 0x7F +#define AT45DB161D_ENABLE_SECTOR_PROTECTION_3 0xA9 +/** Disable Sector Protection **/ +#define AT45DB161D_DISABLE_SECTOR_PROTECTION_0 0x3D +#define AT45DB161D_DISABLE_SECTOR_PROTECTION_1 0x2A +#define AT45DB161D_DISABLE_SECTOR_PROTECTION_2 0x7F +#define AT45DB161D_DISABLE_SECTOR_PROTECTION_3 0x9A +/** Erase Sector Protection Register **/ +#define AT45DB161D_ERASE_SECTOR_PROTECTION_REGISTER_0 0x3D +#define AT45DB161D_ERASE_SECTOR_PROTECTION_REGISTER_0 0x2A +#define AT45DB161D_ERASE_SECTOR_PROTECTION_REGISTER_0 0x7F +#define AT45DB161D_ERASE_SECTOR_PROTECTION_REGISTER_0 0xCF +/** Program Sector Protection Register **/ +#define AT45DB161D_PROGRAM_SECTOR_PROTECTION_REGISTER_0 0x3D +#define AT45DB161D_PROGRAM_SECTOR_PROTECTION_REGISTER_1 0x2A +#define AT45DB161D_PROGRAM_SECTOR_PROTECTION_REGISTER_2 0x7F +#define AT45DB161D_PROGRAM_SECTOR_PROTECTION_REGISTER_3 0xFC +/** Sector Lockdown **/ +#define AT45DB161D_SECTOR_LOCKDOWN_0 0X3D +#define AT45DB161D_SECTOR_LOCKDOWN_1 0x2A +#define AT45DB161D_SECTOR_LOCKDOWN_2 0x7F +#define AT45DB161D_SECTOR_LOCKDOWN_3 0x30 +/** Program Security Register **/ +#define AT45DB161D_PROGRAM_SECURITY_REGISTER_0 0x9B +#define AT45DB161D_PROGRAM_SECURITY_REGISTER_1 0x00 +#define AT45DB161D_PROGRAM_SECURITY_REGISTER_2 0x00 +#define AT45DB161D_PROGRAM_SECURITY_REGISTER_3 0x00 +#endif /* AT45DB161D_EXPERT_MODE */ + +/** Read Sector Protection Register **/ +#define AT45DB161D_READ_SECTOR_PROTECTION_REGISTER 0x32 +/** Read Sector Lockdown Register **/ +#define AT45DB161D_READ_SECTOR_LOCKDOWN_REGISTER 35H +/** Read Security Register **/ +#define AT45DB161D_READ_SECURITY_REGISTER 0x77 +/** + * @} + **/ + +/** + * @defgroup Additional_commands Additional Commands + * @{ + **/ +/** Main Memory Page to Buffer 1 Transfer **/ +#define AT45DB161D_TRANSFER_PAGE_TO_BUFFER_1 0x53 +/** Main Memory Page to Buffer 2 Transfer **/ +#define AT45DB161D_TRANSFER_PAGE_TO_BUFFER_2 0x55 +/** Main Memory Page to Buffer 1 Compare **/ +#define AT45DB161D_COMPARE_PAGE_TO_BUFFER_1 0x60 +/** Main Memory Page to Buffer 2 Compare **/ +#define AT45DB161D_COMPARE_PAGE_TO_BUFFER_2 0x61 +/** Auto Page Rewrite through Buffer 1 **/ +#define AT45DB161D_AUTO_PAGE_REWRITE_THROUGH_BUFFER_1 0x58 +/** Auto Page Rewrite through Buffer 2 **/ +#define AT45DB161D_AUTO_PAGE_REWRITE_THROUGH_BUFFER_2 0x59 +/** Deep Power-down **/ +#define AT45DB161D_DEEP_POWER_DOWN 0xB9 +/** Resume from Deep Power-down **/ +#define AT45DB161D_RESUME_FROM_DEEP_POWER_DOWN 0xAB +/** Status Register Read **/ +#define AT45DB161D_STATUS_REGISTER_READ 0xD7 +/** Manufacturer and Device ID Read **/ +#define AT45DB161D_READ_MANUFACTURER_AND_DEVICE_ID 0x9F +/** + * @} + **/ + +/** + * @defgroup Legacy_commands Legacy Commands + * @{ + **/ +/** Buffer 1 Read **/ +#define AT45DB161D_BUFFER_1_READ_LEGACY 0X54 +/** Buffer 2 Read **/ +#define AT45DB161D_BUFFER_2_READ_LEGACY 0x56 +/** Main Memory Page Read **/ +#define AT45DB161D_PAGE_READ_LEGACY 0x52 +/** Continuous Array Read **/ +#define AT45DB161D_CONTINUOUS_READ_LEGACY 0x68 +/** Status Register Read **/ +#define AT45DB161D_STATUS_REGISTER_READ_LEGACY 0x57 +/** + * @} + **/ + +/** + * @} + **/ + +#endif /* AT45DB161D_COMMANDS_H */