内核文件系统分区基于ARM和Linux的嵌入式平台的构建

基于ARM和Linux的嵌入式平台的构建

时间:2011年11月21日
进入后PC 时代以来, 伴随着设计和制造技术的发展, 集成电路从当初的晶体管集成发展到现在的IP 集成, 即SoC(System on Chip ) 设计技术。促使嵌入式系统渗透到了当今社会中的各个行 适配器电流电池组TI模拟新品介绍-BQ24721C图像科技接口凌华科技首发PoE接口高速图像采集卡GIE62+半导体粒子运算放大器ST扩大抗辐射航天用模拟芯片产品阵容振荡器线圈抽头调频信号发生器原理及制作云端数据中心应用程序英特尔未来规划 千万美元在台设研发中心寄存器设备缓冲区ISPl362在基于FPGA的红外成像系统中的应用三星京东方面板液晶面板显示产业陷入群架时代部件系统电池电动汽车产业化关键:动力电池和电动化部件中文芯片产品第一款真正意义的中文语音合成芯片

进入后PC 时代以来, 伴随着设计和制造技术的发展, 集成电路从当初的晶体管集成发展到现在的IP 集成, 即SoC(System on Chip ) 设计技术。促使嵌入式系统渗透到了当今社会中的各个行业, 并且发挥越来越重要的作用。嵌入式系统一般可定义为以应用为中心、以计算机技术为基础、软硬件可裁剪、适用于应用系统且对功能、成本、体积、功耗有严格要求的专用计算机系统,它的主要特点是嵌入、应用。

  随着各种嵌入式设备功能越来越强大, 在设备中使用嵌入式操作系统也成为必然。Linux 操作系统具有开放源代码、易于移植、资源丰富、免费等特点, 在嵌入式领域的地位越来越重要。嵌入式Linux 和PC 上的Linux是同一套内核代码, 只是裁剪的程度不一样, 所以, 很多在PC 上开发的软件, 经过交叉编译后可以直接在嵌入式设备上运行。本文主要涉及到Bootloader 移植和Linux-2.6.32.2 内核的移植、根文件系统移植、在S3C2440平台上构建完整的嵌入式开发平台三个方面。

  1 交叉开发环境的建立

  在进行嵌入式软件开发之前, 必须要在PC 上建立ARM 的交叉编译环境。交叉编译就是在PC 平台上生成可以在ARM 平台上运行的代码。其中主要包括ARM 的交叉编译器arm-elf-gcc 和交叉连接器arm-elf-ld 。本文采用的交叉编译器的版本是gcc -3.4.5 -glibc -2.3.6 。

  交叉编译流程如图1 所示。

图1 嵌入式系统交叉编译流程

  2 BootLoader 引导加载程序

  BootLoader 是一段在系统上电时开始执行的程序,用以初始化硬件设备, 准备好软件环境, 设置好启动参数, 最后引导操作系统, 与PC 上的BIOS 程序相似。当前开放源码的Linux 引导程序主要有x86 架构的LILO、GRUB, 对于ARM 架构的主要有Vivi 和U-Boot 。本文使用U-Boot 作为引导程序。U-Boot(Universal Boot Loader) ,即通用的BootLoader , 遵循GPL 条款开放源代码。U-Boot相对于Vivi 功能更加强大, 也更方便后续程序的调试。

  BootLoader 的启动一般分为两个阶段, 第一阶段的代码主要是用汇编语言编写, 主要的功能是完成硬件设备的初始化, 为加载第二阶段的代码准备RAM 空间, 设置好堆栈; 第二阶段主要用C 语言编写, 检测内存映射, 将内核映像和根文件系统从Nand Flash 读到RAM中, 为内核启动设置参数, 引导内核。

  U-Boot 的源代码可以从ftp://ftp.denx.de/pub/u-boot/进行下载, 本文使用的U-Boot 版本是U-Boot2009.08 。

  移植U-Boot 的关键步骤如下:

  (1) 首先, 将include/configs 目录下的smdk2410.h 复制并改名为mini2440.h , 根据U-Boot 的说明可以知道,如果要使用开发板board/<board_name > , 则先执行“make <board_nAME > ”_config 命令进行配置, 然后执行“make all ” , 生成可执行文件。所以, 修改U-Boot 顶层的Makefile 文件, 添加下面一行mini2440_config : unconfig@ $ (MKCONFIG) $ (@:_config = ) arm arm920t mini2440frank s3c24x0 。这里有几个重要的参数,arm 指CPU 的架构,arm920t 指CPU 的类型,s3c24x0 指CPU 的型号。这样就可以使用make mini2440_config 这条命令进行配置。

  (2)本文使用的U-Boot 是从Nand Flash 启动的, CPU可以直接访问Nand Flash 中前4 KB 代码, 利用这4 KB代码把U-Boot 中绝大部分代码拷贝到内存中[ 3]。其中下面的代码就是调用C 语言中的Nand Flash 的读写函数, 该函数主要把Nand Flash 中4 KB 以后的代码复制到RAM 中。在编写nand_read_ll 的函数时, 注意参考Nand Flash 的数据手册, 对大页和小页的Nand Flash , 其读写的命令和时序是不同的。

  @copy U-Boot to RAM

  ldr r0,=TEXT_BASE

  mov r1,#0x0

  mov r2,#0x60000

  bl nand_read_ll

  tst r0,#0x0

  beq ok_nand_read

  由于在后面加载Linux 内核和根文件系统时, 使用的是tftp 方式, 所以必须添加DM9000EP 网卡的驱动。在mini2440.h 文件中, 其主要的配置如下:

  #define CONFIG_DRIVER_DM9000 1

  #define CONFIG_NET_MULTI 1

  #define CONFIG_DM9000_NO_SROM 1

  #define CONFIG_DM9000_BASE 0x20000300

  #define DM9000_DATA (CONFIG_DM9000_BASE +4)

  其中,CONFIG_DM9000_BASE 宏是最重要的, 因为它定义的是网卡的地址, 不同的网卡有不同的地址,DM9000EP 访问的基址为0x20000000, 之所以再偏移0x300 是由它的特性决定的。

  (3) 要正确引导Linux 内核, 还需要配置下面几个重要的宏定义, 这几个宏定义不同, 意味着引导Linux 内核的方式也不同。

  #define CONFIG_BOOTARGS"noinitrd root=/dev/mtdblock3

  init=/linuxrc console=ttySAC0,115200 mem=64M"

  其中,root =/dev/mtdblock3 是由Linux 中的Nand Flash 分区所决定的, 意味着Nand Flash 的第4 个分区为根文件系统。

  #define CONFIG_BOOTCOMMAND"nand read 0x32000000 0x60000 0x560000;bootm 0x32000000"

  这个宏定义是将Nand Flash 中0x60000 -0x560000( 和kernel 分区一致) 的内容读到内存0x32000000 中, 然后用bootm 命令来执行。

  要正常地引导Linux 内核, 必须要具备如下几个条件:

  (1)CPU 寄存器

  R0=0 ;

  R1= 机器类型ID ; 对于ARM 结构的CPU, 其机器类

  型ID 在linux/arch/arm/tools/mach-types ;

  R2=启动参数标记列表在RAM 中起始基地址。

  (2)CPU 工作模式

  必须禁止中断(IRQs 和FIQs ) ;

  CPU 必须为SVC 模式。

  (3)Cach 和MMU 的设置

  MMU 必须关闭;

  指令Cach 可以打开也可以关闭;

  数据Cach 必须关闭。

  3 Linux2.6.32.2 内核的移植

  3.1 内核的获取

  Linux 内核的更新很快, 可以从http://www.kernel.org/pub/linux/kernel/ 得到最新的Linux 内核版本, 本文使用的Linux 内核版本是Linux -2.6.32.2, 交叉编译工具使用符合EABI 标准的arm-linux-gcc-4.3.2 。

  3.2 内核的移植

  可以在内核的根目录下, 运行make menuconfig 命令, 对内核进行适当的裁剪, 以适应硬件平台。

  对内核进行适当的裁剪, 以适应硬件平台。

  (1) 修改Makefile 文件

  欲设置Linux 的默认平台为ARM 平台, 需进入Linux-2.6.32 文件夹中, 修改此目录下的Makefile 文件。

  export KBUILD_BUILDHOST := $(SUBARCH)

  ARCH ?=arm // 使用的目标平台

  CROSS_COMPILE ?=arm-linux- // 使用的交叉编译器,

  这里使用系统默认的编译器

  (2) 关于机器码

  在启动内核时, 根据BootLoader 传入的机器码(MACH_TYPE) 来决定应启动哪种目标平台[ 6], 本开发平台的机器码为1999 。机器码存放在文件opt/kernel/linux-2.6.32.2/arch/arm/tools/mach-types 中。

  mini2440 MACH_MINI2440 MINI2440 1999 // 机器码

  如果机器码不匹配, 引导内核不成功, 则会出现如下的错误提示:

  Uncompressing

  Linux……………………………………………………………………………done, booting the kernel.

(3) 修改时钟源

  将/kernel/linux -2.6.32.2/arch/arm/mach -s3c2440/ 目录下的mach-smdk2440.c 文件改名为mach-mini2440.c。

  因为mini2440 和mach-smdk2440.c 极其相似, 以该文件为基础进行修改, 在mach -mini2440.c 文件中将staticvoid__init smdk2440_map_io ( void ) 函数中的晶振频率修改为mini2440 开发板上实际使用的12000000。

  (4) 为内核打上yaffs2 补丁

  ①Yaffs2 文件系统是专门针对嵌入式设备, 特别是使用Nand Flash 作为存储器的嵌入式设备而创建的一种文件系统, 使用yaffs2 就可以支持大页的Nand Flash。

  进入yaffs2 源代码目录执行如下命令:

  #./patch -ker.sh c /opt/FriendlyARM/mini2440/linux -2.6.32.2

  ②配置内核以支持Yaffs2 文件系统

  在Linux 内核源代码根目录运行make xconfig, 在“File systems ” 选项中, 找到“Miscellaneous filesystems ” 菜单项, 找到“YAFFS2 file system support ” 并选中它, 这样就在内核中添加了yaffs2 文件系统的支持, 保存并退出。然后在命令行中, 执行make zImage 。

  (5) 修改Nand Flash 分区信息

  ①在mach-mini2440.c 文件中添加Nand Flash 的分区信息, 下面的代码将Nand Flash 分成了4 个分区, 第1 分区也是BootLoader 所在的分区, 对应dev/mtdblock0 ;第2 个分区是U-Boot 的参数分区, 对应dev/mtdblock1 ;第3 个分区是内核分区, 对应dev/mtdblock2 ; 第4 个分区为根文件系统分区对应dev/mtdblock3 。分区结构图如表1 所示。

表1 128 MB Nand Flash 的分区结构图

  其部分实现代码如下:

  static struct mtd_partition mini2440_default_nand_part[] ={

  [0] = {

  .name="U-boot",

  .offset= 0,

  .size= 0x00040000,

  }

  其中name 是分区的名字,offset 是偏移的开始地址,size是分区的大小, 其余部分的分区与此类似。

  ②下面代码是添加Nand Flash 的设置表, 因为板子上只有一片Nand Flash, 因此也就只有一个设置表。

  static struct s3c2410_nand_set mini2440_nand_sets[] = {

  [0] = {

  .name= "NAND",

  .nr_chips= 1,

  .nr_partitions=

  ARRAY_SIZE(mini2440_default_nand_part),

  .partitions= mini2440_default_nand_part,

  }

  }

  ③上面的设置完成后, 还需要将Nand Flash 设备注册到系统中。下面这段代码就是将Nand Flash 设备添加到开发板的设备列表结构。

  static struct platform_device *mini2440_devices [] __initdata

  = {

  &s3c_device_nand,

  }

  ④在mini2440_machine_init 函数中添加平台的数据信息。

  static void __init mini2440_machine_init(void){

  s3c_device_nand.dev.platform_data=&mini2440_nand_info;

  }

  现在可以进入kernel/linux-2.6.32.2/arch/arm/boot 目录,然后执行下面的命令, 就会在该目录下生成uImage.img格式的、U-Boot 可以引导的内核镜象。

  Mkimage – n ‘linux-2.6.32.2 ’ –A arm – O linux–T kernel –C none – a 0x30008000 – e 0x30008000 –d zImage uImage.img

  至此, 可以把生成的uImage.img 格式的镜像文件复制到tftp 目录下, 使用tftp 进行下载。

  3.3 文件系统

  所谓根文件系统, 就是创建各个目录, 例如在/bin 、/sbin/ 目录下存放各种可执行的程序, 在/etc 目录下存放配置文件, 在/lib 目录下存放库文件。

  可以利用Busybox 工具创建根文件系统,Bosybox 是一个遵循GPL v2 协议的开源项目, 它在编写过程中对文件大小进行优化, 并考虑了系统资源有限( 例如内存)的情况, 使用Busybox 可以自动生成根文件系统所需的bin、sbin、usr 目录和linuxrc 文件, 可以使用make menuconfig对Busybox 的选项进行配置。

  (1) 进入opt/kernel, 创建一个shell 脚本用于构建根文件系统的各个目录, 并且为其增加执行权限;(2)Linux 中的init 进程会根据etc/inittab 文件创建其他子进程, 下面代码是inittab 文件中的内容, 说明了系统启动后首先执行的脚本文件是rcS, 虚拟的终端是串口0, 当按下ctr+alt+del 时重启系统,inittab 文件的作用就是控制系统启动时和启动后一些程序的运行。

  #etc/inittab

  ::sysinit:/etc/init.d/rcS

  s3c2410_serial0::askfirst:-/bin/sh

  ::ctrlaltdel:/sbin/reboot

  ::shutdown:/bin/umount -a-r

  (3) 创建etc/init.d/rcS 文件, 这是一个脚本文件, 可以在里面添加要自动执行的一些命令。

  #! /bin/sh

  PATH=/sbin:/bin:/usr/sbin:/usr/bin

  runlevel=S // 运行的级别

  prevlevel=N

  umask 022 // 文件夹的掩码

  mount -a // 挂载/etc/fstab/ 文件指定的所有的文件系统

  mdev-s

  /bin/hostname -F /etc/sysconfig/HOSTNAME// 主机的名字

  使用yaffs 源码提供的工具制作文件系统的映像文件。由于128 MB 的Nand Flash 是大页结构, 所以需要使用相应的大页制作工具; 使用命令mkyaffs2image rootfsrootfs.img 生成根文件系统映像文件。

  本文通过对U-Boot 移植和Linux 内核移植的讨论,给出了移植U-Boot 和Linux 到大多数开发板的关键部分。由于移植的复杂性, 不可能包括全部步骤, 但通过本文的阐述可以了解移植的基本流程和关键点, 为移植不同版本到其他硬件平台提供了参考, 也为应用程序的开发搭建了一个比较完整的嵌入式平台。

重金属三星企业IBM等IT商被指供应链存重金属污染融资节能市场“十二五”展望 2011环保产业透镜耐热模块Heptagon用300mm晶圆生产高耐热透镜日韩面板商被曝每月开会商量定价驱动器性能电压ADI公司推出业界最低失真ADC差分驱动器目录最新客户Mouser全新移动版目录 将最新产品与技术信息带著走耗电量配备单元2GHz工作频率下耗电量最大25W,美国P.A. Semi发布双核电源芯片模块干扰器件Vishay推出新型3-V IR接收器模块公司美元华尔街AMD预计Q1营收达12.3亿美元 将进行业务重组
Hitachi 日立 Sanyo 三洋 TCM-3000 Series Universal Instruments 环球 HSP-4796A HSP-4796B SUPPORT 6300663198Panasonic KME 松下 CM212-M(NM-EJM6A) Modular Placement Machine 高速模块化贴装机 CM402(KXF-4Z4C) CM602(NM-EJM8A NM-EJM4A)Modular High Speed Placement Machine 模块化超高速贴片机 KXF02T3AA00 JOINT M-5AU-4FUJI 富士 NXT SMT贴片机配件 Scalable Placement Platform BEARING SLIDE H4274KHitachi 日立 Sanyo 三洋 TCM-X100 4240059309 FUSE 600V 12A F201.F203 765RF-010-065FUJI 富士 IP3 IP-III IP-IIIE IP-III-4000 IP-III-5000 K1053A FIXTURE HPU2-MAOS(Movable)SIEMENS SIPLACE 西门子 00318687-02 COMP.MAGAZINE LONG B6. 5/H3. 7/LE7. 5FUJI 富士 NXT SMT贴片机配件 Scalable Placement Platform SPACER S3231AFUJI 富士 IP3 IP-III IP-IIIE IP-III-4000 IP-III-5000 H4157T BEARING 17TAC47B-DBC8PN7AYAMAHA 雅马哈 YV88 YV88X YV88XG KV7-9907 KGA-0110 99009-17800 CIRCLIPPanasonic KME 松下 Next Production Modular NPM N610102223AA 12 nozzle head THE axis control board 12 nozzle head THE axis control boardAssembleon安必昂Philips飞利浦SECURITY KEYSWITCH 532227711843松下BM系列SMT贴片机12mm电动feeder、电动供料器、电动飞达 Panasert BM Motorized Feeder BM221 BM232 BM123 FAE1200MA300 12mmSIEMENS SIPLACE 西门子 00354980S01 Simovert Masterdrive Feed AxisHitachi 日立 Sanyo 三洋 TCM-3000 Series Universal Instruments 环球 HSP-4796A HSP-4796B BOLT HEX-SCT(SHOULDER) 6300490220SIEMENS SIPLACE 西门子 00332512-02 PROXIMITY SWITCH: WIDTH ADJUSTMENT TRA.1
1.6445519924164 s