SMALL RTOS51是,请教中断FIFO插入消息“有关插入位置”的疑问【恢复】
陈明计先生的SMALL RTOS消息队列中(假如用户任务数<9)Buf=指示消息队列中消息的数目
buf=指示消息队列占用的内存空间(包括buf,buf,buf,buf)
buf=指示出队位置
buf=消息等待任务列表
(1)、在任务数<9时,出队位置=4,也就是说从buf开始取出消息。从P94页的图7.1和图7.2也可以看出,第一个装入消息的位置是从buf开始装入的。
(2)、但是在P103页的“中断中FIFO方式向消息队列发送消息”系统函数中
计算消息保存位置的代码如下:
temp=Buf+buf+1
即作者为了省去数据结构中队列入队指针,而采用“出队位置+消息数目”来确定入队位置
假如:目前消息队列刚刚被创建,此时buf=0,buf=4,当收到一个消息后,计算插入位置
那么temp=4+0+1=5
显示将第一条消息从buf位置装,不是从buf开始装入的吗?我的理解到底错在哪里?
在FIFO方式中,Buf指示下一个消息出队位置,而在取得消息时候,代码是:
/* 有,消息出队 */
Buf--;
Buf++;
if (Buf>= Buf)
{
#if OS_MAX_TASKS < 9
Buf = 4;
#else
Buf = 5;
#endif
}
*Ret = Buf];
也就是说,Buf+1才是真的出队位置,所以消息入队时候应该是:
/* 使用堆栈是为了使函数具有重入性 */
#ifdef __C51__
SP++;
*((uint8 data *)SP) = Data;
#endif
/* 计算新入队消息存储位置 */
temp = Buf + Buf + 1;
if (temp <= Buf || temp>= Buf)
{
#if OS_MAX_TASKS < 9
temp = temp - Buf + 4;
#else
temp = temp - Buf + 5;
#endif
}
/* 存储消息 */
#ifdef __C51__
Buf = *((uint8 data *)SP);
SP--;
也就是temp = Buf + Buf + 1;中的1来源吧
这样才能吻合。 我顶,我顶上去。 总之,遇到比较难理解的问题,只有一步一步的分析,就能解决自己的困惑的。 (3)任务取走第1条消息后,队列示意图
首先执行BUF++《【BUF=7】,由于BUF>=BUF,因此调整出队位置,调整后BUF=4
而BUF中存储的消息刚好是第一条插入的消息,然后将该消息(第一条插入的消息)返回给任务。
此时消息队列如下:
-------------------------------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| | | | | | | |---> Buf
| | | | | | | |
--------------------------------------------------
|
-----> 取出插入第一条消息后的出队位置
从上可以看出,消息队列中,目前已经没有消息了 (1)任务取走第3条消息后,队列示意图
首先执行BUF++《【BUF=6】
而BUF中存储的消息刚好是第二条插入的消息,然后将该消息(第二条插入的消息)返回给任务。
此时消息队列如下:
-------------------------------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| | | | | | | |---> Buf
| | | | | 消息1 | | |
--------------------------------------------------
|
-----> 取出插入第二条消息后的出队位置
从上可以看出,消息队列中,目前只有消息1(消息2已经被取走) 下面我们来分析任务等待消息过程。接上图,消息队列中已经插入了三条消息。
(1)任务取走第3条消息后,队列示意图
由于插入第三条消息后BUF=4,此时取出消息时,执行BUF++《【BUF=5】
而BUF中存储的消息刚好是第三条插入的消息,然后将该消息(第三条插入的消息)返回给任务。
此时消息队列如下:
-------------------------------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| | | | | | | |---> Buf
| | | | | 消息1 | | 消息2 |
--------------------------------------------------
|
-----> 取出最后插入第三条消息后的出队位置
从上可以看出,消息队列中,目前只有消息1和消息2(消息3已经被取走) 明天,此时请看任务等待消息过程的示意图。 (5)向消息队列插入第四条消息后,示意图如下:
-------------------------------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| | | | | | | |---> Buf
| | | | | 消息1 | 消息3 | 消息2 |
--------------------------------------------------
|
-----> 插入第三条消息后的出队位置
由于消息队列已经满(Buf>=Buf-4),无法插入第四条消息。
(3)向消息队列插入第二条消息后,示意图如下:
-------------------------------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| | | | | | | |---> Buf
| | | | | 消息1 | | 消息2 |
--------------------------------------------------
|
-----> 插入第二条消息后的出队位置
buf=2 消息数目
buf=5 出队位置 (4)向消息队列插入第三条消息后,示意图如下:
-------------------------------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| | | | | | | |---> Buf
| | | | | 消息1 | 消息3 | 消息2 |
--------------------------------------------------
|
-----> 插入第三条消息后的出队位置
buf=3 消息数目
buf=4 出队位置 其中Buf和buf前后紧挨着,构成环形队列。
(2)向消息队列插入第一条消息后,示意图如下:
-------------------------------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| | | | | | | |---> Buf
| | | | | 消息1 | | |
--------------------------------------------------
|
-----> 插入第一条消息后的出队位置
buf=1 消息数目
buf=6 出队位置 下面我们来分析一下LOFI(后进先出)方式,向消息队列发送消息
(a)假设任务数<9
(b)消息队列尺寸=7
(1)消息队列初始化后,示意图 如下:
-------------------------------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| | | | | | | |---> Buf
| | | | | | | |
--------------------------------------------------
|
-----> 初始化后的出队位置
buf=0 消息数目
Buf=7 消息队列尺寸
buf=4 出队位置
buf=消息等待任务列表 昨天晚上仔细分析了一下,终于把
(1)、任务等待消息
(2)、LIFO发送消息
搞清楚了,目前还剩下FIFO方式,怎么FIFO方式发送消息,不修正出队指针(Buf)呢?
唉,陈明计先生,为了节省一个入队指针Front,把程序代码搞得太难懂了。如果是一对Front(入队指针),
Rear(出队指针),程序代码就非常清楚了。
我顶! 没人帮我吗? 在普通的队列结构中。定义了队头指针QUEUE.Front和队尾指针QUEUE.Rear
同时为了达到环形缓冲区的效果,定义的队列长度=可以使用队列长度+1。
也就是说空闲一个单元,用于判断队列是否已满。
陈明计先生P94页的图7.1和图7.2很容易让人勿导
P94页的图7.1和图7.2也可以看出,第一个装入消息的位置是从buf开始装入的。
为什么取消息不从buf开始取,而是从buf取呢? P94页的图7.1和图7.2也可以看出,第一个装入消息的位置是从buf开始装入的。
为什么取消息不从buf开始取,而是从buf取呢? (3)在等待消息系统函数OSQPend()中,当等到消息后,为什么先出队指针buf先加一,然后从Buf]中取出消息呢? 我顶! 受教了
页:
[1]