新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > S3C2440之MMU操作(MDK4.22)

        S3C2440之MMU操作(MDK4.22)

        作者: 時間:2016-11-19 來源:網絡 收藏
        關于MMU知識:

        1.ARM CPU上的地址轉換過程涉及到了3個概念,虛擬地址VA,變換地址MVA,物理地址PA。當沒有啟動MMU的時候,CPU核,CACHE,MMU見到的都是PA。

        本文引用地址:http://www.104case.com/article/201611/318144.htm

        啟動MMU之后,CPU核對外發出VA,VA被轉換為MVA,供給CACHE和MMU使用,MMU再將MVA轉換為PA,最終找到真實的地址。

        CPU看見的VA,CACHE和MMU看不見VA,看見的是MVA;設備只看到VA。

        轉換算法:如果VA<32M,那么使用進程PID來轉換,PID通過CP15的C13讀取。

        if(VA<32M) then

        MVA = VA | (PID << 25);

        else

        MVA = VA; //VA >= 32M

        2.協處理器的cp15寄存器c2的31-14位存放一級頁表的地址,一級頁表有4096項,每項4字節,共16k,所以c2的0到13位不使用

        若為段映射,只需要一級頁表,每段1M,4096*1M=4G空間;若為頁映射就需要二級頁表,目標的物理頁有大頁,小頁,極小頁。


        3.一級頁表的描述符和二級頁表描述符


        注意到一級描述符是用來指引二級描述符的,除了段的直接指引到物理內存,若使用二級頁表的話,那么二級頁表類型有粗頁表,細頁表兩種。

        粗頁表256項,每項指引真是內存為4K大小,本身占256*4=1k字節;細頁表1024項,每項指引1k大小,本身二級頁表占1024*4=4k字節。

        所以注意到,若要對應真實物理頁的大頁的話,怎么辦呢?利用粗頁的話,需要16個粗頁二級描述符;利用細頁的話,需要64個二級描述符。


        4段的轉換舉例


        5內存訪問權限問題

        注意到一級頁表中的描述符中有domain字段,4位,共16種情況


        對應的為cp15中的c3寄存器設置。

        00無訪問權限,任何訪問都會導致domain fault異常

        01客戶模式,使用段描述符,頁描述符進行權限檢查

        10保留

        11管理模式,不進行權限檢查,運行任何訪問

        cp15中的c3 + domain + cp15寄存器c1中的R/S/A位 + 描述符AP共同決定訪問權限

        6TIB和Cache的作用

        TLB是為了減輕頁表訪問所帶來的訪問內存負擔,利用程序訪問的局部性原理,選擇高速且容量較小的存儲器存儲近期使用的頁表條目。

        一般做法:在啟動MMU之前使無效整個TLB;更改頁表表項的時候,使無效所涉及到的虛擬地址所對應到的TLB條目。

        Cache的作用,在主存和CPU通用寄存器之間設置一個高速,容量相對較小的存儲器。把正在執行的指令的附近一部分數據或者指令從主存調入這個

        存儲器,供CPU在一段時間內使用。Cache的(1)clean操作是將cache或writerbuffer已經臟的數據寫入主存(2)invalidate不將數據寫入主存,使之不能

        再使用而已。

        cp15的寄存器1的12位Icr位開啟Icaches;第2位寫1開啟Dcaches;Writterbuffer和Dcache緊密結合,沒有專門的控制為開啟,停止它。

        程序部分:

        本程序將0-1M映射為本身,將0xa0000000~0xa000fffff映射為0x56000000~0x560ffffff,將0xb0000000~0xb3ffffff映射為0x30000000~0x3fffffff

        涉及到代碼文件有s3c2440.s文件,init.c文件,led.c文件,led.sct文件

        s3c2440.s主要是調用一些初始化程序,init.c是初始化代碼,led.c只是利用新的虛擬地址尋找gpio,點亮led。

        編譯器MDK4.22a

        led.sct文件如下所示:

        LR_ROM1 0x00000000 0x00200000 { ; load region size_region
        NANDFLASH 0x00000000 0x00200000 { ; load address = execution address
        *.o (initcode, +First)
        .ANY (+RO)
        }
        }


        LR_ROM2 2048 2048 {
        SDRAM 0xb0004000 {
        led.o (*)
        }
        }

        存在多個加載域,會產生多個bin,可以參見的另一篇文章講到如何連接多個bin文件S3C2440開發工具realview MDK4.22使用入門

        init.c文件:

        //creat page table
        void create_page_table(void)
        {
        #define MMU_FULL_ACCESS(3<<10)
        #define MMU_DOMAIN(0<<5)
        #define MMU_SPECIAL(1<<4)
        #define MMU_CACHEABLE(1<<3)
        #define MMU_BUFFERABLE(1<<2)
        #define MMU_SECTION(2<<0)
        #define MMU_SECDESC(MMU_FULL_ACCESS | MMU_DOMAIN | MMU_SPECIAL |
        MMU_SECTION)
        #define MMU_SECDESC_WB(MMU_FULL_ACCESS | MMU_DOMAIN | MMU_SPECIAL |
        MMU_SECTION | MMU_CACHEABLE | MMU_BUFFERABLE)
        #define MMU_SECTION_SIZE0x00100000

        ulong virtualaddr, physicaladdr;
        ulong *mmu_tlb_base = (ulong*)0x30000000;

        /*<1>0~1M map to 0~1M virtualaddr == physicaladdr*/
        virtualaddr = 0;
        physicaladdr = 0;


        //mmu page table store at 0x30000000
        //vritualaddr>>20 is index of mmu page table
        *(mmu_tlb_base + (virtualaddr>>20)) = (physicaladdr&0xfff00000) | MMU_SECDESC_WB;

        /*<2>0xa0000000~0xa000fffff map to 0x56000000~0x560fffff*/
        virtualaddr = 0xa0000000;
        physicaladdr = 0x56000000;
        *(mmu_tlb_base + (virtualaddr>>20)) = (physicaladdr&0xfff00000) | MMU_SECDESC;


        /*<3>0xb0000000~0xb3ffffff map to 0x30000000~0x33fffffff total=64m totaldescs=64*/
        virtualaddr = 0xb0000000;
        physicaladdr = 0x30000000;

        while(virtualaddr < (ulong)0xb4000000)
        {
        *(mmu_tlb_base + (virtualaddr>>20)) = (physicaladdr&0xfff00000) | MMU_SECDESC_WB;
        virtualaddr += MMU_SECTION_SIZE;
        physicaladdr += MMU_SECTION_SIZE;
        }
        }




        //init MMU
        void mmu_init(void)
        {
        ulong ttb = 0x30000000;

        __asm{
        mov r0,#0
        mcr p15,0,r0,c7,c7,0 //invalidate Icache Dcache

        mcrp15,0,r0,c7,c10,4//drain writer buffer
        mcr p15,0,r0,c8,c7,0 //invalidate TLB

        mov r4,ttb
        mcr p15,0,r4,c2,c0,0 //set page table base-addr

        mvn r0,#0 //invert all bits:0x0000000->0xffffffff
        mcr p15,0,r0,c3,c0,0 //set domain(all is 0b11)


        mrc p15,0,r0,c1,c0,0 //read control register

        bic r0,r0,#0x3000
        bic r0,r0,#0x0300
        bic r0,r0,#0x0087

        orr r0,r0,#0x0002
        orr r0,r0,#0x0004
        orr r0,r0,#0x1000
        orr r0,r0,#0x0001

        mcr p15,0,r0,c1,c0,0

        };
        }



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 宝丰县| 天津市| 古交市| 马鞍山市| 阿坝县| 望城县| 武穴市| 深泽县| 鄂托克前旗| 宁都县| 垫江县| 邹城市| 水城县| 腾冲县| 恩施市| 龙口市| 襄汾县| 东乡| 石河子市| 班玛县| 鄂托克前旗| 山东省| 葵青区| 常德市| 东山县| 海盐县| 闸北区| 琼中| 武汉市| 凉山| 安泽县| 茌平县| 合水县| 吴江市| 上林县| 麻江县| 都江堰市| 石屏县| 略阳县| 汉阴县| 南郑县|