如何在 STM32 平台移植 Letter shell

发布于:2023-01-16 ⋅ 阅读:(666) ⋅ 点赞:(0)

1. 简介

Letter shell 是一个 C 语言编写的,可以嵌入在程序中的嵌入式 shell,主要面向嵌入式设备,以 C 语言函数为运行单位,可以通过命令行调用,运行程序中的函数。

1.1. 主要特性

  • 命令自动补全
  • 快捷键功能定义
  • 命令权限管理
  • 用户管理
  • 变量支持
  • 代理函数和参数代理解析

2. 获取 Letter shell 源码

Letter shell 的 github 仓库地址为: https://github.com/NevermindZZT/letter-shell
在这里插入图片描述
这里我下载最新版的3.1.2版本
在这里插入图片描述

3.CubeMX 新建工程

3.1 FreeRTOS 移植letter-shell

为什么以FreeRTOS移植 Letter shell 官方给的例程就是FreeRTOS的,基于开发板新建工程,主要配置串口。根据自己的开发板选择相应的串口。串口配置默认就好,波特率1152000 ,注意一定要将中断打开。
在这里插入图片描述
在这里插入图片描述
由于使用了FreeRTOS,简单配置一下,随便新建一个任务。
在这里插入图片描述
在这里为避免生成代码时出现警告,重新配置下SYS将滴答定时器换成TIM6;
在这里插入图片描述
CubeMX就配置完成了。

4. STM32G474 Letter shell 移植

4.1. 工程文件结构

新建Letter_shell 文件夹,导入 Letter_shell 核心文件, 将 extensions、 src 和 tools 文件夹直接拷贝到 Letter_shell 文件夹里,新建 port 文件夹,用于存放移植接口文件 shell_cfg.h、 shell_port.h和 shell_port.c 文件,这三个文件在下载的源码letter-shell-master->demo->stm32-freertos文件夹内。
直接添加到自己新建的port文件夹内。

4.2. 搭建 Keil 工程框架

以Keil这个IDE为例(其他IDE工程搭建情况类似,这里不做赘述), 在工程里添加Letter_shell,并将 src 文件夹和 port 文件夹下的 c 文件添加进来。
在这里插入图片描述

在 Setup Compiler Include Paths 中将 src 和 port 文件夹里的头文件包含进来。
在这里插入图片描述

在 Keil 工程的 Linker 选项卡里,添加–keep shellCommand*, 以防被编译优化。
在这里插入图片描述

4.3. 编写移植接口文件

重写shell_port.c

/**
 * @file shell_port.c
 * @author Letter (NevermindZZT@gmail.com)
 * @brief 
 * @version 0.1
 * @date 2019-02-22
 * 
 * @copyright (c) 2019 Letter
 * 
 */

#include "FreeRTOS.h"
#include "task.h"
#include "shell.h"
//#include "serial.h"
#include "stm32g4xx_hal.h"
#include "usart.h"
//#include "cevent.h"
//#include "log.h"


Shell shell;
char shellBuffer[512];

//static SemaphoreHandle_t shellMutex;

/**
 * @brief 用户shell写
 * 
 * @param data 数据
 * @param len 数据长度
 * 
 * @return short 实际写入的数据长度
 */
short userShellWrite(char *data, unsigned short len)
{
    HAL_UART_Transmit(&huart2, (uint8_t *)data, len, 0x1FF);
    return len;
}


/**
 * @brief 用户shell读
 * 
 * @param data 数据
 * @param len 数据长度
 * 
 * @return short 实际读取到
 */
short userShellRead(char *data, unsigned short len)
{
    //return HAL_UART_Receive(&hlpuart1, (uint8_t *)data, len, 0);
	  if(HAL_UART_Receive(&huart2, (uint8_t *)data, 1, 0xFFFF) != HAL_OK)
    {
        return 0;
    }
    else
    {

			return 1;
    }
}

/**
 * @brief 用户shell上锁
 * 
 * @param shell shell
 * 
 * @return int 0
 */
int userShellLock(Shell *shell)
{
   // xSemaphoreTakeRecursive(shellMutex, portMAX_DELAY);
    return 0;
}

/**
 * @brief 用户shell解锁
 * 
 * @param shell shell
 * 
 * @return int 0
 */
int userShellUnlock(Shell *shell)
{
   // xSemaphoreGiveRecursive(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);
//    if (xTaskCreate(shellTask, "shell", 256, &shell, 5, NULL) != pdPASS)
//    {
//        logError("shell task creat failed");
//    }
}
//CEVENT_EXPORT(EVENT_INIT_STAGE2, userShellInit);

编写串口回调函数,这里我放在main.c.

/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    
    if(huart ->Instance == USART2)
    {
		
       
			  shellHandler(&shell, recv_buf);
			  HAL_UART_Receive_IT(&huart2, (uint8_t*)&recv_buf, 1);
    }
}
/* USER CODE END 4 */

Letter shell 函数调用,由于使用了操作系统只需要初始化,在shell_cfg.h中已经配置好了。

 /* USER CODE BEGIN 2 */

	userShellInit();
	HAL_UART_Receive_IT(&huart2, (uint8_t*)&recv_buf, 1);
  /* USER CODE END 2 */

5.🆗大功告成,MobaXtermh展示结果

在这里插入图片描述

6.总结

提示:

  1. 打开串口中断,确定能进入回调函数。
  2. 注意shell_cfg.h文件里的配置
  3. 最好选择USART

网站公告

今日签到

点亮在社区的每一天
去签到