Mirror with some correction

Dependencies:   mbed FastIO FastPWM USBDevice

Committer:
mjr
Date:
Sat Dec 19 06:37:19 2015 +0000
Revision:
35:e959ffba78fd
Child:
40:cc0d9814522b
Keyboard/Media Control interface working, but the extra interface confuses the DOF connector.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mjr 35:e959ffba78fd 1 // NVM - Non-Volatile Memory
mjr 35:e959ffba78fd 2 //
mjr 35:e959ffba78fd 3 // This module handles the storage of our configuration settings
mjr 35:e959ffba78fd 4 // and calibration data in flash memory, which allows us to
mjr 35:e959ffba78fd 5 // retrieve these settings after each power cycle.
mjr 35:e959ffba78fd 6
mjr 35:e959ffba78fd 7
mjr 35:e959ffba78fd 8 #ifndef NVM_H
mjr 35:e959ffba78fd 9 #define NVM_H
mjr 35:e959ffba78fd 10
mjr 35:e959ffba78fd 11 #include "config.h"
mjr 35:e959ffba78fd 12 #include "FreescaleIAP.h"
mjr 35:e959ffba78fd 13
mjr 35:e959ffba78fd 14
mjr 35:e959ffba78fd 15 // Non-volatile memory (NVM) structure
mjr 35:e959ffba78fd 16 //
mjr 35:e959ffba78fd 17 // This structure defines the layout of our saved configuration
mjr 35:e959ffba78fd 18 // and calibration data in flash memory.
mjr 35:e959ffba78fd 19 //
mjr 35:e959ffba78fd 20 // Hack alert!
mjr 35:e959ffba78fd 21 // Our use of flash for this purpose is ad hoc and not supported
mjr 35:e959ffba78fd 22 // by the mbed platform. mbed doesn't impose a file system on the
mjr 35:e959ffba78fd 23 // KL25Z flash; it simply treats the flash as a raw storage space
mjr 35:e959ffba78fd 24 // and assumes that the linker output is the only thing using it.
mjr 35:e959ffba78fd 25 // So if we want to use the flash, we basically have to do it on
mjr 35:e959ffba78fd 26 // the sly, by using space that the linker happens to leave unused.
mjr 35:e959ffba78fd 27 // Fortunately, it's fairly easy to do this, because the flash
mjr 35:e959ffba78fd 28 // is mapped in the obvious way, as a single contiguous block in
mjr 35:e959ffba78fd 29 // the CPU memory space, and the linker does the obvious thing,
mjr 35:e959ffba78fd 30 // storing its entire output in a single contiguous block starting
mjr 35:e959ffba78fd 31 // at the lowest flash address. This means that all flash memory
mjr 35:e959ffba78fd 32 // from (lowest flash address + length of linker output) to
mjr 35:e959ffba78fd 33 // (highest flash address) is unused and available for our sneaky
mjr 35:e959ffba78fd 34 // system. Unfortunately, there's no reliable way for the program
mjr 35:e959ffba78fd 35 // to determine the length of the linker output, so we can't know
mjr 35:e959ffba78fd 36 // where our available region starts. But we do know how much flash
mjr 35:e959ffba78fd 37 // there is overall, so we know where the flash ends. We can
mjr 35:e959ffba78fd 38 // therefore align our storage region at the end of memory and hope
mjr 35:e959ffba78fd 39 // that it's small enough not to encroach on the linker space. We
mjr 35:e959ffba78fd 40 // can actually do a little better than hope: the mbed tools tell us
mjr 35:e959ffba78fd 41 // at the UI level how much flash the linker is using, even though it
mjr 35:e959ffba78fd 42 // doesn't expose that information to us programmatically, so we can
mjr 35:e959ffba78fd 43 // manually check that we have enough room. As of this writing, the
mjr 35:e959ffba78fd 44 // configuration structure is much much smaller than the available
mjr 35:e959ffba78fd 45 // leftover flash space, so we should be safe indefinitely, barring
mjr 35:e959ffba78fd 46 // a major expansion of the configuration structure or code size.
mjr 35:e959ffba78fd 47 //
mjr 35:e959ffba78fd 48 // The boot loader seems to erase the entire flash space every time
mjr 35:e959ffba78fd 49 // we load new firmware, so our configuration structure is lost
mjr 35:e959ffba78fd 50 // when we update. Furthermore, since we explicitly choose to put
mjr 35:e959ffba78fd 51 // the config structure in space that isn't initialized by the linker,
mjr 35:e959ffba78fd 52 // we can't specify the new contents stored on these erasure events.
mjr 35:e959ffba78fd 53 // To deal with this, we use a signature and checksum to check the
mjr 35:e959ffba78fd 54 // integrity of the stored data. The erasure leaves deterministic
mjr 35:e959ffba78fd 55 // values in memory unused by the linker, so we'll always detect
mjr 35:e959ffba78fd 56 // an uninitialized config structure after an update.
mjr 35:e959ffba78fd 57 //
mjr 35:e959ffba78fd 58 struct NVM
mjr 35:e959ffba78fd 59 {
mjr 35:e959ffba78fd 60 public:
mjr 35:e959ffba78fd 61 // checksum - we use this to determine if the flash record
mjr 35:e959ffba78fd 62 // has been properly initialized
mjr 35:e959ffba78fd 63 uint32_t checksum;
mjr 35:e959ffba78fd 64
mjr 35:e959ffba78fd 65 // signature and version reference values
mjr 35:e959ffba78fd 66 static const uint32_t SIGNATURE = 0x4D4A522A;
mjr 35:e959ffba78fd 67 static const uint16_t VERSION = 0x0003;
mjr 35:e959ffba78fd 68
mjr 35:e959ffba78fd 69 // Is the data structure valid? We test the signature and
mjr 35:e959ffba78fd 70 // checksum to determine if we've been properly stored.
mjr 35:e959ffba78fd 71 int valid() const
mjr 35:e959ffba78fd 72 {
mjr 35:e959ffba78fd 73 return (d.sig == SIGNATURE
mjr 35:e959ffba78fd 74 && d.vsn == VERSION
mjr 35:e959ffba78fd 75 && d.sz == sizeof(NVM)
mjr 35:e959ffba78fd 76 && checksum == CRC32(&d, sizeof(d)));
mjr 35:e959ffba78fd 77 }
mjr 35:e959ffba78fd 78
mjr 35:e959ffba78fd 79 // save to non-volatile memory
mjr 35:e959ffba78fd 80 void save(FreescaleIAP &iap, int addr)
mjr 35:e959ffba78fd 81 {
mjr 35:e959ffba78fd 82 // update the checksum and structure size
mjr 35:e959ffba78fd 83 d.sig = SIGNATURE;
mjr 35:e959ffba78fd 84 d.vsn = VERSION;
mjr 35:e959ffba78fd 85 d.sz = sizeof(NVM);
mjr 35:e959ffba78fd 86 checksum = CRC32(&d, sizeof(d));
mjr 35:e959ffba78fd 87
mjr 35:e959ffba78fd 88 // figure the number of sectors required
mjr 35:e959ffba78fd 89 int sectors = (sizeof(NVM) + SECTOR_SIZE - 1) / SECTOR_SIZE;
mjr 35:e959ffba78fd 90 for (int i = 0 ; i < sectors ; ++i)
mjr 35:e959ffba78fd 91 iap.erase_sector(addr + i*SECTOR_SIZE);
mjr 35:e959ffba78fd 92
mjr 35:e959ffba78fd 93 // save the data
mjr 35:e959ffba78fd 94 iap.program_flash(addr, this, sizeof(*this));
mjr 35:e959ffba78fd 95 }
mjr 35:e959ffba78fd 96
mjr 35:e959ffba78fd 97 // stored data (excluding the checksum)
mjr 35:e959ffba78fd 98 struct
mjr 35:e959ffba78fd 99 {
mjr 35:e959ffba78fd 100 // Signature, structure version, and structure size, as further
mjr 35:e959ffba78fd 101 // verification that we have valid data.
mjr 35:e959ffba78fd 102 uint32_t sig;
mjr 35:e959ffba78fd 103 uint16_t vsn;
mjr 35:e959ffba78fd 104 int sz;
mjr 35:e959ffba78fd 105
mjr 35:e959ffba78fd 106 // configuration and calibration data
mjr 35:e959ffba78fd 107 Config c;
mjr 35:e959ffba78fd 108 } d;
mjr 35:e959ffba78fd 109 };
mjr 35:e959ffba78fd 110
mjr 35:e959ffba78fd 111 #endif /* NVM_M */