Mirror with some correction
Dependencies: mbed FastIO FastPWM USBDevice
Diff: nvm.h
- Revision:
- 76:7f5912b6340e
- Parent:
- 59:94eb9265b6d7
- Child:
- 79:682ae3171a08
--- a/nvm.h Sun Jan 29 19:04:47 2017 +0000 +++ b/nvm.h Fri Feb 03 20:50:02 2017 +0000 @@ -17,52 +17,10 @@ // This structure defines the layout of our saved configuration // and calibration data in flash memory. // -// Hack alert! -// -// Our use of flash for this purpose is ad hoc and not supported -// by the mbed platform. mbed doesn't impose a file system (or any -// other kind of formal structure) on the KL25Z flash; it simply -// treats the flash as a raw storage space for linker output and -// assumes that the linker is the only thing using it. So in order -// to use the flash, we basically have to do it on the sly, by -// using space that the linker happens to leave unused. -// -// Fortunately, it's fairly easy to do this, because the flash is -// mapped in the obvious way, as a single contiguous block in the -// CPU memory space, and because the mbed linker seems to do the -// obvious thing, storing its entire output in a single contiguous -// block starting at the lowest flash address. This means that all -// flash memory from (lowest flash address + length of linker output) -// to (highest flash address) is unused and available for our sneaky -// system. Unfortunately, there's no reliable way for the program -// to determine the length of the linker output, so we can't know -// where our available region starts. But we do know how much flash -// there is overall, so we know where the flash ends. We can -// therefore align our storage region at the end of memory and hope -// that it's small enough not to encroach on the linker space. We -// can actually do a little better than hope: the mbed tools tell us -// at the UI level how much flash the linker is using, even though it -// doesn't expose that information to us programmatically, so we can -// manually check that we have enough room. As of this writing, the -// configuration structure is much much smaller than the available -// leftover flash space, so we should be safe indefinitely, barring -// a major expansion of the configuration structure or code size. -// (And if we get to the point where we actually don't have space -// for our ~1K structure, we'll be up against the limits of the -// device anyway, so we'd have to rein in our ambitions or write -// more efficient code for deeper reasons than sharing this tiny -// sliver of memory.) -// -// The boot loader seems to erase the entire flash space every time -// we load new firmware, so our configuration structure is lost -// when we update. Furthermore, since we explicitly choose to put -// the config structure in space that isn't initialized by the linker, -// we can't specify the new contents stored on these erasure events. -// To deal with this, we use a signature and checksum to check the -// integrity of the stored data. The erasure leaves deterministic -// values in memory unused by the linker, so we'll always detect -// an uninitialized config structure after an update. -// +// The space in flash for the structure is reserved in the main +// program, by exploiting the linker's placement of const data +// in flash memory. This gives us a region of the appropriate +// size. struct NVM { public: @@ -76,7 +34,7 @@ // Is the data structure valid? We test the signature and // checksum to determine if we've been properly stored. - int valid() const + bool valid() const { return (d.sig == SIGNATURE && d.vsn == VERSION @@ -93,15 +51,16 @@ d.sz = sizeof(NVM); checksum = CRC32(&d, sizeof(d)); - // figure the number of sectors required - int sectors = (sizeof(NVM) + SECTOR_SIZE - 1) / SECTOR_SIZE; - for (int i = 0 ; i < sectors ; ++i) - iap.erase_sector(addr + i*SECTOR_SIZE); - - // save the data + // save the data to flash iap.program_flash(addr, this, sizeof(*this)); } + // verify that the NVM matches the in-memory configuration + bool verify(int addr) + { + return memcmp((NVM *)addr, this, sizeof(*this)) == 0; + } + // stored data (excluding the checksum) struct {