
System Management code
Dependencies: mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP
Fork of SystemManagement by
DataStructures/DataStructures.cpp@39:ddf38df9699e, 2015-02-11 (annotated)
- 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?
User | Revision | Line number | New 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(©Buffer[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(©Buffer[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 | } |