1 /* ram_console.c - Console messages to a RAM buffer */
2 
3 /*
4  * Copyright (c) 2015 Intel Corporation
5  * Copyright 2024-2025 NXP
6  *
7  * SPDX-License-Identifier: Apache-2.0
8  */
9 
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/sys/printk.h>
13 #include <zephyr/sys/printk-hooks.h>
14 #include <zephyr/sys/libc-hooks.h>
15 #include <zephyr/device.h>
16 #include <zephyr/init.h>
17 #include <zephyr/linker/devicetree_regions.h>
18 
19 #ifdef CONFIG_RAM_CONSOLE_BUFFER_SECTION
20 #if !DT_HAS_CHOSEN(zephyr_ram_console)
21 #error "Lack of chosen property zephyr,ram_console!"
22 #elif (CONFIG_RAM_CONSOLE_BUFFER_SIZE > DT_REG_SIZE(DT_CHOSEN(zephyr_ram_console)))
23 #error "Custom RAM console buffer exceeds the section size!"
24 #endif
25 
26 #define RAM_CONSOLE_BUF_ATTR	\
27 	__attribute__((__section__(LINKER_DT_NODE_REGION_NAME(DT_CHOSEN(zephyr_ram_console)))))
28 #else
29 #define RAM_CONSOLE_BUF_ATTR
30 #endif
31 
32 /* workaround the fact that device_map() is not defined for SoCs with no MMU */
33 #ifndef DEVICE_MMIO_IS_IN_RAM
34 #define device_map(virt, phys, size, flags) *(virt) = (phys)
35 #endif /* DEVICE_MMIO_IS_IN_RAM */
36 
37 char ram_console_buf[CONFIG_RAM_CONSOLE_BUFFER_SIZE] RAM_CONSOLE_BUF_ATTR;
38 char *ram_console;
39 static int pos;
40 
ram_console_out(int character)41 static int ram_console_out(int character)
42 {
43 	ram_console[pos] = (char)character;
44 	/* Leave one byte to ensure we're always NULL-terminated */
45 	pos = (pos + 1) % (CONFIG_RAM_CONSOLE_BUFFER_SIZE - 1);
46 	return character;
47 }
48 
ram_console_init(void)49 static int ram_console_init(void)
50 {
51 #ifdef CONFIG_RAM_CONSOLE_BUFFER_SECTION
52 	mm_reg_t ram_console_va;
53 
54 	device_map((mm_reg_t *)&ram_console_va, DT_REG_ADDR(DT_CHOSEN(zephyr_ram_console)),
55 		   CONFIG_RAM_CONSOLE_BUFFER_SIZE, K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP);
56 	ram_console = (char *)ram_console_va;
57 #else
58 	ram_console = ram_console_buf;
59 #endif
60 	__printk_hook_install(ram_console_out);
61 	__stdout_hook_install(ram_console_out);
62 
63 	return 0;
64 }
65 
66 SYS_INIT(ram_console_init, PRE_KERNEL_1, CONFIG_CONSOLE_INIT_PRIORITY);
67