GithubHelp home page GithubHelp logo

超时溢出有问题 about multitimer HOT 18 OPEN

0x1abin avatar 0x1abin commented on July 4, 2024
超时溢出有问题

from multitimer.

Comments (18)

longdelu avatar longdelu commented on July 4, 2024 7
    //fix bug when ticks overflow
    if((int)((uint32_t)(target->timeout -_timer_ticks)) <= 0) {
       
    }

这样修改即可,修改后暂时没有再测到溢出时出现我所述问题

from multitimer.

VanchTan avatar VanchTan commented on July 4, 2024 5
    //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.

Eureka1024 avatar Eureka1024 commented on July 4, 2024 5

是不是可以换个思路,解决溢出的原因是以为溢出后会导致计时器不准。
可以将_timer_ticks定义为64位的,这样即使1ms累加一次,也要上亿年,设备也运行不到那个时候。

from multitimer.

angwangiot avatar angwangiot commented on July 4, 2024

可以通过增加溢出标识来处理,具体如下:
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;
  1. 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.

jiejieTop avatar jiejieTop commented on July 4, 2024
    //fix bug when ticks overflow
    if((int)((uint32_t)(target->timeout -_timer_ticks)) <= 0) {
       
    }

这样修改即可,修改后暂时没有再测到溢出时出现我所述问题

其实还有一种更优雅的解决方法~采用双链表去维护,溢出时切换链表

from multitimer.

IYQ-Github avatar IYQ-Github commented on July 4, 2024

if( (_time_ticks - target->time) < (UINT32_MAX)/2)
结构体多增加了一个target->time,用于在启动定时器时缓存,target->time = _time_ticks+ target->timeout;
target->timeout 值不能超过(UINT32_MAX)/2

from multitimer.

dongxinwanwu avatar dongxinwanwu commented on July 4, 2024

这个方案是否可行:timeout参数采用倒计时。
(1)在timer_init函数中timeout参数采用倒计时的方式,不需要算上当前的时间戳;
(2)在HAL_IncTick中每次减去tick,减到0时,增加一个标志位
(3)在timer_loop中检查标志位。

from multitimer.

askhua520 avatar askhua520 commented on July 4, 2024

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.

cancundiudiu avatar cancundiudiu commented on July 4, 2024

是不是可以换个思路,解决溢出的原因是以为溢出后会导致计时器不准。 可以将_timer_ticks定义为64位的,这样即使1ms累加一次,也要上亿年,设备也运行不到那个时候。

简单粗暴而不失优雅,哈哈, 在判断时再加个锁可以防止8位、16位、32位CPU的汇编中断问题。

from multitimer.

VanchTan avatar VanchTan commented on July 4, 2024

from multitimer.

ChunxingJin avatar ChunxingJin commented on July 4, 2024
    //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.

VanchTan avatar VanchTan commented on July 4, 2024

from multitimer.

flyiingdust avatar flyiingdust commented on July 4, 2024

推荐另外一种的解决方法: 不用设置标志,不用去考虑有符号无符号中间的转换。

定义一个获取时间长度的宏 TIME_PASSED
#define TIME_MAX 0xFFFFFFFFu /* 最大时间长度取决于使用的timer计时器长度,这里以32bit为例 */
#define TIME_PASSED(now, since) ((now) >= (since)) ? ((now) -(since)) : ((now) + (1 + TIME_MAX - (since)))

image

参考资料:《嵌入式系统设计与实践》5.4.2 p138

from multitimer.

VanchTan avatar VanchTan commented on July 4, 2024

from multitimer.

ZengXianCong avatar ZengXianCong commented on July 4, 2024
    //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.

VanchTan avatar VanchTan commented on July 4, 2024

from multitimer.

weiyang-github avatar weiyang-github commented on July 4, 2024

实际上这里可以直接使用减法,不用考虑溢出条件,无符号减法本身就是借位操作,比如说,我们定义两个32位无符号整数:
uint32_t a = x;
uint32_t b = y;
当x < y 时,a - b的计算结果实际上就是2^32 + (x - y)。

from multitimer.

VanchTan avatar VanchTan commented on July 4, 2024

from multitimer.

Related Issues (12)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.