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
62
63#include <stddef.h>
64#include <stdint.h>
65
66#include "ra8_board_ek_ra8d2.h"
67#include "ra8_boot_entry.h"
68#include "ra8_cgc.h"
69#include "ra8_elc_regs.h"
70#include "ra8_err.h"
71#include "ra8_isr.h"
72#include "ra8_lpm.h"
73#include "ra8_lpm_regs.h"
74#include "ra8_time.h"
75#include "ra8_ulpt.h"
76#include "ra8_ulpt_regs.h"
77
94typedef enum : uint32_t {
95 k_lpi_baud = 115200U,
96 /* ULPTLCLK = LOCO / 1 = 32.768 kHz; 0x4000 (16384) ticks ~= 0.5 s. A
97 * sub-second period keeps the bench heartbeat prompt without spinning
98 * the console. */
100 /* Bounded spin (NASA P10 Rule 2) waiting for ULPTCR.TCSTF to confirm
101 * the count actually started before we drop into standby. */
103 /* Number of wake-work-standby periods before the app reports PASS and
104 * parks. Bounds the outer loop (NASA P10 Rule 2). */
107
120typedef enum : uint8_t {
122} lpi_chan_t;
123
136typedef enum : uint8_t {
138} lpi_led_t;
139
141static const uint8_t k_lpi_boot_msg[] = "lpm_periodic_idle: boot\r\n";
142
144static const uint8_t k_lpi_work_msg[] = "lpm_periodic_idle: work\r\n";
145
147static const uint8_t k_lpi_pass_msg[] = "lpm_periodic_idle PASS\r\n";
148
164volatile uint32_t g_lpm_periodic_wake_count = 0U;
165
179[[noreturn]] static void lpi_panic_halt(void)
180{
181 while (1) {
182 __asm__ volatile("wfi");
183 }
184}
185
205static void lpi_ulpt_isr(void* ctx)
206{
207 (void)ctx;
209}
210
236[[nodiscard]] static ra8_err_t lpi_wait_count_started(uint8_t channel)
237{
238 const uint8_t tcstf_mask = (uint8_t)(1U << (uint8_t)k_ra8_ulpt_bit_tcstf);
239 for (uint32_t i = 0U; i < (uint32_t)k_lpi_tcstf_poll_limit; ++i) {
240 uint8_t status = 0U;
241 ra8_err_t err = ra8_ulpt_get_status(channel, &status);
242 if (err != k_ra8_ok) {
243 return err;
244 }
245 if ((status & tcstf_mask) != 0U) {
246 return k_ra8_ok;
247 }
248 }
250}
251
272static void lpi_setup_or_halt(void)
273{
274 uint32_t cpuclk0_hz = 0U;
275 if (ra8_cgc_init() != k_ra8_ok) {
277 }
280 }
281 if (ra8_time_init(cpuclk0_hz) != k_ra8_ok) {
283 }
286 }
289 }
290 if (ra8_ulpt_init() != k_ra8_ok) {
292 }
293 const ra8_lpm_config_t lpm_cfg = {
294 .io_port_keep = false,
295 .opa_bus_keep = true,
296 .sscr_fast_return = false,
297 .dcdc_softstart = k_ra8_lpm_dcssmode_128us,
298 .sscr_low_power = k_ra8_lpm_ss2lp_default,
299 };
300 if (ra8_lpm_init(&lpm_cfg) != k_ra8_ok) {
302 }
303 /* Keep LOCO running (LCSTP = 0) so ULPTLCLK survives Software Standby:
304 * HUM Table 11.3 footnote *2 (p 433). */
307 }
308}
309
337[[nodiscard]] static ra8_err_t lpi_arm_wake(void)
338{
339 ra8_err_t err = ra8_isr_init();
340 if (err != k_ra8_ok) {
341 return err;
342 }
345 nullptr,
346 (uint8_t)k_ra8_isr_prio_default,
347 nullptr);
348 if (err != k_ra8_ok) {
349 return err;
350 }
352}
353
373[[nodiscard]] static ra8_err_t lpi_do_work(void)
374{
376 if (err != k_ra8_ok) {
377 return err;
378 }
379 return ra8_board_uart_console_write(k_lpi_work_msg, (size_t)(sizeof(k_lpi_work_msg) - 1U));
380}
381
407[[nodiscard]] static ra8_err_t lpi_idle_one_period(void)
408{
409 ra8_err_t err = ra8_ulpt_start((uint8_t)k_lpi_channel, (uint32_t)k_lpi_period_ticks);
410 if (err != k_ra8_ok) {
411 return err;
412 }
414 if (err != k_ra8_ok) {
415 return err;
416 }
418 if (err != k_ra8_ok) {
419 return err;
420 }
421 return ra8_ulpt_stop((uint8_t)k_lpi_channel);
422}
423
424void main(void)
425{
427
428 if (lpi_arm_wake() != k_ra8_ok) {
430 }
432
433 if (ra8_board_uart_console_write(k_lpi_boot_msg, (size_t)(sizeof(k_lpi_boot_msg) - 1U)) !=
434 k_ra8_ok) {
436 }
437
438 /* Bounded periodic loop (NASA P10 Rule 2): k_lpi_period_count periods
439 * of work-then-standby, each woken by the ULPT0 underflow. */
440 for (uint32_t period = 0U; period < (uint32_t)k_lpi_period_count; ++period) {
441 if (lpi_do_work() != k_ra8_ok) {
443 }
444 if (lpi_idle_one_period() != k_ra8_ok) {
446 }
447 }
448
449 if (ra8_board_uart_console_write(k_lpi_pass_msg, (size_t)(sizeof(k_lpi_pass_msg) - 1U)) !=
450 k_ra8_ok) {
452 }
453
455}
void main(void)
Secure fallback main entry point.
Definition main.c:37
static ra8_err_t lpi_wait_count_started(uint8_t channel)
Spin until the ULPT count operation has actually started.
Definition main.c:236
static void lpi_panic_halt(void)
Park the CPU forever on an unrecoverable bring-up failure.
Definition main.c:179
lpi_const_t
Demo tunables for the periodic-idle loop.
Definition main.c:94
@ k_lpi_tcstf_poll_limit
Lpi tcstf poll limit.
Definition main.c:102
@ k_lpi_period_ticks
Lpi period ticks.
Definition main.c:99
@ k_lpi_baud
SCI8 console baud rate.
Definition main.c:95
@ k_lpi_period_count
Lpi period count.
Definition main.c:105
static void lpi_ulpt_isr(void *ctx)
ULPT0 underflow interrupt service routine.
Definition main.c:205
static ra8_err_t lpi_idle_one_period(void)
Arm ULPT0, drop to Software Standby, and clean up after wake.
Definition main.c:407
static ra8_err_t lpi_arm_wake(void)
Wire the ULPT0 underflow as a Software-Standby wake source.
Definition main.c:337
lpi_led_t
Heartbeat LED selector.
Definition main.c:136
@ k_lpi_led
Blue user LED heartbeat.
Definition main.c:137
static const uint8_t k_lpi_pass_msg[]
Completion banner – emitted once after the last period.
Definition main.c:147
volatile uint32_t g_lpm_periodic_wake_count
Liveness counter – bumped in the ULPT0 underflow ISR.
Definition main.c:164
lpi_chan_t
ULPT channel selector for this demo.
Definition main.c:120
@ k_lpi_channel
ULPT0 (its underflow is the wake source).
Definition main.c:121
static const uint8_t k_lpi_boot_msg[]
Boot banner – emitted once before the first work step.
Definition main.c:141
static const uint8_t k_lpi_work_msg[]
Per-period work banner – one per active period.
Definition main.c:144
static void lpi_setup_or_halt(void)
Bring CGC + SysTick + SCI8 + LED + ULPT + LPM block up.
Definition main.c:272
static ra8_err_t lpi_do_work(void)
Do one period's unit of work: heartbeat LED + console banner.
Definition main.c:373
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).
ra8_board_led_id_t
Identifiers for the three user LEDs on EK-RA8D2 v1.
@ 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
Event Link Controller (ELC) register layout for the Renesas RA8D2.
@ k_ra8_elc_event_ulpt0_ulpti
ULPT0 underflow (counter reaches 0).
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
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.
@ k_ra8_isr_prio_default
Middle priority.
Definition ra8_isr.h:107
ra8_err_t ra8_isr_init(void)
Initialise the ra8_isr table.
Definition ra8_isr.c:229
void ra8_isr_globals_enable(void)
Globally enable maskable interrupts (PRIMASK = 0).
Definition ra8_isr.c:439
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
Low Power Mode (LPM) HAL driver – public API.
ra8_err_t ra8_lpm_init(const ra8_lpm_config_t *cfg)
Initialise the LPM block from a config descriptor.
Definition ra8_lpm.c:358
@ k_ra8_lpm_clock_loco
Low-Speed On-Chip Oscillator.
Definition ra8_lpm.h:155
ra8_err_t ra8_lpm_enter_sleep(ra8_sleep_mode_t mode)
Programme LPSCR for mode and enter the requested sleep.
Definition ra8_lpm.c:735
ra8_err_t ra8_lpm_arm_wupen1_bits(uint32_t bits)
OR-in additional WUPEN1 bits without disturbing other sources.
Definition ra8_lpm.c:481
ra8_err_t ra8_lpm_set_clock_stop(ra8_lpm_clock_t clock, bool stop)
Set or clear the per-oscillator stop bit before sleep entry.
Definition ra8_lpm.c:661
Low Power Mode (LPM) register layout for the Renesas RA8D2.
@ k_ra8_lpm_ss2lp_default
SS2LP_0 – default mode.
@ k_ra8_sleep_mode_software_std
Software Standby (LPMD=0x5).
@ k_ra8_lpm_dcssmode_128us
128 us soft-start (cold-reset default).
@ k_ra8_lpm_wupen1_ulpt0u
ULP0UWUPEN @ bit 8.
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
Ultra-Low-Power Timer (ULPT) driver header.
ra8_err_t ra8_ulpt_get_status(uint8_t channel, uint8_t *out_mask)
Read ULPTCR status bits.
Definition ra8_ulpt.c:249
ra8_err_t ra8_ulpt_stop(uint8_t channel)
Stop a ULPT channel and confirm the counter has halted.
Definition ra8_ulpt.c:121
ra8_err_t ra8_ulpt_init(void)
Reset both ULPT channels to their power-on state.
Definition ra8_ulpt.c:64
ra8_err_t ra8_ulpt_start(uint8_t channel, uint32_t period)
Start a ULPT channel counting down from period.
Definition ra8_ulpt.c:93
Ultra-Low-Power Timer (ULPT) register layout for the Renesas RA8D2.
@ k_ra8_ulpt_bit_tcstf
Count-status flag (read-only).
Configuration descriptor for ra8_lpm_init.
Definition ra8_lpm.h:96