uC/OS-II中的消息队列不是FIFO顺序吗?

huangapple go评论85阅读模式
英文:

Message queue in uC/OS-II is not FIFO order?

问题

我使用De10-Nano套件,已经成功地将uC/OS-II移植到Weston Embedded网站上的示例中。目前,我遇到了OS的消息队列API问题。

我的程序包含两个任务:生产者任务(优先级5)和消费者任务(优先级4)。我的目的是生产者任务通过消息队列向消费者任务发送消息。
在我第一次尝试时,生产者任务比消费者任务慢(生产者任务延迟100ms,消费者任务延迟10ms),消息队列正常工作,因为每当生产者任务发送消息(使用OSQPost),消费者任务都会接收到它(使用OSQPend)。
但是,当我更改了两个任务的时间片以使消费者任务运行得比生产者任务慢时,我期望消费者任务可以按FIFO顺序从消息队列中提取数据。然而,消费者任务提取的数据不按照该顺序排列。

以下是你的代码部分,我不会再次翻译它,但我会回答你的问题:

你的代码看起来是uC/OS-II的任务示例,它使用消息队列来在任务之间传递数据。根据你的描述,当生产者任务比消费者任务慢时,消息队列不按照FIFO顺序工作。

可能的原因是任务调度的机制。uC/OS-II是一个抢占式实时操作系统,任务的执行顺序是由任务的优先级决定的。当你让消费者任务比生产者任务运行得更慢时,消费者任务可能会在执行之前被抢占,从而导致不按FIFO顺序提取数据。

为了确保消息队列按照FIFO顺序工作,你可以考虑使用更高的任务优先级来确保生产者任务不被抢占。或者你可以在消费者任务中引入适当的延迟,以等待生产者任务发送完所有消息。

你还可以查看uC/OS-II的文档和配置,以确保消息队列的行为符合你的预期。

英文:

I'm using kit De10-Nano which has successfully ported uC/OS-II as in the example on the Weston Embedded website. Currently, I'm having a problem with message queue API of the OS.

My program contains two tasks: producer task (priority 5) and consumer task (priority 4). My purpose is that the producer task would send the message to the consumer task via a message queue.
In the first time I've tried, the producer task is slower than the consumer task (producer task is delayed for 100ms and consumer task is delayed for 10ms) and the message queu e works fine as every time producer task sends a message (using OSQPost), the consumer task receives it (using OSQPend).
However, when I change the time slice for both task to make the consumer task runs slower than the producer task, I've expected that the consumer task can extract data from the message queue in the FIFO order. However, the data extracted by the consumer task is not in that order.

Here is my code:

/* Includes ------------------------------------------------------------------*/
/* Standard C/C++ Library Includes */
#include <stdio.h>
#include <stdint.h>
/* User Library Includes */

/* Altera's Library Includes */

/* uC/OS-II's Library Includes */
extern "C"
{
#include "includes.h"
}
/* End of Includes ------------------------------------------------------------------*/

/* Private defines ---------------------------------------------------------*/
#define PRODUCER_TASK_STK_SIZE			(1024)
#define CONSUMER_TASK_STK_SIZE			(1024)

#define PRODUCER_TASK_PRIO				(5)
#define CONSUMER_TASK_PRIO				(4)

#define MSG_QUEUE_SIZE					(30)
/* USER CODE BEGIN PD */
static OS_STK		ProducerTaskStk[PRODUCER_TASK_STK_SIZE];
static OS_STK		ConsumerTaskStk[CONSUMER_TASK_STK_SIZE];
void*				myMsgQueue[MSG_QUEUE_SIZE];
static OS_EVENT*	msgQueueHandler;
static uint32_t		myProducerBuffer = 0;
static uint32_t		myConsumerBuffer = 0;
static uint8_t		errorCode;
static OS_Q_DATA	queue_data;
/* USER CODE END PD */

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
static void ProducerTask	(void  *p_arg);
static void ConsumerTask	(void  *p_arg);
/* USER CODE END PFP */

static void ProducerTask (void  *p_arg)
{
	while(1)
	{
		++myProducerBuffer;
		printf("Producer sent value: %d\n", myProducerBuffer);
		if(OSQPost(msgQueueHandler, (void*)&myProducerBuffer) != OS_ERR_NONE)
		{
			printf("Producer sent failed\n");
		}
		else
		{
			OSQQuery(msgQueueHandler, &queue_data);
			printf("Current queue size in producer: %d\n", queue_data.OSNMsgs);
		}
		OSTimeDlyHMSM(0u,0u,0u,10u);
	}
}

static void ConsumerTask  (void  *p_arg)
{
	uint32_t* pConsumerBuffer;
	while(1)
	{
		pConsumerBuffer = (uint32_t*)OSQPend(msgQueueHandler, 0, &errorCode);
		myConsumerBuffer = *pConsumerBuffer;
		printf("Consumer get value: %d\n", myConsumerBuffer);
		OSQQuery(msgQueueHandler, &queue_data);
		printf("Current queue size in consumer: %d\n", queue_data.OSNMsgs);

		OSTimeDlyHMSM(0u,0u,0u,100u);
	}
}

int main()
{
	OSInit();

    msgQueueHandler = OSQCreate(&myMsgQueue[0],MSG_QUEUE_SIZE);

	OSTaskCreateExt(ProducerTask,                               /* Create the producer task                              */
				    0,
				    &ProducerTaskStk[PRODUCER_TASK_STK_SIZE - 1u],
					PRODUCER_TASK_PRIO,
					PRODUCER_TASK_PRIO,
				    &ProducerTaskStk[0u],
					PRODUCER_TASK_STK_SIZE,
				    0u,
				    (OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR));

	OSTaskCreateExt(ConsumerTask,                               /* Create the consumer task                              */
				    0,
				    &ConsumerTaskStk[CONSUMER_TASK_STK_SIZE - 1u],
					CONSUMER_TASK_PRIO,
					CONSUMER_TASK_PRIO,
				    &ConsumerTaskStk[0u],
					CONSUMER_TASK_STK_SIZE,
				    0u,
				    (OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR));

	OSStart();

	while(1); /* Should never get here. */

	return -1;
}

And here is my result:
enter image description here

At first, producer sends 1 and consumer receives 1. And then, the consumer is delayed for 100ms and producer sends message from 2 to 10 to the message queue during this time. The consumer then extracts from the message queue and get value of 10 instead of 2. So I'm assuming that the message queue is not in FIFO order. Is there anything I've done wrong ? If not, why the message queue does not behave as I've expected ?

答案1

得分: 3

uC/OS-II消息队列在使用OSQPost()时是FIFO的。你遇到了不同的问题。

你的错误在于期望队列存储消息的拷贝,实际上队列存储的是消息的指针。你的代码重复地将相同的指针发布到myProducerBuffer变量,然后更改底层变量的值。你的队列并不包含所有不同值的拷贝。你的队列包含多个指向相同值的指针。每次你递增myProducerBuffer,你都在更改队列中所有指针指向的值。

如果你想要使用这样的队列,你需要单独分配消息,这样每条消息在队列中使用时都具有唯一的地址。

英文:

The uC/OS-II Message Queue is FIFO when you use OSQPost(). You have a different problem.

You're mistake is expecting that the Queue stores a copy of the message when the Queue actually stores a pointer to the message. Your code repeatedly posts the same pointer to the myProducerBuffer variable and then changes the value of the underlying variable. Your queue does not contain a copy of all the different values. Your queue contains multiple pointers to the same value. Each time you increment myProducerBuffer you are changing the value pointed to by all the pointers in the queue.

If you want to use a Queue like this you need to allocate the messages separately so each message has a unique address while it's in use by the Queue.

huangapple
  • 本文由 发表于 2023年4月11日 11:43:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/75982240.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定