STM32 EEPROM Testing
Dependencies: mbed
Revision 0:77080c9376de, committed 2018-04-04
- Comitter:
- chromaticdeth87
- Date:
- Wed Apr 04 15:16:19 2018 +0000
- Commit message:
- This is the Test for the Flash to EEPROM operations on STM32F334C8T6
Changed in this revision
diff -r 000000000000 -r 77080c9376de cal.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cal.cpp Wed Apr 04 15:16:19 2018 +0000 @@ -0,0 +1,322 @@ +#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 \ No newline at end of file
diff -r 000000000000 -r 77080c9376de cal.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cal.h Wed Apr 04 15:16:19 2018 +0000 @@ -0,0 +1,32 @@ +#ifndef CAL_H +#define CAL_H + + +typedef struct { + float uv_zero_mV; // uv adc mV reading at 0 ppb + float uv_cal_mV; // uv adc mV reading at calibration point + float uv_cal_ppb; // uv user ppb value at calibration point + + float vis_zero_mV; + float vis_cal_mV; + float vis_cal_ppb; + + uint16_t trim_4mA; // 12-bit dac value to use for 4 mA + uint16_t trim_20mA; // 12-bit dac value to use for 20 mA + float ppb_at_20mA; // ppb value equal to 20 mA, zero is assumed at 4 + + uint16_t padding; // needed to create multiple of 2 bytes + //double mAOffsetValue; //mA Offset Value for simulator project. + uint16_t checksum; + +} CALIBRATION_DATA; // compiler makes this a multiple of 2 bytes (half-word) + +extern CALIBRATION_DATA g_cal; + +void cal_init(); +void cal_save(); +void cal_print(); +void cal_factory(); +void cal_test(); + +#endif \ No newline at end of file
diff -r 000000000000 -r 77080c9376de globals.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/globals.h Wed Apr 04 15:16:19 2018 +0000 @@ -0,0 +1,15 @@ +#ifndef GLOBALS_H +#define GLOBALS_H +/* globals.h */ + +#define EMIT_OFF 0 +#define EMIT_ON 1 + +extern SPI g_SPI1; + +extern Serial pc; +extern int g_rx_char; +extern uint32_t g_optics_timer_ms; +extern int g_emit_mode; + +#endif \ No newline at end of file
diff -r 000000000000 -r 77080c9376de main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Apr 04 15:16:19 2018 +0000 @@ -0,0 +1,83 @@ +#include "mbed.h" +#include "cal.h" + + +/*------------------------------------------------------------------------------ +Before to use this example, ensure that you an hyperterminal installed on your +computer. More info here: https://developer.mbed.org/handbook/Terminals + +The default serial comm port uses the SERIAL_TX and SERIAL_RX pins (see their +definition in the PinNames.h file). + +The default serial configuration in this case is 9600 bauds, 8-bit data, no parity + +If you want to change the baudrate for example, you have to redeclare the +serial object in your code: + +Serial pc(SERIAL_TX, SERIAL_RX); + +Then, you can modify the baudrate and print like this: + +pc.baud(115200); +pc.printf("Hello World !\n"); +------------------------------------------------------------------------------*/ +BusOut FunctionLEDs(PB_15, PA_8); +BusOut LevelLEDs(PA_11,PA_12); + +Serial pc(PA_9, PA_10); //tx,rx + + +//StartupLEDs +#define Blank 0x00 +#define AllLEDs 0xFF + +//Function LED Defines +#define pHG 0x01 +#define ORPG 0x02 +#define mAOutput 0x04 + +//LevelOut LED Defines +#define LowLED 0x01 +#define MidLED 0x02 +#define HighLED 0x04 + + + +int main() +{ + pc.baud(115200); + + //cal_test(); + + + //initialize Calibration Data + //cal_init(); + + cal_test(); + cal_factory(); + cal_test(); + cal_init(); + cal_test(); + g_cal.vis_cal_ppb = 2.0; + cal_save(); + cal_init(); + cal_test(); + + //cal_init(); + //cal_test(); + + + + + + //cal_test(); + //cal_init(); + //cal_test(); + //g_cal.vis_cal_ppb = 2.0; + //cal_save(); + // cal_test(); + + + + +}
diff -r 000000000000 -r 77080c9376de mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Wed Apr 04 15:16:19 2018 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/mbed_official/code/mbed/builds/994bdf8177cb \ No newline at end of file