summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwdfk-prog <[email protected]>2026-04-08 13:45:46 +0800
committerRbb666 <[email protected]>2026-04-08 18:58:33 +0800
commite74547bbb36c38bbebf8baca4d728b3db14885df (patch)
tree372ac027d38f65c39d868e3055fd7c5c0c1ec3a9
parent2548bdb9c2d617523ce5c0b7e489ed815630f0c7 (diff)
feat(core): Add Cortex-M4 interrupt context helpers
-rw-r--r--libcpu/arm/cortex-m4/cpuport.c105
-rw-r--r--src/scheduler_up.c6
2 files changed, 109 insertions, 2 deletions
diff --git a/libcpu/arm/cortex-m4/cpuport.c b/libcpu/arm/cortex-m4/cpuport.c
index 9504008e36..69bcc4c6d9 100644
--- a/libcpu/arm/cortex-m4/cpuport.c
+++ b/libcpu/arm/cortex-m4/cpuport.c
@@ -20,6 +20,10 @@
#include <rtthread.h>
+#define DBG_TAG "cortex.m4"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
#if /* ARMCC */ ( (defined ( __CC_ARM ) && defined ( __TARGET_FPU_VFP )) \
/* Clang */ || (defined ( __clang__ ) && defined ( __VFP_FP__ ) && !defined(__SOFTFP__)) \
/* IAR */ || (defined ( __ICCARM__ ) && defined ( __ARMVFP__ )) \
@@ -436,6 +440,107 @@ void rt_hw_cpu_reset(void)
SCB_AIRCR = SCB_RESET_VALUE;
}
+/**
+ \brief Get IPSR Register
+ \details Returns the content of the IPSR Register.
+ \return IPSR Register value
+ */
+rt_inline rt_uint32_t rt_hw_get_ipsr(void)
+{
+#if defined(__CC_ARM)
+ register uint32_t __regIPSR __asm("ipsr");
+ return(__regIPSR);
+#elif defined(__clang__)
+ uint32_t result;
+ __asm volatile ("MRS %0, ipsr" : "=r" (result) );
+ return(result);
+#elif defined(__IAR_SYSTEMS_ICC__)
+ return __iar_builtin_rsr("IPSR");
+#elif defined ( __GNUC__ )
+ uint32_t result;
+ __asm volatile ("MRS %0, ipsr" : "=r" (result) );
+ return(result);
+#endif
+}
+
+/**
+ * @brief This function will be invoked by BSP, when enter interrupt service routine
+ *
+ * @note Please don't invoke this routine in application
+ *
+ * @see rt_interrupt_leave
+ */
+void rt_interrupt_enter(void)
+{
+ extern void (*rt_interrupt_enter_hook)(void);
+ RT_OBJECT_HOOK_CALL(rt_interrupt_enter_hook,());
+ LOG_D("irq has come...");
+}
+
+/**
+ * @brief This function will be invoked by BSP, when leave interrupt service routine
+ *
+ * @note Please don't invoke this routine in application
+ *
+ * @see rt_interrupt_enter
+ */
+void rt_interrupt_leave(void)
+{
+ extern void (*rt_interrupt_leave_hook)(void);
+ LOG_D("irq is going to leave");
+ RT_OBJECT_HOOK_CALL(rt_interrupt_leave_hook,());
+}
+
+/**
+ * @brief This function will return the nest of interrupt.
+ *
+ * User application can invoke this function to get whether current
+ * context is interrupt context.
+ *
+ * @return the number of nested interrupts.
+ */
+rt_uint8_t rt_interrupt_get_nest(void)
+{
+ return (rt_hw_get_ipsr() != 0);
+}
+
+/**
+ \brief Get PRIMASK Register
+ \details Returns the content of the PRIMASK Register.
+ \return PRIMASK Register value
+ */
+rt_inline rt_uint32_t rt_hw_get_primask_value(void)
+{
+#if defined(__CC_ARM)
+ register uint32_t __regPRIMASK __asm("primask");
+ return (__regPRIMASK);
+#elif defined(__clang__)
+ uint32_t result;
+ __asm volatile ("MRS %0, primask" : "=r" (result));
+ return result;
+#elif defined(__IAR_SYSTEMS_ICC__)
+ return __iar_builtin_rsr("PRIMASK");
+#elif defined(__GNUC__)
+ uint32_t result;
+ __asm volatile ("MRS %0, primask" : "=r" (result));
+ return result;
+#endif
+}
+
+/**
+ * @brief Check whether maskable interrupts are currently disabled.
+ *
+ * @details
+ * For Cortex-M4, interrupts are considered disabled when either:
+ * - PRIMASK masks all configurable interrupts.
+ *
+ * @return RT_TRUE if interrupts are masked; otherwise RT_FALSE.
+ */
+rt_bool_t rt_hw_interrupt_is_disabled(void)
+{
+ return ((rt_hw_get_primask_value() & 0x1UL) != 0UL);
+}
+
#ifdef RT_USING_CPU_FFS
/**
* This function finds the first bit set (beginning with the least significant bit)
diff --git a/src/scheduler_up.c b/src/scheduler_up.c
index e2d90d14c5..8560166fd1 100644
--- a/src/scheduler_up.c
+++ b/src/scheduler_up.c
@@ -284,6 +284,7 @@ void rt_schedule(void)
struct rt_thread *to_thread;
struct rt_thread *from_thread;
struct rt_thread *curr_thread;
+ rt_base_t interrupt_nest;
/* disable interrupt */
level = rt_hw_interrupt_disable();
@@ -343,16 +344,17 @@ void rt_schedule(void)
RT_SCHED_CTX(to_thread).stat = RT_THREAD_RUNNING | (RT_SCHED_CTX(to_thread).stat & ~RT_THREAD_STAT_MASK);
/* switch to new thread */
+ interrupt_nest = rt_interrupt_get_nest();
LOG_D("[%d]switch to priority#%d "
"thread:%.*s(sp:0x%08x), "
"from thread:%.*s(sp: 0x%08x)",
- rt_interrupt_get_nest(), highest_ready_priority,
+ interrupt_nest, highest_ready_priority,
RT_NAME_MAX, to_thread->parent.name, to_thread->sp,
RT_NAME_MAX, from_thread->parent.name, from_thread->sp);
RT_SCHEDULER_STACK_CHECK(to_thread);
- if (rt_interrupt_get_nest() == 0)
+ if (interrupt_nest == 0)
{
extern void rt_thread_handle_sig(rt_bool_t clean_state);