ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1
82
83#include <stddef.h>
84#include <stdint.h>
85
86#include "ra8_board_ek_ra8d2.h"
87#include "ra8_boot_entry.h"
88#include "ra8_cache.h"
89#include "ra8_cgc.h"
90#include "ra8_check.h"
91#include "ra8_dtc.h"
92#include "ra8_dtc_regs.h"
93#include "ra8_elc.h"
94#include "ra8_err.h"
95#include "ra8_icu_regs.h"
96#include "ra8_isr.h"
97#include "ra8_log.h"
98#include "ra8_mstp.h"
99
101static const char* s_tag = "dtc_coherency_hil";
102
110typedef enum : uint32_t {
111 k_dtc_coh_baud = 115200U,
115 k_dtc_coh_sentinel = 0xA5A5A5A5U,
117
125typedef enum : uint8_t {
130
141typedef enum : uint16_t {
144
151typedef enum : uint8_t {
154
169
185
194typedef enum : uint16_t {
198
208typedef enum : uint32_t {
213
214static_assert((uint32_t)k_dtc_coh_buf_words == (uint32_t)k_dtc_coh_cra_units,
215 "CRA=0x0000 encodes a 256-unit block; buffer must be 256 words");
216static_assert((uint32_t)k_dtc_coh_buf_words * sizeof(uint32_t) == (uint32_t)k_dtc_coh_buf_bytes,
217 "buffer byte count must equal words * 4");
218static_assert((uint32_t)k_dtc_coh_buf_bytes >= (uint32_t)k_dtc_coh_align,
219 "buffer must span at least one D-cache line");
220
230static const uint8_t k_dtc_coh_pass_banner[] = "dtc_coherency_hil: dtc coherent PASS\r\n";
231
239static const uint8_t k_dtc_coh_fail_banner[] = "dtc_coherency_hil: dtc coherent FAIL\r\n";
240
250alignas(k_dtc_coh_align) static uint32_t s_src[k_dtc_coh_buf_words];
251
261alignas(k_dtc_coh_align) static uint32_t s_dst[k_dtc_coh_buf_words];
262
274
286
295static uint16_t s_dtc_slot;
296
315[[noreturn]] static void dtc_coh_park(void)
316{
317 while (1) {
318 __asm__ volatile("wfi");
319 }
320}
321
341static void dtc_coh_complete_cb(void* ctx, uint16_t status)
342{
343 (void)ctx;
344 (void)status;
345}
346
366static void dtc_coh_swevt_isr(void* ctx)
367{
368 (void)ctx;
370}
371
390static void dtc_coh_setup_or_halt(void)
391{
392 if (ra8_cgc_init() != k_ra8_ok) {
393 dtc_coh_park();
394 }
395 if (ra8_mstp_init() != k_ra8_ok) {
396 dtc_coh_park();
397 }
398 if (ra8_isr_init() != k_ra8_ok) {
399 dtc_coh_park();
400 }
401 if (ra8_elc_init() != k_ra8_ok) {
402 dtc_coh_park();
403 }
405 dtc_coh_park();
406 }
408 dtc_coh_park();
409 }
411 dtc_coh_park();
412 }
413}
414
433static void dtc_coh_bringup_or_halt(void)
434{
436 dtc_coh_park();
437 }
439 dtc_coh_park();
440 }
443 nullptr,
444 (uint8_t)k_dtc_coh_isr_prio,
445 &s_dtc_slot) != k_ra8_ok) {
446 dtc_coh_park();
447 }
448 if (s_dtc_slot >= (uint16_t)k_dtc_coh_vt_entries) {
449 dtc_coh_park();
450 }
451}
452
474static void dtc_coh_fill_buffers(void)
475{
476 for (uint32_t i = 0U; i < (uint32_t)k_dtc_coh_buf_words; ++i) {
477 s_src[i] = i ^ (i >> (uint32_t)k_dtc_coh_byte_sh);
478 s_dst[i] = (uint32_t)k_dtc_coh_sentinel;
479 }
480}
481
503static void dtc_coh_program_ti(void)
504{
505 const uint8_t mra = (uint8_t)(((uint8_t)k_dtc_coh_md_block << k_dtc_coh_mra_md_pos) |
508 const uint8_t mrb = (uint8_t)((uint8_t)k_dtc_coh_dm_inc << k_dtc_coh_mrb_dm_pos);
509 /* MR[31:24]=MRA, MR[23:16]=MRB, MR[15:8]=MRC(0); HUM Ch 18.2.2 p 786 /
510 * 18.2.3 p 787 / 18.2.4 p 789, Figure 18.4 p 799. SRAM (not MMIO). */
511 s_dtc_ti.MR =
512 ((uint32_t)mra << k_dtc_coh_mra_byte_pos) | ((uint32_t)mrb << k_dtc_coh_mrb_byte_pos);
513 s_dtc_ti.SAR = (uint32_t)(uintptr_t)s_src;
514 s_dtc_ti.DAR = (uint32_t)(uintptr_t)s_dst;
515 s_dtc_ti.CRB = (uint16_t)k_dtc_coh_crb_one_block;
516 s_dtc_ti.CRA = (uint16_t)k_dtc_coh_cra_block_256;
517 s_dtc_vt[s_dtc_slot] = (uint32_t)(uintptr_t)&s_dtc_ti;
518}
519
539[[nodiscard]] static ra8_err_t dtc_coh_arm_slot(void)
540{
541 volatile uint32_t* slot_reg = ra8_icu_ielsr(s_dtc_slot);
542 if (slot_reg == nullptr) {
543 return k_ra8_err_hw_error;
544 }
545 /* HUM Ch 14.2.17 "IELSRn : ICU Event Link Setting Register n" p 547:
546 * DTCE[24] enables DTC activation; the IELS event field is preserved. */
547 *slot_reg = *slot_reg | (uint32_t)k_ra8_ielsr_dtce_mask;
548 return k_ra8_ok;
549}
550
575[[nodiscard]] static uint8_t dtc_coh_verify(void)
576{
577 for (uint32_t i = 0U; i < (uint32_t)k_dtc_coh_buf_words; ++i) {
578 if (s_dst[i] != s_src[i]) {
579 return 0U;
580 }
581 }
582 return 1U;
583}
584
622[[nodiscard]] static ra8_err_t dtc_coh_run_once(uint8_t* out_ok)
623{
624 RA8_CHECK_NULL_PTR(out_ok, s_tag, "out_ok must not be nullptr");
625 *out_ok = 0U;
626
627 /* clean-before (app owns the TI + source): dirty lines -> SRAM so the DTC
628 * reads the real descriptor and the real pattern from memory. */
629 if (ra8_cache_dcache_clean_by_addr(s_src, (uint32_t)sizeof(s_src)) != k_ra8_ok) {
630 return k_ra8_err_hw_error;
631 }
632 if (ra8_cache_dcache_clean_by_addr(&s_dtc_ti, (uint32_t)sizeof(s_dtc_ti)) != k_ra8_ok) {
633 return k_ra8_err_hw_error;
634 }
635
636 /* The HAL cleans the caller-populated vector table here, then DTCST = 1. */
637 const ra8_err_t en = ra8_dtc_enable();
638 if (en != k_ra8_ok) {
639 return en;
640 }
641 const ra8_err_t arm = dtc_coh_arm_slot();
642 if (arm != k_ra8_ok) {
643 return arm;
644 }
646 if (trig != k_ra8_ok) {
647 return trig;
648 }
649
650 /* Completion + coherency gate: invalidate-after each poll so the verify reads
651 * what the DTC wrote to SRAM (not the dirty sentinel still in cache), and stop
652 * as soon as the full block has landed. Bounded so a stale-descriptor copy
653 * (the regression this app guards against) times out instead of hanging. */
654 bool done = false;
655 for (uint32_t i = 0U; i < (uint32_t)k_dtc_coh_poll_limit; ++i) {
656 if (ra8_cache_dcache_invalidate_by_addr(s_dst, (uint32_t)sizeof(s_dst)) != k_ra8_ok) {
657 return k_ra8_err_hw_error;
658 }
659 if (dtc_coh_verify() != 0U) {
660 done = true;
661 break;
662 }
663 }
664 if (!done) {
666 }
667 *out_ok = 1U;
668 return k_ra8_ok;
669}
670
686static void dtc_coh_report(uint8_t ok)
687{
688 if (ok != 0U) {
690 (size_t)(sizeof(k_dtc_coh_pass_banner) - 1U));
692 ra8_log_info(s_tag, "dtc coherent PASS");
694 } else {
696 (size_t)(sizeof(k_dtc_coh_fail_banner) - 1U));
698 ra8_log_info(s_tag, "dtc coherent FAIL");
700 }
701}
702
719void main(void)
720{
721 ra8_log_init();
722 ra8_log_info(s_tag, "==== dtc_coherency_hil: M85 D-cache DTC descriptor coherency ====");
723
726
729
730 uint8_t ok = 0U;
731 const ra8_err_t err = dtc_coh_run_once(&ok);
732 const uint8_t good = (err == k_ra8_ok && ok != 0U) ? 1U : 0U;
733 dtc_coh_report(good);
734
735 dtc_coh_park();
736}
void main(void)
Secure fallback main entry point.
Definition main.c:37
static uint32_t s_dtc_vt[k_dtc_arm_vt_entries]
DTC vector table – one 4-byte TI start address per IELSR slot.
Definition main.c:189
static r_dtc_xfer_info_t s_dtc_ti
The 16-byte Transfer Information block the DTC reads each pass.
Definition main.c:196
static uint32_t s_src[k_dtc_arm_buf_words]
Source / destination buffers (32-bit aligned by element type).
Definition main.c:181
static uint16_t s_dtc_slot
IELSR slot allocated for the DTC activation = DTC vector number.
Definition main.c:199
static uint32_t s_dst[k_dtc_arm_buf_words]
Definition main.c:182
static void dtc_coh_fill_buffers(void)
Fill s_src with a deterministic pattern; prime s_dst.
Definition main.c:474
static void dtc_coh_complete_cb(void *ctx, uint16_t status)
DTC completion callback (fanned out by ra8_dtc_dispatch).
Definition main.c:341
dtc_coh_event_t
ELC software event 0 -> ICU event number.
Definition main.c:141
@ k_dtc_coh_event_swevt0
ELC software event 0 (HUM Table 19.3).
Definition main.c:142
static void dtc_coh_program_ti(void)
Write the 16-byte TI block and point the slot's vector entry at it.
Definition main.c:503
dtc_coh_vt_geom_t
DTC vector-table geometry.
Definition main.c:208
@ k_dtc_coh_vt_entries
One pointer per IELSR slot 0..95.
Definition main.c:209
@ k_dtc_coh_vt_align
DTCVBR 1 KiB alignment (HUM 18.2.2).
Definition main.c:210
@ k_dtc_coh_cra_units
Units per block when CRAH/CRAL = 0.
Definition main.c:211
static void dtc_coh_setup_or_halt(void)
Bring CGC + MSTP + ISR + ELC + SCI8 console + LEDs up.
Definition main.c:390
dtc_coh_mr_field_t
DTC Transfer-Information mode-bit field values.
Definition main.c:163
@ k_dtc_coh_dm_inc
MRB.DM[3:2] = 10b: increment DAR.
Definition main.c:167
@ k_dtc_coh_sm_inc
MRA.SM[3:2] = 10b: increment SAR.
Definition main.c:166
@ k_dtc_coh_md_block
MRA.MD[7:6] = 10b: block transfer mode.
Definition main.c:164
@ k_dtc_coh_sz_word
MRA.SZ[5:4] = 10b: 32-bit word units.
Definition main.c:165
static const uint8_t k_dtc_coh_pass_banner[]
Deterministic one-shot HIL success banner (uart_scrape gate).
Definition main.c:230
dtc_coh_count_t
DTC count-register values for one 256-word block.
Definition main.c:194
@ k_dtc_coh_cra_block_256
CRAH = CRAL = 0 => 256-unit block.
Definition main.c:195
@ k_dtc_coh_crb_one_block
CRB = 1 => one block per pass.
Definition main.c:196
static ra8_err_t dtc_coh_arm_slot(void)
Re-arm DTC activation on the slot (set IELSRn.DTCE).
Definition main.c:539
static ra8_err_t dtc_coh_run_once(uint8_t *out_ok)
Clean src + TI, enable + trigger the DTC, then wait for the copy.
Definition main.c:622
static void dtc_coh_park(void)
Park the Cortex-M85 forever in a WFI idle loop.
Definition main.c:315
dtc_coh_mr_pos_t
Bit positions inside the DTC TI MR word.
Definition main.c:177
@ k_dtc_coh_mra_byte_pos
MRA byte offset within MR.
Definition main.c:182
@ k_dtc_coh_mra_md_pos
MRA.MD field position.
Definition main.c:178
@ k_dtc_coh_mra_sz_pos
MRA.SZ field position.
Definition main.c:179
@ k_dtc_coh_mrb_byte_pos
MRB byte offset within MR.
Definition main.c:183
@ k_dtc_coh_mrb_dm_pos
MRB.DM field position.
Definition main.c:181
@ k_dtc_coh_mra_sm_pos
MRA.SM field position.
Definition main.c:180
dtc_coh_swevt_t
ELSEGRn index fired by ra8_elc_software_trigger.
Definition main.c:151
@ k_dtc_coh_swevt_index
ELSEGR0 -> ELC_SWEVT0 (0x0CC).
Definition main.c:152
static void dtc_coh_swevt_isr(void *ctx)
IELSR-slot ISR for the DTC-complete interrupt (masked in this app).
Definition main.c:366
dtc_coh_config_t
Compile-time scalar parameters for the DTC coherency self-test.
Definition main.c:110
@ k_dtc_coh_buf_bytes
Bytes copied per pass (>= 256, 1 KiB).
Definition main.c:113
@ k_dtc_coh_baud
VCOM console line rate (8N1).
Definition main.c:111
@ k_dtc_coh_poll_limit
Bounded wait for the copy to land in RAM.
Definition main.c:114
@ k_dtc_coh_buf_words
32-bit words per buffer (256 x 4).
Definition main.c:112
@ k_dtc_coh_sentinel
Destination pre-fill; no-op copy fails.
Definition main.c:115
static const uint8_t k_dtc_coh_fail_banner[]
Failure banner: the copy was wrong, absent, or timed out.
Definition main.c:239
dtc_coh_byte_t
Single-byte scalar constants for the self-test.
Definition main.c:125
@ k_dtc_coh_isr_prio
NVIC priority for the DTC-complete slot.
Definition main.c:128
@ k_dtc_coh_align
D-cache line size (bytes).
Definition main.c:127
@ k_dtc_coh_byte_sh
Source-pattern shift (i ^ (i >> 8)).
Definition main.c:126
static void dtc_coh_bringup_or_halt(void)
Initialise the DTC and allocate its ELC-software-event activation slot.
Definition main.c:433
static void dtc_coh_report(uint8_t ok)
Emit the PASS/FAIL result over VCOM and ITM, toggle an LED.
Definition main.c:686
static uint8_t dtc_coh_verify(void)
Verify s_dst matches s_src element-by-element.
Definition main.c:575
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Board-support layer for the Renesas EK-RA8D2 v1 evaluation kit.
ra8_err_t ra8_board_led_toggle(ra8_board_led_id_t led)
Toggle led's output state.
ra8_err_t ra8_board_led_init(ra8_board_led_id_t led)
Configure led as a digital output, initial level low (off).
@ k_ra8_board_led2
LED2, GREEN, P303 (jumper E26).
@ k_ra8_board_led1
LED1, BLUE, P600 (jumper E27).
ra8_err_t ra8_board_uart_console_write(const uint8_t *data, size_t len)
Polled blocking write to the J-Link OB VCOM console.
ra8_err_t ra8_board_uart_console_init(uint32_t baud)
Configure SCI8 + PD02/PD03 as the debug-console UART.
ra8_err_t ra8_board_uart_console_flush(void)
Block until every byte queued on the J-Link OB VCOM console has finished clocking out on the wire.
Boot entry points shared between a vector table and its startup code.
Cortex-M85 L1 cache maintenance, enable/disable, and I-cache invalidate.
ra8_err_t ra8_cache_dcache_invalidate_by_addr(const void *addr, uint32_t size)
Invalidate (drop) the D-cache lines covering a byte range.
Definition ra8_cache.c:185
ra8_err_t ra8_cache_dcache_clean_by_addr(const void *addr, uint32_t size)
Clean (write back) the D-cache lines covering a byte range.
Definition ra8_cache.c:180
High-level Clock Generation Circuit driver.
ra8_err_t ra8_cgc_init(void)
Configure the clock tree to a safe default.
Definition ra8_cgc.c:727
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
Data Transfer Controller (DTC) driver.
void ra8_dtc_dispatch(void)
Fire the attached activation callback with current DTCSTS.
Definition ra8_dtc.c:180
ra8_err_t ra8_dtc_attach_handler(ra8_dtc_event_fn_t fn, void *ctx)
Attach a shared activation-complete callback.
Definition ra8_dtc.c:172
ra8_err_t ra8_dtc_enable(void)
Start the DTC module.
Definition ra8_dtc.c:104
ra8_err_t ra8_dtc_init(void *vector_base)
Initialise the DTC and install its vector table base.
Definition ra8_dtc.c:60
DTC (Data Transfer Controller) register layout for the RA8D2.
Event Link Controller driver.
ra8_err_t ra8_elc_init(void)
Reset the ELC register block and enable the controller.
Definition ra8_elc.c:91
ra8_err_t ra8_elc_software_trigger(uint8_t event_index)
Fire a software event via one of the ELSEGRn registers.
Definition ra8_elc.c:147
ra8_elc_event_t
Partial list of ELC events (populate as drivers need them).
Error Code Definitions for ra8-firmware.
@ k_ra8_err_hw_timeout
Hardware timed out waiting for a flag or handshake.
Definition ra8_err.h:304
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_hw_error
Generic hardware fault detected (error flag set, fault interrupt).
Definition ra8_err.h:310
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Interrupt Control Unit (ICU) register layout for the Renesas RA8D2.
static volatile uint32_t * ra8_icu_ielsr(uint16_t index)
Get pointer to IELSR register N.
@ k_ra8_ielsr_dtce_mask
DTCE bit mask.
NVIC + ICU IELSR allocator.
ra8_err_t ra8_isr_init(void)
Initialise the ra8_isr table.
Definition ra8_isr.c:229
ra8_err_t ra8_isr_register(ra8_elc_event_t event, ra8_isr_handler_t handler, void *ctx, uint8_t priority, uint16_t *out_slot)
Allocate an IELSR slot for an ELC event + handler.
Definition ra8_isr.c:296
Lightweight Logging Interface for ra8-firmware.
void ra8_log_init(void)
Initialise the logging backend.
Definition ra8_log.c:379
#define ra8_log_info(tag, message)
RA8 log info.
Definition ra8_log.h:364
Ref-counted Module Stop Control wrapper for the RA8D2.
ra8_err_t ra8_mstp_init(void)
Re-establish the ra8_mstp ref-count table from current hardware state.
Definition ra8_mstp.c:291
One 16-byte Transfer Information (TI) block referenced by the DTC vector table.