mirror of
https://github.com/ole00/afterburner.git
synced 2025-01-15 08:29:45 +00:00
sparse fusemap: added support for compacting
Compacting searches for fuse blocks where all 32 bits are set to 1. If such block is found then it is removed from the fuse array (reducing its top position) and then the fuse type of such block is changed to 3. Note that the fuse bit is never changed from 1 to 0, therefore there is no need to cover these cases in the code (ie. converting block type 3 to block type 1). Compacting happens after every 256 fuse writes. Compacting is required to be able to read erased GALs where all fuse bits are initialised to 1.
This commit is contained in:
parent
f3147397f9
commit
ba3caf3a15
107
aftb_sparse.h
107
aftb_sparse.h
@ -17,15 +17,59 @@
|
|||||||
|
|
||||||
#ifdef USE_SPARSE_FUSEMAP
|
#ifdef USE_SPARSE_FUSEMAP
|
||||||
|
|
||||||
|
// compacting statistics - disabled by default
|
||||||
|
#define COMPACT_STAT 0
|
||||||
|
|
||||||
#define SPFUSES 128
|
#define SPFUSES 128
|
||||||
unsigned char fuseType[SPFUSES]; //sparse fuses index
|
unsigned char fuseType[SPFUSES]; //sparse fuses index
|
||||||
|
|
||||||
uint16_t sparseFusemapStat = 0; //bit 15: use sparse fusemaps, bits 0-11 : sparse fusemap size in bytes
|
uint16_t sparseFusemapStat = 0; //bit 15: use sparse fusemaps, bits 0-11 : sparse fusemap size in bytes
|
||||||
|
uint8_t sparseCompactCounter = 0;
|
||||||
uint16_t sparseCacheBitPos = 0;
|
uint16_t sparseCacheBitPos = 0;
|
||||||
uint16_t sparseCacheOffset = 0;
|
uint16_t sparseCacheOffset = 0;
|
||||||
uint16_t sparseCacheHit = 0;
|
uint16_t sparseCacheHit = 0;
|
||||||
uint8_t sparseCacheIndex = 0;
|
uint8_t sparseCacheIndex = 0;
|
||||||
|
|
||||||
|
#if COMPACT_STAT
|
||||||
|
uint8_t sparseCompactRun = 0;
|
||||||
|
uint8_t sparseCompactAct = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// reverse search of the fuse group index based on the byte position in the sparse array
|
||||||
|
// returns the group index
|
||||||
|
static uint16_t getFuseGroupIndex(uint16_t fuseOffsetBytePos) {
|
||||||
|
uint16_t groupPos = 0;
|
||||||
|
uint16_t i = 0;
|
||||||
|
uint16_t fuseOffset = 0;
|
||||||
|
|
||||||
|
//calculate fusemap offset
|
||||||
|
while (1) {
|
||||||
|
uint8_t rec = fuseType[i];
|
||||||
|
// speed optimised special case: all 8 bits are 0 (4 * 32 bits)
|
||||||
|
if (rec == 0) {
|
||||||
|
groupPos += 4; //4 groups in the byte
|
||||||
|
} else {
|
||||||
|
uint8_t j = 0;
|
||||||
|
//4 types per byte
|
||||||
|
while (j < 4) {
|
||||||
|
if ((rec & 0b11) == 1) { // type 0 & 3 - no byte stored in fusemap
|
||||||
|
if (fuseOffset == fuseOffsetBytePos) {
|
||||||
|
return groupPos;
|
||||||
|
}
|
||||||
|
fuseOffset += 4; // 32 bits in the group, fuse byte offset advances by 4 bytes
|
||||||
|
}
|
||||||
|
groupPos++; //check next group
|
||||||
|
rec >>= 2;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++; //next byte from the fuseTypes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// get position of the fuse bit in the sparse array
|
||||||
static uint16_t getFusePositionAndType(uint16_t bitPos) {
|
static uint16_t getFusePositionAndType(uint16_t bitPos) {
|
||||||
uint16_t counter = 0;
|
uint16_t counter = 0;
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
@ -94,9 +138,57 @@ static void insertFuseGroup(uint16_t dataPos, uint16_t bitPos) {
|
|||||||
fusemap[dataPos] = 0;
|
fusemap[dataPos] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void sparseCompactFuseMap(void) {
|
||||||
|
uint16_t i, j;
|
||||||
|
uint16_t total = (sparseFusemapStat & 0x7FF) >> 2; // max is 2048 bytes, and convert to the group index
|
||||||
|
uint32_t* fuses = (uint32_t*) fusemap;
|
||||||
|
|
||||||
|
if (total < 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if COMPACT_STAT
|
||||||
|
sparseCompactRun++; //statistics
|
||||||
|
#endif
|
||||||
|
|
||||||
|
i = total - 1;
|
||||||
|
while(i) {
|
||||||
|
// remove 4 fusemap bytes at a position when the bits are all 1's
|
||||||
|
if (fuses[i] == 0xFFFFFFFF) {
|
||||||
|
if (i < total - 1) {
|
||||||
|
uint16_t fuseGroup = getFuseGroupIndex(i << 2); //ensure the int32 index is converted to int8/byte index
|
||||||
|
#if COMPACT_STAT
|
||||||
|
sparseCompactAct++; //statistics
|
||||||
|
#endif
|
||||||
|
/// shift the fuses by 4 bytes to the left
|
||||||
|
for (j = i; j < total - 1 ; j++) {
|
||||||
|
fuses[j] = fuses[j + 1];
|
||||||
|
}
|
||||||
|
total--;
|
||||||
|
fuseType[fuseGroup >> 2] |= (3 << ((fuseGroup & 0b11) << 1)); //set type 3 at the fuse group record
|
||||||
|
sparseFusemapStat -= 4; // fuse map total size reduced by 4 bytes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
//destory cache
|
||||||
|
sparseCacheBitPos = 0;
|
||||||
|
sparseCacheOffset = 0;
|
||||||
|
sparseCacheIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline uint16_t sparseSetFuseBit(uint16_t bitPos) {
|
static inline uint16_t sparseSetFuseBit(uint16_t bitPos) {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint16_t pos = getFusePositionAndType(bitPos);
|
uint16_t pos;
|
||||||
|
|
||||||
|
//try to reduce the size of the fuse map by finding and removing blocks with all 1's
|
||||||
|
sparseCompactCounter ++;
|
||||||
|
if (sparseCompactCounter == 255) {
|
||||||
|
sparseCompactFuseMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = getFusePositionAndType(bitPos);
|
||||||
type = pos & 0b11;
|
type = pos & 0b11;
|
||||||
pos >>= 2; //trim the type to get the byte position in fuse map
|
pos >>= 2; //trim the type to get the byte position in fuse map
|
||||||
if (type == 0) { //we need to write the bit into a group that has all bits 0 so far
|
if (type == 0) { //we need to write the bit into a group that has all bits 0 so far
|
||||||
@ -123,8 +215,14 @@ static inline uint16_t sparseGetFuseBit(uint16_t bitPos) {
|
|||||||
static void sparsePrintStat() {
|
static void sparsePrintStat() {
|
||||||
Serial.print(F("sp bytes="));
|
Serial.print(F("sp bytes="));
|
||||||
Serial.println(sparseFusemapStat & 0x7FF, DEC);
|
Serial.println(sparseFusemapStat & 0x7FF, DEC);
|
||||||
Serial.print("chit=");
|
Serial.print(F("c_hit="));
|
||||||
Serial.println(sparseCacheHit, DEC);
|
Serial.println(sparseCacheHit, DEC);
|
||||||
|
#if COMPACT_STAT
|
||||||
|
Serial.print(F("compact run="));
|
||||||
|
Serial.print(sparseCompactRun, DEC);
|
||||||
|
Serial.print(F(" cnt="));
|
||||||
|
Serial.println(sparseCompactAct, DEC);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sparseInit(char clearArray) {
|
static void sparseInit(char clearArray) {
|
||||||
@ -136,9 +234,14 @@ static void sparseInit(char clearArray) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
sparseFusemapStat = (1 << 15);
|
sparseFusemapStat = (1 << 15);
|
||||||
|
sparseCompactCounter = 0;
|
||||||
sparseCacheBitPos = 0;
|
sparseCacheBitPos = 0;
|
||||||
sparseCacheOffset = 0;
|
sparseCacheOffset = 0;
|
||||||
sparseCacheIndex = 0;
|
sparseCacheIndex = 0;
|
||||||
|
#if COMPACT_STAT
|
||||||
|
sparseCompactRun = 0;
|
||||||
|
sparseCompactAct = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static inline void sparseDisable(void) {
|
static inline void sparseDisable(void) {
|
||||||
sparseFusemapStat = 0;
|
sparseFusemapStat = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user