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.htmarch/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的更多相关文章

  1. Spring Boot 学习系列(10)—SpringBoot+JSP的使

    此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 解决问题 随着spring boot 框架的逐步使用,我们期望对于一些已有的系统进行改造,做成通用的脚手架, ...

  2. Spring Boot 学习系列(03)—jar or war,做出你的选择

    此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 两种打包方式 采用Spring Boot框架来构建项目,我们对项目的打包有两种方式可供选择,一种仍保持原有的 ...

  3. Spring Boot 学习系列(序)—Spring Boot

    此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Spring Boot? Spring Boot 是由pivotal团队提供的一个基于Spring的全新框架 ...

  4. Spring Boot 学习系列(06)—采用log4j2记录日志

    此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 为什么选择log4j2 log4j2相比于log4j1.x和logback来说,具有更快的执行速度.同时也支 ...

  5. Spring Boot 学习系列(02)—使用热部署,提升开发效

    此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 开发调试很简单 热部署的使用非常简单,但能极大的提高我们的开发效率,像传统的web应用,我们修改后需要重新编 ...

  6. Spring Boot 学习系列(05)—自定义视图解析规则

    此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 自定义视图解析 在默认情况下Spring Boot 的MVC框架使用的视图解析ViewResolver类是C ...

  7. Spring Boot 学习系列(11)—tomcat参数配置建

    此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 在SpringBoot项目中,使用的是内嵌的Tomcat容器,相关的配置项如下表: 除去和默认值相同的配置, ...

  8. Spring Boot 学习系列(09)—自定义Bean的顺序加载

    此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Bean 的顺序加载 有些场景中,我们希望编写的Bean能够按照指定的顺序进行加载.比如,有UserServ ...

  9. Spring Boot 学习系列(08)—自定义servlet、filter及listener

    此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 传统的filter及listener配置 在传统的Java web项目中,servlet.filter和li ...

随机推荐

  1. Eval的格式,主要看大括号的格式,其他不用那样写

    原文发布时间为:2009-08-26 -- 来源于本人的百度文章 [由搬家工具导入] 使用范例:<%#Eval("date","{0:d}") %> ...

  2. bugs view:

    Expecially those business bugs! I should check better especially when data changes! This place requi ...

  3. 转载——Visiual Studio2012 CLR20r3问题

    看到有更新,习惯性的点了,升级到Visiual Studio Ultimate 2012 Update 1,并且按照提升重启了电脑.因为昨天太晚,也没验证.尽早打开VS,结果直接Crash.错误如下: ...

  4. 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 ...

  5. [LeetCode] 1.Two Sum 两数之和分析以及实现 (golang)

    题目描述: /* Given an array of integers, return indices of the two numbers such that they add up to a sp ...

  6. Office 2016 安装你所必须要注意的事项

    坑主要是,Office 2016专业增强不能自定义安装路径,不能选择需要安装的产品组件(不能取消outlook, onenote等垃圾组件). 软件的下载可以在百度上搜索,cn_office_prof ...

  7. Auto-Test 要点纪录(一)

    1,select下拉框类型 使用工具可以看到html对应标签为<select>这类标签才是真正的下拉框类型就需要对应的方法,不能但看页面上的效果,有的做成了效果但其实不是select类型即 ...

  8. ThinkPHP3.1 模板布局

    ThinkPHP的模板引擎内置了布局模板功能支持,可以方便的实现模板布局以及布局嵌套功能.有三种布局模板的支持方式: 第一种方式:全局配置方式 这种方式仅需在项目配置文件中添加相关的布局模板配置,就可 ...

  9. nx sdk

    最近在做ns 任天堂略坑.. 他想做成一键安装,可总是有些问题,这样再去找就很麻烦了.都是包在里面的,要看很多文档 第一个问题是 NintendoSDK Configuration Manager 这 ...

  10. GIS可视化——热点格网图

    一.简介 原理:按照格网大小将区域进行划分,由一个矩形格网替代当前范围内的数据,由格网中心数字代替格网的权重(可以为格网中数据的数量,数据某权重的平均值.最大值.最小值等), 由格网之间颜色的不同表达 ...