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

Software Watchdog Timer (WDT) driver header. More...

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

Go to the source code of this file.

Data Structures

struct  ra8_wdt_cfg_t
 Register-start-mode configuration block. More...
struct  ra8_wdt_ofs_decoded_t
 Decoded view of an OFSm option-setting word. More...

Typedefs

typedef void(* ra8_wdt_event_fn_t) (void *ctx, uint16_t status_mask)
 WDT NMI / underflow event callback.
typedef ra8_err_t(* ra8_wdt_ofs_reader_fn_t) (uintptr_t ofs_addr, uint32_t *out_word)
 Hook used to fetch one OFSm option-setting word.

Enumerations

enum  ra8_wdt_clock_div_t : uint8_t {
  k_ra8_wdt_clkdiv_4 = 0x1U ,
  k_ra8_wdt_clkdiv_64 = 0x4U ,
  k_ra8_wdt_clkdiv_128 = 0xFU ,
  k_ra8_wdt_clkdiv_512 = 0x6U ,
  k_ra8_wdt_clkdiv_2048 = 0x7U ,
  k_ra8_wdt_clkdiv_8192 = 0x8U
}
 Legal CKS[3:0] encodings for WDTCR. More...
enum  ra8_wdt_timeout_sel_t : uint8_t {
  k_ra8_wdt_timeout_1024 = 0x0U ,
  k_ra8_wdt_timeout_4096 = 0x1U ,
  k_ra8_wdt_timeout_8192 = 0x2U ,
  k_ra8_wdt_timeout_16384 = 0x3U
}
 Legal TOPS[1:0] encodings for WDTCR. More...
enum  ra8_wdt_window_start_t : uint8_t {
  k_ra8_wdt_window_start_25 = 0x0U ,
  k_ra8_wdt_window_start_50 = 0x1U ,
  k_ra8_wdt_window_start_75 = 0x2U ,
  k_ra8_wdt_window_start_100 = 0x3U
}
 Legal RPSS[1:0] encodings (refresh-permitted window start). More...
enum  ra8_wdt_window_end_t : uint8_t {
  k_ra8_wdt_window_end_75 = 0x0U ,
  k_ra8_wdt_window_end_50 = 0x1U ,
  k_ra8_wdt_window_end_25 = 0x2U ,
  k_ra8_wdt_window_end_0 = 0x3U
}
 Legal RPES[1:0] encodings (refresh-permitted window end). More...
enum  ra8_wdt_reset_ctrl_t : uint8_t {
  k_ra8_wdt_on_expiry_nmi = 0U ,
  k_ra8_wdt_on_expiry_reset = 1U
}
 WDTRCR.RSTIRQS encoding – reset vs NMI on expiry. More...
enum  ra8_wdt_stop_ctrl_t : uint8_t {
  k_ra8_wdt_sleep_keep_count = 0U ,
  k_ra8_wdt_sleep_stop_count = 1U
}
 WDTCSTPR.SLCSTP encoding – counter behaviour in Sleep. More...
enum  ra8_wdt_ofs_strt_t : uint8_t {
  k_ra8_wdt_ofs_strt_auto = 0U ,
  k_ra8_wdt_ofs_strt_register = 1U
}
 OFSm.WDTnSTRT encoding – auto vs register start mode. More...
enum  ra8_wdt_status_mask_t : uint16_t {
  k_ra8_wdt_status_none = 0x0000U ,
  k_ra8_wdt_status_underflow = k_ra8_wdt_sr_undff ,
  k_ra8_wdt_status_refresh = k_ra8_wdt_sr_refef
}
 WDTSR top-bit status flags. More...
enum  ra8_wdt_subs_count_t : uint8_t { k_ra8_wdt_max_subs = 6U }
 Maximum number of hot-pluggable subscribers per WDT instance. More...
enum  ra8_wdt_clear_timeout_t : uint32_t { k_ra8_wdt_clear_max_polls = 0x4000UL }
 Bounded retry budget for ra8_wdt_clear_status_blocking. More...

Functions

ra8_err_t ra8_wdt_init (const ra8_wdt_cfg_t *cfg)
 Initialise the WDT in register-start mode.
ra8_err_t ra8_wdt_deinit (void)
 Quiesce the driver into a Sleep-stop posture.
void ra8_wdt_refresh_deferred (void)
 Refresh the software WDT counter (WDT0).
ra8_err_t ra8_wdt_refresh_for (ra8_wdt_instance_t which)
 Refresh a specific WDT instance.
ra8_err_t ra8_wdt_get_status (uint16_t *out_mask)
 Read the WDTSR status flag bits.
ra8_err_t ra8_wdt_clear_status (void)
 Clear the WDTSR underflow / refresh-error flags.
ra8_err_t ra8_wdt_clear_status_blocking (uint16_t mask)
 Clear specific WDTSR flag bits and busy-wait until they read 0.
ra8_err_t ra8_wdt_get_counter (uint16_t *out_count)
 Read the live CNTVAL[13:0] down-counter value.
ra8_err_t ra8_wdt_timeout_cycles_get (ra8_wdt_timeout_sel_t sel, uint16_t *out_cycles)
 Decode a ra8_wdt_timeout_sel_t into its cycle count.
ra8_err_t ra8_wdt_pclkb_divisor (ra8_wdt_clock_div_t div, uint16_t *out_divisor)
 Decode a ra8_wdt_clock_div_t into its numeric divisor.
ra8_err_t ra8_wdt_total_pclkb_cycles (ra8_wdt_timeout_sel_t sel, ra8_wdt_clock_div_t div, uint32_t *out_pclkb_cycles)
 Compute the effective timeout in PCLKB cycles.
ra8_err_t ra8_wdt_attach_handler (ra8_wdt_event_fn_t fn, void *ctx)
 Register a callback invoked from the WDT NMI / underflow ISR.
ra8_err_t ra8_wdt_subscribe (ra8_wdt_event_fn_t fn, void *ctx, uint8_t *out_slot)
 Add a hot-pluggable subscriber to the WDT NMI dispatch list.
ra8_err_t ra8_wdt_unsubscribe (uint8_t slot)
 Remove a previously-registered subscriber.
uint8_t ra8_wdt_subscriber_count (void)
 Number of currently-installed subscribers.
void ra8_wdt_dispatch (void)
 Dispatch a WDT event – snapshot WDTSR + fan-out to subscribers.
ra8_err_t ra8_wdt_install_nmi (void)
 Enable the WDT bit in NMIER so the NMI line fires on underflow.
ra8_err_t ra8_wdt_uninstall_nmi (void)
 Disable the WDT bit in NMIER (counterpart to ra8_wdt_install_nmi).
ra8_err_t ra8_wdt_enter_stop (void)
 Enable counter halt on Sleep entry.
ra8_err_t ra8_wdt_exit_stop (void)
 Disable counter halt on Sleep entry.
ra8_err_t ra8_wdt_ofs_reader_set (ra8_wdt_ofs_reader_fn_t reader)
 Override the OFSm reader hook used by ra8_wdt_ofs_get.
ra8_err_t ra8_wdt_ofs_get (ra8_wdt_instance_t which, ra8_wdt_ofs_decoded_t *out)
 Decode an OFSm option-setting word into ra8_wdt_cfg_t.

Detailed Description

Software Watchdog Timer (WDT) driver header.

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

This is the software-controlled Watchdog Timer described in HUM Ch 27 (p 1256-1270). It is distinct from the IWDT driver (ra8_iwdt.h, HUM Ch 28) which has its own free-running clock and cannot be reconfigured at runtime.

Start mode and OFS0

The WDT has two start modes selected by the OFS0.WDT0STRT bit in option-setting memory (HUM Ch 7, "Option-Setting Memory") for WDT0, and by OFS3.WDT1STRT for the M33-side WDT1:

  • Auto-start mode (WDT0STRT = 0): the period, clock divider, window, reset-vs-NMI behaviour, and Sleep stop control are all baked in to the OFS0 word at flash time. The runtime WDTCR / WDTRCR / WDTCSTPR registers become read-only-as-zero – this driver's ra8_wdt_init is a no-op in that build, but refresh, status and dispatch still work.
  • Register-start mode (WDT0STRT = 1): the counter does not start out of reset. Software must programme WDTCR / WDTRCR / WDTCSTPR and then issue the first WDTRR refresh to arm the down-counter. This is the mode ra8_wdt_init expects.

The driver does not (and cannot) flip OFS0 itself – ra8_ofs.c owns the writable side. ra8_wdt_ofs_get exposes the read-only view so the application can decode whichever mode the boot ROM latched.

API surface

State machine

State Machine:

Definition in file ra8_wdt.h.

Typedef Documentation

◆ ra8_wdt_event_fn_t

typedef void(* ra8_wdt_event_fn_t) (void *ctx, uint16_t status_mask)

WDT NMI / underflow event callback.

Parameters
[in]ctxCaller context as registered with ra8_wdt_attach_handler.
[in]status_maskLatched WDTSR top bits at dispatch time (k_ra8_wdt_status_underflow and / or k_ra8_wdt_status_refresh).

Definition at line 343 of file ra8_wdt.h.

◆ ra8_wdt_ofs_reader_fn_t

typedef ra8_err_t(* ra8_wdt_ofs_reader_fn_t) (uintptr_t ofs_addr, uint32_t *out_word)

Hook used to fetch one OFSm option-setting word.

Production builds default to internal_default_ofs_reader which dereferences the address directly. The hook exists so unit tests (and bring-up debuggers running from non-secure world) can supply canned OFSm contents without needing the option-setting MRAM page mapped at the host. Per CLAUDE.md NASA Rule 9 deviation, function pointers are allowed for Dependency Inversion.

It is also the seam a non-secure caller needs: OFS0, OFS3_SEC and OFS3_SEL are all secure-region words, so a non-secure image must route this through a veneer rather than loading from them.

Parameters
[in]ofs_addrOne of the ra8_ofs_addr_t constants – k_ra8_ofs0_addr, k_ra8_ofs3_addr, k_ra8_ofs3_sec_addr or k_ra8_ofs3_sel_addr (HUM Ch 7 Figure 7.1 p 279).
[out]out_wordReceives the 32-bit option-setting word.
Returns
k_ra8_ok on success; k_ra8_err_* on hook-defined failure.

Definition at line 918 of file ra8_wdt.h.

Enumeration Type Documentation

◆ ra8_wdt_clear_timeout_t

enum ra8_wdt_clear_timeout_t : uint32_t

Bounded retry budget for ra8_wdt_clear_status_blocking.

HUM Ch 27.2.3 p 1261 says clearing UNDFF / REFEF takes N + 1 PCLKB cycles, where N depends on the divider (worst case 8192 + 1). The blocking helper polls the flag, decrementing a read-back counter sized for that worst case (with a generous margin) before returning k_ra8_err_hw_timeout.

Enumerator
k_ra8_wdt_clear_max_polls 

16384 reads – safely > 8193.

Definition at line 278 of file ra8_wdt.h.

◆ ra8_wdt_clock_div_t

enum ra8_wdt_clock_div_t : uint8_t

Legal CKS[3:0] encodings for WDTCR.

Only six of the sixteen 4-bit CKS encodings are usable – HUM Ch 27.2.2 p 1258 marks the rest as "Setting prohibited". Each value is the raw bit pattern that must land in WDTCR.CKS, so the driver can & k_ra8_wdt_mask_cks and << k_ra8_wdt_shift_cks straight from this enum.

See also
HUM Ch 27.2.2 "WDTCR : WDT Control Register", p 1258.
Enumerator
k_ra8_wdt_clkdiv_4 

PCLKB / 4.

k_ra8_wdt_clkdiv_64 

PCLKB / 64.

k_ra8_wdt_clkdiv_128 

PCLKB / 128.

k_ra8_wdt_clkdiv_512 

PCLKB / 512.

k_ra8_wdt_clkdiv_2048 

PCLKB / 2048.

k_ra8_wdt_clkdiv_8192 

PCLKB / 8192.

Definition at line 125 of file ra8_wdt.h.

◆ ra8_wdt_ofs_strt_t

enum ra8_wdt_ofs_strt_t : uint8_t

OFSm.WDTnSTRT encoding – auto vs register start mode.

The boot ROM latches this bit out of the OFS0 (WDT0) or OFS3 (WDT1) option-setting word at reset. auto means WDTCR / WDTRCR / WDTCSTPR are all sourced from OFSm; register_start means they are programmable via the runtime registers exactly once after reset.

See also
HUM Ch 27.3.1 p 1263.
Enumerator
k_ra8_wdt_ofs_strt_auto 

Auto-start (OFSm-driven).

k_ra8_wdt_ofs_strt_register 

Register-start (runtime config).

Definition at line 235 of file ra8_wdt.h.

◆ ra8_wdt_reset_ctrl_t

enum ra8_wdt_reset_ctrl_t : uint8_t

WDTRCR.RSTIRQS encoding – reset vs NMI on expiry.

Determines what the WDT does when it underflows or sees a refresh-error. on_expiry_nmi routes the event through ICU.NMIER (HUM Ch 14.2.14 p 542) where ra8_wdt_install_nmi picks it up; on_expiry_reset triggers an internal reset.

See also
HUM Ch 27.2.4 "WDTRCR" p 1262.
Enumerator
k_ra8_wdt_on_expiry_nmi 

RSTIRQS=0 – route to NMI / IRQ.

k_ra8_wdt_on_expiry_reset 

RSTIRQS=1 – internal reset.

Definition at line 200 of file ra8_wdt.h.

◆ ra8_wdt_status_mask_t

enum ra8_wdt_status_mask_t : uint16_t

WDTSR top-bit status flags.

Mirrors the high two bits of WDTSR – see HUM Ch 27.2.3 p 1260.

Enumerator
k_ra8_wdt_status_none 

No flag set.

k_ra8_wdt_status_underflow 

UNDFF (bit 14).

k_ra8_wdt_status_refresh 

REFEF (bit 15).

Definition at line 247 of file ra8_wdt.h.

◆ ra8_wdt_stop_ctrl_t

enum ra8_wdt_stop_ctrl_t : uint8_t

WDTCSTPR.SLCSTP encoding – counter behaviour in Sleep.

sleep_keep_count keeps the counter ticking through Sleep / Deep Sleep so the WDT can still fire if the wake event is missed. sleep_stop_count halts the counter on Sleep entry, useful for battery / low-power operation.

See also
HUM Ch 27.2.5 "WDTCSTPR" p 1262.
Enumerator
k_ra8_wdt_sleep_keep_count 

SLCSTP=0 – counter runs in Sleep.

k_ra8_wdt_sleep_stop_count 

SLCSTP=1 – counter halts in Sleep.

Definition at line 217 of file ra8_wdt.h.

◆ ra8_wdt_subs_count_t

enum ra8_wdt_subs_count_t : uint8_t

Maximum number of hot-pluggable subscribers per WDT instance.

Sized to cover the typical fan-out of underflow / refresh-error handlers (state-of-health logger, watchdog-aware task cleanup, crash-logger, and one or two app callbacks). All slots are statically allocated – no malloc per the project's rules.

Enumerator
k_ra8_wdt_max_subs 

Max simultaneous subscribers.

Definition at line 263 of file ra8_wdt.h.

◆ ra8_wdt_timeout_sel_t

enum ra8_wdt_timeout_sel_t : uint8_t

Legal TOPS[1:0] encodings for WDTCR.

Selects the WDT timeout in counter cycles before the divider is applied. Decode with ra8_wdt_timeout_cycles_get to recover the numeric cycle count, or with ra8_wdt_total_pclkb_cycles to fold in the CKS divider.

See also
HUM Ch 27.2.2 Table 27.2 p 1259.
Enumerator
k_ra8_wdt_timeout_1024 

1024 cycles.

k_ra8_wdt_timeout_4096 

4096 cycles.

k_ra8_wdt_timeout_8192 

8192 cycles.

k_ra8_wdt_timeout_16384 

16384 cycles.

Definition at line 146 of file ra8_wdt.h.

◆ ra8_wdt_window_end_t

enum ra8_wdt_window_end_t : uint8_t

Legal RPES[1:0] encodings (refresh-permitted window end).

Selects the lower bound of the refresh-permitted window, expressed as a percentage of the full timeout. window_end_0 disables the lower bound. HUM Ch 27.2.2 p 1259.

Invariant
window_end < window_start – silicon forces window_end = 0% if the constraint is violated.
Enumerator
k_ra8_wdt_window_end_75 

75 %.

k_ra8_wdt_window_end_50 

50 %.

k_ra8_wdt_window_end_25 

25 %.

k_ra8_wdt_window_end_0 

0 % (no lower bound).

Definition at line 181 of file ra8_wdt.h.

◆ ra8_wdt_window_start_t

enum ra8_wdt_window_start_t : uint8_t

Legal RPSS[1:0] encodings (refresh-permitted window start).

Selects the upper bound of the refresh-permitted window, expressed as a percentage of the full timeout. window_start_100 disables the upper bound. HUM Ch 27.2.2 p 1259.

Enumerator
k_ra8_wdt_window_start_25 

25 %.

k_ra8_wdt_window_start_50 

50 %.

k_ra8_wdt_window_start_75 

75 %.

k_ra8_wdt_window_start_100 

100 % (no upper bound).

Definition at line 162 of file ra8_wdt.h.

Function Documentation

◆ ra8_wdt_attach_handler()

ra8_err_t ra8_wdt_attach_handler ( ra8_wdt_event_fn_t fn,
void * ctx )
nodiscard

Register a callback invoked from the WDT NMI / underflow ISR.

Single-callback wrapper preserved from v0.2.0 so existing wiring keeps compiling. Internally just calls ra8_wdt_subscribe / ra8_wdt_unsubscribe with a private "legacy" slot, so it coexists with the multi-subscriber API without losing entries.

Parameters
[in]fnCallback fn (may be nullptr to clear).
[in]ctxContext pointer forwarded to fn.
Returns
ra8_err_t
Return values
k_ra8_okSlot updated.
k_ra8_err_no_memSubscriber table full and a non-null fn was supplied (theoretical).
Precondition
Caller is in single-writer init context.
No NMI is being dispatched concurrently.
Postcondition
Subsequent ra8_wdt_dispatch calls invoke fn.
ctx is captured exactly as passed.
Note
Not thread-safe – attach during init only.
See also
ra8_wdt_subscribe Multi-subscriber alternative.
Since
0.1.0

Definition at line 519 of file ra8_wdt.c.

References k_ra8_ok, k_ra8_wdt_legacy_slot, and s_wdt_subs.

◆ ra8_wdt_clear_status()

ra8_err_t ra8_wdt_clear_status ( void )
nodiscard

Clear the WDTSR underflow / refresh-error flags.

Writes 0 to UNDFF and REFEF (write-1 has no effect, per HUM Ch 27.2.3 p 1261). The flag clear takes N + 1 PCLKB cycles to land, where N depends on the CKS divider; the driver does not busy-wait, so an immediate read-back may still return the old value. Use ra8_wdt_clear_status_blocking for the polled variant.

Returns
ra8_err_t
Return values
k_ra8_okAlways succeeds.
Precondition
WDT block has been powered.
Caller is in a single-writer context.
Postcondition
UNDFF / REFEF will read 0 within (N + 1) PCLKB cycles.
CNTVAL[13:0] is unaffected.
Note
Not thread-safe.
Since
0.1.0

Definition at line 379 of file ra8_wdt.c.

References k_ra8_ok, k_ra8_wdt_status_all, ra8_wdt(), and r_wdt_regs_t::WDTSR.

Referenced by wdt_window_demo_iter().

◆ ra8_wdt_clear_status_blocking()

ra8_err_t ra8_wdt_clear_status_blocking ( uint16_t mask)
nodiscard

Clear specific WDTSR flag bits and busy-wait until they read 0.

HUM Ch 27.2.3 p 1261 documents that the W0C flag clear takes N + 1 PCLKB cycles to land. This helper polls the register up to k_ra8_wdt_clear_max_polls times and returns k_ra8_err_hw_timeout if the bit is still set when the budget runs out (the FSP analogue is the do/while loop in R_WDT_StatusClear).

Parameters
[in]maskBit mask of flags to clear (any combination of k_ra8_wdt_status_underflow / ..._refresh).
Returns
ra8_err_t
Return values
k_ra8_okTargeted flags read 0 within budget.
k_ra8_err_invalid_argmask outside the legal flag bits.
k_ra8_err_hw_timeoutFlag still latched after k_ra8_wdt_clear_max_polls.
Precondition
WDT block has been powered.
Caller is in single-writer context (or has masked IRQs).
Postcondition
On success, the targeted bits in WDTSR read 0.
On hw_timeout, hardware state is unchanged from a single ra8_wdt_clear_status call.
Note
Not thread-safe.
Since
0.1.0

Definition at line 389 of file ra8_wdt.c.

References k_ra8_err_hw_timeout, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_wdt_clear_max_polls, k_ra8_wdt_status_all, k_ra8_wdt_status_none, ra8_log_error, ra8_wdt(), s_tag, and r_wdt_regs_t::WDTSR.

◆ ra8_wdt_deinit()

ra8_err_t ra8_wdt_deinit ( void )
nodiscard

Quiesce the driver into a Sleep-stop posture.

Sets WDTCSTPR.SLCSTP so the counter halts when the CPU enters Sleep / Deep Sleep. The WDT itself cannot be disarmed once started, so this is the closest analogue to a "deinit" the silicon allows. Also clears every multi-subscriber slot so a follow-up ra8_wdt_init starts from a known callback table.

Returns
ra8_err_t
Return values
k_ra8_okAlways succeeds.
Precondition
ra8_wdt_init has been called.
Caller is in a single-writer context.
Postcondition
WDTCSTPR.SLCSTP = 1 (in register-start mode).
Counter still runs while CPU is awake.
Subscriber table is empty (every slot {nullptr, nullptr}).
Note
No-op in auto-start mode – WDTCSTPR is then read-only-zero.
Since
0.1.0

Definition at line 332 of file ra8_wdt.c.

References internal_subs_clear_all(), k_ra8_ok, k_ra8_wdt_cstpr_slcstp, ra8_log_info, ra8_wdt(), s_tag, and r_wdt_regs_t::WDTCSTPR.

◆ ra8_wdt_dispatch()

void ra8_wdt_dispatch ( void )

Dispatch a WDT event – snapshot WDTSR + fan-out to subscribers.

Latches the UNDFF / REFEF bits, clears them, then invokes every registered subscriber (legacy attach_handler + multi-sub list) in registration order. Intended to be called from the WDT NMI vector. The status mask is captured before the W0C clear so all subscribers see the same snapshot.

Precondition
WDT block has been powered.
Called from NMI context (interrupts disabled).
Postcondition
WDTSR's UNDFF and REFEF bits will read 0 within (N + 1) PCLKB cycles.
Every populated subscriber slot has been invoked exactly once.
Note
Safe to call when no subscriber is registered (becomes a flag clear with no further effect).
Since
0.1.0

Definition at line 575 of file ra8_wdt.c.

References k_ra8_wdt_max_subs, k_ra8_wdt_status_all, ra8_wdt(), s_wdt_subs, and r_wdt_regs_t::WDTSR.

◆ ra8_wdt_enter_stop()

ra8_err_t ra8_wdt_enter_stop ( void )
nodiscard

Enable counter halt on Sleep entry.

Sets WDTCSTPR.SLCSTP. In auto-start mode this is a no-op because the same field is locked from OFS0.

Returns
ra8_err_t
Return values
k_ra8_okAlways succeeds.
Precondition
ra8_wdt_init has been called.
Caller is in a single-writer context.
Postcondition
WDTCSTPR.SLCSTP = 1 (register-start mode).
Counter halts on the next WFI / WFE.
Note
Idempotent.
Since
0.1.0

Definition at line 628 of file ra8_wdt.c.

References k_ra8_ok, k_ra8_wdt_cstpr_slcstp, ra8_wdt(), and r_wdt_regs_t::WDTCSTPR.

◆ ra8_wdt_exit_stop()

ra8_err_t ra8_wdt_exit_stop ( void )
nodiscard

Disable counter halt on Sleep entry.

Clears WDTCSTPR.SLCSTP so the counter keeps decrementing in Sleep. Useful when the application uses Sleep as an idle posture but still wants the WDT to fire if the wake source never arrives.

Returns
ra8_err_t
Return values
k_ra8_okAlways succeeds.
Precondition
ra8_wdt_init has been called.
Caller is in a single-writer context.
Postcondition
WDTCSTPR.SLCSTP = 0 (register-start mode).
Counter continues to count in Sleep.
Note
Idempotent.
Since
0.1.0

Definition at line 637 of file ra8_wdt.c.

References k_ra8_ok, ra8_wdt(), and r_wdt_regs_t::WDTCSTPR.

◆ ra8_wdt_get_counter()

ra8_err_t ra8_wdt_get_counter ( uint16_t * out_count)
nodiscard

Read the live CNTVAL[13:0] down-counter value.

Parameters
[out]out_countReceives the current counter; range 0..0x3FFF. The hardware notes the read may differ from the actual count by 1 (HUM Ch 27.2.3 p 1261).
Returns
ra8_err_t
Return values
k_ra8_okCounter read.
k_ra8_err_null_ptrout_count was null.
Precondition
out_count is non-null.
WDT block has been powered.
Postcondition
*out_count <= 0x3FFF.
No side effect on WDTSR.
Note
Read-only; safe to call from any context.
Since
0.1.0

Definition at line 428 of file ra8_wdt.c.

References k_ra8_ok, k_ra8_wdt_sr_cnt_mask, RA8_CHECK_NULL_PTR, ra8_wdt(), and s_tag.

Referenced by wdt_window_demo_iter().

◆ ra8_wdt_get_status()

ra8_err_t ra8_wdt_get_status ( uint16_t * out_mask)
nodiscard

Read the WDTSR status flag bits.

Parameters
[out]out_maskReceives k_ra8_wdt_status_underflow and / or k_ra8_wdt_status_refresh (others = 0).
Returns
ra8_err_t
Return values
k_ra8_okStatus read.
k_ra8_err_null_ptrout_mask was null.
Precondition
out_mask is non-null.
WDT block has been powered (always-on for this peripheral).
Postcondition
*out_mask is one of the k_ra8_wdt_status_* masks.
No side effect on WDTSR.
Note
Thread-safe wrt other readers; concurrent writers must serialise the access.
Since
0.1.0

Definition at line 371 of file ra8_wdt.c.

References k_ra8_ok, k_ra8_wdt_status_all, RA8_CHECK_NULL_PTR, ra8_wdt(), and s_tag.

◆ ra8_wdt_init()

ra8_err_t ra8_wdt_init ( const ra8_wdt_cfg_t * cfg)
nodiscard

Initialise the WDT in register-start mode.

Programmes WDTCR with the timeout / clock divider / window selection from cfg, WDTRCR with the reset-vs-NMI choice, and WDTCSTPR with the Sleep-stop selection. After all three are written this function issues the first refresh, which is what actually arms the counter.

Algorithm:

  1. Validate cfg non-null.
  2. Validate cfg->clock_div against the legal CKS encodings.
  3. Build WDTCR by shifting each field into place.
  4. Write WDTCR (one 16-bit transaction), WDTRCR, WDTCSTPR.
  5. Issue the unlock sequence on WDTRR to arm the counter.

In auto-start mode the WDTCR / WDTRCR / WDTCSTPR writes are silently dropped by silicon, but the refresh still works – so the function is safe to call in either mode.

Parameters
[in]cfgPointer to the configuration block.
Returns
ra8_err_t Result code.
Return values
k_ra8_okCounter armed.
k_ra8_err_null_ptrcfg was null.
k_ra8_err_invalid_argcfg->clock_div is not one of the legal CKS encodings.
Precondition
cfg is non-null.
PCLKB has been started by the CGC driver.
Postcondition
WDTCR / WDTRCR / WDTCSTPR reflect cfg (register-start mode).
WDTRR holds 0xFF – the counter has been refreshed once.
Note
Not thread-safe – call from init context only. The WDT control registers can only be written once after reset (HUM Ch 27.3.2 "Controlling Writes to the WDTCR, WDTRCR, and WDTCSTPR Registers"), so subsequent calls have no effect.
See also
ra8_wdt_refresh_deferred Run-time heartbeat.
ra8_wdt_deinit Counterpart that disables in Sleep.
Since
0.1.0

Definition at line 296 of file ra8_wdt.c.

References ra8_wdt_cfg_t::clock_div, internal_clock_div_is_valid(), internal_pack_wdtcr(), internal_timeout_sel_is_valid(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_wdt_cstpr_slcstp, k_ra8_wdt_on_expiry_reset, k_ra8_wdt_rcr_rstirqs, k_ra8_wdt_sleep_stop_count, ra8_wdt_cfg_t::on_expiry, RA8_CHECK_NULL_PTR, ra8_log_info, ra8_wdt(), ra8_wdt_refresh(), s_tag, ra8_wdt_cfg_t::stop_in_sleep, ra8_wdt_cfg_t::timeout, r_wdt_regs_t::WDTCR, r_wdt_regs_t::WDTCSTPR, and r_wdt_regs_t::WDTRCR.

Referenced by main(), ra8_nsc_wdt_start(), sh_wdt_arm_or_halt(), wdt_rr_arm_and_wait_for_reset(), and wdt_sup_demo_bring_up().

◆ ra8_wdt_install_nmi()

ra8_err_t ra8_wdt_install_nmi ( void )
nodiscard

Enable the WDT bit in NMIER so the NMI line fires on underflow.

HUM Ch 14.2.14 p 542 – NMIER is sticky-set; once written it cannot be cleared by software except via the matching ra8_wdt_uninstall_nmi helper which goes through ra8_icu_nmi_disable. Use this from the boot sequence after the ICU is initialized but before the WDT starts decrementing.

Returns
ra8_err_t
Return values
k_ra8_okAlways succeeds (the underlying ra8_icu_nmi_enable only OR's into the register).
Precondition
ra8_icu_init has been called.
Caller is in single-writer init context.
Postcondition
NMIER.WDTEN reads 1.
NMICLR has cleared any stale WDT NMI status.
Since
0.1.0

Definition at line 598 of file ra8_wdt.c.

References k_ra8_ok, k_ra8_wdt_nmier_wdten_mask, ra8_icu_nmi_clear(), and ra8_icu_nmi_enable().

◆ ra8_wdt_ofs_get()

ra8_err_t ra8_wdt_ofs_get ( ra8_wdt_instance_t which,
ra8_wdt_ofs_decoded_t * out )
nodiscard

Decode an OFSm option-setting word into ra8_wdt_cfg_t.

Recovers the seven WDT fields the boot ROM latched when OFSm.WDTnSTRT == 0, per HUM Ch 27.3.8 Table 27.5 p 1269. The two instances read different numbers of words, because the hardware does:

  • k_ra8_wdt0one read of OFS0 (HUM Ch 7.2.1 p 280). OFS0 is a single secure-region word with no _SEC / _SEL companions.
  • k_ra8_wdt1three reads. OFS3_SEL (HUM Ch 7.2.7 p 289) selects, per field, whether WDT1 latched that field from OFS3_SEC (selector 0) or OFS3 (selector 1), so the effective word is a mux of the two copies. Reading either copy alone reports a configuration the hardware may not be using.

The WDT driver is read-only with respect to OFSm; only ra8_ofs.c may write the option-setting sections. Every fetch goes through the ra8_wdt_ofs_reader_set hook so unit tests / bring-up code can supply canned words without touching MRAM.

Parameters
[in]whichInstance whose OFSm word should be decoded.
[out]outReceives the decoded view.
Returns
ra8_err_t
Return values
k_ra8_okDecoded.
k_ra8_err_null_ptrout was null.
k_ra8_err_invalid_argwhich is not a known instance.
k_ra8_err_invalid_statewhich was k_ra8_wdt1 and OFS3_SEL holds an encoding HUM Ch 7.2.7 p 289 marks "Setting prohibit".
k_ra8_err_*Whatever the reader hook returned.
Precondition
out is non-null.
which < k_ra8_wdt_instance_count.
Postcondition
out->cfg mirrors the latched OFSm fields.
out->auto_start matches out->start_mode == k_ra8_wdt_ofs_strt_auto.
Note
Read-only; callable from any context.
Warning
Secure-world only under the default reader – see ra8_wdt_ofs_reader_fn_t.
See also
ra8_ofs_addr_t The addresses this reads.
Since
0.1.0

Definition at line 824 of file ra8_wdt.c.

References internal_decode_ofs_word(), internal_read_wdt1_word(), k_ra8_err_invalid_arg, k_ra8_ofs0_addr, k_ra8_ok, k_ra8_wdt0, k_ra8_wdt_instance_count, RA8_CHECK_NULL_PTR, s_ofs_reader, and s_tag.

◆ ra8_wdt_ofs_reader_set()

ra8_err_t ra8_wdt_ofs_reader_set ( ra8_wdt_ofs_reader_fn_t reader)
nodiscard

Override the OFSm reader hook used by ra8_wdt_ofs_get.

Pass nullptr to restore the default reader (direct MMIO read). Production code never needs to call this; it exists for unit tests and for early-bring-up code that has not yet mapped the option- setting page.

Parameters
[in]readerNew reader function or nullptr for default.
Returns
Always k_ra8_ok.
Precondition
Caller is in single-writer init context.
Postcondition
Subsequent ra8_wdt_ofs_get calls go through reader.
Since
0.1.0

Definition at line 651 of file ra8_wdt.c.

References internal_default_ofs_reader(), k_ra8_ok, and s_ofs_reader.

◆ ra8_wdt_pclkb_divisor()

ra8_err_t ra8_wdt_pclkb_divisor ( ra8_wdt_clock_div_t div,
uint16_t * out_divisor )
nodiscard

Decode a ra8_wdt_clock_div_t into its numeric divisor.

Parameters
[in]divCKS field (k_ra8_wdt_clkdiv_*).
[out]out_divisorReceives the divisor in {4, 64, 128, 512, 2048, 8192} per HUM Ch 27.2.2 p 1258.
Returns
ra8_err_t
Return values
k_ra8_okDecoded.
k_ra8_err_null_ptrout_divisor was null.
k_ra8_err_invalid_argdiv not a legal CKS encoding.
Precondition
out_divisor is non-null.
div is one of the legal CKS encodings.
Postcondition
*out_divisor is one of {4, 64, 128, 512, 2048, 8192}.
No hardware state is touched.
Since
0.1.0

Definition at line 464 of file ra8_wdt.c.

References k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_wdt_clkdiv_128, k_ra8_wdt_clkdiv_2048, k_ra8_wdt_clkdiv_4, k_ra8_wdt_clkdiv_512, k_ra8_wdt_clkdiv_64, k_ra8_wdt_clkdiv_8192, k_ra8_wdt_div_value_128, k_ra8_wdt_div_value_2048, k_ra8_wdt_div_value_4, k_ra8_wdt_div_value_512, k_ra8_wdt_div_value_64, k_ra8_wdt_div_value_8192, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by ra8_wdt_total_pclkb_cycles().

◆ ra8_wdt_refresh_deferred()

void ra8_wdt_refresh_deferred ( void )

Refresh the software WDT counter (WDT0).

Thin wrapper around the inline ra8_wdt_refresh helper in the register header so other compilation units do not have to pull in ra8_wdt_regs.h.

Precondition
WDT has been armed (auto-start out of reset, or ra8_wdt_init succeeded).
Refresh occurs strictly inside the refresh-permitted window programmed by cfg->window_start / cfg->window_end.
Postcondition
WDTRR holds 0xFF.
Down-counter is reloaded.
Note
Not thread-safe.
Since
0.1.0

Definition at line 350 of file ra8_wdt.c.

References ra8_wdt_refresh().

Referenced by internal_default_refresh(), and ra8_nsc_wdt_refresh().

◆ ra8_wdt_refresh_for()

ra8_err_t ra8_wdt_refresh_for ( ra8_wdt_instance_t which)
nodiscard

Refresh a specific WDT instance.

Parameters
[in]whichInstance to refresh (k_ra8_wdt0 or k_ra8_wdt1).
Returns
ra8_err_t
Return values
k_ra8_okCounter refreshed.
k_ra8_err_invalid_argwhich not a known instance.
Precondition
which < k_ra8_wdt_instance_count.
WDT has been armed.
Postcondition
Targeted WDT's WDTRR holds 0xFF.
Targeted WDT down-counter is reloaded.
Since
0.1.0

Definition at line 356 of file ra8_wdt.c.

References k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_wdt_instance_count, and ra8_wdt_refresh_instance().

Referenced by sh_run(), wdt_rr_arm_and_wait_for_reset(), and wdt_window_demo_iter().

◆ ra8_wdt_subscribe()

ra8_err_t ra8_wdt_subscribe ( ra8_wdt_event_fn_t fn,
void * ctx,
uint8_t * out_slot )
nodiscard

Add a hot-pluggable subscriber to the WDT NMI dispatch list.

Multiple modules can listen for the underflow / refresh-error event (an SoH logger, the application crash recorder, a watchdog-aware task scheduler,...). Each ra8_wdt_subscribe call grabs the first free slot in the static dispatch table; ra8_wdt_dispatch later walks every populated slot in registration order.

Parameters
[in]fnCallback. Must not be nullptr.
[in]ctxCaller-supplied pointer forwarded to fn on every dispatch.
[out]out_slotReceives the slot index (0..k_ra8_wdt_max_subs-1) assigned to this subscriber. May be nullptr if the caller doesn't need it.
Returns
ra8_err_t
Return values
k_ra8_okSubscriber installed.
k_ra8_err_null_ptrfn was null.
k_ra8_err_no_memAll k_ra8_wdt_max_subs slots are taken.
Precondition
fn is non-null.
Caller is in single-writer init context (subscribe is not NMI-safe; do all subscribes during boot).
Postcondition
On success, exactly one previously-empty slot is filled.
Slot count grows by 1.
Note
Not thread-safe; treat the subscriber table as immutable once interrupts are unmasked.
See also
ra8_wdt_unsubscribe Inverse operation.
Since
0.1.0

Definition at line 529 of file ra8_wdt.c.

References k_ra8_err_no_mem, k_ra8_ok, k_ra8_wdt_max_subs, RA8_CHECK_NULL_PTR, ra8_log_error, s_tag, and s_wdt_subs.

◆ ra8_wdt_subscriber_count()

uint8_t ra8_wdt_subscriber_count ( void )

Number of currently-installed subscribers.

Diagnostic accessor used by tests and dump helpers. Counts only slots whose fn is non-null.

Returns
The current populated-slot count.
Precondition
None.
Postcondition
No state is mutated.
Since
0.1.0
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.

Definition at line 563 of file ra8_wdt.c.

References k_ra8_wdt_max_subs, and s_wdt_subs.

◆ ra8_wdt_timeout_cycles_get()

ra8_err_t ra8_wdt_timeout_cycles_get ( ra8_wdt_timeout_sel_t sel,
uint16_t * out_cycles )
nodiscard

Decode a ra8_wdt_timeout_sel_t into its cycle count.

Parameters
[in]selTOPS field (k_ra8_wdt_timeout_*).
[out]out_cyclesReceives the cycle count (1024 / 4096 / 8192 / 16384) per HUM Ch 27.2.2 Table 27.2 p 1259.
Returns
ra8_err_t
Return values
k_ra8_okDecoded.
k_ra8_err_null_ptrout_cycles was null.
k_ra8_err_invalid_argsel outside 0..3.
Precondition
out_cycles is non-null.
sel is a valid TOPS encoding.
Postcondition
*out_cycles is one of {1024, 4096, 8192, 16384}.
No hardware state is touched.
Since
0.1.0

Definition at line 442 of file ra8_wdt.c.

References k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_wdt_cycles_1024, k_ra8_wdt_cycles_16384, k_ra8_wdt_cycles_4096, k_ra8_wdt_cycles_8192, k_ra8_wdt_timeout_1024, k_ra8_wdt_timeout_16384, k_ra8_wdt_timeout_4096, k_ra8_wdt_timeout_8192, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by ra8_wdt_total_pclkb_cycles().

◆ ra8_wdt_total_pclkb_cycles()

ra8_err_t ra8_wdt_total_pclkb_cycles ( ra8_wdt_timeout_sel_t sel,
ra8_wdt_clock_div_t div,
uint32_t * out_pclkb_cycles )
nodiscard

Compute the effective timeout in PCLKB cycles.

Returns cycles_for(TOPS) * divisor_for(CKS) as a 32-bit value. Matches Table 27.2 p 1259 row by row – e.g. CKS=PCLKB/8192, TOPS=16384 yields 134_217_728 PCLKB cycles.

Parameters
[in]selTOPS field.
[in]divCKS field.
[out]out_pclkb_cyclesReceives the product.
Returns
ra8_err_t
Return values
k_ra8_okComputed.
k_ra8_err_null_ptrout_pclkb_cycles was null.
k_ra8_err_invalid_argsel or div invalid.
Precondition
out_pclkb_cycles is non-null.
sel and div decode successfully.
Postcondition
*out_pclkb_cycles <= 134_217_728 (largest table entry).
No hardware state is touched.
Since
0.1.0

Definition at line 492 of file ra8_wdt.c.

References k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_wdt_pclkb_divisor(), ra8_wdt_timeout_cycles_get(), and s_tag.

◆ ra8_wdt_uninstall_nmi()

ra8_err_t ra8_wdt_uninstall_nmi ( void )
nodiscard

Disable the WDT bit in NMIER (counterpart to ra8_wdt_install_nmi).

Returns
ra8_err_t
Return values
k_ra8_okAlways succeeds.
Precondition
ra8_icu_init has been called.
Caller is in single-writer context.
Postcondition
NMIER.WDTEN reads 0.
Pending WDT NMI status is cleared via NMICLR.
Since
0.1.0

Definition at line 612 of file ra8_wdt.c.

References k_ra8_ok, k_ra8_wdt_nmier_wdten_mask, ra8_icu_nmi_clear(), and ra8_icu_nmi_disable().

◆ ra8_wdt_unsubscribe()

ra8_err_t ra8_wdt_unsubscribe ( uint8_t slot)
nodiscard

Remove a previously-registered subscriber.

Parameters
[in]slotSlot index returned by ra8_wdt_subscribe.
Returns
ra8_err_t
Return values
k_ra8_okSlot freed.
k_ra8_err_invalid_argslot out of range.
k_ra8_err_not_foundSlot was already empty.
Precondition
slot < k_ra8_wdt_max_subs.
Caller is in single-writer init context.
Postcondition
Slot reads {nullptr, nullptr}.
Subsequent dispatches skip the slot.
Since
0.1.0

Definition at line 550 of file ra8_wdt.c.

References k_ra8_err_invalid_arg, k_ra8_err_not_found, k_ra8_ok, k_ra8_wdt_max_subs, and s_wdt_subs.