From 0d5deffa587345edf99c9bf1c5908f5a4f6b8722 Mon Sep 17 00:00:00 2001 From: Steins7 Date: Sun, 7 Apr 2024 16:47:34 +0200 Subject: [PATCH 01/11] Update debug service to use new dma_mbuf --- srv/debug.c | 81 +++++++++++++++++++++++++++++++++++++++++------------ srv/debug.h | 3 +- 2 files changed, 64 insertions(+), 20 deletions(-) diff --git a/srv/debug.c b/srv/debug.c index 44711ac..2937fe5 100644 --- a/srv/debug.c +++ b/srv/debug.c @@ -8,20 +8,20 @@ //--includes-------------------------------------------------------------------- #include "debug.h" +#include "dma_mbuf.h" //--local definitions----------------------------------------------------------- -#define BUFFER_SIZE 83 //80 char line + \n + 2 bytes for index -#define BUFFER_NB 3 //1 buffer in write, one in transfer and one waiting +static void print_debug(char* str); + +#define BUFFER_SIZE 162 //(80 char line + \n) * 2 + //--local variables------------------------------------------------------------- -static enum UsartPeriph usart_periph; -static uint8_t tx_buffer1[BUFFER_SIZE]; -static uint8_t tx_buffer2[BUFFER_SIZE]; -static uint8_t tx_buffer3[BUFFER_SIZE]; -static uint8_t* tx_buffers[BUFFER_NB] = {tx_buffer1, tx_buffer2, tx_buffer3}; +static struct DmaMultiBuffer mbuf; +static uint8_t tx_buffer[BUFFER_SIZE]; //--public functions------------------------------------------------------------ @@ -31,30 +31,75 @@ static uint8_t* tx_buffers[BUFFER_NB] = {tx_buffer1, tx_buffer2, tx_buffer3}; void _debug_init(enum UsartPeriph usart, enum GpioPort tx_port, enum GpioPin tx_pin) { - usart_periph = usart; gpio_configure(tx_port, tx_pin, GPIO_MODE_OUTPUT_FAST, GPIO_CONFIG_OUT_ALT_PUSH_PULL); - usart_configure(usart_periph, USART_CONFIG_8N1, 1152000); - - usart_set_tx_buffer(USART_PERIPH_3, tx_buffers, BUFFER_SIZE, BUFFER_NB, - DMA_CONFIG_PRIO_LOW); + usart_configure(usart, USART_CONFIG_8N1, 1000000); + dma_mbuf_configure(&mbuf,usart_configure_tx_dma(usart), + DMA_CONFIG_PRIO_LOW, tx_buffer, BUFFER_SIZE); debug_trace("\n"); - debug_trace("--------------------------------------------------------------------------------\n"); + debug_trace("------------------------------------------------------------------------------\n"); debug_trace("starting debug software\n"); debug_trace("compiled on " __DATE__ " at " __TIME__ "\n"); - debug_trace("--------------------------------------------------------------------------------\n"); + debug_trace("------------------------------------------------------------------------------\n"); } +#endif + +#if DEBUG_TRACE + void _debug_trace(char* format, ...) { - while(*format != '\0') { - while(usart_write_byte(usart_periph, *format)) {} - ++format; - } + print_debug("T:"); + print_debug(format); + + //ensure everything is written when done + while (dma_mbuf_switch(&mbuf)) {} +} + +#endif + +#if DEBUG_WARN + +void _debug_warn(char* format, ...) +{ + print_debug("W:"); + print_debug(format); + + //ensure everything is written when done + while (dma_mbuf_switch(&mbuf)) {} +} + +#endif + +#if DEBUG_ERROR + +void _debug_error(char* format, ...) +{ + print_debug("E:"); + print_debug(format); + + //ensure everything is written when done + while (dma_mbuf_switch(&mbuf)) {} } #endif //--local functions------------------------------------------------------------- +#if DEBUG_TRACE || DEBUG_WARN || DEBUG_ERROR + +static void print_debug(char* str) +{ + while (*str != '\0') { + if (dma_mbuf_write_byte(&mbuf, *str)) + { + //buffer is full, wait until transfer started + while (dma_mbuf_switch(&mbuf)) {} + } + ++str; + } +} + +#endif + diff --git a/srv/debug.h b/srv/debug.h index cd511d6..b954511 100644 --- a/srv/debug.h +++ b/srv/debug.h @@ -13,12 +13,11 @@ #include "../drv/usart.h" #include "../drv/gpio.h" -#include "stdint.h" - #define DEBUG_TRACE 1 #define DEBUG_WARN 0 #define DEBUG_ERROR 0 + //--type definitions------------------------------------------------------------ #if DEBUG_TRACE || DEBUG_WARN || DEBUG_ERROR From 3dc548332ff26761cba1dbcef527f310a32467f1 Mon Sep 17 00:00:00 2001 From: Steins7 Date: Mon, 15 Apr 2024 16:54:54 +0200 Subject: [PATCH 02/11] Implement basic string formatting --- srv/debug.c | 27 +++++---- srv/format.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++ srv/format.h | 33 +++++++++++ 3 files changed, 211 insertions(+), 11 deletions(-) create mode 100644 srv/format.c create mode 100644 srv/format.h diff --git a/srv/debug.c b/srv/debug.c index 2937fe5..00f1265 100644 --- a/srv/debug.c +++ b/srv/debug.c @@ -9,11 +9,12 @@ #include "debug.h" #include "dma_mbuf.h" +#include "format.h" //--local definitions----------------------------------------------------------- -static void print_debug(char* str); +static uint32_t write_debug(uint8_t c, void* arg); #define BUFFER_SIZE 162 //(80 char line + \n) * 2 @@ -50,8 +51,13 @@ void _debug_init(enum UsartPeriph usart, enum GpioPort tx_port, void _debug_trace(char* format, ...) { - print_debug("T:"); - print_debug(format); + write_debug('T', nullptr); + write_debug(':', nullptr); + va_list va; + va_start(va, format); + format_vfctprintf(write_debug, nullptr, format, va); + va_end(va); + write_debug('\n', nullptr); //ensure everything is written when done while (dma_mbuf_switch(&mbuf)) {} @@ -89,16 +95,15 @@ void _debug_error(char* format, ...) #if DEBUG_TRACE || DEBUG_WARN || DEBUG_ERROR -static void print_debug(char* str) +static uint32_t write_debug(uint8_t c, void* arg) { - while (*str != '\0') { - if (dma_mbuf_write_byte(&mbuf, *str)) - { - //buffer is full, wait until transfer started - while (dma_mbuf_switch(&mbuf)) {} - } - ++str; + while (dma_mbuf_write_byte(&mbuf, c)) + { + //buffer is full, wait until transfer started + while (dma_mbuf_switch(&mbuf)) {} } + + return 0; } #endif diff --git a/srv/format.c b/srv/format.c new file mode 100644 index 0000000..cad9774 --- /dev/null +++ b/srv/format.c @@ -0,0 +1,162 @@ +/** @file format.c + * Module handling various formating functions + * + * The module provides a lightweight printf function and the attached tools + */ + +//--includes-------------------------------------------------------------------- + +#include "format.h" + + +//--local definitions----------------------------------------------------------- + +struct BufferArg { + char* restrict buffer; + uint32_t buffer_size; + uint32_t byte_index; +}; + +uint32_t buffer_write(uint8_t byte, void* arg); +uint32_t render_format(FormatCallback callback, void* arg, + const char* restrict format, va_list va); +uint32_t render_signed(FormatCallback callback, void* arg, + va_list va, uint8_t size, uint8_t base); +uint32_t render_unsigned(FormatCallback callback, void* arg, + va_list* va, uint8_t size, uint8_t base); + + +//--local variables------------------------------------------------------------- + +//--public functions------------------------------------------------------------ + +uint32_t format_snprintf(char* restrict buffer, uint32_t buffer_size, + const char* restrict format, ...) +{ + va_list va; + va_start(va, format); + struct BufferArg arg = { buffer, buffer_size, 0 }; + uint32_t ret = render_format(buffer_write, &arg, format, va); + va_end(va); + return ret; +} + +uint32_t format_fctprintf(FormatCallback callback, void* arg, + const char* restrict format, ...) +{ + va_list va; + va_start(va, format); + uint32_t ret = render_format(callback, arg, format, va); + va_end(va); + return ret; +} + +uint32_t format_vfctprintf(FormatCallback callback, void* arg, + const char* restrict format, va_list va) +{ + return render_format(callback, arg, format, va); +} + +//--local functions------------------------------------------------------------- + +uint32_t buffer_write(uint8_t byte, void* arg) +{ + struct BufferArg* buffer_arg = (struct BufferArg*)arg; + if (buffer_arg->byte_index >= buffer_arg->buffer_size) { + return 1; + } + + buffer_arg->buffer[buffer_arg->byte_index] = byte; + ++buffer_arg->byte_index; + return 0; +} + +uint32_t render_format(FormatCallback callback, void* arg, + const char* restrict format, va_list va) +{ + uint8_t size; + bool in_format = false; + + for (const char* c = format; *c != '\0'; ++c) { + + if (in_format) { + switch (*c) { + case '%': + callback('%', arg); + break; + case 'h': + size = size / 2; + continue; + case 'l': + size = size * 2; + continue; + case 'c': + callback((uint8_t)va_arg(va, uint32_t), arg); + break; + case 's': + { + const char* str = va_arg(va, const char*); + for (const char* c2 = str; *c2 != '\0'; ++c2) { + callback(*c2, arg); + } + } + break; + case 'i': + //render_signed(callback, arg, va, size, 10); + break; + case 'u': + render_unsigned(callback, arg, &va, size, 10); + break; + case 'x': + render_unsigned(callback, arg, &va, size, 16); + break; + default: + //TODO manage error + break; + } + } else { + switch (*c) { + case '%': + in_format = true; + size = 4; + continue; + default: + callback(*c, arg); + break; + } + } + + in_format = false; + } + + return 0; +} + +uint32_t render_unsigned(FormatCallback callback, void* arg, + va_list* va, uint8_t size, uint8_t base) +{ + uint32_t number = va_arg(*va, uint32_t); + uint32_t base_power = base; + + while (base_power <= number) { + base_power *= base; + } + + while (base_power > 1) { + base_power /= base; + + uint8_t digit = 0; + while (number >= base_power) { + number -= base_power; + ++digit; + } + + if (digit < 10) { + callback('0' + digit, arg); + } else { + callback('A' + digit - 10, arg); + } + } + + return 0; +} diff --git a/srv/format.h b/srv/format.h new file mode 100644 index 0000000..04de136 --- /dev/null +++ b/srv/format.h @@ -0,0 +1,33 @@ +/** @file format.h + * Module handling various formating functions + * + * The module provides a lightweight printf function and the attached tools + */ + +#ifndef _FORMAT_H_ +#define _FORMAT_H_ + +//--includes-------------------------------------------------------------------- + +#include +#include + + +//--type definitions------------------------------------------------------------ + +typedef uint32_t (*FormatCallback)(uint8_t byte, void* arg); + + +//--functions------------------------------------------------------------------- + +uint32_t format_snprintf(char* restrict buffer, uint32_t buffer_size, + const char* restrict format, ...); + +uint32_t format_fctprintf(FormatCallback callback, void* arg, + const char* restrict format, ...); + +uint32_t format_vfctprintf(FormatCallback callback, void* arg, + const char* restrict format, va_list va); + +#endif //_FORMAT_H_ + From 727aadaba9a21a2ef3567f58162b16d2dd8dc9c0 Mon Sep 17 00:00:00 2001 From: Steins7 Date: Mon, 15 Apr 2024 17:04:35 +0200 Subject: [PATCH 03/11] Implement signed integer formating --- srv/format.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/srv/format.c b/srv/format.c index cad9774..11456a1 100644 --- a/srv/format.c +++ b/srv/format.c @@ -21,9 +21,9 @@ uint32_t buffer_write(uint8_t byte, void* arg); uint32_t render_format(FormatCallback callback, void* arg, const char* restrict format, va_list va); uint32_t render_signed(FormatCallback callback, void* arg, - va_list va, uint8_t size, uint8_t base); + int32_t number, uint8_t base); uint32_t render_unsigned(FormatCallback callback, void* arg, - va_list* va, uint8_t size, uint8_t base); + uint32_t number, uint8_t base); //--local variables------------------------------------------------------------- @@ -74,7 +74,6 @@ uint32_t buffer_write(uint8_t byte, void* arg) uint32_t render_format(FormatCallback callback, void* arg, const char* restrict format, va_list va) { - uint8_t size; bool in_format = false; for (const char* c = format; *c != '\0'; ++c) { @@ -84,12 +83,6 @@ uint32_t render_format(FormatCallback callback, void* arg, case '%': callback('%', arg); break; - case 'h': - size = size / 2; - continue; - case 'l': - size = size * 2; - continue; case 'c': callback((uint8_t)va_arg(va, uint32_t), arg); break; @@ -102,13 +95,13 @@ uint32_t render_format(FormatCallback callback, void* arg, } break; case 'i': - //render_signed(callback, arg, va, size, 10); + render_signed(callback, arg, va_arg(va, int32_t), 10); break; case 'u': - render_unsigned(callback, arg, &va, size, 10); + render_unsigned(callback, arg, va_arg(va, uint32_t), 10); break; case 'x': - render_unsigned(callback, arg, &va, size, 16); + render_unsigned(callback, arg, va_arg(va, uint32_t), 16); break; default: //TODO manage error @@ -118,7 +111,6 @@ uint32_t render_format(FormatCallback callback, void* arg, switch (*c) { case '%': in_format = true; - size = 4; continue; default: callback(*c, arg); @@ -132,10 +124,20 @@ uint32_t render_format(FormatCallback callback, void* arg, return 0; } -uint32_t render_unsigned(FormatCallback callback, void* arg, - va_list* va, uint8_t size, uint8_t base) +uint32_t render_signed(FormatCallback callback, void* arg, + int32_t number, uint8_t base) +{ + if (number < 0) { + callback('-', arg); + number = -number; + } + + return render_unsigned(callback, arg, (uint32_t)number, base); +} + +uint32_t render_unsigned(FormatCallback callback, void* arg, + uint32_t number, uint8_t base) { - uint32_t number = va_arg(*va, uint32_t); uint32_t base_power = base; while (base_power <= number) { From 075d9e17a64fece09cd8ccaa3d7b2e9524ed0689 Mon Sep 17 00:00:00 2001 From: Steins7 Date: Mon, 15 Apr 2024 17:17:05 +0200 Subject: [PATCH 04/11] Changed internal functions to static --- srv/format.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/srv/format.c b/srv/format.c index 11456a1..2694d02 100644 --- a/srv/format.c +++ b/srv/format.c @@ -17,12 +17,12 @@ struct BufferArg { uint32_t byte_index; }; -uint32_t buffer_write(uint8_t byte, void* arg); -uint32_t render_format(FormatCallback callback, void* arg, +static uint32_t buffer_write(uint8_t byte, void* arg); +static uint32_t render_format(FormatCallback callback, void* arg, const char* restrict format, va_list va); -uint32_t render_signed(FormatCallback callback, void* arg, +static uint32_t render_signed(FormatCallback callback, void* arg, int32_t number, uint8_t base); -uint32_t render_unsigned(FormatCallback callback, void* arg, +static uint32_t render_unsigned(FormatCallback callback, void* arg, uint32_t number, uint8_t base); @@ -59,7 +59,7 @@ uint32_t format_vfctprintf(FormatCallback callback, void* arg, //--local functions------------------------------------------------------------- -uint32_t buffer_write(uint8_t byte, void* arg) +static uint32_t buffer_write(uint8_t byte, void* arg) { struct BufferArg* buffer_arg = (struct BufferArg*)arg; if (buffer_arg->byte_index >= buffer_arg->buffer_size) { @@ -71,7 +71,7 @@ uint32_t buffer_write(uint8_t byte, void* arg) return 0; } -uint32_t render_format(FormatCallback callback, void* arg, +static uint32_t render_format(FormatCallback callback, void* arg, const char* restrict format, va_list va) { bool in_format = false; @@ -124,7 +124,7 @@ uint32_t render_format(FormatCallback callback, void* arg, return 0; } -uint32_t render_signed(FormatCallback callback, void* arg, +static uint32_t render_signed(FormatCallback callback, void* arg, int32_t number, uint8_t base) { if (number < 0) { @@ -135,7 +135,7 @@ uint32_t render_signed(FormatCallback callback, void* arg, return render_unsigned(callback, arg, (uint32_t)number, base); } -uint32_t render_unsigned(FormatCallback callback, void* arg, +static uint32_t render_unsigned(FormatCallback callback, void* arg, uint32_t number, uint8_t base) { uint32_t base_power = base; From 3bcb9c7df47938b05dbf5ac86bc81633193c6b12 Mon Sep 17 00:00:00 2001 From: Steins7 Date: Mon, 15 Apr 2024 17:17:23 +0200 Subject: [PATCH 05/11] Add error handling --- srv/format.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/srv/format.c b/srv/format.c index 2694d02..f3bc2c1 100644 --- a/srv/format.c +++ b/srv/format.c @@ -81,27 +81,37 @@ static uint32_t render_format(FormatCallback callback, void* arg, if (in_format) { switch (*c) { case '%': - callback('%', arg); + if (callback('%', arg)) return 1; break; case 'c': - callback((uint8_t)va_arg(va, uint32_t), arg); + if (callback((uint8_t)va_arg(va, uint32_t), arg)) { + return 1; + } break; case 's': { const char* str = va_arg(va, const char*); for (const char* c2 = str; *c2 != '\0'; ++c2) { - callback(*c2, arg); + if (callback(*c2, arg)) return 1; } } break; case 'i': - render_signed(callback, arg, va_arg(va, int32_t), 10); + if (render_signed(callback, arg, va_arg(va, int32_t), 10)) { + return 1; + } break; case 'u': - render_unsigned(callback, arg, va_arg(va, uint32_t), 10); + if (render_unsigned(callback, arg, + va_arg(va, uint32_t), 10)) { + return 1; + } break; case 'x': - render_unsigned(callback, arg, va_arg(va, uint32_t), 16); + if (render_unsigned(callback, arg, + va_arg(va, uint32_t), 16)) { + return 1; + } break; default: //TODO manage error @@ -113,7 +123,7 @@ static uint32_t render_format(FormatCallback callback, void* arg, in_format = true; continue; default: - callback(*c, arg); + if (callback(*c, arg)) return 1; break; } } @@ -154,9 +164,9 @@ static uint32_t render_unsigned(FormatCallback callback, void* arg, } if (digit < 10) { - callback('0' + digit, arg); + if (callback('0' + digit, arg)) return 1; } else { - callback('A' + digit - 10, arg); + if (callback('A' + digit - 10, arg)) return 1; } } From e477055e6e3f5bf631fffdd8d0469116f1e73b77 Mon Sep 17 00:00:00 2001 From: Steins7 Date: Mon, 15 Apr 2024 22:56:49 +0200 Subject: [PATCH 06/11] Implement right-justified padding --- srv/format.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 10 deletions(-) diff --git a/srv/format.c b/srv/format.c index f3bc2c1..ec4de76 100644 --- a/srv/format.c +++ b/srv/format.c @@ -21,9 +21,9 @@ static uint32_t buffer_write(uint8_t byte, void* arg); static uint32_t render_format(FormatCallback callback, void* arg, const char* restrict format, va_list va); static uint32_t render_signed(FormatCallback callback, void* arg, - int32_t number, uint8_t base); + int32_t number, uint8_t base, uint8_t width, bool zero_padding); static uint32_t render_unsigned(FormatCallback callback, void* arg, - uint32_t number, uint8_t base); + uint32_t number, uint8_t base, uint8_t width, bool zero_padding); //--local variables------------------------------------------------------------- @@ -74,7 +74,9 @@ static uint32_t buffer_write(uint8_t byte, void* arg) static uint32_t render_format(FormatCallback callback, void* arg, const char* restrict format, va_list va) { + uint8_t width = 0; bool in_format = false; + bool zero_padding = false; for (const char* c = format; *c != '\0'; ++c) { @@ -97,22 +99,40 @@ static uint32_t render_format(FormatCallback callback, void* arg, } break; case 'i': - if (render_signed(callback, arg, va_arg(va, int32_t), 10)) { + if (render_signed(callback, arg, va_arg(va, int32_t), + 10, width, zero_padding)) { return 1; } break; case 'u': - if (render_unsigned(callback, arg, - va_arg(va, uint32_t), 10)) { + if (render_unsigned(callback, arg, va_arg(va, uint32_t), + 10, width, zero_padding)) { return 1; } break; case 'x': - if (render_unsigned(callback, arg, - va_arg(va, uint32_t), 16)) { + if (render_unsigned(callback, arg, va_arg(va, uint32_t), + 16, width, zero_padding)) { return 1; } break; + case '0': + if (width == 0) { + zero_padding = true; + continue; + } + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + width *= 10; + width += (*c - '0'); + continue; default: //TODO manage error break; @@ -121,6 +141,8 @@ static uint32_t render_format(FormatCallback callback, void* arg, switch (*c) { case '%': in_format = true; + zero_padding = false; + width = 0; continue; default: if (callback(*c, arg)) return 1; @@ -135,23 +157,70 @@ static uint32_t render_format(FormatCallback callback, void* arg, } static uint32_t render_signed(FormatCallback callback, void* arg, - int32_t number, uint8_t base) + int32_t number, uint8_t base, uint8_t width, bool zero_padding) { + if (width > 0 && number < 0) { + --width; + } + + if (width > 0) { + uint32_t abs_number; + if (number < 0) { + abs_number = -number; + } else { + abs_number = number; + } + + uint32_t base_power = base; + while (width > 0 && base_power <= abs_number) { + base_power *= base; + --width; + } + if (width > 0) { + --width; + } + + while (width > 0) { + --width; + if (zero_padding) { + if (callback('0', arg)) return 1; + } else { + if (callback(' ', arg)) return 1; + } + } + } + if (number < 0) { callback('-', arg); number = -number; } - return render_unsigned(callback, arg, (uint32_t)number, base); + return render_unsigned(callback, arg, (uint32_t)number, base, 0, + zero_padding); } static uint32_t render_unsigned(FormatCallback callback, void* arg, - uint32_t number, uint8_t base) + uint32_t number, uint8_t base, uint8_t width, bool zero_padding) { uint32_t base_power = base; while (base_power <= number) { base_power *= base; + if (width > 0) { + --width; + } + } + if (width > 0) { + --width; + } + + while (width > 0) { + --width; + if (zero_padding) { + if (callback('0', arg)) return 1; + } else { + if (callback(' ', arg)) return 1; + } } while (base_power > 1) { From 0088322ee79452dfe1c71ad8e26f0e3d5556004a Mon Sep 17 00:00:00 2001 From: Steins7 Date: Mon, 15 Apr 2024 23:10:19 +0200 Subject: [PATCH 07/11] Fix warning --- srv/format.c | 1 + 1 file changed, 1 insertion(+) diff --git a/srv/format.c b/srv/format.c index ec4de76..baa122b 100644 --- a/srv/format.c +++ b/srv/format.c @@ -121,6 +121,7 @@ static uint32_t render_format(FormatCallback callback, void* arg, zero_padding = true; continue; } + // fall through case '1': case '2': case '3': From 254fec4f006d6e1fee5e0d345122fd32c9230f51 Mon Sep 17 00:00:00 2001 From: Steins7 Date: Mon, 15 Apr 2024 23:10:31 +0200 Subject: [PATCH 08/11] Disable zero padding for signed integers zero padding is mostly used with unsiged integers, and is quite difficult to properly implement for signed integers. Disbaling iti n that case seems like a good compromise --- srv/format.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/srv/format.c b/srv/format.c index baa122b..8bdcc0d 100644 --- a/srv/format.c +++ b/srv/format.c @@ -21,7 +21,7 @@ static uint32_t buffer_write(uint8_t byte, void* arg); static uint32_t render_format(FormatCallback callback, void* arg, const char* restrict format, va_list va); static uint32_t render_signed(FormatCallback callback, void* arg, - int32_t number, uint8_t base, uint8_t width, bool zero_padding); + int32_t number, uint8_t base, uint8_t width); static uint32_t render_unsigned(FormatCallback callback, void* arg, uint32_t number, uint8_t base, uint8_t width, bool zero_padding); @@ -100,7 +100,7 @@ static uint32_t render_format(FormatCallback callback, void* arg, break; case 'i': if (render_signed(callback, arg, va_arg(va, int32_t), - 10, width, zero_padding)) { + 10, width)) { return 1; } break; @@ -158,7 +158,7 @@ static uint32_t render_format(FormatCallback callback, void* arg, } static uint32_t render_signed(FormatCallback callback, void* arg, - int32_t number, uint8_t base, uint8_t width, bool zero_padding) + int32_t number, uint8_t base, uint8_t width) { if (width > 0 && number < 0) { --width; @@ -183,11 +183,7 @@ static uint32_t render_signed(FormatCallback callback, void* arg, while (width > 0) { --width; - if (zero_padding) { - if (callback('0', arg)) return 1; - } else { - if (callback(' ', arg)) return 1; - } + if (callback(' ', arg)) return 1; } } @@ -196,8 +192,7 @@ static uint32_t render_signed(FormatCallback callback, void* arg, number = -number; } - return render_unsigned(callback, arg, (uint32_t)number, base, 0, - zero_padding); + return render_unsigned(callback, arg, (uint32_t)number, base, 0, false); } static uint32_t render_unsigned(FormatCallback callback, void* arg, From 84deb788a03bfb2589c75d6cd41eb7418650d822 Mon Sep 17 00:00:00 2001 From: Steins7 Date: Sat, 20 Apr 2024 11:37:11 +0200 Subject: [PATCH 09/11] Improve debug module architecture --- srv/debug.c | 48 +++++++++--------------------------------------- srv/debug.h | 22 ++++++++++++++-------- 2 files changed, 23 insertions(+), 47 deletions(-) diff --git a/srv/debug.c b/srv/debug.c index 00f1265..23d3794 100644 --- a/srv/debug.c +++ b/srv/debug.c @@ -11,6 +11,8 @@ #include "dma_mbuf.h" #include "format.h" +#if DEBUG_TRACE || DEBUG_WARN || DEBUG_ERROR + //--local definitions----------------------------------------------------------- @@ -27,8 +29,6 @@ static uint8_t tx_buffer[BUFFER_SIZE]; //--public functions------------------------------------------------------------ -#if DEBUG_TRACE || DEBUG_WARN || DEBUG_ERROR - void _debug_init(enum UsartPeriph usart, enum GpioPort tx_port, enum GpioPin tx_pin) { @@ -45,16 +45,12 @@ void _debug_init(enum UsartPeriph usart, enum GpioPort tx_port, debug_trace("------------------------------------------------------------------------------\n"); } -#endif - -#if DEBUG_TRACE - -void _debug_trace(char* format, ...) +void _debug_print(const char* restrict header, + const char* restrict format, ...) { - write_debug('T', nullptr); - write_debug(':', nullptr); va_list va; va_start(va, format); + format_vfctprintf(write_debug, nullptr, header, va); format_vfctprintf(write_debug, nullptr, format, va); va_end(va); write_debug('\n', nullptr); @@ -63,40 +59,13 @@ void _debug_trace(char* format, ...) while (dma_mbuf_switch(&mbuf)) {} } -#endif - -#if DEBUG_WARN - -void _debug_warn(char* format, ...) -{ - print_debug("W:"); - print_debug(format); - - //ensure everything is written when done - while (dma_mbuf_switch(&mbuf)) {} -} - -#endif - -#if DEBUG_ERROR - -void _debug_error(char* format, ...) -{ - print_debug("E:"); - print_debug(format); - - //ensure everything is written when done - while (dma_mbuf_switch(&mbuf)) {} -} - -#endif //--local functions------------------------------------------------------------- -#if DEBUG_TRACE || DEBUG_WARN || DEBUG_ERROR - static uint32_t write_debug(uint8_t c, void* arg) { + (void)arg; //unused, required because of FormatCallback + while (dma_mbuf_write_byte(&mbuf, c)) { //buffer is full, wait until transfer started @@ -106,5 +75,6 @@ static uint32_t write_debug(uint8_t c, void* arg) return 0; } -#endif +#endif //DEBUG_TRACE || DEBUG_WARN || DEBUG_ERROR + diff --git a/srv/debug.h b/srv/debug.h index b954511..7fcb31d 100644 --- a/srv/debug.h +++ b/srv/debug.h @@ -14,8 +14,8 @@ #include "../drv/gpio.h" #define DEBUG_TRACE 1 -#define DEBUG_WARN 0 -#define DEBUG_ERROR 0 +#define DEBUG_WARN 1 +#define DEBUG_ERROR 1 //--type definitions------------------------------------------------------------ @@ -27,19 +27,22 @@ #endif #if DEBUG_TRACE -#define debug_trace(format, ...) _debug_trace(format __VA_OPT__(,) __VA_ARGS__) +#define debug_trace(format, ...) _debug_print("T:", \ + format __VA_OPT__(,) __VA_ARGS__) #else #define debug_trace(format, ...) do {} while (0) #endif #if DEBUG_WARN -#define debug_warn(format, ...) _debug_warn(format __VA_OPT__(,) __VA_ARGS__) +#define debug_warn(format, ...) _debug_print("W:", \ + format __VA_OPT__(,) __VA_ARGS__) #else #define debug_warn(format, ...) do {} while (0) #endif #if DEBUG_ERROR -#define debug_error(format, ...) _debug_error(format __VA_OPT__(,) __VA_ARGS__) +#define debug_error(format, ...) _debug_print("E:", \ + format __VA_OPT__(,) __VA_ARGS__) #else #define debug_error(format, ...) do {} while (0) #endif @@ -47,12 +50,15 @@ //--functions------------------------------------------------------------------- +#if DEBUG_TRACE || DEBUG_WARN || DEBUG_ERROR + void _debug_init(enum UsartPeriph usart, enum GpioPort tx_port, enum GpioPin tx_pin); -void _debug_trace(char* format, ...); -void _debug_warn(char* format, ...); -void _debug_error(char* format, ...); +void _debug_print(const char* restrict header, + const char* restrict format, ...); + +#endif #endif //_DEBUG_H_ From 12800818ce40f12979c2c50da6f95fd3d3f1fff2 Mon Sep 17 00:00:00 2001 From: Steins7 Date: Sat, 20 Apr 2024 11:44:56 +0200 Subject: [PATCH 10/11] Document debug module --- srv/debug.c | 4 +++- srv/debug.h | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/srv/debug.c b/srv/debug.c index 23d3794..416880c 100644 --- a/srv/debug.c +++ b/srv/debug.c @@ -62,6 +62,9 @@ void _debug_print(const char* restrict header, //--local functions------------------------------------------------------------- +/** + * Callback to use with format_vfctprintf() to print caracters to the debug port + */ static uint32_t write_debug(uint8_t c, void* arg) { (void)arg; //unused, required because of FormatCallback @@ -77,4 +80,3 @@ static uint32_t write_debug(uint8_t c, void* arg) #endif //DEBUG_TRACE || DEBUG_WARN || DEBUG_ERROR - diff --git a/srv/debug.h b/srv/debug.h index 7fcb31d..523b117 100644 --- a/srv/debug.h +++ b/srv/debug.h @@ -27,6 +27,12 @@ #endif #if DEBUG_TRACE +/** + * Prints a trace message on the debug port. This function should return + * immediately, provided that the message's length doesn't exceed 80 caracters + * and that it isn't called in very quick succession. Otherwise, it will block + * until the internal buffering system is ready to accept the message + */ #define debug_trace(format, ...) _debug_print("T:", \ format __VA_OPT__(,) __VA_ARGS__) #else @@ -34,6 +40,12 @@ #endif #if DEBUG_WARN +/** + * Prints a warning message on the debug port. This function should return + * immediately, provided that the message's length doesn't exceed 80 caracters + * and that it isn't called in very quick succession. Otherwise, it will block + * until the internal buffering system is ready to accept the message + */ #define debug_warn(format, ...) _debug_print("W:", \ format __VA_OPT__(,) __VA_ARGS__) #else @@ -41,6 +53,12 @@ #endif #if DEBUG_ERROR +/** + * Prints an error message on the debug port. This function should return + * immediately, provided that the message's length doesn't exceed 80 caracters + * and that it isn't called in very quick succession. Otherwise, it will block + * until the internal buffering system is ready to accept the message + */ #define debug_error(format, ...) _debug_print("E:", \ format __VA_OPT__(,) __VA_ARGS__) #else @@ -52,9 +70,24 @@ #if DEBUG_TRACE || DEBUG_WARN || DEBUG_ERROR +/** + * Initializes the debug system to use the given usart peripheral on the given + * tx port, printing a banner if traces are enabled. + * The usart doesn't need to be configured, neither does the tx port. + * + * This function shouldn't be called directly. Instead, use the debug_init macro + */ void _debug_init(enum UsartPeriph usart, enum GpioPort tx_port, enum GpioPin tx_pin); +/** + * Prints a debug message on the debug port with the given header. This function + * should return immediately, provided that the message's length doesn't exceed + * 80 caracters and that it isn't called in very quick succession. Otherwise, it + * will block until the internal buffering system is ready to accept the message + * + * This function shouldn't be called directly. Instead, use the debug macros + */ void _debug_print(const char* restrict header, const char* restrict format, ...); From 26f2b4d545e486c2559a186003bdf0d12425ce03 Mon Sep 17 00:00:00 2001 From: Steins7 Date: Sat, 20 Apr 2024 11:57:02 +0200 Subject: [PATCH 11/11] Document format module --- srv/format.c | 26 ++++++++++++++++++++++++++ srv/format.h | 24 ++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/srv/format.c b/srv/format.c index 8bdcc0d..ccf392e 100644 --- a/srv/format.c +++ b/srv/format.c @@ -57,8 +57,15 @@ uint32_t format_vfctprintf(FormatCallback callback, void* arg, return render_format(callback, arg, format, va); } + //--local functions------------------------------------------------------------- +/** + * FormatCallback to write into a regular buffer. A pointer to BufferArg shall + * be passed as arg. + * + * Returns 0 if everything went as expected, 1 otherwise + */ static uint32_t buffer_write(uint8_t byte, void* arg) { struct BufferArg* buffer_arg = (struct BufferArg*)arg; @@ -71,6 +78,12 @@ static uint32_t buffer_write(uint8_t byte, void* arg) return 0; } +/** + * Renders the given format to the output defined by the provided callback, + * formatting accordingly the provided arguments + * + * Returns 0 if everything went as expected, 1 otherwise + */ static uint32_t render_format(FormatCallback callback, void* arg, const char* restrict format, va_list va) { @@ -157,6 +170,12 @@ static uint32_t render_format(FormatCallback callback, void* arg, return 0; } +/** + * Formats a signed integer and renders it to the output defined by the provided + * callback + * + * Returns 0 if everything went as expected, 1 otherwise + */ static uint32_t render_signed(FormatCallback callback, void* arg, int32_t number, uint8_t base, uint8_t width) { @@ -195,6 +214,12 @@ static uint32_t render_signed(FormatCallback callback, void* arg, return render_unsigned(callback, arg, (uint32_t)number, base, 0, false); } +/** + * Formats an unsigned integer and renders it to the output defined by the + * provided callback + * + * Returns 0 if everything went as expected, 1 otherwise + */ static uint32_t render_unsigned(FormatCallback callback, void* arg, uint32_t number, uint8_t base, uint8_t width, bool zero_padding) { @@ -237,3 +262,4 @@ static uint32_t render_unsigned(FormatCallback callback, void* arg, return 0; } + diff --git a/srv/format.h b/srv/format.h index 04de136..a735542 100644 --- a/srv/format.h +++ b/srv/format.h @@ -20,12 +20,36 @@ typedef uint32_t (*FormatCallback)(uint8_t byte, void* arg); //--functions------------------------------------------------------------------- +/** + * Custom implementation of snprintf. Print the given format into the given + * buffer with the attached arguments properly formated. + * + * This function only provided a minimal subset of the standard library's + * snprintf : %c, %s, %i, %d, %x as well as right-justified padding for %d and + * %x + * + * Returns 0 if everything went as expected, 1 otherwise + */ uint32_t format_snprintf(char* restrict buffer, uint32_t buffer_size, const char* restrict format, ...); +/** + * Custom implementation of fprintf using a callback instead of a file pointer. + * Print the given format using the given callback with the attached arguments + * properly formated. + * + * This function only provided a minimal subset of the standard library's + * snprintf : %c, %s, %i, %d, %x as well as right-justified padding for %d and + * %x + * + * Returns 0 if everything went as expected, 1 otherwise + */ uint32_t format_fctprintf(FormatCallback callback, void* arg, const char* restrict format, ...); +/** + * Variadic variation of format_fctprintf(), see the later for more information + */ uint32_t format_vfctprintf(FormatCallback callback, void* arg, const char* restrict format, va_list va);