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

Battery Backup Function (VBATT) driver – core lifecycle and storage. More...

#include "ra8_bkup.h"
#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_bkup_internal.h"
#include "ra8_bkup_regs.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_log.h"
#include "ra8_register_protection.h"
Include dependency graph for ra8_bkup.c:

Go to the source code of this file.

Enumerations

enum  ra8_bkup_internal_t : uint16_t {
  k_ra8_bkup_max_vdet_level ,
  k_ra8_bkup_no_switch_lvl_raw ,
  k_ra8_bkup_status_clear_keep_mask ,
  k_ra8_bkup_vbae_settle_iters
}
 Local numeric constants – avoid magic numbers per CLAUDE.md. More...

Functions

static ra8_err_t internal_validate_cfg (const ra8_bkup_config_t *cfg)
 Validate a ra8_bkup_config_t against HUM constraints.
void priv_ra8_bkup_internal_rmw8 (volatile uint8_t *reg, uint8_t mask, bool enable, uint16_t unlock_val)
 Set or clear a bit in an 8-bit PRCR-protected RMW register.
static void internal_vbae_access_settle (void)
 Busy-wait the HUM-mandated VBTBKRn access settle after arming VBAE.
ra8_err_t ra8_bkup_init (const ra8_bkup_config_t *cfg)
 Configure the battery-backup block from cfg.
ra8_err_t ra8_bkup_deinit (void)
 Disable the battery-backup switch and close the VBTBKRn window.
ra8_err_t ra8_bkup_cold_start_init (ra8_bkup_vdet_level_t level, uint32_t timeout_iters)
 Drive the cold-start flow from HUM Ch 12.3.7.1 p 517.
ra8_err_t ra8_bkup_warm_start_check (bool *needs_reinit, uint32_t timeout_iters)
 Warm-start sanity check (HUM Ch 12.3.7.2 p 517).
ra8_err_t ra8_bkup_no_switch_init (uint32_t timeout_iters)
 "Power-supply switch unused" init flow (HUM Ch 12.3.7.3 p 518).
ra8_err_t ra8_bkup_get_status (ra8_bkup_status_t *out)
 Read VBTBPSR + VBTADSR and decode into out.
ra8_err_t ra8_bkup_clear_status (uint8_t mask)
 Clear latched VBPORF and tamper flags selected by mask.
ra8_err_t ra8_bkup_read_word (uint8_t word_index, uint32_t *out)
 Read one 32-bit word from the VBTBKRn array.
ra8_err_t ra8_bkup_write_word (uint8_t word_index, uint32_t value)
 Write one 32-bit word into the VBTBKRn array.
ra8_err_t ra8_bkup_read_byte (uint16_t index, uint8_t *out)
 Read one 8-bit byte from the VBTBKRn array.
ra8_err_t ra8_bkup_write_byte (uint16_t index, uint8_t value)
 Write one 8-bit byte into the VBTBKRn array.
ra8_err_t ra8_bkup_zero_all (void)
 Bulk-zeroise the entire 128-byte backup-register array.
ra8_err_t ra8_bkup_set_voltage_monitor (bool enable)
 Enable / disable the VBATT/6 analog tap to ADC16H.
ra8_err_t ra8_bkup_get_voltage_monitor_enabled (bool *enabled_out)
 Read the live VBATTMNSELR.VBTMNSEL bit.
ra8_err_t ra8_bkup_attach_handler (ra8_bkup_event_fn_t fn, void *ctx)
 Attach the shared low-battery / tamper event callback.
ra8_err_t ra8_bkup_isr_handle (void)
 ISR entry point that fires the registered callback.
void ra8_bkup_dispatch (uint8_t tamper_flags)
 Fire the registered callback (called from the ISR shim).

Variables

const char * g_bkup_tag = "BKUP"
 Log tag used for this driver's diagnostics.
static ra8_bkup_event_fn_t s_bkup_fn
 Currently attached low-battery / tamper callback or nullptr.
static void * s_bkup_ctx
 Opaque pointer forwarded to the s_bkup_fn callback.
bool s_bkup_initialized
 true once any of the lifecycle init helpers have run.

Detailed Description

Battery Backup Function (VBATT) driver – core lifecycle and storage.

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

Driver for the RA8D2 battery-backup block (HUM Ch 12 p 498-519). Mirrors the API laid out in ra8_bkup.h. Every register access carries a HUM Ch 12 citation; the BAT* / VBT* registers physically live inside the SYSC peripheral window so the offsets match ra8_bkup_regs.h.

This translation unit owns the concerns that every user of the block needs: the power-supply lifecycle (init / deinit / cold-start / warm-start / no-switch), the status registers, the VBTBKRn backup store, the VBATT analog voltage monitor, and the interrupt path. Two further concerns live beside it because the whole driver did not fit under the per-file line cap, and both are self-contained:

The handful of symbols those TUs share with this one are declared in ra8_bkup_internal.h.

The block has no MSTPCR bit – it is permanently powered as long as VBATT or VCC is supplied (HUM Ch 12.1 p 498 – "the battery-powered area is powered by the main power supply"). So we skip the usual ra8_mstp_enable step that other drivers run in their init.

PRCR write protection (issue #131)
Every register this driver writes is listed in HUM Ch 13.1 Table 13.1 "Association between PRCR bits and use of registers to be protected" p 520-521, split across three protection groups:
  • PRC1 – VBTBER, VBTICTLR, VBTICTLR2, VBTBKRn (n = 0 to 127), VBTBPCR1, VBTBPCR2, VBTBPSR, VBTADSR, VBTADCR1, VBTADCR2, VBTADCR3, VBTNCWCR. That is the whole backup + tamper register file.
  • PRC3 – VBATTMNSELR (grouped with the PVD registers).
  • PRC4 – BBFSAR, VBRSABAR, VBRPABARS, VBRPABARNS (the security/privilege attribution registers).

A write issued while the owning group is locked is silently discarded: no bus fault, no status flag, and the register simply reads back its old value. Until this was fixed the driver issued every write with PRCR locked, so on real silicon VBTBKRn stayed all-zero and bkup_survival_demo reported rw=BAD while the emulator – which modelled no protection – reported rw=ok. Bench-confirmed by J-Link: writing VBTBKR0 with PRCR locked reads back 0x00000000; after PRCR = 0xA502 the same write reads back intact.

Reads are never protected, so only the write paths take an unlock window. Each window is opened for a whole run of consecutive writes rather than per register, which matches the HUM's usage model and keeps the relock on every exit path (RA8_PROTECTED_WRITE relocks from its loop-increment clause, including on an early return).

Definition in file ra8_bkup.c.

Enumeration Type Documentation

◆ ra8_bkup_internal_t

enum ra8_bkup_internal_t : uint16_t

Local numeric constants – avoid magic numbers per CLAUDE.md.

Enumerator
k_ra8_bkup_max_vdet_level 

Highest legal VDETLVL encoding.

k_ra8_bkup_no_switch_lvl_raw 

110b sentinel for VDETLVL "initial value" (HUM 12.3.7.3).

k_ra8_bkup_status_clear_keep_mask 

W0C base for VBPORF.

k_ra8_bkup_vbae_settle_iters 

NOP-spin count: >= 500 ns at 1 GHz M85 (HUM Ch 12.2.6 p 504).

Definition at line 126 of file ra8_bkup.c.

Function Documentation

◆ internal_validate_cfg()

ra8_err_t internal_validate_cfg ( const ra8_bkup_config_t * cfg)
static

Validate a ra8_bkup_config_t against HUM constraints.

Parameters
[in]cfgAlready null-checked configuration descriptor.
Returns
k_ra8_ok if every field is in range, else k_ra8_err_invalid_arg.
Precondition
cfg != nullptr.
cfg->vdet_level represents a valid VBTBPCR2.VDETLVL encoding.
Postcondition
No side effects.

See the matching header declaration for the full contract; this site adds no behaviour beyond what the public API documents.

Return values
k_ra8_okSuccess path.
k_ra8_err_invalid_argCaller violated a precondition.
Note
Thread safety: see the header declaration.
Since
0.1.0
Postcondition
Side effects bounded to documented state.

Definition at line 164 of file ra8_bkup.c.

References k_ra8_bkup_max_vdet_level, k_ra8_err_invalid_arg, k_ra8_ok, RA8_INTERNAL, and ra8_bkup_config_t::vdet_level.

Referenced by ra8_bkup_init().

◆ internal_vbae_access_settle()

void internal_vbae_access_settle ( void )
static

Busy-wait the HUM-mandated VBTBKRn access settle after arming VBAE.

HUM Ch 12.2.6 p 504 ("VBTBER : VBATT Backup Enable Register") requires two things before the VBATT backup registers may be touched: "You must write 1 to VBAE before accessing VBTBKR" and "To access VBTBKR, wait for at least 500 ns after writing 1 to VBAE, and then access VBTBKR". The VBAE write is done by the caller; this helper burns the 500 ns floor so the first VBTBKRn access after ra8_bkup_init is valid on silicon. The HAL exposes no timed primitive, so a bounded NOP spin calibrated for the 1 GHz Cortex-M85 (~k_ra8_bkup_vbae_settle_iters cycles) provides the floor; a slower core only lengthens the wait, which is safe. The spin runs once per arm() so the cost is negligible. The loop counter is volatile and the body is a documented nop so neither the target nor the host optimiser can elide the delay (mirrors ra8_usb_phy.c).

Precondition
Caller has just written 1 to VBTBER.VBAE.
Caller is in single-threaded init context (the spin blocks the CPU).
Postcondition
At least 500 ns has elapsed since the VBAE write (at <= 1 GHz).
No register or global state is mutated.
Note
Not thread-safe; calibrated for the 1 GHz Cortex-M85 core clock.
Since
0.1.0

Definition at line 210 of file ra8_bkup.c.

References k_ra8_bkup_vbae_settle_iters, and RA8_INTERNAL.

Referenced by ra8_bkup_init().

◆ priv_ra8_bkup_internal_rmw8()

void priv_ra8_bkup_internal_rmw8 ( volatile uint8_t * reg,
uint8_t mask,
bool enable,
uint16_t unlock_val )

Set or clear a bit in an 8-bit PRCR-protected RMW register.

The read half needs no unlock (PRCR gates writes only, HUM Ch 13.1 p 520), so only the store runs inside the protection window. The caller supplies the window because this driver spans three groups: PRC1 for the VBT* file and PRC3 for VBATTMNSELR.

Shared by both register-touching TUs of the driver: ra8_bkup.c uses it for the status W0C paths and the voltage-monitor select, and ra8_bkup_tamper.c uses it for the per-channel input enable.

Parameters
[in,out]regPointer to the live 8-bit register.
[in]maskBit mask to manipulate.
[in]enabletrue to set, false to clear.
[in]unlock_valk_ra8_prcr_unlock_* for reg's group.
Precondition
reg != nullptr.
mask != 0.
unlock_val names the PRCR group that owns reg (HUM Table 13.1).
Postcondition
Bits in mask reflect enable; other bits unchanged.
PRCR is relocked.
Warning
The store is only durable inside the unlock window: a write issued while reg's PRCR group is locked is discarded silently, with no bus fault and no status flag (issue #131). Do not separate the write from its unlock.
Note
Thread safety: not thread-safe; caller must serialise.
Since
0.1.0

Definition at line 172 of file ra8_bkup.c.

References RA8_PROTECTED_WRITE.

Referenced by ra8_bkup_clear_status(), ra8_bkup_isr_handle(), ra8_bkup_set_input_enable(), and ra8_bkup_set_voltage_monitor().

◆ ra8_bkup_attach_handler()

ra8_err_t ra8_bkup_attach_handler ( ra8_bkup_event_fn_t fn,
void * ctx )
nodiscard

Attach the shared low-battery / tamper event callback.

The battery-backup block exposes its tamper / low-battery events through ICU IELSR slots that map onto VBTADSR.VBTADF[2:0]. The driver provides a single callback slot; the ISR is expected to call ra8_bkup_dispatch with the live VBTADSR mask.

Parameters
[in]fnCallback function (may be nullptr to detach).
[in]ctxOpaque pointer forwarded to the callback.
Returns
ra8_err_t error code.
Return values
k_ra8_okHandler stored.
Precondition
Driver initialized.
Caller-managed lifetime for ctx.
Postcondition
Subsequent ra8_bkup_dispatch invokes fn.
Passing nullptr for fn makes dispatch a no-op.
Note
Thread safety: callback storage is plain pointer assignment, not atomic.
Since
0.1.0

Definition at line 580 of file ra8_bkup.c.

References k_ra8_ok, s_bkup_ctx, and s_bkup_fn.

◆ ra8_bkup_clear_status()

ra8_err_t ra8_bkup_clear_status ( uint8_t mask)
nodiscard

Clear latched VBPORF and tamper flags selected by mask.

VBPORF is W0C (write-0-to-clear) per HUM Ch 12.2.13 p 509; the driver does the inverted-mask write so callers can pass the same bit mask they observed via ra8_bkup_get_status.

Parameters
[in]maskOR of k_ra8_bkup_vbtbpsr_mask_vbporf and k_ra8_bkup_vbtadsr_mask_* values.
Returns
ra8_err_t error code.
Return values
k_ra8_okAlways succeeds (bits not set in mask left alone).
Precondition
Driver initialized.
IRQs masked or single-threaded context.
Postcondition
VBPORF cleared if requested.
Bits of VBTADSR present in mask cleared.
Note
Not thread-safe.
Since
0.1.0

Definition at line 448 of file ra8_bkup.c.

References k_ra8_bkup_vbtadsr_mask_all, k_ra8_bkup_vbtbpsr_mask_vbporf, k_ra8_ok, k_ra8_prcr_unlock_lpm, priv_ra8_bkup_internal_rmw8(), ra8_bkup_vbtadsr(), and ra8_bkup_vbtbpsr().

◆ ra8_bkup_cold_start_init()

ra8_err_t ra8_bkup_cold_start_init ( ra8_bkup_vdet_level_t level,
uint32_t timeout_iters )
nodiscard

Drive the cold-start flow from HUM Ch 12.3.7.1 p 517.

Implements the seven HUM-documented steps for first-time power-up of both VCC and VBATT:

  1. Wait for VBPORM to read 1 (VBATT_R above VPORBATT).
  2. Clear VBPORF.
  3. Program VDETLVL.
  4. Caller must wait tDETWT externally (see timeout_iters).
  5. Set VDETE.
  6. Sub-clock + RTC bring-up is the caller's job (out of scope here).
  7. Returns success once the switch is armed.

The wait in step 1 is bounded by timeout_iters polling cycles to avoid livelock on broken hardware – callers should pass a value that comfortably exceeds the spec'd VBATT_R rise time.

Parameters
[in]levelVDETBATT level to programme.
[in]timeout_itersMaximum poll iterations waiting for VBPORM.
Returns
ra8_err_t error code.
Return values
k_ra8_okSwitch armed.
k_ra8_err_invalid_arglevel out of range.
k_ra8_err_hw_timeoutVBPORM stayed 0 for the whole poll loop.
Precondition
PRCR unlocked, IRQs masked.
timeout_iters > 0.
Postcondition
VBTBPCR2.VDETE == 1.
VBPORF cleared, VDETLVL == level.
Note
Caller still needs to wait tDETWT between this call and any use of the switch; the wait is intentionally external so the HAL stays clock-agnostic.
See also
ra8_bkup_warm_start_check
ra8_bkup_no_switch_init
Since
0.1.0

Definition at line 291 of file ra8_bkup.c.

References g_bkup_tag, k_ra8_bkup_max_vdet_level, k_ra8_bkup_status_clear_keep_mask, k_ra8_bkup_vbtbpcr2_mask_lvl, k_ra8_bkup_vbtbpcr2_mask_vdete, k_ra8_bkup_vbtbpsr_mask_vbporm, k_ra8_err_hw_timeout, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_prcr_unlock_lpm, ra8_bkup_vbtbpcr1(), ra8_bkup_vbtbpcr2(), ra8_bkup_vbtbpsr(), ra8_log_info, RA8_PROTECTED_WRITE, and s_bkup_initialized.

◆ ra8_bkup_deinit()

ra8_err_t ra8_bkup_deinit ( void )
nodiscard

Disable the battery-backup switch and close the VBTBKRn window.

Clears VBAE so VBTBKRn data is preserved across VCC loss (per HUM Ch 12.2.6 p 504 the bit must be 0 before VBATT cutover) and stops the battery power-supply switch by setting BPWSWSTP. Leaves the latched VBPORF / tamper flags alone – use ra8_bkup_clear_status to also wipe them.

Returns
ra8_err_t error code.
Return values
k_ra8_okAlways succeeds.
Precondition
Driver previously initialized via ra8_bkup_init.
IRQs masked or single-threaded shutdown context.
Postcondition
VBTBER.VBAE == 0.
VBTBPCR1.BPWSWSTP == 1.
Note
Not thread-safe.
See also
ra8_bkup_init
Since
0.1.0

Definition at line 273 of file ra8_bkup.c.

References g_bkup_tag, k_ra8_bkup_vbtbpcr1_mask_bpwswstp, k_ra8_ok, k_ra8_prcr_unlock_lpm, ra8_bkup_vbtber(), ra8_bkup_vbtbpcr1(), ra8_log_info, RA8_PROTECTED_WRITE, and s_bkup_initialized.

◆ ra8_bkup_dispatch()

void ra8_bkup_dispatch ( uint8_t tamper_flags)

Fire the registered callback (called from the ISR shim).

Parameters
[in]tamper_flagsSnapshot of VBTADSR observed in the ISR.
Precondition
Driver initialized.
Caller has read VBTADSR before clearing flags.
Postcondition
Callback executed if attached.
No state change in this driver.
Note
Thread safety: not re-entrant; call from one ISR context only.
Since
0.1.0

See the matching header declaration for the full contract; this site adds no behaviour beyond what the public API documents.

Definition at line 613 of file ra8_bkup.c.

References s_bkup_ctx, and s_bkup_fn.

Referenced by ra8_bkup_isr_handle().

◆ ra8_bkup_get_status()

ra8_err_t ra8_bkup_get_status ( ra8_bkup_status_t * out)
nodiscard

Read VBTBPSR + VBTADSR and decode into out.

Parameters
[out]outNon-NULL status descriptor.
Returns
ra8_err_t error code.
Return values
k_ra8_okout populated.
k_ra8_err_null_ptrout == nullptr.
Precondition
Driver initialized.
out points to writable storage.
Postcondition
out->source reflects current BPWSWM bit.
out->raw_vbtbpsr matches the live register read.
Note
Thread safety: read-only, safe to call concurrently with writes provided the register is naturally aligned (it is).
See also
ra8_bkup_clear_status
Since
0.1.0

Definition at line 427 of file ra8_bkup.c.

References g_bkup_tag, k_ra8_bkup_source_vbatt, k_ra8_bkup_source_vcc, k_ra8_bkup_vbtadsr_mask_all, k_ra8_bkup_vbtbpsr_mask_swm, k_ra8_bkup_vbtbpsr_mask_vbporf, k_ra8_bkup_vbtbpsr_mask_vbporm, k_ra8_ok, ra8_bkup_status_t::por_detected, ra8_bkup_vbtadsr(), ra8_bkup_vbtbpsr(), RA8_CHECK_NULL_PTR, ra8_bkup_status_t::raw_vbtbpsr, ra8_bkup_status_t::source, ra8_bkup_status_t::tamper_flags, and ra8_bkup_status_t::vbatt_r_ok.

◆ ra8_bkup_get_voltage_monitor_enabled()

ra8_err_t ra8_bkup_get_voltage_monitor_enabled ( bool * enabled_out)
nodiscard

Read the live VBATTMNSELR.VBTMNSEL bit.

Parameters
[out]enabled_outSet to true when the analog tap is on.
Returns
ra8_err_t error code.
Return values
k_ra8_okStatus decoded.
k_ra8_err_null_ptrenabled_out == nullptr.
Precondition
enabled_out writable.
Postcondition
*enabled_out matches the register bit.
Since
0.1.0

Definition at line 567 of file ra8_bkup.c.

References g_bkup_tag, k_ra8_bkup_vbattmnselr_mask_vbtmnsel, k_ra8_ok, ra8_bkup_vbattmnselr(), and RA8_CHECK_NULL_PTR.

◆ ra8_bkup_init()

ra8_err_t ra8_bkup_init ( const ra8_bkup_config_t * cfg)
nodiscard

Configure the battery-backup block from cfg.

Sequence (HUM Ch 12.2.11 p 507 + Ch 12.2.6 p 504):

  1. If cfg->enable_switch, clear BPWSWSTP and program VBTBPCR2.VDETLVL, then set VDETE so the VCC drop detector arms.
  2. If cfg->enable_backup, write 1 to VBTBER.VBAE to open the VBTBKRn access window, then busy-wait the HUM-mandated >= 500 ns settle (HUM Ch 12.2.6 p 504: "You must write 1 to VBAE before accessing VBTBKR" ... "wait for at least 500 ns after writing 1 to VBAE, and then access VBTBKR"). VBAE resets to 1, but the HUM procedure requires the explicit write + settle. To retain VBTBKRn across a real VBATT cutover the app must later write VBAE back to 0 via ra8_bkup_deinit. Note: VBAE is only one precondition – the battery-backup block is also inoperative unless voltage monitor 0 (LVD0) reset is enabled via the OFS1.PVDAS option byte (HUM Ch 12.1.3 p 499, Ch 12.3.2 p 514), which is a boot-time option setting outside this driver's scope.
  3. Clear any latched VBPORF and tamper flags so the first call to ra8_bkup_get_status starts from a known state.

The driver does not unlock PRCR – the caller (typically board init) is expected to handle the SYSC protection key for the few BAT* registers that require it.

State Machine
Driver-state transitions enforced by this entry point:
Parameters
[in]cfgNon-NULL configuration descriptor.
Returns
ra8_err_t error code.
Return values
k_ra8_okHardware armed; backup window open.
k_ra8_err_null_ptrcfg == nullptr.
k_ra8_err_invalid_argcfg->vdet_level is one of the two "setting prohibited" encodings.
Precondition
PRCR group 0 is unlocked (caller's responsibility).
IRQs masked or single-threaded init context.
Postcondition
BPWSWSTP and VBAE reflect cfg.
When cfg->enable_backup, the VBTBKRn window is armed and the >= 500 ns settle has elapsed, so the next VBTBKRn access is valid.
VBTADSR == 0 and VBPORF == 0.
Note
Not thread-safe.
See also
ra8_bkup_deinit
ra8_bkup_cold_start_init
Since
0.1.0

Definition at line 222 of file ra8_bkup.c.

References ra8_bkup_config_t::enable_backup, ra8_bkup_config_t::enable_switch, g_bkup_tag, internal_validate_cfg(), internal_vbae_access_settle(), k_ra8_bkup_status_clear_keep_mask, k_ra8_bkup_vbtber_mask_vbae, k_ra8_bkup_vbtbpcr1_mask_bpwswstp, k_ra8_bkup_vbtbpcr2_mask_lvl, k_ra8_bkup_vbtbpcr2_mask_vdete, k_ra8_ok, k_ra8_prcr_unlock_lpm, ra8_bkup_vbtadsr(), ra8_bkup_vbtber(), ra8_bkup_vbtbpcr1(), ra8_bkup_vbtbpcr2(), ra8_bkup_vbtbpsr(), RA8_CHECK_NULL_PTR, ra8_log_info, RA8_PROTECTED_WRITE, RA8_RETURN_ON_ERROR, s_bkup_initialized, and ra8_bkup_config_t::vdet_level.

Referenced by internal_bkup_demo_setup_or_halt().

◆ ra8_bkup_isr_handle()

ra8_err_t ra8_bkup_isr_handle ( void )
nodiscard

ISR entry point that fires the registered callback.

Reads VBTADSR, masks against VBTADCR1.VBTADIE[2:0] (only IRQ-armed channels generate the VBATTADI interrupt per HUM Ch 12.4 Table 12.2 p 518), W0Cs the flags it dispatched on, then invokes the registered callback with the mask of fired channels.

Returns
ra8_err_t error code.
Return values
k_ra8_okDispatched (or no-op if no flag set).
k_ra8_err_not_initializedDriver not initialized.
Precondition
ISR caller, IRQs masked at this point.
Postcondition
Flagged-and-armed VBTADFn bits are W0Ced.
Callback invoked exactly once with the dispatched mask.
Since
0.1.0

Definition at line 587 of file ra8_bkup.c.

References k_ra8_bkup_vbtadcr1_mask_ie_all, k_ra8_bkup_vbtadsr_mask_all, k_ra8_err_not_initialized, k_ra8_ok, k_ra8_prcr_unlock_lpm, priv_ra8_bkup_internal_rmw8(), ra8_bkup_dispatch(), ra8_bkup_vbtadcr1(), ra8_bkup_vbtadsr(), and s_bkup_initialized.

◆ ra8_bkup_no_switch_init()

ra8_err_t ra8_bkup_no_switch_init ( uint32_t timeout_iters)
nodiscard

"Power-supply switch unused" init flow (HUM Ch 12.3.7.3 p 518).

Used when VCC and VBATT are externally tied together. Sets BPWSWSTP, waits for VBPORM to drop, clears VDETE, restores VDETLVL to the prohibited 110b sentinel (HUM-documented "initial" value), W0Cs VBPORF, and zeroes VBTICTLR / VBTICTLR2 / VBTADSR / VBTADCR1 / VBTADCR2 / VBTBKRn. Sub-clock and RTC bring-up are out of scope for the HAL.

Parameters
[in]timeout_itersMax polls waiting for VBPORM == 0.
Returns
ra8_err_t error code.
Return values
k_ra8_okAll registers reset, switch stopped.
k_ra8_err_hw_timeoutVBPORM never dropped.
Precondition
PRCR unlocked, IRQs masked.
timeout_iters > 0.
Postcondition
VBTBPCR1.BPWSWSTP == 1.
VBTBPCR2.VDETE == 0 and VDETLVL == 110b.
VBTICTLR / VBTICTLR2 / VBTADSR / VBTADCR1 / VBTADCR2 == 0.
See also
ra8_bkup_cold_start_init
Since
0.1.0

Definition at line 367 of file ra8_bkup.c.

References g_bkup_tag, k_ra8_bkup_no_switch_lvl_raw, k_ra8_bkup_status_clear_keep_mask, k_ra8_bkup_vbtbpcr1_mask_bpwswstp, k_ra8_bkup_vbtbpsr_mask_vbporm, k_ra8_err_hw_timeout, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_prcr_unlock_lpm, ra8_bkup_vbtadcr1(), ra8_bkup_vbtadcr2(), ra8_bkup_vbtadsr(), ra8_bkup_vbtbpcr1(), ra8_bkup_vbtbpcr2(), ra8_bkup_vbtbpsr(), ra8_bkup_vbtictlr(), ra8_bkup_vbtictlr2(), ra8_log_info, RA8_PROTECTED_WRITE, and s_bkup_initialized.

◆ ra8_bkup_read_byte()

ra8_err_t ra8_bkup_read_byte ( uint16_t index,
uint8_t * out )
nodiscard

Read one 8-bit byte from the VBTBKRn array.

Parameters
[in]indexBackup-register index in 0..127.
[out]outNon-NULL receiver.
Returns
ra8_err_t error code.
Return values
k_ra8_okByte read.
k_ra8_err_null_ptrout == nullptr.
k_ra8_err_invalid_argindex >= 128.
Precondition
Driver initialized with cfg->enable_backup == true.
out writable.
Postcondition
*out matches the live byte.
See also
ra8_bkup_write_byte
Since
0.1.0

Definition at line 504 of file ra8_bkup.c.

References g_bkup_tag, k_ra8_bkup_reg_count, k_ra8_err_invalid_arg, k_ra8_ok, ra8_bkup_vbtbkr(), and RA8_CHECK_NULL_PTR.

◆ ra8_bkup_read_word()

ra8_err_t ra8_bkup_read_word ( uint8_t word_index,
uint32_t * out )
nodiscard

Read one 32-bit word from the VBTBKRn array.

Parameters
[in]word_indexWord index in 0..31 (32 words = 128 bytes).
[out]outNon-NULL receiver for the word value.
Returns
ra8_err_t error code.
Return values
k_ra8_okWord read into *out.
k_ra8_err_null_ptrout == nullptr.
k_ra8_err_invalid_argword_index >= 32.
Precondition
Driver initialized with cfg->enable_backup == true.
out points to writable storage.
Postcondition
*out matches the live 32-bit register value.
Note
Thread safety: read-only.
See also
ra8_bkup_write_word
Since
0.1.0

Definition at line 474 of file ra8_bkup.c.

References g_bkup_tag, k_ra8_bkup_word_count, k_ra8_err_invalid_arg, k_ra8_ok, ra8_bkup_vbtbkr_word(), and RA8_CHECK_NULL_PTR.

Referenced by internal_bkup_demo_rw_check(), and internal_bkup_demo_survival_check().

◆ ra8_bkup_set_voltage_monitor()

ra8_err_t ra8_bkup_set_voltage_monitor ( bool enable)
nodiscard

Enable / disable the VBATT/6 analog tap to ADC16H.

HUM Ch 12.2.5 p 503 + Ch 12.3.6 p 517: set VBTMNSEL = 1 to route VBATT/6 to ANVBAT (ADC channel input). The HUM mandates a tMONWT settling delay before the ADC reading is valid; the wait is the caller's responsibility because the HAL has no delay primitive. Recommend clearing again as soon as the conversion completes because VBTMNSEL = 1 increases VBATT current draw.

Parameters
[in]enabletrue -> enable monitor; false -> disable.
Returns
ra8_err_t error code.
Return values
k_ra8_okAlways succeeds.
Precondition
PRCR unlocked.
Postcondition
VBATTMNSELR.VBTMNSEL == enable.
See also
ra8_bkup_get_voltage_monitor_enabled
Since
0.1.0

Definition at line 555 of file ra8_bkup.c.

References k_ra8_bkup_vbattmnselr_mask_vbtmnsel, k_ra8_ok, k_ra8_prcr_unlock_pvd, priv_ra8_bkup_internal_rmw8(), and ra8_bkup_vbattmnselr().

◆ ra8_bkup_warm_start_check()

ra8_err_t ra8_bkup_warm_start_check ( bool * needs_reinit,
uint32_t timeout_iters )
nodiscard

Warm-start sanity check (HUM Ch 12.3.7.2 p 517).

After a VBATT->VCC transition the firmware must:

  1. Wait for VBPORM == 1.
  2. Inspect VBPORF: if set, the VBATT_R rail dropped below VPORBATT and the entire backup area must be reinitialized by calling ra8_bkup_cold_start_init. If clear, the backup area state survived and no further action is required.
Parameters
[out]needs_reinitSet to true when VBPORF was latched and the caller must run cold-start init.
[in]timeout_itersMax polls waiting for VBPORM.
Returns
ra8_err_t error code.
Return values
k_ra8_okStatus decoded into *needs_reinit.
k_ra8_err_null_ptrneeds_reinit == nullptr.
k_ra8_err_hw_timeoutVBPORM stayed 0.
Precondition
PRCR unlocked.
timeout_iters > 0.
Postcondition
*needs_reinit reflects VBPORF.
VBPORF is left untouched (caller decides when to W0C it).
Note
Pure status read; safe to call from cold reset path.
See also
ra8_bkup_cold_start_init
Since
0.1.0

Definition at line 341 of file ra8_bkup.c.

References g_bkup_tag, k_ra8_bkup_vbtbpsr_mask_vbporf, k_ra8_bkup_vbtbpsr_mask_vbporm, k_ra8_err_hw_timeout, k_ra8_err_invalid_arg, k_ra8_ok, ra8_bkup_vbtbpsr(), and RA8_CHECK_NULL_PTR.

◆ ra8_bkup_write_byte()

ra8_err_t ra8_bkup_write_byte ( uint16_t index,
uint8_t value )
nodiscard

Write one 8-bit byte into the VBTBKRn array.

Parameters
[in]indexBackup-register index in 0..127.
[in]valueByte to store.
Returns
ra8_err_t error code.
Return values
k_ra8_okByte written.
k_ra8_err_invalid_argindex >= 128.
Precondition
Driver initialized with cfg->enable_backup == true.
Postcondition
VBTBKRn[index] == value.
See also
ra8_bkup_read_byte
Since
0.1.0

Definition at line 517 of file ra8_bkup.c.

References g_bkup_tag, k_ra8_bkup_reg_count, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_prcr_unlock_lpm, ra8_bkup_vbtbkr(), RA8_CHECK_NULL_PTR, and RA8_PROTECTED_WRITE.

◆ ra8_bkup_write_word()

ra8_err_t ra8_bkup_write_word ( uint8_t word_index,
uint32_t value )
nodiscard

Write one 32-bit word into the VBTBKRn array.

Parameters
[in]word_indexWord index in 0..31.
[in]value32-bit value to store.
Returns
ra8_err_t error code.
Return values
k_ra8_okValue written.
k_ra8_err_invalid_argword_index >= 32.
Precondition
Driver initialized with cfg->enable_backup == true.
IRQs masked or single-threaded context.
Postcondition
VBTBKRn[word_index*4 .. word_index*4+3] == value (LE).
Note
Not thread-safe.
See also
ra8_bkup_read_word
Since
0.1.0

Definition at line 487 of file ra8_bkup.c.

References g_bkup_tag, k_ra8_bkup_word_count, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_prcr_unlock_lpm, ra8_bkup_vbtbkr_word(), RA8_CHECK_NULL_PTR, and RA8_PROTECTED_WRITE.

Referenced by internal_bkup_demo_rw_check(), and internal_bkup_demo_survival_check().

◆ ra8_bkup_zero_all()

ra8_err_t ra8_bkup_zero_all ( void )
nodiscard

Bulk-zeroise the entire 128-byte backup-register array.

Software equivalent of the tamper-detection backup-clear path. Useful when an application detects a logical tamper that does not trip an RTCICn pin.

Returns
ra8_err_t error code.
Return values
k_ra8_okAll 128 VBTBKRn slots zeroed.
Precondition
Driver initialized with cfg->enable_backup == true.
IRQs masked.
Postcondition
Every VBTBKRn[0..127] == 0.
Since
0.1.0

Definition at line 533 of file ra8_bkup.c.

References k_ra8_bkup_reg_count, k_ra8_ok, k_ra8_prcr_unlock_lpm, ra8_bkup_vbtbkr(), and RA8_PROTECTED_WRITE.

Variable Documentation

◆ g_bkup_tag

const char* g_bkup_tag = "BKUP"

Log tag used for this driver's diagnostics.

Log tag every TU of this driver logs under.

Defined once here and shared with the tamper and security TUs through ra8_bkup_internal.h, so the whole driver logs under one identity.

Note
Read-only after definition.
Since
0.1.0

Defined once in ra8_bkup.c. The tamper and security TUs reference it through this declaration rather than each defining their own copy, so the driver has a single logging identity and a single object.

Note
Read-only after definition; never reassigned.
Since
0.1.0

Definition at line 88 of file ra8_bkup.c.

Referenced by internal_validate_security_cfg(), internal_validate_tamper_channels(), ra8_bkup_cold_start_init(), ra8_bkup_deinit(), ra8_bkup_get_status(), ra8_bkup_get_voltage_monitor_enabled(), ra8_bkup_init(), ra8_bkup_no_switch_init(), ra8_bkup_read_byte(), ra8_bkup_read_input(), ra8_bkup_read_word(), ra8_bkup_security_apply(), ra8_bkup_security_get(), ra8_bkup_tamper_init(), ra8_bkup_warm_start_check(), ra8_bkup_write_byte(), and ra8_bkup_write_word().

◆ s_bkup_ctx

void* s_bkup_ctx
static

Opaque pointer forwarded to the s_bkup_fn callback.

Definition at line 103 of file ra8_bkup.c.

Referenced by ra8_bkup_attach_handler(), and ra8_bkup_dispatch().

◆ s_bkup_fn

ra8_bkup_event_fn_t s_bkup_fn
static

Currently attached low-battery / tamper callback or nullptr.

Note
Direct pointer assignment; not atomic. Only mutate from single-threaded init or with IRQs masked.

Definition at line 97 of file ra8_bkup.c.

Referenced by ra8_bkup_attach_handler(), and ra8_bkup_dispatch().

◆ s_bkup_initialized

bool s_bkup_initialized

true once any of the lifecycle init helpers have run.

Defined here and referenced from ra8_bkup_tamper.c through ra8_bkup_internal.h: ra8_bkup_tamper_init is an init entry point in its own right, so it sets the flag too.

Note
Strictly used to gate ra8_bkup_isr_handle with the k_ra8_err_not_initialized return – everything else is state-less so the flag is set generously.
Warning
File-scope state, not thread-safe.
Since
0.1.0

Defined once in ra8_bkup.c and referenced from ra8_bkup_tamper.c through this declaration: ra8_bkup_tamper_init is an init entry point in its own right, so it sets the latch too. Read only by ra8_bkup_isr_handle, which returns k_ra8_err_not_initialized while the latch is clear.

Note
Everything else in the driver is state-less, so the flag is set generously rather than tracking a full lifecycle.
Warning
File-scope state, not thread-safe. Mutate only from single-threaded init or with IRQs masked.
Since
0.1.0

Definition at line 120 of file ra8_bkup.c.

Referenced by ra8_bkup_cold_start_init(), ra8_bkup_deinit(), ra8_bkup_init(), ra8_bkup_isr_handle(), ra8_bkup_no_switch_init(), and ra8_bkup_tamper_init().