作者:zzssdd2
E-mail:zzssdd2@foxmail.com
一、前言
了解ThreadX
的初始化流程有助于移植使用,掌握任务的的调度有助于更加得心应手地运用该实时操作系统。
二、初始化流程
官方手册给出的ThreadX初始化流程如下图所示:
以STM32F429 + MDK-ARM-AC6平台举例,初始化流程的前3步在startup_stm32f429xx.s
文件中完成 ,该启动文件内容是STM32复位后首先执行的,主要完成以下操作:
- 设置堆栈( __initial_sp、__heap_base、__heap_limit)
- 设置中断向量表(__Vectors)
- 设置复位入口程序(Reset_Handler)
- 链接到C库中的__main,最终进入到main()函数
进入main()函数后开始进行ThreadX的x相关初始化,后面几步更详细的调用流程如下所示:
关于STM32移植ThreadX更详细的过程可以参考这篇文章:ThreadX移植——STM32H7+MDK-AC6平台
三、线程状态
理解线程的不同处理状态是理解整个多线程环境的关键因素。在ThreadX中包含5种不同的线程状态:就绪
、挂起
、执行
、终止
和完成
。下图展示了ThreadX的线程状态转换图:
- 当线程准备执行时处于就绪状态,就绪线程只有在它是处于就绪线程列表的最高优先级时才会执行。当线程开始执行时其状态由就绪态转为运行态
- 如果更高优先级的线程准备就绪,则执行线程将恢复到就绪状态。然后执行新准备好的高优先级线程,将其逻辑状态更改为运行态。每次发生线程抢占时,都会发生就绪状态和运行状态之间的转换。
- 在任何给定的时刻,只有一个线程处于执行状态。这是因为处于执行状态的线程对底层处理器具有控制权。
- 处于挂起状态的线程不符合执行条件。处于挂起状态的原因包括时间挂起、队列消息、信号量、互斥、事件标志、内存和基本线程挂起。在清除挂起的原因后,线程将恢复到就绪状态。
- 处于完成状态的线程是已完成其任务处理并从其入口函数返回的线程。 入口函数是在线程创建期间指定的。 处于完成状态的线程无法再次执行。
- 线程处于终止状态是因为另一个线程或是线程本身调用tx_thread_terminate服务。线程处于终止状态将无法再次执行。
- 如果需要重新启动已完成或终止的线程,应用程序必须首先删除该线程。然后可以重新创建并重新启动它。
四、配置选项
在使用ThreadX时,有一些配置选项可供选择。这些选项包含在tx_user.h文件中。要使用这些配置项的前提是工程编译时包含TX_INCLUDE_USER_DEFINE_FILE 宏定义。
-
TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
定义后,此选项可在字节池上收集性能信息。默认情况下,未定义此选项。
-
TX_DISABLE_ERROR_CHECKING
绕过基本服务呼叫错误检查。在应用程序源中定义时,将禁用所有基本参数错误检查。这可以将性能提高多达30%,并且还可以减小镜像大小。
注意:只有在应用程序可以绝对保证所有输入参数在所有情况下始终有效的情况下,才可以禁用错误检查,包括从外部输入派生的输入参数。如果在禁用错误检查的情况下向API提供了无效的输入,则导致的行为是不确定的,并且可能导致内存损坏或系统崩溃。
注意:不受禁用错误检查影响的ThreadX API返回值在第4章的每个API描述的“返回值”部分中以粗体列出。如果通过使用TX_DISABLE_ERROR_CHECKING选项禁用了错误检查,则非粗体返回值将无效。
-
TX_DISABLE_NOTIFY_CALLBACKS
定义后,将为各种ThreadX对象禁用通知回调。使用此选项可略微减小代码大小并提高性能。默认情况下,未定义此选项。
-
TX_DISABLE_PREEMPTION_THRESHOLD
定义后,将禁用抢占阈值功能,并略微减小代码大小并提高性能。当然,抢占阈值功能不再可用。默认情况下,未定义此选项。
-
TX_DISABLE_REDUNDANT_CLEARING
定义后,删除用于将ThreadX全局C数据结构初始化为零的逻辑。仅当编译器的初始化代码将所有未初始化的C全局数据设置为零时,才应使用此方法。使用此选项可略微减小代码大小并提高初始化期间的性能。默认情况下,未定义此选项。
-
TX_DISABLE_STACK_FILLING
定义时,禁用在创建时将0xEF值放置在每个线程堆栈的每个字节中。默认情况下,未定义此选项。
-
TX_ENABLE_EVENT_TRACE
定义后,ThreadX启用事件收集代码以创建TraceX跟踪缓冲区。
-
TX_ENABLE_STACK_CHECKING
定义后,将启用ThreadX运行时堆栈检查,其中包括分析已使用了多少堆栈以及检查堆栈区域之前和之后的数据模式“围栏”。如果检测到堆栈错误,则会调用已注册的应用程序堆栈错误处理程序。此选项的确会导致开销和代码大小略有增加。查看***tx_thread_stack_error_notify*** API函数以获取更多信息。默认情况下,未定义此选项。
-
TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
定义后,可以收集有关事件标志组的性能信息。默认情况下,未定义此选项。
-
TX_INLINE_THREAD_RESUME_SUSPEND
定义后,ThreadX通过内联代码改进tx_thread_resume和tx_thread_suspend API调用。这增加了代码大小,但增强了这两个API调用的性能。
-
TX_MAX_PRIORITIES
定义ThreadX的优先级。合法值的范围是32到1024(含),并且必须能被32整除。增加的优先级级别数对于每组32个优先级将RAM使用量增加128字节。但是,对性能的影响可忽略不计。默认情况下,此值设置为32个优先级。
-
TX_MINIMUM_STACK
定义最小堆栈大小(以字节为单位)。创建线程时,用于错误检查。默认值是特定于端口的,可以在tx_port.h中找到。
-
TX_MISRA_ENABLE
定义后,ThreadX将使用符合MISRA C的约定。有关详细信息,请参考 ThreadX_MISRA_Compliance.pdf。
-
TX_MUTEX_ENABLE_PERFORMANCE_INFO
定义后,可以收集互斥量上的性能信息。默认情况下,未定义此选项。
-
TX_NO_TIMER
定义后,将完全禁用ThreadX计时器逻辑。在不使用ThreadX计时器功能(线程睡眠,API超时,时间分片和应用程序计时器)的情况下,这很有用。如果TX_NO_TIMER指定,则选项TX_TIMER_PROCESS_IN_ISR也必须定义。
-
TX_NOT_INTERRUPTABLE
定义后,ThreadX不会尝试最小化中断锁定时间。这样可以加快执行速度,但会略微增加中断锁定时间。
-
TX_QUEUE_ENABLE_PE