123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- /**
- * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
- *
- * SPDX-License-Identifier: Apache-2.0
- ******************************************************************************
- * @file interrupt.c
- * @version V0.1
- * @brief interrupt interface for rt-thread
- *
- * Change Logs:
- * Date Author Notes
- * 2019-05-08 Cliff.Chen first implementation
- *
- ******************************************************************************
- */
- #include <rthw.h>
- #include "hal_base.h"
- #if defined(ARCH_ARM_CORTEX_M0) || defined(ARCH_ARM_CORTEX_M3) || defined(ARCH_ARM_CORTEX_M4) || defined(ARCH_ARM_CORTEX_M7)
- #if EXT_INTERRUPT
- struct rk_intc
- {
- void *intc_base;
- rt_isr_handler_t irq_handler;
- };
- static rt_isr_handler_t ext_vector[NUM_EXT_INTERRUPTS];
- static void intc_irq_dispatch(void *intc, uint32_t offset)
- {
- uint32_t i, irq_no;
- for (i = 0; i < NUM_EXT_INTERRUPTS; i++)
- {
- if (HAL_INTC_GetFinalStatus(intc, i))
- {
- irq_no = i + offset * NUM_INT_PER_CONTROLLER;
- ext_vector[irq_no](NUM_INTERRUPTS + irq_no, NULL);
- }
- }
- }
- #define DEFINE_RK_INTC_IRQ(ID) \
- static void rk_intc##ID##_irq_dispatch(int irq, void *param); \
- static struct rk_intc rk_intc##ID = \
- { \
- .intc_base = INTC##ID, \
- .irq_handler = rk_intc##ID##_irq_dispatch, \
- }; \
- static void rk_intc##ID##_irq_dispatch(int irq, void *param) \
- { \
- intc_irq_dispatch(INTC##ID, ID); \
- }
- #ifdef INTC0
- DEFINE_RK_INTC_IRQ(0);
- #endif
- #ifdef INTC1
- DEFINE_RK_INTC_IRQ(1);
- #endif
- #ifdef INTC2
- DEFINE_RK_INTC_IRQ(2);
- #endif
- #ifdef INTC3
- DEFINE_RK_INTC_IRQ(3);
- #endif
- static struct rk_intc *rk_intc_table[] =
- {
- #ifdef INTC0
- &rk_intc0,
- #endif
- #ifdef INTC1
- &rk_intc1,
- #endif
- #ifdef INTC2
- &rk_intc2,
- #endif
- #ifdef INTC3
- &rk_intc3,
- #endif
- };
- static void rk_intc_init(void)
- {
- uint32_t i;
- memset(ext_vector, 0, sizeof(ext_vector));
- for (i = 0; i < HAL_ARRAY_SIZE(rk_intc_table); i++)
- {
- HAL_NVIC_SetIRQHandler(INTC0_IRQn + i, (NVIC_IRQHandler)rk_intc_table[i]->irq_handler);
- HAL_NVIC_EnableIRQ(INTC0_IRQn + i);
- HAL_INTC_EnableAllRQ(rk_intc_table[i]->intc_base);
- }
- }
- static void rk_intc_mask(uint32_t vector)
- {
- uint32_t intc, irq;
- if (vector >= TOTAL_INTERRUPTS)
- return;
- if (vector < NUM_INTERRUPTS)
- HAL_NVIC_DisableIRQ(vector);
- else
- {
- intc = (vector - NUM_INTERRUPTS) / NUM_INT_PER_CONTROLLER;
- irq = (vector - NUM_INTERRUPTS) % NUM_INT_PER_CONTROLLER;
- if (intc >= HAL_ARRAY_SIZE(rk_intc_table))
- return;
- HAL_INTC_MaskIRQ(rk_intc_table[intc]->intc_base, irq);
- }
- }
- static void rk_intc_unmask(uint32_t vector)
- {
- uint32_t intc, irq;
- if (vector >= TOTAL_INTERRUPTS)
- return;
- if (vector < NUM_INTERRUPTS)
- HAL_NVIC_EnableIRQ(vector);
- else
- {
- intc = (vector - NUM_INTERRUPTS) / NUM_INT_PER_CONTROLLER;
- irq = (vector - NUM_INTERRUPTS) % NUM_INT_PER_CONTROLLER;
- if (intc >= HAL_ARRAY_SIZE(rk_intc_table))
- return;
- HAL_INTC_UnmaskIRQ(rk_intc_table[intc]->intc_base, irq);
- }
- }
- #endif /* end of EXT_INTERRUPT */
- #ifdef RT_USING_PROF_IRQ
- #define IRQ_AVG_COUNT 200
- struct irq_summry
- {
- uint32_t count;
- uint32_t start;
- uint32_t time_total;
- uint32_t time_avg;
- uint32_t time_max;
- };
- static struct irq_summry g_irq_prof[TOTAL_INTERRUPTS];
- static void irq_enter_hook(void)
- {
- uint32_t irq;
- irq = __get_IPSR() - 16;
- g_irq_prof[irq].count++;
- g_irq_prof[irq].start = HAL_TIMER_GetCount(SYS_TIMER);
- }
- static void irq_leave_hook(void)
- {
- uint32_t time_cur, end, irq;
- irq = __get_IPSR() - 16;
- end = HAL_TIMER_GetCount(SYS_TIMER);
- if (end < g_irq_prof[irq].start)
- end += PLL_INPUT_OSC_RATE;
- time_cur = end - g_irq_prof[irq].start;
- g_irq_prof[irq].time_total += time_cur;
- g_irq_prof[irq].time_max =
- g_irq_prof[irq].time_max > time_cur ? g_irq_prof[irq].time_max : time_cur;
- if (g_irq_prof[irq].count > 0 &&
- g_irq_prof[irq].count % IRQ_AVG_COUNT == 0)
- {
- g_irq_prof[irq].time_avg = g_irq_prof[irq].time_total / IRQ_AVG_COUNT;
- g_irq_prof[irq].time_total = 0;
- }
- }
- static void dump_irq_summry(int argc, char **argv)
- {
- uint32_t i;
- rt_kprintf("IRQ COUNT AVG MAX\n");
- for (i = 0; i < NUM_INTERRUPTS; i++)
- {
- rt_kprintf("%03d %08d %08d %08d\n", i, g_irq_prof[i].count,
- g_irq_prof[i].time_avg,
- g_irq_prof[i].time_max);
- }
- }
- #ifdef RT_USING_FINSH
- #include <finsh.h>
- MSH_CMD_EXPORT(dump_irq_summry, dump irq summry);
- #endif
- #endif /* end of RT_USING_PROF_IRQ */
- void rt_hw_interrupt_init(void)
- {
- uint32_t i;
- for (i = 0; i < NUM_INTERRUPTS; i++)
- {
- HAL_NVIC_SetPriority(i, NVIC_PERIPH_PRIO_DEFAULT, NVIC_PERIPH_SUB_PRIO_DEFAULT);
- }
- #if EXT_INTERRUPT
- rk_intc_init();
- #endif
- #ifdef RT_USING_PROF_IRQ
- rt_interrupt_enter_sethook(irq_enter_hook);
- rt_interrupt_leave_sethook(irq_leave_hook);
- #endif
- }
- void rt_hw_interrupt_mask(int vector)
- {
- #if EXT_INTERRUPT
- rk_intc_mask(vector);
- #else
- HAL_NVIC_DisableIRQ(vector);
- #endif
- }
- void rt_hw_interrupt_umask(int vector)
- {
- #if EXT_INTERRUPT
- rk_intc_unmask(vector);
- #else
- HAL_NVIC_EnableIRQ(vector);
- #endif
- }
- rt_isr_handler_t rt_hw_interrupt_install(int vector,
- rt_isr_handler_t handler,
- void *param,
- const char *name)
- {
- #if EXT_INTERRUPT
- if (vector < NUM_INTERRUPTS)
- HAL_NVIC_SetIRQHandler(vector, (NVIC_IRQHandler)handler);
- else
- ext_vector[vector - NUM_INTERRUPTS] = handler;
- #else
- HAL_NVIC_SetIRQHandler(vector, (NVIC_IRQHandler)handler);
- #endif
- return handler;
- }
- #endif /* end of defined(ARCH_ARM_CORTEX_M0) || defined(ARCH_ARM_CORTEX_M3) || defined(ARCH_ARM_CORTEX_M4) || defined(ARCH_ARM_CORTEX_M7) */
|