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

news2024/10/5 21:21:16

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

	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1246862.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SSM教材管理系统开发mysql数据库web结构java编程计算机网页源码eclipse项目

一、源码特点 SSM 教材管理系统是一套完善的信息系统&#xff0c;结合springMVC框架完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开…

如何为你的味蕾选择最完美的白葡萄酒

每一种白葡萄酒都有独特的味道和气味&#xff0c;如何选择一款你喜欢的口味的葡萄酒呢&#xff1f;每一种独特的白葡萄酒产品都使用了非常不同的发酵过程和葡萄种类&#xff0c;以达到它们所熟知的独特味道和风味。 来自云仓酒庄品牌雷盛红酒分享长相思是最具绿色口感的白葡萄…

NX二次开发UF_CSYS_create_temp_csys 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CSYS_create_temp_csys Defined in: uf_csys.h int UF_CSYS_create_temp_csys(const double csys_origin [ 3 ] , tag_t matrix_id, tag_t * csys_id ) overview 概述 Creates …

VMware 虚拟机设置静态IP

1.桥接模式&#xff1a;无线网卡虚拟机可以桥接的&#xff0c;Vmware0是虚拟机默认进入的虚拟网络&#xff0c;打开虚拟网络编辑器把Vmware0桥接到具体的无线网卡上&#xff0c;再打开网卡设置选择桥接模式即可。 2、.NAT模式下 &#xff1a;window下VMnet8: IPv4 地址 . . . …

ArcMap针对正射影像图生成切片操作

1.导入图层jpg文件 2.添加地图坐标系 右键点击地图 --》数据框属性 坐标系选项设置地图的坐标系 地图应该有对应的坐标文件 3.地理配准选项 --》去除自动校正&#xff0c; 4.选择参考坐标 在图中选三个定位坐标保存 5.地理配准选项 --》更新地理位置配准 6.管理工具下 --》…

绿色能源守护者:光伏运维无人机

随着我国太阳能光伏产业被纳入战略性新兴产业&#xff0c;光伏发电成为实现“双碳”目标的关键之一。在政策支持下&#xff0c;光伏产业维持高速发展&#xff0c;为迎接“碳达峰、碳中和”大势注入了强大动力。在这一背景下&#xff0c;复亚智能与安徽一家光伏企业合作&#xf…

【周报2023-11-24】

周报2023-11-24 本周主要工作下周工作计划 本周主要工作 本周的话一个主要工作有&#xff1a; 前后端进行联调接口&#xff1a; 那么目前为止的话&#xff0c;已经调通的接口 可以使用的是个人中心 历史生成的接口 选择新模板 新模板详情 ps: 下周工作计划 主要的话就是将…

spark数据倾斜的解决思路

数据倾斜是&#xff1a;多个分区中&#xff0c;某个分区的数据比其他分区的数据多的多 数据倾斜导致的问题&#xff1a; 导致某个spark任务耗时较长&#xff0c;导致整个任务耗时增加&#xff0c;甚至出现OOM运行速度慢&#xff1a;主要发生在shuffle阶段&#xff0c;同样的k…

水厂桶装水订水小程序搭建,提高用户订水的便捷性。

桶装水订水小程序&#xff0c;轻松实现在线预订&#xff0c;统计数量&#xff0c;告别繁琐电话预订。微信水预订小程序&#xff0c;不仅方便用户在线预订&#xff0c;还助力水店提升互联网管理效率。 一、微信订水小程序的作用 1. 简化预订流程&#xff0c;提高服务效率&#…

金风玉露一相逢|实在智能联手浪潮信息合力致新生成式AI产业生态

近日&#xff0c;实在智能正式加入浪潮信息元脑生态AIStore。 实在智能是一家基于AGI大模型超自动化技术&#xff0c;领跑人机协同时代的人工智能科技公司&#xff0c;以其自研垂直的“TARS&#xff08;塔斯&#xff09;大语言模型”技术、实在RPA Agent智能体数字员工产品和超…

pytest-html测试报告这样写,某易测开都直呼:大哥受小弟一拜

在 pytest 中提供了生成html格式测试报告的插件 pytest-html 安装 安装命令如下&#xff1a; pip install pytest-html使用 我们已经知道执行用例的两种方式&#xff0c;pytest.main()执行和命令行执行&#xff0c;而要使用pytest-html生成报告&#xff0c;只需要在执行时加…

华大基因助力乌兹别克斯坦精准医学发展,共筑健康丝绸之路

今年上半年&#xff0c;中国与中亚五国元首齐聚陕西西安&#xff0c;举办中国&#xff0d;中亚峰会。过去的20年里&#xff0c;中国已经成为中亚国家的主要投资来源国&#xff0c;总投资额接近400亿美元。乌兹别克斯坦是中国&#xff0d;中亚合作机制的重要参与者&#xff0c;乌…

飞凌嵌入式受邀参加「2023年电子工程师大会」并做主旨演讲

11月23日&#xff0c;华秋电子发烧友在深圳总部举办了「2023年电子工程师大会暨第三届社区年度颁奖」活动&#xff0c;邀请到了高校教授、企业创始人及高管、行业技术专家、电子工程师等众多嘉宾到场&#xff0c;呈现并传播了电子产业动态、最新技术、应用案例及开源硬件项目。…

数据治理技术之数据清洗

数据清洗背景 数据质量一般由准确性、完整性、一致性、时效性、可信性以及可解释性等特征来描述&#xff0c;根据 Rahm 等人在 2000 年对数据质量基于单数据源还是多数据源以及问题出在模式层还是实例层的标准进行分类&#xff0c;将数据质量问题分为单数据源模式层问题、单数…

Vatee万腾科技新高峰:Vatee前瞻性创新的数字化之力

Vatee万腾科技&#xff0c;一家以前瞻性创新为核心驱动力的数字化引领者&#xff0c;正迈向新的高峰。其在科技领域的卓越表现不仅体现在技术实力上&#xff0c;更展现在对未来的深刻洞察和独到思考上。 在Vatee的科技舞台上&#xff0c;前瞻性创新如一道独特的光芒&#xff0c…

【Linux】make/Makefile 进度条小程序

目录 一&#xff0c;认识 make/makefile 二&#xff0c;实例代码 1&#xff0c;依赖关系 2&#xff0c;原理 3&#xff0c;项目清理 4&#xff0c;测试讲解 三&#xff0c;Linux第一个小程序&#xff0d;进度条 game.h game.c test.c 程序详解 一&#xff0c;认识 m…

管易云与金蝶云星空对接集成其他出库查询连通其他出库新增(其他出库单)

管易云与金蝶云星空对接集成其他出库查询连通其他出库新增(其他出库单) 数据源系统:管易云 管易云是上海管易云计算软件有限公司旗下的专注提供电商企业管理软件服务的品牌&#xff0c;总部位于中国上海张江高科技产业园区。管易云旗下拥有管易云C-ERP、EC-OMS、EC-WMS、B2C/B2…

【Vue】浏览器安装vue插件

首先看一下安装之后的效果&#xff0c;再考虑一下要不要安装 安装完之后&#xff0c;打开浏览器控制台&#xff08;ctrl shift j) <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</t…

无人智能柜:经营成本低,运维智能化

在现代商业领域中&#xff0c;无人智能柜正逐渐崭露头角&#xff0c;成为一种具有前景的商业模式。其独特之处在于经营成本的低廉性和运维过程的智能化。相较于传统的便利店等实体店铺&#xff0c;无人智能柜在运营过程中不仅能够降低成本&#xff0c;还能够实现高效的运维管理…

内网渗透之Linux权限提升大法

文章目录 内网渗透|Linux权限提升大法0x01 前言0x02 工具介绍1.traitor2.LinEnum3.linux-exploit-suggester.sh4.Linux Exploit Suggester 25.beroot 0X02提权手法1.环境变量提权2.利用suid提权3.定时任务提权3.1定时任务文件覆盖提权3.2定时任务tar命令通配符注入提权 4.sudo提…