SPI Flash AT45DBXXXD
Fork of at45db161d by
Diff: at45db161d.cpp
- Revision:
- 6:1872f591d604
- Parent:
- 5:ef7247c6f073
- Child:
- 7:2f9d8b47704f
--- a/at45db161d.cpp Fri Mar 06 09:18:42 2015 +0800 +++ b/at45db161d.cpp Fri Mar 06 09:42:28 2015 +0800 @@ -8,21 +8,20 @@ * * Modified for mbed, 2011 Suga. */ + #include "at45db161d.h" +#include "at45db161d_commands.h" -ATD45DB161D::ATD45DB161D(SPI *spi, PinName cs) - : _spi(spi), _cs(cs) -{ +#define DF_CS_inactive _cs = 1 +#define DF_CS_active _cs = 0 + +ATD45DB161D::ATD45DB161D(SPI *spi, PinName cs) : + _spi(spi), _cs(cs) { _bytes = 264; _pages = 4095; -} + /* Disable device */ + DF_CS_inactive; -/** Setup SPI and pinout **/ -void ATD45DB161D::Init() -{ - /* Disable device */ - DF_CS_inactive; - /* Setup SPI */ _spi->format(8, 0); _spi->frequency(10000000); @@ -32,13 +31,12 @@ * Read status register * @return The content of the status register **/ -uint8_t ATD45DB161D::ReadStatusRegister() -{ +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 */ - + DF_CS_inactive; /* Make sure to toggle CS signal in order */ + DF_CS_active; /* to reset Dataflash command decoder */ + /* Send status read command */ _spi->write(AT45DB161D_STATUS_REGISTER_READ); /* Get result with a dummy write */ @@ -54,12 +52,11 @@ * the extended device information string bytes. * @param id Pointer to the ID structure to initialize **/ -void ATD45DB161D::ReadManufacturerAndDeviceID(struct ATD45DB161D::ID *id) -{ +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 */ - DF_CS_inactive; /* Make sure to toggle CS signal in order */ - DF_CS_active; /* to reset Dataflash command decoder */ - /* Send status read command */ _spi->write(AT45DB161D_READ_MANUFACTURER_AND_DEVICE_ID); @@ -83,18 +80,17 @@ * @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 */ +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->write(AT45DB161D_PAGE_READ); /* Address (page | offset) */ - _spi->write((uint8_t)(page >> 6)); - _spi->write((uint8_t)((page << 2) | (offset >> 8))); - _spi->write((uint8_t)(offset & 0xff)); + _spi->write((uint8_t) (page >> 6)); + _spi->write((uint8_t) ((page << 2) | (offset >> 8))); + _spi->write((uint8_t) (offset & 0xff)); /* 4 "don't care" bytes */ _spi->write(0x00); @@ -111,21 +107,22 @@ * @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 */ +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->write( low ? AT45DB161D_CONTINUOUS_READ_LOW_FREQ : - AT45DB161D_CONTINUOUS_READ_HIGH_FREQ ); + _spi->write(low ? AT45DB161D_CONTINUOUS_READ_LOW_FREQ : + AT45DB161D_CONTINUOUS_READ_HIGH_FREQ); /* Address (page | offset) */ - _spi->write((uint8_t)(page >> 6)); - _spi->write((uint8_t)((page << 2) | (offset >> 8))); - _spi->write((uint8_t)(offset & 0xff)); + _spi->write((uint8_t) (page >> 6)); + _spi->write((uint8_t) ((page << 2) | (offset >> 8))); + _spi->write((uint8_t) (offset & 0xff)); - if (!low) { _spi->write(0x00); } + if (!low) { + _spi->write(0x00); + } } void ATD45DB161D::read(uint16_t addr, void *ptr, uint16_t len) { @@ -159,30 +156,26 @@ * @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 */ +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) - { + if (bufferNum == 1) { _spi->write(low ? AT45DB161D_BUFFER_1_READ_LOW_FREQ : - AT45DB161D_BUFFER_1_READ); - } - else - { + AT45DB161D_BUFFER_1_READ); + } else { _spi->write(low ? AT45DB161D_BUFFER_2_READ_LOW_FREQ : - AT45DB161D_BUFFER_2_READ); + AT45DB161D_BUFFER_2_READ); } /* 14 "Don't care" bits */ _spi->write(0x00); /* Rest of the "don't care" bits + bits 8,9 of the offset */ - _spi->write((uint8_t)(offset >> 8)); + _spi->write((uint8_t) (offset >> 8)); /* bits 7-0 of the offset */ - _spi->write((uint8_t)(offset & 0xff)); + _spi->write((uint8_t) (offset & 0xff)); } /** @@ -194,20 +187,19 @@ * @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 */ +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->write( (bufferNum == 1) ? AT45DB161D_BUFFER_1_WRITE : - AT45DB161D_BUFFER_2_WRITE); + _spi->write((bufferNum == 1) ? AT45DB161D_BUFFER_1_WRITE : + AT45DB161D_BUFFER_2_WRITE); /* 14 "Don't care" bits */ _spi->write(0x00); /* Rest of the "don't care" bits + bits 8,9 of the offset */ - _spi->write((uint8_t)(offset >> 8)); + _spi->write((uint8_t) (offset >> 8)); /* bits 7-0 of the offset */ - _spi->write((uint8_t)(offset & 0xff)); + _spi->write((uint8_t) (offset & 0xff)); } /** @@ -217,21 +209,17 @@ * @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 */ +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->write( (bufferNum == 1) ? AT45DB161D_BUFFER_1_TO_PAGE_WITH_ERASE : - AT45DB161D_BUFFER_2_TO_PAGE_WITH_ERASE); - } - else - { - _spi->write( (bufferNum == 1) ? AT45DB161D_BUFFER_1_TO_PAGE_WITHOUT_ERASE : - AT45DB161D_BUFFER_2_TO_PAGE_WITHOUT_ERASE); + if (erase) { + _spi->write((bufferNum == 1) ? AT45DB161D_BUFFER_1_TO_PAGE_WITH_ERASE : + AT45DB161D_BUFFER_2_TO_PAGE_WITH_ERASE); + } else { + _spi->write((bufferNum == 1) ? AT45DB161D_BUFFER_1_TO_PAGE_WITHOUT_ERASE : + AT45DB161D_BUFFER_2_TO_PAGE_WITHOUT_ERASE); } /* @@ -241,16 +229,16 @@ * the main memory to be written * - 10 don�ft care bits */ - _spi->write((uint8_t)(page >> 6)); - _spi->write((uint8_t)(page << 2)); + _spi->write((uint8_t) (page >> 6)); + _spi->write((uint8_t) (page << 2)); _spi->write(0x00); - DF_CS_inactive; /* Start transfer */ - DF_CS_active; /* If erase was set, the page will first be erased */ + 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)) - {} + while (!(ReadStatusRegister() & READY_BUSY)) { + } } /** @@ -258,14 +246,13 @@ * @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 */ - +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->write((bufferNum == 1) ? AT45DB161D_TRANSFER_PAGE_TO_BUFFER_1 : - AT45DB161D_TRANSFER_PAGE_TO_BUFFER_2); + AT45DB161D_TRANSFER_PAGE_TO_BUFFER_2); /* * 3 address bytes consist of : @@ -274,26 +261,25 @@ * the main memory to be written * - 10 don�ft care bits */ - _spi->write((uint8_t)(page >> 6)); - _spi->write((uint8_t)(page << 2)); + _spi->write((uint8_t) (page >> 6)); + _spi->write((uint8_t) (page << 2)); _spi->write(0x00); - - DF_CS_inactive; /* Start page transfer */ + + DF_CS_inactive; /* Start page transfer */ DF_CS_active; /* Wait for the end of the transfer */ - while(!(ReadStatusRegister() & READY_BUSY)) - {} + 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 */ +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->write(AT45DB161D_PAGE_ERASE); @@ -305,26 +291,25 @@ * the main memory to be written * - 10 don�ft care bits */ - _spi->write((uint8_t)(page >> 6)); - _spi->write((uint8_t)(page << 2)); + _spi->write((uint8_t) (page >> 6)); + _spi->write((uint8_t) (page << 2)); _spi->write(0x00); - - DF_CS_inactive; /* Start block erase */ + + DF_CS_inactive; /* Start block erase */ DF_CS_active; /* Wait for the end of the block erase operation */ - while(!(ReadStatusRegister() & READY_BUSY)) - {} + 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 */ +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->write(AT45DB161D_BLOCK_ERASE); @@ -335,16 +320,16 @@ * - 9 block address bits (PA11 - PA3) * - 13 don�ft care bits */ - _spi->write((uint8_t)(block >> 3)); - _spi->write((uint8_t)(block << 5)); + _spi->write((uint8_t) (block >> 3)); + _spi->write((uint8_t) (block << 5)); _spi->write(0x00); - - DF_CS_inactive; /* Start block erase */ + + DF_CS_inactive; /* Start block erase */ DF_CS_active; /* Wait for the end of the block erase operation */ - while(!(ReadStatusRegister() & READY_BUSY)) - {} + while (!(ReadStatusRegister() & READY_BUSY)) { + } } /** @@ -352,10 +337,9 @@ * 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 */ +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->write(AT45DB161D_SECTOR_ERASE); @@ -363,8 +347,7 @@ /* * 3 address bytes consist of : */ - if((sector == 0x0a) || (sector == 0x0b)) - { + if ((sector == 0x0a) || (sector == 0x0b)) { /* * - 11 don�ft care bits * - @@ -373,9 +356,7 @@ _spi->write(0x00); _spi->write(((sector & 0x01) << 4)); _spi->write(0x00); - } - else - { + } else { /* * - 2 don't care bits * - 4 sector number bits @@ -385,36 +366,35 @@ _spi->write(0x00); _spi->write(0x00); } - - DF_CS_inactive; /* Start block erase */ + + DF_CS_inactive; /* Start block erase */ DF_CS_active; /* Wait for the end of the block erase operation */ - while(!(ReadStatusRegister() & READY_BUSY)) - {} + 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 */ +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->write(AT45DB161D_CHIP_ERASE_0); _spi->write(AT45DB161D_CHIP_ERASE_1); _spi->write(AT45DB161D_CHIP_ERASE_2); _spi->write(AT45DB161D_CHIP_ERASE_3); - - DF_CS_inactive; /* Start chip erase */ + + DF_CS_inactive; /* Start chip erase */ DF_CS_active; /* Wait for the end of the chip erase operation */ - while(!(ReadStatusRegister() & READY_BUSY)) - {} + while (!(ReadStatusRegister() & READY_BUSY)) + ; } /** @@ -426,36 +406,34 @@ * @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 */ +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->write((bufferNum == 1) ? AT45DB161D_PAGE_THROUGH_BUFFER_1 : - AT45DB161D_PAGE_THROUGH_BUFFER_2); + AT45DB161D_PAGE_THROUGH_BUFFER_2); /* Address */ - _spi->write((uint8_t)(page >> 6)); - _spi->write((uint8_t)((page << 2) | (offset >> 8))); - _spi->write((uint8_t)offset); + _spi->write((uint8_t) (page >> 6)); + _spi->write((uint8_t) ((page << 2) | (offset >> 8))); + _spi->write((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... ) */ +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 */ + while (!(ReadStatusRegister() & READY_BUSY)) { + } + + DF_CS_inactive; /* Release SPI Bus */ } /** @@ -467,31 +445,30 @@ * - 0 else * @warning UNTESTED **/ -int8_t ATD45DB161D::ComparePageToBuffer(uint16_t page, uint8_t bufferNum) -{ +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 */ + DF_CS_inactive; /* Make sure to toggle CS signal in order */ + DF_CS_active; /* to reset Dataflash command decoder */ /* Send opcode */ _spi->write((bufferNum == 1) ? AT45DB161D_COMPARE_PAGE_TO_BUFFER_1 : - AT45DB161D_COMPARE_PAGE_TO_BUFFER_2); + AT45DB161D_COMPARE_PAGE_TO_BUFFER_2); /* Page address */ - _spi->write((uint8_t)(page >> 6)); - _spi->write((uint8_t)(page << 2)); + _spi->write((uint8_t) (page >> 6)); + _spi->write((uint8_t) (page << 2)); _spi->write(0x00); - DF_CS_inactive; /* Start comparaison */ + DF_CS_inactive; /* Start comparaison */ DF_CS_active; /* Wait for the end of the comparaison and get the result */ - while(!((status = ReadStatusRegister()) & READY_BUSY)) - {} - + while (!((status = ReadStatusRegister()) & READY_BUSY)) { + } + // return ((status & COMPARE) == COMPARE); - return ((status & COMPARE) ? 0 : 1); + return ((status & COMPARE) ? 0 : 1); } /** @@ -501,10 +478,9 @@ * 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 */ +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->write(AT45DB161D_DEEP_POWER_DOWN); @@ -520,10 +496,9 @@ /** * 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 */ +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->write(AT45DB161D_RESUME_FROM_DEEP_POWER_DOWN); @@ -538,5 +513,5 @@ // delay(100); wait_ms(100); } - + /** **/