Using Task Notification as queue

I would like to use the task notification system as a way to send variables from one task to another.
Unfortunately, there is a problem that I cannot understand: with xTaskNotify(ToggleLED, LEDnumber, eSetValueWithOverwrite); I am trying to send a LED number to be toggled. The receiving task gets the Notification but always reacts as if the notified value was ‘0’ - every time the ‘0’ LED toggles. I am attaching the code, and would be grateful for any tips:

    void vSendLEDnumber(void* pvParamaters)
	 uint32_t LEDnumber = 0;
	 extern TaskHandle_t ToggleLEDonNotification;
	 //8 LEDs: pa4, pa0, pj4,ph5,pc4,ph13,pa7,pa10

		 /* send notification with LED number to be lit */
			 xTaskNotify(ToggleLEDonNotification, LEDnumber, eSetValueWithOverwrite);
			 if (LEDnumber > 7){LEDnumber = 0;}
			 	 vTaskDelay( 763 / portTICK_PERIOD_MS );

    void vToggleLEDonNotification(void* pvParamaters)
	 uint32_t receivedLEDno;
	 //8 LEDs: pa4, pa0, pj4,ph5,pc4,ph13,pa7,pa10
		 if(xTaskNotifyWait(0,0, &receivedLEDno, portMAX_DELAY) == pdTRUE){
			 //PINS_DRV_TogglePins(PTA, 0x1) ;
				   case '0': //PA4
					   PINS_DRV_TogglePins(PTA, 0x10) ;
				   case '1': //PA0
					   PINS_DRV_TogglePins(PTA, 0x1) ;
				   case '2': //PJ4
					   PINS_DRV_TogglePins(PTA, 0x10) ;
					   PINS_DRV_TogglePins(PTA, 0x10);

The code seems correct. At least regarding the notifications… :thinking:
Do you have a debugger attached ? Should be easy to verify the relevant lines of code.

Hint: Please enclose code blocks by 3 tildas (~~~) or alternatively 3 backticks (```) for better readability.

The code for case 0, case 2 and default is same: PINS_DRV_TogglePins(PTA, 0x10);. Is that intentional?

Also, what are the priorities for these 2 tasks?


thanks for the replies!
yes, the PJ4 LED on default is intetnional.
Both task have the same priority : 1.
There are no other tasks in the application so far.

Unfortunatelly my debugger stopped working - I guess I need to troubleshoot that first…

The line for case 0, case 2 and default is exactly the same:

PINS_DRV_TogglePins(PTA, 0x10);

How is it that one is PA4 and the other is PJ4?

yes, you are right. I made a mistake when copying the port names. There are different LEDs programmed in the application I am actually debugging. Unfrotunatelly I can’t edit the original post any more

The problem, however, is still there: every time only the ‘default’ case is being run. Furthermore it freezes after ca 100 iterations.

I tried debugging the code, and it is really weird: right after the task scheduler starts the debugger jumps around switch/case loop (however the LEDs don’t toggle) even without a notification being sent… When the first notification is sent, the value sent to consumer task seems to be ok (the receivedLEDno is 0), however the debugger freezes after the first notification. I tried moving the vTaskDelay at the begging for the sending task, and I also tried different stack sizes for the tasks,and setting the producer task to a higher priority. This didn’t help.
How does C interpret the variables in switch/case loop? Does case ‘0’ mean case [variable of type uint32_t var equals to 0], or does it use some other types?

my main.c:

TaskHandle_t ToggleLEDonNotification = NULL;

int main(void){
/* ....processor expert... and board initialization code... */
xTaskCreate(vToggleLEDonNotification, "ToggleLEDonNotificationTask", 128U, NULL, 1, &ToggleLEDonNotification);
xTaskCreate(vSendLEDnumber, "SendLEDnumber", 128U, NULL, 1, NULL);

The switch case (loop) is ok. Otherwise the compiler would tell you if it couldn’t implicitly convert the case constants matching the type of the switch variable.
Do you run the application with compile and linker optimization disabled (for GCC it’s the -O0 CFLAG and LTO shouldn’t be used for debugging, too) ?
Debuggers seem to unpredictable jump around the source code if debugging optimized builds because the 1:1 relation of source lines and executed assembly is then not longer fully provided.
Using -Og (for GCC) works in a acceptable way but it’s a compromise. For instance you won’t be able to inspect all local variables because they’re often optimized out by using registers.
Stack size of 128 words is not that much but could be sufficient because the code is not yet complex. And it really should be possible to step through those few lines of code with the debugger. You’d be completely lost once your app grows and get’s more complex without it.
Please also see this development hints you should consider to take into account.


Your program seems to be correct. You might want to try the first complete program in this post of my own, and then you can modify it to meet your needs. It works as expected on the ATmega328. The post is in spanish, but the programs there are mostly in english.

Thanks for all the responses.
The problem were the apostrophes next to the case command - it took the variable as char and evaluated to ASCII value of each number, which was never equal to the uint32 i was sending.

 case '0':

evaluates to ASCII for ‘0’

 case 0:

evaluates to int 0.

Removing all the apostrophes from switch/case loop solved the problem.