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
54
55#include <stdint.h>
56
57#include "ra8_board_ek_ra8d2.h"
58#include "ra8_boot_entry.h"
59#include "ra8_cgc.h"
60#include "ra8_check.h"
61#include "ra8_dtc.h"
62#include "ra8_dtc_regs.h"
63#include "ra8_elc.h"
64#include "ra8_err.h"
65#include "ra8_isr.h"
66#include "ra8_mstp.h"
67#include "ra8_time.h"
68
70static const char* s_tag = "dtc_arm";
71
82
84typedef enum : uint8_t {
88
99typedef enum : uint16_t {
102
104typedef enum : uint8_t {
107
122
138
147typedef enum : uint16_t {
151
167
169typedef enum : uint32_t {
172
173static_assert((uint32_t)k_dtc_arm_buf_words == (uint32_t)k_dtc_arm_cra_block_units,
174 "CRA=0x0000 encodes a 256-unit block; buffer must be 256 words");
175
177static const uint8_t k_dtc_arm_ok_msg[] = "dtc-arm: armed+disarmed OK\r\n";
178static const uint8_t k_dtc_arm_bad_msg[] = "dtc-arm: FAILED\r\n";
179
181static uint32_t s_src[k_dtc_arm_buf_words];
182static uint32_t s_dst[k_dtc_arm_buf_words];
183
189[[gnu::aligned(k_dtc_arm_vt_align)]] static uint32_t s_dtc_vt[k_dtc_arm_vt_entries];
190
197
199static uint16_t s_dtc_slot;
200
207volatile uint32_t g_dtc_armed_ok = 0U;
208
215volatile uint32_t g_dtc_disarmed_ok = 0U;
216
223volatile uint32_t g_dtc_activations = 0U;
224
231volatile uint32_t g_dtc_isr_count = 0U;
232
239volatile uint32_t g_dtc_heartbeat = 0U;
240
242static void dtc_arm_panic_halt(void)
243{
244 while (1) {
245 __asm__ volatile("wfi");
246 }
247}
248
259static void dtc_arm_complete_cb(void* ctx, uint16_t status)
260{
261 (void)ctx;
262 (void)status;
264}
265
280static void dtc_arm_swevt_isr(void* ctx)
281{
282 (void)ctx;
284}
285
287static void dtc_arm_setup_or_halt(void)
288{
289 uint32_t cpuclk0_hz = 0U;
290
291 if (ra8_cgc_init() != k_ra8_ok) {
293 }
296 }
297 if (ra8_mstp_init() != k_ra8_ok) {
299 }
300 if (ra8_time_init(cpuclk0_hz) != k_ra8_ok) {
302 }
303 if (ra8_isr_init() != k_ra8_ok) {
305 }
306 if (ra8_elc_init() != k_ra8_ok) {
308 }
311 }
314 }
317 }
318}
319
332static void dtc_arm_fill(uint32_t dst_init)
333{
334 for (uint32_t i = 0U; i < (uint32_t)k_dtc_arm_buf_words; ++i) {
335 s_src[i] = i ^ (i >> (uint32_t)k_dtc_arm_byte_sh);
336 s_dst[i] = dst_init;
337 }
338}
339
356static void dtc_arm_program_ti(void)
357{
358 const uint8_t mra = (uint8_t)(((uint8_t)k_dtc_arm_md_block << k_dtc_arm_mra_md_pos) |
361 const uint8_t mrb = (uint8_t)((uint8_t)k_dtc_arm_dm_inc << k_dtc_arm_mrb_dm_pos);
362 /* MR[31:24]=MRA, MR[23:16]=MRB, MR[15:8]=MRC(0); HUM Ch 18.2.2 p 786 /
363 * 18.2.3 p 787 / 18.2.4 p 789, Figure 18.4 p 799. SRAM (not MMIO). */
364 s_dtc_ti.MR =
365 ((uint32_t)mra << k_dtc_arm_mra_byte_pos) | ((uint32_t)mrb << k_dtc_arm_mrb_byte_pos);
366 s_dtc_ti.SAR = (uint32_t)(uintptr_t)s_src;
367 s_dtc_ti.DAR = (uint32_t)(uintptr_t)s_dst;
368 s_dtc_ti.CRB = (uint16_t)k_dtc_arm_crb_one_block;
369 s_dtc_ti.CRA = (uint16_t)k_dtc_arm_cra_block_256;
370}
371
385static void dtc_arm_bringup_or_halt(void)
386{
389 }
392 }
395 nullptr,
396 (uint8_t)k_dtc_arm_isr_prio,
397 &s_dtc_slot) != k_ra8_ok) {
399 }
400 if (s_dtc_slot >= (uint16_t)k_dtc_arm_vt_entries) {
402 }
403 /* DTCVBR + slot*4 holds the 16-byte-aligned TI start address; bit0 is the
404 * privilege attribution (0 = privileged). HUM Ch 18.3.1 p 796 + Figure 18.3
405 * p 798. SRAM vector-table write (not MMIO). */
406 s_dtc_vt[s_dtc_slot] = (uint32_t)(uintptr_t)&s_dtc_ti;
407 if (ra8_dtc_enable() != k_ra8_ok) {
409 }
410}
411
425static uint8_t dtc_arm_all_match_src(void)
426{
427 for (uint32_t i = 0U; i < (uint32_t)k_dtc_arm_buf_words; ++i) {
428 if (s_dst[i] != s_src[i]) {
429 return 0U;
430 }
431 }
432 return 1U;
433}
434
449static uint8_t dtc_arm_all_equal(uint32_t expect)
450{
451 for (uint32_t i = 0U; i < (uint32_t)k_dtc_arm_buf_words; ++i) {
452 if (s_dst[i] != expect) {
453 return 0U;
454 }
455 }
456 return 1U;
457}
458
477[[nodiscard]] static ra8_err_t dtc_arm_run_armed(uint8_t* out_ok)
478{
479 RA8_CHECK_NULL_PTR(out_ok, s_tag, "out_ok must not be nullptr");
480
481 dtc_arm_fill(0U);
483 const ra8_err_t arm = ra8_isr_set_dtc(s_dtc_slot, true);
484 if (arm != k_ra8_ok) {
485 return arm;
486 }
488 if (trig != k_ra8_ok) {
489 return trig;
490 }
492
493 for (uint32_t i = 0U; i < (uint32_t)k_dtc_arm_poll_limit; ++i) {
495 break;
496 }
497 }
498
499 *out_ok = dtc_arm_all_match_src();
500 return k_ra8_ok;
501}
502
521[[nodiscard]] static ra8_err_t dtc_arm_run_disarmed(uint8_t* out_ok)
522{
523 RA8_CHECK_NULL_PTR(out_ok, s_tag, "out_ok must not be nullptr");
524
527 const ra8_err_t disarm = ra8_isr_set_dtc(s_dtc_slot, false);
528 if (disarm != k_ra8_ok) {
529 return disarm;
530 }
532 if (trig != k_ra8_ok) {
533 return trig;
534 }
536
537 /* No copy is expected, so there is nothing to poll for; give the (gated)
538 * DTC a bounded settle window, then confirm the destination is untouched.
539 * The volatile read keeps the loop from being optimised away. */
540 for (uint32_t i = 0U; i < (uint32_t)k_dtc_arm_settle; ++i) {
541 if (s_dst[k_dtc_arm_buf_words - 1U] != (uint32_t)k_dtc_arm_dst_sentinel) {
542 break;
543 }
544 }
545
546 *out_ok = dtc_arm_all_equal((uint32_t)k_dtc_arm_dst_sentinel);
547 return k_ra8_ok;
548}
549
550void main(void)
551{
554 /* Completion is detected by polling (armed) or a settle window (disarmed),
555 * so the global interrupt is intentionally left masked -- as in
556 * dtc_transfer_demo, enabling the DTC-complete CPU interrupt lets its ISR
557 * (which writes DTCSTS) race the in-flight transfer on silicon. The IELSR
558 * slot armed by ra8_isr_set_dtc still activates the DTC; we simply do not
559 * take the completion IRQ. */
560
561 while (1) {
562 uint8_t armed_ok = 0U;
563 uint8_t disarmed_ok = 0U;
564 const ra8_err_t e_arm = dtc_arm_run_armed(&armed_ok);
565 const ra8_err_t e_dis = dtc_arm_run_disarmed(&disarmed_ok);
566
567 g_dtc_armed_ok = (e_arm == k_ra8_ok && armed_ok != 0U) ? 1U : 0U;
568 g_dtc_disarmed_ok = (e_dis == k_ra8_ok && disarmed_ok != 0U) ? 1U : 0U;
569
570 /* The DTCE primitive is correct only if arming COPIED and disarming did
571 * NOT -- both must hold. This compound decision is the demo's verdict. */
572 const uint8_t good = (g_dtc_armed_ok != 0U && g_dtc_disarmed_ok != 0U) ? 1U : 0U;
573
574 if (good != 0U) {
577 } else {
579 (size_t)(sizeof(k_dtc_arm_bad_msg) - 1U));
581 }
584 }
585}
void main(void)
Secure fallback main entry point.
Definition main.c:37
static void dtc_arm_program_ti(void)
Write the 16-byte TI block describing the block copy.
Definition main.c:356
volatile uint32_t g_dtc_isr_count
Count of DTC-complete callbacks fanned through the HAL dispatch.
Definition main.c:231
dtc_arm_vt_geom_t
DTC vector-table geometry.
Definition main.c:162
@ k_dtc_arm_vt_entries
One pointer per IELSR slot 0..95.
Definition main.c:163
@ k_dtc_arm_ti_align
TI start address multiple of 16.
Definition main.c:165
@ k_dtc_arm_vt_align
DTCVBR 1 KB alignment (HUM 18.2.11).
Definition main.c:164
static void dtc_arm_setup_or_halt(void)
Bring CGC + SysTick + ISR + ELC + SCI8 + LEDs + MSTP up.
Definition main.c:287
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
dtc_arm_event_t
ELC software event 0 -> ICU event number.
Definition main.c:99
@ k_dtc_arm_event_swevt0
ELC software event 0 (HUM Table 19.3).
Definition main.c:100
volatile uint32_t g_dtc_heartbeat
Bumps once per main-loop pass – liveness for headless probes.
Definition main.c:239
dtc_arm_cra_t
CRA=0x0000 encodes a full 256-unit block.
Definition main.c:169
@ k_dtc_arm_cra_block_units
Units per block when CRAH/CRAL = 0.
Definition main.c:170
static uint8_t dtc_arm_all_match_src(void)
Verify s_dst matches s_src element-by-element.
Definition main.c:425
static void dtc_arm_fill(uint32_t dst_init)
Fill s_src with a deterministic pattern and s_dst with a value.
Definition main.c:332
static uint32_t s_src[k_dtc_arm_buf_words]
Source / destination buffers (32-bit aligned by element type).
Definition main.c:181
dtc_arm_count_t
DTC count-register values for one 256-word block.
Definition main.c:147
@ k_dtc_arm_cra_block_256
CRAH = CRAL = 0 => 256-unit block.
Definition main.c:148
@ k_dtc_arm_crb_one_block
CRB = 1 => one block per pass.
Definition main.c:149
dtc_arm_config_t
Compile-time settings.
Definition main.c:73
@ k_dtc_arm_poll_limit
Bounded wait for the block to land.
Definition main.c:78
@ k_dtc_arm_buf_bytes
Bytes copied per armed pass.
Definition main.c:76
@ k_dtc_arm_baud
SCI8 baud rate.
Definition main.c:74
@ k_dtc_arm_buf_words
32-bit words per buffer / block.
Definition main.c:77
@ k_dtc_arm_period_ms
Delay between passes.
Definition main.c:75
@ k_dtc_arm_settle
Bounded settle for the disarmed pass.
Definition main.c:79
@ k_dtc_arm_dst_sentinel
Disarmed-phase destination fill.
Definition main.c:80
static uint16_t s_dtc_slot
IELSR slot allocated for the DTC activation = DTC vector number.
Definition main.c:199
static uint8_t dtc_arm_all_equal(uint32_t expect)
Verify every word of s_dst still holds expect.
Definition main.c:449
static ra8_err_t dtc_arm_run_disarmed(uint8_t *out_ok)
Run one DISARMED pass: DTCE = 0, fire the event, expect NO copy.
Definition main.c:521
volatile uint32_t g_dtc_armed_ok
1 when the armed pass copied the block correctly.
Definition main.c:207
dtc_arm_mr_field_t
DTC Transfer-Information mode-bit field values.
Definition main.c:116
@ k_dtc_arm_md_block
MRA.MD[7:6] = 10b: block transfer mode.
Definition main.c:117
@ k_dtc_arm_dm_inc
MRB.DM[3:2] = 10b: increment DAR.
Definition main.c:120
@ k_dtc_arm_sz_word
MRA.SZ[5:4] = 10b: 32-bit word units.
Definition main.c:118
@ k_dtc_arm_sm_inc
MRA.SM[3:2] = 10b: increment SAR.
Definition main.c:119
dtc_arm_byte_t
Single-byte constants.
Definition main.c:84
@ k_dtc_arm_isr_prio
NVIC priority for the DTC-complete slot.
Definition main.c:86
@ k_dtc_arm_byte_sh
Source-pattern shift (i ^ (i >> 8)).
Definition main.c:85
static ra8_err_t dtc_arm_run_armed(uint8_t *out_ok)
Run one ARMED pass: DTCE = 1, fire the event, expect a full copy.
Definition main.c:477
dtc_arm_mr_pos_t
Bit positions inside the DTC TI MR word.
Definition main.c:130
@ k_dtc_arm_mra_byte_pos
MRA byte offset within MR.
Definition main.c:135
@ k_dtc_arm_mra_md_pos
MRA.MD field position.
Definition main.c:131
@ k_dtc_arm_mrb_byte_pos
MRB byte offset within MR.
Definition main.c:136
@ k_dtc_arm_mrb_dm_pos
MRB.DM field position.
Definition main.c:134
@ k_dtc_arm_mra_sm_pos
MRA.SM field position.
Definition main.c:133
@ k_dtc_arm_mra_sz_pos
MRA.SZ field position.
Definition main.c:132
static void dtc_arm_complete_cb(void *ctx, uint16_t status)
DTC completion callback (fanned out by ra8_dtc_dispatch).
Definition main.c:259
static void dtc_arm_panic_halt(void)
Park forever after a fatal init failure.
Definition main.c:242
static void dtc_arm_bringup_or_halt(void)
Initialise the DTC, allocate its activation slot, and enable it.
Definition main.c:385
volatile uint32_t g_dtc_disarmed_ok
1 when the disarmed pass left the destination untouched.
Definition main.c:215
static void dtc_arm_swevt_isr(void *ctx)
IELSR-slot ISR for the DTC-complete interrupt.
Definition main.c:280
static const uint8_t k_dtc_arm_ok_msg[]
Output line tags.
Definition main.c:177
dtc_arm_swevt_t
ELSEGRn index fired by ra8_elc_software_trigger.
Definition main.c:104
@ k_dtc_arm_swevt_index
ELSEGR0 -> ELC_SWEVT0 (0x0CC).
Definition main.c:105
volatile uint32_t g_dtc_activations
Count of ELC software-event triggers issued (armed + disarmed).
Definition main.c:223
static uint32_t s_dst[k_dtc_arm_buf_words]
Definition main.c:182
static const uint8_t k_dtc_arm_bad_msg[]
Definition main.c:178
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.
Boot entry points shared between a vector table and its startup code.
High-level Clock Generation Circuit driver.
ra8_err_t ra8_cgc_get_clock_hz(ra8_clock_id_t id, uint32_t *out_hz)
Query the current frequency of a clock-tree domain.
Definition ra8_cgc.c:132
@ k_ra8_clock_id_cpuclk0
Cortex-M85 CPUCLK0.
Definition ra8_cgc.h:70
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_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
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_set_dtc(uint16_t slot, bool enable)
Enable or disable DTC activation on a registered IELSR slot.
Definition ra8_isr.c:415
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
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
SysTick-based tick counter, delay and timestamp helpers.
ra8_err_t ra8_time_init(uint32_t cpu_hz)
Initialise SysTick for a 1 kHz tick interrupt.
Definition ra8_time.c:59
void ra8_delay_ms(uint32_t ms)
Busy-wait for at least ms milliseconds.
Definition ra8_time.c:129
One 16-byte Transfer Information (TI) block referenced by the DTC vector table.