STM32 EEPROM Testing

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers cal.cpp Source File

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