基于IMX6Q的uboot启动流程分析(1):uboot入口函数
基于IMX6Q的uboot启动流程分析(2):_main函数之board_init_f
基于IMX6Q的uboot启动流程分析(3):_main函数之relocate_code与board_init_r
基于IMX6Q的uboot启动流程分析(4):uboot中的串口设备

第3章:_main函数之relocate_code与board_init_r

3.1 relocate_code函数

上一小节,介绍了board_init_f函数,主要的是对整个DRAM的内存进行了分配,以便uboot的重定位。

3.1.1 设置中间环境

在调用relocate_code函数前,需设置中间环境,更新分配DRAM后的sp指针值和gd指针值,其内容如下

 ldr r0, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */ //新的spbic  r0, r0, #7  /* 8-byte alignment for ABI compliance */mov    sp, r0ldr   r9, [r9, #GD_NEW_GD]        /* r9 <- gd->new_gd */adr lr, hereldr r0, [r9, #GD_RELOC_OFF]     /* r0 = gd->reloc_off */add lr, lr, r0
#if defined(CONFIG_CPU_V7M)orr  lr, #1              /* As required by Thumb-only */
#endifldr   r0, [r9, #GD_RELOCADDR]     /* r0 = gd->relocaddr */b   relocate_code

将新的sp地址赋值给r0 = 0x4DF68F50

3.1.2 relocate_code函数详解

uboot重定位主要由relocate_code函数实现,其定义在arch/arm/lib/relocate.S文件中,内容为:

 80 ENTRY(relocate_code)81         ldr     r1, =__image_copy_start /* r1 <- SRC &__image_copy_start */82         subs    r4, r0, r1              /* r4 <- relocation offset */83         beq     relocate_done           /* skip relocation */84         ldr     r2, =__image_copy_end   /* r2 <- SRC &__image_copy_end */85 86 copy_loop:87         ldmia   r1!, {r10-r11}          /* copy from source address [r1]    */88         stmia   r0!, {r10-r11}          /* copy to   target address [r0]    */89         cmp     r1, r2                  /* until source end address [r2]    */90         blo     copy_loop91 92         /*93          * fix .rel.dyn relocations94          */95         ldr     r2, =__rel_dyn_start    /* r2 <- SRC &__rel_dyn_start */96         ldr     r3, =__rel_dyn_end      /* r3 <- SRC &__rel_dyn_end */97 fixloop:98         ldmia   r2!, {r0-r1}            /* (r0,r1) <- (SRC location,fixup) */99         and     r1, r1, #0xff
100         cmp     r1, #R_ARM_RELATIVE
101         bne     fixnext
102
103         /* relative fix: increase location by offset */
104         add     r0, r0, r4
105         ldr     r1, [r0]
106         add     r1, r1, r4
107         str     r1, [r0]
108 fixnext:
109         cmp     r2, r3
110         blo     fixloop
111
112 relocate_done:
113
114 #ifdef __XSCALE__
115         /*
116          * On xscale, icache must be invalidated and write buffers drained,
117          * even with cache disabled - 4.2.7 of xscale core developer's manual
118          */
119         mcr     p15, 0, r0, c7, c7, 0   /* invalidate icache */
120         mcr     p15, 0, r0, c7, c10, 4  /* drain write buffer */
121 #endif
122
123         /* ARMv4- don't know bx lr but the assembler fails to see that */
124
125 #ifdef __ARM_ARCH_4__
126         mov     pc, lr
127 #else
128         bx      lr
129 #endif
130
131 ENDPROC(relocate_code)
  • 第81行,将__image_copy_start的值赋值给r1寄存器。由uboot.map文件得知

    __image_copy_start = 0x17800000
    
  • 第82行,r4寄存器保存重定位前后位置的偏移量。r4 = r0 - r1 = 0x4DF68F50 - 0x17800000 = 0x36768F50。

  • 第83行,跳转relocate_done函数,判断uboot重定位的目的地址是否和uboot源地址是否相等,如果相等的话,表示不需要重定位,跳到relocate_done处,继续运行,如果不相等的话,则是需要进行重定位。

  • 第84行,r2寄存器保存uboot复制结束的地址__image_copy_end。由uboot.map文件得知,__image_copy_end = 0x1787ba9c。

  • 第86-90行,copy_loop区域,执行拷贝,将uboot从低地址重定位到高地址。重定位过程描述为:

    • 第一:从r1,也就是__image_copy_start开始,读取uboot代码到r10和r11寄存器,一次就拷贝两个32位的数据,r1自动更新,保存下一个需要拷贝的地址,
    • 第二:将r10和r11里面的数据,写到r0保存的地址,也就是uboot重定位的目的地址,r0自动更新。
    • 第三:比较r1和r2是否相等,也就是判断uboot代码是否拷贝完成,如果没完成的话,跳转到copy_loop处,继续循环,直到uboot拷贝完成。
  • 第95-110行,重定位.rel.dyn段,.rel.dyn段是存放.text段中需要重定位地址的集合。

补充:

一个可执行的bin文件,它的链接地址和运行地址一定要相等,也就是链接到哪个地址,运行之前就需要拷贝到哪个地址中进行运行,在前面的重定位后,运行地址和链接地址就不一样了,这样在进行寻址就会出问题,对.rel.dyn的定位问题进行修复,就是为了解决该问题。

至此uboot的重定位工作已经完成,将保存在低地址的uboot,自搬移到高地址中执行。

3.1.3 relocate_vectors函数详解

在重定位uboot后,需要调用relocate_vectors函数,来重定位向量表。函数内容为:

ENTRY(relocate_vectors)#ifdef CONFIG_CPU_V7M/** On ARMv7-M we only have to write the new vector address* to VTOR register.*/ldr  r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ldr r1, =V7M_SCB_BASEstr   r0, [r1, V7M_SCB_VTOR]
#else
#ifdef CONFIG_HAS_VBAR/** If the ARM processor has the security extensions,* use VBAR to relocate the exception vectors.*/ldr   r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */mcr     p15, 0, r0, c12, c0, 0  /* Set VBAR */
#else...
#endif
#endifbx    lrENDPROC(relocate_vectors)

在IMX6Q中,定义了CONFIG_HAS_VBAR,因此这个函数只用执行以下语句:

 ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */mcr     p15, 0, r0, c12, c0, 0  /* Set VBAR */

首先是将gd->relocaddr的值赋给r0,也就是r0里面保存重定位后uboot的首地址,中断向量表也是从这个首地址开始存储的,接下来,使用mcr指令,将r0的值写到CP15的VBAR寄存器中,其实就是将新的中断向量表首地址写到VBAR寄存器中,设置中断向量表偏移。

至此uboot的重定位与中断向量表重定位的工作已经完成。

3.2 board_init_r函数

2.1节对board_init_f函数进行介绍,其作用gd结构体的成员变量,以及对DRAM内存进行规划。而本节board_init_r函数是将一些板子需要的外设进行初始化。

3.2.1 设置board_init_r环境

调用board_init_r函数前,需要设置一些参数,其代码为:

 bl  c_runtime_cpu_setup /* we still call old routine here */
#endif
#if !defined(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(FRAMEWORK)#if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_SPL_EARLY_BSS)CLEAR_BSS
#endif...
#if ! defined(CONFIG_SPL_BUILD)bl coloured_LED_initbl red_led_on
#endif/* call board_init_r(gd_t *id, ulong dest_addr) */mov     r0, r9                  /* gd_t */ldr   r1, [r9, #GD_RELOCADDR] /* dest_addr *//* call board_init_r */
#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD)ldr   lr, =board_init_r  /* this is auto-relocated! */bx lr
#elseldr    pc, =board_init_r  /* this is auto-relocated! */
#endif/* we should not return here. */
#endif

首先是调用了函数c_runtime_cpu_setup函数,关闭cache。然后调用CLEAR_BSS清除bss段。接着将gd地址赋值给r0,将gd->relocaddr地址赋值给r1。board_init_r(gd_t *id, ulong dest_addr)函数具有两个参数,第一个参数为gd指针的值,第二个参数为gd->relocaddr。最后跳转到board_init_r函数执行。

3.2.2 board_init_r函数详解

board_init_r函数定义在common/board_r.c文件中。函数的主要内容为:

void board_init_r(gd_t *new_gd, ulong dest_addr)
{...
#ifdef CONFIG_NEEDS_MANUAL_RELOCint i;
#endif#if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64)gd = new_gd;
#endifgd->flags &= ~GD_FLG_LOG_READY;#ifdef CONFIG_NEEDS_MANUAL_RELOCfor (i = 0; i < ARRAY_SIZE(init_sequence_r); i++)init_sequence_r[i] += gd->reloc_off;
#endifif (initcall_run_list(init_sequence_r))hang();/* NOTREACHED - run_main_loop() does not return */hang();
}

该函数的重点是initcall_run_list(init_sequence_r)init_sequence_r是一个函数集合的数组,也就是函数初始化序列。其内容为:

641 static init_fnc_t init_sequence_r[] = {  //函数初始化序列
642         initr_trace,
643         initr_reloc,
644         /* TODO: could x86/PPC have this also perhaps? */
645 #ifdef CONFIG_ARM
646         initr_caches,
647         /* Note: For Freescale LS2 SoCs, new MMU table is created in DDR.
648          *       A temporary mapping of IFC high region is since removed,
649          *       so environmental variables in NOR flash is not available
650          *       until board_init() is called below to remap IFC to high
651          *       region.
652          */
653 #endif
654         initr_reloc_global_data,
655 #if defined(CONFIG_SYS_INIT_RAM_LOCK) && defined(CONFIG_E500)
656         initr_unlock_ram_in_cache,
657 #endif
658         initr_barrier,
659         initr_malloc,
660         log_init,
661         initr_bootstage,        /* Needs malloc() but has its own timer */
662 #if defined(CONFIG_CONSOLE_RECORD)
663         console_record_init,
664 #endif
665 #ifdef CONFIG_SYS_NONCACHED_MEMORY
666         noncached_init,
667 #endif
668         initr_of_live,
669 #ifdef CONFIG_DM
670         initr_dm,
671 #endif
672 #ifdef CONFIG_ADDR_MAP
673         initr_addr_map,
674 #endif
675 #if defined(CONFIG_ARM) || defined(CONFIG_NDS32) || defined(CONFIG_RISCV) || \
676         defined(CONFIG_SANDBOX)
677         board_init,     /* Setup chipselects */
678 #endif
679         /*
680          * TODO: printing of the clock inforamtion of the board is now
681          * implemented as part of bdinfo command. Currently only support for
682          * davinci SOC's is added. Remove this check once all the board
683          * implement this.
684          */
685 #ifdef CONFIG_CLOCKS
686         set_cpu_clk_info, /* Setup clock information */
687 #endif
688 #ifdef CONFIG_EFI_LOADER
689         efi_memory_init,
690 #endif
691         initr_binman,
692 #ifdef CONFIG_FSP_VERSION2
693         arch_fsp_init_r,
694 #endif
695         initr_dm_devices,
696         stdio_init_tables,
697         serial_initialize,
698         initr_announce,
699 #if CONFIG_IS_ENABLED(WDT)
700         initr_watchdog,
701 #endif
702         INIT_FUNC_WATCHDOG_RESET
703 #if defined(CONFIG_NEEDS_MANUAL_RELOC) && defined(CONFIG_BLOCK_CACHE)
704         blkcache_init,
705 #endif
706 #ifdef CONFIG_NEEDS_MANUAL_RELOC
707         initr_manual_reloc_cmdtable,
708 #endif
709         arch_initr_trap,
710 #if defined(CONFIG_BOARD_EARLY_INIT_R)
711         board_early_init_r,
712 #endif
713         INIT_FUNC_WATCHDOG_RESET
714 #ifdef CONFIG_POST
715         post_output_backlog,
716 #endif
717         INIT_FUNC_WATCHDOG_RESET
718 #if defined(CONFIG_PCI_INIT_R) && defined(CONFIG_SYS_EARLY_PCI_INIT)
719         /*
720          * Do early PCI configuration _before_ the flash gets initialised,
721          * because PCU resources are crucial for flash access on some boards.
722          */
723         pci_init,
724 #endif
725 #ifdef CONFIG_ARCH_EARLY_INIT_R
726         arch_early_init_r,
727 #endif
728         power_init_board,
729 #ifdef CONFIG_MTD_NOR_FLASH
730         initr_flash,
731 #endif
732         INIT_FUNC_WATCHDOG_RESET
733 #if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_X86)
734         /* initialize higher level parts of CPU like time base and timers */
735         cpu_init_r,
736 #endif
737 #ifdef CONFIG_CMD_NAND
738         initr_nand,
739 #endif
740 #ifdef CONFIG_CMD_ONENAND
741         initr_onenand,
742 #endif
743 #ifdef CONFIG_MMC
744         initr_mmc,
745 #endif
746 #ifdef CONFIG_XEN
747         xen_init,
748 #endif
749 #ifdef CONFIG_PVBLOCK
750         initr_pvblock,
751 #endif
752         initr_env,
753 #ifdef CONFIG_SYS_BOOTPARAMS_LEN
754         initr_malloc_bootparams,
755 #endif
756         INIT_FUNC_WATCHDOG_RESET
757         cpu_secondary_init_r,
758 #if defined(CONFIG_ID_EEPROM) || defined(CONFIG_SYS_I2C_MAC_OFFSET)
759         mac_read_from_eeprom,
760 #endif
761         INIT_FUNC_WATCHDOG_RESET
762 #if defined(CONFIG_PCI_INIT_R) && !defined(CONFIG_SYS_EARLY_PCI_INIT)
763         /*
764          * Do pci configuration
765          */
766         pci_init,
767 #endif
768         stdio_add_devices,
769         jumptable_init,
770 #ifdef CONFIG_API
771         api_init,
772 #endif
773         console_init_r,         /* fully init console as a device */
774 #ifdef CONFIG_DISPLAY_BOARDINFO_LATE
775         console_announce_r,
776         show_board_info,
777 #endif
778 #ifdef CONFIG_ARCH_MISC_INIT
779         arch_misc_init,         /* miscellaneous arch-dependent init */
780 #endif
781 #ifdef CONFIG_MISC_INIT_R
782         misc_init_r,            /* miscellaneous platform-dependent init */
783 #endif
784         INIT_FUNC_WATCHDOG_RESET
785 #ifdef CONFIG_CMD_KGDB
786         initr_kgdb,
787 #endif
788         interrupt_init,
789 #if defined(CONFIG_MICROBLAZE) || defined(CONFIG_M68K)
790         timer_init,             /* initialize timer */
791 #endif
792 #if defined(CONFIG_LED_STATUS)
793         initr_status_led,
794 #endif
795         /* PPC has a udelay(20) here dating from 2002. Why? */
796 #ifdef CONFIG_CMD_NET
797         initr_ethaddr,
798 #endif
799 #if defined(CONFIG_GPIO_HOG)
800         gpio_hog_probe_all,
801 #endif
802 #ifdef CONFIG_BOARD_LATE_INIT
803         board_late_init,
804 #endif
805 #ifdef CONFIG_FSL_FASTBOOT
806         initr_fastboot_setup,
807 #endif
808 #if defined(CONFIG_SCSI) && !defined(CONFIG_DM_SCSI)
809         INIT_FUNC_WATCHDOG_RESET
810         initr_scsi,
811 #endif
812 #ifdef CONFIG_BITBANGMII
813         bb_miiphy_init,
814 #endif
815 #ifdef CONFIG_PCI_ENDPOINT
816         pci_ep_init,
817 #endif
818 #ifdef CONFIG_CMD_NET
819         INIT_FUNC_WATCHDOG_RESET
820         initr_net,
821 #endif
822 #ifdef CONFIG_POST
823         initr_post,
824 #endif
825 #if defined(CONFIG_IDE) && !defined(CONFIG_BLK)
826         initr_ide,
827 #endif
828 #ifdef CONFIG_LAST_STAGE_INIT
829         INIT_FUNC_WATCHDOG_RESET
830         /*
831          * Some parts can be only initialized if all others (like
832          * Interrupts) are up and running (i.e. the PC-style ISA
833          * keyboard).
834          */
835         last_stage_init,
836 #endif
837 #ifdef CONFIG_CMD_BEDBUG
838         INIT_FUNC_WATCHDOG_RESET
839         bedbug_init,
840 #endif
841 #if defined(CONFIG_PRAM)
842         initr_mem,
843 #endif
844 #ifdef CONFIG_EFI_SETUP_EARLY
845         (init_fnc_t)efi_init_obj_list,
846 #endif
847 #if defined(AVB_RPMB) && !defined(CONFIG_SPL)
848         initr_avbkey,
849 #endif
850 #ifdef CONFIG_IMX_TRUSTY_OS
851         initr_tee_setup,
852 #endif
853 #ifdef CONFIG_FSL_FASTBOOT
854         initr_check_fastboot,
855 #endif
856 #ifdef CONFIG_DUAL_BOOTLOADER
857         initr_check_spl_recovery,
858 #endif
859         run_main_loop,
860 };
  • 第642行,initr_trace,该函数是与初始化和调试跟踪相关的内容。

  • 第643行,initr_reloc,该函数设置了gd->flags成员,标记uboot重定位完成。

  • 第646行,initr_reloc,该函数用于初始化cache,使能cache。

  • 第654行,initr_reloc_global_data,该函数用于初始化重定为后gd的一些成员变量。。

  • 第659行,initr_malloc,该函数用于初始化malloc。

    int board_init(void)
    {/* address of boot parameters */gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;#if defined(CONFIG_DM_REGULATOR)regulators_enable_boot_on(false);
    #endif#ifdef CONFIG_MXC_SPIsetup_spi();
    #endif#ifdef CONFIG_SYS_I2Csetup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
    #endif#if defined(CONFIG_PCIE_IMX) && !defined(CONFIG_DM_PCI)setup_pcie();
    #endif#if defined(CONFIG_MX6DL) && defined(CONFIG_MXC_EPDC)setup_epdc();
    #endif#ifdef CONFIG_FEC_MXCsetup_fec();
    #endifreturn 0;
    }
    
  • 第696行,stdio_init_tables,该函数用于stdio相关初始化。

  • 第 697行,serial_initialize,该函数初始化串口相关东西。

  • 第738行,initr_nand,该函数用于nand flash初始化,需要时调用。

  • 第744行,initr_mmc该函数用来初始化和sd/mmc相关的接口,实际调用mmc_initialize函数实现,定义在drivers/mmc/mmc.c文件中,其内容为:

    int mmc_initialize(struct bd_info *bis)
    {static int initialized = 0;int ret;if (initialized)   /* Avoid initializing mmc multiple times */return 0;initialized = 1;#if !CONFIG_IS_ENABLED(BLK)
    #if !CONFIG_IS_ENABLED(MMC_TINY)mmc_list_init();
    #endif
    #endifret = mmc_probe(bis);if (ret)return ret;#ifndef CONFIG_SPL_BUILDprint_mmc_devices(',');
    #endifmmc_do_preinit();return 0;
    }
    
  • 第744行,initr_env,该函数用来初始化环境变量。

  • 第768行,stdio_add_devices,该函数用于初始化各种输入输出设备,例如LCD相关的设备。

  • 第769行,stdio_add_devices,该函数用来初始化跳转表相关的内容。

  • 第78行,interrupt_init,该函数用来初始化中断相关内容。IMX6Q为空,需要时使用。

  • 第797行,interrupt_init,该函数用于初始化网络地址,用于获取网卡的MAC地址。

  • 第803行,board_late_init,该函数用于板级后续的一些外设初始化。

  • 第806行,initr_fastboot_setup,初始化fastboot。

  • 第820行,initr_net,初始化以太网,实际调用eth_initialize函数实现,其定义在net/eth-uclass.c文件。

  • 第859行,run_main_loop,该函数主循环函数,用于处理输入的命令,也就是uboot进入了命令行终端模式,内容为:

    static int run_main_loop(void)
    {#ifdef CONFIG_SANDBOXsandbox_main_loop_init();
    #endif/* main_loop() can return to retry autoboot, if so just run it again */for (;;)main_loop();return 0;
    }
    

    函数在无线循环执行main_loop函数,此函数将在下一小节详细介绍。

    至此board_init_r函数介绍完,主要是完成一些需要的外设初始化,不同的板子,会进行不同的初始化。

3.2.3 main_loop函数

main_loop函数主要作用是实现目标板与人的交互,其定义在common/main.c文件中,内容为:

 40 void main_loop(void)41 {42         const char *s;43 44         bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");45 46         if (IS_ENABLED(CONFIG_VERSION_VARIABLE))47                 env_set("ver", version_string);  /* set version variable */48 49         cli_init();50 51         if (IS_ENABLED(CONFIG_USE_PREBOOT))52                 run_preboot_environment_command();53 54         if (IS_ENABLED(CONFIG_UPDATE_TFTP))55                 update_tftp(0UL, NULL, NULL);56 57         if (IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK_EARLY))58                 efi_launch_capsules();59 60         s = bootdelay_process();61         if (cli_process_fdt(&s))62                 cli_secure_boot_cmd(s);63 64         autoboot_command(s);65 66         cli_loop();67         panic("No CLI available");68 }
  • 第60行,bootdelay_process,该函数获取bootdelaybootcmd参数的内容,返回值为环境变量bootcmd的值。

  • 第64行,autoboot_command,该函数的作用是,用于检测u-boot启动过程中的倒计时过程是否结束。倒计时结束之前是否被打断。函数定义在文件common/autoboot.c,其内容为:

    void autoboot_command(const char *s)
    {debug("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");if (s && (stored_bootdelay == -2 ||(stored_bootdelay != -1 && !abortboot(stored_bootdelay)))) {bool lock;int prev;lock = IS_ENABLED(CONFIG_AUTOBOOT_KEYED) &&!IS_ENABLED(CONFIG_AUTOBOOT_KEYED_CTRLC);if (lock)prev = disable_ctrlc(1); /* disable Ctrl-C checking */run_command_list(s, -1, 0);if (lock)disable_ctrlc(prev);    /* restore Ctrl-C checking */}if (IS_ENABLED(CONFIG_USE_AUTOBOOT_MENUKEY) &&menukey == AUTOBOOT_MENUKEY) {s = env_get("menucmd");if (s)run_command_list(s, -1, 0);}
    }
    

    如果倒计时正常结束,那么将执行run_command_list,此函数会执行参数s指定的一系列命令,也就是bootcmd中配置中的命令,一般配置为linux内核启动命令,因此linux内核启动。

    如果在倒计时结束前按下回车键,run_command_list就不会执行,autoboot_command相当于空函数。

    run_command_list函数定义在common/cli.c文件,其内容为:

    int run_command_list(const char *cmd, int len, int flag)
    {int need_buff = 1;char *buff = (char *)cmd;  /* cast away const */int rcode = 0;if (len == -1) {len = strlen(cmd);
    #ifdef CONFIG_HUSH_PARSER/* hush will never change our string */need_buff = 0;
    #else/* the built-in parser will change our string if it sees \n */need_buff = strchr(cmd, '\n') != NULL;
    #endif}if (need_buff) {buff = malloc(len + 1);if (!buff)return 1;memcpy(buff, cmd, len);buff[len] = '\0';}
    #ifdef CONFIG_HUSH_PARSERrcode = parse_string_outer(buff, FLAG_PARSE_SEMICOLON);
    #else
    #ifdef CONFIG_CMDLINErcode = cli_simple_run_command_list(buff, flag);
    #elsercode = board_run_command(buff);
    #endif
    #endifif (need_buff)free(buff);return rcode;
    }
    

    主要工作内容为,调用parse_string_outer函数解析并执行bootcmd中配置中的命令。

  • 第66行,cli_init,该函数是uboot命令行处理函数,输入的各种命令,进行各种操作就是cli_loop函数来处理的,函数处理过程比较复杂,就不单独分析。

至此整个uboot2021启动流程分析完成,下面介绍uboot中的串口模块。

基于IMX6Q的uboot启动流程分析(3):_main函数之relocate_code与board_init_r相关推荐

  1. u-boot启动流程分析

    u-boot启动流程分析 以smdk2410为例,分析u-boot的启动流程.u-boot的启动流程是指从cpu上电开机执行u-boot到u-boot成功加载完操作系统的过程.这一过程可以分为两个阶段 ...

  2. Exynos4412 Uboot 移植(二)—— Uboot 启动流程分析

    uboot启动流程分析如下: 第一阶段: a -- 设置cpu工作模式为SVC模式 b -- 关闭中断,mmu,cache v -- 关看门狗 d -- 初始化内存,串口 e -- 设置栈 f -- ...

  3. 基于 LPC1114 的 M0 启动流程分析

    基于LPC1114的M0启动流程分析 作者:解琛 时间:2020 年 8 月 1 日 基于LPC1114的M0启动流程分析 一..s 启动进程 1.1 堆栈配置 1.2 中断向量表 1.3 定义中断服 ...

  4. u-boot启动流程分析(1)_平台相关部分

    转自:http://www.wowotech.net/u-boot/boot_flow_1.html 1. 前言 本文将结合u-boot的"board->machine->arc ...

  5. linux uboot启动流程分析,uboot启动流程分析

    uboot版本为NXP维护的2016.03版本 下载地址为http://git.freescale.com/git/... 分析uboot的启动流程,需要编译一下uboot,然后打开链接脚本 u-bo ...

  6. am335x uboot启动流程分析

    基本指令含义 .globl _start .globl指示告诉汇编器,_start这个符号要被链接器用到,所以要在目标文件的符号表中标记它是一个全局符号 b,bl b是不带返回的跳转  bl带返回的跳 ...

  7. U-BOOT学习之2014.4版Uboot启动流程分析

    一.前言 老大给我布置了一个任务:某某项目uboot开发之usb增强ic驱动. 不知道大家看到这个任务懵不懵,反正我最开始是蒙的.后来又问了一下,才明白到底要做啥. 任务是这样的:因为这个项目的usb ...

  8. Uboot 启动流程分析

    uboot启动流程 复位CPU 设置异常向量表 设置cpu为SVC模式 但是从U-Boot方面考虑,其要做的事情是初始化系统的相关硬件资源,因此需要获取尽量多的权限,以方便操作硬件,初始化硬件. 关闭 ...

  9. 2014.4新版uboot启动流程分析

    原文 http://blog.csdn.net/skyflying2012/article/details/25804209 此处转载有稍作修改 最近开始接触uboot,现在需要将2014.4版本ub ...

最新文章

  1. 搭建Ubuntu18.04+Anaconda3.x+Pycharm+SimpleITK(三)
  2. 2020-12-09 深度学习 卷积神经网络中感受野的详细介绍
  3. MapReduce Java API实例-统计单词出现频率
  4. DAG的深度优先搜索标记
  5. 2020CCPC威海
  6. 共享单车变“私有”、被毁、被盗:用户们都看不下去了,举报!
  7. cesium three性能比较_硬金和千足金都是黄金,哪个比较好?为什么80%人都说硬金不好?...
  8. FastDfs工作笔记002---SpringBoot集成FastDfs
  9. Kafka和Unix管道的示例
  10. H5和小程序区别详解
  11. cad插件加载bplot成功用不了_Batchplot批量打印命令无效,对照情况进行解决
  12. linux 备份 网络配置,如何备份已经配置好的虚拟机linux系统的网络..._网络编辑_帮考网...
  13. linux系统下回收站,Linux怎么开启回收站功能
  14. Dynamic Head: Unifying Object Detection Heads with Attentions
  15. 深度学习需要多强的数学基础?
  16. 不定积分 定积分 计算方法
  17. 微信小程序人脸核身---快速入门到实战(附开发工具类,复制即用)
  18. 商用向南,家用向北丨DOMOTEX asia 2020地毯馆大布局
  19. Leetcode 905 c#
  20. 为什么收藏了这么多3D游戏建模教程,还是没达到可以就业接包的水准?

热门文章

  1. 中国唯一的图灵奖获得者姚期智,在清华开设的“姚班”有哪些 AI 名徒?
  2. android apk 永久root,Android 实现永久性开启adb 的root权限
  3. 计算机三级网络技术最全知识点总结三
  4. vue3基础 —— 子传父
  5. 字母c代表什么数字_字母C
  6. 实战PyQt5: 130-使用HTTP请求下载文件
  7. linux shell脚本攻略 第三章 以文件之名 find,chmod,touch,head,tail,tree,wc
  8. JSP起源、JSP的运行原理、JSP的执行过程
  9. 微信公众号--发送模板消息
  10. Maya角色UV展平技巧笔记