Dependencies:   DM_FATFileSystem EthernetInterface HTTPClient mbed-rtos mbed-src

Fork of DMSupport by Embedded Artists

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