RT-Thread Version
5.1.0~master
Hardware Type/Architectures
ARM M4/STM32
Develop Toolchain
GCC
Describe the bug
复现方式
-
实现一个延时函数,使用 nop 指令进行延时。用于插入rt_schedule函数的curr_thread获取到禁用中断之间插入.
- 更好的将中断触发插入到
rt_schedule函数的curr_thread获取到禁用中断之间.
/**
* @brief 使用 nop 指令进行延时
* @param nop_counts: 需要执行的 nop 指令数量
* @note 这是一个忙等待延时,会独占 CPU。
* 延时时间取决于 CPU 主频和编译器的优化行为。
* 主要用于需要精确指令周期的短延时场景。
*/
void delay_nops(volatile uint32_t nop_counts)
{
while(nop_counts--)
{
__asm__ volatile ("nop");
}
}
-
rt_schedule函数中插入delay_nops,模拟将中断触发插入到rt_schedule函数的curr_thread获取到禁用中断之间.
volatile uint32_t ti = 1;
/**
* @brief Perform thread scheduling once. Select the highest priority thread and switch to it.
*
* @details This function:
* - Disables interrupts to prevent preemption during scheduling
* - Checks if scheduler is enabled (lock_nest == 0)
* - Gets the highest priority ready thread
* - Determines if current thread should continue running or be preempted
* - Performs context switch if needed:
* * From current thread to new thread (normal case)
* * Handles special cases like interrupt context switches
* - Manages thread states (READY/RUNNING) and priority queues
* - Handles thread yield flags and signal processing
*/
void rt_schedule(void)
{
rt_base_t level;
struct rt_thread *to_thread;
struct rt_thread *from_thread;
/* using local variable to avoid unecessary function call */
struct rt_thread *curr_thread = rt_thread_self();
/* 修改开始部分 */
extern void delay_nops(volatile uint32_t nop_counts);
delay_nops(ti);
//使用如下判断来识别是否已经异常
if(curr_thread != rt_thread_self())
{
while (1);
}
/* 修改结束部分 */
/* disable interrupt */
level = rt_hw_interrupt_disable();
//后续相同.....
}
-
开启系统软件定时器线程与CAN驱动
- (can实现与文档例程一致既可)
- 主要是需要线程阻塞等待唤醒,中断里执行唤醒操作,调用rt_schedule.
- 即线程中使用(rt_sem_take(&rx_sem, RT_WAITING_FOREVER);)
- 中断里使用 rt_sem_release(&rx_sem);
- 并且需要开启两个来模拟
-
接入仿真器,执行debug,模拟中断触发在rt_schedule函数的curr_thread获取到禁用中断之间.
- 执行完rtt初始化进入main函数后
- 添加触发点
rt_sem_release(&_soft_timer_sem);
3. 等待debeug暂停,暂停后,设置全局变量`ti`为10000(更好触发中断在`rt_schedule`函数的`curr_thread`获取到禁用中断之间).
4. 在`delay_nops(ti);`加入断点
5. 运行程序到`delay_nops(ti);`断点处,debug暂停
6. 使用can分析仪触发can接收中断
7. 运行程序,已经进入while(1)
- rtconfig.h配置如下
#define RT_NAME_MAX 18
#define RT_CPUS_NR 1
#define RT_ALIGN_SIZE 8
#define RT_THREAD_PRIORITY_32
#define RT_THREAD_PRIORITY_MAX 32
#define RT_TICK_PER_SECOND 1000
#define RT_USING_OVERFLOW_CHECK
#define RT_USING_HOOK
#define RT_HOOK_USING_FUNC_PTR
#define RT_USING_IDLE_HOOK
#define RT_IDLE_HOOK_LIST_SIZE 4
#define IDLE_THREAD_STACK_SIZE 256
#define RT_USING_TIMER_SOFT
#define RT_TIMER_THREAD_PRIO 4
#define RT_TIMER_THREAD_STACK_SIZE 512
#define RT_USING_CPU_USAGE_TRACER
#define RT_USING_CAN
#define RT_CAN_USING_HDR
#define RT_CANMSG_BOX_SZ 16
#define RT_CANSND_BOX_NUM 3
#define RT_CANSND_MSG_TIMEOUT 100
使用环境
- rtt studio
- gcc编译器
- master主线代码
- stm32f407vg, 主频168mhz
总结
struct rt_thread *curr_thread = rt_thread_self();这个需要在中断屏蔽的范围内获取,否则会出现异常
- 异常情况与中断插入有关.
- 需要一次执行调度的时候,插入了中断在在
rt_schedule函数的curr_thread获取到禁用中断之间.并且这次调度要产生执行线程切换的逻辑,将当前current线程进行修改
- 当中断执行完毕后再来执行原先的调度逻辑就会产生问题.
- 问题只是获取的current线程与死机不符.会不会实际造成影响也是概率性问题.
- 中断要恰好在在
rt_schedule函数的curr_thread获取到禁用中断之间触发,也是个概率性问题.只有高频率的触发中断长时间挂测才能不在debug中产生
Other additional context
No response
RT-Thread Version
5.1.0~master
Hardware Type/Architectures
ARM M4/STM32
Develop Toolchain
GCC
Describe the bug
复现方式
实现一个延时函数,使用 nop 指令进行延时。用于插入
rt_schedule函数的curr_thread获取到禁用中断之间插入.rt_schedule函数的curr_thread获取到禁用中断之间.rt_schedule函数中插入delay_nops,模拟将中断触发插入到
rt_schedule函数的curr_thread获取到禁用中断之间.开启系统软件定时器线程与CAN驱动
接入仿真器,执行debug,模拟中断触发在
rt_schedule函数的curr_thread获取到禁用中断之间.rt_sem_release(&_soft_timer_sem);使用环境
总结
struct rt_thread *curr_thread = rt_thread_self();这个需要在中断屏蔽的范围内获取,否则会出现异常rt_schedule函数的curr_thread获取到禁用中断之间.并且这次调度要产生执行线程切换的逻辑,将当前current线程进行修改rt_schedule函数的curr_thread获取到禁用中断之间触发,也是个概率性问题.只有高频率的触发中断长时间挂测才能不在debug中产生Other additional context
No response