freeRTOS源码解析4--tasks.c 7
4.2.20 空闲任务调用1--prvCheckTasksWaitingTermination删除所有终止的任务, 释放资源。简单描述就是清空xTasksWaitingTermination列表,释放资源,递减uxCurrentNumberOfTasks和uxDeletedTasksWaitingCleanUp。
接口:
static void prvCheckTasksWaitingTermination( void )
接口代码如下:
1 static void prvCheckTasksWaitingTermination( void )
2 {
3 /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/
4
5 #if ( INCLUDE_vTaskDelete == 1 )
6 {
7 TCB_t * pxTCB;
8
9 /* uxDeletedTasksWaitingCleanUp is used to prevent taskENTER_CRITICAL()
10 * being called too often in the idle task. */
11 while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
12 {
13 #if ( configNUMBER_OF_CORES == 1 )
14 {
15 taskENTER_CRITICAL();
16 {
17 {
18 /* 从终止列表中取出任务 */
19 pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
20 /* 将任务从终止列表中移出 */
21 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
22 --uxCurrentNumberOfTasks;
23 --uxDeletedTasksWaitingCleanUp;
24 }
25 }
26 taskEXIT_CRITICAL();
27
28 prvDeleteTCB( pxTCB ); // 释放任务资源
29 }
30 #endif /* #if( configNUMBER_OF_CORES == 1 ) */
31 }
32 }
33 #endif /* INCLUDE_vTaskDelete */
34 }prvCheckTasksWaitingTermination4.2.21 空闲任务调用2--prvGetExpectedIdleTime
这个用于低功耗,主要作用是获取期望睡眠的tick时间。
接口:
static TickType_t prvGetExpectedIdleTime( void )
返回:实际返回的是最近唤醒任务的剩余tick数,即最多能够睡眠这么多tick数后就要苏醒了,因为有任务延迟结束需要唤醒了。
接口代码如下:
1 static TickType_t prvGetExpectedIdleTime( void )
2 {
3 TickType_t xReturn;
4 UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;
5
6 /* uxHigherPriorityReadyTasks takes care of the case where
7 * configUSE_PREEMPTION is 0, so there may be tasks above the idle priority
8 * task that are in the Ready state, even though the idle task is
9 * running. */
10 /* uxHigherPriorityReadyTasks用于configUSE_PREEMPTION为0的情况, 因为有可能
11 * 存在空闲任务在运行时, 也有高于空闲任务优先级的任务处于就绪态。如果是抢占
12 * 式的调度的话, 则不可能会有更高优先级的任务就绪, 否则根本轮不到空闲任务
13 * 运行。 */
14 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
15 {
16 if( uxTopReadyPriority > tskIDLE_PRIORITY )
17 {
18 uxHigherPriorityReadyTasks = pdTRUE;
19 }
20 }
21 #else
22 {
23 const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01;
24
25 /* When port optimised task selection is used the uxTopReadyPriority
26 * variable is used as a bit map.If bits other than the least
27 * significant bit are set then there are tasks that have a priority
28 * above the idle priority that are in the Ready state.This takes
29 * care of the case where the co-operative scheduler is in use. */
30 if( uxTopReadyPriority > uxLeastSignificantBit )
31 {
32 uxHigherPriorityReadyTasks = pdTRUE;
33 }
34 }
35 #endif /* if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) */
36
37 /* 这里一样, 抢占式的话当前任务就是空闲任务, 所以下面的判断除了最后的else,
38 * 其他都只有非抢占式的才有可能进, 抢占式的就直接看最后的else即可。 */
39 if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
40 {
41 xReturn = 0;
42 }
43 else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1U )
44 {
45 /* There are other idle priority tasks in the ready state.If
46 * time slicing is used then the very next tick interrupt must be
47 * processed. */
48 /* 和空闲任务同优先级的话, 应该也是先运行其他任务最后运行空闲任务 */
49 xReturn = 0;
50 }
51 else if( uxHigherPriorityReadyTasks != pdFALSE )
52 {
53 /* There are tasks in the Ready state that have a priority above the
54 * idle priority.This path can only be reached if
55 * configUSE_PREEMPTION is 0. */
56 xReturn = 0;
57 }
58 else
59 {
60 /* 这里算出来的值是最近唤醒的任务的剩余tick数 */
61 xReturn = xNextTaskUnblockTime;
62 xReturn -= xTickCount;
63 }
64
65 return xReturn;
66 }prvGetExpectedIdleTime 4.2.22 空闲任务调用3--vPortSuppressTicksAndSleep
这个接口就是用于进入低功耗模式的,由于这个和具体的平台相关,所以定义在port.c中,这里只看cortex-m3和m4核的代码。
这个接口个人认为非常复杂,里面有一些计算流程本人也不是很明白,还需要以后反复开发和阅读才能理解。
接口:
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
__weak:如果没有__weak修饰的相同接口定义了,则用新定义的接口,否则就使用该接口,类似与多态,需要编译器支持,非c标准。
参数1:xExpectedIdleTime,4.2.21的接口计算返回的tick数。
前置接口1:eSleepModeStatus eTaskConfirmSleepModeStatus( void ),用于确定是否真的需要进入低功耗模式。
返回:eSleepModeStatus,eAbortSleep:不进入,eStandardSleep:进入但休眠时间不高于xExpectedIdleTime,eNoTasksWaitingTimeout:进入但只能依靠外部中断唤醒。
1 eSleepModeStatus eTaskConfirmSleepModeStatus( void )
2 {
3 #if ( INCLUDE_vTaskSuspend == 1 )
4 /* The idle task exists in addition to the application tasks. */
5 const UBaseType_t uxNonApplicationTasks = configNUMBER_OF_CORES;
6 #endif /* INCLUDE_vTaskSuspend */
7
8 eSleepModeStatus eReturn = eStandardSleep;
9
10 /* This function must be called from a critical section. */
11
12 /* 此时调度器暂停, 有必要检查一下是否有任务就绪了, 或者调度延迟了,
13 * 或者有tick中断处理被延迟了 */
14 if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0U )
15 {
16 /* A task was made ready while the scheduler was suspended. */
17 eReturn = eAbortSleep;
18 }
19 else if( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE )
20 {
21 /* A yield was pended while the scheduler was suspended. */
22 eReturn = eAbortSleep;
23 }
24 else if( xPendedTicks != 0U )
25 {
26 /* A tick interrupt has already occurred but was held pending
27 * because the scheduler is suspended. */
28 eReturn = eAbortSleep;
29 }
30
31 #if ( INCLUDE_vTaskSuspend == 1 )
32 else if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
33 {
34 /* If all the tasks are in the suspended list (which might mean they
35 * have an infinite block time rather than actually being suspended)
36 * then it is safe to turn all clocks off and just wait for external
37 * interrupts. */
38 /* 如果所有的任务都在挂起列表中(即使是那些等待事件且无限延迟的任务有),
39 * 那么可以停止时钟并等待外部中断 */
40 eReturn = eNoTasksWaitingTimeout;
41 }
42 #endif /* INCLUDE_vTaskSuspend */
43 else
44 {
45 mtCOVERAGE_TEST_MARKER();
46 }
47
48 return eReturn;
49 } 前置接口2:void vTaskStepTick( TickType_t xTicksToJump )
参数:xTicksToJump--休眠的tick数,用于更新xTickCount值。
1 void vTaskStepTick( TickType_t xTicksToJump )
2 {
3 TickType_t xUpdatedTickCount;
4
5 /* Correct the tick count value after a period during which the tick
6 * was suppressed.Note this does *not* call the tick hook function for
7 * each stepped tick. */
8 xUpdatedTickCount = xTickCount + xTicksToJump;
9 configASSERT( xUpdatedTickCount <= xNextTaskUnblockTime );
10
11 if( xUpdatedTickCount == xNextTaskUnblockTime )
12 {
13 /* Arrange for xTickCount to reach xNextTaskUnblockTime in
14 * xTaskIncrementTick() when the scheduler resumes.This ensures
15 * that any delayed tasks are resumed at the correct time. */
16 /* 有任务到达唤醒时间了, 使xPendedTicks自增, 让xTaskIncrementTick()
17 * 接口去实现任务的唤醒 */
18 configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U );
19 configASSERT( xTicksToJump != ( TickType_t ) 0 );
20
21 /* Prevent the tick interrupt modifying xPendedTicks simultaneously. */
22 taskENTER_CRITICAL();
23 {
24 xPendedTicks++;
25 }
26 taskEXIT_CRITICAL();
27 xTicksToJump--; // xPendedTicks已自增了, xTicksToJump就需要少算一个
28 }
29 else
30 {
31 mtCOVERAGE_TEST_MARKER();
32 }
33
34 // 更新xTickCount值
35 xTickCount += xTicksToJump;
36 }vPortSuppressTicksAndSleep
这一篇内容较多,也较难,日后如果有问题的地方,笔者再回来更新。好了,下篇再见!
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页:
[1]