在ThreadX中官方提供了execution_profile工具,这个工具能够统计ThreadX在线程、中断、空闲时的时间。通过这些时间,我们可以推算出CPU的利用率。
移植说明
这个工具位于utility\execution_profile_kit
文件夹下,使用时将这个文件夹下的源文件添加进工程,C/C++的包含路径也添加这个文件夹。使用这个工具需要实现TX_EXECUTION_TIME_SOURCE
和TX_EXECUTION_MAX_TIME_SOURCE
两个宏定义,分别为该工具使用的时钟源和这个时钟源的最大值,在ARM中我们可以使用DWT(Data Watchpoint and Trace)中的DWT_CYCCNT(一个32位计数器,时钟源为内核时钟)作为该工具的时钟源。需要注意,这个外设仅在ARM Cortex-M3/M4/M7/M33等中提供,M0是不支持的。
使能DWT
在ThreadX给出的tx_initialize_low_level.S
文件中已经帮我们初始化好了,无需我们再手动启用。
@
@ /* Enable the cycle count register. */
@
LDR r0, =0xE0001000 @ Build address of DWT register
LDR r1, [r0] @ Pickup the current value
ORR r1, r1, #1 @ Set the CYCCNTENA bit
STR r1, [r0] @ Enable the cycle count register
宏定义TX_EXECUTION_TIME_SOURCE
和TX_EXECUTION_MAX_TIME_SOURCE
若使用ARM,ThreadX已经帮我们定义好了TX_EXECUTION_TIME_SOURCE
和TX_EXECUTION_MAX_TIME_SOURCE
,无需额外操作。其中0xE0001004
就是DWT_CYCCNT的地址。
/* Example for Cortex-M targets: */
#ifndef TX_EXECUTION_TIME_SOURCE
#define TX_EXECUTION_TIME_SOURCE (EXECUTION_TIME_SOURCE_TYPE) *((volatile ULONG *) 0xE0001004)
#endif
#ifndef TX_EXECUTION_MAX_TIME_SOURCE
#define TX_EXECUTION_MAX_TIME_SOURCE 0xFFFFFFFF
#endif
使能execution_profile工具
在tx_user.h
中添加宏定义TX_EXECUTION_PROFILE_ENABLE
以使能execution_profile工具,并在tx_user.h
中添加宏定义TX_CORTEX_M_EPK
以指定使用的是ARM Cortex-M内核。最后还需要在ASM宏定义中添加TX_ENABLE_EXECUTION_CHANGE_NOTIFY
,这是为了使能tx_initialize_low_level.S
调用_tx_execution_isr_enter
等函数。
计算CPU利用率的例子
使用线程调用下面这个函数则每一秒都会刷新CPU利用率。
double CPU_usage = 0.0;
void thread_execution_profile_entry(ULONG thread_input)
{
EXECUTION_TIME thread_total_time;
EXECUTION_TIME isr_time;
EXECUTION_TIME idle_time;
while (true)
{
_tx_execution_thread_total_time_get(&thread_total_time);
_tx_execution_isr_time_get(&isr_time);
_tx_execution_idle_time_get(&idle_time);
_tx_execution_thread_total_time_reset();
_tx_execution_isr_time_reset();
_tx_execution_idle_time_reset();
CPU_usage = (double)(thread_total_time + isr_time)
/ (double)(thread_total_time + isr_time + idle_time);
tx_thread_sleep(1000U);
}
}