io内存使用方法

 本文介绍linux下io内存的使用方法,所举例子已经在开发板中成功实验过。

设备通常会提供一组寄存器来用于控制、读写设备和获取设备状态,即控制寄存器,数据寄存器,状态寄存器。
这些寄存器可能位于IO空间,也可能位于内存空间,
当位于IO空间时,称为IO端口
当位于内存空间时,称为IO内存。
嵌入式处理器的寄存器一般都位于内存空间。

以下函数需要包含头文件#include<asm/io.h>  #include<linux/ioport.h>
1、IO内存申请
 struct resource *request_mem_region(unsigned long start,unsigned long len,char *name);
 该函数向内存申请len个内存地址,从start开始,设备名称为name
 分配成功返回非NULL(NULL=0),失败返回NULL
 request_mem_region()申请的内存需要使用release_mem_region()释放
2、IO内存映射
   在内核中访问IO之前,需先将设备所处的物理地址映射到虚拟地址
 void *ioremap(unsigned long offset,unsigned long size)
 offset要映射的起始地址
 size要映射的大小
   ioremap()与vmalloc()类似,也需要建立新的页表,但是它不进行vmalloc()中所执行的内存分配
   ioremap()返回一个特殊的虚拟地址,该地址可用来存取特定的物理地址范围
   ioremap()函数映射的地址需要使用iounmap()函数释放
3、释放IO内存的映射
 void iounmap(void *addr)
4、IO内存释放
 void release_mem_region(unsigned long start,unsigned long len)
注:request_mem_region()和release_mem_region()函数不是必须的,其任务是检查申请的资源是否可用
    如果可用则申请成功,并标志为已经使用,其他驱动再次申请该资源时就会失败。
    这样能保证资源的安全和正确使用。

linux内核下提供对IO内存的操作函数:
读io内存:
 unsigned int ioread8(void *addr);
 unsigned int ioread16(void *addr);
 unsigned int ioread32(void *addr);
写io内存:
 unsigned int iowrite8(u8 value,void *addr);
 unsigned int iowrite16(u8 value,void *addr);
 unsigned int iowrite32(u8 value,void *addr);
读一串io内存:
 unsigned int ioread8_rep(void *addr,void *buf,unsigned long count);
 unsigned int ioread16_rep(void *addr,void *buf,unsigned long count);
 unsigned int ioread32_rep(void *addr,void *buf,unsigned long count);
写一串io内存:
 unsigned int iowrite8_rep(void *addr,const void *buf,unsigned long count);
 unsigned int iowrite16_rep(void *addr,const void *buf,unsigned long count);
 unsigned int iowrite32_rep(void *addr,const void *buf,unsigned long count);
复制io内存:
 void memcpy_fromio(void *dest,void *source,unsigned int count);
 void memcpy_toio(void *dest,void *source,unsigned int count);
设置io内存:
 void *memset_io(void *addr,u8 value,unsigned int count);
=========================================================
使用例子:以hi3515控制两个led灯为例
#include<asm/io.h>
#include<linux/ioport.h>
#include...

static unsigned int gpio3_addr_base;/*端口方向,数据设置寄存器*/
static unsigned int reg_virtual_addr;/*端口功能选择寄存器*/

static int xxx_init(void)
{
 unsigned char led_dir;
 unsigned char led_data[2];
 int ret1,ret2;
/*申请内存*/
 ret1 = request_mem_region(0x200f0000,0x1000,"reg_led");
 if(NULL == ret1)
 {
  printk("get reg virtaddr region failed!");
  return -1;
 }
 ret2 = request_mem_region(0x20180000,0x1000,"my_led");
 if(NULL == ret2)
 {
  printk("get led virtaddr region failed!");
  return -1;
 }
/*映射内存*/
 reg_virtual_addr = ioremap(0x200f0000,0x1000);
 gpio3_addr_base = ioremap(0x20180000,0x1000);
/*内存操作*/
 iowrite8(0x1,reg_virtual_addr+0x08);
 iowrite8(0x1,reg_virtual_addr+0x0c);

 iowrite8(0x0,gpio3_addr_base+0x400);/*设置为输入*/
 led_data[0] = ioread8(gpio3_addr_base+0x4);/*读取gpio3_0管脚*/
 led_data[1] = ioread8(gpio3_addr_base+0x8)>>1;/*读取gpio3_1管脚*/

 iowrite8(0x3,gpio3_addr_base+0x400);/*设置为输出*/
 iowrite8(0x0,gpio3_addr_base+0x4);/*设置gpio3_0管脚,led1亮*/
 iowrite8(0x0,gpio3_addr_base+0x8);/*设置gpio3_1管脚,led2亮*/

 return 0; 
}

static void xxx_exi(void)
{
 iounmap(reg_virtual_addr);
 iounmap(gpio3_virtual_base);
 release_mem_region(0x200f0000,0x1000);
 release_mem_region(0x20180000,0x1000);
}
...
/*注意:申请和释放的内存大小一定要一样,否则会出现不可预知的错误*/
====================================================

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值