System Management code

Dependencies:   mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP

Fork of SystemManagement by Martin Deng

Committer:
pspatel321
Date:
Wed Feb 11 23:09:57 2015 +0000
Revision:
39:ddf38df9699e
Parent:
38:8efacce315ae
Updated CAN IDs for datalogging.  Changed profile encoding.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pspatel321 38:8efacce315ae 1 #include "DataStructures.h"
pspatel321 38:8efacce315ae 2 #include "DefaultProfile.h"
pspatel321 38:8efacce315ae 3 #include "IAP.h"
pspatel321 38:8efacce315ae 4
pspatel321 38:8efacce315ae 5 #define HEADER_SECTOR 27 // Where the NV_Data header information is stored
pspatel321 38:8efacce315ae 6 #define HEADER_PTR (NV_Data*)((uint32_t*)(sector_start_adress[HEADER_SECTOR]))
pspatel321 38:8efacce315ae 7 #define ID_MARKER 0x5a5a5a5a // Marker that identifies whether the flash was erased from programming a new .bin file
pspatel321 38:8efacce315ae 8 #define FRAME_SECTOR 28 // First sector for freeze frame storage (swapspace)
pspatel321 38:8efacce315ae 9 #define FRAME_PTR (FreezeFrame*)((uint32_t*)(sector_start_adress[FRAME_SECTOR]))
pspatel321 38:8efacce315ae 10 #define PROFILE_SECTOR 29 // The flash sector where profiles are stored, 29 is the last 32kB size sector in memory
pspatel321 38:8efacce315ae 11 #define PROFILE_START_PTR (Profile_checkSum*)((uint32_t*)(sector_start_adress[PROFILE_SECTOR])) // Pointer to the first profile object in flash
pspatel321 38:8efacce315ae 12
pspatel321 38:8efacce315ae 13 // OPERATING DATA OBJECTS
pspatel321 38:8efacce315ae 14 FreezeFrame frame; // Current working object in RAM, contains both param and freeze frame
pspatel321 38:8efacce315ae 15 OperatingInfo *op = &(frame.op.op); // Handle to just the op section
pspatel321 38:8efacce315ae 16 Profile *param = &(frame.param.param); // Handle to just the param section
pspatel321 38:8efacce315ae 17 TemporaryData tempData; // Temporary data object in RAM
pspatel321 38:8efacce315ae 18
pspatel321 38:8efacce315ae 19 IAP iap; // Access to In-Application-Programming --> flash memory programming routines
pspatel321 38:8efacce315ae 20 Profile_checkSum copyBuffer[NUM_STORED_PROFILES]; // Scratch-space in RAM for saving profiles, since flash writes must erase the entire sector and only RAM is usable during flash write
pspatel321 38:8efacce315ae 21
pspatel321 38:8efacce315ae 22 // Non-volatile data holder class
pspatel321 38:8efacce315ae 23 class NV_Data
pspatel321 38:8efacce315ae 24 {
pspatel321 38:8efacce315ae 25 public:
pspatel321 38:8efacce315ae 26 NV_Data() {
pspatel321 38:8efacce315ae 27 id = ID_MARKER;
pspatel321 38:8efacce315ae 28 frameStoredFlag = 0;
pspatel321 38:8efacce315ae 29 usingProfile = 0;
pspatel321 38:8efacce315ae 30 }
pspatel321 38:8efacce315ae 31 int frameStoredFlag;
pspatel321 38:8efacce315ae 32 int usingProfile;
pspatel321 38:8efacce315ae 33
pspatel321 38:8efacce315ae 34 int id;
pspatel321 38:8efacce315ae 35 };
pspatel321 38:8efacce315ae 36
pspatel321 38:8efacce315ae 37 // Construct new freeze frames with empty OperatingInfo and default Profile
pspatel321 38:8efacce315ae 38 FreezeFrame::FreezeFrame()
pspatel321 38:8efacce315ae 39 {
pspatel321 38:8efacce315ae 40 memcpy(&(this->param), &defaultProfile, sizeof(Profile));
pspatel321 38:8efacce315ae 41 memset(&(this->op), 0, sizeof(OperatingInfo));
pspatel321 38:8efacce315ae 42 }
pspatel321 38:8efacce315ae 43
pspatel321 38:8efacce315ae 44 // Helper function to compute checksums using the BSD checksum algorithim for checking validity of flash contents
pspatel321 38:8efacce315ae 45 // Arguments: start location of the block, size in bytes Returns: checksum
pspatel321 38:8efacce315ae 46 uint32_t checksum(const void* ptr, unsigned int size)
pspatel321 38:8efacce315ae 47 {
pspatel321 38:8efacce315ae 48 const char* start = (char*)(ptr);
pspatel321 38:8efacce315ae 49 uint32_t checksum = 0;
pspatel321 38:8efacce315ae 50 for (uint32_t i = 0; i < size; i++) { // Skip last 4 bytes which holds the checksum itsel
pspatel321 38:8efacce315ae 51 // BSD checksum algorithm
pspatel321 38:8efacce315ae 52 checksum = (checksum >> 1) + ((checksum & 1) << 15);
pspatel321 38:8efacce315ae 53 checksum += start[i]; // Accumulate
pspatel321 38:8efacce315ae 54 checksum &= 0xffff; // Time to 16 bits
pspatel321 38:8efacce315ae 55 }
pspatel321 38:8efacce315ae 56 return checksum;
pspatel321 38:8efacce315ae 57 }
pspatel321 38:8efacce315ae 58
pspatel321 38:8efacce315ae 59 // Helper function to streamline flash memory prep-erase-prep-write
pspatel321 38:8efacce315ae 60 // Takes start pointer (RAM), size of object to copy, start pointer (flash), and sector number
pspatel321 38:8efacce315ae 61 int flashWrite(void* start, int size, void* flash_start, int sector)
pspatel321 38:8efacce315ae 62 {
pspatel321 38:8efacce315ae 63 for (int i = 256; i <= 8192; i *= 2) { // Count by powers of 2
pspatel321 38:8efacce315ae 64 if (size <= i) { // Stop when oversize or equal
pspatel321 38:8efacce315ae 65 size = i;
pspatel321 38:8efacce315ae 66 break;
pspatel321 38:8efacce315ae 67 }
pspatel321 38:8efacce315ae 68 }
pspatel321 38:8efacce315ae 69 if (size > 4096) return -1; // Chunk too big to copy
pspatel321 38:8efacce315ae 70 if (size == 2048) size = 4096; // 2048 does not exist, next size up
pspatel321 38:8efacce315ae 71
pspatel321 38:8efacce315ae 72 __disable_irq(); // Flash operations are non-interruptable
pspatel321 38:8efacce315ae 73
pspatel321 38:8efacce315ae 74 // Flash prepare, erase, prepare, write - (r == 0) means successful, non-zero = error code
pspatel321 38:8efacce315ae 75 int r = iap.prepare(sector, sector);
pspatel321 38:8efacce315ae 76 if (r == 0) {
pspatel321 38:8efacce315ae 77 r = iap.erase(sector, sector);
pspatel321 38:8efacce315ae 78 if (r == 0) {
pspatel321 38:8efacce315ae 79 r = iap.prepare(sector, sector);
pspatel321 38:8efacce315ae 80 if (r == 0) {
pspatel321 38:8efacce315ae 81 r = iap.write((char*)start, (char*)flash_start, size);
pspatel321 38:8efacce315ae 82 }
pspatel321 38:8efacce315ae 83 }
pspatel321 38:8efacce315ae 84 }
pspatel321 38:8efacce315ae 85 __enable_irq(); // Re-enable interrupts
pspatel321 38:8efacce315ae 86 return r; // 0 if success, otherwise see fault codes in LPC1768 User Manual
pspatel321 38:8efacce315ae 87 }
pspatel321 38:8efacce315ae 88 bool setProfile(int index)
pspatel321 38:8efacce315ae 89 {
pspatel321 38:8efacce315ae 90 bool passed = false;
pspatel321 38:8efacce315ae 91 if (index == 0) passed = true;
pspatel321 38:8efacce315ae 92 else if (index == -1) passed = true;
pspatel321 38:8efacce315ae 93 else if (index <= NUM_STORED_PROFILES && index > 0) passed = true;
pspatel321 38:8efacce315ae 94
pspatel321 38:8efacce315ae 95 if (!passed) return false;
pspatel321 38:8efacce315ae 96 NV_Data temp;
pspatel321 38:8efacce315ae 97 NV_Data* header = HEADER_PTR;
pspatel321 38:8efacce315ae 98
pspatel321 38:8efacce315ae 99 __disable_irq();
pspatel321 38:8efacce315ae 100 memcpy(&temp, header, sizeof(NV_Data)); // Atomic copy to RAM
pspatel321 38:8efacce315ae 101 __enable_irq();
pspatel321 38:8efacce315ae 102
pspatel321 38:8efacce315ae 103 temp.usingProfile = index;
pspatel321 38:8efacce315ae 104
pspatel321 38:8efacce315ae 105 // Write it back to flash
pspatel321 38:8efacce315ae 106 int i = flashWrite(&temp, sizeof(NV_Data), sector_start_adress[HEADER_SECTOR], HEADER_SECTOR);
pspatel321 38:8efacce315ae 107 return (i == 0);
pspatel321 38:8efacce315ae 108 }
pspatel321 38:8efacce315ae 109
pspatel321 38:8efacce315ae 110 // Retrieve the index number of the currently active profile (last profile loaded/saved)
pspatel321 38:8efacce315ae 111 int Profile::usingProfile()
pspatel321 38:8efacce315ae 112 {
pspatel321 38:8efacce315ae 113 NV_Data* header = HEADER_PTR;
pspatel321 38:8efacce315ae 114 return header->usingProfile;
pspatel321 38:8efacce315ae 115 }
pspatel321 38:8efacce315ae 116
pspatel321 38:8efacce315ae 117 // Startup procedure run on chip reset to fetch last used profile
pspatel321 38:8efacce315ae 118 bool Profile::loadStartUp()
pspatel321 38:8efacce315ae 119 {
pspatel321 38:8efacce315ae 120 // Check health of the header
pspatel321 38:8efacce315ae 121 NV_Data *header = HEADER_PTR;
pspatel321 38:8efacce315ae 122 bool passed=true;
pspatel321 38:8efacce315ae 123 if (header->id != ID_MARKER) passed = false;
pspatel321 38:8efacce315ae 124 if (header->usingProfile > NUM_STORED_PROFILES || header->usingProfile < -1) passed = false;
pspatel321 38:8efacce315ae 125 if (header->frameStoredFlag != 0 && header->frameStoredFlag != ~0) passed = false;
pspatel321 38:8efacce315ae 126
pspatel321 38:8efacce315ae 127 // Write a new, blank header
pspatel321 38:8efacce315ae 128 if (!passed) {
pspatel321 38:8efacce315ae 129 NV_Data temp;
pspatel321 38:8efacce315ae 130 int i = flashWrite(&temp, sizeof(NV_Data), sector_start_adress[HEADER_SECTOR], HEADER_SECTOR);
pspatel321 38:8efacce315ae 131 }
pspatel321 38:8efacce315ae 132
pspatel321 38:8efacce315ae 133 if (loadProfile(usingProfile())) { // Try to fetch the profile that is currently marked
pspatel321 38:8efacce315ae 134 return true;
pspatel321 38:8efacce315ae 135 } else { // If fail, revert to default
pspatel321 38:8efacce315ae 136 loadProfile(0);
pspatel321 38:8efacce315ae 137 return false;
pspatel321 38:8efacce315ae 138 }
pspatel321 38:8efacce315ae 139 }
pspatel321 38:8efacce315ae 140
pspatel321 38:8efacce315ae 141 // Attempt to copy profile from flash to RAM object as indicated by int index
pspatel321 38:8efacce315ae 142 bool Profile::loadProfile(int index)
pspatel321 38:8efacce315ae 143 {
pspatel321 38:8efacce315ae 144 Profile *p;
pspatel321 38:8efacce315ae 145 if (!getProfile(&p, index)) return false;
pspatel321 38:8efacce315ae 146
pspatel321 38:8efacce315ae 147 __disable_irq();
pspatel321 38:8efacce315ae 148 memcpy(param, p, sizeof(Profile));
pspatel321 38:8efacce315ae 149 __enable_irq();
pspatel321 38:8efacce315ae 150
pspatel321 38:8efacce315ae 151 if (setProfile(index)) return true;
pspatel321 38:8efacce315ae 152 return false; // Bad sum, no copy was done
pspatel321 38:8efacce315ae 153 }
pspatel321 38:8efacce315ae 154
pspatel321 38:8efacce315ae 155 // Attempt to fetch the profile pointer only, no copy to RAM
pspatel321 38:8efacce315ae 156 bool Profile::getProfile(Profile **ptr, int index)
pspatel321 38:8efacce315ae 157 {
pspatel321 38:8efacce315ae 158 Profile_checkSum *p;
pspatel321 38:8efacce315ae 159
pspatel321 38:8efacce315ae 160 // If default profile requested
pspatel321 38:8efacce315ae 161 if (index == 0) {
pspatel321 38:8efacce315ae 162 *ptr = &defaultProfile; // Set pointer to default, return
pspatel321 38:8efacce315ae 163 return true;
pspatel321 38:8efacce315ae 164
pspatel321 38:8efacce315ae 165 // If freeze profile requested
pspatel321 38:8efacce315ae 166 } else if (index == -1) {
pspatel321 38:8efacce315ae 167 FreezeFrame *freeze;
pspatel321 38:8efacce315ae 168 if (!FreezeFrame::getFrame(&freeze)) { // Attempt to fetch frame
pspatel321 38:8efacce315ae 169 *ptr = NULL; // Not available, set NULL
pspatel321 38:8efacce315ae 170 return false;
pspatel321 38:8efacce315ae 171 }
pspatel321 38:8efacce315ae 172 p = &(freeze->param);
pspatel321 38:8efacce315ae 173
pspatel321 38:8efacce315ae 174 // Profile from flash storage requested
pspatel321 38:8efacce315ae 175 } else if (index <= NUM_STORED_PROFILES && index > 0) {
pspatel321 38:8efacce315ae 176 p = PROFILE_START_PTR + (index - 1); // Set a pointer to the profile
pspatel321 38:8efacce315ae 177
pspatel321 38:8efacce315ae 178 // Bad command, invalid index
pspatel321 38:8efacce315ae 179 } else {
pspatel321 38:8efacce315ae 180 *ptr = NULL;
pspatel321 38:8efacce315ae 181 return false;
pspatel321 38:8efacce315ae 182 }
pspatel321 38:8efacce315ae 183 // Validate contents by computing checksum
pspatel321 38:8efacce315ae 184 if (p->BSDchecksum == checksum(&(p->param), sizeof(Profile))) { // Check checksum
pspatel321 38:8efacce315ae 185 *ptr = &(p->param); // Fill out the pointer, checksum passed
pspatel321 38:8efacce315ae 186 return true;
pspatel321 38:8efacce315ae 187 }
pspatel321 38:8efacce315ae 188 *ptr = NULL;
pspatel321 38:8efacce315ae 189 return false; // Bad checksum, ptr set to NULL
pspatel321 38:8efacce315ae 190 }
pspatel321 38:8efacce315ae 191 // Take the current RAM object contents and save it to flash at location given by index
pspatel321 38:8efacce315ae 192 // Flash write requires the sector to be erased first, so the function will copy out and re-wrtie the profiles
pspatel321 38:8efacce315ae 193 bool Profile::saveProfile(int index)
pspatel321 38:8efacce315ae 194 {
pspatel321 38:8efacce315ae 195 if (index > NUM_STORED_PROFILES || index <= 0) return false; // Index invalid
pspatel321 38:8efacce315ae 196 frame.param.BSDchecksum = checksum(param, sizeof(Profile)); // Add the checksum
pspatel321 38:8efacce315ae 197
pspatel321 38:8efacce315ae 198 // Copy out all of the old profiles
pspatel321 38:8efacce315ae 199 for (int i = 0; i < NUM_STORED_PROFILES; i++) {
pspatel321 38:8efacce315ae 200 if (i == (index - 1)) { // Exception, replace this slot with the RAM profile
pspatel321 38:8efacce315ae 201 __disable_irq();
pspatel321 38:8efacce315ae 202 memcpy(&copyBuffer[i], &(frame.param), sizeof(Profile_checkSum));
pspatel321 38:8efacce315ae 203 __enable_irq();
pspatel321 38:8efacce315ae 204 continue; // Skip to next
pspatel321 38:8efacce315ae 205 }
pspatel321 38:8efacce315ae 206 __disable_irq();
pspatel321 38:8efacce315ae 207 memcpy(&copyBuffer[i], PROFILE_START_PTR+i, sizeof(Profile_checkSum)); // Copy profile from flash to RAM
pspatel321 38:8efacce315ae 208 __enable_irq();
pspatel321 38:8efacce315ae 209 }
pspatel321 38:8efacce315ae 210 int r = flashWrite(copyBuffer, sizeof(copyBuffer), sector_start_adress[PROFILE_SECTOR], PROFILE_SECTOR);
pspatel321 38:8efacce315ae 211
pspatel321 38:8efacce315ae 212 if (r == 0) {
pspatel321 38:8efacce315ae 213 return setProfile(index);
pspatel321 38:8efacce315ae 214 }
pspatel321 38:8efacce315ae 215 return false;
pspatel321 38:8efacce315ae 216 }
pspatel321 38:8efacce315ae 217
pspatel321 38:8efacce315ae 218 // Fetch pointer to the last written freeze frame object if available, do not copy contents to RAM
pspatel321 38:8efacce315ae 219 bool FreezeFrame::getFrame(FreezeFrame **frame)
pspatel321 38:8efacce315ae 220 {
pspatel321 38:8efacce315ae 221 if (FreezeFrame::getError() == false) {
pspatel321 38:8efacce315ae 222 *frame = NULL; // No frame available, return
pspatel321 38:8efacce315ae 223 return false;
pspatel321 38:8efacce315ae 224 }
pspatel321 38:8efacce315ae 225
pspatel321 38:8efacce315ae 226 FreezeFrame* ptr = FRAME_PTR; // Set pointer to frame
pspatel321 38:8efacce315ae 227 uint32_t checksumOp = checksum(&(ptr->op.op), sizeof(OperatingInfo)); // Compute checksum for operatingInfo section
pspatel321 38:8efacce315ae 228 uint32_t checksumParam = checksum(&(ptr->param.param), sizeof(Profile)); // Compute checksum for profile section
pspatel321 38:8efacce315ae 229
pspatel321 38:8efacce315ae 230 if (checksumOp == ptr->op.BSDchecksum && checksumParam == ptr->param.BSDchecksum) { // Compare to stored checksum
pspatel321 38:8efacce315ae 231 *frame = ptr; // Checksum passed, pass out the ptr
pspatel321 38:8efacce315ae 232 return true;
pspatel321 38:8efacce315ae 233 }
pspatel321 38:8efacce315ae 234 *frame = NULL; // Checksum failed, write NULL
pspatel321 38:8efacce315ae 235 return false;
pspatel321 38:8efacce315ae 236 }
pspatel321 38:8efacce315ae 237
pspatel321 38:8efacce315ae 238 // Copy contents of RAM to flash, usually called on error to record the internal state upon enetering fault conditions
pspatel321 38:8efacce315ae 239 bool FreezeFrame::writeFrame()
pspatel321 38:8efacce315ae 240 {
pspatel321 38:8efacce315ae 241 // Compute and record the checksums
pspatel321 38:8efacce315ae 242 frame.param.BSDchecksum = checksum(&(frame.param.param), sizeof(Profile));
pspatel321 38:8efacce315ae 243 frame.op.BSDchecksum = checksum(&(frame.op.op), sizeof(OperatingInfo));
pspatel321 38:8efacce315ae 244
pspatel321 38:8efacce315ae 245 int r = flashWrite(&frame, sizeof(FreezeFrame), sector_start_adress[FRAME_SECTOR], FRAME_SECTOR);
pspatel321 38:8efacce315ae 246 if (r == 0) {
pspatel321 38:8efacce315ae 247 // Set the error flag in the header
pspatel321 38:8efacce315ae 248 NV_Data temp;
pspatel321 38:8efacce315ae 249 NV_Data* header = HEADER_PTR;
pspatel321 38:8efacce315ae 250 __disable_irq();
pspatel321 38:8efacce315ae 251 memcpy(&temp, header, sizeof(NV_Data));
pspatel321 38:8efacce315ae 252 __enable_irq();
pspatel321 38:8efacce315ae 253 temp.frameStoredFlag = ~0;
pspatel321 38:8efacce315ae 254 int i = flashWrite(&temp, sizeof(NV_Data), sector_start_adress[HEADER_SECTOR], HEADER_SECTOR);
pspatel321 38:8efacce315ae 255 return (i == 0);
pspatel321 38:8efacce315ae 256 }
pspatel321 38:8efacce315ae 257 return false; // False if flash operations failed
pspatel321 38:8efacce315ae 258 }
pspatel321 38:8efacce315ae 259
pspatel321 38:8efacce315ae 260 // Get the non-volatile freeze Frame recorded flag that indicates whether a freeze frame is available
pspatel321 38:8efacce315ae 261 bool FreezeFrame::getError()
pspatel321 38:8efacce315ae 262 {
pspatel321 38:8efacce315ae 263 NV_Data* header = HEADER_PTR;
pspatel321 38:8efacce315ae 264 return header->frameStoredFlag;
pspatel321 38:8efacce315ae 265 }
pspatel321 38:8efacce315ae 266 // Clear the frame error, for ex. when the frame is read by user
pspatel321 38:8efacce315ae 267 bool FreezeFrame::clearError()
pspatel321 38:8efacce315ae 268 {
pspatel321 38:8efacce315ae 269 NV_Data temp;
pspatel321 38:8efacce315ae 270 NV_Data* header = HEADER_PTR;
pspatel321 38:8efacce315ae 271 __disable_irq();
pspatel321 38:8efacce315ae 272 memcpy(&temp, header, sizeof(NV_Data));
pspatel321 38:8efacce315ae 273 __enable_irq();
pspatel321 38:8efacce315ae 274 temp.frameStoredFlag = 0;
pspatel321 38:8efacce315ae 275 int i = flashWrite(&temp, sizeof(NV_Data), sector_start_adress[HEADER_SECTOR], HEADER_SECTOR);
pspatel321 38:8efacce315ae 276 return (i == 0);
pspatel321 38:8efacce315ae 277 }