【实验目的】
了解U-boot-2010.03的代码结构及移植方法。
【实验环境】
1、 Ubuntu 10.10发行版
2、 u-boot-2010.03
3、 FS2410平台
4、 交叉编译器arm-none-linux-gnueabi-gcc
【实验步骤】
说明:后面实验中的命令行提示符是($)则为主机命令(主机上执行)
1、 建立自己的平台
1、 下载源码
我们可以在下面这个网站上下载最新的和以前任一版本的uboot
我们这里使用的是u-boot-2010.03.tar.bz2
2、 解压uboot源码
$ tar jxvf u-boot-2010.03.tar.bz2
3、 进入到uboot源码
$ cd u-boot-2010.03
4、 添加FS2410平台信息
我们关心的班级相关内容文件或目录
u-boot-2010.03/Makefile
u-boot-2010.03/cpu/arm920t/start.S
u-boot-2010.03/board/Samsung/smdk2410
u-boot-2010.03/lib_arm
u-boot-2010.03/include/configs/smdk2410.h
smdk2410是s3c2410的标准板,我们在smdk2410的基础上做FS2410的移植
$ cd board/samsung/
$ cp smdk2410 fs2410 –a
$ cd fs2410
$ mv smdk2410.c fs2410.c
$ vim Makefile
修改
COBJS := smdk2410.o flash.o
为
COBJS := fs2410.o flash.o
$ cd include/configs
$ cp smdk2410.h fs2410.h
修改u-boot顶层目录下的Makefile,按照smdk2410的内容添加fs2410的内容
$ vim Makefile
在
smdk2410_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 samsung s3c24x0
下添加:
fs2410_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t fs2410 samsung s3c24x0
修改编译器
在
ifeq ($(HOSTARCH, $(ARCH))
CROSS_COMPILE ?=
endif
下添加:
ifeq (arm, $(ARCH))
CROSS_COMPILE ?= arm-none-linux-gnueabi-
endif
5、 编译u-boot-2010.03
$ make distclean
$ make fs2410_config
$ make
这个时候我们就可以得到一个u-boot.bin也就是我们的目标文件,但是这个文件通常情况下是不能够正常工作的,我们还需要对u-boot源代码进行进一步的修改。
2、 针对我们的FS2410平台进行进一步的修改
1、 u-boot源码中的中断屏蔽位
在s3c2410中有11个子中断屏蔽位代码里只有10个
修改cpu/arm920t/start.S
修改
# if defined(CONFIG_S3C2410)
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
为:
# if defined(CONFIG_S3C2410)
ldr r1, =0x7ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
2、 修改配置文件include/configs/fs2410.h
1) 命令行提示符的修改:
#define CONFIG_SYS_PROMPT "SMDK2410 # "
改成:
#define CONFIG_SYS_PROMPT "fs2410 # "
2) 网络参数设置
修改
#define CONFIG_ETHADDR 08:00:3e:26:0a:5b
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 10.0.0.110
#define CONFIG_SERVERIP 10.0.0.1
为
#define CONFIG_ETHADDR 11:22:33:44:55:66
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 192.168.7.222
#define CONFIG_SERVERIP 192.168.7.223
3) 内核加载地址的修改
修改
#define CONFIG_SYS_LOAD_ADDR 0x33000000
改成:
#define CONFIG_SYS_LOAD_ADDR 0x30008000
4) Nand功能添加
对照include/config_cmd_default.h和include/config_cmd_all.h添加我们需要的相应功能。
Nand的功能的添加
#define CONFIG_CMD_NAND /* NAND support*/
#if defined(CONFIG_CMD_NAND)
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_BASE 0x4E000000
#define CONFIG_NAND_S3C2410
#define STACK_BASE 0x33f00000
#define STACK_SIZE 0x8000
/* Nand Flash */
#define CONFIG_MTD_NAND_VERIFY_WRITE 1
#endif
5) 同时支持nand启动和nor启动
#if defined(CONFIG_S3C2410)
#define CONFIG_S3C2410_NAND_BOOT 1 //nand 启动
#define CONFIG_S3C2410_NOR_BOOT 1 //nor 启动
#endif
6) 环境变量保存位置
添加:
#ifdef CONFIG_S3C2410_NOR_BOOT
#define CONFIG_ENV_IS_IN_FLASH 1 /*common/env_flash.c */
#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x30000)
#endif
#ifdef CONFIG_S3C2410_NAND_BOOT
#define CONFIG_ENV_IS_IN_NAND 1 /* common/env_nand.c */
#define CONFIG_ENV_SIZE 0x10000
#define CONFIG_ENV_OFFSET 0x30000
#define NAND_CTL_BASE 0x4E000000
/* Offset */
#define oNFCONF 0x00
#define oNFCMD 0x04
#define oNFADDR 0x08
#define oNFDATA 0x0c
#define oNFSTAT 0x10
#define oNFECC 0x14
#endif
7) USB功能的添加
#define CONFIG_CMD_FAT /* FAT support*/
#define CONFIG_CMD_USB /* USB support*/
#if defined(CONFIG_CMD_USB)
#define CONFIG_DOS_PARTITION
#define CONFIG_USB_OHCI
#define CONFIG_USB_STORAGE
#define CONFIG_SUPPORT_VFAT
#define LITTLEENDIAN
#endif
Ping命令的添加
#define CONFIG_CMD_PING /* ping support*/
8) Nor flash(sst39vf1601)及Norflash相关内容的
注释掉
#define CONFIG_AMD_LV400 1 /* uncomment this if you have a LV400 flash */
添加
#define CONFIG_SST_39VF1601 1
添加
#ifdef CONFIG_SST_39VF1601
#define PHYS_FLASH_SIZE 0x00200000 /* 2M*/
#define CONFIG_SYS_MAX_FLASH_SECT (512) /* max number of sectors on one chip */
#endif
3、 添加Nand启动功能(修改cpu/arm920t/start.S)
u-boot默认情况下是nar启动,这里我们添加nand启动的内容:
1) 添加头文件
#include
#include
2) 添加nand启动标志位
/*add for env_nand.c*/
.extern pbootflag
@pbootflag: //1:NOR flash, 0:NAND flash
3) 添加BWSCON寄存器的定义(加粗字体为添加内容)
# 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 */
# define BWSCON 0x48000000
# endif
4) 添加启动模式判断Nor启动还是nand启动(加粗字体为添加内容)
/*czm add 2010-8-18*/
ldr r0,=BWSCON
ldr r0,[r0]
ands r0,r0,#6
beq nand_boot
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
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
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 */
#endif
/* add 2010-08-18 */
bl stack_setup
5) 添加NAND启动自搬移代码(在上一步代码下添加)
nand_boot:
#ifdef CONFIG_S3C2410_NAND_BOOT
@ 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, #0x30000
bl nand_read_ll
tst r0, #0x0
beq ok_nand_read
bad_nand_read:
loop2: b loop2 @ infinite loop
ok_nand_read:
ldr r0, =pbootflag
mov r1, #0x0
str r1, [r0]
@ 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 @ CONFIG_S3C2410_NAND_BOOT
在_start_armboot: .word start_armboot下添加如下代码:
.align 2
DW_STACK_START: .word STACK_BASE + STACK_SIZE - 4
4、 添加nand_read.c为nand启动做支持
在board/samsung/fs2410下添加文件nand_read.c并在这个文件中添加如下内容:
#include
#define __REGb(x) (*(volatile unsigned char *)(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 BUSY 1
#define NAND_SECTOR_SIZE 512
#define NAND_BLOCK_MASK (NAND_SECTOR_SIZE – 1)
inline void wait_idle(void) {
int i;
while(!(NFSTAT & BUSY))
for(i=0; i<10; i++);
}
/* low level nand read function */
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 */
NFCONF &= ~0x800;
for(i=0; i<10; i++);
for(i=start_addr; i < (start_addr + size);) {
/* READ0 */
NFCMD = 0;
/* Write Address */
NFADDR = i & 0xff;
NFADDR = (i >> 9) & 0xff;
NFADDR = (i >> 17) & 0xff;
NFADDR = (i >> 25) & 0xff;
wait_idle();
for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
*buf = (NFDATA & 0xff);
buf++;
}
}
/* chip Disable */
NFCONF |= 0x800; /* chip disable */
return 0;
}
# endif
并修改board/Samsung/fs2410/ 下Makefile
修改
COBJS := fs2410.o flash.o
为:
COBJS := fs2410.o flash.o nand_read.o
5、 修改board/samsung/fs2410/flash.c支持sst19lv1601 nor flash芯片
修改
#define MAIN_SECT_SIZE 0x10000 /*64KB*/
为:
#define MAIN_SECT_SIZE 0x1000 /*4KB for sst39lv1601*/
修改
#define CMD_UNLOCK_BYPASS 0x00000020
为
#define CMD_UNLOCK_BYPASS 0x000000A0
修改
#define MEM_FLASH_ADDR1 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x00000555 << 1)))
#define MEM_FLASH_ADDR2 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x000002AA << 1)))
为
#define MEM_FLASH_ADDR1 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x00005555 << 1)))
#define MEM_FLASH_ADDR2 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x00002AAA << 1)))
在
#elif defined(CONFIG_AMD_LV800)
(AMD_MANUFACT & FLASH_VENDMASK) |
(AMD_ID_LV800B & FLASH_TYPEMASK);
下添加
#elif defined(CONFIG_SST_39VF1601)
(SST_MANUFACT & FLASH_VENDMASK) |
(SST_ID_xF1601 & FLASH_TYPEMASK);
修改
for (j = 0; j < flash_info[i].sector_count; j++) {
if (j <= 3) {
/* 1st one is 16 KB */
if (j == 0) {
flash_info[i].start[j] = flashbase + 0;
}
/* 2nd and 3rd are both 8 KB */
if ((j == 1) || (j == 2)) {
flash_info[i].start[j] =
flashbase + 0x4000 + (j -1) * 0x2000;
}
/* 4th 32 KB */
if (j == 3) {
flash_info[i].start[j] =
flashbase + 0x8000;
}
} else {
flash_info[i].start[j] =
flashbase + (j - 3)*MAIN_SECT_SIZE;
}
}
替换为
for (j = 0; j < flash_info[i].sector_count; j++) {
flash_info[i].start[j] =
flashbase + j*MAIN_SECT_SIZE;
}
在
case (AMD_MANUFACT & FLASH_VENDMASK):
printf ("AMD: ");
break;
下添加
case (SST_MANUFACT & FLASH_VENDMASK):
printf ("SST: ");
break;
在
case (AMD_ID_LV800B & FLASH_TYPEMASK):
printf ("1x Amd29LV800BB (8Mbit)\n");
break;
下添加
case ( SST_ID_xF1601 & FLASH_TYPEMASK):
printf ("1x 39VF1601\n");
break;
修改
if ((info->flash_id & FLASH_VENDMASK) !=
(AMD_MANUFACT & FLASH_VENDMASK)) {
return ERR_UNKNOWN_FLASH_VENDOR;
}
为
if ((info->flash_id & FLASH_VENDMASK) !=
(SST_MANUFACT & FLASH_VENDMASK)) {
return ERR_UNKNOWN_FLASH_VENDOR;
}
注释掉下面语句
if (!chip
&& (result & 0xFFFF) & BIT_PROGRAM_ERROR)
chip = ERR;
注释掉
*addr = CMD_PROGRAM;
6、 修改common/env_flash.c,为nor flash保存环境变量做准备
修改
char * env_name_spec = "Flash";
为
char * nor_env_name_spec = "Flash";
修改
env_t *env_ptr = (env_t *)(&environment[0]);
为
extern env_t *env_ptr = (env_t *)(&environment[0]);
修改
env_t *env_ptr = (env_t *)CONFIG_ENV_ADDR;
为
extern env_t *env_ptr ;
添加
extern uchar env_get_char_spec (int index);
并注释掉下面语句
uchar env_get_char_spec (int index)
{
return ( *((uchar *)(gd->env_addr + index)) );
}
修改
int env_init(void)
为
int nor_env_init(void)
修改
int saveenv(void)
为
int nor_saveenv(void)
修改
void env_relocate_spec (void)
为
void nor_env_relocate_spec (void)
7、 修改common/env_nand.c添加nor flash环境变量烧写功能
添加
volatile int pbootflag=1; //add by lht 1->nor 0->nand
extern int nor_env_init(void);
修改int env_init(void)函数在函数开始添加如下内容:
if(pbootflag==1) //by lht
{
env_name_spec = "NOR";
env_ptr=(env_t *)CONFIG_ENV_ADDR;
return nor_env_init();
}
修改int saveenv(void)函数,在函数开始添加如下内容
if(pbootflag==1)
{
env_name_spec = "NOR";
return nor_saveenv();
}
修改void env_relocate_spec (void)函数,在函数开始添加如下内容
if(pbootflag==1)
{
return nor_env_relocate_spec();
}
8、 修改SDRAM刷新周期:board/samsung/fs2410/lowlevel_init.S
#define REFCNT 1113 /* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */
改成:
#define REFCNT 1268 /* period=7.8125us, HCLK=100Mhz, (2048+1-7.8125*100) */
9、 链接文件的修改
修改cpu/arm920t/u-boot.lds:
在
cpu/arm920t/start.o (.text)
下添加
board/samsung/fs2410/lowlevel_init.o (.text)
board/samsung/fs2410/nand_read.o (.text)
10、 go命令的优化
修改该common/cmd_boot.c
int do_go (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
ulong addr, rc;
int rcode = 0;
/****add by farsight 2010-8-18**************************************/
char *commandline = getenv("bootargs");
struct param_struct *lht_params=(struct param_struct *)0x30000100;
printf("setup linux parameters at 0x30000100\n");
memset(lht_params,0,sizeof(struct param_struct));
lht_params->u1.s.page_size=4096;
lht_params->u1.s.nr_pages=0x4000000>>12;
memcpy(lht_params->commandline,commandline,strlen(commandline)+1);
printf("linux command line is: \"%s\"\n",commandline);
/***************************************************************/
if (argc < 2) {
cmd_usage(cmdtp);
return 1;
}
addr = simple_strtoul(argv[1], NULL, 16);
printf ("## Starting application at 0x%08lX ...\n", addr);
/*
* pass address parameter as argv[0] (aka command name),
* and all remaining args
*/
/*********************add by farsight 2010-8-18*********************/
__asm__(
"mov r1, #193\n"
"mov ip, #0\n"
"mcr p15, 0, ip, c13, c0, 0\n" /* zero PID */
"mcr p15, 0, ip, c7, c7, 0\n" /* invalidate I,D caches */
"mcr p15, 0, ip, c7, c10, 4\n" /* drain write buffer */
"mcr p15, 0, ip, c8, c7, 0\n" /* invalidate I,D TLBs */
"mrc p15, 0, ip, c1, c0, 0\n" /* get control register */
"bic ip, ip, #0x0001\n" /* disable MMU */
"mov pc, %0\n"
"nop\n"
:
:"r"(addr)
);
/***************************************************************/
rc = do_go_exec ((void *)addr, argc - 1, argv + 1);
if (rc != 0) rcode = 1;
printf ("## Application terminated, rc = 0x%lX\n", rc);
return rcode;
}
3、 重新编译
$ make distclean
$ make fs2410_config
$ make
这个时候我们就可以获得一个我们能够使用的u-boot了,不过此时只可以通过命令setenv bootcmd tftp 30800000 zImage \; go 30800000 通过前面go命令的优化传入环境变量引导内核挂载根文件系统。而bootm还没支持。待更新……
补充:上面所编译出来的uboot只支持加载zImage而不能加载uImage,因为给内核传递参数的时候被某些宏给屏蔽了,所以还须打开某些宏。
9>uboot给uImage内核传递参数修改:(include/configs/fs2410.h)
在
#define USE_920T_MMU
#undef CONFIG_USE_IRQ
在这两行下面添加:
#define CONFIG_CMDLINE_TAG 1
#define CONFIG_SETUP_MEMORY_TAGS 1
#define CONFIG_INITRD_TAG 1
#define CONFIG_ETH_TAG 1