[PATCH v2 0/2] serial: introduce CONFIG_CONSOLE_FLUSH_ON_NEWLINE

v2: - fix implementation (lacked CONFIG_ inside IS_ENABLED...).
- drop dependency on CONSOLE_FLUSH_SUPPORT - that governs whether functions for explicit flushing should be built, and is not actually a requirement for allowing this implicit flushing, so the features should be selectable independently.
- add Simon's R-b to 1/2
1/2 is trivial prep. Motivation from 2/2:
When debugging, one sometimes only gets partial output lines or nothing at all from the last printf, because the uart has a largish buffer, and the code after the printf() may cause the CPU to hang before the uart IP has time to actually emit all the characters. That can be very confusing, because one doesn't then know exactly where the hang happens.
Rasmus Villemoes (2): serial: serial-uclass.c: move definition of _serial_flush up a bit serial: introduce CONFIG_CONSOLE_FLUSH_ON_NEWLINE
common/Kconfig | 10 ++++++++++ drivers/serial/serial-uclass.c | 28 ++++++++++++++++------------ 2 files changed, 26 insertions(+), 12 deletions(-)

Preparation for next patch.
Reviewed-by: Simon Glass sjg@chromium.org Signed-off-by: Rasmus Villemoes rasmus.villemoes@prevas.dk --- drivers/serial/serial-uclass.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 4a2da7a331..8bdcdd1eaa 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -182,6 +182,18 @@ int serial_initialize(void) return serial_init(); }
+#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT +static void _serial_flush(struct udevice *dev) +{ + struct dm_serial_ops *ops = serial_get_ops(dev); + + if (!ops->pending) + return; + while (ops->pending(dev, false) > 0) + ; +} +#endif + static void _serial_putc(struct udevice *dev, char ch) { struct dm_serial_ops *ops = serial_get_ops(dev); @@ -235,18 +247,6 @@ static void _serial_puts(struct udevice *dev, const char *str) } while (*str); }
-#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT -static void _serial_flush(struct udevice *dev) -{ - struct dm_serial_ops *ops = serial_get_ops(dev); - - if (!ops->pending) - return; - while (ops->pending(dev, false) > 0) - ; -} -#endif - static int __serial_getc(struct udevice *dev) { struct dm_serial_ops *ops = serial_get_ops(dev);

On Mon, Oct 16, 2023 at 10:35:21AM +0200, Rasmus Villemoes wrote:
Preparation for next patch.
Reviewed-by: Simon Glass sjg@chromium.org Signed-off-by: Rasmus Villemoes rasmus.villemoes@prevas.dk
Applied to u-boot/master, thanks!

When debugging, one sometimes only gets partial output lines or nothing at all from the last printf, because the uart has a largish buffer, and the code after the printf() may cause the CPU to hang before the uart IP has time to actually emit all the characters. That can be very confusing, because one doesn't then know exactly where the hang happens.
Introduce a config knob allowing one to wait for the uart fifo to drain whenever a newline character is printed, roughly corresponding to the effect of setvbuf(..., _IOLBF, ...) in ordinary C programs.
Since this uses IS_ENABLED() instead of cpp ifdef, we can remove the ifdef around the _serial_flush() definition - if neither CONSOLE_FLUSH_SUPPORT or CONSOLE_FLUSH_ON_NEWLINE are enabled, the compiler elides _serial_flush(), but it won't warn about it being unused.
Signed-off-by: Rasmus Villemoes rasmus.villemoes@prevas.dk --- common/Kconfig | 10 ++++++++++ drivers/serial/serial-uclass.c | 8 ++++++-- 2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/common/Kconfig b/common/Kconfig index 93c96f23b0..43701fe9e8 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -224,6 +224,16 @@ config CONSOLE_FLUSH_SUPPORT help This enables compilation of flush() function for console flush support.
+config CONSOLE_FLUSH_ON_NEWLINE + bool "Flush console buffer on every newline character" + depends on DM_SERIAL + help + This makes the serial core code flush the console device + whenever a newline (\n) character has been emitted. This can + be especially useful when "printf debugging", as otherwise + lots of output could still be in the UART's FIFO by the time + one hits the code which causes the CPU to hang or reset. + config CONSOLE_MUX bool "Enable console multiplexing" default y if VIDEO || LCD diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 8bdcdd1eaa..df6a387284 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -182,7 +182,6 @@ int serial_initialize(void) return serial_init(); }
-#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT static void _serial_flush(struct udevice *dev) { struct dm_serial_ops *ops = serial_get_ops(dev); @@ -192,7 +191,6 @@ static void _serial_flush(struct udevice *dev) while (ops->pending(dev, false) > 0) ; } -#endif
static void _serial_putc(struct udevice *dev, char ch) { @@ -205,6 +203,9 @@ static void _serial_putc(struct udevice *dev, char ch) do { err = ops->putc(dev, ch); } while (err == -EAGAIN); + + if (IS_ENABLED(CONFIG_CONSOLE_FLUSH_ON_NEWLINE) && ch == '\n') + _serial_flush(dev); }
static int __serial_puts(struct udevice *dev, const char *str, size_t len) @@ -243,6 +244,9 @@ static void _serial_puts(struct udevice *dev, const char *str) if (*newline && __serial_puts(dev, "\r\n", 2)) return;
+ if (IS_ENABLED(CONFIG_CONSOLE_FLUSH_ON_NEWLINE) && *newline) + _serial_flush(dev); + str += len + !!*newline; } while (*str); }

On Mon, 16 Oct 2023 at 02:36, Rasmus Villemoes rasmus.villemoes@prevas.dk wrote:
When debugging, one sometimes only gets partial output lines or nothing at all from the last printf, because the uart has a largish buffer, and the code after the printf() may cause the CPU to hang before the uart IP has time to actually emit all the characters. That can be very confusing, because one doesn't then know exactly where the hang happens.
Introduce a config knob allowing one to wait for the uart fifo to drain whenever a newline character is printed, roughly corresponding to the effect of setvbuf(..., _IOLBF, ...) in ordinary C programs.
Since this uses IS_ENABLED() instead of cpp ifdef, we can remove the ifdef around the _serial_flush() definition - if neither CONSOLE_FLUSH_SUPPORT or CONSOLE_FLUSH_ON_NEWLINE are enabled, the compiler elides _serial_flush(), but it won't warn about it being unused.
Signed-off-by: Rasmus Villemoes rasmus.villemoes@prevas.dk
common/Kconfig | 10 ++++++++++ drivers/serial/serial-uclass.c | 8 ++++++-- 2 files changed, 16 insertions(+), 2 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

On Mon, Oct 16, 2023 at 10:35:22AM +0200, Rasmus Villemoes wrote:
When debugging, one sometimes only gets partial output lines or nothing at all from the last printf, because the uart has a largish buffer, and the code after the printf() may cause the CPU to hang before the uart IP has time to actually emit all the characters. That can be very confusing, because one doesn't then know exactly where the hang happens.
Introduce a config knob allowing one to wait for the uart fifo to drain whenever a newline character is printed, roughly corresponding to the effect of setvbuf(..., _IOLBF, ...) in ordinary C programs.
Since this uses IS_ENABLED() instead of cpp ifdef, we can remove the ifdef around the _serial_flush() definition - if neither CONSOLE_FLUSH_SUPPORT or CONSOLE_FLUSH_ON_NEWLINE are enabled, the compiler elides _serial_flush(), but it won't warn about it being unused.
Signed-off-by: Rasmus Villemoes rasmus.villemoes@prevas.dk Reviewed-by: Simon Glass sjg@chromium.org
Applied to u-boot/master, thanks!
participants (3)
-
Rasmus Villemoes
-
Simon Glass
-
Tom Rini