1 思路
之前线程需要延时的时候,就初始化remaining_tick,只是将线程就绪优先级组中对应的位清0,并不会将线程从就绪列表中删除。每次systick中断,就remaining_tick递减,如果为0表示延时时间到,将该线程就绪(就绪优先级组中对应的位置1),然后等待系统写一次调度。缺点是所有扫描线程一遍,费时,优点是容易理解。
在新的方案里,每个线程都内置一个定时器,当线程需要延时,就将线程挂起,然后内置的定时器就会启动,并将定时器插入到一个全局的系统定时器列表上rt_timer_list.节点按照延时时间大小做升序排列。当sysTICK来,系统扫描定时器列表的第一个定时器,如果定时器到期,就让该线程就绪,如果时间不到,就退出扫描。
2.实现定时器
2.1系统定时器列表
timer.c中
static rt_list_t rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
rtdef.h中
#ifndef RT_TIMER_SKIP_LIST_LEVEL
#define RT_TIMER_SKIP_LIST_LEVEL 1
#endif
2.2 定时器列表初始化
timer.c中
void rt_system_timer_init(void)
{
int i;
for(i = 0; i < sizeof(rt_timer_list)/sizeof(rt_timer_list[0]);i++)
{
rt_list_init(rt_timer_list+i);
}
}
2.3 定义定时器结构体
rtdef.h中
struct rt_timer
{
struct rt_object parent; /**< inherit from rt_object */
rt_list_t row[RT_TIMER_SKIP_LIST_LEVEL];
void (*timeout_func)(void *parameter); /**< timeout function */
void *parameter; /**< timeout function's parameter */
rt_tick_t init_tick; /**< timer timeout tick */
rt_tick_t timeout_tick; /**< timeout tick */
};
2.4 线程控制块中内置定时器
struct rt_thread
{
char name[RT_NAME_MAX];
rt_uint8_t type;
rt_uint8_t flag;
rt_list_t list;
void *sp; /* 线程栈指针 */
void *entry; /* 线程入口地址 */
void *parameter; /* 线程形参 */
void *stack_addr; /* 线程起始地址 */
rt_uint32_t stack_size; /* 线程栈大小,单位为字节 */
rt_list_t tlist; /* 线程链表节点 */
rt_ubase_t remaining_tick;
rt_uint8_t current_priority;
rt_uint8_t init_priority;
rt_uint32_t number_mask;
rt_err_t error;
rt_uint8_t stat;
**struct rt_timer thread_timer;**
};
2.5 定时器初始化
timer.c中
void rt_timer_init(rt_timer_t timer,
const char *name,
void (*timeout)(void *parameter),
void *parameter,
rt_tick_t time,
rt_uint8_t flag)
{
rt_object_init((rt_object_t)timer,RT_Object_Class_Timer,name);
_rt_timer_init(timer,timeout,parameter,time,flag);
}
static void _rt_timer_init(rt_timer_t timer,
void (*timeout)(void *parameter),
void *parameter,
rt_tick_t time,
rt_uint8_t flag)
{
int i;
timer->parent.flag = flag;
timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
timer->timeout_func = timeout;
timer->parameter = parameter;
timer->timeout_tick = 0;
timer->init_tick = time;
for(i = 0; i < RT_TIMER_SKIP_LIST_LEVEL;i++)
{
rt_list_init(&(timer->row[i]));
}
}
redef.h中定义标志
#define RT_TIMER_FLAG_DEACTIVATED 0x0
#define RT_TIMER_FLAG_ACTIVATED 0x1
#define RT_TIMER_FLAG_ONE_SHOT 0x0
#define RT_TIMER_FLAG_PERIODIC 0x02
#define RT_TIMER_FLAG_HARD_TIMER 0x0
#define RT_TIMER_FLAG_SOFT_TIMER 0x4
2.6定时器删除函数
rt_inline void _rt_timer_remove(rt_timer_t timer)
{
int i;
for(i = 0; i < RT_TIMER_SKIP_LIST_LEVEL;i++)
{
rt_list_remove(&timer->row[i]);
}
}
2.7 定时器停止函数
rt_err_t rt_timer_stop(rt_timer_t timer)
{
register rt_base_t level;
if(!(timer->parent.flag & RT_TIMER_FLAG_ACTIVATED))
return -RT_ERROR;
level = rt_hw_interrupt_disable();
_rt_timer_remove(timer);
rt_hw_interrupt_enable(level);
timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
return RT_EOK;
}
2.8 定时器控制函数
rt_err_t rt_timer_control(rt_timer_t timer,int cmd,void *arg)
{
switch(cmd)
{
case RT_TIMER_CTRL_GET_TIME:
*(rt_tick_t *)arg = timer->init_tick;
break;
case RT_TIMER_CTRL_SET_TIME:
timer->init_tick = *(rt_tick_t *)arg;
break;
case RT_TIMER_CTRL_SET_ONESHOT:
timer->parent.flag &= ~RT_TIMER_FLAG_PERIODIC;
break;
case RT_TIMER_CTRL_SET_PERODIC:
timer->parent.flag |= RT_TIMER_FLAG_PERIODIC;
break;
}
return RT_EOK;
}
rtdef.h中定义控制命令
#define RT_TIMER_CTRL_SET_TIME 0x0
#define RT_TIMER_CTRL_GET_TIME 0x1
#define RT_TIMER_CTRL_SET_ONESHOT 0x2
#define RT_TIMER_CTRL_SET_PERODIC 0x3
2.9 定义启动函数
rt_err_t rt_timer_start(rt_timer_t timer)
{
unsigned int row_lvl = 0;
rt_list_t *timer_list;
register rt_base_t level;
rt_list_t *row_head[RT_TIMER_SKIP_LIST_LEVEL];
unsigned int tst_nr;
static unsigned int random_nr;
level = rt_hw_interrupt_disable();
_rt_timer_remove(timer);
timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
rt_hw_interrupt_enable(level);
timer->timeout_tick = rt_tick_get() + timer->init_tick;
level = rt_hw_interrupt_disable();
timer_list = rt_timer_list;
row_head[0]=&timer_list[0];
for(row_lvl = 0; row_lvl < RT_TIMER_SKIP_LIST_LEVEL;row_lvl++)
{
for(;row_head[row_lvl]!=timer_list[row_lvl].prev;row_head[row_lvl]=row_head[row_lvl]->next)
{
struct rt_timer *t;
rt_list_t *p = row_head[row_lvl]->next;
t = rt_list_entry(p,struct rt_timer,row[row_lvl]);
if((t->timeout_tick-timer->timeout_tick)==0)
{
continue;
}
else if((t->timeout_tick-timer->timeout_tick)<RT_TICK_MAX/2)
{
break;
}
}
if(row_lvl != RT_TIMER_SKIP_LIST_LEVEL -1)
{
row_head[row_lvl+1]=row_head[row_lvl]+1;
}
}
random_nr++;
tst_nr = random_nr;
P_DBG("row_lvl %d inset timer %s\n",row_lvl,timer->parent.name);
rt_list_insert_after(row_head[RT_TIMER_SKIP_LIST_LEVEL-1],&(timer->row[RT_TIMER_SKIP_LIST_LEVEL-1]));
for(row_lvl = 2;row_lvl <= RT_TIMER_SKIP_LIST_LEVEL;row_lvl)
{
if(!(tst_nr & RT_TIMER_SKIP_LIST_LEVEL))
rt_list_insert_after(row_head[RT_TIMER_SKIP_LIST_LEVEL-row_lvl],&(timer->row[RT_TIMER_SKIP_LIST_LEVEL-row_lvl]));
else
break;
tst_nr >>= (RT_TIMER_SKIP_LIST_MASK+1)>>1;
}
timer->parent.flag |= RT_TIMER_FLAG_ACTIVATED;
rt_hw_interrupt_enable(level);
return -RT_EOK;
}
2.10 定时器扫描函数
void rt_timer_check(void)
{
struct rt_timer *t;
rt_tick_t current_tick;
register rt_base_t level;
current_tick = rt_tick_get();
level = rt_hw_interrupt_disable();
//P_DBG("check...\n");
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]);
if((current_tick-t->timeout_tick)<RT_TICK_MAX/2)
{
P_DBG("t %s timeout\n",t->parent.name);
_rt_timer_remove(t);
t->timeout_func(t->parameter);
current_tick = rt_tick_get();
if((t->parent.flag & RT_TIMER_FLAG_PERIODIC)&&(t->parent.flag&RT_TIMER_FLAG_ACTIVATED))
{
t->parent.flag &= ~ RT_TIMER_FLAG_ACTIVATED;
rt_timer_start(t);
}
else
{
t->parent.flag &= ~ RT_TIMER_FLAG_ACTIVATED;
}
}
else
{
break;
}
}
rt_hw_interrupt_enable(level);
}
3.修改代码
3.1 修改线程初始化函数
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_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) );
thread->init_priority = priority;
thread->current_priority = priority;
thread->number_mask = 0;
thread->error = RT_EOK;
thread->stat = RT_THREAD_INIT;
rt_timer_init(&(thread->thread_timer),thread->name,rt_thread_timeout,thread,0,RT_TIMER_FLAG_ONE_SHOT);
return RT_EOK;
}
3.2 修改延时函数
rt_err_t rt_thread_delay(rt_tick_t tick)
{
return rt_thread_sleep(tick);
}
rt_err_t rt_thread_sleep(rt_tick_t tick)
{
register rt_base_t temp;
struct rt_thread *thread;
temp = rt_hw_interrupt_disable();
thread = rt_current_thread;
rt_thread_suspend(thread);
rt_timer_control(&(thread->thread_timer),RT_TIMER_CTRL_SET_TIME,&tick);
rt_timer_start(&(thread->thread_timer));
rt_hw_interrupt_enable(temp);
rt_schedule();
return RT_EOK;
}
rt_err_t rt_thread_suspend(rt_thread_t thread)
{
register rt_base_t temp;
if((thread->stat & RT_THREAD_STAT_MASK)!= RT_THREAD_READY)
{
return -RT_ERROR;
}
temp = rt_hw_interrupt_disable();
thread->stat = RT_THREAD_SUSPEND;
rt_schedule_remove_thread(thread);
rt_timer_stop(&(thread->thread_timer));
rt_hw_interrupt_enable(temp);
return RT_EOK;
}
3.3 修改时基函数
void rt_tick_increase(void)
{
++ rt_tick;
rt_timer_check();
}
3.4 修改main函数
rt_system_timer_init();
4 用例
void flag1_thread_entry( void *p_arg )
{
for( ;; )
{
P_DBG("flag1 thread\n");
flag2 = 1;
P_DBG("flag1 thread will dela1\n");
rt_thread_delay(10);
flag2 = 0;
P_DBG("flag1 thread will dela2\n");
rt_thread_delay(10);
}
}