【說明】
根據上一節介紹的原理,很容易寫出DDR的初始化代碼,這節附上代碼,包括代碼重定位,以及初始化DDR。
【初始化DDR】
common.h...包含了一些通用宏定義
[cpp] view plain copy
- #ifndef __COMMON_H
- #define __COMMON_H
- #define vi *( volatile unsigned int * )
- #define set_zero( addr, bit ) ( (vi addr) &= ( ~ ( 1 << (bit) ) ) )
- #define set_one( addr, bit ) ( (vi addr) |= ( 1 << ( bit ) ) )
- #define set_bit( addr, bit, val ) ( (vi addr) = (( vi addr)&=(~(1<<(bit))) ) | ( (val)<<(bit) ) )
- #define set_2bit( addr, bit, val ) ( (vi addr) = (( vi addr)&(~(3<<(bit))) ) | ( (val)<<(bit) ) )
- #define set_nbit( addr, bit, len, val ) \
- ( (vi addr) = ((( vi addr)&(~(( ((1<<(len))-1) )<<(bit)))) | ( (val)<<(bit) ) ))
- #define get_bit( addr, bit ) ( (( vi addr ) & ( 1 << (bit) )) > 0 )
- #define get_val( addr, val ) ( (val) = vi addr )
- #define read_val( addr ) ( vi ( addr ) )
- #define set_val( addr, val ) ( (vi addr) = (val) )
- #define or_val( addr, val ) ( (vi addr) |= (val) )
- ///
- typedef unsigned char u8;
- typedef unsigned short u16;
- typedef unsigned int u32;
- // function declare
- int delay( int );
- #endif
sdram.c 初始化代碼
[cpp] view plain copy
- // 功能:初始化dram控制器(dramc)
- #include "common.h"
- #define MEMCCMD 0x7e001004
- #define P1REFRESH 0x7e001010
- #define P1CASLAT 0x7e001014
- #define MEM_SYS_CFG 0x7e00f120
- #define P1MEMCFG 0x7e00100c
- #define P1T_DQSS 0x7e001018
- #define P1T_MRD 0x7e00101c
- #define P1T_RAS 0x7e001020
- #define P1T_RC 0x7e001024
- #define P1T_RCD 0x7e001028
- #define P1T_RFC 0x7e00102c
- #define P1T_RP 0x7e001030
- #define P1T_RRD 0x7e001034
- #define P1T_WR 0x7e001038
- #define P1T_WTR 0x7e00103c
- #define P1T_XP 0x7e001040
- #define P1T_XSR 0x7e001044
- #define P1T_ESR 0x7e001048
- #define P1MEMCFG2 0X7e00104c
- #define P1_chip_0_cfg 0x7e001200
- #define P1MEMSTAT 0x7e001000
- #define P1MEMCCMD 0x7e001004
- #define P1DIRECTCMD 0x7e001008
- #define HCLK 133000000
- #define nstoclk(ns) ( ns/(1000000000/HCLK)+1 ) //+1是四舍五入
- int sdram_init( void )
- {
- set_val(P1MEMCCMD, 0x4);
- set_val(P1REFRESH, nstoclk(7800)); //重新整理周期:(7.8us)/((1/HCLK)s)=(7.8*10^3)/(1/133*10^6)
- set_val( P1CASLAT, ( 3 << 1 ) ); //CAS Latency:指的是記憶體存取資料所需的延遲時間,簡單的說,就是記憶體接到CPU的指令後的反應速度。一般的參數值是2和3兩種。K4X1G163PQ的晶片手冊上CAS Latency=3
- set_val( P1T_DQSS, 0x1 ); //下列設定均在sdram手冊中可查詢到
- set_val( P1T_MRD, 0x2 );
- set_val( P1T_RAS, nstoclk(42) );
- set_val( P1T_RC, nstoclk(60) );
- u32 trcd = nstoclk( 18 );
- set_val( P1T_RCD, trcd | (( trcd - 3 ) << 3 ) );
- u32 trfc = nstoclk( 72 );
- set_val( P1T_RFC, trfc | ( ( trfc-3 ) << 5 ) );
- u32 trp = nstoclk( 18 );
- set_val( P1T_RP, trp | ( ( trp - 3 ) << 3 ) );
- set_val( P1T_RRD, nstoclk(12) );
- set_val( P1T_WR, nstoclk(12) );
- set_val( P1T_WTR, 0x1 );
- set_val( P1T_XP, 0x1 );
- set_val( P1T_XSR, nstoclk(120) );
- set_val( P1T_ESR, nstoclk(120) );
- set_nbit( P1MEMCFG, 0, 3, 0x2 ); // column address(10):A0~A9
- set_nbit( P1MEMCFG, 3, 3, 0x3 ); // row address(14):A0~A13
- set_zero( P1MEMCFG, 6 ); // A10/AP
- set_nbit( P1MEMCFG, 15, 3, 0x2 ); // Burst Length (2, 4, 8, 16)
- set_nbit( P1MEMCFG2, 0, 4, 0x5 );
- set_2bit( P1MEMCFG2, 6, 0x1 ); // 32 bit
- set_nbit( P1MEMCFG2, 8, 3, 0x3 ); // Mobile DDR SDRAM
- set_2bit( P1MEMCFG2, 11, 0x1 );
- set_one( P1_chip_0_cfg, 16 ); // Bank-Row-Column organization
- set_val( P1DIRECTCMD, 0xc0000 ); // NOP
- set_val( P1DIRECTCMD, 0x000 ); // precharge
- set_val( P1DIRECTCMD, 0x40000 ); // auto refresh
- set_val( P1DIRECTCMD, 0x40000 ); // auto refresh
- set_val( P1DIRECTCMD, 0xa0000 ); // EMRS
- set_val( P1DIRECTCMD, 0x80032 ); // MRS
- set_val( MEM_SYS_CFG, 0x0 );
- set_val( P1MEMCCMD, 0x000 );
- while( !(( read_val( P1MEMSTAT ) & 0x3 ) == 0x1));// 等待dramc進入"ready"狀态
- }
【代碼重定位】
start.S 其中的_bss_start 等符号來至連結腳本,,,連結腳本同以前
[cpp] view plain copy
- // 啟動代碼
- .global _start
- _start:
- // 把外設的基位址告訴CPU
- ldr r0, =0x70000000
- orr r0, r0, #0x13
- mcr p15,0,r0,c15,c2,4
- // 關看門狗
- ldr r0, =0x7E004000
- mov r1, #0
- str r1, [r0]
- // 設定棧
- ldr sp, =8*1024
- // 開啟icaches
- #ifdef CONFIG_SYS_ICACHE_OFF
- bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache
- #else
- orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache
- #endif
- mcr p15, 0, r0, c1, c0, 0
- // 設定時鐘
- bl clock_init
- // 初始化sdram
- bl sdram_init
- // 重定位
- adr r0, _start
- ldr r1, =_start
- ldr r2, =bss_start
- cmp r0, r1 // 這裡是看程式是否已經在需要的位置了,如果是就不用重定位了
- beq clean_bss
- copy_loop: //這裡真正的是重定位代碼,很簡單,就是讀寫讀寫。。。
- ldr r3, [r0], #4
- str r3, [r1], #4
- cmp r1, r2
- bne copy_loop
- // 清BSS段
- clean_bss:
- ldr r0, =bss_start
- ldr r1, =bss_end
- mov r3, #0
- cmp r0, r1
- beq on_ddr
- clean_loop:
- str r3, [r0], #4
- cmp r0, r1
- bne clean_loop
- // 調用main函數
- on_ddr:
- ldr pc, =main
- halt:
- b halt