RT-Thread 组件 FinSH 使用时遇到的问题
一、FinSH 的移植与使用问题
FinSH组件输入无反应的问题
- 现象:当打开 finsh 组件后,控制台会打相应的信息,如下图说是:
\ | /
- RT - Thread Operating System
/ | \ 3.1.5 build Jul 6 2022
2006 - 2020 Copyright by rt-thread team
do components initialization.
initialize rti_board_end:0 done
initialize finsh_system_init:0 done
RT-Thread Start......
msh >
但是输入回车或任意内容时,无反应。当然导致这样的现象有两种可能,一种可能是未正常开启相应的配置,第二种是未对接收字符的函数进行实现,具体看下面内容
- FinSH 组件在 rtconfig.h 中的配置,如下所示:
/* --------------------------------- RT-Thread 内核部分 --------------------------------- */
/* 表示内核对象的名称的最大长度,若代码中对象名称的最大长度大于宏定义的长度,
* 多余的部分将被截掉。*/
#define RT_NAME_MAX 8
/* 字节对齐时设定对齐的字节个数。常使用 ALIGN(RT_ALIGN_SIZE) 进行字节对齐。*/
#define RT_ALIGN_SIZE 4
/* 定义系统线程优先级数;通常用 RT_THREAD_PRIORITY_MAX-1 定义空闲线程的优先级 */
#define RT_THREAD_PRIORITY_MAX 32
/* 定义时钟节拍,为 100 时表示 100 个 tick 每秒,一个 tick 为 10ms */
#define RT_TICK_PER_SECOND 1000
/* 检查栈是否溢出,未定义则关闭 */
#define RT_USING_OVERFLOW_CHECK
/* 定义该宏开启 debug 模式,未定义则关闭 */
#define RT_DEBUG
/* 开启 debug 模式时:该宏定义为 0 时表示关闭打印组件初始化信息,定义为 1 时表示启用 */
#define RT_DEBUG_INIT 1
/* 开启 debug 模式时:该宏定义为 0 时表示关闭打印线程切换信息,定义为 1 时表示启用 */
#define RT_DEBUG_THREAD 0
/* 定义该宏表示开启钩子函数的使用,未定义则关闭 */
//#define RT_USING_HOOK
/* 定义了空闲线程的栈大小 */
#define IDLE_THREAD_STACK_SIZE 1024
FinSH 移植
FinSH 组件使用有三种种方式,如下:
通过 rt_hw_console_getchar() 函数获取控制台数据
FinSH 线程的使用方式主要是通过实现rt_hw_console_getchar()函数,获取控制台输入的数据,具体方式看我之前的笔记,STM32 移植 RT-Thread 标准版的 FinSH 组件 。通过外设驱动中的 数据流(stm32_getc函数) 获取控制台数据
具体实现方式见UART外设的移植,稍后我也会将我移植的过程发出来,有需要的可以看我之后的笔记。通过外设驱动中的 中断方式 获取控制台数据
中断的方式包涵了DMA的方式获取控制台数据。
注意: 第二和第三中方式其实都是通过RT-Thread中的外设驱动获取的,这里我为啥会将 数据流和中断 分开说明,是因为他们之间会引入一个新的问题,具体见之后的流程
二、设备为空问题
现象:msh >(dev != RT_NULL) assertion failed at function:rt_device_read, line number:320
原因:出现这个现象主要是在注册设备的时候导致的,在注册设备的时候才用了数据流的方式回去了数据,如下所示:
/* 配置串口设备 */
result = rt_hw_serial_register(&uart_obj[i].serial, uart_obj[i].config->name,
RT_DEVICE_OFLAG_RDWR
| RT_DEVICE_FLAG_INT_RX
| RT_DEVICE_FLAG_INT_TX
, NULL);相应的配置宏如下所示:
#define RT_DEVICE_FLAG_RDONLY 0x001 /* 只读 */
#define RT_DEVICE_FLAG_WRONLY 0x002 /* 只写 */
#define RT_DEVICE_FLAG_RDWR 0x003 /* 读写 */
#define RT_DEVICE_FLAG_REMOVABLE 0x004 /* 可移除 */
#define RT_DEVICE_FLAG_STANDALONE 0x008 /* 独立 */
#define RT_DEVICE_FLAG_SUSPENDED 0x020 /* 挂起 */
#define RT_DEVICE_FLAG_STREAM 0x040 /* 流模式 */
#define RT_DEVICE_FLAG_INT_RX 0x100 /* 中断接收 */
#define RT_DEVICE_FLAG_DMA_RX 0x200 /* DMA 接收 */
#define RT_DEVICE_FLAG_INT_TX 0x400 /* 中断发送 */
#define RT_DEVICE_FLAG_DMA_TX 0x800 /* DMA 发送 */认真思考的小伙伴就会存在一个疑问,为啥将数据接收注册为 流模式 会导致设备为空了,可以猜测在某处导致了设备丢失,我们仔细找一下代码就会发现在shell.c文件中,通过了中断的方式打开了设备,如下图所示:
现在原因找到了,那么解决方式有两种,如下所示:
解决办法
将注册设备时,改为中断接收的方式注册设备
将shell.c文件中的发开方式改为流模式即可,只需要将 RT_DEVICE_FLAG_INT_RX 屏蔽,如下所示:
void finsh_set_device(const char *device_name)
{
rt_device_t dev = RT_NULL; RT_ASSERT(shell != RT_NULL);
dev = rt_device_find(device_name);
if (dev == RT_NULL)
{
rt_kprintf("finsh: can not find device: %s\n", device_name);
return;
} /* check whether it's a same device */
if (dev == shell->device) return;
/* open this device and set the new device in finsh shell */
if (rt_device_open(dev, RT_DEVICE_OFLAG_RDWR |
// RT_DEVICE_FLAG_INT_RX |
RT_DEVICE_FLAG_STREAM) == RT_EOK)
{
if (shell->device != RT_NULL)
{
/* close old finsh device */
rt_device_close(shell->device);
rt_device_set_rx_indicate(shell->device, RT_NULL);
} /* clear line buffer before switch to new device */
memset(shell->line, 0, sizeof(shell->line));
shell->line_curpos = shell->line_position = 0; shell->device = dev;
rt_device_set_rx_indicate(dev, finsh_rx_ind);
}
}** 注意:** 改为流模式后,会发现一个奇怪的现象,就是当你使用调试模式时,可以正常接收指令,但是正常运行时,就无任何响应,遇到这样的现象不要慌,接着往下看。
三、FinSH 卡死问题
现象:FinSH线程卡死,明显的发现就是,使用调试模式时,可以正常接收指令,但是正常运行时,就无任何响应。
原因:深入分析后,会在 shell.c 文件中的 finsh_getchar 函数中看到信号量的使用,如下图所示:
现在原因找到了,那么我们只需要在适当的时候释放信号量即可,那我们在找找看看有么有信号释放的函数,接下来我们会发现在 shell.c 文件中 finsh_rx_ind 函数就是释放信号量的,如图所示:
那么新的问题又来了,怎么调用这个函数了,因为在shell.h文件中也没有这个函数的定义, 不要怕我们接着找,最后在shell.c 文件中的 finsh_set_device 函数中,会将释放信号量的函数指针放入 rt_device 结构体中,如下图所示:
那么问题就变得简单了,解决办法如下
解决办法:我们已经知道怎么释放信号量了,所以只需要在 数据接收函数(stm32_getc)中,完成数据接收后,释放信号量即可,如下所示:
/**
* 接收一个字符数据
*/
static int stm32_getc(struct rt_serial_device *serial)
{
int ch;
struct stm32_uart *uart;
RT_ASSERT(serial != RT_NULL);
uart = rt_container_of(serial, struct stm32_uart, serial); ch = -1;
if (USART_GetFlagStatus(uart->handle.Instance, USART_FLAG_RXNE) != RESET)
{
#if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32F0) \
|| defined(SOC_SERIES_STM32L0) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32H7) \
|| defined(SOC_SERIES_STM32G4)
ch = uart->handle.Instance->RDR & 0xff;
#else
// ch = (uint16_t)uart->handle.Instance->DR & (uint16_t)0x00ff;
ch = (char)USART_ReceiveData(uart->handle.Instance);
#endif } /* 调用设备接收数据回调,释放信号量 */
uart->serial.parent.rx_indicate(&serial->parent, 0);
return ch;
}
四、测试
解决完问题后,在控制台输入回车有相应的回应就没问题,如下图所示:
RT-Thread 组件 FinSH 使用时遇到的问题的更多相关文章
- 小程序scroll-view组件使用时,子元素虽设置样式display:inline-flex;whit-space:nowrap
小程序scroll-view组件使用时,子元素虽设置样式display:inline-flex;whit-space:nowrap
- Android插件化(三):OpenAtlas的插件重建以及使用时安装
Android插件化(三):OpenAtlas的插件重建以及使用时安装 转 https://www.300168.com/yidong/show-2778.html 核心提示:在上一篇博客 An ...
- Android Loader使用时,屏幕解锁后,重复加载
在使用AsyncTaskLoader时,当手机解锁后,会重复加载数据,代码如下: static class CouponShopQueryLoader extends AsyncTaskLoader& ...
- Cookie使用时需要注意个数及大小限制
各浏览器对Cookie有一定的限制,在使用时需要格外注意. 各浏览器之间对cookie的不同限制: IE6.0 IE7.0/8.0/9.0+ Opera FF Safari Chrome cook ...
- EntityFrameWork 使用时碰到的小问题
EntityFrameWork 使用时碰到的小问题 1,在使用orm访问数据库的相目里,也要引用EntityFrameWork.dll,否则无法使用orm 否则,编译错误 错误 5 "Sys ...
- MySQL 安装和启动服务,“本地计算机 上的 MySQL 服务启动后停止。某些服务在未由其他服务或程序使用时将自动停止。”
MySQL 安装和启动服务,以及遇到的问题 MySQL版本: mysql-5.7.13-winx64.zip (免安装,解压放到程序文件夹即可,比如 C:\Program Files\mysql-5. ...
- MaterialCalendarView使用时遇到的问题
一.概述 MaterialCalendarView是一个开源项目.功能强大支持多选.单选.标注等. 二.问题 1.其继承自ViewGroup,故与CalendarView半毛钱关系都没有,完全是一个新 ...
- [备忘][转]rsync使用时的常见问题
sync使用时的常见问题: 错误1: rsync: read error: Connection reset by peer (104) rsync error: error in rsync pro ...
- 小白学数据分析----->移动游戏的使用时长分析
写下该文章,是因为之前看到了几款游戏一个典型的玩家刺激活动,在<多塔联盟>,<萌江湖>等多款游戏的设计中都有体现,如下图所示: 这个功能点的设计,今天在这里讲的更多的还是跟数据 ...
随机推荐
- VMware虚拟机无法安装Win11解决方法 (暂时全网最全方案)
目录 1.现象 1.蓝屏重启 2.如下图示,无法启动 2.解决方案 2.1 Hyper-V方案 2.2 禁用 Device Guard(系统:win11) 2.3 升级虚拟机VMware pro的版本 ...
- hibernate查询不到关联对象列表-fetchType的选择
概述 昨天排查问题的时候,发现使用hibernate关联对象时,订单实体类对象死活无法获取关联的订单明细列表 Order order = orderDao.findById(201L); //明明数据 ...
- js 前端实现下拉刷新 上拉加载
效果 css html,body{ height:100%; // 其他界面未设置html 无法监听scroll } /* 下拉刷新 */ .refresh-loading { transition: ...
- Unity实现A*寻路算法学习2.0
二叉树存储路径节点 1.0中虽然实现了寻路的算法,但是使用List<>来保存节点性能并不够强 寻路算法学习1.0在这里:https://www.cnblogs.com/AlphaIcaru ...
- Error:java: Can‘t generate mapping method with primitive return type.报错
原因:Spring项目中使用了JPA以及Mybatis–mapper文件注解引错包导致编译错误 解决: 错误:import org.mapstruct.Mapper;正确路径:import org.a ...
- Hadoop(三)通过C#/python实现Hadoop MapReduce
MapReduce Hadoop中将数据切分成块存在HDFS不同的DataNode中,如果想汇总,按照常规想法就是,移动数据到统计程序:先把数据读取到一个程序中,再进行汇总. 但是HDFS存的数据量非 ...
- form表单与CSS选择器和样式操作
form表单 """获取前端用户数据并发送给后端服务器""" <form action=""></fo ...
- ubuntu helpers
linux 命令大全 Apt proxy configuration on Ubuntu 20.04 Focal Fossa Linux 临时使用socks代理apt-get的方法 docker - ...
- 274. H-Index - LeetCode
Question 274. H-Index Solution 题目大意: 论文里的 h 因子判定,题目的意思可能有点晦涩.h 因子是评判学术成就的一种重要方法,h 因子越高越好,h 因子兼顾研究学术人 ...
- ElasticSearch7.3学习(二十七)----聚合概念(bucket和metric)及其示例
一.两个核心概念:bucket和metric 1.1 bucket 有如下数据 city name 北京 张三 北京 李四 天津 王五 天津 赵六 天津 王麻子 划分出来两个bucket,一个是北 ...