How to send a pointer to a character string to a task queue?

m4l490n wrote on Monday, February 16, 2015:

Hello everybody.

I need to send some ascii character strings from one task to another.

I need to send not the string but the address of the first character (as a reference to the string) to another task. The reason I want to send “a reference” to the string and not the string is because I may have a string as long as 250 characters, or maybe more, and I don’t want the queue send routine to be copying all the 250+ characters every time a message has to be sent.

As I’m dealing with shared memory then there is no problem about sending pointers and this is a more efficient approach since the FreeRTOS queue send routine just copies 4 bytes (the size of the pointer to the first characters from the string to be sent) instead the n characters in the string.

The function for sending this messages is as follows:


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 *));
}

The “System_Events_Send_to_Task” is a system task I created and I use it to send events to any task. Since the events may have data then this routine helps to abstract the process. Don’t pay attention to everything as I just put this for you to see this “intermediate” step in the character string sending.

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;
}

Ok then, the problem I’m facing is that in the receiving task I’m getting an “Invalid Address” when triyng to get the address sent in the “TR_Trace” routine. I get this Invalid address error when single stepping in the debug session.

Here is the way I’m trying to recover the 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;
        }
     }
  }

  ...

}

Maybe I’m not dereferencing properly or I don’t know what is happening.

Any Ideas?

Regards.

bowerymarc wrote on Monday, February 16, 2015:

You probably want to do this:

System_Events_Send_to_Task(SYSTEM_TASK_TR_Trace_Task,
TR_EV_SEND_TRACE_MSG,
msg_location, sizeof(char *));

the value of msg_location is the address of the string.

also you are creating a local variable ‘event’ that then disappears off the stack once the function exits, but you’re queueing the address of it, which will probably be garbage once it’s dequeued.

M

On Feb 16, 2015, at 5:16 PMEST, Manuel Malagon m4l490n@users.sf.net wrote:

Hello everybody.

I need to send some ascii character strings from one task to another.

I need to send not the string but the address of the first character (as a reference to the string) to another task. The reason I want to send “a reference” to the string and not the string is because I may have a string as long as 250 characters, or maybe more, and I don’t want the queue send routine to be copying all the 250+ characters every time a message has to be sent.

As I’m dealing with shared memory then there is no problem about sending pointers and this is a more efficient approach since the FreeRTOS queue send routine just copies 4 bytes (the size of the pointer to the first characters from the string to be sent) instead the n characters in the string.

The function for sending this messages is as follows:

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 *));
}
The “System_Events_Send_to_Task” is a system task I created and I use it to send events to any task. Since the events may have data then this routine helps to abstract the process. Don’t pay attention to everything as I just put this for you to see this “intermediate” step in the character string sending.

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;
}
Ok then, the problem I’m facing is that in the receiving task I’m getting an “Invalid Address” when triyng to get the address sent in the “TR_Trace” routine. I get this Invalid address error when single stepping in the debug session.

Here is the way I’m trying to recover the 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;
    }
 }

}

}
Maybe I’m not dereferencing properly or I don’t know what is happening.

Any Ideas?

Regards.

How to send a pointer to a character string to a task queue?

Sent from sourceforge.net because you indicated interest in https://sourceforge.net/p/freertos/discussion/382005/

To unsubscribe from further messages, please visit https://sourceforge.net/auth/subscriptions/

m4l490n wrote on Tuesday, February 17, 2015:

also you are creating a local variable ‘event’ that then disappears off the stack once the function exits, but you’re queueing the address of it, which will probably be garbage once it’s dequeued.

This is not the case because the “event.event_id” is never corrupted. When dequeueing I always have the “.event_id” right but I don’t know why the “.data” is always 0.

And the freertos queue routine is supposed to copy the contents of this local variable so that is another reason why that may not be the problem.

davedoors wrote on Tuesday, February 17, 2015:

Is it because of this line -

System_Events_Send_to_Task(SYSTEM_TASK_TR_Trace_Task,
TR_EV_SEND_TRACE_MSG,
&msg_location, sizeof(char *));

msg_location is a pointer that points to a string. You are passing the address of the variable (&msg_location), not the address the pointer is pointing to.