Mirror with some correction

Dependencies:   mbed FastIO FastPWM USBDevice

Committer:
mjr
Date:
Wed Feb 03 22:57:25 2016 +0000
Revision:
40:cc0d9814522b
Parent:
35:e959ffba78fd
Child:
59:94eb9265b6d7
Gamma correction option for outputs; work in progress on new config program

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