文章寫于2010.4.17,總結(jié)了友善之臂的mini2440開發(fā)板使用自帶uboot的具體方法,希望能對正在使用mini2440開發(fā)板,而且又想使用uboot引導(dǎo)系統(tǒng)的朋友們有所幫助。
Google一下會發(fā)現(xiàn)網(wǎng)上類似的帖子不少,但是對mini2440開發(fā)板是哪一個版本都沒有具體的說明,個人感覺mini2440開發(fā)板的版本是經(jīng)常更新的,可能不同的版本的開發(fā)板在移植uboot時會稍有不同,因此這里我把自己使用的開發(fā)板的詳細信息都羅列一下,希望網(wǎng)友少走彎路。
另外,要感謝illidan和Martin兩位的文章:
http://www./2009/05/mini2440%E4%BD%BF%E7%94%A8u-boot/
http://www./bbs/viewthread.php?tid=14
使用的mini2440開發(fā)板的詳細信息:
kernel:linux-2.6.29-mini2440-20090708.tgz
gcc:arm-linux-gcc-4.3.2.tgz
uboot:bootloader.tgz(該壓縮包內(nèi)含有u-boot-1.1.6)
roots:root_qtopia-64M.img
問題源于:
(1)使用128M NAND Flash mini2440開發(fā)板的用戶都知道,此時開發(fā)板附帶的supervivi-64M和supervivi-128M都不再支持“空格”進入supervivi的menu菜單,而是改成了使用開發(fā)板上的k1~k6任何一個按鍵觸發(fā)進入menu(而我需要空格鍵觸發(fā)menu的方式);
(2)開發(fā)板附帶的supervivi不支持網(wǎng)絡(luò)下載kernel和root(文件系統(tǒng))。
具體的修改步驟如下:
注1:arm-linux-gcc的安裝方法見《mini2440-um-20090817.pdf》第5.3小節(jié)。
注2:mini2440開發(fā)板附帶的uboot源碼已經(jīng)是經(jīng)過移植的,適用s3c2440處理器,我們只需要修改一些uboot參數(shù)即可。
一、修改uboot源碼
(1)解壓出源碼
創(chuàng)建工作目錄
mkdir /tmp/workspace
cd /tmp/workspace
解壓mini2440開發(fā)板光盤附帶的uboot源碼,bootloader.tgz同時包含了u-boot-1.1.6和vivi的源碼
tar -xvf bootloader.tgz
cd u-boot-1.1.6
(2)修改u-boot-1.1.6/include/configs/open24x0.h文件
修改NAND FLASH MTD分區(qū)表:
56 /*
57 #define MTDPARTS_DEFAULT "mtdparts=nandflash0:2m@0(kernel)," \
58 "8m(jffs2)," \
59 "-(yaffs)"
60 */
61 #define MTDPARTS_DEFAULT "mtdparts=nandflash0:" \
62 "256k@0(boot)," \
63 "64k(env)," \
64 "2m(kernel)," \
65 "-(yaffs)"
注:該分區(qū)表一定要與內(nèi)核中的分區(qū)表一致,后面我會給出kernel中分區(qū)表的修改。
修改內(nèi)核啟動參數(shù):
把“mtdblock2” 改為“ mtdblock3 ”
133 //#define CONFIG_BOOTARGS "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0"
134 #define CONFIG_BOOTARGS "noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0"
注:此處一定要改,否則文件系統(tǒng)會加載失?。ù颂幨亲屛易钔纯嗟牡胤剑M了大量時間才找到這個癥結(jié)所在)
修改env參數(shù)保存位置:
221 //#define CFG_ENV_IS_IN_FLASH 1
222 #define CFG_ENV_IS_IN_NAND 1
223 #define CFG_ENV_OFFSET 0x40000
224 #define CFG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */
注1:env是uboot引導(dǎo)系統(tǒng)時用到的一系列參數(shù),是可修改的,如果不改動此處,env修改后,即使執(zhí)行saveenv命令,斷電后也會丟失。
注2:注意一下223和224行,這兩行定義了env保存在nand flash的具體位置,與MTD分區(qū)表中的"64k(env)," 是對應(yīng)的(64K=0x40000 - 0x10000)。
(3)修改u-boot-1.1.6/include/asm-arm/mach-types.h文件
修改machine ID
377 //#define MACH_TYPE_S3C2440 362
378 #define MACH_TYPE_S3C2440 1999
注1:查看linux-2.6.29/include/asm/mach-types.h會發(fā)現(xiàn)machine ID為1999
1985 #define MACH_TYPE_MINI2440 1999
注2:對于此處的修改Martin給出了他的經(jīng)驗:
“查看u-boot-1.1.6/board/open24×0/open24×0.c與linux-2.6.29/include/asm/mach-types.h,發(fā)現(xiàn)Machine ID果然設(shè)置的不對。mini2440的ID是1999,而u-boot中設(shè)置的是三星官方的362。改完,刷寫,重啟。
依然不靈。
這就有點土了。沒有仿真器,沒有打印信息,我和mini2440之間又不能通過腦電波交流…冥思苦想中,我進入了準(zhǔn)無意識狀態(tài),大腦在迷惘,手指在不停地用NOR或者NAND啟動mini2440。突然,我感到有什么東西不對。隱隱約約的,我似乎看到了什么東西,不應(yīng)該出現(xiàn)的東西。定定神,一行一行地翻看串口console日志,貌似每一行都很正常,但最后我停在了SuperVIVI啟動的一行語句上面:”Machine ID: 782″。
782?為什么會是782?我grep了一下linux-2.6.29/include/asm/mach-types.h,782是MACH_TYPE_PNX4008。先不想那么多,改成782試試。改完,刷寫,重啟。
Kernel成功啟動了。
回過頭研究782,不由啞然失笑。原來是這個linux-2.6.29移植的有點潦草,defconfig中的宏定義前后不一致,使得Machine ID沒有設(shè)置為預(yù)想的值。好吧,這個問題就留在這里吧,也是一種不和諧美?!?/SPAN>
注3:Martin用的可能是較老的mini2440開發(fā)板,我這一版已經(jīng)解決了他提的這個問題,如果跟我的kernel一樣,應(yīng)該改為1999。
(4)修改uboot功能菜單,增加tftp下載功能選項
修改u-boot-1.1.6/common/cmd_menu.c文件,
在原文件中添加146~149行:
142 void main_menu_usage(void)
143 {
144 printf("\r\n##### uboot for mini2440 #####\r\n");
145
146 printf("[1] TFTP Install U-boot\r\n");
147 printf("[2] TFTP Install Linux kernel\r\n");
148 printf("[3] TFTP Install JFFS2 root\r\n");
149 printf("[4] TFTP Install YAFFS root\r\n");
150 printf(" Download u-boot\r\n");
151
152 #ifdef CONFIG_SURPORT_WINCE
153 printf("[e] Download Eboot\r\n");
154 #endif
155 printf("[k] Download Linux kernel\r\n");
156 #ifdef CONFIG_SURPORT_WINCE
157 printf("[w] Download WinCE NK.bin\r\n");
158 #endif
159 printf("[j] Download JFFS2 image\r\n");
160 printf("[y] Download YAFFS image\r\n");
161 printf("[d] Download to SDRAM & Run\r\n");
162 printf(" Boot the system\r\n");
163 printf("[f] Format the Nand Flash\r\n");
164 printf("[s] Set the boot parameters\r\n");
165 printf("[r] Reboot u-boot\r\n");
166 printf("[q] Quit from menu\r\n");
167 printf("Enter your selection: ");
168 }
在原文件menu_shell函數(shù)中添加200~235行
171 void menu_shell(void)
172 {
173 char c;
174 char cmd_buf[200];
175 char *p = NULL;
176 unsigned long size;
177 unsigned long offset;
178 struct mtd_info *mtd = &nand_info[nand_curr_device];
179
180 while (1)
181 {
182 main_menu_usage();
183 c = awaitkey(-1, NULL);
184 printf("%c\n", c);
185 switch (c)
186 {
187 case 'u':
188 {
189 if (bBootFrmNORFlash())
190 {
191 strcpy(cmd_buf, "usbslave 1 0x30000000; protect off all; erase 0 +$(filesize); cp.b 0x30000000 0 $(filesize)");
192 }
193 else
194 {
195 strcpy(cmd_buf, "usbslave 1 0x30000000; nand erase bios; nand write.jffs2 0x30000000 bios $(filesize)");
196 }
197 run_command(cmd_buf, 0);
198 break;
199 }
200 case '1':
201 {
202 if (bBootFrmNORFlash())
203 {
204 strcpy(cmd_buf, "tftp 0x30000000 u-boot.bin; protect off all; erase 0 +$(filesize); cp.b 0x30000000 0 $(filesize)");
205 }
206 else
207 {
208 strcpy(cmd_buf, "tftp 0x30000000 u-boot.bin; nand erase boot; nand write.jffs2 0x30000000 boot $(filesize)");
209 }
210 run_command(cmd_buf, 0);
211 break;
212 }
213 case '2':
214 {
215 strcpy(cmd_buf, "tftp 0x30000000 uImage; nand erase kernel; nand write.jffs2 0x30000000 kernel $(filesize)");
216 run_command(cmd_buf, 0);
217 #ifdef CONFIG_SURPORT_WINCE
218 if (!TOC_Read())
219 TOC_Erase();
220 #endif
221 break;
222 }
223 case '3':
224 {
225 strcpy(cmd_buf, "tftp 0x30000000 rootfs.jffs2; nand erase jffs2; nand write.jffs2 0x30000000 jffs2 $(filesize)");
226 run_command(cmd_buf, 0);
227 break;
228 }
229
230 case '4':
231 {
232 strcpy(cmd_buf, "tftp 0x30000000 rootfs.yaffs; nand erase yaffs; nand write.yaffs 0x30000000 yaffs $(filesize)");
233 run_command(cmd_buf, 0);
234 break;
235 }
236
237 #ifdef CONFIG_SURPORT_WINCE
238 case 'e':
239 {
240 offset = EBOOT_BLOCK * mtd->erasesize;
241 size = EBOOT_BLOCK_SIZE * mtd->erasesize;
242 sprintf(cmd_buf, "nand erase 0x%x 0x%x; usbslave 1 0x30000000; nand write 0x30000000 0x%x $(filesize)", offset, size, offset);
243 run_command(cmd_buf, 0);
244 break;
245 }
246 #endif
247
248 case 'k':
249 {
250 strcpy(cmd_buf, "usbslave 1 0x30000000; nand erase kernel; nand write.jffs2 0x30000000 kernel $(filesize)");
251 run_command(cmd_buf, 0);
252 #ifdef CONFIG_SURPORT_WINCE
253 if (!TOC_Read())
254 TOC_Erase();
255 #endif
256 break;
257 }
(5)重新編譯
cd /tmp/workspace/u-boot-1.1.6
make clean
make distclean
make
編譯完成后會在tmp/workspace/u-boot-1.1.6目錄下發(fā)現(xiàn)u-boot.bin文件,即是我們需要的uboot鏡像文件。
(6)安裝mkimag工具
cp /tmp/workspace/u-boot-1.1.6/tools/mkimage /usr/sbin
注:該工具必須安裝,后面編譯內(nèi)核要用到。因為,uboot不支持zImage格式,我們需要mkiamge將內(nèi)核編譯成uImage格式。
二、修改kernel源碼
(1)解壓源碼
cd /tmp/workspace
tar -xvf linux-2.6.29-mini2440-20090708.tgz
cd linux-2.6.29
(2)修改inux-2.6.29/arch/arm/plat-s3c24xx/common-friendly-arm.c文件
cd /tmp/workspace/inux-2.6.29
49 /*
50 static struct mtd_partition friendly_arm_default_nand_part[] = {
51 [0] = {
52 .name = "supervivi",
53 .size = 0x00060000,
54 .offset = 0,
55 },
56 [1] = {
57 .name = "Kernel",
58 .offset = 0x00060000,
59 .size = 0x00200000,
60 },
61 [2] = {
62 .name = "root",
63 .offset = 0x00260000,
64 .size = 1024 * 1024 * 1024, //64U * 1024 * 1024 - 0x00260000,
65 },
66 [3] = {
67 .name = "nand",
68 .offset = 0x00000000,
69 .size = 1024 * 1024 * 1024, //64U * 1024 * 1024 - 0x00260000,
70 }
71 };
72 */
73 //modified by sunny, 2010.4.16 13:24
74 static struct mtd_partition friendly_arm_default_nand_part[] = {
75 [0] = {
76 .name = "boot",
77 .size = 0x00040000,
78 .offset = 0,
79 },
80 [1] = {
81 .name = "env",
82 .offset = 0x00040000,
83 .size = 0x00010000,
84 },
85 [2] = {
86 .name = "kernel",
87 .offset = 0x00050000,
88 .size = 0x00200000, //64U * 1024 * 1024 - 0x00260000,
89 },
90 [3] = {
91 .name = "root",
92 .offset = 0x00250000,
93 .size = 0x03db0000, //64U * 1024 * 1024 - 0x00260000,
94 }
95 };
注:該分區(qū)表是與u-boot-1.1.6/include/configs/open24x0.h文件對應(yīng)的,自己可以研究一下。
(3)重新編譯內(nèi)核,詳細見《mini2440-um-20090817.pdf》第六章 定制 Linux 內(nèi)核及制作文件系統(tǒng)
cd /tmp/workspace/linux-2.6.29
cp config_mini2440_t35 .config
make uIamge
注1:注意是make uImage而不是zImage了,編譯uImage也會生成zImage,生成的位置仍然在 /tmp/workspace/linux-2.6.29/arch/arm/boot/
注2:此處需要根據(jù)自己實際用的開發(fā)板選擇,我用的開發(fā)板帶的是T35的顯示屏,因此選用onfig_mini2440_t35
三、安裝tftpserver工具到xp
(1)將mini2440光盤中帶的tftpd32拷貝到自己的PC上,具體位置在"windows平臺工具\tftpboot",整個目錄都拷貝下來,放在任何地方皆可。
(2)打開tftpd32.exe,設(shè)置一下“Current Directory”,選擇你要存放u-boot.bin,uImage,rootfs.yaffs的目錄(假設(shè)為C:\Program Files\tftpboot\download)。
(3)“Server Interface”選擇你的網(wǎng)口的IP(假設(shè)ip地址為192.168.1.10)。
(4)單擊“Show Dir”,如果能看到C:\Program Files\tftpboot\download目錄下的文件,則說明你的tftpd設(shè)置成功。
注1:root_yaffs實際為mini2440帶的root鏡像文件(root_qtopia-64M.img或root_qtopia-128M.img)
注2:這三個鏡像文件的名字必須為u-boot.bin(uboot),uImage(內(nèi)核),rootfs.yaffs(文件系統(tǒng)),這與uboot的功能菜單程序有關(guān)。
四、燒寫u-boot.bin,uImage,root_yaffs
(1)用網(wǎng)線將pc和開發(fā)板連接,將u-boot.bin,uImage,rootfs.yaffs鏡像文件拷貝到C:\Program Files\tftpboot\download目錄。
(2)燒寫u-boot.bin
對于該文件的燒寫你可以直接用norflash帶的supervivi燒寫(用【a】選項即可);也可以用jtag電纜從并口燒寫。
燒寫完u-boot.bin后,從nand flash啟動,發(fā)現(xiàn)uboot啟動后,按下空格鍵進入uboot功能菜單;
進入uboot功能菜單后,按下空格鍵,進入uboot命令窗口;
輸入printenv命令,可顯示當(dāng)前的env設(shè)置;
發(fā)現(xiàn)serverip=192.168.1.1,更改為192.168.1.10(因為你的PC當(dāng)前的ip為192.168.1.10),輸入下面的命令:
setenv serverip 192.168.1.10
saveenv
或者你也可以改變自己pc的ip為192.168.1.1
輸入menu命令重新回到uboot功能菜單
按下1鍵重新下載u-boot.bin到nand flash(也可以不用重新下載)
(3)燒寫kernel
在uboot功能菜單按下2鍵下載uImage到nand flash
(4)燒寫root_yaffs
在uboot功能菜單按下4鍵下載root_yaffs到nand flash
注:開始我下載的時候,PC機與mini2440開發(fā)板是通過交換機連接的,下載uImage和u-boot.bin都沒問題,但是下載root_yaffs是總是會出現(xiàn)crc error提示,
后來用一根網(wǎng)線直連的方式下載時,crc error消失,可能是我的交換機不好吧,如果大家用交換機時也出現(xiàn)這個問題,我們共同討論一下。
終于寫完了,寫的比較匆忙,如有錯誤還望大家指正!