STM32 EEPROM Testing
Dependencies: mbed
Diff: cal.cpp
- Revision:
- 0:77080c9376de
--- /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