STM32+FreeRtos 移植letter-shell工具_freedompoi的博客-程序员秘密_shell_export_cmd

技术标签: stm32  STM32  arm  单片机  

前言

        Rt-thread系统有非常好用的FinSH调试工具,考虑在FreeRtos也移植一款类似的嵌入式Shell工具,经过资料查找,开源的letter-shell库满足此需求,搞起。

1、平台

       开发环境:vscode+STM32CubeMX+MDKV5

        芯片:STM32F429

        操作系统:FreeRTOS

        STM32库:HAL

2、串口初始化

通过STM32CubeMX软件直接生成,配置参数如下:

  huart7.Instance = UART7;
  huart7.Init.BaudRate = 9600;
  huart7.Init.WordLength = UART_WORDLENGTH_8B;
  huart7.Init.StopBits = UART_STOPBITS_1;
  huart7.Init.Parity = UART_PARITY_NONE;
  huart7.Init.Mode = UART_MODE_TX_RX;
  huart7.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart7.Init.OverSampling = UART_OVERSAMPLING_16;

3、源码移植

源码下载:

letter-shell: letter shell一个嵌入式小型shell,特别适用于单片机系统。https://gitee.com/zhang-ge/letter-shell.git解压得到下列文件

文件移植

 把文件添加如MDK工程里面

 参照作者的移植步骤,我们重点修改shell_port.c文件:

  • 定义shell对象
Shell shell;
  • 定义shell读,写函数
/**
 * @brief 用户shell写
 * 
 * @param data 数据
 * @param len 数据长度
 * 
 * @return short 实际写入的数据长度
 */
short userShellWrite(char *data, unsigned short len)
{
    HAL_UART_Transmit(&huart7, (uint8_t *)data, len, 0x1FF);
    return len;
}


/**
 * @brief 用户shell读
 * 
 * @param data 数据
 * @param len 数据长度
 * 
 * @return short 实际读取到
 */
short userShellRead(char *data, unsigned short len)
{
    if(HAL_UART_Receive(&huart7, (uint8_t *)data, len, 0xFFFF) != HAL_OK)
    {
        return 0;
    }
    else
    {
        return 1;
    }
    //return HAL_UART_Receive(&huart7, (uint8_t *)data, len, 0);
}
  • 申请一片缓冲区
char shellBuffer[512];
  • 定义互斥锁
static SemaphoreHandle_t shellMutex;
  • 实现上锁解锁功能
/**
 * @brief 用户shell上锁
 * 
 * @param shell shell
 * 
 * @return int 0
 */
int userShellLock(Shell *shell)
{
    xSemaphoreTake(shellMutex, portMAX_DELAY);
    return 0;
}

/**
 * @brief 用户shell解锁
 * 
 * @param shell shell
 * 
 * @return int 0
 */
int userShellUnlock(Shell *shell)
{
    xSemaphoreGive(shellMutex);
    return 0;
}
  • 初始化函数实现
/**
 * @brief 用户shell初始化
 * 
 */
void userShellInit(void)
{
    shellMutex = xSemaphoreCreateMutex();

    shell.write = userShellWrite;
    shell.read = userShellRead;
    shell.lock = userShellLock;
    shell.unlock = userShellUnlock;
    shellInit(&shell, shellBuffer, 512);
    xTaskCreate(shellTask, "shell", 256, &shell, 5, NULL);
}
  • 配置文件修改

去掉了shell伴生对象配置和设置命令触发条件(0x0d)

/**
 * @file shell_cfg.h
 * @author Letter ([email protected])
 * @brief shell config
 * @version 3.0.0
 * @date 2019-12-31
 * 
 * @copyright (c) 2019 Letter
 * 
 */

#ifndef __SHELL_CFG_H__
#define __SHELL_CFG_H__

#include "stm32f4xx_hal.h"
#include "FreeRTOS.h"
#include "portable.h"


/**
 * @brief 是否使用默认shell任务while循环,使能宏`SHELL_USING_TASK`后此宏有意义
 *        使能此宏,则`shellTask()`函数会一直循环读取输入,一般使用操作系统建立shell
 *        任务时使能此宏,关闭此宏的情况下,一般适用于无操作系统,在主循环中调用`shellTask()`
 */
#define     SHELL_TASK_WHILE            1

/**
 * @brief 是否使用命令导出方式
 *        使能此宏后,可以使用`SHELL_EXPORT_CMD()`等导出命令
 *        定义shell命令,关闭此宏的情况下,需要使用命令表的方式
 */
#define     SHELL_USING_CMD_EXPORT      1

/**
 * @brief 是否使用shell伴生对象
 *        一些扩展的组件(文件系统支持,日志工具等)需要使用伴生对象
 */
#define     SHELL_USING_COMPANION       0


/**
 * @brief 支持shell尾行模式
 */
#define     SHELL_SUPPORT_END_LINE      1

/**
 * @brief 是否在输出命令列表中列出用户
 */
#define     SHELL_HELP_LIST_USER        0

/**
 * @brief 是否在输出命令列表中列出变量
 */
#define     SHELL_HELP_LIST_VAR         0

/**
 * @brief 是否在输出命令列表中列出按键
 */
#define     SHELL_HELP_LIST_KEY         1

/**
 * @brief 是否在输出命令列表中展示命令权限
 */
#define     SHELL_HELP_SHOW_PERMISSION  1

/**
 * @brief 使用LF作为命令行回车触发
 *        可以和SHELL_ENTER_CR同时开启
 */
#define     SHELL_ENTER_LF              0

/**
 * @brief 使用CR作为命令行回车触发
 *        可以和SHELL_ENTER_LF同时开启
 */
#define     SHELL_ENTER_CR              1

/**
 * @brief 使用CRLF作为命令行回车触发
 *        不可以和SHELL_ENTER_LF或SHELL_ENTER_CR同时开启
 */
#define     SHELL_ENTER_CRLF            0

/**
 * @brief 使用执行未导出函数的功能
 *        启用后,可以通过`exec [addr] [args]`直接执行对应地址的函数
 * @attention 如果地址错误,可能会直接引起程序崩溃
 */
#define     SHELL_EXEC_UNDEF_FUNC       0

/**
 * @brief shell命令参数最大数量
 *        包含命令名在内,超过16个参数并且使用了参数自动转换的情况下,需要修改源码
 */
#define     SHELL_PARAMETER_MAX_NUMBER  8

/**
 * @brief 历史命令记录数量
 */
#define     SHELL_HISTORY_MAX_NUMBER    5

/**
 * @brief 双击间隔(ms)
 *        使能宏`SHELL_LONG_HELP`后此宏生效,定义双击tab补全help的时间间隔
 */
#define     SHELL_DOUBLE_CLICK_TIME     200

/**
 * @brief 管理的最大shell数量
 */
#define     SHELL_MAX_NUMBER            5

/**
 * @brief shell格式化输出的缓冲大小
 *        为0时不使用shell格式化输出
 */
#define     SHELL_PRINT_BUFFER          128

/**
 * @brief shell格式化输入的缓冲大小
 *        为0时不使用shell格式化输入
 * @note shell格式化输入会阻塞shellTask, 仅适用于在有操作系统的情况下使用
 */
#define     SHELL_SCAN_BUFFER          128

/**
 * @brief 获取系统时间(ms)
 *        定义此宏为获取系统Tick,如`HAL_GetTick()`
 * @note 此宏不定义时无法使用双击tab补全命令help,无法使用shell超时锁定
 */
#define     SHELL_GET_TICK()            HAL_GetTick()

/**
 * @brief 使用锁
 * @note 使用shell锁时,需要对加锁和解锁进行实现
 */
#define     SHELL_USING_LOCK            1

/**
 * @brief shell内存分配
 *        shell本身不需要此接口,若使用shell伴生对象,需要进行定义
 */
#define     SHELL_MALLOC(size)          pvPortMalloc(size)

/**
 * @brief shell内存释放
 *        shell本身不需要此接口,若使用shell伴生对象,需要进行定义
 */
#define     SHELL_FREE(obj)             vPortFree(obj)

/**
 * @brief 是否显示shell信息
 */
#define     SHELL_SHOW_INFO             1

/**
 * @brief 是否在登录后清除命令行
 */
#define     SHELL_CLS_WHEN_LOGIN        1

/**
 * @brief shell默认用户
 */
#define     SHELL_DEFAULT_USER          "letter"

/**
 * @brief shell默认用户密码
 *        若默认用户不需要密码,设为""
 */
#define     SHELL_DEFAULT_USER_PASSWORD ""

/**
 * @brief shell自动锁定超时
 *        shell当前用户密码有效的时候生效,超时后会自动重新锁定shell
 *        设置为0时关闭自动锁定功能,时间单位为`SHELL_GET_TICK()`单位
 * @note 使用超时锁定必须保证`SHELL_GET_TICK()`有效
 */
#define     SHELL_LOCK_TIMEOUT          0 * 60 * 1000

#endif

4、测试

测试代码如下:

void TestEasyTask(void const *argument)
{

 	userShellInit();

	while(1)
	{
		osDelay(1000);
	}

}


void shell_test(uint32_t num)
{
	printf("shell:%d",num);
}

SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), func, shell_test, test);

打开Mobaxterm软件,设备上电即有信息打印出来 

按下”TAB“键,调出帮助信息

如图输入命令,得到结果

 我们即可通过串口测试shell_test函数

总结

 letter shell是一个C语言编写的,可以嵌入在程序中的嵌入式shell,主要面向嵌入式设备,以C语言函数为运行单位,可以通过命令行调用,运行程序中的函数。通过移植这个工具,方便我们进行模块的单元测试。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/freedompoi/article/details/122132431

智能推荐

基于Docker的Redis高可用集群搭建(redis-sentinel)_weixin_34240657的博客-程序员秘密

前言  之前介绍了用docker来搭建redis主从环境,但这只是对数据添加了从库备份(主从复制),当主库down掉的时候,从库是不会自动升级为主库的,也就是说,该redis主从集群并非是高可用的。  目前来说,高可用(主从复制、主从切换)redis集群有两种方案,一种是redis-sentinel,只有...

PowerShell批量扫描IP和端口_weixin_33774615的博客-程序员秘密

前面的文章中曾经发布了对指定IP进行批量端口扫描的方法和脚本,过PowerShell收发TCP和UDP消息包的方法以及通过PowerShell尝试登录SQLServer服务的方法,这构成了PSNet程序集用于通过PowerShell对网络状态进行操作。最近在不断尝试之下,找到了对指定范围的IP段进行扫描和对端口进行扫描的方法,本文将会介绍如何通过PowerShell批量扫描IP及其对应的端口。...

【动态规划】01背包问题(通俗易懂,超基础讲解)_01背包问题动态规划_春卷同学的博客-程序员秘密

转载自https://blog.csdn.net/qq_38410730/article/details/81667885问题描述有n个物品,它们有各自的体积和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?为方便讲解和理解,下面讲述的例子均先用具体的数字代入,即:eg:number=4,capacity=8i(物品编号) 1 2 3 ...

TPM 协议栈和工具介绍(一)_June_Hou的博客-程序员秘密

1.TPM相关的项目,有几个开源的项目地址:https://github.com/tpm2-software2.tpm2-software 一共包含四个项目 tpm2-tools tpm2-tss tpm2-abrmd tpm2-tss-engine3. tpm2-tools这一个项目为用户提供了使用TPM资源的几个命令,如:tpm2_create : 创建keytpm2_sign ...

【蓝桥杯省赛】冲刺练习题【第十二届省赛1套题】倒计时【03】天(准考证组委会已下发,请查询)_红目香薰的博客-程序员秘密

距离【第十三届蓝桥杯4月9日省赛】仅剩【04天】今日题型:【第十二届省赛1套题】️循环是一切暴力的基础,暴力基础,转起来。️国一镇楼比赛题目与分数比例确认范围:结果填空题5道,共计45分。程序设计题5道,共计105分。️刷题安排️日期 题目类型 题目数量 3月25日 循环 6 3月26日 超大数 6 3月27日 数组 6 3月28日 枚举 6..

BCM56330系列交换芯片学习心得_98K甩狙的博客-程序员秘密

因为所里面的任务的要求,所以要学习学习BCM交换芯片,导师也说过,学习BCM芯片的Datasheet或者Programmerguider是对以后是很有好处的,所以我就奔着学习英语的心态开始学习BCM56330交换芯片。我学习的是BCM56330PG100,其实博通的芯片在5633x系列都差不多,会一种其他都会了。长话短说,开始记录学习内容。2015.2.12首先要弄清楚BCM5633X是

随便推点

SSH-KeyGen 实现linux服务器之间免密码登录_weixin_33721427的博客-程序员秘密

为什么80%的码农都做不了架构师?>>> ...

深入浅出NIO之Selector实现原理_nio selector工作原理_PolarisHuster的博客-程序员秘密

转载自:https://www.jianshu.com/p/0d497fe5484a前言Java NIO 由以下几个核心部分组成:1、Buffer2、Channel3、SelectorBuffer和Channel在深入浅出NIO之Channel、Buffer一文中已经介绍过,本文主要讲解NIO的Selector实现原理。之前进行socket编程时,accept方法会一直阻塞,...

BZOJ2875: [Noi2012]随机数生成器 矩阵乘法+快速乘_多位数乘法生成器_Oakley_的博客-程序员秘密

显然需要用矩阵乘法快速幂矩阵为:A 0C 1因为mod很大所以直接做乘法会爆掉,在做乘法运算的时候要用一下快速乘#include#include#include#include#includeusing namespace std;#define ll long longstruct matrix {ll ju[3][3];}s,a;ll mod,b,c,x0,

redis持久化RDB与AOF_旅人mfy的博客-程序员秘密

问题说明,依赖冲突,循环依赖

通过NI Vision Assistant 实现Labview实时图像处理的步骤_woshigaowei5146的博客-程序员秘密

通过NI Vision Assistant 实现Labview实时图像处理的步骤可分为两步:相机实时图像获取,图像处理。第一步相机实时图像获取:Labview中有很多范例:帮助-查找范例-目录结构-Vision Acquisition-NI-IMAQdx,随便打开一个都可以实现实时图像的获取。第二步图像处理:可打开Vision Assistant,右上角Acquice Images,第二...

Hive 常见错误及解决方案_ITBOY_ITBOX的博客-程序员秘密

1.连接不上mysql数据库 (1)导错驱动包,应该把mysql-connector-java-5.1.27-bin.jar导入/opt/module/hive/lib的不是这个包。错把mysql-connector-java-5.1.27.tar.gz导入hive/lib包下。 (2)修改user表中的主机名称没有都修改为%,而是修改为localhost...

推荐文章

热门文章

相关标签