Subdirectory provided by Embedded Artists

Dependencies:   DM_FATFileSystem DM_HttpServer DM_USBHost EthernetInterface USBDevice mbed-rpc mbed-rtos mbed-src

Dependents:   lpc4088_displaymodule_hello_world_Sept_2018

Fork of DMSupport by Embedded Artists

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers InternalEEPROM.cpp Source File

InternalEEPROM.cpp

00001 /*
00002  *  Copyright 2014 Embedded Artists AB
00003  *
00004  *  Licensed under the Apache License, Version 2.0 (the "License");
00005  *  you may not use this file except in compliance with the License.
00006  *  You may obtain a copy of the License at
00007  *
00008  *    http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  *  Unless required by applicable law or agreed to in writing, software
00011  *  distributed under the License is distributed on an "AS IS" BASIS,
00012  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *  See the License for the specific language governing permissions and
00014  *  limitations under the License.
00015  */
00016 
00017 #include "mbed.h"
00018 #include "InternalEEPROM.h"
00019 
00020 
00021 /******************************************************************************
00022  * Defines and typedefs
00023  *****************************************************************************/
00024 
00025 #define EEPROM_INT_ENDOFRW    (1<<26)
00026 #define EEPROM_INT_ENDOFPROG  (1<<28)
00027 
00028 #define EEPROM_PWRDWN          (1<<0)
00029 
00030 /*
00031  * Commands (for the LPC_EEPROM->CMD register)
00032  */
00033 #define EEPROM_CMD_8BITS_READ           (0)     /*!< EEPROM 8-bit read command */
00034 #define EEPROM_CMD_16BITS_READ          (1)     /*!< EEPROM 16-bit read command */
00035 #define EEPROM_CMD_32BITS_READ          (2)     /*!< EEPROM 32-bit read command */
00036 #define EEPROM_CMD_8BITS_WRITE          (3)     /*!< EEPROM 8-bit write command */
00037 #define EEPROM_CMD_16BITS_WRITE         (4)     /*!< EEPROM 16-bit write command */
00038 #define EEPROM_CMD_32BITS_WRITE         (5)     /*!< EEPROM 32-bit write command */
00039 #define EEPROM_CMD_ERASE_PRG_PAGE       (6)     /*!< EEPROM erase/program command */
00040 #define EEPROM_CMD_RDPREFETCH           (1 << 3)/*!< EEPROM read pre-fetch enable */
00041 
00042 
00043 /******************************************************************************
00044  * Local variables
00045  *****************************************************************************/
00046 
00047 /******************************************************************************
00048  * Private Functions
00049  *****************************************************************************/
00050 
00051 void InternalEEPROM::powerUp()
00052 {
00053   LPC_EEPROM->PWRDWN = 0;
00054 }
00055 
00056 void InternalEEPROM::clearInterrupt(uint32_t mask)
00057 {
00058   LPC_EEPROM->INT_CLR_STATUS = mask;
00059 }
00060 
00061 void InternalEEPROM::waitForInterrupt(uint32_t mask)
00062 {
00063   while ((LPC_EEPROM->INT_STATUS & mask) != mask) {
00064   }
00065 
00066   clearInterrupt(mask);
00067 }
00068 
00069 void InternalEEPROM::setAddr(uint32_t pageAddr, uint32_t pageOffset)
00070 {
00071   LPC_EEPROM->ADDR = (pageAddr << 6) | pageOffset;
00072 }
00073 
00074 void InternalEEPROM::setCmd(uint32_t cmd)
00075 {
00076   LPC_EEPROM->CMD = cmd;
00077 }
00078 
00079 void InternalEEPROM::readPage(uint32_t pageAddr, uint32_t pageOffset, uint8_t* buf, uint32_t size)
00080 {
00081   clearInterrupt(EEPROM_INT_ENDOFRW);
00082   setAddr(pageAddr, pageOffset);
00083   setCmd(EEPROM_CMD_8BITS_READ | EEPROM_CMD_RDPREFETCH);
00084   for (uint32_t i = 0; i < size; i++) {
00085     buf[i] = LPC_EEPROM->RDATA & 0xff;
00086     waitForInterrupt(EEPROM_INT_ENDOFRW);
00087   }
00088 }
00089 
00090 void InternalEEPROM::writePage(uint32_t pageAddr, uint32_t pageOffset, const uint8_t* buf, uint32_t size)
00091 {
00092   clearInterrupt(EEPROM_INT_ENDOFRW);
00093   setCmd(EEPROM_CMD_8BITS_WRITE);
00094   setAddr(pageAddr, pageOffset);
00095   for (uint32_t i = 0; i < size; i++) {
00096     LPC_EEPROM->WDATA = buf[i];
00097     waitForInterrupt(EEPROM_INT_ENDOFRW);
00098   }
00099 }
00100 
00101 void InternalEEPROM::eraseOrProgramPage(uint32_t pageAddr)
00102 {
00103   // Write data from page register to non-volatile memory
00104   clearInterrupt(EEPROM_INT_ENDOFPROG);
00105   setAddr(pageAddr, 0);
00106   setCmd(EEPROM_CMD_ERASE_PRG_PAGE);
00107   waitForInterrupt(EEPROM_INT_ENDOFPROG);
00108 }
00109 
00110 
00111 /******************************************************************************
00112  * Public Functions
00113  *****************************************************************************/
00114 
00115 InternalEEPROM::InternalEEPROM() : _initialized(false)
00116 {
00117 }
00118 
00119 InternalEEPROM::~InternalEEPROM()
00120 {
00121 }
00122 
00123 void InternalEEPROM::init()
00124 {
00125   if (!_initialized) {
00126     // Bring EEPROM device out of power down mode
00127     powerUp();
00128   
00129     // Setup EEPROM timing to 375KHz based on PCLK rate
00130     uint32_t clk = SystemCoreClock;
00131     LPC_EEPROM->CLKDIV = SystemCoreClock / 375000 - 1;
00132     
00133     // Setup wait states (ticks needed for 15ms, 55ms and 35ms)
00134     uint32_t val;
00135     val  = ((((clk / 1000000) * 15) / 1000) + 1);
00136     val |= (((((clk / 1000000) * 55) / 1000) + 1) << 8);
00137     val |= (((((clk / 1000000) * 35) / 1000) + 1) << 16);
00138     LPC_EEPROM->WSTATE = val;
00139       
00140     _initialized = true;
00141   }
00142 }
00143 
00144 void InternalEEPROM::powerDown()
00145 {
00146   LPC_EEPROM->PWRDWN = EEPROM_PWRDWN;
00147 }
00148 
00149 int InternalEEPROM::read(uint32_t addr, uint8_t* data, uint32_t size)
00150 {
00151   uint32_t numRead = 0;
00152   uint32_t pageAddr = addr/EEPROM_PAGE_SIZE;
00153   uint32_t readOffset = (addr & (EEPROM_PAGE_SIZE - 1));
00154   uint32_t readSize = EEPROM_PAGE_SIZE - readOffset;
00155   
00156   // Prevent reading past the end of the memory
00157   if (addr >= EEPROM_MEMORY_SIZE) {
00158     return 0;
00159   }
00160   if ((size + addr) > EEPROM_MEMORY_SIZE) {
00161     size = EEPROM_MEMORY_SIZE - addr;
00162   }
00163 
00164   powerUp();
00165 
00166   // Read and store data in buffer
00167   while (size) {
00168     // Make sure we don't write past the end of the buffer
00169     if (readSize > size) {
00170       readSize = size;
00171     }
00172     
00173     readPage(pageAddr, readOffset, &(data[numRead]), readSize);
00174     numRead += readSize;
00175     size -= readSize;
00176 
00177     // Change to next page
00178     pageAddr++;
00179     readOffset = 0;
00180     readSize = EEPROM_PAGE_SIZE;
00181   }
00182   return numRead;
00183 }
00184 
00185 int InternalEEPROM::write(uint32_t addr, const uint8_t* data, uint32_t size)
00186 {
00187   uint32_t numWritten = 0;
00188   uint32_t pageAddr = addr/EEPROM_PAGE_SIZE;
00189   uint32_t writeOffset = (addr & (EEPROM_PAGE_SIZE - 1));
00190   uint32_t writeSize = EEPROM_PAGE_SIZE - writeOffset;
00191 
00192   // Prevent writing past the end of the memory
00193   if (addr >= EEPROM_MEMORY_SIZE) {
00194     return 0;
00195   }
00196   if ((size + addr) > EEPROM_MEMORY_SIZE) {
00197     size = EEPROM_MEMORY_SIZE - addr;
00198   }
00199 
00200   powerUp();
00201 
00202   // Read and store data in buffer
00203   while (size) {
00204     // Make sure we don't read past the end of the buffer
00205     if (writeSize > size) {
00206       writeSize = size;
00207     }
00208     
00209     writePage(pageAddr, writeOffset, &(data[numWritten]), writeSize);
00210     eraseOrProgramPage(pageAddr);
00211     numWritten += writeSize;
00212     size -= writeSize;
00213 
00214     // Change to next page
00215     pageAddr++;
00216     writeOffset = 0;
00217     writeSize = EEPROM_PAGE_SIZE;
00218   }
00219   return numWritten;
00220 }