230 lines
8.4 KiB
C
230 lines
8.4 KiB
C
/*
|
|
* Copyright (c) 2014, Wind River Systems, Inc.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* @brief Software-managed ISR table
|
|
*
|
|
* Data types for a software-managed ISR table, with a parameter per-ISR.
|
|
*/
|
|
|
|
#ifndef ZEPHYR_INCLUDE_SW_ISR_TABLE_H_
|
|
#define ZEPHYR_INCLUDE_SW_ISR_TABLE_H_
|
|
|
|
#if !defined(_ASMLANGUAGE)
|
|
#include <zephyr/device.h>
|
|
#include <zephyr/types.h>
|
|
#include <zephyr/toolchain.h>
|
|
#include <zephyr/sys/util.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* Default vector for the IRQ vector table */
|
|
void _isr_wrapper(void);
|
|
|
|
/* Spurious interrupt handler. Throws an error if called */
|
|
void z_irq_spurious(const void *unused);
|
|
|
|
/*
|
|
* Note the order: arg first, then ISR. This allows a table entry to be
|
|
* loaded arg -> r0, isr -> r3 in _isr_wrapper with one ldmia instruction,
|
|
* on ARM Cortex-M (Thumb2).
|
|
*/
|
|
struct _isr_table_entry {
|
|
const void *arg;
|
|
void (*isr)(const void *);
|
|
};
|
|
|
|
/* The software ISR table itself, an array of these structures indexed by the
|
|
* irq line
|
|
*/
|
|
extern struct _isr_table_entry _sw_isr_table[];
|
|
|
|
struct _irq_parent_entry {
|
|
const struct device *dev;
|
|
unsigned int irq;
|
|
unsigned int offset;
|
|
};
|
|
|
|
/*
|
|
* Data structure created in a special binary .intlist section for each
|
|
* configured interrupt. gen_irq_tables.py pulls this out of the binary and
|
|
* uses it to create the IRQ vector table and the _sw_isr_table.
|
|
*
|
|
* More discussion in include/linker/intlist.ld
|
|
*
|
|
* This is a version used when CONFIG_ISR_TABLES_LOCAL_DECLARATION is disabled.
|
|
* See _isr_list_sname used otherwise.
|
|
*/
|
|
struct _isr_list {
|
|
/** IRQ line number */
|
|
int32_t irq;
|
|
/** Flags for this IRQ, see ISR_FLAG_* definitions */
|
|
int32_t flags;
|
|
/** ISR to call */
|
|
void *func;
|
|
/** Parameter for non-direct IRQs */
|
|
const void *param;
|
|
};
|
|
|
|
/*
|
|
* Data structure created in a special binary .intlist section for each
|
|
* configured interrupt. gen_isr_tables.py pulls this out of the binary and
|
|
* uses it to create linker script chunks that would place interrupt table entries
|
|
* in the right place in the memory.
|
|
*
|
|
* This is a version used when CONFIG_ISR_TABLES_LOCAL_DECLARATION is enabled.
|
|
* See _isr_list used otherwise.
|
|
*/
|
|
struct _isr_list_sname {
|
|
/** IRQ line number */
|
|
int32_t irq;
|
|
/** Flags for this IRQ, see ISR_FLAG_* definitions */
|
|
int32_t flags;
|
|
/** The section name */
|
|
const char sname[];
|
|
};
|
|
|
|
#ifdef CONFIG_SHARED_INTERRUPTS
|
|
struct z_shared_isr_table_entry {
|
|
struct _isr_table_entry clients[CONFIG_SHARED_IRQ_MAX_NUM_CLIENTS];
|
|
size_t client_num;
|
|
};
|
|
|
|
void z_shared_isr(const void *data);
|
|
|
|
extern struct z_shared_isr_table_entry z_shared_sw_isr_table[];
|
|
#endif /* CONFIG_SHARED_INTERRUPTS */
|
|
|
|
/** This interrupt gets put directly in the vector table */
|
|
#define ISR_FLAG_DIRECT BIT(0)
|
|
|
|
#define _MK_ISR_NAME(x, y) __MK_ISR_NAME(x, y)
|
|
#define __MK_ISR_NAME(x, y) __isr_ ## x ## _irq_ ## y
|
|
|
|
|
|
#if IS_ENABLED(CONFIG_ISR_TABLES_LOCAL_DECLARATION)
|
|
|
|
#define _MK_ISR_ELEMENT_NAME(func, id) __MK_ISR_ELEMENT_NAME(func, id)
|
|
#define __MK_ISR_ELEMENT_NAME(func, id) __isr_table_entry_ ## func ## _irq_ ## id
|
|
|
|
#define _MK_IRQ_ELEMENT_NAME(func, id) __MK_ISR_ELEMENT_NAME(func, id)
|
|
#define __MK_IRQ_ELEMENT_NAME(func, id) __irq_table_entry_ ## func ## _irq_ ## id
|
|
|
|
#define _MK_ISR_SECTION_NAME(prefix, file, counter) \
|
|
"." Z_STRINGIFY(prefix)"."file"." Z_STRINGIFY(counter)
|
|
|
|
#define _MK_ISR_ELEMENT_SECTION(counter) _MK_ISR_SECTION_NAME(irq, __FILE__, counter)
|
|
#define _MK_IRQ_ELEMENT_SECTION(counter) _MK_ISR_SECTION_NAME(isr, __FILE__, counter)
|
|
|
|
/* Separated macro to create ISR table entry only.
|
|
* Used by Z_ISR_DECLARE and ISR tables generation script.
|
|
*/
|
|
#define _Z_ISR_TABLE_ENTRY(irq, func, param, sect) \
|
|
static Z_DECL_ALIGN(struct _isr_table_entry) \
|
|
__attribute__((section(sect))) \
|
|
__used _MK_ISR_ELEMENT_NAME(func, __COUNTER__) = { \
|
|
.arg = (const void *)(param), \
|
|
.isr = (void (*)(const void *))(void *)(func) \
|
|
}
|
|
|
|
#define Z_ISR_DECLARE_C(irq, flags, func, param, counter) \
|
|
_Z_ISR_DECLARE_C(irq, flags, func, param, counter)
|
|
|
|
#define _Z_ISR_DECLARE_C(irq, flags, func, param, counter) \
|
|
_Z_ISR_TABLE_ENTRY(irq, func, param, _MK_ISR_ELEMENT_SECTION(counter)); \
|
|
static struct _isr_list_sname Z_GENERIC_SECTION(.intList) \
|
|
__used _MK_ISR_NAME(func, counter) = \
|
|
{irq, flags, _MK_ISR_ELEMENT_SECTION(counter)}
|
|
|
|
/* Create an entry for _isr_table to be then placed by the linker.
|
|
* An instance of struct _isr_list which gets put in the .intList
|
|
* section is created with the name of the section where _isr_table entry is placed to be then
|
|
* used by isr generation script to create linker script chunk.
|
|
*/
|
|
#define Z_ISR_DECLARE(irq, flags, func, param) \
|
|
BUILD_ASSERT(((flags) & ISR_FLAG_DIRECT) == 0, "Use Z_ISR_DECLARE_DIRECT macro"); \
|
|
Z_ISR_DECLARE_C(irq, flags, func, param, __COUNTER__)
|
|
|
|
|
|
/* Separated macro to create ISR Direct table entry only.
|
|
* Used by Z_ISR_DECLARE_DIRECT and ISR tables generation script.
|
|
*/
|
|
#define _Z_ISR_DIRECT_TABLE_ENTRY(irq, func, sect) \
|
|
COND_CODE_1(CONFIG_IRQ_VECTOR_TABLE_JUMP_BY_ADDRESS, ( \
|
|
static Z_DECL_ALIGN(uintptr_t) \
|
|
__attribute__((section(sect))) \
|
|
__used _MK_IRQ_ELEMENT_NAME(func, __COUNTER__) = ((uintptr_t)(func)); \
|
|
), ( \
|
|
static void __attribute__((section(sect))) __attribute__((naked)) \
|
|
__used _MK_IRQ_ELEMENT_NAME(func, __COUNTER__)(void) { \
|
|
__asm(ARCH_IRQ_VECTOR_JUMP_CODE(func)); \
|
|
} \
|
|
))
|
|
|
|
#define Z_ISR_DECLARE_DIRECT_C(irq, flags, func, counter) \
|
|
_Z_ISR_DECLARE_DIRECT_C(irq, flags, func, counter)
|
|
|
|
#define _Z_ISR_DECLARE_DIRECT_C(irq, flags, func, counter) \
|
|
_Z_ISR_DIRECT_TABLE_ENTRY(irq, func, _MK_IRQ_ELEMENT_SECTION(counter)); \
|
|
static struct _isr_list_sname Z_GENERIC_SECTION(.intList) \
|
|
__used _MK_ISR_NAME(func, counter) = { \
|
|
irq, \
|
|
ISR_FLAG_DIRECT | (flags), \
|
|
_MK_IRQ_ELEMENT_SECTION(counter)}
|
|
|
|
/* Create an entry to irq table and place it in specific section which name is then placed
|
|
* in an instance of struct _isr_list to be then used by the isr generation script to create
|
|
* the linker script chunks.
|
|
*/
|
|
#define Z_ISR_DECLARE_DIRECT(irq, flags, func) \
|
|
BUILD_ASSERT(IS_ENABLED(CONFIG_IRQ_VECTOR_TABLE_JUMP_BY_ADDRESS) || \
|
|
IS_ENABLED(CONFIG_IRQ_VECTOR_TABLE_JUMP_BY_CODE), \
|
|
"CONFIG_IRQ_VECTOR_TABLE_JUMP_BY_{ADDRESS,CODE} not set"); \
|
|
Z_ISR_DECLARE_DIRECT_C(irq, flags, func, __COUNTER__)
|
|
|
|
|
|
#else /* IS_ENABLED(CONFIG_ISR_TABLES_LOCAL_DECLARATION) */
|
|
|
|
/* Create an instance of struct _isr_list which gets put in the .intList
|
|
* section. This gets consumed by gen_isr_tables.py which creates the vector
|
|
* and/or SW ISR tables.
|
|
*/
|
|
#define Z_ISR_DECLARE(irq, flags, func, param) \
|
|
static Z_DECL_ALIGN(struct _isr_list) Z_GENERIC_SECTION(.intList) \
|
|
__used _MK_ISR_NAME(func, __COUNTER__) = \
|
|
{irq, flags, (void *)&func, (const void *)param}
|
|
|
|
/* The version of the Z_ISR_DECLARE that should be used for direct ISR declaration.
|
|
* It is here for the API match the version with CONFIG_ISR_TABLES_LOCAL_DECLARATION enabled.
|
|
*/
|
|
#define Z_ISR_DECLARE_DIRECT(irq, flags, func) \
|
|
Z_ISR_DECLARE(irq, ISR_FLAG_DIRECT | (flags), func, NULL)
|
|
|
|
#endif
|
|
|
|
#define IRQ_TABLE_SIZE (CONFIG_NUM_IRQS - CONFIG_GEN_IRQ_START_VECTOR)
|
|
|
|
#ifdef CONFIG_DYNAMIC_INTERRUPTS
|
|
void z_isr_install(unsigned int irq, void (*routine)(const void *),
|
|
const void *param);
|
|
|
|
#ifdef CONFIG_SHARED_INTERRUPTS
|
|
int z_isr_uninstall(unsigned int irq, void (*routine)(const void *),
|
|
const void *param);
|
|
#endif /* CONFIG_SHARED_INTERRUPTS */
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* _ASMLANGUAGE */
|
|
|
|
#endif /* ZEPHYR_INCLUDE_SW_ISR_TABLE_H_ */
|