嵌入式系统应用-第五章 操作系统(RTOS)之FinSH(shell)

本文介绍了RT-Thread操作系统中的FinSHshell,它是用于与设备交互的命令行组件,支持命令行模式和C语言解释器模式。文章详细描述了FinSH的两种输入模式、配置方法,以及如何使用shell进行设备调试和命令执行。
摘要由CSDN通过智能技术生成

第五章 操作系统(RTOS)之shell

5.1 shell 介绍

在计算机发展的早期,图形系统出现之前,没有鼠标,甚至没有键盘。那时候人们如何与计算机交互呢?最早期的计算机使用打孔的纸条向计算机输入命令,编写程序。后来随着计算机的不断发展,显示器、键盘成为计算机的标准配置,但此时的操作系统还不支持图形界面,计算机先驱们开发了一种软件,它接受用户输入的命令,解释之后,传递给操作系统,并将操作系统执行的结果返回给用户。这个程序像一层外壳包裹在操作系统的外面,所以它被称为 shell。

嵌入式设备通常需要将开发板与 PC 机连接起来通讯,常见连接方式包括:串口、USB、以太网、Wi-Fi等。一个灵活的 shell 也应该支持在多种连接方式上工作。有了 shell,就像在开发者和计算机之间架起了一座沟通的桥梁,开发者能很方便的获取系统的运行情况,并通过命令控制系统的运行。特别是在调试阶段,有了 shell,开发者除了能更快的定位到问题之外,也能利用 shell 调用测试函数,改变测试函数的参数,减少代码的烧录次数,缩短项目的开发时间。FinSH 是 RT-Thread 的命令行组件shell),正是基于上面这些考虑而诞生的,FinSH 的发音为[ˈfɪnʃ]。读完本章,我们会对 FinSH 的工作方式以及如何导出自己的命令到 FinSH 有更加深入的了解。

FinSH 是 RT-Thread 的命令行组件,提供一套供用户在命令行调用的操作接口,主要用于调试或查看系统信息。它可以使用串口 / 以太网 / USB 等与 PC 机进行通信,硬件拓扑结构如下图所示:
在这里插入图片描述
当使用串口连接设备与控制终端时,FinSH 命令的执行流程,如下图所示:
在这里插入图片描述
跟linux的shell一样,RTOS也支持一下补全指令
在这里插入图片描述

5.2 FISH 输入模式

FinSH 支持两种输入模式,分别是传统命令行模式和 C 语言解释器模式。

5.2.1 命令行模式

此模式又称为 msh(module shell),msh 模式下,FinSH 与传统 shell(dos/bash)执行方式一致,例如,可以通过 cd / 命令将目录切换至根目录。
msh 通过解析,将输入字符分解成以空格区分开的命令和参数。其命令执行格式如下所示:
command [arg1] [arg2] […]
其中 command 既可以是 RT-Thread 内置的命令,也可以是可执行的文件。

5.2.2 解释器模式

C-Style 模式。C 语言解释器模式下,FinSH 能够解析执行大部分 C 语言的表达式,并使用类似 C 语言的函数调用方式访问系统中的函数及全局变量,此外它也能够通过命令行方式创建变量。在该模式下,输入的命令必须类似 C 语言中的函数调用方式,即必须携带 () 符号,例如,要输出系统当前所有线程及其状态,在 FinSH 中输入 list_thread() 即可打印出需要的信息。FinSH 命令的输出为此函数的返回值。对于一些不存在返回值的函数(void 返回值),这个打印输出没有意义。

如果在 RT-Thread 中同时使能了这两种模式,那它们可以动态切换,在 msh 模式下输入 exit 后回车,即可切换到 C-Style 模式。在 C-Style 模式输入 msh() 后回车,即可进入 msh 模式。两种模式的命令不通用,msh 命令无法在 C-Style 模式下使用,反之同理。
我们一般还是采用命令行模式。

5.3 Finsh 配置

5.3.1 加载Finsh的库

在这里插入图片描述

5.3.2 开启配置。

标黄的部分,删除模块。在这里插入图片描述

5.3.3 配置串口函数

进入一下界面,配置以下代码。在这里插入图片描述
串口配置

static int uart_init(void)
{
//#error "TODO 2: Enable the hardware uart and config baudrate."
	
 USART_InitTypeDef USART_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
  
  /* Enable GPIO clock */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA , ENABLE);  // PA9 & pa 10
  
  /* Enable USART clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  
  /* Connect USART pins to AF7 */
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
  
  /* Configure USART Tx and Rx as alternate function push-pull */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Enable the USART OverSampling by 8 */
  USART_OverSampling8Cmd(USART1, ENABLE);  

  /* USARTx configuration ----------------------------------------------------*/
  /* USARTx configured as follows:
        - BaudRate = 5250000 baud
		   - Maximum BaudRate that can be achieved when using the Oversampling by 8
		     is: (USART APB Clock / 8) 
			 Example: 
			    - (USART3 APB1 Clock / 8) = (42 MHz / 8) = 5250000 baud
			    - (USART1 APB2 Clock / 8) = (84 MHz / 8) = 10500000 baud
		   - Maximum BaudRate that can be achieved when using the Oversampling by 16
		     is: (USART APB Clock / 16) 
			 Example: (USART3 APB1 Clock / 16) = (42 MHz / 16) = 2625000 baud
			 Example: (USART1 APB2 Clock / 16) = (84 MHz / 16) = 5250000 baud
        - Word Length = 8 Bits
        - one Stop Bit
        - No parity
        - Hardware flow control disabled (RTS and CTS signals)
        - Receive and transmit enabled
  */ 
  USART_InitStructure.USART_BaudRate = 4800;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  USART_Init(USART1, &USART_InitStructure);
  
  /* NVIC configuration */
  /* Configure the Priority Group to 2 bits */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  
  /* Enable the USARTx Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

	 /* Enable the Tx buffer empty interrupt */
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); 
   
  /* Enable USART */
  USART_Cmd(USART1, ENABLE);
		
	
    return 0;
}
}

输出配置

void rt_hw_console_output(const char *str)
{
//#error "TODO 3: Output the string 'str' through the uart."
	/* Place your implementation of fputc here */
  /* e.g. write a character to the USART */
		u32 size = rt_strlen(str);
    for (u32 i = 0; i < size; i++)
    {
				if(*str=='\n')
				{
					
						USART_SendData(USART1, '\r');
					  while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
				    {}
						USART_SendData(USART1, '\n');
				}
				else
				{
						USART_SendData(USART1, (uint8_t) *(str));
				}
			  while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
				{}
			  str++;       
    }
}

5.3.3 配置接收缓存

输入配置,找到finsh_port.c文件,修改一下代码。

#include <rthw.h>
#include <rtconfig.h>
#include "stm32f4xx.h"
#ifndef RT_USING_FINSH
#error Please uncomment the line <#include "finsh_config.h"> in the rtconfig.h 
#endif
#ifdef RT_USING_FINSH
#define BUFFERSIZE  28
u32 ubRxIndex=0;
u32 rbRxIndex=0;
char aRxBuffer[BUFFERSIZE];

RT_WEAK char rt_hw_console_getchar(void)
{
    /* Note: the initial value of ch must < 0 */
    int ch = -1;

//#error "TODO 4: Read a char from the uart and assign it to 'ch'."
		if(rbRxIndex!=ubRxIndex)
		{
				ch=aRxBuffer[rbRxIndex++];
			  if(rbRxIndex>=BUFFERSIZE)
					rbRxIndex=0;
		}
    return ch;
}

void USART1_IRQHandler(void)
{
  /* USART in Receiver mode */
  if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
  {
    if (ubRxIndex < BUFFERSIZE)
    {
      /* Receive Transaction data */
      aRxBuffer[ubRxIndex++] = USART_ReceiveData(USART1);
    }
    else
    {
      /* Disable the Rx buffer not empty interrupt */
			 ubRxIndex=0;
       aRxBuffer[ubRxIndex++] = USART_ReceiveData(USART1);
    } 
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
  }
}
#endif /* RT_USING_FINSH */

5.4 shell 常见命令

相关指令

version - show RT-Thread version information
list_thread - list thread
list_sem - list semaphore in system
list_event - list event in system
list_mutex - list mutex in system
list_mailbox - list mail box in system
list_msgqueue - list message queue in system
list_timer - list timer in system
list_device - list device in system
exit - return to RT-Thread shell mode
help - RT-Thread shell help.
ps - List threads in the system.
time - Execute command with time.
free - Show the memory usage in the system.

5.5 shell 应用

5.5.1 不带参数操作

代码

#include <rtthread.h>
void hello(void)
{
rt_kprintf("hello RT-Thread!\n");
}
MSH_CMD_EXPORT(hello , say hello to RT-Thread);

操作

msh />hello
hello RT_Thread!
msh />

5.5.2 带参数操作

配置函数

static void atcmd(int argc, char**argv)
{
if (argc < 2)
{
	rt_kprintf("Please input'atcmd <server|client>'\n");
	return;
}
if (!rt_strcmp(argv[1], "server"))
{
	rt_kprintf("AT server!\n");
}
else if (!rt_strcmp(argv[1], "client"))
{
	rt_kprintf("AT client!\n");
}
else
{
	rt_kprintf("Please input'atcmd <server|client>'\n");
}
}
MSH_CMD_EXPORT(atcmd, atcmd sample: atcmd <server|client>);

输出结果

msh >atcmd
Please input'atcmd <server|client>'
msh >
msh >atcmd server
AT server!
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

HHONGQI123

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

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

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

打赏作者

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

抵扣说明:

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

余额充值