灵动微电子 MM32
直播中

zhu

8年用户 1640经验值
擅长:控制/MCU
私信 关注
[原创]

灵动微课堂 (第137讲) | 基于MM32 MCU的OS移植与应用——RT-Thread Shell使用

01
FinSH简介
FinSH是RT-Thread的命令行组件(shell),FinSH完全采用ANSI C编写,具有极好的移植性;内存占用少,支持权限验证、自动补全、查看历史命令等功能。

FinSH支持两种输入模式,分别是传统命令行模式和C语言解释器模式,这两个模式可以相互切换。传统模式又称为msh模式,在传统模式下输入exit后回车,即可切换到C语言解释器模式;在C语言解释器模式下输入msh()后回车即可切换到传统模式。

使用Shell,特别是在开发调试阶段,极大的方便了开发者快速调试功能、定位问题、调用测试函数、修改测试参数、减少代码反复烧录次数等操作,从而缩短项目开发周期,是开发过程中不可或缺的调试工具。

02
FinSH执行流程
FinSH给用户提供了一套基于命令行调用的操作接口,用户在控制终端输入命令,控制终端通过串口、USB、网络等形式将命令传给设备里的FinSH,FinSH会读取设备输入命令,解析并自动扫描内部函数表,寻找对应函数名,执行函数后输出回应,回应通过原路返回,将结果显示在控制终端上。

当使用串口连接设备与控制终端时,FinSH命令的执行流程如下图所示:
1.jpg
图 1 FinSH命令执行流程

03
FinSH移植
我们使用串口作为接控制台的交互接口,将FinSH的移植分为两个部分:第一部分是添加UART控制台功能;第二部分是实现FinSH组件的移植,实现对控制台输入命令的解析和执行。

添加UART控制台
UART的初始化配置和接收中断处理:struct rt_semaphore shell_rx_sem;

static int UART2_Configure(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    UART_InitTypeDef UART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    /* initialize a semaphore for shell */
    rt_sem_init(&shell_rx_sem, "shell_rx", 0, RT_IPC_FLAG_FIFO);

    /* Enable GPIO and SYSCFG clock */
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,    ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

    /* Enable UART2 clock */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART2, ENABLE);

    /* UART Configuration ad follow */
    UART_StructInit(&UART_InitStructure);
    UART_InitStructure.UART_BaudRate            = 115200;
    UART_InitStructure.UART_WordLength          = UART_WordLength_8b;
    UART_InitStructure.UART_StopBits            = UART_StopBits_1;
    UART_InitStructure.UART_Parity              = UART_Parity_No;
    UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;
    UART_InitStructure.UART_Mode                = UART_Mode_Rx | UART_Mode_Tx;
    UART_Init(UART2, &UART_InitStructure);

    /* Enable UART2 Rx Interrupt */
    UART_ITConfig(UART2, UART_IT_RXIEN, ENABLE);

    /* Enable UART */
    UART_Cmd(UART2, ENABLE);

    /* Enable PA2 & PA3 alternate function */
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_1);

    /* Configure UART Tx as alternate function push-pull */
    GPIO_StructInit(&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

     /* Configure UART Rx as input floating */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Config UART2 Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = UART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority  = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd  = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    return 0;
}
INIT_BOARD_EXPORT(UART2_Configure);

void UART2_IRQHandler(void)
{
    if(UART_GetITStatus(UART2, UART_IT_RXIEN) != RESET)
    {
        /* Clear UART2 Rx Interrupt Flag */
        UART_ClearITPendingBit(UART2, UART_IT_RXIEN);

        /* semaphore release */
        rt_sem_release(&shell_rx_sem);
    }
}

实现rt_hw_console_output函数:让FinSH组件输出一个字符,即在该函数中实现UART字符输出: void rt_hw_console_output(const char *str)
{
    while(*str)
    {
        if(*str == 'n')
        {
            /* Send a character to the UART */
            UART_SendData(UART2, 'r');

        /* Loop until the end of transmission */
            while(!UART_GetFlagStatus(UART2, UART_FLAG_TXEPT));
        }

        /* Send a character to the UART */
        UART_SendData(UART2, *str++);

    /* Loop until the end of transmission */
        while(!UART_GetFlagStatus(UART2, UART_FLAG_TXEPT));
    }
}

添加FinSH组件
将FinSH组件的源代码复制到目标工程目录下:
2.jpg
图 2 工程目录
将FinSH添加到软件工程中,使能RT_USING_FINSH宏定义,如下图以MDK-ARM为例:
3.jpg
图 3 使能RT_USING_FINSH宏定义
实现rt_hw_console_getchar函数:控制台获取一个字符,即在该函数中实现UART字符获取:char rt_hw_console_getchar(void)
{
    rt_sem_take(&shell_rx_sem, RT_WAITING_FOREVER);

    /* Receive UART2 Data */
    return UART_ReceiveData(UART2);
}
04
结果验证
编译软件工程,无误后下载代码;在串口终端工具中输入TAB按键或者help命令可以查看当前系统支持的命令信息:
4.jpg 图 4 操作结果窗口

更多回帖

发帖
×
20
完善资料,
赚取积分