|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
MRAM slot program / verify for the USB-DFU bootloader core. More...
#include <string.h>#include "ra8_dfu.h"#include "ra8_dfu_internal.h"#include "ra8_flash.h"#include "ra8_register_guard.h"Go to the source code of this file.
Enumerations | |
| enum | ra8_dfu_prog_cfg_t : uint16_t { k_ra8_dfu_prog_mrcfreq_mhz = 250U , k_ra8_dfu_prog_mrefreq_mhz = 125U } |
| MRAM clock notifications used to (re)open the controller. More... | |
| enum | ra8_dfu_prog_fill_t : uint8_t { k_ra8_dfu_prog_erased_byte = 0xFFU } |
| MRAM erased-state fill byte. More... | |
Functions | |
| ra8_err_t | priv_dfu_write_secure (uintptr_t addr, const uint8_t *src, uint32_t len) |
| Implementation of priv_dfu_write_secure() – IRQ-masked, page-at-a-time erase-then-program through the secure MRAM gate. | |
| uintptr_t | ra8_dfu_slot_base (ra8_dfu_slot_t slot) |
| Return the MRAM base address of a slot. | |
| ra8_dfu_slot_t | ra8_dfu_other_slot (ra8_dfu_slot_t slot) |
| Return the opposite slot (A<->B). | |
| ra8_err_t | ra8_dfu_read_header (ra8_dfu_slot_t slot, ra8_dfu_img_hdr_t *out_hdr) |
| Copy a slot's 32-byte header out of MRAM. | |
| bool | ra8_dfu_slot_valid (ra8_dfu_slot_t slot) |
| Implementation of ra8_dfu_slot_valid() – guards the CRC read so a bogus img_len cannot drive an out-of-bounds MRAM fold. | |
| ra8_err_t | ra8_dfu_slot_seq (ra8_dfu_slot_t slot, uint32_t *out_seq) |
| Read a slot header's sequence number (0 if the magic is wrong). | |
| ra8_err_t | ra8_dfu_program_prepare (ra8_dfu_slot_t inactive) |
| Open ra8_flash and fence all writes to one slot's window. | |
| ra8_err_t | ra8_dfu_program_image (ra8_dfu_slot_t inactive, uint32_t img_offset, const uint8_t *data, uint32_t len) |
| Program one image chunk into the inactive slot's body. | |
| ra8_err_t | ra8_dfu_program_commit (ra8_dfu_slot_t inactive, uint32_t img_len, uint32_t seq) |
| Finalize a slot: CRC the programmed body, then program the header. | |
| ra8_err_t | ra8_dfu_program_verify (ra8_dfu_slot_t slot) |
| Read-back verify: re-CRC a slot's body against its stored header. | |
Variables | |
| static const ra8_flash_cfg_t | s_ra8_dfu_flash_cfg |
| Default controller bring-up descriptor for ra8_dfu_program_prepare. | |
MRAM slot program / verify for the USB-DFU bootloader core.
Erases, programs, and read-back-verifies the inactive application slot over ra8_flash, and reads slot headers for the boot decision. The MRAM controller's program loop must NOT execute from the MRAM it touches (see ra8_flash.h); on the firmware target each consumer's linker script places this TU and ra8_flash in SRAM. Under RA8_OFF_TARGET the code-MRAM window is backed by fake memory, so the program -> read-back -> verify round-trip is exercised directly by the host unit tests.
Definition in file ra8_dfu_program.c.
| enum ra8_dfu_prog_cfg_t : uint16_t |
MRAM clock notifications used to (re)open the controller.
Mirrors the EK-RA8D2 code/extra MRAM operating clocks the apps advertise via MRCFREQ / MREFREQ (HUM Ch 59.4.3 p 3550).
| Enumerator | |
|---|---|
| k_ra8_dfu_prog_mrcfreq_mhz | Code-MRAM clock notification (MHz). |
| k_ra8_dfu_prog_mrefreq_mhz | Extra-MRAM clock notification (MHz). |
Definition at line 34 of file ra8_dfu_program.c.
| enum ra8_dfu_prog_fill_t : uint8_t |
MRAM erased-state fill byte.
Value every byte holds after an MRAM erase; used to seed the SRAM-resident all-ones page so the erase baseline operand never has to be read out of code-MRAM while the array is busy (see ::internal_write_secure).
| Enumerator | |
|---|---|
| k_ra8_dfu_prog_erased_byte | Erased-state byte for an MRAM page. |
Definition at line 46 of file ra8_dfu_program.c.
| ra8_err_t priv_dfu_write_secure | ( | uintptr_t | addr, |
| const uint8_t * | src, | ||
| uint32_t | len ) |
Implementation of priv_dfu_write_secure() – IRQ-masked, page-at-a-time erase-then-program through the secure MRAM gate.
Program len bytes at addr through the SECURE MRAM gate.
Definition at line 61 of file ra8_dfu_program.c.
References k_ra8_dfu_page_size, k_ra8_dfu_prog_erased_byte, k_ra8_err_invalid_arg, k_ra8_flash_world_s, k_ra8_ok, memset(), ra8_flash_write_block(), RA8_PRIV, ra8_register_guard_enter(), and ra8_register_guard_exit().
Referenced by ra8_dfu_program_commit(), and ra8_dfu_program_image().
| ra8_dfu_slot_t ra8_dfu_other_slot | ( | ra8_dfu_slot_t | slot | ) |
Return the opposite slot (A<->B).
Inverts the slot identifier: Slot A returns Slot B and any other value (Slot B or k_ra8_dfu_slot_none) returns Slot A. Used by the DFU device and host glue to locate the inactive (write-target) slot when the active slot is known. Passing k_ra8_dfu_slot_none returns k_ra8_dfu_slot_a by the else branch, consistent with "no preference -> start with A".
| [in] | slot | Slot identifier (A or B). |
| k_ra8_dfu_slot_b | Input was k_ra8_dfu_slot_a. |
| k_ra8_dfu_slot_a | Input was k_ra8_dfu_slot_b or k_ra8_dfu_slot_none. |
Definition at line 117 of file ra8_dfu_program.c.
References k_ra8_dfu_slot_a, and k_ra8_dfu_slot_b.
Referenced by blc_decide().
|
nodiscard |
Finalize a slot: CRC the programmed body, then program the header.
Folds ra8_dfu_crc32 over the just-programmed body in MRAM, builds a ra8_dfu_img_hdr_t (magic, the given seq, img_len, that CRC, and entry = k_ra8_dfu_run_base), and programs the 32-byte header LAST into the slot's last page. After this the slot is bootable; a power loss before the header lands leaves the slot header erased (invalid) – never half-valid.
| [in] | inactive | Slot being committed. |
| [in] | img_len | Total image-body length programmed; 32-byte multiple. |
| [in] | seq | Sequence number to stamp (caller uses other-slot seq + 1). |
| k_ra8_ok | Header programmed; slot now valid. |
| k_ra8_err_invalid_arg | inactive none/invalid or img_len out of range. |
| k_ra8_err_hw_error | Controller reported a program error. |
Definition at line 226 of file ra8_dfu_program.c.
References ra8_dfu_img_hdr_t::entry, ra8_dfu_img_hdr_t::img_crc32, ra8_dfu_img_hdr_t::img_len, k_ra8_dfu_hdr_magic, k_ra8_dfu_hdr_offset, k_ra8_dfu_hdr_size, k_ra8_dfu_img_max, k_ra8_dfu_page_size, k_ra8_dfu_run_base, k_ra8_err_invalid_arg, ra8_dfu_img_hdr_t::magic, priv_dfu_write_secure(), ra8_dfu_crc32(), ra8_dfu_slot_base(), and ra8_dfu_img_hdr_t::seq.
|
nodiscard |
Program one image chunk into the inactive slot's body.
Writes len bytes at slot_base + img_offset through the SECURE MRAM gate (k_ra8_flash_world_s). Each 32-byte page is erased to 0xFF then programmed, IRQ-masked, by the SRAM-resident internal_write_secure (ra8_dfu_program.c). The header page (the slot's last page, at slot_base + k_ra8_dfu_hdr_offset) is left untouched until ra8_dfu_program_commit, so a torn download never leaves a valid-looking header over a partial image.
| [in] | inactive | Slot being programmed (must match ra8_dfu_program_prepare). |
| [in] | img_offset | Byte offset into the image body; 32-byte aligned. |
| [in] | data | Source bytes (non-NULL). |
| [in] | len | Length in bytes; non-zero multiple of k_ra8_dfu_page_size. |
| k_ra8_ok | Chunk programmed. |
| k_ra8_err_null_ptr | data is NULL. |
| k_ra8_err_invalid_arg | inactive none/invalid, bad alignment, or the chunk would exceed k_ra8_dfu_img_max. |
| k_ra8_err_out_of_range | The access window rejected the address. |
| k_ra8_err_hw_error | Controller reported a program error. |
Definition at line 203 of file ra8_dfu_program.c.
References k_ra8_dfu_img_max, k_ra8_dfu_page_size, k_ra8_err_invalid_arg, k_ra8_err_null_ptr, priv_dfu_write_secure(), and ra8_dfu_slot_base().
|
nodiscard |
Open ra8_flash and fence all writes to one slot's window.
Opens the MRAM controller (ra8_flash_open) and sets the software access window (ra8_flash_set_window) to exactly the inactive slot so any stray write outside it is rejected. It does NOT erase: there is no full-slot erase (which would block USB long enough to time out the host's DFU_GETSTATUS), and no header pre-erase either. Instead ra8_dfu_program_image erases each 32-byte page to 0xFF immediately before programming its body, and ra8_dfu_program_commit writes the header LAST – so a torn download leaves the OLD header over a NEW partial image, whose CRC will not match -> invalid. Brick defense: the bootloader region and the active slot are outside the window and untouchable.
| [in] | inactive | The slot to (re)program (A or B; must NOT be the running one). |
| k_ra8_ok | Slot opened and the write window fenced to it. |
| k_ra8_err_invalid_arg | inactive is none/invalid. |
| k_ra8_err_hw_error | Controller bring-up reported an error. |
Definition at line 181 of file ra8_dfu_program.c.
References k_ra8_dfu_slot_size, k_ra8_err_invalid_arg, k_ra8_ok, ra8_dfu_slot_base(), ra8_flash_open(), ra8_flash_set_window(), and s_ra8_dfu_flash_cfg.
|
nodiscard |
Read-back verify: re-CRC a slot's body against its stored header.
| [in] | slot | Slot to verify (A or B). |
| k_ra8_ok | Header valid and the body CRC matches. |
| k_ra8_err_invalid_arg | slot is none/invalid. |
| k_ra8_err_crc_mismatch | Header invalid or the recomputed CRC differs. |
Definition at line 252 of file ra8_dfu_program.c.
References k_ra8_err_crc_mismatch, k_ra8_err_invalid_arg, k_ra8_ok, ra8_dfu_slot_base(), and ra8_dfu_slot_valid().
|
nodiscard |
Copy a slot's 32-byte header out of MRAM.
| [in] | slot | Slot to read (A or B). |
| [out] | out_hdr | Destination header (non-NULL). |
| k_ra8_ok | Header copied. |
| k_ra8_err_invalid_arg | slot is none/invalid. |
| k_ra8_err_null_ptr | out_hdr is NULL. |
Definition at line 122 of file ra8_dfu_program.c.
References k_ra8_dfu_hdr_offset, k_ra8_err_invalid_arg, k_ra8_err_null_ptr, k_ra8_ok, memcpy(), and ra8_dfu_slot_base().
Referenced by blc_boot_slot(), ra8_dfu_slot_seq(), and ra8_dfu_slot_valid().
| uintptr_t ra8_dfu_slot_base | ( | ra8_dfu_slot_t | slot | ) |
Return the MRAM base address of a slot.
Maps the ra8_dfu_slot_t identifier to its fixed MRAM window start address. Slot A maps to k_ra8_dfu_slot_a_base and Slot B maps to k_ra8_dfu_slot_b_base. Returns 0 for k_ra8_dfu_slot_none or any out-of-range value so callers can detect the sentinel without a separate validity test.
| [in] | slot | Slot identifier. |
| k_ra8_dfu_slot_a_base | Slot A (slot == k_ra8_dfu_slot_a). |
| k_ra8_dfu_slot_b_base | Slot B (slot == k_ra8_dfu_slot_b). |
| 0 | slot is k_ra8_dfu_slot_none or out of range. |
Definition at line 99 of file ra8_dfu_program.c.
References k_ra8_dfu_slot_a, k_ra8_dfu_slot_a_base, k_ra8_dfu_slot_b, k_ra8_dfu_slot_b_base, and k_ra8_dfu_slot_none.
Referenced by blc_boot_slot(), ra8_dfu_program_commit(), ra8_dfu_program_image(), ra8_dfu_program_prepare(), ra8_dfu_program_verify(), ra8_dfu_read_header(), and ra8_dfu_slot_valid().
|
nodiscard |
Read a slot header's sequence number (0 if the magic is wrong).
| [in] | slot | Slot to read (A or B). |
| [out] | out_seq | Destination sequence (non-NULL); 0 when magic mismatches. |
| k_ra8_ok | *out_seq populated (0 if header magic wrong). |
| k_ra8_err_invalid_arg | slot is none/invalid. |
| k_ra8_err_null_ptr | out_seq is NULL. |
Definition at line 167 of file ra8_dfu_program.c.
References k_ra8_dfu_hdr_magic, k_ra8_err_null_ptr, k_ra8_ok, ra8_dfu_img_hdr_t::magic, ra8_dfu_read_header(), and ra8_dfu_img_hdr_t::seq.
Referenced by blc_decide().
| bool ra8_dfu_slot_valid | ( | ra8_dfu_slot_t | slot | ) |
Implementation of ra8_dfu_slot_valid() – guards the CRC read so a bogus img_len cannot drive an out-of-bounds MRAM fold.
Validate a slot live: header magic/length/CRC over its real image.
Definition at line 142 of file ra8_dfu_program.c.
References ra8_dfu_img_hdr_t::img_len, k_ra8_dfu_img_max, k_ra8_dfu_page_size, k_ra8_ok, ra8_dfu_crc32(), ra8_dfu_hdr_valid(), ra8_dfu_read_header(), and ra8_dfu_slot_base().
Referenced by blc_decide(), dfu_host_pass(), and ra8_dfu_program_verify().
|
static |
Default controller bring-up descriptor for ra8_dfu_program_prepare.
Definition at line 51 of file ra8_dfu_program.c.
Referenced by ra8_dfu_program_prepare().