STM32 EEPROM Testing
Dependencies: mbed
cal.cpp
- Committer:
- chromaticdeth87
- Date:
- 2018-04-04
- Revision:
- 0:77080c9376de
File content as of revision 0:77080c9376de:
#include "mbed.h" #include "globals.h" #include "cal.h" #define ENABLE_DEBUG_PRINTING 1 // turn on diagnostic printing #define ENABLE_TEST_CODE 1 // turn on self-test code (disable for release) // Must customize which page of flash is used for calibration data // The STM32F334C8 has 32 pages (0..31) so use the last one // Note that on the initial prototype boards, a STM32F334C6 was used #define CAL_PAGE 31 static uint32_t CalPageAddress = FLASH_BASE + (CAL_PAGE * FLASH_PAGE_SIZE); #define CAL_HALFWORD_COUNT (sizeof(CALIBRATION_DATA)/sizeof(uint16_t)) #define CAL_WORD_COUNT (sizeof(CALIBRATION_DATA)/sizeof(uint32_t)) #define CAL_DOUBLEWORD_COUNT (sizeof(CALIBRATION_DATA)/sizeof(uint64_t)) CALIBRATION_DATA g_cal; static uint32_t DataAddress; // address of last saved data static HAL_StatusTypeDef erase_page(uint32_t PageAddress) { HAL_StatusTypeDef Status; FLASH_EraseInitTypeDef EraseInit; uint32_t PageError; EraseInit.TypeErase = FLASH_TYPEERASE_PAGES; EraseInit.PageAddress = PageAddress; //EraseInit.PageAddress = FLASH_BASE + (page_number * FLASH_PAGE_SIZE); EraseInit.NbPages = 1; HAL_FLASH_Unlock(); Status = HAL_FLASHEx_Erase(&EraseInit, &PageError); HAL_FLASH_Lock(); return Status; } static uint16_t calc_checksum() { int i; uint16_t *p; uint16_t checksum; // read cal data from flash in 16 bit chunks p = (uint16_t *)&g_cal; checksum = 0; for (i=0; i < (CAL_HALFWORD_COUNT - 1); i++) { // don't sum checksum field checksum += *p; p++; } return checksum; } static void factory_defaults() { //ppb_per_mv = 100.0f / 871.0f; // From Pyxis with factory cal //ppb_per_mv = 95.3f / (418.0f - 80.0f); // From Megatron and protoboard (reading-dark current) and scope //ppb_per_mv = 95.3f / (418.0f); // From Megatron and protoboard and scope //ppb_per_mv = 0.3225f; // manual 300/930 //ppb_per_mv = 0.305f; // manual 300/981 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) g_cal.uv_cal_mV = 981; // uv adc mV reading at calibration point g_cal.uv_cal_ppb = 300; // uv user ppb value at calibration point g_cal.vis_zero_mV = 81; g_cal.vis_cal_mV = 981; g_cal.vis_cal_ppb = 300; g_cal.trim_4mA = 816; // dac value to use for 4 mA (see mA.cpp) g_cal.trim_20mA = 4080; // dac value to use for 20 mA (see mA.cpp) g_cal.ppb_at_20mA = 300; // factory default 4-20 mA range is 0-300 ppb g_cal.padding = 0; //g_cal.mAOffsetValue = 0.0; g_cal.checksum = calc_checksum(); } void cal_print() { printf("cal data = %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %u, %u, %.0f, %u, %u\n", g_cal.uv_zero_mV, g_cal.uv_cal_mV, g_cal.uv_cal_ppb, g_cal.vis_zero_mV, g_cal.vis_cal_mV, g_cal.vis_cal_ppb, g_cal.trim_4mA, g_cal.trim_20mA, g_cal.ppb_at_20mA, g_cal.padding, g_cal.checksum); } static void read_cal_data(uint32_t address) { int i; uint16_t *p; // read cal data from flash address in 16 bit chunks p = (uint16_t *)&g_cal; for (i=0; i < CAL_HALFWORD_COUNT; i++) { *p = *(__IO uint16_t *)address; // read cal data address += sizeof(uint16_t); p++; } #ifdef ENABLE_DEBUG_PRINTING cal_print(); #endif } void cal_init() { uint32_t address; // Assign factory defaults factory_defaults(); // Start at beginning DataAddress = CalPageAddress; address = CalPageAddress; while (IS_FLASH_PROGRAM_ADDRESS(address)) { uint32_t val; uint8_t *p; p = (uint8_t *)&val; val = *(__IO uint32_t*)address; // read 32 bits (4 bytes) pc.printf("%hhX %hhX %hhX %hhX\n", p[0], p[1], p[2],p[3]); // If the first 4 bytes are all 0xFF, the end of data has been reached if ( (p[0] == 0xFF) && (p[1] == 0xFF) && (p[2] == 0xFF) && (p[3] == 0xFF)) break; #ifdef ENABLE_DEBUG_PRINTING pc.printf("Saved data found at %lX\n", address); #endif // Read cal data (this might not be the last one yet) read_cal_data(address); DataAddress = address; // save last used data address address += sizeof(CALIBRATION_DATA); // Keep looking } // Verify checksum if (g_cal.checksum != calc_checksum()) { #ifdef ENABLE_DEBUG_PRINTING pc.printf("Checksum mismatch, using factory defaults, flash = %u, calc = %u\n", g_cal.checksum, calc_checksum()); #endif factory_defaults(); } #ifdef ENABLE_DEBUG_PRINTING else { pc.printf("Checksum OK\n"); } #endif // Either valid data was found, or factory defaults are set } void cal_save() { int i; uint16_t *p; /* * FLASH_TYPEPROGRAM_HALFWORD is 16 bits * FLASH_TYPEPROGRAM_WORD is 32 bits = sizeof(float) * FLASH_TYPEPROGRAM_DOUBLEWORD is 64 bits * HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data) */ //HAL_StatusTypeDef Status; uint32_t NextDataAddress; // address to use for next saved data uint32_t LastByteAddress; // address of last byte when new data is added NextDataAddress = DataAddress + sizeof(CALIBRATION_DATA); LastByteAddress = NextDataAddress + sizeof(CALIBRATION_DATA) - 1; // First, decide if there is room at the end of the page for new data if (!IS_FLASH_PROGRAM_ADDRESS(LastByteAddress)) { // Erase the entire cal page erase_page(CalPageAddress); // Point to new location NextDataAddress = CalPageAddress; } // Remember the location of the start of the new data DataAddress = NextDataAddress; // Update the checksum g_cal.checksum = calc_checksum(); p = (uint16_t *) &g_cal; HAL_FLASH_Unlock(); for (i=0; i < CAL_HALFWORD_COUNT; i++) { HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, NextDataAddress, (uint64_t )(*p)); NextDataAddress += sizeof(uint16_t); p++; } HAL_FLASH_Lock(); } void cal_factory() { // Set device to factory defaults erase_page(CalPageAddress); cal_init(); cal_save(); } #ifdef ENABLE_TEST_CODE void direct() { int i; //HAL_StatusTypeDef Status; FLASH_EraseInitTypeDef EraseInit; uint32_t PageError; EraseInit.TypeErase = FLASH_TYPEERASE_PAGES; EraseInit.PageAddress = FLASH_BASE + (18 * FLASH_PAGE_SIZE); EraseInit.NbPages = 1; HAL_FLASH_Unlock(); HAL_FLASHEx_Erase(&EraseInit, &PageError); HAL_FLASH_Lock(); printf("\nFlash memory values at start of each page:\n"); for (i=0; i<32; i++) { uint32_t address; uint32_t val; uint8_t *p; p = (uint8_t *)&val; address = FLASH_BASE + (i * FLASH_PAGE_SIZE); val = *(__IO uint32_t*)address; // read 32 bits (4 bytes) printf("%i %hhX %hhX %hhX %hhX\n", i, p[0], p[1], p[2],p[3]); } } static void increment_data() { g_cal.uv_zero_mV += 1; // uv adc mV reading at 0 ppb g_cal.uv_cal_mV += 1; // uv adc mV reading at calibration point g_cal.uv_cal_ppb += 0; // uv user ppb value at calibration point g_cal.vis_zero_mV += 1; g_cal.vis_cal_mV += 1; g_cal.vis_cal_ppb += 1; g_cal.trim_4mA += 1; // dac value to use for 4 mA g_cal.trim_20mA += 1; // dac value to use for 20 mA g_cal.checksum = calc_checksum(); } void cal_test() { pc.printf("\b\nSTM32 Test Flash Memory\n"); pc.printf("Flash page size = %d bytes\n", FLASH_PAGE_SIZE); pc.printf("CALIBRATION_DATA size = %d bytes\n", sizeof(CALIBRATION_DATA)); pc.printf("Max saves per page = %d\n", FLASH_PAGE_SIZE / sizeof(CALIBRATION_DATA)); pc.printf("Number of half-words = %d\n", CAL_HALFWORD_COUNT); pc.printf("Number of words = %d\n", CAL_WORD_COUNT); pc.printf("Number of double-words = %d\n", CAL_DOUBLEWORD_COUNT); pc.printf("g_cal.vis_cal_ppb = %2.2f\n", g_cal.vis_cal_ppb); pc.printf("Page Address: %lX \n", CalPageAddress); // pc.printf("g_cal.mAOffsetValue = %f\n", g_cal.mAOffsetValue); //cal_init(); //increment_data(); //cal_save(); //direct(); // Test 1: empty flash // Test 2: junk in flash // Test 3: valid stuff in flash // Test 4: invalid checksum in flash // Test 5: Repeated saves - does it loop back correctly ? } #endif