硬汉嵌入式论坛

 找回密码
 立即注册
查看: 3887|回复: 7
收起左侧

[μCOS-III] 任务内建消息队列大小为0时仍能处理消息的问题。

[复制链接]

31

主题

53

回帖

146

积分

初级会员

积分
146
发表于 2016-4-8 13:26:57 | 显示全部楼层 |阅读模式
问题描述:创建一个按键处理任务,指定其内建消息队列数量为0,按照ucos的API说明,此参数为0时,不能接收消息,如下图:
1.png


按键处理任务用pend等待其他任务发送过来的按键消息,然后处理该消息,如下图:
2.png


由中断服务函数检测到按键键值,用post函数向按键处理函数发送消息,如下图:
3.png


问题:按照API说明,OS_MSG_QTY参数指定了该任务通过消息队列能够接收的消息的最大数目, 设置为0时,禁止该任务接收消息。
理解起来也就是即使中断服务函数向该任务发送消息,也不会得到响应,因为该任务的消息队列最大数目是0.
但是实测代码时:按键处理任务可以正常工作。如下图:
4.png


原因何在? OS_MSG_QTY参数设置为0,并不是我有意为之,而是创建任务的时候忘记了指定该参数,并且任务正常工作了。
但是回头检查代码时忽然发现这个参数是0,按理说不能处理按键消息才对。。。有朋友遇到过这个问题吗,能否给与解答?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
111540
QQ
发表于 2016-4-8 13:47:21 | 显示全部楼层

Re:UCOSIII,任务内建消息队列大小为0时仍能处理消息的问题。

你得OSTaskQPost使用错误,第二个参数是变量地址。修改后试试。
回复

使用道具 举报

31

主题

53

回帖

146

积分

初级会员

积分
146
 楼主| 发表于 2016-4-8 14:01:04 | 显示全部楼层

回 eric2013 的帖子

eric2013:你得OSTaskQPost使用错误,第二个参数是变量地址。修改后试试。 (2016-04-08 13:47)
谢谢,但是这个问题的原因不在于此,解释如下:

如果要发送的消息是一个结构体,那么就必须要发送这个结构体变量的地址,
接收这个消息的任务,再将这个指针强转换为结构体类型,需要注意的是,在消息被发送和被任务处理完成期间,结构体指针变量所指向的内存空间不能被修改或释放。

如果要发送的消息是个变量,例如本例中的键值,指针本身就可以表示消息。

你指出的这个问题,我觉得跟我描述的这个问题是不相关的。
谢谢你的解答。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
111540
QQ
发表于 2016-4-8 14:31:37 | 显示全部楼层
1. 刚刚没有注意你的任务函数的使用,这种使用方式,第三个参数设置的这个地址下的变量个数将没有意义,这个不说了,不是问题重点。
2. 可以认为是uCOS-III的一个bug,如果情况是一个任务在等待消息,另一个任务或者中断是事后发消息的话,uCOS-III的处理方式是把这个任务从挂起列表删除。
    直接给这个任务的控制块发消息,没有再通过msg pool
======================================================================
发送消息的中断函数会调用OS_POST函数的处理:

#if (OS_MSG_EN == DEF_ENABLED)
                 p_tcb->MsgPtr  = p_void;                       /* Deposit message in OS_TCB of task waiting            */
                 p_tcb->MsgSize = msg_size;                   /* ... assuming posting a message                       */

#endif
#if (OS_CFG_TS_EN == DEF_ENABLED)
                 p_tcb->TS      = ts;
#endif
#if (OS_CFG_PEND_MULTI_EN == DEF_ENABLED)
             }
#endif
             if (p_obj != DEF_NULL) {
                 OS_PendListRemove(p_tcb);                      /* Remove task from wait list(s)                        */
#if (OS_CFG_DBG_EN == DEF_ENABLED)
                 OS_PendDbgNameRemove(p_obj,
                                      p_tcb);
#endif
             }
=======================================================================
挂起等待的任务直接通过这种方式读取:
             p_void      = OSTCBCurPtr->MsgPtr;
            *p_msg_size  = OSTCBCurPtr->MsgSize;


这样处理的弊端就是完全没有经过MSG消息池的FIFO去操作了,所以设置消息个数不起作用了。
回复

使用道具 举报

31

主题

53

回帖

146

积分

初级会员

积分
146
 楼主| 发表于 2016-4-8 19:41:11 | 显示全部楼层

回 eric2013 的帖子

eric2013:1. 刚刚没有注意你的任务函数的使用,这种使用方式,第三个参数设置的这个地址下的变量个数将没有意义,这个不说了,不是问题重点。
2. 可以认为是uCOS-III的一个bug,如果情况是一个任务在等待消息,另一个任务或者中断是事后发消息的话,uCOS-III的处理方式是把这个任务从挂起列 .. (2016-04-08 14:31)
对ucos源码理解还停留在仅仅会使用的水平,一时半会还读不懂。

不过还想继续讨论一下:

你的回答是否可以这样理解,一个处在阻塞状态等待一个消息的任务1,不会丢失任务2向任务1内建消息队列发送过来的第一个消息,即使任务1的内建消息队列的容量为0。
按照你上面的说法,是因为此时ucos会绕开msg pool,数量0不再起作用,那么,是否可以认为任务内建消息队列的容量设置为0和设置为1是等效的?
因为内建消息队列容量为1的任务,其行为,看上去和上面应该是一致的。

另一种情况,任务1的消息队列容量为0,如果任务1的内建消息队列中已经存在一个从任务2发送过来的消息,但是由于任务1的优先级较低,还没有得到运行的机会时,任务2或者其他任务又向任务1的消息队列中发送了新的消息,那么这些消息都会丢失。

这个行为,也跟队列容量为1的任务行为一致,所以,是否可以认为:任务内建消息队列的容量设置为0和设置为1是等效的?

是否还可以进一步推论:ucos这么做是为了防止队列容量为0的任务永远处于阻塞状态而采取得一种措施,而不是ucos的一个bug?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
111540
QQ
发表于 2016-4-8 19:48:49 | 显示全部楼层

回 ggafish 的帖子

ggafish:对ucos源码理解还停留在仅仅会使用的水平,一时半会还读不懂。

不过还想继续讨论一下:

....... (2016-04-08 19:41) 
可以这么理解哦。[s:142]
回复

使用道具 举报

31

主题

53

回帖

146

积分

初级会员

积分
146
 楼主| 发表于 2016-4-8 19:51:06 | 显示全部楼层

回 eric2013 的帖子

eric2013:可以这么理解哦。[s:142] (2016-04-08 19:48) 
谢谢你的解答,找个能一起讨论的问题的人真难。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
111540
QQ
发表于 2016-4-9 01:28:28 | 显示全部楼层

回 ggafish 的帖子

ggafish:谢谢你的解答,找个能一起讨论的问题的人真难。 (2016-04-08 19:51) 
不客气,楼主还有什么问题了,一起交流,共同学习。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-11-1 07:00 , Processed in 0.467588 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表