linux外设内存访问,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

#include

#include

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

2 #include

3 #include

4 #include

5 #include

6 #include

7 #include

8 #include

9 #include

10 #include

11

12 #define GPJ2CON_PA 0xe0200280

13 #define GPJ2DAT_PA 0xe0200280

14 unsigned int *GPJ2CON_VA;15 unsigned int *GPJ2DAT_VA;16 structcdev chrdev;17 struct resource *res;18 unsigned int TestMajor=0;19 unsigned int TestMinor=0;20 dev_t dev_no;21 intret;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 inta;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 returnret;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

2 #include

3 #include

4 #include

5 #include

6 #include

7

8 intmain()9 {10 unsigned intledconfig;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 }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值