EmbeddedArtists AB
/
lpc812_exp_solution_spi-e2prom
Solutions for the SPI E2PROM experiments for LPC812 MAX
Diff: SPI25LC080.cpp
- Revision:
- 1:819f21483c01
- Parent:
- 0:aa38ad0bf51d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SPI25LC080.cpp Thu Nov 28 12:17:45 2013 +0000 @@ -0,0 +1,117 @@ +#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); + } +} +