u-boot2012.04.01移植到mini2440
2015-11-06 13:13
393 查看
软件平台: Windows XP, Ubuntu
硬件平台: mini2440
软件: Source Insight、u-boot.2012.04.01 (官方下载源码)
一、uboot 启动分析
1.set the cpu to SVC32 mode(start.S)
2.turn off the watchdog
3.mask all IRQs by setting all bits in the INTMR
4.设置分频系数
5.cpu_init_crit
flush v4 I/D caches
disable MMU stuff and caches
lowlevel_init //setup RAM timing(lowlevel_init.S)
设置BWSCON
board_init_f //set sp, call board_init_f
init_sequence
(各种初始化)
...
board_early_init_f
...
serial_init
...
二、尝试
make smdk2410_config
make
成功生成的u-boot.bin并不能让mini2440启动
三、修改
1.修改根目录下boards.cfg在
smdk2410 arm arm920t - samsung s3c24x0
下添加一行
mini2440 arm arm920t
- samsung s3c24x0
2.make
mini2440_config
3.复制include\configs\smdk2410.h为include\configs\mini2440.h
4.cp board\samsung\smdk2410到board\samsung\mini2440
5.从start.S里可以看出,缺省认为60Mhz的HCLK来设置内存控制器,才设置系统时钟MPLL是有问题的。
因为没设置时钟时,是以晶振的频率运行的
注释掉(mini2440\smdk2410.c)int board_early_init_f(void)中的
#if
0
/*
configure MPLL */
writel((M_MDIV
<< 12) + (M_PDIV << 4) + M_SDIV,
&clk_power->mpllcon);
#endif
start.S修改分频设置
ldr
r0, =0x4C000014 /* FCLK提高到400Mhz,但HCLK不能超过133Mhz */
mov r1, #5 /*
FCLK:HCLK:PCLK = 1:4:8, HDIVN=10, PDIVN=1*/
str r1, [r0]
将MPLL的设置放到start.S
在分频后加上
/* 如果HDIVN非0,CPU的总线模式应该从“fast
bus mode”变为“asynchronous bus mode” */
mrc p15, 0, r1, c1, c0,
0 /* 读出控制寄存器 */
orr r1, r1, #0xc0000000 /*
设置为“asynchronous bus mode” */
mcr p15, 0, r1, c1, c0,
0 /* 写入控制寄存器 */
#define S3C2440_MPLL_400MHZ
((0x5c<<12)|(0x01<<4)|(0x01))
/*
MPLLCON = S3C2440_MPLL_200MHZ */
ldr r0, =0x4c000004
ldr r1, =S3C2440_MPLL_400MHZ
str r1, [r0]
/* 启动ICACHE */
mrc p15, 0, r0, c1, c0,
0 @ read control reg
orr r0, r0, #(1<<12)
mcr p15, 0, r0, c1, c0,
0 @ write it back
6.修改设置BWSCON的SMRDATA(lowlevel_init.S)
/*
BWSCON
[31]ST7:0 [27]ST6:0
[30]WS7:0 [26]WS6:0
[29:28]DW7:10 [25:24]DW6:10
only
bank6 and bank7 for sdram
[19]ST4:0
[18]WS4:1
[17:16]DW4:01
bank4 for DM9000
*/
.long
0x22050000 //BWSCON
/*
use the reset value */
.long
0x00000700 //BANKCON0
.long 0x00000700 //BANKCON1
.long 0x00000700 //BANKCON2
.long 0x00000700 //BANKCON3
.long 0x00000700 //BANKCON4
.long 0x00000700 //BANKCON5
/* MT [16:15] Determine
the memory type for bank6 and bank7
= 11 SDRAM
Trcd [3:2] RAS to
CAS delay, HCLK = 400Mhz/4 = 100Mhz
= 01 3 clocks (view
HY57V561620.pdf)
SCAN [1:0] Column
address number
= 01 9-bit (view
HY57V561620.pdf)
*/
.long 0x00018005 //BANKCON6
.long
0x00018005 //BANKCON7
/*
REFEN [23] SDRAM
Refresh Enable
= 1 Enable (self
or CBR/auto refresh)
TREFMD [22] SDRAM
Refresh Mode
= 0 CBR/Auto Refresh
Trp [21:20] SDRAM
RAS pre-charge Time
= 01 3 clocks (view
HY57V561620.pdf)
Tsrc [19:18] SDRAM
Semi Row cycle time, Trc=Tsrc+Trp => Tsrc=Trc-Trp => 9-3
= 10 6 clocks (view
HY57V561620.pdf)
Refresh Counter [10:0]
SDRAM refresh count value.
Refresh period =
(2^11-refresh_count+1)/HCLK
refresh_count = 64/8192
ms = 7.8125us
Rp = 2^11 + 1 - 135.75*7.8125
= 988 = 0x3dc
*/
.long
0x009803dc //REFRESH
/*
BURST_EN [7] ARM core burst operation enable.
= 1 Enable burst
operation
SCKE_EN [5] SDRAM
power down mode enable control by SCKE
= 1 SDRAM power down
mode enable
SCLK_EN [4]
= 1 SCLK is active
only during the access (recommended)
BK76MAP [2:0] BANK6/7
memory map
= 001 64MB/64MB
*/
.long
0x000000B1 //BANKSIZE
/*
CL [6:4] CAS latency
= 011 3 clocks
*/
.long
0x00000030 //MRSRB6
.long 0x00000030 //MRSRB7
再次make,并烧写u-boot.bin到nor
flash,启动后发现是乱码,应该是串口波特率问题,看看串口初始化
![](http://blog.chinaunix.net/attachment/201303/11/22609852_1362997247edSL.jpg)
7.board.c (z:\u-boot-2012.04.01\arch\arm\lib\Board.c)
serial_init(z:\u-boot-2012.04.01\drivers\serial\Serial_s3c24x0.c)
serial_init_dev
_serial_setbrg
get_PCLK(z:\u-boot-2012.04.01\arch\arm\cpu\arm920t\s3c24x0\Speed.c)
get_HCLK
发现没有定义CONFIG_S3C2440,它用2410的那套
那么在config中的mini2440.h中去掉#define
CONFIG_S3C2410改成#define CONFIG_S3C2440
make发现多个错误
s3c2410_nand.c:
In function 's3c2410_hwcontrol':
s3c2410_nand.c:57:
warning: implicit declaration of function 's3c2410_get_base_nand'
s3c2410_nand.c:57:
warning: initialization makes pointer from integer without a cast
s3c2410_nand.c:72: error:
dereferencing pointer to incomplete type
s3c2410_nand.c:72:
error: dereferencing pointer to incomplete type
s3c2410_nand.c:75:
error: dereferencing pointer to incomplete type
s3c2410_nand.c:75:
error: dereferencing pointer to incomplete type
s3c2410_nand.c:
In function 's3c2410_dev_ready':
s3c2410_nand.c:85:
warning: initialization makes pointer from integer without a cast
s3c2410_nand.c:87:
error: dereferencing pointer to incomplete type
s3c2410_nand.c:
In function 'board_nand_init':
s3c2410_nand.c:129:
warning: initialization makes pointer from integer without a cast
s3c2410_nand.c:150:
error: dereferencing pointer to incomplete type
s3c2410_nand.c:153:
error: dereferencing pointer to incomplete type
s3c2410_nand.c:154:
error: dereferencing pointer to incomplete type、
s3c2410_nand.c找错误,发现是因为更改了#define CONFIG_S3C2440后,s3c2410_nand未定义
暂且先让串口输出正常看看,去掉nand支持。
[root: u-boot-2012.04.01]# grep
"s3c2410_nand.o" * -nR
drivers/mtd/nand/Makefile:61:COBJS-$(CONFIG_NAND_S3C2410)
+= s3c2410_nand.o
drivers/mtd/nand/.depend.s3c2410_nand:1:s3c2410_nand.o:
s3c2410_nand.c \
drivers/mtd/nand/.depend:341:s3c2410_nand.o:
s3c2410_nand.c \
[root: u-boot-2012.04.01]# vi
drivers/mtd/nand/Makefile
找到
COBJS-$(CONFIG_NAND_S3C2410)
+= s3c2410_nand.o
现取消CONFIG_NAND_S3C2410的定义,在mini2440.h中发现
#ifdef CONFIG_CMD_NAND
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_BASE 0x4E000000
#endif
则注释掉//#define CONFIG_CMD_NAND
再编译提示
fs/yaffs2/libyaffs2.o:
In function `yaffs_StartUp':
/home/profiles/u-boot-2012.04.01/fs/yaffs2/yaffscfg.c:210: undefined reference to `nand_info'
还是在mini2440.h中先注释掉
//#define CONFIG_YAFFS2
再次make,并烧写u-boot.bin到nor
flash,启动后发现Flash: *** failed ***,串口正常了,只是flash还有问题
8.为了去掉原u-boot复杂的重定位代码,现自己写重定位代码,将init.c添加到board/samsung/mini2440下。修改
board/samsung/mini2440/Makefile
改COBJS := smdk2410.o init.o
init.c内容如下
点击(此处)折叠或打开
#define NFCONF (*((volatile
unsigned long *)0x4E000000))
#define NFCONT (*((volatile
unsigned long *)0x4E000004))
#define NFCMMD (*((volatile
unsigned char *)0x4E000008)) //注意是char* 不是long*,与下面保持一致
#define NFADDR (*((volatile
unsigned char *)0x4E00000C))
#define NFDATA (*((volatile
unsigned char *)0x4E000010))
#define NFSTAT (*((volatile
unsigned char *)0x4E000020))
void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len);
static int isNor()
{
volatile int *p = (volatile int *)0;
int val;
val = *p;
*p = 0xfdfdfdfd;
if(0xfdfdfdfd == *p) //可写,证明是在SRAM中运行,即是从NAND启动
{
*p = val;
return 0;
}
else //写NOR需要特定的命令时序
{
return 1;
}
}
void copy_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)
{
int i = 0;
/* 判断启动方式 */
if (isNor())
{
while(i < len)
{
dest[i] = src[i]; //直接读
NOR(view Figure 5-1. S3C2440A Memory Map after Reset)
i++;
}
}
else
{
nand_read_ll((unsigned int)src, dest, len);
}
}
void clear_bss(void)
{
extern int __bss_start, __bss_end__;
int *p = &__bss_start;
for(; p<=&__bss_end__; p++)
{
*p = 0;
}
}
void nand_init_ll(void)
{
/* NFCONF
TACLS [13:12] CLE & ALE
duration setting value (0~3)
= 0 Duration = HCLK x TACLSHCLK x TACLS (view K9F1208.pdf)
TWRPH0 [10:8] TWRPH0 duration setting value (0~7)
Duration = HCLK x ( TWRPH0 + 1 ) = 25ns (view
K9F1208.pdf) 1/135.75 = 7ns
= 3 TWRPH0 >= 25 / 7 - 1 = 2.57
TWRPH1 [6:4] TWRPH1 duration setting value (0~7)
Duration = HCLK x ( TWRPH1 + 1 ) = 10ns (view
K9F1208.pdf)
= 1 TWRPH1 >= 10 / 7 - 1 = 0.42
*/
#define TACLS 0
#define TWRPH0 3
#define TWRPH1 1
NFCONF = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);
/* NFCONT
InitECC [4] Initialize ECC decoder/encoder(Write-only)
= 1 Initialize ECC decoder/encoder
Reg_nCE [1] NAND Flash Memory nFCE signal control
= 1 Force nFCE to high (Disable chip select)
MODE [0] NAND flash controller operating mode
= 1 NAND flash controller enable
*/
NFCONT = (1<<4) | (0<<1) | (1<<0);
}
static void nand_select(void)
{
NFCONT &= ~(1<<1);
}
static void nand_deselect(void)
{
NFCONT |= (1<<1);
}
static void nand_cmd(unsigned char cmd)
{
volatile int i;
NFCMMD = cmd;
for (i = 0; i < 10; i++);
}
static void nand_addr(unsigned int addr)
{
/* Address(5Cycle)
Col Add.1,2 & Row Add.1,2,3
*/
int col = addr % 2048;
int row = addr / 2048;
volatile int i;
NFADDR = col & 0xff;
for(i=0; i<10; i++);
NFADDR = (col>>8) & 0xff;
for(i=0; i<10; i++);
NFADDR = row & 0xff;
for(i=0; i<10; i++);
NFADDR = (row>>8) & 0xff;
for(i=0; i<10; i++);
NFADDR = (row>>16) & 0xff;
for(i=0; i<10; i++);
}
static void nand_wait(void)
{
while(!(NFSTAT&1));
}
void nand_read_ll(unsigned int addr, unsigned char *dest, unsigned int len)
{
int col = addr % 2048, i = 0;
nand_select();
while(i < len)
{
/* view K9K8G08U0A.pdf */
nand_cmd(0x00);
nand_addr(addr);
nand_cmd(0x30);
nand_wait();
for(; col<2048 && i<len; col++)
{
dest[i] = NFDATA;
i++;
addr++;
}
col = 0;
}
nand_deselect();
}
修改start.S
#ifndef
CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic sp, sp, #7 /* 8-byte
alignment for ABI compliance */
bl
nand_init_ll
mov
r0, #0
//ldr r1, =_start
ldr r1, _TEXT_BASE //CONFIG_SYS_TEXT_BASE
= 0x33f00000
ldr r2, _bss_start_ofs
bl
copy_to_sdram //copy_to_sdram(r0, r1, r2)
bl clear_bss
ldr
pc, =call_board_init_f //远跳转
/*
Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
ldr
r0,=0x00000000
bl board_init_f
修改mini2440.h中#define CONFIG_SYS_TEXT_BASE
0x33f80000
自己写了重定位,就去掉它写的重定位函数
注释掉掉board.c中board_init_f中//relocate_code(addr_sp,
id, addr);
删掉start.S中下面不需要的代码
点击(此处)折叠或打开
/*------------------------------------------------------------------ ------------*/
/*
* void relocate_code (addr_sp, gd, addr_moni)
*
* This "function" does not return, instead
it continues in RAM
* after relocating the monitor code.
*
*/
.globl relocate_code
relocate_code:
mov r4, r0 /* save addr_sp */
mov r5, r1 /* save addr of gd */
mov r6, r2 /* save addr of destination */
/* Set up the stack */
stack_setup:
mov sp, r4
adr r0, _start
cmp r0, r6
beq clear_bss /* skip relocation */
mov r1, r6 /* r1 <- scratch for copy_loop */
ldr r3, _bss_start_ofs
add r2, r0, r3 /* r2 <- source
end address */
copy_loop:
ldmia {r9-r10} /* copy from source address [r0] */
stmia {r9-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end address [r2] */
blo copy_loop
#ifndef CONFIG_SPL_BUILD
/*
* fix .rel.dyn relocations
*/
ldr r0, _TEXT_BASE /* r0 <- Text
base */
sub r9, r6, r0 /* r9 <- relocation
offset */
ldr r10, _dynsym_start_ofs /* r10 <- sym
table ofs */
add r10, r10, r0 /* r10 <- sym
table in FLASH */
ldr r2, _rel_dyn_start_ofs /* r2 <- rel
dyn start ofs */
add r2, r2, r0 /* r2 <- rel
dyn start in FLASH */
ldr r3, _rel_dyn_end_ofs /* r3 <- rel
dyn end ofs */
add r3, r3, r0 /* r3 <- rel
dyn end in FLASH */
fixloop:
ldr r0, [r2] /* r0 <- location
to fix up, IN */
add r0, r0, r9 /* r0 <- location
to fix up in RAM */
ldr r1, [r2, #4]
and r7, r1, #0xff
cmp r7, #23 /* relative fixup? */
beq fixrel
cmp r7, #2 /* absolute fixup? */
beq fixabs
/* ignore unknown type of fixup */
b fixnext
fixabs:
/* absolute fix: set location to (offset) symbol
value */
mov r1, r1, LSR #4 /* r1 <- symbol
index in .dynsym */
add r1, r10, r1 /* r1 <- address of symbol in table */
ldr r1, [r1, #4]
/* r1 <- symbol value */
add r1, r1, r9 /* r1 <- relocated
sym addr */
b fixnext
fixrel:
/* relative fix: increase location by offset */
ldr r1, [r0]
add r1, r1, r9
fixnext:
str r1, [r0]
add r2, r2, #8 /* each
rel.dyn entry is 8 bytes */
cmp r2, r3
blo fixloop
#endif
clear_bss:
#ifndef CONFIG_SPL_BUILD
ldr r0, _bss_start_ofs
ldr r1, _bss_end_ofs
mov r4, r6 /* reloc addr */
add r0, r0, r4
add r1, r1, r4
mov r2, #0x00000000 /* clear */
clbss_l:str r2, [r0]
/* clear loop... */
add r0, r0, #4
cmp r0, r1
bne clbss_l
bl coloured_LED_init
bl red_led_on
#endif
因为第二阶段函数board_init_f需要
修改函数定义
unsigned int board_init_f (ulong);(common.h)
unsigned int board_init_f(ulong bootflag) (arch/arm/lib/board.c)
函数体最后加上
return
(unsigned int)id;
返回后给start.S的第二阶段代码用
在start.S
ldr r0,=0x00000000
bl board_init_f
后加上
//board_init_f的返回值在r0里面,刚好把id传给board_init_r
ldr r1, _TEXT_BASE
bl board_init_r
vi
arch/arm/config.mk
注释掉
#LDFLAGS_u-boot
+= -pie
修改
arch/arm/cpu/u-boot.lds添加 board/samsung/mini2440/libmini2440.o
(.text)
.text :
{
__image_copy_start = .;
CPUDIR/start.o (.text)
board/samsung/mini2440/libmini2440.o
(.text)
*(.text)
}
修改board.c
//addr -= gd->mon_len;
//addr &= ~(4096
- 1);
addr
= CONFIG_SYS_TEXT_BASE;
make后烧写发现
![](http://blog.chinaunix.net/attachment/201303/11/22609852_1362998490uk3f.jpg)
9.在SI中搜索"Flash:“
(z:\u-boot-2012.04.01\arch\arm\lib\Board.c)
#if !defined(CONFIG_SYS_NO_FLASH)
puts("Flash: ");
继续看
if (flash_size > 0) {
...
}else {
puts(failed);
//输出*** failed ***
hang();
//挂起
}
void hang(void)
{
puts("###
ERROR ### Please RESET the board ###\n");
for
(;;); //死循环
}
注释掉//hang();
再次make,并烧写u-boot.bin到nor
flash,发现uboot是启动起来了不过flash和nand都不识别
![](http://blog.chinaunix.net/attachment/201303/11/22609852_1362998626R55z.jpg)
10.定义#define DEBUG (z:\u-boot-2012.04.01\include\configs\Mini2440.h)
方便调试
![](http://blog.chinaunix.net/attachment/201303/11/22609852_1362998710rVDh.jpg)
11.找nor的识别问题
从图中JEDEC
PROBE: ID 1 2249 0和代码(z:\u-boot-2012.04.01\drivers\mtd\Cfi_flash.c)
debug("JEDEC
PROBE: ID %x %x %x\n",
info->manufacturer_id,
info->device_id,
info->device_id2);
可以看出manufacturer_id是1,device_id是2249,device_id2是0
flash_init (z:\u-boot-2012.04.01\drivers\mtd\Cfi_flash.c)
flash_detect_legacy
//
match jedec ids against table. If a match is found, fill flash_info entry
jedec_flash_match
(z:\u-boot-2012.04.01\drivers\mtd\Jedec_flash.c)
if
((jedec_table[i].mfr_id & mask) == (info->manufacturer_id
& mask) &&
(jedec_table[i].dev_id
& mask) == (info->device_id & mask)) {
fill_info(info, &jedec_table[i], base);
ret = 1;
break;
}
可以看到manufacturer_id、device_id都要和jedec_table中的信息匹配。
添加mini2440用的nor
flash信息(需要查看芯片手册Am29LV160DB.pdf)
{
.mfr_id = 1,
.dev_id = 0x2249,
.name
= "Am29LV160DB",
.uaddr = {
[1] = MTD_UADDR_0x0555_0x02AA /* x16 */
},
.DevSize = SIZE_2MiB,
.CmdSet = CFI_CMDSET_AMD_LEGACY,
.NumEraseRegions = 4,
.regions = {
ERASEINFO(0x04000, 1),
ERASEINFO(0x02000,
2),
ERASEINFO(0x08000,
1),
ERASEINFO(0x10000, 31),
}
},
![](http://blog.chinaunix.net/attachment/201303/11/22609852_1362999028s4EE.jpg)
取消DEBUG定义(看之前的DEBUG信息足以),再次编译烧写
12.提示Flash: ERROR: too many flash sectors
搜索发现#define CONFIG_SYS_MAX_FLASH_SECT
(19) //(z:\u-boot-2012.04.01\include\configs\Mini2440.h)
修改大一点#define CONFIG_SYS_MAX_FLASH_SECT
(128)
make烧写,Flash:2 MiB.
![](http://blog.chinaunix.net/attachment/201303/11/22609852_13629990619Vdv.jpg)
13.修改栈指针
start.S中加上
.globl base_sp
base_sp:
.long 0
start_code:
.....
ldr
r1, _TEXT_BASE
ldr
sp, base_sp
bl
board_init_r
在board.c的board_init_f加上
extern
ulong base_sp;
...
memcpy(id, (void *)gd, sizeof(gd_t));
base_sp
= addr_sp;
//relocate_code(addr_sp,
id, addr);
14.加上nand的支持
在mini2440.h中取消注释
#define CONFIG_CMD_NAND
make出错,拷贝drivers/mtd/nand/s3c2410_nand.c复制为s3c2440_nand.c
修改mini2440.h
#ifdef CONFIG_CMD_NAND
#ifdef
CONFIG_S3C2410
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
#else
#define
CONFIG_NAND_S3C2440
#define CONFIG_SYS_S3C2440_NAND_HWECC
#endif
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_BASE 0x4E000000
#endif
修改drivers/mtd/nand/Makefile
加上
COBJS-$(CONFIG_NAND_S3C2410)
+= s3c2410_nand.o
COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o
修改s3c2440_nand.c中的s3c2410_nand为s3c2440_nand(除了宏)
包括s3c2440_dev_ready、s3c2440_hwcontrol、s3c2440_get_base_nand
从nand_init开始看
nand_init_chip
board_nand_init
...
tacls
= 4;
twrph0
= 8;
twrph1
= 8;
#endif
cfg = S3C2410_NFCONF_EN;
cfg |= S3C2410_NFCONF_TACLS(tacls
- 1);
cfg |= S3C2410_NFCONF_TWRPH0(twrph0
- 1);
cfg |= S3C2410_NFCONF_TWRPH1(twrph1
- 1);
writel(cfg, &nand_reg->nfconf);
/*
NFCONF
TACLS [13:12]
CLE & ALE duration setting value (0~3)
= 0
Duration = HCLK x TACLSHCLK x TACLS (view K9F1208.pdf)
TWRPH0 [10:8]
TWRPH0 duration setting value (0~7)
Duration
= HCLK x ( TWRPH0 + 1 ) = 25ns (view K9F1208.pdf) 1/135.75 = 7ns
= 3
TWRPH0 >= 25 / 7 - 1 = 2.57
TWRPH1 [6:4]
TWRPH1 duration setting value (0~7)
Duration
= HCLK x ( TWRPH1 + 1 ) = 10ns (view K9F1208.pdf)
= 1 TWRPH1
>= 10 / 7 - 1 = 0.42
*/
cfg = ((tacls-1)<<12) | ((tacls-1)<<8)
| ((tacls-1)<<4);
writel(cfg, &nand_reg->nfconf);
/*
NFCONT
InitECC
[4] Initialize ECC decoder/encoder(Write-only)
= 1 Initialize
ECC decoder/encoder
Reg_nCE
[1] NAND Flash Memory nFCE signal control
= 1 Force
nFCE to high (Disable chip select)
MODE [0]
NAND flash controller operating mode
= 1 NAND
flash controller enable
*/
writel((1<<4) | (0<<1) | (1<<0),
&nand_reg->nfcont);
...
nand->select_chip
= NULL;
//修改为nand->select_chip
= s3c2440_select_nand;
自己写
static void s3c2440_select_nand(struct
mtd_info *mtd, int chipnr)
{
struct
s3c2440_nand *nand = s3c2440_get_base_nand();
switch (chipnr) {
case -1: //-1 for deselect
nand->nfcont
|= 1<<1;
break;
case
0: //0 for select
nand->nfcont
&= ~(1<<1);
break;
default:
BUG();
}
}
nand->cmd_ctrl
= s3c2440_hwcontrol;
//修改s3c2410_hwcontrol,根据ctrl判断是发命令还是地址
static void s3c2410_hwcontrol(struct mtd_info *mtd, int dat, unsigned int ctrl)
{
struct s3c2440_nand *nand = s3c2440_get_base_nand();
debug("hwcontrol(): 0x%02x 0x%02x\n", dat, ctrl);
if (ctrl & NAND_CLE)
{
writeb(dat,
&nand->nfcmd);
}
else if (ctrl & NAND_ALE)
{
writeb(dat,
&nand->nfaddr);
}
}
...
nand_scan
nand_scan_ident
nand_set_defaults
if
(chip->cmdfunc == NULL)
chip->cmdfunc = nand_command; //static
void nand_command(struct mtd_info *mtd, unsigned int command, int column, int page_addr)
if
(!chip->select_chip)
chip->select_chip = nand_select_chip;
nand_get_flash_type
chip->select_chip(mtd,
0);
chip->cmdfunc(mtd,
NAND_CMD_READID, 0x00, -1);
<=>nand_command
chip->cmd_ctrl(mtd, readcmd, ctrl);
<=>s3c2410_hwcontrol;
nand_register
add_mtd_device
make后nand可以正常使用了
15.mini2440用dm9000网卡,搜索drivers/net/Makefile 可以发现
COBJS-$(CONFIG_DRIVER_DM9000)
+= dm9000x.o
由mini2440.h中的宏CONFIG_DRIVER_DM9000控制,并且从上面结果可以看到,需要去掉cs8900的宏.
#if 0
#define CONFIG_CS8900
/* we have a CS8900 on-board */
#define CONFIG_CS8900_BASE
0x19000300
#define CONFIG_CS8900_BUS16
/* the Linux driver does accesses as shorts */
#else
#define
CONFIG_DRIVER_DM9000
#endif
make看看结果
dm9000x.c:
In function 'dm9000_outblk_8bit':
dm9000x.c:156:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:156:
error: (Each undeclared identifier is reported only once
dm9000x.c:156:
error: for each function it appears in.)
dm9000x.c:
In function 'dm9000_outblk_16bit':
dm9000x.c:165:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:
In function 'dm9000_outblk_32bit':
dm9000x.c:173:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:
In function 'dm9000_inblk_8bit':
dm9000x.c:180:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:
In function 'dm9000_inblk_16bit':
dm9000x.c:189:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:
In function 'dm9000_inblk_32bit':
dm9000x.c:197:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:
In function 'dm9000_rx_status_32bit':
dm9000x.c:204:
error: 'DM9000_IO' undeclared (first use in this function)
dm9000x.c:206:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:
In function 'dm9000_rx_status_16bit':
dm9000x.c:213:
error: 'DM9000_IO' undeclared (first use in this function)
dm9000x.c:215:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:
In function 'dm9000_rx_status_8bit':
dm9000x.c:221:
error: 'DM9000_IO' undeclared (first use in this function)
dm9000x.c:224:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:
In function 'dm9000_probe':
dm9000x.c:243:
error: 'CONFIG_DM9000_BASE' undeclared (first use in this function)
dm9000x.c:
In function 'dm9000_send':
dm9000x.c:420:
error: 'DM9000_IO' undeclared (first use in this function)
dm9000x.c:
In function 'dm9000_rx':
dm9000x.c:484:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:
In function 'DM9000_ior':
dm9000x.c:574:
error: 'DM9000_IO' undeclared (first use in this function)
dm9000x.c:575:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:
In function 'DM9000_iow':
dm9000x.c:584:
error: 'DM9000_IO' undeclared (first use in this function)
dm9000x.c:585:
error: 'DM9000_DATA' undeclared (first use in this function)
make[1]:
*** [dm9000x.o] Error 1
make[1]:
Leaving directory `/home/profiles/u-boot-2012.04.01/drivers/net'
make:
*** [drivers/net/libnet.o] Error 2
报错
grep
"DM9000_DATA" * -nR参考其他开发板
include/configs/M5253DEMO.h:95:#
define DM9000_DATA (CONFIG_DM9000_BASE + 4)
定义了
#
define CONFIG_DM9000_BASE (CONFIG_SYS_CS1_BASE | 0x300)
#
define DM9000_IO CONFIG_DM9000_BASE
#
define DM9000_DATA (CONFIG_DM9000_BASE + 4)
则在mini2440.h上加上这些宏,并把值参照原理图芯片手册,DM9000接片选4即bank4,由2440手册知0x20000000是bank4的基址修改过来为:
#define
CONFIG_DM9000_BASE 0x20000000
#define
DM9000_IO CONFIG_DM9000_BASE
#define
DM9000_DATA (CONFIG_DM9000_BASE + 4) //LADDR2开始接到DM9000上
内存控制器初始化已经在lowlevel.S中设置过为
SMRDATA:
.long 0x22050000 //BWSCON
make烧写从nor启动,发现Net:
No ethernet found.
![](http://blog.chinaunix.net/attachment/201303/11/22609852_13630002221lCZ.jpg)
16.在source insight中搜索“No
ethernet found.”找出原因
eth_initialize (board.c)
board_eth_init (mini2440/smdk2410.c)
cs8900_initialize此处不合适,添加DM9000的函数
#ifdef
CONFIG_CS8900
rc = cs8900_initialize(0, CONFIG_CS8900_BASE);
#endif
#ifdef
CONFIG_DRIVER_DM9000
rc
= dm9000_initialize(bis);
#endif
再次make烧写来试验网络功能
set
ipaddr 169.254.252.201 (连上网线同自己要ping的机器在一个网段)
set
serverip 169.254.252.200
set
gatewayip 255.255.0.0 (同自己要ping的机器一致)
set
ethaddr 08:00:27:71:89:bb
ping
169.254.252.200 通了
![](http://blog.chinaunix.net/attachment/201303/11/22609852_1363000464vd4p.jpg)
自行测试下tftp的下载功能。
tftp
30000000 uImage
发面bootm
30000000后不能启动linux,在解压后停住了。应该是开发板型号没修改
修改board_init(board.c)中
gd->bd->bi_arch_number
= MACH_TYPE_SMDK2410;为
gd->bd->bi_arch_number
= MACH_TYPE_MINI2440;
再次tftp下载后bootm就启动了
17.环境变量
开发板烧写u-boot后,发现***
Warning - bad CRC, using default environment
SI搜索一下。
set_default_env
default_environment
#ifdef CONFIG_BOOTARGS
"bootargs=" CONFIG_BOOTARGS
"\0"
#ifdef CONFIG_BOOTCOMMAND
"bootcmd=" CONFIG_BOOTCOMMAND
"\0"
在mini2440.h中加上
#define CONFIG_BOOTARGS
"console=ttySAC0 root=/dev/mtdblock3"
#define
CONFIG_BOOTCOMMAND "nand read 30000000 0x60000 0x500000;bootm 30000000"
修改
#define
CONFIG_NETMASK 255.255.0.0
#define CONFIG_IPADDR
169.254.252.201
#define CONFIG_SERVERIP
169.254.252.200
加上
#define CONFIG_ETHADDR
08:00:27:71:89:bb
18.裁剪
在mini2440.h找不需要的宏
#if 0
#define
CONFIG_USB_OHCI
#define
CONFIG_USB_KEYBOARD
#define
CONFIG_USB_STORAGE
#define
CONFIG_DOS_PARTITION
#endif
//#define
CONFIG_RTC_S3C24X0
#if
0
#define
CONFIG_BOOTP_BOOTFILESIZE
#define
CONFIG_BOOTP_BOOTPATH
#define
CONFIG_BOOTP_GATEWAY
#define
CONFIG_BOOTP_HOSTNAME
#endif
//#define
CONFIG_CMD_USB
//#define
CONFIG_CMD_DATE
//#define
CONFIG_CMD_DHCP
#if
0
#define
CONFIG_CMD_FAT
#define
CONFIG_CMD_EXT2
#define
CONFIG_CMD_UBI
#define
CONFIG_CMD_UBIFS
#define
CONFIG_CMD_MTDPARTS
#define
CONFIG_MTD_DEVICE
#define
CONFIG_MTD_PARTITIONS
#define
CONFIG_YAFFS2
#define
CONFIG_RBTREE
#endif
裁剪后make发现
u-boot.bin的大小为204344B小了很多
19.环境变量默认存在nor,为了让u-boot里面的saveenv命令将环境变量保存到nand,且不能破坏内核,需要修改保存的位置。
在SI中搜索"saveenv",找到env_nand.c文件,到Makefile中找寻它所依赖的宏.
vi
common/Makefile,发现它依赖于CONFIG_ENV_IS_IN_NAND
(mini2440.h)修改
#if 0
#define CONFIG_ENV_ADDR
(CONFIG_SYS_FLASH_BASE + 0x070000)
#define CONFIG_ENV_IS_IN_FLASH
#define CONFIG_ENV_SIZE
0x10000
/* allow to overwrite
serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
#endif
添加
#define CONFIG_ENV_IS_IN_NAND
在env_nand.c中找到宏CONFIG_ENV_OFFSET,这个制定存在nand的哪个地址
需要看看原内核的分区。
在我使用的2.6.32.2源代码中发现
static struct mtd_partition friendly_arm_default_nand_part[]
= {
[0]
= {
.name
= "supervivi",
.size
= 0x00040000,
.offset
= 0,
},
[1]
= {
.name
= "param",
.offset
= 0x00040000,
.size
= 0x00020000,
},
[2]
= {
.name
= "Kernel",
.offset
= 0x00060000,
.size
= 0x00500000,
},
[3]
= {
.name
= "root",
.offset
= 0x00560000,
.size
= 1024 * 1024 * 1024, //
},
[4]
= {
.name
= "nand",
.offset
= 0x00000000,
.size
= 1024 * 1024 * 1024, //
}
};
(或者启动内核后发现)
![](http://blog.chinaunix.net/attachment/201303/11/22609852_1363001228D6B2.jpg)
参数存在0x40000开始的0x20000大小处
则加定义(mini2440.h)
#define CONFIG_ENV_OFFSET
0x40000
#define CONFIG_ENV_SIZE
0x20000
#define CONFIG_ENV_RANGE
CONFIG_ENV_SIZE //擦除单位
make后烧写nor
此时还有***
Warning - bad CRC, using default environment
在u-boot里执行save命令重启就行了
u-boot倒计时5秒如果没有执行的话,就会执行我们设置的
#define CONFIG_BOOTCOMMAND "nand
read 30000000 0x60000 0x500000;bootm 30000000"
即从nand flash 0x60000的地方读0x500000的数据(整个内核)到内存0x30000000的地方,然后从0x30000000启动内核。
于是我们必须先将uImage烧写到0x60000的地方:
先下载tftp
30000000 uImage
nand
erase 60000 500000
nand
write 30000000 60000 500000 //这样60000的地方就有了可启动的内核
下次重启开发板,5秒延时之后将自动读内核并加载运行
20.代替繁琐的数字
在board.c的board_init_r中加上
run_command("mtdparts
default", 0); //必须让uboot执行这条命令
/*
main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop();
}
在mini2440中定义宏
#define
CONFIG_CMD_MTDPARTS
参照其它开发板再添加上
#define
CONFIG_MTD_DEVICE
#define MTDIDS_DEFAULT "nand0=mini2440-0"
#define MTDPARTS_DEFAULT
"mtdparts=mini2440-0:256k(u-boot)," \
"128k(params)," \
"5m(kernel),"
\
"-(rootfs)"
\ //-余下的所有给rootfs
make后提示发现drivers\mtd\mtdcore.c中的get_mtd_device_nm未定义。
则可以直接去drivers\mtd\Makefile中查看哪个宏决定是否编译成mtdcore.o
或者grep
"mtdcore.o" * -nR发现是CONFIG_MTD_DEVICE控制的
将宏添加到mini2440.h
#define CONFIG_MTD_DEVICE
再次make并烧写
在uboot执行命令mtdparts
![](http://blog.chinaunix.net/attachment/201303/11/22609852_1363001667Z74J.jpg)
现在可以尝试用名字代替数字的分区表示,如
tftp
30000000 uImage
nand
erase.part kernel
nand
write 30000000 kernel
此版对于yaffs的一个小bug
drivers/mtd/nand/nand_util.c (nand_write_skip_bad)中
改为
ops.len = pagesize;
ops.ooblen = nand->oobsize;
ops.mode = MTD_OOB_RAW;
ops.ooboffs = 0;
pages = write_size / pagesize_oob;
for (page = 0; page < pages; page++) {
WATCHDOG_RESET();
ops.datbuf = p_buffer;
ops.oobbuf = ops.datbuf + pagesize;
rval = nand->write_oob(nand, offset, &ops);
if (rval)
break;
offset += pagesize;
p_buffer += pagesize_oob;
}
if (!need_skip && !(flags & WITH_DROP_FFS))
{
改为
if
(!need_skip && !(flags & WITH_DROP_FFS) && !(flags & WITH_YAFFS_OOB)) {
之前的内核都是用nfs文件系统。
如果想用jffs2或者yaffs应该执行下列命令
烧写JFFS2
tftp 30000000 fs.jffs2
nand erase.part rootfs
nand write.jffs2 30000000 0x00260000 5b89a8
set bootargs console=ttySAC0 root=/dev/mtdblock3 rootfstype=jffs2
烧写YAFFS(需要先在mini2440中重新#define CONFIG_CMD_NAND_YAFFS再编译)
tftp 30000000 fs.yaffs2
nand erase.part rootfs
nand write.yaffs 30000000 260000 889bc0 //文件大小
用uboot更新自身
tftp 30000000 u-boot_new.bin; protect off all; erase 0 3ffff; cp.b 30000000 0 40000
移植完后制作补丁
mv u-boot-2012.04.01 u-boot-2012.04.01_ok
tar xjf u-boot-2012.04.01.tar.bz2
diff -urN u-boot-2012.04.01 u-boot-2012.04.01_ok > u-boot-2012.04.01.patch
打补丁
cd u-boot-2012.04.01
patch -p1 < ../u-boot-2012.04.01.patch //因为现在所在u-boot-2012.04.01目录,-p1
数字表示忽略第一个斜杠
![](http://blog.chinaunix.net/image/default/fj.png)
u-boot-2012-patch@2440.rar
编译新uboot
make mini2440_config
make
硬件平台: mini2440
软件: Source Insight、u-boot.2012.04.01 (官方下载源码)
一、uboot 启动分析
1.set the cpu to SVC32 mode(start.S)
2.turn off the watchdog
3.mask all IRQs by setting all bits in the INTMR
4.设置分频系数
5.cpu_init_crit
flush v4 I/D caches
disable MMU stuff and caches
lowlevel_init //setup RAM timing(lowlevel_init.S)
设置BWSCON
board_init_f //set sp, call board_init_f
init_sequence
(各种初始化)
...
board_early_init_f
...
serial_init
...
二、尝试
make smdk2410_config
make
成功生成的u-boot.bin并不能让mini2440启动
三、修改
1.修改根目录下boards.cfg在
smdk2410 arm arm920t - samsung s3c24x0
下添加一行
mini2440 arm arm920t
- samsung s3c24x0
2.make
mini2440_config
3.复制include\configs\smdk2410.h为include\configs\mini2440.h
4.cp board\samsung\smdk2410到board\samsung\mini2440
5.从start.S里可以看出,缺省认为60Mhz的HCLK来设置内存控制器,才设置系统时钟MPLL是有问题的。
因为没设置时钟时,是以晶振的频率运行的
注释掉(mini2440\smdk2410.c)int board_early_init_f(void)中的
#if
0
/*
configure MPLL */
writel((M_MDIV
<< 12) + (M_PDIV << 4) + M_SDIV,
&clk_power->mpllcon);
#endif
start.S修改分频设置
ldr
r0, =0x4C000014 /* FCLK提高到400Mhz,但HCLK不能超过133Mhz */
mov r1, #5 /*
FCLK:HCLK:PCLK = 1:4:8, HDIVN=10, PDIVN=1*/
str r1, [r0]
将MPLL的设置放到start.S
在分频后加上
/* 如果HDIVN非0,CPU的总线模式应该从“fast
bus mode”变为“asynchronous bus mode” */
mrc p15, 0, r1, c1, c0,
0 /* 读出控制寄存器 */
orr r1, r1, #0xc0000000 /*
设置为“asynchronous bus mode” */
mcr p15, 0, r1, c1, c0,
0 /* 写入控制寄存器 */
#define S3C2440_MPLL_400MHZ
((0x5c<<12)|(0x01<<4)|(0x01))
/*
MPLLCON = S3C2440_MPLL_200MHZ */
ldr r0, =0x4c000004
ldr r1, =S3C2440_MPLL_400MHZ
str r1, [r0]
/* 启动ICACHE */
mrc p15, 0, r0, c1, c0,
0 @ read control reg
orr r0, r0, #(1<<12)
mcr p15, 0, r0, c1, c0,
0 @ write it back
6.修改设置BWSCON的SMRDATA(lowlevel_init.S)
/*
BWSCON
[31]ST7:0 [27]ST6:0
[30]WS7:0 [26]WS6:0
[29:28]DW7:10 [25:24]DW6:10
only
bank6 and bank7 for sdram
[19]ST4:0
[18]WS4:1
[17:16]DW4:01
bank4 for DM9000
*/
.long
0x22050000 //BWSCON
/*
use the reset value */
.long
0x00000700 //BANKCON0
.long 0x00000700 //BANKCON1
.long 0x00000700 //BANKCON2
.long 0x00000700 //BANKCON3
.long 0x00000700 //BANKCON4
.long 0x00000700 //BANKCON5
/* MT [16:15] Determine
the memory type for bank6 and bank7
= 11 SDRAM
Trcd [3:2] RAS to
CAS delay, HCLK = 400Mhz/4 = 100Mhz
= 01 3 clocks (view
HY57V561620.pdf)
SCAN [1:0] Column
address number
= 01 9-bit (view
HY57V561620.pdf)
*/
.long 0x00018005 //BANKCON6
.long
0x00018005 //BANKCON7
/*
REFEN [23] SDRAM
Refresh Enable
= 1 Enable (self
or CBR/auto refresh)
TREFMD [22] SDRAM
Refresh Mode
= 0 CBR/Auto Refresh
Trp [21:20] SDRAM
RAS pre-charge Time
= 01 3 clocks (view
HY57V561620.pdf)
Tsrc [19:18] SDRAM
Semi Row cycle time, Trc=Tsrc+Trp => Tsrc=Trc-Trp => 9-3
= 10 6 clocks (view
HY57V561620.pdf)
Refresh Counter [10:0]
SDRAM refresh count value.
Refresh period =
(2^11-refresh_count+1)/HCLK
refresh_count = 64/8192
ms = 7.8125us
Rp = 2^11 + 1 - 135.75*7.8125
= 988 = 0x3dc
*/
.long
0x009803dc //REFRESH
/*
BURST_EN [7] ARM core burst operation enable.
= 1 Enable burst
operation
SCKE_EN [5] SDRAM
power down mode enable control by SCKE
= 1 SDRAM power down
mode enable
SCLK_EN [4]
= 1 SCLK is active
only during the access (recommended)
BK76MAP [2:0] BANK6/7
memory map
= 001 64MB/64MB
*/
.long
0x000000B1 //BANKSIZE
/*
CL [6:4] CAS latency
= 011 3 clocks
*/
.long
0x00000030 //MRSRB6
.long 0x00000030 //MRSRB7
再次make,并烧写u-boot.bin到nor
flash,启动后发现是乱码,应该是串口波特率问题,看看串口初始化
![](http://blog.chinaunix.net/attachment/201303/11/22609852_1362997247edSL.jpg)
7.board.c (z:\u-boot-2012.04.01\arch\arm\lib\Board.c)
serial_init(z:\u-boot-2012.04.01\drivers\serial\Serial_s3c24x0.c)
serial_init_dev
_serial_setbrg
get_PCLK(z:\u-boot-2012.04.01\arch\arm\cpu\arm920t\s3c24x0\Speed.c)
get_HCLK
发现没有定义CONFIG_S3C2440,它用2410的那套
那么在config中的mini2440.h中去掉#define
CONFIG_S3C2410改成#define CONFIG_S3C2440
make发现多个错误
s3c2410_nand.c:
In function 's3c2410_hwcontrol':
s3c2410_nand.c:57:
warning: implicit declaration of function 's3c2410_get_base_nand'
s3c2410_nand.c:57:
warning: initialization makes pointer from integer without a cast
s3c2410_nand.c:72: error:
dereferencing pointer to incomplete type
s3c2410_nand.c:72:
error: dereferencing pointer to incomplete type
s3c2410_nand.c:75:
error: dereferencing pointer to incomplete type
s3c2410_nand.c:75:
error: dereferencing pointer to incomplete type
s3c2410_nand.c:
In function 's3c2410_dev_ready':
s3c2410_nand.c:85:
warning: initialization makes pointer from integer without a cast
s3c2410_nand.c:87:
error: dereferencing pointer to incomplete type
s3c2410_nand.c:
In function 'board_nand_init':
s3c2410_nand.c:129:
warning: initialization makes pointer from integer without a cast
s3c2410_nand.c:150:
error: dereferencing pointer to incomplete type
s3c2410_nand.c:153:
error: dereferencing pointer to incomplete type
s3c2410_nand.c:154:
error: dereferencing pointer to incomplete type、
s3c2410_nand.c找错误,发现是因为更改了#define CONFIG_S3C2440后,s3c2410_nand未定义
暂且先让串口输出正常看看,去掉nand支持。
[root: u-boot-2012.04.01]# grep
"s3c2410_nand.o" * -nR
drivers/mtd/nand/Makefile:61:COBJS-$(CONFIG_NAND_S3C2410)
+= s3c2410_nand.o
drivers/mtd/nand/.depend.s3c2410_nand:1:s3c2410_nand.o:
s3c2410_nand.c \
drivers/mtd/nand/.depend:341:s3c2410_nand.o:
s3c2410_nand.c \
[root: u-boot-2012.04.01]# vi
drivers/mtd/nand/Makefile
找到
COBJS-$(CONFIG_NAND_S3C2410)
+= s3c2410_nand.o
现取消CONFIG_NAND_S3C2410的定义,在mini2440.h中发现
#ifdef CONFIG_CMD_NAND
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_BASE 0x4E000000
#endif
则注释掉//#define CONFIG_CMD_NAND
再编译提示
fs/yaffs2/libyaffs2.o:
In function `yaffs_StartUp':
/home/profiles/u-boot-2012.04.01/fs/yaffs2/yaffscfg.c:210: undefined reference to `nand_info'
还是在mini2440.h中先注释掉
//#define CONFIG_YAFFS2
再次make,并烧写u-boot.bin到nor
flash,启动后发现Flash: *** failed ***,串口正常了,只是flash还有问题
8.为了去掉原u-boot复杂的重定位代码,现自己写重定位代码,将init.c添加到board/samsung/mini2440下。修改
board/samsung/mini2440/Makefile
改COBJS := smdk2410.o init.o
init.c内容如下
点击(此处)折叠或打开
#define NFCONF (*((volatile
unsigned long *)0x4E000000))
#define NFCONT (*((volatile
unsigned long *)0x4E000004))
#define NFCMMD (*((volatile
unsigned char *)0x4E000008)) //注意是char* 不是long*,与下面保持一致
#define NFADDR (*((volatile
unsigned char *)0x4E00000C))
#define NFDATA (*((volatile
unsigned char *)0x4E000010))
#define NFSTAT (*((volatile
unsigned char *)0x4E000020))
void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len);
static int isNor()
{
volatile int *p = (volatile int *)0;
int val;
val = *p;
*p = 0xfdfdfdfd;
if(0xfdfdfdfd == *p) //可写,证明是在SRAM中运行,即是从NAND启动
{
*p = val;
return 0;
}
else //写NOR需要特定的命令时序
{
return 1;
}
}
void copy_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)
{
int i = 0;
/* 判断启动方式 */
if (isNor())
{
while(i < len)
{
dest[i] = src[i]; //直接读
NOR(view Figure 5-1. S3C2440A Memory Map after Reset)
i++;
}
}
else
{
nand_read_ll((unsigned int)src, dest, len);
}
}
void clear_bss(void)
{
extern int __bss_start, __bss_end__;
int *p = &__bss_start;
for(; p<=&__bss_end__; p++)
{
*p = 0;
}
}
void nand_init_ll(void)
{
/* NFCONF
TACLS [13:12] CLE & ALE
duration setting value (0~3)
= 0 Duration = HCLK x TACLSHCLK x TACLS (view K9F1208.pdf)
TWRPH0 [10:8] TWRPH0 duration setting value (0~7)
Duration = HCLK x ( TWRPH0 + 1 ) = 25ns (view
K9F1208.pdf) 1/135.75 = 7ns
= 3 TWRPH0 >= 25 / 7 - 1 = 2.57
TWRPH1 [6:4] TWRPH1 duration setting value (0~7)
Duration = HCLK x ( TWRPH1 + 1 ) = 10ns (view
K9F1208.pdf)
= 1 TWRPH1 >= 10 / 7 - 1 = 0.42
*/
#define TACLS 0
#define TWRPH0 3
#define TWRPH1 1
NFCONF = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);
/* NFCONT
InitECC [4] Initialize ECC decoder/encoder(Write-only)
= 1 Initialize ECC decoder/encoder
Reg_nCE [1] NAND Flash Memory nFCE signal control
= 1 Force nFCE to high (Disable chip select)
MODE [0] NAND flash controller operating mode
= 1 NAND flash controller enable
*/
NFCONT = (1<<4) | (0<<1) | (1<<0);
}
static void nand_select(void)
{
NFCONT &= ~(1<<1);
}
static void nand_deselect(void)
{
NFCONT |= (1<<1);
}
static void nand_cmd(unsigned char cmd)
{
volatile int i;
NFCMMD = cmd;
for (i = 0; i < 10; i++);
}
static void nand_addr(unsigned int addr)
{
/* Address(5Cycle)
Col Add.1,2 & Row Add.1,2,3
*/
int col = addr % 2048;
int row = addr / 2048;
volatile int i;
NFADDR = col & 0xff;
for(i=0; i<10; i++);
NFADDR = (col>>8) & 0xff;
for(i=0; i<10; i++);
NFADDR = row & 0xff;
for(i=0; i<10; i++);
NFADDR = (row>>8) & 0xff;
for(i=0; i<10; i++);
NFADDR = (row>>16) & 0xff;
for(i=0; i<10; i++);
}
static void nand_wait(void)
{
while(!(NFSTAT&1));
}
void nand_read_ll(unsigned int addr, unsigned char *dest, unsigned int len)
{
int col = addr % 2048, i = 0;
nand_select();
while(i < len)
{
/* view K9K8G08U0A.pdf */
nand_cmd(0x00);
nand_addr(addr);
nand_cmd(0x30);
nand_wait();
for(; col<2048 && i<len; col++)
{
dest[i] = NFDATA;
i++;
addr++;
}
col = 0;
}
nand_deselect();
}
修改start.S
#ifndef
CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic sp, sp, #7 /* 8-byte
alignment for ABI compliance */
bl
nand_init_ll
mov
r0, #0
//ldr r1, =_start
ldr r1, _TEXT_BASE //CONFIG_SYS_TEXT_BASE
= 0x33f00000
ldr r2, _bss_start_ofs
bl
copy_to_sdram //copy_to_sdram(r0, r1, r2)
bl clear_bss
ldr
pc, =call_board_init_f //远跳转
/*
Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
ldr
r0,=0x00000000
bl board_init_f
修改mini2440.h中#define CONFIG_SYS_TEXT_BASE
0x33f80000
自己写了重定位,就去掉它写的重定位函数
注释掉掉board.c中board_init_f中//relocate_code(addr_sp,
id, addr);
删掉start.S中下面不需要的代码
点击(此处)折叠或打开
/*------------------------------------------------------------------ ------------*/
/*
* void relocate_code (addr_sp, gd, addr_moni)
*
* This "function" does not return, instead
it continues in RAM
* after relocating the monitor code.
*
*/
.globl relocate_code
relocate_code:
mov r4, r0 /* save addr_sp */
mov r5, r1 /* save addr of gd */
mov r6, r2 /* save addr of destination */
/* Set up the stack */
stack_setup:
mov sp, r4
adr r0, _start
cmp r0, r6
beq clear_bss /* skip relocation */
mov r1, r6 /* r1 <- scratch for copy_loop */
ldr r3, _bss_start_ofs
add r2, r0, r3 /* r2 <- source
end address */
copy_loop:
ldmia {r9-r10} /* copy from source address [r0] */
stmia {r9-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end address [r2] */
blo copy_loop
#ifndef CONFIG_SPL_BUILD
/*
* fix .rel.dyn relocations
*/
ldr r0, _TEXT_BASE /* r0 <- Text
base */
sub r9, r6, r0 /* r9 <- relocation
offset */
ldr r10, _dynsym_start_ofs /* r10 <- sym
table ofs */
add r10, r10, r0 /* r10 <- sym
table in FLASH */
ldr r2, _rel_dyn_start_ofs /* r2 <- rel
dyn start ofs */
add r2, r2, r0 /* r2 <- rel
dyn start in FLASH */
ldr r3, _rel_dyn_end_ofs /* r3 <- rel
dyn end ofs */
add r3, r3, r0 /* r3 <- rel
dyn end in FLASH */
fixloop:
ldr r0, [r2] /* r0 <- location
to fix up, IN */
add r0, r0, r9 /* r0 <- location
to fix up in RAM */
ldr r1, [r2, #4]
and r7, r1, #0xff
cmp r7, #23 /* relative fixup? */
beq fixrel
cmp r7, #2 /* absolute fixup? */
beq fixabs
/* ignore unknown type of fixup */
b fixnext
fixabs:
/* absolute fix: set location to (offset) symbol
value */
mov r1, r1, LSR #4 /* r1 <- symbol
index in .dynsym */
add r1, r10, r1 /* r1 <- address of symbol in table */
ldr r1, [r1, #4]
/* r1 <- symbol value */
add r1, r1, r9 /* r1 <- relocated
sym addr */
b fixnext
fixrel:
/* relative fix: increase location by offset */
ldr r1, [r0]
add r1, r1, r9
fixnext:
str r1, [r0]
add r2, r2, #8 /* each
rel.dyn entry is 8 bytes */
cmp r2, r3
blo fixloop
#endif
clear_bss:
#ifndef CONFIG_SPL_BUILD
ldr r0, _bss_start_ofs
ldr r1, _bss_end_ofs
mov r4, r6 /* reloc addr */
add r0, r0, r4
add r1, r1, r4
mov r2, #0x00000000 /* clear */
clbss_l:str r2, [r0]
/* clear loop... */
add r0, r0, #4
cmp r0, r1
bne clbss_l
bl coloured_LED_init
bl red_led_on
#endif
因为第二阶段函数board_init_f需要
修改函数定义
unsigned int board_init_f (ulong);(common.h)
unsigned int board_init_f(ulong bootflag) (arch/arm/lib/board.c)
函数体最后加上
return
(unsigned int)id;
返回后给start.S的第二阶段代码用
在start.S
ldr r0,=0x00000000
bl board_init_f
后加上
//board_init_f的返回值在r0里面,刚好把id传给board_init_r
ldr r1, _TEXT_BASE
bl board_init_r
vi
arch/arm/config.mk
注释掉
#LDFLAGS_u-boot
+= -pie
修改
arch/arm/cpu/u-boot.lds添加 board/samsung/mini2440/libmini2440.o
(.text)
.text :
{
__image_copy_start = .;
CPUDIR/start.o (.text)
board/samsung/mini2440/libmini2440.o
(.text)
*(.text)
}
修改board.c
//addr -= gd->mon_len;
//addr &= ~(4096
- 1);
addr
= CONFIG_SYS_TEXT_BASE;
make后烧写发现
![](http://blog.chinaunix.net/attachment/201303/11/22609852_1362998490uk3f.jpg)
9.在SI中搜索"Flash:“
(z:\u-boot-2012.04.01\arch\arm\lib\Board.c)
#if !defined(CONFIG_SYS_NO_FLASH)
puts("Flash: ");
继续看
if (flash_size > 0) {
...
}else {
puts(failed);
//输出*** failed ***
hang();
//挂起
}
void hang(void)
{
puts("###
ERROR ### Please RESET the board ###\n");
for
(;;); //死循环
}
注释掉//hang();
再次make,并烧写u-boot.bin到nor
flash,发现uboot是启动起来了不过flash和nand都不识别
![](http://blog.chinaunix.net/attachment/201303/11/22609852_1362998626R55z.jpg)
10.定义#define DEBUG (z:\u-boot-2012.04.01\include\configs\Mini2440.h)
方便调试
![](http://blog.chinaunix.net/attachment/201303/11/22609852_1362998710rVDh.jpg)
11.找nor的识别问题
从图中JEDEC
PROBE: ID 1 2249 0和代码(z:\u-boot-2012.04.01\drivers\mtd\Cfi_flash.c)
debug("JEDEC
PROBE: ID %x %x %x\n",
info->manufacturer_id,
info->device_id,
info->device_id2);
可以看出manufacturer_id是1,device_id是2249,device_id2是0
flash_init (z:\u-boot-2012.04.01\drivers\mtd\Cfi_flash.c)
flash_detect_legacy
//
match jedec ids against table. If a match is found, fill flash_info entry
jedec_flash_match
(z:\u-boot-2012.04.01\drivers\mtd\Jedec_flash.c)
if
((jedec_table[i].mfr_id & mask) == (info->manufacturer_id
& mask) &&
(jedec_table[i].dev_id
& mask) == (info->device_id & mask)) {
fill_info(info, &jedec_table[i], base);
ret = 1;
break;
}
可以看到manufacturer_id、device_id都要和jedec_table中的信息匹配。
添加mini2440用的nor
flash信息(需要查看芯片手册Am29LV160DB.pdf)
{
.mfr_id = 1,
.dev_id = 0x2249,
.name
= "Am29LV160DB",
.uaddr = {
[1] = MTD_UADDR_0x0555_0x02AA /* x16 */
},
.DevSize = SIZE_2MiB,
.CmdSet = CFI_CMDSET_AMD_LEGACY,
.NumEraseRegions = 4,
.regions = {
ERASEINFO(0x04000, 1),
ERASEINFO(0x02000,
2),
ERASEINFO(0x08000,
1),
ERASEINFO(0x10000, 31),
}
},
![](http://blog.chinaunix.net/attachment/201303/11/22609852_1362999028s4EE.jpg)
取消DEBUG定义(看之前的DEBUG信息足以),再次编译烧写
12.提示Flash: ERROR: too many flash sectors
搜索发现#define CONFIG_SYS_MAX_FLASH_SECT
(19) //(z:\u-boot-2012.04.01\include\configs\Mini2440.h)
修改大一点#define CONFIG_SYS_MAX_FLASH_SECT
(128)
make烧写,Flash:2 MiB.
![](http://blog.chinaunix.net/attachment/201303/11/22609852_13629990619Vdv.jpg)
13.修改栈指针
start.S中加上
.globl base_sp
base_sp:
.long 0
start_code:
.....
ldr
r1, _TEXT_BASE
ldr
sp, base_sp
bl
board_init_r
在board.c的board_init_f加上
extern
ulong base_sp;
...
memcpy(id, (void *)gd, sizeof(gd_t));
base_sp
= addr_sp;
//relocate_code(addr_sp,
id, addr);
14.加上nand的支持
在mini2440.h中取消注释
#define CONFIG_CMD_NAND
make出错,拷贝drivers/mtd/nand/s3c2410_nand.c复制为s3c2440_nand.c
修改mini2440.h
#ifdef CONFIG_CMD_NAND
#ifdef
CONFIG_S3C2410
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
#else
#define
CONFIG_NAND_S3C2440
#define CONFIG_SYS_S3C2440_NAND_HWECC
#endif
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_BASE 0x4E000000
#endif
修改drivers/mtd/nand/Makefile
加上
COBJS-$(CONFIG_NAND_S3C2410)
+= s3c2410_nand.o
COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o
修改s3c2440_nand.c中的s3c2410_nand为s3c2440_nand(除了宏)
包括s3c2440_dev_ready、s3c2440_hwcontrol、s3c2440_get_base_nand
从nand_init开始看
nand_init_chip
board_nand_init
...
tacls
= 4;
twrph0
= 8;
twrph1
= 8;
#endif
cfg = S3C2410_NFCONF_EN;
cfg |= S3C2410_NFCONF_TACLS(tacls
- 1);
cfg |= S3C2410_NFCONF_TWRPH0(twrph0
- 1);
cfg |= S3C2410_NFCONF_TWRPH1(twrph1
- 1);
writel(cfg, &nand_reg->nfconf);
/*
NFCONF
TACLS [13:12]
CLE & ALE duration setting value (0~3)
= 0
Duration = HCLK x TACLSHCLK x TACLS (view K9F1208.pdf)
TWRPH0 [10:8]
TWRPH0 duration setting value (0~7)
Duration
= HCLK x ( TWRPH0 + 1 ) = 25ns (view K9F1208.pdf) 1/135.75 = 7ns
= 3
TWRPH0 >= 25 / 7 - 1 = 2.57
TWRPH1 [6:4]
TWRPH1 duration setting value (0~7)
Duration
= HCLK x ( TWRPH1 + 1 ) = 10ns (view K9F1208.pdf)
= 1 TWRPH1
>= 10 / 7 - 1 = 0.42
*/
cfg = ((tacls-1)<<12) | ((tacls-1)<<8)
| ((tacls-1)<<4);
writel(cfg, &nand_reg->nfconf);
/*
NFCONT
InitECC
[4] Initialize ECC decoder/encoder(Write-only)
= 1 Initialize
ECC decoder/encoder
Reg_nCE
[1] NAND Flash Memory nFCE signal control
= 1 Force
nFCE to high (Disable chip select)
MODE [0]
NAND flash controller operating mode
= 1 NAND
flash controller enable
*/
writel((1<<4) | (0<<1) | (1<<0),
&nand_reg->nfcont);
...
nand->select_chip
= NULL;
//修改为nand->select_chip
= s3c2440_select_nand;
自己写
static void s3c2440_select_nand(struct
mtd_info *mtd, int chipnr)
{
struct
s3c2440_nand *nand = s3c2440_get_base_nand();
switch (chipnr) {
case -1: //-1 for deselect
nand->nfcont
|= 1<<1;
break;
case
0: //0 for select
nand->nfcont
&= ~(1<<1);
break;
default:
BUG();
}
}
nand->cmd_ctrl
= s3c2440_hwcontrol;
//修改s3c2410_hwcontrol,根据ctrl判断是发命令还是地址
static void s3c2410_hwcontrol(struct mtd_info *mtd, int dat, unsigned int ctrl)
{
struct s3c2440_nand *nand = s3c2440_get_base_nand();
debug("hwcontrol(): 0x%02x 0x%02x\n", dat, ctrl);
if (ctrl & NAND_CLE)
{
writeb(dat,
&nand->nfcmd);
}
else if (ctrl & NAND_ALE)
{
writeb(dat,
&nand->nfaddr);
}
}
...
nand_scan
nand_scan_ident
nand_set_defaults
if
(chip->cmdfunc == NULL)
chip->cmdfunc = nand_command; //static
void nand_command(struct mtd_info *mtd, unsigned int command, int column, int page_addr)
if
(!chip->select_chip)
chip->select_chip = nand_select_chip;
nand_get_flash_type
chip->select_chip(mtd,
0);
chip->cmdfunc(mtd,
NAND_CMD_READID, 0x00, -1);
<=>nand_command
chip->cmd_ctrl(mtd, readcmd, ctrl);
<=>s3c2410_hwcontrol;
nand_register
add_mtd_device
make后nand可以正常使用了
15.mini2440用dm9000网卡,搜索drivers/net/Makefile 可以发现
COBJS-$(CONFIG_DRIVER_DM9000)
+= dm9000x.o
由mini2440.h中的宏CONFIG_DRIVER_DM9000控制,并且从上面结果可以看到,需要去掉cs8900的宏.
#if 0
#define CONFIG_CS8900
/* we have a CS8900 on-board */
#define CONFIG_CS8900_BASE
0x19000300
#define CONFIG_CS8900_BUS16
/* the Linux driver does accesses as shorts */
#else
#define
CONFIG_DRIVER_DM9000
#endif
make看看结果
dm9000x.c:
In function 'dm9000_outblk_8bit':
dm9000x.c:156:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:156:
error: (Each undeclared identifier is reported only once
dm9000x.c:156:
error: for each function it appears in.)
dm9000x.c:
In function 'dm9000_outblk_16bit':
dm9000x.c:165:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:
In function 'dm9000_outblk_32bit':
dm9000x.c:173:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:
In function 'dm9000_inblk_8bit':
dm9000x.c:180:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:
In function 'dm9000_inblk_16bit':
dm9000x.c:189:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:
In function 'dm9000_inblk_32bit':
dm9000x.c:197:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:
In function 'dm9000_rx_status_32bit':
dm9000x.c:204:
error: 'DM9000_IO' undeclared (first use in this function)
dm9000x.c:206:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:
In function 'dm9000_rx_status_16bit':
dm9000x.c:213:
error: 'DM9000_IO' undeclared (first use in this function)
dm9000x.c:215:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:
In function 'dm9000_rx_status_8bit':
dm9000x.c:221:
error: 'DM9000_IO' undeclared (first use in this function)
dm9000x.c:224:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:
In function 'dm9000_probe':
dm9000x.c:243:
error: 'CONFIG_DM9000_BASE' undeclared (first use in this function)
dm9000x.c:
In function 'dm9000_send':
dm9000x.c:420:
error: 'DM9000_IO' undeclared (first use in this function)
dm9000x.c:
In function 'dm9000_rx':
dm9000x.c:484:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:
In function 'DM9000_ior':
dm9000x.c:574:
error: 'DM9000_IO' undeclared (first use in this function)
dm9000x.c:575:
error: 'DM9000_DATA' undeclared (first use in this function)
dm9000x.c:
In function 'DM9000_iow':
dm9000x.c:584:
error: 'DM9000_IO' undeclared (first use in this function)
dm9000x.c:585:
error: 'DM9000_DATA' undeclared (first use in this function)
make[1]:
*** [dm9000x.o] Error 1
make[1]:
Leaving directory `/home/profiles/u-boot-2012.04.01/drivers/net'
make:
*** [drivers/net/libnet.o] Error 2
报错
grep
"DM9000_DATA" * -nR参考其他开发板
include/configs/M5253DEMO.h:95:#
define DM9000_DATA (CONFIG_DM9000_BASE + 4)
定义了
#
define CONFIG_DM9000_BASE (CONFIG_SYS_CS1_BASE | 0x300)
#
define DM9000_IO CONFIG_DM9000_BASE
#
define DM9000_DATA (CONFIG_DM9000_BASE + 4)
则在mini2440.h上加上这些宏,并把值参照原理图芯片手册,DM9000接片选4即bank4,由2440手册知0x20000000是bank4的基址修改过来为:
#define
CONFIG_DM9000_BASE 0x20000000
#define
DM9000_IO CONFIG_DM9000_BASE
#define
DM9000_DATA (CONFIG_DM9000_BASE + 4) //LADDR2开始接到DM9000上
内存控制器初始化已经在lowlevel.S中设置过为
SMRDATA:
.long 0x22050000 //BWSCON
make烧写从nor启动,发现Net:
No ethernet found.
![](http://blog.chinaunix.net/attachment/201303/11/22609852_13630002221lCZ.jpg)
16.在source insight中搜索“No
ethernet found.”找出原因
eth_initialize (board.c)
board_eth_init (mini2440/smdk2410.c)
cs8900_initialize此处不合适,添加DM9000的函数
#ifdef
CONFIG_CS8900
rc = cs8900_initialize(0, CONFIG_CS8900_BASE);
#endif
#ifdef
CONFIG_DRIVER_DM9000
rc
= dm9000_initialize(bis);
#endif
再次make烧写来试验网络功能
set
ipaddr 169.254.252.201 (连上网线同自己要ping的机器在一个网段)
set
serverip 169.254.252.200
set
gatewayip 255.255.0.0 (同自己要ping的机器一致)
set
ethaddr 08:00:27:71:89:bb
ping
169.254.252.200 通了
![](http://blog.chinaunix.net/attachment/201303/11/22609852_1363000464vd4p.jpg)
自行测试下tftp的下载功能。
tftp
30000000 uImage
发面bootm
30000000后不能启动linux,在解压后停住了。应该是开发板型号没修改
修改board_init(board.c)中
gd->bd->bi_arch_number
= MACH_TYPE_SMDK2410;为
gd->bd->bi_arch_number
= MACH_TYPE_MINI2440;
再次tftp下载后bootm就启动了
17.环境变量
开发板烧写u-boot后,发现***
Warning - bad CRC, using default environment
SI搜索一下。
set_default_env
default_environment
#ifdef CONFIG_BOOTARGS
"bootargs=" CONFIG_BOOTARGS
"\0"
#ifdef CONFIG_BOOTCOMMAND
"bootcmd=" CONFIG_BOOTCOMMAND
"\0"
在mini2440.h中加上
#define CONFIG_BOOTARGS
"console=ttySAC0 root=/dev/mtdblock3"
#define
CONFIG_BOOTCOMMAND "nand read 30000000 0x60000 0x500000;bootm 30000000"
修改
#define
CONFIG_NETMASK 255.255.0.0
#define CONFIG_IPADDR
169.254.252.201
#define CONFIG_SERVERIP
169.254.252.200
加上
#define CONFIG_ETHADDR
08:00:27:71:89:bb
18.裁剪
在mini2440.h找不需要的宏
#if 0
#define
CONFIG_USB_OHCI
#define
CONFIG_USB_KEYBOARD
#define
CONFIG_USB_STORAGE
#define
CONFIG_DOS_PARTITION
#endif
//#define
CONFIG_RTC_S3C24X0
#if
0
#define
CONFIG_BOOTP_BOOTFILESIZE
#define
CONFIG_BOOTP_BOOTPATH
#define
CONFIG_BOOTP_GATEWAY
#define
CONFIG_BOOTP_HOSTNAME
#endif
//#define
CONFIG_CMD_USB
//#define
CONFIG_CMD_DATE
//#define
CONFIG_CMD_DHCP
#if
0
#define
CONFIG_CMD_FAT
#define
CONFIG_CMD_EXT2
#define
CONFIG_CMD_UBI
#define
CONFIG_CMD_UBIFS
#define
CONFIG_CMD_MTDPARTS
#define
CONFIG_MTD_DEVICE
#define
CONFIG_MTD_PARTITIONS
#define
CONFIG_YAFFS2
#define
CONFIG_RBTREE
#endif
裁剪后make发现
u-boot.bin的大小为204344B小了很多
19.环境变量默认存在nor,为了让u-boot里面的saveenv命令将环境变量保存到nand,且不能破坏内核,需要修改保存的位置。
在SI中搜索"saveenv",找到env_nand.c文件,到Makefile中找寻它所依赖的宏.
vi
common/Makefile,发现它依赖于CONFIG_ENV_IS_IN_NAND
(mini2440.h)修改
#if 0
#define CONFIG_ENV_ADDR
(CONFIG_SYS_FLASH_BASE + 0x070000)
#define CONFIG_ENV_IS_IN_FLASH
#define CONFIG_ENV_SIZE
0x10000
/* allow to overwrite
serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
#endif
添加
#define CONFIG_ENV_IS_IN_NAND
在env_nand.c中找到宏CONFIG_ENV_OFFSET,这个制定存在nand的哪个地址
需要看看原内核的分区。
在我使用的2.6.32.2源代码中发现
static struct mtd_partition friendly_arm_default_nand_part[]
= {
[0]
= {
.name
= "supervivi",
.size
= 0x00040000,
.offset
= 0,
},
[1]
= {
.name
= "param",
.offset
= 0x00040000,
.size
= 0x00020000,
},
[2]
= {
.name
= "Kernel",
.offset
= 0x00060000,
.size
= 0x00500000,
},
[3]
= {
.name
= "root",
.offset
= 0x00560000,
.size
= 1024 * 1024 * 1024, //
},
[4]
= {
.name
= "nand",
.offset
= 0x00000000,
.size
= 1024 * 1024 * 1024, //
}
};
(或者启动内核后发现)
![](http://blog.chinaunix.net/attachment/201303/11/22609852_1363001228D6B2.jpg)
参数存在0x40000开始的0x20000大小处
则加定义(mini2440.h)
#define CONFIG_ENV_OFFSET
0x40000
#define CONFIG_ENV_SIZE
0x20000
#define CONFIG_ENV_RANGE
CONFIG_ENV_SIZE //擦除单位
make后烧写nor
此时还有***
Warning - bad CRC, using default environment
在u-boot里执行save命令重启就行了
u-boot倒计时5秒如果没有执行的话,就会执行我们设置的
#define CONFIG_BOOTCOMMAND "nand
read 30000000 0x60000 0x500000;bootm 30000000"
即从nand flash 0x60000的地方读0x500000的数据(整个内核)到内存0x30000000的地方,然后从0x30000000启动内核。
于是我们必须先将uImage烧写到0x60000的地方:
先下载tftp
30000000 uImage
nand
erase 60000 500000
nand
write 30000000 60000 500000 //这样60000的地方就有了可启动的内核
下次重启开发板,5秒延时之后将自动读内核并加载运行
20.代替繁琐的数字
在board.c的board_init_r中加上
run_command("mtdparts
default", 0); //必须让uboot执行这条命令
/*
main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop();
}
在mini2440中定义宏
#define
CONFIG_CMD_MTDPARTS
参照其它开发板再添加上
#define
CONFIG_MTD_DEVICE
#define MTDIDS_DEFAULT "nand0=mini2440-0"
#define MTDPARTS_DEFAULT
"mtdparts=mini2440-0:256k(u-boot)," \
"128k(params)," \
"5m(kernel),"
\
"-(rootfs)"
\ //-余下的所有给rootfs
make后提示发现drivers\mtd\mtdcore.c中的get_mtd_device_nm未定义。
则可以直接去drivers\mtd\Makefile中查看哪个宏决定是否编译成mtdcore.o
或者grep
"mtdcore.o" * -nR发现是CONFIG_MTD_DEVICE控制的
将宏添加到mini2440.h
#define CONFIG_MTD_DEVICE
再次make并烧写
在uboot执行命令mtdparts
![](http://blog.chinaunix.net/attachment/201303/11/22609852_1363001667Z74J.jpg)
现在可以尝试用名字代替数字的分区表示,如
tftp
30000000 uImage
nand
erase.part kernel
nand
write 30000000 kernel
此版对于yaffs的一个小bug
drivers/mtd/nand/nand_util.c (nand_write_skip_bad)中
改为
ops.len = pagesize;
ops.ooblen = nand->oobsize;
ops.mode = MTD_OOB_RAW;
ops.ooboffs = 0;
pages = write_size / pagesize_oob;
for (page = 0; page < pages; page++) {
WATCHDOG_RESET();
ops.datbuf = p_buffer;
ops.oobbuf = ops.datbuf + pagesize;
rval = nand->write_oob(nand, offset, &ops);
if (rval)
break;
offset += pagesize;
p_buffer += pagesize_oob;
}
if (!need_skip && !(flags & WITH_DROP_FFS))
{
改为
if
(!need_skip && !(flags & WITH_DROP_FFS) && !(flags & WITH_YAFFS_OOB)) {
之前的内核都是用nfs文件系统。
如果想用jffs2或者yaffs应该执行下列命令
烧写JFFS2
tftp 30000000 fs.jffs2
nand erase.part rootfs
nand write.jffs2 30000000 0x00260000 5b89a8
set bootargs console=ttySAC0 root=/dev/mtdblock3 rootfstype=jffs2
烧写YAFFS(需要先在mini2440中重新#define CONFIG_CMD_NAND_YAFFS再编译)
tftp 30000000 fs.yaffs2
nand erase.part rootfs
nand write.yaffs 30000000 260000 889bc0 //文件大小
用uboot更新自身
tftp 30000000 u-boot_new.bin; protect off all; erase 0 3ffff; cp.b 30000000 0 40000
移植完后制作补丁
mv u-boot-2012.04.01 u-boot-2012.04.01_ok
tar xjf u-boot-2012.04.01.tar.bz2
diff -urN u-boot-2012.04.01 u-boot-2012.04.01_ok > u-boot-2012.04.01.patch
打补丁
cd u-boot-2012.04.01
patch -p1 < ../u-boot-2012.04.01.patch //因为现在所在u-boot-2012.04.01目录,-p1
数字表示忽略第一个斜杠
![](http://blog.chinaunix.net/image/default/fj.png)
u-boot-2012-patch@2440.rar
编译新uboot
make mini2440_config
make
相关文章推荐
- poj 2265 Bee Maja 模拟计数
- 我的 Cubieboard 4 (CC-A80) 到了
- 关于inputFile的那些事
- hdoj2047(EOF牛肉串
- Android 在你的app实现拖放
- Apache Hadoop安装
- node.js安装模块报 .node-gyp\4.2.1\Release\node.lib : fatal error LNK1106: invalid file or disk full:
- FileStream、Read和Write对文件的读写
- Hash表算法详解
- ——————————————————————————2004————————————————————
- FreeMarker 数字内建函数(取值)
- python 提取url中的主域名
- poj 1012 约瑟夫置换
- 关于继承的使用
- MSBUILD : error MSB3428: 未能加载 Visual C++ 组件“VCBuild.exe”。
- s5p4418-android5.1.1编译出错问题2
- leetcode笔记:Interlaving String
- Apache和Nginx防盗链的几种配置方法
- IOS9 UItableView 拖动卡顿明显
- [BCB] C++ Builder 绘图 绘制直线 —— 基于像素