|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
NVIC + ICU IELSR allocator implementation. More...
#include "ra8_isr.h"#include <stdint.h>#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_hw_intrinsics.h"#include "ra8_icu_regs.h"#include "ra8_log.h"Go to the source code of this file.
Data Structures | |
| struct | ra8_isr_slot_t |
| Dispatch-table entry for one IELSR slot. More... | |
Enumerations | |
| enum | ra8_isr_nvic_t : uintptr_t { k_ra8_isr_nvic_iser_base = 0xE000E100UL , k_ra8_isr_nvic_icer_base = 0xE000E180UL , k_ra8_isr_nvic_icpr_base = 0xE000E280UL , k_ra8_isr_nvic_ipr_base = 0xE000E400UL } |
| NVIC register-base offsets used by the dispatcher. More... | |
| enum | ra8_isr_nvic_layout_t : uint16_t { k_ra8_isr_nvic_bits_per_word = 32U , k_ra8_isr_nvic_prio_shift = 4U } |
| Bit-per-word geometry of ISER / ICER arrays. More... | |
Functions | |
| static void | internal_nvic_enable (uint16_t n) |
| Enable NVIC line n. | |
| static void | internal_nvic_disable (uint16_t n) |
| Disable NVIC line n. | |
| static void | internal_nvic_clear_pending (uint16_t n) |
| Clear pending flag on NVIC line n. | |
| static void | internal_nvic_set_priority (uint16_t n, uint8_t prio) |
| Set NVIC priority byte for line n. | |
| static void | internal_ielsr_write (uint16_t slot, ra8_elc_event_t event) |
| Write the event number into an IELSR slot. | |
| static void | internal_ielsr_clear (uint16_t slot) |
| Clear an IELSR slot (set event = 0, IR bit clear). | |
| ra8_err_t | ra8_isr_init (void) |
| Initialise the ra8_isr table. | |
| static uint16_t | internal_find_event (ra8_elc_event_t event) |
| Search the dispatch table for a previously-registered event. | |
| static uint16_t | internal_find_free (void) |
| Find the first free dispatch-table slot. | |
| ra8_err_t | ra8_isr_register (ra8_elc_event_t event, ra8_isr_handler_t handler, void *ctx, uint8_t priority, uint16_t *out_slot) |
| Allocate an IELSR slot for an ELC event + handler. | |
| ra8_err_t | ra8_isr_unregister (ra8_elc_event_t event) |
| Release a previously-allocated IELSR slot. | |
| void | ra8_isr_dispatch (uint16_t slot) |
| Invoke the handler stored in dispatch-table slot slot. | |
| ra8_err_t | ra8_isr_set_priority (ra8_elc_event_t event, uint8_t priority) |
| Change the NVIC priority of a registered slot. | |
| ra8_err_t | ra8_isr_lookup_slot (ra8_elc_event_t event, uint16_t *out_slot) |
| Look up the slot allocated to a registered event. | |
| ra8_err_t | ra8_isr_set_dtc (uint16_t slot, bool enable) |
| Enable or disable DTC activation on a registered IELSR slot. | |
| void | ra8_isr_globals_enable (void) |
| Globally enable maskable interrupts (PRIMASK = 0). | |
| void | ra8_isr_globals_disable (void) |
| Globally mask maskable interrupts (PRIMASK = 1). | |
Variables | |
| static const char * | s_tag = "ISR" |
| static ra8_isr_slot_t | s_slots [k_ra8_isr_slot_count] |
| Per-slot dispatch table. | |
NVIC + ICU IELSR allocator implementation.
Ring 3 / HAL substrate. Owns every write to the ICU IELSR slot array and to the Cortex-M85 NVIC ISER / ICER / IPR windows. See ra8_isr.h for the API contract.
Definition in file ra8_isr.c.
| enum ra8_isr_nvic_layout_t : uint16_t |
| enum ra8_isr_nvic_t : uintptr_t |
NVIC register-base offsets used by the dispatcher.
Cortex-M85 architectural layout from the Armv8.1-M reference manual. The same addresses apply on the Cortex-M33 secondary core; that is why this module is a substrate module and not a target-specific peripheral driver.
|
static |
Search the dispatch table for a previously-registered event.
See implementation.
| [in] | event | See implementation. |
| k_ra8_ok | Operation succeeded. |
Definition at line 262 of file ra8_isr.c.
References k_ra8_isr_slot_count, k_ra8_isr_slot_none, RA8_INTERNAL, and s_slots.
Referenced by ra8_isr_lookup_slot(), ra8_isr_register(), ra8_isr_set_priority(), and ra8_isr_unregister().
|
static |
Find the first free dispatch-table slot.
See implementation.
| k_ra8_ok | Operation succeeded. |
Definition at line 286 of file ra8_isr.c.
References k_ra8_isr_slot_count, k_ra8_isr_slot_none, RA8_INTERNAL, and s_slots.
Referenced by ra8_isr_register().
|
static |
Clear an IELSR slot (set event = 0, IR bit clear).
See implementation.
| [in] | slot | See implementation. |
Definition at line 216 of file ra8_isr.c.
References ra8_icu_ielsr(), and RA8_INTERNAL.
Referenced by ra8_isr_init(), and ra8_isr_unregister().
|
static |
Write the event number into an IELSR slot.
The 9-bit event number goes into bits 8..0 per HUM Ch 14.2.x (IELSRn layout). Upper bits (DTC enable, IR status) are written zero so the slot starts clean.
| [in] | slot | See implementation. |
| [in] | event | See implementation. |
Definition at line 195 of file ra8_isr.c.
References k_ra8_ielsr_iels_mask, ra8_icu_ielsr(), and RA8_INTERNAL.
Referenced by ra8_isr_register().
|
static |
Clear pending flag on NVIC line n.
See implementation.
| [in] | n | See implementation. |
Definition at line 150 of file ra8_isr.c.
References k_ra8_isr_nvic_bits_per_word, k_ra8_isr_nvic_icpr_base, and RA8_INTERNAL.
Referenced by ra8_isr_init(), ra8_isr_register(), and ra8_isr_unregister().
|
static |
Disable NVIC line n.
See implementation.
| [in] | n | See implementation. |
Definition at line 129 of file ra8_isr.c.
References k_ra8_isr_nvic_bits_per_word, k_ra8_isr_nvic_icer_base, and RA8_INTERNAL.
Referenced by ra8_isr_init(), and ra8_isr_unregister().
|
static |
Enable NVIC line n.
See implementation.
| [in] | n | See implementation. |
Definition at line 108 of file ra8_isr.c.
References k_ra8_isr_nvic_bits_per_word, k_ra8_isr_nvic_iser_base, and RA8_INTERNAL.
Referenced by ra8_isr_register().
|
static |
Set NVIC priority byte for line n.
See implementation.
| [in] | n | See implementation. |
| [in] | prio | See implementation. |
Definition at line 172 of file ra8_isr.c.
References k_ra8_isr_nvic_ipr_base, k_ra8_isr_nvic_prio_shift, and RA8_INTERNAL.
Referenced by ra8_isr_register(), and ra8_isr_set_priority().
| void ra8_isr_dispatch | ( | uint16_t | slot | ) |
Invoke the handler stored in dispatch-table slot slot.
Called from the Cortex-M85 vector-table trampoline when any ICU NVIC line fires. The trampoline feeds its NVIC index (which matches the IELSR slot number). ra8_isr_dispatch looks up the handler + context stored at registration time and calls the handler with the stored context. The IELSR.IR flag is cleared before the handler runs so a nested identical event re-raises the interrupt instead of being latched.
| [in] | slot | Slot number 0..k_ra8_isr_slot_count - 1. |
Definition at line 362 of file ra8_isr.c.
References k_ra8_ielsr_ir_bit, k_ra8_isr_slot_count, ra8_icu_ielsr(), and s_slots.
| void ra8_isr_globals_disable | ( | void | ) |
Globally mask maskable interrupts (PRIMASK = 1).
Companion to ra8_isr_globals_enable. Used by the application around critical sections where an ISR firing mid-update would corrupt shared state (the per-driver ra8_register_guard.h helpers wrap this for short scopes; this function exists for application-level sequencing during shutdown / reset).
Definition at line 445 of file ra8_isr.c.
References ra8_hw_irq_disable().
| void ra8_isr_globals_enable | ( | void | ) |
Globally enable maskable interrupts (PRIMASK = 0).
The Cortex-M85 boots with PRIMASK clear, but SystemInit masks IRQs with cpsid i to give the application a quiet boot window for driver setup. Once every IRQ source has been registered via ra8_isr_register and the application is ready to start servicing interrupts, call this to drop the global mask. Standard CMSIS convention is "mask at boot, unmask once main() has finished deterministic init".
Definition at line 439 of file ra8_isr.c.
References ra8_hw_irq_enable().
Referenced by app_bringup_clocks(), arm_ipc_wake(), c6_cam_app_run(), cm_bringup_clocks(), ez_bringup_clocks(), internal_lcd_bringup_clocks(), internal_npu_infer_execute(), internal_rtc_demo_setup_or_halt(), lcd_bringup_clocks(), main(), mg_bringup_clocks(), and sfr_bringup_clocks().
|
nodiscard |
Initialise the ra8_isr table.
Zeros every IELSR slot, clears every dispatch-table entry, and disables every NVIC line 0..k_ra8_isr_slot_count. After this call every ra8_isr_register starts from a clean table.
| k_ra8_ok | Table cleared. |
Definition at line 229 of file ra8_isr.c.
References internal_ielsr_clear(), internal_nvic_clear_pending(), internal_nvic_disable(), k_ra8_isr_slot_count, k_ra8_ok, ra8_log_info, s_slots, and s_tag.
Referenced by arm_ipc_wake(), dtc_arm_setup_or_halt(), dtc_coh_setup_or_halt(), dtc_demo_setup_or_halt(), internal_c6_cam_setup_or_halt(), internal_gpt_irq_demo_arm(), internal_init_bind_owner(), internal_lus_arm_wake(), internal_npu_infer_setup_or_halt(), lpi_arm_wake(), ra8_nsc_periph_init(), and uart_irq_setup_or_halt().
|
nodiscard |
Look up the slot allocated to a registered event.
Diagnostic accessor used by unit tests to verify the allocator state. Returns k_ra8_isr_slot_none via *out_slot if the event is not registered.
| [in] | event | ELC event number. |
| [out] | out_slot | Slot number on success, or k_ra8_isr_slot_none if unregistered. |
Definition at line 408 of file ra8_isr.c.
References internal_find_event(), k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.
Referenced by internal_usbfs_storm_guard_init().
|
nodiscard |
Allocate an IELSR slot for an ELC event + handler.
Walks the free list, picks the first open slot, writes the event number into the corresponding IELSR register, stores (handler, ctx) in the dispatch table, clears the pending bit in the NVIC, sets the priority, and enables the NVIC line.
On success, *out_slot holds the assigned slot number. The caller normally ignores this value and only cares that the interrupt will fire; the slot number is useful for unregistration and for diagnostic dumps.
| [in] | event | ELC event number from ra8_elc_event_t. |
| [in] | handler | Callback invoked on interrupt entry. Must not be NULL. |
| [in] | ctx | Caller-supplied context handed to the handler on every invocation. May be NULL. |
| [in] | priority | NVIC priority 0..k_ra8_isr_prio_max. |
| [out] | out_slot | Slot number on success. May be NULL if the caller does not need it. |
| k_ra8_ok | Slot allocated, IELSR written, NVIC line enabled. |
| k_ra8_err_null_ptr | handler was NULL. |
| k_ra8_err_invalid_arg | priority out of range. |
| k_ra8_err_no_mem | No free IELSR slot. |
| k_ra8_err_exists | event is already mapped by a previous registration. |
Definition at line 296 of file ra8_isr.c.
References internal_find_event(), internal_find_free(), internal_ielsr_write(), internal_nvic_clear_pending(), internal_nvic_enable(), internal_nvic_set_priority(), k_ra8_err_exists, k_ra8_err_invalid_arg, k_ra8_err_no_mem, k_ra8_isr_prio_max, k_ra8_isr_slot_none, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_log_error, s_slots, and s_tag.
Referenced by arm_ipc_wake(), dtc_arm_bringup_or_halt(), dtc_coh_bringup_or_halt(), dtc_demo_bringup_or_halt(), internal_gpt_irq_demo_arm(), internal_init_bind_owner(), internal_lus_arm_wake(), internal_npu_infer_execute(), lpi_arm_wake(), ra8_board_sw_attach_irq(), ra8_cnecc_attach_isr(), ra8_gpio_attach_irq(), ra8_ipc_install_isr(), ra8_pdm_stream_enable(), and uart_irq_register_isrs().
|
nodiscard |
Enable or disable DTC activation on a registered IELSR slot.
The Data Transfer Controller has no software-start register (HUM Ch 18.3 p 796: "The DTC is activated by an interrupt request"); a peripheral or ELC event activates it only when that event's ICU.IELSRn slot has its DTCE bit (bit 24) set. With DTCE clear the same event is taken by the CPU as an ordinary interrupt instead. Because ra8_isr owns every IELSR slot (ra8_isr_register writes the IELS event field, the dispatcher clears IR), arming or disarming DTC on an allocated slot belongs here rather than open-coded in every DTC application.
The write is a read-modify-write that touches only DTCE: the IELS event-select field written by ra8_isr_register is preserved, and the write-0-to-clear IR status flag is left untouched – its own read value is written back, which retains it (see ra8_isr_dispatch and issue #170). The DTC clears DTCE itself when a block completes (HUM Figure 18.5 p 801), so a repeating transfer re-arms with enable = true before each activation.
| [in] | slot | IELSR slot 0..k_ra8_isr_slot_count - 1, as returned by ra8_isr_register through its out_slot parameter. |
| [in] | enable | true sets DTCE (route the event to the DTC); false clears it (route the event to the CPU). |
| k_ra8_ok | IELSRn.DTCE for the slot now equals enable. |
| k_ra8_err_invalid_arg | slot is out of range. |
| k_ra8_err_not_found | slot is not currently registered. |
| k_ra8_err_hw_error | The IELSR accessor returned NULL. |
enable. Definition at line 415 of file ra8_isr.c.
References k_ra8_err_hw_error, k_ra8_err_invalid_arg, k_ra8_err_not_found, k_ra8_ielsr_dtce_mask, k_ra8_isr_slot_count, k_ra8_ok, ra8_icu_ielsr(), and s_slots.
Referenced by dtc_arm_run_armed(), and dtc_arm_run_disarmed().
|
nodiscard |
Change the NVIC priority of a registered slot.
| [in] | event | ELC event number that was previously registered. |
| [in] | priority | New priority 0..k_ra8_isr_prio_max. |
| k_ra8_ok | Priority updated. |
| k_ra8_err_not_found | event not registered. |
| k_ra8_err_invalid_arg | priority out of range. |
Definition at line 394 of file ra8_isr.c.
References internal_find_event(), internal_nvic_set_priority(), k_ra8_err_invalid_arg, k_ra8_err_not_found, k_ra8_isr_prio_max, k_ra8_isr_slot_none, k_ra8_ok, and s_slots.
|
nodiscard |
Release a previously-allocated IELSR slot.
| [in] | event | ELC event number to tear down. |
| k_ra8_ok | Slot released. |
| k_ra8_err_not_found | event was not registered. |
Definition at line 335 of file ra8_isr.c.
References internal_find_event(), internal_ielsr_clear(), internal_nvic_clear_pending(), internal_nvic_disable(), k_ra8_err_not_found, k_ra8_isr_slot_count, k_ra8_isr_slot_none, k_ra8_ok, and s_slots.
Referenced by ra8_cnecc_attach_isr(), ra8_cnecc_detach_isr(), ra8_gpio_detach_irq(), ra8_ipc_uninstall_isr(), and ra8_pdm_stream_disable().
|
static |
Per-slot dispatch table.
Indexed by slot number 0..k_ra8_isr_slot_count - 1. Updated by ra8_isr_register / unregister and read by ra8_isr_dispatch. Static so it is zero-initialized at boot.
Definition at line 77 of file ra8_isr.c.
Referenced by app_launch_register(), app_shell_register(), internal_find_event(), internal_find_free(), ra8_isr_dispatch(), ra8_isr_init(), ra8_isr_register(), ra8_isr_set_dtc(), ra8_isr_set_priority(), ra8_isr_unregister(), ra8_rmac_attach_handler(), ra8_rmac_deinit(), ra8_rmac_dispatch(), ra8_rmac_exit_stop(), ra8_rmac_init(), ra8_rmac_set_rx_filter(), and wd_register_apps().