2021年09月03日:
1、线程调度源码
void rt_schedule(void)
{
rt_base_t level;
struct rt_thread *to_thread;
struct rt_thread *from_thread;
/* disable interrupt */
level = rt_hw_interrupt_disable();
/* check the scheduler is enabled or not */
if (rt_scheduler_lock_nest == 0)//当前不处于线程嵌套中-没有上锁
{
rt_ubase_t highest_ready_priority;
if (rt_thread_ready_priority_group != 0)//就绪表组,存在已就绪的线程
{
/* need_insert_from_thread: need to insert from_thread to ready queue */
int need_insert_from_thread = 0;
to_thread = _get_highest_priority_thread(&highest_ready_priority);//获取就绪表中优先级最高
if ((rt_current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_RUNNING)//当前线程处于运行态
{
if (rt_current_thread->current_priority < highest_ready_priority)
{
to_thread = rt_current_thread;
}
else if (rt_current_thread->current_priority == highest_ready_priority && (rt_current_thread->stat & RT_THREAD_STAT_YIELD_MASK) == 0)//优先级一致的,时间片还没到时,接着运行
{
to_thread = rt_current_thread;
}
else
{
rt_current_thread->stat &= ~RT_THREAD_STAT_YIELD_MASK;//将优先级的时间片标志清零
need_insert_from_thread = 1;
}
}
if (to_thread != rt_current_thread)
{
/* if the destination thread is not the same as current thread */
rt_current_priority = (rt_uint8_t)highest_ready_priority;
from_thread = rt_current_thread;
rt_current_thread = to_thread;
RT_OBJECT_HOOK_CALL(rt_scheduler_hook, (from_thread, to_thread));
if (need_insert_from_thread)
{
rt_schedule_insert_thread(from_thread);//往调度器中添加线程
}
rt_schedule_remove_thread(to_thread);//将线程中调度器中移除
to_thread->stat = RT_THREAD_RUNNING | (to_thread->stat & ~RT_THREAD_STAT_MASK);
/* switch to new thread */
RT_DEBUG_LOG(RT_DEBUG_SCHEDULER,
("[%d]switch to priority#%d "
"thread:%.*s(sp:0x%08x), "
"from thread:%.*s(sp: 0x%08x)\n",
rt_interrupt_nest, highest_ready_priority,
RT_NAME_MAX, to_thread->name, to_thread->sp,
RT_NAME_MAX, from_thread->name, from_thread->sp));
#ifdef RT_USING_OVERFLOW_CHECK
_rt_scheduler_stack_check(to_thread);//线程栈溢出检查
#endif
if (rt_interrupt_nest == 0)//如果当前没有处于中断嵌套中
{
extern void rt_thread_handle_sig(rt_bool_t clean_state);
rt_hw_context_switch((rt_ubase_t)&from_thread->sp,
(rt_ubase_t)&to_thread->sp);//线程切换
/* enable interrupt */
rt_hw_interrupt_enable(level);
#ifdef RT_USING_SIGNALS
/* check stat of thread for signal */
level = rt_hw_interrupt_disable();
if (rt_current_thread->stat & RT_THREAD_STAT_SIGNAL_PENDING)
{
extern void rt_thread_handle_sig(rt_bool_t clean_state);
rt_current_thread->stat &= ~RT_THREAD_STAT_SIGNAL_PENDING;
rt_hw_interrupt_enable(level);
/* check signal status */
rt_thread_handle_sig(RT_TRUE);
}
else
{
rt_hw_interrupt_enable(level);
}
#endif
goto __exit;
}
else
{
RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("switch in interrupt\n"));
rt_hw_context_switch_interrupt((rt_ubase_t)&from_thread->sp,
(rt_ubase_t)&to_thread->sp);//中断中线程切换
}
}
else
{
rt_schedule_remove_thread(rt_current_thread);
rt_current_thread->stat = RT_THREAD_RUNNING | (rt_current_thread->stat & ~RT_THREAD_STAT_MASK);
}
}
}
/* enable interrupt */
rt_hw_interrupt_enable(level);
__exit:
return;
}
2、定时器中断
每经过一个时钟节拍时,都会检查当前线程的时间片是否用完,以及是否有定时器超时
void rt_tick_increase(void)
{
struct rt_thread *thread;
/* increase the global tick */
#ifdef RT_USING_SMP
rt_cpu_self()->tick ++;
#else
++ rt_tick;
#endif
/* check time slice */
thread = rt_thread_self();
-- thread->remaining_tick;
if (thread->remaining_tick == 0)//当前线程时间片是否用完
{
/* change to initialized tick */
thread->remaining_tick = thread->init_tick;
thread->stat |= RT_THREAD_STAT_YIELD;
/* yield */
rt_thread_yield();
}
/* check timer */
rt_timer_check();//查看定时器列表中,线程时间片是否存在超过
}
查看定时器列表中,线程时间片是否存在超过
void rt_timer_check(void)
{
struct rt_timer *t;
rt_tick_t current_tick;
register rt_base_t level;
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check enter\n"));
current_tick = rt_tick_get();
/* disable interrupt */
level = rt_hw_interrupt_disable();
/*当定时器链表非空,这里用的是while,也就是说如果有多个到期的定时器,都会在这个循环中处理掉*/
while (!rt_list_isempty(&rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))//定时器列表是否为空
{
t = rt_list_entry(rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);//获取下个定时器时间
/*
* It supposes that the new tick shall less than the half duration of
* tick max.
判断是否到期,current_tick是一步步加上来的,一定小于等于timeout_tick,所以做差要么小于0
要么等于0,RT_TICK_MAX是0xffff,除以2大概是0x7fff,当差小于0时最高位是1,
要比RT_TICK_MAX / 2大,等于0时一定是比他小
*/
if ((current_tick - t->timeout_tick) < RT_TICK_MAX / 2)
{
RT_OBJECT_HOOK_CALL(rt_timer_enter_hook, (t));
/* remove timer from timer list firstly */
_rt_timer_remove(t);
/* call timeout function */
t->timeout_func(t->parameter);
/* re-get tick */
current_tick = rt_tick_get();
RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));
/*如果是周期型定时器,则再次开启*/
if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
{
/* start it */
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
rt_timer_start(t);
}
else
{
/* stop timer如果是一次性的就扔了 */
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
}
}
else
break;
}
/* enable interrupt */
rt_hw_interrupt_enable(level);
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check leave\n"));
}
定时器超时接口
void rt_thread_timeout(void *parameter)
{
struct rt_thread *thread;
thread = (struct rt_thread *)parameter;
/* thread check */
RT_ASSERT(thread != RT_NULL);
//RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND);
RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
/* set error number */
thread->error = -RT_ETIMEOUT;
if(RT_THREAD_SUSPEND == (thread->stat & RT_THREAD_STAT_MASK))
{
/* remove from suspend list */
rt_list_remove(&(thread->tlist));
/* insert to schedule ready list */
rt_schedule_insert_thread(thread);
}
/* do schedule */
rt_schedule();
}
3、rtt启动接口
int $Sub$$main(void)
{
rtthread_startup();
return 0;
}
int rtthread_startup(void)
{
rt_hw_interrupt_disable();//yxj-清除所有硬件中断
/* board level initialization
* NOTE: please initialize heap inside board initialization.
*/
rt_hw_board_init();//执行MCU的外设等初始化
/* show RT-Thread version */
rt_show_version();
/* timer system initialization 系统时钟初始化*/
rt_system_timer_init();
/* scheduler system initialization 调度器初始化*/
rt_system_scheduler_init();
#ifdef RT_USING_SIGNALS
/* signal system initialization */
rt_system_signal_init();
#endif
/* create init_thread 原始线程-main线程*/
rt_application_init();
/* timer thread initialization 定时器线程*/
rt_system_timer_thread_init();
/* idle thread initialization 空闲线程*/
rt_thread_idle_init();
#ifdef RT_USING_SMP
rt_hw_spin_lock(&_cpus_lock);
#endif /*RT_USING_SMP*/
/* start scheduler */
rt_system_scheduler_start();//启动调度器
/* never reach here */
return 0;
}
控制台设备的设置,printf输出的接口
设备运行步骤:
1)先注册设备
rt_err_t rt_device_register(rt_device_t dev,
const char *name,
rt_uint16_t flags);
2)打开设备
rt_device_t rt_device_find(const char *name)
3)设置设备的权限
rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflag)
4)rtt默认的打印接口
void rt_hw_console_output(const char *str)