This commit is contained in:
152
main/serial_log.c
Normal file
152
main/serial_log.c
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* MTG RFID Companion - In-memory Serial Log Ring Buffer
|
||||
*/
|
||||
|
||||
#include "serial_log.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#define LOG_BUFFER_SIZE (16 * 1024)
|
||||
|
||||
static vprintf_like_t s_prev_vprintf = NULL;
|
||||
static char s_ring_buffer[LOG_BUFFER_SIZE];
|
||||
static uint32_t s_write_idx = 0;
|
||||
static uint32_t s_total_bytes = 0;
|
||||
static portMUX_TYPE s_log_mux = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
static int serial_log_vprintf(const char *fmt, va_list args)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* Maintain original console/UART output */
|
||||
if (s_prev_vprintf != NULL) {
|
||||
va_list copy1;
|
||||
va_copy(copy1, args);
|
||||
ret = s_prev_vprintf(fmt, copy1);
|
||||
va_end(copy1);
|
||||
} else {
|
||||
va_list copy1;
|
||||
va_copy(copy1, args);
|
||||
ret = vprintf(fmt, copy1);
|
||||
va_end(copy1);
|
||||
}
|
||||
|
||||
/* Format message into local buffer */
|
||||
char line_buf[512];
|
||||
va_list copy2;
|
||||
va_copy(copy2, args);
|
||||
int written = vsnprintf(line_buf, sizeof(line_buf), fmt, copy2);
|
||||
va_end(copy2);
|
||||
|
||||
if (written > 0) {
|
||||
size_t len = (size_t)written;
|
||||
if (len >= sizeof(line_buf)) {
|
||||
len = sizeof(line_buf) - 1;
|
||||
}
|
||||
|
||||
portENTER_CRITICAL(&s_log_mux);
|
||||
size_t space_to_end = LOG_BUFFER_SIZE - s_write_idx;
|
||||
if (len <= space_to_end) {
|
||||
memcpy(&s_ring_buffer[s_write_idx], line_buf, len);
|
||||
s_write_idx = (s_write_idx + len) % LOG_BUFFER_SIZE;
|
||||
} else {
|
||||
memcpy(&s_ring_buffer[s_write_idx], line_buf, space_to_end);
|
||||
memcpy(&s_ring_buffer[0], line_buf + space_to_end, len - space_to_end);
|
||||
s_write_idx = (uint32_t)(len - space_to_end);
|
||||
}
|
||||
s_total_bytes += (uint32_t)len;
|
||||
portEXIT_CRITICAL(&s_log_mux);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t serial_log_init(void)
|
||||
{
|
||||
portENTER_CRITICAL(&s_log_mux);
|
||||
s_total_bytes = 0;
|
||||
s_write_idx = 0;
|
||||
memset(s_ring_buffer, 0, sizeof(s_ring_buffer));
|
||||
portEXIT_CRITICAL(&s_log_mux);
|
||||
|
||||
s_prev_vprintf = esp_log_set_vprintf(serial_log_vprintf);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
size_t serial_log_read(uint32_t from_offset, char *dest, size_t max_len, uint32_t *next_offset)
|
||||
{
|
||||
if (!dest || max_len == 0) {
|
||||
if (next_offset) {
|
||||
*next_offset = from_offset;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t copied = 0;
|
||||
|
||||
portENTER_CRITICAL(&s_log_mux);
|
||||
|
||||
uint32_t total = s_total_bytes;
|
||||
uint32_t oldest = (total > LOG_BUFFER_SIZE) ? (total - LOG_BUFFER_SIZE) : 0;
|
||||
|
||||
if (from_offset < oldest || from_offset == 0) {
|
||||
from_offset = oldest;
|
||||
}
|
||||
|
||||
if (from_offset >= total) {
|
||||
if (next_offset) {
|
||||
*next_offset = total;
|
||||
}
|
||||
dest[0] = '\0';
|
||||
portEXIT_CRITICAL(&s_log_mux);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t to_read = total - from_offset;
|
||||
if (to_read > (uint32_t)(max_len - 1)) {
|
||||
to_read = (uint32_t)(max_len - 1);
|
||||
}
|
||||
|
||||
size_t start_idx = from_offset % LOG_BUFFER_SIZE;
|
||||
size_t chunk1 = LOG_BUFFER_SIZE - start_idx;
|
||||
|
||||
if (to_read <= chunk1) {
|
||||
memcpy(dest, &s_ring_buffer[start_idx], to_read);
|
||||
} else {
|
||||
memcpy(dest, &s_ring_buffer[start_idx], chunk1);
|
||||
memcpy(dest + chunk1, &s_ring_buffer[0], to_read - chunk1);
|
||||
}
|
||||
|
||||
copied = to_read;
|
||||
dest[copied] = '\0';
|
||||
|
||||
if (next_offset) {
|
||||
*next_offset = from_offset + (uint32_t)to_read;
|
||||
}
|
||||
|
||||
portEXIT_CRITICAL(&s_log_mux);
|
||||
|
||||
return copied;
|
||||
}
|
||||
|
||||
void serial_log_clear(void)
|
||||
{
|
||||
portENTER_CRITICAL(&s_log_mux);
|
||||
s_total_bytes = 0;
|
||||
s_write_idx = 0;
|
||||
memset(s_ring_buffer, 0, sizeof(s_ring_buffer));
|
||||
portEXIT_CRITICAL(&s_log_mux);
|
||||
}
|
||||
|
||||
uint32_t serial_log_get_total_bytes(void)
|
||||
{
|
||||
uint32_t total;
|
||||
portENTER_CRITICAL(&s_log_mux);
|
||||
total = s_total_bytes;
|
||||
portEXIT_CRITICAL(&s_log_mux);
|
||||
return total;
|
||||
}
|
||||
Reference in New Issue
Block a user