u-boot-2009.11移植(适用于TQ2440和MINI2440)第二篇:探索启动代码

注意:红色标记部分为修改的地方

 

二、第一阶段:探索启动代码

首先进入/cpu/arm920t/start.S

2.1 关闭为AT9200写的LED跳转

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

@  bl red_LED_on

2.2 修改CPU频率初始化设置

2410 2440 相比一个不同的地方就是PLL 的初始化参数不一样,在数据手册可以查到。这里一开始就将频率升到405MHz。其中还包括了中断掩码的修正。

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(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

 

#define CLK_CTL_BASE    0x4C000000  /* tekkaman */

#define MDIV_405    0x7f << 12  /* tekkaman */

#define PSDIV_405   0x21        /* tekkaman */

#define MDIV_200    0xa1 << 12  /* tekkaman */

#define PSDIV_200   0x31        /* tekkaman */

 

………

 

# if defined(CONFIG_S3C2410)

    ldr r1, =0x7ff

    ldr r0, =INTSUBMSK

    str r1, [r0]

# endif

 

#if defined(CONFIG_S3C2440)

    ldr r1, =0x7fff

    ldr r0, =INTSUBMSK

    str r1, [r0]

#endif

 

#if defined(CONFIG_S3C2440)

    /* FCLK:HCLK:PCLK = 1:4:8 */

    ldr r0, =CLKDIVN

    mov r1, #5

    str r1, [r0]

   

    mrc p15, 0, r1, c1, c0, 0  

    orr r1, r1, #0xc0000000    

    mcr p15, 0, r1, c1, c0, 0  

   

   

    mov r1, #CLK_CTL_BASE  

    mov r2, #MDIV_405  

    add r2, r2, #PSDIV_405 

    str r2, [r1, #0x04]     /* MPLLCON tekkaman */

 

#else

    /* FCLK:HCLK:PCLK = 1:2:4 */

    /* default FCLK is 120 MHz ! */

    ldr r0, =CLKDIVN

    mov r1, #3

    str r1, [r0]

//#endif    /* CONFIG_S3C2400 || CONFIG_S3C2410 */

    mrc p15, 0, r1, c1, c0, 0  

    orr r1, r1, #0xc0000000

    mcr p15, 0, r1, c1, c0, 0   /*write ctrl register tekkaman*/

   

   

    mov r1, #CLK_CTL_BASE   /* tekkaman*/

    mov r2, #MDIV_200  

    add r2, r2, #PSDIV_200 

    str r2, [r1, #0x04]

#endif

 

#endif  /* CONFIG_S3C2400 || CONFIG_S3C2410 || CONFIG_S3C2440 */

 

    /*

     * we do sys-critical inits only at reboot,

 

2.3 修改board/sunzl/sunzl2440/lowlevel_init.S文件

依照开发板的内存区的配置情况, 修改board/sunzl/sunzl2440/lowlevel_init.S文件,利用友善之臂提供的vivi源码里的信息做了如下更改:

/* 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 */

 

#if defined(CONFIG_S3C2440)

#define Trp         0x2 /* 4clk */

#define REFCNT          1012

#else

#define Trp         0x0 /* 2clk */

#define REFCNT          0x0459

#endif

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

 

_TEXT_BASE:

 

2.4 修改代码重定向部分

Tekkaman Ninja2009.08 开始就在启动时增加了启动时检测自身是否已经在SDRAM中,以及芯片是Norboot还是Nandboot的机制,来决定代码重定向的方式,使得编译出的bin文件可以同时烧入Nand FlashNor flash。至于这部分的原理,在Tekkaman Ninja的博客文章《在U-boot下实现自动识别启动Flash的原理(针对S3C24x0)》中有详细叙述。

再次打开/cpu/arm920t/start.S

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

    bl  cpu_init_crit

#endif

//#ifndef CONFIG_SKIP_RELOCATE_UBOOT

//relocate:             /* relocate U-Boot to RAM       */

/***************** CHECK_CODE_POSITION ******************************************/

    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

/***************** CHECK_CODE_POSITION ******************************************/

 

/***************** CHECK_BOOT_FLASH ******************************************/

    ldr r1, =( (4<<28)|(3<<4)|(3<<2) )      /* address of Internal SRAM  0x4000003C*/

    mov r0, #0      /* r0 = 0 */

    str r0, [r1]

 

 

    mov r1, #0x3c       /* address of men  0x0000003C*/

    ldr r0, [r1]

    cmp r0, #0

    bne relocate

 

    /* recovery  */

    ldr r0, =(0xdeadbeef)

    ldr r1, =( (4<<28)|(3<<4)|(3<<2) )

    str r0, [r1]

/***************** CHECK_BOOT_FLASH ******************************************/

 

/***************** NAND_BOOT *************************************************/

 

#define LENGTH_UBOOT 0x60000

#define NAND_CTL_BASE 0x4E000000

 

#ifdef CONFIG_S3C2440

/* Offset */

#define oNFCONF 0x00

#define oNFCONT 0x04

#define oNFCMD 0x08

#define oNFSTAT 0x20

 

    @ reset NAND

    mov r1, #NAND_CTL_BASE

    ldr r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )

    str r2, [r1, #oNFCONF]

    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]

   

    mov r3, #0  @ wait

nand1:

    add r3, r3, #0x1

    cmp r3, #0xa

    blt nand1

 

nand2:

    ldr r2, [r1, #oNFSTAT]  @ wait ready

    tst r2, #0x4

    beq nand2

   

   

    ldr r2, [r1, #oNFCONT]

    orr r2, r2, #0x2    @ Flash Memory Chip Disable

    str r2, [r1, #oNFCONT]

   

    @ get read to call C functions (for nand_read())

    ldr sp, DW_STACK_START  @ setup stack pointer

    mov fp, #0  @ no previous frame, so fp=0

 

    @ copy U-Boot to RAM

    ldr r0, =TEXT_BASE

    mov r1, #0x0

    mov r2, #LENGTH_UBOOT

    bl  nand_read_ll

    tst r0, #0x0

    beq ok_nand_read

 

bad_nand_read:

loop2:

    b   loop2   @ infinite loop

ok_nand_read:

    @ verify

    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

 

#ifdef  CONFIG_S3C2410

 

/* Offset */

#define oNFCONF 0x00

#define oNFCMD 0x04

#define oNFSTAT 0x10

 

    @ 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

nand1:

    add r3, r3, #0x1

    cmp r3, #0xa

    blt nand1

 

nand2:

    ldr r2, [r1, #oNFSTAT]  @ wait ready

    tst r2, #0x1

    beq nand2

   

    ldr r2, [r1, #oNFCONF]

    orr r2, r2, #0x800  @ disable chip

    str r2, [r1, #oNFCONF]

   

    @ get read to call C functions (for nand_read())

    ldr sp, DW_STACK_START  @ setup stack pointer

    mov fp, #0  @ no previous frame, so fp=0

   

    @ copy U-Boot to RAM

    ldr r0, =TEXT_BASE

    mov r1, #0x0

    mov r2, #LENGTH_UBOOT

    bl  nand_read_ll

    tst r0, #0x0

    beq ok_nand_read

 

bad_nand_read:

loop2:

    b   loop2   @ infinite loop

 

 

ok_nand_read:

    @ verify

    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

/***************** NAND_BOOT *************************************************/

 

/***************** NOR_BOOT *************************************************/

relocate:               /* relocate U-Boot to RAM       */

      /*********** CHECK_FOR_MAGIC_NUMBER***************/

    ldr r1, =(0xdeadbeef)

    cmp r0, r1

    bne loop3

      /*********** CHECK_FOR_MAGIC_NUMBER***************/

    adr r0, _start      /* r0 <- current position of code   */

    ldr r1, _TEXT_BASE      /* test if we run from flash or RAM */

    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   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 */

/***************** NOR_BOOT *************************************************/

    /* Set up the stack                         */

stack_setup:

 

在上面添加的代码中有一个跳转:bl nand_read_ll ,它跳入是新增的C语言文件(board/sunzl/sunzl2440/nand_read.c中的函数,这个文件原本是用vivi 的代码,好来经过了openmoko 的修改,并支持不同的Nand Flash 芯片,Tekkaman Ninja又多加了几个个芯片ID以支持所有mini2440TQ2440 Nand Flash。代码如下:

/*

 * nand_read.c: Simple NAND read functions for booting from NAND

 *

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

 * and the board-specific linker script must make sure this

 * file is linked within the first 4kB of NAND flash.

 *

 * 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))

#define NF_BASE     0x4e000000

#if defined(CONFIG_S3C2410)

#define NFCONF      __REGi(NF_BASE + 0x0)

#define NFCMD       __REGb(NF_BASE + 0x4)

#define NFADDR      __REGb(NF_BASE + 0x8)

#define NFDATA      __REGb(NF_BASE + 0xc)

#define NFSTAT      __REGb(NF_BASE + 0x10)

#define NFSTAT_BUSY 1

#define nand_select()   (NFCONF &= ~0x800)

#define nand_deselect() (NFCONF |= 0x800)

#define nand_clear_RnB()    do {} while (0)

#elif defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)

#define NFCONF      __REGi(NF_BASE + 0x0)

#define NFCONT      __REGi(NF_BASE + 0x4)

#define NFCMD       __REGb(NF_BASE + 0x8)

#define NFADDR      __REGb(NF_BASE + 0xc)

#define NFDATA      __REGb(NF_BASE + 0x10)

#define NFDATA16    __REGw(NF_BASE + 0x10)

#define NFSTAT      __REGb(NF_BASE + 0x20)

#define NFSTAT_BUSY 1

#define nand_select()   (NFCONT &= ~(1 << 1))

#define nand_deselect() (NFCONT |= (1 << 1))

#define nand_clear_RnB()    (NFSTAT |= (1 << 2))

#endif

 

static inline void nand_wait(void)

{

    int i;

 

    while (!(NFSTAT & NFSTAT_BUSY))

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

}

 

struct boot_nand_t {

    int page_size;

    int block_size;

    int bad_block_offset;

//  unsigned long size;

};

 

#if 0

#if defined(CONFIG_S3C2410) || defined(CONFIG_sunzl2440)

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

#define NAND_PAGE_SIZE      512

#define BAD_BLOCK_OFFSET    5

#define NAND_BLOCK_MASK     (NAND_PAGE_SIZE - 1)

#define NAND_BLOCK_SIZE     0x4000

#else

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

#define NAND_5_ADDR_CYCLE

#define NAND_PAGE_SIZE      2048

#define BAD_BLOCK_OFFSET    NAND_PAGE_SIZE

#define NAND_BLOCK_MASK     (NAND_PAGE_SIZE - 1)

#define NAND_BLOCK_SIZE     (NAND_PAGE_SIZE * 64)

#endif

 

/* compile time failure in case of an invalid configuration */

#if defined(CONFIG_S3C2410) && (NAND_PAGE_SIZE != 512)

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

#endif

#endif

 

static int is_bad_block(struct boot_nand_t * nand, unsigned long i)

{

    unsigned char data;

    unsigned long page_num;

 

    nand_clear_RnB();

    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 int nand_read_page_ll(struct boot_nand_t * nand, unsigned char *buf, unsigned long addr)

{

    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;

    } else {

        return -1;

    }

    nand_wait();

 

#if defined(CONFIG_S3C2410)

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

        *buf = (NFDATA & 0xff);

        buf++;

    }

#elif defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)

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

        *ptr16 = NFDATA16;

        ptr16++;

    }

#endif

 

    return nand->page_size;

}

 

static unsigned short nand_read_id()

{

    unsigned short res = 0;

    NFCMD = NAND_CMD_READID;

    NFADDR = 0;

    res = NFDATA;

    res = (res << 8) | NFDATA;

    return res;

}

 

extern unsigned int dynpart_size[];

 

/* low level nand read function */

int nand_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 if nand id is misread */

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

        *nid = nand_id;

    }  

 

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

           nand_id == 0xad76 ) {  /*Hynix HY27US08121A*/

        nand.page_size = 512;

        nand.block_size = 16 * 1024;

        nand.bad_block_offset = 5;

    //  nand.size = 0x4000000;

    } else if (nand_id == 0xecf1 || /* Samsung K9F1G08U0B */

           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);) {

#ifdef CONFIG_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;

}

 

在添加了这个文件之后,记得要在 Makefile 里加上对这个文件的编译

board/sunzl/sunzl2440/Makefile文件中

include $(TOPDIR)/config.mk

 

LIB = $(obj)lib$(BOARD).a

 

COBJS   := sunzl2440.o nand_read.o flash.o

SOBJS   := lowlevel_init.o

 

2.5 初始化堆栈的定义

还记得前面有调用C 语言的nand_read_ll 函数吧,初始化堆栈的定义就在此

打开 /cpu/arm920t/start.S文件

ldr pc, _start_armboot

 

_start_armboot: .word start_armboot

 

#define STACK_BASE 0x33f00000

#define STACK_SIZE 0x10000

    .align  2

DW_STACK_START: .word   STACK_BASE+STACK_SIZE-4

 

到这里,启动的第一阶段就修改完了,但是在 U-boot-1.3.3 之后,这些本应放在bin 文件前4K 的代码会被放到后面,以至启动失败。所以必须手动修改链接时使用的.lds 文件,使得这些代码被放在bin 文件的最前面:

打开/cpu/arm920t/u-boot.lds文件

SECTIONS

{

    . = 0x00000000;

 

    . = ALIGN(4);

    .text :

    {

        cpu/arm920t/start.o (.text)

        board/sunzl/sunzl2440/lowlevel_init.o   (.text)

        board/sunzl/sunzl2440/nand_read.o   (.text)

        *(.text)

    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值