打印

u-boot代码分析和移植,连载中

[复制链接]
10315|47
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
8421bcd|  楼主 | 2009-11-18 01:00 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 8421bcd 于 2009-11-24 19:56 编辑


这个是40楼(changyongid)对MPLL的补充,现在明白为什么初始时钟是120M了,可以参考DATASHEET的242页,感谢changyongid!
补充一个。

初始120M的频率。。。

MPLL= ((M+8) * Fin) / ((P+2) * 2 ^ S)
上电后,默认M = 0X5C , P = 0X08 , S = 0X0,
而FIN = 12M
这样计算下来,FCLK=120M


/********************以上为更新说明*********************/

用的U-BOOT版本是1.1.2,CPU是S3C2410
U-BOOT源码在这里可以下到http://sourceforge.net/projects/u-boot/files/u-boot/
*/

#include <config.h>
#include <version.h>

/*
*************************************************************************
*
* Jump vector table as in table 3.1 in [1]
*
*************************************************************************
*/

.globl _start        ;声明一个全局变量,可以把它当然一个程序标号,不过在整系统中是都可以使用的,globl是一个伪指令,可以查看资料,它不进行数据操作
_start: b       reset      ;跳转到复位异常执行,优先级为1  
ldr pc, _undefined_instruction    ;该指令存放地址为0x00000004,是示定义指令异常入口,也就是说当产生未定义异常时,程序寄存器PC会自动给赋值0x00000004,学过单片机的应该明白,优先级为6
ldr pc, _software_interrupt                         ;软件中断入口,存放地址为0x00000008,优先级为6,因为它和未定义指令异常是互斥的,所有可以为同一优先级
ldr pc, _prefetch_abort     ;指令预取终止异常,地址为0x0000000c,十六进制表示,这应该清楚吧
ldr pc, _data_abort                                 ;数据访问终止异常,地址为0x00000010  
ldr pc, _not_used      ;未使用异常,地址为0x00000014,还不清楚是做什么的,清楚的请补充
ldr pc, _irq      ;外中断异常,地址为0x00000018
ldr pc, _fiq      ;快速中断异常
/*以上是ARM920T核的9个异常入口地址,其中 b reset不需要返回,好好想下为什么!呵呵。*/
_undefined_instruction: .word undefined_instruction   ;这条指令相当用undefined_instruction对_undefined_instruction赋值,.word也是一个伪指令,它说明赋的值为字!这些值应该都在链接时生成         
_software_interrupt: .word software_interrupt   ;说明下,在ARM中,8位的为字节,十六位的为半字,三十二位的字,下面几条指令一样,不多说
_prefetch_abort: .word prefetch_abort
_data_abort:  .word data_abort
_not_used:  .word not_used
_irq:   .word irq
_fiq:   .word fiq
.balignl 16,0xdeadbeef     ;没搞明白,不是浪费空间么?还是十六的倍数!可以查看http://haoyeren.blog.sohu.com/84511571.html

/*
*************************************************************************
*
* Startup Code (reset vector)                           这里介绍了整个start.S代码的作用:
*                                   初始化内存,移动代码到内存,设置堆栈等
*************************************************************************
*/
_TEXT_BASE:
.word TEXT_BASE      ;TEXT_BASE对_TEXT_BASE赋值,TEXT_BASE在board/smdk2410/config.mk文件中定义,值为0x33F80000,如果是64M内存的话,它就是内存的最后一个地址,有点意思
.globl _armboot_start      ;声明全局变量
_armboot_start:
.word _start       ;_start对_armboot_start赋值,_start的值由链接文件生成,也是程序的入口地址           

.globl _bss_start       ;声明一个代码段的开始标号
_bss_start:
.word __bss_start      ;并用__bss_start对它赋值,这个值应该是在链接时候生成
.globl _bss_end       ;声明一个代码段的结束标号
_bss_end:
.word _end       ;并用_end对它赋值,也是在链接的时候生成
#ifdef CONFIG_USE_IRQ      ;如果定义了CONFIG_USE_IRQ名,可能是在IRQ(包括FIQ)中断保护时对其有定义,先不理,回头再看它
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START      ;声明一个外中断处理程序规堆栈的开始名
IRQ_STACK_START:
.word 0x0badc0de      ;对刚声明的IRQ_STACK_START进行赋值,值为0x0badc0de,不知道为什么设这个值,它影射不到SDRAM的任何地址吧,带着疑问继续
/* IRQ stack memory (calculated at run-time) */  
.globl FIQ_STACK_START      ;声明一个快中断程序处理堆栈的开始名
FIQ_STACK_START:
.word 0x0badc0de                                       ;对刚声明的FIQ_STACK_START赋值为0x0badc0de,它跟外中断的堆栈始地址相同
#endif         ;配合#ifdef一起用

/*
* the actual reset code实际的复位代码    ;好了,到这里开始执行CPU初始化工作了,以下用尽量符号表示其指令含义
*/
reset:
/*
  * set the cpu to SVC32 mode   设置CPU工作在32位管理模式
  */
mrs r0,cpsr      ;r0<--cpsr,把cpsr送到r0中      ;
bic r0,r0,#0x1f      ;对r0中的01234位清0,把0x1f转换为二进制为0b00011111,明白为什么为012345位了吧,bic是一个位清0指令
orr r0,r0,#0xd3      ;orr是或逻辑运算指令,它的意思是r0 | 0xd3,再把运算结果放到r0中,0xd3转换为二进制0b11010011,这时r0的8位就应该是这个0b11010011了     
msr cpsr,r0      ;再把r0的值送到程序状态寄存器cpsr中,些时cpsr中的值为0b11010011,用这些字符(I F T M4 M3 M2 M1 M0)表示cpsr的低8位,I=1表示禁止IRQ中断,F=1表示禁止FIQ中断,T=0,表示以下的指令是ARM指令集开始执行
         ;也就是32位指令集,(还有一个THUMB是16位指令集)低5位的值使CPU工作在管理模式,这个模式下可以处理软中断SWI。
/* turn off the watchdog */                                   ;关闭看门狗,为什么关呢,这时CPU还没有初始化,没有喂狗信号,时间一长CPU就会自动复位了!
/*下面这段代码主要是关闭看门狗,屏蔽所有中断,设置CPU时钟*/
#if defined(CONFIG_S3C2400)      ;如果定义了CONFIG_S3C2400,那么执行下面三行语句,s3c2410这段没有定义,下面三行不说了
# define pWTCON  0x15300000   
# define INTMSK  0x14400008 /* Interupt-Controller base addresses */
# define CLKDIVN 0x14800014 /* clock divisor register */
#elif defined(CONFIG_S3C2410)     ;如果定义了CONFIG_S3C2410执行下面四行语句
# define pWTCON  0x53000000    ;宏定义,地球人都知道了 ~_~ ,0x53000000是看门狗控制寄存器,以后再用它的时候是不是很方便,查下DATASHEET就知道了
# define INTMSK  0x4A000008 /* Interupt-Controller base addresses */ ;0x4A000008是中断屏蔽寄存器
# define INTSUBMSK 0x4A00001C     ;0x4A00001C是子中断屏蔽寄存器   
# define CLKDIVN 0x4C000014 /* clock divisor register */时钟分频寄存器,用于控制FCLK,HCLK,PCLK之间的时钟关系
#endif
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)    ;我们定义了2410的的
ldr     r0, =pWTCON      ;把看门狗寄存器的地址加载到r0
mov     r1, #0x0      ;r1 <-- #0
str     r1, [r0]      ;对看门狗寄存器清0      
/*
  * mask all IRQs by setting all bits in the INTMR - default
  */
mov r1, #0xffffffff     ;r1 <-- #0xffffffff
ldr r0, =INTMSK      ;把中断屏蔽寄存器地址赋到r0
str r1, [r0]      ;对中断屏蔽寄存器位全置1,屏蔽所有中断
# if defined(CONFIG_S3C2410)     ;到这里是不是看到了两种关于#define的用法,对比刚才的,不同的时候不同的妙用!
ldr r1, =0x3ff      ;r1 <-- 0x3ff,等号表示后面的是立即数,可以直接用
ldr r0, =INTSUBMSK     ;这里引用了宏定义,相当于r0 <--0x4A000008
str r1, [r0]      ;把0x3ff存到0x4A000008地址里,也是中断寄存器进行设置,屏蔽部分中断,要根据实际配置
# endif
/* FCLK:HCLK:PCLK = 1:2:4 */    ;设置FCLK、HCLK、PCLK的比例关系
/* default FCLK is 120 MHz ! */                        ;看DATASHEET也没看明白为什么初始FCLK为120M,晕倒,跟DATASHEET不一样
ldr r0, =CLKDIVN      ;把时钟频控制寄存器地址赋给r0
mov r1, #3       ;r1 <-- 3
str r1, [r0]      ;把3赋给时钟控制寄存器,这时FCLK:HCLK:PCLK=1:2:4,查看DATASHEET可以得到,FCLK指CPU内核的工作频率;HCLK指一些高速设备频率,比如USB,LCD,网口等;PCLK指低速的设备如IDE,SPI等
#endif

start.rar

7.91 KB

mysoft_k-SourceInsight.rar

3.14 MB

相关帖子

沙发
8421bcd|  楼主 | 2009-11-18 01:00 | 只看该作者
/* CONFIG_S3C2400 || CONFIG_S3C2410 */   

/*
  * we do sys-critical inits only at reboot,
  * not when booting from ram!
  */
#ifdef CONFIG_INIT_CRITICAL      ;到这里忽然意识到,包括上面类似的指令,应该都在UBOOT的Makefile找到定义,也就是判断的这些定义,先不管
bl cpu_init_crit      ;要初始化CPU(包括内存),同时把当前r15(PC寄存器)保存到r14(程序链接寄存器),保护现场,上面那个应该条件成立吧,不然后CPU怎么工作,好现在我们看它到哪里去了,到这里要跳转了,跟着程序走哟
#endif         ;执行bl的时候系统会自动保存,舒服吧

relocate:    /* relocate U-Boot to RAM     */ ;这下面这段程序就要移代码了,因为SRAM已经初始化(我们假设的,回头再看那),2410片内的4KSRAM用得应该差不多了吧
adr r0, _start  /* r0 <- current position of code   */;adr伪指令,把_start的地址赋给r0,_start还记得吧,链接生成的地址
ldr r1, _TEXT_BASE  /* test if we run from flash or RAM */;查看上面定义过的_TEXT_BASE,ldr是把地址为0x33F80000的数据读到r1,测试下看内在初始化OK了没,ldr指令一般用于从存储器中读取数据
cmp     r0, r1                  /* don't relocate during debug         */;r0与r1中的数据比较,实际上是r0、r1进行减运算,大、小、等于来更改CPSR的标志位(第31位,也是最高位),1为正数,0为负数,r0>r1标志位清0,些时后面GT后缀的指令可以执行
beq     stack_setup         ;如果r0=r1,则跳转到stact_setup(用于堆栈设置)
/*下面4行代码用于计算要移动的代码的大小,还不太清楚是怎么计算出来的,到连接的时候再回头看*/
ldr r2, _armboot_start        ;把地址给r2
ldr r3, _bss_start        ;把代码的起始地址给r3
sub r2, r3, r2  /* r2 <- size of armboot            */  ;r2 <-- r3 - r2
add r2, r0, r2  /* r2 <- source end address         */  ;r2 <-- r0 + r2
/*下面4行用于移动代码*/
copy_loop:
ldmia r0!, {r3-r10}  /* copy from source address [r0]    */  ;以r0的值为地址递增的加载到r3-r10,并把最的的基址给r0
stmia r1!, {r3-r10}  /* copy to   target address [r1]    */  ;把r3-r10的数据送到以r1的值为地址递增的地址空间里,并把最后的基址给r1
cmp r0, r2   /* until source end addreee [r2]    */  ;判断有没有移动完成
ble copy_loop         ;r0若小于等于r2,则跳转到copy_loop

/* Set up the stack ;堆栈初始化,现在还不知道位置在哪里,链接的时候再回头看    */   
stack_setup:
ldr r0, _TEXT_BASE  /* upper 128 KiB: relocated uboot   */ ;把内存地址为0x33F80000(最后一个地址)中的数据加载到r0,可以猜测u-boot可能把堆栈设置在了内存的最高地址
sub r0, r0, #CFG_MALLOC_LEN /* malloc area                      */ ;r0 <-- r0-#CFG_MALLOC_LEN,CFG_MALLOC_LEN在include/configs/smdk2410.h文件中有定义
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */ ;r0 <-- r0-#CFG_GBL_DATA_SIZE,CFG_GBL_DATA_SIZE值为128,在include/configs/smdk2410.h文件中有定义,这两条指令可能是用于设置堆栈空间大小和单位
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)   ;r0 <-- r0-#CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ,不知道这个在哪里定义,在根目录下搜索也没找到,可能由编译器产生吧
#endif
sub sp, r0, #12  /* leave 3 words for abort-stack    */  ;sp <-- r0-#12,给堆栈指针赋值


clear_bss:
ldr r0, _bss_start  /* find start of bss segment        */ ;把_bbs_start地址存到r0
ldr r1, _bss_end  /* stop here                        */  ;把_bbs_end地址存到r1
mov  r2, #0x00000000  /* clear                            */ ;r2 <--#0x00000000


clbss_l:str r2, [r0]  /* clear loop...                    */  ;0x00000000 --> _bss_start
add r0, r0, #4         ;r0 <-- r0 + #4
cmp r0, r1          ;r0与r1比较,实际上是进行减运算,但不改其值,只更新标志位
bne clbss_l         ;r0,r1不相等跳转,只到代码段尾,这样所有代码地址就被清0了,难道是为BOOTLOAD 2阶段做准备?

#if 0            ;为假,先不理,继续走
/* try doing this stuff after the relocation */
ldr     r0, =pWTCON
mov     r1, #0x0
str     r1, [r0]

/*
  * mask all IRQs by setting all bits in the INTMR - default
  */
mov r1, #0xffffffff
ldr r0, =INTMR
str r1, [r0]

/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
/* END stuff after relocation */
#endif

ldr pc, _start_armboot        ;pc <-- _start_armboot

_start_armboot: .word start_armboot       ;start_armboot是一个C函数指针,也就是阶段2的入口程序地址。到这里阶段1完成http://www.diybl.com/course/6_sy ... /200876/130696.html


/*
*************************************************************************
*
* CPU_init_critical registers        下面段程序主要设置关键的寄存器,和内存的时序,应该是SDRAM的吧,这里可是算是到了重要的地方了
*
* setup important registers
* setup memory timing
*
*************************************************************************
*/


cpu_init_crit:
/*
  * flush v4 I/D caches                                      刷新缓存,V4的意思是S3C2410内核的架构
  */
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */   ;把ARM寄存器里的r0,写到协处理器p15的c7(c7用于控制缓存)寄存器中,一般为是只写的,读没有意义,其中的两个0,是操作码
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */    ;刷新v4架构的TLB(TLB一般也是只写的),TLB就是内在映射表,MMU才会用得着吧,参考资料http://hi.baidu.com/grqq7/blog/item/6393607fd0b0af0b28388a8d.html
            ;不明白这里为什么写两次,暂且放过
/*
  * disable MMU stuff and caches       ;下面就关于到MMU的设置了
  */
mrc p15, 0, r0, c1, c0, 0       ;把协处理器p15的c1(缓冲类型寄存器)、c0(ID号寄存器)寄存器读到ARM寄存器r0中,
bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)   ;对r0的13、9、8位清0
bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)   ;对r0的7、2、0位清0
orr r0, r0, #0x00000002 @ set bit 1 (A) Align    ;对r0的1位置1(寄存器的最低位为0位)
orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache    ;对r0的12位置1
mcr p15, 0, r0, c1, c0, 0       ;把r0的数据送到c1、c0中,原来ID号是这样写进去的呀,哈哈   


/*
  * before relocating, we have to setup RAM timing
  * because memory timing is board-dependend, you will    ;cpu_init_crit调用快要返回了,不过在返回之前要设置SRAM的操作时序,设置好就可以使用SDRAM了!
  * find a memsetup.S in your board directory.
  */
mov ip, lr          ;先看下先行指令吧,为避免再次调用把lr寄存器的数据给覆盖掉,给于保护,ip寄存器就是一个过程调用中间的一个临时寄存器
bl memsetup         ;跳转到到内存设置程序,bl 是带返回的跳转,对比下本段程序的第一条跳转指令b,好现在看下跑哪里去了,看代码时要注意看注释,就在我们的board/smdk2410下,
mov lr, ip          ;内存设置代码先放一下,回头再把它给贴上来!这里假设内存已经初始化成功,把调用memsetup前保存到lr值恢复

mov pc, lr          ;这里就是把调用cpu_init_crit时的程序指针恢复,这里PC指向bl调用cpu_init_crit的一条指令的地址,到这里现在返回到调用cpu_init_crit


/*
*************************************************************************
*
* Interrupt handling 下面这段代码是中断处理函数,不理它,累人,先把总体流程给搞清楚再说
*
*************************************************************************
*/

@
@ IRQ stack frame.
@
#define S_FRAME_SIZE 72

#define S_OLD_R0 68
#define S_PSR  64
#define S_PC  60

使用特权

评论回复
板凳
dream_east| | 2009-11-18 09:13 | 只看该作者
向楼主学习

使用特权

评论回复
地板
wangkj| | 2009-11-18 13:47 | 只看该作者
支持一个,继续。虽然版本老点。

使用特权

评论回复
5
lelee007| | 2009-11-18 18:36 | 只看该作者
顶一个!

使用特权

评论回复
6
huangqi412| | 2009-11-18 20:34 | 只看该作者
跟着丽丽顶

使用特权

评论回复
7
utterboy| | 2009-11-18 20:35 | 只看该作者
做个记号

使用特权

评论回复
8
8421bcd|  楼主 | 2009-11-18 20:57 | 只看该作者
谢谢你们的支持,谢谢wangjk盖印!

    说下学习嵌入式的感受,其实我从去年就开始学了,还花了N多钱参加培训班,但结果不理想!不是老师讲课不好,是自己基础太差!老师讲课是从应用开始往下讲的,以前要是搞过软件的人听起来应该会比较轻,但自己确听得云里雾里,上课还打瞌睡,晕倒吧,那时候还暗恋一个女孩儿,每次上课都是心不在焉的,就那样的把课给听完了,结束后,脑袋里没有留下什么。还有在学校的时候,也看过这方面的资料,那时候刚学完单片机,感觉嵌入式也没什么的,到参加参加培训,感觉着挺受打击,那时候可能是把它当做一个高端单片机来想了吧,并不知道上面还要跑系统!
     
     差不多过了一年,现在又从头开始,这次分析了自己的特点,因为是电子专业的,又学过单片机,在网上也看到过这样的贴子,就可以从裸机开始起,于是就在网上下载了很多关于裸机的程序,接着自己就试着编译,生成BIN文件,然后下载到板中调试,这试中发现N多问题,程序不运行,甚至发现PC指针一直是减的,后来才明白生成的那些BIN文件都是用JTAG下载到NAND 或 NOR FLASH中才可以运行的,电脑没有并口,这下又开始找调试工具,就买了个JLINK,回来才发现它的驱动里面并没有支持下载到NAND FLASH的配置文件(不过可以调试920T的核),就又郁闷了,在网上寻找方法,找到了一种间接的方法,就是先制作一个CPU初始化文件,包括内存初始化,下载到2410的SRAM中(2410自带4K的SRAM),运行,初始化后再下载BOOTLOADER单内存中,再用网口或者串口通过BOOTLOADER下载到NAND FLASH中,看着挺麻烦的,就试着去修改程序,就让它跑CPU自带的那4K SRAM上,最后终于点亮了一个灯!把我给乐呵的,哈哈,后来就想,不能停在这个层次上,它自带的4K的SRAM也不是太丰富,与是就决定从BOOTLOADER移植开始,一步一步迈向嵌入式!

    BOOTLADER选择了UBOOT,其版本又选择了1.1.2!阳初的板上原本用的BOOTLADER是VIVI,但它是以后的应用有局限性,VIVI好像是针对2410、2440开发出来的吧!而UBOOT支持的体系结构最多了,然后选择1.1.2是在网上看到了阳初移植的UBOOT也是1.1.2的,然后它的整体代码容量只有几M,可以减少些心理负担,代码太多了可不容易消化,不过它们应该都是一脉相成的吧!还有听说新版本的支持的核更多些,也有很多的板级配置文件!

    好了,现在开始看memsetup,对了,VIVI的MEMSETUP和CPU、等初始化程序都在head.s里面

使用特权

评论回复
9
8421bcd|  楼主 | 2009-11-18 22:08 | 只看该作者
内存时序是个挺麻烦问题呢,找了个文档,大家一起来看看!

使用特权

评论回复
10
8421bcd|  楼主 | 2009-11-18 22:14 | 只看该作者
内存时序是个挺麻烦问题呢,找了个文档,大家一起来看看!

高手进阶,终极内存技术指南——完整.pdf

1.54 MB

使用特权

评论回复
11
8421bcd|  楼主 | 2009-11-19 00:27 | 只看该作者
本帖最后由 8421bcd 于 2009-11-19 00:28 编辑

/*
* Memory Setup stuff - taken from blob memsetup.S
*
* Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and
*                     Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
*
* Modified for the Samsung SMDK2410 by
* (C) Copyright 2002
* David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/

#include <config.h>                                  ;现在开始分析内存初化,它用到两头文件,version在include目录下,config.h在include/linux下
#include <version.h>         ;总线一般分为数据总线、地址总线、时钟总线,也就是说内存工作需要这些东西
           ;下面涉及到内存的时序,则可以通过内存芯片的DATASHEET来对就下面的宏定义就行修改
           ;FLASH的地址为0x00000000-0x08000000,SDRAM的地址为0x30000000-0x3800000000
/* some parameters for the board */   板子的一些参数
/*
*
* Taken from linux/arch/arm/boot/compressed/head-s3c2410.S     
*
* Copyright (C) 2002 Samsung Electronics SW.LEE  <hitchcar@sec.samsung.com>
*
*/
#define BWSCON 0x48000000    ;定义一个总线宽度、等待控制寄存器,参DATASHEET 0x48000000就是这个寄存器的地址
/* BWSCON */
#define DW8    (0x0)    ;以后它应该标识8位的数据宽度,再对BWSCON设置的时候用到
#define DW16    (0x1)    ;16位
#define DW32    (0x2)    ;32位
#define WAIT    (0x1<<2)   ;等待控制
#define UBLB    (0x1<<3)   ;?
#define B1_BWSCON    (DW32)    ;进一步描述,以后用的时候更直观些,也是分别定义7个BAKN控制器
#define B2_BWSCON    (DW16)   
#define B3_BWSCON    (DW16 + WAIT + UBLB)  ;
#define B4_BWSCON    (DW16)    ?
#define B5_BWSCON    (DW16)
#define B6_BWSCON    (DW32)
#define B7_BWSCON    (DW32)
/* BANK0CON */      ;现在的东西就是对8个BANK的时序进行设置,具体参考内存芯片手册
#define B0_Tacs    0x0 /*  0clk */
#define B0_Tcos    0x0 /*  0clk */
#define B0_Tacc    0x7 /* 14clk */
#define B0_Tcoh    0x0 /*  0clk */
#define B0_Tah    0x0 /*  0clk */
#define B0_Tacp    0x0
#define B0_PMC    0x0 /* normal */
/* BANK1CON */
#define B1_Tacs    0x0 /*  0clk */
#define B1_Tcos    0x0 /*  0clk */
#define B1_Tacc    0x7 /* 14clk */
#define B1_Tcoh    0x0 /*  0clk */
#define B1_Tah    0x0 /*  0clk */
#define B1_Tacp    0x0
#define B1_PMC    0x0
#define B2_Tacs    0x0
#define B2_Tcos    0x0
#define B2_Tacc    0x7
#define B2_Tcoh    0x0
#define B2_Tah    0x0
#define B2_Tacp    0x0
#define B2_PMC    0x0
#define B3_Tacs    0x0 /*  0clk */
#define B3_Tcos    0x3 /*  4clk */
#define B3_Tacc    0x7 /* 14clk */
#define B3_Tcoh    0x1 /*  1clk */
#define B3_Tah    0x0 /*  0clk */
#define B3_Tacp    0x3     /*  6clk */
#define B3_PMC    0x0 /* normal */
#define B4_Tacs    0x0 /*  0clk */
#define B4_Tcos    0x0 /*  0clk */
#define B4_Tacc    0x7 /* 14clk */
#define B4_Tcoh    0x0 /*  0clk */
#define B4_Tah    0x0 /*  0clk */
#define B4_Tacp    0x0
#define B4_PMC    0x0 /* normal */
#define B5_Tacs    0x0 /*  0clk */
#define B5_Tcos    0x0 /*  0clk */
#define B5_Tacc    0x7 /* 14clk */
#define B5_Tcoh    0x0 /*  0clk */
#define B5_Tah    0x0 /*  0clk */
#define B5_Tacp    0x0
#define B5_PMC    0x0 /* normal */
#define B6_MT    0x3 /* SDRAM */     ;对SDRAM也就是说的内在设置
#define B6_Trcd     0x1
#define B6_SCAN    0x1 /* 9bit */
#define B7_MT    0x3 /* SDRAM */
#define B7_Trcd    0x1 /* 3clk */
#define B7_SCAN    0x1 /* 9bit */
/* REFRESH parameter */        ;下面为程序刷新控制器的配置,具体配置根据内存手册来
#define REFEN    0x1 /* Refresh enable */
#define TREFMD    0x0 /* CBR(CAS before RAS)/Auto refresh */
#define Trp    0x0 /* 2clk */
#define Trc    0x3 /* 7clk */
#define Tchr    0x2 /* 3clk */
#define REFCNT    1113 /* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */
/**************************************/
_TEXT_BASE:
.word TEXT_BASE
.globl memsetup
memsetup:
/* memory control configuration */      ;参考资料http://blog.chinaunix.net/u3/104787/showart_2089407.html
/* make r0 relative the current location so that it */          ;http://blog.chinaunix.net/u1/58780/showart_459188.html
/* reads SMRDATA out of FLASH rather than memory ! */   ;http://hi.baidu.com/caicry/blog/ ... 7107eafc6f7c3ce79bc
ldr     r0, =SMRDATA        ;在FLASH中内存控制器的开始数据,一共有13个内存控制器,SMRDATA是编译链接的时候生成
ldr r1, _TEXT_BASE       ;这个值也就是start.S的值,看资料说,当程序在FLASH程序中的时候为0,内存中的时候为0x33f80000之后,看了链接文件就应该知道了,先过去
sub r0, r0, r1        ;相减后r0还是为SMRDATA的首地址
ldr r1, =BWSCON /* Bus Width Status Controller */   ;加载第一个内在控制器的首地址
add     r2, r0, #13*4       ;计算出内存控制寄存器的末地址,并存到r2
0:
ldr     r3, [r0], #4        ;从FLASH中加载第一个内存控制寄存器的数据,存完同时 r0 <-- r0 + 4 ,以后以次类推
str     r3, [r1], #4        ;存放到第一个寄存器的地址,完成的同时 r1 <-- r1 + 4 ,以后以次类推
cmp     r2, r0        ;比较r2、r0
bne     0b         ;不相等则向上转到标号为0的地址执行,b的意思是向上跳转
/* everything is fine now */
mov pc, lr         ;程序返回到start.S中
.ltorg
/* the literal pools origin */
SMRDATA:          ;下面的就是配置各内存控制寄存器的值了http://6xudonghai.blog.163.com/blog/static/3364062920097324411969/
    .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
    .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
    .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
    .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
    .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
    .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
    .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
    .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
    .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
    .word 0x32
    .word 0x30
    .word 0x30

memsetup.rar

2.93 KB

使用特权

评论回复
12
8421bcd|  楼主 | 2009-11-19 01:10 | 只看该作者
本帖最后由 8421bcd 于 2009-11-20 21:02 编辑

贴两个图上来,描述第一阶段的流程,和整个系统存储空间的分配情况!看代码的时候最好能够对照着这个看会好些,不容易迷,更容易理解代码的原理!接着继续第二阶段,进入到C代码!

09111901109539e09bdc0d96dd.png (57.75 KB )

09111901109539e09bdc0d96dd.png

系统存储空间分配图.jpg (38.71 KB )

系统存储空间分配图.jpg

使用特权

评论回复
13
wangkj| | 2009-11-19 08:28 | 只看该作者
内存时序不用管太多。
只要设置好ras,cas,bank位宽。就好了。
其他都是硬件逻辑操作。

使用特权

评论回复
14
tingtang| | 2009-11-19 10:33 | 只看该作者
好哦哦哦哦哦

使用特权

评论回复
15
cwei8545| | 2009-11-19 12:14 | 只看该作者
最近正在看,学习下

使用特权

评论回复
16
jweiok| | 2009-11-19 12:44 | 只看该作者
我顶你个肺~

使用特权

评论回复
17
因特网用户| | 2009-11-19 13:16 | 只看该作者
mark

使用特权

评论回复
18
itelectron| | 2009-11-19 16:29 | 只看该作者
偶有一个问题 困绕 很久 了
在这里 请教LZ
就是

在steppingstone中 把stage1 stage2都 复制到 RAM 起始地址 0X30000000:后


肯定是要跳到stage2中的 但是steppingstone 结尾 如何
获取RAM中的 stage2 中的MAIN()的 地址:

使用特权

评论回复
19
8421bcd|  楼主 | 2009-11-19 16:38 | 只看该作者
ldr pc, _start_armboot        ;pc <-- _start_armboot   

_start_armboot: .word start_armboot       ;start_armboot是一个C函数指针,也就是阶段2的入口程序地址。到这里阶段1完成http://www.diybl.com/course/6_sy ... /200876/130696.html
start_armboot在lib_arm/board.c中,它的地址应该是在链接的时候生成吧!
第二部分刚开始看!还没弄太明白``

使用特权

评论回复
20
itelectron| | 2009-11-19 18:32 | 只看该作者
你 说的哪个  我也看过
但是 MAIN()的 地址 是 编译器给定的么?
在NAND中  是前4K  COPY UBOOT到RAM中 所以 地址发生了改变
网上说 是 拷贝完 stage1 stage2 后  
在把NAND 的stage1 和  RAM里的stage1 比较下如果相同
然后在从 前4K  的 地方直接 跳到RAM  stage2 里的MAIN()
那么 肯定要知道RAM 里MAIN()的地址啊!!!!!!!!!!!!
我感觉是 MAIN()的地址=0x30000000+stage1:
但是我没有验证过.......

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

19

主题

123

帖子

0

粉丝