经过四天的苦战,今天终于将Uboot成功移植到博创的UP-Star2410上了。其实前几天就做好了,但是当时想通过原厂烧好的Uboot将我新移植的下载到SDRAM上运行,但是总是提示test:RC0,然后就停在原地了,只能重启。后来,我又将光盘里的U-boot 1.3.2重新配置编译好后发现仍然不能在RAM中运行,我就猜到了可能是在对RAM的配置上有些问题。还好我多了个心眼,又把编译好的通过sjf2410下载到NAND Flash上,结果一上电,哈,果然能够运行。看来还真是RAM在作怪。
今天终于发现问题了,原来时调试阶段是程序的链接和CPU的初始化有问题。偶然间看到一篇帖子上回复à直接在内存运行uboot就更简单了,只需要借助uboot自身把新编译的uboot先下载到内存,然后用go命令就行了,不过需要注意,调试uboot的时候,这个uboot链接位置千万不要和原来在运行的uboot链接地址一样,不能对SDRAM初始化,最好也不要对系统时钟再初始化。查查代码中这2个宏相关的代码CONFIG_SKIP_LOWLEVEL_INIT CONFIG_SKIP_RELOCATE_UBOOT,读读就知道怎么做了。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
其实要做的也很简单,就是在设置链接脚本是将_TEXT_BASE=0x33f80000改为与当前运行的Uboot的地址不重合就行(之所以说不重合是指既不能相同,还要保证彼此不覆盖)。另外,在/cpu/arm920t下面的start.S中把包含lowlevel_init.S的语句跳过(即把#ifndef CONFIG_SKIP_LOWLEVEL_INIT改为#ifdef CONFIG_SKIP_LOWLEVEL_INIT)。然后 tftp 到内存里.直接从那go 就可以了
好了,闲话少说,下面把自己的移植过程跟大家分享一下,有不对的地方,恳请大家多多指正,让我能再上一个台阶。主要分以下几个步骤:
1. 下载源码
推荐官网ftp下载ftp://ftp.denx.de/pub/u-boot/,这里有最新最全的Uboot源码。但是利用校园网上网的同学需要麻烦一下,至少我们学校是这样,就得通过代理来下载了。至于怎么利用代理,我就不多叙述了,搞嵌入式这一行遇到问题就得是do {baidu; google;} while (~problem solved)
这里我下载的是U-boot-1.3.4,大家也可以下载其他的版本,至于区别这个我没有研究,等以后学习深入了再说吧。
2. 准备阶段。
下载到源码以后,解压到自己的工作目录,比如我的工作目录是/home/celer/u-boot,将源码拷贝到工作目录后解压,tar xjf u-boot-1.3.4.tar.bz2。网上已经有很多人介绍如何移植了,其实步骤都是很相似的。
解压好后,进入Uboot根目录,进入board目录,这里存放的是Uboot支持的所有开发板,所有为了让Uboot支持我们的开发板,我们也要新建一个,但是之所以称之为Uboot“移植”,我理解就是“修改”,我们要利用现有的代码来“搭建”成我们需要的代码。现在市面上主流的嵌入式ARM处理器比较常见的就是S3C2410和S3C2440,针对这两个开发板我们选择smdk2410开发板文件夹,因此我们可以复制一个到我们的开发板,这里我起名为UP-Star2410。
cp –rf smdk2410/ UP-Star2410
进入UP-Star2410,ls一下,看到有以下文件
config.mk flash.c lowlevel_init.S Makefile smdk2410.c u-boot.lds
为了让大家能够更加明白为什么是这样或那样移植的,我们先来看看这几个文件的作用。(这里为了复制粘贴方便,我使用SSH来远程登录我虚拟机上的Linux。或者也可以使用UltraEdit,这个也是一个不错的工具,我所遇到的什么文件都能查看,真是厉害。大家不妨尝试一下)。
先来看看config.mk,只摘录比较关键的。(关于代码的改变,便于大家理解,注释部分我用蓝色来标记,需要改变的源代码我用紫色标记,改好后的代码我用红色标记,之所以选用红色,一是因为大家看起来方便,更主要的是大家如果发现错用可以及时指正)
# SMDK2410 has 1 bank of 64 MB DRAM
#
# 3000'0000 to 3400'0000
#
# Linux-Kernel is expected to be at 3000'8000, entry 3000'8000
# optionally with a ramdisk at 3080'0000
#
# we load ourself to 33F8'0000
#
# download area is 3300'0000
#
TEXT_BASE = 0x33F80000
可以看出这个文件是对Uboot进行链接的,链接地址在0x33F80000。但是大家请注意注释里说到的,SMDK2410开发板配置了一个64M的SDRAM,地址范围在30000000~34000000,内核默认的运行地址是30008000,可选的ramdisk运行地址是30800000,uboot的默认运行地址是33F8000.但是我手中博创的开发板只有32M的SDRAM,并且接在BANK6上,所以地址空间就变成30000000~32000000.这时我们程序的运行地址就需要相应的改变了,现在我们只讨论Uboot的移植,所有关于内核和ramdisk我们这里先不讨论。改好后的代码如下:
# UP-Star2410 has 1 bank of 32 MB DRAM
#
# 3000'0000 to 3200'0000
#
# Linux-Kernel is expected to be at 3000'8000, entry 3000'8000
# optionally with a ramdisk at 3080'0000
#
# we load ourself to 31F8'0000
#
# download area is 3300'0000
#
TEXT_BASE = 0x31F80000
下面我们来看看smdk2410.c,这个文件主要是用来配置开发板的时钟分配以及SDARM的起始地址和大小的参数传递。
#include <common.h>
#include <s3c2410.h>
/*此全局变量指定用R8寄存器来存放其存储地址,所有在任意函数里面声明一下就可以使用同一个全局变量了,比如后面的gd*/
DECLARE_GLOBAL_DATA_PTR;
/*这部分是用来定义全局时钟和USB时钟的,但是可以看出默认的CPU主频是202.8MHz,而我们一般选择的是200MHz,所以这个地方我们需要修改一下*/
#define FCLK_SPEED 1
#if FCLK_SPEED==0 /* Fout = 203MHz, Fin = 12MHz for Audio */
#define M_MDIV 0xC3
#define M_PDIV 0x4
#define M_SDIV 0x1
#elif FCLK_SPEED==1 /* Fout = 202.8MHz */
#define M_MDIV 0xA1
#define M_PDIV 0x3
#define M_SDIV 0x1
#endif
#define USB_CLOCK 1
#if USB_CLOCK==0
#define U_M_MDIV 0xA1
#define U_M_PDIV 0x3
#define U_M_SDIV 0x1
#elif USB_CLOCK==1
#define U_M_MDIV 0x48
#define U_M_PDIV 0x3
#define U_M_SDIV 0x2
#endif
static inline void delay (unsigned long loops)
{
__asm__ volatile ("1:\n"
"subs %0, %1, #1\n"
"bne 1b":"=r" (loops):"0" (loops));
}
/*
* Miscellaneous platform dependent initialisations
*/
int board_init (void)
{
/* clk_power这个结构体指针指向的是一个S3C2410_CLOCK_POWER类型的结构体,里面封装了关于时钟以及电源配置的寄存器,这里我就不深究了,大家了解一下就行*/
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
/*以下是开发板的时钟配置*/
/*我们先来配置一下时钟分频比例*/
clk_power->CLKDIVN = S3C2410_CLKDIV;
/*修改为异步总线模式—这里我参考韦东山老师的代码,具体为什么我也没有深究,希望讨论的大家可以给我留言,我再仔细看看*/
__asm__( “mrc p15, 0, r1, c1, c0,0 \n” /*read ctrl register*/
“orr r1, r1, #0xc0000000 \n” /* asynchronous */
“mcr p15, 0, r1, c1, c0, 0 \n” /*write ctrl register*/
::: “r1”
);
/* to reduce PLL lock time, adjust the LOCKTIME register */
clk_power->LOCKTIME = 0xFFFFFF;
/* configure MPLL */
clk_power->MPLLCON = S3C2410_MPLL_200MHZ;
/* some delay between MPLL and UPLL */
delay (4000);
/* configure UPLL */
clk_power->UPLLCON = S3C2410_UPLL_48MHZ;
/* some delay between MPLL and UPLL */
delay (8000);
/* set up the I/O ports */
gpio->GPACON = 0x007FFFFF;
gpio->GPBCON = 0x00044555;
gpio->GPBUP = 0x000007FF;
gpio->GPCCON = 0xAAAAAAAA;
gpio->GPCUP = 0x0000FFFF;
gpio->GPDCON = 0xAAAAAAAA;
gpio->GPDUP = 0x0000FFFF;
gpio->GPECON = 0xAAAAAAAA;
gpio->GPEUP = 0x0000FFFF;
gpio->GPFCON = 0x000055AA;
gpio->GPFUP = 0x000000FF;
gpio->GPGCON = 0xFF95FFBA;
gpio->GPGUP = 0x0000FFFF;
gpio->GPHCON = 0x002AFAAA;
gpio->GPHUP = 0x000007FF;
/* arch number of SMDK2410-Board */
gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
/* 这个是Uboot引导内核时传递参数的地址,这个要记住,因为我们以后移植内核时还要用到 */
gd->bd->bi_boot_params = 0x30000100;
icache_enable();
dcache_enable();
return 0;
}
/*这个是我们开发板上的SDRAM起始地址和空间大小,在include/configs/smdk2410.h中定义*/
int dram_init (void)
{
gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
return 0;
}
/*参照S3C2410的datasheet,我们看到时钟频率设定的公式如下
* S3C2410: MPLL,UPLL=(m* Fin) / (p*2^s)
*m= MDIV (the value for divider M) + 8, p= PDIV (the value for divider) + 2, s="SDIV"
*虽然手册上有个表可以参考,不过没有我们想要的200MHz,所有还得我们自己来计算
*这里我就用大家常用的代入就可以了
*开发板的时钟为12MHz,在include/configs/smdk2410.h中的宏CONFIG_CLK_FREG中定义,*如果大家的时钟不同(不过我所见过的都是这个),可以修改
*/
#define S3C2410_MPLL_200MHZ ((0x5c<<12) | (0x04<<4) | (0x00))
#define S3C2410_UPLL_48MHZ ((0x28<<12) | (0x01<<4) | (0x02))
#define S3C2410_CLKDIV 0x03 /*FCLK:HCLK:PCLK=1:2:4*/
现在我们看出来,smdk2410.c就是我们开发板的时钟和RAM配置,那么我们的开发板既然是UP-Star2410,那么这个文件名也得改成UP-Star2410了。
我们再来看看u-boot.lds文件,这个文件我们不需要改动。
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
OUTPUT_ARCH(arm)
/*指明了Uboot程序的入口函数时_start,在cpu/arm920t/start.S中,后面会介绍*/
ENTRY(_start)
SECTIONS
{
. = 0x00000000; /* 后记:这个链接起始地址实际上被-Ttest $(TEST_BASE)更新了*/
. = ALIGN(4);
.text : //程序段基址
{
cpu/arm920t/start.o (.text)
*(.text)
}
. = ALIGN(4); //只读数据段基址
.rodata : { *(.rodata) }
. = ALIGN(4);
.data : { *(.data) } //读写数据段基址
. = ALIGN(4);
.got : { *(.got) }
. = .;
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
. = ALIGN(4);
__bss_start = .; //初始化为0或未定义变量的存储基址
.bss (NOLOAD) : { *(.bss) }
_end = .;
}
我们再来看看lowlevel_init.S文件,这个文件在Uboot启动后执行的第一个函数start.S中被调用,这个文件是用来配置S3C2410的Memory Controller(比如我们需要添加网卡时也要配置这个文件)和SDRAM的设置。
#include <config.h>
#include <version.h>
/* some parameters for the board */
/*
*
* Taken from linux/arch/arm/boot/compressed/head-s3c2410.S
*
* Copyright (C) 2002 Samsung Electronics SW.LEE <hitchcar@sec.samsung.com>
*
*/
/*S3C2410特殊功能寄存器SFR的起始地址*/
#define BWSCON 0x48000000
/* BWSCON */
#define DW8 (0x0)
#define DW16 (0x1)
#define DW32 (0x2)
#define WAIT (0x1<<2)
#define UBLB (0x1<<3)
/*定义每个BANK的数据总线带宽,注意BANK0的带宽只能是16位或32位,而且由CPU的M0和M1引脚硬件决定*/
#define B1_BWSCON (DW32)
#define B2_BWSCON (DW16)
#define B3_BWSCON (DW16 + WAIT + UBLB)
#define B4_BWSCON (DW16)
#define B5_BWSCON (DW16)
//#define B6_BWSCON (DW32)
//#define B7_BWSCON (DW32)
/*UP-Star2410开发板上配置的是K4S561632A是16位数据宽度32M的SDRAM*/
#define B6_BWSCON (DW16)
#define B7_BWSCON (DW16)
/* BANK0CON */
#define B0_Tacs 0x0 /* 0clk */
#define B0_Tcos 0x0 /* 0clk */
#define B0_Tacc 0x7 /* 14clk */
#define B0_Tcoh 0x0 /* 0clk */
#define B0_Tah 0x0 /* 0clk */
#define B0_Tacp 0x0
#define B0_PMC 0x0 /* normal */
/* BANK1CON */
#define B1_Tacs 0x0 /* 0clk */
#define B1_Tcos 0x0 /* 0clk */
#define B1_Tacc 0x7 /* 14clk */
#define B1_Tcoh 0x0 /* 0clk */
#define B1_Tah 0x0 /* 0clk */
#define B1_Tacp 0x0
#define B1_PMC 0x0
#define B2_Tacs 0x0
#define B2_Tcos 0x0
#define B2_Tacc 0x7
#define B2_Tcoh 0x0
#define B2_Tah 0x0
#define B2_Tacp 0x0
#define B2_PMC 0x0
#define B3_Tacs 0x0 /* 0clk */
#define B3_Tcos 0x3 /* 4clk */
#define B3_Tacc 0x7 /* 14clk */
#define B3_Tcoh 0x1 /* 1clk */
#define B3_Tah 0x0 /* 0clk */
#define B3_Tacp 0x3 /* 6clk */
#define B3_PMC 0x0 /* normal */
#define B4_Tacs 0x0 /* 0clk */
#define B4_Tcos 0x0 /* 0clk */
#define B4_Tacc 0x7 /* 14clk */
#define B4_Tcoh 0x0 /* 0clk */
#define B4_Tah 0x0 /* 0clk */
#define B4_Tacp 0x0
#define B4_PMC 0x0 /* normal */
#define B5_Tacs 0x0 /* 0clk */
#define B5_Tcos 0x0 /* 0clk */
#define B5_Tacc 0x7 /* 14clk */
#define B5_Tcoh 0x0 /* 0clk */
#define B5_Tah 0x0 /* 0clk */
#define B5_Tacp 0x0
#define B5_PMC 0x0 /* normal */
#define B6_MT 0x3 /* SDRAM */
#define B6_Trcd 0x1
#define B6_SCAN 0x1 /* 9bit */
#define B7_MT 0x3 /* SDRAM */
#define B7_Trcd 0x1 /* 3clk */
#define B7_SCAN 0x1 /* 9bit */
/* 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 */
/*根据SDRAM的datasheet,我们需要改变这里的刷新频率*/
//#define REFCNT 1113 /* period="15".6us, HCLK="60Mhz", (2048+1-15.6*60) */
#define REFCNT 0x4f4 /*period=64ms/8192=7.8125us HCLK="100MHz"*/
/**************************************/
_TEXT_BASE:
.word TEXT_BASE
.globl lowlevel_init
lowlevel_init:
/* memory control configuration */
/* make r0 relative the current location so that it */
/* reads SMRDATA out of FLASH rather than memory ! */
ldr r0, =SMRDATA
ldr r1, _TEXT_BASE
sub r0, r0, r1
ldr r1, =BWSCON /* Bus Width Status Controller */
add r2, r0, #13*4
0:
ldr r3, [r0], #4
str r3, [r1], #4
cmp r2, r0
bne 0b
/* everything is fine now */
mov pc, lr
.ltorg
/* the literal pools origin */
SMRDATA:
.word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
.word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
.word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
.word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
.word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
.word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
.word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
.word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
.word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
.word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
.word 0x32 //这个地址用来存放BANKSIZE的,注意BANK6和BANK7的大小要相同
.word 0x30
.word 0x30
.word 0x30
我想看到这,大家可以都有些“乱了”,只是看到个文件便改,却不知道这个文件时怎么调用的,或是在什么时候用到。这样,flash.c文件我们就不看了,其实它是配置Nor Flash的。Uboot的源码只支持Nor flash操作,不支持Nand Flash的操作,所以如果我们将来的系统是想从Nand Flash启动的话,就得需要我们自己来增加nand flash的操作了。这留在后面再详细讲述。我们直接进入UP-Star2410开发板的Makefile来看看。
include $(TOPDIR)/config.mk
LIB = $(obj)lib$(BOARD).a
#既然我们的文件名都改为UP-Star2410.c了,那么这里也要相应地修改
COBJS := smdk2410.o flash.o
COBJS := UP-Star2410.o flash.o
SOBJS := lowlevel_init.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
SOBJS := $(addprefix $(obj),$(SOBJS))
$(LIB): $(obj).depend $(OBJS) $(SOBJS)
$(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
clean:
rm -f $(SOBJS) $(OBJS)
distclean: clean
rm -f $(LIB) core *.bak $(obj).depend
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
好了,到此我们关于UP-Star2410的开发板文件夹就配置完了。下面我们进入include/configs目录,里面有关于开发板配置的头文件,我们还是利用smdk2410.h来复制一个我们的UP-Star2410.h,我们进来看一看
#ifndef __CONFIG_H
#define __CONFIG_H
/*
* High Level Configuration Options
* (easy to change)
*/
/*关于我们开发板的声明,至于具体的名字建议大家还是不要改,因为有很多地方会利用它们,如果修改了,一定要保证所有的都有替换*/
#define CONFIG_ARM920T 1 /* This is an ARM920T Core */
#define CONFIG_S3C2410 1 /* in a SAMSUNG S3C2410 SoC */
#define CONFIG_SMDK2410 1 /* on a SAMSUNG SMDK2410 Board */
/* input clock of PLL
*这就是上面我提到的CPU输入时钟设置
*/
#define CONFIG_SYS_CLK_FREQ 12000000/* the SMDK2410 has 12MHz input clock */
#define USE_920T_MMU 1
#undef CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
/*
* Size of malloc() pool
*/
#define CFG_MALLOC_LEN (CFG_ENV_SIZE + 128*1024)
#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
/*
* Hardware drivers
*网卡声明,SMDK2410开发板自带的是CS8900网卡,而我们的UP-Star是DM9000网卡
*等到用到的时候我们再来配置
*/
#define CONFIG_DRIVER_CS8900 1 /* we have a CS8900 on-board */
#define CS8900_BASE 0x19000300
#define CS8900_BUS16 1 /* the Linux driver does accesses as shorts */
/*
* select serial console configuration
*/
#define CONFIG_SERIAL1 1 /* we use SERIAL 1 on SMDK2410 */
/************************************************************
* RTC
************************************************************/
#define CONFIG_RTC_S3C24X0 1
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
#define CONFIG_BAUDRATE 115200
/*
* BOOTP options
*/
#define CONFIG_BOOTP_BOOTFILESIZE
#define CONFIG_BOOTP_BOOTPATH
#define CONFIG_BOOTP_GATEWAY
#define CONFIG_BOOTP_HOSTNAME
/*
* Command line configuration.
*Uboot提供的命令行,非常有用,无论是在调试还是下载都是大有帮助的
*但是初始时提供的命令很少,需要我们自己来添加,这个也放在后面再说
*/
#include <config_cmd_default.h>
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_DATE
#define CONFIG_CMD_ELF
/*系统自启动时间设定,这个可以根据自己的需要来设定,我把它改为5s*/
//#define CONFIG_BOOTDELAY 3
#define CONFIG_BOOTDELAY 5
/*下面几个宏定义是用来设置网络的,等以后我们用到网络再来改*/
/*#define CONFIG_BOOTARGS "root=ramfs devfs="mount" console="ttySA0",9600" */
/*#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_BOOTFILE "elinos-lart" */
/*#define CONFIG_BOOTCOMMAND "tftp; bootm" */
#if defined(CONFIG_CMD_KGDB)
#define CONFIG_KGDB_BAUDRATE 115200 /* speed to run kgdb serial port */
/* what's this ? it's not used anywhere */
#define CONFIG_KGDB_SER_INDEX 1 /* which serial port to use */
#endif
/*
* Miscellaneous configurable options
*/
#define CFG_LONGHELP /* undef to save memory */
/*用来设定命令行的名字,这里我改成我自己设置的开发板的名字UP-Star2410*/
//#define CFG_PROMPT "SMDK2410 # " /* Monitor Command Prompt */
#define CFG_PROMPT "UP-Star2410 # " /* Monitor Command Prompt */
#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
#define CFG_MAXARGS 16 /* max number of command args */
#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */
/*设置RAM的工作范围*/
#define CFG_MEMTEST_START 0x30000000 /* memtest works on */
//#define CFG_MEMTEST_END 0x33F00000 /* 63 MB in DRAM */
#define CFG_MEMTEST_END 0x31F00000 /* 32 MB in DRAM */
#undef CFG_CLKS_IN_HZ /* everything, incl board info, in Hz */
/*串口默认的下载地址,这里我改成0x30008000*/
//#define CFG_LOAD_ADDR 0x33000000 /* default load address */
#define CFG_LOAD_ADDR 0x30008000 /* default load address */
/* the PWM TImer 4 uses a counter of 15625 for 10 ms, so we need */
/* it to wrap 100 times (total 1562500) to get 1 sec. */
#define CFG_HZ 1562500
/* valid baudrates */
#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
/*-----------------------------------------------------------------------
* Stack sizes
*
* The stack sizes are set up in start.S using the settings below
*/
#define CONFIG_STACKSIZE (128*1024) /* regular stack */
#ifdef CONFIG_USE_IRQ
#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */
#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
#endif
/*-----------------------------------------------------------------------
* Physical Memory Map
*这就是我们再UP-Star2410.c里面最好两行用来设置SDRAM的宏定义
*/
#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
#define PHYS_SDRAM_1 0x30000000 /* SDRAM Bank #1 */
//#define PHYS_SDRAM_1_SIZE 0x04000000 /* 64 MB */
#define PHYS_SDRAM_1_SIZE 0x02000000 /* 32 MB */
#define PHYS_FLASH_1 0x00000000 /* Flash Bank #1 */
#define CFG_FLASH_BASE PHYS_FLASH_1
/*-----------------------------------------------------------------------
* FLASH and environment organization
*下面是Flash的配置,等我们用到的时候再说
*/
#define CONFIG_AMD_LV400 1 /* uncomment this if you have a LV400 flash */
#if 0
#define CONFIG_AMD_LV800 1 /* uncomment this if you have a LV800 flash */
#endif
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
#ifdef CONFIG_AMD_LV800
#define PHYS_FLASH_SIZE 0x00100000 /* 1MB */
#define CFG_MAX_FLASH_SECT (19) /* max number of sectors on one chip */
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x0F0000) /* addr of environment */
#endif
#ifdef CONFIG_AMD_LV400
#define PHYS_FLASH_SIZE 0x00080000 /* 512KB */
#define CFG_MAX_FLASH_SECT (11) /* max number of sectors on one chip */
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x070000) /* addr of environment */
#endif
/* timeout values are in ticks */
#define CFG_FLASH_ERASE_TOUT (5*CFG_HZ) /* Timeout for Flash Erase */
#define CFG_FLASH_WRITE_TOUT (5*CFG_HZ) /* Timeout for Flash Write */
#define CFG_ENV_IS_IN_FLASH 1
#define CFG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */
#endif /* __CONFIG_H */
最后,我们再来进入cpu/arm920t/start.S里面看看,这个才是Uboot启动后执行的第一个文件,不过全是用汇编来写的,大家要做好心理准备。
28 #include <config.h>
29 #include <version.h>
30 #include <status_led.h>
31
32 /*
33 *************************************************************************
34 *
35 * Jump vector table as in table 3.1 in [1]
36 *
37 *************************************************************************
38 */
39
40
41 .globl _start
42 _start: b start_code @执行的第一条语句,在110行
*************************************************************************
64 *
65 * Startup Code (called from the ARM reset exception vector)
66 *
67 * do important init only if we don't start from memory!
68 * relocate armboot to ram
69 * setup stack
70 * jump to second stage
71 *
72 *************************************************************************
78 .globl _armboot_start @第二阶段C语言的入口函数
79 _armboot_start:
80 .word _start
106 /*
107 * the actual start code
108 */
109
110 start_code:
111 /*
112 * set the cpu to SVC32 mode
113 */
114 mrs r0,cpsr
115 bic r0,r0,#0x1f
116 orr r0,r0,#0xd3
117 msr cpsr,r0
118
119 // bl coloured_LED_init @SMDK开发板上的LED,后面我们用自己的
120 // bl red_LED_on
121 /* 下面的#if…#endif之间的内容我们去掉,对我们代码的执行没有作用*/
/*********************************************************************
122 #if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
123 /*
124 * relocate exception table
125 */
126 ldr r0, =_start
127 ldr r1, =0x0
128 mov r2, #16
129 copyex:
130 subs r2, r2, #1
131 ldr r3, [r0], #4
132 str r3, [r1], #4
133 bne copyex
134 #endif
135************************************************************************/
136 #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
137 /* turn off the watchdog */
138
139 # if defined(CONFIG_S3C2400)
140 # define pWTCON 0x15300000
141 # define INTMSK 0x14400008 /* Interupt-Controller base addresses */
142 # define CLKDIVN 0x14800014 /* clock divisor register */
143 #else
144 # define pWTCON 0x53000000
145 # define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
146 # define INTSUBMSK 0x4A00001C
147 # define CLKDIVN 0x4C000014 /* clock divisor register */
148 # endif
149
150 ldr r0, =pWTCON
151 mov r1, #0x0
152 str r1, [r0]
153
154 /*
155 * mask all IRQs by setting all bits in the INTMR - default
156 */
157 mov r1, #0xffffffff
158 ldr r0, =INTMSK
159 str r1, [r0]
160 # if defined(CONFIG_S3C2410)
161 ldr r1, =0x3ff
162 ldr r0, =INTSUBMSK
163 str r1, [r0]
164 # endif
165
166 /* FCLK:HCLK:PCLK = 1:2:4 */
167 /* default FCLK is 120 MHz ! */
168 ldr r0, =CLKDIVN
169 mov r1, #3
170 str r1, [r0]
171 #endif /* CONFIG_S3C2400 || CONFIG_S3C2410 */
172 /*第一步设置完成,点亮一下我们的LED1,我这里接的是GPC5/6/7*/
#if 1
ldr r6, =0x5400
ldr r7, =0x56000020
str r6, [r7]
ldr r6, =0xc0
ldr r7, =0x56000024
str r6, [r7]
#endif
173/*
174 * we do sys-critical inits only at reboot,
175* not when booting from ram!
*用来设置CPU初始化,比如关闭MMU\Cache等
*注意:当我们再调试阶段时,也就是把UBoot装载到RAM中运行时,我们一定能
*能再初始化CPU
176 */
177 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
178 bl cpu_init_crit
179 #endif
180/*这个#ifdef和#endif也去掉*/
181 // #ifndef CONFIG_AT91RM9200
182
183 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
184 relocate: /* relocate U-Boot to RAM*/
185 adr r0, _start /* r0:当前代码的开始地址*/
186 ldr r1, _TEXT_BASE /* r1:代码段链接地址,即运行地址*/
187 cmp r0, r1 /* test if we run from flash or RAM */
188 beq stack_setup /* don't reloc during debug */
189/*如果已经在RAM中(调试时直接下载到RAM中),则不需要复制
*如果不是出于调试阶段,这段搬移代码中的r0和r1肯定不相等的,*r0=#0,r1=#TEXT_BASE: 0x33F80000(在./board/smdk2410/config.mk中),所以执行代码*的自身拷贝与搬移
*如果是调试阶段,则_start地址就是串口或网卡下载的默认地址,比如30008000
*/
190 ldr r2, _armboot_start
191 ldr r3, _bss_start
192 sub r2, r3, r2 /* r2 <- size of armboot */
193 add r2, r0, r2 /* r2 <- source end address */
194
195 copy_loop:
196 ldmia r0!, {r3-r10} /* copy from source address [r0] */
197 stmia r1!, {r3-r10} /* copy to target address [r1] */
198 cmp r0, r2 /* until source end addreee [r2] */
199 ble copy_loop
200 // #endif /* CONFIG_SKIP_RELOCATE_UBOOT */
201 #endif
202 /* Set up the stack */
203 stack_setup:
204 ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
205 sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
206 sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
207 #ifdef CONFIG_USE_IRQ
208 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
209 #endif
210 sub sp, r0, #12 /* leave 3 words for abort-stack */
211/*堆栈设置完成,准备调用第二阶段的C语言,我们再来点亮一个LED2*/
#if 1
ldr r6, =0x5400
ldr r7, =0x56000020
str r6, [r7]
ldr r6, =0xa0
ldr r7, =0x56000024
str r6, [r7]
#endif
212 clear_bss:
213 ldr r0, _bss_start /* find start of bss segment */
214 ldr r1, _bss_end /* stop here */
215 mov r2, #0x00000000 /* clear */
216
217 clbss_l:str r2, [r0] /* clear loop... */
218 add r0, r0, #4
219 cmp r0, r1
220 ble clbss_l
221 /*在进入C语言前,我们再来点亮一下LED3*/
#if 1
ldr r6, =0x5400
ldr r7, =0x56000020
str r6, [r7]
ldr r6, =0x80
ldr r7, =0x56000024
str r6, [r7]
#endif
222 ldr pc, _start_armboot
223
224 _start_armboot: .word start_armboot
225
226
227 /*
228 *************************************************************************
229 *
230 * CPU_init_critical registers
231 *
232 * setup important registers
233 * setup memory timing
234 *
235 *************************************************************************
236 */
237
238
239 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
240 cpu_init_crit:
241 /*
242 * flush v4 I/D caches
243 */
244 mov r0, #0
245 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
246 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
247
248 /*
249 * disable MMU stuff and caches
250 */
251 mrc p15, 0, r0, c1, c0, 0
252 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
253 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
254 orr r0, r0, #0x00000002 @ set bit 2 (A) Align
255 orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
256 mcr p15, 0, r0, c1, c0, 0
257
258 /*
259 * before relocating, we have to setup RAM timing
260 * because memory timing is board-dependend, you will
261 * find a lowlevel_init.S in your board directory.
262 */
263 mov ip, lr
/*再次去掉#if、#else和#endif*/
264 //#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
265
266 //#else
267 bl lowlevel_init
268 ///#endif
269 mov lr, ip
270 mov pc, lr
271 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
现在我们再回到根目录,修改Makefile。关于根目录的Makefile的介绍,大家可以参考其他相关的资料,这里我就不再赘述了,如果有问题欢迎给我留言,我尽量帮大家来解答。
在Makefile中有关于CPU分类的开发板配置文件,我们在其中第2494行找到smdk2410对应的配置项
smdk2410_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
修改如下
UP-Star2410_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t UP-Star2410 NULL s3c24x0
现在,我们的Uboot就可以编译了,目前具备的功能只有串口,而且还只能在RAM上运行。总结一下我们之前做过的配置,首先我们要建立一个自己的开发板目录,然后先针对CPU进行一下修改,这里我们用的是S3C2410,正是Uboot的默认配置,所以不需要修改,如果是S3C2440或者是其他CPU就需要修改了。然后就是配置开发板的时钟、SDRAM的配置,另外,如果是从Nor Flash上启动,好需要配置一下Nor Flash(由于我的板子上没有,所有没有写,需要的话也欢迎讨论)。经过以上的一些配置,正常情况一个最基本的Uboot就移植完成,但是功能太过简单,有失Uboot的身份,呵呵。剩下的工作就留在下一篇博文吧。
P.S没想到一下写了这么多,连上传都得分好几次等10分钟~
用户1664007 2010-4-11 11:39