Linux内核完全注释 阅读笔记:2.2、I/O端口寻址和访问控制方式
<p class="artical_littlestyle1">1、I/O端口和寻址</p><p style="text-indent: 2em;">CPU为了访问I/O接口控制器或控制卡上的数据和状态信息,需要首先指定它们的地址。这种地址就称为I/O端口地址或者简称端口。通常一个I/O控制器包含访问数据的数据端口、输出命令的命令端口和访问控制器执行状态的状态端口。端口地址的设置方法一般有两种:统一编址和独立编址。<br/></p><p style="text-indent: 2em;">端口统一编址的原理是把I/O控制器中的端口地址归入存储器寻址地址空间范围内。因此这种编址方式也称为存储器映像编址。CPU访问一个端口的操作与访问内存的操作一样,也使用访问内存的指令。端口独立编址的方法是把I/O控制器和控制卡的寻址空间单独作为一个独立的地址空间对待,称为I/O地址空间。每个端口有一个I/O地址与之对应,并且使用专门的I/O指令来访问端口。<br/></p><p style="text-indent: 2em;">IBM PC及其兼容微机主要使用独立编址方式,采用了一个独立的I/O地址空间对控制设备中的寄存器进行寻址和访问。使用ISA总线结构的传统PC机其I/O地址空间范围是0x000~0x3ff,有1024个I/O端口地址可供使用。各个控制器和控制卡所默认分配使用的端口地址范围如下表所示:<br/></p><p style="text-indent: 2em; text-align: center;">表2-1 I/O端口地址分配</p><table><tbody><tr class="firstRow"><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">端口地址范围</td><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">分配说明</td></tr><tr><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">0x000 --- 0x01F<br/></td><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">8237A DMA控制器1</td></tr><tr><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">0x020 --- 0x03F</td><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">8259A可编程中断控制器1</td></tr><tr><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">0x040 --- 0x05F</td><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">8253/8254A 定时计数器</td></tr><tr><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">0x060 --- 0x06F</td><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">8042键盘控制器</td></tr><tr><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">0x070 --- 0x07F</td><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">访问CMOS RAM/实时时钟RTC(Real Time Clock)端口</td></tr><tr><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">0x080 --- 0x09F</td><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">DMA页面寄存器访问端口</td></tr><tr><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">0x0A0 --- 0x0BF</td><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">8259A可编程中断控制器2<br/></td></tr><tr><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">0x0C0 --- 0x0DF</td><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">8237A DMA控制器2</td></tr><tr><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">0x0F0 --- 0x0FF</td><td style="border-width: 1px; border-style: solid; word-break: break-all;" width="534" valign="top">协处理器访问端口</td></tr><tr><td colspan="1" rowspan="1" style="border-width: 1px; word-break: break-all; border-style: solid;" valign="top">0x170 --- 0x177</td><td colspan="1" rowspan="1" style="border-width: 1px; word-break: break-all; border-style: solid;" valign="top">IDE硬盘控制器1</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x1F0 --- 0x1F7</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">IDE硬盘控制器0</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x278 --- 0x27F</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">并行打印机端口2</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x2F8 --- 0x2FF</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">串行控制器2</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x378 --- 0x37F</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">并行打印机端口1</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x3B0 --- 0x3BF</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">单色MDA显示控制器</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x3C0 --- 0x3CF</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">彩色CGA显示控制器</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x3D0 --- 0x3DF</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">彩色EGA/VGA显示控制器</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x3F0 --- 0x3F7</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">软盘控制器</td></tr><tr><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">0x3F8 --- 0x3FF</td><td colspan="1" rowspan="1" style="word-break: break-all; border-width: 1px; border-style: solid;" valign="top">串行控制器1<br/></td></tr></tbody></table><p style="text-indent: 2em; text-align: left;">另外,IBM PC机也部分的使用了统一编址方式。例如,CGA显示卡上显示内存的地址就直接占用了存储器地址空间0xB800 --- 0xBC00范围。因此若要让一个字符显示在屏幕上,可以直接使用内存操作指令往这个内存区域执行写操作。<br/></p><p style="text-indent: 2em; text-align: left;">对于使用EISA或者是PCI等总线结构的现代PC机,有64KB的I/O地址空间可供使用。在普通Linux系统下通过查看/proc/ioports文件可以得到相关控制器或设置使用的I/O地址范围,如下如所示:<br/></p><p style="text-align:center"><img src="/uploads/AilsonJack/2018.09.03/1535981030585281.png" onclick="preview_image('/uploads/AilsonJack/2018.09.03/1535981030585281.png')"/></p><p class="artical_littlestyle2">2、接口访问控制</p><p style="text-indent: 2em; text-align: left;">PC机I/O接口数据传输控制方式一般可采用:<span style="color: rgb(0, 112, 192);">程序循环查询方式</span>、<span style="color: rgb(0, 112, 192);">中断处理方式</span>和<span style="color: rgb(0, 112, 192);">DMA传输方式</span>。<br/></p><p style="text-indent: 2em; text-align: left;">循环查询方式是指CPU通过在程序中循环查询指定设备控制器中的状态来判断是否可以与设备进行数据交互。这种方式不需要过多的硬件支持,使用和编程都比较简单,但是特别耗费CPU宝贵的时间。因此在多任务操作系统中,除非等待时间极短或必须,否则就不应该使用这种方式。在Linux操作系统中,只有在设备或控制器能够立刻返回信息时,才会在很少的几个地方采用这种方式。<br/></p><p style="text-indent: 2em; text-align: left;">中断处理控制方式需要中断控制器的支持。在这种控制方式下,只有当I/O设备通过中断向CPU提出处理请求时,CPU才会暂时中断当前执行的程序转而去执行相应的I/O中断处理服务程序。当执行完该中断处理服务程序后,CPU又会继续执行刚才被中断的程序。在I/O控制器或设备发出中断请求时,CPU通过使用中断向量表(或中断描述表)来寻址相对应的中断处理服务程序的入口地址。因此采用中断控制方式时,要首先设置好中断向量表,并编制好相应的中断处理服务程序。Linux操作系统中,大多数设备I/O控制都采用中断处理方式。<br/></p><p style="text-indent: 2em; text-align: left;">直接存储器访问DMA(Direct Memory Access)方式用于I/O设备与系统内存间进行批量数据传送,整个操作过程需要使用专门的DMA控制器来进行而无需CPU插手。由于在传输过程中不需要软件介入,因此操作效率很高。在Linux操作系统中,软盘驱动程序使用中断和DMA方式配合来实现数据的传输工作。<br/></p>
你可能也喜欢:
暂无评论,要不要来个沙发
发表评论
JLink V9掉固件修复(灯不亮) 3Zephyr笔记2 - 在STM32F429上运行HelloWorld 2计算NandFlash要传入的行地址和列地址 1Linux MMC子系统 - 6.eMMC 5.1工作模式-设备识别模式 0Linux MMC子系统 - 5.eMMC 5.1工作模式-引导模式 0Linux MMC子系统 - 4.eMMC 5.1常用命令说明(2) 0
标签云
Linux嵌入式实用技巧ARM内核学习问题集合CC++编程语言阅读笔记汇编Linux内核完全注释Windows驱动开发计算机基础ARM11ARMv7-ASTM32IDESublimeLinux内核学习eMMCMMC子系统Ubuntu操作系统OfficeVMWareAPUEgccRTOS中断漫游世界随笔感悟开发工具软件应用编程VsCodearmccarmclang编译器ZephyrSPIJLink网卡驱动安装各种芯片库函数NFSμCOS内核sambaFlashUnix命令与脚本输入法Linux内核设计与实现gitRIFFWAVJATGFTPar8161安装centos有线上网μCGUI字库工程建立右键菜单网络文件系统Firefox百度NTFS文件系统CodeBlocksCentOS数据结构算法PhotoShop51KeilQTUltraEditscanfglibc宏定义UIDGID优先级娱乐天地SourceInsight磁盘扇区总线I2CPDFBComparePythonI2SFPUMakefileSWDCPUARP软件推荐FileZilla