Threadx应用讲解
1.应用基础讲解
我们前两章重点讲解了线程的知识,对于操作系统的线程部分已经掌握了足够的了解,这次是基于ThreadX内核操作系统对线程进行的部分操作,在本章节中大家会对之前学习的知识进行实际的应用。
那再次之前,我先讲解关于Threadx的一些基础使用方法。
1.1tx_kernel_enter() —-开启操作系统
对于Threadx操作系统【ps:对每一个操作系统都是】,有启动操作系统步骤。Threadx启动操作系统的步骤就是在主函数调用tx_kernel_enter();
对于**tx_kernel_enter();**函数有这几点需要注意:
- 要在主函数调用:因为它是开启Threadx操作系统,让操作系统进行运行的。在操作系统未运行之前还只是普通的main函数而已。
- 位于此函数上面代码会执行,位于此函数下面代码将不会执行。
- 可将初始化程序,初始化代码放入到主函数的此函数的上面。
- 如果此函数执行,则一定会执行tx_application_define();函数,此函数由用户编写所有关于线程的创建操作。
例如:我创建的历程-创建线程与检测时序的主函数代码块
1 | /******************************************************************************************************************************** |
1.2 tx_application_define —构建threadx个组件功能的初始化代码
对于Threadx操作系统的线程创建部分来说,我们将线程的创建部分代码写入到
*void tx_application_define(void first_unused_memory)
函数里面。这个函数是Threadx操作系统留给我们的一个接口,他被Threadx内部声明,但却没有编写这个函数。对于编写这个函数权限是给你的。你可以在里面编写所有的关于Threadx操作系统初始化的东西。所以综上对于*void tx_application_define(void first_unused_memory) 的总结如下
- 此函数是ThreadX操作系统接口的其中之一。
- 此函数调用权限在ThreadX内部,声明在Threadx内部。但构造(编写)此函数是由我们来做的。所以如果不编写此函数,编译器会报错!!!!。
- 此函数里面可以编写关于操作系统的组件初始化部分的代码。像:线程初始化、信号量初始化、计数器初始化、信号量初始化等等。
- 此函数在构造(编写)的时候要注意函数头要与*void tx_application_define(void first_unused_memory) 一模一样。
*例如:我创建的历程-创建线程与检测时序的void tx_application_define(void first_unused_memory)函数代码块。
1 | /******************************************************************************************************************************** |
对于tx_thread_create();是线程的创建函数,具体内容我会在下面一节中讲解。
1.3 线程优先级分配和最小优先级设置
线程总优先级设置:对于线程优先级,是由我们进行分配的。对于Threadx操作系统来说,是数值越小优先级越大,那优先级最小可以到达哪里呢?是这样的Threadx对于最小优先级是用TX_MAX_PRIORITIES来规定的。对于用户可以设置的优先级的范围是:0~(32-1);对于优先级0来说是系统的最高优先级。这最高优先级中首先里面有一个系统线程用于负责计数器的过期和重新建立,这个线程名字是“System Timer Thread”,至于这个线程具体应用在计数器那一章讲解。回到正题对于TX_MAX_PRIORITIES最小优先级的设置是在tx_port.h里。
1 | /* Define the priority levels for ThreadX. Legal values range |
我们需要更改
1 |
通过分配代表其优先级的数值来创建线程时,ThreadX可以确定线程的重要性。ThreadX优先级的最大数量可以在32到1024之间配置,以32为增量。实际最大优先级的数量由ThreadX库编译期间的TX_MAX_PRIORITIES常数确定。具有较大数量的优先级不会显着增加处理开销。但是,对于每组32个优先级,需要额外的128字节RAM来管理它们。例如,32个优先级需要128个字节的RAM,64个优先级需要256个字节的RAM,96个优先级需要384个字节的RAM。
即可以更改为:
- ```c
#define TX_MAX_PRIORITIES 32 //更改此值1
2
3
2. ```c
#define TX_MAX_PRIORITIES 64 //更改此值 - ```c
#define TX_MAX_PRIORITIES 96 //更改此值1
2
3
4. ```c
#define TX_MAX_PRIORITIES 128 //更改此值 - 等等。每次递增32;即满足公式
$$
最小优先级=最小优先级+32
$$
最小优先级不要超过1024。最小优先级不要设置到0。
注意:这个这是的是最小优先级,还没到用户给线程分配的优先级。用户给线程分配的优先级是由0到TX_MAX_PRIORITIES-1。
1.4 TX_THREAD 线程控制块
每个线程的特征都包含在其控制块中。此结构在tx_api.h文件中定义。
线程的控制块可以位于内存中的任何位置,但是最常见的是通过在任何函数范围之外定义控制块来使其成为全局结构。
就像所有动态分配的内存一样,将控制块定位在其他区域也需要多加注意。如果在C函数中分配了控制块,则与其关联的内存将成为调用线程堆栈的一部分。通常,避免对控制块使用本地存储,因为函数返回后,将释放其所有本地变量堆栈空间,而不管另一个线程是否正在将其用于控制块。
在大多数情况下,应用程序会忽略线程控制块的内容。但是,在某些情况下,尤其是在调试期间,查看某些成员很有用。以下是一些更有用的控制块成员。
tx_thread_run_count包含一个计数器,该计数器已对该线程进行了多次调度。计数器增加表示线程正在调度和执行。
tx_thread_state包含关联线程的状态。下面列出了可能的线程状态
2.tx_thread_create—-线程的创建
函数原型:
1 | UINT tx_thread_create( |
函数作用:创建应用线程
函数解析:该服务创建一个应用程序线程,该线程在指定的任务输入功能处开始执行。堆栈、优先级、抢占阈值和时间片是输入参数指定的属性。另外,还指定了线程初始执行状态。
参数:
thread_ptr:指向线程控制块的指针。
name_ptr:指向线程名称的指针。
entry_function:指定用于线程执行的初始C函数。当线程从此入口函数返回时,它将处于完成状态并无限期挂起。即函数必须是**void 函数名字(ULONG thread_input);**格式
entry_input:一个32位值,该值在首次执行时传递给线程的入口函数。此输入的使用完全由应用程序确定。其实也是就是我们在调用函数的时候往函数里面写的形参例:Key_scan(1);就是这个1。
stack_start:堆栈存储区的起始地址。即用于存储线程变量和运算结果的地方。通常使用一个数组,其起始地址就是**&数组名字[0]或数组名字**。
1
2
3int a[10];
&a[0] //起始地址的第一种表示方法
a //起始地址的第二种表达方法stack_size:堆栈存储区中的字节数。线程的堆栈区域必须足够大以处理最坏情况的函数调用嵌套和局部变量使用。例一个整形变量字节是4个,现在1个整形数组里面有10个整形变量,问:现在字节数是多少?答:40。
priority:线程的数字优先级。有效值的范围是0到(TX_MAX_PRIORITES-1),其中0表示最高优先级。
preempt_threshold:禁用的抢占的最高优先级(0到(TX_MAX_PRIORITIES-1))。只有高于此级别的优先级才可以抢占该线程。该值必须小于或等于指定的优先级。等于线程优先级的值将禁用抢占阈值。
time_slice允许在同一优先级的其他就绪线程运行之前,允许该线程运行的计时器计数。请注意,使用抢占阈值将禁用时间片。合法的时间片值范围是1到0xFFFFFFFF(包括0)。值为TX_NO_TIME_SLICE(值为0)禁用此线程的时间切片。
-------------本文结束感谢您的阅读-------------
本文链接: http://1ywd1.github.io/2021/02/15/Threadx%E7%AC%AC%E5%85%AD%E7%AB%A0%E8%AE%B2%E8%A7%A3/
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!