FreeRTOS 中队列数组的问题
我正在构建一个 FreeRTOS 应用程序。我创建了一个模块,它从另一个模块注册 freeRTOS 队列句柄,当该模块中发生中断时,它会向所有注册的队列发送一条消息。但似乎我能够从队列发送消息,但无法在其他模块接收它。
这是我的代码。
远程模块:-
CanRxMsg RxMessage;
can_rx0_queue = xQueueCreate( 10, sizeof(CanRxMsg) ); // can_rx0_queue is globally defined
// Register my queue with can module
if (registerRxQueueWithCAN(can_rx0_queue) == -1)
{
TurnLedRed();
}
while(1)
{
if(can_rx0_queue){
while( xQueueReceive( can_rx0_queue, ( void * ) &RxMessage, portMAX_DELAY))
{
}
.....
这是注册模块
#define MAX_NUMBER_OF_RX_QUEUES 2
//xQueueHandle rxQueueStore[MAX_NUMBER_OF_RX_QUEUES];
typedef struct QUEUE_REGISTRY_ITEM
{
// signed char *pcQueueName;
xQueueHandle xHandle;
} xQueueRegistryItem;
xQueueRegistryItem rxQueueStore[MAX_NUMBER_OF_RX_QUEUES];
int numberOfQueuesRegistered;
#define cError -1
#define cSuccess 0
void processInterrupt()
{
for(int i=0; i < numberOfQueuesRegistered; i++)
{
if(xQueueSendFromISR(rxQueueStore[i].xHandle,(void *) &RxMessage,&tmp) != pdTRUE)
TurnLedRed();
if(tmp)resched_needed = pdTRUE;
}
portEND_SWITCHING_ISR(resched_needed);
}
int registerRxQueueWithCAN(xQueueHandle myQueue)
{
if(numberOfQueuesRegistered == MAX_NUMBER_OF_RX_QUEUES)
{
// Over Flow of registerations
TurnLedRed();
return cError;
}else
{
rxQueueStore[numberOfQueuesRegistered].xHandle = myQueue;
numberOfQueuesRegistered++;
}
return cSuccess;
}
要点:-
- xQuehandle 的类型定义为“void *”
- 如果删除注册内容,并且如果我通过 extern 获取指针,则代码可以工作,并且只需直接处理 xQueueSendFromISR 中的队列指针即可。
需要任何建议或信息吗?
I am building a FreeRTOS application. I created a module which registers a freeRTOS queue handle from another module and when an interrupt in this module module occurs, it sends a message to all the registered queues. But it seems I am able to send the message from the queue but not able to receive it at the other module.
Here is my code.
remote module:-
CanRxMsg RxMessage;
can_rx0_queue = xQueueCreate( 10, sizeof(CanRxMsg) ); // can_rx0_queue is globally defined
// Register my queue with can module
if (registerRxQueueWithCAN(can_rx0_queue) == -1)
{
TurnLedRed();
}
while(1)
{
if(can_rx0_queue){
while( xQueueReceive( can_rx0_queue, ( void * ) &RxMessage, portMAX_DELAY))
{
}
.....
Here is the registration module
#define MAX_NUMBER_OF_RX_QUEUES 2
//xQueueHandle rxQueueStore[MAX_NUMBER_OF_RX_QUEUES];
typedef struct QUEUE_REGISTRY_ITEM
{
// signed char *pcQueueName;
xQueueHandle xHandle;
} xQueueRegistryItem;
xQueueRegistryItem rxQueueStore[MAX_NUMBER_OF_RX_QUEUES];
int numberOfQueuesRegistered;
#define cError -1
#define cSuccess 0
void processInterrupt()
{
for(int i=0; i < numberOfQueuesRegistered; i++)
{
if(xQueueSendFromISR(rxQueueStore[i].xHandle,(void *) &RxMessage,&tmp) != pdTRUE)
TurnLedRed();
if(tmp)resched_needed = pdTRUE;
}
portEND_SWITCHING_ISR(resched_needed);
}
int registerRxQueueWithCAN(xQueueHandle myQueue)
{
if(numberOfQueuesRegistered == MAX_NUMBER_OF_RX_QUEUES)
{
// Over Flow of registerations
TurnLedRed();
return cError;
}else
{
rxQueueStore[numberOfQueuesRegistered].xHandle = myQueue;
numberOfQueuesRegistered++;
}
return cSuccess;
}
Few points:-
- xQuehandle is typdefed to "void *"
- The code works if remove the registration thing and just do with directly pointer of queue in xQueueSendFromISR if I take the pointer by extern.
Any advice or information required?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
乍一看,我看不出有什么明显的错误。问题可能出在您所显示的代码之外,例如如何声明 can_rx0_queue、如何输入中断、您使用哪个端口等。
有一个 FreeRTOS 支持论坛,可从 FreeRTOS 主页链接到 http://www.FreeRTOS.org
问候。
At first glance I cannot see anything obviously wrong. The problem might be outside of the code you have shown, like how is can_rx0_queue declared, how is the interrupt entered, which port are you using, etc.
There is a FreeRTOS support forum, linked to from the FreeRTOS home page http://www.FreeRTOS.org
Regards.
我认为理查德是对的。该问题可能不属于您在此处发布的代码范围内。
您是否对队列中等待的接收任务调用任何形式的暂停?当您对在队列上等待的任务调用 vTaskSuspend() 时,被挂起的任务将被移至 pxSuspishedTaskList,并且它将“忘记”它正在等待事件队列,因为该任务中的 xEventListItem 的 pvContainer任务将被设置为 NULL。
您可能想检查您的接收任务在等待队列时是否曾被挂起。希望有帮助。干杯!
I think Richard is right. The problem could be issues that are not within your code that you have posted here.
Are you calling any form of suspension on the receiving Task that is waiting on the Queue? When you invoke a vTaskSuspend() on a Task that is blocked waiting on a Queue, the Task that is suspended will be moved to the pxSuspendedTaskList and it will "forget" that it is waiting on an Event Queue because the pvContainer of xEventListItem in that Task will be set to NULL.
You might want to check if your receiving Task is ever suspended while waiting on a Queue. Hope that helped. Cheers!
你的共享内存至少应该被声明为易失性的:
否则编译器可能会优化对这些内存的读取或写入,因为它没有不同执行线程(在ISR和主线程之间)的概念。
我还记得一些 PIC C 运行时启动选项不应用静态数据的零初始化,以便最大限度地缩短启动时间,如果您使用此类启动,则应显式初始化
numberOfQueuesRegistered.我建议无论如何这样做都是一个好主意。
从您的代码中不清楚ISR中的
RxMessage
与“远程模块”中的RxMessage
不同;它们不应该被共享,因为这将允许 ISR 在接收线程处理数据时潜在地修改数据。如果它们可以共享,那么首先就没有理由有队列,因为共享内存和信号量就足够了。顺便说一句,永远不需要将指针转换为
void*
,并且通常应该避免这样做,因为它会阻止编译器发出如果您要传递指针以外的其他内容,则会出错。void*
的全部意义在于它可以接受任何指针类型。Your shared memory should at least be declared volatile:
otherwise the compiler may optimise out read or writes to these because it has no concept of different threads of execution (between the ISR and the main thread).
Also I recall that some PIC C runtime start-up options do not apply zero-initialisation of static data in order to minimise start-up time, if you are using such a start-up, you should explicitly initialise
numberOfQueuesRegistered
. I would suggest that to do so would be a good idea in any case.It is not clear from your code that
RxMessage
in the ISR is not the same asRxMessage
in the 'remote module'; they should not be shared, since that would allow the ISR to potentially modify the data while the receiving thread was processing it. If they could be shared, there would ne no reason to have a queue in the first place, since shared memory and a semaphore would suffice.As a side-note, there is never any need to cast a pointer to
void*
, and you should generally avoid doing so, since it will prevent the compiler from issuing an error if you were to pass something other than a pointer. The whole point of avoid*
is rather that it can accept any pointer type.