|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Cortex-M85 L1 cache maintenance, enable/disable, and I-cache invalidate. More...
#include "ra8_cache.h"#include <stdint.h>#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_hw_intrinsics.h"Go to the source code of this file.
Enumerations | |
| enum | ra8_cache_reg_addr_t : uintptr_t { k_ra8_cache_ccr = 0xE000ED14UL , k_ra8_cache_ctr = 0xE000ED7CUL , k_ra8_cache_ccsidr = 0xE000ED80UL , k_ra8_cache_csselr = 0xE000ED84UL , k_ra8_cache_iciallu = 0xE000EF50UL , k_ra8_cache_dcimvac = 0xE000EF5CUL , k_ra8_cache_dcisw = 0xE000EF60UL , k_ra8_cache_dccmvac = 0xE000EF68UL , k_ra8_cache_dccimvac = 0xE000EF70UL , k_ra8_cache_dccisw = 0xE000EF74UL } |
| Arm v8-M SCB cache-maintenance register addresses (PPB 0xE000Exxx). More... | |
| enum | ra8_cache_field_t : uint32_t { k_ra8_cache_word_bytes = 4U , k_ra8_cache_ctr_dmin_shift = 16U , k_ra8_cache_ctr_dmin_mask = 0xFU , k_ra8_cache_ccsidr_sets_sh = 13U , k_ra8_cache_ccsidr_sets_msk = 0x7FFFU , k_ra8_cache_ccsidr_assoc_sh = 3U , k_ra8_cache_ccsidr_assoc_mk = 0x3FFU , k_ra8_cache_dcisw_set_shift = 5U , k_ra8_cache_dcisw_way_shift = 30U , k_ra8_cache_ccr_ic_bit = 1UL << 17 , k_ra8_cache_ccr_dc_bit = 1UL << 16 } |
| Bit positions, masks, and sizes for the CTR / CCSIDR / DCISW fields. More... | |
Functions | |
| static volatile uint32_t * | internal_ra8_cache_reg (ra8_cache_reg_addr_t addr) |
| Typed pointer to a 32-bit SCB cache register. | |
| uint32_t | ra8_cache_dcache_line_bytes (void) |
| Smallest Cortex-M85 D-cache line size, in bytes. | |
| static uint32_t | internal_ra8_cache_span_lines (uintptr_t addr, uint32_t size, uint32_t line, uintptr_t *out_start) |
Number of cache lines spanning size bytes from addr. | |
| static ra8_err_t | internal_ra8_cache_maintain_range (const void *addr, uint32_t size, ra8_cache_reg_addr_t reg) |
| Apply a by-MVA maintenance op to every line of a range. | |
| ra8_err_t | ra8_cache_dcache_clean_by_addr (const void *addr, uint32_t size) |
| Clean (write back) the D-cache lines covering a byte range. | |
| ra8_err_t | ra8_cache_dcache_invalidate_by_addr (const void *addr, uint32_t size) |
| Invalidate (drop) the D-cache lines covering a byte range. | |
| ra8_err_t | ra8_cache_dcache_clean_invalidate_by_addr (const void *addr, uint32_t size) |
| Clean and invalidate the D-cache lines covering a byte range. | |
| static void | internal_ra8_cache_setway_all (ra8_cache_reg_addr_t op_reg) |
| Apply a set/way maintenance op to every line of the L1 D-cache. | |
| void | ra8_cache_dcache_invalidate_all (void) |
| Invalidate the entire D-cache by set/way. | |
| void | ra8_cache_icache_invalidate_all (void) |
| Invalidate the entire Cortex-M85 L1 instruction cache (ICIALLU). | |
| void | ra8_cache_icache_enable (void) |
| Invalidate then enable the Cortex-M85 L1 instruction cache (CCR.IC). | |
| void | ra8_cache_icache_disable (void) |
| Disable the Cortex-M85 L1 instruction cache and invalidate it (CCR.IC). | |
| void | ra8_cache_dcache_enable (void) |
| Invalidate then enable the Cortex-M85 L1 data cache (CCR.DC). | |
| void | ra8_cache_dcache_disable (void) |
| Disable the Cortex-M85 L1 data cache, cleaning dirty lines (CCR.DC). | |
| void | ra8_cache_enable (void) |
| Enable both Cortex-M85 L1 caches (I-cache then D-cache). | |
Variables | |
| static const char *const | s_tag = "ra8_cache" |
| Module log tag. | |
Cortex-M85 L1 cache maintenance, enable/disable, and I-cache invalidate.
Implements ::ra8_cache.h against the Arm v8-M System Control Block cache registers (PPB window 0xE000Exxx). The by-address operations walk the cache lines spanning a byte range, writing each line's address to the relevant maintenance register (DCCMVAC / DCIMVAC / DCCIMVAC) with the line size read at run time from CTR. internal_ra8_cache_setway_all walks the geometry from CCSIDR and applies a set/way op to every {set,way} – DCISW for the cold invalidate (ra8_cache_dcache_invalidate_all / enable) and DCCISW for the clean+invalidate used by ra8_cache_dcache_disable – mirroring the CMSIS `SCB*DCache idioms. The enable/disable primitives read-modify-write SCB.CCR (bits IC / DC) and the I-cache path writes ICIALLU, encoding the exact sequences the boot system_init.c` copies previously hand-rolled (issue #577).
These are Arm-architecture registers, so the inline comments reference the Arm v8-M Architecture Reference Manual (the "Arm v8-M ARM") rather than the RA8D2 Hardware User's Manual. On a host build the SCB window is backed by the fake MMIO map, so the writes are observable to unit tests.
Definition in file ra8_cache.c.
| enum ra8_cache_field_t : uint32_t |
Bit positions, masks, and sizes for the CTR / CCSIDR / DCISW fields.
Arm v8-M ARM register descriptions for CTR, CCSIDR, and DCISW.
Definition at line 67 of file ra8_cache.c.
| enum ra8_cache_reg_addr_t : uintptr_t |
Arm v8-M SCB cache-maintenance register addresses (PPB 0xE000Exxx).
Arm v8-M ARM B11 "System Control Block". Mapped into the fake core window (0xE0000000) on a host build, real PPB on silicon.
Definition at line 49 of file ra8_cache.c.
|
static |
Apply a by-MVA maintenance op to every line of a range.
Shared body of the three public by-address operations: validate the range, compute its line span, and write each line address to reg, bracketed by data barriers.
| [in] | addr | Range start (must be non-NULL). |
| [in] | size | Range length in bytes (0 is a success no-op). |
| [in] | reg | Maintenance register (DCCMVAC / DCIMVAC / DCCIMVAC). |
| k_ra8_ok | Range maintained (or size == 0). |
| k_ra8_err_null_ptr | addr was NULL. |
addr is non-NULL unless size is zero. reg is a by-MVA maintenance register address. reg. Definition at line 162 of file ra8_cache.c.
References internal_ra8_cache_reg(), internal_ra8_cache_span_lines(), k_ra8_ok, ra8_cache_dcache_line_bytes(), RA8_CHECK_NULL_PTR, ra8_hw_dsb(), ra8_hw_isb(), and s_tag.
Referenced by ra8_cache_dcache_clean_by_addr(), ra8_cache_dcache_clean_invalidate_by_addr(), and ra8_cache_dcache_invalidate_by_addr().
|
inlinestatic |
Typed pointer to a 32-bit SCB cache register.
| [in] | addr | One of ra8_cache_reg_addr_t. |
addr is a valid SCB cache-register address. Definition at line 92 of file ra8_cache.c.
References RA8_INTERNAL.
Referenced by internal_ra8_cache_maintain_range(), internal_ra8_cache_setway_all(), ra8_cache_dcache_disable(), ra8_cache_dcache_enable(), ra8_cache_dcache_line_bytes(), ra8_cache_icache_disable(), ra8_cache_icache_enable(), and ra8_cache_icache_invalidate_all().
|
static |
Apply a set/way maintenance op to every line of the L1 D-cache.
Shared body of the whole-cache set/way operations: select level-0 data (CSSELR=0), read the geometry from CCSIDR, and write each {set,way} pair to op_reg, bracketed by data barriers. op_reg is DCISW for a bare invalidate (cold-cache enable) or DCCISW for clean+invalidate (cache disable, so dirty lines are written back). A degenerate CCSIDR (all-zero or all-ones) means the geometry is unavailable, so nothing is written.
| [in] | op_reg | Set/way maintenance register: k_ra8_cache_dcisw or k_ra8_cache_dccisw. |
op_reg is a set/way maintenance register address. op_reg (unless the geometry was unavailable, in which case none was). Definition at line 219 of file ra8_cache.c.
References internal_ra8_cache_reg(), k_ra8_cache_ccsidr, k_ra8_cache_ccsidr_assoc_mk, k_ra8_cache_ccsidr_assoc_sh, k_ra8_cache_ccsidr_sets_msk, k_ra8_cache_ccsidr_sets_sh, k_ra8_cache_csselr, k_ra8_cache_dcisw_set_shift, k_ra8_cache_dcisw_way_shift, ra8_hw_dsb(), ra8_hw_isb(), and RA8_INTERNAL.
Referenced by ra8_cache_dcache_disable(), and ra8_cache_dcache_invalidate_all().
|
static |
Number of cache lines spanning size bytes from addr.
Rounds addr down to its line boundary and counts the lines up to and including the one holding the last byte. Pure address arithmetic so the by-address operations share one tested span calculation.
| [in] | addr | Range start. |
| [in] | size | Range length in bytes (must be non-zero). |
| [in] | line | Cache line size in bytes (a power of two, >= 4). |
| [out] | out_start | Receives the line-aligned start address. |
| count | Line count covering [addr, addr + size); always >= 1 since a non-zero range touches at least one line. |
size is non-zero and line is a non-zero power of two. out_start is non-NULL. *out_start <= addr and is line-aligned. Definition at line 130 of file ra8_cache.c.
Referenced by internal_ra8_cache_maintain_range().
| ra8_err_t ra8_cache_dcache_clean_by_addr | ( | const void * | addr, |
| uint32_t | size ) |
Clean (write back) the D-cache lines covering a byte range.
Writes every cache line that overlaps [addr, addr + size) back to main memory via DCCMVAC, bracketed by data barriers. Call this on a buffer the CPU has filled, immediately before handing it to a TX DMA or to the secondary core, so the consumer sees the latest bytes.
| [in] | addr | Start of the range. Must not be NULL. |
| [in] | size | Range length in bytes; 0 is a no-op success. |
| k_ra8_ok | Lines cleaned (or size == 0). |
| k_ra8_err_null_ptr | addr was NULL. |
Definition at line 180 of file ra8_cache.c.
References internal_ra8_cache_maintain_range(), and k_ra8_cache_dccmvac.
Referenced by cam_image_clean_outputs(), dtc_coh_run_once(), internal_lcd_clear(), internal_lcd_flush(), internal_run_copy(), ra8_dtc_enable(), ra8_dtc_reconfigure(), and ra8_spi_write_dma().
| ra8_err_t ra8_cache_dcache_clean_invalidate_by_addr | ( | const void * | addr, |
| uint32_t | size ) |
Clean and invalidate the D-cache lines covering a byte range.
Writes back then drops every cache line overlapping [addr, addr + size) via DCCIMVAC, bracketed by data barriers. Use for a buffer that is both produced and re-read across a DMA or a cross-core handoff.
| [in] | addr | Start of the range. Must not be NULL. |
| [in] | size | Range length in bytes; 0 is a no-op success. |
| k_ra8_ok | Lines cleaned and invalidated (or size == 0). |
| k_ra8_err_null_ptr | addr was NULL. |
Definition at line 190 of file ra8_cache.c.
References internal_ra8_cache_maintain_range(), and k_ra8_cache_dccimvac.
Referenced by cache_hal_test_cacheable_rw(), cache_mpu_test_cacheable_rw(), and internal_ceu_capture().
| void ra8_cache_dcache_disable | ( | void | ) |
Disable the Cortex-M85 L1 data cache, cleaning dirty lines (CCR.DC).
Clears SCB.CCR bit DC (preserving the other CCR controls) to stop new allocations, then walks the cache geometry and issues DCCISW to clean AND invalidate every set/way – so any dirty line is written back to memory as the cache goes cold. Unlike ra8_cache_dcache_enable, the disable path must not discard dirty data, hence clean+invalidate rather than a bare invalidate.
Definition at line 299 of file ra8_cache.c.
References internal_ra8_cache_reg(), internal_ra8_cache_setway_all(), k_ra8_cache_ccr, k_ra8_cache_ccr_dc_bit, and k_ra8_cache_dccisw.
| void ra8_cache_dcache_enable | ( | void | ) |
Invalidate then enable the Cortex-M85 L1 data cache (CCR.DC).
Runs ra8_cache_dcache_invalidate_all (the set/way invalidate) first so no random power-on line is treated as valid, then read-modify-writes SCB.CCR to set bit DC, preserving the other CCR controls. This encodes the exact set/way-invalidate + CCR.DC sequence the boot internal_enable_dcache helper hand-rolled.
Definition at line 286 of file ra8_cache.c.
References internal_ra8_cache_reg(), k_ra8_cache_ccr, k_ra8_cache_ccr_dc_bit, ra8_cache_dcache_invalidate_all(), ra8_hw_dsb(), and ra8_hw_isb().
Referenced by ra8_cache_enable(), and SystemInit().
| void ra8_cache_dcache_invalidate_all | ( | void | ) |
Invalidate the entire D-cache by set/way.
Walks the cache geometry from CCSIDR (selected via CSSELR) and invalidates every set and way via DCISW, bracketed by data barriers. This is the bulk invalidate a safe cache-enable sequence runs once at boot before setting CCR.DC, so the cache starts from a known-clean state. It does NOT clean – any dirty lines are discarded, which is correct only when the cache has not yet been enabled.
Definition at line 243 of file ra8_cache.c.
References internal_ra8_cache_setway_all(), and k_ra8_cache_dcisw.
Referenced by internal_enable_dcache(), and ra8_cache_dcache_enable().
| ra8_err_t ra8_cache_dcache_invalidate_by_addr | ( | const void * | addr, |
| uint32_t | size ) |
Invalidate (drop) the D-cache lines covering a byte range.
Discards every cache line overlapping [addr, addr + size) via DCIMVAC, bracketed by data barriers, so the next CPU read fetches from memory. Call this on a buffer after an RX DMA (or the secondary core) has written it, before the CPU reads it.
| [in,out] | addr | Start of the range. Must not be NULL. |
| [in] | size | Range length in bytes; 0 is a no-op success. |
| k_ra8_ok | Lines invalidated (or size == 0). |
| k_ra8_err_null_ptr | addr was NULL. |
Definition at line 185 of file ra8_cache.c.
References internal_ra8_cache_maintain_range(), and k_ra8_cache_dcimvac.
Referenced by dtc_coh_run_once(), internal_ceu_capture(), internal_run_copy(), and internal_spi_dma_rx_complete().
|
nodiscard |
Smallest Cortex-M85 D-cache line size, in bytes.
Reads CTR.DminLine (the log2 of the line size in words) from the Arm v8-M Cache Type Register and returns the line size in bytes (4 << DminLine). On the RA8D2's Cortex-M85 this is 32 bytes.
| 32 | The Cortex-M85 L1 D-cache line size. |
Definition at line 97 of file ra8_cache.c.
References internal_ra8_cache_reg(), k_ra8_cache_ctr, k_ra8_cache_ctr_dmin_mask, k_ra8_cache_ctr_dmin_shift, and k_ra8_cache_word_bytes.
Referenced by internal_ra8_cache_maintain_range(), and internal_round_up_to_cache_line().
| void ra8_cache_enable | ( | void | ) |
Enable both Cortex-M85 L1 caches (I-cache then D-cache).
Convenience bring-up that calls ra8_cache_icache_enable then ra8_cache_dcache_enable, matching the order every system_init.c boot copy uses. Each half runs its own architectural invalidate before setting its CCR enable bit, so this is the single call a cold-boot path needs to turn the L1 caches on through the HAL.
Definition at line 310 of file ra8_cache.c.
References ra8_cache_dcache_enable(), and ra8_cache_icache_enable().
| void ra8_cache_icache_disable | ( | void | ) |
Disable the Cortex-M85 L1 instruction cache and invalidate it (CCR.IC).
Clears SCB.CCR bit IC (preserving the other CCR controls) then runs ICIALLU so no stale line survives a later re-enable. The I-cache holds no dirty state, so a plain invalidate (not clean) is correct here.
Definition at line 272 of file ra8_cache.c.
References internal_ra8_cache_reg(), k_ra8_cache_ccr, k_ra8_cache_ccr_ic_bit, k_ra8_cache_iciallu, ra8_hw_dsb(), and ra8_hw_isb().
| void ra8_cache_icache_enable | ( | void | ) |
Invalidate then enable the Cortex-M85 L1 instruction cache (CCR.IC).
Runs ra8_cache_icache_invalidate_all so no random power-on line is treated as valid, then read-modify-writes SCB.CCR to set bit IC, preserving the other CCR controls. This encodes the exact ICIALLU + CCR.IC sequence the boot internal_enable_icache helpers hand-rolled.
Definition at line 260 of file ra8_cache.c.
References internal_ra8_cache_reg(), k_ra8_cache_ccr, k_ra8_cache_ccr_ic_bit, ra8_cache_icache_invalidate_all(), ra8_hw_dsb(), and ra8_hw_isb().
Referenced by ra8_cache_enable(), and SystemInit().
| void ra8_cache_icache_invalidate_all | ( | void | ) |
Invalidate the entire Cortex-M85 L1 instruction cache (ICIALLU).
Writes the Arm v8-M ICIALLU register to drop every I-cache line to the point of unification, bracketed by data + instruction barriers so the invalidate completes and the pipeline refetches before execution continues. Run once at boot before enabling the I-cache, or after overwriting instruction memory (e.g. a copy-to-run loader) so the core fetches the new code rather than a stale cached copy.
Definition at line 248 of file ra8_cache.c.
References internal_ra8_cache_reg(), k_ra8_cache_iciallu, ra8_hw_dsb(), and ra8_hw_isb().
Referenced by ra8_cache_icache_enable().
|
static |
Module log tag.
Definition at line 41 of file ra8_cache.c.