#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; } } }