• Tiny6410之重定位代码到SDRAM


    在上一章中,将代码重定位到了SRAM中,但是这样的做法作用不大。正确的做法的是将代码重定位到更大的主存中,即DRAM。Tiny6410的DRAM控制寄存器最多只能支持两个同一类型的芯片。每个芯片最多可分配256MB的地址空间,所有的芯片在相同的端口共享所有的引脚,除了时钟启动信号和片选信号。

    通过原理图

    DRAM的地址为0x50000000

    通过原理图可知SDRAM的使用的是K4X1G163PE-L(F)E/GC6。通过查看该芯片的数据手册可知道,如何启动SDRAM控制寄存器。

    SDRAM  初始化顺序
      上电复位时,软件必须初始化 DRAM 控制器,SDRAM 的每一项都连接到 DRAM 控制器?仅以 SDRAM 的数据表为启动程序
    1 1 . M DRAM  控制器初始化顺序
    (1)以 ‘3’b100’ 执行 memc_cmd,使得 DRAM 控制器输入‘配置’状态
    (2)写存储器时间参数,芯片配置和 ID 配置寄存器
    (3)等待 200μs 来使 SDRAM 电源和时钟稳定?当 CPU 开始工作时,电源和时钟已经被稳定下来
    (4)执行存储器初始化顺序
    (5)以 ‘3’b000’ 执行 memc_cmd,使得 DRAM 控制器输入‘准备’状态
    (6)在 memc_stat 中检查存储器状态域,直到存储器状态变为 ‘2’b01’ ,即‘准备’

    DDR/ 移动  M DDR SDRAM  初始化顺序
    (1)在 direct_cmd,以‘ 2’b10 ’执行 mem_cmd,使得 DRAM 控制器产生‘NOP’存储器命令
    (2)在 direct_cmd,以‘ 2’b00 ’执行 mem_cmd,使得 DRAM 控制器产生‘Prechargeall’存储器命令
    (3)在 direct_cmd,以‘ 2’b11 ’执行 mem_cmd,使得 DRAM 控制器产生‘Autorefresh’存储器命令
    (4)在 direct_cmd,以‘ 2’b10 ’执行 mem_cmd,使得 DRAM 控制器产生‘MRS’存储器命令
    EMRS 块地址必须被设置
    (5)在 direct_cmd,以‘ 2’b10 ’执行 mem_cmd,使得 DRAM 控制器产生‘MRS’存储器命令
    MRS 块地址必须被设置
    (6)在 direct_cmd,以‘ 2’b11 ’执行 mem_cmd,使得 DRAM 控制器产生‘Autorefresh’存储器命令
    (7)在 direct_cmd,以‘ 2’b11 ’执行 mem_cmd,使得 DRAM 控制器产生‘Autorefresh’存储器命令
    (8)在 direct_cmd,以‘ 2’b11 ’执行 mem_cmd,使得 DRAM 控制器产生‘Prechargeall’存储器命令

    具体代码如下:

      1 //Tiny6410Addr.h
      2 #ifndef _Tiny6410Addr_H
      3 #define _Tiny6410Addr_H
      4 //GPK 
      5 #define GPKIO_BASE (0x7F008800)
      6 #define rGPKCON0 (*((volatile unsigned long *)(GPKIO_BASE+0x00)))
      7 #define rGPKDAT  (*((volatile unsigned long *)(GPKIO_BASE+0x08)))
      8 
      9 //CLOCK
     10 #define APLL_LOCK (*((volatile unsigned long *)0x7E00F000))
     11 #define MPLL_LOCK (*((volatile unsigned long *)0x7E00F004))
     12 #define EPLL_LOCK (*((volatile unsigned long *)0x7E00F008))
     13 #define OTHERS    (*((volatile unsigned long *)0x7e00f900))
     14 #define CLK_DIV0  (*((volatile unsigned long *)0x7E00F020))
     15 #define APLL_CON  (*((volatile unsigned long *)0x7E00F00C))
     16 #define MPLL_CON  (*((volatile unsigned long *)0x7E00F010))
     17 #define CLK_SRC   (*((volatile unsigned long *)0x7E00F01C))
     18 
     19 
     20 
     21 //GPA /uart
     22 #define ULCON0     (*((volatile unsigned long *)0x7F005000))
     23 #define UCON0      (*((volatile unsigned long *)0x7F005004))
     24 #define UFCON0     (*((volatile unsigned long *)0x7F005008))
     25 #define UMCON0     (*((volatile unsigned long *)0x7F00500C))
     26 #define UTRSTAT0   (*((volatile unsigned long *)0x7F005010))
     27 #define UFSTAT0    (*((volatile unsigned long *)0x7F005018))
     28 #define UTXH0      (*((volatile unsigned char *)0x7F005020))
     29 #define URXH0      (*((volatile unsigned char *)0x7F005024))
     30 #define UBRDIV0    (*((volatile unsigned short *)0x7F005028))
     31 #define UDIVSLOT0  (*((volatile unsigned short *)0x7F00502C))
     32 #define GPACON     (*((volatile unsigned long *)0x7F008000))
     33 
     34 
     35 //SDRAM
     36 #define P1MEMCCMD    (*((volatile unsigned long *)0x7e001004))
     37 #define P1REFRESH    (*((volatile unsigned long *)0x7e001010))
     38 #define P1CASLAT    (*((volatile unsigned long *)0x7e001014))
     39  
     40 #define MEM_SYS_CFG    (*((volatile unsigned long *)0x7e00f120))
     41 #define P1MEMCFG    (*((volatile unsigned long *)0x7e00100c))
     42 #define P1T_DQSS    (*((volatile unsigned long *)0x7e001018))
     43 #define P1T_MRD        (*((volatile unsigned long *)0x7e00101c))
     44 #define P1T_RAS        (*((volatile unsigned long *)0x7e001020))
     45 #define P1T_RC        (*((volatile unsigned long *)0x7e001024))
     46 #define P1T_RCD        (*((volatile unsigned long *)0x7e001028))
     47 #define P1T_RFC        (*((volatile unsigned long *)0x7e00102c))
     48 #define P1T_RP        (*((volatile unsigned long *)0x7e001030))
     49 #define P1T_RRD        (*((volatile unsigned long *)0x7e001034))
     50 #define P1T_WR        (*((volatile unsigned long *)0x7e001038))
     51 #define P1T_WTR        (*((volatile unsigned long *)0x7e00103c))
     52 #define P1T_XP        (*((volatile unsigned long *)0x7e001040))
     53 #define P1T_XSR        (*((volatile unsigned long *)0x7e001044))
     54 #define P1T_ESR        (*((volatile unsigned long *)0x7e001048))
     55 #define P1MEMCFG2    (*((volatile unsigned long *)0X7e00104c))
     56 #define P1_chip_0_cfg    (*((volatile unsigned long *)0x7e001200))
     57 
     58 #define P1MEMSTAT    (*((volatile unsigned long *)0x7e001000))
     59  
     60 #define P1DIRECTCMD    (*((volatile unsigned long *)0x7e001008))
     61 
     62 #endif
     63 
     64 //start.S
     65 // 启动代码
     66 .global _start
     67 
     68 _start:
     69 
     70     // 把外设的基地址告诉CPU
     71     ldr r0, =0x70000000                     
     72     orr r0, r0, #0x13                    
     73     mcr p15,0,r0,c15,c2,4                
     74     
     75     // 关看门狗
     76     ldr r0, =0x7E004000
     77     mov r1, #0
     78     str r1, [r0] 
     79     
     80     // 设置栈
     81     ldr sp, =8*1024
     82     
     83     // 开启icaches
     84 #ifdef  CONFIG_SYS_ICACHE_OFF
     85     bic r0, r0, #0x00001000                 @ clear bit 12 (I) I-cache
     86 #else
     87     orr r0, r0, #0x00001000                 @ set bit 12 (I) I-cache
     88 #endif
     89     mcr p15, 0, r0, c1, c0, 0
     90 
     91     // 设置时钟
     92     bl clock_init
     93     
     94     // 初始化sdram
     95     bl sdram_init
     96 
     97     // 重定位
     98     adr r0, _start 
     99     ldr r1, =_start
    100     ldr r2, =bss_start
    101     cmp r0, r1
    102     beq clean_bss
    103 copy_loop:
    104     ldr r3, [r0], #4
    105     str r3, [r1], #4
    106     cmp r1, r2
    107     bne copy_loop
    108         
    109     // 清BSS段
    110 clean_bss:
    111     ldr r0, =bss_start
    112     ldr r1, =bss_end
    113     mov r3, #0
    114     cmp r0, r1
    115     beq on_ddr
    116 clean_loop:
    117     str r3, [r0], #4
    118     cmp r0, r1    
    119     bne clean_loop        
    120 
    121         
    122     // 调用main函数
    123 on_ddr:    
    124     ldr pc, =main
    125 halt:
    126     b halt    
    127 //clock.c
    128 #include "Tiny6410Addr.h"
    129 // 功能:c语言初始化时钟
    130  
    131 
    132 #define ARM_RATIO    0                           // ARMCLK     = DOUTAPLL / (ARM_RATIO + 1)      = 532/(0+1) = 532  MHz
    133 #define MPLL_RATIO   0                           // DOUTMPLL = MOUTMPLL / (MPLL_RATIO + 1)   = 532/(0+1) = 532  MHz
    134 #define HCLKX2_RATIO 1                           // HCLKX2     = HCLKX2IN / (HCLKX2_RATIO + 1) = 532/(1+1) = 266  MHz
    135 #define HCLK_RATIO   1                           // HCLK     = HCLKX2   / (HCLK_RATIO + 1)   = 266/(1+1) = 133  MHz
    136 #define PCLK_RATIO   3                           // PCLK       = HCLKX2   / (PCLK_RATIO + 1)   = 266/(3+1) = 66.5 MHz
    137 
    138 
    139  
    140 #define APLL_CON_VAL  ((1<<31) | (266 << 16) | (3 << 8) | (1))
    141 
    142  
    143 #define MPLL_CON_VAL  ((1<<31) | (266 << 16) | (3 << 8) | (1))
    144 
    145  
    146 
    147 void clock_init(void)
    148 {    
    149     /* 1. 设置各PLL的LOCK_TIME,使用默认值 */
    150     APLL_LOCK = 0xffff;                            // APLL_LOCK,供cpu使用 
    151     MPLL_LOCK = 0xffff;                            // MPLL_LOCK,供AHB(存储/中断/lcd等控制器)/APB(看门狗,定时器,SD等)总线上的设备使用
    152     EPLL_LOCK = 0xffff;                            // EPLL_LOCK,供UART,IIS,IIC使用 
    153 
    154     /* 2. 设置为异步模式(Asynchronous mode) */
    155     OTHERS &= ~0xc0;                            //《linux installation for u-boot》3.7中:用MPLL作为HCLK和PCLK的Source是异步(ASYNC)模式,用APLL是同步(SYNC)模式
    156     while ((OTHERS & 0xf00) != 0);
    157 
    158     /* 3. 设置分频系数 */
    159     CLK_DIV0 = (ARM_RATIO) | (MPLL_RATIO << 4) | (HCLK_RATIO << 8) | (HCLKX2_RATIO << 9) | (PCLK_RATIO << 12);
    160 
    161     /* 4. 设置PLL,放大时钟 */    
    162     APLL_CON = APLL_CON_VAL;  
    163     MPLL_CON = MPLL_CON_VAL;  
    164 
    165     /* 5. 选择PLL的输出作为时钟源 */
    166     CLK_SRC = 0x03;
    167 }
    168 
    169 //sdram.c
    170 #include "Tiny6410Addr.h"
    171     
    172 #define set_zero( addr, bit ) ( addr &= ( ~ ( 1 << (bit) ) ) )
    173 #define set_one( addr, bit ) ( addr |= ( 1 << ( bit ) ) )
    174 
    175 #define set_bit( addr, bit, val ) ( addr = (addr &=(~(1<<(bit))) ) | ( (val)<<(bit) ) )
    176 
    177 #define set_2bit( addr, bit, val ) ( addr = (addr &(~(3<<(bit))) ) | ( (val)<<(bit) ) )
    178 
    179 #define set_nbit( addr, bit, len,  val ) 
    180     ( (addr) = (((addr)&(~(( ((1<<(len))-1) )<<(bit))))  | ( (val)<<(bit) ) ))
    181 
    182 #define get_bit( addr, bit ) ( ((addr ) & ( 1 << (bit) )) > 0  )
    183 
    184 #define get_val( addr, val ) ( (val) = addr )
    185 #define read_val( addr ) addr
    186 #define set_val( addr, val ) ( addr = (val) )
    187 #define or_val( addr, val ) ( addr |= (val) ) 
    188 
    189 
    190 #define HCLK    133000000
    191 
    192 #define nstoclk(ns)    ( ns/(1000000000/HCLK)+1 )
    193 ///////////////////////////////
    194 
    195 typedef unsigned char u8;
    196 typedef unsigned short u16;
    197 typedef unsigned int u32;
    198 
    199 // function declare
    200 
    201 int delay( int );
    202 
    203 /* 根据6410手册P192页相关步骤和sdram手册来初始化dram控制器(dramc) */
    204 int sdram_init( void )
    205 {
    206     /* 1. 使dramc进入"config"状态 */
    207     set_val(P1MEMCCMD, 0x4);
    208 
    209     /* 2. 设置timing parameter, chip configuration,id configuration registers */
    210     /* 2.1 刷新周期 */
    211     set_val(P1REFRESH, nstoclk(7800));                    //刷新周期:(7.8us)/((1/HCLK)s)=(7.8*10^3)/(1/133*10^6)
    212     /* 2.2 时间参数,下列设置全都是取了最小值 */
    213     set_val( P1CASLAT, ( 3 << 1 ) );                      //CAS Latency:指的是内存存取数据所需的延迟时间,简单的说,就是内存接到CPU的指令后的反应速度。一般的参数值是2和3两种。K4X1G163PQ的芯片手册上CAS Latency=3 
    214     set_val( P1T_DQSS, 0x1 );                            //下列设置均在sdram手册中可查询到                
    215     set_val( P1T_MRD, 0x2 );                            
    216     set_val( P1T_RAS, nstoclk(42) );                    
    217     set_val( P1T_RC, nstoclk(60) );        
    218     u32 trcd = nstoclk( 18 );                            
    219     set_val( P1T_RCD, trcd | (( trcd - 3 ) << 3 ) );
    220     u32 trfc = nstoclk( 72 );
    221     set_val( P1T_RFC, trfc | ( ( trfc-3 ) << 5 ) );   
    222     u32 trp = nstoclk( 18 );
    223     set_val( P1T_RP, trp | ( ( trp - 3 ) << 3 ) ); 
    224     set_val( P1T_RRD, nstoclk(12) );
    225     set_val( P1T_WR, nstoclk(12) );
    226     
    227     set_val( P1T_WTR, 0x1 );
    228     set_val( P1T_XP, 0x1 );
    229     set_val( P1T_XSR, nstoclk(120) );
    230     set_val( P1T_ESR, nstoclk(120) );
    231     
    232     /* 2.3 chip configuration */
    233     set_nbit( P1MEMCFG, 0, 3, 0x2 );                      // column address(10):A0~A9
    234     set_nbit( P1MEMCFG, 3, 3, 0x3 );                      // row address(14):A0~A13
    235     set_zero( P1MEMCFG, 6 );                              // A10/AP 
    236     set_nbit( P1MEMCFG, 15, 3, 0x2 );                     //  Burst Length (2, 4, 8, 16)
    237     set_nbit( P1MEMCFG2, 0, 4, 0x5 );
    238     set_2bit( P1MEMCFG2, 6, 0x1 );                        // 32 bit 
    239     set_nbit( P1MEMCFG2, 8, 3, 0x3 );                    // Mobile DDR SDRAM     
    240     set_2bit( P1MEMCFG2, 11, 0x1 );
    241     set_one( P1_chip_0_cfg, 16 );                        // Bank-Row-Column organization 
    242 
    243     /* 3. 初始化sdram */
    244     set_val( P1DIRECTCMD, 0xc0000 );                     // NOP
    245     set_val( P1DIRECTCMD, 0x000 );                        // precharge
    246     set_val( P1DIRECTCMD, 0x40000 );                    // auto refresh
    247     set_val( P1DIRECTCMD, 0x40000 );                    // auto refresh
    248     set_val( P1DIRECTCMD, 0xa0000 );                     // EMRS
    249     set_val( P1DIRECTCMD, 0x80032 );                     // MRS
    250 
    251     set_val( MEM_SYS_CFG, 0x0 );
    252                     
    253     /* 4. 使dramc进入"ready"状态    */
    254     set_val( P1MEMCCMD, 0x000 );
    255     while( !(( read_val( P1MEMSTAT ) & 0x3 ) == 0x1));// 等待dramc进入"ready"状态        
    256 }
    257 //main.c
    258 
    259 #include "Tiny6410Addr.h"
    260 #define GPK4_OUT  (1<<4*4)
    261 #define GPK5_OUT  (1<<4*5)
    262 #define GPK6_OUT  (1<<4*6)
    263 #define GPK7_OUT  (1<<4*7)
    264 //延时函数
    265 void delay()
    266 {
    267    volatile int i = 0x10000;
    268    while (i--);
    269 }
    270 
    271 int main()
    272 {
    273     unsigned int i = 0x10;
    274     //将GPK4-7设置为输出
    275     rGPKCON0 = GPK4_OUT | GPK5_OUT |GPK6_OUT |GPK7_OUT;
    276     //跑马灯式
    277     while (1)
    278     {
    279         rGPKDAT = 0x00;
    280         delay();
    281         rGPKDAT = 0xF0;
    282         
    283     }
    284     
    285     return 0;
    286     }
    287 
    288 //ddr.lds
    289 SECTIONS 
    290 {
    291     . = 0x50000000;
    292     .text : 
    293     { 
    294         start.o 
    295         * (.text)
    296     } 
    297     
    298     . = ALIGN(4);
    299     .rodata :
    300     {
    301         * (.rodata)
    302     }
    303     
    304     . = ALIGN(4);
    305     .data :
    306     {
    307     * (.data)
    308     }
    309 
    310     . = ALIGN(4);    
    311     
    312     bss_start = . ; 
    313     
    314     .bss :
    315       {
    316     * (.bss)    
    317     * (.common)
    318       }
    319     
    320     bss_end = . ;   
    321 }
    View Code
    海阔凭鱼跃,天高任鸟飞。
  • 相关阅读:
    程序员的算法课(10)-字符串排序算法实例(纯代码)
    程序员的算法课(9)-常见字符串算法
    程序员的算法课(8)-贪心算法:理解霍夫曼编码
    程序员的算法课(7)-01背包问题
    程序员的算法课(6)-最长公共子序列(LCS)
    吴晓波跨年演讲全文-预见-2020 (八、奥运激荡,5G热潮)
    吴晓波跨年演讲全文-预见-2020 (七、资本市场回暖可期)
    吴晓波跨年演讲全文-预见-2020 (六、快公司面临期中考)
    吴晓波跨年演讲全文-预见-2020 (五、硬科技催生慢哲学)
    吴晓波跨年演讲全文-预见-2020 (四、体验经济,美好爆发)
  • 原文地址:https://www.cnblogs.com/chenshikun/p/5840200.html
Copyright © 2020-2023  润新知