ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
board_periph_ssie.c
Go to the documentation of this file.
1
33
34#include <stdint.h>
35#include <stdio.h>
36
37#include "board_console.h"
38#include "board_periph_block.h"
40
42typedef enum : uint32_t {
45
47typedef enum : uint64_t {
48 k_ssie_base = 0x4025D000UL,
49 k_ssie_stride = 0x100UL,
51 k_ssie_span = 0x100UL * 2UL,
52 k_ssie_regs = 0x40UL,
54
56typedef enum : uint64_t {
64
66typedef enum : uint32_t {
67 k_ssie_ren_ten = 0x00000003U,
68 k_ssie_iirq = 0x02000000U,
69 k_ssie_tde = 0x00010000U,
71
73typedef enum : uint32_t {
76
78typedef struct {
79 uint32_t reg[k_ssie_regs];
80 uint32_t tx_samples;
82
84
94{
95 for (uint32_t ch = 0U; ch < (uint32_t)k_ssie_count; ch++) {
96 for (uint32_t i = 0U; i < (uint32_t)k_ssie_regs; i++) {
97 s_ssie[ch].reg[i] = 0U;
98 }
99 s_ssie[ch].tx_samples = 0U;
100 }
101}
102
116RA8_INTERNAL static uint64_t internal_ssie_read(uc_engine* uc, uint64_t addr, unsigned size)
117{
118 (void)uc;
119 (void)size;
120 const uint32_t ch = (uint32_t)((addr - (uint64_t)k_ssie_base) / (uint64_t)k_ssie_stride);
121 const uint64_t off = (addr - (uint64_t)k_ssie_base) % (uint64_t)k_ssie_stride;
122 if (ch >= (uint32_t)k_ssie_count) {
123 return 0U;
124 }
125 const ssie_state_t* s = &s_ssie[ch];
126 if (off == (uint64_t)k_ssie_off_ssisr) {
127 /* IIRQ asserts while the channel is idle (REN and TEN both clear), so the
128 * driver's "must be idle before enabling" gate in ra8_ssie_start passes. */
129 const bool running = (s->reg[k_ssie_off_ssicr / 4U] & (uint32_t)k_ssie_ren_ten) != 0U;
130 return running ? 0U : (uint64_t)k_ssie_iirq;
131 }
132 if (off == (uint64_t)k_ssie_off_ssifsr) {
133 return (uint64_t)k_ssie_tde; /* TX FIFO always has room; RX empty. */
134 }
135 if (off == (uint64_t)k_ssie_off_ssifrdr) {
136 return 0U; /* No RX audio source in the model. */
137 }
138 if ((off % 4UL) != 0UL) {
139 return 0U;
140 }
141 const uint32_t idx = (uint32_t)(off / 4UL);
142 return (idx < (uint32_t)k_ssie_regs) ? (uint64_t)s->reg[idx] : 0U;
143}
144
157RA8_INTERNAL static void
158internal_ssie_write(uc_engine* uc, uint64_t addr, unsigned size, uint64_t value)
159{
160 (void)uc;
161 (void)size;
162 const uint32_t ch = (uint32_t)((addr - (uint64_t)k_ssie_base) / (uint64_t)k_ssie_stride);
163 const uint64_t off = (addr - (uint64_t)k_ssie_base) % (uint64_t)k_ssie_stride;
164 if (ch >= (uint32_t)k_ssie_count) {
165 return;
166 }
167 ssie_state_t* s = &s_ssie[ch];
168 if (off == (uint64_t)k_ssie_off_ssiftdr) {
169 s->tx_samples++; /* Transmit FIFO drains immediately in the model. */
170 return;
171 }
172 if ((off % 4UL) != 0UL) {
173 return;
174 }
175 const uint32_t idx = (uint32_t)(off / 4UL);
176 if (idx < (uint32_t)k_ssie_regs) {
177 s->reg[idx] = (uint32_t)value;
178 }
179}
180
190{
191 for (uint32_t ch = 0U; ch < (uint32_t)k_ssie_count; ch++) {
192 const uint32_t ssicr = s_ssie[ch].reg[k_ssie_off_ssicr / 4U];
193 if ((ssicr == 0U) && (s_ssie[ch].tx_samples == 0U)) {
194 continue; /* Untouched channel: stay quiet. */
195 }
196 /* Console I2S tab: per-channel TX-sample tally at end-of-run. I2S streams a
197 * sample per SSIFTDR write (far too fast to log live), so the bounded
198 * transfer summary is the whole-run tally -- the same shape spi_report uses. */
200 (void)snprintf(ln,
201 sizeof(ln),
202 "I2S ch%u tx_samples=%u",
203 (unsigned)ch,
204 (unsigned)s_ssie[ch].tx_samples);
206 (void)priv_emu_io_errf(" SSIE%u : TEN=%u REN=%u tx_samples=%u\n",
207 ch,
208 (unsigned)((ssicr >> 1) & 1U),
209 (unsigned)(ssicr & 1U),
210 s_ssie[ch].tx_samples);
211 }
212}
213
216 .base = (uint32_t)k_ssie_base,
217 .span = (uint32_t)k_ssie_span,
218 .order = (uint32_t)k_ssie_block_order,
219 .read = internal_ssie_read,
221 .tick = nullptr,
222 .reset = internal_ssie_reset,
223 .report = internal_ssie_report,
224 .name = "SSIE",
225};
226
228[[gnu::constructor]] RA8_INTERNAL static void internal_ssie_block_register(void)
229{
231}
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_i2s
SSIE / I2S sample-block summaries.
Decentralized peripheral-block registry for the board emulator core.
void board_periph_register_block(const board_periph_block_t *block)
Register a peripheral block's descriptor with the core registry.
ssie_field_t
SSICR / SSISR / SSIFSR field masks used by the model.
@ k_ssie_ren_ten
SSICR REN | TEN.
@ k_ssie_iirq
SSISR IIRQ idle-mode flag (bit 25).
@ k_ssie_tde
SSIFSR TDE transmit-FIFO-empty.
static RA8_INTERNAL void internal_ssie_block_register(void)
Register the SSIE block before main (host constructor).
ssie_off_t
Per-channel register byte offsets (ra8_ssie_regs.h).
@ k_ssie_off_ssifrdr
Receive FIFO data.
@ k_ssie_off_ssicr
Control (REN/TEN, MST, DWL, SWL ...).
@ k_ssie_off_ssifsr
FIFO status (RDF, TDE, RDC, TDC).
@ k_ssie_off_ssisr
Status (IIRQ + over/underflow flags).
@ k_ssie_off_ssifcr
FIFO control (RFRST/TFRST ...).
@ k_ssie_off_ssiftdr
Transmit FIFO data.
ssie_order_t
Per-tick order slot for the SSIE block (relative order only).
@ k_ssie_block_order
After the existing blocks; report order.
static RA8_INTERNAL void internal_ssie_reset(void)
Reset all SSIE channel shadows to power-on (zeroed) state.
static ssie_state_t s_ssie[k_ssie_count]
static const board_periph_block_t s_k_ssie_block
SSIE block descriptor (self-registered with the core).
static RA8_INTERNAL void internal_ssie_report(void)
End-of-run SSIE section: per-channel enable state + TX tally.
static RA8_INTERNAL void internal_ssie_write(uc_engine *uc, uint64_t addr, unsigned size, uint64_t value)
MMIO write inside the SSIE window: route to the addressed channel.
ssie_console_t
Console-tap line buffer capacity for an I2S/SSIE summary.
@ k_ssie_console_line_cap
Max chars in an "I2S ch.. tx=.." line.
ssie_map_t
SSIE block geometry (ra8_ssie_regs.h).
@ k_ssie_base
SSIE0 base.
@ k_ssie_span
Ssie span.
@ k_ssie_count
SSIE0, SSIE1.
@ k_ssie_stride
Bytes per SSIE channel.
@ k_ssie_regs
Shadowed 32-bit words per channel (0x00..0xFC).
static RA8_INTERNAL uint64_t internal_ssie_read(uc_engine *uc, uint64_t addr, unsigned size)
MMIO read inside the SSIE window: route to the addressed channel.
Bounded raw-descriptor I/O seam for the RA8 emulator.
emu_io_result_t priv_emu_io_errf(const char *format,...)
Format bounded text and write it to the injected error descriptor.
-proof
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
A modelled peripheral block's self-description for the core registry.
One SSIE channel: a flat register shadow + a TX sample tally.
uint32_t tx_samples
SSIFTDR writes drained.
uint32_t reg[k_ssie_regs]
32-bit register shadow by word index.