书海七天

2007-02-23

      转眼七天,书也看了不少,不过Linux Device Drivers这本书恐怕不能看完第一遍。第一次拿起全英的书认真地读,感觉不错,就是有些句子不好懂。看来,阅读能力还亟待提高 ^_^
      但是,我发现这本书并没有直接指导怎么写driver,前些天看到的一些代码也没提到(如platform_device)。大体上介绍了一些结构体及其使用,也许driver就是如何填写这些机构体。回去后应该看看具体的代码写写实际的driver,然后再看第二遍的LDD,效果应该不错...
      不过,首先应解决网卡问题。想不到在业余时间找到解决的方法:修改s3c2410 eint0的快速中断模式为普通中断,__raw_writel(0, S3C2410_INTMOD) 。在arm.linux的maillist里提到过,但ben的这句话不懂:
There isn't any current ARM interface to change IRQ to FIQ mode,
but I don't see any reason there can't be.
也不知道为什么只有eint0处于FIQ模式...

      话说今天顺路去修电脑,竟被小流氓耍了一个晚上。由于时间关系,这台电脑已被外面修电脑的老友修过一遍,将我ghost备份包通通删掉,分区全部卸掉...唉,混口饭也不应该这么随便...不理,这次的任务是恢复IE的xmlhttp功能(其实就是一个看比分的网站刷新失常)。看启动项,没异常;重装IE,没解决...要是手上有光盘,重装系统比现在傻模还省时间...实在不行看看新闻 ^_^,想起流氓之父,马上下个360safe。没想到,浏览器真的被劫持了...这些网站还真是的,连firefox都不支持,兼容性有待提高 ^_^

Tag: 琐事


      自从移植BusyBox v1.4.1后,上下左右这几个方向键总是有问题,按下后很可爱的显示 ^[[A^[[B^[[D^[[C 等无法识别的字符。在BusyBox的maillist和google里找到少许类似的问题,不过没有解答。今天总算找到一个部分解决的方法...

      在Shell选项里选中 command line editing、tab completion、username completion。好了,小问题算解决一半,telnet连入开发板后命令行记录、编辑和tab提示都好了!有点激动,我的嵌入式系统又稍微完善了一点 ^_^ 可是,通过串口连进开发板仍然有问题。

# cd /

# ^[[A^[[A
# cd /
# ^[[A
# cd /
# ^[[A
# cd /
# cd /^[[A^[[A
上箭头回车后第一次按下时正常,按多几下就不行了...

# cd li (注:此处有一个tab ^_^)
# cd lib/
#

# cd /mn (两个)
# cd /mnt/etc/
#
由上可见,tab是有点正常的,不过傻么显示都没有...真傻...

算了,总算有个完整的telnet可用,不用狂击键盘了...



      UDEV,新一代的用户空间设备管理系统,用以取代臃肿的DEVFS(其实DEVFS我还没用过,谁叫我是新来的 ^_^ ,关于两者的对比,可以参考 udev_vs_devfs )。关于UDEV的使用已经有一遍不错的译文 udev轻松上路 ,不过里面关于配置文件的编写与 Writing udev rules 不符。/etc/udev/udev.conf 是udev启动检查的配置文件,包括路径,权限,规则目录等,具体的规则文件应该为/etc/udev/rules.d/10-local.rules 。

      我开始移植的第一个Linux是2.6.19.2,已放弃对DEVFS的支持,下面谈谈UDEV在我的arm开发板上的应用。由于BusyBox已带有一个简化板的udev--mdev。通过简单的 mdev -s ,就能自动装配/dev目录下的设备文件:

# ls /dev
console  null     ptmx     pts      shm
# mdev -s && ls /dev
apm_bios         ptypd            tty24            tty56
console          ptype            tty25            tty57
fb0              ptypf            tty26            tty58
full             ram0             tty27            tty59
kmem             ram1             tty28            tty6
kmsg             ram2             tty29            tty60
loop0            ram3             tty3             tty61
... ...

启动热拔插支持的话,用这一句

echo /sbin/mdev > /proc/sys/kernel/hotplug

      一切就是这么简单,相应的/dev目录下会出现一大堆设备文件,甚是难看 ^_^ 

      mdev的规则文件是/etc/mdev.conf ,与传统的udev规则文件写法上有点区别(简化了^_^)。

KERNEL=="tty[0-9]*", NAME="vc/%n"   //for udev

tty[0-9]* 0:5 660  //for mdev

如果选上FEATURE_MDEV_EXEC支持,规则后面可以执行相应的命令,如:

pts/ 0:0 755 $mount -t devpts /dev/pts /dev/pts

不过我的程序还算简单,mdev -s 对我而言已足够,规则,留作日后写吧 ^_^


nc 使用摘录

2007-02-11

netcat -- 功能多得无法想象的网络通道,俗称“瑞士军刀”

server: nc -l -p 1234 监听端口1234

client: nc 192.168.0.1 1234 连入服务器

server: nc -l -p 1234 -e bash 连入时获得shell

client: nc -e 192.168.0.1 1234 也可以在客户端指定

server: nc -e bash 192.168.0.11234 反向连接

client: nc -l -p 1234

server: tar -czf - file | nc -l -c -p 1234 打包文件传送

client: nc 192.168.0.1 1234 | tar xzvf - 解压

nc -nv -w2 -z 192.168.0.1 80-445 扫描端口

......

Tag: 代码


      想不到,早上才解决网卡问题,晚上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号中断就死机...


分页共1页 1