第 2 章 - 安装和使用 Azure RTOS ThreadX SMP

本章旨在介绍与安装、设置和使用高性能 Azure RTOS ThreadX SMP 内核相关的各种问题。

主机注意事项

嵌入式软件通常是在 Windows 或 Linux (Unix) 主机计算机上开发的。 在对应用程序进行编译和链接并将其放置在主机上之后,将应用程序下载到目标硬件,以执行它。

通常,从开发工具调试器内完成目标下载。 在下载后,调试器负责提供目标执行控件(“执行”、“暂停”、“断点”等)以及对内存和处理器寄存器的访问。

大多数开发工具调试器通过 JTAG (IEEE 1149.1) 和后台调试模式 (BDM) 等芯片调试 (OCD) 连接与目标硬件进行通信。 调试器还通过线路内仿真 (ICE) 连接与目标硬件进行通信。 OCD 和 ICE 连接提供可靠的解决方案,使对目标常驻软件的入侵最少。

对于主机上使用的资源,ThreadX SMP 的源代码以 ASCII 格式提供,并需要大约 1 MB 的主计算机硬盘空间。

重要

请查看提供的 readme_threadx.txt 文件,了解其他主机系统注意事项和选项。

目标注意事项

ThreadX SMP 要求目标具有 2 KB 和 20 KB 只读内存 (ROM)。 对于 ThreadX SMP 系统堆栈和其他全局数据结构,它还需要 1 到 2KB 的目标的随机访问内存 (RAM)。

对于与计时器相关的函数(如服务调用超时、时间切片和要运行的应用程序计时器),基础目标硬件必须提供定期中断源。 如果处理器具有此功能,则 ThreadX SMP 会使用它。 否则,如果目标处理器无法生成定期中断,则用户的硬件必须提供此功能。 计时器中断的设置和配置通常位于 ThreadX SMP 分发的 tx_initialize_low_level 程序集文件中

重要

即使没有可用的定期计时器中断源,ThreadX SMP 仍可正常运行。 但是,与计时器相关的服务都无法正常运行。 请查看提供的 readme_threadx.txt 文件,了解任何其他主机系统注意事项和/或选项。

产品分发

分发磁盘的确切内容取决于目标处理器、开发工具和购买的 ThreadX SMP 包。 但是,下面列出了大多数产品分发共有的几个重要文件:

ThreadX_Express_Startup.pdf

此 PDF 提供了一个简单的四步过程,能够让 ThreadX SMP 在特定的目标处理器/板和特定的开发工具上运行。

readme_threadx.txt

文本文件,其中包含有关 ThreadX SMP 端口的特定信息(包括有关目标处理器和开发工具的信息)。

工具 说明
tx_api.h C 头文件,包含所有系统等式、数据结构和服务原型。
tx_port.h C 头文件包含所有开发工具及目标特定的数据定义和结构。
demo_threadx.c C 文件包含小型演示应用程序。
tx.a(或 tx.lib) 随标准包一起分发的 ThreadX C 库的二进制版本。

重要

所有文件名均为小写。 通过此命名约定可以更轻松地将命令转换为 Linux (Unix) 开发平台的命令。

ThreadX SMP 安装

ThreadX SMP 的安装非常简单。 有关针对特定环境安装 ThreadX SMP 的特定信息,请参阅 ThreadX_Express_Startup.pdf 文件和 readme_threadx.txt 文件

重要

请确保备份 ThreadX SMP 分发磁盘,并将其存储在安全的位置。

重要

应用程序软件需要访问 ThreadX SMP 库文件(通常为 tx.a 或 tx.lib)和 C 包含文件 tx_api.h 和 tx_port.h 。 为实现此目的,可以设置开发工具的相应路径,或者将这些文件复制到应用程序开发区域。

使用 ThreadX SMP

使用 ThreadX SMP 非常简单。 基本上,应用程序代码必须在编译期间包含 tx_api.h,并与 ThreadX SMP 运行时库 tx.a(或tx.lib)链接

生成 ThreadX SMP 应用程序需要四个步骤:

在所有使用 ThreadX SMP 服务或数据结构的应用程序文件中包含 tx_api.h 文件

创建标准 C main 函数。 此函数必须最终调用 tx_kernel_enter 才能启动 ThreadX SMP。 在输入内核之前,可能会添加不涉及 ThreadX SMP 的应用程序特定的初始化。

重要

ThreadX SMP entry 函数 tx_kernel_enter 不返回。 因此,请确保在其之后不进行任何处理或函数调用。

创建 tx_application_define 函数。 这是创建初始系统资源的位置。 系统资源的示例包括线程、队列、内存池、事件标志组、互斥体和信号灯。

编译应用程序源并与 ThreadX SMP 运行时库 tx.lib 链接。 生成的图像可下载到目标并执行!

小型示例系统

第 28 页图 1 中的小型示例系统显示了优先级为 3 的单个线程的创建。 线程执行,递增计数器,然后休眠一个时钟周期。 此过程会永远继续下去。

#include              "tx_api.h"

unsigned long         my_thread_counter = 0;
TX_THREAD             my_thread;

main( )
{
      /* Enter the ThreadX SMP kernel. */
      tx_kernel_enter( );
}

void tx_application_define(void *first_unused_memory)
{

      /* Create my_thread! */
      tx_thread_create(&my_thread, "My Thread",
          my_thread_entry, 0x1234, first_unused_memory, 1024,
             3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
}

void my_thread_entry(ULONG thread_input)
{
      /* Enter into a forever loop. */
      while(1)
      {

            /* Increment thread counter. */
            my_thread_counter++;

            /* Sleep for 1 tick. */
            tx_thread_sleep(1);
      }
}

图 1. 应用程序开发模板

尽管这是一个简单的示例,但它为真正的应用程序开发提供了一个很好的模板。 同样,有关其他详细信息,请参阅 readme_threadx.txt 文件

故障排除

每个 ThreadX SMP 端口都随演示应用程序一起提供。 首先运行演示系统,无论是在实际的目标硬件上,还是在模拟环境中,这始终是个不错的主意。

重要

有关演示系统的详细信息,请参阅随分发提供的 readme_threadx.txt 文件。

如果演示系统未正确执行,以下是一些故障排除提示:

  • 确定演示的运行量。

  • 增加堆栈大小(这在实际的应用程序代码中比在演示中更为重要)。

  • 重新生成 ThreadX SMP 库,其中定义了 TX_ENABLE_STACK_CHECKING。 这将启用内置的 ThreadX SMP 堆栈检查。

  • 暂时跳过最近所做的任何更改,以查看问题是否消失或发生更改。 此类信息对于支持工程师非常有用。

按照第 12 页的“我们需要你提供的内容”中所述的过程发送在故障排除步骤中收集的信息。

配置选项

使用 ThreadX SMP 生成 ThreadX SMP 库和应用程序时,有几个配置选项。 可以在应用程序源、命令行或 tx_user.h include 文件中定义以下选项

重要

只有当应用程序和 ThreadX SMP 库在构建时定义了 TX_INCLUDE_USER_DEFINE_FILE,才会应用在 tx_user.h 中定义的选项 。

最小配置

对于最小的代码大小,应考虑以下 ThreadX SMP 配置选项(缺少所有其他选项):

  • TX_DISABLE_ERROR_CHECKING
  • TX_DISABLE_PREEMPTION_THRESHOLD
  • TX_DISABLE_NOTIFY_CALLBACKS
  • TX_DISABLE_REDUNDANT_CLEARING
  • TX_DISABLE_STACK_FILLING
  • TX_NOT_INTERRUPTABLE
  • TX_TIMER_PROCESS_IN_ISR

最快配置

为实现最快的执行,在以前的最小配置中使用相同的配置选项,但也将此选项考虑在内:

  • TX_REACTIVATE_INLINE

有关 ThreadX SMP 特定版本的其他选项,请查看 readme_threadx.txt 文件。 第 28 页开头介绍了详细的配置选项。

全局时间源

对于其他 Azure RTOS 产品(FileX、NetX、GUIX、USBX 等),ThreadX SMP 定义表示一秒的 ThreadX SMP 计时器时钟周期数。 其他产品基于此常量派生其时间要求。 默认情况下,该值为 100(假设 10ms 定期中断)。 用户可以通过在 tx_port.h 或在 IDE 或命令行中以所需值定义 TX_TIMER_TICKS_PER_SECOND 来覆盖此值

详细的配置选项

  • TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO:定义后,可以收集块池的性能信息。 默认情况下,未定义此选项。
  • TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO:定义后,可以收集字节池的性能信息。 默认情况下,未定义此选项。
  • TX_DISABLE_ERROR_CHECKING:跳过基本服务调用错误检查。 在应用程序源中定义后,将禁用所有基本参数错误检查。 这可能会将性能提高多达 30%,还可能会减小图像大小。

注意

仅当应用程序可以绝对保证所有输入参数(包括从外部输入派生的输入参数)在所有情况下都始终有效时,才可以安全地禁用错误检查。 如果在禁用错误检查的情况下向 API 提供无效输入,则因此而发生的行为是未定义的,并且可能会导致内存损坏或系统崩溃。

注意

不受禁用错误检查影响的 ThreadX SMP API 返回值在第 4 章的每个 API 说明的“返回值”部分中以粗体列出。 如果通过使用 TX_DISABLE_ERROR_CHECKING 选项禁用了错误检查,则非加粗返回值失效。

  • TX_DISABLE_NOTIFY_CALLBACKS:定义后,将对各种 ThreadX SMP 对象禁用通知回调。 使用此选项可以略微减小代码大小并提高性能。 默认情况下,未定义此选项。

  • TX_DISABLE_PREEMPTION_THRESHOLD:定义后,将禁用抢占阈值功能,略微减小代码大小并提高性能。 当然,抢占阈值功能不再可用。 默认情况下,未定义此选项。

  • TX_DISABLE_REDUNDANT_CLEARING:定义后,将删除使 ThreadX SMP 全局 C 数据结构初始化为零的逻辑。 仅当编译器的初始化代码将所有未初始化的 C 全局数据设置为零时,才应使用此选项。 在初始化期间,使用此选项可以略微减小代码大小并提高性能。 默认情况下,未定义此选项。

  • TX_DISABLE_STACK_FILLING:定义后,将禁止在创建时将 0xEF 值置于每个线程的堆栈的每个字节中。 默认情况下,未定义此选项。

  • TX_ENABLE_EVENT_TRACE:定义后,ThreadX SMP 启用事件收集代码,用于创建 TraceX 跟踪缓冲区。 有关更多详细信息,请参阅 TraceX 用户指南。

  • TX_ENABLE_STACK_CHECKING:定义后,将启用 ThreadX SMP 运行时堆栈检查,其中包括分析已使用的堆栈量,以及堆栈区域前后的数据模式“防护”检查。 如果检测到堆栈错误,则会调用已注册应用程序堆栈错误处理程序。 此选项会导致系统开销和代码大小略有增加。 有关详细信息,请查看 tx_thread_stack_error_notify API。 默认情况下,未定义此选项。

  • TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO:定义后,可以收集事件标志组的性能信息。 默认情况下,未定义此选项。

  • TX_INLINE_THREAD_RESUME_SUSPEND:定义后,ThreadX SMP 通过行内代码改进 tx_thread_resume 和 tx_thread_suspend API 调用。 这会增加代码大小,但会增强这两个 API 调用的性能。

  • TX_MAX_PRIORITIES:定义 ThreadX SMP 的优先级别。 合法值的范围为 32 到 1024(含),且必须能被 32 整除。 增加支持的优先级别数量会使每组 32 个优先级别的 RAM 用量增加 128 字节。 但是,对性能的影响可忽略不计。 默认情况下,此值设置为 32 个优先级别。

  • TX_MINIMUM_STACK:定义最小堆栈大小(以字节为单位)。 它用于在创建线程时进行错误检查。 默认值是端口特定的,位于 tx_port.h 中。

  • TX_MISRA_ENABLE:定义后,ThreadX SMP 使用 MISRA C 兼容约定。 有关详细信息,请参阅 ThreadX_MISRA_Compliance

  • TX_MUTEX_ENABLE_PERFORMANCE_INFO:定义后,可以收集互斥体的性能信息。 默认情况下,未定义此选项。

  • TX_NO_TIMER:定义后,将完全禁用 ThreadX SMP 计时器逻辑。 这在无法使用 ThreadX SMP 计时器功能(线程睡眠、API 超时、时间切片和应用程序计时器)的情况下十分有用。

  • TX_NOT_INTERRUPTABLE:定义后,ThreadX SMP 不会尝试最大程度地缩短中断锁定时间。 这会提升执行速度,但会略微增加中断锁定时间。

  • TX_QUEUE_ENABLE_PERFORMANCE_INFO:定义后,可以收集队列的性能信息。 默认情况下,未定义此选项。

  • TX_REACTIVATE_INLINE:定义后,执行 ThreadX SMP 计时器内联的激活,而不是使用函数调用。 这可以提升性能,但会略微增加代码大小。 默认情况下,未定义此选项。

  • TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO:定义后,可以收集信号灯的性能信息。 默认情况下,未定义此选项。

  • TX_THREAD_ENABLE_PERFORMANCE_INFO:定义后,可以收集线程的性能信息。 默认情况下,未定义此选项。

  • TX_THREAD_SMP_CORE_MASK:定义核心排除的位映射掩码。 例如,根据此定义,四核环境的值为 0xF。

  • TX_THREAD_SMP_DEBUG_ENABLE:定义后,ThreadX SMP 调试信息保存在循环缓冲区中。

  • TX_THREAD_SMP_DYNAMIC_CORE_MAX:定义后,实现可在运行时进行调整的动态最大核心数。

  • TX_THREAD_SMP_EQUAL_PRIORITY:定义后,ThreadX SMP 仅计划并行的相同优先级线程。 应在生成 ThreadX SMP 库之前定义。

  • TX_THREAD_SMP_INTER_CORE_INTERRUPT:定义后,ThreadX SMP 将生成核心间中断。

  • TX_THREAD_SMP_MAX_CORES:定义最大核心数。

  • TX_THREAD_SMP_ONLY_CORE_0_DEFAULT:定义后,ThreadX SMP 默认所有线程和计时器都只在核心 0 上执行。 应用程序可以调用核心排除 API 来替代这一点。 应在生成 ThreadX SMP 库之前定义。

  • TX_THREAD_SMP_WAKEUP_LOGIC:定义后,将调用唤醒核心“i”的应用程序宏。 应在包含 tx_port.h 之前定义。

  • TX_THREAD_SMP_WAKEUP(i):将应用程序宏定义为唤醒核心“i”。 应在包含 tx_port.h 之前定义。

  • TX_TIMER_ENABLE_PERFORMANCE_INFO:定义后,可以收集计时器的性能信息。 默认情况下,未定义此选项。

  • TX_TIMER_PROCESS_IN_ISR:定义后,将消除 ThreadX SMP 的内部系统计时器线程。 这会提升计时器事件和更小 RAM 要求的性能,因为不再需要计时器堆栈和控制块。 但是,使用此选项会将所有计时器过期处理移动到计时器 ISR 级别。 默认情况下,未定义此选项。

    注意

    计时器允许的该服务可能得不到 ISR 的允许,因此,在使用此选项时可能不允许这样做。

  • TX_TIMER_THREAD_PRIORITY:定义内部 ThreadX SMP 系统计时器线程的优先级。 默认值为优先级 0,即 ThreadX SMP 中的最高优先级。 默认值定义在 tx_port.h 中。

  • TX_TIMER_THREAD_STACK_SIZE:定义内部 ThreadX SMP 系统计时器线程的堆栈大小(以字节为单位)。 此线程处理所有线程睡眠请求以及所有服务调用超时。 此外,从该上下文调用所有应用程序计时器回调例程。 默认值是端口特定的,位于 tx_port.h 中。

ThreadX SMP 版本 ID

可在 readme_threadx.txt 文件中找到 ThreadX SMP 版本 ID。 该文件还包含相应端口的版本历史记录。 应用程序软件可以通过检查全局字符串 tx_version_id 来获取 ThreadX SMP 版本