zephyr/tests/kernel/interrupt/src/interrupt_util.h
Henrik Brix Andersen a115e44246 tests: kernel: interrupt: check that irq is not constantly pending
Extend check to determine a usable ARM NVIC IRQ line to verify that the
IRQ line is not always pending.

Signed-off-by: Henrik Brix Andersen <henrik@brixandersen.dk>
2020-08-14 13:35:39 -05:00

108 lines
2.5 KiB
C

/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef INTERRUPT_UTIL_H_
#define INTERRUPT_UTIL_H_
#include <ztest.h>
#define MS_TO_US(ms) (ms * USEC_PER_MSEC)
#if defined(CONFIG_CPU_CORTEX_M)
#include <arch/arm/aarch32/cortex_m/cmsis.h>
static inline uint32_t get_available_nvic_line(uint32_t initial_offset)
{
int i;
for (i = initial_offset - 1; i >= 0; i--) {
if (NVIC_GetEnableIRQ(i) == 0) {
/*
* Interrupts configured statically with IRQ_CONNECT(.)
* are automatically enabled. NVIC_GetEnableIRQ()
* returning false, here, implies that the IRQ line is
* either not implemented or it is not enabled, thus,
* currently not in use by Zephyr.
*/
/* Set the NVIC line to pending. */
NVIC_SetPendingIRQ(i);
if (NVIC_GetPendingIRQ(i)) {
/*
* If the NVIC line is pending, it is
* guaranteed that it is implemented; clear the
* line.
*/
NVIC_ClearPendingIRQ(i);
if (!NVIC_GetPendingIRQ(i)) {
/*
* If the NVIC line can be successfully
* un-pended, it is guaranteed that it
* can be used for software interrupt
* triggering. Return the NVIC line
* number.
*/
break;
}
}
}
}
zassert_true(i >= 0, "No available IRQ line\n");
return i;
}
static inline void trigger_irq(int irq)
{
printk("Triggering irq : %d\n", irq);
#if defined(CONFIG_SOC_TI_LM3S6965_QEMU) || defined(CONFIG_CPU_CORTEX_M0) \
|| defined(CONFIG_CPU_CORTEX_M0PLUS) || defined(CONFIG_CPU_CORTEX_M1)
NVIC_SetPendingIRQ(irq);
#else
NVIC->STIR = irq;
#endif
}
#elif defined(CONFIG_GIC)
#include <drivers/interrupt_controller/gic.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
static inline void trigger_irq(int irq)
{
printk("Triggering irq : %d\n", irq);
/* Ensure that the specified IRQ number is a valid SGI interrupt ID */
zassert_true(irq <= 15, "%u is not a valid SGI interrupt ID", irq);
/*
* Generate a software generated interrupt and forward it to the
* requesting CPU.
*/
#if CONFIG_GIC_VER <= 2
sys_write32(GICD_SGIR_TGTFILT_REQONLY | GICD_SGIR_SGIINTID(irq),
GICD_SGIR);
#else
gic_raise_sgi(irq, GET_MPIDR(), BIT(MPIDR_TO_CORE(GET_MPIDR())));
#endif
}
#elif defined(CONFIG_CPU_ARCV2)
static inline void trigger_irq(int irq)
{
printk("Triggering irq : %d\n", irq);
z_arc_v2_aux_reg_write(_ARC_V2_AUX_IRQ_HINT, irq);
}
#else
/* for not supported architecture */
#define NO_TRIGGER_FROM_SW
#endif
#endif /* INTERRUPT_UTIL_H_ */