- 1、本文档共20页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
使用IO内存控制硬件点亮LED灯
? Linux中控制GPIO点亮LED的方法有好几种。一种是使用内核提供的专门用来控制GPIO的函数来点亮LED,如:s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
????????????? s3c2410_gpio_setpin(led_table[i], 0);
一种是通过IO内存获取硬件地址从而控制GPIO来点亮LED,如:
void *ioremap(unsigned long phys_addr, unsigned long size);
void ioumap(void *addr);
这里主要介绍第二种点亮LED方式。
1. 理论支撑
1.1 IO内存分配和映射
1.1.1在使用IO内存之前首先分配IO内存区域。分配和撤销IO内存区域使用的函数如下:
?????? #include linux/ioport.h
?????? 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中不能使用实际的物理地址,要对指定的物理地址进行操作必须先将物理地址映射到虚拟地址中。下面的函数就是实现物理地址到虚拟地址的映射:
#include asm/io.h
void *ioremap(unsigned long phys_addr, unsigned long size);
参数说明:phys_addr 需要访问的物理内存(寄存器)的首地址
????????????? ? size?????? 内存区域大小
返回与该段物理地址对应的虚拟地址
??????
相应的撤销映射关系的函数是:
void ioumap(void *addr);
?
1.1.3使用IO内存时,request_mem_region函数并不是必须的,该函数只是在内核中标志该内存区域已经分配出去,不能再进行分配出去。但是,这不不是说别的驱动不能再使用该IO内存。至于能不能使用,分下面2种情况:
?????? 1. 两个驱动都用request_mem_region分配相同的IO内存,则两个驱动只能有一个驱动可以使用。
?????? 2. 两个驱动只有一个使用了request_mem_region函数,那么这两个驱动可以同时使用,并可以同时访问该IO内存。
?
1.2 访问IO内存
?????? ioremap函数的返回值可以直接当做指针(指向对应的物理内存(寄存器)地址)使用,但是这种使用方式不具有可移植性。使用下面的访问IO内存的专用函数符合可移植性要求。
?
从 I/O 内存读取, 使用下列函数之一:
unsigned int ioread8(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内存值
????? addr 所要写入的IO内存地址
?
2. 具体操作与实现
2.1只使用ioremap映射GPIO寄存器实现LED点亮
??????
内核模块代码(基于mini2440开发板的4个LED) 如下:
/*************************************************************************/
#include linux/module.h
#include linux/init.h
#include asm/io.h
?
volatile unsigned long virt, phys;//用于存放虚拟地址和物理地址
volatile unsigned long *GPBCON, *GPBDAT, *GPBUP;//用与存放三
文档评论(0)