Driver for AT25SF041 SPI Flash Memory, just basic operations

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