宿主机环境:
Linux version 2.6.32-24, Ubuntu10.04
gcc version 4.1.3, Thread model: posix;
GNU Make 3.81
arm-linux-gcc 3.4.5

开发板环境:
CPU: S3C2410X
SDRAM: HY57V561620(32MB)
FLASH: K9F1208(64MB)
Linux Kernel: 2.6.23.8

移植步骤:
运行kernel的时候,我们会发现如下的错误:

JFFS2 version 2.2. (NAND) .. 2001-2006 Red Hat, Inc.
io scheduler noop registered
io scheduler anticipatory registered (default)
io scheduler deadline registered
io scheduler cfq registered
s3c2410-lcd s3c2410-lcd: no platform data for lcd, cannot attach
s3c2410-lcd: probe of s3c2410-lcd failed with error -22

lp: driver loaded but no devices found
ppdev: user-space parallel port driver
Serial: 8250/16550 driver $Revision: 1.90 $ 4 ports, IRQ sharing enabled
s3c2410-uart.0: s3c2410_serial0 at MMIO 0×50000000 (irq = 70) is a S3C2410
s3c2410-uart.1: s3c2410_serial1 at MMIO 0×50004000 (irq = 73) is a S3C2410
s3c2410-uart.2: s3c2410_serial2 at MMIO 0×50008000 (irq = 76) is a S3C2410
RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize

表示与LCD相关的平台信息没有找到,因此没法加载LCD。 我们所要做的就是将对LCD设备的初始化加入到整个S3C2410的初始化过程中。

通过对arch/arm/mach-smdk2410/mach-smdk2410.c与arch/arm/mach-smdk2440/mach-smdk2440.c进行对比后,可以发现在smdk2440上存在着对结构体s3c2410fb_mach_info的初始化,而smdk2410则不存在,所以我们所要做的是把smdk2440上的初始化操作复制到smdk2410上,并做一定的修改。

rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8$ vim arch/arm/mach-s3c2410/mach-smdk2410.c

#include <asm/plat-s3c24xx/common-smdk.h>

#include <asm/arch/smdk2410.h> // sean chi 18Aug2010, added.
#include <asm/arch/fb.h> // sean chi 31Aug2010, added.

static struct map_desc smdk2410_iodesc[] __initdata = {
{ vSMDK2410_ETH_IO , pSMDK2410_ETH_IO, SZ_1M, MT_DEVICE }, // sean chi 18Aug2010, added.
/* nothing here yet */
};

// sean chi 31Aug2010, added.
static struct s3c2410fb_mach_info nano2410_fb_info __initdata = {
.fixed_syncs = 1,
.type = S3C2410_LCDCON1_TFT,
.width        = 240,
.height        = 320,
.xres        = {
.min    = 240,
.max    = 240,
.defval    = 240,
},

.yres        = {
.min    = 320,
.max    = 320,
.defval = 320,
},

.bpp        = {
.min    = 16,
.max    = 16,
.defval = 16,
},
.regs    = {

.lcdcon1    = S3C2410_LCDCON1_TFT16BPP |
S3C2410_LCDCON1_TFT |
S3C2410_LCDCON1_CLKVAL(0×04),

.lcdcon2    = S3C2410_LCDCON2_VBPD(1) |
S3C2410_LCDCON2_LINEVAL(319) |
S3C2410_LCDCON2_VFPD(5) |
S3C2410_LCDCON2_VSPW(1),

.lcdcon3    = S3C2410_LCDCON3_HBPD(36) |
S3C2410_LCDCON3_HOZVAL(239) |
S3C2410_LCDCON3_HFPD(19),

.lcdcon4    = S3C2410_LCDCON4_MVAL(13) |
S3C2410_LCDCON4_HSPW(5),

.lcdcon5    = S3C2410_LCDCON5_FRM565 |
S3C2410_LCDCON5_INVVLINE|
S3C2410_LCDCON5_INVVFRAME|
S3C2410_LCDCON5_PWREN|
S3C2410_LCDCON5_HWSWP,
},
#if 1
.gpccon            =0xaaaaaaaa,
.gpccon_mask    =0xffffffff,
.gpcup            =0xffffffff,
.gpcup_mask        =0xffffffff,

.gpdcon            =0xaaaaaaaa,
.gpdcon_mask    =0xffffffff,
.gpdup            =0xffffffff,
.gpdup_mask        =0xffffffff,

#endif
.lpcsel        = 0×01,
};

……

…….

static void __init smdk2410_init(void)
{
s3c24xx_fb_set_platdata(&nano2410_fb_info); // sean chi 31Aug2010, added.
platform_add_devices(smdk2410_devices, ARRAY_SIZE(smdk2410_devices));
smdk_machine_init();
}

在对源代码进行修改了以后,配置内核,将Device Driver->Graphic support下的Support for frame buffer devices, S3C2410 LCD framebuffer support和Bootup logo勾选上。

rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8$ make menuconfig

Device Driver –>

Graphics support ->

<*>Support for frame buffer devices

<*>S3C2410 LCD framebuffer support

<*>Bootup logo

对于其他版本来说,在这里可以重新编译内核,加载到开发板上运行就可以了,但在linux kernel 2.6.23上,这还不够,这时候如果编译加载的话,会在开发板上显示如下结果:

io scheduler noop registered
io scheduler anticipatory registered (default)
io scheduler deadline registered
io scheduler cfq registered
Unable to handle kernel NULL pointer dereference at virtual address 00000014
pgd = c0004000
[00000014] *pgd=00000000
Internal error: Oops: 805 [#1]
Modules linked in:
CPU: 0 Not tainted (2.6.23.8 #18)
PC is at s3c2410fb_set_lcdaddr+0×94/0xb4
LR is at 0xc02fdb48
pc : [] lr : [] psr: 60000013
sp : c03ebe24 ip : c02fdb48 fp : c03ebe40
r10: c02fc714 r9 : c0333d60 r8 : c02fc70c
r7 : c0305358 r6 : 19e80000 r5 : 19e92c00 r4 : 000000f0
r3 : 00000014 r2 : 00000001 r1 : 00000001 r0 : 00000025
Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel
Control: c000717f Table: 30004000 DAC: 00000017
Process swapper (pid: 1, stack limit = 0xc03ea258)
Stack: (0xc03ebe24 to 0xc03ec000)
be20: c3c4025c c4a00000 c0305358 c0333d60 c03ebe60 c03ebe44 c014f03c
be40: c014e500 00000000 c3c4025c c3c40000 00000000 c03ebe9c c03ebe64 c001afa0
be60: c014ef7c c3c4025c c3c400a8 00000020 c03dd454 c02fc714 00000000 c03052c8
be80: c03052c8 c0337038 c0024860 00000000 c03ebeac c03ebea0 c0179df0 c001aad4
bea0: c03ebed0 c03ebeb0 c0177f30 c0179de0 c02fc7d4 c02fc714 c0178090 c03052c8
bec0: c03ea000 c03ebee8 c03ebed4 c0178110 c0177e58 00000000 c03ebeec c03ebf14
bee0: c03ebeec c0176f44 c01780a0 c0309250 c0309250 c02fc75c 00000000 c03052c8
bf00: c03052d0 c0309164 c03ebf24 c03ebf18 c0178190 c0176f04 c03ebf4c c03ebf28
bf20: c017770c c0178180 c03052c8 00000000 00000000 c0023410 c03ea000 00000000
bf40: c03ebf60 c03ebf50 c017860c c01776a8 00000000 c03ebf70 c03ebf64 c0179f04
bf60: c017859c c03ebf80 c03ebf74 c014f284 c0179ea8 c03ebff4 c03ebf84 c0008c3c
bf80: c014f280 e1a00007 e89da9f0 00000000 00000001 e24cb004 00000000 00000000
bfa0: 00000000 c03ebfb0 c002cec4 c0044b38 00000000 00000000 c0008b5c c004aee8
bfc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
bfe0: 00000000 00000000 00000000 c03ebff8 c004aee8 c0008b6c 1580302c e5943018
Backtrace:
[] (s3c2410fb_set_lcdaddr+0×0/0xb4) from [] (s3c2410fb_init_registers+0xd0/0×144)
r7:c0333d60 r6:c0305358 r5:c4a00000 r4:c3c4025c
[] (s3c2410fb_init_registers+0×0/0×144) from [] (s3c2410fb_probe+0x4dc/0x5e8)
r7:00000000 r6:c3c40000 r5:c3c4025c r4:00000000
[] (s3c2410fb_probe+0×0/0x5e8) from [] (platform_drv_probe+0×20/0×24)
[] (platform_drv_probe+0×0/0×24) from [] (driver_probe_device+0xe8/0x18c)
[] (driver_probe_device+0×0/0x18c) from [] (__driver_attach+0×80/0xe0)
r8:c03ea000 r7:c03052c8 r6:c0178090 r5:c02fc714 r4:c02fc7d4
[] (__driver_attach+0×0/0xe0) from [] (bus_for_each_dev+0×50/0×84)
r5:c03ebeec r4:00000000
[] (bus_for_each_dev+0×0/0×84) from [] (driver_attach+0×20/0×28)
r7:c0309164 r6:c03052d0 r5:c03052c8 r4:00000000
[] (driver_attach+0×0/0×28) from [] (bus_add_driver+0×74/0x1b0)
[] (bus_add_driver+0×0/0x1b0) from [] (driver_register+0×80/0×88)
[] (driver_register+0×0/0×88) from [] (platform_driver_register+0x6c/0×88)
r4:00000000
[] (platform_driver_register+0×0/0×88) from [] (s3c2410fb_init+0×14/0x1c)
[] (s3c2410fb_init+0×0/0x1c) from [] (kernel_init+0xe0/0x29c)
[] (kernel_init+0×0/0x29c) from [] (do_exit+0×0/0×748)
Code: e3530000 e1a01004 1bfbec4f e3a03014 (e4836004)
Kernel panic – not syncing: Attempted to kill init!

通过上面错误信息中的Backtrace,可以看到问题出在一个名为s3c2410fb_lcd_setaddr的函数上。在源代码中找到这个函数,存在于drivers/video/s3c2410fb.c文件里,通过对Linux 2.6.22, 2.6.23, 2.6.24的对比,发现对这段函数做如下代码修改即可,原因末知,发了邮件给写这部分代码的Ben Dooks大神询问,末回。。。

static void s3c2410fb_set_lcdaddr(struct s3c2410fb_info *fbi)
{
struct fb_var_screeninfo *var = &fbi->fb->var;
void __iomem *regs = fbi->io; // sean chi 31Aug2010, added.
unsigned long saddr1, saddr2, saddr3;

saddr1 = fbi->fb->fix.smem_start >> 1;
saddr2 = fbi->fb->fix.smem_start;
saddr2 += (var->xres * var->yres * var->bits_per_pixel)/8;
saddr2>>= 1;

saddr3 = S3C2410_OFFSIZE(0) | S3C2410_PAGEWIDTH((var->xres * var->bits_per_pixel / 16) & 0x3ff);

dprintk(“LCDSADDR1 = 0x%08lx\n”, saddr1);
dprintk(“LCDSADDR2 = 0x%08lx\n”, saddr2);
dprintk(“LCDSADDR3 = 0x%08lx\n”, saddr3);

writel(saddr1, regs + S3C2410_LCDSADDR1); // sean chi 31Aug2010, was writel(saddr, S3C2410_LCDSADDR1);
writel(saddr2, regs + S3C2410_LCDSADDR2);
writel(saddr3, regs + S3C2410_LCDSADDR3);

}

除此之外,还要把drivers/video/fbmem.c中的register_framebuffer做如下修改:

/**
* register_framebuffer – registers a frame buffer device
* @fb_info: frame buffer info structure
*
* Registers a frame buffer device @fb_info.
*
* Returns negative errno on error, or zero for success.
*
*/

int
register_framebuffer(struct fb_info *fb_info)
{
int i;
struct fb_event event;
struct fb_videomode mode;

if (num_registered_fb == FB_MAX)
return -ENXIO;
num_registered_fb++;
for (i = 0 ; i < FB_MAX; i++) if (!registered_fb[i]) break; fb_info->node = i;

fb_info->dev = device_create(fb_class, fb_info->device,
MKDEV(FB_MAJOR, i), “fb%d”, i);
if (IS_ERR(fb_info->dev)) {
/* Not fatal */
printk(KERN_WARNING “Unable to create device for framebuffer %d; errno = %ld\n”, i, PTR_ERR(fb_info->dev));
fb_info->dev = NULL;
} else
fb_init_device(fb_info);

if (fb_info->pixmap.addr == NULL) {
fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
if (fb_info->pixmap.addr) {
fb_info->pixmap.size = FBPIXMAPSIZE;
fb_info->pixmap.buf_align = 1;
fb_info->pixmap.scan_align = 1;
fb_info->pixmap.access_align = 32;
fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;
}
}
fb_info->pixmap.offset = 0;

if (!fb_info->pixmap.blit_x)
fb_info->pixmap.blit_x = ~(u32)0;

if (!fb_info->pixmap.blit_y)
fb_info->pixmap.blit_y = ~(u32)0;

if (!fb_info->modelist.prev || !fb_info->modelist.next)
INIT_LIST_HEAD(&fb_info->modelist);

fb_var_to_videomode(&mode, &fb_info->var);
fb_add_videomode(&mode, &fb_info->modelist);
registered_fb[i] = fb_info;

event.info = fb_info;
// sean chi 31Aug2010, removed. fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);

return 0;
}

否则将会出现kernel的启动过程hang掉的情况,至于为什么这么改的原因。。。我也不知道,同样问了Ben Dooks大神,没回。。。

对Linux2.6.23进行这样的修改将会导致启动后LCD屏上不会显示LOGO, 原因在于Linux启动时LOGO的加载是由fb_notifier_call_chain调用的,但由于我们之前把fb_notifier_call_chain从启动过程中去掉了,因此我们不会看到LOGO,但通过编写应用程序对/dev/fb0进行读写依然可以在LCD屏上画出图像。

宿主机环境:
Linux version 2.6.32-24, Ubuntu10.04
gcc version 4.1.3, Thread model: posix;
GNU Make 3.81
arm-linux-gcc 3.4.5

开发板环境:
CPU: S3C2410X
SDRAM: HY57V561620(32MB)
FLASH: K9F1208(64MB)
NET: CS8900
Linux Kernel: 2.6.23.8

移植步骤:

使用s3c2410的默认配置文件编译出来的内核不能识别USB设备,在插上U盘的时候,内核会显示如下内容:

usb 1-1: new full speed USB device using s3c2410-ohci and addr2
usb 1-1: device descriptor read/64, error -62
usb 1-1: device descriptor read/64, error -62
usb 1-1: new full speed USB device using s3c2410-ohci and address 3
usb 1-1: device descriptor read/64, error -62
usb 1-1: device descriptor read/64, error -62
usb 1-1: new full speed USB device using s3c2410-ohci and address 4
usb 1-1: device not accepting address 4, error -62
usb 1-1: new full speed USB device using s3c2410-ohci and address 5
usb 1-1: device not accepting address 5, error -62

这里有两个问题需要解决,一个是”device not accepting address #, error -62″, 另外一个就是在查看partition下的分区信息的时候,没有出现usb设备:

[root@armsys /]# cat /proc/partitions

major minor  #blocks  name

31     0         16 mtdblock0
31     1       2048 mtdblock1
31     2       4096 mtdblock2
31     3       2048 mtdblock3
31     4       4096 mtdblock4
31     5      10240 mtdblock5
31     6      24576 mtdblock6
31     7      16384 mtdblock7

为了解决”error -62″的问题,我们需要修改drivers/usb/host/ohci-s3c2410.c:

rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8$ vim drivers/usb/host/ohci-s3c2410.c

#include <asm/hardware.h>
#include <asm/arch/usb-control.h>
#if 1 // sean chi 20Aug2010, added.
#include <asm/arch-s3c2410/regs-clock.h>
#include <asm-arm/io.h>

unsigned long upllvalue = (0×78 << 12) | (0×02 << 4) | (0×03);
#endif

#define valid_port(idx) ((idx) == 1 || (idx) == 2)

/* clock device associated with the hcd */

…………

static void s3c2410_start_hc(struct platform_device *dev, struct usb_hcd *hcd)
{
struct s3c2410_hcd_info *info = dev->dev.platform_data;

dev_dbg(&dev->dev, “s3c2410_start_hc:\n”);

clk_enable(usb_clk);
mdelay(2);            /* let the bus clock stabilise */

clk_enable(clk);

if (info != NULL) {
info->hcd    = hcd;
info->report_oc = s3c2410_hcd_oc;

if (info->enable_oc != NULL) {
(info->enable_oc)(info, 1);
}
}

// sean chi 20Aug2010, added.
while (upllvalue !=__raw_readl(S3C2410_UPLLCON))
{
__raw_writel(upllvalue, S3C2410_UPLLCON);
mdelay(1);
}

}

之后,我们需要重新配置内核,确保勾选以下选项

Device Drivers —>
[*] USB support —>
[*]   Support for Host-side USB
[*]     USB device filesystem
[*]     OHCI HCD support
[*]   USB Mass Storage support
[*]   The shared table of common (or usual) storage devices

SCSI device support —>

[*] SCSI device support
[*] SCSI target support
[*] legacy /proc/scsi/ support
[*] SCSI disk support

重新编译, 加载新的内核,这样从根文件系统上查看分区信息就可以看到usb设备的分区信处sda, sda1。

[root@armsys /]# cat /proc/partitions

major minor  #blocks  name

31     0         16 mtdblock0
31     1       2048 mtdblock1
31     2       4096 mtdblock2
31     3       2048 mtdblock3
31     4       4096 mtdblock4
31     5      10240 mtdblock5
31     6      24576 mtdblock6
31     7      16384 mtdblock7
8     0    3895296 sda
8     1    3891200 sda1

挂载USB设备:

[root@armsys /]# mount -t vfat /dev/sda1 /mnt

出现如下错误:

Unable to load NLS charset cp437
FAT: codepage cp437 not found
mount: mounting /dev/sda1 on /mnt failed: Invalid argument

这时,需要make menuconfig时选择cp437的支持:

File systems —>
-*- Native language support —>
— Native language support
[*] Codepage 437 (United States, Canada)
[*]  NLS ISO 8859-1 (Latin 1; Western European Languages)
当然也可以设置其他编码方式:
[*] Simplified Chinese charset (CP936, GB2312)
[*] ASCII (United States)
[*] NLS UTF-8

重新编译后,加载内核就可以读取USB设备里的内容了。

参考资料:

linux-2.6.28系统移植s3c6410开发板USB不能识别的处理
USB error-62
Linux 2.6.24.4移植到S3C2410(nano2410)之:USB
linux-2.6.28 s3c2410上添加USB和SD卡设备

宿主机环境:
Linux version 2.6.32-24, Ubuntu10.04
gcc version 4.1.3, Thread model: posix;
GNU Make 3.81
arm-linux-gcc 3.4.5

开发板环境:
CPU: S3C2410X
SDRAM: HY57V561620(32MB)
FLASH: K9F1208(64MB)
Linux Kernel: 2.6.23.8

移植步骤:
将前面生成的内核加载到开发板中的时候,我们可以发现以下的内容:

s3c2410-wdt s3c2410-wdt: watchdog inactive, reset disabled, irq enabled
TCP cubic registered
NET: Registered protocol family 1
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
IP-Config: Complete:
device=eth0, addr=10.12.33.38, mask=255.255.255.0, gw=10.12.33.254,

红色字体部分表示S3C2410的RTC支持已经在kernel中,但是没有将rtc device加入SMDK2410 targetboard的device列表中,所以我们需要将RTC加入初始化的设备列表中。

修改文件arch/arm/mach-s3c2410/mach-smdk2410.c,在数组smdk2410_devices[]中添加&s3c_device_rtc:

rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8$ cd arch/arm/mach-s3c2410/
rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8/arch/arm/mach-s3c2410$ vim mach-smdk2410.c

static struct platform_device *smdk2410_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c,
&s3c_device_iis,
&s3c_device_rtc, // sean chi 20Aug2010, added.
};

static void __init smdk2410_map_io(void)
{
s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc));

重新编译内核后,加载内核到开发板,发现以下内容:

S3C24XX RTC, (c) 2004,2006 Simtec Electronics
s3c2410-rtc s3c2410-rtc: rtc disabled, re-enabling
s3c2410-rtc s3c2410-rtc: rtc core: registered s3c as rtc0
…………
NET: Registered protocol family 1
s3c2410-rtc s3c2410-rtc: hctosys: invalid date/time
IP-Config: Complete:
device=eth0, addr=10.12.33.38, mask=255.255.255.0, gw=10.12.33.254,

以上信息表示RTC设备已经初始化成功。红色字体问题表示从硬件时钟(hc)处读到的时间转换到系统时钟(sys)的过程发生错误,硬件时钟传递的时间参数是一个不合法的时间参数(invalid date/time)。从内核函数int rtc_valid_tm(struct rtc_time *tm),可以看出,当year小于1970时,认为是时间 invalid,函数返回-EINVAL。

/*
* Does the rtc_time represent a valid date/time?
*/
int rtc_valid_tm(struct rtc_time *tm)
{
if (tm->tm_year < 70
|| ((unsigned)tm->tm_mon) >= 12
|| tm->tm_mday < 1
|| tm->tm_mday > rtc_month_days(tm->tm_mon, tm->tm_year + 1900)
|| ((unsigned)tm->tm_hour) >= 24
|| ((unsigned)tm->tm_min) >= 60
|| ((unsigned)tm->tm_sec) >= 60)
return -EINVAL;

return 0;
}

从根文件系统上运行hwclock可以看到,hwclock的初始值是小于1970的,也验证了上面所说出现invalid date/time的原因:

[root@armsys /]# hwclock
Wed Dec 31 23:59:59 1969 0.000000 seconds

所以我们需要设置正确的系统时间,然后再把系统时间传递给RTC:

[root@armsys /]# date 082013342010.0
Fri Aug 20 13:34:00 UTC 2010

[root@armsys /]# hwclock -w
[root@armsys /]# hwclock
Fri Aug 20 13:34:42 2010 0.000000 seconds

为了使系统时间和RTC时间同步,可以在初始化文件中添加命令

hwclock –s

使每次开机时读取RTC时间,并同步给系统时间。

[root@armsys /]# vi /etc/init.d/rcS

#! /bin/sh
echo “Processing etc/init.d/rc.s”

#hostname ${HOSTNAME}

echo “Mount all”
/bin/mount -a

echo “Start mdev….”
/bin/echo /sbin/mdev >proc/sys/kernel/hotplug
mdev -s

echo “Set RTC…”
/sbin/hwclock -s

echo “******************************************”
echo ” rookiesean’s rootfs ”
echo ” 8Aug2010 ”
echo “******************************************”
echo

搞定。

参考资料:
Linux 2.6.24.4移植到S3C2410(nano2410)之:RTC

主机环境:
Linux version 2.6.32-24, Ubuntu10.04
gcc version 4.1.3, Thread model: posix;
GNU Make 3.81
arm-linux-gcc 3.4.5

所需源文件:
busybox-1.9.2.tar.bz2

Busybox创建nfs文件系统:

1. 解压busybox-1.9.2.tar.bz2后,修改Makefile中的ARCH和CROSS_COMPILE与本机的路径一致

rookiesean@rookiesean-desktop:~/workspace$ cd busybox-1.9.2/
rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2$ vi Makefile

ARCH ?= arm
CROSS_COMPILE ?= /usr/local/arm/arm-9tdmi-linux-gnu/bin/arm-9tdmi-linux-gnu-

2. 编译busybox, 首先运行make menuconfig

rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2$ make menuconfig

大部分的menu config都可以自定义,但是这里有几个是必须要选上的

Busybox Settings —>
Build Options —>
[*] Build BusyBox as a static binary (no shared libs)
//若想直接编译成静态库,勾选此选项,若想使用动态链接,则不选。
Installation Options —>
[*] Don’t use /usr
//不用本机的目录,否则生成的/bin/*会覆盖本机的/bin/*文件,会导致宿主机损坏。
Shells —>
Choose your default shell (ash) —>
//这里选择shell为ash,应该是默认选中的
— ash
//把ash这档的选项全部选上

保存退出,执行以下命令编译生成busybox基本文件:

rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2$ make
rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2$ make install

在make的过程中,有可能遇到这样的问题:

applets/applets.c:20:2: error: #warning Static linking against glibc produces buggy executables
applets/applets.c:21:2: error: #warning (glibc does not cope well with ld –gc-sections).
applets/applets.c:22:2: error: #warning See sources.redhat.com/bugzilla/show_bug.cgi?id=3400
applets/applets.c:23:2: error: #warning Note that glibc is unsuitable for static linking anyway.
applets/applets.c:24:2: error: #warning If you still want to do it, remove -Wl,–gc-sections
applets/applets.c:25:2: error: #warning from top-level Makefile and remove this warning.
make[1]: *** [applets/applets.o] Error 1

这个警告的定义在applets/applets.c中, 它的意思是告诉你最好用uclibc编译,而不是用glibc因为glibc比较大,busybox在寸土寸金的嵌入式系统中运用比较多,所以会有这样的要求。

解决方案是去掉这一段注释:

rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2$ vim applets/applets.c

/* vi: set sw=4 ts=4: */
/*
* Stub for linking busybox binary against libbusybox.
*
* Copyright (C) 2007 Denys Vlasenko <vda.linux@googlemail.com>
*
* Licensed under GPLv2, see file License in this tarball for details.
*/

#include <assert.h>
#include “busybox.h”

/* Apparently uclibc defines __GLIBC__ (compat trick?). Oh well. */
#if ENABLE_STATIC && defined(__GLIBC__) && !defined(__UCLIBC__)
//#warning Static linking against glibc produces buggy executables
//#warning (glibc does not cope well with ld –gc-sections).
//#warning See sources.redhat.com/bugzilla/show_bug.cgi?id=3400
//#warning Note that glibc is unsuitable for static linking anyway.
//#warning If you still want to do it, remove -Wl,–gc-sections
//#warning from scripts/trylink and remove this warning.
//#error Aborting compilation.

#endif

或者按照Warning message的提示,到scripts/trylink里面移掉-Wl跟–gc-sections.

3. 用shell脚本创建根文件系统的目录结构
rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2$ vim makedir.sh

#!/bin/sh
echo “makeing rootdir”
mkdir rootfs
cd rootfs

echo “makeing dir: bin dev etc lib proc sbin sys usr”
mkdir bin dev etc lib proc sbin sys usr #8 dirs
mkdir usr/bin usr/lib usr/sbin lib/modules

#Don’t use mknod, unless you run this Script as
#mknod -m 600 dev/console c 5 1
#mknod -m 666 dev/null c 1 3

echo “making dir: mnt tmp var”
mkdir mnt tmp var
chmod 1777 tmp
mkdir mnt/etc mnt/jiffs2 mnt/yaffs mnt/data mnt/temp
mkdir var/lib var/lock var/log var/run var/tmp
chmod 1777 var/tmp

echo “making dir: home root boot”
mkdir home root boot
echo “done”

执行makedir.sh:

rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2$ sh makedir.sh

将会在busybox目录下生成文件夹rootfs, 以及rootfs里一批文件夹及文件:

rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2$ cd rootfs/
rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2/rootfs$ ls
bin boot dev etc home lib mnt proc root sbin sys tmp usr var

4. 将busybox源码目录下etc里的内容拷贝到rootfs下在的etc

rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2/rootfs$ cp ../examples/bootfloppy/etc/* ./etc/

5. 修改拷贝过来的profile文件

rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2/rootfs$ cd etc/
rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2/rootfs/etc$ vim profile

# /etc/profile: system-wide .profile file for the Bourne shells

echo
echo -n “Processing /etc/profile… ”
# no-op

#sean chi 29Aug2010, added, set search library path
echo “Set search library path”
export LD_LIBRARY_PATH=/lib:/usr/lib

#sean chi 29Aug2010, added, set user path
echo “Set user path”
PATH=/bin:/sbin:/usr/bin:/usr/sbin
export PATH

#sean chi 29Aug2010, added, set PS1
echo “Set PS1″
HOSTNAME=`/bin/hostname`
export PS1=”\\e[32m[$USER@$HOSTNAME \\w\\a]\\$\\e[00;37m "

echo "Done"
echo

6. 修改inittab与fstab文件

rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2/rootfs/etc$ vim inittab

::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
::restart:/sbin/init

tty2::askfirst:-/bin/sh
::ctrlaltdel:/bin/umount -a -r
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a

rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2/rootfs/etc$ vim fstab

proc /proc proc defaults 0 0
none /tmp ramfs defaults 0 0
mdev /dev ramfs defaults 0 0
sysfs /sys sysfs defaults 0 0

7. 修改初始化脚本文件init.d/rcS

rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2/rootfs/etc$ vim init.d/rcS

#! /bin/sh
echo "Processing etc/init.d/rcS"

echo "Mount all"
/bin/mount -a

echo "Start mdev..."
/bin/echo /sbin/mdev > proc/sys/kernel/hotplug

mdev -s

echo "**********************************"
echo " "
echo " rootFS created by Sean chi 29Aug "
echo " "
echo "**********************************"
echo

8. 创建一个空的mdev.conf文件,在挂载根文件系统时会用到的

rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2/rootfs/etc$ touch mdev.conf

9. 把busybox默认安装目录中的文件全部复制到这里的rootfs中。会发现多了linuxrc -> bin/busybox文件,这是挂载文件系统需要执行的,基本上和init相同,入口都是init_main,在init/init.c里面。至于init,一般是读/etc/inittab,根据里面的定义运行若干子进程

rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2/rootfs$ cp ../_install/* ./ -r

如果编译busybox时选择动态库方式编译,则需要查看生成的busybox使用哪些动态库,然后把它们拷贝到rootfs/lib目录下。

rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2/rootfs$cd bin
rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2/rootfs/bin$ /usr/local/arm/arm-9tdmi-linux-gnu/bin/arm-9tdmi-linux-gnu-readelf -d busybox

得到如下结果:

Dynamic segment at offset 0xd46c8 contains 22 entries:
Tag                   Type                         Name/Value
0x00000001 (NEEDED)                     Shared library: [libcrypt.so.1]
0×00000001 (NEEDED)                     Shared library: [libm.so.6]
0×00000001 (NEEDED)                     Shared library: [libc.so.6]
0x0000000c (INIT)                              0xd5d4
0x0000000d (FINI)                              0xbdfbc
0×00000004 (HASH)                           0×8128
0×00000005 (STRTAB)                     0xace8
0×00000006 (SYMTAB)                    0x8d38
0x0000000a (STRSZ)                          5067 (bytes)
0x0000000b (SYMENT)                     16 (bytes)
0×00000015 (DEBUG)                         0×0
0×00000003 (PLTGOT)                       0xe47b4
0×00000002 (PLTRELSZ)                  3080 (bytes)
0×00000014 (PLTREL)                       REL
0×00000017 (JMPREL)                      0xc9cc
0×00000011 (REL)                              0xc58c
0×00000012 (RELSZ)                        1088 (bytes)
0×00000013 (RELENT)                     8 (bytes)
0x6ffffffe (VERNEED)                          0xc4ac
0x6fffffff (VERNEEDNUM)                 3
0x6ffffff0 (VERSYM)                         0xc0b4
0×00000000 (NULL)                          0×0

所以我们从交叉编译工具链的库文件目录下面拷取以下的文件(自编译交叉工具链的具体操作见《嵌入式Linux移植 – 使用crosstool创建自己的交叉编译器》一文):

rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2/rootfs/bin$ cd ../lib/
rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2/rootfs/lib$ cp /usr/local/arm/arm-9tdmi-linux-gnu/arm-9tdmi-linux-gnu/lib/ld* ./
rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2/rootfs/lib$ cp /usr/local/arm/arm-9tdmi-linux-gnu/arm-9tdmi-linux-gnu/lib/libc-2.3.6.so ./
rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2/rootfs/lib$ cp /usr/local/arm/arm-9tdmi-linux-gnu/arm-9tdmi-linux-gnu/lib/libc.so.6 ./
rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2/rootfs/lib$ cp /usr/local/arm/arm-9tdmi-linux-gnu/arm-9tdmi-linux-gnu/lib/libm.so.6 ./
rookiesean@rookiesean-desktop:~/workspace/busybox-1.9.2/rootfs/lib$ cp /usr/local/arm/arm-9tdmi-linux-gnu/arm-9tdmi-linux-gnu/lib/libcrypt.so.1 ./

对busybox的配置工作完成。在对宿主机和开发板的bootloader配置,使其能以NFS的形式加载内核后,启动开发板,得到如下显示:

Looking up port of RPC 100005/1 on 10.12.33.30
VFS: Mounted root (nfs filesystem).
Freeing init memory: 132K
init started: BusyBox v1.9.2 (2010-08-29 15:45:16 CST)
starting pid 772, tty ”: ‘/etc/init.d/rcS’
Processing etc/init.d/rcS
Mount all
Start mdev…
**********************************

rootFS created by Sean chi 29Aug

**********************************

starting pid 776, tty ”: ‘/bin/sh’

Processing /etc/profile… Set search library path
Set user path
Set PS1
Done

[root@armsys /]#

根文件系统顺利加载。

参考资料:
用busybox创建基于Linux2.6.24内核的nfs根文件系统
Linux2.6.24.4 根文件系统移植到S3C2410

宿主机环境:
Linux version 2.6.32-24, Ubuntu10.04
gcc version 4.1.3, Thread model: posix;
GNU Make 3.81
arm-linux-gcc 3.4.5

开发板环境:
CPU: S3C2410X
SDRAM: HY57V561620(32MB)
FLASH: K9F1208(64MB)
NET: CS8900
Linux Kernel: 2.6.23.8

所需源文件:
cs8900.tar.gz

移植步骤:

下载上面所给出的cs8900.tar.bz2文件,解压缩到drivers/net/arm/目录下面。

rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8$ cd drivers/net/arm/
rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8/drivers/net/arm$ tar xvf /home/rookiesean/Downloads/cs8900.tar.bz2

在/drivers/net/arm/Kconfig中增加menu config中CS8900编译选项。

rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8/drivers/net/arm$ vim Kconfig

config ARM_CS8900
tristate “CS8900 support (sean chi 18Aug2010, added)”
depends on NET_ETHERNET && ARM && ARCH_SMDK2410
help
Support for CS8900A chipset based Ethernet cards. If you have a
network card of this type, say Y and read the EthernetHOWTO, available
from as well as. To compile this driver as a module, choose M here and
read. The module will be called cs8900.o

在/drivers/net/arm/Makefile中添加如下内容:

rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8/drivers/net/arm$ vim Makefile

obj-$(CONFIG_ARM_CS8900) += cs8900.o#sean chi 18Aug2010, added.

然后我们在include/asm-arm/arch-s3c2410/目录下面创建一个smdk2410.h的头文件。

rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8$ cd include/asm-arm/arch-s3c2410/
rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8/include/asm-arm/arch-s3c2410$ vim smdk2410.h

添加如下代码:

#define pSMDK2410_ETH_IO __phys_to_pfn(0×19000000)
#define vSMDK2410_ETH_IO 0xE0000000
#define SMDK2410_EHT_IRQ IRQ_EIN

修改arch/arm/mach-s3c2410/mach-smdk2410.c文件,包含新创建的smdk2410.h头文件,并在map_desc smdk2410_iodesc[]
中添加cs8900的对于的io空间映射:

rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8$ cd arch/arm/mach-s3c2410/
rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8/arch/arm/mach-s3c2410$ vi mach-smdk2410.c

#include <asm/plat-s3c24xx/devs.h>
#include <asm/plat-s3c24xx/cpu.h>

#include <asm/plat-s3c24xx/common-smdk.h>

#include <asm/arch/smdk2410.h> // sean chi 18Aug2010, added.

static struct map_desc smdk2410_iodesc[] __initdata = {
{ vSMDK2410_ETH_IO , pSMDK2410_ETH_IO, SZ_1M, MT_DEVICE }, // sean chi 18Aug2010, added.
/* nothing here yet */
};

#define UCON S3C2410_UCON_DEFAULT
#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE

执行menu config。 Device drivers->network device support->Ethernet中选择(*)CS8900 support。

编译内核make zImage。

通过uboot把zImage加载到SDRAM的0×30008000处,接着运行新的内核。

SMDK2410 # tftp 30008000 zImage.sean.cs8900
SMDK2410 # g 30008000

可以看到如下结果,表示添加对cs8900的支持成功。

dm9000 Ethernet Driver
Cirrus Logic CS8900A driver for Linux (Modified for SMDK2410)
eth0: CS8900A rev E at 0xe0000300 irq=53, addr: 00: 0:3E:26:0A: 0
Uniform Multi-Platform E-IDE driver Revision: 7.00alpha2
ide: Assuming 50MHz system bus speed for PIO modes; override with idebus=xx

参考资料:
Linux 2.6.24.4移植到S3C2410(nano2410)之:CS8900移植

宿主机环境:
Linux version 2.6.32-24, Ubuntu10.04
gcc version 4.1.3, Thread model: posix;
GNU Make 3.81
arm-linux-gcc 3.4.5

开发板环境:
CPU: S3C2410X
SDRAM: HY57V561620(32MB)
FLASH: K9F1208(64MB)
NET: CS8900

所需源文件:
Linux-2.6.23.8.tar.bz2

移植步骤:

首先运行命令解压缩内核文件到工作目录。

rookiesean@rookiesean-desktop:~/workspace$ tar xvf ../Downloads/linux-2.6.23.8.tar.bz2

在解压得到linux内核文件后,为方便以后的编译过程,修改Makefile文件,指定ARCH及CROSS COMPILE工具链目录。

rookiesean@rookiesean-desktop:~/workspace$ cd linux-2.6.23.8
rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8$ vim Makefile

# CROSS_COMPILE specify the prefix used for all executables used
# during compilation. Only gcc and related bin-utils executables
# are prefixed with $(CROSS_COMPILE).
# CROSS_COMPILE can be set on the command line
# make CROSS_COMPILE=ia64-linux-
# Alternatively CROSS_COMPILE can be set in the environment.
# Default value for CROSS_COMPILE is not to prefix executables
# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile

ARCH ?= arm#sean chi 17Aug2010, was $(SUBARCH).
CROSS_COMPILE ?= /usr/local/arm/arm-9tdmi-linux-gnu/bin/arm-9tdmi-linux-gnu-#sean chi 17Aug2010, was blank

# Architecture as present in compile.h
UTS_MACHINE := $(ARCH)

在这里,我们的ARCH是arm, 交叉编译工具链使用《嵌入式Linux系统移植-使用crosstool创建自己的交叉编译器》中生成的交叉编译工具链。注意ARCH ?= arm后面不跟空格,否则在make menuconfig的时候会出现以下错误:

rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8$ make menuconfig

make: *** /home/rookiesean/workspace/linux-2.6.23.8/arch/arm: 是一个目录。 停止。

设置完Makefile之后,为方便起见,我们把linux内核文件中已有的对s3c2410的配置文件设为默认的配置文件。

rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8$ cp arch/arm/configs/s3c2410_defconfig .config

在运行make menuconfig之前,我们还要确认系统中已经安装了ncurses-devel(redhat 或者 FC的安装程序),Ubuntu上则是libncurses5-dev, 否则会出现如下错误:

rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8$ make menuconfig

HOSTCC scripts/kconfig/lxdialog/checklist.o
In file included from scripts/kconfig/lxdialog/checklist.c:24:
scripts/kconfig/lxdialog/dialog.h:32:20: error: curses.h: 没有那个文件或目录
In file included from scripts/kconfig/lxdialog/checklist.c:24:
scripts/kconfig/lxdialog/dialog.h:97: error: expected specifier-qualifier-list before ‘chtype’
scripts/kconfig/lxdialog/dialog.h:187: error: expected ‘)’ before ‘*’ token
scripts/kconfig/lxdialog/dialog.h:194: error: expected ‘)’ before ‘*’ token
scripts/kconfig/lxdialog/dialog.h:196: error: expected ‘)’ before ‘*’ token
…………
scripts/kconfig/lxdialog/checklist.c:232: warning: implicit declaration of function ‘wrefresh’
scripts/kconfig/lxdialog/checklist.c:293: warning: implicit declaration of function ‘delwin’
scripts/kconfig/lxdialog/checklist.c:297: error: ‘KEY_LEFT’ undeclared (first use in this function)
scripts/kconfig/lxdialog/checklist.c:298: error: ‘KEY_RIGHT’ undeclared (first use in this function)
scripts/kconfig/lxdialog/checklist.c:310: warning: implicit declaration of function ‘on_key_esc’
scripts/kconfig/lxdialog/checklist.c:312: error: ‘KEY_RESIZE’ undeclared (first use in this function)
make[1]: *** [scripts/kconfig/lxdialog/checklist.o] 错误 1
make: *** [menuconfig] 错误 2

暂时不对menuconfig进行任何操作,保存新的配置文件退出后运行make

rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8$ make

发现如下错误:

…………
drivers/mtd/nand/s3c2410.c:63:32: asm/arch/regs-nand.h: No such file or directory
drivers/mtd/nand/s3c2410.c:64:27: asm/arch/nand.h: No such file or directory
drivers/mtd/nand/s3c2410.c: In function `s3c2410_nand_inithw’:
drivers/mtd/nand/s3c2410.c:195: error: dereferencing pointer to incomplete type
drivers/mtd/nand/s3c2410.c:196: error: dereferencing pointer to incomplete type
drivers/mtd/nand/s3c2410.c:197: error: dereferencing pointer to incomplete type
…………

打开drivers/mtd/nand/s3c2410.c, 修改第62行及63行中所包含的头文件如下所示:

rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8$ vi drivers/mtd/nand/s3c2410.c

#include <asm/io.h>

#if 0 // sean chi 17Aug2010, modified.
#include <asm/arch/regs-nand.h>
#include <asm/arch/nand.h>
#else
#include <asm/plat-s3c/regs-nand.h>
#include <asm/plat-s3c/nand.h>
#endif

#ifdef CONFIG_MTD_NAND_S3C2410_HWECC
static int hardware_ecc = 1;
#else
static int hardware_ecc = 0;
#endif

修改后重新编译通后,运行make zImage生成zImage文件。

rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8$ make
rookiesean@rookiesean-desktop:~/workspace/linux-2.6.23.8$ make zImage

将arch/arm/boot/目录下的zImage拷贝到宿主机的/tftpboot目录下后,使用minicom连接到开发板,通过uboot把zImage加载到SDRAM的0×30008000处,接着运行新的内核。

SMDK2410 # tftp 30008000 zImage.sean.newkernel
SMDK2410 # go 30008000

发现以下错误:

TCP cubic registered
NET: Registered protocol family 1
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
IP-Config: Device `eth0′ not found.
Looking up port of RPC 100003/2 on 10.12.33.30
rpcbind: server 10.12.33.30 not responding, timed out
Root-NFS: Unable to get nfsd port number from server, using default
Looking up port of RPC 100005/1 on 10.12.33.30
rpcbind: server 10.12.33.30 not responding, timed out
Root-NFS: Unable to get mountd port number from server, using default
mount: server 16.0.0.0 not responding, timed out
Root-NFS: Server returned error -5 while mounting /armsys2410/root
VFS: Unable to mount root fs via NFS, trying floppy.
VFS: Cannot open root device “nfs” or unknown-block(2,0)
Please append a correct “root=” boot option; here are the available partitions:
1f00 16 mtdblock0 (driver?)
1f01 2048 mtdblock1 (driver?)
1f02 4096 mtdblock2 (driver?)
1f03 2048 mtdblock3 (driver?)
1f04 4096 mtdblock4 (driver?)
1f05 10240 mtdblock5 (driver?)
1f06 24576 mtdblock6 (driver?)
1f07 16384 mtdblock7 (driver?)
Kernel panic – not syncing: VFS: Unable to mount root fs on unknown-block(2,0)

由于这里是通过网络使用NFS的形式去加载根文件系统,所以从以上的错误我们可以得知是网卡配置的问题,通过添加对CS8900网卡的支持以解决这个问题。

参考资料:
Linux 2.6.24.4移植到S3C2410(nano2410)之:内核移植篇

crosstool官网上下载解压crosstool后,对demo-*.sh, gcc-*glibc-*.dat脚本进行配置,配置方法参照《嵌入式Linux系统移植-使用crosstool创建自己的交叉编译器》

配置好crosstool后,运行demo-*.sh脚本有可能得到如下错误:

rookiesean@rookiesan-laptop:~/workspace/crosstool-0.43$ ./demo-arm9tdmi.sh

……………….
……………….
applying patch /home/rookiesean/workspace/crosstool-0.43/patches/glibc-2.3.6/arm-ctl_bus_isa.patch
getandpatch.sh: 1: patch: not found
patch /home/rookiesean/workspace/crosstool-0.43/patches/glibc-2.3.6/arm-ctl_bus_isa.patch failed

安装patch以解决这一问题

rookiesean@rookiesan-laptop:~/workspace/crosstool-0.43$ sudo apt-get install patch

…………………………
…………………………
/home/rookiesean/workspace/crosstool-0.43/crosstool.sh: 110: bison: not found
crosstool: You don’t have bison installed

安装bison以解决这一问题。

rookiesean@rookiesan-laptop:~/workspace/crosstool-0.43$ sudo apt-get install bison

…………………………
…………………………
/home/rookiesean/workspace/crosstool-0.43/crosstool.sh: 111: flex: not found
crosstool: You don’t have flex installed

安装flex以解决这个问题

rookiesean@rookiesan-laptop:~/workspace/crosstool-0.43$ sudo apt-get install flex

………………………..
………………………..
configure: error:
*** These critical programs are missing or too old: as ld
*** Check the INSTALL file for required versions.

这里重点讲一下以上的错误。出现这种情况是因为Ubuntu默认所安装的binutils版本为binutils-2.20, 当binutils太新的时候,crosstool只好将它当成太老的版本,报告说too old; as ld. 于是我们需要重新编译安装一个老版本的binutils, 2.19或者2.18都可以被crosstool所识别,这里拿binutils-2.18举例。但还有一个问题,Ubuntu10.04默认安装的gcc版本是gcc-4.4.3,跟binutils-2.20一样,太高版本的gcc对语法要求更为严格,这样会导致binutils-2.18无法轻松的编译通过,于是我们需要编译安装一个老版本的gcc, 4.1的版本可以编译成功binutils-2.18。在Ubuntu10.04可以通过

rookiesean@rookiesan-laptop:~/workspace/crosstool-0.43$ sudo apt-get install gcc-4.1

安装gcc-4.1。安装完成后运行如下命令:

rookiesean@rookiesan-laptop:~/workspace/crosstool-0.43$ cd /usr/bin
rookiesean@rookiesan-laptop:/usr/bin$ sudo rm gcc
rookiesean@rookiesan-laptop:/usr/bin$ sudo ln -sf gcc-4.1 gcc
rookiesean@rookiesan-laptop:/usr/bin$ gcc -v

得到如下显示:

Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v –enable-languages=c,c++ –prefix=/usr –enable-shared –with-system-zlib –libexecdir=/usr/lib –without-included-gettext –enable-threads=posix –enable-nls –with-gxx-include-dir=/usr/include/c++/4.1.3 –program-suffix=-4.1 –enable-__cxa_atexit –enable-clocale=gnu –enable-libstdcxx-debug –with-tune=generic –enable-checking=release i486-linux-gnu
Thread model: posix
gcc version 4.1.3 20080704 (prerelease) (Ubuntu 4.1.2-27ubuntu1)

表明原先指向gcc-4.4的的符号链接已经被重新指向新安装的gcc-4.1,系统中默认的gcc版本为4.1。

下载binutils-2.18, 将其解压缩后,进入binutils顶层目录,运行

rookiesean@rookiesan-laptop:~/workspace/binutils-2.18$ ./configure –prefix=/home/rookiesean/temp/binutils –disable-nls
rookiesean@rookiesan-laptop:~/workspace/binutils-2.18$ make all
rookiesean@rookiesan-laptop:~/workspace/binutils-2.18$ make install

其中–prefix=/home/rookiesean/temp/binutils表示生成可执行文件的存放位置,可自定义。

编译成功后在/home/rookiesean/temp/binutils/bin/中就生成了ld as程序的可执行文件, 到/usr/bin目录下面将系统默认的ld和as替换成2.18版本的:

rookiesean@rookiesan-laptop:~/workspace/binutils-2.18$ cd /usr/bin
rookiesean@rookiesan-laptop:/usr/bin$ sudo rm as ld
rookiesean@rookiesan-laptop:/usr/bin$ sudo ln -sf /home/rookiesean/temp/binutils/bin/ld ld
rookiesean@rookiesan-laptop:/usr/bin$ sudo ln -sf /home/rookiesean/temp/binutils/bin/as as
rookiesean@rookiesan-laptop:/usr/bin$ ld -v; as -v

得到如下显示:

GNU ld (GNU Binutils) 2.18
GNU assembler version 2.18 (i686-pc-linux-gnu) using BFD version (GNU Binutils) 2.18

表示系统默认的binutils版本已经变换为2.18版本。

接下来,就可以运行demo-*.sh建立属于自己的交叉编译器了。

rookiesean@rookiesan-laptop:~/workspace/crosstool-0.43$ ./demo-arm9tdmi.sh

等一下,还有一个错误。。。-_-!

In file included from version.c:33:
/home/rookiesean/workspace/crosstool-0.43/build/arm-9tdmi-linux-gnu/gcc-3.4.5-glibc-2.3.6/build-glibc/csu/version-info.h:2: error: missing terminating ” character
/home/rookiesean/workspace/crosstool-0.43/build/arm-9tdmi-linux-gnu/gcc-3.4.5-glibc-2.3.6/build-glibc/csu/version-info.h:3: error: missing terminating ” character
version.c:40: error: syntax error before string constant
make[2]: *** [/home/rookiesean/workspace/crosstool-0.43/build/arm-9tdmi-linux-gnu/gcc-3.4.5-glibc-2.3.6/build-glibc/csu/version.o] 错误 1
make[2]:正在离开目录 `/home/rookiesean/workspace/crosstool-0.43/build/arm-9tdmi-linux-gnu/gcc-3.4.5-glibc-2.3.6/glibc-2.3.6/csu’
make[1]: *** [csu/subdir_lib] 错误 2
make[1]:正在离开目录 `/home/rookiesean/workspace/crosstool-0.43/build/arm-9tdmi-linux-gnu/gcc-3.4.5-glibc-2.3.6/glibc-2.3.6′
make: *** [lib] 错误 2

老版本的glibc在/bin/sh为dash的时候会出现这个问题,一种解决方法是把/bin/sh重定向为bash,在创建完交叉编译器后可以将/bin/sh重新改回dash,运行如下面命令修改/bin/sh:

rookiesean@rookiesan-laptop:~/workspace/crosstool-0.43$ cd /bin
rookiesean@rookiesan-laptop:/bin$ sudo mv /bin/sh sh.old
rookiesean@rookiesan-laptop:/bin$ sudo ln -sf bash /bin/sh
rookiesean@rookiesan-laptop:/bin$ sh –version

得到如下显示:

GNU bash, version 4.1.5(1)-release (i486-pc-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

搞定,继续编译crosstool并使用自己的交叉编译器吧。

参考资料:
ubuntu10.04下建立交叉编译工具链支持软浮点
How to cross-compile?

在嵌入式系统移植的过程中,必不可少的一样东西是交叉编译器,只有使用交叉编译器才可以把原先在宿主机(相信大多数人所使用的宿主机会是Linux x86系统的)上所编写的程序交叉编译成开发板(如ARM系统或PPC系统)所识别的二进制形式。 对于一些成熟的移植过程来说,互联网上存在已经制作好的交叉编译器,只要下载过来解压缩配置后就可以使用了。但在使用这些交叉编译器的过程中可能存在着一些问题,由于自己机子上的某些环境不一样,会导致使用这些交叉编译器编译出来的内核,bootloader存在这样或那样的问题。为了去除交叉编译器对今后的编译工作带来的错误影响,最好创建属于自己的交叉编译器。

手动创建交叉编译器相当复杂,对于一般的嵌入式程序开发员来说,这部分知识并不是必须的。幸好我们有Dan Kegel所写的创建交叉编译器的脚本工具crosstool。从crosstool官方网站上下载crosstool的最新版本(0.43之后就再没更新过),解压缩后进入crosstool顶层目录,如下所示,workspace是我的工作目录,Downloads是我的下载目录:

rookiesean@rookiesean-desktop:~/workspace$ tar zxvf ../Downloads/cross-3.4.3.tgz
rookiesean@rookiesean-desktop:~/workspace$ cd crosstool-0.43/

查看crosstool文件夹中,可以看到目录下有很多demo-*.sh脚本和*.dat配置文件。首先需要找到你要交叉编译的平台CPU所对应的demo-*.sh脚本,比如说我要交叉编译的平台是三星的S3C2410,它的CPU是ARM9T,则选用demo-arm9tdmi.sh。对其进行如下修改:

rookiesean@rookiesean-desktop:~/crosstool-0.43$ vim demo-arm9tdmi.sh

#!/bin/sh
# This script has one line for each known working toolchain
# for this architecture. Uncomment the one you want.
# Generated by generate-demo.pl from buildlogs/all.dats.txt

set -ex
TARBALLS_DIR=/home/rookiesean/Downloads
RESULT_TOP=/home/rookiesean/temp
export TARBALLS_DIR RESULT_TOP
GCC_LANGUAGES=”c,c++”
export GCC_LANGUAGES

# Really, you should do the mkdir before running this,
# and chown /opt/crosstool to yourself so you don’t need to run as root.
mkdir -p $RESULT_TOP

#eval `cat arm9tdmi.dat gcc-3.2.3-glibc-2.2.5.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.2.3-glibc-2.3.2.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.2.3-glibc-2.3.2-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.3.6-glibc-2.2.5.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.3.6-glibc-2.3.2.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.3.6-glibc-2.3.2-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.2.5.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.3.2.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.3.2-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.3.5.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.3.5-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.3.6.dat` sh all.sh –notest
eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.3.6-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.0.2-glibc-2.3.2.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.0.2-glibc-2.3.2-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.0.2-glibc-2.3.5.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.0.2-glibc-2.3.5-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.0.2-glibc-2.3.6.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.0.2-glibc-2.3.6-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.1.0-glibc-2.3.2.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.1.0-glibc-2.3.2-tls.dat` sh all.sh –notest

echo Done.

TARBALLS_DIR是指创建crosstool过程中所需要的glibc, binutils, gcc等程序的tar.bz2文件所要存放的位置, 这里我把他们放在我的下载目录。crosstool可以自动的从网上下载所需的程序,但由于crosstool在下载的过程中选择的服务器会是国外的官方服务器,会比较慢,最好在build过程之前从网上把这些所需要的文件下载过来放到TARBALLS_DIR中,具体所需要的文件会在下面做介绍。

RESULT_TOP指的是编译好后所生成的交叉编译器存放的目录,一定要改到有写权限的目录,不然无法编译。这里我把他放在我的临时目录中。

eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.3.6-tls.dat` sh all.sh –notest

表示使用cross-tools顶层目录下的arm9tdmi.dat(根据CPU类型选择)和gcc-3.4.5-glibc-2.3.6-tls.dat(根据想要使用的gcc版本和glibc版本进行选择)来进行交叉编译器的创建。在crosstool官方网站的buildlog页面上可以看到各种CPU和GCC+Glibc版本那些已经编译成功,那些部分成功,那些彻底失败。

在修改好demo-*.sh脚本后,打开所选定的arm9tdmi.dat和 gcc-3.4.5-glibc-2.3.6-tls.dat文件

rookiesean@rookiesean-desktop:~/crosstool-0.43$ vim arm9tdmi.dat

KERNELCONFIG=`pwd`/arm.config
TARGET=arm-9tdmi-linux-gnu
GCC_EXTRA_CONFIG=”–with-cpu=arm9tdmi –enable-cxx-flags=-mcpu=arm9tdmi”
TARGET_CFLAGS=”-O”

这里没什么好修改的。

rookiesean@rookiesean-desktop:~/crosstool-0.43$ vim gcc-3.4.5-glibc-2.3.6-tls.dat

BINUTILS_DIR=binutils-2.15
GCC_DIR=gcc-3.4.5
GLIBC_DIR=glibc-2.3.6
LINUX_DIR=linux-2.6.23.8
LINUX_SANITIZED_HEADER_DIR=linux-libc-headers-2.6.12.0
GLIBCTHREADS_FILENAME=glibc-linuxthreads-2.3.6

将这里的LINUX_DIR改成你真正想要移植的Linux版本,然后这里的binutils-2.15, gcc-3.4.5, glibc-2.3.6, linux-2.6.23.8, linux-libc-headers-2.6.12.0, glibc-linuxthreads-2.3.6就是你所要下载后放到之前提到的TARBALLS_DIR里的文件(必须是tar.bz2文件)。

最后一步:进入crosstool-0.43目录,输入./demo-arm9tdmi.sh(为免勿操作,crosstool强制使用非root用户才可以运行demo脚本),然后就是泡茶、看书。经过不到1小时的编译,就可以在${RESULT_TOP}目录中看到想要的工具链、头文件、库文件等文件了。

Ubuntu10.04在创建交叉编译器时所遇到的问题及解决方案

在GRUB2里改变默认的内核启动顺序
ubuntu9.10之前的发行版采用的是menu.list来配置系统的默认启动内核,而在ubunt9.10以后,使用的是Grub2,配置方法跟menu.list发生了变化。Grub2的配置与两个文件有关,一个是/boot/grub/grub.cfg, 这是grub运行时所使用的配置文件,不能被人为编辑,而只能通过相应的script如”update-grub”来修改。另一个文件是/etc/default/grub, 这个文件可以使用Linux提供的任意文本编译器修改,再通过相应script更新到/boot/grub/grub.cfg. 所以我们接下来的操作是对/etc/default/grub的操作,但首先需要打开/boot/grub/grub.cfg记下想要设为默认启动内核的内核的menu entry position 或者是 menu entry description string 。

#
# DO NOT EDIT THIS FILE
#
# It is automatically generated by /usr/sbin/grub-mkconfig using templates
# from /etc/grub.d and settings from /etc/default/grub
#

### BEGIN /etc/grub.d/00_header ###
if [ -s $prefix/grubenv ]; then
load_env
fi
set default=”Microsoft Windows XP Professional (on /dev/sda1)” //当前默认的启动内核
if [ ${prev_saved_entry} ]; then
set saved_entry=${prev_saved_entry}
save_env saved_entry
set prev_saved_entry=
save_env prev_saved_entry
set boot_once=true
fi

function savedefault {
if [ -z ${boot_once} ]; then
saved_entry=${chosen}
save_env saved_entry
fi
}

function recordfail {
set recordfail=1
if [ -n ${have_grubenv} ]; then if [ -z ${boot_once} ]; then save_env recordfail; fi; fi
}
insmod ext2
set root=’(hd0,8)’
search –no-floppy –fs-uuid –set 61d65174-d17d-44a9-a88a-9a8346754243
if loadfont /usr/share/grub/unicode.pf2 ; then
set gfxmode=640×480
insmod gfxterm
insmod vbe
if terminal_output gfxterm ; then true ; else
# For backward compatibility with versions of terminal.mod that don’t
# understand terminal_output
terminal gfxterm
fi
fi
insmod ext2
set root=’(hd0,8)’
search –no-floppy –fs-uuid –set 61d65174-d17d-44a9-a88a-9a8346754243
set locale_dir=($root)/boot/grub/locale
set lang=zh
insmod gettext
if [ ${recordfail} = 1 ]; then
set timeout=-1
else
set timeout=10
fi
### END /etc/grub.d/00_header ###

### BEGIN /etc/grub.d/05_debian_theme ###
set menu_color_normal=white/black
set menu_color_highlight=black/light-gray
### END /etc/grub.d/05_debian_theme ###

### BEGIN /etc/grub.d/10_linux ### // 从这里开始是当前机器中所有的可以加载的内核
/*第一个可加载的内核,menu entry position为0,以下递加, menu entry description string为包括引号的’Ubuntu,Linux 2.6.32-23-generic’*/

menuentry ‘Ubuntu,Linux 2.6.32-23-generic’ –class ubuntu –class gnu-linux –class gnu –class os {
recordfail
insmod ext2
set root=’(hd0,8)’
search –no-floppy –fs-uuid –set 61d65174-d17d-44a9-a88a-9a8346754243
linux    /boot/vmlinuz-2.6.32-23-generic root=UUID=61d65174-d17d-44a9-a88a-9a8346754243 ro   quiet splash
initrd    /boot/initrd.img-2.6.32-23-generic
}
menuentry ‘Ubuntu,Linux 2.6.32-23-generic (恢复模式)’ –class ubuntu –class gnu-linux –class gnu –class os {
recordfail
insmod ext2
set root=’(hd0,8)’
search –no-floppy –fs-uuid –set 61d65174-d17d-44a9-a88a-9a8346754243

接下来打开/etc/default/grub文件

# If you change this file, run ‘update-grub’ afterwards to update
# /boot/grub/grub.cfg.

GRUB_DEFAULT=”Microsoft Windows XP Professional (on /dev/sda1)”
#GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_TIMEOUT=10
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT=”quiet splash”
GRUB_CMDLINE_LINUX=”"

# Uncomment to disable graphical terminal (grub-pc only)
#GRUB_TERMINAL=console

# The resolution used on graphical terminal
# note that you can use only modes which your graphic card supports via VBE
# you can see them in real GRUB with the command `vbeinfo’
#GRUB_GFXMODE=640×480

比如说你想把默认内核设置为可加载的第一个内核,既/boot/grub/grub.cfg里的’Ubuntu,Linux 2.6.32-23-generic’, 就可以将上面的GRUB_DEFAULT设成

GRUB_DEFAULT=’Ubuntu,Linux 2.6.32-23-generic’或者GRUB_DEFAULT=0

想要设成其他的内核也是一样的操作。

完成后将/etc/default/grub保存,然后在terminal中运行

update-grub

重启机子,就可以发现默认的启动内核已经改成你所想要的内核了。

当然,对于grub2的操作还可以有其他方法,可以不用修改/etc/default/grub文件,直接通过调用命令 grub-set_default去修改,想要了解更多点击这儿

Ubuntu与XP双系统下卸载Ubuntu

由于我的破电脑总共只有40G硬盘,装了Ubuntu以后,Windows只有20G感觉不够用。而整个Ubuntu安装完成后实际上只用了2G的空间,原先为Ubuntu分区分了20G浪费了,所以在安装Ubuntu一个星期之后,我打起了先卸载Ubuntu,再重分区,再重新安装Ubuntu的主意(实际上只要重新安装Ubuntu,就可以在安装过程中重新分区了,天知道我那时候是怎么想的)。要卸载Ubuntu的话,实际上就只需要两步,首先是要更改MBR区,使得引导扇区不再使用Ubuntu的Grub程序,还是使用Windows的引导程序,这一步可以通过在Windows安装光盘中运行恢复控制台,敲入命令:

fixboot
fixmbr

既可,然后重启电脑就会直接进入Windows引导程序启动Windows XP。另一步就是要删除Ubuntu分区,这一步可以在Windows中使用Windows自带的磁盘管理工具删除分区,重新格式化分区。这里我的操作出现了一些错误,在我将原先旧的Ubuntu分区删除,重新分区时,磁盘管理工具提示我出现错误,无法为我创建分区,但似乎别人都没遇到这个问题,后来我还是通过Ubuntu的安装光盘将电脑上的未分区磁盘空间重新分区了一个FAT32给Windows,一个SWAP做为Ubuntu的交换区, 一个EXT4挂载到Ubuntu的根目录,搞定。

© 2011 《洛克.肖恩的救赎》 Suffusion theme by Sayontan Sinha