xQueueReceive holds one item sometimes

I have UART transmittion, i use queue to send data from UART IRQ with xQueueSendFromISR and task with xQueueReceive to receive data. Data is struct with char *data; size_t len; only.
And this works fine for 90% time, but some times xQueueReceive don’t want to receive item from queue, it like hold it inside, but when next UART payload is sended from IRQ, Iam receive the old “holded” data first, and after that present data comes. Does anyone can help me with this strange problem.

First question, do you have confit ASSERT defined and stack overflow checking enabled to catch configuration errors.

Second, does the ISR properly use the was woken flag from toxQueueSendFromISR call?.

No, configASSERT off, and configCHECK_FOR_STACK_OVERFLOW off too.
I check returning value from xQueueSendFromISR and its good.

Not the return value, but the xHigherPriorityTaskWasWoken parameter, if it sets that you need to invoke the scheduler at the end of you ISR or the task that was woken might not get run for a while.

Always recommend to make use of the facilities available to help debugging, like configASSERT and stack overflow checking.

Hi Alex,

it would be nice if you provided some more useful info voluntarily…

What is the call you use to create the queue with? In particular what queue depth?

Can it simply be the case that the task that does the queue receive is starved out by higher priority threads and thus doesn’t have a chance to unqueue the items timely? Remember that the very purpose of a multi entry queue is like a shock absorber; if the characters come in faster than they can be processed, the queue buffers them. That is all defined and desired behavior.

Sorry if this should be a shot in the dark, but your problem description is farily generic, so we have to make wild guesses until we get more info.

You might want to trace the flow of events with counters throughout your system to get a better idea of the timing involved. Using tracealyzer is also a good idea.

I rty to give you pieces of code from which you must understand the logic of work.

struct {
    char *data;                            
    size_t len;                           
} recv_t;

uart3RxQueue = xQueueCreate(15, sizeof(recv_t));

Uart3RxQueueParserHandle = sys_thread_new("Uart3RxQueueParser", Uart3RxQueueParser, NULL, 1000, 7);

//RX TASK

void Uart3RxQueueParser(){
	recv_t recv_buff2;
	BaseType_t QueueGood;

	while(1){
		ack_cnt2++;
		do
			QueueGood = xQueueReceive(uart3RxQueue, &recv_buff2, portMS_TO_TASK_TICKS(5000));//portMAX_DELAY);
//when issue happens i get here but dont receive data
		while(QueueGood != pdTRUE);

		if (QueueGood != pdTRUE) {
			uartRecvQueueErr++;
		}

		receiving_cnt++;

		parse_received(&recv_buff2);
		free(recv_buff2.data);
        ...
        }
}

//UART IRQ


volatile recv_t recv_buff;
volatile char uartRxStaticBuff[UART3_RXBUF_SIZE];
volatile uint32_t uartRxChar=0;

void UART3_IRQHandler(void) {
uartRxStaticBuff[uartRxChar] = (char)UART_REG;
uartRxChar++;
...
   if (uartRxChar == UART3_RXBUF_SIZE-1) {
	recv_buff.len = UART3_RXBUF_SIZE;
	uartRxChar=0;

	uartQueueSended++;

	recv_buff.data = (char*)malloc(recv_buff.len);
	memcpy(recv_buff.data,&uartRxStaticBuff,recv_buff.len);

	QueueGood = xQueueSendFromISR(uart3RxQueue, &recv_buff, &xHigherPriorityTaskWoken);

	uartQueueSended2++;

	if (QueueGood != pdTRUE) {
		error_rxQueue_cnt++;
	}
	portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
  }
...
}

so most of time uartQueueSended,uartQueueSended2,receiving_cnt are the same, but after issue happens receiving_cnt becomes smaller by 1

Are you using a version of malloc that is ISR safe? It normally isn’t

its generic malloc, but before i used fixed array for recv_buff.data and don’t call malloc in irq, but result stay same.
Also i forgot to tell that i use LPC1788 with FreeRTOS V8.2.0.
I hardly know FreeRTOS, so i think may be important to mention this defines(because its related to IRQ):
configPRIO_BITS = 5
IRQ_PRI_RTOS_KERNEL = 31
IRQ_PRI_MAX_SYSCALL_RTOS = 15
configKERNEL_INTERRUPT_PRIORITY = (IRQ_PRI_RTOS_KERNEL << (8 - configPRIO_BITS))
configMAX_SYSCALL_INTERRUPT_PRIORITY = (IRQ_PRI_MAX_SYSCALL_RTOS << (8 - configPRIO_BITS))

IRQ_PRI_UART3 = 4

Your use of malloc there likely risks corrupting the heap, as it is almost certainly not save to use in an ISR then.

The code looks ok, I presume that error_rxQueue_cnt stays 0, as if a xQueueSendFromISR fails you will increment it.