SPI Flash memory

Dependents:   AT45DB161D SPIFLASH_AT45DB n-bed_AT45DB161E AT45DB161D

at45db161d.h

Committer:
okini3939
Date:
2011-09-15
Revision:
1:b379e16fdf6f
Parent:
0:2e953bbaf3a5

File content as of revision 1:b379e16fdf6f:

/**
 * @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 */