RT-Thread Nano实战2-msh配置与运行

RT-Thread Nano实战2-msh配置与运行

相关代码已上传到个人github仓库https://github.com/flyingcys/RT-Thread-Nano-GD32F150

之前已经完成GD32F150上RT-Thread Nano的内核运行,为了在产品中方便调试除错,RT-Thread的shell是非常实用且必不可少的一个功能的。其实RT-Thread Nano的keil pack也是可以支持shell中的msh功能的,只需要完成一些配置及串口驱动编写等工作就可以正常使用msh。
同时RT-Thread官方也在STM32L0及LPC824这2个芯片上提供了“bink”和“msh”示例来演示Nano的基本使用和msh的使用。这次先学习example示例工程安装、学习,而后完成GD32F150上Nano的msh功能开发。

1. 示例安装

  1. 打开keil5主界面上的“Pack Installer”按钮,进入Pack安装界面。

RT-Thread Nano实战2-msh配置与运行_第1张图片
2. 在“Devices”栏中的“Search”中输入“STM32L0”或“LPC824”,在右侧“Examples”中可以找到“bink”和“msh”示例,如未发现,请点击“Packs”->“Check For Updates”.

STM32L0 example

RT-Thread Nano实战2-msh配置与运行_第2张图片

LPC824 example

RT-Thread Nano实战2-msh配置与运行_第3张图片
点击“copy”按钮即可安装。这次我们选择的是STM32L0的“rtthread msh example”。
RT-Thread Nano实战2-msh配置与运行_第4张图片
如按钮为灰色“Install”,请先右键点击“rtthread msh example”并选择“cancel actions”即可点击“Install”进行安装。
下载的example已完成全部配置可正常编译运行。example工程含有msh功能必需的串口驱动“uart.c”和“uart.h”,在后面将按照这个uart驱动模版来完成自己芯片的串口驱动。

2. msh功能配置与运行

2.1 加载msh相关文件

要使用msh,除了上次使用的kernel外,还必须加载Pack中的shell和device drivers。
RT-Thread Nano实战2-msh配置与运行_第5张图片
选中全部3个功能后,可以在Project栏中看到已加载shell及device drivers相关文件。
RT-Thread Nano实战2-msh配置与运行_第6张图片

2.2 keil工程配置

在keil中要正确使用RT-Thread的shell功能,必须在keil的“Options”->“Linker”页面下的“Misc controls”栏中加入--keep *.o(.rti_fn.*) --keep *.o(FSymTab)
RT-Thread Nano实战2-msh配置与运行_第7张图片

2.3 串口驱动编写

msh功能必须依赖串口,串口驱动编写可参考example中的uart.c和uart.h模板来完成。uart主要用到了RT-Thread的device驱动组件和ringbuffer组件。和RT-Thread标准版bsp下的serial驱动有一些区别,具体可参照第5部分.相关阅读

2.3.1 串口初始化函数:

RT-Thread常使用rt_hw_usart_init()函数,也可自定义函数名。同时为了让Nano msh能正确使用,必须使用INIT_BOARD_EXPORT(rt_hw_usart_init);来完成串口驱动初始化。

int rt_hw_usart_init(void)
{
    struct gd32_uart *uart;

#ifdef RT_USING_UART1
    uart = &uart1_device;

    uart->parent.type = RT_Device_Class_Char;
    uart->uart_base = USART1;
    uart->uart_irq = USART1_IRQn;

    rt_ringbuffer_init(&uart->rx_rb, uart->rx_buffer, sizeof(uart->rx_buffer));

    uart->parent.init = rt_uart_init;
    uart->parent.open = rt_uart_open;
    uart->parent.close = rt_uart_close;
    uart->parent.read = rt_uart_read;
    uart->parent.write = rt_uart_write;
    uart->parent.control = RT_NULL;
    uart->parent.user_data = RT_NULL;

    rt_device_register(&uart->parent, "uart1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
#endif

    return 0;
}
INIT_BOARD_EXPORT(rt_hw_usart_init);

在该函数内用到了自定义gd32_uart的结构体指针变量, 该结构体变量内包含rt_device设备控制块、环形队列、gd32串口设备号、中断号、串口接收buffer等。

#define UART_RX_BUFSZ 8

struct gd32_uart
{
    struct rt_device parent;
    struct rt_ringbuffer rx_rb;

    USART_TypeDef* uart_base;
    IRQn_Type uart_irq;

    rt_uint8_t rx_buffer[UART_RX_BUFSZ];
};
2.3.2 GD32F150串口驱动:

串口驱动需完成init/open/close/read/write函数,其中:
1. init函数内完成GPIO配置、USART使能、NVIC中断使能等工作。
2. 在open/close函数内主要是对NVIC中断进行了开/关操作,如不需要对中断操作,这2个函数可不实现。
3. 在write函数内实现串口数据发送操作。
4. 在read函数内实现串口ringbuffer数据读取。

具体代码实现可参照example

2.3.3 串口中断处理:

中断处理依然使用的是GD32的中断处理函数,在中断处理函数中完成ringbuffer的串口数据写入。同时需要在中断处理函数中插入rt_interrupt_enter();/rt_interrupt_leave();通知RT-Thread内核当前处于中断模式。

static gd32_uart_recv_handler(struct gd32_uart *uart)
{
    if(USART_GetIntBitState(uart->uart_base, USART_INT_RBNE) != RESET)
    {
        rt_ringbuffer_putchar_force(&(uart->rx_rb), (rt_uint8_t)USART_DataReceive(uart->uart_base));
        if(uart->parent.rx_indicate != RT_NULL)
        {
            uart->parent.rx_indicate(&uart->parent, rt_ringbuffer_data_len(&uart->rx_rb));
        }
    }
}

void USART1_IRQHandler(void)
{
    rt_interrupt_enter();

    gd32_uart_recv_handler(&uart1_device);

    rt_interrupt_leave();
}

2.3.4 串口宏定义修改:

由于我使用的是GD32F150的usart1作为msh串口,还需要将rtconfig.h文件第186行的#define RT_USING_UART2修改为#define RT_USING_UART1
RT-Thread Nano实战2-msh配置与运行_第8张图片

同时将rtconfig.h文件第148行的#define RT_CONSOLE_DEVICE_NAME "uart2"修改为#define RT_CONSOLE_DEVICE_NAME "uart1"
RT-Thread Nano实战2-msh配置与运行_第9张图片

正确完成以上配置后,msh就可以正常运行了。
RT-Thread Nano实战2-msh配置与运行_第10张图片

3. msh使用

msh命令与linux下bash类似,在msh命令行下输入help命令可获取当前已支持的全部msh命令行
RT-Thread Nano实战2-msh配置与运行_第11张图片
同时我们如需将自己编写的函数导出到msh命令行,只需要加入MSH_CMD_EXPORT
如RT-Thread内置的version指令

#include "finsh.h"
int hello_world(void)
{
    rt_kprintf("%s\n", "hello world!");

    return 0;
}
MSH_CMD_EXPORT(hello_world, printf hello world);

RT-Thread Nano实战2-msh配置与运行_第12张图片

4. Nano资源占用对比

只使用Nano Kernel的资源占用:FLASH:6.08K,RAM:1.305K

RT-Thread Nano实战2-msh配置与运行_第13张图片

增加msh功能后的资源占用:FLASH:14.48K,RAM:2.375K

RT-Thread Nano实战2-msh配置与运行_第14张图片

通过对比可以发现,RT-Thread Nano添加了UART及msh功能后,资源占用依然比较小的,FLASH增大了8.4K,RAM只增大了1.07K。

5.相关阅读

  1. RT-Thread编程手册第6章:I/O设备管理
    https://www.rt-thread.org/document/site/zh/1chapters/06-chapter_device/
  2. GD32F150实战RT-Thread Nano:
    http://blog.csdn.net/flyingcys/article/details/78923352
  3. RT thread 设备驱动组件之USART设备:
    http://www.cnblogs.com/King-Gentleman/p/4653011.html
  4. 剥洋葱:从RT-Thread的串口到内核对象:
    https://mp.weixin.qq.com/s/Nd5QRBcYyarjx38wme7Z7Q

你可能感兴趣的:(RT-Thread)