Chinaunix首页 | 论坛 | 博客
  • 博客访问: 371756
  • 博文数量: 56
  • 博客积分: 1449
  • 博客等级: 中尉
  • 技术积分: 822
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-08 10:24
文章分类

全部博文(56)

文章存档

2014年(7)

2012年(13)

2011年(10)

2010年(26)

分类:

2010-11-28 13:14:02

 在前面实验的基础上. 对MMU相关寄存器进行配置. 主要涉及到的是协处理器里的几个寄存器.
p15 c1:  这个寄存器中有几个比特位控制D/I cache 和 write buffer 主要是C/W/I比特位。
        使能MMU的比特为M,地址对齐检查A等...
p15 c2:  保存顶级页表的物理基址, 相当于x86里的cr0寄存器的作用
p15 c3:  硬件实现的16个域的访问权限控制,这里简单的设置为全1,即不进行检查
p15 c7:  这个寄存器比较复杂,命令比较多,实验中所用到的命令是invalidate I/D cache. clean write buffer
p15 c8:  invalidate TLB for D/I cache.、

为方便起见,只用一级页表,即段类型,一个页表项控制1MB的物理地址映射。
映射方案: 将steppingstone进行恒等映射,即将虚拟地址的第一个MB映射到物理地址的第一个MB,这也是为了方便。
          GPIO地址0x56000000开始的1MB对应虚拟地址0xf6000000开始的1MB。
          SDRAM地址0x3000000的SDRAM结束地址映射到虚拟地址的0xe0000000开始处。
          其余的不作映射处理。

前面实验中的start.S只需要稍微修改一下, lowlevel_init.S不变, main.c文件也不变, 添加init.c文件初始化mmu,建立页表。将mian.c文件对应的代码拷贝到SDRAM偏移0x4000处(因为SDRAM偏移0 - 0x3ff放置页表),还有一个链接脚本,控制目标文件在二进制可执行文件中的位置。

start.S文件:
#define SDRAM_BASE 0x30000000
#define WATCHDOG    0x53000000
#define GPBCON    0x56000010

#define LED4_SET_OUTPUT ((1<<10) | (1<<12) | (1<<14) | (1<<16))

.text
.global _start
_start:
    bl    disable_watchdog
    bl sdram_init
    ldr    sp, =4096
    bl    copy_main_to_sdram
    bl    paging_init
    bl    mmu_init
    ldr    sp, =0xe4000000
    ldr    pc, =0xe0004000

halt:
    b    halt

disable_watchdog:
    ldr    r0, =WATCHDOG
    mov    r1, #0
    str    r1, [r0]
    mov    pc, lr

init.c 文件

#define SDRAM_BASE 0x30000000
#define VIRTUAL_SDRAM_BASE 0xe0000000
#define SDRAM_LENGTH 0x4000000

#define PG_NO_CHECK        (3<<10)
#define PG_DOMAIN            (0<<5)
#define PG_RESERVED        (1<<4)
#define PG_CACHED            (1<<3)
#define PG_BUFFERED        (1<<2)
#define PG_SECTION_TYPE        (2<<0)

#define PG_SECTION_DCB    (PG_NO_CHECK | PG_DOMAIN | PG_RESERVED \
                                | PG_SECTION_TYPE)
#define PG_SECTION_ECB    (PG_SECTION_DCB | PG_CACHED | PG_BUFFERED)

#define SECTION_SIZE (0x100000UL)
#define SECTION_MASK (~(SECTION_SIZE - 1))

void copy_main_to_sdram(void)
{
/*
 *  when link the objects, i place the main.o at fixed pos, it's offset in the binay file is 2048
 *  see ld script in detail
 */
    unsigned long *src = (unsigned long *)2048;
    unsigned long *dst = (unsigned long *)(SDRAM_BASE + 0x4000);
    while(src < (unsigned long *)4096) {
        *dst = *src;
        src++;
        dst++;
    }
}

void paging_init(void)
{
    unsigned long vaddr, paddr;
    unsigned long *sdram_base = (unsigned long *)SDRAM_BASE;
   
    vaddr = 0;
    paddr = 0;
    *(sdram_base + (vaddr >> 20)) = (paddr & SECTION_MASK) \
                                                        | PG_SECTION_ECB;
   
    /* GPIO MAPPING, should not be cacheable and bufferable */
    vaddr = 0xf6000000;
    paddr = 0x56000000;
    *(sdram_base + (vaddr >> 20)) = (paddr & SECTION_MASK) \
                                                    | PG_SECTION_DCB;

    vaddr = VIRTUAL_SDRAM_BASE;
    paddr = SDRAM_BASE;
    while(paddr < SDRAM_BASE + SDRAM_LENGTH) {
        *(sdram_base + (vaddr >> 20)) = (paddr & SECTION_MASK) \
                                                        | PG_SECTION_DCB;
        vaddr += SECTION_SIZE;
        paddr += SECTION_SIZE;
    }
}
void mmu_init(void)
{
    unsigned long ttb = SDRAM_BASE;
    __asm__ (
        "mov    r0, #0\n\t"
        "mcr    p15, 0, r0, c7, c7, 0\n\t" /* invalidate Dcache and Icache */
        "mcr    p15, 0, r0, c7, c10, 4\n\t" /* clean write buffer */
        "mcr    p15, 0, r0, c8, c7, 0\n\t" /* invalidate TLB for Dcache and Icache*/

        "mov    r0, %0\n\t"     /* r4 = page table base addr*/
        "mcr     p15, 0, r0, c2, c0, 0\n\t"

        "mvn    r0, #0\n\t"
        "mcr    p15, 0, r0, c3, c0, 0\n\t"    /* do not check the domain priv */
       
        "mrc     p15, 0, r0, c1, c0, 0\n\t" /* read c1 to r0 */
        "bic    r0, r0, #0x3000\n\t" /* diable Icache, low intrrupt vector */
        "bic    r0, r0, #0x300\n\t" /* clear R, S bit */
        "bic    r0, r0, #0x87\n\t" /* clear B\C\A\M bit */
        "orr    r0, r0, #0x2\n\t" /* set A bit */
        "orr    r0, r0, #0x4\n\t" /* set C bit */
        "orr    r0, r0, #0x1000\n\t" /* set I bit */
        "orr    r0, r0, #0x1\n\t" /* set M bit,namely enable MMU */
        "mcr    p15, 0, r0, c1, c0, 0\n\t"
        ::"r"(ttb));
}
       

Makefile 文件:
 
CROSS_COMPILE := arm-linux-
CC := $(CROSS_COMPILE)gcc
CPP := $(CROSS_COMPILE)gcc -E
AS := $(CROSS_COMPILE)as
LD := $(CROSS_COMPILE)ld
OBJCOPY := $(CROSS_COMPILE)objcopy

OBJ = start.o lowlevel_init.o init.o main.o

all:u-boot.bin

u-boot.bin: test_elf
    $(OBJCOPY) -O binary -S $< $@

test_elf: $(OBJ)
    $(LD) -Tld.lds -o $@ $^

.S.s:
    $(CPP) -o $@ $<

.s.o:
    $(AS)  -o $@ $<

.c.o:
    $(CC) -c -o $@ $<

.PHONY clean:
clean:
    rm -f *.s *.o *.bin test_elf

ld.lds 链接脚本文件

SECTIONS {
    start    0x00000000 : { start.o lowlevel_init.o init.o }
    main 0xe0004000 : AT(2048) { main.o }
}



阅读(1637) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~