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;
}