Chinaunix首页 | 论坛 | 博客
  • 博客访问: 57918
  • 博文数量: 11
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 140
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-09 15:19
文章分类
文章存档

2017年(2)

2011年(1)

2010年(1)

2009年(7)

我的朋友

分类:

2009-01-10 23:39:21

先来看看从NAND读取RedBoot到SDRAM的代码:
 

#ifdef CYG_HAL_STARTUP_NAND
                // reset NAND
                mov     r1, #NAND_CTL_BASE
                ldr     r2, =0xf830          // initial value
                str     r2, [r1, #oNFCONF]
                ldr     r2, [r1, #oNFCONF]
                bic     r2, r2, #0x800       // enable chip
                str     r2, [r1, #oNFCONF]
                mov     r2, #0xff            // RESET command
                strb    r2, [r1, #oNFCMD]
                mov     r3, #0               // wait
1:              add     r3, r3, #0x1
                cmp     r3, #0xa
                blt     1b
2:              ldr     r2, [r1, #oNFSTAT]       // wait ready
                tst     r2, #0x1
                beq     2b
                ldr     r2, [r1, #oNFCONF]
                orr     r2, r2, #0x800           // disable chip
                str     r2, [r1, #oNFCONF]
                    
                // copy redboot to RAM                            
                // Set up a stack [for calling C code]
                ldr     r1,=__startup_stack
                ldr     r2,=LEO2410_SDRAM_PHYS_BASE
                orr     sp,r1,r2
        
                ldr     r2, =__rom_data_end
                ldr     r0, =__exception_handlers                
                sub     r2,r2,r0
                ldr     r0,=__exception_handlers
                ldr     r1,=LEO2410_SDRAM_PHYS_BASE
                orr     r0,r0,r1
                mov     r1,#0x0                
                bl      nand_read_ll        
                teq     r0, #0x0
                beq     ok_nand_read            
1:              b       1b        // infinite loop
            
ok_nand_read:        
                // verify            
                mov     r0, #0
                ldr     r1, =__exception_handlers
                ldr     r2, =LEO2410_SDRAM_PHYS_BASE
                orr     r1,r1,r2
                mov     r2, #0x400      // 4 bytes * 1024 = 4K-bytes
go_next:
                ldr     r3, [r0], #4
                ldr     r4, [r1], #4
                teq     r3, r4
                bne     notmatch
                subs    r2, r2, #4
                beq     done_nand_read    
                bne     go_next
notmatch:
1:              b       1b        
done_nand_read:     
                // jump to ram
                ldr     r1,=on_the_ram
                ldr     r2,=LEO2410_SDRAM_PHYS_BASE
                add     pc,r1,r2
                nop
                nop
1:              b       1b         // infinite loop
on_the_ram:         
#endif /* CYG_HAL_STARTUP_NAND */

这一段代码其实并不复杂,主要做了三个方面的事情。第一:初始化S3C2410的NAND控制器,以便用于读取NAND中的RedBoot代码;第二:初始化C函数调用堆栈地址,设置好NAND读取函数的入口参数并调用该函数;第三:将读取到SDRAM的RedBoot代码段的前4k和位于SRAM中的代码进行比较,确定读取过程是正确的,然后将PC跳转到SDRAM的相应位置进行执行!

仔细分析了代码,实在没有看到什么地方有问题。比较了s3c2410的文档,NAND控制器的设置也没有错误,SDRAM地址和NAND地址参数的设置也没有错(其中LEO2410_SDRAM_PHY_BASE的值为0x30000000,这是因为SDRAM是使用的BANK6、7)。但是为什么会无法启动呢?(另外,在这里出现的LEO2410_SDRAM_PHY_BASE,实际上对应于SMDK2410模板应该是SMDK2410_SDRAM_PHY_BASE,只是我在移植时新建了一个叫leo2410的模板,从而改的新名字,呵呵)

没有办法,只好step in了。一开始还真不知道该怎么来调试,是不是需要去弄个ICE来,那可要投资一大笔了...。突然想起不是有JTAG线吗,摸索了一下直接使用AxD+H-JTAG就可以完成调试了,呵呵!在网上找了一下,对于阳初的开发板,H-JTAG的设置为:

 TMS  Pin4  D2
 TCK  Pin2  D0
 TDI  Pin3  D1
 TDO  Pin11 Busy
 nTRST  NO TAP RST
 nSRST  NO SYS RST
连上开发板,直接将PC的值设置为0,就可以单步调试了。跟踪到bl nand_read_ll,单步执行就发现程序跑掉了,全是乱指令。问题就在这里,但是为什么会这样呢?其实非常简单,突然间想起了现在的执行过程是在SRAM中进行的,而SRAM只拷贝了4K的代码,而非常不幸的是nand_read_ll函数并没有在这4k代码中。
这太让人头痛了,如何让nand_read_ll进入到前4k代码呢?想过直接将nand_read_ll函数写成汇编的宏放进hal_platform_setup.h中,不过把这段代码写成汇编也比较麻烦,而且不是很符合这样的结构。没有办法,只好研究一下RedBoot的编译过程,查看Makefile了。eCos的目录结构也比较繁杂,而且每个模块下几乎都有一个Makefile,一层层的看太费力了,所以比较方便的办法是直接对configurtool中打印出来的Make信息进行分析。
根据分析结果,RedBoot的链接顺序是:Vectors.o、extras.o、libtarget.a...等,Vectors.o是直接由Vectors.S编译来的,而extras.o是最靠前的目标文件,它是由libextras.a生成的。显然,将nand_read_ll放到extras.o库中是最合理和可靠的。研究了libextras.a的编译顺序,发现合并是放到最前面的是ConfigureTool中选项RedBoot for ARM Option下面的配置项所对应的c文件,如redboot_linux_exec.c文件。于是就想到将nand_read_ll函数的实现所在的c文件(nand_read.c)设置到该选项下面,这样应该就可以保证其位置处于4k代码之内了!说干就干,在hal\arm\arch\current\cdl\hal_arm.cdl中加入以下脚本:
 

cdl_option CYGPKG_REDBOOT_NAND_READ {
    display      "Provide the nand flash device read command"
    flavor       bool
    calculated   {CYG_HAL_STARTUP == "NAND" ? 1:0}
    description  "
                 This option contains the code which impliment the command for nand flash reading. It is useful to boot redboot from nand device. The option is enabled/disabled from RedBoots CDL."

    compile -library=libextras.a nand_read.c
    }

这一段脚本直接加到cdl_component CYGPKG_REDBOOT_ARM_OPTIONS脚本的里面,放到cdl_component CYGPKG_REDBOOT_ARM_LINUX_EXEC之前,就可以让编译链接时nand_read.c被编译到extras.o的最前面。

弄好之后,重新编译,下载...重启...太爽了,接上串口,终于看到了RedBoot的启动信息,以及RedBoot>的提示符,至此,终于实现了从NAND启动RedBoot的任务,终于迎来了对RedBoot的第一次感性认识。接下来的工作,就是一步一步的加入各个器件的驱动以及用RedBoot启动eCos或者linux了。

 

阅读(2337) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2011-01-12 21:49:09

请问作者,你的内存布局文件有没有添加或者改动,我做到这里redboot还是起不来。我发现这个模板没有nand对应的内存布局文件的定义,是不是问题出在这里。