Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
EEPROMEmulation Class Referenceabstract

Emulates EEPROM in FLASH for the Tiva, LPC17xx and LPC40xx platforms. More...

#include <EEPROMEmulation.hxx>

Inheritance diagram for EEPROMEmulation:
EEPROM Node Device FileIO LpcEEPROMEmulation MyEEPROM Stm32EEPROMEmulation TivaEEPROMEmulation

Protected Types

enum  MagicBlockIndex {
  MAGIC_FIRST_INDEX = 0 , MAGIC_DIRTY_INDEX = 0 , MAGIC_INTACT_INDEX , MAGIC_USED_INDEX ,
  MAGIC_COUNT
}
 Raw block indexes within a sector to mark the state of the sector. More...
 

Protected Member Functions

 EEPROMEmulation (const char *name, size_t file_size)
 Constructor.
 
 ~EEPROMEmulation ()
 Destructor.
 
void mount ()
 Mount the EEPROM file.
 
 EEPROMEmulation ()
 Default constructor.
 
 DISALLOW_COPY_AND_ASSIGN (EEPROMEmulation)
 
- Protected Member Functions inherited from EEPROM
 EEPROM (const char *name, size_t file_size)
 Constructor.
 
 ~EEPROM ()
 Destructor.
 
size_t file_size ()
 Get the maximum file size of the EEPROM file.
 
- Protected Member Functions inherited from Node
 Node (const char *name)
 Constructor.
 
virtual ~Node ()
 Destructor.
 
int open (File *, const char *, int, int) OVERRIDE
 Open method.
 
int close (File *) OVERRIDE
 Close method.
 
virtual int fstat (File *file, struct stat *stat) override
 Get the status information of a file or device.
 
- Protected Member Functions inherited from FileIO
 FileIO (const char *name)
 Constructor.
 
virtual ~FileIO ()
 Destructor.
 
virtual int ioctl (File *file, unsigned long int key, unsigned long data)
 Request an ioctl transaction.
 
virtual int fcntl (File *file, int cmd, unsigned long data)
 Manipulate a file descriptor.
 
virtual bool select (File *file, int mode)
 Device select method.
 

Protected Attributes

const uint8_t sectorCount_ {(uint8_t)(EEPROMEMU_FLASH_SIZE / SECTOR_SIZE)}
 Total number of sectors available.
 
uint8_t activeSector_ {0}
 Index of the active sector.
 
const uint16_t rawBlockCount_ {(uint16_t)(SECTOR_SIZE / BLOCK_SIZE)}
 How many blocks are there in a sector.
 
size_t availableSlots_ {0}
 Number of available (writable) slots for new data in the active sector.
 
bool shadowInRam_ {false}
 local copy of SHADOW_IN_RAM which we can manipulate at run time.
 
uint8_t * shadow_ {nullptr}
 pointer to RAM for shadowing EEPROM.
 
- Protected Attributes inherited from Node
OSMutex lock_
 protects internal structures.
 
mode_t mode_
 File open mode, such as O_NONBLOCK.
 
unsigned int references_
 number of open references
 
- Protected Attributes inherited from FileIO
const char * name
 device name
 

Static Protected Attributes

static const size_t SECTOR_SIZE = (4 * 1024)
 Sector size in bytes.
 
static const size_t BLOCK_SIZE = 16
 block size in bytes
 
static constexpr unsigned MAX_BLOCK_SIZE = 16
 Maximum byte size of a single block.
 
static const uint32_t MAGIC_INTACT = 0xaa558001
 magic marker for an intact block
 
static const uint32_t MAGIC_DIRTY = 0xaa55aa55
 magic marker for a block that we are transitioning to intact
 
static const uint32_t MAGIC_USED = 0x00000000
 magic marker for a used block
 
static const uint32_t MAGIC_ERASED = 0xFFFFFFFF
 magic marker for an erased block
 
- Static Protected Attributes inherited from FileIO
static const unsigned int numOpenFiles = 20
 
static File files []
 File descriptor pool.
 
static OSMutex mutex
 mutual exclusion for fileio
 

Private Member Functions

void updated_notification ()
 This function will be called after every write.
 
void write (unsigned int offset, const void *buf, size_t len) OVERRIDE
 Write to the EEPROM.
 
void read (unsigned int offset, void *buf, size_t len) OVERRIDE
 Read from the EEPROM.
 
void write_fblock (unsigned int index, const uint8_t data[])
 Write to the EEPROM on a native block boundary.
 
bool read_fblock (unsigned int index, uint8_t data[])
 Read from the EEPROM on a native block boundary.
 
unsigned next_active ()
 Get the next active sector pointer.
 
unsigned sector_count ()
 Total number of FLASH sectors being used for emulation.
 
unsigned slot_count ()
 Total number of EEPROM slots in a FLASH sector.
 
unsigned slot_last ()
 
unsigned slot_first ()
 
virtual const uint32_t * block (unsigned sector, unsigned offset)=0
 Computes the pointer to load the data stored in a specific block from.
 
virtual void flash_erase (unsigned sector)=0
 Simple hardware abstraction for FLASH erase API.
 
virtual void flash_program (unsigned sector, unsigned start_block, uint32_t *data, uint32_t byte_count)=0
 Simple hardware abstraction for FLASH program API.
 

Static Private Attributes

static const size_t BYTES_PER_BLOCK = 8
 useful data bytes size in bytes
 
static const size_t HEADER_BLOCK_COUNT = 3
 number of reserved header blocks
 
static const bool SHADOW_IN_RAM = false
 Shadow the EEPROM data in RAM.
 

Additional Inherited Members

- Public Member Functions inherited from EEPROM
 EEPROM (const char *name, size_t file_size)
 Constructor.
 
size_t file_size ()
 
- Public Member Functions inherited from Device
 Device (const char *name)
 Constructor.
 
virtual ~Device ()
 Destructor.
 
- Static Public Member Functions inherited from Device
static int open (struct _reent *reent, const char *path, int flags, int mode)
 Open a file or device.
 
static int close (struct _reent *reent, int fd)
 Close a file or device.
 
static int stat (struct _reent *reent, const char *path, struct stat *stat)
 Get the status information of a file or device.
 
static int select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, long long timeout)
 POSIX select().
 
static void select_clear ()
 Clears the current thread's select bits.
 
- Static Public Member Functions inherited from FileIO
static ssize_t read (struct _reent *reent, int fd, void *buf, size_t count)
 Read from a file or device.
 
static ssize_t write (struct _reent *reent, int fd, const void *buf, size_t count)
 Write to a file or device.
 
static _off_t lseek (struct _reent *reent, int fd, _off_t offset, int whence)
 Change the offset index of a file or device.
 
static int fstat (struct _reent *reent, int fd, struct stat *stat)
 Get the status information of a file or device.
 
static int ioctl (int fd, unsigned long int key, unsigned long data)
 Request and ioctl transaction.
 
static int fcntl (int fd, int cmd, unsigned long data)
 Manipulate a file descriptor.
 
static bool is_device (int fd)
 Test if the file descriptor belongs to a device.
 
- Static Protected Member Functions inherited from Device
static void select_insert (SelectInfo *info)
 Add client to list of clients needing woken.
 
static void select_wakeup (SelectInfo *info)
 Wakeup the list of clients needing woken.
 
static void select_wakeup_from_isr (SelectInfo *info, int *woken)
 Wakeup the list of clients needing woken.
 
- Static Protected Member Functions inherited from FileIO
static int fd_alloc (void)
 Allocate a free file descriptor.
 
static void fd_free (int fd)
 Free up a file descriptor.
 
static Filefile_lookup (int fd)
 Looks up a reference to a File corresponding to a given file descriptor.
 
static int fd_lookup (File *file)
 Looks up a file descriptor corresponding to a given File reference.
 

Detailed Description

Emulates EEPROM in FLASH for the Tiva, LPC17xx and LPC40xx platforms.

Applicable in general to any microcontroller with self-writeable flash.

Theory of operation:

The EEPROM area is an area of the MCU Flash reserved for the EEPROMEmulation driver. This area must fall onto flash erase boundaries. The driver will perform a journal of every write into this flash area by writing (offset, data) pairs in append mode. Reads will scan through the journal to find the desired data. When the journal gets full, the data is copied to a second flash area, compacting data by keeping overwrites only once, and then the original area is erased.

Specifics and parameters:

The flash area is specified by the linker symbols __eeprom_start and __eeprom_end. It is the responsibility of the memory map linker script to align these at flash erase boundaries. Inside this area there are independently eraseable sectors. The requirement is that at least two independently eraseable sectors be present, in order to allow copying data from one sector to another without endangering data loss due to power interruption.

The layout of each sector is the following: the sector is split into blocks, where each block can be independently written. Each block will be written only once between two erase operations. The first few blocks are reserved for tracking the state of the sector, the rest of the blocks are used as slots holding data payload. The sectors go through the following states (in order): 1) erased. When the sector is all 0xFF. 2) dirty. The data is being copied over into this sector. 3) intact. This sector contains all the data. 4) used. This sector contains old data and can be reused after erasing.

The layout of a slot is very simple: the first two bytes hold the address. The lower two bytes of each 4-byte hold the data payload.

Parameters:

Parameters
SECTOR_SIZEsize of independently erased flash areas. Usually in the range of kilobytes; for example somewhere between 1-16 kbytes.
EEPROMEMU_FLASH_SIZEAutomatically detected from the linker symbols. An integer (at least 2) multiple of SECTOR_SIZE. Sectors within the designatedflash are will be used in a round-robin manner to maximize flash endurance.
BLOCK_SIZEDefines how many bytes shall be flashed in one operation. Usually a small integer, at least 4, defined by the hardware limitations of the MCU flash (for example on the NXP 17xx it is 16 bytes, because programming less than 16 bytes in one go is not supported).
BYTES_PER_BLOCKhow many bytes of actual data should be stored in a block. Must be <= BLOCK_SIZE - 2 (in order to leave space for the address in the block). Must be a power of two.
SHADOW_IN_RAMa boolean, if set to true, a shadow_ memory are will be allocated in RAM that will be pre-filled with the entire eeprom data. Dramatically speeds up reads, because reads will not have to go through the log anymore.
file_sizeThe total number of bytes held by the emulated eeprom file. Reads from address 0 .. file_size - 1 will be valid. Must be smaller than half of one sector, but should be realistically about 35% of the sector size to avoid too frequent sector erasing.

Limitations:

At any point in time there is only one active sector. This means that all useful data has to fit in one sector. This limits the max number of bytes to be sector_size / 2. To work around this is makes sense to set the eepromemu sector size to be a multiple of what the microcontroller can erase in one go, and writing the flash_erase in a way that just erases all flash sectors that fall into the chosen eepromemu sector.

Since there is only one active sector, it makes fairly little sense to have more than two sectors in total. One spare sector is needed for copying data over in a power-failure-safe manner. More than two sectors will not extend the size of available eepromemu space, just round-robin with using the flash sectors, thereby extending flash lifetime – which already should not be a problem on modern MCUs.

The efficiency is not great: only 25% of the allocated flash space can be used for data storage. Users should leave some additional buffer to avoid too frequent overflowing of sectors.

The file size is limited to 64k - BLOCK_SIZE because the address is stored on 2 bytes in each block.

Definition at line 130 of file EEPROMEmulation.hxx.

Member Enumeration Documentation

◆ MagicBlockIndex

Raw block indexes within a sector to mark the state of the sector.

Enumerator
MAGIC_FIRST_INDEX 

first metadata block index

MAGIC_DIRTY_INDEX 

dirty metadata block index: programmed when we start writing to the sector (i.e.

it is not erased).

MAGIC_INTACT_INDEX 

intact metadata block index: programmed when the data in this sector is authoritative.

MAGIC_USED_INDEX 

used metadata block index: programmed when the data has been copied to a new sector.

MAGIC_COUNT 

total metadata block count

Definition at line 216 of file EEPROMEmulation.hxx.

Constructor & Destructor Documentation

◆ EEPROMEmulation()

EEPROMEmulation::EEPROMEmulation ( const char *  name,
size_t  file_size 
)
protected

Constructor.

Parameters
namedevice name
file_sizemaximum file size that we can grow to.

Definition at line 49 of file EEPROMEmulation.cxx.

◆ ~EEPROMEmulation()

EEPROMEmulation::~EEPROMEmulation ( )
inlineprotected

Destructor.

Definition at line 141 of file EEPROMEmulation.hxx.

Member Function Documentation

◆ block()

virtual const uint32_t * EEPROMEmulation::block ( unsigned  sector,
unsigned  offset 
)
privatepure virtual

Computes the pointer to load the data stored in a specific block from.

Parameters
sectorsector number [0..sectorCount_ - 1]
offsetblock index within sector, [0..rawBlockCount_ - 1]
Returns
pointer to the beginning of the data in the block. Must be alive until the next call to this function.

Implemented in MyEEPROM, LpcEEPROMEmulation, Stm32EEPROMEmulation, and TivaEEPROMEmulation.

◆ flash_erase()

virtual void EEPROMEmulation::flash_erase ( unsigned  sector)
privatepure virtual

Simple hardware abstraction for FLASH erase API.

Parameters
sectorNumber of sector [0.. sectorCount_ - 1] to erase

Implemented in LpcEEPROMEmulation, Stm32EEPROMEmulation, TivaEEPROMEmulation, and MyEEPROM.

◆ flash_program()

virtual void EEPROMEmulation::flash_program ( unsigned  sector,
unsigned  start_block,
uint32_t *  data,
uint32_t  byte_count 
)
privatepure virtual

Simple hardware abstraction for FLASH program API.

Parameters
sectorthe sector to write to [0..sectorCount_ - 1]
start_blockthe block index to start writing to [0..rawBlockCount_ - 1]
dataa pointer to the data to be programmed
byte_countthe number of bytes to be programmed. Must be a multiple of BLOCK_SIZE

The bytes to program cannot overflow beyond the end of sector, so start_block + byte_count / BLOCK_SIZE <= rawBlockCount_ must hold.

Implemented in MyEEPROM, LpcEEPROMEmulation, Stm32EEPROMEmulation, and TivaEEPROMEmulation.

◆ mount()

void EEPROMEmulation::mount ( )
protected

Mount the EEPROM file.

Should be called during construction of the derived class.

Definition at line 64 of file EEPROMEmulation.cxx.

◆ next_active()

unsigned EEPROMEmulation::next_active ( )
inlineprivate

Get the next active sector pointer.

Returns
sector index for the next sector to use.

Definition at line 246 of file EEPROMEmulation.hxx.

◆ read()

void EEPROMEmulation::read ( unsigned int  offset,
void *  buf,
size_t  len 
)
privatevirtual

Read from the EEPROM.

Parameters
offsetindex within EEPROM address space to start read
buflocation to post read data
lenlength in bytes of data to read
offsetwithin EEPROM address space to start read
buflocation to post read data
lenlength in bytes of data to read

Implements EEPROM.

Definition at line 282 of file EEPROMEmulation.cxx.

◆ read_fblock()

bool EEPROMEmulation::read_fblock ( unsigned int  index,
uint8_t  data[] 
)
private

Read from the EEPROM on a native block boundary.

Parameters
indexblock within EEPROM address space to read
datalocation to place read data, array size must be BYTES_PER_BLOCK large
Returns
true if any of the data is not "erased", else return false
Parameters
indexblock within EEPROM address space to read
datalocation to place read data, array size must be BYTES_PER_BLOCK large
returntrue if any of the data is not "erased", else return false

Definition at line 345 of file EEPROMEmulation.cxx.

◆ sector_count()

unsigned EEPROMEmulation::sector_count ( )
inlineprivate

Total number of FLASH sectors being used for emulation.

Returns
number of FLASH sectors being used for emulation

Definition at line 256 of file EEPROMEmulation.hxx.

◆ slot_count()

unsigned EEPROMEmulation::slot_count ( )
inlineprivate

Total number of EEPROM slots in a FLASH sector.

A slot is a block that contains user data (i.e., excludes any metadata blocks).

Returns
number of EEPROM slots in a FLASH sector.

Definition at line 265 of file EEPROMEmulation.hxx.

◆ slot_first()

unsigned EEPROMEmulation::slot_first ( )
inlineprivate
Returns
raw block index of the first block containing user data.

Definition at line 281 of file EEPROMEmulation.hxx.

◆ slot_last()

unsigned EEPROMEmulation::slot_last ( )
inlineprivate
Returns
raw block index of the last block containing user data.

Definition at line 273 of file EEPROMEmulation.hxx.

◆ updated_notification()

void EEPROMEmulation::updated_notification ( )
private

This function will be called after every write.

The default implementation is a weak symbol with an empty function. It is intended to be overridden in the application to get callbacks for eeprom writes that can trigger a reload.

Definition at line 45 of file EEPROMEmulation_weak.cxx.

◆ write()

void EEPROMEmulation::write ( unsigned int  index,
const void *  buf,
size_t  len 
)
privatevirtual

Write to the EEPROM.

NOTE!!! This is not necessarily atomic across byte boundaries in the case of power loss. The user should take this into account as it relates to data integrity of a whole block.

Parameters
offsetindex within EEPROM address space to start write
bufdata to write
lenlength in bytes of data to write

NOTE!!! This is not necessarily atomic across BLOCK_SIZE boundaries in the case of power loss. The user should take this into account as it relates to data integrity of a whole block.

Parameters
indexwithin EEPROM address space to start write
bufdata to write
lenlength in bytes of data to write

Implements EEPROM.

Definition at line 128 of file EEPROMEmulation.cxx.

◆ write_fblock()

void EEPROMEmulation::write_fblock ( unsigned int  index,
const uint8_t  data[] 
)
private

Write to the EEPROM on a native block boundary.

Parameters
indexblock within EEPROM address space to write
datadata to write, array size must be BYTES_PER_BLOCK large

Definition at line 206 of file EEPROMEmulation.cxx.

Member Data Documentation

◆ activeSector_

uint8_t EEPROMEmulation::activeSector_ {0}
protected

Index of the active sector.

Definition at line 316 of file EEPROMEmulation.hxx.

◆ availableSlots_

size_t EEPROMEmulation::availableSlots_ {0}
protected

Number of available (writable) slots for new data in the active sector.

Definition at line 322 of file EEPROMEmulation.hxx.

◆ BLOCK_SIZE

const size_t EEPROMEmulation::BLOCK_SIZE = 16
staticprotected

block size in bytes

Definition at line 154 of file EEPROMEmulation.hxx.

◆ BYTES_PER_BLOCK

const size_t EEPROMEmulation::BYTES_PER_BLOCK = 8
staticprivate

useful data bytes size in bytes

Todo:
maybe this should be a macro of BLOCK_SIZE / 2

Definition at line 192 of file EEPROMEmulation.hxx.

◆ HEADER_BLOCK_COUNT

const size_t EEPROMEmulation::HEADER_BLOCK_COUNT = 3
staticprivate

number of reserved header blocks

Definition at line 195 of file EEPROMEmulation.hxx.

◆ MAGIC_DIRTY

const uint32_t EEPROMEmulation::MAGIC_DIRTY = 0xaa55aa55
staticprotected

magic marker for a block that we are transitioning to intact

Definition at line 207 of file EEPROMEmulation.hxx.

◆ MAGIC_ERASED

const uint32_t EEPROMEmulation::MAGIC_ERASED = 0xFFFFFFFF
staticprotected

magic marker for an erased block

Definition at line 213 of file EEPROMEmulation.hxx.

◆ MAGIC_INTACT

const uint32_t EEPROMEmulation::MAGIC_INTACT = 0xaa558001
staticprotected

magic marker for an intact block

Definition at line 204 of file EEPROMEmulation.hxx.

◆ MAGIC_USED

const uint32_t EEPROMEmulation::MAGIC_USED = 0x00000000
staticprotected

magic marker for a used block

Definition at line 210 of file EEPROMEmulation.hxx.

◆ MAX_BLOCK_SIZE

constexpr unsigned EEPROMEmulation::MAX_BLOCK_SIZE = 16
staticconstexprprotected

Maximum byte size of a single block.

Definition at line 157 of file EEPROMEmulation.hxx.

◆ rawBlockCount_

const uint16_t EEPROMEmulation::rawBlockCount_ {(uint16_t)(SECTOR_SIZE / BLOCK_SIZE)}
protected

How many blocks are there in a sector.

Definition at line 319 of file EEPROMEmulation.hxx.

◆ SECTOR_SIZE

const size_t EEPROMEmulation::SECTOR_SIZE = (4 * 1024)
staticprotected

Sector size in bytes.

Definition at line 151 of file EEPROMEmulation.hxx.

◆ sectorCount_

const uint8_t EEPROMEmulation::sectorCount_ {(uint8_t)(EEPROMEMU_FLASH_SIZE / SECTOR_SIZE)}
protected

Total number of sectors available.

Definition at line 313 of file EEPROMEmulation.hxx.

◆ shadow_

uint8_t* EEPROMEmulation::shadow_ {nullptr}
protected

pointer to RAM for shadowing EEPROM.

Definition at line 328 of file EEPROMEmulation.hxx.

◆ SHADOW_IN_RAM

const bool EEPROMEmulation::SHADOW_IN_RAM = false
staticprivate

Shadow the EEPROM data in RAM.

This will increase read performance at the expense of additional RAM usage.

Definition at line 200 of file EEPROMEmulation.hxx.

◆ shadowInRam_

bool EEPROMEmulation::shadowInRam_ {false}
protected

local copy of SHADOW_IN_RAM which we can manipulate at run time.

Specifies whether the shadowing is active.

Definition at line 325 of file EEPROMEmulation.hxx.


The documentation for this class was generated from the following files: