|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Software Watchdog Timer (WDT) driver implementation. More...
#include "ra8_wdt.h"#include <stdint.h>#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_hw_err.h"#include "ra8_icu.h"#include "ra8_log.h"#include "ra8_ofs.h"#include "ra8_wdt_regs.h"Go to the source code of this file.
Data Structures | |
| struct | ra8_wdt_sub_t |
| One entry in the multi-subscriber dispatch table. More... | |
Enumerations | |
| enum | ra8_wdt_legacy_slot_t : uint8_t { k_ra8_wdt_legacy_slot = 0U } |
| Slot reserved for the legacy single-callback API. More... | |
| enum | ra8_wdt_status_combined_t : uint16_t { k_ra8_wdt_status_all } |
| Union of the two WDTSR top-flag bits the driver cares about. More... | |
Functions | |
| static ra8_err_t | internal_default_ofs_reader (uintptr_t ofs_addr, uint32_t *out_word) |
| Default OFSm reader: dereferences the address as a 32-bit word. | |
| static bool | internal_clock_div_is_valid (ra8_wdt_clock_div_t div) |
| Reject CKS encodings the silicon marks as "Setting prohibited". | |
| static bool | internal_timeout_sel_is_valid (ra8_wdt_timeout_sel_t sel) |
| Reject TOPS encodings outside the documented 2-bit range. | |
| static uint16_t | internal_pack_wdtcr (const ra8_wdt_cfg_t *cfg) |
| Pack a ra8_wdt_cfg_t into a 16-bit WDTCR word. | |
| static void | internal_subs_clear_all (void) |
| Clear every subscriber slot. | |
| 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. | |
| static bool | internal_sel_field_uniform (uint32_t sel, uint32_t shift, uint32_t mask) |
| Report whether one multi-bit OFS3_SEL field holds a legal encoding. | |
| static bool | internal_ofs3_sel_is_legal (uint32_t sel) |
| Report whether an OFS3_SEL word is legal in every multi-bit field. | |
| static ra8_err_t | internal_read_wdt1_word (uint32_t *out_word) |
| Resolve WDT1's effective option word from the OFS3 family. | |
| static void | internal_decode_ofs_word (uint32_t ofsm, ra8_wdt_ofs_decoded_t *out) |
| Decode the seven WDT fields out of a resolved OFSm word. | |
| 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. | |
Variables | |
| static const char * | s_tag = "WDT" |
| Module log tag. | |
| static ra8_wdt_sub_t | s_wdt_subs [k_ra8_wdt_max_subs] |
| Dispatch table of registered subscribers. | |
| static ra8_wdt_ofs_reader_fn_t | s_ofs_reader = internal_default_ofs_reader |
| Active OFSm reader hook (dependency-inverted for test isolation). | |
Software Watchdog Timer (WDT) driver implementation.
Register-start-mode driver for the RA8D2 WDT (HUM Ch 27, p 1256-1270). The companion IWDT lives in ra8_iwdt.c; do not confuse the two.
In auto-start mode the OFS0 option-setting register (HUM Ch 7) latches every period / clock-divider / window / reset-vs-NMI / Sleep-stop bit before this driver runs, and the runtime WDTCR / WDTRCR / WDTCSTPR registers become read-only-as-zero. This driver therefore makes ra8_wdt_init()'s register writes harmless no-ops in that mode while still issuing the first refresh – so the same call site works in either configuration. The decoded OFSm view is exposed by ra8_wdt_ofs_get() so the application can introspect what the boot ROM latched.
In register-start mode (OFS0.WDT0STRT = 1) the same ra8_wdt_init() writes WDTCR / WDTRCR / WDTCSTPR exactly once and then refreshes WDTRR to arm the counter. HUM Ch 27.3.2 limits these three control registers to a single post-reset write, which the driver respects implicitly by exposing only one init entry point.
The WDT underflow / refresh-error event is not an IELSR-routed peripheral interrupt – it is a non-maskable interrupt source on the ICU's NMIER (HUM Ch 14.2.14 p 542 lists WDTEN at bit 1). ra8_wdt_install_nmi enables that bit (and clears any stale status); the dispatch entry point ra8_wdt_dispatch is what the NMI handler calls.
The driver maintains a static k_ra8_wdt_max_subs slot table so several modules (state-of-health logger, crash recorder, app cleanup task, ...) can fan-out the same event without any module owning the single callback slot exclusively. The legacy single- callback ra8_wdt_attach_handler still works – it owns one dedicated slot in the same table.
Every register access carries a HUM Ch 27.x citation.
Definition in file ra8_wdt.c.
| enum ra8_wdt_legacy_slot_t : uint8_t |
Slot reserved for the legacy single-callback API.
ra8_wdt_attach_handler shares the same dispatch table as the multi-subscriber API but always lives in slot 0; that way both APIs can coexist without one tearing down the other's entry.
| Enumerator | |
|---|---|
| k_ra8_wdt_legacy_slot | RA8 wdt legacy slot. |
| enum ra8_wdt_status_combined_t : uint16_t |
|
static |
Reject CKS encodings the silicon marks as "Setting prohibited".
| [in] | div | Caller-supplied divider value. |
See implementation.
| k_ra8_ok | Operation succeeded. |
Definition at line 191 of file ra8_wdt.c.
References 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, and RA8_INTERNAL.
Referenced by ra8_wdt_init().
|
static |
Decode the seven WDT fields out of a resolved OFSm word.
Field positions are identical for OFS0's WDT0* fields (HUM Ch 7.2.1 p 280) and OFS3's WDT1* fields (HUM Ch 7.2.6 p 287), so one decoder serves both instances.
| [in] | ofsm | Resolved 32-bit option word. |
| [out] | out | Receives the decoded view. |
Definition at line 802 of file ra8_wdt.c.
References ra8_wdt_ofs_decoded_t::auto_start, ra8_wdt_ofs_decoded_t::cfg, ra8_wdt_cfg_t::clock_div, k_ra8_wdt_ofs_mask_cks, k_ra8_wdt_ofs_mask_rpes, k_ra8_wdt_ofs_mask_rpss, k_ra8_wdt_ofs_mask_rstirqs, k_ra8_wdt_ofs_mask_stpctl, k_ra8_wdt_ofs_mask_strt, k_ra8_wdt_ofs_mask_tops, k_ra8_wdt_ofs_shift_cks, k_ra8_wdt_ofs_shift_rpes, k_ra8_wdt_ofs_shift_rpss, k_ra8_wdt_ofs_shift_rstirqs, k_ra8_wdt_ofs_shift_stpctl, k_ra8_wdt_ofs_shift_strt, k_ra8_wdt_ofs_shift_tops, k_ra8_wdt_ofs_strt_auto, ra8_wdt_cfg_t::on_expiry, RA8_INTERNAL, ra8_wdt_ofs_decoded_t::start_mode, ra8_wdt_cfg_t::stop_in_sleep, ra8_wdt_cfg_t::timeout, ra8_wdt_cfg_t::window_end, and ra8_wdt_cfg_t::window_start.
Referenced by ra8_wdt_ofs_get().
|
static |
Default OFSm reader: dereferences the address as a 32-bit word.
Used when ra8_wdt_ofs_reader_set(nullptr) is the active reader choice. On the target this maps to a real flash / MRAM read; in unit tests the ra8_wdt_ofs_reader_set hook is normally swapped for a stub that returns canned data.
| [in] | ofs_addr | See implementation. |
| [in] | out_word | See implementation. |
| k_ra8_ok | Operation succeeded. |
Definition at line 142 of file ra8_wdt.c.
References k_ra8_err_null_ptr, k_ra8_ok, and RA8_INTERNAL.
Referenced by ra8_wdt_ofs_reader_set().
|
static |
Report whether an OFS3_SEL word is legal in every multi-bit field.
Checks the four multi-bit selector fields (TOPS, CKS, RPES, RPSS). The three single-bit selectors (STRT, RSTIRQS, STPCTL) cannot be mixed and so are always legal.
| [in] | sel | Raw OFS3_SEL word. |
| true | All four fields are uniform; the word can be used as a mux. |
| false | At least one field holds a prohibited mixed encoding. |
Definition at line 716 of file ra8_wdt.c.
References internal_sel_field_uniform(), k_ra8_wdt_ofs_mask_cks, k_ra8_wdt_ofs_mask_rpes, k_ra8_wdt_ofs_mask_rpss, k_ra8_wdt_ofs_mask_tops, k_ra8_wdt_ofs_shift_cks, k_ra8_wdt_ofs_shift_rpes, k_ra8_wdt_ofs_shift_rpss, k_ra8_wdt_ofs_shift_tops, and RA8_INTERNAL.
Referenced by internal_read_wdt1_word().
|
static |
Pack a ra8_wdt_cfg_t into a 16-bit WDTCR word.
| [in] | cfg | Caller-validated configuration block. |
See implementation.
| k_ra8_ok | Operation succeeded. |
Definition at line 256 of file ra8_wdt.c.
References ra8_wdt_cfg_t::clock_div, k_ra8_wdt_mask_cks, k_ra8_wdt_mask_rpes, k_ra8_wdt_mask_rpss, k_ra8_wdt_mask_tops, k_ra8_wdt_shift_cks, k_ra8_wdt_shift_rpes, k_ra8_wdt_shift_rpss, k_ra8_wdt_shift_tops, RA8_INTERNAL, ra8_wdt_cfg_t::timeout, ra8_wdt_cfg_t::window_end, and ra8_wdt_cfg_t::window_start.
Referenced by ra8_wdt_init().
|
static |
Resolve WDT1's effective option word from the OFS3 family.
WDT1's boot configuration is not a single word. HUM Ch 7.2.7 p 289 makes OFS3_SEL a per-field selector between the secure copy OFS3_SEC and the non-secure copy OFS3: a selector bit of 0 takes the field from OFS3_SEC, 1 takes it from OFS3. Because each selector bit occupies the same position as the field it governs, the resolution is a bitwise mux over k_ra8_wdt_ofs_field_mask.
| [out] | out_word | Receives the resolved 32-bit option word. |
| k_ra8_ok | Resolved. |
| k_ra8_err_null_ptr | out_word was null. |
| k_ra8_err_invalid_state | OFS3_SEL holds a prohibited encoding. |
| k_ra8_err_* | Whatever the reader hook returned. |
Definition at line 751 of file ra8_wdt.c.
References internal_ofs3_sel_is_legal(), k_ra8_err_invalid_state, k_ra8_err_null_ptr, k_ra8_ofs3_addr, k_ra8_ofs3_sec_addr, k_ra8_ofs3_sel_addr, k_ra8_ok, k_ra8_wdt_ofs_field_mask, RA8_INTERNAL, ra8_log_error, s_ofs_reader, and s_tag.
Referenced by ra8_wdt_ofs_get().
|
static |
Report whether one multi-bit OFS3_SEL field holds a legal encoding.
HUM Ch 7.2.7 p 289 permits only all-zeroes (select OFS3_SEC) or all-ones (select OFS3) in each multi-bit selector field; every mixed encoding is marked "Setting prohibit". A prohibited value leaves the hardware's choice undefined, so it must be rejected rather than decoded.
| [in] | sel | Raw OFS3_SEL word. |
| [in] | shift | Bit position of the field's low bit. |
| [in] | mask | Field width mask, pre-shift (e.g. 0x3 for a 2-bit field). |
| true | The field is all-zeroes or all-ones. |
| false | The field is a prohibited mixed encoding. |
Definition at line 682 of file ra8_wdt.c.
References RA8_INTERNAL.
Referenced by internal_ofs3_sel_is_legal().
|
static |
Clear every subscriber slot.
See implementation.
Definition at line 283 of file ra8_wdt.c.
References k_ra8_wdt_max_subs, RA8_INTERNAL, and s_wdt_subs.
Referenced by ra8_wdt_deinit().
|
static |
Reject TOPS encodings outside the documented 2-bit range.
| [in] | sel | Caller-supplied timeout selector. |
See implementation.
| k_ra8_ok | Operation succeeded. |
Definition at line 223 of file ra8_wdt.c.
References k_ra8_wdt_timeout_1024, k_ra8_wdt_timeout_16384, k_ra8_wdt_timeout_4096, k_ra8_wdt_timeout_8192, and RA8_INTERNAL.
Referenced by ra8_wdt_init().
|
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.
| [in] | fn | Callback fn (may be nullptr to clear). |
| [in] | ctx | Context pointer forwarded to fn. |
| k_ra8_ok | Slot updated. |
| k_ra8_err_no_mem | Subscriber table full and a non-null fn was supplied (theoretical). |
Definition at line 519 of file ra8_wdt.c.
References k_ra8_ok, k_ra8_wdt_legacy_slot, and s_wdt_subs.
|
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.
| k_ra8_ok | Always succeeds. |
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().
|
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).
| [in] | mask | Bit mask of flags to clear (any combination of k_ra8_wdt_status_underflow / ..._refresh). |
| k_ra8_ok | Targeted flags read 0 within budget. |
| k_ra8_err_invalid_arg | mask outside the legal flag bits. |
| k_ra8_err_hw_timeout | Flag still latched after k_ra8_wdt_clear_max_polls. |
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.
|
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.
| k_ra8_ok | Always succeeds. |
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.
| 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.
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.
|
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.
| k_ra8_ok | Always succeeds. |
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.
|
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.
| k_ra8_ok | Always succeeds. |
Definition at line 637 of file ra8_wdt.c.
References k_ra8_ok, ra8_wdt(), and r_wdt_regs_t::WDTCSTPR.
|
nodiscard |
Read the live CNTVAL[13:0] down-counter value.
| [out] | out_count | Receives 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). |
| k_ra8_ok | Counter read. |
| k_ra8_err_null_ptr | out_count was null. |
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().
|
nodiscard |
Read the WDTSR status flag bits.
| [out] | out_mask | Receives k_ra8_wdt_status_underflow and / or k_ra8_wdt_status_refresh (others = 0). |
| k_ra8_ok | Status read. |
| k_ra8_err_null_ptr | out_mask was null. |
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.
|
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:
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.
| [in] | cfg | Pointer to the configuration block. |
| k_ra8_ok | Counter armed. |
| k_ra8_err_null_ptr | cfg was null. |
| k_ra8_err_invalid_arg | cfg->clock_div is not one of the legal CKS encodings. |
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().
|
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.
| k_ra8_ok | Always succeeds (the underlying ra8_icu_nmi_enable only OR's into the register). |
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().
|
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:
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.
| [in] | which | Instance whose OFSm word should be decoded. |
| [out] | out | Receives the decoded view. |
| k_ra8_ok | Decoded. |
| k_ra8_err_null_ptr | out was null. |
| k_ra8_err_invalid_arg | which is not a known instance. |
| k_ra8_err_invalid_state | which 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. |
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.
|
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.
| [in] | reader | New reader function or nullptr for default. |
Definition at line 651 of file ra8_wdt.c.
References internal_default_ofs_reader(), k_ra8_ok, and s_ofs_reader.
|
nodiscard |
Decode a ra8_wdt_clock_div_t into its numeric divisor.
| [in] | div | CKS field (k_ra8_wdt_clkdiv_*). |
| [out] | out_divisor | Receives the divisor in {4, 64, 128, 512, 2048, 8192} per HUM Ch 27.2.2 p 1258. |
| k_ra8_ok | Decoded. |
| k_ra8_err_null_ptr | out_divisor was null. |
| k_ra8_err_invalid_arg | div not a legal CKS encoding. |
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().
| 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.
Definition at line 350 of file ra8_wdt.c.
References ra8_wdt_refresh().
Referenced by internal_default_refresh(), and ra8_nsc_wdt_refresh().
|
nodiscard |
Refresh a specific WDT instance.
| [in] | which | Instance to refresh (k_ra8_wdt0 or k_ra8_wdt1). |
| k_ra8_ok | Counter refreshed. |
| k_ra8_err_invalid_arg | which not a known instance. |
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().
|
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.
| [in] | fn | Callback. Must not be nullptr. |
| [in] | ctx | Caller-supplied pointer forwarded to fn on every dispatch. |
| [out] | out_slot | Receives the slot index (0..k_ra8_wdt_max_subs-1) assigned to this subscriber. May be nullptr if the caller doesn't need it. |
| k_ra8_ok | Subscriber installed. |
| k_ra8_err_null_ptr | fn was null. |
| k_ra8_err_no_mem | All k_ra8_wdt_max_subs slots are taken. |
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.
| 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.
| k_ra8_ok | Operation succeeded. |
Definition at line 563 of file ra8_wdt.c.
References k_ra8_wdt_max_subs, and s_wdt_subs.
|
nodiscard |
Decode a ra8_wdt_timeout_sel_t into its cycle count.
| [in] | sel | TOPS field (k_ra8_wdt_timeout_*). |
| [out] | out_cycles | Receives the cycle count (1024 / 4096 / 8192 / 16384) per HUM Ch 27.2.2 Table 27.2 p 1259. |
| k_ra8_ok | Decoded. |
| k_ra8_err_null_ptr | out_cycles was null. |
| k_ra8_err_invalid_arg | sel outside 0..3. |
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().
|
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.
| [in] | sel | TOPS field. |
| [in] | div | CKS field. |
| [out] | out_pclkb_cycles | Receives the product. |
| k_ra8_ok | Computed. |
| k_ra8_err_null_ptr | out_pclkb_cycles was null. |
| k_ra8_err_invalid_arg | sel or div invalid. |
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.
|
nodiscard |
Disable the WDT bit in NMIER (counterpart to ra8_wdt_install_nmi).
| k_ra8_ok | Always succeeds. |
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().
|
nodiscard |
Remove a previously-registered subscriber.
| [in] | slot | Slot index returned by ra8_wdt_subscribe. |
| k_ra8_ok | Slot freed. |
| k_ra8_err_invalid_arg | slot out of range. |
| k_ra8_err_not_found | Slot was already empty. |
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.
|
static |
Active OFSm reader hook (dependency-inverted for test isolation).
Definition at line 159 of file ra8_wdt.c.
Referenced by internal_read_wdt1_word(), ra8_wdt_ofs_get(), and ra8_wdt_ofs_reader_set().
|
static |
|
static |
Dispatch table of registered subscribers.
Static storage; cleared at C startup and again during ra8_wdt_deinit. Slot 0 is owned by the legacy single-callback API; slots 1..k_ra8_wdt_max_subs-1 are claimed by ra8_wdt_subscribe.
Definition at line 120 of file ra8_wdt.c.
Referenced by internal_subs_clear_all(), ra8_wdt_attach_handler(), ra8_wdt_dispatch(), ra8_wdt_subscribe(), ra8_wdt_subscriber_count(), and ra8_wdt_unsubscribe().