关于嵌入式开发中IO的应用

时间:2021-07-21 09:42:52

ioremap,iowrite,ioread,request_mem_region

 一。I/O使用前准备工作

首先要搞清楚一个概念,就是I/O memory是什么。Memory-mapped I/O uses the same address space to address both memory and I/O devices. 意味着,寻址I/O的寄存器和内存(memory)是公用内存中的地址的。所以,在cpu发出寻址指令时,可能是寻找物理的RAM也可能指向IO设备。因此,在内存中要保留一部分内存以供IO硬件所使用。

I/O内存的区域需要再使用前进行分配,因此涉及到函数struct resource *request_mem_region(unsigned long start, unsigned long len,char *name);

是将一块分配从start的地址开始的len Bytes的区域。成功返回non-null指针。

释放空间使用void release_mem_region(unsigned long start, unsigned long len);

 

在使用前,分配I/O memory并不是唯一需要的步骤,我们需要确认内核能使用I/o memory。因此需要先通过ioremap进行寻址。此函数设计目的就是讲虚拟地址分配给I/o memory的区域。其返回值不应该直接通过取值符*进行使用,而应该通过内核的引用函数进行操作。void *ioremap(unsigned long phys_addr, unsigned long size);

 

2。I/O的调用

调用其实是通过对返回地址(其实就是寄存器)输出或读取值。

读取: unsigned int ioread8(void *addr);unsigned int ioread16(void *addr);unsigned int ioread32(void *addr);

输出: void iowrite8(u8 value, void *addr); void iowrite16(u16 value, void *addr); void iowrite32(u32 value, void *addr);

还有块操作的 :void ioread8_rep(void *addr, void *buf, unsigned long count);等等。

实验1:不使用分配函数,看是否能进行IO访问。

 

因此,对于ARM寄存器,如gpio要用到的DATA_REG数据寄存器,物理地址为0x41200000和三态寄存器TRP_PHA,物理地址为0x41200004,可以分配一个连续的空间。内存每个地址对应一个Byte,因为Arm寄存器为32bit即0x41200000-0x41200003都为DATA_REG,接下去为三态寄存器,ioremap可以直接从初始地址分配8个bytes。也就是

 unsigned long io_base_addr=ioremap(0x41200000,8);

 

实验2,对指定io口寻址,查看对应寄存器的值是否改变。 

 

 

参考:http://www.makelinux.net/ldd3/chp-9-sect-4

  https://en.wikipedia.org/wiki/Memory-mapped_I/O