在尚观听了一阵课了,收获目前还算一般,并没有特别兴奋的点。截止今日ARM内容已经结束,有些课并不是很有兴趣去听。根据本人一向颇为难以理解的习惯,当时不听事后琢磨,现在是仔细写下东西的时候了。那么,也不嫌再多单片机文档的繁琐,重新开始这个从裸机到U-BOOT的小过程。
目前我们使用的是ARM11核心的三星S3C6410作为处理器。事实上不搭系统就是单片机的类型,起码我一直是这么称呼的。深深的希望内核驱动课程给我以启发,否则就太无趣了。
很显然,我们的S3C6410微处理器是封装了ARM1176JZF-S的核,关于ARM11另开博文再讲自己的学习,这里仅仅针对高一层的6410微处理器。按照自己的思路,开始吧!
注,本文属于个人读书笔记性质,有心的随便看看就行了,转载请注明出处:
我的博客:Moon小夜曲
http://blog.chinaunix.net/uid/28720832.html
欢迎大家文明探讨
由于博客中大图片显示不方便,现在在文末放上原本的笔者doc文档,欢迎下载,多多指教支持~
1:哈佛结构与冯诺伊曼结构
哈佛结构是程序指令与数据分开存储的一种的结构。它是一种并行结构,如图:
它的特点是程序的指令与数据分开存储在不同的存储空间,并且独立编址,独立访问。
对于哈佛结构,一个明显的例子就是51单片机了。使用过汇编编程的都知道,如AT89C51下有4KB的FLASH,128字节的RAM,对应的,4KB就是程序存储器,128字节的数据存储器。这两者的地址分别为:FLASH 0x0000 – 0x0FFF ;RAM 0x00 – 0x7F。这两个地址的0地址对应完全不同的存储空间,程序的地址由汇编的ORG指定,而RAM中包括有4套通用寄存器和各种SFR。
冯诺伊曼结构则是程序指令与数据存储合并在一起的一种结构。指令与数据共享总线,它们的存储器是统一编址的,指令与数据的识别与时间有关。S3C6410就是冯诺伊曼结构的。由于是32位的地址范围,也即为0x00000000 – 0xFFFFFFFF 共4G的地址范围。
但是从0x80000000 – 0xFFFFFFFF 2G的地址是被保留了,因此,所有的设备都对应在0x00000000 – 0x7FFFFFFF 的范围内,也即为统一编址,如下图所示:
0x00000000 – 0x7FFFFFFF这段地址,被分为了两个部分:高地址的0x7000_0000 – 0x7FFF_FFFF被用于对应所有外设的寄存器。低地址的0x0000_0000 – 0x6FFF_FFFF对应于各种存储器的地址。类似51中FLASH和RAM的部分并没有具有单独的地址,而是使用唯一的地址,也即是冯诺依曼结构统一编址。
2:存储器简介
事实上来说,就操作单片机而言,可以认为所有的外设就是存储器(寄存器)。这里,将是一个及其重要的部分,首先还是整理下,“存储器”这个东西。
有篇文:什么是ROM、RAM、DRAM、SRAM和FLASH及区别_IT168文库
地址:http://wenku.it168.com/d_000139890.shtml
关于存储器说的比较多了,看的也是云里雾里,但是概括的说:
ROM方面:
过去的EPROM之类基本上被FLASH全部取代了,FLASH具有电擦除,掉电不丢数据,较快读取等优点。FLASH主要分为nor FLASH与NAND FLASH。
这两者的对比包括:nor FLASH的读取与SRAM一样,因此可以直接从中直接运行加载在其中的代码,NAND FLASH中的程序不能直接运行,必须加载到内存运行;nor FLASH的访问比NAND FLASH稍快;NADN FLASH的写入比nor FLASH快很多,擦除则快了很大的数量级。
因此,显然的,基于以上的特点,在1M ~ 4M等小容量存储的时候,nor FLASH是有很大优势的,但是作为类似硬盘的大量存储时,NADN FLASH是不二的选择。(如我们使用的up6410上挂载两片NADN FLASH)。至于AT89C51上带的4K FLASH是什么性质,百度得知名为:FPEROM—Flash Programmable and Erasable Read Only Memory,就不得而知是什么物体了,里面应该是可以直接运行指令的。这里做下注脚,将来讲到NAND FLASH与SRAM等的时候在仔细分析吧。
这里,还有一种叫做one NAND的存储设备,它就是针对上面的nor FLASH与NAND FLASH的,它具有nor FLASH与NAND FLASH的优势,是下一代嵌入式存储设备。S3C6410上是有one NAND控制器的。
RAM方面:
RAM分为两大类,一类就是静态RAM----SRAM,它是所有存储器中速度最快的,当然啦,价格也要贵,一般用在最重要的地方。传说中CPU的一级二级缓冲就是。另一类就是动态-----DRAM,DRAM比SRAM便宜的多,但是比所有的ROM快,一般用于内存。
DDRRAM是DRAM的一类。
如我们使用的up6410板,S3C6410芯片内部有8KB的SRAM,32KB的SROM,这是用于开机启动初始化等等的,外部则搭了貌似128M的DDR RAM,这一部分的DDRRAM被当做内存使用。裸机运行程序,需要将NAND FLASH中的程序搬运到DDRRAM中,然后You Jump,I Jump~
另外还有外设寄存器的部分,应当是使用RAM。
3:地址映射
3.1 S3C6410存储器地址空间分类
上面介绍了些存储器,接下来自然就是看看这些存储器在统一编址下是怎样的编址了。
在第一小节介绍过,被使用的低2G的地址空间分为两部分,
高地址的0x7000_0000 - 0x7FFF_FFFF共计256MB的空间是分给S3C6410的外设寄存器的
低地址的0x0000_0000 - 0x6FFF_FFFF 共计 0x700 MB = 1792MB是分给存储器的
高地址部分是ARM核通过PERI总线访问,现在暂且认为里面皆是寄存器即可。
低地址部分则比较复杂了,根据S3C6410 data sheet第二章Memory Map,这一部分分为四个区域,它通过SPINE总线访问:
Main memory is accessed via SPINE bus, and its address range is from 0x0000_0000 to 0x6FFF_FFFF. This main memory part is seperated into four areas, boot image area, internal memory area, static memory area, and
dynamic memory area.
(1)
boot image area 引导镜像区
Address range of boot image area is from 0x0000_0000 to 0x07FF_FFFF, but there is no real mapped-memory. Boot image area has mirrored image which points a partial region of internal memory area or static memory area. Start address of boot image is fixed to 0x0000_0000.
这里我们发现,这是个坑爹镜像区。ARM体系复位后PC跳到0x0000_0000处开始运行指令,因此这个地址出必须存储一些启动芯片的信息。这个就是引导区得由来吧。这个区的大小是0x0000_0000 – 0x07FFF_FFFF。然而,文中说到,事实上,这个区并没有真实的对应存储器设备。Boot image area has mirrored image which points a partial region of internal memory area or static memory area.直译就是:引导镜像区有镜像指向内存或者静态存储区。这个镜像区的0x0000_0000地址将是一个争夺的焦点。
(2) internal memory area 内部存储区
Internal memory area is used to access internal ROM and internal SRAM for boot loader, which is also called Steppingstone. Start address for each internal memory is fixed. Address range of internal ROM is from 0x0800_0000 to 0x0BFF_FFFF, but real storage is only 32KB. This region is read-only, and can be mapped to boot image area when internal ROM booting is selected. A ddress range of internal SRAM is from 0x0C00_0000 to 0x0FFF_FFFF, but real storage is only 4KB.
内部存储区包括两个部分,内部SROM部分和内部SRAM部分。这两个部分基本上可以说就是为了boot loader准备的。其中的SROM区的地址是0x0800_0000 – 0x0BFFF_FFFF,但是事实上没有存满,仅仅存了32K。同理的,SRAM的地址范围,但是只有4K的实际设备。(S3C6410里面8K)。非常有意思的一句:This region is read-only, and can be mapped to boot image area when internal ROM booting is selected.简单的说,当芯片被选择为内部ROM启动时,这32K就映射到引导镜像区了,可见引导镜像区是随着启动模式不一样而不同映射的。
(3) dynamic memory area 动态存储区
Address range of dynamic memory area is from 0x4000_0000 to 0x6FFF_FFFF. DMC1 has right to use address range from 0x5000_0000 to 0x6FFF_FFFF. Start address for each chip select is configurable.
动态存储区的范围是从0x4000_0000 – 0x6FFF_FFFF 也就是共计 0x300MB = 768MB的范围。这个范围是用于搭载DRAM的,也就是是内存的区域。我们使用的板子内存地址是从0x5000_0000开始的。很多资料上说的是0x4000_0000 – 0x5000_0000的地址被保留了,也有资料说是对应到了别的部分。
(4) static memory area 静态存储区
这是最复杂的一个区:
Address range of static memory area is from 0x1000_0000 to 0x3FFF_FFFF. SROM, SRAM, NOR Flash, asyncronous NOR interface device, OneNAND Flash, and Steppingstone can be accessed by this address area.
Each area stands for a chip select, for example, address range from 0x1000_0000 to 0x17FF_FFFF stands for Xm0CSn[0]. Start address for each chip select is fix ed. NAND Flash and CF/ATA c annot be accessed via static
memory area, so if any of Xm0CSn[5:2] is mapped to NFCON or CFCON, related address region should not be accessed. One exception is that if Xm0CSn[2] is used for NAND Flash, Steppingstone is mirrored to address region from 0x2000_0000 to 27FF_FFFF.
静态存储区的地址是0x1000_0000到0x3FFF_FFFF 各种各样的存储设备都可以被搭载在这个区,也包括Steppingstone。这个区域的大小为6*128MB,共有6个Bank。对应地址片选引脚Xm0CSn[0]~ Xm0CSn[5]。在我们使用的板子上,这6个Bank搭载了的NAND FLASH,网卡。也就是,访问这些地址,有的是访问存储器,有的就选中了网卡。接下来就对动态存储区和静态存储区先粗略分析下吧,主要是让地址明晰。目前,我们得到的0到2G的地址映射图就是这样的:
3.2: 动态存储区(0x5000_0000 – 0x6FFF_FFFF)的设备
这个区在我们使用的up6410上用于接上了两片DDRRAM(k4x51163PC),作为程序运行的内存。
先看看两片DDRRAM的连接:
除了图中标记的高亮部分和数据总线XM1_DATA,两片DDRRAM的连接一样。另外一片对应的信号线为“XM1_DQS2”“XM1_DQS3”“XM1_DQM2”“XM1_DQM3”,对应的数据线为XM1_DATA[16:31]。
其后是地址线,两片均连接在XM1_ADDR[0:15]上。
K4X51163是32M*16bit,一片64M,两片共计128M映射在我们使用的板子的动态存储区的0x5000_0000 – 0x57FF_FFFF上。其余地址未使用。
3.3:静态存储区(0x1000_0000 – 0x4000_0000)挂载的设备
静态存储区分为6个Bank0 ~ Bank5,这六个Bank使用信号线XM0CSN[0:4]分别。
现在来简略看下在静态存储器的BANK上,都挂载了哪些设备。
NADN FLASH 挂载在BANK2 BANK3
网卡,挂载BANK1上。
因此,在我们使用的开发板上BANK1 2 3挂载了设备,其余并未使用。
这个就决定了这些设备的地址,因为地址就是片选。具体后面再说吧,现在仅仅为了个观感。
4 S3C6410的启动过程
启动过程近乎是S3C6410学习一定要明白的第一个点,这是bootloader的基础,也是理解上面存储器区间的很重要的点。
首先,认识下几个6410外部的引脚:
这几个引脚的OM1 – OM4,EINT13 - EINT15(也就是GPN[13:15]),是接在一个拨码开关上的,如下:
那么,对照上面这张图,可以大体明白这些引脚的作用:启动时候的设备选择。
这里呢,仅针对我使用的UP6410开发板分析吧,一则其他的模式我也未使用过,不敢乱说,二则本文很大程度也仅仅是个读书笔记,不敢奢求大而全。
1:OM[0:4] GPN[15:13] XSELNAND
(1)OM[0]
OM[0]信号参见上图的clock source时钟源一栏,该信号对于设备的选择是无效力的(左侧的设备选择OM[0]位全是X),但是直接决定复位时时钟的选择。
OM[0]信号为0时候选择是一个叫“XXTIpll”的时钟源;为1时选择的是“XEXTCLK”。
在6410的用户手册下搜索”XXTIpll”,一箭双雕,找到了这样一段话
可见,XXTIpll指的是外部晶振,XEXTCLK指的是外部clock(我也不知道怎么翻译了~)。
而在我使用的6410开发板下,这个可怜的引脚都没有机会接到那个决定启动的拨码开关上,在一个不起眼的角落里,发现了它:
意义太明显了。
至于外部晶振,貌似是12M,不过内部各种锁相环倍频。到了时钟的时候再分析吧。
(2)OM[4:1]
由上面的图标Table 3-1可以看出,这四位直接决定了S3C6410的启动模式(设备选择)。
从开发板的原理图上看不出这些引脚具体是怎么接的(拨码开关是两个拨码的),事实上我也没弄明白这张图的全部涵义 (囧),在我们使用开发板的过程中,是有两种启动模式的:SD卡启动与NANDFLASH启动。
当然,这里参考网上大神的说法,把这几个引脚的事情说清楚,具体对照Table3 – 1:
OM[4:0]:选择启动设备及时钟源。OM[0]为0选择XXTlpll,为1选择XEXTCLK。
GPN[15:13]:用于识别所支持的Nandflash的类型,包括Page的类型和地址周期。
XSELNAND:选择Nand启动或者是OneNand启动。0为OneNand,1为Nand。
前面分析了我使用的板子,上面是没有oneNAND/nor FLASH的,因此XSELNAND为1,而OM[0]直接接地线了,OM[0] = 0;
2:S3C6410支持的启动模式
然后看看OM[4:1]
(此处转载)
1. NORFlash启动
通过Nor Flash启动,此时OM[4:1]为0100或0101,对应8bit和16bit。
2. NandFlash启动
虽然在S3C6410 User Manual中没有提到,但是也是支持的,从S3C6400 User Manual可以找到。OM[4:1]四个硬件管脚决定了Nandflash启动,以及支持的Nandflash的类型,包括大Page和小Page,地址周期为3,4,5。当然,XSELNAND管脚也要为1。
3. OneNAND启动
首先XSELNAND管脚为0,其次OM[4:1]为0110,为OneNand启动模式。
4. MODEM启动
当OM[4:1]为0111的时候,为MODEM启动。S3C6410通过MODEM接口下载boot代码到内部RAM中,然后进行引导。
5. IROM启动
当OM[4:1]为1111的时候,从Internal ROM中启动,此时GPN[15:13]用于识别设备的类型。
IROM模式可以支持MoviNand,SD/MMC,iNand,OneNand和Nand等。
(转载完毕--)
上面标为粉色部分与蓝色部分为我使用的up6410开发板的使用的启动类型。
我使用的开发板的NANDFLASH启动的方式可能是蓝色或者粉色的一种,这里为什么这么说呢,是因为之前的一句“拨码开关不知道怎么接的”。因此NANDFLASH的启动也有可能与SD启动一样,是IROM(粉色)方式。但是如果是最简单的接法,就是将EINT[15:13],XSELNAND,OM[4:1]全部接在这个开关两端,那么作为蓝色的NANDFLASH启动方式-也是完全说的通的。如果按照这样的接法,我们就看见了如下效果:
这样的话,当拨码开关合上,也就是所有信号都接上了1.从Table3-1表上可以是IROM启动下的SD卡启动,这与我使用开发板时一致。
但是如果是接在一起的时刻,就有疑问了。这样的话,开关断开时候,所有信号线全部接在了0(GND)上,而图Table3-1中全部为0的一项是没有的(reserved)。
这时,也有牛人找出了可以解释这个的原因,说是事实上,S3C6410与S3C6400的启动模式兼容,而S3C6400的启动模式中,上图Table3-1的几个保留项全部都是使用NANDFLASH启动(汗),如果是这个成立的话,就完全能解释了,也符合我使用up6410开发板的现象:向下搬动拨码开关时,S3C6410通过NANDFLASH启动(不经过IROM引导)。
这样的话,现在如果我们认为蓝色的NANDFLASH是我所使用的up6410的实际启动方式,那么,它的流程可能是这样的:
1:开机S3C6410拷贝NANDFLASH的前8K程序到SRAM(stepingstone)中
2:SRAM中的程序运行(实际0地址),这个程序要负责初始化各种设备,以及内存,并且如果需要运行的程序大于SRAM的8K,把存在DNADFLASH中的程序拷贝到内存中,跳至内存中运行。
这个流程应该说是使用NAND启动还是有可能的,毕竟引导镜像区是有指向静态存储区的,但是如何拷贝程序就有很大疑问了。疑问的关键在于,在芯片不运行内部SROM的32K固化代码的情况下(这就意味着很多设备包括NANDFLASH可能没有初始化),将NANDFLASH的程序拷贝到8KSRAM运行。现在的SAMSUNG似乎不提倡这种启动方式以至于S3C6410的启动方式表(也就是上文的Table3-1)上这种NANDFLASH启动方式都reserved了。不过,在网上找到的一段关于S3C2440的博文似乎给出了解释:
nandflash由于其自身的特点,不具备运行程序的功能。但s3c2440通过称为“Steppingstone”的内部SRAM缓存,实现了可以运行存储在外部nandflash中的启动代码的功能。它的机制是:当检测到是由nandflash启动时,系统会自动把nandflash中的前4k字节的数据加载到Steppingstone中,然后把该Steppingstone映----------射为Bank0,因此系统会从Steppingstone开始运行程序,从而实现了s3c2440的nandflash自启动的功能。这一过程是由系统自动完成的,无需人为干预。在系统启动以后,Steppingstone所在的SRAM就可以用作其他用途了。
由于都是SAMSUNG出的家伙,应该认为是个合理的解释。
然后接下来就是我们可爱的,最重要的IROM模式了(粉色部分)
(蓝色部分的NANDFLASH流程与IROM的NANDFLASH流程主要不同于是否跑32K SROM)
3:IROM启动方式流程简析(最重要)
上节说过,我使用的开发板NANDFLASH启动方式也有可能是与IROM方式(上节粉色方式),这里再写下来:
IROM启动: -
当OM[4:1]为1111的时候,从Internal ROM中启动,此时GPN[15:13]用于识别设备的类型。
IROM模式可以支持MoviNand,SD/MMC,iNand,OneNand和Nand等。
这个IROM启动模式,略微有些复杂。对于具体的某些部分究竟实现了某些功能,因为这种启动模式的主要模块—32KSROM中的代码是芯片固有的,因此也只大概了解即可。以下的这张图描述了这种启动方式。这里根据下图概括下这种模式的流程,标号与图中对应:
图中的BL0 BL1 BL2就是这种芯片的启动代码。全部三者的集合将会完成上电后初始化芯片设备,拷贝存储设备上的用户需要运行的代码到SRAM(或者DDRRAM内存也是一样),跳转到SRAM/DDRRAM等运行用户程序等功能。
①开机启动,32KIROM(内部SROM,地址参见内部存储区)映射到0地址,芯片跑存储在其中的程序。这个程序成为BL0,它是三星烧入的,固有在芯片内部。它初始化了很多的东西,细节参见手册,这些东西必须保证芯片的初步运行,笔者也不太说的全(云里雾里)。运行的结果之一当然是为了②步骤。这个时候就要看外部的OM[4:1]与GPN[15:13]的接法了,这段程序会初始化与之对应的启动方式的启动设备(SD卡,NANDFLASH,oneNAND等,MMC是什么?~~~~)。然后把存储在这些设备的中的BL1部分拷到8KSRAM中(内部SROM,地址参见内部存储区)。
②此时程序跑到8KSRAM中。这部分的作用还是初始化某些设备堆栈神马的,然后,将BL2拷到SRAM或者DDRRAM之类的地方,总之是可以跑程序的地方,当然这些地方的初始化会在这一步完成。
③传闻中BL2是比较复杂的,当上一步的8K程序跑完,就跳到内存/SRAM之类的BL2地址了。运行它可以加载复杂的程序了,例如加载操作系统。
然后一去不复返..........
感觉好口水好低俗的描述,为了弥补下,下文找个时间翻译下文档的这个流程?算了,免得累死! - -
描述IROM的文档:
S3C6410_Internal_ROM_Booting.pdf
至于其它的启动模式,没有使用过,板子上也没有nor FLASH或者MODEN或者one NAND。很显然,IROM这种启动方式将会受到偏爱。后面的u-boot神马的都得跟着这个来,这里架构一定要清晰。
5:0x0000_0000地址争夺战
其实前面提到过一个问题,ARM体系复位的时候程序指针PC是指向0x0000_0000这个地址的。而现在,在S3C6410中,这个地址成为了所谓的“引导镜像区”。也就是说,根据启动方式的不同,不同的设备都有可能映射到这个地址。换言之,不同启动模式下的0x0000_0000的实际指向是不同的。这是一个之前纠结了一阵的点,太诡异了不是么?哈哈!
当然了,这个还只是小事。对应的0地址之后不远还有几个异常向量表。0地址漫天飞,这个向量表呢?额,难怪这里不能用所谓“与地址相关的指令”,看样子也是漫天飞吧。