软件平台: 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,启动后发现是乱码,应该是串口波特率问题,看看串口初始化
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后烧写发现
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都不识别
10.定义#define DEBUG (z:\u-boot-2012.04.01\include\configs\Mini2440.h)
方便调试
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),
}
},
取消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.
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.
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 通了
自行测试下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, //
}
};
(或者启动内核后发现)
参数存在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
现在可以尝试用名字代替数字的分区表示,如
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 数字表示忽略第一个斜杠
u-boot-2012-patch@2440.rar
编译新uboot
make mini2440_config
make