色偷偷偷亚洲综合网另类,亚洲欧美另类在线观看,欧美午夜激情在线,久久久精品一区

當前位置:首頁 > 嵌入式培訓(xùn) > 嵌入式學(xué)習 > 講師博文 >
裸奔之MMU
時間:2018-08-16作者:華清遠見

一、MMU的介紹

MMU全稱Memory Management Unit,中文稱內(nèi)存管理單元

主要有兩個功能:
        A.將虛擬地址轉(zhuǎn)換成實際的物理地址
        B.對物理內(nèi)存設(shè)置訪問權(quán)限

二、MMU的工作過程

在s3c2410中MMU是由協(xié)處理器(cp15)控制的,s3c2410/s3c2440多會用到兩級頁表:以段(Section,1MB)的方式進行轉(zhuǎn)換時只用到一級頁表,以頁(page)的方式進行轉(zhuǎn)換時用到兩級頁表。頁的大小有3種:大頁(64KB),小頁(4KB),極小頁(1KB)。

明確一個概念:
        條目也稱為"描述符"(Descriptor),有:段描述符,大頁描述符,小頁描述符,極小頁描述符----它們保存段、大頁、小頁或極小頁的起始物理地址;粗頁表描述符、細頁表描述符---他們保存二級頁表的物理地址

轉(zhuǎn)換過程如下:
        (1) 根據(jù)給定的虛擬地址找到一級頁表中的條目
        (2)如果此條目是段描述符,則返回物理地址,轉(zhuǎn)換結(jié)束
        (3)如果此條目是二級頁表描述符,繼續(xù)利用虛擬地址在二級頁表中找到下一個條目;
        (4)如果這第二個條目是葉描述符,則返回物理地址,轉(zhuǎn)換結(jié)束;
        (5)其他情況出錯

注意:這里面所有的轉(zhuǎn)換過程都是由MMU完成的

以段的方式映射實例說明:

例如:虛擬地址 0xa0004000
       nbsp; 注意:當MMU打開以后,所有的地址都會被MMU攔截,然后將其轉(zhuǎn)換,cpu是不管虛擬地址還是實際物理地址的。

轉(zhuǎn)換如下:

先來看看TTB

簡單的來說,它保存了一級頁表所存放的實際物理地址,要求16KB對齊,以段的方式映射,4GB的虛擬地址空間,需要段描述符4096個(每個段描述符映射1M空間),沒個描述符占用4byte,所以一段的方式映射一級頁表占用的空間為16KB。

在這里我們假設(shè),我們的一級頁表存放在物理地址:0x30000000.

第一步:
        獲得虛擬地址所對應(yīng)的段描述符所在的地址
        addr = TTB&0xffffc000 | ((viraddr >> 20) << 2 ) = 0x30000000 & 0xfffc000 | ((0xa0004000 >> 20) << 2)= 0x30000000 | (0xa00 << 2) = 0x30002800

第二步:
        從0x30002800取出虛擬地址所對應(yīng)的段描述符

段描述的構(gòu)造我們到后面再來講解,這里我們假設(shè)我們把0xa0004000映射到實際的物理地址0x30004000,則這里的[31:20]為0x300

第三步:
        組合成實際的物理地址

phyaddr = 0x300 << 20 | (0xa0004000 & 0xfffff) = 0x30004000

三.實驗
        目標:以段的方式映射s3c2410的地址空間,一級頁表存放在0x30000000

流程:
        A.計算每個虛擬地址對應(yīng)段描述符所在的地址(addr),方法如下:

B.構(gòu)造段描述符

注意:Section base address 存放的是實際的物理地址的[31:20]

C.存放段描述符
        (unsigned int *)addr = section descriptor

D.使能MMU

整個流程比較復(fù)雜的就是段描述符的構(gòu)造,具體的流程大家可以直接看芯片手冊,寫的很詳細

實例代碼:

/*Nand 啟動sdram的起始地址*/
        #define SRAM_START_ADDR        0x00000000
        /*內(nèi)存空間地址*/
        #define VMRAM_ADDR_START        0xa0000000
        #define SDRAM_ADDR_END 0x34000000
        /*IO空間地址*/
        #define VMIO_ADDR_START 0xb0000000
        #define PHIO_ADDR_START 0x56000000
        #define PHIO_ADDR_END 0x56010000
        /*用SDRAM起始地址開始的16KB,存放頁表*/
        #define PAGE_TABLE_BASE 0x30000000
        /*MASK*/
        #define PAGE_TABLE_BASE_MASK 0xffffc000
        #define VIRADDR_MASK 0xfff00000
        #define PHYADDR_MASK 0xfff00000
        /*頁表項內(nèi)容*/
        #define PAGE_TABLE_SECTION_AP (0x01 << 10)
        #define APGE_TABLE_SECTION_DOMAIN (0x0 << 5)
        #define PAGE_TABLE_SECTION_CACHE_WB (0x0 << 2)
        #define PAGE_TABLE_SECTION_4BIT (1 << 4)
  &nnbsp;     #define PAGE_TABLE_SECTION_TYPE (0x2)
        /*段大小*/
        #define SECTION_SIZE 0x100000
        //根據(jù)虛擬地址和頁表基地址確定頁表項所在的物理地址

unsigned int get_pgtindex_addr(unsigned int viraddr,unsigned int pgtaddr)
        {
        unsigned int addr;
        /*[31:14]頁表基地地址
        *[13: 2]虛擬地址>>20位得到的page index
        *[1 : 0]總是為0,因為每一項占用4byte
        */
        addr = (pgtaddr & PAGE_TABLE_BASE_MASK) | (((viraddr & VIRADDR_MASK) >> 20) << 2);
        return addr;
        }

//獲取頁表項

unsigned int get_page_entry(unsigned int phyaddr)
        {
        unsigned int entry_value;
        /*[31:20]section base address
                *[19:12]
                *[11:10]AP
                *[9]
                *[8:5]Domain
                *[4]:1
                *[3]:C
                *[2]:B
                *[1:0]:Type
                */
        entry_value = (phyaddr & PHYADDR_MASK) | PAGE_TABLE_SECTION_AP |\
        PAGE_TABLE_SECTION_CACHE_WB | PAGE_TABLE_SECTION_4BIT|\
        PAGE_TABLE_SECTION_TYPE;
        return entry_value;
        }

/*創(chuàng)建一級頁表:段描述符*/

void create_page_table()
        {
        int i;
        unsigned int pgt_index_addr;
        unsigned int viraddr,phyaddr,pgtaddr;
        /*我們代碼的起始運行地址0x00000000在這里需要注意的是:當我們開啟MMU后,cpu發(fā)出的地址都會被MMU攔截,要想程序正常運行,pc所用的的地址必須是虛擬地址。然而此時cpu執(zhí)行下一條指令實際運行的地址是物理地址,但是MMU會將此物理地址當作虛擬虛擬地址處理。暈,亂套了。為了解決這個問題,我們通常的做法是,讓開啟MMU的附近地址指令的虛擬地址和物理地址空間做一個等價的映射。在這里我們將0x00000000開始的1M物理空間映射到0x00000000開始的虛擬地址空間。*/ 
        phyaddr = SRAM_START_ADDR;
        viraddr = phyaddr;
        pgtaddr = PAGE_TABLE_BASE;
        pgt_index_addr = get_pgtindex_addr(viraddr,pgtaddr); 
        *(volatile unsigned int *)pgt_index_addr = get_page_entry(phyaddr);
        #if 1
        /*映射64MSDRAM*/
        for(phyaddr = SDRAM_ADDR_START,viraddr = VMRAM_ADDR_START;\
        phyaddr < SDRAM_ADDR_END;phyaddr += SECTION_SIZE,\
        viraddr += SECTION_SIZE)
        {
                pgtaddr = PAGE_TABLE_BASE;
                pgt_index_addr = get_pgtindex_addr(viraddr,pgtaddr);
                *(volatile unsigned int *)pgt_index_addr = get_page_entry(phyaddr);
        }
        #endif 
        /*映射IO地址空間*/
        phyaddr = PHIO_ADDR_START;
        viraddr = VMIO_ADDR_START;
        pgtaddr = PAGE_TABLE_BASE;
        pgt_index_addr = get_pgtindex_addr(viraddr,pgtaddr);
        *(volatile unsigned int *)pgt_index_addr = get_page_entry(phyaddr); 
        return;
        }

/*
        Care must be taken if the translated address differs from the
        untranslated address as several instructions following the 
        enabling of the MMU may have been prefetched with the MMU off 
        (using physical = virtual address - flat translation) and enabling 
        the MMU may be considered as a branch with delayed execution. A similar
        situation occurs when the MMU is disabled. Consider the following code 
        sequence:
        MRC    p15, 0, R1, c1, C0, 0: Read control rejectio
        ORR    R1, #0x1
        MCR    p15,0,R1,C1, C0,0 ; Enable MMUS
        Fetch    Flat
        Fetch    Flat
        Fetch    Translated
        */

void init_mmu()
        {
        unsigned long mmu_table_base = PAGE_TABLE_BASE;
        asm(
                /*set Translation Table Base(TTB) register*/
                "mrc p15,0,r0,c2,c0,0\n"
                "mov r0,%0\n"
                "mcr p15,0,r0,c2,c0,0\n"
                /*set Domain Access Control register*/
                "mrc p15,0,r0,c3,c0,0\n"
                "mvn r0,#0\n"
                "mcr p15,0,r0,c3,c0,0\n"
                /*Enable MMU*/
                "mrc p15,0,r0,c1,c0,0\n"
                "orr r0, #0x1\n"
                "mcr p15,0,r0,c1,c0,0\n"
                "mov r0,r0\n"
                "mov r0,r0\n"
                "mov r0,r0\n"
                :
                :"r"(mmu_table_base)
                :"r0"
    &nnbsp;           );
        return;
        }
        start.S
        .text
        .global _start
        _start:

#define pWTCON 0x53000000
        #define  CLKDIVN  0x4c000014
        #define  MPLLCON  0x4c000004
        #define  MEMBASE  0x48000000
        #define  SRAM_2_ADDR  2048 
        #define  SDRAM_2_ADDR  0x30004000
        #define  SRAM_SIZE  4096 

start_code:
        @set the cpu to SVC32 mode
        mrs r0,cpsr
        bic r0,r0,#0x1f
        orr r0,r0,#0xd3
        msr cpsr,r0 

@打開指令cache
        mrc p15,0,r0,c1,c0,0
        @orr r0,r0,#0x1000
        mcr p15,0,r0,c1,c0,0

@設(shè)置棧指針位置
        ldr sp,=4096
        @關(guān)看門狗
        bl disable_watchdog
        @初始化系統(tǒng)時鐘
        bl init_sys_clock
        @初始化內(nèi)存
        bl init_sdram
        @拷貝SRAM的代碼到SDRAM
        bl copy_to_sdram
        @創(chuàng)建頁表
        bl create_page_table
        @啟動MMU 
        bl init_mmu
        @運行l(wèi)ed程序
        ldr sp,=0xa3000000 @重設(shè)sp指針,mmu之后,@cpu操作的地址都是虛擬地址 
        ldr pc,_main
        halt_loop:
        b halt_loop
        _main:
        .word main
        disable_watchdog:
        @關(guān)看門狗,不然cpu會不斷重啟
        ldr r0,=pWTCON
        mov r1,#0
        str r1,[r0]
        mov pc,lr
        init_sys_clock:
        @目前為止,cpu工作在12MHZ頻率下
        @提升cpu工作頻率FCLK:HCLK:PCLK=1:2:4
        ldr r0,=CLKDIVN
        mov r1,#3
        str r1,[r0]
        @ifHDIVN=1,must asynchronous buf mode
        mrc p15,0,r0,c1,c0,0
        orr r0,r0,#0xc0000000
        mcr p15,0,r0,c1,c0,0
        @設(shè)置MPLL,使cpu工作在202.80MHZ
        ldr r0,=MPLLCON
        ldr r1,=0x000a1031
        str r1,[r0] 
        mov pc,lr

copy_to_sdram:
        ldr  r0,=SRAM_2_ADDR  @第二階段代碼起始地址(2048)
        ldr  r1,=SDRAM_2_ADDR  @第二階段代碼存放的物理地址(0x30004000)

1:
        ldr  r2,[r0],#4
        str  r2,[r1],#4
        cmp  r0,#SRAM_SIZE
        bne  1b
        mov  pc,lr
        init_sdram:
        @初始化sdram
        ldr  r0,=MEMBASE  @13個寄存器的首地址
        adrl  r1,SMRDATA  @13個寄存器值存放的地址
        mov  r2,#52 @13 * 4 = 52 
        add  r2,r2,r1 

1:
        ldr  r3,[r1],#4
        str  r3,[r0],#4
        cmp  r1,r2
        bne  1b
        /*every thing is fine now*/
        mov  pc,lr
        .ltorg  @聲明一個數(shù)據(jù)緩沖池的開始
        SMRDATA:
        .word  0x2201d110        @BWSCON 設(shè)置BANK3位寬16,使能nWait,使能UB/LB
        .word  0x0700 @BANKCON0
        .word  0x700 @BANKCON1
        .word  0x700 @BANKCON2
        .word  0x700 @BANKCON3
        .word  0x700 @BANKCON4
        .word  0x700 @BANKCON5
        .word  (3 << 15) + (1 << 0) @BANKCON6
        .word  0x18001 @BANKCON7
        .word  (1 << 23) + (2 << 18) + (1256 << 0) @REFRESH
        .word  (1 << 7) + (1 << 0) @BANKSIZE
        .word  (3 << 4) @MRSRB6
        .word  (3 << 4) @MRSRB7

led.c
        //#include "s3c2410.h"
        /*虛擬地址*/
        #define GPFCON        (*(volatile unsigned long *) 0xb0000050)
        #define GPFDAT        (*(volatile unsigned long *) 0xb0000054)
        //初始化
        static inline void led_init()
        {
        //GPFCON -> [8:15]清零
        GPFCON &= ~(0xff << 8);
        //GPF4 GPF5 GPF6 GPF7設(shè)為輸出模式
        GPFCON |= 0x55 << 8;
        //輸出高低平,關(guān)閉四路LED燈
        GPFDAT |= 0xf << 4;
        return;
        }
        //關(guān)閉LED
        static inline int led_off()
        {
        GPFDAT |= 0xf << 4;
        return 0;
        }
        //延時函數(shù)
        static inline int delay_time(int time)
        {
        int i,j;
        //讓兩個for循環(huán)作為延時
        for(i = 0;i < time;i ++)
        for(j = 0;j < time;j ++);
        return 0;
        }
        //流水燈
        static inline int run_water_led(int count)
        {
        int i = 0;
        while(count --)
        {
        led_off();
        delay_time(500);
        for(i = 4;i < 8;i ++)
        {
                GPFDAT &= ~(0x1 << i);
                delay_time(500);
                }
        }
        return 0;
        }

int main()
        { 
                led_init();
                run_water_led(5); 
                led_off(); 
                delay_time(5000);
                return 0; 
        } 
        Makefile:
        led.bin:start.S led.c
        arm-none-linux-gnueabi-gcc -c start.S -o start.o
        arm-none-linux-gnueabi-gcc -c mmu.c -o mmu.o
        arm-none-linux-gnueabi-gcc -c led.c -o led.o
        #arm-none-linux-gnueabi-ld -Ttext 0x00000000 start.o led.o -o led_elf
        arm-none-linux-gnueabi-ld -Tmap.lds start.o mmu.o led.o -o led_elf
        arm-none-linux-gnueabi-objcopy -O binary -S led_elf led.bin
        cp led.bin /tftpboot
        clean:
        rm -rf *.o led_elf led.bin
        連接腳本(map.lds)
        OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
        /*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
        OUTPUT_ARCH(arm)
        ENTRY(_start)
        SECTIONS
        {
                firtst 0x00000000:
               &nbsnbsp;{
                        start.o
                        mmu.o
                }
                second 0xa0004000:
                AT(2048)
                        {
                                led.o
                        }
        }


發(fā)表評論

全國咨詢電話:400-611-6270,雙休日及節(jié)假日請致電值班手機:15010390966

在線咨詢: 曹老師QQ(3337544669), 徐老師QQ(1462495461), 劉老師 QQ(3108687497)

企業(yè)培訓(xùn)洽談專線:010-82600901,院校合作洽談專線:010-82600350,在線咨詢:QQ(248856300)

Copyright 2004-2018 華清遠見教育科技集團 版權(quán)所有 ,京ICP備16055225號,京公海網(wǎng)安備11010802025203號

色偷偷偷亚洲综合网另类,亚洲欧美另类在线观看,欧美午夜激情在线,久久久精品一区
主站蜘蛛池模板: 亚洲一二三在线| 亚洲国产小视频在线观看| 91久久综合亚洲鲁鲁五月天| 日韩激情片免费| 欧美乱大交xxxxx另类电影| 国产91色在线|| 国产亚洲精品久久久久久牛牛| 高跟丝袜欧美一区| 成人啪啪免费看| 欧美猛交免费看| 国产视频福利一区| 久久电影一区二区| 国产精品一区二区三区毛片淫片| 最新国产精品亚洲| 国产99视频在线观看| 在线精品91av| 国产精品久久久一区| 久久在线观看视频| 亚洲综合在线播放| 欧美黑人性生活视频| 精品伊人久久97| 日韩av大片免费看| xxx一区二区| 成人精品一区二区三区电影黑人| 久久777国产线看观看精品| 亚洲aaa激情| 2021国产精品视频| 综合国产在线观看| 国产噜噜噜噜噜久久久久久久久| 欧美日韩国产二区| 日韩成人中文字幕| 国产成人精品视频| 精品久久久久久久中文字幕| 日韩精品小视频| 国产精品普通话| 色综合久久悠悠| 在线日韩第一页| 96pao国产成视频永久免费| 91超碰中文字幕久久精品| 久久av在线看| 国产性猛交xxxx免费看久久|