arm移植过程(写的非常好,受益匪浅)(转发)

    技术2022-05-20  74

    arm内核移植过程

    转自: http://student.csdn.net/space.php?uid=366890&do=blog&id=28865

    1 内核移植过程

     

    1.1 下载linux 内核

     

        从http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.14.1.tar.bz2

    下载linux-2.6.14.1 内核至home/arm/dev_home/kernel.

    [root@localhost ~]#su arm

    [arm@localhost ~]#cd $KERNEL

    [arm@localhost kernel]#tar -xzvf linux-2.6.14.1.tar.gz

    [arm@localhost kernel]# pwd

    /home/arm/dev_home/kernel

    [arm@localhost kernel]# cd linux-2.6.14

           进入内核解压后的目录,以后示例中,只要是相对路径全部是相对于

           /home/arm/dev_home/kernel/linux-2.6.14/此目录

     

    1.2 修改 Makefile

     

    修改内核目录树根下的的Makefile,指明交叉编译器

    [arm@localhost linux-2.6.14]# vi Makefile

    找到ARCH 和CROSS_COMPILE ,修改

    ARCH       ?= arm

    CROSS_COMPILE    ?= arm-linux-

     

    然后设置你的PATH 环境变量,使其可以找到你的交叉编译工具链

    [arm@localhost linux-2.6.14]# echo $PATH

    ----------------------- 页面 53-----------------------

    /usr/local/arm/3.4.4/bin:/usr/kerberos/bin:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/home/ly/bin

    如果/usr/local/arm/3.4.4/bin 搜索路径, 加入下面语句在~/.bashrc 中

    [arm@localhost linux-2.6.14]# vi ~/.bashrc

    export PATH=/usr/local/arm/3.4.4/bin:$PATH

     

    再重新登陆.

    [arm@localhost linux-2.6.14]#su arm

     

    1.3 设置flash 分区

     

    此处一共要修改 3个文件,分别是:

     

    1.3.1指明分区信息

     

    在arch/arm/mach-s3c2410/devs.c 文件中:

     

    [arm@localhost linux-2.6.14]$ vi arch/arm/mach-s3c2410/devs.c

     

    添加如下内容:

    #include <linux/mtd/partitions.h>

    #include <linux/mtd/nand.h>

    #include <asm/arch/nand.h>

    ...

    /* NAND Controller */

     

    1.建立Nand Flash 分区表

    /* 一个Nand Flash 总共64MB, 按如下大小进行分区 */

    static struct mtd_partition partition_info[] ={

            { /* 1MB  */

                     name: "bootloader",

                     size:  0x00100000,

                     offset: 0x0,

            },{ /* 3MB */

                     name: "kernel",

                     size:  0x00300000,

                     offset: 0x00100000,

            }, { /* 40MB */

                     name: "root",

                     size:  0x02800000,

                     offset: 0x00400000,

            }, { /* 20MB */

                     name: "user",

                     size: 0x00f00000,

                     offset: 0x02d00000,

            }

    };

     

    name: 代表分区名字

    size: 代表flash 分区大小(单位:字节)

    offset: 代表flash 分区的起始地址(相对于0x0 的偏移)

     

     目标板计划分4 个区,分别存放bootloader, kernel, rootfs 以及以便以后扩展使用的用户文件系统空间。

    各分区在Nand flash 中起始地址. 分区大小. 记录如下:

    ----------------------- 页面 54-----------------------

     bootloader:

            start: 0x00000000

            len:    0x00100000

            1MB

     kernel:

            start: 0x00100000

            len:    0x00300000

            3MB

     rootfs:

            start: 0x00400000

            len:    0x02800000

            40MB

     User:

            start: 0x02c00000

            len:    0x01400000

            20MB

     

    2. 加入Nand Flash 分区

    struct s3c2410_nand_set nandset ={

            nr_partitions: 4,           /* the number of partitions */

            partitions: partition_info, /* partition table          */

    };

    nr_partitions: 指明partition_info 中定义的分区数目

    partitions: 分区信息表

     

    3. 建立Nand Flash 芯片支持

    struct s3c2410_platform_nand superlpplatform={

            tacls:0,

            twrph0:30,

            twrph1:0,

            sets: &nandset,

            nr_sets: 1,

    };

    tacls, twrph0, twrph1 的意思见S3C2410 手册的6-3, 这3 个值最后会被设置到NFCONF 中,见S3C2410 手册6-6.

    sets: 支持的分区集

    nr_set:分区集的个数

     

    4. 加入Nand Flash 芯片支持到Nand Flash 驱动

    另外,还要修改此文件中的s3c_device_nand 结构体变量,添加对dev 成员的赋值

    struct platform_device s3c_device_nand = {

            .name            = "s3c2410-nand",     /* Device name */

            .id              = -1,                 /* Device ID    */

            .num_resources       = ARRAY_SIZE(s3c_nand_resource),

            .resource        = s3c_nand_resource, /* Nand Flash Controller Registers */

     

            /* Add the Nand Flash device */

            .dev = {

                      .platform_data = &superlpplatform

              }

    };

    ----------------------- 页面 55-----------------------

    name:  设备名称

    id: 有效设备编号,如果只有唯一的一个设备为-1, 有多个设备从0 开始计数.

    num_resource: 有几个寄存器区

    resource: 寄存器区数组首地址

    dev: 支持的Nand Flash 设备

     

    1.3.2 指定启动时初始化

     

    kernel 启动时依据我们对分区的设置进行初始配置 

    修改arch/arm/mach-s3c2410/mach-smdk2410.c 文件

    [arm@localhost linux-2.6.14]$ vi arch/arm/mach-s3c2410/mach-smdk2410.c

    修改smdk2410_devices[].指明初始化时包括我们在前面所设置的flash 分区信息

    static struct platform_device *smdk2410_devices[] __initdata = {

            &s3c_device_usb,

            &s3c_device_lcd,

            &s3c_device_wdt,

            &s3c_device_i2c,

            &s3c_device_iis,

     

            /* 添加如下语句即可 */

            &s3c_device_nand,

    };

    保存,退出。

     

    1.3.3 禁止 Flash ECC校验 

     

        我们的内核都是通过UBOOT 写到Nand Flash 的, UBOOT 通过的软件ECC 算法产生ECC 校验码, 这与内核

    校验的ECC 码不一样, 内核中的ECC 码是由S3C2410 中Nand Flash 控制器产生的. 所以, 我们在这里选择禁止

    内核ECC 校验.

    修改drivers/mtd/nand/s3c2410.c 文件:

    [arm@localhost linux-2.6.14]$ vi drivers/mtd/nand/s3c2410.c

    找到s3c2410_nand_init_chip()函数,在该函数体最后加上一条语句:

    chip->eccmode = NAND_ECC_NONE;

    保存,退出。

     

    OK.我们的关于flash 分区的设置全部完工.

     

    1.4 配置内核

     

    1.4.1 支持启动时挂载 devfs

     

    为了我们的内核支持devfs 以及在启动时并在/sbin/init 运                 之前能自动挂载/dev 为devfs 文件系统,修改

    fs/Kconfig 文件

    [arm@localhost linux-2.6.14]$ vi fs/Kconfig

    找到menu "Pseudo filesystems"

    添加如下语句:

    config DEVFS_FS

            bool "/dev file system support (OBSOLETE)"

            default y

     

    config DEVFS_MOUNT

    ----------------------- 页面 56-----------------------

            bool "Automatically mount at boot"

            default y

            depends on DEVFS_FS

     

    1.4.2 配置内核产生.config 文件

     

    [arm@localhost linux-2.6.14]$ cp arch/arm/configs/smdk2410_defconfig .config

    [arm@localhost linux-2.6.14]$ make menuconfig

     

    在smdk2410_defconfig 基础上,我所增删的内核配置项如下:

     

    Loadable module support  --->

                              [*] Enable loadable module support

                                       [*] Automatic kernel module loading

     

    System Type  ---> [*] S3C2410 DMA support

     

    Boot options  ---> Default kernel command string:

             noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0,115200

     

             #说明:mtdblock2 代表我的第3 个flash 分区,它是我的rootfs

             #   console=ttySAC0,115200 使kernel 启动期间的信息全部输出到串口0 上.

             #   2.6 内核对于串口的命名改为ttySAC0 ,但这不影响用户空间的串口编程。

             #   用户空间的串口编程针对的仍是/dev/ttyS0 等

     

    Floating point emulation --->

                              [*] NWFPE math emulation

                                This is necessary to run most binaries!!!

     

    #接下来要做的是对内核MTD 子系统的设置

    Device Drivers  --->

             Memory Technology Devices (MTD)  --->

                              [*] MTD partitioning support

                                #支持MTD 分区,这样我们在前面设置的分区才有意义

                              [*] Command line partition table parsing

                                #支持从命令行设置flash 分区信息,灵活

                                       RAM/ROM/Flash chip drivers  --->

                                        <*> Detect flash chips by Common Flash

                                         Interface (CFI) probe

                                        <*> Detect non-CFI AMD/JEDEC-compatible flash chips

                                        <*> Support for Intel/Sharp flash chips

                                        <*> Support for AMD/Fujitsu flash chips

                                        <*> Support for ROM chips in bus mapping

                                       NAND Flash Device Drivers  --->

                                        <*> NAND Device Support

                                        <*> NAND Flash support for S3C2410/S3C2440 SoC

     

             Character devices  --->

                              [*] Non-standard serial port support

                              [*] S3C2410 RTC Driver

     

    #接下来做的是针对文件系统的设置,本人实验时目标板上要上的文件系统是cramfs,故做如下配置

    ----------------------- 页面 57-----------------------

    File systems  --->

                              <> Second extended fs support  #去除对ext2 的支持

                     Pseudo filesystems  --->

                              [*] /proc file system support

                              [*] Virtual memory file system support (former shm fs)

                              [*] /dev file system support (OBSOLETE)

                              [*] Automatically mount at boot (NEW)

                                #这里会看到我们前先修改fs/Kconfig 的成果,devfs 已经被支持上了

                     Miscellaneous filesystems  --->

                              <*> Compressed ROM file system support (cramfs)

                                #支持cramfs

                     Network File Systems  --->

                              <*> NFS file system support

     

    保存退出,产生.config 文件.

    .config 文件能从提供的2.4.14.1 的内核包中找到,文件名为config.back.

     

    1.4.3编译内核

     

    [arm@localhost linux-2.6.14]$ make zImage

    注意:若编译内核出现如下情况

      LD     .tmp_vmlinux1

      arm-linux-ld:arch/arm/kernel/vmlinux.lds:1439: parse error

      make: *** [.tmp_vmlinux1] Error 1

     

    解决方法:修改arch/arm/kernel/vmlinux.lds

    [arm@localhost linux-2.6.14]$ vi arch/arm/kernel/vmlinux.lds

    将文件尾2 条的ASSERT 注释掉 (1439                    )

    /* ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support") */

    /* ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined") */

     

    然后重新make zImage 即可

     

    1.4.4 下载zImage到开发板

     

    CRANE2410 # tftp 0x30008000 zImage

    TFTP from server 192.168.1.6; our IP address is 192.168.1.5

    Filename 'zImage'.

    Load address: 0x30008000

    Loading: #################################################################

             #################################################################

             #################################################################

             #############################

    done

    Bytes transferred = 1142856 (117048 hex)

    CRANE2410 # bootm 0x30008000

     

    1.4.5 目标板启动信息如下

    IRQ Stack: 33fc149c

    FIQ Stack: 33fc249c

    1

    ----------------------- 页面 58-----------------------

    1

    DRAM Configuration:

    Bank #0: 30000000 64 MB

    1

    NAND:64 MB

    In:   serial

    Out:   serial

    Err:  serial

    Hit any key to stop autoboot:  0

    zImage magic = 0x016f2818

    NOW, Booting Linux......

    Uncompressing Linux............................................................................ don.Linux version 2.6.14.1 (arm@dozec) (gcc

    version 3.3.2) #15 Thu Jul 6 14:26:29 CST 2006

    CPU: ARM920Tid(wb) [41129200] revision 0 (ARMv4T)

    Machine: SMDK2410

    Warning: bad configuration page, trying to continue

    Memory policy: ECC disabled, Data cache writeback

    CPU S3C2410A (id 0x32410002)

    S3C2410: core 202.800 MHz, memory 101.400 MHz, peripheral 50.700 MHz

    S3C2410 Clocks, (c) 2004 Simtec Electronics

    CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on

    CPU0: D VIVT write-back cache

    CPU0: I cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets

    CPU0: D cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets

    Built 1 zonelists

    Kernel command line: noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0,115200

    irq: clearing subpending status 00000002

    PID hash table entries: 128 (order: 7, 2048 bytes)

    timer tcon=00500000, tcnt a509, tcfg 00000200,00000000, usec 00001e4c

    Console: colour dummy device 80x30

    Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)

    Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)

    Memory: 16MB = 16MB total

    Memory: 13712KB available (1927K code, 422K data, 104K init)

    Mount-cache hash table entries: 512

    CPU: Testing write buffer coherency: ok

    softlockup thread 0 started up.

    NET: Registered protocol family 16

    S3C2410: Initialising architecture

    SCSI subsystem initialized

    usbcore: registered new driver usbfs

    usbcore: registered new driver hub

    S3C2410 DMA Driver, (c) 2003-2004 Simtec Electronics

    DMA channel 0 at c1800000, irq 33

    DMA channel 1 at c1800040, irq 34

    DMA channel 2 at c1800080, irq 35

    DMA channel 3 at c18000c0, irq 36

    NetWinder Floating Point Emulator V0.97 (double precision)

    devfs: 2004-01-31 Richard Gooch (rgooch@atnf.csiro.au)

    devfs: boot_options: 0x1

    Console: switching to colour frame buffer device 80x25

    fb0: Virtual frame buffer device, using 1024K of video memory

    ----------------------- 页面 59-----------------------

    S3C2410 RTC, (c) 2004 Simtec Electronics

    s3c2410_serial0 at MMIO 0x50000000 (irq = 70) is a S3C2410

    s3c2410_serial1 at MMIO 0x50004000 (irq = 73) is a S3C2410

    s3c2410_serial2 at MMIO 0x50008000 (irq = 76) is a S3C2410

    io scheduler noop registered

    io scheduler anticipatory registered

    io scheduler deadline registered

    io scheduler cfq registered

    RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize

    Cirrus Logic CS8900A driver for Linux (Modified for SMDK2410)

    eth0: CS8900A rev E at 0xe0000300 irq=53, no eeprom , addr: 08: 0:3E:26:0A:5B

    S3C24XX NAND Driver, (c) 2004 Simtec Electronics

    s3c2410-nand: mapped registers at c1980000

    s3c2410-nand: timing: Tacls 10ns, Twrph0 30ns, Twrph1 10ns

    NAND device: Manufacturer ID: 0xec, Chip ID: 0x76 (Samsung NAND 64MiB 3,3V 8-bit)

    NAND_ECC_NONE selected by board driver. This is not recommended !!

    Scanning device for bad blocks

    Creating 4 MTD partitions on "NAND 64MiB 3,3V 8-bit":

    0x00000000-0x00100000 : "bootloader"

    0x00100000-0x00500000 : "kernel"

    0x00500000-0x02d00000 : "root"

    0x02d00000-0x03c00000 : "User"

    usbmon: debugfs is not available

    116x: driver isp116x-hcd, 05 Aug 2005

    s3c2410-ohci s3c2410-ohci: S3C24XX OHCI

    s3c2410-ohci s3c2410-ohci: new USB bus registered, assigned bus number 1

    s3c2410-ohci s3c2410-ohci: irq 42, io mem 0x49000000

    usb usb1: Product: S3C24XX OHCI

    usb usb1: Manufacturer: Linux 2.6.14.1 ohci_hcd

    usb usb1: SerialNumber: s3c24xx

    hub 1-0:1.0: USB hub found

    hub 1-0:1.0: 2 ports detected

    sl811: driver sl811-hcd, 19 May 2005

    usbcore: registered new driver cdc_acm

    drivers/usb/class/cdc-acm.c: v0.23:USB Abstract Control Model driver for USB modems and ISDN

    adaptesdrivers/usb/class/bluetty.c: USB Bluetooth support registered

    usbcore: registered new driver bluetty

    drivers/usb/class/bluetty.c: USB Bluetooth tty driver v0.13

    usbcore: registered new driver usblp

    drivers/usb/class/usblp.c: v0.13: USB Printer Device Class driver

    Initializing USB Mass Storage driver...

    usbcore: registered new driver usb-storage

    USB Mass Storage support registered.

    mice: PS/2 mouse device common for all mice

    NET: Registered protocol family 2

    IP route cache hash table entries: 256 (order: -2, 1024 bytes)

    TCP established hash table entries: 1024 (order: 0, 4096 bytes)

    TCP bind hash table entries: 1024 (order: 0, 4096 bytes)

    TCP: Hash tables configured (established 1024 bind 1024)

    TCP reno registered

    TCP bic registered

    NET: Registered protocol family 1

    ----------------------- 页面 60-----------------------

    NET: Registered protocol family 17

    Reading data from NAND FLASH without ECC is not recommended

    VFS: Mounted root (cramfs filesystem) readonly.

    Mounted devfs on /dev

    Freeing init memory: 104K

    Reading data from NAND FLASH without ECC is not recommended

    mount /etc as ramfs

    re-create the /etc/mtab entries

    ------------mount /dev/shm as tmpfs

    ------------mount /proc as proc

    ------------mount /sys as sysfs

    init started:  BusyBox v1.1.3 (2006.07.03-03:43+0000) multi-call binary

    Starting pid 28, console /dev/tts/0: '/etc/init.d/rcS'

    in /etc/init.d/rcS

    -------------/sbin/ifconfig eth0 192.168.1.5

     

    Please press Enter to activate this console.

    #

     

    1.5 Linux 下cs8900a 的移植说明

     

    1.5.1 为 cs8900a建立编译菜单

     

    1. 拷贝到文件

    把cs8900a 的压缩包拷贝到arm 用户下的dev_home/localapps/

    [arm@localhost localapps]$ tar -xzvf cs8900a.tar.gz

    [arm@localhost localapps]$cd cs8900a

    [arm@localhost cs8900a]$cp     cs8900a.c $KERNEL/linux-2.6.14.1/drivers/net/

    [arm@localhost cs8900a]$cp cs8900.h $KERNEL/linux-2.6.14.1/drivers/net/

     

    2. 修改Kconfig 文件

    [arm@localhost cs8900a]$vi $KERNEL/linux-2.6.14.1/drivers/net/Kconfig

    #加入如下内容

     

            config CS8900a

            tristate "CS8900a support"

            depends on NET_ETHERNET && ARM && ARCH_SMDK2410

            ---help---

             Support for CS8900A chipset based Ethernet cards. If you have a network (Ether

             net) card of this type, say Y and read the  Ethernet-HOWTO, available from  as

             well as.

             To compile this driver as a module, choose M here and read.

             The module will be called cs8900.o.

     

    3. 修改Makefile 文件

    [arm@localhost cs8900a]$vi $KERNEL/linux-2.6.14.1/drivers/net/Makefile

    #加入如下内容

             obj-$(CONFIG_CS8900a)            += cs8900a.o

     

    1.5.2 修改 S3C2410相关信息

     

    1. 加入CS8900A 在内存中的起始位置

    ----------------------- 页面 61-----------------------

    [arm@localhost cs8900a]$cp reg-cs8900.h $KERNEL/linux-2.6.14.1/include/asm-arm/arch-s3c2410/

    cs8900.h 的内容如下:

    #ifndef _INCLUDE_CS8900A_H_

    #define _INCLUDE_CS8900A_H_

     

    #include <linux/config.h>

     

    #define pSMDK2410_ETH_IO           0x19000000 /* S3C2410_CS3 0x18000000 */

    #define vSMDK2410_ETH_IO           0xE0000000

    #define SMDK2410_ETH_IRQ           IRQ_EINT9

     

    #endif

     

    2. 加入cs8900A 的物理地址到虚拟地址的映射

    [arm@localhost cs8900a]$vi $KERNEL/linux-2.6.14.1/arch/arm/mach-s3c2410/mach-smdk2410.c

    /* 加入如下内容 */

    static struct map_desc smdk2410_iodesc[] __initdata = {

      {vSMDK2410_ETH_IO, 0x19000000, SZ_1M, MT_DEVICE} /* Add this line */

    };

     

    2 创建 uImage

     

    2.1 相关技术背景介绍

     

        前面已经介绍了内核编译后,生成zImage 的内核镜像文件。该镜像文件可以通过U-BOOT 提供的go 命令,

    跳转执行,引导内核。同时在u-boot-1.1.4 的tools  目录下,提供了生成uImage 的工具mkimage 命令,在生成

    u-boot 的二进制镜像文件的同时,mkimage 命令会同时编译生成,无需另外编译。通过mkimage 命令,在

    zImage 中加入头文件 (镜像头长0x40,真正的内核入口向后偏移了0x40 大小),生成uImage 镜像文件,该文

    件就是执       bootm 所需的内核镜像文件。

     

    2.2 在内核中创建 uImage 的方法

     

    2.2.1 获取 mkimage工具

     

       2.6 内核树的Makefile 提供了创建uImage 的方法,但需要我们提供相应的mkimage 命令。

       所以首先拷贝u-boot 中tools  目录下编译后生成的mkimage 到/usr/bin/下,然后便可以在内核根目录下通过

    make uImage

       来创建uImage 文件。该文件生成在arch/arm/boot/下。

     

    2.2.2 修改内核的 Makefile文件

     

    [arm@localhost linux-2.6.14.1]$ vi arch/arm/boot/Makefile

     

    #MKIMAGE 变量记录mkimage 命令的路径mkuboot.sh 脚本文件可以scripts  目录中找到

    MKIMAGE        := $(srctree)/scripts/mkuboot.sh

     

    #zreladdr-y 与params_phys-y 可以在arch/arm/mach-s3c2410/Makefile.boot 当中找到

    ZRELADDR     := $(zreladdr-y)

    PARAMS_PHYS := $(params_phys-y)

    INITRD_PHYS := $(initrd_phys-y)

    ----------------------- 页面 62-----------------------

    #生成uImage 的mkImage 命令行,其中需要关注的就是-a 与 -e 参数。

    #参数-a:指明uImage 加载的SDRAM 地址,内核默认指定加载地址为0x30008000 。

    #       u-boot 引导时,bootm 命令跳到与上相同位置执行,检查完镜像头后,它会跳到内核真正的入口点开

    始执    。

    #参数-e:指明uImage 中刨去镜像头后真正的内核入口地址。

    #    镜像头为0x40 长,故此处指定为0x30008040 。

    #       u-boot 引导时,go 命令可以直接指定此位置。go 命令不检查镜像头。

    quiet_cmd_uimage = UIMAGE  $@

          cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel /

                      -C none -a $(ZRELADDR) -e 0x30008040 /

                      -n 'Linux-$(KERNELRELEASE)' -d $< $@

     

    3追加实验记录

     

    以同样方式移植其他2.6 主线内核,出现问题如下:

     

    3.1移植 linux-2.6.15.7

     

        编译通过,启动时显示:

           VFS: Cannot open root device "mtdblock2" or unknown-block(31,2)

           Please append a correct "root=" boot option

           Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(31,2)

     

    3.2 移植 linux-2.6.16.21

     

         编译通过,启动时显示:

           VFS: Cannot open root device "mtdblock2" or unknown-block(31,2)

           Please append a correct "root=" boot option

           Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(31,2)

     

    3.3 移植 linux-2.6.17

     

           编译失败

     

    4 参考资料

     

    1. Porting kernel 2.6.11.7 to S3C2410

           http://superlp.blogchina.com/1391393.html

           非常感谢此篇文档的作者

     

    2. devfs 介绍

           http://www-128.ibm.com/developerworks/cn/linux/filesystem/l-fs4/index.html#resources

     

    3. <<BUILDING EMBEDDED LINUX SYSTEMS>>

        中文名:<<构建嵌入式Linux 系统>>

     


    最新回复(0)