ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
emu_console.c
Go to the documentation of this file.
1
31
32#include "emu_console.h"
33
34#include <stdio.h>
35
36#include "board_console.h"
38#include "emu_memory_access.h"
39
41static char s_itm_line[k_itm_line_max + 1U];
42
44static uint32_t s_itm_len;
45
47static uint32_t s_uart_line_len;
48
72RA8_INTERNAL static void internal_on_itm_stim_write(uc_engine* uc,
73 uc_mem_type type,
74 uint64_t addr,
75 int size,
76 int64_t value,
77 void* user)
78{
79 (void)uc;
80 (void)type;
81 (void)addr;
82 (void)size;
83 (void)user;
84 const char c = (char)(uint8_t)value;
85 if (c == '\r') {
86 return;
87 }
88 if ((c == '\n') || (s_itm_len >= (uint32_t)k_itm_line_max)) {
89 s_itm_line[s_itm_len] = '\0';
90 /* Emit one ra8_log line as `[itm] <line>` -- the CoreSight ITM/SWO-trace
91 * analog of the `[uart] SCI8:` console echo (see the ITM model block
92 * above). */
93 (void)priv_emu_io_outf("[itm] %s\n", s_itm_line);
94 /* Also route it to the board_console ITM channel so the tabbed board-view
95 * console shows ITM/SWO trace in its own tab (a different endpoint than the
96 * UART line). The injected output sink echo above is unchanged -- this is
97 * purely additive. */
99 s_itm_len = 0U;
100 if (c == '\n') {
101 return;
102 }
103 }
105 s_itm_len++;
106}
107
128RA8_INTERNAL static void internal_itm_seed_ready(uc_engine* uc)
129{
130 const uint32_t demcr = (uint32_t)k_scb_demcr_trcena;
131 const uint32_t tcr = (uint32_t)k_itm_tcr_itmena;
132 const uint32_t tenr = (uint32_t)k_itm_tenr_port0;
133 const uint32_t stim = (uint32_t)k_itm_stim_ready;
134 (void)emu_mem_write(uc, (uint64_t)k_scb_demcr_addr, &demcr, sizeof(demcr));
135 (void)emu_mem_write(uc, (uint64_t)k_itm_tcr_addr, &tcr, sizeof(tcr));
136 (void)emu_mem_write(uc, (uint64_t)k_itm_tenr_addr, &tenr, sizeof(tenr));
137 (void)emu_mem_write(uc, (uint64_t)k_itm_stim0_addr, &stim, sizeof(stim));
138}
139
142void emu_console_install(uc_engine* uc)
143{
145 static uc_hook s_h_itm;
146 (void)uc_hook_add(uc,
147 &s_h_itm,
148 UC_HOOK_MEM_WRITE,
150 nullptr,
151 (uint64_t)k_itm_stim0_addr,
152 (uint64_t)k_itm_stim0_addr + 3U);
153}
154
155void console_flush_line(uint8_t channel)
156{
157 if (s_uart_line_len == 0U) {
158 return;
159 }
161 (void)priv_emu_io_outf("[uart] SCI%u: %s\n", channel, s_uart_line);
162 s_uart_line_len = 0U;
163}
164
165void console_tx_sink(uint8_t channel, uint8_t byte)
166{
167 if (byte == (uint8_t)'\n') {
168 console_flush_line(channel);
169 return;
170 }
171 if ((byte != (uint8_t)'\r') && (s_uart_line_len < (uint32_t)(k_uart_line_max - 1U))) {
172 s_uart_line[s_uart_line_len++] = (char)byte;
173 }
174 if (s_uart_line_len == (uint32_t)(k_uart_line_max - 1U)) {
175 console_flush_line(channel); /* avoid an unbounded line on a stream with no LF */
176 }
177}
178
179uint32_t decode_escapes(const char* in, uint8_t* out, uint32_t cap)
180{
181 uint32_t n = 0U;
182 for (uint32_t i = 0U; (in[i] != '\0') && (n < cap); i++) {
183 char c = in[i];
184 if ((c == '\\') && (in[i + 1U] != '\0')) {
185 i++;
186 switch (in[i]) {
187 case 'n':
188 c = '\n';
189 break;
190 case 'r':
191 c = '\r';
192 break;
193 case 't':
194 c = '\t';
195 break;
196 case '0':
197 c = '\0';
198 break;
199 default:
200 c = in[i]; /* \\ -> \, and any other escape is taken literally */
201 break;
202 }
203 }
204 out[n++] = (uint8_t)c;
205 }
206 return n;
207}
208
212{
213 s_itm_len = 0U;
214}
Multi-channel console log store backing the board view's tabbed console.
void board_console_push(board_console_ch_t ch, const char *line)
Append one completed line to a channel ring and the ALL ring.
@ k_board_console_ch_itm
CoreSight ITM/SWO trace ([itm]).
uint32_t decode_escapes(const char *in, uint8_t *out, uint32_t cap)
Decode a C-style escaped –input string into a raw byte buffer.
void emu_console_reset(void)
Implementation of emu_console_reset() – drop the pending ITM line.
static char s_itm_line[k_itm_line_max+1U]
Accumulated current ITM line (flushed on newline or when full).
Definition emu_console.c:41
static void internal_itm_seed_ready(uc_engine *uc)
Seed the ITM "ready" bits into PPB RAM so ra8_log emits.
void emu_console_install(uc_engine *uc)
Implementation of emu_console_install() – ITM seed + STIM0 echo hook.
static char s_uart_line[k_uart_line_max]
Pending [uart] line text.
Definition emu_console.c:46
static void internal_on_itm_stim_write(uc_engine *uc, uc_mem_type type, uint64_t addr, int size, int64_t value, void *user)
UC_HOOK_MEM_WRITE handler for ITM stimulus port 0 – echo the byte.
Definition emu_console.c:72
static uint32_t s_itm_len
Bytes currently buffered in s_itm_line.
Definition emu_console.c:44
void console_tx_sink(uint8_t channel, uint8_t byte)
SCI TX sink: print each transmitted byte (prefixed line + raw mirror).
static uint32_t s_uart_line_len
Chars buffered in the line.
Definition emu_console.c:47
void console_flush_line(uint8_t channel)
Flush the pending [uart] line to injected output sink with its channel prefix.
Emulator text-console surfaces: UART echo, ITM/SWO echo, escapes.
@ k_uart_line_max
Pretty-print line buffer for the [uart] prefix.
Definition emu_console.h:92
@ k_itm_line_max
Max chars buffered before a forced flush.
Definition emu_console.h:71
@ k_itm_tcr_itmena
TCR bit 0: ITM global enable.
Definition emu_console.h:72
@ k_itm_stim_ready
Non-zero STIM0 read = FIFO ready.
Definition emu_console.h:74
@ k_itm_tenr_port0
TENR bit 0: stimulus port 0 enabled.
Definition emu_console.h:73
@ k_scb_demcr_trcena
DEMCR bit 24: trace subsystem enable.
Definition emu_console.h:75
@ k_itm_tenr_addr
ITM Trace Enable Register (port 0).
Definition emu_console.h:51
@ k_scb_demcr_addr
Debug Exception + Monitor Control.
Definition emu_console.h:52
@ k_itm_tcr_addr
ITM Trace Control Register (ITMENA).
Definition emu_console.h:50
@ k_itm_stim0_addr
ITM stimulus port 0 (byte FIFO).
Definition emu_console.h:49
Bounded raw-descriptor I/O seam for the RA8 emulator.
emu_io_result_t priv_emu_io_outf(const char *format,...)
Format bounded text and write it to the injected output descriptor.
Central first-party Unicorn memory access seam.
uc_err emu_mem_write(uc_engine *uc, uint64_t address, const void *bytes, size_t count)
Write guest memory through the central access seam.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).