Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread Studio
RT-Thread活动
瑞萨_RA6M4
基于RT-Thread+RA6M4的虚拟仪器开发:第六章SHELL介绍
发布于 2022-07-21 10:31:06 浏览:568
订阅该版
[TOC] # 前言 除了仿真器很多时候我们需要使用串口进行命令行的输入输出调试。RT-Thread自带FINSH组件,实现该需求,这里简单介绍下RT-Thread的Finsh # 关键代码介绍 ## 串口初始化注册流程 Reset_Handler->entry->rtthread_startup->rt_hw_board_init->rt_hw_usart_init(rtconfig.h中定义RT_USING_SERIAL)->rt_hw_serial_register 设置如下回调函数 device->init = rt_serial_init; device->open = rt_serial_open; device->close = rt_serial_close; device->read = RT_NULL; device->write = RT_NULL; device->control = rt_serial_control; ## 终端串口初始化 Reset_Handler->entry->rtthread_startup->rt_hw_board_init->rt_console_set_device(RT_CONSOLE_DEVICE_NAME);其中rtconfig.h中定义#define RT_CONSOLE_DEVICE_NAME "uart7"->rt_device_open 全局变量_console_device为新打开的串口设备。 使用仿真器跟踪可知,最终调用R_SCI_UART_Open进行了串口的配置 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20220721/2c3a97657699e95c409aa36121cb08aa.png.webp) 串口的配置如下,定义的const的g_uart7_cfg结构体,该结构体定义了串口的波特率,中断号等参数,R_SCI_UART_Open根据该参数结构体进行初始化。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20220721/57d50d021c31e0a59b8381ae729ae11c.png.webp) 从上看出,如果需要使用串口的接收中断需要定义中断号,VETCTOR_NUMBER_SCI7_RXI,默认是没有定义的所以串口没有输入,也就是FINSH只能输出不能输入。 而SCI_RXI_IRQn则是和vector_data.c中 g_vector_table的数组下标定义的, [0]= sci_uart_rxi_isr, /* SCI7 RXI (Received data full) */ 所以 SCI7_RXI_IRQn = 0, VECTOR_NUMBER_SCI7_RXI为SCI7_RXI_IRQn ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20220721/8ef0db132d4fdf3e3a728aca9c73265c.png.webp) ## 串口接收 配置接收回调函数_serial_fifo_rx 路径如下 rt_serial_rx_enablle最终配置 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20220721/67c340e0990ee8ff1c0c6bf941fb4d97.png.webp) 串口接收流程 中断->上面配置的回调函数 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20220721/b0803b8a9f06392acc7a4815f19bc8b8.png.webp) ## 终端串口写 配置发送回调函数_serial_poll_tx ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20220721/b7835fc91171307f15fe939805539f65.png.webp) 所以整体路径如下 rt_kprintf->rt_device_write(_console_device, 0, rt_log_buf, length);->_serial_poll_tx->serial->ops->putc(serial, *putc_buffer); ->ra_uart_putc 其中rt_serial_open->rt_serial_tx_enable中 设置dev->write = _serial_poll_tx; 正是调用了上面配置的回调函数_serial_poll_tx static const struct rt_uart_ops ra_uart_ops = { .configure = ra_uart_configure, .control = ra_uart_control, .putc = ra_uart_putc, .getc = ra_uart_getc, }; 而_serial_poll_tx调用serial->ops->putc 串口发送调用的正是伤处结构体的ra_uart_putc 因为rt_hw_usart_init中 uart_obj[i].serial.ops = &ra_uart_ops;进行了配置。 仿真器跟踪执行路径如下: ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20220721/caadd66f2da82cb9537cf396a20ad1ff.png.webp) ## 终端串口读 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20220721/1d9f8b0ee4c79a361b8dc657881b48df.png.webp) INIT_APP_EXPORT(finsh_system_init);指定函数放在.rti_fn.6段 const init_fn_t __rt_init_finsh_system_init __attribute__((used)) __attribute__((section(.rti_fn.6))) rtthread_startup->rt_application_init->main_thread_entry->rt_components_init-> for (fn_ptr = &__rt_init_rti_board_end; fn_ptr < &__rt_init_rti_end; fn_ptr ++) { (*fn_ptr)(); } INIT_EXPORT(rti_board_end, "1.end") INIT_EXPORT(rti_end, "6.end"); 调用.rti_fn.1~.rti_fn.6之间函数。 即调用finsh_system_init创建任务finsh_thread_entry循环执行 该线程循环执行 finsh_getchar->rt_device_read->msh_exec->_msh_exec_cmd msh_get_cmd-> 查询_syscall_table_begin~_syscall_table_end之间CMD命令执行回调函数 finsh_system_init-> finsh_system_function_init(&__fsymtab_start, &__fsymtab_end); 上设置syscall_table_begin~_syscall_table_end 链接脚本中 . = ALIGN(4); __fsymtab_start = .; KEEP(*(FSymTab)) __fsymtab_end = .; MSH_CMD_EXPORT 正是将命令结构体存入FSymTab段 ``` #define MSH_FUNCTION_EXPORT_CMD(name, cmd, desc) \ const char __fsym_##cmd##_name[] RT_SECTION(".rodata.name") = #cmd; \ const char __fsym_##cmd##_desc[] RT_SECTION(".rodata.name") = #desc; \ RT_USED const struct finsh_syscall __fsym_##cmd RT_SECTION("FSymTab")= \ { \ __fsym_##cmd##_name, \ __fsym_##cmd##_desc, \ (syscall_func)&name \ }; ``` 其中rt_device_read就是等信号量rt_sem_take(&shell->rx_sem, RT_WAITING_FOREVER);有信号量就读串口缓冲区数据 调用过程如下 而串口中断收到数据则发送信号量写入串口缓冲区,FINSH任务读该缓冲区和信号量 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20220721/9a6aa8210f5b913c539cf376c44163ce.png.webp) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20220721/ed1ff95ebc7a1bc8b08aa926f357cc15.png.webp) 串口接收中断服务函数sci_uart_rxi_isr-> r_sci_uart_call_callback中调用p_ctrl->p_callback(p_args); 由于g_uart7_cfg中指定了.p_callback = user_uart7_callback, 所以实际是调用user_uart7_callback 将数据写入缓冲区rt_ringbuffer_putchar 并调用rt_hw_serial_isr中调用 serial->parent.rx_indicate(&(serial->parent), rx_length); 由于之前finsh_set_device配置了rt_device_set_rx_indicate,为finsh_rx_ind 则这里就是调用finsh_rx_ind就是进行信号量释放rt_sem_release(&shell->rx_sem); ## 串口驱动接口 补充下串口设备驱动的函数执行流 rtthread_startup->rt_hw_board_init->rt_hw_usart_init->rt_hw_serial_register->rt_device_register rt_device_find根据设备名找到设备 rt_serial_open打开设备 调用 device->init最终调用rt_serial_init device->open最终调用rt_serial_open rt_serial_tx_enable设置发送回调函数dev->write = _serial_poll_tx;根据tx_oflag或其他 rt_serial_rx_enable设置接收回调函数 dev->read = _serial_poll_rx;根据tx_oflag或其他 rt_serial_close关闭设备 调用device->close最终调用rt_serial_close; 读写 rt_device_write rt_device_read # 添加自定义命令 任意c文件中 需要包含finsh.h 包含#include
间接包含了finsh.h ``` static long cmd_test(void) { rt_kprintf("cmd_test\n"); return 0; } MSH_CMD_EXPORT(cmd_test, test cmd); P613- TXD7 P614- RXD7 ``` 启动会打印log和版本信息 输入回车打印提示信息 输入help打印帮助,有我们新加的指令cmd_test 输入cmd_test执行我们定义的命令处理。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20220721/7b635f264b306e3d5d9400c14d19b397.png.webp) # 总结 FINSH使用了串口驱动,总结下就是一个字绕,两个字很绕,三个字非常绕,四个字就是云里雾里。相信对于初学者拿到这样的代码会完全不知所措,串口有问题时完全无法去分析,我们这里借助仿真器才更方便快捷梳理流程,通过上面的分析也知道了串口有发送没有接收是因为中断号没有配置导致的。 正因为这个驱动太复杂了,所以我们下一章介绍如何从0开始用简洁高效模块化的思路重新设计串口驱动,相信对比之后会有清晰的感受。
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
qinyunti
这家伙很懒,什么也没写!
文章
30
回答
1
被采纳
0
关注TA
发私信
相关文章
1
(苏州站)RT-Thread物联网开发者沙龙【已结束】
2
(成都站)RT-Thread物联网开发者沙龙
3
(深圳站)RT-Thread物联网开发者沙龙
4
(西安站)RT-Thread物联网开发者沙龙
5
成都站2018 RT-Thread开发者沙龙回顾及PPT下载
6
2018 RT-Thread物联网开发者沙龙(北京站)
7
2018 RT-Thread物联网开发者沙龙(南京站)
8
第十三届研电赛RT-Thread企业专项奖发布通知
9
RT-Thread应用作品征集大赛开始啦!
10
你的投票将决定RT-Thread官网应该优先准备的文档是哪些
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
中断
编译报错
Debug
SFUD
rt_mq_消息队列_msg_queue
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
a1012112796
10
个答案
1
次被采纳
踩姑娘的小蘑菇
4
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
Ryan_CW
4
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
YZRD
2
篇文章
5
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部