当前位置: 首页 > article >正文

软定时器的删除与状态查询

目录

软定时器的删除

设计实现


软定时器的删除

将软定时器所在列表移除

设计实现

  • 定时器删除(调用tTimerStop函数)
  • 定时器状态查询(状态查询结构:初次启动延后的ticks数、周期定时时的周期tick数、定时回调函数、传递给回调函数的参数、定时器配置参数、定时器状态)

tTimer.c

#include "tinyOS.h"

static tList tTimerHardList;	//中断服务处理程序中处理的软定时器列表
static tList tTimerSoftList;	//定时器任务处理的软定时器列表
static tSem tTimerProtectSem;	//定时器任务以及其他任务访问SoftList的信号量
static tSem tTimerTickSem;		//中断服务处理程序中通知定时器任务有定时中断发生

/* 软定时器初始化 */
//参数:软定时器,初始延时的tick数,周期数,定时器的回调函数,回调函数参数,配置
void tTimerInit(tTimer *timer, uint32_t delayTicks, uint32_t durationTicks, void (*timerFunc)(void *arg), void *arg, uint32_t config)
{
	tNodeInit(&timer->linkNode);
	timer->startDelayTicks = delayTicks;
	timer->durationTicks = durationTicks;
	timer->timerFunc = timerFunc;
	timer->arg = arg;
	timer->config = config;
	
	if(delayTicks == 0)
	{
		timer->delayTicks = durationTicks;//定时器当前计数值等于使用周期的计数器
	}
	else
	{
		//有延时
		timer->delayTicks = timer->startDelayTicks;
	}
	
	timer->state = tTimerCreated;
}

/* 软定时器启动函数 */
void tTimerStart(tTimer *timer)
{
	//判断定时器状态
	switch(timer->state)
	{
		case tTimerCreated:
		case tTimerStopped://创建或已停止才能启动
			//设置初始延时tick数
			timer->delayTicks = timer->startDelayTicks ? timer->startDelayTicks : timer->durationTicks;
			timer->state = tTimerStarted;
		
			//根据配置决定插入到哪个定时器列表中
			if(timer->config & TIMER_CONFIG_TYPE_HARD)
			{
				//时钟节拍的中断处理函数中也会访问定时器中断列表,开启临界区保护
				uint32_t status = tTaskEnterCritical();
				tListAddFirst(&tTimerHardList, &timer->linkNode);
				tTaskExitCritical(status);
			}
			else
			{
				//信号量保护,中断中已经不允许访问SoftList
				//想在中断中调用不能用信号量保护,需要使用临界区保护
				tSemWait(&tTimerProtectSem, 0);
				tListAddFirst(&tTimerSoftList, &timer->linkNode);
				tSemNotify(&tTimerProtectSem);
			}
			break;
		default:
			break;
	}
}

/* 软定时器停止函数 */
void tTimerStop(tTimer *timer)
{
	switch (timer->state)
	{
		case tTimerStarted:
		case tTimerRunning://已经启动或正在运行才能停止
			if(timer->config & TIMER_CONFIG_TYPE_HARD)
			{
				uint32_t status = tTaskEnterCritical();
				tListRemove(&tTimerHardList, &timer->linkNode);
				tTaskExitCritical(status);
			}
			else
			{
				tSemWait(&tTimerProtectSem, 0);
				tListRemove(&tTimerSoftList, &timer->linkNode);
				tSemNotify(&tTimerProtectSem);
			}
			break;
		default:
			break;
	}
}

/* 软定时器删除函数 */
void tTimerDestroy(tTimer *timer)
{
	tTimerStop(timer);
	timer->state = tTimerDestroyed;
}

/* 软定时器状态查询函数 */
void tTimerGetInfo(tTimer *timer, tTimerInfo *info)
{
	uint32_t status = tTaskEnterCritical();
	
	info->startDelayTicks = timer->startDelayTicks;
	info->durationTicks = timer->durationTicks;
	info->timerFunc = timer->timerFunc;
	info->arg = timer->arg;
	info->config = timer->config;
	info->state = timer->state;
	
	tTaskExitCritical(status);
}

/* 对软定时器列表进行处理函数 */
static void tTimerCallFuncList(tList *timerList)
{
	//遍历各结点
	tNode *node;
	for(node = timerList->headNode.nextNode; node != &(timerList->headNode); node = node->nextNode)
	{
		tTimer *timer = tNodeParent(node, tTimer, linkNode);//取出结点对应的定时器
		//判断定时器延时时间是否到达或者对定时器延时计数减减操作后为0
		if((timer->delayTicks == 0) || (--timer->delayTicks == 0))
		{
			//调用定时器处理函数
			timer->state = tTimerRunning;
			timer->timerFunc(timer->arg);
			timer->state = tTimerStarted;
			
			//检查定时器是否需要周期计数
			if(timer->durationTicks > 0)
			{
				timer->delayTicks = timer->durationTicks;
			}
			else
			{
				tListRemove(timerList, &timer->linkNode);
				timer->state = tTimerStopped;
			}
		}
	}
}

static tTask tTimerTask;//定时器任务
static tTaskStack tTimerTaskStack[TINYOS_TIMERTASK_STACK_SIZE];//定时器任务堆栈

/* 定时器任务函数 */
static void tTimerSoftTask(void *param)
{
	for(;;)
	{
		tSemWait(&tTimerTickSem, 0);//等待tTimerTickSem,在系统节拍处理函数中向信号量发送通知
		
		tSemWait(&tTimerProtectSem, 0);//申请tTimerProtectSem信号量,定时器任务拥有对SoftList访问权
		
		tTimerCallFuncList(&tTimerSoftList);//对SoftList中软定时器处理
		
		tSemNotify(&tTimerProtectSem);//释放信号量
	}
}

/* 通知信号量相应的tick中断已发生函数 */
//中断服务函数中调用,计数器恢复运行
void tTimerModuleTickNotify(void)
{
	uint32_t status = tTaskEnterCritical();
	
	//函数在中断服务处理函数中调用,同时处理HandList定时器列表
	tTimerCallFuncList(&tTimerHardList);
	
	tTaskExitCritical(status);
	
	tSemNotify(&tTimerTickSem);//通知信号量,计数值加1。定时器任务函数SemWait函数唤醒
}

/* 定时器初始化 */
void tTimerModuleInit(void)
{
	//初始化定时器列表
	tListInit(&tTimerHardList);
	tListInit(&tTimerSoftList);
	//初始化信号量
	tSemInit(&tTimerProtectSem, 1, 1);//初始值和最大计数值均为1
	tSemInit(&tTimerTickSem, 0, 0);		//初始值为0,最大计数值没有限制
	
	//初始化任务
	//任务定时器优先级要大于空闲任务优先级
#if TINYOS_TIMERTASK_PRIO >= (TINYOS_PRO_COUNT - 1)
	#error "The proprity of timer tasker must be greater then (TINYOS_PRO_COUNT - 1)"
#endif
	tTaskInit(&tTimerTask, tTimerSoftTask, (void *)0, TINYOS_TIMERTASK_PRIO, &tTimerTaskStack[TINYOS_TIMERTASK_STACK_SIZE]);
}

tTimer.h

#ifndef __TTIMER_H
#define __TTIMER_H

#include "tEvent.h"

/* 软定时器状态 */
typedef enum _tTimerState
{
	tTimerCreated,		//已创建
	tTimerStarted,		//已启动
	tTimerRunning,		//正在运行
	tTimerStopped,		//已停止
	tTimerDestroyed		//已销毁
}tTimerState;

/* 软定时器结构 */
typedef struct _tTimer
{
	tNode linkNode;								//链接结点
	uint32_t startDelayTicks;			//初始时的延时计数
	uint32_t durationTicks;				//周期的计数值
	uint32_t delayTicks;					//当前的计数值
	void (*timerFunc)(void *arg);	//定时器的回调处理函数
	void *arg;										//传递给回调处理函数的参数
	uint32_t config;							//定时器配置
	
	tTimerState state;						//定时器状态
}tTimer;

/* 软定时器状态查询结构 */
typedef struct _tTimerInfo
{
	uint32_t startDelayTicks;			//初始时的延时计数
	uint32_t durationTicks;				//周期的计数值
	void (*timerFunc)(void *arg);	//定时器的回调处理函数
	void *arg;										//传递给回调处理函数的参数
	uint32_t config;							//定时器配置
	tTimerState state;						//定时器状态
	
}tTimerInfo;

//定时器是在定时器任务中处理的还是系统时钟节拍中断中处理的宏
#define TIMER_CONFIG_TYPE_HARD		(1 << 0)	//中断中
#define TIMER_CONFIG_TYPE_SOFT		(0 << 0)	//任务中

void tTimerInit(tTimer *timer, uint32_t delayTicks, uint32_t durationTicks, void (*timerFunc)(void *arg), void *arg, uint32_t config);
void tTimerStart(tTimer *timer);
void tTimerStop(tTimer *timer);
void tTimerDestroy(tTimer *timer);
void tTimerGetInfo(tTimer *timer, tTimerInfo *info);
void tTimerModuleTickNotify(void);
void tTimerModuleInit(void);
	
#endif

app.c

#include "tinyOS.h"
#include "string.h"

//定义任务,分别为它们配备独立的堆栈空间
tTask tTask1;
tTask tTask2;
tTask tTask3;
tTask tTask4;
tTaskStack task1Env[1024];
tTaskStack task2Env[1024];
tTaskStack task3Env[1024];
tTaskStack task4Env[1024];

tTimer timer1;
tTimer timer2;
tTimer timer3;

uint32_t bit1 = 0;
uint32_t bit2 = 0;
uint32_t bit3 = 0;

//传32位整型指针的值,将值原来对应变量的最低位取反
void timerFunc(void *arg)
{
	uint32_t *ptrBit = (uint32_t *)arg;
	*ptrBit ^= 0x1;
}

//定义任务要执行的功能
int task1Flag;
void task1Entry(void *param)
{
	uint32_t destroy = 0;
	tTimerInfo timerinfo;
	tSetSysTickPeriod(10);//初始化
	
	tTimerInit(&timer1, 100, 10, timerFunc, (void *)&bit1, TIMER_CONFIG_TYPE_HARD);
	tTimerStart(&timer1);
	tTimerInit(&timer2, 200, 20, timerFunc, (void *)&bit2, TIMER_CONFIG_TYPE_HARD);
	tTimerStart(&timer2);
	tTimerInit(&timer3, 300, 0, timerFunc, (void *)&bit3, TIMER_CONFIG_TYPE_SOFT);
	tTimerStart(&timer3);
	
	for(;;)//任务里是for的死循环
	{
		task1Flag = 0; 
		tTaskDelay(1);
		task1Flag = 1;
		tTaskDelay(1);
		
		if(destroy == 0)
		{
			tTaskDelay(200);
			tTimerDestroy(&timer1);
			destroy = 1;
		}
		
		tTimerGetInfo(&timer2, &timerinfo);
	}
}

int task2Flag;
void task2Entry(void *param)
{
	
	for(;;)
	{	
 		task2Flag = 0;
		tTaskDelay(1);
		task2Flag = 1;
		tTaskDelay(1);
	}
}
int task3Flag;
void task3Entry(void *param)
{
	for(;;)
	{
		task3Flag = 0;
		tTaskDelay(1);
		task3Flag = 1;
		tTaskDelay(1);
	}
}
int task4Flag;
void task4Entry(void *param)
{
	for(;;)
	{
		task4Flag = 0;
		tTaskDelay(1);
		task4Flag = 1;
		tTaskDelay(1);
	}
}

/* 应用任务初始化函数 */
void tInitApp(void)
{
	//最后一个参数:传堆栈末端地址,因为堆栈是向下生长的,初始堆栈地址是堆栈空间最后一个单元地址的末端
	tTaskInit(&tTask1, task1Entry, (void *)0x11111111, 0, &task1Env[1024]);
	tTaskInit(&tTask2, task2Entry, (void *)0x22222222, 1, &task2Env[1024]);
	tTaskInit(&tTask3, task3Entry, (void *)0x22222222, 1, &task3Env[1024]);
	tTaskInit(&tTask4, task4Entry, (void *)0x22222222, 1, &task4Env[1024]);
}


http://www.kler.cn/a/504707.html

相关文章:

  • Windows 蓝牙驱动开发-安装蓝牙设备
  • GLM: General Language Model Pretraining with Autoregressive Blank Infilling论文解读
  • .net core 中使用AsyncLocal传递变量
  • 二十三种模式-适配器模式
  • Flutter插件制作、本地/远程依赖及缓存机制深入剖析(原创-附源码)
  • pytorch张量分块投影示例代码
  • UE材质节点Fresnel
  • 2025年互联网医院系统源码开发趋势:如何构建AI在线问诊APP
  • 2025.1.15——假期回归训练,从sql注入开始|一、SQL整数型注入
  • Kibana:ES|QL 编辑器简介
  • Visual Studio 同一解决方案 同时运行 多个项目
  • 宇泰串口卡驱动在Ubuntu22.04编译、安装汇总
  • 【PGCCC】PostgreSQL 临时文件的使用
  • 【Unity】unity3D 调用LoadSceneAsync 场景切换后比较暗 部门材质丢失
  • 【AI】探索 Anything LLM:解锁多领域语言模型的无限可能
  • 系统架构设计师-第1章-计算机系统知识要点
  • Uniapp判断设备是安卓还是 iOS,并调用不同的方法
  • C#Halcon视觉流程框架个人封装流程心得
  • MySQL程序之:简要概述
  • 基于 Python 和 Django 的课程管理系统设计与实现
  • rtthread学习笔记系列--29 SPI驱动
  • 基于微信小程序的智能停车场管理系统设计与实现(LW+源码+讲解)
  • Android - 仓库镜像记录
  • 【Unity踩坑】Unity中提示缺少Visual Studio组件
  • 分布式 IO 模块:引领立体车库迈向智能化新时代
  • 一文了解汽车嵌入式软件开发Franca IDL 知识