Detailed explanation of the role of SPL in uboot

SPL

SPL is the code that is executed in the first phase of uboot. Mainly responsible for moving the second phase of uboot code to run in memory. The SPL is guided by a ROM that is solidified inside the chip. We know that many ROM manufacturers have fixed ROM support from external media such as nandflash, SDCARD.

The so-called startup is to move a fixed size (4K/8K/16K, etc.) code from these external media to the internal RAM. Here is the SPL. In the latest version of uboot, you can see that SPL also supports nandflash, SDCARD and other startup methods. When the SPL itself is moved to the internal RAM, it will move the second stage code of the uboot from the external media such as nandflash, SDCARD to the external memory.

SPL file composition

When we execute the make command under uboot, its core function is to execute the all target in the Makefile to compile the corresponding file. Let's take a look at this all target.

[plain] view plaincopyall: $(ALL-y) $(SUBDIR_EXAMPLES)

[plain] view plain copyall: $(ALL-y) $(SUBDIR_EXAMPLES)

All depends on $(ALL-y) and $(SUBDIR_EXAMPLES), here I only focus on ALL-y, as follows:

[plain] view plaincopy# Always append ALL so that arch config.mk's can add custom ones

ALL-y += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map

ALL-$(CONFIG_NAND_U_BOOT) += $(obj)u-boot-nand.bin

ALL-$(CONFIG_ONENAND_U_BOOT) += $(obj)u-boot-onenand.bin

ALL-$(CONFIG_SPL) += $(obj)spl/u-boot-spl.bin

ALL-$(CONFIG_SPL_FRAMEWORK) += $(obj)u-boot.img

ALL-$(CONFIG_TPL) += $(obj)tpl/u-boot-tpl.bin

ALL-$(CONFIG_OF_SEPARATE) += $(obj)u-boot.dtb $(obj)u-boot-dtb.bin

Ifneq ($(CONFIG_SPL_TARGET),)

ALL-$(CONFIG_SPL) += $(obj)$(subst “,,$(CONFIG_SPL_TARGET))

Endif

# enable combined SPL/u-boot/dtb rules for tegra

Ifneq ($(CONFIG_TEGRA),)

Ifeq ($(CONFIG_OF_SEPARATE), y)

ALL-y += $(obj)u-boot-dtb-tegra.bin

Else

ALL-y += $(obj)u-boot-nodtb-tegra.bin

Endif

Endif

[plain] view plain copy# Always append ALL so that arch config.mk's can add custom ones

ALL-y += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map

ALL-$(CONFIG_NAND_U_BOOT) += $(obj)u-boot-nand.bin

ALL-$(CONFIG_ONENAND_U_BOOT) += $(obj)u-boot-onenand.bin

ALL-$(CONFIG_SPL) += $(obj)spl/u-boot-spl.bin

ALL-$(CONFIG_SPL_FRAMEWORK) += $(obj)u-boot.img

ALL-$(CONFIG_TPL) += $(obj)tpl/u-boot-tpl.bin

ALL-$(CONFIG_OF_SEPARATE) += $(obj)u-boot.dtb $(obj)u-boot-dtb.bin

Ifneq ($(CONFIG_SPL_TARGET),)

ALL-$(CONFIG_SPL) += $(obj)$(subst ”,,$(CONFIG_SPL_TARGET))

Endif

# enable combined SPL/u-boot/dtb rules for tegra

Ifneq ($(CONFIG_TEGRA),)

Ifeq ($(CONFIG_OF_SEPARATE), y)

ALL-y += $(obj)u-boot-dtb-tegra.bin

Else

ALL-y += $(obj)u-boot-nodtb-tegra.bin

Endif

Endif

Detailed explanation of the role of SPL in uboot

Because this section is about SPL, we only focus on one of the ALL-$(CONFIG_SPL) += $(obj)spl/u-boot-spl.bin

This sentence indicates

You must define CONFIG_SPL to compile the spl bin: generally defined in "include/configs/${CONFIG_NAME}.h"

SPL bin depends on u-boot-spl.bin

Then look down

[plain] view plaincopy$(obj)spl/u-boot-spl.bin: $(SUBDIR_TOOLS) depend

$(MAKE) -C spl all

[plain] view plain copy$(obj)spl/u-boot-spl.bin: $(SUBDIR_TOOLS) depend

$(MAKE) -C spl all

Here you can see that u-boot-spl.bin depends on $(SUBDIR_TOOLS) depend

$(SUBDIR_TOOLS) : Not yet analyzed

Depend: Refer to the dependencies in the appendix

Go to the spl directory and execute make all

Next, go to the spl directory and look at its Makefile: here only analyze the parts related to SPL.

[plain] view plaincopyCONFIG_SPL_BUILD := y

Export CONFIG_SPL_BUILD

[plain] view plain copyCONFIG_SPL_BUILD := y

Export CONFIG_SPL_BUILD

Export CONFIG_SPL_BUILD: In the next compilation, this variable is y. As you can see from the analysis later, the stage1 and stage2 code of uboot use the same Start.S, but use # in Start.S. Ifdef CONFIG_SPL_BUILD this condition is compiled to distinguish. There are other files similar.

[plain] view plaincopyHAVE_VENDOR_COMMON_LIB = $(if $(wildcard $(SRCTREE)/board/$(VENDOR)/common/Makefile),y,n)

[plain] view plain copyHAVE_VENDOR_COMMON_LIB = $(if $(wildcard $(SRCTREE)/board/$(VENDOR)/common/Makefile),y,n)

[cpp] view plaincopy If there is a Makefile in the board/$(VENDOR)/common directory, then HAVE_VENDOR_COMMON_LIB is y otherwise n

[cpp] view plain copy If there is a Makefile in the board/$(VENDOR)/common directory, then HAVE_VENDOR_COMMON_LIB is y otherwise n

[plain] view plaincopyifdef CONFIG_SPL_START_S_PATH

START_PATH := $(subst ",,$(CONFIG_SPL_START_S_PATH))

Else

START_PATH := $(CPUDIR)

Endif

[plain] view plain copyifdef CONFIG_SPL_START_S_PATH

START_PATH := $(subst ",,$(CONFIG_SPL_START_S_PATH))

Else

START_PATH := $(CPUDIR)

Endif

We have not defined CONFIG_SPL_START_S_PATH here, so START_PATH := $(CPUDIR)

[plain] view plaincopySTART := $(START_PATH)/start.o

[plain] view plain copySTART := $(START_PATH)/start.o

Depending on start.o, in summary, it is necessary to compile start.S under CPUDIR.

[plain] view plaincopyLIBS-y += arch/$(ARCH)/lib/lib$(ARCH).o

[plain] view plain copyLIBS-y += arch/$(ARCH)/lib/lib$(ARCH).o

Depends on lib$(ARCH).o, specifically, it depends on arch/arm/lib/libarm.o

[plain] view plaincopyLIBS-y += $(CPUDIR)/lib$(CPU).o

[plain] view plain copyLIBS-y += $(CPUDIR)/lib$(CPU).o

Depends on lib$(CPU).o, specifically, it depends on arch/arm/cpu/armv7/libarmv7.o

[plain] view plaincopyifdef SOC

LIBS-y += $(CPUDIR)/$(SOC)/lib$(SOC).o

Endif

[plain] view plain copyifdef SOC

LIBS-y += $(CPUDIR)/$(SOC)/lib$(SOC).o

Endif

If SOC is defined, it depends on lib$(SOC).o. Specifically, it depends on arch/arm/cpu/s5pc1xx/libs5pc1xx.o

[plain] view plaincopyLIBS-y += board/$(BOARDDIR)/lib$(BOARD).o

[plain] view plain copyLIBS-y += board/$(BOARDDIR)/lib$(BOARD).o

Depends on lib$(BOARD).o, specifically, it depends on board/samsung/TIny210/libTIny210.o

[plain] view plaincopyLIBS-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/lib$(VENDOR).o

[plain] view plain copyLIBS-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/lib$(VENDOR).o

If HAVE_VENDOR_COMMON_LIB is y, then rely on lib$(VENDOR).o, specifically, rely on board/samsung/common/libsamsung.o

[plain] view plaincopyLIBS-$(CONFIG_SPL_FRAMEWORK) += common/spl/libspl.o

LIBS-$(CONFIG_SPL_LIBCOMMON_SUPPORT) += common/libcommon.o

LIBS-$(CONFIG_SPL_LIBDISK_SUPPORT) += disk/libdisk.o

LIBS-$(CONFIG_SPL_I2C_SUPPORT) += drivers/i2c/libi2c.o

LIBS-$(CONFIG_SPL_GPIO_SUPPORT) += drivers/gpio/libgpio.o

LIBS-$(CONFIG_SPL_MMC_SUPPORT) += drivers/mmc/libmmc.o

LIBS-$(CONFIG_SPL_SERIAL_SUPPORT) += drivers/serial/libserial.o

LIBS-$(CONFIG_SPL_SPI_FLASH_SUPPORT) += drivers/mtd/spi/libspi_flash.o

LIBS-$(CONFIG_SPL_SPI_SUPPORT) += drivers/spi/libspi.o

LIBS-$(CONFIG_SPL_FAT_SUPPORT) += fs/fat/libfat.o

LIBS-$(CONFIG_SPL_LIBGENERIC_SUPPORT) += lib/libgeneric.o

LIBS-$(CONFIG_SPL_POWER_SUPPORT) += drivers/power/libpower.o \

Drivers/power/pmic/libpmic.o

LIBS-$(CONFIG_SPL_NAND_SUPPORT) += drivers/mtd/nand/libnand.o

LIBS-$(CONFIG_SPL_ONENAND_SUPPORT) += drivers/mtd/onenand/libonenand.o

LIBS-$(CONFIG_SPL_DMA_SUPPORT) += drivers/dma/libdma.o

LIBS-$(CONFIG_SPL_POST_MEM_SUPPORT) += post/drivers/memory.o

LIBS-$(CONFIG_SPL_NET_SUPPORT) += net/libnet.o

LIBS-$(CONFIG_SPL_ETH_SUPPORT) += drivers/net/libnet.o

LIBS-$(CONFIG_SPL_ETH_SUPPORT) += drivers/net/phy/libphy.o

LIBS-$(CONFIG_SPL_USBETH_SUPPORT) += drivers/net/phy/libphy.o

LIBS-$(CONFIG_SPL_MUSB_NEW_SUPPORT) += drivers/usb/musb-new/libusb_musb-new.o

LIBS-$(CONFIG_SPL_USBETH_SUPPORT) += drivers/usb/gadget/libusb_gadget.o

LIBS-$(CONFIG_SPL_WATCHDOG_SUPPORT) += drivers/watchdog/libwatchdog.o

[plain] view plain copyLIBS-$(CONFIG_SPL_FRAMEWORK) += common/spl/libspl.o

LIBS-$(CONFIG_SPL_LIBCOMMON_SUPPORT) += common/libcommon.o

LIBS-$(CONFIG_SPL_LIBDISK_SUPPORT) += disk/libdisk.o

LIBS-$(CONFIG_SPL_I2C_SUPPORT) += drivers/i2c/libi2c.o

LIBS-$(CONFIG_SPL_GPIO_SUPPORT) += drivers/gpio/libgpio.o

LIBS-$(CONFIG_SPL_MMC_SUPPORT) += drivers/mmc/libmmc.o

LIBS-$(CONFIG_SPL_SERIAL_SUPPORT) += drivers/serial/libserial.o

LIBS-$(CONFIG_SPL_SPI_FLASH_SUPPORT) += drivers/mtd/spi/libspi_flash.o

LIBS-$(CONFIG_SPL_SPI_SUPPORT) += drivers/spi/libspi.o

LIBS-$(CONFIG_SPL_FAT_SUPPORT) += fs/fat/libfat.o

LIBS-$(CONFIG_SPL_LIBGENERIC_SUPPORT) += lib/libgeneric.o

LIBS-$(CONFIG_SPL_POWER_SUPPORT) += drivers/power/libpower.o \

Drivers/power/pmic/libpmic.o

LIBS-$(CONFIG_SPL_NAND_SUPPORT) += drivers/mtd/nand/libnand.o

LIBS-$(CONFIG_SPL_ONENAND_SUPPORT) += drivers/mtd/onenand/libonenand.o

LIBS-$(CONFIG_SPL_DMA_SUPPORT) += drivers/dma/libdma.o

LIBS-$(CONFIG_SPL_POST_MEM_SUPPORT) += post/drivers/memory.o

LIBS-$(CONFIG_SPL_NET_SUPPORT) += net/libnet.o

LIBS-$(CONFIG_SPL_ETH_SUPPORT) += drivers/net/libnet.o

LIBS-$(CONFIG_SPL_ETH_SUPPORT) += drivers/net/phy/libphy.o

LIBS-$(CONFIG_SPL_USBETH_SUPPORT) += drivers/net/phy/libphy.o

LIBS-$(CONFIG_SPL_MUSB_NEW_SUPPORT) += drivers/usb/musb-new/libusb_musb-new.o

LIBS-$(CONFIG_SPL_USBETH_SUPPORT) += drivers/usb/gadget/libusb_gadget.o

LIBS-$(CONFIG_SPL_WATCHDOG_SUPPORT) += drivers/watchdog/libwatchdog.o

According to the specific configuration, select the corresponding dependencies

[plain] view plaincopy View the code snippet on CODEDerived to my code piece Ifeq ($(SOC),exynos)

LIBS-y += $(CPUDIR)/s5p-common/libs5p-common.o

Endif

[plain] view plain copyifeq ($(SOC),exynos)

LIBS-y += $(CPUDIR)/s5p-common/libs5p-common.o

Endif

If the SOC is exynos, then rely on libs5p-common.o, our SOC here is s5pc1xx, so it does not depend on

[plain] view plaincopySTART := $(addprefix $(SPLTREE)/,$(START))

LIBS := $(addprefix $(SPLTREE)/,$(sort $(LIBS-y)))

[plain] view plain copySTART := $(addprefix $(SPLTREE)/,$(START))

LIBS := $(addprefix $(SPLTREE)/,$(sort $(LIBS-y)))

Prefix START and LIBS, $(SPLTREE), specifically, the .o files generated during compilation will be placed under the spl/ directory.

[plain] view plaincopy# Linker Script

Ifdef CONFIG_SPL_LDSCRIPT

# need to strip off double quotes

LDSCRIPT := $(addprefix $(SRCTREE)/,$(subst ",,$(CONFIG_SPL_LDSCRIPT)))

Endif

Ifeq ($(wildcard $(LDSCRIPT)),)

LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-spl.lds

Endif

Ifeq ($(wildcard $(LDSCRIPT)),)

LDSCRIPT := $(TOPDIR)/$(CPUDIR)/u-boot-spl.lds

Endif

Ifeq ($(wildcard $(LDSCRIPT)),)

LDSCRIPT := $(TOPDIR)/arch/$(ARCH)/cpu/u-boot-spl.lds

Endif

Ifeq ($(wildcard $(LDSCRIPT)),)

$(error could not find linker script)

Endif

[plain] view plain copy# Linker Script

Ifdef CONFIG_SPL_LDSCRIPT

# need to strip off double quotes

LDSCRIPT := $(addprefix $(SRCTREE)/,$(subst ”,,$(CONFIG_SPL_LDSCRIPT)))

Endif

Ifeq ($(wildcard $(LDSCRIPT)),)

LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-spl.lds

Endif

Ifeq ($(wildcard $(LDSCRIPT)),)

LDSCRIPT := $(TOPDIR)/$(CPUDIR)/u-boot-spl.lds

Endif

Ifeq ($(wildcard $(LDSCRIPT)),)

LDSCRIPT := $(TOPDIR)/arch/$(ARCH)/cpu/u-boot-spl.lds

Endif

Ifeq ($(wildcard $(LDSCRIPT)),)

$(error could not find linker script)

Endif

Find the link configuration file of spl. Specifically, use u-boot-spl.lds under arch/arm/cpu.

[plain] view plaincopyALL-y += $(obj)$(SPL_BIN).bin

Ifdef CONFIG_SAMSUNG

ALL-y += $(obj)$(BOARD)-spl.bin

Endif

All: $(ALL-y)

Ifdef CONFIG_SAMSUNG

$(obj)$(BOARD)-spl.bin: $(obj)u-boot-spl.bin

$(OBJTREE)/tools/mk$(BOARD)spl \

$(obj)u-boot-spl.bin $(obj)$(BOARD)-spl.bin

Endif

$(obj)$(SPL_BIN).bin: $(obj)$(SPL_BIN)

$(OBJCOPY) $(OBJCFLAGS) -O binary $" $@

GEN_UBOOT = \

Cd $(obj) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) $(__START) \

--start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \

-Map $(SPL_BIN).map -o $(SPL_BIN)

$(obj)$(SPL_BIN): depend $(START) $(LIBS) $(obj)u-boot-spl.lds

$(GEN_UBOOT)

$(START): depend

$(MAKE) -C $(SRCTREE)/$(START_PATH) $@

$(LIBS): depend

$(MAKE) -C $(SRCTREE)$(dir $(subst $(SPLTREE),,$@))

$(obj)u-boot-spl.lds: $(LDSCRIPT) depend

$(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(obj). -ansi -D__ASSEMBLY__ -P - "$" ” $@

Depend: $(obj).depend

.PHONY: depend

[plain] view plain copyALL-y += $(obj)$(SPL_BIN).bin

Ifdef CONFIG_SAMSUNG

ALL-y += $(obj)$(BOARD)-spl.bin

Endif

All: $(ALL-y)

Ifdef CONFIG_SAMSUNG

$(obj)$(BOARD)-spl.bin: $(obj)u-boot-spl.bin

$(OBJTREE)/tools/mk$(BOARD)spl \

$(obj)u-boot-spl.bin $(obj)$(BOARD)-spl.bin

Endif

$(obj)$(SPL_BIN).bin: $(obj)$(SPL_BIN)

$(OBJCOPY) $(OBJCFLAGS) -O binary $" $@

GEN_UBOOT = \

Cd $(obj) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) $(__START) \

--start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \

-Map $(SPL_BIN).map -o $(SPL_BIN)

$(obj)$(SPL_BIN): depend $(START) $(LIBS) $(obj)u-boot-spl.lds

$(GEN_UBOOT)

$(START): depend

$(MAKE) -C $(SRCTREE)/$(START_PATH) $@

$(LIBS): depend

$(MAKE) -C $(SRCTREE)$(dir $(subst $(SPLTREE),,$@))

$(obj)u-boot-spl.lds: $(LDSCRIPT) depend

$(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(obj). -ansi -D__ASSEMBLY__ -P - "$" ” $@

Depend: $(obj).depend

.PHONY: depend

All: $(ALL-y), remember the above mentioned, after entering the spl directory, do you do something? That's right, execute make all, in fact, is the all target here. It depends on $(ALL-y). The specific dependencies will not be described in detail.

Ifdef CONFIG_SAMSUNG: This is a special feature for the Samsung platform.

Use the tools/mk$(BOARD)spl tool to convert u-boot-spl.bin to $(BOARD)-spl.bin

The essence of the conversion is to add head info in front of u-boot-spl.bin. For what is head info, you can refer to the document S5PV210_iROM_ApplicaTIonNote_Preliminary_20091126.pdf. By the way, you can understand the startup process of the Samsung chip.

The tools/mk$(BOARD)spl tool is generated in the tools/Makefile.

OK, the analysis is over. Next, we start analyzing the code based on our analysis above.

SPL code analysis

U-boot-spl.lds: Its location is analyzed in the above

According to the rules in u-boot-spl.lds, we know that CPUDIR/start.o is placed first. The file it corresponds to is arch/arm/cpu/armv7/start.S

start.S

Let's take a look at start.S

[plain] view plaincopy View the code snippet on CODEDerived to my code piece .globl _start

_start: b reset

Ldr pc, _undefined_instrucTIon

Ldr pc, _software_interrupt

Ldr pc, _prefetch_abort

Ldr pc, _data_abort

Ldr pc, _not_used

Ldr pc, _irq

Ldr pc, _fiq

[plain] view plain copy.globl _start

_start: b reset

Ldr pc, _undefined_instruction

Ldr pc, _software_interrupt

Ldr pc, _prefetch_abort

Ldr pc, _data_abort

Ldr pc, _not_used

Ldr pc, _irq

Ldr pc, _fiq

_start is the ENTRY (_start) we specified in lds

First jump to the reset

Ldr pc, _xxx defines the interrupt vector table

[plain] view plaincopy#ifdef CONFIG_SPL_BUILD

_undefined_instruction: .word _undefined_instruction

_software_interrupt: .word _software_interrupt

_prefetch_abort: .word _prefetch_abort

_data_abort: .word _data_abort

_not_used: .word _not_used

_irq: .word _irq

_fiq: .word _fiq

_pad: .word 0x12345678 /* now 16*4=64 */

#else

_undefined_instruction: .word undefined_instruction

_software_interrupt: .word software_interrupt

_prefetch_abort: .word prefetch_abort

_data_abort: .word data_abort

_not_used: .word not_used

_irq: .word irq

_fiq: .word fiq

_pad: .word 0x12345678 /* now 16*4=64 */

#endif /* CONFIG_SPL_BUILD */

[plain] view plain copy#ifdef CONFIG_SPL_BUILD

_undefined_instruction: .word _undefined_instruction

_software_interrupt: .word _software_interrupt

_prefetch_abort: .word _prefetch_abort

_data_abort: .word _data_abort

_not_used: .word _not_used

_irq: .word _irq

_fiq: .word _fiq

_pad: .word 0x12345678 /* now 16*4=64 */

#else

_undefined_instruction: .word undefined_instruction

_software_interrupt: .word software_interrupt

_prefetch_abort: .word prefetch_abort

_data_abort: .word data_abort

_not_used: .word not_used

_irq: .word irq

_fiq: .word fiq

_pad: .word 0x12345678 /* now 16*4=64 */

#endif /* CONFIG_SPL_BUILD */

When CONP has SPL_BUILD, an abort occurs and an infinite loop occurs. So we don't allow aborting in our SPL.

However, the normal uboot (stage2 stage) can still handle abnormal interrupts.

Reset

[plain] view plaincopy/*

* the actual reset code

*/

Reset:

Bl save_boot_params

/*

* disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,

*except if in HYP mode already

*/

Mrs r0, cpsr

And r1, r0, #0x1f @ mask mode bits

Teq r1, #0x1a @ test for HYP mode

Bicene r0, r0, #0x1f @ clear all mode bits

Orrne r0, r0, #0x13 @ set SVC mode

Orr r0, r0, #0xc0 @ disable FIQ and IRQ

Msr cpsr, r0

/*. . . . . . . . */

/* the mask ROM code should have PLL and others stable */

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

Bl cpu_init_cp15

Bl cpu_init_crit

#endif

Bl _main

[plain] view plain copy/*

* the actual reset code

*/

Reset:

Bl save_boot_params

/*

* disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,

*except if in HYP mode already

*/

Mrs r0, cpsr

And r1, r0, #0x1f @ mask mode bits

Teq r1, #0x1a @ test for HYP mode

Bicene r0, r0, #0x1f @ clear all mode bits

Orrne r0, r0, #0x13 @ set SVC mode

Orr r0, r0, #0xc0 @ disable FIQ and IRQ

Msr cpsr, r0

/*. . . . . . . . */

/* the mask ROM code should have PLL and others stable */

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

Bl cpu_init_cp15

Bl cpu_init_crit

#endif

Bl _main

When powering up or resetting for the first time, Uboot is running the code here.

Bl save_boot_params: If save_boot_params is not redefined, use save_boot_params in arch/arm/cpu/armv7/start.S. It does not do anything, return directly

Disable FIQ, IRQ; set CPU to work in SVC32 mode

Bl cpu_init_cp15: (I/D-Cache, MMU, TLBs), see the comments in the code below

Bl cpu_init_crit : Mainly set the PLL of the CPU, GPIO pin multiplexing, memory, etc. See below

Bl _main : Jump to _main in "arch/arm/lib/crt0.S". See below

Cpu_init_cp15

[plain] view plaincopy/******************************************** *****************************

*

* cpu_init_cp15

*

* Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless

* CONFIG_SYS_ICACHE_OFF is defined.

*

************************************************** ***********************/

ENTRY(cpu_init_cp15)

/*

* Invalidate L1 I/D

*/

Mov r0, #0 @ set up for MCR

Mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs

Mcr p15, 0, r0, c7, c5, 0 @ invalidate icache

Mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array

Mcr p15, 0, r0, c7, c10, 4 @ DSB

Mcr p15, 0, r0, c7, c5, 4 @ ISB

/*

* disable MMU stuff and caches

*/

Mrc p15, 0, r0, c1, c0, 0

Bic r0, r0, #0x00002000 @ clear bits 13 (--V-)

Bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)

Orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align

Orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB

#ifdef CONFIG_SYS_ICACHE_OFF

Bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache

#else

Orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache

#endif

Mcr p15, 0, r0, c1, c0, 0

#ifdef CONFIG_ARM_ERRATA_716044

Mrc p15, 0, r0, c1, c0, 0 @ read system control register

Orr r0, r0, #1 "11 @ set bit #11

Mcr p15, 0, r0, c1, c0, 0 @ write system control register

#endif

#ifdef CONFIG_ARM_ERRATA_742230

Mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register

Orr r0, r0, #1 "4 @ set bit #4

Mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register

#endif

#ifdef CONFIG_ARM_ERRATA_743622

Mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register

Orr r0, r0, #1 "6 @ set bit #6

Mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register

#endif

#ifdef CONFIG_ARM_ERRATA_751472

Mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register

Orr r0, r0, #1 "11 @ set bit #11

Mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register

#endif

Mov pc, lr @ back to my caller

ENDPROC(cpu_init_cp15)

[plain] view plain copy/******************************************* ******************************

*

* cpu_init_cp15

*

* Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless

* CONFIG_SYS_ICACHE_OFF is defined.

*

************************************************** ***********************/

ENTRY(cpu_init_cp15)

/*

* Invalidate L1 I/D

*/

Mov r0, #0 @ set up for MCR

Mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs

Mcr p15, 0, r0, c7, c5, 0 @ invalidate icache

Mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array

Mcr p15, 0, r0, c7, c10, 4 @ DSB

Mcr p15, 0, r0, c7, c5, 4 @ ISB

/*

* disable MMU stuff and caches

*/

Mrc p15, 0, r0, c1, c0, 0

Bic r0, r0, #0x00002000 @ clear bits 13 (--V-)

Bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)

Orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align

Orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB

#ifdef CONFIG_SYS_ICACHE_OFF

Bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache

#else

Orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache

#endif

Mcr p15, 0, r0, c1, c0, 0

#ifdef CONFIG_ARM_ERRATA_716044

Mrc p15, 0, r0, c1, c0, 0 @ read system control register

Orr r0, r0, #1 "11 @ set bit #11

Mcr p15, 0, r0, c1, c0, 0 @ write system control register

#endif

#ifdef CONFIG_ARM_ERRATA_742230

Mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register

Orr r0, r0, #1 "4 @ set bit #4

Mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register

#endif

#ifdef CONFIG_ARM_ERRATA_743622

Mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register

Orr r0, r0, #1 "6 @ set bit #6

Mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register

#endif

#ifdef CONFIG_ARM_ERRATA_751472

Mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register

Orr r0, r0, #1 "11 @ set bit #11

Mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register

#endif

Mov pc, lr @ back to my caller

ENDPROC(cpu_init_cp15)

Cpu_init_crit

[plain] view plaincopy View the code snippet on CODEDerived to my code piece #ifndef CONFIG_SKIP_LOWLEVEL_INIT

/************************************************* ************************

*

* CPU_init_critical registers

*

* setup important registers

* setup memory timing

*

************************************************** ***********************/

ENTRY(cpu_init_crit)

/*

* Jump to board specific initialization. .

* The Mask ROM will have already initialized

* basic memory. Go here to bump up clock rate and handle

* wake up conditions.

*/

b lowlevel_init @ go setup pll,mux,memory

ENDPROC(cpu_init_crit)

#endif

[plain] view plain copy#ifndef CONFIG_SKIP_LOWLEVEL_INIT

/************************************************* ************************

*

* CPU_init_critical registers

*

* setup important registers

* setup memory timing

*

************************************************** ***********************/

ENTRY(cpu_init_crit)

/*

* Jump to board specific initialization. .

* The Mask ROM will have already initialized

* basic memory. Go here to bump up clock rate and handle

* wake up conditions.

*/

b lowlevel_init @ go setup pll,mux,memory

ENDPROC(cpu_init_crit)

#endif

b lowlevel_init : Jump to lowlevel_init in arch/arm/cpu/armv7/lowlevel_init.S

lowlevel_init.S

Lowlevel_init

[plain] view plaincopy#include "asm-offsets.h"

#include "config.h"

#include "linux/linkage.h"

ENTRY(lowlevel_init)

/*

* Setup a temporary stack

*/

Ldr sp, =CONFIG_SYS_INIT_SP_ADDR

Bic sp, sp, #7 /* 8-byte alignment for ABI compliance */

#ifdef CONFIG_SPL_BUILD

Ldr r9, =gdata

#else

Sub sp, #GD_SIZE

Bic sp, sp, #7

Mov r9, sp

#endif

/*

* Save the old lr(passed in ip) and the current lr to stack

*/

Push {ip, lr}

/*

* go setup pll, mux, memory

*/

Bl s_init

Pop {ip, pc}

[plain] view plain copy#include "asm-offsets.h"

#include "config.h"

#include "linux/linkage.h"

ENTRY(lowlevel_init)

/*

* Setup a temporary stack

*/

Ldr sp, =CONFIG_SYS_INIT_SP_ADDR

Bic sp, sp, #7 /* 8-byte alignment for ABI compliance */

#ifdef CONFIG_SPL_BUILD

Ldr r9, =gdata

#else

Sub sp, #GD_SIZE

Bic sp, sp, #7

Mov r9, sp

#endif

/*

* Save the old lr(passed in ip) and the current lr to stack

*/

Push {ip, lr}

/*

* go setup pll, mux, memory

*/

Bl s_init

Pop {ip, pc}

Previously, the old version of uboot, lowlevel_init is generally implemented under the board level folder under board/xxx. Now put it directly under CPUDIR, what did it do?

Assign the stack pointer to CONFIG_SYS_INIT_SP_ADDR

Make sure sp is 8-byte aligned

Store the address of gdata in the r9 register

Jump to s_init: This s_init requires the chip vendor or ourselves to implement it in the board file. What it does mainly

Setup pll, mux, memory

I personally feel that the new version of uboot implements a lowlevel_init.S file under CPUDIR. The main goal is to initialize sp, so that s_init can be implemented in C language. In the old version, the things to do in s_init are all done in assembly.

crt0.S

_main

[plain] view plaincopyENTRY(_main)

/*

* Set up initial C runtime environment and call board_init_f(0).

*/

#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)

Ldr sp, =(CONFIG_SPL_STACK)

#else

Ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)

#endif

Bic sp, sp, #7 /* 8-byte alignment for ABI compliance */

Sub sp, #GD_SIZE /* allocate one GD above SP */

Bic sp, sp, #7 /* 8-byte alignment for ABI compliance */

Mov r9, sp /* GD is above SP */

Mov r0, #0

Bl board_init_f

[plain] view plain copyENTRY(_main)

/*

* Set up initial C runtime environment and call board_init_f(0).

*/

#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)

Ldr sp, =(CONFIG_SPL_STACK)

#else

Ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)

#endif

Bic sp, sp, #7 /* 8-byte alignment for ABI compliance */

Sub sp, #GD_SIZE /* allocate one GD above SP */

Bic sp, sp, #7 /* 8-byte alignment for ABI compliance */

Mov r9, sp /* GD is above SP */

Mov r0, #0

Bl board_init_f

Detailed explanation of the role of SPL in uboot

Re-assign the SP, confirm that sp is 8-word aligned

The size of a global_data is reserved at the top of the stack. This global_data is a global data in uboot, which is used in many places. Commonly known as gd_t

Confirm that the updated sp is 8-word aligned

R9 points to global_data, and when you want to use global_data elsewhere, you can get the address directly from r9.

R0 assignment 0

Bl board_init_f: Jump to board_init_f. When compiling SPL, analysis of the Makefile shows that the implementation of this function is in "arch/arm/lib/spl.c".

Arch/arm/lib/spl.c

Board_init_f

[plain] view plaincopy/*

* In the context of SPL, board_init_f must ensure that any clocks/etc for

* DDR are enabled, ensure that the stack pointer is valid, clear the BSS

* and call board_init_f. We provide this version by default but mark it

* as __weak to allow for platforms to do this in their own way if needed.

*/

Void __weak board_init_f(ulong dummy)

{

/* Clear the BSS. */

Memset(__bss_start, 0, __bss_end - __bss_start);

/* Set global data pointer. */

Gd = &gdata;

Board_init_r(NULL, 0);

}

[plain] view plain copy/*

* In the context of SPL, board_init_f must ensure that any clocks/etc for

* DDR are enabled, ensure that the stack pointer is valid, clear the BSS

* and call board_init_f. We provide this version by default but mark it

* as __weak to allow for platforms to do this in their own way if needed.

*/

Void __weak board_init_f(ulong dummy)

{

/* Clear the BSS. */

Memset(__bss_start, 0, __bss_end - __bss_start);

/* Set global data pointer. */

Gd = &gdata;

Board_init_r(NULL, 0);

}

__weak: indicates that the function can be redefined

Clear the BSS segment

Gd = &gdata;

Gd is defined in DECLARE_GLOBAL_DATA_PTR "arch/arm/include/asm/global_data.h"

#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r9")

Remember the r9 register, which was initialized above.

The definition of gdata is in this file: gd_t gdata __attribute__ ((section(".data"))));

It is a variable of type gd_t or global_data

__attribute__ indicates that this variable will be placed in the input section ".data". The connector stores the input section in the output section according to the rules specified in the link script (u-boot-spl.lds).

Why is there such an assignment operation, I don't quite understand. . .

Board_init_r : When compiling SPL, you can see that the implementation of this function is in "common/spl/spl.c".

Common/spl/spl.c

Board_init_r

[plain] view plaincopy#ifdef CONFIG_SYS_SPL_MALLOC_START

Mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,

CONFIG_SYS_SPL_MALLOC_SIZE);

#endif

[plain] view plain copy#ifdef CONFIG_SYS_SPL_MALLOC_START

Mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,

CONFIG_SYS_SPL_MALLOC_SIZE);

#endif

If CONFIG_SYS_SPL_MALLOC_START is defined, the malloc pool initialization of memory is performed. After calling malloc, allocate memory in this pool.

[plain] view plaincopy#ifndef CONFIG_PPC

/*

* timer_init() does not exist on PPC systems. The timer is initialized

* and enabled (decrementer) in interrupt_init() here.

*/

Timer_init();

#endif

[plain] view plain copy#ifndef CONFIG_PPC

/*

* timer_init() does not exist on PPC systems. The timer is initialized

* and enabled (decrementer) in interrupt_init() here.

*/

Timer_init();

#endif

If no definition is made: CONFIG_PPC, the timer is initialized. Definition in "arch/arm/cpu/armv7/s5p-common/timer.c"

[plain] view plaincopy#ifdef CONFIG_SPL_BOARD_INIT

Spl_board_init();

#endif

[plain] view plain copy#ifdef CONFIG_SPL_BOARD_INIT

Spl_board_init();

#endif

In the SPL phase, if you need to do something else, you can put it here. The specific implementation can be under BOARDDIR.

[plain] view plaincopyboot_device = spl_boot_device();

Debug("boot device - %d", boot_device);

[plain] view plain copyboot_device = spl_boot_device();

Debug("boot device - %d", boot_device);

Spl_boot_device must be implemented to return from which external device was booted (NAND/SDCARD/NOR..). Can be implemented by the manufacturer or by themselves under BOARDDIR

[plain] view plaincopyswitch (boot_device) {

#ifdef CONFIG_SPL_RAM_DEVICE

Case BOOT_DEVICE_RAM:

Spl_ram_load_image();

Break;

#endif

#ifdef CONFIG_SPL_MMC_SUPPORT

Case BOOT_DEVICE_MMC1:

Case BOOT_DEVICE_MMC2:

Case BOOT_DEVICE_MMC2_2:

Spl_mmc_load_image();

Break;

#endif

#ifdef CONFIG_SPL_NAND_SUPPORT

Case BOOT_DEVICE_NAND:

Spl_nand_load_image();

Break;

#endif

#ifdef CONFIG_SPL_ONENAND_SUPPORT

Case BOOT_DEVICE_ONENAND:

Spl_onenand_load_image();

Break;

#endif

#ifdef CONFIG_SPL_NOR_SUPPORT

Case BOOT_DEVICE_NOR:

Spl_nor_load_image();

Break;

#endif

#ifdef CONFIG_SPL_YMODEM_SUPPORT

Case BOOT_DEVICE_UART:

Spl_ymodem_load_image();

Break;

#endif

#ifdef CONFIG_SPL_SPI_SUPPORT

Case BOOT_DEVICE_SPI:

Spl_spi_load_image();

Break;

#endif

#ifdef CONFIG_SPL_ETH_SUPPORT

Case BOOT_DEVICE_CPGMAC:

#ifdef CONFIG_SPL_ETH_DEVICE

Spl_net_load_image(CONFIG_SPL_ETH_DEVICE);

#else

Spl_net_load_image(NULL);

#endif

Break;

#endif

#ifdef CONFIG_SPL_USBETH_SUPPORT

Case BOOT_DEVICE_USBETH:

Spl_net_load_image("usb_ether");

Break;

#endif

Default:

Debug("SPL: Un-supported Boot Device");

Hang();

}

[plain] view plain copy switch (boot_device) {

#ifdef CONFIG_SPL_RAM_DEVICE

Case BOOT_DEVICE_RAM:

Spl_ram_load_image();

Break;

#endif

#ifdef CONFIG_SPL_MMC_SUPPORT

Case BOOT_DEVICE_MMC1:

Case BOOT_DEVICE_MMC2:

Case BOOT_DEVICE_MMC2_2:

Spl_mmc_load_image();

Break;

#endif

#ifdef CONFIG_SPL_NAND_SUPPORT

Case BOOT_DEVICE_NAND:

Spl_nand_load_image();

Break;

#endif

#ifdef CONFIG_SPL_ONENAND_SUPPORT

case BOOT_DEVICE_ONENAND:

spl_onenand_load_image();

Break;

#endif

#ifdef CONFIG_SPL_NOR_SUPPORT

case BOOT_DEVICE_NOR:

spl_nor_load_image();

Break;

#endif

#ifdef CONFIG_SPL_YMODEM_SUPPORT

case BOOT_DEVICE_UART:

spl_ymodem_load_image();

Break;

#endif

#ifdef CONFIG_SPL_SPI_SUPPORT

case BOOT_DEVICE_SPI:

spl_spi_load_image();

Break;

#endif

#ifdef CONFIG_SPL_ETH_SUPPORT

case BOOT_DEVICE_CPGMAC:

#ifdef CONFIG_SPL_ETH_DEVICE

spl_net_load_image(CONFIG_SPL_ETH_DEVICE);

#else

spl_net_load_image(NULL);

#endif

Break;

#endif

#ifdef CONFIG_SPL_USBETH_SUPPORT

case BOOT_DEVICE_USBETH:

spl_net_load_image(“usb_ether”);

Break;

#endif

Default:

debug(“SPL: Un-supported Boot Device”);

Hang();

}

将image从具体的外部设备中load到ram中。 这里暂时先不分析具体的load过程。

[plain] view plaincopyswitch (spl_image.os) {

case IH_OS_U_BOOT:

debug(“Jumping to U-Boot”);

Break;

#ifdef CONFIG_SPL_OS_BOOT

case IH_OS_LINUX:

debug(“Jumping to Linux”);

spl_board_prepare_for_linux();

jump_to_image_linux((void *)CONFIG_SYS_SPL_ARGS_ADDR);

#endif

Default:

debug(“Unsupported OS image.。 Jumping nevertheless.。”);

}

jump_to_image_no_args(&spl_image);

[plain] view plain copy switch (spl_image.os) {

case IH_OS_U_BOOT:

debug(“Jumping to U-Boot”);

Break;

#ifdef CONFIG_SPL_OS_BOOT

case IH_OS_LINUX:

debug(“Jumping to Linux”);

spl_board_prepare_for_linux();

jump_to_image_linux((void *)CONFIG_SYS_SPL_ARGS_ADDR);

#endif

Default:

debug(“Unsupported OS image.。 Jumping nevertheless.。”);

}

jump_to_image_no_args(&spl_image);

判断image的类型

如果是u-boot,则直接break, 去运行u-boot

如果是Linux,则启动Linux

至此,SPL结束它的生命,控制权交于u-boot或Linux

在接下来的一篇中, 我们会分析当控制权交给u-boot之后, uboot的运行流程

to sum up

SPL移植注意点

s_init: C语言实现此函数, 必须的。 如果是厂商提供的, 一般在arch/arm/cpu/xxx下面。 如果厂商没有提供, 我们可以在BOARDDIR下面实现。 主要完成以下功能

设置CPU的PLL, GPIO管脚复用, memory等

spl_board_init: C语言实现, 可选的。 如果是厂商提供的, 一般在arch/arm/cpu/xxx下面。 如果厂商没有提供, 我们可以在BOARDDIR下面实现。 主要完成的功能自己决定

spl_boot_device: C语言实现, 必须的。 如果是厂商提供的, 一般在arch/arm/cpu/xxx下面。 如果厂商没有提供, 我们可以在BOARDDIR下面实现。 主要完成的功能

返回是从什么设备启动的(NAND/SDCARD/Nor 。。。)。 像Atmel, Samsung的芯片, 都是有办法做这个事情的.

0.8mm Female Pin Header

0.8mm ( 0.031") Female Header Connector
Category:Board To Board Connectors
Sub-Category:Pin Header Female
Type:0.8mm

0.8mm ( 0.031") Female Headers Overview
Whenever there is a need for fitting small-sized connectors in compact devices, the 0.8mm pitch female header, or sometimes referred to as header connector, is ideally suited for this application. Not only does this female header space-savvy, but it is also designed for vacuum pick and place that makes it suitable for high volume automated manufacturing.

Antenk offers these low profile, easy-install, SMT or THM miniature female connector plugs at high quality and affordable China-quoted price, for board-to-board connection, snuggly fitting the pins of a male header and acting as a receptacle.

Assembly and service is simple with either vertical (straight), elevated or at a right angle configuration/orientation, which can dissipate current of about 1.0 A or less in a tape and reel packaging. The filleted corners can also remove shadowing allowing optimization of LED output.

Also, the 0.8mm pitch female headers are made to work in Arduino boards, Arduino Pro and Arduino Mega with either single or double-row female headers, facilitating connections for programming and incorporation into other circuits. They have the perfect height for clearing the USB-B connector and great for stacking multiple shields.

Female header always called as [Header connector", Antenk provide widely range of header connector, from 2.54mm (.100″ inch) pitch to 0.8mm (0.031 inch) pitch. The number of pins (contacts) is from 2 to 40 pins per orw. There are three type: Straight (Dip Vertical), Right angle, SMT (surface mount).

If you can not find the items you interest from above items, welcome to contact us, and you will always get fully responsive from us.

Applications of 0.8mm Pitch Female Headers
Its small size is most suitable for PCB connections of small equipment and devices such as:
Arduino Boards
Architectural and sign lighting
Retail and display lighting
Fluorescent LED retrofit lighting
Cabinet or furniture lighting
Commercial / residential cove lighting
WiFi equipment
Gaming consoles,
Measurement instruments
Medical Diagnostic and Monitoring equipment
Communications: Telecoms and Datacoms
Industrial and Automotive Control and Test


Mount Type: Through-hole vs Surface Mount
At one side of this female header is a series of pins which can either be mounted and soldered directly onto the surface of the PCB (SMT) or placed into drilled holes on the PCB (THM).

Through-Hole (Poke-In)
Best used for high-reliability products that require stronger connections between layers.
Aerospace and military products are most likely to require this type of mounting as these products experience extreme accelerations, collisions, or high temperatures.
Useful in test and prototyping applications that sometimes require manual adjustments and replacements.
0.8mm vertical single row female header, 0.8mm vertical dual row female header, 0.8mm Elevated single row female header, 0.8mm Elevated dual row female Header, 0.8mm right-angle single row female header and 0.8mm right-angle dual row female header are some examples of Antenk products with through-hole mount type.

Surface-Mount
The most common electronic hardware requirements are SMT.
Essential in PCB design and manufacturing, having improved the quality and performance of PCBs overall.
Cost of processing and handling is reduced.
SMT components can be mounted on both side of the board.
Ability to fit a high number of small components on a PCB has allowed for much denser, higher performing, and smaller PCBs.
0.8mm Right-angle Dual Row female header, 0.8mm SMT Single row female header, 0.8mm SMT Dual row female header and 0.8mm Elevated Dual Row female Header are Antenk`s SMT female headers.

Soldering Temperature for 0.8mm Pitch Female Headers
Soldering SMT female connectors can be done at a maximum peak temperature of 260°C for maximum 60 seconds.

Orientation/Pin-Type: Vertical (Straight) and Right-Angle
0.8mm pitch female headers may be further classified into pin orientation as well, such as vertical or straight male header or right-angle female header.

Vertical or Straight Female Header Orientation

One side of the series of pins is connected to PCB board in which the pins can be at a right-angle to the PCB surface (usually called "straight" or [vertical") or.

Right-Angle Female Header Orientation
Parallel to the board's surface (referred to as "right-angle" pins).
Each of these pin-types have different applications that fit with their specific configuration.

PCB Connector Stacking
Profile Above PCB
This type of configuration is the most common way of connecting board-to-board by a connector. First, the stacking height is calculated from one board to another and measured from the printed circuit board face to its highest insulator point above the PCB.

Elevated Sockets/Female Headers
Elevated Sockets aka Stacked sockets/receptacles or Mezzanine are simply stacked female headers providing an exact distance requirement between PCBs that optimizes electrical reliability and performance between PCB boards.

Choosing this type of stacking configuration promotes the following benefits:
Connector Isolation - the contacts are shrouded preventing cable connection mishaps and good guidance for the mating header connectors.
For off-the-shelf wireless PCB module, stacking height is optimized with elevated sockets.
Offers superior strength and rigidity.
Polarisation prevents users from inverted insertion.

Single, Dual or Multiple Number of Rows
For a 1.0mm straight or vertical female header, the standard number of rows that Antenk offers ranges from 1 to 2 rows. However, customization can be available if 3 ,4 or n number of rows is needed by the customer. Also, the number of contacts for the single row is about 2-40 pins while for dual row, the number contacts may vary from 2-80 pins.

Pin Material
The pins of the connector attached to the board have been designed with copper alloy. With customer`s demand the pins can be made gold plated.

Custom 1.0mm Pitch Female Headers
Customizable 1.0 mm pitch female headers are also available, making your manufacturing process way faster as the pins are already inserted in the headers, insulator height is made at the right size and the accurate pin length you require is followed.
Parts are made using semi-automated manufacturing processes that ensure both precision and delicacy in handling the headers before packaging on tape and reel.

Tape and Reel Packaging for SMT Components
Antenk's SMT headers are offered with customizable mating pin lengths, in which each series has multiple number of of circuits, summing up to a thousand individual part number combinations per connector series.

The tape and reel carrier strip ensures that the headers are packaged within accurately sized cavities for its height, width and depth, securing the headers from the environment and maintaining consistent position during transportation.

Antenk also offer a range of custom Tape and reel carrier strip packaging cavities.

Female Header Connector,0.8Mm Female Pin Header,0.8Mm Female Header,0.8Mm Pcb Header, Pitch 0.8mm Board to Board Connectors

ShenZhen Antenk Electronics Co,Ltd , https://www.antenkconn.com