理解S3C2440里面*.S文件的一些基础

最好手上有一本<ARM920T技术参考手册>,老古开发网上免费下载

关于cache:

计算机系统一般都采用多级存储器结构,如寄存器、主存、磁盘、光盘、磁带等。这种多级存储器的特点是从外存储器到CPU中的寄存器逐级向上,存储容量逐级减小,而存取速度逐级提高。由于上下两级存储器的速度可以相差l—2个数量级或者更高,因此,上一级和下一级存储器的数据交换常常成为系统瓶颈,大大降低了系统的性能。为了解决这个问题,通常采用的办法是在两级存储器之间增加一个高速缓冲存储器Cache。  
    所谓Cache是一个速度等于或者接近上一级存储器访问速度的小容量存储器,其中保存了下级存储器中部分当前所需的数据,因此CPU可以直接从Cache中取得所需的数据,而不必访问下一级存储器。由于Cache的速度与上一级存储器相当,因此保证了系统效率不会降低。Cache的设计依据是程序存取局部性原理,通常程序存取的一批数据总是存放在存储器相邻的单元中,只要把这一批数据同时调入cache中,即可保证近期内需要的数据都能在Caclle中访问成功。为了实现上述目标,在设计Cache时必须做到以下两点:  
    1.保证访问Cache有较高的命中率;  
    2.访问Cache与访问下级存储器的方式不变、容量不减。因此对于编程人员来说,Cache是完全透明的,也就是说,他们感觉不到Cache的存在。  
  由于Cache的容量比下级存储器小l-2个数量级、要做到上述两点,则必须考虑以下问题:  
    1.如何组织Cache,使得下级存储器的每个部分都能够在需要时调入Cache  
    2.采用何种替换策略、使得访问cache的命中率最高;  
    3.采用什么方法使得Cache和下级存储器的数据具有—致性,即修改Cache后保证下级存储器的内容也随之修改(或者相反)。  
   
    通过上面的介绍,我们知道Cache也是一种存储器,其工作速度很高,如Ll和L2   Cache就是为了解决PU和DRAM主存之间的速度匹配而设置的。因此主存Cache也可以看作是高速CPU和低速DRAM之间的接口。或者说,把Cache看成一个适配器来解决CPU和DRAM之间的速度匹配问题。CPU、Cache和DRAM三者之间的关系可用图2所示的工作原理图来表示。  

    当CPU要从存储器中读取一个数据字时,它首先在Cache中查找。如果找到了,则立即从Cache中读取并送到CPU中;如果在Cache中找不到,则用一个存储器读周期的时间从主存个读出这个数据字送到CPU、并且把包含这个数据字的整个内存数据块都从主存送到Cache中。之所以要把包含被读数据字的整个内存数据块都从主存送到Cache中是因为对存储器的访问具有局部性,也就是说连续读取的数据宇一般在内存中都是连续存放的;调入一个数据块后,将使得以后若干次的访存都可以通过访问Cache来完成。如果调度算法得当,Cache的命中率可以很高。这样,从用户的角度看来,整个存储器(Cache+DRAM)就变成了既有Cache这样高的速度,又有DRAM这样的大容量的存储系统了。这对于解决存储器这个瓶颈是十分有效的。  
    综上所述,Cache具有以下一些特点:  
    ·Cache虽然也是一类存储器.但是不能由用户直接访问。  
    ·Cache的容量不大,其中存放的只是主存储器中某一部分内容的拷贝,称为存储器映象。  
    ·为了保证CPU访问时有较高的命中率,Cache中的内容应该按一定的算法更换。  
    ·Cache中的内容应该与主存中对应的部分保持一致。也就是说,如果主存中的内容在调入Cache之后发生了改变,那么它在Cache中的拷贝也应该随之改变。反过来,如果CPU修改了Cache中的内容,也应该修改主存中的相应内容。  
    现代的Cache系统常常采用分级组织的方法,在CPU中集成了一级Cache(L1),也称为片内Cache;在主板上配置二级Cache(L2)。CPU中的片内Cache虽然容量较小,但是能够以CPU相同的工作频率工作,因此速度极快。一般情况下在L1未命中时,才在L2中查找。从赛扬处理器开始,甚至已经把L2集成到CPU内部了(K6-3处理器也内置了二级缓存,而这时相应的Socket   7主板上的二级缓存就成为“三级”缓存了)。  
    所谓存储器映像问题就是如何组织Cache.使得下级存储器的每个部分都能够在需要时调入Cache,并且确定调入的内容放在Cache中的什么地方,以便于准确迅速地查找。存储器映像的方法主要有全相联映像法、直接映象法和组相联映象法。   MMU管理
    全相联映像法的基本思想是把一个主存块的地址(块号)和块的内容都拷贝到Cache行中;由于块地址也保存在Cache中,因此可以拷贝到Cache中的任意位置。此法的优点是灵活,但是查找比较困难,而且硬件的实现较为困难。  
    直接映像法的基本思想是一个主存块只能拷贝到Cache中固定的行内。该按硬件成本低,但是由于一个Cache行要对应多个主存块,在使用中当这些主存块需要同时调入Cache时将发生冲突、增加调入调出的开销。  
    组相联映像法是上述两种方法的折衷方案。其基本思想是把Cache分为m个组,每个组分为n行。主存块分配时对组是固定的、而在组内的位置可以任意。这样就综合了两者的优点,这是目前最常用的方法。


 
    由于Cache的容量总是远小于下一级存储器的容量,因此Cache中只能是下级存储器的部分映像。为了使下级存储器的内容都能在需要时拷贝到Cache中,必须随时替换Cache内容:即把当前不需要的内容调出Cache,腾出空间,调入当前需要的内存块。在这种调入调出方法中,最重要的是替换的策略,即在需要时选择Cache中的哪些行调出,再调入所需的内存块。这种替换策略通常称为调度算法,它是由硬件实现的。如果算法选择不当,将大大增加调入调出的频度。例如把一个当前不需要但是很快就将使用的行调出,必然会降低系统的效率。  
    常用算法有最不经常使用算法、最近最少使用算法。  
    最不经常使用算法(LFU算法)的思想是把最近一段时间内被访问次数最少的行调出。因此需要对每一个行设置一个计数器,对该行的访问次数计数、在需要时比较各个计数器的值,淘汰计数次数最少的数据行。这种算法的问题是明显的、那些在程序前期被频繁访问而在后期不再使用的行,可能会在相当长的时间内不被淘沈而那些刚刚调入并将继续反复使用的行则可能因为其计数器中的值较小而频道淘汰。这将严重影响系统的效率。  

另一种较常用的算法是最近最少使用算法(LRU算法)。LRU算法的思想是将最近一段时间内最少被访问过的行淘汰出局。因此也需要为每行设置一个计数器、但是计数方法与LFU算法不同。LRU算法是把命中行的计数器清零、其它各行计数器加1。当需要替换时淘汰行计数器计数值最大的数据行出局。  
    此外还有一些算法,鉴于篇幅不再赘述。  
    由于Cache中的内容只是主存中相应单元的“拷贝”。因此必须保持这两处的数据绝对一致,否则就会产生错误。造成Cache和相应主存单元数据不一致的原因来自两个方面。一是CPU读人Cache数据作了修改后再写入Cache,而主存中相应单元的内容并未随之变化二是在有多个设备对主存访问的情况下造成的。如多处理器或有DMA的系统,它们直接访问主存储器,修改了其中的内容,而cache中的相应数据却末随之修改。  
    1.CPU修改Cache后的处理  
    对于CPU修改了Cache的数据,如何使主存中相应单元的数据也随之修改的问题。通常有三种不同的处理方式。  
    一种方式称为“直写式(write—through)”,其原理是在CPU向Cache写入的同时,也把数据写入主存储器,以保证Cache和主存中相应单元数据的一致性。直写式系统简单可靠,但由于CPU每次更新Cache时都要对主存储器写入,习此速度受到了影响。  
    第二种方式称为“缓冲直写式(Posted   Write)”,其原理是CPU在更新Cache时不直接更新主存中的数据,而是把更新的数据送入一个缓冲器中暂存,这样CPU就不必等待主存写入造成的延时而直接进入下一周期的操作在适当的时候再把缓冲器中的内容写入主存中(例如在CPU读Cache的同时;把缓冲器的内容写入主存)。这种方式在一定程序上提高了速度,但由于缓冲器的容量有限,只能锁存——次写入的数据,如果发生连续的写操作则CPU仍需要等待。上述的直写式或缓冲直写式不仅速度低,而且在很多时候向主存写入是不必要的。例如CPU可能多次对同一个Cache单元更新内容,实际上只需把最后更新结果写入主存即可,而不必更新一次Cache,就向主存写入一次。

         根据这种思想提出了第三种方式,称为“回写式(Write—back)”。有的资料中也称为“写回”。这种方式的原理是CPU修改了Cache的内容后并不立即修改主存中相应的单元,而在被修改的Cache单元的内容将从Cache中淘汰时(如更换页面)才把它写入主存储器的相应单元中。回写式系统速度快,避免了不必要的冗余写操作,但结构上比较复杂。当前的微机普遍采回写式系统。  
    2.多处理器或DMA直接访问主存储器后的处理  
    多处理器或DMA直接访问主存储器造成主存和cache中的数据不一致发生在以下情形:当主存中某单元内容调入Cache后,又由其它处理器或DMA更新了主存储器该单元的内容。为了避免这种情况下的数据不一致,通常采用以下三种处理办法。  
    一种办法称为“总线监视”,即由cache控制器随时监视系统的地址总线,若有其它部件向主存中写入了内容,则把Cache中相应单元的内容置为无效,CPU必须重新从主存中读人该单元的内容  
  第二种方式称为“主存监视”、由Cache控制器监视所有主存储器的读写操作所有对主存的访问都必须通过Cache来完成。这样,凡对主存的写入也就对Cache中的相应单元进行拷贝从而保证了两者数据的一致性。  
    第三种方式是设置“不可Cache区   (Non   Cacheable   Block)”,这种方式的基本思想是在主存中开辟一块区域,该区域中数据不受cache控制器的管理,不能调入Cache,CPU只能直接读写该区域的内容。其它总线设备也只能把数据直接写入该区域中。由于该区域不与Cache发生关系,也就不存在数据不一致的问题。不可Cache区方式是微机中最主要的方式,不少BIOS设置程序允许用户设置不可Cache区的首地址和尺寸、以及可Cache区的地址范围。  
    Cache在微机系统中获得了广泛应用。除了CPU中的cache外,硬盘、光盘甚至主存中部可找到它的踪影。  
    1、CPU中的Cache  
    从486CPU开始,在CPU芯片内集成了Cache,称为片内Cache。此时由于受到工艺上的限制,片内Cache的容量很小,只有8KB。片内Cache的最大优点是,CPU对它的访问是在芯片内部进行的,不需要通过总线传送数据因此速度很快;但是由于其容量很小,而处理器的时钟频率又很高,一旦出现片内cache末命中的情况,性能将明显化。因此在处理器芯片之外的主板上再加Cache,称为二级Cache(L2Cache),或称为板载Cache。  
    在实际使用中,进入Cache的内容既可以是指令也可以是数据,而CPU对于这两者的处理是不完全相同的。为了使系统效率达到最佳状态,从Pentium处理器开始把片内Cache容量增加到16KB。其中指令CBche和数据Cache各占8KB。  
    Intel公司在1995年末推出了Pentium   Pro(P6),为了进一步改善系统性能,P6采用了双穴封装,即除了CPU外,还把256/5l2KB的二级Cache也封装在同一个陶瓷片内。这样,L2也能以处理器的时钟高速运行,大大地提高了系统效率。  
    由于P6采用的方式成本很高,在InteI随后推出的Pentium   II中,把L2又从CPU陶瓷封装中分立出来,和CPU共同安装在一块称为SEC的卡盒内,而Pentium   II处理器则采用了双独立总线结构,其中一条总线联接L2高速缓存,另一条负责主存。由于Pentium   II的L2只能以CPU时钟的一半工作。因此比Pentium   Pro的L2慢一些。作为一种补偿,Intel将Pentium   II上的Ll高速缓存从16K加倍到32K,从而减少了对L2高速缓存的调用频率。而在非Intel   CPU中,L1的容量则更大,以期求得更好的系统性能。  
    为了匹配硬盘和主存在数据传送速度上的矛盾,微机系统中毫无例外地采用了硬盘高速缓存,或称为硬盘Cache。硬盘高速缓存分为两种:硬件高速缓存和软件高速缓存。软件高速缓存是利用软件工具(如Smart   Drive)在系统主存中开辟的一块区域作为数据传送缓冲区,硬件高速缓存则是在磁盘控制器中安装的一块RAM,通过RAM缓冲区读写数据可以得到更高的访问速度。早期硬盘中的cache很小,只有数十KB到数百KB,目前新型硬盘的高速缓存均达到2MB。在选购硬盘时除了注意容量、带宽、转速等参数外,还应该考虑Cache的容量,越大越好。当Cache容量大时,能够保证较稳定的突发数据传送;而如果Cache容量较小,在读写大型图形或视频文件时,由于连续传送的数据量很大,缓冲区则不能表示出其优越性,使得数据传送不再能处于突发传送方式,而处于持续传送方式,降低了数据带宽。  
    3.光盘。  
    以CD—ROM驱动器为例,其中配置的Cache通常为128KB或者256KB,高档CD—ROM驱动器中的Cache容量可达512KB甚至更高。在CD   ROM中配置Cache的目的仍然是作为光盘的高速缓存,以便减少读盘的次数,这对于改善CD   RoM的性能是很有好处的。  
  同样,其它品种的光盘驱动器,如CD-R、CD—RW、M0、DVD—ROM等,也都配置了Cache。  
    4.主存储器中的Cache  
    主存通常是采用DRAM(动态随机存取存储器)器件制作的,而Cache一般采用速度更高的SRAM(静态随机存取存储器)制作。一种新型的增强DRAM)采用了在DRAM芯片上集成一个小容量SRAM的办法,我们可以把这一小片SRAM称为主存中的Cache。这个Cache在突发式读写时非常有利,使DRAM芯片的性能得到了明显的提高。


//ARM920T有16k的ICache和16K的DCache

 一些指令的作用:

mcr p15,0,rd,c7,c14,2          clean and invalidate Dcache entry(using index)

mcr p15,0,rd,c7,c14,1          clean and invalidate Dcache entry(using MVA)

;void MMU_CleanInvalidateDCacheIndex(U32 index)
   EXPORT MMU_CleanInvalidateDCacheIndex
MMU_CleanInvalidateDCacheIndex
   ;r0=index
   mcr p15,0,r0,c7,c14,2         ;查看ARM920T手册 p43 图2-5  C7寄存器的index模式的index设置
   MOV_PC_LR

可以理解如下的i<<26,j<<5

还有ARM920T手册的p87页的表4-1就能够很详细的理解了,cache的构造,2kb RAM=64lines×8words

j的取值范围从5-7bit位,既3位=8,因此j表示的是8个seg,8个段,一共=8*2kB=16KB

R1_I    EQU    (1<<12)
R1_C    EQU    (1<<2)
R1_A    EQU    (1<<1)
R1_M    EQU    (1)
R1_iA    EQU    (1<<31)
R1_nF   EQU    (1<<30)


/ARM920T手册P38,寄存器C1,控制寄存器,使能各个寄存器

;void MMU_EnableICache(void)  

   EXPORT MMU_EnableICache  
MMU_EnableICache
   mrc p15,0,r0,c1,c0,0
   orr r0,r0,#R1_I
   mcr p15,0,r0,c1,c0,0
   MOV_PC_LR

;void MMU_DisableICache(void)
   EXPORT MMU_DisableICache
MMU_DisableICache
   mrc p15,0,r0,c1,c0,0
   bic r0,r0,#R1_I
   mcr p15,0,r0,c1,c0,0
   MOV_PC_LR

;void MMU_EnableDCache(void)
   EXPORT MMU_EnableDCache
MMU_EnableDCache
   mrc p15,0,r0,c1,c0,0
   orr r0,r0,#R1_C
   mcr p15,0,r0,c1,c0,0
   MOV_PC_LR

;void MMU_DisableDCache(void)
   EXPORT MMU_DisableDCache
MMU_DisableDCache
   mrc p15,0,r0,c1,c0,0
   bic r0,r0,#R1_C
   mcr p15,0,r0,c1,c0,0
   MOV_PC_LR


;void MMU_InvalidateICache(void)     //ICache 无效
   EXPORT MMU_InvalidateICache
MMU_InvalidateICache
   mcr p15,0,r0,c7,c5,0
   MOV_PC_LR


 

;voic MMU_InvalidateTLB(void)     //page 45  TLB无效
   EXPORT MMU_InvalidateTLB
MMU_InvalidateTLB
   mcr p15,0,r0,c8,c7,0
   MOV_PC_LR

 

void MMU_Init(void)
{
    int i,j;

for(i=0;i<64;i++)
        for(j=0;j<8;j++)
            MMU_CleanInvalidateDCacheIndex((i<<26)|(j<<5));

要使用write-back,就一定要对DCache进行清除


    MMU_InvalidateICache();

    MMU_DisableMMU();
    MMU_InvalidateTLB();

    //MMU_SetMTT(int vaddrStart,int vaddrEnd,int paddrStart,int attr)
    MMU_SetMTT(0x00000000,0x07f00000,0x00000000,RW_CNB);  //bank0   128M
    MMU_SetMTT(0x08000000,0x0ff00000,0x08000000,RW_CNB);  //bank1   128M
    MMU_SetMTT(0x10000000,0x17f00000,0x10000000,RW_NCNB); //bank2
    MMU_SetMTT(0x18000000,0x1ff00000,0x18000000,RW_NCNB); //bank3
    //MMU_SetMTT(0x20000000,0x27f00000,0x20000000,RW_CB); //bank4
    MMU_SetMTT(0x20000000,0x27f00000,0x20000000,RW_CNB); //bank4 for STRATA Flash
    MMU_SetMTT(0x28000000,0x2ff00000,0x28000000,RW_NCNB); //bank5
    MMU_SetMTT(0x30000000,0x30f00000,0x30000000,RW_CB);      //bank6-1   16M
    MMU_SetMTT(0x31000000,0x33e00000,0x31000000,RW_NCNB); //bank6-2      46M
    MMU_SetMTT(0x33f00000,0x33f00000,0x33f00000,RW_CB);   //bank6-3   0
    MMU_SetMTT(0x38000000,0x3ff00000,0x38000000,RW_NCNB); //bank7   127M 
   
    MMU_SetMTT(0x40000000,0x47f00000,0x40000000,RW_NCNB); //SFR   128M
    MMU_SetMTT(0x48000000,0x5af00000,0x48000000,RW_NCNB); //SFR   128M
    MMU_SetMTT(0x5b000000,0x5b000000,0x5b000000,RW_NCNB); //SFR
    MMU_SetMTT(0x5b100000,0xfff00000,0x5b100000,RW_FAULT);//not used
 
    MMU_SetTTBase(_MMUTT_STARTADDRESS); //33ff8000

    MMU_SetDomain(0x55555550|DOMAIN1_ATTR|DOMAIN0_ATTR);   //C3

        //DOMAIN1: no_access, DOMAIN0,2~15=client(AP is checked)
    
    MMU_SetProcessId(0x0);      //快速上下文切换,禁止  MVA=VA  《ARM结构和编程》 page 220
    MMU_EnableAlignFault();    //是否开启地址对齐检查功能     《ARM结构和编程》page 222
       
    MMU_EnableMMU();
    MMU_EnableICache();
    MMU_EnableDCache(); //DCache should be turned on after MMU is turned on.

 }

//上面程序中的MMU_SET(),就是关于页表的函数

MMU要完成虚拟存储空间到物理存储空间的映射。把虚拟地址空间分成一个个固定大小的块,每一块称为一页。把物理内存的地址空间也分成同样大小的页。MMU就要是要实现两者之间的转换。

而页表(Translate table )(ARM920T page 40 register 2,TTB)是实现上述的功能的重要手段 C2,他是位于内存中的一个表。  表的每一行对应于虚拟存储空间的一个页,内容有:该虚拟内存页对应的物理内存页的地址、该页的方位权限和该页的缓冲特性。一般我们把这个表中的这样的一行,称为一条地址变换条目(entry).
***查找先在cache中找地址变换条目,没有找到再到内存找,并保存 到TLB中
TLB:针对程序运行时候只是一部分运行的特性,采用了一个容量更小的存取器件,称快表(TLB)。C8
地址条目锁存(locked down):mmu可以利用这个提高cpu速度,读取页表中的地址条目。 C10
域(domain):每个域对应一个内存区域。  C3

详细的MMU部分还有寄存器的参考:请自行参阅《ARM结构和编程》的page 188 --220和《ARM技术参考手册》的page 40 寄存器


/****设置页表*函数****/

/**vaddrstart : 虚拟起始地址**/

/**vaddrend :虚拟结束地址**/


/****设置页表*****/
void MMU_SetMTT(int vaddrStart,int vaddrEnd,int paddrStart,int attr)
{
    volatile U32 *pTT;
    volatile int i,nSec;
   
    /****虚拟存储空间到物理存储空间的映射是以内存块为单位的:分为1M/64Lb/4Kb/1kB
         虚拟存储空间中的一块连续的存储空间被映射成物理存储空间中同样大小的一块连续存储空间
         页表中,每一个地址变换条目实际上就记录了一个虚拟存储空间的存储块的基地址
         与物理存储空间相应的一个存储块的基地址的对应关系
         C2:存放的是内存中页表的基地址[31:14]--查找页表
         而C2寄存器的位[31:14]和虚拟地址的位[31:20](页表内的序号)结合作为一个32位数的高30位
         作为合成建立的页表中相应的地址转换条目的地址,低2位为00
         此设置详细查看 <ARM结构和编程>的page 193,基于段的****/
    /*******/
    pTT=(U32 *)_MMUTT_STARTADDRESS+(vaddrStart>>20);   //#define    _MMUTT_STARTADDRESS        0x33ff8000
    nSec=(vaddrEnd>>20)-(vaddrStart>>20);  /****nSec:段大小***/
    for(i=0;i<=nSec;i++)
    /****addr : [11:10]:[5]:[3:2]:[4]:[1:0]****/
            *pTT++=attr |(((paddrStart>>20)+i)<<20);
}

 


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值