-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Open
Description
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
Ryan-CW-Code and Rbb666
Metadata
Metadata
Assignees
Labels
No labels