|
| 1 | +/* |
| 2 | + EEPROM.h - EEPROM library |
| 3 | + Original Copyright (c) 2006 David A. Mellis. All right reserved. |
| 4 | + New version by Christopher Andrews 2015. |
| 5 | + Curie porting by Intel and Arduino LLC - 2016 |
| 6 | + This library is free software; you can redistribute it and/or |
| 7 | + modify it under the terms of the GNU Lesser General Public |
| 8 | + License as published by the Free Software Foundation; either |
| 9 | + version 2.1 of the License, or (at your option) any later version. |
| 10 | + This library is distributed in the hope that it will be useful, |
| 11 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 13 | + Lesser General Public License for more details. |
| 14 | + You should have received a copy of the GNU Lesser General Public |
| 15 | + License along with this library; if not, write to the Free Software |
| 16 | + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| 17 | +*/ |
| 18 | + |
| 19 | +#include <EEPROM.h> |
| 20 | + |
| 21 | +EEPROMClass EEPROM; |
| 22 | + |
| 23 | +void CurieClear() |
| 24 | +{ |
| 25 | + //erase the 2k bytes of the eeprom section inside the otp area |
| 26 | + *(uint32_t*)(ROM_WR_CTRL) = 0x4002; |
| 27 | + //wait for erase to be complete |
| 28 | + #if 0 |
| 29 | + // TODO: wait for FLASH_STTS.ER_DONE to be set to 1 |
| 30 | + while(((*(uint32_t*)FLASH_STTS) & 0x01) == 0) { |
| 31 | + delay(1); |
| 32 | + } |
| 33 | + #endif |
| 34 | + delay(5); |
| 35 | +} |
| 36 | + |
| 37 | +void CurieRestoreMemory(uint32_t* buffer, uint32_t size) |
| 38 | +{ |
| 39 | + uint32_t rom_wr_ctrl = 0; |
| 40 | + uint32_t address; |
| 41 | + |
| 42 | + for (uint32_t i=0; i<size; i++) { |
| 43 | + |
| 44 | + uint32_t data32 = buffer[i]; |
| 45 | + if (data32 == 0xFFFFFFFF) { |
| 46 | + continue; |
| 47 | + } |
| 48 | + |
| 49 | + //store data into ROM_WR_DATA register |
| 50 | + *(uint32_t*)(ROM_WR_DATA) = data32; |
| 51 | + address = i * 4 + EEPROM_OFFSET; |
| 52 | + //shift left 2 bits to store offset into bits 19:2 (WR_ADDR) |
| 53 | + rom_wr_ctrl = (address)<<2; |
| 54 | + rom_wr_ctrl |= 0x00000001; //set (WR_REQ) bit |
| 55 | + *(uint32_t*)(ROM_WR_CTRL) = rom_wr_ctrl; |
| 56 | + |
| 57 | + delay(3); //give it enough time to finish writing |
| 58 | + } |
| 59 | +} |
| 60 | + |
| 61 | +uint8_t CurieRead8(uint32_t address) |
| 62 | +{ |
| 63 | + if((address > 0x7FF)) |
| 64 | + { |
| 65 | + return 0; |
| 66 | + } |
| 67 | + int offset = address%4; |
| 68 | + uint32_t value = *(uint32_t*)(EEPROM_ADDR+(address/4)*4); |
| 69 | + value = (value >> ((3-offset)*8)) & 0xFF; |
| 70 | + return (uint8_t)value; |
| 71 | +} |
| 72 | + |
| 73 | +uint32_t CurieRead32(uint32_t address) |
| 74 | +{ |
| 75 | + if((address > 0x7FF)) |
| 76 | + { |
| 77 | + return 0; |
| 78 | + } |
| 79 | + uint32_t value = *(uint32_t*)(EEPROM_ADDR+(address/4)*4); |
| 80 | + return value; |
| 81 | +} |
| 82 | + |
| 83 | +void CurieWrite8(uint32_t address, uint8_t data) |
| 84 | +{ |
| 85 | + //make sure address is valid |
| 86 | + if((address > 0x7FF)) |
| 87 | + { |
| 88 | + return; |
| 89 | + } |
| 90 | + |
| 91 | + uint8_t currentValue = CurieRead8(address); |
| 92 | + //only do something if value is different from what is currently stored |
| 93 | + if(currentValue==data) |
| 94 | + { |
| 95 | + return; |
| 96 | + } |
| 97 | + |
| 98 | + uint32_t currentDword = CurieRead32(address); |
| 99 | + |
| 100 | + int offset = address%4; |
| 101 | + |
| 102 | + uint32_t data32 = (currentDword & ~(uint32_t)(0xFF << ((3-offset)*8))); |
| 103 | + data32 = data32 | (data << ((3-offset)*8)); |
| 104 | + |
| 105 | + if (currentValue != 0xFF) { |
| 106 | + uint32_t dump[EEPROM_SIZE/4]; |
| 107 | + memcpy(dump, (uint32_t *)EEPROM_ADDR, EEPROM_SIZE); |
| 108 | + dump[(address >> 2)] = data32; |
| 109 | + CurieClear(); |
| 110 | + CurieRestoreMemory((uint32_t *)dump, EEPROM_SIZE/sizeof(uint32_t)); |
| 111 | + return; |
| 112 | + } |
| 113 | + |
| 114 | + uint32_t rom_wr_ctrl = 0; |
| 115 | + |
| 116 | + //store data into ROM_WR_DATA register |
| 117 | + *(uint32_t*)(ROM_WR_DATA) = data32; |
| 118 | + address = ((address >> 2) << 2) + EEPROM_OFFSET; |
| 119 | + //shift left 2 bits to store offset into bits 19:2 (WR_ADDR) |
| 120 | + rom_wr_ctrl = (address)<<2; |
| 121 | + rom_wr_ctrl |= 0x00000001; //set (WR_REQ) bit |
| 122 | + *(uint32_t*)(ROM_WR_CTRL) = rom_wr_ctrl; |
| 123 | + |
| 124 | + delay(3); //give it enough time to finish writing |
| 125 | +} |
0 commit comments