ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_wdt.c
Go to the documentation of this file.
1
55
56#include "ra8_wdt.h"
57
58#include <stdint.h>
59
60#include "ra8_attributes.h"
61#include "ra8_check.h"
62#include "ra8_err.h"
63#include "ra8_hw_err.h"
64#include "ra8_icu.h"
65#include "ra8_log.h"
66#include "ra8_ofs.h"
67#include "ra8_wdt_regs.h"
68
79static const char* s_tag = "WDT";
80
90typedef struct {
92 void* ctx;
94
104typedef enum : uint8_t {
107
121
142RA8_INTERNAL static ra8_err_t internal_default_ofs_reader(uintptr_t ofs_addr, uint32_t* out_word)
143{
144 if (out_word == nullptr) {
145 return k_ra8_err_null_ptr;
146 }
147 /* HUM Ch 7.1 "Overview" Figure 7.1 "Option-setting memory area" p 279 --
148 * the option-setting words live in the extra-MRAM configuration setting
149 * area and are ordinary readable memory. */
150 const volatile uint32_t* src = (const volatile uint32_t*)ofs_addr;
151 *out_word = *src;
152 return k_ra8_ok;
153}
154
160
169
170/* =============================================================================
171 * Internal helpers
172 * =============================================================================
173 */
174
192{
193 /* HUM Ch 27.2.2 "WDTCR : WDT Control Register", p 1258 -- legal
194 * CKS[3:0] encodings are 0x1, 0x4, 0x6, 0x7, 0x8, 0xF only. */
195 switch (div) {
202 return true;
203 default:
204 return false;
205 }
206}
207
224{
225 /* HUM Ch 27.2.2 "WDTCR" p 1259 */
226 bool ok = false;
227 switch (sel) {
232 ok = true;
233 break;
234 default:
235 ok = false;
236 break;
237 }
238 return ok;
239}
240
257{
258 /* HUM Ch 27.2.2 "WDTCR : WDT Control Register", p 1258 */
259 const uint16_t tops = (uint16_t)((uint16_t)cfg->timeout & k_ra8_wdt_mask_tops);
260 const uint16_t cks = (uint16_t)((uint16_t)cfg->clock_div & k_ra8_wdt_mask_cks);
261 const uint16_t rpes = (uint16_t)((uint16_t)cfg->window_end & k_ra8_wdt_mask_rpes);
262 const uint16_t rpss = (uint16_t)((uint16_t)cfg->window_start & k_ra8_wdt_mask_rpss);
263
264 uint16_t word = 0U;
265 word |= (uint16_t)(tops << k_ra8_wdt_shift_tops);
266 word |= (uint16_t)(cks << k_ra8_wdt_shift_cks);
267 word |= (uint16_t)(rpes << k_ra8_wdt_shift_rpes);
268 word |= (uint16_t)(rpss << k_ra8_wdt_shift_rpss);
269 return word;
270}
271
284{
285 for (uint8_t i = 0U; i < k_ra8_wdt_max_subs; ++i) {
286 s_wdt_subs[i].fn = nullptr;
287 s_wdt_subs[i].ctx = nullptr;
288 }
289}
290
291/* =============================================================================
292 * Lifecycle
293 * =============================================================================
294 */
295
296[[nodiscard]] ra8_err_t ra8_wdt_init(const ra8_wdt_cfg_t* cfg)
297{
298 RA8_CHECK_NULL_PTR(cfg, s_tag, "cfg must not be nullptr");
301 }
304 }
305
306 volatile r_wdt_regs_t* reg = ra8_wdt();
307
308 /* HUM Ch 27.2.2 "WDTCR : WDT Control Register", p 1258 -- one
309 * 16-bit transaction commits the timeout / divider / window. */
310 reg->WDTCR = internal_pack_wdtcr(cfg);
311
312 /* HUM Ch 27.2.4 "WDTRCR : WDT Reset Control Register", p 1262 --
313 * RSTIRQS selects internal reset (1) vs NMI / IRQ (0) on
314 * underflow or refresh-error. */
315 reg->WDTRCR =
317
318 /* HUM Ch 27.2.5 "WDTCSTPR : WDT Count Stop Control Register",
319 * p 1262 -- SLCSTP halts the counter on Sleep / Deep Sleep. */
320 reg->WDTCSTPR =
322
323 /* HUM Ch 27.2.1 "WDTRR : WDT Refresh Register", p 1257 -- the
324 * 0x00 / 0xFF unlock sequence is what arms the down-counter in
325 * register-start mode, and is harmless in auto-start mode. */
327
328 ra8_log_info(s_tag, "wdt_init armed");
329 return k_ra8_ok;
330}
331
332[[nodiscard]] ra8_err_t ra8_wdt_deinit(void)
333{
334 volatile r_wdt_regs_t* reg = ra8_wdt();
335 /* HUM Ch 27.2.5 "WDTCSTPR : WDT Count Stop Control Register",
336 * p 1262 -- the strongest "off" the driver can request is to halt
337 * the counter while the CPU is asleep. The peripheral itself
338 * cannot be disarmed once started. */
341 ra8_log_info(s_tag, "wdt_deinit (sleep-stop set)");
342 return k_ra8_ok;
343}
344
345/* =============================================================================
346 * Refresh
347 * =============================================================================
348 */
349
351{
352 /* HUM Ch 27.2.1 "WDTRR : WDT Refresh Register", p 1257 */
354}
355
357{
358 if ((uint8_t)which >= k_ra8_wdt_instance_count) {
360 }
361 /* HUM Ch 27.2.1 "WDTRR : WDT Refresh Register", p 1257 */
363 return k_ra8_ok;
364}
365
366/* =============================================================================
367 * Status read / clear / counter
368 * =============================================================================
369 */
370
371[[nodiscard]] ra8_err_t ra8_wdt_get_status(uint16_t* out_mask)
372{
373 RA8_CHECK_NULL_PTR(out_mask, s_tag, "out_mask must not be nullptr");
374 /* HUM Ch 27.2.3 "WDTSR : WDT Status Register", p 1260 */
375 *out_mask = (uint16_t)(ra8_wdt()->WDTSR & k_ra8_wdt_status_all);
376 return k_ra8_ok;
377}
378
380{
381 volatile r_wdt_regs_t* reg = ra8_wdt();
382 /* HUM Ch 27.2.3 "WDTSR : WDT Status Register", p 1260 -- UNDFF /
383 * REFEF are write-0-to-clear; writing 1 has no effect. We mask
384 * out the flag bits and write the result back. */
385 reg->WDTSR = (uint16_t)(reg->WDTSR & (uint16_t)~k_ra8_wdt_status_all);
386 return k_ra8_ok;
387}
388
389[[nodiscard]] ra8_err_t ra8_wdt_clear_status_blocking(uint16_t mask)
390{
391 if ((mask & ~k_ra8_wdt_status_all) != 0U) {
393 }
394 if (mask == k_ra8_wdt_status_none) {
395 return k_ra8_ok;
396 }
397
398 volatile r_wdt_regs_t* reg = ra8_wdt();
399
400 /* HUM Ch 27.2.3 "WDTSR : WDT Status Register", p 1261 -- W0C
401 * sequence: write the inverse of the bits we want to clear back
402 * into WDTSR, then poll until the targeted bits read 0. The
403 * (N + 1) PCLKB cycle latency is bounded by the divider; we
404 * cap our polls at k_ra8_wdt_clear_max_polls (16384). */
405 for (uint32_t poll = 0U; poll < k_ra8_wdt_clear_max_polls; ++poll) {
406 /* Build a write value in which only the bits NOT in `mask`
407 * remain set; those are the bits we want to leave untouched.
408 * Bits inside `mask` are written 0 to clear. */
409 const uint16_t write_val = (uint16_t)(reg->WDTSR & (uint16_t)~mask);
410 reg->WDTSR = write_val;
411
412#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
413 /* HUM Ch 27.2.3 "WDTSR : WDT Status Register" p 1260 */
414 const bool cleared = ra8_fake_mmio_poll(&reg->WDTSR, poll, ((uint16_t)reg->WDTSR & mask) == 0U);
415#else
416 /* HUM Ch 27.2.3 "WDTSR : WDT Status Register" p 1260 */
417 const bool cleared = ((uint16_t)reg->WDTSR & mask) == 0U;
418#endif
419 if (cleared) {
420 return k_ra8_ok;
421 }
422 }
423
424 ra8_log_error(s_tag, "wdt_clear_status_blocking timed out");
426}
427
428[[nodiscard]] ra8_err_t ra8_wdt_get_counter(uint16_t* out_count)
429{
430 RA8_CHECK_NULL_PTR(out_count, s_tag, "out_count must not be nullptr");
431 /* HUM Ch 27.2.3 "WDTSR : WDT Status Register", p 1260 -- the live
432 * down-counter occupies CNTVAL[13:0]. */
433 *out_count = (uint16_t)(ra8_wdt()->WDTSR & k_ra8_wdt_sr_cnt_mask);
434 return k_ra8_ok;
435}
436
437/* =============================================================================
438 * Timeout decoding (FSP timeoutGet analogue)
439 * =============================================================================
440 */
441
442[[nodiscard]] ra8_err_t ra8_wdt_timeout_cycles_get(ra8_wdt_timeout_sel_t sel, uint16_t* out_cycles)
443{
444 RA8_CHECK_NULL_PTR(out_cycles, s_tag, "out_cycles must not be nullptr");
445 /* HUM Ch 27.2.2 "WDTCR" p 1259 */
446 switch (sel) {
448 *out_cycles = k_ra8_wdt_cycles_1024;
449 return k_ra8_ok;
451 *out_cycles = k_ra8_wdt_cycles_4096;
452 return k_ra8_ok;
454 *out_cycles = k_ra8_wdt_cycles_8192;
455 return k_ra8_ok;
457 *out_cycles = k_ra8_wdt_cycles_16384;
458 return k_ra8_ok;
459 default:
461 }
462}
463
464[[nodiscard]] ra8_err_t ra8_wdt_pclkb_divisor(ra8_wdt_clock_div_t div, uint16_t* out_divisor)
465{
466 RA8_CHECK_NULL_PTR(out_divisor, s_tag, "out_divisor must not be nullptr");
467 /* HUM Ch 27.2.2 "WDTCR" p 1258 */
468 switch (div) {
470 *out_divisor = k_ra8_wdt_div_value_4;
471 return k_ra8_ok;
473 *out_divisor = k_ra8_wdt_div_value_64;
474 return k_ra8_ok;
476 *out_divisor = k_ra8_wdt_div_value_128;
477 return k_ra8_ok;
479 *out_divisor = k_ra8_wdt_div_value_512;
480 return k_ra8_ok;
482 *out_divisor = k_ra8_wdt_div_value_2048;
483 return k_ra8_ok;
485 *out_divisor = k_ra8_wdt_div_value_8192;
486 return k_ra8_ok;
487 default:
489 }
490}
491
494 uint32_t* out_pclkb_cycles)
495{
496 RA8_CHECK_NULL_PTR(out_pclkb_cycles, s_tag, "out_pclkb_cycles must not be nullptr");
497
498 uint16_t cycles = 0U;
499 uint16_t divisor = 0U;
500 const ra8_err_t e1 = ra8_wdt_timeout_cycles_get(sel, &cycles);
501 if (e1 != k_ra8_ok) {
502 return e1;
503 }
504 const ra8_err_t e2 = ra8_wdt_pclkb_divisor(div, &divisor);
505 if (e2 != k_ra8_ok) {
506 return e2;
507 }
508
509 /* Largest product is 16384 * 8192 = 134_217_728 -- fits 32 bits. */
510 *out_pclkb_cycles = (uint32_t)cycles * (uint32_t)divisor;
511 return k_ra8_ok;
512}
513
514/* =============================================================================
515 * Single + multi-subscriber callback API
516 * =============================================================================
517 */
518
520{
521 /* The legacy attach API maps to the reserved slot 0 -- that way
522 * both APIs share the same dispatch table without stomping each
523 * other. ``fn == nullptr`` clears the slot. */
526 return k_ra8_ok;
527}
528
529[[nodiscard]] ra8_err_t ra8_wdt_subscribe(ra8_wdt_event_fn_t fn, void* ctx, uint8_t* out_slot)
530{
531 RA8_CHECK_NULL_PTR(fn, s_tag, "fn must not be nullptr");
532
533 /* Walk the table starting at the first non-legacy slot; slot 0 is
534 * reserved for ``ra8_wdt_attach_handler``. */
535 for (uint8_t i = 1U; i < k_ra8_wdt_max_subs; ++i) {
536 if (s_wdt_subs[i].fn == nullptr) {
537 s_wdt_subs[i].fn = fn;
538 s_wdt_subs[i].ctx = ctx;
539 if (out_slot != nullptr) {
540 *out_slot = i;
541 }
542 return k_ra8_ok;
543 }
544 }
545
546 ra8_log_error(s_tag, "wdt_subscribe table full");
547 return k_ra8_err_no_mem;
548}
549
550[[nodiscard]] ra8_err_t ra8_wdt_unsubscribe(uint8_t slot)
551{
552 if (slot >= k_ra8_wdt_max_subs) {
554 }
555 if (s_wdt_subs[slot].fn == nullptr) {
556 return k_ra8_err_not_found;
557 }
558 s_wdt_subs[slot].fn = nullptr;
559 s_wdt_subs[slot].ctx = nullptr;
560 return k_ra8_ok;
561}
562
564{
565 uint8_t count = 0U;
566 for (uint8_t i = 0U; i < k_ra8_wdt_max_subs; ++i) {
567 if (s_wdt_subs[i].fn != nullptr) {
568 ++count;
569 }
570 }
571 return count;
572}
573
576{
577 volatile r_wdt_regs_t* reg = ra8_wdt();
578 /* HUM Ch 27.2.3 "WDTSR : WDT Status Register", p 1260 -- snapshot
579 * the flags before clearing, then hand the latched mask to every
580 * registered subscriber. */
581 const uint16_t mask = (uint16_t)(reg->WDTSR & k_ra8_wdt_status_all);
582 reg->WDTSR = (uint16_t)(reg->WDTSR & (uint16_t)~mask);
583
584 for (uint8_t i = 0U; i < k_ra8_wdt_max_subs; ++i) {
585 const ra8_wdt_event_fn_t fn = s_wdt_subs[i].fn;
586 void* const ctx = s_wdt_subs[i].ctx;
587 if (fn != nullptr) {
588 fn(ctx, mask);
589 }
590 }
591}
592
593/* =============================================================================
594 * NMI vector wiring (HUM Ch 14.2.14 p 542)
595 * =============================================================================
596 */
597
599{
600 /* HUM Ch 14.2.15 "NMICLR" p 544 -- W1C any stale WDT NMI status
601 * before unmasking the source so we don't immediately fire on a
602 * pre-existing latched flag. */
604 if (e_clr != k_ra8_ok) {
605 return e_clr;
606 }
607 /* HUM Ch 14.2.14 "NMIER" p 542 -- WDTEN bit 1 (0x2) routes the
608 * WDT0 underflow / refresh-error to the Cortex-M85 NMI line. */
610}
611
613{
614 /* HUM Ch 14.2.14 "NMIER" p 542 */
616 if (e_dis != k_ra8_ok) {
617 return e_dis;
618 }
619 /* HUM Ch 14.2.15 "NMICLR" p 544 */
621}
622
623/* =============================================================================
624 * Sleep-mode stop control
625 * =============================================================================
626 */
627
628[[nodiscard]] ra8_err_t ra8_wdt_enter_stop(void)
629{
630 volatile r_wdt_regs_t* reg = ra8_wdt();
631 /* HUM Ch 27.2.5 "WDTCSTPR : WDT Count Stop Control Register",
632 * p 1262 -- set SLCSTP to halt the counter on Sleep entry. */
634 return k_ra8_ok;
635}
636
637[[nodiscard]] ra8_err_t ra8_wdt_exit_stop(void)
638{
639 volatile r_wdt_regs_t* reg = ra8_wdt();
640 /* HUM Ch 27.2.5 "WDTCSTPR : WDT Count Stop Control Register",
641 * p 1262 -- clear SLCSTP so the counter keeps running in Sleep. */
642 reg->WDTCSTPR = 0U;
643 return k_ra8_ok;
644}
645
646/* =============================================================================
647 * OFS0 / OFS3 read-only decode
648 * =============================================================================
649 */
650
652{
653 s_ofs_reader = (reader == nullptr) ? internal_default_ofs_reader : reader;
654 return k_ra8_ok;
655}
656
682RA8_INTERNAL static bool internal_sel_field_uniform(uint32_t sel, uint32_t shift, uint32_t mask)
683{
684 const uint32_t field = (sel >> shift) & mask;
685 return (field == 0U) || (field == mask);
686}
687
723
752{
753 /* Single-exit (MISRA C 2012 Rule 15.5): the three reads chain on ``e``
754 * rather than returning early, so a failure at any word falls straight
755 * through to the one return without touching ``*out_word``. */
757 if (out_word != nullptr) {
758 uint32_t sel = 0U;
759 uint32_t sec = 0U;
760 uint32_t nonsec = 0U;
761
763 if (e == k_ra8_ok) {
765 }
766 if (e == k_ra8_ok) {
767 e = s_ofs_reader(k_ra8_ofs3_addr, &nonsec);
768 }
769 if (e == k_ra8_ok) {
771 const uint32_t mux = sel & (uint32_t)k_ra8_wdt_ofs_field_mask;
772 *out_word = (nonsec & mux) | (sec & ~mux);
773 } else {
774 ra8_log_error(s_tag, "OFS3_SEL holds a prohibited mixed encoding");
776 }
777 }
778 }
779 return e;
780}
781
803{
804 const uint8_t strt = (uint8_t)((ofsm >> k_ra8_wdt_ofs_shift_strt) & k_ra8_wdt_ofs_mask_strt);
805 const uint8_t tops = (uint8_t)((ofsm >> k_ra8_wdt_ofs_shift_tops) & k_ra8_wdt_ofs_mask_tops);
806 const uint8_t cks = (uint8_t)((ofsm >> k_ra8_wdt_ofs_shift_cks) & k_ra8_wdt_ofs_mask_cks);
807 const uint8_t rpes = (uint8_t)((ofsm >> k_ra8_wdt_ofs_shift_rpes) & k_ra8_wdt_ofs_mask_rpes);
808 const uint8_t rpss = (uint8_t)((ofsm >> k_ra8_wdt_ofs_shift_rpss) & k_ra8_wdt_ofs_mask_rpss);
809 const uint8_t rstirqs =
811 const uint8_t stpctl =
813
814 out->cfg.timeout = (ra8_wdt_timeout_sel_t)tops;
818 out->cfg.on_expiry = (ra8_wdt_reset_ctrl_t)rstirqs;
820 out->start_mode = (ra8_wdt_ofs_strt_t)strt;
822}
823
825{
826 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
827 if ((uint8_t)which >= k_ra8_wdt_instance_count) {
829 }
830
831 /* HUM Ch 27.3.8 Table 27.5 "Association between Option Function Select
832 * Register m (OFSm) and the WDT registers" p 1269 -- in auto-start mode the
833 * seven WDT fields come from OFSm rather than from WDTCR/WDTRCR/WDTCSTPR.
834 *
835 * WDT0 takes them from OFS0 (HUM Ch 7.2.1 p 280), a single secure-region
836 * word. WDT1 takes them from OFS3/OFS3_SEC selected field-by-field by
837 * OFS3_SEL (HUM Ch 7.2.6 p 287, Ch 7.2.7 p 289), so it needs three reads.
838 *
839 * The WDT driver never writes OFSm; only ``ra8_ofs.c`` emits the
840 * option-setting sections. Reads go through the hook so tests and
841 * non-secure callers can supply their own transport. */
842 uint32_t ofsm = 0U;
843 const ra8_err_t e =
845 if (e != k_ra8_ok) {
846 return e;
847 }
848
849 internal_decode_ofs_word(ofsm, out);
850 return k_ra8_ok;
851}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_ISR_SAFE
The function is callable from interrupt context.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
Error Code Definitions for ra8-firmware.
@ k_ra8_err_no_mem
Static buffer exhausted (no dynamic memory on this project).
Definition ra8_err.h:142
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
Definition ra8_err.h:161
@ k_ra8_err_hw_timeout
Hardware timed out waiting for a flag or handshake.
Definition ra8_err.h:304
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
Definition ra8_err.h:478
@ k_ra8_err_not_found
Requested item not found (lookup / search missed).
Definition ra8_err.h:173
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Bounded wait-flag primitives for RA8D2 HAL drivers.
Interrupt Control Unit driver (IRQ pins, NMI).
ra8_err_t ra8_icu_nmi_enable(uint32_t mask)
Enable one or more NMI sources by OR'ing into NMIER.
Definition ra8_icu.c:119
ra8_err_t ra8_icu_nmi_clear(uint32_t mask)
Clear pending NMI status flags via NMICLR (HUM 14.2.15 p 544).
Definition ra8_icu.c:135
ra8_err_t ra8_icu_nmi_disable(uint32_t mask)
Disable NMI sources by clearing bits in NMIER.
Definition ra8_icu.c:127
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_info(tag, message)
RA8 log info.
Definition ra8_log.h:364
#define ra8_log_error(tag, message)
RA8 log error.
Definition ra8_log.h:335
Option Function Select (OFS) boot-map inventory for the active RA8 device.
@ k_ra8_ofs0_addr
OFS0 – IWDT + WDT0 fields (Secure).
Definition ra8_ofs.h:138
@ k_ra8_ofs3_sec_addr
OFS3_SEC – WDT1 fields (Secure).
Definition ra8_ofs.h:142
@ k_ra8_ofs3_addr
OFS3 – WDT1 fields (Non-secure alias).
Definition ra8_ofs.h:140
@ k_ra8_ofs3_sel_addr
OFS3_SEL – per-field S/NS selector.
Definition ra8_ofs.h:144
ra8_err_t ra8_wdt_install_nmi(void)
Enable the WDT bit in NMIER so the NMI line fires on underflow.
Definition ra8_wdt.c:598
ra8_err_t ra8_wdt_uninstall_nmi(void)
Disable the WDT bit in NMIER (counterpart to ra8_wdt_install_nmi).
Definition ra8_wdt.c:612
void ra8_wdt_refresh_deferred(void)
Refresh the software WDT counter (WDT0).
Definition ra8_wdt.c:350
ra8_wdt_status_combined_t
Union of the two WDTSR top-flag bits the driver cares about.
Definition ra8_wdt.c:165
@ k_ra8_wdt_status_all
RA8 wdt status all.
Definition ra8_wdt.c:166
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.
Definition ra8_wdt.c:142
ra8_wdt_legacy_slot_t
Slot reserved for the legacy single-callback API.
Definition ra8_wdt.c:104
@ k_ra8_wdt_legacy_slot
RA8 wdt legacy slot.
Definition ra8_wdt.c:105
static uint16_t internal_pack_wdtcr(const ra8_wdt_cfg_t *cfg)
Pack a ra8_wdt_cfg_t into a 16-bit WDTCR word.
Definition ra8_wdt.c:256
static bool internal_clock_div_is_valid(ra8_wdt_clock_div_t div)
Reject CKS encodings the silicon marks as "Setting prohibited".
Definition ra8_wdt.c:191
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.
Definition ra8_wdt.c:651
static void internal_subs_clear_all(void)
Clear every subscriber slot.
Definition ra8_wdt.c:283
ra8_err_t ra8_wdt_refresh_for(ra8_wdt_instance_t which)
Refresh a specific WDT instance.
Definition ra8_wdt.c:356
ra8_err_t ra8_wdt_exit_stop(void)
Disable counter halt on Sleep entry.
Definition ra8_wdt.c:637
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.
Definition ra8_wdt.c:442
static ra8_err_t internal_read_wdt1_word(uint32_t *out_word)
Resolve WDT1's effective option word from the OFS3 family.
Definition ra8_wdt.c:751
static bool internal_timeout_sel_is_valid(ra8_wdt_timeout_sel_t sel)
Reject TOPS encodings outside the documented 2-bit range.
Definition ra8_wdt.c:223
uint8_t ra8_wdt_subscriber_count(void)
Number of currently-installed subscribers.
Definition ra8_wdt.c:563
ra8_err_t ra8_wdt_init(const ra8_wdt_cfg_t *cfg)
Initialise the WDT in register-start mode.
Definition ra8_wdt.c:296
static ra8_wdt_ofs_reader_fn_t s_ofs_reader
Active OFSm reader hook (dependency-inverted for test isolation).
Definition ra8_wdt.c:159
ra8_err_t ra8_wdt_unsubscribe(uint8_t slot)
Remove a previously-registered subscriber.
Definition ra8_wdt.c:550
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.
Definition ra8_wdt.c:529
ra8_err_t ra8_wdt_get_status(uint16_t *out_mask)
Read the WDTSR status flag bits.
Definition ra8_wdt.c:371
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.
Definition ra8_wdt.c:824
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.
Definition ra8_wdt.c:802
ra8_err_t ra8_wdt_clear_status(void)
Clear the WDTSR underflow / refresh-error flags.
Definition ra8_wdt.c:379
static ra8_wdt_sub_t s_wdt_subs[k_ra8_wdt_max_subs]
Dispatch table of registered subscribers.
Definition ra8_wdt.c:120
ra8_err_t ra8_wdt_deinit(void)
Quiesce the driver into a Sleep-stop posture.
Definition ra8_wdt.c:332
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.
Definition ra8_wdt.c:464
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.
Definition ra8_wdt.c:492
ra8_err_t ra8_wdt_get_counter(uint16_t *out_count)
Read the live CNTVAL[13:0] down-counter value.
Definition ra8_wdt.c:428
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.
Definition ra8_wdt.c:682
ra8_err_t ra8_wdt_enter_stop(void)
Enable counter halt on Sleep entry.
Definition ra8_wdt.c:628
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.
Definition ra8_wdt.c:519
void ra8_wdt_dispatch(void)
Dispatch a WDT event – snapshot WDTSR + fan-out to subscribers.
Definition ra8_wdt.c:575
ra8_err_t ra8_wdt_clear_status_blocking(uint16_t mask)
Clear specific WDTSR flag bits and busy-wait until they read 0.
Definition ra8_wdt.c:389
static bool internal_ofs3_sel_is_legal(uint32_t sel)
Report whether an OFS3_SEL word is legal in every multi-bit field.
Definition ra8_wdt.c:716
Software Watchdog Timer (WDT) driver header.
ra8_wdt_timeout_sel_t
Legal TOPS[1:0] encodings for WDTCR.
Definition ra8_wdt.h:146
@ k_ra8_wdt_timeout_16384
16384 cycles.
Definition ra8_wdt.h:150
@ k_ra8_wdt_timeout_1024
1024 cycles.
Definition ra8_wdt.h:147
@ k_ra8_wdt_timeout_8192
8192 cycles.
Definition ra8_wdt.h:149
@ k_ra8_wdt_timeout_4096
4096 cycles.
Definition ra8_wdt.h:148
ra8_wdt_clock_div_t
Legal CKS[3:0] encodings for WDTCR.
Definition ra8_wdt.h:125
@ k_ra8_wdt_clkdiv_512
PCLKB / 512.
Definition ra8_wdt.h:129
@ k_ra8_wdt_clkdiv_8192
PCLKB / 8192.
Definition ra8_wdt.h:131
@ k_ra8_wdt_clkdiv_4
PCLKB / 4.
Definition ra8_wdt.h:126
@ k_ra8_wdt_clkdiv_2048
PCLKB / 2048.
Definition ra8_wdt.h:130
@ k_ra8_wdt_clkdiv_64
PCLKB / 64.
Definition ra8_wdt.h:127
@ k_ra8_wdt_clkdiv_128
PCLKB / 128.
Definition ra8_wdt.h:128
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.
Definition ra8_wdt.h:918
ra8_wdt_ofs_strt_t
OFSm.WDTnSTRT encoding – auto vs register start mode.
Definition ra8_wdt.h:235
@ k_ra8_wdt_ofs_strt_auto
Auto-start (OFSm-driven).
Definition ra8_wdt.h:236
ra8_wdt_window_start_t
Legal RPSS[1:0] encodings (refresh-permitted window start).
Definition ra8_wdt.h:162
@ k_ra8_wdt_clear_max_polls
16384 reads – safely > 8193.
Definition ra8_wdt.h:279
ra8_wdt_reset_ctrl_t
WDTRCR.RSTIRQS encoding – reset vs NMI on expiry.
Definition ra8_wdt.h:200
@ k_ra8_wdt_on_expiry_reset
RSTIRQS=1 – internal reset.
Definition ra8_wdt.h:202
@ k_ra8_wdt_status_underflow
UNDFF (bit 14).
Definition ra8_wdt.h:249
@ k_ra8_wdt_status_none
No flag set.
Definition ra8_wdt.h:248
@ k_ra8_wdt_status_refresh
REFEF (bit 15).
Definition ra8_wdt.h:250
@ k_ra8_wdt_max_subs
Max simultaneous subscribers.
Definition ra8_wdt.h:264
ra8_wdt_stop_ctrl_t
WDTCSTPR.SLCSTP encoding – counter behaviour in Sleep.
Definition ra8_wdt.h:217
@ k_ra8_wdt_sleep_stop_count
SLCSTP=1 – counter halts in Sleep.
Definition ra8_wdt.h:219
void(* ra8_wdt_event_fn_t)(void *ctx, uint16_t status_mask)
WDT NMI / underflow event callback.
Definition ra8_wdt.h:343
ra8_wdt_window_end_t
Legal RPES[1:0] encodings (refresh-permitted window end).
Definition ra8_wdt.h:181
Watchdog Timer (WDT) register layout for the RA8D2.
static void ra8_wdt_refresh(void)
Refresh the WDT0 instance using the two-byte unlock sequence.
static void ra8_wdt_refresh_instance(ra8_wdt_instance_t which)
Refresh a specific WDT instance.
@ k_ra8_wdt_cycles_1024
TOPS = 0b00.
@ k_ra8_wdt_cycles_8192
TOPS = 0b10.
@ k_ra8_wdt_cycles_16384
TOPS = 0b11.
@ k_ra8_wdt_cycles_4096
TOPS = 0b01.
@ k_ra8_wdt_sr_cnt_mask
CNTVAL[13:0] mask.
@ k_ra8_wdt_ofs_mask_rpss
2-bit field.
@ k_ra8_wdt_ofs_shift_rstirqs
OFSm.WDTRSTIRQS shift.
@ k_ra8_wdt_ofs_shift_tops
OFSm.WDTTOPS shift.
@ k_ra8_wdt_ofs_shift_rpss
OFSm.WDTRPSS shift.
@ k_ra8_wdt_ofs_mask_stpctl
1-bit field.
@ k_ra8_wdt_ofs_mask_tops
2-bit field.
@ k_ra8_wdt_ofs_shift_rpes
OFSm.WDTRPES shift.
@ k_ra8_wdt_ofs_shift_strt
OFSm.WDTSTRT shift.
@ k_ra8_wdt_ofs_shift_stpctl
OFSm.WDTSTPCTL shift.
@ k_ra8_wdt_ofs_mask_strt
1-bit field.
@ k_ra8_wdt_ofs_mask_rpes
2-bit field.
@ k_ra8_wdt_ofs_shift_cks
OFSm.WDTCKS shift.
@ k_ra8_wdt_ofs_mask_cks
4-bit field.
@ k_ra8_wdt_ofs_mask_rstirqs
1-bit field.
@ k_ra8_wdt_ofs_field_mask
Union of all seven fields.
@ k_ra8_wdt_nmier_wdten_mask
NMIER.WDTEN = bit 1.
ra8_wdt_instance_t
Hardware instance selector used by per-instance helpers.
@ k_ra8_wdt0
WDT0 – Cortex-M85 side.
@ k_ra8_wdt_instance_count
Number of WDT instances on RA8D2.
static volatile r_wdt_regs_t * ra8_wdt(void)
Get pointer to WDT0 (the default / M85-side instance).
@ k_ra8_wdt_rcr_rstirqs
RSTIRQS = bit 7 (1 = reset, 0 = NMI / IRQ).
@ k_ra8_wdt_div_value_128
RA8 wdt div value 128.
@ k_ra8_wdt_div_value_2048
RA8 wdt div value 2048.
@ k_ra8_wdt_div_value_8192
RA8 wdt div value 8192.
@ k_ra8_wdt_div_value_4
RA8 wdt div value 4.
@ k_ra8_wdt_div_value_64
RA8 wdt div value 64.
@ k_ra8_wdt_div_value_512
RA8 wdt div value 512.
@ k_ra8_wdt_mask_rpss
RPSS field width (2 bits).
@ k_ra8_wdt_shift_cks
CKS occupies bits 7:4.
@ k_ra8_wdt_mask_tops
TOPS field width (2 bits).
@ k_ra8_wdt_shift_rpss
RPSS occupies bits 13:12.
@ k_ra8_wdt_shift_rpes
RPES occupies bits 9:8.
@ k_ra8_wdt_mask_rpes
RPES field width (2 bits).
@ k_ra8_wdt_shift_tops
TOPS occupies bits 1:0.
@ k_ra8_wdt_mask_cks
CKS field width (4 bits).
@ k_ra8_wdt_cstpr_slcstp
SLCSTP = bit 7 (1 = halt counter in Sleep).
Memory-mapped layout of one WDT instance.
volatile uint16_t WDTCR
+0x02 Control register.
volatile uint8_t WDTCSTPR
+0x08 Count-stop control.
volatile uint16_t WDTSR
+0x04 Status register.
volatile uint8_t WDTRCR
+0x06 Reset control register.
Register-start-mode configuration block.
Definition ra8_wdt.h:305
ra8_wdt_window_start_t window_start
WDTCR.RPSS[1:0] selection.
Definition ra8_wdt.h:308
ra8_wdt_timeout_sel_t timeout
WDTCR.TOPS[1:0] selection.
Definition ra8_wdt.h:306
ra8_wdt_stop_ctrl_t stop_in_sleep
WDTCSTPR.SLCSTP halt-on-Sleep.
Definition ra8_wdt.h:311
ra8_wdt_clock_div_t clock_div
WDTCR.CKS[3:0] selection.
Definition ra8_wdt.h:307
ra8_wdt_reset_ctrl_t on_expiry
WDTRCR.RSTIRQS reset vs IRQ.
Definition ra8_wdt.h:310
ra8_wdt_window_end_t window_end
WDTCR.RPES[1:0] selection.
Definition ra8_wdt.h:309
Decoded view of an OFSm option-setting word.
Definition ra8_wdt.h:327
ra8_wdt_ofs_strt_t start_mode
OFSm.WDTnSTRT (auto vs register start).
Definition ra8_wdt.h:329
ra8_wdt_cfg_t cfg
Decoded period / divider / window / etc.
Definition ra8_wdt.h:328
bool auto_start
Convenience flag = (start_mode == auto).
Definition ra8_wdt.h:330
One entry in the multi-subscriber dispatch table.
Definition ra8_wdt.c:90
ra8_wdt_event_fn_t fn
Subscriber callback or nullptr if slot is free.
Definition ra8_wdt.c:91
void * ctx
Opaque pointer forwarded to fn.
Definition ra8_wdt.c:92