当前位置:首页 > 嵌入式 > 嵌入式教程
[导读]简单地说,Bootloader就是在操作系统内核运行之前运行的一段程序,它类似于PC机中的BIOS程序。通过这段程序,可以完成硬件设备的初始化,并建立内存空间的映射关系,从而将系统的软硬件环境带到一个合适的状态,为最终加载系统内核做好准备。

5.2U-Boot移植5.2.1Bootloader介绍1.概念

简单地说,Bootloader就是在操作系统内核运行之前运行的一段程序,它类似于PC机中的BIOS程序。通过这段程序,可以完成硬件设备的初始化,并建立内存空间的映射关系,从而将系统的软硬件环境带到一个合适的状态,为最终加载系统内核做好准备。

通常,Bootloader比较依赖于硬件平台,特别是在嵌入式系统中,更为如此。因此,在嵌入式世界里建立一个通用的Bootloader是一件比较困难的事情。尽管如此,仍然可以对Bootloader归纳出一些通用的概念来指导面向用户定制的Bootloader设计与实现。

(1)Bootloader所支持的CPU和嵌入式开发板。

每种不同的CPU体系结构都有不同的Bootloader。有些Bootloader也支持多种体系结构的CPU,如后面要介绍的U-Boot支持ARM、MIPS、PowerPC等众多体系结构。除了依赖于CPU的体系结构外,Bootloader实际上也依赖于具体的嵌入式板级设备的配置。

(2)Bootloader的存储位置。

系统加电或复位后,所有的CPU通常都从某个由CPU制造商预先安排的地址上取指令。而基于CPU构建的嵌入式系统通常都有某种类型的固态存储设备(比如ROM、EEPROM或Flash等)被映射到这个预先安排的地址上。因此在系统加电后,CPU将首先执行Bootloader程序。

(3)Bootloader的启动过程分为单阶段和多阶段两种。通常多阶段的Bootloader能提供更为复杂的功能,以及更好的可移植性。

(4)Bootloader的操作模式。大多数Bootloader都包含两种不同的操作模式:“启动加载”模式和“下载”模式,这种区别仅对于开发人员才有意义。

n 启动加载模式:这种模式也称为“自主”模式。也就是Bootloader从目标机上的某个固态存储设备上将操作系统加载到RAM中运行,整个过程并没有用户的介入。这种模式是嵌入式产品发布时的通用模式。

n 下载模式:在这种模式下,目标机上的Bootloader将通过串口连接或网络连接等通信手段从主机(Host)下载文件,比如:下载内核映像和根文件系统映像等。从主机下载的文件通常首先被Bootloader保存到目标机的RAM中,然后再被Bootloader写入到目标机上的Flash类固态存储设备中。Bootloader的这种模式在系统更新时使用。工作于这种模式下的Bootloader通常都会向它的终端用户提供一个简单的命令行接口。

(5)Bootloader与主机之间进行文件传输所用的通信设备及协议,最常见的情况就是,目标机上的Bootloader通过串口与主机之间进行文件传输,传输协议通常是xmodem/ymodem/zmodem等。但是,串口传输的速度是有限的,因此通过以太网连接并借助TFTP等协议来下载文件是个更好的选择。

2.Bootloader启动流程

Bootloader的启动流程一般分为两个阶段:stage1和stage2,下面分别对这两个阶段进行讲解。

(1)Bootloader的stage1。

在stage1中Bootloader主要完成以下工作。

n 基本的硬件初始化,包括屏蔽所有的中断、设置CPU的速度和时钟频率、RAM初始化、初始化外围设备、关闭CPU内部指令和数据cache等。

n 为加载stage2准备RAM空间,通常为了获得更快的执行速度,通常把stage2加载到RAM空间中来执行,因此必须为加载Bootloader的stage2准备好一段可用的RAM空间。

n 复制stage2到RAM中,在这里要确定两点:①stage2的可执行映像在固态存储设备的存放起始地址和终止地址;②RAM空间的起始地址。

n 设置堆栈指针sp,这是为执行stage2的C语言代码做好准备。

(2)Bootloader的stage2。

在stage2中Bootloader主要完成以下工作。

n 用汇编语言跳转到main入口函数。

由于stage2的代码通常用C语言来实现,目的是实现更复杂的功能和取得更好的代码可读性和可移植性。但是与普通C语言应用程序不同的是,在编译和链接Bootloader这样的程序时,不能使用glibc库中的任何支持函数。

n 初始化本阶段要使用到的硬件设备,包括初始化串口、初始化计时器等。在初始化这些设备之前可以输出一些打印信息。

n 检测系统的内存映射,所谓内存映射就是指在整个4GB物理地址空间中指出哪些地址范围被分配用来寻址系统的内存。

n 加载内核映像和根文件系统映像,这里包括规划内存占用的布局和从Flash上复制数据。

n 设置内核的启动参数。

5.2.2U-Boot概述1.U-Boot简介

U-Boot(UniversalBootloader)是遵循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的支持最完善。

2.U-Boot特点

U-Boot的特点如下。

n 开放源码;

n 支持多种嵌入式操作系统内核,如Linux、NetBSD、VxWorks、QNX、RTEMS、ARTOS、LynxOS;

n 支持多个处理器系列,如PowerPC、ARM、x86、MIPS、XScale;

n 较高的可靠性和稳定性;

n 高度灵活的功能设置,适合U-Boot调试、操作系统不同引导要求和产品发布等;

n 丰富的设备驱动源码,如串口、以太网、SDRAM、Flash、LCD、NVRAM、EEPROM、RTC、键盘等;

n 较为丰富的开发调试文档与强大的网络技术支持。

3.U-Boot主要功能

U-Boot可支持的主要功能列表。

n 系统引导:支持NFS挂载、RAMDISK(压缩或非压缩)形式的根文件系统。支持NFS挂载,并从Flash中引导压缩或非压缩系统内核。

n 基本辅助功能:强大的操作系统接口功能;可灵活设置、传递多个关键参数给操作系统,适合系统在不同开发阶段的调试要求与产品发布,尤其对Linux支持最为强劲;支持目标板环境参数多种存储方式,如Flash、NVRAM、EEPROM;CRC32校验,可校验Flash中内核、RAMDISK映像文件是否完好。

n 设备驱动:串口、SDRAM、Flash、以太网、LCD、NVRAM、EEPROM、键盘、USB、PCMCIA、PCI、RTC等驱动支持。

n 上电自检功能:SDRAM、Flash大小自动检测;SDRAM故障检测;CPU型号。

n 特殊功能:XIP内核引导。

5.2.3U-Boot源码导读1.U-Boot源码结构

U-Boot源码结构如图5.27所示。

图5.27U-Boot源码结构

n board:和一些已有开发板有关的代码,比如makefile和U-Boot.lds等都和具体开发板的硬件和地址分配有关。

n common:与体系结构无关的代码,用来实现各种命令的C程序。

n cpu:包含CPU相关代码,其中的子目录都是以U-BOOT所支持的CPU为名,比如有子目录arm926ejs、mips、mpc8260和nios等,每个特定的子目录中都包括cpu.c和interrupt.c,start.S等。其中cpu.c初始化CPU、设置指令Cache和数据Cache等;interrupt.c设置系统的各种中断和异常,比如快速中断、开关中断、时钟中断、软件中断、预取中止和未定义指令等;汇编代码文件start.S是U-BOOT启动时执行的第一个文件,它主要是设置系统堆栈和工作方式,为进入C程序奠定基础。

n disk:disk驱动的分区相关代码。

n doc:文档。

n drivers:通用设备驱动程序,比如各种网卡、支持CFI的Flash、串口和USB总线等。

n fs:支持文件系统的文件,U-BOOT现在支持cramfs、fat、fdos、jffs2和registerfs等。

n include:头文件,还有对各种硬件平台支持的汇编文件,系统的配置文件和对文件系统支持的文件。

n net:与网络有关的代码,BOOTP协议、TFTP协议、RARP协议和NFS文件系统的实现。

n lib_arm:与ARM体系结构相关的代码。

n tools:创建S-Record格式文件和U-BOOTimages的工具。

2.U-Boot重要代码

(1)cpu/arm920t/start.S

这是U-Boot的起始位置。在这个文件中设置了处理器的状态、初始化中断向量和内存时序等,从Flash中跳转到定位好的内存位置执行。

.globl_start(起始位置:中断向量设置)

_start:breset

ldrpc,_undefined_instruction

ldrpc,_software_interrupt

ldrpc,_prefetch_abort

ldrpc,_data_abort

ldrpc,_not_used

ldrpc,_irq

ldrpc,_fiq

_undefined_instruction:.wordundefined_instruction

_software_interrupt:.wordsoftware_interrupt

_prefetch_abort:.wordprefetch_abort

_data_abort:.worddata_abort

_not_used:.wordnot_used

_irq:.wordirq

_fiq:.wordfiq

_TEXT_BASE:(代码段起始位置)

.wordTEXT_BASE

.globl_armboot_start

_armboot_start:

.word_start

/*

*Thesearedefinedintheboard-specificlinkerscript.

*/

.globl_bss_start(BSS段起始位置)

_bss_start:

.word__bss_start

.globl_bss_end

_bss_end:

.word_end

reset:(执行入口)

/*

*setthecputoSVC32mode;使处理器进入特权模式

*/

mrsr0,cpsr

bicr0,r0,#0x1f

orrr0,r0,#0xd3

msrcpsr,r0

relocate:(代码的重置)/*relocateU-BoottoRAM*/

adrr0,_start/*r0<-currentpositionofcode*/

ldrr1,_TEXT_BASE/*testifwerunfromflashorRAM*/

cmpr0,r1/*don'trelocduringdebug*/

beqstack_setup

ldrr2,_armboot_start

ldrr3,_bss_start

subr2,r3,r2/*r2<-sizeofarmboot*/

addr2,r0,r2/*r2<-sourceendaddress*/

copy_loop:(拷贝过程)

ldmiar0!,{r3-r10}/*copyfromsourceaddress[r0]*/

stmiar1!,{r3-r10}/*copytotargetaddress[r1]*/

cmpr0,r2/*untilsourceendaddreee[r2]*/

blecopy_loop

/*Setupthestack;设置堆栈*/

stack_setup:

ldrr0,_TEXT_BASE/*upper128KiB:relocateduboot*/

subr0,r0,#CFG_MALLOC_LEN/*mallocarea*/

subr0,r0,#CFG_GBL_DATA_SIZE/*bdinfo*/

clear_bss:(清空BSS段)

ldrr0,_bss_start/*findstartofbsssegment*/

ldrr1,_bss_end/*stophere*/

movr2,#0x00000000/*clear*/

clbss_l:strr2,[r0]/*clearloop...*/

addr0,r0,#4

cmpr0,r1

bneclbss_l

ldrpc,_start_armboot

_start_armboot:.wordstart_armboot

(2)interrupts.c

这个文件是处理中断的,如打开和关闭中断等。

#ifdefCONFIG_USE_IRQ

/*enableIRQinterrupts;中断使能函数*/

voidenable_interrupts(void)

{

unsignedlongtemp;

__asm____volatile__("mrs%0,cpsrn"

"bic%0,%0,#0x80n"

"msrcpsr_c,%0"

:"=r"(temp)

:

:"memory");

}

/*

*disableIRQ/FIQinterrupts;中断屏蔽函数

*returnstrueifinterruptshadbeenenabledbeforewedisabledthem

*/

intdisable_interrupts(void)

{

unsignedlongold,temp;

__asm____volatile__("mrs%0,cpsrn"

"orr%1,%0,#0xc0n"

"msrcpsr_c,%1"

:"=r"(old),"=r"(temp)

:

:"memory");

return(old&0x80)==0;

}

#endif

voidshow_regs(structpt_regs*regs)

{

unsignedlongflags;

constchar*processor_modes[]={

"USER_26","FIQ_26","IRQ_26","SVC_26",

"UK4_26","UK5_26","UK6_26","UK7_26",

"UK8_26","UK9_26","UK10_26","UK11_26",

"UK12_26","UK13_26","UK14_26","UK15_26",

"USER_32","FIQ_32","IRQ_32","SVC_32",

"UK4_32","UK5_32","UK6_32","ABT_32",

"UK8_32","UK9_32","UK10_32","UND_32",

"UK12_32","UK13_32","UK14_32","SYS_32",

};

}

/*在U-Boot启动模式下,在原则上要禁止中断处理,所以如果发生中断,当作出错处理*/

voiddo_fiq(structpt_regs*pt_regs)

{

printf("fastinterruptrequestn");

show_regs(pt_regs);

bad_mode();

}

voiddo_irq(structpt_regs*pt_regs)

{

printf("interruptrequestn");

show_regs(pt_regs);

bad_mode();

}

(3)cpu.c

这个文件是对处理器进行操作,如下所示:

intcpu_init(void)

{

/*

*setupupstacksifnecessary;设置需要的堆栈

*/

#ifdefCONFIG_USE_IRQ

DECLARE_GLOBAL_DATA_PTR;

IRQ_STACK_START=_armboot_start-CFG_MALLOC_LEN-CFG_GBL_DATA_SIZE-4;

FIQ_STACK_START=IRQ_STACK_START-CONFIG_STACKSIZE_IRQ;

#endif

return0;

}

intcleanup_before_linux(void)/*准备加载linux*/

{

/*

*thisfunctioniscalledjustbeforewecalllinux

*itpreparestheprocessorforlinux

*

*weturnoffcachesetc...

*/

unsignedlongi;

disable_interrupts();

/*turnoffI/D-cache:关闭cache*/

asm("mrcp15,0,%0,c1,c0,0":"=r"(i));

i&=~(C1_DC|C1_IC);

asm("mcrp15,0,%0,c1,c0,0"::"r"(i));

/*flushI/D-cache*/

i=0;

asm("mcrp15,0,%0,c7,c7,0"::"r"(i));

return(0);

}

OUTPUT_ARCH(arm)

ENTRY(_start)

SECTIONS

{

.=0x00000000;

.=ALIGN(4);

.text:

{

cpu/arm920t/start.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=.;

}

(4)memsetup.S

这个文件是用于配置开发板参数的,如下所示:

/*memsetup.c*/

/*memorycontrolconfiguration*/

/*maker0relativethecurrentlocationsothatit*/

/*readsSMRDATAoutofFLASHratherthanmemory!*/

ldrr0,=SMRDATA

ldrr1,_TEXT_BASE

subr0,r0,r1

ldrr1,=BWSCON /*BusWidthStatusController*/

addr2,r0,#52

0:

ldrr3,[r0],#4

strr3,[r1],#4

cmpr2,r0

bne0b

/*everythingisfinenow*/

movpc,lr

.ltorg

5.2.4U-Boot移植主要步骤

(1)建立自己的开发板类型。

阅读makefile文件,在makefile文件中添加两行,如下所示:

fs2410_config:unconfig

@./mkconfig$(@:_config=)armarm920tfs2410

其中“arm”为表示处理器体系结构的种类,“arm920t”表示处理器体系结构的名称,“fs2410”为主板名称。

在board目录中建立fs2410目录,并将smdk2410目录中的内容(cp–asmdk2410/*fs2410)复制到该目录中。

n 在include/configs/目录下将smdk2410.h复制到(cpsmdk2410.hfs2410.h)。

n 修改ARM编译器的目录名及前缀(都要改成以“fs2410”开头)。

n 完成之后,可以测试配置。

$makefs2410_config;make

(2)修改程序链接地址。

在board/s3c2410中有一个config.mk文件,它是用于设置程序链接的起始地址,因为会在U-Boot中增加功能,所以留下6MB的空间,修改33F80000为33A00000。

为了以后能用U-Boot的“go”命令执行修改过的用loadb或tftp下载的U-Boot,需要在board/s3c2410的memsetup.S中标记符”0:”上加入5句:

movr3,pc

ldrr4,=0x3FFF0000

andr3,r3,r4(以上3句得到实际代码启动的内存地址)

aadr0,r0,r3(用go命令调试u-boot时,启动地址在RAM)

addr2,r2,r3(把初始化内存信息的地址,加上实际启动地址)

(3)将中断禁止的部分应该改为如下所示(/cpu/arm920t/start.S):

#ifdefined(CONFIG_S3C2410)

ldrr1,=0x7ff

ldrr0,=INTSUBMSK

strr1,[r0]

#endif

(4)因为在fs2410开发板启动时是直接从NandFlash加载代码,所以启动代码应该改成如下所示(/cpu/arm920t/start.S):

#ifdefCONFIG_S3C2410_NAND_BOOT@START

@resetNAND

movr1,#NAND_CTL_BASE

ldrr2,=0xf830@initialvalue

strr2,[r1,#oNFCONF]

ldrr2,[r1,#oNFCONF]

bicr2,r2,#0x800@enablechip

strr2,[r1,#oNFCONF]

movr2,#0xff@RESETcommand

strbr2,[r1,#oNFCMD]

movr3,#0@wait

nand1:

addr3,r3,#0x1

cmpr3,#0xa

bltnand1

nand2:

ldrr2,[r1,#oNFSTAT]@waitready

tstr2,#0x1

beqnand2

ldrr2,[r1,#oNFCONF]

orrr2,r2,#0x800@disablechip

strr2,[r1,#oNFCONF]

@getreadtocallCfunctions(fornand_read())

ldrsp,DW_STACK_START@setupstackpointer

movfp,#0@nopreviousframe,sofp=0

@copyU-BoottoRAM

ldrr0,=TEXT_BASE

movr1,#0x0

movr2,#0x20000

blnand_read_ll

tstr0,#0x0

beqok_nand_read

bad_nand_read:

loop2:bloop2@infiniteloop

ok_nand_read:

@verify

movr0,#0

ldrr1,=TEXT_BASE

movr2,#0x400@4bytes*1024=4K-bytes

go_next:

ldrr3,[r0],#4

ldrr4,[r1],#4

teqr3,r4

bnenotmatch

subsr2,r2,#4

beqstack_setup

bnego_next

notmatch:

loop3:bloop3@infiniteloop

#endif@CONFIG_S3C2410_NAND_BOOT@END

在“_start_armboot:.wordstart_armboot”后加入:

.align2

DW_STACK_START:.wordSTACK_BASE+STACK_SIZE-4

(5)修改内存配置(board/fs2410/lowlevel_init.S)。

#defineBWSCON0x48000000

#definePLD_BASE0x2C000000

#defineSDRAM_REG0x2C000106

/*BWSCON*/

#defineDW8 (0x0)

#defineDW16(0x1)

#defineDW32(0x2)

#defineWAIT(0x1<<2)

#defineUBLB(0x1<<3)

/*BANKSIZE*/

#defineBURST_EN(0x1<<7)

#defineB1_BWSCON(DW16+WAIT)

#defineB2_BWSCON(DW32)

#defineB3_BWSCON(DW32)

#defineB4_BWSCON(DW16+WAIT+UBLB)

#defineB5_BWSCON(DW8+UBLB)

#defineB6_BWSCON(DW32)

#defineB7_BWSCON(DW32)

/*BANK0CON*/

#defineB0_Tacs0x0/*0clk*/

#defineB0_Tcos0x1/*1clk*/

#defineB0_Tacc0x7/*14clk*/

#defineB0_Tcoh0x0/*0clk*/

#defineB0_Tah0x0/*0clk*/

#defineB0_Tacp0x0/*pagemodeisnotused*/

#defineB0_PMC0x0/*pagemodedisabled*/

/*BANK1CON*/

#defineB1_Tacs0x0/*0clk*/

#defineB1_Tcos0x1/*1clk*/

#defineB1_Tacc0x7/*14clk*/

#defineB1_Tcoh0x0/*0clk*/

#defineB1_Tah0x0/*0clk*/

#defineB1_Tacp0x0/*pagemodeisnotused*/

#defineB1_PMC0x0/*pagemodedisabled*/

……

/*REFRESHparameter*/

#defineREFEN0x1/*Refreshenable*/

#defineTREFMD0x0/*CBR(CASbeforeRAS)/Autorefresh*/

#defineTrp0x0/*2clk*/

#defineTrc0x3/*7clk*/

#defineTchr0x2/*3clk*/

#defineREFCNT1113/*period=15.6us,HCLK=60Mhz,(2048+1-15.6*60)*/

......

.word((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))

.word((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))

.word((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)

.word0x32

.word0x30

.word0x30

(6)加入NandFlash读函数(创建board/fs2410/nand_read.c文件)。

#include<config.h>

#define__REGb(x)(*(volatileunsignedchar*)(x))

#define__REGi(x)(*(volatileunsignedint*)(x))

#defineNF_BASE0x4e000000

#defineNFCONF__REGi(NF_BASE+0x0)

#defineNFCMD__REGb(NF_BASE+0x4)

#defineNFADDR__REGb(NF_BASE+0x8)

#defineNFDATA__REGb(NF_BASE+0xc)

#defineNFSTAT__REGb(NF_BASE+0x10)

#defineBUSY1

inlinevoidwait_idle(void)

{

Inti;

while(!(NFSTAT&BUSY))

{

for(i=0;i<10;i++);

}

}

/*lowlevelnandreadfunction*/

intnand_read_ll(unsignedchar*buf,unsignedlongstart_addr,intsize)

{

inti,j;

if((start_addr&NAND_BLOCK_MASK)||(size&NAND_BLOCK_MASK))

{

return-1;/*invalidalignment*/

}

/*chipEnable*/

NFCONF&=~0x800;

for(i=0;i<10;i++);

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

{

/*READ0*/

NFCMD=0;

/*WriteAddress*/

NFADDR=i&0xff;

NFADDR=(i>>9)&0xff;

NFADDR=(i>>17)&0xff;

NFADDR=(i>>25)&0xff;

wait_idle();

for(j=0;j<NAND_SECTOR_SIZE;j++,i++)

{

*buf=(NFDATA&0xff);

buf++;

}

}

/*chipDisable*/

NFCONF|=0x800;/*chipdisable*/

return0;

}

修改board/fs2410/makefile文件,以增加nand_read()函数。

OBJS:=fs2410.oflash.onand_read.o

(7)加入NandFlash的初始化函数(board/fs2410/fs2410.c)。

#if(CONFIG_COMMANDS&CFG_CMD_NAND)

typedefenum

{

NFCE_LOW,

NFCE_HIGH

}NFCE_STATE;

staticinlinevoidNF_Conf(u16conf)

{

S3C2410_NAND*constnand=S3C2410_GetBase_NAND();

nand->NFCONF=conf;

}

staticinlinevoidNF_Cmd(u8cmd)

{

S3C2410_NAND*constnand=S3C2410_GetBase_NAND();

nand->NFCMD=cmd;

}

staticinlinevoidNF_CmdW(u8cmd)

{

NF_Cmd(cmd);

udelay(1);

}

staticinlinevoidNF_Addr(u8addr)

{

S3C2410_NAND*constnand=S3C2410_GetBase_NAND();

nand->NFADDR=addr;

}

staticinlinevoidNF_SetCE(NFCE_STATEs)

{

S3C2410_NAND*constnand=S3C2410_GetBase_NAND();

switch(s)

{

caseNFCE_LOW:

nand->NFCONF&=~(1<<11);

break;

caseNFCE_HIGH:

nand->NFCONF|=(1<<11);

break;

}

}

staticinlinevoidNF_WaitRB(void)

{

S3C2410_NAND*constnand=S3C2410_GetBase_NAND();

while(!(nand->NFSTAT&(1<<0)));

}

staticinlinevoidNF_Write(u8data)

{

S3C2410_NAND*constnand=S3C2410_GetBase_NAND();

nand->NFDATA=data;

}

staticinlineu8NF_Read(void)

{

S3C2410_NAND*constnand=S3C2410_GetBase_NAND();

return(nand->NFDATA);

}

staticinlinevoidNF_Init_ECC(void)

{

S3C2410_NAND*constnand=S3C2410_GetBase_NAND();

nand->NFCONF|=(1<<12);

}

staticinlineu32NF_Read_ECC(void)

{

S3C2410_NAND*constnand=S3C2410_GetBase_NAND();

return(nand->NFECC);

}

#endif

/*

*NANDflashinitialization.

*/

#if(CONFIG_COMMANDS&CFG_CMD_NAND)

externulongnand_probe(ulongphysadr);

staticinlinevoidNF_Reset(void)

{

inti;

NF_SetCE(NFCE_LOW);

NF_Cmd(0xFF);/*resetcommand*/

for(i=0;i<10;i++);/*tWB=100ns.*/

NF_WaitRB();/*wait200~500us;*/

NF_SetCE(NFCE_HIGH);

}

staticinlinevoidNF_Init(void)

{

#defineTACLS0

#defineTWRPH04

#defineTWRPH12

NF_Conf((1<<15)|(0<<14)|(0<<13)|(1<<12)

|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0));

/*1111,1xxx,rxxx,rxxx*/

/*En512B4stepECCRnFCE=HtACLStWRPH0tWRPH1*/

NF_Reset();

}

voidnand_init(void)

{

S3C2410_NAND*constnand=S3C2410_GetBase_NAND();

NF_Init();

#ifdefDEBUG

printf("NANDflashprobingat0x%.8lXn",(ulong)nand);

#endif

printf("%4luMBn",nand_probe((ulong)nand)>>20);

}

#endif

(8)修改GPIO配置(board/fs2410/fs2410.c)。

/*setuptheI/Oports*/

gpio->GPACON=0x007FFFFF;

gpio->GPBCON=0x002AAAAA;

gpio->GPBUP=0x000002BF;

gpio->GPCCON=0xAAAAAAAA;

gpio->GPCUP=0x0000FFFF;

gpio->GPDCON=0xAAAAAAAA;

gpio->GPDUP=0x0000FFFF;

gpio->GPECON=0xAAAAAAAA;

gpio->GPEUP=0x000037F7;

gpio->GPFCON=0x00000000;

gpio->GPFUP=0x00000000;

gpio->GPGCON=0xFFEAFF5A;

gpio->GPGUP=0x0000F0DC;

gpio->GPHCON=0x0018AAAA;

gpio->GPHDAT=0x000001FF;

gpio->GPHUP=0x00000656

(9)提供nandflash相关宏定义(include/configs/fs2410.h),具体参考源码。

(10)加入NandFlash设备(include/linux/mtd/nand_ids.h)

staticstructnand_flash_devnand_flash_ids[]=

{

......

{"SamsungKM29N16000",NAND_MFR_SAMSUNG,0x64,21,1,2,0x1000,0},

{"SamsungK9F1208U0M",NAND_MFR_SAMSUNG,0x76,26,0,3,0x4000,0},

{"Samsungunknown4Mb",NAND_MFR_SAMSUNG,0x6b,22,0,2,0x2000,0},

......

{NULL,}

};

(11)设置NandFlash环境(common/env_nand.c)

intnand_legacy_rw(structnand_chip*nand,intcmd,

size_tstart,size_tlen,

size_t*retlen,u_char*buf);

externstructnand_chipnand_dev_desc[CFG_MAX_NAND_DEVICE];

externintnand_legacy_erase(structnand_chip*nand,

size_tofs,size_tlen,intclean);

/*infoforNANDchips,definedindrivers/nand/nand.c*/

externnand_info_tnand_info[CFG_MAX_NAND_DEVICE];

......

#else/*!CFG_ENV_OFFSET_REDUND*/

intsaveenv(void)

{

ulongtotal;

intret=0;

puts("ErasingNand...");

if(nand_legacy_erase(nand_dev_desc+0,

CFG_ENV_OFFSET,CFG_ENV_SIZE,0))

{

return1;

}

puts("WritingtoNand...");

total=CFG_ENV_SIZE;

ret=nand_legacy_rw(nand_dev_desc+0,0x00|0x02,CFG_ENV_OFFSET,

CFG_ENV_SIZE,&total,(u_char*)env_ptr);

if(ret||total!=CFG_ENV_SIZE)

{

return1;

}

puts("donen");

returnret;

......

#else/*!CFG_ENV_OFFSET_REDUND*/

voidenv_relocate_spec(void)

{

#if!defined(ENV_IS_EMBEDDED)

ulongtotal;

intret;

total=CFG_ENV_SIZE;

ret=nand_legacy_rw(nand_dev_desc+0,0x01|0x02,CFG_ENV_OFFSET,

CFG_ENV_SIZE,&total,(u_char*)env_ptr);

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭