summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRbb666 <[email protected]>2026-08-03 11:54:48 +0800
committerRbb666 <[email protected]>2026-08-12 12:54:50 +0800
commit46fdeefb3239f8f4a22a373fc6fd362499389c9e (patch)
tree57464ca099223e8ad42219eaf1ff3d9e36ed63d2
parent1f23e3f27052a6b7fd75def2da634c79db5773e2 (diff)
refactor(pic): dispatch NVIC IRQs through traps
-rw-r--r--bsp/stm32/libraries/HAL_Drivers/drivers/dm/drv_exti.c14
-rwxr-xr-xcomponents/drivers/include/drivers/pic.h4
-rw-r--r--components/drivers/pic/pic-arm-nvic.c113
-rw-r--r--libcpu/arm/cortex-m4/cpuport.h37
-rw-r--r--libcpu/arm/cortex-m7/cpuport.h37
-rw-r--r--libcpu/arm/cortex-m85/cpuport.h37
6 files changed, 181 insertions, 61 deletions
diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/dm/drv_exti.c b/bsp/stm32/libraries/HAL_Drivers/drivers/dm/drv_exti.c
index 4a0db6ad56..3901e2b206 100644
--- a/bsp/stm32/libraries/HAL_Drivers/drivers/dm/drv_exti.c
+++ b/bsp/stm32/libraries/HAL_Drivers/drivers/dm/drv_exti.c
@@ -391,35 +391,35 @@ RT_PIC_OFW_DECLARE(stm32_exti, exti_ofw_ids, exti_ofw_init);
void EXTI0_IRQHandler(void)
{
- rt_hw_nvic_dispatch();
+ rt_pic_do_traps();
}
void EXTI1_IRQHandler(void)
{
- rt_hw_nvic_dispatch();
+ rt_pic_do_traps();
}
void EXTI2_IRQHandler(void)
{
- rt_hw_nvic_dispatch();
+ rt_pic_do_traps();
}
void EXTI3_IRQHandler(void)
{
- rt_hw_nvic_dispatch();
+ rt_pic_do_traps();
}
void EXTI4_IRQHandler(void)
{
- rt_hw_nvic_dispatch();
+ rt_pic_do_traps();
}
void EXTI9_5_IRQHandler(void)
{
- rt_hw_nvic_dispatch();
+ rt_pic_do_traps();
}
void EXTI15_10_IRQHandler(void)
{
- rt_hw_nvic_dispatch();
+ rt_pic_do_traps();
}
diff --git a/components/drivers/include/drivers/pic.h b/components/drivers/include/drivers/pic.h
index 71bdc50dde..c624d249d1 100755
--- a/components/drivers/include/drivers/pic.h
+++ b/components/drivers/include/drivers/pic.h
@@ -214,8 +214,4 @@ rt_err_t rt_pic_irq_parent_set_triger_mode(struct rt_pic_irq *pirq, rt_uint32_t
rt_err_t rt_pic_init(void);
-#ifdef RT_PIC_ARM_NVIC
-void rt_hw_nvic_dispatch(void);
-#endif
-
#endif /* __PIC_H__ */
diff --git a/components/drivers/pic/pic-arm-nvic.c b/components/drivers/pic/pic-arm-nvic.c
index 87fe598c8c..c7cacdadc7 100644
--- a/components/drivers/pic/pic-arm-nvic.c
+++ b/components/drivers/pic/pic-arm-nvic.c
@@ -9,6 +9,7 @@
*/
#include <rtthread.h>
+#include <cpuport.h>
#define DBG_TAG "pic.nvic"
#define DBG_LVL DBG_INFO
@@ -18,42 +19,46 @@
#include <drivers/ofw.h>
#include <drivers/ofw_io.h>
-#define NVIC_ICTR_ADDR 0xe000e004UL
-#define NVIC_ISER_OFFSET 0x000UL
-#define NVIC_ICER_OFFSET 0x080UL
-#define NVIC_ISPR_OFFSET 0x100UL
-#define NVIC_ICPR_OFFSET 0x180UL
-#define NVIC_IABR_OFFSET 0x200UL
-#define NVIC_IPR_OFFSET 0x300UL
-#define NVIC_REG_INDEX(irq) ((rt_uint32_t)(irq) >> 5)
-#define NVIC_REG_MASK(irq) RT_BIT((rt_uint32_t)(irq) & 0x1f)
+#define NVIC_ICTR_ADDR 0xe000e004UL
+#define NVIC_ICSR_ADDR 0xe000ed04UL
+#define NVIC_ICSR_VECTACTIVE_MASK 0x1ffUL
+#define NVIC_ISER_OFFSET 0x000UL
+#define NVIC_ICER_OFFSET 0x080UL
+#define NVIC_ISPR_OFFSET 0x100UL
+#define NVIC_ICPR_OFFSET 0x180UL
+#define NVIC_IABR_OFFSET 0x200UL
+#define NVIC_IPR_OFFSET 0x300UL
+#define NVIC_REG_INDEX(irq) ((rt_uint32_t)(irq) >> 5)
+#define NVIC_REG_MASK(irq) RT_BIT((rt_uint32_t)(irq) & 0x1f)
struct arm_nvic
{
struct rt_pic parent;
- volatile rt_uint8_t *base;
+ rt_ubase_t base;
rt_uint32_t irq_nr;
rt_uint8_t priority_bits;
};
rt_inline void nvic_sync(void)
{
- __asm volatile ("dsb 0xf\n\tisb 0xf" ::: "memory");
+ rt_hw_dsb();
+ rt_hw_isb();
}
static struct arm_nvic _nvic;
-static volatile rt_uint32_t *nvic_reg32(struct arm_nvic *nvic,
- rt_ubase_t offset, int hwirq)
+static rt_ubase_t nvic_reg(struct arm_nvic *nvic,
+ rt_ubase_t offset, int hwirq)
{
- return (volatile rt_uint32_t *)(nvic->base + offset) + NVIC_REG_INDEX(hwirq);
+ return nvic->base + offset + NVIC_REG_INDEX(hwirq) * sizeof(rt_uint32_t);
}
static void nvic_irq_mask(struct rt_pic_irq *pirq)
{
struct arm_nvic *nvic = pirq->pic->priv_data;
- *nvic_reg32(nvic, NVIC_ICER_OFFSET, pirq->hwirq) = NVIC_REG_MASK(pirq->hwirq);
+ HWREG32(nvic_reg(nvic, NVIC_ICER_OFFSET, pirq->hwirq)) =
+ NVIC_REG_MASK(pirq->hwirq);
nvic_sync();
}
@@ -61,7 +66,8 @@ static void nvic_irq_unmask(struct rt_pic_irq *pirq)
{
struct arm_nvic *nvic = pirq->pic->priv_data;
- *nvic_reg32(nvic, NVIC_ISER_OFFSET, pirq->hwirq) = NVIC_REG_MASK(pirq->hwirq);
+ HWREG32(nvic_reg(nvic, NVIC_ISER_OFFSET, pirq->hwirq)) =
+ NVIC_REG_MASK(pirq->hwirq);
nvic_sync();
}
@@ -75,18 +81,18 @@ static rt_err_t nvic_irq_set_priority(struct rt_pic_irq *pirq, rt_uint32_t prior
return -RT_EINVAL;
}
- *(volatile rt_uint8_t *)(nvic->base + NVIC_IPR_OFFSET + pirq->hwirq) =
- priority << (8 - nvic->priority_bits);
+ HWREG8(nvic->base + NVIC_IPR_OFFSET + pirq->hwirq) =
+ priority << (8 - nvic->priority_bits);
pirq->priority = priority;
return RT_EOK;
}
static rt_err_t nvic_irq_set_state(struct rt_pic *pic, int hwirq,
- int type, rt_bool_t state)
+ int type, rt_bool_t state)
{
struct arm_nvic *nvic = pic->priv_data;
- volatile rt_uint32_t *reg;
+ rt_ubase_t reg;
if (hwirq < 0 || hwirq >= nvic->irq_nr)
{
@@ -96,13 +102,13 @@ static rt_err_t nvic_irq_set_state(struct rt_pic *pic, int hwirq,
switch (type)
{
case RT_IRQ_STATE_PENDING:
- reg = nvic_reg32(nvic, state ? NVIC_ISPR_OFFSET : NVIC_ICPR_OFFSET, hwirq);
- *reg = NVIC_REG_MASK(hwirq);
+ reg = nvic_reg(nvic, state ? NVIC_ISPR_OFFSET : NVIC_ICPR_OFFSET, hwirq);
+ HWREG32(reg) = NVIC_REG_MASK(hwirq);
break;
case RT_IRQ_STATE_MASKED:
- reg = nvic_reg32(nvic, state ? NVIC_ICER_OFFSET : NVIC_ISER_OFFSET, hwirq);
- *reg = NVIC_REG_MASK(hwirq);
+ reg = nvic_reg(nvic, state ? NVIC_ICER_OFFSET : NVIC_ISER_OFFSET, hwirq);
+ HWREG32(reg) = NVIC_REG_MASK(hwirq);
break;
default:
@@ -115,7 +121,7 @@ static rt_err_t nvic_irq_set_state(struct rt_pic *pic, int hwirq,
}
static rt_err_t nvic_irq_get_state(struct rt_pic *pic, int hwirq,
- int type, rt_bool_t *out_state)
+ int type, rt_bool_t *out_state)
{
rt_ubase_t offset;
struct arm_nvic *nvic = pic->priv_data;
@@ -143,7 +149,8 @@ static rt_err_t nvic_irq_get_state(struct rt_pic *pic, int hwirq,
return -RT_ENOSYS;
}
- *out_state = !!(*nvic_reg32(nvic, offset, hwirq) & NVIC_REG_MASK(hwirq));
+ *out_state = !!(HWREG32(nvic_reg(nvic, offset, hwirq)) &
+ NVIC_REG_MASK(hwirq));
if (type == RT_IRQ_STATE_MASKED)
{
*out_state = !*out_state;
@@ -175,7 +182,7 @@ static int nvic_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t priority)
}
static rt_err_t nvic_irq_parse(struct rt_pic *pic,
- struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq)
+ struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq)
{
if (args->args_count != 2 || args->args[0] >= pic->irq_nr)
{
@@ -188,8 +195,7 @@ static rt_err_t nvic_irq_parse(struct rt_pic *pic,
return RT_EOK;
}
-static const struct rt_pic_ops nvic_ops =
-{
+static const struct rt_pic_ops nvic_ops = {
.name = "NVIC",
.irq_enable = nvic_irq_unmask,
.irq_disable = nvic_irq_mask,
@@ -202,32 +208,38 @@ static const struct rt_pic_ops nvic_ops =
.irq_parse = nvic_irq_parse,
};
-void rt_hw_nvic_dispatch(void)
+static rt_bool_t nvic_handler(void *data)
{
- rt_uint32_t exception;
-
- __asm volatile ("mrs %0, ipsr" : "=r" (exception));
+ int hwirq;
+ struct rt_pic_irq *pirq;
+ struct arm_nvic *nvic = data;
+ rt_uint32_t exception = HWREG32(NVIC_ICSR_ADDR) &
+ NVIC_ICSR_VECTACTIVE_MASK;
- if (exception >= 16)
+ if (exception < 16)
{
- int hwirq = exception - 16;
+ return RT_FALSE;
+ }
- if (hwirq < _nvic.irq_nr)
- {
- struct rt_pic_irq *pirq = rt_pic_find_irq(&_nvic.parent, hwirq);
+ hwirq = exception - 16;
+ if (hwirq >= nvic->irq_nr)
+ {
+ return RT_FALSE;
+ }
- if (pirq->irq >= 0)
- {
- rt_interrupt_enter();
- rt_pic_handle_isr(pirq);
- rt_interrupt_leave();
- }
- }
+ pirq = rt_pic_find_irq(&nvic->parent, hwirq);
+ if (pirq->irq < 0)
+ {
+ return RT_FALSE;
}
+
+ rt_pic_handle_isr(pirq);
+
+ return RT_TRUE;
}
static rt_err_t nvic_ofw_init(struct rt_ofw_node *np,
- const struct rt_ofw_node_id *id)
+ const struct rt_ofw_node_id *id)
{
rt_err_t err;
rt_uint32_t value;
@@ -251,7 +263,7 @@ static rt_err_t nvic_ofw_init(struct rt_ofw_node *np,
return -RT_EINVAL;
}
- hw_irq_nr = ((*(volatile rt_uint32_t *)NVIC_ICTR_ADDR & 0xf) + 1) * 32;
+ hw_irq_nr = ((HWREG32(NVIC_ICTR_ADDR) & 0xf) + 1) * 32;
if (!rt_ofw_prop_read_u32(np, "arm,num-irqs", &value))
{
if (!value || value > hw_irq_nr)
@@ -271,7 +283,7 @@ static rt_err_t nvic_ofw_init(struct rt_ofw_node *np,
_nvic.priority_bits = value;
}
- _nvic.base = (volatile rt_uint8_t *)(rt_ubase_t)reg;
+ _nvic.base = (rt_ubase_t)reg;
_nvic.irq_nr = hw_irq_nr;
_nvic.parent.priv_data = &_nvic;
_nvic.parent.ops = &nvic_ops;
@@ -282,14 +294,15 @@ static rt_err_t nvic_ofw_init(struct rt_ofw_node *np,
return err;
}
+ rt_pic_add_traps(nvic_handler, &_nvic);
+
rt_ofw_data(np) = &_nvic.parent;
rt_pic_user_extends(&_nvic.parent);
return RT_EOK;
}
-static const struct rt_ofw_node_id nvic_ofw_ids[] =
-{
+static const struct rt_ofw_node_id nvic_ofw_ids[] = {
{ .compatible = "arm,v7m-nvic" },
{ .compatible = "arm,v8m-nvic" },
{ /* sentinel */ }
diff --git a/libcpu/arm/cortex-m4/cpuport.h b/libcpu/arm/cortex-m4/cpuport.h
index 05bb12cf2f..9bf02e57af 100644
--- a/libcpu/arm/cortex-m4/cpuport.h
+++ b/libcpu/arm/cortex-m4/cpuport.h
@@ -10,6 +10,43 @@
#ifndef CPUPORT_H__
#define CPUPORT_H__
+#include <rtdef.h>
+
+#ifdef rt_hw_isb
+#undef rt_hw_isb
+#endif
+#ifdef rt_hw_dsb
+#undef rt_hw_dsb
+#endif
+
+rt_inline void rt_hw_isb(void)
+{
+#if defined(__CC_ARM)
+ __asm
+ {
+ ISB
+ }
+#elif defined(__clang__) || defined(__CLANG_ARM) || defined(__GNUC__)
+ __asm volatile("isb 0xf" ::: "memory");
+#elif defined(__IAR_SYSTEMS_ICC__)
+ __asm("ISB");
+#endif
+}
+
+rt_inline void rt_hw_dsb(void)
+{
+#if defined(__CC_ARM)
+ __asm
+ {
+ DSB
+ }
+#elif defined(__clang__) || defined(__CLANG_ARM) || defined(__GNUC__)
+ __asm volatile("dsb 0xf" ::: "memory");
+#elif defined(__IAR_SYSTEMS_ICC__)
+ __asm("DSB");
+#endif
+}
+
#ifdef RT_USING_SMP
typedef union {
unsigned long slock;
diff --git a/libcpu/arm/cortex-m7/cpuport.h b/libcpu/arm/cortex-m7/cpuport.h
index 05bb12cf2f..9bf02e57af 100644
--- a/libcpu/arm/cortex-m7/cpuport.h
+++ b/libcpu/arm/cortex-m7/cpuport.h
@@ -10,6 +10,43 @@
#ifndef CPUPORT_H__
#define CPUPORT_H__
+#include <rtdef.h>
+
+#ifdef rt_hw_isb
+#undef rt_hw_isb
+#endif
+#ifdef rt_hw_dsb
+#undef rt_hw_dsb
+#endif
+
+rt_inline void rt_hw_isb(void)
+{
+#if defined(__CC_ARM)
+ __asm
+ {
+ ISB
+ }
+#elif defined(__clang__) || defined(__CLANG_ARM) || defined(__GNUC__)
+ __asm volatile("isb 0xf" ::: "memory");
+#elif defined(__IAR_SYSTEMS_ICC__)
+ __asm("ISB");
+#endif
+}
+
+rt_inline void rt_hw_dsb(void)
+{
+#if defined(__CC_ARM)
+ __asm
+ {
+ DSB
+ }
+#elif defined(__clang__) || defined(__CLANG_ARM) || defined(__GNUC__)
+ __asm volatile("dsb 0xf" ::: "memory");
+#elif defined(__IAR_SYSTEMS_ICC__)
+ __asm("DSB");
+#endif
+}
+
#ifdef RT_USING_SMP
typedef union {
unsigned long slock;
diff --git a/libcpu/arm/cortex-m85/cpuport.h b/libcpu/arm/cortex-m85/cpuport.h
index 05bb12cf2f..9bf02e57af 100644
--- a/libcpu/arm/cortex-m85/cpuport.h
+++ b/libcpu/arm/cortex-m85/cpuport.h
@@ -10,6 +10,43 @@
#ifndef CPUPORT_H__
#define CPUPORT_H__
+#include <rtdef.h>
+
+#ifdef rt_hw_isb
+#undef rt_hw_isb
+#endif
+#ifdef rt_hw_dsb
+#undef rt_hw_dsb
+#endif
+
+rt_inline void rt_hw_isb(void)
+{
+#if defined(__CC_ARM)
+ __asm
+ {
+ ISB
+ }
+#elif defined(__clang__) || defined(__CLANG_ARM) || defined(__GNUC__)
+ __asm volatile("isb 0xf" ::: "memory");
+#elif defined(__IAR_SYSTEMS_ICC__)
+ __asm("ISB");
+#endif
+}
+
+rt_inline void rt_hw_dsb(void)
+{
+#if defined(__CC_ARM)
+ __asm
+ {
+ DSB
+ }
+#elif defined(__clang__) || defined(__CLANG_ARM) || defined(__GNUC__)
+ __asm volatile("dsb 0xf" ::: "memory");
+#elif defined(__IAR_SYSTEMS_ICC__)
+ __asm("DSB");
+#endif
+}
+
#ifdef RT_USING_SMP
typedef union {
unsigned long slock;