zoukankan      html  css  js  c++  java
  • linux使用i/o内存访问外设

    一。linux中访问外设的方法.
    1.IO端口(IO port)
    linux系统给外设分配不同的端口号,linux利用端口号来访问设备(驱动) (cpu x86)

    cpu访问外设通过端号,访问通过地址

    gec@ubuntu:/mnt/hgfs/tea/demo2$ cat /proc/ioports
    0000-0cf7 : PCI Bus 0000:00
    0000-001f : dma1
    0020-0021 : pic1
    0040-0043 : timer0
    0050-0053 : timer1
    0060-0060 : keyboard
    0064-0064 : keyboard
    0070-0071 : rtc0
    0080-008f : dma page reg
    00a0-00a1 : pic2
    00c0-00df : dma2
    00f0-00ff : fpu
    0170-0177 : 0000:00:07.1
    0170-0177 : ata_piix


    2.IO内存 (IO mem) ---> ARM/MPIS
    cpu访问外设的方法和访问内存方法都是一样,都是根据地址来方问。
    外设(GPIO,ADC,WDT)都内存一样,是统一编址。


    二。LINUX中IO内存的使用
    思想:申请IO内存区-->动态是映射--->使用虚拟地址--> 解除动态映射击--->释放IO内存区。

    1.IO内存的申请
    struct resource *request_mem_region(resource_size_t start,resource_size_t n,const char *name)
    参数值:
    start-->资源的内存区的开始地址(物理地址)
    n ----->物理内存区的大小
    name --->自定义内存区的名字 cat /proc/iomem


    返回值:
    struct resource * -->申请到的资源
    NULL--->申请失败



    2.释放IO内存
    void release_mem_region(resource_size_t start,resource_size_t n)


    例:
    struct resource *ledp=request_mem_region(OxE0200280,8,"gpj2_led");


    ----------------------------------------------------------------------------
    3.IO内存的动态映射
    void __iomem * ioremap (unsigned long phys_addr, unsigned long size)
    参数:
    unsigned long phys_addr--》需要映射的物理内存的地址(开始地址)
    unsigned long size -->需要映射的物理内存大小
    返值:
    void __iomem * --->映射后虚拟地址(开始地址)
    NULL --->失败

    4。IO内存动态映射解除
    void iounmap(void *addr)
    void *addr--->映射后的虚拟地址


    例:
    #define OxE0200280 GPJ2CON_PA
    unsigned int *GPJ2CON_VA =ioremap(GPJ2CON_PA,8);
    unsigned int *GPJ2DAT_VA =GPJ2CON_VA+1;


    iounmap(GPJ2CON_VA);


    -------------------------------------------------
    5.访问虚拟地址的函数(读写)
    1.
    unsigned int ioread32(void __iomem *addr)


    void __iomem *addr--->虚拟地址
    unsigned int ---》数据

    void iowrite32(u32 b, void __iomem *addr);


    例:

    unsigned int a=ioread(GPJ2CON_VA);
    a &= ;

    iowrite32(a,GPJ2CON_VA)

    2.
    static inline u32 readl(const volatile void __iomem *addr)
    static inline void writel(unsigned int b, volatile void __iomem *addr)

    3.
    static inline u32 __raw_readl(const volatile void __iomem *addr)
    static inline void __raw_writel(u32 v, volatile void __iomem *addr)

    实例:LED字符设备的驱动模块、

    #include <linux/module.h>
    #include <linux/kernel.h>
    #include<linux/cdev.h>

    struct cdev chrdev3;
    unsigned int TestMajor=0;
    unsigned int TestMinor=0;
    #define *** GPJ*CON_PA
    #define *** GPJ*DAT_PA
    unsigned int *GPJ2CON_VA;
    dev_t dev_no;

    int testopen(struct inode *inode, struct file *file)
    {
    //LED输出
    printk("led init ");

    }
    int testclose (struct inode *inode, struct file *file);
    {
    printk("close");
    return 0;

    }
    ssize_t testwrtie(struct file *, char __user *usr, size_t len, loff_t *off)
    {
    char buf[12];
    copy_from_user(buf,usr,);
    buf[12];
    //if(buf[]=='1')
    // led点明
    printk(,buf);


    }
    ssize_t testread(struct file *, char __user *usr, size_t len, loff_t *);
    {
    char buf='r';
    read_led;
    copy_to_user(usr,buf,);
    }

    struct file_operations fops= --->结构体初始化 .---???????????????
    { .owner=THIS_MODULE,
    .open=testopen,
    .write=testwrite,
    .release=testclose,
    }


    static int __init test_init(void) //入口函数
    {
    printk("hello world! "); //相当于printf()
    int ret;
    dev_no =MKDEV(TestMajor,TestMinor)


    if(dev_no>0)
    {
    ret=register_chrdev_region(dev_no, 1,"chrdev_test");//静态注册设备号

    }
    else //动态申请设备号
    {

    alloc_chrdev_region(&dev_no,TestMinor, 1,"chrdev_test");

    }


    if(ret<0)
    {
    return ret;
    }


    cdev_init(&chrdev3,&fops);
    cdev.owner=THIS_MODULE;
    cdev_add(&chrdev3,dev_no,1);

    request_mem_region();

    GPJ2CON_VA =ioremap(GPJ2CON_PA,8);
    GPJ2DAT_VA =GPJ2CON_VA+1;

    return 0;
    }

    static void __exit test_exit(void) //出口函数
    {
    unregister_chrdev_region(dev_no, 1);
    cdev_del(&chrdev3);
    }


    module_init(test_init); //驱动的入口 #insmod *.ko
    module_exit(test_exit); //驱动的出口 #rmmod *.ko

    //#modinfo *.ko 可以查看module的信息
    MODULE_AUTHOR("fbx@GEC");
    MODULE_DESCRIPTION("the first module of drivers");
    MODULE_LICENSE("GPL");
    MODULE_VERSION("V1.0");

      1 #include<linux/module.h>
      2 #include<linux/kernel.h>
      3 #include<linux/cdev.h>
      4 #include<linux/fs.h>
      5 #include<linux/kdev_t.h>
      6 #include<linux/types.h>
      7 #include<linux/uaccess.h>
      8 #include<linux/string.h>
      9 #include<linux/ioport.h>
     10 #include<asm/io.h>
     11 
     12 #define  GPJ2CON_PA 0xe0200280
     13 #define  GPJ2DAT_PA 0xe0200280
     14 unsigned int *GPJ2CON_VA;
     15 unsigned int *GPJ2DAT_VA;
     16 struct cdev chrdev;
     17 struct resource *res;
     18 unsigned int TestMajor=0;
     19 unsigned int TestMinor=0;
     20 dev_t dev_no;
     21 int ret;
     22 
     23 int testopen(struct inode *inode,struct file *file)
     24 {
     25     unsigned int a = ioread32(GPJ2CON_VA);
     26     a |= 0x1111;
     27     iowrite32(a,GPJ2CON_VA);
     28     printk("cdev init
    ");
     29     return 0;
     30     
     31 }
     32 ssize_t testwrite(struct file *file, const char __user *usr, size_t len, loff_t *off)
     33 {
     34     unsigned int a;
     35     
     36     copy_from_user(&a,usr,len);
     37     iowrite32(a,GPJ2DAT_VA);
     38     
     39 
     40 }
     41 ssize_t testread(struct file *file, char __user *usr, size_t len, loff_t *off)
     42 {
     43     unsigned int a = ioread32(GPJ2DAT_VA);
     44     copy_to_user(usr,&a,len);
     45 
     46 
     47 }
     48 int testrelease(struct inode *inode, struct file *file)
     49 {
     50     printk("close
    ");
     51     return 0;
     52 
     53 }
     54 
     55 struct file_operations fops=
     56 {
     57     .owner=THIS_MODULE,
     58     .open = testopen,
     59     .write = testwrite,
     60     .read = testread,
     61     .release = testrelease,
     62 };
     63 static int __init test_init(void)
     64 {
     65     dev_no = MKDEV(TestMajor,TestMinor);
     66     if(dev_no>0)
     67     {
     68         ret = register_chrdev_region(dev_no,1,"chrdev_test");    
     69     }
     70     else
     71     {
     72         alloc_chrdev_region(&dev_no,0,1,"chrdev_test");
     73     }
     74     if(ret<0)
     75     {
     76         return ret;
     77     }
     78     cdev_init(&chrdev,&fops);
     79     chrdev.owner=THIS_MODULE;
     80     cdev_add(&chrdev,dev_no,1);
     81     res = request_mem_region(GPJ2CON_PA,8,"gpj2_led");
     82     GPJ2CON_VA = ioremap(GPJ2CON_PA,8);
     83     GPJ2DAT_VA = GPJ2CON_VA + 1;
     84     return 0;
     85 }
     86 
     87 static int __exit test_exit(void)
     88 {
     89     unregister_chrdev_region(dev_no,1);
     90     cdev_del(&chrdev);
     91     iounmap(GPJ2CON_VA);
     92     release_mem_region(GPJ2CON_PA,8);
     93     return 0;
     94 }
     95 
     96 module_init(test_init);
     97 module_exit(test_exit);
     98 
     99 
    100 MODULE_AUTHOR("FENG");
    101 MODULE_DESCRIPTION("the first module of char drivers");
    102 MODULE_LICENSE("GPL");
    103 MODULE_VERSION("V1.0");

    test.c 使一盏led循环点灭

     1 #include<stdio.h>
     2 #include <sys/stat.h>
     3 #include <fcntl.h>
     4 #include <errno.h>
     5 #include <unistd.h>
     6 #include <string.h>
     7 
     8 int main()
     9 {
    10 unsigned int ledconfig;
    11 char buf1[20];
    12 int fd = open("/dev/chrdev_test",O_RDWR);
    13 if(fd<0)
    14 perror("open() error!
    ");
    15 bzero(buf1,20);
    16 while(1)
    17 {
    18 read(fd,&ledconfig,4);
    19 ledconfig ^=0x1;
    20 write(fd,&ledconfig,4);
    21 sleep(1);
    22 }
    23 }
  • 相关阅读:
    2.19
    2.16sqlite
    2.14Android6
    2.12Android5
    2.11Android4
    2.09Android3
    2.08Android2
    2.06Android学习
    dpdk bond
    ContainerCreating
  • 原文地址:https://www.cnblogs.com/defen/p/5465962.html
Copyright © 2011-2022 走看看