http://www.enjoylinux.cn/bbs/simple/?t2074.html
http://blog.sina.com.cn/s/blog_7943319e01018ip7.html
http://blog.csdn.net/klw2612/article/details/9055393
这几篇博文写得很好,但都不太完整,结合这几篇博文写下本人移植uboot-2012-07的过程,希望对各位有所帮助,不对的地方也请大家批评指正,本人的联系方式416390409@qq.com!
1、uboot下载
ftp://ftp.denx.de/pub/u-boot/ (本文是uboot-2012-07版本的移植过程)
2、建一个单板
tar xvjf u-boot-2012.07.tar.bz2
cd u-boot-2012.07/board/samsung/ /*进入目录*/
mkdir mini2440 /*创建mini2440文件夹*/
/*因2410和2440资源差不多,所以就以2410项目的代码为模板进行修改*/
cp smdk2410/* ./mini2440/ -rf /*将2410的代码复制到2440下*/
cd mini2440 /*进入mini2440目录*/
mv smdk2410.c mini2440.c /*将mini2440下的smdk2410.c重名为mini2440.c*/
vim ./Makefile /*修改mini2440下的Makefile编译选项*/
/*约28行将smdk2410.o修改为mini2440.o*/
COBJS :=mini2440.o
cd ../../../ /*回到u-boot根目录*/
cp include/configs/smdk2410.h ./include/configs/mini2440.h/*建立mini2440.h头文件*/
vim boards.cfg /*修改boards.cfg*/
/*65行后面添加*/
smdk2410 arm arm920t - samsung s3c24x0
mini2440 arm arm920t - samsung s3c24x0
3、建立source insight工程方便程序的阅读与修改
通过samba服务器找到u-boot-2012.07目录,路径为
\\10.8.12.100\share\yizhi\u-boot-2012.07/*根据自己的sanmba配置来寻找uboot的目录,路径不是绝对的*/
建立网络映射驱动器(打开计算机->工具菜单栏->映射网络驱动器->文件夹将uboot路径拷贝进去即可)
打开source insight软件建立工程(project->new project->项目名,保存路径自己选择->add all将文件添加到项目中)
将.s .S汇编文件添加到项目中(option->document option->c source->*.c;*.h,*.s,*.S)重新添加文件
同步信息
具体建立source insight工程可以网上查阅资料这里不在赘述
(uboot移植过程中需要修改文件的权限才能保存,以下移植过程中需要修改的文件默认其权限已修改,chmod 666 'filename')
4、修改时钟
(1)、在arch/arm/cpu/arm920t/start.S里面将:/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
改为
ldr r0, =0x4C000014 /* FCLK提高到405Mhz,但HCLK不能超过133Mhz */
mov r1, #5 /* FCLK:HCLK:PCLK = 1:4:8, HDIVN=10, PDIVN=1*/
str r1, [r0]
mrc p15,0,r1,c1,c0,0
orr r1,r1,#0xc0000000
mcr p15,0,r1,c1,c0,0
#define MPLL_405MHZ((127<<12)|(2<<4)|(1<<0))
ldr r0, =0x4C000004
ldr r1, =MPLL_405MHZ
str r1, [r0]
/* 2.3 启用ICACHE */
mrc p15, 0, r0, c1, c0, 0@ read control reg
orr r0, r0, #(1<<12)
mcr p15, 0, r0, c1, c0, 0@ write it back
(2)、在board/samsung/mini2440/mini2440.c的board_early_init_f函数中去掉:
writel(0xFFFFFF, &clk_power->locktime);
writel((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV,
&clk_power->mpllcon);
(在start.S中已经设置了时钟)
(3)、通过之前的分析可知:u-boot的源代码中已经带有了2440的串口初始化函数,只需在配置文件mini2440.h中定义宏CONFIG _S3C2440,去掉CONFIG_S3C2410即可。
将38行#define CONFIG_S3C2410改为 #define CONFIG_S3C2440
将101行//#define CONFIG_CMD_NAND注释掉
将222行//#define CONFIG_YAFFS2 注释掉
(4)、编译 在u-boot的跟目录下执行
make distclean
make mini2440_config
make 生成u-boot.bin文件
将生成的u-boot.bin通过jlink烧到Nor flash中启动开发板,可以看到开发板可以看到有信信息输出,证明该u-boot的对2440的时钟以及串口的支持已经正常。在串口上打印的信息中有 ### ERROR ### Please RESET the board ###
(5)、去掉arch/arm/lib/board.c中:第537,538行
//puts(failed);//hang();
并加上:
puts("0 KB\n"); (当不能识别nor flash时打印出flash: 0KB,但程序还是继续运行。)
(6)、在单板目录board/samsung/mini2440下添加init.c文件代码如下:
/* NAND FLASH控制器 */
#define NFCONF (*((volatile unsigned long *)0x4E000000))
#define NFCONT (*((volatile unsigned long *)0x4E000004))
#define NFCMMD (*((volatile unsigned char *)0x4E000008))
#define NFADDR (*((volatile unsigned char *)0x4E00000C))
#define NFDATA (*((volatile unsigned char *)0x4E000010))
#define NFSTAT (*((volatile unsigned char *)0x4E000020))
void nand_read(unsigned int addr, unsigned char *buf, unsigned int len);
static int isBootFromNorFlash(void)
{
volatile int *p = (volatile int *)0;
int val;
val = *p;
*p = 0x12345678;
if (*p == 0x12345678)
{
/* 写成功,是nand启动 */
*p = val;
return 0;
}
else
{
/* NOR不能像内存一样写 */
return 1;
}
}
void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)
{
int i = 0;
/* 如果是nor启动 */
if (isBootFromNorFlash())
{
while (i < len)
{
dest[i] = src[i];
i++;
}
}
else
{
nand_read((unsigned int)src, dest, len);
}
}
void clear_bss(void)
{
extern int __bss_start, __bss_end__;
int *p = &__bss_start;
for (; p < &__bss_end__; p++)
*p = 0;
}
void my_nand_init(void)
{
#define TACLS 0
#define TWRPH0 1
#define TWRPH1 0
/* 设置时序*/
NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
/* 使能nand flash控制器,初始化ECC,禁止片选 */
NFCONT = (1<<4)|(1<<1)|(1<<0);
}
static void nand_select(void)
{
NFCONT &= ~(1<<1);
}
static void nand_deselect(void)
{
NFCONT |= (1<<1);
}
static void nand_cmd(unsigned char cmd)
{
volatile int i;
NFCMMD = cmd;
for (i = 0; i < 10; i++);
}
static void nand_addr(unsigned int addr)
{
unsigned int col = addr % 2048;
unsigned int page = addr / 2048;
volatile int i;
NFADDR = col & 0xff;
for (i = 0; i < 10; i++);
NFADDR = (col >> 8) & 0xff;
for (i = 0; i < 10; i++);
NFADDR = page & 0xff;
for (i = 0; i < 10; i++);
NFADDR = (page >> 8) & 0xff;
for (i = 0; i < 10; i++);
NFADDR = (page >> 16) & 0xff;
for (i = 0; i < 10; i++);
}
static void nand_wait_ready(void)
{
while (!(NFSTAT & 1));
}
static unsigned char nand_data(void)
{
return NFDATA;
}
void nand_read(unsigned int addr, unsigned char *buf, unsigned int len)
{
int col = addr % 2048;
int i = 0;
/* 1.选中 */
nand_select();
while (i < len)
{
/* 2. 发出读命令00h */
nand_cmd(0x00);
/* 3. 发出地址(分5步发出) */
nand_addr(addr);
/* 4. 发现读命令30h */
nand_cmd(0x30);
/* 5. 判断状态 */
nand_wait_ready();
/* 6. 读数据*/
for (; (col < 2048) && (i < len); col++)
{
buf[i] = nand_data();
i++;
addr++;
}
col = 0;
}
/* 7. 取消选中*/
nand_deselect();
}
(7)、并且需要修改board/samsung/mini2440/Makefile文件:
将COBJS := mini2440.o
改为
COBJS := mini2440.o init.o
(8)、将arch/arm/lib/board.c第265行中的void board_init_f(ulong bootflag)函数改为返回id的具有返回值的函数unsigned int board_init_f(ulong bootflag)
并在start.S中定义一个变量,该变量用于存放栈指针。约113行
/* IRQ stack memory (calculated at run-time) + 8 bytes */.globl IRQ_STACK_START_IN
IRQ_STACK_START_IN:
.word 0x0badc0de
后添加
.globl base_sp
base_sp:
.long 0
在arch/arm/lib/board.c中将栈指针赋值,在unsigned int board_init_f函数约270行中定义
gd_t *id;
extern ulong base_sp;
ulong addr, addr_sp;
约443行
memcpy(id, (void *)gd, sizeof(gd_t));
base_sp = addr_sp; /*栈指针赋值*/
//relocate_code(addr_sp, id, addr); /*因为在start.S中已经完成了重定位,故在board_init_f函数中去掉relocate_code*/
return (unsigned int)id;/*返回id*/
约379行将下面两行注释并修改
//addr -= gd->mon_len;
//addr &= ~(4096 - 1);
addr = CONFIG_SYS_TEXT_BASE;
此外还需要将include/common.h的:
board_init_f (ulong) __attribute__ ((noreturn));
void board_init_r (gd_t *, ulong) __attribute__ ((noreturn));
改为:
unsigned int board_init_f (ulong);
void board_init_r (gd_t *, ulong) ;
(9)将start.S中的
call_board_init_f:
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
ldr r0,=0x00000000
bl board_init_f
改为:
/* Set stackpointer in internal RAM to call board_init_f */
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
bl my_nand_init /* 初始化nand 控制器 */
mov r0, #0 // 源
ldr r1, _TEXT_BASE // 目的
ldr r2, _bss_start_ofs // 长度
bl copy_code_to_sdram // 从定位代码
bl clear_bss // 清bss段
ldr pc,=call_board_init_f // 跳到SDRAM中执行
/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
ldr r0,=0x00000000
bl board_init_f
ldr r1, _TEXT_BASE // call_board_init_f 函数的返回值存放在r0中,刚好让 // board_init_r函数使用
// 函数使用
ldr sp, base_sp // 重新设置栈
bl board_init_r // 进入第二阶段
在mini2440.h中将
#define CONFIG_SYS_TEXT_BASE 0x0
改为
#define CONFIG_SYS_TEXT_BASE 0x33f80000 /*重定位代码的基地址为33f80000在高地址处留出512k供u-boot运行*/
原来的代码在链接时加了"-pie"选项, 使得u-boot.bin里多了"*(.rel*)", "*(.dynsym)"
故应去掉 "-pie"选项
arch/arm/config.mk中LDFLAGS_u-boot += -pie 去掉这行
修改链接脚本: 把start.S, init.c, lowlevel.S等文件放在最前面
即在arch/arm/cpu/u-boot.lds文件在CPUDIR/start.o后面添加:
CPUDIR/start.o (.text)后添加
board/samsung/mini2440/libmini2440.o(.text)
(10)、修改宏CONFIG_SYS_MAX_FLASH_SECT的值,将配置文件中mini2440.h中的
#define CONFIG_SYS_MAX_FLASH_SECT (19)
改为
#define CONFIG_SYS_MAX_FLASH_SECT (128) //(只需这个值打于35即可,因为该nor flash一共35个扇区)