Driver for AT25SF041 SPI Flash Memory, just basic operations
Diff: at25sf041.cpp
- Revision:
- 0:9225e2aef6b3
- Child:
- 1:e6ad2967ec95
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/at25sf041.cpp Thu Sep 17 19:46:19 2015 +0000 @@ -0,0 +1,169 @@ +#include "at25sf041.h" + +/** CTOR **/ +AT25SF041::AT25SF041(PinName mosi, PinName miso, PinName sclk, PinName cs) + : _spi(mosi, miso, sclk), _cs(cs) +{} + +AT25SF041::AT25SF041(SPI &spi, PinName cs) + : _spi(spi), _cs(cs) +{} + +/** DTOR **/ +AT25SF041::~AT25SF041() +{} + +/** Setup SPI and pinout **/ +void AT25SF041::Init() +{ + /* Disable device */ + DF_CS_inactive; + + /* Setup SPI */ + _spi.format(8, 0); + +} + +/** + * Read status register + * @return The content of the status register + **/ +uint8_t AT25SF041::ReadStatusRegister(int n) +{ + uint8_t status; + + DF_CS_inactive; + DF_CS_active; + + /* Send status read command */ + if(n == 1){ + spi_transfer(READ_STATUS_REGISTER_BYTE_1); + } else{ + spi_transfer(READ_STATUS_REGISTER_BYTE_2); + } + /* Get result with a dummy write */ + status = spi_transfer(0x00); + + DF_CS_inactive; + + return status; +} + +void AT25SF041::WriteEnable() +{ + DF_CS_inactive; + DF_CS_active; + + spi_transfer(WRITE_ENABLE); + + DF_CS_inactive; +} + +void AT25SF041::WriteDisable() +{ + DF_CS_inactive; + DF_CS_active; + + spi_transfer(WRITE_DISABLE); + + DF_CS_inactive; +} + +/** + * 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 AT25SF041::ReadManufacturerAndDeviceID(struct AT25SF041::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(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); + + DF_CS_inactive; +} + +void AT25SF041::ReadArray(uint32_t address, uint32_t length, uint8_t *buffer) +{ + DF_CS_inactive; /* Make sure to toggle CS signal in order */ + DF_CS_active; /* to reset Dataflash command decoder */ + + /* Send opcode */ + spi_transfer(READ_ARRAY_HF); + + /* Address (page | offset) */ + spi_transfer((uint8_t)((address >> 16) & 0xff)); + spi_transfer((uint8_t)((address >> 8) & 0xff)); + spi_transfer((uint8_t)(address & 0xff)); + spi_transfer(0x00); + + for(int i=0; i < length; i++){ + buffer[i] = spi_transfer(0x00); + } + +} + +void AT25SF041::WriteArray(uint32_t address, uint32_t length, uint8_t *buffer){ + DF_CS_inactive; /* Make sure to toggle CS signal in order */ + DF_CS_active; /* to reset Dataflash command decoder */ + + /* Send opcode */ + spi_transfer(PROGRAM); + + /* Address (page | offset) */ + spi_transfer((uint8_t)((address >> 16) & 0xff)); + spi_transfer((uint8_t)((address >> 8) & 0xff)); + spi_transfer((uint8_t)(address & 0xff)); + + for(int i=0; i < length; i++){ + spi_transfer(buffer[i]); + } + + EndAndWait(); +} + +/** + * Erase the entire chip memory. Sectors proteced or locked down will + * not be erased. + **/ +void AT25SF041::ChipErase() +{ + WriteEnable(); + + DF_CS_inactive; + DF_CS_active; + + spi_transfer(CHIP_ERASE); + + EndAndWait(); + + WriteDisable(); +} + +/** + * Perform a low-to-high transition on the CS pin and then poll + * the status register to check if the dataflash is busy. + **/ +void AT25SF041::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(1) & READY_BUSY) > 0); + + DF_CS_inactive; /* Release SPI Bus */ +}