微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 电源设计 > U-Boot从NAND Flash启动的实现

U-Boot从NAND Flash启动的实现

时间:08-05 来源:互联网 点击:

摘要:U-Boot不能从NAND Flash启动给应用带来些不便,因此修改U-Boot使其支持从NAND Flash启动。分析了U-Boot启动流程的两个阶段及实现从NAND Flash启动的原理和思路,并根据NAND Flash的物理结构和存储特点,增加U-Boot对NAND Flash的操作支持,从而完成把存储在NAND Flash上的U-Boot代码复制到SDRAM中执行,实现从NAND Flash的启动。修改过后的U-Boot可以直接从NAND Flash启动,给应用带来便利。
关键词:U-Boot;NAND Flash;Boofloader;S3C2440;移植

Bootloader引导装载程序是系统上电后运行的第一段程序,其作用是完成基本的硬件初始化工作,所以引导装载程序跟硬件有着紧密的联系。因此必须根据开发板的硬件配置对引导装载程序进行修改才可以使其运行起来。随着嵌入式系统的复杂化,大容量数据存储的NAND Flash的应用会越来越广泛,同时U-Boot是功能最丰富的Bootloader,但遗憾的是U-Boot不支持从NAND Flash启动。所以如果能实现U-Boot从NAND Flash启动的话将会给应用带来很大的方便。本文讨论修改U-Boot使其支持从NAND Flash启动.采用基于S3C2440的开发板。

1 U-Boot简介及流程分析
U-Boot,全称universal boot loader,是遵循GPL条款的开放源代码项目。可以引导多种操作系统,支持多种架构的CPU。它支持如下操作系统:Linux、NetBSD、VxWorks等,支持如下架构的CPU:PowerPC、MIPS、X86、ARM、NIOS、XSeale等,同时支持NFS挂载,是一个功能丰富的BootLoader。它的整个程序框架清晰,易于移植,许多设计人员将自己的移植代码上传到网站(http://sourceforge.net/project-s/u-boot/) 上,更新速度很快。目前的版本是1.1.6,本论文正是采用此版本进行说明,U-Boot的目录结构参见U-Boot源代码。

要进行U-Boot的修改移植必须了解U-Boot的程序运行流程,这是必要的一步。U-Boot属于两阶段的BootLoader,其启动流程如图l所示。第一阶段的文件为cpu/arm920t/start.S和board/smdk2410/lowlevel_init.S,用ARM汇编语言编写,前者是平台相关的,后者是开发板相关的。第一阶段主要是关于基本硬件的初始化,包括关闭MMU、CACHE、设置PLL时钟比例、关闭看门狗;初始化SDRAM,为复制第二阶段代码做准备,最后复制第二阶段代码到SDRAM中,然后跳到SDRAM中运行第二阶段。第二阶段代码都是用C语言编写的,功能更加复杂。主要是进一步初始化硬件设备、检测内存映射、复制内核镜像和根文件系统到SDRAM以及设置启动参数从而启动内核。

2 支持NAND启动的代码修改
2.1 添加NAND Hash的初始化函数
U-Boot中关于NAND Hash的初始化流程如下:在上电后最先运行的汇编程序cpu\arm920t\start.S中调用start_armboot函数,而star-t_armboot该函数则调用了一系列的关于设备的初始化函数。这一系列的函数中包含一个名为nand_init的函数,nand_init就是完成NAND Ha-sh的初始化工作。
在1.1.6版本的U-Boot的include\linux\mtd\nand.h中定义了nand_chip结构体,该结构体中定义了关于NAND Hash操作的所有函数,包括读、写、ECC校验等,而这些函数在U-Boot中都有完整编写,只是有些个别函数需要根据自己的要求重新编写。而实现NAND Flash初始化的nand_init函数主要任务就是完成这些需要重新编写的函数和用这些函数连同U-Boot中其他默认函数来初始化nand_chip结构体。NAND-_init中的board_nand_init函数在U-Boot中并未实现,显然需要重新编写的函数就在其内添加。
先在cpu\arm920t\s3c24x0中添加nand.c文件,然后在该文件中实现所需要的初始化函数。一般只需要重新编写nand_ehip结构体中相对应的hweontrol、dev_ready和select_chip函数。这些函数的构建可参照linux内核2.6版本里的drivers\mtd\nand\s3e2410.e文件来进行编写,如内核文件中的s3c2440_nand_hwcontrol,s3c2440_nand_devready,s3c2410nand_select_chip函数,然后将其赋值给nand_chip结构体中对应的函数。

2.2 实现NAND启动
由于NAND的自身特点,对NAND Flash的操作不能像对NOR Flash那样方便地直接对地址进行操作,而是通过读写NAND Flash控制器的寄存器来完成。三星公司的S3C2440自带NAND Flash控制器,寄存器的地址是从nGCS4的地址开始。S3C2440处理器有NOR和NAND两种启动模式,当选择从NAND模式启动时,S3C2440会把NAND Hash的前4K数据搬运到内部称为Steppingstone的硬件中,同时把Steppingstone映射到地址0X00处,从而启动,启动完成后处理器会把Steppingstone释放掉以作为他用。U-Boot的一般大小都上100 K,远大于4 K,所以实现从NAND启动的原理就是让前4K代码完成基本初始化,重要的是把NAND Flash中的U-Boot代码复制到SDRAM中,从而跳到SDRAM中去执行。分析可知,S3C2440的该特点为U-Boot从NAND Flash启动提供了可能。本文讨论的实现思路就是依据此原理。
源代码中有/board/smdk2410/U-boot/lds,该文件是U-Boot代码的链接脚本,有如下代码:

可以看到Text段也就是程序代码段,被编译链接到OX00地址处,同时start.S编译后的目标文件start.O被放到text段的第一个文件处,所以start.S就是程序上电运行的第一段代码,而/cpu/arm920t/start.S这个汇编文件正是U-Boot的程序代码入口。因此代码修改和添加主要在start.S中完成,以此来保证NAND启动代码可以在最终程序编译链接所生成的文件的前4K内。
NAND Flash读写操作比较复杂,汇编实现较为麻烦,没有C语言简单容易,因此用C语言实现对NAND的操作复制工作,最后在start.S中调用编写的C程序即可。
在/board/smdk2410/中添加boot_init.c文件,在其中实现nand_reset(nand重置函数)、wait_idle(等待即查询设备是否读写就位)、nand_select_chip(片选使能)、nand_dleselect_chip(取消片选)、write_cmd(写命令)、write_addr(写地址)、read_data(读数据)、nand_init(nand控制器初始化)这些子函数和copy2ram函数,同时在copy2ram中依据NAND Flash的读写操作特点来调用这些子函数。具体操作流程如图2所示。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top