目
board
cpu
lib_arm
include
common
lib_generic
net
fs
post
drivers
disk
rtc
dtt
examples
tools
2.
Makefile
#!/bin/sh -e
#获得参数,开发板名字
APPEND=no
BOARD_NAME=""
while [ $# -gt 0 ] ; do
done
[ "${BOARD_NAME}" ] || BOARD_NAME="$1"
#${BOARD_NAME}即为开发板名称smdk6410
[ $# -lt 4 ] && exit 1
[ $# -gt 6 ] && exit 1
echo "Configuring for ${BOARD_NAME} board..."
#创建平台/开发板头文件链接
if [ "$SRCTREE" != "$OBJTREE" ] ; then
else
fi
rm -f asm-$2/arch
if [ "$3" = "s3c64xx" ] ; then
fi
if [ "$2" = "arm" ] ; then
fi
#创建include/config.mk配置文件
echo "ARCH
echo "CPU
echo "BOARD
[ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk
[ "$6" ] && [ "$6" != "NULL" ] && echo "SOC
#创建头文件include/config.h
if [ "$APPEND" = "yes" ]
then
else
fi
echo "" >>config.h
echo "#include <configs/$1.h>" >>config.h
#头文件内容
exit 0
makefile详解
VERSION = 1
PATCHLEVEL = 1
SUBLEVEL = 6
EXTRAVERSION =
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) #1.1.6版本
VERSION_FILE = $(obj)include/version_autogenerated.h
#HOSTARCH 使用主机的环境(硬件)
HOSTARCH := $(shell uname -m | \
#HOSTOS 主机的操作系统
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
export
VENDOR=
#方法1
ifdef O
ifeq ("$(origin O)", "command line") #如果是在命令行定义的变量‘O’,$(origin O)就是得到‘O’的定义来源
BUILD_DIR := $(O)
endif
endif
#方法2
ifneq ($(BUILD_DIR),)
saved-output := $(BUILD_DIR)
$(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR})#在shell中判断${BUILD_DIR}目录是否存在,如果不存在就建目录
BUILD_DIR := $(shell cd $(BUILD_DIR) && /bin/pwd)
#在shell如果打开${BUILD_DIR}目录就调用PWD显示当前路径,将该路径赋值给 BUILD_DIR
$(if $(BUILD_DIR),,$(error output directory "$(saved-output)" does not exist))#如果$(BUILD_DIR)为空,输出错误信息
endif
#OBJTREE LNDIR生成文件目录 SRCTREE TOPDIR源码目录
OBJTREE
#方法3 如果$(BUILD_DIR)为空,将$(CURDIR)赋给OBJTREE,非空就将$(BUILD_DIR)赋给OBJTREE
SRCTREE
TOPDIR
LNDIR
export
#MKCONFIG指向源码所在目录下的mkconfig配置文件
MKCONFIG
export MKCONFIG
ifneq ($(OBJTREE),$(SRCTREE)) #如果目标文件存放目录不是U-BOOT顶层目录,定义一个标志变量
REMOTE_BUILD
export REMOTE_BUILD
endif
ifneq ($(OBJTREE),$(SRCTREE))#如果目标文件存放目录不是U-BOOT顶层目录,定义obj src
obj := $(OBJTREE)/
src := $(SRCTREE)/
else
obj :=
src :=
endif
export obj src
ifeq ($(OBJTREE)/include/config.mk,$(wildcard $(OBJTREE)/include/config.mk))#判断config.mk文件是否存在,如果存在就执行下去,如果不存在就要执行者make xxx.config来生成该文件
#执行config.mk,加载ARCH BAORD CPU配置
include $(OBJTREE)/include/config.mk
export
#根据硬件结构指定交叉编译器
ifeq ($(ARCH),arm)
CROSS_COMPILE = arm-linux-
endif
export
#加载其他设置,include顶层目录下的config.mk配置文件(定义了交叉编译器 定义了编译选项 定义了编译规则)
include $(TOPDIR)/config.mk
#start.o必须放在第一位,u-boot执行的第一段代码为start.S
OBJS
#加前缀函数 就是在$(OBJS)变量的前面加上$(obj),相当于获得准确的路径
OBJS := $(addprefix $(obj),$(OBJS))
#一下为编译u-boot需要的库文件
LIBS
LIBS += board/$(BOARDDIR)/lib$(BOARD).a
LIBS += cpu/$(CPU)/lib$(CPU).a
LIBS += cpu/$(CPU)/$(SOC)/lib$(SOC).a
LIBS += lib_$(ARCH)/lib$(ARCH).a
LIBS += fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a \
LIBS += net/libnet.a
LIBS += disk/libdisk.a
LIBS += rtc/librtc.a
LIBS += dtt/libdtt.a
LIBS += drivers/libdrivers.a
LIBS += drivers/nand/libnand.a
LIBS += drivers/nand_legacy/libnand_legacy.a
LIBS += drivers/onenand/libonenand.a
LIBS += drivers/sk98lin/libsk98lin.a
LIBS += post/libpost.a post/cpu/libcpu.a
LIBS += common/libcommon.a
LIBS += $(BOARDLIBS)
LIBS := $(addprefix $(obj),$(LIBS))
#.PHONY定义一个伪目标,$(LIBS)该目标是一个永远不会存在的文件(like make clean规则中的clean文件),不会建立该文件
.PHONY : $(LIBS)
#添加GCC库文件
PLATFORM_LIBS += -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc
#伪目标用于执行tools examples post post/cpu下的makefile
SUBDIRS
.PHONY : $(SUBDIRS)
ifeq ($(CONFIG_NAND_U_BOOT),y)
NAND_SPL = nand_spl
U_BOOT_NAND = $(obj)u-boot-nand.bin
endif
__OBJS := $(subst $(obj),,$(OBJS))
__LIBS := $(subst $(obj),,$(LIBS))
#这里为最终要生成的各种镜像文件
ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND)
all:
$(obj)u-boot.hex:
$(obj)u-boot.srec:
$(obj)u-boot.bin:
$(obj)u-boot.img:
$(obj)u-boot.dis:
#此处生成的是uboot的ELF文件镜像
$(obj)u-boot:
#依赖目标$(OBJS),也就是cpu/start.o
$(OBJS):
#依赖目标$(LIBS),每个子目录下的*.a,通过执行相应子目录下的make来完成
$(LIBS):
$(SUBDIRS):
$(NAND_SPL):
$(U_BOOT_NAND):
#生程版本文件
version:
gdbtools:
updater:
env:
depend dep:
tags ctags:
etags:
$(obj)System.map:
#########################################################################
else
all $(obj)u-boot.hex $(obj)u-boot.srec $(obj)u-boot.bin \
$(obj)u-boot.img $(obj)u-boot.dis $(obj)u-boot \
$(SUBDIRS) version gdbtools updater env depend \
dep tags ctags etags $(obj)System.map:
endif
.PHONY : CHANGELOG
CHANGELOG:
#unconfig清楚生成的配置文件
unconfig:
#make smdk6410_config相当与执行./mkconfig smdk6410(开发板名) arm(arch架构) s3c64xx(cpu) smdk6410(开发板) samsung(开发商) s3c6410(soc)
smdk6410_config
clean:
clobber:
ifeq ($(OBJTREE),$(SRCTREE))
mrproper \
distclean:
else
mrproper \
distclean:
endif
backup:
#########################################################################
u-boot第一阶段代码分析
/board/samsung/sdmk6410/u-boot.lds得知U-boot首先执行/cpu/s3c64xx/start.S
start.S
1.reset将CPU的模式设置为管理模式(svc)
2.cpu_init_crit初始化CPU的关键寄存器
关闭MMU和catch
重映射SFR(特殊功能寄存器的地址)
关闭看门狗 关中断
3.跳转到lowlevel_init(/board/samsung/sdmk6410/lowlevel_init.S)设置系统时钟
4.复制第二阶段代码到SDRAM中(使能mmu)
5.设置栈,即确定内存的使用情况
6.跳转到第二阶段的C程序代码入口(/lib_arm/board.c)
注意:/include/configs/smdk6410.h定义了开发板的配置信息(前缀为CONFIG_和CFG_宏)
u-boot.lds 文件说明
OUTPUT_FORMAT("elf32littlearm", "elf32littlearm", "elf32littlearm");指定输出可执行文件是 elf 格式,32 位 ARM 指令,小端
OUTPUT_ARCH(arm);指定输出可执行文件的平台为 ARM
ENTRY(_start);指定输出可执行文件的起始代码段为_start.
SECTIONS
{
}
idea6410开发板u-boot1.1.6移植dm9000a驱动
首先,从http://ftp.denx.de/pub/u-boot/下载u-boot-2010.06.tar.bz2,解压后用u-boot-2010.06/driver/net中的dm9000x.c和dm9000x.h替换友坚u-boot driver目录下的dm9000x.c和dm9000x.h,并将u-boot-2010.06/include/目录下的dm9000.h拷贝到友坚u-boot include目录下。
其次,修改/include/configs/smdk6410.h,将
再次,修改/board/samsung/smdk6410/smdk6410.c文件,将文件中的CS8900字符全部替换为dm9000
然后,在/net/eth.c中添加
{
#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
#endif
#if defined(CONFIG_DRIVER_DM9000)
#endif
}
最后,按照手册编译生成u-boot-nand.bin文件
方法二:
前两天在6410开发板上玩了玩u-boot,开发板是友坚的6410开发板,配套的光盘中给的是很古老的u-boot 1.1.6,而且没有网络支持。从网上下了个最新的uboot-2010.06版本,看了下发现它并不支持6410的SD卡启动模式,本来是想移植下,使得新版本也支持SD卡启动,但现在时间很紧张,没那么多时间慢慢玩了,于是就想把dm9000弄上去。
本来以为dm9000这类的大白菜,uboot肯定是一切ok了,但google了下,发现有人说低版本的uboot带的dm9000x.c驱动是不支持dm9000a的,只支持比较老的dm9000x。于是看linux 2.6.32内核代码,发现有dm9000驱动,对比了下,也没觉得有多大差别,为了省事,又看了下uboot2010.06版本里面的dm9000驱动。看注释,发现它已经支持dm9000ae了。于是直接拷贝过来,替换原先的dm9000x.c。
在include/configs/smdk6410.h中添加
#define CONFIG_DRIVER_DM9000 1
#define CONFIG_DM9000_BASE 0X18000300
#define DM9000_IO CONFIG_DM9000_BASE
#define DM9000_DATA (CONFIG_DM9000_BASE+4)
#define CONFIG_DM9000_NO_SROM 1
注销其他网卡芯片的支持,比如//#define CONFIG_DRIVER_SMC911X 1 /* we have a SMC9115 on-board */
再添加:
#define CONFIG_NET_MULTI 1
修改board/smdk6410.c
本来里面好像是cs8900的,所以里面有这么一些与cs8900相关的代码:
#define CS8900_Tacs (0x0) // 0clk address set-up
#define CS8900_Tcos (0x4) // 4clk chip selection set-up
#define CS8900_Tacc (0xE) // 14clk access cycle
#define CS8900_Tcoh (0x1) // 1clk chip selection hold
#define CS8900_Tah (0x4) // 4clk address holding time
#define CS8900_Tacp (0x6) // 6clk page mode access cycle
#define CS8900_PMC (0x0) // normal(1data)page mode configuration
static void cs8900_pre_init(void)
{
SROM_BW_REG &= ~(0xf << 4);
SROM_BW_REG |= (1<<7) | (1<<6) | (1<<4);
SROM_BC1_REG = ((CS8900_Tacs<<28)+(CS8900_Tcos<<24)+(CS8900_Tacc<<16)+(CS8900_Tcoh<<12)+(CS8900_Tah<<8)+(CS8900_Tacp<<4)+(CS8900_PMC));
}
int board_init(void)
{
DECLARE_GLOBAL_DATA_PTR;
cs8900_pre_init();//改为dm9000_pre_init
gd->bd->bi_arch_number = MACH_TYPE;
gd->bd->bi_boot_params = (PHYS_SDRAM_1+0x100);
#if 0
icache_enable();
dcache_enable();
#endif
return 0;
}
把所有cs8900改为dm9000,代码是不需要改的,对照s3c6410手册,这块memory访问的配置是没问题。这个开发板是用的是16bit的模式,所以确认cs8900_pre_init确实是把总线初始化为16bit模式的。
在net/eth.c中添加
extern int dm9000_initialize(bd_t*);
int eth_initialize(bd_t *bis)
{
char enetvar[32], env_enetaddr[6];
int i, eth_number = 0;
char *tmp, *end;
eth_devices = NULL;
eth_current = NULL;
#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
miiphy_init();
#endif
#if defined(CONFIG_DRIVER_DM9000)
dm9000_initialize(bis);//这是我添加的
#endif
#if defined(CONFIG_DB64360) || defined(CONFIG_CPCI750)
mv6436x_eth_initialize(bis);
#endif
编译测试。顺便说下,这个工作看起来是简单的,但仍然碰到一些问题,花了两天时间才搞定。特别开始的时候忘记定义#define CONFIG_DM9000_NO_SROM 1
结果导致每次mac地址都不对,后来看了下代码,才发现如果没有定义CONFIG_DM9000_NO_SROM,则uboot会从eeprom中读mac地址,dm9000是支持eeprom接口的,但友坚开发板上并没有用这个功能,所以需要设置CONFIG_DM9000_NO_SROM。
还遇到个恶心的问题,就是ping不通,一会说checksum bad,一会又是无任何提示的,直接给出”host is not active“。这个问题足足浪费我一天时间,最后发现是防火墙问题,把系统防火墙关闭就正常。不过我在另一台台式机上测试,防火墙开了也没啥影响,就是在我这台笔记本上不行。
bluehacker
实验过程
ubuntu9.04配置tftp
1:在新立得软件包管理器中安装 xinetd, tftpd, tftp.
2:在/etc/xinetd.d/下增加一个文件,名为tftp,内容如下:
service tftp
{
}
3:进入目录/etc/init.d/中,重新启动xinetd
sudo ./xinetd restart
4:到根目录创建文件夹 /tftproot,并将权限设置为777
sudo mkdir /tftproot
sudo chmod 777 /tftproot
5:将生成的内核镜像zImage拷贝到/tftproot目录下
6:主机ip地址192.168.1.20
设置u-boot启动参数
#setenv bootcmd tftp 0xc0008000 zImage\;bootm 0xc0008000
#setenv bootargs "root=/dev/nfs nfsroot=192.168.1.10:/home/yangze/nfs_share ip=192.168.1.20:192.168.1.10:192.168.1.1:255.255.255.0:www.urbetter.com:eth0:off console=ttySAC0,115200"
#saveenv
实验结果
OK
U-Boot 1.1.6 (Jun
****************************************
**
**
**
****************************************
CPU:
Board:
DRAM:
Flash:
NAND:
In:
Out:
Err:
Net:
Hit any key to stop autoboot:
dm9000 i/o: 0x18000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: c7e32ff8M
operating at 100M full duplex mode
Using dm9000 device
TFTP from server 192.168.1.10; our IP address is 192.168.1.20
Filename 'zImage'.
Load address: 0xc0008000
Loading: checksum bad
T #################################################################
done
Bytes transferred = 2088756 (1fdf34 hex)
Boot with zImage
Starting kernel ...
Uncompressing Linux........................................................................................................................................ done, booting the kernel.
Linux version 2.6.28.6 (yangze@ubuntu) (gcc version 4.2.2) #60 Tue Dec 14 16:29:29 CST 2010
CPU: ARMv6-compatible processor [410fb766] revision 6 (ARMv7), cr=00c5387f
CPU: VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
Machine: SMDK6410
TFTP内核镜像文件到sdram,NFS根文件系统,linux启动完成
这个网上有DM9000A的驱动,只要替换对应的driver/dm9000.c 和driver/dm9000.h即可,但是发现只有在使用ping命令(发送数据包)的时候,对应的网卡才会激活,而一旦ping结束后,那么网卡就会自动断掉,查看代码发现在do_ping时会做eth_init,而结束后会做eth_close动作
所以在start_armboot函数中加入初始化动作:eth_init(gd->bd); 并注释掉eth_close动作即可。
http://blog.sina.com.cn/u/1241837852
友坚恒天已经正式推出了exynos 4412开发板~