uboot源码结构、配置、编译和移植

news2024/11/24 6:35:32

目录

一、uboot源码结构

1.1 uboot源码获取

1.2 uboot的特点

1.3 uboot源码结构

二、uboot配置与编译

2.1uboot配置

2.2 uboot编译

三、uboot移植

3.1添加board信息

3.2再次配置和编译

3.3添加三星加密引导程序

3.4添加调制代码(点灯法)

3.5添加编译脚本

3.6测试uboot

3.7修改UART源码

3.8修改网络初始代码

3.9修改网络配置代码

3.10修改emmc初始代码

3.11添加emmc命令

3.12修改emmc配置代码

3.13修改电源管理相关代码


百度百科-验证

一、uboot源码结构

1.1 uboot源码获取

uboot是一个开源的软件。开源有两层含义。一是可以免费用、二是开放源代码

uboot源码下载

    http://www.denx.de/wiki/U-Boot/

直接百度搜uboot这个就能下载。

或者进入上面那个链接我们进入它的官网下载,uboot是德国一个小组做的。

现在貌似被GitHub管理起来了,反正直接搜索还是去官网他的下载路径都是GitHub的具体什么原因不清楚,这个历史问题和学习无关我们能用就行。

对于不会英语的人很不友好,下载都找不到怎么下建议使用下面链接

uboot官方下载地址,无需密码

Index of /pub/u-boot/

或者:

ftp://ftp.denx.de/pub/u-boot/

uboot版本命名

    前期:uboot-1.2.3

    现在:uboot-2008.01

08年以前uboot是1.2.几1.3.几这样命名08年开始以年份和月份命名。

它的更新是非常频繁的上次更新是两天前。

uboot版本选择

    支持对应的硬件平台

    相对成熟的版本(资料多)

每当发布新的芯片后uboot就会增加对应芯片的版本。一般和处理器同一时期发布的uboot版本对处理器的支持较好。

1.2 uboot的特点

n 代码结构清晰
n 支持丰富的处理器与开发板,易于移植
嵌入式领域还有一个常用的操作系统Vxworks,uboot也可以引导。
VxWorks 操作系统是美国WindRiver公司于1983年设计开发的一种嵌入式 实时操作系统(RTOS),是嵌入式开发环境的关键组成部分。良好的持续发展能力、高性能的内核以及友好的用户开发环境,在嵌入式实时操作系统领域占据一席之地。它以其良好的可靠性和卓越的实时性被广泛地应用在通信、军事、航空、 航天等高精尖技术及实时性要求极高的领域中,如卫星通讯、 军事演习、弹道制导、飞机导航等。在美国的  F-16、FA-18战斗机、 B-2 隐形轰炸机和 爱国者导弹上,甚至连1997年4月在火星表面登陆的 火星探测器、2008年5月登陆的凤凰号,和2012年8月登陆的好奇号也都使用到了VxWorks。
百度百科-验证
n 支持丰富的用户命令
之前专门学过好多
n 支持丰富的网络协议
n 支持丰富的文件系统
文件系统就是帮助我们管理磁盘的工具也是一个软件。大的存储空间一般都自带文件系统。
n 支持丰富的设备驱动
n 更新活跃、用户较多、资料丰富
n 开放源代码
n 较高的稳定性
n 不具有通用性(不同的处理器、开发板uboot不可通用)

1.3 uboot源码结构

由于uboot的源码特别多所以是由很多个文件夹组成的,同类型的源码放到一个文件夹里
平台相关代码

    即与CPU架构或开发板硬件相关的源码,硬件的改动对应的代码也需要进行修改

    arch:与CPU架构相关的源代码

    board:与开发板相关的源代码,包含各种官方评估板对应的源码

api: 这个目录下有很多的用户接口 

arch: 目录下存储的是架构

 这里有很多的架构如果我们使用的arm那么剩下的就可以都删了

在cpu这个文件夹下他又细分了很多的架构。我们使用的A9是V7架构的。

 在使用时我们可以把arch目录除了V7外的其它文件夹内容都删掉。不过其实不删也行,编译的时候不编译它就行了。这里还有makefile文件官方给我们写好了。

board:这个目录下都是一些公司的名字比如三星、诺基亚、ST剩下的也不认识了哈哈。

 在samsung的目录下我们看到还有很多的文件夹,这些就是三星出的一些机器。

 但是这里不能把所有的公司出的开发板都包括,这里都是官方的评估版,评估版就是这些公司在新出一款芯片时为这款芯片做的测试的板子。这个origen就是exynos4412的评估板。不过我使用的板子是华清远见的所以在这里找不到。但是我们可以找和官方用一样芯片的评估板我们自己修改一下。

boards.cfg:这个文件是配置信息

common:这下面全是uboot命令的.c文件

config.mk:也是一个配置文件

COPYING:这是版权文件虽然是开源软件但是也不能乱用

CREDITS:这里是代码贡献者名单包括他们的邮箱,出了问题可以给他们发邮件问,但是也许不会回你,之前都是外国人我今天进GitHub发现贡献者前几名还有几个中国人。

disk:磁盘操作的命令文件夹

readme:一个说明书或者说帮助文档,这个说明书有5000多行都是一些介绍性的的东西。

dos:这里是详细的说明书

drivers:这里面全是驱动文件 

dts:设备树文件夹,后面学习驱动时在详细学习。

examples:里面是例程,在不会写的时候可以参考一下

fs:文件系统,这里面每个文件夹内都是文件系统的源代码和makefile文件这里面ext4是嵌入式领域常用的文件系统。

include:这里是头文件

lib:这里是库

makefile:方便我们编译uboot镜像。它这个makefile是层层调用的每个文件夹下都有,使用make命令后总的makefile文件会调用每层的马克file文件来共同编译出uboot镜像。这个makefile文件非常的复杂。

post:上电自检程序

tools:工具

net:网络文件夹,这里面是uboot支持的一些网络。

 剩下的都是无关紧要的,想要了解就看readme来学习。uboot的源码是非常复杂的想要修改要学习很长的时间。

二、uboot配置与编译

为了保证uboot适用所有的开发板,uboot把所有的开发板都写出来了,需要哪个编译哪个

2.1uboot配置

1.指定当前使用的硬件平台

  make <board_name>_config

  注1:<board_name>为当前使用的开发板的名字

  注2:执行该命令的前提是uboot源码支持该开发板

  注3:该命令必须在uboot源码的顶层目录下执行

 

 出现下面这种提示就是配置成功了。

2.指定编译uboot源码使用的编译器

  在uboot源码顶层目录下的Makefile中指定(CROSS_COMPILE变量)

因为编译过程很复杂所有我们不可能自己去gcc编译。我们用官方写好的makefile就行。

但是我们要先指定编译器

打开顶层目录的makefile文件,搜索CROSS_COMPILE

 我们加上arm的编译工具,不要加那个gcc因为在编译过程中不止需要gcc

 因为它放在了if语句中,但是我们不知道那俩条件是什么所以改一下。

2.2 uboot编译

1.编译uboot

  make

  注1:该命令必须在uboot源码的顶层目录下执行

  注2:该命令执行后在uboot源码顶层目录下生成u-boot.bin

 编译需要大概一分钟。编译完多了几个文件

 多了一个system.map文件和那些u-boot开头的。

make在编译的过程中先将.c和.s编译成.o文件。最后把他们链接(ld)成一个可执行文件绿色的那个u-boot。他是elf格式的。我们肯定不能把他刷到板子上。不过在这之后它还会用objcopy把利用elf文件生成bin文件。这里还有一个srec文件这是符合摩托罗拉的二进制文件。

2.清除编译过程中生成的中间文件

  make clean

  make distclean

  注1:该命令必须在uboot源码的顶层目录下执行

这些中间文件就是.o文件。执行make clean只是清除这些.o文件。执行下面那个会把生成的可执行文件和二进制文件也删除。恢复刚下载的源码状态。

三、uboot移植

因为uboot支持的只是官方的评估板,所以我们没法直接用。

因为咱们和origen的SOC一样都是exynos4412所以不需要修改arch目录的内容。

uboot就先不深入学习了,芯片厂家的开放程度不够,很少需要自己去配置,一般用三星或者全志的芯片都会给我们提供相关的uboot。而且uboot代码量太大了,我们要改就得把他的代码结构,实现过程,具体的代码都研究透。所以又来了一个可以研究一辈子的东西。

3.1添加board信息

拷贝出来一份不要破坏本来的程序

 修改C文件名

因为vi编译器不好操作所以使用图形化的编译器

同样这个也换了

 然后再把这个路径下的h文件复制一份

把这个也改成fs4412

 这句话是编译的时候的提示信息其实该不该不影响用,改了只是让提示信息变过来

打开顶层目录的boards.cfg在origen后加一个我们的信息

这个文件就是一个支持的开发板列表包括一些信息,所以我们要添加一下

3.2再次配置和编译

 试了一下在底层目录运行不好使哈哈。回到顶层配置成功

然后再make,但是现在还是用不了因为我们只是换了名,其它的都没改

3.3添加三星加密引导程序

三星公司为了安全性或者一些“其他原因”它没有全部使用uboot的开源程序,有一部三星自己写好了,我们可以用但是不能看里面是什么

 把这俩目录放到顶层

这之后不要执行make cleanmake distclean,这会将加密文件清除

然后修改一些makefile让原来的代码和三星的引导文件链接到一起

 再这段话后面加上一些东西:

@#./mkuboot

        @split -b 14336 u-boot.bin bl2

        @+make -C sdfuse_q/

        @#cp u-boot.bin u-boot-4212.bin

        @#cp u-boot.bin u-boot-4412.bin

        @#./sdfuse_q/add_sign

        @./sdfuse_q/chksum

        @./sdfuse_q/add_padding

        @rm bl2a*

        @echo

 这些前面都要加一个tab件不然会报错

3.4添加调制代码(点灯法)

vi  arch/arm/cpu/armv7/start.S

打开这个文件

在这个位置加上点亮LED2的操作这样可以保证终端无现象第一时间找到是串口坏了还是uboot没启动导致的问题。干别的也行就是确认用的,不理解这段程序可以看我前面的文章。

GPIO实验_gpio控制实验_宇努力学习的博客-CSDN博客 

3.5添加编译脚本

        使用make命令编译时只链接uboot源码中的相关代码,而我们添加的初始引导加密的        代码不会被连接到u-boot.bin中,所以这里我们自己编写编译脚本build.sh,这个脚本  中除了对uboot源码进行配置和编译外还将初始引导加密代码链接到了u-boot.bin上, 最终生成一个完成的uboot镜像u-boot-fs4412.bin

 先配置后编译  -j是使用多线程编译加快编译速度

然后直接执行就行了

这个u-boot-fs4412就是开发板可执行的文件

3.6测试uboot

 

 把这个bin文件拖出来刷到SD卡上

改成SD卡启动模式

这时候LED2应该是亮的,但是串口没有信息还是需要修改硬件设备的代码。

3.7修改UART源码

$ vi  board/samsung/fs4412/lowlevel_init.S

打开这个文件

添加下面变色的代码:

初始化栈 

 

关闭看门狗

 

 

把这句话注释,上面的操作是为了初始化串口

然后再试试,先创造一个512字节的空镜像

 把他们组合一下

 做一个1M的空镜像用来擦除

 先擦除再烧写

欧克没有问题。我们运行help命令发现不全。

3.8修改网络初始代码

        虽然可以通过终端输入命令,但此时的uboot还不能使用ping、tftp等命令,原因在于        命令都是操作网络的,而uboot源码中网卡的相关配置与我们当前的板子不匹配,所以        我们还要对网卡进行移植。我们的开发板用的网卡是dm9000

打开这个文件             board/samsung/fs4412/fs4412.c

#ifdef  CONFIG_DRIVER_DM9000
#define EXYNOS4412_SROMC_BASE 0X12570000

#define DM9000_Tacs     (0x1) 
#define DM9000_Tcos     (0x1) 
#define DM9000_Tacc     (0x5) 
#define DM9000_Tcoh     (0x1) 
#define DM9000_Tah      (0xC) 
#define DM9000_Tacp     (0x9)   
#define DM9000_PMC      (0x1)  

struct exynos_sromc {
	unsigned int bw;
	unsigned int bc[6];
};

void exynos_config_sromc(u32 srom_bank, u32 srom_bw_conf, u32 srom_bc_conf)
{
	unsigned int tmp;
	struct exynos_sromc *srom = (struct exynos_sromc *)(EXYNOS4412_SROMC_BASE);

	/* Configure SMC_BW register to handle proper SROMC bank */
	tmp = srom->bw;
	tmp &= ~(0xF << (srom_bank * 4));
	tmp |= srom_bw_conf;
	srom->bw = tmp;

	/* Configure SMC_BC register */
	srom->bc[srom_bank] = srom_bc_conf;
}

static void dm9000aep_pre_init(void)
{
	unsigned int tmp;
	unsigned char smc_bank_num = 1;
	unsigned int     smc_bw_conf=0;
	unsigned int     smc_bc_conf=0;
       
	/* gpio configuration */
	writel(0x00220020, 0x11000000 + 0x120);
	writel(0x00002222, 0x11000000 + 0x140);
	/* 16 Bit bus width */
	writel(0x22222222, 0x11000000 + 0x180);
	writel(0x0000FFFF, 0x11000000 + 0x188);
	writel(0x22222222, 0x11000000 + 0x1C0);
	writel(0x0000FFFF, 0x11000000 + 0x1C8);
	writel(0x22222222, 0x11000000 + 0x1E0);
	writel(0x0000FFFF, 0x11000000 + 0x1E8);              
	smc_bw_conf &= ~(0xf<<4);
	smc_bw_conf |= (1<<7) | (1<<6) | (1<<5) | (1<<4);
	smc_bc_conf = ((DM9000_Tacs << 28)
				 | (DM9000_Tcos << 24)
				 | (DM9000_Tacc << 16)
				 | (DM9000_Tcoh << 12)
				 | (DM9000_Tah  << 8)
				 | (DM9000_Tacp << 4)
				 | (DM9000_PMC));
	exynos_config_sromc(smc_bank_num,smc_bw_conf,smc_bc_conf);
}
#endif

 

文件末尾加上‘

#ifdef CONFIG_CMD_NET
int board_eth_init(bd_t *bis)                                                  
{      
	int rc = 0;
#ifdef CONFIG_DRIVER_DM9000
	rc = dm9000_initialize(bis);                                            
#endif                                                                         
	return rc;                                                              
}  
#endif

3.9修改网络配置代码

uboot默认不编译这部分的代码,所以要使用需要配置一下

打开这个文件     include/configs/fs4412.h

这两个undef改成define

 

文件末尾这个前面加上:

#ifdef  CONFIG_CMD_NET
#define CONFIG_NET_MULTI
#define CONFIG_DRIVER_DM9000	1
#define CONFIG_DM9000_BASE	0x05000000
#define DM9000_IO	CONFIG_DM9000_BASE
#define DM9000_DATA	(CONFIG_DM9000_BASE + 4)
#define CONFIG_DM9000_USE_16BIT
#define CONFIG_DM9000_NO_SROM	1
#define CONFIG_ETHADDR	11:22:33:44:55:66
#define CONFIG_IPADDR	192.168.9.200
#define CONFIG_SERVERIP	192.168.9.120
#define CONFIG_GATEWAYIP	192.168.9.1
#define CONFIG_NETMASK	255.255.255.0
#endif

 然后再编译

cat zero.bin u-boot-fs4412.bin > win-u-boot-fs4412.bin 

 sudo dd if=/dev/zero of=clear.bin count=2048

 sudo dd if=/dev/zero of=zero.bin count=1

上面这三个命令总用我就单独粘了一份。

 没啥问题,上面最后加的那段就是网卡一些初始的信息,根据自己需要改就行,当然不改也行后面可以自己设置。

3.10修改emmc初始代码

将资料中“移植相关文件”下的movi.c拷贝到uboot源码的arch/arm/cpu/armv7/exynos/  目录下

这里都是emmc的相关代码,一般也是emmc厂家提供的

 然后再当前目录下的makefile加上我们新加入的文件的.o

board/samsung/fs4412/fs4412.c

再打开这个文件

加上这俩头文件

 

u32 sclk_mmc4;  /*clock source for emmc controller*/
#define __REGMY(x) (*((volatile u32 *)(x)))
#define CLK_SRC_FSYS  __REGMY(EXYNOS4_CLOCK_BASE + CLK_SRC_FSYS_OFFSET)
#define CLK_DIV_FSYS3 __REGMY(EXYNOS4_CLOCK_BASE + CLK_DIV_FSYS3_OFFSET)

int emmc_init()
{
	u32 tmp;
	u32 clock;
	u32 i;
	/* setup_hsmmc_clock */
	/* MMC4 clock src = SCLKMPLL */
	tmp = CLK_SRC_FSYS & ~(0x000f0000);
	CLK_SRC_FSYS = tmp | 0x00060000;
	/* MMC4 clock div */
	tmp = CLK_DIV_FSYS3 & ~(0x0000ff0f);
	clock = get_pll_clk(MPLL)/1000000;

	for(i=0 ; i<=0xf; i++)  {
		sclk_mmc4=(clock/(i+1));

		if(sclk_mmc4 <= 160) //200
		{
			CLK_DIV_FSYS3 = tmp | (i<<0);
			break;
		}
	}
	emmcdbg("[mjdbg] sclk_mmc4:%d MHZ; mmc_ratio: %d\n",sclk_mmc4,i);
	sclk_mmc4 *= 1000000;

	/*
	* MMC4 EMMC GPIO CONFIG
	*
	* GPK0[0]	SD_4_CLK
	* GPK0[1]	SD_4_CMD
	* GPK0[2]	SD_4_CDn
	* GPK0[3:6]	SD_4_DATA[0:3]
	*/
	writel(readl(0x11000048)&~(0xf),0x11000048); //SD_4_CLK/SD_4_CMD pull-down enable
	writel(readl(0x11000040)&~(0xff),0x11000040);//cdn set to be output

	writel(readl(0x11000048)&~(3<<4),0x11000048); //cdn pull-down disable
	writel(readl(0x11000044)&~(1<<2),0x11000044); //cdn output 0 to shutdown the emmc power
	writel(readl(0x11000040)&~(0xf<<8)|(1<<8),0x11000040);//cdn set to be output
	udelay(100*1000);
	writel(readl(0x11000044)|(1<<2),0x11000044); //cdn output 1

	writel(0x03333133, 0x11000040);

	writel(0x00003FF0, 0x11000048);
	writel(0x00002AAA, 0x1100004C);

#ifdef CONFIG_EMMC_8Bit
	writel(0x04444000, 0x11000060);
	writel(0x00003FC0, 0x11000068);
	writel(0x00002AAA, 0x1100006C);
#endif

#ifdef USE_MMC4
	smdk_s5p_mshc_init();
#endif 
}

 把上面代码加到那个宏的后面

把原来的文件换掉

int board_mmc_init(bd_t *bis)
{
	int i, err;
#ifdef CONFIG_EMMC
	err = emmc_init();
#endif
	return err;
}

 文件最末尾加上

#ifdef CONFIG_BOARD_LATE_INIT
#include <movi.h>
int  chk_bootdev(void)//mj for boot device check
{
	char run_cmd[100];
	struct mmc *mmc;
	int boot_dev = 0;
	int cmp_off = 0x10;
	ulong  start_blk, blkcnt;

	mmc = find_mmc_device(0);

	if (mmc == NULL)
	{
		printf("There is no eMMC card, Booting device is SD card\n");
		boot_dev = 1;
		return boot_dev;
 	}
	start_blk = (24*1024/MOVI_BLKSIZE);
	blkcnt = 0x10;

	sprintf(run_cmd,"emmc open 0");
	run_command(run_cmd, 0);

	sprintf(run_cmd,"mmc read 0 %lx %lx %lx",CFG_PHY_KERNEL_BASE,start_blk,blkcnt);
	run_command(run_cmd, 0);

	/* switch mmc to normal paritition */
	sprintf(run_cmd,"emmc close 0");
	run_command(run_cmd, 0);

	return 0;
}

int board_late_init (void)
{
	int boot_dev =0 ;
	char boot_cmd[100];
	boot_dev = chk_bootdev();
	if(!boot_dev)
	{
		printf("\n\nChecking Boot Mode ... EMMC4.41\n");
	}
	return 0;
}
#endif

3.11添加emmc命令

将资料中“移植相关文件”下的cmd_movi.c、cmd_mmc.c、cmd_mmc_fdisk.c拷贝到uboot  源码的common/目录下

然后修改当前目录的makefile

 

COBJS-$(CONFIG_CMD_MMC) += cmd_mmc_fdisk.o
COBJS-$(CONFIG_CMD_MOVINAND) += cmd_movi.o

 在这句话后面加上这两个

将资料中“移植相关文件”下的mmc.c、s5p_mshc.c拷贝到uboot源码的drivers/mmc/  目录下

 

  将资料中“移植相关文件”下的mmc.h、movi.h、s5p_mshc.h拷贝到uboot源码的include/    目录下 

 还要配置makefile

 在蓝色框后面加上红色框的内容

3.12修改emmc配置代码

include/configs/fs4412.h

#define CONFIG_EVT1     1       /* EVT1 */
#ifdef CONFIG_EVT1
#define CONFIG_EMMC44_CH4 //eMMC44_CH4 (OMPIN[5:1] = 4)

#ifdef CONFIG_SDMMC_CH2
#define CONFIG_S3C_HSMMC
#undef DEBUG_S3C_HSMMC
#define USE_MMC2  
#endif

#ifdef CONFIG_EMMC44_CH4
#define CONFIG_S5P_MSHC
#define CONFIG_EMMC             1
#define USE_MMC4  
/* #define CONFIG_EMMC_8Bit */
#define CONFIG_EMMC_EMERGENCY
/*#define emmcdbg(fmt,args...) printf(fmt ,##args) */
#define emmcdbg(fmt,args...)
#endif

#endif /*end CONFIG_EVT1*/
#define CONFIG_CMD_MOVINAND
#define CONFIG_CLK_1000_400_200
#define CFG_PHY_UBOOT_BASE      CONFIG_SYS_SDRAM_BASE + 0x3e00000
#define CFG_PHY_KERNEL_BASE     CONFIG_SYS_SDRAM_BASE + 0x8000

#define BOOT_MMCSD      0x3
#define BOOT_EMMC43     0x6
#define BOOT_EMMC441    0x7
#define CONFIG_BOARD_LATE_INIT	

 再这个文件的最后加上上面的代码,这些都是emmc的配置这个最后是指文件名宏那句话的前面。

接着测试

 

麻了

 第一个错误是有个函数重定义了

终于修好了,有俩函数有个叫board_init  一个叫board_emc_init我把这俩整混了。

 

太感人终于搞出来了。

3.13修改电源管理相关代码

        因为uboot源码中对电源管理芯片的配置与我们的板子不匹配,后续有可能会导致内核        启动卡死,这里还需要对电源管理芯片相关的代码进行修改和配置。

 再makefile里加这句话

include/power/pmic.h

 再上面这个文件里添加声明

 include/configs/fs4412.h 

 board/samsung/fs4412/fs4412.c 

 

 drivers/power/Makefile

 

注释掉这句话

arch/arm/cpu/armv7/s5p-common/cpu_info.c

 

 加上头文件

编译然后做镜像

最后clearSD卡,再把镜像写进去

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/333880.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CMMI-结项管理

结项管理&#xff08;ProjectClosing Management, PCM&#xff09;是指在项目开发工作结束后&#xff0c;对项目的有形资产和无形资产进行清算&#xff1b;对项目进行综合评估&#xff1b;总结经验教训等。结项管理过程域是SPP模型的重要组成部分。本规范阐述了结项管理的规程&…

绘图软件推荐——Diagram Designer

目录 Diagram Designer安装 软件下载 软件图标 Diagram Designer应用 新建页面 工具栏简介 绘制多边形 创建并添加图形模板 图像导出 Diagram Designer安装 软件下载 在腾讯管家&#xff0c;软件管理中 &#xff0c;搜索 Diagram Designer 即可下载软件图标 Diagram Des…

lio-sam学习笔记(三)

前言&#xff1a; 对于lio-sam前端中图像投影和特征提取部分的学习。 一、imageProjection.cpp main函数&#xff1a; int main(int argc, char** argv) {ros::init(argc, argv, "lio_sam");ImageProjection IP;ROS_INFO("\033[1;32m----> Image Project…

训练营day17

110.平衡二叉树 力扣题目链接 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a;一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。 示例 1: 给定二叉树 [3,9,20,null,null,15,7] 返回 true 。 示…

GIS矢量图形多边形地块行政区发光,阴影发光特效实现

先来看下效果: 其实做到发光效果我们必须明白两件事: 1.必须有亮色作为发光色 2.必须有暗色作为衬托色 二者缺一不可 如果你仅仅用了亮色,那么效果是这样的: 注意哦,我使用的是同一个颜色哦,为什么这一次看起来就不是发光呢? 原因很简单,第二幅图我没有加衬托色 ,…

Java基础常见面试题(一)

基础概念与常识 Java 语言有哪些特点? 简单易学&#xff1b;面向对象&#xff08;封装&#xff0c;继承&#xff0c;多态&#xff09;&#xff1b;平台无关性&#xff0c;平台无关性的具体表现在于&#xff0c;Java 是“一次编写&#xff0c;到处运行&#xff08;Write Once&…

手把手教你将Eureka升级Nacos注册中心

由于原有SpringCloud体系版本比较老&#xff0c;最初的注册中心使用的Eureka后期官方无升级方案&#xff0c;配置中心无法在线管理配置&#xff0c;还有实时上下线的问题&#xff0c;因此需要将原有系统的Eureka服务升级Nacos注册心服务。原有版本SpringBoot1.5.15、SpringClou…

Python序列类型之集合

&#x1f490;&#x1f490;&#x1f490;欢迎来到小十一的博客&#xff01;&#xff01;&#xff01; &#x1f3af;博客主页&#xff1a;&#x1f3af;程序员小十一的博客 &#x1f680;博客专栏&#xff1a;&#x1f680;Python入门基础语法 &#x1f337;欢迎关注&#xff…

github报错Key is invalid. You must supply a key in OpenSSH public key format

原因&#xff1a;由于github官方提示 普通类型的ssh不安全&#xff0c;所以改成OpenSSH 解决办法 第一步&#xff1a;打开终端。粘贴下面的文本&#xff0c;替换为您的 GitHub 电子邮件地址。连续按回车键 ssh-keygen -t ed25519 -C "your_emailexample.com"第二步…

JavaWeb入门看这一篇文章就够了

第一章 JavaWeb简介 第1节 什么是web 1web&#xff08;World Wide Web&#xff09;即全球广域网&#xff0c;也称为万维网&#xff0c;它是一种基于超文本和HTTP的、全球性的、动态交互的、跨平台的分布式图形信息系统。是建立在Internet上的一种网络服务&#xff0c;为浏览者…

插入排序基本概念

插入排序基本概念1.插入排序1.1 基本概念1.2 插入排序执行步骤有1.3 对于5个元素的值步骤次数1.4 插入排序大O记法表示2. 将[4,2,7,1,3]进行插入排序 【实战】2.1 第一次轮回步骤2.2 第二次轮回步骤2.3 第三次轮回步骤2.4 第四次轮回步骤3.插入排序代码实现1.插入排序 1.1 基本…

VHDL语言基础-组合逻辑电路-译码器

目录 译码器的设计&#xff1a; 译码器的分类&#xff1a; 常用译码器&#xff1a; 3-8译码器&#xff1a; 3-8译码器的描述&#xff1a; 小结&#xff1a; 译码器的设计&#xff1a; 译码器和编码器是数字系统中广泛使用的多输入多输出组合逻辑部件。 实现译码的组合逻…

锁与原子操作

锁与原子操作 锁 以自增操作为例子&#xff1a; void *func(void *arg) {int *pcount (int *)arg;int i 0;//while (i < 100000) {(*pcount) ; // 并不会到达100000usleep(1);} }int main(){int i 0;for (i 0;i < THREAD_COUNT;i ) {pthread_create(&thid…

2023年,云计算还有发展前景吗?

云计算在促进经济回暖中扮演者不可或缺的角色&#xff0c;疫情期间复工复产都是基于云计算的基础设施&#xff0c;实现远程办公、在线学习、在线看病、在线政务等等。同时由于数字技术在各个领域的渗透和发展&#xff0c;社会整体对于云技术人才、云服务、算力服务等的需求都在…

虹科分享 | 作为域名系统的SPoF

“SPoF”或“单点故障”背后的思想是&#xff0c;如果系统的一部分发生故障&#xff0c;那么整个系统也会发生故障。 这是不可取的。在IT和安全领域&#xff0c;如果一个组件或子组件的故障会导致系统或应用程序严重中断或降级&#xff0c;那么我们通常认为设计有缺陷。 这就…

OpenAI GPT3 + Flask 利用 text-davinci-003 API 制作自己的交互网页教程 | 附源码 和 Github链接

1. OpenAI GPT3 text-davinci-003 API 最近ChatGPT很火&#xff0c;使用与InstructGPT相同的方法&#xff0c;使用来自人类反馈的强化学习 Reinforcement Learning from Human Feedback (RLHF) 来训练该模型&#xff0c;但数据收集设置略有不同。ChatGPT是在 GPT-3.5 系列中的…

JavaWEB-Servlet

目录 Servlet简介Servlet快速入门Servlet配置详解ServletContext 1 Servlet简介 Servlet 运行在服务端的Java小程序&#xff0c;是sun公司提供一套规范&#xff08;接口&#xff09;&#xff0c;用来处理客户端请求、响应给浏览器的动态资源。但servlet的实质就是java代码&a…

101-并发编程详解(上篇)

并发编程详解在学习之前&#xff0c;如果多线程的理解足够&#xff0c;可以往下学习&#xff0c;否则的话&#xff0c;建议先看看26章博客&#xff08;只是建议&#xff09;&#xff0c;注意&#xff1a;可能有些字的字体不对&#xff0c;那么一般是复制粘贴来的&#xff0c;但…

前端构建工具 Vite

文章目录参考环境构建工具构建工具的主要功能目前主流的前端构建工具Vite为什么使用 Vite冷启动WebpackVite热更新优化热更新优化预构建依赖Webpack VS ViteVite 的缺点首屏性能懒加载与 Vite 相关的基本操作获取create-vite创建项目Project nameSelect a frameworkSelect a va…

信息系统与信息化

1.1 信息系统与信息化 1.1.1 信息的基本概念 信息质量属性(掌握)信息传输模型 1.1.2 信息系统的基本概念1.1.3 信息化的基本概念 信息化的五个层次信息化基本内涵信息化的基本概念&#xff08;了解&#xff09;六要素关系图&#xff08;掌握&#xff09; 1.1.4 信息系统生命周…