From 2acc8f2c995697f3306423eafc3c0d8632064f88 Mon Sep 17 00:00:00 2001 From: Richard Barry Date: Wed, 10 Feb 2016 12:58:15 +0000 Subject: [PATCH] FreeRTOS source: - Major refactor to consolidate the multiple places where a task is removed from a ready list and placed in a delay list into a single function, reducing code size, and enabling the easy addition of up-coming functionality. - Replace the enum used for task notification states with a uint8_t to reduce the TCB struct size with some compilers, and allow additional members to be added without increasing its size. - Rearrange FreeRTOS.h so all INCLUDE_ defaults are grouped together. --- .../Include/trcKernelPort.h | 12 +- FreeRTOS/Source/include/FreeRTOS.h | 123 +++-- FreeRTOS/Source/include/task.h | 10 +- FreeRTOS/Source/tasks.c | 507 ++++++------------ 4 files changed, 234 insertions(+), 418 deletions(-) diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort.h index 7c8244137..47b6fdcf8 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort.h @@ -56,7 +56,7 @@ extern int uiInEventGroupSetBitsFromISR; #define TRACE_CPU_CLOCK_HZ configCPU_CLOCK_HZ /* Defined in "FreeRTOSConfig.h" */ #if (SELECTED_PORT == PORT_ARM_CortexM) - + /* Uses CMSIS API */ #define TRACE_SR_ALLOC_CRITICAL_SECTION() int __irq_status; @@ -571,8 +571,8 @@ void* prvTraceGetCurrentTaskHandle(void); /* Called on vTaskDelayUntil - note the use of FreeRTOS variable xTimeToWake */ #undef traceTASK_DELAY_UNTIL -#define traceTASK_DELAY_UNTIL() \ - trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY_UNTIL, pxCurrentTCB, xTimeToWake); \ +#define traceTASK_DELAY_UNTIL( xTickTimeToWake ) \ + trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY_UNTIL, pxCurrentTCB, ( xTickTimeToWake)); \ trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); #if (INCLUDE_OBJECT_DELETE == 1) @@ -819,7 +819,7 @@ else \ #undef traceTASK_NOTIFY_TAKE #define traceTASK_NOTIFY_TAKE() \ - if (pxCurrentTCB->eNotifyState == eNotified) \ + if (pxCurrentTCB->ucNotifyState == taskNOTIFICATION_RECEIVED) \ vTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_TAKE, TRACE_CLASS_TASK, uxTaskGetTaskNumber(pxCurrentTCB), xTicksToWait); \ else \ vTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_TAKE_FAILED, TRACE_CLASS_TASK, uxTaskGetTaskNumber(pxCurrentTCB), xTicksToWait); @@ -831,7 +831,7 @@ else \ #undef traceTASK_NOTIFY_WAIT #define traceTASK_NOTIFY_WAIT() \ - if (pxCurrentTCB->eNotifyState == eNotified) \ + if (pxCurrentTCB->ucNotifyState == taskNOTIFICATION_RECEIVED) \ vTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT, TRACE_CLASS_TASK, uxTaskGetTaskNumber(pxCurrentTCB), xTicksToWait); \ else \ vTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT_FAILED, TRACE_CLASS_TASK, uxTaskGetTaskNumber(pxCurrentTCB), xTicksToWait); @@ -848,7 +848,7 @@ else \ #undef traceTASK_NOTIFY_FROM_ISR #define traceTASK_NOTIFY_FROM_ISR() \ vTraceStoreKernelCall(TRACE_TASK_NOTIFY_FROM_ISR, TRACE_CLASS_TASK, uxTaskGetTaskNumber(xTaskToNotify)); - + #undef traceTASK_NOTIFY_GIVE_FROM_ISR #define traceTASK_NOTIFY_GIVE_FROM_ISR() \ vTraceStoreKernelCall(TRACE_TASK_NOTIFY_GIVE_FROM_ISR, TRACE_CLASS_TASK, uxTaskGetTaskNumber(xTaskToNotify)); diff --git a/FreeRTOS/Source/include/FreeRTOS.h b/FreeRTOS/Source/include/FreeRTOS.h index 33a4d79f1..55306add0 100644 --- a/FreeRTOS/Source/include/FreeRTOS.h +++ b/FreeRTOS/Source/include/FreeRTOS.h @@ -129,30 +129,6 @@ extern "C" { #error Missing definition: configUSE_TICK_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #endif -#ifndef INCLUDE_vTaskPrioritySet - #error Missing definition: INCLUDE_vTaskPrioritySet must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -#endif - -#ifndef INCLUDE_uxTaskPriorityGet - #error Missing definition: INCLUDE_uxTaskPriorityGet must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -#endif - -#ifndef INCLUDE_vTaskDelete - #error Missing definition: INCLUDE_vTaskDelete must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -#endif - -#ifndef INCLUDE_vTaskSuspend - #error Missing definition: INCLUDE_vTaskSuspend must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -#endif - -#ifndef INCLUDE_vTaskDelayUntil - #error Missing definition: INCLUDE_vTaskDelayUntil must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -#endif - -#ifndef INCLUDE_vTaskDelay - #error Missing definition: INCLUDE_vTaskDelay must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -#endif - #ifndef configUSE_16_BIT_TICKS #error Missing definition: configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #endif @@ -165,20 +141,38 @@ extern "C" { #define configUSE_CO_ROUTINES 0 #endif -#if configUSE_CO_ROUTINES != 0 - #ifndef configMAX_CO_ROUTINE_PRIORITIES - #error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1. - #endif +#ifndef INCLUDE_vTaskPrioritySet + #define INCLUDE_vTaskPrioritySet 0 #endif -#ifndef configUSE_DAEMON_TASK_STARTUP_HOOK - #define configUSE_DAEMON_TASK_STARTUP_HOOK 0 +#ifndef INCLUDE_uxTaskPriorityGet + #define INCLUDE_uxTaskPriorityGet 0 +#endif + +#ifndef INCLUDE_vTaskDelete + #define INCLUDE_vTaskDelete 0 +#endif + +#ifndef INCLUDE_vTaskSuspend + #define INCLUDE_vTaskSuspend 0 +#endif + +#ifndef INCLUDE_vTaskDelayUntil + #define INCLUDE_vTaskDelayUntil 0 +#endif + +#ifndef INCLUDE_vTaskDelay + #define INCLUDE_vTaskDelay 0 #endif #ifndef INCLUDE_xTaskGetIdleTaskHandle #define INCLUDE_xTaskGetIdleTaskHandle 0 #endif +#ifndef INCLUDE_xTaskAbortDelay + #define INCLUDE_xTaskAbortDelay 0 +#endif + #ifndef INCLUDE_xTimerGetTimerDaemonTaskHandle #define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 #endif @@ -199,14 +193,6 @@ extern "C" { #define INCLUDE_xTaskGetTaskHandle 0 #endif -#ifndef configUSE_APPLICATION_TASK_TAG - #define configUSE_APPLICATION_TASK_TAG 0 -#endif - -#ifndef configNUM_THREAD_LOCAL_STORAGE_POINTERS - #define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0 -#endif - #ifndef INCLUDE_uxTaskGetStackHighWaterMark #define INCLUDE_uxTaskGetStackHighWaterMark 0 #endif @@ -215,6 +201,40 @@ extern "C" { #define INCLUDE_eTaskGetState 0 #endif +#ifndef INCLUDE_xTaskResumeFromISR + #define INCLUDE_xTaskResumeFromISR 1 +#endif + +#ifndef INCLUDE_xTimerPendFunctionCall + #define INCLUDE_xTimerPendFunctionCall 0 +#endif + +#ifndef INCLUDE_xTaskGetSchedulerState + #define INCLUDE_xTaskGetSchedulerState 0 +#endif + +#ifndef INCLUDE_xTaskGetCurrentTaskHandle + #define INCLUDE_xTaskGetCurrentTaskHandle 0 +#endif + +#if configUSE_CO_ROUTINES != 0 + #ifndef configMAX_CO_ROUTINE_PRIORITIES + #error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1. + #endif +#endif + +#ifndef configUSE_DAEMON_TASK_STARTUP_HOOK + #define configUSE_DAEMON_TASK_STARTUP_HOOK 0 +#endif + +#ifndef configUSE_APPLICATION_TASK_TAG + #define configUSE_APPLICATION_TASK_TAG 0 +#endif + +#ifndef configNUM_THREAD_LOCAL_STORAGE_POINTERS + #define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0 +#endif + #ifndef configUSE_RECURSIVE_MUTEXES #define configUSE_RECURSIVE_MUTEXES 0 #endif @@ -251,14 +271,6 @@ extern "C" { #error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h #endif -#ifndef INCLUDE_xTaskResumeFromISR - #define INCLUDE_xTaskResumeFromISR 1 -#endif - -#ifndef INCLUDE_xTimerPendFunctionCall - #define INCLUDE_xTimerPendFunctionCall 0 -#endif - #ifndef configASSERT #define configASSERT( x ) #define configASSERT_DEFINED 0 @@ -283,15 +295,6 @@ extern "C" { #endif /* configUSE_TIMERS */ -#ifndef INCLUDE_xTaskGetSchedulerState - #define INCLUDE_xTaskGetSchedulerState 0 -#endif - -#ifndef INCLUDE_xTaskGetCurrentTaskHandle - #define INCLUDE_xTaskGetCurrentTaskHandle 0 -#endif - - #ifndef portSET_INTERRUPT_MASK_FROM_ISR #define portSET_INTERRUPT_MASK_FROM_ISR() 0 #endif @@ -515,7 +518,7 @@ extern "C" { #endif #ifndef traceTASK_DELAY_UNTIL - #define traceTASK_DELAY_UNTIL() + #define traceTASK_DELAY_UNTIL( x ) #endif #ifndef traceTASK_DELAY @@ -877,12 +880,6 @@ typedef struct xSTATIC_LIST StaticMiniListItem_t xDummy3; } StaticList_t; -/* For data hiding purposes. */ -typedef enum -{ - eNothing = 0 -} eDummy; - /* * In line with software engineering best practice, especially when supplying a * library that is likely to change in future versions, FreeRTOS implements a @@ -932,7 +929,7 @@ typedef struct xSTATIC_TCB #endif #if ( configUSE_TASK_NOTIFICATIONS == 1 ) uint32_t ulDummy18; - eDummy eDummy19; + uint8_t ucDummy19; #endif #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) uint8_t uxDummy20; diff --git a/FreeRTOS/Source/include/task.h b/FreeRTOS/Source/include/task.h index b736b6010..182d35912 100644 --- a/FreeRTOS/Source/include/task.h +++ b/FreeRTOS/Source/include/task.h @@ -185,14 +185,6 @@ typedef enum eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe to enter a sleep mode that can only be exited by an external interrupt. */ } eSleepModeStatus; -/* Value that can be assigned to the eNotifyState member of the TCB. */ -typedef enum -{ - eNotWaitingNotification = 0, - eWaitingNotification, - eNotified -} eNotifyValue; - /** * Defines the priority used by the idle task. This must not be modified. * @@ -2105,7 +2097,7 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xIte * indefinitely, whereas vTaskPlaceOnEventList() does. * */ -void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION; +void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION; /* * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN diff --git a/FreeRTOS/Source/tasks.c b/FreeRTOS/Source/tasks.c index d65e91698..3dcb0049e 100644 --- a/FreeRTOS/Source/tasks.c +++ b/FreeRTOS/Source/tasks.c @@ -129,6 +129,11 @@ deleted. */ #define taskSTATICALLY_ALLOCATED_STACK ( ( uint8_t ) 0x01 ) #define taskSTATICALLY_ALLOCATED_TCB ( ( uint8_t ) 0x02 ) +/* Values that can be assigned to the ucNotifyState member of the TCB. */ +#define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 ) +#define taskWAITING_NOTIFICATION ( ( uint8_t ) 1 ) +#define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 ) + /* * Task control block. A task control block (TCB) is allocated for each task, * and stores task state information, including a pointer to the task's context @@ -174,7 +179,7 @@ typedef struct tskTaskControlBlock void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; #endif - #if ( configGENERATE_RUN_TIME_STATS == 1 ) + #if( configGENERATE_RUN_TIME_STATS == 1 ) uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */ #endif @@ -189,16 +194,16 @@ typedef struct tskTaskControlBlock struct _reent xNewLib_reent; #endif - #if ( configUSE_TASK_NOTIFICATIONS == 1 ) + #if( configUSE_TASK_NOTIFICATIONS == 1 ) volatile uint32_t ulNotifiedValue; - volatile eNotifyValue eNotifyState; + volatile uint8_t ucNotifyState; #endif #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) uint8_t ucStaticAllocationFlags; /* Set to pdTRUE if the stack is a statically allocated array, and pdFALSE if the stack is dynamically allocated. */ #endif - } tskTCB; +} tskTCB; /* The old tskTCB name is maintained above then typedefed to the new TCB_t name below to enable the use of older kernel aware debuggers. */ @@ -489,7 +494,7 @@ static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION; * The currently executing task is entering the Blocked state. Add the task to * either the current or the overflow delayed task list. */ -static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake ) PRIVILEGED_FUNCTION; +static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION; /* * Allocates memory from the heap for a TCB and associated stack. Checks the @@ -615,7 +620,7 @@ StackType_t *pxTopOfStack; /* If we want to use stack checking on architectures that use a positive stack growth direction then we also need to store the other extreme of the stack space. */ - pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 ); + pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - ( uint16_t ) 1 ); } #endif /* portSTACK_GROWTH */ @@ -889,23 +894,11 @@ StackType_t *pxTopOfStack; if( xShouldDelay != pdFALSE ) { - traceTASK_DELAY_UNTIL(); + traceTASK_DELAY_UNTIL( xTimeToWake ); - /* Remove the task from the ready list before adding it to the - blocked list as the same list item is used for both lists. */ - if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) - { - /* The current task must be in a ready list, so there is - no need to check, and the port reset macro can be called - directly. */ - portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - prvAddCurrentTaskToDelayedList( xTimeToWake ); + /* prvAddCurrentTaskToDelayedList() needs the block time, not + the time to wake, so subtract the current tick count. */ + prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE ); } else { @@ -933,10 +926,8 @@ StackType_t *pxTopOfStack; void vTaskDelay( const TickType_t xTicksToDelay ) { - TickType_t xTimeToWake; BaseType_t xAlreadyYielded = pdFALSE; - /* A delay time of zero just forces a reschedule. */ if( xTicksToDelay > ( TickType_t ) 0U ) { @@ -952,26 +943,7 @@ StackType_t *pxTopOfStack; This task cannot be in an event list as it is the currently executing task. */ - - /* Calculate the time to wake - this may overflow but this is - not a problem. */ - xTimeToWake = xTickCount + xTicksToDelay; - - /* We must remove ourselves from the ready list before adding - ourselves to the blocked list as the same list item is used for - both lists. */ - if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) - { - /* The current task must be in a ready list, so there is - no need to check, and the port reset macro can be called - directly. */ - portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - prvAddCurrentTaskToDelayedList( xTimeToWake ); + prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE ); } xAlreadyYielded = xTaskResumeAll(); } @@ -2447,8 +2419,6 @@ void vTaskSwitchContext( void ) void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait ) { -TickType_t xTimeToWake; - configASSERT( pxEventList ); /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE @@ -2460,54 +2430,12 @@ TickType_t xTimeToWake; list is locked, preventing simultaneous access from interrupts. */ vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) ); - /* The task must be removed from from the ready list before it is added to - the blocked list as the same list item is used for both lists. Exclusive - access to the ready lists guaranteed because the scheduler is locked. */ - if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) - { - /* The current task must be in a ready list, so there is no need to - check, and the port reset macro can be called directly. */ - portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - #if ( INCLUDE_vTaskSuspend == 1 ) - { - if( xTicksToWait == portMAX_DELAY ) - { - /* Add the task to the suspended task list instead of a delayed task - list to ensure the task is not woken by a timing event. It will - block indefinitely. */ - vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) ); - } - else - { - /* Calculate the time at which the task should be woken if the event - does not occur. This may overflow but this doesn't matter, the - scheduler will handle it. */ - xTimeToWake = xTickCount + xTicksToWait; - prvAddCurrentTaskToDelayedList( xTimeToWake ); - } - } - #else /* INCLUDE_vTaskSuspend */ - { - /* Calculate the time at which the task should be woken if the event does - not occur. This may overflow but this doesn't matter, the scheduler - will handle it. */ - xTimeToWake = xTickCount + xTicksToWait; - prvAddCurrentTaskToDelayedList( xTimeToWake ); - } - #endif /* INCLUDE_vTaskSuspend */ + prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); } /*-----------------------------------------------------------*/ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait ) { -TickType_t xTimeToWake; - configASSERT( pxEventList ); /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by @@ -2526,56 +2454,14 @@ TickType_t xTimeToWake; the task level). */ vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) ); - /* The task must be removed from the ready list before it is added to the - blocked list. Exclusive access can be assured to the ready list as the - scheduler is locked. */ - if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) - { - /* The current task must be in a ready list, so there is no need to - check, and the port reset macro can be called directly. */ - portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - #if ( INCLUDE_vTaskSuspend == 1 ) - { - if( xTicksToWait == portMAX_DELAY ) - { - /* Add the task to the suspended task list instead of a delayed task - list to ensure it is not woken by a timing event. It will block - indefinitely. */ - vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) ); - } - else - { - /* Calculate the time at which the task should be woken if the event - does not occur. This may overflow but this doesn't matter, the - kernel will manage it correctly. */ - xTimeToWake = xTickCount + xTicksToWait; - prvAddCurrentTaskToDelayedList( xTimeToWake ); - } - } - #else /* INCLUDE_vTaskSuspend */ - { - /* Calculate the time at which the task should be woken if the event does - not occur. This may overflow but this doesn't matter, the kernel - will manage it correctly. */ - xTimeToWake = xTickCount + xTicksToWait; - prvAddCurrentTaskToDelayedList( xTimeToWake ); - } - #endif /* INCLUDE_vTaskSuspend */ + prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); } /*-----------------------------------------------------------*/ -#if configUSE_TIMERS == 1 +#if( configUSE_TIMERS == 1 ) - void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) + void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) { - TickType_t xTimeToWake; - configASSERT( pxEventList ); /* This function should not be called by application code hence the @@ -2590,59 +2476,16 @@ TickType_t xTimeToWake; can be used in place of vListInsert. */ vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) ); - /* We must remove this task from the ready list before adding it to the - blocked list as the same list item is used for both lists. This - function is called with the scheduler locked so interrupts will not - access the lists at the same time. */ - if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + /* If the task should block indefinitely then set the block time to a + value that will be recognised as an indefinite delay inside the + prvAddCurrentTaskToDelayedList() function. */ + if( xWaitIndefinitely == pdTRUE ) { - /* The current task must be in a ready list, so there is no need to - check, and the port reset macro can be called directly. */ - portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); - } - else - { - mtCOVERAGE_TEST_MARKER(); + xTicksToWait = portMAX_DELAY; } - /* If vTaskSuspend() is available then the suspended task list is also - available and a task that is blocking indefinitely can enter the - suspended state (it is not really suspended as it will re-enter the - Ready state when the event it is waiting indefinitely for occurs). - Blocking indefinitely is useful when using tickless idle mode as when - all tasks are blocked indefinitely all timers can be turned off. */ - #if( INCLUDE_vTaskSuspend == 1 ) - { - if( xWaitIndefinitely == pdTRUE ) - { - /* Add the task to the suspended task list instead of a delayed - task list to ensure the task is not woken by a timing event. It - will block indefinitely. */ - vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) ); - } - else - { - /* Calculate the time at which the task should be woken if the - event does not occur. This may overflow but this doesn't - matter. */ - xTimeToWake = xTickCount + xTicksToWait; - traceTASK_DELAY_UNTIL(); - prvAddCurrentTaskToDelayedList( xTimeToWake ); - } - } - #else - { - /* Calculate the time at which the task should be woken if the event - does not occur. This may overflow but this doesn't matter. */ - xTimeToWake = xTickCount + xTicksToWait; - traceTASK_DELAY_UNTIL(); - prvAddCurrentTaskToDelayedList( xTimeToWake ); - - /* Remove compiler warnings when INCLUDE_vTaskSuspend() is not - defined. */ - ( void ) xWaitIndefinitely; - } - #endif + traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) ); + prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely ); } #endif /* configUSE_TIMERS */ @@ -2782,9 +2625,9 @@ BaseType_t xReturn; const TickType_t xConstTickCount = xTickCount; #if ( INCLUDE_vTaskSuspend == 1 ) - /* 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. */ + /* 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. */ if( *pxTicksToWait == portMAX_DELAY ) { xReturn = pdFALSE; @@ -2794,16 +2637,17 @@ BaseType_t xReturn; 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 us again. This - passed since vTaskSetTimeout() was called. */ + /* 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( ( xConstTickCount - pxTimeOut->xTimeOnEntering ) < *pxTicksToWait ) + else if( ( ( TickType_t ) ( xConstTickCount - pxTimeOut->xTimeOnEntering ) ) < *pxTicksToWait ) { /* Not a genuine timeout. Adjust parameters for time remaining. */ - *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering ); + *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering ); vTaskSetTimeOutState( pxTimeOut ); xReturn = pdFALSE; } @@ -3117,7 +2961,7 @@ UBaseType_t x; #if ( configUSE_TASK_NOTIFICATIONS == 1 ) { pxTCB->ulNotifiedValue = 0; - pxTCB->eNotifyState = eNotWaitingNotification; + pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; } #endif @@ -3126,7 +2970,7 @@ UBaseType_t x; /* Initialise this task's Newlib reent structure. */ _REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) ); } - #endif /* configUSE_NEWLIB_REENTRANT */ + #endif } /*-----------------------------------------------------------*/ @@ -3261,36 +3105,6 @@ static void prvCheckTasksWaitingTermination( void ) } /*-----------------------------------------------------------*/ -static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake ) -{ - /* The list item will be inserted in wake time order. */ - listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake ); - - if( xTimeToWake < xTickCount ) - { - /* Wake time has overflowed. Place this item in the overflow list. */ - vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) ); - } - else - { - /* The wake time has not overflowed, so the current block list is used. */ - vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) ); - - /* If the task entering the blocked state was placed at the head of the - list of blocked tasks then xNextTaskUnblockTime needs to be updated - too. */ - if( xTimeToWake < xNextTaskUnblockTime ) - { - xNextTaskUnblockTime = xTimeToWake; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } -} -/*-----------------------------------------------------------*/ - static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer, TCB_t * const pxTaskBuffer ) { TCB_t *pxNewTCB; @@ -4190,7 +4004,6 @@ TickType_t uxReturn; uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) { - TickType_t xTimeToWake; uint32_t ulReturn; taskENTER_CRITICAL(); @@ -4199,55 +4012,11 @@ TickType_t uxReturn; if( pxCurrentTCB->ulNotifiedValue == 0UL ) { /* Mark this task as waiting for a notification. */ - pxCurrentTCB->eNotifyState = eWaitingNotification; + pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION; if( xTicksToWait > ( TickType_t ) 0 ) { - /* The task is going to block. First it must be removed - from the ready list. */ - if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) - { - /* The current task must be in a ready list, so there is - no need to check, and the port reset macro can be called - directly. */ - portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - #if ( INCLUDE_vTaskSuspend == 1 ) - { - if( xTicksToWait == portMAX_DELAY ) - { - /* Add the task to the suspended task list instead - of a delayed task list to ensure the task is not - woken by a timing event. It will block - indefinitely. */ - vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) ); - } - else - { - /* Calculate the time at which the task should be - woken if no notification events occur. This may - overflow but this doesn't matter, the scheduler will - handle it. */ - xTimeToWake = xTickCount + xTicksToWait; - prvAddCurrentTaskToDelayedList( xTimeToWake ); - } - } - #else /* INCLUDE_vTaskSuspend */ - { - /* Calculate the time at which the task should be - woken if the event does not occur. This may - overflow but this doesn't matter, the scheduler will - handle it. */ - xTimeToWake = xTickCount + xTicksToWait; - prvAddCurrentTaskToDelayedList( xTimeToWake ); - } - #endif /* INCLUDE_vTaskSuspend */ - + prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); traceTASK_NOTIFY_TAKE_BLOCK(); /* All ports are written to allow a yield in a critical @@ -4289,7 +4058,7 @@ TickType_t uxReturn; mtCOVERAGE_TEST_MARKER(); } - pxCurrentTCB->eNotifyState = eNotWaitingNotification; + pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; } taskEXIT_CRITICAL(); @@ -4303,13 +4072,12 @@ TickType_t uxReturn; BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) { - TickType_t xTimeToWake; BaseType_t xReturn; taskENTER_CRITICAL(); { /* Only block if a notification is not already pending. */ - if( pxCurrentTCB->eNotifyState != eNotified ) + if( pxCurrentTCB->ucNotifyState != taskNOTIFICATION_RECEIVED ) { /* Clear bits in the task's notification value as bits may get set by the notifying task or interrupt. This can be used to @@ -4317,55 +4085,11 @@ TickType_t uxReturn; pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry; /* Mark this task as waiting for a notification. */ - pxCurrentTCB->eNotifyState = eWaitingNotification; + pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION; if( xTicksToWait > ( TickType_t ) 0 ) { - /* The task is going to block. First it must be removed - from the ready list. */ - if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) - { - /* The current task must be in a ready list, so there is - no need to check, and the port reset macro can be called - directly. */ - portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - #if ( INCLUDE_vTaskSuspend == 1 ) - { - if( xTicksToWait == portMAX_DELAY ) - { - /* Add the task to the suspended task list instead - of a delayed task list to ensure the task is not - woken by a timing event. It will block - indefinitely. */ - vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) ); - } - else - { - /* Calculate the time at which the task should be - woken if no notification events occur. This may - overflow but this doesn't matter, the scheduler will - handle it. */ - xTimeToWake = xTickCount + xTicksToWait; - prvAddCurrentTaskToDelayedList( xTimeToWake ); - } - } - #else /* INCLUDE_vTaskSuspend */ - { - /* Calculate the time at which the task should be - woken if the event does not occur. This may - overflow but this doesn't matter, the scheduler will - handle it. */ - xTimeToWake = xTickCount + xTicksToWait; - prvAddCurrentTaskToDelayedList( xTimeToWake ); - } - #endif /* INCLUDE_vTaskSuspend */ - + prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); traceTASK_NOTIFY_WAIT_BLOCK(); /* All ports are written to allow a yield in a critical @@ -4397,11 +4121,11 @@ TickType_t uxReturn; *pulNotificationValue = pxCurrentTCB->ulNotifiedValue; } - /* If eNotifyValue is set then either the task never entered the + /* If ucNotifyValue is set then either the task never entered the blocked state (because a notification was already pending) or the task unblocked because of a notification. Otherwise the task unblocked because of a timeout. */ - if( pxCurrentTCB->eNotifyState == eWaitingNotification ) + if( pxCurrentTCB->ucNotifyState == taskWAITING_NOTIFICATION ) { /* A notification was not received. */ xReturn = pdFALSE; @@ -4414,7 +4138,7 @@ TickType_t uxReturn; xReturn = pdTRUE; } - pxCurrentTCB->eNotifyState = eNotWaitingNotification; + pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; } taskEXIT_CRITICAL(); @@ -4429,8 +4153,8 @@ TickType_t uxReturn; BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ) { TCB_t * pxTCB; - eNotifyValue eOriginalNotifyState; BaseType_t xReturn = pdPASS; + uint8_t ucOriginalNotifyState; configASSERT( xTaskToNotify ); pxTCB = ( TCB_t * ) xTaskToNotify; @@ -4442,9 +4166,9 @@ TickType_t uxReturn; *pulPreviousNotificationValue = pxTCB->ulNotifiedValue; } - eOriginalNotifyState = pxTCB->eNotifyState; + ucOriginalNotifyState = pxTCB->ucNotifyState; - pxTCB->eNotifyState = eNotified; + pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; switch( eAction ) { @@ -4461,7 +4185,7 @@ TickType_t uxReturn; break; case eSetValueWithoutOverwrite : - if( eOriginalNotifyState != eNotified ) + if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED ) { pxTCB->ulNotifiedValue = ulValue; } @@ -4482,7 +4206,7 @@ TickType_t uxReturn; /* If the task is in the blocked state specifically to wait for a notification then unblock it now. */ - if( eOriginalNotifyState == eWaitingNotification ) + if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) { ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); prvAddTaskToReadyList( pxTCB ); @@ -4535,7 +4259,7 @@ TickType_t uxReturn; BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ) { TCB_t * pxTCB; - eNotifyValue eOriginalNotifyState; + uint8_t ucOriginalNotifyState; BaseType_t xReturn = pdPASS; UBaseType_t uxSavedInterruptStatus; @@ -4568,8 +4292,8 @@ TickType_t uxReturn; *pulPreviousNotificationValue = pxTCB->ulNotifiedValue; } - eOriginalNotifyState = pxTCB->eNotifyState; - pxTCB->eNotifyState = eNotified; + ucOriginalNotifyState = pxTCB->ucNotifyState; + pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; switch( eAction ) { @@ -4586,7 +4310,7 @@ TickType_t uxReturn; break; case eSetValueWithoutOverwrite : - if( eOriginalNotifyState != eNotified ) + if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED ) { pxTCB->ulNotifiedValue = ulValue; } @@ -4607,7 +4331,7 @@ TickType_t uxReturn; /* If the task is in the blocked state specifically to wait for a notification then unblock it now. */ - if( eOriginalNotifyState == eWaitingNotification ) + if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) { /* The task should not have been on an event list. */ configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); @@ -4659,7 +4383,7 @@ TickType_t uxReturn; void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken ) { TCB_t * pxTCB; - eNotifyValue eOriginalNotifyState; + uint8_t ucOriginalNotifyState; UBaseType_t uxSavedInterruptStatus; configASSERT( xTaskToNotify ); @@ -4686,8 +4410,8 @@ TickType_t uxReturn; uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); { - eOriginalNotifyState = pxTCB->eNotifyState; - pxTCB->eNotifyState = eNotified; + ucOriginalNotifyState = pxTCB->ucNotifyState; + pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; /* 'Giving' is equivalent to incrementing a count in a counting semaphore. */ @@ -4697,7 +4421,7 @@ TickType_t uxReturn; /* If the task is in the blocked state specifically to wait for a notification then unblock it now. */ - if( eOriginalNotifyState == eWaitingNotification ) + if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) { /* The task should not have been on an event list. */ configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); @@ -4756,9 +4480,9 @@ TickType_t uxReturn; taskENTER_CRITICAL(); { - if( pxTCB->eNotifyState == eNotified ) + if( pxTCB->ucNotifyState == taskNOTIFICATION_RECEIVED ) { - pxTCB->eNotifyState = eNotWaitingNotification; + pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; xReturn = pdPASS; } else @@ -4775,6 +4499,109 @@ TickType_t uxReturn; /*-----------------------------------------------------------*/ +static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, BaseType_t xCanBlockIndefinitely ) +{ +TickType_t xTimeToWake; + + /* Remove the task from the ready list before adding it to the blocked list + as the same list item is used for both lists. */ + if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + /* The current task must be in a ready list, so there is no need to + check, and the port reset macro can be called directly. */ + portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) ) + { + /* Add the task to the suspended task list instead of a delayed task + list to ensure it is not woken by a timing event. It will block + indefinitely. */ + vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) ); + } + else + { + /* Calculate the time at which the task should be woken if the event + does not occur. This may overflow but this doesn't matter, the + kernel will manage it correctly. */ + xTimeToWake = xTickCount + xTicksToWait; + + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake ); + + if( xTimeToWake < xTickCount ) + { + /* Wake time has overflowed. Place this item in the overflow + list. */ + vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) ); + } + else + { + /* The wake time has not overflowed, so the current block list + is used. */ + vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) ); + + /* If the task entering the blocked state was placed at the + head of the list of blocked tasks then xNextTaskUnblockTime + needs to be updated too. */ + if( xTimeToWake < xNextTaskUnblockTime ) + { + xNextTaskUnblockTime = xTimeToWake; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + } + #else /* INCLUDE_vTaskSuspend */ + { + /* Calculate the time at which the task should be woken if the event + does not occur. This may overflow but this doesn't matter, the kernel + will manage it correctly. */ + xTimeToWake = xTickCount + xTicksToWait; + + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake ); + + if( xTimeToWake < xTickCount ) + { + /* Wake time has overflowed. Place this item in the overflow list. */ + vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) ); + } + else + { + /* The wake time has not overflowed, so the current block list is used. */ + vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) ); + + /* If the task entering the blocked state was placed at the head of the + list of blocked tasks then xNextTaskUnblockTime needs to be updated + too. */ + if( xTimeToWake < xNextTaskUnblockTime ) + { + xNextTaskUnblockTime = xTimeToWake; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + /* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */ + ( void ) xCanBlockIndefinitely; + } + #endif /* INCLUDE_vTaskSuspend */ +} + + #ifdef FREERTOS_MODULE_TEST #include "tasks_test_access_functions.h" #endif