10 #include <lib/assert.h> 17 #define EEPROM_BUFFER_SIZE(e) (((e)->PageSize < 64) ? 64 : ((e)->PageSize)) 19 #define EEPROM_BIT_PRESENT (1 << 0) 20 #define EEPROM_BIT_USED (1 << 1) 21 #define EEPROM_BIT_VALID (1 << 2) 22 #define EEPROM_BITS(bits) ((uint8_t) ~(bits)) 35 struct eeprom_bank_t {
41 static uint32_t eeprom_sector(
const struct eeprom_t *e, uint8_t bank);
42 static uint32_t eeprom_page(
const struct eeprom_t *e, uint8_t bank, uint16_t page);
43 static uint32_t eeprom_addr(
const struct eeprom_t *e, uint8_t bank, uint16_t page, uint32_t offset);
44 static void eeprom_bank_init(
const struct eeprom_t *e, uint8_t *buffer, uint8_t bank);
45 static bool eeprom_bank_open(
const struct eeprom_t *e, uint8_t *buffer,
unsigned bank,
struct eeprom_bank_t *cache);
46 static void eeprom_read_impl(eeprom_addr_t addr,
unsigned char *buf,
int size,
const struct eeprom_t *e);
47 static void eeprom_write_impl(eeprom_addr_t addr,
const unsigned char *buf,
int size,
const struct eeprom_t *e);
48 static void eeprom_init_impl(
const struct eeprom_t *e);
50 static bool eeprom_ext_power(
bool On);
51 static void eeprom_ext_erase(uint32_t SectorIndex);
52 static void eeprom_ext_write(uint32_t DstAddress,
const void *SrcBuffer, uint32_t ByteCount);
53 static void eeprom_ext_read(
void *DstBuffer, uint32_t SrcAddress, uint32_t ByteCount);
55 static bool eeprom_int_power(
bool On);
56 static void eeprom_int_erase(uint32_t SectorIndex);
57 static void eeprom_int_write(uint32_t DstAddress,
const void *SrcBuffer, uint32_t ByteCount);
58 static void eeprom_int_read(
void *DstBuffer, uint32_t SrcAddress, uint32_t ByteCount);
63 .Power = eeprom_ext_power,
64 .Erase = eeprom_ext_erase,
65 .Write = eeprom_ext_write,
66 .Read = eeprom_ext_read,
71 .Power = eeprom_int_power,
72 .Erase = eeprom_int_erase,
73 .Write = eeprom_int_write,
74 .Read = eeprom_int_read,
80 static uint32_t eeprom_sector(
const struct eeprom_t *e, uint8_t bank)
86 static uint32_t eeprom_page(
const struct eeprom_t *e, uint8_t bank, uint16_t page)
92 static uint32_t eeprom_addr(
const struct eeprom_t *e, uint8_t bank, uint16_t page, uint32_t offset)
94 return eeprom_page(e, bank, page) * e->
PageSize + offset;
98 static void eeprom_bank_init(
const struct eeprom_t *e, uint8_t *buffer, uint8_t bank)
106 v->Erase(eeprom_sector(e, bank));
110 if (chunk > EEPROM_BUFFER_SIZE(e))
111 chunk = EEPROM_BUFFER_SIZE(e);
114 memset(&buffer[0], EEPROM_BITS(EEPROM_BIT_PRESENT), chunk);
116 buffer[0] = EEPROM_BITS(EEPROM_BIT_PRESENT | EEPROM_BIT_USED);
118 v->Write(eeprom_addr(e, bank, 0, pos), buffer, chunk);
122 buffer[0] = EEPROM_BITS(EEPROM_BIT_PRESENT | EEPROM_BIT_USED | EEPROM_BIT_VALID);
123 v->Write(eeprom_addr(e, bank, 0, 0), buffer, 1);
127 static bool eeprom_bank_open(
const struct eeprom_t *e, uint8_t *buffer,
unsigned bank,
struct eeprom_bank_t *cache)
135 cache->read = cache->write = 0;
139 if (chunk > EEPROM_BUFFER_SIZE(e))
140 chunk = EEPROM_BUFFER_SIZE(e);
142 v->Read(buffer, eeprom_addr(e, bank, 0, pos), chunk);
146 && buffer[0] != EEPROM_BITS(EEPROM_BIT_PRESENT | EEPROM_BIT_USED | EEPROM_BIT_VALID))
150 while (idx < pos + chunk) {
152 if (buffer[idx - pos] == EEPROM_BITS(EEPROM_BIT_PRESENT | EEPROM_BIT_USED | EEPROM_BIT_VALID)) {
155 }
else if (buffer[idx - pos] == EEPROM_BITS(EEPROM_BIT_PRESENT)) {
156 if (cache->write == 0)
159 }
else if (buffer[idx - pos] != EEPROM_BITS(EEPROM_BIT_PRESENT | EEPROM_BIT_USED)) {
171 static void eeprom_read_impl(eeprom_addr_t addr,
unsigned char *buf,
int size,
const struct eeprom_t *e)
182 if (addr > eeprom_size || (addr + size) > eeprom_size || size <= 0)
187 memset(buf, 0xFF, size);
197 static void eeprom_write_impl(eeprom_addr_t addr,
const unsigned char *buf,
int size,
const struct eeprom_t *e)
202 uint8_t *buffer = alloca(EEPROM_BUFFER_SIZE(e));
210 if (addr > eeprom_size || (addr + size) > eeprom_size || size <= 0)
238 memset(buffer, EEPROM_BITS(EEPROM_BIT_PRESENT | EEPROM_BIT_USED), e->
PagesPerEeprom);
245 if (addr < (page + 1) * e->
PageSize && size > 0) {
246 unsigned offset = addr & (e->
PageSize - 1);
247 unsigned chunk = e->
PageSize - offset;
251 memcpy(&buffer[offset], buf, chunk);
262 memset(buffer, EEPROM_BITS(EEPROM_BIT_PRESENT | EEPROM_BIT_USED | EEPROM_BIT_VALID), e->
PagesPerEeprom);
267 eeprom_bank_init(e, buffer, s->
read_bank);
279 static void eeprom_init_impl(
const struct eeprom_t *e)
284 uint8_t *buffer = alloca(EEPROM_BUFFER_SIZE(e));
285 struct eeprom_bank_t bank[BANK__COUNT];
286 struct eeprom_bank_t idx;
302 for (i = 0; i < BANK__COUNT; ++i) {
303 if (!eeprom_bank_open(e, buffer, i, &bank[i])) {
304 eeprom_bank_init(e, buffer, i);
305 eeprom_bank_open(e, buffer, i, &bank[i]);
311 if (bank[BANK_1].read == 0 && bank[BANK_2].read == 0)
313 else if (bank[BANK_1].read == 0)
315 else if (bank[BANK_2].read == 0)
317 else if (bank[BANK_1].read < bank[BANK_2].read)
323 if (bank[BANK_1].write == 0 && bank[BANK_2].write == 0) {
324 eeprom_bank_init(e, buffer, BANK_1);
325 eeprom_bank_open(e, buffer, BANK_1, &bank[BANK_1]);
326 eeprom_bank_init(e, buffer, BANK_2);
327 eeprom_bank_open(e, buffer, BANK_2, &bank[BANK_2]);
329 }
else if (bank[BANK_2].write == 0)
331 else if (bank[BANK_1].write == 0)
333 else if (bank[BANK_2].write == header_size)
335 else if (bank[BANK_1].write == header_size)
337 else if (bank[BANK_1].write > bank[BANK_2].write)
343 if (idx.read == idx.write) {
344 uint8_t other = idx.read ^ (BANK_1 ^ BANK_2);
346 if (bank[other].write != header_size || bank[other].read != 0) {
347 eeprom_bank_init(e, buffer, other);
348 eeprom_bank_open(e, buffer, other, &bank[other]);
367 static bool eeprom_ext_power(
bool On)
371 return (RequestExtFlash() == 0);
380 static void eeprom_ext_erase(uint32_t SectorIndex)
385 static void eeprom_ext_write(uint32_t DstAddress,
const void *SrcBuffer, uint32_t ByteCount)
390 static void eeprom_ext_read(
void *DstBuffer, uint32_t SrcAddress, uint32_t ByteCount)
397 static bool eeprom_int_power(
bool On)
402 static void eeprom_int_erase(uint32_t SectorIndex)
404 DECLARE_FLASH_OP_MONITOR(Monitor);
405 sd_flash_page_erase(SectorIndex);
406 FLASH_OP_WAIT(Monitor);
409 static void eeprom_int_write(uint32_t DstAddress,
const void *SrcBuffer, uint32_t ByteCount)
413 uint8_t Data[4] = {0xFF, 0xFF, 0xFF, 0xFF};
414 unsigned Chunk = 4 - (DstAddress & 3);
416 if (Chunk > ByteCount)
419 memcpy(&Data[DstAddress & 3], SrcBuffer, Chunk);
421 DECLARE_FLASH_OP_MONITOR(Monitor);
422 sd_flash_write((
void *) (DstAddress & 3), (
const uint32_t *) &Data, 1);
423 FLASH_OP_WAIT(Monitor);
425 SrcBuffer = (uint8_t *) SrcBuffer + Chunk;
432 DECLARE_FLASH_OP_MONITOR(Monitor);
433 sd_flash_write((
void *) DstAddress, (
const uint32_t *) SrcBuffer, ByteCount / 4);
434 FLASH_OP_WAIT(Monitor);
436 SrcBuffer = (uint8_t *) SrcBuffer + (ByteCount & ~3);
437 DstAddress += (ByteCount & ~3);
443 uint8_t Data[4] = {0xFF, 0xFF, 0xFF, 0xFF};
445 memcpy(&Data[0], SrcBuffer, ByteCount);
447 DECLARE_FLASH_OP_MONITOR(Monitor);
448 sd_flash_write((
void *) DstAddress, (
const uint32_t *) &Data, 1);
449 FLASH_OP_WAIT(Monitor);
453 static void eeprom_int_read(
void *DstBuffer, uint32_t SrcAddress, uint32_t ByteCount)
455 memcpy(DstBuffer, (
void *) SrcAddress, ByteCount);
463 for (i = 0; i < EepromTableSize; ++i) {
464 if (EepromTable[i].BeginAddr <= addr && EepromTable[i].EndAddr >= addr + size) {
465 eeprom_write_impl(addr - EepromTable[i].BeginAddr, buf, size, &EepromTable[i]);
471 void eeprom_read(eeprom_addr_t addr,
unsigned char *buf,
int size)
474 for (i = 0; i < EepromTableSize; ++i) {
475 if (EepromTable[i].BeginAddr <= addr && EepromTable[i].EndAddr >= addr + size) {
476 eeprom_read_impl(addr - EepromTable[i].BeginAddr, buf, size, &EepromTable[i]);
485 for (i = 0; i < EepromTableSize; ++i) {
486 eeprom_init_impl(&EepromTable[i]);
const struct eeprom_vtbl_t * Vtbl
bool SpiMemoryWrite(const struct spi_memory_t *Memory, uint32_t DstAddress, const void *SrcBuffer, uint32_t ByteCount)
Name: SpiMemoryWrite Writes bytes from SrcBuffer to SPI memory. It the SPI memory is page based...
#define SWINT_AUTO_LOCK()
Header file for the EVE work scheduling.
struct eeprom_state_t * State
void eeprom_read(eeprom_addr_t addr, unsigned char *buf, int size)
Header file for the EVE event monitor primitive.
void eeprom_write(eeprom_addr_t addr, unsigned char *buf, int size)
Driver for SPI-based memories.
bool SpiMemoryEraseSector(const struct spi_memory_t *Memory, uint32_t SectorIndex)
Name: SpiMemoryEraseSector Erases given sector in SPI memory and waits for completion. Called from main program level.
bool SpiMemoryRead(const struct spi_memory_t *Memory, void *DstBuffer, uint32_t SrcAddress, uint32_t ByteCount)
Name: SpiMemoryRead Reads bytes from SPI memory to DstBuffer. Called from main program level...
Driver for EEPROM emulation layer.