使用io内存控制硬件点亮led灯

上传人:第*** 文档编号:32821106 上传时间:2018-02-12 格式:DOC 页数:20 大小:118.50KB
返回 下载 相关 举报
使用io内存控制硬件点亮led灯_第1页
第1页 / 共20页
使用io内存控制硬件点亮led灯_第2页
第2页 / 共20页
使用io内存控制硬件点亮led灯_第3页
第3页 / 共20页
使用io内存控制硬件点亮led灯_第4页
第4页 / 共20页
使用io内存控制硬件点亮led灯_第5页
第5页 / 共20页
点击查看更多>>
资源描述

《使用io内存控制硬件点亮led灯》由会员分享,可在线阅读,更多相关《使用io内存控制硬件点亮led灯(20页珍藏版)》请在金锄头文库上搜索。

1、 Linux 中控制 GPIO 点亮 LED 的方法有好几种。一种是使用内核提供的专门用来控制GPIO 的函数来点亮 LED,如:s3c2410_gpio_cfgpin(led_tablei, led_cfg_tablei);s3c2410_gpio_setpin(led_tablei, 0);一种是通过 IO 内存获取硬件地址从而控制 GPIO 来点亮 LED,如:void *ioremap(unsigned long phys_addr, unsigned long size);void ioumap(void *addr);这里主要介绍第二种点亮 LED 方式。1. 理论支撑1.1 IO

2、 内存分配和映射1.1.1 在使用 IO 内存之前首先分配 IO 内存区域。分配和撤销 IO 内存区域使用的函数如下:#include struct resource *request_mem_region(unsigned long start,unsigned long len,char *name);参数说明:start 分配内存起始地址len 分配内存长度返回 成功非 NULL,否则返回 NULL。相应的释放函数:void release_mem_region(unsigned long start,unsigned long len);1.1.2 在 linux 中不能使用实际的物理

3、地址,要对指定的物理地址进行操作必须先将物理地址映射到虚拟地址中。下面的函数就是实现物理地址到虚拟地址的映射:#include void *ioremap(unsigned long phys_addr, unsigned long size);参数说明:phys_addr 需要访问的物理内存(寄存器)的首地址size 内存区域大小返回与该段物理地址对应的虚拟地址相应的撤销映射关系的函数是:void ioumap(void *addr);1.1.3 使用 IO 内存时,request_mem_region 函数并不是必须的,该函数只是在内核中标志该内存区域已经分配出去,不能再进行分配出去。但是

4、,这不不是说别的驱动不能再使用该 IO 内存。至于能不能使用,分下面 2 种情况:1. 两个驱动都用 request_mem_region 分配相同的 IO 内存,则两个驱动只能有一个驱动可以使用。2. 两个驱动只有一个使用了 request_mem_region 函数,那么这两个驱动可以同时使用,并可以同时访问该 IO 内存。1.2 访问 IO 内存ioremap 函数的返回值可以直接当做指针(指向对应的物理内存(寄存器)地址)使用,但是这种使用方式不具有可移植性。使用下面的访问 IO 内存的专用函数符合可移植性要求。从 I/O 内存读取, 使用下列函数之一: unsigned int io

5、read8(void *addr); unsigned int ioread16(void *addr); unsigned int ioread32(void *addr);参数:addr 是从 ioremap 获得的地址(可能包含一个整数偏移量)返回值: 从给定 I/O 内存读取的到的值 相应的有一系列函数来写 I/O 内存: void iowrite8(u8 value, void *addr); void iowrite16(u16 value, void *addr); void iowrite32(u32 value, void *addr);参数:value 要写入 IO 内存值

6、addr 所要写入的 IO 内存地址2. 具体操作与实现2.1 只使用 ioremap 映射 GPIO 寄存器实现 LED 点亮内核模块代码(基于 mini2440 开发板的 4 个 LED) 如下:/*/#include #include #include volatile unsigned long virt, phys;/用于存放虚拟地址和物理地址volatile unsigned long *GPBCON, *GPBDAT, *GPBUP;/用与存放三个寄存器的地址void led_device_init(void) / 0x56000000 + 0xd0 包揽全所有的 IO 引脚寄存

7、器地址phys = 0x56000000; / 0x56000000=GPACON /在虚拟地址空间中申请一块长度为 0xd0 的连续空间/这样,物理地址 phys 到 phys+0xd0 对应虚拟地址 virt 到 virt+0xd0virt =(unsigned long)ioremap(phys, 0xd0); GPBCON = (unsigned long *)(virt + 0x10);/指定需要操作的三个寄存器的地址GPBDAT = (unsigned long *)(virt + 0x14); GPBUP = (unsigned long *)(virt + 0x18); /le

8、d 配置函数,这种是裸板控制寄存器的方式void led_configure(void) *GPBCON /GPB12 defaule*GPBCON |= (1 #include #include volatile unsigned long virt, phys;/用于存放虚拟地址和物理地址volatile unsigned long *GPBCON, *GPBDAT, *GPBUP;/用与存放三个寄存器的地址unsigned long reg;void led_device_init(void) phys = 0x56000000; /指定物理地址 0x56000000=GPACONvir

9、t =(unsigned long)ioremap(phys, 0xd0); GPBCON = (unsigned long *)(virt + 0x10);GPBDAT = (unsigned long *)(virt + 0x14); GPBUP = (unsigned long *)(virt + 0x18); void led_configure(void) /led 配置函数 /*GPBCON /GPB12 defaule/*GPBCON |= (1 #include #include #include volatile unsigned long virt, phys;/用于存放虚

10、拟地址和物理地址volatile unsigned long *GPBCON, *GPBDAT, *GPBUP;/用与存放三个寄存器的地址unsigned long reg;struct resource *led_resource;void led_device_init(void) phys = 0x56000000;virt =(unsigned long)ioremap(phys, 0xd0);GPBCON = (unsigned long *)(virt + 0x10);GPBDAT = (unsigned long *)(virt + 0x14); GPBUP = (unsigne

11、d long *)(virt + 0x18); void led_configure(void) /led 配置函数 /*GPBCON /GPB12 defaule/*GPBCON |= (1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #incl

12、ude #include #include volatile unsigned long virt, phys;volatile unsigned long *GPBCON, *GPBDAT, *GPBUP;unsigned long reg;struct resource *led_resource;dev_t my_major=0;/主设备号#define MY_DEVNAME leds /设备名称/设备结构体struct my_led struct cdev my_cdev;struct my_led *my_ledp;struct class *my_class;void led_de

13、vice_init(void) /0x56000000=GPACON 0x56000000 + 0xd0 包揽所有的 IO 引脚寄存器地址phys = 0x56000000;/在虚拟地址空间中申请一块长度为 0xd0 的连续空间/这样,物理地址 phys 到 phys+0xd0 对应虚拟地址 virt 到 virt+0xd0virt =(unsigned long)ioremap(phys, 0xd0);GPBCON = (unsigned long *)(virt + 0x10);GPBDAT = (unsigned long *)(virt + 0x14); GPBUP = (unsign

14、ed long *)(virt + 0x18); void led_configure(void) reg=ioread32(GPBCON);reg /outputiowrite32(reg,GPBCON);reg=ioread32(GPBUP);reg |= (1 4) return -EINVAL; reg=ioread32(GPBDAT);if(cmd=1)reg if(cmd=0)reg |= (1 my_cdev,my_ledp-my_cdev.owner=THIS_MODULE;cdev_add(/创建设备文件my_class=class_create(THIS_MODULE,my

15、_class);device_create(my_class,NULL,MKDEV(my_major,0),NULL,my_led%d,0);printk(hello led!n); return 0; fail_malloc:unregister_chrdev_region(devno,1);return 0;static void _exit test_exit(void) if(led_resource!=NULL)led_off(); iounmap(void *)virt);release_mem_region(phys,0xd0);cdev_del(kfree(my_ledp);unregister_chrdev_region(MKDEV(my_major,0),1);device_destroy(my_class,MKDEV(my_major,0);class_destroy(my_class

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 建筑/环境 > 工程造价

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号