This repository has been archived on 2020-06-14. You can view files and clone it, but cannot push or open issues or pull requests.
philsson d72e7e099b New mixer mode implemented with low scaling. Renaming of Airmode into Full scale
Implemented new modes in cli
Fixed bugg in motors.c cutting out max value
2016-10-17 14:34:09 +02:00

627 lines
19 KiB
C

/**********************************************************************
* 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"
#include "stm32f4xx_revo.h"
#include "Scheduler/scheduler.h"
#include "drivers/failsafe_toggles.h"
#include "drivers/motormix.h"
#include "drivers/motors.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 */
uint8_t eeprom_profile_tmp_a[EEPROM_PROFILE_SIZE];
uint8_t eeprom_profile_tmp_b[EEPROM_PROFILE_SIZE];
/* The two temporary buffers are addressed through this array */
uint8_t * eeprom_profile_tmp_Arr[2] = {
eeprom_profile_tmp_a,
eeprom_profile_tmp_b
};
/* Created CRC */
uint8_t calculated_crc;
uint8_t read_crc;
/* Defines which profile is active. Should not be changed other than calling setActiveProfile() */
ACTIVE_PROFILE active_profile = 1; // Between 1 .. 3
/* List of all EEPROM lists */
uint8_t eeprom_blocksize_Arr[4] = {
EEPROM_HEADER_COUNT,
EEPROM_SYS_COUNT,
EEPROM_PROFILE_COUNT,
EEPROM_FOOTER_COUNT
};
/* General EEPROM data info. All data addressed needs both size and pointer */
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;
/* Data pointers and sizes for header content */
EEPROM_DATA_t eeprom_header_Arr[EEPROM_HEADER_COUNT] = {
[EEPROM_VERSION] =
{
.size = sizeof(stored_eeprom_identifier),
.dataPtr = &stored_eeprom_identifier,
}
};
/* Data pointers and sizes for sys content */
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,
},
/* Motor calibrate */
[EEPROM_MOTORCALIBRATE] =
{
.size = sizeof(bool),
.dataPtr = &perfromMotorCalibration,
},
/* Task eeprom values */
[EEPROM_PERIOD_SYSTEM] =
{
.size = sizeof(SystemTasks[TASK_SYSTEM].desiredPeriod),
.dataPtr = &(SystemTasks[TASK_SYSTEM].desiredPeriod),
},
[EEPROM_PERIOD_GYROPID] =
{
.size = sizeof(SystemTasks[TASK_GYROPID].desiredPeriod),
.dataPtr = &(SystemTasks[TASK_GYROPID].desiredPeriod),
},
[EEPROM_PERIOD_ACCELEROMETER] =
{
.size = sizeof(SystemTasks[TASK_ACCELEROMETER].desiredPeriod),
.dataPtr = &(SystemTasks[TASK_ACCELEROMETER].desiredPeriod),
},
[EEPROM_PERIOD_ATTITUDE] =
{
.size = sizeof(SystemTasks[TASK_ATTITUDE].desiredPeriod),
.dataPtr = &(SystemTasks[TASK_ATTITUDE].desiredPeriod),
},
[EEPROM_PERIOD_RX] =
{
.size = sizeof(SystemTasks[TASK_RX].desiredPeriod),
.dataPtr = &(SystemTasks[TASK_RX].desiredPeriod),
},
[EEPROM_PERIOD_RX_CLI] =
{
.size = sizeof(SystemTasks[TASK_RX_CLI].desiredPeriod),
.dataPtr = &(SystemTasks[TASK_RX_CLI].desiredPeriod),
},
[EEPROM_PERIOD_SERIAL] =
{
.size = sizeof(SystemTasks[TASK_SERIAL].desiredPeriod),
.dataPtr = &(SystemTasks[TASK_SERIAL].desiredPeriod),
},
[EEPROM_PERIOD_BATTERY] =
{
.size = sizeof(SystemTasks[TASK_BATTERY].desiredPeriod),
.dataPtr = &(SystemTasks[TASK_BATTERY].desiredPeriod),
},
#ifdef BARO
[EEPROM_PERIOD_BARO] =
{
.size = sizeof(SystemTasks[TASK_BARO].desiredPeriod),
.dataPtr = &(SystemTasks[TASK_BARO].desiredPeriod),
},
#endif
#ifdef COMPASS
[EEPROM_PERIOD_COMPASS] =
{
.size = sizeof(SystemTasks[TASK_COMPASS].desiredPeriod),
.dataPtr = &(SystemTasks[TASK_COMPASS].desiredPeriod),
},
#endif
#ifdef GPS
[EEPROM_PERIOD_GPS] =
{
.size = sizeof(SystemTasks[TASK_GPS].desiredPeriod),
.dataPtr = &(SystemTasks[TASK_GPS].desiredPeriod),
},
#endif
#ifdef SONAR
[EEPROM_PERIOD_SONAR] =
{
.size = sizeof(SystemTasks[TASK_SONAR].desiredPeriod),
.dataPtr = &(SystemTasks[TASK_SONAR].desiredPeriod),
},
#endif
#if defined(BARO) || defined(SONAR)
[EEPROM_PERIOD_ALTITUDE] =
{
.size = sizeof(SystemTasks[TASK_ALTITUDE].desiredPeriod),
.dataPtr = &(SystemTasks[TASK_ALTITUDE].desiredPeriod),
},
#endif
#if BEEPER
[EEPROM_PERIOD_BEEPER] =
{
.size = sizeof(SystemTasks[TASK_BEEPER].desiredPeriod),
.dataPtr = &(SystemTasks[TASK_BEEPER].desiredPeriod),
},
#endif
/* Motormix values */
[EEPROM_MOTORMIX_CONFIG] =
{
.size = sizeof(mixerConfig_s),
.dataPtr = &(mixerConfig),
},
/* Flags eeprom values */
[EEPROM_FLAG_ARM] =
{
.size = sizeof(flags_Configuration_t),
.dataPtr = &(flagConfigArr[FLAG_CONFIGURATION_ARM]),
},
[EEPROM_FLAG_FLIGHTMODE_ACCELEROMETER] =
{
.size = sizeof(flags_Configuration_t),
.dataPtr = &(flagConfigArr[FLAG_CONFIGURATION_FLIGHTMODE_ACCELEROMETER]),
},
[EEPROM_FLAG_FLIGHTMODE_BAROMETER] =
{
.size = sizeof(flags_Configuration_t),
.dataPtr = &(flagConfigArr[FLAG_CONFIGURATION_FLIGHTMODE_BAROMETER]),
},
[EEPROM_FLAG_FLIGHTMODE_COMPASS] =
{
.size = sizeof(flags_Configuration_t),
.dataPtr = &(flagConfigArr[FLAG_CONFIGURATION_FLIGHTMODE_COMPASS]),
},
[EEPROM_FLAG_FLIGHTMODE_GPS] =
{
.size = sizeof(flags_Configuration_t),
.dataPtr = &(flagConfigArr[FLAG_CONFIGURATION_FLIGHTMODE_GPS]),
},
[EEPROM_FLAG_MIXERFULLSCALE] =
{
.size = sizeof(flags_Configuration_t),
.dataPtr = &(flagConfigArr[FLAG_CONFIGURATION_MIXERFULLSCALE]),
},
[EEPROM_FLAG_MIXERLOWSCALE] =
{
.size = sizeof(flags_Configuration_t),
.dataPtr = &(flagConfigArr[FLAG_CONFIGURATION_MIXERLOWSCALE]),
},
[EEPROM_FLAG_FLIGHTMODE_3] =
{
.size = sizeof(flags_Configuration_t),
.dataPtr = &(flagConfigArr[FLAG_CONFIGURATION_FLIGHTMODE_3]),
},
};
/* Data pointers and sizes for profile content */
EEPROM_DATA_t eeprom_profile_Arr[EEPROM_PROFILE_COUNT] = {
[EEPROM_PID_ROLL_KP] =
{
.size = sizeof(pid_pitch_pk),
.dataPtr = &pid_pitch_pk,
}
};
/* Data pointers and sizes for footer content */
EEPROM_DATA_t eeprom_footer_Arr[EEPROM_FOOTER_COUNT] = {
[EEPROM_CRC] =
{
.size = sizeof(calculated_crc),
.dataPtr = &calculated_crc,
}
};
/* List of all EEPROM content arrays */
EEPROM_DATA_t * eeprom_Arr_list[4] = {
eeprom_header_Arr,
eeprom_sys_Arr,
eeprom_profile_Arr,
eeprom_footer_Arr
};
/***********************************************************************
* BRIEF: Reads Calculates the combined size of all elements *
* in an EEPROM_DATA_t array *
* INFORMATION: return value is in bytes *
***********************************************************************/
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: XOR operator byte per byte *
***********************************************************************/
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. Requires the next active profile *
* to be selected (current profile can be used as input) *
* INFORMATION: passes all data directly from where they are defined *
***********************************************************************/
void writeEEPROM(uint8_t new_profile)
{
/* 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
uint8_t profile_counter = 0;
uint8_t buff_counter = 0;
ACTIVE_PROFILE old_profile = active_profile;
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)11U),VOLTAGE_RANGE_3);
FLASH_Erase_Sector(EEPROM_SECTOR_ERASE, VOLTAGE_RANGE_3);
stored_eeprom_identifier = (uint8_t)EEPROM_SYS_VERSION;
for (int j = 0; j < 4; j++)
{
// We exclude reading of profiles not active to memory
if (!((j == 2) && (profile_counter != ((uint8_t)active_profile - 1) )))
{
if (j == 1) // Writing sys we store the NEW profile
active_profile = new_profile;
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);
}
if (j == 1)
active_profile = old_profile; // restore the old profile
}
else
{
if (buff_counter >= 2)
Error_Handler();
int eeprom_profile_arr_size = eepromArrSize(eeprom_profile_Arr);
for (int i = 0; i < eeprom_profile_arr_size; i ++)
HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, addrIterator + i , *((uint8_t*)(eeprom_profile_tmp_Arr[buff_counter] + i)));
crc = incrementChecksum(crc, eeprom_profile_tmp_Arr[buff_counter], eepromArrSize(eeprom_profile_Arr));
buff_counter++; // move on to next buffer
// Adding size of eeprom array
addrIterator += eeprom_profile_arr_size;
}
// Halt iterator j @2 (profile) for 3 iterations (3 profiles)
if ((j == 2) && (profile_counter < 2))
{
profile_counter++;
j--; // We do this to keep j = 2 for three iterations (looping through all profiles)
}
}
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));
}
/***********************************************************************
* BRIEF: Copies a profile from EEPROM into a buffer *
* INFORMATION: Run once for every buffer *
***********************************************************************/
void readEepromBuff(uint32_t addr, uint8_t * eeprom_profile_tmp, uint32_t length)
{
for (int i = 0; i < length; i++)
*(uint8_t*)(eeprom_profile_tmp + i) = *(uint8_t*)(addr + i * sizeof(uint8_t));
}
/***********************************************************************
* BRIEF: Verifies EEPROM only *
* INFORMATION: compares EEPROM version and makes CRC checks *
* Return value is true if okay *
***********************************************************************/
bool scanEEPROM(void)
{
uint8_t crc = 0;
uint8_t old_crc = calculated_crc; // store to restore
uint8_t profile_counter = 0; // To iterate through the profiles
uint32_t addrIterator = EEPROM_BASE_ADDR;
HAL_FLASH_Unlock();
HAL_Delay(100);
for (int j = 0; j < 4; j++) // 3 to skip footer from CRC calculation
{
for (int i = 0; i < eeprom_blocksize_Arr[j]; i++)
{
// Store data only for Header (EEPROM version) and footer (CRC) while scanning
if ((eeprom_Arr_list[j] == eeprom_header_Arr) || (eeprom_Arr_list[j] == eeprom_footer_Arr))
readEepromExtension(addrIterator, eeprom_Arr_list[j], i);
// Checksum not incremented for footer
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;
}
// Halt iterator j @2 (profile) for 3 iterations (3 profiles)
if ((j == 2) && (profile_counter < 2))
{
profile_counter++;
j--; // We do this to keep j = 2 for three iterations (looping through all profiles)
}
}
HAL_FLASH_Lock();
/* Check to see if CRC matches */
if ( (crc == calculated_crc) && (stored_eeprom_identifier == (uint8_t)EEPROM_SYS_VERSION) )
{
return true;
}
else
{
// ERROR!!! CORRUPT EEPROM, RESETTING
calculated_crc = old_crc;
#ifdef USE_DEBUG_EEPROM
Error_Handler();
#endif
resetEEPROM(); // Reinitialize eeprom with default values.
return true /* false */;
}
}
/***********************************************************************
* BRIEF: Reads EEPROM data from FLASH *
* INFORMATION: passes all data directly to where they are defined *
***********************************************************************/
bool readEEPROM()
{
bool success;
uint8_t profile_counter = 0;
uint8_t buff_counter = 0;
uint32_t addrIterator = EEPROM_BASE_ADDR;
/* This check has to be done as not to overwrite memory with bad data */
if ((success = scanEEPROM()))
{
HAL_FLASH_Unlock();
HAL_Delay(100);
for (int j = 0; j < 3; j++) // 3 excludes the footer
{
// We exclude reading of profiles not active to memory
if (!((j == 2) && (profile_counter != (uint8_t)(active_profile - 1))))
{
for (int i = 0; i < eeprom_blocksize_Arr[j]; i++)
{
readEepromExtension(addrIterator, eeprom_Arr_list[j], i);
addrIterator += eeprom_Arr_list[j][i].size;
}
}
// The two not loaded profiles are stored to buffers
else
{
if (buff_counter >= 2)
Error_Handler();
// Import the data from eeprom to buffer
readEepromBuff((uint32_t*)addrIterator, (uint8_t*)eeprom_profile_tmp_Arr[buff_counter], EEPROM_PROFILE_SIZE);
buff_counter++;
// Adding size of eeprom array
addrIterator += eepromArrSize(eeprom_profile_Arr);
}
// Halt iterator j @2 (profile) for 3 iterations (3 profiles)
if ((j == 2) && (profile_counter < 2))
{
profile_counter++;
j--; // We do this to keep j = 2 for three iterations (looping through all profiles)
}
}
HAL_FLASH_Lock();
}
else
{
Error_Handler();
}
return success;
}
/***********************************************************************
* BRIEF: Choose a profile between 1 .. 3 *
* INFORMATION: The current changes will be saved *
***********************************************************************/
void setActiveProfile(ACTIVE_PROFILE new_profile)
{
// Error handler
if (new_profile < 1 || new_profile > 3)
Error_Handler();
writeEEPROM(new_profile);
readEEPROM();
}
/***********************************************************************
* BRIEF: Writes current profile values to all EEPROM profiles *
* INFORMATION: used when EEPROM is corrupt or there is a version *
* mismatch *
***********************************************************************/
void resetEEPROM(void)
{
/* check so that the profile buffer sizes are not smaller than the size of one profile */
if (EEPROM_PROFILE_SIZE < eepromArrSize(eeprom_profile_Arr) )
Error_Handler(); // We need to increment the EEPROM_PROFILE_SIZE
uint32_t bufferIterator = 0;
//Loop through all the values in the EEPROM profile
for (int j = 0; j < EEPROM_PROFILE_COUNT; j++)
{
//for each value loop on its byte size and then write byte by byte to the buffers
for (int i = 0; i < eeprom_profile_Arr[i].size; i++)
{
*(uint8_t*)(eeprom_profile_tmp_Arr[0] + bufferIterator) = *(uint8_t*)(eeprom_profile_Arr[j].dataPtr + i);
*(uint8_t*)(eeprom_profile_tmp_Arr[1] + bufferIterator) = *(uint8_t*)(eeprom_profile_Arr[j].dataPtr + i);
bufferIterator++;
}
}
writeEEPROM(active_profile);
}
/***********************************************************************
* BRIEF: Writes EEPROM data to FLASH without the need of setting next *
* active profile *
* INFORMATION: Keeps the current profile active *
***********************************************************************/
void saveEEPROM()
{
writeEEPROM(active_profile);
}
void * getDataAddresFromID(uint16_t id, uint8_t dataType)
{
void * toReturn = NULL;
//switch on the dataType to return it will return from a different array of data
//one for system vars another for the profile vars etc
switch(dataType)
{
case EEPROM_VALUE_TYPE_SYSTEM:
toReturn = eeprom_sys_Arr[id].dataPtr;
break;
case EEPROM_VALUE_TYPE_PROFILE:
toReturn = eeprom_profile_Arr[id].dataPtr;
break;
case EEPROM_VALUE_TYPE_HEADER:
toReturn = eeprom_header_Arr[id].dataPtr;
break;
case EEPROM_VALUE_TYPE_FOOTER:
toReturn = eeprom_footer_Arr[id].dataPtr;
break;
default:
break;
}
return toReturn;
}
void defaultEEPROM(void)
{
//Erase the secotr
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(EEPROM_SECTOR_ERASE, VOLTAGE_RANGE_3);
HAL_FLASH_Lock();
//Reboot the system
HAL_NVIC_SystemReset();
}
int getActiveProfile()
{
return active_profile;
}