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

Reset cause introspection + software reset trigger. More...

#include <stdint.h>
#include "ra8_err.h"
#include "ra8_reset_regs.h"
Include dependency graph for ra8_reset.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ra8_reset_raw_t
 Raw register snapshot returned by ra8_reset_get_raw. More...

Enumerations

enum  ra8_reset_cause_t : uint8_t {
  k_ra8_reset_cause_unknown = 0U ,
  k_ra8_reset_cause_power_on = 1U ,
  k_ra8_reset_cause_lvd0 = 2U ,
  k_ra8_reset_cause_lvd1 = 3U ,
  k_ra8_reset_cause_lvd2 = 4U ,
  k_ra8_reset_cause_lvd4 = 5U ,
  k_ra8_reset_cause_lvd5 = 6U ,
  k_ra8_reset_cause_deep_sw_standby = 7U ,
  k_ra8_reset_cause_core_voltage = 8U ,
  k_ra8_reset_cause_overcurrent = 9U ,
  k_ra8_reset_cause_temperature = 10U ,
  k_ra8_reset_cause_iwdt = 11U ,
  k_ra8_reset_cause_wdt0 = 12U ,
  k_ra8_reset_cause_software = 13U ,
  k_ra8_reset_cause_lockup0 = 14U ,
  k_ra8_reset_cause_local_memory0 = 15U ,
  k_ra8_reset_cause_bus_peripheral_mpu = 16U ,
  k_ra8_reset_cause_common_memory = 17U ,
  k_ra8_reset_cause_wdt1 = 18U ,
  k_ra8_reset_cause_lockup1 = 19U ,
  k_ra8_reset_cause_local_memory1 = 20U ,
  k_ra8_reset_cause_network = 21U ,
  k_ra8_reset_cause_warm_start = 22U
}
 Decoded reset-cause taxonomy. More...
enum  ra8_reset_source_t : uint8_t {
  k_ra8_reset_source_iwdt = 0U ,
  k_ra8_reset_source_wdt0 = 1U ,
  k_ra8_reset_source_sw = 2U ,
  k_ra8_reset_source_clu0 = 3U ,
  k_ra8_reset_source_lm0 = 4U ,
  k_ra8_reset_source_cm = 5U ,
  k_ra8_reset_source_bus = 6U ,
  k_ra8_reset_source_wdt1 = 7U ,
  k_ra8_reset_source_clu1 = 8U ,
  k_ra8_reset_source_lm1 = 9U ,
  k_ra8_reset_source_pvd1 = 10U ,
  k_ra8_reset_source_pvd2 = 11U ,
  k_ra8_reset_source_count = 12U
}
 Reset sources whose occurrence can be individually disabled. More...

Functions

ra8_err_t ra8_reset_init (void)
 Snapshot the reset cause at boot.
void ra8_reset_test_only_reset_state (void)
 Reset the cached reset-cause snapshot for host tests.
ra8_err_t ra8_reset_get_cause (ra8_reset_cause_t *out)
 Decode the latched RSTSRn flags into a single primary cause.
ra8_err_t ra8_reset_get_raw (ra8_reset_raw_t *out)
 Read the raw RSTSR0 / RSTSR1 / RSTSR2 / RSTSR3 register words.
ra8_err_t ra8_reset_clear_cause (uint32_t mask)
 Clear (write 0 to) the requested set of latched RSTSRn flags.
ra8_err_t ra8_reset_get_attribution (uint32_t *out)
 Read the RSTSAR (Reset Security Attribution) register.
void ra8_reset_software_reset (void)
 Trigger a software-initiated system reset.
ra8_err_t ra8_reset_set_source_mask (ra8_reset_source_t source, bool disable)
 Enable or disable the occurrence of a specific reset source.
ra8_err_t ra8_reset_get_source_mask (ra8_reset_source_t source, bool *disabled)
 Read whether a specific reset source is currently masked (disabled).

Detailed Description

Reset cause introspection + software reset trigger.

Tag
[Ring 3 / HAL] {World: S}

RA8D2 reset HAL driver. The chip exposes 21 distinct reset causes (HUM Ch 6.1 p 244 Table 6.1) and three "Reset Status Registers" (RSTSR0, RSTSR1, RSTSR2) plus an extended RSTSR3 for the core-voltage / overcurrent / temperature monitor flags. This driver collapses every cause into a small set of tagged enums that the application can switch on without having to know which physical register or bit owns which cause.

Driver surface (minimum-viable)

API Purpose
ra8_reset_init Snapshot reset cause at boot
ra8_reset_get_cause Decode RSTSR0/1/2/3 -> typed cause
ra8_reset_get_raw Return the raw 8/32-bit register words
ra8_reset_clear_cause Software-clear (write 0 after read 1)
ra8_reset_get_attribution Read RSTSAR security attribution
ra8_reset_software_reset Trigger AIRCR.SYSRESETREQ (no return)
ra8_reset_set_source_mask Disable/enable a reset source (SYRSTMSK0/1/2)
ra8_reset_get_source_mask Read a reset source's mask state

Not yet implemented (deferred TODO)

  • TEMPRCR / TEMPRLR temperature reset control. The register definitions live in ra8_reset_regs.h (HUM Ch 6.2.9 / 6.2.10 p 264-265) but the write-side bring-up is deferred: TEMPRLR accepts only two writes total before requiring a real reset, so the enable sequence is call-once-at-boot and belongs in the secure-boot / temperature-sensor path, not in the general reset HAL.
  • Hot-pluggable per-cause callbacks (ra8_reset_attach_handler). Reset causes fire before the firmware runs, so the only "callback" is whatever code consumes ra8_reset_get_cause during init. Adding a publish/subscribe layer with no consumer would be speculative; deferred until a caller needs it.
  • VBATT_POR. The HUM lists VBATT_POR as a separate (non-system) reset whose flag lives in the VBAT block, not in SYSC. The existing ra8_bkup driver owns that path.

Locking

Per HUM Ch 6.2.2 / 6.2.3 / 6.2.4 / 6.2.5 register descriptions, the RSTSRn registers are R/W with the Note: "Only 0 can be written. To clear a flag, read 1 from it and then write 0." They do not sit behind PRCR. RSTSAR sits behind PRCR.PRC1 (CGC + LVD group); the driver does not touch RSTSAR write-side – only read-side – so no PRCR unlock is required for ra8_reset_get_attribution.

Definition in file ra8_reset.h.

Enumeration Type Documentation

◆ ra8_reset_cause_t

enum ra8_reset_cause_t : uint8_t

Decoded reset-cause taxonomy.

Values are non-overlapping so the driver can return exactly one primary cause; callers that want to inspect all latched flags (multiple resets can stack between two software reads) should use ra8_reset_get_raw.

Ordering follows HUM Ch 6.1 Table 6.1 p 244. The first matching flag (in register-index order RSTSR2 -> RSTSR0 -> RSTSR3 -> RSTSR1) wins; k_ra8_reset_cause_unknown is returned when no flag is set (e.g. the firmware itself cleared every cause earlier in boot).

Enumerator
k_ra8_reset_cause_unknown 

No flag latched.

k_ra8_reset_cause_power_on 

RSTSR0.PORF.

k_ra8_reset_cause_lvd0 

RSTSR0.LVD0RF.

k_ra8_reset_cause_lvd1 

RSTSR0.LVD1RF.

k_ra8_reset_cause_lvd2 

RSTSR0.LVD2RF.

k_ra8_reset_cause_lvd4 

RSTSR0.LVD4RF.

k_ra8_reset_cause_lvd5 

RSTSR0.LVD5RF.

k_ra8_reset_cause_deep_sw_standby 

RSTSR0.DPSRSTF.

k_ra8_reset_cause_core_voltage 

RSTSR3.CVMRF.

k_ra8_reset_cause_overcurrent 

RSTSR3.OCPRF.

k_ra8_reset_cause_temperature 

RSTSR3.TEMPRF.

k_ra8_reset_cause_iwdt 

RSTSR1.IWDTRF.

k_ra8_reset_cause_wdt0 

RSTSR1.WDTRF.

k_ra8_reset_cause_software 

RSTSR1.SWRF.

k_ra8_reset_cause_lockup0 

RSTSR1.CLURF.

k_ra8_reset_cause_local_memory0 

RSTSR1.LM0RF.

k_ra8_reset_cause_bus_peripheral_mpu 

RSTSR1.BUSSRF.

k_ra8_reset_cause_common_memory 

RSTSR1.CMRF.

k_ra8_reset_cause_wdt1 

RSTSR1.WDT1RF.

k_ra8_reset_cause_lockup1 

RSTSR1.CLU1RF.

k_ra8_reset_cause_local_memory1 

RSTSR1.LM1RF.

k_ra8_reset_cause_network 

RSTSR1.NWRF.

k_ra8_reset_cause_warm_start 

RSTSR2.CWSF == 1.

Definition at line 93 of file ra8_reset.h.

◆ ra8_reset_source_t

enum ra8_reset_source_t : uint8_t

Reset sources whose occurrence can be individually disabled.

Each value maps to one mask bit across SYRSTMSK0/1/2 (HUM Ch 6.2.6-6.2.8 p 262-264). Setting a source's mask disables the corresponding reset; clearing it re-enables the reset (the reset-value of every mask is 0 = enabled). k_ra8_reset_source_count is a non-source sentinel used for range validation, never a maskable bit.

Invariant
0 <= source < k_ra8_reset_source_count for every API call.
Enumerator
k_ra8_reset_source_iwdt 

Independent watchdog reset (SYRSTMSK0).

k_ra8_reset_source_wdt0 

CPU0 watchdog reset (SYRSTMSK0).

k_ra8_reset_source_sw 

Software reset (SYRSTMSK0).

k_ra8_reset_source_clu0 

CPU0 lockup reset (SYRSTMSK0).

k_ra8_reset_source_lm0 

Local-memory-0 error reset (SYRSTMSK0).

k_ra8_reset_source_cm 

Common-memory error reset (SYRSTMSK0).

k_ra8_reset_source_bus 

Bus error reset (SYRSTMSK0).

k_ra8_reset_source_wdt1 

CPU1 watchdog reset (SYRSTMSK1).

k_ra8_reset_source_clu1 

CPU1 lockup reset (SYRSTMSK1).

k_ra8_reset_source_lm1 

Local-memory-1 error reset (SYRSTMSK1).

k_ra8_reset_source_pvd1 

Voltage-monitor-1 reset (SYRSTMSK2).

k_ra8_reset_source_pvd2 

Voltage-monitor-2 reset (SYRSTMSK2).

k_ra8_reset_source_count 

Sentinel: number of maskable sources.

Definition at line 391 of file ra8_reset.h.

Function Documentation

◆ ra8_reset_clear_cause()

ra8_err_t ra8_reset_clear_cause ( uint32_t mask)
nodiscard

Clear (write 0 to) the requested set of latched RSTSRn flags.

Per HUM Ch 6.2.2 / 6.2.3 / 6.2.4 register descriptions, every RSTSRn flag uses the "read 1 then write 0" idiom: software clears a bit by writing 0 after observing it as 1. This function performs the write step for every bit selected by mask across all three RSTSR registers.

The mask argument is encoded as follows so a single call can clear flags from RSTSR0 (bits 0..7), RSTSR1 (bits 8..30) and RSTSR2/RSTSR3 (bits 31..) without forcing the caller to issue three separate calls:

  • bits 0..7 – RSTSR0 mask (PORF, LVDxRF, DPSRSTF).
  • bits 8..30 – RSTSR1 mask shifted left by 8.
  • bit 31 – RSTSR2.CWSF (write-1-to-set per HUM Ch 6.2.4 Note 2 p 261).

RSTSR3 has no software-clear path – its flags are owned by the core-voltage / temperature monitor secure code; this function leaves RSTSR3 alone.

Parameters
[in]maskEncoded clear mask (see above).
Returns
ra8_err_t error code.
Return values
k_ra8_okMask applied.
Precondition
None.
Caller has already inspected the cause via ra8_reset_get_cause if the cause needs to survive the clear.
Postcondition
Every flag selected by mask reads 0 (after a 2-PCLKB settling window per HUM Ch 6.2.2 p 258 Note).
Other RSTSRn bits are untouched.
Note
Thread safety: not thread-safe.
Warning
After this call ra8_reset_get_cause will reflect the remaining (unclearned) flags or k_ra8_reset_cause_unknown.
See also
ra8_reset_init Snapshot the cause before calling clear.
Since
0.1.0

Definition at line 350 of file ra8_reset.c.

References internal_decode(), internal_read_raw(), k_ra8_ok, k_ra8_reset_mask_rstsr0_msk, k_ra8_reset_mask_rstsr1_shift, k_ra8_reset_mask_rstsr1_window, k_ra8_reset_mask_rstsr2_cwsf, k_ra8_reset_rstsr2_cwsf_msk, ra8_reset_rstsr0(), ra8_reset_rstsr1(), ra8_reset_rstsr2(), and s_state.

Referenced by main().

◆ ra8_reset_get_attribution()

ra8_err_t ra8_reset_get_attribution ( uint32_t * out)
nodiscard

Read the RSTSAR (Reset Security Attribution) register.

RSTSAR at SYSC offset 0x3C4 holds five NONSECn bits that select whether each of the five reset-status group registers (RSTSR0..RSTSR3 + future) is reachable from the non-secure side. The driver returns the raw 32-bit value; callers can mask against k_ra8_reset_rstsar_field_msk to drop reserved upper bits.

Parameters
[out]outReceives the RSTSAR value (non-NULL).
Returns
ra8_err_t error code.
Return values
k_ra8_okValue written.
k_ra8_err_null_ptrout was nullptr.
Precondition
out != nullptr.
Caller is on the secure side or RSTSAR has already been made non-secure-readable.
Postcondition
*out holds the RSTSAR snapshot.
No hardware state is modified.
Note
Thread safety: read-only.
Since
0.1.0

Definition at line 386 of file ra8_reset.c.

References k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_reset_rstsar(), and s_tag.

◆ ra8_reset_get_cause()

ra8_err_t ra8_reset_get_cause ( ra8_reset_cause_t * out)
nodiscard

Decode the latched RSTSRn flags into a single primary cause.

If ra8_reset_init was called this returns the cached snapshot; otherwise it reads the registers fresh. The returned value is the highest-priority cause currently latched. Priority order matches HUM Ch 6.1 Table 6.1 p 244 (POR -> LVD -> Deep SW Standby -> core/temp/overcurrent -> IWDT/WDT/SW/Lockup/LM/BUS/CM -> Cold/Warm).

To examine every latched flag at once (multiple causes can stack between two reads), use ra8_reset_get_raw instead.

Parameters
[out]outDecoded cause (non-NULL).
Returns
ra8_err_t error code.
Return values
k_ra8_okCause written to *out.
k_ra8_err_null_ptrout was nullptr.
Precondition
out != nullptr.
The host or target has the SYSC block mapped (always true on RA8D2 and via ra8_fake_mmap in host tests).
Postcondition
*out holds the decoded cause.
No hardware state is modified.
Note
Thread safety: read-only; safe to call from any context.
See also
ra8_reset_get_raw
ra8_reset_clear_cause
Since
0.1.0

Definition at line 326 of file ra8_reset.c.

References internal_decode(), internal_read_raw(), k_ra8_ok, RA8_CHECK_NULL_PTR, s_state, and s_tag.

Referenced by internal_wakeup_reason(), and main().

◆ ra8_reset_get_raw()

ra8_err_t ra8_reset_get_raw ( ra8_reset_raw_t * out)
nodiscard

Read the raw RSTSR0 / RSTSR1 / RSTSR2 / RSTSR3 register words.

If ra8_reset_init has run this returns the cached snapshot; otherwise the registers are read fresh.

Parameters
[out]outDestination struct (non-NULL).
Returns
ra8_err_t error code.
Return values
k_ra8_okRaw values written.
k_ra8_err_null_ptrout was nullptr.
Precondition
out != nullptr.
The reset block is mapped (true on target and host-test).
Postcondition
*out populated with the latest snapshot.
No hardware state is modified.
Note
Thread safety: read-only.
Since
0.1.0

Definition at line 339 of file ra8_reset.c.

References internal_read_raw(), k_ra8_ok, RA8_CHECK_NULL_PTR, s_state, and s_tag.

◆ ra8_reset_get_source_mask()

ra8_err_t ra8_reset_get_source_mask ( ra8_reset_source_t source,
bool * disabled )
nodiscard

Read whether a specific reset source is currently masked (disabled).

Reads the relevant SYRSTMSK0/1/2 byte and returns the mask state for source. Reads do not require a PRCR unlock.

Parameters
[in]sourceReset source to query (< k_ra8_reset_source_count).
[out]disabledReceives true if the reset is masked/disabled.
Returns
ra8_err_t error code.
Return values
k_ra8_okResult written to *disabled.
k_ra8_err_null_ptrdisabled was nullptr.
k_ra8_err_invalid_argsource >= k_ra8_reset_source_count.
Precondition
disabled != nullptr.
source is a valid ra8_reset_source_t (< count).
Postcondition
*disabled holds the current mask state.
No hardware state is modified.
Note
Thread safety: read-only; safe from any context.
See also
ra8_reset_set_source_mask
Since
0.1.0

Definition at line 537 of file ra8_reset.c.

References internal_source_loc(), k_ra8_err_invalid_arg, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_log_error, and s_tag.

◆ ra8_reset_init()

ra8_err_t ra8_reset_init ( void )
nodiscard

Snapshot the reset cause at boot.

Reads RSTSR0/1/2/3 once and caches the decoded cause + raw words in a file-scope static. Subsequent calls to ra8_reset_get_cause / ra8_reset_get_raw return the snapshot rather than re-reading the registers. This is the only safe way to share the cause across the firmware – any other code path that calls ra8_reset_clear_cause would otherwise destroy the information before later modules could see it.

Idempotent: calling ra8_reset_init more than once re-reads the registers and overwrites the snapshot, which is what you want during unit tests but you should avoid in production code.

Returns
ra8_err_t error code.
Return values
k_ra8_okSnapshot captured.
Precondition
None – can be called as the very first init step.
PRCR does not need to be unlocked for RSTSRn reads.
Postcondition
ra8_reset_get_cause will return the cached value.
ra8_reset_get_raw will return the cached raw register snapshot.
Note
Thread safety: not thread-safe; intended for single-threaded boot context.
See also
ra8_reset_get_cause
ra8_reset_get_raw
Since
0.1.0

Definition at line 310 of file ra8_reset.c.

References internal_decode(), internal_read_raw(), k_ra8_ok, ra8_log_info_val, s_state, and s_tag.

Referenced by internal_wdt_demo_setup_or_halt(), main(), and wdt_rr_setup_or_halt().

◆ ra8_reset_set_source_mask()

ra8_err_t ra8_reset_set_source_mask ( ra8_reset_source_t source,
bool disable )
nodiscard

Enable or disable the occurrence of a specific reset source.

Sets (disable == true) or clears (disable == false) the mask bit for source in SYRSTMSK0/1/2. The register group is write-protected by PRCR.PRC5 (HUM Ch 6.2.6 Note p 262): this function unlocks PRC5, performs the read-modify-write of the relevant SYRSTMSKn byte, then relocks PRC5 – leaving the other PRC bits untouched.

Parameters
[in]sourceReset source to mask/unmask (< k_ra8_reset_source_count).
[in]disabletrue disables the reset; false re-enables it.
Returns
ra8_err_t error code.
Return values
k_ra8_okMask bit updated.
k_ra8_err_invalid_argsource >= k_ra8_reset_source_count.
Precondition
source is a valid ra8_reset_source_t (< count).
Caller is on the secure side (the SYSC reset-control group is secure-attributed by default).
Postcondition
The SYRSTMSKn mask bit for source reads disable.
PRCR.PRC5 is left re-locked (write-protected) on return.
Note
Thread safety: not thread-safe; serialize SYSC PRCR-gated writes.
Warning
Per HUM Ch 6.2.6 p 263, IWDTMASK cannot be rewritten while the independent watchdog is running and WDT0MASK cannot be rewritten while the CPU0 watchdog is running – the hardware silently ignores such writes. Mask those sources before starting their watchdogs.
See also
ra8_reset_get_source_mask
Since
0.1.0

Definition at line 505 of file ra8_reset.c.

References internal_source_loc(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_reset_prcr_key, k_ra8_reset_prcr_pr_bits_msk, k_ra8_reset_prcr_prc5_msk, ra8_log_error, ra8_reset_prcr(), and s_tag.

◆ ra8_reset_software_reset()

void ra8_reset_software_reset ( void )

Trigger a software-initiated system reset.

Writes the Cortex-M85 SCB->AIRCR register with the mandatory 0x05FA write-key in the upper half-word and the SYSRESETREQ bit set, exactly as CMSIS NVIC_SystemReset does. The reset does not return – on real hardware control is given to the reset exception handler within a few cycles. The function ends with a __DSB (or its off-target equivalent) so the AIRCR write is observable before the CPU stalls waiting for reset.

After the reset completes RSTSR1.SWRF will read 1 and ra8_reset_get_cause will return k_ra8_reset_cause_software.

Precondition
None.
Caller has flushed any data that must survive the reset to non-volatile storage (MRAM, BKUP regs).
Postcondition
On target: control transferred to the reset vector.
On host: *ra8_reset_aircr() & SYSRESETREQ_msk reads 1.
Note
Thread safety: not thread-safe; should be the last code that runs on the CPU before the reset.
Warning
This call does not return on target – treat it as equivalent to [[noreturn]] for control-flow analysis. The function is not declared [[noreturn]] because host unit tests need to observe the AIRCR write and then continue executing; on the host build the function does return after writing AIRCR. Use it only as the last statement of a function on target firmware.
Pending DMA, USB, and watchdog state are wiped. Make sure you have already disabled any external bus controller that might continue driving lines after the CPU resets.
See also
HUM Ch 6.1 Table 6.1 p 244 ("Software reset / Source / Register setting (use the software reset bit AIRCR.SYSRESETREQ)")
Since
0.1.0

Definition at line 394 of file ra8_reset.c.

References k_ra8_reset_aircr_sysresetreq_msk, k_ra8_reset_aircr_vectkey_pos, k_ra8_reset_aircr_vectkey_value, ra8_hw_wait_for_reset(), ra8_log_info, ra8_reset_aircr(), and s_tag.

Referenced by main().

◆ ra8_reset_test_only_reset_state()

void ra8_reset_test_only_reset_state ( void )

Reset the cached reset-cause snapshot for host tests.

Zeroes the cached boot-cause snapshot so each host test case starts from the driver's just-loaded state. Compiled unconditionally (like the other *_test_* helpers) but only ever called from tests/; on the target it is an unreferenced symbol dropped by --gc-sections.

Note
Host-test only; not part of the target firmware API.
Precondition
The driver is otherwise idle (single-threaded test context).
No caller depends on the current cached snapshot.
Postcondition
ra8_reset_get_cause re-reads the registers on the next call.
The cached cause is k_ra8_reset_cause_unknown.
Since
0.1.0

Definition at line 319 of file ra8_reset.c.

References k_ra8_reset_cause_unknown, and s_state.