ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_lpm.c
Go to the documentation of this file.
1
41
42#include "ra8_lpm.h"
43
44#include <stdint.h>
45
46#include "ra8_attributes.h"
47#include "ra8_check.h"
48#include "ra8_err.h"
49#include "ra8_hw_intrinsics.h"
50#include "ra8_log.h"
51#include "ra8_lpm_regs.h"
53
58static const char* s_tag = "LPM";
59
61typedef enum : uint16_t {
64
75
84
94
113{
114 ra8_hw_dsb();
115 ra8_hw_wfi();
116}
117
139RA8_INTERNAL static inline void internal_set_sleepdeep(bool enable)
140{
141 /* Arm Cortex-M85 SCB->SCR (Armv8-M System Control Space; no HUM
142 * chapter -- architectural register). */
143 volatile uint32_t* scr = ra8_lpm_scb_scr();
144 if (enable) {
145 *scr |= (uint32_t)k_ra8_lpm_scb_scr_sleepdeep;
146 } else {
147 *scr &= ~(uint32_t)k_ra8_lpm_scb_scr_sleepdeep;
148 }
149}
150
166{
168 switch (mode) {
175 result = k_ra8_ok;
176 break;
177 default:
178 result = k_ra8_err_invalid_arg;
179 break;
180 }
181 return result;
182}
183
201{
203 switch (clock) {
205 /* HUM Ch 11.2.18 "SBYCR : Standby Control Register", p 456 */
207 break;
209 /* HUM Ch 11.2.18 "SBYCR : Standby Control Register", p 456 */
211 break;
213 /* HUM Ch 11.2.21 "DPSBYCR : Deep Software Standby Control", p 458 */
215 break;
217 /* HUM Ch 11.2.18 "SBYCR : Standby Control Register", p 456 */
219 break;
221 /* HUM Ch 11.2.21 "DPSBYCR : Deep Software Standby Control", p 458 */
223 break;
225 default:
227 break;
228 }
229 return off;
230}
231
247{
249 switch (idx) {
251 /* HUM Ch 11.2.22 "DPSIER0", p 459 */
253 break;
255 /* HUM Ch 11.2.23 "DPSIER1", p 459 */
257 break;
259 /* HUM Ch 11.2.24 "DPSIER2", p 460 */
261 break;
264 default:
265 /* HUM Ch 11.2.25 "DPSIER3", p 461 */
267 break;
268 }
269 return off;
270}
271
287{
289 switch (idx) {
291 /* HUM Ch 11.2.22 "DPSIER0", p 459 */
293 break;
295 /* HUM Ch 11.2.23 "DPSIER1", p 459 */
297 break;
299 /* HUM Ch 11.2.24 "DPSIER2", p 460 */
301 break;
304 default:
305 /* HUM Ch 11.2.25 "DPSIER3", p 461 */
307 break;
308 }
309 return off;
310}
311
331{
333 switch (idx) {
335 /* HUM Ch 11.2.22 "DPSIER0", p 459 */
337 break;
339 /* HUM Ch 11.2.23 "DPSIER1", p 459 */
341 break;
345 default:
346 /* HUM Ch 11.2.24 "DPSIER2", p 460 */
348 break;
349 }
350 return off;
351}
352
353/* =============================================================================
354 * Lifecycle
355 * =============================================================================
356 */
357
358[[nodiscard]] ra8_err_t ra8_lpm_init(const ra8_lpm_config_t* cfg)
359{
360 RA8_CHECK_NULL_PTR(cfg, s_tag, "cfg must not be nullptr");
361
362 /* SBYCR: only OPE is software-writable (HUM Ch 11.2.18 p 456). */
363 uint8_t sbycr = 0U;
364 if (cfg->opa_bus_keep) {
366 }
367 /* HUM Ch 11.2.18 "SBYCR : Standby Control Register", p 456 */
369
370 /* DPSBYCR: IOKEEP + DCSSMODE (HUM Ch 11.2.21 p 458). */
371 uint8_t dpsbycr = (uint8_t)((uint8_t)cfg->dcdc_softstart << k_ra8_lpm_dpsbycr_dcssmode_shift);
372 if (cfg->io_port_keep) {
374 }
375 /* HUM Ch 11.2.21 "DPSBYCR : Deep Software Standby Control Register", p 458 */
377
378 /* SSCR1: SS2FR + SS2LP (HUM Ch 11.2.19 p 456). */
379 uint8_t sscr1 = (uint8_t)((uint8_t)cfg->sscr_low_power << k_ra8_lpm_sscr1_ss2lp_shift);
380 if (cfg->sscr_fast_return) {
382 }
383 /* HUM Ch 11.2.19 "SSCR1 : Software Standby Control Register 1", p 456 */
385
386 /* LPSCR: clear LPMD so the next plain WFI is just a CPU sleep. */
387 /* HUM Ch 11.2.20 "LPSCR : Low Power State Control Register", p 457 */
389
390 ra8_log_info(s_tag, "lpm_init");
391 return k_ra8_ok;
392}
393
394[[nodiscard]] ra8_err_t ra8_lpm_deinit(void)
395{
396 /* HUM Ch 11.2.18 "SBYCR : Standby Control Register", p 456 */
398 /* HUM Ch 11.2.21 "DPSBYCR : Deep Software Standby Control Register", p 458 */
400 /* HUM Ch 11.2.19 "SSCR1 : Software Standby Control Register 1", p 456 */
402 /* HUM Ch 11.2.20 "LPSCR : Low Power State Control Register", p 457 */
404
405 /* Clear wake-up enables so a stray pending interrupt does not race. */
406 /* HUM Ch 14.2.19 "WUPEN0 : Wake Up Interrupt Enable Register 0", p 550 */
408 /* HUM Ch 14.2.20 "WUPEN1 : Wake Up Interrupt Enable Register 1", p 552 */
410
411 /* Clear all DPSIER0..3 so a stale per-factor enable does not survive. */
412 /* HUM Ch 11.2.22 "DPSIER0 : Deep Standby Interrupt Enable 0", p 459 */
414 /* HUM Ch 11.2.23 "DPSIER1 : Deep Standby Interrupt Enable 1", p 459 */
416 /* HUM Ch 11.2.24 "DPSIER2 : Deep Standby Interrupt Enable 2", p 460 */
418 /* HUM Ch 11.2.25 "DPSIER3 : Deep Standby Interrupt Enable 3", p 461 */
420
421 ra8_log_info(s_tag, "lpm_deinit");
422 return k_ra8_ok;
423}
424
425/* =============================================================================
426 * PRCR unlock / relock
427 * =============================================================================
428 */
429
431{
432 /* HUM Ch 11.2.18 "SBYCR : Standby Control Register", p 456 -- PRCR is
433 * the cross-cut write-protect register that gates SBYCR/DPSBYCR/etc. */
434 volatile uint16_t* prcr = ra8_lpm_sysc_reg16(k_ra8_lpm_prcr_off);
435 const uint16_t cur = *prcr;
436 const uint16_t mask = (uint16_t)((cur & k_lpm_byte_mask) | k_ra8_lpm_prcr_prc1_msk);
437 *prcr = (uint16_t)(k_ra8_lpm_prcr_key | mask);
438 return k_ra8_ok;
439}
440
442{
443 /* HUM Ch 11.2.18 "SBYCR : Standby Control Register", p 456 */
444 volatile uint16_t* prcr = ra8_lpm_sysc_reg16(k_ra8_lpm_prcr_off);
445 const uint16_t cur = *prcr;
446 const uint16_t mask = (uint16_t)((cur & k_lpm_byte_mask) & (uint16_t)~k_ra8_lpm_prcr_prc1_msk);
447 *prcr = (uint16_t)(k_ra8_lpm_prcr_key | mask);
448 return k_ra8_ok;
449}
450
451/* =============================================================================
452 * Wake-up source programming
453 * =============================================================================
454 */
455
456[[nodiscard]] ra8_err_t ra8_lpm_set_wakeup_sources(uint32_t wupen0, uint32_t wupen1)
457{
458 /* HUM Ch 14.2.19 "WUPEN0 : Wake Up Interrupt Enable Register 0", p 550 */
460 /* HUM Ch 14.2.20 "WUPEN1 : Wake Up Interrupt Enable Register 1", p 552 */
462 return k_ra8_ok;
463}
464
465[[nodiscard]] ra8_err_t ra8_lpm_arm_wupen0_bits(uint32_t bits)
466{
467 /* HUM Ch 14.2.19 "WUPEN0 : Wake Up Interrupt Enable Register 0", p 550 */
468 volatile uint32_t* p = ra8_lpm_icu_reg32(k_ra8_lpm_wupen0_off);
469 *p = *p | bits;
470 return k_ra8_ok;
471}
472
473[[nodiscard]] ra8_err_t ra8_lpm_clear_wupen0_bits(uint32_t bits)
474{
475 /* HUM Ch 14.2.19 "WUPEN0 : Wake Up Interrupt Enable Register 0", p 550 */
476 volatile uint32_t* p = ra8_lpm_icu_reg32(k_ra8_lpm_wupen0_off);
477 *p = (uint32_t)(*p & ~bits);
478 return k_ra8_ok;
479}
480
481[[nodiscard]] ra8_err_t ra8_lpm_arm_wupen1_bits(uint32_t bits)
482{
483 /* HUM Ch 14.2.20 "WUPEN1 : Wake Up Interrupt Enable Register 1", p 552 */
484 volatile uint32_t* p = ra8_lpm_icu_reg32(k_ra8_lpm_wupen1_off);
485 *p = *p | bits;
486 return k_ra8_ok;
487}
488
489[[nodiscard]] ra8_err_t ra8_lpm_clear_wupen1_bits(uint32_t bits)
490{
491 /* HUM Ch 14.2.20 "WUPEN1 : Wake Up Interrupt Enable Register 1", p 552 */
492 volatile uint32_t* p = ra8_lpm_icu_reg32(k_ra8_lpm_wupen1_off);
493 *p = (uint32_t)(*p & ~bits);
494 return k_ra8_ok;
495}
496
497/* =============================================================================
498 * Deep-standby cancel programming
499 * =============================================================================
500 */
501
502[[nodiscard]] ra8_err_t ra8_lpm_arm_dpsier(ra8_lpm_dpsier_idx_t idx, uint8_t value)
503{
504 if ((uint8_t)idx >= k_ra8_lpm_dpsier_idx_count) {
505 ra8_log_error(s_tag, "arm_dpsier: idx out of range");
507 }
508 const ra8_lpm_off_t en_off = internal_dpsier_offset(idx);
509 const ra8_lpm_off_t fr_off = internal_dpsifr_offset(idx);
510
511 /* HUM Ch 11.2.22 "DPSIER0", p 459 (and siblings 11.2.23..25): the enable
512 * register is byte-wide and S-TYPE-4 protected. */
513 *ra8_lpm_sysc_reg8(en_off) = value;
514
515 /* HUM Ch 11.2.22 "DPSIER0 : Deep Standby Interrupt Enable 0", p 459
516 * mandates a dummy read of DPSIFR before clearing it. */
517 (void)*ra8_lpm_sysc_reg8(fr_off);
518 *ra8_lpm_sysc_reg8(fr_off) = 0U;
519 return k_ra8_ok;
520}
521
523{
524 if ((uint8_t)idx >= k_ra8_lpm_dpsier_idx_count) {
525 ra8_log_error(s_tag, "clear_dpsifr: idx out of range");
527 }
528 const ra8_lpm_off_t fr_off = internal_dpsifr_offset(idx);
529 /* HUM Ch 11.2.22 "DPSIER0 : Deep Standby Interrupt Enable 0", p 459 */
530 (void)*ra8_lpm_sysc_reg8(fr_off);
531 *ra8_lpm_sysc_reg8(fr_off) = 0U;
532 return k_ra8_ok;
533}
534
535[[nodiscard]] ra8_err_t ra8_lpm_set_dpsiegr(ra8_lpm_dpsier_idx_t idx, uint8_t value)
536{
537 if ((uint8_t)idx >= k_ra8_lpm_dpsier_idx_count) {
538 ra8_log_error(s_tag, "set_dpsiegr: idx out of range");
540 }
541 const ra8_lpm_off_t eg_off = internal_dpsiegr_offset(idx);
542 /* HUM Ch 11.2.22 "DPSIER0 : Deep Standby Interrupt Enable 0", p 459 */
543 *ra8_lpm_sysc_reg8(eg_off) = value;
544 return k_ra8_ok;
545}
546
547/* =============================================================================
548 * Snooze controller (Standby + Snooze pattern on RA8D2)
549 * =============================================================================
550 */
551
552[[nodiscard]] ra8_err_t
553ra8_lpm_snooze_set_request_sources(bool ulpt0_underflow, bool ulpt1_underflow, bool acmphs0)
554{
555 /* HUM Ch 14.2.20 "WUPEN1 : Wake Up Interrupt Enable Register 1", p 552 */
556 volatile uint32_t* w1 = ra8_lpm_icu_reg32(k_ra8_lpm_wupen1_off);
557 uint32_t v = *w1;
558 if (ulpt0_underflow) {
560 }
561 if (ulpt1_underflow) {
563 }
564 *w1 = v;
565
566 if (acmphs0) {
567 /* HUM Ch 14.2.19 "WUPEN0 : Wake Up Interrupt Enable Register 0", p 550 */
568 volatile uint32_t* w0 = ra8_lpm_icu_reg32(k_ra8_lpm_wupen0_off);
569 *w0 = *w0 | k_ra8_lpm_wupen0_acmphs0;
570 }
571 return k_ra8_ok;
572}
573
574[[nodiscard]] ra8_err_t
575ra8_lpm_snooze_set_end_sources(bool ulpt0, bool ulpt1, bool usbfs, bool usbhs)
576{
577 /* HUM Ch 11.2.25 "DPSIER3 : Deep Standby Interrupt Enable 3", p 461 */
578 volatile uint8_t* en = ra8_lpm_sysc_reg8(k_ra8_lpm_dpsier3_off);
579 uint8_t v = *en;
580 if (ulpt0) {
582 }
583 if (ulpt1) {
585 }
586 if (usbfs) {
588 }
589 if (usbhs) {
591 }
592 *en = v;
593
594 /* HUM Ch 11.2.25 "DPSIER3 : Deep Standby Interrupt Enable 3", p 461
595 * mandates a dummy read of DPSIFR3 before writing 0 to clear it. */
598 return k_ra8_ok;
599}
600
601/* =============================================================================
602 * RAM and LDO retention
603 * =============================================================================
604 */
605
607{
608 RA8_CHECK_NULL_PTR(cfg, s_tag, "ram retention cfg null");
609
610 /* HUM Ch 11.2.16 "PDRAMSCR0 : SRAM Power Domain Standby Control 0", p 453 */
613
614 uint8_t pdramscr1 = 0U;
615 if (cfg->cpu0_tcm_keep) {
617 }
618 if (cfg->cpu1_tcm_keep) {
620 }
621 /* HUM Ch 11.2.17 "PDRAMSCR1 : SRAM Power Domain Standby Control 1", p 455 */
623 return k_ra8_ok;
624}
625
627{
628 RA8_CHECK_NULL_PTR(cfg, s_tag, "ldo cfg null");
629
630 /* Verify OPCCR.OPCM == 0 (High-speed mode) per HUM Ch 11.2.1 p 436 -- *LDOCR
631 * writes are only permitted in HSM. */
632 /* HUM Ch 11.2.11 "OPCCR : Operating Power Control Register", p 451 */
633 const uint8_t opccr = *ra8_lpm_sysc_reg8(k_ra8_lpm_opccr_off);
634 if (((uint8_t)(opccr & k_ra8_lpm_opccr_opcm_mask)) != 0U) {
635 ra8_log_error(s_tag, "set_ldo: OPCM!=0");
637 }
638
639 /* HUM Ch 11.2.1 "LPMSAR : Low Power Mode Security Attribution Register", p 436 */
640 volatile uint8_t* pll1 = ra8_lpm_sysc_reg8(k_ra8_lpm_pll1ldocr_off);
641 *pll1 = (uint8_t)((*pll1 & (uint8_t)~k_ra8_lpm_ldocr_skeep_mask) |
642 (uint8_t)((uint8_t)cfg->pll1 << k_ra8_lpm_ldocr_skeep_shift));
643
644 /* HUM Ch 11.2.1 "LPMSAR : Low Power Mode Security Attribution Register", p 436 */
645 volatile uint8_t* pll2 = ra8_lpm_sysc_reg8(k_ra8_lpm_pll2ldocr_off);
646 *pll2 = (uint8_t)((*pll2 & (uint8_t)~k_ra8_lpm_ldocr_skeep_mask) |
647 (uint8_t)((uint8_t)cfg->pll2 << k_ra8_lpm_ldocr_skeep_shift));
648
649 /* HUM Ch 11.2.1 "LPMSAR : Low Power Mode Security Attribution Register", p 436 */
650 volatile uint8_t* hoco = ra8_lpm_sysc_reg8(k_ra8_lpm_hocoldocr_off);
651 *hoco = (uint8_t)((*hoco & (uint8_t)~k_ra8_lpm_ldocr_skeep_mask) |
652 (uint8_t)((uint8_t)cfg->hoco << k_ra8_lpm_ldocr_skeep_shift));
653 return k_ra8_ok;
654}
655
656/* =============================================================================
657 * Clock-shutdown matrix
658 * =============================================================================
659 */
660
661[[nodiscard]] ra8_err_t ra8_lpm_set_clock_stop(ra8_lpm_clock_t clock, bool stop)
662{
663 if ((uint8_t)clock >= k_ra8_lpm_clock_count) {
664 ra8_log_error(s_tag, "set_clock_stop: bad clock");
666 }
667 volatile uint8_t* p = ra8_lpm_sysc_reg8(internal_clock_offset(clock));
668
669 /* The oscillator control registers (MOSCCR/HOCOCR/MOCOCR/LOCOCR/SOSCCR) each
670 * carry their STOP bit at bit 0 and belong to the clock-generation circuit,
671 * which is PRC0-protected (HUM Ch 13.1 Table 13.1 p 520). A store issued with
672 * PRC0 locked is silently discarded, so open a CGC unlock window around the
673 * read-modify-write rather than trusting an undocumented caller contract. */
675 {
676 /* HUM Ch 9.2.18 "MOCOCR : MOCO Control Register", p 341 -- representative of
677 * the OCR family; internal_clock_offset() selects the register this clock
678 * owns and each OCR places its STOP bit at bit 0. */
679 if (stop) {
680 *p = (uint8_t)(*p | k_ra8_lpm_clock_stop_mask);
681 } else {
682 *p = (uint8_t)(*p & (uint8_t)~k_ra8_lpm_clock_stop_mask);
683 }
684 }
685 return k_ra8_ok;
686}
687
688[[nodiscard]] ra8_err_t ra8_lpm_get_clock_stop(ra8_lpm_clock_t clock, bool* stop)
689{
690 RA8_CHECK_NULL_PTR(stop, s_tag, "stop must not be nullptr");
691 if ((uint8_t)clock >= k_ra8_lpm_clock_count) {
692 ra8_log_error(s_tag, "get_clock_stop: bad clock");
694 }
695 /* HUM Ch 11.2.18 "SBYCR : Standby Control Register", p 456 */
696 const uint8_t v = *ra8_lpm_sysc_reg8(internal_clock_offset(clock));
697 *stop = ((uint8_t)(v & k_ra8_lpm_clock_stop_mask) != 0U);
698 return k_ra8_ok;
699}
700
701/* =============================================================================
702 * OPCCR
703 * =============================================================================
704 */
705
706[[nodiscard]] ra8_err_t ra8_lpm_get_opccr(uint8_t* opccr)
707{
708 RA8_CHECK_NULL_PTR(opccr, s_tag, "opccr must not be nullptr");
709 /* HUM Ch 11.2.11 "OPCCR : Operating Power Control Register", p 451 */
711 return k_ra8_ok;
712}
713
714[[nodiscard]] ra8_err_t ra8_lpm_wait_for_opccr(uint32_t poll_limit)
715{
716 if (poll_limit == 0U) {
718 }
719 for (uint32_t i = 0U; i < poll_limit; ++i) {
720 /* HUM Ch 11.2.11 "OPCCR : Operating Power Control Register", p 451 */
721 const uint8_t v = *ra8_lpm_sysc_reg8(k_ra8_lpm_opccr_off);
722 if (((uint8_t)(v & k_ra8_lpm_opccr_opcmtsf_msk)) == 0U) {
723 return k_ra8_ok;
724 }
725 }
726 ra8_log_error(s_tag, "wait_for_opccr timeout");
728}
729
730/* =============================================================================
731 * Sleep entry
732 * =============================================================================
733 */
734
736{
737 const ra8_err_t mode_err = internal_validate_mode(mode);
738 RA8_RETURN_ON_ERROR(mode_err, s_tag, "lpm_enter_sleep: bad mode");
739
740 /* For Sleep / Deep-Sleep, LPMD stays at 0 (System Active); only WFI +
741 * SCR.SLEEPDEEP toggle differs. For Software Standby and Deep Standby,
742 * LPMD encodes the destination per HUM Ch 11.2.20 p 457. */
743 uint8_t lpscr_value = 0U;
744 bool sleepdeep = false;
745 switch (mode) {
747 lpscr_value = 0U;
748 sleepdeep = false;
749 break;
751 lpscr_value = 0U;
752 sleepdeep = true;
753 break;
758 default:
759 lpscr_value = (uint8_t)((uint8_t)mode & k_ra8_lpm_lpscr_lpmd_mask);
760 sleepdeep = true;
761 break;
762 }
763
764 /* HUM Ch 11.2.20 "LPSCR : Low Power State Control Register", p 457 */
766
767 /* Toggle SCB.SCR.SLEEPDEEP per HUM Ch 11.3 entry sequence (the bit
768 * is owned by the Cortex-M85 SCB, not by SYSC; on host this is a
769 * no-op). */
770 internal_set_sleepdeep(sleepdeep);
771
772 ra8_log_info_val(s_tag, "lpm_enter_sleep mode", (uint32_t)mode);
774
775 /* On wake (or immediately on host), restore SLEEPDEEP for the next
776 * plain Sleep entry, and clear LPSCR back to Sleep mode so the next
777 * WFI does not re-enter Software Standby. Without this, a debugger-
778 * issued SYSRESETREQ leaves LPSCR set (SYSC LPM block is in a
779 * separate reset domain), and the first WFI in J-Link's RAMCode
780 * helper re-enters standby -- bricking the chip until a true PORST. */
783 return k_ra8_ok;
784}
785
790
791/* =============================================================================
792 * Status / diagnostics
793 * =============================================================================
794 */
795
796[[nodiscard]] ra8_err_t ra8_lpm_get_status(uint32_t* out)
797{
798 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
799
800 /* HUM Ch 11.2.18 "SBYCR : Standby Control Register", p 456 */
801 const uint32_t sbycr = (uint32_t)*ra8_lpm_sysc_reg8(k_ra8_lpm_sbycr_off);
802 /* HUM Ch 11.2.21 "DPSBYCR : Deep Software Standby Control Register", p 458 */
803 const uint32_t dpsbycr = (uint32_t)*ra8_lpm_sysc_reg8(k_ra8_lpm_dpsbycr_off);
804 /* HUM Ch 11.2.20 "LPSCR : Low Power State Control Register", p 457 */
805 const uint32_t lpscr = (uint32_t)*ra8_lpm_sysc_reg8(k_ra8_lpm_lpscr_off);
806 /* HUM Ch 11.2.19 "SSCR1 : Software Standby Control Register 1", p 456 */
807 const uint32_t sscr1 = (uint32_t)*ra8_lpm_sysc_reg8(k_ra8_lpm_sscr1_off);
808
809 *out = (sbycr << k_ra8_lpm_status_shift_sbycr) | (dpsbycr << k_ra8_lpm_status_shift_dpsbycr) |
811 return k_ra8_ok;
812}
813
814[[nodiscard]] ra8_err_t ra8_lpm_get_exit_cause(uint64_t* out)
815{
816 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
817
818 /* HUM Ch 14.2.19 "WUPEN0 : Wake Up Interrupt Enable Register 0", p 550 */
819 const uint64_t w0 = (uint64_t)*ra8_lpm_icu_reg32(k_ra8_lpm_wupen0_off);
820 /* HUM Ch 14.2.20 "WUPEN1 : Wake Up Interrupt Enable Register 1", p 552 */
821 const uint64_t w1 = (uint64_t)*ra8_lpm_icu_reg32(k_ra8_lpm_wupen1_off);
822
824 return k_ra8_ok;
825}
826
827[[nodiscard]] ra8_err_t
828ra8_lpm_get_dpsi_state(uint8_t enables[4], uint8_t flags[4], uint8_t edges[3])
829{
830 RA8_CHECK_NULL_PTR(enables, s_tag, "enables nullptr");
831 RA8_CHECK_NULL_PTR(flags, s_tag, "flags nullptr");
832 RA8_CHECK_NULL_PTR(edges, s_tag, "edges nullptr");
833
834 /* HUM Ch 11.2.22 "DPSIER0 : Deep Standby Interrupt Enable 0", p 459 */
836 /* HUM Ch 11.2.23 "DPSIER1 : Deep Standby Interrupt Enable 1", p 459 */
838 /* HUM Ch 11.2.24 "DPSIER2 : Deep Standby Interrupt Enable 2", p 460 */
840 /* HUM Ch 11.2.25 "DPSIER3 : Deep Standby Interrupt Enable 3", p 461 */
842
843 /* HUM Ch 11.2.22 "DPSIER0 : Deep Standby Interrupt Enable 0", p 459 */
845 /* HUM Ch 11.2.23 "DPSIER1 : Deep Standby Interrupt Enable 1", p 459 */
847 /* HUM Ch 11.2.24 "DPSIER2 : Deep Standby Interrupt Enable 2", p 460 */
849 /* HUM Ch 11.2.25 "DPSIER3 : Deep Standby Interrupt Enable 3", p 461 */
851
852 /* HUM Ch 11.2.22 "DPSIER0 : Deep Standby Interrupt Enable 0", p 459 */
854 /* HUM Ch 11.2.23 "DPSIER1 : Deep Standby Interrupt Enable 1", p 459 */
856 /* HUM Ch 11.2.24 "DPSIER2 : Deep Standby Interrupt Enable 2", p 460 */
858 return k_ra8_ok;
859}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_RETURN_ON_ERROR(err, tag, message)
Early return on error, propagating the code upward.
Definition ra8_check.h:184
#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_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
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Shared CPU-intrinsic seam for the HAL drivers (host/target split).
static void ra8_hw_dsb(void)
Data Synchronisation Barrier (full system).
static void ra8_hw_wfi(void)
Wait For Interrupt: place the core in low-power wait.
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_info_val(tag, message, value)
RA8 log info val.
Definition ra8_log.h:366
#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
ra8_err_t ra8_lpm_wait_for_opccr(uint32_t poll_limit)
Wait for OPCCR.OPCMTSF to clear (mode-transition complete).
Definition ra8_lpm.c:714
ra8_lpm_cause_shift_t
Bit shifts used to pack WUPEN0 / WUPEN1 into a 64-bit cause word.
Definition ra8_lpm.c:80
@ k_ra8_lpm_cause_shift_wupen0
WUPEN0 occupies the low 32 bits.
Definition ra8_lpm.c:81
@ k_ra8_lpm_cause_shift_wupen1
WUPEN1 occupies the high 32 bits.
Definition ra8_lpm.c:82
ra8_err_t ra8_lpm_get_opccr(uint8_t *opccr)
Read OPCCR raw byte (OPCM[1:0] + OPCMTSF).
Definition ra8_lpm.c:706
ra8_err_t ra8_lpm_init(const ra8_lpm_config_t *cfg)
Initialise the LPM block from a config descriptor.
Definition ra8_lpm.c:358
ra8_err_t ra8_lpm_clear_wupen1_bits(uint32_t bits)
AND-out WUPEN1 bits to disarm specific wake-up sources.
Definition ra8_lpm.c:489
ra8_err_t ra8_lpm_snooze_set_request_sources(bool ulpt0_underflow, bool ulpt1_underflow, bool acmphs0)
Configure ULPT-driven snooze request sources.
Definition ra8_lpm.c:553
ra8_err_t ra8_lpm_get_exit_cause(uint64_t *out)
Snapshot WUPEN0 / WUPEN1 into a single 64-bit word.
Definition ra8_lpm.c:814
static ra8_lpm_off_t internal_dpsifr_offset(ra8_lpm_dpsier_idx_t idx)
Resolve a DPSIFR index to its register offset.
Definition ra8_lpm.c:286
static ra8_lpm_off_t internal_clock_offset(ra8_lpm_clock_t clock)
Resolve ra8_lpm_clock_t to its OCR offset.
Definition ra8_lpm.c:200
static ra8_err_t internal_validate_mode(ra8_sleep_mode_t mode)
Validate mode against the LPSCR.LPMD encoding table.
Definition ra8_lpm.c:165
ra8_err_t ra8_lpm_set_ram_retention(const ra8_lpm_ram_retention_t *cfg)
Programme PDRAMSCR0 / PDRAMSCR1 from a retention descriptor.
Definition ra8_lpm.c:606
static ra8_lpm_off_t internal_dpsiegr_offset(ra8_lpm_dpsier_idx_t idx)
Resolve a DPSIEGR index to its register offset.
Definition ra8_lpm.c:330
ra8_err_t ra8_lpm_prcr_relock(void)
Re-lock PRCR.PRC1 after protected writes.
Definition ra8_lpm.c:441
ra8_err_t ra8_lpm_set_dpsiegr(ra8_lpm_dpsier_idx_t idx, uint8_t value)
Programme DPSIEGR0..2 (deep-standby IRQ edge polarity).
Definition ra8_lpm.c:535
static void internal_set_sleepdeep(bool enable)
Toggle SCB.SCR.SLEEPDEEP for non-Sleep mode entry.
Definition ra8_lpm.c:139
ra8_err_t ra8_lpm_enter_deep_standby(void)
Convenience wrapper – enter Deep Software Standby mode 1.
Definition ra8_lpm.c:786
lpm_byte_mask_t
Low-byte mask for the PRCR protect register.
Definition ra8_lpm.c:61
@ k_lpm_byte_mask
Lpm byte mask.
Definition ra8_lpm.c:62
ra8_err_t ra8_lpm_enter_sleep(ra8_sleep_mode_t mode)
Programme LPSCR for mode and enter the requested sleep.
Definition ra8_lpm.c:735
ra8_err_t ra8_lpm_get_clock_stop(ra8_lpm_clock_t clock, bool *stop)
Read the per-oscillator stop bit.
Definition ra8_lpm.c:688
ra8_err_t ra8_lpm_snooze_set_end_sources(bool ulpt0, bool ulpt1, bool usbfs, bool usbhs)
Configure end-of-snooze sources via DPSIER3 (ULPT/USB hooks).
Definition ra8_lpm.c:575
ra8_err_t ra8_lpm_arm_wupen0_bits(uint32_t bits)
OR-in additional WUPEN0 bits without disturbing other sources.
Definition ra8_lpm.c:465
ra8_lpm_status_shift_t
Bit shifts used to pack SBYCR / DPSBYCR / LPSCR / SSCR1.
Definition ra8_lpm.c:69
@ k_ra8_lpm_status_shift_dpsbycr
DPSBYCR occupies byte 1.
Definition ra8_lpm.c:71
@ k_ra8_lpm_status_shift_lpscr
LPSCR occupies byte 2.
Definition ra8_lpm.c:72
@ k_ra8_lpm_status_shift_sscr1
SSCR1 occupies byte 3.
Definition ra8_lpm.c:73
@ k_ra8_lpm_status_shift_sbycr
SBYCR occupies byte 0.
Definition ra8_lpm.c:70
ra8_err_t ra8_lpm_clear_dpsifr(ra8_lpm_dpsier_idx_t idx)
Clear DPSIFR0..3 so a stale flag does not cancel deep standby.
Definition ra8_lpm.c:522
ra8_err_t ra8_lpm_arm_wupen1_bits(uint32_t bits)
OR-in additional WUPEN1 bits without disturbing other sources.
Definition ra8_lpm.c:481
ra8_err_t ra8_lpm_deinit(void)
Restore SBYCR / DPSBYCR / LPSCR / SSCR1 to cold-reset defaults.
Definition ra8_lpm.c:394
static void internal_wait_for_interrupt(void)
Issue a Data Synchronization Barrier followed by WFI.
Definition ra8_lpm.c:112
ra8_err_t ra8_lpm_get_status(uint32_t *out)
Read LPM status (SBYCR | DPSBYCR | LPSCR | SSCR1) packed.
Definition ra8_lpm.c:796
ra8_err_t ra8_lpm_prcr_unlock(void)
Unlock PRCR.PRC1 to permit writes to LPM control registers.
Definition ra8_lpm.c:430
ra8_err_t ra8_lpm_set_clock_stop(ra8_lpm_clock_t clock, bool stop)
Set or clear the per-oscillator stop bit before sleep entry.
Definition ra8_lpm.c:661
ra8_err_t ra8_lpm_arm_dpsier(ra8_lpm_dpsier_idx_t idx, uint8_t value)
Programme the per-byte DPSIER0..3 enable byte directly.
Definition ra8_lpm.c:502
ra8_err_t ra8_lpm_set_wakeup_sources(uint32_t wupen0, uint32_t wupen1)
Programme the raw WUPEN0 / WUPEN1 masks.
Definition ra8_lpm.c:456
ra8_err_t ra8_lpm_get_dpsi_state(uint8_t enables[4], uint8_t flags[4], uint8_t edges[3])
Read DPSIER0..3 + DPSIFR0..3 + DPSIEGR0..2 into a buffer.
Definition ra8_lpm.c:828
ra8_lpm_dpsi_count_t
Buffer counts for ra8_lpm_get_dpsi_state.
Definition ra8_lpm.c:89
@ k_ra8_lpm_dpsifr_count
DPSIFR0..3 count.
Definition ra8_lpm.c:91
@ k_ra8_lpm_dpsieg_count
DPSIEGR0..2 count.
Definition ra8_lpm.c:92
@ k_ra8_lpm_dpsier_count
DPSIER0..3 count.
Definition ra8_lpm.c:90
ra8_err_t ra8_lpm_clear_wupen0_bits(uint32_t bits)
AND-out WUPEN0 bits to disarm specific wake-up sources.
Definition ra8_lpm.c:473
ra8_err_t ra8_lpm_set_ldo_standby(const ra8_lpm_ldo_cfg_t *cfg)
Programme PLL1LDOCR / PLL2LDOCR / HOCOLDOCR SKEEP bits.
Definition ra8_lpm.c:626
static ra8_lpm_off_t internal_dpsier_offset(ra8_lpm_dpsier_idx_t idx)
Resolve a DPSIER index to its register offset.
Definition ra8_lpm.c:246
Low Power Mode (LPM) HAL driver – public API.
ra8_lpm_clock_t
Selector for ra8_lpm_set_clock_stop / ra8_lpm_get_clock_stop.
Definition ra8_lpm.h:152
@ k_ra8_lpm_clock_loco
Low-Speed On-Chip Oscillator.
Definition ra8_lpm.h:155
@ k_ra8_lpm_clock_sub
Sub-clock Oscillator.
Definition ra8_lpm.h:157
@ k_ra8_lpm_clock_moco
Middle-Speed On-Chip Oscillator.
Definition ra8_lpm.h:153
@ k_ra8_lpm_clock_main
Main Oscillator.
Definition ra8_lpm.h:156
@ k_ra8_lpm_clock_count
RA8 lpm clock count.
Definition ra8_lpm.h:158
@ k_ra8_lpm_clock_hoco
High-Speed On-Chip Oscillator.
Definition ra8_lpm.h:154
Low Power Mode (LPM) register layout for the Renesas RA8D2.
@ k_ra8_lpm_dpsbycr_reset_val
Cold-reset value.
@ k_ra8_lpm_dpsbycr_iokeep_mask
IOKEEP @ bit 6.
@ k_ra8_lpm_dpsbycr_dcssmode_shift
DCSSMODE[1:0] starts at bit 2.
@ k_ra8_lpm_scb_scr_sleepdeep
SCR.SLEEPDEEP @ bit 2.
static volatile uint32_t * ra8_lpm_scb_scr(void)
Return a typed pointer to the Cortex-M SCB->SCR register.
@ k_ra8_lpm_sbycr_ope_mask
OPE @ bit 6 – bus-signal output keep.
@ k_ra8_lpm_sbycr_reset_val
Cold-reset value (OPE=1, all else 0).
ra8_sleep_mode_t
Software-selectable sleep modes (LPSCR.LPMD encoding).
@ k_ra8_sleep_mode_deep_standby_1
Deep Standby 1 (LPMD=0x8).
@ k_ra8_sleep_mode_deep_standby_2
Deep Standby 2 (LPMD=0x9).
@ k_ra8_sleep_mode_deep_sleep
CPU deep sleep (SCR.SLEEPDEEP=1).
@ k_ra8_sleep_mode_software_std
Software Standby (LPMD=0x5).
@ k_ra8_sleep_mode_sleep
CPU sleep, peripherals run.
@ k_ra8_sleep_mode_deep_standby_3
Deep Standby 3 (LPMD=0xA).
static volatile uint32_t * ra8_lpm_icu_reg32(ra8_lpm_off_t off)
Return a typed pointer to a 32-bit ICU/WUPEN register.
@ k_ra8_lpm_pdramscr0_writable
b14..b0 writable mask.
@ k_ra8_lpm_ldocr_skeep_shift
SKEEP starts at bit 1.
@ k_ra8_lpm_ldocr_skeep_mask
SKEEP @ bit 1 – retain in standby.
@ k_ra8_lpm_pdramscr1_rkeep1_mask
RKEEP1 @ bit 1 – CPU1 TCM.
@ k_ra8_lpm_pdramscr1_rkeep0_mask
RKEEP0 @ bit 0 – CPU0 TCM.
@ k_ra8_lpm_wupen0_acmphs0
legacy alias for PVD1 path.
ra8_lpm_dpsier_idx_t
Selector for DPSIER0..3 / DPSIFR0..3 / DPSIEGR0..2 helpers (HUM Ch 11.2.22..36 p 459....
@ k_ra8_lpm_dpsier_idx_count
RA8 lpm dpsier index count.
@ k_ra8_lpm_dpsier_idx_2
DPSIER2 / DPSIFR2 / DPSIEGR2.
@ k_ra8_lpm_dpsier_idx_1
DPSIER1 / DPSIFR1 / DPSIEGR1.
@ k_ra8_lpm_dpsier_idx_0
DPSIER0 / DPSIFR0 / DPSIEGR0.
@ k_ra8_lpm_dpsier_idx_3
DPSIER3 / DPSIFR3 (HUM Ch 11.2.25 p 461 – DPSIEGR3 @ 0xA34 exists, unexposed here).
ra8_lpm_off_t
Byte offsets of every LPM-relevant register from its block base.
@ k_ra8_lpm_pll2ldocr_off
PLL2LDOCR (8b) – HUM Ch 11.2.41 p 475.
@ k_ra8_lpm_dpsbycr_off
DPSBYCR (8b) – HUM Ch 11.2.21 p 458.
@ k_ra8_lpm_dpsiegr2_off
DPSIEGR2 (8b) – HUM Ch 11.2.36 p 463.
@ k_ra8_lpm_pdramscr1_off
PDRAMSCR1 (8b) – HUM Ch 11.2.17 p 455.
@ k_ra8_lpm_pll1ldocr_off
PLL1LDOCR (8b) – HUM Ch 11.2.40 p 475.
@ k_ra8_lpm_dpsifr0_off
DPSIFR0 (8b) – HUM Ch 11.2.28 p 462.
@ k_ra8_lpm_dpsier0_off
DPSIER0 (8b) – HUM Ch 11.2.22 p 459.
@ k_ra8_lpm_wupen0_off
WUPEN0 (32b) – HUM Ch 14.2.19 p 550.
@ k_ra8_lpm_dpsier1_off
DPSIER1 (8b) – HUM Ch 11.2.23 p 459.
@ k_ra8_lpm_sscr1_off
SSCR1 (8b) – HUM Ch 11.2.19 p 456.
@ k_ra8_lpm_mococr_off
MOCOCR (8b) – HUM Ch 9.2.18 p 346.
@ k_ra8_lpm_sbycr_off
SBYCR (8b) – HUM Ch 11.2.18 p 456.
@ k_ra8_lpm_dpsifr2_off
DPSIFR2 (8b) – HUM Ch 11.2.30 p 462.
@ k_ra8_lpm_hocoldocr_off
HOCOLDOCR (8b) – HUM Ch 11.2.42 p 476.
@ k_ra8_lpm_dpsier3_off
DPSIER3 (8b) – HUM Ch 11.2.25 p 461.
@ k_ra8_lpm_hococr_off
HOCOCR (8b) – HUM Ch 9.2.16 p 345.
@ k_ra8_lpm_lpscr_off
LPSCR (8b) – HUM Ch 11.2.20 p 457.
@ k_ra8_lpm_dpsiegr1_off
DPSIEGR1 (8b) – HUM Ch 11.2.35 p 463.
@ k_ra8_lpm_opccr_off
OPCCR (8b) – HUM Ch 11.2.11 p 451.
@ k_ra8_lpm_dpsiegr0_off
DPSIEGR0 (8b) – HUM Ch 11.2.34 p 463.
@ k_ra8_lpm_lococr_off
LOCOCR (8b) – HUM Ch 9.2.15 p 344.
@ k_ra8_lpm_wupen1_off
WUPEN1 (32b) – HUM Ch 14.2.20 p 552.
@ k_ra8_lpm_sosccr_off
SOSCCR (8b) – HUM Ch 9.2.14 p 343.
@ k_ra8_lpm_pdramscr0_off
PDRAMSCR0 (16b) – HUM Ch 11.2.16 p 453.
@ k_ra8_lpm_dpsier2_off
DPSIER2 (8b) – HUM Ch 11.2.24 p 460.
@ k_ra8_lpm_prcr_off
PRCR (16b) – HUM Ch 11.2.18 p 456.
@ k_ra8_lpm_dpsifr3_off
DPSIFR3 (8b) – HUM Ch 11.2.31 p 462.
@ k_ra8_lpm_mosccr_off
MOSCCR (8b) – HUM Ch 9.2.13 p 343.
@ k_ra8_lpm_dpsifr1_off
DPSIFR1 (8b) – HUM Ch 11.2.29 p 462.
@ k_ra8_lpm_sscr1_ss2lp_shift
SS2LP[1:0] starts at bit 2.
@ k_ra8_lpm_sscr1_ss2fr_mask
SS2FR @ bit 0 – fast return.
@ k_ra8_lpm_clock_stop_mask
STOP @ bit 0 in every OCR.
static volatile uint16_t * ra8_lpm_sysc_reg16(ra8_lpm_off_t off)
Return a typed pointer to a 16-bit SYSC register.
@ k_ra8_lpm_dpsier3_dulpt1ie_mask
DULPT1IE @ bit 3.
@ k_ra8_lpm_dpsier3_dusbfsie_mask
DUSBFSIE @ bit 0.
@ k_ra8_lpm_dpsier3_dulpt0ie_mask
DULPT0IE @ bit 2.
@ k_ra8_lpm_dpsier3_dusbhsie_mask
DUSBHSIE @ bit 1.
@ k_ra8_lpm_lpscr_lpmd_mask
LPMD[3:0] occupies bits 3..0.
@ k_ra8_lpm_prcr_key
Mandatory password in upper byte.
@ k_ra8_lpm_prcr_prc1_msk
PRC1 – LPM/SYSC group.
@ k_ra8_lpm_wupen1_ulpt1u
ULP1UWUPEN @ bit 12.
@ k_ra8_lpm_wupen1_ulpt0u
ULP0UWUPEN @ bit 8.
static volatile uint8_t * ra8_lpm_sysc_reg8(ra8_lpm_off_t off)
Return a typed pointer to an 8-bit SYSC register.
@ k_ra8_lpm_opccr_opcmtsf_msk
OPCMTSF @ bit 4 – mode-transition flag.
@ k_ra8_lpm_opccr_opcm_mask
OPCM[1:0] @ bits 1..0 – power mode.
Scoped PRCR unlock helper.
#define RA8_PROTECTED_WRITE(unlock_val)
Scoped PRCR unlock block.
@ k_ra8_prcr_unlock_cgc
RA8 prcr unlock cgc.
Configuration descriptor for ra8_lpm_init.
Definition ra8_lpm.h:96
bool opa_bus_keep
SBYCR.OPE – keep bus signals driven.
Definition ra8_lpm.h:98
ra8_lpm_dcssmode_t dcdc_softstart
DCSSMODE encoding (k_ra8_lpm_dcssmode_*).
Definition ra8_lpm.h:100
bool io_port_keep
DPSBYCR.IOKEEP – retain IOs across DSBY.
Definition ra8_lpm.h:97
bool sscr_fast_return
SSCR1.SS2FR – speed up wake from SSTBY.
Definition ra8_lpm.h:99
ra8_lpm_sscr1_ss2lp_t sscr_low_power
SSCR1.SS2LP encoding.
Definition ra8_lpm.h:101
LDO standby retention selection (HUM 11.2.1 p 436).
Definition ra8_lpm.h:112
ra8_lpm_ldo_state_t pll2
PLL2 LDO state in standby.
Definition ra8_lpm.h:114
ra8_lpm_ldo_state_t pll1
PLL1 LDO state in standby.
Definition ra8_lpm.h:113
ra8_lpm_ldo_state_t hoco
HOCO LDO state in standby.
Definition ra8_lpm.h:115
RAM retention configuration (HUM 11.2.16 / 11.2.17).
Definition ra8_lpm.h:127
bool cpu0_tcm_keep
PDRAMSCR1.RKEEP0.
Definition ra8_lpm.h:129
bool cpu1_tcm_keep
PDRAMSCR1.RKEEP1 (dual-core only).
Definition ra8_lpm.h:130
uint16_t pdramscr0_bits
Raw PDRAMSCR0 RKEEP[12:0] value.
Definition ra8_lpm.h:128