Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
Lpc17xx40xxEEPROMEmulation.cxx
Go to the documentation of this file.
1
35
36#include <cstring>
37
38#include "iap.h"
39#include "chip.h"
40
41// We can't put a weak definition of a constant, because GCC, due to a bug,
42// will inline the definition that appears here even if it is overridden at link
43// time.
44//
45// const size_t __attribute__((weak)) EEPROMEmulation::SECTOR_SIZE = 0x8000;
46const size_t EEPROMEmulation::BLOCK_SIZE = 16;
48
49static uint8_t get_first_sector() {
50 unsigned estart = (unsigned)(&__eeprom_start);
51 if (estart < 0x10000) {
52 return estart / 0x1000;
53 } else {
54 return 16 - 2 + estart / 0x8000; // estart==0x10000 -> sector==16.
55 }
56}
57
62LpcEEPROMEmulation::LpcEEPROMEmulation(const char *name, size_t file_size)
63 : EEPROMEmulation(name, file_size), firstSector_(get_first_sector())
64{
65 /* IAP cannot access RAM below 0x10000200) */
66 HASSERT(((uintptr_t)scratch) >= 0x10000200);
67
68 unsigned eend = (unsigned)(&__eeprom_end);
69 unsigned estart = (unsigned)(&__eeprom_start);
70 if (eend <= 0x10000) {
71 HASSERT(SECTOR_SIZE == 0x1000);
72 } else if (estart >= 0x10000) {
73 HASSERT(SECTOR_SIZE == 0x8000);
74 } else {
75 DIE("LPC17xx cannot have the EEPROM range cross the boundary of "
76 "address of 0x10000");
77 }
78 HASSERT(estart % SECTOR_SIZE == 0);
79 HASSERT(eend % SECTOR_SIZE == 0);
80
81 mount();
82}
83
84inline const uint32_t *LpcEEPROMEmulation::get_block(
85 unsigned sector, unsigned offset)
86{
87 return (uint32_t*)(&__eeprom_start + sector * EEPROMEmulation::SECTOR_SIZE + offset * EEPROMEmulation::BLOCK_SIZE);
88}
89
96const uint32_t* LpcEEPROMEmulation::block(unsigned sector, unsigned offset) {
97 return get_block(sector, offset);
98}
99
104{
105 HASSERT(sector < sectorCount_);
106
107 unsigned s = sector + firstSector_;
108 portENTER_CRITICAL();
109 Chip_IAP_PreSectorForReadWrite(s, s);
110 Chip_IAP_EraseSector(s, s);
111 portEXIT_CRITICAL();
112}
113
123 unsigned relative_sector, unsigned start_block, uint32_t *data, uint32_t byte_count)
124{
125 HASSERT(relative_sector < sectorCount_);
126 HASSERT((byte_count % BLOCK_SIZE) == 0);
127 HASSERT(start_block + (byte_count / BLOCK_SIZE) <= rawBlockCount_);
128 auto* address = get_block(relative_sector, start_block);
129
130 /* make sure we have the correct frequency */
131 SystemCoreClockUpdate();
132
133 uint32_t start_address = (uintptr_t)address & ~(WRITE_SIZE - 1);
134 uint32_t sector = firstSector_ + relative_sector;
135
136 HASSERT(((uintptr_t)address + byte_count) <= (start_address + WRITE_SIZE));
137
138 memset(scratch, 0xFF, sizeof(scratch));
139 memcpy(scratch + ((uintptr_t)address - start_address), data, byte_count);
140
141 portENTER_CRITICAL();
142 Chip_IAP_PreSectorForReadWrite(sector, sector);
143 Chip_IAP_CopyRamToFlash(start_address, (uint32_t*)scratch, WRITE_SIZE);
144 portEXIT_CRITICAL();
145}
const char __eeprom_end
Linker-defined symbol where in the memory space (flash) the eeprom emulation data ends.
const char __eeprom_start
Linker-defined symbol where in the memory space (flash) the eeprom emulation data starts.
Emulates EEPROM in FLASH for the Tiva, LPC17xx and LPC40xx platforms.
static const size_t BLOCK_SIZE
block size in bytes
const uint16_t rawBlockCount_
How many blocks are there in a sector.
static const size_t SECTOR_SIZE
Sector size in bytes.
void mount()
Mount the EEPROM file.
static const size_t BYTES_PER_BLOCK
useful data bytes size in bytes
const uint8_t sectorCount_
Total number of sectors available.
LpcEEPROMEmulation()
Default constructor.
static constexpr unsigned WRITE_SIZE
write size in bytes, must be used as an array size
void flash_erase(unsigned sector) override
Simple hardware abstraction for FLASH erase API.
const uint32_t * block(unsigned sector, unsigned offset) override
Computes the pointer to load the data stored in a specific block from.
const uint8_t firstSector_
Stores the IAP sector code for the first sector starting at __eeprom_start.
uint8_t scratch[WRITE_SIZE]
scratchpad for performing write operations
void flash_program(unsigned sector, unsigned start_block, uint32_t *data, uint32_t byte_count) override
Simple hardware abstraction for FLASH program API.
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Definition macros.h:138
#define DIE(MSG)
Unconditionally terminates the current process with a message.
Definition macros.h:143