Uboot源码

上传人:熏** 文档编号:57390223 上传时间:2022-02-23 格式:DOC 页数:22 大小:136.50KB
返回 下载 相关 举报
Uboot源码_第1页
第1页 / 共22页
Uboot源码_第2页
第2页 / 共22页
Uboot源码_第3页
第3页 / 共22页
点击查看更多>>
资源描述
uboot 源码阅读这篇文章属于转载cpu/arm920t/start.S在开始处首先定义了一个全局的标签,.globl _start这个是整个uboot 程序的入口,可在链接脚本board/s3c2410/u-boot.lds 中找到。这个标签所指的地址处就是一跳转指令_start: b reset开始复位。reset:/* set the cpu to SVC32 mode*/mrs r0,cpsrbic r0,r0,#0x1f/* disable IRQ and FIQ, ARM instruct set, supervisor mode. added by BoySKung*/orr r0,r0,#0xd3msr cpsr,r0首先将cpu 设置为supervisor 模式。通过设置cpsr 的低5 位为10011 实现,并禁止IRQ、FIQ。即cpsr 的第七第六位设置为11.接着关闭看门狗定时器ldr r0, =pWTCONmov r1, #0x0str r1, r0将看门狗定时器控制寄存器置0。ldr r0, =CLKDIVNmov r1, #3str r1, r0设置FCLK:HCLK:PCLK 为1:2:4, 通过设置CLKDIVN 控制寄存器的HDIVN、PDIVN 值实现不同的比例00(1:1:1)01(1:1:2)10(1:2:2)11(1:2:4)这些然后开初始化cpucpu_init_crit:/* flush v4 I/D caches*/mov r0, #0mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */首先关闭ICache 和DCache./* disable MMU stuff and caches*/mrc p15, 0, r0, c1, c0, 0bic r0, r0, #0x00002300 clear bits 13, 9:8 (-V- -RS)bic r0, r0, #0x00000087 clear bits 7, 2:0 (B- -CAM)orr r0, r0, #0x00000002 set bit 2 (A) Alignorr r0, r0, #0x00001000 set bit 12 (I) I-Cachemcr p15, 0, r0, c1, c0, 0关闭MMU,数据存储格式为小端。开启数据地址对齐错误检测,使能ICACHE。/* before relocating, we have to setup RAM timing* because memory timing is board-dependend, you will* find a memsetup.S in your board directory.*/mov ip, lrbl memsetupmov lr, ipmov pc, lr还要对内存时序进行设置,因为内存时序是依赖于开发板的。Cpu 初始化结束后,开始初始化串口uart Initialize UART r0 = number of UART portInitUART:ldr r1, =0x50000000mov r2, #0x0str r2, r1, #0x8str r2, r1, #0xcmov r2, #0x3str r2, r1, #0x0ldr r2, =0x245str r2, r1, #0x4/* 50700000 = PCLK = 202.8 / 4 = 50.7 when FCLK at 202.8 */#define UART_BRD (50700000 / (115200 * 16) - 1)mov r2, #UART_BRDstr r2, r1, #0x28这里主要对uart 的一些控制寄存器进行了设置,并设置了串口的波特率mov r3, #100mov r2, #0x01: sub r3, r3, #0x1tst r2, r3bne 1bmov pc, lr这里是一段延时,具体起什么作用还不清楚。这些初始化都结束后开始代码重定位relocate: /* relocate U-Boot to RAM */adr r0, _start /* r0 - current position of code */ldr r1, _TEXT_BASE /* test if we run from flash or RAM */cmp r0, r1 /* dont reloc during debug */beq stack_setupldr r2, _armboot_startldr r3, _bss_startsub r2, r3, r2 /* r2 - size of armboot */add r2, r0, r2 /* r2 - source end address */copy_loop:ldmia r0!, r3-r10 /* copy from source address r0 */stmia r1!, r3-r10 /* copy to target address r1 */cmp r0, r2 /* until source end addreee r2 */ble copy_loop重定位时,首先检查当前是不是在ram 中运行,若是则不需重定位紧接着设置堆栈stack_setup:ldr r1, =0x48000004ldr r0, r1bl PrintHexWord/* enter ansynchronous, when cpu at 202.8MHZ, it must into asynchronous mode*/mrc p15, 0, r1, c1, c0, 0 read ctrl registerorr r1, r1, #0xc0000000 Asynchronousmcr p15, 0, r1, c1, c0, 0 write ctrl registerldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */sub r0, r0, #CFG_MALLOC_LEN /* malloc area */sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */#ifdef CONFIG_USE_IRQsub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)#endifsub sp, r0, #12 /* leave 3 words for abort-stack */清除bss 段clear_bss:ldr r0, _bss_start /* find start of bss segment */add r0, r0, #4 /* start at first byte of bss */ldr r1, _bss_end /* stop here */mov r2, #0x00000000 /* clear */clbss_l:str r2, r0 /* clear loop. */add r0, r0, #4cmp r0, r1bne clbss_l就是将bss 段全部置0最后ldr pc, _start_armboot开始进入c 的世界,uboot 启动的stage 2Lib_arm/board.c当第一阶段的汇编部分执行完,跳到stage2 时,开始执行c 函数start_armboot开头首先声明一个全局指针变量DECLARE_GLOBAL_DATA_PTR; 这个宏定义在头文件include/asm-arm/global_data.h 中#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm (r8)typedef struct global_data bd_t *bd;unsigned long flags;unsigned long baudrate;unsigned long have_console; /* serial_init() was called */unsigned long reloc_off; /* Relocation Offset */unsigned long env_addr; /* Address of Environment struct */unsigned long env_valid; /* Checksum of Environment valid? */unsigned long fb_base; /* base address of frame buffer */#ifdef CONFIG_VFDunsigned char vfd_type; /* display type */#endif#if 0unsigned long cpu_clk; /* CPU clock in Hz! */unsigned long bus_clk;unsigned long ram_size; /* RAM size */unsigned long reset_status; /* reset status register at boot */#endifvoid *jt; /* jump table */ gd_t;在这个结构中存放一些全局数据。gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t);这行是对指针的初始化。接下来通过一个循环,执行初始化序列中的一些函数for (init_fnc_ptr = init_sequence; *init_fnc_ptr; +init_fnc_ptr) if (*init_fnc_ptr)() != 0) hang ();初始化序列的定义如下:init_fnc_t *init_sequence = cpu_init, /初始化cpu,主要是设置FIQ 和IRQ 的堆栈起始地址board_init, /开发板初始化,设置电源、时钟、I/O 端口及全能I/DCacheinterrupt_init, /中断初始化,设置PWM 时钟env_init, /环境变量初始化,检测环境变量是否有效,并初始化相全局变量init_baudrate, /初始化波特率,设置板子通信时的波特率serial_init, /初始化串口,设置串口和通信时数据结构,包括起始/停止位等console_init_f, /控制台初始化,将控制台设置为silent 模式display_banner,/打印板子相关信息dram_init, /内存初始化,设置内存的起始地址和大小display_dram_config, /显示内存配置信息#if defined(CONFIG_VCMA9)checkboard,#endifNULL,;这些初始化都完成后开始初始化flashunsigned long flash_init (void)unsigned long size_b0;int i;/* Init: no FLASHes known */for (i=0; iCFG_MAX_FLASH_BANKS; +i) flash_infoi.flash_id = FLASH_UNKNOWN;/* Static FLASH Bank configuration here - FIXME XXX */#if 1debug (n# Get flash bank 1 size 0x%08xn,CFG_FLASH_BASE);#endif/根据flash 的基地址CFG_FLASH_BASE,获得flash 的大小,size_b0 = flash_get_size(vu_short *)CFG_FLASH_BASE, &flash_info0);if (flash_info0.flash_id = FLASH_UNKNOWN) printf (# Unknown FLASH on Bank 0: ID 0x%lx, Size = 0x%08lx = %ld MBn,flash_info0.flash_id,size_b0, size_b0= CFG_FLASH_BASE/* monitor protection ON by default */flash_protect(FLAG_PROTECT_SET,CFG_MONITOR_BASE,CFG_MONITOR_BASE+monitor_flash_len-1,&flash_info0);#endif#ifdef CFG_ENV_IS_IN_FLASH/* ENV protection ON by default */flash_protect(FLAG_PROTECT_SET,CFG_ENV_ADDR,CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,&flash_info0);#endifreturn size_b0;然后是初始内存堆staticvoid mem_malloc_init (ulong dest_addr)mem_malloc_start = dest_addr;mem_malloc_end = dest_addr + CFG_MALLOC_LEN;mem_malloc_brk = mem_malloc_start;memset (void *) mem_malloc_start, 0,mem_malloc_end - mem_malloc_start);之后要进行环境变量重定位,把环境变量放到内存当中env_relocate ();还要设置网卡的ip 地址和mac 地址/* IP Address */gd-bd-bi_ip_addr = getenv_IPaddr (ipaddr);/* MAC Address */int i;ulong reg;char *s, *e;uchar tmp64;i = getenv_r (ethaddr, tmp, sizeof (tmp);s = (i 0) ? tmp : NULL;for (reg = 0; reg bd-bi_enetaddrreg = s ? simple_strtoul (s, &e, 16) : 0;if (s)s = (*e) ? e + 1 : e;设备初始化int devices_init (void)char *s;#ifndef CONFIG_ARM /* already relocated for current ARM implementation */DECLARE_GLOBAL_DATA_PTR;ulong relocation_offset = gd-reloc_off;int i;/* relocate device name pointers */for (i = 0; i = 1 & sm501mode jt = (void *) malloc (XF_MAX * sizeof (void *);for (i = 0; i jti = (void *) dummy;gd-jtXF_get_version = (void *) get_version;gd-jtXF_malloc = (void *) malloc;gd-jtXF_free = (void *) free;gd-jtXF_get_timer = (void *)get_timer;gd-jtXF_udelay = (void *)udelay;#if defined(CONFIG_I386) | defined(CONFIG_PPC)gd-jtXF_install_hdlr = (void *) irq_install_handler;gd-jtXF_free_hdlr = (void *) irq_free_handler;#endif /* I386 | PPC */#if (CONFIG_COMMANDS & CFG_CMD_I2C)gd-jtXF_i2c_write = (void *) i2c_write;gd-jtXF_i2c_read = (void *) i2c_read;#endif /* CFG_CMD_I2C */初始化跳转表,主要是保存了一些系统函数的指针。便于以后引用然后对控制台进行全面的初始化console_init_r (); /* fully init console as a device */主要是初始化控制台输入输出设备接下来开中断/* enable exceptions */enable_interrupts ();初始化网卡设备等/* Perform network card initialisation if necessary */#ifdef CONFIG_DRIVER_DM9000DM9000_get_enetaddr (gd-bd-bi_enetaddr);#endif最后进入主循环/* main_loop() can return to retry autoboot, if so just run it again. */for (;) main_loop ();在这个循环中,将检测是自动启动还是命令行起动。起动后,uboot 的stage2 也就结束了Uboot 中的每一个命令都由一个宏进行声明,这宏在文件include/command.h 中定义#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) cmd_tbl_t _u_boot_cmd_#name Struct_Section = #name, maxargs, rep, cmd, usage, help如i2c 设备操作中的某个命令的声明如下U_BOOT_CMD(imd, 4, 1, do_i2c_md, imd - i2c memory displayn, chip address.0, .1, .2 # of objectsn - i2c memory displayn );这个声明里初始化了cmd_tbl_t 结构struct cmd_tbl_s char *name; /* Command Name */int maxargs; /* maximum number of arguments */int repeatable; /* autorepeat allowed? */* Implementation function */int (*cmd)(struct cmd_tbl_s *, int, int, char *);char *usage; /* Usage message (short) */#ifdef CFG_LONGHELPchar *help; /* Help message (long) */#endif;上面的声明分别初始化命令名(imd)、最大参数个数(4)、是否允许自动重复(1 允许,即第一次没执行成功时会自动重复执行)、实现函数(do_i2c_md)、用法(imd - i2c memorydisplayn)和帮助(chip address.0, .1, .2 # of objectsn - i2c memory displayn )。当执行imd 命令时,系统会调用common/command.c 中的find_cmd 函数,查找相应的实现函数do_i2c_md。查找时在由_u_boot_cmd_start 开始到_u_boot_cmd_end 结束的范围内查找。这两个符号的地址在链接脚本board/s3c2410/uboot.lds 中确定OUTPUT_FORMAT(elf32-littlearm, elf32-littlearm, elf32-littlearm)/*OUTPUT_FORMAT(elf32-arm, elf32-arm, elf32-arm)*/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 = .;在这里,将所有的命令链接到bss 段前面的一段内存中。引导加载内核Common/main.c main_loop()Common/cmd_bootm.c do_bootm()Lib_arm/armlinux.c do_bootm_linux()在uboot 的stage2 的最后阶段,进入main_loop()函数。在这个函数中首先检查是否有启动延时,然后决定是自动加载内核映像来启动内核还是通过命令行来启动内核:s = getenv (bootdelay);bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;上面两行是获得延时时长s = getenv (bootcmd);这行代码是获得启动命令行,这个环境变量的定义是Bootcmd = cp 0x200000 0x32000000 0x100000;bootm这个在配置头文件include/configs/s3c2410.h 中也有定义#define CONFIG_BOOTCOMMAND cp 0x200000 0x320000000x100000;bootm因内核映像在flash 的0x200000 地址处,所以这里先把内核映像复制到sdram 的32000000地址处,然后运行bootm 启动。Bootm 这个命令将在后面提到判断延时是否结束,若延时已结束,则运行上面所获得的命令if (bootdelay = 0 & s & !abortboot (bootdelay) # ifdef CONFIG_AUTOBOOT_KEYEDint prev = disable_ctrlc(1); /* disable Control C checking */# endif# ifndef CFG_HUSH_PARSER/运行启动命令run_command (s, 0);# elseparse_string_outer(s, FLAG_PARSE_SEMICOLON |FLAG_EXIT_FROM_LOOP);# endif# ifdef CONFIG_AUTOBOOT_KEYEDdisable_ctrlc(prev); /* restore Control C checking */# endif若延时期间按了某个键,即上面粗体字函数abortboot (bootdelay) 返回1,则进入命令行模式,这时可以通过网络加载内核映像到sdram 中:Tftpboot 32000000 uImage然后运行bootm 启动或者从flash 中拷贝Cp 200000 32000000 size然后运行bootm 启动。不管是自动加载,还是在命令行下加载,最后都是把内核映像加载到sdram 中,再运行bootm命令启动。下面就说说bootm 这个命令。在cmd_bootm.c 中声明并实现了bootm 命令U_BOOT_CMD(bootm, CFG_MAXARGS, 1, do_bootm,bootm - boot application image from memoryn,addr arg .n - boot application image stored in memoryn passing arguments arg .; when booting a Linux kernel,n arg can be the address of an initrd imagen);若对uboot 命令不熟悉可参看其实现函数为do_bootm()image_header_t header; /存放映像头信息的数据结构/在include/configs/s3c2410.h 中,CFG_LOAD_ADDR=32000000,即内核映像加载在这个地址处ulong load_addr = CFG_LOAD_ADDR; /* Default Load Address */int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv)ulong iflag;ulong addr;ulong data, len, checksum;ulong *len_ptr;uint unc_len = 0x400000;int i, verify;char *name, *s;int (*appl)(int, char *);image_header_t *hdr = &header;/确定是否进行校验s = getenv (verify);/verify = 1 时进行校验verify = (s & (*s = n) ? 0 : 1;if (argc ih_magic) != IH_MAGIC) #ifdef _I386_ /* correct image format not implemented yet - fake it */if (fake_header(hdr, (void*)addr, -1) != NULL) /* to compensate for the addition below */addr -= sizeof(image_header_t);/* turnof verify,* fake_header() does not fake the data crc*/verify = 0; else#endif /* _I386_ */printf (Bad Magic Numbern);SHOW_BOOT_PROGRESS (-1);return 1;SHOW_BOOT_PROGRESS (2);/获得内核映像头部的起始地址data = (ulong)&header;/头部大小len = sizeof(image_header_t);/内核映像的crc 校验码checksum = ntohl(hdr-ih_hcrc);hdr-ih_hcrc = 0;/检测校验码if (crc32 (0, (char *)data, len) != checksum) printf (Bad Header Checksumn);SHOW_BOOT_PROGRESS (-2);return 1;SHOW_BOOT_PROGRESS (3);/打印内核映像头部信息/* for multi-file images we need the data part, too */print_image_hdr (image_header_t *)addr);/获得映像数据起始地址(除支内核映像头部)data = addr + sizeof(image_header_t);/映像数据的大小(除头部)len = ntohl(hdr-ih_size);#ifdef CONFIG_HAS_DATAFLASHif (addr_dataflash(addr)read_dataflash(data, len, (char *)CFG_LOAD_ADDR);data = CFG_LOAD_ADDR;#endif/若verify = 1 进行校验if (verify) printf ( Verifying Checksum . );if (crc32 (0l, (volatile char *)data, len) != ntohl(hdr-ih_dcrc) printf (Bad Data CRCn);SHOW_BOOT_PROGRESS (-3);return 1;printf (OKn);SHOW_BOOT_PROGRESS (4);/映像数据的起始地址(除头部)len_ptr = (ulong *)data;/查看头部信息,体系结构与配置的是否一致#if defined(_PPC_)if (hdr-ih_arch != IH_CPU_PPC)#elif defined(_ARM_)if (hdr-ih_arch != IH_CPU_ARM)#elif defined(_I386_)if (hdr-ih_arch != IH_CPU_I386)#elif defined(_mips_)if (hdr-ih_arch != IH_CPU_MIPS)#elif defined(_nios_)if (hdr-ih_arch != IH_CPU_NIOS)#elif defined(_M68K_)if (hdr-ih_arch != IH_CPU_M68K)#else# error Unknown CPU type#endifprintf (Unsupported Architecture 0x%xn, hdr-ih_arch);SHOW_BOOT_PROGRESS (-4);return 1;SHOW_BOOT_PROGRESS (5);/检测映像类型switch (hdr-ih_type) case IH_TYPE_STANDALONE:name = Standalone Application;/* A second argument overwrites the load address */if (argc 2) hdr-ih_load = simple_strtoul(argv2, NULL, 16);break;case IH_TYPE_KERNEL:name = Kernel Image;break;case IH_TYPE_MULTI:name = Multi-File Image;len = ntohl(len_ptr0);/* OS kernel is always the first image */data += 8; /* kernel_len + terminator */for (i=1; len_ptri; +i)data += 4;break;default: printf (Wrong Image Type for %s commandn, cmdtp-name);SHOW_BOOT_PROGRESS (-5);return 1;SHOW_BOOT_PROGRESS (6);/* We have reached the point of no return: we are going to* overwrite all exception vector code, so we cannot easily* recover from any failures any more.*/iflag = disable_interrupts();#ifdef CONFIG_AMIGAONEG3SE/* Weve possible left the caches enabled during* bios emulation, so turn them off again*/icache_disable();invalidate_l1_instruction_cache();flush_data_cache();dcache_disable();#endif/检测映像的压缩类型,用相应工具解压缩switch (hdr-ih_comp) case IH_COMP_NONE:if(ntohl(hdr-ih_load) = addr) printf ( XIP %s . , name); else #if defined(CONFIG_HW_WATCHDOG) | defined(CONFIG_WATCHDOG)size_t l = len;void *to = (void *)ntohl(hdr-ih_load);void *from = (void *)data;printf ( Loading %s . , name);while (l 0) size_t tail = (l CHUNKSZ) ? CHUNKSZ : l;WATCHDOG_RESET();memmove (to, from, tail);to += tail;from += tail;l -= tail;#else /* !(CONFIG_HW_WATCHDOG | CONFIG_WATCHDOG) */memmove (void *) ntohl(hdr-ih_load), (uchar *)data, len);#endif /* CONFIG_HW_WATCHDOG | CONFIG_WATCHDOG */break;case IH_COMP_GZIP:printf ( Uncompressing %s . , name);if (gunzip (void *)ntohl(hdr-ih_load), unc_len,(uchar *)data, (int *)&len) != 0) printf (GUNZIP ERROR - must RESET board to recovern);SHOW_BOOT_PROGRESS (-6);do_reset (cmdtp, flag, argc, argv);break;#ifdef CONFIG_BZIP2case IH_COMP_BZIP2:printf ( Uncompressing %s . , name);/* If weve got less than 4 MB of malloc() space,* use slower decompression algorithm which requires* at most 2300 KB of memory.*/i = BZ2_bzBuffToBuffDecompress (char*)ntohl(hdr-ih_load),&unc_len, (char *)data, len,CFG_MALLOC_LEN ih_comp);SHOW_BOOT_PROGRESS (-7);return 1;printf (OKn);SHOW_BOOT_PROGRESS (7);/根据映像压缩类型进行相应设置switch (hdr-ih_type) case IH_TYPE_STANDALONE:if (iflag)enable_interrupts();/* load (and uncompress), but dont start if autostart* is set to no*/if (s = getenv(autostart) != NULL) & (strcmp(s,no) = 0) char buf32;sprintf(buf, %lX, len);setenv(filesize, buf);return 0;appl = (int (*)(int, char *)ntohl(hdr-ih_ep);(*appl)(argc-1, &argv1);return 0;case IH_TYPE_KERNEL:case IH_TYPE_MULTI:/* handled below */b
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 商业管理 > 营销创新


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!