免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1132 | 回复: 0
打印 上一主题 下一主题

s3c2440 上性线地址到物理地址映射 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-20 09:44 |只看该作者 |倒序浏览
s3c2440外接RAM所在的地址空间0x30000000-0x34000000. MMU启用后,只能通过虚拟地址访问内存。线性地址就是虚拟地址。

下面是在u-boot进行试验的过程及代码:

将虚拟地址空间0x30000000-0x34000000映射到物理地址空间0x30000000-0x34000000
将虚拟地址空间0x48000000-0x60000000映射到物理地址空间0x48000000-0x60000000
以上映射的建立,使相应的虚拟地址与物理地址相同。

将虚拟地址空间0xc0000000-0xc4000000映射到物理地址空间0x30000000-0x34000000
以上映射建立后,虚拟地址空间0xc0000000-0xc4000000与0x30000000-0x34000000对应同一块物理地址空间。

当个修改0x30000000-0x34000000中某个地址的内容时,0xc0000000-0xc4000000中相应地址的内容也被修改了.

下面修改0x30130000的内容,然后查看0xc0130000的内容。其内容会相应的改变。
test.c文件的内容

#define COARSE_FLAGS    (1 | (1 << 4) ) //bit(1,0) = 01 coarse page base,
#define SMALL_MEM_FLAGS        (2 | (1 << 2) | ( 1 << 3)) //bit(1,0) = 10 4KB page, bit(3,2) = 11 write back cacheable
#define SMALL_IO_FLAGS        (2 ) //bit(1,0) = 10 4KB page, bit(3,2) = 00 nocached nobuffered


(*printf)(char *, ...) = 0x33f95964;

/*
 *前面0地址开始的4KB + 0x30000000开始的64MB
 *
 *1个一级页项表对应256个二级页表项
 *
 *1个二级页表项对应1个页帧
 *
 *1个页帧4KB
 *
 */


#define TTB 0x32000000; //ttb基址,也是一级页目录表基址
#define TTB_L2 (0x32000000 + 0x4000) //二级页表基址, 给一级页表留足16KB

unsigned long *ttb = (void *)TTB;
unsigned long *ttb_l2 = (void *)TTB_L2;

void memset(char *dst, char ch, int size);
void _start(void)
{
    unsigned long c1_flags;
    unsigned long virt, phys, temp, addr;
    int *p;

    memset(ttb, 0x00, 4096 * 4);

    c1_flags = 1 | (1 << 1) | (0xf << 3) | (0x3 << 30); //bit0 = 1 MMU enable,bit1 = 1 fault check, bit6..3 = 0xf write, bit31,30 = 0x3 async clock mode

/*第一个4KB, 第一页*/
    ttb[0] = ((unsigned long)ttb_l2) | COARSE_FLAGS;
    ttb_l2[0] = 0 | SMALL_MEM_FLAGS;
    ttb_l2 = TTB_L2 + 256 * 4;
/*线性地址空间[0x30000000, 0x34000000] 映射到物理地址空间[0x30000000, 0x34000000]*/
    for (addr = 0x30000000; addr < 0x34000000; ttb_l2 += 256) {
        ttb[addr >> 20]    = ((unsigned long )ttb_l2 & 0xfffffc00) | COARSE_FLAGS;

        temp = addr + 0x100000; //限定处理1MB空间对应的页表

        for (; addr < temp; addr += 0x1000) {
            ttb_l2[(addr & 0xff000) >> 12] = (addr & 0xfffff000) | SMALL_MEM_FLAGS;
        }    
    }
    
/*线性地址空间[0x48000000, 0x60000000] 映射到物理地址空间[0x48000000, 0x60000000]*/
    for (addr = 0x48000000; addr < 0x60000000; ttb_l2 += 256) {
        ttb[addr >> 20]    = ((unsigned long)ttb_l2 & 0xfffffc00) | COARSE_FLAGS;

        temp = addr + 0x100000; //限定处理1MB空间对应的页表

        for (; addr < temp; addr += 0x1000) {
            ttb_l2[(addr & 0xff000) >> 12] = (addr & 0xfffff000) | SMALL_IO_FLAGS;
        }
    }

/*线性地址空间[0xc0000000, 0xc4000000] 映射到物理地址空间[0x30000000, 0x34000000]*/
    for (virt = 0xc0000000; virt < 0xc4000000; ttb_l2 += 256) {
        ttb[virt >> 20]    = ((unsigned long )ttb_l2 & 0xfffffc00) | COARSE_FLAGS;

        temp = virt + 0x100000; //每一个一级页表项限定处理1MB空间对应的页表

        for (; virt < temp; virt += 0x1000) {
            phys = virt - 0xc0000000 + 0x30000000; //虚拟地址与物理地址之间的关系

            ttb_l2[(virt & 0xff000) >> 12] = (phys & 0xfffff000) | SMALL_MEM_FLAGS;
        }    
    }
//------------------------------------------


    __asm__ __volatile__ (    
        "mov r0, #0\n"            
        "mcr p15, 0, r0, c7, c7, 0\n" //清除I-cache和D-cache的内容:
        "mcr p15, 0, r0, c8, c7, 0\n" //清除I & D TLB 的内容

        "mvn r0, #0\n"
        "mcr p15, 0, r0, c3, c0, 0\n" //clear Domain access control
        //--------------------------------
        "mcr p15, 0, %1, c2, c0, 0\n" //ttb写入c2
        "mcr p15, 0, %0, c1, c0, 0\n" //c1_flags写入c1
        :
        : "r" (c1_flags), "r" (ttb)
        : "r0"
    );
/*先看初始值*/
    virt = 0x30130000;
    printf("0x30130000 = %x\n", *(int *)virt);
    virt = 0xc0130000;
    printf("0xc0130000 = %x\n", *(int *)virt);

/*修改0x30130000地址处的值, 再看0xc0130000处的值*/
    virt = 0x30130000;
    *(int *)virt = 0x2222;
    virt = 0xc0130000;
    printf("0xc0130000 = %x\n", *(int *)virt);

/*修改0x30130000地址处的值, 再看0xc0130000处的值*/
    virt = 0x30130000;
    *(int *)virt = 0x3333;
    virt = 0xc0130000;
    printf("0xc0130000 = %x\n", *(int *)virt);
}

void memset(char *dst, char ch, int size)
{
    int i;
    for (i = 0; i < size; i ++) {
        dst[i] = ch;
    }
}


Makefile内容:

PREFIX    = ~/tftpboot
EXEC_PREFIX    = /usr/local/arm/3.4.1/bin/arm-linux-
TARGET     ?= test

REMOVE    = rm -f

CC    = $(EXEC_PREFIX)gcc
LD    = $(EXEC_PREFIX)ld
OBJCOPY    = $(EXEC_PREFIX)objcopy

C_FLAGS    = -march=armv4 -c -o
LD_FLAGS    = -o

$(TARGET):$(TARGET:=.o)
    $(LD) -T $(@:=.lds) $(LD_FLAGS) $@ $^
    $(OBJCOPY) -I elf32-littlearm -O binary $@ $(PREFIX)/$(@:=.bin)

%.o:%.c
    $(CC) $(C_FLAGS) $@ $<

%.o:%.S
    $(CC) $(C_FLAGS) $@ $<


.PHONY:clean
clean:
    $(REMOVE) $(TARGET) $(TARGET:=.bin) $(TARGET:=.o) ~*


1.执行make之后生面test.bin文件
2.在u-boot的命令行界面加载test.bin文件
    tftp 30000000 test.bin
3.在u-boot的命令行界面执行
    go 30000000
4.显示结果:
## Starting application at 0x30000000 ...
    0x30130000 = 3333
       0xc0130000 = 3333
       0xc0130000 = 2222
       0xc0130000 = 3333
## Aplication terminated, rc = 0x0



您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP