1 /* ram_console.c - Console messages to a RAM buffer */
2 
3 /*
4  * Copyright (c) 2015 Intel Corporation
5  * Copyright 2024 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 char ram_console_buf[CONFIG_RAM_CONSOLE_BUFFER_SIZE] RAM_CONSOLE_BUF_ATTR;
33 char *ram_console;
34 static int pos;
35 
ram_console_out(int character)36 static int ram_console_out(int character)
37 {
38 	ram_console[pos] = (char)character;
39 	/* Leave one byte to ensure we're always NULL-terminated */
40 	pos = (pos + 1) % (CONFIG_RAM_CONSOLE_BUFFER_SIZE - 1);
41 	return character;
42 }
43 
ram_console_init(void)44 static int ram_console_init(void)
45 {
46 #ifdef CONFIG_RAM_CONSOLE_BUFFER_SECTION
47 	mm_reg_t ram_console_va;
48 
49 	device_map((mm_reg_t *)&ram_console_va, DT_REG_ADDR(DT_CHOSEN(zephyr_ram_console)),
50 		   CONFIG_RAM_CONSOLE_BUFFER_SIZE, K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP);
51 	ram_console = (char *)ram_console_va,
52 #else
53 	ram_console = ram_console_buf,
54 #endif
55 	__printk_hook_install(ram_console_out);
56 	__stdout_hook_install(ram_console_out);
57 
58 	return 0;
59 }
60 
61 SYS_INIT(ram_console_init, PRE_KERNEL_1, CONFIG_CONSOLE_INIT_PRIORITY);
62