修改上传所有文件

This commit is contained in:
2025-10-21 19:40:27 +08:00
parent 5a84d13ae4
commit 391f81f8fc
8417 changed files with 2995282 additions and 0 deletions

View File

@@ -0,0 +1,210 @@
/*
* interrupt.c
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: interrupt driver.
*
* Revision History:
* -----------------
*/
#if CONFIG_IRQ
#include <types.h>
#include "armv7-r/cache.h"
#include "armv7-r/irq.h"
#include "core_id.h"
#include "irq.h"
#include "irq_num.h"
#include "sdrv_vic.h"
/* irq info type */
struct irq_info_s {
irq_handler handler; /* Address of the interrupt handler */
void *arg; /* The argument provided to the interrupt handler. */
};
struct irq_table {
struct irq_info_s irq_info[IRQ_MAX_INTR_NUM];
} __CACHE_ALIGN;
/* int table */
static struct irq_table g_irq_table[CORE_NUM_SMP];
static int irq_handle(uint32_t irq)
{
if (irq < IRQ_MAX_INTR_NUM) {
int core_id = get_core_id_smp();
struct irq_info_s *irq_info = &g_irq_table[core_id].irq_info[irq];
if (irq_info->handler) {
return irq_info->handler(irq, irq_info->arg);
}
}
return -1;
}
/**
* @brief Initialize interruppt controller.
*
* @param [in] base base address.
* @param [in] intr_num number of interrupts.
*/
void irq_initialize(uint32_t base, uint32_t intr_num)
{
irq_lld_initialize(base, intr_num, irq_handle);
arch_irq_enable();
}
/**
* @brief Interrupt attach.
*
* @param [in] irq IRQ number.
* @param [in] handler Pointer to function.
* @arg [in] arg parameter of handler.
* @return int Return zero after attach set;
*/
int irq_attach(uint32_t irq, irq_handler handler, void *arg)
{
int ret = -1;
if (irq < IRQ_MAX_INTR_NUM) {
int core_id = get_core_id_smp();
struct irq_info_s *irq_info = &g_irq_table[core_id].irq_info[irq];
IRQ_SAVE
irq_info->handler = handler;
irq_info->arg = arg;
irq_lld_set_priority(irq, DEFAULT_IRQ_PRIORITY);
IRQ_RESTORE
ret = 0;
}
return ret;
}
/**
* @brief Interrupt datach.
*
* @param [in] irq IRQ number.
* @return int Return zero after datach set succesfully;
*/
int irq_detach(uint32_t irq)
{
int ret = -1;
if (irq < IRQ_MAX_INTR_NUM) {
int core_id = get_core_id_smp();
struct irq_info_s *irq_info = &g_irq_table[core_id].irq_info[irq];
IRQ_SAVE
irq_lld_disable(irq);
irq_info->handler = NULL;
irq_info->arg = NULL;
IRQ_RESTORE
ret = 0;
}
return ret;
}
/**
* @brief Interrupt disptach.
*
*/
int irq_dispatch(void)
{
int ret = -1;
uint32_t irq = irq_lld_acknowledge();
ret = irq_handle(irq);
irq_lld_complete(irq);
return ret;
}
/**
* @brief irq enable.
*
* @param [in] irq irq number.
*/
void irq_enable(uint32_t irq)
{
irq_lld_enable(irq);
}
/**
* @brief irq disable.
*
* @param [in] irq number.
*/
void irq_disable(uint32_t irq)
{
irq_lld_disable(irq);
}
/**
* @brief interrupt set priority mask.
*
* @param [in]mask int priority mask.
* @return mask old int priority mask.
*/
uint32_t irq_mask(uint32_t mask)
{
return irq_lld_mask(mask);
}
/**
* @brief interrupt unmask all int.
*/
void irq_unmask(void)
{
irq_lld_unmask();
}
/**
* @brief set irq priority.
*
* @param [in] irq irq number.
* @param [in] priority irq priority.
*/
void irq_set_priority(uint32_t irq, uint32_t priority)
{
irq_lld_set_priority(irq, priority);
}
/**
* @brief get irq priority.
*
* @param [in] irq irq number.
* @return int irq priority.
*/
int irq_get_priority(uint32_t irq)
{
return irq_lld_get_priority(irq);
}
/**
* @brief interrupt get current int priority.
*
* @return int priority.
*/
uint32_t irq_get_current_priority(void)
{
return irq_lld_get_current_priority();
}
#endif /* CONFIG_IRQ */

View File

@@ -0,0 +1,730 @@
/*
* sd_vic.c
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: SemiDrive VIC driver.
*
* Revision History:
* -----------------
*/
#include <string.h>
#include "compiler.h"
#include "param.h"
#include "reg.h"
#include "armv7-r/cache.h"
#include "armv7-r/irq.h"
#include "bits.h"
#include "core_id.h"
#include "common.h"
#include "part.h"
#include "sdrv_vic.h"
#define OFFSET32(v) (((v) >> 5) << 2)
#define SHIFT32(v) ((v) & 31U)
#define VICINTENABLE(v) (g_vic_data[core_id].base + 0x100U + OFFSET32(v))
#define VICINTENCLEAR(v) (g_vic_data[core_id].base + 0x1C0U + OFFSET32(v))
#define VICSWMASK(v) (g_vic_data[core_id].base + 0x180U + OFFSET32(v))
#define VICVECTPRIORITY(v) (g_vic_data[core_id].base + 0x400U + ((v) << 2))
#define VIC_WDT_EN (g_vic_data[core_id].base + 0x380U)
#define VIC_WDT_TH (g_vic_data[core_id].base + 0x3C0U)
#define VIC_ERRINT_CLR (g_vic_data[core_id].base + 0x3CCU)
#define VIC_SFINT_MASK (g_vic_data[core_id].base + 0x1F00U)
#define VICVECADDR(v) (g_vic_data[core_id].base + 0xF000U + ((v) << 2))
#define VICADDRESS (g_vic_data[core_id].base + 0xF00U)
#define VICINTSELECT(v) (g_vic_data[core_id].base + 0xC0U + OFFSET32(v))
#define VICSOFTINT(v) (g_vic_data[core_id].base + 0x140U + OFFSET32(v))
#define VICSOFTINTCLEAR(v) (g_vic_data[core_id].base + 0x200U + OFFSET32(v))
#define VICFIQSTATUS(v) (g_vic_data[core_id].base + 0x40U + OFFSET32(v))
#define VICSWPRIORITYMASK (g_vic_data[core_id].base + 0x3C8U)
#define VICSWMASK_REG(n) (g_vic_data[core_id].base + 0x180U + ((n) << 2))
#define MAX_PRI 15
#define SWMASK_REG_NUM 8
/* Timeout configuration */
#define WDT_EN 0U
#define WDT_DIV 1U
#define WDT_TH 0x80U
#define MAKE_WDT_TH(en, div, th) (((en) << 31) | (((div) & 0x3FFU) << 16) | \
((th) & 0xFFU))
struct vic_data {
uint32_t base;
uint32_t int_num;
uint32_t cur_rp;
uint32_t irq_nest_cnt;
/* Current masked priority set by user or interrrupt framework. */
uint32_t pri_masked;
#if !CONFIG_VIC_IRQ_INTERRUPT_MODE
#ifndef CONFIG_VIC_INT_NEST_MAX_CNT
#define CONFIG_VIC_INT_NEST_MAX_CNT 16
#endif
struct stack {
uint32_t buf[CONFIG_VIC_INT_NEST_MAX_CNT];
uint32_t head;
} old_pri;
#endif
/* The following members are only needed on E3 v1.0. */
struct sw_mask {
/* Bitmap that record registered interrupt of each priority
* and each sw mask register value.
*/
struct pri_mask {
/* Is each priority masked?
* Each priority is arranged linealy to get higher access performance.
*/
bool masked[MAX_PRI + 1] __CACHE_ALIGN;
/* Registered interrupt of each priority. */
unsigned long int_mask[MAX_PRI + 1][SWMASK_REG_NUM] __CACHE_ALIGN;
/* Registerd interrupt which has a equal or lower priority than
* each given priority specified by array index.
*/
unsigned long low_pri_mask[MAX_PRI + 1][SWMASK_REG_NUM] __CACHE_ALIGN;
} pmsk;
uint32_t cur_sw_mask[SWMASK_REG_NUM] __CACHE_ALIGN;
} swmsk;
/* Current masked priority set by user. */
uint32_t cur_swmask;
/* Previous masked priority by user. */
uint32_t previous_masked_pri;
} __CACHE_ALIGN;
static struct vic_data g_vic_data[CORE_NUM_SMP];
static uint8_t get_minor_chip_id(void)
{
#if CONFIG_E3L
return 1;
#else
static uint8_t minor_id = 0xFF;
if (minor_id == 0xFF)
minor_id = sdrv_fuse_get_minor_chipid();
return minor_id;
#endif
}
int int_nest_errata_enabled(void)
{
uint8_t minor_id = get_minor_chip_id();
/* Maybe other version number needed, if so add it here. */
if ((minor_id == 0) || (minor_id == 1)) {
#if CONFIG_VIC_INT_NEST_ERRATA
if (minor_id == 0)
return INT_NEST_ERRATA_TYPE_0;
else {
#if CONFIG_VIC_IRQ_INTERRUPT_MODE
return INT_NEST_ERRATA_TYPE_1;
#else
return INT_NEST_ERRATA_TYPE_2;
#endif
}
#else
return NO_INT_NEST_ERRATA;
#endif
}
else
return NO_INT_NEST_ERRATA;
}
static inline void sdrv_vic_lld_int_disable_all(void)
{
int core_id = get_core_id_smp();
uint32_t int_num = g_vic_data[core_id].int_num;
for (uint32_t i = 0U; i < int_num; i += 32U) {
writel(0xFFFFFFFFU, VICINTENCLEAR(i));
}
}
static void sdrv_vic_lld_func_safety_en(void)
{
int core_id = get_core_id_smp();
/* Enable timeout dection. */
writel(MAKE_WDT_TH(WDT_EN, WDT_DIV, WDT_TH), VIC_WDT_TH);
writel(WDT_EN, VIC_WDT_EN);
/* Unmask error interrupts. */
writel(0U, VIC_SFINT_MASK);
}
static void sdrv_vic_lld_all_ints_trigger_irq(void)
{
int core_id = get_core_id_smp();
uint32_t int_num = g_vic_data[core_id].int_num;
for (uint32_t i = 0U; i < int_num; i += 32U) {
writel(0U, VICINTSELECT(i));
}
}
static void sdrv_vic_lld_set_vector(void)
{
int core_id = get_core_id_smp();
uint32_t int_num = g_vic_data[core_id].int_num;
#if CONFIG_VIC_IRQ_INTERRUPT_MODE
extern uint8_t vectored_irq0_handler, vectored_irq1_handler;
uint32_t vector_start_addr = (uint32_t)&vectored_irq0_handler;
uint32_t each_vector_size = (uint32_t)(&vectored_irq1_handler -
&vectored_irq0_handler);
for (uint32_t i = 0U; i < int_num; i++) {
writel(vector_start_addr + i * each_vector_size,
VICVECADDR(i));
}
#else
for (uint32_t i = 0U; i < int_num; i++) {
writel(i, VICVECADDR(i));
}
#endif
}
#if CONFIG_VIC_IRQ_INTERRUPT_MODE
static int sdrv_vic_dummy_isr(uint32_t vector)
{
return -1;
}
/* IRQ handler may be allowed not to use per cpu variable?
* Because this variable value is the same on all cores.
*/
int (*g_vic_user_isr)(uint32_t vector) = sdrv_vic_dummy_isr;
static inline void sdrv_vic_lld_set_user_isr(int (*isr)(uint32_t))
{
if (isr) {
g_vic_user_isr = isr;
}
}
#else
static inline void sdrv_vic_inc_int_nest_cnt(void)
{
g_vic_data[get_core_id_smp()].irq_nest_cnt++;
}
static inline int sdrv_vic_dec_int_nest_cnt(void)
{
return (--g_vic_data[get_core_id_smp()].irq_nest_cnt);
}
#endif
static inline void sdrv_vic_lld_clr_int_nest_cnt(void)
{
int core_id = get_core_id_smp();
g_vic_data[core_id].irq_nest_cnt = 0U;
}
static void sdrv_vic_lld_unmask_interrupt(uint32_t vector)
{
int core_id = get_core_id_smp();
RMWREG32(VICSWMASK(vector), SHIFT32(vector), 1U, 0U);
}
/**
* @brief Mask specified interrupt
* @param vector priority to be masked
*/
static void sdrv_vic_lld_mask_interrupt(uint32_t vector)
{
int core_id = get_core_id_smp();
RMWREG32(VICSWMASK(vector), SHIFT32(vector), 1U, 1U);
}
/**
* @brief Mask all low priority level
* @param [in] pri_threshold interrupts with priority equals
* to or lower than pri_threshold are masked.
* @param [in] user if this api called by user or interrupt
* framework.
* @return Previous masked priority value
*/
uint32_t sdrv_vic_lld_mask_low_priority(uint32_t pri_threshold, bool user)
{
uint32_t ret;
int core_id = get_core_id_smp();
struct vic_data *vicdata = &g_vic_data[core_id];
irq_state_t state = arch_irq_save();
ret = vicdata->previous_masked_pri;
pri_threshold = MIN(pri_threshold, MAX_PRI + 1);
if (user)
vicdata->previous_masked_pri = pri_threshold;
if (NO_INT_NEST_ERRATA != int_nest_errata_enabled()) {
/* If called by user, update current masked priority. */
if (user)
vicdata->cur_swmask = pri_threshold;
/* When user sets priority mask, always no unmasking any
* priority masked by interrupt framework.
*/
if (user && (vicdata->cur_rp < pri_threshold))
pri_threshold = vicdata->cur_rp;
/* When interrupt framework sets priority mask, always no
* unmasking any priority masked by user.
*/
else if (!user && (vicdata->cur_swmask < pri_threshold))
pri_threshold = vicdata->cur_swmask;
}
if (0 == get_minor_chip_id()) {
uint32_t swmask[SWMASK_REG_NUM] = {0};
struct pri_mask *pmsk = &vicdata->swmsk.pmsk;
uint32_t *curmask = vicdata->swmsk.cur_sw_mask;
/* Larger priority value, lower priority. */
for (int i = 0; i <= MAX_PRI; i++) {
/* Update mask value of each priroity. */
if (i < pri_threshold)
pmsk->masked[i] = false;
else
pmsk->masked[i] = true;
}
if (pri_threshold <= MAX_PRI) {
/* Update swmask register value to low pri masked bitmap. */
memcpy(swmask, pmsk->low_pri_mask[pri_threshold], sizeof(swmask));
}
for (int i = 0; i < SWMASK_REG_NUM; i++) {
if (curmask[i] != swmask[i]) {
writel(swmask[i], VICSWMASK_REG(i));
curmask[i] = swmask[i];
}
}
}
else {
uint16_t temp = 0xFFFF;
temp = temp >> (16 - pri_threshold);
writel(temp, VICSWPRIORITYMASK);
}
vicdata->pri_masked = pri_threshold;
arch_irq_restore(state);
return ret;
}
/**
* @brief Unmask all interrupt
*/
void sdrv_vic_lld_unmask_all_interrupt(void)
{
if (1 == get_minor_chip_id()) {
int core_id = get_core_id_smp();
irq_state_t state = arch_irq_save();
for (int i = 0; i < SWMASK_REG_NUM; i++)
writel(0, VICSWMASK_REG(i));
arch_irq_restore(state);
}
}
/**
* @brief Unmask all priority
*/
void sdrv_vic_lld_unmask_all_priority(void)
{
sdrv_vic_lld_mask_low_priority(0xFF, true);
}
/**
* @brief Initialize VIC
* @param isr user ISR
*/
void sdrv_vic_lld_init(uint32_t base, uint32_t intr_num, int (*isr)(uint32_t))
{
int core_id = get_core_id_smp();
g_vic_data[core_id].base = base;
g_vic_data[core_id].int_num = intr_num;
g_vic_data[core_id].cur_rp = 0xFF;
g_vic_data[core_id].previous_masked_pri = ~0;
if (0 == get_minor_chip_id())
memset(g_vic_data[core_id].swmsk.cur_sw_mask, 0xFF,
sizeof(g_vic_data[core_id].swmsk.cur_sw_mask));
sdrv_vic_lld_int_disable_all();
sdrv_vic_lld_all_ints_trigger_irq();
sdrv_vic_lld_unmask_all_interrupt();
sdrv_vic_lld_unmask_all_priority();
sdrv_vic_lld_func_safety_en();
sdrv_vic_lld_set_vector();
#if CONFIG_VIC_IRQ_INTERRUPT_MODE
sdrv_vic_lld_set_user_isr(isr);
arch_vectored_irq_enable(1U);
#else
arch_vectored_irq_enable(0U);
#endif
sdrv_vic_lld_clr_int_nest_cnt();
}
static inline void
sdrv_vic_lld_clear_int_mask(uint32_t vector)
{
int core_id = get_core_id_smp();
struct sw_mask *swmsk = &g_vic_data[core_id].swmsk;
for (int i = 0; i <= MAX_PRI; i++) {
unsigned long *intmask = swmsk->pmsk.int_mask[i];
unsigned long *low_pir_mask = swmsk->pmsk.low_pri_mask[i];
if (bitmap_test(intmask, vector))
bitmap_clear(intmask, vector);
if (bitmap_test(low_pir_mask, vector))
bitmap_clear(low_pir_mask, vector);
}
}
/**
* @brief Set priority
*/
void sdrv_vic_lld_set_priority(uint32_t vector,
uint32_t pri)
{
int core_id = get_core_id_smp();
irq_state_t state = arch_irq_save();
writel(pri & 15U, VICVECTPRIORITY(vector));
if (0 == get_minor_chip_id()) {
struct pri_mask *pmsk = &g_vic_data[core_id].swmsk.pmsk;
unsigned long *intmask = pmsk->int_mask[pri];
/* In case of modifying priority dynamically, clear
* previous int bitmap first.
*/
sdrv_vic_lld_clear_int_mask(vector);
bitmap_set(intmask, vector);
/* If masking a equal or higher priority, this
* vector should be masked. So, set this vector
* in each low pir mask bitmap with a equal or
* higher priority.
*/
for (int i = 0; i <= pri; i++) {
bitmap_set(pmsk->low_pri_mask[i], vector);
}
if (pmsk->masked[pri])
sdrv_vic_lld_mask_interrupt(vector);
else
sdrv_vic_lld_unmask_interrupt(vector);
}
arch_irq_restore(state);
}
/**
* @brief Enable interrupt
* @param [in] vector interrupt vector number
*/
void sdrv_vic_lld_int_enable(uint32_t vector)
{
int core_id = get_core_id_smp();
irq_state_t state = arch_irq_save();
RMWREG32(VICINTENABLE(vector), SHIFT32(vector), 1U, 1U);
arch_irq_restore(state);
}
/**
* @brief Disable interrupt
* @param [in] vector interrupt vector number
*/
void sdrv_vic_lld_int_disable(uint32_t vector)
{
int core_id = get_core_id_smp();
irq_state_t state = arch_irq_save();
RMWREG32(VICINTENCLEAR(vector), SHIFT32(vector), 1U, 1U);
arch_irq_restore(state);
}
/**
* @brief Get priority
* @param [in] vector interrupt vector number
* @return interrupt priority
*/
uint32_t sdrv_vic_lld_get_priority(uint32_t vector)
{
int core_id = get_core_id_smp();
return readl(VICVECTPRIORITY(vector)) & 15U;
}
/**
* @brief Get current running priority
* @return uint32_t current running priority
*/
uint32_t sdrv_vic_lld_current_running_priority(void)
{
return g_vic_data[get_core_id_smp()].cur_rp;
}
/**
* @brief Set one vector to trigger FIQ requeset
* @param [in] vector vector number
*/
void sdrv_vic_lld_set_fiq_req_src(uint32_t vector)
{
int core_id = get_core_id_smp();
uint32_t int_num = g_vic_data[core_id].int_num;
irq_state_t state = arch_irq_save();
/* The system should have at most one FIQ source. */
for (uint32_t i = 0U; i < int_num; i += 32U) {
if ((i >> 5) == (vector >> 5)) {
writel(1U << SHIFT32(vector), VICINTSELECT(vector));
}
else {
writel(0U, VICINTSELECT(i));
}
}
arch_irq_restore(state);
}
static inline int local_fls(int x)
{
int r = 32;
if (!x)
return 0;
if (!(x & 0xffff0000u)) {
x <<= 16;
r -= 16;
}
if (!(x & 0xff000000u)) {
x <<= 8;
r -= 8;
}
if (!(x & 0xf0000000u)) {
x <<= 4;
r -= 4;
}
if (!(x & 0xc0000000u)) {
x <<= 2;
r -= 2;
}
if (!(x & 0x80000000u)) {
x <<= 1;
r -= 1;
}
return r;
}
/**
* @brief Get current serviced fiq vector number
* @return uint32_t vector number
*/
uint32_t sdrv_vic_lld_get_active_fiq_src(void)
{
int core_id = get_core_id_smp();
uint32_t int_num = g_vic_data[core_id].int_num;
uint32_t i = 0U;
uint32_t fiq_status = 0U;
uint32_t ret = ~0;
irq_state_t state = arch_irq_save();
for (i = 0U; i < int_num; i += 32U) {
fiq_status = readl(VICFIQSTATUS(i));
if (fiq_status) {
ret = i + local_fls(fiq_status) - 1;
break;
}
}
arch_irq_restore(state);
return ret;
}
#if !CONFIG_VIC_IRQ_INTERRUPT_MODE
/**
* No lock needed, because the folling function
* is always called in IRQ disabled interrupt context.
*/
static void sdrv_vic_push_stack(struct stack *s, uint32_t val)
{
uint32_t head = s->head;
s->buf[head] = val;
s->head = head + 1;
}
static uint32_t sdrv_vic_pop_stack(struct stack *s)
{
uint32_t top = s->head - 1;
uint32_t ret = s->buf[top];
s->head = top;
return ret;
}
static inline void sdrv_vic_push_old_pri(void)
{
int core_id = get_core_id_smp();
struct stack *old_pri = &g_vic_data[core_id].old_pri;
sdrv_vic_push_stack(old_pri, g_vic_data[core_id].cur_rp);
}
static inline void sdrv_vic_pop_old_pri(void)
{
int core_id = get_core_id_smp();
struct stack *old_pri = &g_vic_data[core_id].old_pri;
g_vic_data[core_id].cur_rp = sdrv_vic_pop_stack(old_pri);
}
#endif
void sdrv_vic_lld_ack_slow_path(int errata, uint32_t running_pri)
{
/* Mask all interrupt with the same and lower priority
* to prevent:
* 1) same or lower priority interrupt preempting after
* writing VICADDRESS
* 2) same sw priority but higher hw priority interrupt
* preempting
*/
sdrv_vic_lld_mask_low_priority(running_pri, false);
/* Type0 (v1.0) & Type2 (v1.1 non-vectored irq) should wr isr to
* clear hwmask, in order to avoid mismatch between hwmask and
* vicaddress.
*/
if ((errata == INT_NEST_ERRATA_TYPE_0) ||
(errata == INT_NEST_ERRATA_TYPE_2)) {
int core_id = get_core_id_smp();
if (errata == INT_NEST_ERRATA_TYPE_0)
/* Because irq_b given by vic can only be cleared by CPU
* acknowledge to vic, so if vic outputs another valid
* irq_b signal triggered by interrupt with the same sw
* priority but lower interrupt number before masking it,
* CPU will take it after IRQ re-enabled.
* To avoid this, here we should read vicaddress register
* first to clear the additional irq_b signal, and then
* writing vicaddress register to clear hwmask to make all
* interrupts, including this additional interrupt, can be
* sent to CPU at the right time.
*/
(void)readl(VICADDRESS);
/* A dummy write to VICADDRESS
* finish the current interrupt.
*/
writel(0, VICADDRESS);
}
}
/**
* @brief Interrupt acknowledge
* @return uint32_t interrupt number
*/
uint32_t sdrv_vic_lld_ack(void)
{
#if !CONFIG_VIC_IRQ_INTERRUPT_MODE
int core_id = get_core_id_smp();
if (!arch_in_fiq_mode()) {
sdrv_vic_inc_int_nest_cnt();
uint32_t vector_num = readl(VICADDRESS);
/* Save previous running priority. */
sdrv_vic_push_old_pri();
/* Update current running priority. */
uint32_t cur_rp = sdrv_vic_lld_get_priority(vector_num);
g_vic_data[core_id].cur_rp = cur_rp;
/* Save priority mask before this interrupt. */
uint32_t pri_mask = g_vic_data[core_id].pri_masked;
int errata = int_nest_errata_enabled();
if (errata != NO_INT_NEST_ERRATA)
sdrv_vic_lld_ack_slow_path(errata, cur_rp);
/* Make sure only unmasked interrupt can be taken. */
if (cur_rp >= pri_mask)
return g_vic_data[core_id].int_num;
#if CONFIG_VIC_INT_NEST_AUTO_ENABLE
if (g_vic_data[core_id].irq_nest_cnt < CONFIG_VIC_INT_NEST_MAX_CNT)
arch_irq_enable();
#endif
return vector_num;
}
else
#endif
{
return sdrv_vic_lld_get_active_fiq_src();
}
}
#if !CONFIG_VIC_IRQ_INTERRUPT_MODE
/**
* @brief Interrupt completed
*/
void sdrv_vic_lld_eoi(uint32_t vector)
{
/* No need to write vicaddress register
* in FIQ service routine.
*/
if (!arch_in_fiq_mode()) {
int core_id = get_core_id_smp();
arch_irq_disable();
int errta = int_nest_errata_enabled();
if (errta == NO_INT_NEST_ERRATA)
/* A dummy write to VICADDRESS
* finish the current interrupt.
*/
writel(vector, VICADDRESS);
sdrv_vic_dec_int_nest_cnt();
/* Restore previous running priority. */
sdrv_vic_pop_old_pri();
if (errta != NO_INT_NEST_ERRATA)
/* Unmask priority to previous state. */
sdrv_vic_lld_mask_low_priority(g_vic_data[core_id].cur_rp,
false);
}
}
#endif
/**
* @brief Trigger software interrupt
* @param [in] vector interrupt number
*/
void sdrv_vic_lld_trigger_soft_int(uint32_t vector)
{
int core_id = get_core_id_smp();
irq_state_t state = arch_irq_save();
writel(1U << SHIFT32(vector), VICSOFTINT(vector));
arch_irq_restore(state);
}
/**
* @brief Clear software interrupt
* @param [in] vector interrupt number
*/
void sdrv_vic_lld_clear_soft_int(uint32_t vector)
{
int core_id = get_core_id_smp();
irq_state_t state = arch_irq_save();
writel(1U << SHIFT32(vector), VICSOFTINTCLEAR(vector));
arch_irq_restore(state);
}
void *get_vic_data_base(void)
{
return &g_vic_data[get_core_id_smp()];
}

View File

@@ -0,0 +1,76 @@
/*
* sd_vic.h
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: SemiDrive VIC header file.
*
* Revision History:
* -----------------
*/
#ifndef SDRV_VIC_H_
#define SDRV_VIC_H_
#define DEFAULT_IRQ_PRIORITY 10U
#define irq_lld_initialize sdrv_vic_lld_init
#define irq_lld_set_priority sdrv_vic_lld_set_priority
#define irq_lld_disable sdrv_vic_lld_int_disable
#define irq_lld_enable sdrv_vic_lld_int_enable
#define irq_lld_mask(x) sdrv_vic_lld_mask_low_priority(x, true)
#define irq_lld_get_priority sdrv_vic_lld_get_priority
#define irq_lld_get_current_priority sdrv_vic_lld_current_running_priority
#define irq_lld_unmask sdrv_vic_lld_unmask_all_priority
#define irq_lld_acknowledge sdrv_vic_lld_ack
#if CONFIG_VIC_IRQ_INTERRUPT_MODE
#define irq_lld_complete(irq)
#else
#define irq_lld_complete(irq) sdrv_vic_lld_eoi(irq)
#endif
/* Not supported interface by VIC. */
#define irq_lld_set_trigger_mode(irq, mode) (void)mode
/**
* Type 0: v1.0
* Type 1: v1.1 vectored irq mode
* Type 2: v1.1 non-vectored irq mode
*/
#define NO_INT_NEST_ERRATA 0
#define INT_NEST_ERRATA_TYPE_0 1
#define INT_NEST_ERRATA_TYPE_1 2
#define INT_NEST_ERRATA_TYPE_2 3
#ifndef ASSEMBLY
#include <compiler.h>
#include <stdint.h>
__BEGIN_CDECLS
uint32_t sdrv_vic_lld_mask_low_priority(uint32_t pri_threshold, bool user);
void sdrv_vic_lld_unmask_all_priority(void);
void sdrv_vic_lld_init(uint32_t base, uint32_t intr_num, int (*isr)(uint32_t));
void sdrv_vic_lld_set_priority(uint32_t vector,
uint32_t pri);
void sdrv_vic_lld_int_enable(uint32_t vector);
void sdrv_vic_lld_int_disable(uint32_t vector);
uint32_t sdrv_vic_lld_get_priority(uint32_t vector);
uint32_t sdrv_vic_lld_current_running_priority(void);
void sdrv_vic_lld_set_fiq_req_src(uint32_t vector);
uint32_t sdrv_vic_lld_get_active_fiq_src(void);
uint32_t sdrv_vic_lld_ack(void);
#if !CONFIG_VIC_IRQ_INTERRUPT_MODE
void sdrv_vic_lld_eoi(uint32_t vector);
#endif
void sdrv_vic_lld_trigger_soft_int(uint32_t vector);
void sdrv_vic_lld_clear_soft_int(uint32_t vector);
__END_CDECLS
#endif // !ASSEMBLY
#endif // !SDRV_VIC_H_

View File

@@ -0,0 +1,199 @@
/*
* sd_vic_baremetal.S
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: SemiDrive VIC interrupt handlers for baremetal.
*
* Revision History:
* -----------------
*/
#if __ICCARM__
extern get_vic_data_base
extern sdrv_vic_lld_get_priority
extern sdrv_vic_lld_ack_slow_path
extern g_vic_user_isr
extern int_nest_errata_enabled
extern sdrv_vic_lld_mask_low_priority
#endif
#if __GNUC__
.macro save_fpu_context
#elif __ICCARM__
save_fpu_context macro
#endif
vmrs r1, fpexc
tst r1, #(1 << 30)
beq save_exit
/* Save callee corrupted fpu registers */
vpush {d0-d7}
/* Save fpscr and fpexc */
vmrs r1, fpscr
push {r1}
vmrs r1, fpexc
save_exit:
push {r1}
#if __GNUC__
.endm
#elif __ICCARM__
endm
#endif
#if __GNUC__
.macro restore_fpu_context
#elif __ICCARM__
restore_fpu_context macro
#endif
pop {r1}
vmsr fpexc, r1
tst r1, #(1 << 30)
beq restore_exit
pop {r1}
vmsr fpscr, r1
vpop {d0-d7}
restore_exit:
#if __GNUC__
.endm
#elif __ICCARM__
endm
#endif
#if __GNUC__
.macro vectored_irq_handler vector_num
.globl vectored_irq\vector_num\()_handler
vectored_irq\vector_num\()_handler:
sub lr, lr, #4
srsdb sp!, #SVC_MODE
cps #SVC_MODE
/* Save callee and common_irq_handler corrupted registers */
push {r0-r5, r12}
mov r0, #\vector_num
b .Lcommon_irq_handler
.endm
#elif __ICCARM__
vectored_irq_handler macro vector_num
public vectored_irq\1_handler
vectored_irq\1_handler:
sub lr, lr, #4
srsdb sp!, #SVC_MODE
cps #SVC_MODE
/* Save callee and common_irq_handler corrupted registers */
push {r0-r5, r12}
mov r0, #vector_num
b .Lcommon_irq_handler
endm
#endif
.Lcommon_irq_handler:
/* Save fpu context, will corrupt r1 */
save_fpu_context
/* Force sp to align to 8 bytes */
mov r1, sp
bic sp, sp, #7
/* Save old sp and supervisor lr */
push {r1, lr}
/* Save vector number into callee-saved register */
mov r4, r0
/* Save old running priority */
blx get_vic_data_base
add r1, r0, #8 /* r1 now holds address of {struct vic_data}.cur_rp */
ldr r2, [r1]
push {r1, r2}
/* Update current running priority */
mov r0, r4
blx sdrv_vic_lld_get_priority
ldr r1, [sp]
str r0, [r1]
/* Get previous masked priority */
ldr r1, [r1, #8]
push {r0, r1}
blx int_nest_errata_enabled
/* Save errata enabled flag into callee-saved r5 */
movs r5, r0
beq .Lno_errata
ldr r1, [sp]
blx sdrv_vic_lld_ack_slow_path
.Lno_errata:
pop {r0, r1}
/* Make sure only unmasked interrupt can be taken. */
cmp r0, r1
bge .Lirq_out
/* Increment interrupt nesting counter */
ldr r1, [sp]
ldr r2, [r1, #4]! /* r1 now holds address of {struct vic_data}.irq_nest_cnt */
add r0, r2, #1
str r0, [r1]
push {r1, r2}
#if CONFIG_VIC_INT_NEST_AUTO_ENABLE
cmp r0, #CONFIG_VIC_INT_NEST_MAX_CNT
bge .Lskip_reenable_irq
cpsie i
.Lskip_reenable_irq:
#endif
/* Call user ISR */
mov r0, r4
ldr r1, =g_vic_user_isr
ldr r1, [r1]
blx r1
cpsid i
/* Decrement interrupt nesting counter */
pop {r1, r2}
str r2, [r1]
.Lirq_out:
/* Restore current running priority */
pop {r1, r2}
str r2, [r1]
cmp r5, #INT_NEST_ERRATA_TYPE_0
beq .Lerrata_skip_wr_isr
ldr r1, [r1, #-8]
add r1, r1, #0xF00
/* Perform a dummy write to VICADDRESS register to clear hwmask */
str r4, [r1]
.Lerrata_skip_wr_isr:
cmp r5, #NO_INT_NEST_ERRATA
beq .Lrestore_context
/* Unmask priority to previous state. */
mov r0, r2
mov r1, #0
blx sdrv_vic_lld_mask_low_priority
.Lrestore_context:
/* Restore sp and supervisor lr */
pop {r1, lr}
mov sp, r1
restore_fpu_context
/* Restore context */
pop {r0-r5, r12}
rfeia sp!
#if __GNUC__
.ltorg
#elif __ICCARM__
ltorg
#endif

View File

@@ -0,0 +1,334 @@
/*
* sd_vic_freertos.S
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: SemiDrive VIC interrupt handlers for freertos.
*
* Revision History:
* -----------------
*/
#if __ICCARM__
EXTERN ulCriticalNesting
EXTERN ulMaxAPIPriority
EXTERN pxCurrentTCB
EXTERN vTaskSwitchContext
EXTERN vApplicationIRQHandler
EXTERN ulPortInterruptNesting
EXTERN ulPortTaskHasFPUContext
EXTERN ulPortYieldRequired
EXTERN vPortSetInterruptMaskAsm
EXTERN get_vic_data_base
EXTERN sdrv_vic_lld_get_priority
EXTERN sdrv_vic_lld_ack_slow_path
EXTERN g_vic_user_isr
EXTERN int_nest_errata_enabled
EXTERN sdrv_vic_lld_mask_low_priority
#endif
#if __GNUC__
.macro portSAVE_CONTEXT
#elif __ICCARM__
portSAVE_CONTEXT MACRO
#endif
/* Save the LR and SPSR onto the system mode stack before switching to
system mode to save the remaining system mode registers. */
SRSDB sp!, #SYS_MODE
CPS #SYS_MODE
PUSH {R0-R12, R14}
/* Push the critical nesting count. */
LDR R2, =ulCriticalNesting
LDR R1, [R2]
PUSH {R1}
/* Does the task have a floating point context that needs saving? If
ulPortTaskHasFPUContext is 0 then no. */
LDR R2, =ulPortTaskHasFPUContext
LDR R3, [R2]
CMP R3, #0
/* Save the floating point context, if any. */
FMRXNE R1, FPSCR
VPUSHNE {D0-D15}
/*VPUSHNE {D16-D31}*/
PUSHNE {R1}
/* Save ulPortTaskHasFPUContext itself. */
PUSH {R3}
/* Save the stack pointer in the TCB. */
LDR R0, =pxCurrentTCB
LDR R1, [R0]
STR SP, [R1]
#if __GNUC__
.endm
#elif __ICCARM__
ENDM
#endif
; /**********************************************************************/
#if __GNUC__
.macro portRESTORE_CONTEXT
#elif __ICCARM__
portRESTORE_CONTEXT MACRO
#endif
/* Set the SP to point to the stack of the task being restored. */
LDR R0, =pxCurrentTCB
LDR R1, [R0]
LDR SP, [R1]
/* Is there a floating point context to restore? If the restored
ulPortTaskHasFPUContext is zero then no. */
LDR R0, =ulPortTaskHasFPUContext
POP {R1}
STR R1, [R0]
CMP R1, #0
/* Restore the floating point context, if any. */
POPNE {R0}
/*VPOPNE {D16-D31}*/
VPOPNE {D0-D15}
VMSRNE FPSCR, R0
/* Restore the critical section nesting depth. */
LDR R0, =ulCriticalNesting
POP {R1}
STR R1, [R0]
/* Ensure the priority mask is correct for the critical nesting depth. */
CMP R1, #0
MOVEQ R0, #255
LDRNE R0, =ulMaxAPIPriority
LDRNE R0, [R0]
LDR R4, =vPortSetInterruptMaskAsm
BLX R4
/* Restore all system mode registers other than the SP (which is already
being used). */
POP {R0-R12, R14}
/* Return to the task code, loading CPSR on the way. */
RFEIA sp!
#if __GNUC__
.endm
#elif __ICCARM__
ENDM
#endif
#if __GNUC__
.macro vectored_irq_handler vector_num
.globl vectored_irq\vector_num\()_handler
vectored_irq\vector_num\()_handler:
/* Return to the interrupted instruction. */
SUB lr, lr, #4
/* Push the return address and SPSR. */
PUSH {lr}
MRS lr, SPSR
PUSH {lr}
/* Change to supervisor mode to allow reentry. */
CPS #SVC_MODE
/* Push used registers. */
PUSH {r0-r4, r12}
MOV r0, #\vector_num
B .Lcommon_irq_handler
.endm
#elif __ICCARM__
vectored_irq_handler MACRO vector_num
PUBLIC vectored_irq\1_handler
vectored_irq\1_handler:
/* Return to the interrupted instruction. */
SUB lr, lr, #4
/* Push the return address and SPSR. */
PUSH {lr}
MRS lr, SPSR
PUSH {lr}
/* Change to supervisor mode to allow reentry. */
CPS #SVC_MODE
/* Push used registers. */
PUSH {r0-r4, r12}
MOV r0, #vector_num
B .Lcommon_irq_handler
ENDM
#endif
.Lcommon_irq_handler:
/* Save old running priority. */
PUSH {r0, lr} /* Save vectore number (r0) & svc return address (lr) */
BLX get_vic_data_base
ADD r2, r0, #8 /* r2 now holds address of {struct vic_data}.cur_rp */
POP {r0, lr} /* Restore vectore number (r0) & svc return address (lr) */
LDR r1, [r2]
PUSH {r1, r2}
/* Increment nesting count. r3 holds the address of ulPortInterruptNesting
for future use. r1 holds the original ulPortInterruptNesting value for
future use. */
LDR r3, =ulPortInterruptNesting
LDR r1, [r3]
ADD r4, r1, #1
STR r4, [r3]
/* Save address of {struct vic_data}.cur_rp into callee-saved r4. */
MOV r4, r2
/* Use r5 to record errata enabled flag, save it before corrupted. */
PUSH {r5}
/* Ensure bit 2 of the stack pointer is clear. r2 holds the bit 2 value for
future use. _RB_ Is this ever needed provided the start of the stack is
alligned on an 8-byte boundary? */
MOV r2, sp
AND r2, r2, #4
SUB sp, sp, r2
/* Call the interrupt handler. */
PUSH {r0-r4, lr}
/* Update current running priority. */
BLX sdrv_vic_lld_get_priority
STR r0, [r4]
/* Get previous masked priority. */
LDR r1, [r4, #8]
PUSH {r0, r1}
BLX int_nest_errata_enabled
MOVS r5, r0
BEQ .Lno_errata
LDR r1, [sp]
BLX sdrv_vic_lld_ack_slow_path
.Lno_errata:
POP {r0, r1}
/* Make sure only unmasked interrupt can be taken. */
CMP r0, r1
BGE .Lirq_out
#if CONFIG_VIC_INT_NEST_AUTO_ENABLE
LDR r0, [sp, #4]
CMP r0, #(CONFIG_VIC_INT_NEST_MAX_CNT - 1)
BGE .Lskip_reenable_irq
CPSIE i
.Lskip_reenable_irq:
#endif
/* Restore vector number */
LDR r0, [sp]
/* Call user ISR. */
LDR r1, =g_vic_user_isr
LDR r1, [r1]
BLX r1
.Lirq_out:
POP {r0-r4, lr}
ADD sp, sp, r2
CPSID i
DSB
ISB
CMP r5, #INT_NEST_ERRATA_TYPE_0
BEQ .Lerrata_skip_wr_isr
LDR r2, [r4, #-8]
ADD r2, r2, #0xF00
/* Perform a dummy write to VICADDRESS register to finish this interrupt */
STR r0, [r2]
.Lerrata_skip_wr_isr:
/* Restore the old nesting count. */
STR r1, [r3]
CMP r5, #NO_INT_NEST_ERRATA
/* Restore r5. */
POP {r5}
/* Restore current running priority. */
POP {r0, r2}
STR r0, [r2]
BEQ .Lrestore_context
/* Save previous nesting counter and supervisor lr (preempted isr lr). */
PUSH {r1, lr}
MOV r1, #0
/* Unmask priority to previous state. */
BLX sdrv_vic_lld_mask_low_priority
/* Restore previous nesting counter and supervisor lr. */
POP {r1, lr}
.Lrestore_context:
/* A context switch is never performed if the nesting count is not 0. */
CMP r1, #0
BNE .Lexit_without_switch
/* Did the interrupt request a context switch? r1 holds the address of
ulPortYieldRequired and r0 the value of ulPortYieldRequired for future
use. */
LDR r1, =ulPortYieldRequired
LDR r0, [r1]
CMP r0, #0
BNE .Lswitch_before_exit
B .Lexit_without_switch
#if __GNUC__
.ltorg
#elif __ICCARM__
LTORG
#endif
.Lexit_without_switch:
/* No context switch. Restore used registers, LR_irq and SPSR before
returning. */
POP {r0-r4, r12}
CPS #IRQ_MODE
POP {LR}
MSR SPSR_cxsf, LR
POP {LR}
MOVS PC, LR
.Lswitch_before_exit:
/* A context swtich is to be performed. Clear the context switch pending
flag. */
MOV r0, #0
STR r0, [r1]
/* Restore used registers, LR-irq and SPSR before saving the context
to the task stack. */
POP {r0-r4, r12}
CPS #IRQ_MODE
POP {LR}
MSR SPSR_cxsf, LR
POP {LR}
portSAVE_CONTEXT
/* Call the function that selects the new task to execute.
vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD
instructions, or 8 byte aligned stack allocated data. LR does not need
saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */
LDR R0, =vTaskSwitchContext
BLX R0
/* Restore the context of, and branch to, the task selected to execute
next. */
portRESTORE_CONTEXT
#if __GNUC__
.ltorg
#elif __ICCARM__
LTORG
#endif

View File

@@ -0,0 +1,307 @@
/*
* sd_vic.S
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: SemiDrive VIC interrupt handlers.
*
* Revision History:
* -----------------
*/
#include "config.h"
#if __GNUC__
.arm
.set SYS_MODE, 0x1f
.set SVC_MODE, 0x13
.set IRQ_MODE, 0x12
#elif __ICCARM__
section .text:CODE:ROOT(2)
arm
SYS_MODE equ 0x1f
SVC_MODE equ 0x13
IRQ_MODE equ 0x12
#else
#error Unknown compiler.
#endif
#if CONFIG_VIC_IRQ_INTERRUPT_MODE
#include "sdrv_vic.h"
#if CONFIG_OS_FREERTOS
#include "sdrv_vic_freertos.S"
#else
#include "sdrv_vic_baremetal.S"
#endif
vector:
vectored_irq_handler 0
vectored_irq_handler 1
vectored_irq_handler 2
vectored_irq_handler 3
vectored_irq_handler 4
vectored_irq_handler 5
vectored_irq_handler 6
vectored_irq_handler 7
vectored_irq_handler 8
vectored_irq_handler 9
vectored_irq_handler 10
vectored_irq_handler 11
vectored_irq_handler 12
vectored_irq_handler 13
vectored_irq_handler 14
vectored_irq_handler 15
vectored_irq_handler 16
vectored_irq_handler 17
vectored_irq_handler 18
vectored_irq_handler 19
vectored_irq_handler 20
vectored_irq_handler 21
vectored_irq_handler 22
vectored_irq_handler 23
vectored_irq_handler 24
vectored_irq_handler 25
vectored_irq_handler 26
vectored_irq_handler 27
vectored_irq_handler 28
vectored_irq_handler 29
vectored_irq_handler 30
vectored_irq_handler 31
vectored_irq_handler 32
vectored_irq_handler 33
vectored_irq_handler 34
vectored_irq_handler 35
vectored_irq_handler 36
vectored_irq_handler 37
vectored_irq_handler 38
vectored_irq_handler 39
vectored_irq_handler 40
vectored_irq_handler 41
vectored_irq_handler 42
vectored_irq_handler 43
vectored_irq_handler 44
vectored_irq_handler 45
vectored_irq_handler 46
vectored_irq_handler 47
vectored_irq_handler 48
vectored_irq_handler 49
vectored_irq_handler 50
vectored_irq_handler 51
vectored_irq_handler 52
vectored_irq_handler 53
vectored_irq_handler 54
vectored_irq_handler 55
vectored_irq_handler 56
vectored_irq_handler 57
vectored_irq_handler 58
vectored_irq_handler 59
vectored_irq_handler 60
vectored_irq_handler 61
vectored_irq_handler 62
vectored_irq_handler 63
vectored_irq_handler 64
vectored_irq_handler 65
vectored_irq_handler 66
vectored_irq_handler 67
vectored_irq_handler 68
vectored_irq_handler 69
vectored_irq_handler 70
vectored_irq_handler 71
vectored_irq_handler 72
vectored_irq_handler 73
vectored_irq_handler 74
vectored_irq_handler 75
vectored_irq_handler 76
vectored_irq_handler 77
vectored_irq_handler 78
vectored_irq_handler 79
vectored_irq_handler 80
vectored_irq_handler 81
vectored_irq_handler 82
vectored_irq_handler 83
vectored_irq_handler 84
vectored_irq_handler 85
vectored_irq_handler 86
vectored_irq_handler 87
vectored_irq_handler 88
vectored_irq_handler 89
vectored_irq_handler 90
vectored_irq_handler 91
vectored_irq_handler 92
vectored_irq_handler 93
vectored_irq_handler 94
vectored_irq_handler 95
vectored_irq_handler 96
vectored_irq_handler 97
vectored_irq_handler 98
vectored_irq_handler 99
vectored_irq_handler 100
vectored_irq_handler 101
vectored_irq_handler 102
vectored_irq_handler 103
vectored_irq_handler 104
vectored_irq_handler 105
vectored_irq_handler 106
vectored_irq_handler 107
vectored_irq_handler 108
vectored_irq_handler 109
vectored_irq_handler 110
vectored_irq_handler 111
vectored_irq_handler 112
vectored_irq_handler 113
vectored_irq_handler 114
vectored_irq_handler 115
vectored_irq_handler 116
vectored_irq_handler 117
vectored_irq_handler 118
vectored_irq_handler 119
vectored_irq_handler 120
vectored_irq_handler 121
vectored_irq_handler 122
vectored_irq_handler 123
vectored_irq_handler 124
vectored_irq_handler 125
vectored_irq_handler 126
vectored_irq_handler 127
vectored_irq_handler 128
vectored_irq_handler 129
vectored_irq_handler 130
vectored_irq_handler 131
vectored_irq_handler 132
vectored_irq_handler 133
vectored_irq_handler 134
vectored_irq_handler 135
vectored_irq_handler 136
vectored_irq_handler 137
vectored_irq_handler 138
vectored_irq_handler 139
vectored_irq_handler 140
vectored_irq_handler 141
vectored_irq_handler 142
vectored_irq_handler 143
vectored_irq_handler 144
vectored_irq_handler 145
vectored_irq_handler 146
vectored_irq_handler 147
vectored_irq_handler 148
vectored_irq_handler 149
vectored_irq_handler 150
vectored_irq_handler 151
vectored_irq_handler 152
vectored_irq_handler 153
vectored_irq_handler 154
vectored_irq_handler 155
vectored_irq_handler 156
vectored_irq_handler 157
vectored_irq_handler 158
vectored_irq_handler 159
vectored_irq_handler 160
vectored_irq_handler 161
vectored_irq_handler 162
vectored_irq_handler 163
vectored_irq_handler 164
vectored_irq_handler 165
vectored_irq_handler 166
vectored_irq_handler 167
vectored_irq_handler 168
vectored_irq_handler 169
vectored_irq_handler 170
vectored_irq_handler 171
vectored_irq_handler 172
vectored_irq_handler 173
vectored_irq_handler 174
vectored_irq_handler 175
vectored_irq_handler 176
vectored_irq_handler 177
vectored_irq_handler 178
vectored_irq_handler 179
vectored_irq_handler 180
vectored_irq_handler 181
vectored_irq_handler 182
vectored_irq_handler 183
vectored_irq_handler 184
vectored_irq_handler 185
vectored_irq_handler 186
vectored_irq_handler 187
vectored_irq_handler 188
vectored_irq_handler 189
vectored_irq_handler 190
vectored_irq_handler 191
vectored_irq_handler 192
vectored_irq_handler 193
vectored_irq_handler 194
vectored_irq_handler 195
vectored_irq_handler 196
vectored_irq_handler 197
vectored_irq_handler 198
vectored_irq_handler 199
vectored_irq_handler 200
vectored_irq_handler 201
vectored_irq_handler 202
vectored_irq_handler 203
vectored_irq_handler 204
vectored_irq_handler 205
vectored_irq_handler 206
vectored_irq_handler 207
vectored_irq_handler 208
vectored_irq_handler 209
vectored_irq_handler 210
vectored_irq_handler 211
vectored_irq_handler 212
vectored_irq_handler 213
vectored_irq_handler 214
vectored_irq_handler 215
vectored_irq_handler 216
vectored_irq_handler 217
vectored_irq_handler 218
vectored_irq_handler 219
vectored_irq_handler 220
vectored_irq_handler 221
vectored_irq_handler 222
vectored_irq_handler 223
vectored_irq_handler 224
vectored_irq_handler 225
vectored_irq_handler 226
vectored_irq_handler 227
vectored_irq_handler 228
vectored_irq_handler 229
vectored_irq_handler 230
vectored_irq_handler 231
vectored_irq_handler 232
vectored_irq_handler 233
vectored_irq_handler 234
vectored_irq_handler 235
vectored_irq_handler 236
vectored_irq_handler 237
vectored_irq_handler 238
vectored_irq_handler 239
vectored_irq_handler 240
vectored_irq_handler 241
vectored_irq_handler 242
vectored_irq_handler 243
vectored_irq_handler 244
vectored_irq_handler 245
vectored_irq_handler 246
vectored_irq_handler 247
vectored_irq_handler 248
vectored_irq_handler 249
vectored_irq_handler 250
vectored_irq_handler 251
vectored_irq_handler 252
vectored_irq_handler 253
vectored_irq_handler 254
vectored_irq_handler 255
#endif /* CONFIG_VIC_IRQ_INTERRUPT_MODE */
#if __ICCARM__
end
#endif