Linux驱动开发二

2)创建设备节点
            ----->手动创建设备节点
                mknod 设备名 设备类型  主设备号  次设备号
                mknod /dev/hello c 254 0 
        
        
            ----->自动创建设备节点
                创建类                
                    class_create(owner, name)
                    参数1:表示模块   一般用THIS_MODULE表示
                    参数2:类的描述信息--------》自定义
                    成功:返回struct class的结构体,失败用PTR_ERR()表示
                
                创建设备
                device_create(struct class * cls, struct device * parent, dev_t devt, void * drvdata, const char * fmt,...)
                    参数1:class_create中成功返回的结构体struct class 
                    参数2:父类------》一般为NULL
                    参数3:设备号
                        #define MINORBITS    20
                        #define MINORMASK    ((1U << MINORBITS) - 1)

                        #define MAJOR(dev)    ((unsigned int) ((dev) >> MINORBITS)) //通过设备号获取主设备号
                        #define MINOR(dev)    ((unsigned int) ((dev) & MINORMASK))  //通过设备号获取次设备号
                        #define MKDEV(ma,mi)    (((ma) << MINORBITS) | (mi))      //获取设备号
                    
                    
                    参数4:私有数据-------->一般为NULL
                    参数5:设备名
                    成功:返回struct device的结构体,失败用PTR_ERR()表示
        
        3)实现操作方法
     
            int hello_open(struct inode *inode,struct file *filp)
            {
                printk("open success -----> %s\n",__FUNCTION__);

                return 0;
            }

            int hello_close(struct inode *inode,struct file *filp)
            {
                printk("close sad -----> %s\n",__FUNCTION__);

                return 0;
            }

            struct file_operations fops={
                .open = hello_open,
                .release = hello_close,
            };             
     
     
     
        4)实例化对象
        kzalloc(size_t size, gfp_t flags)
            参数1:要申请空间的大小
            参数2:分配空间的标志-----> 一般用GFP_KERNEL(表示没有资源可申请时,休眠)
            
        5)硬件初始化:地址映射
        ioremap(cookie, size)
        参数1:表示映射的起始地址
        参数2:表示映射空间的大小
        gpc0_conf = ioremap(0xE0200060,8);
        gpc0_data = gpc0_conf + 1;
     
四:实现应用空间与内核空间的数据交互
        应用空间:实现策略--------》如何实现功能
        内核空间:实现机制--------》能不能实现
        
        应用空间------->内核空间    实现write函数接口
        copy_from_user(void * to, const void __user * from, unsigned long n)
        参数1: 目标地址---内核中的空间地址
        参数2: 原地址-----应用空间中数据的地址
        参数3: 传递给内核的数据的长度
        返回值: 0---成功,非0 ---- 没有传递过来的数据的个数
        ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
             
                
        内核空间------->应用空间    实现read函数接口
        copy_to_user(void __user * to, const void * from, unsigned long n)
        参数1: 目标地址---应用空间的地址
        参数2: 原地址-----内核中数据的地址
        参数3: 传递给应用空间的数据的长度
        返回值: 0---成功,非0 ---- 没有传递给应用空间的数据的个数
         ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
         
         
    五:   ioctl实现点灯,指定某个亮或者灭
    
        1)通过使用ioctl实现应用层的ioctl

        应用层
        
            int ioctl(int d, int request, ...);

        ——————————————————————————————————————————
        内核层
        
            long xxx_ioctl (struct file *, unsigned int, unsigned long)
            switch(cmd)
            {
                case LED_NUM1_ON:
                    .................
                    break;
                    
                case LED_NUM1_ON:
                    .................
                    break;
                    
                case LED_NUM1_ON:
                    .................
                    break;
            
            }
        
        方法1:任意定义一些数来表示某个命令
            #define LED_NUM1_ON 0X1234
            #define LED_NUM1_OFF 0X5678
            
        方法2:利用内核的算法生成一些数
        #define _IO(type,nr)        _IOC(_IOC_NONE,(type),(nr),0)
        #define _IOW(type,nr,size)    _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
        
        
        #define _IOR(type,nr,size)    _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
        
        #define _IOWR(type,nr,size)    _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
        #define _IOR_BAD(type,nr,size)    _IOC(_IOC_READ,(type),(nr),sizeof(size))
        #define _IOW_BAD(type,nr,size)    _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
        #define _IOWR_BAD(type,nr,size)    _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
        
    2)通过库函数实现
        //获取/申请IO
        static inline int gpio_request(unsigned gpio, const char *label)
        //给某个指定的IO设置值
        static inline void gpio_set_value(unsigned gpio, int value)
        //从某个指定的IO口获取值
        static inline int gpio_get_value(unsigned gpio)        
        
        //向指定的IO口输出一个特定的值
        static inline int gpio_direction_output(unsigned gpio, int value)
        //从指定的IO口输入
        static inline int gpio_direction_input(unsigned gpio)
        //释放/回收IO
        static inline void gpio_free(unsigned gpio)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值