Author : balancesli<br />mail : balancesli@thizlinux.com.cn<br /><br /> 前阶段做了一次基于at91rm9200引导部分的技术分析,主要采用了u-boot,这里只面向使用at91rm9200板子的的朋友做个简单的推敲,希望起到抛砖引玉的作用.<br /><br />关键词 : <br />u-boot: 一个开源的面向多个目标平台(ppc, mips, arm, x86)的bootloader.<br />at91rm9200 : Atmel 公司生产的基于arm9核的Soc处理器.<br /><br />以下先给出at91rm9200引导流程图<br /><br />Boot program Flow Diagram <br /><br />Device Setup<br />|<br />|<br />Boot SPI DataFlash Boot --> Download from DataFlash --> run<br />|<br />| <br />TWI EEPROM Boot --> Download from EEPROM --> run<br />|<br />|<br />Parallel Boot --> Download from 8-bit Device --> <br />| <br />| Xmodem protocol <br />| |---DBGU Serial Download ---------------------> run<br />|____|<br />| DFU protocol<br />|-----USB download -----------------------> run <br /><br />在这里我主要介绍通过片内引导和片外引导, 片内引导主要采用串口下载并引导u-boot,并完成程序被烧写到Flash上, <br />然后就可以通过跳线的方式从片外引导执行已经烧写到片外Flash上的引导程序(bootloader).<br /><br />这里要提及的是at91rm9200内部本身有128k的片内rom,其固化了一个bootloader和uploader, 用来支持程序的<br />下载和引导,而且其内部固化的程序提供了很多内部服务接口(Internel Service)供我们来使用,例如Xmodem,Tempo<br />DataFlash, CRC, Sine服务接口,这样我们就可以利用它所提供的Service interface API完成程序的下载。<br />这里主要介绍Xmodem接口服务。<br /><br />at91rm9200内部固化的代码在设计上采用了面向对象的设计方法,如下:<br /><br /><br />typedef struct _AT91S_Service <br />{<br />char data;<br />char (*MainMethod)();<br />char (*ChildMethod)();<br />}AT91S_Service, *AT91PS_Service;<br /><br />char AT91F_MainMethod()<br />{<br /><br />}<br />char AT91F_ChildMethod()<br />{<br /><br />}<br /><br />/*init the Service */<br />AT91PS_Service AT91F_OpenDevice(AT91PS_Service pService)<br />{<br />pService->data = 0;<br />pService->MainMethod = AT91F_MainMethod;<br />pService->ChildMethod = AT91F_ChildMethod;<br />}<br /><br />//使用方法如下<br />AT91S_Service service;<br />AT91PS_Service pService = AT91F_OpenDevice(&service);<br />pService->AT91F_MainMethmod();<br />.....<br /><br />通过如上代码片断可以看出它采用了类似面向对象的设计方法。<br />其实如果各位朋友接触过的话或者看过这本书的话,应该很容易便接受它。<br />下面以Xmodem服务为例子介绍:<br /><br /><br />at91rm9200内部提供的服务包含了几个服务对象, 这些对象在片内启动xmodem协议Host端和Targe端通讯时会用到.<br /><br /><br />typedef struct _AT91S_RomBoot <br />{<br />const unsigned int version;<br />// Peripheral descriptors<br />const AT91S_MEMCDesc MEMC_DESC;<br />const AT91S_STDesc SYSTIMER_DESC;<br />const AT91S_Pio2Desc PIOA_DESC;<br />const AT91S_Pio2Desc PIOB_DESC;<br />const AT91S_USART2Desc DBGU_DESC;<br />const AT91S_USART2Desc USART0_DESC;<br />const AT91S_USART2Desc USART1_DESC;<br />const AT91S_USART2Desc USART2_DESC;<br />const AT91S_USART2Desc USART3_DESC;<br />const AT91S_TWIDesc TWI_DESC;<br />const AT91S_SPIDesc SPI_DESC;<br /><br />// Objects entry<br />const AT91PF_OpenPipe OpenPipe;<br />const AT91PF_OpenSBuffer OpenSBuffer;<br />const AT91PF_OpenSvcUdp OpenSvcUdp;<br />const AT91PF_OpenSvcXmodem OpenSvcXmodem;<br />const AT91PF_OpenCtlTempo OpenCtlTempo;<br />const AT91PF_OpenDfuDesc OpenDfuDesc;<br />const AT91PF_OpenUsbDesc OpenUsbDesc;<br />const AT91PF_OpenSvcDataFlash OpenSvcDataFlash;<br />const AT91PF_SVC_CRC16 CRC16;<br />const AT91PF_SVC_CRCCCITT CRCCCITT;<br />const AT91PF_SVC_CRCHDLC CRCHDLC;<br />const AT91PF_SVC_CRC32 CRC32;<br />// Array<br />const AT91PS_SVC_CRC_BIT_REV Bit_Reverse_Array;<br />const AT91PS_SINE_TAB SineTab;<br />const AT91PF_Sinus Sine;<br />} AT91S_RomBoot;<br /><br />//AT91S_Pipe<br />typedef struct _AT91S_Pipe<br />{<br />// A pipe is linked with a peripheral and a buffer<br />AT91PS_SvcComm pSvcComm;<br />AT91PS_Buffer pBuffer;<br /><br />// Callback functions with their arguments<br />void (*WriteCallback) (AT91S_PipeStatus, void *);<br />void (*ReadCallback) (AT91S_PipeStatus, void *);<br />void *pPrivateReadData;<br />void *pPrivateWriteData;<br /><br />// Pipe methods<br />AT91S_PipeStatus (*Write) (<br />struct _AT91S_Pipe *pPipe,<br />char const * pData,<br />unsigned int size,<br />void (*callback) (AT91S_PipeStatus, void *),<br />void *privateData<br />);<br /><br />AT91S_PipeStatus (*Read) (<br />struct _AT91S_Pipe *pPipe,<br />char *pData,<br />unsigned int size,<br />void (*callback) (AT91S_PipeStatus, void *),<br />void *privateData<br />);<br /><br />AT91S_PipeStatus (*AbortWrite)(struct _AT91S_Pipe *pPipe);<br />AT91S_PipeStatus (*AbortRead)(struct _AT91S_Pipe *pPipe);<br />AT91S_PipeStatus (*AbortRead)(struct _AT91S_Pipe *pPipe);<br />AT91S_PipeStatus (*Reset)(struct _AT91S_Pipe *pPipe);<br />char (*IsWritten)(struct _AT91S_Pipe *pPipe, char const *pVoid);<br />char (*IsReceived) (struct _AT91S_Pipe *pPipe, char const *pVoid);<br />} AT91S_Pipe;<br /><br />//AT91S_Buff<br />typedef struct _AT91S_SBuffer<br />{<br />AT91S_Buffer parent;<br />char *pRdBuffer;<br />char const *pWrBuffer;<br />unsigned int szRdBuffer;<br />unsigned int szWrBuffer;<br />unsigned int stRdBuffer;<br />unsigned int stWrBuffer;<br />} AT91S_SBuffer;<br /><br />// AT91S_SvcTempo<br />typedef struct _AT91S_SvcTempo<br />{<br /><br />// Methods:<br />AT91S_TempoStatus (*Start) (<br />struct _AT91S_SvcTempo *pSvc,<br />unsigned int timeout,<br />unsigned int reload,<br />void (*callback) (AT91S_TempoStatus, void *),<br />void *pData);<br />AT91S_TempoStatus (*Stop) (struct _AT91S_SvcTempo *pSvc);<br /><br />struct _AT91S_SvcTempo *pPreviousTempo;<br />struct _AT91S_SvcTempo *pNextTempo;<br /><br />// Data<br />unsigned int TickTempo; //* timeout value<br />unsigned int ReloadTempo;//* Reload value for periodic execution<br />void (*TempoCallback)(AT91S_TempoStatus, void *);<br />void *pPrivateData;<br />AT91E_SvcTempo flag;<br />} AT91S_SvcTempo;<br /><br />// AT91S_CtrlTempo<br />typedef struct _AT91S_CtlTempo<br />{<br />// Members:<br /><br />// Start and stop for Timer hardware<br />AT91S_TempoStatus (*CtlTempoStart) (void *pTimer);<br />AT91S_TempoStatus (*CtlTempoStop) (void *pTimer);<br /><br />// Start and stop for Tempo service<br />AT91S_TempoStatus (*SvcTempoStart) (<br />struct _AT91S_SvcTempo *pSvc,<br />unsigned int timeout,<br />unsigned int reload,<br />void (*callback) (AT91S_TempoStatus, void *),<br />void *pData);<br />AT91S_TempoStatus (*SvcTempoStop) (struct _AT91S_SvcTempo *pSvc);<br />AT91S_TempoStatus (*CtlTempoSetTime)(struct _AT91S_CtlTempo *pCtrl, unsigned int NewTime);<br />AT91S_TempoStatus (*CtlTempoGetTime)(struct _AT91S_CtlTempo *pCtrl);<br />AT91S_TempoStatus (*CtlTempoIsStart)(struct _AT91S_CtlTempo *pCtrl);<br />AT91S_TempoStatus (*CtlTempoCreate) (struct _AT91S_CtlTempo *pCtrl,struct _AT91S_SvcTempo *pTempo);<br />AT91S_TempoStatus (*CtlTempoRemove) (struct _AT91S_CtlTempo *pCtrl,struct _AT91S_SvcTempo *pTempo);<br />AT91S_TempoStatus (*CtlTempoTick) (struct _AT91S_CtlTempo *pCtrl);<br /><br />// Data:<br /><br />void *pPrivateData; // Pointer to devived class<br />void const *pTimer; // hardware<br />AT91PS_SvcTempo pFirstTempo;<br />AT91PS_SvcTempo pNewTempo;<br />} AT91S_CtlTempo;<br /><br /><br /><br />//以下代码是上面几个对象的使用范例,通过这样就可以完成Host端和Targe端之间的xmodem通讯,并可以下载代码了。<br /><br />AT91S_RomBoot const *pAT91;<br />AT91S_SBuffer sXmBuffer;<br />AT91S_SvcXmodem svcXmodem;<br />AT91S_Pipe xmodemPipe;<br />AT91S_CtlTempo ctlTempo;<br /><br />AT91PS_Buffer pXmBuffer;<br />AT91PS_SvcComm pSvcXmodem;<br />unsigned int SizeDownloaded; <br /><br />/* Init of ROM services structure */<br />pAT91 = AT91C_ROM_BOOT_ADDRESS;//这里取得内部ROM服务的入口地址<br /><br />/* Tempo Initialization */<br />pAT91->OpenCtlTempo(&ctlTempo, (void *) &(pAT91->SYSTIMER_DESC));<br />ctlTempo.CtlTempoStart((void *) &(pAT91->SYSTIMER_DESC));<br /><br />/* Xmodem Initialization */<br />pXmBuffer = pAT91->OpenSBuffer(&sXmBuffer);<br />pSvcXmodem = pAT91->OpenSvcXmodem(&svcXmodem, (AT91PS_USART)AT91C_BASE_DBGU, &ctlTempo);<br />pAT91->OpenPipe(&xmodemPipe, pSvcXmodem, pXmBuffer);<br />xmodemPipe.Read(&xmodemPipe, (char *)AT91C_UBOOT_BASE_ADDRESS, AT91C_UBOOT_MAXSIZE, <br />AT91F_XmodemProtocol, 0); <br />while(XmodemComplete !=1);<br /><br />//上面部分主要针对at91rm9200片内启动时我们可以使用的片内接口服务介绍,玩H9200的朋友可以参考一下便知道缘由。<br /><br />下面主要介绍at91rm9200片外启动时所使用的bootloader-->u-boot<br /><br />一. bootloader <br /><br />BootLoader(引导装载程序)是嵌入式系统软件开发的非常重要的环节,它把操作系统和硬件平台衔接在一起,<br />是跟硬件体系密切相关的。<br /><br />1.1 典型的嵌入式系统软件部分Image memory layout : bootloader , bootloader param, kernel, rootfs.<br /><br />1.2 引导模式 : 1. bootstrap或download<br />2. autoboot<br />1.3 u-boot简介 :<br />u-boot是由Wolfgang Denk开发,它支持(mips, ppc, arm, x86)等目标体系,<br />可以在http://sourceforge.net 上下载获得源码,<br /><br />1.4 u-boot源代码目录结构<br /><br />board:开发板相关的源码,不同的板子对应一个子目录,内部放着主板相关代码。<br /><br />at91rm9200dk/at91rm9200.c, config.mk, Makefile, flash.c ,u-boot.lds等都和具体开发板的硬件和地址分配有关。<br /><br />common:与体系结构无关的代码文件,实现了u-boot所有命令,<br />其中内置了一个shell脚本解释器(hush.c, a prototype Bourne shell grammar parser), busybox中也使用了它.<br /><br />cpu:与cpu相关代码文件,其中的所有子目录都是以u-boot所支持的cpu命名.<br /><br />at91rm9200/at45.c, at91rm9200_ether.c, cpu.c, interrupts.c serial.c, start.S, config.mk, Makefile等.<br />其中cpu.c负责初始化CPU、设置指令Cache和数据Cache等;<br /><br />interrupt.c负责设置系统的各种中断和异常,比如快速中断、开关中断、时钟中断、软件中断、<br />预取中止和未定义指令等;<br /><br />start.S负责u-boot启动时执行的第一个文件,它主要是设置系统堆栈和工作方式,为跳转到C程序入口点.<br /><br />disk:设备分区处理代码。<br /><br />doc:u-boot相关文档。<br /><br />drivers:u-boot所支持的设备驱动代码, 网卡、支持CFI的Flash、串口和USB总线等。<br /><br />fs: u-boot所支持支持文件系统访问存取代码, 如jffs2.<br /><br />include:u-boot head文件,主要是与各种硬件平台相关的头文件,<br />如include/asm-arm/arch-at91rm9200/, include/asm-arm/proc-armv<br /><br />net:与网络有关的代码,BOOTP协议、TFTP协议、RARP协议代码实现.<br /><br />lib_arm:与arm体系相关的代码。(这里我们主要面向的是ARM体系,所以该目录是我们主要研究对象)<br /><br />tools:编译后会生成mkimage工具,用来对生成的raw bin文件加入u-boot特定的image_header.<br /><br />1.5 u-boot的功能介绍<br /><br /> u-boot支持SCC/FEC以太网、OOTP/TFTP引导、IP和MAC的功能.<br /><br />读写Flash、DOC、IDE、IIC、EEROM、RTC<br /><br />支持串行口kermit和S-record下载代码, 并直接从串口下载并执行。<br /><br />在我们生成的内核镜像时,要做如下处理.<br />1. arm-linux-objcopy -O binary -R.note -R.comment -S vmlinux linux.bin <br />2. gzip -9 linux.bin<br />3. mkimage -A arm -O linux -T kernel -C gzip -a 0xc0008000 -e 0xc0008000 -n <br />'Linux-2.4.19-rmk7” -d linux.bin.gz uImage<br /><br />即在Linux内核镜像vmLinux前添加了一个特殊的头,这个头在include/image.h中定义,<br />typedef struct image_header <br />{<br />uint32_t ih_magic; /* Image Header Magic Number */<br />uint32_t ih_hcrc; /* Image Header CRC Checksum */<br />uint32_t ih_time; /* Image Creation Timestamp */<br />uint32_t ih_size; /* Image Data Size */<br />uint32_t ih_load; /* Data Load Address */<br />uint32_t ih_ep; /* Entry Point Address */<br />uint32_t ih_dcrc; /* Image Data CRC Checksum */<br />uint8_t ih_os; /* Operating System */<br />uint8_t ih_arch; /* CPU architecture */<br />uint8_t ih_type; /* Image Type */<br />uint8_t ih_comp; /* Compression Type */<br />uint8_t ih_name[IH_NMLEN]; /* Image Name */<br />} image_header_t;<br /><br />当u-boot引导时会对这个文件头进行CRC校验,如果正确,才会跳到内核执行.<br /><br />如果u-boot启动以后会出现<br />u-boot><br />敲入help, 会出现大量的命令提示,Monitor command<br />go - start application at address 'addr'<br />run - run commands in an environment variable<br />bootm - boot application image from memory<br />bootp - boot image via network using BootP/TFTP protocol<br />tftpboot- boot image via network using TFTP protocol<br />and env variables 'ipaddr' and 'serverip'<br />(and eventually 'gatewayip')<br />rarpboot- boot image via network using RARP/TFTP protocol<br />diskboot- boot from IDE devicebootd - boot default, i.e., run 'bootcmd'<br />loads - load S-Record file over serial line<br />loadb - load binary file over serial line (kermit mode)<br />md - memory display<br />mm - memory modify (auto-incrementing)<br />nm - memory modify (constant address)<br />mw - memory write (fill) <br />cp - memory copy<br />cmp - memory compare<br />crc32 - checksum calculation<br />imd - i2c memory display<br />imm - i2c memory modify (auto-incrementing)<br />inm - i2c memory modify (constant address)<br />imw - i2c memory write (fill)<br />icrc32 - i2c checksum calculation<br />iprobe - probe to discover valid I2C chip addresses<br />iloop - infinite loop on address range<br />isdram - print SDRAM configuration information<br />sspi - SPI utility commands<br />base - print or set address offset<br />printenv- print environment variables<br />setenv - set environment variables<br />saveenv - save environment variables to persistent storage<br />protect - enable or disable FLASH write protection<br />erase - erase FLASH memory<br />flinfo - print FLASH memory information<br />bdinfo - print Board Info structure<br />iminfo - print header information for application image<br />coninfo - print console devices and informations<br />ide - IDE sub-system<br />loop - infinite loop on address range<br />mtest - simple RAM test<br />icache - enable or disable instruction cache<br />dcache - enable or disable data cache<br />reset - Perform RESET of the CPU<br />echo - echo args to console<br />version - print monitor version<br />help - print online help<br />? - alias for 'help'<br /><br />u-boot支持大量的命令可用, 这里就不作介绍,大家有兴趣可以看看u-boot 的README文档<br />3.3 对u-boot-1.0.0的修改和移植<br /><br />1.6 关于u-boot的移植如下,由于u-boot的软件设计体系非常清晰,它的移植工作并不复杂,<br />相信各位的代码阅读功力不错的话,参照如下就可以完成。<br /><br />If the system board that you have is not listed, then you will need<br />to port U-Boot to your hardware platform. To do this, follow these<br />steps:<br /><br />1. Add a new configuration option for your board to the toplevel<br />'Makefile' and to the 'MAKEALL' script, using the existing<br />entries as examples. Note that here and at many other places<br />boards and other names are listed in alphabetical sort order. Please<br />keep this order.<br /><br />2. Create a new directory to hold your board specific code. Add any<br />files you need. In your board directory, you will need at least<br />the 'Makefile', a '.c', 'flash.c' and 'u-boot.lds'.<br /><br />3. Create a new configuration file 'include/configs/.h' for<br />your board<br /><br />4. If you're porting U-Boot to a new CPU, then also create a new<br />directory to hold your CPU specific code. Add any files you need.<br /><br />5. Run 'make _config' with your new name.<br /><br />6. Type 'make', and you should get a working 'u-boot.srec' file<br /><br />7. Debug and solve any problems that might arise.<br />[Of course, this last step is much harder than it sounds.]<br /><br />为了使u-boot-1.0.0支持新的开发板,一种简便的做法是在u-boot已经支持的开发板中参考选择一种较接近板的进行修改,<br />幸运的是在u-boot-1.0.0中已经有了at91rm9200的支持。<br /><br />1.7 与at91rm9200相关的u-boot代码<br /><br />在include/configs/at91rm9200dk.h 它包括开发板的CPU、系统时钟、RAM、Flash系统及其它相关的配置信息。<br />在include/asm-arm/AT91RM9200.h, 该文件描述了H9200寄存器的结构及若干宏定义。<br />具体内容要参考相关处理器手册。<br />在cpu/at91rm9200/目录下别为cpu.c、interrupts.c和serial.c等文件.<br />在board/at91rm9200dk/目录下分别为flash.c、at91rm9200dk.c, config.mk, Makefile,u-boot.lds<br /><br />flash.c : u-boot读、写和删除Flash设备的源代码文件。由于不同开发板中Flash存储器的种类各不相同,<br />所以,修改flash.c时需参考相应的Flash芯片手册。它包括如下几个函数:<br />unsigned long flash_init (void ),Flash初始化;<br />void flash_print_info (flash_info_t *info),打印Flash信息;<br />int flash_erase (flash_info_t *info, int s_first, int s_last),Flash擦除;<br />volatile static int write_dword (flash_info_t *info, ulong dest, ulong data),Flash写入;<br />int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt),从内存复制数据。<br /><br />u-boot.lds :linker scripte, 设置u-boot中各个目标文件的连接地址.<br /><br />网口设备控制程序<br /><br /> 在drivers/目录中网口设备控制程序cs8900, bcm570x等, 还可以添加其他网卡驱动<br />int eth_init (bd_t *bd) : 初始化网络设备;<br />void eth_halt (void) : 关闭网络设备;<br />int eth_send (volatile void *packet,int len) : 发送数据包;<br />int eth_rx (void) : 接收数据包。<br /><br />Makefile<br /><br /> 在u-boot-1.0.0/Makefile中 <br />at91rm9200dk_config : unconfig<br />./mkconfig $(@:_config=) arm at91rm9200 at91rm9200dk<br /><br />1.8 编译u-boot<br /><br /> make at91rm9200_config<br />Configuring for at91rm9200 board...<br />make all<br />生成三个文件:u-boot.bin, u-boot, u-boot.srec<br /><br />u-boot.bin is a raw binary image<br />u-boot is an image in ELF binary format<br />u-boot.srec is in Motorola S-Record format (objcopy -O srec -R.note -R.comment -S [inputfile] [outfile]<br /><br />以上工作完成我们可以通过串口将u-boot.bin下载到主板的SDRAM中,它会自动执行, 并出现uboot><br />这里我们可以通过串口把boot.bin, u-boot.bin.gz下载到主板,再用u-boot的提供的写flash功能分别<br />把boot.bin, u-boot.bin.gz写入到flash中,完成以上工作后,对主板跳线选择片外启动,<br />板子复位后会自动启动u-boot.<br /><br />二.loader.bin, boot.bin, u-boot.bin代码执行流分析.<br /><br />以上三个文件时at91rm9200启动所需要的三个bin,他们的实现代码并不难。<br />如果是你是采用at91rm9200的评估版,应该能得到其源码。<br /><br />2.1 loader.bin 执行流程,这个文件主要在片内启动从串口下载代码时会用到<br />loader/entry.S init cpu<br />b main ---> crt0.S<br />--> copydata --> clearbss --> b boot<br />main.c --> boot --><br />/*Get internel rom service address*/<br />/* Init of ROM services structure */ <br />pAT91 = AT91C_ROM_BOOT_ADDRESS;<br /><br />/* Xmodem Initialization */<br />--> pAT91->OpenSBuffer<br />--> pAT91->OpenSvcXmodem<br />/* System Timer initialization */<br />---> AT91F_AIC_ConfigureIt<br />/* Enable ST interrupt */<br />AT91F_AIC_EnableIt<br />AT91F_DBGU_Printk('XMODEM: Download U-BOOT ');<br /><br />Jump.S<br />// Jump to Uboot BaseAddr exec<br />Jump((unsigned int)AT91C_UBOOT_BASE_ADDRESS) <br /><br />2.2 boot.bin执行流程 该文件会在从片内启动时被下载到板子上,以后还会被烧写到片外Flash中,以便在片外启动时<br />用它来引导并解压u-boot.gz,并跳转到u-boot来执行。<br />boot/entry.S<br />b main --> crt0.S --> copydata --> clearbss --> b boot<br /><br />T91F_DBGU_Printk(' ');<br />AT91F_DBGU_Printk('************************************** ');<br />AT91F_DBGU_Printk('** Welcome to at91rm9200 ** ');<br />AT91F_DBGU_Printk('************************************** ');<br /><br />boot/misc.s /* unzip uboot.bin.gz */<br />----> decompress_image(SRC,DST,LEN) --> gunzip <br /><br />//jump to ubootBaseAddr exec 这里跳转到解压u-boot.gz的地址处直接开始执行u-boot<br />asm('mov pc,%0' : : 'r' (DST));<br /><br />2.3 uboot.bin执行流程<br />u-boot/cpu/at91rm9200/start.S <br />start --->reset <br />---> copyex ---> cpu_init_crit <br />---> /* set up the stack */ --> start_armboot<br />u-boot/lib_arm/board.c<br /><br />init_fnc_t *init_sequence[] = {<br />cpu_init, /* basic cpu dependent setup */<br />board_init, /* basic board dependent setup */<br />interrupt_init, /* set up exceptions */<br />env_init, /* initialize environment */<br />init_baudrate, /* initialze baudrate settings */<br />serial_init, /* serial communications setup */<br />console_init_f, /* stage 1 init of console */<br />display_banner, /* say that we are here */<br />dram_init, /* configure available RAM banks */<br />display_dram_config,<br />checkboard,<br />NULL,<br />};<br /><br />---> start_armboot ---> call init_sequence<br />---> flash_init --> display_flash_config <br />---> nand_init ---> AT91F_DataflashInit <br />---> dataflash_print_info --> env_relocate<br />---> drv_vfd_init --> devices_init --> jumptable_init<br />---> console_init_r --> misc_init_r --> enable_interrupts<br />---> cs8900_get_enetaddr --> board_post_init --> <br /><br />u-boot/common/main.c<br />for (;;) <br />{ /* shell parser */<br />main_loop () --> u_boot_hush_start --> readline<br />--> abortboot <br />-->printf('Hit any key to stop autoboot: %2d ', bootdelay);<br />}<br /><br />以上是at91rm9200启动并进入u-boot的执行流分析。后面u-boot还会将uImage解压到特定的位置并开始执行内核代码。<br /><br />三. 综述<br /><br /> 总之, 不同厂商的出的Soc片子在启动方式大都提供片内和片外启动两种方式,一般都是在片内固化一段小程序<br />方便于程序开发而已,在其DataSheet文档中有详尽的描述。若是对at92rm9200有兴趣或玩过的朋友,可以与我共同探讨相互学习<br /> |
|