Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT




Loading

vTaskNotifyGive works from a task NOT within an ISR (vTaskNotifyGiveFromISR)

Posted by simointe on May 31, 2016

(TMS570LC4, nested interrupt, C++)

I have a task waiting on a notification, I aim for a semaphore-like binary behaviour.

The stuff works fine as long as I call xTaskNotifyGive( taskHandle ) within another task (not ISR). The waiting task awake from : ulTaskNotifyTake( pdTRUE, portMAX_DELAY );

Now I want to do the same thing from my ISR (InterruptCan1High), I call : xHigherPriorityTaskWoken = pdFALSE; vTaskNotifyGiveFromISR( taskHandle, &xHigherPriorityTaskWoken ); portYIELDFROMISR(xHigherPriorityTaskWoken);

...and the waiting task never wake. Interrupt comes and comes, multiple vTaskNotifyGiveFromISR() are done.

I have try both ways to define my ISR:

__interrupt void InterruptCan1High( void ) { ...; //code above }

or

NESTEDINTERRUPTENTRYIRQ( InterruptCan1High ) { ...; //code above } NESTEDINTERRUPTEXITIRQ( InterruptCan1High )

Nothing happen.

Regards.

Simon


vTaskNotifyGive works from a task NOT within an ISR (vTaskNotifyGiveFromISR)

Posted by rtel on May 31, 2016

I don't know what NESTEDINTERRUPTENTRY_IRQ() is, so I should stick to the __interrupt method of defining the interrupt handler.

Are you sure taskHandle used in the interrupt handler is the correct handle.

If you step though the call to vTaskNotifyGiveFromISR() in the debugger, what do you see happening - does it try to unblock a task?


vTaskNotifyGive works from a task NOT within an ISR (vTaskNotifyGiveFromISR)

Posted by simointe on June 8, 2016

NESTEDINTERRUPTENTRY_IRQ() is some assembler code we defined in order to manage nesting interrupt. But I don't use it for rtos tick interrupt and the swi interrupt cause it seems conflict with freeRtos stuff. We have CANBUS interrupt using NO rtos stuff at all and I use these define in order it works. I'll test what you talk about stepping through vTaskNotifyGiveFromISR(), I'll be right back.

~~~

define NESTEDINTERRUPTENTRY_IRQ( fn )
  _Pragma ("FUNC_CANNOT_INLINE")           \
  static void internalIrq##fn (void)

//----------------------------------------------------------------------------- /// brief Define adding the necessary assembly instructions to exit a nested /// interrupt. It needs to be a define because it can not be a function /// call. /// Restore LR /// Disable IRQ (IRQ Mode) /// Restore SPSRirq to LR /// Copy LR to SPSRirq //-----------------------------------------------------------------------------

define NESTEDINTERRUPTEXIT_IRQ( fn )

Pragma ("CODESTATE(32)") void fn (void) { { asm( " ADD SP, SP, #8 " ); asm( " SUB LR, LR, #4 " ); asm( " SRSFD #0x12 ! " ); asm( " CPS #0x13 " ); asm( " PUSH {R0-R12} " ); asm( " FMRX R5,FPEXC " ); asm( " PUSH {R5} " ); asm( " FMRX R5,FPSCR " ); asm( " PUSH {R5} " ); asm( " FSTMDBD SP!, {D0-D7} " ); asm( " MOV R1, SP " ); asm( " AND R1, R1, #4 " ); asm( " SUB SP, SP, R1 " ); asm( " PUSH {R1, R14} " ); } internalIrq##fn(); { asm( " POP {R1, LR} " ); asm( " ADD SP, SP, r1 " ); asm( " FLDMIAD SP!, {D0-D7} " ); asm( " POP {R5} " ); asm( " FMXR FPSCR, R5 " ); asm( " POP {R5} " ); asm( " FMXR FPEXC, R5 " ); asm( " POP {R0-R12} " ); asm( " CPS #0x12 " ); asm( " RFEFD SP! " ); } } ~~~


vTaskNotifyGive works from a task NOT within an ISR (vTaskNotifyGiveFromISR)

Posted by rtel on June 8, 2016

I can't recall if the TMS570 port support interrupt nesting or not, but know the generic ARM Cortex-R port does. If the port does implement interrupt nesting it could be dangerous to have your own code on some interrupts and use FreeRTOS code on other interrupts if those two interrupts could nest with each other (don't know that for a fact, hence I say 'could').


vTaskNotifyGive works from a task NOT within an ISR (vTaskNotifyGiveFromISR)

Posted by user1966 on June 9, 2016

Hi! (PIC24, MPLAB X, FreeRTOS 9.0.0)

I have the same issue, actually it seems that none of the FromISR calls are working, I have tried at least task notification, semaphores, queues and deferred interrupt handling.

My setup is very simple, just one simple task having only waiting point and a separate timer interrupt routine (60 ms interval) trying to wake it up. Tick is 1 ms. The code is straight from the text book. Using debugger I can see that it looks like the FromISR is working correctly but the task is not unblocked. The task and the interrupt priorities are the same (1). Maybe there is something very basic missing from my setup. Is there something specific in the configuration file that needs to be added to make it work? This is my freertos configuration .h ~~~

define MPLABPIC24PORT
define configUSE_PREEMPTION 1
define configUSEIDLEHOOK 0
define configUSETICKHOOK 0
define configTICKRATEHZ ( ( portTickType ) 1000 )
define configCPUCLOCKHZ ( ( unsigned long ) 16000000 ) /* Fosc / 2 */
define configMAXPRIORITIES ( ( unsigned portBASETYPE ) 4 )
define configMINIMALSTACKSIZE ( 115 )
define configTOTALHEAPSIZE ( ( size_t ) (6000) )
define configMAXTASKNAME_LEN ( 4 )
define configUSETRACEFACILITY 0 // For tracing
define configUSE16BIT_TICKS 1
define configIDLESHOULDYIELD 1

/* Co-routine definitions. */

define configUSECOROUTINES 0
define configMAXCOROUTINE_PRIORITIES ( 2 )

/* Set the following definitions to 1 to include the API function, or zero to exclude the API function. */

define INCLUDE_vTaskPrioritySet 1
define INCLUDE_uxTaskPriorityGet 0
define INCLUDE_vTaskDelete 1
define INCLUDE_vTaskCleanUpResources 1
define INCLUDE_vTaskSuspend 1
define INCLUDE_vTaskDelayUntil 1
define INCLUDE_vTaskDelay 1
define configUSE_MUTEXES 1
define configKERNELINTERRUPTPRIORITY 0x01

~~~


vTaskNotifyGive works from a task NOT within an ISR (vTaskNotifyGiveFromISR)

Posted by rtel on June 10, 2016

Have you followed the instructions on the documentation page for the PIC24, and used the examples provided as a template?

The instructions from the web page (which is somewhat historic):

"Interrupt service routines that cannot cause a context switch have no special requirements and can be written as per the compiler documentation.

Interrupt service routines that can cause a context switch must execute with priority portKERNELINTERRUPTPRIORITY, and only call taskYIELD() at the very end of the service routine after the interrupt source has been cleared. See the file serial.c included in the demo application for an example."

The example provided:

~~~ void attribute((interrupt, autopsv)) _U2TXInterrupt( void ) { signed char cChar; portBASETYPE xHigherPriorityTaskWoken = pdFALSE;

/* If the transmit buffer is full we cannot get the next character. Another interrupt will occur the next time there is space so this does not matter. / IFS1bits.U2TXIF = serCLEAR_FLAG; while( !( U2STAbits.UTXBF ) ) { if( xQueueReceiveFromISR( xCharsForTx, &cChar, &xHigherPriorityTaskWoken ) == pdTRUE ) { / Send the next character queued for Tx. / U2TXREG = cChar; } else { / Queue empty, nothing to send. */ xTxHasEnded = pdTRUE; break; } }

if( xHigherPriorityTaskWoken != pdFALSE ) { taskYIELD(); } } ~~~

I just tried this in the simulator and it seems to work.


vTaskNotifyGive works from a task NOT within an ISR (vTaskNotifyGiveFromISR)

Posted by user1966 on June 10, 2016

Thanks for your reply.

I think I have followed the instructions as such. I'm not using the PIC24 demo project, my HW is something else than the explorer board.

It's getting a bit weird. I played with xQueueSendFromISR and if I go through the code line-by-line (using step-into in MPLABX) it works. But if I let the code run freely, it doesn't. I followed the code and found strange behaviour in queue.c at line 1258. I assume that the scheduler works correctly and calls the xQueueGenericReceive to wake up the task. Something happens at line 1258 when it uses taskENTERCRITICAL() macro. By using "step-into" the debugger passes the taskENTERCRITICAL and enters the next code line after at line 1264 and eventually comes out of the xQueueReceive in the task as expected. But if I use "step-over" or set a breakpoint at line 1264, it will never reach that line (just stays running and never wakes up the task). Here's the FreeRTOS code for taskENTER_CRITICAL()

void vPortEnterCritical( void ) { portDISABLE_INTERRUPTS(); uxCriticalNesting++; }

portDISABLE_INTERRUPTS() macro is something like this:

SETCPUIPL( configKERNELINTERRUPTPRIORITY ); __asm volatile ( "NOP" )

and finally SETCPUIPL macro is:

#define SET_CPU_IPL(ipl) { \` unsigned int DISIsave; DISIsave = DISICNT; asm volatile ("disi #0x3FFF"); SRbits.IPL = ipl; _builtinwriteDISICNT( DISIsave); } (void) 0

Is there something I need to correct for the taskENTER_CRITICAL() for this port?


vTaskNotifyGive works from a task NOT within an ISR (vTaskNotifyGiveFromISR)

Posted by rtel on June 11, 2016

Please post your ISR code.


vTaskNotifyGive works from a task NOT within an ISR (vTaskNotifyGiveFromISR)

Posted by user1966 on June 11, 2016

Here it is. The tcounter1 and tcounter2 are UINT32 and just for debugging purposes.

/* _T1Interrupt ISR */

void attribute((interrupt, auto_psv)) _T2Interrupt( void )

{

/* Description Interrupt service routine for Timer2 interrupt

Return values
    None

*/

/* Data structures */

BaseType_t xHigherPriorityTaskWoken;
TaskHandle_t task_handle;
UINT8 messu;

/* Code */

messu = 0xa;

t_counter1++;

xHigherPriorityTaskWoken = pdFALSE;

xQueueSendFromISR( xQueue, &messu, &xHigherPriorityTaskWoken );


// reset timer interrupt flag and return from ISR
IFS0bits.T1IF = 0;

if (xHigherPriorityTaskWoken == pdTRUE) {
    t_counter2++;
    portYIELD();
}

}

vTaskNotifyGive works from a task NOT within an ISR (vTaskNotifyGiveFromISR)

Posted by richard_damon on June 11, 2016

One thing I see is it is installed for T2, but mesing with T1


vTaskNotifyGive works from a task NOT within an ISR (vTaskNotifyGiveFromISR)

Posted by user1966 on June 12, 2016

Thanks Richard, that seemed to solve the problem! I was using old ISR template and didn't check the interrupt flag setting at all (assumed it to be correct one). I was just too blind to see the solution.


vTaskNotifyGive works from a task NOT within an ISR (vTaskNotifyGiveFromISR)

Posted by simointe on June 13, 2016

Now it works, I have to admit that I don't know exactly why. But when the error was there, stepping through xTaskGenericNotifyFromISR() the problem was that the original state of the thread is taskNOTIFICATIONRECEIVED instead of taskWAITINGNOTIFICATION and the task was NOT unblock by the call. ~~~ xTaskGenericNotifyFromISR().. if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) ~~~


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS