分类: 嵌入式
2011-03-22 09:38:50
基于AN2410SB的u-boot移植
首先u-boot的移植主要是修改以下几个文件夹:
board目录,cpu/arm920t目录,include/configs目录,lib_arm目录, common目录, rtc目录
其它目录不用修改
一、在U-Boot中建立自己的开发板类型,并测试编译。
我为开发板取名叫: AN2410SSB
1 在工作目录下解压U-Boot。
$tar
zxvf u-boot-1.2.0 tar.bz2
2 进入U-Boot目录,修改Makefile
$cd
u-boot-1.2.0/
$vi Makefile
#为AN24102440建立编译项
smdk2410_config:
unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
AN2410SB_config : unconfig
@$(MKCONFIG) $(@:_config=) arm
arm920t AN2410SSB AN s3c24x0
各项的意思如下:
arm: CPU的架构(ARCH)
arm920t: CPU的类型(CPU),其对应于cpu/arm920t子目录。
AN2410SSB: 开发板的型号(BOARD),对应于board/AN/AN2410SSB目录。
AN: 开发者/或经销商(vender)。
s3c24x0: 片上系统(SOC)。
3 在/board子目录中建立自己的开发板AN2410SSB目录
由于我在上一步板子的开发者/或经销商(vender)中填了 AN,所以开发板AN2410SSB目录一定要建在/board子目录中的AN目录下 ,否则编译会出错。
$cd board
$mkdir AN AN/AN2410SSB
$cp -arf smdk2410/* AN/AN2410SSB/
$cd AN/AN2410SSB/
$mv smdk2410.c AN2410SSB.c
$vi Makefile
还要记得修改自己的开发板AN2410SSB目录下的Makefile文件,不然编译时会出错:
COBJS := AN2410SSB.o
flash.o
4 在include/configs/中建立配置头文件
$cd
../../..
$cp include/configs/smdk2410.h include/configs/ AN2410SSB.h
5 测试编译能否成功
$make AN2410SSB
_config
Configuring for AN2410SSB board...
请在U-boot的根目录下的Makefile的
@$(MKCONFIG) $(@:_config=) arm arm920t AN2410SSB ...
前加上“Tab”键)
$make
二、修改U-Boot中的文件,以AN2410SSB实验板为基准。
1 修改/cpu/arm920t/start.S
(1)修改中断禁止部分
# if defined(CONFIG_S3C2410)
ldr
r1, =0x7ff //INTSUBMSK有11位可用(参考2410数据手册)
ldr
r0, =INTSUBMSK
str r1, [r0]
# endif
(2)将从Flash启动改成从NAND Flash启动。
将以下U-Boot的重定向语句段:
#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] */
cmp r0, r2
/* until source end addreee [r2] */
ble copy_loop
#endif /* CONFIG_SKIP_RELOCATE_UBOOT
*/
替换成:
#ifdef CONFIG_S3C2410_NAND_BOOT
@@@@@@@@@@@@@@@@SSSSSSS
@ reset NAND
mov r1, #NAND_CTL_BASE
ldr r2,
=0xf830 @ initial
value
str r2, [r1, #oNFCONF]
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
nand1:
add r3, r3, #0x1
cmp r3, #0xa
blt nand1
nand2:
ldr r2, [r1,
#oNFSTAT] @ wait ready
tst r2, #0x1
beq nand2
ldr r2, [r1,
#oNFCONF]
orr r2, r2,
#0x800
@ disable chip
str r2, [r1, #oNFCONF]
@ get read to call C functions (for nand_read())
ldr sp,
DW_STACK_START @ setup stack pointer
mov fp,
#0
@ no previous frame, so fp=0
@ copy U-Boot to RAM
ldr r0, =TEXT_BASE
mov r1, #0x0
mov r2, #0x20000
bl
nand_read_ll
tst r0, #0x0
beq ok_nand_read
bad_nand_read:
loop2:
b loop2
@ infinite loop
ok_nand_read:
@ 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:
loop3:
b loop3
@ infinite loop
#endif @ CONFIG_S3C2410_NAND_BOOT @@@@@@@@@@@@@@@@@@EEEE
在 “ _start_armboot: .word start_armboot
” 后加入:
.align 2
DW_STACK_START: .word STACK_BASE+STACK_SIZE-4
附:顺便提一下,在start.S文件的注释部分有个小错误(红色部分:原来是2):
cpu_init_crit:
......
/*
* disable MMU stuff and caches
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002300
@ clear bits 13, 9:8 (--V- --RS)
bic r0, r0, #0x00000087
@ clear bits 7, 2:0 (B--- -CAM)
orr r0, r0, #0x00000002
@ set bit 1 (A) Align
......
2 在board/AN/AN2410SSB加入NAND Flash读函数,建立nand_read.c文件,加入如下内容(copy from vivi):
#include
#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++);
}
/* 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)) {
return -1; /* invalid alignment
*/
}
/* chip
Enable */
NFCONF &= ~0x800;
for(i=0; i<10; i++);
for(i=start_addr; i < (start_addr + size);) {
/* READ0 */
NFCMD = 0;
/* Write Address */
NFADDR = i & 0xff;
NFADDR = (i >> 9) & 0xff;
NFADDR = (i >> 17) & 0xff;
NFADDR = (i >> 25) & 0xff;
wait_idle();
for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
*buf = (NFDATA & 0xff);
buf++;
}
}
/* chip
Disable */
NFCONF |= 0x800; /* chip disable */
return 0;
}
3 修改board/AN/AN2410SSB/Makefile文件
......
OBJS := AN2410SSB.o nand_read.o
......
4 修改include/configs/AN2410SSB.h文件,添加如下内容:
......
/*
* Nandflash Boot
*/
#define CONFIG_S3C2410_NAND_BOOT 1
#define STACK_BASE 0x33f00000
#define STACK_SIZE 0x8000
//#define UBOOT_RAM_BASE 0x33f80000
/* NAND Flash Controller */
#define
NAND_CTL_BASE
0x4E000000
#define bINT_CTL(Nb)
__REG(INT_CTL_BASE + (Nb))
/* Offset */
#define
oNFCONF
0x00
#define
oNFCMD
0x04
#define
oNFADDR
0x08
#define oNFDATA
0x0c
#define
oNFSTAT
0x10
#define
oNFECC
0x14
#endif
/* __CONFIG_H */
5 board/AN/AN2410SB/lowlevel_init.S文件(没有修改)
这不分主要涉及到寄存器配置,AN2410SSB的与smdk2410的大体相同,无需修改。经过我试验得出的。 smdk2410的网卡CS8900是在Bank3 AN2410SSB的网卡与之一样
6 board/AN/AN2410SB/ AN2410SB.c(没有修改)
7 为了实现NAND Flash的读写,再次修改
/include/configs/AN2410SB.h
/***********************************************************
* Command definition
***********************************************************/
#define CONFIG_COMMANDS \
(CONFIG_CMD_DFL | \
CFG_CMD_CACHE | \
CFG_CMD_NAND
| \
CFG_CMD_NET | \
/*CFG_CMD_EEPROM |*/ \
/*CFG_CMD_I2C |*/ \
/*CFG_CMD_USB |*/ \
CFG_CMD_PING | \
CFG_CMD_ENV
| \
CFG_CMD_REGINFO
| \
CFG_CMD_DATE | \
CFG_CMD_ELF)
/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include
//增加U-Boot对内核参数传递的功能,
......
#define CFG_LONGHELP
/* undef to save memory */
#define CFG_PROMPT
"[AN2410SSb]#"
/*Monitor Command Prompt */
#define CFG_CBSIZE
256
/* Console I/O Buffer Size */
......
#define CFG_LOAD_ADDR
0x30008000
/* default load address */
......
//#define PHYS_FLASH_1 0x00000000 /*
Flash Bank #1 */
//#define CFG_FLASH_BASE
PHYS_FLASH_1
/*-----------------------------------------------------------------------
* FLASH and environment organization
*/
#define CFG_NO_FLASH 1
#if 0
#define CONFIG_AMD_LV400 1 /*
uncomment this if you have a LV400 flash */
//#if 0
#define CONFIG_AMD_LV800 1 /* uncomment
this if you have a LV800 flash */
#endif
//#define CFG_MAX_FLASH_BANKS 1 /*
max number of memory banks */
......
/* 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 */
#define CFG_ENV_IS_IN_NAND 1
#define CFG_ENV_OFFSET 0X20000
//#define ENV_IS_EMBEDDED 1
#define CFG_NAND_LEGACY
#define CFG_ENV_SIZE 0x10000
/* Total Size of Environment Sector */
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#define CFG_NAND_BASE 0x4E000000
/* NandFlash控制器在SFR区起始寄存器地址 */
#define CFG_MAX_NAND_DEVICE 1
/* 支持的最在Nand
Flash数据 */
#define SECTORSIZE 512
/* 1页的大小 */
#define NAND_SECTOR_SIZE SECTORSIZE
#define NAND_BLOCK_MASK 511
/* 页掩码 */
#define ADDR_COLUMN 1
/* 一个字节的Column地址 */
#define ADDR_PAGE 3
/* 3字节的页块地址!!!!!*/
#define ADDR_COLUMN_PAGE 4
/* 总共4字节的页块地址!!!!!
*/
#define NAND_ChipID_UNKNOWN 0x00
/* 未知芯片的ID号 */
#define NAND_MAX_FLOORS 1
#define NAND_MAX_CHIPS 1
/* Nand Flash命令层底层接口函数 */
#define WRITE_NAND_COMMAND(d, adr) {rNFCMD = d;}
#define WRITE_NAND_ADDRESS(d, adr) {rNFADDR = d;}
#define WRITE_NAND(d, adr) {rNFDATA = d;}
#define READ_NAND(adr) (rNFDATA)
#define NAND_WAIT_READY(nand) {while(!(rNFSTAT&(1<<0)));}
#define NAND_DISABLE_CE(nand) {rNFCONF |= (1<<11);}
#define NAND_ENABLE_CE(nand) {rNFCONF &= ~(1<<11);}
/* the following functions are NOP's because S3C24X0 handles this in
hardware 一定要加上 */
#define NAND_CTL_CLRALE(nandptr)
#define NAND_CTL_SETALE(nandptr)
#define NAND_CTL_CLRCLE(nandptr)
#define NAND_CTL_SETCLE(nandptr)
/* 允许Nand
Flash写校验 */
#define CONFIG_MTD_NAND_VERIFY_WRITE 1
*
* Nandflash Boot
*/
#define CONFIG_S3C2410_NAND_BOOT 1
#define STACK_BASE 0x33f00000
#define STACK_SIZE 0x8000
//#define UBOOT_RAM_BASE 0x33f80000
/* NAND Flash Controller */
#define
NAND_CTL_BASE
0x4E000000
#define bINT_CTL(Nb)
__REG(INT_CTL_BASE + (Nb))
/* Offset */
#define
oNFCONF
0x00
#define oNFCMD
0x04
#define
oNFADDR
0x08
#define
oNFDATA
0x0c
#define
oNFSTAT
0x10
#define
oNFECC
0x14
#define rNFCONF (*(volatile unsigned int *)0x4e000000)
#define rNFCMD (*(volatile unsigned char *)0x4e000004)
#define rNFADDR (*(volatile unsigned char *)0x4e000008)
#define rNFDATA (*(volatile unsigned char *)0x4e00000c)
#define rNFSTAT (*(volatile unsigned int *)0x4e000010)
#define rNFECC (*(volatile unsigned int *)0x4e000014)
#define rNFECC0 (*(volatile unsigned char *)0x4e000014)
#define rNFECC1 (*(volatile unsigned char *)0x4e000015)
#define rNFECC2 (*(volatile unsigned char *)0x4e000016)
#endif /* CONFIG_COMMANDS & CFG_CMD_NAND*/
#endif /* __CONFIG_H */
8
在 include/linux/mtd/nand_ids.h的结构体nand_flash_ids加入
AN2410SSB的nand flash型号是Samsung K9F1208U0C。
static struct nand_flash_dev nand_flash_ids[] = {
......
{"Samsung KM29N16000",NAND_MFR_SAMSUNG, 0x64, 21,
1, 2, 0x1000, 0},
{"Samsung K9F1208U0C",
NAND_MFR_SAMSUNG, 0x76, 26, 0, 3, 0x4000, 0},
{"Samsung unknown 4Mb", NAND_MFR_SAMSUNG, 0x6b,
22, 0, 2, 0x2000, 0},
......
{NULL,}
};
9 修改/lib_arm中的board.c。
static int
display_banner (void)
{
printf ("\n\n%s\n\n", version_string);
debug ("U-Boot code: %08lX -> %08lX BSS: ->
%08lX\n",
_armboot_start,
_bss_start, _bss_end);
printf ("U-Boot code: %08lX
-> %08lX BSS: -> %08lX\n", //add
_armboot_start, _bss_start,
_bss_end); //add
#ifdef CONFIG_MODEM_SUPPORT
debug ("Modem Support enabled\n");
#endif
#ifdef CONFIG_USE_IRQ
debug ("IRQ Stack: %08lx\n", IRQ_STACK_START);
debug ("FIQ Stack: %08lx\n", FIQ_STACK_START);
#endif
return (0);
}
10 修改common/env_nand.c
......
#ifdef CONFIG_INFERNO
#error CONFIG_INFERNO not supported yet
#endif
int nand_legacy_rw (struct nand_chip* nand, int cmd,
size_t start, size_t len,
size_t * retlen, u_char * buf);
extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
extern int nand_legacy_erase(struct nand_chip *nand, size_t ofs, size_t len,
int clean);
/* info for NAND chips, defined in drivers/nand/nand.c */
extern nand_info_t nand_info[CFG_MAX_NAND_DEVICE];
......
#else /* ! CFG_ENV_OFFSET_REDUND */
int saveenv(void)
{
ulong total;
int ret = 0;
puts ("Erasing Nand...");
//if (nand_erase(&nand_info[0], CFG_ENV_OFFSET,
CFG_ENV_SIZE))
if (nand_legacy_erase(nand_dev_desc + 0, CFG_ENV_OFFSET, CFG_ENV_SIZE, 0))
return 1;
puts ("Writing to Nand... ");
total = CFG_ENV_SIZE;
//ret = nand_write(&nand_info[0], CFG_ENV_OFFSET,
&total, (u_char*)env_ptr);
ret = nand_legacy_rw(nand_dev_desc + 0,
0x00 | 0x02, CFG_ENV_OFFSET, CFG_ENV_SIZE,
&total, (u_char*)env_ptr);
if (ret || total !=
CFG_ENV_SIZE)
return 1;
puts ("done\n");
return ret;
......
#else /* ! CFG_ENV_OFFSET_REDUND */
/*
* The legacy NAND code saved the environment in the first NAND device
i.e.,
* nand_dev_desc + 0. This is also the behaviour using the new NAND code.
*/
void env_relocate_spec (void)
{
#if !defined(ENV_IS_EMBEDDED)
ulong total;
int ret;
total = CFG_ENV_SIZE;
//ret =
nand_read(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr);
ret = nand_legacy_rw(nand_dev_desc + 0, 0x01 | 0x02,
CFG_ENV_OFFSET, CFG_ENV_SIZE, &total, (u_char*)env_ptr);
......
11 在/board/AN/AN2410SSB/AN2410SSB.c文件的末尾添加对Nand Flash 的初始化函数(在后面Nand Flash的操作都要用到)
u-boot运行至第二阶段进入start_armboot()函数。其中nand_init()函数是对nand flash的最初初始化函数。Nand_init()函数在两个文件中实现。其调用与CFG_NAND_LEGACY宏有关,如果没有定义这个宏,系统调用 drivers/nnd/nand.c中的nand_init();否则调用自己在board/smdk2410/smdk2410.c中的nand_init()函数。这里我选择第二种方式。
#if (CONFIG_COMMANDS &
CFG_CMD_NAND)
typedef enum {
NFCE_LOW,
NFCE_HIGH
} NFCE_STATE;
static inline void
NF_Conf(u16 conf)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFCONF = conf;
}
static inline void NF_Cmd(u8
cmd)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFCMD = cmd;
}
static inline void NF_CmdW(u8
cmd)
{
NF_Cmd(cmd);
udelay(1);
}
static inline void NF_Addr(u8
addr)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFADDR = addr;
}
static inline void
NF_SetCE(NFCE_STATE s)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
switch (s) {
case NFCE_LOW:
nand->NFCONF &= ~(1<<11);
break;
case NFCE_HIGH:
nand->NFCONF |= (1<<11);
break;
}
}
static inline void
NF_WaitRB(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
while (!(nand->NFSTAT
& (1<<0)));
}
static inline void
NF_Write(u8 data)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFDATA = data;
}
static inline u8
NF_Read(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
return(nand->NFDATA);
}
static inline void
NF_Init_ECC(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFCONF |=
(1<<12);
}
static inline u32 NF_Read_ECC(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
return(nand->NFECC);
}
#endif
/*
* NAND flash initialization.
*/
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
extern ulong nand_probe(ulong physadr);
static inline void NF_Reset(void)
{
int i;
NF_SetCE(NFCE_LOW);
NF_Cmd(0xFF); /* reset command */
for(i = 0; i < 10; i++); /* tWB = 100ns. */
NF_WaitRB(); /* wait 200~500us; */
NF_SetCE(NFCE_HIGH);
}
static inline void NF_Init(void)
{
#if 0 /* a little bit too optimistic */
#define TACLS 0
#define TWRPH0 3
#define TWRPH1 0
#else
#define TACLS 0
#define TWRPH0 4
#define TWRPH1 2
#endif
NF_Conf((1<<15)|(0<<14)|(0<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0));
/*nand->NFCONF =
(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
*/
/* 1 1 1 1, 1 xxx, r xxx, r xxx */
/* En 512B 4step ECCR nFCE=H tACLS tWRPH0 tWRPH1 */
NF_Reset();
}
void
nand_init(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
NF_Init();
#ifdef DEBUG
printf("NAND flash probing at 0x%.8lX\n", (ulong)nand);
#endif
printf ("%4lu MB\n", nand_probe((ulong)nand) >> 20);
}
#endif
13 因为没有Nor Flash芯片,所以注释掉/common/cmd_bootm.c中关于imls命令的程序段和/common/cmd_flash.c中的程序。不然,按上面的修改,编译会出错。
/common/cmd_bootm.c第91行:(“0”后面一定要换行!!!不然还会错!!!)
#if 0
(CONFIG_COMMANDS & CFG_CMD_IMLS)
#include
extern flash_info_t flash_info[]; /* info for FLASH chips */
static int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
#endif
#if 0
(CONFIG_COMMANDS & CFG_CMD_IMLS)
/*-----------------------------------------------------------------------
* List all images found in flash.
*/
int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
flash_info_t *info;
int i, j;
image_header_t *hdr;
ulong data, len, checksum;
for (i=0, info=&flash_info[0]; i
......
......
#if 0
(CONFIG_COMMANDS & CFG_CMD_FLASH)
#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) &&
defined(CONFIG_JFFS2_CMDLINE)
#include
......
三、交叉编译U-Boot。
在U-Boot的根目录下
$make
结束~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
如果有什么错误的,请及时和我联系,我好修正改文章,因为从我移植到现在发表有一段时间了,具体过程大体是这样的,上面绿色部分是我比较
AN2410SSB和博创2410-S的硬件电路图,经过实验得出的结果。AN2410SSB和smdk2410的寄存器配置部分大体相同。