学习目标:
RT-THHRAD
学习内容:
在rt-thread的系统中,研究空闲线程与阻塞延时的实现
学习产出:
提示:这里统计学习计划的总量
想要实现空闲线程,并进行阻塞延时,则是需要进行滴答定时器的设计,可以通过滴答定时器进行的延时计算。
/*Systick的中断频率设置*/
SysTick_Config(SystemCoreClock /RT_TICK_PER_SECOND);
于是在SYSTick_Handler(void)中执行:
void SysTick_Handler(void)
{
rt_interrupt_entry ();
rt_tick_increase();
rt_interrupt_leave ();
}
其中的rt_tick_increase()为:
通过进入就绪线程优先级链表数组,遍历链表数组,将里面的remaining_tick每进入一次滴答定时器中断就进行减一操作
void rt_tick_increase(void)
{
rt_ubase_t i;
struct rt_thread *thread;
rt_tick ++;
/*扫描remaining——tick,不为0就减一*/
for(i=0;i<RT_THREAD_PRIORITY_MAX;i++)
{
thread=rt_list_entry (rt_thread_priority_table [i].next ,
struct rt_thread ,
tlist);
if(thread->remaining_tick >0)
{
thread->remaining_tick --;
}
}
rt_schedule (); //进行任务调度工作
}
扩展 rt_schedule ():
*如果当前的线程是空闲线程
则尝试执行线程1或者线程2是否延时时间结束,否则继续执行空闲线程*/
if(rt_current_thread == &idle)
{
if(rt_flag1_thread .remaining_tick == 0)
{
from_thread = rt_current_thread ;
to_thread = &rt_flag1_thread ;
rt_current_thread = to_thread ;
}
else if(rt_flag2_thread .remaining_tick == 0)
{
from_thread = rt_current_thread ;
to_thread = &rt_flag2_thread ;
rt_current_thread = to_thread ;
}
else
{
return; /*线程阻塞未到期,返回空闲线程*/
}
}
else
{/*如果当前线程1或者线程2,检查另外的线程是否处于延时状态,如果不是就切换到该线程。
否则判断当前线程是否进入延时,如果是就切换到空闲线程,否则继续执行*/
if(rt_current_thread == &rt_flag1_thread )
{
if(rt_flag2_thread .remaining_tick ==0)
{
from_thread = rt_current_thread ;
to_thread = &rt_flag2_thread ;
rt_current_thread = to_thread ;
}
else if(rt_current_thread ->remaining_tick != 0)
{
from_thread = rt_current_thread ;
to_thread = &idle;
rt_current_thread = to_thread ;
}
else
{
return ; /*线程都在延时,不切换*/
}
}
else if (rt_current_thread == &rt_flag2_thread )
{
if(rt_flag1_thread .remaining_tick ==0)
{
from_thread = rt_current_thread ;
to_thread = &rt_flag1_thread ;
rt_current_thread = to_thread ;
}
else if(rt_current_thread ->remaining_tick != 0)
{
from_thread = rt_current_thread ;
to_thread = &idle;
rt_current_thread = to_thread ;
}
else
{
return ; /*线程都在延时,不切换*/
}
}
}
#endif
/*产生上下文切换*/
rt_hw_context_switch ((rt_uint32_t )&from_thread ->sp ,(rt_uint32_t)&to_thread ->sp ); //进入汇编进行 任务栈调度
}
/*初始化系统调度器*/
/*
****************************************************************************
初始化rt_thread_priority_table形成自闭和指针
初始化rt_current_thread为空
初始化rt_thread_defunct为自闭和指针
******************************************************************************
*/
void rt_system_scheduler_init(void)
{
register rt_base_t offset;
/*线程就绪列表初始化*/
for (offset=0; offset<RT_THREAD_PRIORITY_MAX;offset ++)
{
rt_list_init(&rt_thread_priority_table[offset]);
}
/*初始化当前线程控制块指针*/
rt_current_thread = RT_NULL;
/*初始化线程休眠列表,当线程创建好没有启动之前会被放入到这个列表*/
rt_list_init(&rt_thread_defunct);
}
初始化空闲线程,将空闲线程降到最低的优先级。
void rt_thread_idle_init(void)
{
/*初始化线程*/
rt_thread_init(&idle,
"idle",
rt_thread_idle_entry,
RT_NULL,
&rt_thread_stack[0],
sizeof(rt_thread_stack) );
/*将线程插入到就绪列表*/
rt_list_insert_before(&(rt_thread_priority_table[RT_THREAD_PRIORITY_MAX - 1]),&(idle.tlist));
}
分析线程初始化的过程:
rt_err_t rt_thread_init(struct rt_thread *thread,const char *name,void (*entry)(void *parameter), void *parameter, void *stack_start, rt_uint32_t stack_size)
{ /* 线程结构体开头部分的成员就是rt_object_t类型 */
rt_object_init((rt_object_t)thread, RT_Object_Class_Thread, name);
rt_list_init(&(thread->tlist));
thread->entry = (void*)entry;
thread->parameter = parameter;
thread->stack_addr = stack_start;
thread->stack_size = stack_size;
/*初始化线程栈,并返回线程栈指针*/
thread->sp = (void*)rt_hw_stack_init(thread->entry ,
thread->parameter,
(void*)((char *)thread->stack_addr+thread->stack_size-4));
return RT_EOK;
}
/**
*该函数将初始化对象并将对象添加到对象容器中
*
*/
void rt_object_init(struct rt_object *object,
enum rt_object_class_type type,
const char *name)
{
register rt_base_t temp;
struct rt_object_information *information;
/*获取对象信息,即从容器里拿到对应对象列表头指针*/
information = rt_object_get_information (type);
/*设置对象的类型为静态*/
object ->type =type | RT_Object_Class_Static ;
/*拷贝名字*/
rt_strncpy(object->name,name,RT_NAME_MAX );
/*关中断*/
temp=rt_hw_interrupt_disable ();
/*将对象插入到容器的对应列表中,不同的类型的对象所在列表不一样*/
rt_list_insert_after(&(information ->object_list ),&(object ->list ));
/*开中断*/
rt_hw_interrupt_enable (temp);
}
上述操作是将线程挂载到容器列表中