论坛原始地址(持续更新):http://www.armbbs.cn/forum.php?mod=viewthread&tid=99514
本章节主要为大家讲解ThreadX任务优先级设置的注意事项、任务优先级的分配方案及其相关的一个例子,内容相对比较简单。
12.1 任务优先级说明
12.2 任务优先级分配方案
12.3 中断优先级和任务优先级的区别
12.4 任务优先级修改函数tx_thread_priority_change
12.5 任务优先级获取函数tx_thread_info_get
12.6 实验例程说明
12.7 总结
下面对ThreadX优先级相关的几个重要知识点进行下说明,这些知识点在以后的使用中务必要掌握牢固。
1、 ThreadX中任务的最大优先级数值是通过tx_port.h文件中的TX_MAX_PRIORITIES进行配置的,用户实际可以使用的优先级范围是0到configMAX_PRIORITIES – 1。比如我们配置此宏定义为32,那么用户可以使用的优先级号是0到31,不包含32,对于这一点,初学者要特别的注意。并且TX_MAX_PRIORITIES的宏定义设置的数值必须是32的整数倍:
#define TX_MAX_PRIORITIES 32
2、 用户配置任务的优先级数值越小,那么此任务的优先级越低(0是最高优先级任务),ThreadX没有空闲任务,如果大家创建空闲任务,需要将其设置为最低优先级。
3、 建议用户配置宏定义TX_MAX_PRIORITIES的最大值不要超过32,即用户任务可以使用的优先级范围是0到31。
ULONG _tx_thread_preempted_maps[TX_MAX_PRIORITIES/32];
如果TX_MAX_PRIORITIES设置为32,那么仅需一个32bit变量就可以方便记录32不同优先级任务,程序运行时查找最高优先级任务也方便。
4、 ThreadX中处于运行状态的任务永远是当前能够运行的最高优先级任务。下一章节讲解调度器,大家会对这个知识点有一个全面的认识。
对于初学者,有时候会纠结任务优先级设置为多少合适,因为任务优先级设置多少是没有标准的。对于这个问题,我们这里为大家推荐一个标准,任务优先级设置推荐方式如下图所示:
这里的优先级分配方案是我们推荐的一种方式,实际项目也可以不采用这种方法。调试出适合项目需求的才是最好的。
部分初学者也容易在这两个概念上面出现问题。简单的说,这两个之间没有任何关系,不管中断的优先级是多少,中断的优先级永远高于任何任务的优先级,即任务在执行的过程中,中断来了就开始执行中断服务程序。
另外对于STM32来说,中断优先级的数值越小,优先级越高。同样,ThreadX的任务优先级也是任务优先级数值越小,任务优先级越高。
函数原型:
UINT tx_thread_priority_change(
TX_THREAD *thread_ptr,
UINT new_priority,
UINT *old_priority);
函数描述:
函数tx_thread_priority_change用于实现ThreadX任务优先级的修改。
注意事项:
使用举例:
TX_THREAD AppTaskUserIFTCB;
UINT OldPriority;
/*优先级将其设置为6 */
tx_thread_priority_change(&AppTaskUserIFTCB, 6, &OldPriority);
函数原型:
UINT tx_thread_info_get(
TX_THREAD *thread_ptr,
CHAR **name,
UINT *state,
ULONG *run_count,
UINT *priority,
UINT *preemption_threshold,
ULONG *time_slice,
TX_THREAD **next_thread,
TX_THREAD **suspended_thread);
函数描述:
函数tx_thread_info_get不仅仅可用于获取ThreadX任务优先级。还可以获取其它相关信息。
1、 第1个参数thread_ptr是任务句柄,用于区分不同的任务。
2、 第2个参数name用于获取任务名。
3、 第3个参数state用于获取任务状态,可能的值如下所示。
4、 第4个参数run_count用于获取任务运行计数。
5、 第5个参数priority用于获取任务优先级。
6、 第6个参数preemption_threshold用于获取抢占阀值。
7、 第7个参数time_slice用于获取时间片。
8、 第8个参数next_thread指向下一个创建的任务句柄。
9、 第9个参数suspended_thread指向挂起列表中下一个任务句柄。
10、 返回值
注意事项:
使用举例:
TX_THREAD AppTaskUserIFTCB;
CHAR *name;
UINT state;
ULONG run_count;
UINT priority;
UINT preemption_threshold;
UINT time_slice;
TX_THREAD *next_thread;
TX_THREAD *suspended_thread;
UINT status;
status = tx_thread_info_get(&AppTaskUserIFTCB,
&name,
&state,
&run_count,
&priority,
&preemption_threshold,
&time_slice,
&next_thread,
&suspended_thread);
配套例子:
V7-3007_ThreadX Task Priority Change
实验目的:
实验内容:
1、共创建了如下几个任务,通过按下按键K1可以通过串口或者RTT打印任务堆栈使用情况
===================================================
OS CPU Usage = 1.94%
===================================================
Prio StackSize CurStack MaxStack Taskname
2 4092 383 391 App Task Start
3 4092 543 659 App Msp Pro
4 4092 391 391 App Task UserIF
5 4092 543 659 App Task COM
30 1020 519 519 App Task STAT
31 1020 143 71 App Task IDLE
0 1020 391 391 System Timer Thread
串口软件可以使用SecureCRT或者H7-TOOL RTT查看打印信息。
App Task Start任务 :启动任务,这里用作BSP驱动包处理。
App Task MspPro任务 :消息处理,这里未使用。
App Task UserIF任务 :按键消息处理。
App Task COM任务 :这里用作LED闪烁。
App Task STAT任务 :统计任务
App Task IDLE任务 :空闲任务
System Timer Thread任务:系统定时器任务
2、 (1) 凡是用到printf函数的全部通过函数App_Printf实现。
(2) App_Printf函数做了信号量的互斥操作,解决资源共享问题。
3、默认上电是通过串口打印信息,如果使用RTT打印信息
(1) MDK AC5,MDK AC6或IAR通过使能bsp.h文件中的宏定义为1即可
#define Enable_RTTViewer 1
(2) Embedded Studio继续使用此宏定义为0, 因为Embedded Studio仅制作了调试状态RTT方式查看。
实验操作:
串口打印信息方式(AC5,AC6和IAR):
波特率 115200,数据位 8,奇偶校验位无,停止位 1
RTT打印信息方式(AC5,AC6和IAR):
Embedded Studio仅支持调试状态RTT打印:
由于Embedded Studio不支持中文,所以中文部分显示乱码,不用管。
程序执行框图:
本章节内容相对比较容易,重点是学习任务优先级分配方案,随着后面的学习,初学者需要慢慢积累这方面的经验。