/********************************************************************** * NAME: eeprom.c * * AUTHOR: Philip Johansson * * PURPOSE: Virtual EEPROM driver * * INFORMATION: * * This file mainly has two functions of which one brings the settings * * from EEPROM and the other stores them * * * * All values we want in EEPROM have to be added to the EEPROM_ID_t * * struct as well as defined in eeprom_Arr with a pointer to the data * * * * GLOBAL VARIABLES: * * Variable Type Description * * -------- ---- ----------- * * * **********************************************************************/ #include "config/eeprom.h" #include "drivers/adc.h" #include "drivers/uart1_inverter.h" #include "system_variables.h" #include "utilities.h" /* Reads the EEPROM version from EEPROM - Is compared to EEPROM_SYS_VERSION */ uint8_t stored_eeprom_identifier; /* Buffer where we temporarily store profiles we not use as we erase eeprom before write */ uint32_t eeprom_profile_tmp_a[EEPROM_PROFILE_SIZE]; uint32_t eeprom_profile_tmp_b[EEPROM_PROFILE_SIZE]; /* Created CRC */ uint8_t calculated_crc; uint8_t read_crc; uint8_t active_profile = 0; typedef enum { EEPROM_VERSION = 0, /* Counts the amount of system settings */ EEPROM_HEADER_COUNT } EEPROM_HEADER_ID_t; /*********************************************************************** * BRIEF: List of all System EEPROM values * * INFORMATION: This content of this struct will be used in EEPROM * ***********************************************************************/ typedef enum { EEPROM_ACTIVE_PROFILE = 0, EEPROM_ADC_SCALES, EEPROM_UART1_RX_INV, /* Counts the amount of system settings */ EEPROM_SYS_COUNT } EEPROM_SYS_ID_t; /*********************************************************************** * BRIEF: List of all Profile EEPROM values * * INFORMATION: This content of this struct will be used in EEPROM * ***********************************************************************/ typedef enum { EEPROM_PID_ROLL_KP = 0, /* Counts the amount of settings in profile */ EEPROM_PROFILE_COUNT } EEPROM_PROFILE_ID_t; typedef enum { EEPROM_CRC = 0, /* Counts the amount of system settings */ EEPROM_FOOTER_COUNT } EEPROM_FOOTER_ID_t; uint8_t eeprom_blocksize_Arr[4] = { EEPROM_HEADER_COUNT, EEPROM_SYS_COUNT, EEPROM_PROFILE_COUNT, EEPROM_FOOTER_COUNT }; /*********************************************************************** * BRIEF: General EEPROM data info * * INFORMATION: Each EEPROM parameter needs an instance of this struct * * to be added in eepromArr * ***********************************************************************/ typedef struct { uint32_t writeTypeId; uint32_t size; //Size of the data void * dataPtr; //pointer to the data, that should be saved to EEPROM } EEPROM_DATA_t; /*********************************************************************** * BRIEF: Data info to be passed to the write function * * INFORMATION: passes size and data pointer * ***********************************************************************/ EEPROM_DATA_t eeprom_header_Arr[EEPROM_HEADER_COUNT] = { [EEPROM_VERSION] = { .size = sizeof(stored_eeprom_identifier), .dataPtr = &stored_eeprom_identifier, } }; EEPROM_DATA_t eeprom_sys_Arr[EEPROM_SYS_COUNT] = { [EEPROM_ACTIVE_PROFILE] = { .size = sizeof(active_profile), .dataPtr = &active_profile, }, [EEPROM_ADC_SCALES] = { .size = sizeof(adcScaleStruct_t), .dataPtr = &adcScaleStruct_t, }, [EEPROM_UART1_RX_INV] = { .size = sizeof(bool), .dataPtr = &uart1_rx_inverter, } }; EEPROM_DATA_t eeprom_profile_Arr[EEPROM_PROFILE_COUNT] = { [EEPROM_PID_ROLL_KP] = { .size = sizeof(pid_pitch_pk), .dataPtr = &pid_pitch_pk, } }; EEPROM_DATA_t eeprom_footer_Arr[EEPROM_FOOTER_COUNT] = { [EEPROM_CRC] = { .size = sizeof(calculated_crc), .dataPtr = &calculated_crc, } }; /* to loop through these arrays*/ EEPROM_DATA_t * eeprom_Arr_list[4] = { eeprom_header_Arr, eeprom_sys_Arr, eeprom_profile_Arr, eeprom_footer_Arr }; uint16_t eepromArrSize(EEPROM_DATA_t * data) { int size = 0; for (int j = 0; j < 4; j++) { if (data == eeprom_Arr_list[j]) for (int i = 0; i < eeprom_blocksize_Arr[j]; i++) { size += data[i].size; } } if (size == 0) Error_Handler(); // We should never get here return size; } /*********************************************************************** * BRIEF: Increments the checksum * * INFORMATION: * ***********************************************************************/ uint8_t incrementChecksum(uint8_t crc, const void *data, uint32_t length) { const uint8_t * addrIterator = (const uint8_t *)data; const uint8_t * addrEnd = addrIterator + length; for (;addrIterator != addrEnd; addrIterator++) crc ^= *addrIterator; return crc; } /*********************************************************************** * BRIEF: Stores one data type at the time from eepromArr to EEPROM * * INFORMATION: Writes byte per byte until end of data * ***********************************************************************/ void writeEepromExtension(uint32_t addr,EEPROM_DATA_t * data, uint32_t id) { for (int i = 0; i < data[id].size; i ++) HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, addr + i , *((uint8_t*)(data[id].dataPtr + i))); } /*********************************************************************** * BRIEF: Writes EEPROM data to FLASH * * INFORMATION: passes all data directly from where they are defined * ***********************************************************************/ void writeEEPROM() { /* Add size and a pointer to the data for each value * Each value when saved will store the data that it points to. * When loaded the system will know what the value for each id should * point to and it can read the data directly to that value which is pointed to*/ uint32_t addrIterator = EEPROM_BASE_ADDR; uint8_t crc = 0; // Initializing the checksum to 0 HAL_FLASH_Unlock(); __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGSERR ); FLASH_Erase_Sector(((uint32_t)FLASH_SECTOR_11),VOLTAGE_RANGE_3); stored_eeprom_identifier = (uint8_t)EEPROM_SYS_VERSION; for (int j = 0; j < 4; j++) { for (int i = 0; i < eeprom_blocksize_Arr[j]; i++) { if (eeprom_Arr_list[j] == eeprom_footer_Arr) calculated_crc = crc; writeEepromExtension(addrIterator, eeprom_Arr_list[j], i); addrIterator += eeprom_Arr_list[j][i].size; crc = incrementChecksum(crc, eeprom_Arr_list[j][i].dataPtr, eeprom_Arr_list[j][i].size); } } // // /* Write the Header and calc CRC */ // for (int i = 0; i < EEPROM_HEADER_COUNT; i ++) // { // writeEepromExtension(addrIterator, eeprom_header_Arr, i); // addrIterator += eeprom_header_Arr[i].size; // crc = incrementChecksum(crc, eeprom_header_Arr[i].dataPtr, eeprom_header_Arr[i].size); // } // // /* Write the system settings and calc CRC */ // for (int i = 0; i < EEPROM_SYS_COUNT; i ++) // { // writeEepromExtension(addrIterator, eeprom_sys_Arr, i); // addrIterator += eeprom_sys_Arr[i].size; // crc = incrementChecksum(crc, eeprom_sys_Arr[i].dataPtr, eeprom_sys_Arr[i].size); // } // /* Write the profile and calc CRC */ // for (int i = 0; i < EEPROM_PROFILE_COUNT; i ++) // { // writeEepromExtension(addrIterator, eeprom_profile_Arr, i); // addrIterator += eeprom_profile_Arr[i].size; // crc = incrementChecksum(crc, eeprom_profile_Arr[i].dataPtr, eeprom_profile_Arr[i].size); // } // // // Updating the calculated crc value before writing to EEPROM // calculated_crc = crc; // // /* Write the CRC to footer */ // for (int i = 0; i < EEPROM_FOOTER_COUNT; i ++) // { // writeEepromExtension(addrIterator, eeprom_footer_Arr, i); // addrIterator += eeprom_footer_Arr[i].size; // } HAL_FLASH_Lock(); } /*********************************************************************** * BRIEF: Restores one data type at the time from eepromArr from EEPROM * * INFORMATION: * ***********************************************************************/ void readEepromExtension(uint32_t addr, EEPROM_DATA_t * data, uint32_t id) { for (int i = 0; i < data[id].size; i++) *(uint8_t*)(data[id].dataPtr + i) = *( uint8_t*)(addr + i * sizeof(uint8_t)); } // Verifies that eeprom is not corrupt and that the EEPROM version is correct bool scanEEPROM(void) { uint8_t crc = 0; uint8_t old_crc = calculated_crc; // store to restore uint32_t addrIterator = EEPROM_BASE_ADDR; HAL_FLASH_Unlock(); HAL_Delay(100); for (int j = 0; j < 4; j++) { for (int i = 0; i < eeprom_blocksize_Arr[j]; i++) { if ((eeprom_Arr_list[j] == eeprom_header_Arr) || (eeprom_Arr_list[j] == eeprom_footer_Arr)) readEepromExtension(addrIterator, eeprom_Arr_list[j], i); if (eeprom_Arr_list[j] != eeprom_footer_Arr) crc = incrementChecksum(crc, (int*)addrIterator, eeprom_Arr_list[j][i].size); addrIterator += eeprom_Arr_list[j][i].size; } } // /* Read the Header */ // for (int i = 0; i < EEPROM_HEADER_COUNT; i ++) // { // readEepromExtension(addrIterator, eeprom_header_Arr, i); // crc = incrementChecksum(crc, addrIterator, eeprom_header_Arr[i].size); // addrIterator += eeprom_header_Arr[i].size; // } // // /* Read the system array */ // for (int i = 0; i < EEPROM_SYS_COUNT; i ++) // { // crc = incrementChecksum(crc, addrIterator, eeprom_sys_Arr[i].size); // addrIterator += eeprom_sys_Arr[i].size; // } // // /* Read the profile array */ // for (int i = 0; i < EEPROM_PROFILE_COUNT; i ++) // { // crc = incrementChecksum(crc, addrIterator, eeprom_profile_Arr[i].size); // addrIterator += eeprom_profile_Arr[i].size; // } // // /* Read the Footer */ // for (int i = 0; i < EEPROM_FOOTER_COUNT; i ++) // { // readEepromExtension(addrIterator, eeprom_footer_Arr, i); // addrIterator += eeprom_footer_Arr[i].size; // } HAL_FLASH_Lock(); /* Check to see if CRC matches */ if ( (crc == calculated_crc) && (stored_eeprom_identifier == (uint8_t)EEPROM_SYS_VERSION) ) { return true; } else { calculated_crc = old_crc; //Error_Handler(); // Reinitialize eeprom with default values. return false; } } /*********************************************************************** * BRIEF: Reads EEPROM data from FLASH * * INFORMATION: passes all data directly to where they are defined * ***********************************************************************/ void readEEPROM() { uint32_t addrIterator = EEPROM_BASE_ADDR; /* This check has to be done as not to overwrite memory with bad data */ if (scanEEPROM()) { HAL_FLASH_Unlock(); HAL_Delay(100); for (int j = 0; j < 3; j++) // 3 excludes the footer { for (int i = 0; i < eeprom_blocksize_Arr[j]; i++) { readEepromExtension(addrIterator, eeprom_Arr_list[j], i); addrIterator += eeprom_Arr_list[j][i].size; } } // /* Read the Header */ // for (int i = 0; i < EEPROM_HEADER_COUNT; i ++) // { // readEepromExtension(addrIterator, eeprom_header_Arr, i); // addrIterator += eeprom_header_Arr[i].size; // } // // /* Read the system array */ // for (int i = 0; i < EEPROM_SYS_COUNT; i ++) // { // readEepromExtension(addrIterator, eeprom_sys_Arr, i); // addrIterator += eeprom_sys_Arr[i].size; // } // // /* Read the profile array */ // for (int i = 0; i < EEPROM_PROFILE_COUNT; i ++) // { // readEepromExtension(addrIterator, eeprom_profile_Arr, i); // addrIterator += eeprom_profile_Arr[i].size; // } // Now there is no need to read the footer HAL_FLASH_Lock(); } else { } }