三、位置判断与代码搬移

本文详细介绍了基于ARM920T处理器的启动代码,如何判断当前运行位置是在SDRAM还是Flash,并分别展示了NandFlash和NorFlash的启动流程,包括初始化、数据读取和内存拷贝等关键步骤。
摘要由CSDN通过智能技术生成

判断当前位置

判断当前位置是否在SDRAM

# < cpu\arm920t\start.S >

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

判断当前位置为Nand还是Nor Flash

# < cpu\arm920t\start.S >

ldr r1, =0x4000003c

mov r0, #0

str r0, [r1]

// mov r1, #0x3c

ldr r1, =0x4000003c

ldr r0, [r1]

cmp r0, #0

bne relocate2

/**/

ldr r0, =0xdeadbeef

ldr r1, =0x4000003c

str r0, [r1]

说明:

从地址总线可以看出,Nor和Nand启动的区别为BootSRAM位置,所以判断0x40000000-0x40000FFFF是否可以存储数据,就可以知道是不是Nor启动

Nand Boot

# < cpu\arm920t\start.S >

/***************************NAND BOOT*****************************/

#define LENGTH_UBOOT 0x40000

#define NAND_CTL_BASE 0x4e000000

#define oNFCONF 0x00

#define oNFCONT 0x04

#define oNFCMD 0x08

#define oNFSTAT 0x20

/*reset NAND*/

mov r1, #NAND_CTL_BASE

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

str r2, [r1, #oNFCONF]

ldr r2, =((1<<4)|(0<<1)|(1<<0))

str r2, [r1, #oNFCONT]

ldr r2, =0x6

str r2, [r1, #oNFSTAT]

mov r2, #0xff

strb r2, [r1, #oNFCMD]

mov r3, #0

nand1:

add r3, r3, #0x01

cmp r3, #0xa

blt nand1

nand2:

ldr r2, [r1, #oNFSTAT]

tst r2, #0x4

beq nand2

ldr r2, [r1, #oNFCONT]

orr r2, r2, #0x02

str r2, [r1, #oNFCONT]

ldr sp, DW_STACK_START

mov fp, #0

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

ok_nand_read:

mov r0, #0

ldr r1, =TEXT_BASE

mov r2, #0x400

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

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

_start_armboot: .word start_armboot

NFCONF(指令周期)

    mov r1, #NAND_CTL_BASE

    ldr r2, =((2<<12)|(1<<8)|(1<<4))

    str r2, [r1, #oNFCONF]

周期(HCLK: 100M)

TACLS = 2*HCLK=20ns > 0 ns

TWRPH0 = (1+1)*HCLK=20ns > 12 ns

TWRPH1 = (1+1)*HCLK=20ns > 5 ns

 

 

 

 

 NFCONT(配置使能Nand Flash)

    ldr r2, =((1<<4)|(0<<1)|(1<<0))

    str r2, [r1, #oNFCONT]

初始化ECC(错误校验)

使能片选

Nand Flash控制器使能

 

NFSTAT(Nand Flash状态)

    ldr r2, =0x6

    str r2, [r1, #oNFSTAT]

清除RnB

NFCMD(Nand Flash命令)

    mov r2, #0xff

    strb r2, [r1, #oNFCMD]

复位

片选、设置栈底、跳转c代码拷贝第二阶段

nand2:

        // 判断状态

ldr r2, [r1, #oNFSTAT]

tst r2, #0x4

beq nand2

        

        // 片选

ldr r2, [r1, #oNFCONT]

orr r2, r2, #0x02

str r2, [r1, #oNFCONT]

        // 设置栈顶

ldr sp, DW_STACK_START

mov fp, #0

        设置参数,跳转c代码

ldr r0, =TEXT_BASE

mov r1, #0x0

mov r2, #LENGTH_UBOOT

bl nand_read_ll

c代码拷贝第二阶段

# < board\vbird\mini2440\nand_read.c >

#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

#define NFCONF _REGi(NF_BASE+0x0)

#define NFCONT _REGi(NF_BASE+0x04)

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

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;

};

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 == 2048)

{

page_num=i>>11;

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 char *ptr = (unsigned char *)buf;

unsigned int i, page_num;

nand_clear_RnB();

NFCMD = NAND_CMD_READ0;

if (nand->page_size == 2048)

{

page_num = addr>>11;

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

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

{

*ptr = NFDATA;

ptr++;

}

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[];

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

nand.page_size = 2048;

nand.block_size = 128*1024;

nand.bad_block_offset = nand.page_size;

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

return -1;

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

{

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

i += j;

buf += j;

}

nand_deselect();

return 0;

}

设置栈、bss段、跳转第二阶段

# < cpu\arm920t\start.S >

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

_start_armboot: .word start_armboot

Nor Boot

# < cpu\arm920t\start.S >

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

ldr r1, =0x4000003c

mov r0, #0

str r0, [r1]

mov r1, #0x3c

ldr r0, [r1]

cmp r0, #0

bne relocate2

/**/

ldr r0, =0xdeadbeef

ldr r1, =0x4000003c

str r0, [r1]

loop3:

b loop3

/*******************nor boot*********************/

relocate2:

ldr r1, =0xdeadbeef

cmp r0, r1

bne loop3

adr r0, _start

ldr r1, _TEXT_BASE

ldr r2, _armboot_start

ldr r3, _bss_start

sub r2, r3, r2

// stmia r1!, {r3-r10}

cmp r0, r2

ble copy_loop

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

_armboot_start = _start 代码起始

_bss_start 代码结尾

_bss_start - _armboot_start 代码大小

拷贝:从_start,拷贝(_bss_start - _armboot_start )整个代码

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值