ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
main.c File Reference

Deep-Sleep mode (LPMD=0, SCR.SLEEPDEEP=1) one-shot wake demo. More...

#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_board_ek_ra8d2.h"
#include "ra8_boot_entry.h"
#include "ra8_cgc.h"
#include "ra8_err.h"
#include "ra8_isr.h"
#include "ra8_lpm.h"
#include "ra8_lpm_regs.h"
#include "ra8_time.h"
Include dependency graph for main.c:

Go to the source code of this file.

Enumerations

enum  lpm_deep_config_t : uint32_t {
  k_lpm_deep_park_blink_ms = 500U ,
  k_lpm_deep_baud = 115200U
}
 Compile-time tunables for the deep-sleep demo. More...

Functions

static void internal_lpm_deep_panic_halt (void)
 Park forever after a fatal low-power demo failure.
static void internal_lpm_deep_setup_or_halt (void)
 Bring CGC + SysTick + LED1 + SCI8 + LPM up.
void main (void)
 Application entry.

Variables

static const uint8_t s_lpm_deep_msg_boot [] = "lpm_deep: boot\r\n"
 Fixed UART banners emitted before and after the Deep-Sleep cycle.
static const uint8_t s_lpm_deep_msg_woke [] = "lpm_deep: woke\r\n"
volatile uint32_t g_lpm_deep_pre_count = 0U
 Counter bumped right BEFORE the Deep-Sleep entry.
volatile uint32_t g_lpm_deep_wake_count = 0U
 Counter bumped right AFTER waking from Deep-Sleep.

Detailed Description

Deep-Sleep mode (LPMD=0, SCR.SLEEPDEEP=1) one-shot wake demo.

Tag
[Ring 6 / APP] {World: S}

Demonstrates Cortex-M85 Deep Sleep (the second-shallowest LPM state) on the EK-RA8D2. LPSCR.LPMD stays at 0 (System Active) but SCR.SLEEPDEEP is asserted before WFI so the core power-gates more aggressively than plain Sleep. SysTick is the wake source.

Sequence:

  1. CGC + SysTick + LED1 + SCI8 + LPM bring-up.
  2. Emit "lpm_deep: boot\r\n" over SCI8.
  3. Bump g_lpm_deep_pre_count so a JLink probe can confirm the firmware reached the LPM entry.
  4. ra8_lpm_enter_sleep(k_ra8_sleep_mode_deep_sleep) – WFI with SLEEPDEEP=1. SysTick wakes the core ~1 ms later.
  5. Bump g_lpm_deep_wake_count – proves the chip woke from Deep-Sleep cleanly.
  6. Emit "lpm_deep: woke\r\n" over SCI8 – the HIL gate scrapes for this banner.
  7. Park in a normal infinite loop (LED1 toggle every 500 ms). The loop is NOT in LPM, so subsequent bench flashes have a reliable halt window. Re-flashing the demo causes another boot -> Deep-Sleep -> wake -> banner cycle.
SCI wedge note
Earlier prototypes printed UART traffic INSIDE the Deep-Sleep loop (one banner per wake). That output never appeared on the bench – the SCI8 module clock (PCLKA) is gated by the default ra8_lpm_init config (opa_bus_keep=true, io_port_keep=false) when SLEEPDEEP is asserted, so the first post-wake TDR write dropped on the floor and continuous post-wake printing mis-framed subsequent bytes. The "one-shot then park" approach here avoids that: the banner is emitted ONCE after a single Deep-Sleep cycle, while the chip is back in normal active mode, and never again.
Why two memprobe counters?
g_lpm_deep_pre_count increments BEFORE the LPM entry; if a future regression breaks the LPM init the pre-counter still moves but the wake-counter does not, narrowing the failure mode. Both counters are externally readable via SWD.

No external hardware required – bare EK-RA8D2.

Since
0.1.0

Definition in file main.c.

Enumeration Type Documentation

◆ lpm_deep_config_t

enum lpm_deep_config_t : uint32_t

Compile-time tunables for the deep-sleep demo.

Enumerator
k_lpm_deep_park_blink_ms 

Lpm deep park blink ms.

k_lpm_deep_baud 

Lpm deep baud.

Definition at line 67 of file main.c.

Function Documentation

◆ internal_lpm_deep_panic_halt()

void internal_lpm_deep_panic_halt ( void )
static

Park forever after a fatal low-power demo failure.

Repeats wait-for-interrupt without initiating another low-power transition, preserving the wake and setup state for a debugger.

Returns
None.
Precondition
The caller has determined that entering or continuing sleep is unsafe.
Any required UART diagnostic has already been completed.
Postcondition
The function never returns to its caller.
The pre-sleep and wake counters are no longer modified.
Note
Interrupt wakeups return immediately to the permanent loop.
Since
0.1.0

Definition at line 118 of file main.c.

References RA8_INTERNAL.

Referenced by internal_lpm_deep_setup_or_halt(), and main().

◆ internal_lpm_deep_setup_or_halt()

void internal_lpm_deep_setup_or_halt ( void )
static

Bring CGC + SysTick + LED1 + SCI8 + LPM up.

Initializes the clock and time base, board status LED, UART console, and LPM policy required for the single Deep-Sleep transition. Any dependency failure enters the permanent panic halt.

Returns
None.
Precondition
IRQs disabled at entry.
Reset_Handler has copied .data and zeroed .bss.
Postcondition
On success the five sub-systems are armed.
LPSCR.LPMD == 0 (System Active); the first WFI is a plain CPU sleep until ra8_lpm_enter_sleep is called.
Note
Single-shot boot helper; it is not reentrant.
Since
0.1.0

Definition at line 143 of file main.c.

References internal_lpm_deep_panic_halt(), k_lpm_deep_baud, k_ra8_board_led1, k_ra8_clock_id_cpuclk0, k_ra8_lpm_dcssmode_128us, k_ra8_lpm_ss2lp_default, k_ra8_ok, ra8_board_led_init(), ra8_board_uart_console_init(), ra8_cgc_get_clock_hz(), ra8_cgc_init(), RA8_INTERNAL, ra8_lpm_init(), and ra8_time_init().

Referenced by main().

◆ main()

void main ( void )

Application entry.

The application entry point Reset_Handler hands control to.

Performs one Deep-Sleep cycle, emits the wake banner, then parks in a normal blink loop.

MC/DC:
Compound decision: enter_sleep != ok || any_sci_write != ok. Two atomic conditions x N+1 = 3 vectors – both-ok happy path, enter_sleep fails (covered by host test), sci_write fails (covered by host test).
Precondition
Reset_Handler / SystemInit completed normally.
LPM init has not yet been attempted.
Postcondition
On clean entry the chip emitted both banners and is parked in a normal blink loop, ready for the next bench flash.
On any HAL hard error LED1 latches OFF and the chip halts.
Since
0.1.0

Definition at line 192 of file main.c.

References g_lpm_deep_pre_count, g_lpm_deep_wake_count, internal_lpm_deep_panic_halt(), internal_lpm_deep_setup_or_halt(), k_lpm_deep_park_blink_ms, k_ra8_board_led1, k_ra8_ok, k_ra8_sleep_mode_deep_sleep, ra8_board_led_toggle(), ra8_board_uart_console_write(), ra8_delay_ms(), ra8_isr_globals_enable(), ra8_lpm_enter_sleep(), s_lpm_deep_msg_boot, and s_lpm_deep_msg_woke.

Variable Documentation

◆ g_lpm_deep_pre_count

volatile uint32_t g_lpm_deep_pre_count = 0U

Counter bumped right BEFORE the Deep-Sleep entry.

Externally readable via SWD memprobe. Lets future regression-bisects distinguish "LPM init crashed" (this counter stays 0) from "Deep-Sleep entry crashed" (this counter increments once, g_lpm_deep_wake_count stays 0).

Note
Read externally by J-Link only.
Since
0.1.0

Definition at line 88 of file main.c.

Referenced by main().

◆ g_lpm_deep_wake_count

volatile uint32_t g_lpm_deep_wake_count = 0U

Counter bumped right AFTER waking from Deep-Sleep.

Externally readable via SWD memprobe. Non-zero value proves the chip entered Deep-Sleep AND woke cleanly via SysTick.

Note
Read externally by J-Link only.
Since
0.1.0

Definition at line 100 of file main.c.

Referenced by main().

◆ s_lpm_deep_msg_boot

const uint8_t s_lpm_deep_msg_boot[] = "lpm_deep: boot\r\n"
static

Fixed UART banners emitted before and after the Deep-Sleep cycle.

Definition at line 73 of file main.c.

Referenced by main().

◆ s_lpm_deep_msg_woke

const uint8_t s_lpm_deep_msg_woke[] = "lpm_deep: woke\r\n"
static

Definition at line 74 of file main.c.

Referenced by main().