u-boot 学习系列 1 - SPL
u-boot这个东西从自我N年前使用到现在,变化好多,今天开始重新研究下,本系列的研究都是基于BeagleBoneBlack(bbb)开发板和 u-boot v201801版本的。
SPL介绍
在源代码中 doc/README.SPL 中说得比较明白,我这里再归纳下。
现在很多处理器都内置一个BOOT ROM,执行部分初始化,并可从各种外设和存储器中加载程序并执行,BOOT ROM中固化的程序被称为一级程序加载器,被它加载的程序就称为二级程序加载器(secondary program loader,即SPL)。其实u-boot本身就可以作为二级程序加载器,但不幸的是一般BOOT ROM之后,主存储器都是没有初始化的,例如BBB只有109K的内置RAM可用,这就限制了程序的大小,全功能的u-boot不能运行在这么小的RAM上运行。于是精简的u-boot,u-boot-spl就此问世。
SPL精简代码的方式
在 Kconfig 文件中有一个 CONFIG_SPL 的选项,使能后,就会定义 CONFIG_SPL_BUILD
Makefile层面使用 CONFIG_SPL_BUILD 选择不同的文件或文件夹进行编译,例如
ifeq ($(CONFIG_SPL_BUILD),y)
obj-y += board_spl.o
else
obj-y += board.o
endif obj-$(CONFIG_SPL_BUILD) += foo.o
而C代码层面,则使用 CONFIG_SPL_BUILD 宏来进行条件编译,例如
#ifdef CONFIG_SPL_BUILD
foo();
#endif
因为C代码中有条件编译选项,所以SPL和主u-boot代码,不能复用.o文件,所有文件必须全部重新编译。下面我们就来编译试试看(arm-linux-gnueabihf-gcc请到linaro官方网站下载,然后放到PATH中即可)
make distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=bbb-build am335x_boneblack_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=bbb-build
为了说明下问题,我把打印的输出放到这里
CHK include/config/uboot.release
Using .. as source for U-Boot
GEN ./Makefile
CHK include/generated/version_autogenerated.h
CHK include/generated/timestamp_autogenerated.h
UPD include/generated/timestamp_autogenerated.h
HOSTCC scripts/basic/fixdep
CC lib/asm-offsets.s
CHK include/generated/generic-asm-offsets.h
CC arch/arm/lib/asm-offsets.s
CHK include/generated/asm-offsets.h
HOSTCC tools/gen_eth_addr
HOSTCC tools/gen_ethaddr_crc.o
WRAP tools/lib/crc8.c
HOSTCC tools/lib/crc8.o
HOSTLD tools/gen_ethaddr_crc
HOSTCC tools/img2srec
HOSTCC tools/mkenvimage.o
HOSTCC tools/os_support.o
WRAP tools/lib/crc32.c
HOSTCC tools/lib/crc32.o
HOSTLD tools/mkenvimage
HOSTCC tools/aisimage.o
HOSTCC tools/atmelimage.o
WRAP tools/common/bootm.c
HOSTCC tools/common/bootm.o
HOSTCC tools/default_image.o
WRAP tools/lib/fdtdec_common.c
HOSTCC tools/lib/fdtdec_common.o
WRAP tools/lib/fdtdec.c
HOSTCC tools/lib/fdtdec.o
HOSTCC tools/fit_common.o
HOSTCC tools/fit_image.o
WRAP tools/common/image-fit.c
HOSTCC tools/common/image-fit.o
HOSTCC tools/image-host.o
WRAP tools/common/image.c
HOSTCC tools/common/image.o
HOSTCC tools/imagetool.o
HOSTCC tools/imximage.o
HOSTCC tools/kwbimage.o
WRAP tools/lib/md5.c
HOSTCC tools/lib/md5.o
HOSTCC tools/lpc32xximage.o
HOSTCC tools/mxsimage.o
HOSTCC tools/omapimage.o
HOSTCC tools/pblimage.o
HOSTCC tools/pbl_crc32.o
HOSTCC tools/vybridimage.o
WRAP tools/lib/rc4.c
HOSTCC tools/lib/rc4.o
HOSTCC tools/rkcommon.o
HOSTCC tools/rkimage.o
HOSTCC tools/rksd.o
HOSTCC tools/rkspi.o
HOSTCC tools/socfpgaimage.o
WRAP tools/lib/sha1.c
HOSTCC tools/lib/sha1.o
WRAP tools/lib/sha256.c
HOSTCC tools/lib/sha256.o
WRAP tools/common/hash.c
HOSTCC tools/common/hash.o
HOSTCC tools/ublimage.o
HOSTCC tools/zynqimage.o
HOSTCC tools/zynqmpimage.o
HOSTCC tools/libfdt/fdt.o
HOSTCC tools/libfdt/fdt_wip.o
HOSTCC tools/libfdt/fdt_sw.o
HOSTCC tools/libfdt/fdt_strerror.o
HOSTCC tools/libfdt/fdt_empty_tree.o
HOSTCC tools/libfdt/fdt_addresses.o
HOSTCC tools/libfdt/fdt_overlay.o
WRAP tools/lib/libfdt/fdt_ro.c
HOSTCC tools/lib/libfdt/fdt_ro.o
WRAP tools/lib/libfdt/fdt_rw.c
HOSTCC tools/lib/libfdt/fdt_rw.o
WRAP tools/lib/libfdt/fdt_region.c
HOSTCC tools/lib/libfdt/fdt_region.o
HOSTCC tools/gpimage.o
HOSTCC tools/gpimage-common.o
HOSTCC tools/dumpimage.o
HOSTLD tools/dumpimage
HOSTCC tools/mkimage.o
HOSTLD tools/mkimage
HOSTCC tools/proftool
HOSTCC tools/fdtgrep.o
HOSTLD tools/fdtgrep
LD arch/arm/cpu/built-in.o
CC arch/arm/cpu/armv7/cache_v7.o
AS arch/arm/cpu/armv7/cache_v7_asm.o
CC arch/arm/cpu/armv7/cpu.o
CC arch/arm/cpu/armv7/cp15.o
CC arch/arm/cpu/armv7/syslib.o
LD arch/arm/cpu/armv7/built-in.o
AS arch/arm/cpu/armv7/start.o
AS arch/arm/lib/vectors.o
AS arch/arm/lib/crt0.o
AS arch/arm/lib/setjmp.o
AS arch/arm/lib/relocate.o
CC arch/arm/lib/bootm-fdt.o
CC arch/arm/lib/bootm.o
CC arch/arm/lib/zimage.o
AS arch/arm/lib/memset.o
AS arch/arm/lib/memcpy.o
CC arch/arm/lib/sections.o
CC arch/arm/lib/stack.o
CC arch/arm/lib/interrupts.o
CC arch/arm/lib/reset.o
CC arch/arm/lib/cache.o
CC arch/arm/lib/cache-cp15.o
CC arch/arm/lib/psci-dt.o
LD arch/arm/lib/built-in.o
AS arch/arm/lib/ashldi3.o
AS arch/arm/lib/ashrdi3.o
CC arch/arm/lib/div0.o
AS arch/arm/lib/div64.o
AS arch/arm/lib/lib1funcs.o
AS arch/arm/lib/lshrdi3.o
AS arch/arm/lib/muldi3.o
AS arch/arm/lib/uldivmod.o
AR arch/arm/lib/lib.a
CC arch/arm/lib/eabi_compat.o
AS arch/arm/lib/crt0_arm_efi.o
CC arch/arm/lib/reloc_arm_efi.o
CC arch/arm/mach-omap2/am33xx/clock_am33xx.o
CC arch/arm/mach-omap2/am33xx/clock.o
CC arch/arm/mach-omap2/am33xx/sys_info.o
CC arch/arm/mach-omap2/am33xx/ddr.o
CC arch/arm/mach-omap2/am33xx/board.o
CC arch/arm/mach-omap2/am33xx/mux.o
CC arch/arm/mach-omap2/am33xx/prcm-regs.o
CC arch/arm/mach-omap2/am33xx/hw_data.o
CC arch/arm/mach-omap2/am33xx/fdt.o
CC arch/arm/mach-omap2/am33xx/clk_synthesizer.o
LD arch/arm/mach-omap2/am33xx/built-in.o
CC arch/arm/mach-omap2/reset.o
CC arch/arm/mach-omap2/timer.o
CC arch/arm/mach-omap2/utils.o
CC arch/arm/mach-omap2/sysinfo-common.o
CC arch/arm/mach-omap2/omap-cache.o
CC arch/arm/mach-omap2/boot-common.o
AS arch/arm/mach-omap2/lowlevel_init.o
CC arch/arm/mach-omap2/mem-common.o
CC arch/arm/mach-omap2/fdt-common.o
LD arch/arm/mach-omap2/built-in.o
CC board/ti/am335x/board.o
LD board/ti/am335x/built-in.o
CC board/ti/common/board_detect.o
LD board/ti/common/built-in.o
CC cmd/boot.o
CC cmd/bootm.o
CC cmd/help.o
CC cmd/version.o
CC cmd/blk_common.o
CC cmd/source.o
CC cmd/bdinfo.o
CC cmd/bootefi.o
CC cmd/bootz.o
CC cmd/console.o
CC cmd/echo.o
CC cmd/eeprom.o
CC cmd/elf.o
CC cmd/exit.o
CC cmd/ext4.o
CC cmd/ext2.o
CC cmd/fat.o
CC cmd/fdt.o
CC cmd/fs.o
CC cmd/gpio.o
CC cmd/i2c.o
CC cmd/itest.o
CC cmd/load.o
CC cmd/mem.o
CC cmd/mii.o
CC cmd/mdio.o
CC cmd/misc.o
CC cmd/mmc.o
CC cmd/net.o
CC cmd/part.o
CC cmd/pcmcia.o
CC cmd/pxe.o
CC cmd/sf.o
CC cmd/spi.o
CC cmd/time.o
CC cmd/test.o
CC cmd/usb.o
CC cmd/disk.o
CC cmd/fastboot.o
CC cmd/ximg.o
CC cmd/spl.o
CC cmd/dfu.o
CC cmd/gpt.o
CC cmd/nvedit.o
LD cmd/built-in.o
CC common/init/board_init.o
LD common/init/built-in.o
CC common/main.o
CC common/exports.o
CC common/hash.o
CC common/cli_hush.o
CC common/autoboot.o
CC common/board_f.o
CC common/board_r.o
CC common/board_info.o
CC common/bootm.o
CC common/bootm_os.o
CC common/fdt_support.o
CC common/miiphyutil.o
CC common/usb.o
CC common/usb_hub.o
CC common/usb_storage.o
CC common/splash.o
CC common/menu.o
CC common/update.o
CC common/cli_readline.o
CC common/cli_simple.o
CC common/console.o
CC common/dlmalloc.o
CC common/malloc_simple.o
CC common/image.o
CC common/image-android.o
CC common/image-fdt.o
CC common/image-fit.o
CC common/memsize.o
CC common/stdio.o
CC common/cli.o
CC common/dfu.o
CC common/command.o
CC common/s_record.o
CC common/xyzModem.o
LD common/built-in.o
CC disk/part.o
CC disk/part_dos.o
CC disk/part_iso.o
CC disk/part_efi.o
LD disk/built-in.o
LD drivers/adc/built-in.o
LD drivers/ata/built-in.o
CC drivers/block/blk_legacy.o
LD drivers/block/built-in.o
CC drivers/bootcount/bootcount.o
CC drivers/bootcount/bootcount_davinci.o
LD drivers/bootcount/built-in.o
CC drivers/core/device.o
CC drivers/core/fdtaddr.o
CC drivers/core/lists.o
CC drivers/core/root.o
CC drivers/core/uclass.o
CC drivers/core/util.o
CC drivers/core/device-remove.o
CC drivers/core/dump.o
LD drivers/core/built-in.o
CC drivers/crypto/fsl/sec.o
LD drivers/crypto/fsl/built-in.o
LD drivers/crypto/rsa_mod_exp/built-in.o
LD drivers/crypto/built-in.o
CC drivers/dfu/dfu.o
CC drivers/dfu/dfu_mmc.o
CC drivers/dfu/dfu_ram.o
CC drivers/dfu/dfu_tftp.o
LD drivers/dfu/built-in.o
LD drivers/firmware/built-in.o
CC drivers/input/input.o
LD drivers/input/built-in.o
LD drivers/mailbox/built-in.o
LD drivers/memory/built-in.o
LD drivers/misc/built-in.o
CC drivers/mmc/mmc.o
CC drivers/mmc/mmc_legacy.o
CC drivers/mmc/mmc_write.o
CC drivers/mmc/omap_hsmmc.o
LD drivers/mmc/built-in.o
LD drivers/pcmcia/built-in.o
LD drivers/phy/marvell/built-in.o
LD drivers/pwm/built-in.o
LD drivers/reset/built-in.o
CC drivers/rtc/date.o
LD drivers/rtc/built-in.o
LD drivers/scsi/built-in.o
LD drivers/soc/built-in.o
LD drivers/sound/built-in.o
LD drivers/spmi/built-in.o
LD drivers/sysreset/built-in.o
LD drivers/thermal/built-in.o
LD drivers/tpm/built-in.o
LD drivers/video/bridge/built-in.o
LD drivers/video/sunxi/built-in.o
LD drivers/video/built-in.o
CC drivers/watchdog/omap_wdt.o
LD drivers/watchdog/built-in.o
LD drivers/built-in.o
LD drivers/dma/built-in.o
CC drivers/gpio/gpio-uclass.o
CC drivers/gpio/omap_gpio.o
LD drivers/gpio/built-in.o
CC drivers/i2c/i2c_core.o
CC drivers/i2c/omap24xx_i2c.o
LD drivers/i2c/built-in.o
CC drivers/mtd/mtdcore.o
CC drivers/mtd/mtd_uboot.o
LD drivers/mtd/built-in.o
LD drivers/mtd/onenand/built-in.o
CC drivers/mtd/spi/sf_probe.o
CC drivers/mtd/spi/spi_flash.o
CC drivers/mtd/spi/spi_flash_ids.o
CC drivers/mtd/spi/sf.o
LD drivers/mtd/spi/built-in.o
CC drivers/net/cpsw.o
CC drivers/net/cpsw-common.o
LD drivers/net/built-in.o
CC drivers/net/phy/phy.o
CC drivers/net/phy/atheros.o
CC drivers/net/phy/smsc.o
LD drivers/net/phy/built-in.o
LD drivers/pci/built-in.o
LD drivers/power/built-in.o
LD drivers/power/battery/built-in.o
LD drivers/power/domain/built-in.o
LD drivers/power/fuel_gauge/built-in.o
LD drivers/power/mfd/built-in.o
CC drivers/power/pmic/pmic_tps65217.o
CC drivers/power/pmic/pmic_tps65910.o
LD drivers/power/pmic/built-in.o
LD drivers/power/regulator/built-in.o
CC drivers/serial/serial-uclass.o
CC drivers/serial/ns16550.o
LD drivers/serial/built-in.o
CC drivers/spi/spi.o
CC drivers/spi/omap3_spi.o
LD drivers/spi/built-in.o
LD drivers/usb/common/built-in.o
LD drivers/usb/dwc3/built-in.o
LD drivers/usb/emul/built-in.o
LD drivers/usb/eth/built-in.o
CC drivers/usb/gadget/epautoconf.o
CC drivers/usb/gadget/config.o
CC drivers/usb/gadget/usbstring.o
CC drivers/usb/gadget/g_dnl.o
CC drivers/usb/gadget/f_dfu.o
CC drivers/usb/gadget/f_fastboot.o
CC drivers/usb/gadget/ether.o
CC drivers/usb/gadget/rndis.o
LD drivers/usb/gadget/built-in.o
LD drivers/usb/gadget/udc/built-in.o
LD drivers/usb/host/built-in.o
CC drivers/usb/musb-new/musb_gadget.o
CC drivers/usb/musb-new/musb_gadget_ep0.o
CC drivers/usb/musb-new/musb_core.o
CC drivers/usb/musb-new/musb_uboot.o
CC drivers/usb/musb-new/musb_host.o
CC drivers/usb/musb-new/musb_dsps.o
LD drivers/usb/musb-new/built-in.o
LD drivers/usb/musb/built-in.o
LD drivers/usb/phy/built-in.o
LD drivers/usb/ulpi/built-in.o
CC env/common.o
CC env/env.o
CC env/attr.o
CC env/callback.o
CC env/flags.o
CC env/mmc.o
LD env/built-in.o
CC fs/fs.o
CC fs/ext4/ext4fs.o
CC fs/ext4/ext4_common.o
CC fs/ext4/dev.o
CC fs/ext4/ext4_write.o
CC fs/ext4/ext4_journal.o
CC fs/ext4/crc16.o
LD fs/ext4/built-in.o
CC fs/fat/fat_write.o
LD fs/fat/built-in.o
CC fs/fs_internal.o
LD fs/built-in.o
CC lib/efi_loader/efi_image_loader.o
CC lib/efi_loader/efi_boottime.o
CC lib/efi_loader/efi_runtime.o
CC lib/efi_loader/efi_console.o
CC lib/efi_loader/efi_memory.o
CC lib/efi_loader/efi_device_path_to_text.o
CC lib/efi_loader/efi_device_path.o
CC lib/efi_loader/efi_file.o
CC lib/efi_loader/efi_variable.o
CC lib/efi_loader/efi_bootmgr.o
CC lib/efi_loader/efi_watchdog.o
CC lib/efi_loader/efi_disk.o
CC lib/efi_loader/efi_net.o
CC lib/efi_loader/efi_smbios.o
LD lib/efi_loader/built-in.o
CC lib/efi_loader/helloworld.o
LD lib/efi_loader/helloworld_efi.so
OBJCOPY lib/efi_loader/helloworld.efi
rm lib/efi_loader/helloworld_efi.so lib/efi_loader/helloworld.o
LD lib/efi_selftest/built-in.o
CC lib/libfdt/fdt.o
CC lib/libfdt/fdt_wip.o
CC lib/libfdt/fdt_strerror.o
CC lib/libfdt/fdt_sw.o
CC lib/libfdt/fdt_empty_tree.o
CC lib/libfdt/fdt_addresses.o
CC lib/libfdt/fdt_overlay.o
CC lib/libfdt/fdt_ro.o
CC lib/libfdt/fdt_rw.o
CC lib/libfdt/fdt_region.o
LD lib/libfdt/built-in.o
CC lib/lzo/lzo1x_decompress.o
LD lib/lzo/built-in.o
CC lib/zlib/zlib.o
LD lib/zlib/built-in.o
CC lib/charset.o
CC lib/crc7.o
CC lib/crc8.o
CC lib/crc16.o
CC lib/fdtdec_common.o
CC lib/smbios.o
CC lib/initcall.o
CC lib/lmb.o
CC lib/ldiv.o
CC lib/md5.o
CC lib/net_utils.o
CC lib/qsort.o
CC lib/rc4.o
CC lib/list_sort.o
CC lib/sha1.o
CC lib/sha256.o
CC lib/gunzip.o
CC lib/hashtable.o
CC lib/errno.o
CC lib/display_options.o
CC lib/crc32.o
CC lib/ctype.o
CC lib/div64.o
CC lib/hang.o
CC lib/linux_compat.o
CC lib/linux_string.o
CC lib/membuff.o
CC lib/slre.o
CC lib/string.o
CC lib/tables_csum.o
CC lib/time.o
CC lib/uuid.o
CC lib/rand.o
CC lib/vsprintf.o
CC lib/panic.o
CC lib/strto.o
CC lib/strmhz.o
LD lib/built-in.o
CC net/checksum.o
CC net/arp.o
CC net/bootp.o
CC net/eth_legacy.o
CC net/eth_common.o
CC net/net.o
CC net/nfs.o
CC net/ping.o
CC net/tftp.o
LD net/built-in.o
LD test/built-in.o
CC test/dm/cmd_dm.o
LD test/dm/built-in.o
CC examples/standalone/stubs.o
LD examples/standalone/libstubs.o
CC examples/standalone/hello_world.o
LD examples/standalone/hello_world
OBJCOPY examples/standalone/hello_world.srec
OBJCOPY examples/standalone/hello_world.bin
LDS u-boot.lds
LD u-boot
OBJCOPY u-boot-nodtb.bin
COPY u-boot.bin
MKIMAGE u-boot.img
OBJCOPY u-boot.srec
SYM u-boot.sym
/bin/sh: : bc: not found
CC spl/arch/arm/mach-omap2/am33xx/clock_am33xx.o
CC spl/arch/arm/mach-omap2/am33xx/clock.o
CC spl/arch/arm/mach-omap2/am33xx/sys_info.o
CC spl/arch/arm/mach-omap2/am33xx/ddr.o
CC spl/arch/arm/mach-omap2/am33xx/emif4.o
CC spl/arch/arm/mach-omap2/am33xx/board.o
CC spl/arch/arm/mach-omap2/am33xx/mux.o
CC spl/arch/arm/mach-omap2/am33xx/prcm-regs.o
CC spl/arch/arm/mach-omap2/am33xx/hw_data.o
CC spl/arch/arm/mach-omap2/am33xx/fdt.o
CC spl/arch/arm/mach-omap2/am33xx/clk_synthesizer.o
LD spl/arch/arm/mach-omap2/am33xx/built-in.o
CC spl/arch/arm/mach-omap2/reset.o
CC spl/arch/arm/mach-omap2/timer.o
CC spl/arch/arm/mach-omap2/utils.o
CC spl/arch/arm/mach-omap2/sysinfo-common.o
CC spl/arch/arm/mach-omap2/omap-cache.o
CC spl/arch/arm/mach-omap2/boot-common.o
AS spl/arch/arm/mach-omap2/lowlevel_init.o
CC spl/arch/arm/mach-omap2/mem-common.o
CC spl/arch/arm/mach-omap2/fdt-common.o
LD spl/arch/arm/mach-omap2/built-in.o
CC spl/arch/arm/cpu/armv7/cache_v7.o
AS spl/arch/arm/cpu/armv7/cache_v7_asm.o
CC spl/arch/arm/cpu/armv7/cpu.o
CC spl/arch/arm/cpu/armv7/cp15.o
CC spl/arch/arm/cpu/armv7/syslib.o
AS spl/arch/arm/cpu/armv7/lowlevel_init.o
LD spl/arch/arm/cpu/armv7/built-in.o
AS spl/arch/arm/cpu/armv7/start.o
LD spl/arch/arm/cpu/built-in.o
AS spl/arch/arm/lib/vectors.o
AS spl/arch/arm/lib/crt0.o
AS spl/arch/arm/lib/setjmp.o
CC spl/arch/arm/lib/spl.o
CC spl/arch/arm/lib/zimage.o
CC spl/arch/arm/lib/bootm-fdt.o
AS spl/arch/arm/lib/memset.o
AS spl/arch/arm/lib/memcpy.o
CC spl/arch/arm/lib/sections.o
CC spl/arch/arm/lib/stack.o
CC spl/arch/arm/lib/interrupts.o
CC spl/arch/arm/lib/reset.o
CC spl/arch/arm/lib/cache.o
CC spl/arch/arm/lib/cache-cp15.o
CC spl/arch/arm/lib/psci-dt.o
LD spl/arch/arm/lib/built-in.o
AS spl/arch/arm/lib/ashldi3.o
AS spl/arch/arm/lib/ashrdi3.o
CC spl/arch/arm/lib/div0.o
AS spl/arch/arm/lib/div64.o
AS spl/arch/arm/lib/lib1funcs.o
AS spl/arch/arm/lib/lshrdi3.o
AS spl/arch/arm/lib/muldi3.o
AS spl/arch/arm/lib/uldivmod.o
AR spl/arch/arm/lib/lib.a
CC spl/arch/arm/lib/eabi_compat.o
AS spl/arch/arm/lib/crt0_arm_efi.o
CC spl/arch/arm/lib/reloc_arm_efi.o
CC spl/board/ti/am335x/mux.o
CC spl/board/ti/am335x/board.o
LD spl/board/ti/am335x/built-in.o
CC spl/board/ti/common/board_detect.o
LD spl/board/ti/common/built-in.o
CC spl/common/spl/spl.o
CC spl/common/spl/spl_ymodem.o
CC spl/common/spl/spl_mmc.o
CC spl/common/spl/spl_fat.o
CC spl/common/spl/spl_ext.o
LD spl/common/spl/built-in.o
CC spl/common/init/board_init.o
LD spl/common/init/built-in.o
CC spl/common/xyzModem.o
CC spl/common/fdt_support.o
CC spl/common/console.o
CC spl/common/dlmalloc.o
CC spl/common/malloc_simple.o
CC spl/common/image.o
CC spl/common/image-android.o
CC spl/common/image-fdt.o
CC spl/common/memsize.o
CC spl/common/stdio.o
CC spl/common/cli.o
CC spl/common/dfu.o
CC spl/common/command.o
CC spl/common/s_record.o
LD spl/common/built-in.o
CC spl/cmd/nvedit.o
LD spl/cmd/built-in.o
CC spl/env/common.o
CC spl/env/env.o
CC spl/env/attr.o
CC spl/env/flags.o
CC spl/env/callback.o
CC spl/env/mmc.o
LD spl/env/built-in.o
CC spl/lib/sha1.o
CC spl/lib/sha256.o
CC spl/lib/libfdt/fdt.o
CC spl/lib/libfdt/fdt_wip.o
CC spl/lib/libfdt/fdt_strerror.o
CC spl/lib/libfdt/fdt_sw.o
CC spl/lib/libfdt/fdt_empty_tree.o
CC spl/lib/libfdt/fdt_addresses.o
CC spl/lib/libfdt/fdt_overlay.o
CC spl/lib/libfdt/fdt_ro.o
CC spl/lib/libfdt/fdt_rw.o
CC spl/lib/libfdt/fdt_region.o
LD spl/lib/libfdt/built-in.o
CC spl/lib/crc16.o
CC spl/lib/hashtable.o
CC spl/lib/errno.o
CC spl/lib/display_options.o
CC spl/lib/crc32.o
CC spl/lib/ctype.o
CC spl/lib/div64.o
CC spl/lib/hang.o
CC spl/lib/linux_compat.o
CC spl/lib/linux_string.o
CC spl/lib/membuff.o
CC spl/lib/slre.o
CC spl/lib/string.o
CC spl/lib/tables_csum.o
CC spl/lib/time.o
CC spl/lib/uuid.o
CC spl/lib/rand.o
CC spl/lib/tiny-printf.o
CC spl/lib/panic.o
CC spl/lib/strto.o
LD spl/lib/built-in.o
CC spl/disk/part.o
CC spl/disk/part_dos.o
CC spl/disk/part_iso.o
CC spl/disk/part_efi.o
LD spl/disk/built-in.o
CC spl/drivers/block/blk_legacy.o
LD spl/drivers/block/built-in.o
CC spl/drivers/core/device.o
CC spl/drivers/core/fdtaddr.o
CC spl/drivers/core/lists.o
CC spl/drivers/core/root.o
CC spl/drivers/core/uclass.o
CC spl/drivers/core/util.o
CC spl/drivers/core/dump.o
LD spl/drivers/core/built-in.o
CC spl/drivers/gpio/gpio-uclass.o
CC spl/drivers/gpio/omap_gpio.o
LD spl/drivers/gpio/built-in.o
CC spl/drivers/i2c/i2c_core.o
CC spl/drivers/i2c/omap24xx_i2c.o
LD spl/drivers/i2c/built-in.o
CC spl/drivers/mmc/mmc.o
CC spl/drivers/mmc/mmc_legacy.o
CC spl/drivers/mmc/omap_hsmmc.o
LD spl/drivers/mmc/built-in.o
LD spl/drivers/power/built-in.o
CC spl/drivers/power/pmic/pmic_tps65217.o
CC spl/drivers/power/pmic/pmic_tps65910.o
LD spl/drivers/power/pmic/built-in.o
LD spl/drivers/power/regulator/built-in.o
CC spl/drivers/serial/serial-uclass.o
CC spl/drivers/serial/ns16550.o
LD spl/drivers/serial/built-in.o
CC spl/drivers/usb/musb-new/musb_gadget.o
CC spl/drivers/usb/musb-new/musb_gadget_ep0.o
CC spl/drivers/usb/musb-new/musb_core.o
CC spl/drivers/usb/musb-new/musb_uboot.o
CC spl/drivers/usb/musb-new/musb_host.o
CC spl/drivers/usb/musb-new/musb_dsps.o
LD spl/drivers/usb/musb-new/built-in.o
CC spl/drivers/watchdog/omap_wdt.o
LD spl/drivers/watchdog/built-in.o
LD spl/drivers/built-in.o
LD spl/dts/built-in.o
CC spl/fs/ext4/ext4fs.o
CC spl/fs/ext4/ext4_common.o
CC spl/fs/ext4/dev.o
CC spl/fs/ext4/ext4_write.o
CC spl/fs/ext4/ext4_journal.o
CC spl/fs/ext4/crc16.o
LD spl/fs/ext4/built-in.o
CC spl/fs/fat/fat_write.o
LD spl/fs/fat/built-in.o
CC spl/fs/fs_internal.o
LD spl/fs/built-in.o
LDS spl/u-boot-spl.lds
LD spl/u-boot-spl
OBJCOPY spl/u-boot-spl-nodtb.bin
COPY spl/u-boot-spl.bin
MKIMAGE MLO
MKIMAGE MLO.byteswap
CHK include/config.h
CFG u-boot.cfg
CFGCHK u-boot.cfg
以spl/打头的都是spl相关的编译,在输出的后半部分,大家可以看到 475行和125 行编译的是同一个C文件,一个是u-boot,一个是u-boot-spl
SPL的其他配置项
由于现在u-boot同时使用Kconfig和老的头文件方式进行配置,下面很多配置在BBB中仍然是在头文件中配置的。
- CONFIG_SPL_TEXT_BASE SPL的入口地址
- CONFIG_SPL_LDSCRIPT SPL的链接脚本
除了板子特有的代码外,如果要使用u-boot通用的库或驱动,还需要定义 CONFIG_SPL_XXX_SUPPORT,当前支持如下配置
- CONFIG_SPL_LIBCOMMON_SUPPORT (common/libcommon.o)
- CONFIG_SPL_LIBDISK_SUPPORT (disk/libdisk.o)
- CONFIG_SPL_I2C_SUPPORT (drivers/i2c/libi2c.o)
- CONFIG_SPL_GPIO_SUPPORT (drivers/gpio/libgpio.o)
- CONFIG_SPL_MMC_SUPPORT (drivers/mmc/libmmc.o)
- CONFIG_SPL_SERIAL_SUPPORT (drivers/serial/libserial.o)
- CONFIG_SPL_SPI_FLASH_SUPPORT (drivers/mtd/spi/libspi_flash.o)
- CONFIG_SPL_SPI_SUPPORT (drivers/spi/libspi.o)
- CONFIG_SPL_FAT_SUPPORT (fs/fat/libfat.o)
- CONFIG_SPL_EXT_SUPPORT
- CONFIG_SPL_LIBGENERIC_SUPPORT (lib/libgeneric.o)
- CONFIG_SPL_POWER_SUPPORT (drivers/power/libpower.o)
- CONFIG_SPL_NAND_SUPPORT (drivers/mtd/nand/libnand.o)
- CONFIG_SPL_DRIVERS_MISC_SUPPORT (drivers/misc)
- CONFIG_SPL_DMA_SUPPORT (drivers/dma/libdma.o)
- CONFIG_SPL_POST_MEM_SUPPORT (post/drivers/memory.o)
- CONFIG_SPL_NAND_LOAD (drivers/mtd/nand/nand_spl_load.o)
- CONFIG_SPL_SPI_LOAD (drivers/mtd/spi/spi_spl_load.o)
- CONFIG_SPL_RAM_DEVICE (common/spl/spl.c)
- CONFIG_SPL_WATCHDOG_SUPPORT (drivers/watchdog/libwatchdog.o)
SPL 编译分析
u-boot在最近几年引入了Linux内核的Kconfig方式,主要介绍在源代码的 doc/README.kconfig 中,u-boot的目标是把所有配置都放到Kconfig中去,但是目前仍然有大量配置是写在头文件中的。在目前的情况下,C文件中可使用的配置文件是
- include/generated/autoconf.h (generated by Kconfig for Normal)
- include/configs/<target>.h (exists for all boards) 例如:bbb的target为 am335x_evm
Makefile中可使用的配置文件是
- include/config/auto.conf (generated by Kconfig)
- include/autoconf.mk (generated by the old config for Normal)
- spl/include/autoconfig.mk (generated by the old config for SPL)
- tpl/include/autoconfig.mk (generated by the old config for TPL) (注意:TPL跟SPL差不多,是第三级程序加载器,也是一个精简版的u-boot,很少用到,参见 doc/README.TPL)
板级相关的代码都在哪里
- CONFIG_SYS_CPU="cpu" 将会编译 arch/<arch>/cpu/<cpu>
- CONFIG_SYS_SOC="soc" 将会编译 arch/<arch>/cpu/<cpu>/<soc>
- CONFIG_SYS_VENDOR="vendor" 将会编译 board/<vendor>/common/* 和 board/<vendor>/<board>/*
- CONFIG_SYS_BOARD="board" 将会编译 board/<board>/* (或 board/<vendor>/<board>/* 如果 CONFIG_SYS_VENDOR 也定义了)
- CONFIG_SYS_CONFIG_NAME="target" 将包含 include/configs/<target>.h
- 在 arch/<arch>/Kconfig 或 arch/<arch>/*/Kconfig 中应 source 板级相关的 Kconfig 文件来编译更多的文件
对于BBB开发板来说,可以查看 am335x_boneblack_defconfig:
- <arch> = arm
- <cpu> = armv7
- <soc> = am33xx
- <vendor> = ti
- <board> = am335x
- <target> = am335x_evm
对照上面,BBB板级相关的代码包括以下文件夹中
- arch/arm/cpu/armv7
- arch/arm/cpu/armv7/am33xx(无此文件夹)取而代之的是 arch/arm/mach-omap2/am33xx ,这是因为 arch/arm/mach-omap2/Kconfig 中 source 了 arch/arm/mach-omap2/am33xx/Kconfig 和 board/ti/am335x/Kconfig
- board/ti/common
- board/ti/am335x
- 配置的头文件为 includes/configs/am335x_evm.h
对照下上面实际编译输出,基本上差不多,除了多了一个 arch/arm/mach-omap2/* ,参见下文 (machine-$(CONFIG_ARCH_OMAP2PLUS))。
Makefile简述
u-boot根目录中的Makefile包含如下语句
ALL-$(CONFIG_SPL) += spl/u-boot-spl.bin spl/u-boot-spl.bin: spl/u-boot-spl
@:
spl/u-boot-spl: tools prepare \
$(if $(CONFIG_OF_SEPARATE)$(CONFIG_OF_EMBED)$(CONFIG_SPL_OF_PLATDATA),dts/dt.dtb) \
$(if $(CONFIG_OF_SEPARATE)$(CONFIG_OF_EMBED)$(CONFIG_TPL_OF_PLATDATA),dts/dt.dtb)
$(Q)$(MAKE) obj=spl -f $(srctree)/scripts/Makefile.spl all
而Makefile.spl首先包含了源代码树根目录的 config.mk,这个文件根据配置定义了ARCH、CPU、SOC、BOARD、VENDOR、CPUDIR、BOARDDIR等板级相关的变量,并包含了 ARCH、CPU、SOC、BOARD等板级相关的文件夹中的config.mk,以便添加或覆盖默认配置。配置确定后,Makefile.spl中定义了spl的各依赖,其中libs-y是spl需要编译的库(即子文件夹)
u-boot-spl-dirs := $(patsubst %/,%,$(filter %/, $(libs-y)))
u-boot-spl-init := $(head-y)
# 注意:最后libs-y被转换为对应目录的 built-in.o,参见下文中对 Makefile.build 的分析
libs-y := $(patsubst %/, %/built-in.o, $(libs-y))
u-boot-spl-main := $(libs-y) $(obj)/$(SPL_BIN): $(u-boot-spl-platdata) $(u-boot-spl-init) \
$(u-boot-spl-main) $(obj)/u-boot-spl.lds FORCE
$(call if_changed,u-boot-spl) # May be overridden by arch/$(ARCH)/config.mk
# 这是 $(call if_changed,u-boot-spl) 实际执行的命令
quiet_cmd_u-boot-spl ?= LD $@
cmd_u-boot-spl ?= (cd $(obj) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) \
$(patsubst $(obj)/%,%,$(u-boot-spl-init)) --start-group \
$(patsubst $(obj)/%,%,$(u-boot-spl-main)) \
$(patsubst $(obj)/%,%,$(u-boot-spl-platdata)) \
--end-group \
$(PLATFORM_LIBS) -Map $(SPL_BIN).map -o $(SPL_BIN))
其中 link script的查找方法是
ifeq ($(wildcard $(LDSCRIPT)),)
LDSCRIPT := $(srctree)/board/$(BOARDDIR)/u-boot-spl.lds
endif
ifeq ($(wildcard $(LDSCRIPT)),)
LDSCRIPT := $(srctree)/$(CPUDIR)/u-boot-spl.lds
endif
ifeq ($(wildcard $(LDSCRIPT)),)
LDSCRIPT := $(srctree)/arch/$(ARCH)/cpu/u-boot-spl.lds
endif
ifeq ($(wildcard $(LDSCRIPT)),)
$(error could not find linker script)
endif
即,依次查找 BOARD、CPU、ARCH目录,第一个发现的u-boot-spl.lds文件。
大部分libs都是在Makefile.spl中直接定义的,如下
libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/)
libs-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/ libs-$(CONFIG_SPL_FRAMEWORK) += common/spl/
libs-y += common/init/ # Special handling for a few options which support SPL/TPL
ifeq ($(CONFIG_TPL_BUILD),y)
libs-$(CONFIG_TPL_LIBCOMMON_SUPPORT) += common/ cmd/ env/
libs-$(CONFIG_TPL_LIBGENERIC_SUPPORT) += lib/
else
libs-$(CONFIG_SPL_LIBCOMMON_SUPPORT) += common/ cmd/ env/
libs-$(CONFIG_SPL_LIBGENERIC_SUPPORT) += lib/
endif libs-$(CONFIG_SPL_LIBDISK_SUPPORT) += disk/
libs-y += drivers/
libs-$(CONFIG_SPL_USB_GADGET_SUPPORT) += drivers/usb/dwc3/
libs-y += dts/
libs-y += fs/
libs-$(CONFIG_SPL_POST_MEM_SUPPORT) += post/drivers/
libs-$(CONFIG_SPL_NET_SUPPORT) += net/
但是有一部分是ARCH和CPU相关的是在 arch/arm/Makefile中定义的
# head-y 也是在这个文件中定义的
head-y := arch/arm/cpu/$(CPU)/start.o # 注意:这就是为什么BBB会编译 mach-omap2 文件夹了
machine-$(CONFIG_ARCH_OMAP2PLUS) += omap2 machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y)) libs-y += $(machdirs) libs-y += arch/arm/cpu/$(CPU)/
libs-y += arch/arm/cpu/
libs-y += arch/arm/lib/
最后要说明下,这些lib-y的子文件夹是如何编译的
$(u-boot-spl-dirs): $(u-boot-spl-platdata)
$(Q)$(MAKE) $(build)=$@
上面这句话非常简洁,但包含的内容却很多,注意是 $(build)=$@ 而不是 build=$@,build是kbuild.include中定义的一个变量,其值是
build := -f $(srctree)/scripts/Makefile.build obj
对u-boot-spl-dirs中的每一个子目录,展开了之后是
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.build obj=目录
Makefile.build是Kbuild体系的核心文件,文件夹的编译都是通过这个文件来完成的,理解这个文件我认为需要知道几个要点:
- 这个文件包含了 Kbuild.include 和 Makefile.lib,这两个文件定义了很多实用函数、变量和通用的规则,一般位置找不到的东西都在这里
- 这个文件包含了 obj=目录 中的 Kbuild或Makefile文件,这样我们再写某个目录中的Kbuild或Makefile时就比较简单了,我们只需要定义
- obj-y:本目录中的源文件
- subdir-y:需要递归编译的子目录
- extra-y:额外要执行的编译目标
- 一个目录中的所有源文件及子目录的编译结果最终会LD成一个 built-in.o
- subdir-y中的目录又会使用 Makefile.build 递归编译
# 至少有lib-y lib-m lib- 其中一个时才生成 lib.a
ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
lib-target := $(obj)/lib.a
endif
# 至少有obj-y obj-m obj- subdir-m lib-y lib-m lib- 其中一个时才生成 built-in.o
ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),)
builtin-target := $(obj)/built-in.o
endif modorder-target := $(obj)/modules.order # We keep a list of all modules in $(MODVERDIR)
# KBUILD_BUILTIN 在顶层Makefile赋为了1,u-boot中不需要module,所以KBUILD_MODULES为0
__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
$(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
$(subdir-ym) $(always)
@:
以上这个部分我认为比较重要,未指定目标时,Makefile.build的默认目标是 __build,这个__build依赖
- built-in.o
- lib.a
- extra-y
- subdir-ym:这是子目录
SPL执行分析
(源代码根目录下 README 文件中有一节Board Initialisation Flow专门讲了启动流程)
SPL编译分析结束后,我们就知道了SPL由哪些源文件组成,分析起来要方便多了。首先当然是从head-y开始,即 arch/arm/cpu/armv7/start.S
- save_boot_params:通过weak方式调用了 arch/arm/omach-omap2/lowlevel_init.S中的同名函数(存了r0到RAM)(暂时还没有搞清r0是啥)
- 关中断,进入SVC模式
- cpu_init_cp15:Cache、MMU、TLB操作等(该清清,该禁禁,I-Cache一般是打开)
- cpu_init_crit:调用 lowlevel_init,BBB板级未定义lowlevel_init,于是就调用了 arch/arm/cpu/armv7/lowlevel_init.S 中的 lowlevel_init函数,对SPL来说基本没干啥
- _main:这个函数是重头戏,定义在 arch/arm/lib/crt0.S中,这个函数大概流程是这样的
- 初始化GD
- board_init_f
- 正常的u-boot此处会进行relocate,SPL不会,但是SPL可能会改变栈和GD的位置(参见 CONFIG_SPL_FRAMEWORK,common/spl/spl.c中的spl_relocate_stack_gd函数)
- 清零bss区
- board_init_r
GD(struct global_data)
为了简单起见,u-boot有一个全局的结构体数据,称为GD(指针为gd),很多数据都会丢到这个结构体里。
typedef struct global_data {
//...
struct arch_global_data arch;
// ...
} gd_t;
这个结构体的定义在源代码目录的 include/asm-generic/global_data.h,这个文件应被arch的同名文件包含,以便可以定义不同的 struct arch_global_data 结构体,对于arm来说是 arch/arm/include/asm/global_data.h ,使用时 采用 #include<asm/global_data.h>的方式就可以包含不同arch的同名文件了。
这么重要的结构体是在_main的一开始就被初始化为0了,代码在 common/init/board_init.c中的 board_init_f_alloc_reserve/board_init_f_init_reserve 两个函数里,通过在栈顶预留内存来达到给GD开辟空间的目的(因栈是向下增长的,所有不会和栈冲突)。
注:在arm架构中,gd的指针被赋给了r9寄存器,在需要使用gd地方,通过全局声明r9,使编译器不会使用r9寄存器作为临时变量,加快gd的访问速度。
https://gcc.gnu.org/onlinedocs/gcc/Global-Register-Variables.htm 在 arch/arm/config.mk 中 PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections \
-fno-common -ffixed-r9 注意: -ffixed-r9 就是上述链接中的 -ffixed-reg ,所有函数都不可以使用r9寄存器
board_init_f
GD初始化完成之后,就会调用 board_init_f,这个函数的目的是使board_init_r可以运行,主要是初始化DRAM和console串口,要注意下这个函数的运行环境:
- GD指针可使用,因为GD已经初始化
- 栈是在SRAM中的
- BSS还未清零,因为所有全局或静态变量都是不可以访问的,只能访问局部变量和GD
虽说这个函数以board打头,但是相似的板子可能会定义一个初始化的流程,在流程中大量使用虚函数和配置来抽象不同的板子。BBB的board_init_f是在 arch/arm/march-omap2/am33xx/board.c 中
#ifdef CONFIG_SPL_BUILD
void board_init_f(ulong dummy)
{
hw_data_init();
early_system_init();
board_early_init_f();
sdram_init();
/* dram_init must store complete ramsize in gd->ram_size */
gd->ram_size = get_ram_size(
(void *)CONFIG_SYS_SDRAM_BASE,
CONFIG_MAX_RAM_BANK_SIZE);
}
#endif
board_init_r
这个函数用来实现主要的代码逻辑,对于SPL来说,主要函数都是在 common/spl/spl.c 中实现了,具体大家直接看代码就是了
falcon
参见 doc/README.falcon,大概就是SPL=>u-boot=>Linux这个流程有点慢,falcon的功能就是不启动u-boot,直接启动Linux,相关的配置项是 CONFIG_SPL_OS_BOOT
这篇文章就写这么多了,把这些搞明白了,u-boot-spl就大体上理解了,更详细的还得大家自己回去读代码了,共勉!
u-boot 学习系列 1 - SPL的更多相关文章
- Spring Boot 学习系列(10)—SpringBoot+JSP的使
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 解决问题 随着spring boot 框架的逐步使用,我们期望对于一些已有的系统进行改造,做成通用的脚手架, ...
- Spring Boot 学习系列(03)—jar or war,做出你的选择
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 两种打包方式 采用Spring Boot框架来构建项目,我们对项目的打包有两种方式可供选择,一种仍保持原有的 ...
- Spring Boot 学习系列(序)—Spring Boot
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Spring Boot? Spring Boot 是由pivotal团队提供的一个基于Spring的全新框架 ...
- Spring Boot 学习系列(06)—采用log4j2记录日志
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 为什么选择log4j2 log4j2相比于log4j1.x和logback来说,具有更快的执行速度.同时也支 ...
- Spring Boot 学习系列(02)—使用热部署,提升开发效
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 开发调试很简单 热部署的使用非常简单,但能极大的提高我们的开发效率,像传统的web应用,我们修改后需要重新编 ...
- Spring Boot 学习系列(05)—自定义视图解析规则
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 自定义视图解析 在默认情况下Spring Boot 的MVC框架使用的视图解析ViewResolver类是C ...
- Spring Boot 学习系列(11)—tomcat参数配置建
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 在SpringBoot项目中,使用的是内嵌的Tomcat容器,相关的配置项如下表: 除去和默认值相同的配置, ...
- Spring Boot 学习系列(09)—自定义Bean的顺序加载
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Bean 的顺序加载 有些场景中,我们希望编写的Bean能够按照指定的顺序进行加载.比如,有UserServ ...
- Spring Boot 学习系列(08)—自定义servlet、filter及listener
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 传统的filter及listener配置 在传统的Java web项目中,servlet.filter和li ...
随机推荐
- Eval的格式,主要看大括号的格式,其他不用那样写
原文发布时间为:2009-08-26 -- 来源于本人的百度文章 [由搬家工具导入] 使用范例:<%#Eval("date","{0:d}") %> ...
- bugs view:
Expecially those business bugs! I should check better especially when data changes! This place requi ...
- 转载——Visiual Studio2012 CLR20r3问题
看到有更新,习惯性的点了,升级到Visiual Studio Ultimate 2012 Update 1,并且按照提升重启了电脑.因为昨天太晚,也没验证.尽早打开VS,结果直接Crash.错误如下: ...
- Process 'command 'D:\IDE\SDK\build-tools\28.0.3\aapt.exe'' finished with non-zero exit value 1问题分析解决
当在Android Studio的XML布局文件写错属性或单词拼错时,会出现如下所列的错误,而AS编辑器又没任何提示, 再次点击下方的"Run build",也只能得到:app:p ...
- [LeetCode] 1.Two Sum 两数之和分析以及实现 (golang)
题目描述: /* Given an array of integers, return indices of the two numbers such that they add up to a sp ...
- Office 2016 安装你所必须要注意的事项
坑主要是,Office 2016专业增强不能自定义安装路径,不能选择需要安装的产品组件(不能取消outlook, onenote等垃圾组件). 软件的下载可以在百度上搜索,cn_office_prof ...
- Auto-Test 要点纪录(一)
1,select下拉框类型 使用工具可以看到html对应标签为<select>这类标签才是真正的下拉框类型就需要对应的方法,不能但看页面上的效果,有的做成了效果但其实不是select类型即 ...
- ThinkPHP3.1 模板布局
ThinkPHP的模板引擎内置了布局模板功能支持,可以方便的实现模板布局以及布局嵌套功能.有三种布局模板的支持方式: 第一种方式:全局配置方式 这种方式仅需在项目配置文件中添加相关的布局模板配置,就可 ...
- nx sdk
最近在做ns 任天堂略坑.. 他想做成一键安装,可总是有些问题,这样再去找就很麻烦了.都是包在里面的,要看很多文档 第一个问题是 NintendoSDK Configuration Manager 这 ...
- GIS可视化——热点格网图
一.简介 原理:按照格网大小将区域进行划分,由一个矩形格网替代当前范围内的数据,由格网中心数字代替格网的权重(可以为格网中数据的数量,数据某权重的平均值.最大值.最小值等), 由格网之间颜色的不同表达 ...