UBOOT从NAND FLASH启动分析

UBOOT从NAND FLASH启动分析
UBOOT从NAND FLASH启动分析

UBOOT从NAND FLASH启动分析

UBOOT从NAND FLASH启动分析

在分析启动代码之前先看一下S3C2440的NAND启动:

在配置NAND启动模式之后,S3C2440上电会先将NAND中的0x0 - 0x1000共4096字节的数据拷贝到位于Bank0中的Boot Internal SRAM上

Bank0如下图:

可以看出Boot Internal SRAM为4KB大小,也正是因为Boot Internal SRAM只有4KB 大小,所以只能从NAND中拷贝4K的内容= 3= 这个Boot Internal SRAM是配置为NAND FLASH启动模式才有的

这4K内容是什么呢?~ 这就要看Uboot的镜像文件中是如何进行连接的了~

连接脚本在board/smdk2440/u-boot.lds中,如下

SECTIONS

{

. = 0x00000000;

. = ALIGN(4);

.text :

{

cpu/arm920t/start.o (.text)

cpu/arm920t/s3c24x0/nand_read.o (.text)

*(.text)

}

. = ALIGN(4);

.rodata : { *(.rodata) }

. = ALIGN(4);

.data : { *(.data) }

. = ALIGN(4);

.got : { *(.got) }

. = .;

__u_boot_cmd_start = .;

.u_boot_cmd : { *(.u_boot_cmd) }

__u_boot_cmd_end = .;

. = ALIGN(4);

__bss_start = .;

.bss : { *(.bss) }

_end = .;

}

.text为代码段,可以看出cpu/arm920t/start.o在代码段的最前面,所以会先执行start.o 中的代码

连接完成后的镜像文件的前4K如下

cpu/arm920t/start.o(.text)

.text 0x33f80000 0x4e0 cpu/arm920t/start.o

0x33f80050 IRQ_STACK_START

0x33f80048 _bss_start

0x33f8004c _bss_end

0x33f80044 _armboot_start

0x33f80000 _start

0x33f80054 FIQ_STACK_START

cpu/arm920t/s3c24x0/nand_read.o(.text)

.text 0x33f804e0 0x1b8 cpu/arm920t/s3c24x0/nand_read.o

0x33f804e0 nand_read_ll

*(.text)

.text 0x33f80698 0x64 board/smdk2440/libsmdk2440.a(lowlevel_init.o)

0x33f8069c lowlevel_init

.text 0x33f806fc 0x280 cpu/arm920t/libarm920t.a(interrupts.o)

0x33f80934 do_fiq

0x33f80880 do_undefined_instruction

0x33f80744 show_regs

0x33f80958 do_irq

0x33f80728 bad_mode

0x33f808c8 do_prefetch_abort

0x33f8070c disable_interrupts

0x33f80910 do_not_used

0x33f808ec do_data_abort

0x33f808a4 do_software_interrupt

0x33f806fc enable_interrupts

.text 0x33f8097c 0x250 cpu/arm920t/s3c24x0/libs3c24x0.a(interrupts.o)

0x33f80aa4 set_timer

0x33f80a20 reset_timer

0x33f8097c interrupt_init

0x33f80ba0 get_tbclk

0x33f80a90 get_timer

0x33f809f0 reset_timer_masked

0x33f80a24 get_timer_masked

0x33f80ab4 udelay

0x33f80b10 udelay_masked

0x33f80bac reset_cpu

0x33f80b8c get_ticks

.text 0x33f80bcc 0x150 cpu/arm920t/s3c24x0/libs3c24x0.a(speed.o)

0x33f80c4c get_HCLK

0x33f80cec get_PCLK

0x33f80c44 get_FCLK

0x33f80d14 get_UCLK

.text 0x33f80d1c 0x1e8 cpu/arm920t/s3c24x0/libs3c24x0.a(cmd_s3c24xx.o) 0x33f80d8c do_s3c24xx

.text 0x33f80f04 0xdc cpu/arm920t/s3c24x0/libs3c24x0.a(serial.o)

0x33f80f04 serial_setbrg

0x33f80fa8 serial_tstc

0x33f80f80 serial_putc

0x33f80f58 serial_init

0x33f80fb8 serial_puts

0x33f80f68 serial_getc

.text 0x33f80fe0 0x140 lib_arm/libarm.a(_divsi3.o)

0x33f80fe0 __divsi3

如何设置从0x33f80000开始呢?~这是链接的时候指定的

在根目录下面的config.mk中有下面一句

LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)

关键就是其中的-Ttext $(TEXT_BASE),这句指明了代码段的起始地址

而TEXT_BASE在board/smdk2440/config.mk中定义TEXT_BASE = 0x33F8 0000 为什么是0x33F8 0000呢?~

这是将NAND中Uboot拷贝到RAM中的起始地址,所以在代码拷贝到RAM之前不能使用绝对地址来寻址数据,只能用相对地址

在以下将用虚拟地址来指Uboot在RAM中的地址,也就是0x33F8 0000

现在来看代码cpu/arm920t/start.S

_start: ;异常处理向量表

b start_code

ldr pc, _undefined_instruction ;未定义指令异常:0x00000004

ldr pc, _software_interrupt ;软中断异常:0x00000008

ldr pc, _prefetch_abort ;预取异常:0x0000000C

ldr pc, _data_abort ;数据异常:0x00000010

ldr pc, _not_used ;未使用:0x00000014

ldr pc, _irq ;外部中断请求IRQ:0x00000018

ldr pc, _fiq ;快束中断请求FIQ:0x0000001C

b start_code在虚拟地址0x33F8 0000处, 拷贝到Boot Internal SRAM后则位于0x0处,所以b start_code是第一条执行的指令,

start_code在cpu/arm920t/start.S中

代码如下:

//读取CPSR寄存器的内容到R0

mrs r0,cpsr

//清除R0中的0 - 4 这5个位后保存到R0中

//也就是清除用户模式位

bic r0,r0,#0x1f

//置R0的0 1 4 6 7 位为真

//也就是选择SVC模式,同时IRQ和FIQ被禁止,处理器处于ARM状态

//关闭中断和快速中断

orr r0,r0,#0xd3

//将R0中的值保存到CPSR上

msr cpsr,r0

# define pWTCON 0x53000000 ;看门狗控制寄存器WTCON

# define INTMSK 0x4A000008 ;中断屏蔽寄存器INTMSK

# define INTSUBMSK 0x4A00001C ;辅助中断屏蔽寄存器,由于外设中断源太多,要用此寄存器屏蔽剩余的中断源

# define LOCKTIME 0x4c000000 ;PLL锁定时间计数寄存器

# define MPLLCON 0x4c000004 ;主时钟锁相环控制寄存器

# define UPLLCON 0x4c000008

# define CLKDIVN 0x4C000014 ;时钟分频寄存器/* clock divisor register */

# define INTSUBMSK_val 0xffff

# define MPLLCON_val ((184 12) + (2 4) + 2) /*406M*/

# define UPLLCON_val ((60 12) + (4 4) + 2) /* 47M */

# define CLKDIVN_val 7 /* FCLK:HCLK:PCLK = 1:3:6 */

# define CAMDIVN 0x4C000018

//取得看门狗寄存器的地址

ldr r0, =pWTCON

//将R1寄存器清0

mov r1, #0x0

//将看门狗寄存器清0,即将看门狗禁止,包括定时器定时,溢出中断及溢出复位等

str r1, [r0]

/*

* mask all IRQs by setting all bits in the INTMR - default

*/

//设R1寄存器为0xFFFF FFFF

mov r1, #0xffffffff

//读取中断屏蔽寄存器的地址

ldr r0, =INTMSK

//将中断屏蔽寄存器中的位全设1,屏蔽所有中断

str r1, [r0]

//# define INTSUBMSK_val 0xffff

//设R1寄存器为0xFFFF

ldr r1, =INTSUBMSK_val

//读取辅助中断屏蔽寄存器的地址

ldr r0, =INTSUBMSK

//将辅助中断屏蔽寄中的11个中断信号屏蔽掉,本人觉得INTSUBMS_val应设成7ff str r1, [r0]

//# define LOCKTIME 0x4c000000

//读取PLL锁频计数器寄存器地址到R0中

ldr r0,=LOCKTIME

//将R1设为0x00FF FFFF

ldr r1,=0xffffff

//M_LTIME为最大的0xFFF

//U_LTIME为最大的0xFFF

str r1,[r0] ;0xfff=4096>1800,远远满足锁定要求

/* FCLK:HCLK:PCLK = 1:2:4 */

/* default FCLK is 120 MHz ! */

//# define CLKDIVN 0x4C000014 /* clock divisor register */

//读取时钟分频寄存器的地址

ldr r0, =CLKDIVN

//# define CLKDIVN_val 7 /* FCLK:HCLK:PCLK = 1:3:6 */

//将R1设为0x7

mov r1, #CLKDIVN_va

//PDIVN - 1: PCLK has the clock same as the HCLK/2.

//HDIVN - 11 : HCLK = FCLK/3 when CAMDIVN[8] = 0.

// HCLK = FCLK/6 when CAMDIVN[8] = 1.

str r1, [r0]

/* Make sure we get FCLK:HCLK:PCLK = 1:3:6 */

//# define CAMDIVN 0x4C000018

//读取摄像头时钟分频寄存器的地址

ldr r0, =CAMDIVN

//将R1设为0

mov r1, #0

//将摄像头时钟分频寄存器清0

str r1, [r0]

/* Clock asynchronous mode */

//MRC p15, 0, Rd, c1, c0, 0 ; read control register

//读取控制寄存器中的值到R1中

mrc p15, 0, r1, c1, c0, 0 ;将协处理器p15的寄存器c1和c0的值传到arm处理器的R1寄存器中

//31 iA bit Asynchronous clock select

//30 nF bit notFastBus select

orr r1, r1, #0xc0000000 ;将最高两位置1

//MCR p15, 0, Rd, c1, c0, 0 ; write control register

//将R1中的值写到控制寄存器中

mcr p15, 0, r1, c1, c0, 0 将arm的寄存器R1的32位数据传到协处理器p15的两个16位寄存器c1和c0

//# define UPLLCON 0x4c000008

//读取UPLL设置寄存器的地址到R0中

ldr r0,=UPLLCON

//# define UPLLCON_val ((60

ldr r1,=UPLLCON_val

//将R1中的值写入UPLL设置寄存器中

str r1,[r0]

//ARM920T为5级流水线,需要至少5个周期来让指令生效

nop

nop

nop

nop

nop

nop

nop

nop

//读取MPLL设置寄存器的地址到R0中

ldr r0,=MPLLCON

//# define MPLLCON_val ((184

ldr r1,=MPLLCON_val

//将R1中的值写入MPLL设置寄存器中

str r1,[r0]

#define GPJCON 0x560000D0

#define GPJDAT 0x560000D4

#define GPJUP 0x560000D8

//跳转到cpu_init_crit处执行

//并将下一条指令的地址写入LR寄存器中

bl cpu_init_crit

cpu_init_crit在cpu/arm920t/start.S中

代码如下:

cpu_init_crit:

/*

* flush v4 I/D caches

*/

//将R0寄存器置0

mov r0, #0

//Invalidate ICache and DCache SBZ MCR p15,0,Rd,c7,c7,0 //禁止指令和数据cache

mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */

//Invalidate TLB(s) SBZ MCR p15,0,Rd,c8,c7,0

mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */

/*

* disable MMU stuff and caches

*/

//MRC p15, 0, Rd, c1, c0, 0 ; read control register

mrc p15, 0, r0, c1, c0, 0

//清除[8] [9] [13] 这3个位

//8 - System protection

//9 - ROM protection

//13 - Base location of exception registers - 0 = Low addresses = 0x00000000. bic r0, r0, #0x00002300 // clear bits 13, 9:8 (--V- --RS)

//清除[0] [1] [2] [7] 这4个位

// 0 - MMU enable - 0 = MMU disabled.

// 1 - Alignment fault enable - 0 = Fault checking disabled.

// 2 - DCache enable - 0 = DCache disabled.

// 7 - Endianness - 0 = Little-endian operation.

bic r0, r0, #0x00000087 // clear bits 7, 2:0 (B--- -CAM)

//设置位[1]为真

// 1 - Alignment fault enable - 1 = Fault checking enabled.

orr r0, r0, #0x00000002 // set bit 2 (A) Align

//设置位[12]为真

//12 - ICache enable - 1 = ICache enabled.

orr r0, r0, #0x00001000 // set bit 12 (I) I-Cache

//MCR p15, 0, Rd, c1, c0, 0 ; write control register

mcr p15, 0, r0, c1, c0, 0

//将返回地址保存到IP中

mov ip, lr

//跳转到lowlevel_init中执行

bl lowlevel_init

cpu_init_crit在cpu/arm920t/start.S中

代码如下:

.globl lowlevel_init

//读取下面标号为SMRDATA处的地址到R0中

ldr r0, =SMRDATA

//读取上面标号为_TEXT_BASE处的地址内容到R1中

//也就是取得TEXT_BASE的值到R1中

ldr r1, _TEXT_BASE

//计算SMRDATA的相对地址保存到R0中

//SMRDATA为虚拟地址,而TEXT_BASE为虚拟地址的起始地址

//而现在Uboot的起始地址并不为虚拟地址

//TEXT_BASE为0x33F8 0000,SMRDATA为0x33F8 06C8

//而现在程序运行在起始地址为0x0000 0000的地方

//所以需要计算以0x0000 0000为标准的相对地址

sub r0, r0, r1

//取得带宽与等待状态控制寄存器地址到R1中

ldr r1, =BWSCON /* Bus Width Status Controller */

//一共需要设置13个寄存器,每个寄存器4字节

add r2, r0, #13*4

0:

//读取R0所指的项的值到R3中后R0自加4字节

ldr r3, [r0], #4

//将R3中的值保存到R1所指的地址中后R1自加4字节

str r3, [r1], #4

//比较R0和R2是否相等,相等则说明13个寄存器全部设置完毕

cmp r2, r0

//不等则跳转到上面标号为0处的地址继续执行

bne 0b

//跳回到返回地址中继续执行

mov pc, lr

.ltorg

/* the literal pools origin */

SMRDATA:

.word

(0+(B1_BWSCON4)+(B2_BWSCON8)+(B3_BWSCON12)+(B4_BWSCON16)+( B5_BWSCON20)+(B6_BWSCON24)+(B7_BWSCON28))

.word

((B0_Tacs13)+(B0_Tcos11)+(B0_Tacc8)+(B0_Tcoh6)+(B0_Tah4)+(B0_Tacp2) +(B0_PMC))

.word

((B1_Tacs13)+(B1_Tcos11)+(B1_Tacc8)+(B1_Tcoh6)+(B1_Tah4)+(B1_Tacp2) +(B1_PMC))

.word

((B2_Tacs13)+(B2_Tcos11)+(B2_Tacc8)+(B2_Tcoh6)+(B2_Tah4)+(B2_Tacp2) +(B2_PMC))

.word

((B3_Tacs13)+(B3_Tcos11)+(B3_Tacc8)+(B3_Tcoh6)+(B3_Tah4)+(B3_Tacp2) +(B3_PMC))

.word

((B4_Tacs13)+(B4_Tcos11)+(B4_Tacc8)+(B4_Tcoh6)+(B4_Tah4)+(B4_Tacp2) +(B4_PMC))

.word

((B5_Tacs13)+(B5_Tcos11)+(B5_Tacc8)+(B5_Tcoh6)+(B5_Tah4)+(B5_Tacp2) +(B5_PMC))

.word ((B6_MT15)+(B6_Trcd2)+(B6_SCAN))

.word ((B7_MT15)+(B7_Trcd2)+(B7_SCAN))

.word ((REFEN23)+(TREFMD22)+(Trp20)+(Trc18)+(Tchr16)+REFCNT)

.word 0x32

.word 0x30

.word 0x30

执行mov pc, lr后将返回到cpu_init_crit中

剩下来还有2条指令

//恢复返回地址到LR

mov lr, ip

//跳转到返回地址

mov pc, lr

执行完毕之后将返回到start_code中执行接下来的代码

代码如下:

//#define GPJCON 0x560000D0

//取得J端口控制寄存器的地址到R0中

LDR R0, = GPJCON

//将R1设置为0x1 5555

LDR R1, = 0x15555

//将R1中的值保存到J端口控制寄存器

//GPJ0 - 01 - Output

//GPJ1 - 01 - Output

//GPJ2 - 01 - Output

//GPJ3 - 01 - Output

//GPJ4 - 01 - Output

STR R1, [R0]

//#define GPJUP 0x560000D8

//取得J端口上拉功能寄存器的地址到R0中

LDR R0, = GPJUP

//将R1设置为0x1F

LDR R1, = 0x1f

//将R1中的值保存到J端口上拉功能寄存器

//禁止GPJ0 - GPJ4的上拉功能

STR R1, [R0]

//#define GPJDAT 0x560000D4

//取得J端口数据寄存器的地址到R0中

LDR R0, = GPJDAT

//将R1设为0x0

LDR R1, = 0x00

//将R1中的值保存到J端口数据寄存器

//将J端口数据寄存器清0

STR R1, [R0]

//下面是NAND数据拷贝过程

//relocate:

copy_myself:

//#define S3C2440_NAND_BASE 0x4E000000

//取得Nand Flash设置寄存器的地址

mov r1, #S3C2440_NAND_BASE

//将R2设为0xFFF0

ldr r2, =0xfff0 // initial value tacls=3,rph0=7,rph1=7 //#define oNFCONF 0x00

//读取Nand Flash设置寄存器中的值到R3中

ldr r3, [r1, #oNFCONF]

//将R3或上R2后保存到R3中

orr r3, r3, r2

//将R3中的值保存到Nand Flash设置寄存器中

//TWRPH0 - 111 - Duration = HCLK * (TWRPH0 + 1) //TACLS - 11 - Duration = HCLK * TACLS

str r3, [r1, #oNFCONF]

//#define oNFCONT 0x04

//读取Nand Flash控制寄存器中的值到R3中

ldr r3, [r1, #oNFCONT]

//将R3的[0]位置1

orr r3, r3, #1 // enable nand controller

//将R3中的值保存到Nand Flash控制寄存器中

//Mode - 1:Nand Flash Controller Enable

str r3, [r1, #oNFCONT]

//读取虚拟起始地址到R0中

ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */

//预留malloc所需要的空间

sub r0, r0, #CFG_MALLOC_LEN /* malloc area */

//预留bdinfo所需要的空间

sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */

//预留中断和快速中断向量表空间

sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

//预留12字节给中断栈

sub sp, r0, #12 /* leave 3 words for abort-stack */

// copy u-boot to RAM

//读取虚拟起始地址到R0中,作为目标地址

ldr r0, _TEXT_BASE

//将R1设为0,作为源地址

mov r1, #0x0

//将UBOOT大小的值保存在R2中,作为数据大小

mov r2, #CFG_UBOOT_SIZE

//跳转到nand_read_ll处执行

//并将下一条指令的地址保存在LR中

bl nand_read_ll

nand_read_ll的原型为

int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size) 之前设置的R0 R1 R2为它的3个参数

R0 - buf

R1 - start_addr

R2 - size

nand_read_ll的代码在cpu/arm920t/s3c24x0/nand_read.c中

int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size) {

int i, j;

//检测源地址和大小是否在NandFlash的边界上

if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) //不在边界上则返回-1表示出错

return -1; /* invalid alignment */

/* chip Enable */

// #define nand_select() (NFCONT &= ~(1

//置NAND Flash控制寄存器中除Reg_nCE外所有的位为1

//Reg_nCE - NAND FLASH Memory nFCE signal control

//0 - Force nFCE to low (Enable chip select)

nand_select();

// #define nand_clear_RnB() (NFSTAT |= (1

//置NAND Flash操作状态寄存器中的RnB_TransDetect位为1

//When RnB low to high transition is occurred, this value set and issue interrupt if enabled.

//To clear this value write '1'

//1: RnB transition is detected

nand_clear_RnB();

for (i=0; i10; i++);

//从源地址的首地址开始历便所要拷贝的数据大小

for (i=start_addr; i (start_addr + size);)

{

//检测地址是否在NAND Flash的边界上

if (start_addr % NAND_BLOCK_SIZE == 0)

{

//检测是否为坏块

if (is_bad_block(i))

{

/* Bad block */

//向后延伸一个存储块

i += NAND_BLOCK_SIZE;

size += NAND_BLOCK_SIZE;

//跳到下一块

continue;

}

}

j = nand_read_page_ll(buf, i);

//指向下一块

i += j;

buf += j;

// LED_FLASH();

}

/* chip Disable */

// #define nand_deselect() (NFCONT |= (1

//置Reg_nCE位为1

//NAND Flash Memory nFCE signal control

//1: Force nFCE to High(Disable chip select)

nand_deselect();

return 0;

}

nand_read_ll将Uboot从NAND中拷贝到RAM中

拷贝完成后将返回到start_code

接下来的代码如下:

//检测R0是否为0,R0为nand_read_ll的返回值

tst r0, #0x0

//为0则说明无错,跳转到ok_nand_read处执行

beq ok_nand_read

ok_nand_read:

//将R0设为0

mov r0, #0

//ldr r1, =0x33f00000

//将R1设为虚拟地址起始处

ldr r1, _TEXT_BASE

//检测0x400个字节

mov r2, #0x400 // 4 bytes * 1024 = 4K-bytes

go_next:

//读取R0处地址的数据到R3中

//然后R0自加4字节

ldr r3, [r0], #4

//读取R1处地址的数据到R4中

//然后R1自加4字节

ldr r4, [r1], #4

//比较R3和R4的数据是否相等

//也就是检测Boot Internal SRAM和RAM中的数据是否相等//以保证数据无错

teq r3, r4

//不等则跳转到notmatch

bne notmatch

//相等则R2自减4

subs r2, r2, #4

//当R2为0则跳转到done_nand_read

beq done_nand_read

//R2不为0则跳转回go_next继续检测

bne go_next

done_nand_read:

LDR R0, = GPJDAT

LDR R1, = 0x2

STR R1, [R0]

stack_setup:

//读取虚拟起始地址到R0中

ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ //预留malloc所需要的空间

sub r0, r0, #CFG_MALLOC_LEN /* malloc area */

//预留bdinfo所需要的空间

sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */

//预留中断和快速中断向量表空间

sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

//预留12字节给中断栈

sub sp, r0, #12 /* leave 3 words for abort-stack */

clear_bss:

//读取BSS段的起始地址

ldr r0, _bss_start /* find start of bss segment */

//读取BSS段的结束地址

ldr r1, _bss_end /* stop here */

//将R2设为0x0

mov r2, #0x00000000 /* clear */

clbss_l:

//将R2中的值保存在R0所指的地址

str r2, [r0] /* clear loop... */

//R0自加4字节

add r0, r0, #4

//比较R0和R1是否相等

cmp r0, r1

//不等则说明清0还没结束

ble clbss_l

LDR R0, = GPJDAT

LDR R1, = 0x1

STR R1, [R0]

//跳转到start_armboot处执行

ldr pc, _start_armboot

_start_armboot: .word start_armboot

这里start_armboot是一个绝对地址,在朗成所修改的这个Uboot中为0x33F8 13F4 执行ldr pc, _start_armboot之后将会跳到RAM中的绝对地址继续执行

整理了一个流程图,分为3个存储器:

1 Boot Internal SRAM , 接在BANK0,起始地址为0x0

2 RAM , 接在BANK6,起始地址为0x3000 0000

3 NAND FLASH,为单独寻址

流程如下图:

红字为流程序号:

1. 首先将NAND FLASH中的前0x1000字节内容拷贝到Boot Internal SRAM中

2. 从Boot Internal SRAM的0x0地址处开始执行指令

3. 将Uboot从Flash拷贝到RAM中

4. 执行ldr pc, _start_armboot

从Boot Internal SRAM中跳转到RAM中的绝对地址0x33F8 13F4处继续执行

u-boot启动分析

背景: Board →ar7240(ap93) Cpu →mips 1、首先弄清楚什么是u-boot Uboot是德国DENX小组的开发,它用于多种嵌入式CPU的bootloader程序, uboot不仅支持嵌入式linux系统的引导,当前,它还支持其他的很多嵌入式操作系统。 除了PowerPC系列,还支持MIPS,x86,ARM,NIOS,XScale。 2、下载完uboot后解压,在根目录下,有如下重要的信息(目录或者文件): 以下为为每个目录的说明: Board:和一些已有开发板有关的文件。每一个开发板都以一个子目录出现在当前目录中,子目录存放和开发板相关的配置文件。它的每个子文件夹里都有如下文件(以ar7240/ap93为例): Makefile Config.mk Ap93.c 和板子相关的代码 Flash.c Flash操作代码 u-boot.lds 对应的链接文件 common:实现uboot命令行下支持的命令,每一条命令都对应一个文件。例如bootm命令对应就是cmd_bootm.c cpu:与特定CPU架构相关目录,每一款Uboot下支持的CPU在该目录下对应一个子目录,比如有子目录mips等。它的每个子文件夹里都有入下文件: Makefile Config.mk Cpu.c 和处理器相关的代码s Interrupts.c 中断处理代码 Serial.c 串口初始化代码 Start.s 全局开始启动代码 Disk:对磁盘的支持

Doc:文档目录。Uboot有非常完善的文档。 Drivers:Uboot支持的设备驱动程序都放在该目录,比如网卡,支持CFI的Flash,串口和USB等。 Fs:支持的文件系统,Uboot现在支持cramfs、fat、fdos、jffs2和registerfs。 Include:Uboot使用的头文件,还有对各种硬件平台支持的汇编文件,系统的配置文件和对文件系统支持的文件。该目下configs目录有与开发板相关的配置文件,如 ar7240_soc.h。该目录下的asm目录有与CPU体系结构相关的头文件,比如说mips 对应的有asm-mips。 Lib_xxx:与体系结构相关的库文件。如与ARM相关的库放在lib_arm中。 Net:与网络协议栈相关的代码,BOOTP协议、TFTP协议、RARP协议和NFS文件系统的实现。 Tools:生成Uboot的工具,如:mkimage等等。 3、mips架构u-boot启动流程 u-boot的启动过程大致做如下工作: 1、cpu初始化 2、时钟、串口、内存(ddr ram)初始化 3、内存划分、分配栈、数据、配置参数、以及u-boot代码在内存中的位置。 4、对u-boot代码作relocate 5、初始化malloc、flash、pci以及外设(比如,网口) 6、进入命令行或者直接启动Linux kernel 刚一开始由于参考网上代码,我一个劲的对基于smdk2410的板子,arm926ejs的cpu看了N 久,启动过程和这个大致相同。 整个启动中要涉及到四个文件: Start.S →cpu/mips/start.S Cache.S →cpu/mips/cache.S Lowlevel_init.S →board/ar7240/common/lowlevel_init.S Board.c →lib_mips/board.c 整个启动过程分为两个阶段来看: Stage1:系统上电后通过汇编执行代码 Stage2:通过一些列设置搭建了C环境,通过汇编指令跳转到C语言执行. Stage1: 程序从Start.S的_start开始执行.(至于为什么,参考u-boot.lds分析.doc) 先查看start.S文件吧!~ 从_start标记开始会看到一长串莫名奇妙的代码:

NandFlash简介

NandFlash简介 分类:Linux2013-03-06 14:34 2945人阅读评论(0) 收藏举报 Flash Memory中文名字叫闪存,是一种长寿命的非易失性(在断电情况下仍能保持所存储的数据信息)的存储器。 从名字中就可以看出,非易失性就是不容易丢失,数据存储在这类设备中,即使断电了,也不会丢失,这类设备,除了Flash,还有其他比较常见的入硬盘,ROM等,与此相对的,易失性就是断电了,数据就丢失了,比如大家常用的内存,不论是以前的SDRAM,DDR SDRAM,还是现在的DDR2,DDR3等,都是断电后,数据就没了。 FLASH的分类:功能特性分为两种:一种是NOR型闪存,以编码应用为主,其功能多与运算相关;另一种为NAND型闪存,主要功能是存储资料,如数码相机中所用的记忆卡。 NOR FLASH和NAND FLASH NOR和NAND是现在市场上两种主要的非易失闪存技术。Intel于1988年首先开发出NOR flash技术,彻底改变了原先由EPROM和EEPROM 一统天下的局面。紧接着,1989年,东芝公司发表了NAND flash结结,强调降低每比特的成本,更高的性能,并且象磁盘一样可以通过接口轻松升级。但是经过了十多年之后,仍然有相当多的硬件工程师分不清NOR和NAND闪存。 NOR的读速度比NAND稍快一些。 NAND的写入速度比NOR快很多。 NAND的4ms擦除速度远比NOR的5s快。 大多数写入操作需要先进行擦除操作。 NAND的擦除单元更小,相应的擦除电路更少 在NOR Flash中, 所有的存储区域都保证是完好的, 同时也拥有相同的耐久性。在硬模中专门制成了一个相当容量的扩展存储单元—他们被用来修补存储阵列中那些坏的部分,这也是为了保证生产出来的产品全部拥有完好的存储区域。为了增加产量和降低生产成本, NAND Flash 器件中存在一些随机bad block 。为了防止数据存储到这些坏的单元中, bad block 在IC烧录前必须先识别。在一些出版物中, 有人称bad block 为“bad block”, 也有人称bad block 为“invalid block”。其实他们拥有相同的含义, 指相同的东西。 从实际的应用上来说, NOR Flash与NAND Flash主要的区别在于接口。NOR Flash拥有完整的存取-映射访问接口, 它拥有专门的地址线和数据线, 类似与EPROM。然而在NAND Flash中没有专门的地址线。它发送指令,地址和数据都通过8/16位宽的总线(I/O接口)到内部的寄存器。 SLC/MLC基本原理

NAND Flash中文版资料

NAND Flash 存储器 和 使用ELNEC编程器烧录NAND Flash 技术应用文档 Summer 翻译整理 深圳市浦洛电子科技有限公司 August 2006

目录 一. 简介 ----------------------------------------------------------------------------------- 1 二. NAND Flash与NOR Flash的区别 -------------------------------------------- 1 三. NAND Flash存储器结构描叙 --------------------------------------------------- 4 四. 备用单元结构描叙 ---------------------------------------------------------------- 6 五. Skip Block method(跳过坏块方式) ------------------------------------------ 8 六. Reserved Block Area method(保留块区域方式)----------------------------- 9 七. Error Checking and Correction(错误检测和纠正)-------------------------- 10 八. 文件系统 ------------------------------------------------------------------------------10 九. 使用ELNEC系列编程器烧录NAND Flash -------------------------------- 10 十. Invalid Block Management drop-down menu -------------------------------- 12 十一. User Area Settings3 -------------------------------------------------------- 13 十二. Solid Area Settings --------------------------------------------------------- 15 十三. Quick Program Check-box ---------------------------------------------- 16 十四. Reserved Block Area Options --------------------------------------------17 十五. Spare Area Usage drop-down menu ------------------------------------18

UBOOT命令详解

常用U-boot命令详解(z) 2010-09-30 15:05:52| 分类:学习心得体会|字号订阅 U-boot发展到现在,他的命令行模式已经非常接近Linux下的shell了,在我编译的 U-boot-2009.11中的命令行模式模式下支持“Tab”键的命令补全和命令的历史记录功能。而且如果你输入的命令的前几个字符和别的命令不重复,那么你就只需要打这几个字符即可,比如我想看这个U-boot的版本号,命令就是“ version”,但是在所有的命令中没有其他任何一个的命令是由“v”开头的,所以只需要输入“v”即可。 [u-boot@MINI2440]# version U-Boot 2009.11 ( 4月04 2010 - 12:09:25) [u-boot@MINI2440]# v U-Boot 2009.11 ( 4月04 2010 - 12:09:25) [u-boot@MINI2440]# base Base Address: 0x00000000 [u-boot@MINI2440]# ba Base Address: 0x00000000 由于U-boot支持的命令实在太多,一个一个细讲不现实,也没有必要。所以下面我挑一些烧写和引导常用命令介绍一下,其他的命令大家就举一反三,或者“help”吧! (1)获取帮助 命令:help 或? 功能:查看当前U-boot版本中支持的所有命令。 [u-boot@MINI2440]#help ?- alias for'help' askenv - get environment variables from stdin base - print or set address offset bdinfo - print Board Info structure bmp - manipulate BMP image data boot - boot default, i.e., run 'bootcmd' bootd - boot default, i.e., run 'bootcmd' bootelf - Boot from an ELF image in memory bootm - boot application image from memory bootp - boot image via network using BOOTP/TFTP protocol

Tiny6410_Uboot移植步骤详解

Uboot_for_Tiny6410_移植步骤详解 一、设计要求 1.目的 1)掌握U-boot剪裁编写 2)掌握交叉编译环境的配置 3)掌握U-boot的移植 2.实现的功能 1)U-boot编译成功 2)移植U-boot,使系统支持从NAND FLASH启动 二、设计方案 1.硬件资源 1)ARM处理器:ARM11芯片(Samsung S3C6410A),基于ARM1176JZF-S核设 计,运行频率533Mhz,最高可达 667Mhz 2)存储器:128M DDR RAM,可升级至 256M;MLC NAND Flash(2GB) 3)其他资源:具有三LCD接口、4线电阻 触摸屏接口、100M标准网络接口、标准DB9 五线串口、Mini USB2.0接口、USB Host 1.1、3.5mm音频输入输出口、标准TV-OUT

接口、SD卡座、红外接收等常用接口;另外 还引出4路TTL串口,另1路TV-OUT、 SDIO2接口(可接SD WiFi)接口等;在板的 还有蜂鸣器、I2C-EEPROM、备份电池、A D 可调电阻、8个中断式按键等。 2.软件资源 1)arm-linux-gcc-4.5.1(交叉编译) 2)u-boot-2010.09.tar.gz arm-linux-gcc-4.5.1-v6-vfp-20101103.t gz 三、移植过程 1.环境搭建 1)建立交叉编译环境 2)去这2个网站随便下载都可以下载得到最 新或者你想要的u-boot。( https://www.360docs.net/doc/ce3626002.html,/batch.viewl ink.php?itemid=1694 ftp://ftp.denx.de/pub/u-boot/ )

AM335x uboot spl分析

AM335x uboot spl分析 芯片到uboot启动流程 ROM → SPL→ uboot.img 简介 在335x 中ROM code是第一级的bootlader。mpu上电后将会自动执行这里的代码,完成部分初始化和引导第二级的bootlader,第二级的bootlader引导第三级bootader,在 ti官方上对于第二级和第三级的bootlader由uboot提供。 SPL To unify all existing implementations for a secondary program loader (SPL) and to allow simply adding of new implementations this generic SPL framework has been created. With this framework almost all source files for a board can be reused. No code duplication or symlinking is necessary anymore. 1> Basic ARM initialization 2> UART console initialization 3> Clocks and DPLL locking (minimal) 4> SDRAM initialization 5> Mux (minimal) 6> BootDevice initialization(based on where we are booting from.MMC1/MMC2/Nand/Onenand) 7> Bootloading real u-boot from the BootDevice and passing control to it. uboot spl源代码分析 一、makefile分析 打开spl文件夹只有一个makefile 可见spl都是复用uboot原先的代码。 主要涉及的代码文件为u-boot-2011.09-psp04.06.00.03/arch/arm/cpu/armv7 u-boot-2011.09-psp04.06.00.03/arch/arm/lib u-boot-2011.09-psp04.06.00.03/drivers LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-spl.lds 这个为链接脚本 __image_copy_end _end 三、代码解析 __start 为程序开始(arch/arm/cpu/armv7/start.S) .globl _start 这是在定义u-boot的启动定义入口点,汇编程序的缺省入口是 start 标号,用户也可以在连接脚本文件中用ENTRY标志指明其它入口点。

UBoot移植详解

u-boot 移植步骤详解 1 U-Boot简介 U-Boot,全称Universal Boot Loader,是遵循GPL条款的开放源码项目。从FADSROM、8xxROM、PPCBOOT逐步发展演化而来。其源码目录、编译形式与Linux内核很相似,事实上,不少U-Boot源码就是相应的Linux内核源程序的简化,尤其是一些设备的驱动程序,这从U-Boot源码的注释中能体现这一点。但是U-Boot不仅仅支持嵌入式Linux 系统的引导,当前,它还支持NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS嵌入式操作系统。其目前要支持的目标操作系统是OpenBSD, NetBSD, FreeBSD,4.4BSD, Linux, SVR4, Esix, Solaris, Irix, SCO, Dell, NCR, VxWorks, LynxOS, pSOS, QNX, RTEMS, ARTOS。这是U-Boot中Universal的一层含义,另外一层含义则是U-Boot除了支持PowerPC系列的处理器外,还能支持MIPS、x86、ARM、NIOS、XScale等诸多常用系列的处理器。这两个特点正是U-Boot项目的开发目标,即支持尽可能多的嵌入式处理器和嵌入式操作系统。就目前来看,U-Boot对PowerPC系列处理器支持最为丰富,对Linux的支持最完善。其它系列的处理器和操作系统基本是在2002年11 月PPCBOOT 改名为U-Boot后逐步扩充的。从PPCBOOT向U-Boot的顺利过渡,很大程度上归功于U-Boot的维护人德国DENX软件工程中心Wolfgang Denk[以下简称W.D]本人精湛专业水平和持着不懈的努力。当前,U-Boot项目正在他的领军之下,众多有志于开放源码BOOT LOADER移植工作的嵌入式开发人员正如火如荼地将各个不同系列嵌入式处理器的移植工作不断展开和深入,以支持更多的嵌入式操作系统的装载与引导。 选择U-Boot的理由: ①开放源码; ②支持多种嵌入式操作系统内核,如Linux、NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS; ③支持多个处理器系列,如PowerPC、ARM、x86、MIPS、XScale; ④较高的可靠性和稳定性; ④较高的可靠性和稳定性; ⑤高度灵活的功能设置,适合U-Boot调试、操作系统不同引导要求、产品发布等; ⑥丰富的设备驱动源码,如串口、以太网、SDRAM、FLASH、LCD、NVRAM、EEPROM、RTC、键盘等; ⑦较为丰富的开发调试文档与强大的网络技术支持; 2 U-Boot主要目录结构 - board 目标板相关文件,主要包含SDRAM、FLASH驱动; - common 独立于处理器体系结构的通用代码,如内存大小探测与故障检测;

i.MX6UL -- Linux系统移植过程详解(最新的长期支持版本)

i.MX6UL -- Linux系统移植过程详解(最新的长期支持版本) ?开发平台:i.MX 6UL ?最新系统: u-boot2015.04 + Linux4.1.15_1.2.0 ?交叉编译工具:dchip-linaro-toolchain.tar.bz2 源码下载地址: U-Boot: (选择rel_imx_4.1.15_1.2.0_ga.tar.bz2) https://www.360docs.net/doc/ce3626002.html,/git/cgit.cgi/imx/uboot-imx.git/ Kernel: (选择rel_imx_4.1.15_1.2.0_ga.tar.bz2) https://www.360docs.net/doc/ce3626002.html,/git/cgit.cgi/imx/linux-2.6-imx.git/ 源码移植过程: 1、将linux内核及uBoot源码拷贝到Ubuntu12.04系统中的dchip_imx6ul目录下; 2、使用tar命令分别将uboot和kernel解压到dchip_imx6ul目录下; 3、解压后进入uboot目录下,新建文件make_dchip_imx6ul_uboot201504.sh,且文件内容如下: ################################################################### # Build U-Boot.2015.04 For D518--i.MX6UL By FRESXC # ################################################################### #!/bin/bash export ARCH=arm export CROSS_COMPILE=/dchip-linaro-toolchain/bin/arm-none-linux-gnueabi - make mrproper # means CLEAN make mx6ul_14x14_evk_defconfig make2>&1|tee built_dchip_imx6ul_uboot201504.out 4进入kernel目录下,新建文件make_dchip_imx6ul_linux4115120.sh,且文件内容如下: ###################################################################

uboot版本文件结构

uboot版本文件结构的更新改变 分类:ARM2011-09-22 12:57 339人阅读评论(0) 收藏举报本来是开始分析uboot代码的,但是无论是教材还是网上资料都对于我最新下的uboot原码结构不同,对于还是小白的我不容易找到相应的文件,下面是uboot版本中文件组织结构的改变,,,,, u-boot版本情况 网站:http://ftp.denx.de/pub/u-boot/ 1、版本号变化: 2008年8月及以前 按版本号命名:u-boot-1.3.4.tar.bz2(2008年8月更新) 2008年8月以后均按日期命名。 目前最新版本:u-boot-2011.06.tar.bz2(2011年6月更新) 2、目录结构变化: u-boot目录结构主要经历过2次变化,u-boot版本第一次从u-boot-1.3.2开始发生变化,主要增加了api的内容;变化最大的是第二次,从2010.6版本开始。 u-boot-2010.03及以前版本 ├── api存放uboot提供的接口函数 ├── board根据不同开发板定制的代码,代码也不少 ├── common通用的代码,涵盖各个方面,已命令行处理为主 ├── cpu与体系结构相关的代码,uboot的重头戏 ├── disk磁盘分区相关代码 ├── doc文档,一堆README开头的文件 ├── drivers驱动,很丰富,每种类型的设备驱动占用一个子目录 ├── examples示例程序 ├── fs文件系统,支持嵌入式开发板常见的文件系统 ├── include头文件,已通用的头文件为主 ├── lib_【arch】与体系结构相关的通用库文件 ├── nand_spl NAND存储器相关代码 ├── net网络相关代码,小型的协议栈 ├── onenand_ipl

海力士NANDFlash选型

Q1’2011 DATABOOK Rev 0.1

NAND Flash –SLC / MLC / TLC AND Flash N NAND Flash SLC COMPONENT Product Tech Density Block Size Stack Vcc/Org Package Availability Remark HY27US08281A 90nm 128Mb 16KB Mono 3.3v/X8TSOP/USOP Now HY27US08561A 90nm 256Mb 16KB Mono 3.3v/X8TSOP/USOP/FBGA Now HY27US08121B 70nm 512Mb 16KB Mono 3.3v/X8TSOP/USOP/FBGA Now H27U518S2C 57nm 512Mb 16KB Mono 3.3v/X8TSOP Now HY27US081G1M 70nm 1Gb 16KB Mono 3.3v/X8USOP Now HY27UF081G2A 70nm 1Gb 128KB Mono 3.3v/X8TSOP/USOP/FBGA Now HY27US081G2A 70nm 1Gb 128KB Mono 1.8v/X8FBGA Now H27U1G8F2B 48nm 1Gb 128KB Mono 3.3v/X8TSOP,FBGA Now H27U1G8F2B 48nm 1Gb 128KB Mono 1.8v/X8FBGA Now H27U1G8F2CTR 32nm 1Gb 128KB Mono 1.8v/X8TSOP Q4 '11H27U1G8F2CFR 32nm 1Gb 128KB Mono 1.8v/X8FBGA Q4 '11HY27UF082G2B 57nm 2Gb 128KB Mono 3.3v/X8TSOP,FBGA, LGA Now H27U2G8F2C 41nm 2Gb 128KB Mono 3.3v/X8TSOP Now HY27UF084G2B 57nm 4Gb 128KB Mono 3.3v/X8TSOP Now H27U4G8F2D 41nm 4Gb 128KB Mono 3.3v/X8TSOP Now HY27UG088G5(D)B 57nm 8Gb 128KB DDP 3.3v/X8TSOP Now 2CE/Dual CH.H27U8G8G5D 41nm 8Gb 128KB Mono 3.3v/X8TSOP Now H27QBG8GDAIR-BCB 32nm 32Gb 512KB DDP 1.8v/x8VFBGA Now 2CE/Dual CH.H27QCG8HEAIR-BCB 32nm 64Gb 512KB QDP 1.8v/x8VFBGA Now 4CE/Dual CH.H27QDG8JEAJR-BCB 32nm 128Gb 512KB ODP 1.8v/x8 JFBGA Feb. '11 4CE/Dual CH.NAND Flash MLC COMPONENT Product Tech Density Block Size Stack Vcc/Org Package Availability Remark H27U8G8T2B 48nm 8Gb 512KB Mono 3.3v/X8TSOP Now H27UAG8T2M 48nm 16Gb 512KB(4KB Page)Mono 3.3v/X8TSOP/VLGA Now H27UAG8T2A 41nm 16Gb 512KB(4KB Page)Mono 3.3v/X8TSOP Now H27UBG8U5A 41nm 32Gb 512KB(4KB Page)DDP 3.3v/X8TSOP Now H27UBG8T2M 41nm 32Gb 512KB(4KB Page)Mono 3.3v/X8VLGA Now H27UBG8T2A 32nm 32Gb 2MB(8KB Page)SDP 3.3v/x8TSOP / VLGA Now H27UCG8VFA 41nm 64Gb 512KB(4KB Page)QDP 3.3v/X8TSOP Now H27UCG8UDM 41nm 64Gb 512KB(4KB Page)DDP 3.3v/X8VLGA Now Dual CH.H27UCG8U5(D)A 32nm 64Gb 2MB(8KB Page)DDP 3.3v/x8TSOP / VLGA Now Dual CH. LGA H27UCG8T2M 26nm 64Gb 2MB(8KB Page)SDP 3.3v/x8VLGA Now H27UDG8VEM 41nm 128Gb 512KB(4KB Page)QDP 3.3v/X8VLGA Now 4CE,Dual CH.H27UDG8V5(E)A 32nm 128Gb 2MB(8KB Page)QDP 3.3v/x8TSOP / VLGA Now 4CE,Dual CH.H27UEG8YEA 32nm 256Gb 2MB(8KB Page)ODP 3.3v/x8VLGA Now 4CE,Dual CH.H27UAG8T2B 32nm 16Gb 2MB(8KB Page)SDP 3.3v/x8TSOP Now H27UBG8T2B 26nm 32Gb 2MB(8KB Page)SDP 3.3v/x8TSOP Now Legacy H27UCG8U2B 26nm 64Gb 2MB(8KB Page)DDP 3.3v/x8TSOP Jan. '11Legacy H27UDG8V2B 26nm 128Gb 2MB(8KB Page)QDP 3.3v/x8FBGA-100Feb. '11HS(ONFi2.2)H27UEG8Y2B 26nm 256Gb 2MB(8KB Page) ODP 3.3v/x8 FBGA-100 Mar. '11 HS(ONFi2.2)NAND Flash TLC COMPONENT Product Tech Density Block Size Stack Vcc/Org Package Availability Remark H27UAG8M2M 41nm 16Gb 768KB (4KB page)SDP 3.3V/x8VLGA Now H27UBG8M2A 32nm 32Gb 1MB (4KB page) SDP 3.3V/x8 VLGA Now

NOR-FLASH驱动文档(SST39VF1601)

NOR-FLASH驱动文档(SST39VF1601)2012-03-30 00:57:33 NOR-FLASH是最早出现的Flash Memory,目前仍是多数供应商支持的技术架 构.NOR-FLASH在擦除和编程操作较少而直接执行代码的场合,尤其是纯代码存储的应用中广泛使用,但是由于NOR-FLASH只支持块擦除,其擦除和编程速度较慢,而块尺寸又较大,导致擦除和编程操作所花费的时间很长,所以在纯数据存储和文件存储的应用中显得力不从心. NOR-FLASH的特点是: 1. 程序和数据可存放在同一芯片上,FLASH芯片拥有独立的数据总线和地址总线,能快速随 机读取,并且允许系统直接从Flash中读取代码执行,而无需先将代码下载至RAM中再执行; 2. 可以单字节或单字读取,但不能单字节擦除,必须以部分或块为单位或对整片执行擦除操 作,在执行写操作之前,必需先根据需要对部分,块或整片进行擦除,然后才能写入数据。 以SST系列NOR-FLASH芯片为例介绍FLASH的使用方法及驱动. 首先,在驱动的头文件中,要根据芯片的具体情况和项目的要求作如下定义: 1. 定义操作的单位,如 typedef unsigned char BYTE; // BYTE is 8-bit in length typedef unsigned short int WORD; // WORD is 16-bit in length typedef unsigned long int Uint32; // Uint32 is 32-bit in length 在这里地址多是32位的,芯片写操作的最小数据单位为WORD,定义为16位,芯片读操作的最小数据单位是BYTE,定义为8位. 2. 因为芯片分为16位和32位的,所以对芯片的命令操作也分为16位操作和32位操作(命令 操作在介绍具体的读写过程中将详细介绍). #ifdef GE01 /*宏NorFlash_32Bit,若定义了为32位NorFlash,否则为16位NorFlash*/ #define NorFlash_32Bit #endif 3. 根据芯片的情况,定义部分(段)和块的大小. #define SECTOR_SIZE 2048 // Must be 2048 words for 39VF160X #define BLOCK_SIZE 32768 // Must be 32K words for 39VF160X

uboot环境变量总结

Common目录下面与环境变量有关的文件有以下几个:env_common.c,env_dataflash.c,env_eeprom.c,env_flash.c,env_nand.c,env_nowhere.c,env_nvram.c,environment.c。 env_common.c中包含的是default_environment[]的定义; env_dataflash.c,env_eeprom.c,env_flash.c,env_nand.c, env_nvram.c 中包含的是相应存储器与环境变量有关的函数:env_init(void),saveenv(void),env_relocate_spec (void),env_relocate_spec (void),use_default()。至于env_nowhere.c,因为我们没有定义CFG_ENV_IS_NOWHERE,所以这个文件实际上没有用。 environment.c这个文件时是我真正理解环境变量的一个关键。在这个文件里定义了一个完整的环境变量的结构体,即包含了这两个ENV_CRC(用于CRC校验),Flags(标志有没有环境变量的备份,根据CFG_REDUNDAND_ENVIRONMENT这个宏定义判断)。定义这个环境变量结构体的时候还有一个非常重要的关键字: __PPCENV__,而__PPCENV__在该.c文件中好像说是gnu c编译器的属性,如下: # define __PPCENV__ __attribute__ ((section(".text"))) 意思是把这个环境变量表作为代码段,所以在编译完UBOOT后,UBOOT的代码段就会有环境变量表。当然,这要在我们定义了ENV_IS_EMBEDDED之后才行,具体而言,环境变量表会在以下几个地方出现(以nand flash为例): 1、UBOOT中的代码段(定义了ENV_IS_EMBEDDED), 2、UBOOT中的默认环 境变量, 3、紧接UBOOT(0x0 ~ 0x1ffff)后面:0x20000 ~ 0x3ffff 之间,包括备份的环境变量,我们读取,保存也是对这个区域(即参数区)进行的。3、SDRAM中的UBOOT中,包括代码段部分和默认部分,4、SDRAM中的melloc分配的内存空间中。 Environment.c代码如下: env_t environment __PPCENV__ = { ENV_CRC, /* CRC Sum */ #ifdef CFG_REDUNDAND_ENVIRONMENT 1, /* Flags: valid */ #endif { #if defined(CONFIG_BOOTARGS) "bootargs=" CONFIG_BOOTARGS "\0" #endif #if defined(CONFIG_BOOTCOMMAND) "bootcmd=" CONFIG_BOOTCOMMAND "\0" #endif #if defined(CONFIG_RAMBOOTCOMMAND) "ramboot=" CONFIG_RAMBOOTCOMMAND "\0"

NandFlash的基础知识

NAND FLASH的基础知识 NAND Flash 的数据是以bit 的方式保存在memory cell,一般来说,一个cell 中只能存储一个bit。这些cell 以8 个或者16 个为单位,连成bit line,形成所谓的byte(x8)/word(x16),这就是NAND Device 的位宽。这些Line 会再组成Page,(Nand Flash 有多种结构,我使用的Nand Flash 是K9F1208,下面内容针对三星的K9F1208U0M),每页528Byte,每32 个page 形成一个Block, Sizeof(block)=16kByte = 32 page = 32 * 528 byte Numberof(block)=64Mbyte/16kbyte=4096 1page=528byte=512byte(Main Area)+16byte(Spare Area) Nand flash 以页为单位读写数据,而以块为单位擦除数据。按照这样的组织方式可以形成所谓的三类地址: --Block Address -- Page Address --Column Address 对于NAND Flash 来讲,地址和命令只能在I/O[7:0]上传递,数据宽度是8 位。 512byte需要9bit来表示,对于528byte系列的NAND,这512byte被分成1st half和2nd half,各自的访问由地址指针命令来选择,A[7:0]就是所谓的column address。32 个page 需要5bit 来表示,占用A[13:9],即该page 在块内的相对地址。Block的地址是由A14 以上的bit 来表示,例如512Mbit的NAND,共4096block,因此,需要12 个bit 来表示,即A[25:14],如果是1Gbit 的528byte/page的NAND Flash,则block address用A[26:24]表示。而page address就是blcok address|page address in block NAND Flash 的地址表示为:Block Address|Page Address in block|halfpage pointer|Column Address 地址传送顺序是Column Address,Page Address,Block Address。由于地址只能在I/O[7:0]上传递,因此,必须采用移位的方式进行。例如,对于512Mbit x8 的NAND flash,地址范围是0~0x3FF_FFFF,只要是这个范围内的数值表示的地址都是有效的。以NAND_ADDR 为例: ◆第1 步是传递column address,就是NAND_ADDR[7:0],不需移位即可传递到I/O[7:0] 上,而halfpage pointer 即bit8 是由操作指令决定的,即指令决定在哪个halfpage 上进行读写。而真正的bit8 的值是don't care 的。 ◆第2 步就是将NAND_ADDR 右移9 位,将NAND_ADDR[16:9]传到I/O[7:0]上 ◆第3 步将NAND_ADDR[24:17]放到I/O 上 ◆第4 步需要将NAND_ADDR[25]放到I/O 上因此,整个地址传递过程需要4 步才能 完成,即4-step addressing。 如果NAND Flash 的容量是256Mbit 以下,那么,block adress 最高位只到bit24,因此寻址只需要3 步。下面,就x16 的NAND flash 器件稍微进行一下说明。由于一个page 的main area 的容量为256word,仍相当于512byte。但是,这个时候没有所谓的1st halfpage 和2nd halfpage 之分了,所以,bit8就变得没有意义了,也就是这个时候bit8 完全不用管,地址传递仍然和x8 器件相同。除了,这一点之外,x16 的NAND使用方法和x8 的使用方法完全相同。 正如硬盘的盘片被分为磁道,每个磁道又分为若干扇区,一块nand flash也分为若干block,每个block分为如干page。一般而言,block、page之间的关系随着芯片的不同而不同,典型的分配是这样的

浅谈NorFlash的原理及其应用

浅谈NorFlash的原理及其应用 NOR Flash NOR Flash是现在市场上两种主要的非易失闪存技术之一。Intel 于1988年首先开发出NOR Flash 技术,彻底改变了原先由EPROM(Erasable Programmable Read-Only-Memory电可编程序只读存储器)和EEPROM(电可擦只读存储器Electrically Erasable Programmable Read - Only Memory)一统天下的局面。紧接着,1989年,东芝公司发表了NAND Flash 结构,强调降低每比特的成本,有更高的性能,并且像磁盘一样可以通过接口轻松升级。NOR Flash 的特点是芯片内执行(XIP ,eXecute In Place),这样应用程序可以直接在Flash闪存内运行,不必再把代码读到系统RAM中。NOR 的传输效率很高,在1~4MB的小容量时具有很高的成本效益,但是很低的写入和擦除速度大大影响到它的性能。NAND的结构能提供极高的单元密度,可以达到高存储密度,并且写入和擦除的速度也很快。应用NAND的困难在于Flash的管理需要特殊的系统接口。性能比较 flash闪存是非易失存储器,可以对称为块的存储器单元块进行擦写和再编程。任何flash 器件的写入操作只能在空或已擦除的单元内进行,所以大多数情况下,在进行写入操作之前必须先执行擦除。NAND器件执行擦除操作是十分简单的,而NOR则要求在进行擦除前先要将目标块内所有的位都写为0。由于擦除NOR器件时是以64~128KB的块进行的,执行一个写入/擦除操作的时间为5s,与此相反,擦除NAND器件是以8~32KB的块进行的,执行相同的操作最多只需要4ms。执行擦除时块尺寸的不同进一步拉大了NOR和NAND之间的性能差距,统计表明,对于给定的一套写入操作(尤其是更新小文件时),更多的擦除操作必须在基于NOR的单元中进行。这样,当选择存储解决方案时,设计师必须权衡以下的各项因素。 l 、NOR的读速度比NAND稍快一些。 2、NAND的写入速度比NOR快很多。 3 、NAND的4ms擦除速度远比NOR的5s快。 4 、大多数写入操作需要先进行擦除操作。 5 、NAND的擦除单元更小,相应的擦除电路更少。此外,NAND 的实际应用方式要比NOR复杂的多。NOR可以直接使用,并可在上面直接运行代码;而NAND需要I/O接口,因此使用时需要驱动程序。不过当今流行的操作系统对NAND结构的Flash都有支持。此外,Linux内核也提供了对NAND结构的Flash的支持。详解 NOR

相关文档
最新文档