分类: LINUX
2009-11-12 22:55:07
今天晚上弄了一下如何在ADS程序中建立一级页表,并开MMU和cache的方法;其实要改的地方只有三个地方:
(1) 建立sdram的虚实映射页表描述符,在这里我的SDRAM的物理地址是0X30000000大小是
; 8.0x30000000映射到0x30000000 得到并写入1级页表
ldr r0, =0x30005000 ; R0寄存器加载1级页表描述符地址,具体配置如下:
ldr r1, =0x
add r2, r1, #0x2000000
11 ;循环将
str r1, [r0]
add r0, r0, #0x4
add r1, r1, #0x100000
teq r1, r2
bne %b11
(2) 我们既然将sdram映射到0x40000000的虚拟地址上面去了,我们就应该在编译链接我们ADS程序的时候就应该指定我们的连接起始地址,因此我的scat文件应该如下写法:
ESRAM 0x04000000
{
ESRAM 0x04000000
{
boot_gfd_mmu.o (BOOT, +First)
}
}
SDram 0x40000000
{
SDram1 0x40000000
{
int_gfd.o (INT, +First)
; main.o (+First)
* (+RO,+RW,+ZI)
}
}
(3) 既然链接地址改了,我们的堆栈地址也需要改变了,这里的堆栈地址是:
SP_USR EQU 0x40700000; ; USR模式下的堆栈首指针
SP_SYS EQU 0x40701000; ; SYS模式下的堆栈首指针
SP_SVC EQU 0x40702000; ; SVC模式下的堆栈首指针
SP_IRQ EQU 0x40703000; ; IRQ模式下的堆栈首指针
SP_FIQ EQU 0x40704000; ; FIQ模式下的堆栈首指针
SP_UND EQU 0x40705000; ; UND模式下的堆栈首指针
SP_ABT EQU 0x40706000; ; ABT模式下的堆栈首指针
下面贴下我的4020的起始代码boot_gfd_mmu.s
;*****************************************************************
;* 本文件中用到的常量定义
;*****************************************************************
SP_USR EQU 0x40700000;0x0400fff0; ; USR模式下的堆栈首指针
SP_SYS EQU 0x40701000;0x0400fef0; ; SYS模式下的堆栈首指针
SP_SVC EQU 0x40702000;0x0400fdf0; ; SVC模式下的堆栈首指针
SP_IRQ EQU 0x40703000;0x0400fcf0; ; IRQ模式下的堆栈首指针
SP_FIQ EQU 0x40704000;0x0400fbf0; ; FIQ模式下的堆栈首指针
SP_UND EQU 0x40705000;0x0400faf0; ; UND模式下的堆栈首指针
SP_ABT EQU 0x40706000;0x
PMU_PLTR EQU 0x10001000 ; PLL的稳定过渡时间
PMU_PMCR EQU 0x10001004 ; 系统主时钟PLL的控制寄存器
PMU_PUCR EQU 0x10001008 ; USB时钟PLL的控制寄存器
PMU_PCSR EQU 0x
PMU_PDSLOW EQU 0x10001010 ; SLOW状态下时钟的分频因子
PMU_PMDR EQU 0x10001014 ; 芯片工作模式寄存器
PMU_RCTR EQU 0x10001018 ; Reset控制寄存器
PMU_CLRWAKUP EQU 0x
EMI_CSACONF EQU 0x11000000 ; CSA参数配置寄存器
EMI_CSECONF EQU 0x11000010 ; CSE参数配置寄存器
EMI_CSFCONF EQU 0x11000014 ; CSF参数配置寄存器
EMI_SDCONF1 EQU 0x11000018 ; SDRAM时序配置寄存器1
EMI_SDCONF2 EQU 0x
EMI_REMAPCONF EQU 0x11000020 ; 片选空间及地址映射REMAP配置寄存器
AREA BOOT, CODE, READONLY
ENTRY ; Mark first instruction to execute
EXPORT RST_DO
RST_DO
;*****************************************************************
;* 初始化各种模式下的堆栈首指针
;*****************************************************************
ldr sp, =SP_SVC ;init sp_svc
mov R4, #0xD2 ;chmod to irq and init sp_irq
msr cpsr_cf, R4
ldr sp, =SP_IRQ
mov R4, #0XD1 ;chomod to fiq and init sp_fiq
msr cpsr_cf, R4
ldr sp, =SP_FIQ
mov R4, #0XD7 ;chomod to abt and init sp_ABT
msr cpsr_cf, R4
ldr sp, =SP_ABT
mov R4, #0XDB ;chomod to undf and init sp_UNDF
msr cpsr_cf, R4
ldr sp, =SP_UND
;chomod to abt and init sp_sys
mov R4, #0xDF ;all interrupts disabled
msr cpsr_cxsf, R4 ;SYSTEM mode, @32-bit code mode
ldr sp, =SP_SYS
mov R4, #0XD3 ;chmod to svc modle, CPSR IRQ bit is disable
msr cpsr_c, R4
;****************************************************************
;* 初始化PMU模块, 配置系统时钟
;****************************************************************
ldr r4, =PMU_PCSR ; 打所有模块时钟
ldr r5, =0x0001ffff
str r5, [ r4 ]
ldr r4, =PMU_PLTR ; 配置PLL稳定过度时间为保守值50us*
ldr r5, =0x13881388
str r5, [ r4 ]
ldr r4, =PMU_PMCR ; 配置系统时钟为40MHz,pv=20,pd=1,tscal=000
ldr r5, =0x
str r5, [ r4 ]
ldr r4, =PMU_PMDR ; 由SLOW模式进入NORMAL模式
ldr r5, =0x00000001
str r5, [ r4 ]
ldr r4, =PMU_PMCR ; 配置系统时钟为40MHz,pv=20,pd=1,tscal=000
ldr r5, =0xC
str r5, [ r4 ]
;****************************************************************
;* 初始化EMI
;****************************************************************
ldr r4, =EMI_CSACONF ; CSA片选时序参数配置
ldr r5, =0x
str r5, [ r4 ]
ldr r4, =EMI_CSECONF ; CSE片选时序参数配置,最保守配置
ldr r5, =0x8cfffff1
str r5, [ r4 ]
ldr r4, =EMI_SDCONF1 ; SDRAM参数配置1
ldr r5, =0x1d004177
str r5, [ r4 ]
ldr r4, =EMI_SDCONF2 ; SDRAM参数配置2
ldr r5, =0x80001860
str r5, [ r4 ]
ldr r4, =EMI_REMAPCONF ; 重映射cse到0地址
ldr r5, =0x0000000b
str r5, [ r4 ]
;***************************************************************
;* 打开IRQ中断
;***************************************************************
mrs R4, cpsr
bic R4, R4, #0x80 ; set bit7 to zero
msr cpsr_c, R4
;**************************************************************************************
;* 初始化页表
;**************************************************************************************
; 初始化MMU,Cache以及WB
mov r0, #0 ; 将r0寄存器置0,用于后续对CP15寄存器赋值
mcr p15, 0, r0, c7, c7, 0 ; 失效I/DCache
; mcr p15, 0, r0, c7, c10, 4 ; 挤干WB清空写缓冲
mcr p15, 0, r0, c8, c7, 0 ; 失效I/D TLBs
mrc p15, 0, r0, c1, c0, 0 ; 加载控制寄存器C1到R0
bic r0, r0,#0x
bic r0, r0,#0x1100 ; 将R0的I(ICache)S(System Protection)位清零
mcr p15, 0, r0, c1, c0, 0 ; 将R0写到控制寄存器C1
ldr r5, =0x30004000 ; 加载页表基址0x4000到R5,该值不能低于0x4000,因为C2寄存器近31:14位有效,低于该值则1级页表项将从0x0开始,这将和中断向量表以及中断处理函数冲突
mcr p15, 0, r5, c2, c0, 0 ; 将R5写到翻译表CP15协处理器的基址寄存器C2中
; 0.0x4000000映射到0x4000000 得到并写入1级页表
ldr r0, =0x30004100 ; R0寄存器加载1级页表描述符地址,具体配置如下:
ldr r1, =0x
str r1, [r0] ;0x
;ldr r0, =0x30004104 ; R0寄存器加载1级页表描述符地址,具体配置如下:
;ldr r1, =0x
;str r1, [r0]
; 1.0x0(虚地址)映射到0x30000000(实地址) 得到并写入1级页表
ldr r0, =0x30004000 ; R0寄存器加载1级页表描述符地址,具体配置如下:
ldr r1, =0x
str r1, [r0]
; 2.0x10000000映射到0x10000000 得到并写入1级页表
ldr r0, =0x30004400 ; R0寄存器加载1级页表描述符地址,具体配置如下:
ldr r1, =0x
str r1, [r0]
; 3.0x11000000映射到0x11000000 得到并写入1级页表
ldr r0, =0x30004440 ; R0寄存器加载1级页表描述符地址,具体配置如下:
ldr r1, =0x
str r1, [r0]
; 4.0x20000000映射到0x20000000 得到并写入1级页表
ldr r0, =0x30004800 ; R0寄存器加载1级页表描述符地址,具体配置如下:
ldr r1, =0x
str r1, [r0]
; 5.0x24000000映射到0x24000000 得到并写入1级页表
ldr r0, =0x30004900 ; R0寄存器加载1级页表描述符地址,具体配置如下:
ldr r1, =0x
str r1, [r0]
; 6.0x28000000映射到0x28000000 得到并写入1级页表
ldr r0, =0x
ldr r1, =0x
str r1, [r0]
; 7.0x
ldr r0, =0x30004b00 ; R0寄存器加载1级页表描述符地址,具体配置如下:
ldr r1, =0x
str r1, [r0]
ldr r0, =0x
;ldr r0, =0x30005000 ; R0寄存器加载1级页表描述符地址,具体配置如下:
ldr r1, =0x
add r2, r1, #0x2000000
12 ;循环将
str r1, [r0]
add r0, r0, #0x4
add r1, r1, #0x100000
teq r1, r2
bne %b12
; 8.0x30000000映射到0x30000000 得到并写入1级页表
;ldr r0, =0x
ldr r0, =0x30005000 ; R0寄存器加载1级页表描述符地址,具体配置如下:
ldr r1, =0x
add r2, r1, #0x2000000
11 ;循环将
str r1, [r0]
add r0, r0, #0x4
add r1, r1, #0x100000
teq r1, r2
bne %b11
; 9.0x34000000映射到0x34000000 得到并写入1级页表
ldr r0, =0x30004d00 ; R0寄存器加载1级页表描述符地址,具体配置如下:
ldr r1, =0x
str r1, [r0]
; 开启MMU并跳转到主程序开始执行
ldr r0, =0x0 ;
ldr r1, =0x400000ff ; 准备填写Domain域,由于上面用到0域,所以需要给0xFF,最前面的4问题不大
mcr p15, 0, r1, c3, c0, 0 ; 写入Domain域
ldr r1, =0x4005147D ; 准备填写C1控制寄存器(IFLDPWCM)
;**************************************************************************************
;* 跳转到主函数 main()
;**************************************************************************************
IMPORT __main
ldr r5,=__main
mcr p15, 0, r1, c1, c0, 0 ; 打开MMU和Cache等
;add pc, r5,#0 ; 跳PC到刚才准备的__main的虚地址地址继续执行
add pc, r5,#0x0 ; 跳PC到刚才准备的__main的虚地址地址继续执行
mov r0, r0 ; 填充流水线
mov r0, r0 ; 填充流水线
mov r0, r0 ; 填充流水线
;**************************************************************************************
END