建议使用以下浏览器,以获得最佳体验。 IE 9.0+以上版本 Chrome 31+ 谷歌浏览器 Firefox 30+ 火狐浏览器
请选择 进入手机版 | 继续访问电脑版
设置昵称

在此一键设置昵称,即可参与社区互动!

确定
我再想想
选择版块
直达楼层
标签
您还可以添加5个标签
  • 没有搜索到和“关键字”相关的标签
  • 云产品
  • 解决方案
  • 技术领域
  • 通用技术
  • 平台功能
取消

采纳成功

您已采纳当前回复为最佳回复

樊心昊

发帖: 172粉丝: 141

发消息 + 关注

发表于2020年05月16日 15:32:29 959 3
直达本楼层的链接
楼主
显示全部楼层
[技术干货] 0x03 LiteOS_Lab仓库组件详解--Driver (下)

设备开启函数


我们在使用某个设备之前,如果该设备具有open和close的能力,就要先去打开该设备,用完之后关闭该设备。

/*******************************************************************************
function     :open the device with the specified name
parameters   :
instruction  :if first open the device,then will call the init function if exsited
*******************************************************************************/

/* 传入需要开启的设备名称,以及一个flag,该flag的值取决于我们定义设备的open函数指针时定义的 */
los_dev_t  los_dev_open  (const char *name,unsigned int flag)
{
    bool_t opret = true;           //operate result
    struct driv_cb *driv = NULL;   //the driver attached
    struct dev_cb  *dev = NULL;    //the device opened
    if ( NULL == name )
    {
        goto EXIT_PARAERR;
    }

    dev = osal_malloc(sizeof(struct dev_cb));    //为设备结构体指针分配内存,用于存储需要操作设备的信息
    if (NULL == dev)
    {
        goto EXIT_MEMERR;
    }
    (void) memset(dev,0,sizeof(struct dev_cb));

    opret = osal_mutex_lock(s_los_driv_module.lock);    //加锁,防止多个进程同时访问
    if(false == opret)
    {
        goto EXIT_MUTEXERR;
    }

    driv = __driv_match(name);                        //通过设备名称寻找设备对应的结构体
    if(NULL == driv)
    {
        goto EXIT_DRIVERR;
    }
    //WE DON'T CARE TOO MUCH ABOUT THE RD AND WR FLAG,MAY BE TODO IT IN THE NEXT VERSION HERE
    if((O_EXCL & (unsigned int )driv->flagmask) && (NULL != driv->devlst))
    {
        goto EXIT_EXCLERR;
    }

    if((0 == (driv->drivstatus & cn_driv_status_initialized)) && \    //如果设备未初始化但是有初始化函数
        (NULL != driv->op->init))
    {
        opret = driv->op->init(driv->pri);                    //在这里调用其初始化函数
        if(false == opret)
        {
            driv->errno = en_dev_err_init;
            goto EXIT_INITERR;
        }
        driv->drivstatus |= cn_driv_status_initialized;
    }

    if(NULL != driv->op->open)                            //如果该设备没有open能力或者说是open函数
    {
        opret = driv->op->open(driv->pri,flag);
        if(false == opret)
        {
            driv->errno = en_dev_err_open;
            goto EXIT_OPENERR;
        }
    }

    //reach here means all the initialize is ok
    //add the dev to the list of the drive and  attach the driv to the device
    driv->opencounter++;        //开启的设备总数加一
    dev->nxt = driv->devlst;    //将这个设备的结构体指针挂载到开启的设备链表中
    driv->devlst = dev;

    dev->driv = driv;
    dev->openflag =  flag;

    (void) osal_mutex_unlock(s_los_driv_module.lock);
    return dev;

EXIT_OPENERR:
EXIT_INITERR:
EXIT_EXCLERR:
EXIT_DRIVERR:
    (void) osal_mutex_unlock(s_los_driv_module.lock);
EXIT_MUTEXERR:
    osal_free(dev);
    dev = NULL;
EXIT_MEMERR:
EXIT_PARAERR:
    return dev;    //返回一个操作句柄,我们读写数据就是通过这个操作句柄来操作
}

设备关闭函数


在使用完设备之后,我们可以调用设备关闭函数。

/*******************************************************************************
function     :close the device of opened
parameters   :handle returned by open
instruction  :
*******************************************************************************/
bool_t  los_dev_close  (los_dev_t dev)    //传入操作句柄
{
    bool_t ret = false;
    struct dev_cb *devcb = NULL;
    struct dev_cb *tmp = NULL;
    struct driv_cb *driv = NULL;

    if ( NULL == dev )
    {
        goto EXIT_PARAERR;
    }
    devcb = dev;

    if(false == osal_mutex_lock(s_los_driv_module.lock))    //加锁,防止多进程同时访问出错
    {
        goto EXIT_MUTEXERR;
    }

    //deattach the dev from the driv
    driv = devcb->driv;    //将设备结构体地址赋值给driv
    if(NULL == driv)
    {
        goto EXIT_DRIVERR;
    }

    if(devcb == driv->devlst)    //如果需要关闭的设备是链表中第一个
    {
        driv->devlst = devcb->nxt;
    }
    else                        //如果需要关闭的设备不是链表中第一个
    {
        tmp = driv->devlst;
        while(NULL != tmp)
        {
            if(tmp->nxt == devcb)
            {
                tmp->nxt = devcb->nxt;
                break;
            }
            tmp = tmp->nxt;
        }
        if(NULL == tmp)
        {
            goto EXIT_DETACHERR;
        }
    }
    if(NULL != driv->op->close)    //调用设备的关闭函数
    {
        driv->op->close(driv->pri);
    }

    if((NULL == driv->devlst) && (NULL != driv->op->deinit))
    {
        driv->op->deinit(driv->pri);        //调用设备的去除初始化函数
        driv->drivstatus &= (~cn_driv_status_initialized);    //将设备状态置为未初始化
    }

    osal_free(dev);        //释放设备结构体所占用内存
    driv->opencounter--;    //开启的设备总数减一

    (void) osal_mutex_unlock(s_los_driv_module.lock);    //解锁

    ret = true;

EXIT_DETACHERR:
EXIT_DRIVERR:
    (void) osal_mutex_unlock(s_los_driv_module.lock);
EXIT_MUTEXERR:
EXIT_PARAERR:
    return ret;
}

向设备中读取数据


/*******************************************************************************
function     :use this function to read data from the device
parameters   :dev,returned by the los_dev_open function
              offet:from where to read,only used for storage device
              buf:used to storage the data
              len:the length of the buf
              timeout:the waittime if no data current
instruction  :how many data has been read to the buf
*******************************************************************************/
//传入操作句柄、需要读取的数据在设备中的偏移量,读到指针对应的某个内存空间,读取的长度,读取超时时间
ssize_t   los_dev_read  (los_dev_t dev,size_t offset, void *buf,size_t len,uint32_t timeout)
{
    ssize_t ret = 0;
    struct dev_cb  *devcb;
    struct driv_cb *drivcb;

    if((NULL != dev)&&(NULL != buf)&&(0 != len))
    {
        devcb = dev;
        if((0 == ((uint32_t)devcb->openflag & O_WRONLY)))    //检查设备属性,是否可读
        {
            drivcb = devcb->driv;
            if((NULL != drivcb->op)&&(NULL != drivcb->op->read))
            {
                ret = drivcb->op->read( drivcb->pri,offset,buf,len,timeout);    //调用设备的读函数,传入参数
                if(ret > 0)
                {
                    drivcb->total_read += ret;
                }
            }
        }
    }

    return ret;     //返回读出数据的个数
}

向设备中写入数据


/*******************************************************************************
function     :use this function to write data to the device
parameters   :dev,returned by the los_dev_open function
              offset: from where to write,only used for storage device
              buf:the data to be written
              len:the length of the buf
              timeout:the waittime if no data current
instruction  :how many data has been written to the device
*******************************************************************************/
//传入操作句柄,需要写入的位置,需要被写入数据的地址,写入长度,超时时间
ssize_t los_dev_write (los_dev_t dev,size_t offset,const void *buf,size_t len, uint32_t timeout)
{
    ssize_t ret = 0;
    struct dev_cb  *devcb;
    struct driv_cb *drivcb;

    if((NULL != dev) && (NULL != buf) && (len != 0))
    {
        devcb = dev;
        if((((uint32_t)devcb->openflag) & O_WRONLY) || (((uint32_t)devcb->openflag) & O_RDWR))    //查看设备的属性是否支持写入
        {
            drivcb = devcb->driv;
            if((NULL != drivcb->op)&&(NULL != drivcb->op->write))
            {
                ret = drivcb->op->write( drivcb->pri,offset,buf,len,timeout);    //调用设备的写入函数,并将参数传入
                if(ret > 0)
                {
                    drivcb->total_write += ret;
                }
            }
        }
    }

    return ret;    //返回写入数据的个数
}


举报
分享

分享文章到朋友圈

分享文章到微博

采纳成功

您已采纳当前回复为最佳回复

极客潇

发帖: 520粉丝: 69

发消息 + 关注

发表于2020年05月21日 08:43:07
直达本楼层的链接
沙发
显示全部楼层

感谢分享

点赞 评论 引用 举报

采纳成功

您已采纳当前回复为最佳回复

scu-w

发帖: 354粉丝: 9

发消息 + 关注

发表于2020年05月25日 17:52:23
直达本楼层的链接
板凳
显示全部楼层

棒棒哒

点赞 评论 引用 举报

采纳成功

您已采纳当前回复为最佳回复

我是卤蛋

发帖: 121粉丝: 293

级别 : 版主,版块专家

发消息 + 关注

发表于2020年06月26日 11:10:06
直达本楼层的链接
地板
显示全部楼层

感谢分享,持续学习~

点赞 评论 引用 举报

游客

富文本
Markdown
您需要登录后才可以回帖 登录 | 立即注册

结贴

您对问题的回复是否满意?
满意度
非常满意 满意 一般 不满意
我要反馈
0/200