STM32 EEPROM Testing

Dependencies:   mbed

Files at this revision

API Documentation at this revision

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

cal.cpp Show annotated file Show diff for this revision Revisions of this file
cal.h Show annotated file Show diff for this revision Revisions of this file
globals.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
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