瑞萨单片机william hill官网
直播中

jyaxz

11年用户 428经验值
擅长:嵌入式技术
私信 关注
[经验]

【瑞萨RA4系列开发板体验】+串口驱动及shell终端的移植

串口驱动及shell终端的移植

基于demo测试的基础,我们已经完成了基本工程建立,同时包含GPIO小灯闪烁的驱动,本测试为完成串口驱动,及基于串口的shell终端的移植。

基本硬件

为了方便起见,串口就采用程序更新的USB转串口位置。根据硬件原理图可以知道,该串口连接到了控制器的P110和P109。
image.png

软件实现

1 通过FSP配置串口

配置System:DEBUG,将Operation Mode 调整为 SWD。
image.png

配置 Connectivity:SCI 的 SCI9,调整Pin Group Selection为Mixed,Operation Mode为Asynchronous UART,并检查TXD9为P109,RXD9为P110。
image.png

切换到Stacks选项页,选择New Stack->Connectivity->UART(r_sci_uart),添加一个串口g_uart0
UART(r_sci_uart)。
image.png

点击新增的串口控件,编辑Properties,如下标所示。
image.png

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执行的特性,具体的配置加下面的说明。

/**
*  @brief 是否使用默认shell任务while循环,使能宏`SHELL_USING_TASK`后此宏有意义
 * 
使能此宏,则`shellTask()`函数会一直循环读取输入,一般使用操作系统建立shell
 *   任务时使能此宏,关闭此宏的情况下,一般适用于无操作系统,在主循环中调用`shellTask()`
 */
#define  SHELL_TASK_WHILE            1
/**
 *
@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      1
/** *
@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  1
/**
 *
@brief 使用LF作为命令行回车触发
 *       
可以和SHELL_ENTER_CR同时开启
 */
#define    SHELL_ENTER_LF              0
/**
 *
@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命令参数最大数量
 *       
包含命令名在内,超过8个参数并且使用了参数自动转换的情况下,需要修改源码
 */
#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     200
/**
 *
@brief 管理的最大shell数量
 */
#define    SHELL_MAX_NUMBER            1
/** *
@brief shell格式化输出的缓冲大小
 *       
为0时不使用shell格式化输出
 */
#define    SHELL_PRINT_BUFFER          128
/**
 *
@brief 获取系统时间(ms)
 *       
定义此宏为获取系统Tick,如`HAL_GetTick()` *
@note 此宏不定义时无法使用双击tab补全命令help,无法使用shell超时锁定
 */
#define    SHELL_GET_TICK()           xTaskGetTickCount()
/**
 *
@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         "jy"

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

2) Shell_port移植

Shell_port的移植时一个难点,为了兼容freertos操作系统,采用队列的方式传递所接收到的串口数据。

增加freertos队列,在Stacks选下卡中,增加一个Objects队列对象,队列配置为Item
Size 为1,Queue Length 为 100 ,如下图所示。

image.png
增加串口回调函数和接收及发送处理。

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 );
    }
}

串口数据发送处理函数

/**
 *[url=home.php?mod=space&uid=2666770]@Brief[/url] 用户shell写
 * 
 * [url=home.php?mod=space&uid=3142012]@param[/url] data 数据
 */
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任务。

/* @brief 用户shell读
 * 
 *@param data 数据
 *[url=home.php?mod=space&uid=1141835]@Return[/url] char 状态
 */
signed char userShellRead(char *data)
{   
BaseType_t xStatus;   
/* 读队列
 *  xQueue: 读哪个队列    
*  &lReceivedValue: 读到的数据复制到这个地址
 *  xTicksToWait: 如果队列为空, 阻塞一会    
*/   
xStatus = xQueueReceive( g_uart0rx_queue0, data, portMAX_DELAY );
   
   if( xStatus == pdPASS )
   {
        /* 读到了数据 */      
       return 0;
    }   
   else
   {       
       /* 没读到数据 */       
       return -1;
    }
}

3) ShellTask任务创建

创建一个任务,完成shellTask信息的处理过程,如下图所示,在Stacks中,创建一个shellt任务,完成shellTask()的调用。
image.png
在创建的shellt_entry函数中,去掉原有的代码,增加shell处理和串口初始化代码。

/*pvParameters contains TaskHandle_t */
void  shellt_entry (void *pvParameters)
{
    FSP_PARAMETER_NOT_USED (pvParameters);
    /*  **TODO** : add your own code here */
    fsp_err_t err =  *FSP_SUCCESS* ;
    /* Open the transfer instance with initial configuration.*/
    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);

image.png
启动后,打印了Letter shell 图案,命令提示中,也出现了我们新增的hello_test命令,执行后结果负荷我们的设计,letter shell成功移植完成。

更多回帖

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