[Funkunux] 自己写MMU实验 基于S3C2440

代码的顺序分别为head.S, led.c, Makefile
我把0x56000000映射到0xb0000000,把sdram的地址映射到0xa0000000,这里的做法也和韦老师的相反,主要内容是head.S


.text
.global _start
_start:
    bl Disable_Watch_Dog
    bl MemSetup
    bl MMUSetup
    bl Copy_SteppingStone_to_Sdram
    ldr pc,=On_Sdram
    
    
    
Disable_Watch_Dog:              ;关看门狗
    mov r1,#0x53000000
    mov r2,#0
    str r2,[r1]
    mov pc,lr
    
MemSetup:                       ;初始化SDRAM
    mov r1,#0x48000000
    adrl r2,SetMem_avl
    ldr r3,=0x48000034
Loop1:
    ldr r4,[r2],#4
    str r4,[r1],#4
    cmp r1,r3
    bne Loop1
    mov pc,lr
    
Copy_SteppingStone_to_Sdram:    ;将程序复制到虚拟地址0xa0004000处运行
    mov r1,#0
    ldr r2,=0xa0004000
    mov r3,#4096
Loop2:
    ldr r4,[r1],#4
    str r4,[r2],#4
    cmp r3,r1
    bne Loop2
    mov pc,lr

MMUSetup: ;初始化MMU ;建立4G内存空间页表 mov r4,#0x30000000 ;页表基址 ldr r3,=0x00000c12 ;domain 0,uncached,unbuffered mcr p15, 0, r4, c2, c0, 0 ;将页表基址存入C2中 ldr r5,=0x1000 ;循环4K次(4K*1MB=4GB) l1: str r3,[r4],#4 ;建立页表 add r3,r3,#(1<<20) ;更新描述符 subs r5,r5,#1 bne l1 ;映射0x56000000到0xb0000000 mov r4,#0x30000000 ;页表基址 ldr r3,=0x00000c12 ;domain 0,uncached,unbuffered ldr r1,=0xfff00000 mov r2,#0xb0000000 ;VA mov r0,#0x56000000 ;PA and r2,r2,r1 orr r3,r3,r0 ;段描述符 4Byte add r4,r4,r2,lsr #(18) ;描述符地址=基址+虚拟段地址>>(20-2)位 ([1:0]位为00,4字节对齐) str r3,[r4]

;映射0x30000000到0xa0000000 mov r4,#0x30000000 ldr r3,=0x00000c1e ;domain 0,cached,buffered ldr r1,=0xfff00000 mov r2,#0xa0000000 ;VA mov r0,#0x30000000 ;PA and r2,r2,r1 orr r3,r3,r0 ;段描述符 4Byte add r4,r4,r2,lsr #(18) ;描述符地址=基址+虚拟段地址>>(20-2)位 ([1:0]位为00,4字节对齐) mov r5,#64 ;SDRAM总共有64MB 循环64次 l2: str r3,[r4],#4 add r3,r3,#(1<<20) subs r5,r5,#1 bne l2 mov r0,#0 mcr p15,0,r0,c7,c7,0 ;使无效ICache和DCache mcr p15,0,r0,c7,c10,4 ;清空缓冲区 mcr p15,0,r0,c7,c5,4 ;清空预取缓冲区 mcr p15,0,r0,c7,c5,6 ;清空整个跳转目标cache mcr p15,0,r0,c8,c7,0 ;使无效TLB mvn r0,#0 mcr p15,0,r0,c3,c0,0 ;域访问控制寄存器设为0xFFFFFFFF,不进行权限检查

mrc p15,0,r0,c1,c0,0 ;读取C1内容到R0 bic r0,r0,#0x3000 bic r0,r0,#0x380 bic r0,r0,#0x7 orr r0,r0,#0x1000 orr r0,r0,#0x7 ;开启对齐检查,使能ICache,使能DCache,打开MMU mcr p15,0,r0,c1,c0,0 ;将R0中内容写回C1中 mov pc,lr On_Sdram: mov sp,#0xa4000000 ;设置栈顶在SDRAM最上方 bl main Halt_loop: b Halt_loop .align 4 SetMem_avl: @ 存储控制器13个寄存器的设置值 .long 0x02011110 @ BWSCON .long 0x00000700 @ BANKCON0 .long 0x00000700 @ BANKCON1 .long 0x00000700 @ BANKCON2 .long 0x00000700 @ BANKCON3 .long 0x00000700 @ BANKCON4 .long 0x00000700 @ BANKCON5 .long 0x00018009 @ BANKCON6 .long 0x00018009 @ BANKCON7 .long 0x00aC07A3 @ REFRESH .long 0x000000B1 @ BANKSIZE .long 0x00000030 @ MRSRB6 .long 0x00000030 @ MRSRB7/* * leds.c: 循环点亮4个LED * 属于第二部分程序,此时MMU已开启,使用虚拟地址 */ #define GPFCON (*(volatile unsigned long *)0xb0000050) // 物理地址0x56000050 #define GPFDAT (*(volatile unsigned long *)0xb0000054) // 物理地址0x56000054 #define GPF4_out (1<<(4*2)) #define GPF5_out (1<<(5*2)) #define GPF6_out (1<<(6*2)) /* * wait函数加上“static inline”是有原因的, * 这样可以使得编译leds.c时,wait嵌入main中,编译结果中只有main一个函数。 * 于是在连接时,main函数的地址就是由连接文件指定的运行时装载地址。 * 而连接文件mmu.lds中,指定了leds.o的运行时装载地址为0xB4004000, * 这样,head.S中的“ldr pc, =0xB4004000”就是跳去执行main函数。 */ static inline void wait(unsigned long dly) { for(; dly > 0; dly--); } int main(void) { unsigned long i = 0; GPFCON = GPF4_out|GPF5_out|GPF6_out; // 将LED1,2,4对应的GPF4/5/6三个引脚设为输出 while(1){ wait(30000); GPFDAT = (~(i<<4)); // 根据i的值,点亮LED1,2,4 if(++i == 8) i = 0; } return 0; }mmu.bin : head.S led.c arm-linux-gcc -c -o head.o head.S arm-linux-gcc -c -o led.o led.c arm-linux-ld -Ttext 0xa0004000 head.o led.o -o mmu_elf arm-linux-objcopy -O binary -S mmu_elf mmu.bin arm-linux-objdump -D -m arm mmu_elf > mmu.dis clean: rm -f mmu.dis mmu.bin mmu_elf *.o

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值