добавил второй проект для C8T6

This commit is contained in:
2026-02-14 18:13:02 +03:00
parent 69ae4f8cf2
commit 8552d8ee90
2781 changed files with 1626381 additions and 41 deletions

View File

@@ -0,0 +1,297 @@
//#include "eeprom_emul.h"
#include <string.h>
// Внутренние переменные
static uint32_t eeprom_current_write_address = EEPROM_START_ADDRESS;
static uint8_t eeprom_initialized = 0;
// Прототипы внутренних функций
static EEPROM_Status EEPROM_FindLatestData(uint16_t virt_address, uint16_t* data);
static EEPROM_Status EEPROM_WriteItem(EEPROM_Item* item);
static EEPROM_Status EEPROM_ErasePage(uint32_t address);
static uint32_t EEPROM_FindNextWriteAddress(void);
static uint8_t EEPROM_IsPageErased(uint32_t address);
static uint32_t EEPROM_CalculateCRC(EEPROM_Item* item);
// Инициализация EEPROM
EEPROM_Status EEPROM_Init(void)
{
if (eeprom_initialized)
{
return EEPROM_OK;
}
// Находим следующий адрес для записи
eeprom_current_write_address = EEPROM_FindNextWriteAddress();
// Если вся память заполнена, выполняем сборку мусора (форматирование)
if (eeprom_current_write_address >= EEPROM_START_ADDRESS + EEPROM_SIZE)
{
EEPROM_Format();
}
else
{
eeprom_initialized = 1;
}
return EEPROM_OK;
}
// Чтение данных по виртуальному адресу
EEPROM_Status EEPROM_Read(uint16_t virt_address, uint16_t* data)
{
if (!eeprom_initialized)
{
return EEPROM_ERROR;
}
if (virt_address >= EEPROM_MAX_VARIABLES || data == NULL)
{
return EEPROM_INVALID;
}
return EEPROM_FindLatestData(virt_address, data);
}
// Запись данных по виртуальному адресу
EEPROM_Status EEPROM_Write(uint16_t virt_address, uint16_t data)
{
EEPROM_Item item;
if (!eeprom_initialized)
{
return EEPROM_ERROR;
}
if (virt_address >= EEPROM_MAX_VARIABLES)
{
return EEPROM_INVALID;
}
// Подготавливаем элемент данных
item.address = virt_address;
item.data = data;
item.timestamp = HAL_GetTick(); // Используем системный таймер
// Записываем элемент
return EEPROM_WriteItem(&item);
}
// Поиск последних данных для виртуального адреса
static EEPROM_Status EEPROM_FindLatestData(uint16_t virt_address, uint16_t* data)
{
uint32_t address = EEPROM_START_ADDRESS;
EEPROM_Item current_item;
uint32_t latest_timestamp = 0;
uint16_t latest_data = 0;
uint8_t data_found = 0;
// Сканируем всю область EEPROM
while (address < EEPROM_START_ADDRESS + EEPROM_SIZE)
{
// Читаем элемент
memcpy(&current_item, (void*)address, sizeof(EEPROM_Item));
// Проверяем, является ли это валидными данными
if (current_item.address == virt_address)
{
if (current_item.timestamp >= latest_timestamp)
{
latest_timestamp = current_item.timestamp;
latest_data = current_item.data;
data_found = 1;
}
}
address += sizeof(EEPROM_Item);
// Проверяем конец страницы
if ((address - EEPROM_START_ADDRESS) % EEPROM_PAGE_SIZE == 0)
{
address += (EEPROM_PAGE_SIZE - (sizeof(EEPROM_Item) * 2));
}
}
if (data_found)
{
*data = latest_data;
return EEPROM_OK;
}
return EEPROM_INVALID;
}
// Запись элемента в EEPROM
static EEPROM_Status EEPROM_WriteItem(EEPROM_Item* item)
{
HAL_StatusTypeDef hal_status;
// Проверяем, нужно ли стирать страницу
if ((eeprom_current_write_address - EEPROM_START_ADDRESS) % EEPROM_PAGE_SIZE == 0)
{
if (!EEPROM_IsPageErased(eeprom_current_write_address))
{
if (EEPROM_ErasePage(eeprom_current_write_address) != EEPROM_OK)
{
return EEPROM_ERROR;
}
}
}
// Разблокируем Flash
HAL_FLASH_Unlock();
// Записываем данные по словам (32 бита)
uint32_t* data_ptr = (uint32_t*)item;
for (uint8_t i = 0; i < sizeof(EEPROM_Item) / 4; i++)
{
hal_status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,
eeprom_current_write_address + (i * 4),
data_ptr[i]);
if (hal_status != HAL_OK)
{
HAL_FLASH_Lock();
return EEPROM_ERROR;
}
}
// Блокируем Flash
HAL_FLASH_Lock();
// Обновляем адрес для следующей записи
eeprom_current_write_address += sizeof(EEPROM_Item);
// Проверяем переполнение
if (eeprom_current_write_address >= EEPROM_START_ADDRESS + EEPROM_SIZE)
{
// Выполняем сборку мусора (в данном случае - форматирование)
EEPROM_Format();
}
return EEPROM_OK;
}
// Стирание страницы Flash
static EEPROM_Status EEPROM_ErasePage(uint32_t address)
{
FLASH_EraseInitTypeDef erase;
uint32_t page_error;
// Определяем номер страницы
uint32_t page = (address - FLASH_BASE) / EEPROM_PAGE_SIZE;
HAL_FLASH_Unlock();
erase.TypeErase = FLASH_TYPEERASE_PAGES;
erase.PageAddress = address;
erase.NbPages = 1;
if (HAL_FLASHEx_Erase(&erase, &page_error) != HAL_OK)
{
HAL_FLASH_Lock();
return EEPROM_ERROR;
}
HAL_FLASH_Lock();
return EEPROM_OK;
}
// Поиск следующего адреса для записи
static uint32_t EEPROM_FindNextWriteAddress(void)
{
uint32_t address = EEPROM_START_ADDRESS;
EEPROM_Item item;
// Ищем первую свободную позицию
while (address < EEPROM_START_ADDRESS + EEPROM_SIZE)
{
memcpy(&item, (void*)address, sizeof(EEPROM_Item));
// Если нашли пустой элемент (все FFFF), это свободная позиция
if (item.address == 0xFFFF && item.data == 0xFFFF && item.timestamp == 0xFFFFFFFF)
{
break;
}
address += sizeof(EEPROM_Item);
// Проверяем границу страницы
if ((address - EEPROM_START_ADDRESS) % EEPROM_PAGE_SIZE == 0)
{
address += (EEPROM_PAGE_SIZE - (sizeof(EEPROM_Item) * 2));
}
}
return address;
}
// Проверка, стерта ли страница
static uint8_t EEPROM_IsPageErased(uint32_t address)
{
uint32_t* check_addr = (uint32_t*)address;
// Проверяем первые несколько слов
for (uint8_t i = 0; i < 8; i++)
{
if (check_addr[i] != 0xFFFFFFFF)
{
return 0;
}
}
return 1;
}
// Полное форматирование EEPROM
EEPROM_Status EEPROM_Format(void)
{
uint32_t address = EEPROM_START_ADDRESS;
// Стираем все страницы, используемые для EEPROM
while (address < EEPROM_START_ADDRESS + EEPROM_SIZE)
{
if (EEPROM_ErasePage(address) != EEPROM_OK)
{
return EEPROM_ERROR;
}
address += EEPROM_PAGE_SIZE;
}
eeprom_current_write_address = EEPROM_START_ADDRESS;
eeprom_initialized = 1;
return EEPROM_OK;
}
// Получение информации об использовании EEPROM
void EEPROM_GetInfo(uint32_t* used, uint32_t* total)
{
uint32_t address = EEPROM_START_ADDRESS;
uint32_t used_bytes = 0;
if (used)
{
// Подсчитываем использованные байты
while (address < EEPROM_START_ADDRESS + EEPROM_SIZE)
{
EEPROM_Item item;
memcpy(&item, (void*)address, sizeof(EEPROM_Item));
if (item.address != 0xFFFF || item.data != 0xFFFF || item.timestamp != 0xFFFFFFFF)
{
used_bytes += sizeof(EEPROM_Item);
}
address += sizeof(EEPROM_Item);
}
*used = used_bytes;
}
if (total)
{
*total = EEPROM_SIZE;
}
}