为什么我在 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 是空的,我不知道为什么。

有什么想法吗?

此致。

我没有看到任何危险信号,几乎没有什么要检查的。

  1. 确保您创建的队列使用相同的 System_Event_T 结构。
  2. 确保 System_Queue_Handles_Array[dest_task] 正在传递到 TraceMessageQueue 队列。
  3. 检查 pvPortMalloc(stringSize + 1) 是否返回 NULL 或一些奇怪的内存位置。

此代码与您在 FreeRTOS 支持论坛上发布的代码略有不同,其中建议原因是您排队的是指针的地址,而不是指针的值。哪个代码出现问题 - 其他论坛代码上的代码 - 因为这里的代码似乎没有同样的问题。