From 1231be7f721db2fe921907cdd945323ff5a89fa0 Mon Sep 17 00:00:00 2001 From: Krzychuo Date: Mon, 23 Mar 2026 01:36:54 +0100 Subject: [PATCH 1/3] Started rewriting logging --- src/kernel/logging/klog.c | 106 +++++++++++++++++++++++++++++++++----- src/kernel/logging/klog.h | 4 +- 2 files changed, 96 insertions(+), 14 deletions(-) diff --git a/src/kernel/logging/klog.c b/src/kernel/logging/klog.c index 2a5d7096..2d7f5012 100644 --- a/src/kernel/logging/klog.c +++ b/src/kernel/logging/klog.c @@ -1,5 +1,7 @@ #include "klog.h" +#include +#include #include #include @@ -7,35 +9,115 @@ // Right now I will leave it as is, will change once the basic kernel at least runs. #include "debug/debug_stdio.h" -static u32 g_indent_level = 0; +// static u32 g_indent_level = 0; static const char* g_prefixes[] = {"[ERROR]", "[WARNING]", "[ ]", "[~]"}; +static const char* overwrite_warning = "[WARNING]Some of the logs were lost due to too small size of buffer"; -void klog_indent_increase() { - ++g_indent_level; +#ifdef __DEBUG__ +#define RING_BUF_SIZE 1<<20 +#else +#define RING_BUF_SIZE 1<<16 +#endif // !__DEBUG__ + +#define TEMP_BUF_SIZE 1<<12 + +typedef struct { + char ring[RING_BUF_SIZE]; + i32 read; + i32 write; + bool full; +} ring_buffer; + +static ring_buffer buffer; + +size_t available_space(const ring_buffer* buf) { + if (buf->full) return 0; + if (buf->write >= buf->read) + return RING_BUF_SIZE - (buf->write - buf->read); + else + return buf->read - buf->write; +} + +void put_char(ring_buffer* buf, char c){ + buf->ring[buf->write++] = c; + buf->write %= RING_BUF_SIZE; + if(buf->full){ + buf->read = (buf->read + 1) % RING_BUF_SIZE; + } + buf->full = buf->read == buf->write; +} + +void put_string(ring_buffer* buf, const char* str){ + size_t it = 0; + while(str[it]){ + put_char(buf, str[it++]); + } } -void klog_indent_decrease() { - if (g_indent_level != 0) - --g_indent_level; +void put_msg(ring_buffer* buf, const char* msg, int msg_len){ + if ((size_t)msg_len > available_space(buf)) + put_string(buf, overwrite_warning); + put_string(buf, msg); } +char get_char(ring_buffer* buf){ + if(buf->read == buf->write && !buf->full) + return 0; + char ret = buf->ring[buf->read++]; + buf->read %= RING_BUF_SIZE; + buf->full = false; + return ret; +} + +// void klog_indent_increase() { +// ++g_indent_level; +// } + +// void klog_indent_decrease() { +// if (g_indent_level != 0) +// --g_indent_level; +// } + static void klogv(klog_severity_level_t loglvl, const char* fmt, va_list va) { - (void)fmt; - (void)va; + static char temp_buffer[TEMP_BUF_SIZE]; if (loglvl > KLSL_TRACE) { KLOGLN_ERROR("Invalid loglvl passed to klog"); loglvl = KLSL_ERROR; } - DEBUG_PUTGAP(g_indent_level); - DEBUG_PRINTF("%s ", g_prefixes[loglvl]); - DEBUG_VPRINTF(fmt, va); + const char* prefix = g_prefixes[loglvl]; + size_t prefix_len = 0; + while (prefix[prefix_len]) ++prefix_len; + + for (size_t i=0;i= sizeof(temp_buffer)) { + // Truncated + written = sizeof(temp_buffer) - 1; + } + + put_msg(&buffer, &temp_buffer, written); + + // DEBUG_PUTGAP(g_indent_level); + // DEBUG_PRINTF("%s ", g_prefixes[loglvl]); + // DEBUG_VPRINTF(fmt, va); } static void kloglnv(klog_severity_level_t loglvl, const char* fmt, va_list va) { klogv(loglvl, fmt, va); - DEBUG_PUTC('\n'); + put_msg(&buffer, "\n", 1); + // DEBUG_PUTC('\n'); } void klog(klog_severity_level_t loglvl, const char* fmt, ...) { diff --git a/src/kernel/logging/klog.h b/src/kernel/logging/klog.h index 91000474..63f6c8ee 100644 --- a/src/kernel/logging/klog.h +++ b/src/kernel/logging/klog.h @@ -10,8 +10,8 @@ typedef enum { KLSL_TRACE = 3, } klog_severity_level_t; -void klog_indent_increase(); -void klog_indent_decrease(); +// void klog_indent_increase(); +// void klog_indent_decrease(); [[gnu::format(printf, 2, 3)]] void klog(klog_severity_level_t loglvl, const char* fmt, ...); From 46eb5baf371d7cd2e42d74abd9507cd3323d4239 Mon Sep 17 00:00:00 2001 From: Krzychuo Date: Sun, 29 Mar 2026 14:03:09 +0200 Subject: [PATCH 2/3] Added uart interface, formated and cleaned up the code --- src/kernel/logging/klog.c | 127 ++++++++++++++++++++++---------------- src/kernel/logging/klog.h | 6 +- 2 files changed, 79 insertions(+), 54 deletions(-) diff --git a/src/kernel/logging/klog.c b/src/kernel/logging/klog.c index 2d7f5012..678adef6 100644 --- a/src/kernel/logging/klog.c +++ b/src/kernel/logging/klog.c @@ -1,113 +1,136 @@ #include "klog.h" -#include -#include +#include <../../external/include/stb_sprintf.h> #include #include -// NOTE: In the future this lib should manage logging (formating and outputing to the screen or uart) on its own. -// Right now I will leave it as is, will change once the basic kernel at least runs. #include "debug/debug_stdio.h" -// static u32 g_indent_level = 0; +static u32 g_indent_level = 0; static const char* g_prefixes[] = {"[ERROR]", "[WARNING]", "[ ]", "[~]"}; -static const char* overwrite_warning = "[WARNING]Some of the logs were lost due to too small size of buffer"; +static const char* overflow_warning = "[WARNING]Some of the logs were lost due to overflow"; #ifdef __DEBUG__ -#define RING_BUF_SIZE 1<<20 + #define RING_BUF_SIZE (1 << 20) #else -#define RING_BUF_SIZE 1<<16 + #define RING_BUF_SIZE (1 << 16) #endif // !__DEBUG__ -#define TEMP_BUF_SIZE 1<<12 +#define TEMP_BUF_SIZE (1 << 12) typedef struct { char ring[RING_BUF_SIZE]; i32 read; i32 write; bool full; -} ring_buffer; + bool overflown; + void (*uart_tx)(char c); +} ring_buffer_t; -static ring_buffer buffer; +static ring_buffer_t buffer; -size_t available_space(const ring_buffer* buf) { - if (buf->full) return 0; - if (buf->write >= buf->read) - return RING_BUF_SIZE - (buf->write - buf->read); - else - return buf->read - buf->write; +static ring_buffer_t* get_buffer() { + return &buffer; } -void put_char(ring_buffer* buf, char c){ +static void put_char(ring_buffer_t* buf, const char c) { + if (c == '\0') + return; // Null characters are not suppossed to be logged. buf->ring[buf->write++] = c; buf->write %= RING_BUF_SIZE; - if(buf->full){ + if (buf->full) { buf->read = (buf->read + 1) % RING_BUF_SIZE; + buf->overflown = true; } buf->full = buf->read == buf->write; + if (buf->uart_tx) + buf->uart_tx(c); } -void put_string(ring_buffer* buf, const char* str){ +static void put_string(ring_buffer_t* buf, const char* str) { size_t it = 0; - while(str[it]){ - put_char(buf, str[it++]); - } + while (str[it]) put_char(buf, str[it++]); +} + +static void put_overflow_char(ring_buffer_t* buf, const char c) { + i32 temp_write = buf->write; + buf->ring[temp_write++] = c; + temp_write %= RING_BUF_SIZE; +} + +static void put_overflow_warning(ring_buffer_t* buf) { + size_t it = 0; + while (overflow_warning[it]) put_overflow_char(buf, overflow_warning[it++]); } -void put_msg(ring_buffer* buf, const char* msg, int msg_len){ - if ((size_t)msg_len > available_space(buf)) - put_string(buf, overwrite_warning); - put_string(buf, msg); +static void put_msg(ring_buffer_t* buf, const char* msg, const int msg_len) { + put_string(buf, msg); + if (buf->overflown) + put_overflow_warning(buf); } -char get_char(ring_buffer* buf){ - if(buf->read == buf->write && !buf->full) +static char get_char(ring_buffer_t* buf) { + if (buf->read == buf->write && !buf->full) return 0; - char ret = buf->ring[buf->read++]; + const char ret = buf->ring[buf->read++]; buf->read %= RING_BUF_SIZE; buf->full = false; return ret; } -// void klog_indent_increase() { -// ++g_indent_level; -// } +void flush_to_uart() { + ring_buffer_t* buf = get_buffer(); + if (!buf->uart_tx) + return; + char c; + while ((c = get_char(buf))) buf->uart_tx(c); +} + +void set_uart_tx_function(void (*uart_tx)(char c), bool flush) { + ring_buffer_t* buf = get_buffer(); + buf->uart_tx = uart_tx; + if (flush) + flush_to_uart(); +} + +void klog_indent_increase() { + ++g_indent_level; +} -// void klog_indent_decrease() { -// if (g_indent_level != 0) -// --g_indent_level; -// } +void klog_indent_decrease() { + if (g_indent_level != 0) + --g_indent_level; +} static void klogv(klog_severity_level_t loglvl, const char* fmt, va_list va) { - static char temp_buffer[TEMP_BUF_SIZE]; + char temp_buffer[TEMP_BUF_SIZE]; if (loglvl > KLSL_TRACE) { KLOGLN_ERROR("Invalid loglvl passed to klog"); loglvl = KLSL_ERROR; } - const char* prefix = g_prefixes[loglvl]; - size_t prefix_len = 0; - while (prefix[prefix_len]) ++prefix_len; + size_t written = 0; + for (u32 i = 0; i < g_indent_level && written < TEMP_BUF_SIZE - 1; i++) temp_buffer[written++] = ' '; - for (size_t i=0;i= sizeof(temp_buffer)) { - // Truncated + // stbsp_vsnprintf doesn't return errors, so just check for truncation + if (n < 0) + n = 0; + written += (size_t)n; + + if (written >= sizeof(temp_buffer)) written = sizeof(temp_buffer) - 1; - } + temp_buffer[written] = '\0'; - put_msg(&buffer, &temp_buffer, written); + put_msg(&buffer, temp_buffer, written); // DEBUG_PUTGAP(g_indent_level); // DEBUG_PRINTF("%s ", g_prefixes[loglvl]); diff --git a/src/kernel/logging/klog.h b/src/kernel/logging/klog.h index 63f6c8ee..2aa0c5e1 100644 --- a/src/kernel/logging/klog.h +++ b/src/kernel/logging/klog.h @@ -10,8 +10,10 @@ typedef enum { KLSL_TRACE = 3, } klog_severity_level_t; -// void klog_indent_increase(); -// void klog_indent_decrease(); +void flush_to_uart(); +void set_uart_tx_function(void (*uart_tx)(char c), bool flush); +void klog_indent_increase(); +void klog_indent_decrease(); [[gnu::format(printf, 2, 3)]] void klog(klog_severity_level_t loglvl, const char* fmt, ...); From 203537975373084d5ccbbc5ac25142e46a94d91a Mon Sep 17 00:00:00 2001 From: Krzychuo Date: Sun, 29 Mar 2026 14:03:09 +0200 Subject: [PATCH 3/3] Added uart interface, formated and cleaned up the code --- src/kernel/logging/klog.c | 127 ++++++++++++++++++++++---------------- src/kernel/logging/klog.h | 6 +- 2 files changed, 78 insertions(+), 55 deletions(-) diff --git a/src/kernel/logging/klog.c b/src/kernel/logging/klog.c index 2d7f5012..ab9c9c59 100644 --- a/src/kernel/logging/klog.c +++ b/src/kernel/logging/klog.c @@ -1,113 +1,134 @@ #include "klog.h" -#include -#include +#include <../../external/include/stb_sprintf.h> #include #include -// NOTE: In the future this lib should manage logging (formating and outputing to the screen or uart) on its own. -// Right now I will leave it as is, will change once the basic kernel at least runs. #include "debug/debug_stdio.h" -// static u32 g_indent_level = 0; +static u32 g_indent_level = 0; static const char* g_prefixes[] = {"[ERROR]", "[WARNING]", "[ ]", "[~]"}; -static const char* overwrite_warning = "[WARNING]Some of the logs were lost due to too small size of buffer"; +static const char* g_overflow_warning = "[WARNING]Some of the logs were lost due to overflow"; #ifdef __DEBUG__ -#define RING_BUF_SIZE 1<<20 + #define RING_BUF_SIZE (1 << 20) #else -#define RING_BUF_SIZE 1<<16 + #define RING_BUF_SIZE (1 << 16) #endif // !__DEBUG__ -#define TEMP_BUF_SIZE 1<<12 +#define TEMP_BUF_SIZE (1 << 12) typedef struct { char ring[RING_BUF_SIZE]; i32 read; i32 write; bool full; -} ring_buffer; + bool overflown; + void (*uart_tx)(char c); +} ring_buffer_t; -static ring_buffer buffer; +static ring_buffer_t g_buffer; -size_t available_space(const ring_buffer* buf) { - if (buf->full) return 0; - if (buf->write >= buf->read) - return RING_BUF_SIZE - (buf->write - buf->read); - else - return buf->read - buf->write; +static ring_buffer_t* get_buffer() { + return &g_buffer; } -void put_char(ring_buffer* buf, char c){ +static void put_char(ring_buffer_t* buf, const char c) { + if (c == '\0') + return; // Null characters are not suppossed to be logged. buf->ring[buf->write++] = c; buf->write %= RING_BUF_SIZE; - if(buf->full){ + if (buf->full) { buf->read = (buf->read + 1) % RING_BUF_SIZE; + buf->overflown = true; } buf->full = buf->read == buf->write; + if (buf->uart_tx) + buf->uart_tx(c); } -void put_string(ring_buffer* buf, const char* str){ +static void put_string(ring_buffer_t* buf, const char* str) { size_t it = 0; - while(str[it]){ - put_char(buf, str[it++]); + while (str[it]) put_char(buf, str[it++]); +} + +static void put_overflow_warning(ring_buffer_t* buf) { + size_t it = 0; + i32 temp_write = buf->write; + while (g_overflow_warning[it]){ + buf->ring[temp_write++] = g_overflow_warning; + temp_write %= RING_BUF_SIZE; } } -void put_msg(ring_buffer* buf, const char* msg, int msg_len){ - if ((size_t)msg_len > available_space(buf)) - put_string(buf, overwrite_warning); - put_string(buf, msg); +static void put_msg(ring_buffer_t* buf, const char* msg) { + put_string(buf, msg); + if (buf->overflown) + put_overflow_warning(buf); } -char get_char(ring_buffer* buf){ - if(buf->read == buf->write && !buf->full) +static char get_char(ring_buffer_t* buf) { + if (buf->read == buf->write && !buf->full) return 0; - char ret = buf->ring[buf->read++]; + const char ret = buf->ring[buf->read++]; buf->read %= RING_BUF_SIZE; buf->full = false; return ret; } -// void klog_indent_increase() { -// ++g_indent_level; -// } +void flush_to_uart() { + ring_buffer_t* buf = get_buffer(); + if (!buf->uart_tx) + return; + char c; + while ((c = get_char(buf))) buf->uart_tx(c); +} -// void klog_indent_decrease() { -// if (g_indent_level != 0) -// --g_indent_level; -// } +void set_uart_tx_function(void (*uart_tx)(char c), bool flush) { + ring_buffer_t* buf = get_buffer(); + buf->uart_tx = uart_tx; + if (flush) + flush_to_uart(); +} + +void klog_indent_increase() { + ++g_indent_level; +} + +void klog_indent_decrease() { + if (g_indent_level != 0) + --g_indent_level; +} static void klogv(klog_severity_level_t loglvl, const char* fmt, va_list va) { - static char temp_buffer[TEMP_BUF_SIZE]; + char temp_buffer[TEMP_BUF_SIZE]; if (loglvl > KLSL_TRACE) { KLOGLN_ERROR("Invalid loglvl passed to klog"); loglvl = KLSL_ERROR; } - const char* prefix = g_prefixes[loglvl]; - size_t prefix_len = 0; - while (prefix[prefix_len]) ++prefix_len; + size_t written = 0; + for (u32 i = 0; i < g_indent_level && written < TEMP_BUF_SIZE - 1; i++) temp_buffer[written++] = ' '; - for (size_t i=0;i= sizeof(temp_buffer)) { - // Truncated - written = sizeof(temp_buffer) - 1; - } + // stbsp_vsnprintf doesn't return errors, so just check for truncation + if (n < 0) + n = 0; + written += (size_t)n; + + if (written >= TEMP_BUF_SIZE) + written = TEMP_BUF_SIZE - 1; + temp_buffer[written] = '\0'; - put_msg(&buffer, &temp_buffer, written); + put_msg(&g_buffer, temp_buffer); // DEBUG_PUTGAP(g_indent_level); // DEBUG_PRINTF("%s ", g_prefixes[loglvl]); @@ -116,7 +137,7 @@ static void klogv(klog_severity_level_t loglvl, const char* fmt, va_list va) { static void kloglnv(klog_severity_level_t loglvl, const char* fmt, va_list va) { klogv(loglvl, fmt, va); - put_msg(&buffer, "\n", 1); + put_msg(&g_buffer, "\n"); // DEBUG_PUTC('\n'); } diff --git a/src/kernel/logging/klog.h b/src/kernel/logging/klog.h index 63f6c8ee..2aa0c5e1 100644 --- a/src/kernel/logging/klog.h +++ b/src/kernel/logging/klog.h @@ -10,8 +10,10 @@ typedef enum { KLSL_TRACE = 3, } klog_severity_level_t; -// void klog_indent_increase(); -// void klog_indent_decrease(); +void flush_to_uart(); +void set_uart_tx_function(void (*uart_tx)(char c), bool flush); +void klog_indent_increase(); +void klog_indent_decrease(); [[gnu::format(printf, 2, 3)]] void klog(klog_severity_level_t loglvl, const char* fmt, ...);