Received the exact length of data when buffer size was less in xQueueReceive of messageQueue

sasikalaswathi wrote on Monday, October 14, 2019:

In message queue, I was created the queue of item size as 10 bytes.

  1. Inside the send function, send the data of correct size(10 bytes).
    Inside receive function, I allocated the receiver buffer size was 5 bytes only. But in this case after received the message, whileC I tried to print the value received, the printed message size was 10 bytes.How this is possible?

  2. Could you clarify what happened when tried to receive more data than allocated data item size?

Attached the code for reference

rtel wrote on Monday, October 14, 2019:

In a queue the item size is set when you create the queue and the buffer
into which you receive from the queue must be large enough to hold that
number of bytes. If you want to queue variable size messages then you
can queue pointers or structures as described in the [free to download]
book https://www.freertos.org/Documentation/RTOS_book.html . If you
only have one sender and one receiver then you can use a message buffer
in place of a queue as message buffers allow for variable size messages.
However your post doesn’t actually state your intention so maybe you
are trying to do something else?

sasikalaswathi wrote on Monday, October 14, 2019:

Hi Richard,
Thanks for the response.
Actually I want to know the failure cases of API functions, xQueueReceive and xQueueSend. For that, I tried with different scenarios of sending and receiving length values. While doing that scenario’s, I am wondering how receiving of allocated item size was successful when buffer size inside receiver function was lesser than that. To know about that I am asked.

Could you help me with at what are the cases the message queue’s sending and receiving API might get failed?

richard_damon wrote on Monday, October 14, 2019:

xQueueReceive (and Send) ASSUMES the buffer provided is at least the size given in the Create call, if it isn’t it will just overwrite the data that follows, possibly causing all sorts of problems. (Send won’t overwrite anything, just copy some ‘garbage’)

There is no way for that function to know how big the buffer is, so it can’t check for that.

If you want to send varying length messages, you can use the MessageBuffer API, in which case you tell the function how big the message is to send and how big the buffer to receive is.

rtel wrote on Monday, October 14, 2019:

The queue semantics are to set the item size in advance, then ensure the
buffer you pass is at least large enough. Therefore the queue receive
function does not have a buffer size parameter and if you pass in a
buffer that is too small you will end up with data corruption. If I
may, I think it would be faster for you to look at the source code and
step through the function than to ask a question here and have somebody
reply - you will be able to see what the code does quite easily I think.

sasikalaswathi wrote on Tuesday, October 15, 2019:

Hi Richard,
Thanks for the response.

sasikalaswathi wrote on Tuesday, October 15, 2019:

Hi Richard,

I created the queue item size of 100 bytes, Inside the send function sent 100 bytes successfully. Inside the receive function, char array was declared as size of 50 bytes.

While running the above configured program, program hangs at the hardfault handler function hits.

You told one thing about the queue receive function in above post,
There is no way for that function to know how big the buffer is, so it can’t check for that.
But here, it hangs at the hardfault handler.

I tried the same in the case of 10 bytes of queue item size. But at that time, no fault received. Eventhough the buffer size of 8 bytes, then anyway 10 bytes was received.

The code: for reference.

Global_Queue=xQueueCreate(1,100);
if( Global_Queue != NULL )
{
xTaskCreate( send_task, “Task 1”, 512,NULL, 1,NULL );
xTaskCreate( receive_task, “Task 12”, 512, NULL, 1, NULL );
vTaskStartScheduler();
}

void send_task(void *p)
{
BaseType_t xStatus;
const char buffer2[100]=“Task1Task1Task1Task1Task1Task1Task1Task1Task1Task1Task1Task1Task1Task1Task1Task1Task1Task1Task1END\r\n”;
while(1)
{
xStatus = xQueueSend(Global_Queue,&buffer2,1);
if(xStatus==pdPASS)
{
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_7,0);
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_8,1);
}
}
}
void receive_task(void *p)
{
char rx[50];
BaseType_t xStatus;
const TickType_t xTicksToWait = pdMS_TO_TICKS( 1UL );
while(1)
{
xStatus = xQueueReceive(Global_Queue, &rx,xTicksToWait);
if(xStatus == pdPASS)
{
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_7,1);
}
}
}

richard_damon wrote on Tuesday, October 15, 2019:

Putting 100 bytes into a 50 byte buffer is going to overwrite a lot more that putting 10 bytes into an 8 byte buffer. You get a fault if something ‘important’ was overwritten cause a major error in your program. The extra 2 bytes likely just changed the value of an adjacent variable, which might not be noticed.

sasikalaswathi wrote on Wednesday, October 16, 2019:

  1. I tried the same in the case of 10 bytes of queue item size. But at that time, no fault received. Eventhough the buffer size of 8 bytes, then anyway 10 bytes was received.

In the above case, I set the buffer size of 0 bytes (char rx[0]) inside the receiver function, then receiving of 10 bytes was successful. in this case eventhough I set the buffer size as 0 bytes, 10 bytes received successfully.

  1. a) But in the case : sent 100 bytes. Inside the receive function, char array was declared as size of 50 bytes.
    While I tried to set the buffer size of 60,70,80 and 90 bytes, data received and no hardfault detected. In the case(buffer size as 60) almost 40 bytes skipped , but here no hardfault occurs.
    My doubt was there is no default case / what are the cases hardfault occurs?

b) Inside the sender function, before sending data to queue, see the return values of uxQueueMessagesWaiting API which returns the values 0 and 1 then hardfault occurs. While tried to send the value to queue eventhough it was full (Queuecreate(1,100)), hardfault occurred? is that correct?

richard_damon wrote on Wednesday, October 16, 2019:

No, the case of receiving 10 bytes into a too small buffer was not ‘successful’ in the full sense, because some memory outside the buffer was overwritten. It may at first appear ‘successful’ because nothing immediately went wrong, but computers are not designed to catch every error.

For the 100 byte case, whent he receive buffer was 50, the 50 bytes overwritting apparently over write far enough that the machine detects the problem, perhaps it is because you overwrote all of the used stack space and then went past the end of the stack and clobbered some important data that causes the hardfault. Just because a slight larger receive buffer (but still too small) doesn’t immediately hardfault doesn’t mean that it ‘worked’, just that it didn’t damage something important enough to cause the immediate hardfault. In some ways the immediate hardfault is fortunate, as it is occuring close to the point of the error, often these sorts of errors cause problems that might not be seen for a while, so hard to trace to their sources.

One thing to watch out for is that just because something SEEMS to work, doesn’t mean it was done right. C, the language you are using when you are using FreeRTOS was designed to favor performance over safety, so it won’t detect many cases where you ‘break the rules’.

sasikalaswathi wrote on Wednesday, October 16, 2019:

Learn lot of things new here. Thank you Richard for reply