u-boot-2017.07移植到S5PV210单板

下面教程的源代码见此链接,点击打开链接http://download.csdn.net/download/qq_15015097/10043644,

一、添加单板信息  
1、   
cp -r board/samsung/smdkc100 board/samsung/smdkv210  
  
2、进入smdkv210下  
    cd board/samsung/smdkv210/  
    mv smdkc100.c smdkv210.c  

3、修改Kconfig  
    if TARGET_SMDKV210  
  
    config SYS_BOARD  
            default "smdkv210"  
  
    config SYS_VENDOR  
            default "samsung"  
  
    config SYS_SOC  
            default "s5pv2xx"  
  
    config SYS_CONFIG_NAME  
            default "smdkv210"  
  
    endif       
                                                                                                       
4、修改MAINTAINERS  
SMDKV210 BOARD  
M:      Minkyu Kang <mk7.kang@samsung.com>  
S:      Maintained  
F:      board/samsung/smdkv210/  
F:      include/configs/smdkv210.h  
F:      configs/smdkv210_defconfig  

5、修改Makefile  
obj-y   := smdkv210.o  
obj-$(CONFIG_SAMSUNG_ONENAND)   += onenand.o  
obj-y   += lowlevel_init.o  

6、根据MAINTAINERS修改includ/configs/smdkv210.h 和configs/smdkv210_defconfig  
cp include/configs/smdkc100.h include/configs/smdkv210.h  
cp configs/smdkc100_defconfig configs/smdkv210_defconfig
   
7、修改smdkv210_defconfig  
CONFIG_ARM=y
CONFIG_ARCH_S5PV2XX=y
CONFIG_TARGET_SMDKV210=y
CONFIG_IDENT_STRING=" for SMDKV210"
CONFIG_DEFAULT_DEVICE_TREE="s5pv2xx-smdkv210"
CONFIG_BOOTDELAY=3
CONFIG_USE_BOOTARGS=y
CONFIG_BOOTARGS="root=/dev/mtdblock5 ubi.mtd=4 rootfstype=cramfs console=ttySAC0,115200n8 mem=128M  mtdparts=s3c-onenand:256k(bootloader),128k@0x40000(params),3m@0x60000(kernel),16m@0x360000(test),-(UBI)"
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PROMPT="SMDKV210 # "
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_FLASH is not set
CONFIG_CMD_ONENAND=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CMD_CACHE=y
CONFIG_CMD_FAT=y
CONFIG_CMD_MTDPARTS=y
CONFIG_ENV_IS_IN_ONENAND=y
# CONFIG_MMC is not set

8、修改smdkv210.h
#define CONFIG_SAMSUNG		1	/* in a SAMSUNG core */
#define CONFIG_S5P		1	/* which is in a S5P Family */
#define CONFIG_S5PV210		1	/* which is in a S5PV210 */
#define CONFIG_SMDKV210		1	/* working with SMDKV210 */ 

/* DRAM Base */
#define CONFIG_SYS_SDRAM_BASE		0x20000000

/* Text Base */
#define CONFIG_SYS_TEXT_BASE		0x20000000
#define PHYS_SDRAM_1_SIZE	(1024 << 20)	/*1024 MB Bank #1 */
#define CONFIG_SYS_INIT_SP_ADDR	(CONFIG_SYS_SDRAM_BASE + PHYS_SDRAM_1_SIZE)

二、添加S5PV210信息  
1、进入arch/arn目录下  
cd arch/arm  
  
vim Kconfig  
  
/*add by xcl*/
config ARCH_S5PV2XX
	bool "Samsung S5PV2XX"
	select CPU_V7
	select DM
	select DM_SERIAL
	select DM_GPIO
	select DM_I2C 
  
/*add by xcl*/ 
source "arch/arm/mach-s5pv2xx/Kconfig"
  
2、修改Makefile  
vim Makefile  
  
/*add by xcl*/  
machine-$(CONFIG_ARCH_S5PV2XX)		+= s5pv2xx
  
3、复制mach-s5pc1xx  
cp -r mach-s5pc1xx mach-s5pv2xx  
  
4、修改mach-s5pv210目录下Kconfig  
cd mach-s5pv210/  
  
vim Kconfig  
  
if ARCH_S5PV2XX

choice
	prompt "S5PV2XX board select"
	optional

config TARGET_SMDKV210
	bool "Support smdkv210 board"
	select OF_CONTROL

endchoice

config SYS_SOC
	default "s5pv2xx"

source "board/samsung/smdkv210/Kconfig"

endif 
  
5、修改cpu.h  
cd include/mach  
  
vim cpu.h  
#ifndef _S5PV210_CPU_H  
#define _S5PV210_CPU_H  
  
#define S5P_CPU_NAME            "S5P"  
#define S5PV210_ADDR_BASE       0xE0000000  
  
/* S5PV210 */  
#define S5PV210_PRO_ID          0xE0000000  
#define S5PV210_CLOCK_BASE      0xE0100000  
#define S5PV210_GPIO_BASE       0xE0200000  
#define S5PV210_PWMTIMER_BASE   0xE2500000  
#define S5PV210_WATCHDOG_BASE   0xE2700000  
#define S5PV210_UART_BASE       0xE2900000  
#define S5PV210_MMC_BASE        0xEB000000  
#define S5PV210_SROMC_BASE      0xE8000000  
#define S5PV210_DMC0_BASE       0xF0000000  
#define S5PV210_DMC1_BASE       0xF1400000  
#define S5PV210_VIC0_BASE       0xF2000000  
#define S5PV210_VIC1_BASE       0xF2100000  
#define S5PV210_VIC2_BASE       0xF2200000  
#define SPPV210_VIC3_BASE       0xF2300000  
#define S5PV210_NAND_BASE       0xB0E00000  
/*modified by xcl*/
static inline void s5p_set_cpu_id(void)  
{  
        int id = 0;  
        s5p_cpu_id = readl(S5PV210_PRO_ID);  
        s5p_cpu_rev = s5p_cpu_id & 0x000000FF;  
        id = (s5p_cpu_id & 0xFFFFF000) >> 12;  
        if (id == 0x43110) {
			id = s5p_cpu_id & 0x0F;
			switch (id){
				case 0x00:
					s5p_cpu_id = 0x56210;
					break;  
  
                case 0x01:
					s5p_cpu_id = 0xc110;  
               		break;  

                case 0x02:
					s5p_cpu_id = 0xc111;
					break;  

                default :
					break;
						}
			}  
}   
/*add by xcl*/  
IS_SAMSUNG_TYPE(s5pv210, 0x56210)  
  
/*modified by xcl*/
#define SAMSUNG_BASE(device, base)				\
static inline unsigned int samsung_get_base_##device(void)	\
{								\
	if (cpu_is_s5pc100())					\
		return S5PC100_##base;				\
	else if (cpu_is_s5pc110())				\
		return S5PC110_##base;				\
	else if (cpu_is_s5pv210())\
		return S5PV210_##base;\
	else\
		return 0;					\
}
  
  
5、修改board/samsung/smdkv210/lowlevel_init.S 将里面S5PC100全部替换为S5PV210  
  
6、添加soc  
cd arch/arm/cpu/armv7  
vim Makefile  
/*modified by xcl*/  
ifneq (,$(filter s5pv2xx s5pc1xx exynos,$(SOC)))  
obj-y += s5p-common/  
endif  
  
7、添加设备树  
cd arch/arm/dts/  
cp s5pc1xx-smdkc100.dts  s5pv2xx-smdkv210.dts  
cp s5pc110-pinctrl.dtsi  s5pv210-pinctrl.dtsi

8、修改Makefile  
vim Makefile  
/*add by xcl*/  
dtb-$(CONFIG_S5PV210) += s5pv2xx-smdkv210.dtb
  
9、修改设备树 
vim s5pv2xx-smdkv210.dts

#include "skeleton.dtsi"
#include "s5pv210-pinctrl.dtsi"

/ {
	model = "Samsung SMDKV210 based on S5PV210";
	compatible = "samsung,smdkv210", "samsung,s5pv210";

	aliases {
		serial0 = "/serial@e2900000";
		console = "/serial@e2900000";
		pinctrl0 = &pinctrl0;
	};

	pinctrl0: pinctrl@e0200000 {
		compatible = "samsung,s5pv210-pinctrl";
		reg = <0xe0200000 0x1000>;
	};

	serial@e2900000 {
		compatible = "samsung,exynos4210-uart";
		reg = <0xe2900000 0x100>;
		interrupts = <0 51 0>;
		id = <0>;
	};

}; 
这样基本就算添加了单板信息,回到uboot主目录,为了支持SPL故修改
vim common/spl/Kconfig

config SUPPORT_SPL
	bool "enable spl"
	help
	  add by xcl
	  

执行make smdkv210_defconfig
	make menuconfig将SPL编译选项选上
	make
	
将上面编译生成的u-boot.bin下载到开发板发现没有现象,然后我通过点灯调试发现问题出现了
common/board_f.c的函数数组static const init_fnc_t init_sequence_f[]里面的timer_init函数
于是继续跟踪到arch/arm/mach-s5pv2xx/clock.c的s5pc1xx_get_pwm_clk函数,发现这个函数是这样的
static unsigned long s5pc1xx_get_pwm_clk(void)
{
	if (cpu_is_s5pc110())
		return s5pc110_get_pclk();
	else
		return s5pc100_get_pclk();
}
很明显返回的是s5pc100_get_pclk(),所以有问题;类似的函数还有很多个修改的方法有两个。
方法1:把刚开始修改的arch/arm/mach-s5pv2xx/include/mach/cpu.h里面的s5p_set_cpu_id()
修改成u-boot原来的样子,然后再修改arch/arm/mach-s5pv2xx/include/mach/cpu.h的
#define SAMSUNG_BASE(device, base)				\
static inline unsigned int samsung_get_base_##device(void)	\
{								\
		return S5PV210_##base;\
}	

方法2:
	修改arch/arm/mach-s5pv2xx/clock.c
改为:
/*
 * Copyright (C) 2009 Samsung Electronics
 * Minkyu Kang <mk7.kang@samsung.com>
 * Heungjun Kim <riverful.kim@samsung.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/clk.h>

#define CLK_M	0
#define CLK_D	1
#define CLK_P	2

#ifndef CONFIG_SYS_CLK_FREQ_C100
#define CONFIG_SYS_CLK_FREQ_C100	12000000
#endif
#ifndef CONFIG_SYS_CLK_FREQ_C110
#define CONFIG_SYS_CLK_FREQ_C110	24000000
#endif
/*add by xcl*/
#ifndef CONFIG_SYS_CLK_FREQ_V210
#define CONFIG_SYS_CLK_FREQ_V210	24000000
#endif


/* s5pc110: return pll clock frequency */
static unsigned long s5pc100_get_pll_clk(int pllreg)
{
	struct s5pc100_clock *clk =
		(struct s5pc100_clock *)samsung_get_base_clock();
	unsigned long r, m, p, s, mask, fout;
	unsigned int freq;

	switch (pllreg) {
	case APLL:
		r = readl(&clk->apll_con);
		break;
	case MPLL:
		r = readl(&clk->mpll_con);
		break;
	case EPLL:
		r = readl(&clk->epll_con);
		break;
	case HPLL:
		r = readl(&clk->hpll_con);
		break;
	default:
		printf("Unsupported PLL (%d)\n", pllreg);
		return 0;
	}

	/*
	 * APLL_CON: MIDV [25:16]
	 * MPLL_CON: MIDV [23:16]
	 * EPLL_CON: MIDV [23:16]
	 * HPLL_CON: MIDV [23:16]
	 */
	if (pllreg == APLL)
		mask = 0x3ff;
	else
		mask = 0x0ff;

	m = (r >> 16) & mask;

	/* PDIV [13:8] */
	p = (r >> 8) & 0x3f;
	/* SDIV [2:0] */
	s = r & 0x7;

	/* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
	freq = CONFIG_SYS_CLK_FREQ_C100;
	fout = m * (freq / (p * (1 << s)));

	return fout;
}

/* s5pc100: return pll clock frequency */
static unsigned long s5pc110_get_pll_clk(int pllreg)
{
	struct s5pc110_clock *clk =
		(struct s5pc110_clock *)samsung_get_base_clock();
	unsigned long r, m, p, s, mask, fout;
	unsigned int freq;

	switch (pllreg) {
	case APLL:
		r = readl(&clk->apll_con);
		break;
	case MPLL:
		r = readl(&clk->mpll_con);
		break;
	case EPLL:
		r = readl(&clk->epll_con);
		break;
	case VPLL:
		r = readl(&clk->vpll_con);
		break;
	default:
		printf("Unsupported PLL (%d)\n", pllreg);
		return 0;
	}

	/*
	 * APLL_CON: MIDV [25:16]
	 * MPLL_CON: MIDV [25:16]
	 * EPLL_CON: MIDV [24:16]
	 * VPLL_CON: MIDV [24:16]
	 */
	if (pllreg == APLL || pllreg == MPLL)
		mask = 0x3ff;
	else
		mask = 0x1ff;

	m = (r >> 16) & mask;

	/* PDIV [13:8] */
	p = (r >> 8) & 0x3f;
	/* SDIV [2:0] */
	s = r & 0x7;

	freq = CONFIG_SYS_CLK_FREQ_C110;
	if (pllreg == APLL) {
		if (s < 1)
			s = 1;
		/* FOUT = MDIV * FIN / (PDIV * 2^(SDIV - 1)) */
		fout = m * (freq / (p * (1 << (s - 1))));
	} else
		/* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
		fout = m * (freq / (p * (1 << s)));

	return fout;
}


/* s5pc100: return pll clock frequency(add by xcl) */
static unsigned long s5pv210_get_pll_clk(int pllreg)
{
	struct s5pv210_clock *clk =
		(struct s5pv210_clock *)samsung_get_base_clock();
	unsigned long r, m, p, s, mask, fout;
	unsigned int freq;

	switch (pllreg) {
	case APLL:
		r = readl(&clk->apll_con);
		break;
	case MPLL:
		r = readl(&clk->mpll_con);
		break;
	case EPLL:
		r = readl(&clk->epll_con);
		break;
	case VPLL:
		r = readl(&clk->vpll_con);
		break;
	default:
		printf("Unsupported PLL (%d)\n", pllreg);
		return 0;
	}

	/*
	 * APLL_CON: MIDV [25:16]
	 * MPLL_CON: MIDV [25:16]
	 * EPLL_CON: MIDV [24:16]
	 * VPLL_CON: MIDV [24:16]
	 */
	if (pllreg == APLL || pllreg == MPLL)
		mask = 0x3ff;
	else
		mask = 0x1ff;

	m = (r >> 16) & mask;

	/* PDIV [13:8] */
	p = (r >> 8) & 0x3f;
	/* SDIV [2:0] */
	s = r & 0x7;

	freq = CONFIG_SYS_CLK_FREQ_V210;
	if (pllreg == APLL) {
		if (s < 1)
			s = 1;
		/* FOUT = MDIV * FIN / (PDIV * 2^(SDIV - 1)) */
		fout = m * (freq / (p * (1 << (s - 1))));
	} else
		/* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
		fout = m * (freq / (p * (1 << s)));

	return fout;
}


/* s5pc110: return ARM clock frequency */
static unsigned long s5pc110_get_arm_clk(void)
{
	struct s5pc110_clock *clk =
		(struct s5pc110_clock *)samsung_get_base_clock();
	unsigned long div;
	unsigned long dout_apll, armclk;
	unsigned int apll_ratio;

	div = readl(&clk->div0);

	/* APLL_RATIO: [2:0] */
	apll_ratio = div & 0x7;

	dout_apll = get_pll_clk(APLL) / (apll_ratio + 1);
	armclk = dout_apll;

	return armclk;
}

/* s5pv210: return ARM clock frequency (add by xcl)*/
static unsigned long s5pv210_get_arm_clk(void)
{
	struct s5pv210_clock *clk =
		(struct s5pv210_clock *)samsung_get_base_clock();
	unsigned long div;
	unsigned long dout_apll, armclk;
	unsigned int apll_ratio;

	div = readl(&clk->div0);

	/* APLL_RATIO: [2:0] */
	apll_ratio = div & 0x7;

	dout_apll = get_pll_clk(APLL) / (apll_ratio + 1);
	armclk = dout_apll;

	return armclk;
}


/* s5pc100: return ARM clock frequency */
static unsigned long s5pc100_get_arm_clk(void)
{
	struct s5pc100_clock *clk =
		(struct s5pc100_clock *)samsung_get_base_clock();
	unsigned long div;
	unsigned long dout_apll, armclk;
	unsigned int apll_ratio, arm_ratio;

	div = readl(&clk->div0);

	/* ARM_RATIO: [6:4] */
	arm_ratio = (div >> 4) & 0x7;
	/* APLL_RATIO: [0] */
	apll_ratio = div & 0x1;

	dout_apll = get_pll_clk(APLL) / (apll_ratio + 1);
	armclk = dout_apll / (arm_ratio + 1);

	return armclk;
}

/* s5pc100: return HCLKD0 frequency */
static unsigned long get_hclk(void)
{
	struct s5pc100_clock *clk =
		(struct s5pc100_clock *)samsung_get_base_clock();
	unsigned long hclkd0;
	uint div, d0_bus_ratio;

	div = readl(&clk->div0);
	/* D0_BUS_RATIO: [10:8] */
	d0_bus_ratio = (div >> 8) & 0x7;

	hclkd0 = get_arm_clk() / (d0_bus_ratio + 1);

	return hclkd0;
}

/* s5pc100: return PCLKD1 frequency */
static unsigned long get_pclkd1(void)
{
	struct s5pc100_clock *clk =
		(struct s5pc100_clock *)samsung_get_base_clock();
	unsigned long d1_bus, pclkd1;
	uint div, d1_bus_ratio, pclkd1_ratio;

	div = readl(&clk->div0);
	/* D1_BUS_RATIO: [14:12] */
	d1_bus_ratio = (div >> 12) & 0x7;
	/* PCLKD1_RATIO: [18:16] */
	pclkd1_ratio = (div >> 16) & 0x7;

	/* ASYNC Mode */
	d1_bus = get_pll_clk(MPLL) / (d1_bus_ratio + 1);
	pclkd1 = d1_bus / (pclkd1_ratio + 1);

	return pclkd1;
}

/* s5pc110: return HCLKs frequency */
static unsigned long get_hclk_sys(int dom)
{
	struct s5pc110_clock *clk =
		(struct s5pc110_clock *)samsung_get_base_clock();
	unsigned long hclk;
	unsigned int div;
	unsigned int offset;
	unsigned int hclk_sys_ratio;

	if (dom == CLK_M)
		return get_hclk();

	div = readl(&clk->div0);

	/*
	 * HCLK_MSYS_RATIO: [10:8]
	 * HCLK_DSYS_RATIO: [19:16]
	 * HCLK_PSYS_RATIO: [27:24]
	 */
	offset = 8 + (dom << 0x3);

	hclk_sys_ratio = (div >> offset) & 0xf;

	hclk = get_pll_clk(MPLL) / (hclk_sys_ratio + 1);

	return hclk;
}

/* s5pc110: return PCLKs frequency */
static unsigned long get_pclk_sys(int dom)
{
	struct s5pc110_clock *clk =
		(struct s5pc110_clock *)samsung_get_base_clock();
	unsigned long pclk;
	unsigned int div;
	unsigned int offset;
	unsigned int pclk_sys_ratio;

	div = readl(&clk->div0);

	/*
	 * PCLK_MSYS_RATIO: [14:12]
	 * PCLK_DSYS_RATIO: [22:20]
	 * PCLK_PSYS_RATIO: [30:28]
	 */
	offset = 12 + (dom << 0x3);

	pclk_sys_ratio = (div >> offset) & 0x7;

	pclk = get_hclk_sys(dom) / (pclk_sys_ratio + 1);

	return pclk;
}

/* s5pc110: return peripheral clock frequency */
static unsigned long s5pc110_get_pclk(void)
{
	return get_pclk_sys(CLK_P);
}

/* s5pc110: return peripheral clock frequency */
static unsigned long s5pv210_get_pclk(void)
{
	return get_pclk_sys(CLK_P);
}

/* s5pc100: return peripheral clock frequency */
static unsigned long s5pc100_get_pclk(void)
{
	return get_pclkd1();
}

/* s5pc1xx: return uart clock frequency (modified by xcl)*/
static unsigned long s5pc1xx_get_uart_clk(int dev_index)
{
	if (cpu_is_s5pc110())
		return s5pc110_get_pclk();
	else if (cpu_is_s5pv210())
		return s5pv210_get_pclk();
	else
		return s5pc100_get_pclk();
}

/* s5pc1xx: return pwm clock frequency (modified by xcl) */
static unsigned long s5pc1xx_get_pwm_clk(void)
{
	if (cpu_is_s5pc110())
		return s5pc110_get_pclk();
	else if(cpu_is_s5pv210())
		return s5pv210_get_pclk();
	else
		return s5pc100_get_pclk();
}
/* (modified by xcl) */
unsigned long get_pll_clk(int pllreg)
{
	if (cpu_is_s5pc110())
		return s5pc110_get_pll_clk(pllreg);
	else if(cpu_is_s5pv210())
		return s5pv210_get_pll_clk(pllreg);
	else
		return s5pc100_get_pll_clk(pllreg);
}
/* (modified by xcl) */
unsigned long get_arm_clk(void)
{
	if (cpu_is_s5pc110())
		return s5pc110_get_arm_clk();
	else if(cpu_is_s5pv210())
		return s5pv210_get_arm_clk();
	else
		return s5pc100_get_arm_clk();
}

unsigned long get_pwm_clk(void)
{
	return s5pc1xx_get_pwm_clk();
}

unsigned long get_uart_clk(int dev_index)
{
	return s5pc1xx_get_uart_clk(dev_index);
}

void set_mmc_clk(int dev_index, unsigned int div)
{
	/* Do NOTHING */
}

在arch/arm/mach-s5pv2xx/clock.h添加
struct s5pv210_clock {
	unsigned int	apll_lock;
	unsigned char	res1[0x4];
	unsigned int	mpll_lock;
	unsigned char	res2[0x4];
	unsigned int	epll_lock;
	unsigned char	res3[0xc];
	unsigned int	vpll_lock;
	unsigned char	res4[0xdc];
	unsigned int	apll_con;
	unsigned char	res5[0x4];
	unsigned int	mpll_con;
	unsigned char	res6[0x4];
	unsigned int	epll_con;
	unsigned char	res7[0xc];
	unsigned int	vpll_con;
	unsigned char	res8[0xdc];
	unsigned int	src0;
	unsigned int	src1;
	unsigned int	src2;
	unsigned int	src3;
	unsigned char	res9[0xf0];
	unsigned int	div0;
	unsigned int	div1;
	unsigned int	div2;
	unsigned int	div3;
	unsigned int	div4;
	unsigned char	res10[0x1ec];
	unsigned int	gate_d00;
	unsigned int	gate_d01;
	unsigned int	gate_d02;
	unsigned char	res11[0x54];
	unsigned int	gate_sclk0;
	unsigned int	gate_sclk1;
};

这样修改后在timer_init函数就没有错误了。
接着在common/board_f.c的函数数组static const init_fnc_t init_sequence_f[]
里面的env_init函数出错,一直跟踪到env/env.c里面的env_get_default_location
函数出错,这个函数看上去像是u-boot环境变量出发介质的选择。然后我就去配置看
看能不能解决这个问题直接make menuconfig然后依次选择下去environment->select the location of the environment->
environment is not stord,保存编译,
然后用tftp下载到内存:tftp 20000000 u-boot.bin
去执行:go 20000000
哇!!!!!!!!打印出信息了

说明:我这儿用tftp下载bin文件,大家可能感觉奇怪,怎么移植uboot就有tftp下载了呢?
其实我这儿只是学习,所以我现在在移植uboot的时候开发板是从SD卡启动的,SD卡里面下载了开发板
厂家提供的移植好了的uboot,我用这个u-boot就能直接下载裸机程序到内存去运行,感觉比用dnw方便
快捷一些。值得注意的一点是现在现在进去的u-boot.bin是没有进行内存初始化的,如果通过这种方式
下载的裸机程序是不能进行内存初始化,不然会挂掉,所以我是将内存初始化放在SPL代码里面去进行的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值