前言
- 使用过rt-thread的shell 命令交互的方式,觉得比较方便,所以在threadx中也移植个shell的组件。这里使用的是letter-shell
- letter-shell 核心的逻辑在于组件通过链接文件自动初始化或自动添加的两种方式,方便开发
- 源码仓库
实验(核心代码)
shell 线程组件
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-16 shchl first version
*/
#include "includes.h"
#if 1
#include "shell.h"
#include "tx_initialize.h"
#define SHELL_STACK_SIZE 2048
#define SHELL_THREAD_PRIORITY 18
/*
*******************************************************************************************************
* 外部引入变量
*******************************************************************************************************
*/
extern TX_MUTEX console_lock;/*控制台互斥锁变量*/
extern ULONG _tx_thread_system_state; /*tx 系统状态,保证编译器不报错,因为这个是在汇编文件中定义的*/
/*
*******************************************************************************************************
* 变量
*******************************************************************************************************
*/
TX_THREAD shell_thread;
/*
*********************************************************************************************************
* 静态全局变量
*********************************************************************************************************
*/
static Shell g_shell; /*全局shell*/
static char shell_cache_buf[TX_LOG_BUF_SZ];
/*
*********************************************************************************************************
* 函数声明
*********************************************************************************************************
*/
static signed short console_write_handle(char *data, unsigned short len);
static signed short console_read_handle(char *dst, unsigned short read_len);
static int console_lock_handle(struct shell_def *self);
static int console_unlock_handle(struct shell_def *self);
static void shell_thread_entry(ULONG input);
/*
*********************************************************************************************************
* 外部函数
*********************************************************************************************************
*/
/**
* @brief 控制台shell 组件初始化
* @return
*/
int app_shell_console_component_init() {
g_shell.write = console_write_handle;
g_shell.read = console_read_handle;
g_shell.lock = console_lock_handle;
g_shell.unlock = console_unlock_handle;
shellInit(&g_shell, shell_cache_buf, TX_LOG_BUF_SZ);
/*创建shell 线程*/
tx_thread_create(&shell_thread, "shell",
shell_thread_entry, 0,
app_malloc(SHELL_STACK_SIZE), SHELL_STACK_SIZE,
SHELL_THREAD_PRIORITY, SHELL_THREAD_PRIORITY,
TX_NO_TIME_SLICE, TX_AUTO_START
);
return TX_SUCCESS;
}
TX_APP_DEFINE_EXPORT(app_shell_console_component_init); /*shell 控制台组件初始化*/
/*
*********************************************************************************************************
* 内部函数
*********************************************************************************************************
*/
static signed short console_write_handle(char *data, unsigned short len) {
comSendBuf(COM1, (uint8_t *) data, len);
return (signed short) len;
}
static signed short console_read_handle(char *dst, unsigned short read_len) {
signed short readCnt = 0;
while (read_len) {
if (comGetChar(COM1, (uint8_t *) dst) == 1) {
readCnt++;
read_len--;
} else {
break;
}
}
return readCnt;
}
static int console_lock_handle(struct shell_def *self) {
if (TX_THREAD_GET_SYSTEM_STATE() == TX_INITIALIZE_IS_FINISHED) { /*还没初始化*/
/*初始化完成才使用互斥量*/
return tx_mutex_get(&console_lock, TX_WAIT_FOREVER);
}
return TX_SUCCESS;
}
static int console_unlock_handle(struct shell_def *self) {
if (TX_THREAD_GET_SYSTEM_STATE() == TX_INITIALIZE_IS_FINISHED) { /*还没初始化*/
/*初始化完成才使用互斥量*/
return tx_mutex_put(&console_lock);
}
return TX_SUCCESS;
}
static void shell_thread_entry(ULONG input) {
while (1) {
shellTask(&g_shell);
tx_thread_sleep(10);
}
}
#endif
CPU 状态信息(使用shell 交互来打印)
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-4 shchl first version
*/
#include "includes.h"
/*
*******************************************************************************************************
* 任务相关宏定义
*******************************************************************************************************
*/
#define APP_TASK_CPU_STAT_PRIO 30
#define APP_TASK_CPU_STAT_STK_SIZE 1024
/*
*******************************************************************************************************
* 外部引入变量
*******************************************************************************************************
*/
#if defined(TX_EXECUTION_PROFILE_ENABLE)
extern EXECUTION_TIME _tx_execution_idle_time_total;
extern EXECUTION_TIME _tx_execution_thread_time_total;
extern EXECUTION_TIME _tx_execution_isr_time_total;
#endif
/*
*******************************************************************************************************
* 变量
*******************************************************************************************************
*/
__IO double OSCPUUsage; /* CPU百分比 */
/*
*********************************************************************************************************
* 静态全局变量
*********************************************************************************************************
*/
static TX_THREAD cpu_stat_task_thread;
/*
*********************************************************************************************************
* 函数声明
*********************************************************************************************************
*/
static VOID task_cpu_stat_entry(ULONG input);
/*
*********************************************************************************************************
* 外部函数
*********************************************************************************************************
*/
/**
* @brief cpu 状态任务
* @param first_thread 第一个启动的任务线程首地址
*/
int tx_task_cpu_stat_create() {
tx_thread_create(&cpu_stat_task_thread, /* 任务控制块地址 */
"app_cpu_stat", /* 任务名 */
task_cpu_stat_entry, /* 启动任务函数地址 */
0, /* 传递给任务的参数 */
app_malloc(APP_TASK_CPU_STAT_STK_SIZE), /* 堆栈基地址 */
APP_TASK_CPU_STAT_STK_SIZE, /* 堆栈空间大小 */
APP_TASK_CPU_STAT_PRIO, /* 任务优先级*/
APP_TASK_CPU_STAT_PRIO, /* 任务抢占阀值 */
TX_NO_TIME_SLICE, /* 不开启时间片 */
TX_AUTO_START); /* 创建后立即启动 */
return TX_SUCCESS;
}
TX_THREAD_EXPORT(tx_task_cpu_stat_create);
/*
*********************************************************************************************************
* 函 数 名: app_task_info_out
* 功能说明: 将ThreadX任务信息通过串口打印出来
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void app_task_info_out(void) {
TX_THREAD *p_tcb = _tx_thread_identify(); /* 定义一个任务控制块指针,并指向当前线程 */
/* 打印标题 */
// tx_log("调用线程======[%s]\r\n", p_tcb->tx_thread_name);
#if defined(TX_EXECUTION_PROFILE_ENABLE)
tx_log("CPU利用率 = %5.2f%%\r\n", OSCPUUsage);
tx_log("任务执行时间 = %.9fs\r\n", (double) _tx_execution_thread_time_total / SystemCoreClock);
tx_log("空闲执行时间 = %.9fs\r\n", (double) _tx_execution_idle_time_total / SystemCoreClock);
tx_log("中断执行时间 = %.9fs\r\n", (double) _tx_execution_isr_time_total / SystemCoreClock);
tx_log("系统总执行时间 = %.9fs\r\n", (double) (_tx_execution_thread_time_total + \
_tx_execution_idle_time_total + \
_tx_execution_isr_time_total) / SystemCoreClock);
#endif
tx_log("===============================================================\r\n");
// tx_log(" 任务优先级 任务栈大小 当前使用栈 最大栈使用 状态 任务名\r\n");
tx_log(" Prio StackSize CurStack MaxStack State Taskname\r\n");
/* 遍历任务控制列表TCB list),打印所有的任务的优先级和名称 */
while (p_tcb != (TX_THREAD *) 0) {
tx_log(" %2d %5d %5d %5d %5d %s\r\n",
p_tcb->tx_thread_priority,
p_tcb->tx_thread_stack_size,
(int) p_tcb->tx_thread_stack_end - (int) p_tcb->tx_thread_stack_ptr,
(int) p_tcb->tx_thread_stack_end - (int) p_tcb->tx_thread_stack_highest_ptr,
p_tcb->tx_thread_state,
p_tcb->tx_thread_name);
p_tcb = p_tcb->tx_thread_created_next;
if (p_tcb == _tx_thread_identify()) break;
}
}
/*
*********************************************************************************************************
* 内部函数
*********************************************************************************************************
*/
static VOID task_cpu_stat_entry(ULONG input) {
#if defined(TX_EXECUTION_PROFILE_ENABLE)
EXECUTION_TIME TolTime, IdleTime, deltaTolTime, deltaIdleTime;
uint32_t uiCount = 0;
(void) input;
/* 计算CPU利用率 */
IdleTime = _tx_execution_idle_time_total;
TolTime = _tx_execution_thread_time_total + _tx_execution_isr_time_total + _tx_execution_idle_time_total;
while (1) {
/* CPU利用率统计 */
uiCount++;
if (uiCount == 20) {
uiCount = 0;
deltaIdleTime = _tx_execution_idle_time_total - IdleTime;
deltaTolTime =
_tx_execution_thread_time_total + _tx_execution_isr_time_total + _tx_execution_idle_time_total -
TolTime;
OSCPUUsage = (double) deltaIdleTime / deltaTolTime;
OSCPUUsage = 100 - OSCPUUsage * 100;
IdleTime = _tx_execution_idle_time_total;
TolTime = _tx_execution_thread_time_total + _tx_execution_isr_time_total + _tx_execution_idle_time_total;
}
tx_thread_sleep(10);
}
#else
while (1) {
bsp_Idle();
tx_thread_sleep(10);
}
#endif
}
#ifdef SHELL_USING_CMD_EXPORT
/*shell 脚本来管理*/
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_DISABLE_RETURN,
ps, app_task_info_out, "cpu statue info print");
#endif
测试结果
总结
- 在使用shell 和threadx 组合的时候,shell 加锁和解锁时,判断os是否启动,没有启动直接返回即可