6410所使用的內存為DDR 210使用的是DDR2 2440使用的是SDRAM,關于他們之間的區分,我在之前的文章中ok6410內存及啟動流程簡單介紹過,有興趣的可以看看。
S3C6410處理器擁32位地址總線,其尋址空間為4GB。其中高2GB為保存區,低2GB區域又可劃分為兩部份:主存儲區和外設區。
外設區主要是與6410寄存器相干,在核心初始化—外設基地址初始化中,有說明外設的寄存器的基地址為0x70000000
下面則是主存儲區的地址散布,在之前的課程中有介紹,現在貼出來加強理解
主存儲區可以分為
這個區域并沒有固定的存儲介質與之對應,也就是沒有實際的映照內存。但是可以把不同的啟動介質的地址映照到該區域。比如說選擇了IROM 啟動方式后,就把IROM映照到該區域。這在之前有介紹過。
這個區域對應著內部的內存地址,iROM和SRAM都是散布在這個區間。0x08000000~0x0bffffff對應著內部ROM,但是IROM實際只有32KB,選擇從IROM啟動的時候,首先運行就是這里面的程序BL0,這部份代碼由3星固化。0x0c000000~0x0fffffff對應內部SRAM,實際就是8KB的Steppingstone。
這個區域用于訪問掛在外部總線上的裝備,比如說NOR flash、oneNand等。這個區
域被分割為6個bank,每一個bank為128MB,數據寬度最大支持16bit,每一個bank由片選Xm0CS[0]~Xm0CS[5] 選中。
該區域從0x50000000~0x6fffffff,又分為2個區間,分別占256MB,可以片選Xm1CS[0]~Xm1CS[1]來進行著2個區間的選擇。我們6410開發板上256MB的DDR內存就安排在這個區域,這也就是為何6410的內存地址是從0x50000000開始的緣由。
如上圖可以看到,6410的內存是由兩塊128MB的內存芯片連接而成,除每一個芯片的16位數據位不同,其他均相同。
根據上面的DRAM控制器初始化流程,可以得到以下步驟:
根據上面的圖,可知需要設置[2:0]位設置位0b100便可
ldr r0,=0x7e001004
mov r1,#0x4
str r1,[r0]
這1步驟的主要流程在6410的手冊中并沒有找到具體的進程,因此主要參考內存芯片手冊和uboot相干步驟寫的。
ldr r0, =0x7e001010 @刷新寄存器地址
ldr r1, =( ( 7800 / ( 1000000000/133000000 ) + 1 ) ) @設置刷新時間
str r1, [r0]
ldr r0, =0x7e001014 @CAS latency寄存器
mov r1, #(3 << 1)
str r1, [r0]
ldr r0, =0x7e001018 @t_DQSS寄存器
mov r1, #0x1
str r1, [r0]
ldr r0, =0x7e00101c @T_MRD寄存器
mov r1, #0x2
str r1, [r0]
ldr r0, =0x7e001020 @t_RAS寄存器
ldr r1, =( ( 45 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e001024 @t_RC寄存器
ldr r1, =( ( 68 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e001028 @t_RCD寄存器
ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e00102c @t_RFC寄存器
ldr r1, =( ( 80 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e001030 @t_RP寄存器
ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e001034 @t_rrd寄存器
ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e001038 @t_wr寄存器
ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) )
@ ldr r2, [r0]
str r1, [r0]
ldr r0, =0x7e00103c @t_wtr寄存器
mov r1, #0x07
str r1, [r0]
ldr r0, =0x7e001040 @t_xp寄存器
mov r1, #0x02
str r1, [r0]
ldr r0, =0x7e001044 @t_xsr寄存器
ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e001048 @t_esr寄存器
ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e00100c @內存控制配置寄存器
ldr r1, =0x00010012 @配置控制器
str r1, [r0]
ldr r0, =0x7e00104c @32位DRAM配置控制寄存器
ldr r1, =0x0b45
str r1, [r0]
ldr r0, =0x7e001200 @片選寄存器
ldr r1, =0x150f8
str r1, [r0]
ldr r0, =0x7e001304 @用戶配置寄存器
mov r1, #0x0
str r1, [r0]
等待200μs 來使SDRAM 電源和時鐘穩定。當 CPU 開始工作時,電源和時鐘已被穩定下來因此過剩 不做。
下面是step4 內存初始化中的各個步驟
根據上圖,使[19:18]位為0b011便可滿足要求,因此轉化為16進制為0xc0000
ldr r0,=0x7e001008
ldr r1,=0xc0000
str r1,[r0]
根據上圖,使[19:18]位為0b000便可滿足要求
ldr r0,=0x7e001008
ldr r1,=0x0
str r1,[r0]
4.3 和 4.4 為相同的操作,履行兩遍
根據上圖,使[19:18]位為0b001便可滿足要求,因此轉化為16進制為0x40000
ldr r0,=0x7e001008
ldr r1,=0x40000
str r1,[r0]
ldr r0,=0x7e001008
ldr r1,=0x40000
str r1,[r0]
參考自uboot源碼
ldr r0,=0x7e001008
ldr r1,=0xa0000
str r1,[r0]
參考自uboot源碼
ldr r0,=0x7e001008
ldr r1,=0x80032
str r1,[r0]
如上圖所示,需要設置[2:0]位0b000便可,
ldr r0,=0x7e001004
mov r1,#0x0
str r1,[r0]
根據上圖,需要設置其為ready狀態,即[1:0]為0b10
check_ready:
ldr r0,=0x7e001000
ldr r1,[r0]
mov r2,#0x3
and r1,r1,r2 @將r1與r2進行位與操作
cmp r1,#0x1 @與0x1進行比較
bne check_ready @不相等,跳轉到check_ready
在代碼設置之前,需要設置DDR的管腳為數據管腳,要設置第2塊內存芯片的數據引腳,以下所示
ldr r0,=0x7e00f120 @設置為數據引腳
mov r1,#0x0
str r1,[r0]
以下是全部代碼片斷:
Makefile
all: start.o mem.o
arm-linux-ld -Tgboot.lds -o gboot.elf $^
arm-linux-objcopy -O binary gboot.elf gboot.bin
%.o : %.S
arm-linux-gcc -g -c $^
%.o : %.c
arm-linux-gcc -g -c $^
.PHONY: clean
clean:
rm *.o *.elf *.bin
start.S
@****************************
@name: start.S
@by : stone
@time: 2016.6.26
@function:
@ 異常向量表
@ 設置SVC模式
@ 關閉看門狗
@ 關閉中斷
@ 關閉MMU
@ 外設基地址初始化
@ 點亮LED
@ 時鐘初始化
@ 內存初始化
@****************************
.text
.global _start @將_start聲明為全局變量
_start:
b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
_undefined_instruction: .word undefined_instruction
_software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort
_data_abort: .word data_abort
_not_used: .word not_used
_irq: .word irq
_fiq: .word fiq
undefined_instruction: @處理未定義指令異常
nop
software_interrupt: @軟中斷
nop
prefetch_abort: @預取指令異常
nop
data_abort: @數據訪問異常
nop
not_used: @空位
nop
irq: @中斷
nop
fiq: @快速中斷
nop
reset: @reset
bl set_svc @設置為SVC模式
bl set_peri_port @外設基地址初始化
bl disable_watchdog @關閉看門狗
bl disable_interrupt @關閉中斷
bl disable_mmu @關閉mmu
bl init_clock @時鐘初始化
bl mem_init @內存初始化
bl light_led @點亮LED
set_svc:
mrs r0, cpsr @將值取出cpsr寄存器
bic r0, r0, #0x1f @將后5位 即M[4:0]清零
orr r0, r0, #0xd3 @0b10011 轉化為16進制為0x13 同時為了屏蔽irq和fiq,可以將其設置為0b11010011即0xd3
msr cpsr, r0 @將值送回cpsr寄存器
mov pc, lr @返回
set_peri_port:
ldr r0, =0x70000000 @基地址
orr r0, r0, #0x13 @256MB
mcr p15,0,r0,c15,c2,4 @寫入cp15
mov pc, lr
#define pwTCON 0x7E004000 @WTCON寄存器
disable_watchdog:
ldr r0, =pwTCON @把地址裝載到R0
mov r1, #0x0 @置0,關閉看門狗
str r1,[r0]
mov pc,lr
disable_interrupt:
mvn r1,#0x0 @0x0 取反,給r1
ldr r0,=0x71200014 @VIC0
str r1,[r0]
ldr r0,=0x71300014 @VIC1
str r1,[r0]
mov pc,lr
disable_mmu:
mcr p15,0,r0,c7,c7,0 @使ICACHE 和DCACHE 無效
mrc p15,0,r0,c1,c0,0 @read control register
bic r0,r0,#0x00000007 @mmu 和 dcache置零
mcr p15,0,r0,c1,c0,0 @write control register
mov pc,lr
#define CLK_DIV0 0x7e00f020
#define CLK_SRC 0x7e00f01c
#define OTHERS 0x7e00f900
#define MPLL_CON 0X7E00F010
#define APLL_CON 0X7E00F00c
#define PLL_VAL ((1<<31)|(266<<16)|(3<<8)|(1<<0))
#define DIV_VAL ((0X0<<0)|(0X1<<9)|(0X1<<8)|(0X3<<12))
init_clock:
ldr r0,=CLK_DIV0 @設置分頻系數
ldr r1,=DIV_VAL
str r1,[r0]
ldr r0,=OTHERS @設置異步工作模式 第7位為0 第6位為0(時鐘選擇器)
ldr r1,[r0]
bic r1,r1,#0xc0
str r1,[r0]
ldr r0,=APLL_CON @APLL設置為533Mhz
ldr r1,=PLL_VAL
str r1,[r0]
ldr r0,=MPLL_CON @MPLL設置為533Mhz
ldr r1,=PLL_VAL
str r1,[r0]
ldr r0, =CLK_SRC @選擇時鐘源為APLL MPLL還是外部
mov r1, #0x3 @APLL MPLL
str r1, [r0]
mov pc,lr
#define GPMCON 0x7F008820 @控制寄存器
#define GPMDAT 0x7F008824 @數據寄存器
light_led:
ldr r0,=GPMCON
ldr r1,=0x1111 @輸出模式
str r1,[r0]
ldr r0,=GPMDAT
ldr r1,=0x00 @低電平點亮
str r1,[r0]
mov pc,lr
mem.S
@*************************************
@name : mem.S
@time : 2016/06/26
@function : 內存初始化相干代碼
@************************************
.text @代碼段
.global mem_init
mem_init:
ldr r0,=0x7e00f120 @設置為數據引腳
mov r1,#0x0
str r1,[r0]
ldr r0,=0x7e001004 @配置寄存器 使DRAM控制器進入 config 狀態
mov r1,#0x4
str r1,[r0]
ldr r0, =0x7e001010 @刷新寄存器地址
ldr r1, =( ( 7800 / ( 1000000000/133000000 ) + 1 ) ) @設置刷新時間
str r1, [r0]
ldr r0, =0x7e001014 @CAS latency寄存器
mov r1, #(3 << 1)
str r1, [r0]
ldr r0, =0x7e001018 @t_DQSS寄存器
mov r1, #0x1
str r1, [r0]
ldr r0, =0x7e00101c @T_MRD寄存器
mov r1, #0x2
str r1, [r0]
ldr r0, =0x7e001020 @t_RAS寄存器
ldr r1, =( ( 45 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e001024 @t_RC寄存器
ldr r1, =( ( 68 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e001028 @t_RCD寄存器
ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e00102c @t_RFC寄存器
ldr r1, =( ( 80 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e001030 @t_RP寄存器
ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e001034 @t_rrd寄存器
ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e001038 @t_wr寄存器
ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) )
@ ldr r2, [r0]
str r1, [r0]
ldr r0, =0x7e00103c @t_wtr寄存器
mov r1, #0x07
str r1, [r0]
ldr r0, =0x7e001040 @t_xp寄存器
mov r1, #0x02
str r1, [r0]
ldr r0, =0x7e001044 @t_xsr寄存器
ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e001048 @t_esr寄存器
ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e00100c @內存控制配置寄存器
ldr r1, =0x00010012 @配置控制器
str r1, [r0]
ldr r0, =0x7e00104c @32位DRAM配置控制寄存器
ldr r1, =0x0b45
str r1, [r0]
ldr r0, =0x7e001200 @片選寄存器
ldr r1, =0x150f8
str r1, [r0]
ldr r0, =0x7e001304 @用戶配置寄存器
mov r1, #0x0
str r1, [r0]
ldr r0,=0x7e001008
ldr r1,=0xc0000
str r1,[r0]
ldr r0,=0x7e001008
ldr r1,=0x0
str r1,[r0]
ldr r0,=0x7e001008
ldr r1,=0x40000
str r1,[r0]
ldr r0,=0x7e001008
ldr r1,=0x40000
str r1,[r0]
ldr r0,=0x7e001008
ldr r1,=0xa0000
str r1,[r0]
ldr r0,=0x7e001008
ldr r1,=0x80032
str r1,[r0]
ldr r0,=0x7e001004
mov r1,#0x0
str r1,[r0]
check_ready:
ldr r0,=0x7e001000
ldr r1,[r0]
mov r2,#0x3
and r1,r1,r2 @將r1與r2進行位與操作
cmp r1,#0x1 @與0x1進行比較
bne check_ready @不相等,跳轉到check_ready
mov pc,lr
菜鳥1枚,如有毛病,多多指教。。。