基于Linux内核的驱动开发

 1  设备树
      定义:描述设备硬件信息的一种数据结构
      exynos4412-fs4412.dtb--》硬件信息
       uImage-->代码框架
       将代码逻辑和数据信息分离的思想
      硬件:内存 flash gpio uart usb...---》可以用一种数据结构来表示--》设备树--》信息
      软件:uImage-->linux内核软件--》逻辑
    dt:device tree
     dtb:设备树二进制文件 exynos4412-fs4412.dtb
    dts:设备树源文件exynos4412-fs4412.dts
    dtsi:设备树头文件,它相当于C的头文件
    注意:一张板卡对应一个设备树文件
        linux内核代码支持ARM体系部分从3.0版本以后就将描述设备数据的文件和描述
        设备的逻辑代码分开了,描述设备硬件数据的文件称为设备树文件,描述设备的
        逻辑代码称为内核(kernel)。
     一个设备树源文件对应一张板卡的所有外设硬件信息,在文件中描述硬件节点的语法
    是设备树语法。
     设备树文件语法:
            1 /{} 表示一张板卡的所有硬件信息,它是根节点。
            2 节点名称@地址{节点属性}--》子节点
            3  compatible:根节点:制造商和产品型号
                                子节点:用来关联驱动和被驱动的设备
            4 reg:可寻址设备用来表示编码地址的信息,是一个列表
                led2--->gpx2_7   0x11000c40  4     0x11000c44 4  1/0
                reg=<地址1 长度1 地址2 长度2 。。。>
            每一个可编址的设备都有一个reg ,它是一个元组表,每一个元组都表示一个
            设备的地址范围。
            5 interrupt-parent:中断控制器节点指针,设备节点通过它来指定它所依附
                                    的中断控制器
           6 interrupts:中断指示符列表 (中断号和触发方式)
                            <中断类型  中断号 中断的触发方式>
        系统移植试验五:
         DM9000(DM9000IRQ)--->转化器--》con5--》con4-->U1A(gpx0_6)

    2 平台设备驱动框架
        设备:硬件设备 led uart spi i2c usb 网卡。。。--》设备树节点--》硬件信息
       驱动:软件
       使用虚拟总线可以将设备和它的驱动程序关联起来,虚拟总线就称为平台platform。
        我们将挂接在虚拟总线上的设备称为平台设备platform_device
        我们将挂接在虚拟总线上的驱动称为平台驱动platform_driver
       当在Linux 系统中注册一个设备时,设备会通过虚拟总线去找与之匹配的驱动程序
       当在Linux系统中注册一个驱动时,驱动程序会通过虚拟总线去找与之匹配的设备
       
     平台设备驱动框架:
        init:
            {
                1 注册平台设备
            int platform_device_register(struct platform_device *pdev)
                (将设备挂接在平台总线上)
                2 注册平台驱动
            int platform_driver_register(struct platform_driver *pdr)
                (将驱动挂接在平台总线上)
            }

        exit:
            {
                1 去注册平台驱动
            void platform_driver_unregister(struct platform_driver *)
                    (将驱动从平台总线上移除)
                2 去注册平台设备
            void platform_device_unregister(struct platform_device *pdev)
                    (将设备从平台总线上移除)
            }
       
        在Linux内核中用struct platform_device来描述一个平台设备
        struct platform_device {
        const char    *name;--》设备名
        int        id;--》设备ID
        bool        id_auto;
        struct device    dev;--》代表一个内核设备---》release:释放平台设备
        u32        num_resources;--》资源总数
        struct resource    *resource;--》设备资源
            。。。
        }
        在Linux内核中用struct platform_driver描述平台驱动
        struct platform_driver {
        int (*probe)(struct platform_device *);--》探测函数
        int (*remove)(struct platform_device *);--》移除驱动
        void (*shutdown)(struct platform_device *);
        int (*suspend)(struct platform_device *, pm_message_t state);
        int (*resume)(struct platform_device *);
        struct device_driver driver;--》驱动匹配设备的因素
        const struct platform_device_id *id_table;
        bool prevent_deferred_probe;
        };
    3 平台设备和平台驱动分开
        平台设备--》hello.ko
           平台驱动--》driver.ko
        注意:安装时,先安装平台设备,再安装平台驱动
                卸载时,先卸载平台驱动,再卸载平台设备
    4 平台设备添加资源
        如何给平台设备添加资源?
        使用平台设备中的struct resource来增加资源
        struct resource {-->用来描述设备资源
            resource_size_t start;--》起始地址
            resource_size_t end;--》结束地址
            const char *name;--》资源名称
            unsigned long flags;--》资源类型
            struct resource *parent, *sibling, *child;
            };
        struct resource    res[]=
            {
                {
                .start=0x11000c40,
                .end=0x11000c43,
                .flags=IORESOURCE_MEM,-->内存资源
                },
                {
                .start=88,
                .flags=IORESOURCE_IRQ,
                },
            }
    4 平台驱动获取资源
         当注册平台驱动时,平台驱动的helloProbe函数就会通过虚拟总线去获取到
        挂接在虚拟总线上的设备信息
        helloProbe(struct platform_device *pdev)
        {
            pdev->resource
            if(pdev->resource->flags&IORESOURCE_MEM)
                {
                    使用
                }
        }

    5 mmap
       mmap-->系统调用函数
        fd=open(“/dev/haha0”)
    void *mmap(void *addr, size_t length, int prot, int flags,
                  int fd, off_t offset);---》vma-->起始,结束 保护标志  flags
        作用:将用户空间的地址映射到内核空间
        *addr:被映射的用户空间地址,通常给NULL,
          length:映射地址的长度
        prot:内核保护标志 PROT_READ PROT_WRITE
        flags:MAP_SHARED MAP_PRIVATE
        fd:文件描述符
        offset:被映射对象的读写偏移量 0
        返回值:成功:被映射区的地址(指针)
                  失败:MAP_FAILED
        
        int munmap(void *addr, size_t length);----》取消映射
            *addr:被映射区的地址---》用户空间地址
            length:映射地址的长度
            返回值:    0 成功
                        -1 失败

        驱动:
            int (*mmap) (struct file *, struct vm_area_struct *);
            HelloMmap(struct file *pFile,struct vm_area_struct *vma)
                *pFile:指向内核打开的文件
                *vma:指向应用层调用mmap映射成功后生成的映射结构体对象
             
            int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
            unsigned long pfn, unsigned long size, pgprot_t prot)
                作用:将映射结构体中指定的用户内存地址映射到内核虚拟地址,并将该
                        虚拟地址对应到具体的物理地址上
                *vma:应用层使用mmap后,内核生成的映射结构体变量
                addr:被映射的用户空间地址的起始值 vma->vm_start;
                pfn:内核虚拟地址对应的物理地址的页编号
                        virt_to_phys(g_buf)>>12
                size:被映射区域的大小
                prot:内核保护标志

            g_buf=kmalloc(size,GFP_KERNEL)  -->申请的空间在物理上是连续的--》kfree
             作用:申请一块内核内存空间
            vmalloc--》申请的空间在物理上是不连续的-->vfree
    
            struct vm_area_struct {
                unsigned long vm_start;--》起始地址        
                unsigned long vm_end;--》结束地址
                pgprot_t vm_page_prot;--》保护标志
                unsigned long vm_flags;--》MAP_SHARED MAP_PRIVATE
                ....
                }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值