Chinaunix首页 | 论坛 | 博客
  • 博客访问: 439487
  • 博文数量: 123
  • 博客积分: 2686
  • 博客等级: 少校
  • 技术积分: 1349
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-23 22:11
文章分类
文章存档

2012年(3)

2011年(10)

2010年(100)

2009年(10)

我的朋友

分类: LINUX

2010-01-04 20:56:31

版本:U-Boot-2009-11        
交叉编译器:arm-linux-gcc-4.3.2
环境:Fedora 12
开发板配置:s3c2440(cpu), K9F2G08U0A(Nand flah), HY57V561620F(Dram)
 
目标:移植u-boot-2009-11到s3c2440上,并从Nandflash启动。
 
STEP 1: 把源码解压后,进入到解压源码所在目录,输入命令:
          

make smdk2410_config
make all

如果有编译错误,那肯定是交叉编译器的版本有问题。4.3.2没有问题。

STEP 2: 分析顶层目录的Makefile,看u-boot是由哪些文件构成,是怎样链接的,链接顺序是怎样的.在这篇博客里面写好了。u-boot-2009-11移植之顶层目录及宏的分析  和  u-boot-2009-11移植之Makefile分析
 
STEP 3: 分析顶层目录的文件,这篇博客里面有:u-boot.lds
 
STEP 4: 分析make smdk2410_config究竟做了哪些工作。在这篇博客里面做了分析:u-boot-2009-11移植之make smdk2410_config 执行过程分析
 
STEP 5: 分析make all 做了什么事情。看顶层Makefile就知道了。
 
STEP 6: 复制模板,建立s3c240所需的所有目录和文件。
 

cd board/samsung

cp -r smdk2410 smdk2440     ;以smdk2410为模板

cd smdk2440

mv smdk2410.c smdk2440.c    ;改名

 

cd include

cp s3c2410.h s3c2440.h      ;复制头文件

cd include/configs

cp smdk2410.h smdk2440.h    ;建立我们定义的board类型smdk2440的头文件

STEP 7: 修改Makefile。使make smdk2440_config和 make all都能正确的执行。

  • 修改/board/samsung/smdk2440/ 目录下的Makefile。修改:

         COBJS   := smdk2410.o flash.o  改成:

         COBJS   := smdk2440.o flash.o

  • 修改顶层目录下的Makefile。修改:在smdk2410_config这个目标下面再加一个我们的目标:

smdk2440_config :       unconfig
        @$(MKCONFIG) $(@:_config=) arm arm920t smdk2440 samsung s3c24x0

STEP 8: 执行make smdk2440_config;make all。如果没有错误,自此,移植工作的实质性平台搭建好了。

STEP 9: 分析make all生成的文件。重点看u-boot.map 和 System.map ,这两个文件记录了链接后,各个代码段、数据段、bss段的内存地址分布。现在就要动脑子了,要从nandflash启动,那么就必须使 cpu单元初始化代码,时钟频率设置代码,内存初始化代码,Nandflash控制器初始化代码和Nandflash读写代码,栈初始化代码,放在前4k之内,否则不能把Nandflash的代码搬运到内存中。也就是说,如果TextBase 是 0x33f80000,那么之前提到的代码就要在 0x33f80000 ~ 0x33f80000 + 0x1000 内。但是,很遗憾,通过查看u-boot.map,内存初始化代码lowlevel_init并没有在这个范围之内;同时,u-boot-2009-11也并不支持从Nandflash启动。那么就要解决2个问题:

  • 增加Nandflash初始化代码和读代码。
  • 使Nandflash初始化代码和读代码,内存初始化代码放在前4k之内。

STEP 10: 从VIVI中复制代码。把VIVI里面的nand_read.c 文件复制到:

/cpu/arm920t/s3c24x0/ ,并修改这个目录下的Makefile。在COBJS-y += usb_ohci.o

后加入:COBJS-y += nand_read.o

STEP 11: 改变lowlevel_init.o的链接顺序。使,start.o为第一个链接的文件,接着就是lowlevel_init.o这个文件。修改顶层Makefile:

    # U-Boot objects....order is important (i.e. start must be first)
    171
    172 OBJS  = cpu/$(CPU)/start.o
在这个语句后面加上我们要链接的目标文件lowlevel_init.o,加上这句:

        OBJS += board/samsung/smdk2440/lowlevel_init.o

STEP 12: 分析cpu/arm920t/start.S文件。在这篇博客里面分析了。u-boot-2009-11移植之start.S分析

STEP 13:  修改start.S文件。红色的部分为添加的部分或修改的部分。(VIVI的代码是个垃圾,还不如自己写来得快,用它的代码调试了好几天。)

#include <common.h>
#include <config.h>


.globl _start
_start:    b    start_code
    ldr    pc, _undefined_instruction
    ldr    pc, _software_interrupt
    ldr    pc, _prefetch_abort
    ldr    pc, _data_abort
    ldr    pc, _not_used
    ldr    pc, _irq
    ldr    pc, _fiq

_undefined_instruction:    .word undefined_instruction
_software_interrupt:    .word software_interrupt
_prefetch_abort:    .word prefetch_abort
_data_abort:        .word data_abort
_not_used:        .word not_used
_irq:            .word irq
_fiq:            .word fiq

    .balignl 16,0xdeadbeef


_TEXT_BASE:
    .word    TEXT_BASE

.globl _armboot_start
_armboot_start:
    .word _start

/*
 * These are defined in the board-specific linker script.
 */
.globl _bss_start
_bss_start:
    .word __bss_start

.globl _bss_end
_bss_end:
    .word _end

#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
    .word    0x0badc0de

/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
    .word 0x0badc0de
#endif


/*
 * the actual start code
 */

start_code:
    /*
     * set the cpu to SVC32 mode
     */
    mrs    r0, cpsr
    bic    r0, r0, #0x1f
    orr    r0, r0, #0xd3
    msr    cpsr, r0

    @ bl    coloured_LED_init     /*1,---------modify------------*/
    @ bl    red_LED_on            /*2,---------modify------------*/


#if    defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)
    /*
     * relocate exception table
     */
    ldr    r0, =_start
    ldr    r1, =0x0
    mov    r2, #16
copyex:
    subs    r2, r2, #1
    ldr    r3, [r0], #4
    str    r3, [r1], #4
    bne    copyex
#endif

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2440)      /*3,CONFIG_S3C2410 --> CONFIG_S3C2440*/
    /* turn off the watchdog */

# if defined(CONFIG_S3C2400)
# define pWTCON    0x15300000
# define INTMSK    0x14400008    /* Interupt-Controller base addresses */
# define CLKDIVN    0x14800014    /* clock divisor register */
#else
# define pWTCON    0x53000000
# define INTMSK    0x4A000008    /* Interupt-Controller base addresses */
# define INTSUBMSK    0x4A00001C
# define CLKDIVN    0x4C000014    /* clock divisor register */
# endif

    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, =INTMSK
    str    r1, [r0]
# if defined(CONFIG_S3C2440)/*4,CONFIG_S3C2410 -->CONFIG_S3C2440 */
    ldr    r1, =0x7fff      /*5,     0x3ff --> 0x7fff    */
    ldr    r0, =INTSUBMSK
    str    r1, [r0]
# endif

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

    /*
     * we do sys-critical inits only at reboot,
     * not when booting from ram!
     */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    bl    cpu_init_crit
#endif

#ifndef CONFIG_SKIP_RELOCATE_UBOOT
#if defined(CONFIG_NOR_BOOT) /*6, add a this line ,at the same time, add in smdk2440.h*/
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 of armboot */
    add    r2, r0, r2        /* r2 <- source end address */

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


#if defined(CONFIG_NAND_BOOT)    /*8, add this line,and added in smdk2440.h*/
/*************************vivi start*****************************/
#define NAND_CTL_BASE    0x4e000000
#define oNFCONF          0x00
#define oNFCONT          0x04
#define oNFCMD           0x08
#define oNFSTAT          0x20
copy_myself:

@mov    r10, lr
/*----------------------Init Nandflash controller---------------*/
    @ reset NAND
    ldr    r1, =NAND_CTL_BASE
    ldr    r2, =0x1400        @ initial value
    str    r2, [r1, #oNFCONF]

    /*@ldr    r2, [r1, #oNFCONF]
    @bic    r2, r2, #0x800        @ enable chip
    @str    r2, [r1, #oNFCONF]*/
    @ldr    r2, [r1, #oNFCONT]
    @orr    r2, r2, #0x1
    @bic    r2, r2, #0x2
    @str    r2, [r1, #oNFCONT]
    ldr    r2, =0x73
    str    r2, [r1, #oNFCONT]

    ldr    r2, =0x0
    str    r2, [r1, #oNFSTAT]    
/*-----------------Init Nandflash controller end ---------------*/
    
/*--------------------Reset Nandflash controller ---------------*/
    bic    r2, r2, #0x2
    str    r2, [r1, #oNFCONT]

    ldr    r2, [r1, #oNFSTAT]
    orr    r2, r2, #0x2
    str    r2, [r1, #oNFSTAT]

    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, #oNFCONT]
    orr    r2, r2, #0x2        @ disable chip
    str    r2, [r1, #oNFCONT]
/*---------------Reset Nandflash controller end---------------*/

   
 @ get read to call C functions (for nand_read())
    @ldr    sp, DW_STACK_START    @ setup stack pointer
    ldr    r0, _TEXT_BASE      /* upper 128 KiB: relocated uboot */
    sub    r0, r0, #CONFIG_SYS_MALLOC_LEN    /* malloc area */
    sub    r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */
    sub    sp, r0, #12        /* leave 3 words for abort-stack */
    mov    fp, #0            @ no previous frame, so fp=0

    @ copy vivi to RAM
    @ldr    r0, =VIVI_RAM_BASE
    @mov r1, #0x0
    @mov    r2, #0x20000

    ldr   r0, _TEXT_BASE /* test if we run from flash or RAM */    
    adr    r1, _start    /* r1 <- current position of code */
    cmp    r0, r1        /* dondon't reloc duringdebug   */

 

 beq stack_setup

 ldr r2, _armboot_start
 ldr r3, _bss_start
 sub r2, r3, r2  /* r2 <- size of armboot            */
 ldr r3, =0x1ff
 bic r2, r2, r3 /*7.1,  ensure the size is (n * 512) B */
 ldr r3, =0x200
 add r2, r2, r3 /*7.2,  size + 512 B                   */

 /*[r0 --- buf], [r1 --- start_addr] , [r2 --- size]*/
 mov r1, #0x0
 ldr r2, =0x20000

 bl nand_read_ll
 /*the return value of nand_read_ll is 0,means OK.*/
 cmp r0, #0x1
 beq ok_nand_read
 bne bad_nand_read
ok_nand_read:

bad_nand_read:

/***********************end vivi************************************/
#endif /*CONFIG_NAND_BOOT*/


 /* Set up the stack          */
stack_setup:
 ldr r0, _TEXT_BASE  /* upper 128 KiB: relocated uboot   */
 sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area              */
 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo                 */
#ifdef CONFIG_USE_IRQ
 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
 sub sp, r0, #12  /* leave 3 words for abort-stack    */

clear_bss:
 ldr r0, _bss_start  /* find start of bss segment        */
 ldr r1, _bss_end  /* stop here                        */
 mov r2, #0x00000000  /* clear                            */

clbss_l:str r2, [r0]  /* clear loop...                    */
 add r0, r0, #4
 cmp r0, r1
 ble clbss_l

 ldr pc, _start_armboot

 @ldr pc, =0x33f80604
_start_armboot: .word start_armboot


/**********************后面代码不变(略)***************************/


STEP 14: 修改/include/configs/smdk2440.h , 红色的部分为修改的部分
 

#ifndef __CONFIG_H
#define __CONFIG_H

/*
 * High Level Configuration Options
 * (easy to change)
 */
#define CONFIG_ARM920T    1    /* This is an ARM920T Core    */
#define CONFIG_S3C2440    1    /* 1, CONFIG_S3C2410 --> CONFIG_S3C2440 */
#define CONFIG_SMDK2440   1   /*2,n a SAMSUNG SMDK2410 Board */

#define CONFIG_NAND_BOOT  1    /* 3, add this line */


 
STEP 15:修改nand_read.c 文件。这个文件是从VIVI copy过来的,简直不能用。要改。
 

/* low level nand read function */


#define NAND_SECTOR_SIZE 2048
#define NAND_BLOCK_MASK  (NAND_SECTOR_SIZE - 1)

int
nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
{
    int i, j;

    if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
        return -1;    /* invalid alignment */
    }

    /* chip Enable */
    NFCONT |=0x1;
    NFCONT &= ~0x2;
    for(i=0; i<10; i++);

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

    {
    /* READ0 */
    NFCMD = 0;
    NFADDR = i & 0xff;
    NFADDR = (i >> 8) & 0xf;
    NFADDR = (i >> 12) & 0xff;
    NFADDR = (i >> 20) & 0xff;
    NFADDR = (i >> 28) & 0x1;
    NFCMD = 0x30;

    wait_idle();
    for(j=0; j < NAND_SECTOR_SIZE; j++)

    {
        *buf = (NFDATA & 0xff);
        buf++;
    }

    i+= (1 <<12 );
    }

    /* chip Disable */
    NFCONT |= 0x2;    /* chip disable */
    NFCONT &= ~0x1;
}


STEP 16: make all 并改错,出现的错误基本上都是因为,我们在smdk2440.h中修改了宏,导致很多文件的头文件不能包含,故,把缺失的头文件包含就来就ok了。

  • 在文件/drivers/rtc/s3c24x0.c,/drivers/serial/serial_s3c24x0.c 中,加入如下宏,把 头文件包含进来;

#if defined(CONFIG_S3C2440) /*1, add this line*/
#include <s3c2440.h> /*2, add this line*/
#endif /*3, add this line*/

  • 修改/include/s3c24x0.h ,把宏CONFIG_S3C2410 改成CONFIG_S3C2440 .
  • 修改文件/board/samsung/sdmk2440/smdk2440.c,

    #include <s3c2440.h> /*1, 1---4 */
    gd->bd->bi_arch_number = MACH_TYPE_SMDK2440; /*2, 1 -> 4*/

  • CPU/ARM920T/S3C24X0/下的所有文件,都要 加入宏把头文件包含进来.最简单的办法是,搜索宏S3C2410_CONFIG, 所有有这个宏的地方都要修改。以timer.c 文件为例:


 /*0, add this line */
#include <common.h>
#if defined(CONFIG_S3C2400) || \
    defined(CONFIG_S3C2410) || \
    defined(CONFIG_S3C2440) || \
    defined(CONFIG_TRAB)

#include <asm/io.h>

#if defined(CONFIG_S3C2400)
#include <s3c2400.h>
#elif defined(CONFIG_S3C2410)
#include <s3c2410.h>
#endif
#if defined(CONFIG_S3C2440)    /*1, add this line*/
#include <s3c2440.h>        /*2, add this line*/
#endif                /*3, add this line*/


int timer_load_val = 0;
static ulong timer_clk;

/* macro to read the 16 bit timer */
static inline ulong READ_TIMER(void)
{
    struct s3c24x0_timers *timers = s3c24x0_get_base_timers();

    return readl(&timers->TCNTO4) & 0xffff;
}

static ulong timestamp;
static ulong lastdec;
///////////////////////////中间代码不变(略)////////////////////////


ulong get_tbclk(void)
{
    ulong tbclk;

#if defined(CONFIG_SMDK2400) || defined(CONFIG_TRAB)
    tbclk = timer_load_val * 100;
#elif defined(CONFIG_SBC2410X) || \
      defined(CONFIG_SMDK2410) || \
    defined(CONFIG_SMDK2440) || \
      defined(CONFIG_VCMA9)
    tbclk = CONFIG_SYS_HZ;
#else
#    error "tbclk not configured"
#endif

    return tbclk;
}

///////////////////////////中间代码不变(略)////////////////////////
#endif /* defined(CONFIG_S3C2400) ||
     defined (CONFIG_S3C2410) ||
     defined (CONFIG_TRAB) */

STEP 17: 在/lib_arm/board.c,找到函数void start_armboot (void) ,在里面添加测试代码,测试是否u-boot第一阶段的代码移植成功。

 

后记:关键是Nandflash有很多型号,要根据具体的型号修改读写代码。下一篇博客将是u-boot第二阶段代码移植。

欢迎转载,但注明出处。

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