修改上传所有文件
This commit is contained in:
210
e3_176_ref/drivers/source/vic/irq.c
Normal file
210
e3_176_ref/drivers/source/vic/irq.c
Normal 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 */
|
||||
730
e3_176_ref/drivers/source/vic/sdrv_vic.c
Normal file
730
e3_176_ref/drivers/source/vic/sdrv_vic.c
Normal 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()];
|
||||
}
|
||||
76
e3_176_ref/drivers/source/vic/sdrv_vic.h
Normal file
76
e3_176_ref/drivers/source/vic/sdrv_vic.h
Normal 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_
|
||||
199
e3_176_ref/drivers/source/vic/sdrv_vic_baremetal.S
Normal file
199
e3_176_ref/drivers/source/vic/sdrv_vic_baremetal.S
Normal 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
|
||||
334
e3_176_ref/drivers/source/vic/sdrv_vic_freertos.S
Normal file
334
e3_176_ref/drivers/source/vic/sdrv_vic_freertos.S
Normal 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
|
||||
307
e3_176_ref/drivers/source/vic/sdrv_vic_s.S
Normal file
307
e3_176_ref/drivers/source/vic/sdrv_vic_s.S
Normal 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
|
||||
Reference in New Issue
Block a user