Chinaunix首页 | 论坛 | 博客
  • 博客访问: 192694
  • 博文数量: 71
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 210
  • 用 户 组: 普通用户
  • 注册时间: 2013-01-13 14:49
文章分类
文章存档

2017年(1)

2015年(5)

2014年(10)

2013年(55)

我的朋友

分类: 嵌入式

2013-08-02 18:17:27

u-boot自2010.09版以后有比较大的变化,首先是不再在顶层Makefile中配置板级支持文件,其次是重写了start.S和board.c,还有就是提供了对S3C2440的部分支持,使得在移植时难度减小。但由于是新版本,bug也有不少。本文尝试对u-boot-2011.03进行移植,主要参考了bscbem的日志和L_Backkom的专栏,在此表示感谢。

具体见 与 

U-Boot源代码下载地址 

1.1 移植环境

u-boot版本:u-boot-2011-03
Linux平台: 14
交叉编译工具:arm-linux-gcc-4.3.2
arm开发板:micro2440
        CPU:S3C2440
        SDRAM:64M
        Nor Flash:2M
        Nand Flash:256M
        网卡:DM9000EP

 

1.2 移植目标

支持Nand启动
支持Nand读写
支持yaffs写入
支持tftp下载

 

1.3 删减u-boot文件(可不做)

(1)删除arch目录下除arm目录以外的所有目录
(2)删除arm/cpu目录下除arm920tmulu以外的所有目录
(3)删除arch/arm/cpu/arm920t目录下除s3c24x0目录以外的所有目录(文件不要删)
(4)删除arch/arm/include/asm目录下除arch‐s3c24x0外的所有arch‐xxxx目录(文件不要删)
(5)删除board目录下除samsung目录以外的所有目录
(6)删除board/samsung目录下除smdk2410目录以外的所有目录
(7)删除include/configs目录下除smdk2410.h文件以外的所有头文件。

 

1.4 建立Micro2440配置

(1)[ u-boot-2011.03]$ vim boards.cfg 
添加一行
micro2440 arm arm920t - samsung s3c24x0
【说明】
我们是基于smdk2410开发板移植,我们仍然将开发板文件建立在board/samsung下

 

(2)创建板级支持文件
[ u-boot-2011.06]$ cp -r board/samsung/smdk2410 board/samsung/micro2440
[ u-boot-2011.06]$ cd board/samsung/micro2440/
[ micro2440]$ mv smdk2410.c micro2440.c
[ micro2440]$ vim Makefile
COBJS := smdk2410.o flash.o改为COBJS := micro2440.o flash.o
[ u-boot-2011.06]$ cd ../../..
[ u-boot-2011.06]$ cp include/configs/smdk2410.h include/configs/micro2440.h
[ u-boot-2011.03]$ vim include/configs/micro2440.h
修改一:
#define CONFIG_SYS_PROMPT "[Micro2440]# " /* Monitor Command Prompt */
修改二:
#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE)

【说明】
如果不定义修改二的内容,编译时就会出错,这是新版本的一个bug。
这里需要注意,直接复制内容到micro2440.h可能导致make通不过,提示有garbage,我想可能是因为windows和Linux回车编码不同造成的。

(3)测试编译环境
[ u-boot-2011.06]$ make micro2440_config
Configuring for micro2440 board...
[ u-boot-2011.06]$ make
Generating include/autoconf.mk
Generating include/autoconf.mk.dep
......
......
arm-linux-objcopy -O srec u-boot u-boot.srec
arm-linux-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin

2.1  include/configs/micro2440.h

删除

#define CONFIG_S3C2410 1 /* specifically a SAMSUNG S3C2410 SoC */

#define CONFIG_SMDK2410 1 /* on a SAMSUNG SMDK2410 Board */

添加
#define CONFIG_S3C2440 1 /* specifically a SAMSUNG S3C2440 SoC */
#define CONFIG_MICRO2440
#define CONFIG_SKIP_LOWLEVEL_INIT

 

【说明】
定义CONFIG_SKIP_LOWLEVEL_INIT是因为我们要在RAM中运行,所以要跳过底层的一些初始化代码

 2.2 arch/arm/cpu/arm920t/start.S

# if defined(CONFIG_S3C2410)
    ldr r1, =0x3ff
    ldr r0, =INTSUBMSK
    str r1, [r0]
# endif

 

# if defined(CONFIG_S3C2440)
# define LOCKTIME 0x4C000000
# define MPLLCON 0x4C000004
# define UPLLCON 0x4C000008

 

# define CLKDIV_VAL 5
# define M_MDIV 0x7f /* XTal=12.0MHz MPLL=405MHz */
# define M_PDIV 2
# define M_SDIV 1
# define U_MDIV 0x38 /* XTal=12.0MHz UPLL=48MHz */
# define U_PDIV 2 
# define U_SDIV 2

 

    ldr r1, =0x7fff
    ldr r0, =INTSUBMSK
    str r1, [r0]

 

    ldr r0,=LOCKTIME /* 设置U_LTIME和M_LTIME */
    ldr r1,=0x0fff0fff
    str r1,[r0]

 

    ldr r0, =CLKDIVN /* Fclk:Hclk:Pclk = 1:4:8 */
    ldr r1, =CLKDIV_VAL
    str r1, [r0]

 

    mrc p15, 0, r0, c1, c0, 0 /* 总线模式设为异步模式 */
    orr r0, r0, #0xc0000000
    mcr p15, 0, r0, c1, c0, 0

 

    ldr r0,=UPLLCON /* 配置UPLL */
    ldr r1,=((U_MDIV<<12) + (U_PDIV<<4) + U_SDIV) 
    str r1,[r0]
    nop /* 为确保硬件完成操作,至少需7个时钟周期 */
    nop
    nop
    nop
    nop
    nop
    nop

    ldr r0,=MPLLCON /* 配置MPLL */
    ldr r1,=((M_MDIV<<12) + (M_PDIV<<4) + M_SDIV)
    str r1,[r0]
#else

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

 

#endif /* CONFIG_S3C24X0 */

 

2.3 board/samsung/micro2440/micro2440.c

#define FCLK_SPEED 2

 

#if FCLK_SPEED==0 /* Fout = 203MHz, Fin = 12MHz for Audio */
#define M_MDIV 0xC3
#define M_PDIV 0x4
#define M_SDIV 0x1
#elif FCLK_SPEED==1 /* Fout = 202.8MHz */
#define M_MDIV 0xA1
#define M_PDIV 0x3
#define M_SDIV 0x1
#elif FCLK_SPEED==2 /* Fout = 405MHz */
#define M_MDIV 0x7F
#define M_PDIV 0x2
#define M_SDIV 0x1

#endif

 

#define USB_CLOCK 2

 

#if USB_CLOCK==0
#define U_M_MDIV 0xA1
#define U_M_PDIV 0x3
#define U_M_SDIV 0x1
#elif USB_CLOCK==1
#define U_M_MDIV 0x48
#define U_M_PDIV 0x3
#define U_M_SDIV 0x2
#elif USB_CLOCK==2 /* Fout = 48MHz */
#define U_M_MDIV 0x38
#define U_M_PDIV 0x2
#define U_M_SDIV 0x2

#endif

 

int board_init (void)
{
     ......
     gd->bd->bi_arch_number = MACH_TYPE_MINI2440;

     ......
}

 

int dram_init (void)
{
     ......
     gd->ram_size = PHYS_SDRAM_1_SIZE; 

     return 0;
}

 

【说明】

我在发布资源时用的是MACH_TYPE_MICRO2440,之前的Linux内核中有MICRO2440的机器码,值为2680,但是最近的内核,比如Linux-2.6.39中并没有这个值,虽然我自己是在Micro2440开发板上移植,但机器码还是使用MACH_TYPE_MINI2440,其值为1999。所以下载了资源的网友一定要注意gd->bd->bi_arch_number 的值。

 2.4 测试

[ u-boot-2011.06]$ make
编译完成后将u-boot.bin下载到SDRAM的0x33f80000地址处,u-boot已经能在RAM中运行。



3.1 include/configs/micro2440.h

删除

#define CONFIG_CS8900  /* we have a CS8900 on-board */
#define CONFIG_CS8900_BASE 0x19000300
#define CONFIG_CS8900_BUS16 /* the Linux driver does accesses as shorts */

 

#define CONFIG_NETMASK          255.255.255.0
#define CONFIG_IPADDR  10.0.0.110
#define CONFIG_SERVERIP  10.0.0.1

添加

#define CONFIG_CMD_NET
#define CONFIG_DRIVER_DM9000    1  
#define CONFIG_DM9000_NO_SROM   1
#define CONFIG_DM9000_BASE      0x20000300
#define DM9000_IO   CONFIG_DM9000_BASE
#define DM9000_DATA  (CONFIG_DM9000_BASE + 4)

#define CONFIG_CMD_PING  
#define CONFIG_ETHADDR   08:00:3e:26:0a:5b  //开发板MAC地址
#define CONFIG_NETMASK   255.255.255.0
#define CONFIG_IPADDR    192.168.10.126      //开发板IP地址
#define CONFIG_SERVERIP  192.168.10.124      //主机IP地址

 

【说明】

IP地址要根据实际情况自己设置, CONFIG_SERVERIP用于制定tftp等下载时的主机IP

 

3.2 board/samsung/micro2440/micro2440.c

int board_eth_init(bd_t *bis)
{
    int rc = 0;
#ifdef CONFIG_CS8900
    rc = cs8900_initialize(0, CONFIG_CS8900_BASE);
#endif

 

#ifdef CONFIG_DRIVER_DM9000
    rc = dm9000_initialize(bis);
#endif

    return rc;
}
#endif

 

【说明】

到此,DM9000已经能初始化了,但是使用ping命令时,串口一直打印 "raise: Signal # 8 caught",下一步直接将该打印语句注释掉,经测试没有影响。

 

3.3 arch/arm/lib/eabi_compat.c

int raise (int signum)
{
#ifndef CONFIG_MICRO2440
        printf("raise: Signal # %d caught/n", signum);
#endif
        return 0;
}

 

【说明】

到这一步后可以ping通,但是总是出现了一个"could not establish link"的提示。按照下一步修改,这样修改的结果是第一次不能ping通,需使用Ctrl+C结束,以后即可ping通并使用tftp下载。

 

3.4 drivers/net/dm9000x.c

static int dm9000_init(struct eth_device *dev, bd_t *bd)
{
    ……
#ifndef CONFIG_MICRO2440
    i = 0;
    while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */
        udelay(1000);
        i++;
       if (i == 10000) {
          printf("could not establish link/n");
          return 0;
       }
    }
#endif
    ……
}


static void dm9000_halt(struct eth_device *netdev)
{
 DM9000_DBG("%s/n", __func__);
#ifndef CONFIG_MICRO2440
    /* RESET devie */
    phy_write(0, 0x8000); /* PHY RESET */
    DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */
    DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */
    DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */
#endif
}
 


4.1 include/conskfigs/micro2440.h

添加

#define CONFIG_SETUP_MEMORY_TAGS    1 //如果没有定义这个参数,则uboot参数必须加入men=内存大小
#define CONFIG_INITRD_TAG            1
#define CONFIG_CMDLINE_TAG           1 //设置bootargs出入内核必须
#define CONFIG_BOOTARGS         "noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0"

【说明】

到此步后,使用bootm后在"Starting kernel ..."地方死机。按照下一步修改,具体原因尚不理解,需要在以后阅读uboot的源代码。

 

4.2 arch/arm/lib/bootm.c

static void announce_and_cleanup(void)
{
        printf("/nStarting kernel .../n/n");

#ifdef CONFIG_USB_DEVICE
        {
                extern void udc_disconnect(void);
                udc_disconnect();
        }
#endif

 

#ifndef CONFIG_MICRO2440
        cleanup_before_linux();
#endif
}

 

4.3 自动启动内核

如果要自动启动内核,需要在include/conskfigs/micro2440.h定义CONFIG_BOOTCOMMAND,类似如下内容:

#define CONFIG_BOOTCOMMAND  "nand read 0x30008000 0x60000 0x300000;bootm 0x30008000"

5.1 添加s3c2440_nand.c

[ u-boot-2011.03]$ touch drivers/mtd/nand/s3c2440_nand.c 
[ u-boot-2011.03]$ cat> drivers/mtd/nand/s3c2440_nand.c

#include

#if 0
#define DEBUGN    printf
#else
#define DEBUGN(x, args ...) {}
#endif

#include
#include
#include

#define __REGb(x)    (*(volatile unsigned char *)(x))
#define __REGi(x)    (*(volatile unsigned int *)(x))

#define NF_BASE  0x4e000000             //Nand配置寄存器基地址
#define NFCONF   __REGi(NF_BASE + 0x0)  //偏移后还是得到配置寄存器基地址
#define NFCONT   __REGi(NF_BASE + 0x4)  //偏移后得到Nand控制寄存器基地址
#define NFCMD    __REGb(NF_BASE + 0x8)  //偏移后得到Nand指令寄存器基地址
#define NFADDR   __REGb(NF_BASE + 0xc)  //偏移后得到Nand地址寄存器基地址
#define NFDATA   __REGb(NF_BASE + 0x10) //偏移后得到Nand数据寄存器基地址
#define NFMECCD0 __REGi(NF_BASE + 0x14) //偏移后得到Nand主数据区域ECC0寄存器基地址
#define NFMECCD1 __REGi(NF_BASE + 0x18) //偏移后得到Nand主数据区域ECC1寄存器基地址
#define NFSECCD  __REGi(NF_BASE + 0x1C) //偏移后得到Nand空闲区域ECC寄存器基地址
#define NFSTAT   __REGb(NF_BASE + 0x20) //偏移后得到Nand状态寄存器基地址
#define NFSTAT0  __REGi(NF_BASE + 0x24) //偏移后得到Nand ECC0状态寄存器基地址
#define NFSTAT1  __REGi(NF_BASE + 0x28) //偏移后得到Nand ECC1状态寄存器基地址
#define NFMECC0  __REGi(NF_BASE + 0x2C) //偏移后得到Nand主数据区域ECC0状态寄存器基地址
#define NFMECC1  __REGi(NF_BASE + 0x30) //偏移后得到Nand主数据区域ECC1状态寄存器基地址
#define NFSECC   __REGi(NF_BASE + 0x34) //偏移后得到Nand空闲区域ECC状态寄存器基地址
#define NFSBLK   __REGi(NF_BASE + 0x38) //偏移后得到Nand块开始地址
#define NFEBLK   __REGi(NF_BASE + 0x3c) //偏移后得到Nand块结束地址

#define S3C2440_NFCONT_nCE  (1<<1)
#define S3C2440_ADDR_NALE   0x0c
#define S3C2440_ADDR_NCLE   0x08

ulong IO_ADDR_W = NF_BASE;

static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
 struct nand_chip *chip = mtd->priv;

 DEBUGN("hwcontrol(): 0x%02x 0x%02x/n", cmd, ctrl);

 if (ctrl & NAND_CTRL_CHANGE)
 {
  IO_ADDR_W = NF_BASE;

  if (!(ctrl & NAND_CLE))                //要写的是地址
   IO_ADDR_W |= S3C2440_ADDR_NALE;
  if (!(ctrl & NAND_ALE))                //要写的是命令
   IO_ADDR_W |= S3C2440_ADDR_NCLE;

  if (ctrl & NAND_NCE) 
   NFCONT &= ~S3C2440_NFCONT_nCE;    //使能nand flash
  else
   NFCONT |= S3C2440_NFCONT_nCE;     //禁止nand flash
 }

 if (cmd != NAND_CMD_NONE)
  writeb(cmd,(void *)IO_ADDR_W);
}

static int s3c2440_dev_ready(struct mtd_info *mtd)
{
 DEBUGN("dev_ready/n");
 return (NFSTAT & 0x01);
}

int board_nand_init(struct nand_chip *nand)
{
 u_int32_t cfg;
 u_int8_t tacls, twrph0, twrph1;
 struct s3c24x0_clock_power * const clk_power = s3c24x0_get_base_clock_power();

 DEBUGN("board_nand_init()/n");

 tacls = 1;

 twrph0 = 2; 

 twrph1 = 1; 

 cfg = (tacls<<12)|(twrph0<<8)|(twrph1<<4);
 NFCONF = cfg;

 cfg = (1<<6)|(1<<4)|(0<<1)|(1<<0);
 NFCONT = cfg;

 /* initialize nand_chip data structure */
 nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e000010;

 /* read_buf and write_buf are default */
 /* read_byte and write_byte are default */

 /* hwcontrol always must be implemented */
 nand->cmd_ctrl = s3c2440_hwcontrol;

 nand->dev_ready = s3c2440_dev_ready;

 return 0;
}

 【说明】

经过几次测试,yaffs2写入不太稳定,修改上面红色部分后,yaffs2写入正常

5.2 drivers/mtd/nand/Makefile

COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o

 

5.3 include/conskfigs/micro2440.h

添加

#define CONFIG_MTD_DEVICE
#define CONFIG_NAND_S3C2440
#define CONFIG_CMD_NAND
#if defined(CONFIG_CMD_NAND)
#define CONFIG_SYS_NAND_BASE            0x4E000000 //Nand配置寄存器基地址
#define CONFIG_SYS_MAX_NAND_DEVICE      1
#define CONFIG_MTD_NAND_VERIFY_WRITE    1

#endif

 

#define CONFIG_ENV_IS_IN_NAND  1
#define CONFIG_ENV_OFFSET      0x40000 //将环境变量保存到nand中的0x40000位置
#define CONFIG_ENV_SIZE        0x10000 /* Total Size of Environment Sector */

6.1 include/conskfigs/micro2440.h

添加
#define CONFIG_CMD_NAND_YAFFS

 

【说明】

本人在阅读cmd_nand.c时发现u-boot-2011.03已经支持yaffs写入,只需添加如上定义即可,但实际写入错误,再阅读源代码,发现只要按下一步修改即可,虽然这是最简单的方法,但似乎并不是最优的方法。

6.2 drivers/mtd/nand/nand_util.c

int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
   u_char *buffer, int withoob)
{
 ……
 if (need_skip < 0) {
  printf ("Attempt to write outside the flash area/n");
  *length = 0;
  return -EINVAL;
 }

 if (!need_skip && !withoob) {
 ……
 }

 while (left_to_write > 0) {
  ……
#ifdef CONFIG_CMD_NAND_YAFFS
  if (withoob) {
   ……
   ops.len = pagesize;
   ops.ooblen = nand->oobsize;
   ops.mode = MTD_OOB_RAW;
   ops.ooboffs = 0;

   pages = write_size / pagesize_oob;
   for (page = 0; page < pages; page++) {
    ops.datbuf = p_buffer;
    ops.oobbuf = ops.datbuf + pagesize;

    rval = nand->write_oob(nand, offset, &ops);
   if (rval)
     break;

    offset += pagesize;
    p_buffer += pagesize_oob;
   }
  }
  ……
}

 

6.3 下载yaffs镜像

下载yaffs镜像的时候要注意分区的第一块不能写,比如友善之臂的默认分区如下:

Number of partitions: 4
name            :       offset          size            flag
------------------------------------------------------------
vivi            :       0x00000000      0x00040000      0
param           :       0x00040000      0x00020000      0
kernel          :       0x00060000      0x00500000      0
root            :       0x00560000      0x3fa80000      0

也就是说yaffs镜像所在分区的起始地址在0x560000,因此使用nand write.yaffs命令下载yaffs时要写的地址为0x560000 + 0x20000 (Nand Flash每块的大小)= 0x580000,即下载命令类似如下

tftp 0x30008000 uImage

nand write.yaffs 0x30008000 0x580000 0x300000

7.1 创建nand_read.c

【注意】
本程序只能用于读取2K/页的Nand。本人的Micro2440上的Nand Flash为256M,型号为K9F2G08

 

[ u-boot-2011.06]$ touch board/samsung/micro2440/nand_read.c
[ u-boot-2011.06]$ cat> board/samsung/micro2440/nand_read.c

 

#define rNFCONF  (*(volatile unsigned *)0x4E000000)
#define rNFCONT  (*(volatile unsigned *)0x4E000004)
#define rNFCMD  (*(volatile unsigned *)0x4E000008)
#define rNFADDR  (*(volatile unsigned *)0x4E00000C)
#define rNFDATA8 (*(volatile unsigned char*)0x4E000010)
#define rNFSTAT  (*(volatile unsigned *)0x4E000020)

#define CMD_READ1   0x00            /* 页读命令周期1 */
#define CMD_READ2   0x30            /* 页读命令周期2 */
#define CMD_RESET   0xFF          /* 复位    */

#define NF_CMD(cmd)   {rNFCMD=(cmd);}     /* 写命令   */
#define NF_ADDR(addr)  {rNFADDR=(addr);}    /* 写地址   */
#define NF_RDDATA8()  (rNFDATA8)         /* 读8位数据  */
#define NF_nFCE_L()   {rNFCONT&=~(1<<1);}    /* 片选使能   */
#define NF_nFCE_H()   {rNFCONT|=(1<<1);}    /* 片选禁用   */
#define NF_WAITRB()      {while(!(rNFSTAT&(1<<1)));}  /* 等待就绪   */
#define NF_CLEAR_RB()     {rNFSTAT |= (1<<2);}   /* 清除就绪/忙位 */
#define NF_DETECT_RB()     {while(!(rNFSTAT&(1<<2)));}  /* 等待就绪   */

#define TACLS  1
#define TWRPH0  2
#define TWRPH1  1

void delay(int i)
{
 while(i-->0);
}

void Nand_Init(void)
{
 rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0); 
 rNFCONT = (1<<4)|(1<<1)|(1<<0);
}

static void Nand_Reset(void)
{
 NF_nFCE_L();      /* 片选使能   */
 NF_CLEAR_RB();      /* 清除就绪/忙位  */
 NF_CMD(CMD_RESET);     /* 写复位命令  */
 NF_DETECT_RB();      /* 等待就绪   */
 NF_nFCE_H();      /* 片选禁用   */
}

unsigned char Nand_ReadPage(const int page, unsigned char * const buffer)
{
 int i;
 
 Nand_Reset();
 
 NF_nFCE_L();
 NF_CLEAR_RB();

 NF_CMD(CMD_READ1); 
 NF_ADDR(0x0);
 NF_ADDR(0x0);
 NF_ADDR(page&0xff);
 NF_ADDR((page>>8)&0xff);
 NF_ADDR((page>>16)&0xff);
 NF_CMD(CMD_READ2); 
   
 NF_DETECT_RB();

 for (i = 0; i < 2048; i++) 
 {
  buffer[i] =  NF_RDDATA8();
 }
 
 NF_nFCE_H();
}

int nand_read(int start_page, int read_pages, unsigned char *buffer)
{
 int i;

 Nand_Init();
 for(i=0; i  {
  Nand_ReadPage(start_page, buffer + 2048*i);
  start_page++;
 }
 return 0;
}

 

7.2 board/samsung/micro2440/Makefile

COBJS := micro2440.o flash.o nand_read.o

 

7.3 arch/arm/cpu/arm920t/u-boot.lds

 .text :
 {
  arch/arm/cpu/arm920t/start.o (.text)
  board/samsung/micro2440/libmicro2440.o    (.text)
  *(.text)
 }

 

【说明】

如果是在RAM中运行,一定要删去board/samsung/micro2440/libmicro2440.o    (.text),否则在RAM中也不能运行。原因尚不理解,需要阅读代码。

 

7.4 arch/arm/cpu/arm920t/start.S

下面红色部分是添加的部分,黑色的代码用于定位。

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    bl cpu_init_crit
#endif

 

#ifdef CONFIG_S3C2440_NAND_BOOT 
    ldr sp, =0x30008000 
    ldr r0, =0x0; 
    ldr r1, _end_ofs 
    mov r1, r1, LSR #11 
    add r1, r1, #1 
    ldr r2, =(CONFIG_SYS_TEXT_BASE) 
    bl nand_read 
    ldr pc, =relocations 
#endif

......
......
copy_loop: 
ldmia r0!, {r9-r10} /* copy from source address [r0] */ 
stmia r1!, {r9-r10} /* copy to target address [r1] */ 
cmp r0, r2 /* until source end address [r2] */ 
blo copy_loop 

#ifdef CONFIG_S3C2440_NAND_BOOT 
relocations: 
    ldr r6, =CONFIG_SYS_TEXT_BASE 
#endif
 

#ifndef CONFIG_PRELOADER 
/* 
* fix .rel.dyn relocations 
*/
......
......
clbss_l:str r2, [r0] /* clear loop... */ 
add r0, r0, #4 
cmp r0, r1 
bne clbss_l 

bl coloured_LED_init 
bl red_LED_on 
#endif 

#ifdef CONFIG_S3C2440_NAND_BOOT 
    ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) 
    bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 
    ldr r0,=0x00000000 
   ldr pc, =board_init_f 
#endif 

/* 
* We are done. Do not return, instead branch to second part of board 
* initialization, now running from RAM. 
*/ 
#ifdef CONFIG_NAND_SPL

 

7.5 include/configs/micro2440.h

#define CONFIG_S3C2440_NAND_BOOT /* #define CONFIG_SKIP_LOWLEVEL_INIT */

【说明】
由于要在Nand Flash中运行,所以需要注释掉#define CONFIG_SKIP_LOWLEVEL_INIT

7.6 arch/arm/lib/board.c

void board_init_f (ulong bootflag) 

    ...... 

    gd->mon_len = _bss_end_ofs + 0x100000; /* why */ 

    ...... 

					

这里的修改参考了bscbem的日志:

如果有读者想了解原理请参考这个日志。

 


    /* relocate_code (addr_sp, id, addr); */
#ifdef CONFIG_S3C2440_NAND_BOOT /*add by wzc*/ 
    __asm__ __volatile__("mov sp,%0"::"r"(addr_sp):"sp");/*add by wzc*/ 
    board_init_r(id, addr); 
#else     relocate_code (addr_sp, id, addr); 
    /* NOTREACHED - relocate_code() does not return */ #endif }
【说明】
至于gd->mon_len = _bss_end_ofs + 0x100000;我也不理解,需要阅读源代码才能解释。

7.7 下载到Nand Flash

 到这里应该就可以从Nand Flash启动了。

8.1 其他

(1)支持使用向上的箭头显示上一条命令

include/configs/micro2440.h

#define CONFIG_CMDLINE_EDITING
#ifdef CONFIG_CMDLINE_EDITING
#undef CONFIG_AUTO_COMPLETE
#else
#define CONFIG_AUTO_COMPLETE
#endif

 

(2)使用自己的环境变量

common/env_common.c文件中的default_environment[]数组,格式如:
"b=" "nand read 0x30008000 0x60000 0x300000;bootm 0x30008000" "/0"

8.2 下载

(1)按照本文移植后的u-boot 下载地址:

相关文件下载地址在Linux公社的1号FTP服务器里,下载地址:

FTP地址:

用户名:

密码:

在 2011年LinuxIDC.com\8月\u-boot-2011.03在mini2440µ2440上的移植

下载方法见这里 

(2)再次提醒:我在发布资源时用的是MACH_TYPE_MICRO2440,之前的Linux内核中有MICRO2440的机器码,值为2680,但是最近的内核,比如Linux-2.6.39中并没有这个值,虽然我自己是在Micro2440开发板上移植,但机器码还是使用MACH_TYPE_MINI2440,其值为1999。所以下载了资源的网友一定要注意gd->bd->bi_arch_number 的值。该值定义在board/samsung/micro2440/micro2440.c中的int board_init (void)函数中使用。具体内容在

(3)经过几次测试,yaffs2写入不太稳定,修改适当的时序后,yaffs2写入正常。具体参见。

(4)本文可能有遗漏的地方,但本资源可以编译

     make micro2440_config

     make CROSS_COMPILE=arm-linux-

8.3 评论与交流

(1)如本文有遗漏,欢迎指出

(2)如果您对本文提到的一些疑难有见解,欢迎评论

(3)共同交流,一起进步


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