Microsoft Word - mini2440之U-boot移植详细手册

Save this PDF as:
 WORD  PNG  TXT  JPG

Size: px
Start display at page:

Download "Microsoft Word - mini2440之U-boot移植详细手册"

Transcription

1 Mini2440 之 U-boot 使用及移植详细手册 简介有很多网友基于 mini2440 移植了 U-boot, 不过大都是功能比较简单, 我们发现网友 Tekkaman 移植的 U-boot 集成了很多其他版本 U-boot 的优点, 比如支持 SD 卡 优盘 开机 Logo USB 下载等, 这使得 U-boot 更加方便易用且实用, 这和我们公司对产品设计的追求理念是一致的 遂与其取得联系, 并于 2009 年底并提供了各个版本的 mini2440 样品以供测试, 因此你现在可以在 Tekkaman 的代码仓库中下载到支持当前所有 Nand Flash 容量版本 (64M/128M/256M/1GB) 的 U-boot 源代码, 它完全适用于 mini2440/micro2440 对于大部分初学者而言, 仅仅会下载和编译使用别人移植好的软件或许还是不够的, 因此我们根据网友 Tekkaman 的博客文章为材料, 并做了适当的整理和补充, 得以形成此手册, 以便其他人学习参考, 在此我们十分感谢 Tekkaman 对此付出的努力和贡献 也许有不少网友已经浏览过他的博客, 上面已经有一部分移植的说明文档, 但此手册介绍的内容将会更加系统和细致, 因此十分适合打算采用 U-boot 的初学者 其实我们公司也提供了其他开源的 bootloader, 比如 vboot 和 nboot, 它们都十分短小精悍, 分别适用于 Linux 和 WinCE 系统, 我们认为这对于研究 bootloader 原理和实际的项目应用更加合适 基于习惯 (Linux 爱好者和 Windows 用户向来是有水火不相容的斗争意识 ) 考虑,vboot 是基于 ARM Gcc 开发制作的,nboot 是基于 ADS 开发制作的 本手册目前主要由友善之臂整理 审阅和发布, 我们希望本手册遵循开源软件之自由和共享的核心精神, 但为了避免争议, 友善之臂保留本手册的一切解释权, 本公司及作者并不提供关于该手册的任何技术支持 如果你对本手册的内容有任何疑问, 可以到 arm9 之家论坛反馈和交流讨论, 我们将会在以后尽量更正, 更新后的手册也将在该论坛发布 另外, 本手册是以首页的日期为版本标志的 广州友善之臂计算机科技有限公司网址 : ARM9 之家论坛网址 :

2 第 1 章 BOOTLOADER 的概念与功能 嵌入式 LINUX 软件结构与分布 在嵌入式 LINUX 中 BOOTLOADER 的必要性 BOOT LOADER 的功能和选择... 5 第 2 章 U BOOT 简介 U BOOT 的起源 U BOOT 的开发情况和资源... 6 第 3 章开发环境搭建 交叉编译工具链的安装 网路服务的设置 安装配置 TFTP 服务 安装配置 NFS 服务 串口终端程序的安装配置 C kermit 的安装配置 ( 推荐安装 ) minicom 的安装配置 第 4 章熟悉 U BOOT 的使用与烧写 烧写 U BOOT 到 MINI2440 开发板 常用 U BOOT 命令详解 获取帮助 环境变量与相关指令 串口传输命令 网络命令 Nand Flash 操作指令 内存 / 寄存器操作指令 Nor Flash 指令 USB 操作指令 SD 卡 (MMC) 指令 FAT 文件系统指令 系统引导指令 其他指令 下载与烧写 通过 SD 卡烧入 Nand Flash: 通过 U 盘烧入 Nor Flash: 通过 TFTP 服务烧入 Nand Flash: 通过 NFS 服务烧入 Nand Flash: 内核引导 通过 SD 卡引导内核 : 通过 TFTP 服务引导内核 通过 NFS 服务引导内核 : 通过 Nand Flash 引导内核 : 第 5 章 U BOOT 源码简要分析 U-BOOT 源码整体框架 U BOOT 代码的大致执行流程 ( 以 S3C24X0 为例 ) 第 6 章 U BOOT 在 MINI2440 上的移植 建立开发板文件, 测试编译环境 修改顶层 Makefile... 53

3 6.1.2 在 /board 中建立 mini2440 目录和文件 在 include/configs/ 中建立开发板配置文件 测试编译环境 第一阶段 : 探索启动代码 关闭为 AT9200 写的 LED 跳转 修改 CPU 频率初始化设置 修改 lowlevel_init.s 文件 修改代码重定向部分 增加 LED 的点亮操作 第二阶段 : 修改初始化代码 修改 lib_arm/board.c 文件 修改 board/tekkamanninja/mini2440/mini2440.c 文件 第三阶段 : 完善目标板外设驱动 Nand Flash 相关代码的修改 添加 Yaffs(2) 镜像烧写功能 修改 Nor Flash 写入功能的代码 修改网络相关代码 添加串口 Xmodem 传输协议 ( 可不修改 ) 添加 LCD 显示功能 添加 SD 卡 (MMC) 读取功能 第四阶段 : 修正配置文件 添加 CONFIG_S3C2440 条件定义 修改配置文件 include/configs/mini2440.h 重新编译并测试 第 7 章下载最新的源代码

4 第 1 章 BootLoader 的概念与功能 1.1 嵌入式 Linux 软件结构与分布 一般情况下嵌入式 Linux 系统中的软件主要分为以下几部分 : 1) 引导加载程序 : 其中包括内部 ROM 中的固化启动代码和 BootLoader 两部分 内部固化 ROM 是厂家在芯片生产时候固化的, 作用基本上是引导 BootLoader 有的芯片比较复杂, 比如 Omap3 在 flash 中没有代码的时候有许多启动方式 : USB UART 或以太网等等 而 S3C24x0 则很简单, 只有 Norboot 和 Nandboot 2) Linux kernel 和 drivers 3) 文件系统 包括根文件系统和建立于 Flash 内存设备之上的文件系统 (EXT4 UBI CRAMFS 等等 ) 它是提供管理系统的各种配置文件以及系统执行用户应用程序的良好运行环境及载体 4) 应用程序 用户自定义的应用程序, 存放于文件系统之中 在 Flash 存储器中, 他们的分布一般如下 : BootLoader BootLoader 参数区 Linux Kernel 根文件系统 其他文件系统 ( 被挂载到根文件系统或者作为 但是以上只是大部分情况下的分布, 也有一些可能根文件系统是 initramfs, 被一起压缩到了内核映像里, 或者没有 Bootloader 参数区, 等等 1.2 在嵌入式 Linux 中 BootLoader 的必要性 Linux 内核的启动除了内核映像必须在主存的适当位置,CPU 还必须具备一定的条件 : R0=0; R1=Machine ID( 即 Machine Type Number, 定义在 1. CPU 寄存器的设置 : linux/arch/arm/tools/mach-types); R2= 内核启动参数在 RAM 中起始基地址 ; 必须禁止中断 (IRQs 和 FIQs); 2. CPU 模式 : CPU 必须 SVC 模式 ; MMU 必须关闭 ; 3. Cache 和 MMU 的设置 : 指令 Cache 可以打开也可以关闭 ; 数据 Cache 必须关闭 ; 但是在 CPU 刚上电启动的时候, 一般连内存控制器都没有初始化过, 根本无法在主存中

5 运行程序, 更不可能处在 Linux 内核启动环境中 为了初始化 CPU 及其他外设, 使得 Linux 内核可以在系统主存中运行, 并让系统符合 Linux 内核启动的必备条件, 必须要有一个先于内核运行的程序, 他就是所谓的引导加载程序 (Boot Loader) 而 BootLoader 并不是 Linux 才需要, 而是几乎所有运行操作系统的设备都需要 我们的 PC 的 BOIS 就是 Boot Loader 的一部分 ( 只是前期引导, 后面一般还有外存中的各种 Boot Loader), 对于 Linux PC 来说,Boot Loader = BIOS GRUB/LILO 1.3 Boot Loader 的功能和选择 综上所述 :BootLoader 是在操作系统内核启动之前运行的一段小程序 通过这段程序, 我们可以初始化硬件设备, 从而将系统的软硬件环境带到一个合适的状态, 以便为最终调用操作系统内核准备好正确的环境, 最后从别处 (Flash 以太网 UART) 载入内核映像到主存并跳到入口地址 由于 BootLoader 需要直接操作硬件, 所以它严重依赖于硬件, 而且依据所引导的操作系统的不同, 也有不同的选择 对于嵌入式世界中更是如此 就 S3C24x0 而言, 如果是引导 Linux, 一般选用韩国的 mizi 公司设计的 vivi 或者 DENX 软件工程中心的 Das U-boot, 如果是引导 Win CE, 就选用 Eboot 如果是开发 StrongARM 构架下的 LART, 就可选用由 Jan- Derk Bakker 和 Erik Mouw 发布的 Blob(Boot Loader Object) 如果是要引导 ecos 系统, 可以选用同是 Redhat 公司开发的 Redboot 所以在嵌入式世界中建立一个通用的 BootLoader 几乎是不可能的, 而可能的是让一个 Boot Loader 代码支持多种不同的构架和操作系统, 并让她有很好的可移植性 U-boot 就是支持多平台多操作系统的一个杰出代表 这也是 U-boot 的优势所在, 因为如果在开发 S3C2440 时熟悉了 U-boot, 再转到别的平台的时候, 就可以很快地完成这个平台下 U-boot 的移植 而且 U-boot 的代码结构越来越合理, 对于新功能的添加也十分容易 * 推荐阅读 : 嵌入式系统 Boot Loader 技术内幕

6 第 2 章 U-boot 简介 2.1 U boot 的起源 U-Boot 是 Das U-Boot 的简称, 其含义是 Universal Boot Loader, 是遵循 GPL 条款的开放源码项目 最早德国 DENX 软件工程中心的 Wolfgang Denk 基于 8xxROM 和 FADSROM 的源码创建了 PPCBoot 工程项目, 此后不断添加处理器的支持 而后,Sysgo Gmbh 把 PPCBoot 移植到 ARM 平台上, 创建了 ARMBoot 工程项目 最终, 以 PPCBoot 工程和 ARMBoot 工程为基础, 创建了 U-Boot 工程,2002 年 12 月 17 日第一个版本 U-Boot 发布, 同时 PPCBoot 和 ARMBoot 停止维护 而今,U-Boot 作为一个主流 通用的 BootLoader, 成功地被移植到包括 PowerPC ARM X86 MIPS NIOS XScale 等主流体系结构上的百种开发板, 成为功能最多 灵活性最强, 并且开发最积极的开源 BootLoader 目前 U-Boot 仍然由 DENX 的 Wolfgang Denk 维护 2.2 U boot 的开发情况和资源 最早 U-boot 的版本号是由 X.Y.Z 来表示的, 从 一直发展到 之后便开始使用年份加月份的表示方法, 从 到现在的 平均每 3 个多月出一个新版本 每次代码的结构和定义都会有一些修正和改进, 其代码越来越规整, 功能越来越强, 但是移植的难度反而越来越小, 需要修改的地方越来越少 U-boot 不仅有主线版本, 在 U-boot 的 Git 代码仓库中还有各个 CPU 构架的分支版本, 这些分支会在一定的时候将修改汇入主线 下面总结一下关于 U-boot 源代码的网络资源 : 官方链接 德国 DENX 软件工程中心主页 U-boot 官方主页 ( 注意其中的邮件列表链接 ) U-boot 官方源码 FTP 下载 U-boot 官方 Git 代码仓库 针对 S3C2440 的修改 Openmoko 手机的 U-boot 源码 Git ftp://ftp.denx.de/pub/u-boot/

7 buserror 的 U-boot 源码 Git ( 针对 mini2440) Tekkaman Ninja 的 U-boot 源码 Git ( 针对 mini2440)

8 第 3 章开发环境搭建 3.1 交叉编译工具链的安装 编译 U-boot 给 mini2440 的时候, 必须使用交叉编译工具链 你可以使用友善之臂提供的交叉编译工具 (gcc 版本 4.3.2), 也可以使用 crosstool-0.43 或 crosstool-ng 自己编译一个 至于如何用工具自己编译交叉编译工具链, 请看 Tekkaman Ninja 的博客的相关文章 : 用 crosstool0.43 建立 ARM-Linux 交叉编译环境 用 crosstool-ng 建立 Linux 交叉编译环境 ( 以 S3C2440(armv4t) 为例 ) 在编译好交叉编译工具链后, 要在环境变量的 PATH 中添加编译工具的路径 ( 也就是 arm-*-linux-*-gcc 所在的路径 ), 这样在编译时系统才找得到编译器的命令 在 Ubuntu 下的修改方法如下 : vi ~/.profile, 在最后加上 :PATH="< 交叉编译工具的路径 >:$PATH" 3.2 网路服务的设置 在使用 U-boot 的时候常常会用到宿主机的 TFTP 和 NFS 这两种网络服务, 所以最好在开发前设置好 下面以 Ubuntu 下使用 apt-get 安装为例, 简单介绍一下安装配置过程 : 安装配置 TFTP 服务 安装配置 TFTP 服务的大致步骤如下 : (1) 安装 tftp-hpa tftpd-hpa 和 openbsd-inetd 程序 ; (2) 修改配置文件 /etc/inetd.conf; (3) 根据配置文件的路径, 建立 tftp 目录, 并修改目录权限 ; (4) 重启 tftp 服务 ; (5) 本地传输测试 以下是一个安装和配置主要步骤的脚本, 大家参考 : #!/bin/sh TFTPDIR=< 你想要的 tftp 目录路径 > echo install tftp server... sudo apt-get install tftp-hpa tftpd-hpa

9 if [ "$?" = "0" ] then echo "install tftp-hpa and tftpd-hpa OK!!" else echo "install tftp-hpa and tftpd-hpa error!!!" # exit 1 fi sudo apt-get install openbsd-inetd if [ "$?" = "0" ] then echo "install openbsd-inetd OK!!" else echo "install openbsd-inetd error!!!" # exit 1 fi echo modify /etc/inetd.conf #tftp dgram udp wait root /usr/sbin/in.tftpd /usr/sbin/in.tftpd -c -s < 你想要的 tftp 目录路径 > sudo vi /etc/inetd.conf # 建立 tftp 目录, 并修改目录权限 : mkdir -p $TFTPDIR if [ "$?" = "0" ] then echo "make tftp dir $TFTPDIR OK!!" else echo "make tftp dir $TFTPDIR error!!!" # exit 1 fi sudo chmod 777 $TFTPDIR # 重启 tftp server sudo /etc/init.d/openbsd-inetd restart 安装配置 NFS 服务 安装配置 NFS 服务的大致步骤如下 : (1) 安装 NFS 内核服务 ; (2) 重新配置 portmap 服务, 修改 /etc/hosts.deny 和 /etc/hosts.allow 配置文件, 重启 portmap 服务 ; (3) 修改 NFS 服务的配置文件 /etc/exports, 添加服务目录和配置, 重新导入配置 ; (4) 重启 NFS 服务, 并检查可挂载的目录 ; (5) 在本地挂载测试 以下是一个安装和配置主要步骤的脚本, 大家参考 : #!/bin/sh echo install tftp server... sudo apt-get install nfs-kernel-server if [ "$?" = "0" ]

10 then echo "install nfs-kernel-server OK!!" else echo "install nfs-kernel-server error!!!" # exit 1 fi sudo dpkg-reconfigure portmap # 对 Should portmap be bound to the loopback address? 选 N. sudo vi /etc/hosts.deny #portmap:all #lockd:all #mountd:all #rquotad:all #statd:all sudo vi /etc/hosts.allow #portmap: #lockd: #rquotad: #mountd: #statd: sudo service portmap restart sudo vi /etc/exports #/home/tekkaman/development/share /24(rw,nohide,insecure,no_wdelay,no_root_squash,no_subtree_check,sync) # 特别要注意上面的 IP 的形式, 以前是形如 *, 现在是 IP/ 掩码为数的形式 用旧的格式可能会出问题 # 具体的说明, 建议看 man 手册 : man exports sudo exportfs -r sudo /etc/init.d/nfs-kernel-server restart showmount -e 串口终端程序的安装配置 在使用 U-boot 的时候, 必然会用到串口与开发板进行通信, 所以串口终端程序必不可少 下面简单介绍一下 Linux 下常用的串口终端 :minicom 和 C-kermit 的安装配置 ( 以 Ubuntu 下使用 apt-get 安装为例 ) C-kermit 的安装配置 ( 推荐安装 ) 在 Linux 下是通过串口传输文件到开发板, 就属 C-kermit 比较好用 (1) 安装 ckermit 程序 ; (2) 编写 ckermit 的配置文件 ~/.kermrc 下面是一个很简单的安装和配置脚本, 供大家参考 : #!/bin/sh

11 echo install C-kermit... sudo apt-get install ckermit if [ "$?" = "0" ] then echo "install ckermit OK!!" else echo "install ckermit error!!!" # exit 1 fi # 如果是 USB 转串口, 就是类似 /dev/ttyusb0 的设备, 如果是原生的硬件串口, 就是类似 /dev/ttys0 的设备节点 # 根据你使用的串口, 设备节点编号可能有变, 你可以 ls /dev/tty* 看看你用的到底有什么设备节点 cat >~/.kermrc <<EOF set line /dev/ttyusb0 set speed set carrier-watch off set handshake none set flow-control none robust set file type bin set file name u-boot.bin set rec pack 1000 set send pack 1000 set window 5 c EOF minicom 的安装配置 minicom 是在 Linux 系统下比较常用的串口终端工具, 简单的安装配置步骤如下 : (1) 安装 minicom 程序 ; (2) 使用 minicom -s 命令生成配置文件 ~/.minirc.dfl #!/bin/sh echo install Minicom... sudo apt-get install minicom if [ "$?" = "0" ] then echo "install minicom OK!!" else echo "install minicom error!!!" # exit 1 fi minicom -s 运行命令 minicom -s 后, 屏幕出现如下界面 : ----[ 配置 ]---- 文件名和路径 文件传输协议

12 串口设置 调制解调器和拨号 屏幕和键盘 设置保存为 dfl 设置保存为.. 退出 退出 Minicom 使用方向键选择 串口设置, 出现具体的配置 : A - 串口设备 : /dev/ttyusb0 B - 锁文件的位置 : /var/lock C - 调入程序 : D - 调出程序 : E - Bps/Par/Bits : N1 F - 硬件数据流控制 : 否 G - 软件数据流控制 : 否 希望修改哪个设置? 使用相应的字母键配置, 比如修改设备节点则输入 A, 光标转移到 串口设备 选项后, 可 以对其值进行修改, 完成后回车确定 如果选择了 E 则出现 : [ 普通参数 ] 当前 : N1 速度 参数 数据 A: <next> L: None S: 5 B: <prev> M: Even T: 6 C: 9600 N: Odd U: 7 D: O: Mark V: 8 E: P: Space 停止位 W: 1 Q: 8-N-1 X: 2 R: 7-E-1 退出 Mini 选择, 或按 <Enter> 退出? 选择 E 和 Q, 设置好后回车, 回到 配置 菜单后再进入 调制解调器和拨号, 清除以下几 项的数据 : A - 初始化字符串... B - 重置字符串... K - 停机字符串... 清除完后, 回车退到 配置 菜单后再进入 设置保存为 dfl, 就会保存配置到 ~/.minirc.dfl 然后选择 退出 退出配置状态, 就可以通过串口连接开发板了 还有一个图形化的串口终端 :gtkterm, 图形配置, 简单易用, 但无法传输文件

13 第 4 章熟悉 U-boot 的使用与烧写 要开发和移植 U-boot, 首先要对 U-boot 有一定的了解, 起码要会使用 所以这里首先熟悉一下 U-boot 的使用以及如何将 U-boot 烧入 mini2440 当然在这之前首先必须保证你的开发板上已经有了 U-boot 如果没有, 就请先烧入一个已经编译好的 U-boot 已经针对 mini2440 编译好的 U-boot 的 bin 文件在 Tekkaman Ninja 的博客中有, 可以直接烧入, 链接 :u-boot.bin_tekkaman_ tar.bz2 把它烧到 mini2440 的 NAND 或者 NOR Flash 的起始地址即可, 烧入的方法请参考友善之臂官方网提供的 MINI2440 用户手册 4.1 烧写 U boot 到 mini2440 开发板 4.2 常用 U boot 命令详解 U-boot 发展到现在, 其命令行模式已经非常接近 Linux 下的 shell 了, 在 Tekkaman Ninja 编译的 U-boot 中的命令行模式下支持 Tab 键的命令补全和命令的历史记录功能 而且如果命令的前几个字符和别的命令不重复, 那就只需要打出这几个字符即可, 比如查看 U-boot 的版本号命令是 version, 但是在所有其它命令中没有任何一个的命令是由 v 开头的, 所以只需要输入 v 即可 version U-Boot ( 4 月 :09:25) v U-Boot ( 4 月 :09:25) base Base Address: 0x ba Base Address: 0x 下面简单介绍常用的命令 获取帮助 命令 :help 或? 功能 : 查看当前 U-boot 支持的所有命令 help? - alias for 'help' askenv - get environment variables from stdin

14 base - print or set address offset bdinfo - print Board Info structure bmp - manipulate BMP image data boot - boot default, i.e., run 'bootcmd' bootd - boot default, i.e., run 'bootcmd' bootelf - Boot from an ELF image in memory bootm - boot application image from memory bootp - boot image via network using BOOTP/TFTP protocol bootvx - Boot vxworks from an ELF image cmp - memory compare coninfo - print console devices and information cp - memory copy crc32 - checksum calculation date - get/set/reset date & time dcache - enable or disable data cache dhcp - boot image via network using DHCP/TFTP protocol echo - echo args to console editenv - edit environment variable eeprom - EEPROM sub-system erase - erase FLASH memory exit - exit script fatinfo - print information about filesystem fatload - load binary file from a dos filesystem fatls - list files in a directory (default /) flinfo - print FLASH memory information fsinfo - print information about filesystems fsload - load binary file from a filesystem image go - start application at address 'addr' help - print online help i2c - I2C sub-system icache - enable or disable instruction cache iminfo - print header information for application image imls - list all images found in flash imxtract- extract a part of a multi-image itest - return true/false on integer compare loadb - load binary file over serial line (kermit mode) loads - load S-Record file over serial line loadx - load binary file over serial line (xmodem mode) loady - load binary file over serial line (ymodem mode) loop - infinite loop on address range ls - list files in a directory (default /) md - memory display mm - memory modify (auto-incrementing address) mmc - MMC sub-system mtest - simple RAM read/write test mw - memory write (fill) nand - NAND sub-system nboot - boot from NAND device nfs - boot image via network using NFS protocol nm - memory modify (constant address) ping - send ICMP ECHO_REQUEST to network host printenv- print environment variables protect - enable or disable FLASH write protection rarpboot- boot image via network using RARP/TFTP protocol reginfo - print register information reset - Perform RESET of the CPU run - run commands in an environment variable saveenv - save environment variables to persistent storage setenv - set environment variables showvar - print local hushshell variables

15 sleep - delay execution for some time source - run script from memory test - minimal test like /bin/sh tftpboot- boot image via network using TFTP protocol unzip - unzip a memory region usb - USB sub-system usbboot - boot from USB device version - print monitor version 如果想获取某条命令的详细帮助, 可使用 : help < 想要查的指令 > 或者? < 想要查的指令 >, 甚至 h < 想要查的指令缩写 > 以 bmp 指令为例 : help bmp bmp - manipulate BMP image data Usage: bmp info <imageaddr> - display image info bmp display <imageaddr> [x y] - display image at x,y bmp bmp - manipulate BMP image data Usage: bmp info <imageaddr> - display image info bmp display <imageaddr> [x y] - display image at x,y h bm bmp - manipulate BMP image data Usage: bmp info <imageaddr> - display image info bmp display <imageaddr> [x y] - display image at x,y 环境变量与相关指令 和 shell 类似,U-Boot 也有环境变量 (environment variables, 简称 ENV),U-boot 默认的一些环境变量如下 : 环境变量 解释说明 bootdelay baudrate netmask ethaddr bootfile 执行自动启动 (bootcmd 中的命令 ) 的等候秒数 串口控制台的波特率 以太网的网络掩码 以太网的 MAC 地址 默认下载文件名

16 bootargs bootcmd serverip ipaddr stdin stdout stderr 传递给 Linux 内核的启动参数自动启动时执行命令文件服务器端的 IP 地址本地 IP 地址标准输入设备, 一般是串口标准输出, 一般是串口, 也可是 LCD(VGA) 标准出错, 一般是串口, 也可是 LCD(VGA) 查看当前 U-boot 的 ENV 值可使用 printenv 命令 : printenv bootargs=noinitrd root=/dev/nfs rw nfsroot= :/home/tekkaman/working/nfs/rootfs ip= : :: console=ttysac0, init=/linuxrc mem=64m bootcmd=nfs 0x :/home/tekkaman/working/nfs/zImage.img;bootm bootdelay=1 baudrate= ethaddr=08:08:11:18:12:27 ipaddr= serverip= gatewayip= netmask= tekkaman=bmp d stdin=serial stdout=serial stderr=serial ethact=dm9000 Environment size: 470/ bytes 你会发现有些上面提到的 ENV 没有显示, 还有一个名为 tekkaman 的 ENV 原因是如果没有设置这个环境变量就它不会被打印出, 也可以自己定义 ENV, 并在命令中使用 ${ENV 来调用它 同时还可以删除这个 ENV 设置 ENV 的命令是 setenv, 格式为 : setenv name value 第 1 个参数 name 是环境变量的名称 第 2 个参数 value 是要设置的值, 如果没有第 2 个参数, 表示删除这个环境变量 范例 : 先将 tekkaman 参数删除, 再设置, 最后在一个命令串中调用 printenv tekkaman tekkaman=bmp d setenv tekkaman printenv tekkaman ## Error: "tekkaman" not defined setenv tekkaman echo "I am Tekkaman Ninja!" printenv tekkaman tekkaman=echo I am Tekkaman Ninja! echo I Love Linux ;${tekkaman

17 I Love Linux I am Tekkaman Ninja! 当设置或改动了 ENV, 它只保存在了内存中 如果需要它保存在存放 ENV 的固态存储器中, 请使用 :saveenv saveenv Saving Environment to NAND... Erasing Nand... Erasing at 0x % complete. Writing to Nand... done 如果在启动时,U-boot 打印出 : Warning - bad CRC, using default environment, 说明 U-boot 没有在存放 ENV 的固态存储器中找到有效的 ENV, 只好使用编译时定义的默认 ENV 如果 U-boot 存放 ENV 的固态存储器的驱动是没问题的, 那只要运行 saveenv 就可以把当前系统的所有 ENV 写入固态存储器, 下次启动就不会有这个警告了 ENV 可以放在多种固体存储器中, 对于 mini2440 来说 Nor Flash Nand Flash 或 EEPROM 都可以, 这依赖 include/configs 下的配置文件是如何定义的 例如 : Nor Flash: #define CONFIG_ENV_IS_IN_FLASH 1 #define CONFIG_ENV_OFFSET 0X40000 #define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */ Nand Flash: #define CONFIG_ENV_IS_IN_NAND 1 #define CONFIG_ENV_OFFSET 0X40000 #define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */ EEPROM: #define CONFIG_ENV_IS_IN_EEPROM 1 /* use EEPROM for environment vars */ #define CONFIG_ENV_OFFSET 0x000 /* environment starts at offset 0 */ #define CONFIG_ENV_SIZE 0x400 /* 1KB */ CONFIG_ENV_OFFSET : 是在整个存储器中的偏移地址 ; CONFIG_ENV_SIZE : 是指用来保存 ENV 的分区大小 注意 CONFIG_ENV_OFFSET 和 CONFIG_ENV_SIZE 的设置, 请不要覆盖了其他分区 串口传输命令 命令 : loadb - load binary file over serial line (kermit mode) loadx - load binary file over serial line (xmodem mode) loady - load binary file over serial line (ymodem mode)

18 功能 : 以不同的协议从串口获取 Host 传输过来的文件. 格式 : Load? [ off ] [ baud ] 第 1 个参数 off 是下载到 SDRAM 的地址 如果不填, 就使用默认配置 : CONFIG_SYS_LOAD_ADDR 第 2 个参数是波特率, 一般不填, 用默认的 在 windows 下的超级终端可以用这些协议发送文件, 但是在 ubuntu 下基本只能用 kermit 协议 以下是使用 C-kermit 来发送一个文件到 mini2440 loadb ## Ready for binary (kermit) download to 0x at bps... 上面已经启动了 U-boot 的 kermit 传输协议, 这时按下 Ctrl \, 再按 c, 切换到 C-kermit 的命令行模式, 输入命令 :send < 文件路径 >, 回车 loadb ## Ready for binary (kermit) download to 0x at bps... (Back at MAGI-Linux) C-Kermit , 10 Apr 2004, for Linux Copyright (C) 1985, 2004, Trustees of Columbia University in the City of New York. Type? or HELP for help. (/home/tekkaman/ 桌面 /) C-Kermit>send /home/tekkaman/development/share/zimage.img C-kermit 就开始传送, 并且显示一个传送界面, 并动态显示传送进度 C-Kermit , 10 Apr 2004, MAGI-Linux Current Directory: /home/tekkaman/~l~] Communication Device: /dev/ttyusb0 Communication Speed: Parity: none RTT/Timeout: 01 / 02 SENDING: /home/tekkaman/development/share/zimage.img => zimage.img File Type: BINARY File Size: Percent Done: 19 ///////// Estimated Time Left: 00:03:35 Transfer Rate, CPS: 8536 Window Slots: 1 of 1 Packet Type: D Packet Count: 557 Packet Length: 1000 Error Count: 0 Last Error: Last Message: X to cancel file, Z to cancel group, <CR> to resend last packet,

19 E to send Error packet, ^C to quit immediately, ^L to refresh screen. 传送完毕后, 输入 c, 回到 U-boot 的串口界面 loadb ## Ready for binary (kermit) download to 0x at bps... (Back at MAGI-Linux) C-Kermit , 10 Apr 2004, for Linux Copyright (C) 1985, 2004, Trustees of Columbia University in the City of New York. Type? or HELP for help. (/home/tekkaman/ 桌面 /) C-Kermit>send /home/tekkaman/development/share/zimage.img (/home/tekkaman/ 桌面 /) C-Kermit>c Connecting to /dev/ttyusb0, speed Escape character: Ctrl-\ (ASCII 28, FS): enabled Type the escape character followed by C to get back, or followed by? to see other options ## Total Size = 0x0022c0a4 = Bytes ## Start Addr = 0x 网络命令 只要 U-boot 的网卡驱动没问题, 就可以通过网络来传输文件到开发板, 这比串口快多了 你可以直接用交叉网线连接开发板和电脑, 也可以用普通直连网线通过路由器连到电脑, 不过记得配置好网络, 关闭防火墙 先测试网络是否畅通, 在开发板使用 ping 命令, 看看同电脑的网络连接是否畅通 : ping dm9000 i/o: 0x , id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:08:11:18:12:27 operating at 100M full duplex mode Using dm9000 device host is alive 如果出现 : ping dm9000 i/o: 0x , id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:08:11:18:12:27 operating at 100M full duplex mode Using dm9000 device ping failed; host is not alive 这种无法 ping 通的问题, 原因可能是 : 1 U-boot 网卡驱动有问题 ; 2 U-boot 网络协议延时配置有问题 ;

20 3 网络参数配置问题, 比如 IP 配置等,Host 和 Target 都有可能有问题 Host 最好关闭 IPv6 如果还找不到原因, 可用 Wireshark 抓包看看 如果网络畅通, 就可以使用下面的命令从 tftp 服务目录或者 nfs 服务目录下载文件到 SDRAM 了 命令 : dhcp : 使用 DHCP/TFTP 协议获取文件 rarpboot : 使用 RARP/TFTP 协议获取文件 nfs : 使用 NFS 协议获取文件 tftpboot : 使用 TFTP 协议获取文件 bootp : 使用 BOOTP/TFTP 协议获取文件以上命令的格式都为 : 指令 [ 目的 SDRAM 地址 ] [[ 主机 IP:] 文件名 ] 注意 : 要使用 dhcp rarpboot 或 bootp 要路由器或 Host 支持的这些协议和服务 如果没有输入 [ 目的 SDRAM 地址 ], 系统就是用编译时定义的 CONFIG_SYS_LOAD_ADDR 在使用如果 tftpboot 和 nfs 命令没有定义 [ 主机 IP:], 则使用 ENV 中的 serverip 其它命令必需定义 [ 主机 IP:], 否则使用提供动态 IP 服务的主机 IP 以下是使用范例, 请注意红色字体 : nfs 0x :/home/tekkaman/development/share/u-boot.bin dm9000 i/o: 0x , id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:08:11:18:12:27 operating at 100M full duplex mode Using dm9000 device File transfer via NFS from server ; our IP address is Filename '/home/tekkaman/development/share/u-boot.bin'. Load address: 0x Loading: ################################################### done Bytes transferred = (3e8dc hex) tftp u-boot.bin dm9000 i/o: 0x , id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:08:11:18:12:27 operating at 100M full duplex mode Using dm9000 device TFTP from server ; our IP address is Filename 'u-boot.bin'. Load address: 0x Loading: T ################## done Bytes transferred = (3e8dc hex) dhcp :u-boot.bin dm9000 i/o: 0x , id: 0x90000a46 DM9000: running in 16 bit mode

21 MAC: 08:08:11:18:12:27 operating at 100M full duplex mode BOOTP broadcast 1 BOOTP broadcast 2 DHCP client bound to address Using dm9000 device TFTP from server ; our IP address is Filename 'u-boot.bin'. Load address: 0x Loading: ################## done Bytes transferred = (3e8dc hex) bootp :u-boot.bin dm9000 i/o: 0x , id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:08:11:18:12:27 operating at 100M full duplex mode BOOTP broadcast 1 BOOTP broadcast 2 DHCP client bound to address Using dm9000 device TFTP from server ; our IP address is Filename 'u-boot.bin'. Load address: 0x Loading: ################## done Bytes transferred = (3e8dc hex) rarpboot :u-boot.bin Nand Flash 操作指令 常用的 Nand Flash 指令如下 : 指令 功能 nand info 显示可使用的 Nand Flash nand device [dev] 显示或设定当前使用的 Nand Flash nand read addr off size Nand Flash 读取命令, 从 Nand 的 off 偏移地 址处读取 size 字节的数据到 SDRAM 的 addr 地址 nand write addr off size Nand Flash 烧写命令, 将 SDRAM 的 addr 地 址处的 size 字节的数据烧写到 Nand 的 off 偏移地址 nand write[.yaffs[1]] addr off size 烧写 yaffs 映像专用的命令,.yaffs1 for NAND nand erase [clean] [off size] Nand Flash 檫除命令, 擦除 Nand Flash 的 off 偏移地址处的 size 字节的数据 nand bad 显示 Nand Flash 的坏块 nand dump[.oob] off 显示 Nand Flash 中的数据 (16 进制 ) nand scrub 彻底擦除整块 Nand Flash 中的数据, 包括 OOB 可以擦除软件坏块标志 nand markbad off 标示 Nand 的 off 偏移地址处的块为坏块

22 使用范例 : nand info Device 0: NAND 128MiB 3,3V 8-bit, sector size 128 KiB nand device 0 Device 0: NAND 128MiB 3,3V 8-bit... is now current device nand read 0x x NAND read: device 0 offset 0x60000, size 0x bytes read: OK nand bad Device 0 bad blocks: 030a c e ee0000 nand markbad 0x block 0x successfully marked as bad nand bad Device 0 bad blocks: a c e ee0000 nand scrub NAND scrub: device 0 whole chip Warning: scrub option will erase all factory set bad blocks! There is no reliable way to recover them. Use this command only for testing purposes if you are sure of what you are doing! Really scrub this NAND flash? <y/n> Erasing at 0x2f % complete. NAND 128MiB 3,3V 8-bit: MTD Erase failure: -5 NAND 128MiB 3,3V 8-bit: MTD Erase failure: -5 NAND 128MiB 3,3V 8-bit: MTD Erase failure: -5 Erasing at 0x7ea % complete. NAND 128MiB 3,3V 8-bit: MTD Erase failure: -5 Erasing at 0x7fe % complete. OK nand bad Device 0 bad blocks: 030a c e ee0000 nand dump 0x8000 Page dump: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ( 略 )

23 OOB: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff tftp u-boot.bin dm9000 i/o: 0x , id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:08:11:18:12:27 operating at 100M full duplex mode Using dm9000 device TFTP from server ; our IP address is Filename 'u-boot.bin'. Load address: 0x Loading: T ################## done Bytes transferred = (3e8dc hex) nand write 0x NAND write: device 0 offset 0x0, size 0x40000 Writing at 0x % is complete bytes written: OK nand dump 0x8000 Page dump: e a e0 e ea ( 略 ) e e1 f6 ff ff ba a0 e3 OOB: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 65 a9 6b f3 ff 33 fc 30 f3 33 cf 33 0f f0 ff 00 cc 0f a5 5b nboot 指令也是一条 Nand Flash 读取指令, 它是将 Nand Flash 的 offset 偏移地址的内核映像读取到 SDRAM 的 loadaddr 位置 它会自动读取到内核映像 ( 使用 mkimage 处理过的 ) 的结束, 所以不用给出读取大小 格式 :nboot loadaddr dev offset 使用范例 : tftp :zImage.img dm9000 i/o: 0x , id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:08:11:18:12:27 operating at 100M full duplex mode Using dm9000 device TFTP from server ; our IP address is Filename 'zimage.img'. Load address: 0x Loading: T ################################################################# #################################################################

24 ########################## done Bytes transferred = (22c0a4 hex) nand erase 0x NAND erase: device 0 offset 0x100000, size 0x Erasing at 0x3e % complete. OK nand write 0x x NAND write: device 0 offset 0x100000, size 0x Writing at 0x3e % is complete bytes written: OK nand device 0 Device 0: NAND 128MiB 3,3V 8-bit... is now current device nboot x Loading from NAND 128MiB 3,3V 8-bit, offset 0x Image Name: tekkaman Created: :59:51 UTC Image Type: ARM Linux Kernel Image (uncompressed) Data Size: Bytes = 2.2 MB Load Address: Entry Point: bootm ## Booting kernel from Legacy Image at Image Name: tekkaman Created: :59:51 UTC Image Type: ARM Linux Kernel Image (uncompressed) Data Size: Bytes = 2.2 MB Load Address: Entry Point: Verifying Checksum... OK XIP Kernel Image... OK OK Starting kernel... Uncompressing Linux... done, booting the kernel. Linux version (gcc version (crosstool-ng tekkaman) ) #5 Mon Mar 29 20:58:50 CST 2010 CPU: ARM920T [ ] revision 0 (ARMv4T), cr=c CPU: VIVT data cache, VIVT instruction cache Machine: MINI2440 ( 略 ) 内存 / 寄存器操作指令 nm 修改内存值 ( 指定地址 ) 格式 : nm [.b,.w,.l] address mm 修改内存值 ( 地址自动加一 ) 格式 : mm [.b,.w,.l] address

25 md 显示内存值格式 : md [.b,.w,.l] address [# of objects] mw 用指定的数据填充内存格式 : mw [.b,.w,.l] address value [count] cp 内存的拷贝 ( 包括内存与 Nor Flash 间的数据拷贝 ) 格式 :cp [.b,.w,.l] source target count 上面是查看和修改内存值的指令, 可以查看和修改 SDRAM 和寄存器值 [.b,.w,.l] 代表了查看和修改形式 :bit word long 使用范例 : md.b 0x : cc 33 fe 33 cc b3 4c 33 ac 33 de 33 5c 13 cc L3.3.3\ : cc 32 cc 31 dc 33 cf 33 cc 33 4e 33 8f 13 cc N3...3 md.w 0x : 33cc 33fe b3cc 334c 33ac 33de 135c 33cc.3.3..L3.3.3\ : 32cc 31cc 33dc 33cf 33cc 334e 138f 33cc N : 338c 33cd 33cc 7bcc 3bcc 33cc 135e 734c {.;.3^.Ls : 7bdc 37cc 31dc 33c4 038c 33e8 77cc 13cc.{ w.. md.l 0x : 33fe33cc 334cb3cc 33de33ac 33cc135c.3.3..L3.3.3\ : 31cc32cc 33cf33dc 334e33cc 33cc138f N : 33cd338c 7bcc33cc 33cc3bcc 734c135e {.;.3^.Ls : 37cc7bdc 33c431dc 33e8038c 13cc77cc.{ w : 234c77ce 33dc339c 33ec3ece f3cc36ec.wl#.3.3.> : 37dc33cc 73cc3f5c 17dd314c 33cc62e8.3.7\?.sL1...b : b6cc33dc 33c233cc 33cc32cc 33cc3f h? : 73cc31cc b3cc33cc 33cc37c9 33df13cc.1.s nm 0x : 33fe33cc? : ? : ? q nm.b 0x : 90? : 11? : 12? q mm 0x : ? : 334cb3cc? : 33de33ac?

26 c: 33cc135c? q md.b 0x : c 13 cc 33 #.2TxV4.CE#!\ : cc 32 cc 31 dc 33 cf 33 cc 33 4e 33 8f 13 cc N3...3 mw.b 0x aa 10 mw.b 0x md.b 0x : aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa : UUUUUUUUUUUUUUUU cp.b 0x x md.b 0x : aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa : aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa... 你可以试着修改 LED 相连的 GPIO 寄存器的数据寄存器值, 可以控制 LED 的点亮! 先熄灭后点亮 LED1 的范例 :( 这个实验要结合芯片数据手册和 mini2440 的原理图来理解 ) md 0x : nm.w 0x : 0600? 620 ( 熄灭 ) : 0620? 600 ( 点亮 ) Nor Flash 指令 Nor Flash 的命令经常用于烧写数据到 Nor Flash flinfo 打印 Flash 存储器的信息, 并列出所有 Sector flinfo N 单独打 Flash 存储器 N Block 的信息 ( 在有多块 Nor Flash 时使用 ) flinfo Bank # 1: SST: 1x SST39VF1601 (2MB) Size: 2 MB in 32 Sectors Sector Start Addresses: (RO) (RO) (RO) (RO) (RO) (RO) A B C D E F A B C D E F0000 flinfo 1 Bank # 1: SST: 1x SST39VF1601 (2MB) Size: 2 MB in 32 Sectors Sector Start Addresses: (RO) (RO) (RO) (RO) (RO) (RO)

27 000A B C D E F A B C D E F0000 flinfo 2 Only FLASH Banks # 1... # 1 supported 后面带有 (RO) 的说明这个 Sector 已经写保护了 因为 Nor Flash 的读取接口和 SDRAM 是一样的, 所以 Nor Flash 的读取也是使用 md 命 令 范例如下 : md.b 0x : ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e : 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5... md 0x : ea e59ff014 e59ff014 e59ff : e59ff014 e59ff014 e59ff014 e59ff : 33f f802c0 33f f80380 ` : 33f803e0 33f f804a : 33f f fbe8dc c L : e10f0000 e3c0001f e38000d3 e129f000...) : e3a00453 e3a01000 e e3e01000 S : e59f0488 e e59f1484 e59f 但由于 Nor Flash 的烧写时序和 SDRAM 的写入不同, 烧写 Nor Flash 不能使用 mm 等命令, 只能使用 cp 命令从内存拷贝到 Nor Flash, 而且之前必须解除保护并擦除! 命令如下 : protect : 对 Flash 写保护的操作, 可以使能和解除写保护 格式 : protect on/off start end protect on/off start end protect on/off N:SF[-SL] protect on/off bank N protect on/off all 第 1 个参数 on 代表使能写保护 ;off 代表解除写保护 第 2 3 参数是指定 Flash 写保护操作范围 start end 是照起始地址和结束地址定义范围,start 是擦除块的起始地址 ;end 是擦除末尾块的结束地址 例如 : 擦除 Sector 2 和 Sector 3 区域命令为 erase ffff start end 是照起始地址和操作字节数定义范围, 这种方式最常用 start 是擦除块的起始地址 ;end 是擦除的字节数 例如 : 擦除 Sector 2 和 Sector 3 区域命令为 erase

28 N:SF[-SL] 是按照组和扇区,N 表示 Flash 的 Block 号,SF 表示擦除起始 Sector 号,SL 表示擦除结束 Sector 号 例如 : 擦除 Block1 的 Sector 2 和 Sector 3 区域命令为 erase 1:2-3 bank N 是擦除整个 Block, 擦除 Block 号为 N 的整个 Flash all 是擦除全部 Flash 注意 :Nor Flash 擦除的最小单位是 Sector, 也就是 0x10000 字节, 如果你定义的大小不满 1 Sector 或超过 Sector 的边界, 那么被定义到的 Sector 会被全部擦除 erase : 擦除 Flash 的命令格式 : erase start end erase start end erase N:SF[-SL] erase bank N erase all 参数是指定 Flash 擦除操作范围, 跟写保护的方式相同 范例将 mini2440 的 Nor Flash 的 Sector 16 写保护, 再解除保护, 擦除数据, 最后将起始的 20 字节拷贝到 Sector 16 flinfo 1 Bank # 1: SST: 1x SST39VF1601 (2MB) Size: 2 MB in 32 Sectors Sector Start Addresses: (RO) (RO) (RO) (RO) (RO) (RO) A B C D E F A B C D E F0000 protect on 1:16-16 Protect Flash Sectors in Bank # 1 flinfo 1 Bank # 1: SST: 1x SST39VF1601 (2MB) Size: 2 MB in 32 Sectors Sector Start Addresses: (RO) (RO) (RO) (RO)

29 (RO) (RO) A B C D E F (RO) A B C D E F0000 protect off 0x x10ffff Un-Protect Flash Sectors in Bank # 1 flinfo 1 Bank # 1: SST: 1x SST39VF1601 (2MB) Size: 2 MB in 32 Sectors Sector Start Addresses: (RO) (RO) (RO) (RO) (RO) (RO) A B C D E F A B C D E F0000 erase 0x Erasing sector ok. Erased 1 sectors cp.b 0x0 0x x20 Copy to Flash... done md.b : ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e : 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 14 f0 9f e USB 操作指令 usb reset usb stop [f] usb tree usb info [dev] usb storage usb dev [dev] usb part [dev] 指令 功能初始化 USB 控制器关闭 USB 控制器已连接的 USB 设备树显示 USB 设备 [dev] 的信息显示已连接的 USB 存储设备显示和设置当前 USB 存储设备显示 USB 存储设备 [dev] 的分区信息

30 usb read addr blk# cnt 读取 USB 存储设备数据 我将一个 4G 的 kingstonu 盘 ( 可引导盘 ) 插入 mini2440, 然后读取他的头 512 字节 (MBR): usb reset (Re)start USB... USB: scanning bus for devices... 2 USB Device(s) found scanning bus for storage devices... 1 Storage Device(s) found usb tree Device Tree: 1 Hub (12 Mb/s, 0mA) OHCI Root Hub -2 Mass Storage (12 Mb/s, 100mA) Kingston DT 101 II 0019E02CB6EB5B8B1B usb info 1: Hub, USB Revision OHCI Root Hub - Class: Hub - PacketSize: 8 Configurations: 1 - Vendor: 0x0000 Product 0x0000 Version 0.0 Configuration: 1 - Interfaces: 1 Self Powered 0mA Interface: 0 - Alternate Setting 0, Endpoints: 1 - Class Hub - Endpoint 1 In Interrupt MaxPacket 2 Interval 255ms 2: Mass Storage, USB Revision Kingston DT 101 II 0019E02CB6EB5B8B1B Class: (from Interface) Mass Storage - PacketSize: 64 Configurations: 1 - Vendor: 0x0951 Product 0x1613 Version 1.0 Configuration: 1 - Interfaces: 1 Bus Powered 100mA Interface: 0 - Alternate Setting 0, Endpoints: 2 - Class Mass Storage, Transp. SCSI, Bulk only - Endpoint 1 In Bulk MaxPacket 64 - Endpoint 2 Out Bulk MaxPacket 64 usb storage

31 Device 0: Vendor: Kingston Rev: PMAP Prod: DT 101 II Type: Removable Hard Disk Capacity: MB = 3.7 GB ( x 512) usb dev 0 USB device 0: Device 0: Vendor: Kingston Rev: PMAP Prod: DT 101 II Type: Removable Hard Disk Capacity: MB = 3.7 GB ( x 512)... is now current device usb part 0 print_part of 0 Partition Map for USB device 0 -- Partition Type: DOS Partition Start Sector Num Sectors Type c usb read 0x USB read: device 0 block # 0, count blocks read: OK md.b 0x : fa 31 c0 8e d8 8e c0 8e d0 bc 00 7c fb fc 89 e : bf b f3 a5 ea dc : c f ? : ff 00 ed 01 1e 0e 1f 3a f ea 36...:...t : e7 00 f0 3d fb c d8 fb eb 1d 80 fc 08...=.Tu : 75 1b e a fe ce 8b 0e u : cd c0 e1 06 0a 0e c0 f8 eb fc e : 72 cb 80 fc c cc be c : e c 04 8c D..\..D.f : c c 88 f0 f cf 88 eb c0.f.d...& a0: ef e1 3f c c7 a f ?...H...& b0: f7 e3 01 f8 81 d a...D..T c0: c0 8a e8 0c a1 X0...&..a d0: f ca c ff 1e c3 80 fa 8f 7f..." e0: d 06 be e8 8d 00 be be c f0: b f f5 81 c : f cd 18 bf be 1d 06 c Ht...D : b b a 16 2d 06.f.F.f.D...B : cd d 4f e4 8a 16 2d 06 cd 13 eb..s.oti : d8 a1 fe 7d 3d 55 aa fa 66 a1 4c a3...=u.u7.f.l.f : 3f 06 be b c1 e0 06 8e c0 31?...H : ff be 1d 06 b fc f3 a5 c7 06 4c `...L...

32 : a3 4e 00 fb 8a 16 2d ee fa ea 00 7c N : be aa 07 e eb fe ac 20 c b4 0e bb....t : cd 10 eb f2 c f 6f...Start boo : e f 6d ting from USB de a0: e 2e 2e 0d 0a f 6f vice...boot f b0: c ea eb d4 ca ailed c0: d0: e0: f0: c fe 7f ec 3f c aa...?...y.u. 在所有的命令使用前, 必须先插入 USB 设备, 然后使用 :usb reset, 以初始化 USB 控 制器, 获取设备信息 SD 卡 (MMC) 指令 mmc mmc - MMC sub-system Usage: mmc init [dev] - init MMC sub system mmc device [dev] - show or set current device SD 卡的使用命令比较简单, 只有初始化和设备信息的显示, 读写是通过文件系统命令实现的 使用和 USB 类似, 在所有的命令使用前, 必须先插入 SD 卡, 然后使用 :mmc init, 以初始化 MMC 控制器, 获取设备信息 我在 mini2440 中插入 1GB SD 卡 : mmc init mmc: Probing for SDHC... mmc: SD 2.0 or later card found trying to detect SD Card... Manufacturer: 0x00, OEM "Product name: " ", revision 0.0 Serial number: Manufacturing date: 11/2006 CRC: 0x4f, b0 = 1 READ_BL_LEN=6, C_SIZE_MULT=7, C_SIZE=4095 size = 0 SD Card detected RCA: 0x2 type: SD mmc1 is available mmc device mmc1 is current device

33 FAT 文件系统指令 fatinfo: 显示文件系统的相关信息格式 :fatinfo <interface> <dev[:part]> Interface: 代表接口, 如 usb mmc; dev: 代表设备编号, 如 0 1 ; part: 代表存储设备中的分区, 如 1 2 fatload: 从 FAT32 文件系统中读取二进制文件到 SDRAM 格式 :fatload <interface> <dev[:part]> <addr> <filename> [bytes] Interface dev 和 part 同上 ; addr: 代表写入 SDRAM 的地址 ; filename: 代表存储设备中的文件名 ; bytes: 代表从存储设备中读取的文件大小, 可不填 ; 如果填的数据比文件小, 就只读取 bytes 字节, 如果填的数据比文件大, 也只读取文件的大小 fatls: 列出 FAT32 文件系统中目录里的文件 格式 :fatls <interface> <dev[:part]> [directory] Interface dev 和 part 同上 ; directoryr: 代表所要查看的目录, 可不填, 默认为 / 这些指令基本上要和 U 盘或者 SD 卡同时使用, 主要用于读取这些移动存储器上的 FAT32 分区 使用范例 : usb part 0 print_part of 0 Partition Map for USB device 0 -- Partition Type: DOS Partition Start Sector Num Sectors Type c fatinfo usb 0:4 Interface: USB Device 0: Vendor: Kingston Rev: PMAP Prod: DT 101 II Type: Removable Hard Disk Capacity: MB = 3.7 GB ( x 512) Partition 4: Filesystem: FAT32 "7600_16385_"

34 fatls usb 0:4 boot/ efi/ sources/ support/ upgrade/ 43 autorun.inf bootmgr setup.exe u-boot.bin 4 file(s), 5 dir(s) fatls usb 0:4 /boot/./../ fonts/ zh-cn/ bcd boot.sdi 1024 bootfix.bin bootsect.exe 4096 etfsboot.com memtest.exe 6 file(s), 4 dir(s) fatload usb 0:4 0x u-boot.bin reading u-boot.bin bytes read fatload usb 0:4 0x u-boot.bin 200 reading u-boot.bin 512 tes read 系统引导指令 boot 和 bootd 都是运行 ENV bootcmd 中指定的指令 bootm 指令是专门用于启动在 SDRAM 中的用 U-boot 的 mkimage 工具处理过的内核映像 格式 :bootm [addr [arg...]]

35 addr 是内核映像所在的 SDRAM 中的地址 当启动的是 Linux 内核时,'arg' 可以使 initrd 的地址 范例 : setenv bootcmd tftp\;bootm saveenv Saving Environment to NAND... Erasing Nand... Erasing at 0x % complete. Writing to Nand... done boot dm9000 i/o: 0x , id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:08:11:18:12:27 operating at 100M full duplex mode Using dm9000 device TFTP from server ; our IP address is Filename 'zimage.img'. Load address: 0x Loading: T ################################################################# ################################################################# ########################## done Bytes transferred = (22c0a4 hex) ## Booting kernel from Legacy Image at Image Name: tekkaman Created: :59:51 UTC Image Type: ARM Linux Kernel Image (uncompressed) Data Size: Bytes = 2.2 MB Load Address: Entry Point: Verifying Checksum... OK XIP Kernel Image... OK OK Starting kernel... Uncompressing Linux... done, booting the kernel. Linux version (gcc version (crosstool-ng tekkaman) ) #5 Mon Mar 29 20:58:50 CST 2010 CPU: ARM920T [ ] revision 0 (ARMv4T), cr=c CPU: VIVT data cache, VIVT instruction cache Machine: MINI2440 ( 略 ) U-Boot ( 4 月 :09:25) modified by tekkamanninja Love Linux forever!! I2C: ready DRAM: 64 MB Flash: 2 MB NAND: 128 MiB Video: 240x320x16 20kHz 62Hz In: serial Out: serial

36 Err: serial Net: dm9000 U-Boot ( 4 月 :09:25) modified by tekkamanninja Love Linux forever!! Hit any key to stop autoboot: 0 bootd dm9000 i/o: 0x , id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:08:11:18:12:27 operating at 100M full duplex mode Using dm9000 device TFTP from server ; our IP address is Filename 'zimage.img'. Load address: 0x Loading: T ################################################################# ################################################################# ########################## done Bytes transferred = (22c0a4 hex) ## Booting kernel from Legacy Image at Image Name: tekkaman Created: :59:51 UTC Image Type: ARM Linux Kernel Image (uncompressed) Data Size: Bytes = 2.2 MB Load Address: Entry Point: Verifying Checksum... OK XIP Kernel Image... OK OK Starting kernel... ( 略 ) 其他指令 run - 运一个 ENV 定义的命令脚本 使用范例 : setenv a_run_test echo $bootfile \; version run a_run_test zimage.img U-Boot ( 4月 :09:25) reset - 重启 CPU 其他指令, 可以用 help 查到用法

37 4.3 下载与烧写 使用 U-boot 将映像文件烧写到板上的 Flash, 一般步骤是 : (1) 通过网络 串口 U 盘 SD 卡等方式将文件传输到 SDRAM; (2) 使用 Nand Flash 或 Nor Flash 相关的读写命令将 SDRAM 中的数据烧入 Flash 下面是烧写范例 : 如果使用 SD 卡和 U 盘形式更新 U-boot, 那么首先 SD 卡和 U 盘中必须有 FAT32 文件系统, 并在里面存放了 u-boot.bin 文件 通过 SD 卡烧入 Nand Flash: mmc init mmc: Probing for SDHC... mmc: SD 2.0 or later card found trying to detect SD Card... Manufacturer: 0x00, OEM "Product name: " ", revision 0.0 Serial number: Manufacturing date: 11/2006 CRC: 0x4f, b0 = 1 READ_BL_LEN=6, C_SIZE_MULT=7, C_SIZE=4095 size = 0 SD Card detected RCA: 0x2 type: SD mmc1 is available fatload mmc 1 0x u-boot.bin reading u-boot.bin bytes read nand erase 0 0x40000 NAND erase: device 0 offset 0x0, size 0x40000 Erasing at 0x % complete. OK nand write 0x x40000 NAND write: device 0 offset 0x0, size 0x40000 Writing at 0x % is complete bytes written: OK 通过 U 盘烧入 Nor Flash: usb start (Re)start USB... USB: scanning bus for devices... 2 USB Device(s) found scanning bus for storage devices... 1 Storage Device(s) found usb storage Device 0: Vendor: Kingston Rev: PMAP Prod: DT 101 II Type: Removable Hard Disk

38 Capacity: MB = 3.7 GB ( x 512) usb part 0 print_part of 0 Partition Map for USB device 0 -- Partition Type: DOS Partition Start Sector Num Sectors Type c fatload usb 0:4 0x u-boot.bin reading u-boot.bin bytes read protect off all Un-Protect Flash Bank # 1 erase 0x0 0x3ffff Erasing sector 0... ok. Erasing sector 1... ok. Erasing sector 2... ok. Erasing sector 3... ok. Erased 4 sectors cp.b 0x x0 0x3ffff Copy to Flash... done 通过 TFTP 服务烧入 Nand Flash: tftpboot :u-boot.bin dm9000 i/o: 0x , id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:08:11:18:12:27 operating at 100M full duplex mode Using dm9000 device TFTP from server ; our IP address is Filename 'u-boot.bin'. Load address: 0x Loading: T ################## done Bytes transferred = (3e8dc hex) nand erase 0 0x40000 NAND erase: device 0 offset 0x0, size 0x40000 Erasing at 0x % complete. OK nand write 0x x40000 NAND write: device 0 offset 0x0, size 0x40000 Writing at 0x % is complete bytes written: OK 通过 NFS 服务烧入 Nand Flash: nfs :/home/tekkaman/development/share/u-boot.bin dm9000 i/o: 0x , id: 0x90000a46 DM9000: running in 16 bit mode

39 MAC: 08:08:11:18:12:27 operating at 100M full duplex mode Using dm9000 device File transfer via NFS from server ; our IP address is Filename '/home/tekkaman/development/share/u-boot.bin'. Load address: 0x Loading: ################################################### done Bytes transferred = (3e8dc hex) nand erase 0 0x40000 NAND erase: device 0 offset 0x0, size 0x40000 Erasing at 0x % complete. OK nand write 0x x40000 NAND write: device 0 offset 0x0, size 0x40000 Writing at 0x % is complete bytes written: OK 4.4 内核引导 内核的引导步骤如下 : (1) 用 U-boot 的 mkimage 工具处理内核映像 zimage (2) 通过网络 串口 U 盘 SD 卡等方式将处理过的内核映像传输到 SDRAM 的一定位置 ( 一般使用 0x ) (3) 然后使用 bootm" 等内核引导命令来启动内核 为什么要用 U-boot 的 mkimage 工具处理内核映像 zimage? 因为在用 bootm 命令引导内核的时候,bootm 需要读取一个 64 字节的文件头, 来获取这个内核映象所针对的 CPU 体系结构 OS 加载到内存中的位置 在内存中入口点的位置以及映象名等等信息 这样 bootm 才能为 OS 设置好启动环境, 并跳入内核映象的入口点 而 mkimage 就是添加这个文件头的专用工具 具体的实现请看 U-boot 中 bootm 的源码和 mkimage 的源码 mkimage 工具的使用 : 参数说明 : -A 指定 CPU 的体系结构, 可用值有 :alpha arm x86 ia64 mips mips64 ppc s390 sh sparc sparc64 m68k 等 -O 指定操作系统类型, 可用值有 :openbsd netbsd freebsd 4_4bsd linux svr4 esix solaris irix sco dell ncr lynxos vxworks psos qnx u-boot rtems artos -T 指定映象类型, 可用值有 :standalone kernel ramdisk multi firmware script filesystem -C 指定映象压缩方式, 可用值有 : none 不压缩 ( 一般使用这个, 因为 zimage 是已经被 bzip2 压缩过的自解压内核 )

40 gzip 用 gzip 的压缩方式 bzip2 用 bzip2 的压缩方式 -a 指定映象在内存中的加载地址, 映象下载到内存中时, 要按照用 mkimage 制作映象时, 这个参数所指定的地址值来下载 -e 指定映象运行的入口点地址, 这个地址就是 -a 参数指定的值加上 0x40( 因为前面有个 mkimage 添加的 0x40 个字节的头 ) -n 指定映象名 -d 指定制作映象的源文件 以下是制作内核映像的命令示例 : mkimage -n 'tekkaman' -A arm -O linux -T kernel -C none -a 0x e 0x d zimage zimage.img 以下是使用范例 : 通过 SD 卡引导内核 : 首先 SD 卡中必须有 FAT32 文件系统, 并在里面存放了处理过的内核映像文件 mmc init mmc: Probing for SDHC... mmc: SD 2.0 or later card found trying to detect SD Card... Manufacturer: 0x00, OEM "Product name: " ", revision 0.0 Serial number: Manufacturing date: 11/2006 CRC: 0x4f, b0 = 1 READ_BL_LEN=6, C_SIZE_MULT=7, C_SIZE=4095 size = 0 SD Card detected RCA: 0x2 type: SD mmc1 is available fatload mmc zimage.img reading zimage.img bytes read bootm ## Booting kernel from Legacy Image at Image Name: tekkaman Created: :59:51 UTC Image Type: ARM Linux Kernel Image (uncompressed) Data Size: Bytes = 2.2 MB Load Address: Entry Point: Verifying Checksum... OK XIP Kernel Image... OK OK Starting kernel...

41 Uncompressing Linux... done, booting the kernel. Linux version (gcc version (crosstool-ng tekkaman) ) #5 Mon Mar 29 20:58:50 CST 2010 CPU: ARM920T [ ] revision 0 (ARMv4T), cr=c CPU: VIVT data cache, VIVT instruction cache Machine: MINI2440 ( 略 ) 通过 TFTP 服务引导内核 tftpboot 0x :zImage.img dm9000 i/o: 0x , id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:08:11:18:12:27 operating at 100M full duplex mode Using dm9000 device TFTP from server ; our IP address is Filename 'zimage.img'. Load address: 0x Loading: T ################################################################# ################################################################# ########################## done Bytes transferred = (22c0a4 hex) bootm ## Booting kernel from Legacy Image at Image Name: tekkaman Created: :59:51 UTC Image Type: ARM Linux Kernel Image (uncompressed) Data Size: Bytes = 2.2 MB Load Address: Entry Point: Verifying Checksum... OK XIP Kernel Image... OK OK Starting kernel... Uncompressing Linux... done, booting the kernel. Linux version (gcc version (crosstool-ng tekkaman) ) #5 Mon Mar 29 20:58:50 CST 2010 CPU: ARM920T [ ] revision 0 (ARMv4T), cr=c CPU: VIVT data cache, VIVT instruction cache Machine: MINI2440 ( 略 ) 通过 NFS 服务引导内核 : nfs :/home/tekkaman/development/share/zImage.img dm9000 i/o: 0x , id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:08:11:18:12:27 operating at 100M full duplex mode

42 Using dm9000 device File transfer via NFS from server ; our IP address is Filename '/home/tekkaman/development/share/zimage.img'. Load address: 0x Loading: ################################################################# ################################################################# ################################################################# ################################################################# ################################################################# ################################################################# ####################################################### done Bytes transferred = (22c0a4 hex) bootm ## Booting kernel from Legacy Image at Image Name: tekkaman Created: :59:51 UTC Image Type: ARM Linux Kernel Image (uncompressed) Data Size: Bytes = 2.2 MB Load Address: Entry Point: Verifying Checksum... OK XIP Kernel Image... OK OK Starting kernel... Uncompressing Linux... done, booting the kernel. Linux version (gcc version (crosstool-ng tekkaman) ) #5 Mon Mar 29 20:58:50 CST 2010 CPU: ARM920T [ ] revision 0 (ARMv4T), cr=c CPU: VIVT data cache, VIVT instruction cache Machine: MINI2440 ( 略 ) 通过 Nand Flash 引导内核 : 首先要将处理过的内核映像文件烧入 Nand Flash 的一定位置 ( 由内核分区表决定 ) 以后每次启动时用 Nand Flash 的读取命令先将这个内核映像文件读到内存的一定位置 ( 由制作内核映像时的 -a 参数决定 ), 再使用 bootm 命令引导内核 内核映像文件的烧入 : nfs :/home/tekkaman/development/share/zImage.img dm9000 i/o: 0x , id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:08:11:18:12:27 operating at 100M full duplex mode Using dm9000 device File transfer via NFS from server ; our IP address is Filename '/home/tekkaman/development/share/zimage.img'. Load address: 0x Loading: ################################################################# #################################################################

43 ################################################################# ################################################################# ################################################################# ################################################################# ####################################################### done Bytes transferred = (22c0a4 hex) nand erase 0x x NAND erase: device 0 offset 0x80000, size 0x Erasing at 0x % complete. OK nand write x NAND write: device 0 offset 0x80000, size 0x Writing at 0x % is complete bytes written: OK 内核引导 : nand read x NAND read: device 0 offset 0x80000, size 0x bytes read: OK bootm ## Booting kernel from Legacy Image at Image Name: tekkaman Created: :59:51 UTC Image Type: ARM Linux Kernel Image (uncompressed) Data Size: Bytes = 2.2 MB Load Address: Entry Point: Verifying Checksum... OK XIP Kernel Image... OK OK Starting kernel... Uncompressing Linux... done, booting the kernel. Linux version (gcc version (crosstool-ng tekkaman) ) #5 Mon Mar 29 20:58:50 CST 2010 CPU: ARM920T [ ] revision 0 (ARMv4T), cr=c CPU: VIVT data cache, VIVT instruction cache Machine: MINI2440 ( 略 )

44 第 5 章 U-boot 源码简要分析 本次移植使用的是 U-boot 先来看看源码目录结构, 再按照代码的执行顺序简单地分析源码 5.1 U-boot 源码整体框架 源码解压以后, 我们可以看到以下的文件和文件夹 : cpu 与处理器相关的文件 每个子目录中都包括 cpu.c 和 interrupt.c start.s u-boot.lds cpu.c 初始化 CPU 设置指令 Cache 和数据 Cache 等 interrupt.c 设置系统的各种中断和异常 start.s 是 U-boot 启动时执行的第一个文件, 它主要做最早其的系统初始化, 代码重定向和设置系统堆栈, 为进入 U-boot 第二阶段的 C 程序奠定基础 u-boot.lds 链接脚本文件, 对于代码的最后组装非常重要 board 已经支持的所有开发板相关文件, 其中包含 SDRAM 初始化代码 Flash 底层驱动 板级初始化文件 其中的 config.mk 文件定义了 TEXT_BASE, 也就是代码在内存的其实地址, 非常重要 common 与处理器体系结构无关的通用代码,U-boot 的命令解析代码 /common/command.c 所有命令的上层代码 cmd_*.c U- boot 环境变量处理代码 env_*.c 等都位于该目录下 drivers 包含几乎所有外围芯片的驱动, 网卡 USB 串口 LCD disk fs net include doc lib_arm lib_avr32 lib_blackfin lib_generic lib_i386 lib_m68k lib_microblaze api examples lib_mips lib_nios lib_nios2 lib_ppc lib_sh lib_sparc Nand Flash 等等支持的 CPU 无关的重要子系统 : 磁盘驱动的分区处理代码文件系统 :FAT JFFS2 EXT2 等网络协议 :NFS TFTP RARP DHCP 等等头文件, 包括各 CPU 的寄存器定义, 文件系统 网络等等 configs 子目录下的文件是与目标板相关的配置头文件 U-Boot 的说明文档, 在修改配置文件的时候可能用得上处理器体系相关的初始化文件比较重要的是其中的 board.c 文件, 几乎是 U-boot 的所有架构第二阶段代码入口函数和相关初始化函数存放的地方 外部扩展应用程序的 API 和范例

45 nand_spl onenand_ipl post libfdt tools Makefile MAKEALL config.mk rules.mk mkconfig CHANGELOG CHANGELOG-before-U-Boot COPYING CREDITS MAINTAINERS README 一些特殊构架需要的启动代码和上电自检程序代码 支持平坦设备树 (flattened device trees) 的库文件编译 S-Record 或 U-Boot 映像等相关工具, 制作 bootm 引导的内核映像文件工具 mkimage 源码就在此控制整个编译过程的主 Makefile 文件和规则文件 一些介绍性的文档 版权说明 标为红色的是移植时比较重要的文件或文件夹 5.2 U boot 代码的大致执行流程 ( 以 S3C24x0 为例 ) 从链接脚本文件 u-boot.lds 中可以找到代码的起始 : OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_ARCH(arm) ENTRY(_start) SECTIONS {. = 0x ;.... = ALIGN(4);.text : { cpu/arm920t/start.o *(.text) (.text) 从中知道程序的入口点是 _start, 定位于 cpu/arm920t /start.s( 即 u-boot 启动的第一阶段 ) 下面我们来仔细分析一下 start.s ( 请对照数据手册阅读源码 ) #include <common.h> #include <config.h> /* ************************************************************************* * * Jump vector table as in table 3.1 in [1] * ************************************************************************* */ // 位于 \include 目录下是一个包含其他头文件的头文件 // 位于 \include\linux 目录下.globl _start _start: b start_code ldr pc, _undefined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort ldr pc, _data_abort u-boot 的主入口, 跳入了后面的 start_code

46 ldr pc, _not_used ldr pc, _irq ldr pc, _fiq _undefined_instruction:.word undefined_instruction _software_interrupt:.word software_interrupt _prefetch_abort:.word prefetch_abort _data_abort:.word data_abort _not_used:.word not_used _irq:.word irq _fiq:.word fiq.balignl 16,0xdeadbeef /* ************************************************************************* * * Startup Code (called from the ARM reset exception vector) * * do important init only if we don't start from memory! * relocate armboot to ram * setup stack * jump to second stage * ************************************************************************* */ _TEXT_BASE:.word TEXT_BASE 这些是跳转向量表, 和芯片的体系结构有关 ldr 语句的意思是将第二个操作数 ( 如 : _undefined_instruction) 指向的地址数据传给 PC.word 为定义一个 4 字节的空间 undefined_instruction 为地址, 即后面标号所对的偏移地址数据 16 字节对齐, 并以 0xdeadbeef 填充, 它是个 Magic number 这些和上面的一样, 定义一个 4 字节的空间存放地址.globl _armboot_start _armboot_start:.word _start /* * These are defined in the board-specific linker script. */.globl _bss_start _bss_start:.word bss_start.globl _bss_end _bss_end:.word _end #ifdef CONFIG_USE_IRQ /* IRQ stack memory (calculated at run-time) */.globl IRQ_STACK_START IRQ_STACK_START:.word 0x0badc0de /* IRQ stack memory (calculated at run-time) */.globl FIQ_STACK_START FIQ_STACK_START:.word 0x0badc0de /* * the actual start code */ start_code: /* * set the cpu to SVC32 mode */ mrs r0, cpsr bic r0, r0, #0x1f orr r0, r0, #0xd3 msr cpsr, r0 代码从这里开始执行!! 让系统进入 SVC( 管理员模式 ) bl bl coloured_led_init red_led_on 这些都是为 AT91RM9200 写的

47 #if copyex: defined(config_at91rm9200dk) defined(config_at91rm9200ek) /* * relocate exception table */ ldr r0, =_start ldr r1, =0x0 mov r2, #16 subs r2, r2, #1 ldr r3, [r0], #4 str r3, [r1], #4 bne copyex #if defined(config_s3c2400) defined(config_s3c2410) /* turn off the watchdog */ # if defined(config_s3c2400) # define pwtcon 0x # define INTMSK 0x /* Interupt-Controller base addresses */ # define CLKDIVN 0x /* clock divisor register */ #else # define pwtcon 0x # define INTMSK 0x4A /* Interupt-Controller base addresses */ # define INTSUBMSK 0x4A00001C # define CLKDIVN 0x4C /* clock divisor register */ # endif ldr r0, =pwtcon mov r1, #0x0 str r1, [r0] /* * mask all IRQs by setting all bits in the INTMR - default */ mov r1, #0xffffffff ldr r0, =INTMSK str r1, [r0] # if defined(config_s3c2410) ldr r1, =0x3ff ldr r0, =INTSUBMSK str r1, [r0] # endif /* FCLK:HCLK:PCLK = 1:2:4 */ /* default FCLK is 120 MHz! */ ldr r0, =CLKDIVN mov r1, #3 str r1, [r0] /* CONFIG_S3C2400 CONFIG_S3C2410 */ 系统时钟的寄存器地址定义关闭看门狗关闭所有中断设置时钟的分频比 /* * we do sys-critical inits only at reboot, * not when booting from ram! */ #ifndef CONFIG_SKIP_LOWLEVEL_INIT bl cpu_init_crit #ifndef CONFIG_SKIP_RELOCATE_UBOOT relocate: /* relocate U-Boot to RAM */ adr r0, _start /* r0 <- current position of code */ ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ cmp r0, r1 /* don't reloc during debug */ beq stack_setup ldr r2, _armboot_start ldr r3, _bss_start sub r2, r3, r2 /* r2 <- size of armboot */ add r2, r0, r2 /* r2 <- source end address */ copy_loop: ldmia r0!, {r3-r10 /* copy from source address [r0] */ stmia r1!, {r3-r10 /* copy to target address [r1] */ 跳入 cpu_init_crit, 这是一个系统初始化函数, 他还会调用 board/*/lowlevel_init.s 中的 lowlevel_init 函数 主要是对系统总线的初始化, 初始化了连接存储器的位宽 速度 刷新率等重要参数 经过这个函数的正确初始化,Nor Flash SDRAM 才可以被系统使用 下面的代码重定向就依赖 它 代码重定向, 它首先检测自己是否已经在内存中 : 如果是直接跳到下面的堆栈初始化代码 stack_setup 如果不是就将自己从 Nor Flash 中拷贝到内存中

48 cmp r0, r2 /* until source end addreee [r2] */ ble copy_loop 自拷贝循环 /* CONFIG_SKIP_RELOCATE_UBOOT */ 请注意看英文注释 /* Set up the stack */ stack_setup: ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */ sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */ 堆栈初始化代码 ( 为第二阶段的 C 语言做准 #ifdef CONFIG_USE_IRQ sub r0, r0, #(CONFIG_STACKSIZE_IRQCONFIG_STACKSIZE_FIQ) 备 ) sub sp, r0, #12 /* leave 3 words for abort-stack */ clear_bss: ldr r0, _bss_start /* find start of bss segment */ ldr r1, _bss_end /* stop here */ mov r2, #0x /* clear */ clbss_l:str r2, [r0] /* clear loop... */ add r0, r0, #4 cmp r0, r1 ble clbss_l ldr _start_armboot: pc, _start_armboot.word start_armboot /* ************************************************************************* * * CPU_init_critical registers * * setup important registers * setup memory timing * ************************************************************************* */ 对 BSS 段清零 ( 为第二阶段的 C 语言做准备 ) BSS 段 (bss segment) 通常是用来存放程序中未初始化的全局变量的一块内存区域 BSS 是英文 Block Started by Symbol 的简称 BSS 段属于静态内存分配 在编译时, 编译器已经为他们分配好了空间, 只不过他们的值为 0, 为了节省空间, 在 bin 或 ELF 文件中不占空间 编译器会计算出 _bss_start 和 _bss_end 的值, 不是定义的 跳入第二阶段的 C 语言代码入口 _start_armboot ( 已经被重定向到内存 ) #ifndef CONFIG_SKIP_LOWLEVEL_INIT cpu_init_crit: /* * flush v4 I/D caches */ mov r0, #0 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ /* * disable MMU stuff and caches */ mrc p15, 0, r0, c1, c0, 0 bic r0, r0, clear bits 13, 9:8 (--V- --RS) bic r0, r0, clear bits 7, 2:0 (B--- -CAM) orr r0, r0, set bit 2 (A) Align orr r0, r0, set bit 12 (I) I-Cache mcr p15, 0, r0, c1, c0, 0 前面所说的 cpu_init_crit 系统初始化函数 操作 CP15 协处理器, /* * before relocating, we have to setup RAM timing * because memory timing is board-dependend, you will * find a lowlevel_init.s in your board directory. */ mov ip, lr bl lowlevel_init mov lr, ip mov pc, lr /* CONFIG_SKIP_LOWLEVEL_INIT */... 调用 board/*/lowlevel_init.s 中的 lowlevel_init 函数, 对系统总线的初始化, 初始化了连接存储器的位宽 速度 刷新率等重要参数 经过

49 这个函数的正确初始化,Nor Flash SDRAM 才可以被系统使用 后面的代码略, 主要是中断相关代码, 但是 U- boot 基本不使用中断所以暂且略过 现在我们再来看看 lib_arm/board.c 中的第二阶段入口函数 start_armboot : void start_armboot (void) { init_fnc_t **init_fnc_ptr; char *s; #if defined(config_vfd) defined(config_lcd) unsigned long addr; /* Pointer is writable since we allocated a register for it */ gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t)); /* compiler optimization barrier needed for GCC >= 3.4 */ asm volatile ("": : :"memory"); gd_t 和 bd_t 这两个数据结构比较重要, 建议大家看看 分配一个存储全局数据的区域, 地址给指针 gd memset ((void*)gd, 0, sizeof (gd_t)); gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); memset (gd->bd, 0, sizeof (bd_t)); gd->flags = GD_FLG_RELOC; monitor_flash_len = _bss_start - _armboot_start; for (init_fnc_ptr = init_sequence; *init_fnc_ptr; init_fnc_ptr) { if ((*init_fnc_ptr)()!= 0) { hang (); /* armboot_start is defined in the board-specific linker script */ mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN, CONFIG_SYS_MALLOC_LEN); #ifndef CONFIG_SYS_NO_FLASH /* configure available FLASH banks */ display_flash_config (flash_init ()); /* CONFIG_SYS_NO_FLASH */ #ifdef CONFIG_VFD # ifndef PAGE_SIZE # define PAGE_SIZE 4096 # endif /* * reserve memory for VFD display (always full pages) */ /* bss_end is defined in the board-specific linker script */ addr = (_bss_end (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); vfd_setmem (addr); gd->fb_base = addr; /* CONFIG_VFD */ 全局数据的区清零给 gd->bd( 指针 ) 赋值 ( 在 gd 的前面 ) 并清零 gd->flags 赋值, 表示已经重定向 ( 在内存中 ) monitor_flash_len 为 u-boot 代码长度 初始化循环 : init_sequence 是一个初始化函数集的函数指针数组 ( 后面讲解 ) 如果有任何一个函数失败就进入死循环 这个始化函数集比较重要, 建议大家认真跟踪一下 初始化堆空间, 清零 初始化 Nor Flash 相关参数, 并显示其大小 初始化 VFD 存储区 (LCD 显示相关 ) #ifdef CONFIG_LCD /* board init may have inited fb_base */ if (!gd->fb_base) {

50 # ifndef PAGE_SIZE # define PAGE_SIZE 4096 # endif /* * reserve memory for LCD display (always full pages) */ /* bss_end is defined in the board-specific linker script */ addr = (_bss_end (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); lcd_setmem (addr); gd->fb_base = addr; /* CONFIG_LCD */ #if defined(config_cmd_nand) puts ("NAND: "); nand_init(); /* go init the NAND */ #if defined(config_cmd_onenand) onenand_init(); #ifdef CONFIG_HAS_DATAFLASH AT91F_DataflashInit(); dataflash_print_info(); /* initialize environment */ env_relocate (); #ifdef CONFIG_VFD /* must do this after the framebuffer is allocated */ drv_vfd_init(); /* CONFIG_VFD */ #ifdef CONFIG_SERIAL_MULTI serial_initialize(); /* IP Address */ gd->bd->bi_ip_addr = getenv_ipaddr ("ipaddr"); stdio_init (); /* get the devices list going. */ jumptable_init (); #if defined(config_api) /* Initialize API */ api_init (); console_init_r (); /* fully init console as a device */ #if defined(config_arch_misc_init) /* miscellaneous arch dependent initialisations */ arch_misc_init (); #if defined(config_misc_init_r) /* miscellaneous platform dependent initialisations */ misc_init_r (); 初始化 LCD 显存 初始化 Nand Flash 控制器, 并显示其容量大小 初始化 OneNand 初始化 DataFlash 初始化环境变量, 如果认为没有找到存储其中的, 就用默认值并打印 : *** Warning - bad CRC, using default environment 这是我们常看到的 初始化 VFD(LCD 显示相关 ) 初始化串口 从环境变量里获取 IP 地址 初始化标准输入输出设备 比如 : 串口 LCD 键盘等等 初始化全局数据表中的跳转表 gd- >jt 跳转表是一个函数指针数组, 定义了 u-boot 中基本的常用的函数库, gd->jt 是这个函数指针数组的首指针 初始化 API, 用于为 U-boot 编写的 应用程序 初始化 console, 平台无关, 不一定是串口哦, 如果把标准输出设为 vga, 字符会显示在 LCD 上 平台相关的其他初始化, 有的平台有

51 /* enable exceptions */ enable_interrupts (); 中断使能 ( 一般不使用, 很多平台此函数是空的 ) /* Perform network card initialisation if necessary */ #ifdef CONFIG_DRIVER_TI_EMAC /* XXX: this needs to be moved to board init */ extern void davinci_eth_set_mac_addr (const u_int8_t *addr); if (getenv ("ethaddr")) { uchar enetaddr[6]; eth_getenv_enetaddr("ethaddr", enetaddr); davinci_eth_set_mac_addr(enetaddr); #if defined(config_driver_smc91111) defined (CONFIG_DRIVER_LAN91C96) /* XXX: this needs to be moved to board init */ if (getenv ("ethaddr")) { uchar enetaddr[6]; eth_getenv_enetaddr("ethaddr", enetaddr); smc_set_mac_addr(enetaddr); /* CONFIG_DRIVER_SMC91111 CONFIG_DRIVER_LAN91C96 */ /* Initialize from environment */ if ((s = getenv ("loadaddr"))!= NULL) { load_addr = simple_strtoul (s, NULL, 16); #if defined(config_cmd_net) if ((s = getenv ("bootfile"))!= NULL) { copy_filename (BootFile, s, sizeof (BootFile)); #ifdef BOARD_LATE_INIT board_late_init (); #ifdef CONFIG_GENERIC_MMC puts ("MMC: "); mmc_initialize (gd->bd); #ifdef CONFIG_BITBANGMII bb_miiphy_init(); #if defined(config_cmd_net) #if defined(config_net_multi) puts ("Net: "); eth_initialize(gd->bd); #if defined(config_reset_phy_r) debug ("Reset Ethernet PHY\n"); reset_phy(); /* main_loop() can return to retry autoboot, if so just run it again. */ for (;;) { TI 芯片中的内置 MAC 初始化 ( 平台相关 ) 一种网卡芯片初始化 ( 平台相关 ) 获取 bootfile 参数 一些板级初始化 ( 有的板子有 ) SD 卡 /MMC 控制器初始化 MII 相关初始化 网卡初始化 进入主循环, 其中会读取 bootdelay 和 bootcmd 在 bootdelay 时间内按下键进入命令行, 否则执行 bootcmd 的命令

52 main_loop (); /* NOTREACHED - no way out of command loop except booting */ 标有红色的是比较重要的地方 大致的 U-boot 启动流程就简单介绍到这

53 第 6 章 U-boot 在 mini2440 上的移植 通过上面的叙述, 大家应该比较了解 U-boot 的大致情况, 下面开始移植工作了 我们要做的工作是移植, 就是根据不同的地方做修改 U-Boot 一直都没有支持 S3C2440, 移植仍是用 U-Boot 支持的友善之臂 SBC2410 的文件作蓝本来移植 所以移植所要做的就是针对 S3C2440 和 S3C2410 的不同, 以及 SBC2410 和 mini2440 开发板的外设不同作相应的修改, 并增加新的功能 移植之前必须对 S3C2440 和 S3C2410 有所了解, 移植过程和芯片关系紧密 特别是 Nandboot 的原理和 Norboot 的内部 ram 映射原理必须搞清楚 S3C2440 和 S3C2410 的区别主要是 2440 的主频更高, 接口方面, 增加了摄像头接口和 AC 97 音频接口 ; 寄存器方面, 除了新增模块的寄存器外, NAND FlASH 控制器的寄存器有较大的变化, 芯片时钟频率控制寄存器有一定的变化, 其他寄存器基本是兼容的 下面大部分以补丁的形式介绍移植过程 : 6.1 建立开发板文件, 测试编译环境 修改顶层 Makefile 目的 : 定义交叉编译工具链和开发板配置选项 diff -aurnp u-boot /makefile u-boot _tekkaman/makefile --- u-boot /makefile :20: u-boot _tekkaman/makefile :16: ,7 157,7 sinclude $(obj)include/autoconf.mk # load ARCH, BOARD, and CPU configuration include $(obj)include/config.mk export ARCH CPU BOARD VENDOR SOC - CROSS_COMPILE = arm-tekkaman-linux-gnueabi- # set default to nothing for native builds ifeq ($(HOSTARCH),$(ARCH)) CROSS_COMPILE?= -3046,6 3046,9 smdk2400_config : unconfig smdk2410_config : arm arm920t smdk2410 samsung s3c24x0

54 mini2440_config : arm arm920t mini2440 tekkamanninja s3c24x0 SX1_stdout_serial_config \ SX1_config: unconfig 开发板配置选项中各项的含义如下 : arm CPU 的架构 (ARCH) arm920t CPU 的类型 (CPU), 其对应于 cpu/arm920t 子目录 tekkamanninja 开发者 / 或经销商 (vender), 对应于 board/tekkamanninja 目录 mini2440 开发板的型号 (BOARD), 对应于 board/tekkamanninja/mini2440 目录 s3c24x0 片上系统 (SOC) 定义 在 /board 中建立 mini2440 目录和文件 在 /board 目录中建立开发板 mini2440 的目录, 并复制 sbc2410x 的文件到此, 做适当修改 目的 : 以 sbc2410x 为蓝本, 加快移植进度 由于上一步板子的 vender 中填了 tekkamanninja, 所以开发板 mini2440 目录一定要建在 /board 子目录中的 tekkamanninja 目录下, 否则编译出错 cd board mkdir -p tekkamanninja/mini2440 cp -arf sbc2410x/* tekkamanninja/mini2440/ cd tekkamanninja/mini2440/ mv sbc2410x.c mini2440.c 修改 mini2440 目录下的 Makefile 文件 ( 现在先不用动, 后面还会修改此文件 ): -25,7 25,7 include $(TOPDIR)/config.mk LIB = $(obj)lib$(board).a -COBJS := sbc2410x.o flash.o COBJS := mini2440.o flash.o SOBJS := lowlevel_init.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) 在 include/configs/ 中建立开发板配置文件 因为 sbc2410x 和 mini2440 最接近, 所以以 sbc2410x 的配置为蓝本 cp include/configs/sbc2410x.h include/configs/mini2440.h

55 6.1.4 测试编译环境 在 U-boot 源码的根目录下 : make mini2440_config Configuring for mini2440 board... make 可能出现的问题 : 如果出现 : (1) 配置出错 make mini2440_config Makefile:????: *** 遗漏分隔符 停止 请在 U-boot 的根目录下 Makefile arm arm920t mini2440 tekkamanninja s3c24x0 前加上 Tab 键, 这是 Makefile 的规则 : 所有命令都必须以 Tab 开头 (2) 如果编译时出现以下错误 ( 这是编译器的问题, 没出错就不要修改 ): uses hardware FP, whereas u-boot uses software FP 修正的方法 : diff -aurnp u-boot /cpu/arm920t/config.mk u-boot _tekkaman/cpu/arm920t/config.mk --- u-boot /cpu/arm920t/config.mk :20: u-boot _tekkaman/cpu/arm920t/config.mk :16: ,7 21,8 # MA USA # -PLATFORM_RELFLAGS = -fno-common -ffixed-r8 -msoft-float PLATFORM_RELFLAGS = -fno-common -ffixed-r8 #-msoft-float PLATFORM_CPPFLAGS = -march=armv4 # ========================================================================= 以上测试通过后, 说明编译环境和基本的开发板的代码创建都没有问题 现在编译出来的都是蓝本 SBC2410 的, 下面按照代码的执行流程来针对 mini2440 做修改 6.2 第一阶段 : 探索启动代码 首先进入 /cpu/arm920t/start.s

56 6.2.1 关闭为 AT9200 写的 LED 跳转 diff -aurnp u-boot /cpu/arm920t/start.s u-boot _tekkaman/cpu/arm920t/start.s --- u-boot /cpu/arm920t/start.s :20: u-boot _tekkaman/cpu/arm920t/start.s :16: ,8 114,8 start_code: orr r0, r0, #0xd3 msr cpsr, r0 - bl coloured_led_init - bl bl bl red_led_on #if defined(config_at91rm9200dk) defined(config_at91rm9200ek) /* 修改 CPU 频率初始化设置 2410 和 2440 相比一个不同的地方就是 PLL 的初始化参数不一样, 在数据手册可以查到 这里一开始就将频率升到 405MHz 其中还包括了中断掩码的修正 diff -aurnp u-boot /cpu/arm920t/start.s u-boot _tekkaman/cpu/arm920t/start.s --- u-boot /cpu/arm920t/start.s :20: u-boot _tekkaman/cpu/arm920t/start.s :16: ,7 131,7 copyex: bne copyex -#if defined(config_s3c2400) defined(config_s3c2410) #if defined(config_s3c2400) defined(config_s3c2410) defined(config_s3c2440) /* turn off the watchdog */ # if defined(config_s3c2400) -144,6 144,12 copyex: # define INTSUBMSK 0x4A00001C # define CLKDIVN 0x4C /* clock divisor register */ # endif #define CLK_CTL_BASE 0x4C /* tekkaman */ #define MDIV_405 0x7f << 12 /* tekkaman */ #define PSDIV_405 0x21 /* tekkaman */ #define MDIV_200 0xa1 << 12 /* tekkaman */ #define PSDIV_200 0x31 /* tekkaman */ ldr r0, =pwtcon mov r1, #0x0 -156,17 162,53 copyex: ldr r0, =INTMSK str r1, [r0] # if defined(config_s3c2410) - ldr r1, =0x3ff ldr r1, =0x7ff ldr r0, =INTSUBMSK str r1, [r0]

57 # endif #if defined(config_s3c2440) ldr r1, =0x7fff ldr r0, =INTSUBMSK str r1, [r0] #if defined(config_s3c2440) /* FCLK:HCLK:PCLK = 1:4:8 */ ldr r0, =CLKDIVN mov r1, #5 str r1, [r0] mrc p15, 0, r1, c1, c0, 0 orr r1, r1, #0xc mcr p15, 0, r1, c1, c0, 0 mov r1, #CLK_CTL_BASE mov r2, #MDIV_405 add r2, r2, #PSDIV_405 str r2, [r1, #0x04] /* MPLLCON tekkaman */ #else /* FCLK:HCLK:PCLK = 1:2:4 */ /* default FCLK is 120 MHz! */ ldr r0, =CLKDIVN mov r1, #3 str r1, [r0] - /* CONFIG_S3C2400 CONFIG_S3C2410 */ mrc p15, 0, r1, c1, c0, 0 orr r1, r1, #0xc mcr p15, 0, r1, c1, c0, 0 /*write ctrl register tekkaman*/ mov r1, #CLK_CTL_BASE /* tekkaman*/ mov r2, #MDIV_200 add r2, r2, #PSDIV_200 str r2, [r1, #0x04] /* CONFIG_S3C2400 CONFIG_S3C2410 CONFIG_S3C2440*/ /* * we do sys-critical inits only at reboot, 修改 lowlevel_init.s 文件 为了匹配 mini2440 的存储器配置 ( 总线上连接的 Nor Flash 和 SDRAM), 需要修改 lowlevel_init.s 文件 这个所连接的 Nor Flash 位数有关 至于 SDRAM 的参数, 可以从芯片手册查到 据说有人将其 64MB 的内存升到了 128MB, 其参数就是在这里修改的, 有需要可以看 MINI2440: Auto probe for SDRAM size

58 以下的 64MB 内存的参数修改 : diff -aurnp u-boot /board/sbc2410x/lowlevel_init.s u-boot _tekkaman/board/sbc2410x/lowlevel_init.S --- u-boot /board/sbc2410x/lowlevel_init.s :20: u-boot _tekkaman/board/sbc2410x/lowlevel_init.s :16: ,10 116,18 /* REFRESH parameter */ #define REFEN 0x1 /* Refresh enable */ #define TREFMD 0x0 /* CBR(CAS before RAS)/Auto refresh */ -#define Trp 0x0 /* 2clk */ #define Trc 0x3 /* 7clk */ #define Tchr 0x2 /* 3clk */ #if defined(config_s3c2440) #define Trp 0x2 /* 4clk */ #define REFCNT 1012 #else #define Trp 0x0 /* 2clk */ #define REFCNT 0x0459 /**************************************/ _TEXT_BASE: 在这个 lowlevel_init.s 有一个小 bug, 使得无法使用 OpenJTAG 下载到内存中直接运行, 修正如下 : diff -aurnp u-boot /board/sbc2410x/lowlevel_init.s u-boot _tekkaman/board/sbc2410x/lowlevel_init.S --- u-boot /board/sbc2410x/lowlevel_init.s :20: ,8 139,10 lowlevel_init: /* make r0 relative the current location so that it */ /* reads SMRDATA out of FLASH rather than memory! */ ldr r0, =SMRDATA - ldr r1, _TEXT_BASE ldr r1, =lowlevel_init sub r0, r0, r1 adr r3, lowlevel_init /* r3 <- current position of code */ add r0, r0, r3 ldr r1, =BWSCON /* Bus Width Status Controller */ add r2, r0, #13*4 0: 修改代码重定向部分 Tekkaman Ninja 从 开始就在启动时增加了启动时检测自身是否已经在 SDRAM 中 ( 通过 OpenJTAG 载入 ), 以及芯片是 Norboot 还是 Nandboot 的机制, 来决定代码重定向的方式, 使得编译出的 bin 文件可以同时烧入 Nand Flash 和 Nor flash, 以及被 OpenJTAG 载入进行调试 至于这部分的原理, 在 Tekkaman Ninja 的博客文章 在 U-boot 下实现自动识别启动 Flash 的原理 ( 针对 S3C24x0) 中有详细叙述

59 diff -aurnp u-boot /cpu/arm920t/start.s u-boot _tekkaman/cpu/arm920t/start.s --- u-boot /cpu/arm920t/start.s :20: u-boot _tekkaman/cpu/arm920t/start.s :16: ,13 218,189 copyex: bl cpu_init_crit -#ifndef CONFIG_SKIP_RELOCATE_UBOOT -relocate: /* relocate U-Boot to RAM */ /***************** CHECK_CODE_POSITION ******************************************/ adr r0, _start /* r0 <- current position of code */ ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ cmp r0, r1 /* don't reloc during debug */ beq stack_setup /***************** CHECK_CODE_POSITION ******************************************/ /***************** CHECK_BOOT_FLASH ******************************************/ ldr r1, =( (4<<28) (3<<4) (3<<2) ) /* address of Internal SRAM 0x C*/ mov r0, #0 /* r0 = 0 */ str r0, [r1] mov r1, #0x3c /* address of men 0x C*/ ldr r0, [r1] cmp r0, #0 bne relocate /* recovery */ ldr r0, =(0xdeadbeef) ldr r1, =( (4<<28) (3<<4) (3<<2) ) str r0, [r1] /***************** CHECK_BOOT_FLASH ******************************************/ /***************** NAND_BOOT *************************************************/ #define LENGTH_UBOOT 0x60000 #define NAND_CTL_BASE 0x4E #ifdef CONFIG_S3C2440 /* Offset */ #define onfconf 0x00 #define onfcont 0x04 #define onfcmd 0x08 #define onfstat reset NAND mov r1, #NAND_CTL_BASE ldr r2, =( (7<<12) (7<<8) (7<<4) (0<<0) ) str r2, [r1, #onfconf] ldr r2, [r1, #onfconf] ldr r2, =( (1<<4) (0<<1) (1<<0) Active low CE Control str r2, [r1, #onfcont] ldr r2, [r1, #onfcont] ldr r2, RnB Clear str r2, [r1, #onfstat] ldr r2, [r1, #onfstat] mov r2, RESET command

60 strb r2, [r1, #onfcmd] mov r3, wait nand1: add r3, r3, #0x1 cmp r3, #0xa blt nand1 nand2: ldr r2, [r1, wait ready tst r2, #0x4 beq nand2 ldr r2, [r1, #onfcont] orr r2, r2, Flash Memory Chip Disable str r2, [r1, get read to call C functions (for nand_read()) ldr sp, setup stack pointer mov fp, no previous frame, so copy U-Boot to RAM ldr r0, =TEXT_BASE mov r1, #0x0 mov r2, #LENGTH_UBOOT bl nand_read_ll tst r0, #0x0 beq ok_nand_read bad_nand_read: loop2: b infinite loop verify mov r0, #0 ldr r1, =TEXT_BASE mov r2, 4 bytes * 1024 = 4K-bytes go_next: ldr r3, [r0], #4 ldr r4, [r1], #4 teq r3, r4 bne notmatch subs r2, r2, #4 beq stack_setup bne go_next notmatch: loop3: b infinite loop #ifdef CONFIG_S3C2410 /* Offset */ #define onfconf 0x00 #define onfcmd 0x04 #define onfstat reset NAND

61 mov r1, #NAND_CTL_BASE ldr r2, initial value str r2, [r1, #onfconf] ldr r2, [r1, #onfconf] bic r2, r2, enable chip str r2, [r1, #onfconf] mov r2, RESET command strb r2, [r1, #onfcmd] mov r3, wait nand1: add r3, r3, #0x1 cmp r3, #0xa blt nand1 nand2: ldr r2, [r1, wait ready tst r2, #0x1 beq nand2 ldr r2, [r1, #onfconf] orr r2, r2, disable chip str r2, [r1, get read to call C functions (for nand_read()) ldr sp, setup stack pointer mov fp, no previous frame, so copy U-Boot to RAM ldr r0, =TEXT_BASE mov r1, #0x0 mov r2, #LENGTH_UBOOT bl nand_read_ll tst r0, #0x0 beq ok_nand_read bad_nand_read: loop2: b infinite loop verify mov r0, #0 ldr r1, =TEXT_BASE mov r2, 4 bytes * 1024 = 4K-bytes go_next: ldr r3, [r0], #4 ldr r4, [r1], #4 teq r3, r4 bne notmatch subs r2, r2, #4 beq stack_setup bne go_next notmatch: loop3: b infinite loop

62 /***************** NAND_BOOT *************************************************/ /***************** NOR_BOOT *************************************************/ relocate: /* relocate U-Boot to RAM */ /*********** CHECK_FOR_MAGIC_NUMBER***************/ ldr r1, =(0xdeadbeef) cmp r0, r1 bne loop3 /*********** CHECK_FOR_MAGIC_NUMBER***************/ adr r0, _start /* r0 <- current position of code */ ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ ldr r2, _armboot_start ldr r3, _bss_start sub r2, r3, r2 /* r2 <- size of armboot */ -193,7 411,7 copy_loop: stmia r1!, {r3-r10 /* copy to target address [r1] */ cmp r0, r2 /* until source end addreee [r2] */ ble copy_loop - /* CONFIG_SKIP_RELOCATE_UBOOT */ /***************** NOR_BOOT *************************************************/ /* Set up the stack */ stack_setup: 在上面添加的代码中有一个跳转 :bl nand_read_ll, 它跳入是新增的 C 语言文件 (board/tekkamanninja/mini2440/nand_read.c) 中的函数, 这个文件原本是用 vivi 的代码, 好来经过了 openmoko 的修改, 并支持不同的 Nand Flash 芯片, 我又多加了几个个芯片 ID 以支持所有 mini2440 的 Nand Flash 代码如下 : /* * nand_read.c: Simple NAND read functions for booting from NAND * * This is used by cpu/arm920/start.s assembler code, * and the board-specific linker script must make sure this * file is linked within the first 4kB of NAND flash. * * Taken from GPLv2 licensed vivi bootloader, * Copyright (C) 2002 MIZI Research, Inc. * * Author: Hwang, Chideok * Date : $Date: 2004/02/04 10:37:37 $ * * u-boot integration and bad-block skipping (C) 2006 by OpenMoko, Inc. * Author: Harald Welte */ #include <common.h> #include <linux/mtd/nand.h> #define REGb(x) (*(volatile unsigned char *)(x)) #define REGw(x) (*(volatile unsigned short *)(x)) #define REGi(x) (*(volatile unsigned int *)(x)) #define NF_BASE 0x4e #if defined(config_s3c2410) #define NFCONF REGi(NF_BASE 0x0) #define NFCMD REGb(NF_BASE 0x4)

63 #define NFADDR REGb(NF_BASE 0x8) #define NFDATA REGb(NF_BASE 0xc) #define NFSTAT REGb(NF_BASE 0x10) #define NFSTAT_BUSY 1 #define nand_select() (NFCONF &= ~0x800) #define nand_deselect() (NFCONF = 0x800) #define nand_clear_rnb() do { while (0) #elif defined(config_s3c2440) defined(config_s3c2442) #define NFCONF REGi(NF_BASE 0x0) #define NFCONT REGi(NF_BASE 0x4) #define NFCMD REGb(NF_BASE 0x8) #define NFADDR REGb(NF_BASE 0xc) #define NFDATA REGb(NF_BASE 0x10) #define NFDATA16 REGw(NF_BASE 0x10) #define NFSTAT REGb(NF_BASE 0x20) #define NFSTAT_BUSY 1 #define nand_select() (NFCONT &= ~(1 << 1)) #define nand_deselect() (NFCONT = (1 << 1)) #define nand_clear_rnb() (NFSTAT = (1 << 2)) static inline void nand_wait(void) { int i; while (!(NFSTAT & NFSTAT_BUSY)) for (i=0; i<10; i); struct boot_nand_t { int page_size; int block_size; int bad_block_offset; // unsigned long size; ; #if 0 #if defined(config_s3c2410) defined(config_mini2440) /* configuration for 2410 with 512byte sized flash */ #define NAND_PAGE_SIZE 512 #define BAD_BLOCK_OFFSET 5 #define NAND_BLOCK_MASK (NAND_PAGE_SIZE - 1) #define NAND_BLOCK_SIZE 0x4000 #else /* configuration for 2440 with 2048byte sized flash */ #define NAND_5_ADDR_CYCLE #define NAND_PAGE_SIZE 2048 #define BAD_BLOCK_OFFSET NAND_PAGE_SIZE #define NAND_BLOCK_MASK (NAND_PAGE_SIZE - 1) #define NAND_BLOCK_SIZE (NAND_PAGE_SIZE * 64) /* compile time failure in case of an invalid configuration */ #if defined(config_s3c2410) && (NAND_PAGE_SIZE!= 512) #error "S3C2410 does not support nand page size!= 512" static int is_bad_block(struct boot_nand_t * nand, unsigned long i) {

64 unsigned char data; unsigned long page_num; nand_clear_rnb(); if (nand->page_size == 512) { NFCMD = NAND_CMD_READOOB; /* 0x50 */ NFADDR = nand->bad_block_offset & 0xf; NFADDR = (i >> 9) & 0xff; NFADDR = (i >> 17) & 0xff; NFADDR = (i >> 25) & 0xff; else if (nand->page_size == 2048) { page_num = i >> 11; /* addr / 2048 */ NFCMD = NAND_CMD_READ0; NFADDR = nand->bad_block_offset & 0xff; NFADDR = (nand->bad_block_offset >> 8) & 0xff; NFADDR = page_num & 0xff; NFADDR = (page_num >> 8) & 0xff; NFADDR = (page_num >> 16) & 0xff; NFCMD = NAND_CMD_READSTART; else { return -1; nand_wait(); data = (NFDATA & 0xff); if (data!= 0xff) return 1; return 0; static int nand_read_page_ll(struct boot_nand_t * nand, unsigned char *buf, unsigned long addr) { unsigned short *ptr16 = (unsigned short *)buf; unsigned int i, page_num; nand_clear_rnb(); NFCMD = NAND_CMD_READ0; if (nand->page_size == 512) { /* Write Address */ NFADDR = addr & 0xff; NFADDR = (addr >> 9) & 0xff; NFADDR = (addr >> 17) & 0xff; NFADDR = (addr >> 25) & 0xff; else if (nand->page_size == 2048) { page_num = addr >> 11; /* addr / 2048 */ /* Write Address */ NFADDR = 0; NFADDR = 0; NFADDR = page_num & 0xff; NFADDR = (page_num >> 8) & 0xff; NFADDR = (page_num >> 16) & 0xff; NFCMD = NAND_CMD_READSTART; else { return -1; nand_wait(); #if defined(config_s3c2410)

65 for (i = 0; i < nand->page_size; i) { *buf = (NFDATA & 0xff); buf; #elif defined(config_s3c2440) defined(config_s3c2442) for (i = 0; i < (nand->page_size>>1); i) { *ptr16 = NFDATA16; ptr16; return nand->page_size; static unsigned short nand_read_id() { unsigned short res = 0; NFCMD = NAND_CMD_READID; NFADDR = 0; res = NFDATA; res = (res << 8) NFDATA; return res; extern unsigned int dynpart_size[]; /* low level nand read function */ int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size) { int i, j; unsigned short nand_id; struct boot_nand_t nand; /* chip Enable */ nand_select(); nand_clear_rnb(); for (i = 0; i < 10; i) ; nand_id = nand_read_id(); if (0) { /* dirty little hack to detect if nand id is misread */ unsigned short * nid = (unsigned short *)0x31fffff0; *nid = nand_id; if (nand_id == 0xec76 /* Samsung K91208 */ nand_id == 0xad76 ) { /*Hynix HY27US08121A*/ nand.page_size = 512; nand.block_size = 16 * 1024; nand.bad_block_offset = 5; // nand.size = 0x ; else if (nand_id == 0xecf1 /* Samsung K9F1G08U0B */ nand_id == 0xecda /* Samsung K9F2G08U0B */ nand_id == 0xecd3 ) { /* Samsung K9K8G08 */ nand.page_size = 2048; nand.block_size = 128 * 1024; nand.bad_block_offset = nand.page_size; // nand.size = 0x ; else { return -1; // hang

66 if ((start_addr & (nand.block_size-1)) (size & ((nand.block_size-1)))) return -1; /* invalid alignment */ for (i=start_addr; i < (start_addr size);) { #ifdef CONFIG_S3C2410_NAND_SKIP_BAD if (i & (nand.block_size-1)== 0) { if (is_bad_block(&nand, i) is_bad_block(&nand, i nand.page_size)) { /* Bad block */ i = nand.block_size; size = nand.block_size; continue; j = nand_read_page_ll(&nand, buf, i); i = j; buf = j; /* chip Disable */ nand_deselect(); return 0; 在添加了这个文件之后, 记得要在 Makefile 里加上对这个文件的编译 diff -aurnp u-boot /board/sbc2410x/makefile u-boot _tekkaman/board/sbc2410x/makefile --- u-boot /board/sbc2410x/makefile :20: u-boot _tekkaman/board/sbc2410x/makefile :16: ,7 25,7 include $(TOPDIR)/config.mk LIB = $(obj)lib$(board).a -COBJS := sbc2410x.o flash.o COBJS := nand_read.o mini2440.o flash.o SOBJS := lowlevel_init.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) 增加 LED 的点亮操作 作用是显示代码进度, 对 Debug 有帮助 代码在跳转到第二阶段代码 start_armboot 函数前会亮起一个 LED 灯 ( 还记得前面有调用 C 语言的 nand_read_ll 函数吧, 初始化堆栈的定义就在此 ) diff -aurnp u-boot /cpu/arm920t/start.s u-boot _tekkaman/cpu/arm920t/start.s --- u-boot /cpu/arm920t/start.s :20: u-boot _tekkaman/cpu/arm920t/start.s :16: ,8 435,29 clbss_l:str r2, [r0] /* clear loop... ldr pc, _start_armboot

67 -_start_armboot:.word start_armboot #if defined(config_mini2440_led) #define GPIO_CTL_BASE 0x #define ogpio_b 0x10 #define ogpio_con 0x0 /* R/W, Configures the pins of the port */ #define ogpio_dat 0x4 #define ogpio_up 0x8 /* R/W, Pull-up disable register */ mov r1, #GPIO_CTL_BASE add r1, r1, #ogpio_b ldr r2, =0x str r2, [r1, #ogpio_con] mov r2, #0xff str r2, [r1, #ogpio_up] ldr r2, =0x1c1 str r2, [r1, #ogpio_dat] _start_armboot:.word start_armboot #define STACK_BASE 0x33f00000 #define STACK_SIZE 0x10000.align 2 DW_STACK_START:.word STACK_BASESTACK_SIZE-4 /* ************************************************************************* 到这里, 启动的第一阶段就修改完了, 但是在 U-boot 之后, 这些本应放在 bin 文件前 4K 的代码会被放到后面, 以至启动失败 所以必须手动修改链接时使用的.lds 文件, 使得这些代码被放在 bin 文件的最前面 : diff -aurnp u-boot /cpu/arm920t/u-boot.lds u-boot _tekkaman/cpu/arm920t/u-boot.lds --- u-boot /cpu/arm920t/u-boot.lds :20: u-boot _tekkaman/cpu/arm920t/u-boot.lds :16: ,6 40,8 SECTIONS.text : { cpu/arm920t/start.o (.text) board/tekkamanninja/mini2440/lowlevel_init.o (.text) board/tekkamanninja/mini2440/nand_read.o (.text) *(.text) 6.3 第二阶段 : 修改初始化代码 代码运行到了第二阶段代码 lib_arm/board.c 中的 start_armboot 函数, 开始了系统的全面初始化

68 6.3.1 修改 lib_arm/board.c 文件 这个文件的修改主要是关闭为 AT9200 写的代码, 增加 LED 的点亮, 在初始化 console 后和进入命令行之前各点亮一个 LED(3 4)( 第二个 LED 的点亮在其中的 board_init 函数中 ), 增加打印信息 (for LCD console) diff -aurnp u-boot /lib_arm/board.c u-boot _tekkaman/lib_arm/board.c --- u-boot /lib_arm/board.c :20: u-boot _tekkaman/lib_arm/board.c :16: ,6 49,7 #include <nand.h> #include <onenand_uboot.h> #include <mmc.h> #include <s3c2410.h> //tekkamanninja for LED #ifdef CONFIG_BITBANGMII #include <miiphy.h> -86,7 87,7 extern void rtl8019_get_enetaddr (uchar #include <i2c.h> - #if 0 /************************************************************************ * Coloured LED functionality ************************************************************************ -110,6 111,7 void inline blue_led_on(void) { void blue_led_on(void) attribute ((weak, alias(" blue_led_on"))); void inline blue_led_off(void) { void blue_led_off(void) attribute ((weak, alias(" blue_led_off"))); /************************************************************************ * Init Utilities * -135,7 137,13 static int init_baudrate (void) static int display_banner (void) { - printf ("\n\n%s\n\n", version_string); #if defined(config_mini2440_led) struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio(); gpio->gpbdat = 0x101; //tekkamanninja printf ("\n\n%s\n\n", version_string); printf (" modified by tekkamanninja printf (" Love Linux forever!!\n\n"); debug ("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n", _armboot_start, _bss_start, _bss_end); #ifdef CONFIG_MODEM_SUPPORT -272,7 280,9 void start_armboot (void) #if defined(config_vfd) defined(config_lcd) unsigned long addr; - #if defined(config_mini2440_led) struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();

69 /* Pointer is writable since we allocated a register for it */ gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t)); /* compiler optimization barrier needed for GCC >= 3.4 */ -434,6 444,15 extern void davinci_eth_set_mac_addr (co reset_phy(); #if defined(config_mini2440_led) gpio->gpbdat = 0x0; //tekkamanninja #if defined(config_cfb_console) printf ("%s\n", version_string); printf ("modified by printf ("Love Linux forever!!\n"); /* main_loop() can return to retry autoboot, if so just run it again. */ for (;;) { main_loop (); 大家可以看到 lib_arm/board.c 中的 start_armboot 函数中调用了很多初始化函数, 这些函数分布在不同的文件中, 后面会分别来修改 修改 board/tekkamanninja/mini2440/mini2440.c 文件 这个文件负责板级初始化的任务, 修改的地方主要包括 : 增加 LCD 初始化函数 修改 GPIO 设置 ( 这个和开发板的外设连接有关, 比如 LCD 和 LED) LED 的点亮 ( 第二个 ) 屏蔽已不使用的 Nand 控制器初始化代码, 还有添加网卡芯片 (DM9000) 的初始化函数 diff -aurnp u-boot /board/sbc2410x/sbc2410x.c u-boot _tekkaman/ board/tekkamanninja/mini2440/mini2440.c --- u-boot /board/sbc2410x/sbc2410x.c :20: u-boot _tekkaman/board/tekkamanninja/mini2440/mini2440.c :16: ,6 31,7 #include <common.h> #include <netdev.h> #include <s3c2410.h> #include <video_fb.h> #if defined(config_cmd_nand) #include <linux/mtd/nand.h> -45,9 46,20 DECLARE_GLOBAL_DATA_PTR; #define M_PDIV 0x4 #define M_SDIV 0x1 #elif FCLK_SPEED==1 /* Fout = 202.8MHz */ -#define M_MDIV 0x5c -#define M_PDIV 0x4 -#define M_SDIV 0x0 #if defined(config_s3c2410) /* Fout = 202.8MHz */ #define M_MDIV 0xA1 #define M_PDIV 0x3 #define M_SDIV 0x1

70 #if defined(config_s3c2440) /* Fout = 405MHz */ #define M_MDIV 0x7f #define M_PDIV 0x2 #define M_SDIV 0x1 #define USB_CLOCK 1 -57,8 69,17 DECLARE_GLOBAL_DATA_PTR; #define U_M_PDIV 0x3 #define U_M_SDIV 0x1 #elif USB_CLOCK==1 #if defined(config_s3c2410) #define U_M_MDIV 0x48 #define U_M_PDIV 0x3 #if defined(config_s3c2440) #define U_M_MDIV 0x38 #define U_M_PDIV 0x2 #define U_M_SDIV 0x2 -96,13 117,21 int board_init (void) /* set up the I/O ports */ gpio->gpacon = 0x007FFFFF; #if defined(config_mini2440) gpio->gpbcon = 0x ; #else gpio->gpbcon = 0x ; gpio->gpbup = 0x000007FF; gpio->gpccon = 0xAAAAAAAA; - gpio->gpcup = 0x0000FFFF; gpio->gpcup = 0xFFFFFFFF; gpio->gpdcon = 0xAAAAAAAA; - gpio->gpdup = 0x0000FFFF; - gpio->gpecon = 0xAAAAAAAA; gpio->gpdup = 0xFFFFFFFF; gpio->gpecon = 0xAAAAAAAA; gpio->gpeup = 0x0000FFFF; gpio->gpfcon = 0x000055AA; gpio->gpfup = 0x000000FF; -115,18 144,82 int board_init (void) gpio->extint1=0x ; gpio->extint2=0x ; #if defined(config_s3c2410) /* arch number of SMDK2410-Board */

71 gd->bd->bi_arch_number = MACH_TYPE_SMDK2410; #if defined(config_s3c2440) /* arch number of S3C2440-Board */ gd->bd->bi_arch_number = MACH_TYPE_MINI2440 ; /* adress of boot parameters */ gd->bd->bi_boot_params = 0x ; icache_enable(); dcache_enable(); - #if defined(config_mini2440_led) gpio->gpbdat = 0x ; return 0; #define MVAL (0) #define MVAL_USED (0) //0=each frame 1=rate by MVAL #define INVVDEN (1) //0=normal 1=inverted #define BSWP (0) //Byte swap control #define HWSWP (1) //Half word swap control //TFT #define LCD_XSIZE_TFT_ (240) #define LCD_YSIZE_TFT_ (320) //TFT #define HOZVAL_TFT_ (LCD_XSIZE_TFT_ ) #define LINEVAL_TFT_ (LCD_YSIZE_TFT_ ) //Timing parameter for NEC3.5" #define VBPD_ (3) #define VFPD_ (10) #define VSPW_ (1) #define HBPD_ (5) #define HFPD_ (2) #define HSPW_240320_NEC (36) //Adjust the horizontal displacement of the screen #define HSPW_240320_TD (23) //64MB nand mini2440 is 36,128MB is 23 // : --> - : <-- #define CLKVAL_TFT_ (3) //FCLK=101.25MHz,HCLK=50.625MHz,VCLK=6.33MHz void board_video_init(graphicdevice *pgd) { struct s3c24x0_lcd * const lcd = s3c24x0_get_base_lcd(); struct s3c2410_nand * const nand = s3c2410_get_base_nand(); /* FIXME: select LCM type by env variable */ /* Configuration for GTA01 LCM on QT2410 */

72 lcd->lcdcon1 = 0x ; /* CLKVAL=4, BPPMODE=16bpp, TFT, ENVID=0 */ lcd->lcdcon2 = (VBPD_240320<<24) (LINEVAL_TFT_240320<<14) (VFPD_240320<<6) (VSPW_240320); lcd->lcdcon3 = (HBPD_240320<<19) (HOZVAL_TFT_240320<<8) (HFPD_240320); if ( (nand->nfconf) & 0x08 ) { lcd->lcdcon4 = (MVAL<<8) (HSPW_240320_TD); else { lcd->lcdcon4 = (MVAL<<8) (HSPW_240320_NEC); lcd->lcdcon5 = 0x00000f09; lcd->lpcsel = 0x ; int dram_init (void) { gd->bd->bi_dram[0].start = PHYS_SDRAM_1; -135,6 228,7 int dram_init (void) return 0; #if 0 #if defined(config_cmd_nand) extern ulong nand_probe(ulong physadr); -180,6 274,7 void nand_init(void) printf ("%4lu MB\n", nand_probe((ulong)nand) >> 20); #ifdef CONFIG_CMD_NET int board_eth_init(bd_t *bis) -188,6 283,9 int board_eth_init(bd_t *bis) #ifdef CONFIG_CS8900 rc = cs8900_initialize(0, CONFIG_CS8900_BASE); #ifdef CONFIG_DRIVER_DM9000 rc = dm9000_initialize(bis); return rc; 到这里第二阶段的初始化的主线代码就修改完了, 下面是各子系统的初始化和功能代码的修改

73 6.4 第三阶段 : 完善目标板外设驱动 Nand Flash 相关代码的修改 在 U-boot 启动的第一阶段, 初始化了 Nand Flash 控制器 但到第二阶段 start_armboot 函数还是会再次初始化 Nand Flash 控制器 因为第二阶段和第一阶段的代码基本是独立的, 第一阶段的代码基本只起到代码重定位的作用, 到了第二阶段才是真正 U-boot 的开始, 以前的初始化过程还会重做一遍, 比如始化 Nand Flash 控制器 CPU 频率等 因为 S3C2440 和 S3C2410 之间的很大差别就是 :S3C2410 的 Nand Flash 控制器只支持 512B16B 的 Nand Flash, 而 S3C2440 还支持 2KB64B 的大容量 Nand Flash 所以在 Nand Flash 控制器上寄存器和控制流程上的差别很明显, 底层驱动代码的修改也是必须的 具体的差别还是需要对比芯片数据手册的, 下面是关于 Nand Flash 底层驱动代码的修改 : diff -aurnp u-boot /drivers/mtd/nand/s3c2410_nand.c u-boot _tekkaman/drivers/mtd/nand/s3c2410_nand.c --- u-boot /drivers/mtd/nand/s3c2410_nand.c :20: u-boot _tekkaman/drivers/mtd/nand/s3c2410_nand.c :16: ,6 24,9 #include <s3c2410.h> #include <asm/io.h> #define NF_BASE 0x4e #if defined(config_s3c2410) #define S3C2410_NFCONF_EN (1<<15) #define S3C2410_NFCONF_512BYTE (1<<14) #define S3C2410_NFCONF_4STEP (1<<13) -35,24 38,41 #define S3C2410_ADDR_NALE 4 #define S3C2410_ADDR_NCLE 8 #if defined(config_s3c2440) #define S3C2410_NFCONT_EN (1<<0) #define S3C2410_NFCONT_INITECC (1<<4) #define S3C2410_NFCONT_nFCE (1<<1) #define S3C2410_NFCONT_MAINECCLOCK (1<<5) #define S3C2410_NFCONF_TACLS(x) ((x)<<12) #define S3C2410_NFCONF_TWRPH0(x) ((x)<<8) #define S3C2410_NFCONF_TWRPH1(x) ((x)<<4) #define S3C2410_ADDR_NALE 0x08 #define S3C2410_ADDR_NCLE 0x0c ulong IO_ADDR_W = NF_BASE; static void s3c2410_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - struct nand_chip *chip = mtd->priv; // struct nand_chip *chip = mtd->priv;

74 struct s3c2410_nand *nand = s3c2410_get_base_nand(); debugx(1, "hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl); if (ctrl & NAND_CTRL_CHANGE) { - ulong IO_ADDR_W = (ulong)nand; IO_ADDR_W = (ulong)nand; if (!(ctrl & NAND_CLE)) IO_ADDR_W = S3C2410_ADDR_NCLE; if (!(ctrl & NAND_ALE)) IO_ADDR_W = S3C2410_ADDR_NALE; - chip->io_addr_w = (void *)IO_ADDR_W; // chip->io_addr_w = (void *)IO_ADDR_W; #if defined(config_s3c2410) if (ctrl & NAND_NCE) writel(readl(&nand->nfconf) & ~S3C2410_NFCONF_nFCE, &nand->nfconf); -60,9 80,19 static void s3c2410_hwcontrol(struct mtd writel(readl(&nand->nfconf) S3C2410_NFCONF_nFCE, &nand->nfconf); #if defined(config_s3c2440) if (ctrl & NAND_NCE) writel(readl(&nand->nfcont) & ~S3C2410_NFCONT_nFCE, &nand->nfcont); else writel(readl(&nand->nfcont) S3C2410_NFCONT_nFCE, &nand->nfcont); if (cmd!= NAND_CMD_NONE) - writeb(cmd, chip->io_addr_w); writeb(cmd, (void *)IO_ADDR_W); static int s3c2410_dev_ready(struct mtd_info *mtd) -77,7 107,13 void s3c2410_nand_enable_hwecc(struct mt { struct s3c2410_nand *nand = s3c2410_get_base_nand(); debugx(1, "s3c2410_nand_enable_hwecc(%p, %d)\n", mtd, mode); #if defined(config_s3c2410) writel(readl(&nand->nfconf) S3C2410_NFCONF_INITECC, &nand->nfconf); #if defined(config_s3c2440) writel(readl(&nand->nfcont) S3C2410_NFCONT_INITECC, &nand->nfcont); static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, -116,6 152,7 int board_nand_init(struct nand_chip *na writel(readl(&clk_power->clkcon) (1 << 4), &clk_power->clkcon); #if defined(config_s3c2410)

75 /* initialize hardware */ twrph0 = 3; twrph1 = 0; -129,7 166,24 int board_nand_init(struct nand_chip *na /* initialize nand_chip data structure */ nand->io_addr_r = nand->io_addr_w = (void *)&nand_reg->nfdata; #if defined(config_s3c2440) twrph0 = 4; twrph1 = 2; tacls = 0; cfg = 0; cfg = S3C2410_NFCONF_TACLS(tacls - 1); cfg = S3C2410_NFCONF_TWRPH0(twrph0-1); cfg = S3C2410_NFCONF_TWRPH1(twrph1-1); writel(cfg, &nand_reg->nfconf); cfg = (0<<13) (0<<12) (0<<10) (0<<9) (0<<8) (0<<6) (0<<5) (1<<4) (0<<1) (1<<0); writel(cfg, &nand_reg->nfcont); /* initialize nand_chip data structure */ nand->io_addr_r = nand->io_addr_w = (void *)&nand_reg->nfdata; /* read_buf and write_buf are default */ /* read_byte and write_byte are default */ 添加 Yaffs(2) 镜像烧写功能 修改好了 Nand Flash 驱动, 接下来修改相关的 Yaffs(2) 映像烧写代码, 由于现在很多使用 Nand Flash 的系统, 在 Linux 下都用 Yaffs(2) 作为存储数据的文件系统, 甚至是根文件系统 所以在 BootLoader 下能够烧写 Yaffs(2) 映像文件变得很必要 对于 Yaffs(2) 映像烧写的支持其实就是在烧写时, 写入数据的同时, 将镜像文件中的 oob 数据也写入到 Nand Flash 的 Spare 区 这和 Yaffs 文件系统原理以及 Nand Flash 的结构有关, 请参考相关资料 下面是需要修改的 4 个文件的补丁 : diff -aurnp u-boot /common/cmd_nand.c u-boot _tekkaman/common/cmd_nand.c --- u-boot /common/cmd_nand.c :20: u-boot _tekkaman/common/cmd_nand.c :16: ,6 389,25 int do_nand(cmd_tbl_t * cmdtp, int flag, else ret = nand_write_skip_bad(nand, off, &size, (u_char *)addr); #if defined(enable_cmd_nand_yaffs) else if ( s!= NULL && (!strcmp(s, ".yaffs")!strcmp(s, ".yaffs1"))){ if(read) { printf("nand read.yaffs[1] is not provide temporarily!"); else { nand->rw_oob = 1; #if defined(enable_cmd_nand_yaffs_skipfb)

76 nand->skipfirstblk = 1; #else nand->skipfirstblk = 0; ret = nand_write_skip_bad(nand,off,&size,(u_char *)addr); #if defined(enable_cmd_nand_yaffs_skipfb) nand->skipfirstblk = 0; nand->rw_oob = 0; else if (!strcmp(s, ".oob")) { /* out-of-band data */ mtd_oob_ops_t ops = { -496,6 515,11 U_BOOT_CMD(nand, CONFIG_SYS_MAXARGS, 1, " to/from memory address 'addr', skipping bad blocks.\n" "nand erase [clean] [off size] - erase 'size' bytes from\n" " offset 'off' (entire device if not specified)\n" #if defined(enable_cmd_nand_yaffs) "nand read[.yaffs[1]] is not provide temporarily!\n" "nand write[.yaffs[1]] addr off size - write the `size' byte yaffs image starting\n" " at offset `off' from memory address `addr' (.yaffs1 for NAND)\n" "nand bad - show bad blocks\n" "nand dump[.oob] off - dump page\n" "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n" diff -aurnp u-boot /drivers/mtd/nand/nand_base.c u-boot _tekkaman/drivers/mtd/nand/nand_base.c --- u-boot /drivers/mtd/nand/nand_base.c :20: u-boot _tekkaman/drivers/mtd/nand/nand_base.c :16: ,7 2008,30 static int nand_write(struct mtd_info *m { struct nand_chip *chip = mtd->priv; int ret; - #if defined(enable_cmd_nand_yaffs) /*Thanks for hugerat's code!*/ int oldopsmode = 0; if(mtd->rw_oob==1) { size_t oobsize = mtd->oobsize; size_t datasize = mtd->writesize; int i = 0; uint8_t oobtemp[oobsize]; int datapages = 0; datapages = len/(datasize); for(i=0;i<(datapages);i) { memcpy((void *)oobtemp, (void *)(bufdatasize*(i1)), oobsize); memmove((void *)(bufdatasize*(i1)), (void *)(bufdatasize*(i1)oobsize), (datapages-(i1))*(datasize)(datapages-1)*oobsize); memcpy((void *)(buf(datapages)*(datasizeoobsize)-oobsize), (void *)(oobtemp), oobsize);

77 /* Do not allow reads past end of device */ if ((to len) > mtd->size) return -EINVAL; -2019, ,30 static int nand_write(struct mtd_info *m chip->ops.len = len; chip->ops.datbuf = (uint8_t *)buf; - chip->ops.oobbuf = NULL; #if defined(enable_cmd_nand_yaffs) /*Thanks for hugerat's code!*/ if(mtd->rw_oob!=1) { chip->ops.oobbuf = NULL; else { chip->ops.oobbuf = (uint8_t *)(buflen); // chip->ops.ooblen = mtd->oobsize; oldopsmode = chip->ops.mode; chip->ops.mode = MTD_OOB_RAW; // #else chip->ops.oobbuf = NULL; ret = nand_do_write_ops(mtd, to, &chip->ops); *retlen = chip->ops.retlen; nand_release_device(mtd); #if defined(enable_cmd_nand_yaffs) /*Thanks for hugerat's code!*/ chip->ops.mode = oldopsmode; // return ret; diff -aurnp u-boot /drivers/mtd/nand/nand_util.c u-boot _tekkaman/drivers/mtd/nand/nand_util.c --- u-boot /drivers/mtd/nand/nand_util.c :20: u-boot _tekkaman/drivers/mtd/nand/nand_util.c :16: ,6 480,26 int nand_write_skip_bad(nand_info_t *nan size_t left_to_write = *length; size_t len_incl_bad; u_char *p_buffer = buffer; #if defined(enable_cmd_nand_yaffs) /*Thanks for hugerat's code*/ if(nand->rw_oob==1) { size_t oobsize = nand->oobsize; size_t datasize = nand->writesize; int datapages = 0; if (((*length)%(nand->oobsizenand->writesize))!= 0) { printf ("Attempt to write error length data!\n"); return -EINVAL; datapages = *length/(datasizeoobsize); *length = datapages*datasize;

78 left_to_write = *length; // nand->skipfirstblock=1; /* Reject writes, which are not page aligned */ if ((offset & (nand->writesize - 1))!= ,7 514,9 int nand_write_skip_bad(nand_info_t *nan printf ("Attempt to write outside the flash area\n"); return -EINVAL; - #if!defined(enable_cmd_nand_yaffs) /*by hugerat*/ if (len_incl_bad == *length) { rval = nand_write (nand, offset, length, buffer); if (rval!= 0) -503,7 525,7 int nand_write_skip_bad(nand_info_t *nan return rval; - while (left_to_write > 0) { size_t block_offset = offset & (nand->erasesize - 1); size_t write_size; -516,12 538,21 int nand_write_skip_bad(nand_info_t *nan offset = nand->erasesize - block_offset; continue; - #if defined(enable_cmd_nand_yaffs) /*Thanks for hugerat's code*/ if(nand->skipfirstblk==1) { nand->skipfirstblk=0; printf ("Skip the first good block %llx\n", offset & ~(nand->erasesize - 1)); offset = nand->erasesize - block_offset; continue; if (left_to_write < (nand->erasesize - block_offset)) write_size = left_to_write; else write_size = nand->erasesize - block_offset; - printf("\rwriting at 0x%llx -- ",offset); /*Thanks for hugerat's code*/ rval = nand_write (nand, offset, &write_size, p_buffer); if (rval!= 0) { printf ("NAND write to offset %llx failed %d\n", -531,8 562,18 int nand_write_skip_bad(nand_info_t *nan left_to_write -= write_size; printf("%d%% is complete.",100-(left_to_write/(*length/100)));/*thanks for hugerat's code*/ offset = write_size; #if defined(enable_cmd_nand_yaffs) /*Thanks for hugerat's code*/ if(nand->rw_oob==1) {

79 p_buffer = write_size(write_size/nand->writesize*nand->oobsize); else { p_buffer = write_size; #else p_buffer = write_size; return 0; diff -aurnp u-boot /include/linux/mtd/mtd.h u-boot _tekkaman/include/linux/mtd/mtd.h --- u-boot /include/linux/mtd/mtd.h :20: u-boot _tekkaman/include/linux/mtd/mtd.h :16: ,6 129,12 struct mtd_info { */ u_int32_t writesize; #if defined(enable_cmd_nand_yaffs) /*Thanks for hugerat's code*/ u_char rw_oob; u_char skipfirstblk; u_int32_t oobsize; /* Amount of OOB data per block (e.g. 16) */ u_int32_t oobavail; /* Available OOB bytes per block */ 修改 Nor Flash 写入功能的代码 在虽然 S3C2440 和 S3C2410 对于 Nor Flash 的链接都是一样的, 但是 SBC2410 使用的 AMD 的 Nor Flash 芯片, 而 mini2440 使用的 SST 的 Nor Flash 这两款芯片在写入时所使用的块大小 时序和指令代码有差别, 所以必须根据芯片的数据手册进行修改 主要的差别请看数据手册的对比 : SST39VF1601:

80 Am29LV160: 除了上面的不同以外,SST39VF1601 每个 SECTOR 的大小都是一样的, 而 Am29LV160 的头几块比较小 需要做的修改集中在 board/tekkamanninja/mini2440/flash.c 这个文件上, 修改如下 :

81 diff -aurnp u-boot /board/sbc2410x/flash.c u-boot _tekkaman/board/tekkamanninja/mini2440/flash.c --- u-boot /board/sbc2410x/flash.c :20: u-boot _tekkaman/board/tekkamanninja/mini2440/flash.c :16: ,12 35,18 flash_info_t flash_info[config_sys_max_f #define CMD_UNLOCK1 0x000000AA #define CMD_UNLOCK2 0x #define CMD_ERASE_SETUP 0x #define CMD_ERASE_CONFIRM 0x //#define CMD_ERASE_CONFIRM 0x #define CMD_ERASE_CONFIRM 0x #define CMD_PROGRAM 0x000000A0 #define CMD_UNLOCK_BYPASS 0x #ifdef CONFIG_SST_VF1601 #define MEM_FLASH_ADDR1 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE (0x << 1))) #define MEM_FLASH_ADDR2 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE (0x000002AAA << 1))) #else #define MEM_FLASH_ADDR1 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE (0x << 1))) #define MEM_FLASH_ADDR2 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE (0x000002AA << 1))) #define BIT_ERASE_DONE 0x #define BIT_RDY_MASK 0x ,6 75,9 ulong flash_init (void) #elif defined(config_amd_lv800) (AMD_MANUFACT & FLASH_VENDMASK) (AMD_ID_LV800B & FLASH_TYPEMASK); #elif defined(config_sst_vf1601) (SST_MANUFACT & FLASH_VENDMASK) (SST_ID_xF1601 & FLASH_TYPEMASK); #else #error "Unknown flash configured" -80,6 89,7 ulong flash_init (void) else panic ("configured too many flash banks!\n"); for (j = 0; j < flash_info[i].sector_count; j) { #ifndef CONFIG_SST_VF1601 if (j <= 3) { /* 1st one is 16 KB */ if (j == 0) { -90,9 100,7 ulong flash_init (void) /* 2nd and 3rd are both 8 KB */ if ((j == 1) (j == 2)) { flash_info[i].start[j] = - flashbase 0x4000 (j - - 1) * - 0x2000; flashbase 0x4000 (j -1) *0x2000; /* 4th 32 KB */ -104,6 112,11 ulong flash_init (void)

82 flash_info[i].start[j] = flashbase (j - 3) * MAIN_SECT_SIZE; #else flash_info[i].start[j] = flashbase (j) * MAIN_SECT_SIZE; size = flash_info[i].size; -130,6 143,9 void flash_print_info (flash_info_t * in case (AMD_MANUFACT & FLASH_VENDMASK): printf ("AMD: "); break; case (SST_MANUFACT & FLASH_VENDMASK): printf ("SST: "); break; default: printf ("Unknown Vendor "); break; -142,6 158,10 void flash_print_info (flash_info_t * in case (AMD_ID_LV800B & FLASH_TYPEMASK): printf ("1x Amd29LV800BB (8Mbit)\n"); break; case (SST_ID_xF1601 & FLASH_TYPEMASK): printf ("1x SST39VF1601 (2MB)\n"); break; default: printf ("Unknown Chip Type\n"); goto Done; -169,10 189,10 void flash_print_info (flash_info_t * in int flash_erase (flash_info_t * info, int s_first, int s_last) { - ushort result; // ushort result; int iflag, cflag, prot, sect; int rc = ERR_OK; - int chip; // int chip; /* first look for protection bits */ -182,12 202,17 int flash_erase (flash_info_t * info, in if ((s_first < 0) (s_first > s_last)) { return ERR_INVAL; - #ifdef CONFIG_SST_VF1601 if ((info->flash_id & FLASH_VENDMASK)!= (SST_MANUFACT & FLASH_VENDMASK)) { return ERR_UNKNOWN_FLASH_VENDOR; #else if ((info->flash_id & FLASH_VENDMASK)!= (AMD_MANUFACT & FLASH_VENDMASK)) { return ERR_UNKNOWN_FLASH_VENDOR;

83 - prot = 0; for (sect = s_first; sect <= s_last; sect) { if (info->protect[sect]) { -226,6 251,7 int flash_erase (flash_info_t * info, in MEM_FLASH_ADDR2 = CMD_UNLOCK2; *addr = CMD_ERASE_CONFIRM; #if 0 /* wait until flash is ready */ chip = 0; -267,11 293,31 int flash_erase (flash_info_t * info, in printf ("protected!\n"); /* wait until flash is ready */ while(1){ unsigned short i; i = *((volatile unsigned short *)addr) & 0x40; if(i!= (*((volatile unsigned short *)addr) & 0x40)) continue; if((*((volatile unsigned short *)addr)) & 0x80) break; printf ("ok.\n"); else { /* it was protected */ printf ("protected!\n"); if (ctrlc ()) printf ("User Interrupt!\n"); - outahere: // outahere: /* allow flash to settle - wait 10 ms */ udelay_masked (10000); -294,7 340,7 static int write_hword (flash_info_t * i ushort result; int rc = ERR_OK; int cflag, iflag; - int chip; // int chip; /* * Check if Flash is (sufficiently) erased -317,13 363,15 static int write_hword (flash_info_t * i MEM_FLASH_ADDR1 = CMD_UNLOCK1; MEM_FLASH_ADDR2 = CMD_UNLOCK2; - MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS;

84 - *addr = CMD_PROGRAM; // MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS; // *addr = CMD_PROGRAM; MEM_FLASH_ADDR1 = CMD_PROGRAM; *addr = data; - #if 0 /* arm simple, non interrupt dependent timer */ reset_timer_masked (); /* wait until flash is ready */ chip = 0; do { -352,6 400,18 static int write_hword (flash_info_t * i if (chip == ERR *addr!= data) rc = ERR_PROG_ERROR; /* wait until flash is ready */ while(1){ unsigned short i = *(volatile unsigned short *)addr & 0x40; if(i!= (*(volatile unsigned short *)addr & 0x40)) //D6 == D6 continue; if((*(volatile unsigned short *)addr & 0x80) == (data & 0x80)){ rc = ERR_OK; break; //D7 == D7 if (iflag) enable_interrupts (); 修改网络相关代码 以前的 U-boot 对于网络延时部分有问题, 需要修改许多地方 但是现在的 U-boot 网络部分已经基本不需要怎么修改了, 只有在 DM9000 的驱动和 NFS 的 TIMEOUT 参数上需要稍微修改一下 : 对于 DM9000 的驱动, 只是屏蔽了一点代码 : diff -aurnp u-boot /drivers/net/dm9000x.c u-boot _tekkaman/drivers/net/dm9000x.c --- u-boot /drivers/net/dm9000x.c :20: u-boot _tekkaman/drivers/net/dm9000x.c :16: ,12 364,13 static int dm9000_init(struct eth_device while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */ udelay(1000); i; - if (i == 10000) { - printf("could not establish link\n"); - return 0; if (i == 1000) { // printf("could not establish link\n"); // return 0; break;

85 /* see what we've got */ lnk = phy_read(17) >> 12; printf("operating at "); 对于 NFS, 增加了延时, 否则会出现 *** ERROR: Cannot mount 的错误 diff -aurnp u-boot /net/nfs.c u-boot _tekkaman/net/nfs.c --- u-boot /net/nfs.c :20: u-boot _tekkaman/net/nfs.c :16: ,7 33,7 #define HASHES_PER_LINE 65 /* Number of "loading" hashes per line */ #define NFS_RETRY_COUNT 30 -#define NFS_TIMEOUT 2000UL #define NFS_TIMEOUT (10*2000UL) static int fs_mounted = 0; static unsigned long rpc_id = 0; 添加串口 Xmodem 传输协议 ( 可不修改 ) 对于使用串口传输数据到内存的操作, 有可能会用到 Xmodem 协议 但是原本的 kermit 协议传输就挺好用的, 速度也比较快, 所以可添加此功能 修改的方法是参考 的方法 diff -aurnp u-boot /common/cmd_load.c u-boot _tekkaman/common/cmd_load.c --- u-boot /common/cmd_load.c :20: u-boot _tekkaman/common/cmd_load.c :16: ,6 34,9 DECLARE_GLOBAL_DATA_PTR; #if defined(config_cmd_loadb) #if defined(enable_cmd_loadb_x) static ulong load_serial_xmodem (ulong offset); static ulong load_serial_ymodem (ulong offset); -475,7 478,19 int do_load_serial_bin (cmd_tbl_t *cmdtp #if defined(enable_cmd_loadb_x) if (strcmp(argv[0],"loadx")==0) { printf ("## Ready for binary (xmodem) download " "to 0x%08lX at %d bps...\n", offset, load_baudrate); addr = load_serial_xmodem (offset); else if (strcmp(argv[0],"loady")==0) { #else if (strcmp(argv[0],"loady")==0) {

86 printf ("## Ready for binary (ymodem) download " "to 0x%08lX at %d bps...\n", offset, -963,6 978,66 static int getcxmodem(void) { return (getc()); return -1; #if defined(enable_cmd_loadb_x) static ulong load_serial_xmodem (ulong offset) { int size; char buf[32]; int err; int res; connection_info_t info; char xmodembuf[1024]; ulong store_addr = ~0; ulong addr = 0; size = 0; info.mode = xyzmodem_xmodem; res = xyzmodem_stream_open (&info, &err); if (!res) { while ((res = xyzmodem_stream_read (xmodembuf, 1024, &err)) > 0) { store_addr = addr offset; size = res; addr = res; #ifndef CFG_NO_FLASH if (addr2info (store_addr)) { int rc; rc = flash_write ((char *) xmodembuf, store_addr, res); if (rc!= 0) { flash_perror (rc); return (~0); else { memcpy ((char *) (store_addr), xmodembuf, res); else { printf ("%s\n", xyzmodem_error (err)); xyzmodem_stream_close (&err); xyzmodem_stream_terminate (false, &getcxmodem); flush_cache (offset, size); printf ("## Total Size = 0x%08x = %d Bytes\n", size, size);

87 sprintf (buf, "%X", size); setenv ("filesize", buf); return offset; static ulong load_serial_ymodem (ulong offset) { int size; -1078,6 1153,16 U_BOOT_CMD( " with offset 'off' and baudrate 'baud'" ); #if defined(enable_cmd_loadb_x) U_BOOT_CMD( loadx, 3, 0, do_load_serial_bin, "load binary file over serial line (xmodem mode)", "[ off ] [ baud ]\n" " - load binary file over serial line" " with offset 'off' and baudrate 'baud'" ); U_BOOT_CMD( loady, 3, 0, do_load_serial_bin, "load binary file over serial line (ymodem mode)", 添加 LCD 显示功能 对于这个 LCD 的支持是参考 Openmoko 的代码移植的 Openmoko 的 GTA2 使用的是 S3C2442 的 CPU, 在 LCD 控制器上是一样的 而 GTA2 在 U-boot 的可以在 LCD 上显示字符, 而且对于软件分层的 U-boot 来说, 只要将底层驱动移植过来并调整好初始化参数就可以在 LCD 上显示 console 由于友善之臂使用了两种屏, 他们在一个参数上有很小的差别, 而屏有不可以通过程序去识别, 所以只能简单的通过 Nand Flash 配置来区分导入的参数 (64MB Nand 的板子使用的都是 NEC 的, 其他的都是统宝的 ) 这个功能的移植修改了 5 个文件 ( 包括 drivers/video/makefile, 以及前面已经修改过的 board/tekkamanninja/mini2440/mini2440.c 文件 ), 在 /drivers/video/ 下添加一个驱动文件 s3c2410_fb.c diff -aurnp u-boot /drivers/video/cfb_console.c u-boot _tekkaman/drivers/video/cfb_console.c --- u-boot /drivers/video/cfb_console.c :20: u-boot _tekkaman/drivers/video/cfb_console.c :16: ,8 281,11 void console_cursor (int state); #define VIDEO_LOGO_LUT_OFFSET LINUX_LOGO_LUT_OFFSET #define VIDEO_LOGO_COLORS LINUX_LOGO_COLORS /* CONFIG_VIDEO_BMP_LOGO */ -#define VIDEO_INFO_X (VIDEO_LOGO_WIDTH) -#define VIDEO_INFO_Y (VIDEO_FONT_HEIGHT/2) #define VIDEO_INFO_X (0) #define VIDEO_INFO_Y (VIDEO_LOGO_HEIGHT)

88 //#define VIDEO_INFO_X (VIDEO_LOGO_WIDTH) //#define VIDEO_INFO_Y (VIDEO_FONT_HEIGHT/2) #else /* CONFIG_VIDEO_LOGO */ #define VIDEO_LOGO_WIDTH 0 #define VIDEO_LOGO_HEIGHT 0 diff -aurnp u-boot /drivers/video/makefile u-boot _tekkaman/drivers/video/makefile --- u-boot /drivers/video/makefile :20: u-boot _tekkaman/drivers/video/makefile :16: ,6 38,7 COBJS-$(CONFIG_VIDEO_SM501) = sm501.o COBJS-$(CONFIG_VIDEO_SMI_LYNXEM) = smilynxem.o COBJS-$(CONFIG_VIDEO_VCXK) = bus_vcxk.o COBJS-y = videomodes.o COBJS-y = s3c2410_fb.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff -aurnp u-boot /drivers/video/videomodes.c u-boot _tekkaman/drivers/video/videomodes.c --- u-boot /drivers/video/videomodes.c :20: u-boot _tekkaman/drivers/video/videomodes.c :16: ,6 95,7 const struct ctfb_vesa_modes vesa_modes[ {0x319, RES_MODE_1280x1024, 15, {0x31A, RES_MODE_1280x1024, 16, {0x31B, RES_MODE_1280x1024, 24, {0x211, RES_MODE_240x320, 16, ; const struct ctfb_res_modes res_mode_init[res_modes_count] = { /* x y pixclk le ri up lo hs vs s vmode */ -104,6 105,7 const struct ctfb_res_modes res_mode_ini {960, 720, 13100, 160, 40, 32, 8, 80, 4, 0, FB_VMODE_NONINTERLACED, {1152, 864, 12004, 200, 64, 32, 16, 80, 4, 0, FB_VMODE_NONINTERLACED, {1280, 1024, 9090, 200, 48, 26, 1, 184, 3, 0, FB_VMODE_NONINTERLACED, {240, 320, , 26, 6, 1, 11, 37, 2, 0, FB_VMODE_NONINTERLACED, ; /************************************************************************ diff -aurnp u-boot /drivers/video/videomodes.h u-boot _tekkaman/drivers/video/videomodes.h --- u-boot /drivers/video/videomodes.h :20: u-boot _tekkaman/drivers/video/videomodes.h :16: ,8 22,8 */ -#ifndef CONFIG_SYS_DEFAULT_VIDEO_MODE -#define CONFIG_SYS_DEFAULT_VIDEO_MODE #ifndef CFG_SYS_DEFAULT_VIDEO_MODE #define CFG_SYS_DEFAULT_VIDEO_MODE 0x211 0x301 /* Some mode definitions */ -78,9 78,11 struct ctfb_vesa_modes { #define RES_MODE_960_720 3 #define RES_MODE_1152x864 4 #define RES_MODE_1280x #define RES_MODES_COUNT 6 #define RES_MODE_240x #define VESA_MODES_COUNT 19

89 #define RES_MODES_COUNT 7 #define VESA_MODES_COUNT 20 extern const struct ctfb_vesa_modes vesa_modes[]; extern const struct ctfb_res_modes res_mode_init[]; /drivers/video/s3c2410_fb.c: /* * (C) Copyright 2006 by OpenMoko, Inc. * Author: Harald Welte * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA USA */ #include <common.h> #if defined(config_video_s3c2410) #include <video_fb.h> #include "videomodes.h" #include <s3c2410.h> /* * Export Graphic Device */ GraphicDevice smi; #define VIDEO_MEM_SIZE 0x /* 240x320x16bit = 0x25800 bytes */ extern void board_video_init(graphicdevice *pgd); /******************************************************************************* * * Init video chip with common Linux graphic modes (lilo) */ void *video_hw_init (void) { struct s3c24x0_lcd * const lcd = s3c24x0_get_base_lcd(); GraphicDevice *pgd = (GraphicDevice *)&smi; int videomode; unsigned long t1, hsynch, vsynch; char *penv; int tmp, i, bits_per_pixel; struct ctfb_res_modes *res_mode; struct ctfb_res_modes var_mode;

90 // unsigned char videoout; /* Search for video chip */ printf("video: "); tmp = 0; videomode = CFG_SYS_DEFAULT_VIDEO_MODE; /* get video mode via environment */ if ((penv = getenv ("videomode"))!= NULL) { /* deceide if it is a string */ if (penv[0] <= '9') { videomode = (int) simple_strtoul (penv, NULL, 16); tmp = 1; else { tmp = 1; if (tmp) { /* parameter are vesa modes */ /* search params */ for (i = 0; i < VESA_MODES_COUNT; i) { if (vesa_modes[i].vesanr == videomode) break; if (i == VESA_MODES_COUNT) { printf ("no VESA Mode found, switching to mode 0x%x ", CFG_SYS_DEFAULT_VIDEO_MODE); i = 0; res_mode = (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i]. resindex]; bits_per_pixel = vesa_modes[i].bits_per_pixel; else { res_mode = (struct ctfb_res_modes *) &var_mode; bits_per_pixel = video_get_params (res_mode, penv); /* calculate hsynch and vsynch freq (info only) */ t1 = (res_mode->left_margin res_mode->xres res_mode->right_margin res_mode->hsync_len) / 8; t1 *= 8; t1 *= res_mode->pixclock; t1 /= 1000; hsynch = L / t1; t1 *= (res_mode->upper_margin res_mode->yres res_mode->lower_margin res_mode->vsync_len); t1 /= 1000; vsynch = L / t1; /* fill in Graphic device struct */ sprintf (pgd->modeident, "%dx%dx%d %ldkhz %ldhz", res_mode->xres, res_mode->yres, bits_per_pixel, (hsynch / 1000), (vsynch / 1000)); printf ("%s\n", pgd->modeident); pgd->winsizex = res_mode->xres; pgd->winsizey = res_mode->yres;

91 pgd->plnsizex = res_mode->xres; pgd->plnsizey = res_mode->yres; switch (bits_per_pixel) { case 8: pgd->gdfbytespp = 1; pgd->gdfindex = GDF 8BIT_INDEX; break; case 15: pgd->gdfbytespp = 2; pgd->gdfindex = GDF_15BIT_555RGB; break; case 16: pgd->gdfbytespp = 2; pgd->gdfindex = GDF_16BIT_565RGB; break; case 24: pgd->gdfbytespp = 3; pgd->gdfindex = GDF_24BIT_888RGB; break; /* statically configure settings */ pgd->winsizex = pgd->plnsizex = 240; pgd->winsizey = pgd->plnsizey = 320; pgd->gdfbytespp = 2; pgd->gdfindex = GDF_16BIT_565RGB; pgd->frameadrs = LCD_VIDEO_ADDR; pgd->memsize = VIDEO_MEM_SIZE; board_video_init(pgd); lcd->lcdsaddr1 = pgd->frameadrs >> 1; /* This marks the end of the frame buffer. */ lcd->lcdsaddr2 = (lcd->lcdsaddr1&0x1fffff) (pgd->winsizex0) * pgd->winsizey; lcd->lcdsaddr3 = (pgd->winsizex & 0x7ff); /* Clear video memory */ memset((void *)pgd->frameadrs, 0, pgd->memsize); /* Enable Display */ lcd->lcdcon1 = 0x01; /* ENVID = 1 */ return ((void*)&smi); void video_set_lut (unsigned int index, /* color number */ unsigned char r, /* red */ unsigned char g, /* green */ unsigned char b /* blue */ ) { /* CONFIG_VIDEO_S3C2410 */

92 6.4.7 添加 SD 卡 (MMC) 读取功能 SD 卡的支持参考了 buserror 的 Git 代码仓库中的源码, 他也是为 mini2440 移植的 它使用的代码也是 Openmoko 的 GTA2 源码 因为 GTA2 可以在 U-boot 中使用 SD 卡更新系统 将其 SD 卡底层驱动代码搬过来, 经过简单的修改就可以使用了 这个功能需要修改 5 个文件, 添加 3 个驱动代码文件 diff -aurnp u-boot /common/cmd_mem.c u-boot _tekkaman/common/cmd_mem.c --- u-boot /common/cmd_mem.c :20: u-boot _tekkaman/common/cmd_mem.c :16: ,6 32,9 #ifdef CONFIG_HAS_DATAFLASH #include <dataflash.h> #if defined(config_cmd_mmc) #include <mmc.h> #include <watchdog.h> #include <u-boot/md5.h> -404,6 407,46 int do_mem_cp ( cmd_tbl_t *cmdtp, int fl #if defined(config_cmd_mmc) if (mmc2info(dest)) { int rc; puts ("Copy to MMC... "); switch (rc = mmc_write ((uchar *)addr, dest, count*size)) { case 0: putc ('\n'); return 1; case -1: puts ("failed\n"); return 1; default: printf ("%s[%d] FIXME: rc=%d\n", FILE, LINE,rc); return 1; puts ("done\n"); return 0; if (mmc2info(addr)) { int rc; puts ("Copy from MMC... "); switch (rc = mmc_read (addr, (uchar *)dest, count*size)) { case 0: putc ('\n'); return 1; case -1: puts ("failed\n"); return 1; default:

93 printf ("%s[%d] FIXME: rc=%d\n", FILE, LINE,rc); return 1; puts ("done\n"); return 0; #ifdef CONFIG_HAS_DATAFLASH /* Check if we are copying from RAM or Flash to DataFlash */ if (addr_dataflash(dest) &&!addr_dataflash(addr)){ diff -aurnp u-boot /common/cmd_mmc.c u-boot _tekkaman/common/cmd_mmc.c --- u-boot /common/cmd_mmc.c :20: u-boot _tekkaman/common/cmd_mmc.c :16: ,7 50,7 int do_mmc (cmd_tbl_t *cmdtp, int flag, return 1; - if (mmc_legacy_init(dev)!= 0) { if (mmc_init(dev)!= 0) { puts("no MMC card found\n"); return 1; diff -aurnp u-boot /cpu/arm920t/s3c24x0/makefile u-boot _tekkaman/cpu/arm920t/s3c24x0/Makefile --- u-boot /cpu/arm920t/s3c24x0/makefile :20: u-boot _tekkaman/cpu/arm920t/s3c24x0/makefile :16: ,7 30,7 COBJS-y = speed.o COBJS-y = timer.o COBJS-y = usb.o COBJS-y = usb_ohci.o - COBJS-y = mmc.o SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c) OBJS := $(addprefix $(obj),$(sobjs) $(COBJS-y)) diff -aurnp u-boot /include/mmc.h u-boot _tekkaman/include/mmc.h --- u-boot /include/mmc.h :20: u-boot _tekkaman/include/mmc.h :16: ,7 169,7 #define MMC_RSP_R6 (MMC_RSP_PRESENT MMC_RSP_CRC MMC_RSP_OPCODE) #define MMC_RSP_R7 (MMC_RSP_PRESENT MMC_RSP_CRC MMC_RSP_OPCODE) - #if 0 struct mmc_cid { unsigned long psn; unsigned short oid; -218,7 218,7 struct mmc_csd u8 crc:7; u8 one:1; ; - struct mmc_cmd { ushort cmdidx; uint resp_type; -268,8 268,10 struct mmc {

94 int mmc_register(struct mmc *mmc); int mmc_initialize(bd_t *bis); -int mmc_init(struct mmc *mmc); -int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size); //int mmc_init(struct mmc *mmc); //int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size); int mmc_init(int verbose); int mmc_read(ulong src, uchar *dst, int size); struct mmc *find_mmc_device(int dev_num); void print_mmc_devices(char separator); diff -aurnp u-boot /include/part.h u-boot _tekkaman/include/part.h --- u-boot /include/part.h :20: u-boot _tekkaman/include/part.h :16: ,6 62,7 typedef struct block_dev_desc { #define IF_TYPE_MMC 6 #define IF_TYPE_SD 7 #define IF_TYPE_SATA 8 #define IF_TYPE_SDHC 9 /* Part types */ #define PART_TYPE_UNKNOWN 0x00 添加的 3 个驱动代码文件 : /cpu/arm920t/s3c24x0/mmc.c: /* * u-boot S3C2410 MMC/SD card driver * (C) Copyright 2006 by OpenMoko, Inc. * Author: Harald Welte * * based on u-boot pxa MMC driver and linux/drivers/mmc/s3c2410mci.c * (C) Thomas Kleffel * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA USA */ #include <config.h> #include <common.h> #include <mmc.h> #include <asm/arch/mmc.h> #include <asm/errno.h> #include <asm/io.h> #include <s3c2410.h>

95 #include <part.h> #include <fat.h> #if defined(config_mmc) && defined(config_mmc_s3c) #ifdef DEBUG #define pr_debug(fmt, args...) printf(fmt, ##args) #else #define pr_debug(...) do { while(0) #define CONFIG_MMC_WIDE static struct s3c2410_sdi *sdi; static block_dev_desc_t mmc_dev; block_dev_desc_t * mmc_get_dev(int dev) { return ((block_dev_desc_t *)&mmc_dev); /* * FIXME needs to read cid and csd info to determine block size * and other parameters */ static uchar mmc_buf[mmc_block_size]; static mmc_csd_t mmc_csd; static int mmc_ready = 0; static int wide = 0; #define CMD_F_RESP 0x01 #define CMD_F_RESP_LONG 0x02 #define CMD_F_RESP_R7 CMD_F_RESP static u_int32_t *mmc_cmd(ushort cmd, ulong arg, ushort flags) { static u_int32_t resp[5]; u_int32_t ccon, csta; u_int32_t csta_rdy_bit = S3C2410_SDICMDSTAT_CMDSENT; memset(resp, 0, sizeof(resp)); debug("mmc_cmd CMD%d arg=0x%08x flags=%x\n", cmd, arg, flags); sdi->sdicsta = 0xffffffff; sdi->sdidsta = 0xffffffff; sdi->sdifsta = 0xffffffff; sdi->sdicarg = arg; ccon = cmd & S3C2410_SDICMDCON_INDEX; ccon = S3C2410_SDICMDCON_SENDERHOST S3C2410_SDICMDCON_CMDSTART; if (flags & CMD_F_RESP) { ccon = S3C2410_SDICMDCON_WAITRSP; csta_rdy_bit = S3C2410_SDICMDSTAT_RSPFIN; /* 1 << 9 */

96 if (flags & CMD_F_RESP_LONG) ccon = S3C2410_SDICMDCON_LONGRSP; sdi->sdiccon = ccon; while (1) { csta = sdi->sdicsta; if (csta & csta_rdy_bit) break; if (csta & S3C2410_SDICMDSTAT_CMDTIMEOUT) { printf("===============> MMC CMD Timeout\n"); sdi->sdicsta = S3C2410_SDICMDSTAT_CMDTIMEOUT; break; debug("final MMC CMD status 0x%x\n", csta); sdi->sdicsta = csta_rdy_bit; if (flags & CMD_F_RESP) { resp[0] = sdi->sdirsp0; resp[1] = sdi->sdirsp1; resp[2] = sdi->sdirsp2; resp[3] = sdi->sdirsp3; return resp; #define FIFO_FILL(host) ((host->sdifsta & S3C2410_SDIFSTA_COUNTMASK) >> 2) static int mmc_block_read(uchar *dst, ulong src, ulong len) { u_int32_t dcon, fifo; u_int32_t *dst_u32 = (u_int32_t *)dst; u_int32_t *resp; if (len == 0) return 0; debug("mmc_block_rd dst %lx src %lx len %d\n", (ulong)dst, src, len); /* set block len */ resp = mmc_cmd(mmc_cmd_set_blocklen, len, CMD_F_RESP); sdi->sdibsize = len; //sdi->sdipre = 0xff; /* setup data */ dcon = (len >> 9) & S3C2410_SDIDCON_BLKNUM; dcon = S3C2410_SDIDCON_BLOCKMODE; dcon = S3C2410_SDIDCON_RXAFTERCMD S3C2410_SDIDCON_XFER_RXSTART; if (wide) dcon = S3C2410_SDIDCON_WIDEBUS; #if defined(config_s3c2440) defined(config_s3c2442) dcon = S3C2440_SDIDCON_DS_WORD S3C2440_SDIDCON_DATSTART;

97 sdi->sdidcon = dcon; /* send read command */ resp = mmc_cmd(mmc_cmd_read_block, (mmc_dev.if_type == IF_TYPE_SDHC)? (src >> 9) : src, CMD_F_RESP); while (len > 0) { u_int32_t sdidsta = sdi->sdidsta; fifo = FIFO_FILL(sdi); if (sdidsta & (S3C2410_SDIDSTA_FIFOFAIL S3C2410_SDIDSTA_CRCFAIL S3C2410_SDIDSTA_RXCRCFAIL S3C2410_SDIDSTA_DATATIMEOUT)) { printf("mmc_block_read: err SDIDSTA=0x%08x\n", sdidsta); return -EIO; while (fifo--) { //debug("dst_u32 = 0x%08x\n", dst_u32); *(dst_u32) = sdi->sdidat; if (len >= 4) len -= 4; else { len = 0; break; debug("waiting for SDIDSTA (currently 0x%08x\n", sdi->sdidsta); while (!(sdi->sdidsta & (1 << 4))) { debug("done waiting for SDIDSTA (currently 0x%08x\n", sdi->sdidsta); sdi->sdidcon = 0; if (!(sdi->sdidsta & S3C2410_SDIDSTA_XFERFINISH)) debug("mmc_block_read; transfer not finished!\n"); return 0; static int mmc_block_write(ulong dst, uchar *src, int len) { printf("mmc block write not yet supported on S3C2410!\n"); return -1; int mmc_read(ulong src, uchar *dst, int size) { ulong end, part_start, part_end, part_len, aligned_start, aligned_end; ulong mmc_block_size, mmc_block_address; if (size == 0) return 0; if (!mmc_ready) { printf("please initialize the MMC first\n"); return -1;

98 mmc_block_size = MMC_BLOCK_SIZE; mmc_block_address = ~(mmc_block_size - 1); src -= CFG_MMC_BASE; end = src size; part_start = ~mmc_block_address & src; part_end = ~mmc_block_address & end; aligned_start = mmc_block_address & src; aligned_end = mmc_block_address & end; /* all block aligned accesses */ debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); if (part_start) { part_len = mmc_block_size - part_start; debug("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0) return -1; memcpy(dst, mmc_bufpart_start, part_len); dst = part_len; src = part_len; debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); for (; src < aligned_end; src = mmc_block_size, dst = mmc_block_size) { debug("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); if ((mmc_block_read((uchar *)(dst), src, mmc_block_size)) < 0) return -1; debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); if (part_end && src < end) { debug("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0) return -1; memcpy(dst, mmc_buf, part_end); return 0; int mmc_write(uchar *src, ulong dst, int size) { ulong end, part_start, part_end, part_len, aligned_start, aligned_end; ulong mmc_block_size, mmc_block_address; if (size == 0) return 0; if (!mmc_ready) { printf("please initialize the MMC first\n"); return -1; mmc_block_size = MMC_BLOCK_SIZE;

99 mmc_block_address = ~(mmc_block_size - 1); dst -= CFG_MMC_BASE; end = dst size; part_start = ~mmc_block_address & dst; part_end = ~mmc_block_address & end; aligned_start = mmc_block_address & dst; aligned_end = mmc_block_address & end; /* all block aligned accesses */ debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); if (part_start) { part_len = mmc_block_size - part_start; debug("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", (ulong)src, dst, end, part_start, part_end, aligned_start, aligned_end); if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0) return -1; memcpy(mmc_bufpart_start, src, part_len); if ((mmc_block_write(aligned_start, mmc_buf, mmc_block_size)) < 0) return -1; dst = part_len; src = part_len; debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); for (; dst < aligned_end; src = mmc_block_size, dst = mmc_block_size) { debug("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); if ((mmc_block_write(dst, (uchar *)src, mmc_block_size)) < 0) return -1; debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); if (part_end && dst < end) { debug("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end); if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0) return -1; memcpy(mmc_buf, src, part_end); if ((mmc_block_write(aligned_end, mmc_buf, mmc_block_size)) < 0) return -1; return 0; ulong mmc_bread(int dev_num, ulong blknr, ulong blkcnt, void *dst) { int mmc_block_size = MMC_BLOCK_SIZE; ulong src = blknr * mmc_block_size CFG_MMC_BASE; mmc_read(src, dst, blkcnt*mmc_block_size); return blkcnt;

100 /* MMC_DEFAULT_RCA should probably be just 1, but this may break other code that expects it to be shifted. */ static u_int16_t rca = MMC_DEFAULT_RCA >> 16; static u_int32_t mmc_size(const struct mmc_csd *csd) { u_int32_t block_len, mult, blocknr; block_len = csd->read_bl_len << 12; mult = csd->c_size_mult1 << 8; blocknr = (csd->c_size1) * mult; return blocknr * block_len; struct sd_cid { char pnm_0; /* product name */ char oid_1; /* OEM/application ID */ char oid_0; uint8_t mid; /* manufacturer ID */ char pnm_4; char pnm_3; char pnm_2; char pnm_1; uint8_t psn_2; /* product serial number */ uint8_t psn_1; uint8_t psn_0; /* MSB */ uint8_t prv; /* product revision */ uint8_t crc; /* CRC7 checksum, b0 is unused and set to 1 */ uint8_t mdt_1; /* manufacturing date, LSB, RRRRyyyy yyyymmmm */ uint8_t mdt_0; /* MSB */ uint8_t psn_3; /* LSB */ ; static void print_mmc_cid(mmc_cid_t *cid) { printf("mmc found. Card desciption is:\n"); printf("manufacturer ID = %02x%02x%02x\n", cid->id[0], cid->id[1], cid->id[2]); printf("hw/fw Revision = %x %x\n",cid->hwrev, cid->fwrev); cid->hwrev = cid->fwrev = 0; /* null terminate string */ printf("product Name = %s\n",cid->name); printf("serial Number = %02x%02x%02x\n", cid->sn[0], cid->sn[1], cid->sn[2]); printf("month = %d\n",cid->month); printf("year = %d\n",1997 cid->year); static void print_sd_cid(const struct sd_cid *cid) { printf("manufacturer: 0x%02x, OEM \"%c%c\"\n", cid->mid, cid->oid_0, cid->oid_1); printf("product name: \"%c%c%c%c%c\", revision %d.%d\n", cid->pnm_0, cid->pnm_1, cid->pnm_2, cid->pnm_3, cid->pnm_4, cid->prv >> 4, cid->prv & 15); printf("serial number: %u\n", cid->psn_0 << 24 cid->psn_1 << 16 cid->psn_2 << 8 cid->psn_3); printf("manufacturing date: %d/%d\n", cid->mdt_1 & 15,

101 2000((cid->mdt_0 & 15) << 4)((cid->mdt_1 & 0xf0) >> 4)); printf("crc: 0x%02x, b0 = %d\n", cid->crc >> 1, cid->crc & 1); int mmc_init(int verbose) { int retries, rc = -ENODEV; int is_sd = 0; u_int32_t *resp; struct s3c24x0_clock_power * const clk_power = s3c24x0_get_base_clock_power(); block_dev_desc_t *mmc_blkdev_p = &mmc_dev; sdi = s3c2410_get_base_sdi(); debug("mmc_init(pclk=%u)\n", get_pclk()); clk_power->clkcon = (1 << 9); sdi->sdibsize = 512; #if defined(config_s3c2410) /* S3C2410 has some bug that prevents reliable operation at higher speed */ //sdi->sdipre = 0x3e; /* SDCLK = PCLK/2 / (SDIPRE1) = 396kHz */ sdi->sdipre = 0x02; /* 2410: SDCLK = PCLK/2 / (SDIPRE1) = 11MHz */ sdi->sdidtimer = 0xffff; #elif defined(config_s3c2440) defined(config_s3c2442) sdi->sdipre = 0x05; /* 2410: SDCLK = PCLK / (SDIPRE1) = 11MHz */ sdi->sdidtimer = 0x7fffff; sdi->sdiimsk = 0x0; sdi->sdicon = S3C2410_SDICON_FIFORESET S3C2410_SDICON_CLOCKTYPE; udelay(125000); /* FIXME: 74 SDCLK cycles */ mmc_csd.c_size = 0; /* reset */ retries = 10; resp = mmc_cmd(mmc_cmd_reset, 0, 0); mmc_dev.if_type = IF_TYPE_UNKNOWN; if(verbose) puts("mmc: Probing for SDHC...\n"); /* Send supported voltage range */ /* SD cards 1.x do not answer to CMD8 */ resp = mmc_cmd(mmc_cmd_if_cond, ((1 << 8) 0xAA), CMD_F_RESP_R7); if (!resp[0]) { /* * ARC: No answer let's try SD 1.x */ if(verbose) puts("mmc: No answer to CMD8 trying SD\n"); mmc_blkdev_p->if_type = IF_TYPE_SD; else { /* * ARC: probably an SDHC card */ mmc_blkdev_p->if_type = IF_TYPE_SDHC; if(verbose) puts("mmc: SD 2.0 or later card found\n");

102 /* Check if the card supports this voltage */ if (resp[0]!= ((1 << 8) 0xAA)) { pr_debug("mmc: Invalid voltage range\n"); return -ENODEV; /* * ARC: HC (30) bit set according to response to * CMD8 command */ pr_debug("mmc: Sending ACMD41 %s HC set\n", ((mmc_blkdev_p->if_type == IF_TYPE_SDHC)? "with" : "without")); printf("trying to detect SD Card...\n"); while (retries--) { udelay(100000); resp = mmc_cmd(55, 0x , CMD_F_RESP); resp = mmc_cmd(41, (mmc_blkdev_p->if_type == IF_TYPE_SDHC)? (0x (1<<30)) : 0x , CMD_F_RESP); if (resp[0] & (1 << 31)) { is_sd = 1; break; /* * ARC: check for HC bit, if its not set * sd card is SD */ if (is_sd && (resp[0] & 0xc ) == 0x ) { mmc_dev.if_type = IF_TYPE_SD; if (retries == 0 &&!is_sd) { retries = 10; printf("failed to detect SD Card, trying MMC\n"); mmc_blkdev_p->if_type = IF_TYPE_MMC; resp = mmc_cmd(mmc_cmd_send_op_cond, 0x00ffc000, CMD_F_RESP); while (retries-- && resp &&!(resp[4] & 0x80)) { debug("resp %x %x\n", resp[0], resp[1]); udelay(50); resp = mmc_cmd(1, 0x00ffff00, CMD_F_RESP); /* try to get card id */ resp = mmc_cmd(mmc_cmd_all_send_cid, 0, CMD_F_RESP CMD_F_RESP_LONG); if (resp) { if (!is_sd) { /* TODO configure mmc driver depending on card attributes */ mmc_cid_t *cid = (mmc_cid_t *)resp; if (verbose) print_mmc_cid(cid);

103 else { sprintf((char *) mmc_dev.vendor, "Man %02x%02x%02x Snr %02x%02x%02x", cid->id[0], cid->id[1], cid->id[2], cid->sn[0], cid->sn[1], cid->sn[2]); sprintf((char *) mmc_dev.product,"%s",cid->name); sprintf((char *) mmc_dev.revision,"%x %x", cid->hwrev, cid->fwrev); struct sd_cid *cid = (struct sd_cid *) resp; if (verbose) print_sd_cid(cid); sprintf((char *) mmc_dev.vendor, "Man %02x OEM %c%c \"%c%c%c%c%c\"", cid- >mid, cid->oid_0, cid->oid_1, cid->pnm_0, cid->pnm_1, cid->pnm_2, cid->pnm_3, cid->pnm_4); sprintf((char *) mmc_dev.product, "%d", cid->psn_0 << 24 cid->psn_1 << 16 cid->psn_2 << 8 cid->psn_3); sprintf((char *) mmc_dev.revision, "%d.%d", cid->prv >> 4, cid->prv & 15); /* fill in device description */ if (mmc_dev.if_type == IF_TYPE_UNKNOWN) mmc_dev.if_type = IF_TYPE_MMC; mmc_dev.part_type = PART_TYPE_DOS; mmc_dev.dev = 0; mmc_dev.lun = 0; mmc_dev.type = 0; /* FIXME fill in the correct size (is set to 32MByte) */ mmc_dev.blksz = 512; mmc_dev.lba = 0x10000; mmc_dev.removable = 0; mmc_dev.block_read = mmc_bread; /* MMC exists, get CSD too */ resp = mmc_cmd(mmc_cmd_set_rca, MMC_DEFAULT_RCA, CMD_F_RESP); if (is_sd) rca = resp[0] >> 16; resp = mmc_cmd(mmc_cmd_send_csd, rca<<16, CMD_F_RESP CMD_F_RESP_LONG); if (resp) { mmc_csd_t *csd = (mmc_csd_t *)resp; memcpy(&mmc_csd, csd, sizeof(csd)); rc = 0; mmc_ready = 1; /* FIXME add verbose printout for csd */ printf("read_bl_len=%u, C_SIZE_MULT=%u, C_SIZE=%u\n", csd->read_bl_len, csd->c_size_mult1, csd->c_size); printf("size = %u\n", mmc_size(csd)); resp = mmc_cmd(mmc_cmd_select_card, rca<<16, CMD_F_RESP); if (verbose) printf("sd Card detected RCA: 0x%x type: %s\n", rca, ((mmc_dev.if_type == IF_TYPE_SDHC)? "SDHC" : ((mmc_dev.if_type == IF_TYPE_SD)? "SD" : "MMC")));

104 #ifdef CONFIG_MMC_WIDE if (is_sd) { resp = mmc_cmd(55, rca<<16, CMD_F_RESP); resp = mmc_cmd(6, 0x02, CMD_F_RESP); wide = 1; fat_register_device(&mmc_dev,1); /* partitions start counting with 1 */ return rc; int mmc_ident(block_dev_desc_t *dev) { return 0; int mmc2info(ulong addr) { /* FIXME hard codes to 32 MB device */ if (addr >= CFG_MMC_BASE && addr < CFG_MMC_BASE 0x ) return 1; return 0; /* defined(config_mmc) && defined(config_mmc_s3c) */ include/asm-arm/arch-s3c24x0/mmc.h: /* * linux/drivers/mmc/mmc_pxa.h * * Author: Vladimir Shebordaev, Igor Oblakov * Copyright: MontaVista Software Inc. * * $Id: mmc_pxa.h,v /09/25 19:25:48 ted Exp ted $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #ifndef MMC_PXA_P_H #define MMC_PXA_P_H #include <asm/arch/regs-sdi.h> #define MMC_DEFAULT_RCA (1<<16) #define MMC_BLOCK_SIZE 512 #define MMC_CMD_RESET 0 #define MMC_CMD_SEND_OP_COND 1 #define MMC_CMD_ALL_SEND_CID 2 #define MMC_CMD_SET_RCA 3 #define MMC_CMD_SELECT_CARD 7

105 #define MMC_CMD_IF_COND 8 #define MMC_CMD_SEND_CSD 9 #define MMC_CMD_SEND_CID 10 #define MMC_CMD_SEND_STATUS 13 #define MMC_CMD_SET_BLOCKLEN 16 #define MMC_CMD_READ_BLOCK 17 #define MMC_CMD_RD_BLK_MULTI 18 #define MMC_CMD_WRITE_BLOCK 24 #define MMC_MAX_BLOCK_SIZE 512 #define MMC_R1_IDLE_STATE #define MMC_R1_ERASE_STATE #define MMC_R1_ILLEGAL_CMD #define MMC_R1_COM_CRC_ERR #define MMC_R1_ERASE_SEQ_ERR #define MMC_R1_ADDR_ERR #define MMC_R1_PARAM_ERR #define MMC_R1B_WP_ERASE_SKIP #define MMC_R1B_ERR #define MMC_R1B_CC_ERR #define MMC_R1B_CARD_ECC_ERR #define MMC_R1B_WP_VIOLATION #define MMC_R1B_ERASE_PARAM #define MMC_R1B_OOR #define MMC_R1B_IDLE_STATE #define MMC_R1B_ERASE_RESET #define MMC_R1B_ILLEGAL_CMD #define MMC_R1B_COM_CRC_ERR #define MMC_R1B_ERASE_SEQ_ERR #define MMC_R1B_ADDR_ERR #define MMC_R1B_PARAM_ERR typedef struct mmc_cid { /* FIXME: BYTE_ORDER */ uchar year:4, month:4; uchar sn[3]; uchar fwrev:4, hwrev:4; uchar name[6]; uchar id[3]; mmc_cid_t; typedef struct mmc_csd { uchar ecc:2, file_format:2, tmp_write_protect:1, perm_write_protect:1, copy:1, file_format_grp:1; uint64_t content_prot_app:1, rsvd3:4, write_bl_partial:1, write_bl_len:4, r2w_factor:3, default_ecc:2, 0x01 0x02 0x04 0x08 0x01 0x02 0x04 0x0002 0x0004 0x0008 0x0010 0x0020 0x0040 0x0080 0x0100 0x0200 0x0400 0x0800 0x1000 0x2000 0x4000

106 wp_grp_enable:1, wp_grp_size:5, erase_grp_mult:5, erase_grp_size:5, c_size_mult1:3, vdd_w_curr_max:3, vdd_w_curr_min:3, vdd_r_curr_max:3, vdd_r_curr_min:3, c_size:12, rsvd2:2, dsr_imp:1, read_blk_misalign:1, write_blk_misalign:1, read_bl_partial:1; ushort read_bl_len:4, ccc:12; uchar tran_speed; uchar nsac; uchar taac; uchar rsvd1:2, spec_vers:4, csd_structure:2; mmc_csd_t; /* MMC_PXA_P_H */ include/asm-arm/arch-s3c24x0/regs-sdi.h : /* linux/include/asm/arch-s3c2410/regs-sdi.h * * Copyright (c) 2004 Simtec Electronics * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * S3C2410 MMC/SDIO register definitions * * Changelog: * 18-Aug-2004 Ben Dooks Created initial file * 29-Nov-2004 Koen Martens Added some missing defines, fixed duplicates * 29-Nov-2004 Ben Dooks Updated Koen's patch */ #ifndef ASM_ARM_REGS_SDI #define ASM_ARM_REGS_SDI "regs-sdi.h" #define S3C2440_SDICON_SDRESET (1<<8) #define S3C2440_SDICON_MMCCLOCK (1<<5) #define S3C2410_SDICON_BYTEORDER (1<<4) #define S3C2410_SDICON_SDIOIRQ (1<<3) #define S3C2410_SDICON_RWAITEN (1<<2) #define S3C2410_SDICON_FIFORESET (1<<1) #define S3C2410_SDICON_CLOCKTYPE (1<<0)

107 #define S3C2410_SDICMDCON_ABORT (1<<12) #define S3C2410_SDICMDCON_WITHDATA (1<<11) #define S3C2410_SDICMDCON_LONGRSP (1<<10) #define S3C2410_SDICMDCON_WAITRSP (1<<9) #define S3C2410_SDICMDCON_CMDSTART (1<<8) #define S3C2410_SDICMDCON_SENDERHOST (1<<6) #define S3C2410_SDICMDCON_INDEX (0x3f) #define S3C2410_SDICMDSTAT_CRCFAIL (1<<12) #define S3C2410_SDICMDSTAT_CMDSENT (1<<11) #define S3C2410_SDICMDSTAT_CMDTIMEOUT (1<<10) #define S3C2410_SDICMDSTAT_RSPFIN (1<<9) #define S3C2410_SDICMDSTAT_XFERING (1<<8) #define S3C2410_SDICMDSTAT_INDEX (0xff) #define S3C2440_SDIDCON_DS_BYTE (0<<22) #define S3C2440_SDIDCON_DS_HALFWORD (1<<22) #define S3C2440_SDIDCON_DS_WORD (2<<22) #define S3C2410_SDIDCON_IRQPERIOD (1<<21) #define S3C2410_SDIDCON_TXAFTERRESP (1<<20) #define S3C2410_SDIDCON_RXAFTERCMD (1<<19) #define S3C2410_SDIDCON_BUSYAFTERCMD (1<<18) #define S3C2410_SDIDCON_BLOCKMODE (1<<17) #define S3C2410_SDIDCON_WIDEBUS (1<<16) #define S3C2410_SDIDCON_DMAEN (1<<15) #define S3C2410_SDIDCON_STOP (1<<14) #define S3C2440_SDIDCON_DATSTART (1<<14) #define S3C2410_SDIDCON_DATMODE (3<<12) #define S3C2410_SDIDCON_BLKNUM (0x7ff) /* constants for S3C2410_SDIDCON_DATMODE */ #define S3C2410_SDIDCON_XFER_READY (0<<12) #define S3C2410_SDIDCON_XFER_CHKSTART (1<<12) #define S3C2410_SDIDCON_XFER_RXSTART (2<<12) #define S3C2410_SDIDCON_XFER_TXSTART (3<<12) #define S3C2410_SDIDCNT_BLKNUM_MASK (0xFFF) #define S3C2410_SDIDCNT_BLKNUM_SHIFT (12) #define S3C2410_SDIDSTA_RDYWAITREQ (1<<10) #define S3C2410_SDIDSTA_SDIOIRQDETECT (1<<9) #define S3C2410_SDIDSTA_FIFOFAIL (1<<8) /* reserved on 2440 */ #define S3C2410_SDIDSTA_CRCFAIL (1<<7) #define S3C2410_SDIDSTA_RXCRCFAIL (1<<6) #define S3C2410_SDIDSTA_DATATIMEOUT (1<<5) #define S3C2410_SDIDSTA_XFERFINISH (1<<4) #define S3C2410_SDIDSTA_BUSYFINISH (1<<3) #define S3C2410_SDIDSTA_SBITERR (1<<2) /* reserved on 2410a/2440 */ #define S3C2410_SDIDSTA_TXDATAON (1<<1) #define S3C2410_SDIDSTA_RXDATAON (1<<0) #define S3C2440_SDIFSTA_FIFORESET (1<<16) #define S3C2440_SDIFSTA_FIFOFAIL (3<<14) /* 3 is correct (2 bits) */ #define S3C2410_SDIFSTA_TFDET (1<<13) #define S3C2410_SDIFSTA_RFDET (1<<12) #define S3C2410_SDIFSTA_TFHALF (1<<11) #define S3C2410_SDIFSTA_TFEMPTY (1<<10) #define S3C2410_SDIFSTA_RFLAST (1<<9) #define S3C2410_SDIFSTA_RFFULL (1<<8) #define S3C2410_SDIFSTA_RFHALF (1<<7)

108 #define S3C2410_SDIFSTA_COUNTMASK (0x7f) #define S3C2410_SDIIMSK_RESPONSECRC (1<<17) #define S3C2410_SDIIMSK_CMDSENT (1<<16) #define S3C2410_SDIIMSK_CMDTIMEOUT (1<<15) #define S3C2410_SDIIMSK_RESPONSEND (1<<14) #define S3C2410_SDIIMSK_READWAIT (1<<13) #define S3C2410_SDIIMSK_SDIOIRQ (1<<12) #define S3C2410_SDIIMSK_FIFOFAIL (1<<11) #define S3C2410_SDIIMSK_CRCSTATUS (1<<10) #define S3C2410_SDIIMSK_DATACRC (1<<9) #define S3C2410_SDIIMSK_DATATIMEOUT (1<<8) #define S3C2410_SDIIMSK_DATAFINISH (1<<7) #define S3C2410_SDIIMSK_BUSYFINISH (1<<6) #define S3C2410_SDIIMSK_SBITERR (1<<5) /* reserved 2440/2410a */ #define S3C2410_SDIIMSK_TXFIFOHALF (1<<4) #define S3C2410_SDIIMSK_TXFIFOEMPTY (1<<3) #define S3C2410_SDIIMSK_RXFIFOLAST (1<<2) #define S3C2410_SDIIMSK_RXFIFOFULL (1<<1) #define S3C2410_SDIIMSK_RXFIFOHALF (1<<0) /* ASM_ARM_REGS_SDI */ 6.5 第四阶段 : 修正配置文件 添加 CONFIG_S3C2440 条件定义 对于 S3C2440, 很多代码是借用 S3C2410 的, 所以要在所有条件编译中有 CONFIG_S3C2410 的地方添加 CONFIG_S3C2440, 这样这些代码才会编译进来 一个简单的方法就是在代码中搜索出所有的 CONFIG_S3C2410, 并根据实际情况修改 在有些地方不仅要加入 CONFIG_S3C2440, 还必须根据两个芯片的不同来分布做出修改, 比如 PLL 的操作代码 对于 U-boot 的修改如下 : diff -aurnp u-boot /common/serial.c u-boot _tekkaman/common/serial.c --- u-boot /common/serial.c :20: u-boot _tekkaman/common/serial.c :16: ,7 59,7 struct serial_device * default_serial_c #else return &serial0_device; -#elif defined(config_s3c2410) #elif defined(config_s3c2410) defined(config_s3c2440) #if defined(config_serial1) return &s3c24xx_serial0_device; #elif defined(config_serial2) -148,7 148,7 void serial_initialize (void) #if defined (CONFIG_STUART) serial_register(&serial_stuart_device); -#if defined(config_s3c2410) #if defined(config_s3c2410) defined(config_s3c2440) serial_register(&s3c24xx_serial0_device);

109 serial_register(&s3c24xx_serial1_device); serial_register(&s3c24xx_serial2_device); diff -aurnp u-boot /cpu/arm920t/s3c24x0/interrupts.c u-boot _tekkaman/cpu/arm920t/s3c24x0/interrupts.c --- u-boot /cpu/arm920t/s3c24x0/interrupts.c :20: u-boot _tekkaman/cpu/arm920t/s3c24x0/interrupts.c :16: ,7 33,7 #if defined(config_s3c2400) #include <s3c2400.h> -#elif defined(config_s3c2410) #elif defined(config_s3c2410) defined (CONFIG_S3C2440) #include <s3c2410.h> #include <asm/proc-armv/ptrace.h> diff -aurnp u-boot /cpu/arm920t/s3c24x0/timer.c u-boot _tekkaman/cpu/arm920t/s3c24x0/timer.c --- u-boot /cpu/arm920t/s3c24x0/timer.c :20: u-boot _tekkaman/cpu/arm920t/s3c24x0/timer.c :16: ,13 32,14 #include <common.h> #if defined(config_s3c2400) \ defined(config_s3c2410) \ defined(config_s3c2440) \ defined(config_trab) #include <asm/io.h> #if defined(config_s3c2400) #include <s3c2400.h> -#elif defined(config_s3c2410) #elif defined(config_s3c2410) defined (CONFIG_S3C2440) #include <s3c2410.h> -188,6 189,7 ulong get_tbclk(void) tbclk = timer_load_val * 100; #elif defined(config_sbc2410x) \ defined(config_smdk2410) \ defined(config_mini2440) \ defined(config_vcma9) tbclk = CONFIG_SYS_HZ; #else -229,4 231,5 void reset_cpu(ulong ignored) /* defined(config_s3c2400) defined (CONFIG_S3C2410) defined(config_s3c2440) defined (CONFIG_TRAB) */ diff -aurnp u-boot /cpu/arm920t/s3c24x0/usb.c u-boot _tekkaman/cpu/arm920t/s3c24x0/usb.c --- u-boot /cpu/arm920t/s3c24x0/usb.c :20: u-boot _tekkaman/cpu/arm920t/s3c24x0/usb.c :16: ,11 24,11 #include <common.h> #if defined(config_usb_ohci_new) && defined(config_sys_usb_ohci_cpu_init) -# if defined(config_s3c2400) defined(config_s3c2410) # if defined(config_s3c2400) defined(config_s3c2410) defined(config_s3c2440)

110 #if defined(config_s3c2400) # include <s3c2400.h> -#elif defined(config_s3c2410) #elif defined(config_s3c2410) defined(config_s3c2440) # include <s3c2410.h> diff -aurnp u-boot /cpu/arm920t/s3c24x0/usb_ohci.c u-boot _tekkaman/cpu/arm920t/s3c24x0/usb_ohci.c --- u-boot /cpu/arm920t/s3c24x0/usb_ohci.c :20: u-boot _tekkaman/cpu/arm920t/s3c24x0/usb_ohci.c :16: ,7 40,7 #if defined(config_s3c2400) #include <s3c2400.h> -#elif defined(config_s3c2410) #elif defined(config_s3c2410) defined (CONFIG_S3C2440) #include <s3c2410.h> diff -aurnp u-boot /drivers/i2c/s3c24x0_i2c.c u-boot _tekkaman/drivers/i2c/s3c24x0_i2c.c --- u-boot /drivers/i2c/s3c24x0_i2c.c :20: u-boot _tekkaman/drivers/i2c/s3c24x0_i2c.c :16: ,7 29,7 #include <common.h> #if defined(config_s3c2400) #include <s3c2400.h> -#elif defined(config_s3c2410) #elif defined(config_s3c2410) defined (CONFIG_S3C2440) #include <s3c2410.h> -61,7 61,7 static int GetI2CSDA(void) { struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio(); -#ifdef CONFIG_S3C2410 #if defined(config_s3c2410) defined (CONFIG_S3C2440) return (readl(&gpio->gpedat) & 0x8000) >> 15; #ifdef CONFIG_S3C ,7 80,7 static void SetI2CSCL(int x) { struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio(); -#ifdef CONFIG_S3C2410 #if defined(config_s3c2410) defined (CONFIG_S3C2440) writel((readl(&gpio->gpedat) & ~0x4000) (x & 1) << 14, &gpio->gpedat); #ifdef CONFIG_S3C ,7 132,7 void i2c_init(int speed, int slaveadd) if ((readl(&i2c->iicstat) & I2CSTAT_BSY) GetI2CSDA() == 0) { -#ifdef CONFIG_S3C2410 #if defined(config_s3c2410) defined (CONFIG_S3C2440) ulong old_gpecon = readl(&gpio->gpecon);

111 #ifdef CONFIG_S3C ,7 141,7 void i2c_init(int speed, int slaveadd) /* bus still busy probably by (most) previously interrupted transfer */ -#ifdef CONFIG_S3C2410 #if defined(config_s3c2410) defined (CONFIG_S3C2440) /* set I2CSDA and I2CSCL (GPE15, GPE14) to GPIO */ writel((readl(&gpio->gpecon) & ~0xF ) 0x , &gpio->gpecon); -167,7 167,7 void i2c_init(int speed, int slaveadd) udelay(1000); /* restore pin functions */ -#ifdef CONFIG_S3C2410 #if defined(config_s3c2410) defined (CONFIG_S3C2440) writel(old_gpecon, &gpio->gpecon); #ifdef CONFIG_S3C2400 diff -aurnp u-boot /drivers/rtc/s3c24x0_rtc.c u-boot _tekkaman/drivers/rtc/s3c24x0_rtc.c --- u-boot /drivers/rtc/s3c24x0_rtc.c :20: u-boot _tekkaman/drivers/rtc/s3c24x0_rtc.c :16: ,7 32,7 #if defined(config_s3c2400) #include <s3c2400.h> -#elif defined(config_s3c2410) #elif defined(config_s3c2410) defined(config_s3c2440) #include <s3c2410.h> diff -aurnp u-boot /drivers/serial/serial_s3c24x0.c u-boot _tekkaman/drivers/serial/serial_s3c24x0.c --- u-boot /drivers/serial/serial_s3c24x0.c :20: u-boot _tekkaman/drivers/serial/serial_s3c24x0.c :16: ,7 21,7 #include <common.h> #if defined(config_s3c2400) defined(config_trab) #include <s3c2400.h> -#elif defined(config_s3c2410) #elif defined(config_s3c2410) defined (CONFIG_S3C2440) #include <s3c2410.h> diff -aurnp u-boot /drivers/usb/host/ohci-hcd.c u-boot _tekkaman/drivers/usb/host/ohci-hcd.c --- u-boot /drivers/usb/host/ohci-hcd.c :20: u-boot _tekkaman/drivers/usb/host/ohci-hcd.c :16: ,6 67,7 #if defined(config_arm920t) \ defined(config_s3c2400) \ defined(config_s3c2410) \ defined(config_s3c2440) \ defined(config_s3c6400) \ defined(config_440ep) \ defined(config_pci_ohci) \ diff -aurnp u-boot /include/common.h u-boot _tekkaman/include/common.h --- u-boot /include/common.h :20: u-boot _tekkaman/include/common.h :16:

112 -496,7 496,7 ulong get_opb_freq (void); ulong get_pci_freq (void); #if defined(config_s3c2400) defined(config_s3c2410) \ - defined(config_lh7a40x) defined(config_s3c6400) defined(config_lh7a40x) defined(config_s3c6400) defined(config_s3c2440) ulong get_fclk (void); ulong get_hclk (void); ulong get_pclk (void); diff -aurnp u-boot /include/serial.h u-boot _tekkaman/include/serial.h --- u-boot /include/serial.h :20: u-boot _tekkaman/include/serial.h :16: ,7 37,7 extern struct serial_device eserial4_dev -#if defined(config_s3c2410) #if defined(config_s3c2410) defined(config_s3c2440) extern struct serial_device s3c24xx_serial0_device; extern struct serial_device s3c24xx_serial1_device; extern struct serial_device s3c24xx_serial2_device; 在 cpu/arm920t/s3c24x0/speed.c 文件中必须根据 S3C2440 与 S3C2410 的不同来修改 : diff -aurnp u-boot /cpu/arm920t/s3c24x0/speed.c u-boot _tekkaman/cpu/arm920t/s3c24x0/speed.c --- u-boot /cpu/arm920t/s3c24x0/speed.c :20: u-boot _tekkaman/cpu/arm920t/s3c24x0/speed.c :16: ,13 30,13 */ #include <common.h> -#if defined(config_s3c2400) defined (CONFIG_S3C2410) defined (CONFIG_TRAB) #if defined(config_s3c2400) defined (CONFIG_S3C2410) defined (CONFIG_TRAB) defined (CONFIG_S3C2440) #include <asm/io.h> #if defined(config_s3c2400) #include <s3c2400.h> -#elif defined(config_s3c2410) #elif defined(config_s3c2410) defined (CONFIG_S3C2440) #include <s3c2410.h> -68,7 68,13 static ulong get_pllclk(int pllreg) m = ((r & 0xFF000) >> 12) 8; p = ((r & 0x003F0) >> 4) 2; s = r & 0x3; - //tekkaman #if defined(config_s3c2440) if (pllreg == MPLL) return ((CONFIG_SYS_CLK_FREQ * m * 2) /(p << s)); else if (pllreg == UPLL) //tekkaman

113 return (CONFIG_SYS_CLK_FREQ * m) / (p << s); -83,7 89,21 ulong get_hclk(void) { struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); - return (readl(&clk_power->clkdivn) & 2)? get_fclk() / 2 : get_fclk(); // return (readl(&clk_power->clkdivn) & 2)? get_fclk() / 2 : get_fclk(); //tekkaman #if defined(config_s3c2440) if (readl(&clk_power->clkdivn) & 0x6) { if ((readl(&clk_power->clkdivn) & 0x6)==2) return(get_fclk()/2); if ((readl(&clk_power->clkdivn) & 0x6)==6) return((readl(&clk_power- >CAMDIVN) & 0x100)? get_fclk()/6 : get_fclk()/3); if ((readl(&clk_power->clkdivn) & 0x6)==4) return((readl(&clk_power- >CAMDIVN) & 0x200)? get_fclk()/8 : get_fclk()/4); return(get_fclk()); else return(get_fclk()); #else return((readl(&clk_power->clkdivn) & 0x2)? get_fclk()/2 : get_fclk()); //tekkaman /* return PCLK frequency */ -102,4 122,5 ulong get_uclk(void) /* defined(config_s3c2400) defined (CONFIG_S3C2410) defined (CONFIG_S3C2440) defined (CONFIG_TRAB) */ include/s3c24x0.h 文件中主要放的是寄存器定义, 根据两款芯片的不同在 Nand USB 和 SD 开接口等方面必须经过修改 diff -aurnp u-boot /include/s3c24x0.h u-boot _tekkaman/include/s3c24x0.h --- u-boot /include/s3c24x0.h :20: u-boot _tekkaman/include/s3c24x0.h :16: ,7 82,7 struct s3c24x0_interrupt { S3C24X0_REG32 PRIORITY; S3C24X0_REG32 INTPND; S3C24X0_REG32 INTOFFSET; -#ifdef CONFIG_S3C2410 #if defined(config_s3c2410) defined (CONFIG_S3C2440) S3C24X0_REG32 SUBSRCPND; S3C24X0_REG32 INTSUBMSK; -92,11 92,11 struct s3c24x0_interrupt { /* DMAS (see manual chapter 8) */ struct s3c24x0_dma { S3C24X0_REG32 DISRC; -#ifdef CONFIG_S3C2410 #if defined(config_s3c2410) defined (CONFIG_S3C2440) S3C24X0_REG32 DISRCC; S3C24X0_REG32 DIDST;

114 -#ifdef CONFIG_S3C2410 #if defined(config_s3c2410) defined (CONFIG_S3C2440) S3C24X0_REG32 DIDSTC; S3C24X0_REG32 DCON; -107,7 107,7 struct s3c24x0_dma { #ifdef CONFIG_S3C2400 S3C24X0_REG32 res[1]; -#ifdef CONFIG_S3C2410 #if defined(config_s3c2410) defined (CONFIG_S3C2440) S3C24X0_REG32 res[7]; ; -126,6 126,9 struct s3c24x0_clock_power { S3C24X0_REG32 CLKCON; S3C24X0_REG32 CLKSLOW; S3C24X0_REG32 CLKDIVN; #if defined (CONFIG_S3C2440) S3C24X0_REG32 CAMDIVN; ; -145,7 148,7 struct s3c24x0_lcd { S3C24X0_REG32 res[8]; S3C24X0_REG32 DITHMODE; S3C24X0_REG32 TPAL; -#ifdef CONFIG_S3C2410 #if defined(config_s3c2410) defined (CONFIG_S3C2440) S3C24X0_REG32 LCDINTPND; S3C24X0_REG32 LCDSRCPND; S3C24X0_REG32 LCDINTMSK; -153,7 156,7 struct s3c24x0_lcd { ; - #if defined(config_s3c2410) /* NAND FLASH (see S3C2410 manual chapter 6) */ struct s3c2410_nand { S3C24X0_REG32 NFCONF; -163,7 166,28 struct s3c2410_nand { S3C24X0_REG32 NFSTAT; S3C24X0_REG32 NFECC; ; - #if defined (CONFIG_S3C2440) /* NAND FLASH (see S3C2440 manual chapter 6) */ struct s3c2410_nand { S3C24X0_REG32 NFCONF; S3C24X0_REG32 NFCONT; S3C24X0_REG32 NFCMD; S3C24X0_REG32 NFADDR; S3C24X0_REG32 NFDATA; S3C24X0_REG32 NFMECCD0; S3C24X0_REG32 NFMECCD1; S3C24X0_REG32 NFSECCD; S3C24X0_REG32 NFSTAT;

115 S3C24X0_REG32 NFESTAT0; S3C24X0_REG32 NFESTAT1; S3C24X0_REG32 NFMECC0; S3C24X0_REG32 NFMECC1; S3C24X0_REG32 NFSECC; S3C24X0_REG32 NFSBLK; S3C24X0_REG32 NFEBLK; ; /* UART (see manual chapter 11) */ struct s3c24x0_uart { -316,8 340,17 struct s3c24x0_usb_device { S3C24X0_REG8 OUT_FIFO_CNT2_REG; S3C24X0_REG8 res16[3]; /* BIG_ENDIAN */ // struct s3c24x0_usb_dev_fifos fifo[5]; // struct s3c24x0_usb_dev_dmas dma[5]; S3C24X0_REG32 res17[8]; struct s3c24x0_usb_dev_fifos fifo[5]; - struct s3c24x0_usb_dev_dmas dma[5]; S3C24X0_REG32 res18[11]; struct s3c24x0_usb_dev_dmas ep1; struct s3c24x0_usb_dev_dmas ep2; S3C24X0_REG8 res19[16]; struct s3c24x0_usb_dev_dmas ep3; struct s3c24x0_usb_dev_dmas ep4; ; -401,7 434,7 struct s3c24x0_gpio { S3C24X0_REG32 MISCCR; S3C24X0_REG32 EXTINT; -#ifdef CONFIG_S3C2410 #if defined(config_s3c2410) defined (CONFIG_S3C2440) S3C24X0_REG32 GPACON; S3C24X0_REG32 GPADAT; S3C24X0_REG32 res1[2]; -450,6 483,14 struct s3c24x0_gpio { S3C24X0_REG32 GSTATUS2; S3C24X0_REG32 GSTATUS3; S3C24X0_REG32 GSTATUS4; #if defined (CONFIG_S3C2440) S3C24X0_REG32 res9[3]; S3C24X0_REG32 MSLCON; S3C24X0_REG32 GPJCON; S3C24X0_REG32 GPJDAT; S3C24X0_REG32 GPJUP; ; -643,6 684,8 struct s3c2410_sdi { S3C24X0_REG32 SDIDCNT; S3C24X0_REG32 SDIDSTA; S3C24X0_REG32 SDIFSTA; #if defined(config_s3c2410)

116 #if 0 #ifdef BIG_ENDIAN S3C24X0_REG8 res[3]; S3C24X0_REG8 SDIDAT; -650,7 693,14 struct s3c2410_sdi { S3C24X0_REG8 SDIDAT; S3C24X0_REG8 res[3]; S3C24X0_REG32 SDIDAT; S3C24X0_REG32 SDIIMSK; #elif defined(config_s3c2440) S3C24X0_REG32 SDIIMSK; S3C24X0_REG32 SDIDAT; ; /* S3C24X0_H */ 修改配置文件 include/configs/mini2440.h 最后, 还有修改配置文件, 使得前面修改的很多功能编译进来 这里主要做了以下修改 : (1) 去除了 CS8900 网卡的定义, 添加了 DM9000 (2) 使能了 JFFS2 FAT 文件系统 (3) 使能了 USB SD 卡功能 (5) 使能了 I2C EEPROM 功能 (6) 使能了 LCD 功能, 以及 BMP 图片显示和字符 console 的功能 (7) 去除了 AMD 的 Nor Flash 芯片的定义, 增加 SST Nor Flash 芯片定义 --- u-boot /include/configs/sbc2410x.h :20: u-boot _tekkaman/include/configs/mini2440.h :16: ,9 44,12 * (easy to change) */ #define CONFIG_ARM920T 1 /* This is an ARM920T Core */ -#define CONFIG_S3C /* in a SAMSUNG S3C2410 SoC */ -#define CONFIG_SBC2410X 1 /* on a friendly-arm SBC-2410X Board */ - //#define CONFIG_S3C /* in a SAMSUNG S3C2410 SoC */ //#define CONFIG_SBC2410X 1 /* on a friendly-arm SBC-2410X Board */ #define CONFIG_S3C /* in a SAMSUNG S3C2440 SoC */ #define CONFIG_MINI /* on a friendly-arm MINI2440 Board */ #define CONFIG_MINI2440_LED 1 #define CONFIG_S3C2410_NAND_SKIP_BAD 1 /* input clock of PLL */ #define CONFIG_SYS_CLK_FREQ /* the SBC2410X has 12MHz input clock */ -63,11 66,21 /* * Hardware drivers

117 */ #if 0 #define CONFIG_NET_MULTI #define CONFIG_CS8900 /* we have a CS8900 on-board */ #define CONFIG_CS8900_BASE 0x #define CONFIG_CS8900_BUS16 /* the Linux driver does accesses as shorts */ - #define CONFIG_NET_MULTI 1 #define CONFIG_NET_RETRY_COUNT 20 #define CONFIG_DRIVER_DM #define CONFIG_DM9000_BASE 0x #define DM9000_IO CONFIG_DM9000_BASE #define DM9000_DATA (CONFIG_DM9000_BASE4) #define CONFIG_DM9000_USE_16BIT 1 #define CONFIG_DM9000_NO_SROM 1 #undef CONFIG_DM9000_DEBUG /* * select serial console configuration */ -104,19 117,37 #define CONFIG_CMD_DATE #define CONFIG_CMD_DHCP #define CONFIG_CMD_ELF //#define CONFIG_MTD_DEVICE //#define CONFIG_CMD_MTDPARTS #define CONFIG_CMD_PING - - -#define CONFIG_BOOTDELAY 3 -#define CONFIG_BOOTARGS "console=ttysac0 root=/dev/nfs " \ - "nfsroot= :/friendly-arm/rootfs_netserv " \ - "ip= : : : :debian:eth0:off" -#define CONFIG_ETHADDR 08:00:3e:26:0a:5b #define CONFIG_CMD_NAND #define CONFIG_CMD_REGINFO #define CONFIG_CMD_FAT /* FAT support*/ //#define CONFIG_CMD_EXT2 #define CONFIG_CMD_JFFS2 /* JFFS2 Support*/ #define CONFIG_CMD_USB /* USB Support*/ #define CONFIG_BOOTDELAY 1 #define CONFIG_BOOTARGS "noinitrd root=/dev/nfs rw nfsroot= :/home/tekkaman/working/nfs/rootfs ip= : :: console=ttysac0, init=/linuxrc mem=64m" #define CONFIG_ETHADDR 08:08:11:18:12:27 #define CONFIG_NETMASK #define CONFIG_IPADDR #define CONFIG_IPADDR #define CONFIG_SERVERIP #define CONFIG_GATEWAYIP #define CONFIG_OVERWRITE_ETHADDR_ONCE /*#define CONFIG_BOOTFILE "elinos-lart" */ -#define CONFIG_BOOTCOMMAND "dhcp; bootm" #define CONFIG_BOOTCOMMAND "nfs 0x

118 :/home/tekkaman/working/nfs/zImage.img;bootm" #define CONFIG_EXTRA_ENV_SETTINGS \ "tekkaman=bmp d 70000\0 " \ "stdin=serial\0" \ "stdout=serial\0" \ "stderr=serial\0" \ "" #if defined(config_cmd_kgdb) #define CONFIG_KGDB_BAUDRATE /* speed to run kgdb serial port */ -128,7 159,7 * Miscellaneous configurable options */ #define CONFIG_SYS_LONGHELP /* undef to save memory */ -#define CONFIG_SYS_PROMPT "[ ]# " /* Monitor Command Prompt */ #define CONFIG_SYS_PROMPT " /* Monitor Command Prompt */ #define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */ #define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZEsizeof(CONFIG_SYS_PROMPT)16) /* Print Buffer Size */ #define CONFIG_SYS_MAXARGS 16 /* max number of command args */ -137,7 168,8 #define CONFIG_SYS_MEMTEST_START 0x /* memtest works on */ #define CONFIG_SYS_MEMTEST_END 0x33F00000 /* 63 MB in DRAM */ -#define CONFIG_SYS_LOAD_ADDR 0x /* default load address */ #define CONFIG_SYS_LOAD_ADDR 0x /* default load address */ #define CONFIG_SYS_HZ ,7 203,8 */ /* #define CONFIG_AMD_LV400 1 /\* uncomment this if you have a LV400 flash *\/ */ -#define CONFIG_AMD_LV800 1 /* uncomment this if you have a LV800 flash */ //#define CONFIG_AMD_LV800 1 /* uncomment this if you have a LV800 flash */ #define CONFIG_SST_VF /* uncomment this if you have a Am29LV160DB flash */ #define CONFIG_SYS_MAX_FLASH_BANKS 1 /* max number of memory banks */ -191,15 224,62 #define CONFIG_SYS_FLASH_ERASE_TOUT (5*CONFIG_SYS_HZ) /* Timeout for Flash Erase */ #define CONFIG_SYS_FLASH_WRITE_TOUT (5*CONFIG_SYS_HZ) /* Timeout for Flash Write */ -#define CONFIG_ENV_IS_IN_FLASH 1 -#define CONFIG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */ //#if 0 #define CONFIG_CMD_EEPROM #define CONFIG_CMD_I2C #define CONFIG_DRIVER_S3C24X0_I2C 1 /* we use the buildin I2C controller */ #define CONFIG_HARD_I2C 1 /* I2C with hardware support */ #define CONFIG_SYS_I2C_SPEED /* I2C speed and slave address */ #define CONFIG_SYS_I2C_SLAVE 0x7F #define CONFIG_SYS_I2C_EEPROM_ADDR 0x50 /* EEPROM at24c08 */

119 #define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 /* Bytes of address */ /* mask of address bits that overflow into the "EEPROM chip address" */ #define CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW 0x07 #define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 4 /* The Catalyst CAT24WC08 has */ /* 16 byte page write mode using*/ /* last 4 bits of the address */ #define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 10 /* and takes up to 10 msec */ #define CONFIG_SYS_EEPROM_PAGE_WRITE_ENABLE //#define CONFIG_ENV_IS_IN_EEPROM 1 /* use EEPROM for environment vars */ //#define CONFIG_ENV_OFFSET 0x000 /* environment starts at offset 0 */ //#define CONFIG_ENV_SIZE 0x400 /* 1KB */ //#else #define CONFIG_ENV_IS_IN_NAND 1 //#define CONFIG_ENV_IS_IN_FLASH 1 #define CONFIG_ENV_OFFSET 0X60000 #define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */ // /* == LENGTH_UBOOT*/ #ifdef CONFIG_SST_VF1601 #define PHYS_FLASH_SIZE 0x /* 2MB */ #define CONFIG_SYS_MAX_FLASH_SECT (32) /* max number of sectors on one chip */ #define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE CONFIG_ENV_OFFSET) /* addr of environment */ /* * NAND flash settings */ #if defined(config_cmd_nand) #define CONFIG_NAND_S3C2410 #define CONFIG_SYS_NAND_BASE 0x4E #define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ #define SECTORSIZE 512 #define SECTORSIZE_2K 2048 #define NAND_SECTOR_SIZE SECTORSIZE #define NAND_SECTOR_SIZE_2K SECTORSIZE_2K #define NAND_BLOCK_MASK 511 #define NAND_BLOCK_MASK_2K 2047 #define NAND_MAX_CHIPS 1 #define CONFIG_MTD_NAND_VERIFY_WRITE #define CONFIG_SYS_64BIT_VSPRINTF /* needed for nand_util.c */ /* CONFIG_CMD_NAND */ #define CONFIG_SETUP_MEMORY_TAGS -211,10 291,83 #define CONFIG_CMDLINE_EDITING -#ifdef CONFIG_CMDLINE_EDITING -#undef CONFIG_AUTO_COMPLETE -#else //#ifdef CONFIG_CMDLINE_EDITING //#undef CONFIG_AUTO_COMPLETE //#else #define CONFIG_AUTO_COMPLETE //

120 #if 1 #define CONFIG_USB_OHCI #define CONFIG_USB_STORAGE //#define CONFIG_KEYBOARD //#define CONFIG_USB_KEYBOARD #define CONFIG_DOS_PARTITION #define CONFIG_SYS_DEVICE_DEREGISTER #define CONFIG_SUPPORT_VFAT #define LITTLEENDIAN #define CONFIG_JFFS2_NAND 1 //#undef CONFIG_JFFS2_CMDLINE #define CONFIG_JFFS2_DEV "nand0" #define CONFIG_JFFS2_PART_SIZE 0x #define CONFIG_JFFS2_PART_OFFSET 0x80000 #define CONFIG_JFFS2_CMDLINE 1 #define MTDIDS_DEFAULT "nand0=nandflash0" #define MTDPARTS_DEFAULT "mtdparts=nandflash0:384k(bootloader)," \ "128k(params)," \ "5m(kernel)," \ "-(root)" #define ENABLE_CMD_LOADB_X 1 #define ENABLE_CMD_NAND_YAFFS 1 #define ENABLE_CMD_NAND_YAFFS_SKIPFB 1 //#define CFG_NAND_YAFFS1_NEW_OOB_LAYOUT 1 #if 1 #define CONFIG_CMD_BMP #define CONFIG_VIDEO #define CONFIG_VIDEO_S3C2410 #define CONFIG_VIDEO_LOGO #define VIDEO_FB_16BPP_PIXEL_SWAP #define CONFIG_VIDEO_SW_CURSOR #define CONFIG_VIDEO_BMP_LOGO //#define CONFIG_CONSOLE_EXTRA_INFO //#define CONFIG_CONSOLE_CURSOR //#define CONFIG_CONSOLE_TIME #define CONFIG_CFB_CONSOLE #define CONFIG_SYS_CONSOLE_IS_IN_ENV //#define CFG_CONSOLE_INFO_QUIET //#define VIDEO_FB_LITTLE_ENDIAN #define CONFIG_SPLASH_SCREEN #define CONFIG_SYS_VIDEO_LOGO_MAX_SIZE (240* ) /* 100 = slack */ #define CONFIG_VIDEO_BMP_GZIP #define CONFIG_CMD_UNZIP #define LCD_VIDEO_ADDR 0x33d00000 /*for PC-keyboard*/ #define VIDEO_KBD_INIT_FCT 0 #define VIDEO_TSTC_FCT serial_tstc #define VIDEO_GETC_FCT serial_getc

121 /*for SD Card*/ #define CONFIG_CMD_MMC #define CONFIG_MMC 1 #define CONFIG_MMC_S3C 1 /* Enabling the MMC driver */ #define CFG_MMC_BASE 0xff #if 0 #define CONFIG_YAFFS2 //#undef CONFIG_YAFFS_YAFFS2 #undef CONFIG_YAFFS_NO_YAFFS1 /* CONFIG_H */ 所有的修改到此结束 6.6 重新编译并测试 make distclean make mini2440_config Configuring for mini2440 board... make 编译完成后按照前面讲的烧写方法烧到板子上, 重启 当听到蜂鸣器的响声,LCD 屏亮起并显示 DENX 的 logo, 串口中传出 : U-Boot ( 4 月 :09:25) modified by tekkamanninja Love Linux forever!! I2C: ready DRAM: 64 MB Flash: 2 MB NAND: 128 MiB Video: 240x320x16 20kHz 62Hz In: serial Out: serial Err: serial Net: dm9000 U-Boot ( 4 月 :09:25) modified by tekkamanninja Love Linux forever!! Hit any key to stop autoboot: 0 说明你基本成功了!!! 第 7 章下载最新的源代码 如果在移植中出了什么问题, 可以直接下载 Tekkaman Ninja 的源码做参考 下载方法如

122 图 :