RK3568------Openharmony 4.0-Release HDF串口驱动BUG改进方案
文章目录
- RK3568------Openharmony 4.0-Release HDF串口驱动BUG改进方案
- 前言
- 一、HDF串口驱动的BUG解析
- 二、HDF串口驱动的BUG改进
- 总结
前言
因为目前项目进入XTS认证阶段,遇到的都是具有特殊性问题,所以就没有频率很高的发布文章。今天发布的内容主要针对《RK3568------Openharmony 4.0-Release HDF串口驱动(USB转串口) 下》一文中串口通讯遇到的BUG改进方案做一个解析与分享。
一、HDF串口驱动的BUG解析
源码: uart_adapter.c
- 假如我们在
HCS中定义多个串口设备
,并且串口设备名称的前缀格式不同
,当我们通过接口获取到HCS中属性的driver_name后,将这个driver_name写入到全局变量数组
中后,会形成一个错误的设备名称,因为这种处理方式的现象是将多个串口写入同一个变量
中,这在逻辑上是不对的,正常的逻辑应该是一个串口设备就应该对应一个设备名称。
- 这里是一个伪实现函数
- 这里串口属性配置不全,可能会导致接收不到数据情况
- 读的逻辑与下面写的逻辑不一致,不是一次全部读出
二、HDF串口驱动的BUG改进
改进代码:链接: uart_adapter.c
- 创建一个结构体,存储文件描述符与设备名称,保证一个串口设备对应一个名称
- 因为是在内核里的操作,所以我采用重新打开文件描述符的方案来修改读写的模式
static int32_t UartAdapterSetTransMode(struct UartHost *host, enum UartTransMode mode)
{// 这里是一个伪函数,没有实现功能,因为是在内核里的操作,所以我采用重新打开文件描述符的方案char name[UART_PATHNAME_LEN] = {0};struct file *fp = NULL;mm_segment_t oldfs;struct UartPriv *uartpriv = NULL;int open_mode;if (host == NULL) {HDF_LOGE("UartAdapterSetTransMode: host is null!");return HDF_ERR_INVALID_OBJECT;}uartpriv = (struct UartPriv *)host->priv;if (sprintf_s(name, UART_PATHNAME_LEN - 1, "/dev/%s%d", uartpriv->g_driverName, host->num) < 0) {return HDF_FAILURE;}// 确定打开标志if(mode == UART_MODE_RD_BLOCK){open_mode = O_RDWR | O_NOCTTY;}else{open_mode = O_RDWR | O_NOCTTY | O_NONBLOCK;}fp = uartpriv->fp;oldfs = get_fs();set_fs(KERNEL_DS);// 关闭文件描述符if (!IS_ERR(fp) && fp) {filp_close(fp, NULL);} // 重新打开文件描述符fp = filp_open(name, open_mode, 0600); /* 0600 : file mode */if (IS_ERR(fp)) {HDF_LOGE("UartAdapterSetTransMode: filp_open %s fail!", name);set_fs(oldfs);return HDF_FAILURE;}set_fs(oldfs);uartpriv->fp = fp;return HDF_SUCCESS;
}
- 重写配置串口的属性
termios.c_cflag |= CLOCAL | CREAD;termios.c_cflag &= ~CSIZE;termios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); termios.c_iflag &= ~(IXON | IXOFF | IXANY); termios.c_oflag &= ~OPOST;
4.重写读的逻辑
static int32_t UartAdapterRead(struct UartHost *host, uint8_t *data, uint32_t size)
{loff_t pos = 0;int ret;struct file *fp = NULL;char *p = (char *)data;mm_segment_t oldfs;uint32_t tmp = 0;struct UartPriv *uartpriv = NULL;if (host == NULL || host->priv == NULL || data == NULL || size == 0) {HDF_LOGE("UartAdapterRead: invalid parameters!");return HDF_ERR_INVALID_OBJECT;}uartpriv = (struct UartPriv *)host->priv;fp = uartpriv->fp;oldfs = get_fs();set_fs(KERNEL_DS);while (tmp < size) {ret = vfs_read(fp, p + tmp, size - tmp, &pos);if (ret < 0) {HDF_LOGE("UartAdapterRead: vfs_read fail ret: %d!", ret);if (tmp == 0)tmp = ret ;break;}if (ret == 0)break ;tmp += ret;}set_fs(oldfs);return tmp;
}
总结
本人之前一直从事应用开发,借着这次电鸿的契机进行系统级开发的学习,将我在工作中的遇到的问题及解决思路记录并分享,希望可以与诸君共勉
目前网上技术讨论群大都是鸿蒙的应用开发,总结此类文章也是希望将同样进行鸿蒙设备开发的同僚召集到一起,一起讨论学习。如果有同样在进行鸿蒙设备开发的朋友,可以加我的联系方式,期待您的消息
个人微信