Bootloader(Vivi)源代码分析2.doc_第1页
Bootloader(Vivi)源代码分析2.doc_第2页
Bootloader(Vivi)源代码分析2.doc_第3页
Bootloader(Vivi)源代码分析2.doc_第4页
Bootloader(Vivi)源代码分析2.doc_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Bootloader(Vivi)源代码分析 -基于S3C2410处理器1.3 vivi代码分析vivi的代码包括arch,init,lib,drivers和include等几个目录,共200多条文件。Vivi主要包括下面几个目录:arch:此目录包括了所有vivi支持的目标板的子目录,例如s3c2410目录。drivers:其中包括了引导内核需要的设备的驱动程序(MTD和串口)。MTD目录下分map、nand和nor三个目录。init:这个目录只有main.c和version.c两个文件。和普通的C程序一样,vivi将从main函数开始执行。lib:一些平台公共的接口代码,比如time.c里的udelay()和mdelay()。include:头文件的公共目录,其中的s3c2410.h定义了这块处理器的一些寄存器。Platform/smdk2410.h定义了与开发板相关的资源配置参数,我们往往只需要修改这个文件就可以配置目标板的参数,如波特率、引导参数、物理内存映射等。1.4 vivi的运行vivi的运行也可以分为两个阶段:1.4.1 vivi的第一阶段完成含依赖于CPU的体系结构硬件初始化的代码,包括禁止中断、初始化串口、复制自身到RAM等。相关代码集中在head.S(viviarchs3c2410目录下).Head.S:#include config.h#include linkage.h#include machine.h Start of executable code ENTRY(_start)ENTRY(ResetEntryPoint) Exception vector table (physical address = 0x00000000) ;异常向量表物理地址 0x00: Reset;复位bReset 0x04: Undefined instruction exception;未定义的指令异常UndefEntryPoint:bHandleUndef 0x08: Software interrupt exception;软件中断异常SWIEntryPoint:bHandleSWI 0x0c: Prefetch Abort (Instruction Fetch Memory Abort);内存操作异常PrefetchAbortEnteryPoint:bHandlePrefetchAbort 0x10: Data Access Memory Abort;数据异常DataAbortEntryPoint:bHandleDataAbort 0x14: Not used;未使用NotUsedEntryPoint:bHandleNotUsed 0x18: IRQ(Interrupt Request) exception;慢速中断处理IRQEntryPoint:bHandleIRQ 0x1c: FIQ(Fast Interrupt Request) exception;快速中断处理FIQEntryPoint:bHandleFIQ VIVI magics 0x20: magic number so we can verify that we only put .long 0 0x24:.long 0 0x28: where this vivi was linked, so we can put it in memory in the right place.long _start 0x2C: this contains the platform, cpu and machine id.long ARCHITECTURE_MAGIC 0x30: vivi capabilities .long 0#ifdef CONFIG_PM;vivi考虑不需要使用电源管理 0x34:bSleepRamProc#endif#ifdef CONFIG_TEST 0x38:bhmi#endif Start VIVI headReset: disable watch dog timer;禁止看门狗计时器movr1, #0x53000000;WTCON寄存器地址是0x53000000,清0movr2, #0x0strr2, r1#ifdef CONFIG_S3C2410_MPORT3;不符合条件,跳到下面的关中断/* 在/vivi/include/autoconf.h中#undef CONFIG_S3C2410_MPORT3*/movr1, #0x56000000;GPACON寄存器地址是0x56000000movr2, #0x00000005strr2, r1, #0x70;配置GPHCON寄存器mov r2, #0x00000001strr2, r1, #0x78;配置GPHUP寄存器movr2, #0x00000001str r2, r1, #0x74;配置GPHDAT寄存器#endif disable all interrupts;禁止全部中断movr1, #INT_CTL_BASEmovr2, #0xffffffffstrr2, r1, #oINTMSK;掩码关闭所有中断ldrr2, =0x7ffstrr2, r1, #oINTSUBMSK initialise system clocks;初始化系统时钟movr1, #CLK_CTL_BASEmvnr2, #0xff000000strr2, r1, #oLOCKTIMEldrr2, mpll_50mhzstrr2, r1, #oMPLLCON#ifndef CONFIG_S3C2410_MPORT1;满足条件,向下执行/* 在/vivi/include/autoconf.h中#undef CONFIG_S3C2410_MPORT1*/ 1:2:4movr1, #CLK_CTL_BASEmovr2, #0x3strr2, r1, #oCLKDIVNmrcp15, 0, r1, c1, c0, 0 read ctrl register orrr1, r1, #0xc0000000 Asynchronous mcrp15, 0, r1, c1, c0, 0 write ctrl register now, CPU clock is 200 Mhz;CPU的频率是200MHzmovr1, #CLK_CTL_BASEldrr2, mpll_200mhzstrr2, r1, #oMPLLCON#else 1:2:2 mov r1, #CLK_CTL_BASE ldr r2, clock_clkdivn str r2, r1, #oCLKDIVN mrc p15, 0, r1, c1, c0, 0 read ctrl register orr r1, r1, #0xc0000000 Asynchronous mcr p15, 0, r1, c1, c0, 0 write ctrl register now, CPU clock is 100 Mhz;CPU的频率是100MHz mov r1, #CLK_CTL_BASE ldr r2, mpll_100mhz str r2, r1, #oMPLLCON#endifblmemsetup;跳转到memsetup函数/*Memsetup函数的实现:ENTRY(memsetup) initialise the static memory set memory control registers;设置内存控制寄存器的初值movr1, #MEM_CTL_BASEadrlr2, mem_cfg_val/* Data Area Memory configuration values.align 4mem_cfg_val:;定义好的13*4=52个字节初值.longvBWSCON;在/vivi/include/platform/smdk2410.h中赋值/* SDRAM从32位变成16位,需要修改vBWSCON的值 */.longvBANKCON0.longvBANKCON1.longvBANKCON2.longvBANKCON3/* 网卡控制器vBANKCON3的值可能需要修改 */.longvBANKCON4.longvBANKCON5.longvBANKCON6/* SDRAM从32位变成16位,可能需要修改vBANKCON6的值 */.longvBANKCON7.longvREFRESH.longvBANKSIZE/* SDRAM从64MB变成32MB,需要修改vBANKSIZE的值 */.longvMRSRB6.longvMRSRB7*/addr3, r1, #521:ldrr4, r2, #4strr4, r1, #4cmpr1, r3bne1b;循环操作,直到13个寄存器赋值完成movpc, lr*/#ifdef CONFIG_PM;vivi考虑不需要使用电源管理 Check if this is a wake-up from sleepldrr1, PMST_ADDRldrr0, r1tstr0, #(PMST_SMR)bneWakeupStart;查看状态,判断是否需要跳转到WakeupStart#endif#ifdef CONFIG_S3C2410_SMDK;SMDK开发板使用 All LED on;点亮开发板上的LEDmovr1, #GPIO_CTL_BASEaddr1, r1, #oGPIO_F;LED使用GPIOF组的管脚ldrr2,=0x55aa ;使能EINT0,EINT1,EINT2,EINT3,;另四个管脚配置成输出,屏蔽EINT4,5,6,7strr2, r1, #oGPIO_CONmovr2, #0xffstrr2, r1, #oGPIO_UP;disable the pull-up functionmovr2, #0x00strr2, r1, #oGPIO_DAT#endif#if 0 SVCmrsr0, cpsrbicr0, r0, #0xdforrr1, r0, #0xd3msrcpsr_all, r1#endif set GPIO for UART;设置串口movr1, #GPIO_CTL_BASEaddr1, r1, #oGPIO_H;设置GPIO_H组管脚为串口ldrr2, gpio_con_uartstrr2, r1, #oGPIO_CONldrr2, gpio_up_uartstrr2, r1, #oGPIO_UP/* inital values for GPIOgpio_con_uart:.longvGPHCON;vGPHCON在/vivi/include/platform/smdk2410.h中赋值;#define vGPHCON0x0016faaa;GPIO_H配置为nCTS0,nRTS0, RXD0,TXD0, RXD1,;TXD1,nCTS1,nRTS1,/* 三个串口都使能,可能需要修改#define vGPHCON 0x0016aaaa */gpio_up_uart:.longVgphup;同上#define vGPHUP0x000007ff;The pull-up function is disabled.*/blInitUART;跳转到InitUART串口初始化函数/* Initialize UART r0 = number of UART portInitUART:ldrr1, SerBase/*.align 4;缺省情况下在vivi中只初始化了UART0SerBase:#if defined(CONFIG_SERIAL_UART0).long UART0_CTL_BASE;基地址在/vivi/include/s3c2410.h中定义#elif defined(CONFIG_SERIAL_UART1).long UART1_CTL_BASE#elif defined(CONFIG_SERIAL_UART2).long UART2_CTL_BASE#else#error not defined base address of serial#endif*/movr2, #0x0strr2, r1, #oUFCONstrr2, r1, #oUMCONmovr2, #0x3strr2, r1, #oULCONldrr2, =0x245strr2, r1, #oUCON#define UART_BRD (50000000 / (UART_BAUD_RATE * 16) - 1)movr2, #UART_BRDstrr2, r1, #oUBRDIVmovr3, #100movr2, #0x01:subr3, r3, #0x1tstr2, r3bne1b#if 0movr2, #Ustrr2, r1, #oUTXHL1:ldrr3, r1, #oUTRSTATandr3, r3, #UTRSTAT_TX_EMPTYtstr3, #UTRSTAT_TX_EMPTYbne1bmovr2, #0strr2, r1, #oUTXHL1:ldrr3, r1, #oUTRSTATandr3, r3, #UTRSTAT_TX_EMPTYtstr3, #UTRSTAT_TX_EMPTYbne1b#endifmovpc, lr*/#ifdef CONFIG_DEBUG_LL;打印调试信息,缺省未定义 Print current Program Counterldrr1, SerBasemovr0, #rblPrintCharmovr0, #nblPrintCharmovr0, #blPrintCharmovr0, pcblPrintHexWord#endif#ifdef CONFIG_BOOTUP_MEMTEST simple memory test to find some DRAM flaults.blmemtest#endif#ifdef CONFIG_S3C2410_NAND_BOOT;从NAND Flash启动blcopy_myself;跳转到copy_myself函数/* copy_myself: copy vivi to ramcopy_myself:movr10, lr reset NANDmovr1, #NAND_CTL_BASEldrr2, =0xf830 initial valuestrr2, r1, #oNFCONFldrr2, r1, #oNFCONFbicr2, r2, #0x800 enable chipstrr2, r1, #oNFCONFmovr2, #0xff RESET commandstrbr2, r1, #oNFCMDmovr3, #0 wait 1:addr3, r3, #0x1cmpr3, #0xablt1b2:ldrr2, r1, #oNFSTAT wait readytstr2, #0x1beq2bldrr2, r1, #oNFCONForrr2, r2, #0x800 disable chipstrr2, r1, #oNFCONF get read to call C functions (for nand_read()ldrsp, DW_STACK_START setup stack pointermovfp, #0 no previous frame, so fp=0 copy vivi to RAMldrr0, =VIVI_RAM_BASE/*在/vivi/linux/platform/smdk2410.h中定义#define VIVI_RAM_BASE(DRAM_BASE + DRAM_SIZE - VIVI_RAM_SIZE)*/mov r1, #0x0movr2, #0x20000;0x20000-128k字节blnand_read_ll;nand_read_ll在/vivi/arch/s3c2410/nand_read.c中定义;r0,r1,r2分别为函数的三个参数;从NANDFlash的0地址拷贝128k到SDRAM指定处tstr0, #0x0beqok_nand_read#ifdef CONFIG_DEBUG_LLbad_nand_read: ldrr0, STR_FAILldrr1, SerBaseblPrintWord1:b1b infinite loop #endifok_nand_read:#ifdef CONFIG_DEBUG_LLldrr0, STR_OKldrr1, SerBaseblPrintWord#endif verifymovr0, #0ldrr1, =0x33f00000movr2, #0x400 4 bytes * 1024 = 4K-bytesgo_next:ldrr3, r0, #4ldrr4, r1, #4teqr3, r4bnenotmatchsubsr2, r2, #4beqdone_nand_readbnego_nextnotmatch:#ifdef CONFIG_DEBUG_LLsubr0, r0, #4ldrr1, SerBaseblPrintHexWordldrr0, STR_FAILldrr1, SerBaseblPrintWord#endif1:b1bdone_nand_read:#ifdef CONFIG_DEBUG_LLldrr0, STR_OKldrr1, SerBaseblPrintWord#endifmovpc, r10;vivi拷贝到SDRAM完成,函数返回*/ jump to ramldrr1, =on_the_ramaddpc, r1, #0nopnop1:b1b infinite loopon_the_ram:#endif#ifdef CONFIG_DEBUG_LLldrr1, SerBaseldrr0, STR_STACKblPrintWordldrr0, DW_STACK_STARTblPrintHexWord#endif get read to call C functionsldrsp, DW_STACK_START setup stack pointermovfp, #0 no previous frame, so fp=0mova2, #0 set argv to NULL blmain call main movpc, #FLASH_BASE otherwise, reboot End VIVI head1.4.2 vivi的第二阶段vivi的第二阶段是从main()函数开始,同一般的C语言程序一样,该函数在/init/main.c文件中,总共可以分为8个步骤。(1) 函数开始,通过putstr(vivi_banner)打印出vivi的版本。Vivi_banner在/init/version.c文件中定义(2) 对开发板进行初始化(board_init函数),board_init是与开发板紧密相关的,这个函数在/arch/s3c2410/smdk.c文件中。开发板初始化主要完成两个功能,时钟初始化(init_time())和通用IO口设置(set_gpios())。int board_init(void)init_time(); /arch/s3c2410/proc.c中set_gpios(); /arch/s3c2410/smdk.creturn 0;先来看看init_time():void init_time(void)TCFG0 = (TCFG0_DZONE(0) | TCFG0_PRE1(15) | TCFG0_PRE0(0);void set_gpios(void)GPACON = vGPACON;GPBCON = vGPBCON;GPBUP = vGPBUP; GPCCON = vGPCCON;GPCUP = vGPCUP; GPDCON = vGPDCON;GPDUP = vGPDUP; GPECON = vGPECON;GPEUP = vGPEUP; GPFCON = vGPFCON;GPFUP = vGPFUP; GPGCON = vGPGCON;GPGUP = vGPGUP; GPHCON = vGPHCON;GPHUP = vGPHUP; EXTINT0 = vEXTINT0;EXTINT1 = vEXTINT1;EXTINT2 = vEXTINT2; /也就是设置各个GPIO口的控制寄存器,和上拉寄存器其中,GPIO口在smdk2410.h(viviincludeplatform目录下)文件中定义。(3) 内存映射初始化和内存管理单元的初始化工作:mem_map_init();mmu_init();这两个函数都在/arch/s3c2410/mmu.c文件中。void mem_map_init(void)#ifdef CONFIG_S3C2410_NAND_BOOTmem_map_nand_boot();#elsemem_map_nor();#endifcache_clean_invalidate();tlb_invalidate();如果配置vivi时使用了NAND作为启动设备,则执行mem_map_nand_boot(),否则执行mem_map_nor()。这里要注意的是,如果使用NAND启动,则必须先把vivi代码复制到RAM中。这个过程是由copy_vivi_to_ram()函数来完成的。代码如下: static void copy_vivi_to_ram(void)putstr_hex(Evacuating 1MB of Flash to DRAM at 0x, VIVI_RAM_BASE);memcpy(void *)VIVI_RAM_BASE, (void *)VIVI_ROM_BASE, VIVI_RAM_SIZE);VIVI_RAM_BASE、VIVI_ROM_BASE、VIVI_RAM_SIZE这些值都可以在smdk2410.h中查到,并且这些值必须根据自己开发板的RAM实际大小修改。这也是在移植vivi的过程中需要注意的一个地方。mmu_init()函数中执行了arm920_setup函数。这段代码是用汇编语言实现的,针对arm920t核的处理器。(4) 初始化堆,heap_init()。(定义在vivilibheap.c文件中)int heap_init(void)return mmalloc_init(unsigned char *)(HEAP_BASE), HEAP_SIZE);heap堆,内存动态分配函数mmalloc就是从heap中划出一块空闲内存的,mfree则将动态分配的某块内存释放回heap中。heap_init函数在SDRAM中指定了一块1M大小的内存作为heap(起始地址HEAP_BASE = 0x33e00000),并在heap的开头定义了一个数据结构blockhead(5) 初始化mtd设备,mtd_dev_init()。 /内存技术设备在分析代码前先介绍一下MTD(Memory Technology Device)相关的技术。在inux系统中,我们通常会用到不同的存储设备,特别是FLASH设备。为了在使用新的存储设备时,我们能更简便地提供它的驱动程序,在上层应用和硬件驱动的中间,抽象出MTD设备层。驱动层不必关心存储的数据格式如何,比如是FAT32、ETX2还是FFS2或其它。它仅仅提供一些简单的接口,比如读写、擦除及查询。如何组织数据,则是上层应用的事情。MTD层将驱动层提供的函数封装起来,向上层提供统一的接口。这样,上层即可专注于文件系统的实现,而不必关心存储设备的具体操作。int mtd_init(void)int ret;#ifdef CONFIG_MTD_CFIret = cf

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论