为什么我在 FreeRTOS 中出队时得到一个空指针?
Why am I getting an empty pointer when dequeuing in FreeRTOS?
我需要将一些 ascii 字符串从一个任务发送到另一个任务。
我需要发送的不是字符串,而是第一个字符的地址(作为对字符串的引用)到另一个任务。我想将 "a reference" 发送到字符串而不是字符串的原因是因为我可能有一个长达 250 个字符或更多的字符串,并且我不希望队列发送例程复制所有每次必须发送消息时超过 250 个字符。
因为我正在处理共享内存,所以发送指针没有问题,这是一种更有效的方法,因为 FreeRTOS 队列发送例程只复制 4 个字节(指向第一个字符的指针的大小)要发送的字符串)而不是字符串中的 n 个字符。
发送这条消息的函数如下:
static char* msg_location = NULL; /* global memory so its contents doesn't corrupt */
void TR_Trace(const char *const string)
{
size_t stringSize = 0;
/* Get the string size to create the dinamyc memory storage */
stringSize = strlen(string);
msg_location = pvPortMalloc(stringSize + 1);
/* Now copy the text to the newly created buffer */
strcpy(msg_location, string);
System_Events_Send_to_Task(SYSTEM_TASK_TR_Trace_Task,
TR_EV_SEND_TRACE_MSG,
msg_location, sizeof(char *));
}
"System_Events_Send_to_Task" 是我创建的系统任务,我用它向任何任务发送事件。由于事件可能有数据,因此此例程有助于抽象流程。什么都别管,我只是给大家看看发送字符串中的这个"intermediate"步骤
bool System_Events_Send_to_Task(System_Tasks_T dest_task,
System_Events_IDs_T event_id,
void *data, size_t size)
{
bool event_sent = false;
portBASE_TYPE send_status;
System_Event_T event;
if(NULL != System_Queue_Handles_Array[dest_task])
{
/* Fill the system event struct with the data from the parameters */
event.event_id = event_id;
event.data = data;
event.data_size = size;
/* Send the event to the selected Events Queue */
send_status = xQueueSend(System_Queue_Handles_Array[dest_task],
&event,
(QUEUE_SEND_WAIT_TIME / portTICK_RATE_MS));
/* Check if the event was sent */
if (pdPASS == send_status)
{
event_sent = true;
}
else
{
event_sent = false;
}
}
else
{
/* If the queue is not created yet then the transfer is signaled as failed */
event_sent = false;
}
return event_sent;
}
好吧,我面临的问题是,在接收任务中,当尝试获取 "TR_Trace" 例程中发送的地址时,我得到一个 "Invalid Address"。在调试会话中单步执行时出现此无效地址错误。
这是我尝试恢复地址的方式。
void TR_Trace_Task(void *pvParameters)
{
System_Event_T bb_event; /**< Variable to read the events received by the task */
char* temp_ptr;
...
while(1)
{
xQueueReceive(TraceMessageQueue, &bb_event, portMAX_DELAY);
switch (bb_event.event_id)
{
case TR_EV_SEND_TRACE_MSG:
{
temp_ptr = (char*)bb_event.data; /* THE PROBLEM IS HERE! */
strcpy(DMATxBuffer, (const char *)temp_ptr);
DmaChnStartTxfer(TRACE_TX_DMA_CHANNEL, DMA_WAIT_NOT, TX_TRANSMISSION_RETRIES);
/* The memory allocated and being pointed to by the var "temp_ptr"
* is freed */
vPortFree((void *)temp_ptr);
break;
}
default:
{
break;
}
}
}
...
}
当我调试时,我注意到如果我在 temp_ptr = (char*)bb_event.data; 处放置一个断点,调试器会显示.data 是空的,我不知道为什么。
有什么想法吗?
此致。
我没有看到任何危险信号,几乎没有什么要检查的。
- 确保您创建的队列使用相同的 System_Event_T 结构。
- 确保 System_Queue_Handles_Array[dest_task] 正在传递到 TraceMessageQueue 队列。
- 检查 pvPortMalloc(stringSize + 1) 是否返回 NULL 或一些奇怪的内存位置。
此代码与您在 FreeRTOS 支持论坛上发布的代码略有不同,其中建议原因是您排队的是指针的地址,而不是指针的值。哪个代码出现问题 - 其他论坛代码上的代码 - 因为这里的代码似乎没有同样的问题。
我需要将一些 ascii 字符串从一个任务发送到另一个任务。
我需要发送的不是字符串,而是第一个字符的地址(作为对字符串的引用)到另一个任务。我想将 "a reference" 发送到字符串而不是字符串的原因是因为我可能有一个长达 250 个字符或更多的字符串,并且我不希望队列发送例程复制所有每次必须发送消息时超过 250 个字符。
因为我正在处理共享内存,所以发送指针没有问题,这是一种更有效的方法,因为 FreeRTOS 队列发送例程只复制 4 个字节(指向第一个字符的指针的大小)要发送的字符串)而不是字符串中的 n 个字符。 发送这条消息的函数如下:
static char* msg_location = NULL; /* global memory so its contents doesn't corrupt */
void TR_Trace(const char *const string)
{
size_t stringSize = 0;
/* Get the string size to create the dinamyc memory storage */
stringSize = strlen(string);
msg_location = pvPortMalloc(stringSize + 1);
/* Now copy the text to the newly created buffer */
strcpy(msg_location, string);
System_Events_Send_to_Task(SYSTEM_TASK_TR_Trace_Task,
TR_EV_SEND_TRACE_MSG,
msg_location, sizeof(char *));
}
"System_Events_Send_to_Task" 是我创建的系统任务,我用它向任何任务发送事件。由于事件可能有数据,因此此例程有助于抽象流程。什么都别管,我只是给大家看看发送字符串中的这个"intermediate"步骤
bool System_Events_Send_to_Task(System_Tasks_T dest_task,
System_Events_IDs_T event_id,
void *data, size_t size)
{
bool event_sent = false;
portBASE_TYPE send_status;
System_Event_T event;
if(NULL != System_Queue_Handles_Array[dest_task])
{
/* Fill the system event struct with the data from the parameters */
event.event_id = event_id;
event.data = data;
event.data_size = size;
/* Send the event to the selected Events Queue */
send_status = xQueueSend(System_Queue_Handles_Array[dest_task],
&event,
(QUEUE_SEND_WAIT_TIME / portTICK_RATE_MS));
/* Check if the event was sent */
if (pdPASS == send_status)
{
event_sent = true;
}
else
{
event_sent = false;
}
}
else
{
/* If the queue is not created yet then the transfer is signaled as failed */
event_sent = false;
}
return event_sent;
}
好吧,我面临的问题是,在接收任务中,当尝试获取 "TR_Trace" 例程中发送的地址时,我得到一个 "Invalid Address"。在调试会话中单步执行时出现此无效地址错误。 这是我尝试恢复地址的方式。
void TR_Trace_Task(void *pvParameters)
{
System_Event_T bb_event; /**< Variable to read the events received by the task */
char* temp_ptr;
...
while(1)
{
xQueueReceive(TraceMessageQueue, &bb_event, portMAX_DELAY);
switch (bb_event.event_id)
{
case TR_EV_SEND_TRACE_MSG:
{
temp_ptr = (char*)bb_event.data; /* THE PROBLEM IS HERE! */
strcpy(DMATxBuffer, (const char *)temp_ptr);
DmaChnStartTxfer(TRACE_TX_DMA_CHANNEL, DMA_WAIT_NOT, TX_TRANSMISSION_RETRIES);
/* The memory allocated and being pointed to by the var "temp_ptr"
* is freed */
vPortFree((void *)temp_ptr);
break;
}
default:
{
break;
}
}
}
...
}
当我调试时,我注意到如果我在 temp_ptr = (char*)bb_event.data; 处放置一个断点,调试器会显示.data 是空的,我不知道为什么。
有什么想法吗?
此致。
我没有看到任何危险信号,几乎没有什么要检查的。
- 确保您创建的队列使用相同的 System_Event_T 结构。
- 确保 System_Queue_Handles_Array[dest_task] 正在传递到 TraceMessageQueue 队列。
- 检查 pvPortMalloc(stringSize + 1) 是否返回 NULL 或一些奇怪的内存位置。
此代码与您在 FreeRTOS 支持论坛上发布的代码略有不同,其中建议原因是您排队的是指针的地址,而不是指针的值。哪个代码出现问题 - 其他论坛代码上的代码 - 因为这里的代码似乎没有同样的问题。