xMessageBufferReceive time bug xTaskNotifyFromISR

dungeonlords wrote on Saturday, August 10, 2019:

MessageBufferHandle_t onlyForTestBuf;   //this is global var

//at task
onlyForTestBuf = xMessageBufferCreate(24);
  for(;;)
  {		
      xMessageBufferReceive(onlyForTestBuf, ( void * )myMessage, sizeof(myMessage), **portMAX_DELAY** );
		BeepMini();
  } 
  
void TIM3_IRQHandler(void)
{
	xTaskNotifyFromISR(MotorsActionsHandle, PWMIR_FAULT, eSetValueWithOverwrite, NULL);
	TIM3->SR = 0;     
  while(TIM3->SR &= TIM_SR_CC1IF);
  //HAL_TIM_IRQHandler(&htim3);
}

I don’t use onlyForTestBuf at any place! No more can add into onlyForTestBuf! But I hear Beep because of my function BeepMini(). But if I delete xTaskNotifyFromISR from my interrupt no more beep. Problem at O3 and O0 too. I use HAL and I don’t forget to check TIM3 global interrupt (at NVIC page) “Uses FreeRTOS functionality”, also there are no dynamic interrupt priority changes in my code.

STM32F401xE,KEIL ARM COMPILER 5

Full proj https://yadi.sk/d/oiabwcgqJjvHMA

rtel wrote on Saturday, August 10, 2019:

So if I understand correctly xMessageBufferReceive() should never return because nothing is ever sent to onlyForTestBuf(), yet BeepMini() seems to execute - indicating that xMessageBufferReceive() did infact return.

You are sending a notification to MotorsActionsHandle(), is that the function that is calling BeepMini()?

If you place a break point on BeepMini(), does it actually get hit? If not, is anything else calling BeepMini()? Or could anything else accidentally write to whatever peripheral is used to generate a beep?

Have you read through https://www.freertos.org/FAQHelp.html and in particular https://www.freertos.org/RTOS-Cortex-M3-M4.html ? As always it is best to be using the latest version of FreeRTOS (or at least V10.2.0) as the newer the version the more configASSERT() there are that help catch errors in interrupt setup misconfigurations.

richard_damon wrote on Saturday, August 10, 2019:

I’m wondering if it could be the case that if a task is sitting in a wait for Message Buffer, and the task gets sent a notifiaction, if that could cause the xMessageBufferReceive to return with a timeout error instead of going back into the wait.

I try to program defensively and still test for timeout errors even when the wait is an infinite wait. A simple test would be to test the return value of the xMessageBufferReceive() and only beep on success to see if that is the issue.

dungeonlords wrote on Sunday, August 11, 2019:

Yes, xMessageBufferReceive() should never return because nothing is ever sent to onlyForTestBuf(), yet BeepMini() seems to execute - indicating that xMessageBufferReceive() did infact return.

I think I understand problem. Look at FreeRTOS code stream_buffer.c:

size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, ...
/* Wait for data to be available. */
....
( void ) xTaskNotifyWait( ( uint32_t ) 0, UINT32_MAX, NULL, xTicksToWait );

In my interrupt I send via xTaskNotifyFromISR!

And as said Richard Damon if my code will be:

MessageBufferHandle_t onlyForTestBuf;   //this is global var

//at task
onlyForTestBuf = xMessageBufferCreate(24);
size_t xReceivedBytes;
  for(;;)
    xReceivedBytes = xMessageBufferReceive(onlyForTestBuf, ( void * )myMessage, sizeof(myMessage), 100 );
		if( xReceivedBytes > 0 ) 
			BeepMini();
		}

no beep.

Now you can see xTaskNotifyFromISR makes xMessageBufferReceive return with zero bytes of data.

May be should change at stream_buffer.c
xTaskNotifyWait( ( uint32_t ) 0, UINT32_MAX, NULL, xTicksToWait );
to
vTaskDelay(xTicksToWait);
?

richard_damon wrote on Sunday, August 11, 2019:

Yes, MessageBuffers use the Notify feature to signal that data is available (but don’t set any bits so any bits set with a notify do remain for the task to see later. The issue is that the MessageBuffer receive routine when it is woken from the Wait, if it still doesn’t have the needed data, doesn’t check if it woke up from a timeout (so it should report that back) or if it was woken up be some other Notify, and thus it could possible continue to wait for the remaining time (but still allow for the abort delay function to abort the waiting.)

Because of the xTaskAbortDelay case, fixing the behavior may be difficult (FreeRTOS might need to have a flag in the TCB to let parts know that an AbortDelay has been done to prevent resuming blocking from ‘spurious’ wakeups, which might impose execessive costs.

An alternative would be a clear indication in the MessageBufferReceive documentation that other task notifications might abort the Receive early, so tasks using it do need to check the return value and understand that a ‘timeout’ might not mean the full time has elapsed, but the task might be able to handle that other notification and resume the receive.

I can actually see cases where this behavior that in your case is undesired (but simple to test for) could actually be very useful to allow a task to do a form of multiple source wait (able to respond to a number of different notifcations or a message).

rtel wrote on Sunday, August 11, 2019:

That’s why I asked if it was the same task.

I actually plan, if feasible, to extend the task notification function so there is an array of them, rather than just one, then you can use different indexes for different purposes.

dungeonlords wrote on Sunday, August 11, 2019:

“I can actually see cases where this behavior that in your case is undesired (but simple to test for) could actually be very useful to allow a task to do a form of multiple source wait (able to respond to a number of different notifcations or a message).”
For Direct To Task Notifications there are a lot of: xTaskNotifyGive(), vTaskNotifyGiveFromISR(), ulTaskNotifyTake(), xTaskNotify(), xTaskNotifyAndQuery(), xTaskNotifyAndQueryFromISR(), xTaskNotifyFromISR(), xTaskNotifyWait(), xTaskNotifyStateClear().

Please do not add xMessageBufferReceive to this list. But I’m interested in the situations you are talking about. Can you give some examples?

Also this situation depreciates xTicksToWait param. xTicksToWait no more ticks to wait.

“I actually plan, if feasible, to extend the task notification function so there is an array of them, rather than just one, then you can use different indexes for different purposes.”
It will be interesting. Good luck

richard_damon wrote on Sunday, August 11, 2019:

First, this absolutely does not depreciates the xTickToWait paramater, that still h as a very vital role, the when the task blocks for a notification it really wants to block and not need to keep polling for an event (so other tasks can run), but it also may want to wait for just a limited period of time, and if no event occured, do some other action, and perhaps then go back and wait again.

As to multiple sources, the list you gave is basically all the variants of the Direct to Task API, which has a single base Notify function (and its ISR twin), and then a number of specializations that just effectively provide a value for the eAction parameter and maybe default values for some of the others, but all are just variations of the Notify operation.

Many people have wanted ways to wait for events from many sources, and we have the QueueSet to manage data from multiple Queues and Semaphores. With a Message Buffer there is less need for multiple Queues, as you can make make the messages that are put on the queue indicate what type of message it is and then send them all on the same MessageBuffer. What this doesn’t provide is a way to handle mixing in some Semaphores in this mix. You could create a whole message for each Semaphore, but that adds complexity at the sending end to need to actually build the messages. Letting the program use the Direct to Task Notifications as an array of Semaphores, and the task waiting on the message, gets woken up on sending one of the notifications and on getting the 0 return on the MessageBufferReceive dosn’t process the message not received, and then checks the notification and finds it.

This does slightli complicate programs that don’t use that feature, but not by that much, it does say that they need to check the return value of the Receive, but they really should be anyway out of general principle. if you want the equivalent of the max delay case, just do a

    while(!xMessageBufferReceive( ... portMAX_DELAY)) continue;

and that statement won’t move on until a message is received.

Note this issue only happens if a task does both MessageBuffers and Direct to Task Notifications, and I really suspect that most of the time, if that notification occurs, the task wants to handle the notification, not continue to wait for the message.

Look at the example that started the thread, A timer signaled a motor fault to the task, I would expect that that is likely wanted to be processed now, rather than waiting for some message, which by the portMAX_DELAY period, may well be a long time in comming (if you were expecting it soon, there would be a timeout to handle it getting lost).