原项目地址:GitHub - 0x1abin/MultiTimer: Software timers extend module for embedded
之前在项目上有利用一个硬件定时器,对多段代码执行时间进行测量,于是就去网上寻找一下是否有较为成熟的源码,就看到很多人在讨论MultiTimer,翻看一下代码确实简约高效,于是把它作为项目前后台系统任务添加方式,可以避免变量跨文件,有利于工程管理;
在实际使用过程,做了部分调整(不一定是优化),更贴合自己的使用目的:
1、因为前后台任务均是周期调用,我在原来定时器类增加周期调用属性;
2、因为为满足多个使用场景,修改为面向对象属性,支持定义多个定时器系统;
3、考虑多个线程时序问题,还要考虑运行时临界问题,由于该代码我仅在初始化使用,暂时不添加;
#include "MultiTimer.h"
#include <stdio.h>
/**
* @brief 初始化定时器
* @param timer 定时器上下文
* @param ticksFunc 平台定时器回调函数
* @return 0 成功,-1 失败
*/
int multiTimerInit(stTimerContext* timerHandle,uint64_t(*ticksFunc)(void))
{
if(timerHandle == NULL || ticksFunc == NULL)
{
return -1;
}
timerHandle->timerList = NULL;
timerHandle->callback = ticksFunc;
return 0;
}
/**
* @brief 移除定时器
* @param timer 要移除的定时器
* @return 无
*/
static void removeTimer(stTimerContext* timerHandle,MultiTimer* timer)
{
MultiTimer** current = &timerHandle->timerList;
while (*current)
{
if (*current == timer)
{
*current = timer->next;
break;
}
current = &(*current)->next;
}
}
/**
* @brief 启动定时器
* @param timer 要启动的定时器
* @param timing 定时时间(单位:毫秒)
* @param callback 定时器回调函数
* @param userData 用户数据
* @return 0 成功,-1 失败
*/
int multiTimerStart(stTimerContext* timerHandle, MultiTimer* timer, uint64_t timing, uint8_t isRepeat, void (*callback)(MultiTimer*,void*), void* userData)
{
if(timerHandle == NULL || timer == NULL || timing == 0 || callback == NULL)
{
return -1;
}
removeTimer(timerHandle, timer);
timer->Ctrl.bit.repeat = (isRepeat?1:0);
timer->deadline = timerHandle->callback() + timing;
timer->interval = timing;
timer->callback = callback;
timer->userData = userData;
MultiTimer** current = &timerHandle->timerList;
while (*current && ((*current)->deadline < timer->deadline))
{
current = &(*current)->next;
}
timer->next = *current;
*current = timer;
return 0;
}
/**
* @brief 停止定时器
* @param timer 要停止的定时器
* @return 0 成功,-1 失败
*/
int multiTimerStop(stTimerContext* timerHandle, MultiTimer* timer)
{
removeTimer(timerHandle, timer);
return 0;
}
/**
* @brief 等待下一个定时器事件
* @return 距离下一个定时器事件的剩余时间(单位:毫秒),如果没有定时器事件,则返回0
*/
int multiTimerYield(stTimerContext* timerHandle)
{
if(timerHandle == NULL || timerHandle->timerList == NULL || timerHandle->callback == NULL)
{
return -1;
}
uint64_t currentTicks = timerHandle->callback();
MultiTimer* timer = timerHandle->timerList;
MultiTimer** current = NULL;
while(timer && (timer->deadline <= currentTicks))
{
if (timer->callback)
{
timer->callback(timer, timer->userData);
}
if(timer->Ctrl.bit.repeat)
{
timer->deadline = currentTicks + timer->interval;
removeTimer(timerHandle, timer);
current = &timerHandle->timerList;
while (*current && ((*current)->deadline < timer->deadline))
{
current = &(*current)->next;
}
timer->next = *current;
*current = timer;
}
else
{
removeTimer(timerHandle, timer);
}
timer = timerHandle->timerList;;
}
return timer ? (int)(timer->deadline - currentTicks) : 0;
}
#ifndef __MULTITIMER_H__
#define __MULTITIMER_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct MultiTimer{
struct MultiTimer* next;
union{
uint32_t all;
struct{
uint32_t repeat:1;
uint32_t rev:31;
}bit;
}Ctrl;
uint64_t deadline;
uint64_t interval;
void (*callback)(struct MultiTimer*, void*);
void* userData;
}MultiTimer;
typedef struct{
MultiTimer* timerList;
uint64_t(*callback)(void);
}stTimerContext;
/**
* @brief 初始化定时器
* @param timer 定时器上下文
* @param ticksFunc 平台定时器回调函数
* @return 0 成功,-1 失败
*/
int multiTimerInit(stTimerContext* timerHandle,uint64_t(*ticksFunc)(void));
/**
* @brief 移除定时器
* @param timer 要移除的定时器
* @return 无
*/
static void removeTimer(stTimerContext* timerHandle,MultiTimer* timer);
/**
* @brief 启动定时器
* @param timer 要启动的定时器
* @param timing 定时时间(单位:毫秒)
* @param callback 定时器回调函数
* @param userData 用户数据
* @return 0 成功,-1 失败
*/
int multiTimerStart(stTimerContext* timerHandle, MultiTimer* timer, uint64_t timing,
uint8_t isRepeat, void (*callback)(MultiTimer*,void*), void* userData);
/**
* @brief 停止定时器
* @param timer 要停止的定时器
* @return 0 成功,-1 失败
*/
int multiTimerStop(stTimerContext* timerHandle, MultiTimer* timer);
/**
* @brief 等待下一个定时器事件
* @return 距离下一个定时器事件的剩余时间(单位:毫秒),如果没有定时器事件,则返回0
*/
int multiTimerYield(stTimerContext* timerHandle);
#ifdef __cplusplus
}
#endif
#endif
以下是搭好框架后,成果展示,是不是实现了类似RTOS任务调度操作?当然这仅是基于裸机,并没有任务调度,仅有时间片驱动的周期执行事件
/**
* @file Test.c
* @author <NAME> (<EMAIL>)
* @brief Test file for APL
* @version 0.1
* @date 2021-09-13
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "TimerManage.h"
#include "BspGpio.h"
static MultiTimer taskLed1 = {0};
static MultiTimer taskLed2 = {0};
static MultiTimer taskLed3 = {0};
/**
* @brief Led1任务回调函数
* @param timer 定时器指针
* @param user 用户数据
*/
static void taskLed1Callback(MultiTimer* timer, void* user)
{
BspGpioSet(GPIO_PORT_C,GPIO_PIN_11,2);
}
/**
* @brief Led2任务回调函数
* @param timer 定时器指针
* @param user 用户数据
*/
static void taskLed2Callback(MultiTimer* timer, void* user)
{
BspGpioSet(GPIO_PORT_C,GPIO_PIN_10,2);
}
/**
* @brief Led3任务回调函数
* @param timer 定时器指针
* @param user 用户数据
*/
static void taskLed3Callback(MultiTimer* timer, void* user)
{
BspGpioSet(GPIO_PORT_D,GPIO_PIN_3,2);
}
/**
* @brief 初始化Led
* @return None
*/
void LedInit(void)
{
//初始化Led
BspGpioInit(GPIO_PORT_C,GPIO_PIN_11,GPIO_MODE_OUTPUT,GPIO_OUTPUT_OPEN_DRAIN,GPIO_SPEED_MEDIUM,GPIO_PULL_NONE);
BspGpioInit(GPIO_PORT_C,GPIO_PIN_10,GPIO_MODE_OUTPUT,GPIO_OUTPUT_OPEN_DRAIN,GPIO_SPEED_MEDIUM,GPIO_PULL_NONE);
BspGpioInit(GPIO_PORT_D,GPIO_PIN_3,GPIO_MODE_OUTPUT,GPIO_OUTPUT_OPEN_DRAIN,GPIO_SPEED_MEDIUM,GPIO_PULL_NONE);
//添加Led1任务
TimerManageMsAddTask(&taskLed1, 10, 1, taskLed1Callback, NULL);
//添加Led2任务
TimerManageMsAddTask(&taskLed2, 100, 1, taskLed2Callback, NULL);
//添加Led3任务
TimerManageMsAddTask(&taskLed3, 1000, 1, taskLed3Callback, NULL);
}
#ifdef __cplusplus
}
#endif