|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Ref-counted Module Stop Control implementation. More...
#include "ra8_mstp.h"#include <stdint.h>#include "ra8_attributes.h"#include "ra8_bit_constants.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_hw_err.h"#include "ra8_log.h"#include "ra8_mstp_internal.h"#include "ra8_mstp_regs.h"Go to the source code of this file.
Enumerations | |
| enum | ra8_mstp_dim_t : uint8_t { k_ra8_mstp_reg_count = 5U , k_ra8_mstp_bit_count = 32U } |
| Dimensions of the ref-count table. More... | |
| enum | ra8_mstp_spin_t : uint16_t { k_ra8_mstp_readback_spin = 0x100U } |
| Bounded spin budget for the read-back protocol (HUM 11.2.6 N2). More... | |
| enum | ra8_mstp_init_val_t : uint32_t { k_ra8_mstp_all_stopped = 0xFFFFFFFFU , k_ra8_mstp_safe_stopped_a = 0xFFFFFFF0U } |
| Per-register safe all-stopped patterns for MSTPCRA..MSTPCRE. More... | |
| enum | ra8_mstp_psar_t : uintptr_t { k_ra8_mstp_psarb_addr = 0x40204004U , k_ra8_mstp_psarc_addr = 0x40204008U , k_ra8_mstp_psard_addr = 0x4020400CU , k_ra8_mstp_psare_addr = 0x40204010U } |
| R_PSCU Peripheral Security Attribution Register addresses (PSARB..E). More... | |
Functions | |
| ra8_mstp_reg_t | ra8_mstp_id_reg (ra8_mstp_t id) |
| Extract the register index from a packed MSTP id. | |
| uint8_t | ra8_mstp_id_bit (ra8_mstp_t id) |
| Extract the bit number from a packed MSTP id. | |
| static bool | internal_decode (ra8_mstp_t id, uint8_t *out_reg, uint8_t *out_bit) |
| Decode an ra8_mstp_t id and validate its bit position. | |
| static volatile uint32_t * | internal_reg_ptr (uint8_t reg) |
| Pointer to MSTPCRA..MSTPCRE indexed by register number. | |
| static ra8_err_t | internal_wait_readback (uint8_t reg, uint8_t bit, bool expected_stopped) |
| Read-back protocol from HUM 11.2.6 Note 2. | |
| ra8_err_t | priv_ra8_mstp_wait_reg_settle_internal (uint8_t reg, uint32_t expect, uint32_t care_mask) |
| Implementation of priv_ra8_mstp_wait_reg_settle_internal() – masked settle poll. | |
| uint32_t | priv_ra8_mstp_ns_mask_internal (uint8_t reg) |
| Implementation of priv_ra8_mstp_ns_mask_internal() – reads PSARB..E. | |
| ra8_err_t | ra8_mstp_init (void) |
| Re-establish the ra8_mstp ref-count table from current hardware state. | |
| ra8_err_t | ra8_mstp_enable (ra8_mstp_t id) |
| Reference-counted "ungate this peripheral" request. | |
| ra8_err_t | ra8_mstp_disable (ra8_mstp_t id) |
| Reference-counted "gate this peripheral" request. | |
| ra8_err_t | ra8_mstp_get_refcount (ra8_mstp_t id, uint8_t *out_ref) |
| Read the current ref count for an MSTP id. | |
| ra8_err_t | ra8_mstp_is_stopped (ra8_mstp_t id, bool *out_stopped) |
| Read the current MSTP bit value for an id. | |
Variables | |
| static const char * | s_tag = "MSTP" |
| static uint8_t | s_refcount [k_ra8_mstp_reg_count][k_ra8_mstp_bit_count] |
| Per-(register, bit) usage counter. | |
Ref-counted Module Stop Control implementation.
Ring 3 / HAL substrate. Wraps the RA8D2 MSTPCRA..MSTPCRE registers (HUM Ch 11.2.6..10, p 443..450) behind a small ref-counted API so two unrelated drivers can both depend on the same MSTP bit (DMAC + DTC, OSPI + DOTF, SSIE0/SSIE1, ...) without trampling each other's state.
The ref-count table lives entirely in this file – no other compilation unit may write to MSTPCRA..MSTPCRE.
Definition in file ra8_mstp.c.
| enum ra8_mstp_dim_t : uint8_t |
Dimensions of the ref-count table.
| Enumerator | |
|---|---|
| k_ra8_mstp_reg_count | MSTPCRA..MSTPCRE. |
| k_ra8_mstp_bit_count | 32 bits per register. |
Definition at line 46 of file ra8_mstp.c.
| enum ra8_mstp_init_val_t : uint32_t |
Per-register safe all-stopped patterns for MSTPCRA..MSTPCRE.
Most MSTPCRx bits default to 1 ("module stopped") on a power-on reset. Reserved bits are "read as 1, write 1" (HUM Ch 11.2.6..10).
Exception – MSTPCRA bits 0..3 (SRAM0..3): these control the ECC SRAM controllers that back the CPU stack and data. Stopping them (writing 1) while code is running causes a precise BusFault on the next stack access. They must be kept at 0 (running) at all times. HUM Ch 11.2.6 p 443, MSTPA0..MSTPA3.
| Enumerator | |
|---|---|
| k_ra8_mstp_all_stopped | RA8 mstp all stopped. |
| k_ra8_mstp_safe_stopped_a | MSTPCRA: bits 0-3 (SRAM0-3) kept 0. |
Definition at line 79 of file ra8_mstp.c.
| enum ra8_mstp_psar_t : uintptr_t |
R_PSCU Peripheral Security Attribution Register addresses (PSARB..E).
A module-stop bit follows its peripheral's PSAR attribution: once the Secure side marks a peripheral Non-secure (PSARx bit = 1), that MSTPCRx bit is owned by the Non-secure alias and a Secure write to it is masked (the bit does not change). PSAR bit N mirrors MSTPCRx bit N one-for-one, so the PSAR value is directly the Non-secure-owned bit mask for that register. R_PSCU begins with a reserved word (no PSARA), so MSTPCRA has no attribution register and its whole width stays Secure-owned. On a non-TrustZone system every PSAR reads 0 (all Secure), so the mask is empty and the read-back stays fully strict.
R_PSCU begins at 0x40204000; PSARB is at +0x04, with PSARC..PSARE in the consecutive words that follow (HUM Ch 51.8.2..51.8.4, same layout). HUM Ch 51.8.1 "PSARB : Peripheral Security Attribution Register B" p 3284
Definition at line 102 of file ra8_mstp.c.
| enum ra8_mstp_spin_t : uint16_t |
Bounded spin budget for the read-back protocol (HUM 11.2.6 N2).
The MSTP bit is expected to update on the next bus cycle, so the realistic worst case is single digits. The budget below is the 16-bit ceiling we use to keep an unconditionally-bounded loop (NASA Power of 10 Rule 2).
| Enumerator | |
|---|---|
| k_ra8_mstp_readback_spin | RA8 mstp readback spin. |
Definition at line 61 of file ra8_mstp.c.
|
static |
Decode an ra8_mstp_t id and validate its bit position.
| [in] | id | Packed id from the ra8_mstp_t enum. |
| [out] | out_reg | Register index 0..4 on success. |
| [out] | out_bit | Bit position 0..31 on success. |
See implementation.
| k_ra8_ok | Operation succeeded. |
Definition at line 167 of file ra8_mstp.c.
References k_ra8_mstp_bit_count, k_ra8_mstp_reg_count, RA8_INTERNAL, ra8_mstp_id_bit(), and ra8_mstp_id_reg().
Referenced by ra8_mstp_disable(), ra8_mstp_enable(), ra8_mstp_get_refcount(), and ra8_mstp_is_stopped().
|
static |
Pointer to MSTPCRA..MSTPCRE indexed by register number.
The five MSTPCR registers sit at consecutive 4-byte offsets in the r_mstp_regs_t block, so a single base pointer plus [reg] indexing is unambiguous and matches the layout asserted by the static_assert in ra8_mstp_regs.h.
Definition at line 192 of file ra8_mstp.c.
References r_mstp_regs_t::MSTPCRA, RA8_INTERNAL, and ra8_mstp().
Referenced by internal_wait_readback(), priv_ra8_mstp_wait_reg_settle_internal(), ra8_mstp_disable(), ra8_mstp_enable(), ra8_mstp_init(), and ra8_mstp_is_stopped().
|
static |
Read-back protocol from HUM 11.2.6 Note 2.
| [in] | reg | MSTPCR register index 0..4. |
| [in] | bit | Bit position 0..31. |
| [in] | expected_stopped | True if the bit must read back as 1. |
Bounded poll of one MSTPCR bit until it reads back at the commanded gate state (HUM 11.2.6 Note 2), part of the NASA Power-of-10 Rule 2 statically-bounded loop budget.
| k_ra8_ok | Operation succeeded. |
| k_ra8_err_hw_timeout | The bit never settled within the budget. |
Definition at line 226 of file ra8_mstp.c.
References internal_reg_ptr(), k_ra8_err_hw_timeout, k_ra8_mstp_readback_spin, and k_ra8_ok.
Referenced by ra8_mstp_disable(), and ra8_mstp_enable().
|
nodiscard |
Implementation of priv_ra8_mstp_ns_mask_internal() – reads PSARB..E.
Non-secure-owned bit mask for one MSTPCR register (read from PSAR).
Definition at line 268 of file ra8_mstp.c.
References k_ra8_mstp_psarb_addr, k_ra8_mstp_psarc_addr, k_ra8_mstp_psard_addr, k_ra8_mstp_psare_addr, and k_ra8_mstp_reg_count.
Referenced by ra8_mstp_init().
|
nodiscard |
Implementation of priv_ra8_mstp_wait_reg_settle_internal() – masked settle poll.
Poll one MSTPCR register until its cared-for bits read back expect.
Definition at line 248 of file ra8_mstp.c.
References internal_reg_ptr(), k_ra8_err_hw_timeout, k_ra8_mstp_readback_spin, and k_ra8_ok.
Referenced by ra8_mstp_init().
|
nodiscard |
Reference-counted "gate this peripheral" request.
Decrements the ref count for id. If the count transitions 1 -> 0, sets the corresponding MSTP bit so the peripheral stops receiving its clock. If the count was greater than 1, the bit is left cleared (other users are still active).
Honors the same read-back protocol as ra8_mstp_enable().
| [in] | id | Peripheral identifier from ra8_mstp_t. |
| k_ra8_ok | Gated successfully (or still in use by another caller). |
| k_ra8_err_invalid_arg | id decodes to an out-of-range register or bit position. |
| k_ra8_err_invalid_state | Refcount was already 0 – caller disabled a peripheral they had not enabled. |
| k_ra8_err_hw_timeout | Bit did not read back as set within the spin budget. |
Definition at line 382 of file ra8_mstp.c.
References internal_decode(), internal_reg_ptr(), internal_wait_readback(), k_ra8_err_invalid_arg, k_ra8_err_invalid_state, k_ra8_ok, ra8_log_error_val, s_refcount, and s_tag.
Referenced by internal_agt_mstp_release(), ra8_acmphs_channel_deinit(), ra8_acmphs_enter_stop(), ra8_adc_deinit(), ra8_adc_enter_stop(), ra8_cac_deinit(), ra8_cac_enter_stop(), ra8_canfd_enter_stop(), ra8_ceu_deinit(), ra8_ceu_enter_stop(), ra8_cnecc_deinit(), ra8_crc_deinit(), ra8_crc_enter_stop(), ra8_dac_b_deinit(), ra8_dac_b_enter_stop(), ra8_dma_deinit(), ra8_dmac_stop(), ra8_dotf_deinit(), ra8_dotf_enter_stop(), ra8_drw_deinit(), ra8_drw_enter_stop(), ra8_dtc_deinit(), ra8_dtc_enter_stop(), ra8_elc_deinit(), ra8_eth_close(), ra8_eth_coma_deinit(), ra8_eth_coma_enter_stop(), ra8_eth_deinit(), ra8_eth_enter_stop(), ra8_eth_gptp_deinit(), ra8_eth_gptp_enter_stop(), ra8_eth_gwca_deinit(), ra8_eth_gwca_enter_stop(), ra8_eth_mfwd_deinit(), ra8_eth_mfwd_enter_stop(), ra8_glcdc_deinit(), ra8_glcdc_enter_stop(), ra8_gpt_deinit(), ra8_gpt_enter_stop(), ra8_i2c_deinit(), ra8_i3c_deinit(), ra8_i3c_enter_stop(), ra8_i3c_i2c_deinit(), ra8_i3c_i2c_peripheral_close(), ra8_mipi_csi_deinit(), ra8_mipi_csi_enter_stop(), ra8_mipi_dsi_deinit(), ra8_mipi_dsi_enter_stop(), ra8_pdg_deinit(), ra8_pdm_deinit(), ra8_poeg_deinit(), ra8_poeg_enter_stop(), ra8_pwr_module_release(), ra8_rsip_deinit(), ra8_rsip_enter_stop(), ra8_rsip_exit_stop(), ra8_rsip_init(), ra8_sci_deinit(), ra8_sci_enter_stop(), ra8_sci_spi_deinit(), ra8_sdhi_deinit(), ra8_sdhi_enter_stop(), ra8_spi_deinit(), ra8_spi_enter_stop(), ra8_sram_deinit(), ra8_sram_enter_stop(), ra8_ssie_deinit(), ra8_ssie_enter_stop(), ra8_tsn_deinit(), ra8_tsn_enter_stop(), ra8_ulpt_deinit(), ra8_ulpt_enter_stop(), ra8_usb_device_deinit(), ra8_usb_enter_stop(), ra8_usb_host_deinit(), ra8_vin_deinit(), ra8_vin_enter_stop(), ra8_xspi_deinit(), and ra8_xspi_enter_stop().
|
nodiscard |
Reference-counted "ungate this peripheral" request.
Increments the ref count for id. If the count transitions 0 -> 1, clears the corresponding MSTP bit so the peripheral starts receiving its clock. If the count was already non-zero, the bit is left as-is (someone else is already using the module) and the function returns success without touching hardware.
Implements the read-back protocol from HUM 11.2.6 Note 2: after the bit-clear, the register is read repeatedly until the cleared bit is observed or the polling budget runs out.
Algorithm:
| [in] | id | Peripheral identifier from ra8_mstp_t. |
| k_ra8_ok | Ungated successfully (or already on). |
| k_ra8_err_invalid_arg | id decodes to an out-of-range register or bit position. |
| k_ra8_err_hw_timeout | Bit did not read back as cleared within the spin budget. |
Definition at line 343 of file ra8_mstp.c.
References internal_decode(), internal_reg_ptr(), internal_wait_readback(), k_ra8_err_invalid_arg, k_ra8_err_invalid_state, k_ra8_ok, ra8_log_error_val, s_refcount, and s_tag.
Referenced by ehb_run_once(), internal_agt_mstp_acquire(), internal_apply_instance(), internal_i3c_i2c_block_bringup(), internal_open_prep(), internal_reset_channel(), internal_ssie_power_up(), internal_usbhs_clock_and_mstp(), internal_validate_and_ungate(), priv_ra8_board_eth_eswm_bring_up(), ra8_acmphs_channel_init(), ra8_acmphs_exit_stop(), ra8_adc_exit_stop(), ra8_adc_init(), ra8_adc_init_configured(), ra8_cac_exit_stop(), ra8_cac_init(), ra8_canfd_exit_stop(), ra8_canfd_init(), ra8_ceu_exit_stop(), ra8_ceu_init(), ra8_cgc_eswclk_init(), ra8_crc_exit_stop(), ra8_crc_init(), ra8_dac_b_exit_stop(), ra8_dac_b_init(), ra8_dac_b_init_configured(), ra8_dma_init(), ra8_dmac_start(), ra8_doc_init(), ra8_dotf_exit_stop(), ra8_dotf_init(), ra8_drw_exit_stop(), ra8_drw_init(), ra8_dtc_exit_stop(), ra8_dtc_init(), ra8_elc_init(), ra8_eth_coma_exit_stop(), ra8_eth_coma_init(), ra8_eth_exit_stop(), ra8_eth_gptp_exit_stop(), ra8_eth_gptp_init(), ra8_eth_gwca_exit_stop(), ra8_eth_gwca_init(), ra8_eth_init(), ra8_eth_mfwd_exit_stop(), ra8_eth_mfwd_init(), ra8_etha_init(), ra8_glcdc_exit_stop(), ra8_glcdc_init(), ra8_gpt_exit_stop(), ra8_gpt_init(), ra8_gpt_start_free_run(), ra8_i2c_init(), ra8_i3c_exit_stop(), ra8_i3c_i2c_peripheral_open(), ra8_i3c_init(), ra8_mipi_csi_exit_stop(), ra8_mipi_csi_init(), ra8_mipi_dsi_exit_stop(), ra8_mipi_dsi_init(), ra8_pdg_init(), ra8_pdm_init(), ra8_poeg_exit_stop(), ra8_poeg_init(), ra8_pwr_module_request(), ra8_rmac_init(), ra8_rsip_exit_stop(), ra8_rsip_init(), ra8_sci_exit_stop(), ra8_sci_init(), ra8_sci_spi_init(), ra8_sdhi_exit_stop(), ra8_sdhi_init(), ra8_spi_b_target_init(), ra8_spi_exit_stop(), ra8_spi_init(), ra8_sram_exit_stop(), ra8_ssie_exit_stop(), ra8_tsn_exit_stop(), ra8_tsn_init(), ra8_ulpt_exit_stop(), ra8_ulpt_init(), ra8_usb_device_init(), ra8_usb_exit_stop(), ra8_usb_host_init(), ra8_vin_exit_stop(), ra8_vin_init(), ra8_xspi_exit_stop(), and ra8_xspi_init().
|
nodiscard |
Read the current ref count for an MSTP id.
Diagnostic accessor. Used by unit tests to verify that ra8_mstp_enable() / disable() pairs balance correctly. Should not appear on hot paths – production code should not need to branch on the ref count.
| [in] | id | Peripheral identifier from ra8_mstp_t. |
| [out] | out_ref | On success, the current ref count value. |
| k_ra8_ok | Ref count returned in *out_ref. |
| k_ra8_err_null_ptr | out_ref was nullptr. |
| k_ra8_err_invalid_arg | id decodes to an out-of-range register or bit position. |
Definition at line 420 of file ra8_mstp.c.
References internal_decode(), k_ra8_err_invalid_arg, k_ra8_ok, RA8_CHECK_NULL_PTR, s_refcount, and s_tag.
| uint8_t ra8_mstp_id_bit | ( | ra8_mstp_t | id | ) |
Extract the bit number from a packed MSTP id.
| [in] | id | Packed id. |
Defined in libs/ra8_hal/src/ra8_mstp.c.
| k_ra8_ok | Operation succeeded. |
Definition at line 139 of file ra8_mstp.c.
References k_ra8_mask_byte.
Referenced by internal_decode().
| ra8_mstp_reg_t ra8_mstp_id_reg | ( | ra8_mstp_t | id | ) |
Extract the register index from a packed MSTP id.
| [in] | id | Packed id. |
Real (non-inline) function so coverage tooling can attribute line counts to a single defining translation unit. The body is in libs/ra8_hal/src/ra8_mstp.c.
| k_ra8_ok | Operation succeeded. |
Definition at line 134 of file ra8_mstp.c.
References k_ra8_bits_per_byte, and k_ra8_mask_byte.
Referenced by internal_decode().
|
nodiscard |
Re-establish the ra8_mstp ref-count table from current hardware state.
After a cold reset every MSTP bit is 1 (peripheral stopped) and every ref-count is 0. After a warm reset or a NS->S transition, the table may be out of sync with hardware and the caller wants to start clean.
Calling this function:
After ra8_mstp_init() returns, every subsequent ra8_mstp_enable() is the first request for that module.
| k_ra8_ok | Refcount table reset and hardware confirmed all-stopped. |
| k_ra8_err_hw_timeout | Read-back loop did not observe the expected value within budget. |
Definition at line 291 of file ra8_mstp.c.
References internal_reg_ptr(), k_ra8_err_hw_timeout, k_ra8_mstp_all_stopped, k_ra8_mstp_bit_count, k_ra8_mstp_reg_count, k_ra8_mstp_safe_stopped_a, k_ra8_ok, priv_ra8_mstp_ns_mask_internal(), priv_ra8_mstp_wait_reg_settle_internal(), ra8_log_error_val, ra8_log_info, s_refcount, and s_tag.
Referenced by adc_diag_setup_or_halt(), al_setup_or_halt(), app_bringup_clocks(), bm_setup_or_halt(), bs_setup_or_halt(), c6_fwver_setup_or_halt(), c6_hosted_setup_or_halt(), c6_join_setup_or_halt(), c6_probe_clocks_or_halt(), c6_wifi_setup_or_halt(), cam_bringup(), ch_setup_or_halt(), cm_bringup_clocks(), combo_clocks_or_halt(), demo_setup_or_halt(), drw_blend_setup_or_halt(), drw_demo_setup_or_halt(), dtc_arm_setup_or_halt(), dtc_coh_setup_or_halt(), dtc_demo_setup_or_halt(), ec_setup_or_halt(), ef_setup_or_halt(), ehb_setup_or_halt(), eop_setup_or_halt(), ep_bringup_core(), ep_setup_or_halt(), erb_setup_or_halt(), es_setup_or_halt(), est_setup_or_halt(), ez_bringup_clocks(), fc_setup_or_halt(), gh_setup_or_halt(), gpt_ecc_clocks_or_halt(), gptp_setup_or_halt(), i3c_demo_clocks_or_halt(), iic_setup_or_halt(), imu_demo_clocks_or_halt(), internal_bkup_demo_setup_or_halt(), internal_c6_cam_setup_or_halt(), internal_clocks_or_halt(), internal_clocks_or_halt(), internal_dotf_demo_setup_or_halt(), internal_eth_loopback_setup_or_halt(), internal_lcd_bringup_clocks(), internal_lvd_demo_setup_or_halt(), internal_mecc_setup_or_halt(), internal_motor_3phase_init_clocks_and_led(), internal_pdg_demo_setup_or_halt(), internal_poeg_demo_setup_or_halt(), internal_rc_setup_or_halt(), internal_setup_or_halt(), internal_ssie_loop_setup_or_halt(), internal_tc_setup_or_halt(), internal_td_setup_or_halt(), iu_setup_or_halt(), iv_setup_or_halt(), kb_setup_or_halt(), l3_setup_or_halt(), lcd_bringup_clocks(), lk_setup_or_halt(), mem_setup_or_halt(), mg_bringup_clocks(), modem_clocks_or_halt(), pdm_demo_clocks_or_halt(), pp_demo_clocks_or_halt(), ra8_nsc_periph_init(), ra8_pwr_init(), riic_target_clocks_or_halt(), sbns_console_bringup(), scb_demo_setup_or_halt(), sd_setup_or_halt(), sdram_demo_setup_or_halt(), sfr_bringup_clocks(), sh_setup_or_halt(), tb_setup_or_halt(), timer_demo_setup_or_halt(), tsn_setup_or_halt(), wa_setup_or_halt(), wc_setup_or_halt(), wd_setup_or_halt(), webp_demo_setup_or_halt(), wifi_hal_setup_or_halt(), and wk_setup_or_halt().
|
nodiscard |
Read the current MSTP bit value for an id.
Diagnostic accessor. Returns true if the peripheral is currently STOPPED (bit set), false if it is RUNNING (bit clear). Mostly used by tests; production code should track its own state via ra8_mstp_get_refcount() or simply call ra8_mstp_enable() again.
| [in] | id | Peripheral identifier from ra8_mstp_t. |
| [out] | out_stopped | On success, true if the bit is set. |
| k_ra8_ok | Bit value returned in *out_stopped. |
| k_ra8_err_null_ptr | out_stopped was nullptr. |
| k_ra8_err_invalid_arg | id is out of range. |
Definition at line 432 of file ra8_mstp.c.
References internal_decode(), internal_reg_ptr(), k_ra8_err_invalid_arg, k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.
|
static |
Per-(register, bit) usage counter.
5 x 32 = 160 entries, each uint8_t. Indexed by s_refcount[reg][bit] where reg is 0..4 (MSTPCRA..E) and bit is 0..31. A value of 0 means "no driver currently needs this peripheral"; the corresponding MSTPCR bit should be 1.
Definition at line 127 of file ra8_mstp.c.
Referenced by ra8_mstp_disable(), ra8_mstp_enable(), ra8_mstp_get_refcount(), and ra8_mstp_init().
|
static |
Definition at line 40 of file ra8_mstp.c.