Driver for AT25SF041 SPI Flash Memory, just basic operations

at25sf041.cpp

Committer:
tpadovani
Date:
2015-09-17
Revision:
0:9225e2aef6b3
Child:
1:e6ad2967ec95

File content as of revision 0:9225e2aef6b3:

#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 */ 
}