K1Guitar/APP/app_log.c

227 lines
5.6 KiB
C
Raw Normal View History

#include "includes.h"
#include "SEGGER_RTT.h"
#include <stdarg.h>
#if APP_LOG_ENABLE
static char s_slots[APP_LOG_SLOT_COUNT][APP_LOG_SLOT_SIZE];
static uint16_t s_head;
static uint16_t s_count;
static uint32_t s_overflow;
static uint32_t s_boot_count;
static char s_ui_page[16] = "boot";
static char s_debug_level = 'D';
static char s_cmd_buf[48];
static uint8_t s_cmd_len;
static uint32_t app_log_ms(void)
{
return (uint32_t)(rt_tick_get() * 1000U / RT_TICK_PER_SECOND);
}
static void app_log_slot_store(const char *line)
{
uint16_t idx = s_head;
strncpy(s_slots[idx], line, APP_LOG_SLOT_SIZE - 1U);
s_slots[idx][APP_LOG_SLOT_SIZE - 1U] = '\0';
s_head = (uint16_t)((s_head + 1U) % APP_LOG_SLOT_COUNT);
if (s_count < APP_LOG_SLOT_COUNT) {
s_count++;
} else {
s_overflow++;
}
}
void app_log_set_ui_page(const char *name)
{
if (name == NULL) {
return;
}
strncpy(s_ui_page, name, sizeof(s_ui_page) - 1U);
s_ui_page[sizeof(s_ui_page) - 1U] = '\0';
}
void app_log_write(char level, const char *cat, const char *fmt, ...)
{
char line[APP_LOG_SLOT_SIZE];
va_list ap;
int n;
if (level == 'D' && s_debug_level != 'D') {
return;
}
n = snprintf(line, sizeof(line), "[%05u][%c][%-4s] ",
(unsigned)app_log_ms(), level, cat);
if (n < 0) {
return;
}
if ((size_t)n >= sizeof(line)) {
n = (int)sizeof(line) - 1;
}
va_start(ap, fmt);
vsnprintf(line + n, sizeof(line) - (size_t)n, fmt, ap);
va_end(ap);
app_log_slot_store(line);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "\n");
}
static void app_log_dump_ram(void)
{
uint16_t start;
uint16_t i;
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "LOG_DUMP_BEGIN\n");
{
char meta[APP_LOG_SLOT_SIZE];
snprintf(meta, sizeof(meta),
"meta boot=%u lines=%u overflow=%u ui=%s",
(unsigned)s_boot_count,
(unsigned)s_count,
(unsigned)s_overflow,
s_ui_page);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, meta);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "\n");
}
if (s_count == 0U) {
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "LOG_DUMP_END\n");
return;
}
start = (s_count < APP_LOG_SLOT_COUNT)
? 0U
: s_head;
for (i = 0; i < s_count; i++) {
uint16_t idx = (uint16_t)((start + i) % APP_LOG_SLOT_COUNT);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, s_slots[idx]);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "\n");
}
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "LOG_DUMP_END\n");
}
static void app_log_clear_ram(void)
{
s_head = 0U;
s_count = 0U;
s_overflow = 0U;
memset(s_slots, 0, sizeof(s_slots));
LOG_I("LOG", "ram cleared");
}
static void app_log_print_status(void)
{
char line[APP_LOG_SLOT_SIZE];
snprintf(line, sizeof(line),
"LOG_STATUS boot=%u lines=%u overflow=%u level=%c ui=%s tick=%u",
(unsigned)s_boot_count,
(unsigned)s_count,
(unsigned)s_overflow,
s_debug_level,
s_ui_page,
(unsigned)app_log_ms());
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "\n");
}
static void app_log_sys_reset(void)
{
LOG_I("SYS", "reset via RTT");
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "SYS_RESET_OK\n");
rt_thread_mdelay(20);
__disable_irq();
nvic_system_reset();
}
uint8_t app_log_try_command(const char *cmd)
{
if (cmd == NULL || cmd[0] == '\0') {
return 0U;
}
if (strncmp(cmd, "log dump", 8) == 0) {
app_log_dump_ram();
return 1U;
}
if (strncmp(cmd, "log clear", 9) == 0) {
app_log_clear_ram();
return 1U;
}
if (strncmp(cmd, "log status", 10) == 0) {
app_log_print_status();
return 1U;
}
if (strncmp(cmd, "log level ", 10) == 0 && cmd[10] != '\0') {
s_debug_level = cmd[10];
LOG_I("LOG", "level set %c", s_debug_level);
return 1U;
}
if (strncmp(cmd, "sys reset", 9) == 0) {
app_log_sys_reset();
return 1U;
}
return 0U;
}
static void app_log_feed_char(char c)
{
if (c == '\r' || c == '\n' || c == '\0') {
if (s_cmd_len > 0U) {
s_cmd_buf[s_cmd_len] = '\0';
(void)app_log_try_command(s_cmd_buf);
}
s_cmd_len = 0U;
s_cmd_buf[0] = '\0';
return;
}
if (s_cmd_len + 1U >= sizeof(s_cmd_buf)) {
s_cmd_len = 0U;
}
s_cmd_buf[s_cmd_len++] = c;
s_cmd_buf[s_cmd_len] = '\0';
if (strstr(s_cmd_buf, "sys reset") != NULL) {
s_cmd_len = 0U;
s_cmd_buf[0] = '\0';
(void)app_log_try_command("sys reset");
}
}
void app_log_poll(void)
{
char rx[16];
unsigned read_len;
unsigned i;
read_len = SEGGER_RTT_Read(APP_LOG_RTT_CHANNEL, rx, sizeof(rx));
if (read_len == 0U) {
return;
}
for (i = 0; i < read_len; i++) {
app_log_feed_char(rx[i]);
}
}
void app_log_init(void)
{
s_boot_count++;
LOG_I("BOOT", "app_log init boot=%u", (unsigned)s_boot_count);
}
#else
void app_log_init(void) {}
void app_log_write(char level, const char *cat, const char *fmt, ...) { (void)level; (void)cat; (void)fmt; }
void app_log_poll(void) {}
uint8_t app_log_try_command(const char *cmd) { (void)cmd; return 0U; }
void app_log_set_ui_page(const char *name) { (void)name; }
#endif /* APP_LOG_ENABLE */