This is a test of the ability to publish code
Dependencies: mbed SpiFlash25 mtsas
SettingsManager.h
00001 00002 #ifndef _SettingsManager_h_ 00003 #define _SettingsManager_h_ 00004 00005 #include "mbed.h" 00006 #include "SpiFlash25.h" 00007 00008 00009 #define PAGE_SIZE 256 00010 #define SECTOR_SIZE 64*1024 00011 #define MEM_SIZE 2*1024*1024 00012 00013 00014 class SettingsManager 00015 { 00016 public: 00017 static const size_t HOSTNAME_LENGTH = 128; 00018 00019 static const uint32_t DefaultSignature = 0x130c8215; 00020 00021 // This image appears at the top of the first two erasable sectors of the SPI flash. 00022 #pragma pack(push,1) 00023 struct SettingsImage 00024 { 00025 uint32_t m_valid; // Must be exactly 1 for valid; any other value (ffffffff, 0) are invalid. 00026 uint32_t m_signature; // arbitrary value, change if you want to force an update 00027 //char m_apn[HOSTNAME_LENGTH]; // For now, RadioManager hardcodes the ATT M2M APN; it's only a liability to make it changeable remotely, at this stage. 00028 char m_host1[HOSTNAME_LENGTH]; 00029 uint32_t m_port1; 00030 char m_host2[HOSTNAME_LENGTH]; 00031 uint32_t m_port2; 00032 int32_t m_sampleIntervalInSeconds; 00033 int32_t m_dischargeThreshold; // in mA 00034 int32_t m_chargeThreshold; // in mA 00035 int32_t m_currentHysteresis; // in mA 00036 int32_t m_serverSettingsUpdateSeconds; // seconds after which to ask server for updated settings -- usually the socket/radio will go down before this anyway 00037 uint32_t m_statusUpdateEvictionTime; 00038 uint32_t m_voltageFilterLengthInSamples; 00039 int32_t m_vspUpdateThreshold; 00040 int32_t m_vspJumpThreshold; 00041 int32_t m_voemUpdateThreshold; 00042 int32_t m_voemJumpThreshold; 00043 int32_t m_v3UpdateThreshold; 00044 int32_t m_v3JumpThreshold; 00045 int32_t m_v4UpdateThreshold; 00046 int32_t m_v4JumpThreshold; 00047 uint32_t m_currentFilterLengthInSamples; 00048 int32_t m_a1UpdateThreshold; 00049 int32_t m_a1JumpThreshold; 00050 int32_t m_a2UpdateThreshold; 00051 int32_t m_a2JumpThreshold; 00052 uint32_t m_temperatureFilterLengthInSamples; 00053 int32_t m_temperatureUpdateThreshold; 00054 int32_t m_temperatureJumpThreshold; 00055 int32_t m_useFilteredA1ForBatteryState; 00056 int32_t m_minimumEventSampleDuration; 00057 00058 // NOTE: Must pad this struct (before m_checksum) to an integral number of u32's if it isn't already... 00059 // char m_pad[3]; 00060 uint32_t m_mtime; // The time_t that the settings were written--so the manager can always take the most recent 00061 uint32_t m_checksum; // Sum of all 32-bit chunks preceding this, XOR'd by the XOR of all preceding u32's. Always the last thing in the struct. 00062 00063 bool matches(const SettingsImage& other) const 00064 { 00065 return 0 == memcmp(this, &other, sizeof(SettingsImage)); 00066 /* 00067 // Keep this around; useful for debugging settings update problems 00068 int i; 00069 const char* otherBuffer = (const char*)&other; 00070 const char* buffer = (const char*)this; 00071 bool matched = true; 00072 for (i = 0; i < sizeof(SettingsImage)-2*sizeof(uint32_t); ++i) 00073 { 00074 if (otherBuffer[i] != buffer[i]) 00075 { 00076 printf("Buffer mismatch offset %d, %02X != %02X\r\n", i, buffer[i], otherBuffer[i]); 00077 matched = false; 00078 } 00079 } 00080 if (matched) printf("Everything matched.\r\n"); 00081 return matched; 00082 */ 00083 } 00084 00085 00086 }; 00087 #pragma pack(pop) 00088 00089 SettingsManager(SpiFlash25& flash) : 00090 m_flash(flash) 00091 { 00092 m_settings.m_signature = DefaultSignature; 00093 } 00094 00095 /* 00096 const char* getAPN() const 00097 { 00098 return m_settings.m_apn; 00099 } 00100 */ 00101 00102 const char* getHost1() const 00103 { 00104 return m_settings.m_host1; 00105 } 00106 00107 uint16_t getPort1() const 00108 { 00109 return (uint16_t)m_settings.m_port1; 00110 } 00111 00112 const char* getHost2() const 00113 { 00114 return m_settings.m_host2; 00115 } 00116 00117 uint16_t getPort2() const 00118 { 00119 return (uint16_t)m_settings.m_port2; 00120 } 00121 00122 float getSampleIntervalInSeconds() const 00123 { 00124 return (float)m_settings.m_sampleIntervalInSeconds; 00125 } 00126 00127 float getSettingsUpdateIntervalInSeconds() const 00128 { 00129 return (float)m_settings.m_serverSettingsUpdateSeconds; 00130 } 00131 00132 float getDischargeThreshold() const 00133 { 00134 return (float)(m_settings.m_dischargeThreshold * 0.001); 00135 } 00136 00137 float getChargeThreshold() const 00138 { 00139 return (float)(m_settings.m_chargeThreshold * 0.001); 00140 } 00141 00142 float getCurrentHysteresis() const 00143 { 00144 return (float)(m_settings.m_currentHysteresis * 0.001); 00145 } 00146 00147 uint32_t getStatusUpdateEvictionTime() const 00148 { 00149 return (uint32_t)(m_settings.m_statusUpdateEvictionTime); 00150 } 00151 00152 uint32_t getVoltageFilterLengthInSamples() const 00153 { 00154 return (uint32_t)(m_settings.m_voltageFilterLengthInSamples); 00155 } 00156 00157 float getVspUpdateThreshold() const 00158 { 00159 return (float)(m_settings.m_vspUpdateThreshold * 0.001); 00160 } 00161 00162 float getVspJumpThreshold() const 00163 { 00164 return (float)(m_settings.m_vspJumpThreshold * 0.001); 00165 } 00166 00167 float getVoemUpdateThreshold() const 00168 { 00169 return (float)(m_settings.m_voemUpdateThreshold * 0.001); 00170 } 00171 00172 float getVoemJumpThreshold() const 00173 { 00174 return (float)(m_settings.m_voemJumpThreshold * 0.001); 00175 } 00176 00177 float getV3UpdateThreshold() const 00178 { 00179 return (float)(m_settings.m_v3UpdateThreshold * 0.001); 00180 } 00181 00182 float getV3JumpThreshold() const 00183 { 00184 return (float)(m_settings.m_v3JumpThreshold * 0.001); 00185 } 00186 00187 float getV4UpdateThreshold() const 00188 { 00189 return (float)(m_settings.m_v4UpdateThreshold * 0.001); 00190 } 00191 00192 float getV4JumpThreshold() const 00193 { 00194 return (float)(m_settings.m_v4JumpThreshold * 0.001); 00195 } 00196 00197 uint32_t getCurrentFilterLengthInSamples() const 00198 { 00199 return (uint32_t)(m_settings.m_currentFilterLengthInSamples); 00200 } 00201 00202 float getA1UpdateThreshold() const 00203 { 00204 return (float)(m_settings.m_a1UpdateThreshold * 0.001); 00205 } 00206 00207 float getA1JumpThreshold() const 00208 { 00209 return (float)(m_settings.m_a1JumpThreshold * 0.001); 00210 } 00211 00212 float getA2UpdateThreshold() const 00213 { 00214 return (float)(m_settings.m_a2UpdateThreshold * 0.001); 00215 } 00216 00217 float getA2JumpThreshold() const 00218 { 00219 return (float)(m_settings.m_a2JumpThreshold * 0.001); 00220 } 00221 00222 uint32_t getTemperatureFilterLengthInSamples() const 00223 { 00224 return (uint32_t)(m_settings.m_temperatureFilterLengthInSamples); 00225 } 00226 00227 float getTemperatureUpdateThreshold() const 00228 { 00229 return (float)(m_settings.m_temperatureUpdateThreshold * 0.001); 00230 } 00231 00232 float getTemperatureJumpThreshold() const 00233 { 00234 return (float)(m_settings.m_temperatureJumpThreshold * 0.001); 00235 } 00236 00237 bool getUseFilteredA1ForBatteryState() const 00238 { 00239 return m_settings.m_useFilteredA1ForBatteryState != 0; 00240 } 00241 00242 int32_t getMinimumEventSampleDuration() const 00243 { 00244 return m_settings.m_minimumEventSampleDuration; 00245 } 00246 00247 void loadDefaultSettings() 00248 { 00249 memset(&m_settings, 0, sizeof(m_settings)); 00250 // Loads memory settings from hardcoded constants--don't use this unless the flash is toast 00251 m_settings.m_valid = 1; 00252 m_settings.m_signature = DefaultSignature; 00253 m_settings.m_mtime = 0; // default value, earliest possible value. 00254 //snprintf(m_settings.m_apn, HOSTNAME_LENGTH, "m2m.com.attz"); 00255 memset(m_settings.m_host1, HOSTNAME_LENGTH, 0); 00256 snprintf(m_settings.m_host1, HOSTNAME_LENGTH, "iotdata1.idlereduction.com"); 00257 m_settings.m_port1 = 4700; 00258 memset(m_settings.m_host2, HOSTNAME_LENGTH, 0); 00259 snprintf(m_settings.m_host2, HOSTNAME_LENGTH, "52.54.102.85"); // EC2 elastic IP 00260 m_settings.m_port2 = 4700; 00261 m_settings.m_sampleIntervalInSeconds = 60 * 60; // hourly reporting by default 00262 m_settings.m_dischargeThreshold = 2500; // mA 00263 m_settings.m_chargeThreshold = -2500; // mA 00264 m_settings.m_currentHysteresis = 250; // mA 00265 m_settings.m_serverSettingsUpdateSeconds = 60 * 60; // hourly updates for server settings by default 00266 m_settings.m_statusUpdateEvictionTime = 60*60; // at least report status hourly if no other reason 00267 m_settings.m_voltageFilterLengthInSamples = 100; // smooth exponentially over this many samples 00268 m_settings.m_vspUpdateThreshold = 50; // mV 00269 m_settings.m_vspJumpThreshold = 1000; // mV 00270 m_settings.m_voemUpdateThreshold = 50; // mV 00271 m_settings.m_voemJumpThreshold = 1000; // mV 00272 m_settings.m_v3UpdateThreshold = 50; // mV 00273 m_settings.m_v3JumpThreshold = 1000; // mV 00274 m_settings.m_v4UpdateThreshold = 50; // mV 00275 m_settings.m_v4JumpThreshold = 1000; // mV 00276 m_settings.m_currentFilterLengthInSamples = 0; 00277 m_settings.m_a1UpdateThreshold = 1000; // mA 00278 m_settings.m_a1JumpThreshold = 3000; 00279 m_settings.m_a2UpdateThreshold = 1000; // mA 00280 m_settings.m_a2JumpThreshold = 3000; 00281 m_settings.m_temperatureFilterLengthInSamples = 100; 00282 m_settings.m_temperatureUpdateThreshold = 2500; // thousands of degree 00283 m_settings.m_temperatureJumpThreshold = 2500; 00284 m_settings.m_useFilteredA1ForBatteryState = 0; //false 00285 m_settings.m_minimumEventSampleDuration = 5; 00286 _populateChecksum(m_settings); 00287 } 00288 00289 void printSettings() 00290 { 00291 printf(" dischargeThreshold: %d mA\r\n", m_settings.m_dischargeThreshold); 00292 printf(" chargeThreshold: %d mA\r\n", m_settings.m_chargeThreshold); 00293 printf(" currentHysteresis: %d mA\r\n", m_settings.m_currentHysteresis); 00294 printf(" regularSampleInterval: %d s\r\n", m_settings.m_sampleIntervalInSeconds); 00295 printf(" settingsCheckInterval: %d s\r\n", m_settings.m_serverSettingsUpdateSeconds); 00296 printf(" primaryHost: '%s'\r\n", m_settings.m_host1); 00297 printf(" primaryPort: %d\r\n", m_settings.m_port1); 00298 printf(" secondaryHost: '%s'\r\n", m_settings.m_host2); 00299 printf(" secondaryPort: %d\r\n", m_settings.m_port2); 00300 printf(" statusUpdateEvictionTime: %d s\r\n", m_settings.m_statusUpdateEvictionTime); 00301 printf(" voltageFilterLengthInSamples: %d\r\n", m_settings.m_voltageFilterLengthInSamples); 00302 printf(" vspUpdateThreshold: %d mV\r\n", m_settings.m_vspUpdateThreshold); 00303 printf(" vspJumpThreshold: %d mV\r\n", m_settings.m_vspJumpThreshold); 00304 printf(" voemUpdateThreshold: %d mV\r\n", m_settings.m_voemUpdateThreshold); 00305 printf(" voemJumpThreshold: %d mV\r\n", m_settings.m_voemJumpThreshold); 00306 printf(" v3UpdateThreshold: %d mV\r\n", m_settings.m_v3UpdateThreshold); 00307 printf(" v3JumpThreshold: %d mV\r\n", m_settings.m_v3JumpThreshold); 00308 printf(" v4UpdateThreshold: %d mV\r\n", m_settings.m_v4UpdateThreshold); 00309 printf(" v4JumpThreshold: %d mV\r\n", m_settings.m_v4JumpThreshold); 00310 printf(" currentFilterLengthInSamples: %d\r\n", m_settings.m_currentFilterLengthInSamples); 00311 printf(" a1UpdateThreshold: %d mA\r\n", m_settings.m_a1UpdateThreshold); 00312 printf(" a1JumpThreshold: %d mA\r\n", m_settings.m_a1JumpThreshold); 00313 printf(" a2UpdateThreshold: %d mA\r\n", m_settings.m_a2UpdateThreshold); 00314 printf(" a2JumpThreshold: %d mA\r\n", m_settings.m_a2JumpThreshold); 00315 printf(" temperatureFilterLengthInSamples: %d s\r\n", m_settings.m_temperatureFilterLengthInSamples); 00316 printf(" temperatureUpdateThreshold: %d mDegC\r\n", m_settings.m_temperatureUpdateThreshold); 00317 printf(" temperatureJumpThreshold: %d mDegC\r\n", m_settings.m_temperatureJumpThreshold); 00318 printf(" useFilteredA1ForBatteryState: %d\r\n", m_settings.m_useFilteredA1ForBatteryState); 00319 printf(" minimumEventSampleDuration: %d\r\n", m_settings.m_minimumEventSampleDuration); 00320 } 00321 00322 bool setAll( 00323 const char* primaryHost, 00324 uint16_t primaryPort, 00325 const char* secondaryHost, 00326 uint16_t secondaryPort, 00327 int32_t dischargeThreshold, /* threshold in mV above which the stealth battery current is considered 'discharging' */ 00328 int32_t chargeThreshold, /* threshold below which the stealth battery current is considered 'charging' */ 00329 int32_t currentHysteresis, /* amount to ease the discharging/charging thresholds once already in that respective state */ 00330 int32_t regularSampleInterval, /* interval, in seconds, at which to send regularly-sampled data; 0 means "don't" */ 00331 int32_t settingsCheckInterval, 00332 uint32_t statusUpdateEvictionTime, 00333 uint32_t voltageFilterLengthInSamples, 00334 int32_t vspUpdateThreshold, 00335 int32_t vspJumpThreshold, 00336 int32_t voemUpdateThreshold, 00337 int32_t voemJumpThreshold, 00338 int32_t v3UpdateThreshold, 00339 int32_t v3JumpThreshold, 00340 int32_t v4UpdateThreshold, 00341 int32_t v4JumpThreshold, 00342 uint32_t currentFilterLengthInSamples, 00343 int32_t a1UpdateThreshold, 00344 int32_t a1JumpThreshold, 00345 int32_t a2UpdateThreshold, 00346 int32_t a2JumpThreshold, 00347 uint32_t temperatureFilterLengthInSamples, 00348 int32_t temperatureUpdateThreshold, 00349 int32_t temperatureJumpThreshold, 00350 int32_t useFilteredA1ForBatteryState, 00351 int32_t minimumEventSampleDuration) 00352 { 00353 if (!primaryHost || strlen(primaryHost) >= HOSTNAME_LENGTH) return false; 00354 if (!secondaryHost || strlen(secondaryHost) >= HOSTNAME_LENGTH) return false; 00355 if (regularSampleInterval < 0) regularSampleInterval = 0; 00356 if (settingsCheckInterval < 20) settingsCheckInterval = 20; // min 20 sec between settings checks 00357 if (settingsCheckInterval > 24*60*60) settingsCheckInterval = 24*60*60; // max 1 day between settings check 00358 if (minimumEventSampleDuration < 0) minimumEventSampleDuration = 0; 00359 00360 memset(m_settings.m_host1, 0, HOSTNAME_LENGTH); 00361 strncpy(m_settings.m_host1, primaryHost, HOSTNAME_LENGTH); 00362 m_settings.m_port1 = primaryPort; 00363 memset(m_settings.m_host2, 0, HOSTNAME_LENGTH); 00364 strncpy(m_settings.m_host2, secondaryHost, HOSTNAME_LENGTH); 00365 m_settings.m_port2 = secondaryPort; 00366 m_settings.m_dischargeThreshold = dischargeThreshold; 00367 m_settings.m_currentHysteresis = currentHysteresis; 00368 m_settings.m_chargeThreshold = chargeThreshold; 00369 m_settings.m_sampleIntervalInSeconds = regularSampleInterval; 00370 m_settings.m_serverSettingsUpdateSeconds = settingsCheckInterval; 00371 m_settings.m_statusUpdateEvictionTime = statusUpdateEvictionTime; 00372 m_settings.m_voltageFilterLengthInSamples = voltageFilterLengthInSamples; 00373 m_settings.m_vspUpdateThreshold = vspUpdateThreshold; 00374 m_settings.m_vspJumpThreshold = vspJumpThreshold; 00375 m_settings.m_voemUpdateThreshold = voemUpdateThreshold; 00376 m_settings.m_voemJumpThreshold = voemJumpThreshold; 00377 m_settings.m_v3UpdateThreshold = v3UpdateThreshold; 00378 m_settings.m_v3JumpThreshold = v3JumpThreshold; 00379 m_settings.m_v4UpdateThreshold = v4UpdateThreshold; 00380 m_settings.m_v4JumpThreshold = v4JumpThreshold; 00381 m_settings.m_currentFilterLengthInSamples = currentFilterLengthInSamples; 00382 m_settings.m_a1UpdateThreshold = a1UpdateThreshold; 00383 m_settings.m_a1JumpThreshold = a1JumpThreshold; 00384 m_settings.m_a2UpdateThreshold = a2UpdateThreshold; 00385 m_settings.m_a2JumpThreshold = a2JumpThreshold; 00386 m_settings.m_temperatureFilterLengthInSamples = temperatureFilterLengthInSamples; 00387 m_settings.m_temperatureUpdateThreshold = temperatureUpdateThreshold; 00388 m_settings.m_temperatureJumpThreshold = temperatureJumpThreshold; 00389 m_settings.m_useFilteredA1ForBatteryState = useFilteredA1ForBatteryState; 00390 m_settings.m_minimumEventSampleDuration = minimumEventSampleDuration; 00391 //printSettings(); 00392 return true; 00393 } 00394 /* other settings you can think of here ... ? */ 00395 00396 00397 00398 bool loadSettingsFromFlash() 00399 { 00400 // Try to get settings from sector 0 and from sector 1. 00401 // If they're both valid, take the one with the newer mtime. 00402 // If neither is valid, return false. 00403 00404 bool gotImage0 = false; 00405 SettingsImage image0; 00406 memset(&image0, 0, sizeof(SettingsImage)); 00407 gotImage0 = _loadIfValid(0*SECTOR_SIZE, image0); 00408 00409 bool gotImage1 = false; 00410 SettingsImage image1; 00411 memset(&image1, 0, sizeof(SettingsImage)); 00412 gotImage1 = _loadIfValid(1*SECTOR_SIZE, image1); 00413 00414 if (gotImage0 && !gotImage1) 00415 { 00416 m_settings = image0; 00417 printf("Loaded settings from sector 0 because sector 1 was bad\r\n"); 00418 } 00419 else if (gotImage1 && !gotImage0) 00420 { 00421 m_settings = image1; 00422 printf("Loaded settings from sector 1 because sector 0 was bad\r\n"); 00423 } 00424 else if (gotImage0 && gotImage1) 00425 { 00426 if (image0.m_mtime >= image1.m_mtime) 00427 { 00428 printf("Loaded settings from sector 0\r\n"); 00429 m_settings = image0; 00430 } 00431 else 00432 { 00433 printf("Loaded settings from sector 1\r\n"); 00434 m_settings = image1; 00435 } 00436 } 00437 00438 return gotImage0 || gotImage1; 00439 } 00440 00441 bool writeSettingsToFlash() 00442 { 00443 int mtime = SystemTimeKeeper::instance().walltime(); 00444 00445 // Compare to sector 0--if different, erase and write sector 0. 00446 SettingsImage image; 00447 memset(&image, 0, sizeof(SettingsImage)); 00448 if (_load(0*SECTOR_SIZE, image)) 00449 { 00450 if (!image.matches(m_settings) || 00451 !_checkChecksum(image)) 00452 { 00453 printf("Saving updated settings in sector 0.\r\n"); 00454 // Update the settings' mtime iff we're committed to rewriting flash 00455 m_settings.m_mtime = mtime; 00456 _populateChecksum(m_settings); 00457 00458 m_flash.clear_sector(0*SECTOR_SIZE); 00459 if (!m_flash.write(0*SECTOR_SIZE, sizeof(m_settings), (char*)&m_settings)) 00460 { 00461 printf("Error writing settings to sector 0.\r\n"); 00462 } 00463 } 00464 else 00465 { 00466 //printf("Settings already written in sector 0.\r\n"); 00467 } 00468 } 00469 else 00470 { 00471 printf("Couldn't validate settings in sector 0.\r\n"); 00472 } 00473 00474 // Compare to sector 1--if different, erase and write sector 1. 00475 memset(&image, 0, sizeof(SettingsImage)); 00476 if (_load(1*SECTOR_SIZE, image)) 00477 { 00478 if (!image.matches(m_settings) || 00479 !_checkChecksum(image)) 00480 { 00481 printf("Saving updated settings in sector 1.\r\n"); 00482 00483 // Update the settings' mtime iff we're committed to rewriting flash 00484 m_settings.m_mtime = mtime; 00485 _populateChecksum(m_settings); 00486 00487 m_flash.clear_sector(1*SECTOR_SIZE); 00488 if (!m_flash.write(1*SECTOR_SIZE, sizeof(m_settings), (char*)&m_settings)) 00489 { 00490 printf("Error writing settings to sector 1.\r\n"); 00491 } 00492 } 00493 else 00494 { 00495 //printf("Settings already written in sector 1.\r\n"); 00496 } 00497 } 00498 else 00499 { 00500 printf("Couldn't validate settings in sector 1.\r\n"); 00501 } 00502 00503 return true; 00504 } 00505 00506 bool serviceSettingsInFlash() 00507 { 00508 // This really means do what writeSettingsToFlash() already does--make sure 00509 // the settings we *have* are actually in the flash, in duplicate. 00510 return writeSettingsToFlash(); 00511 } 00512 00513 void initializeSettings() 00514 { 00515 /* 00516 //Keep this around--nice to dump flash contents to hex... 00517 uint32_t buffer[64] = {0}; 00518 int i; 00519 flash.read(0*SECTOR_SIZE, 64*4, (char*)&buffer); 00520 for (i = 0; i < 64; ++i) 00521 { 00522 printf(" %08x", buffer[i]); 00523 if (i % 8 == 7) printf("\r\n"); 00524 } 00525 printf("\r\n"); 00526 flash.read(1*SECTOR_SIZE, 64*4, (char*)&buffer); 00527 for (i = 0; i < 64; ++i) 00528 { 00529 printf(" %08x", buffer[i]); 00530 if (i % 8 == 7) printf("\r\n"); 00531 } 00532 //printf("\r\n"); 00533 */ 00534 00535 if (!loadSettingsFromFlash()) 00536 { 00537 printf("No settings found in Flash; forced to load hard-coded default settings.\r\n"); 00538 loadDefaultSettings(); 00539 } 00540 if (!writeSettingsToFlash()) 00541 { 00542 printf("Error writing settings to flash.\r\n"); 00543 } 00544 } 00545 00546 protected: 00547 bool _load(uint32_t offset, SettingsImage& image) 00548 { 00549 return m_flash.read(offset, sizeof(SettingsImage), (char*)&image); 00550 } 00551 00552 bool _loadIfValid(uint32_t offset, SettingsImage& image) 00553 { 00554 SettingsImage tempImage; 00555 memset(&tempImage, 0, sizeof(SettingsImage)); 00556 if (!_load(offset, tempImage)) return false; 00557 if (!_checkChecksum(tempImage)) return false; 00558 if (tempImage.m_valid != 1) return false; 00559 if (tempImage.m_signature != DefaultSignature) return false; 00560 image = tempImage; 00561 return true; 00562 } 00563 00564 uint32_t _calculateChecksum(const SettingsImage& settings) 00565 { 00566 uint32_t* raw = (uint32_t*)&settings; 00567 uint32_t xorValue = 0; 00568 uint32_t sum = 0; 00569 while (raw < (uint32_t*)&settings.m_checksum) 00570 { 00571 sum += (*raw); 00572 xorValue ^= (*raw); 00573 ++raw; 00574 } 00575 uint32_t calculated = sum; // ^ xorValue; 00576 //printf("calculated = %08x\r\n", calculated); 00577 return calculated; 00578 } 00579 00580 void _populateChecksum(SettingsImage& settings) 00581 { 00582 // Fill in the included settings.checksum is what it should be 00583 settings.m_checksum = _calculateChecksum(settings); 00584 } 00585 00586 bool _checkChecksum(const SettingsImage& settings) 00587 { 00588 // See if the included settings.checksum is what it should be 00589 return settings.m_checksum == _calculateChecksum(settings); 00590 } 00591 00592 SpiFlash25& m_flash; 00593 00594 SettingsImage m_settings; 00595 }; 00596 00597 #endif //_SettingsManager_h_ 00598
Generated on Sat Jul 16 2022 20:02:36 by 1.7.2