Solutions for the SPI E2PROM experiments for LPC812 MAX

Dependencies:   mbed

SPI25LC080.cpp

Committer:
embeddedartists
Date:
2013-11-28
Revision:
1:819f21483c01
Parent:
SPI24LC080.cpp@ 0:aa38ad0bf51d

File content as of revision 1:819f21483c01:

#include "mbed.h"
#include "SPI25LC080.h"

/* SPI E2PROM command set */
#define INST_WREN      0x06    /* MSB A8 is set to 0, simplifying test */
#define INST_WRDI      0x04
#define INST_RDSR      0x05
#define INST_WRSR      0x01
#define INST_READ      0x03
#define INST_WRITE     0x02

/* RDSR status bit definition */
#define RDSR_RDY       0x01
#define RDSR_WEN       0x02

/* Page size of E2PROM */
#define PAGE_SIZE        16

#define LOCAL_MIN(__a, __b)  ( ((__a) < (__b)) ? (__a) : (__b) )

SPI25LC080::SPI25LC080(PinName mosi, PinName sclk, PinName miso, PinName ssel) :
    m_spi(mosi, miso, sclk), m_ssel(ssel)
{
}

void SPI25LC080::read(uint16_t address, uint8_t* pData, uint32_t length)
{
    //pull SSEL/CS low
    m_ssel = 0;

    //output read command and address
    m_spi.write(INST_READ);
    m_spi.write((address >> 8) & 0xff);
    m_spi.write(address & 0xff);

    //read bytes from E2PROM
    for (uint32_t i = 0; i < length; i++) {
        pData[i] = m_spi.write(0x00); // write dummy byte to get read next value
    }

    //pull SSEL/CS high
    m_ssel = 1;
}

uint8_t SPI25LC080::status()
{
    //pull SSEL/CS low
    m_ssel = 0;

    uint8_t status = m_spi.write(INST_RDSR);

    //pull SSEL/CS high
    m_ssel = 1;
    
    return status;
}

void SPI25LC080::write_enable()
{
  //pull SSEL/CS low
  m_ssel = 0;

  //output write command and address
  m_spi.write(INST_WREN);

  //pull SSEL/CS high
  m_ssel = 1;
}

void SPI25LC080::write(uint16_t address, uint8_t* pData, uint32_t length)
{
  uint32_t left = length;
  uint32_t offset = address;
  uint32_t len = 0;

  // find length of first page write
  if ((address / PAGE_SIZE) != ((address + length) / PAGE_SIZE)) {
    //spans across at least one boundary
    len = PAGE_SIZE - (address % PAGE_SIZE);
  } else {
    // ends inside same page => use normal length
    len = length % PAGE_SIZE;
  }

  //insert code here to break up large write operation into several
  //page write operations (16 or 32 byte pages)
  while (left > 0) {

    //Enable write latch
    write_enable();

    //pull SSEL/CS low
    m_ssel = 0;

    //output write command and address
    m_spi.write(INST_WRITE);
    m_spi.write((offset >> 8) & 0xff);
    m_spi.write(offset & 0xff);

    //send bytes to write E2PROM
    for (uint32_t i = 0; i < len; i++) {
        m_spi.write(pData[offset + i]);
    }

    //pull SSEL/CS high
    m_ssel = 1;

    offset += len;
    left -= len;
    len = LOCAL_MIN(left, PAGE_SIZE);

    //wait until write operations is done
    //for now, just wait. A more sophisticated method is to poll the status register
    wait_ms(5);
  }
}