打印
[MM32软件]

MM32F3273G8P火龙果开发板MindSDK开发教程20 - letter shell 的移植

[复制链接]
153|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
1、Letter Shell
犹如linux下的命令行,或者更像是uboot下的命令行,可以输入命令,执行相对应的函数。

2、Letter Shell移植(GCC 环境)
解压后,将相关文件拷贝到我们的工程,并新建shell_port.c shell_prot.h文件,整体代码视图如下:



shell_prot.c里面主要完成一个write函数,read函数我们不在这里定义,我们在串口收数据的中断里,调用
shellHandler函数。所以在串口的初始化中,要使能串口的收中断。

a、串口初始化函数
static void BOARD_InitUartPins(void)
{
    /* Pb6 - UART1_TX. */
    GPIO_Init_Type gpio_init;
    gpio_init.Pins  = CONSOLE_TX_GPIO_PIN;
    gpio_init.PinMode  = GPIO_PinMode_AF_PushPull;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(CONSOLE_GPIO_PORT, &gpio_init);
    GPIO_PinAFConf(CONSOLE_GPIO_PORT, gpio_init.Pins, GPIO_AF_7);

    /* Pb7 - UART1_RX. */
    gpio_init.Pins  = CONSOLE_RX_GPIO_PIN;
    gpio_init.PinMode  = GPIO_PinMode_In_Floating;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(CONSOLE_GPIO_PORT, &gpio_init);
    GPIO_PinAFConf(CONSOLE_GPIO_PORT, gpio_init.Pins, GPIO_AF_7);
}

void BOARD_InitDebugConsole(void)
{
    UART_Init_Type uart_init;
        BOARD_InitUartPins();

    uart_init.ClockFreqHz   = CLOCK_APB2_FREQ;
    uart_init.BaudRate      = 115200U;
    uart_init.WordLength    = UART_WordLength_8b;
    uart_init.StopBits      = UART_StopBits_1;
    uart_init.Parity        = UART_Parity_None;
    uart_init.XferMode      = UART_XferMode_RxTx;
    uart_init.HwFlowControl = UART_HwFlowControl_None;
    uart_init.XferSignal    = UART_XferSignal_Normal;
    uart_init.EnableSwapTxRxXferSignal = false;
    UART_Init(BOARD_DEBUG_UART_PORT, &uart_init);

        /* Enable RX interrupt. */
    UART_EnableInterrupts(BOARD_DEBUG_UART_PORT, UART_INT_RX_DONE, true);
    NVIC_EnableIRQ(UART1_IRQn);

    UART_Enable(BOARD_DEBUG_UART_PORT, true);
}



b、中断处理函数
uint8_t recv_buf = 0;

void app_uart_rx_isr_hook(void)
{
    if (   (0u != (UART_INT_RX_DONE & UART_GetEnabledInterrupts(BOARD_DEBUG_UART_PORT)))
        && (0u != (UART_INT_RX_DONE & UART_GetInterruptStatus(BOARD_DEBUG_UART_PORT))) )
    {
        recv_buf = UART_GetData(BOARD_DEBUG_UART_PORT); /* read data to clear rx interrupt bits. */

        //调用shell处理数据的接口
                shellHandler(&shell, recv_buf);
    }
}

/* BOARD_DEBUG_UART_IRQHandler ISR entry. */
void UART1_IRQHandler(void)
{
    app_uart_rx_isr_hook();
}



c、shell_port.c中完善写函数
#include "shell_port.h"

#include "shell.h"
#include "hal_uart.h"
#include "shell_port.h"

Shell shell;
char shell_buffer[512];

short userShellWrite(char *data, unsigned short len)
{
    uint32_t i;
        for (i = 0; i < len; i++)
        {
            while ( 0u == (UART_STATUS_TX_EMPTY & UART_GetStatus(UART1)) )
        {}
        UART_PutData(UART1, (uint8_t)(data));
        }
    return len;
}

void User_Shell_Init(void)
{
    shell.write = userShellWrite;
    shellInit(&shell, shell_buffer, 512);
}




其中write定义 signed short (*write)(char *, unsigned short);
shell_cfg.h内容如下:

/**
* @file shell_cfg.h
* @author Letter (nevermindzzt@gmail.com)
* @brief shell config
* @version 3.0.0
* @date 2019-12-31
*
* @CopyRight (c) 2019 Letter
*
*/

#ifndef __SHELL_CFG_H__
#define __SHELL_CFG_H__


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

/**
* @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      0

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

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

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

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

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

/**
* @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     0//200

/**
* @brief 快速帮助
*        作用于双击tab的场景,当使能此宏时,双击tab不会对命令进行help补全,而是直接显示对应命令的帮助信息
*/
#define     SHELL_QUICK_HELP            0//1

/**
* @brief 保存命令返回值
*        开启后会默认定义一个`RETVAL`变量,会保存上一次命令执行的返回值,可以在随后的命令中进行调用
*        如果命令的`SHELL_CMD_DISABLE_RETURN`标志被设置,则该命令不会更新`RETVAL`
*/
#define     SHELL_KEEP_RETURN_VALUE     0

/**
* @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          0

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

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

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

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

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

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

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

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

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

#endif



其中 #define SHELL_USING_CMD_EXPORT 1时编译报错,要修改Ld文件如下:



shell_port.h内容如下:

#ifndef __SHELL_PORT_H__
#define __SHELL_PORT_H__
#include "shell.h"

extern Shell shell;
void User_Shell_Init(void);
#endif



3、调用以及现象
在main函数中调用代码如下:

#include <stdint.h>
#include <stdio.h>
#include "clock_init.h"
#include "hal_rcc.h"
#include "hal_gpio.h"
#include "hal_uart.h"
#include "led.h"
#include "uart.h"
#include "systick.h"
#include "key.h"
#include "timer.h"
#include "multi_button.h"
#include "shell_port.h"

struct Button btn1;

void BTN1_PRESS_DOWN_Handler(void* btn)
{
        //do something...
        printf("BTN1_PRESS_DOWN_Handler \r\n");
}

void BTN1_PRESS_UP_Handler(void* btn)
{
        //do something...
        printf("BTN1_PRESS_UP_Handler \r\n");
}

int test(int i)
{
    printf("input int: %d \r\n", i);

    return 0;
}

SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC), test, test, test);

int main(void)
{
        BOARD_InitBootClocks();  // ³õʼ»¯Ê±ÖÓ
        BOARD_InitDebugConsole();
        BOARD_UserKeyInit();
        LED_Init();
        BOARD_TIM6_Init();

        // for mutilbutton init
        button_init(&btn1, read_button_GPIO, 0, btn1_id);
        button_attach(&btn1, PRESS_DOWN,       BTN1_PRESS_DOWN_Handler);
        button_attach(&btn1, PRESS_UP,         BTN1_PRESS_UP_Handler);
        button_start(&btn1);

        BOARD_TIM7_Init();

        BOARD_Delay1Ms(1000);
        User_Shell_Init();
        while(1)
        {

        }       
}


我们添加了一个test命令,如下:



现象:



4、代码
代码下载
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/weixin_43932857/article/details/131215533

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

20

主题

60

帖子

0

粉丝