+ /* If null is passed in here then it is the priority of the calling\r
+ task that is being queried. */\r
+ pxTCB = prvGetTCBFromHandle( xTask );\r
+ uxReturn = pxTCB->uxPriority;\r
+ }\r
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptState );\r
+\r
+ return uxReturn;\r
+ }\r
+\r
+#endif /* INCLUDE_uxTaskPriorityGet */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( INCLUDE_vTaskPrioritySet == 1 )\r
+\r
+ void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority )\r
+ {\r
+ TCB_t *pxTCB;\r
+ UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;\r
+ BaseType_t xYieldRequired = pdFALSE;\r
+\r
+ configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );\r
+\r
+ /* Ensure the new priority is valid. */\r
+ if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )\r
+ {\r
+ uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+\r
+ taskENTER_CRITICAL();\r
+ {\r
+ /* If null is passed in here then it is the priority of the calling\r
+ task that is being changed. */\r
+ pxTCB = prvGetTCBFromHandle( xTask );\r
+\r
+ traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );\r
+\r
+ #if ( configUSE_MUTEXES == 1 )\r
+ {\r
+ uxCurrentBasePriority = pxTCB->uxBasePriority;\r
+ }\r
+ #else\r
+ {\r
+ uxCurrentBasePriority = pxTCB->uxPriority;\r
+ }\r
+ #endif\r
+\r
+ if( uxCurrentBasePriority != uxNewPriority )\r
+ {\r
+ /* The priority change may have readied a task of higher\r
+ priority than the calling task. */\r
+ if( uxNewPriority > uxCurrentBasePriority )\r
+ {\r
+ if( pxTCB != pxCurrentTCB )\r
+ {\r
+ /* The priority of a task other than the currently\r
+ running task is being raised. Is the priority being\r
+ raised above that of the running task? */\r
+ if( uxNewPriority >= pxCurrentTCB->uxPriority )\r
+ {\r
+ xYieldRequired = pdTRUE;\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* The priority of the running task is being raised,\r
+ but the running task must already be the highest\r
+ priority task able to run so no yield is required. */\r
+ }\r
+ }\r
+ else if( pxTCB == pxCurrentTCB )\r
+ {\r
+ /* Setting the priority of the running task down means\r
+ there may now be another task of higher priority that\r
+ is ready to execute. */\r
+ xYieldRequired = pdTRUE;\r
+ }\r
+ else\r
+ {\r
+ /* Setting the priority of any other task down does not\r
+ require a yield as the running task must be above the\r
+ new priority of the task being modified. */\r
+ }\r
+\r
+ /* Remember the ready list the task might be referenced from\r
+ before its uxPriority member is changed so the\r
+ taskRESET_READY_PRIORITY() macro can function correctly. */\r
+ uxPriorityUsedOnEntry = pxTCB->uxPriority;\r
+\r
+ #if ( configUSE_MUTEXES == 1 )\r
+ {\r
+ /* Only change the priority being used if the task is not\r
+ currently using an inherited priority. */\r
+ if( pxTCB->uxBasePriority == pxTCB->uxPriority )\r
+ {\r
+ pxTCB->uxPriority = uxNewPriority;\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+\r
+ /* The base priority gets set whatever. */\r
+ pxTCB->uxBasePriority = uxNewPriority;\r
+ }\r
+ #else\r
+ {\r
+ pxTCB->uxPriority = uxNewPriority;\r
+ }\r
+ #endif\r
+\r
+ /* Only reset the event list item value if the value is not\r
+ being used for anything else. */\r
+ if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )\r
+ {\r
+ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+\r
+ /* If the task is in the blocked or suspended list we need do\r
+ nothing more than change its priority variable. However, if\r
+ the task is in a ready list it needs to be removed and placed\r
+ in the list appropriate to its new priority. */\r
+ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )\r
+ {\r
+ /* The task is currently in its ready list - remove before\r
+ adding it to it's new ready list. As we are in a critical\r
+ section we can do this even if the scheduler is suspended. */\r
+ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )\r
+ {\r
+ /* It is known that the task is in its ready list so\r
+ there is no need to check again and the port level\r
+ reset macro can be called directly. */\r
+ portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ prvAddTaskToReadyList( pxTCB );\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+\r
+ if( xYieldRequired != pdFALSE )\r
+ {\r
+ taskYIELD_IF_USING_PREEMPTION();\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+\r
+ /* Remove compiler warning about unused variables when the port\r
+ optimised task selection is not being used. */\r
+ ( void ) uxPriorityUsedOnEntry;\r
+ }\r
+ }\r
+ taskEXIT_CRITICAL();\r
+ }\r
+\r
+#endif /* INCLUDE_vTaskPrioritySet */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( INCLUDE_vTaskSuspend == 1 )\r
+\r
+ void vTaskSuspend( TaskHandle_t xTaskToSuspend )\r
+ {\r
+ TCB_t *pxTCB;\r
+\r
+ taskENTER_CRITICAL();\r
+ {\r
+ /* If null is passed in here then it is the running task that is\r
+ being suspended. */\r
+ pxTCB = prvGetTCBFromHandle( xTaskToSuspend );\r
+\r
+ traceTASK_SUSPEND( pxTCB );\r
+\r
+ /* Remove task from the ready/delayed list and place in the\r
+ suspended list. */\r
+ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )\r
+ {\r
+ taskRESET_READY_PRIORITY( pxTCB->uxPriority );\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+\r
+ /* Is the task waiting on an event also? */\r
+ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )\r
+ {\r
+ ( void ) uxListRemove( &( pxTCB->xEventListItem ) );\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+\r
+ vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );\r
+\r
+ #if( configUSE_TASK_NOTIFICATIONS == 1 )\r
+ {\r
+ if( pxTCB->ucNotifyState == taskWAITING_NOTIFICATION )\r
+ {\r
+ /* The task was blocked to wait for a notification, but is\r
+ now suspended, so no notification was received. */\r
+ pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;\r
+ }\r
+ }\r
+ #endif\r
+ }\r
+ taskEXIT_CRITICAL();\r
+\r
+ if( xSchedulerRunning != pdFALSE )\r
+ {\r
+ /* Reset the next expected unblock time in case it referred to the\r
+ task that is now in the Suspended state. */\r
+ taskENTER_CRITICAL();\r
+ {\r
+ prvResetNextTaskUnblockTime();\r
+ }\r
+ taskEXIT_CRITICAL();\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+\r
+ if( pxTCB == pxCurrentTCB )\r
+ {\r
+ if( xSchedulerRunning != pdFALSE )\r
+ {\r
+ /* The current task has just been suspended. */\r
+ configASSERT( uxSchedulerSuspended == 0 );\r
+ portYIELD_WITHIN_API();\r
+ }\r
+ else\r
+ {\r
+ /* The scheduler is not running, but the task that was pointed\r
+ to by pxCurrentTCB has just been suspended and pxCurrentTCB\r
+ must be adjusted to point to a different task. */\r
+ if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) /*lint !e931 Right has no side effect, just volatile. */\r
+ {\r
+ /* No other tasks are ready, so set pxCurrentTCB back to\r
+ NULL so when the next task is created pxCurrentTCB will\r
+ be set to point to it no matter what its relative priority\r
+ is. */\r
+ pxCurrentTCB = NULL;\r
+ }\r
+ else\r
+ {\r
+ vTaskSwitchContext();\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+\r
+#endif /* INCLUDE_vTaskSuspend */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( INCLUDE_vTaskSuspend == 1 )\r
+\r
+ static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )\r
+ {\r
+ BaseType_t xReturn = pdFALSE;\r
+ const TCB_t * const pxTCB = xTask;\r
+\r
+ /* Accesses xPendingReadyList so must be called from a critical\r
+ section. */\r
+\r
+ /* It does not make sense to check if the calling task is suspended. */\r
+ configASSERT( xTask );\r
+\r
+ /* Is the task being resumed actually in the suspended list? */\r
+ if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ) != pdFALSE )\r
+ {\r
+ /* Has the task already been resumed from within an ISR? */\r
+ if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )\r
+ {\r
+ /* Is it in the suspended list because it is in the Suspended\r
+ state, or because is is blocked with no timeout? */\r
+ if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) /*lint !e961. The cast is only redundant when NULL is used. */\r
+ {\r
+ xReturn = pdTRUE;\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+\r
+ return xReturn;\r
+ } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */\r
+\r
+#endif /* INCLUDE_vTaskSuspend */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( INCLUDE_vTaskSuspend == 1 )\r
+\r
+ void vTaskResume( TaskHandle_t xTaskToResume )\r
+ {\r
+ TCB_t * const pxTCB = xTaskToResume;\r
+\r
+ /* It does not make sense to resume the calling task. */\r
+ configASSERT( xTaskToResume );\r
+\r
+ /* The parameter cannot be NULL as it is impossible to resume the\r
+ currently executing task. */\r
+ if( ( pxTCB != pxCurrentTCB ) && ( pxTCB != NULL ) )\r
+ {\r
+ taskENTER_CRITICAL();\r
+ {\r
+ if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )\r
+ {\r
+ traceTASK_RESUME( pxTCB );\r
+\r
+ /* The ready list can be accessed even if the scheduler is\r
+ suspended because this is inside a critical section. */\r
+ ( void ) uxListRemove( &( pxTCB->xStateListItem ) );\r
+ prvAddTaskToReadyList( pxTCB );\r
+\r
+ /* A higher priority task may have just been resumed. */\r
+ if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )\r
+ {\r
+ /* This yield may not cause the task just resumed to run,\r
+ but will leave the lists in the correct state for the\r
+ next yield. */\r
+ taskYIELD_IF_USING_PREEMPTION();\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+ taskEXIT_CRITICAL();\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+\r
+#endif /* INCLUDE_vTaskSuspend */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )\r
+\r
+ BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )\r
+ {\r
+ BaseType_t xYieldRequired = pdFALSE;\r
+ TCB_t * const pxTCB = xTaskToResume;\r
+ UBaseType_t uxSavedInterruptStatus;\r
+\r
+ configASSERT( xTaskToResume );\r
+\r
+ /* RTOS ports that support interrupt nesting have the concept of a\r
+ maximum system call (or maximum API call) interrupt priority.\r
+ Interrupts that are above the maximum system call priority are keep\r
+ permanently enabled, even when the RTOS kernel is in a critical section,\r
+ but cannot make any calls to FreeRTOS API functions. If configASSERT()\r
+ is defined in FreeRTOSConfig.h then\r
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
+ failure if a FreeRTOS API function is called from an interrupt that has\r
+ been assigned a priority above the configured maximum system call\r
+ priority. Only FreeRTOS functions that end in FromISR can be called\r
+ from interrupts that have been assigned a priority at or (logically)\r
+ below the maximum system call interrupt priority. FreeRTOS maintains a\r
+ separate interrupt safe API to ensure interrupt entry is as fast and as\r
+ simple as possible. More information (albeit Cortex-M specific) is\r
+ provided on the following link:\r
+ https://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
+\r
+ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
+ {\r
+ if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )\r
+ {\r
+ traceTASK_RESUME_FROM_ISR( pxTCB );\r
+\r
+ /* Check the ready lists can be accessed. */\r
+ if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )\r
+ {\r
+ /* Ready lists can be accessed so move the task from the\r
+ suspended list to the ready list directly. */\r
+ if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )\r
+ {\r
+ xYieldRequired = pdTRUE;\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+\r
+ ( void ) uxListRemove( &( pxTCB->xStateListItem ) );\r
+ prvAddTaskToReadyList( pxTCB );\r
+ }\r
+ else\r
+ {\r
+ /* The delayed or ready lists cannot be accessed so the task\r
+ is held in the pending ready list until the scheduler is\r
+ unsuspended. */\r
+ vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );\r
+ }\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
+\r
+ return xYieldRequired;\r
+ }\r
+\r
+#endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */\r
+/*-----------------------------------------------------------*/\r
+\r
+void vTaskStartScheduler( void )\r
+{\r
+BaseType_t xReturn;\r
+\r
+ /* Add the idle task at the lowest priority. */\r
+ #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
+ {\r
+ StaticTask_t *pxIdleTaskTCBBuffer = NULL;\r
+ StackType_t *pxIdleTaskStackBuffer = NULL;\r
+ uint32_t ulIdleTaskStackSize;\r
+\r
+ /* The Idle task is created using user provided RAM - obtain the\r
+ address of the RAM then create the idle task. */\r
+ vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );\r
+ xIdleTaskHandle = xTaskCreateStatic( prvIdleTask,\r
+ configIDLE_TASK_NAME,\r
+ ulIdleTaskStackSize,\r
+ ( void * ) NULL, /*lint !e961. The cast is not redundant for all compilers. */\r
+ portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */\r
+ pxIdleTaskStackBuffer,\r
+ pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */\r
+\r
+ if( xIdleTaskHandle != NULL )\r
+ {\r
+ xReturn = pdPASS;\r
+ }\r
+ else\r
+ {\r
+ xReturn = pdFAIL;\r
+ }\r
+ }\r
+ #else\r
+ {\r
+ /* The Idle task is being created using dynamically allocated RAM. */\r
+ xReturn = xTaskCreate( prvIdleTask,\r
+ configIDLE_TASK_NAME,\r
+ configMINIMAL_STACK_SIZE,\r
+ ( void * ) NULL,\r
+ portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */\r
+ &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */\r
+ }\r
+ #endif /* configSUPPORT_STATIC_ALLOCATION */\r
+\r
+ #if ( configUSE_TIMERS == 1 )\r
+ {\r
+ if( xReturn == pdPASS )\r
+ {\r
+ xReturn = xTimerCreateTimerTask();\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+ #endif /* configUSE_TIMERS */\r
+\r
+ if( xReturn == pdPASS )\r
+ {\r
+ /* freertos_tasks_c_additions_init() should only be called if the user\r
+ definable macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is\r
+ the only macro called by the function. */\r
+ #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT\r
+ {\r
+ freertos_tasks_c_additions_init();\r
+ }\r
+ #endif\r
+\r
+ /* Interrupts are turned off here, to ensure a tick does not occur\r
+ before or during the call to xPortStartScheduler(). The stacks of\r
+ the created tasks contain a status word with interrupts switched on\r
+ so interrupts will automatically get re-enabled when the first task\r
+ starts to run. */\r
+ portDISABLE_INTERRUPTS();\r
+\r
+ #if ( configUSE_NEWLIB_REENTRANT == 1 )\r
+ {\r
+ /* Switch Newlib's _impure_ptr variable to point to the _reent\r
+ structure specific to the task that will run first. */\r
+ _impure_ptr = &( pxCurrentTCB->xNewLib_reent );\r
+ }\r
+ #endif /* configUSE_NEWLIB_REENTRANT */\r
+\r
+ xNextTaskUnblockTime = portMAX_DELAY;\r
+ xSchedulerRunning = pdTRUE;\r
+ xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;\r
+\r
+ /* If configGENERATE_RUN_TIME_STATS is defined then the following\r
+ macro must be defined to configure the timer/counter used to generate\r
+ the run time counter time base. NOTE: If configGENERATE_RUN_TIME_STATS\r
+ is set to 0 and the following line fails to build then ensure you do not\r
+ have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in your\r
+ FreeRTOSConfig.h file. */\r
+ portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();\r
+\r
+ traceTASK_SWITCHED_IN();\r
+\r
+ /* Setting up the timer tick is hardware specific and thus in the\r
+ portable interface. */\r
+ if( xPortStartScheduler() != pdFALSE )\r
+ {\r
+ /* Should not reach here as if the scheduler is running the\r
+ function will not return. */\r
+ }\r
+ else\r
+ {\r
+ /* Should only reach here if a task calls xTaskEndScheduler(). */\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* This line will only be reached if the kernel could not be started,\r
+ because there was not enough FreeRTOS heap to create the idle task\r
+ or the timer task. */\r
+ configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );\r
+ }\r
+\r
+ /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,\r
+ meaning xIdleTaskHandle is not used anywhere else. */\r
+ ( void ) xIdleTaskHandle;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vTaskEndScheduler( void )\r
+{\r
+ /* Stop the scheduler interrupts and call the portable scheduler end\r
+ routine so the original ISRs can be restored if necessary. The port\r
+ layer must ensure interrupts enable bit is left in the correct state. */\r
+ portDISABLE_INTERRUPTS();\r
+ xSchedulerRunning = pdFALSE;\r
+ vPortEndScheduler();\r
+}\r
+/*----------------------------------------------------------*/\r
+\r
+void vTaskSuspendAll( void )\r
+{\r
+ /* A critical section is not required as the variable is of type\r
+ BaseType_t. Please read Richard Barry's reply in the following link to a\r
+ post in the FreeRTOS support forum before reporting this as a bug! -\r
+ http://goo.gl/wu4acr */\r
+ ++uxSchedulerSuspended;\r
+ portMEMORY_BARRIER();\r
+}\r
+/*----------------------------------------------------------*/\r
+\r
+#if ( configUSE_TICKLESS_IDLE != 0 )\r
+\r
+ static TickType_t prvGetExpectedIdleTime( void )\r
+ {\r
+ TickType_t xReturn;\r
+ UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;\r
+\r
+ /* uxHigherPriorityReadyTasks takes care of the case where\r
+ configUSE_PREEMPTION is 0, so there may be tasks above the idle priority\r
+ task that are in the Ready state, even though the idle task is\r
+ running. */\r
+ #if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )\r
+ {\r
+ if( uxTopReadyPriority > tskIDLE_PRIORITY )\r
+ {\r
+ uxHigherPriorityReadyTasks = pdTRUE;\r
+ }\r
+ }\r
+ #else\r
+ {\r
+ const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01;\r
+\r
+ /* When port optimised task selection is used the uxTopReadyPriority\r
+ variable is used as a bit map. If bits other than the least\r
+ significant bit are set then there are tasks that have a priority\r
+ above the idle priority that are in the Ready state. This takes\r
+ care of the case where the co-operative scheduler is in use. */\r
+ if( uxTopReadyPriority > uxLeastSignificantBit )\r
+ {\r
+ uxHigherPriorityReadyTasks = pdTRUE;\r
+ }\r
+ }\r
+ #endif\r
+\r
+ if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )\r
+ {\r
+ xReturn = 0;\r
+ }\r
+ else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )\r
+ {\r
+ /* There are other idle priority tasks in the ready state. If\r
+ time slicing is used then the very next tick interrupt must be\r
+ processed. */\r
+ xReturn = 0;\r
+ }\r
+ else if( uxHigherPriorityReadyTasks != pdFALSE )\r
+ {\r
+ /* There are tasks in the Ready state that have a priority above the\r
+ idle priority. This path can only be reached if\r
+ configUSE_PREEMPTION is 0. */\r
+ xReturn = 0;\r
+ }\r
+ else\r
+ {\r
+ xReturn = xNextTaskUnblockTime - xTickCount;\r
+ }\r
+\r
+ return xReturn;\r
+ }\r
+\r
+#endif /* configUSE_TICKLESS_IDLE */\r
+/*----------------------------------------------------------*/\r
+\r
+BaseType_t xTaskResumeAll( void )\r
+{\r
+TCB_t *pxTCB = NULL;\r
+BaseType_t xAlreadyYielded = pdFALSE;\r
+\r
+ /* If uxSchedulerSuspended is zero then this function does not match a\r
+ previous call to vTaskSuspendAll(). */\r
+ configASSERT( uxSchedulerSuspended );\r
+\r
+ /* It is possible that an ISR caused a task to be removed from an event\r
+ list while the scheduler was suspended. If this was the case then the\r
+ removed task will have been added to the xPendingReadyList. Once the\r
+ scheduler has been resumed it is safe to move all the pending ready\r
+ tasks from this list into their appropriate ready list. */\r
+ taskENTER_CRITICAL();\r
+ {\r
+ --uxSchedulerSuspended;\r
+\r
+ if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )\r
+ {\r
+ if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )\r
+ {\r
+ /* Move any readied tasks from the pending list into the\r
+ appropriate ready list. */\r
+ while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )\r
+ {\r
+ pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */\r
+ ( void ) uxListRemove( &( pxTCB->xEventListItem ) );\r
+ ( void ) uxListRemove( &( pxTCB->xStateListItem ) );\r
+ prvAddTaskToReadyList( pxTCB );\r
+\r
+ /* If the moved task has a priority higher than the current\r
+ task then a yield must be performed. */\r
+ if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )\r
+ {\r
+ xYieldPending = pdTRUE;\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+\r
+ if( pxTCB != NULL )\r
+ {\r
+ /* A task was unblocked while the scheduler was suspended,\r
+ which may have prevented the next unblock time from being\r
+ re-calculated, in which case re-calculate it now. Mainly\r
+ important for low power tickless implementations, where\r
+ this can prevent an unnecessary exit from low power\r
+ state. */\r
+ prvResetNextTaskUnblockTime();\r
+ }\r
+\r
+ /* If any ticks occurred while the scheduler was suspended then\r
+ they should be processed now. This ensures the tick count does\r
+ not slip, and that any delayed tasks are resumed at the correct\r
+ time. */\r
+ {\r
+ UBaseType_t uxPendedCounts = uxPendedTicks; /* Non-volatile copy. */\r
+\r
+ if( uxPendedCounts > ( UBaseType_t ) 0U )\r
+ {\r
+ do\r
+ {\r
+ if( xTaskIncrementTick() != pdFALSE )\r
+ {\r
+ xYieldPending = pdTRUE;\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ --uxPendedCounts;\r
+ } while( uxPendedCounts > ( UBaseType_t ) 0U );\r
+\r
+ uxPendedTicks = 0;\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+\r
+ if( xYieldPending != pdFALSE )\r
+ {\r
+ #if( configUSE_PREEMPTION != 0 )\r
+ {\r
+ xAlreadyYielded = pdTRUE;\r
+ }\r
+ #endif\r
+ taskYIELD_IF_USING_PREEMPTION();\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+ taskEXIT_CRITICAL();\r
+\r
+ return xAlreadyYielded;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+TickType_t xTaskGetTickCount( void )\r
+{\r
+TickType_t xTicks;\r
+\r
+ /* Critical section required if running on a 16 bit processor. */\r
+ portTICK_TYPE_ENTER_CRITICAL();\r
+ {\r
+ xTicks = xTickCount;\r
+ }\r
+ portTICK_TYPE_EXIT_CRITICAL();\r
+\r
+ return xTicks;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+TickType_t xTaskGetTickCountFromISR( void )\r
+{\r
+TickType_t xReturn;\r
+UBaseType_t uxSavedInterruptStatus;\r
+\r
+ /* RTOS ports that support interrupt nesting have the concept of a maximum\r
+ system call (or maximum API call) interrupt priority. Interrupts that are\r
+ above the maximum system call priority are kept permanently enabled, even\r
+ when the RTOS kernel is in a critical section, but cannot make any calls to\r
+ FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h\r
+ then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
+ failure if a FreeRTOS API function is called from an interrupt that has been\r
+ assigned a priority above the configured maximum system call priority.\r
+ Only FreeRTOS functions that end in FromISR can be called from interrupts\r
+ that have been assigned a priority at or (logically) below the maximum\r
+ system call interrupt priority. FreeRTOS maintains a separate interrupt\r
+ safe API to ensure interrupt entry is as fast and as simple as possible.\r
+ More information (albeit Cortex-M specific) is provided on the following\r
+ link: https://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
+\r
+ uxSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR();\r
+ {\r
+ xReturn = xTickCount;\r
+ }\r
+ portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
+\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+UBaseType_t uxTaskGetNumberOfTasks( void )\r
+{\r
+ /* A critical section is not required because the variables are of type\r
+ BaseType_t. */\r
+ return uxCurrentNumberOfTasks;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+char *pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+{\r
+TCB_t *pxTCB;\r
+\r
+ /* If null is passed in here then the name of the calling task is being\r
+ queried. */\r
+ pxTCB = prvGetTCBFromHandle( xTaskToQuery );\r
+ configASSERT( pxTCB );\r
+ return &( pxTCB->pcTaskName[ 0 ] );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( INCLUDE_xTaskGetHandle == 1 )\r
+\r
+ static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] )\r
+ {\r
+ TCB_t *pxNextTCB, *pxFirstTCB, *pxReturn = NULL;\r
+ UBaseType_t x;\r
+ char cNextChar;\r
+ BaseType_t xBreakLoop;\r
+\r
+ /* This function is called with the scheduler suspended. */\r
+\r
+ if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )\r
+ {\r
+ listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */\r
+\r
+ do\r