From 1cd37f21f3aee6486946420cab28982f48fc59c9 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Wed, 24 Jan 2024 15:18:25 +0800 Subject: [PATCH] drivers: ram_console: add option to link console buffer to given section Currently, the ram_console buffer is defined as a global var, its address is determined during the building and may be changed when code update. This is not a problem if the ram_console is just used in debug purpose. While in the heterogeneous SoCs, there can be multiple MPU Cores and several MCU cores, it can run multiple OS/bare-metal instances on these cores, but the UART ports may be not enough, so the ram_console can be leveraged. To make it easy to use, it's better make the console buffer fixed and predefined. This patch adds a option to link the console buffer to a given section, through the "zephyr,memory-region" device tree node, then the address can be known from the device tree node and easy to check from other cores running Linux/U-Boot. To use this option, the chosen property 'zephyr,ram-console' must be added, the following is a example: chosen { zephyr,ram-console = &ram_console; }; ram_console: memory@93d00000 { compatible = "zephyr,memory-region"; reg = <0x93d00000 DT_SIZE_K(4)>; zephyr,memory-region = "RAM_CONSOLE"; }; Signed-off-by: Hou Zhiqiang --- drivers/console/Kconfig | 14 ++++++++++++++ drivers/console/ram_console.c | 27 ++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/drivers/console/Kconfig b/drivers/console/Kconfig index 901f7a0ecc63..2fd0111a9dd5 100644 --- a/drivers/console/Kconfig +++ b/drivers/console/Kconfig @@ -95,16 +95,30 @@ config JAILHOUSE_DEBUG_CONSOLE Useful in board bring-up if there aren't any working serial drivers. +# Workaround for not being able to have commas in macro arguments +DT_CHOSEN_Z_RAM_CONSOLE := zephyr,ram-console + config RAM_CONSOLE bool "Use RAM console" select CONSOLE_HAS_DRIVER + select RAM_CONSOLE_BUFFER_SECTION if $(dt_chosen_enabled,$(DT_CHOSEN_Z_RAM_CONSOLE)) help Emit console messages to a RAM buffer "ram_console" which can be examined at runtime with a debugger. Useful in board bring-up if there aren't any working serial drivers. +config RAM_CONSOLE_BUFFER_SECTION + bool "Use dedicated section as RAM console buffer" + depends on RAM_CONSOLE && $(dt_chosen_enabled,$(DT_CHOSEN_Z_RAM_CONSOLE)) + select KERNEL_DIRECT_MAP if MMU + help + Use a dedicated section as the RAM console buffer, whose address is + known before build so that the console output messages can be easily + examined by a debugger or software tool from a parallel-running OS. + config RAM_CONSOLE_BUFFER_SIZE int "Ram Console buffer size" + default $(dt_chosen_reg_size_int,$(DT_CHOSEN_Z_RAM_CONSOLE)) if RAM_CONSOLE_BUFFER_SECTION default 1024 depends on RAM_CONSOLE help diff --git a/drivers/console/ram_console.c b/drivers/console/ram_console.c index 6d8031ed476d..fdb71b8bda0a 100644 --- a/drivers/console/ram_console.c +++ b/drivers/console/ram_console.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2015 Intel Corporation + * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,11 +12,26 @@ #include #include #include +#include + +#ifdef CONFIG_RAM_CONSOLE_BUFFER_SECTION +#if !DT_HAS_CHOSEN(zephyr_ram_console) +#error "Lack of chosen property zephyr,ram_console!" +#elif (CONFIG_RAM_CONSOLE_BUFFER_SIZE > DT_REG_SIZE(DT_CHOSEN(zephyr_ram_console))) +#error "Custom RAM console buffer exceeds the section size!" +#endif + +#define RAM_CONSOLE_BUF_ATTR \ + __attribute__((__section__(LINKER_DT_NODE_REGION_NAME(DT_CHOSEN(zephyr_ram_console))))) +#else +#define RAM_CONSOLE_BUF_ATTR +#endif extern void __printk_hook_install(int (*fn)(int)); extern void __stdout_hook_install(int (*fn)(int)); -char ram_console[CONFIG_RAM_CONSOLE_BUFFER_SIZE]; +char ram_console_buf[CONFIG_RAM_CONSOLE_BUFFER_SIZE] RAM_CONSOLE_BUF_ATTR; +char *ram_console; static int pos; static int ram_console_out(int character) @@ -28,6 +44,15 @@ static int ram_console_out(int character) static int ram_console_init(void) { +#ifdef CONFIG_RAM_CONSOLE_BUFFER_SECTION + mm_reg_t ram_console_va; + + device_map((mm_reg_t *)&ram_console_va, DT_REG_ADDR(DT_CHOSEN(zephyr_ram_console)), + CONFIG_RAM_CONSOLE_BUFFER_SIZE, K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP); + ram_console = (char *)ram_console_va, +#else + ram_console = ram_console_buf, +#endif __printk_hook_install(ram_console_out); __stdout_hook_install(ram_console_out);