storage overhaul
needs tested tho
This commit is contained in:
457
main/storage.c
457
main/storage.c
@@ -11,6 +11,25 @@
|
||||
|
||||
#define TAG "STORAGE"
|
||||
|
||||
// ============================================================================
|
||||
// LOG TYPE DEFINITIONS (Magic values 0xC0-0xCF)
|
||||
// ============================================================================
|
||||
#define LOG_TYPE_DATA 0xC0 // Generic data log
|
||||
#define LOG_TYPE_EVENT 0xC1 // Event marker
|
||||
#define LOG_TYPE_ERROR 0xC2 // Error log
|
||||
#define LOG_TYPE_DEBUG 0xC3 // Debug message
|
||||
#define LOG_TYPE_SENSOR 0xC4 // Sensor reading
|
||||
#define LOG_TYPE_COMMAND 0xC5 // Command executed
|
||||
#define LOG_TYPE_STATUS 0xC6 // Status update
|
||||
#define LOG_TYPE_PADDING 0xCE // Padding to sector boundary
|
||||
#define LOG_TYPE_CUSTOM 0xCF // Custom/user-defined
|
||||
|
||||
// Helper macro to check if a byte is a valid log type
|
||||
#define IS_VALID_LOG_TYPE(x) ((x) >= 0xC0 && (x) <= 0xCF)
|
||||
|
||||
// Maximum payload size per log entry (255 max due to 1-byte size field)
|
||||
#define LOG_MAX_PAYLOAD 255
|
||||
|
||||
// ============================================================================
|
||||
// PARAMETER TABLE GENERATION
|
||||
// ============================================================================
|
||||
@@ -55,19 +74,33 @@ const char parameter_units[NUM_PARAMS][8] = {
|
||||
};
|
||||
#undef PARAM_DEF
|
||||
|
||||
size_t param_type_size(param_type_e x) {
|
||||
switch(x) {
|
||||
case PARAM_TYPE_u16: return 2;
|
||||
case PARAM_TYPE_i16: return 2;
|
||||
case PARAM_TYPE_u32: return 4;
|
||||
case PARAM_TYPE_i32: return 4;
|
||||
case PARAM_TYPE_f32: return 4;
|
||||
case PARAM_TYPE_f64: return 8;
|
||||
case PARAM_TYPE_str: return PARAM_STR_SIZE;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Partition pointer
|
||||
static const esp_partition_t *storage_partition = NULL;
|
||||
|
||||
// Log head tracking with mutex protection
|
||||
static uint32_t log_head_index = 0;
|
||||
static uint32_t log_tail_index = 0;
|
||||
// Log head/tail tracking with mutex protection
|
||||
// These now track byte offsets within the log area, not entry indices
|
||||
static uint32_t log_head_offset = 0; // Offset from LOG_START_OFFSET
|
||||
static uint32_t log_tail_offset = 0; // Offset from LOG_START_OFFSET
|
||||
static SemaphoreHandle_t log_mutex = NULL;
|
||||
static bool log_initialized = false;
|
||||
|
||||
uint32_t get_log_head(void) {
|
||||
uint32_t head;
|
||||
if (log_mutex) xSemaphoreTake(log_mutex, portMAX_DELAY);
|
||||
head = LOG_START_OFFSET + (log_head_index * LOG_ENTRY_SIZE);
|
||||
head = LOG_START_OFFSET + log_head_offset;
|
||||
if (log_mutex) xSemaphoreGive(log_mutex);
|
||||
return head;
|
||||
}
|
||||
@@ -75,7 +108,7 @@ uint32_t get_log_head(void) {
|
||||
uint32_t get_log_tail(void) {
|
||||
uint32_t tail;
|
||||
if (log_mutex) xSemaphoreTake(log_mutex, portMAX_DELAY);
|
||||
tail = LOG_START_OFFSET + (log_tail_index * LOG_ENTRY_SIZE);
|
||||
tail = LOG_START_OFFSET + log_tail_offset;
|
||||
if (log_mutex) xSemaphoreGive(log_mutex);
|
||||
return tail;
|
||||
}
|
||||
@@ -252,6 +285,9 @@ static void pack_param(uint8_t *dest, param_idx_t id) {
|
||||
case PARAM_TYPE_str:
|
||||
memcpy(dest, parameter_table[id].str, 16);
|
||||
break;
|
||||
default:
|
||||
memset(dest, 0, 16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,6 +320,8 @@ static void unpack_param(const uint8_t *src, param_idx_t id) {
|
||||
memcpy(parameter_table[id].str, src, 16);
|
||||
parameter_table[id].str[15] = '\0'; // Ensure null termination
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,49 +331,46 @@ static void unpack_param(const uint8_t *src, param_idx_t id) {
|
||||
esp_err_t commit_params(void) {
|
||||
if (storage_partition == NULL) {
|
||||
ESP_LOGE(TAG, "Storage partition not initialized");
|
||||
return ESP_FAIL;
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
set_param_string(PARAM_BUILD_VERSION, FIRMWARE_VERSION);
|
||||
ESP_LOGI(TAG, "Committing %d parameters to flash...", NUM_PARAMS);
|
||||
|
||||
// Calculate flash offset for each parameter
|
||||
uint32_t flash_offset = PARAMS_OFFSET;
|
||||
|
||||
// Erase the parameter sectors
|
||||
// Erase parameter sectors first
|
||||
esp_err_t err = esp_partition_erase_range(storage_partition, PARAMS_OFFSET,
|
||||
LOG_START_OFFSET);
|
||||
PARAMETER_NUM_SECTORS * FLASH_SECTOR_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to erase parameter sectors: %s", esp_err_to_name(err));
|
||||
return ESP_FAIL;
|
||||
return err;
|
||||
}
|
||||
|
||||
// Write each parameter with its CRC
|
||||
// Write each parameter with CRC
|
||||
uint32_t flash_offset = PARAMS_OFFSET;
|
||||
for (int i = 0; i < NUM_PARAMS; i++) {
|
||||
param_stored_t stored;
|
||||
memset(&stored, 0, sizeof(stored));
|
||||
memset(&stored, 0, sizeof(param_stored_t));
|
||||
|
||||
// Pack the parameter value
|
||||
uint8_t size = param_type_size(parameter_types[i]);
|
||||
// Pack parameter data
|
||||
pack_param(stored.data, i);
|
||||
|
||||
// Calculate CRC over the actual data size used
|
||||
// Calculate CRC over actual data size
|
||||
uint8_t size = param_type_size(parameter_types[i]);
|
||||
uint32_t crc_input = PARAM_CRC_SALT;
|
||||
//uint32_t crc = esp_crc32_le(0, (uint8_t*)&crc_input, sizeof(crc_input));
|
||||
stored.crc = esp_crc32_le(crc_input, stored.data, size);
|
||||
|
||||
// Write to flash
|
||||
err = esp_partition_write(storage_partition, flash_offset,
|
||||
&stored, sizeof(param_stored_t));
|
||||
&stored, sizeof(param_stored_t));
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to write parameter %d (%s): %s",
|
||||
i, parameter_names[i], esp_err_to_name(err));
|
||||
return ESP_FAIL;
|
||||
return err;
|
||||
}
|
||||
|
||||
flash_offset += sizeof(param_stored_t);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Parameters committed to flash successfully");
|
||||
ESP_LOGI(TAG, "Successfully committed all parameters to flash");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -343,48 +378,33 @@ esp_err_t commit_params(void) {
|
||||
// FACTORY RESET
|
||||
// ============================================================================
|
||||
esp_err_t factory_reset(void) {
|
||||
if (storage_partition == NULL) {
|
||||
ESP_LOGE(TAG, "Storage partition not initialized");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
ESP_LOGI(TAG, "Performing factory reset...");
|
||||
|
||||
ESP_LOGW(TAG, "FACTORY RESET: Erasing entire storage partition...");
|
||||
|
||||
// Erase the entire storage partition
|
||||
esp_err_t err = esp_partition_erase_range(storage_partition, 0, storage_partition->size);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to erase storage partition: %s", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Storage partition erased successfully");
|
||||
|
||||
// Reset all parameters to defaults in RAM
|
||||
// Reset all parameters to defaults
|
||||
for (int i = 0; i < NUM_PARAMS; i++) {
|
||||
memcpy(¶meter_table[i], ¶meter_defaults[i], sizeof(param_value_t));
|
||||
}
|
||||
|
||||
// Reset log indices
|
||||
if (log_mutex) xSemaphoreTake(log_mutex, portMAX_DELAY);
|
||||
log_head_index = 0;
|
||||
log_tail_index = 0;
|
||||
if (log_mutex) xSemaphoreGive(log_mutex);
|
||||
|
||||
ESP_LOGI(TAG, "Factory reset complete - all data erased");
|
||||
// Commit defaults to flash
|
||||
esp_err_t err = commit_params();
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to commit defaults during factory reset");
|
||||
return err;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Factory reset complete");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// INITIALIZATION FUNCTIONS
|
||||
// STORAGE INITIALIZATION
|
||||
// ============================================================================
|
||||
|
||||
esp_err_t storage_init(void) {
|
||||
// Find the partition labeled "storage"
|
||||
ESP_LOGI(TAG, "Initializing storage system...");
|
||||
|
||||
storage_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,
|
||||
ESP_PARTITION_SUBTYPE_ANY,
|
||||
"storage");
|
||||
|
||||
if (storage_partition == NULL) {
|
||||
ESP_LOGE(TAG, "Storage partition not found");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
@@ -406,7 +426,7 @@ esp_err_t storage_init(void) {
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Failed to read parameter %d (%s), using default",
|
||||
i, parameter_names[i]);
|
||||
memcpy(¶meter_table[i], ¶meter_defaults[i], sizeof(param_value_t)); // SET DEFAULT HERE
|
||||
memcpy(¶meter_table[i], ¶meter_defaults[i], sizeof(param_value_t));
|
||||
all_valid = false;
|
||||
flash_offset += sizeof(param_stored_t);
|
||||
continue;
|
||||
@@ -415,7 +435,6 @@ esp_err_t storage_init(void) {
|
||||
// Validate CRC over actual data size
|
||||
uint8_t size = param_type_size(parameter_types[i]);
|
||||
uint32_t crc_input = PARAM_CRC_SALT;
|
||||
//uint32_t crc = esp_crc32_le(0, (uint8_t*)&crc_input, sizeof(crc_input));
|
||||
uint32_t calculated_crc = esp_crc32_le(crc_input, stored.data, size);
|
||||
|
||||
if (calculated_crc == stored.crc) {
|
||||
@@ -423,7 +442,7 @@ esp_err_t storage_init(void) {
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Parameter %d (%s) failed CRC check, using default",
|
||||
i, parameter_names[i]);
|
||||
memcpy(¶meter_table[i], ¶meter_defaults[i], sizeof(param_value_t)); // SET DEFAULT HERE
|
||||
memcpy(¶meter_table[i], ¶meter_defaults[i], sizeof(param_value_t));
|
||||
all_valid = false;
|
||||
}
|
||||
|
||||
@@ -440,50 +459,55 @@ esp_err_t storage_init(void) {
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// LOGGING FUNCTIONS (unchanged from original)
|
||||
// VARIABLE-LENGTH LOGGING FUNCTIONS
|
||||
// ============================================================================
|
||||
|
||||
static esp_err_t find_log_head(void) {
|
||||
/**
|
||||
* Find the first valid log entry by scanning for magic bytes.
|
||||
* Returns absolute flash offset, or -1 if no valid entry found.
|
||||
*/
|
||||
/*static int32_t find_first_valid_entry(uint32_t start_offset, uint32_t end_offset) {
|
||||
if (storage_partition == NULL) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t log_area_size = storage_partition->size - LOG_START_OFFSET;
|
||||
uint32_t max_entries = log_area_size / LOG_ENTRY_SIZE;
|
||||
uint8_t buffer[256];
|
||||
uint32_t scan_pos = start_offset;
|
||||
|
||||
uint8_t entry[LOG_ENTRY_SIZE];
|
||||
uint8_t empty_entry[LOG_ENTRY_SIZE];
|
||||
memset(empty_entry, 0xFF, LOG_ENTRY_SIZE);
|
||||
|
||||
for (uint32_t i = 0; i < max_entries; i++) {
|
||||
uint32_t offset = LOG_START_OFFSET + (i * LOG_ENTRY_SIZE);
|
||||
while (scan_pos < end_offset) {
|
||||
size_t chunk_size = (end_offset - scan_pos) < sizeof(buffer) ?
|
||||
(end_offset - scan_pos) : sizeof(buffer);
|
||||
|
||||
esp_err_t err = esp_partition_read(storage_partition, offset, entry, LOG_ENTRY_SIZE);
|
||||
esp_err_t err = esp_partition_read(storage_partition, scan_pos, buffer, chunk_size);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to read log entry at index %lu", (unsigned long)i);
|
||||
return err;
|
||||
ESP_LOGE(TAG, "Failed to read during scan at offset %lu", (unsigned long)scan_pos);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(entry, empty_entry, LOG_ENTRY_SIZE) == 0) {
|
||||
log_head_index = i;
|
||||
ESP_LOGI(TAG, "Log head found at index %lu", (unsigned long)log_head_index);
|
||||
return ESP_OK;
|
||||
// Scan for valid type byte
|
||||
for (size_t i = 0; i < chunk_size; i++) {
|
||||
if (IS_VALID_LOG_TYPE(buffer[i])) {
|
||||
// Found potential entry - verify we can read size byte
|
||||
if (i + 1 < chunk_size) {
|
||||
// Size byte is in buffer
|
||||
return scan_pos + i;
|
||||
} else if (scan_pos + i + 1 < end_offset) {
|
||||
// Size byte is in next read
|
||||
return scan_pos + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move to next chunk, with 1-byte overlap to catch split entries
|
||||
scan_pos += chunk_size - 1;
|
||||
}
|
||||
|
||||
log_head_index = 0;
|
||||
ESP_LOGI(TAG, "Log is full, wrapping to beginning");
|
||||
|
||||
esp_err_t err = esp_partition_erase_range(storage_partition, LOG_START_OFFSET,
|
||||
FLASH_SECTOR_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to erase first log sector");
|
||||
return err;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
return -1;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Initialize the log system by finding head position
|
||||
*/
|
||||
esp_err_t log_init(void) {
|
||||
if (storage_partition == NULL) {
|
||||
ESP_LOGE(TAG, "Storage partition not initialized, call storage_init() first");
|
||||
@@ -496,38 +520,159 @@ esp_err_t log_init(void) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
esp_err_t err = find_log_head();
|
||||
if (err != ESP_OK) {
|
||||
vSemaphoreDelete(log_mutex);
|
||||
log_mutex = NULL;
|
||||
return err;
|
||||
//uint32_t log_area_size = storage_partition->size - LOG_START_OFFSET;
|
||||
uint32_t log_area_end = storage_partition->size;
|
||||
|
||||
// Scan for first empty (0xFF) byte to find head
|
||||
uint8_t buffer[256];
|
||||
bool found_head = false;
|
||||
|
||||
for (uint32_t offset = LOG_START_OFFSET; offset < log_area_end; offset += sizeof(buffer)) {
|
||||
size_t to_read = (log_area_end - offset) < sizeof(buffer) ?
|
||||
(log_area_end - offset) : sizeof(buffer);
|
||||
|
||||
esp_err_t err = esp_partition_read(storage_partition, offset, buffer, to_read);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to read during log init at offset %lu", (unsigned long)offset);
|
||||
vSemaphoreDelete(log_mutex);
|
||||
log_mutex = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
// Look for first 0xFF byte (empty flash)
|
||||
for (size_t i = 0; i < to_read; i++) {
|
||||
if (buffer[i] == 0xFF) {
|
||||
log_head_offset = (offset + i) - LOG_START_OFFSET;
|
||||
found_head = true;
|
||||
ESP_LOGI(TAG, "Log head found at offset %lu (absolute: %lu)",
|
||||
(unsigned long)log_head_offset,
|
||||
(unsigned long)(LOG_START_OFFSET + log_head_offset));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_head) break;
|
||||
}
|
||||
|
||||
if (!found_head) {
|
||||
// Log is completely full, wrap to beginning
|
||||
log_head_offset = 0;
|
||||
ESP_LOGI(TAG, "Log is full, wrapping to beginning");
|
||||
|
||||
// Erase first sector
|
||||
esp_err_t err = esp_partition_erase_range(storage_partition, LOG_START_OFFSET,
|
||||
FLASH_SECTOR_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to erase first log sector");
|
||||
vSemaphoreDelete(log_mutex);
|
||||
log_mutex = NULL;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
// Set tail to start of log area initially (will be updated as sectors are erased)
|
||||
log_tail_offset = 0;
|
||||
|
||||
log_initialized = true;
|
||||
ESP_LOGI(TAG, "Log system initialized. Head offset: %lu, Tail offset: %lu",
|
||||
(unsigned long)log_head_offset, (unsigned long)log_tail_offset);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t write_log(char* entry) {
|
||||
/**
|
||||
* Write a variable-length log entry
|
||||
* @param type Log entry type (0xC0-0xCF range)
|
||||
* @param data Payload data pointer
|
||||
* @param size Payload size in bytes (0-255)
|
||||
*/
|
||||
/*esp_err_t write_log(char* entry) {
|
||||
// Legacy interface for compatibility - treat as raw 32-byte entry
|
||||
// Extract type and size from first two bytes if they look valid
|
||||
uint8_t type = (uint8_t)entry[0];
|
||||
uint8_t size = (uint8_t)entry[1];
|
||||
|
||||
if (!IS_VALID_LOG_TYPE(type)) {
|
||||
// Old format - use as LOG_TYPE_DATA with 30 bytes
|
||||
type = LOG_TYPE_DATA;
|
||||
size = 30; // Assume old 32-byte format minus 2-byte header
|
||||
}
|
||||
|
||||
return write_log(type, (const uint8_t*)&entry[2], size);
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Write a variable-length log entry (new interface)
|
||||
*/
|
||||
esp_err_t write_log(uint8_t type, const uint8_t* data, uint8_t size) {
|
||||
if (!log_initialized || storage_partition == NULL) {
|
||||
ESP_LOGE(TAG, "Logging not initialized");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (log_mutex) xSemaphoreTake(log_mutex, portMAX_DELAY);
|
||||
|
||||
uint32_t log_area_end = storage_partition->size;
|
||||
uint32_t max_entries = (log_area_end - LOG_START_OFFSET) / LOG_ENTRY_SIZE;
|
||||
|
||||
uint32_t current_offset = LOG_START_OFFSET + (log_head_index * LOG_ENTRY_SIZE);
|
||||
uint32_t next_offset = current_offset + LOG_ENTRY_SIZE;
|
||||
if (next_offset >= log_area_end) {
|
||||
next_offset = LOG_START_OFFSET;
|
||||
if (!IS_VALID_LOG_TYPE(type)) {
|
||||
ESP_LOGE(TAG, "Invalid log type: 0x%02X", type);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/*if (size > LOG_MAX_PAYLOAD) {
|
||||
ESP_LOGE(TAG, "Log payload too large: %d bytes (max %d)", size, LOG_MAX_PAYLOAD);
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}*/
|
||||
|
||||
if (log_mutex) xSemaphoreTake(log_mutex, portMAX_DELAY);
|
||||
|
||||
uint32_t log_area_size = storage_partition->size - LOG_START_OFFSET;
|
||||
uint32_t log_area_end = storage_partition->size;
|
||||
uint32_t entry_total_size = LOG_HEADER_SIZE + size; // 2 + payload
|
||||
|
||||
// Calculate absolute offsets
|
||||
uint32_t abs_head = LOG_START_OFFSET + log_head_offset;
|
||||
|
||||
// Check if entry would cross sector boundary
|
||||
uint32_t current_sector = abs_head / FLASH_SECTOR_SIZE;
|
||||
uint32_t entry_end = abs_head + entry_total_size;
|
||||
uint32_t end_sector = entry_end / FLASH_SECTOR_SIZE;
|
||||
|
||||
if (end_sector != current_sector) {
|
||||
// Entry would cross sector boundary - write padding
|
||||
uint32_t bytes_to_sector_end = FLASH_SECTOR_SIZE - (abs_head % FLASH_SECTOR_SIZE);
|
||||
|
||||
ESP_LOGI(TAG, "Entry would cross sector boundary, padding %lu bytes",
|
||||
(unsigned long)bytes_to_sector_end);
|
||||
|
||||
// Write padding entry (type + size = 0)
|
||||
uint8_t pad_entry[2] = {LOG_TYPE_PADDING, 0x00};
|
||||
esp_err_t err = esp_partition_write(storage_partition, abs_head, pad_entry, 2);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to write padding: %s", esp_err_to_name(err));
|
||||
if (log_mutex) xSemaphoreGive(log_mutex);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Advance head to next sector boundary
|
||||
log_head_offset += bytes_to_sector_end;
|
||||
|
||||
// Handle wrap-around
|
||||
if (log_head_offset >= log_area_size) {
|
||||
log_head_offset = 0;
|
||||
}
|
||||
|
||||
// Recalculate abs_head for actual entry write
|
||||
abs_head = LOG_START_OFFSET + log_head_offset;
|
||||
current_sector = abs_head / FLASH_SECTOR_SIZE;
|
||||
}
|
||||
|
||||
// Check if we need to erase the next sector before writing
|
||||
uint32_t next_offset = abs_head + entry_total_size;
|
||||
if (next_offset >= log_area_end) {
|
||||
next_offset = LOG_START_OFFSET; // Wrap
|
||||
}
|
||||
|
||||
uint32_t current_sector = current_offset / FLASH_SECTOR_SIZE;
|
||||
uint32_t next_sector = next_offset / FLASH_SECTOR_SIZE;
|
||||
|
||||
if (next_sector != current_sector) {
|
||||
// Next write will be in a new sector - check if it needs erasing
|
||||
uint8_t check_byte;
|
||||
esp_err_t err = esp_partition_read(storage_partition, next_sector * FLASH_SECTOR_SIZE,
|
||||
&check_byte, 1);
|
||||
@@ -544,82 +689,120 @@ esp_err_t write_log(char* entry) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
uint32_t tail_offset = next_sector * FLASH_SECTOR_SIZE;
|
||||
if (tail_offset < LOG_START_OFFSET) {
|
||||
tail_offset = LOG_START_OFFSET;
|
||||
// Update tail - it's now at the start of the sector we just erased
|
||||
uint32_t new_tail_abs = next_sector * FLASH_SECTOR_SIZE;
|
||||
if (new_tail_abs < LOG_START_OFFSET) {
|
||||
new_tail_abs = LOG_START_OFFSET;
|
||||
}
|
||||
log_tail_index = (tail_offset - LOG_START_OFFSET) / LOG_ENTRY_SIZE;
|
||||
log_tail_offset = new_tail_abs - LOG_START_OFFSET;
|
||||
|
||||
if (log_tail_index >= max_entries) {
|
||||
log_tail_index = 0;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Tail/Head are now %ld/%ld", (long)log_tail_index, (long)log_head_index);
|
||||
ESP_LOGI(TAG, "Tail/Head are now %lu/%lu",
|
||||
(unsigned long)log_tail_offset, (unsigned long)log_head_offset);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t err = esp_partition_write(storage_partition, current_offset, entry, LOG_ENTRY_SIZE);
|
||||
// Write the actual log entry header + payload
|
||||
uint8_t header[LOG_HEADER_SIZE] = {type, size};
|
||||
|
||||
esp_err_t err = esp_partition_write(storage_partition, abs_head, header, LOG_HEADER_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to write log entry: %s", esp_err_to_name(err));
|
||||
ESP_LOGE(TAG, "Failed to write log header: %s", esp_err_to_name(err));
|
||||
if (log_mutex) xSemaphoreGive(log_mutex);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
log_head_index++;
|
||||
if (log_head_index >= max_entries) {
|
||||
log_head_index = 0;
|
||||
ESP_LOGI(TAG, "Log wrapped to beginning");
|
||||
if (size > 0) {
|
||||
err = esp_partition_write(storage_partition, abs_head + LOG_HEADER_SIZE, data, size);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to write log payload: %s", esp_err_to_name(err));
|
||||
if (log_mutex) xSemaphoreGive(log_mutex);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
// Advance head
|
||||
log_head_offset += entry_total_size;
|
||||
if (log_head_offset >= log_area_size) {
|
||||
log_head_offset -= log_area_size; // Wrap around
|
||||
}
|
||||
|
||||
if (log_mutex) xSemaphoreGive(log_mutex);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// TEST FUNCTIONS FOR VARIABLE-LENGTH LOGS
|
||||
// ============================================================================
|
||||
|
||||
esp_err_t write_dummy_log_1(void) {
|
||||
ESP_LOGI(TAG, "Writing dummy variable-length log pattern 1");
|
||||
|
||||
if (log_mutex) xSemaphoreTake(log_mutex, portMAX_DELAY);
|
||||
log_head_index = 0;
|
||||
log_tail_index = 0;
|
||||
log_head_offset = 0;
|
||||
log_tail_offset = 0;
|
||||
if (log_mutex) xSemaphoreGive(log_mutex);
|
||||
|
||||
uint32_t log_area_end = storage_partition->size;
|
||||
uint32_t max_entries = (log_area_end - LOG_START_OFFSET) / LOG_ENTRY_SIZE;
|
||||
for (uint32_t i=0; i<max_entries*3/2; i++) {
|
||||
ESP_LOGI(TAG, "log[%ld]", (long)i);
|
||||
char entry[32] = {32, i>>24,i>>16,i>>8,i>>0};
|
||||
write_log(entry);
|
||||
// Write varied-size entries
|
||||
for (uint32_t i = 0; i < 100; i++) {
|
||||
uint8_t size = (i % 3 == 0) ? 16 : (i % 3 == 1) ? 48 : 32;
|
||||
uint8_t data[256];
|
||||
|
||||
// Fill with pattern
|
||||
for (uint8_t j = 0; j < size; j++) {
|
||||
data[j] = (i + j) & 0xFF;
|
||||
}
|
||||
|
||||
uint8_t type = LOG_TYPE_DATA + (i % 4); // Vary types
|
||||
write_log(type, data, size);
|
||||
|
||||
if (i % 10 == 0) {
|
||||
ESP_LOGI(TAG, "Wrote entry %lu (type=0x%02X, size=%d)",
|
||||
(unsigned long)i, type, size);
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t write_dummy_log_2(void) {
|
||||
ESP_LOGI(TAG, "Writing dummy variable-length log pattern 2");
|
||||
|
||||
if (log_mutex) xSemaphoreTake(log_mutex, portMAX_DELAY);
|
||||
log_head_index = 56;
|
||||
log_tail_index = 105;
|
||||
log_head_offset = 1000;
|
||||
log_tail_offset = 5000;
|
||||
if (log_mutex) xSemaphoreGive(log_mutex);
|
||||
|
||||
uint32_t log_area_end = storage_partition->size;
|
||||
uint32_t max_entries = (log_area_end - LOG_START_OFFSET) / LOG_ENTRY_SIZE;
|
||||
for (uint32_t i=0; i<max_entries*3/2; i++) {
|
||||
ESP_LOGI(TAG, "log[%ld]", (long)i);
|
||||
char entry[32] = {32, i>>24,i>>16,i>>8,i>>0};
|
||||
write_log(entry);
|
||||
for (uint32_t i = 0; i < 50; i++) {
|
||||
uint8_t size = 10 + (i * 3) % 200; // Varied sizes
|
||||
uint8_t data[256];
|
||||
memset(data, 0xAA + i, size);
|
||||
|
||||
write_log(LOG_TYPE_SENSOR, data, size);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t write_dummy_log_3(void) {
|
||||
ESP_LOGI(TAG, "Writing dummy variable-length log pattern 3");
|
||||
|
||||
if (log_mutex) xSemaphoreTake(log_mutex, portMAX_DELAY);
|
||||
log_head_index = 105;
|
||||
log_tail_index = 34;
|
||||
log_head_offset = 8000;
|
||||
log_tail_offset = 2000;
|
||||
if (log_mutex) xSemaphoreGive(log_mutex);
|
||||
|
||||
uint32_t log_area_end = storage_partition->size;
|
||||
uint32_t max_entries = (log_area_end - LOG_START_OFFSET) / LOG_ENTRY_SIZE;
|
||||
for (uint32_t i=0; i<max_entries*3/2; i++) {
|
||||
ESP_LOGI(TAG, "log[%ld]", (long)i);
|
||||
char entry[32] = {32, i>>24,i>>16,i>>8,i>>0};
|
||||
write_log(entry);
|
||||
// Write maximum-size entries
|
||||
for (uint32_t i = 0; i < 20; i++) {
|
||||
uint8_t data[LOG_MAX_PAYLOAD];
|
||||
for (uint16_t j = 0; j < LOG_MAX_PAYLOAD; j++) {
|
||||
data[j] = (i * 17 + j) & 0xFF;
|
||||
}
|
||||
|
||||
write_log(LOG_TYPE_DEBUG, data, LOG_MAX_PAYLOAD);
|
||||
|
||||
ESP_LOGI(TAG, "Wrote max-size entry %lu", (unsigned long)i);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user