S3C6410开发全纪录(二)《如何计算内存大小,并在UBOOT中调整内存大小》

简介: http://bbs.2beanet.com/boot-f31/s3c6410-uboot-t3135.html 前章我们已经可以制作出用来启动的SD卡了,并将自己编译的UBOOT烧录到了SD卡中这份UBOOT代码中的内存配置肯定和手头的开发...

http://bbs.2beanet.com/boot-f31/s3c6410-uboot-t3135.html

 

前章我们已经可以制作出用来启动的SD卡了,并将自己编译的UBOOT烧录到了SD卡中

这份UBOOT代码中的内存配置肯定和手头的开发板不一致,这里我们将搞清楚如何修改内存大小,并说清楚内存大小到底是如何计算的

一、关于内存大小的计算

1)硬件的型号,在飞凌的开发板中

128M内存 采用的是 K4X51163PC 可以看出来 这颗芯片是 总大小为512 bit 位宽 为16
256M内存 采用的是 K4X1G163PC 可以看出来 这颗芯片是 总大小为1G  bit 位宽 为16

2)贴片数量2,都是用2DDR,来构成32位

3)查看DDR的芯片手册
128M内存 总共有 4 个 BANK 行列地址线数量分别为 Row = 13 Col = 10
256M内存 总共有 4 个 BANK 行列地址线数量分别为 Row = 14 Col = 10

4)以256M内存为例,内存大小的计算为

每个BANK的存储单元个数 = (2^Row)*(2^Col) = 2^(Row+Col)
每个存储单元 可以存放 16 位 的数据
总容量 = 芯片个数 * 每个芯片的BANK数量 * 位宽 * 行地址线数量 * 列地址线数量 (这里的单位都是bit)
= 2*4*16*(2^14)*(2^10) = 2^(1+2+4+14+10)= 2^31 bit

转换为 字节 2^28  转换为兆 2^8 M = 256 M

这里需要说明的是 行列地址线的总数是 > 16 的,行列地址线在实际的使用过程中是分时复用的。

二、内存大小的修改

修改用来显示的内存大小

代码:
    ./include/configs/smdk6410.h:#define PHYS_SDRAM_1_SIZE  0x10000000 /* 256 MB */  



修改CPU中对应的寄存器配置

《s3c6410_rev12.pdf》196页,5.5.4 MEMORY CONFIGURATION REGISTER

代码:
    P1MEMCFG  0x7E00100C  R/W  32-bit DRAM controller memory config register  0x01_0020




代码:
    Active chips  [22:21]  
    00 = 1 chip   
    01 = 2 chips   
    10 = Reserved  
    11 = Reserved  



这里我们是2片所以要选成 01

代码:
    Row bits [5:3] 
    000 = 11 bits   
    001 = 12 bits   
    010 = 13 bits   
    011 = 14 bits   
    100 = 15 bits   
    101 = 16 bits  



代码:
    Column bits  [2:0]  
    000 = 8 bits   
    001 = 9 bits   
    010 = 10 bits   
    011 = 11 bits   
    100 = 12 bits 



以256M内存芯片的参数为例

《K4X1G163PC.pdf》芯片手册中描述如下:

代码:
    32M x16 BA0,BA1 A0 - A13 A0 - A9 



这里我们需要将Row设置为011将Column设置为010

uboot代码中我们可以看到

代码:
    ./include/s3c6410.h:#define ELFIN_DMC1_BASE         0x7e001000 



 

代码:
    ./include/s3c6410.h:#define INDEX_DMC_MEMORY_CFG    (0x0C) 




 

代码:
    ./include/s3c6410.h:#define DMC1_MEM_CFG            0x00010012 



实际上,如果通过读CPU的手册而将内存配置正确,是件挺困的事情,还好我们有很多可参考的代码,但我们需要弄清楚这些代码为什么要这样修改

修改行列地址线的配置

代码:
    #define DMC1_MEM_CFG 0x0001001A 



1A转换为二进制为00011010,可以看到,是我们查到的Row,Column的寄存器配置的值

在有些代码中也修改了 #define DMC1_CHIP0_CFG  0x150F8 这个寄存器的值,为 #define DMC1_CHIP0_CFG  0x150F0
翻遍了资料也不知道这个值是做什么用的,为什么要修改,所以我这里并没有修改这个值,也希望有经验的朋友能告诉我为什么。

修改UBOOT的自举地址

一般考虑修改UBOOT自举地址都会去修改 board/samsum/smdk6410/config.mk 中的 TEXT_BASE 的值,但这里不能做

网上下来资料看了下,目前大多数的s3c6410开发板都没有去修改UBOOT的自举地址,这里记录了下查找及修改的过程

cpu/s3c64xx/start.S 中看到 

代码:
    #ifdef CONFIG_BOOT_MOVINAND 
            ldr     sp, _TEXT_PHY_BASE 
            bl      movi_bl2_copy 
            b       after_copy 
    #endif 




 

代码:
    _TEXT_PHY_BASE: 
            .word   CFG_PHY_UBOOT_BASE 




修改 include/configs/smdk6410.h 

代码:
    #define CFG_MEMTEST_END         MEMORY_BASE_ADDRESS + 0x7e00000         /* 128 MB in DRAM       */ 
    #define CFG_MEMTEST_END         MEMORY_BASE_ADDRESS + 0xfe00000         /* 256 MB in DRAM       */ 
     
     
    #ifdef CONFIG_ENABLE_MMU 
            // #define CFG_UBOOT_BASE               0xc7e00000 
            #define CFG_UBOOT_BASE 0xcfe00000 
    #else 
            //#define CFG_UBOOT_BASE                0x57e00000 
            #define CFG_UBOOT_BASE 0x5fe00000 
    #endif 
     
    //#define CFG_PHY_UBOOT_BASE    MEMORY_BASE_ADDRESS + 0x7e00000 
    #define CFG_PHY_UBOOT_BASE MEMORY_BASE_ADDRESS + 0XFE00000 




修改 board/samsung/smdk6410/config.mk 

代码:
    //TEXT_BASE = 0xc7e00000 
    TEXT_BASE = 0xcfe00000 





修改 include/movi.h 

代码:
    //#define BL2_BASE                0x57E00000 
    #define BL2_BASE                0x5FE00000 



这宏只作用于movi_bl2_copy函数,因为我们需要将UBOOT自举到256的最顶端 

修改MMU地址映射规则

    修改 board/samsung/smdk6410/lowlevel_init.S 
找到 mmu_table:将 

代码:
            // 128MB for SDRAM 0xC0000000 -> 0x50000000 
            .set __base, 0x500 
            .rept 0xC80 - 0xC00         
            FL_SECTION_ENTRY __base,3,0,1,1 
            .set __base,__base+1 
            .endr 
     
            // access is not allowed. 
            .rept 0x1000 - 0xc80         
            .word 0x00000000 
            .endr 



修改为: 

代码:
            // 256MB for SDRAM 0xC0000000 -> 0x50000000 
            .set __base, 0x500 
            .rept 0xd00 - 0xC00 
            FL_SECTION_ENTRY __base,3,0,1,1 
            .set __base,__base+1 
            .endr 
     
            // access is not allowed. 
            .rept 0x1000 - 0xd00 
            .word 0x00000000 
            .endr 



UBOOT启动起来,敲入 md cfe00000,打印出内存的数据,可以查看到跟我们编译出来的u-boot.bin是一致的

相关文章
|
6月前
|
消息中间件 存储 测试技术
【消息队列开发】 实现MemoryDataCenterTests类——测试管理内存数据
【消息队列开发】 实现MemoryDataCenterTests类——测试管理内存数据
|
3月前
|
存储 运维
.NET开发必备技巧:使用Visual Studio分析.NET Dump,快速查找程序内存泄漏问题!
.NET开发必备技巧:使用Visual Studio分析.NET Dump,快速查找程序内存泄漏问题!
|
4月前
|
Swift iOS开发
iOS开发-属性的内存管理
【8月更文挑战第12天】在iOS开发中,属性的内存管理至关重要,直接影响应用性能与稳定性。主要策略包括:`strong`(强引用),不维持对象生命期,可用于解除循环引用;`assign`(赋值),适用于基本数据类型及非指针对象属性;`copy`,复制对象而非引用,确保对象不变性。iOS采用引用计数管理内存,ARC(自动引用计数)自动处理引用增减,简化开发。为避免循环引用,可利用弱引用或Swift中的`[weak self]`。最佳实践包括:选择恰当的内存管理策略、减少不必要的强引用、及时释放不再使用的对象、注意block内存管理,并使用Xcode工具进行内存分析。
|
5月前
|
Java 运维
开发与运维内存问题之文件句柄泄漏如何解决
开发与运维内存问题之文件句柄泄漏如何解决
76 3
|
5月前
|
缓存 Java Linux
开发与运维内存问题之线上遇到故障,使用jstat命令发现Old区持续增长如何解决
开发与运维内存问题之线上遇到故障,使用jstat命令发现Old区持续增长如何解决
48 2
|
5月前
|
NoSQL Redis C++
c++开发redis module问题之在复杂的Redis模块中,特别是使用第三方库或C++开发时,接管内存统计有哪些困难
c++开发redis module问题之在复杂的Redis模块中,特别是使用第三方库或C++开发时,接管内存统计有哪些困难
|
5月前
|
Java 运维
开发与运维内存问题之在堆内存中新创建的对象通常首先分配如何解决
开发与运维内存问题之在堆内存中新创建的对象通常首先分配如何解决
24 1
|
5月前
|
Java Windows
Java演进问题之JVM在内存返还策略上会左右为难如何解决
Java演进问题之JVM在内存返还策略上会左右为难如何解决
|
4月前
|
Java 开发工具 Android开发
Android经典面试题之开发中常见的内存泄漏,以及如何避免和防范
本文介绍Android开发中内存泄漏的概念及其危害,并列举了四种常见泄漏原因:静态变量持有Context、非静态内部类、资源未释放及监听器未注销。提供了具体代码示例和防范措施,如使用ApplicationContext、弱引用、适时释放资源及利用工具检测泄漏。通过遵循这些建议,开发者可以有效提高应用稳定性和性能。
55 0
|
5月前
|
缓存 运维 监控
开发与运维内存问题之dmesg,它在故障排查中的作用如何解决
开发与运维内存问题之dmesg,它在故障排查中的作用如何解决
55 0