每块处理器在出厂的时候已经固化好其寄存器的默认值,这些值决定了处理器上电时刻的行为。程序计数器的默认值决定了处理器从哪一个具体的地址去获取第一条需要执行的指令。假设程序计数器上电时的默认值是0xFFFF0000。那么0xFFFF0000对应于哪个具体存储器设备呢?假设第一条指令是放在闪存中,处理器如何知道0xFFFF0000地址所对应的的指令是从闪存中获取呢?
对于处理器来说,不论它的总线上挂接的是闪存、内存还是硬盘,它在启动时一无所知,我们需要通过硬件设计来告诉它存储第一条指令的外设,也就是说处理器的第一条执行指令的地址是通过硬件来实现的。处理器一启动,就会从0xFFFF0000处读取指令,内存控制器就会产生相应的地址空间片选信号,以使能位于0xFFFF0000地址处的存储器件。如果希望0xFFFF0000对应闪存的第一个字节,那么就需要通过硬件设计,将闪存的片选信号与处理器的0xFFFF0000地址所对应的片选信号相连,且通过恰当的地址线使得闪存的第一个字节就在0xFFFF0000处。也就是说,硬件设计需要完成地址与外设间的映射。
嵌入式产品中除了中央处理单元和内存两大部件外,另外一大部件就是外设(peripheral)。外设是一个非常广泛的概念,既可以集成在微控制器内(片内外设),也可以挂接在处理器总线上的外部芯片(片外外设)。外设的种类很多,常见的有:用于实现以太网通信的外设;用于实现串口通信的外设;用于实现USB通信的外设;用于实现存储的闪存外设;用于实现视频采集的外设等等。中央处理器与外部通信被称为输入与输出(input/output),简称I/O。
外设也像内存一样通过地址进行区分,但他们的地址称为I/O端口(I/O Port)。每一个外设在处理器地址空间中占用不同的I/O端口,处理器可以通过不同的I/O端口实现与外设通信。I/O端口所在的空间被称为I/O空间,各种架构的处理器的I/O空间设计形式不一样。第一种I/O空间设计是将之设计成独立于内存所在的空间,这种设计下,读写I/O需要使用与存取内存不一样的指令。对于I/O的操作不能像操作内存那样直接使用C语言中的指针完成,需要调用相应的函数来完成。另一种I/O空间设计是将之设计成与内存在同一个地址空间中,也就是所谓的采用统一编址,它也被称为内存映射I/O空间。从编程的角度来看,内存映射I/O空间端口操作与访问内存完全一样,像ARM处理器就采用内存映射I/O空间。
更多的精彩内容请关注微信公众号“Linux嵌入式”