跳至主要内容

【转】《嵌入式系统》读书笔记(1):ARM体系结构(上)

文章说明:calmarrow(lqm)读毛德操的《嵌入式系统》所做笔记
文章引自:http://piaoxiang.cublog.cn

 
    学习《嵌入式系统��采用公开源代码和StrongARM/XScale处理器》一书,对ARM核的体系结构有了一个比较全面而且深入的认识,纠正了以前不少错误的认识。现在以ARM核的体系结构为主线,按照理解的先后顺序,结合自己的实际应用经验,总结相关知识点,以获得更大的提高。

什么是体系结构?

    所谓"体系结构",也可以称为"系统结构",是指程序员在为特定处理器编制程序时所"看到"从而可以在程序中使用的资源及其相互间的关系。
 
    体系结构最为重要的就是处理器所提供的指令系统和寄存器组。指令系统分为CISC(Complex Instruction Set Computer,复杂指令集计算机)和RISC(Reduced Instruction Set Computer,精简指令集计算机)。其中,嵌入式系统中的CPU往往是RISC结构的,至于原因,在后面总结完CISC和RISC之后会给出。ARM核就是RISC结构,由于其在嵌入式系统占的比重比较大,所以ARM几乎成为RISC的代名词了。寄存器组与采用的指令系统是密切相关的,从这一点上考虑,体系结构中最为重要的应该就是指令系统了。
 
    在体系结构中,还有存储器结构。现在有两种:冯・诺依曼结构和哈佛结构。传统的计算机采用冯・诺依曼结构,也称为普林斯顿结构,是一种将程序指令存储器和数据存储器合并在一起的存储器结构。主要特点是:程序和数据共用一个存储空间;程序指令存储地址和数据存储地址指向同一个存储器的不同物理位置;采用单一的地址及数据总线;程序指令和数据的宽度相同。这样,处理器在执行指令时,必须从存储器中取出指令解码,再取操作数执行运算,即使单条指令也要耗费几个甚至几十个周期,那么,在高速运算的时候,在传输通道上会出现瓶颈效应。目前使用冯・诺依曼结构的MPU和MCU有很多,如Intel 8086、ARM公司的ARM7、MIPS公司的MIPS处理器等。Harvard结构是一种将程序指令存储和数据存储分开的存储器结构,Harvard结构是一种并行体系结构,主要特点是:程序和数据存储在不同的存储空间中,即程序存储器和数据存储器是两个相互独立的存储器,每个存储器独立编址、独立访问。与两个存储器相对应的是系统中的4套总线:程序的数据总线和地址总线,数据的数据总线和地址总线。这种分离的程序总线和数据总线可允许在一个机器周期内同时获取指令字和操作数,从而提高了执行速度,使数据的吞吐量提高了1倍。又由于程序和数据存储器在两个分开的物理空间中,因而取指和执行能完全重叠。目前使用Harvard结构的如所有的DSP处理器、Motolora公司的MC68系列、Zilog公司的Z8系列、ATMEL公司的AVR系列、ARM公司的ARM9等。
 
体系结构与实现的关系是什么?

    一个处理器的体系结构就是它的逻辑抽象,至于这个抽象的处理器具体如何实现,则称为(硬件)组成,或者就成为"实现"。同一个体系结构可以有不同的实现。计算机专业的基础课程《计算机体系结构与组成原理》就是从理论研究逻辑抽象及其实现方法。这两个方面是不同层次上的概念,原则上是相互独立的。但是实际上是相互影响的。这里有一个比较重要的概念就是微程序。它对指令系统的设计有比较密切的关系和影响。
 
CISC与微程序

    微程序是指令系统实现的一种方法,另外,相同的指令系统也可以通过"硬链接"来实现。不过,CISC体系结构的处理器一般采用微程序来实现复杂指令集,当然也可以采用其他实现方法,而RISC则不需要。由于微程序在CISC中比较重要,下面CISC均指微程序实现的CISC。
 
    为了支持复杂指令集,CISC通常采用一个复杂的数据通路和一个微程序控制器。微程序控制器由一个微程序存储器、一个微程序计数器和地址选择逻辑构成。基本工作原理如下:在微程序存储器中的每个字表示一个控制字,并且包含了一个时钟周期内所有数据通路控制信号的值。这就意味着控制字中的每一位表示一个数据通路控制线的值。而每个处理器指令是由一系列的控制字组成。当从内存中取出这样的一条指令时,首先把它放在指令寄存器中,然后地址选择逻辑再根据它来确定微程序存储器中相应的控制字顺序起始位置。当把该起始位置放到微程序计数器中后,就从微程序存储器中找到相应的控制字,并利用它在数据通路中把数据从一个寄存器传送到另一个寄存器。由于微程序计数器中的地址并发递增来指向下一个控制字,因此对于序列中的每个控制器都会重复上述步骤。最后,执行完最后一个控制字,该条指令执行结束,就从内存中取出一条新的指令,继续如上执行。
 
    从宏观上理解,采用微程序技术的存储器中,实际上有两种不同层次的指令。一种是面向程序员(软件)的、高层的"指令",另一种是面向硬件实现的、低层的"微指令"。这样,由电子元件和线路完成一套基本的功能,就可以通过微程序对这些功能进行不同的组合和编排,以实现高层指令所要求的复杂功能。而高层的"指令系统",则相当于由函数库向用户提供的API。所以,微程序的采用实际上是对软件设计中"子程序调用"这个概念的推广,将其适用范围向下推进了一个层次,从而对所要求的操作进一步化整为零,分而治之(Divide and Conquer),使指令系统的实现得到简化。
 
    从另一个角度来看,微程序的采用鼓励助长了在指令系统中采用复杂指令的倾向。人们曾经普遍认为:既然微程序的采用使复杂指令的实现成为可能和并行,处理器就应该为一些典型的复杂操作和典型的高级语言成分提供相应的指令,这样执行效率应该比较高。结果自然使人们得到一个印象,即指令系统的设计应该向高级语言看齐和靠拢,其"最高境界"就是与某种高级语言相同。在这种倾向下,各种处理器的指令系统越来越大,一些指令也越来越复杂。但是,随着技术的发展,人们对此产生怀疑,这是有着坚实的实践基础的。主要有以下几个方面:
 
1、为了提高运算速度,在微处理器中采用了"预取指令"等"流水线操作技术"。流水线技术是提高总体运算速度的有效手段,但是对CISC来说,控制字的数量和时钟周期的数目对于每一条指令都可以是不同的,所以很难实现指令流水操作。
 
2、即使不考虑流水线,在实现中也往往因为要顾及一些特殊的复杂指令的实现,而只好让简单指令作出一些牺牲。问题在于这样做从总体和全局看是否划算,这就取决于指令的使用频度。然而调查研究表明,20%的比较简单的指令被反复使用,使用量约占整个程序的80%;而80%左右的指令则很少使用,使用量仅占20%左右。这就是指令的2/8规律。
 
3、微处理器的集成规模是受半导体技术以及生产成本限制的,而微程序存储器又是微处理器内部"占地"面积最大的部分,复杂指令又是其中的"大户"。如果能消减微程序存储器的大小,或者在同样大小的芯片中集成其他的功能部件,或者可以减少芯片的尺寸和耗电,或者二者兼得,对嵌入式系统有着特殊的意义。因为用于嵌入式系统的处理器/控制器,常常要求将这些外围模块集成在同一芯片中。而要消减微程序存储器的大小,从指令系统中砍掉复杂指令当然是首选,最好是不用。
 
4、VLSI制造工艺要求CPU控制逻辑的规整性
进入20世纪80年代后,VLSI技术的发展非常迅速,往往每3到4年集成度就提高一个数量级。VLSI工艺要求规整性,而CISC处理器中,为了实现大量复杂的指令,控制逻辑极不规整,给VLSI工艺造成很大困难。
 
5、现代的微处理器都带有较大的高速缓存,运行中访问内存时命中高速缓存的概率可以达到较高的程度。命中时,高速缓存的访问速度与微程序存储器相似。这样使得许多简单指令没有必要用微程序来实现,而复杂的指令,用微程序来实现和用简单指令组成的子程序实现已经没有多大区别。
 
    基于以上原因,RISC的概念和技术应运而生了。
 
RISC的特点

    RISC是在继承CISC的成功技术并且克服其缺点的基础上产生并发展起来的,大部分RISC具有以下特点。
 
1、RISC体系结构中的指令系统都比较小,即不同指令的数量较少,并且只提供简单指令。所谓"精简指令集",一方面是说指令集的大小,另一方面是说每条指令的复杂程度,两个条件缺一不可。
 
2、每条运算指令的操作数都必须先预存于寄存器中。也就是说,一般运算指令在执行过程中是不访问内存的,所有的操作数不是立即数就是来自某个寄存器,而执行结果也只能存入寄存器。为此,需要配备专门的访内指令。主要是两条:LOAD和STORE,都是以微处理器为中心进行的命名。Load就是从内存load数据到某寄存器,Store就是store寄存器中的数据到内存中。这样所有指令的执行长度就变得整齐划一,而寻址方式的实现也就变得既简单又整齐。
 
3、指令的格式也整齐划一,典型的RISC体系结构中,每条指令长度为32位,包括一个操作码位段和三个操作数位段。这样,由于每条指令都是32位,其执行长度固定,采用流水线以后就可以基本上达到每个时钟脉冲执行一条指令的目标,因此,"每个时钟脉冲一条指令"成了RISC拥护者的旗号和目标。
 
4、由于一般指令的操作数都必须事先存放在寄存器中,计算过程中的中间结果自然也就不应该存放到内存中,也应该存放到寄存器中。这样就需要较多的通用寄存器,而传统的CISC寄存器的数量一般不超过16个,不适合RISC体系结构的要求。所以RISC体系结构一般都有比较多的寄存器组,通常是32个。
 
5、RISC的子程序调用过程,或"子程序链接",与CISC的不同。在CISC体系结构中,call指令将返回地址存入内存中的堆栈,因而需要访问内存。而RISC的原则之一就是尽量少访问内存,所以返回地址是放在寄存器中而不是堆栈中的。这样,一般专门拿一个寄存器作为"(子程序)链接寄存器"(R14,映射为LR)。这样如果调用的是底层的"叶"子程序,便不需要为子程序链接访问内存,而如果是中层的子程序,则可按照一定的调用约定将此寄存器的内容溅出到堆栈中。此外,调用参数的传递也不通过堆栈,而是通过寄存器。对于有大量子程序调用,特别是有大量很小的"叶"子程序调用的软件,这样的链接方法可以节省很多访问内存的开销,有利于提高效率。
 
6、中断的过程也可以看成是特殊的子程序链接。对于RISC体系结构,对中断是的寄存器作出约定,那些寄存器的内容是必须保存,因而在中断处理程序中可以自由使用。如果中断处理程序需要更多的寄存器,那么就先行一步溅出这些寄存器的内容。
 
    与CISC架构相比较,尽管RISC架构有诸多的优点,但是决不能认为可以取代CISC架构。事实上,RISC和CISC架构各有优势,而且界限并不那么明显。现代的CPU往往采用CISC的外围,内部加入了RISC的特性,如超长指令集CPU就是融合了RISC和CISC的优势,成为未来CPU的发展方向之一。
 
嵌入式系统的处理器为什么大都是RISC结构的?

1、在同样的集成规模下,RISC的CPU核在芯片上占用面积要小得多。这样就可以将一些如外设接口等等的外围模块集成在同一块芯片上。
 
2、有利于减少芯片的尺寸和功耗(有利于散热)。
 
3、结构简单,开发成本低。
 
4、对于实时应用,RISC指令具有均匀划一并且较小的执行长度,因此有利于中断延迟的可预测性,并且有利于缩短中断延迟。
 
ARM的四层含义

1、ARM是一种RISC MPU/MCU的体系结构,如同x86架构是一种CISC体系结构一样。另外,还有MIPS架构、PowerPC架构等等。
 
2、ARM是Advanced RISC Machine Limited公司的简称。
 
3、ARM是Advanced RISC Machine Limited 公司的产品,该产品以IP Core(Intellectual Property Core,知识产权核)的形式提供的。
 
4、ARM还用以泛指许多半导体厂商买了这种设计后生产出来的"ARM处理器"系列的芯片及其衍生产品。
半导体厂商固然可以光购买ARM公司的设计而直接生产ARM处理器芯片,但是更好的方法是以ARM处理器为核心,在同一块芯片上配上自己开发的外围模块,形成面向特定应用和市场的专用芯片,甚至"片上系统(System on a Chip, SoC)"。这样,作为专用处理器/控制器芯片的生产商既可以减少开发中的风险,又可以大大缩短开发周期,降低成本。所以,"ARM处理器"一般是作为"内核"存在于一些专用处理器/控制器的内部,因而又常常叫做"ARM核"。特别地,如果一个处理器核不带浮点运算功能,有时候就对此特别加以强调,称之为"整形核"。
 
ARM体系结构版本及其变种的含义

    ARM体系结构的版本的字符串由下面几个部分组成:
1、字符串ARMv
2、ARM指令集版本号
3、表示变种的字符。由于在ARM体系版本4以后,M变种成为系统的标准功能,字符M通常不需要列出。
4、使用字符x表示排除某种功能。
    例如:ARMv4T 表示ARM版本4,支持Thumb。
 
    变种字母含义:
1、T��支持Thumb
2、M��Multiplier,支持长乘法指令
3、E��Extended,支持增强型DSP指令
4、J��Java加速器Jazelle
5、SIMD��支持ARM媒体功能扩展
 
    还有几个字母含义如下:
1、D��Debug,提供调试支持
2、I��芯片上带有内置的ICE,从而支持程序内的断点和数据空间的"观察点"设置。
 
ARM的存储器结构

    以ARM体系结构的第4版为界限,之前采用的是冯・诺依曼结构,此版本及其之后的版本都是采用Harvard结构。不过这种结构是一种Modified Harvard,就是将CPU访问内存的通道分成指令和数据两个相互独立的通道。CPU虽然可以同时从"内存"取指令和读写数据,但实际上只是分别访问两个高速缓存。而这两个高速缓存最后还是通过共同的总线访问内存。

评论

此博客中的热门博文

【转】AMBA、AHB、APB总线简介

AMBA 简介 随着深亚微米工艺技术日益成熟,集成电路芯片的规模越来越大。数字IC从基于时序驱动的设计方法,发展到基于IP复用的设计方法,并在SOC设计中得到了广泛应用。在基于IP复用的SoC设计中,片上总线设计是最关键的问题。为此,业界出现了很多片上总线标准。其中,由ARM公司推出的AMBA片上总线受到了广大IP开发商和SoC系统集成者的青睐,已成为一种流行的工业标准片上结构。AMBA规范主要包括了AHB(Advanced High performance Bus)系统总线和APB(Advanced Peripheral Bus)外围总线。   AMBA 片上总线        AMBA 2.0 规范包括四个部分:AHB、ASB、APB和Test Methodology。AHB的相互连接采用了传统的带有主模块和从模块的共享总线,接口与互连功能分离,这对芯片上模块之间的互连具有重要意义。AMBA已不仅是一种总线,更是一种带有接口模块的互连体系。下面将简要介绍比较重要的AHB和APB总线。 基于 AMBA 的片上系统        一个典型的基于AMBA总线的系统框图如图3所示。        大多数挂在总线上的模块(包括处理器)只是单一属性的功能模块:主模块或者从模块。主模块是向从模块发出读写操作的模块,如CPU,DSP等;从模块是接受命令并做出反应的模块,如片上的RAM,AHB/APB 桥等。另外,还有一些模块同时具有两种属性,例如直接存储器存取(DMA)在被编程时是从模块,但在系统读传输数据时必须是主模块。如果总线上存在多个主模块,就需要仲裁器来决定如何控制各种主模块对总线的访问。虽然仲裁规范是AMBA总线规范中的一部分,但具体使用的算法由RTL设计工程师决定,其中两个最常用的算法是固定优先级算法和循环制算法。AHB总线上最多可以有16个主模块和任意多个从模块,如果主模块数目大于16,则需再加一层结构(具体参阅ARM公司推出的Multi-layer AHB规范)。APB 桥既是APB总线上唯一的主模块,也是AHB系统总线上的从模块。其主要功能是锁存来自AHB系统总...

【转】GPIO编程模拟I2C入门

ARM编程:ARM普通GPIO口线模拟I2C  请教个问题: 因为需要很多EEPROM进行点对点控制,所以我现在要用ARM的GPIO模拟I2C,管脚方向我设 置的是向外的。我用网上的RW24C08的万能程序修改了一下,先进行两根线的模拟,SDA6, SCL6,但是读出来的数不对。我做了一个简单的实验,模拟SDA6,SCL6输出方波,在示波 器上看到正确方波,也就是说,我的输出控制是没问题的。 哪位大哥能指点一下,是否在接收时管脚方向要设为向内?(不过IOPIN不管什么方向都可 以读出当前状态值的阿) 附修改的RW24C08()程序: #define  SomeNOP() delay(300); /**/ /* *********************************  RW24C08   **************************************** */ /**/ /* ----------------------------------------------------------------------------- ---  调用方式:void I2CInit(void)   函数说明:私有函数,I2C专用 ------------------------------------------------------------------------------- -- */ void  I2CInit( void ) ... {  IO0CLR  =  SCL6;      // 初始状态关闭总线  SomeNOP();  // 延时   I2CStop();  // 确保初始化,此时数据线是高电平 }   /**/ /* ---------------------------------------------------------------------------- ----  调用方式:void I2CSta...

【转】cs8900网卡的移植至基于linux2.6内核的s3c2410平台

cs8900网卡的移植至基于linux2.6内核的s3c2410平台(转) 2008-03-11 20:58 硬件环境:SBC-2410X开发板(CPU:S3C2410X) 内核版本:2.6.11.1 运行环境:Debian2.6.8 交叉编译环境:gcc-3.3.4-glibc-2.3.3 第一部分 网卡CS8900A驱动程序的移植 一、从网上将Linux内核源代码下载到本机上,并将其解压: #tar jxf linux-2.6.11.1.tar.bz2 二、打开内核顶层目录中的Makefile文件,这个文件中需要修改的内容包括以下两个方面。 (1)指定目标平台。 移植前:         ARCH?= $(SUBARCH) 移植后: ARCH            :=arm (2)指定交叉编译器。 移植前: CROSS_COMPILE ?= 移植后: CROSS_COMPILE   :=/opt/crosstool/arm-s3c2410-linux-gnu/gcc-3.3.4-glibc-2.3.3/bin/arm-s3c2410-linux-gnu- 注:这里假设编译器就放在本机的那个目录下。 三、添加驱动程序源代码,这涉及到以下几个方面。(1)、从网上下载了cs8900.c和cs8900.h两个针对2.6.7的内核的驱动程序源代码,将其放在drivers/net/arm/目录下面。 #cp cs8900.c ./drivers/net/arm/ #cp cs8900.h ./drivers/net/arm/ 并在cs8900_probe()函数中,memset (&priv,0,sizeof (cs8900_t));函数之后添加如下两条语句: __raw_writel(0x2211d110,S3C2410_BWSCON); __raw_writel(0x1f7c,S3C2410_BANKCON3); 注:其原因在"第二部分"解释。 (2)、修改drivers/net/arm/目录下的Kconfig文件,在最后添加如...