Mirror with some correction

Dependencies:   mbed FastIO FastPWM USBDevice

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
     {