• 硬件访问方法和混杂字符设备


    1、 寄存器与内存

           寄存器与内存的区别在哪里呢?

           寄存器和RAM 的主要不同在于寄存器操作有副作用side effect或边际效果):读取某个地址时可能导致该地址内容发生变化,比如很多设备的中断状态寄存器只要一读取,便自动清零。

    2、 内存与I/O

           在X86处理器中存在I/O空间的概念,I/O空间是相对内存空间而言的,他们是彼此独立的地址空间,在32位的x86系统中,I/O空间大小为64K,内存空间大小为4G

    3、 IO/内存空间

           X86支持内存空间、IO空间

           ARM只支持内存空间

           MIPS只支持内存空间

           PowerPC只支持内存空间

    4、 IO端口与IO内存

           IO端口:当一个寄存器或内存位于IO空间时,称其为IO端口

           IO内存:当一个寄存器或内存位于内存空间时,称其为IO内存

    5、 操作I/O端口

           对I/O端口的操作需按如下步骤完成:

           1申请

           2访问

           3释放

           1)申请I/O端口

           内核提供了一套函数来允许驱动申请它需要的I/O端口,其中核心的函数是:

           struct resource *request_region(unsigned long first,unsigned long n, const char *name)

           这个函数告诉内核,你要使用从first 开始的n个端口,name参数是设备的名字。如果申请成功,返回NULL申请失败,返回NULL

           系统中端口的分配情况记录在/proc/ioports(展示)。如果不能分配需要的端口,可以来这里查看谁在使用。

           2)访问I/O端口

           I/O端口可分为8-位, 16-位, 和32-位端口。Linux内核头文件(体系依赖的头文件<asm/io.h>) 定义了下列内联函数来访问I/O 端口:

    unsigned inb(unsigned port) 读字节端口( 8 位宽)

    void outb(unsigned char byte, unsigned port) 写字节端口( 8 位宽)。

    unsigned inw(unsigned port)

    void outw(unsigned short word, unsigned port)存取16-位端口。

    unsigned inl(unsigned port)

    void outl(unsigned longword, unsigned port)存取32-位端口。

           3)释放I/O端口

           当用完一组I/O 端口(通常在驱动卸载时),应使用如下函数把它们返还给系统:

           void release_region(unsigned long start, unsigned long n)

    6、 操作I/O内存

           对I/O内存的操作需按如下步骤完成:

           1)申请

           2映射

           3)访问

           4)释放

           1)申请I/O内存

           内核提供了一套函数来允许驱动申请它需要的I/O内存,其中核心的函数是:

           struct resource *request_mem_region(unsignedlong start, unsigned long len, char *name)

           这个函数申请一个从start 开始,长度为len 字节的内存区。如果成功,返回NULL;否则返回NULL,所有已经在使用的I/O内存在/proc/iomem中列出。

           2)映射I/O内存

           在访问I/O内存之前, 必须进行物理地址到虚拟地址的映射,ioremap 函数具有此功能:

           void *ioremap(unsigned long phys_addr, unsigned long size)

           3)访问I/O内存

           访问I/O 内存的正确方法是通过一系列内核提供的函数:

           从I/O 内存读, 使用下列之一:

    unsigned ioread8(void *addr)

    unsigned ioread16(void *addr)

    unsigned ioread32(void *addr)

           写I/O 内存, 使用下列之一:

    void iowrite8(u8 value, void *addr)

    void iowrite16(u16 value, void *addr)

    void iowrite32(u32 value, void *addr)

          访问I/O内存

    老版本的I/O 内存访问函数:

    从I/O 内存读, 使用下列之一:

    unsigned readb(address)

    unsigned readw(address)

    unsigned readl(address)

          写I/O 内存, 使用下列之一:

    unsigned writeb(unsigned value, address)

    unsigned writew(unsigned value, address)

    unsigned writel(unsigned value, address)

    7、 释放I/O内存

           I/O内存不再需要使用时应当释放,步骤如下:

          1)void iounmap(void * addr)

          2)void release_mem_region(unsigned long start, unsigned long len)

    8、 混杂字符设备
          在Linux系统中,存在一类字符设备,它们共享一个主设备号(10),但次设备号不同,我们称这类设备为混杂设备
    (miscdevice)。所有的混杂设备形成一个链表,对设备访问时内核根据次设备号查找到相应的miscdevice设备。
          1)混杂字符设备设备描述
          Linux内核使用struct miscdevice来描述一个混杂设备。

    struct miscdevice {
    int minor; /* 次设备号*/
    const char *name; /* 设备名*/
    const struct file_operations *fops; /*文件操作*/
    struct list_head list;
    struct device *parent;
    struct device *this_device;
    };

          2)设备注册
          Linux内核使用misc_register函数来注册一个混杂设备驱动。
          int misc_register(struct miscdevice * misc)

  • 相关阅读:
    storm原理写得比较好的文章
    maven设置jdk版本
    项目中记录log4j记录日志
    eclipse jadeclipse配置
    Maven使用说明
    crond不执行原因分析
    空调遥控器图标含义
    window7开放端sqlserver端口
    servlet仿struts参数注入
    cocos 2dx-js3.5整合anySDK
  • 原文地址:https://www.cnblogs.com/Daniel-G/p/3324663.html
Copyright © 2020-2023  润新知