Dependencies: DM_FATFileSystem EthernetInterface HTTPClient mbed-rtos mbed-src
Fork of DMSupport by
Memory/InternalEEPROM.cpp@34:fc366bab393f, 2015-03-09 (annotated)
- Committer:
- embeddedartists
- Date:
- Mon Mar 09 11:15:56 2015 +0100
- Revision:
- 34:fc366bab393f
- Parent:
- 29:b1ec19000e15
- Added size guards in InternalEEPROM
- Added documentation in missing classes
- Added option to redirect RtosLog to USBSerial (a USB Device Serial port)
- Moved the mbed_mac_address function from the SDK to the BIOS
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
embeddedartists | 0:6b68dac0d986 | 1 | /* |
embeddedartists | 9:a33326afd686 | 2 | * Copyright 2014 Embedded Artists AB |
embeddedartists | 0:6b68dac0d986 | 3 | * |
embeddedartists | 0:6b68dac0d986 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
embeddedartists | 0:6b68dac0d986 | 5 | * you may not use this file except in compliance with the License. |
embeddedartists | 0:6b68dac0d986 | 6 | * You may obtain a copy of the License at |
embeddedartists | 0:6b68dac0d986 | 7 | * |
embeddedartists | 0:6b68dac0d986 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
embeddedartists | 0:6b68dac0d986 | 9 | * |
embeddedartists | 0:6b68dac0d986 | 10 | * Unless required by applicable law or agreed to in writing, software |
embeddedartists | 0:6b68dac0d986 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
embeddedartists | 0:6b68dac0d986 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
embeddedartists | 0:6b68dac0d986 | 13 | * See the License for the specific language governing permissions and |
embeddedartists | 0:6b68dac0d986 | 14 | * limitations under the License. |
embeddedartists | 0:6b68dac0d986 | 15 | */ |
embeddedartists | 0:6b68dac0d986 | 16 | |
embeddedartists | 0:6b68dac0d986 | 17 | #include "mbed.h" |
embeddedartists | 0:6b68dac0d986 | 18 | #include "InternalEEPROM.h" |
embeddedartists | 0:6b68dac0d986 | 19 | |
embeddedartists | 0:6b68dac0d986 | 20 | |
embeddedartists | 0:6b68dac0d986 | 21 | /****************************************************************************** |
embeddedartists | 0:6b68dac0d986 | 22 | * Defines and typedefs |
embeddedartists | 0:6b68dac0d986 | 23 | *****************************************************************************/ |
embeddedartists | 0:6b68dac0d986 | 24 | |
embeddedartists | 0:6b68dac0d986 | 25 | #define EEPROM_INT_ENDOFRW (1<<26) |
embeddedartists | 0:6b68dac0d986 | 26 | #define EEPROM_INT_ENDOFPROG (1<<28) |
embeddedartists | 0:6b68dac0d986 | 27 | |
embeddedartists | 0:6b68dac0d986 | 28 | #define EEPROM_PWRDWN (1<<0) |
embeddedartists | 0:6b68dac0d986 | 29 | |
embeddedartists | 0:6b68dac0d986 | 30 | /* |
embeddedartists | 0:6b68dac0d986 | 31 | * Commands (for the LPC_EEPROM->CMD register) |
embeddedartists | 0:6b68dac0d986 | 32 | */ |
embeddedartists | 0:6b68dac0d986 | 33 | #define EEPROM_CMD_8BITS_READ (0) /*!< EEPROM 8-bit read command */ |
embeddedartists | 0:6b68dac0d986 | 34 | #define EEPROM_CMD_16BITS_READ (1) /*!< EEPROM 16-bit read command */ |
embeddedartists | 0:6b68dac0d986 | 35 | #define EEPROM_CMD_32BITS_READ (2) /*!< EEPROM 32-bit read command */ |
embeddedartists | 0:6b68dac0d986 | 36 | #define EEPROM_CMD_8BITS_WRITE (3) /*!< EEPROM 8-bit write command */ |
embeddedartists | 0:6b68dac0d986 | 37 | #define EEPROM_CMD_16BITS_WRITE (4) /*!< EEPROM 16-bit write command */ |
embeddedartists | 0:6b68dac0d986 | 38 | #define EEPROM_CMD_32BITS_WRITE (5) /*!< EEPROM 32-bit write command */ |
embeddedartists | 0:6b68dac0d986 | 39 | #define EEPROM_CMD_ERASE_PRG_PAGE (6) /*!< EEPROM erase/program command */ |
embeddedartists | 0:6b68dac0d986 | 40 | #define EEPROM_CMD_RDPREFETCH (1 << 3)/*!< EEPROM read pre-fetch enable */ |
embeddedartists | 0:6b68dac0d986 | 41 | |
embeddedartists | 0:6b68dac0d986 | 42 | |
embeddedartists | 0:6b68dac0d986 | 43 | /****************************************************************************** |
embeddedartists | 0:6b68dac0d986 | 44 | * Local variables |
embeddedartists | 0:6b68dac0d986 | 45 | *****************************************************************************/ |
embeddedartists | 0:6b68dac0d986 | 46 | |
embeddedartists | 0:6b68dac0d986 | 47 | /****************************************************************************** |
embeddedartists | 0:6b68dac0d986 | 48 | * Private Functions |
embeddedartists | 0:6b68dac0d986 | 49 | *****************************************************************************/ |
embeddedartists | 0:6b68dac0d986 | 50 | |
embeddedartists | 0:6b68dac0d986 | 51 | void InternalEEPROM::powerUp() |
embeddedartists | 0:6b68dac0d986 | 52 | { |
embeddedartists | 0:6b68dac0d986 | 53 | LPC_EEPROM->PWRDWN = 0; |
embeddedartists | 0:6b68dac0d986 | 54 | } |
embeddedartists | 0:6b68dac0d986 | 55 | |
embeddedartists | 0:6b68dac0d986 | 56 | void InternalEEPROM::clearInterrupt(uint32_t mask) |
embeddedartists | 0:6b68dac0d986 | 57 | { |
embeddedartists | 0:6b68dac0d986 | 58 | LPC_EEPROM->INT_CLR_STATUS = mask; |
embeddedartists | 0:6b68dac0d986 | 59 | } |
embeddedartists | 0:6b68dac0d986 | 60 | |
embeddedartists | 0:6b68dac0d986 | 61 | void InternalEEPROM::waitForInterrupt(uint32_t mask) |
embeddedartists | 0:6b68dac0d986 | 62 | { |
embeddedartists | 0:6b68dac0d986 | 63 | while ((LPC_EEPROM->INT_STATUS & mask) != mask) { |
embeddedartists | 0:6b68dac0d986 | 64 | } |
embeddedartists | 0:6b68dac0d986 | 65 | |
embeddedartists | 0:6b68dac0d986 | 66 | clearInterrupt(mask); |
embeddedartists | 0:6b68dac0d986 | 67 | } |
embeddedartists | 0:6b68dac0d986 | 68 | |
embeddedartists | 0:6b68dac0d986 | 69 | void InternalEEPROM::setAddr(uint32_t pageAddr, uint32_t pageOffset) |
embeddedartists | 0:6b68dac0d986 | 70 | { |
embeddedartists | 0:6b68dac0d986 | 71 | LPC_EEPROM->ADDR = (pageAddr << 6) | pageOffset; |
embeddedartists | 0:6b68dac0d986 | 72 | } |
embeddedartists | 0:6b68dac0d986 | 73 | |
embeddedartists | 0:6b68dac0d986 | 74 | void InternalEEPROM::setCmd(uint32_t cmd) |
embeddedartists | 0:6b68dac0d986 | 75 | { |
embeddedartists | 0:6b68dac0d986 | 76 | LPC_EEPROM->CMD = cmd; |
embeddedartists | 0:6b68dac0d986 | 77 | } |
embeddedartists | 0:6b68dac0d986 | 78 | |
embeddedartists | 0:6b68dac0d986 | 79 | void InternalEEPROM::readPage(uint32_t pageAddr, uint32_t pageOffset, uint8_t* buf, uint32_t size) |
embeddedartists | 0:6b68dac0d986 | 80 | { |
embeddedartists | 0:6b68dac0d986 | 81 | clearInterrupt(EEPROM_INT_ENDOFRW); |
embeddedartists | 0:6b68dac0d986 | 82 | setAddr(pageAddr, pageOffset); |
embeddedartists | 0:6b68dac0d986 | 83 | setCmd(EEPROM_CMD_8BITS_READ | EEPROM_CMD_RDPREFETCH); |
embeddedartists | 29:b1ec19000e15 | 84 | for (uint32_t i = 0; i < size; i++) { |
embeddedartists | 0:6b68dac0d986 | 85 | buf[i] = LPC_EEPROM->RDATA & 0xff; |
embeddedartists | 0:6b68dac0d986 | 86 | waitForInterrupt(EEPROM_INT_ENDOFRW); |
embeddedartists | 0:6b68dac0d986 | 87 | } |
embeddedartists | 0:6b68dac0d986 | 88 | } |
embeddedartists | 0:6b68dac0d986 | 89 | |
embeddedartists | 0:6b68dac0d986 | 90 | void InternalEEPROM::writePage(uint32_t pageAddr, uint32_t pageOffset, const uint8_t* buf, uint32_t size) |
embeddedartists | 0:6b68dac0d986 | 91 | { |
embeddedartists | 0:6b68dac0d986 | 92 | clearInterrupt(EEPROM_INT_ENDOFRW); |
embeddedartists | 0:6b68dac0d986 | 93 | setCmd(EEPROM_CMD_8BITS_WRITE); |
embeddedartists | 0:6b68dac0d986 | 94 | setAddr(pageAddr, pageOffset); |
embeddedartists | 29:b1ec19000e15 | 95 | for (uint32_t i = 0; i < size; i++) { |
embeddedartists | 0:6b68dac0d986 | 96 | LPC_EEPROM->WDATA = buf[i]; |
embeddedartists | 0:6b68dac0d986 | 97 | waitForInterrupt(EEPROM_INT_ENDOFRW); |
embeddedartists | 0:6b68dac0d986 | 98 | } |
embeddedartists | 0:6b68dac0d986 | 99 | } |
embeddedartists | 0:6b68dac0d986 | 100 | |
embeddedartists | 0:6b68dac0d986 | 101 | void InternalEEPROM::eraseOrProgramPage(uint32_t pageAddr) |
embeddedartists | 0:6b68dac0d986 | 102 | { |
embeddedartists | 0:6b68dac0d986 | 103 | // Write data from page register to non-volatile memory |
embeddedartists | 0:6b68dac0d986 | 104 | clearInterrupt(EEPROM_INT_ENDOFPROG); |
embeddedartists | 0:6b68dac0d986 | 105 | setAddr(pageAddr, 0); |
embeddedartists | 0:6b68dac0d986 | 106 | setCmd(EEPROM_CMD_ERASE_PRG_PAGE); |
embeddedartists | 0:6b68dac0d986 | 107 | waitForInterrupt(EEPROM_INT_ENDOFPROG); |
embeddedartists | 0:6b68dac0d986 | 108 | } |
embeddedartists | 0:6b68dac0d986 | 109 | |
embeddedartists | 0:6b68dac0d986 | 110 | |
embeddedartists | 0:6b68dac0d986 | 111 | /****************************************************************************** |
embeddedartists | 0:6b68dac0d986 | 112 | * Public Functions |
embeddedartists | 0:6b68dac0d986 | 113 | *****************************************************************************/ |
embeddedartists | 0:6b68dac0d986 | 114 | |
embeddedartists | 0:6b68dac0d986 | 115 | InternalEEPROM::InternalEEPROM() : _initialized(false) |
embeddedartists | 0:6b68dac0d986 | 116 | { |
embeddedartists | 0:6b68dac0d986 | 117 | } |
embeddedartists | 0:6b68dac0d986 | 118 | |
embeddedartists | 0:6b68dac0d986 | 119 | InternalEEPROM::~InternalEEPROM() |
embeddedartists | 0:6b68dac0d986 | 120 | { |
embeddedartists | 0:6b68dac0d986 | 121 | } |
embeddedartists | 0:6b68dac0d986 | 122 | |
embeddedartists | 0:6b68dac0d986 | 123 | void InternalEEPROM::init() |
embeddedartists | 0:6b68dac0d986 | 124 | { |
embeddedartists | 0:6b68dac0d986 | 125 | if (!_initialized) { |
embeddedartists | 0:6b68dac0d986 | 126 | // Bring EEPROM device out of power down mode |
embeddedartists | 0:6b68dac0d986 | 127 | powerUp(); |
embeddedartists | 0:6b68dac0d986 | 128 | |
embeddedartists | 0:6b68dac0d986 | 129 | // Setup EEPROM timing to 375KHz based on PCLK rate |
embeddedartists | 0:6b68dac0d986 | 130 | uint32_t clk = SystemCoreClock; |
embeddedartists | 0:6b68dac0d986 | 131 | LPC_EEPROM->CLKDIV = SystemCoreClock / 375000 - 1; |
embeddedartists | 0:6b68dac0d986 | 132 | |
embeddedartists | 0:6b68dac0d986 | 133 | // Setup wait states (ticks needed for 15ms, 55ms and 35ms) |
embeddedartists | 0:6b68dac0d986 | 134 | uint32_t val; |
embeddedartists | 0:6b68dac0d986 | 135 | val = ((((clk / 1000000) * 15) / 1000) + 1); |
embeddedartists | 0:6b68dac0d986 | 136 | val |= (((((clk / 1000000) * 55) / 1000) + 1) << 8); |
embeddedartists | 0:6b68dac0d986 | 137 | val |= (((((clk / 1000000) * 35) / 1000) + 1) << 16); |
embeddedartists | 0:6b68dac0d986 | 138 | LPC_EEPROM->WSTATE = val; |
embeddedartists | 0:6b68dac0d986 | 139 | |
embeddedartists | 0:6b68dac0d986 | 140 | _initialized = true; |
embeddedartists | 0:6b68dac0d986 | 141 | } |
embeddedartists | 0:6b68dac0d986 | 142 | } |
embeddedartists | 0:6b68dac0d986 | 143 | |
embeddedartists | 0:6b68dac0d986 | 144 | void InternalEEPROM::powerDown() |
embeddedartists | 0:6b68dac0d986 | 145 | { |
embeddedartists | 0:6b68dac0d986 | 146 | LPC_EEPROM->PWRDWN = EEPROM_PWRDWN; |
embeddedartists | 0:6b68dac0d986 | 147 | } |
embeddedartists | 0:6b68dac0d986 | 148 | |
embeddedartists | 20:9df19da50290 | 149 | int InternalEEPROM::read(uint32_t addr, uint8_t* data, uint32_t size) |
embeddedartists | 0:6b68dac0d986 | 150 | { |
embeddedartists | 0:6b68dac0d986 | 151 | uint32_t numRead = 0; |
embeddedartists | 20:9df19da50290 | 152 | uint32_t pageAddr = addr/EEPROM_PAGE_SIZE; |
embeddedartists | 20:9df19da50290 | 153 | uint32_t readOffset = (addr & (EEPROM_PAGE_SIZE - 1)); |
embeddedartists | 0:6b68dac0d986 | 154 | uint32_t readSize = EEPROM_PAGE_SIZE - readOffset; |
embeddedartists | 34:fc366bab393f | 155 | |
embeddedartists | 34:fc366bab393f | 156 | // Prevent reading past the end of the memory |
embeddedartists | 34:fc366bab393f | 157 | if (addr >= EEPROM_MEMORY_SIZE) { |
embeddedartists | 34:fc366bab393f | 158 | return 0; |
embeddedartists | 34:fc366bab393f | 159 | } |
embeddedartists | 34:fc366bab393f | 160 | if ((size + addr) > EEPROM_MEMORY_SIZE) { |
embeddedartists | 34:fc366bab393f | 161 | size = EEPROM_MEMORY_SIZE - addr; |
embeddedartists | 34:fc366bab393f | 162 | } |
embeddedartists | 0:6b68dac0d986 | 163 | |
embeddedartists | 0:6b68dac0d986 | 164 | powerUp(); |
embeddedartists | 0:6b68dac0d986 | 165 | |
embeddedartists | 0:6b68dac0d986 | 166 | // Read and store data in buffer |
embeddedartists | 0:6b68dac0d986 | 167 | while (size) { |
embeddedartists | 0:6b68dac0d986 | 168 | // Make sure we don't write past the end of the buffer |
embeddedartists | 0:6b68dac0d986 | 169 | if (readSize > size) { |
embeddedartists | 0:6b68dac0d986 | 170 | readSize = size; |
embeddedartists | 0:6b68dac0d986 | 171 | } |
embeddedartists | 0:6b68dac0d986 | 172 | |
embeddedartists | 0:6b68dac0d986 | 173 | readPage(pageAddr, readOffset, &(data[numRead]), readSize); |
embeddedartists | 0:6b68dac0d986 | 174 | numRead += readSize; |
embeddedartists | 0:6b68dac0d986 | 175 | size -= readSize; |
embeddedartists | 0:6b68dac0d986 | 176 | |
embeddedartists | 0:6b68dac0d986 | 177 | // Change to next page |
embeddedartists | 0:6b68dac0d986 | 178 | pageAddr++; |
embeddedartists | 0:6b68dac0d986 | 179 | readOffset = 0; |
embeddedartists | 0:6b68dac0d986 | 180 | readSize = EEPROM_PAGE_SIZE; |
embeddedartists | 0:6b68dac0d986 | 181 | } |
embeddedartists | 0:6b68dac0d986 | 182 | return numRead; |
embeddedartists | 0:6b68dac0d986 | 183 | } |
embeddedartists | 0:6b68dac0d986 | 184 | |
embeddedartists | 20:9df19da50290 | 185 | int InternalEEPROM::write(uint32_t addr, const uint8_t* data, uint32_t size) |
embeddedartists | 0:6b68dac0d986 | 186 | { |
embeddedartists | 0:6b68dac0d986 | 187 | uint32_t numWritten = 0; |
embeddedartists | 20:9df19da50290 | 188 | uint32_t pageAddr = addr/EEPROM_PAGE_SIZE; |
embeddedartists | 20:9df19da50290 | 189 | uint32_t writeOffset = (addr & (EEPROM_PAGE_SIZE - 1)); |
embeddedartists | 0:6b68dac0d986 | 190 | uint32_t writeSize = EEPROM_PAGE_SIZE - writeOffset; |
embeddedartists | 0:6b68dac0d986 | 191 | |
embeddedartists | 34:fc366bab393f | 192 | // Prevent writing past the end of the memory |
embeddedartists | 34:fc366bab393f | 193 | if (addr >= EEPROM_MEMORY_SIZE) { |
embeddedartists | 34:fc366bab393f | 194 | return 0; |
embeddedartists | 34:fc366bab393f | 195 | } |
embeddedartists | 34:fc366bab393f | 196 | if ((size + addr) > EEPROM_MEMORY_SIZE) { |
embeddedartists | 34:fc366bab393f | 197 | size = EEPROM_MEMORY_SIZE - addr; |
embeddedartists | 34:fc366bab393f | 198 | } |
embeddedartists | 34:fc366bab393f | 199 | |
embeddedartists | 0:6b68dac0d986 | 200 | powerUp(); |
embeddedartists | 0:6b68dac0d986 | 201 | |
embeddedartists | 0:6b68dac0d986 | 202 | // Read and store data in buffer |
embeddedartists | 0:6b68dac0d986 | 203 | while (size) { |
embeddedartists | 0:6b68dac0d986 | 204 | // Make sure we don't read past the end of the buffer |
embeddedartists | 0:6b68dac0d986 | 205 | if (writeSize > size) { |
embeddedartists | 0:6b68dac0d986 | 206 | writeSize = size; |
embeddedartists | 0:6b68dac0d986 | 207 | } |
embeddedartists | 0:6b68dac0d986 | 208 | |
embeddedartists | 0:6b68dac0d986 | 209 | writePage(pageAddr, writeOffset, &(data[numWritten]), writeSize); |
embeddedartists | 0:6b68dac0d986 | 210 | eraseOrProgramPage(pageAddr); |
embeddedartists | 0:6b68dac0d986 | 211 | numWritten += writeSize; |
embeddedartists | 0:6b68dac0d986 | 212 | size -= writeSize; |
embeddedartists | 0:6b68dac0d986 | 213 | |
embeddedartists | 0:6b68dac0d986 | 214 | // Change to next page |
embeddedartists | 0:6b68dac0d986 | 215 | pageAddr++; |
embeddedartists | 0:6b68dac0d986 | 216 | writeOffset = 0; |
embeddedartists | 0:6b68dac0d986 | 217 | writeSize = EEPROM_PAGE_SIZE; |
embeddedartists | 0:6b68dac0d986 | 218 | } |
embeddedartists | 0:6b68dac0d986 | 219 | return numWritten; |
embeddedartists | 0:6b68dac0d986 | 220 | } |