i.MX6ULL - 从零开始移植uboot-imx_v2020.04_5.4.70_2.3.0

2023-10-26

i.MX6ULL - 从零开始移植uboot-imx_v2020.04_5.4.70_2.3.0



前言

         ~~~~~~~~         一般的,我们做linux开发,移植uboot和kernel的时候并不需要从头开始移植,uboot和kernel庞大又复杂,从头开始移植不仅耗时耗力,而且还很容易出错,没有人比SOC设计人员更熟悉他们自己的芯片,所以我们不管是软件还是硬件的设计都是根据官方出的开发板进行参考设计,并且在设计的过程中,比较重要的部分会和官方保持一致,例如EMMC、内存、NAND、SD卡、网络等,这是因为如果想要启动起uboot内存是必须的,只要比较重要或常用的几个外设跟官方的原理图保持一致或基本保持一致,那么我们下载进官方的uboot或者依据官方给的uboot进行简单更改,就能适配我们自己的板子,大大缩短了我们的开发周期。

uboot只是一个启动linux的作用,所以没必要将项目中使用到的驱动都适配好,因为在uboot阶段如果需要适配驱动是需要去修改源代码的,没有一些经验和基础是做不到这一步的。在项目开发阶段,uboot中最常用的就是控制台(串口)、SD卡、USB、网络这四个,对于i.MX6ULL来说,设计的时候对于这三个外设只要我们跟官方保持一致,那么用官方的uboot拿来就能直接用!毕竟我们项目开发的目的是在linux系统基础上开发应用而已(ps:这也是现在越来越趋向于嵌入式linux应用开发工程师的职位,因为现在有了设备树的开发方式以及半导体厂家做的BSP足够好了,所以嵌入式linux驱动工程师需要做的事越来越少。。。)。


我所使用的开发板是飞凌的,OKMX6UL-C底板+FETMX6UL-C核心板(512MB内存+8G EMMC)。


1、环境搭建

开发环境使用的是ubuntu1804,64位系统。

交叉编译器使用的是linaro提供的gcc7.5.0版本(用最新版本是因为移植的uboot版本也比较新,旧版本的交叉编译器无法编译新版uboot),im6ull支持硬件浮点,所以要使用带hf字样的编译器,如下图:

https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/arm-linux-gnueabihf/

编译uboot和内核所必须的依赖库安装:

sudo apt-get install -y libncurses5-dev lsb-core lib32stdc++6 bison flex lzop git

将交叉编译器通过samba传入到虚拟机ubuntu中,解压:

tar xvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz

然后将交叉编译器加入到系统环境变量,打开/etc/profile文件:

sudo gedit /etc/profile

在最后一行加入并保存退出:

export PATH=$PATH:/home/hello/install/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin

最后使环境变量生效:

source /etc/profile

测试一下交叉编译器是否可用了,输入以下命令查看arm-linux-gnueabihf-gcc的版本号:

arm-linux-gnueabihf-gcc -v

2、NXP官方原版UBOOT编译

下载uboot(下载的很慢):

git clone https://source.codeaurora.org/external/imx/uboot-imx
cd uboot-imx

查看所有分支:

git branch --all

检出分支,这里我检出5.4.70_2.3.0版本,新版本的uboot支持了设备树,基于设备树的uboot可以更刚方便的便于我们移植:

git checkout imx_v2020.04_5.4.70_2.3.0

修改顶层Makefile,指定编译器和架构:

gedit Makefile

找到CROSS_COMPILE,在下方添加以下内容后并保存退出(效果如下图):

ARCH = arm
CROSS_COMPILE = arm-linux-gnueabihf-
  • ARCH:用于指定编译平台是ARM
  • CROSS_COMPILE:指定交叉编译工具链

在configs目录下存在许多mx6ull的配置文件,其中带evk字样的为NXP为他们自己的EVK开发板定制的配置文件。

我使用的板子是SOC是IM6ULL,EMMC版本,且也是根据NXP的EVK开发板参考设计而来,所以使用mx6ull_14x14_evk_emmc_defconfig这个配置文件进行编译。

编译前先清理一下uboot工程:

make distclean

加载编译配置(效果如下图):

make mx6ull_14x14_evk_emmc_defconfig

开始编译:

make -j 2

make的【-j】参数表示多核编译,能够加快编译速度。例如我虚拟机设置的是双核CPU,所以【- j 2】表示双核一块编译uboot源码。

有时候你还会看到make -V=1,V参数表示编译时候的显示的详情。

编译完成(如下图):

其中u-boot-dtb.imx就是我们放到SD卡中刷写进板子的文件。


3、自己的单板UBOOT建立并编译

以上步骤是基于NXP官方EVK开发板进行的编译,下面我们建立自己的目标板进行编译,这样的话方便我们对工程进行管理。

以下步骤参考的是官网EVK开发板所需的配置以及相关文件,以此来建立自己的板子配置。

添加自己板子的配置文件和头文件:

cp configs/mx6ull_14x14_evk_emmc_defconfig configs/mx6ull_14x14_hello_emmc_defconfig
cp include/configs/mx6ullevk.h include/configs/mx6ullhello.h

修改配置文件:

gedit configs/mx6ull_14x14_hello_emmc_defconfig
  • 找到CONFIG_TARGET_MX6ULL_14X14_EVK=y改为CONFIG_TARGET_MX6ULL_14X14_HELLO=y,这是指定编译我们自己的板子

  • 找到CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx6ullevk/imximage.cfg"改为CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx6ullhello/imximage.cfg",这是指定我们板子的配置

  • 找到CONFIG_DEFAULT_DEVICE_TREE="imx6ull-14x14-evk-emmc"改为CONFIG_DEFAULT_DEVICE_TREE="imx6ull-14x14-hello-emmc"

  • 找到CONFIG_DM_74X164=y改为# CONFIG_DM_74X164=y,官网EVK开发板使用了一个74LV594,我们的板子没有使用所以屏蔽掉

  • 找到CONFIG_SOFT_SPI=y改为# CONFIG_SOFT_SPI=y,屏蔽掉软件模拟的SPI,这是官方驱动74LV594用的,我们自己的板子也用不到

修改头文件:

gedit include/configs/mx6ullhello.h

修改宏编译:

添加自己开发板的设备树内容:

添加自己板子描述文件的文件夹:

cp board/freescale/mx6ullevk board/freescale/mx6ullhello -r

修改board\freescale\mx6ullhello目录下的文件。

 cd board/freescale/mx6ullhello/

重命名mx6ullevk.cmx6ullhello.c

mv mx6ullevk.c mx6ullhello.c

修改imximage.cfg文件如下:

gedit imximage.cfg


修改Kconfig文件如下(注意该文件endif后面必须有换行):

gedit Kconfig

修改MAINTAINERS文件如下:

gedit MAINTAINERS

修改Makefile如下:

gedit Makefile

添加自己板子所对应的设备树文件(新版本的uboot支持了设备树,移植阶段可以直接修改设备树进行裁剪移植,更方便开发,这也是选用新版本uboot的原因):

添加imx6ull-14x14-hello-emmc.dts并修改:

cp arch/arm/dts/imx6ull-14x14-evk-emmc.dts arch/arm/dts/imx6ull-14x14-hello-emmc.dts
gedit arch/arm/dts/imx6ull-14x14-hello-emmc.dts

添加imx6ull-14x14-hello.dts并修改:

cp arch/arm/dts/imx6ull-14x14-evk.dts arch/arm/dts/imx6ull-14x14-hello.dts
gedit arch/arm/dts/imx6ull-14x14-hello.dts

添加imx6ul-14x14-hello.dtsiimx6ul-14x14-hello-u-boot.dtsi

cp arch/arm/dts/imx6ul-14x14-evk.dtsi arch/arm/dts/imx6ul-14x14-hello.dtsi
cp arch/arm/dts/imx6ul-14x14-evk-u-boot.dtsi arch/arm/dts/imx6ul-14x14-hello-u-boot.dtsi 

修改arch/arm/dts/Makefile文件,将我们开发板的设备树文件添加进编译项:

gedit arch/arm/dts/Makefile

将我们的开发板添加进编译uboot的编译选项,修改arch/arm/mach-imx/mx6/Kconfig文件:

gedit arch/arm/mach-imx/mx6/Kconfig

找到config TARGET_MX6ULL_14X14_EVK的配置,在该配置下方添加:

config TARGET_MX6ULL_14X14_HELLO
	bool "Support mx6ull_14x14_hello"
	select BOARD_LATE_INIT
	select DM
	select DM_THERMAL
	select MX6ULL
	imply CMD_DM


找到source "board/freescale/mx6ullevk/Kconfig",在下一行将我们板子的配置添加上:

source "board/freescale/mx6ullhello/Kconfig"

如下图所示:


4、SD卡驱动修改

接下来我们检查一下自己板子的SD卡接口和使用到的IO是否和官方EVK开发板使用的一致,因为在uboot移植测试阶段,我们使用SD卡启动uboot是最方便的,所以首先要确保SD卡的驱动是正确的。

一般情况下,SD卡的DATA[0:3]、CLK、CMD引脚是直接使用固定的IO,而CD(Card Detecet)引脚可能会根据自己板子的情况进行更改,我的板子原理图如下:

从原理图可以看到CD引脚使用的是UART1_RTS这个引脚,这个引脚是GPIO1_IO19。

检查uboot设备树文件arch/arm/dts/imx6ul-14x14-hello.dtsi中SD卡的CD引脚是否是用的这个引脚。


检查后没问题,CD引脚跟我的原理图使用的是一致的。


5、官方EVK开发板无用配置移除

官方evk开发板使用了一颗扩展IO的芯片74lv595,我的板子没有用,所以需要去掉该芯片相关内容,屏蔽或删除以下内容:

/*
	aliases {
		spi5 = &{/spi4};
	};
*/

/*
	reg_can_3v3: regulator-can-3v3 {
		compatible = "regulator-fixed";
		regulator-name = "can-3v3";
		regulator-min-microvolt = <3300000>;
		regulator-max-microvolt = <3300000>;
		gpios = <&gpio_spi 3 GPIO_ACTIVE_LOW>;
	};

	spi4 {
		compatible = "spi-gpio";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_spi4>;
		status = "okay";
		pinctrl-assert-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
		gpio-sck = <&gpio5 11 0>;
		gpio-mosi = <&gpio5 10 0>;
		cs-gpios = <&gpio5 7 0>;
		num-chipselects = <1>;
		#address-cells = <1>;
		#size-cells = <0>;

		gpio_spi: gpio@0 {
			compatible = "fairchild,74hc595";
			gpio-controller;
			#gpio-cells = <2>;
			reg = <0>;
			registers-number = <1>;
			registers-default = /bits/ 8 <0x57>;
			spi-max-frequency = <100000>;
		};
	};
*/

&can1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_flexcan1>;
	/* xceiver-supply = <&reg_can_3v3>; */
	status = "okay";
};

&can2 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_flexcan2>;
	/* xceiver-supply = <&reg_can_3v3>; */
	status = "okay";
};

/*
	pinctrl_spi4: spi4grp {
		fsl,pins = <
			MX6UL_PAD_BOOT_MODE0__GPIO5_IO10	0x70a1
			MX6UL_PAD_BOOT_MODE1__GPIO5_IO11	0x70a1
			MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07	0x70a1
			MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08	0x80000000
		>;
	};
*/

至此,我们已经完成了对自己板子的配置的建立,现在用我们板子的配置进行编译,编译前先清理一下:

make distclean
make mx6ull_14x14_hello_emmc_defconfig
make -j 2

编译完成,无问题!

成功编译通过!


6、SD卡烧录uboot并启动测试

下面我们将编译出的u-boot-dtb.imx使用dd命令刻录到SD卡中:

sudo dd if=u-boot-dtb.imx of=/dev/sdb bs=1k seek=1 conv=fsync

注意:SD卡插入ubuntu后,会出现/dev/sdX,具体是/dev/sdb还是/dev/sdc又或者是/dev/sdd要视个人插入ubuntu的USB口设备情况而定。

dd命令可从标准输入或文件中读取数据,根据指定的格式来转换数据,再输出到文件、设备或标准输出。详细命令解释参见:https://www.runoob.com/linux/linux-comm-dd.html

  • if=文件名:输入文件名,默认为标准输入。即指定源文件。
  • of=文件名:输出文件名,默认为标准输出。即指定目的文件。
  • bs=bytes:同时设置读入/输出的块大小为bytes个字节。
  • seek=blocks:从输出文件开头跳过blocks个块后再开始复制。
  • conv=<关键字>,关键字可以有以下11种:
    • conversion:用指定的参数转换文件。
    • ascii:转换ebcdic为ascii
    • ebcdic:转换ascii为ebcdic
    • ibm:转换ascii为alternate ebcdic
    • block:把每一行转换为长度为cbs,不足部分用空格填充
    • unblock:使每一行的长度都为cbs,不足部分用空格填充
    • lcase:把大写字符转换为小写字符
    • ucase:把小写字符转换为大写字符
    • swap:交换输入的每对字节
    • noerror:出错时不停止
    • notrunc:不截短输出文件
    • sync:将每个输入块填充到ibs个字节,不足部分用空(NUL)字符补齐。

将SD卡插入板子卡槽,设置板子上的拨码开关为SD卡启动,控制台打印内容如下:

成功启动!


7、SD卡和eMMC测试

测试一下SD卡和MMC是否都已经识别出来。

mmc list  # 列出所有设备
mmc info # 查看当前设备信息
mmc dev 1 # 切换到emmc


8、网卡驱动移植测试

emmc和SD卡都没问题了,但是网络显示错误,下面我们更改设备树,使网络也能够驱动起来。

同样的,比对官方EVK开发板和我们自己的板子的enet所使用的的IO:


比对后发现我的板子跟官方EVK开发板使用的IO是一致的,但是我的板子的phy还需要硬件复位的引脚,板子上有两路phy,查看原理图得知我的板子fec1的硬件复位IO是GPIO5_IO8,fec2的硬件复位引脚是GPIO5_IO04。

从原理图得到引脚后,继续修改设备树文件arch/arm/dts/imx6ul-14x14-hello.dtsi,由于ENET1和ENET2的复位引脚都是在GPIO5下的,所以需要将这两个IO配置在imouxc_snvs节点下,找到iomuxc节点,在上方添加iomuxc_snvs节点:

&iomuxc_snvs {
	pinctrl-names = "default";
	
	pinctrl_eth2rst: eth2rstgrp {
		fsl,pins = <
			MX6ULL_PAD_SNVS_TAMPER4__GPIO5_IO04  0x17059    /* ENET2 NRST */
		>;    
	};
	
	pinctrl_eth1rst: eth1rstgrp {
		fsl,pins = <
			MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08  0x17059    /* ENET1 NRST */
		>;    
	};
};

如下图所示:


全局搜索MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08、MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04、MX6ULL_PAD_SNVS_TAMPER4__GPIO5_IO04、MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08这四个宏,查看在其他地方有没有被使用,如果有,则屏蔽掉。


找到&fec1&fec2节点,uboot阶段我们只只用fec2即可,修改fec1节点如下:

&fec1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_enet1 &pinctrl_eth1rst>;
	phy-mode = "rmii";
	phy-handle = <&ethphy0>;
	phy-reset-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
	phy-reset-duration = <200>;
	mac-address = [
		0a 1b 2c 3d 4e 5f
	];
	status = "okay";
};

phy-reset-gpios:指定phy的复位引脚且为拉低复位
pht-reset-duration:指定复位的持续时间
mac-address:指定mac地址

修改fec2节点如下:

&fec2 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_enet2 &pinctrl_eth2rst>;
	phy-mode = "rmii";
	phy-handle = <&ethphy1>;
	phy-reset-gpios = <&gpio5 4 GPIO_ACTIVE_LOW>;
	phy-reset-duration = <200>;
	mac-address = [
		a0 b1 c2 d3 e4 f5
	];
	status = "okay";

	mdio {
		#address-cells = <1>;
		#size-cells = <0>;

		ethphy0: ethernet-phy@2 {
			reg = <2>;
			micrel,led-mode = <1>;
			clocks = <&clks IMX6UL_CLK_ENET_REF>;
			clock-names = "rmii-ref";
		};

		ethphy1: ethernet-phy@1 {
			reg = <1>;
			micrel,led-mode = <1>;
			clocks = <&clks IMX6UL_CLK_ENET2_REF>;
			clock-names = "rmii-ref";
		};
	};
};

ethphy0: ethernet-phy@2:这里的2表示的是phy1的地址为2
ethphy1: ethernet-phy@1:这里的1表示的是phy2的地址为1

对比我的原理图,发现phy的地址是一致的:

可选操作:在uboot移植测试阶段可以将随机生成MAC地址使能,方便我们测试使用,但是当移植完了后进入到了上层应用开发阶段建议禁用随机MAC地址,因为使能随机MAC地址的话每次重启板子都会是新的MAC地址,不方便上层程序使用。

打开uboot的图形化配置,使能随机MAC地址:

make menuconfig
[*] Networking support  --->
    [*]   Random ethaddr if unset

补充:如果你没有使能使用随机mac地址,那么需要在uboot中手动设置mac地址,设置命令如下:

setenv ethaddr 00:04:9f:04:d2:35
setenv eth1addr 00:04:9f:04:d2:36
saveenv

其中ethaddr是指定eth0的,eth1addr是指定eth1的,具体需要设置哪一个,需要查看uboot启动时候的Net:这个信息提示。

至此,网络的配置已经完成,再次编译uboot并将u-boot-dtb.imx刻录到SD卡中,板子使用SD卡启动,控制台打印如下(下图为使能随机MAC地址且在设备树中关闭了fec1节点的信息):

下面这些命令是依次设置ip地址、网关、掩码、ubuntu的IP地址、保存环境变量,设置完这环境变量后就可以使用ping命令来测试网卡是否驱动成功了。

setenv ipaddr 192.168.28.234
setenv gatewayip 192.28.28.1
setenv netmask 255.255.255.0
setenv serverip 192.168.28.254
saveenv

在ping一下ubuntu:

没问题,现在我们的网卡驱动就已经移植好了!


9、uboot启动信息修改

启动uboot的时候看到打印信息为EVK,这怎么能忍!

修改gedit board/freescale/mx6ullhello/mx6ullhello.c文件,找到board_late_init函数,修改如下:

gedit gedit board/freescale/mx6ullhello/mx6ullhello.c

找到checkboard函数,修改如下:

重新编译uboot并刻录至SD卡中,开发板选择SD卡启动,控制台打印如下:

完成!


10、uboot增加默认IP地址的环境变量

在开发阶段,在uboot中设置IP地址的操作比较频繁,回复一次默认环境变量,就得重新设置一下,那么有没有什么办法将ip地址增加进boot中呢?

当然有!

只需要在include/configs/mx6ullhello.h文件中新增以下几个宏定义即可!

#define CONFIG_IPADDR       192.168.28.234      /* board ip */
#define CONFIG_SERVERIP     192.168.28.254      /* ubuntu ip */
#define CONFIG_GATEWAYIP    192.168.28.1        /* board gateway ip */
#define CONFIG_NETMASK      255.255.255.0       /* board netmask */

ends…

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

i.MX6ULL - 从零开始移植uboot-imx_v2020.04_5.4.70_2.3.0 的相关文章

随机推荐

  • win10 服务主机:DCOM服务器进程启动器 进程导致电脑卡死解决思路

    新买的笔记本 联想拯救者Y7000 系统 win10专业版 已经禁用了网上可搜的服务 没有win10开始菜单的磁条 原因 总是在开机一段时间后系统卡死 只能强制关机才可以 查找 后来开着任务管理器 放着看到底什么原因造成的 发现 服务主机
  • Ubuntu 16.04 上 CUDA_10.0及cuDNN的安装

    GPU Geforce GTX1060 驱动版本 418 56 最开始打算装CUDA 10 1 nvidia与cuda需相匹配 但是在运行cuda run后出现的用户许可证信息有问题 如图 但是CUDA 10 1与驱动版本是相匹配的 也没有
  • 排序算法总结(长期更新)

    1 最基础的排序算法 1 冒泡排序 思想 每次使用交换的方式将剩余元素中较大的元素放到一端 直到剩余元素为0的时候排序结束 include
  • PCL读取显示点云的两种方式

    读取点云的两种方式 PCL提供了两种pcd点云读写方式 其中PCD Point Cloud Date 点云数据 对应的文件格式为 pcd 是 PCL官方指定格式 具有 ASCII 和 Binary 两种数据存储类型 其中 ASCII 格式的
  • snipaste便捷截图小工具

    Snipaste是一个简单但强大的截图工具 也可以让你将截图贴回到屏幕上 下载并打开Snipaste 按下F1来开始截图 再按F3 截图就在桌面置顶显示了 还可以将剪贴板里的文字或者颜色信息转化为图片窗口 并且将它们进行缩放 旋转 翻转 设
  • 原码 反码 补码 移码

    原码 反码 补码都是有符号定点数的表示方法 一个有符号定点数的最高位为符号位 0是正 1是负 反码 原码 除符号位外 每位取反 补码 反码 1 反码 补码 1 移码 补码符号位取反 原码就是这个数本身的二进制形式 正数的反码和补码都是和原码
  • cmake错误:“未定义的引用”,“未声明的引用”

    描述 在编译代码的时候 经常会出现 未声明的引用 和 未定义的引用 之类的错误 原因 这种情况一般在编译的过程是不会出现问题 在链接的过程会出现这些问题 未声明的引用一般是头文件引入错误 或者找不到头文件 未定义的引用应该是找不到函数的实现
  • omv5-gitlab/gitlab-ce deploy

    omv5 gitlab gitlab ce yml example version 3 6 services web image gitlab gitlab ce latest restart always environment GITL
  • AWS架构图更新2019 - 最强大的AWS架构设计工具

    需要设计您的Amazon Web Services AWS 架构 今天我想介绍一下如何使用Visual Paradigm的云架构设计软件绘制AWS架构图快速而有趣 他们提供世界上最简单 最强大的AWS架构设计工具 全套AWS符号 创建专业的
  • Python-装饰器详解

    装饰器 介绍 在Python中 装饰器是一种特殊的语法 用于修改或增强函数的功能 装饰器是Python的高级特性之一 它允许我们通过在不修改原函数代码的情况下 添加额外的功能或行为 装饰器是一个函数 它接受一个函数作为参数 并返回一个新的函
  • 构建工具Maven/Gradle

    Maven Maven项目对象模型 POM 可以通过一小段描述信息来管理项目的构建 报告和文档的项目管理工具软件 Maven 除了以程序构建能力为特色之外 还提供高级项目管理工具 由于 Maven 的缺省构建规则有较高的可重用性 所以常常用
  • 微信小程序之微信登录

    在开发微信小程序的时候 我们经常需要用到微信登录 通过wx的接口来获取微信用户的信息 然后存储到我们数据库来创建属于我们系统的用户信息 所以我们就要使用到wx login wx getUserProfile 这两个方法 wx login w
  • 向量点乘叉乘等理解和应用

    https baike baidu com item E5 90 91 E9 87 8F 1396519 fr aladdin 1 标量和矢量 2 1 2 3 2 4 6 2 4 6 2 1 2 3 2 矢量和矢量的加减 三角形定则解决向量
  • 程序员3年5年10年三个阶段

    第一阶段 三年 三年对于程序员来说是第一个门槛 这个阶段将会淘汰掉一批不适合写代码的人 这一阶段 我们走出校园 迈入社会 成为一名程序员 正式从书本上的内容迈向真正的企业级开发 我们知道如何团队协作 如何使用项目管理工具 项目版本如何控制
  • 奇偶剪枝算法

    奇偶剪枝是数据结构的搜索中 剪枝的一种特殊小技巧 现假设起点为 sx sy 终点为 ex ey 给定t步恰好走到终点 如图所示 竖走 横走 转弯 易证abs ex sx abs ey sy 为此问题类中任意情况下 起点到终点的最短步数 记做
  • 弱网使用教程

    Network Emulation for Windows Toolkit 1 下载安装包 默认安装 下载地址 https drive google com file d 1jvviwEDRx2UtmpUxe1 Sy94E3wBao5Ot
  • 基于51单片机的红外解码器

    1 简介 本红外解码器是以MCS 51系列AT89C512片机为核心 将红外传感器接收的信号解析出来 LCD1602显示屏将解码数据显示出来 2 总体原理图 硬件组成 单片机最小系统 LCD1602显示屏 IR红外接收器 系统电源 3 程序
  • 数据结构---n皇后问题

    n皇后问题 题目描述 JAVA实现 力扣提交代码 n皇后问题 题目描述 对于四皇后问题的解 放置一个皇后 棋盘被占据的解为 很明显 每行只能放置 且只能放置一个皇后 代码中 queen row 1 来实现的 一个完整的示例 放第一个皇后 放
  • 抖音将会输给快手?时间会证明一切

    为什么快手产品的主界面上没有设置频道分类 这样带来的用户体验真的好吗 在快手一个月之前的员工大会上 入职不久的新员工赵波提出了这个疑问 这个问题不只是他一个人的 之前官方的解答是 不意给用户设置标签是为了保持界面简洁 不对内容做过多的评判
  • i.MX6ULL - 从零开始移植uboot-imx_v2020.04_5.4.70_2.3.0

    i MX6ULL 从零开始移植uboot imx v2020 04 5 4 70 2 3 0 目录 i MX6ULL 从零开始移植uboot imx v2020 04 5 4 70 2 3 0 前言 1 环境搭建 2 NXP官方原版UBOO