Dependencies: DM_FATFileSystem EthernetInterface HTTPClient mbed-rtos mbed-src
Fork of DMSupport by
Diff: Memory/InternalEEPROM.cpp
- Revision:
- 0:6b68dac0d986
- Child:
- 9:a33326afd686
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Memory/InternalEEPROM.cpp Fri Nov 21 11:42:51 2014 +0000 @@ -0,0 +1,224 @@ +/* + * Copyright 2013 Embedded Artists AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbed.h" +#include "InternalEEPROM.h" +#include "dm_board_config.h" + + +/****************************************************************************** + * Defines and typedefs + *****************************************************************************/ + +#define EEPROM_INT_ENDOFRW (1<<26) +#define EEPROM_INT_ENDOFPROG (1<<28) + +#define EEPROM_PWRDWN (1<<0) + +/* + * Commands (for the LPC_EEPROM->CMD register) + */ +#define EEPROM_CMD_8BITS_READ (0) /*!< EEPROM 8-bit read command */ +#define EEPROM_CMD_16BITS_READ (1) /*!< EEPROM 16-bit read command */ +#define EEPROM_CMD_32BITS_READ (2) /*!< EEPROM 32-bit read command */ +#define EEPROM_CMD_8BITS_WRITE (3) /*!< EEPROM 8-bit write command */ +#define EEPROM_CMD_16BITS_WRITE (4) /*!< EEPROM 16-bit write command */ +#define EEPROM_CMD_32BITS_WRITE (5) /*!< EEPROM 32-bit write command */ +#define EEPROM_CMD_ERASE_PRG_PAGE (6) /*!< EEPROM erase/program command */ +#define EEPROM_CMD_RDPREFETCH (1 << 3)/*!< EEPROM read pre-fetch enable */ + + +/****************************************************************************** + * Local variables + *****************************************************************************/ + +/****************************************************************************** + * Private Functions + *****************************************************************************/ + +void InternalEEPROM::powerUp() +{ + LPC_EEPROM->PWRDWN = 0; +} + +void InternalEEPROM::clearInterrupt(uint32_t mask) +{ + LPC_EEPROM->INT_CLR_STATUS = mask; +} + +void InternalEEPROM::waitForInterrupt(uint32_t mask) +{ + while ((LPC_EEPROM->INT_STATUS & mask) != mask) { + } + + clearInterrupt(mask); +} + +void InternalEEPROM::setAddr(uint32_t pageAddr, uint32_t pageOffset) +{ + LPC_EEPROM->ADDR = (pageAddr << 6) | pageOffset; +} + +void InternalEEPROM::setCmd(uint32_t cmd) +{ + LPC_EEPROM->CMD = cmd; +} + +void InternalEEPROM::readPage(uint32_t pageAddr, uint32_t pageOffset, uint8_t* buf, uint32_t size) +{ + clearInterrupt(EEPROM_INT_ENDOFRW); + setAddr(pageAddr, pageOffset); + setCmd(EEPROM_CMD_8BITS_READ | EEPROM_CMD_RDPREFETCH); + for (int i = 0; i < size; i++) { + buf[i] = LPC_EEPROM->RDATA & 0xff; + waitForInterrupt(EEPROM_INT_ENDOFRW); + } +} + +void InternalEEPROM::writePage(uint32_t pageAddr, uint32_t pageOffset, const uint8_t* buf, uint32_t size) +{ + clearInterrupt(EEPROM_INT_ENDOFRW); + setCmd(EEPROM_CMD_8BITS_WRITE); + setAddr(pageAddr, pageOffset); + for (int i = 0; i < size; i++) { + LPC_EEPROM->WDATA = buf[i]; + waitForInterrupt(EEPROM_INT_ENDOFRW); + } +} + +void InternalEEPROM::eraseOrProgramPage(uint32_t pageAddr) +{ + // Write data from page register to non-volatile memory + clearInterrupt(EEPROM_INT_ENDOFPROG); + setAddr(pageAddr, 0); + setCmd(EEPROM_CMD_ERASE_PRG_PAGE); + waitForInterrupt(EEPROM_INT_ENDOFPROG); +} + + +/****************************************************************************** + * Public Functions + *****************************************************************************/ + +InternalEEPROM::InternalEEPROM() : _initialized(false) +{ +} + +InternalEEPROM::~InternalEEPROM() +{ +} + +void InternalEEPROM::init() +{ + if (!_initialized) { + // Bring EEPROM device out of power down mode + powerUp(); + + // Setup EEPROM timing to 375KHz based on PCLK rate + uint32_t clk = SystemCoreClock; + LPC_EEPROM->CLKDIV = SystemCoreClock / 375000 - 1; + + // Setup wait states (ticks needed for 15ms, 55ms and 35ms) + uint32_t val; + val = ((((clk / 1000000) * 15) / 1000) + 1); + val |= (((((clk / 1000000) * 55) / 1000) + 1) << 8); + val |= (((((clk / 1000000) * 35) / 1000) + 1) << 16); + LPC_EEPROM->WSTATE = val; + + _initialized = true; + } +} + +void InternalEEPROM::powerDown() +{ + LPC_EEPROM->PWRDWN = EEPROM_PWRDWN; +} + +int InternalEEPROM::read(uint32_t pageAddr, uint32_t pageOffset, uint8_t* data, uint32_t size) +{ + uint32_t numRead = 0; + uint32_t readOffset = (pageOffset & (EEPROM_PAGE_SIZE - 1)); + uint32_t readSize = EEPROM_PAGE_SIZE - readOffset; + + powerUp(); + + // Read and store data in buffer + while (size) { + // Make sure we don't write past the end of the buffer + if (readSize > size) { + readSize = size; + } + + readPage(pageAddr, readOffset, &(data[numRead]), readSize); + numRead += readSize; + size -= readSize; + + // Change to next page + pageAddr++; + readOffset = 0; + readSize = EEPROM_PAGE_SIZE; + } + return numRead; +} + +int InternalEEPROM::write(uint32_t pageAddr, uint32_t pageOffset, const uint8_t* data, uint32_t size) +{ +#if defined(DM_BOARD_USE_INT_EEPROM_WRITE) + uint32_t numWritten = 0; + uint32_t writeOffset = (pageOffset & (EEPROM_PAGE_SIZE - 1)); + uint32_t writeSize = EEPROM_PAGE_SIZE - writeOffset; + + powerUp(); + + // Read and store data in buffer + while (size) { + // Make sure we don't read past the end of the buffer + if (writeSize > size) { + writeSize = size; + } + + writePage(pageAddr, writeOffset, &(data[numWritten]), writeSize); + eraseOrProgramPage(pageAddr); + numWritten += writeSize; + size -= writeSize; + + // Change to next page + pageAddr++; + writeOffset = 0; + writeSize = EEPROM_PAGE_SIZE; + } + return numWritten; +#else + return 0; +#endif +} + +void InternalEEPROM::erasePage(uint32_t pageAddr) +{ +#if defined(DM_BOARD_USE_INT_EEPROM_WRITE) + + powerUp(); + + clearInterrupt(EEPROM_INT_ENDOFRW); + setCmd(EEPROM_CMD_32BITS_WRITE); + setAddr(pageAddr, 0); + for (int i = 0; i < EEPROM_PAGE_SIZE; i+=4) { + LPC_EEPROM->WDATA = 0; + waitForInterrupt(EEPROM_INT_ENDOFRW); + } + eraseOrProgramPage(pageAddr); +#endif +}