Added xTaskAbortDelayFromISR() and ulTaskNotifyValueClear() API functions.

Added tests for xTaskAbortDelayFromISR() into Demo/Common/Minimal/AbortDelay.c.
Added tests for ulTaskNotifyValueClear() into Demo/Common/Minimal/TaskNotify.c.
This commit is contained in:
Richard Barry 2020-01-02 18:55:20 +00:00
parent 0a29d350b1
commit be3561ed53
9 changed files with 336 additions and 27 deletions

View file

@ -76,6 +76,7 @@ BaseType_t MPU_xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue,
BaseType_t MPU_xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
uint32_t MPU_ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskNotifyStateClear( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
uint32_t MPU_ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskIncrementTick( void ) FREERTOS_SYSTEM_CALL;
TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) FREERTOS_SYSTEM_CALL;

View file

@ -82,6 +82,7 @@ only for ports that are using the MPU. */
#define xTaskNotifyWait MPU_xTaskNotifyWait
#define ulTaskNotifyTake MPU_ulTaskNotifyTake
#define xTaskNotifyStateClear MPU_xTaskNotifyStateClear
#define ulTaskNotifyValueClear MPU_ulTaskNotifyValueClear
#define xTaskCatchUpTicks MPU_xTaskCatchUpTicks
#define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle

View file

@ -841,6 +841,39 @@ void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xT
*/
BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
/**
* task. h
* <pre>BaseType_t xTaskAbortDelayFromISR( TaskHandle_t xTask, BaseType_t * const pxHigherPriorityTaskWoken )</pre>
*
* INCLUDE_xTaskAbortDelay must be defined as 1 in FreeRTOSConfig.h for this
* function to be available.
*
* A version of xTaskAbortDelay() that can be used from an interrupt service routine.
*
* A task will enter the Blocked state when it is waiting for an event. The
* event it is waiting for can be a temporal event (waiting for a time), such
* as when vTaskDelay() is called, or an event on an object, such as when
* xQueueReceive() or ulTaskNotifyTake() is called. If the handle of a task
* that is in the Blocked state is used in a call to xTaskAbortDelay() then the
* task will leave the Blocked state, and return from whichever function call
* placed the task into the Blocked state.
*
* @param xTask The handle of the task to remove from the Blocked state.
*
* @param pxHigherPriorityTaskWoken xTaskAbortDelayFromISR() will set
* *pxHigherPriorityTaskWoken to pdTRUE if a task was removed from the Blocked state,
* and the task that was removed from the Blocked state has a priority higher than the
* currently running task. If xTaskAbortDelayFromISR() sets this value to pdTRUE then
* a context switch should be requested before the interrupt is exited.
*
* @return If the task referenced by xTask was not in the Blocked state then
* pdFAIL is returned. Otherwise pdPASS is returned.
*
* \defgroup xTaskAbortDelay xTaskAbortDelayFromISR
* \ingroup TaskCtrl
*/
BaseType_t xTaskAbortDelayFromISR( TaskHandle_t xTask, BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
/**
* task. h
* <pre>UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask );</pre>
@ -2201,6 +2234,24 @@ uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait
*/
BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask );
/**
* task. h
* <PRE>uint32_t ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear );</pre>
*
* Clears the bits specified by the ulBitsToClear bit mask in the notification
* value of the task referenced by xTask.
*
* Set ulBitsToClear to to 0xffffffff (UINT_MAX on 32-bit architectures) to clear
* the notification value to 0. Set ulBitsToClear to 0 to query the task's
* notification value without clearing any bits.
*
* @return The value of the target task's notification value before the bits
* specified by ulBitsToClear were cleared.
* \defgroup ulTaskNotifyValueClear ulTaskNotifyValueClear
* \ingroup TaskNotifications
*/
uint32_t ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION;
/**
* task.h
* <pre>void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )</pre>

View file

@ -586,6 +586,19 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
#endif
/*-----------------------------------------------------------*/
#if( configUSE_TASK_NOTIFICATIONS == 1 )
uint32_t MPU_ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear ) /* FREERTOS_SYSTEM_CALL */
{
uint32_t ulReturn;
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
ulReturn = ulTaskNotifyValueClear( xTask, ulBitsToClear );
vPortResetPrivilege( xRunningPrivileged );
return ulReturn;
}
#endif
/*-----------------------------------------------------------*/
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
QueueHandle_t MPU_xQueueGenericCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize, uint8_t ucQueueType ) /* FREERTOS_SYSTEM_CALL */
{

View file

@ -2626,7 +2626,7 @@ BaseType_t xYieldRequired = pdFALSE;
relies on xPendedTicks being wound down to 0 in xTaskResumeAll(). */
configASSERT( uxSchedulerSuspended == 0 );
/* Use xPendedTicks to mimic xTicksToCatchUp number of ticks occuring when
/* Use xPendedTicks to mimic xTicksToCatchUp number of ticks occurring when
the scheduler is suspended so the ticks are executed in xTaskResumeAll(). */
vTaskSuspendAll();
xPendedTicks += xTicksToCatchUp;
@ -2636,6 +2636,91 @@ BaseType_t xYieldRequired = pdFALSE;
}
/*----------------------------------------------------------*/
#if ( INCLUDE_xTaskAbortDelay == 1 )
BaseType_t xTaskAbortDelayFromISR( TaskHandle_t xTask, BaseType_t * const pxHigherPriorityTaskWoken )
{
TCB_t *pxTCB = xTask;
BaseType_t xReturn;
UBaseType_t uxSavedInterruptStatus;
configASSERT( pxTCB );
/* RTOS ports that support interrupt nesting have the concept of a maximum
system call (or maximum API call) interrupt priority. Interrupts that are
above the maximum system call priority are kept permanently enabled, even
when the RTOS kernel is in a critical section, but cannot make any calls to
FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
failure if a FreeRTOS API function is called from an interrupt that has been
assigned a priority above the configured maximum system call priority.
Only FreeRTOS functions that end in FromISR can be called from interrupts
that have been assigned a priority at or (logically) below the maximum
system call interrupt priority. FreeRTOS maintains a separate interrupt
safe API to ensure interrupt entry is as fast and as simple as possible.
More information (albeit Cortex-M specific) is provided on the following
link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
/* A task can only be prematurely removed from the Blocked state if
it is actually in the Blocked state. */
if( eTaskGetState( xTask ) == eBlocked )
{
xReturn = pdPASS;
/* Remove the reference to the task from the blocked list. A higher
priority interrupt won't touch the xStateListItem because of the
critical section. */
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
/* Is the task waiting on an event also? If so remove it from
the event list too. */
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
{
( void ) uxListRemove( &( pxTCB->xEventListItem ) );
/* This lets the task know it was forcibly removed from the
blocked state so it should not re-evaluate its block time and
then block again. */
pxTCB->ucDelayAborted = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Place the unblocked task into the appropriate ready list. */
prvAddTaskToReadyList( pxTCB );
if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
{
if( pxHigherPriorityTaskWoken != NULL )
{
/* Pend the yield to be performed when the scheduler
is unsuspended. */
*pxHigherPriorityTaskWoken = pdTRUE;
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
xReturn = pdFAIL;
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
return xReturn;
}
#endif
/*----------------------------------------------------------*/
#if ( INCLUDE_xTaskAbortDelay == 1 )
BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
@ -2667,6 +2752,10 @@ BaseType_t xYieldRequired = pdFALSE;
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
{
( void ) uxListRemove( &( pxTCB->xEventListItem ) );
/* This lets the task know it was forcibly removed from the
blocked state so it should not re-evaluate its block time and
then block again. */
pxTCB->ucDelayAborted = pdTRUE;
}
else
@ -5096,7 +5185,6 @@ TickType_t uxReturn;
}
#endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/
#if( configUSE_TASK_NOTIFICATIONS == 1 )
@ -5130,6 +5218,32 @@ TickType_t uxReturn;
#endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/
#if( configUSE_TASK_NOTIFICATIONS == 1 )
uint32_t ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear )
{
TCB_t *pxTCB;
uint32_t ulReturn;
/* If null is passed in here then it is the calling task that is having
its notification state cleared. */
pxTCB = prvGetTCBFromHandle( xTask );
taskENTER_CRITICAL();
{
/* Return the notification as it was before the bits were cleared,
then clear the bit mask. */
ulReturn = pxCurrentTCB->ulNotifiedValue;
pxTCB->ulNotifiedValue &= ~ulBitsToClear;
}
taskEXIT_CRITICAL();
return ulReturn;
}
#endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/
#if( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
uint32_t ulTaskGetIdleRunTimeCounter( void )