找回密码
 注册会员
更新自动建库工具PCB Footprint Expert 2024.04 Pro / Library Expert 破解版

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

[复制链接]
admin 发表于 2013-3-22 06:53:53 | 显示全部楼层 |阅读模式

本文包含原理图、PCB、源代码、封装库、中英文PDF等资源

您需要 登录 才可以下载或查看,没有账号?注册会员

×
关键字:ARM Linux

        进入后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 所示。
    201211070520157186964.jpg
    图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/ , 则先执行“make  ”_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 的分区结构图
    201211070520158436865.jpg
      其部分实现代码如下:
      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 到大多数开发板的关键部分。由于移植的复杂性, 不可能包括全部步骤, 但通过本文的阐述可以了解移植的基本流程和关键点, 为移植不同版本到其他硬件平台提供了参考, 也为应用程序的开发搭建了一个比较完整的嵌入式平台。
*滑块验证:
您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

QQ|手机版|MCU资讯论坛 ( 京ICP备18035221号-2 )|网站地图

GMT+8, 2024-12-23 20:15 , Processed in 0.070364 second(s), 10 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表