嵌入式RTOS生产者和消费者有多种类型的消息[关闭]
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了嵌入式RTOS生产者和消费者有多种类型的消息[关闭]相关的知识,希望对你有一定的参考价值。
许多RTOS消息传递示例显示生成器生成像int32这样简单的东西和读取它的消费者。这很简单,因为您总是知道什么类型,因此将从队列(或其他消息传递缓冲区)中获得什么大小。
考虑一个从GPS读取数据的RTOS线程的情况。 GPS可能有许多类型的消息。您无法保证邮件何时到达,邮件的顺序或邮件的大小。每条消息都有许多字段,每条消息都可以表示为结构。
该GPS处理生成器RTOS线程将理想地解析数据流,然后将数据传递出去,以便消费者线程可以容易地读取GPS数据。
假设FreeRTOS或CMSIS RTOS。如何最好地安排这种安排?将使用哪些原语?从根本上讲,我正在寻找的是一种干净的方法,可以从生产者线程中传递几种不同类型的不同大小的结构,并在消费者中读取它们。
您可以考虑使用指向消息的指针队列,而不是消息队列本身。这样,队列中的每个项目都是固定大小(指针的大小),而不管消息如何。
该技术确实需要仔细的资源管理,以确保在接收器完成之前不会修改,删除或重用消息。您需要一个allocate-enqueue-dequeue-deallocate机制。
例如,给定:
enum eMessageType
{ AType,
BType
};
struct GenericMessage
{
eMessageType type;
char payload[0] ; // Note GCC zero-length array extension
};
struct A { struct GenericMessage,
uint32_t foo;
};
struct B { struct GenericMessage,
uint8_t bar;
};
然后发件人可能会有(伪代码):
struct A* messageA = allocateMessageA( AType, 0x12345678 ) ;
struct B* messageB = allocateMessageB{ BType, 0x12 } ;
sendGeneric( genericQ, messageA ) ;
sendGeneric( genericQ, messageB ) ;
和接收者:
struct GenericMessage* message_ptr = receiveGeneric( genericQ ) ;
switch( message_ptr->type )
{
case AType:
{
struct A* = (struct A*)message_ptr ;
uint32_t payload = message_ptr->payload ;
...
deallocateMessageA( message_ptr ) ;
}
break;
case BType:
{
struct B* = (struct B*)message_ptr ;
uint8_t payload = message_ptr->payload ;
...
deallocateMessageB( message_ptr ) ;
}
}
我没有定义的分配/释放功能的细节。一种简单的方法是使用固定块内存池。如果您的RTOS不提供这些,则一个简单的实现是在池中具有指向消息的队列,每个消息类型一个队列/池。要分配,只需从队列中取消一条消息,从相关消息池中获取指针,然后通过返回指向队列的指针来解除分配。
请注意,某些RTOS允许直接发送可变长度消息 - 例如,您可以为队列分配内存池,并在发送时指定长度,而不是在创建队列时指定长度。然而,接收器必须能够接收尽可能大的消息。
FreeRTOS文档与QueueSets一起讨论了该问题。 (请参阅“使用队列集的替代方法”一节中的https://www.freertos.org/Pend-on-multiple-rtos-objects.html)。基本上,我们的想法是使用枚举来识别缓冲区中不同类型的消息。
对于缓冲区类型,您可以使用枚举和结构联合的组合。
struct A {uint32_t foo;};
struct B {uint8_t bar;};
enum T {AType, BType};
struct GenericMessage{
T type;
union{
struct A a;
struct B b;
};
};
然后您可以区分消息如下:
void handleGenericMessage(struct GenericMessage* msg){
switch(msg->type){
case AType:
handleA(msg->a);
break;
case BType:
handleB(msg->b);
break;
}
以上是关于嵌入式RTOS生产者和消费者有多种类型的消息[关闭]的主要内容,如果未能解决你的问题,请参考以下文章