Rt-Thread 移植8--定时器的实现(KF32)

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);

	}
}
相关推荐
~yY…s<#>1 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode
EricWang13583 小时前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
我是谁??3 小时前
C/C++使用AddressSanitizer检测内存错误
c语言·c++
希言JY3 小时前
C字符串 | 字符串处理函数 | 使用 | 原理 | 实现
c语言·开发语言
午言若4 小时前
C语言比较两个字符串是否相同
c语言
TeYiToKu5 小时前
笔记整理—linux驱动开发部分(9)framebuffer驱动框架
linux·c语言·arm开发·驱动开发·笔记·嵌入式硬件·arm
互联网打工人no15 小时前
每日一题——第一百二十四题
c语言
爱吃生蚝的于勒6 小时前
深入学习指针(5)!!!!!!!!!!!!!!!
c语言·开发语言·数据结构·学习·计算机网络·算法
羊小猪~~6 小时前
数据结构C语言描述2(图文结合)--有头单链表,无头单链表(两种方法),链表反转、有序链表构建、排序等操作,考研可看
c语言·数据结构·c++·考研·算法·链表·visual studio
洋2406 小时前
C语言常用标准库函数
c语言·开发语言