mirror of
https://github.com/ole00/afterburner.git
synced 2024-11-26 03:49:18 +00:00
sparse fusemap: use 32 bit fuse blocks
Previously 16 bit fuse blocks were used and block types were stored in 1 bit. That did not allow to compact fusemaps where all bits were 1 - which is typically after the fuses are erased. So fuses of an erased chip would not fit into the sparse memory array. The solution was to extend the fuse block type storage from 1 bit to 2 bits and use that extra space to mark blocks as sparse when all bits in the block are 1's. Such block is now block type 3. To keep the fuseType array the same size as it was (128 bytes) the size of the block was extended from 16 bits to 32 bits. The block type is now: 0 - all bits in the fuse block are 0, no block data in the fuse array 3 - all bits in the fuse block are 1, no block data in the fuse array 1 - any combination of bits in the fuse block, data are stored in the fuse array 2 - reserved for future use.
This commit is contained in:
parent
77a5d7d236
commit
f3147397f9
@ -30,7 +30,7 @@ static uint16_t getFusePositionAndType(uint16_t bitPos) {
|
||||
uint16_t counter = 0;
|
||||
uint8_t i = 0;
|
||||
uint8_t type;
|
||||
uint16_t fuseOffset = (bitPos & 0b1000) ? 1 : 0; //set odd / even byte of the fuse offset
|
||||
uint16_t fuseOffset = (bitPos & 0b11000) >> 3; //set odd / even byte of the fuse offset
|
||||
|
||||
if (bitPos <= sparseCacheBitPos) {
|
||||
sparseCacheBitPos = 0;
|
||||
@ -38,7 +38,7 @@ static uint16_t getFusePositionAndType(uint16_t bitPos) {
|
||||
sparseCacheIndex = 0;
|
||||
} else {
|
||||
counter = sparseCacheBitPos;
|
||||
fuseOffset += sparseCacheOffset & 0xFFE;
|
||||
fuseOffset += sparseCacheOffset & 0xFFC;
|
||||
i = sparseCacheIndex;
|
||||
sparseCacheHit++;
|
||||
}
|
||||
@ -46,28 +46,28 @@ static uint16_t getFusePositionAndType(uint16_t bitPos) {
|
||||
//calculate fusemap offset
|
||||
while (1) {
|
||||
uint8_t rec = fuseType[i];
|
||||
// speed optimised special case: all 8 bits are 0
|
||||
// speed optimised special case: all 8 bits are 0 (4 * 32 bits)
|
||||
if (rec == 0) {
|
||||
counter += 128;
|
||||
if (counter > bitPos) {
|
||||
return (fuseOffset << 1); // type is 0
|
||||
return (fuseOffset << 2); // type is 0
|
||||
}
|
||||
sparseCacheBitPos = counter;
|
||||
sparseCacheOffset = fuseOffset;
|
||||
sparseCacheIndex = i + 1;
|
||||
} else {
|
||||
uint8_t j = 0;
|
||||
//8 fuse types per byte
|
||||
while (j < 8) {
|
||||
counter += 16;
|
||||
type = rec & 1;
|
||||
//4 fuse types per byte
|
||||
while (j < 4) {
|
||||
counter += 32;
|
||||
type = rec & 0b11;
|
||||
if (counter > bitPos) {
|
||||
return (fuseOffset << 1) | type;
|
||||
return (fuseOffset << 2) | type;
|
||||
}
|
||||
if (type) {
|
||||
fuseOffset += 2;
|
||||
if (type == 1) { // type 0 & 3 - no byte stored in fusemap
|
||||
fuseOffset += 4;
|
||||
}
|
||||
rec >>= 1;
|
||||
rec >>= 2;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
@ -76,39 +76,47 @@ static uint16_t getFusePositionAndType(uint16_t bitPos) {
|
||||
}
|
||||
|
||||
static void insertFuseGroup(uint16_t dataPos, uint16_t bitPos) {
|
||||
int16_t i = bitPos >> 4; //group index
|
||||
int16_t i = bitPos >> 5; //group index
|
||||
uint16_t totalFuseBytes = sparseFusemapStat & 0x7FF; // max is 2048 bytes
|
||||
fuseType[i >> 3] |= (1 << (i & 7)); // set type 1 at the fuse group record
|
||||
fuseType[i >> 2] |= (1 << ((i & 0b11) << 1)); // set type 1 at the fuse group record
|
||||
|
||||
//shift all data in the fuse map starting at data pos by 2 bytes (16 bits)
|
||||
//shift all data in the fuse map starting at data pos by 4 bytes (32 bits)
|
||||
if (dataPos < totalFuseBytes) {
|
||||
for (i = totalFuseBytes - 1; i >= dataPos; i--) {
|
||||
fusemap[i + 2] = fusemap[i];
|
||||
fusemap[i + 4] = fusemap[i];
|
||||
}
|
||||
}
|
||||
sparseFusemapStat = totalFuseBytes + 2; // we can ignore the sparse bit
|
||||
sparseFusemapStat = totalFuseBytes + 4; // we can ignore the sparse bit
|
||||
//clean the emptied fusemap data
|
||||
fusemap[dataPos++] = 0;
|
||||
fusemap[dataPos++] = 0;
|
||||
fusemap[dataPos++] = 0;
|
||||
fusemap[dataPos] = 0;
|
||||
}
|
||||
|
||||
static inline uint16_t sparseSetFuseBit(uint16_t bitPos) {
|
||||
uint8_t type;
|
||||
uint16_t pos = getFusePositionAndType(bitPos);
|
||||
type = pos & 1;
|
||||
pos >>= 1; //trim the type to get the byte position in fuse map
|
||||
type = pos & 0b11;
|
||||
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
|
||||
insertFuseGroup(pos & 0x7FE, bitPos);
|
||||
insertFuseGroup(pos & 0x7FC, bitPos);
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
static inline uint16_t sparseGetFuseBit(uint16_t bitPos) {
|
||||
uint8_t type;
|
||||
uint16_t pos = getFusePositionAndType(bitPos);
|
||||
if (!(pos & 1)) { //type is 0 - the block contains all zero bits
|
||||
return 0;
|
||||
|
||||
type = pos & 0b11;
|
||||
if (!type) { //type is 0 - the block contains all zero bits
|
||||
return 0xFF00;
|
||||
}
|
||||
pos >>= 1; //trim the type to get byte position in fuse map
|
||||
if (type == 3) { // type is 3 - the block contains all 1 bits
|
||||
return 0xFF01;
|
||||
}
|
||||
pos >>= 2; //trim the type to get byte position in fuse map
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
@ -1535,6 +1535,9 @@ static char getFuseBit(unsigned short bitPos) {
|
||||
uint16_t pos;
|
||||
if (sparseFusemapStat) {
|
||||
pos = sparseGetFuseBit(bitPos);
|
||||
if (pos >= 0xFF00) {
|
||||
return pos & 0x1;
|
||||
}
|
||||
} else {
|
||||
pos = bitPos >> 3;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user