APM32芯得EP.25|基于APM32F4移植使用letter-shell命令行终端

极海Geehy 2023-11-03 17:05


《APM32芯得》系列内容为用户使用APM32系列产品的经验总结,均转载自21ic论坛极海半导体专区,全文未作任何修改,未经原文作者授权禁止转载。



1. letter-shell简介


letter shell是一个C语言编写的,可以嵌入在程序中的嵌入式shell,主要面向嵌入式设备。

说得直白点他就是一个命令行交互软件,可以读取用户输入的命令,找到并执行命令对应的函数。

letter-shell的功能十分强大,目前主要功能有:

命令自动补全

快捷键功能定义

命令权限管理

用户管理

变量支持

代理函数和参数代理解析


下面是letter-shell运行起来的效果图:



该项目代码遵循MIT协议,作者的代码仓库如下:

https://github.com/NevermindZZT/letter-shell


2. 获取源码


我们是要把letter-shell,移植到极海APM32F4的MCU上面运行,所以我们需要获取到极海的APM32F4的SDK包,以及letter-shell的源码。

获取 APM32F4 SDK :

https://geehy.com/support/apm32?id=311


letter-shell 开源项目源码:

可以到简介,给出的作者的github官网下载。如果因为网速的原因,也可以到gitee上面下载,gitee也有很多关于letter-shell的源码,下面给出其中一个仓库地址:

https://gitee.com/biao22ndg/letter-shell


3. APM32F4上移植letter-shell过程


3.1 准备一份可以通过串口打印信息的工程


我们把官网的APM32F4 SDK下载下来后,然后我们选择一个串口中断的例程,如下: 



然后,把这个例程不需要的代码去掉,只留下串口相关的初始化代码,还有printf重定向的代码就行了。

编译下载到板子之后,可以看到串口正常输出打印信息,就说明代码正常。


3.2 向工程添加letter-shell源码


letter-shell源码目录如下: 



我们只需要把src目录下的源码复制到对应工程目录下即可。

我这里就复制到对应工程的 \Middlewares\letter-shell 目录下。


3.3 在keil-MDK中添加源码和文件包含路径


打开keil的项目管理窗口,然后添加我们刚刚复制的letter-shell的源码目录src的所有文件: 



添加文件之后,再添加letter-shell的文件包含路径:



点击OK,退出。这个时候源码相当于添加完成,这是编译是可以通过的,没警告和错误。但是还不能正常使用letter-shell,因为还没有添加移植的接口函数。


3.4 添加shell_port.c文件,提供读写接口函数


我们还需要提供letter-shell的读写接口函数,这样letter-shell才能通过串口输出字符,或者通过串口获取输入字符。

在letter-shell的源码目录下,demo目录中,已经提供了基于stm32 freeRTOS的读写接口,我们可以把该文件复制到我们的工程目录下,然后在该文件基础上进行改写:



1、在shell_port.c中,我们主要实现shell的写函数即可,代码如下:


/**

 * [url=home.php?mod=space&uid=247401]@brief[/url] 用户shell写

 * 

 * @param data 数据

 * @param len 数据长度

 * 

 * [url=home.php?mod=space&uid=266161]@return[/url] short 实际写入的数据长度

 */

short userShellWrite(char *data, unsigned short len)

{

        unsigned short temp = len;

        

        while (temp--)

        {

                /* send a byte of data to the serial port */

                USART_TxData(USART1, *data++);


                /* wait for the data to be send */

                while (USART_ReadStatusFlag(USART1, USART_FLAG_TXBE) == RESET);

        }

        

    return len;

}


2、关于读函数,我们可以不用实现,因为我们使用的是串口中断方式接收字符,不需要实现读函数。我们只需要在串口中断函数中,调用shellHandler即可。串口中断代码如下:


/*!

 * [url=home.php?mod=space&uid=247401]@brief[/url]        This function handles USART1 RX interrupt Handler

 *

 * @param        None

 *

 * @retval       None

 *

 * @note

 */

void USART1_IRQHandler(void)

{

        uint8_t ch;

        

        if (USART_ReadIntFlag(USART1, USART_INT_RXBNE) == SET)

        {

                ch = USART_RxData(USART1);

                shellHandler(&shell, ch);

        }

}


3、提供letter-shell的初始化函数,该函数其实主要就是初始化shell结构体。因为我们只用到写函数,所以只提供了写接口。具体代码如下:


Shell shell;

char shellBuffer[512];


/**

 * [url=home.php?mod=space&uid=247401]@brief[/url] 用户shell初始化

 * 

 */

void userShellInit(void)

{

    shell.write = userShellWrite;

    shellInit(&shell, shellBuffer, 512);

}


3.5 main函数初始化letter-shell


当我们把接口函数都提供了之后,就只需要在main函数调用 letter-shell 的初始化函数 userShellInit 即可。main函数代码如下:


/*!

 * [url=home.php?mod=space&uid=247401]@brief[/url]       Main program

 *

 * @param       None

 *

 * @retval      None

 */

int main(void)

{

    /* USART Initialization */

    USART_Config_T usartConfigStruct;


    usartConfigStruct.baudRate = 115200;

    usartConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;

    usartConfigStruct.mode = USART_MODE_TX_RX;

    usartConfigStruct.parity = USART_PARITY_NONE;

    usartConfigStruct.stopBits = USART_STOP_BIT_1;

    usartConfigStruct.wordLength = USART_WORD_LEN_8B;

    APM_EVAL_COMInit(COM1, &usartConfigStruct);

    APM_EVAL_COMInit(COM2, &usartConfigStruct);


    /* Enable USART1 RXBNE interrput */

    USART_EnableInterrupt(EVAL_COM1, USART_INT_RXBNE);

    USART_ClearStatusFlag(EVAL_COM1, USART_FLAG_RXBNE);

    NVIC_EnableIRQRequest(EVAL_COM1_IRQn,1,0);

        

        userShellInit();


    while(1)

    {

    }

}


主要就是初始化串口之后,就调用 userShellInit 初始化letter-shell。

到这里,我们就完成了letter-shell的移植了,编译下载可以看到如下效果:



可以看到letter-shell支持了一些默认命令。


3.6 letter-shell的配置文件shell_cfg.h


该文件也是在letter-shell的src目录下,shell_cfg.h文件中包含了所有用于配置shell的宏,在使用前,可根据需要进行配置。我们工程是使用的默认配置,基本的功能也有,要想使用其他功能,可能需要先打开某个配置宏,定义的含义如下:



4. 自定义自己的命令


4.1 与导出自定义命令相关的宏


letter-shell支持定义自己的命令,并且把该命令导出到shell终端中,以供我们在命令行下使用自定义的命令。

在使用letter-shell自定义命令时,要先检查 shell_cfg.h 文件是否开启了命令导出功能。


/**

 * [url=home.php?mod=space&uid=247401]@brief[/url] 是否使用命令导出方式

 *        使能此宏后,可以使用`SHELL_EXPORT_CMD()`等导出命令

 *        定义shell命令,关闭此宏的情况下,需要使用命令表的方式

 */

#define     SHELL_USING_CMD_EXPORT      1


就是这个宏需要定义为 1 。开启了这个宏,我们就可以编写自己的命令函数,然后导出到shell终端了。

导出自定义命令的宏在 shell.h 文件中定义,其代码如下:


/**

 * [url=home.php?mod=space&uid=247401]@brief[/url] shell 命令定义

 *

 * @param _attr 命令属性

 * @param _name 命令名

 * @param _func 命令函数

 * @param _desc 命令描述

 */

#define SHELL_EXPORT_CMD(_attr, _name, _func, _desc) \

        const char shellCmd##_name[] = #_name; \

        const char shellDesc##_name[] = #_desc; \

        SHELL_USED const ShellCommand \

        shellCommand##_name SHELL_SECTION("shellCommand") =  \

        { \

            .attr.value = _attr, \

            .data.cmd.name = shellCmd##_name, \

            .data.cmd.function = (int (*)())_func, \

            .data.cmd.desc = shellDesc##_name \

        }


这里作者加入了命令属性的参数,主要就是定义该命令的权限,类型,是否使用返回值输出等等(详细的属性定义可以去看源码),其他参数就是命令名,对应的命令函数名,已经该命令的描述。


4.2 编写一个命令测试函数


这里我编写一个测试命令函数,代码如下:


/* 自定义命令测试函数 */

int test_func(int a, char *str)

{

        printf("%d\r\n", a);

        printf("%s\r\n", str);

        

        return 0;

}


/* 导出到命令列表里 */

SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC), test_cmd, test_func, test cmd);


然后编译运行,可以看到多了一个test_cmd命令:



可以看到我们运行这个命令的时候,输出了我们代码的打印内容。


根据作者的reamme文件,目前 letter shell 3.x 版本,命令函数参数只支持整数,字符,字符串参数,以及在某些情况下的浮点参数直接传递给执行命令的函数。浮点型参数是在哪些情况才支持,可以阅读作者的文档。


另外,参数的个数,是有一个宏配置的:


/**

 * [url=home.php?mod=space&uid=247401]@brief[/url] shell命令参数最大数量

 *        包含命令名在内,超过16个参数并且使用了参数自动转换的情况下,需要修改源码

 */

#define     SHELL_PARAMETER_MAX_NUMBER  8


默认只支持8个参数,当然我们可以修改支持更多参数个数。


我也把整个工程源码上传了,以供大家参考。



注:文章作者在原帖中提供了工程文件,有需要请至原文21ic论坛下载

原文地址:https://bbs.21ic.com/icview-3272196-1-1.html

或点击下方 阅读原文 跳转


   0756 6299999

info@geehy.com

www.geehy.com

广东省珠海市香洲区广湾街83号01栋

极海Geehy 极海半导体是一家致力于开发工业级/车规级MCU、模拟与混合信号IC及系统级芯片的集成电路设计型企业
评论
  • 根据Global Info Research(环洋市场咨询)项目团队最新调研,预计2030年全球无人机电池和电源产值达到2834百万美元,2024-2030年期间年复合增长率CAGR为10.1%。 无人机电池是为无人机提供动力并使其飞行的关键。无人机使用的电池类型因无人机的大小和型号而异。一些常见的无人机电池类型包括锂聚合物(LiPo)电池、锂离子电池和镍氢(NiMH)电池。锂聚合物电池是最常用的无人机电池类型,因为其能量密度高、设计轻巧。这些电池以输出功率大、飞行时间长而著称。不过,它们需要
    GIRtina 2025-01-13 10:49 161浏览
  • ARMv8-A是ARM公司为满足新需求而重新设计的一个架构,是近20年来ARM架构变动最大的一次。以下是对ARMv8-A的详细介绍: 1. 背景介绍    ARM公司最初并未涉足PC市场,其产品主要针对功耗敏感的移动设备。     随着技术的发展和市场需求的变化,ARM开始扩展到企业设备、服务器等领域,这要求其架构能够支持更大的内存和更复杂的计算任务。 2. 架构特点    ARMv8-A引入了Execution State(执行状
    丙丁先生 2025-01-12 10:30 433浏览
  • 01. 什么是过程能力分析?过程能力研究利用生产过程中初始一批产品的数据,预测制造过程是否能够稳定地生产符合规格的产品。可以把它想象成一种预测。通过历史数据的分析,推断未来是否可以依赖该工艺持续生产高质量产品。客户可能会要求将过程能力研究作为生产件批准程序 (PPAP) 的一部分。这是为了确保制造过程能够持续稳定地生产合格的产品。02. 基本概念在定义制造过程时,目标是确保生产的零件符合上下规格限 (USL 和 LSL)。过程能力衡量制造过程能多大程度上稳定地生产符合规格的产品。核心概念很简单:
    优思学院 2025-01-12 15:43 471浏览
  •   在信号处理过程中,由于信号的时域截断会导致频谱扩展泄露现象。那么导致频谱泄露发生的根本原因是什么?又该采取什么样的改善方法。本文以ADC性能指标的测试场景为例,探讨了对ADC的输出结果进行非周期截断所带来的影响及问题总结。 两个点   为了更好的分析或处理信号,实际应用时需要从频域而非时域的角度观察原信号。但物理意义上只能直接获取信号的时域信息,为了得到信号的频域信息需要利用傅里叶变换这个工具计算出原信号的频谱函数。但对于计算机来说实现这种计算需要面对两个问题: 1.
    TIAN301 2025-01-14 14:15 76浏览
  • PNT、GNSS、GPS均是卫星定位和导航相关领域中的常见缩写词,他们经常会被用到,且在很多情况下会被等同使用或替换使用。我们会把定位导航功能测试叫做PNT性能测试,也会叫做GNSS性能测试。我们会把定位导航终端叫做GNSS模块,也会叫做GPS模块。但是实际上他们之间是有一些重要的区别。伴随着技术发展与越发深入,我们有必要对这三个词汇做以清晰的区分。一、什么是GPS?GPS是Global Positioning System(全球定位系统)的缩写,它是美国建立的全球卫星定位导航系统,是GNSS概
    德思特测试测量 2025-01-13 15:42 447浏览
  • 流量传感器是实现对燃气、废气、生活用水、污水、冷却液、石油等各种流体流量精准计量的关键手段。但随着工业自动化、数字化、智能化与低碳化进程的不断加速,采用传统机械式检测方式的流量传感器已不能满足当代流体计量行业对于测量精度、测量范围、使用寿命与维护成本等方面的精细需求。流量传感器的应用场景(部分)超声波流量传感器,是一种利用超声波技术测量流体流量的新型传感器,其主要通过发射超声波信号并接收反射回来的信号,根据超声波在流体中传播的时间、幅度或相位变化等参数,间接计算流体的流量,具有非侵入式测量、高精
    华普微HOPERF 2025-01-13 14:18 443浏览
  • Snyk 是一家为开发人员提供安全平台的公司,致力于协助他们构建安全的应用程序,并为安全团队提供应对数字世界挑战的工具。以下为 Snyk 如何通过 CircleCI 实现其“交付”使命的案例分析。一、Snyk 的挑战随着客户对安全工具需求的不断增长,Snyk 的开发团队面临多重挑战:加速交付的需求:Snyk 的核心目标是为开发者提供更快、更可靠的安全解决方案,但他们的现有 CI/CD 工具(TravisCI)运行缓慢,无法满足快速开发和部署的要求。扩展能力不足:随着团队规模和代码库的不断扩大,S
    艾体宝IT 2025-01-10 15:52 160浏览
  • 说到福特,就要从亨利·福特(Henry Ford)这个人物说起。在发明大王爱迪生的电气工厂担任工程师的福特下班后,总是在自家仓库里努力研究和开发汽车。1896年,福特终于成功制造出一辆三轮车,开启了福特汽车的传奇。最初几年,福特都是独自制造汽车并同时进行销售。 (今天很多人都知道的精益管理中的5S方法,或多或少地受到了福特 CANDO方法的影响。)1903年,福特从牧师、律师、银行家、会计师等十一位股东那里筹集了十万美元,并在自家庭院成立了美国第五百零三家汽车公司——福特汽车公司(Fo
    优思学院 2025-01-10 11:21 49浏览
  • 电动汽车(EV)正在改变交通运输,为传统内燃机提供更清洁、更高效的替代方案。这种转变的核心是电力电子和能源管理方面的创新,而光耦合器在其中发挥着关键作用。这些不起眼的组件可实现可靠的通信、增强安全性并优化电动汽车系统的性能,使其成为正在进行的革命中不可或缺的一部分。光耦合器,也称为光隔离器,是一种使用光传输电信号的设备。通过隔离高压和低压电路,光耦合器可确保安全性、减少干扰并保持信号完整性。这些特性对于电动汽车至关重要,因为精确控制和安全性至关重要。 光耦合器在电动汽车中的作用1.电池
    腾恩科技-彭工 2025-01-10 16:14 69浏览
  • 新年伊始,又到了对去年做总结,对今年做展望的时刻 不知道你在2024年初立的Flag都实现了吗? 2025年对自己又有什么新的期待呢? 2024年注定是不平凡的一年, 一年里我测评了50余块开发板, 写出了很多科普文章, 从一个小小的工作室成长为科工公司。 展望2025年, 中国香河英茂科工, 会继续深耕于,具身机器人、飞行器、物联网等方面的研发, 我觉得,要向未来学习未来, 未来是什么? 是掌握在孩子们生活中的发现,和精历, 把最好的技术带给孩子,
    丙丁先生 2025-01-11 11:35 428浏览
  • 在不断发展的电子元件领域,继电器——作为切换电路的关键设备,正在经历前所未有的技术变革。固态继电器(SSR)和机械继电器之间的争论由来已久。然而,从未来发展的角度来看,固态继电器正逐渐占据上风。本文将从耐用性、速度和能效三个方面,全面剖析固态继电器为何更具优势,并探讨其在行业中的应用与发展趋势。1. 耐用性:经久耐用的设计机械继电器:机械继电器依靠物理触点完成电路切换。然而,随着时间的推移,这些触点因电弧、氧化和材料老化而逐渐磨损,导致其使用寿命有限。因此,它们更适合低频或对切换耐久性要求不高的
    腾恩科技-彭工 2025-01-10 16:15 93浏览
  • 随着通信技术的迅速发展,现代通信设备需要更高效、可靠且紧凑的解决方案来应对日益复杂的系统。中国自主研发和制造的国产接口芯片,正逐渐成为通信设备(从5G基站到工业通信模块)中的重要基石。这些芯片凭借卓越性能、成本效益及灵活性,满足了现代通信基础设施的多样化需求。 1. 接口芯片在通信设备中的关键作用接口芯片作为数据交互的桥梁,是通信设备中不可或缺的核心组件。它们在设备内的各种子系统之间实现无缝数据传输,支持高速数据交换、协议转换和信号调节等功能。无论是5G基站中的数据处理,还是物联网网关
    克里雅半导体科技 2025-01-10 16:20 424浏览
  • 随着数字化的不断推进,LED显示屏行业对4K、8K等超高清画质的需求日益提升。与此同时,Mini及Micro LED技术的日益成熟,推动了间距小于1.2 Pitch的Mini、Micro LED显示屏的快速发展。这类显示屏不仅画质卓越,而且尺寸适中,通常在110至1000英寸之间,非常适合应用于电影院、监控中心、大型会议、以及电影拍摄等多种室内场景。鉴于室内LED显示屏与用户距离较近,因此对于噪音控制、体积小型化、冗余备份能力及电气安全性的要求尤为严格。为满足这一市场需求,开关电源技术推出了专为
    晶台光耦 2025-01-13 10:42 455浏览
  • 随着全球向绿色能源转型的加速,对高效、可靠和环保元件的需求从未如此强烈。在这种背景下,国产固态继电器(SSR)在实现太阳能逆变器、风力涡轮机和储能系统等关键技术方面发挥着关键作用。本文探讨了绿色能源系统背景下中国固态继电器行业的前景,并强调了2025年的前景。 1.对绿色能源解决方案日益增长的需求绿色能源系统依靠先进的电源管理技术来最大限度地提高效率并最大限度地减少损失。固态继电器以其耐用性、快速开关速度和抗机械磨损而闻名,正日益成为传统机电继电器的首选。可再生能源(尤其是太阳能和风能
    克里雅半导体科技 2025-01-10 16:18 319浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦