Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions libcpu/arm/cortex-m4/cpuport.c
Original file line number Diff line number Diff line change
Expand Up @@ -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__ )) \
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions src/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 4 additions & 3 deletions src/scheduler_up.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -285,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();
Expand Down Expand Up @@ -344,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_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_nest == 0)
if (interrupt_nest == 0)
{
extern void rt_thread_handle_sig(rt_bool_t clean_state);

Expand Down
Loading