From 4a74224a6ccb81bd2816964c12144e8d292fd82e Mon Sep 17 00:00:00 2001 From: wdfk-prog <1425075683@qq.com> Date: Mon, 6 Apr 2026 09:09:45 +0800 Subject: [PATCH 1/2] fix(src): Use interrupt nest accessor and export IRQ hook pointers --- src/irq.c | 4 ++-- src/scheduler_up.c | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/irq.c b/src/irq.c index 121f18260b7..9670a809e37 100644 --- a/src/irq.c +++ b/src/irq.c @@ -26,8 +26,8 @@ #if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR) -static void (*rt_interrupt_enter_hook)(void); -static void (*rt_interrupt_leave_hook)(void); +void (*rt_interrupt_enter_hook)(void); +void (*rt_interrupt_leave_hook)(void); /** * @ingroup group_hook diff --git a/src/scheduler_up.c b/src/scheduler_up.c index 4db27104cdb..e2d90d14c56 100644 --- a/src/scheduler_up.c +++ b/src/scheduler_up.c @@ -50,7 +50,6 @@ rt_uint32_t rt_thread_ready_priority_group; rt_uint8_t rt_thread_ready_table[32]; #endif /* RT_THREAD_PRIORITY_MAX > 32 */ -extern volatile rt_atomic_t rt_interrupt_nest; static rt_atomic_t rt_scheduler_lock_nest; rt_uint8_t rt_current_priority; @@ -347,13 +346,13 @@ void rt_schedule(void) LOG_D("[%d]switch to priority#%d " "thread:%.*s(sp:0x%08x), " "from thread:%.*s(sp: 0x%08x)", - rt_interrupt_nest, highest_ready_priority, + rt_interrupt_get_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_nest == 0) + if (rt_interrupt_get_nest() == 0) { extern void rt_thread_handle_sig(rt_bool_t clean_state); From de3622f5b3346772533e1a5058632ef820e931e2 Mon Sep 17 00:00:00 2001 From: wdfk-prog <1425075683@qq.com> Date: Wed, 8 Apr 2026 13:45:46 +0800 Subject: [PATCH 2/2] feat(core): Add Cortex-M4 interrupt context helpers --- libcpu/arm/cortex-m4/cpuport.c | 105 +++++++++++++++++++++++++++++++++ src/scheduler_up.c | 6 +- 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/libcpu/arm/cortex-m4/cpuport.c b/libcpu/arm/cortex-m4/cpuport.c index 9504008e36d..69bcc4c6d9e 100644 --- a/libcpu/arm/cortex-m4/cpuport.c +++ b/libcpu/arm/cortex-m4/cpuport.c @@ -20,6 +20,10 @@ #include +#define DBG_TAG "cortex.m4" +#define DBG_LVL DBG_INFO +#include + #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 e2d90d14c56..8560166fd17 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);