开发板fl2440上Linux内核编译

版权声明:转载请附带原博主的网址 https://blog.csdn.net/qq_43260665/article/details/89646224

注意:该博客基于由crosstool-ng制作的交叉编译器编译出armLinux内核。交叉编译器的具体制作请参考我上两篇博客。

1.fl2440简介
FL2440开发板是飞凌公司使用三星的ARM9 S3C2440 CPU做的一个ARM Linux学习开发板,该CPU是使用armv4t指令集的ARM920T核,工作主频
最高在400MHz。每个CPU厂商在研发并生产出CPU时并不是直接将该CPU推给客户让客户自己研究该CPU特性后再做硬件设计(因为客户不懂这些具体
的CPU使用细节,而研发该CPU的公司会更懂它),而会先使用该CPU设计出母板(demo板,如SMDK2440),在母板上尽可能将该CPU的硬件使用信
息展示给客户,客户再参考母板根据实际的功能、市场需求来高度定制自己的硬件,例如产品不需要显示则可以把母板中的LCD硬件部分去掉、CS8900网
卡供货存在问题那就换成DM9000等等。
相应的CPU厂商在开发出相应的硬件demo板后,也不是直接丢给客户来开发相应的软件,而是会安排软件研发人员针对母板硬件完成u-boot和Linux内
核的开发,以支持相应硬件。因为我们的硬件是参考母板来定制开发的,所以我们的软件移植(u-boot和linux内核)也可以在相关源码里的母板代码上做
针对硬件的修改来支持我们的产品。
在FL2440开发板的移植过程中,我们将以SMDK2440为模版在它的基础上做些修改来支持我们相应的硬件。在开始移植之前,我们先创建FL2440整个
项目的目录框架:

zhanghang@ubuntu:~$ mkdir fl2440
zhanghang@ubuntu:~$ cd fl2440/
zhanghang@ubuntu:~/fl2440$ mkdir -p {crosstool,bootloader,linux/{kernel,rootfs},driver,3rdparty,program,images}
zhanghang@ubuntu:~/fl2440$ tree
.
├── 3rdparty
├── bootloader
├── crosstool
├── driver
├── images
├── linux
│   ├── kernel
│   └── rootfs
└── program

9 directories, 0 files

2.源码修改
Linux 是一个源码开放的操作系统,无论是普通用户还是企业用户都可以编写自己的内核代码,再加上对标准内核的裁剪从而制作出适合自己的操作系统。Linux操作系统有很多发行版本,如Redhat, CentOS, Ubuntu等等,但所有的这些Linux操作系统都是选择一个Linux内核稳定版本,外加不同的C基础库和应用程序构建的一个操作系统。嵌入式Linux系统开发其本质就是我们拿到源码并进行修改DIY(Do It Yourself)一个属于我们自己的操作系统,这个过程包括Booloader和Linux内核(裁剪)移植、驱动模块编写、根文件系统制作、第三方应用程序移植等,这个工作叫做BSP(Board Support Packet,板级支持包)开发,这里面需要相应的硬件协议、操作系统、以及C语言和数据结构等知识,难度较高。

zhanghang@ubuntu:~$ cd fl2440/linux/
zhanghang@ubuntu:~/fl2440/linux$ wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.0.tar.bz2  //下载内核
zhanghang@ubuntu:~/fl2440/linux$ tar -xjf linux-3.0.tar.bz2 //解压
zhanghang@ubuntu:~/fl2440/linux$ cd linux-3.0/
zhanghang@ubuntu:~/fl2440/linux/linux-3.0$ ls
arch     Documentation  init     lib          README          sound
block    drivers        ipc      MAINTAINERS  REPORTING-BUGS  tools
COPYING  firmware       Kbuild   Makefile     samples         usr
CREDITS  fs             Kconfig  mm           scripts         virt
crypto   include        kernel   net          security

修改1:
SMDK2440上使用的是16MHz的晶振,而FL2440上使用的是12MHz的晶振,所以开发板相应代码要做修改,linux-3.0/arch/arm/mach-s3c2440/下支持很多使用S3C2440 CPU做的开发板(大家可以使用ls命令看看具体有哪些开发板,今后驱动添加我们可以参考其他开发板如mini2440的信息),我们以mach-smdk2440.c为原型来进行修改:

zhanghang@ubuntu:~/fl2440/linux/linux-3.0$ vim arch/arm/mach-s3c2440/mach-smdk2440.c
160 static void __init smdk2440_map_io(void)
161 {
162         s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
163 //      s3c24xx_init_clocks(16934400);
164         s3c24xx_init_clocks(12000000);
165         s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
166 }
167 

修改2:
我们的u-boot给Linux内核传的machine ID值为1999,而Linux内核里smdk2440开发板对应的machine ID是362,所以我们要修改内核代码让smdk2440的machine ID与u-boot里的保持一致,这里我们在源码中将两个machine ID值互换:

enp2611                 ARCH_ENP2611            ENP2611                 356
s3c2440                 ARCH_S3C2440            S3C2440                 1999
gumstix                 ARCH_GUMSTIX            GUMSTIX                 373
...
exeda                   MACH_EXEDA              EXEDA                   1994
mini2440                MACH_MINI2440           MINI2440                362
colibri300              MACH_COLIBRI300         COLIBRI300              2000

修改3:
samsung的串口驱动设备名字默认叫ttySAC,而我们一般使用ttyS,所以将源码中的设备名改掉:

  55 /* UART name and device definitions */
  56 
  57 //#define S3C24XX_SERIAL_NAME   "ttySAC"
  58 #define S3C24XX_SERIAL_NAME   "ttyS"
  59 #define S3C24XX_SERIAL_MAJOR    204
  60 #define S3C24XX_SERIAL_MINOR    64

修改4:
修改顶层Makefile的ARCH为arm, CROSS_COMPILE为我们自己相应的交叉编译器:

zhanghang@ubuntu:~$ cd /opt/xtools/arm920t/bin/
zhanghang@ubuntu:/opt/xtools/arm920t/bin$ ls
arm-arm920t-linux-gnueabi-addr2line     arm-arm920t-linux-gnueabi-gprof
arm-arm920t-linux-gnueabi-ar            arm-arm920t-linux-gnueabi-ld
arm-arm920t-linux-gnueabi-as            arm-arm920t-linux-gnueabi-ldd
arm-arm920t-linux-gnueabi-c++           arm-arm920t-linux-gnueabi-nm
arm-arm920t-linux-gnueabi-cc            arm-arm920t-linux-gnueabi-objcopy
arm-arm920t-linux-gnueabi-c++filt       arm-arm920t-linux-gnueabi-objdump
arm-arm920t-linux-gnueabi-cpp           arm-arm920t-linux-gnueabi-populate
arm-arm920t-linux-gnueabi-ct-ng.config  arm-arm920t-linux-gnueabi-ranlib
arm-arm920t-linux-gnueabi-g++           arm-arm920t-linux-gnueabi-readelf
arm-arm920t-linux-gnueabi-gcc           arm-arm920t-linux-gnueabi-size
arm-arm920t-linux-gnueabi-gcc-4.6.0     arm-arm920t-linux-gnueabi-strings
arm-arm920t-linux-gnueabi-gcov          arm-arm920t-linux-gnueabi-strip
 195 #ARCH           ?= $(SUBARCH)
 196 #CROSS_COMPILE  ?= $(CONFIG_CROSS_COMPILE:"%"=%)
 197 ARCH ?= arm
 198 CROSS_COMPILE ?= /opt/xtools/arm920t/bin/arm-arm920t-linux-gnueabi-  //这里改成大家自己的交叉编译器,注意arm-arm920t-linux-gnueabi- 后面应该紧跟回车,不能有其他任何字符

下面是我的交叉编译器位置:

zhanghang@ubuntu:~$ cd /opt/xtools/arm920t/bin/
zhanghang@ubuntu:/opt/xtools/arm920t/bin$ ls
arm-arm920t-linux-gnueabi-addr2line     arm-arm920t-linux-gnueabi-gprof
arm-arm920t-linux-gnueabi-ar            arm-arm920t-linux-gnueabi-ld
arm-arm920t-linux-gnueabi-as            arm-arm920t-linux-gnueabi-ldd
arm-arm920t-linux-gnueabi-c++           arm-arm920t-linux-gnueabi-nm
arm-arm920t-linux-gnueabi-cc            arm-arm920t-linux-gnueabi-objcopy
arm-arm920t-linux-gnueabi-c++filt       arm-arm920t-linux-gnueabi-objdump
arm-arm920t-linux-gnueabi-cpp           arm-arm920t-linux-gnueabi-populate
arm-arm920t-linux-gnueabi-ct-ng.config  arm-arm920t-linux-gnueabi-ranlib
arm-arm920t-linux-gnueabi-g++           arm-arm920t-linux-gnueabi-readelf
arm-arm920t-linux-gnueabi-gcc           arm-arm920t-linux-gnueabi-size
arm-arm920t-linux-gnueabi-gcc-4.6.0     arm-arm920t-linux-gnueabi-strings
arm-arm920t-linux-gnueabi-gcov          arm-arm920t-linux-gnueabi-strip

修改5:
添加DM9000网卡的支持,没有网卡驱动,开发板只能通过串口进行连接,更不能上网,通过ssh或dropbear远程登陆。

zhanghang@ubuntu:~/fl2440/linux/linux-3.0$ vim arch/arm/mach-s3c2440/mach-smdk2440.c
#include <linux/dm9000.h>//add 
//并添加如下代码
#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,
              }
};

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,
        },
};
//在结构体static struct 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,//add
};

2.内核配置和编译

zhanghang@ubuntu:~/fl2440/linux/linux-3.0$ find -name *.c | wc -l
16198
zhanghang@ubuntu:~/fl2440/linux/linux-3.0$ find -name *.S | wc -l
1223

Linux-3.0内核有16198个C文件和1223个汇编文件,就这一份源码支持了不同体系结构CPU, 并且包含了绝大部分硬件的驱动源码。那么根据不同的硬件设计和功能需求,定制化编译生成一个具有特定用途的嵌入式Linux系统image将是一场灾难,好在Linux的源码编译系统有一个非常巧妙的铁三角关系,导致这个过程显得没那么复杂。这个铁三角分别是Kconfig、.config和Makefile文件,他们三者之间的关系简单来说就是去饭店点菜:Kconfig是菜单,.config就是你点的菜,Makefile是做法。
**Kconfig:**一个文本形式的文件,存在内核源码中的每一个文件夹下,内核配置命令make menuconfig读取相应的Konfig文件生成菜单界面;
**.config:**隐藏文件存放在内核源码顶层目录中,make menuconfig命令配置的结果,里面的每个选项用来指导Makefile哪些C文件需要编译,哪些不需要编译;
**Makefile:**一个文本形式的文件,存在内核源码中的每一个文件夹下,用来控制编译该目录下的源码编译;

扫描二维码关注公众号,回复: 6107438 查看本文章
zhanghang@ubuntu:~/fl2440/linux/linux-3.0$ make s3c2410_defconfig
zhanghang@ubuntu:~/fl2440/linux/linux-3.0$ export TERM=vt100
zhanghang@ubuntu:~/fl2440/linux/linux-3.0$ make menuconfig
我们是使用S3C2440做的SMDK2440开发板,所有其他的开发板都不应该选择 
System Type --->
	S3C2400 Machines ---> 里面全部不选 
	S3C2410 Machines ---> 里面全部不选 
	S3C2412 Machines ---> 里面全部不选 
	S3C2416 Machines ---> 里面全部不选 
	S3C2440 and S3C2442 Machines --->
		[*] SMDK2440
		[*] SMDK2440 with S3C2440 CPU module
		其它全部不选 
	S3C2443 Machines ---> 
		里面全部不选 
		... ...
我们的交叉编译器使用的是EABI接口,所以这里一定要修改配置,否则跑不起来。
 	Kernel Features --->
	[*] Use the ARM EABI to compile the kernel
	[*] Allow old ABI binaries to run with this kernel (EXPERIMENTAL) (NEW)
	为防止为串口驱动冲突:
	Device Drivers --->
		Character devices --->
			Serial drivers ---><> 8250/16550 and compatible serial support取消 
				<*> Samsung SoC serial support
				[ ] Samsung SoC serial debug
				[*] Support for console on Samsung SoC serial port
				<*> Samsung S3C2440/S3C2442/S3C2416 Serial port support

写个shell脚本完成这些相应命令

zhanghang@ubuntu:~/fl2440/linux/linux-3.0$ vim build.sh
#!/bin/bash
make
mkimage -A arm -O linux -T kernel -C none -a 30008000 -e 30008040 -n "Linux Kernel" -d arch/arm/boot/zImage linuxroms3c2440.bin
chmod a+x linuxrom-s3c2440.bin

Shell脚本解释说明:
make命令是编译Linux内核源码,编译完成后将生产arch/arm/boot/zImage内核启动文件。
zImage并不能被u-boot的bootm命令启动,而需要使用mkimage工具在其前面加上bootm命令启动内核所需要的64字节(0x40)头信息方可启动,处
理后的文件一般叫做uImage。
mkimage命令是由u-boot编译产生(u-boot-2010.09/tools/mkimage),在编译完成u-boot后我们需要将它以root权限拷贝到系统/bin路径下。
mkimage -A arm -O linux -T kernel -C none -a 30008000 -e 30008040 -n “Linux Kernel” -d arch/arm/boot/zImage linuxrom- s3c2440.bin
-A arm 指定ARCH为arm
-O linux 指定操作系统(OS)为Linux
-T kernel 指定类型(Type)为内核
-C none 指定压缩类型为未压缩,zImage里有自解压的代码;
-a 30008000 指定Image加载的地址, u-boot下使用tftp命令下载linux内核到内存的相应地址
-e 30008040 指定Linux内核的入口地址, uImage的地址在30008000,uImage是在zImage前面加了64字节(0x40)头,所以内核
zImage入口地址为30008040。
-n “Linux Kernel” 指定Image的名字
-d arch/arm/boot/zImage 指定zImage文件所在位置
linuxrom-s3c2440.bin 指定生成的uImage文件名
chmod a+x linuxrom-s3c2440.bin 将生成的uImage文件(linuxrom-s3c2440.bin)变成绿色显眼。

zhanghang@ubuntu:~/fl2440/linux/linux-3.0$ ./build.sh
...//编译过程可能出现错误,由于我是用全新的ubuntu14.04去做的,出现如下错误:
...
  IHEX2FW firmware/emi26/loader.fw
  IHEX2FW firmware/emi26/firmware.fw
  IHEX2FW firmware/emi26/bitstream.fw
  IHEX2FW firmware/emi62/loader.fw
  IHEX2FW firmware/emi62/bitstream.fw
  IHEX2FW firmware/emi62/spdif.fw
  IHEX2FW firmware/emi62/midi.fw
./build.sh: line 3: mkimage: command not found
chmod: cannot access ‘linuxrom-s3c2440.bin’: No such file or directory

解决办法:

zhanghang@ubuntu:~/fl2440/linux/linux-3.0$ sudo apt-get install u-boot-tools
...//最后编译结束,整个过程时常大约20分钟
  KSYM    .tmp_kallsyms2.S
  AS      .tmp_kallsyms2.o
  LD      vmlinux
  SYSMAP  System.map
  SYSMAP  .tmp_System.map
  OBJCOPY arch/arm/boot/Image
  Kernel: arch/arm/boot/Image is ready
  GZIP    arch/arm/boot/compressed/piggy.gzip
  AS      arch/arm/boot/compressed/piggy.gzip.o
  SHIPPED arch/arm/boot/compressed/lib1funcs.S
  AS      arch/arm/boot/compressed/lib1funcs.o
  LD      arch/arm/boot/compressed/vmlinux
  OBJCOPY arch/arm/boot/zImage
  Kernel: arch/arm/boot/zImage is ready
  Building modules, stage 2.
  MODPOST 360 modules
  LD [M]  kernel/configs.ko
Image Name:   Linux Kernel
Created:      Sun Apr 28 07:06:03 2019
Image Type:   ARM Linux Kernel Image (uncompressed)
Data Size:    2277412 Bytes = 2224.04 kB = 2.17 MB
Load Address: 30008000
Entry Point:  30008040//编译结束
zhanghang@ubuntu:~/fl2440/linux/linux-3.0$ ls
arch           firmware  lib                   net             tools
block          fs        linuxrom-s3c2440.bin  README          usr
build.sh       include   MAINTAINERS           REPORTING-BUGS  virt
COPYING        init      Makefile              samples         vmlinux
CREDITS        ipc       mm                    scripts         vmlinux.o
crypto         Kbuild    modules.builtin       security
Documentation  Kconfig   modules.order         sound
drivers        kernel    Module.symvers        System.map
zhanghang@ubuntu:~/fl2440/linux/linux-3.0$ du -h linuxrom-s3c2440.bin 
2.2M    linuxrom-s3c2440.bin

编译完成后将会生成linuxrom-s3c2440.bin(约2.2M),该文件即为u-boot里bootm命令能识别的uImage文件。
此时,该文件就可以移植到开发板上。但是由于没有根文件系统,启动会停止并提示没有根文件系统。
下一节我会讲根文件系统的制作。

猜你喜欢

转载自blog.csdn.net/qq_43260665/article/details/89646224