移植 u-boot1.1.6 从 nand 和 nor 启动选择
2012 年 2 月 27 日
23:29
By Ct
前几天移植在重新研究 uboot 的移植和 linux 的移植,移植没有成功将 uboot
移植到 nor 和 nand 双启动,具体可以看我的日记,今天晚上,我又重新搞了一
遍,终于搞成功了,现在把记录记录如下:
参考文献:
1、http://blog.csdn.net/flytreeleft/article/details/6793126
2、
<>
3、http://www.embedu.org/Column/Column319.htm
4、完全手册
系统环境
编译器版本:gcc3.4.5(针对对于低版本 uboot 移植,久的版本交叉编译器可能会好
点)
Uboot 版本:1.1.6
linux:ubuntu11.04
首先参考 smdk2410 建立自己的配置文件:
1、在 borad/samsung/文件夹中
建立自己的板子的文件夹
cp -ar smdk2410 my2410(一定不能手动复
制,然后重命名)
2、将 my2410 中的 smdk 改成
my2410,
3、在 include/configs 中复制
smdk2410 的配置文件为自己的
配置文件
将 makefile 中 改成 COBJS := my2410.o
cp smdk2410.h my2410.h
4、在根目录下的 makefile 中增
加 my2410 的配置选项,参考
smdk2410
5、接下来修改 start.s 使其能够判断 nor 还是 nand 启动:
判断原理:
我们知道 UBoot 源码本身直接支持从 Nor Flash 启动,这是 Nor Flash 的可执行特
性决定的.而针对 Nand Flash,则涉及到前 4K 数据的问题.S3C2410 的 Nand Flash 控制
器有一个特殊的功能,就是能在上电后自动将 Nand Flash 中的前 4K 数据搬移到 4K 内
部的 RAM 中,并把 0x00000000 设置为内部 RAM 的起始地址,然后 CPU 从内部 RAM
的 0x000000 位置启动,该过程由硬件自动完成.
所以,要使 UBoot 支持从 Nand Flash 启动,必须在其前 4K 代码执行过程中完成将自身
复制到 RAM 中的工作.
但是,我们现在需要让 UBoot 支持双启动,现在的问题就是该如何判断 UBoot 是
在 Nor Flash 还是在 Nand Flash 中呢?呵呵,在 S3C2410(S3C2440)中,这个可以通过
BWSCON(BUS WIDTH & WAIT CONTROL REGISTER)控制寄存器[2:1]的值进行判断,如果
为 00 则表示是从 Nand Flash 启动的.因此,我们可以直接通过如下代码进行判断并在
BWSCON[2:1]为 00 时跳转到 UBoot 复制自身(copy_myself)的代码处:
源文档
在内存重定为之前,加入如下代码:
# define BWSCON 0x48000000
ldr r0,=BWSCON
ldr r0,[r0]
ands r0,r0,#6
beq copy_myself
然后在任意位置加入如下代码:
@
@ copy_myself: copy u-boot to ram
@
copy_myself:
@ reset NAND
mov r1, #NAND_CTL_BASE //r1=0x4e000000
ldr r2, =0xf830 @ initial value
str r2, [r1, #oNFCONF] //初始化 nandflash 寄存器参数
ldr r2, [r1, #oNFCONF]
bic r2, r2, #0x800 @ enable chip
str r2, [r1, #oNFCONF]
mov r2, #0xff @ RESET command
strb r2, [r1, #oNFCMD]
mov r3, #0 @ wait
1: add r3, r3, #0x1
cmp r3, #0xa
blt 1b
2: ldr r2, [r1, #oNFSTAT] @ wait ready
tst r2, #0x1
beq 2b
ldr r2, [r1, #oNFCONF]
orr r2, r2, #0x800 @ disable chip //等后面用的时候载开启
str r2, [r1, #oNFCONF]
@ get read to call C functions //由于下面要运行 c 函数,所以要定义堆栈
ldr sp, DW_STACK_START @ setup stack pointer
mov fp, #0 @ no previous frame, so fp=0
@ copy UBOOT to RAM
ldr r0, _TEXT_BASE //复制目的地的起始地址
mov r1, #0x0 //uboot 源的起始地址,这里应该是 nandflash 中的起始地址
mov r2, #0x40000 //uboot 的大小,这里应该根据自己的 uboot 大小进行相
应的修改,这里为 256K,足以
bl nand_read_ll //跳到 nandflash 复制函数开始复制
teq r0, #0x0 //ro 为上面函数的返回值
beq ok_nand_read
bad_nand_read:
1: b 1b @ infinite loop
ok_nand_read:
ldr r0, =boot_flash
mov r1, #0x0
str r1, [r0] /*设置 boot_flash 的值为 0 表示为 nand 启动*/
@ verify
mov r0, #0
ldr r1, _TEXT_BASE
mov r2, #0x400 @ 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:
1: b 1b
DW_STACK_START:
.word STACK_BASE+STACK_SIZE-4
这样,start.s 修改就完成了
6、接下来修改 my2410.h 的配置文件,增加对 nandflash 和对板子中 sst39vf1208 的支
持:(系统原带的不是这个 norflash)
#ifndef __CONFIG_H
#define __CONFIG_H
/*
* High Level Configuration Options
* (easy to change)
*/
#define CONFIG_ARM920T 1 /* This is an ARM920T Core */
#define CONFIG_S3C2410 1 /* in a SAMSUNG S3C2410 SoC */
#define CONFIG_SMDK2410 1 /* on a SAMSUNG SMDK2410 Board */
/* input clock of PLL */
#define CONFIG_SYS_CLK_FREQ 12000000/* the SMDK2410 has 12MHz input clock */
#define USE_920T_MMU 1
#undef CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
/*
* Size of malloc() pool
*/
#define CFG_MALLOC_LEN (CFG_ENV_SIZE + 128*1024)
#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
/*
* Hardware drivers
*/
#define CONFIG_DRIVER_CS8900 1 /* we have a CS8900 on-board */
#define CS8900_BASE 0x19000300
#define CS8900_BUS16 1 /* the Linux driver does accesses as shorts */
/*
* select serial console configuration
*/
#define CONFIG_SERIAL1 1 /* we use SERIAL 1 on SMDK2410 */
/************************************************************
* RTC
************************************************************/
#define CONFIG_RTC_S3C24X0 1
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
#define CONFIG_BAUDRATE 115200
/* for tag(s) to transfer message to kernel, www.100ask.net */
#define CONFIG_SETUP_MEMORY_TAGS 1
#define CONFIG_CMDLINE_TAG 1
/***********************************************************
* Command definition
***********************************************************/
#define CONFIG_COMMANDS \
(CONFIG_CMD_DFL | \
CFG_CMD_CACHE | \
CFG_CMD_PING | \
CFG_CMD_JFFS2 | \
CFG_CMD_NAND | \
/*CFG_CMD_EEPROM |*/ \
/*CFG_CMD_I2C |*/ \
/*CFG_CMD_USB |*/ \
CFG_CMD_REGINFO | \
CFG_CMD_DATE | \
CFG_CMD_ELF)
/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include
//在这里修改 uboot 的环境参数
#define CONFIG_BOOTDELAY 2
#define CONFIG_BOOTARGS "noinitrd root=/dev/mtdblock2 init=/linuxrc
console=ttySAC0 rootfstype=yaffs"
#define CONFIG_ETHADDR 08:00:3e:26:0a:5b
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 192.168.1.62
#define CONFIG_SERVERIP 192.168.1.63
/*#define CONFIG_BOOTFILE "elinos-lart" */
#define CONFIG_BOOTCOMMAND "nboot 0x32000000 0 0; bootm 0x32000000"
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#define CONFIG_KGDB_BAUDRATE 115200 /* speed to run kgdb serial port */
/* what's this ? it's not used anywhere */
#define CONFIG_KGDB_SER_INDEX 1 /* which serial port to use */
#endif
/*
* Miscellaneous configurable options
*/
#define CFG_LONGHELP /* undef to save memory */
#define CFG_PROMPT "ct@lab410 " /* Monitor Command Prompt 这里可以
自己改成在 uboot 中的显示名称 */
#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
#define CFG_MAXARGS 16 /* max number of command args */
#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */
#define CFG_MEMTEST_START 0x30000000 /* memtest works on */
#define CFG_MEMTEST_END 0x33F00000 /* 63 MB in DRAM */
#undef CFG_CLKS_IN_HZ /* everything, incl board info, in Hz */
#define CFG_LOAD_ADDR 0x33000000 /* default load address */
/* the PWM TImer 4 uses a counter of 15625 for 10 ms, so we need */
/* it to wrap 100 times (total 1562500) to get 1 sec. */
#define CFG_HZ 1562500
/* valid baudrates */
#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
/*-----------------------------------------------------------------------
* Stack sizes
*
* The stack sizes are set up in start.S using the settings below
*/
#define CONFIG_STACKSIZE (128*1024) /* regular stack */
#ifdef CONFIG_USE_IRQ
#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */
#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
#endif
#define CFG_ENV_IS_IN_FLASH 1
#define CFG_ENV_IS_IN_NAND 1
//添加上面两句话是为了确保 common/env_flash.c 和 common/env_nand.c 中的内容被编
译进 uboot,并且添加这两种情况环境变量保存位置信息:
/*-----------------------------------------------------------------------
* Physical Memory Map
*/
#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
#define PHYS_SDRAM_1 0x30000000 /* SDRAM Bank #1 */
#define PHYS_SDRAM_1_SIZE 0x04000000 /* 64 MB */
#define PHYS_FLASH_1 0x00000000 /* Flash Bank #1 */
#define CFG_FLASH_BASE PHYS_FLASH_1
/*-----------------------------------------------------------------------
* FLASH and environment organization
*/
#define CONFIG_SST_39VF1601 1
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
#define PHYS_FLASH_SIZE 0x00200000 /* 2MB */
#define CFG_MAX_FLASH_SECT (512) /* max number of sectors on one chip */ 这里
请关注我的另一片日记对于这个 512 的疑问
/*-----------------------------------------------------------------------
* NAND FLASH BOOT
*/
#define CONFIG_S3C2410_NAND_BOOT 1
#define STACK_BASE 0x33f00000
#define STACK_SIZE 0x8000
#define NAND_CTL_BASE 0x4e000000 //定义 nand flash 控制器的起始地
址
#define bINT_CTL(Nb) _REG(INT_CTL_BASE+(Nb))
#define oNFCONF 0x00
#define oNFCMD 0x04
#define oNFADDR 0x08
#define oNFDATA 0x0c
#define oNFSTAT 0x10
#define oNFECC 0x14
/*-----------------------------------------------------------------------
* NAND flash settings
*/
#define NAND_MAX_CHIPS 1
#define CFG_MAX_NAND_DEVICE 1
#define CFG_NAND_BASE 0
/* timeout values are in ticks */
#define CFG_FLASH_ERASE_TOUT (5*CFG_HZ) /* Timeout for Flash Erase */
#define CFG_FLASH_WRITE_TOUT (5*CFG_HZ) /* Timeout for Flash Write */
/*配置 nor 和 nand 的环境保存信息
#ifdef CFG_ENV_IS_IN_FLASH 1
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x1F0000) /* addr of
environment */
#endif
#ifdef CFG_ENV_IS_IN_NAND 1
#define CFG_ENV_SIZE 0x10000 /* Total Size of Environment Sector
*///64KB
#define CFG_ENV_OFFSET 0x40000
#endif
#endif /* __CONFIG_H */
7、由于自带的没有对 nandflash 的读写,所以要增加这个函数,
nand_read_ll 为新增加的 Nand Flash 读取方法,在 board/samsung/my2410 目录下新建
文件 nand_read.c
源文档
#include
#include "linux/mtd/mtd.h"
#include "linux/mtd/nand.h"
//#define LARGEPAGE_FLASH
#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))
#define NF_BASE 0x4e000000
#define NFCONF __REGi(NF_BASE + 0x0)
#define NFCMD __REGb(NF_BASE + 0x4)
#define NFADDR __REGb(NF_BASE + 0x8)
#define NFDATA __REGb(NF_BASE + 0xc)
#define NFSTAT __REGb(NF_BASE + 0x10)
#define BUSY 1
inline void wait_idle(void) {
int i;
while(!(NFSTAT & BUSY))
for(i=0; i<10; i++);
}
#ifndef LARGEPAGE_FLASH
#define NAND_SECTOR_SIZE 512
#else
#define NAND_SECTOR_SIZE 2048
#endif
#define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1)
/* low level nand read function */
int
nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
{
int i, j;
if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)){
//if ((start_addr & NAND_BLOCK_MASK) /*|| (size > SZ_1M)*/) {
return -1; /* invalid alignment */
}
/* chip Enable */
NFCONF &= ~0x800;
for(i=0; i<10; i++);
for(i=start_addr; i < (start_addr + size);) {
/* READ0 */
NFCMD = NAND_CMD_READ0;
/* Write Address */
#ifndef LARGEPAGE_FLASH
NFADDR = i & 0xff;
NFADDR = (i >> 9) & 0xff;
NFADDR = (i >> 17) & 0xff;
NFADDR = (i >> 25) & 0xff;
#else
NFADDR = i & 0xff;
NFADDR = (i >> 8) & 0x07;
NFADDR = (i >> 11) & 0xff;
NFADDR = (i >> 19) & 0xff;
NFADDR = (i >> 27) & 0x3;
NFCMD = NAND_CMD_READSTART;
#endif
wait_idle();
for(j=0; j < NAND_SECTOR_SIZE; j++) {
*buf = (NFDATA & 0xff);
buf++;
}
i += NAND_SECTOR_SIZE;
}
/* chip Disable */
NFCONF |= 0x800; /* chip disable */
return 0;
}
之后在 makefile 中增加最 nand_read 的编译,即:COBJS := my2410.o flash.o
nand_read.o
8、根据文档,修改板子目录下的 flash.c,以便支持 norflash
9、原生的 u-boot 没有对 nand 的驱动函数,这里得自己添加,这里可以参考完全手册
中第 nandflash 驱动的添加,注意手册上还增加了对 2440nand 的支持,我们这里不需
要,所以要去掉关于 2440 的设置
在 cpu/arm920t/s3c2410/s3c24x0 中增加如下函数,nand_flash.c
/*
* Changed from drivers/mtd/nand/s3c2410.c of kernel 2.6.13
*/