Add dedicated interrupt lines for nrf54h20_cpuppr. Similar exception
was already added to nrf54l15_flpr: 8742e2476.
Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
174 lines
4.4 KiB
C
174 lines
4.4 KiB
C
/*
|
|
* Copyright (c) 2020 Stephanos Ioannidis <root@stephanos.io>
|
|
* Copyright (c) 2018 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/ztest.h>
|
|
#include <zephyr/interrupt_util.h>
|
|
|
|
/*
|
|
* Run the nested interrupt test for the supported platforms only.
|
|
*/
|
|
#if defined(CONFIG_CPU_CORTEX_M) || defined(CONFIG_ARC) || \
|
|
defined(CONFIG_GIC) || defined(CONFIG_NRFX_CLIC)
|
|
#define TEST_NESTED_ISR
|
|
#endif
|
|
|
|
#define DURATION 5
|
|
|
|
#define ISR0_TOKEN 0xDEADBEEF
|
|
#define ISR1_TOKEN 0xCAFEBABE
|
|
|
|
/*
|
|
* This test uses two IRQ lines selected within the range of available IRQs on
|
|
* the target SoC. These IRQs are platform and interrupt controller-specific,
|
|
* and must be specified for every supported platform.
|
|
*
|
|
* In terms of priority, the IRQ1 is triggered from the ISR of the IRQ0;
|
|
* therefore, the priority of IRQ1 must be greater than that of the IRQ0.
|
|
*/
|
|
#if defined(CONFIG_CPU_CORTEX_M)
|
|
/*
|
|
* For Cortex-M NVIC, unused and available IRQs are automatically detected when
|
|
* the test is run.
|
|
*
|
|
* The IRQ priorities start at 1 because the priority 0 is reserved for the
|
|
* SVCall exception and Zero-Latency IRQs (see `_EXCEPTION_RESERVED_PRIO`).
|
|
*/
|
|
#define IRQ0_PRIO 2
|
|
#define IRQ1_PRIO 1
|
|
#elif defined(CONFIG_GIC)
|
|
/*
|
|
* For the platforms that use the ARM GIC, use the SGI (software generated
|
|
* interrupt) lines 14 and 15 for testing.
|
|
*/
|
|
#define IRQ0_LINE 14
|
|
#define IRQ1_LINE 15
|
|
|
|
/*
|
|
* Choose lower prio for IRQ0 and higher priority for IRQ1
|
|
* Minimum legal value of GICC BPR is '3' ie <gggg.ssss>
|
|
* Hence choosing default priority and highest possible priority
|
|
* '0x0' as the priorities so that the preemption rule applies
|
|
* generically to all GIC versions and security states.
|
|
*/
|
|
#define IRQ0_PRIO IRQ_DEFAULT_PRIORITY
|
|
#define IRQ1_PRIO 0x0
|
|
#elif defined(CONFIG_SOC_NRF54L15_ENGA_CPUFLPR) || defined(CONFIG_SOC_NRF54L15_CPUFLPR)
|
|
#define IRQ0_LINE 16
|
|
#define IRQ1_LINE 17
|
|
|
|
#define IRQ0_PRIO 1
|
|
#define IRQ1_PRIO 2
|
|
#elif defined(CONFIG_SOC_NRF54H20_CPUPPR)
|
|
#define IRQ0_LINE 14
|
|
#define IRQ1_LINE 15
|
|
|
|
#define IRQ0_PRIO 1
|
|
#define IRQ1_PRIO 2
|
|
#else
|
|
/*
|
|
* For all the other platforms, use the last two available IRQ lines for
|
|
* testing.
|
|
*/
|
|
#define IRQ0_LINE (CONFIG_NUM_IRQS - 1)
|
|
#define IRQ1_LINE (CONFIG_NUM_IRQS - 2)
|
|
|
|
#define IRQ0_PRIO 1
|
|
#define IRQ1_PRIO 0
|
|
#endif
|
|
|
|
#ifdef TEST_NESTED_ISR
|
|
static uint32_t irq_line_0;
|
|
static uint32_t irq_line_1;
|
|
|
|
static uint32_t isr0_result;
|
|
static uint32_t isr1_result;
|
|
|
|
void isr1(const void *param)
|
|
{
|
|
ARG_UNUSED(param);
|
|
|
|
printk("isr1: Enter\n");
|
|
|
|
/* Set verification token */
|
|
isr1_result = ISR1_TOKEN;
|
|
|
|
printk("isr1: Leave\n");
|
|
}
|
|
|
|
void isr0(const void *param)
|
|
{
|
|
ARG_UNUSED(param);
|
|
|
|
printk("isr0: Enter\n");
|
|
|
|
/* Set verification token */
|
|
isr0_result = ISR0_TOKEN;
|
|
|
|
/* Trigger nested IRQ 1 */
|
|
trigger_irq(irq_line_1);
|
|
|
|
/* Wait for interrupt */
|
|
k_busy_wait(MS_TO_US(DURATION));
|
|
|
|
/* Validate nested ISR result token */
|
|
zassert_equal(isr1_result, ISR1_TOKEN, "isr1 did not execute");
|
|
|
|
printk("isr0: Leave\n");
|
|
}
|
|
|
|
/**
|
|
* @brief Test interrupt nesting
|
|
*
|
|
* @ingroup kernel_interrupt_tests
|
|
*
|
|
* This routine tests the interrupt nesting feature, which allows an ISR to be
|
|
* preempted in mid-execution if a higher priority interrupt is signaled. The
|
|
* lower priority ISR resumes execution once the higher priority ISR has
|
|
* completed its processing.
|
|
*
|
|
* The expected control flow for this test is as follows:
|
|
*
|
|
* 1. [thread] Trigger IRQ 0 (lower priority)
|
|
* 2. [isr0] Set ISR 0 result token and trigger IRQ 1 (higher priority)
|
|
* 3. [isr1] Set ISR 1 result token and return
|
|
* 4. [isr0] Validate ISR 1 result token and return
|
|
* 5. [thread] Validate ISR 0 result token
|
|
*/
|
|
ZTEST(interrupt_feature, test_nested_isr)
|
|
{
|
|
/* Resolve test IRQ line numbers */
|
|
#if defined(CONFIG_CPU_CORTEX_M)
|
|
irq_line_0 = get_available_nvic_line(CONFIG_NUM_IRQS);
|
|
irq_line_1 = get_available_nvic_line(irq_line_0);
|
|
#else
|
|
irq_line_0 = IRQ0_LINE;
|
|
irq_line_1 = IRQ1_LINE;
|
|
#endif
|
|
|
|
/* Connect and enable test IRQs */
|
|
arch_irq_connect_dynamic(irq_line_0, IRQ0_PRIO, isr0, NULL, 0);
|
|
arch_irq_connect_dynamic(irq_line_1, IRQ1_PRIO, isr1, NULL, 0);
|
|
|
|
irq_enable(irq_line_0);
|
|
irq_enable(irq_line_1);
|
|
|
|
/* Trigger test IRQ 0 */
|
|
trigger_irq(irq_line_0);
|
|
|
|
/* Wait for interrupt */
|
|
k_busy_wait(MS_TO_US(DURATION));
|
|
|
|
/* Validate ISR result token */
|
|
zassert_equal(isr0_result, ISR0_TOKEN, "isr0 did not execute");
|
|
}
|
|
#else
|
|
ZTEST(interrupt_feature, test_nested_isr)
|
|
{
|
|
ztest_test_skip();
|
|
}
|
|
#endif /* TEST_NESTED_ISR */
|