Boot 1.3.4到GT2440(第二版2.0)(3)

三、       UBOOT移植

1、注意问题

了解了大概uboot的运行过程,现在开始移植,移植前,说明几个问题

由于uboot-1.3.4较于较早的版本,就是Makefile有一定的变化,使得对于24x0处理器从nand启动会有问题,就是有人说的无法运行过lowlevel_init。这个问题产生的原因是因为编译器将笔者自己添加的用于nandboot的子函数放到了4K之后(为什么说是4K,uboot从nand启动原理,前面说过),解决办法:

1、顶层Makefile文件中:

#__LIBS := $(subst $(obj),,$(LIBS)) $(subst$(obj),,$(LIBBOARD))
__LIBS := $(subst $(obj),,$(LIBBOARD)) $(subst $(obj),,$(LIBS))
这样修改之后查看map文件可以发现,lowlevel_init函数链接到了前面.
2、在不修改Makefile的情况下,可以通过修改目标板下的链接文件u-boot.lds来使lowlevel_init放在4K之内: cpu/arm920t/start.o (.text)board/net2410e/lowlevel_init.o (.text) 把之放到start.o的后面.
这相当于修改链接脚本,未做验证,笔者使用第一种方法!

3、 开始移植/*其中,蓝色为修改内容,红色为添加内容,参考《移植u-boot-1.3.4到s3c2440》*/

下载源码,网址:

U-Boot软件包下载网站:

1)     解压uboot

#tar –xjvf u-boot-1.3.4.tar.gz2

2)     修改Makefile

#cd u-boot-1.3.4

#vi Makefile或者直接在图形界面打开Makefile,可能这种方法更好用

修改内容如下:

__LIBS := $(subst$(obj),,$(LIBS)) $(subst $(obj),,$(LIBBOARD))

改为:

__LIBS := $(subst $(obj),,$(LIBBOARD)) $(subst$(obj),,$(LIBS))

添加开发板信息

       sbc2410x_config: unconfig @$(MKCONFIG)$(@:_config=) arm arm920t sbc2410x NULL s3c24x0

gt2440_config : unconfig @$(MKCONFIG) $(@:_config=) armarm920t  gt2440  NULL  s3c24x0

/*

各项的意思如下:

       gt2440_config : 这个名字是将来你配置板子时候用到的名字,参见make gt2440_config命令。

arm: CPU的架构(ARCH)

arm920t: CPU的类型(CPU),其对应于cpu/arm920t子目录。

gt2440: 开发板的型号(BOARD),对应于board/ gt2440目录。

NULL: 开发者/或经销商(vender)。s3c24x0: 片上系统(SOC)。

*/

 

3)     在/board/下建立自己的开发板目录

由于笔者开发者那填了NULL,所以直接创建,如果有填,则要再建一个子目录,因为笔者是以sbc2410x这板为基础移植的,所以还要将它的内容复制到开发板文件夹上。

[root@localhost u-boot-1.3.4]#mkdir /board/gt2440

[root@localhost u-boot-1.3.4]#cp –arfsbc2410x/* gt2440/

[root@localhost u-boot-1.3.4]#cd gt2440

[root@localhost u-boot-1.3.4]#mv sbc2410x.cgt2440.c

[root@localhost u-boot-1.3.4]#ls可以看到下面这些文件

       config.mk flash.c  lowlevel_init.s     Makefile        GT2440.c u-boot.lds

[root@localhost u-boot-1.3.4]#vi Makefile

COBJS:= gt2440.o flash.o

4)     在include/configs/中建立开发板所需要的配置头文件

[root@localhost u-boot-1.3.4]#cp../../include/configs/sbc2410x.h ../../include/configs/gt2440.h

5)     测试交叉编译能否成功

这里提醒一下,移植uboot是需要交叉编译有浮点运算功能的,安装arm-linux时,应该选用有浮点运算的,而不是最新的,因为最新的未必是最好的,uboot也是一样,新的只是移植简单了,对于交叉编译工具,笔者选用的是arm-linux-gcc-3.4.1

安装步骤:限于篇幅,详情可看笔者的一篇日志

(1)     配置

[root@localhost u-boot-1.3.4]#makegt2440_config

Configure for gt2440 board

(2)     测试编译

[root@localhost u-boot-1.3.4]#make

编译信息最后两行

arm-linux-objcopy --gap-fill=0xff -O srec u-bootu-boot.srec

arm-linux-objcopy --gap-fill=0xff -O binaryu-boot u-boot.bin

 

6)    开始针对自己的开发板移植

1.    修改/cpu/arm920t/start.S

1.1 修改寄存器地址定义

#ifdefined(CONFIG_S3C2400)||defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)

/*turn offthe watchdog*/

#if defined(CONFIG_S3C2400)
# define pWTCON        0x15300000
# define INTMSK       0x14400008    /* Interupt-Controller base addresses */
# define CLKDIVN    0x14800014    /* clockdivisor register */
#else

# define pWTCON        0x53000000   /*该地址用来屏蔽看门狗*/
# define INTMSK       0x4A000008    /* Interupt-Controller base addresses 该地址用来屏蔽中断*/
# define INTSUBMSK    0x4A00001C   /*该地址用来屏蔽子中断*/
# define CLKDIVN    0x4C000014    /* clockdivisor register 该地址用来决定FCLK、HCLK、PCLK的比例*/

#define CLK_CTL_BASE       0x4c000000  /* 从S3C2440A.pdf中可以看出该寄存器是存放Mpll和Upll的P254 */
#if defined(CONFIG_S3C2440)     

#define MDIV_405      0x7f << 12   /*  参见P255表,同时要知道本开发板的Fin是12MHz,需要的Fclk(也就是Mpll)是405MHz*/
#define PSDIV_405      0x21       /* 同上,同时设定PDIV和SDIV的值,PDIV和SDIV参见S3C2440A.pdf*/
#endif
#endif

 

1.2 修改中断禁止部分

  # ifdefined(CONFIG_S3C2410)

//ldr       r1,0x3ff
  ldr    r1, =0x7ff   //根据2410芯片手册,INTSUBMSK有11位可用,
                      //vivi也是0x7ff,不知为什么U-Boot一直没改过来。但是由于芯片复位默认

//所有的终端都是被屏蔽的,所以这个不影响工

 ldr    r0,=INTSUBMSK
 str    r1, [r0]
# endif
# if defined(CONFIG_S3C2440)
    ldr    r1, =0x7fff   //根据2440芯片手册,INTSUBMSK有15位可用
   ldr    r0, =INTSUBMSK
    str    r1, [r0]
# endif

 

1.3 修改时钟设置

/*时钟控制逻辑单元能够产生s3c2440需要的时钟信号,包括CPU使用的主频FCLK,AHB总线使用的HCLK,APB总线设备使用的PCLK,2440里面的两个锁相环(PLL),其中一个对应FCLK、HCLK、PCLK,另外一个对应UCLK(48MHz)*/

/* FCLK:HCLK:PCLK = 1:4:8 */
    ldr    r0, =CLKDIVN
    mov    r1, #5
    str    r1, [r0]
/*协处理器操作

CP15 —系统控制协处理器 (the system control coprocessor)他通过协处理器指令MCR和MRC提供具体的寄存器来配置和控制caches、MMU、保护系统、配置时钟模式(在bootloader时钟初始化用到),详情可看《ARM体系结构与编程》或者笔者的一个浅谈,也是参考那本书的

*/

       mcr p15,0,r1,c1,c0,0          /*读协处理器p15  c1寄存器的值到r1*/

       orr  r1,r1,#0xc0000000

       mcr p15,0,r1,c1,c0,0          /*把r1的内容写到c1中去,禁止MMU、禁止地址对齐检查功能、禁止caches、禁止写入缓冲、异常中断处理程序进入32位地址模式、禁止26位地址异常检查、选择时期中止模型、选择little-endian。。。。。。详情可以看《ARM体系结构与编程》的5.2节*/

       #ifdefined(CONFIG_S3C2440)

       /*now, CPU clock is 405.00 Mhz   qljt*/

mov    r1, #CLK_CTL_BASE   
mov    r2, #MDIV_405                 /* mpll_405mhz */
add   r2, r2, #PSDIV_405            /* mpll_405mhz */
str   r2, [r1,#0x04]               /* MPLLCON实际上是设置寄存器CLK_CTL_BASE+0x04=0x4c000004的值 */
#endif
#endif    /*CONFIG_S3C2400 || CONFIG_S3C2410|| CONFIG_S3C2440 */

 

1.4 将Flash启动改成从NANDFlash启动(这里网上还有一个小程序,是判别现在是nor还是nand启动的,原理可参考

其实就是利用start.S里的魔方数以及nand和nor的写特性,然后可以同时烧进nor和nand中,主要区别在于,nor可以直接运��uboot。笔者这里没加)

将u-boot重定向语句段屏蔽

@#if ndef    CONFIG_AT91RM9200

#if  0
#ifndefCONFIG_SKIP_RELOCATE_UBOOT
relocate:               /* relocate U-Boot to RAM       */
    adr    r0, _start       /* r0 <- current position of code   */
    ldr    r1, _TEXT_BASE       /* test if we run from flash or RAM */
    cmp     r0,r1               /* don't reloc during debug         */
    beq     stack_setup

    ldr    r2, _armboot_start
    ldr    r3, _bss_start
    sub    r2, r3, r2       /* r2 <- size ofarmboot            */
    add    r2, r0, r2       /* r2 <- source endaddress         */

copy_loop:
    ldmia    r0!, {r3-r10}       /* copy from source address [r0]    */
    stmia    r1!, {r3-r10}       /* copy to   target address [r1]   */
    cmp    r0, r2           /* until source end addreee[r2]    */
    ble    copy_loop
#endif    /* CONFIG_SKIP_RELOCATE_UBOOT */

#endif/*#if 0*/

#endif  /*CONFIG_AT91RM9200 */

然后添加(参考VIVI):

#ifdef CONFIG_S3C2440_NAND_BOOT  

/*往下四段内容都是针对S3C2440的关于NAND-FLASH的寄存器的设置*/
    mov    r1, #NAND_CTL_BASE          
    ldr    r2, =((7<<12)|(7<<8)|(7<<4)|(0<<0) )       /*总线宽为8

Bit,设定TWRPH1,TWRPH0(nWE高低电平持续时间)*/
    str    r2, [r1, #oNFCONF]           /*这些宏是在include/configs/GT2440.h中被定义的*/
    ldr    r2, [r1, #oNFCONF] 


    ldr    r2, =((1<<4)|(0<<1)|(1<<0) ) @ Active low CE Control
    str    r2, [r1, #oNFCONT]
    ldr    r2, [r1, #oNFCONT]

    ldr    r2, =(0x6)       @ RnB Clear
   str    r2, [r1, #oNFSTAT]
    ldr    r2, [r1, #oNFSTAT]
   
    mov    r2, #0xff       @ RESET command
   strb    r2, [r1, #oNFCMD]
/*delay一段时间*/
  mov r3,#0                  @ wait
nand1:
  add  r3, r3, #0x1
  cmp r3, #0xa
  blt   nand1
/*等待nand-flash的复位完毕信号*/
nand2:
  ldr   r2, [r1, #oNFSTAT]      @ wait ready
 tst    r2, #0x4
  beq  nand2

  ldr   r2, [r1, #oNFCONT]
 orr    r2, r2,#0x2        @ Flash Memory ChipDisable  /*在这里先Display fansh CE先,在C函数中再enable*/

str   r2, [r1, #oNFCONT]                         

/*下面这段用来初始化栈指针sp和帧指针fp,至于它们的定义和作用参考文件夹” 栈指针sp和帧指针fp”里面的内容

记住它们都是与函数调用时候相关的。简单来讲就是子函数被调用以后是通过指针的相对位置来查找调用参数和局部变量的,但是由于sp经常变化,所以需要fp来协助。*/
@ get ready to call C functions (for nand_read())
  ldr   sp,DW_STACK_START       @ setup stack pointer /*sp 是指堆栈指针*/
  mov fp,#0                   @ no previous frame, so fp=0             
@ copy U-Boot toRAM          /*注意:现在是运行在4k 的SRAM里,现在要把nand flash的内容拷贝到SDRAM中!vivi里面应该是有一段是针对gpio的程序,也许使用来debug用的信号灯,这里省略了*/
       /*TEXT_BASE 是uboot自己的入口地址,在u-boot-1.3.4-board/gt2440的config.mk中定义

有趣的是外国人的逆向思维很厉害,它们很灵活地把它放在SDRAM的最后0x80000地方,也就是0x33F80000

*/

ldr   r0, =TEXT_BASE /*r0 : 把u-boot复制到ram的那个位置*/
       mov    r1, #0x0                /*r1 : 从falsh的那个位置开始复制*/
       mov r2, #0x20000                    /*r2 : 复制多大的内容*/
       bl   nand_read_ll             /*跳到执行uboot复制的程序入口,这个函数从哪里来?自己在后面写的,也可以参考vivi的*/
       tst   r0, #0x0                    /*这里特别注意r0的值是指nand_read_ll 执行完以后的返回值,而不是上面ldr  r0, =TEXT_BASE 的值,可以查看uboot反汇编文件,跟踪到nand_read_ll可得mov r0,#0*/      
       beq  ok_nand_read
bad_nand_read:         /*如果读nand_read失败的话,那么死循环*/
loop2:    b    loop2          @ infinite loop
ok_nand_read:
@ verify       

/*下面这段程序的作用就是用开始执行的4Kbytes程序跟笔者复制到SRAM中的uboot的前4K程序进行比较,从而校验,现在运行在SRAM里*/
  mov r0, #0
  ldr   r1, =TEXT_BASE
  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  stack_setup
  bne  go_next

notmatch:
loop3:     b    loop3         @ infinite loop
#endif @ CONFIG_S3C2440_NAND_BOOT 

1.5 跳转到C函数之前,即跳出start.S进入第二阶段之前,加个led控制,点灯大法,具体参照读者的硬件配置

       ble  clbss_l

 

       ldr   pc,_start_armboot

 

#ifdefined(CONFIG_S3C2440)

/*LED1 onu-boot stage 1 is ok!,gt2440.h*/

    mov   r1, #GPIO_CTL_BASE

    add   r1, r1, #oGPIO_B

    ldr   r2,=0x3D57FC

    str   r2, [r1, #oGPIO_CON]

    ldr   r2, =0x7ff

    str   r2, [r1, #oGPIO_UP]

    ldr   r2, =0x7fce

    str   r2, [r1, #oGPIO_DAT]

#endif/*s3c2440*/

 

_start_armboot:  .word start_armboot

1.6在“_start_armboot:    .word start_armboot”后加入

 

#ifdefined(CONFIG_S3C2440_NAND_BOOT)

.align     2            /*四字节对齐*/

DW_STACK_START:.wordSTACK_BASE+STACK_SIZE-4/*这里的STACK_BASE和 STACK_SIZE 将在gt2440.h中定义*/

#endif

2.     修改include/configs/gt2440.h文件,因为参考的s3c2410与s3c2440的nandflash控制器寄存器不同,其他相同的可以不改

/*
 * Nandflash Boot
 */
#define CONFIG_S3C2440_NAND_BOOT 1
#define STACK_BASE    0x33f00000
#define STACK_SIZE    0x8000
/* NAND Flash Controller */
#define NAND_CTL_BASE        0x4E000000
/* Offset */
#define oNFCONF            0x00    /*这些宏是在start.S中被调用的*/
#define oNFCONT            0x04
#define oNFCMD            0x08
#define oNFADDR            0x0c
#define oNFDATA            0x10
#define oNFSTAT            0x20
#define oNFECC            0x2c

/* GPIO */
#define GPIO_CTL_BASE        0x56000000
#define oGPIO_F            0x50
#define oGPIO_CON       0x0   /* R/W,Configures the pins of the port */
#define oGPIO_DAT        0x4    /*R/W,    Data register for port */
#define oGPIO_UP        0x8    /*R/W, Pull-up disable register */
#endif   /* __CONFIG_H */

 

3.     在board/gt2440中加入NAND FLASH读函数文件同(参考的是《GT2440之 U-boot使用及移植详细手册》,可实现不同大小的nand读操作)

/*

 * nand_read.c: Simple NAND read functions forbooting from NAND

 *

 * This is used by cpu/arm920/start.S assemblercode,

 * and the board-specific linker script must makesure this

 * file is linked within the first 4kB of NANDflash.

 *

 * Taken from GPLv2 licensed vivi bootloader,

 * Copyright (C) 2002 MIZI Research, Inc.

 *

 * Author: Hwang, Chideok<hwang@mizi.com>

 * Date : $Date: 2004/02/04 10:37:37 $

 *

 * u-boot integration and bad-block skipping(C) 2006 by OpenMoko, Inc

 * Author: Harald Welte<laforge@openmoko.org>

 */

 

#include<common.h>

#include<linux/mtd/nand.h>

 

 

#define__REGb(x) (*(volatile unsigned char *)(x))

#define__REGw(x) (*(volatile unsigned short *)(x))

#define__REGi(x) (*(volatile unsigned int *)(x))

#defineNF_BASE  0x4e000000

#ifdefined(CONFIG_S3C2410)

#defineNFCONF  __REGi(NF_BASE + 0x0)

#defineNFCMD  __REGb(NF_BASE + 0x4)

 

#defineNFADDR  __REGb(NF_BASE + 0x8)

#defineNFDATA  __REGb(NF_BASE + 0xc)

#defineNFSTAT  __REGb(NF_BASE + 0x10)

#defineNFSTAT_BUSY 1

#definenand_select() (NFCONF &= ~0x800)

#definenand_deselect() (NFCONF |= 0x800)

#definenand_clear_RnB() do {} while (0)

#elifdefined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)

#defineNFCONF  __REGi(NF_BASE + 0x0)

#defineNFCONT  __REGi(NF_BASE + 0x4)

#defineNFCMD  __REGb(NF_BASE + 0x8)

#defineNFADDR  __REGb(NF_BASE + 0xc)

#defineNFDATA  __REGb(NF_BASE + 0x10)

#defineNFDATA16 __REGw(NF_BASE + 0x10)

#defineNFSTAT  __REGb(NF_BASE + 0x20)

#defineNFSTAT_BUSY 1

#definenand_select() (NFCONT &= ~(1 << 1))

#definenand_deselect() (NFCONT |= (1 << 1))

#definenand_clear_RnB() (NFSTAT |= (1 << 2))

#endif

 

static inlinevoid nand_wait(void)

{

 int i;

 

 while (!(NFSTAT & NFSTAT_BUSY))

  for (i=0; i<10; i++);

}

 

structboot_nand_t { /*用来贮存芯片的参数*/

 int page_size;

 int block_size;

 int bad_block_offset;

// unsignedlong size;

};

 

#if 0

#ifdefined(CONFIG_S3C2410) || defined(CONFIG_GT2440)

/*configuration for 2410 with 512byte sized flash */

#defineNAND_PAGE_SIZE  512

#defineBAD_BLOCK_OFFSET 5

#defineNAND_BLOCK_MASK  (NAND_PAGE_SIZE - 1)

#defineNAND_BLOCK_SIZE  0x4000

#else

/*configuration for 2440 with 2048byte sized flash */

#defineNAND_5_ADDR_CYCLE

#defineNAND_PAGE_SIZE  2048

#defineBAD_BLOCK_OFFSET NAND_PAGE_SIZE

#defineNAND_BLOCK_MASK  (NAND_PAGE_SIZE - 1)

#defineNAND_BLOCK_SIZE  (NAND_PAGE_SIZE * 64)

#endif /*defined(CONFIG_S3C2410) || defined(CONFIG_GT2440)*/

 

/* compile timefailure in case of an invalid configuration */

#ifdefined(CONFIG_S3C2410) && (NAND_PAGE_SIZE != 512)

#error"S3C2410 does not support nand page size != 512"

#endif /*defined(CONFIG_S3C2410) && (NAND_PAGE_SIZE != 512)*/

#endif /*IF 0*/

 

static intis_bad_block(struct boot_nand_t * nand, unsigned long i)

{

 unsigned char data;

 unsigned long page_num;

 

 nand_clear_RnB();

/*page_size的不同主要是读的时候写地址不一样,2K的为5次,2次Colmn 3次row address

而512的是1次Colmn和3次row address具体怎么安排,可看芯片手册

还有一些宏,例如NAND_CMD_READ0定义在include/linux/mtd/nand.h里*/

 if (nand->page_size == 512) {

  NFCMD = NAND_CMD_READOOB; /* 0x50 */

  NFADDR = nand->bad_block_offset & 0xf;

  NFADDR = (i >> 9) & 0xff;

  NFADDR = (i >> 17) & 0xff;

  NFADDR = (i >> 25) & 0xff;

 } else if (nand->page_size == 2048) {

  page_num = i >> 11; /* addr / 2048 */

  NFCMD = NAND_CMD_READ0;

  NFADDR = nand->bad_block_offset &0xff;

  NFADDR = (nand->bad_block_offset >>8) & 0xff;

  NFADDR = page_num & 0xff;

  NFADDR = (page_num >> 8) & 0xff;

  NFADDR = (page_num >> 16) & 0xff;

  NFCMD = NAND_CMD_READSTART;

 } else {

  return -1;

 }

 nand_wait();

 data = (NFDATA & 0xff);

 if (data != 0xff)

  return 1;

 

 return 0;

}

 

static intnand_read_page_ll(struct boot_nand_t * nand, unsigned char *buf, unsigned longaddr)

{

 unsigned short *ptr16 = (unsigned short *)buf;

 unsigned int i, page_num;

 

 nand_clear_RnB();

 

 NFCMD = NAND_CMD_READ0;

 

 if (nand->page_size == 512) {

  /* Write Address */

  NFADDR = addr & 0xff;

  NFADDR = (addr >> 9) & 0xff;

  NFADDR = (addr >> 17) & 0xff;

  NFADDR = (addr >> 25) & 0xff;

 } else if (nand->page_size == 2048) {

  page_num = addr >> 11; /* addr / 2048*/

  /* Write Address */

  NFADDR = 0;

  NFADDR = 0;

  NFADDR = page_num & 0xff;

  NFADDR = (page_num >> 8) & 0xff;

  NFADDR = (page_num >> 16) & 0xff;

  NFCMD = NAND_CMD_READSTART; /*0x30*/

 }

 else

 {

  return -1;

 }

 nand_wait();

 

#ifdefined(CONFIG_S3C2410)

 for (i = 0; i < nand->page_size; i++) {

  *buf = (NFDATA & 0xff);    /*8位线宽*/

  buf++;

 }

#elifdefined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)

 for (i = 0; i <(nand->page_size>>1); i++) {

  *ptr16 = NFDATA16; /*16位线宽*/

  ptr16++;

 }

#endif /* defined(CONFIG_S3C2410)*/

 

 return nand->page_size;

}

 

static unsignedshort nand_read_id()

{

 unsigned short res = 0;

 NFCMD = NAND_CMD_READID;

 NFADDR = 0;

 res = NFDATA;

 res = (res << 8) | NFDATA;

 return res;

}

 

extern unsignedint dynpart_size[];

 

/* low levelnand read function */

intnand_read_ll(unsigned char *buf, unsigned long start_addr, int size)

{

 int i, j;

 unsigned short nand_id;

 struct boot_nand_t nand;

 

 /* chip Enable */

 nand_select();

 nand_clear_RnB();

 

 for (i = 0; i < 10; i++)

  ;

 nand_id = nand_read_id();

 if (0) { /* dirty little hack to detect ifnand id is misread */

  unsigned short * nid = (unsigned short*)0x31fffff0;

  *nid = nand_id;

 } 

 

       if (nand_id == 0xec76 ||  /* Samsung K91208 */

           nand_id == 0xad76 ) { /*HynixHY27US08121A*/

  nand.page_size = 512;

  nand.block_size = 16 * 1024;

  nand.bad_block_offset = 5;

 // nand.size = 0x4000000;

 } else if (nand_id == 0xecf1 || /* SamsungK9F1G08U0B */

     nand_id == 0xecda || /* Samsung K9F2G08U0B*/

     nand_id == 0xecd3 ) { /* Samsung K9K8G08*/

  nand.page_size = 2048;

  nand.block_size = 128 * 1024;

  nand.bad_block_offset = nand.page_size;

 // nand.size = 0x8000000;

 } else {

  return -1; // hang

 }

 if ((start_addr & (nand.block_size-1)) ||(size & ((nand.block_size-1))))

  return-1; /* invalid alignment */

 

 for (i=start_addr; i < (start_addr +size);) {

#ifndefCONFIG_S3C2410_NAND_SKIP_BAD /*不检查坏块*/

  if (i & (nand.block_size-1)== 0) {

   if (is_bad_block(&nand, i) ||

       is_bad_block(&nand, i +nand.page_size)) {

    /* Bad block */

    i += nand.block_size;

    size += nand.block_size;

    continue;

   }

  }

#endif

  j = nand_read_page_ll(&nand, buf, i);

  i += j;

  buf += j;

 }

 

 /* chip Disable */

 nand_deselect();

 

 return 0;

}

 

/*===========================================================

到这里,应该是可以编译通过的,否则就是编辑的时候出现了错误

===========================================================*/

4.    修改board/gt2440/lowlevel_init.S文件

由于这个是底层的初始化文件,所以要根据读者的开发板情况来配置或者修改/board/gt2440/lowlevel_init.S文件

/* REFRESH parameter 下面这6个配置都可以参考s3c2440A datasheet P210的REFRESH寄存器 */
#define REFEN            0x1    /* Refresh enable */
#define TREFMD            0x0    /* CBR(CAS before RAS)/Auto refresh */
#define Trp            0x01    /* 3clk 这个值可以参考本版子上的SDRAM的datasheet*/
#defineTrc            0x3    /* 也就是SDRAM datasheet里面的Tsrc 7clk 本来这个地方是Trc,但从lowlevel_init.S里面的调用来看,应该是s3c2440的寄存器REFRESH的Tsrc才对,好多地方都没有改过来,只是个名字而已,不影响结果

注意:如果这里改了,那么下面这句中的Trc也要改为相应的

Tsrc:

.word((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)*/

#define Tchr            0x2    /* 3clk,这个从lowlevel_init.S里面的调用来看是属于REFRESH的保留位,不知道为什么还要给他赋值*/
#defineREFCNT    1259 /*这个值的算法参考s3c2440A datasheet P210的Refresh Counter

Refresh count = 2^11 + 1- HCLK * period  */

 

/*下面不厌其烦地解析一下lowlevel_init.S这个原文件*/

 

#define BWSCON      0x48000000

……

#define Tchr                     0x2 /* 3clk */

#define REFCNT               0x0459

/**************************************/

/*1.要知道上面这些配置的最终会被用到下面SMRDATA 这个数据池里面,所以必须要明白SMRDATA 这个数据池是用

来干什么的,SMRDATA 后面每一个.word 后面放置的数据都是将要写入BWSCON 开始的寄存器的,总共有13个.word ,它们后面放置的值将会分别写入0x48000000、0x48000004、0x48000008…一直到0x48000030共13个寄存器。 */

/*2.上面那些配置的值是怎样决定的呢,详细请参考s3c2440A和你所用SDRAM的datasheet。细心找总是能找到的。*/

/*3.而上面的那些配置值最终是通过下面lowlevel_init后面的这段函数写到寄存器里面的,下面对该段函数逐一分析:*/

_TEXT_BASE:

       .word     TEXT_BASE

 

.globl lowlevel_init

lowlevel_init:

       /* memory controlconfiguration */

       /* make r0 relative thecurrent location so that it */

       /* reads SMRDATA out of FLASHrather than memory ! */

       ldr     r0, =SMRDATA

       ldr   r1, _TEXT_BASE

     sub r0, r0, r1 /*其实明白了前三条语句这段程序就不难懂了,归根到底就是为什么将SMRDATA 的值减去_TEXT_BASE的值?

原因如下:

当笔者编译出uboot的时候,编译器会给uboot这程序定一个初始地址作为基地址,其它就以它为基准,这个地址就是在config.mk里指定的TEXT_BASE,笔者的定为0x33f80000。

笔者使用的是从nandflashboot的方式,目前程序仍然在4K-bytes ‘Steppingstone’(即开始的4K SRAM)上面运行。

现在代码还没有搬运到内存中,什么时候搬?就是下一段代码要做的。所以如果调用这个label的话,找不到数据的,因为那个位置没东西,那数据在哪?在flash中!!那怎么找?其实flash是安排在0x0地址中的,所以真正的数据也是在相对于0x0的位置,那怎么找?就是用你相对于text_base的位置减去text_base的不就可以吗?事实笔者也是这样做的。*/

       ldr   r1, =BWSCON     /* Bus Width StatusController */

       add     r2, r0, #13*4  /*总共13个寄存器*/

0:

       ldr     r3, [r0], #4

       str     r3, [r1], #4

       cmp     r2, r0

       bne     0b

 

       /* everything is fine now */

       mov       pc, lr

 

       .ltorg     /*数据缓冲池,上网可以查得资料*/

/* the literal pools origin */

 

SMRDATA:

   ……  

    .word((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)

    .word 0xb2

    .word 0x30   /*需要注意的是CASLatency的值在这里直接配置*/

.word 0x30

/***********************************************************

到这里,应该是可以编译通过的,否则就是编辑的时候出现了错误

************************************************************/

 

5.    修改board/gt2440/gt2440.c

这个文件主要板级初始化的任务(如:GPIO初始化,lcd、网卡初始化类,PLL),修改的地方主要包括:修改PLL、增加LCD初始化函数(暂时没加)、修改GPIO设置、如果网上不是CS8900还要添加网卡芯片的初始化函数。

这里主要修改GPIO设置和PLL设置

#elif FCLK_SPEED==1 /* Fout =405MHz */

//#define M_MDIV 0x5c

//#define M_PDIV 0x4

//#define M_SDIV 0x0

#define M_MDIV 0x7f

#define M_PDIV 0x2

#define M_SDIV 0x1

#elif USB_CLOCK==1

//#define U_M_MDIV 0x48

//#define U_M_PDIV 0x3

#define U_M_MDIV 0x38

#define U_M_PDIV 0x2

#define U_M_SDIV 0x2

/*对于PLL时钟问题,笔者把参考《ARM79出口-u-boot移植手册》,将UPLLCON的配置和MPLLCON的配置顺序颠倒一下(不颠倒也是可以工作的,但是S3c2440 datasheet文档中明确规定,笔者就按它说的去做吧)*/

/* configure UPLL */

 clk_power->UPLLCON = ((U_M_MDIV <<12) + (U_M_PDIV << 4) +

U_M_SDIV);

 

 /* some delaybetween MPLL and UPLL */

delay(0xffff);

delay(0xffff);

 delay(0xffff);

 

 /*configure MPLL */

 clk_power->MPLLCON = ((M_MDIV << 12

 

 /*some delay between MPLL and UPLL */

   delay(0xffff);

 delay(0xffff);

 delay(0xffff);

......

/* set up the I/O ports */

gpio->GPACON = 0x007FFFFF;

//    gpio->GPBCON = 0x00044556;

gpio->GPBCON =0x3D57FC; /*for LED*/

......

/* arch number of S3C2440-Board */

gd->bd->bi_arch_number = MACH_TYPE_S3C2440;

/* adress of boot parameters */

gd->bd->bi_boot_params =0x30000100;

icache_enable();

dcache_enable();

gpio->GPBDAT = 0x7f8e; /*for LED*/

//int board_init (void)设置完成后,LED1和LED2会亮起!

return 0;

}

这里说明一下,gt2440.c完成的板级初始化函数在哪里调用。其实它是被定义在

init_fnc_t *init_sequence[]

这个初始化函数指针集里的,很熟悉吧?就是在前面介绍流程board.c里面,它从汇编跳到这执行start_armboot()函数,在函数里一一执行。

/*===========================================================

到这里,应该是可以编译通过的,否则就是编辑的时候出现了错误

===========================================================*/

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwzxyg.html