linux--物理地址到虚拟地址映射,ioremap()函数

CPU对I/O端口的编制方式

设备通常会提供一组寄存器来用于控制设备、读写设备和获取设备状态,即控制寄存器、数据寄存器和状态寄存器。这些寄存器可能位于 I/O 空间,也可能位于内存空间。当位于 I/O 空间时,通常被称为 I/O 端口,位于内存空间时,对应的内存空间被称为 I/O 内存。

  1. I/O映射方式:X86处理器为外设实现了单独的地址空间,称IO地址,通过IO指令来访问;
  2. 内存映射方式:ARM、PowerPC等通常只实现一个物理地址空间,外设I/O端口为内存的一部分,CPU可以访问内存单元那样访问IO端口。

物理地址到虚拟地址的映射

内存管理单元(MMU)通常以页为单位进行处理,而不是字节,ioremap函数也同样属于页映射。

在内核中访问 I/O 内存之前,需首先使用 ioremap()函数将设备所处的物理地址映射到虚拟地址。ioremap()的原型如下:
 

void *ioremap(unsigned long offset, unsigned long size);

参数:

  1. 物理地址
  2. 要映射的空间的大小

返回值:页映射,返回虚拟地址

※同一物理地址可以多次ioremap映射,分配的虚拟空间地址各部相同,iounmap互补影响。

ioremap()与 vmalloc()类似,也需要建立新的页表,但是它并不进行 vmalloc()中所执行的内存分配行为。ioremap()返回一个特殊的虚拟地址,该地址可用来存取特定的物理地址范围。通过 ioremap()获得的虚拟地址应该被 iounmap()函数释放,其原型如下:
 

void iounmap(void * addr);

参数:

  1. addr是ioremap生成的虚拟地址

简单实现的驱动代码:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/io.h>

//用于存放虚拟地址和物理地址
unsigned int virt_addr,phys_addr;
//用户存放三个寄存器的地址
unsigned int *GPL2CON,*GPL2DAT,*GPL2PUD;

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("SZA");

static void gpl2_device_init(void)
{
	phys_addr = 0x11000100;
	GPL2CON = (unsigned int*)ioremap(phys_addr,0x01);
	GPL2DAT = GPL2CON + 1;
	GPL2PUD = GPL2CON + 2;
	printk("virt_addr is %x \n",virt_addr);
	printk("GPL2CON is %x \n",(unsigned int)GPL2CON);
	printk("GPL2DAT is %x \n",(unsigned int)GPL2DAT);
	printk("GPL2PUD is %x \n",(unsigned int)GPL2PUD);
}

static void gpl2_configure(void)
{
	*GPL2CON &= 0xFFFFFFF1;
	*GPL2CON |= 0x00000001;
	*GPL2PUD |=0x0003;
}

static void gpl2_on(void)
{
	*GPL2DAT |= 0x01;
}

static void gpl2_off(void)
{
	*GPL2DAT &= 0xfe;
}

static int led_gpl2_init(void)
{
	printk("init!\n");
	gpl2_device_init();//实现IO内存的映射
	gpl2_configure();//配置GPL2为输出模式
	gpl2_on();
	printk("led gpl2 open\n");
	return 0;
}


static void led_gpl2_exit(void)
{
	printk("exit!\n");
	gpl2_off();
	
	printk("led gpl2 close\n");
}

module_init(led_gpl2_init);
module_exit(led_gpl2_exit);

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值