17-FreeRTOS任务应用函数(3)

1-xTaskGetHandle

task.h
TaskHandle_t xTaskGetHandle( const char *pcNameToQuery );

从任务的名称中查找任务的句柄。
注意: 此函数需要较长的时间才能完成,并且只能 为每个任务调用一次。 一旦获得了一个任务的句柄, 它就可以被储存在本地以便重新使用。
必须在 FreeRTOSConfig.h 中将 INCLUDE_xTaskGetHandle 设置为 1,xTaskGetHandle() 才可用。

1.1 参数:

pCNAMEToQuery: 将返回句柄的任务的文本名称 (作为标准的以 NULL 结尾的 C 字符串)。

1.2 Returns:

如果可以找到在 pcNameToQuery 中传递名称的任务,则 将返回任务句柄,否则返回 NULL。

2-xTaskGetTickCount

获取系统时间计数器值

task.h
volatile TickType_t xTaskGetTickCount( void );

无法从 ISR 调用此函数。 使用 xTaskGetTickCountFromISR() 代替。

2.1 Returns:

自 vTaskStartScheduler 被调用起的 tick 数。

3-xTaskGetTickCountFromISR

在中断服务函数中获取时间计数器值

task.h
volatile TickType_t xTaskGetTickCountFromISR( void );

xTaskGetTickCount() 的一个版本,可以从 ISR 中调用。

3.1 Returns:

自 vTaskStartScheduler 被调用起的 tick 数。

4-xTaskGetSchedulerState

获取任务调度器的壮态,开启或未开启

task.h
BaseType_t xTaskGetSchedulerState( void );

4.1 Returns:

以下常量之一(在 task.h 中定义):taskSCHEDULER_NOT_STARTED、taskSCHEDULER_RUNNING、taskSCHEDULER_SUSPENDED。
必须在 FreeRTOSConfig.h 中将 INCLUDE_xTaskGetSchedulerState 或 configUSE_TIMERS 设置为 1 才能使用此函数。

5- uxTaskGetNumberOfTasks

获取当前系统中存在的任务数量

task.h
UBaseType_t uxTaskGetNumberOfTasks( void );

5.1 Returns:

RTOS 内核当前正在管理的任务数。这包括所有准备就绪、阻塞和挂起的任务。已删除但尚未被闲置任务释放的任务也将包含在计数中。

6- vTaskList

以一种表格的形式输出当前系统中所有任务的详细信息

task.h
void vTaskList( char *pcWriteBuffer );
	

configUSE_TRACE_FACILITY 和 configUSE_STATS_FORMATTING_FUNCTIONS 必须 在 FreeRTOSConfig.h 中定位为 1 ,才可使用此函数。

注意:此函数将在其持续时间内禁用中断。它不是作为 一种正常的应用程序运行时的工具,而是作为调试辅助工具。

vTaskList() 调用 uxTaskGetSystemState(), 然后 将 uxTaskGetSystemState() 生成的原始数据格式化为人类可读的 (ASCII) 表格, 显示每个任务的状态,包括任务的堆栈高水位线(高水位线数字越小, 任务越接近于溢出其堆栈)。
在 ASCII 表中,以下字母用于表示任务的状态:
‘B’ - 已阻塞
‘R’ - 准备就绪
‘D’ - 已删除(等待清理)
‘S’ - 已挂起或已阻塞,没有超时
vTaskList() 是一个仅为方便起见而提供的实用程序函数。 它不是 不是内核的一部分。

6.1 参数:

pcWriteBuffer 一个缓冲区, 上面提到的细节将以 ASCII 形式写入其中。假设此缓冲区 的大小足以容纳产生的报告。 大约为每个任务分配 40 字节的缓冲区就足够了。

7-vTaskStartTrace

task.h
void vTaskStartTrace( char * pcBuffer, unsigned long ulBufferSize );

[该函数与旧版跟踪工具有关-在 FreeRTOSV7.1.0 中被删除-用户可能会发现较新的 Trace Hook 宏更容易使用,功能也更强大。]
启动 RTOS 内核活动跟踪。跟踪记录何时运行任务的标识。
跟踪文件以二进制格式存储。使用名为 convtrce.exe 的单独 DOS 实用程序将其转换为一个带制表符的文本文件-可以在电子表格中查看和绘制。

7.1 参数:

pcBuffer 跟踪将写入的缓冲区。
ulBufferSize pcBuffer 的大小(以字节为单位)。跟踪将持续到缓冲区已满或 ulTaskEndTrace () 被调用。

8-ulTaskEndTrace

task.h
unsigned long ulTaskEndTrace( void );

[该函数与旧版跟踪工具有关-在 FreeRTOSV7.1.0 中被删除-用户可能会发现较新的 Trace Hook 宏更容易使用,功能也更强大。]
停止 RTOS 内核活动跟踪。

8.1 Returns:

已写入跟踪缓冲区的字节数。

9- vTaskGetRunTimeStats

获取每个任务的运行时间

task.h
void vTaskGetRunTimeStats( char *pcWriteBuffer );

configGENERATE_RUN_TIME_STATS、configUSE_STATS_FORMATTING_FUNCTIONS 和 configSUPPORT_DYNAMIC_ALLOCATION 必须被 定义为 1,才可使用此函数。 然后, 应用程序还必须提供 portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() 和 portGET_RUN_TIME_COUNTER_VALUE 的定义, 以分别配置外设的定时器/计数器和返回定时器的当前计数值。 计数器 的频率应该至少是 tick 计数的 10 倍。
注意:此函数将在其持续时间内禁用中断。 它 不是作为正常的应用程序运行时的工具,而是作为调试辅助工具。

vTaskGetRunTimeStats() 调用 uxTaskGetSystemState(), 然后将 uxTaskGetSystemState() 生成的原始数据格式化为 人类可读的 (ASCII) 表格, 显示每个任务在运行状态下花费的时间(每个任务消耗了多少 CPU 时间)。 数据以 绝对值和百分比值的形式提供。 绝对值的分辨率 取决于应用程序提供的运行时间统计时钟的频率。
vTaskGetRunTimeStats() 是一个仅为方便起见而提供的实用程序函数。 它 不是内核的一部分。

9.1 参数:

pcWriteBuffer: 一个缓冲区, 执行时间将以 ASCII 形式写入其中。 假设此缓冲区足够大, 足以容纳生成的报告。 大约为每个任务分配 40 字节的缓冲区 就足够了。

10-vTaskGetIdleRunTimeCounter

task.h
TickType_t xTaskGetIdleRunTimeCounter( void );

返回空闲任务的运行时间计数器。 此函数可用于 确定空闲任务获得了多少 CPU 时间。 请参阅 运行时间统计页面 了解运行时间统计功能的完整描述。
configGENERATE_RUN_TIME_STATS 和 INCLUDE_xTaskGetIdleTaskHandle 必须 定义为 1,才可使用此函数。 然后, 应用程序还必须提供 portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() 和 portGET_RUN_TIME_COUNTER_VALUE 的定义, 以分别配置外设的定时器/计数器和返回定时器的当前计数值。 建议 确保定时器的频率至少是 tick 计数的 10 倍。

11-vTaskSetApplicationTaskTag

task. h

void vTaskSetApplicationTaskTag(
                        TaskHandle_t xTask,
                        TaskHookFunction_t pxTagValue );

configUSE_APPLICATION_TASK_TAG 必须定义为 1,此函数才可用。

可为每个任务分配“标签”值。 此值仅供应用程序使用,RTOS 内核本身无法使用此值。 RTOS 跟踪宏文档页面提供了一个很好的示例,说明了应用程序如何 使用此功能。

11.1 参数:

xTask 正在向其分配标签值的任务的句柄。 将 xTask 作为 NULL 传递会导致将标签分配给调用任务。
pxTagValue 正在分配给任务标签的值。 该值为 TaskHookFunction_t 类型,可将函数指针赋值为标签,尽管实际上可以分配任何值。

11.2 示例用法:

/* 在这个例子中,一个整数被设置为任务标签值。*/
void vATask( void *pvParameters )
{
  /* 把标签1分配给自身 */
  vTaskSetApplicationTaskTag( NULL, ( void * ) 1 );

  for( ;; )
  {
    /* 任务代码存放处*/
  }
}
/***********************************************/

/* 在这个例子中,一个回调函数被分配为任务标记。

首先定义回调函数——它的类型必须是TaskHookFunction_t */
static BaseType_t prvExampleTaskHook( void * pvParameter )
{
  /* 执行一些操作-这可以是记录一个值,

更新任务状态、输出值等。*/

  return 0;
}

/*现在定义将prvExampleTaskHook设置为其钩子/标记值的任务。
方法上所描述的,这实际上是注册任务回调
xTaskCallApplicationTaskHook()文档页。
 */
void vAnotherTask( void *pvParameters )
{
  /* 注册回调函数 */
  vTaskSetApplicationTaskTag( NULL, prvExampleTaskHook );

  for( ;; )
  {
    /* 其余的任务代码放在这里。*/
  }
}

/* A作为钩子(回调)的一个示例,我们可以让RTOS内核调用在重新调度期间被切换的每个任务的钩子函数。 */
#define traceTASK_SWITCHED_OUT() xTaskCallApplicationTaskHook( pxCurrentTCB,
                                    0 )

13- xTaskCallApplicationTaskHook

task. h

BaseType_t xTaskCallApplicationTaskHook(
                                   TaskHandle_t xTask,
                                   void *pvParameter );

configUSE_APPLICATION_TASK_TAG 必须定义为 1,此函数才可用。

可以为每个任务分配“标签”值。 通常,此值仅供应用程序使用,并且 RTOS 内核无法访问它。 但是,可以 使用标签为任务分配钩子(或回调)函数——通过调用 xTaskCallApplicationTaskHook() 执行该钩子函数。 每个任务都可以定义 自己的回调,或者干脆不定义回调。
尽管可以使用第一个函数参数来调用任何任务的钩子函数, 但任务钩子函数最常见的用途是与跟踪钩子宏一起使用,
任务钩子函数必须具有 TaskHookFunction_t 类型,即接受一个 void * 参数,并返回一个 BaseType_t 类型的值。 void * 参数可用于 将任何信息传递到钩子函数中。

13.1 参数:

xTask 其钩子函数被调用的任务的句柄。 传递 NULL 作为 xTask 将调用与当前执行的任务相关的钩子函数。
pvParameter 要传递给钩子函数的值。 这可以是指向一个结构体的指针,也可以是一个数值。

13.2 用法示例:

/* In this example a callback function is being assigned as the task tag.
First define the callback function - this must have type TaskHookFunction_t
as per this example. */
static BaseType_t prvExampleTaskHook( void * pvParameter )
{
   /* Perform some action - this could be anything from logging a value,
   updating the task state, outputting a value, etc. */

   return 0;
}

/* Now define the task that sets prvExampleTaskHook as its hook/tag value.
This is in fact registering the task callback, as described on the
xTaskCallApplicationTaskHook() documentation page. */
void vAnotherTask( void *pvParameters )
{
   /* Register our callback function. */
   vTaskSetApplicationTaskTag( NULL, prvExampleTaskHook );

   for( ;; )
   {
      /* Rest of task code goes here. */
   }
}

/* As an example use of the hook (callback) we can get the RTOS kernel to
call the hook function of each task that is being switched out during a
reschedule. */
#define traceTASK_SWITCHED_OUT() xTaskCallApplicationTaskHook( pxCurrentTCB, 0 )

14- vTaskSetThreadLocalStoragePointer

设置线程本地存储指针

task. h
void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, 
                                        BaseType_t xIndex, 
                                        void *pvValue )

在任务的 线程本地存储数组中设置值。
此功能仅适用于高级用户。

14.1参数:

xTaskToSet 正在写入线程本地数据的任务 的句柄。 使用 NULL 作为参数值, 使用 NULL 作为参数值自行读取其线程本地数据。
xIndex 正在写入数据的 线程本地存储数组中的索引。
可用数组索引的数量 由 configNUM_THREAD_LOCAL_STORAGE_POINTERS 编译时 配置常量 FreeRTOSConfig.h。
pvValue 要写入 xIndex 参数 指定的索引的值。

15- pvTaskGetThreadLocalStoragePointer

获取线程本地存储指针

task. h
void *pvTaskGetThreadLocalStoragePointer(
                                 TaskHandle_t xTaskToQuery,
                                 BaseType_t xIndex );

从任务的线程本地存储数组中获取值。

此功能仅适用于高级用户。

15.1 参数:

xTaskToQuery 从其中读取线程本地数据的任务句柄。任务可以使用NULL作为参数值来读取自己的线程本地数据。
xIndex 读取数据的线程本地存储数组的索引。
可用数组索引的数量由FreeRTOSConfig.h中的confignum_thread_local_storage_pointer编译时配置常量设置。

15.2 返回值:

存储在xTaskToQuery任务的线程本地存储数组的索引位置xIndex中的值。

16- vTaskSetTimeOutState()

task.h
void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut );

此功能仅适用于高级用户。

任务可以进入阻止状态以等待事件。 通常情况下,任务 不会无限期地在阻止状态下等待,而是会指定一个超时时间段 。 如果在任务等待的事件发生之前,超时期限已到, 任务将从阻止状态中删除。

如果任务在等待事件发生的过程中多次进入和退出阻塞状态, 对于事件发生,那么每次任务进入阻止状态时使用的超时时间 必须调整,才能确保花费在 阻止状态的所有时间不会超过最初指定的时时间。 xTaskCheckForTimeOut () 执行调整,同时考虑到 诸如滴答数溢出等情况,这种情况会形成容易出错的手动 手动调整容易出错。

vTaskSetTimeOutState() 可与 xTaskCheckForTimeOut() 一起使用。 可调用 vTaskSetTimeOutState() 设置初始条件,然后调用 xTaskCheckForTimeOut() 检查超时情况。如果没有超时, 则调整剩余的阻塞时间。

16.1 参数:

pxTimeOut 指向结构体的指针,该结构体将被初始化以保存 确定是否发生超时所需的信息。

17-xTaskCheckForTimeOut()

task.h
BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
                                 TickType_t * const pxTicksToWait );

此功能仅适用于高级用户。

任务可以进入阻止状态以等待事件。 通常情况下,任务 不会无限期地在阻止状态下等待,而是会指定一个超时时间段 。 如果在任务等待的事件发生之前,超时期限已到, 任务将从阻止状态中删除。

如果任务在等待事件发生的过程中多次进入和退出阻塞状态, 对于事件发生,那么每次任务进入阻止状态时使用的超时时间 必须调整,才能确保花费在 阻止状态的所有时间不会超过最初指定的时时间。 xTaskCheckForTimeOut () 执行调整,同时考虑到 诸如滴答数溢出等情况,这种情况会形成容易出错的手动 调整。

xTaskCheckForTimeOut () 与 vTaskSetTimeOutState () 一起使用。 调用 vTaskSetTimeOutState () 以设置初始条件,然后 可以调用 xTaskCheckForTimeOut () 检查超时条件,并且 如果没有发生超时,则调整所述剩余块时间。

17.1 参数:

pxTimeOut 指向一个结构的指针(该结构保存必要的信息) 以确定是否已发生超时。 使用 vTaskSetTimeOutState () 将 pxTimeOut 初始化。
pxTicksToWait 来传递调整的块时间,即计入阻止状态已花费的时间后 仍然剩余的时间 。

17.2 Returns:

如果返回 pdTRUE ,则没有块时间剩余,并且发生超时。
如果返回 pdFALSE ,则保留一些块时间,因此未发生超时。

17.3 用法示例:

/* 驱动库函数用于从Rx缓冲区接收uxWantedBytes由UART中断填充。如果Rx缓冲区中没有足够的字节

然后任务进入阻塞状态,直到通知它有更多数据被放入缓冲区。如果仍然没有足够的数据,那么任务

重新进入Blocked状态,使用xTaskCheckForTimeOut()重新计算阻塞时间,以确保在阻塞状态下花费的总时间

不超过MAX_TIME_TO_WAIT。这一直持续到缓冲区包含at为止最少uxWantedBytes字节,或者在Blocked状态下花费的总时间

到达MAX_TIME_TO_WAIT—此时任务读取多少字节可用的最大uxWantedBytes
 */
size_t xUART_Receive( uint8_t *pucBuffer, size_t uxWantedBytes )
{
size_t uxReceived = 0;
TickType_t xTicksToWait = MAX_TIME_TO_WAIT;
TimeOut_t xTimeOut;

   /*初始化xTimeOut。这记录了输入这个函数的时间。*/
   vTaskSetTimeOutState( &xTimeOut );

   /* 循环,直到缓冲区包含所需的字节数,或者发生超时。*/
   while( UART_bytes_in_rx_buffer( pxUARTInstance ) < uxWantedBytes )
   {
      /* 缓冲区没有包含足够的数据,所以这个任务将进入阻塞状态。调整xTicksToWait以考虑到目前为止在这个函数中花费在Blocked状态的任何时间,以确保花费在Blocked状态的总时间不超过MAX_TIME_TO_WAIT。 */
      if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) != pdFALSE )
      {
         /* 在所需字节数可用之前超时,退出循环。*/
         break;
      }

      /* 等待xTicksToWait滴答声的最大值,以通知接收中断已将更多数据放入缓冲区。 */
      ulTaskNotifyTake( pdTRUE, xTicksToWait );
   }

   /* 尝试将uxWantedBytes从接收缓冲区读入pucBuffer。返回读取的实际字节数(可能小于uxWantedBytes)。 */
   uxReceived = UART_read_from_receive_buffer( pxUARTInstance,
                                               pucBuffer,
                                               uxWantedBytes );

   return uxReceived;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Modbus是一种常用的串行通信协议,其主从架构适用于工控领域。STM32是一系列微控制器芯片,其中包含了强大的处理器和周边设备,适用于工业控制、通信等应用。HAL是STM32提供的硬件抽象层,可以简化STM32芯片的驱动和编程过程。FreeRTOS是一个流行的实时操作系统,可以帮助开发者进行多线程编程、任务调度等操作。 在使用Modbus通信协议的过程中,通常使用STM32芯片作为主机或从机,通过HAL驱动与外设进行通信。通过FreeRTOS实现多任务调度,可以使得主从设备之间的通信更加稳定可靠。具体实现过程中,开发者需要熟悉Modbus协议的通信机制和STM32芯片的相关知识,同时掌握HAL驱动和FreeRTOS操作系统的编程方法。相应的,也可以选择其他适用于工控领域的通信协议和芯片平台进行开发。 ### 回答2: Modbus是一种通信协议,它被广泛应用于工业自动化领域。Modbus协议采用主从结构,主设备控制整个通信过程,从设备接收主设备发送的指令并返回相应的数据。STM32是一系列单片机产品,Hal是针对STM32开发的一套低层驱动库,FreeRTOS是一种流行的实时操作系统。 在使用STM32单片机实现Modbus主从通信时,可以使用Hal库提供的相关函数来对串口进行初始化和设置,同时可以使用FreeRTOS来实现多任务并行运行。对于Modbus协议的实现,可以利用从设备的地址进行区分,主设备通过读写寄存器的方式与从设备进行通信,而从设备则需要根据读写寄存器的指令进行相应的数据处理和返回。 总之,通过使用STM32、Hal库和FreeRTOS可以方便地实现Modbus主从通信,提高工业自动化控制系统的效率和稳定性。 ### 回答3: Modbus,又称为Modicon通信协议,是一种基于串行传输的通信协议。Modbus协议中定义了Master-Slave模式的通信方式,其中Master可以向Slave发送读/写命令,Slave可以回复数据给Master。STM32是一种32位的嵌入式微控制器,可以通过外围设备如串口等实现Modbus的通信。HAL则是ST公司提供的硬件抽象层,可以简化开发者对系统引脚和外设的访问。FreeRTOS则是一种开源的实时操作系统,可以帮助开发者实现多任务系统。 因此,modbus-master-slave-stm32-hal-freertos指的是使用STM32芯片作为Modbus通信的主体,使用HAL层引脚和外设抽象库简化访问,使用FreeRTOS实现基于多任务的系统设计,实现Modbus通信的Master-Slave模式。这种模式可以用于控制系统的监控和控制,能够实现高效、准确、可靠的数据交换,广泛应用于自动控制、仪器仪表、工业自动化等领域。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南山府嵌入式

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值