串口驱动及shell终端的移植
基于demo测试的基础,我们已经完成了基本工程建立,同时包含GPIO小灯闪烁的驱动,本测试为完成串口驱动,及基于串口的shell终端的移植。
基本硬件
为了方便起见,串口就采用程序更新的USB转串口位置。根据硬件原理图可以知道,该串口连接到了控制器的P110和P109。
软件实现
1 通过FSP配置串口
配置System:DEBUG,将Operation Mode 调整为 SWD。
配置 Connectivity:SCI 的 SCI9,调整Pin Group Selection为Mixed,Operation Mode为Asynchronous UART,并检查TXD9为P109,RXD9为P110。
切换到Stacks选项页,选择New Stack->Connectivity->UART(r_sci_uart),添加一个串口g_uart0
UART(r_sci_uart)。
点击新增的串口控件,编辑Properties,如下标所示。
2 Shell终端软件移植
letter-shell,一个功能强大的嵌入式shell ,是一个开源项目。letter
shell 3.0是一个C语言编写的,可以嵌入在程序中的嵌入式shell,通俗一点说就是一个串口终端,可以通过命令行调用、运行程序中的函数。支持的功能有:
- 命令自动补全
- 快捷键功能定义
- 命令权限管理
- 用户管理
- 变量支持
移植比较简单,主要分为三个步骤,一个是shell功能的配置,一个是shell_port的移植,一个是基于FreeRTOS的shellTask任务创建。
请大家自己下载letter shell的源码,我这里下载时3.0的源码。下载后,将目录中的src复制到工程中,然后在demo目录下stm32-freertos复制到工程中,并将目录修改为shell_port。
1) Shell配置
Shell_cfg.h文件中包含shell执行的特性,具体的配置加下面的说明。
2) Shell_port移植
Shell_port的移植时一个难点,为了兼容freertos操作系统,采用队列的方式传递所接收到的串口数据。
增加freertos队列,在Stacks选下卡中,增加一个Objects队列对象,队列配置为Item
Size 为1,Queue Length 为 100 ,如下图所示。
增加串口回调函数和接收及发送处理。
void user_uart_callback(uart_callback_args_t * p_args){
if (p_args->event == *UART_EVENT_TX_COMPLETE* )
{
uart_send_complete_flag = true;
}
if (p_args->event == *UART_EVENT_RX_CHAR* )
{
char RxBuff = (char )(p_args->data); xQueueSendFromISR(g_uart0rx_queue0,&RxBuff, pdTRUE );
}
}
串口数据发送处理函数
void userShellWrite(char data)
{
fsp_err_t err = FSP_SUCCESS;
err = R_SCI_UART_Write(&g_uart0_ctrl, (unsigned char *)&data, 1);
if(FSP_SUCCESS != err) __BKPT();
while(uart_send_complete_flag == false){}
uart_send_complete_flag = false;
}
串口数据接收处理函数,函数中读取队列存储的串口输入数据,并反馈给shell任务。
signed char userShellRead(char *data)
{
BaseType_t xStatus;
xStatus = xQueueReceive( g_uart0rx_queue0, data, portMAX_DELAY );
if( xStatus == pdPASS )
{
return 0;
}
else
{
return -1;
}
}
3) ShellTask任务创建
创建一个任务,完成shellTask信息的处理过程,如下图所示,在Stacks中,创建一个shellt任务,完成shellTask()的调用。
在创建的shellt_entry函数中,去掉原有的代码,增加shell处理和串口初始化代码。
void shellt_entry (void *pvParameters)
{
FSP_PARAMETER_NOT_USED (pvParameters);
fsp_err_t err = *FSP_SUCCESS* ;
err = R_SCI_UART_Open(&g_uart0_ctrl, &g_uart0_cfg);
assert(*FSP_SUCCESS* == err);
userShellInit();
shellTask(&shell);
}
实测运行
我创建一个简单的shell命令,观察一下执行效果。
int hello_test (int argc, char *argv[])
{
if (argc <= 2)
{
shellPrint(&shell, "please input string same as
hello 1 2 3\n\r");
return -1;
}
shellPrint(&shell,"hello %s,%s,%s:\r\n",argv[1],argv[2],argv[3]);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE( *SHELL_TYPE_CMD_MAIN* ), hello_test, hello_test,
hello_test);
启动后,打印了Letter shell 图案,命令提示中,也出现了我们新增的hello_test命令,执行后结果负荷我们的设计,letter shell成功移植完成。