vTaskSetTimeOutState(…) and xTaskCheckForTimeOut(…) from interrupt

Can the vTaskSetTimeOutState(…) and xTaskCheckForTimeOut(…) APIs be called by an interrupt service routine?

vTaskSetTimeOutState(…) and xTaskCheckForTimeOut(…) from interrupt

I don’t think so, they would need critical sections, which need to be done differently in ISRs. In general, if it doesn’t say FromISR, it isn’t usable from an ISR.

vTaskSetTimeOutState(…) and xTaskCheckForTimeOut(…) from interrupt

I figured it was like that, is there a way to make these APIs safe?

vTaskSetTimeOutState(…) and xTaskCheckForTimeOut(…) from interrupt

You need to change the critical section macros, as per the example for vTaskSetTimeOutState() below.
void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
{
UBaseType_t uxSavedInterruptStatus;

    configASSERT( pxTimeOut );
    uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
    {
        pxTimeOut->xOverflowCount = xNumOfOverflows;
        pxTimeOut->xTimeOnEntering = xTickCount;
    }
    portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
}

vTaskSetTimeOutState(…) and xTaskCheckForTimeOut(…) from interrupt

ok, thanks a lot for the solution. Is there a way to add this API to FreeRTOS without having to modify the “tasks.c” file? for example by creating a “tasks_helper.c” file. Because if I create an additional *.c I can’t access the “xNumOfOverflows” and “xTickCount” variables

vTaskSetTimeOutState(…) and xTaskCheckForTimeOut(…) from interrupt

You can add your code into a header file called freertostaskcadditions.h, then set configINCLUDEFREERTOSTASKCADDITIONSH to 1 in FreeRTOSConfig.h to have the header file included at the bottom of the source file so you have access to the private data. https://sourceforge.net/p/freertos/code/HEAD/tree/tags/V10.2.1/FreeRTOS/Source/tasks.c#l5203

vTaskSetTimeOutState(…) and xTaskCheckForTimeOut(…) from interrupt

I have created “freertostasksc_additions.h” file: ~~~

include “FreeRTOS.h”

include “task.h”

void vTaskSetTimeOutStateFromISR(TimeOut_t * const pxTimeOut); BaseTypet xTaskCheckForTimeOutFromISR(TimeOutt * const pxTimeOut, TickType_t * const pxTicksToWait); ~~~ tasks_custom.cpp ~~~

include “freertostasksc_additions.h”

void vTaskSetTimeOutStateFromISR(TimeOutt * const pxTimeOut) { UBaseTypet uxSavedInterruptStatus;
configASSERT(pxTimeOut);
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
    pxTimeOut->xOverflowCount = xNumOfOverflows;
    pxTimeOut->xTimeOnEntering = xTickCount;
}
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
} BaseTypet xTaskCheckForTimeOutFromISR(TimeOutt * const pxTimeOut, TickTypet * const pxTicksToWait) { BaseTypet xReturn; UBaseType_t uxSavedInterruptStatus;
configASSERT(pxTimeOut);
configASSERT(pxTicksToWait);

uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
    /* Minor optimisation.  The tick count cannot change in this block. */
    const TickType_t xConstTickCount = xTickCount;
    const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering;

if( INCLUDE_xTaskAbortDelay == 1 )

    if (pxCurrentTCB->ucDelayAborted != pdFALSE)
    {
        /* The delay was aborted, which is not the same as a time out,
        but has the same result. */
        pxCurrentTCB->ucDelayAborted = pdFALSE;
        xReturn = pdTRUE;
    }
    else

endif

if ( INCLUDE_vTaskSuspend == 1 )

if (*pxTicksToWait == portMAX_DELAY)
    {
        /* If INCLUDE_vTaskSuspend is set to 1 and the block time
        specified is the maximum block time then the task should block
        indefinitely, and therefore never time out. */
        xReturn = pdFALSE;
    }
    else

endif

if ((xNumOfOverflows != pxTimeOut->xOverflowCount) && (xConstTickCount >= pxTimeOut->xTimeOnEntering)) /lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */ { / The tick count is greater than the time at which vTaskSetTimeout() was called, but has also overflowed since vTaskSetTimeOut() was called. It must have wrapped all the way around and gone past again. This passed since vTaskSetTimeout() was called. / xReturn = pdTRUE; } else if(xElapsedTime < *pxTicksToWait) /lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. / { / Not a genuine timeout. Adjust parameters for time remaining. */ *pxTicksToWait -= xElapsedTime; vTaskInternalSetTimeOutState(pxTimeOut); xReturn = pdFALSE; } else { *pxTicksToWait = 0; xReturn = pdTRUE; } } portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
return xReturn;
} ~~~ configINCLUDEFREERTOSTASKCADDITIONS_H setted to 1 but when i try to use ‘vTaskSetTimeOutStateFromISR(…)‘ I get the following error: vTaskSetTimeOutStateFromISR(…) was not declared in this scope

edit

Problem solved, I forgot to write #include “freertostasksc_additions.h” in the file where I’m going to use my APIs In any case, is the procedure I wrote to add new APIs valid? do you have any suggestions to improve this implementation?

vTaskSetTimeOutState(…) and xTaskCheckForTimeOut(…) from interrupt

no, I agree that when I compile it doesn’t find the “xNumOfOverflows” and “xTickCount” variables. I suspect the way I implemented these APIs is incorrect. Any tips? Thanks.

vTaskSetTimeOutState(…) and xTaskCheckForTimeOut(…) from interrupt

If you define configINCLUDEFREERTOSTASKCADDITIONS 1 in FreeRTOS config, then your FreeRTOSTaskCAdditions.h file is included a part of Task.c, that means that it won’t need to include FreeRTOS.h or Tasks.h headers, as they are already available. You likely want it to include some other FreeRTOSAdditionsAPI.h that the callers of your new functions also include to provide declerations of the functions. (If you are using C++, don’t forget the extern “C” stuff in the API header). Your other code does NOT include FreeRTOSTaskCAdditions.h

vTaskSetTimeOutState(…) and xTaskCheckForTimeOut(…) from interrupt

But if I don’t include the files ‘FreeRTOS.h’ and ‘task.h’, the types ‘BaseTypet’ and ‘TimeOutt’ are not found. unknown type name ‘BaseTypet’ unknown type name ‘TimeOutt’

vTaskSetTimeOutState(…) and xTaskCheckForTimeOut(…) from interrupt

For your code in freertostaskscadditions.h, those types will have been define by task.c before it includes freertostaskscadditions.h, so they will not be an issue. YOU should NEVER have in include for freertostasksc_additions.h in your own code, so those definitions should be ok. If you include the file in some other file, then it won’t have access to private internals of tack.c, so you can’t do that.

vTaskSetTimeOutState(…) and xTaskCheckForTimeOut(…) from interrupt

I managed to solve most minor problems. The main problem is that I cannot access the variables ‘xTickCount’ and ‘xNumOfOverflows’ from my interrupt safe API “MyAPIFromISR(…)” declared in the file ‘freertostasksc_addtions.h’, because ‘xTickCount’ and ‘xNumOfOverflows’ are declared as ‘static’ in ‘task.c’. I think the only way to fix it is to add my API directly into FreeRTOS’s “task.c” file.

vTaskSetTimeOutState(…) and xTaskCheckForTimeOut(…) from interrupt

That is the whole purpose of freertostaskscadditions.h, it is code that you provide that is automatically included into tasks.c when you define configINCLUDEFREERTOSTASKCADDITIONSH as 1 in FreeRTOSConfig.h Even though it has a .h extension, think of it as a .c file for your program. (I personally might have called it something like freertostasksc_additions.c to be clearer that it shouldn’t be included elsewhere (but then you do need to make sure it isn’t compiled as an indendant file also) Code in freertostasksc_additions.h, since it is include by tasks.c, has full access to all the variables and defintions inside tasks.c. You add your code there, and it effectively gets added to tasks.c without needing to actually change the file. Because the code in there wants to see the private internals of tasks.c, it can’t be included elsewhere in your system. You will need to have a header file to provide the needed declerations of the functions in that file so other files can call them.

vTaskSetTimeOutState(…) and xTaskCheckForTimeOut(…) from interrupt

Thanks for the explanation, but I can’t understand. Can you show me an example? FreeRTOSConfig.h ~~~ //…

define configINCLUDEFREERTOSTASKCADDITIONS_H 1

//… ~~~ freertostasksc_additions.h ~~~

ifndef INCFREERTOSTASKSCADDITIONS_H

define INCFREERTOSTASKSCADDITIONS_H

ifdef __cplusplus

extern “C” {

endif

void MyAPIFromISR() { UBaseType_t uxSavedInterruptStatus;
configASSERT(pxTimeOut);
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
    BaseType_t x = xNumOfOverflows;  //[Clang IntelliSense] Error: use of undeclared identifier 'xNumOfOverflows'
    TickType_t y = xTickCount;  //[Clang IntelliSense] Error: use of undeclared identifier 'xTickCount'
}
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
}

ifdef __cplusplus

}

endif

endif // !INCFREERTOSTASKSCADDITIONS_H

~~~ user_code.cpp ~~~

include <FreeRTOS.h>

include <task.h>

void test() { TimeOut_t temp;
vTaskSetTimeOutStateFromISR(&temp);  //'vTaskSetTimeOutStateFromISR' was not declared in this scope
} ~~~

vTaskSetTimeOutState(…) and xTaskCheckForTimeOut(…) from interrupt

Just like the functions in tasks.c have declerations in task.h, you need to create a header file (other than freertosadditionstasksc.h) to put those declerations in, and THAT file should be included in your user code (and in freertosadditionstasksc.h) to provide the needed declaration. It would have something like: ~~~

ifndef FREERTOSADDITIONSTASKCAPI_H

define FREERTOSADDITIONSTASKCAPI_H 1

ifdef __cplusplus

extern “C” {

endif

extern void vTaskSetTimeOutStateFromISR(TimeOut_t *);

ifdef __cplusplus

}

endif

endif

~~~ and then in freertosadditionstasks_c.h would have the implementation of that function that you have created, and should also include the above header file to confirm the definition matches the decleration.

vTaskSetTimeOutState(…) and xTaskCheckForTimeOut(…) from interrupt

ok thanks a lot for the help, following your advice I solved the problem. FreeRTOSConfig.h ~~~ //…

define configINCLUDEFREERTOSTASKCADDITIONS_H 1

//… ~~~ freertostaskscadditionsapi.h ~~~

ifndef FREERTOSTASKCADDITIONSAPI_H

define FREERTOSTASKCADDITIONSAPI_H

ifdef __cplusplus

extern “C” {

endif

BaseTypet xTaskCheckForTimeOut2(TimeOutt * const pxTimeOut, TimeOutt * const pxTimeOut2, TickTypet const pxTicksToWait); void vTaskSetTimeOutStateFromISR(TimeOut_t*); BaseTypet xTaskCheckForTimeOutFromISR(TimeOutt * const pxTimeOut, TickType_t * const pxTicksToWait);

ifdef __cplusplus

}

endif

endif

~~~ freertostasksc_additions.h ~~~

ifndef INCFREERTOSTASKSCADDITIONS_H

define INCFREERTOSTASKSCADDITIONS_H

ifdef __cplusplus

extern “C” {

endif

void vTaskSetTimeOutStateFromISR(TimeOutt * const pxTimeOut) { UBaseTypet uxSavedInterruptStatus;
configASSERT(pxTimeOut);
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
    pxTimeOut->xTimeOnEntering = xTickCount;
    pxTimeOut->xOverflowCount = xNumOfOverflows;
}
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
} BaseTypet xTaskCheckForTimeOutFromISR(TimeOutt * const pxTimeOut, TickTypet * const pxTicksToWait) { BaseTypet xReturn; UBaseType_t uxSavedInterruptStatus;
configASSERT(pxTimeOut);
configASSERT(pxTicksToWait);

uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{       
    /* Minor optimisation.  The tick count cannot change in this block. */
    const TickType_t xConstTickCount = xTickCount;
    const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering;

if( INCLUDE_xTaskAbortDelay == 1 )

    if (pxCurrentTCB->ucDelayAborted != pdFALSE)
    {
        /* The delay was aborted, which is not the same as a time out,
        but has the same result. */
        pxCurrentTCB->ucDelayAborted = pdFALSE;
        xReturn = pdTRUE;
    }
    else

endif

if ( INCLUDE_vTaskSuspend == 1 )

    if (*pxTicksToWait == portMAX_DELAY)
    {
        /* If INCLUDE_vTaskSuspend is set to 1 and the block time
        specified is the maximum block time then the task should block
        indefinitely, and therefore never time out. */
        xReturn = pdFALSE;
    }
    else

endif

    if ((xNumOfOverflows != pxTimeOut->xOverflowCount) && (xConstTickCount >= pxTimeOut->xTimeOnEntering)) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
    {
        /* The tick count is greater than the time at which
        vTaskSetTimeout() was called, but has also overflowed since
        vTaskSetTimeOut() was called.  It must have wrapped all the way
        around and gone past again. This passed since vTaskSetTimeout()
        was called. */
        xReturn = pdTRUE;
    }
    else if(xElapsedTime < *pxTicksToWait) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */
    {
        /* Not a genuine timeout. Adjust parameters for time remaining. */
        *pxTicksToWait -= xElapsedTime;
        vTaskInternalSetTimeOutState(pxTimeOut);
        xReturn = pdFALSE;
    }
    else
    {
        *pxTicksToWait = 0;
        xReturn = pdTRUE;
    }
}
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);

return xReturn;
}

ifdef __cplusplus

}

endif

endif // !INCFREERTOSTASKSCADDITIONS_H

~~~ my_code.cpp ~~~ //…

include “freertostaskscadditionsapi.h”

//… ~~~