ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
emu_console.c File Reference

Emulator console surfaces implementation (see emu_console.h). More...

#include "emu_console.h"
#include <stdio.h>
#include "board_console.h"
#include "emu_host_io_internal.h"
#include "emu_memory_access.h"
Include dependency graph for emu_console.c:

Go to the source code of this file.

Functions

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.
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.
void console_flush_line (uint8_t channel)
 Flush the pending [uart] line to injected output sink with its channel prefix.
void console_tx_sink (uint8_t channel, uint8_t byte)
 SCI TX sink: print each transmitted byte (prefixed line + raw mirror).
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.

Variables

static char s_itm_line [k_itm_line_max+1U]
 Accumulated current ITM line (flushed on newline or when full).
static uint32_t s_itm_len
 Bytes currently buffered in s_itm_line.
static char s_uart_line [k_uart_line_max]
 Pending [uart] line text.
static uint32_t s_uart_line_len
 Chars buffered in the line.

Detailed Description

Emulator console surfaces implementation (see emu_console.h).

The [uart] SCIn: line assembly fed by the SCI TX sink, the ITM/SWO stimulus-port seed + echo ([itm] lines), and the CLI escape decoder – moved verbatim out of the ra8_emulator main translation unit.

[itm] ... lines are ra8_emulator's echo of the Arm CoreSight ITM stimulus port 0. It is the direct analog of the [uart] SCI8: echo: where that surfaces the firmware's UART console, this surfaces ra8_log's debug trace – the same bytes that on real hardware leave through the ITM/SWO pin to the J-Link SWO console. So [itm] == "what you would see on the SWO trace console", and [uart] SCI8: == "what you would see on the serial console".

ra8_log writes log bytes to ITM stimulus port 0 (0xE0000000) after checking DEMCR.TRCENA + ITM TCR/TENR + a non-zero STIM0 "FIFO ready" read. With no debugger attached those PPB bytes are all zero, so internal_itm_ready() returns false and every byte is dropped – which is why the e-reader (and any ra8_log user) printed nothing in ra8_emulator. We seed the ready bits into PPB RAM at boot (internal_itm_seed_ready: sets DEMCR.TRCENA + TCR.ITMENA + TENR port 0 + a ready STIM0) and hook stimulus-port writes (internal_on_itm_stim_write) to echo the bytes as [itm] <line> on injected output sink. This surfaces ra8_log for every app, not just the TrustZone e-reader.

Since
0.1.0

Definition in file emu_console.c.

Function Documentation

◆ console_flush_line()

void console_flush_line ( uint8_t channel)

Flush the pending [uart] line to injected output sink with its channel prefix.

Terminates and prints the accumulated line as [uart] SCIn: ...; a no-op when nothing is buffered. The run-end report calls this so bytes emitted without a trailing newline still surface.

Parameters
[in]channelSCI channel number used in the printed prefix.
Returns
Nothing.
Precondition
The console TX sink has been collecting bytes (or the buffer is empty).
injected output sink is writable.
Postcondition
The line buffer is empty.
Note
Not thread-safe; the emulator is single-threaded host-side.
See also
console_tx_sink() Fills the buffer this flushes.
Since
0.1.0
Postcondition
Ownership of caller-supplied storage is unchanged.

Definition at line 155 of file emu_console.c.

References priv_emu_io_outf(), s_uart_line, and s_uart_line_len.

Referenced by console_tx_sink(), and internal_run_print_stop_summary().

◆ console_tx_sink()

void console_tx_sink ( uint8_t channel,
uint8_t byte )

SCI TX sink: print each transmitted byte (prefixed line + raw mirror).

Installed via board_periph_sci_set_tx_sink(). Printable bytes accumulate into a line that is flushed – with an [uart] SCIn: prefix – on newline or when the buffer fills, so console output reads cleanly in the log; CR is dropped from the pretty line.

Parameters
[in]channelSCI channel that transmitted the byte.
[in]byteThe transmitted data byte.
Returns
Nothing.
Precondition
The board_periph SCI model routes TX bytes here.
injected output sink is writable.
Postcondition
The byte is buffered or the completed line has been printed.
Note
Not thread-safe; the emulator is single-threaded host-side.
See also
console_flush_line() Forces out a partial line.
Since
0.1.0
Postcondition
Ownership of caller-supplied storage is unchanged.

Definition at line 165 of file emu_console.c.

References console_flush_line(), k_uart_line_max, s_uart_line, and s_uart_line_len.

Referenced by internal_main_bringup_peripherals().

◆ decode_escapes()

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.

Translates \n / \r / \t / \0 / \\ in in so a shell argument can carry the line endings a console example expects (e.g. --input "ping\r\n"); any other character (including an unrecognised escape's backslash) is copied verbatim. Bounded by cap; never overruns.

Parameters
[in]inNUL-terminated source string.
[out]outDestination byte buffer.
[in]capCapacity of out in bytes.
Returns
Number of bytes written to out.
Return values
0in was empty (or cap was 0).
Precondition
in is NUL-terminated and out holds at least cap bytes.
cap bounds the write (enforced by the loop condition).
Postcondition
At most cap bytes of out are written.
Note
Pure transformation; thread-safe.
Since
0.1.0
Postcondition
Ownership of caller-supplied storage is unchanged.

Definition at line 179 of file emu_console.c.

Referenced by internal_main_feed_inputs().

◆ emu_console_install()

void emu_console_install ( uc_engine * uc)

Implementation of emu_console_install() – ITM seed + STIM0 echo hook.

Seed ITM "ready" bits and arm the stimulus-port echo hook.

Definition at line 142 of file emu_console.c.

References internal_itm_seed_ready(), internal_on_itm_stim_write(), and k_itm_stim0_addr.

Referenced by internal_main_install_core_seams().

◆ emu_console_reset()

void emu_console_reset ( void )

Implementation of emu_console_reset() – drop the pending ITM line.

Reset the in-flight ITM line (warm-reboot support).

Definition at line 211 of file emu_console.c.

References s_itm_len.

Referenced by warm_reboot().

◆ internal_itm_seed_ready()

void internal_itm_seed_ready ( uc_engine * uc)
static

Seed the ITM "ready" bits into PPB RAM so ra8_log emits.

On hardware a debugger sets DEMCR.TRCENA and enables the ITM; with none attached those PPB registers read zero and ra8_log drops every byte. ra8_emulator maps the PPB as plain RAM, so writing the enable bits here makes internal_itm_ready() see a live ITM. The firmware only ever reads these registers (it never re-disables the ITM), so the seed persists for the run.

Parameters
[in]ucInitialised Unicorn engine with the PPB region mapped.
Returns
Nothing.
Precondition
uc has the PPB region (0xE0000000) mapped as RAM.
Called once before emulation starts.
Postcondition
DEMCR.TRCENA, ITM TCR.ITMENA, TENR port-0, and a ready STIM0 are set.
ra8_log's internal_itm_ready() returns true for the run.
Note
Not thread-safe; call during single-threaded setup.
Since
0.1.0

Definition at line 128 of file emu_console.c.

References emu_mem_write(), k_itm_stim0_addr, k_itm_stim_ready, k_itm_tcr_addr, k_itm_tcr_itmena, k_itm_tenr_addr, k_itm_tenr_port0, k_scb_demcr_addr, k_scb_demcr_trcena, and RA8_INTERNAL.

Referenced by emu_console_install().

◆ internal_on_itm_stim_write()

void internal_on_itm_stim_write ( uc_engine * uc,
uc_mem_type type,
uint64_t addr,
int size,
int64_t value,
void * user )
static

UC_HOOK_MEM_WRITE handler for ITM stimulus port 0 – echo the byte.

Buffers the low byte of each stimulus write and prints [itm] <line> to injected output sink on a newline (or when the line buffer fills), so ra8_log output is visible in the emulator. Carriage returns are dropped so the \r\n ra8_log line ending yields one clean line.

Parameters
[in]ucUnicorn engine (unused; the byte rides in value).
[in]typeMemory access type (write); unused.
[in]addrObserved address (the stimulus port); unused.
[in]sizeAccess width in bytes; unused.
[in]valueThe value being written; its low byte is the log character.
[in]userHook user pointer; unused.
Returns
Nothing.
Precondition
The hook is registered for the 4-byte STIM0 word only.
value holds the character ra8_log is emitting.
Postcondition
On a newline the buffered line is printed and the buffer reset.
Non-newline printable bytes are appended to s_itm_line.
Note
Not thread-safe; ra8_emulator is single-threaded.
Since
0.1.0

Definition at line 72 of file emu_console.c.

References board_console_push(), k_board_console_ch_itm, k_itm_line_max, priv_emu_io_outf(), RA8_INTERNAL, s_itm_len, and s_itm_line.

Referenced by emu_console_install().

Variable Documentation

◆ s_itm_len

uint32_t s_itm_len
static

Bytes currently buffered in s_itm_line.

Definition at line 44 of file emu_console.c.

Referenced by emu_console_reset(), and internal_on_itm_stim_write().

◆ s_itm_line

char s_itm_line[k_itm_line_max+1U]
static

Accumulated current ITM line (flushed on newline or when full).

Definition at line 41 of file emu_console.c.

Referenced by internal_on_itm_stim_write().

◆ s_uart_line

char s_uart_line[k_uart_line_max]
static

Pending [uart] line text.

Definition at line 46 of file emu_console.c.

Referenced by console_flush_line(), and console_tx_sink().

◆ s_uart_line_len

uint32_t s_uart_line_len
static

Chars buffered in the line.

Definition at line 47 of file emu_console.c.

Referenced by console_flush_line(), and console_tx_sink().