详细讲解 移植Uboot到ARMer9开发系统上
扫描二维码
随时随地手机看文章
首先了解ARMer9开发系统硬件设计上和三星原装SMDK2410之间的区别。让uboot在ARMer9开发系统上跑起来,目前只需要关注如下的硬件区别,解决了下面这个问题,uboot就可以在ARMer9开发系统上正常地从串口输出,进入提示符。很多命令都可以使用,当然有些命令需要做修改。
SMDK2410 : nor flash 是AMD的1M的;
ARMer9: 是Intel E28F128J3A, 两片并联,一共32M Bytes.
下载一个uboot-1.1.1.tar.bz2.;
tar jxvf uboot-1.1.1.tar.bz2;
在uboot 目录board/smdk2410 下的flash.c需要修改。这个是Flash的驱动,如何写,需要参考E28F128J3A的Datasheet. 这里我们提供一个我们修改好的flash.c文件,您只需要将这个文件覆盖掉board/smdk2410 下的文件即可。
(注意:你要安装了交叉编译器才行哦)
修改uboot目录下的Makefile,将
ifeq ($(ARCH),arm)
CROSS_COMPILE = arm-linux-
endif
修改成
ifeq ($(ARCH),arm)
CROSS_COMPILE = /opt/host/armv4l/bin/armv4l-unknown-linux-
endif
修改processor.h中:
union debug_insn
{
u32 arm;
u16 thumb;
}
修改成:
union debug_insn
{
u32 arm_mode;
u16 thumb_mode;
}
然后配置板子
make smdk2410_config
然后
make
在uboot目录生成uboot.bin;
通过sjf2410w程序将uboot.bin下载到nor flash中, 地址为0的地方;
串口接在UART0上,uboot的启动信息将输出。
你将发现很多命令都可以使用了。uboot果然强大。
关于网络部分,因为ARMer9开发系统使用也是CS8900A,所以代码部分几乎不用做改动,只需要在 include/configs/smdk2410.h中看看,有没有定义CONFIG_ETHADDR,CONFIG_IPADDR, CONFIG_SERVERIP这些宏没有,如果没有,请定义好。
#define CONFIG_ETHADDR 00:00:e0:ff:cd:15
#define CONFIG_IPADDR 192.168.0.5
#define CONFIG_SERVERIP 192.168.0.100
就这样修改一下,网络部分功能就通了,哈哈。
可以使用tftpboot命令从tftp服务器下载程序到系统内存中。
#tftpboot 0x33000000 zImage
#bootm 0x33000000
利用uboot引导可执行映象的通用方法
uboot源代码的tools/目录下有mkimage工具,这个工具可以用来制作不压缩或者压缩的多种可启动映象文件。
mkimage在制作映象文件的时候,是在原来的可执行映象文件的前面加上一个0x40字节的头,记录参数所指定的信息,这样uboot才能识别这个映象是针对哪个CPU体系结构的,哪个OS的,哪种类型,加载内存中的哪个位置, 入口点在内存的那个位置以及映象名是什么
root@Glym:/tftpboot# ./mkimage
Usage: ./mkimage -l image
-l ==> list image header information
./mkimage -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
-A ==> set architecture to 'arch'
-O ==> set operating system to 'os'
-T ==> set image type to 'type'
-C ==> set compression type 'comp'
-a ==> set load address to 'addr' (hex)
-e ==> set entry point to 'ep' (hex)
-n ==> set image name to 'name'
-d ==> use image data from 'datafile'
-x ==> set XIP (execute in place)
参数说明:
-A 指定CPU的体系结构:
取值 表示的体系结构
alpha Alpha
arm A RM
x86 Intel x86
ia64 IA64
mips MIPS
mips64 MIPS 64 Bit
ppc PowerPC
s390 IBM S390
sh SuperH
sparc SPARC
sparc64 SPARC 64 Bit
m68k MC68000
-O 指定操作系统类型,可以取以下值:
openbsd、netbsd、freebsd、4_4bsd、linux、svr4、esix、solaris、irix、sco、dell、ncr、lynxos、vxworks、psos、qnx、u-boot、rtems、artos
-T 指定映象类型,可以取以下值:
standalone、kernel、ramdisk、multi、firmware、script、filesystem
-C 指定映象压缩方式,可以取以下值:
none 不压缩
gzip 用gzip的压缩方式
bzip2 用bzip2的压缩方式
-a 指定映象在内存中的加载地址,映象下载到内存中时,要按照用mkimage制作映象时,这个参数所指定的地址值来下载
-e 指定映象运行的入口点地址,这个地址就是-a参数指定的值加上0x40(因为前面有个mkimage添加的0x40个字节的头)
-n 指定映象名
-d 指定制作映象的源文件
常用U-BOOT命令介绍
1. ?或者help,得到所有命令列表;
2. help: help usb, 列出USB功能的使用说明
3. ping:注:通常只能运行uboot的系统PING别的机器
4. setenv: 设置环境变量
setenv serverip 10.36.20.49,设置TFTP Server的IP地址;
setenv ipaddr 10.36.20.200,设置IP地址;
setenv bootcmd ‘tftp 32000000 vmlinux; kgo 32000000’,设置启动命令(实际上就是一个脚本);
5. saveenv:在设置好环境变量以后, 保存环境变量值到flash中间;
6. tftpboot:tftpboot 0x800000 vmlinux, 将TFTP Server(IP = 环境变量中设置的serverip)中/tftpdroot目录 下的vmlinux通过TFTP协议下载到物理内存0x800000开始的地方。
7. kgo:启动没有压缩的linux内核,kgo 0x800000
8. bootm:启动通过UBOOT TOOLS—— mkimage制作的压缩LINUX内核, bootm 3200000;
9 flinfo:列出flash的信息
10. protect: 对FLASH进行写保护或取消写保护, protect on 1:0-3(就是对第一块FLASH的0-3扇区进行保护),protect off 1:0-3取消写保护
11. erase: 删除FLASH的扇区, erase 1:0-2(就是对每一块FLASH的0-2扇区进行删除)
12. cp: 将内存中数据烧写到Flash, cp 0x800000 0xc0000 0x40000(把内存中0x800000开始的0x40000字节复制到0xc0000处);
13. mw: 对RAM中的内容进行写操作, mw 32000000 ff 10000(把内存0x32000000开始的0x10000字节设为0xFF);
14. md: 显示RAM中的内容, md 0x800000;
15. loadb: 准备用 KERMIT协议接收来自kermit或超级终端传送的文件。
16. nfs: nfs 32000000 192.168.0.2:aa.txt , 把192.168.0.2(LINUX 的NFS文件系统)中的NFS文件系统中的aa.txt 读入内存0x32000000处。
17. fatls:列出DOS FAT文件系统, 如:fatls usb 0列出第一块U盘中的文件
18. fatload: 读入FAT中的一个文件,如:fatload usb 0:0 32000000 aa.txt
19. usb相关的命令:
usb start: 起动usb 功能
usb info: 列出设备
usb scan: 扫描usb storage(u 盘)设备
Uboot对SMDK2410板的NAND Flash初始化部分没有写,
即lib_arm/board.c中的start_armboot函数中有这么一句:
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
puts ("NAND:");
nand_init(); /* go init the NAND */
#endif
但是在board/smdk2410目录下任何源文件中都没有定义nand_init这个函数。
所以需要我们补充这个函数以及这个函数涉及的底层操作。
我们可以仿照VCMA9板的nand_init函数,VCMA9板是一款用S3C2410做CPU的DEMO Board,因此这部分操作和SMDK2410 Demo Board很相似。大部分代码可以照搬。
首先将board/mpl/vcma9/vcma9.c中下面代码拷贝到board/smdk2410/ smdk2410.c中来。
/*
* NAND flash initialization.
*/
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
extern ulong
nand_probe(ulong physadr);
static inline void NF_Reset(void)
{
int i;
NF_SetCE(NFCE_LOW);
NF_Cmd(0xFF); /* reset command */
for(i = 0; i < 10; i++); /* tWB = 100ns. */
NF_WaitRB(); /* wait 200~500us; */
NF_SetCE(NFCE_HIGH);
}
static inline void NF_Init(void)
{
#if 0 /* a little bit too optimistic */
#define TACLS 0
#define TWRPH0 3
#define TWRPH1 0
#else
#define TACLS 0
#define TWRPH0 4
#define TWRPH1 2
#endif
NF_Conf((1<<15)|(0<<14)|(0<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0));
/*nand->NFCONF = (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0); */
/* 1 1 1 1, 1 xxx, r xxx, r xxx */
/* En 512B 4step ECCR nFCE=H tACLS tWRPH0 tWRPH1 */
NF_Reset();
}
void
nand_init(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
NF_Init();
#ifdef DEBUG
printf("NAND flash probing at 0x%.8lXn", (ulong)nand);
#endif
printf ("%4lu MBn", nand_probe((ulong)nand) >> 20);
}
#endif
再将board/mpl/vcma9/vcma9.h中下面代码拷贝到board/smdk2410/ smdk2410.c中来。
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
typedef enum {
NFCE_LOW,
NFCE_HIGH
} NFCE_STATE;
static inline void NF_Conf(u16 conf)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFCONF = conf;
}
static inline void NF_Cmd(u8 cmd)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFCMD = cmd;
}
static inline void NF_CmdW(u8 cmd)
{
NF_Cmd(cmd);
udelay(1);
}
static inline void NF_Addr(u8 addr)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFADDR = addr;
}
static inline void NF_SetCE(NFCE_STATE s)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
switch (s) {
case NFCE_LOW:
nand->NFCONF &= ~(1<<11);
break;
case NFCE_HIGH:
nand->NFCONF |= (1<<11);
break;
}
}
static inline void NF_WaitRB(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
while (!(nand->NFSTAT & (1<<0)));
}
static inline void NF_Write(u8 data)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFDATA = data;
}
static inline u8 NF_Read(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
return(nand->NFDATA);
}
static inline void NF_Init_ECC(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFCONF |= (1<<12);
}
static inline u32 NF_Read_ECC(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
return(nand->NFECC);
}
#endif
再将include/configs/vcma.9中下面代码拷贝到include/configs/smdk2410.h中来。
/*-----------------------------------------------------------------------
* NAND flash settings
*/
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#define CFG_MAX_NAND_DEVICE 1 /* Max number of NAND devices */
#define SECTORSIZE 512
#define ADDR_COLUMN 1
#define ADDR_PAGE 2
#define ADDR_COLUMN_PAGE 3
#define NAND_ChipID_UNKNOWN 0x00
#define NAND_MAX_FLOORS 1
#define NAND_MAX_CHIPS 1
#define NAND_WAIT_READY(nand) NF_WaitRB()
#define NAND_DISABLE_CE(nand) NF_SetCE(NFCE_HIGH)
#define NAND_ENABLE_CE(nand) NF_SetCE(NFCE_LOW)
#define WRITE_NAND_COMMAND(d, adr) NF_Cmd(d)
#define WRITE_NAND_COMMANDW(d, adr) NF_CmdW(d)
#define WRITE_NAND_ADDRESS(d, adr) NF_Addr(d)
#define WRITE_NAND(d, adr) NF_Write(d)
#define READ_NAND(adr) NF_Read()