S3C2410内存管理单元MMU基础实验

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

S3C2410内存管理单元MMU基础实验ARM芯片S3C2410内存管理单元MMU基础实验(11)实验十一:MMU在理论上概括或解释MMU,这不是我能胜任的。我仅基于为了理解本实验中操作MMU的代码而对MMU做些说明,现在先简单地描述虚拟地址(VA)、变换后的虚拟地址(MVA)、物理地址(PA)之间的关系:启动MMU后,S3C2410的CPU核看到的、用到的只是虚拟地址VA,至于VA如何最终落实到物理地址PA上,CPU是不理会的。而caches和MMU也是看不见VA的,它们利用VA变换得来的MVA去进行后续操作——转换成PA去读/写实际内存芯片,MVA是除CPU外的其他部分看见的虚拟地址。对于VA与MVA之间的变换关系,请打开数据手册551页,我摘取了“Figure2-8.AddressMappingUsingCP15Register13”:图4VA与MVA的关系如果VA32M,需要使用进程标识号PID(通过读CP15的C13获得)来转换为MVA。VA与MVA的转换方法如下(这是硬件自动完成的):if(VA32M)thenMVA=VA|(PID25)//VA32MelseMVA=VA//VA=32M利用PID生成MVA的目的是为了减少切换进程时的代价:如果两个进程占用的虚拟地址空间(VA)有重叠,不进行上述处理的话,当进行进程切换时必须进行虚拟地址到物理地址的重新影射,这需要重建页表、使无效caches和TLBS等等,代价非常大。但是如果像上述那样处理的话,进程切换就省事多了:假设两个进程1、2运行时的VA都是0-32M,则它们的MVA分别是(0x02000000-0x03ffffff)、(0x04000000-0x05ffffff)——前面说过MMU、Caches使用MVA而不使用VA,这样就不必进行重建页表等工作了。现在来讲讲MVA到PA的变换过程:请打开数据手册557页,“Figure3-1.TranslatingPageTables”(见下述图5)非常精练地概括了对于不同类型的页表,MVA是如何转换为PA的。图中的页表“Translationtable”起始地址为“TTBbase”,在建立页表后,写入CP15的寄存器C2。使用MVA[31:20]检索页表“Translationtable”得到一个页表项(entry,4字节),根据此entry的低2位,可分为以下4种:1、0b00:无效2、0b01:粗表(Coarsepage)entry[31:10]为粗表基址(Coarsepagetablebaseaddress),据此可以确定一块1K大小的内存——称为粗页表(Coarsepagetable,见图5)。粗页表含256个页表项,每个页表项对应一块4K大小的内存,每个页表项又可以分为大页描述符、小页描述符。MVA[19:12]用来确定页表项。一个大页(64K)对应16个大页描述符,这16个大页描述符相邻且完全相同,entry[31:16]为大页基址(Largepagebase)。MVA[15:0]是大页内的偏移地址。一个小页(4K)对应1个小页描述符,entry[31:12]为小页基址(Smallpagebase)。MVA[11:0]是小页内的偏移地址。3、0b10:段(Section)段的操作最为简单,entry[31:20]为段基址(Sectionbase),据此可以确定一块1M大小的内存(Section,见图5),而MVA[19:0]则是块内偏移地址4、0b11:细表(Finepage)entry[31:12]为细表基址(Finepagetablebaseaddress),据此可以确定一块4K大小的内存——称为细页表(Finepagetable,见图5)。细页表含1024个页表项,每个页表项对应一块1K大小的内存,每个页表项又可以分为大页描述符、小页描述符、极小页描述符。MVA[19:10]用来确定页表项。一个大页(64K)对应64个大页描述符,这64个大页描述符相邻且完全相同,entry[31:16]为大页基址(Largepagebase)。MVA[15:0]是大页内的偏移地址。一个小页(4K)对应4个小页描述符,entry[31:12]为小页基址(Smallpagebase)。MVA[11:0]是小页内的偏移地址。极小页(1K)对应1个极小页描述符,entry[31:10]为极小页基址(Tinypagebase)。MVA[9:0]是极小页内的偏移地址。图5TranslatingPageTables访问权限的检查是MMU主要功能之一,它由描述符的AP和domain、CP15寄存器C1的R/S/A位、CP15寄存器C3(域访问控制)等联合作用。本实验不使用权限检查(令C3为全1)。下面简单介绍一下使用Cache和Writebuffer:1、“清空”(clean)的意思是把Cache或Writebuffer中已经脏的(修改过,但未写入主存)数据写入主存2、“使无效”(invalidate):使之不能再使用,并不将脏的数据写入主存3、对于I/O影射的地址空间,不使用Cache和Writebuffer4、在使用MMU前,使无效Cache和drainwritebuffer与cache类似,在使用MMU前,使无效TLB。上面有些部分讲得很简略,除了作者水平不足之外,还在于本书的侧重点——实验。理论部分就麻烦各位自己想办法了。不过这些内容也足以了解本实验的代码了。本实验与实验9完成同样的功能:使用按键K1-K4作为4个外部中断——EINT1-3、EINT7,当Kn按下时,通过串口输出“EINTn,Knpressed!”,主程序让4个LED轮流从0到15计数。代码在目录MMU下。下面摘取与MMU相关的代码详细说明。先看看head.s代码(将一些注释去掉了):1bReset2HandleUndef:3bHandleUndef4HandleSWI:5bHandleSWI6HandlePrefetchAbort:7bHandlePrefetchAbort8HandleDataAbort:9bHandleDataAbort10HandleNotUsed:11bHandleNotUsed12ldrpc,HandleIRQAddr13HandleFIQ:14bHandleFIQ15HandleIRQAddr:16.longHandleIRQ17Reset:@函数disable_watch_dog,memsetup,init_nand,@nand_read_ll在init.c中定义18ldrsp,=4096@设置堆栈19bldisable_watch_dog@关WATCHDOG20blmemsetup_2@初始化SDRAM21blinit_nand@初始化NANDFlash22blcopy_vectors_from_nand_to_sdram@在init.c中23blcopy_process_from_nand_to_sdram@在init.c中24ldrsp,=0x30100000@重新设置堆栈@(因为下面就要跳到SDRAM中执行了)25ldrpc,=run_on_sdram@跳到SDRAM中26run_on_sdram:27blmmu_tlb_init@调用C函数mmu_tlb_init(mmu.c中),建立页表28blmmu_init@调用C函数mmu_init(mmu.c中),使能MMU29msrcpsr_c,#0xd2@进入中断模式30ldrsp,=0x33000000@设置中断模式堆栈31msrcpsr_c,#0xdf@进入系统模式32ldrsp,=0x30100000@设置系统模式堆栈33blinit_irq@调用中断初始化函数,在init.c中34msrcpsr_c,#0x5f@设置I-bit=0,开IRQ中断35ldrlr,=halt_loop@设置返回地址36ldrpc,=main@b指令和bl指令只能前后跳转32M的范围,@所以这里使用向pc赋值的方法进行跳转37halt_loop:38bhalt_loop39HandleIRQ:40sublr,lr,#4@计算返回地址41stmdbsp!,{r0-r12,lr}@保存使用到的寄存器42ldrlr,=int_return@设置返回地址43ldrpc,=EINT_Handle@调用中断处理函数,在interrupt.c中44int_return:45ldmiasp!,{r0-r12,pc}^@中断返回,@^表示将spsr的值复制到cpsr请注意第12、15行,我们将IRQ中断向量由以前的“bHandleIRQ”换成了:12ldrpc,HandleIRQAddr15HandleIRQAddr:16.longHandleIRQ这是因为b跳转指令只能前后跳转32M的范围,而本实验中中断向量将重新放在VA=0xffff0000开始处(而不是通常的0x00000000),到HandleIRQAddr的距离远远超过了32M。将中断向量重新定位在0xffff0000处,是因为MMU使能后,中断发生时:1、如果中断向量放在0x00000000处,则对于不同的进程(PID),中断向量的MVA将不同2、如果中断向量放在0xffff0000处,则对于不同的进程(PID),中断向量的MVA也相同显然,如果使用1,则带来的麻烦非常大——对于每个进程,都得设置自己的中断向量。所以MMU使能后,处理中断的方法应该是2。第22行copy_vectors_from_nand_to_sdram函数将中断向量复制到内存物理地址0x33ff0000处,在mmu_tlb_init函数中会把0x33ff0000影射为虚拟地址0xffff0000。第23行copy_process_from_nand_to_sdram函数将存在nandflash开头的4K代码全部复制到0x30004000处(本实验的连接地址为0x30004000)。请注意SDRAM起始地址为0x30000000,前面的16K空间用来存放一级页表(在mmu_tlb_init中设置)。第27行mmu_tlb_init函数设置页表。本实验以段的方式使用内存,所以仅使用一级页表,且页表中所有页表项均为段描述符。mmu_tlb_init代码(在mmu.c中)如下:1voidmmu_tlb_init()2{3unsignedlongentry_index;4/*SDRAM*/5for(entry_index=0x30000000;entry_index0x34000000;entry_index+=0x100000){6/*sectiontable'sentry:AP=0b11,domain=0,Cached,write-throughmode(WT)*/7*(mmu_tlb_base+(entry_index20))=entry_index|(0x0310)|(05)|(14)|(13)|0x02;8}9/*SFR*/10for(entry_index=0x48000000;entry_index0x60000000;entry_index+=0x100000){11/*sectiontable'sentry:AP=0b11,domain=0,NCNB*/12*(mmu_tlb_base+(entry_index20))=entry_index|(0x0310)|(05)|(14)|0x02;13}14/*exceptionvector*/15/*sectiontable'sentry:AP=0b11,domain=0,Cached,write-throughmode(WT)*/16*(mmu_tlb_base+(0xffff000020))=(VECTORS_PHY_BASE)|(0x0310)|(05)|(14)|(13)|0x02;17}第4-8行令64MSDRAM的虚

1 / 6
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功