• Linux内核开发


    为了说清楚要修改的地方,下面会比较啰嗦

    Linux系统内核的源代码是开放的,因此我们可以从官网上下载Linux内核。

    下载地址:https://www.kernel.org

    解压之后进入内核会看到一下一下目录:

    arch   COPYING  	crypto      drivers   	fs       init  	  Kbuild    kernel     MAINTAINERS  
    mm     README   	samples  	security  	tools  	 virt	  block     CREDITS    Documentation  
    firmware  include  ipc   Kconfig  lib     Makefile     net  REPORTING-BUGS  scripts  sound   usr
    

     其中每个目录的表示如下:

    arch(cpu)   COPYING  	crypto(加密算法)      drivers(驱动)   	fs(file system)       init(init进程)  	  Kbuild(内核编译时使用的)    
    kernel(Linux内核核心相关的)     MAINTAINERS(Linux内核的维护人员信息)    mm(内存管理)      README   	samples(Linux内核使用的示例)  	
    security  	tools(工具)  	 virt(虚拟机)	  block(块设备)     CREDITS(感谢谁)    Documentation(文档)    firmware(系统固件)  
    include(头文件)  ipc(进程间相互通信)   Kconfig(make menuconfig时使用的)  lib(Linux要使用的相关的库)     Makefile     
    net(网络相关的)  REPORTING-BUGS  scripts(Linux内核编译的脚本)  sound(声卡相关的)   usr(用户)
    

    内核要修改的地方其实很少,只需要改一下arch/arm/目录下我们要用的cpu的源代码就可以了。当我们要用到某个驱动时就修改一下driver目录下的驱动的代码。

    在这里要把Linux内核烧录到基于Samsung S3C2440处理器的fl2440开发板上,Linux内核适用于很多架构的内核,可以在arch目录下看到:

    alpha  avr32     cris  h8300  Kconfig  m68k        mips     parisc   s390   sh     tile  unicore32  xtensa
    arm    blackfin  frv   ia64   m32r     microblaze  mn10300  powerpc  score  sparc  um    x86
    

    在这里显示的并不是一种型号的CPU而是一种架构的CPU,我们要进入到arm架构里面去:

    boot           mach-at91      mach-footbridge  mach-ixp23xx   mach-mv78xx0  mach-pnx4008   mach-s3c2443   mach-spear3xx   mach-w90x900  plat-orion      vfp
    common         mach-bcmring   mach-gemini      mach-ixp4xx    mach-mx5      mach-pxa       mach-s3c24a0   mach-spear6xx   Makefile      plat-pxa
    configs        mach-clps711x  mach-h720x       mach-kirkwood  mach-mxs      mach-realview  mach-s3c64xx   mach-tcc8k      mm            plat-s3c24xx
    include        mach-cns3xxx   mach-imx         mach-ks8695    mach-netx     mach-rpc       mach-s5p64x0   mach-tegra      nwfpe         plat-s5p
    Kconfig        mach-davinci   mach-integrator  mach-l7200     mach-nomadik  mach-s3c2400   mach-s5pc100   mach-u300       oprofile      plat-samsung
    Kconfig.debug  mach-dove      mach-iop13xx     mach-loki      mach-nuc93x   mach-s3c2410   mach-s5pv210   mach-ux500      plat-iop      plat-spear
    Kconfig-nommu  mach-ebsa110   mach-iop32x      mach-lpc32xx   mach-omap1    mach-s3c2412   mach-sa1100    mach-versatile  plat-mxc      plat-tcc
    kernel         mach-ep93xx    mach-iop33x      mach-mmp       mach-omap2    mach-s3c2416   mach-shark     mach-vexpress   plat-nomadik  plat-versatile
    lib            mach-exynos4   mach-ixp2000     mach-msm       mach-orion5x  mach-s3c2440   mach-shmobile  mach-vt8500     plat-omap     tools

    惯例,第一步要改的是Makefile文件

    [wangchengcheng@centos6 linux-3.0]$ vim Makefile

    修改要编译的内核与交叉编译器:

    1 @@ -192,8 +192,8 @@
    2  # Default value for CROSS_COMPILE is not to prefix executables
    3  # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
    4  export KBUILD_BUILDHOST := $(SUBARCH)
    5 -ARCH           ?= $(SUBARCH)
    6 -CROSS_COMPILE  ?= $(CONFIG_CROSS_COMPILE:"%"=%)
    7 +ARCH           ?= arm
    8 +CROSS_COMPILE  ?= /opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-

     其次要修改编译完成之后自动调用mkimage,这里的mkimage内核源代码并没有给提供,在编译好的u-boot的tools文件夹中,我们可以把它拷贝到当前目录下或者/bin/目录下或者/usr/bin/目录下。在这里我把它拷贝到了当前目录下。然后修改Makefile文件:

    1 @@ -557,6 +557,9 @@
    2  # This allow a user to issue only 'make' to build a kernel including modules
    3  # Defaults to vmlinux, but the arch makefile usually adds further targets
    4  all: vmlinux
    5 +       cp arch/arm/boot/zImage . -f
    6 +       mkimage -A arm -O linux -T kernel -C none -a 30008000 -e 30008040 -n "Linux Kernel" -d zImage linuxrom-s3c2440.bin
    7 +       rm -f zImage

    注:mkimage命令的作用是将内核编译出来的二进制文件转换为u-boot能够识别的二进制文件。

    接下来改的地方是make distclean,当我们make distclean时我们希望把可执行文件linuxrom-s3c2440.bin文件给删掉:

    1 @@ -1201,6 +1204,7 @@
    2                 -o -name '.*.rej' -o -size 0 
    3                 -o -name '*%' -o -name '.*.cmd' -o -name 'core' ) 
    4                 -type f -print | xargs rm -f
    5 +       @rm -f linuxrom-*.bin

    到此,Makefile文件就修改完成了!要开始修改内核源代码了!

    [wangchengcheng@centos6 linux-3.0]$ vim arch/arm/mach-s3c2440/mach-smdk2440.c

    根据f2440开发板的原理图可知,其晶振频率为12MHZ因此要修改晶振频率:

     1 @@ -155,12 +196,13 @@
     2         &s3c_device_wdt,
     3         &s3c_device_i2c0,
     4         &s3c_device_iis,
     5  };
     6 
     7  static void __init smdk2440_map_io(void)
     8  {
     9         s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
    10 -       s3c24xx_init_clocks(16934400);
    11 +       s3c24xx_init_clocks(12000000);
    12         s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
    13  }

    接下来改串口,因为Linux的所有设备都是文件,文件的匹配需要用到name域来匹配。而Samsung公司串口的默认名字为"ttySAC"所以我们要把串口名字改成“ttyS”

    1 @@ -54,7 +54,7 @@
    2 
    3  /* UART name and device definitions */
    4 
    5 -#define S3C24XX_SERIAL_NAME    "ttySAC"
    6 +#define S3C24XX_SERIAL_NAME    "ttyS"
    7  #define S3C24XX_SERIAL_MAJOR   204
    8  #define S3C24XX_SERIAL_MINOR   64

    最后修改machine id设备编号

    由于将s3c2440的machine id与mini2440的machine id互换:

    [wangchengcheng@centos6 linux-3.0]$ vim arch/arm/tools/mach-types

     1 @@ -85,7 +85,7 @@
     2  bast                   ARCH_BAST               BAST                    331
     3  h1940                  ARCH_H1940              H1940                   347
     4  enp2611                        ARCH_ENP2611            ENP2611                 356
     5 -s3c2440                        ARCH_S3C2440            S3C2440                 362
     6 +s3c2440                        ARCH_S3C2440            S3C2440                 1999
     7  gumstix                        ARCH_GUMSTIX            GUMSTIX                 373
     8  omap_h2                        MACH_OMAP_H2            OMAP_H2                 382
     9  e740                   MACH_E740               E740                    384
    10 @@ -356,7 +356,7 @@
    11  snapper_9260           MACH_SNAPPER_9260       SNAPPER_9260            1987
    12  dsm320                 MACH_DSM320             DSM320                  1988
    13  exeda                  MACH_EXEDA              EXEDA                   1994
    14 -mini2440               MACH_MINI2440           MINI2440                1999
    15 +mini2440               MACH_MINI2440           MINI2440                362
    16  colibri300             MACH_COLIBRI300         COLIBRI300              2000
    17  linkstation_ls_hgl     MACH_LINKSTATION_LS_HGL LINKSTATION_LS_HGL      2005
    18  cpuat9g20              MACH_CPUAT9G20          CPUAT9G20               2031

    到此内核源代码最基本的修改就告一段落了,内核的编译主要依赖于.config这个文件。内核用这个文件来指导编译器要编译的与不要编译的。由于直接修改.config文件过于复杂,就像修改u-boot一样繁琐效率又很低。在这里人们人性化的设计了图形化界面:make menuconfig

    首先我们要在最高目录下创建一个.config文件,这里的.config文件参考mini2440的config文件:

    [wangchengcheng@centos6 linux-3.0]$ cp arch/arm/configs/mini2440_defconfig .config

    [wangchengcheng@centos6 linux-3.0]$ make menuconfig

    我们将看到:

     选择System Type  --->  S3C2440 and S3C2442 Machines  ---> 不选[ ] MINI2440 development board,选择[*] SMDK2440与[*] SMDK2440 with S3C2440 CPU module

    此时Linux内核已经初步修改完成,但是一些基本的驱动都没有加载。所以我们还是不能用它来做事情的。

    添加硬盘分区:

    [wangchengcheng@centos6 linux-3.0]$ vim arch/arm/plat-s3c24xx/common-smdk.c

     1 /* NAND parititon from 2.4.18-swl5 */
     2 
     3 static struct mtd_partition smdk_default_nand_part[] = {
     4     [0] = {
     5         .name   = "bootloader",
     6         .size   = SZ_1M,
     7         .offset = 0,
     8     },
     9     [1] = {
    10         .name   = "linux",
    11         .offset = MTDPART_OFS_NXTBLK,
    12         .size   = SZ_1M*15,
    13     },
    14     [2] = {
    15         .name   = "rootfs",
    16         .offset = MTDPART_OFS_NXTBLK,
    17         .size   = SZ_1M*40,
    18     },
    19     [3] = {
    20         .name   = "apps",
    21         .offset = MTDPART_OFS_NXTBLK,
    22         .size   = SZ_1M*50,
    23     },
    24     [4] = {
    25         .name   = "data",
    26         .offset = MTDPART_OFS_NXTBLK,
    27         .size   = SZ_1M*50,
    28     },
    29     [5] = {
    30         .name   = "backup",
    31         .size   = SZ_1M * 100,
    32         .size   = MTDPART_OFS_NXTBLK,
    33     },
    34 };
    35 
    36 static struct s3c2410_nand_set smdk_nand_sets[] = {
    37     [0] = {

    开发板上的nandflash是256M的,bootleader启动需要1M,内核需要15M,根文件系统需要40M,其他的自由分配。

    注:此时要在进行分区就要选择相应的文件系统。nandflash常用的文件系统有:yaffs2,ubifs,cramfs已经initramfs等。

    添加initramfs文件系统:

    initramfs是最简单的文件系统的添加方式:make menuconfig  --->   General setup  --->   选中[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support,并且在()    Initramfs source file(s)中指定根文件目录树的路径(相对路径或者绝对路径都可以。)

    添加DM9000网卡

    修改arch/arm/mach-s3c2440/mach-smdk2440.c

    #include <linux/dm9000.h>//添加DM9000网卡的头文件

    添加如下代码

    /* add DM9000 ethernet drivers ,whitch is modify by xiaohe */

    #define DM9000_BASE    (S3C2410_CS4 + 0x300)

    static struct resource s3c_dm9000_resource[] = {

         [0] = {

            .start = DM9000_BASE,

            .end   = DM9000_BASE + 3,

            .flags = IORESOURCE_MEM

        },

        [1] = {

            .start = DM9000_BASE + 4,

            .end   = DM9000_BASE + 7,

            .flags = IORESOURCE_MEM

        },

        [2] = {

            .start = IRQ_EINT7,

            .end   = IRQ_EINT7,

            .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,

        }

    };

    /*        

     * The DM9000 has no eeprom, and it's MAC address is set by

     * the bootloader before starting the kernel.

     */

    static struct dm9000_plat_data s3c_dm9000_pdata = {

        .flags      = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),

    };

     

    static struct platform_device s3c_device_dm9000 = {

        .name       = "dm9000",

        .id     = -1,

        .num_resources  = ARRAY_SIZE(s3c_dm9000_resource),

        .resource   = s3c_dm9000_resource,

        .dev        = {

            .platform_data  = &s3c_dm9000_pdata,

        },

    };

    /* modify end  */

     

    修改platform_device *smdk2440_devices[] __initdata结构体为如下,在其中添加启动DM9000

    static struct platform_device *smdk2440_devices[] __initdata = {

        &s3c_device_ohci,

        &s3c_device_lcd,

        &s3c_device_wdt,

        &s3c_device_i2c0,

        &s3c_device_iis,

        &s3c_device_dm9000,

    };

    重新make之后,内核就可以支持DM9000网络了,这时我们就可以用tftp下载文件到内核里去。

    这时输入ifconfig:

    >: ifconfig
    eth0 Link encap:Ethernet HWaddr 6A:C6:F1:ED:0D:F7
    inet addr:192.168.1.111 Bcast:192.168.1.255 Mask:255.255.255.0
    UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
    RX packets:138 errors:0 dropped:0 overruns:0 frame:0
    TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1000
    RX bytes:13167 (12.8 KiB) TX bytes:0 (0.0 B)
    Interrupt:51 Base address:0x4300

     

    添加U盘驱动

    一、添加U盘支持   

    FL2440添加u盘的挂载比较简单,大部分的内容都是在内核里面做make menuconfig,配置内核。

    Device Drivers  --->

         Generic Driver Options  --->

                       (/sbin/hotplug) path to uevent helper                  //配置u盘的热插拔

         [*] Block devices  --->

                       <*>   Low Performance USB Block driver        //低性能USB块设备驱动

         SCSI device support  --->

                      <*> SCSI device support    //SCSI设备的支持

                      <*> SCSI generic support    //SCSI通用的支持

                      [*] Probe all LUNs on each SCSI device            //所有在每个SCSI LUN探针装置

         [*] USB support  --->

                     <*>   Support for Host-side USB           //主机端USB支持

                     [*]     USB device filesystem (DEPRECATED)     //USB设备文件系统(不推荐使用)

                     [*]     USB device class-devices (DEPRECATED)    / /USB设备类设备(不推荐使用)

                     <*>   USB Monitor           //USB监控

                     <*>   OHCI HCD support //支持OHCI标准

                     <*>   USB Mass Storage support //支持USB海量存储

    File systems  --->                                              //配置u盘的文件系统

           DOS/FAT/NT Filesystems  --->

                      <*> MSDOS fs support

                      <*> VFAT (Windows-95) fs support

                      (936) Default codepage for FAT //默认代码页

                      (cp936) Default iocharset for FAT //默认字符集

          -*- Native language support  --->                                      //配置u盘的语言格式支持,不过感觉着个配置没什么用,中文也支持不了,也许是因为linux对中文的支持并不好吧

                      <*>   Simplified Chinese charset (CP936, GB2312)

                      <*>   ASCII (United States)

                      <*>   NLS UTF-8

     

    二、添加USB结构体变量,加厂商ID和设备ID

    diff -Nuar linux-3.0/drivers/usb/serial/option.c linux-3.0-s3c2440/drivers/usb/serial/option.c
    --- linux-3.0/drivers/usb/serial/option.c 2011-07-22 10:17:23.000000000 +0800
    +++ linux-3.0-s3c2440/drivers/usb/serial/option.c 2015-12-07 16:31:30.555485473 +0800
    @@ -51,6 +51,13 @@
    static void option_instat_callback(struct urb *urb);

     

    /* Vendor and product IDs */
    +static int vendor = 0; /* Add by guowenxue */
    +static int product = 0; /* Add by guowenxue */
    +
    +/* Vendor and product IDs */
    +#define OPTION_VENDOR_RESERVED 0xFFFF /* Add by guowenxue */
    +#define OPTION_RESERVED_DEVICE 0xFFFF /* Add by guowenxue */
    +
    #define OPTION_VENDOR_ID 0x0AF0
    #define OPTION_PRODUCT_COLT 0x5000
    #define OPTION_PRODUCT_RICOLA 0x6000
    @@ -446,7 +453,8 @@
    .reason = OPTION_BLACKLIST_SENDSETUP
    };

     

    -static const struct usb_device_id option_ids[] = {
    +static struct usb_device_id option_ids[] = {
    + { USB_DEVICE(OPTION_VENDOR_RESERVED, OPTION_RESERVED_DEVICE) }, /* Add by guowenxue */
    { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
    { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
    { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) },
    @@ -1079,6 +1087,15 @@
    static int __init option_init(void)
    {
    int retval;
    +
    + if ((vendor>0) && (product>0))
    + {
    + option_ids[0].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
    + option_ids[0].idVendor = vendor;
    + option_ids[0].idProduct = product;
    + printk("Register option drvier for modem vendor=0x%04x product=0x%04x ", vendor, product);
    + }
    +

    三、加宏和USB进程

    diff -Nuar linux-3.0/arch/arm/mach-s3c2440/mach-smdk2440.c linux-3.0-s3c2440/arch/arm/mach-s3c2440/mach-smdk2440.c
    --- linux-3.0/arch/arm/mach-s3c2440/mach-smdk2440.c 2011-07-22 10:17:23.000000000 +0800
    +++ linux-3.0-s3c2440/arch/arm/mach-s3c2440/mach-smdk2440.c 2015-12-07 16:31:30.532734715 +0800
    @@ -23,6 +23,13 @@
    #include <linux/platform_device.h>
    #include <linux/io.h>

    +/* add by guowenxue for norflash */
    +#include <linux/gpio_keys.h>
    +#include <linux/input.h>
    +#include <linux/mtd/physmap.h>
    +#include <linux/mtd/mtd.h>
    +#include <linux/mtd/partitions.h>
    +
    #include <asm/mach/arch.h>
    #include <asm/mach/map.h>
    #include <asm/mach/irq.h>
    @@ -44,6 +51,11 @@
    #include <plat/clock.h>
    #include <plat/devs.h>
    #include <plat/cpu.h>
    +#include <plat/ts.h> /*Add by guowenxue to support Touch screen, 2011.09.06*/
    +#include <mach/regs-clock.h> /*Add by guowenxue 2012.07.15, for usb_s3c2440_init() */
    +#include <linux/i2c.h> /*Add by guowenxue 2012.10.22, for AT24C512 driver */
    +#include <linux/i2c/at24.h> /* Add by guowenxue 2012.10.22, for AT24C512 driver */
    +#include <linux/delay.h>

    加USB的init进程:

    +int usb_s3c2440_init(void)
    +{
    + /* Input Frequency is 12.0000MHz, and MDEV=0x38 PDIV=2 SDIV=2, so output frequency 48.00MHz */
    + unsigned long upllvalue = (0x38<<12)|(0x02<<4)|(0x02);
    + while (upllvalue != __raw_readl(S3C2410_UPLLCON))
    + {
    + __raw_writel(upllvalue, S3C2410_UPLLCON);
    + mdelay(1);
    + }
    +
    + return 0;
    +}
    +
    static void __init smdk2440_map_io(void)

    {
    s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
    - s3c24xx_init_clocks(16934400);
    + s3c24xx_init_clocks(12000000); /*Modify by guowenxue, 2011.08.30*/
    s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
    + usb_s3c2440_init(); /* Add by guowenxue, 2012.07.15 */
    }

     配置好之后,插上U盘就可以看到如下信息:

    usb 1-1.1: new full speed USB device number 3 using s3c2410-ohci
    Dec 31 17:44:35 root kern.info kernel: usb 1-1.1: new full speed USB device number 3 using s3c2410-ohci
    usb 1-1.1: New USB device found, idVendor=048d, idProduct=1234
    usb 1-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
    usb 1-1.1: Product:
    usb 1-1.1: Manufacturer:
    usb 1-1.1: SerialNumber: 袎
    Dec 31 17:44:35 root kern.info kernel: usb 1-1.1: New USB device found, idVendor=048d, idProduct=1234
    Dec 31 17:44:35 root kern.info kernel: usb 1-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
    Dec 31 17:44:35 root kern.info kernel: usb 1-1.1: Product:
    Dec 31 17:44:35 root kern.info kernel: usb 1-1.1: Manufacturer:
    Dec 31 17:44:35 root kern.info kernel: usb 1-1.1: SerialNumber: 袎
    uba:
    Dec 31 17:44:35 root kern.info kernel: uba:

    表示USB驱动uba已经装载成功,这时可能会出现一个问题,我们查看/mnt/usb/并没有U盘里的信息。

     

    这是因为U盘没有挂载上去,将U盘挂载到/mnt/usb/下就可以了:

    >: mount -t vfat /dev/uba /mnt/usb/

     

    为什么U盘没有自动挂载上去呢?

    查看自动挂载的配置文件/etc/mdev.conf:

    >: vi mdev.conf

    sd[a-z][0-9] 0:0 0777 @(mount /dev/$MDEV /mnt/usb)
    sd[a-z] 0:0 0777 $(umount /mnt/usb)
    ub[a-z][0-9] 0:0 0777 @(mount /dev/$MDEV /mnt/usb)
    ub[a-z] 0:0 0777 $(umount /mnt/usb)
    mmcblk[0-9]p[0-9] 0:0 0777 @(mount /dev/$MDEV /mnt/sdc)
    mmcblk[0-9] 0:0 0777 $(umount /mnt/sdc)

    原来是第三行的ub[a-z][0-9]的原因,因为我的U盘的驱动挂载上去之后只有uba没有后面的数字,而配置文件里后面有0-9的数字,所以没办法匹配,也就没办法挂载,在这里添加一行:

    ub[a-z] 0:0 0777 @(mount /dev/$MDEV /mnt/usb)
    ub[a-z] 0:0 0777 $(umount /mnt/usb)

    这样就可以实现自动挂载了。

  • 相关阅读:
    解决:ElasticSearch ClusterBlockException[blocked by: [FORBIDDEN/12/index readonly / allow delete (api)];
    Centos 常用命令
    Nodejs的path模块
    webpack externals
    F#反射获取名称的三种方法
    JDK源码阅读之:JDK8的 CHM 为何放弃分段锁
    Mysql基础之:MySQL各种类型索引的及其优缺点介绍
    Java高并发之:从浅入深掌握并发执行框架Executor
    如何读懂火焰图?+ 实例讲解程序性能优化
    Java高并发之:深入浅出线程池+高级选项的使用
  • 原文地址:https://www.cnblogs.com/xiaohexiansheng/p/5492885.html
Copyright © 2020-2023  润新知