erased/programmed many times (there is a 2 page cache, but
random writes are unlikely to hit in it).
- The cache is only flushed on commit.
+ The cache is only flushed on sync.
The first page of a block storage volume stores the maximum address
written in the block and a CRC of the block's contents (up to that
- maximum address). This CRC is written at commit time and verified at
+ maximum address). This CRC is written at sync time and verified at
validate time.
This BlockStorage code is reused in the implementation of
R_IDLE,
R_WRITE,
R_ERASE,
- R_COMMIT,
+ R_SYNC,
R_READ,
- R_VERIFY,
R_CRC,
};
- enum {
- META_IDLE,
- META_COMMIT,
- META_VERIFY
- };
-
enum {
N = uniqueCount(UQ_BLOCK_STORAGE) + uniqueCount(UQ_CONFIG_STORAGE),
NO_CLIENT = 0xff
};
uint8_t client = NO_CLIENT;
- uint8_t metaState;
storage_addr_t bytesRemaining;
- nx_struct {
- nx_uint16_t crc;
- nx_uint32_t maxAddr;
- } sig;
struct {
/* The latest request made for this client, and it's arguments */
uint8_t request; /* automatically initialised to R_IDLE */
- uint8_t *buf;
+ uint8_t * COUNT_NOK(len) buf;
storage_addr_t addr;
storage_len_t len;
-
- /* Maximum address written in this block */
- storage_addr_t maxAddr;
} s[N];
/* ------------------------------------------------------------------ */
void eraseStart();
- void verifyStart();
+ void syncStart();
void multipageStart(storage_len_t len, uint16_t crc);
void startRequest() {
case R_ERASE:
eraseStart();
break;
- case R_VERIFY:
- verifyStart();
+ case R_SYNC:
+ syncStart();
break;
default:
multipageStart(s[client].len, (uint16_t)s[client].buf);
case R_CRC:
signal BlockRead.computeCrcDone[c](addr, actualLength, crc, result);
break;
- case R_COMMIT:
- signal BlockWrite.commitDone[c](result);
- break;
- case R_VERIFY:
- signal BlockRead.verifyDone[c](result);
+ case R_SYNC:
+ signal BlockWrite.syncDone[c](result);
break;
}
}
error_t newRequest(uint8_t newState, uint8_t id,
- storage_addr_t addr, uint8_t* buf, storage_len_t len) {
+ storage_addr_t addr, uint8_t* COUNT_NOK(len) buf, storage_len_t len) {
storage_len_t vsize;
if (s[id].request != R_IDLE)
event void Resource.granted[uint8_t blockId]() {
client = blockId;
- if (s[blockId].request == R_WRITE)
+ if (s[blockId].request == R_WRITE &&
+ call BConfig.writeHook[blockId]())
{
- if (s[blockId].addr + s[blockId].len > s[blockId].maxAddr)
- s[blockId].maxAddr = s[blockId].addr + s[blockId].len;
-
- if (call BConfig.writeHook[blockId]())
- {
- /* Config write intercept. We'll get a writeContinue when it's
- time to resume. */
- client = NO_CLIENT;
- return;
- }
+ /* Config write intercept. We'll get a writeContinue when it's
+ time to resume. */
+ client = NO_CLIENT;
+ return;
}
startRequest();
}
/* Multipage operations */
/* ------------------------------------------------------------------ */
- void commitCrcDone(uint16_t crc);
- void verifyCrcDone(uint16_t crc);
-
- void multipageDone(uint16_t crc) {
- switch (s[client].request)
- {
- default: endRequest(SUCCESS, crc); break;
- case R_COMMIT: commitCrcDone(crc); break;
- case R_VERIFY: verifyCrcDone(crc); break;
- }
- }
-
void calcRequest(storage_addr_t addr, at45page_t *page,
at45pageoffset_t *offset, at45pageoffset_t *count) {
*page = pageRemap(addr >> AT45_PAGE_SIZE_LOG2);
if (bytesRemaining == 0)
{
- multipageDone(crc);
+ endRequest(SUCCESS, crc);
return;
}
case R_READ:
call At45db.read(page, offset, buf, count);
break;
- default:
+ case R_CRC:
call At45db.computeCrc(page, offset, count, crc);
break;
}
}
void multipageStart(storage_len_t len, uint16_t crc) {
- metaState = META_IDLE;
bytesRemaining = len;
multipageContinue(crc);
}
}
/* ------------------------------------------------------------------ */
- /* Commit */
+ /* Sync */
/* ------------------------------------------------------------------ */
- command error_t BlockWrite.commit[uint8_t id]() {
- return newRequest(R_COMMIT, id, 0, NULL, s[id].maxAddr);
+ command error_t BlockWrite.sync[uint8_t id]() {
+ return newRequest(R_SYNC, id, 0, NULL, 0);
}
- /* Called once crc computed. Write crc + signature in block 0. */
- void commitCrcDone(uint16_t crc) {
- sig.crc = crc;
- sig.maxAddr = s[client].maxAddr;
- metaState = META_COMMIT;
- call At45db.write(pageRemap(0), 1 << AT45_PAGE_SIZE_LOG2, &sig, sizeof sig);
- }
-
- void commitWriteDone(error_t error) {
- if (error == SUCCESS)
- call At45db.syncAll();
- else
- endRequest(error, 0);
+ void syncStart() {
+ call At45db.syncAll();
}
- void commitSyncDone(error_t error) {
+ void syncSyncDone(error_t error) {
endRequest(error, 0);
}
- /* ------------------------------------------------------------------ */
- /* Verify */
- /* ------------------------------------------------------------------ */
-
- command error_t BlockRead.verify[uint8_t id]() {
- return newRequest(R_VERIFY, id, 0, NULL, 0);
- }
-
- void verifyStart() {
- metaState = META_VERIFY;
- call At45db.read(pageRemap(0), 1 << AT45_PAGE_SIZE_LOG2, &sig, sizeof sig);
- }
-
- /* See signature written in commit */
- void verifyReadDone(error_t error) {
- if (error == SUCCESS)
- {
- storage_addr_t max = sig.maxAddr;
-
- /* Ignore maxAddress values that are too large */
- if (max <= call BlockRead.getSize[client]())
- {
- s[client].addr = 0;
- s[client].maxAddr = max;
- multipageStart(max, 0);
- return;
- }
- }
- endRequest(FAIL, 0);
- }
-
- void verifyCrcDone(uint16_t crc) {
- if (crc == sig.crc)
- endRequest(SUCCESS, 0);
- else
- {
- s[client].maxAddr = 0;
- endRequest(FAIL, 0);
- }
- }
-
/* ------------------------------------------------------------------ */
/* Read */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
command error_t BlockRead.computeCrc[uint8_t id](storage_addr_t addr, storage_len_t len, uint16_t basecrc) {
- return newRequest(R_CRC, id, addr, (void *)basecrc, len);
+ return newRequest(R_CRC, id, addr, TCAST(void * COUNT(len),basecrc), len);
}
/* ------------------------------------------------------------------ */
event void At45db.writeDone(error_t result) {
if (client != NO_CLIENT)
- if (metaState == META_IDLE)
- multipageOpDone(result, 0);
- else
- commitWriteDone(result);
+ multipageOpDone(result, 0);
}
event void At45db.readDone(error_t result) {
if (client != NO_CLIENT)
- if (metaState == META_IDLE)
- multipageOpDone(result, 0);
- else
- verifyReadDone(result);
+ multipageOpDone(result, 0);
}
event void At45db.computeCrcDone(error_t result, uint16_t newCrc) {
event void At45db.syncDone(error_t result) {
if (client != NO_CLIENT)
- commitSyncDone(result);
+ syncSyncDone(result);
}
event void At45db.flushDone(error_t result) { }
event void At45db.copyPageDone(error_t error) { }
default event void BlockWrite.writeDone[uint8_t id](storage_addr_t addr, void* buf, storage_len_t len, error_t result) { }
default event void BlockWrite.eraseDone[uint8_t id](error_t result) { }
- default event void BlockWrite.commitDone[uint8_t id](error_t result) { }
+ default event void BlockWrite.syncDone[uint8_t id](error_t result) { }
default event void BlockRead.readDone[uint8_t id](storage_addr_t addr, void* buf, storage_len_t len, error_t result) { }
- default event void BlockRead.verifyDone[uint8_t id](error_t result) { }
default event void BlockRead.computeCrcDone[uint8_t id](storage_addr_t addr, storage_len_t len, uint16_t x, error_t result) { }
default command at45page_t At45dbVolume.remap[uint8_t id](at45page_t volumePage) { return 0; }
default command at45page_t At45dbVolume.volumeSize[uint8_t id]() { return 0; }
default async command error_t Resource.request[uint8_t id]() { return FAIL; }
- default async command void Resource.release[uint8_t id]() { }
+ default async command error_t Resource.release[uint8_t id]() { return FAIL; }
}