Comments (18)
//fix bug when ticks overflow
if((int)((uint32_t)(target->timeout -_timer_ticks)) <= 0) {
}
这样修改即可,修改后暂时没有再测到溢出时出现我所述问题
from multitimer.
//fix bug when ticks overflow if((int)((uint32_t)(target->timeout -_timer_ticks)) <= 0) { }
这样修改即可,修改后暂时没有再测到溢出时出现我所述问题
赞同,这种方式是最简单而且容易理解的:
以一个字节的长度为例,当_timer_ticks=254时,定时3ms,即target->timeout=1时发生超时
根据target->timeout -_timer_ticks <= 0 条件
当_timer_ticks=254时,1-254=3,大于0,未超时
当_timer_ticks=255时,1-255=2,大于0,未超时
当_timer_ticks=0时,1-0=1,大于0,未超时
当_timer_ticks=1时,1-1=0,等于0,超时
考虑到超时判断是在主循环进行的,可能会出现判断的时候错过了timer_ticks=1的情况
当_timer_ticks=2时,1-2=-1,小于0,超时
当_timer_ticks=3时,1-3=-2,小于0,超时
from multitimer.
是不是可以换个思路,解决溢出的原因是以为溢出后会导致计时器不准。
可以将_timer_ticks定义为64位的,这样即使1ms累加一次,也要上亿年,设备也运行不到那个时候。
from multitimer.
可以通过增加溢出标识来处理,具体如下:
1.增加 static uint8_t _timer_overflow_flag = 0;
2.Timer结构体:
typedef struct Timer {
uint32_t timeout;
uint32_t repeat;
uint8_t overflow_flag;
void (*timeout_cb)(void);
struct Timer* next;
}Timer;
- timer_ticks函数改为:
void timer_ticks()
{
_timer_ticks++;
if (_timer_ticks == 0) {
_timer_overflow_flag = 1;
}
}
4.timer_loop函数改为:
void timer_loop()
{
struct Timer* target;
uint8_t flag = _timer_overflow_flag;
_timer_overflow_flag = 0;
for(target=head_handle; target; target=target->next) {
if((flag == target->overflow_flag && _timer_ticks >= target->timeout) || flag > target->overflow_flag) {
target->overflow_flag = 0;
if(target->repeat == 0) {
timer_stop(target);
} else {
target->timeout = _timer_ticks + target->repeat;
if (target->timeout < _timer_ticks) {
target->overflow_flag = 1;
}
}
target->timeout_cb();
}
}
}
5.最后timer_init函数也要加上初始化的标识:
handle->overflow_flag = _timer_overflow_flag;
有可能有考虑不周到的情况,可以帮忙检查下这样是否有漏洞。
from multitimer.
//fix bug when ticks overflow if((int)((uint32_t)(target->timeout -_timer_ticks)) <= 0) { }
这样修改即可,修改后暂时没有再测到溢出时出现我所述问题
其实还有一种更优雅的解决方法~采用双链表去维护,溢出时切换链表
from multitimer.
if( (_time_ticks - target->time) < (UINT32_MAX)/2)
结构体多增加了一个target->time,用于在启动定时器时缓存,target->time = _time_ticks+ target->timeout;
target->timeout 值不能超过(UINT32_MAX)/2
from multitimer.
这个方案是否可行:timeout参数采用倒计时。
(1)在timer_init函数中timeout参数采用倒计时的方式,不需要算上当前的时间戳;
(2)在HAL_IncTick中每次减去tick,减到0时,增加一个标志位
(3)在timer_loop中检查标志位。
from multitimer.
typedef struct SortTimer {
uint32_t timestart;
uint32_t interval;
uint32_t repeat;
void (timeout_cb)();
struct SortTimer next;
} SortTimer;
结构体timeout修改为timestart,增加一个interval;
if (_timer_ticks - target->timestart > target->interval)
这样就不存在定时时间必须小于UINT32_MAX/2问题,但是还是存在一个长定时而且主循环超时导致时间点错过的问题
以byte类型为例,假如当前tick为254,定时时长253,这样只有3次tick满足,如果主循环超过3次tick,就会造成错过时间点。
而if((int32_t)((uint32_t)(target->timeout -_timer_ticks)) <= 0)方式存在定时时长不能超过UINT32_MAX/2
完全处理还是要针对UINT32_MAX/2设置标志位,或者设置_timer_ticks过零标志位。
if((_timer_ticks - target->timestart > target->interval)||
(target->overFlag == 1)&&(_timer_ticks > target->timestart)){
target->overFlag = 0;//在_timer_ticks过零时设置
}
_timer_ticks - target->timestart > target->interval
timestart :254
interval:253
timeout:251
ticks = 255 1<253满足
ticks = 1 2<253满足
......
ticks = 250 252<253满足
ticks = 251 253==253不满足,时间到
ticks = 252 254>253不满足,时间到
ticks = 253 255>253不满足,时间到
ticks = 254 0<253满足,时间错过
ticks = 255 1<253满足,时间错过
ticks = 1 2<253满足,时间错过
from multitimer.
是不是可以换个思路,解决溢出的原因是以为溢出后会导致计时器不准。 可以将_timer_ticks定义为64位的,这样即使1ms累加一次,也要上亿年,设备也运行不到那个时候。
简单粗暴而不失优雅,哈哈, 在判断时再加个锁可以防止8位、16位、32位CPU的汇编中断问题。
from multitimer.
from multitimer.
//fix bug when ticks overflow if((int)((uint32_t)(target->timeout -_timer_ticks)) <= 0) { }
这样修改即可,修改后暂时没有再测到溢出时出现我所述问题
赞同,这种方式是最简单而且容易理解的:
以一个字节的长度为例,
当_timer_ticks=254时,定时3ms,即target->timeout=1时发生超时 根据target->timeout -_timer_ticks <= 0 条件
当_timer_ticks=254时,1-254=3,大于0,未超时
当_timer_ticks=255时,1-255=2,大于0,未超时
当_timer_ticks=0时,1-0=1,大于0,未超时
当_timer_ticks=1时,1-1=0,等于0,超时
考虑到超时判断是在主循环进行的,可能会出现判断的时候错过了timer_ticks=1的情况
当_timer_ticks=2时,1-2=-1,小于0,超时
当_timer_ticks=3时,1-3=-2,小于0,超时
//fix bug when ticks overflow
if((int32_t)((uint32_t)(target->timeout -_timer_ticks)) <= 0) {
}
这样严谨点
from multitimer.
from multitimer.
推荐另外一种的解决方法: 不用设置标志,不用去考虑有符号无符号中间的转换。
定义一个获取时间长度的宏 TIME_PASSED
#define TIME_MAX 0xFFFFFFFFu /* 最大时间长度取决于使用的timer计时器长度,这里以32bit为例 */
#define TIME_PASSED(now, since) ((now) >= (since)) ? ((now) -(since)) : ((now) + (1 + TIME_MAX - (since)))
参考资料:《嵌入式系统设计与实践》5.4.2 p138
from multitimer.
from multitimer.
//fix bug when ticks overflow if((int)((uint32_t)(target->timeout -_timer_ticks)) <= 0) { }
这样修改即可,修改后暂时没有再测到溢出时出现我所述问题
是否应该改成这样:
if((int)((uint32_t)(target->timeout -_timer_ticks)) < 0)
{
}
就是把等于0的情况去掉,不然永远进不去这个条件:if(_timer_ticks >= target->timeout)
from multitimer.
from multitimer.
实际上这里可以直接使用减法,不用考虑溢出条件,无符号减法本身就是借位操作,比如说,我们定义两个32位无符号整数:
uint32_t a = x;
uint32_t b = y;
当x < y 时,a - b的计算结果实际上就是2^32 + (x - y)。
from multitimer.
from multitimer.
Related Issues (12)
- 为什么重复执行的定时器不在MultiTimerYield执行重新启动,在回调函数容易漏掉 HOT 3
- 提点需求,希望能完善该项目 HOT 1
- platformTicksFunction 指针未做判空处理 HOT 1
- PlatformTicksGetFunc() 系统时间溢出怎么处理 HOT 3
- timer_tick是否考虑添加形参,由外部指定tick 频率
- 如何解决带参函数的定时 HOT 2
- 会消耗100%的cpu
- MultiTimer
- main.c没上传吗? HOT 1
- BUG HOT 2
- 不用的定时器资源无法回收 HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from multitimer.