1 /* rtt_console.c - Console messages to a RAM buffer that is then read by
2 * the Segger J-Link debugger
3 */
4
5 /*
6 * Copyright (c) 2016 Nordic Semiconductor ASA
7 *
8 * SPDX-License-Identifier: Apache-2.0
9 */
10
11
12 #include <zephyr/kernel.h>
13 #include <zephyr/sys/printk.h>
14 #include <zephyr/sys/printk-hooks.h>
15 #include <zephyr/sys/libc-hooks.h>
16 #include <zephyr/device.h>
17 #include <zephyr/init.h>
18 #include <SEGGER_RTT.h>
19
20 static bool host_present;
21
22 /** @brief Wait for fixed period.
23 *
24 */
wait(void)25 static void wait(void)
26 {
27 if (!IS_ENABLED(CONFIG_MULTITHREADING) || k_is_in_isr()) {
28 if (IS_ENABLED(CONFIG_RTT_TX_RETRY_IN_INTERRUPT)) {
29 k_busy_wait(1000*CONFIG_RTT_TX_RETRY_DELAY_MS);
30 }
31 } else {
32 k_msleep(CONFIG_RTT_TX_RETRY_DELAY_MS);
33 }
34 }
35
rtt_console_out(int character)36 static int rtt_console_out(int character)
37 {
38 char c = (char)character;
39 unsigned int cnt;
40 int max_cnt = CONFIG_RTT_TX_RETRY_CNT;
41
42 do {
43 cnt = SEGGER_RTT_Write(0, &c, 1);
44
45 /* There are two possible reasons for not writing any data to
46 * RTT:
47 * - The host is not connected and not reading the data.
48 * - The buffer got full and will be read by the host.
49 * These two situations are distinguished using the following
50 * algorithm:
51 * At the beginning, the module assumes that the host is active,
52 * so when no data is read, it busy waits and retries.
53 * If, after retrying, the host reads the data, the module
54 * assumes that the host is active. If it fails, the module
55 * assumes that the host is inactive and stores that
56 * information. On next call, only one attempt takes place.
57 * The host is marked as active if the attempt is successful.
58 */
59 if (cnt) {
60 /* byte processed - host is present. */
61 host_present = true;
62 } else if (host_present) {
63 if (max_cnt) {
64 wait();
65 max_cnt--;
66 continue;
67 } else {
68 host_present = false;
69 }
70 }
71
72 break;
73 } while (1);
74
75 return character;
76 }
77
rtt_console_init(void)78 static int rtt_console_init(void)
79 {
80
81 #ifdef CONFIG_PRINTK
82 __printk_hook_install(rtt_console_out);
83 #endif
84 __stdout_hook_install(rtt_console_out);
85
86 return 0;
87 }
88
89 SYS_INIT(rtt_console_init, PRE_KERNEL_1, CONFIG_CONSOLE_INIT_PRIORITY);
90