STM32 EEPROM Testing
Dependencies: mbed
cal.cpp
00001 #include "mbed.h" 00002 #include "globals.h" 00003 #include "cal.h" 00004 00005 #define ENABLE_DEBUG_PRINTING 1 // turn on diagnostic printing 00006 #define ENABLE_TEST_CODE 1 // turn on self-test code (disable for release) 00007 00008 00009 // Must customize which page of flash is used for calibration data 00010 // The STM32F334C8 has 32 pages (0..31) so use the last one 00011 // Note that on the initial prototype boards, a STM32F334C6 was used 00012 #define CAL_PAGE 31 00013 00014 static uint32_t CalPageAddress = FLASH_BASE + (CAL_PAGE * FLASH_PAGE_SIZE); 00015 00016 00017 #define CAL_HALFWORD_COUNT (sizeof(CALIBRATION_DATA)/sizeof(uint16_t)) 00018 #define CAL_WORD_COUNT (sizeof(CALIBRATION_DATA)/sizeof(uint32_t)) 00019 #define CAL_DOUBLEWORD_COUNT (sizeof(CALIBRATION_DATA)/sizeof(uint64_t)) 00020 00021 00022 00023 CALIBRATION_DATA g_cal; 00024 00025 static uint32_t DataAddress; // address of last saved data 00026 00027 static HAL_StatusTypeDef erase_page(uint32_t PageAddress) 00028 { 00029 HAL_StatusTypeDef Status; 00030 FLASH_EraseInitTypeDef EraseInit; 00031 uint32_t PageError; 00032 00033 EraseInit.TypeErase = FLASH_TYPEERASE_PAGES; 00034 EraseInit.PageAddress = PageAddress; 00035 //EraseInit.PageAddress = FLASH_BASE + (page_number * FLASH_PAGE_SIZE); 00036 EraseInit.NbPages = 1; 00037 00038 HAL_FLASH_Unlock(); 00039 Status = HAL_FLASHEx_Erase(&EraseInit, &PageError); 00040 HAL_FLASH_Lock(); 00041 return Status; 00042 } 00043 00044 static uint16_t calc_checksum() 00045 { 00046 int i; 00047 uint16_t *p; 00048 uint16_t checksum; 00049 00050 // read cal data from flash in 16 bit chunks 00051 p = (uint16_t *)&g_cal; 00052 00053 checksum = 0; 00054 00055 for (i=0; i < (CAL_HALFWORD_COUNT - 1); i++) { // don't sum checksum field 00056 00057 checksum += *p; 00058 00059 p++; 00060 } 00061 return checksum; 00062 } 00063 00064 static void factory_defaults() 00065 { 00066 //ppb_per_mv = 100.0f / 871.0f; // From Pyxis with factory cal 00067 //ppb_per_mv = 95.3f / (418.0f - 80.0f); // From Megatron and protoboard (reading-dark current) and scope 00068 //ppb_per_mv = 95.3f / (418.0f); // From Megatron and protoboard and scope 00069 //ppb_per_mv = 0.3225f; // manual 300/930 00070 //ppb_per_mv = 0.305f; // manual 300/981 00071 00072 g_cal.uv_zero_mV = 81; // uv adc mV reading at 0 ppb (might try dark current scaled up a bit here as a guess) 00073 g_cal.uv_cal_mV = 981; // uv adc mV reading at calibration point 00074 g_cal.uv_cal_ppb = 300; // uv user ppb value at calibration point 00075 00076 g_cal.vis_zero_mV = 81; 00077 g_cal.vis_cal_mV = 981; 00078 g_cal.vis_cal_ppb = 300; 00079 00080 g_cal.trim_4mA = 816; // dac value to use for 4 mA (see mA.cpp) 00081 g_cal.trim_20mA = 4080; // dac value to use for 20 mA (see mA.cpp) 00082 g_cal.ppb_at_20mA = 300; // factory default 4-20 mA range is 0-300 ppb 00083 00084 g_cal.padding = 0; 00085 00086 //g_cal.mAOffsetValue = 0.0; 00087 00088 g_cal.checksum = calc_checksum(); 00089 } 00090 00091 00092 00093 void cal_print() 00094 { 00095 printf("cal data = %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %u, %u, %.0f, %u, %u\n", 00096 g_cal.uv_zero_mV, 00097 g_cal.uv_cal_mV, 00098 g_cal.uv_cal_ppb, 00099 g_cal.vis_zero_mV, 00100 g_cal.vis_cal_mV, 00101 g_cal.vis_cal_ppb, 00102 g_cal.trim_4mA, 00103 g_cal.trim_20mA, 00104 g_cal.ppb_at_20mA, 00105 g_cal.padding, 00106 g_cal.checksum); 00107 00108 } 00109 00110 00111 static void read_cal_data(uint32_t address) 00112 { 00113 00114 int i; 00115 uint16_t *p; 00116 00117 // read cal data from flash address in 16 bit chunks 00118 p = (uint16_t *)&g_cal; 00119 00120 for (i=0; i < CAL_HALFWORD_COUNT; i++) { 00121 00122 *p = *(__IO uint16_t *)address; // read cal data 00123 00124 address += sizeof(uint16_t); 00125 p++; 00126 } 00127 #ifdef ENABLE_DEBUG_PRINTING 00128 cal_print(); 00129 #endif 00130 } 00131 00132 void cal_init() 00133 { 00134 uint32_t address; 00135 00136 // Assign factory defaults 00137 factory_defaults(); 00138 00139 // Start at beginning 00140 DataAddress = CalPageAddress; 00141 address = CalPageAddress; 00142 00143 while (IS_FLASH_PROGRAM_ADDRESS(address)) { 00144 uint32_t val; 00145 uint8_t *p; 00146 00147 p = (uint8_t *)&val; 00148 00149 val = *(__IO uint32_t*)address; // read 32 bits (4 bytes) 00150 00151 pc.printf("%hhX %hhX %hhX %hhX\n", p[0], p[1], p[2],p[3]); 00152 00153 // If the first 4 bytes are all 0xFF, the end of data has been reached 00154 if ( (p[0] == 0xFF) && (p[1] == 0xFF) && (p[2] == 0xFF) && (p[3] == 0xFF)) break; 00155 #ifdef ENABLE_DEBUG_PRINTING 00156 pc.printf("Saved data found at %lX\n", address); 00157 #endif 00158 00159 // Read cal data (this might not be the last one yet) 00160 read_cal_data(address); 00161 00162 DataAddress = address; // save last used data address 00163 address += sizeof(CALIBRATION_DATA); // Keep looking 00164 } 00165 00166 // Verify checksum 00167 if (g_cal.checksum != calc_checksum()) { 00168 #ifdef ENABLE_DEBUG_PRINTING 00169 pc.printf("Checksum mismatch, using factory defaults, flash = %u, calc = %u\n", g_cal.checksum, calc_checksum()); 00170 #endif 00171 factory_defaults(); 00172 } 00173 #ifdef ENABLE_DEBUG_PRINTING 00174 else { 00175 pc.printf("Checksum OK\n"); 00176 } 00177 #endif 00178 00179 00180 // Either valid data was found, or factory defaults are set 00181 00182 } 00183 00184 00185 void cal_save() 00186 { 00187 int i; 00188 uint16_t *p; 00189 00190 /* 00191 * FLASH_TYPEPROGRAM_HALFWORD is 16 bits 00192 * FLASH_TYPEPROGRAM_WORD is 32 bits = sizeof(float) 00193 * FLASH_TYPEPROGRAM_DOUBLEWORD is 64 bits 00194 * HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data) 00195 */ 00196 00197 //HAL_StatusTypeDef Status; 00198 uint32_t NextDataAddress; // address to use for next saved data 00199 uint32_t LastByteAddress; // address of last byte when new data is added 00200 NextDataAddress = DataAddress + sizeof(CALIBRATION_DATA); 00201 LastByteAddress = NextDataAddress + sizeof(CALIBRATION_DATA) - 1; 00202 00203 // First, decide if there is room at the end of the page for new data 00204 if (!IS_FLASH_PROGRAM_ADDRESS(LastByteAddress)) { 00205 // Erase the entire cal page 00206 erase_page(CalPageAddress); 00207 // Point to new location 00208 NextDataAddress = CalPageAddress; 00209 } 00210 // Remember the location of the start of the new data 00211 DataAddress = NextDataAddress; 00212 00213 // Update the checksum 00214 g_cal.checksum = calc_checksum(); 00215 00216 p = (uint16_t *) &g_cal; 00217 00218 HAL_FLASH_Unlock(); 00219 00220 for (i=0; i < CAL_HALFWORD_COUNT; i++) { 00221 HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, NextDataAddress, (uint64_t )(*p)); 00222 NextDataAddress += sizeof(uint16_t); 00223 p++; 00224 } 00225 00226 HAL_FLASH_Lock(); 00227 } 00228 00229 00230 void cal_factory() 00231 { 00232 // Set device to factory defaults 00233 erase_page(CalPageAddress); 00234 cal_init(); 00235 cal_save(); 00236 } 00237 00238 00239 00240 00241 #ifdef ENABLE_TEST_CODE 00242 00243 void direct() 00244 { 00245 int i; 00246 00247 //HAL_StatusTypeDef Status; 00248 FLASH_EraseInitTypeDef EraseInit; 00249 uint32_t PageError; 00250 00251 EraseInit.TypeErase = FLASH_TYPEERASE_PAGES; 00252 EraseInit.PageAddress = FLASH_BASE + (18 * FLASH_PAGE_SIZE); 00253 EraseInit.NbPages = 1; 00254 00255 HAL_FLASH_Unlock(); 00256 HAL_FLASHEx_Erase(&EraseInit, &PageError); 00257 HAL_FLASH_Lock(); 00258 00259 00260 printf("\nFlash memory values at start of each page:\n"); 00261 for (i=0; i<32; i++) { 00262 uint32_t address; 00263 uint32_t val; 00264 uint8_t *p; 00265 00266 p = (uint8_t *)&val; 00267 address = FLASH_BASE + (i * FLASH_PAGE_SIZE); 00268 00269 val = *(__IO uint32_t*)address; // read 32 bits (4 bytes) 00270 00271 printf("%i %hhX %hhX %hhX %hhX\n", i, p[0], p[1], p[2],p[3]); 00272 } 00273 } 00274 00275 00276 static void increment_data() 00277 { 00278 g_cal.uv_zero_mV += 1; // uv adc mV reading at 0 ppb 00279 g_cal.uv_cal_mV += 1; // uv adc mV reading at calibration point 00280 g_cal.uv_cal_ppb += 0; // uv user ppb value at calibration point 00281 00282 g_cal.vis_zero_mV += 1; 00283 g_cal.vis_cal_mV += 1; 00284 g_cal.vis_cal_ppb += 1; 00285 00286 g_cal.trim_4mA += 1; // dac value to use for 4 mA 00287 g_cal.trim_20mA += 1; // dac value to use for 20 mA 00288 00289 g_cal.checksum = calc_checksum(); 00290 } 00291 00292 void cal_test() 00293 { 00294 00295 pc.printf("\b\nSTM32 Test Flash Memory\n"); 00296 pc.printf("Flash page size = %d bytes\n", FLASH_PAGE_SIZE); 00297 pc.printf("CALIBRATION_DATA size = %d bytes\n", sizeof(CALIBRATION_DATA)); 00298 pc.printf("Max saves per page = %d\n", FLASH_PAGE_SIZE / sizeof(CALIBRATION_DATA)); 00299 pc.printf("Number of half-words = %d\n", CAL_HALFWORD_COUNT); 00300 pc.printf("Number of words = %d\n", CAL_WORD_COUNT); 00301 pc.printf("Number of double-words = %d\n", CAL_DOUBLEWORD_COUNT); 00302 pc.printf("g_cal.vis_cal_ppb = %2.2f\n", g_cal.vis_cal_ppb); 00303 pc.printf("Page Address: %lX \n", CalPageAddress); 00304 // pc.printf("g_cal.mAOffsetValue = %f\n", g_cal.mAOffsetValue); 00305 00306 00307 00308 //cal_init(); 00309 //increment_data(); 00310 //cal_save(); 00311 00312 //direct(); 00313 00314 // Test 1: empty flash 00315 // Test 2: junk in flash 00316 // Test 3: valid stuff in flash 00317 // Test 4: invalid checksum in flash 00318 // Test 5: Repeated saves - does it loop back correctly ? 00319 00320 00321 } 00322 #endif
Generated on Sat Jul 30 2022 04:25:13 by
1.7.2