Linux内核访问外设I/O资源的方式

转载 2011年07月13日 17:37:16

我们知道默认外设I/O资源是不在Linux内核空间中的(如sram或硬件接口寄存器等),若需要访问该外设I/O资源,必须先将其地址映射到内核空间中来,然后才能在内核空间中访问它。
     Linux内核访问外设I/O内存资源的方式有两种:动态映射(ioremap)和静态映射(map_desc)。
     一、动态映射(ioremap)方式
     动态映射方式是大家使用了比较多的,也比较简单。即直接通过内核提供的ioremap函数动态创建一段外设I/O内存资源到内核虚拟地址的映射表,从而可以在内核空间中访问这段I/O资源。
     Ioremap宏定义在asm/io.h内:
     #define ioremap(cookie,size)            __ioremap(cookie,size,0)
     __ioremap函数原型为(arm/mm/ioremap.c):
     void __iomem * __ioremap(unsigned long phys_addr, size_t size, unsigned long
     flags);
     phys_addr:要映射的起始的IO地址
     size:要映射的空间的大小
     flags:要映射的IO空间和权限有关的标志
     该函数返回映射后的内核虚拟地址(3G-4G). 接着便可以通过读写该返回的内核虚拟地址去访问之这段I/O内存资源。
     举一个简单的例子: (取自s3c2410的iis音频驱动)
     比如我们要访问s3c2410平台上的I2S寄存器, 查看datasheet 知道IIS物理地址为0x55000000,
     我们把它定义为宏S3C2410_PA_IIS,如下:
     #define S3C2410_PA_IIS     (0x55000000)
     若要在内核空间(iis驱动)中访问这段I/O寄存器(IIS)资源需要先建立到内核地址空间的映射:
     our_card->regs = ioremap(S3C2410_PA_IIS, 0x100);
     if (our_card->regs == NULL) {
     err = -ENXIO;
     goto exit_err;
     }
     创建好了之后,我们就可以通过readl(our_card->regs )或writel(value, our_card->regs)等IO接口函数去访问它。
     二、静态映射(map_desc)方式
     下面重点介绍静态映射方式即通过map_desc结构体静态创建I/O资源映射表。
     内核提供了在系统启动时通过map_desc结构体静态创建I/O资源到内核地址空间的线性映射表(即page table)的方式,这种映射表是一种一一映射的关系。程序员可以自己定义该I/O内存资源映射后的虚拟地址。创建好了静态映射表,在内核或驱动中访问该I/O资源时则无需再进行ioreamp动态映射,可以直接通过映射后的I/O虚拟地址去访问它。
     下面详细分析这种机制的原理并举例说明如何通过这种静态映射的方式访问外设I/O内存资源。
     内核提供了一个重要的结构体struct machine_desc ,这个结构体在内核移植中起到相当重要的作用,内核通过machine_desc结构体来控制系统体系架构相关部分的初始化。
     machine_desc结构体的成员包含了体系架构相关部分的几个最重要的初始化函数,包括map_io,init_irq, init_machine以及phys_io , timer成员等。
     machine_desc结构体定义如下:

 

用户可以在定义Machine_desc结构体时指定Map_io的接口函数,这里以s3c2410平台为例。
     s3c2410 machine_desc结构体定义如下:
     /* arch/arm/mach-s3c2410/Mach-smdk2410.c */
     MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
     * to SMDK2410 */
     /* Maintainer: Jonas Dietsche */
     .phys_io     = S3C2410_PA_UART,
     .io_pg_offst     = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
     .boot_params     = S3C2410_SDRAM_PA + 0x100,
     .map_io         = smdk2410_map_io,
     .init_irq     = s3c24xx_init_irq,
     .init_machine     = smdk2410_init,
     .timer         = &s3c24xx_timer,
     MACHINE_END
     如上,map_io被初始化为smdk2410_map_io。smdk2410_map_io即我们自己定义的创建静态I/O映射表的函数。在Porting内核到新开发板时,这个函数需要我们自己实现。
     (注:这个函数通常情况下可以实现得很简单,只要直接调用iotable_init创建映射表就行了,我们的板子内核就是。不过s3c2410平台这个函数实现得稍微有点复杂,主要是因为它将要创建IO映射表的资源分为了三个部分(smdk2410_iodesc, s3c_iodesc以及s3c2410_iodesc)在不同阶段分别创建。这里我们取其中一个部分进行分析,不影响对整个概念的理解。)
     S3c2410平台的smdk2410_map_io函数最终会调用到s3c2410_map_io函数。
     流程如下:s3c2410_map_io -> s3c24xx_init_io -> s3c2410_map_io
     下面分析一下s3c2410_map_io函数:
     void __init s3c2410_map_io(struct map_desc *mach_desc, int mach_size)
     {
     /* register our io-tables */
     iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc));
     ……
     }
     iotable_init内核提供,定义如下:
     /*
     * Create the architecture specific mappings
     */
     void __init iotable_init(struct map_desc *io_desc, int nr)
     {
     int i;
     for (i = 0; i   nr; i++)
     create_mapping(io_desc + i);
     }

相关文章推荐

[转]Linux内核访问外设I/O资源的方式--待整理

Linux内核访问外设I/O资源的方式 Author: DongasDate: 08-08-02 我们知道默认外设I/O资源是不在Linux内核空间中的(如sram或硬件接口寄存器等),若需要访问该外...

Linux内核访问外设I/O资源的方式

Linux内核访问外设I/O资源的方式我们知道默认外设I/O资源是不在Linux内核空间中的(如sram或硬件接口寄存器等),若需要访问该外设I/O资源,必须先将其地址映射到内核空间中来,然后才能在内...

Linux内核访问外设I O资源的方式

转自: http://blog.csdn.net/woshixingaaa/archive/2011/05/15/6421954.aspx  首先介绍一下I/O端口和I/O内存。 1. I/...

Linux内核访问外设I/O资源的方式-静态映射(map_desc)方式

Linux内核访问外设I/O资源的方式 Author: Dongas Date: 08-08-02 我们知道默认外设I/O资源是不在Linux内核空间中的(如sram或硬件接口寄存器等),若需要...
  • swymomo
  • swymomo
  • 2012年01月09日 10:06
  • 292

Linux内核访问外设I/O资源的方式-静态映射(map_desc)方式

Linux内核访问外设I/O资源的方式-静态映射(map_desc)方式

嵌入式Linux之我行——内核访问外设I/O资源的方式

嵌入式Linux之我行,主要讲述和总结了本人在学习嵌入式linux中的每个步骤。一为总结经验,二希望能给想入门嵌入式Linux的朋友提供方便。如有错误之处,谢请指正。 共享资源,欢迎转载:htt...

内核访问外设I/O资源的方式

我们知道默认外设I/O资源是不在Linux内核空间中的(如sram或硬件接口寄存器等),若需要访问该外设I/O资源,必须先将其地址映射到内核空间中来,然后才能在内核空间中访问它。Linux内核访问外设...

内核访问外设I/O资源的方式

我们知道默认外设I/O资源是不在Linux内核空间中的(如sram或硬件接口寄存器等),若需要访问该外设I/O资源,必须先将其地址映射到内核空间中来,然后才能在内核空间中访问它。Linux内核访问外设...

内核访问外设I/O资源方式

内核访问外设I/O资源方式通常有两种静态映射map_desc、动态映射ioremap
  • liaozc
  • liaozc
  • 2011年07月21日 11:20
  • 1209

Linux内核访问外设I/O--动态映射(ioremap)和静态映射(map_desc)

【转】(转)Linux内核访问外设I/O资源的方式-静态映射(map_desc)方式 Linux内核访问外设I/O资源的方式 Author: Dongas Date: 08-08-02 ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux内核访问外设I/O资源的方式
举报原因:
原因补充:

(最多只允许输入30个字)