s3c6410存储系统 (一)

来源:互联网 发布:移民计划 知乎 编辑:程序博客网 时间:2024/06/04 19:46
(一)memory
1.引导镜像区  0x0000_0000~0x07FF_FFFF 128MB
2.内部存储区 128MB
(1) 内部ROM     0x0800_0000~0x0BFF_FFFF  64M
(2) 内部SRAM    0x0C00_0000~0x0FFF_FFFF  64M
 3.静态存储区   0x1000_0000~0x3FFF_FFFF 3*128MB
 4.动态存储区   0x4000_0000~0x6FFF_FFFF 3*256MB
  (这几个区的关系可以看下面的一张图对比一下)
(二)pheriperal(外设地址空间)
0x7000_0000~0x7xxx_xxxx

S3C6410的物理内存分成Memory和Pheriperal两部分,地址范围分别为0x0~0x6fffffff和0x7fffffff。
系统通过 SPINE总线访问Memory空间,通过PERI总线访问Pheriperal空间。
而为了适应不同外设的访问速度,又分别通过AHB总线访问LCD、 Camera、Accelerator等高速外设,通过APB总线访问iic、watchdog等低速外设。


Memory,又叫主内存,分为4大区域,分别是启动镜像区、内部内存区、静态内存区、动态内存区。

启动镜像区物理地址为0x00000000~0x07ffffff,共128MB。这个区域的作用正如它的名字所述,是用来启动系统的。但是这个范围内并没有实际的存储介质与之对应,只能在通过OM[4:0]选择具体的启动介质后再把相应介质的物理地址映射到这个启动区,比如说选择了IROM 启动方式后,就把IROM所占的地址空间映射为0x00000000开始的空间。

内部内存区物理地址为0x08000000~0x0fffffff(内部ROM和内部SRAM),共128MB。这个区域对应着内部的内存地址,内部的ROM和SRAM都是分布在这个区间。其中,0x08000000~0x0bffffff对应着内部ROM,当然实际上内部的ROM也并没有64MB这么多,只有32KB是有实际存储介质的,这32KB是一个只读区,放的是IROM方式下的启动代码,选择IROM启动的时候首先运行的代码就是这一部分,称为BL0,这部分代码由厂家固化。0x0c000000~0x0fffffff对应内部SRAM,实际可用的SRAM按照三星的手册是4KB,其实这就是用于nand flash启动的Steppingstone(但是这个Steppingstone是8KB,这2者似乎有矛盾,不知道是不是我的理解不对)。

静态内存区物理地址为0x10000000~0x3fffffff,共3*128MB。这个区域用于访问挂在外部总线上的设备,比如说SRAM、NOR flash、oneNand等。这个区域被分割为6个bank,每个bank为128MB,数据宽度最大支持16bit,每个bank通过 Xm0CS[5:0]来划定。和S3C2410 不一样的是,bank2~bank5能映射到nand flash、CF等非线性存储器,这并不是说可以通过bank2~bank5的地址段就能直接访问nand flash、CF内部的地址,相反,当映射到这些器件的时候这些bank的地址也不能再使用了,访问这些非线性存储器还是得通过Pheriperal空间的AHB总线进行,和S3C2410中的访问方式是一样的。不过有一个特例是,当Xm0CS2被映射到nand flash的时候,Steppingstone的4KB(or 8K?)SRAM被映射到bank2开始的4KB,而在以nand flash方式启动的时候bank2被映射到0x00000000开始的地方,实际上就是把Steppingstone映射到0x0000000了,这和 S3C2410的情况还是相似的

动态内存区物理地址为0x40000000~0x6fffffff,共3*256MB。其中第一个256MB为保留区,实际使用的动态内存区为 0x50000000~0x6fffffff,又分为2个区间,分别占256MB,可以通过DMC的Xm1CS[1:0]来进行着2个区间的选择。这个内存区主要是扩展DRAM,最大可以扩展512MB的DRAM

所以0x5000_0000~0x6FFF_FFFF是用来挂SDRAM的,我的SDRAM是256的,估计就是地址空间就是0x5000_0000~0x5FFF_FFFF了.事实证明是可以的,哈哈.

也就是说我们可以把程序 放到5000_0000处来执行.


二   ok6410tftp下载内核,文件系统,地址整理

飞凌官方提供了一键下载烧写linux的方式,相对来说比较方便,但是对于开发来说不够灵活,因此这篇文章把tftp相关的点介绍一下,整理下其中遇到的一些问题。

         一键烧写本质上是启动位于SD卡中的Uboot,通过uboot读取sd卡中的文件到SRAM最后通过nand指令实现一键烧写,这一块可以参考飞凌提供的uboot源码中include\configs 中的smdk6410.h 的529行,代码如下:

代码1:

复制代码
#elif defined(FORLINX_BOOT_SD)#define FORLINX_DEBUG#define CONFIG_MMC    1#define CONFIG_LCD#define CONFIG_BOOT_MOVINAND#define CFG_ENV_IS_IN_MOVINAND#define CONFIG_BOOTCOMMAND  "nand led-start;nand erase  ;fatload mmc 0:1 0x50008000 u-boot.bin;nand write.uboot 0x50008000 0 0x200000;fatload mmc 0:1 0x50008000 zImage;nand write.e    0x50008000 0x200000 0x500000; fatload mmc 0:1 0x50008000 rootfs.yaffs2; nand write.yaffs2 0x50008000 0x00700000 $filesize;  nand  beep; nand led-end"
复制代码

        从这段代码代码可以看出,uboot中通过宏定义的方式,当定义为FORLINX_BOOT_SD 式通过对相应配置相应的环境变量完成特定的操作,其中定义CONFIG_BOOTCOMMAND 后就可以自动进行nand的查处,从sd卡加载uboot等,这段代码内容稍后继续分析。

 

下面说一下tftp和地址相关的知识总结

        tftp是指通过tftp协议通过网络的方式进行文件传输,需要说明的是ok6410的出厂uboot是不支持网络的,这也就意味着nfs根文件系统以及通过tftp下载内核等都无法操作,其实解决这个问题也很简单,只需要替换网卡相关的文件就可以了,改动不是很大,这个可以找到很多资料,这里不再赘述。不过飞凌在12年9月的更新光盘中已经做了更新,uboot已经支持网络操作了,查一下源码也就是改了那几个文件,因此可以下载烧写最新版uboot。

        在进行tftp的操作时最开始可能容易搞混的就是烧写内核啥的应该烧写到哪一个地址去,最开始也有点混,比如有人的博客里是tftp c0008000 zImage 这个地址是c0008000,国嵌的视频教程中是c0800000,各不相同,没看到具体的叙述,而在通过usb等方式中通过usb传送的地址是50008000,因此可能会存在混乱,因此觉得有必要在博客中总结一下。关于地址空间的分配首先还需要看一下芯片手册。芯片手册中关于地址空间的安排如图所示。

image

        有一点需要说明的是,图中的地址空间是针对通过地址总线与数据总线进行操作的设备的,通过不同的片选信号来确定对应的地址,所以可以通过图中查表可以确定ok6410的256M RAM的地址范围为0x50000000-0x5FFFFFFF 256M的地址空间因此通过tftp下载到0x50008000也就是加载到RAM中(向后偏移了32K的地址,稍后在介绍)。到这儿对于0x50008000这个地址的由来就初步了解了。

再来看看很多资料中都提到的0xc0008000这个地址,smdk6410.h这个文件的501行可以找到这部分配置:

代码2

复制代码
//uboot-2M ,zImage-5M ,FS-200M,user-other#define CFG_NAND_ERASE_LEN  0xCF00000 //200MB#if defined(FORLINX_BOOT_NAND)#define CONFIG_BOOT_NAND#define CFG_ENV_IS_IN_NAND//#define CFG_NAND_LARGEPAGE_SAVEENV//#define CFG_NAND_FLASH_BBT#define CONFIG_BOOTCOMMAND    "nand read 0xc0008000 0x200000 0x500000;bootm 0xc0008000"
复制代码

        这部分定义了nand flash的地址空间划分和启动的地址:bootm 0xc0008000,也就是说是从内存中的这个地址启动内核的,但问题是在上图的地址划分中地址最大值也只到0x6FFFFFFF,0xc0008000这个地址是什么地方呢?一样从源码入手,继续找!

同样从smdk6410.h这个文件的452行可以找到这部分配置。

代码3

复制代码
/* base address for uboot */#ifdef CONFIG_ENABLE_MMU#define CFG_UBOOT_BASE        TEXT_BASE#define CFG_PHY_UBOOT_BASE    (MEMORY_BASE_ADDRESS + (TEXT_BASE - 0xC0000000))#else#define CFG_UBOOT_BASE        TEXT_BASE#define CFG_PHY_UBOOT_BASE    TEXT_BASE#endif
复制代码

        看了这段代码就明白了,在使能了MMU之后,这段代码相当于对地址做了一个重映射,经过(MEMORY_BASE_ADDRESS + (TEXT_BASE - 0xC0000000))计算后,因为MEMORY_BASE_ADDRESS  为0x50000000(可以在文件开始找到定义)所以经过这样的一个计算,0xc0008000就是0x50008000。而0xc0008000是内核启动的起始虚拟地址,因此需要做这样的一个映射来和内核对应。

        到这儿可能很多人和我当初有一样的疑惑,那就是如果tftp烧写文件系统应该烧写到哪一个地址去呢?在回到上面的地址图表,在最开始我就说过,这个表是针对使用地址总线与数据总线操作的设备而言,因此对于NOR flash、SRAM、DRAM等都是可以直接寻址读写的,而对于Nand Flash,可以参考下电路图,使用的是8个IO进行操作,右Nand控制器弯沉相关的操作,因此是没有一个绝对的地址的。需要注意图表中的黄色框部分,One Nand并不是普通Nand Flash,区别就在于这种Nand是和NOR、SRAM一样的通过地址总线、数据总线进行操作的方式,因此它是有地址的,对于板子所用的Nand Flash来说只有偏移地址,没有绝对地址。

        到这里,对于tftp下载内核、文件系统的相关操作应该清楚了,具体地址其实看看uboot源码就清楚了,可以参考代码1中的这部分:

#define CONFIG_BOOTCOMMAND  "nand led-start;nand erase  ;fatload mmc 0:1 0x50008000 u-boot.bin;nand write.uboot 0x50008000 0 0x200000;fatload mmc 0:1 0x50008000 zImage;nand write.e    0x50008000 0x200000 0x500000; fatload mmc 0:1 0x50008000 rootfs.yaffs2; nand write.yaffs2 0x50008000 0x00700000 $filesize;  nand  beep; nand led-end"

如果通过sd卡启动时跳过自动操作进入手动选择操作的话就应该有印象,可以单独选择烧写某一个文件,例如单独烧写文件系统,操作如下图所示:

SNAGHTML1ac3bff

那么通过找到对应的命令源码也是可以的,源码位于common/mian.c 343行:

复制代码
void arm_USBfuse(void){    unsigned char select;    while(1)    {        printf("\n##### Select the fuction #####\n");        printf("[1] Flash u-boot\n");        printf("[2] Flash kernel\n");            printf("[3] Flash system\n");                printf("[4] Exit\n");        printf("Enter your Selection:");            select = getc();        printf("%c\n", select >= ' ' && select <= 127 ? select : ' ');    void arm_sdfuse(void){    unsigned char select;    while(1)    {        printf("\n##### flash from SDcard  #####\n");        printf("\n##### Select the fuction #####\n");        printf("[1] Flash all image\n");        printf("[2] Flash u-boot\n");        printf("[3] Flash kernel\n");        printf("[4] Flash system\n");                    printf("[5] Exit\n");        printf("Enter your Selection:");            select = getc();        printf("%c\n", select >= ' ' && select <= 127 ? select : ' ');                switch(select)         {            case '1':                ExecuteCmd("nand erase");                ExecuteCmd("fatload mmc 0:1 50008000 u-boot.bin");                ExecuteCmd("nand write.uboot 50008000 0 200000");                ExecuteCmd("fatload mmc 0:1 50008000 zImage");                ExecuteCmd("nand write.e 50008000 200000 500000");                ExecuteCmd("fatload mmc 0:1 50008000 rootfs.yaffs2");                ExecuteCmd("nand write.yaffs2 50008000 700000 $filesize");                break;                        case '2':                ExecuteCmd("nand erase 0 200000");                ExecuteCmd("fatload mmc 0:1 50008000 u-boot.bin");                ExecuteCmd("nand write.uboot 50008000 0 200000");                break;                                case '3':                ExecuteCmd("nand erase 200000 500000");                ExecuteCmd("fatload mmc 0:1 50008000 zImage");                ExecuteCmd("nand write.e 50008000 200000 500000");                break;            case '4':                ExecuteCmd("nand erase 700000");                ExecuteCmd("fatload mmc 0:1 50008000 rootfs.yaffs2");                ExecuteCmd("nand write.yaffs2 50008000 700000 $filesize");                break;            case '5':                return;            default:                break;        }    }}
复制代码

通过tftp单独烧写内核或者文件系统时只需要参考一键烧写的命令烧写到对应的nand 偏移地址即可。


原创粉丝点击