ThreadX应用笔记:内核初始化和任务调度

做者:zzssdd2html

E-mail:zzssdd2@foxmail.comapi

1、前言

了解ThreadX的初始化流程有助于移植使用,掌握任务的的调度有助于更加驾轻就熟地运用该实时操做系统。数据结构

2、初始化流程

官方手册给出的ThreadX初始化流程以下图所示:多线程

STM32F429 + MDK-ARM-AC6平台举例,初始化流程的前3步在startup_stm32f429xx.s文件中完成 ,该启动文件内容是STM32复位后首先执行的,主要完成如下操做:ide

  • 设置堆栈( __initial_sp、__heap_base、__heap_limit)
  • 设置中断向量表(__Vectors)
  • 设置复位入口程序(Reset_Handler)
  • 连接到C库中的__main,最终进入到main()函数

进入main()函数后开始进行ThreadX的x相关初始化,后面几步更详细的调用流程以下所示:函数


关于STM32移植ThreadX更详细的过程能够参考这篇文章:ThreadX移植——STM32H7+MDK-AC6平台性能

3、线程状态

理解线程的不一样处理状态是理解整个多线程环境的关键因素。在ThreadX中包含5种不一样的线程状态:就绪挂起执行终止完成。下图展现了ThreadX的线程状态转换图:
ui

  • 当线程准备执行时处于就绪状态,就绪线程只有在它是处于就绪线程列表的最高优先级时才会执行。当线程开始执行时其状态由就绪态转为运行态
  • 若是更高优先级的线程准备就绪,则执行线程将恢复到就绪状态。而后执行新准备好的高优先级线程,将其逻辑状态更改成运行态。每次发生线程抢占时,都会发生就绪状态和运行状态之间的转换。
  • 在任何给定的时刻,只有一个线程处于执行状态。这是由于处于执行状态的线程对底层处理器具备控制权。
  • 处于挂起状态的线程不符合执行条件。处于挂起状态的缘由包括时间挂起、队列消息、信号量、互斥、事件标志、内存和基本线程挂起。在清除挂起的缘由后,线程将恢复到就绪状态。
  • 处于完成状态的线程是已完成其任务处理并从其入口函数返回的线程。 入口函数是在线程建立期间指定的。 处于完成状态的线程没法再次执行。
  • 线程处于终止状态是由于另外一个线程或是线程自己调用tx_thread_terminate服务。线程处于终止状态将没法再次执行。
  • 若是须要从新启动已完成或终止的线程,应用程序必须首先删除该线程。而后能够从新建立并从新启动它。

4、配置选项

在使用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_resumetx_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_PERFORMANCE_INFO

    定义后,能够在队列上收集性能信息。默认状况下,未定义此选项。

  • TX_REACTIVATE_INLINE

    定义后,直接内联执行ThreadX计时器,而不使用函数调用。这样能够提升性能,但会稍微增长代码大小。默认状况下,未定义此选项。

  • TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO

    定义后,能够收集有关信号量的性能信息。默认状况下,未定义此选项。

  • TX_THREAD_ENABLE_PERFORMANCE_INFO

    定义后,能够在线程上收集性能信息。默认状况下,未定义此选项。

  • TX_TIMER_ENABLE_PERFORMANCE_INFO

    定义后,可在计时器上收集性能信息。默认状况下,未定义此选项。

  • TX_TIMER_PROCESS_IN_ISR

    定义后,消除ThreadX的内部系统计时器线程。因为再也不须要定时器堆栈和控制块,所以能够提升定时器事件的性能,并减小对RAM的需求。可是,使用此选项会将全部计时器到期处理移至计时器ISR级别。默认状况下,未定义此选项。

    注意:ISR可能不容许计时器容许的服务,所以使用此选项时可能不容许。

  • TX_TIMER_THREAD_PRIORITY

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

  • TX_TIMER_THREAD_STACK_SIZE

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

5、任务相关API

一、建立应用程序线程

  • 描述

    该服务建立一个应用程序线程,该线程在指定的任务输入功能处开始执行。堆栈,优先级,抢占阈值和时间片是输入参数指定的属性。另外,还指定了线程的初始执行状态。

  • 参数

    • thread_ptr指向线程控制块的指针。

    • name_ptr指向线程名称的指针。

    • entry_function指定用于线程执行的初始C函数。当线程今后入口函数返回时,它将处于完成状态并没有限期挂起。

    • entry_input一个32位值,该值在首次执行时传递给线程的入口函数。此输入的使用彻底由应用程序肯定。

    • stack_start堆栈存储区的起始地址。

    • stack_size堆栈存储区中的字节数。线程的堆栈区域必须足够大以处理最坏状况的函数调用嵌套和局部变量使用。

    • priority线程的数字优先级。有效值的范围是0到(TX_MAX_PRIORITES-1),其中0表示最高优先级。

    • preempt_threshold禁用的抢占的最高优先级(0到(TX_MAX_PRIORITIES-1))。只有高于此级别的优先级才能够抢占该线程。该值必须小于或等于指定的优先级。等于线程优先级的值将禁用抢占阈值。

    • time_slice容许在同一优先级的其余就绪线程运行以前,容许该线程运行的计时器计数。请注意,使用抢占阈值将禁用时间片。合法的时间片值范围是1到0xFFFFFFFF(包括0)。值为TX_NO_TIME_SLICE(值为0)禁用此线程的时间切片。

      注意:使用时间分片会致使少许系统开销。因为时间片仅在多个线程共享相同优先级的状况下才有用,所以不该将具备惟一优先级的线程分配时间片。

    • auto_start指定线程是当即启动仍是处于挂起状态。有效选项为TX_AUTO_START(0x01)和TX_DONT_START(0x00)。若是指定了TX_DONT_START,则应用程序之后必须调用tx_thread_resume才能运行线程。

  • 返回值

    • TX_SUCCESS(0x00)成功建立线程。
    • TX_THREAD_ERROR(0x0E)无效的线程控制指针。指针为NULL或线程已建立。
    • TX_PTR_ERROR(0x03)入口点或堆栈区域的无效起始地址无效,一般为NULL。
    • TX_SIZE_ERROR(0x05)堆栈区域的大小无效。线程必须至少具备TX_MINIMUM_STACK字节才能执行。
    • TX_PRIORITY_ERROR(0x0F)无效的线程优先级,该值超出(0到(TX_MAX_PRIORITIES-1))的范围。
    • TX_THRESH_ERROR(0x18)指定了无效的抢占阈值。该值的有效优先级必须小于或等于线程的初始优先级。
    • TX_START_ERROR(0x10)无效的自动启动选择。
    • TX_CALLER_ERROR(0x13)该服务的无效调用者。
UINT tx_thread_create(
    TX_THREAD *thread_ptr,
    CHAR *name_ptr, 
    VOID (*entry_function)(ULONG),
    ULONG entry_input, 
    VOID *stack_start,
    ULONG stack_size, 
    UINT priority,
    UINT preempt_threshold, 
    ULONG time_slice,
    UINT auto_start);

二、删除应用程序线程

  • 描述

    该服务删除指定的应用程序线程。因为指定的线程必须处于终止或完成状态,所以没法从试图删除自身的线程中调用此服务。

    注意:应用程序负责管理与线程的堆栈关联的内存区域,此服务完成后才可用。此外,应用程序必须阻止使用已删除的线程。

  • 参数

    thread_ptr指向先前建立的应用程序线程的指针。

  • 返回值

    • TX_SUCCESS(0x00)成功删除线程。
    • TX_THREAD_ERROR(0x0E)无效的应用程序线程指针。
    • TX_DELETE_ERROR(0x11)指定的线程未处于终止或完成状态。
    • TX_CALLER_ERROR(0x13)该服务的无效调用者。
UINT tx_thread_delete(TX_THREAD *thread_ptr);

三、在线程进入和退出时通知应用程序

  • 描述

    此服务注册一个通知回调函数,该函数将在进入或退出指定线程时调用。通知回调的处理由应用程序定义。

    注意:不容许应用程序的线程进入/退出通知回调调用具备暂停选项的任何ThreadX API。

  • 参数

    • thread_ptr指向先前建立的线程的指针。
    • entry_exit_notify指向应用程序的线程进入/退出通知功能的指针。进入/退出通知功能的第二个参数指定是否存在进入或退出。值TX_THREAD_ENTRY(0x00)表示已进入线程,而值TX_THREAD_EXIT(0x01)表示已退出线程。若是此值为TX_NULL,则禁用通知。
  • 返回值

    • TX_SUCCESS(0x00)成功注册线程进入/退出通知功能。
    • TX_THREAD_ERROR(0x0E)无效的线程指针。
    • TX_FEATURE_NOT_ENABLED(0xFF)系统在禁用通知功能的状况下进行了编译。
UINT tx_thread_entry_exit_notify(
    TX_THREAD *thread_ptr,
    VOID (*entry_exit_notify)(TX_THREAD *, UINT));

四、查询当前正在执行的任务

  • 描述

    该服务返回指向当前正在执行的线程的指针。若是没有线程在执行,则此服务返回空指针。

    注意:若是从ISR调用此服务,则返回值表示在执行中断处理程序以前运行的线程。

  • 参数

  • 返回值

    thread pointer 指向当前正在执行的线程的指针。若是没有线程在执行,则返回值为TX_NULL

TX_THREAD* tx_thread_identify(VOID);

五、查询任务相关信息

  • 描述

    该服务检索有关指定线程的信息。

  • 参数

    • thread_ptr指向线程控制块的指针。

    • name指向目标的指针,该目标指向线程名称。

    • state指向线程当前执行状态的目标的指针。可能的值以下。

      • TX_READY(0x00)
      • TX_COMPLETED(0x01)
      • TX_TERMINATED(0x02)
      • TX_SUSPENDED(0x03)
      • TX_SLEEP(0x04)
      • TX_QUEUE_SUSP(0x05)
      • TX_SEMAPHORE_SUSP(0x06)
      • TX_EVENT_FLAG(0x07)
      • TX_BLOCK_MEMORY(0x08)
      • TX_BYTE_MEMORY(0x09)
      • TX_MUTEX_SUSP(0x0D)
    • run_count指向目标的线程运行计数。

    • **priority **指向目标的线程优先级。

    • preemption_threshold指向线程的抢占阈值的目标的指针。

    • time_slice指向线程时间切片目标的指针。

    • next_thread指向下一个建立的线程指针的目标的指针。

    • suspend_thread指向目标的指针,该指针指向指向暂挂列表中下一个线程的指针。

    注意:为任何参数提供TX_NULL表示该参数不是必需的。

  • 返回值

    • TX_SUCCESS(0x00)成功的线程信息检索。
    • TX_THREAD_ERROR(0x0E)无效的线程控制指针。
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);

六、更改线程的抢占阈值

  • 描述

    此服务更改指定线程的抢占阈值。抢占阈值可防止等于或小于抢占阈值的线程抢占指定线程。

    注意:使用抢占阈值会禁用指定线程的时间片。

  • 参数

    • thread_ptr指向先前建立的应用程序线程的指针。
    • new_threshold新的抢占阈值优先级(0到(TX_MAX_PRIORITIES-1)。
    • old_threshold指向要返回先前抢占阈值的位置的指针。
  • 返回值

    • TX_SUCCESS(0x00)成功的抢占阈值更改。
    • TX_THREAD_ERROR(0x0E)无效的应用程序线程指针。
    • TX_THRESH_ERROR(0x18)指定的新抢占阈值不是有效的线程优先级((从(0到(TX_MAX_PRIORITIES -1)之外的值))或大于当前线程优先级((较低的优先级))。
    • TX_PTR_ERROR(0x03)指向先前抢占阈值存储位置的无效指针。
    • TX_CALLER_ERROR(0x13)该服务的无效调用者。
UINT tx_thread_preemption_change(
    TX_THREAD *thread_ptr,
    UINT new_threshold, 
    UINT *old_threshold);

七、更改线程的优先级

  • 描述

    该服务更改指定线程的优先级。有效优先级的范围是0到(TX_MAX_PRIORITES-1),其中0表示最高优先级。

    注意:指定线程的抢占阈值将自动设置为新优先级。若是须要新的阈值,则必须在此调用以后使用tx_thread_preemption_change*服务

  • 参数

    • thread_ptr指向先前建立的应用程序线程的指针。
    • new_priority新线程优先级(0到(TX_MAX_PRIORITIES-1))。
    • old_priority指向一个位置的指针,以返回线程先前的优先级
  • 返回值

    • TX_SUCCESS(0x00)成功的优先级更改。
    • TX_THREAD_ERROR(0x0E)无效的应用程序线程指针。
    • TX_PRIORITY_ERROR(0x0F)指定的新优先级无效(((0到(TX_MAX_PRIORITIES-1)之外的值))。
    • TX_PTR_ERROR(0x03)指向先前优先级存储位置的无效指针。
    • TX_CALLER_ERROR(0x13)该服务的无效调用者。
UINT tx_thread_priority_change(
    TX_THREAD *thread_ptr,
    UINT new_priority, 
    UINT *old_priority);

八、线程释放控制权

  • 描述

    • 此服务放弃处理器的控制权,转交给其余相同或更高优先级的处于就绪状态的线程

    • 除了将控制权放弃给相同优先级的线程以外,此服务还将控制权放弃给因为当前线程的抢占阈值设置而阻止执行的最高优先级线程。

  • 参数

  • 返回值

VOID tx_thread_relinquish(VOID);

九、重置线程

  • 描述

    此服务将指定的线程重置为在线程建立时定义的入口点执行。线程必须处于TX_COMPLETEDTX_TERMINATED状态才能重置

    注意:必须恢复(resume)该线程以使其再次执行

  • 参数

    • thread_ptr指向先前建立的线程的指针。
  • 返回值

    • TX_SUCCESS(0x00)成功的线程重置。
    • TX_NOT_DONE(0x20)指定的线程不处于TX_COMPLETEDTX_TERMINATED状态。
    • TX_THREAD_ERROR(0x0E)无效的线程指针。
    • TX_CALLER_ERROR(0x13)该服务的无效调用者。
UINT tx_thread_reset(TX_THREAD *thread_ptr);

十、恢复线程

  • 描述

    该服务将恢复或准备执行先前由tx_thread_suspend调用暂停的线程。此外,此服务将恢复在没有自动启动的状况下建立的线程。

  • 参数

    • thread_ptr指向挂起的应用程序线程的指针。
  • 返回值

    • TX_SUCCESS(0x00)成功的线程恢复。
    • TX_SUSPEND_LIFTED(0x19)先前设置的延迟暂停已取消。
    • TX_THREAD_ERROR(0x0E)无效的应用程序线程指针。
    • TX_RESUME_ERROR(0x12)指定的线程没有被挂起,或者以前被tx_thread_suspend之外的服务挂起。
UINT tx_thread_resume(TX_THREAD *thread_ptr);

十一、挂起线程

  • 描述

    此服务挂起指定的应用程序线程。线程能够调用此服务来挂起自身。

    挂起后,必须由tx_thread_resume恢复该线程才能再次执行。

    注意:若是指定的线程因为其余缘由已经挂起,则此挂起操做将在内部保持,直到先前的挂起解除为止。当发生这种状况时,将执行指定线程的无条件挂起。进一步的无条件停止请求无效。

  • 参数

    • thread_ptr指向应用程序线程的指针。
  • 返回值

    • TX_SUCCESS(0x00)成功的线程挂起。
    • TX_THREAD_ERROR(0x0E)无效的应用程序线程指针。
    • TX_SUSPEND_ERROR(0x14)指定的线程处于终止或完成状态。
    • TX_CALLER_ERROR(0x13)该服务的无效调用者。
UINT tx_thread_suspend(TX_THREAD *thread_ptr);

十二、将当前线程挂起指定的时间

  • 描述

    此服务使调用线程在指定的计时器刻度数内挂起。与计时器刻度相关的物理时间量是特定于应用程序的。只能从应用程序线程调用此服务。

  • 参数

    • timer_ticks用于暂停调用应用程序线程的计时器滴答数,范围从0到0xFFFFFFFF。若是指定0,则服务将当即返回。
  • 返回值

    • TX_SUCCESS(0x00)成功的线程睡眠。
    • TX_WAIT_ABORTED(0x1A)暂停被另外一个线程,计时器或ISR停止。
    • TX_CALLER_ERROR(0x13)从非线程调用的服务。
UINT tx_thread_sleep(ULONG timer_ticks);

1三、线程堆栈错误通知回调

  • 描述

    该服务注册了一个通知回调函数来处理线程堆栈错误。当ThreadX在执行过程当中检测到线程堆栈错误时,它将调用此通知函数来处理错误。错误的处理彻底由应用程序定义。从暂停违规线程到重置整个系统,任何事情均可以完成。

    注意:必须定义TX_ENABLE_STACK_CHECKING 配置选项,以便此服务返回性能信息。

  • 参数

    • error_handler指向应用程序的堆栈错误处理功能的指针。若是此值为TX_NULL,则禁用通知。
  • 返回值

    • TX_SUCCESS(0x00)成功的线程重置。
    • TX_FEATURE_NOT_ENABLED(0xFF)系统未在启用性能信息的状况下进行编译。
UINT tx_thread_stack_error_notify(VOID (*error_handler)(TX_THREAD *));

1四、终止线程

  • 描述
    • 该服务终止指定的应用程序线程,而无论该线程是否被挂起。线程能够调用此服务以终止自身。
    • 应用程序有责任确保线程处于适合终止的状态。例如,线程不该在关键应用程序处理期间或在其余中间件组件内部终止,不然可能会使这种处理处于未知状态。**
    • 终止后,必须重置线程以使其再次执行。
  • 参数
    • thread_ptr指向应用程序线程的指针。
  • 返回值
    • TX_SUCCESS(0x00)成功终止线程。
    • TX_THREAD_ERROR(0x0E)无效的应用程序线程指针。
    • TX_CALLER_ERROR(0x13)该服务的无效调用者。
UINT tx_thread_terminate(TX_THREAD *thread_ptr);

1五、更改线程的时间片

  • 描述

    该服务更改指定应用程序线程的时间片。为线程选择时间片可确保在相同或更高优先级的其余线程有机会执行以前,它不会执行超过指定数量的计时器滴答。

    注意:使用抢占阈值会禁用指定线程的时间片。

  • 参数

    • thread_ptr指向应用程序线程的指针。
    • new_time_slice新的时间片值。合法值包括TX_NO_TIME_SLICE和从1到0xFFFFFFFF的数值。
    • old_time_slice指向用于存储指定线程的先前时间片值的位置的指针。
  • 返回值

    • TX_SUCCESS(0x00)成功的时间切片机会。
    • TX_THREAD_ERROR(0x0E)无效的应用程序线程指针。
    • TX_PTR_ERROR(0x03)指向先前时间片存储位置的无效指针。
    • TX_CALLER_ERROR(0x13)该服务的无效调用者。
UINT tx_thread_time_slice_change(
    TX_THREAD *thread_ptr,
    ULONG new_time_slice, 
    ULONG *old_time_slice);

1六、停止指定线程

  • 描述

    此服务停止睡眠或指定线程的任何其余对象挂起。若是等待被停止,则线程正在等待的服务将返回TX_WAIT_ABORTED值。

    注意:该服务不会释放由tx_thread_suspend服务进行的显式挂起。

  • 参数

    • thread_ptr指向先前建立的应用程序线程的指针。
  • 返回值

    • TX_SUCCESS(0x00)成功的线程等待停止。
    • TX_THREAD_ERROR(0x0E)无效的应用程序线程指针。
    • TX_WAIT_ABORT_ERROR(0x1B)指定的线程未处于等待状态。
UINT tx_thread_wait_abort(TX_THREAD *thread_ptr);
相关文章
相关标签/搜索