freeRTOS源码解析4--tasks.c 5

news/2024/11/18 2:35:18/文章来源:https://www.cnblogs.com/freeManX1807/p/18425725

4.2.13 继续任务--vTaskResume

接口:
void vTaskResume( TaskHandle_t xTaskToResume )
形参1:xTaskToResume ,想要继续的任务handle;

首先是vTaskResume调用的一个内部函数:static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ),用于检查任务是否是挂起状态,只有挂起的任务才能继续,否则是等待事件、通知等处于阻塞态,那就不能放到就绪列表,必须继续等待。这个接口逻辑非常简单,就直接看代码即可。

 1 static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )
 2 {
 3     BaseType_t xReturn = pdFALSE;
 4     const TCB_t * const pxTCB = xTask;
 5 
 6     /* Accesses xPendingReadyList so must be called from a critical
 7      * section. */
 8 
 9     /* It does not make sense to check if the calling task is suspended. */
10     configASSERT( xTask );
11 
12     /* Is the task being resumed actually in the suspended list? */
13     /* 检查任务是否在挂起列表, 不在则说明任务未挂起 */
14     if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ) != pdFALSE )
15     {
16         /* Has the task already been resumed from within an ISR? */
17         /* 任务在挂起列表里, 但在调度器暂停时被移至等待就绪列表中, 则说明任务未挂起 */
18         if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
19         {
20             /* Is it in the suspended list because it is in the Suspended
21              * state, or because it is blocked with no timeout? */
22             /* 任务在挂起列表里, 但在等待事件, 则说明任务未挂起 */
23             if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE )
24             {
25                 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
26                 {
27                     BaseType_t x;
28 
29                     /* The task does not appear on the event list item of
30                      * and of the RTOS objects, but could still be in the
31                      * blocked state if it is waiting on its notification
32                      * rather than waiting on an object.  If not, is
33                      * suspended. */
34                     /* 任务在挂起列表里, 且未等待事件, 那么如果在等待通知则未挂起, 否则挂起 */
35                     xReturn = pdTRUE;
36 
37                     for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ )
38                     {
39                         if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION )
40                         {
41                             xReturn = pdFALSE;
42                             break;
43                         }
44                     }
45                 }
46                 #else /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
47                 {
48                     xReturn = pdTRUE;
49                 }
50                 #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
51             }
52             else
53             {
54                 mtCOVERAGE_TEST_MARKER();
55             }
56         }
57         else
58         {
59             mtCOVERAGE_TEST_MARKER();
60         }
61     }
62     else
63     {
64         mtCOVERAGE_TEST_MARKER();
65     }
66 
67     /* 总结下来就是任务若在挂起列表里, 如果不是在等待事件或通知, 则是挂起状态, 否则不是 */
68 
69     return xReturn;
70 }
prvTaskIsTaskSuspended
 1 void vTaskResume( TaskHandle_t xTaskToResume )
 2 {
 3     TCB_t * const pxTCB = xTaskToResume;
 4 
 5     /* It does not make sense to resume the calling task. */
 6     configASSERT( xTaskToResume );
 7 
 8     #if ( configNUMBER_OF_CORES == 1 )
 9         /* The parameter cannot be NULL as it is impossible to resume the
10          * currently executing task. */
11         if( ( pxTCB != pxCurrentTCB ) && ( pxTCB != NULL ) )
12     #endif
13     {
14         taskENTER_CRITICAL();
15         {
16             if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
17             {
18                 /* The ready list can be accessed even if the scheduler is
19                  * suspended because this is inside a critical section. */
20                 /* 只有任务处于挂起状态才能继续 */
21                 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
22                 prvAddTaskToReadyList( pxTCB );
23 
24                 /* This yield may not cause the task just resumed to run,
25                  * but will leave the lists in the correct state for the
26                  * next yield. */
27                 /* 保证各任务列表处于正常的状态 */
28                 taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxTCB );
29             }
30             else
31             {
32                 mtCOVERAGE_TEST_MARKER();
33             }
34         }
35         taskEXIT_CRITICAL();
36     }
37     else
38     {
39         mtCOVERAGE_TEST_MARKER();
40     }
41 }
vTaskResume

4.2.14 启动调度--vTaskStartScheduler

 这个接口会创建空闲任务和软定时器任务,之后就是允许第一个任务,这个接口永远也不会返回,也是main中调用的最后一个接口。

 1 void vTaskStartScheduler( void )
 2 {
 3     BaseType_t xReturn;
 4 
 5     /* 创建空闲任务 */
 6     xReturn = prvCreateIdleTasks();
 7 
 8     #if ( configUSE_TIMERS == 1 )
 9     {
10         if( xReturn == pdPASS )
11         {
12             xReturn = xTimerCreateTimerTask();    // 创建软定时器任务
13         }
14         else
15         {
16             mtCOVERAGE_TEST_MARKER();
17         }
18     }
19     #endif /* configUSE_TIMERS */
20 
21     if( xReturn == pdPASS )
22     {
23         /* Interrupts are turned off here, to ensure a tick does not occur
24          * before or during the call to xPortStartScheduler().  The stacks of
25          * the created tasks contain a status word with interrupts switched on
26          * so interrupts will automatically get re-enabled when the first task
27          * starts to run. */
28         /* 关闭中断, 保证在调用xPortStartScheduler前不会发生tick中断, 所有创建
29          * 的任务的栈中都包含一个中断开启的状态字, 所以第一个任务运行时, 中断
30          * 会自动开启 */
31         /* 暂时没看懂这个注释的意思, 但这个接口只是设置了中断优先级屏蔽寄存器,
32          * 实际的中断并未关闭, 系统中断被屏蔽了 */
33         portDISABLE_INTERRUPTS();
34 
35         xNextTaskUnblockTime = portMAX_DELAY;
36         xSchedulerRunning = pdTRUE;
37         xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
38 
39         /* If configGENERATE_RUN_TIME_STATS is defined then the following
40          * macro must be defined to configure the timer/counter used to generate
41          * the run time counter time base.   NOTE:  If configGENERATE_RUN_TIME_STATS
42          * is set to 0 and the following line fails to build then ensure you do not
43          * have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in your
44          * FreeRTOSConfig.h file. */
45         portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
46 
47         /* Setting up the timer tick is hardware specific and thus in the
48          * portable interface. */
49 
50         /* The return value for xPortStartScheduler is not required
51          * hence using a void datatype. */
52         /* 真正的启动调度器, 即启动了第一个任务 */
53         ( void ) xPortStartScheduler();
54 
55         /* In most cases, xPortStartScheduler() will not return. If it
56          * returns pdTRUE then there was not enough heap memory available
57          * to create either the Idle or the Timer task. If it returned
58          * pdFALSE, then the application called xTaskEndScheduler().
59          * Most ports don't implement xTaskEndScheduler() as there is
60          * nothing to return to. */
61     }
62     else
63     {
64         /* This line will only be reached if the kernel could not be started,
65          * because there was not enough FreeRTOS heap to create the idle task
66          * or the timer task. */
67         configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );
68     }
69 
70     /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,
71      * meaning xIdleTaskHandles are not used anywhere else. */
72     ( void ) xIdleTaskHandles;
73 
74     /* OpenOCD makes use of uxTopUsedPriority for thread debugging. Prevent uxTopUsedPriority
75      * from getting optimized out as it is no longer used by the kernel. */
76     ( void ) uxTopUsedPriority;
77 }
vTaskStartScheduler

 

4.2.15 停止调度--vTaskEndScheduler

这个接口和上一个相对,而且这个接口一定是在某个任务中调用的,因为系统不会主动停止调度器,而正常运行中始终只有某个任务和系统在运行,所以必然是某个任务主动调用的。

 1 void vTaskEndScheduler( void )
 2 {
 3     #if ( INCLUDE_vTaskDelete == 1 )
 4     {
 5         BaseType_t xCoreID;
 6 
 7         #if ( configUSE_TIMERS == 1 )
 8         {
 9             /* Delete the timer task created by the kernel. */
10             /* 删除软定时器任务 */
11             vTaskDelete( xTimerGetTimerDaemonTaskHandle() );
12         }
13         #endif /* #if ( configUSE_TIMERS == 1 ) */
14 
15         /* Delete Idle tasks created by the kernel.*/
16         for( xCoreID = 0; xCoreID < ( BaseType_t ) configNUMBER_OF_CORES; xCoreID++ )
17         {
18             vTaskDelete( xIdleTaskHandles[ xCoreID ] );    // 删除空闲任务
19         }
20 
21         /* Idle task is responsible for reclaiming the resources of the tasks in
22          * xTasksWaitingTermination list. Since the idle task is now deleted and
23          * no longer going to run, we need to reclaim resources of all the tasks
24          * in the xTasksWaitingTermination list. */
25         /* 本应由空闲任务回收待删除任务的资源, 但现在空闲任务被删除了, 就在这里处理 */
26         prvCheckTasksWaitingTermination();
27     }
28     #endif /* #if ( INCLUDE_vTaskDelete == 1 ) */
29 
30     /* Stop the scheduler interrupts and call the portable scheduler end
31      * routine so the original ISRs can be restored if necessary.  The port
32      * layer must ensure interrupts enable  bit is left in the correct state. */
33     /* 这跟启动调度器时关中断一样的疑问 */
34     portDISABLE_INTERRUPTS();
35     xSchedulerRunning = pdFALSE;
36 
37     /* This function must be called from a task and the application is
38      * responsible for deleting that task after the scheduler is stopped. */
39     vPortEndScheduler();
40 }
vTaskEndScheduler

 

  好了,下一篇讲xTaskAbortDelay和xTaskIncrementTick接口,这两个接口较为复杂。

  下篇再见。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/801735.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL 必知概念

Delete、Drop 和 Truncatedelete、truncate 仅仅删除表里面的数据,drop会把表的结构也删除 delete 是 DML 语句,操作完成后,可以回滚,truncate 和 drop 是 DDL 语句,删除之后立即生效,不能回滚 执行效率:drop > truncate > deleteMyISAM 与 InnoDBInnoDB 支持事务…

视野修炼-技术周刊第102期 | js 编译运行C

① Bun 现在允许直接在js中直接编译运行 C ! ② caniuse-cli ③ SSL证书管理工具 ④ 好的重构与坏的重构 ⑤ sisi - 命令行图片检索工具 ⑥ cvbee.ai - AI 简历生成欢迎来到第 102 期的【视野修炼 - 技术周刊】,下面是本期的精选内容简介 🔥强烈推荐Bun 现在允许直接在js中…

【vulhub】Discuz-命令执行 wooyun-2010-080723

【vulhub】Discuz-命令执行 wooyun-2010-080723 ​docker-compose up-d​启动! ​​ wooyun-2010-080723 命令执行 0x01 搭建环境 访问192.168.132.138:8080/install​,安装数据库。数据库服务器填写db(必须db,不然安装失败),数据库名为discuz,数据库账号密码均为root,…

华科python与人工智能实践(公选)教程

python基础 软件下载 1.python下载安装 点击此链接进入官网windows下载地址点击箭头处链接下载最新版本,进入页面后下拉根据你的机器下载对应版本,一般人使用的是X86架构windos系统,下载箭头所指即可 若是不知道CPU架构,可见查看cpu架构,x86还是arm 下载后根据指引进行安装…

2376.统计特殊整数

如果一个正整数每一个数位都是 互不相同 的,我们称它是 特殊整数 。 给你一个 正 整数 n ,请你返回区间 [1, n] 之间特殊整数的数目。 示例 1: 输入:n = 20 输出:19 解释:1 到 20 之间所有整数除了 11 以外都是特殊整数。所以总共有 19 个特殊整数。 示例 2: 输入:n = …

数业智能心大陆:职场倦怠的新解法

什么是职业倦怠? 在职场中,职业倦怠的表现形式丰富多样。从数业智能心大陆 AI 心理咨询平台的数据来看,职业倦怠呈现出多种状态。教师可能对教学不再满怀热情,精心备课也成为过去式;情绪上容易烦躁、易怒,在工作压力之下,常常因为一些小事就被激怒。比如在项目团队中,成…

2024“华为杯”数模研赛E数据提取代码

2024年数学建模研究生赛E题从视频中提取数据的代码。主要包括三个部分:车流量计算、各车道车流量计算和平均速度计算。主要讲述了代码的使用方法,包括需要修改的参数和文件路径,以及一些特殊情况的处理方法。同时还提供了参数估计和绘图的相关代码,以及如何根据不同视频视角…

用Eide下配合Cubemx配置stm32环境

PS:本篇为个人学习的记录,一是方便回忆,二是相同时方便给像我一样的小白一点建议。本文默认已安装好STM32Cubemx和VSCode,以及VsCode下的Eide Cubemx部分选择好需要使用的对应单片机创建工程。在Project Manager选项下 选择Toolchain/IDE下的makefile方式来创建工程。什么是…

USB2.0设备的休眠挂起及远程唤醒

USB可见设备状态,分为连接(Attached),上电(Powered),默认(Default),地址(Address),配置(Configured)和挂起(Suspended)6个状态。所谓可见,即USB系统和主机可见的状态,其他状态属于USB设备内部而不可见。其中有关电源的,大致可分下面三类:连接状态(Attached):设备连…

CSP-S 2024 提高组初赛解析(更新至单项选择)

单项选择 1在 Linux 系统中,如果你想显示当前工作目录的路径,应该使用哪个命令? A pwd B cd C ls D echopwd : print working directory cd : 跳转到指定目录 ls : 列出当前目录的所有子文件和子文件夹 echo : 输出指定内容 2假设一个长度为n的整数数组中每个元索值互不相同…

[CVPR2024]DeiT-LT Distillation Strikes Back for Vision Transformer Training on Long-Tailed Datasets

在长尾数据集上,本文引入强增强(文中也称为OOD)实现对DeiT的知识蒸馏的改进,实现尾部类分类性能的提升。 动机ViT相较于CNN缺少归纳偏置,如局部性(一个像素与周围的区域关系更紧密)、平移不变性(图像的主体在图像的任意位置都应该一样重要)。因此需要大型数据集进行预…