RK3568------Openharmony 4.0-Release HDF串口驱动代码BUG改进方案

RK3568------Openharmony 4.0-Release HDF串口驱动BUG改进方案


前言

因为目前项目进入XTS认证阶段,遇到的都是具有特殊性问题,所以就没有频率很高的发布文章。今天发布的内容主要针对《RK3568------Openharmony 4.0-Release HDF串口驱动(USB转串口) 下》一文中串口通讯遇到的BUG改进方案做一个解析与分享。


一、HDF串口驱动的BUG解析

源码: uart_adapter.c

  1. 假如我们在HCS中定义多个串口设备,并且串口设备名称的前缀格式不同,当我们通过接口获取到HCS中属性的driver_name后,将这个driver_name写入到全局变量数组中后,会形成一个错误的设备名称,因为这种处理方式的现象是将多个串口写入同一个变量中,这在逻辑上是不对的,正常的逻辑应该是一个串口设备就应该对应一个设备名称。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  2. 这里是一个伪实现函数
    在这里插入图片描述
  3. 这里串口属性配置不全,可能会导致接收不到数据情况
    在这里插入图片描述
  4. 读的逻辑与下面写的逻辑不一致,不是一次全部读出
    在这里插入图片描述

二、HDF串口驱动的BUG改进

改进代码:链接: uart_adapter.c

  1. 创建一个结构体,存储文件描述符与设备名称,保证一个串口设备对应一个名称
    在这里插入图片描述
  2. 因为是在内核里的操作,所以我采用重新打开文件描述符的方案来修改读写的模式
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;
}
  1. 重写配置串口的属性
    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;
}

总结

本人之前一直从事应用开发,借着这次电鸿的契机进行系统级开发的学习,将我在工作中的遇到的问题及解决思路记录并分享,希望可以与诸君共勉
目前网上技术讨论群大都是鸿蒙的应用开发,总结此类文章也是希望将同样进行鸿蒙设备开发的同僚召集到一起,一起讨论学习。如果有同样在进行鸿蒙设备开发的朋友,可以加我的联系方式,期待您的消息
个人微信

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值