嵌入式ARM64 基于RK3588原生SDK添加用户配置选项./build lunch debian

1 背景

        在我们正常拿到SDK后会有一些配置选项,在使用./build.sh lunch之后会输出一些defautconfig让我们选择,瑞芯微的原厂sdk会提供一些主板的配置选项,但是我们的如果是一块新的主板就需要添加自己的配置选项,本文就讨论如何来添加自己的板卡配置选项。

2 配置介绍

        正常我们配置一套linux系统需要配的目标有uboot,Linux,rootfs,一般情况uboot我们不需要去管,这都是sdk里面做好的,不需要怎么修改。我们需要配的是Liunx的内核和rootfs这两部分。

        以我使用的rk3588_linux6.1_release_v1.2.0_20241220这套sdk为例,使用./build lunch会出现下列选项:

./build.sh lunch
Pick a defconfig:1. rockchip_defconfig
2. rockchip_rk3588_evb1_lp4_v10_defconfig
3. rockchip_rk3588_evb7_v11_defconfig
4. rockchip_rk3588_ipc_evb1_v10_defconfig
5. rockchip_rk3588_multi_ipc_evb1_v10_defconfig
6. rockchip_rk3588s_evb1_lp4x_v10_defconfig
Which would you like? [1]: 

这些选项都是瑞芯微官方主板的一些配置,如果我们直接在这些官方配置里面去改回比较乱,很容易搞混,目标是添加自己的配置又不想去修改原本的。想做到这一点是需要我们去搞懂他这个sdk自动化编译的逻辑。

        在Rockchip提供的Android/LinuxSDK里,顶层通常有一个build.sh脚本,用来封装编译流程,类似于AndroidAOSP的lunch+make。它的主要功能包括:设置环境变量、调用lunch(选择目标平台/产品/编译模式)、调用make或m执行编译、打包生成最终的固件(boot.img,system.img,update.img等)。

        但是我们打开build.sh查看后发现没有lunch这个函数,实际上现在都是通过build-hook机制,在main()有一句run_build_hooks init $OPTIONS实际执行的相当于是run_build_hooks init lunch,然后执行run_hooks "$RK_BUILD_HOOK_DIR" init lunch,这里RK_BUILD_HOOK_DIR=device/rockchip/common/build-hooks相当于run_hooks对这个目录下的所有脚本进行遍历,对所有的脚本执行hook_check看是否支持init lunch命令

run_hooks()
{DIR="$1"shift   # 参数变成:init lunch# Prefer chips' hooks than the common onesfor dir in "$RK_CHIP_DIR/$(basename "$DIR")/" "$DIR"; do[ -d "$dir" ] || continuefor hook in $(find "$dir" -maxdepth 1 -name "*.sh" | sort); do# Ignore unrelated hookshook_check "$hook" "$1" "$2" || continueif ! "$hook" $@; then...fidonedone
}hook_check()
{case "$2" ininit | pre-build | build | post-build) ;;*) return 0 ;;esacCMDS="$(sed -n \"s@^RK_${2//-/_}_CMDS[^ ]*\(.*\)\" # $(realpath "$1")\$@\1@ip" \"$RK_PARSED_CMDS")"if echo "$CMDS" | grep -wq default; thenreturn 0fioption_check "$CMDS" "$3"
}

hook_check()这里关键在 $RK_PARSED_CMDS,它是 output/.parsed_cmds 文件,里面记录了哪些 hook 脚本支持哪些命令。比如 mk-config.sh 里声明了INIT_CMDS="chip defconfig lunch [^:]*_defconfig ..." 这会被解析进 $RK_PARSED_CMDS,最后 hook_check()去执行:device/rockchip/common/scripts/mk-config.sh init lunch ,在mk-config.sh的末尾有init_hook $@,相当于执行 init_hook init lunch,在init_hook里面有lunch|defconfig) shift; choose_defconfig $@ ;; 相当于执行choose_defconfig lunch这就进入了选择defconfig菜单。

rockchip_defconfigs()
{cd "$RK_CHIP_DIR"ls rockchip_defconfig 2>/dev/null || truels *_defconfig | grep -v rockchip_defconfig || true
}choose_defconfig()
{DEFCONFIG_ARRAY=( $(rockchip_defconfigs | grep "$1" || true) )DEFCONFIG_ARRAY_LEN=${#DEFCONFIG_ARRAY[@]}case $DEFCONFIG_ARRAY_LEN in0)error "No available defconfigs${1:+" for: $1"}"return 1;;1)	DEFCONFIG=${DEFCONFIG_ARRAY[0]} ;;*)if [ "$1" = ${DEFCONFIG_ARRAY[0]} ]; then# Prefer exact-matchDEFCONFIG="$1"elsemessage "Pick a defconfig:\n"echo ${DEFCONFIG_ARRAY[@]} | xargs -n 1 | \sed "=" | sed "N;s/\n/. /"local INDEXread -p "Which would you like? [1]: " INDEXINDEX=$((${INDEX:-1} - 1))DEFCONFIG="${DEFCONFIG_ARRAY[$INDEX]}"fi;;esacswitch_defconfig $DEFCONFIG
}INIT_CMDS="chip defconfig lunch [^:]*_defconfig olddefconfig savedefconfig menuconfig config default"
init_hook()
{case "${1:-default}" inchip) shift; choose_chip $@ ;;lunch|defconfig) shift; choose_defconfig $@ ;;*_defconfig) switch_defconfig "$1" ;;olddefconfig | savedefconfig | menuconfig)prepare_configmake $1;;config)prepare_configmake menuconfigmake savedefconfig;;default) prepare_config ;; # End of init*) usage ;;esac
}source "${RK_BUILD_HELPER:-$(dirname "$(realpath "$0")")/../build-hooks/build-helper}"init_hook $@

choose_defconfig()会通过rockchip_defconfigs()搜集.chip目录下后缀为_defconfig的文件放到DEFCONFIG_ARRAY数组,然后打印出来,当我们选择之后会通过switch_defconfig()函数将配置文件保存到output/.config里面。

3 增加配置

        我们先查看一下.chip下面有什么文件,我们先用ls -la命令查看一下device/rockchip下面有哪些目录:

$ ls device/rockchip/ -la
total 24
drwxrwxr-x  5 lubancat lubancat 4096 Sep  5 02:31 .
drwxrwxr-x  3 lubancat lubancat 4096 Sep  3 04:10 ..
lrwxrwxrwx  1 lubancat lubancat   13 Sep  5 02:31 .chip -> .chips/rk3588
drwxrwxr-x  3 lubancat lubancat 4096 Sep  3 04:10 .chips
drwxrwxr-x 13 lubancat lubancat 4096 Sep  3 04:10 common
drwxrwxr-x  2 lubancat lubancat 4096 Sep  3 04:10 .git
-rw-rw-r--  1 lubancat lubancat   24 Sep  3 04:10 .gitignore
lrwxrwxrwx  1 lubancat lubancat   13 Sep  5 02:31 rk3588 -> .chips/rk3588

经过查看发现.chip和rk3588这两个目录都是链接到.chips/rk3588里面的,所以我们真正需要关注是.chips/rk3588目录:

$ ls device/rockchip/.chips/rk3588/ -l
total 48
-rw-rw-r-- 1 lubancat lubancat 1708 Sep  3 04:10 amp_linux.its
-rw-rw-r-- 1 lubancat lubancat 1365 Sep  3 04:10 amp_mcu.its
-rw-rw-r-- 1 lubancat lubancat 1673 Sep  3 04:10 boot4recovery.its
-rw-rw-r-- 1 lubancat lubancat 1430 Sep  3 04:10 boot.its
-rw-rw-r-- 1 lubancat lubancat  477 Sep  3 04:10 parameter-ab.txt
-rw-rw-r-- 1 lubancat lubancat  539 Sep  3 04:10 parameter.txt
lrwxrwxrwx 1 lubancat lubancat   34 Sep  3 04:10 rockchip_defconfig -> rockchip_rk3588_evb7_v11_defconfig
-rw-rw-r-- 1 lubancat lubancat   64 Sep  3 04:10 rockchip_rk3588_evb1_lp4_v10_defconfig
-rw-rw-r-- 1 lubancat lubancat   60 Sep  3 04:10 rockchip_rk3588_evb7_v11_defconfig
-rw-rw-r-- 1 lubancat lubancat  103 Sep  3 04:10 rockchip_rk3588_ipc_evb1_v10_defconfig
-rw-rw-r-- 1 lubancat lubancat  112 Sep  3 04:10 rockchip_rk3588_multi_ipc_evb1_v10_defconfig
-rw-rw-r-- 1 lubancat lubancat   66 Sep  3 04:10 rockchip_rk3588s_evb1_lp4x_v10_defconfig
-rw-rw-r-- 1 lubancat lubancat 1429 Sep  3 04:10 zboot.its

 这里有很多代_defconfig后缀的文件,我们打开一个看一下:

$ vi device/rockchip/.chips/rk3588/rockchip_rk3588_evb7_v11_defconfig 
RK_KERNEL_DTS_NAME="rk3588-evb7-v11-linux"
RK_USE_FIT_IMG=y

 这里其实很简单就是指定了一个RK_KERNEL_DTS_NAME变量,这个变量表明了要编译的内核配置文件。我们新建一个配置文件,将刚才的那个文件改个名字就行了,然后将RK_KERNEL_DTS_NAME改为"yz3588-aiot-v10"

$ cp device/rockchip/.chips/rk3588/rockchip_rk3588_evb7_v11_defconfig device/rockchip/.chips/rk3588/rockchip_rk3588_yeezi_v10_defconfig
$ vi device/rockchip/.chips/rk3588/yz3588_defconfig 
RK_KERNEL_DTS_NAME="yz3588-aiot-v10"
RK_USE_FIT_IMG=y

这个时候我们再执行./build.sh lunch会发现多了一个选项:

$ ./build.sh lunch
Log colors: message notice warning error fatalLog saved at /home/lubancat/rk3588/rk3588_linux6.1_release_v1.2.0_20241220/output/sessions/2025-09-05_02-51-27
Pick a defconfig:1. rockchip_defconfig
2. rockchip_rk3588_evb1_lp4_v10_defconfig
3. rockchip_rk3588_evb7_v11_defconfig
4. rockchip_rk3588_ipc_evb1_v10_defconfig
5. rockchip_rk3588_multi_ipc_evb1_v10_defconfig
6. rockchip_rk3588s_evb1_lp4x_v10_defconfig
7. rockchip_rk3588_yeezi_v10_defconfig
Which would you like? [1]: 

我们的初始配置已经添加成功。

3.1 Linux内核配置

        现在说一下刚才RK_KERNEL_DTS_NAME这个文件的作用,在Linux内核配置中主要是通过dts文件去配置设备树,通过设备树去选择哪些设备需要打开,哪些需要配什么功能。瑞芯微sdk的设备树目录是在kernel/arch/arm64/boot/dts/rockchip/这个目录下,通过ls查看发现有很多rk3588开头的dts和dtsi文件

...
-rw-rw-r--   24364 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5.dtsi
-rw-rw-r--     339 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5-v10.dts
-rw-rw-r--    1886 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5-v10-edp.dts
-rw-rw-r--    1890 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5-v10-edp-linux.dts
-rw-rw-r--     337 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5-v10-linux.dts
-rw-rw-r--    9586 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb4-lp4.dtsi
-rw-rw-r--     304 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb4-lp4-v10.dts
-rw-rw-r--     302 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb4-lp4-v10-linux.dts
-rw-rw-r--    5287 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb5-lp4.dtsi
-rw-rw-r--     304 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb5-lp4-v10.dts
-rw-rw-r--     302 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb5-lp4-v10-linux.dts
-rw-rw-r--    9554 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb6-lp4.dtsi
-rw-rw-r--     304 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb6-lp4-v10.dts
-rw-rw-r--     302 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb6-lp4-v10-linux.dts
-rw-rw-r--   21798 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb7-cam-8x.dtsi
-rw-rw-r--    2710 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb7-imx415.dtsi
-rw-rw-r--   17498 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb7-lp4.dtsi
-rw-rw-r--     339 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb7-lp4-v10.dts
-rw-rw-r--     337 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb7-lp4-v10-linux.dts
-rw-rw-r--    2038 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb7-lp4-v10-rk1608-ipc-8x-linux.dts
-rw-rw-r--     345 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb7-lp4-v11-linux-ipc.dts
-rw-rw-r--     335 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb7-v11.dts
-rw-rw-r--   19537 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb7-v11.dtsi
-rw-rw-r--    2710 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb7-v11-imx415.dtsi
-rw-rw-r--  287281 Sep  3 04:28 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb7-v11-linux.dtb
-rw-rw-r--     333 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb7-v11-linux.dts
-rw-rw-r--    3657 Sep  3 04:10 kernel/arch/arm64/boot/dts/rockchip/rk3588-evb7-v11-rk628-hdmi2csi.dts
...

通过前面的配置发现defconfig调用的是rk3588-evb7-v11-linux.dts文件,打开这个文件:

#include "rk3588-evb7-v11.dtsi"
#include "rk3588-evb7-v11-imx415.dtsi"
#include "rk3588-linux.dtsi"/ {model = "Rockchip RK3588 EVB7 V11 Board";compatible = "rockchip,rk3588-evb7-v11", "rockchip,rk3588";
};

这个文件调用了三个头文件,其中rk3588-linux.dtsi是通用的头文件不需要改,我们选择rk3588-evb7-v11版本改为自己主板的名字,通过复制原有的配置来进行修改比较简单,将rk3588-evb7-v11*开头的文件复制一下得到3个文件,并修改yz3588-aiot-v10-linux.dts文件

$ ls kernel/arch/arm64/boot/dts/rockchip -l
-rw-rw-r-- 1 lubancat lubancat 19537 Sep  5 03:04 yz3588-aiot-v10.dtsi
-rw-rw-r-- 1 lubancat lubancat  2710 Sep  5 03:04 yz3588-aiot-v10-imx415.dtsi
-rw-rw-r-- 1 lubancat lubancat   321 Sep  5 03:12 yz3588-aiot-v10-linux.dts$ vi kernel/arch/arm64/boot/dts/rockchip/yz3588-aiot-v10-linux.dts 
#include "yz3588-aiot-v10.dtsi"
#include "yz3588-aiot-v10-imx415.dtsi"
#include "rk3588-linux.dtsi"/ {model = "Rockchip RK3588 EVB7 V11 Board";compatible = "rockchip,yz3588-aiot-v10", "rockchip,rk3588";
};

这个文件就是我们再defconfig中调用的文件

3.2 Debian配置

        默认在执行build.sh不选择系统的时候是指向的是buildroot,如果要改操作系统就需要更改配置,

$ vi device/rockchip/common/scripts/mk-rootfs.sh
build_hook()
{check_config RK_ROOTFS || falseif [ -z "$1" -o "$1" = rootfs ]; thenROOTFS=${RK_ROOTFS_SYSTEM:-buildroot}elseROOTFS=$1fi

我这里改为使用debian系统,所以就需要修改defconfig选项

$ vi device/rockchip/.chips/rk3588/rockchip_rk3588_yeezi_v10_defconfig 
RK_KERNEL_DTS_NAME="yz3588-aiot-linux"
RK_USE_FIT_IMG=y
RK_ROOTFS_SYSTEM_DEBIAN=y

添加RK_ROOTFS_SYSTEM_DEBIAN=y这就打开了debian系统,然后我们进行编译测试,这里直接使用./build all就可以了,不用单独选择./build.sh debian

需要注意,我们在编译debian的时候可能会报错:

==========================================Start building rootfs(debian)
==========================================Your live-build doesn't support bookworm
Please replace it:
sudo apt-get remove live-build
git clone https://salsa.debian.org/live-team/live-build.git --depth 1 -b debian/1%20230131
cd live-build
rm -rf manpages/po/
sudo make install -j8

因为SDK的rootfs构建逻辑实际上是基于Debianlive-build来生成rootfs镜像的,这里提示系统apt源里的live-build版本比较老,不支持DebianbookwormRockchip的mk-rootfs.sh或hook脚本默认使用bookworm来生成rootfs,所以就提示当前live-build版本太旧。

如果使用提示的方法很可能会连不上网,git不到,有一个办法就是直接下载deb包来解决,注意不要使用太新的软件包,否则会报extlinux错误,我们选择23年的版本就好了,我在这里也折腾了很久,进入https://ftp.debian.org/debian/pool/main/l/live-build/选择一个版本:

下载之后执行sudo dpkg -i live-build_20230502_all.deb || sudo apt-get -f install -y进行安装

3.3 ./build.sh all

到这里所有的配置已经完成,只需要在./build.sh lunch选择刚自定义的配置rockchip_rk3588_yeezi_v10_defconfig执行./build.sh all就会把所有的uboot linux debian编译一遍然后自动打包到output/update/update.img

$ ./build.sh all
Using last kernel version(6.1)==========================================Final configs
==========================================
RK_BOOT_FIT_ITS=/home/lubancat/rk3588/rk3588_linux6.1_release_v1.2.0_20241220/device/rockchip/.chip/boot.its
RK_BOOT_IMG=boot.img
RK_BUILDROOT=y
RK_BUILDROOT_CFG=rockchip_rk3588
RK_CHIP=rk3588
RK_CHIP_FAMILY=rk3588
RK_DEBIAN=y
RK_DEBIAN_ARCH=arm64
RK_DEBIAN_BOOKWORM=y
RK_DEBIAN_MIRROR=mirrors.ustc.edu.cn
RK_DEBIAN_VERSION=bookworm
RK_DEFCONFIG=rockchip_rk3588_yeezi_v10_defconfig
RK_EXTRA_PARTITION_NUM=2
RK_EXTRA_PARTITION_STR=oem:oem:/oem:ext4:defaults:normal:auto:@userdata:userdata:/userdata:ext4:defaults:normal:auto:@@@
RK_KERNEL=y
RK_KERNEL_ARCH=arm64
RK_KERNEL_CFG=rockchip_linux_defconfig
RK_KERNEL_DTS=kernel/arch/arm64/boot/dts/rockchip/yz3588-aiot-v10-linux.dts
RK_KERNEL_IMG=kernel/arch/arm64/boot/Image
RK_KERNEL_VERSION=6.1
RK_KERNEL_VERSION_RAW=6.1
RK_LOADER=y
RK_MISC=y
RK_MISC_BLANK=y
RK_OVERLAY=y
RK_OWNER=lubancat
RK_OWNER_UID=1000
RK_PARAMETER=parameter.txt
RK_RECOVERY=y
RK_RECOVERY_CFG=rockchip_rk3588_recovery
RK_RECOVERY_CPIO_GZ=y
RK_RECOVERY_FIT_ITS=/home/lubancat/rk3588/rk3588_linux6.1_release_v1.2.0_20241220/device/rockchip/.chip/boot4recovery.its
RK_RECOVERY_INITRD_TYPE=cpio.gz
RK_ROOTFS=y
RK_ROOTFS_ASYNC_COMMIT=y
RK_ROOTFS_DEBUG_INFO=y
RK_ROOTFS_EXT4=y
RK_ROOTFS_FSTRIM=y
RK_ROOTFS_FSTRIM_INTERVAL=3600
RK_ROOTFS_GENERATE_LOGS=y
RK_ROOTFS_INPUT_EVENT_DAEMON=y
RK_ROOTFS_IRQBALANCE=y
RK_ROOTFS_LD_CACHE=y
RK_ROOTFS_LOG_GUARDIAN=y
RK_ROOTFS_LOG_GUARDIAN_INTERVAL=10m
RK_ROOTFS_LOG_GUARDIAN_LOG_DIRS=/var/log/,/tmp/
RK_ROOTFS_LOG_GUARDIAN_MIN_SIZE=100M
RK_ROOTFS_OVERLAY=y
RK_ROOTFS_STRIP_MODULES=y
RK_ROOTFS_SYSTEM=debian
RK_ROOTFS_TYPE=ext4
RK_ROOTFS_UDEV_RULES=y
RK_SAVE_TRACKED=y
RK_SESSION=2025-09-05_17-48-38
RK_UBOOT_ARCH=arm64
RK_UBOOT_CFG=rk3588
RK_UPDATE=y
RK_USB_ADBD=y
RK_USB_ADBD_SHELL=/bin/bash
RK_USB_ADBD_TCP_PORT=5555
RK_USB_FW_VER=0x0310
RK_USB_GADGET=y
RK_USB_MANUFACTURER=Rockchip
RK_USB_PRODUCT=rk3xxx
RK_USB_VID=0x2207
RK_USE_FIT_IMG=y
RK_WIFIBT=y
RK_WIFIBT_MODULES=ALL_AP
RK_WIFIBT_RTK_AP=y
RK_YOCTO=y
RK_YOCTO_CHROMIUM=y
RK_YOCTO_DISPLAY_PLATFORM=wayland
RK_YOCTO_MACHINE=rockchip-rk3588-evb
RK_YOCTO_USBMOUNT=y

可以看到

RK_DEFCONFIG=rockchip_rk3588_yeezi_v10_defconfig

RK_ROOTFS_SYSTEM=debian

Unpacking /home/lubancat/rk3588/rk3588_linux6.1_release_v1.2.0_20241220/output/linux-headers/linux-headers-aarch64.tar ...
Debian control file:
Package: linux-headers-6.1-arm64
Source: linux-rockchip (6.1)
Version: 6.1-rockchip
Architecture: aarch64
Section: kernel
Priority: optional
Multi-Arch: foreign
Maintainer: Tao Huang <huangtao@rock-chips.com>
Homepage: https://www.kernel.org/
Description: Kbuild and headers for Rockchip Linux 6.1 arm64 configuration
Packing linux-headers-6.1-arm64_aarch64.deb...
Running mk-kernel.sh - linux-headers-aarch64 succeeded.
Running mk-kernel.sh - linux-headers succeeded.
Running 99-all.sh - build_all succeeded.

最后编译成功,第一次编译需要很久,还有源要更换一下,我是用的是清华的源。这里我们只是把dts这些配置文件搭建出来,还没有进行修改,后面会写一些怎么配置内核的一些方法。

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

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

相关文章

专为石油和天然气检测而开发的基于无人机的OGI相机

专为石油和天然气检测而开发的基于无人机的OGI相机基于无人机的 OGI 相机:&#xff08;Optical Gas Imaging&#xff0c;光学气体成像&#xff09;其实是近几年油气、电力、化工等行业里非常热门的应用方向。什么是 OGI 相机OGI&#xff08;Optical Gas Imaging&#xff09;&am…

iPhone17全系优缺点分析,加持远程控制让你的手机更好用!

知名数码厂商苹果&#xff0c;不久前已官宣将于北京时间9月10日凌晨1点开启发布会&#xff0c;主打对于iPhone 17系列产品介绍&#xff0c;并且和以往不同的是&#xff0c;今年会在购物平台上开启线上直播&#xff0c;还是很有新意的。9.13全平台渠道将开启预售模式&#xff0c…

人工智能-python-深度学习-神经网络VGG(详解)

LeNet 系列之后 —— VGG&#xff08;详解&#xff09;&#xff1a;从原理到 PyTorch 实现 文章目录LeNet 系列之后 —— **VGG&#xff08;详解&#xff09;**&#xff1a;从原理到 PyTorch 实现1. VGG 的发展历史与意义&#xff08;一句话&#xff0b;背景&#xff09;2. VGG…

光伏运维迎来云端革命!AcrelCloud-1200如何破解分布式光伏四大痛点?

在国家“双碳”目标推动下&#xff0c;分布式光伏正迎来爆发式增长&#x1f31e;。甘肃、吉林、云南等多地政策接连落地&#xff0c;整县推进屋顶光伏试点如火如荼&#xff01;然而&#xff0c;快速发展的背后&#xff0c;你是否也遇到过这些“光伏运维之痛”&#xff1f;✨【痛…

将 maven 集成到 idea 后出现 向项目创建模块时出错:null 的问题

1.出现的问题今天想将maven继承到idea出现了一下问题&#xff1a;用生成器里面的也会报错&#xff0c;找了找帖子并没有哪位大佬出现类似错误&#xff0c;于是我解决完想分享一下&#xff0c;如果有不对&#xff0c;请指正。2.解决办法很可能是java 的 版本 与 maven 版本有问题…

类似于 Progress Telerik Fiddler Classic 的 免费 或 开源 HTTP/HTTPS 抓包与调试工具推荐

以下是一些 类似于 Progress Telerik Fiddler Classic 的 免费 或 开源 HTTP/HTTPS 抓包与调试工具推荐&#xff1a;免费 / 开源替代工具推荐 1. Wireshark 免费且开源的网络协议分析工具&#xff0c;支持 Windows、macOS、Linux 等平台。可捕获并深入分析网络流量&#xff0c;…

7.0 热电偶的工作原理

在工业生产过程中&#xff0c;温度是需要测量和控制的重要参数之一。在温度测量中&#xff0c;热电偶的应用极为广泛&#xff0c;它具有结构简单、制造方便、测量范围广、精度高、惯性小和输出信号便于远传等许多优点。另外&#xff0c;由于热电偶是一种无源传感器&#xff0c;…

commons-lang3

概述 提供了许多帮助程序实用程序&#xff0c;特别是字符串操作方法&#xff0c;基本数值方法&#xff0c;对象反射&#xff0c;并发&#xff0c;创建和序列化以及系统属性。maven依赖<dependency><groupId>org.apache.commons</groupId><artifactId>c…

vue-amap组件呈现的效果图如何截图

我们用amap呈现了几个图层后&#xff0c;用户觉得效果很好&#xff0c;想点个按钮直接将这个画面截图下来。 首先我们用Canvas的toDataURL方法可以直接获取图像数据&#xff0c;但是实践发现截图后是空白的。 原因在警告中&#xff1a; 地图的WebGL context 的preserveDrawin…

杰理烧录ERROR: Data error after erasing, address = 0x430000

把CONFIG_BOARD_DEV_KIT关闭&#xff0c;打开CONFIG_BOARD_DEVELOP

超越自动化:为什么说供应链的终局是“AI + 人类专家”的混合智能?

摘要&#xff1a;当前&#xff0c;围绕AI赋能供应链的讨论&#xff0c;大多聚焦于“自动化”带来的降本增效。然而&#xff0c;这仅仅是第一层。当我们的系统面对“黑天鹅”事件时&#xff0c;一个过度依赖自动化的“脆弱”系统可能会瞬间崩溃。本文旨在深入探讨供应链演进的下…

Spine文件导入Unity流程

1、转为Json文件导出 2、对文件进行处理 3、添加Spine的Package包 一、Spine文件导出设置 1、选择Json文件 2、选择导出所在路径 3、点击打包设置 更改图集扩展名 二、文件导出后的设置 1、修改Json的Spine版本 这里必须是3.8 三、下载Unity支持包 1、链接 spine-unit…

Docker Compose healthcheck介绍(监控容器中服务的实际健康状态)数据库健康检查pg_isready

文章目录**功能概述****核心参数详解****配置示例****1. 基础用法****2. 使用数据库健康检查****3. 结合 depends_on 控制启动顺序****高级用法****1. 自定义健康检查脚本****2. 多种健康检查类型**- **HTTP 检查**&#xff1a;- **TCP 端口检查**&#xff1a;- **Redis 检查**…

算法之双指针

在算法设计中&#xff0c;双指针是一种高效优化工具&#xff0c;主要用于线性数据结构&#xff08;如数组&#xff08;数组划分和数组分块常用&#xff09;、链表、字符串&#xff09;&#xff0c;通过控制两个指针的移动轨迹&#xff0c;将原本需要 O (n) 时间复杂度的问题优化…

幂等性、顺序性保障以及消息积压

幂等性 概念 在应用程序中&#xff0c;幂等性就是指对一个系统进行重复调用&#xff08;相同参数&#xff09;&#xff0c;不论请求多少次&#xff0c;这些请求对系统的影响都是相同的效果. 比如数据库的select操作.不同时间两次查询的结果可能不同&#xff0c;但是这个操作…

算法训练营DAY58 第十一章:图论part08

拓扑排序精讲 卡码网&#xff1a;117. 软件构建(opens new window) 题目描述&#xff1a; 某个大型软件项目的构建系统拥有 N 个文件&#xff0c;文件编号从 0 到 N - 1&#xff0c;在这些文件中&#xff0c;某些文件依赖于其他文件的内容&#xff0c;这意味着如果文件 A 依…

如何在Python中使用正则表达式?

在Python中使用正则表达式主要通过内置的re模块实现。正则表达式用于匹配、查找、替换字符串中的特定模式&#xff0c;是处理文本的强大工具。以下是使用正则表达式的核心方法和示例&#xff1a; 一、基本用法步骤 导入re模块&#xff1a;import re定义正则表达式模式&#xff…

用 Trae 玩转 Bright Data MCP 集成

引言 在自动化与智能体浪潮中&#xff0c;Trae 以“开箱即用、所见即所得”的工具编排体验&#xff0c;成为个人与团队落地 AI 工作流的高效选择。本篇将以 Trae 为主角&#xff0c;展示如何通过最少配置完成与 Bright Data MCP 的对接&#xff0c;并快速构建一个可用、可观测…

大数据Spark(六十三):RDD-Resilient Distributed Dataset

文章目录 RDD-Resilient Distributed Dataset 一、RDD五大特性 二、RDD创建方式 RDD-Resilient Distributed Dataset 在 Apache Spark 编程中&#xff0c;RDD&#xff08;Resilient Distributed Dataset&#xff0c;弹性分布式数据集&#xff09;是 Spark Core 中最基本的数…

java,通过SqlSessionFactory实现动态表明的插入和查询(适用于一个版本一个表的场景)

1,测试实体类package org.springblade.sample.test;import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data;/*** Author: 肖扬* CreateTime: 2025-09-05* Description: SqlSessionFactoryTest测试* Version: 1.0*/ Data TableName("session_factory_…