【问题标题】:How to acess the physical address from linux kernel space?如何从linux内核空间访问物理地址?
【发布时间】:2014-04-27 01:35:07
【问题描述】:

我正在研究 rasberry pi 板。是否可以直接访问GPIO物理地址 从 linux 内核空间使用 inb(), outb()... ?.如果是怎么办?

GPIO寄存器地址链接 第 90 页 http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf

谢谢

【问题讨论】:

标签: linux linux-kernel embedded linux-device-driver embedded-linux


【解决方案1】:

是的。

  1. 使用ioremap 获取相关寄存器的虚拟地址映射设置
  2. 使用readl/writel 操作物理内存。

请注意 ARM 处理器会在未对齐访问时出错。 Linux 可以优雅地处理这个问题,但会降低性能。

小例子:

void __iomem *regs = ioremap(0xdead0000, 4);

pr_info("0xdead0000: %#x\n", readl(regs));

iounmap(regs);

【讨论】:

  • 不做ioremap()有没有可能访问物理地址。
  • 在 MMU 系统上,按照设计,您不能直接访问物理地址空间。也就是说,许多架构为 SoC 中的整个 IO 空间设置了映射,以供早期代码使用。该偏移量通常在arch/arm/mach-$YOUR_ARCH/include/mach/hardware.h 中定义。
【解决方案2】:

分配 I/O 内存并不是访问该内存之前唯一需要的步骤。您还必须确保内核可以访问此 I/O 内存。所以必须先建立一个映射。这就是ioremap函数的作用。

void *ioremap(unsigned long phys_addr, unsigned long size);
void *ioremap_nocache(unsigned long phys_addr, unsigned long size);
void iounmap(void * addr);

该函数专门用于为 I/O 内存区域分配虚拟地址。

获取 I/O 内存的正确方法是通过为此目的提供的一组函数(通过 定义)。

要从 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);

举个例子:

void __iomem *io = ioremap(PHYSICAL_ADDRESS, SZ_4K);
iowrite32(value, io);

另一方面,您可以在用户空间中这样做:

static volatile uint32_t *gpio = NULL;
int   fd;

if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0) return -1; 
gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE);
if ((int32_t)gpio == -1) return -1; 

*(gpio + n) = value;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-04
    • 2012-08-15
    • 2012-10-03
    • 2011-12-15
    • 1970-01-01
    • 2017-04-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多