加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

移植Uboot-2010.06到TQ2440开发板详解之三

发布时间:2020-12-15 06:19:33 所属栏目:百科 来源:网络整理
导读:七、支持从NAND启动 1、修改start.S文件 1)???????设置好C语言要用的栈 修改arch/arm/cpu/arm920t/start.S,将stack_setup 子程序搬到relocate 子程序之前(在调用C函数之前设置好栈),并修改之前调用设置栈的函数为清除BSS段,这是因为之前的源码程序调用beq

七、支持从NAND启动

1、修改start.S文件

1)???????设置好C语言要用的栈

修改arch/arm/cpu/arm920t/start.S,将stack_setup 子程序搬到relocate 子程序之前(在调用C函数之前设置好栈),并修改之前调用设置栈的函数为清除BSS段,这是因为之前的源码程序调用beq stack_setup之后接着执行了清除BSS段的子程序clear_bss,把stack_setup搬移到上面之后,应该确保会执行clear_bss子函数,跟之前的效果一样。修改后的代码如下:

?

209stack_setup:

210???????? ldr????r0,_TEXT_BASE????????? /* upper128 KiB: relocated uboot?? */

211???????? sub????r0,r0,#CONFIG_SYS_MALLOC_LEN? /*malloc area????????????? */

212???????? sub????r0,#CONFIG_SYS_GBL_DATA_SIZE /* bdinfo???????????????? */

213 #ifdefCONFIG_USE_IRQ

214???????? sub????r0,#(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

215#endif?

216???????? sub????sp,#12???????????? /* leave 3words for abort-stack??? */

217???????? bic????sp,sp,#7????????????? /* 8-bytealignment for ABI compliance */

218????????

219 #ifndefCONFIG_SKIP_RELOCATE_UBOOT

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

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

222???????? ldr????r1,_TEXT_BASE????????? /* test ifwe run from flash or RAM */

223???????? cmp????r0,r1????????????????? /* don'treloc during debug???????? */

224???????? /*beq??stack_setup */?????????

225???????? beq????clear_bss

226????????

227???????? ldr????r2,_armboot_start

228???????? ldr????r3,_bss_start

229???????? sub????r2,r3,r2 ?????????????/* r2<- size of armboot??????????? */

230???????? add????r2,r2????????????? /* r2<- source end address???????? */

2)???????修改代码搬移程序

在relocate子程序中屏蔽掉原来的拷贝函数,增加自己用C语言实现的拷贝函数:

?

219 #ifndefCONFIG_SKIP_RELOCATE_UBOOT

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

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

222???????? ldr????r1,_TEXT_BASE????????? /* test ifwe run from flash or RAM */

223???????? cmp????r0,r1??????????? ??????/* don't reloc during debug???????? */

224???????? /*beq??stack_setup */?????????

225???????? beq????clear_bss

226????????

227???????? ldr????r2,_armboot_start

228???????? ldr????r3,_bss_start

229???????? sub????r2,r2????????????? /* r2<- size of armboot??????????? */

230 #if1??

231???????? bl CopyCode2Ram

232#else

233???????? add????r2,r2????????????? /* r2<- source end address???????? */

234????????

235 copy_loop:

236???????? ldmia??r0!,{r3-r10}?????????? /* copyfrom source address [r0]??? */

237???????? stmia??r1!,{r3-r10}?????????? /* copyto?? target address [r1]??? */

238???????? cmp????r0,r2????????????????? /* untilsource end addreee [r2]??? */

239???????? ble????copy_loop

240#endif

241 #endif? /* CONFIG_SKIP_RELOCATE_UBOOT */

2、实现代码拷贝函数

?? 在board/samsung/tq2440/目录下增加一个文件nand_start.c,实现Nand的操作:

?

#include<common.h>

//#include<s3c2410.h>

#include<asm/arch/s3c24x0_cpu.h>

?

#defineGSTATUS1??????? (*(volatile unsigned int*)0x560000B0)

#defineBUSY??????????? 1

?

#defineNAND_SECTOR_SIZE?? 512

#defineNAND_BLOCK_MASK?? (NAND_SECTOR_SIZE - 1)

?

#defineNAND_SECTOR_SIZE_LP?? 2048

#defineNAND_BLOCK_MASK_LP?? (NAND_SECTOR_SIZE_LP- 1)

?

charbLARGEBLOCK;???????? //HJ_add 20090807

charb128MB;??????????? //HJ_add 20090807

?

/* 供外部调用的函数 */

voidnand_init_ll(void);

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

intnand_read_ll_lp(unsigned char *buf,int size);

?

/* NAND Flash操作的总入口,它们将调用S3C2410或S3C2440的相应函数 */

static voidnand_reset(void);

static voidwait_idle(void);

static voidnand_select_chip(void);

static voidnand_deselect_chip(void);

static voidwrite_cmd(int cmd);

static voidwrite_addr(unsigned int addr);

static voidwrite_addr_lp(unsigned int addr);

static unsignedchar read_data(void);

intNF_ReadID(void);??????????? //HJ_add20090807

?

/* S3C2440的NAND Flash处理函数 */

static voids3c2440_nand_reset(void);

static voids3c2440_wait_idle(void);

static voids3c2440_nand_select_chip(void);

static voids3c2440_nand_deselect_chip(void);

static voids3c2440_write_cmd(int cmd);

static voids3c2440_write_addr(unsigned int addr);

static voids3c2440_write_addr_lp(unsigned int addr);

static unsignedchar s3c2440_read_data(void);

?

/* S3C2440的NAND Flash操作函数 */

?

/* 复位 */

static voids3c2440_nand_reset(void)

{

?? s3c2440_nand_select_chip();

?? s3c2440_write_cmd(0xff);? // 复位命令

?? s3c2440_wait_idle();

?? s3c2440_nand_deselect_chip();

}

?

/* 等待NAND Flash就绪 */

static voids3c2440_wait_idle(void)

{

?? int i;

?? S3C2440_NAND * s3c2440nand = (S3C2440_NAND*)0x4e000000;

?? volatile unsigned char *p = (volatileunsigned char *)&s3c2440nand->NFSTAT;

?

?? while(!(*p & BUSY))

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

}

?

/* 发出片选信号 */

static voids3c2440_nand_select_chip(void)

{

?? int i;

?? S3C2440_NAND * s3c2440nand = (S3C2440_NAND*)0x4e000000;

?

?? s3c2440nand->NFCONT &= ~(1<<1);

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

}

?

/* 取消片选信号 */

static voids3c2440_nand_deselect_chip(void)

{

?? S3C2440_NAND * s3c2440nand = (S3C2440_NAND*)0x4e000000;

?

??s3c2440nand->NFCONT |= (1<<1);

}

?

/* 发出命令 */

static voids3c2440_write_cmd(int cmd)

{

?? S3C2440_NAND * s3c2440nand = (S3C2440_NAND*)0x4e000000;

?

?? volatile unsigned char *p = (volatileunsigned char *)&s3c2440nand->NFCMD;

?? *p = cmd;

}

?

/* 发出地址 */

static voids3c2440_write_addr(unsigned int addr)

{

?? int i;

?? S3C2440_NAND * s3c2440nand = (S3C2440_NAND*)0x4e000000;

?? volatile unsigned char *p = (volatileunsigned char *)&s3c2440nand->NFADDR;

???

?? *p = addr & 0xff;

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

?? *p = (addr >> 9) & 0xff;

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

?? *p = (addr >> 17) & 0xff;

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

?? *p = (addr >> 25) & 0xff;

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

}

?

?

/* 发出地址 */

static voids3c2440_write_addr_lp(unsigned int addr)

{

?? int i;

?? S3C2440_NAND * s3c2440nand = (S3C2440_NAND*)0x4e000000;

?? volatile unsigned char *p = (volatileunsigned char *)&s3c2440nand->NFADDR;

?? int col,page;

?

?? col = addr & NAND_BLOCK_MASK_LP;

?? page = addr / NAND_SECTOR_SIZE_LP;

??

?? *p = col & 0xff; ????????/* Column Address A0~A7 */

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

?? *p = (col >> 8) & 0x0f;????? /* Column Address A8~A11 */

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

?? *p = page & 0xff;???????? /* Row Address A12~A19 */

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

?? *p = (page >> 8) & 0xff; ??/* Row Address A20~A27 */

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

if (b128MB ==0)

?? *p = (page >> 16) & 0x03;?? /* Row Address A28~A29 */

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

}

?

/* 读取数据 */

static unsignedchar s3c2440_read_data(void)

{

?? S3C2440_NAND * s3c2440nand = (S3C2440_NAND*)0x4e000000;

?? volatile unsigned char *p = (volatileunsigned char *)&s3c2440nand->NFDATA;

?? return *p;

}

?

?

/* 在第一次使用NAND Flash前,复位一下NAND Flash */

static voidnand_reset(void)

{

?? s3c2440_nand_reset();

}

?

static voidwait_idle(void)

{

?? s3c2440_wait_idle();

}

?

static voidnand_select_chip(void)

{

?? int i;

??

?? s3c2440_nand_select_chip();

??

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

}

?

static voidnand_deselect_chip(void)

{

?? s3c2440_nand_deselect_chip();

}

?

static voidwrite_cmd(int cmd)

{

?? s3c2440_write_cmd(cmd);

}

static voidwrite_addr(unsigned int addr)

{

?? s3c2440_write_addr(addr);

}

?

static voidwrite_addr_lp(unsigned int addr)

{

?? s3c2440_write_addr_lp(addr);

}

?

static unsignedchar read_data(void)

{

?? return s3c2440_read_data();

}

?

/* 初始化NAND Flash */

voidnand_init_ll(void)

{

?? S3C2440_NAND * s3c2440nand = (S3C2440_NAND*)0x4e000000;

?

?? #define TACLS?? 0

?? #define TWRPH0? 3

?? #define TWRPH1? 0

?

?? /* 设置时序 */

?? s3c2440nand->NFCONF =(TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);

?? /* 使能NAND Flash控制器,初始化ECC,禁止片选 */

?? s3c2440nand->NFCONT =(1<<4)|(1<<1)|(1<<0);

?

?? /* 复位NAND Flash */

?? nand_reset();

}

#if 1

intNF_ReadID(void)

{

?? char pMID;

?? char pDID;

?? int?nBuff;

?? char??n4thcycle;

?? int i;

?? S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;

?? volatile unsigned char *p = (volatileunsigned char *)&s3c2440nand->NFADDR;

?

?? b128MB = 1;

?? n4thcycle = nBuff = 0;

?

?? nand_init_ll();

?? nand_select_chip();

?? write_cmd(0x90);?? // read id command

?? *p=0x00 & 0xff;

?? for ( i = 0; i < 100; i++ );

?

?? pMID = read_data();

?? pDID =?read_data();

?? nBuff =?read_data();

?? n4thcycle = read_data();

?

?? nand_deselect_chip();

??

?? if (pDID >= 0xA0)

?? {

????? b128MB = 0;

?? }

?

?? return (pDID);

}

#endif

?

/* 读函数 */

intnand_read_ll(unsigned char *buf,int size)

{

?? int i,j;

?? char dat;

?? S3C2440_NAND * s3c2440nand = (S3C2440_NAND*)0x4e000000;

?? volatile unsigned char *p = (volatileunsigned char *)&s3c2440nand->NFADDR;

?

???

?? if ((start_addr & NAND_BLOCK_MASK) ||(size & NAND_BLOCK_MASK))

?? {

????? return -1;??? /* 地址或长度不对齐 */

?? }

?

?? /* 选中芯片 */

?? nand_select_chip();

?

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

?? {

/* Check BadBlock */

if(1){

????? /* 发出READ0命令 */

????? write_cmd(0x50);

?

????? *p = 5;

????? for(j=0; j<10; j++);

????? *p = (i >> 9) & 0xff;

????? for(j=0; j<10; j++);

????? *p = (i >> 17) & 0xff;

????? for(j=0; j<10; j++);

????? *p = (i >> 25) & 0xff;

????? for(j=0; j<10; j++);

????? wait_idle();

????? dat = read_data();

????? write_cmd(0);

?????

????? /* 取消片选信号 */

????? nand_deselect_chip();

????? if(dat != 0xff)

???????? i += 16384;????? // 1 Block = 512*32= 16384

/* Read Page */

????? /* 选中芯片 */

????? nand_select_chip();

}

????? /* 发出READ0命令 */

????? write_cmd(0);

?

????? /* Write Address */

????? write_addr(i);

????? wait_idle();

?

????? for(j=0; j < NAND_SECTOR_SIZE; j++,i++)

????? {

???????? *buf = read_data();

???????? buf++;

????? }

?? }

?

?? /* 取消片选信号 */

?? nand_deselect_chip();

?

?? return 0;

}

?

/* 读函数

?* Large Page

?*/

intnand_read_ll_lp(unsigned char *buf,j;

?? char dat;

?? S3C2440_NAND * s3c2440nand = (S3C2440_NAND*)0x4e000000;

?? volatile unsigned char *p = (volatileunsigned char *)&s3c2440nand->NFADDR;

?

?? if ((start_addr & NAND_BLOCK_MASK_LP) ||(size & NAND_BLOCK_MASK_LP))

?? {

????? return -1;??? /* 地址或长度不对齐 */

?? }

?

?? /* 选中芯片 */

?? nand_select_chip();

?

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

?? {

/* Check BadBlock */

if(1){

????? int col,page;

?

????? col = i & NAND_BLOCK_MASK_LP;

????? page = i / NAND_SECTOR_SIZE_LP;

????? /* 发出READ0命令 */

????? write_cmd(0x00);

?

????? *p = 5;

????? for(j=0; j<10; j++);

????? *p = 8;

????? for(j=0; j<10; j++);

????? *p = page & 0xff;????? /* Row Address A12~A19 */

????? for(j=0; j<10; j++);

????? *p = (page >> 8) & 0xff;????? /* Row Address A20~A27 */

????? for(j=0; j<10; j++);

if (b128MB ==0)

????? *p = (page >> 16) & 0x03;????? /* Row Address A28~A29 */

????? for(j=0; j<10; j++);

?

????? write_cmd(0x30);

????? wait_idle();

????? dat = read_data();

?????

????? /* 取消片选信号 */

????? nand_deselect_chip();

????? if(dat != 0xff)

???????? i += 131072;????? // 1 Block = 2048*64= 131072

/* Read Page */

????? /* 选中芯片 */

????? nand_select_chip();

}

????? /* 发出READ0命令 */

????? write_cmd(0);

?

????? /* Write Address */

????? write_addr_lp(i);

????? write_cmd(0x30);

????? wait_idle();

?

????? for(j=0; j < NAND_SECTOR_SIZE_LP; j++,i++)

????? {

???????? *buf = read_data();

???????? buf++;

????? }

?? }

?

?? /* 取消片选信号 */

?? nand_deselect_chip();

?

?? return 0;

}

?

intbBootFrmNORFlash(void)

{

?? volatile unsigned int *pdw = (volatileunsigned int *)0;

?? unsigned int dwVal;

?

?? /*

??? * 无论是从NOR Flash还是从NAND Flash启动,

??? * 地址0处为指令"b?? Reset",机器码为0xEA00000B,

??? * 对于从NAND Flash启动的情况,其开始4KB的代码会复制到CPU内部4K内存中,

??? * 对于从NOR Flash启动的情况,NOR Flash的开始地址即为0。

??? * 对于NOR Flash,必须通过一定的命令序列才能写数据,

??? * 所以可以根据这点差别来分辨是从NAND Flash还是NOR Flash启动:

??? * 向地址0写入一个数据,然后读出来,如果没有改变的话就是NOR Flash

??? */

?

?? dwVal = *pdw;??????

?? *pdw = 0x12345678;

?? if (*pdw != 0x12345678)

?? {

????? return 1;

?? }

?? else

?? {

????? *pdw = dwVal;

????? return 0;

?? }

}

?

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

{

?? unsigned int *pdwDest;

?? unsigned int *pdwSrc;

?? int i;

?

?? if (bBootFrmNORFlash())

?? {

????? pdwDest = (unsigned int *)buf;

????? pdwSrc?= (unsigned int *)start_addr;

????? /* 从 NOR Flash启动 */

????? for (i = 0; i < size / 4; i++)

????? {

???????? pdwDest[i] = pdwSrc[i];

????? }

????? return 0;

?? }

?? else

?? {

? ????/* 初始化NAND Flash */

????? nand_init_ll();

?

????? /* 从 NAND Flash启动 */

????? if (NF_ReadID() == 0x76 )

???????? nand_read_ll(buf,start_addr,(size +NAND_BLOCK_MASK)&~(NAND_BLOCK_MASK));

????? else

???????? nand_read_ll_lp(buf,(size+ NAND_BLOCK_MASK_LP)&~(NAND_BLOCK_MASK_LP));

????? return 0;

?? }

}

3、修改board/samsung/tq2440/config.mk

????? 代码段

25 TEXT_BASE =0x33000000

26 //TEXT_BASE= 0x33F80000

?

?

?

4、修改Makefile

28 COBJS?? := tq2440.o flash.o nand_start.o

5、修改连接脚本

??? 修改arch/arm/cpu/arm920t/u-boot.lds (由于这个函数是被第一阶段的汇编程序所调用)。

40???????? .text :

41???????? {

42????????????????arch/arm/cpu/arm920t/start.o???(.text)

43????????????????board/samsung/tq2440/nand_start.o (.text)

44???????????????? *(.text)

45???? ????}

6、将之前注释掉的初始化CPU的函数取消注释

??? 修改arch/arm/cpu/arm920t/start.S? 第206行:

206???????? bl?????cpu_init_crit

??? 它会调用lowlevel_init子函数(载lowlevel_init.S文件定义)进行CPU的初始化,包括总线宽度,时序响应等。

7、最重要的修改Makefile

?????? 参见我的另一篇博文,u-boot-2010.06 移植到TQ2440从NAND启动不了以及lowlevel_init运行不过去的解决办法。

编译烧写到Nand Flash,从Nand启动,可以看到启动信息。


八、修改uboot使得支持Linux内核启动

1、修改板子头文件include/configs/tq2440.h

43 /* for tag(s) to transfermessage to kernel */

44 #define CONFIG_SETUP_MEMORY_TAGS1

45 #define CONFIG_CMDLINE_TAG 1

46 #define CONFIG_INITRD_TAG 1

……

123 /*#define CONFIG_BOOTARGS?????? "root=ramfs devfs=mountconsole=ttySA0,9600" */

124 #define CONFIG_BOOTARGS"noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0"

……

131 /*#define CONFIG_BOOTCOMMAND??? "tftp; bootm" */

132 #define CONFIG_BOOTCOMMAND"nand read 0x32000000 0x200000 0x300000; bootm 0x32000000"

?

2、修改机器码

?? 由于内核机器吗被改成了168,所以这里要改成跟内核一样,不然内核无法启动。在文件arch/arm/include/asm/mach-types.h中修改之前tq2440.c中赋值过的机器码:

(gd->bd->bi_arch_number = MACH_TYPE_S3C2440;)

?

375 //#defineMACH_TYPE_S3C2440????????????? 362

376 #defineMACH_TYPE_S3C2440????????????? 168

3、连接mkimage工具

?? 该工具在生成uImage的时候需要用到,它在编译好uboot之后就在tools文件夹下产生了,把他连接到PATH路径去(注意需要使用完整路径):

?

[root@arm 16:50 /home/zhang/uboot]# ln -sf/home/zhang/uboot-2010.06/tools/mkimage /usr/local/bin/mkimage

?

4、编译内核和根文件系统并下载

注意,如果出现文件系统启动之后,隔几秒系统就会自动重启的话,是因为应用层没有喂狗的程序。在文件系统中添加喂狗程序,重新生成文件系统之后就可以了。

Hit any key to stop autoboot:? 0

TQ2440 #

TQ2440 # tftp 0x30000000 uImage

……

TQ2440 # bootm 0x30000000

……

这样就会看到内核启动,要是Nand中已经烧录好了根文件系统,就会正常启动。但是掉电之后就没了。

可以通过nand命令将其固化在Nand中,在运行bootm 0x30000000之前:

?

1)???????下载uImage

?

TQ2440 # tftp0x30000000 uImage

dm9000 i/o: 0x20000000,id: 0x90000a46

DM9000: running in 16 bit mode

MAC: 10:23:45:67:89:ab

could not establish link

Using dm9000 device

TFTP from server 192.168.10.96; our IPaddress is 192.168.10.66

Filename 'uImage'.

Load address: 0x30000000

Loading:#################################################################

?????? ?#################################################################

?????? ?############################

done

Bytes transferred = 2314780 (23521c hex)

?

2)???????擦除NANDFLASH,擦除地址为0x200000,大小为0x300000 的NAND FLASH:

?

TQ2440 # nand erase0x200000 0x300000

?

NAND erase: device 0 offset 0x200000,size0x300000

Erasing at 0x4e0000 -- 100% complete.

OK

?

3)???????写入NANDFLASH,将地址0x30000000 的SDRAM的数据写入到地址0x200000,大小0x300000 的NAND FLASH

?

TQ2440 # nand write0x30000000 0x200000 0x300000

?

NAND write: device 0 offset 0x200000,size0x300000

?3145728 bytes written: OK

TQ2440 #

?

?? 重新启动开发板就可以看到正常引导信息。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读