微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > [ARM笔记]设备IO端口和IO内存的访问

[ARM笔记]设备IO端口和IO内存的访问

时间:12-05 来源:互联网 点击:

t count);

1.3 把IO端口映射到内存空间

void *ioport_map(unsigned long port , unsigned int count);

通过这个函数,可以把port开始的count个连续的IO端口重映射为一段“内存空间”。然后就可以在其返回的地址上像访问IO内存一样访问这些IO端口。当不再需要这种映射时,需要调用下面的函数来撤销。

void ioport_unmap(void *addr);

实际上,分析ioport_map()的源代码可发现,映射到内存空间行为实际上是给开发人员制造的一个“假象”,并没有映射到内核虚拟地址,仅仅是为了让工程师可使用统一的IO内存访问接口访问IO端口。

2. 申请与释放设备IO端口和IO内存

2.1 IO端口申请

Linux内核提供了一组函数用于申请和释放IO端口。

struct resource *request_region(resource_size_t start, resource_size_t n, const char *name);

这个函数向内核申请了n个端口,这些端口从first开始,name参数为设备的名称。如果分配成功返回非NULL,失败,则返回NULL。

当用request_region()申请的IO端口使用完成后,应当使用release_region()函数将它们还给系统,这个函数的原型如下:

void release_region(resource_size_t start , resource_size_t n);

2.2 IO内存申请

Linux内核提供了一组函数用于申请和释放IO内存的范围。

struct resource *request_mem_region(resource_size_t start, resource_size_t n, const char *name, const char *name);

这个函数向内核申请n个内存地址,这些地址从first开始,name参数为设备的名称。如果分配成功返回值是非NULL,如果失败,返回NULL。

当用request_mem_region()申请的IO内存使用完成后,应当使用release_region()函数将它们还给系统,这个函数的原型如下:

void release_region(resource_size_t start , resource_size_t n);

上述request_region()和release_mem_region()都不是必须的,但建议使用。其任务是检查申请的资源是否可用,如果可用则申请成功,并标志为已经使用,其他驱动想再次申请该资源就会失败。

查看内核源码可知,request_region()和request_mem_region()调用的函数是一样的,只是传入参数的不同。

#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name))

#define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name))

3. 设备IO端口和IO内存访问流程

IO端口访问的一种途径是直接使用IO端口操作函数:在设备打开或驱动模块被加载时申请IO端口区域,之后使用inb()、outb()等进行端口访问,最后,在设备关闭或驱动被卸载时释放IO端口范围。

___________________________

| |

| request_region() | 在设备驱动模块加载或open()函数中进行

|__________________________ |

|

___________________________

| |

| inb()、outb()等 | 在设备驱动初始化、write()、read()、iotcl()等函数中进行

|__________________________ |

|

___________________________

| |

| release_region()等 | 在设备驱动模块卸载或release()函数中进行

|__________________________ |

IO端口的访问流程(不映射到内存空间)

IO端口访问的另一种途径是将IO端口映射为内存进行访问:在设备打开或驱动模块被加载时,申请IO端口区域并使用ioport_map()映射到内存,之后使用IO内存的函数进行端口访问,最后,在设备关闭或驱动被卸载时释放IO端口并释放映射。整个流程如下图所示:

___________________________

| |

| request_region()等 | \

|__________________________ | \

| \ 在设备驱动模块加载或open()函数中进行

___________________________ /

| | /

| ioport_map()等 |

|__________________________ |

|

___________________________

| |

| ioread8、ioread16、 | 在设备驱动初始化、write()、read()、ioctl等函数中调用

| ioread32、iowrite8等 |

|__________________________ |

|

___________________________

| |

| ioport_unmap() 

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top