System Management code
Dependencies: mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP
Fork of SystemManagement by
DataStructures.cpp
00001 #include "DataStructures.h" 00002 #include "DefaultProfile.h" 00003 #include "IAP.h" 00004 00005 #define HEADER_SECTOR 27 // Where the NV_Data header information is stored 00006 #define HEADER_PTR (NV_Data*)((uint32_t*)(sector_start_adress[HEADER_SECTOR])) 00007 #define ID_MARKER 0x5a5a5a5a // Marker that identifies whether the flash was erased from programming a new .bin file 00008 #define FRAME_SECTOR 28 // First sector for freeze frame storage (swapspace) 00009 #define FRAME_PTR (FreezeFrame*)((uint32_t*)(sector_start_adress[FRAME_SECTOR])) 00010 #define PROFILE_SECTOR 29 // The flash sector where profiles are stored, 29 is the last 32kB size sector in memory 00011 #define PROFILE_START_PTR (Profile_checkSum*)((uint32_t*)(sector_start_adress[PROFILE_SECTOR])) // Pointer to the first profile object in flash 00012 00013 // OPERATING DATA OBJECTS 00014 FreezeFrame frame; // Current working object in RAM, contains both param and freeze frame 00015 OperatingInfo *op = &(frame.op.op); // Handle to just the op section 00016 Profile *param = &(frame.param.param); // Handle to just the param section 00017 TemporaryData tempData; // Temporary data object in RAM 00018 00019 IAP iap; // Access to In-Application-Programming --> flash memory programming routines 00020 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 00021 00022 // Non-volatile data holder class 00023 class NV_Data 00024 { 00025 public: 00026 NV_Data() { 00027 id = ID_MARKER; 00028 frameStoredFlag = 0; 00029 usingProfile = 0; 00030 } 00031 int frameStoredFlag; 00032 int usingProfile; 00033 00034 int id; 00035 }; 00036 00037 // Construct new freeze frames with empty OperatingInfo and default Profile 00038 FreezeFrame::FreezeFrame() 00039 { 00040 memcpy(&(this->param), &defaultProfile, sizeof(Profile)); 00041 memset(&(this->op), 0, sizeof(OperatingInfo)); 00042 } 00043 00044 // Helper function to compute checksums using the BSD checksum algorithim for checking validity of flash contents 00045 // Arguments: start location of the block, size in bytes Returns: checksum 00046 uint32_t checksum(const void* ptr, unsigned int size) 00047 { 00048 const char* start = (char*)(ptr); 00049 uint32_t checksum = 0; 00050 for (uint32_t i = 0; i < size; i++) { // Skip last 4 bytes which holds the checksum itsel 00051 // BSD checksum algorithm 00052 checksum = (checksum >> 1) + ((checksum & 1) << 15); 00053 checksum += start[i]; // Accumulate 00054 checksum &= 0xffff; // Time to 16 bits 00055 } 00056 return checksum; 00057 } 00058 00059 // Helper function to streamline flash memory prep-erase-prep-write 00060 // Takes start pointer (RAM), size of object to copy, start pointer (flash), and sector number 00061 int flashWrite(void* start, int size, void* flash_start, int sector) 00062 { 00063 for (int i = 256; i <= 8192; i *= 2) { // Count by powers of 2 00064 if (size <= i) { // Stop when oversize or equal 00065 size = i; 00066 break; 00067 } 00068 } 00069 if (size > 4096) return -1; // Chunk too big to copy 00070 if (size == 2048) size = 4096; // 2048 does not exist, next size up 00071 00072 __disable_irq(); // Flash operations are non-interruptable 00073 00074 // Flash prepare, erase, prepare, write - (r == 0) means successful, non-zero = error code 00075 int r = iap.prepare(sector, sector); 00076 if (r == 0) { 00077 r = iap.erase(sector, sector); 00078 if (r == 0) { 00079 r = iap.prepare(sector, sector); 00080 if (r == 0) { 00081 r = iap.write((char*)start, (char*)flash_start, size); 00082 } 00083 } 00084 } 00085 __enable_irq(); // Re-enable interrupts 00086 return r; // 0 if success, otherwise see fault codes in LPC1768 User Manual 00087 } 00088 bool setProfile(int index) 00089 { 00090 bool passed = false; 00091 if (index == 0) passed = true; 00092 else if (index == -1) passed = true; 00093 else if (index <= NUM_STORED_PROFILES && index > 0) passed = true; 00094 00095 if (!passed) return false; 00096 NV_Data temp; 00097 NV_Data* header = HEADER_PTR; 00098 00099 __disable_irq(); 00100 memcpy(&temp, header, sizeof(NV_Data)); // Atomic copy to RAM 00101 __enable_irq(); 00102 00103 temp.usingProfile = index; 00104 00105 // Write it back to flash 00106 int i = flashWrite(&temp, sizeof(NV_Data), sector_start_adress[HEADER_SECTOR], HEADER_SECTOR); 00107 return (i == 0); 00108 } 00109 00110 // Retrieve the index number of the currently active profile (last profile loaded/saved) 00111 int Profile::usingProfile() 00112 { 00113 NV_Data* header = HEADER_PTR; 00114 return header->usingProfile; 00115 } 00116 00117 // Startup procedure run on chip reset to fetch last used profile 00118 bool Profile::loadStartUp() 00119 { 00120 // Check health of the header 00121 NV_Data *header = HEADER_PTR; 00122 bool passed=true; 00123 if (header->id != ID_MARKER) passed = false; 00124 if (header->usingProfile > NUM_STORED_PROFILES || header->usingProfile < -1) passed = false; 00125 if (header->frameStoredFlag != 0 && header->frameStoredFlag != ~0) passed = false; 00126 00127 // Write a new, blank header 00128 if (!passed) { 00129 NV_Data temp; 00130 int i = flashWrite(&temp, sizeof(NV_Data), sector_start_adress[HEADER_SECTOR], HEADER_SECTOR); 00131 } 00132 00133 if (loadProfile(usingProfile())) { // Try to fetch the profile that is currently marked 00134 return true; 00135 } else { // If fail, revert to default 00136 loadProfile(0); 00137 return false; 00138 } 00139 } 00140 00141 // Attempt to copy profile from flash to RAM object as indicated by int index 00142 bool Profile::loadProfile(int index) 00143 { 00144 Profile *p; 00145 if (!getProfile(&p, index)) return false; 00146 00147 __disable_irq(); 00148 memcpy(param, p, sizeof(Profile)); 00149 __enable_irq(); 00150 00151 if (setProfile(index)) return true; 00152 return false; // Bad sum, no copy was done 00153 } 00154 00155 // Attempt to fetch the profile pointer only, no copy to RAM 00156 bool Profile::getProfile(Profile **ptr, int index) 00157 { 00158 Profile_checkSum *p; 00159 00160 // If default profile requested 00161 if (index == 0) { 00162 *ptr = &defaultProfile; // Set pointer to default, return 00163 return true; 00164 00165 // If freeze profile requested 00166 } else if (index == -1) { 00167 FreezeFrame *freeze; 00168 if (!FreezeFrame::getFrame(&freeze)) { // Attempt to fetch frame 00169 *ptr = NULL; // Not available, set NULL 00170 return false; 00171 } 00172 p = &(freeze->param); 00173 00174 // Profile from flash storage requested 00175 } else if (index <= NUM_STORED_PROFILES && index > 0) { 00176 p = PROFILE_START_PTR + (index - 1); // Set a pointer to the profile 00177 00178 // Bad command, invalid index 00179 } else { 00180 *ptr = NULL; 00181 return false; 00182 } 00183 // Validate contents by computing checksum 00184 if (p->BSDchecksum == checksum(&(p->param), sizeof(Profile))) { // Check checksum 00185 *ptr = &(p->param); // Fill out the pointer, checksum passed 00186 return true; 00187 } 00188 *ptr = NULL; 00189 return false; // Bad checksum, ptr set to NULL 00190 } 00191 // Take the current RAM object contents and save it to flash at location given by index 00192 // Flash write requires the sector to be erased first, so the function will copy out and re-wrtie the profiles 00193 bool Profile::saveProfile(int index) 00194 { 00195 if (index > NUM_STORED_PROFILES || index <= 0) return false; // Index invalid 00196 frame.param.BSDchecksum = checksum(param, sizeof(Profile)); // Add the checksum 00197 00198 // Copy out all of the old profiles 00199 for (int i = 0; i < NUM_STORED_PROFILES; i++) { 00200 if (i == (index - 1)) { // Exception, replace this slot with the RAM profile 00201 __disable_irq(); 00202 memcpy(©Buffer[i], &(frame.param), sizeof(Profile_checkSum)); 00203 __enable_irq(); 00204 continue; // Skip to next 00205 } 00206 __disable_irq(); 00207 memcpy(©Buffer[i], PROFILE_START_PTR+i, sizeof(Profile_checkSum)); // Copy profile from flash to RAM 00208 __enable_irq(); 00209 } 00210 int r = flashWrite(copyBuffer, sizeof(copyBuffer), sector_start_adress[PROFILE_SECTOR], PROFILE_SECTOR); 00211 00212 if (r == 0) { 00213 return setProfile(index); 00214 } 00215 return false; 00216 } 00217 00218 // Fetch pointer to the last written freeze frame object if available, do not copy contents to RAM 00219 bool FreezeFrame::getFrame(FreezeFrame **frame) 00220 { 00221 if (FreezeFrame::getError() == false) { 00222 *frame = NULL; // No frame available, return 00223 return false; 00224 } 00225 00226 FreezeFrame* ptr = FRAME_PTR; // Set pointer to frame 00227 uint32_t checksumOp = checksum(&(ptr->op.op), sizeof(OperatingInfo)); // Compute checksum for operatingInfo section 00228 uint32_t checksumParam = checksum(&(ptr->param.param), sizeof(Profile)); // Compute checksum for profile section 00229 00230 if (checksumOp == ptr->op.BSDchecksum && checksumParam == ptr->param.BSDchecksum) { // Compare to stored checksum 00231 *frame = ptr; // Checksum passed, pass out the ptr 00232 return true; 00233 } 00234 *frame = NULL; // Checksum failed, write NULL 00235 return false; 00236 } 00237 00238 // Copy contents of RAM to flash, usually called on error to record the internal state upon enetering fault conditions 00239 bool FreezeFrame::writeFrame() 00240 { 00241 // Compute and record the checksums 00242 frame.param.BSDchecksum = checksum(&(frame.param.param), sizeof(Profile)); 00243 frame.op.BSDchecksum = checksum(&(frame.op.op), sizeof(OperatingInfo)); 00244 00245 int r = flashWrite(&frame, sizeof(FreezeFrame), sector_start_adress[FRAME_SECTOR], FRAME_SECTOR); 00246 if (r == 0) { 00247 // Set the error flag in the header 00248 NV_Data temp; 00249 NV_Data* header = HEADER_PTR; 00250 __disable_irq(); 00251 memcpy(&temp, header, sizeof(NV_Data)); 00252 __enable_irq(); 00253 temp.frameStoredFlag = ~0; 00254 int i = flashWrite(&temp, sizeof(NV_Data), sector_start_adress[HEADER_SECTOR], HEADER_SECTOR); 00255 return (i == 0); 00256 } 00257 return false; // False if flash operations failed 00258 } 00259 00260 // Get the non-volatile freeze Frame recorded flag that indicates whether a freeze frame is available 00261 bool FreezeFrame::getError() 00262 { 00263 NV_Data* header = HEADER_PTR; 00264 return header->frameStoredFlag; 00265 } 00266 // Clear the frame error, for ex. when the frame is read by user 00267 bool FreezeFrame::clearError() 00268 { 00269 NV_Data temp; 00270 NV_Data* header = HEADER_PTR; 00271 __disable_irq(); 00272 memcpy(&temp, header, sizeof(NV_Data)); 00273 __enable_irq(); 00274 temp.frameStoredFlag = 0; 00275 int i = flashWrite(&temp, sizeof(NV_Data), sector_start_adress[HEADER_SECTOR], HEADER_SECTOR); 00276 return (i == 0); 00277 }
Generated on Fri Jul 15 2022 06:07:18 by
1.7.2
