ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_flash.c
Go to the documentation of this file.
1
36
37#include "ra8_flash.h"
38
39#include <stdint.h>
40#include <string.h>
41
42#include "ra8_attributes.h"
43#include "ra8_check.h"
44#include "ra8_err.h"
45#include "ra8_flash_internal.h"
46#include "ra8_flash_regs.h"
47#include "ra8_hw_err.h"
48#include "ra8_log.h"
49
50const char* g_flash_tag = "FLASH";
51
68
69/* =============================================================================
70 * Internal helpers
71 * =============================================================================
72 */
73
94{
95 for (uint32_t i = 0U; i < limit; ++i) {
96 /* HUM Ch 59 "MRCPS : Code MRAM Program Status Register" p 3577 */
97 const uint8_t s = *ra8_mram_reg8(k_ra8_mram_off_mrcps);
98 if (((s & k_ra8_mrcps_mask_prgbsyc) == 0U) && ((s & k_ra8_mrcps_mask_abuffull) == 0U)) {
99 return k_ra8_ok;
100 }
101 }
103}
104
128
149{
150 for (uint32_t i = 0U; i < limit; ++i) {
151 /* HUM Ch 59 "MRCPS : Code MRAM Program Status Register" p 3577 */
152 const uint8_t s = *ra8_mram_reg8(k_ra8_mram_off_mrcps);
153 if (((s & k_ra8_mrcps_mask_abufemp) != 0U) && ((s & k_ra8_mrcps_mask_prgbsyc) == 0U)) {
154 return k_ra8_ok;
155 }
156 }
158}
159
183
204{
205 for (uint32_t i = 0U; i < limit; ++i) {
206 /* HUM Ch 59 "MSTATR : Extra MRAM Status Register" p 3568 */
207 const uint32_t s = *ra8_mram_reg32(k_ra8_mram_off_mstatr);
208 if ((s & k_ra8_mstatr_mask_mrdy) != 0U) {
209 return k_ra8_ok;
210 }
211 }
213}
214
233{
234 const uint16_t off =
236 uint16_t value;
237 if (world == k_ra8_flash_world_s) {
238 if (enable) {
240 } else {
242 }
243 } else {
244 if (enable) {
246 } else {
248 }
249 }
250 /* HUM Ch 59 "MRCPC0/MRCPC1 : Code MRAM Program Control Register" p 3601 */
251 *ra8_mram_reg16(off) = value;
252}
253
270RA8_INTERNAL static void internal_set_hsp_mode(bool enable)
271{
272 /* HUM Ch 59 "MRPSC : MRAM Program Speed Control Register" p 3575 */
273 uint8_t mrpsc = 0U;
274 if (enable) {
276 }
278}
279
297{
298 /* HUM Ch 59.5.1 "MRCPFB : Code MRAM Pre-Fetch Buffer Enable Register" p 3551 */
299 uint8_t mrcpfb = 0U;
300 if (enable) {
301 mrcpfb = 1U;
302 }
304 g_flash_rt.prefetch_on = enable;
305}
306
307#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
308/* Host-test MACI command capture (see ra8_flash_internal.h). The MACI port is a
309 * single MMIO address, so RAM alone cannot retain the stream a host test needs
310 * to assert the emitted opcode sequence (0xE8 Program vs 0x40 Config-Set).
311 * Present only in the host unit-test binary; firmware / ra8_emulator link neither
312 * RA8_OFF_TARGET nor UNIT_TEST, so the whole block compiles out. */
313uint8_t g_ra8_flash_maci_cmd8_log[k_ra8_flash_maci_log_cap];
314uint32_t g_ra8_flash_maci_cmd8_len;
315uint16_t g_ra8_flash_maci_cmd16_log[k_ra8_flash_maci_log_cap];
316uint32_t g_ra8_flash_maci_cmd16_len;
317
318void ra8_flash_internal_maci_log_reset(void)
319{
320 g_ra8_flash_maci_cmd8_len = 0U;
321 g_ra8_flash_maci_cmd16_len = 0U;
322}
323#endif /* RA8_OFF_TARGET && UNIT_TEST */
324
342{
343 /* HUM Ch 59 "MACI Command-Issuing Area" p 3550 */
344 *ra8_mram_cmd8() = byte;
345#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
346 if (g_ra8_flash_maci_cmd8_len < (uint32_t)k_ra8_flash_maci_log_cap) {
347 g_ra8_flash_maci_cmd8_log[g_ra8_flash_maci_cmd8_len] = byte;
348 g_ra8_flash_maci_cmd8_len++;
349 }
350#endif
351}
352
370{
371 /* HUM Ch 59 "MACI Command-Issuing Area" p 3550 */
372 *ra8_mram_cmd16() = half;
373#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
374 if (g_ra8_flash_maci_cmd16_len < (uint32_t)k_ra8_flash_maci_log_cap) {
375 g_ra8_flash_maci_cmd16_log[g_ra8_flash_maci_cmd16_len] = half;
376 g_ra8_flash_maci_cmd16_len++;
377 }
378#endif
379}
380
381/* =============================================================================
382 * Public API: lifecycle
383 * =============================================================================
384 */
385
387{
388 RA8_CHECK_NULL_PTR(cfg, g_flash_tag, "cfg must not be nullptr");
389 if (cfg->mrcfreq_mhz > (uint16_t)k_ra8_flash_max_mrcfreq_mhz) {
391 }
392 if (cfg->mrefreq_mhz > (uint8_t)k_ra8_flash_max_mrefreq_mhz) {
394 }
395
396 /* Frequency-down procedure -- HUM Ch 59.4.3 Figure 59.6 p 3550. */
398
399 /* HUM Ch 59.5.2 "MRCFREQ : Code MRAM Frequency Notifications Register" p 3551 */
400 const uint32_t mrcfreq_word =
402 *ra8_mram_reg32(k_ra8_mram_off_mrcfreq) = mrcfreq_word;
403
404 /* HUM Ch 59.5.3 "MREFREQ : Extra MRAM Frequency Notifications Register" p 3552 */
405 const uint32_t mrefreq_word =
407 *ra8_mram_reg32(k_ra8_mram_off_mrefreq) = mrefreq_word;
408
409 /* HUM Ch 59 "MRCEECC : Code MRAM ECC Encoder Control" p 3580 */
410 uint16_t mrceecc_bits = 0U;
411 if (cfg->ecc_encoder_enable) {
412 mrceecc_bits = k_ra8_mrceecc_mask_eccen;
413 }
415
416 /* HUM Ch 59 "MRCDECC : Code MRAM ECC Decoder Control" p 3554 */
417 uint16_t mrcdecc_bits = 0U;
418 if (cfg->ecc_decoder_enable) {
419 mrcdecc_bits = k_ra8_mrcdecc_mask_dececen;
420 }
422
424
425 /* Lock both program gates so no stray store can program MRAM. */
429
430 /* Clear sticky errors so the new run starts from a clean state. */
431 /* HUM Ch 59 "MRCPS : Code MRAM Program Status Register" p 3577 */
433 /* HUM Ch 59 "MRCRAES : Code MRAM Read Access Error Status" p 3554 */
435 /* HUM Ch 59 "MRERAES : Extra MRAM Read Access Error Status" p 3557 */
437
438 g_flash_rt.initialized = true;
439 g_flash_rt.cb = nullptr;
440 g_flash_rt.user_ctx = nullptr;
441
442 ra8_log_info_val(g_flash_tag, "flash_init mrcfreq", (uint32_t)cfg->mrcfreq_mhz);
443 return k_ra8_ok;
444}
445
447{
448 /* Lock everything, clear sticky errors, re-enable prefetch. */
452 /* If we accidentally left P/E mode on, drop back to read mode. */
453 /* HUM Ch 59 "MENTRYR : Extra MRAM Program-Mode Entry" p 3571 */
455 /* HUM Ch 59 "MRCPS : Code MRAM Program Status Register" p 3577 */
458
459 g_flash_rt.initialized = false;
460 g_flash_rt.cb = nullptr;
461 g_flash_rt.user_ctx = nullptr;
462 return k_ra8_ok;
463}
464
465/* =============================================================================
466 * Public API: status snapshots
467 * =============================================================================
468 */
469
470ra8_err_t ra8_flash_get_status(uint8_t* out_status)
471{
472 RA8_CHECK_NULL_PTR(out_status, g_flash_tag, "out_status must not be nullptr");
473 /* HUM Ch 59 "MRCPS : Code MRAM Program Status Register" p 3577 */
474 *out_status = *ra8_mram_reg8(k_ra8_mram_off_mrcps);
475 return k_ra8_ok;
476}
477
479{
480 RA8_CHECK_NULL_PTR(out, g_flash_tag, "out must not be nullptr");
481 /* HUM Ch 59 "MRCPS : Code MRAM Program Status Register" p 3577 */
483 /* HUM Ch 59 "MASTAT : Extra MRAM Access Status Register" p 3562 */
485 /* HUM Ch 59 "MREZS : Extra MRAM Zeroization Status Register" p 3561 */
487 /* HUM Ch 59 "MCMDR : MACI Command Register" p 3572 */
489 /* HUM Ch 59 "MSTATR : Extra MRAM Status Register" p 3568 */
491 return k_ra8_ok;
492}
493
495{
496 if ((mask & (uint8_t)~k_ra8_mrcps_mask_errors) != 0U) {
498 }
499 /* HUM Ch 59 "MRCPS : Code MRAM Program Status Register" p 3577 -- W1C
500 * for PRGERRC and ECCERRC; other bits are read-only. */
502 return k_ra8_ok;
503}
504
506{
507 bool prefetch = true;
508 if (disable) {
509 prefetch = false;
510 }
512 return k_ra8_ok;
513}
514
545 uint32_t len,
546 uintptr_t win_low,
547 uintptr_t win_high)
548{
549 if (win_low == 0U && win_high == 0U) {
550 return true;
551 }
552 const uintptr_t end_excl = (uintptr_t)((uint64_t)addr + (uint64_t)len);
553 if (addr < win_low) {
554 return false;
555 }
556 if (end_excl > win_high) {
557 return false;
558 }
559 return true;
560}
561
588bool priv_ra8_flash_internal_window_allows(uintptr_t addr, uint32_t len)
589{
591 len,
592 g_flash_rt.win_low,
593 g_flash_rt.win_high);
594}
595
596/* =============================================================================
597 * Public API: direct code-MRAM programming
598 * =============================================================================
599 */
600
625RA8_INTERNAL static ra8_err_t internal_validate_write_block(uint32_t mram_addr, uint32_t len)
626{
627 if (len == 0U || len > k_ra8_mram_write_size_bytes) {
629 }
630 const uint32_t end_excl =
631 (uint32_t)((uint64_t)mram_addr + (uint64_t)len); /* avoids 32-bit overflow */
632 if (mram_addr < (uint32_t)k_ra8_flash_code_start) {
634 }
635 if (end_excl > (uint32_t)k_ra8_flash_code_start + (uint32_t)k_ra8_flash_code_size) {
637 }
638 const uint32_t page_mask = k_ra8_mram_write_size_bytes - 1U;
639 if ((mram_addr & ~page_mask) != ((end_excl - 1U) & ~page_mask)) {
641 }
642 if (!priv_ra8_flash_internal_window_allows((uintptr_t)mram_addr, len)) {
644 }
645 return k_ra8_ok;
646}
647
681 const uint8_t* src,
682 uint32_t len,
683 ra8_flash_world_t world)
684{
687 internal_set_program_gate(world, true);
688
689 volatile uint8_t* dst = (volatile uint8_t*)(uintptr_t)mram_addr;
690 for (uint32_t i = 0U; i < len; ++i) {
691 dst[i] = src[i];
692 }
693
694 __asm__ volatile("" ::: "memory");
695 /* HUM Ch 59 "MRCFLR : Code MRAM Flush Register" p 3580 */
697
699
700 /* Tear down regardless of err so the gate cannot stay open. */
701 internal_set_program_gate(world, false);
704
705 return err;
706}
707
709ra8_flash_write_block(uint32_t mram_addr, const uint8_t* src, uint32_t len, ra8_flash_world_t world)
710{
711 RA8_CHECK_NULL_PTR(src, g_flash_tag, "src must not be nullptr");
712 const ra8_err_t v_err = internal_validate_write_block(mram_addr, len);
713 RA8_RETURN_ON_ERROR(v_err, g_flash_tag, "flash_write: validate");
714
715 /* Step 1: wait for the controller to be idle. */
717 RA8_RETURN_ON_ERROR(err, g_flash_tag, "flash_write: busy wait");
718
719 /* Steps 2-6: gate, write, flush, commit, teardown. */
720 err = internal_flash_program_window(mram_addr, src, len, world);
721 RA8_RETURN_ON_ERROR(err, g_flash_tag, "flash_write: commit wait");
722
723 /* Step 7: error check.
724 * HUM Ch 59 "MRCPS : Code MRAM Program Status Register" p 3601 */
725 const uint8_t status = *ra8_mram_reg8(k_ra8_mram_off_mrcps);
726 if ((status & k_ra8_mrcps_mask_errors) != 0U) {
728 ra8_log_error_val(g_flash_tag, "flash_write: hw error", (uint32_t)status);
729 return k_ra8_err_hw_error;
730 }
731 return k_ra8_ok;
732}
733
735{
736 if ((mram_addr & (k_ra8_mram_block_size_bytes - 1U)) != 0U) {
738 }
739 /* MRAM has no separate erase: erase == program-to-all-ones. */
740 static const uint8_t local_ones[k_ra8_mram_block_size_bytes] = {
741 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU,
742 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU,
743 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU,
744 };
745 return ra8_flash_write_block(mram_addr, local_ones, k_ra8_mram_block_size_bytes, world);
746}
747
748/* =============================================================================
749 * Public API: block protection
750 * =============================================================================
751 */
752
754{
755 if (permanent && !lock) {
756 /* Permanent unlock makes no sense -- the fuse is one-shot. */
758 }
759 uint16_t value;
760 if (world == k_ra8_flash_world_s) {
761 if (lock) {
763 } else {
765 }
766 /* HUM Ch 59 "MRCBPROT1 : Code MRAM Block Protection (S)" p 3577 */
768 } else {
769 if (lock) {
771 } else {
773 }
774 /* HUM Ch 59 "MRCBPROT0 : Code MRAM Block Protection (NS)" p 3576 */
776 }
777 /* The "permanent" flag is conveyed via a configuration-set update of
778 * the OFS region; the per-register write above only takes effect for
779 * this boot. We expose the request for transparency, but defer the
780 * persistent fuse to ``ra8_flash_config_set_write`` for callers who
781 * truly want it. The HUM Ch 7 p 278 OFS layout is the trust anchor. */
782 if (permanent) {
783 ra8_log_warn(g_flash_tag, "permanent block protect requires config-set");
784 }
785 return k_ra8_ok;
786}
787
788/* =============================================================================
789 * Public API: P/E mode transitions
790 * =============================================================================
791 */
792
794{
796 /* HUM Ch 59 "MENTRYR : Extra MRAM Program-Mode Entry" p 3571 */
797 volatile uint16_t* const entry_reg = ra8_mram_reg16(k_ra8_mram_off_mentryr);
798 *entry_reg = k_ra8_mentryr_pe_enter;
799
800 for (uint32_t i = 0U; i < k_ra8_flash_pe_spin_limit; ++i) {
801 /* HUM Ch 59 "MENTRYR : Extra MRAM Program-Mode Entry" p 3571 */
802 const uint16_t v = *entry_reg;
803 bool ready = (v & k_ra8_mentryr_mask_pe_mode) != 0U;
804#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
805 ready = ra8_fake_mmio_poll(entry_reg, i, ready);
806#endif
807 if (ready) {
808 return k_ra8_ok;
809 }
810 }
812}
813
815{
816 /* HUM Ch 59 "MENTRYR : Extra MRAM Program-Mode Entry" p 3571 */
817 volatile uint16_t* const entry_reg = ra8_mram_reg16(k_ra8_mram_off_mentryr);
818 *entry_reg = k_ra8_mentryr_read_mode;
819
820 for (uint32_t i = 0U; i < k_ra8_flash_pe_spin_limit; ++i) {
821 /* HUM Ch 59 "MENTRYR : Extra MRAM Program-Mode Entry" p 3571 */
822 const uint16_t v = *entry_reg;
823 bool ready = (v & k_ra8_mentryr_mask_pe_mode) == 0U;
824#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
825 ready = ra8_fake_mmio_poll(entry_reg, i, ready);
826#endif
827 if (ready) {
829 return k_ra8_ok;
830 }
831 }
833}
834
836{
837 /* HUM Ch 59 "MENTRYR : Extra MRAM Program-Mode Entry" pp 3582+ --
838 * driving MENTRYR with the keyed pause pattern (KEY=0xAA, MENTRY=1,
839 * PCKA=1) halts an in-flight MACI command at the next page
840 * boundary. Poll for PCKA=1 to confirm the pause. */
841 volatile uint16_t* const entry_reg = ra8_mram_reg16(k_ra8_mram_off_mentryr);
842 *entry_reg = k_ra8_mentryr_pe_pause;
843
844 for (uint32_t i = 0U; i < k_ra8_flash_pe_spin_limit; ++i) {
845 /* HUM Ch 59 "MENTRYR" p 3571 */
846 const uint16_t v = *entry_reg;
847 bool ready = (v & k_ra8_mentryr_mask_pcka) != 0U;
848#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
849 ready = ra8_fake_mmio_poll(entry_reg, i, ready);
850#endif
851 if (ready) {
852 return k_ra8_ok;
853 }
854 }
856}
857
859{
860 /* HUM Ch 59 "MENTRYR : Extra MRAM Program-Mode Entry" pp 3582+ --
861 * resume key clears PCKA, leaving MENTRY=1 so programming continues.
862 * Poll for PCKA=0 before returning. */
863 volatile uint16_t* const entry_reg = ra8_mram_reg16(k_ra8_mram_off_mentryr);
864 *entry_reg = k_ra8_mentryr_pe_resume;
865
866 for (uint32_t i = 0U; i < k_ra8_flash_pe_spin_limit; ++i) {
867 /* HUM Ch 59 "MENTRYR" p 3571 */
868 const uint16_t v = *entry_reg;
869 bool ready = (v & k_ra8_mentryr_mask_pcka) == 0U;
870#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
871 ready = ra8_fake_mmio_poll(entry_reg, i, ready);
872#endif
873 if (ready) {
874 return k_ra8_ok;
875 }
876 }
878}
879
880ra8_err_t ra8_flash_lock_set(uintptr_t addr, uint16_t lock_bits)
881{
882 /* Address must lie inside the 1 MiB code-MRAM window. */
883 const uintptr_t code_lo = k_ra8_flash_code_start;
884 const uintptr_t code_hi = code_lo + k_ra8_flash_code_size;
885 if ((addr < code_lo) || (addr >= code_hi)) {
887 }
888 /* Validate the keyed value: bits [15:8] must be one of the two
889 * documented keys (0x88 for MRCBPROT0, 0x44 for MRCBPROT1). */
890 enum : uint16_t {
891 k_ra8_mrcbprot_key_byte_mask = 0xFF00U,
892 k_ra8_mrcbprot_key_ns = 0x8800U,
893 k_ra8_mrcbprot_key_s = 0x4400U,
894 };
895 enum : uint32_t {
896 k_ra8_mrcbprot_secure_bit = 0x00080000UL,
897 };
898 const uint16_t key = (uint16_t)(lock_bits & k_ra8_mrcbprot_key_byte_mask);
899 const bool key_ns = (key == k_ra8_mrcbprot_key_ns);
900 const bool key_s = (key == k_ra8_mrcbprot_key_s);
901 if (!key_ns && !key_s) {
903 }
904
905 const bool is_secure = ((addr & (uintptr_t)k_ra8_mrcbprot_secure_bit) != 0U);
906 if (is_secure) {
907 /* HUM Ch 59 "MRCBPROT1 : Code MRAM Block Protection (S)" p 3577 */
909 } else {
910 /* HUM Ch 59 "MRCBPROT0 : Code MRAM Block Protection (NS)" p 3576 */
912 }
913 return k_ra8_ok;
914}
915
916/* =============================================================================
917 * Public API: forced stop / reset
918 * =============================================================================
919 */
920
922{
923 /* HUM Ch 59 "MACI Command-Issuing Area" p 3550 */
926 if (err != k_ra8_ok) {
927 return err;
928 }
929
930 /* HUM Ch 59 "MASTAT : Extra MRAM Access Status Register" p 3562 */
931 const uint8_t mastat = *ra8_mram_reg8(k_ra8_mram_off_mastat);
932 if ((mastat & k_ra8_mastat_mask_cmdlk) != 0U) {
933 return k_ra8_err_hw_error;
934 }
935 return k_ra8_ok;
936}
937
939{
940 RA8_VALIDATE_INIT(g_flash_rt.initialized, g_flash_tag, "flash_reset before init");
942 if (err != k_ra8_ok) {
943 return err;
944 }
945 ra8_err_t stop_err = ra8_flash_force_stop();
946 /* Clear status whether or not the stop succeeded. */
947 /* HUM Ch 59 "MACI Command-Issuing Area" p 3550 */
951 if (stop_err != k_ra8_ok) {
952 return stop_err;
953 }
954 return exit_err;
955}
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_VALIDATE_INIT(initialized, tag, message)
Precondition: module must be initialized.
Definition ra8_check.h:334
#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_out_of_range
Sensor or peripheral output out of valid range.
Definition ra8_err.h:337
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ 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_hw_error
Generic hardware fault detected (error flag set, fault interrupt).
Definition ra8_err.h:310
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
bool priv_ra8_flash_internal_window_allows_pure(uintptr_t addr, uint32_t len, uintptr_t win_low, uintptr_t win_high)
Pure (state-free) window allow/deny predicate – see priv_ra8_flash_internal_window_allows_pure in ra8...
Definition ra8_flash.c:544
ra8_err_t ra8_flash_init(const ra8_flash_cfg_t *cfg)
Initialise the MRAM controller for safe read access.
Definition ra8_flash.c:386
void priv_ra8_flash_internal_maci_cmd8(uint8_t byte)
Send a single byte through the MACI command-issuing area.
Definition ra8_flash.c:341
ra8_err_t ra8_flash_write_block(uint32_t mram_addr, const uint8_t *src, uint32_t len, ra8_flash_world_t world)
Program 1..32 contiguous bytes into one MRAM page.
Definition ra8_flash.c:709
ra8_err_t ra8_flash_erase_block(uint32_t mram_addr, ra8_flash_world_t world)
Erase (= program to all 0xFF) one 32-byte MRAM block.
Definition ra8_flash.c:734
ra8_flash_runtime_t g_flash_rt
Single shared ra8_flash runtime-state instance.
Definition ra8_flash.c:67
ra8_err_t ra8_flash_lock_set(uintptr_t addr, uint16_t lock_bits)
Programme MRCBPROT0/1 lock bits at addr.
Definition ra8_flash.c:880
static ra8_err_t internal_flash_program_window(uint32_t mram_addr, const uint8_t *src, uint32_t len, ra8_flash_world_t world)
Steps 2-6 of the HUM block-write sequence.
Definition ra8_flash.c:680
ra8_err_t ra8_flash_reset(void)
Reset the MRAM peripheral and clear status.
Definition ra8_flash.c:938
ra8_err_t ra8_flash_suspend(void)
Pause an in-flight MRAM program/erase operation.
Definition ra8_flash.c:835
void priv_ra8_flash_internal_set_prefetch(bool enable)
Set MRCPFB.MPFBEN to enable/disable the prefetch buffer.
Definition ra8_flash.c:296
ra8_err_t priv_ra8_flash_internal_wait_mrdy(uint32_t limit)
Spin until MSTATR.MRDY rises or limit elapses.
Definition ra8_flash.c:203
ra8_err_t ra8_flash_set_rww_disable(bool disable)
Disable the read-while-write prefetch buffer.
Definition ra8_flash.c:505
ra8_err_t priv_ra8_flash_internal_wait_buffer_ready_call(uint32_t limit)
Test-access wrapper for internal_wait_buffer_ready.
Definition ra8_flash.c:124
bool priv_ra8_flash_internal_window_allows(uintptr_t addr, uint32_t len)
Test whether [addr, addr+len) lies inside the configured soft window.
Definition ra8_flash.c:588
static ra8_err_t internal_wait_buffer_ready(uint32_t limit)
Wait for MRCPS.PRGBSYC = 0 and ABUFFULL = 0 (buffer ready).
Definition ra8_flash.c:93
void priv_ra8_flash_internal_maci_cmd16(uint16_t half)
Send a halfword through the MACI command-issuing area.
Definition ra8_flash.c:369
ra8_err_t ra8_flash_get_status(uint8_t *out_status)
Snapshot the program-status register.
Definition ra8_flash.c:470
static ra8_err_t internal_validate_write_block(uint32_t mram_addr, uint32_t len)
Validate the write_block destination range and alignment.
Definition ra8_flash.c:625
static ra8_err_t internal_wait_commit_done(uint32_t limit)
Wait for MRCPS.ABUFEMP = 1 and PRGBSYC = 0 (commit done).
Definition ra8_flash.c:148
ra8_err_t priv_ra8_flash_internal_wait_commit_done_call(uint32_t limit)
Test-access wrapper for internal_wait_commit_done.
Definition ra8_flash.c:179
ra8_err_t ra8_flash_get_extended_status(ra8_flash_status_ext_t *out)
Snapshot every status register the HUM exposes.
Definition ra8_flash.c:478
ra8_err_t ra8_flash_enter_pe_mode(void)
Enter MRAM P/E mode.
Definition ra8_flash.c:793
const char * g_flash_tag
Shared log tag string for the ra8_flash module.
Definition ra8_flash.c:50
ra8_err_t ra8_flash_resume(void)
Resume a previously-paused MRAM operation.
Definition ra8_flash.c:858
ra8_err_t ra8_flash_block_protect_set(ra8_flash_world_t world, bool lock, bool permanent)
Set or clear the per-world block-protection lock.
Definition ra8_flash.c:753
ra8_err_t ra8_flash_clear_status(uint8_t mask)
Clear sticky program-error bits in MRCPS.
Definition ra8_flash.c:494
static void internal_set_program_gate(ra8_flash_world_t world, bool enable)
Open or close the per-world program-control gate.
Definition ra8_flash.c:232
ra8_err_t ra8_flash_force_stop(void)
Issue the MACI forced stop command.
Definition ra8_flash.c:921
ra8_err_t ra8_flash_deinit(void)
Deinitialise: lock all program gates and re-enable prefetch.
Definition ra8_flash.c:446
ra8_err_t ra8_flash_exit_pe_mode(void)
Exit MRAM P/E mode (return to read mode).
Definition ra8_flash.c:814
static void internal_set_hsp_mode(bool enable)
Toggle high-speed program mode (MRPSC.MHSPEN).
Definition ra8_flash.c:270
Code MRAM + Extra MRAM + Option-Setting driver – DANGEROUS, brick-capable.
Test-access surface for ra8_flash internal helpers (MC/DC).
@ k_ra8_flash_mrefreq_key
RA8 flash mrefreq key.
@ k_ra8_flash_mrcfreq_key
RA8 flash mrcfreq key.
@ k_ra8_flash_freq_key_shift
KEY[7:0] @ [31:24] in MRCFREQ/MREFREQ.
@ k_ra8_flash_pe_spin_limit
P/E entry spin limit.
@ k_ra8_flash_max_mrcfreq_mhz
MRCMHZ <= 250.
@ k_ra8_flash_maci_spin_limit
MACI command spin limit.
@ k_ra8_flash_max_mrefreq_mhz
MREMHZ <= 125.
@ k_ra8_flash_busy_spin_limit
Direct-write busy spin.
Flash / MRAM controller register layout for the Renesas RA8D2.
@ k_ra8_mrcbprot0_key_unlock
Cancel block protect.
@ k_ra8_mrcbprot0_key_lock
Keep block protect on.
@ k_ra8_mrcbprot1_key_lock
RA8 mrcbprot1 key lock.
@ k_ra8_mrcbprot1_key_unlock
RA8 mrcbprot1 key unlock.
static volatile uint8_t * ra8_mram_reg8(uint16_t off)
Pointer to a byte-wide MRMS register at offset off.
static volatile uint16_t * ra8_mram_cmd16(void)
Pointer to the MACI command-issuing area, halfword-wide.
static volatile uint8_t * ra8_mram_cmd8(void)
Pointer to the MACI command-issuing area, byte-wide.
@ k_ra8_mrcpc1_key_enable
RA8 mrcpc1 key enable.
@ k_ra8_mrcpc1_key_disable
RA8 mrcpc1 key disable.
@ k_ra8_mrceecc_mask_eccen
Encoder enable bit.
@ k_ra8_mrceecc_key_shift
Pre-shifted KEY[15:8]=0xC0.
@ k_ra8_mastat_mask_cmdlk
Command lock latched.
@ k_ra8_flash_code_size
1 MiB of code MRAM.
@ k_ra8_flash_code_start
Start of code MRAM region.
static volatile uint16_t * ra8_mram_reg16(uint16_t off)
Pointer to a halfword-wide MRMS register at offset off.
@ k_ra8_mrcflr_key_flush
RA8 mrcflr key flush.
@ k_ra8_mrcpc0_key_disable
RA8 mrcpc0 key disable.
@ k_ra8_mrcpc0_key_enable
RA8 mrcpc0 key enable.
@ k_ra8_mstatr_mask_mrdy
MRE ready.
@ k_ra8_mrpsc_mask_mhspen
High-speed program enable.
@ k_ra8_mentryr_mask_pcka
Pause / resume gate bit.
@ k_ra8_mentryr_mask_pe_mode
MENTRY status bit.
@ k_ra8_mentryr_pe_resume
KEY=0xAA, MENTRY=1, PCKA=0.
@ k_ra8_mentryr_pe_enter
KEY=0xAA, MENTRY=1.
@ k_ra8_mentryr_pe_pause
KEY=0xAA, MENTRY=1, PCKA=1.
@ k_ra8_mentryr_read_mode
KEY=0xAA, MENTRY=0.
static volatile uint32_t * ra8_mram_reg32(uint16_t off)
Pointer to a word-wide MRMS register at offset off.
@ k_ra8_maci_cmd_forced_stop
Abort in-flight command processing.
@ k_ra8_maci_cmd_status_clear
Clear the command-locked state.
@ k_ra8_mram_block_size_bytes
One programmable block.
@ k_ra8_mram_write_size_bytes
Minimum programmable unit.
@ k_ra8_mram_off_mentryr
RA8 MRAM off mentryr.
@ k_ra8_mram_off_mrcps
RA8 MRAM off mrcps.
@ k_ra8_mram_off_mrcfreq
RA8 MRAM off mrcfreq.
@ k_ra8_mram_off_mrefreq
RA8 MRAM off mrefreq.
@ k_ra8_mram_off_mrceecc
RA8 MRAM off mrceecc.
@ k_ra8_mram_off_mrcbprot1
RA8 MRAM off mrcbprot1.
@ k_ra8_mram_off_mrcflr
RA8 MRAM off mrcflr.
@ k_ra8_mram_off_mrcraes
RA8 MRAM off mrcraes.
@ k_ra8_mram_off_mrcpfb
RA8 MRAM off mrcpfb.
@ k_ra8_mram_off_mcmdr
RA8 MRAM off mcmdr.
@ k_ra8_mram_off_mrcdecc
RA8 MRAM off mrcdecc.
@ k_ra8_mram_off_mrcpc0
RA8 MRAM off mrcpc0.
@ k_ra8_mram_off_mrcbprot0
RA8 MRAM off mrcbprot0.
@ k_ra8_mram_off_mrezs
RA8 MRAM off mrezs.
@ k_ra8_mram_off_mrpsc
RA8 MRAM off mrpsc.
@ k_ra8_mram_off_mastat
RA8 MRAM off mastat.
@ k_ra8_mram_off_mrcpc1
RA8 MRAM off mrcpc1.
@ k_ra8_mram_off_mstatr
RA8 MRAM off mstatr.
@ k_ra8_mram_off_mreraes
RA8 MRAM off mreraes.
@ k_ra8_mrcdecc_mask_dececen
Decoder enable (ECCSELC).
@ k_ra8_mrcdecc_key_shift
Pre-shifted KEY[15:8]=0x8C.
@ k_ra8_mrcps_mask_errors
W1C: PRGERRC + ECCERRC.
@ k_ra8_mrcps_mask_prgbsyc
Code MRAM program busy.
@ k_ra8_mrcps_mask_abufemp
Address buffer empty.
@ k_ra8_mrcps_mask_abuffull
Address buffer full.
ra8_flash_world_t
Which secure-attribution gate to open for a write.
@ k_ra8_flash_world_s
Open MRCPC1 (secure half).
@ k_ra8_flash_world_ns
Open MRCPC0 (non-secure half).
Bounded wait-flag primitives for RA8D2 HAL drivers.
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_warn(tag, message)
RA8 log warn.
Definition ra8_log.h:347
#define ra8_log_info_val(tag, message, value)
RA8 log info val.
Definition ra8_log.h:366
#define ra8_log_error_val(tag, message, value)
RA8 log error val.
Definition ra8_log.h:337
Initialisation descriptor for ra8_flash_init.
uint8_t mrefreq_mhz
Extra MRAM clock in MHz, 0..0x07D (125 MHz).
bool prefetch_en
true -> leave prefetch enabled at init.
bool ecc_encoder_enable
true -> MRCEECC.ECCEN=1 (default).
uint16_t mrcfreq_mhz
Code MRAM clock in MHz, 0..0x0FA (250 MHz).
bool ecc_decoder_enable
true -> MRCDECC.DECECEN=1 (default).
File-scope runtime state shared across the ra8_flash TUs.
Extended status snapshot (MRCPS + MSTATR + MASTAT + MREZS).
uint8_t mrcps
MRCPS bits (HUM Ch 59 p 3601).
uint32_t mstatr
MSTATR bits (HUM Ch 59 p 3578).
uint8_t mastat
MASTAT bits (HUM Ch 59 p 3577).
uint16_t mcmdr
MCMDR bits (HUM Ch 59 p 3589).
uint8_t mrezs
MREZS bits (HUM Ch 59 p 3565).