124 lines
3.7 KiB
C
124 lines
3.7 KiB
C
#include "flash_ring.h"
|
||
|
||
extern int last_page_addr;
|
||
|
||
|
||
|
||
|
||
BufferState_t buffer_init(void) {
|
||
BufferState_t state = {0};
|
||
|
||
// Ищем последнюю записанную запись
|
||
for (int i = 0; i < RECORDS_PER_PAGE; i++) {
|
||
uint32_t record_addr = LAST_PAGE_ADDR + (i * RECORD_SIZE);
|
||
FlashRecord_t* record = (FlashRecord_t*)record_addr;
|
||
|
||
// Проверяем валидность записи (не 0xFFFFFFFF)
|
||
if (record->timestamp != 0xFFFFFFFF) {
|
||
state.write_index = i + 1;
|
||
state.initialized = 1;
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
|
||
// Если буфер заполнен, начинаем с начала
|
||
if (state.write_index >= RECORDS_PER_PAGE) {
|
||
state.write_index = 0;
|
||
}
|
||
|
||
return state;
|
||
}
|
||
|
||
HAL_StatusTypeDef buffer_write_record(FlashRecord_t* record, BufferState_t* state) {
|
||
HAL_StatusTypeDef status;
|
||
|
||
// Если нужно стереть страницу (начало нового цикла)
|
||
if (state->write_index == 0 && state->initialized) {
|
||
status = erase_flash_page();
|
||
if (status != HAL_OK) return status;
|
||
}
|
||
|
||
// Записываем данные
|
||
uint32_t record_addr = last_page_addr + (state->write_index * RECORD_SIZE);
|
||
|
||
status = write_flash_record(record_addr, record);
|
||
if (status != HAL_OK) return status;
|
||
|
||
// Обновляем индекс
|
||
state->write_index++;
|
||
if (state->write_index >= RECORDS_PER_PAGE) {
|
||
state->write_index = 0;
|
||
}
|
||
|
||
state->initialized = 1;
|
||
return HAL_OK;
|
||
}
|
||
|
||
HAL_StatusTypeDef erase_flash_page(void) {
|
||
HAL_FLASH_Unlock();
|
||
|
||
FLASH_EraseInitTypeDef EraseInit = {
|
||
.TypeErase = FLASH_TYPEERASE_PAGES,
|
||
.PageAddress = LAST_PAGE_ADDR,
|
||
.NbPages = 1
|
||
};
|
||
|
||
uint32_t page_error;
|
||
HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&EraseInit, &page_error);
|
||
|
||
HAL_FLASH_Lock();
|
||
return status;
|
||
}
|
||
// Запись одной записи
|
||
HAL_StatusTypeDef write_flash_record(uint32_t address, FlashRecord_t* record) {
|
||
HAL_FLASH_Unlock();
|
||
HAL_StatusTypeDef status = HAL_OK;
|
||
|
||
// Записываем данные по 4 байта (слово)
|
||
uint32_t* data_ptr = (uint32_t*)record;
|
||
uint32_t words_to_write = (RECORD_SIZE + 3) / 4; // округление вверх
|
||
|
||
for (uint32_t i = 0; i < words_to_write; i++) {
|
||
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,
|
||
address + (i * 4),
|
||
data_ptr[i]);
|
||
if (status != HAL_OK) break;
|
||
}
|
||
|
||
HAL_FLASH_Lock();
|
||
return status;
|
||
}
|
||
|
||
// Чтение записи по индексу
|
||
FlashRecord_t* buffer_read_record(uint32_t index) {
|
||
if (index >= RECORDS_PER_PAGE) return NULL;
|
||
|
||
uint32_t record_addr = LAST_PAGE_ADDR + (index * RECORD_SIZE);
|
||
FlashRecord_t* record = (FlashRecord_t*)record_addr;
|
||
|
||
// Проверяем что запись не пустая
|
||
if (record->timestamp == 0xFFFFFFFF) {
|
||
return NULL;
|
||
}
|
||
|
||
return record;
|
||
}
|
||
// Получение всех записей в порядке от старых к новым
|
||
void buffer_get_all_records(FlashRecord_t* records[], uint32_t* count) {
|
||
*count = 0;
|
||
BufferState_t state = buffer_init();
|
||
|
||
if (!state.initialized) return;
|
||
|
||
// Начинаем с текущего write_index (самые старые данные)
|
||
for (int i = 0; i < RECORDS_PER_PAGE; i++) {
|
||
uint32_t idx = (state.write_index + i) % RECORDS_PER_PAGE;
|
||
FlashRecord_t* record = buffer_read_record(idx);
|
||
|
||
if (record) {
|
||
records[(*count)++] = record;
|
||
}
|
||
}
|
||
}
|