rcbench
Servo and ESC test bench: panel, IOmcu and shared C
Loading...
Searching...
No Matches
out_store_map.c File Reference

Where the next copy of the output binding goes. More...

#include "out_store_map.h"
#include <stddef.h>

Functions

static bool usable (const out_store_rec_t *recs, uint8_t sectors, uint8_t per_sector)
 A geometry this file can index: slots are addressed by uint8_t, and the caller's plan carries them as one.
static bool sector_erased (const out_store_rec_t *recs, uint8_t sector, uint8_t per_sector)
 Whether every slot of one sector is erased.
int out_store_map_newest (const out_store_rec_t *recs, uint8_t sectors, uint8_t per_sector)
 The live record: the valid one with the highest sequence number.
bool out_store_map_write (const out_store_rec_t *recs, uint8_t sectors, uint8_t per_sector, out_store_write_t *out)
 Plan the next save.
bool out_store_map_write_keep (const out_store_rec_t *recs, uint8_t sectors, uint8_t per_sector, int keep, out_store_write_t *out)
 The same, with sector keep never erased while no record is valid: it holds the live record of the layout before this one (a one-page slot of version 7 or older, out_store_rec.h), which the store reads until its first record of the new layout is written.
int out_store_map_stale (const out_store_rec_t *recs, uint8_t sectors, uint8_t per_sector)
 A sector worth erasing now, ahead of the save that would have to wait for it, or -1 when there is none.
int out_store_map_stale_keep (const out_store_rec_t *recs, uint8_t sectors, uint8_t per_sector, int keep)
 The same, never offering sector keep while no record is valid (see out_store_map_write_keep()).
bool out_store_intact (uint32_t zeros, uint32_t zeros_inv, uint32_t counted)
 Whether a record was written whole and has stayed as it was written.

Detailed Description

Where the next copy of the output binding goes.

See out_store_map.h.

SPDX-License-Identifier: MIT

Function Documentation

◆ out_store_intact()

bool out_store_intact ( uint32_t zeros,
uint32_t zeros_inv,
uint32_t counted )

Whether a record was written whole and has stayed as it was written.

zeros is the number of 0 bits the record held when it was written, zeros_inv is ~zeros, and counted is the number of 0 bits it holds now. The pair says the count itself is untouched; the count says the rest of the record is.

A flash erase only sets bits and a program only clears them, so either one interrupted leaves a record with fewer 0 bits than it was written with. Neither can fake the pair: a bit set in zeros would have to be paid for by a bit cleared in zeros_inv, and a bit cleared by one set, and no single flash operation does both.

This is a stronger check than the record's checksum, and it answers a different question. The checksum says the bytes are the ones that were meant; this says the write that put them there finished.

Parameters
zerosNumber of 0 bits when the record was written.
zeros_invComplement of zeros, as written beside it.
countedNumber of 0 bits the record holds now.
Returns
true when zeros_inv is the complement of zeros and counted equals zeros, false otherwise.

◆ out_store_map_newest()

int out_store_map_newest ( const out_store_rec_t * recs,
uint8_t sectors,
uint8_t per_sector )

The live record: the valid one with the highest sequence number.

-1 when none of them is valid, which is a store that has never been written, one written by a build with a different record in it, and one whose only records are torn. The caller keeps its defaults for all three.

The comparison is a plain unsigned one rather than a wrap-safe difference. The sequence starts at 1 and counts saves; a sector pair of 32 slots at 100,000 erase cycles a sector accepts about 3.2 million saves before the part wears out, and a uint32_t counts to 4,294,967,295.

Parameters
recsThe record slots, sectors * per_sector of them.
sectorsNumber of sectors.
per_sectorRecord slots per sector.
Returns
Index of the live slot, 0 to sectors * per_sector - 1. -1 when no slot is valid, or when the geometry is not usable: recs is NULL, a count is 0, or the total is above 255.

◆ out_store_map_stale()

int out_store_map_stale ( const out_store_rec_t * recs,
uint8_t sectors,
uint8_t per_sector )

A sector worth erasing now, ahead of the save that would have to wait for it, or -1 when there is none.

A sector qualifies when it does not hold the live record and is not already erased. Erasing it costs the same window as erasing it later; the point of taking it early is that the caller chooses the moment, and that the save which finds the sector ready costs a page program alone.

Parameters
recsThe record slots, sectors * per_sector of them.
sectorsNumber of sectors.
per_sectorRecord slots per sector.
Returns
Index of the sector to erase, 0 to sectors - 1. -1 when no sector qualifies, or when the geometry is not usable (see out_store_map_newest()).

◆ out_store_map_stale_keep()

int out_store_map_stale_keep ( const out_store_rec_t * recs,
uint8_t sectors,
uint8_t per_sector,
int keep )

The same, never offering sector keep while no record is valid (see out_store_map_write_keep()).

Parameters
recsThe record slots, sectors * per_sector of them.
sectorsNumber of sectors.
per_sectorRecord slots per sector.
keepSector never offered while no record is valid, or -1 for none.
Returns
Index of the sector to erase, or -1 as out_store_map_stale() gives.

◆ out_store_map_write()

bool out_store_map_write ( const out_store_rec_t * recs,
uint8_t sectors,
uint8_t per_sector,
out_store_write_t * out )

Plan the next save.

The slot after the live record, while its sector has an erased slot left; then the first sector that is already erased; then the next sector, which has to be erased first. A slot that is neither erased nor valid is a torn write and is skipped rather than programmed over: bits only clear, so a second record written into a used slot is the two of them anded together.

False when out is NULL or the geometry is empty; the store is otherwise always placeable, because a full store erases a sector to make room.

Parameters
recsThe record slots, sectors * per_sector of them.
sectorsNumber of sectors.
per_sectorRecord slots per sector.
outReceives the plan: the slot to program, its sequence number and the sector to erase first, if any. Not changed when false is returned.
Returns
true when the plan is in out. false when out is NULL or the geometry is not usable (recs NULL, a count of 0, or a total above 255).

◆ out_store_map_write_keep()

bool out_store_map_write_keep ( const out_store_rec_t * recs,
uint8_t sectors,
uint8_t per_sector,
int keep,
out_store_write_t * out )

The same, with sector keep never erased while no record is valid: it holds the live record of the layout before this one (a one-page slot of version 7 or older, out_store_rec.h), which the store reads until its first record of the new layout is written.

The first other sector is erased instead. -1 keeps none, as out_store_map_write().

Parameters
recsThe record slots, sectors * per_sector of them.
sectorsNumber of sectors.
per_sectorRecord slots per sector.
keepSector to keep while no record is valid, or -1 to keep none. With no valid record and no erased slot, the erase goes to sector 1 when keep is 0 and sectors is above 1, and to sector 0 otherwise.
outReceives the plan. Not changed when the call returns false.
Returns
true when the plan is in out, false when out is NULL or the geometry is not usable (see out_store_map_write()).

◆ sector_erased()

bool sector_erased ( const out_store_rec_t * recs,
uint8_t sector,
uint8_t per_sector )
static

Whether every slot of one sector is erased.

Parameters
recsThe record slots of the whole store.
sectorSector index.
per_sectorRecord slots per sector.
Returns
true when all per_sector slots of sector are erased, false when any of them is not.

◆ usable()

bool usable ( const out_store_rec_t * recs,
uint8_t sectors,
uint8_t per_sector )
static

A geometry this file can index: slots are addressed by uint8_t, and the caller's plan carries them as one.

Parameters
recsThe record slots, not NULL when usable.
sectorsNumber of sectors, above 0 when usable.
per_sectorRecord slots per sector, above 0 when usable.
Returns
true when recs is not NULL, both counts are above 0 and the total is at most 255, false otherwise.