[ARM笔记]设备IO端口和IO内存的访问
设备通常会提供一组寄存器来用于控制设备、读写设备和获取设备状态,即控制寄存器、数据寄存器和状态寄存器。这些寄存器可能位于IO空间,也可能位于内存空间。当位于IO空间时,通常被称为IO端口,位于内存空间时,对应的内存空间成为IO内存。
1. Linux IO端口和IO内存访问接口
1.1 IO端口
在Linux设备驱动中,应使用Linux内核提供的函数来访问定位于IO空间的端口,这些函数包括如下几种:
(1)读写字节端口(8位宽)
unsigned inb(unsigned port);
void outb(unsigned char byte , unsigned port);
(2)读写字端口(16位宽)
unsigned inw(unsigned port);
void outw(unsigned char byte , unsigned port);
(3)读写长字端口(32位宽)
unsigned inl(unsigned port);
void outl(unsigned char byte , unsigned port);
(4)读写一串字
void insw(unsigned port , void *addr , unsigned long count);
void outsw(unsigned port , void *addr , unsigned long count);
(5)读写一串长字
void insl(unsigned port , void *addr , unsigned long count);
void outsl(unsigned port , void *addr , unsigned long count);
上述各函数中IO端口号port的类型高度依赖于具体的硬件平台,因此,只是写出了unsigned。
1.2 IO内存
在内核中访问IO内存之前,需首先使用ioremap()函数将设备所处的物理地址映射到虚拟地址。ioremap的原型如下:
void *ioremap(unsigned long offset , unsigned long size);
ioremap()与vmalloc()类似,也需要建立新的页表,但是它并不进行vmalloc()中所执行的内存分配行为。ioremap()返回一个特殊的虚拟地址,该地址可用来存取特定的物理地址范围。通过ioremap()获得的虚拟地址应该被iounmap()函数释放,其原型为:
void iounmap(void *addr);
在设备的物理地址被映射到虚拟地址之后,尽管可以直接通过指针访问这些地址,但是可以使用Linux内核的如下一组函数来完成设备内存映射的虚拟地址的读写,这些函数如下所示。
(1)读IO内存
unsigned int ioread8(void *addr);
unsigned int ioread16(void *addr);
unsigned int ioread32(void *addr);
与上述函数对应的较早版本的函数为(这些函数在Linux2.6中仍然被支持):
unsigned readb(address);
unsigned readw(address);
unsigned readl(address);
(2)写IO内存
void iowrite8(u8 value , void *addr);
void iowrite16(u16 value , void *addr);
void iowrite32(u32 value , void *addr);
与上述函数对应的较早版本的函数为(这些函数在Linux2.6中仍然被支持):
unsigned writeb(address);
unsigned writew(address);
unsigned writel(address);
(3)读一串IO内存
void ioread8_rep(void *addr , void *buf , unsigned long count);
void ioread16_rep(void *addr , void *buf , unsigned long count);
void ioread32_rep(void *addr , void *buf , unsigned long count);
(4)写一串IO内存
void iowrite8_rep(void *addr , void *buf , unsigned long count);
void iowrite16_rep(void *addr , void *buf , unsigned long count);
void iowrite32_rep(void *addr , void *buf , unsigned long count);
(5)复制IO内存
void memcpy_fromio(void *dest , void *source , unsigned int count);
void memcpy_toio(void *dest , void *source , unsigned int count);
(6)设置IO内存
void memset_io(void *addr , u8 value , unsigned in
- Linux嵌入式系统开发平台选型探讨(11-09)
- 基于ARM体系的嵌入式系统BSP的程序设计方案(04-11)
- 在Ubuntu上建立Arm Linux 开发环境(04-23)
- 达芬奇数字媒体片上系统的架构和Linux启动过程(06-02)
- SQLite嵌入式数据库系统的研究与实现(02-20)
- 革新2410D开发板试用手记(04-21)