[ZLG-ARM] 基于Atmel at91rm9200的armlinux的bootloader启动代码分析

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

又学到了新的知识

  
您需要登录后才可以回帖 登录 | 注册

本版积分规则

36

主题

38

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部

36

主题

38

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部