Большой апгрейд:
- исправлены баги библиотеки memspi - добавлены модули для сохранения настреок в eeprom и flash (с равномерным износом) - надо тестить, проверять и рефакторить
This commit is contained in:
380
Src/set_to_mem.c
Normal file
380
Src/set_to_mem.c
Normal file
@@ -0,0 +1,380 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file set_to_mem.c
|
||||
* @brief Модуль для записи в память настроек.
|
||||
*************************************************************************/
|
||||
#include "set_to_mem.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Инициализация одного массива настроек для хранения в памяти.
|
||||
*
|
||||
* @param array Указатель на структуру для записи настроек.
|
||||
* @param pRealArray Указатель на реальные массива настроек.
|
||||
* @param startadr Указатель на начальный адрес в памяти.
|
||||
* @param sizeofarray Размер массива.
|
||||
* @details Функция используется при @ref SETTINGS_USE_SETTINGS_FROM_POINTER
|
||||
*/
|
||||
HAL_StatusTypeDef Settings_AddArray(SettingsTypeDef *settings, uint8_t *pRealArray, uint32_t *startadr, uint32_t sizeofarray)
|
||||
{
|
||||
if(!settings || !pRealArray || !startadr || !sizeofarray)
|
||||
return HAL_ERROR;
|
||||
|
||||
if(settings->setarr_count >= SETTINGS_MAX_ARRAYS)
|
||||
return HAL_ERROR;
|
||||
|
||||
SettingArrayTypeDef *array = &settings->setarr[settings->setarr_count];
|
||||
|
||||
array->adr = *startadr; // Устанавливаем адрес начала массива настроек
|
||||
array->length = sizeofarray; // Устанавливаем размер массива настроек
|
||||
array->real_ptr = pRealArray;
|
||||
|
||||
|
||||
#ifdef SETTINGS_USE_SETTINGS_FROM_POINTER
|
||||
array->mem_ptr = pRealArray;
|
||||
#else
|
||||
if(settings->buffer == NULL)
|
||||
{
|
||||
settings->buffer = malloc(sizeofarray);
|
||||
if(!settings->buffer)
|
||||
return HAL_ERROR;
|
||||
array->mem_ptr = settings->buffer;
|
||||
settings->settings_size = sizeofarray;
|
||||
}
|
||||
else
|
||||
{
|
||||
// расширяем буфер под новый массив
|
||||
uint8_t *newbuf = realloc(settings->buffer, settings->settings_size + sizeofarray);
|
||||
if(!newbuf)
|
||||
return HAL_ERROR;
|
||||
settings->buffer = newbuf;
|
||||
array->mem_ptr = settings->buffer + settings->settings_size;
|
||||
settings->settings_size += sizeofarray;
|
||||
}
|
||||
#endif
|
||||
|
||||
*startadr += array->length; // Смещаем начальный адрес настроек
|
||||
settings->setarr_count++;
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef Settings_Init(SettingsTypeDef *settings, SPI_HandleTypeDef *hspi, uint32_t adr)
|
||||
{
|
||||
if(!settings)
|
||||
return HAL_ERROR;
|
||||
|
||||
settings->start_adr = adr;
|
||||
// settings->setarr_count = 0;
|
||||
settings->settings_error = 0;
|
||||
settings->hmemspi = &memory_spi;
|
||||
|
||||
MEMSPI_Base_Init(settings->hmemspi, hspi);
|
||||
|
||||
#ifdef SETTINGS_USE_WEAR_LEVELING_FLASH
|
||||
if(MEMSPI_FLASH_Protection(&memory_spi, 0, 0x11000, 1000, 1) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
ParamsFlash_HandleInit(&settings->flash_handle, 0, 1, settings->settings_size);
|
||||
|
||||
if(MEMSPI_FLASH_Protection(&memory_spi, 0, 0x11000, 1000, 1) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
#endif
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Запись настроек в память.
|
||||
*
|
||||
* @param settings Указатель на хендл для настроек.
|
||||
* @details Записывает настройки в память, если установлен флаг обновления.
|
||||
* Можно включить защиту @ref SETTINGS_MEMORY_PROTECT_ENABLE : добавляет защиту памяти перед записью и снимает её после.
|
||||
*/
|
||||
void Settings_WriteSettings(SettingsTypeDef *settings)
|
||||
{
|
||||
if(!settings)
|
||||
return;
|
||||
|
||||
static int update_start = 0;
|
||||
static uint32_t update_request_tick = 0;
|
||||
HAL_StatusTypeDef res = HAL_OK;
|
||||
|
||||
|
||||
#ifdef SETTINGS_USE_SETTINGS_FROM_BUFFER
|
||||
// Сравниваем текущие настройки с буфером
|
||||
for(int i = 0; i < settings->setarr_count; i++)
|
||||
{
|
||||
if(memcmp(settings->setarr[i].mem_ptr,
|
||||
settings->setarr[i].real_ptr,
|
||||
settings->setarr[i].length) != 0)
|
||||
{
|
||||
settings->update_settings_flag = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(settings->update_settings_flag)
|
||||
{
|
||||
// if(GPIO_Read_Switch(&MZKT_DISCIN.err_24V))
|
||||
// {
|
||||
// printf_memspi_err("Power Err, cancel writing");
|
||||
// settings->update_settings_flag = 0;
|
||||
// update_start = 0;
|
||||
// return;
|
||||
// }
|
||||
if(msDelayDone(1000, &update_request_tick))
|
||||
{
|
||||
update_start = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
msDelayStart(&update_request_tick);
|
||||
update_start = 0;
|
||||
}
|
||||
|
||||
|
||||
if(update_start)
|
||||
{
|
||||
// Сбрасываем флаг обновления
|
||||
settings->update_settings_flag = 0;
|
||||
update_start = 0;
|
||||
|
||||
#ifdef SETTINGS_USE_SETTINGS_FROM_BUFFER
|
||||
// Обновляем буфер новыми настройками
|
||||
for(uint8_t i = 0; i < settings->setarr_count; i++)
|
||||
{
|
||||
memcpy( settings->setarr[i].mem_ptr,
|
||||
settings->setarr[i].real_ptr,
|
||||
settings->setarr[i].length);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Записываем настройки в память
|
||||
WriteSettingsToMem(settings);
|
||||
|
||||
Settings_CheckSettings(settings);
|
||||
__enable_irq();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Чтение настроек из памяти.
|
||||
*
|
||||
* @param settings Указатель на хендл для настроек.
|
||||
* @details Включает:
|
||||
* - Чтение настроек из памяти (`ReadSettingsFromMem`).
|
||||
* - Обновление буфера, если используется @ref SETTINGS_USE_SETTINGS_FROM_BUFFER.
|
||||
*/
|
||||
void Settings_ReadSettings(SettingsTypeDef *settings)
|
||||
{
|
||||
if(!settings)
|
||||
return;
|
||||
|
||||
__disable_irq();
|
||||
ReadSettingsFromMem(settings);
|
||||
|
||||
#ifdef SETTINGS_USE_SETTINGS_FROM_BUFFER
|
||||
for(uint8_t i = 0; i < settings->setarr_count; i++)
|
||||
{
|
||||
memcpy(settings->setarr[i].real_ptr,
|
||||
settings->setarr[i].mem_ptr,
|
||||
settings->setarr[i].length);
|
||||
}
|
||||
#endif
|
||||
__enable_irq();
|
||||
Settings_CheckSettings(settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Проверить настройки на валидность.
|
||||
*
|
||||
* @param settings Указатель на хендл для настроек.
|
||||
* @details Проверяет не пустые ли настройки. Если пустые - выставялет флаг ошибки.
|
||||
*/
|
||||
void Settings_CheckSettings(SettingsTypeDef *settings)
|
||||
{
|
||||
if(!settings)
|
||||
return;
|
||||
|
||||
uint32_t total_size = 0;
|
||||
uint32_t ff_cnt = 0;
|
||||
|
||||
for(uint8_t i = 0; i < settings->setarr_count; i++)
|
||||
{
|
||||
uint8_t *ptr = settings->setarr[i].mem_ptr;
|
||||
uint32_t size = settings->setarr[i].length;
|
||||
|
||||
total_size += size;
|
||||
|
||||
for(uint32_t j = 0; j < size; j++)
|
||||
{
|
||||
if(ptr[j] == 0xFF)
|
||||
ff_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
if(total_size && ff_cnt > total_size * 0.8)
|
||||
settings->settings_error |= MEMORY_ERROR_EMPTY;
|
||||
else
|
||||
settings->settings_error &= ~MEMORY_ERROR_EMPTY;
|
||||
|
||||
printf_memspi("Zero Bytes: %u/%u", ff_cnt, total_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Записи настроек в память в зависимости от конфигурации.
|
||||
*
|
||||
* @param settings Указатель на хендл для настроек.
|
||||
* @details Реализация зависит от конфигурации:
|
||||
* - @ref SETTINGS_USE_SETTINGS_FROM_POINTER : запись по отдельным указателям на различные массивы настроек.
|
||||
* - @ref SETTINGS_USE_SETTINGS_FROM_BUFFER : запись всего буфера настроек целиком.
|
||||
*/
|
||||
void WriteSettingsToMem(SettingsTypeDef *settings)
|
||||
{
|
||||
HAL_StatusTypeDef res = HAL_OK;
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef SETTINGS_USE_WEAR_LEVELING_FLASH
|
||||
if(MEMSPI_FLASH_Protection(settings->hmemspi, 0, 0x11000, DISABLE, 1000) != HAL_OK)
|
||||
{
|
||||
settings->settings_error |= MEMORY_ERROR_WRITE;
|
||||
return;
|
||||
}
|
||||
|
||||
if(ParamsFlash_WriteBlock(&settings->flash_handle, PARAMS_LAST_BLOCK,
|
||||
(uint16_t *)settings->buffer,
|
||||
settings->settings_size) < 0)
|
||||
{
|
||||
res = HAL_ERROR;
|
||||
}
|
||||
|
||||
if(MEMSPI_FLASH_Protection(settings->hmemspi, 0, 0x11000, ENABLE, 1000) != HAL_OK)
|
||||
{
|
||||
settings->settings_error |= MEMORY_ERROR_WRITE;
|
||||
}
|
||||
#else //SETTINGS_USE_WEAR_LEVELING_FLASH
|
||||
|
||||
if(MEMSPI_FLASH_Protection(settings->hmemspi, settings->start_adr, settings->settings_size, DISABLE, 1000) != HAL_OK)
|
||||
{
|
||||
settings->settings_error |= MEMORY_ERROR_WRITE;
|
||||
return;
|
||||
}
|
||||
|
||||
for(uint8_t i = 0; i < settings->setarr_count; i++)
|
||||
{
|
||||
|
||||
WriteSettingsArrayToMem(settings, &settings->setarr[i]);
|
||||
|
||||
}
|
||||
|
||||
if(MEMSPI_FLASH_Protection(settings->hmemspi, settings->start_adr, settings->settings_size, DISABLE, 1000) != HAL_OK)
|
||||
{
|
||||
settings->settings_error |= MEMORY_ERROR_WRITE;
|
||||
return;
|
||||
}
|
||||
#endif //SETTINGS_USE_WEAR_LEVELING_FLASH
|
||||
|
||||
|
||||
if(res != HAL_OK)
|
||||
{
|
||||
printf_memspi_err("Write Error: %u", res);
|
||||
settings->settings_error |= MEMORY_ERROR_WRITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf_memspi("Write Ok");
|
||||
settings->settings_error &= ~MEMORY_ERROR_WRITE;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief Читает настройки из памяти в зависимости от конфигурации.
|
||||
*
|
||||
* @param settings Указатель на хендл для настроек.
|
||||
* @details Реализация зависит от конфигурации:
|
||||
* - @ref SETTINGS_USE_SETTINGS_FROM_POINTER : чтение по отдельным указателям на различные массивы настроек.
|
||||
* - @ref SETTINGS_USE_SETTINGS_FROM_BUFFER : чтение всего буфера настроек целиком.
|
||||
*/
|
||||
void ReadSettingsFromMem(SettingsTypeDef *settings)
|
||||
{
|
||||
HAL_StatusTypeDef res = HAL_OK;
|
||||
#ifdef SETTINGS_USE_WEAR_LEVELING_FLASH
|
||||
if(ParamsFlash_ReadBlock(&settings->flash_handle, PARAMS_LAST_BLOCK,
|
||||
(uint16_t *)settings->buffer,
|
||||
settings->settings_size, NULL) < 0)
|
||||
{
|
||||
res = HAL_ERROR;
|
||||
}
|
||||
#else //SETTINGS_USE_WEAR_LEVELING_FLASH
|
||||
|
||||
for(uint8_t i = 0; i < settings->setarr_count; i++)
|
||||
{
|
||||
ReadSettingsArrayFromMem(settings, &settings->setarr[i]);
|
||||
}
|
||||
#endif //SETTINGS_USE_WEAR_LEVELING_FLASH
|
||||
|
||||
if(res != HAL_OK)
|
||||
{
|
||||
printf_memspi_err("Read Error: %u", res);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf_memspi("Read Ok");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Записывает массив настроек через указатель в память.
|
||||
*
|
||||
* @param settings Указатель на хендл для настроек.
|
||||
* @param settingarr Указатель на структуру для записи массива настроек.
|
||||
* @details Функция используется при @ref SETTINGS_USE_SETTINGS_FROM_POINTER
|
||||
*/
|
||||
void WriteSettingsArrayToMem(SettingsTypeDef *settings, SettingArrayTypeDef *settingarr)
|
||||
{
|
||||
#ifndef SETTINGS_USE_MEMORY_EEPROM
|
||||
MEMSPI_WriteInitTypeDef writeinit;
|
||||
|
||||
writeinit.Data_Address = settingarr->adr;
|
||||
writeinit.Data_Size = settingarr->length;
|
||||
writeinit.Sector_Address = settings->start_adr;
|
||||
writeinit.Sector_Size = settings->settings_size;
|
||||
writeinit.fSavePrevoisData = 1;
|
||||
writeinit.pDataPtr = settingarr->mem_ptr;
|
||||
|
||||
if(MEMSPI_FLASH_Write(settings->hmemspi, &writeinit, 1000, 1) != HAL_OK)
|
||||
{
|
||||
settings->settings_error |= MEMORY_ERROR_WRITE;
|
||||
return;
|
||||
}
|
||||
|
||||
#else
|
||||
if(MEMSPI_EEPROM_Write(settings->hmemspi, settingarr->adr, settingarr->mem_ptr, settingarr->length, 1000, 1) != HAL_OK)
|
||||
{
|
||||
settings->settings_error |= MEMORY_ERROR_WRITE;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Читает массив настроек через указатель в память.
|
||||
*
|
||||
* @param settings Указатель на хендл для настроек.
|
||||
* @param settingarr Указатель на структуру для записи массива настроек.
|
||||
* @details Функция используется при @ref SETTINGS_USE_SETTINGS_FROM_POINTER
|
||||
*/
|
||||
void ReadSettingsArrayFromMem(SettingsTypeDef *settings, SettingArrayTypeDef *settingarr)
|
||||
{
|
||||
MEMSPI_Read_Memory(settings->hmemspi, settingarr->adr, settingarr->mem_ptr, settingarr->length, 1000);
|
||||
}
|
||||
Reference in New Issue
Block a user