linux开发环境的快速搭建
WeiBing

(本文针对朗成电子公司的 AT2440EVB-I开发板而写)

1.建立文件系统目录
    假定文件系统的目录为/rootfs,将rootfs.tar解压到该目录。
mkdir /rootfs
tar zxf rootfs.tar -C /rootfs

2.配置nfs文件系统
    修改/etc/exports文件,格式为 共享目录 开发板ip地址(权限设置)
cat <<EOM >/etc/exports
/rootfs  192.168.1.120(rw,sync,insecure,no_root_squash)
EOM
    重启nfs服务器
/etc/init.d/nfs restart

3.烧写可启动内核
    将待烧写的uImage放到tftp服务器指定的目录下(假定其ip为192.168.1.100),进入u-boot的命令行状态,顺

序执行下列命令:
set ipaddr 192.168.1.120
set serverip 192.168.1.100
erase 0x00040000 0x001dffff
tftp 0x30000000 uImage
cp.b 0x30000000 0x00040000 $(filesize)

set bootargs root=/dev/nfs nfsroot=202.192.32.100:/arm/rootfs rw noinitrd init=/linuxrc

ip=192.168.1.120:192.168.1.100:192.168.1.100:255.255.255.0:avantech:eth0:off console=ttySAC0,115200

set bootcmd cp.b 0x00040000 0x33000000 $(filesize)

saveenv
reset

4.重新启动即可进入开发环境。在linux服务器端将编译好的程序放到/rootfs目录下,通过telnet连入开发板即可

执行新的程序。下面以usb摄像头的采集程序为例,简要说明开发环境的使用方法。
首先,将摄像头驱动usbcam.ko和采集程序spcaserv复制到/rootfs/opt/usbcam目录下
mkdir /rootfs/opt/usbcam -p
cp usbcam.ko spcaserv /rootfs/opt/usbcam
然后进入开发板,执行
insmod /opt/usbcam/usbcam.ko
./rootfs/opt/usbcam/spcaserv -w 192.168.1.120:7070 -s 320x240 -d /dev/video0
最后可以在windows下执行play.bat即可看到从开发板采集到的图象。

Tag: ARM


猜猜下面的结构体有什么问题? 

struct device_driver {
        const char              * name;
        struct bus_type         * bus;

        struct completion       unloaded;
        struct kobject          kobj;
        struct klist            klist_devices;
        struct klist_node       knode_bus;

        struct module           * owner;

        int     (*Probe)        (struct device * dev);
        int     (*remove)       (struct device * dev);
        void    (*shutdown)     (struct device * dev);
        int     (*suspend)      (struct device * dev, pm_message_t state);
        int     (*resume)       (struct device * dev);
};

搞了一个下午的AD驱动,到最好还是被奇怪的问题捆住。

s3c24xx-adc.c:411: error: unknown field `probe' specified in initializer
s3c24xx-adc.c:411: warning: initialization from incompatible pointer type

我怎么看这个初始化函数的定义都没问题...

static struct device_driver s3c2410_adc_driver = {
        .name           = "s3c2410-adc",
        .bus            = &platform_bus_type,
        .owner          = THIS_MODULE,
        .probe          = s3c24xx_adc_probe,
        .remove         = s3c24xx_adc_remove,
        .resume         = s3c24xx_adc_resume,
        .suspend        = s3c24xx_adc_suspend,
};

幸好设了ctag,跳到device_driver看看,终于发现问题所-- (*Probe) --!!!
不知是谁干的坏事,把p变成P,杀杀杀...

Tag: Linux ARM


      想不到,早上才解决网卡问题,晚上LCD就跳出小企鹅 ^_^ 其实,一开始就搞这个LCD,只可惜就差几个寄存器没调好,一直都白屏...

我的sharp 3.5 TFT 设置如下:(参考 http://www.hhcn.com/cgi-bin/topic.cgi?forum=3&topic=101&start=36&show=0 )

static struct s3c2410fb_mach_info smdk2410_lcdcfg __initdata = {
        .regs={
                .lcdcon1=       S3C2410_LCDCON1_TFT16BPP | \
                                S3C2410_LCDCON1_TFT | \
                                S3C2410_LCDCON1_CLKVAL(7),

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

                .lcdcon3=       S3C2410_LCDCON3_HBPD(6) | \
                                S3C2410_LCDCON3_HOZVAL(239) | \
                                S3C2410_LCDCON3_HFPD(30),

                .lcdcon4=       S3C2410_LCDCON4_MVAL(13) | \
                                S3C2410_LCDCON4_HSPW(3),

                .lcdcon5=       S3C2410_LCDCON5_FRM565 | \
                                S3C2410_LCDCON5_HWSWP | \
                                S3C2410_LCDCON5_PWREN,
        },
        .lpcsel=        0x0,
        .gpccon=        0xaaaaaaaa,
        .gpccon_mask=   0xffffffff,
        .gpcup=         0xffffffff,
        .gpcup_mask=    0xffffffff,
        .gpdcon=        0xaaaaaaaa,

        .width=         240,
        .height=        320,
        .xres=          {240,240,240},
        .yres=          {320,320,320},
        .bpp=           {16,16,16},
};

      关于这些寄存器的作用,已经有一篇很好的文章《S3C2410 下LCD 驱动程序移植及GUI 程序编写》。对我之前根据mach-h1490.c和网友的修改,错在 .lcdcon5 寄存器多了两个值:

                       S3C2410_LCDCON5_INVVLINE | \
                       S3C2410_LCDCON5_INVVFRAME | \

将帧和行同步线的电平翻转了,怪不得上面的寄存器值怎么改都无效...

      顺便提一下minicom连入开发板的ash时键入Backspace键显示^H的问题。我是通过Pietty连入虚拟机再打开minicom的,连入rh4和通过minicom设置u-boot时都一切正常,开始真有点找不着北...打开minicom的setting 有这么一项 Terminal settings..T  >> B - Backspace key sends : BS ,按一下B改为DEL就搞定。在windows的超级终端里也有 Backspace键发送 的设置。但是,上下左右四个方向键 ^[[A ^[[B ^[[D ^[[C 仍然找不到设置的选项... 这些设置应该是历史遗留下来的问题,真麻烦 ^_^



移植路上真是荆棘满路,时不时让你疯狂一两天,却无可奈何...

        网上已有很多相关的移植教程,第一步,当然是照着做。问题是我的Linux是2.6.19.2,与前些版本相比(据查,2.6.17版还在),在移植过程中,我发现有两个变化。一是 include/asm-arm/irq.h 里已删除一些irq操作的预定义,如:

extern void disable_irq(unsigned int);
extern void enable_irq(unsigned int);
int set_irq_type(unsigned int irq, unsigned int type);

而网上的那个cs8900.c驱动比较老,与Linux-2.6.19.2带的cs89x0相差很大(据说这个驱动也没有使用新的驱动模型,不知道,这里应该与dm9000比较一下)。导致出现很多错误,不能编译 cs8900.c ,一天就这样在郁闷中过去...

      旧的不去,新的不来,干脆就直接用cs89x0.c ^_^ google到一个 pathch-cs89x0 ,哪个开心啊...可惜这个patch是针对2.6.14,自动patch失败,手动补齐后再添一些头文件、修改一些小错误,终于编译通过。可是,狂跳几下后又得郁闷了,出现了内核编程常见错误oops:

cs89x0:cs89x0_probe(0x0)
Unable to handle kernel paging request at virtual address f400030a
pgd = c0004000
[f400030a] *pgd=00000000
Internal error: Oops: 5 [#1]
Modules linked in:
CPU: 0
PC is at readword+0x1c/0x2c
LR is at cs89x0_probe1+0xec/0x874
pc : []    lr : []    Not tainted
sp : c032feb0  ip : c032fec0  fp : c032febc
r10: f4000300  r9 : 00000000  r8 : 00000000
r7 : c0f3b800  r6 : c0f3ba60  r5 : c0f3b800  r4 : f4000300
r3 : f400030a  r2 : 00000000  r1 : f400030a  r0 : f4000300
Flags: NzCv  IRQs on  FIQs on  Mode SVC_32  Segment kernel
Control: 717F
Table: 30004000  DAC: 00000017
Process swapper (pid: 1, stack limit = 0xc032e250)
Stack: (0xc032feb0 to 0xc0330000)
fea0:                                     c032ff4c c032fec0 c001bec8 c0139fa8
fec0: ffffffff c0f3b803 0000000a c032ff4c ffffffff 00000002 c0f3b800 ffffffff
fee0: c032ff30 c032fef0 c00fa694 c00f9e88 0000000a ffffffff ffffffff 00000002
ff00: 3f0c47ff 00000000 c0f3b800 00000000 00000000 00000000 00000000 c0021290
ff20: c032ff3c c002619c c0f3b800 00000000 00000000 00000000 00000000 c0021290
ff40: c032ff6c c032ff50 c001c6e0 c001bdec c0026164 00000001 00000000 c00217a4
ff60: c032ff88 c032ff70 c001bb04 c001c660 00000001 00000000 c032e000 c032ffa0
ff80: c032ff8c c001bbd0 c001bad0 00000000 c0021208 c032fff4 c032ffa4 c0027100
ffa0: c001bb48 00000001 c0027e24 c003caf4 00000000 00000000 c0027058 c0043128
ffc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
ffe0: 00000000 00000000 00000000 c032fff8 c0043128 c0027068 0a00003e e5dc3001
Backtrace:
[] (readword+0x0/0x2c) from [] (cs89x0_probe1+0xec/0x874)
[] (cs89x0_probe1+0x0/0x874) from [] (cs89x0_probe+0x90/0x1)
[] (cs89x0_probe+0x0/0x108) from [] (probe_list2+0x44/0x78)
 r7 = C00217A4  r6 = 00000000  r5 = 00000001  r4 = C0026164
[] (probe_list2+0x0/0x78) from [] (net_olddevs_init+0x98/0x)
 r6 = C032E000  r5 = 00000000  r4 = 00000001
[] (net_olddevs_init+0x0/0xdc) from [] (init+0xa8/0x274)
 r5 = C0021208  r4 = 00000000
[] (init+0x0/0x274) from [] (do_exit+0x0/0x7d8)
Code: e0801001 e3510201 e1a03001 328334f2 (e1d300b0)
 <0>Kernel panic - not syncing: Attempted to kill init!

      前两天才在《Linux内核设计与实现》里看到的常见错误,想不到这么快就被我遇上...这里就是新版Linux第二个变化引起的错误。尝试更改映射的虚地址,无效。就在准备回去冲凉的瞬间,google里又出现一个好东西 ARM Linux Kernel Porting ,有原理图,有cs8900的实地址为0x19000000的解析(大致就是A24脚的高低电平控制cs8900开关,故+1000000),可惜是韩文,里面的文字不知说什么,但错误现象一样,根据里面的代码再修改cs89x0一遍(这个文件真的很乱了^_^)。十分可惜,还是不能在我睡前干一件好事...

      早上精神好啊,又经过一番搜索,终于发现问题,原来实地址与虚地址的映射结构 smdk2410_iodesc 里有所变化。第二个参数从原来的 unsigned long physical 变为 unsigned long pfn 。而从 smdk2410_iodesc 传入的SMDK2410_PA_CS8900A_BASE 仍然是一个 physical 值,因此出现 Unable to handle kernel paging request 错误。这里很感谢http://bibu.blogchina.com/bibu/4914641.html的作者,根据提示,将实地址作一个小小变化就Ok了 ^_^

#ifndef __ASM_ARCH_SMDK2410_H
#define __ASM_ARCH_SMDK2410_H

#define SMDK2410_PA_CS8900A_BASE       __phys_to_pfn(S3C2410_CS3 + 0x01000000) /* nGCS3 +0x01000000 */
#define SMDK2410_VA_CS8900A_BASE       S3C2410_ADDR(0x04000000)  /* 0xF4000000 */

#endif /* __ASM_ARCH_SMDK2410_H */

虚地址改多少无所谓,如0xE0000000,只要不和其它设备冲突就行。

      下面总结一下整个移植过程:

1. include/asm-arm/arch-s3c2410/map.h 

添加:
 /* CS8900 */
 #define S3C24XX_VA_CS8900   S3C2410_ADDR(0x04000000)
 #define S3C2410_PA_CS8900     __phys_to_pfn(0x19000000)
 #define S3C24XX_SZ_CS8900    SZ_1M
 #define S3C24XX_PA_CS8900    S3C2410_PA_CS8900

2. arch/arm/mach-s3c2410/mach-smdk2410.c 

修改

static struct map_desc smdk2410_iodesc[] __initdata={
        {S3C24XX_VA_CS8900IO, S3C2410_PA_CS8900, S3C24XX_SZ_CS8900, S3C24XX_SZ_CS8900, MT_DEVICE}
};

3. include/asm-arm/irq.h 

添加

int set_irq_type(unsigned int irq, unsigned int type);

4.  drivers/net/cs89x0.c

下面是我的 diff

--- ../linux2/linux-2.6.19.2/drivers/net/cs89x0.c 2007-01-11 03:10:37.000000000 +0800
+++ drivers/net/cs89x0.c 2007-02-04 21:16:42.000000000 +0800
@@ -96,6 +96,9 @@
   Dmitry Pervushin  : dpervushin@ru.mvista.com
                     : PNX010X platform support
 
+  Christian Pell    : chripell@gmail.com
+                    : SMDK2410 platform support, fixed bug with signed ioaddr
+
 */
 
 /* Always include 'config.h' first in case the user wants to turn on
@@ -194,6 +197,27 @@
 #define CIRRUS_DEFAULT_IRQ VH_INTC_INT_NUM_CASCADED_INTERRUPT_1 /* Event inputs bank 1 - ID 35/bit 3 */
 static unsigned int netcard_portlist[] __initdata = {CIRRUS_DEFAULT_BASE, 0};
 static unsigned int cs8900_irq_map[] = {CIRRUS_DEFAULT_IRQ, 0, 0, 0};
+
+#elif defined(CONFIG_ARCH_S3C2410) //Added weibing
+#include <linux/irq.h>
+#include <asm/irq.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/smdk2410-map.h>
+
+static unsigned int netcard_portlist[] __initdata = {S3C24XX_VA_CS8900+0x300, 0};
+static unsigned int cs8900_irq_map[] = {IRQ_EINT9, 0, 0, 0};
+/*
+#ifdef request_region
+#undef request_region
+#endif
+#ifdef release_region
+#undef release_region
+#endif
+#define request_region(a,s,n) request_mem_region(a,s,n)
+#define release_region(a,s) release_mem_region(a,s)
+*/
 #else
 static unsigned int netcard_portlist[] __initdata =
    { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
@@ -246,7 +270,7 @@
 
 /* Index to functions, as function prototypes. */
 
-static int cs89x0_probe1(struct net_device *dev, int ioaddr, int modular);
+static int cs89x0_probe1(struct net_device *dev, unsigned int ioaddr, int modular);
 static int net_open(struct net_device *dev);
 static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t net_interrupt(int irq, void *dev_id);
@@ -324,6 +348,10 @@
  io = dev->base_addr;
  irq = dev->irq;
 
+#ifdef CONFIG_ARCH_S3C2410 //Added weibing
+ __raw_writel((__raw_readl(S3C2410_GPGCON)&~(0x3<<2))|(0x2<<2),S3C2410_GPGCON);
+ __raw_writel((__raw_readl(S3C2410_EXTINT1)&~(0x7<<4))|(0x4<<4),S3C2410_EXTINT1);
+#endif
  if (net_debug)
   printk("cs89x0:cs89x0_probe(0x%x)\n", io);
 
@@ -386,6 +414,18 @@
 {
  outw(value, base_addr + (portno << 1));
 }
+#elif defined(CONFIG_ARCH_S3C2410) //Added weibing
+static u16
+readword(unsigned long base_addr, int portno)
+{
+ return __raw_readw(base_addr+portno);
+}
+
+static void
+writeword(unsigned long base_addr, int portno,u16 value)
+{
+ __raw_writew(value,base_addr+portno);
+}
 #else
 static u16
 readword(unsigned long base_addr, int portno)
@@ -507,7 +547,7 @@
  */
 
 static int __init
-cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
+cs89x0_probe1(struct net_device *dev, unsigned int ioaddr, int modular)
 {
  struct net_local *lp = netdev_priv(dev);
  static unsigned version_printed;
@@ -638,7 +678,18 @@
     the driver will always do *something* instead of complain that
     adapter_cnf is 0. */
 
-#ifdef CONFIG_SH_HICOSH4
+#if defined CONFIG_ARCH_S3C2410
+ lp->force=FORCE_RJ45;
+ lp->auto_neg_cnf=IMM_BIT;
+
+ dev->dev_addr[0]=0x09; /*setMACaddress*/
+ dev->dev_addr[1]=0x90;
+ dev->dev_addr[2]=0x99;
+ dev->dev_addr[3]=0x09;
+ dev->dev_addr[4]=0x90;
+ dev->dev_addr[5]=0x99;
+
+#elif defined CONFIG_SH_HICOSH4
  if (1) {
   /* For the HiCO.SH4 board, things are different: we don't
      have EEPROM, but there is some data in flash, so we go
@@ -1036,7 +1087,7 @@
 {
 #if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01)
  struct net_local *lp = netdev_priv(dev);
- int ioaddr = dev->base_addr;
+ unsigned int ioaddr = dev->base_addr;
 #endif
  int reset_start_time;
 
@@ -1278,7 +1329,7 @@
  int i;
  int ret;
 
-#if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX010X) /* uses irq#1, so this won't work */
+#if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX010X) && !defined(CONFIG_ARCH_S3C2410) /* uses irq#1, so this won't work */
  if (dev->irq < 2) {
   /* Allow interrupts to be generated by the chip */
 /* Cirrus' release had this: */
@@ -1309,7 +1360,7 @@
  else
 #endif
  {
-#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X)
+#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X) && !defined(CONFIG_ARCH_S3C2410)
   if (((1 << dev->irq) & lp->irq_map) == 0) {
    printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
                                dev->name, dev->irq, lp->irq_map);
@@ -1324,6 +1375,9 @@
   writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON);
 #endif
   write_irq(dev, lp->chip_type, dev->irq);
+#if defined(CONFIG_ARCH_S3C2410)
+  set_irq_type(dev->irq, IRQT_RISING);
+#endif
   ret = request_irq(dev->irq, &net_interrupt, 0, dev->name, dev);
   if (ret) {
    if (net_debug)
@@ -1394,7 +1448,7 @@
  case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break;
         default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2);
         }
-#ifdef CONFIG_ARCH_PNX010X
+#if defined(CONFIG_ARCH_PNX0105) || defined(CONFIG_ARCH_S3C2410)
  result = A_CNF_10B_T;
 #endif
         if (!result) {
@@ -1577,7 +1631,8 @@
 {
  struct net_device *dev = dev_id;
  struct net_local *lp;
- int ioaddr, status;
+ unsigned int ioaddr;
+ int status;
   int handled = 0;
 
  ioaddr = dev->base_addr;
@@ -1683,7 +1738,7 @@
  struct sk_buff *skb;
  int status, length;
 
- int ioaddr = dev->base_addr;
+ unsigned int ioaddr = dev->base_addr;
  status = readword(ioaddr, RX_FRAME_PORT);
  length = readword(ioaddr, RX_FRAME_PORT);

5.重新编译,重新启动,重新happy...

好了,现在可以挂NFS了,玩玩去...

...... ......

现在又有一不像问题的问题,网卡工作正常,但启动是提示申请 io 注册失败,request_region(0xf4000300, 0x10) failed 。

cs89x0:cs89x0_probe(0x0)
cs89x0.c: v2.4.3-pre1 Russell Nelson <nelson@crynwr.com>, Andrew Morton
eth0: cs8900 rev K found at 0xf4000300
cs89x0: Extended EEPROM checksum bad and no Cirrus EEPROM, relying on command le
cs89x0 media RJ-45, IRQ 53, programmed I/O, MAC 09:90:99:09:90:99
cs89x0_probe1() successful
cs89x0:cs89x0_probe(0x0)
cs89x0: request_region(0xf4000300, 0x10) failed
cs89x0: no cs8900 or cs8920 detected.  Be sure to disable PnP with SETUP

更改虚地址也无效,追踪一下,在 kernel/resource.c 里出现问题。不知为什么资源冲突了,我看网上移植cs8900到2.4版也有这个问题...不理,先向下跳,回过头来在处理它...

443                 for (;;) {
444                         struct resource *conflict;
445
446                         conflict = __request_resource(parent, res);
447                         if (!conflict)
448                                 break;
449 if (conflict != parent) {
450                                 parent = conflict;
451                                 if (!(conflict->flags & IORESOURCE_BUSY))
452                                         continue;
453                         }
454
455                         /* Uhhuh, that didn't work out.. */
456                         kfree(res);
457                         res = NULL;
458                         break;
459                 }



init started:  BusyBox v1.4.1 (2007-02-03 10:47:43 CST) multi-call binary
Starting pid 743, console /dev/console: '/etc/init.d/rcS'

Please press Enter to activate this console.
Starting pid 753, console /dev/console: '/bin/sh'

BusyBox v1.4.1 (2007-02-03 10:47:43 CST) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

-sh: can't access tty; job control turned off
Set search library path int /etc/profile
Set user path in /etc/profile
#
可恶的shell终于出来拉...

      搞了两天,原来又犯老毛病--粗心...自从数据结构成绩出来后,心情一直都不好,那么简单的卷子分数竟然这么垃圾,还以为老师故意为难...直到前两天才发现,原来是自己粗心,做错三题,没什么好说的,只能怪自己。月满自亏,水满自溢,人满容易跌倒...人真奇怪,越是提醒,越是容易忘记。以此为训,不要在同一个地方跌倒多次!

      哈哈,牢骚发完,该总结以下移植过程了:

1.制作 ramdisk 。本打算直接用NFS挂文件系统的,可惜网卡驱动还没完全ok... 该部分内容可以参考Linux系统移植 (十分感谢前辈的共享) 和  http://www.hhcn.com/cgi-bin/topic.cgi?forum=3&topic=816 。

        #dd if=/dev/zero of=/dev/ram1 bs=1k count=8000

        # losetup /dev/loop2 ramdisk

        # mkfs.ext2 /dev/loop2

        #mkdir ram

        # mount -t ext2 /dev/loop2 ram 

        #cd ram

        #mkdir bin dev etc lib mnt proc sbin sys tmp root usr

        #mkdir mnt/etc

        #mkdir usr/bin usr/lib usr/sbin

        #mknod -m 660 dev/console c 5 1

        #mknod -m 660 dev/null c 1 3

        #touch linuxrc  (至此,空ramdisk制作完毕)

当然,lib里面还要拷入一些库文件,为了方便,我将交叉编译的库全放进去。

        #cp -rfd /usr/local/arm/3.4.1/arm-linux/lib/* ./  (注意-d,保持库文件的链接关系)

2.下载,当然是最新版的 BusyBox 1.4.1 (stable)  。解压,修改Makefile:

        ARCH            ?= arm
        CROSS_COMPILE   ?= /usr/local/arm/3.4.1/bin/arm-linux-

接着便是make menuconfig 。如果不确定选哪些的话,可以用make depconfig 。值得注意的是 shell 的选择,在 Choose your default shell (none) 这一项回车后选择 ash , 否则,你会想我一样头疼大半天,make 后bin目录下就是没有sh ,而默认shell命令就是sh。错误提示如下:

Please press Enter to activate this console.
Starting pid 739, console /dev/console: '/bin/sh'
sh: applet not found
Process '-/bin/sh' (pid 739) exited.  Scheduling it for restart.

关于Build Options 的 Build BusyBox as a static binary (no shared libs) 静态编译,我用3.4.1版的交叉编译怎么都不通过,提示 glibc 有问题:

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

2.95.3更加不行,唯有选用 Build shared lib busybox 。这样,就需要往 ram/lib 目录拷入相关的库文件。make , make install 后就出来 _install 目录,全拷到 ram 目录下。

        #gzip -9c ramdisk > ramdisk.image.gz

      到这里,基本的都已搞定,可以 reset 开发板看看。下面是常见的错误:

Failed to execute /linuxrc.

      如果传给内核的参数 init=/linuxrc 没错的话,就要看看linuxrc文件是否正确,是否有权限运行。刚开始,由于没有选中 ash shell ,bin 目录下还没有 sh ,而我修改的 linuxrc 第一句的内容是 #!/bin/sh ,根本就不能解析。后来改为 #!/bin/ash ,能解析了,也高兴了一下,可惜提示 sh: applet not found 。选中默认的shell后问题解决。关于Linux的启动详细过程,可以参考 Linux 初始 RAM 磁盘(initrd)概述 、Linux Root Filesystem Primer 这两篇文章。Linux2.6 还引入了新的ram文件系统,配置起来相对简单,有机会尝试一下...

Warning: unable to open an initial console

      新的ramdisk不行,我换回原来的ramdisk,发现可以跑,只是提示找不到终端。于是,对比我和其它网友的串口输出。发现我的Linux-2.6.19.2没有 Mounted devfs on /dev 这项。大段大段的搜索后发现,这个devfs已被提出内核,而替代者udev在嵌入式方面还没有一点资料...网上的资料全都说从fs/Kconfig添加:

onfig DEVFS_FS
        bool "/dev file system support (OBSOLETE)"
        default y
config DEVFS_MOUNT

        bool "Automatically mount at boot"
        default y
        depends on DEVFS_FS

可是,一点用处都没有...从Linux-2.6.18开始,包括文档在内已没有一点devfs的使用信息。而网上移植的Linux版本都比较低,所以...本想尝试从旧版本中移植相关代码过来(有点奇怪^_^),幸好当我对比新旧ramdisk时发现旧的ramdisk dev目录下缺少 console ,mknod 后可以进入旧版的 busybox 0.6 ...

      最后是BusyBox的编译问题,使用3.4.1带的libc库编译,很容易出现与BusyBox里的程序不兼容现象。如:

modutils/lib.a(insmod.o)(.text.insmod_main+0x444): In function `insmod_main':
: undefined reference to `query_module'

miscutils/readahead.c: In function `readahead_main':

miscutils/taskset.c:17: error: parse error before '*' token
miscutils/taskset.c:18: warning: function declaration isn't a prototype
miscutils/taskset.c: In function `__from_cpuset':
......

最根本的解决办法是换一个libc库,可是现在还不知道哪个库最合适,唯有暂时将有问题的命令关掉...

      两个星期过得真快,我的系统也终于跑起来,虽然还有很多问题,但总算有点收获 ^_^



      一个数字问题,花费两天时间,真顶不顺。如果这个所谓的革新公司提供实验板的原理图就好了,可惜...我怀疑他们的板都不知从那里抄来的,也确实佩服他们的销售和我们学校的领导,多么成功的交易啊...

      好,问题解决,留下笔记。Linux 2.6.19.2 ,参考 mach-vr1000.c 和网上众多例子...

vi arch/arm/mach-s3c2410/mach-smdk2410.c ,加入:

static struct resource s3c_d9k_resource[] = {
        [0] = {
                .start = 0x0A000000 + 0x300,
                .end   = 0x0A000000 + 0x300 + 0x03,
                .flags = IORESOURCE_MEM
        },
        [1] = {
                .start = 0x0A000000 + 0x300 + 0x4,
                .end   = 0x0A000000 + 0x300 + 0x4 + 0x7f,
                .flags = IORESOURCE_MEM
        },
        [2] = {
                .start = IRQ_EINT0,
                .end   = IRQ_EINT0,
                .flags = IORESOURCE_IRQ
        }
};
static struct dm9000_plat_data s3c_device_d9k_platdata = {
        .flags= DM9000_PLATF_16BITONLY
};

struct platform_device s3c_device_d9k = {
        .name= "dm9000",
        .id= 0,
        .num_resources= ARRAY_SIZE(s3c_d9k_resource),
        .resource= s3c_d9k_resource,
        .dev= {
                .platform_data = &s3c_device_d9k_platdata,
        }
};

修改static struct platform_device *smdk2410_devices[] __initdata = {
        &s3c_device_usb,
        &s3c_device_lcd,
        &s3c_device_wdt,
        &s3c_device_i2c,
        &s3c_device_iis,
        &s3c_device_d9k
};
      红色部分是关键,网上的 vr1000.c 和网上大多例子此处都为0x40。经查证,是因为DM9000A的地址线和数据线是复用的,它是通过92脚(CMD)来区分。如果CMD接到s3c2410的A2脚, 则数据端口的地址 = 地址端口 + 0x04 。那如果是0x40的话,他的CMD应该是接到s3c2410的A7脚。

       奇怪的是 DM9000 在u-boot下也算工作正常,翻查代码,原来有这么两句:

#define DM9000_IO   CONFIG_DM9000_BASE
#define DM9000_DATA   (CONFIG_DM9000_BASE+4)

唉,一切只能怪自己不仔细,客观的说,是经验不足 ^_^

      哈哈,无论如何,终于摆脱 read wrong id 的恶梦,可是,马上又遇到可恶的 IRQ_EINT0 ,一申请0号中断就死机...



      哈哈,没想到现阶段的移植就是东拼西凑,多亏u-boot丰富的驱动,先辈们辛勤的劳动成果啊 ^_^

      板子是GX-ARM9-2410EP增强型嵌入式教学实验系统,相当垃圾,资料缺少、不全不说,还骗人,两块Nor Flash,SST 39VF800A、INTEL E28F320,分明是1M和4M大小,偏说成2M AMD线性FLASH和8M Intel线性FLASH,我就奇怪学校怎么回买这种东西...

        言归正传,下面是具体的移植过程:

1.硬件 s3c2410 ,64M SDRAM,INTEL E28F320 4M Nor Flash ,CS8900和DM9000双网卡(暂用CS8900);

2.基本配置,使用#make s3c2410_config 。这时的板已经可以启动,可以通过网卡下载内核,可以设置启动参数启动 Linux2.6了,但还不能读写Nor Flash,存储环境变量。

3.配置Nor Flash,主要是修改 board/s3c2410/flash.c 。用 Source-Navigator 或者 grep 可以找到很多带INTEL E28F320驱动的flash.c文件。这里参考http://www.sjsunny.com/jsfw/Linux/06.htm ,将board/CMI/flash.c的Nor Flash借过来。删除write_short()和wirte_buff()函数,将board/ep7312/flash.c的wirte_word()和wirite_buff()函数拷过来(与CMI的写机制不通)。加入以下语句:

#defin ASH_BASE0_PRELIM CFG_FLASH_BASE

修改FLASH_BLOCK_SIZE为0x20000(块大小128K)。修改 include/s3c2410.h ,可以在最后的 #endif  /* __CONFIG_H */ 前添加以下常量定义来覆盖原来的值:

#define PHYS_FLASH_SIZE        0x01000000  /* 16 MB */

#define CFG_FLASH_BASE         PHYS_FLASH_1

#define CFG_MONITOR_BASE   PHYS_FLASH_1

#define CFG_MAX_FLASH_SECT 128   /* 128K*128=16M  */

#define CFG_FLASH_ERASE_TOUT   (2*CFG_HZ) /* Timeout for Flash Erase */

#define CFG_FLASH_WRITE_TOUT  (2*CFG_HZ) /* Timeout for Flash Write */

#define    CFG_ENV_IS_IN_FLASH    1

#define CFG_ENV_ADDR           (PHYS_FLASH_1 + 0x80000)   /* 变量存放地址 */

#define CFG_ENV_SIZE       0x20000  /* 变量存放空间的大小,应和块大小一致,不然saveenv时提示边界问题。     */
至此,Nor Flash已完全驱动起来。

WEIBING # saveenv
Saving Environment to Flash...
Un-Protected 1 sectors
Erasing Flash...
...............................................................................e
Erased 1 sectors
Writing to Flash... done
Protected 1 sectors
WEIBING #

4.DM9000网卡驱动移植,有100M的不用总觉得不爽 ^_^
这一步可以参考 include/configs/scb9328.h 这个文件,删除CS8900的定义,添加以下语句:
#define CONFIG_DRIVER_DM9000  1
#define CONFIG_DM9000_BASE  0x0a000300
#define DM9000_IO   CONFIG_DM9000_BASE
#define DM9000_DATA   (CONFIG_DM9000_BASE+4)
#define CONFIG_DM9000_USE_16BIT

最主要是 CONFIG_DM9000_BASE 这个地址的值,有硬件的接线决定,最后的300是DM9000复位后默认工作方式为I/ O 连接的基址,可以参考 http://msa.vnu.edu.tw/~merlin/932embed/tftp.ppt 。

5.关于flash刷写。配置好的flash信息如下,

WEIBING # flinfo

Bank # 1: Intel 28F320J3A (32Mbit) 16-Bit
  Size: 4 MB in 32 Sectors
  Sector Start Addresses:
    00000000 (RO) 00020000      00040000      00060000      00080000 (RO)
    000A0000      000C0000      000E0000      00100000      00120000
    00140000      00160000      00180000      001A0000      001C0000
    001E0000      00200000      00220000      00240000      00260000
    00280000      002A0000      002C0000      002E0000      00300000
    00320000      00340000      00360000      00380000      003A0000
    003C0000      003E0000

u-boot和参数存放的00000000块和00080000块都标记为只读,修改需要先关闭flash 保护,如烧写u-boot自身:

WEIBING # tftpboot 30008000 u-boot.bin
dm9000 i/o: 0xa000300, id: 0x90000a46
MAC: 00:80:00:80:00:80
could not establish link  ( 这里好像有问题,反应很慢,但传输速度真的比CS8900的10M快多了^_^ )
TFTP from server 202.192.33.100; our IP address is 202.192.33.120
Filename 'u-boot.bin'.
Load address: 0x30008000
Loading: #####################
done
Bytes transferred = 106548 (1a034 hex)
protect off all

......

erase 0 1a0ff

......

cp.b 30008000 0 1a0ff

......

reset

......

      使用一段时间后,感觉u-boot与ppcboot相比进步很大,功能丰富且稳定。好,bootloader也暂告一段落,内核、内核...



      Qt Hello World 出来后,马不停蹄开始自己的linux移植。开发板原来的bootloader是ppcboot2.0,能用就先不理它,第一步是直接跳到内核编译。编译很快(与Qt相比 ^_^ ),通过ppcboot下载到内存,问题就出来了。执行
tftp 30008000 zImage
bootm 30008000
后,直接跳回原来的系统启动,没有从新内核启动。而执行 go 30008000 确可以跳到新内核,这里有点不解。可是新内核也有问题,就是串口在内核的默认名称已改为 ttySAC0 ,而可能ppcboot的传给内核的默认参数是console=ttyS0 。尝试通过boom 30008000 console=ttySAC0 传递,结果如上。尝试修改 ppcboot/lib_arm/armlinux.c 的 boot_cmd 参数,新问题有出现,编译不通过。看来不得不先搞定bootloader,ppcboot太旧了,试一下u-boot吧。最新的为下载是u-boot-1.2.0.tar.bz2,可惜,3.4.1和2.95.3的交叉编译都不通过。暂改用u-boot-1.1.5.tar.bz2 。这里又有一个问题,关于交叉编译链的路径问题。我原本存放在/arm/2.95.3/bin这个目录里,执行

make CROSS_COMPILE=/arm/2.95.3/bin/arm-linux-
      得到一小堆错误就停止,如下:

/arm/2.95.3/bin/arm-linux-gcc -Wa,-gstabs -D__ASSEMBLY__ -g  -Os   -fno-strict-aliasing  -fno-common -ffixed-r8 -msoft-float  -D__KERNEL__ -DTEXT_BASE=0x33F80000  -I/arm/u-boot-1.1.5/include -fno-builtin -ffreestanding -nostdinc -isystem include -pipe  -DCONFIG_ARM -D__ARM__ -mapcs-32 -march=armv4 -mabi=apcs-gnu -c -o lowlevel_init.o lowlevel_init.S
arm-linux-gcc: installation problem, cannot exec `cpp0': No such file or directory
as: unrecognized option `-marmv4'
make[1]: *** [lowlevel_init.o] Error 1
make[1]: Leaving directory `/arm/u-boot-1.1.5/board/smdk2410'
make: *** [board/smdk2410/libsmdk2410.a] Error 2
      改用3.4.1编译,

make CROSS_COMPILE=/arm/3.4.1/bin/arm-linux-

      提示链接错误,搜索后发现网上大多是因为u-boot采用软浮点的问题,但改了-msoft-float 这项后问题依旧:

                -Map u-boot.map -o u-boot
lib_arm/libarm.a(_udivsi3.o)(.text+0x8c):_udivsi3.S:67: relocation truncated to fit: R_ARM_PLT32 __div0
lib_arm/libarm.a(_umodsi3.o)(.text+0xa8):_umodsi3.S:79: relocation truncated to fit: R_ARM_PLT32 __div0
make: *** [u-boot] Error 1

      就这般无奈,一天过去。早上继续搜索,不负有心人啊,终于发现是目录问题,换回2.95.3编译成功。

ln -s /arm/2.95.3 /usr/local/arm/2.95.3

      竟然目录的位置与编译结果有关,不知是否与编译这个 cross toolchain 时的设置有关?尝试将3.4.1作同样的软链接,可惜错误依旧...这些都留到日后研究吧,下一步先搞定linux 2.6.19.2 ......



一不小心,又过三天......

        这个Hello World可真不容易,本以为考完试可以在实验室全情投入,想不到第三天就要封闭...幸好朋友的实验室还可以用,电脑配置也不错 ^_^

        Qtopia Core 4是QT/embedded的最新版,网上找很久都没有相关教材,尽是QT/embedded 2的版本。我刚学,干脆就直接上最新版 ^_^ 费了不少时间,作个记录,方便有需要的朋友...

        我的目标平台是三星的s3c2410,linux2.4内核,开发平台是RHEL.AS.v4.0.Update2,直接从ftp://ftp.scau.edu.cn/linux_unix/VMware_OS/RedHat_AS_4/Red Hat Enterprise Linux 4.vmdk下载的虚拟机镜像。经过这三天的使用,我认为虚拟机构建的系统有两个特点:一是慢,编译整个Qtopia Core 4用了近五个小时,而真机只需一个半钟;二是使用方便,可以直接在windows通过pietty连接,一边查资料,一边配置系统,而且工作环境改变时只需将镜像直接移到另外一台电脑,马上可以工作 ^_^

下面是Qtopia Core 4移植过程:

        1.  下载交叉编译链ftp://ftp.handhelds.org/projects/toolchain/arm-linux-gcc-3.4.1.tar.bz2。不要用cross-2.95.3,Qtopia Core 4指明要3.2以上的版本。网上的教程大多就拿cross-2.95.3编译QT/embedded 2的...解压缩到/usr/local/arm目录下

tar xjvf linux-gcc-3.4.1.tar.bz2 -C /

设置交叉编译的环境变量:

echo 'export PATH=/usr/local/arm/3.4.1/bin:$PATH' >> /root/.bashrc

        2.  下载Qtopia Core 4的源代码,建议到www.qtopia.org.cn下载,速度比www.trolltech.com快,迅雷速度就不错。我下的是qtopia-core-opensource-src-4.2.2.tar.gz,解压

tar zxvf qtopia-core-opensource-src-4.2.2.tar.gz

cd qtopia-core-opensource-src-4.2.2

./configure -embedded arm -xplatform qws/linux-arm-g++ -depths  4,8,12,16 -no-qt3support 

gmake  (这个过程最漫长...)

gmake install  (需root 权限)

设置Qt的环境变量:

echo 'export PATH=/usr/local/Trolltech/QtopiaCore-4.2.2-arm/bin:$PATH' >> /root/.bashrc

这样还有一个字体目录的问题,搞了很久才找到原因,后面讲述。

        3.  编译Hello World,代码参考Qt的文档,保存未 hello.cc 。

qmake -project

qmake

make

将文件移到目标平台,我是通过nfs mount到/mnt/nfs目录下

 mount -t nfs -o nolock 202.192.33.100:/home/nfs /mnt/nfs

export QTDIR=/mnt/nfs

export LD_LIBRARY_PATH=$QTDIR/lib

$QTDIR/lib里面放程序要用到的库和字体

lrwxrwxrwx  1 root root      18 Jan 25 20:39 /home/nfs/new/lib/libQtCore.so.4 -> libQtCore.so.4.2.2
-rwxr-xr-x  1 root root 2082044 Jan 25 20:38 /home/nfs/new/lib/libQtCore.so.4.2.2
lrwxrwxrwx  1 root root      17 Jan 24 21:44 /home/nfs/new/lib/libQtGui.so.4 -> libQtGui.so.4.2.2
-rwxr-xr-x  1 root root 7100212 Jan 24 21:42 /home/nfs/new/lib/libQtGui.so.4.2.2
lrwxrwxrwx  1 root root      21 Jan 25 20:36 /home/nfs/new/lib/libQtNetwork.so.4 -> libQtNetwork.so.4.2.2
-rwxr-xr-x  1 root root  369700 Jan 25 20:35 /home/nfs/new/lib/libQtNetwork.so.4.2.2

        可以根据提示从/usr/local/Trolltech/QtopiaCore-4.2.2-arm/lib/复制过来,注意软链接。如提示缺失libstdc++.so.6等库文件,可从/usr/local/arm/3.4.1/arm-linux/lib复制过来。

        最后一个问题就是刚才提到的字体问题。网上的教程都是说将fontdir放到$QTDIR/lib/fonts目录下即可。但我编译的这个版本总不行,提示 Cannot find font definition file /usr/local/Trolltech/QtopiaCore?

        尝试多次后才发现这个目录就是QtopiaCore的安装目录。创建一个软链接搞定

ln -s /mnt/nfs /usr/local/Trolltech/QtopiaCore-4.2.2-arm

        文档提示可以用-prefix 指定安装目录,但这也不是办法,configure --help里相关的还有-R和-rpath,可以指定链接库位置。只是虚拟机太慢,现在不敢随便乱make了。

没想到一个 Hello World 用了3天......

Tag: Qtopia ARM

分页共1页 1