tiny6410裸机实验第5章--------------DDR(代码)

【说明】

              根据上一节介绍的原理,很容易写出DDR的初始化代码,这节附上代码,包括代码重定位,以及初始化DDR。

 

【初始化DDR】

                common.h...包含了一些通用宏定义

                 

#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 /* __COMMON_H */


 

             sdram.c  初始化代码

            

// 功能:初始化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是四舍五入

/* 根据6410手册P192页相关步骤和sdram手册来初始化dram控制器(dramc) */
int sdram_init( void )
{
        /* 1. 使dramc进入"config"状态 */
        set_val(P1MEMCCMD, 0x4);

        /* 2. 设置timing parameter, chip configuration,id configuration registers */
        /* 2.1 刷新周期 */
        set_val(P1REFRESH, nstoclk(7800));                                      //刷新周期:(7.8us)/((1/HCLK)s)=(7.8*10^3)/(1/133*10^6)
        /* 2.2 时间参数,下列设置全都是取了最小值 */
        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) );

        /* 2.3 chip configuration */
        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 

        /* 3. 初始化sdram */
        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 );

        /* 4. 使dramc进入"ready"状态    */
        set_val( P1MEMCCMD, 0x000 );
        while( !(( read_val( P1MEMSTAT ) & 0x3 ) == 0x1));// 等待dramc进入"ready"状态
}


【代码重定位】

                  start.S       其中的_bss_start  等符号来至链接脚本,,,链接脚本同以前

                 

// 启动代码
.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


 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值