嵌入式技术论坛
直播中

刘敏

7年用户 1170经验值
私信 关注
[问答]

请教各位rt-thread软件定时器大家一般怎么用 ?

请教各位,rt-thread软件定时器大家一般怎么用 ?
按文档说明 软定时器是在一个单独的任务里运行,不能在定时器里做会导致延时的操作,所以在项目中,需要定时器的时候,我在定时器 timeout 回调接口里面使用 rt_mq_send 发送一个消息给自定义的任务,在任务里接收这个消息以完成 实际的定时操作,不过发现跑一段时间后就会挂掉

2.jpg

跟踪进去一般是 定时器里发送 消息时出错

回帖(8)

mintsy

2023-4-20 16:14:13
如果你这么用,实际处理任务的线程除了等待定时器消息队列没有其它消息,如果你现在是这样的,还不如用 rt_thread_mdelay 呢。
软定时器的回调函数里执行的操作尽量不要时间超过 1 个tick ,超过就可能引起定时器逐渐后移。我有篇文章专门讲这个的。里面也提到了解决办法。
最后说这个挂断的问题。即便消息队列容量小,引起的后果也仅仅是丢 timeout 频次。高度怀疑消息队列用法错了。
举报

刘敏

2023-4-20 16:14:28
主任务里除了要接收这个定时器发来的定时时间到的消息外,还要接收处理其他的消息,所以用rt_thread_mdelay不太合适

手册中一再强调,定时器里不要有延时的操作,但像我这种应用(需要定时处理一些耗时的事情)应该怎么用定时器 ?

消息队列用错的问题,我们自己定义了一个固定的消息结构:

typedef struct
{
    UINT8        msgID ;
    UINT32        msgParam1;
    UINT32        msgParam2;
}taskMsg , *ptaskMsg ;
// 定时器里发送消息:
static  rt_err_t _send_mq_msg( rt_mq_t mq , UINT8 id, UINT32 p1, UINT32 p2)
{
    taskMsg msg = {0x00};
    //_ASSERT( !mq );
    if( !mq ) return -1 ;
    msg.msgID = id ;
    msg.msgParam1 = p1 ;
    msg.msgParam2 = p2 ;
    return rt_mq_send( mq , (void *) &msg,    sizeof(taskMsg) );
}
主任务申请消息队列:

if( _mq ) rt_mq_delete( _mq );
_mq = rt_mq_create("mq", sizeof(taskMsg), 8, RT_IPC_FLAG_FIFO );
_ASSERT( !_mq );
主任务等待消息队列:

while(1)
    {
        if( RT_EOK ==
            rt_mq_recv( _mq , (void *)&msg, sizeof(taskMsg), rt_tick_from_millisecond(1000)))
        {
            ....
        }
    }
举报

mintsy

2023-4-20 16:14:38
他强调不用执行长时间操作,就是因为,定时间隔会被偷偷延长。这个问题我解决了。
消息队列的用法也没错,看来你也没搞错消息体的大小。
timer 线程栈是多少?不会是 256 吧
举报

刘敏

2023-4-20 16:14:47
Timer任务 栈空间现在已经改成 8K了,还是一样会出错
举报

mintsy

2023-4-20 16:14:55
这些地方都没问题,那会是哪儿有内存溢出写了?
有地方内存非法写乱了你的消息队列池内存。
举报

梅利号

2023-4-20 16:15:03
你先检查一下你定时器的超时时间是多少,单位是时钟节拍(ms),然后看看你的消息队列创建了一个多大的,是不是定时器周期太快把mq发满了,然后你的recv端用的是阻塞读取,send这边也是阻塞发送,这就会导致卡死了。
举报

刘敏

2023-4-20 16:15:12
消息队列比较大,定时器周期最快30ms,定时器任务优先级默认很高,应该不是阻塞的问题,就算是阻塞也不应该导致出错
举报

梅利号

2023-4-20 16:15:22
这里说的阻塞指的是recv()和send()阻塞接收和发送。
看你目前的需求和其他楼层的回复,我觉得你可以直接用定时器来计数,这也是最普遍的用法,定时器超时设置成30ms,timeout()回调里只进行计数++,单独拿一个线程去检测数值到达你的要求然后再向消息队列发送数据。
如果这样还出错的的话,我觉得就应该是程序的其他地方问题,不是定时器的问题了。
我如果这样用的话就是在线程的开始创建一个定时器,用来计数,然后再线程的while中不断检测定时器计数的值,到达目的清空一次。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分