手机qq怎么群发:u-boot-2009.08在mini2440上的移植

来源:百度文库 编辑:偶看新闻 时间:2024/05/09 18:23:03
u-boot-2009.08在mini2440上的移植

爱丫爱丫 发表于 2011-11-11 23:49:09



移植环境
1,主机环境:VMare下CentOS 5.5 ,1G内存。
2,集成开发环境:Elipse IDE
3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-eabi-gcc v4.5.1。
4,开发板:mini2440,2M nor flash,128M nand flash。
5,u-boot版本:u-boot-2009.08

u-boot-2009.08版本已经对CS8900、RTL8019和DM9000X等网卡有比较完善的代码支持(代码在drivers/net/目录下),而且在S3C24XX系列中默认对CS8900网卡进行配置使用。而mini2440开发板使用的则是DM9000网卡芯片,所以只需在开发板上添加对DM9000的支持即可。还有一点,以前的 U-boot 对于网络延时部分有问题,需要修改许多地方。但是现在的U-boot 网络
部分已经基本不需要怎么修改了,只有在DM9000 的驱动和NFS 的TIMEOUT 参数上需要稍微修改一下。
4.1,DM9000驱动代码修改
【1】修改static int dm9000_init函数中部分代码,如果不修改这一部分,在使用网卡的时候会报“could not establish link”的错误。
打开/drivers/net/dm9000x.c,定位到377行,修改如下:
/* Activate DM9000 */
/* RX enable */
DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
/* Enable TX/RX interrupt mask */
DM9000_iow(DM9000_IMR, IMR_PAR);
#if 0 //default to link MII interface
i = 0;
while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */
udelay(1000);
i++;
if (i == 1650) {
//printf("could not establish link\n");
//return 0;
break;
}
}
#endif
【2】对于NFS,增加了延时,否则会出现“*** ERROR: Cannot mount”的错误。
打开/net/nfs.c,定位到36行,修改如下:
#if defined(CONFIG_CMD_NET) && defined(CONFIG_CMD_NFS)
#define HASHES_PER_LINE 65 /* Number of "loading" hashes per line */
#define NFS_RETRY_COUNT 30
#define NFS_TIMEOUT (CONFIG_SYS_HZ/1000*2000UL) //2000UL
【3】添加网卡芯片(DM9000)的初始化函数
打开board/samsung/mini2440/mini2440.c,定位到194行附近,文件末尾处,修改如下:
int dram_init (void)
{
gd->bd->bi_dram.start = PHYS_SDRAM_1;
gd->bd->bi_dram.size = PHYS_SDRAM_1_SIZE;
return 0;
}
extern int dm9000_initialize(bd_t *bis);//implicit declaration of function 'dm9000_initialize'
#ifdef CONFIG_DRIVER_DM9000
int board_eth_init(bd_t *bis)
{
return dm9000_initialize(bis);
}
#endif
【4】添加串口 Xmodem 传输协议(可不修改)
对于使用串口传输数据到内存的操作,有可能会用到Xmodem协议。但是原本的kermit协议传输就挺好用的,速度也比较快,所以可添加此功能。
打开/common/cmd_load.c,定位到37行,修改如下:
#if defined(CONFIG_CMD_LOADB)
#if defined(ENABLE_CMD_LOADB_X)
static ulong load_serial_xmodem (ulong offset);
#endif
static ulong load_serial_ymodem (ulong offset);
#endif
然后再定位到480行附近,修改如下:
if (load_baudrate != current_baudrate) {
printf ("## Switch baudrate to %d bps and press ENTER ...\n",
load_baudrate);
udelay(50000);
gd->baudrate = load_baudrate;
serial_setbrg ();
udelay(50000);
for (;;) {
if (getc() == '\r')
break;
}
}
#if defined(ENABLE_CMD_LOADB_X)
if (strcmp(argv,"loadx")==0) {
printf ("## Ready for binary (xmodem) download "
"to 0x%08lX at %d bps...\n",
offset,
load_baudrate);
addr = load_serial_xmodem (offset);
} else if (strcmp(argv,"loady")==0) {
#else
if (strcmp(argv,"loady")==0) {
#endif
printf ("## Ready for binary (ymodem) download "
"to 0x%08lX at %d bps...\n",
offset,
load_baudrate);
addr = load_serial_ymodem (offset);
再定位到998行附近,修改如下:
static int getcxmodem(void) {
if (tstc())
return (getc());
return -1;
}
#if defined(ENABLE_CMD_LOADB_X)
static ulong load_serial_xmodem (ulong offset)
{
int size;
char buf;
int err;
int res;
connection_info_t info;
char xmodemBuf;
ulong store_addr = ~0;
ulong addr = 0;
size = 0;
info.mode = xyzModem_xmodem;
res = xyzModem_stream_open (&info, &err);
if (!res) {
while ((res =
xyzModem_stream_read (xmodemBuf, 1024, &err)) > 0) {
store_addr = addr + offset;
size += res;
addr += res;
#ifndef CFG_NO_FLASH
if (addr2info (store_addr)) {
int rc;
rc = flash_write ((char *) xmodemBuf,
store_addr, res);
if (rc != 0) {
flash_perror (rc);
return (~0);
}
} else
#endif
{
memcpy ((char *) (store_addr), xmodemBuf,
res);
}
}
} else {
printf ("%s\n", xyzModem_error (err));
}
xyzModem_stream_close (&err);
xyzModem_stream_terminate (false, &getcxmodem);

flush_cache (offset, size);
printf ("## Total Size = 0x%08x = %d Bytes\n", size, size);
sprintf (buf, "%X", size);
setenv ("filesize", buf);
return offset;
}
#endif
static ulong load_serial_ymodem (ulong offset)
再定位到1169行,修改如下:
#if defined(CONFIG_CMD_LOADB)
U_BOOT_CMD(
loadb, 3, 0, do_load_serial_bin,
"load binary file over serial line (kermit mode)",
"[ off ] [ baud ]\n"
" - load binary file over serial line"
" with offset 'off' and baudrate 'baud'"
);
#if defined(ENABLE_CMD_LOADB_X)
U_BOOT_CMD(
loadx, 3, 0, do_load_serial_bin,
"load binary file over serial line (xmodem mode)",
"[ off ] [ baud ]\n"
" - load binary file over serial line"
" with offset 'off' and baudrate 'baud'"
);
#endif
U_BOOT_CMD(
loady, 3, 0, do_load_serial_bin,
"load binary file over serial line (ymodem mode)",
"[ off ] [ baud ]\n"
" - load binary file over serial line"
" with offset 'off' and baudrate 'baud'"
);
【5】修改配置文件,在mini2440.h中加入相关定义
打开/include/configs/mini2440.h,定位到60行附近,修改如下:
/*
* Hardware drivers
*/
#if 0
#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 */
#endif
#define CONFIG_NET_MULTI 1
#define CONFIG_DRIVER_DM9000 1
#define CONFIG_DM9000_BASE 0x20000300 //网卡片选地址
#define DM9000_IO CONFIG_DM9000_BASE
#define DM9000_DATA (CONFIG_DM9000_BASE+4) //网卡数据地址
#define CONFIG_DM9000_NO_SROM 1
//#define CONFIG_DM9000_USE_16BIT
#undef CONFIG_DM9000_DEBUG
注意:
u-boot-2009.08 可以自动检测DM9000网卡的位数,根据开发板原理图可知网卡的数据位为16位,并且网卡位
于CPU的BANK4上,所以只需在 board/samsung/mini2440/lowlevel_init.S中设置 #define B4_BWSCON (DW16) 即
可,不需要此处的 #define CONFIG_DM9000_USE_16BIT 1
给u-boot加上ping命令,用来测试网络通不通
/*
* Command line configuration.
*/
#include
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_DATE
#define CONFIG_CMD_ELF
#define CONFIG_CMD_NAND
#define CONFIG_CMD_JFFS2 /* JFFS2 Support*/
#define CONFIG_CMD_PING /*ping command support*/

恢复被注释掉的网卡MAC地址和修改你合适的开发板IP地址以及内核启动参数:
#define CONFIG_BOOTDELAY 3
#define CONFIG_ETHADDR 08:00:3e:26:0a:5b
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 10.1.0.129
#define CONFIG_SERVERIP 10.1.0.128
#define CONFIG_GATEWAYIP 10.1.0.1
#define CONFIG_OVERWRITE_ETHADDR_ONCE
/*#define CONFIG_BOOTFILE "elinos-lart" */
定位到139行附近,加入使能串口传输数据到内存的操作:
#define ENABLE_CMD_LOADB_X 1 //使能串口传输数据到内存的操作
#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
4.2,重新编译u-boot,下载到Nand中从Nand启动,查看启动信息和环境变量并使用ping命令测试网卡,操作如下:
Enter your selection: a
USB host is connected. Waiting a download.
Now, Downloading

爱丫爱丫 发表于 2011-11-11 23:49:14


RECEIVED FILE SIZE: 154934 (151KB/S, 1S)
Downloaded file at 0x30000000, size = 154924 bytes
Write to flash ok: skipped size = 0x0, size = 0x25d2c
... ...
nand 方式上电重启后:
U-Boot 2009.08 ( 5链?09 2011 - 15:01:04)
DRAM: 64 MB
Flash: 2 MB
NAND: 128 MiB
In: serial
Out: serial
Err: serial
Net: dm9000
#
显示下环境变量:
# printenv
bootdelay=3
baudrate=115200
netmask=255.255.255.0
stdin=serial
stdout=serial
stderr=serial
ipaddr=10.1.129
serverip=10.1.0.128
ethact=dm9000
Environment size: 141/131068 bytes
ping测试:
# ping 10.1.0.128
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 00:00:00:00:00:00
operating at 100M full duplex mode
*** ERROR: `ethaddr' not set
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 00:00:00:00:00:00
operating at 100M full duplex mode
ping failed; host 10.1.0.128 is not alive
需要设定IP地址和MAC地址
# setenv ipaddr 10.1.0.129
# setenv serverip 10.1.0.128
# setenv setenv ethaddr 12:34:56:78:9A:BC
# saveenv
Saving Environment to NAND...
Erasing Nand...
Erasing at 0x4000000000002 -- 0% complete.
Writing to Nand... done
#
然后再进行ping测试:
# ping 10.1.0.128
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 12:34:56:78:9a:bc
operating at 100M full duplex mode
Using dm9000 device
ping failed; host 10.1.0.128 is not alive
#
可以看到,启动信息里面显示了Net:dm9000,printenv查看的环境变量也和include/configs/mini2440.h中设置的一致。但是现在有个问题就是ping不能通过。
经过一段时间在网上搜索,原来有很多人都碰到了这种情况。出现问题的地方可能是DM9000网卡驱动中关闭网卡的地方,如是就试着修改代码如下:
打开drivers/net/dm9000x.c ,定位到456行附近,屏蔽掉dm9000_halt函数中的内容:
/*
Stop the interface.
The interface is stopped when it is brought.
*/
static void dm9000_halt(struct eth_device *netdev)
{
#if 0
DM9000_DBG("%s\n", __func__);
/* RESET devie */
phy_write(0, 0x8000); /* PHY RESET */
DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */
DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */
DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */
#endif
}
重新编译下载,nand启动,运行结果:
# ping 10.1.0.128
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 00:00:00:00:00:00
operating at unknown: 0 mode
*** ERROR: `ethaddr' not set
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 00:00:00:00:00:00
operating at unknown: 0 mode
ping failed; host 10.1.0.128 is not alive
# setenv gatewayip 10.1.0.1
# setenv ethaddr 12:34:56:78:9a:bc //MAC地址,随便设
# ping 10.1.0.128
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 12:34:56:78:9a:bc
operating at unknown: 0 mode
Using dm9000 device
host 10.1.0.128 is alive
# saveenv
Saving Environment to NAND...
Erasing Nand...
Erasing at 0x4000000000002 -- 0% complete.
Writing to Nand... done
# ping 10.1.0.128
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 12:34:56:78:9a:bc
operating at unknown: 0 mode
Using dm9000 device
host 10.1.0.128 is alive
#
结果,只是第一次ping不通,以后都是可以ping通的(据网友们说这是正常的)。
4.3,tftp功能测试
首先需要将友善官方移植好的有关mini2440的内核文件zImage_T35复制到linux 宿主机的/tftpboot目录下,因为u-boot默认的此目录,然后执行:
# tftp 0x30008000 zImage_T35
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 12:34:56:78:9a:bc
operating at unknown: 0 mode
Using dm9000 device
TFTP from server 10.1.0.128; our IP address is 10.1.0.129
Filename 'zImage_T35'.
Load address: 0x30008000
Loading: T ################################################T #################
#############T T ######################T ##############################
T T
########
done
Bytes transferred = 2022348 (1edbcc hex)
#
至此DM9000网卡驱动移植成功。但是还发现一个问题:"这里之前还是"operating at 100M full duplexmode",而现在怎么是"operating at unknown: 0 mode"?原来是dm9000的phy_read(intreg)函数延时出了问题,现操作如下:
打开/drivers/net/dm9000x.c,定位到595行附近,修改如下:
/*
Read a word from phyxcer
*/
static u16
phy_read(int reg)
{
u16 val;
/* Fill the phyxcer register into REG_0C */
DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
DM9000_iow(DM9000_EPCR, 0xc); /* Issue phyxcer read command */
udelay(1000); //udelay(100); /* Wait read complete */
DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer read command */
val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL);
/* The read data keeps on REG_0D & REG_0E */
DM9000_DBG("phy_read(0x%x): 0x%x\n", reg, val);
return val;
}
重新编译下载后:
# ping 10.1.0.128
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 12:34:56:78:9a:bc
operating at unknown: 15 mode
Using dm9000 device
ping failed; host 10.1.0.128 is not alive
# ping 10.1.0.128
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 12:34:56:78:9a:bc
operating at 100M full duplex mode
Using dm9000 device
host 10.1.0.128 is alive
#
可以看到"operating at 100M full duplex mode"这样的信息了
上面还有一个问题,就是问什么第一次ping不通呢?经过尝试,操作如下:
打开/drivers/net/dm9000x.c,定位到377行,修改如下:
/* Activate DM9000 */
/* RX enable */
DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
/* Enable TX/RX interrupt mask */
DM9000_iow(DM9000_IMR, IMR_PAR);
#if 1 //internet delay loop
i = 0;
while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */
udelay(1000);
i++;
if (i == 3000) {
printf("could not establish link\n");
return 0;
//break;
}
}
#endif
修改后重新编译下载:
# ping 10.1.0.128
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 12:34:56:78:9a:bc
operating at 100M full duplex mode
Using dm9000 device
host 10.1.0.128 is alive
#
OK! 第一次ping不通的问题解决了!

接下来将进入u-boot的第五阶段,为u-boot-2009.08增加yaffs2文件系统。

爱丫爱丫 发表于 2011-11-11 23:49:22



移植环境
1,主机环境:VMare下CentOS 5.5 ,1G内存。
2,集成开发环境:Elipse IDE
3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-eabi-gcc v4.5.1。
4,开发板:mini2440,2M nor flash,128M nand flash。
5,u-boot版本:u-boot-2009.08

5.1,添加Yaffs2镜像烧写功能
由于现在很多使用Nand Flash 的系统,在Linux下都用Yaffs2作为存储数据的文件系统,甚至是根文件系统。所以在BootLoader 下能够烧写Yaffs2映像文件变得很必要。对于Yaffs2 映像烧写的支持其实就是在烧写时,写入数据的同时,将镜像文件中的oob数据也写入到Nand Flash的Spare 区。这和Yaffs 文件系统原理以及Nand Flash 的结构有关,注意:这里对Nand的操作是基于MTD架构方式。
通常一个Nnad Flash存储设备由若干块组成,1个块由若干页组成。一般128MB以下容量的NandFlash芯片,一页大小为528B,被依次分为2个256B的主数据区和16B的额外空间;128MB以上容量的NandFlash芯片,一页大小通常为2KB。由于Nand Flash出现位反转的概率较大,一般在读写时需要使用ECC进行错误检验和恢复。
Yaffs/yaffs2文件系统的设计充分考虑到NandFlash以页为存取单位等的特点,将文件组织成固定大小的段(Chunk)。以528B的页为例,Yaffs/yaffs2文件系统使用前512B存储数据和16B的额外空间存放数据的ECC和文件系统的组织信息等(称为OOB数据)。通过OOB数据,不但能实现错误检测和坏块处理,同时还可以避免加载时对整个存储介质的扫描,加快了文件系统的加载速度。以下是Yaffs/yaffs2文件系统页的结构说明:

Yaffs页结构说明
==============================================
字节 用途
==============================================
0 - 511 存储数据(分为两个半部)
512 - 515 系统信息
516 数据状态字
517 块状态字
518 - 519 系统信息
520 - 522 后半部256字节的ECC
523 - 524 系统信息
525 - 527 前半部256字节的ECC
==============================================
好了,在了解NandFlash组成和Yaffs/yaffs2文件系统结构后,我们再回到u-boot中。目前,在u-boot中已经有对Cramfs、Jffs2等文件系统的读写支持,但与带有数据校验等功能的OOB区的Yaffs/Yaffs2文件系统相比,他们是将所有文件数据简单的以线性表形式组织的。所以,我们只要在此基础上通过修改u-boot的NandFlash读写命令,增加处理00B区域数据的功能,即可以实现对Yaffs/Yaffs2文件系统的读写支持。
实现u-boot对Yaffs或者Yaffs2文件系统的读写支持步骤如下:
【1】下面是需要修改的 4 个文件的补丁:
(1)打开/common/cmd_nand.c,定位到392行,在nand操作的do_nand函数中,修改如下:
if (read)
ret = nand_read_skip_bad(nand, off, &size,
(u_char *)addr);
else
ret = nand_write_skip_bad(nand, off, &size,
(u_char *)addr);
}
#if defined(CONFIG_MTD_NAND_YAFFS2)
else if (s != NULL && (!strcmp(s, ".yaffs2")))
{
nand->rw_oob = 1;
nand->skipfirstblk = 1;
ret = nand_write_skip_bad(nand,off,&size,(u_char *)addr);
nand->skipfirstblk = 0;
nand->rw_oob = 0;
}
#endif
else if (!strcmp(s, ".oob")) {
/* out-of-band data */
mtd_oob_ops_t ops = {
.oobbuf = (u8 *)addr,
.ooblen = size,
.mode = MTD_OOB_RAW
};
... ...
定位到509行附近,在Nand操作的命令集列表中添加Yaffs2对Nand的读写命令,修改如下
U_BOOT_CMD(nand, CONFIG_SYS_MAXARGS, 1, do_nand,
"NAND sub-system",
"info - show available NAND devices\n"
"nand device - show or set current device\n"
"nand read - addr off|partition size\n"
"nand write - addr off|partition size\n"
" read/write 'size' bytes starting at offset 'off'\n"
" to/from memory address 'addr', skipping bad blocks.\n"
"nand erase - erase 'size' bytes from\n"
" offset 'off' (entire device if not specified)\n"
#if defined(CONFIG_MTD_NAND_YAFFS2)
"nand write[.yaffs2] - addr off|partition size - write `size' byte yaffs image\n"
" starting at offset off' from memory address addr' (.yaffs2 for 512+16 NAND)\n"
#endif
"nand bad - show bad blocks\n"
"nand dump[.oob] off - dump page\n"
"nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
"nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
"nand biterr off - make a bit error at offset (UNSAFE)"
#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
"\n"
"nand lock \n"
" bring nand to lock state or display locked pages\n"
"nand unlock - unlock section"
#endif
);
注意:这里只添加了yaffs2的写命令,u-boot下载用的是写功能。

(2)打开include/linux/mtd/mtd.h头文件,定位到131行,在mtd_info结构体中添加上面用到rw_oob和skipfirstblk数据成员,修改如下:
u_int32_t writesize;
#if defined(CONFIG_MTD_NAND_YAFFS2)
/*Thanks for hugerat's code*/
u_char rw_oob;
u_char skipfirstblk;
#endif
u_int32_t oobsize; /* Amount of OOB data per block (e.g. 16) */
u_int32_t oobavail; /* Available OOB bytes per block */

(3)在第一步关联的nand_write_skip_bad函数中添加对Nand OOB的相关操作,修改如下:
打开/drivers/mtd/nand/nand_util.c,定位到483行,在nand_write_skip_bad函数中添加代码,修改如下:
int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
u_char *buffer)
{
int rval;
size_t left_to_write = *length;
size_t len_incl_bad;
u_char *p_buffer = buffer;
#if defined(CONFIG_MTD_NAND_YAFFS2)
if(nand->rw_oob==1)
{
size_t oobsize = nand->oobsize;
size_t datasize = nand->writesize;
int datapages = 0;
if (((*length)%(nand->oobsize+nand->writesize)) != 0)
{
printf ("Attempt to write error length data!\n");
return -EINVAL;
}
datapages = *length/(datasize+oobsize);
*length = datapages*datasize;
left_to_write = *length;
}
#endif
/* Reject writes, which are not page aligned */
if ((offset & (nand->writesize - 1)) != 0 ||
(*length & (nand->writesize - 1)) != 0) {
printf ("Attempt to write non page aligned data\n");
return -EINVAL;
}
len_incl_bad = get_len_incl_bad (nand, offset, *length);
if ((offset + len_incl_bad) >= nand->size) {
printf ("Attempt to write outside the flash area\n");
return -EINVAL;
}
#if !defined(CONFIG_MTD_NAND_YAFFS2)//add yaffs2 file system support
if (len_incl_bad == *length) {
rval = nand_write (nand, offset, length, buffer);
if (rval != 0)
printf ("NAND write to offset %llx failed %d\n",
offset, rval);
return rval;
}
#endif
while (left_to_write > 0) {
size_t block_offset = offset & (nand->erasesize - 1);
size_t write_size;
WATCHDOG_RESET ();
if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) {
printf ("Skip bad block 0x%08llx\n",
offset & ~(nand->erasesize - 1));
offset += nand->erasesize - block_offset;
continue;
}
#if defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support
if(nand->skipfirstblk==1)
{
nand->skipfirstblk=0;
printf ("Skip the first good block %llx\n", offset & ~(nand->erasesize - 1));
offset += nand->erasesize - block_offset;
continue;
}
#endif
if (left_to_write < (nand->erasesize - block_offset))
write_size = left_to_write;
else
write_size = nand->erasesize - block_offset;
printf("\rWriting at 0x%llx -- ",offset); //add yaffs2 file system support
rval = nand_write (nand, offset, &write_size, p_buffer);
if (rval != 0) {
printf ("NAND write to offset %llx failed %d\n",
offset, rval);
*length -= left_to_write;
return rval;
}
left_to_write -= write_size;
printf("%d%% is complete.",100-(left_to_write/(*length/100)));/*Thanks for hugerat's code*/
offset += write_size;
#if defined(CONFIG_MTD_NAND_YAFFS2)
/*Thanks for hugerat's code*/
if(nand->rw_oob==1) {
p_buffer += write_size+(write_size/nand->writesize*nand->oobsize);
} else {
p_buffer += write_size;
}
#else
p_buffer += write_size;
#endif
}
return 0;
}
(4)在第三步的nand_write_skip_bad函数中我们看到又对nand_write函数进行了访问,所以这一步是到nand_write函数中添加对yaffs2的支持。
打开/drivers/mtd/nand/nand_base.c,定位到1961行,修改如下:
static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const uint8_t *buf)
{
struct nand_chip *chip = mtd->priv;
int ret;
#if defined(CONFIG_MTD_NAND_YAFFS2)
/*Thanks for hugerat's code!*/
int oldopsmode = 0;

爱丫爱丫 发表于 2011-11-11 23:49:27

if(mtd->rw_oob==1)
{
int i = 0;
int datapages = 0;
size_t oobsize = mtd->oobsize;
size_t datasize = mtd->writesize;
uint8_t oobtemp;
datapages = len / (datasize);
for(i = 0; i < (datapages); i++)
{
memcpy((void *)oobtemp, (void *)(buf + datasize * (i + 1)), oobsize);
memmove((void *)(buf + datasize * (i + 1)),
(void *)(buf + datasize * (i + 1) + oobsize),
(datapages - (i + 1)) * (datasize) + (datapages - 1) * oobsize);
memcpy((void *)(buf+(datapages) * (datasize + oobsize) - oobsize),
(void *)(oobtemp), oobsize);
}
}
#endif
/* Do not allow reads past end of device */
if ((to + len) > mtd->size)
return -EINVAL;
if (!len)
return 0;
nand_get_device(chip, mtd, FL_WRITING);
chip->ops.len = len;
chip->ops.datbuf = (uint8_t *)buf;
//chip->ops.oobbuf = NULL;
#if defined(CONFIG_MTD_NAND_YAFFS2)//add yaffs2 file system support
/*Thanks for hugerat's code!*/
if(mtd->rw_oob!=1) {
chip->ops.oobbuf = NULL;
} else {
chip->ops.oobbuf = (uint8_t *)(buf+len);
chip->ops.ooblen = mtd->oobsize;
oldopsmode = chip->ops.mode;
chip->ops.mode = MTD_OOB_RAW;
}
#else
chip->ops.oobbuf = NULL;
#endif
ret = nand_do_write_ops(mtd, to, &chip->ops);
*retlen = chip->ops.retlen;
nand_release_device(mtd);
#if defined(CONFIG_MTD_NAND_YAFFS2)//add yaffs2 file system support
/*Thanks for hugerat's code!*/
chip->ops.mode = oldopsmode;
#endif
return ret;
}
【2】在mini2440.h里添加yaffs2相关宏定义
打开include/configs/mini2440.h,定位到98行附近,加入下列代码:
/*
* Command line configuration.
*/
#include
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_DATE
#define CONFIG_CMD_ELF
#define CONFIG_CMD_NAND
#define CONFIG_CMD_JFFS2 /* JFFS2 Support*/
... ...
在文件末尾处加入下列代码:
/*-----------------------------------------------------------------------
* NAND flash settings
*/
#if defined(CONFIG_CMD_NAND)
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_NAND_BASE 0x4E000000
#define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND devices */
#define SECTORSIZE 512
#define SECTORSIZE_2K 2048
#define NAND_SECTOR_SIZE SECTORSIZE
#define NAND_SECTOR_SIZE_2K SECTORSIZE_2K
#define NAND_BLOCK_MASK 511
#define NAND_BLOCK_MASK_2K 2047
#define NAND_MAX_CHIPS 1
#define CONFIG_MTD_NAND_VERIFY_WRITE
#define CONFIG_SYS_64BIT_VSPRINTF /* needed for nand_util.c */
#endif /* CONFIG_CMD_NAND */

#define CONFIG_JFFS2_NAND 1
//#undef CONFIG_JFFS2_CMDLINE
#define CONFIG_JFFS2_DEV "nand0"
#define CONFIG_JFFS2_PART_SIZE 0x480000
#define CONFIG_JFFS2_PART_OFFSET 0x80000
#define CONFIG_JFFS2_CMDLINE 1
#define MTDIDS_DEFAULT "nand0=nandflash0"
#define MTDPARTS_DEFAULT "mtdparts=nandflash0:384k(bootloader)," \
"128k(params)," \
"5m(kernel)," \
"-(root)"
#define CONFIG_MTD_NAND_YAFFS2 1
#define ENABLE_CMD_LOADB_X 1

5.2, 烧录yaffs2文件系统测试
重新编译后下载,nand方式启动,在u-boot的命令行输入nand help查看nand的命令,可以看到多了一个nand write[.yaffs2]的命令:
# nand help
nand - NAND sub-system
Usage:
nand info - show available NAND devices
nand device - show or set current device
nand read - addr off|partition size
nand write - addr off|partition size
read/write 'size' bytes starting at offset 'off'
to/from memory address 'addr', skipping bad blocks.
nand erase - erase 'size' bytes from
offset 'off' (entire device if not specified)
nand write[.yaffs2] - addr off|partition size - write `size' byte yaffs image
starting at offset off' from memory address addr' (.yaffs2 for 512+16 NAND)
nand bad - show bad blocks
nand dump[.oob] off - dump page
nand scrub - really clean NAND erasing bad blocks (UNSAFE)
nand markbad off [...] - mark bad block(s) at offset (UNSAFE)
nand biterr off - make a bit error at offset (UNSAFE)
#
这个就是用来下载yaffs2文件系统到nand中的命令了。首先需要将友善官方提供的有关mini2440的yaffs2文件系统文件root_qtopia-128M.img复制到linux宿主机的/tftpboot目录下,然后执行:
tf# tp 0x30000000 root_qtopia-128M.img
Filename 'root_qtopia-128M.img'.
Load address: 0x30000000
Loading: T ##########T T #####################################################T
##T T
#T T T T ######
Retry count exceeded; starting again
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 12:34:56:78:9a:bc
operating at 100M full duplex mode
Using dm9000 device
TFTP from server 10.1.0.128; our IP address is 10.1.0.129
Filename 'root_qtopia-128M.img'.
Load address: 0x30000000
Loading: T ###T ###T T ########
一直无休止循环,经网上搜索得知Uboot 端 tftp 程序传过来的Timeout参数不符合服务器端定义引起的,原文链接地址
Retry count exceeded; starting again解决方法:tftp客户端传过来的timeout是7810,而服务器端定义的范围在1-255秒之间,不是服务器的问题,而是uboot中tftp参数设置的问题,参见TFTP Unsupported option(s) requested 问题详细分析及解决。
打开/net/net.c,定位到104行附近,修改如下:
#if defined(CONFIG_CMD_NET)
DECLARE_GLOBAL_DATA_PTR;
#ifndef CONFIG_ARP_TIMEOUT
# define ARP_TIMEOUT 10000UL*CONFIG_SYS_HZ/1000 //5000UL /* Milliseconds before trying ARP again */
#else
# define ARP_TIMEOUT CONFIG_ARP_TIMEOUT
#endif
定位到573行附近,修改如下:
#ifndef CONFIG_NET_MULTI
//NetSetTimeout (10000UL, startAgainTimeout);
NetSetTimeout (10000UL*CONFIG_SYS_HZ/1000, startAgainTimeout);
NetSetHandler (startAgainHandler);
#else /* !CONFIG_NET_MULTI*/
定位到585行附近,修改如下:
eth_init (gd->bd);
if (NetRestartWrap) {
NetRestartWrap = 0;
if (NetDevExists && !once) {
//NetSetTimeout (10000UL, startAgainTimeout);
NetSetTimeout (10000UL*CONFIG_SYS_HZ/1000, startAgainTimeout);
NetSetHandler (startAgainHandler);
} else {
NetState = NETLOOP_FAIL;
}
定位到779行附近,修改如下:
#define CDP_SYSOBJECT_TLV 0x0015
#define CDP_MANAGEMENT_ADDRESS_TLV 0x0016
#define CDP_TIMEOUT (250UL*CONFIG_SYS_HZ/1000) //250UL /* one packet every 250ms */
static int CDPSeq;
static int CDPOK;
打开/net/tftp.c,定位到16行,修改如下:
#define TIMEOUT 60000UL //5000UL /* Millisecs to timeout for lost pkt */
然后重新编译后下载测试:
# tftp 0x30000000 root_qtopia-128M.img
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 12:34:56:78:9a:bc
operating at 100M full duplex mode
Using dm9000 device
TFTP from server 10.1.0.128; our IP address is 10.1.0.129
Filename 'root_qtopia-128M.img'.
Load address: 0x30000000
Loading: T T T T T T T T T T
Retry count exceeded; starting again
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 12:34:56:78:9a:bc
operating at 100M full duplex mode
Using dm9000 device
TFTP from server 10.1.0.128; our IP address is 10.1.0.129
Filename 'root_qtopia-128M.img'.
Load address: 0x30000000
Loading: #################################################################
#################################################################
... ...
#################################################################
####################
done
Bytes transferred = 58487616 (37c7340 hex)
#
在yaffs2文件系统镜像下载到内存后:
# nand erase 0 0x40000
NAND erase: device 0 offset 0x0, size 0x40000
Erasing at 0x2000000000004 -- 0% complete.
OK
# nand write 0x30000000 0 0x40000
NAND write: device 0 offset 0x0, size 0x40000
Writing at 0x2000000020000 -- 100% is complete. 262144 bytes written: OK
#

爱丫爱丫 发表于 2011-11-11 23:49:32

可以看到,yaffs2文件系统烧录成功。下一步需要加载内核来挂载yaffs2文件系统。
接下来将进入u-boot的第六阶段,为u-boot-2009.08 增加引导内核功能。

爱丫爱丫 发表于 2011-11-11 23:49:41



移植环境
1,主机环境:VMare下CentOS 5.5 ,1G内存。
2,集成开发环境:Elipse IDE
3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-eabi-gcc v4.5.1。
4,开发板:mini2440,2M nor flash,128M nand flash。
5,u-boot版本:u-boot-2009.08
6,参考文章:

http://www.linuxidc.com/Linux/2011-02/32772p6.htm
6.1,u-boot配置
【1】机器码的确定
通常,在u-boot和kernel中都会有一个机器码(即:MACH_TYPE),只有这两个机器码一致时才能引导内核,否则就会出现如下mach的错误信息或者死机。
打开board/samsung/mini2440/mini2440.c,定位到124行附近,修改如下:
#if defined(CONFIG_S3C2410)
/* arch number of SMDK2410-Board */
gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
#endif
#if defined(CONFIG_S3C2440)
/* arch number of S3C2440-Board */
gd->bd->bi_arch_number = MACH_TYPE_MINI2440 ;
#endif
对于u-boot-2009.08来说,MACH_TYPE_MINI2440已经在include/asm-arm/mach-types.h 文件的1985行附件有定义。
#define MACH_TYPE_Q2440 1997
#define MACH_TYPE_QQ2440 1998
#define MACH_TYPE_MINI2440 1999 //mini2440的机器码
#define MACH_TYPE_COLIBRI300 2000
#define MACH_TYPE_JADES 2001
【2】修改u-boot中内核引导参数:
打开/include/configs/mini2440.h,定位到60行附近,修改如下:
#define CONFIG_BOOTDELAY 3
#define CONFIG_SETUP_MEMORY_TAGS 1 //如果没有定义这个参数,则uboot参数必须加入men=内存大小
#define CONFIG_INITRD_TAG 1
#define CONFIG_CMDLINE_TAG 1 //设置bootargs出入内核必须
#define CONFIG_BOOTARGS "noinitrd console=ttySAC0,115200 init=/linuxrc \
root=/dev/mtdblock3 rw rootfstype=yaffs \
ip=10.1.0.129:10.1.0.128:10.1.0.1:255.255.255.0::eth0:off"
/* "noinitrd console=ttySAC0,115200 init=/linuxrc mem=64M \
root=/dev/nfs rw nfsroot=10.1.0.128:/nfsboot \
ip=10.1.0.129:10.1.128:10.1.0.1:255.255.255.0::eth0:off"
*/
#define CONFIG_ETHADDR 08:00:3e:26:0a:5b
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 10.1.0.129
#define CONFIG_SERVERIP 10.1.0.128
#define CONFIG_GATEWAYIP 10.1.0.1
#define CONFIG_OVERWRITE_ETHADDR_ONCE
/*#define CONFIG_BOOTFILE "elinos-lart" */
#define CONFIG_BOOTCOMMAND "nand read 0x30008000 0x80000 0x300000;bootm 0x30008000"
/*"nfs 0x30008000 10.1.0.128:/nfsboot/zImage.img;bootm" */
#define CONFIG_EXTRA_ENV_SETTINGS \
"singleboy=bmp d 70000\0 " \
"stdin=serial\0" \
"stdout=serial\0" \
"stderr=serial\0" \
""
#if defined(CONFIG_CMD_KGDB)
bootargs参数解析:
initrd, noinitrd:当你没有使用ramdisk启动系统的时候,你需要使用noinitrd这个参数,但是如果使用了的话,就需要指定initrd=r_addr,size, r_addr表示initrd在内存中的位置,size表示initrd的大小。
console: console=tty 使用虚拟串口终端设备 。console=ttyS[,options]使用特定的串口,options可以是这样的形式bbbbpnx,这里bbbb是指串口的波特率,p是奇偶位(从来没有看过使用过),n是指的bits。console=ttySAC[,options]同上面。看你当前的环境,有时用ttyS,有时用ttySAC,网上有人说,这是跟内核的版本有关,2.4用ttyS,2.6用ttySAC,但实际情况是官方文档中也是使用ttyS,所以应该是跟内核版本没有关联的。可以查看Documentation/serial-console.txt找到相关描述。
init: 指定的是内核启起来后,进入系统中运行的第一个脚本,一般init=/linuxrc,或者init=/etc/preinit,preinit的内容一般是创建console,null设备节点,运行init程序,挂载一些文件系统等等操作。请注意,很多初学者以为init=/linuxrc是固定写法,其实不然,/linuxrc指的是/目录下面的linuxrc脚本,一般是一个连接罢了。如果内核找不到linurc文件,将会依搜索/sbin/init, /etc/init,/bin/init,/bin/sh.
mem: 指定内存大小,不是必须的。
root: 用来指定rootfs的位置, 常见的情况有:
root=/dev/ram rw
root=/dev/ram0 rw
请注意上面的这两种设置情况是通用的,我做过测试甚至root=/dev/ram1 rw和root=/dev/ram2rw也是可以的,网上有人说在某些情况下是不通用的,即必须设置成ram或者ram0,但是目前还没有遇到,还需要进一步确认,遇到不行的时候可以逐一尝试。
root=/dev/mtdx rw
root=/dev/mtdblockx rw
root=/dev/mtdblock/x rw
root=31:0x
上面的这几个在一定情况下是通用的,当然这要看你当前的系统是否支持,不过mtd是字符设备,而mtdblock是块设备,有时候你的挨个的试到底当前的系统支持上面那种情况下,不过root=/dev/mtdblockxrw比较通用。此外,如果直接指定设备名可以的话,那么使用此设备的设备号也是可以的。
root=/dev/nfs,并非真的设备,而是一个告诉内核经由网络取得根文件系统的旗标。
在文件系统为基于nfs的文件系统的时候使用。当然指定root=/dev/nfs之后,还需要指定nfsroot,这个参数告诉内核以哪一台机器,哪个目录以及哪个网络文件系统选项作为根文件系统使用。参数的格式如下:
nfsroot=[:][,]
如果指令列上没有给定 nfsroot 参数,则将使用‘/tftpboot/%s’预设值。其它选项如下:
:指定网络文件系统服务端的互联网地址(IP address)。如果没有给定此栏位,则使用由nfsaddrs变量(见下面)所决定的值。此参数的用途之一是允许使用不同机器作为反向地址解析协议(RARP)及网络文件系统服务端。通常你可以不管它(设为空白)。
: 服务端上要作为根挂入的目录名称。如果字串中有个‘%s’ 符记(token),此符记将代换为客户端互联网地址之ASCII 表示法。
:标准的网络文件系统选项。所有选项都以逗号分开。如果没有给定此选项栏位则使用下列的预设值:
port = as given by server portmap daemon
rsize = 1024
wsize = 1024
timeo = 7
retrans = 3
acregmin = 3
acregmax = 60
acdirmin = 30
acdirmax = 60
flags = hard, nointr, noposix, cto, ac
参数nfsaddrs设定网络通讯所需的各种网络接口地址。如果没有给定这个参数,则内核核会试着使用反向地址解析协议以及或是启动协议(BOOTP)以找出这些参数。下面是U-boot官方文档提供的IP参数解析,其格式如下:
setenv bootargs ${bootargs}
ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname:${netdev}:off

注意,上面换行的地方均有空格。其中 10.1.0.129是开发板的IP,10.1.0.128是PC端(或虚拟机)的IP,上面的IP根据自己的实际情况修改,不要弄错了。参数nfsaddrs格式如下:
nfsaddrs=::::::
:客户端的互联网地址。如果没设,此地址将由反向地址解析协议(RARP)或启动协议来决定。使用何种协议端视配置核心时打开的选项以及 参数而定。如果设定此参数,就不会使用反向地址解析协议或启动协议。
:网络文件系统服务端之互联网地址。如果使用反向地址解析协议来决定客户端地址并且设定此参数,则只接受从指定之服务端传来的回应。要使用不同的机器作为反向地址解析与网络文件系统服务端的话,在此指定你的反向地址解析协议服务端(保持空白)并在 nfsroot参数(见上述)中指定你的网络文件系统服务端。如果此项目空白则使用回答反向地址解析协议或启动协议之服务端的地址。
:网关(gateway)之互联网地址,若服务端位於不同的子网络上时。如果此项目空白则不使用任何网关并假设服务端在本地的(local)网络上,除非由启动协议接收到值。
:本地网络界面的网络掩码。如果为空白,则网络掩码由客户端的互联网地址导出,除非由启动协议接收到值。
:客户端的名称。如果空白,则使用客户端互联网地址之 ASCII-标记法,或由启动协议接收的值。
: 要使用的网络设备名称。如果为空白,所有设备都会用来发出反向地址解析请求,启动协议请求由最先找到的设备发出。网络文件系统使用接收到反向地址解析协议或启动协议回应的设备。如果你只有一个设备那你可以不管它。
: 用以作为自动配置的方法。如果是 `rarp' 或是 `bootp' 则使用所指示的协议。如果此值为`both'或空白,若配置核心时有打开这两种协议则都使用。 `none' 表示不使用自动配置。这种情况下你必须指定前述栏位中所有必要的值。
此参数可以作为 nfsaddrs 的参数单独使用(前面没有任何 `:` 字符),这种情况下会使用自动配置。然而,此种情况不能使用 `none'作为值。
保存修改。
重新编译下载后,nand方式启动。
【3】制作能被u-boot直接引导的内核uImage
通常,kernel的启动需要u-boot提供一些参数信息,比如ramdisk在RAM中的地址。经过编译后的u-boot在根目录下的tools目录中,会有个叫做mkimage的工具,他可以给zImage添加一个header,也就是说使得通常我们编译的内核zImage添加一个数据头信息部分,我们把添加头后的image通常叫uImage,uImage是可以被u-boot直接引导的内核镜像。
mkimage工具的使用介绍如下:
使用: 中括号括起来的是可选的
mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
选项:

爱丫爱丫 发表于 2011-11-11 23:49:46

-A:set architecture to 'arch' //用于指定CPU类型,比如ARM
-O:set operating system to 'os' //用于指定操作系统,比如Linux
-T:set image type to 'type' //用于指定image类型,比如Kernel
-C:set compression type 'comp' //指定压缩类型
-a:set load address to 'addr' (hex) //指定image的载入地址
-e:set entry point to 'ep' (hex) //内核的入口地址,一般为image的载入地址+0x40(信息头的大小)
-n:set image name to 'name' //image在头结构中的命名
-d:use image data from 'datafile' //无头信息的image文件名
-x:set XIP (execute in place) //设置执行位置
先将u-boot下的tools中的mkimage复制到主机的/usr/local/bin目录下,这样就可以在主机的任何目录下使用该工具了。现在我们进入kernel生成目录(一般是arch/arm/boot目录),然后执行如下命令,就会在该目录下生成一个uImage.img的镜像文件,把他复制到tftp目录下,这就是我们所说的uImage。打开终端,现操作如下:
# cd /tftpboot
# ls
root_qtopia-128M.img zImage_T35
# mkimage -n 'mini2440_linux' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008040 -d zImage_T35 uImage_T35
Image Name: mini2440_linux
Created: Thu May 12 11:37:00 2011
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2022348 Bytes = 1974.95 kB = 1.93 MB
Load Address: 30008000
Entry Point: 30008040
#
更改用户执行权限
# ls -a
. .. root_qtopia-128M.img uImage_T35 zImage_T35
# ls -l
总计 61140
-rwxrw-rw- 1 root root 58487616 2009-07-18 root_qtopia-128M.img
-rw-r--r-- 1 root root 2022412 05-12 11:37 uImage_T35
-rwxrw-rw- 1 root root 2022348 2009-07-08 zImage_T35
# chmod a+x uImage_T35
# ls -l
总计 61140
-rwxrw-rw- 1 root root 58487616 2009-07-18 root_qtopia-128M.img
-rwxr-xr-x 1 root root 2022412 05-12 11:37 uImage_T35
-rwxrw-rw- 1 root root 2022348 2009-07-08 zImage_T35
#
(2)把uImage.img用tftp下载到内存中,然后再固化到Nand Flash中,操作如下:
# tftp 0x30000000 uImage_T35
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 12:34:56:78:9a:bc
operating at 100M full duplex mode
Using dm9000 device
TFTP from server 10.1.0.128; our IP address is 10.1.0.129
Filename 'uImage_T35'.
Load address: 0x30000000
Loading: #################################################################
#################################################################
########
done
Bytes transferred = 2022412 (1edc0c hex)
#
用bootm命令启动:
# bootm 0x30008000
## Booting kernel from Legacy Image at 30008000 ...
Image Name: mini2440_linux
Created: 2011-05-12 3:37:00 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2022348 Bytes = 1.9 MB
Load Address: 30008000
Entry Point: 30008040
Verifying Checksum ... OK
XIP Kernel Image ... OK
OK
Starting kernel ...
Uncompressing Linux.............................................................
..................................................................... done, boot
ing the kernel.
Linux version 2.6.29.4-FriendlyARM (root@tom) (gcc version 4.3.2 (Sourcery G++ L
ite 2008q3-72) ) #3 Wed Jul 8 18:19:20 CST 2009
CPU: ARM920T revision 0 (ARMv4T), cr=00007177
CPU: VIVT data cache, VIVT instruction cache
Machine: FriendlyARM Mini2440 development board
Memory policy: ECC disabled, Data cache writeback
CPU S3C2440A (id 0x32440001)
... ...
Try to bring eth0 interface up......eth0: link up, 100Mbps, full-duplex, lpa 0x4
5E1
Done
Please press Enter to activate this console.
-/bin/sh: id: not found
# ls
bin get linuxrc proc sdcard www
dev home lost+found root sys
etc lib opt sbin var
#
【4】设置u-boot引导参数并保存到nand flash
设置启动参数,意思是将nand中0x80000-0x300000(和kernel分区一致)的内容读到内存0x30008000中,然后用bootm命令来执行(如果在第一步中的mini2440.h文件设置是正确的,此步可以不做):
# set bootargs noinitrd root=/dev/mtdblock3 console=ttySAC0
# set bootcmd nand read 0x30008000 0x80000 300000 \; bootm 0x30008000
# saveenv
Saving Environment to NAND...
Erasing Nand...
Erasing at 0x4000000000002 -- 0% complete.
Writing to Nand... done
#
【5】将内核写入Nand flash,系统上电后自引导:
擦除nand的0x80000-0x300000的内容,并将将内存0x30008000处的内容写入到nand的0x80000处:
# nand erase 0x80000 0x300000
NAND erase: device 0 offset 0x80000, size 0x300000
Erasing at 0x36000001800000 -- 0% complete.
OK
# nand write 30008000 0x80000 0x300000
NAND write: device 0 offset 0x80000, size 0x300000
Writing at 0x36000000020000 -- 100% is complete. 3145728 bytes written: OK
#
U-Boot 2009.08
modified by singleboy (singleboy@163.com)
Love Linux forever!!
DRAM: 64 MB
Flash: 2 MB
NAND: 128 MiB
Video: 240x320x16 20kHz 62Hz
In: serial
Out: serial
Err: serial
Net: dm9000
U-Boot 2009.08
modified by singleboy(singleboy@163.com)
Love Linux forever!!
Hit any key to stop autoboot: 0
NAND read: device 0 offset 0x80000, size 0x300000
3145728 bytes read: OK
## Booting kernel from Legacy Image at 30008000 ...
Image Name: mini2440_linux
Created: 2011-05-12 3:37:00 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2022348 Bytes = 1.9 MB
Load Address: 30008000
Entry Point: 30008040
Verifying Checksum ... OK
XIP Kernel Image ... OK
OK
Starting kernel ...
Uncompressing Linux.............................................................
..................................................................... done, boot
ing the kernel.
Linux version 2.6.29.4-FriendlyARM (root@tom) (gcc version 4.3.2 (Sourcery G++ L
ite 2008q3-72) ) #3 Wed Jul 8 18:19:20 CST 2009
CPU: ARM920T revision 0 (ARMv4T), cr=00007177
CPU: VIVT data cache, VIVT instruction cache
Machine: FriendlyARM Mini2440 development board
Memory policy: ECC disabled, Data cache writeback
CPU S3C2440A (id 0x32440001)
S3C24XX Clocks, (c) 2004 Simtec Electronics
S3C244X: core 405.000 MHz, memory 101.250 MHz, peripheral 50.625 MHz
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16256
Kernel command line: noinitrd root=/dev/mtdblock3 console=ttySAC0
... ...
mount: mounting none on /tmp failed: No such file or directory
hwclock: settimeofday() failed: Invalid argument
/etc/rc.d/init.d/netd: line 16: /usr/sbin/inetd: not found
/etc/rc.d/init.d/httpd: line 16: /usr/sbin/boa: not found
/etc/rc.d/init.d/leds: line 16: /usr/bin/led-player: not found
Try to bring eth0 interface up......eth0: link down
Done
Please press Enter to activate this console. eth0: link up, 100Mbps, full-duplex
, lpa 0x45E1
-/bin/sh: id: not found
# ls
bin get linuxrc proc sdcard www
dev home lost+found root sys
etc lib opt sbin var
#
内核和yaffs2文件系统成功引导起来了。

雪月 发表于 2011-11-11 23:50:04



移植环境
1,主机环境:VMare下CentOS 5.5 ,1G内存。
2,集成开发环境:Elipse IDE
3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-eabi-gcc v4.5.1。
4,开发板:mini2440,2M nor flash,128M nand flash。
5,u-boot版本:u-boot-2009.08

7.1添加 LCD 显示功能

对于这个 LCD 的支持是参考Openmoko 的代码移植的。Openmoko 的GTA2 使用的是S3C2442 的CPU,在LCD控制器上是一样的。而GTA2 在U-boot 的可以在LCD 上显示字符,而且对于软件分层的U-boot来说,只要将底层驱动移植过来并调整好初始化参数就可以在LCD上显示console。下图是LCD驱动软件分层执行流程示意。可以看到LCD在执行时最终调用的是底层的board_video_init()函数,其主要作用是对LCD控制寄存器进行初始化。可由用户根据实际LCD硬件编写。

由于友善之臂使用了两种屏,他们在一个参数上有很小的差别,而屏有不可以通过程序去识别,所以只能简单的通过Nand Flash配置来区分导入的参数(64MB Nand 的板子使用的都是NEC 的,其他的都是统宝的)。这个功能的移植修改了5个文件(包括drivers/video/Makefile,以及前面已经修改过的board/samsung/mini2440/mini2440.c文件)。
【1】在/drivers/video/下添加一个驱动文件名为s3c2410_fb.c,将下面内容粘贴进去:
/*
* (C) Copyright 2006 by OpenMoko, Inc.
* Author: Harald Welte
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include

#if defined(CONFIG_VIDEO_S3C2410)

#include
#include "videomodes.h"
#include
/*
* Export Graphic Device
*/
GraphicDevice smi;

#define VIDEO_MEM_SIZE 0x200000 /* 240x320x16bit = 0x25800 bytes */

extern void board_video_init(GraphicDevice *pGD);

/*******************************************************************************
*
* Init video chip with common Linux graphic modes (lilo)
*/
void *video_hw_init (void)
{
S3C24X0_LCD * const lcd = S3C24X0_GetBase_LCD();
GraphicDevice *pGD = (GraphicDevice *)&smi;
int videomode;
unsigned long t1, hsynch, vsynch;
char *penv;
int tmp, i, bits_per_pixel;
struct ctfb_res_modes *res_mode;
struct ctfb_res_modes var_mode;
// unsigned char videoout;

/* Search for video chip */
printf("Video: ");
tmp = 0;

videomode = CFG_SYS_DEFAULT_VIDEO_MODE;
/* get video mode via environment */
if ((penv = getenv ("videomode")) != NULL) {
/* deceide if it is a string */
if (penv <= '9') {
videomode = (int) simple_strtoul (penv, NULL, 16);
tmp = 1;
}
} else {
tmp = 1;
}
if (tmp) {
/* parameter are vesa modes */
/* search params */
for (i = 0; i < VESA_MODES_COUNT; i++) {
if (vesa_modes.vesanr == videomode)
break;
}
if (i == VESA_MODES_COUNT) {
printf ("no VESA Mode found, switching to mode 0x%x ", CFG_SYS_DEFAULT_VIDEO_MODE);
i = 0;
}
res_mode =
(struct ctfb_res_modes *) &res_mode_init.
resindex];
bits_per_pixel = vesa_modes.bits_per_pixel;
} else {

res_mode = (struct ctfb_res_modes *) &var_mode;
bits_per_pixel = video_get_params (res_mode, penv);
}

/* calculate hsynch and vsynch freq (info only) */
t1 = (res_mode->left_margin + res_mode->xres +
res_mode->right_margin + res_mode->hsync_len) / 8;
t1 *= 8;
t1 *= res_mode->pixclock;
t1 /= 1000;
hsynch = 1000000000L / t1;
t1 *=
(res_mode->upper_margin + res_mode->yres +
res_mode->lower_margin + res_mode->vsync_len);
t1 /= 1000;
vsynch = 1000000000L / t1;

/* fill in Graphic device struct */
sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,
res_mode->yres, bits_per_pixel, (hsynch / 1000),
(vsynch / 1000));
printf ("%s\n", pGD->modeIdent);
pGD->winSizeX = res_mode->xres;
pGD->winSizeY = res_mode->yres;
pGD->plnSizeX = res_mode->xres;
pGD->plnSizeY = res_mode->yres;

switch (bits_per_pixel) {
case 8:
pGD->gdfBytesPP = 1;
pGD->gdfIndex = GDF__8BIT_INDEX;
break;
case 15:
pGD->gdfBytesPP = 2;
pGD->gdfIndex = GDF_15BIT_555RGB;
break;
case 16:
pGD->gdfBytesPP = 2;
pGD->gdfIndex = GDF_16BIT_565RGB;
break;
case 24:
pGD->gdfBytesPP = 3;
pGD->gdfIndex = GDF_24BIT_888RGB;
break;
}

/* statically configure settings */
pGD->winSizeX = pGD->plnSizeX = 240;
pGD->winSizeY = pGD->plnSizeY = 320;
pGD->gdfBytesPP = 2;
pGD->gdfIndex = GDF_16BIT_565RGB;

pGD->frameAdrs = LCD_VIDEO_ADDR;
pGD->memSize = VIDEO_MEM_SIZE;

board_video_init(pGD);

lcd->LCDSADDR1 = pGD->frameAdrs >> 1;

/* This marks the end of the frame buffer. */
lcd->LCDSADDR2 = (lcd->LCDSADDR1&0x1fffff) + (pGD->winSizeX+0) * pGD->winSizeY;
lcd->LCDSADDR3 = (pGD->winSizeX & 0x7ff);

/* Clear video memory */
memset((void *)pGD->frameAdrs, 0, pGD->memSize);

/* Enable Display */
lcd->LCDCON1 |= 0x01; /* ENVID = 1 */

return ((void*)&smi);
}

void
video_set_lut (unsigned int index, /* color number */
unsigned char r, /* red */
unsigned char g, /* green */
unsigned char b /* blue */
)
{
}

#endif /* CONFIG_VIDEO_S3C2410 */
【2】打开/drivers/video/Makefile,定位到
COBJS-y += videomodes.o
COBJS-y += s3c2410_fb.o
COBJS := $(COBJS-y)

【3】打开/drivers/video/cfb_console.c,定位到284行,修改如下:
#include
#define VIDEO_LOGO_WIDTH LINUX_LOGO_WIDTH
#define VIDEO_LOGO_HEIGHT LINUX_LOGO_HEIGHT
#define VIDEO_LOGO_LUT_OFFSET LINUX_LOGO_LUT_OFFSET
#define VIDEO_LOGO_COLORS LINUX_LOGO_COLORS
#endif /* CONFIG_VIDEO_BMP_LOGO */
//#define VIDEO_INFO_X (VIDEO_LOGO_WIDTH)
//#define VIDEO_INFO_Y (VIDEO_FONT_HEIGHT/2)
#define VIDEO_INFO_X (0)
#define VIDEO_INFO_Y (VIDEO_LOGO_HEIGHT)
#else /* CONFIG_VIDEO_LOGO */
#define VIDEO_LOGO_WIDTH 0
#define VIDEO_LOGO_HEIGHT 0
#endif /* CONFIG_VIDEO_LOGO */
【4】打开/drivers/video/videomodes.c,定位到98行附近,修改如下:
{0x31A, RES_MODE_1280x1024, 16},
{0x31B, RES_MODE_1280x1024, 24},
{0x211, RES_MODE_240x320, 16},
};
const struct ctfb_res_modes res_mode_init = {
/* x y pixclk le ri up lo hs vs s vmode */
{640, 480, 39721, 40, 24, 32, 11, 96, 2, 0, FB_VMODE_NONINTERLACED},
{800, 600, 27778, 64, 24, 22, 1, 72, 2, 0, FB_VMODE_NONINTERLACED},
{1024, 768, 15384, 168, 8, 29, 3, 144, 4, 0, FB_VMODE_NONINTERLACED},
{960, 720, 13100, 160, 40, 32, 8, 80, 4, 0, FB_VMODE_NONINTERLACED},
{1152, 864, 12004, 200, 64, 32, 16, 80, 4, 0, FB_VMODE_NONINTERLACED},
{1280, 1024, 9090, 200, 48, 26, 1, 184, 3, 0, FB_VMODE_NONINTERLACED},
{240, 320, 158025, 26, 6, 1, 11, 37, 2, 0, FB_VMODE_NONINTERLACED},
};
【5】打开/drivers/video/videomodes.h,定位到25行,修改如下:
//#ifndef CONFIG_SYS_DEFAULT_VIDEO_MODE
//#define CONFIG_SYS_DEFAULT_VIDEO_MODE 0x301
#ifndef CFG_SYS_DEFAULT_VIDEO_MODE
#define CFG_SYS_DEFAULT_VIDEO_MODE 0x211
#endif
/* Some mode definitions */
定位到83行,修改如下:
#define RES_MODE_1280x1024 5
//#define RES_MODES_COUNT 6
#define RES_MODE_240x320 6
#define RES_MODES_COUNT 7
//#define VESA_MODES_COUNT 19
#define VESA_MODES_COUNT 20
extern const struct ctfb_vesa_modes vesa_modes[];

【6】打开board/samsung/mini2440/mini2440.c,定位到30行,加入如下头文件:
#include
#include
#include
定位到138行附近,修改如下:
return 0;
}
#define MVAL (0)
#define MVAL_USED (0) //0=each frame 1=rate by MVAL
#define INVVDEN (1)

雪月 发表于 2011-11-11 23:50:10

//0=normal 1=inverted
#define BSWP (0) //Byte swap control
#define HWSWP (1) //Half word swap control

//TFT 240320
#define LCD_XSIZE_TFT_240320 (240)
#define LCD_YSIZE_TFT_240320 (320)
//TFT240320
#define HOZVAL_TFT_240320 (LCD_XSIZE_TFT_240320-1)
#define LINEVAL_TFT_240320 (LCD_YSIZE_TFT_240320-1)
//Timing parameter for NEC3.5"
#define VBPD_240320 (3)
#define VFPD_240320 (10)
#define VSPW_240320 (1)
#define HBPD_240320 (5)
#define HFPD_240320 (2)
#define HSPW_240320_NEC (36) //Adjust the horizontal displacement of the screen
#define HSPW_240320_TD (23) //64MB nand mini2440 is 36 ,128MB is 23
//+ ?--> - : <--
#define CLKVAL_TFT_240320 (3)
//FCLK=101.25MHz,HCLK=50.625MHz,VCLK=6.33MHz

void board_video_init(GraphicDevice *pGD)
{
S3C24X0_LCD * const lcd = S3C24X0_GetBase_LCD();
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
/* FIXME: select LCM type by env variable */

/* Configuration for GTA01 LCM on QT2410 */
lcd->LCDCON1 = 0x00000378; /* CLKVAL=4, BPPMODE=16bpp, TFT, ENVID=0 */
lcd->LCDCON2 = (VBPD_240320<<24)|(LINEVAL_TFT_240320<<14)|(VFPD_240320<<6)|(VSPW_240320);
lcd->LCDCON3 = (HBPD_240320<<19)|(HOZVAL_TFT_240320<<8)|(HFPD_240320);
if ( (nand->NFCONF) & 0x08 ) {
lcd->LCDCON4 = (MVAL<<8)|(HSPW_240320_TD);
}
else {
lcd->LCDCON4 = (MVAL<<8)|(HSPW_240320_NEC);
}

lcd->LCDCON5 = 0x00000f09;
lcd->LPCSEL = 0x00000000;
}

int dram_init (void)
{
gd->bd->bi_dram.start = PHYS_SDRAM_1;
gd->bd->bi_dram.size = PHYS_SDRAM_1_SIZE;
return 0;
}
【7】打开/lib_arm/board.c,定位到482行附近,修改如下:
#if defined(CONFIG_CFB_CONSOLE)
printf ("%s\n", version_string);
printf ("modified by singleboy(singleboy@163.com)\n"); //display on LCD
printf ("Love Linux forever!!\n");
#endif

/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop ();
}
【8】自定义开机logo
(1)如果先改成自己喜欢的图片,可以tools/logos/denx.bmp图片,也可将自己喜欢的图片放在tools/logos/目录下,记住一定图片大小不要起过你的屏的大小,色彩深度不能大于256色,即8位色深的图片8bpp的bmp图。不同的logo图片的大小标准对应不同的,这里S3C2440所对应的是160*96分辨率的BMP图片。
制作方法一:
可以用任何工具把需要处理的logo图片转换成bmp格式图片,大小160*96像素,色彩深度256色,即8bpp(8位色深),然后保存为你需要的文件名字,我的是logott.bmp。
制作方法二(未测试):
在制作图片前,请您现确认您的Linux主机上安装了Netpbm 工具包,如果没有,可以在 Netpbm主页下载源代码编译安装。
将你想要的图片裁减成160*96的JPG图片,然后用以下的脚本处理一下就好了:
#!/bin/sh
#install Netpbm first
jpegtopnm $1 | ppmquant 31 | ppmtobmp -bpp 8 > $2
使用方法: (脚本名) ( 待处理的JPG图片名) (输出文件名)
(2)打开/tools/Makefile,定位到124行附近,修改如下:
# Generated LCD/video logo
LOGO_H = $(OBJTREE)/include/bmp_logo.h
LOGO-$(CONFIG_LCD_LOGO) += $(LOGO_H)
LOGO-$(CONFIG_VIDEO_LOGO) += $(LOGO_H)
ifeq ($(LOGO_BMP),)
#LOGO_BMP= logos/denx.bmp
LOGO_BMP= logos/logott.bmp
endif
ifeq ($(VENDOR),atmel)
LOGO_BMP= logos/atmel.bmp
endif
ifeq ($(VENDOR),ronetix)
LOGO_BMP= logos/ronetix.bmp
endif
如果你将自己制作的logo命名成logos目录下denx.bmp而将之前的替换掉,这里的代码就不用修改了。
然后保存。
【9】打开include/configs/mini2440.h头文件,定位到138行附近,加入下面代码,即可将串口的打印信息显示在lcd上:
#define CONFIG_EXTRA_ENV_SETTINGS \
"stdin=serial\0" \
"stdout=vga\0" \
"stderr=serial\0" \
""
CONFIG_EXTRA_ENV_SETTINGS:系统默认的环境变量在/common/env_common.c的uchardefault_environment[]中,这个数组将所有的环境变量组织起来。而对于这个数组没有定义的环境变量可以在CONFIG_EXTRA_ENV_SETTINGS中由用户自定义。
只要让stdout等于vga就可以了。在lib_arm/board.c文件中可以看到console_init初始化两次,我们修改的影响第二次的初始化,对第一次的初始化不产生影响。
定位到定位到文件末尾处,加入下面代码:
/*
LCD video settings
*/
#define CONFIG_CFB_CONSOLE //Enables console device for a color framebuffer
#define CONFIG_SYS_VIDEO_LOGO_MAX_SIZE (240*320+1024+100) /* 100 = slack */
#define LCD_VIDEO_ADDR 0x33d00000
#define VIDEO_FB_16BPP_PIXEL_SWAP //the color palette,bpp is bits per pixel
#define CONFIG_VIDEO //Video support
#define CONFIG_VIDEO_S3C2410
#define CONFIG_VIDEO_LOGO //display Linux Logo in upper left corner
#define CONFIG_VIDEO_BMP_LOGO //use bmp_logo instead of linux_logo
#define CONFIG_CMD_BMP //BMP support
#define CONFIG_VIDEO_BMP_GZIP //Gzip compressed BMP image support
#define CONFIG_CMD_UNZIP
#define CFG_CONSOLE_INFO_QUIET //Suppress display of console information at boot.
#define CONFIG_SPLASH_SCREEN //enable splash screen support,implicitly enable U-Boot Bitmap Support.
//#define CONFIG_VIDEO_SW_CURSOR //Draws a cursor after the last character.No blinking is provided.
//Uses the macros CURSOR_SET and CURSOR_OFF.
//#define CONFIG_CONSOLE_EXTRA_INFO //Display additional board information to serial port beside the logo.
//This define requires a board specific function: video_drawstring() that fills a info buffer.
//#define CONFIG_CONSOLE_CURSOR //on/off drawing cursor is done with delay loop in VIDEO_TSTC_FCT
//#define CONFIG_CONSOLE_TIME //display time/date in upper right corner, needs CFG_CMD_DATE.
//#define VIDEO_FB_LITTLE_ENDIAN // framebuffer organisation default: big endian

/*for PC-keyboard*/
#define VIDEO_KBD_INIT_FCT 0 //init function for keyboard
#define VIDEO_TSTC_FCT serial_tstc //keyboard_tstc function
#define VIDEO_GETC_FCT serial_getc //keyboard_getc function

#endif /* __CONFIG_H */

相关配置选项说明:
CONFIG_CFB_CONSOLE:使能终端设备的彩色帧缓冲. 在/divers/video/cfb_console.c)有相关定义。
VIDEO_FB_LITTLE_ENDIAN 图像存储组织 (默认为大端序)
VIDEO_HW_RECTFILL 图像芯片支持矩形填充(rectangle fill)(cf. smiLynxEM)
VIDEO_HW_BITBLT 图像芯片支持位块传输(bit-blit) (cf. smiLynxEM)
VIDEO_VISIBLE_COLS 可视像素列 (cols=pitch)
VIDEO_VISIBLE_ROWS 可视像素行
VIDEO_PIXEL_SIZE 每像素字节数
VIDEO_DATA_FORMAT 图像数据格式 (0-5, cf. cfb_console.c)
VIDEO_FB_ADRS 帧缓冲地址
VIDEO_KBD_INIT_FCT keyboard int fct(i.e. i8042_kbd_init())
VIDEO_TSTC_FCT test char fct (i.e. i8042_tstc)
VIDEO_GETC_FCT get char fct (i.e. i8042_getc)
CONFIG_CONSOLE_CURSOR 打开/关闭 光标绘制 (需要 blink timer cf. i8042.c)
CFG_CONSOLE_BLINK_COUNT blink 间隔 (cf. i8042.c)
CONFIG_CONSOLE_TIME 在右上角显示时间/日期信息 (需要 CONFIG_CMD_DATE)
CONFIG_VIDEO_LOGO 在左上角显示Linux logo
CONFIG_VIDEO_BMP_LOGO 使用bmp_logo.h作为logo(默认是linux_logo.h)。 需要 CONFIG_VIDEO_LOGO。
CONFIG_CONSOLE_EXTRA_INFO 除了logo外的其它单板信息
如果定义了CONFIG_CFB_CONSOLE, 视频终端是默认的i/o. 使用'console=serial'环境可以强制使用串口终端
如果定义了 CONFIG_SILENT_CONSOLE, 可以用'silent'环境变量屏蔽所有终端消息(包括U-Boot和Linux的输出!)。更多信息见doc/README.silent
CONFIG_SYS_CONSOLE_IS_IN_ENV:如果你想将标准输入、标准输出、标准错误设为usbttyusbtty(USB串口终端),定义该宏。

CONFIG_VIDEO_BMP_GZIP:如果设置该选项, 除了支持标准BMP图像外, splashscreen或者bmp命令可以使用gzip压缩的BMP图像
CONFIG_SPLASH_SCREEN:如果设置该选项, 将检查环境变量"splashimage"。如果变量存在则显示一张BMP图像,普通的logo, 版权及系统信息不再显示。"splashimage"指定了位图的存放地址。终端也被重定向到"nulldev"。由于启动的早期就会加载Splashscreen,使用它可以实现安静的启动。
7.2 重新编译后nor档a命令下载,nand启动:

雪月 发表于 2011-11-11 23:50:16

可以看到左上角的logo图标换成了自己的制作的图标,下面启动信息与串口终端完全一样。LCD显示功能添加成功。
接下来为u-boot-2009.08添加USB驱动。
页: 1 [2] 3 查看完整版本: u-boot-2009.08在mini2440上的移植