Task notifications

This is a follow up question to RTOS basics

I am trying to use a new task to relieve the extent of processing in an ISR from another task.
REPMTask (priority 3)

    vTaskNotifyGiveFromISR(PRINTERTaskHandle, &printerTaskWoken);

    portYIELD_FROM_ISR(printerTaskWoken);
    ulTaskNotifyTake(pdTRUE, 0);


PrinterTask (priority 2)
void PrinterTask(void * pvParameters)
{
    for(;;){
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        PRINTHEAD_CountAndPrint();
        xTaskNotifyGive(REPMTaskHandle);
    }

}

When I use this combination of priorities and API, the printer task does not print. Other tasks work OK until the ISR tries to switch to printer task. And then nothing else executes.

I still have holes in how I understand this, I appreciate some added pointers.

Thanks,
Priya

So if I understand correctly, everything runs as expected until the interrupt that sends a notification to the printer task runs - after which nothing appears to run.

As before, you can run under the control of the debugger, then when the error occurs, pause the debugger to see what is executing. Maybe you are just in an an assert()?

Also, once you print out the message you send a notification to another ask - REPMTaskHandle - what does that task do? Can you show the code for that too please.

You can use three back ticks “```” before and after a code block to have the code formatted as code in the post. I will edit the post above to do that so you can see what I mean.

Richard,
Thank you for your reply. Seems like the printer task never gets the notification from the ISR. I stepped into
vTaskNotifyGiveFromISR(PRINTERTaskHandle, &printerTaskWoken);

and it skips this conditional check:
if( eOriginalNotifyState == eWaitingNotification )
It also did not step into
configASSERT( xTaskToNotify );

As far as what the REPM task do after returning from printer task:


    portYIELD_FROM_ISR(printerTaskWoken);
    ulTaskNotifyTake(pdTRUE, 0);

  //  PRINTHEAD_CountAndPrint();

    REPM_CTRL_CountAndStop();
    if(g_bShortLongTicketDetectionEnabled)
    	{
    	if(g_bShortLongTicketMeasurementStart)
    		RecordTicketLength (TRUE);
    	else
    		RecordTicketLength (FALSE);

    	}```



Thanks,
Priya



			{

What is eOriginalNotifyState set to before the notification is given?

I don’t really udnerstand the REPM task structure - the task should be in an infinite loop as it must not be allowed to run off the end of its implementing function. Also, what is the portYIELD_FROM_ISR() call at the top - that should only be called from an interrupt service routine. Finally, what is the call to ulTaskNotifyTake() for? Is that where it waits for the notification - because the block time in your call is 0.

Did you read the book I linked to in your previous thread?

Richard,
I am switching tasks from an ISR in the REPM task in order to reduce the extent of processing happening in it.

vTaskNotifyGiveFromISR(PRINTERTaskHandle, &printerTaskWoken);
portYIELD_FROM_ISR(printerTaskWoken);

The structure of the printing task has been posted earlier. When this task is ready to give back control to the REPM task,is the best place to use

ulTaskNotifyTake(pdTRUE, 0);
the main loop of the REPM_task?

Initial value of eOriginnalNotifyState is eNotWaitingNotification and then changes to eNotified.

Trying to piece this together. Is this what you have?

void vMyISR( void )
{
    // Unblock the printer task implemented by PrinterTask().
    vTaskNotifyGiveFromISR(PRINTERTaskHandle, &printerTaskWoken);

    portYIELD_FROM_ISR(printerTaskWoken);
    ulTaskNotifyTake(pdTRUE, 0);  //!! WHAT IS THIS DOING?
}

void PrinterTask(void * pvParameters)
{
    for(;;){
        // Wait for interrupt to notify this task.
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        
        // Perform operation.
        PRINTHEAD_CountAndPrint();
        
        // Unblock the REPMTask.
        xTaskNotifyGive(REPMTaskHandle);
    }
}

void REPMTask( void * pvParameters )
{
    REPM_CTRL_CountAndStop();
    if(g_bShortLongTicketDetectionEnabled)
        {
        if(g_bShortLongTicketMeasurementStart)
            RecordTicketLength (TRUE);
        else
            RecordTicketLength (FALSE);

        }```
        
    //!! IF THIS IS A TASK THEN MUST NOT DROP OFF
    // THE END OF THE FUNCTION (as documented in
    // the book and website).  IF THIS IS JUST A
    // FUNCTION AND NOT A TASK THEN THE LINE:
    // xTaskNotifyGive(REPMTaskHandle); ABOVE WOULD
    // SEEM WRONG.
}
void RepmTask(void * pvParameters)
{


	for( ;; )
	{
      
        }
void My_ISR(void){
     //CALL THE RELEVENT PRINT ROUTINE
    vTaskNotifyGiveFromISR(PRINTERTaskHandle, &printerTaskWoken);

    portYIELD_FROM_ISR(printerTaskWoken);
    ulTaskNotifyTake(pdTRUE, 0);

  

    	}
}
}

My_ISR happens from REPM_Task. I switch control to printer task. Printer task returns control to REPM_task. While I can put all of the ISR processing after the task switch in the printer task, the execution needs to return to whatever happens after the ISR. Or it needs to return to the ISR itself to wrap up the ISR.

Currently the code you have put in the REPM main loop is still inside the ISR, it is possible to move it to the printer task.

I need to understand the right set of APIs to use, where/how to use them. Inside an ISR, what is the best blocking time to use to wait for a return notification?

Thanks,
Priya

The code you posted has one function defined inside another function. I’m surprised that even compiles. Are you sure your code is compiling?

In any case, ISRs (Interrupt Service Routines) are asynchronous - they occur when an interrupt is accepted by the processor, at which point the execution flow jumps from whatever was executing to the interrupt service routine which then runs to completion before execution returns to whatever was executing previously. This is a function of the hardware - there is nothing in software that can effect it. Interrupts to not execute in tasks.

I may be mistaken, but from reading your posts it doesn’t seem that you understand how the processor works. I would recommend writing some basic examples with just a main() function that sets up an interrupt and an interrupt handler to learn some of the basics of embedded programming before attempting to use the RTOS - the processor vendor and compiler vendor probably have lots of examples already. Then, once you have the basics, read the book that is freely available for you before you attempt to use the RTOS. The book also contains lots of examples.

This is code in production. Thank you for your reply.

The code as presented, with the ISR function defined within the task function is NOT valid C, but maybe some extension you are using.

Ths ISR including the statement ulTaskNotifyTake(pdTRUE, 0); breaks the API rules of FREERTOS (that ISRs are not allowed to call functions that don’t end in FromISR.

If this is the actual code you have in production, it is broken.