ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
c6_sideband.c
Go to the documentation of this file.
1
33
34#include <stdint.h>
35
36#include "c6_probe.h"
37#include "ra8_board_ek_ra8d2.h"
38#include "ra8_err.h"
39#include "ra8_port_utils.h"
40#include "ra8_time.h"
41
57
67static const char* const k_c6_sideband_label[k_c6_sb_count + 1U] = {
68 "P006",
69 "P402",
70 "P412",
71 "P413",
72 "unresolved",
73};
74
91
101static const char* const k_c6_wire_label[k_c6_wire_count + 1U] = {
102 "P800(J26-1 in UART mux)",
103 "P801(J26-2)",
104 "P802(J26-3)",
105 "P803(J26-4 in SPI mux)",
106 "P804(J26-1 in SPI mux)",
107 "none",
108};
109
111{
112 for (uint8_t i = 0U; i < (uint8_t)k_c6_sb_count; i++) {
114 if (err != k_ra8_ok) {
115 return err;
116 }
117 }
118 return k_ra8_ok;
119}
120
122{
123 if (out == nullptr) {
124 return;
125 }
126 for (uint8_t i = 0U; i < (uint8_t)k_c6_sb_count; i++) {
128 if (ra8_gpio_read(k_c6_sideband_pin[i], &level) != k_ra8_ok) {
129 level = k_ra8_level_low;
130 }
131 out->level[i] = (level == k_ra8_level_high) ? 1U : 0U;
132 }
133}
134
135const char* c6_probe_sideband_name(uint8_t idx)
136{
137 const uint8_t safe = (idx < (uint8_t)k_c6_sb_count) ? idx : (uint8_t)k_c6_sb_count;
138 return k_c6_sideband_label[safe];
139}
140
141void c6_probe_print_sideband(const char* label, const c6_sideband_sample_t* s)
142{
143 if (s == nullptr) {
144 return;
145 }
146 c6_probe_puts(label);
147 for (uint8_t i = 0U; i < (uint8_t)k_c6_sb_count; i++) {
148 c6_probe_puts(" ");
150 c6_probe_puts("=");
151 c6_probe_put_u32((uint32_t)s->level[i]);
152 }
153 c6_probe_puts("\r\n");
154}
155
157 const c6_sideband_sample_t* mid,
158 const c6_sideband_sample_t* post,
160{
161 if (pre == nullptr || mid == nullptr || post == nullptr || st == nullptr) {
162 return;
163 }
164 for (uint8_t i = 0U; i < (uint8_t)k_c6_sb_count; i++) {
165 if (pre->level[i] != 0U && mid->level[i] == 0U) {
166 st->hs_vote[i]++;
167 }
168 if (pre->level[i] != 0U && post->level[i] == 0U) {
169 st->dr_vote[i]++;
170 }
171 if (pre->level[i] != 0U || mid->level[i] != 0U || post->level[i] != 0U) {
172 st->ever_high[i] = 1U;
173 }
174 if (pre->level[i] == 0U || mid->level[i] == 0U || post->level[i] == 0U) {
175 st->ever_low[i] = 1U;
176 }
177 }
178}
179
180uint8_t c6_probe_best(const uint32_t* votes, uint8_t ignore, uint32_t min_votes)
181{
182 if (votes == nullptr || min_votes == 0U) {
183 return (uint8_t)k_c6_sb_count;
184 }
185 uint8_t best = (uint8_t)k_c6_sb_count;
186 uint32_t best_score = 0U;
187 uint8_t tied = 0U;
188 for (uint8_t i = 0U; i < (uint8_t)k_c6_sb_count; i++) {
189 if (i == ignore || votes[i] < min_votes) {
190 continue;
191 }
192 if (votes[i] > best_score) {
193 best_score = votes[i];
194 best = i;
195 tied = 0U;
196 continue;
197 }
198 if (votes[i] == best_score) {
199 tied++;
200 }
201 }
202 return (tied == 0U) ? best : (uint8_t)k_c6_sb_count;
203}
204
232{
233 if (out_low == nullptr) {
234 return k_ra8_err_null_ptr;
235 }
237 if (err == k_ra8_ok) {
239 }
240 uint8_t low = 0U;
241 if (err == k_ra8_ok) {
243 for (uint8_t s = 0U; s < (uint8_t)k_c6_probe_pull_samples; s++) {
245 /* A failed read must abort the contest, not shorten it. Silently
246 * returning a partial count would report "not sunk" for a pin that was
247 * never fully measured -- the same read-silence-as-absence mistake this
248 * whole mechanism exists to correct. */
249 err = ra8_gpio_read(pin, &level);
250 if (err != k_ra8_ok) {
251 break;
252 }
253 if (level == k_ra8_level_low) {
254 low++;
255 }
257 }
258 }
259
260 const ra8_err_t released = ra8_gpio_release(pin);
262 if (err == k_ra8_ok) {
263 err = (released != k_ra8_ok) ? released : restored;
264 }
265 *out_low = low;
266 return err;
267}
268
270{
271 if (st == nullptr) {
272 return k_ra8_err_null_ptr;
273 }
274 for (uint8_t i = 0U; i < (uint8_t)k_c6_sb_count; i++) {
275 uint8_t low = 0U;
276 const ra8_err_t err = internal_pull_read(k_c6_sideband_pin[i], &low);
277 if (err != k_ra8_ok) {
278 return err;
279 }
280 st->pull_low[i] = low;
281 c6_probe_puts("c6_probe: pull-up ");
283 c6_probe_puts(" low=");
284 c6_probe_put_u32((uint32_t)low);
285 c6_probe_puts("/");
287 c6_probe_puts((low >= (uint8_t)k_c6_probe_pull_samples) ? " SUNK: driven low off-chip\r\n"
288 : " follows the pull-up\r\n");
289 }
291 return k_ra8_ok;
292}
293
294uint8_t c6_probe_sunk_pin(const c6_probe_stats_t* st, uint8_t ignore)
295{
296 if (st == nullptr || st->pull_samples == 0U) {
297 return (uint8_t)k_c6_sb_count;
298 }
299 uint8_t found = (uint8_t)k_c6_sb_count;
300 uint8_t sunk = 0U;
301 for (uint8_t i = 0U; i < (uint8_t)k_c6_sb_count; i++) {
302 if (i == ignore || st->pull_low[i] < st->pull_samples) {
303 continue;
304 }
305 if (sunk == 0U) {
306 found = i;
307 }
308 sunk++;
309 }
310 return (sunk == 1U) ? found : (uint8_t)k_c6_sb_count;
311}
312
313void c6_probe_resolve_map(const c6_probe_stats_t* st, uint8_t* hs_idx, uint8_t* dr_idx)
314{
315 if (st == nullptr || hs_idx == nullptr || dr_idx == nullptr) {
316 return;
317 }
318 const uint8_t hs =
320 uint8_t dr = c6_probe_sunk_pin(st, hs);
321 if (dr == (uint8_t)k_c6_sb_count) {
322 dr = c6_probe_best(st->dr_vote, hs, (uint32_t)k_c6_probe_min_votes);
323 }
324 *hs_idx = hs;
325 *dr_idx = dr;
326}
327
355static ra8_err_t internal_kick_net(ra8_port_pin_t pin, ra8_level_t level, uint8_t* out_level)
356{
357 if (out_level == nullptr) {
358 return k_ra8_err_null_ptr;
359 }
360 ra8_err_t err = ra8_gpio_output_init(pin, level);
361 if (err != k_ra8_ok) {
362 return err;
363 }
365 err = ra8_gpio_release(pin);
366 if (err != k_ra8_ok) {
367 return err;
368 }
370 if (err != k_ra8_ok) {
371 return err;
372 }
375 err = ra8_gpio_read(pin, &sampled);
376 if (err != k_ra8_ok) {
377 (void)ra8_gpio_release(pin);
378 return err;
379 }
380 *out_level = (sampled == k_ra8_level_high) ? 1U : 0U;
381 return ra8_gpio_release(pin);
382}
383
384c6_wire_kind_t c6_probe_wire_kind(uint8_t after_high, uint8_t after_low)
385{
386 if (after_high != 0U && after_low == 0U) {
387 return k_c6_wire_floating;
388 }
389 if (after_high == 0U && after_low == 0U) {
390 return k_c6_wire_low_side;
391 }
392 if (after_high != 0U && after_low != 0U) {
393 return k_c6_wire_high_side;
394 }
395 return k_c6_wire_odd;
396}
397
399{
400 static const char* const k_kind_name[] = {
401 "floating(no termination)",
402 "low-side(pull-down or driven low)",
403 "high-side(pull-up or driven high)",
404 "inconsistent",
405 };
406 for (uint8_t i = 0U; i < (uint8_t)k_c6_wire_count; i++) {
407 uint8_t after_high = 0U;
408 uint8_t after_low = 0U;
409 const ra8_err_t e_high = internal_kick_net(k_c6_wire_pin[i], k_ra8_level_high, &after_high);
410 const ra8_err_t e_low = internal_kick_net(k_c6_wire_pin[i], k_ra8_level_low, &after_low);
411 c6_probe_puts("c6_probe: wire ");
413 if (e_high != k_ra8_ok || e_low != k_ra8_ok) {
414 c6_probe_puts(" test failed\r\n");
415 continue;
416 }
417 c6_probe_puts(" hi->");
418 c6_probe_put_u32((uint32_t)after_high);
419 c6_probe_puts(" lo->");
420 c6_probe_put_u32((uint32_t)after_low);
421 c6_probe_puts(" ");
422 const c6_wire_kind_t kind = c6_probe_wire_kind(after_high, after_low);
423 c6_probe_puts(k_kind_name[(uint8_t)kind]);
424 c6_probe_puts("\r\n");
425 }
426}
427
453static bool internal_cs_try(uint8_t idx, c6_probe_stats_t* st)
454{
455 const ra8_port_pin_t pin = k_c6_wire_pin[idx];
457 return false;
458 }
460 c6_sideband_sample_t idle = {};
462
465 c6_sideband_sample_t asserted = {};
466 c6_probe_sample_sideband(&asserted);
467
470 (void)ra8_gpio_release(pin);
471
472 bool answered = false;
473 for (uint8_t i = 0U; i < (uint8_t)k_c6_sb_count; i++) {
474 if (idle.level[i] != 0U && asserted.level[i] == 0U) {
475 st->hs_vote[i]++;
476 answered = true;
477 }
478 }
479 c6_probe_puts("c6_probe: cs-hunt ");
481 c6_probe_print_sideband(answered ? " ANSWERED, asserted" : " no response, asserted", &asserted);
482 return answered;
483}
484
486{
487 if (st == nullptr) {
488 return (uint8_t)k_c6_wire_count;
489 }
490 uint8_t found = (uint8_t)k_c6_wire_count;
491 for (uint8_t i = 0U; i < (uint8_t)k_c6_wire_count; i++) {
492 if (internal_cs_try(i, st) && found == (uint8_t)k_c6_wire_count) {
493 found = i;
494 }
495 }
496 c6_probe_puts("c6_probe: cs-hunt result ");
498 c6_probe_puts("\r\n");
499 return found;
500}
Shared contract for the EK-RA8D2 <-> ESP32-C6 esp-hosted SPI probe.
@ k_c6_sb_count
Side-band pin count.
Definition c6_probe.h:177
@ k_c6_probe_settle_ms
Post-transfer side-band settle.
Definition c6_probe.h:74
@ k_c6_probe_cs_hold_ms
Chip-select setup / hold.
Definition c6_probe.h:76
void c6_probe_puts(const char *text)
Emit a bounded, NUL-terminated ASCII literal on the console.
Definition c6_console.c:25
c6_wire_kind_t
What the drive-and-release test says is on the far end of a net.
Definition c6_probe.h:250
@ k_c6_wire_low_side
Snapped to 0: pull-down or driven low.
Definition c6_probe.h:252
@ k_c6_wire_high_side
Snapped to 1: pull-up or driven high.
Definition c6_probe.h:253
@ k_c6_wire_odd
Inverted result: not physically sane.
Definition c6_probe.h:254
@ k_c6_wire_floating
Held both levels: no termination.
Definition c6_probe.h:251
void c6_probe_put_u32(uint32_t value)
Emit an unsigned integer in decimal.
Definition c6_console.c:38
@ k_c6_probe_min_votes
Votes required to claim a mapping.
Definition c6_probe.h:114
@ k_c6_probe_pull_samples
Reads per pin in the pull-up contest.
Definition c6_probe.h:112
@ k_c6_probe_pull_settle_ms
Settle between pull-up contest reads.
Definition c6_probe.h:113
@ k_c6_wire_count
Muxed-net candidate count.
Definition c6_probe.h:227
c6_wire_kind_t c6_probe_wire_kind(uint8_t after_high, uint8_t after_low)
Classify one Pmod1 net from its two drive-and-release samples.
void c6_probe_vote(const c6_sideband_sample_t *pre, const c6_sideband_sample_t *mid, const c6_sideband_sample_t *post, c6_probe_stats_t *st)
Fold one transaction's three samples into the classification votes.
const char * c6_probe_sideband_name(uint8_t idx)
Name a side-band pin for the console.
static const char *const k_c6_wire_label[k_c6_wire_count+1U]
Console labels for k_c6_wire_pin, same order.
static const ra8_port_pin_t k_c6_sideband_pin[k_c6_sb_count]
The four Pmod1 side-band pins, in c6_sideband_idx_t order.
Definition c6_sideband.c:51
static const char *const k_c6_sideband_label[k_c6_sb_count+1U]
Console labels for k_c6_sideband_pin, same order.
Definition c6_sideband.c:67
static ra8_err_t internal_kick_net(ra8_port_pin_t pin, ra8_level_t level, uint8_t *out_level)
Drive one net to a level, release it, and sample what it settles to.
static bool internal_cs_try(uint8_t idx, c6_probe_stats_t *st)
Assert one candidate chip-select and report any side-band response.
void c6_probe_sample_sideband(c6_sideband_sample_t *out)
Read every Pmod1 side-band pin into one sample.
void c6_probe_print_sideband(const char *label, const c6_sideband_sample_t *s)
Print a labelled side-band sample as label P006=1 P402=0 ....
ra8_err_t c6_probe_pull_contest(c6_probe_stats_t *st)
Find which side-band pins an external driver is holding low.
uint8_t c6_probe_sunk_pin(const c6_probe_stats_t *st, uint8_t ignore)
Name the one pin that lost every read of the pull-up contest.
static ra8_err_t internal_pull_read(ra8_port_pin_t pin, uint8_t *out_low)
Hold one pin against the internal pull-up and count the low reads.
ra8_err_t c6_probe_sideband_init(void)
Claim the four Pmod1 side-band pins as no-pull digital inputs.
uint8_t c6_probe_best(const uint32_t *votes, uint8_t ignore, uint32_t min_votes)
Pick the side-band pin that won the vote outright, or report none.
void c6_probe_wire_test(void)
Run the drive-and-release test over every Pmod1 muxed net.
static const ra8_port_pin_t k_c6_wire_pin[k_c6_wire_count]
The five Pmod1 muxed-net candidates, in c6_wire_idx_t order.
Definition c6_sideband.c:84
uint8_t c6_probe_cs_hunt(c6_probe_stats_t *st)
Find which MCU pin the board's Pmod1 mux has wired to the C6's chip-select, and identify HANDSHAKE at...
void c6_probe_resolve_map(const c6_probe_stats_t *st, uint8_t *hs_idx, uint8_t *dr_idx)
Resolve the HANDSHAKE and DATA_READY side-band map from the accumulated evidence.
Board-support layer for the Renesas EK-RA8D2 v1 evaluation kit.
@ k_ra8_board_pmod1_uart_cts
Pmod1 UART CTS (CTS2), P800.
@ k_ra8_board_pmod1_spi_copi
Pmod1.2 COPI (MOSI2/TXD2 per UM),P801.
@ k_ra8_board_pmod1_spi_sck
Pmod1.4 SCK (SCK2), P803.
@ k_ra8_board_pmod1_spi_cs
Pmod1.1 CS (SS2/IRQ14), P804.
@ k_ra8_board_pmod1_spi_cipo
Pmod1.3 CIPO (MISO2/RXD2 per UM),P802.
@ k_ra8_board_pmod1_gpio_a
Pmod1.9 GPIO, P412.
@ k_ra8_board_pmod1_gpio_b
Pmod1.10 GPIO, P413.
@ k_ra8_board_pmod1_irq
Pmod1.7 IRQ (IRQ11-DS), P006.
@ k_ra8_board_pmod1_reset
Pmod1.8 RESET, P402.
ra8_board_eth_pin_t pin
Pin.
Error Code Definitions for ra8-firmware.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
Definition ra8_err.h:478
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
ra8_port_pin_t
Packed (port << 8) | pin pin identifier.
ra8_level_t
Digital output / input level.
@ k_ra8_level_high
Drive or read 1.
@ k_ra8_level_low
Drive or read 0.
@ k_ra8_pull_none
No internal pull.
@ k_ra8_pull_up
Internal pull-up.
High-level GPIO helpers on top of the PORT + PFS register layer.
ra8_err_t ra8_gpio_read(ra8_port_pin_t pin, ra8_level_t *out_level)
Read a previously-configured input.
Definition gpio.c:210
ra8_err_t ra8_gpio_input_init(ra8_port_pin_t pin, ra8_pin_pull_t pull)
Configure a pin as a digital input.
Definition gpio.c:121
ra8_err_t ra8_gpio_output_init(ra8_port_pin_t pin, ra8_level_t init_level)
Configure a pin as a digital output and drive it to an initial level.
Definition gpio.c:88
ra8_err_t ra8_gpio_write(ra8_port_pin_t pin, ra8_level_t level)
Drive a previously-configured output to the given level.
Definition gpio.c:154
ra8_err_t ra8_gpio_release(ra8_port_pin_t pin)
Release a GPIO pin claim.
Definition gpio.c:233
SysTick-based tick counter, delay and timestamp helpers.
void ra8_delay_ms(uint32_t ms)
Busy-wait for at least ms milliseconds.
Definition ra8_time.c:129
Running evidence gathered across every transaction.
Definition c6_probe.h:280
uint8_t pull_low[k_c6_sb_count]
Reads that lost to an external sink.
Definition c6_probe.h:289
uint8_t ever_high[k_c6_sb_count]
Pin was seen high at least once.
Definition c6_probe.h:287
uint32_t hs_vote[k_c6_sb_count]
Pin dropped while CS was asserted.
Definition c6_probe.h:285
uint32_t dr_vote[k_c6_sb_count]
Pin dropped once the queue drained.
Definition c6_probe.h:286
uint8_t pull_samples
Pull-up reads per pin; 0 = not run.
Definition c6_probe.h:290
uint8_t ever_low[k_c6_sb_count]
Pin was seen low at least once.
Definition c6_probe.h:288
One simultaneous reading of every side-band pin.
Definition c6_probe.h:194
uint8_t level[k_c6_sb_count]
Per-pin logic level (0 or 1).
Definition c6_probe.h:195