ソースを参照

feat(core): Add Cortex-M4 interrupt context helpers

wdfk-prog 4 日 前
コミット
e74547bbb3
2 ファイル変更109 行追加2 行削除
  1. 105 0
      libcpu/arm/cortex-m4/cpuport.c
  2. 4 2
      src/scheduler_up.c

+ 105 - 0
libcpu/arm/cortex-m4/cpuport.c

@@ -20,6 +20,10 @@
 
 
 #include <rtthread.h>
 #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 ))    \
 #if               /* ARMCC */ (  (defined ( __CC_ARM ) && defined ( __TARGET_FPU_VFP ))    \
                   /* Clang */ || (defined ( __clang__ ) && defined ( __VFP_FP__ ) && !defined(__SOFTFP__)) \
                   /* Clang */ || (defined ( __clang__ ) && defined ( __VFP_FP__ ) && !defined(__SOFTFP__)) \
                   /* IAR */   || (defined ( __ICCARM__ ) && defined ( __ARMVFP__ ))        \
                   /* IAR */   || (defined ( __ICCARM__ ) && defined ( __ARMVFP__ ))        \
@@ -436,6 +440,107 @@ void rt_hw_cpu_reset(void)
     SCB_AIRCR = SCB_RESET_VALUE;
     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
 #ifdef RT_USING_CPU_FFS
 /**
 /**
  * This function finds the first bit set (beginning with the least significant bit)
  * This function finds the first bit set (beginning with the least significant bit)

+ 4 - 2
src/scheduler_up.c

@@ -284,6 +284,7 @@ void rt_schedule(void)
     struct rt_thread *to_thread;
     struct rt_thread *to_thread;
     struct rt_thread *from_thread;
     struct rt_thread *from_thread;
     struct rt_thread *curr_thread;
     struct rt_thread *curr_thread;
+    rt_base_t interrupt_nest;
 
 
     /* disable interrupt */
     /* disable interrupt */
     level = rt_hw_interrupt_disable();
     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);
                 RT_SCHED_CTX(to_thread).stat = RT_THREAD_RUNNING | (RT_SCHED_CTX(to_thread).stat & ~RT_THREAD_STAT_MASK);
 
 
                 /* switch to new thread */
                 /* switch to new thread */
+                interrupt_nest = rt_interrupt_get_nest();
                 LOG_D("[%d]switch to priority#%d "
                 LOG_D("[%d]switch to priority#%d "
                          "thread:%.*s(sp:0x%08x), "
                          "thread:%.*s(sp:0x%08x), "
                          "from 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, to_thread->parent.name, to_thread->sp,
                          RT_NAME_MAX, from_thread->parent.name, from_thread->sp);
                          RT_NAME_MAX, from_thread->parent.name, from_thread->sp);
 
 
                 RT_SCHEDULER_STACK_CHECK(to_thread);
                 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);
                     extern void rt_thread_handle_sig(rt_bool_t clean_state);