ARM仿真器-foxICE 设为首页   |   加入收藏夹   |   网站地图         
  站内搜索:
 
http://www.foxice.net
最新下载_foxICE
ARM7TDMI R3内核
ARM7EJS内核
ARM946E-S内核
ARM966E-S内核
ARM9TDMI内核
ARM940T内核
ARM指令集速查卡
ARM925T内核(TI925T)

更多 >> 

 技术专栏RSS订阅

   首页>技术专栏>U-boot>U-Boot在S3C2410上的移植

U-Boot在S3C2410上的移植

作者:东华理工学院      焦玉全    黄乡生    鲍玉军

点击下载
摘 要:在嵌入式系统的开发中,首先移植一个稳定且功能强大的 U-Boot 对后续软件的开发至关重要。本文将详细介绍 U-Boot S3C2410 开发板上的移植与运行。

关键词:嵌入式系统; U-Boot ;移植

引言
U-Boot 是用于初始化目标板硬件,为嵌入式操作系统提供目标板硬件配置信息,完成嵌入式操作系统装载、引导和运行的固件程序。它能够将系统的软硬件紧密衔接在一起。 S3C2410 是三星公司的一款基于ARM920T核的嵌入式通用处理器。本文将详细介绍 U-Boot S3C2410 开发板上的移植与运行。

U-Boot 简介
U-Boot 支持ARM 、 PowerPC等多种架构的处理器,也支持 Linux 、 NetBSD 和 VxWorks 等多种操作系统。它提供启动加载和下载两种工作模式。启动加载模式也称自主模式,一般是将存储在目标板Flash中的内核和文件系统的镜像装载到SDRAM中,整个过程无需用户的介入。在使用嵌入式产品时,一般工作在该模式下。工作在下载模式时,目标板往往受外设 ( 一般是 PC 机 ) 的控制,从而将外设中调试好的内核和文件系统下载到目标板中去。 U-Boot 允许用户在这两种工作模式间进行切换。通常目标板启动时,会延时等待一段时间,如果在设定的延时时间范围内,用户没有按键, U-Boot 就进入启动加载模式。
开发板的主要配置包括三星ARM9处理器 S3C2410 、 1 个串口和 JTAG 接口,晶振为12MHz ,系统主频为200MHz 。另外,开发板上还包括 1 片 4M ×16 位数据宽度的Flash,地址范围为 0x01000000 ~ 0x01800000 和 2 片 8M ×16 位数据宽度的 SDRAM ,地址范围为 0x30000000 ~ 0x32000000 。 Flash 使用了 2410 处理器的BANK0单元,由于2410中地址是循环映射的,因而 0x01000000 和 0x0 地址等同。
在本系统中, U-Boot 的主要功能包括:建立和初始化 RAM ;初始化一个串口;检测机器的体系结构,传递 MACH_TYPE_xxx 的值 (SMDK2410) 给内核;建立内核的标记列表 (tagged list) ;调用内核镜像。

U-Boot 移植步骤
为了使 U-Boot 支持新的开发板,一种简便的做法是在 U-Boot 已经支持的开发板中选择一种和目标板接近的,并在其基础上进行修改。代码修改的步骤如下:

  1. 在 board 目录下创建 smdk2410 目录,添加 smdk2410.c 、 flash.c 、 memsetup.s 、 u-boot.lds 和 config.mk 等;
  2. 在 cpu 目录下创建 arm920t 目录,主要包含 start.s 、 interrupts.c 、 cpu.c 、 serial.c 和 speed.c 等文件;
  3. 在 include/configs 目录下添加 smdk2410.h ,它定义了全局的宏定义等;
  4. 修改 u-boot 根目录下的 Makefile 文件:
    smdk2410_config : unconfig@./mkconfig $(@:_config=) arm arm920t smdk2410
  5. 运行 make smdk2410_config ,如果没有错误,就可以开始进行与硬件相关的代码移植工作。由于这部分代码与硬件紧密相关,所以要熟悉开发板的硬件配置,可参考各芯片的用户手册。

U-Boot 启动过程
U-Boot 的启动过程可以分成 3 个阶段。首先在 Flash 中运行汇编程序,将 Flash 中的启动代码部分复制到 SDRAM 中,同时创造环境准备运行 C 程序;然后在 SDRAM 中执行,对硬件进行初始化;最后设置内核参数的标记列表,复制镜像文件,进入内核的入口函数。

  1. 程序首先在 Flash 中运行 CPU 入口函数 /cpu/arm920t/start.s 。具体工作包括:设置异常的入口地址和异常处理函数;配置 PLLCON 寄存器,确定系统的主频;屏蔽看门狗和中断;初始化 I/O 寄存器;关闭 MMU 功能;调用 /board/smdk2410 中的 memsetup.s ,初始化存储器空间,设置刷新频率;将 U-Boot 的内容复制到 SDRAM 中;设置堆栈的大小, ldr pc, _start_armboot 。
    board/s 3c 2410 中 config.mk 文件 (TEXT_BASE = 0x 31F 00000) 用于设置程序编译连接的起始地址,在程序中要特别注意与地址相关指令的使用。
    当程序在 Flash 中运行时,执行程序跳转时必须要使用跳转指令,而不能使用绝对地址的跳转 ( 即直接对 PC 操作 ) 。如果使用绝对地址,那么,程序的取指是相对于当前 PC 位置向前或者向后的 32MB 空间内,而不会跳入 SDRAM 中。
  2. 程序跳转到 SDRAM 中执行 /lib_arm/board.c 中的 start_armboot() 函数。该函数将完成如下工作:
    * 设置通用端口 rGPxCON;rGPxUP ;设置处理器类型 gd->bd->bi_arch_number = 193 ;设置启动参数地址 gd->bd->bi_boot_params = 0x30000100 ;
    * env_init :设置环境变量,初始化环境;
    * init_baudrate :设置串口的波特率;
    * serial_init :设置串口的工作方式;
    * flash_init :设置 ID 号、每个分页的起始地址等信息,将信息送到相应的结构体中;
    * dram_init :设置 SDRAM 的起始地址和大小;
    * env_relocate :将环境变量的地址送到全局变量结构体中 (gd->env_addr = (ulong)&(env_ptr->data)) ;
    * enable_interrupts :开启中断;
    * main_loop :该函数主要用于设置延时等待,从而确定目标板是进入下载操作模式还是装载镜像文件启动内核。在设定的延时时间范围内,目标板将在串口等待输入命令,当目标板接到正确的命令后,系统进入下载模式。在延时时间到达后,如果没有接收到相关命令,系统将自动进入装载模式,执行 bootm 30008000 30800000 命令,程序进入 do_bootm_linux() 函数,调用内核启动函数;
  3. 装载模式下系统将执行 do_bootm_linux() 函数, 0x30008000 是内核在 SDRAM 中的起始地址; 0x30800000 是 ramdisk 在 SDRAM 中的起始地址; 0x40000 是内核在 Flash 中的位置, 0x100000 是数据块的大小; 0x140000 是 ramdisk 在 FLASH 中的位置, 0x440000 是数据块的大小。系统调用 memcpy() 函数将内核从 flash 和 ramdisk 复制到 SDRAM 中,具体如下:
    memcpy((void *)0x30008000, (void *)0x40000, 0x100000) ; // 复制数据块
    memcpy((void *)0x30800000, (void *)0x140000, 0x440000) ; // 复制数据块
    通常,将内核参数传递给 Linux 操作系统有两种方法:采用 struct param_struct 结构体或标记列表。本系统中采用了第二种方法。
    一个合法的标记列表开始于 ATAG_CORE ,结束于 ATAG_NONE 。 ATAG_CORE 可以为空,一个空的 ATAG_CORE 的 size 字段设为 “ 2” (0x00000002) 。 ATAG_NONE 的 size 字段必须设为 “ 0” 。标记列表可以有任意多的标记 (tag) 。在嵌入式 Linux 系统中,通常由 U-Boot 设置的启动参数有: ATAG_CORE 、 ATAG_MEM 、 ATAG_CMDLINE 、 ATAG_RAMDISK 、 ATAG_INITRD 等。
    在本系统中,传递参数时分别调用了以下 tag :
    setup_start_tag(bd) ; // 标记列表开始
    setup_memory_tags(bd); // 设置内存的起始位置和大小
    setup_commandline_tag(bd, commandline); /*Linux 内核在启动时可以命令行参数的形式来接收信息,利用这一点可以向内核提供那些内核不能检测的硬件参数信息,或者重载 (override) 内核检测到的信息,这里 char *commandline "initrd=0x30800000,0x440000 root=/dev/ram init=/linuxrc console=ttyS0" ; */
    setup_ramdisk_tag(bd); // 表示内核解压后 ramdisk 的大小
    setup_initrd_tag(bd, initrd_start, initrd_end); // 设置 ramdisk 的大小和物理起始地址
    setup_end_tag(bd); // 标记列表结束
    其中 bd_t *bd = gd->bd 是指向 bd_t 结构体的指针,在该结构体中存放了关于开发板配置的基本信息。标记列表应该放在内核解压和 initrd 的 bootp 程序都不会覆盖的内存区域,同时又不能和异常处理的入口地址相冲突。建议放在 RAM 起始的 16K 大小处 , 在本系统中即为 0x30000100 处。
    U-Boot 调用 Linux 内核的方法是直接跳转到内核的第一条指令处,也即直接跳转到 MEM_START + 0x8000 地址处。在跳转时,要满足下列条件:
    a) CPU 寄存器的设置: R0 = 0 ; R1 =机器类型 ID ,本系统的机器类型 ID = 193 。 R2 =启动参数标记列表在 RAM 中的起始基地址;
    b) CPU 模式:必须禁止中断 (IRQs 和 FIQs) ; CPU 必须工作在 SVC 模式;
    c) Cache 和 MMU 的设置: MMU 必须关闭;指令 Cache 可以打开也可以关闭;数据 Cache 必须关闭。
    系统采用下列代码来进入内核函数:
    theKernel = (void (*)(int, int))ntohl(hdr->ih_ep);
    theKernel(0, bd->bi_arch_number); 其中, hdr 是 image_header_t 类型的结构体, hdr->ih_ep 指向内核的第一条指令地址,即 Linux 操作系统下的 /kernel/arch/arm/boot/compressed/head.S 汇编程序。 theKernel() 函数调用应该不会返回,如果该调用返回,则说明出错。

结语
本文总结介绍了 U-Boot S3C2410 上的移植,移植完成后, U-Boot 能够稳定地运行在开发板上,为后续的软件开发打下较好的基础。

立即下载:
点击下载
相关文档
U-Boot在44B0X开发板上的移植以及代码分析
uboot移植到S3C44B0X开发板的经历
S3C44B0\U-Boot的启动流程及移植
U-boot移植日记(s3c44b0)
uboot在ARM s3c2410上移植过程
VxWorks 的bootrom 到u-boot 的移植心得
嵌入式系统中U-Boot基本特点及其移植方法
下载说明:
  1. 未经本站明确许可,任何网站不得非法盗链及抄袭本站资源!
 

首页 | 产品介绍 | 技术支持 | 下载中心 | 技术专栏 | 关于我们 | 联系我们
电话:86-755-82798083   82796301   传真:86-755-82799007    Email:sales@foxice.net   sales6@foxice.net
在线咨询:QQ:346466907   MSN:sales6@foxice.net   ini3000@msn.com

© 2006 Foxice.net 版权所有