[hisilicon][hi3536][linux-3.10]【PSAM卡】m50x i2c driver

m50x_device.c

#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/interrupt.h>
#include<linux/i2c.h>

static struct i2c_client *m50x_client;
static int i2c_bus_num=1;


static struct i2c_board_info m50x_boardinfo=
{
    I2C_BOARD_INFO("m50x",0x50),
    .platform_data = &i2c_bus_num,
};

static int __init  m50x_dev_init(void)
{
    struct i2c_adapter  *adapter;
    int ret=0;

    //get i2c adapter
    adapter = i2c_get_adapter(*((int *)m50x_boardinfo.platform_data));
    if(NULL == adapter)
    {
        printk("failed to get adapter\n");
        return -ENODEV;
    }

    //register i2c device
    m50x_client = i2c_new_device(adapter,&m50x_boardinfo);
     if(NULL == m50x_client)
    {
        printk("failed to register i2c device\n\n");
        ret = -EINVAL;
        goto err_add_device;
    } 
    m50x_client->adapter=adapter;
    return 0;
err_add_device:
    i2c_put_adapter(adapter);
    return ret;
}


static void __exit m50x_dev_exit(void)
{
    //unregister i2c device
    i2c_unregister_device(m50x_client);
    //release i2c adapater
    i2c_put_adapter(m50x_client->adapter);
}


module_init(m50x_dev_init);
module_exit(m50x_dev_exit);

MODULE_AUTHOR("TOMMY");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("PERSONAL");
 

 

 

 

 

 

 

 

 

 

 

 

 

 

m50x_driver.c

 

/****************
*******author:tommy
*******time:2018-11-25
*******description:此驱动是某公司
*******的PSAM卡的I2C驱动
************************/

#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/i2c.h>
#include<linux/interrupt.h>
#include<linux/bcd.h>
#include<linux/workqueue.h>
#include<linux/slab.h>
#include<linux/types.h>
#include<linux/device.h>


#define BUF_SIZE   256
static dev_t dev_id;            //设备号
static struct class *card_class;//设备类

struct m50x
{
    struct cdev cdev;            //字符设备
    struct i2c_client *client;    //I2C外设结构体,从机
    struct semaphore sem;        //并发控制用的信号量
    wait_queue_head_t r_wq;        //读等待队列
    wait_queue_head_t w_wq;        //写等待队列
    unsigned char buf[BUF_SIZE];//缓冲区
    unsigned char flag;           //读写标志
};

static ssize_t m50x_read(struct file *file,char _user *buf,size_t count,loff_t *ofs)
{
    struct m50x *chip = file->private_data;//通过私有数据获得
    int ret=0;
    
    if(down_interruptible(&chip->sem))//若返回值非0,获取信号量失败,说明临界资源已经被占用
    {
        return -EAGAIN;
    }
    if(!chip->flag)//若不可读
    {
        up(&chip->sem);//释放信号量
        //应用空间若以非阻塞方式访问,则返回错误
        if(file->f_flags & NONBLOCK)
        {
            return -EAGAIN;    
        }
        else//若以阻塞方式访问内核空间
        {
            //将读等待队列挂起,进入睡眠
            if(wait_event_interruptible(chip->r_wq,chip->flag))
            {
                return -ERESTARTSYS;    
            }
            //若获取信号量失败
            if(down_interruptible(&chip->sem))
            {
                return -ERESTARTSYS;    
            }
        }    
    }
    
    if(count > BUF_SIZE)
        count=BUF_SIZE;
    //ret为I2C主控器接收从机的数据长度(字节数)    
    ret=i2c_master_recv(chip->client,chip->buf,count);
    if(ret > 0)
    {
        //若拷贝数据到用户空间失败
        if(copy_to_user(buf,chip->buf,count))
        {
            up(&chip->sem);//释放信号量
            return -EFAULT;    
        }    
        else
        {
            chip->flag=0;//置为可写标志
            wake_up_interruptible(&chip->w_wq);//唤醒写等待队列    
        }
    }
    
    up(&chip->sem);
    return ret ? count : -1;
}

static int m50x_write(struct file *file,char _user *buf,size_t count,loff_t *ops)
{
    struct m50x *chip=file->private_data;
    int ret=0;
    
    if(down_interruptible(&chip->sem))
    {
        return -ERESTARTSYS;    
    }
    
    if(chip->flag)//不可写
    {
        up(&chip->sem);//释放信号量
        if(file->f_flags & NONBLOCK)
        {
            return -EAGAIN;
        }
        else
        {
            //让写等待队列进入睡眠
            if(wait_event_interruptible(chip->w_wq,chip->flag == 0))
            {
                return -ERESTARTSYS;    
            }    
            if(down_interruptible(&chip->sem))//获取信号量
            {
                return -ERESTARTSYS;    
            }
        }    
    }
    
    if(count > BUF_SIZE)
    {
        count = BUF_SIZE;    
    }
    
    if(copy_from_user(chip->buf,buf,count))
    {
        up(&chip->sem);
        return -EFAULT;
    }
    else
    {
        //ret为I2C主控器向从机发送的数据长度(字节数)
        ret=i2c_master_send(chip->client,chip->buf,count);
        if(ret)
        {
            chip->flag=1;//可读    
            wake_up_interruptible(&chip->r_wq);
        }    
    }
    up(&chip->sem);
    
    return ret ? count:-1
    
}

static unsigned int m50x_poll(struct file *file,struct poll_table_struct *wait)
{
    struct m50x *chip;
    unsigned int mask =0;
    int ret=0;
    
    if(down_interruptible(&chip->sem))
    {
        return -ERESTERSYS;    
    }
    
    poll_wait(file,&chip->r_wq,wait);
    poll_wait(file,&chip->w_wq,wait);
    
    if(chip->flag)//可读
    {
        mask |=POLLIN | POLLRDNORM;    
    }
    else//可写
    {
        mask |= POLLOUT | POLLWRNORM;    
    }
    up(&chip->sem);
    
    return mask;
}

static int m50x_open(struct inode *inode,struct file *file)
{
    struct m50x *chip = container_of(inode->i_cdev,struct m50x,cdev);
    
    file->private_data = chip;
    //初始化等待队列
    init_waitqueue_head(&chip->r_wq);
    init_waitqueue_head(&chip->w_wq);
    
    memset(chip->buf,0,BUF_SIZE);
    chip->flag=0;
    
    return 0;
}

static int m50x_release(struct inode *inode,struct file *file)
{
    return 0;
}

static const struct file_operations m50x_fops=
    .owner    =    THIS_MODULE,
    .read    =    m50x_read,
    .write    =    m50x_write,
    .poll    =    m50x_poll,
    .release=    m50x_release,    
};


static int m50x_probe(struct  i2c_client *client,const struct i2c_device_id *id)
{
    struct m50x *chip;
    int ret=0;
    //申请设备结构体的动态内存空间
    chip=kzalloc(sizeof(struct m50x),GFP_KERNEL);
    if(!chip)
    {
        return -ENOMH;
        goto alloc_err;    
    }
    
    //把m50x结构体数据作为I2C从设备的私有数据,便于以后调用
    i2c_set_clientdata(client,chip);
    
    //对chip结构体变量的成员进行初始化
    chip->client = client;
    sema_init(&chip->sem,1);//初始化信号量,必须在注册前初始化,以免产生竞态
    
    //动态申请设备号,让内核自动分配设备号
    ret = alloc_chrdev_region(&dev_id,0,1,DEVICE_NAME);
    if(ret)
    {
        printk("allocate dev id failed!\n ");
        goto alloc_dev_id_err;    
    }
    //字符设备初始化,将字符设备成员与函数操作集进行绑定
    cdev_init(&chip->cdev,&m50x_fops);
    chip->cdev.owner=THIS_MODULE;
    //完成设备注册,将设备与设备号绑定
    ret=cdev_add(&chip->cdev,dev_id,1);
    if(ret)
    {
        printk("cdev add err!\n");
        goto cdev_add_err;    
    }
    //创建一个类,存放在sysfs目录下,sysfs/class/
    card_class=class_create(THIS_MODULE,DEVICE_NAME);
    if(NULL==card_class)
    {
        printk("class create failed!\n");
        ret=-EBUSY;
        goto class_err;    
    }
    //创建设备节点成功,存放在/dev/目录下
    device_create(card_class,NULL,dev_id,NULL,DEVICE_NAME);
    printk(DEVICE_NAME" initalized!\n");
    
    return(0);
    
alloc_err:
    return(ret);
alloc_dev_id_err:
    kfree(chip);
cdev_add_err:
    unregister_chrdev_region(dev_id,1);
class_err:
    cdev_del(&chip->cdev);
        
}

static int m50x_remove(struct i2c_client *client,const struct i2c_device_id *id)
{
    struct m50x *chip = i2c_get_clientdata(client);    //获得外设的数据
    device_destroy(card_class,dev_id);                //将设备号从设备类中删除
    class_destroy(card_class);                        //删除设备类
    cdev_del(&chip->cdev);                            //删除字符设备
    unregister_chrdev_region(dev_id,1);                //注销设备号
    kfree(chip);                                    //释放动态内存
    printk(DEVICE_NAME" destroyed!");
    return 0;    
}

static const struct i2c_device_id m50x_id[]=
{
    {"m50x",0},    
    {}
};
MODULE_DEVICE_TABLE(i2c,m50x_id);


static struct i2c_driver   m50x_driver=
{
    .driver=
    {
        .name = "m50x_card",
        .owner=THIS_MODULE,

    },
    .probe=m50x_probe,
    .remove=m50x_remove,
    .id_table=m50x_id,

};
//入口函数
static __init  int m50x_drv_init(void)
{

    return i2c_add_driver(&m50x_driver);
}
//出口函数
static __exit  void m50x_drv_exit(void)
{

    i2c_del_driver(&m50x_driver);
}


module_init(m50x_drv_init);
module_init(m50x_drv_exit);

MODULE_AUTHOR("TOMMY");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("LINUX_WORKER");

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

makefile


obj-o += m50x

PWD    :=    $(shell pwd)
KERDIR := ${PWD}/../

    make -C  ${KERDIR}  -M ${PWD}  
    
    
    RKImageMaker.exe -RK330A Image\MiniLoaderAll.bin  D:\Image\update_old.img D:\Image\update_%FILENAME% -os_type:androidos

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要使用海思i2c工具来读写imx334 id,我们可以按照以下步骤进行操作: 1. 连接硬件:将imx334摄像头模块与处理器的i2c总线相连。确保电源供应正常并且连接正确。 2. 安装海思i2c工具:在处理器上安装海思i2c工具软件包,包括i2cdetect和i2cget。这些工具将帮助我们进行i2c设备的探测和读写操作。 3. 找到imx334摄像头的i2c地址:使用i2cdetect工具来扫描i2c总线,并查找imx334摄像头的i2c地址。运行i2cdetect -y -r 0命令,其中“0”是i2c总线编号,根据具体配置进行调整。命令的输出将显示i2c总线上找到的设备地址。找到imx334摄像头的i2c地址后,我们可以使用这个地址进行后续的读写操作。 4. 读取imx334 id:使用i2cget工具,运行i2cget -y -r 0 i2c_address register_address命令来读取imx334摄像头的id。其中,“i2c_address”是我们在前一步中找到的imx334摄像头的i2c地址,“register_address”是imx334摄像头的注册地址。运行命令后,将会打印出imx334的id。 5. 写入imx334 id:使用i2cset工具,运行i2cset -y -r 0 i2c_address register_address value命令来写入imx334摄像头的id。其中,“i2c_address”是我们在前一步中找到的imx334摄像头的i2c地址,“register_address”是imx334摄像头的注册地址,“value”是需要写入的id值。运行命令后,将会将id写入imx334摄像头。 通过以上的步骤,我们可以使用海思i2c工具来读写imx334摄像头的id信息。 ### 回答2: 要使用海思 i2c tools读写imx334 id,需要执行以下步骤: 1. 确保你的系统上已经安装了海思的i2c tools软件包。你可以通过在终端中运行以下命令来检查是否安装了这个软件包: ``` i2cdetect -l ``` 如果运行结果中显示有海思的i2c设备列表,则说明软件包已经正确安装。 2. 确定imx334相机模组的i2c地址。使用以下命令可以扫描系统上连接的i2c设备,并显示每个设备的地址: ``` i2cdetect -y <i2c-bus号> ``` 在运行命令时,将<i2c-bus号>替换为相机模组所连接的i2c总线号。例如,如果相机连接到i2c-1总线上,则命令应为: ``` i2cdetect -y 1 ``` 运行命令后,你将看到一个i2c设备网格,显示了每个设备的地址。寻找imx334模组对应的地址。 3. 读取imx334的id。使用以下命令可以读取imx334模组的id: ``` i2cget -y <i2c-bus号> <i2c地址> <寄存器地址> [w] ``` 在运行命令时,将<i2c-bus号>替换为相机模组所连接的i2c总线号,<i2c地址>替换为imx334模组的i2c地址,<寄存器地址>替换为id寄存器的地址。如果id是16位的,可以在命令的末尾添加[w]选项以读取完整的16位id值。 例如,如果imx334模组的i2c地址为0x30,id寄存器地址为0x00,则命令应为: ``` i2cget -y 1 0x30 0x00 w ``` 运行命令后,将显示imx334模组的id值。 通过执行上述步骤,你可以使用海思i2c tools读取imx334模组的id。注意,确保在操作i2c设备时具备足够的权限,并正确连接imx334模组到i2c总线上。 ### 回答3: IMX334是一种高性能的CMOS图像传感器,常用于工业相机和监控设备中。要使用海思(HiSilicon)公司的I2C工具来读写IMX334的ID,可以按照以下步骤进行。 首先,需要将IMX334连接到主控制器上,通常会使用一些引脚将两者连接起来。确保连接正确并且稳定。 接下来,使用I2C工具在主控制器上打开I2C总线。I2C总线是一种串行通信协议,用于在电子设备之间传输数据。通过I2C总线,主控制器可以与IMX334进行通信。 在I2C工具中,您需要设置正确的I2C地址。每个I2C设备都有一个独特的地址,用于在总线上进行识别。查阅IMX334的数据手册,找到正确的I2C地址并设置到工具中。 一旦I2C地址设置完毕,您可以使用I2C工具发送读取指令来读取IMX334的ID。指令的格式和具体内容会根据I2C工具的不同而有所差异。根据IMX334的数据手册,找到对应的读取ID的指令,并将其发送到IMX334。 IMX334会响应读取指令,并返回其ID。您可以通过I2C工具接收并显示ID。 要写入IMX334的ID,可以使用相似的步骤。首先设置I2C地址到I2C工具中,然后发送写入指令和具体的ID值。 请注意,上述步骤只是一个大致的指导,具体的步骤可能因为使用的工具和设备而有所差异。对于准确的操作指导,请参考IMX334和所使用I2C工具的详细文档。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值