全志V40/A40I的lichee 的编译

2023-05-16

首先了解一下全志编译lichee的步骤

回顾编译方式:

一般来说都是先配置一下芯片所包含的信息。

	source build.sh config 

在这里插入图片描述
编译;

		source build.sh

摘要:
在这里插入图片描述


正文

上面执行build.sh config 。那么主要深究的是这个过程,是怎么去编译。将我们需要的芯片产商平台,内核版本,系统类型,具体系列。编译进去的。

build.sh代码:
在这里插入图片描述
这是一个比较简单的脚本代码。 跳到buildroot/scripts/目录下执行mkcommon.sh 附带一个参数 $@ 。
看图说话;
在这里插入图片描述
①首先build.sh 脚本执行下来直接到mkcommon.sh脚本,有两个分支②。
②shflags配置和执行mksetup.sh脚本。
③mksetup脚本包含了两个函数 select-board 和 init_defconf 。
④调用到架构内核的配置。
注:select_board和init_defconf函数mkcmd.sh 脚本里面(里面包含大量函数)。
那么先分析mkcommon.sh,在分析shflags和mksetup.sh,主要分析select-board 和 init_defconf 函数, 最后分析到架构上面去。

分析mkcommon.sh

在整一个脚本里面分为五大块执行,分开看可以更加清晰看到整栋源码楼

  • start
  • source shflags
  • define option, format:
  • parse the command-line
  • init default config

start

#!/bin/bash				
BR_SCRIPTS_DIR=`dirname $0`	  *$0  就是自身目录名字 *

source shflags

. ${BR_SCRIPTS_DIR}/shflags/shflags      *执行shflags*
[ -f .buildconfig ] && . .buildconfig           *如果buildconfig 存在即编译 *
. ${BR_SCRIPTS_DIR}/mkcmd.sh			 *执行mkcmd.sh 里面包含大量的命令*

[ -f .buildconfig ] && . .buildconfig

if [ "x$1" = "xconfig" ] ; then	 *判断传来参数是否config*					
. ${BR_SCRIPTS_DIR}/mksetup.sh
exit $?
elif [ "x$1" = "xpack" ] ; then	 *判断传来参数是否 pack*				
	init_defconf
	mkpack
exit $?
elif [ "x$1" = "xpack_debug" ] ; then *判断传来参数是否pack_debug*				
	init_defconf
	mkpack -d card0
exit $?
elif [ "x$1" = "xpack_dump" ] ; then *判断传来参数是否pack_dump*				
	init_defconf
	mkpack -m dump
exit $?
elif [ "x$1" = "xpack_secure" ] ; then *判断传来参数是否pack_secure*		
	init_defconf
	mkpack -s secure
exit $?
elif [ "x$1" = "xpack_prev_refurbish" ] ; then  *判断传来参数是否pack_prev_refurbish*		
    init_defconf
    mkpack -s secure -f prev_refurbish
    exit $?
elif [ "x$1" = "xpack_prvt" ] ; then   *判断传来参数是否pack_prev_refurbish*
	init_defconf
	mkpack -f prvt
exit $?
elif [ "x$1" = "xpack_nor" ] ;then  *判断传来参数是否xpack_nor*
    init_defconf
if [ "x$2" = "xdebug" ] ; then  *判断传来第二个参数是否debug*
    mkpack -f spinor -d card0
 else
    mkpack -f spinor
fi
exit $?
elif [ "x$1" = "xclean" ] ;then  *判断传来参数是否xclean*
	init_defconf
	mkclean
exit $?
elif [ "x$1" = "xdistclean" ] ;then *判断传来参数是否xdistclean*
	init_defconf
	mkdistclean
exit $?
elif [ $# -eq 0 ] ; then
	init_defconf                   *执行 init_defconf 函数*
	mklichee						 *执行 mklichee函数*
exit $?

fi

define option, format:

DEFINE_string 'platform' '' 'platform to build, e.g. sun9iw1p1' 'p'
DEFINE_string 'kernel' 'linux-3.4' 'kernel to build, e.g. 3.3' 'k'
DEFINE_string 'board' '' 'board to build, e.g. evb' 'b'
DEFINE_string 'module' '' 'module to build, e.g. buildroot, kernel, uboot, clean' 'm'
FLAGS_HELP="Top level build script for lichee

Examples:
1. Set the config option
    $ ./build.sh config
2. Build lichee using preset config value
    $ ./build.sh
3. Pack a linux, dragonboard image
    $ ./build.sh pack
4. Build lichee using command argument
    $ ./build.sh -p <platform>
"

parse the command-line

FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"

chip=${FLAGS_platform%%_*}
platform=${FLAGS_platform##*_}
kernel=${FLAGS_kernel}
board=${FLAGS_board}
module=${FLAGS_module}

	if [ "${platform}" = "${chip}" ] ; then
	    platform="linux"
	fi

if [ -z "${module}" ] ; then
    module="all"
fi

if ! init_chips ${chip} || \
   ! init_platforms ${platform} ; then
    mk_error "invalid platform '${FLAGS_platform}'"
    exit 1
fi

if ! init_kern_ver ${kernel} ; then
	mk_error "invalid kernel '${FLAGS_kernel}'"
	exit 1
fi

if [ ${FLAGS_board} ] && \
   ! init_boards ${chip} ${board} ; then
    mk_error "invalid board '${FLAGS_board}'"
    exit 1
fi

init default config

init_defconf
if [ ${module} = "all" ]; then
    mklichee
elif [ ${module} = "boot" ] ; then
    mkboot
elif [ ${module} = "buildroot" ] ; then
    mkbr
elif [ ${module} = "kernel" ] ; then
    mkkernel
elif [ ${module} = "clean" ] ; then
    mkclean
elif [ ${module} = "distclean" ] ; then
    mkdistclean
else
    mk_error "invalid module '${module}'"
    exit 1
fi

exit $?

到这里mkcommon.sh文件的所有命令都执行完成;



蕴涵大量函数的脚本:mkcmd.sh

这个脚本里面身包含了功能性函数,换句话说就是将里面的所有函数命令都包含出来。

这个函数类似我们查看其他库的 -help  命令一样。 使用这个函数介绍mkcmd.sh 这个脚本里面
大体包含什么东西。
function mkhelp()
{
   printf "
    mkscript - lichee build script
    <version>: 1.0.0
   <author >: james
   
  <command>:
    mkboot      build boot
    mkbr        build buildroot
    mkkernel    build kernel
    mkrootfs    build rootfs for linux, dragonboard
    mklichee    build total lichee
    
    mkclean     clean current board output
    mkdistclean clean entires output
    mkpack      pack firmware for lichee
    mkhelp      show this message" 
}

回到mkcommon.sh文件的主体:

	#!/bin/bash				
	BR_SCRIPTS_DIR=`dirname $0`	  *$0  就是自身目录名字 *
*	. ${BR_SCRIPTS_DIR}/shflags/shflags      *执行shflags*
	[ -f .buildconfig ] && . .buildconfig   *如果buildconfig 存在即编译 *
	. ${BR_SCRIPTS_DIR}/mkcmd.sh   *执行mkcmd.sh 里面包含大量的命令*
	[ -f .buildconfig ] && . .buildconfig

既然这个mkcmd.sh的脚本就是配置函数的那么不详细看,用到在去到那里面找。回到mkcommon.sh脚本里面,停留在一大堆循环的最开始的位置。

	if [ "x$1" = "xconfig" ] ; then	

当一开始我们执行下面命令的时候。

source   build.sh config 

config作为配置参数传进来也就是 $1.。判断成立然后执行下面这个脚本。

	. ${BR_SCRIPTS_DIR}/mksetup.sh

## 分析mksetup.sh脚本里面包含了什么东西

. buildroot/scripts/mkcmd.sh *加载mkcmd.sh 里面的命令函数*
function mksetup()
{
    rm -f .buildconfig
    printf "\n"
    printf "Welcome to mkscript setup progress\n"

    select_board		*select_board函数 选择系列配置*
    init_defconf	    *init_defconf函数初始化定义配置*
}

分析这两个函数,都在mkcmd.sh文件里面。

select_board函数

在这里插入图片描述
通过层层查找下去会发现这里面是一个这样的结构。
在这里插入图片描述
经过层层分析之后最后得到一个这样的结构。
select_board—>select_kern_ver->select_plaform->select_chip
这个结构使我们非常熟悉的一个图解。每个函数在里面都实习了自己的选项和功能。也就是下图
在这里插入图片描述
我们所熟悉这个选项结构就是在上面编译出来。

init_defconf 函数
那么看看init_defconf 函数在里面干了些什么东西。
在这里插入图片描述
在里面出来表明路径和配置之外,特别注重的就是这句命令,他就是这个函数里面的太阳。

	defconf=`awk '$1=="'$pattern'" {print $2,$3}' buildroot/scripts/mkrule`
	注:在 buildroot/scripts/mkrule文件下,按照“$pattern” 字符串来查找这个文件的一
	个行字符。 并且将同行第二段和第三段字符打印出来。 在这里需要自行补课awk命令。

那么必须要进入到这mkrule文件里面分析。
在这里插入图片描述
里面却是一堆这样的东西。那么这些玩意是什么呢?
我们将其中的一行(第一行)抽离出来看。将他们分成3段来看。这就是上面提到的$1,$2 ,$3。他们各自代表里面的一段,其实里面就是可以看成 $1=sun8iw1p1_android
在这里插入图片描述

	defconf=`awk '$1=="'$pattern'" {print $2,$3}' buildroot/scripts/mkrule`

意思就是通过 $1 找到对应的行,然后将后面两段的指令都给执行了。在这里详细讲解一下所谓$1 ,$2 ,$3里面究竟是什么东西。

一、sun8iw1p1_android ($1) 其实是我们芯片和平台来的。但是一定的格式命名要求符合,chip_platform。并且chip和platform是必须与芯片平台保持一致。在对照上面图片。其实$1 就是你自己选择芯片和平台。他直接拿过来使用了。所以才有行代码。对应起来每一项都是自己选择么. 。我们之前选择的每一次决定都影响着之后的编译路径。

pattern="${LICHEE_CHIP}_${LICHEE_PLATFORM}_${LICHEE_BOARD}"
相等于:
LICHEE_CHIP = chip  
LICHEE_PLATFORM = android 
LICHEE_BOARD = board 

在这里插入图片描述

二、 sun8i_defconfig ($2) 也就是所谓中间段。这个是配置我们的buildroot配置的。
具体的位置 。里面包含了产商写的配置文件。

 /lichee/buildroot/configs

在这里插入图片描述
三、sun8iw1p1smp_android_defconfig ($3) 在最后的一段里面。这个是配置内核文件。
文件具体位置。里面文件很多有各个产商的内核配置代码。意思就是说当我们编译$1这个平台的芯片和对应的平台。 使用到对应配置内核文件。

	/lichee/linux-3.10/arch/arm/configs

在这里插入图片描述
所以到这里就比较清晰了。其实init_deconf函数,就是将自己选择平台和芯片型号。都会给你找到对应的配置文件和内核文件。他们全部都编译进去。最后有关于init_deconf函数的代码不再分析了仅仅是调整输出目录。配置环境等等。
init_defconf函数分析完了那么整一个mksetup.sh函数了。那么现在还是再次回到mkcommon.sh文件主体里面。会发现到了函数已经到、
define option,
format:
parse the command-line
init default config
这些配置和判断操作了。 代码十分简单看一下就可以了解大概状况。 所以不再详细source build.sh config 这个命令了。但是我们一旦配置完之后是不是还会执行

source build.sh

这个编译命令。那么下面就是开始介绍我们一旦编译 build.sh 这个文件。整体的源码是怎么操作走势如何。


译 source build.sh

前面的操作都是一样的,但是由于没有带参数进来到mkcommon.sh文件。所以在大循环里面将会进入到这个循环里面了。 init_defconf在上面分析了,那么mklichee这个函数要进行分析。
在这里插入图片描述

函数:mklichee

在这里插入图片描述
其中里面的mk_info函数就是一个打印函数,那么就要去到check_eev函数里面遨游。
发现里面也是空空的东西,仅仅是判断这些文件是否存在,做一个出错判断。
在这里插入图片描述
mklichee函数那么只剩下 mkbr && mkkernel && mkrootfs 这句可以分析的了。里面应该还是三个函数并且都要求同是成立,不然就返回1。

mkbr && mkkernel && mkrootfs
[ $? -ne 0 ] && return 1

那么接下来就是里面的三个函数mkbr ,mkkernel ,mkrootfs。看得是十分熟悉名字应该就是我们的buildroot,内核,根文件系统。

###################################################################
在mkcmd.sh文件里面有着这些定义好的路径,要细心对应观察 里面是都会用到的路径。 在下面就不在详细讲解了

	#define importance variable
	LICHEE_TOP_DIR=`pwd`
	LICHEE_BR_DIR=${LICHEE_TOP_DIR}/buildroot
	LICHEE_KERN_DIR=${LICHEE_TOP_DIR}/${LICHEE_KERN_VER}
	LICHEE_TOOLS_DIR=${LICHEE_TOP_DIR}/tools
	LICHEE_OUT_DIR=${LICHEE_TOP_DIR}/out

###################################################################
函数:mkbr
去到LICHEE_BR_DIR 目录下,然后判断scripts/build.sh是否存在。存在即执行 scripts/build.sh脚本。

	function mkbr() {
	    mk_info "build buildroot ..."
	    local build_script="scripts/build.sh"
	    (cd ${LICHEE_BR_DIR} && [ -x ${build_script} ] && ./${build_script})
	    [ $? -ne 0 ] && mk_error "build buildroot Failed" && return 1
	    mk_info "build buildroot OK."
    }

mkkernel函数

function mkkernel() {
	 mk_info "build kernel ..."
	 local build_script="scripts/build.sh"   
	 prepare_toolchain					 /*	prepare_toolchain  函数*/
	    
    # mark kernel .config belong to which platform
    local config_mark="${LICHEE_KERN_DIR}/.config.mark"    ‘去到LCHEE_KERN_DIR路径’

    if [ -f ${config_mark} ] ; then
        if ! grep -q "${LICHEE_PLATFORM}" ${config_mark} ; then
            mk_info "clean last time build for different platform"
            (cd ${LICHEE_KERN_DIR} && [ -x ${build_script} ] && ./${build_script} "clean")
            echo "${LICHEE_PLATFORM}" > ${config_mark}
        fi
    else
        echo "${LICHEE_PLATFORM}" > ${config_mark}
    fi
    (cd ${LICHEE_KERN_DIR} && [ -x ${build_script} ] && ./${build_script})
    [ $? -ne 0 ] && mk_error "build kernel Failed" && return 1
    
    mk_info "build kernel OK."
}

分段来讲解这个作用于内核的函数:
如果/external-toolchain文件存在的话,进去里面编译 mkbr函数。后面就是配置一下各个文件环境。
①: prepare_toolchain 函数

function prepare_toolchain(){
    mk_info "prepare toolchain of ${LICHEE_CHIP}..."
    tooldir=${LICHEE_BR_OUT}/external-toolchain
    if [ ! -d ${tooldir} ] ; then
		mk_info "The toolchain doesn't exsit. So compile the buildroot ..."
        mkbr
    fi

    if ! echo $PATH | grep -q "${tooldir}" ; then
        export PATH=${tooldir}/bin:$PATH
    fi
}

小提一下mkbr函数; 就是执行scripts/build.sh这个脚本。

		function mkbr(){
		    mk_info "build buildroot ..."
		    local build_script="scripts/build.sh"
		    (cd ${LICHEE_BR_DIR} && [ -x ${build_script} ] && ./${build_script})
		    [ $? -ne 0 ] && mk_error "build buildroot Failed" && return 1
		    mk_info "build buildroot OK."
	   }

② : if [ -f ${config_mark} ]
判断这个文件是否存在,存在将会执行循环里面的函数③。不存在将会执行下面这个命令。将平台写进到 ${config_mark}文件里面。 这种类型sysfs操作和proc文件操作。

	 echo "${LICHEE_PLATFORM}" > ${config_mark}

③ (cd ${LICHEE_KERN_DIR} && [ -x KaTeX parse error: Expected 'EOF', got '&' at position 18: …uild_script} ] &̲& ./{build_script} “clean”)
在这里也就说明一下,③和④都是相对来说的。③的功能相对就是一个清空复位的操作。可以明显看到向./${build_script} 里面配置一个 " clean "进去。


④(cd ${LICHEE_KERN_DIR} && [ -x KaTeX parse error: Expected 'EOF', got '&' at position 18: …uild_script} ] &̲& ./{build_script})
这里说下目录去到那里了不然跟丢了不知道跑到那个目录下了这主要是判断这个文件

	 LICHEE_KERN_DIR = lichee/linux-3.10。

scripts/build.sh 是否存在,并且执行。build.sh里面配置ARM架构,连接模块,连接库文件等等一些内核操作。

函数:mkrootfs

function mkrootfs() {
    mk_info "build rootfs ..."

    if [ ${LICHEE_PLATFORM} = "linux" ] ; then
        make O=${LICHEE_BR_OUT} -C ${LICHEE_BR_DIR} target-generic-getty-busybox
        [ $? -ne 0 ] && mk_error "build rootfs Failed" && return 1
        make O=${LICHEE_BR_OUT} -C ${LICHEE_BR_DIR} target-finalize
        [ $? -ne 0 ] && mk_error "build rootfs Failed" && return 1
        make O=${LICHEE_BR_OUT} -C ${LICHEE_BR_DIR} LICHEE_GEN_ROOTFS=y rootfs-ext4
        [ $? -ne 0 ] && mk_error "build rootfs Failed" && return 1
        cp ${LICHEE_BR_OUT}/images/rootfs.ext4 ${LICHEE_PLAT_OUT}
	if [ -f "${LICHEE_BR_OUT}/images/rootfs.squashfs" ]; then
		cp ${LICHEE_BR_OUT}/images/rootfs.squashfs ${LICHEE_PLAT_OUT}
	fi
        if [ "x$PACK_TINY_ANDROID" = "xtrue" ];then
            packtinyandroid
        fi
    elif [ ${LICHEE_PLATFORM} = "dragonboard" ] ; then
		echo "Regenerating dragonboard Rootfs..."
        (
            cd ${LICHEE_BR_DIR}/target/dragonboard; \
        	if [ ! -d "./rootfs" ]; then \
        	echo "extract dragonboard rootfs.tar.gz"; \
        	tar zxf rootfs.tar.gz; \
        	fi
        )
		mkdir -p ${LICHEE_BR_DIR}/target/dragonboard/rootfs/lib/modules
        rm -rf ${LICHEE_BR_DIR}/target/dragonboard/rootfs/lib/modules/*
        cp -rf ${LICHEE_KERN_DIR}/output/lib/modules/* 		
        ${LICHEE_BR_DIR}/target/dragonboard/rootfs/lib/modules/
        (cd ${LICHEE_BR_DIR}/target/dragonboard; ./build.sh)
        cp ${LICHEE_BR_DIR}/target/dragonboard/rootfs.ext4 ${LICHEE_PLAT_OUT}
    else
        mk_info "skip make rootfs for ${LICHEE_PLATFORM}"
    fi

    mk_info "build rootfs OK."
}

关于这函数的作用,一进来就判断平台是不是Linux,很明显我们的平台是android,内核是Linux-3.10。所以就没有进入循环里面。
主要实现这两行代码:

去到这个文件目录下:
		cd  ${LICHEE_BR_DIR}/target/dragonboard
创建 一个modules目录:
·		${LICHEE_BR_DIR}/target/dragonboard/rootfs/lib/modules
清空里面的内容    
		rm -rf ${LICHEE_BR_DIR}/target/dragonboard/rootfs/lib/modules/*
拷贝这个目录下的文件到刚才创建的目录下:
	  cp -rf ${LICHEE_KERN_DIR}/output/lib/modules/*   		
	  ${LICHEE_BR_DIR}/target/dragonboard/rootfs/lib/modules/
      (cd ${LICHEE_BR_DIR}/target/dragonboard; ./build.sh)

到这里就将真个编译流程都走完一遍了,但是会发现一些到内核配置和根文件系统等等的build.sh 脚本都没有详细讲解, 包含了产家的配置等需要自己去看看或者稍微浏览一下这个是产家提供的一些对应芯片内容。

还有一个章节就是讲解:source build.sh clean
在这里插入图片描述
那么回到 mkcommon.sh 脚本里面。在第二大层的循环分支里面包含了:

	elif [ "x$1" = "xclean" ] ;then
	init_defconf
	mkclean
	exit $?								

里面的里面主要的两个函数,一个init_defconf在前面已经讲过了。只要分析
mkclean这个函数:

	function mkclean() {
    clkernel
	mk_info "clean product output in ${LICHEE_PLAT_OUT} ..."
	cd ${LICHEE_PLAT_OUT}
	ls | grep -v "buildroot" | xargs rm -rf     *  查找到有关的内容删除掉*
	cd - > /dev/null
}

这个函数相对简单点,一进来直接跑到 clkernel 函数里面的进行操作。看这个名字就知道应该是释放有关内核的资源。 clkernel函数相关:

function clkernel() {
    mk_info "clean kernel ..."
    local build_script="scripts/build.sh"
    prepare_toolchain
    (cd ${LICHEE_KERN_DIR} && [ -x ${build_script} ] && ./${build_script} "clean")
    mk_info "clean kernel OK."
}	

首先进入这个函数里面的话,那么直接执行这个函数了 prepare_toolchain。然后去到
对应的配置内核的目录下。判断这个文件(${build_script})是否存在并且,传clean进去
,放之前配置内核的东西都往下面传递全部释放之前使用到的动态资源。
现在主要分析prepare_toolchain函数:其实里面就是一个工具链。

function prepare_toolchain()  {
    mk_info "prepare toolchain of ${LICHEE_CHIP}..."
    tooldir=${LICHEE_BR_OUT}/external-toolchain
    if [ ! -d ${tooldir} ] ; then
		mk_info "The toolchain doesn't exsit. So compile the buildroot ..."
        mkbr
    fi

    if ! echo $PATH | grep -q "${tooldir}" ; then
        export PATH=${tooldir}/bin:$PATH
    fi
}

当工具链不存在的话编译buildroot,构建buildroot。

在这里就分析有关于lichee目录下的build.sh脚本以及他们常用传参,也就完结了。里面其实还有很多可以使用的参数作为测试版本,调试版本等等。需要细心观察了。

关注微信公众号:一起进步
在这里插入图片描述

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

全志V40/A40I的lichee 的编译 的相关文章

  • 小梅哥——38译码器

    三八译码器 xff0c 即是 3 种输入状态翻译成 8 种输出状态 真值表 代码展示 module decoder 3 8 a b c out input a 输入端口a input b 输入端口b input c 输入端口c output
  • 基本RS触发器(SR锁存器)

    一 前言 SR锁存器 Set Reset Latch 是静态存储单元当中最基本 xff0c 也是电路结构最简单的一种 xff0c 通常由两个或非门或者与非门组成 其中S表示Set xff0c R表示Reset 则S D称为置位端或置1输入端
  • 01-RTOS

    对于裸机而言 xff0c 对于RTOS而言 即 xff1a 对于裸机 xff0c 打游戏意味着不能回消息 回消息意味着不能打游戏 对于RTOS 打游戏和裸机的切换只需要一个时间片节拍 1ms 从宏观来看 就是同时进行的两件事 xff08 但
  • uORB笔记

    不同的类调用同一函数orb subscribe ORB ID vehicle gps position xff0c 来订阅GPS信息是 xff0c 该函数返回的值不同 xff0c 也就是说每个订阅者针对同一主题 xff0c 在调用函数orb
  • STM32 SystemInit()函数学习总结

    拿到程序后如何看系统时钟 xff1f User文件夹 system stm32f4xx程序 xff0c 先找systemcoreclock 系统时钟 xff09 但是这里这么多个系统时钟应该如何选择 点击魔法棒 xff0c 然后点击C C
  • FPGA IP核之PLL四种输出模式的理解

    一 源同步模式 使得进入管脚时的数据和上升沿的相位关系与到达芯片内部第一级寄存器时数据和上升沿的相位关系保持不变 xff08 通过调整内部的布局布线延时做到的 xff0c 用于数据接口 xff0c 特别是高速的情况下 xff09 详细理解
  • FPGA_边沿监测理解

    一 简易频率计设计中为什么一定要获取下降沿 gate a 实际闸门信号 gate a stand 将实际闸门信号打一拍之后的信号 gate a fall s 下降沿标志信号 cnt clk stand Y值 xff0c 即在实际闸门信号下
  • HAL库 STM32 串口通信

    一 实验条件 将STM32的PA9复用为串口1的TX xff0c PA10复用为串口1的RX STM32芯片的输出TX和接收RX与CH340的接收RX和发送TX相连 xff08 收发交叉且PCB上默认没有相连 xff0c 所以需要用P3跳线
  • 全局变量和局部变量

    一 C语言由四种地方可以定义变量 在函数外部定义的是全局变量 xff08 这里的函数包括main函数 xff09 在头文件中定义的是全局变量 在函数或语句块内部定义的是局部变量 函数的参数是该函数的局部变量 全局变量 xff0c 在定义位置
  • 单片机中断

    蓝桥杯单片机之中断 1 中断含义及过程 中断是指CPU在处理A事情时 xff0c 发现B请求CPU立刻去处理 xff08 中断发生 xff09 xff0c 于是CPU去处理B xff08 中断服务 xff09 xff0c 处理完B后又再次回
  • AprilTag的使用、相关问题及解决方法

    使用棋盘格标定相机 安装标定功能包 span class token function sudo span span class token function apt get span span class token function i
  • 对接海康综合安防管理平台经验总结

    前言 xff1a 因业务需要对接海康威视的综合安防管理平台获得下属所管理的摄像头 xff0c 根据摄像头code获得监控视频流信息 1 详情可以浏览海康开放平台 xff0c 在官网上有对应的接入指南以及开放的API接口 前提是本地已部署了海
  • 【环境配置】Visual Studio opencv配置

    需求 在Visual Studio环境中编写C 43 43 代码 xff0c 同时可以调用OpenCV的相关代码 1 安装OpenCV 访问 opencv 官网下载对应平台的库文件 注意 xff1a Visual Studio和OpenCV
  • MySQL常见用法

    文章目录 一 时间类1 1 DATE SUB 函数1 2 NOW CURDATE CURTIME DATE 函数1 3 实战 二 统计类三 字符类3 1 LOCATE 函数3 2 concat 函数3 3 concat ws 函数3 4 g
  • 牢记公式,ardupilot EKF2就是纸老虎(四)!

    版权声明 xff1a 本文为博主原创文章 xff0c 转载请附上博文链接 xff01 四 一睹EKF2芳容 因为篇幅过长 xff0c 写的一些公式会乱码 xff0c 没办法只能把 牢记公式 xff0c ardupilot EKF2就是纸老虎
  • Java Optional使用

    文章目录 Optional一 Optional 简介二 创建 Optional 实例2 1 empty 方法2 2 of 方法2 3 ofNullable 方法 三 Optional的使用3 1 访问 Optional 对象的值3 1 1
  • 正则表达式:基础详解以及在Java中的使用

    文章目录 一 正则表达式1 1 正则表达式中的特殊字符1 2 正则表达式所支持的合法字符1 3 方括号表达式1 4 边界匹配符1 5 三种模式的数量表示符 二 应用2 1 String 类2 2 Pattern 类和 Matcher 类 一
  • Python学习:关键字global和nonlocal的用法说明

    一 global global关键字用来在函数或其他局部作用域中使用全局变量 1 1 如果局部要对全局变量修改 xff0c 而不使用global关键字 count 61 0 def global test count 43 61 1 pri

随机推荐

  • Python:flask框架下前后端的数据交互

    文章目录 前提 一 前端发送数据 xff0c 后端接受数据1 1 路由传参数 数据 1 2 表单提交 二 后端发送数据 xff0c 前端接受数据 前提 后端 xff1a python 的 flask 框架 前端 xff1a html css
  • Python关于None的报错:'NoneType' object is not iterable和cannot unpack non-iterable NoneType object

    文章目录 一 TypeError 39 NoneType 39 object is not iterable xff08 类型错误 xff1a 39 NoneType 39 对象不是可迭代的 xff09 二 TypeError cannot
  • Git:合并分支----git merge命令应用的三种情景

    文章目录 一 git merge 命令应用的三种情景1 1 快进 无冲突 1 2 非 快进 xff0c 修改不同文件 无冲突 1 3 非 快进 xff0c 修改相同文件 有冲突 一 git merge 命令应用的三种情景 1 1 快进 无冲
  • Git:远程分支----git fetch命令的使用

    git fetch 命令的使用 从远程主机克隆 Git 的 clone 命令会为你自动将远程主机命名为 origin xff0c 拉取它的所有数据 xff0c 创建一个指向它的 master 分支的指针 xff0c 并且在本地将其命名为 o
  • Git:移除文件----git rm命令的使用

    文章目录 一 git rm 命令使用1 1 rm 命令1 2 git rm 命令1 3 git rm f 命令1 4 git rm cached 命令 一 git rm 命令使用 Git 本地数据管理 xff0c 大概可以分为三个区 xff
  • 【OpenMv小车】OpenMv追小球的小车之pid调用

    pid py gt gt https github com wagnerc4 flight controller blob master pid py openmv 官网 xff1a http book openmv cc project
  • 【深入理解C++】函数模板作为成员函数

    文章目录 1 普通类的成员函数模板2 类模板的成员函数模板 1 普通类的成员函数模板 不管是普通类还是类模板 xff0c 它们的成员函数都可以是函数模板 xff0c 称为成员函数模板 xff0c 但不可以是虚函数 xff0c 否则编译器报错
  • QGroundControl开发之使用自定义mavlink

    工具 对QGC进行二次开发时 xff0c 常常会遇到想使用自定义mavlink的情况 xff0c 但不像APM那样编译命令会根据xml文件自动生成mavlink协议 QGC似乎不能自动生成mavlink协议 xff08 之前试过似乎不能自动
  • 字符串连接 (c语言)

    题目描述 将给定的字符串连接起来 书中的算法描述如下 xff1a 图 xff1a 字符串连接算法 输入描述 三对字符串 xff0c 每对字符串占一行 xff0c 用空格隔开 每个字符串只包含数字和英文字母大小写且长度不超过100 输出描述
  • STM32—UART中断收发 Day4

    软件 xff1a STM32CubeMX xff0c MDK ARM 硬件 xff1a 蓝桥杯物联网Lora开发板 xff0c 板载芯片STM32L071 一 STM32CubeMX配置 1 先在连接 xff08 Connectivity
  • 虚拟机出现command XXX is available in /bin/ls问题

    问题 xff1a 使用本地的shell命令时候 The command could not be located because 39 usr bin bin 39 is not included in the PATH environme
  • 全志lichee的pack命令

    全志lichee目录打包命令流程 pack 将打包命令传进去build sh脚本里面 查看buildsh里面的脚本命令 其实里面的脚本还是较为简单地的 xff0c 仅仅是作为一个过渡 xff0c 然后就跑进去buildroot script
  • Linux_kernel驱动之GPIO子系统

    前言 xff1a gpio子系统的内容在drivers gpio文件夹下 xff0c 主要文件有 xff1a devres c xff1a devres c是针对gpio api增加的devres机制的支持gpiolib c xff1a g
  • 转载:全志问题解决方法

    版权声明 xff1a 本文为博主原创文章 xff0c 遵循 CC 4 0 BY SA 版权协议 xff0c 转载请附上原文出处链接和本声明 本文链接 xff1a https blog csdn net yanzheng1113 articl
  • 从零开始学ESP32:(二) 开启ESP32WIFI -STA和AP模式共存

    从零开始学ESP32 xff1a 个人笔记记录 xff1a 芯片型号 ESP32 网络环境支持 LWIP IDF PY SDK ESP IDF v4 3 芯片功能 xff1a 支持STA AP网络共存模式 xff1a 工程 xff1a es
  • 从零开始学ESP32:(四)ESP32/freeRTOS 实现一个内存池操作

    零开始学ESP32 xff1a 个人笔记记录 xff1a 芯片型号 ESP32 网络环境支持 LWIP IDF PY SDK ESP IDF v4 3 芯片功能 xff1a freeRTOS系统 声明 xff1a 当前内存池参考 Linux
  • 从零开始学ESP32:(五)ESP32/freeRTOS 实现一个线程池(池化)操作

    从零开始学ESP32 xff1a 个人笔记记录 xff1a 芯片型号 ESP32 网络环境支持 LWIP IDF PY SDK ESP IDF v4 3 芯片功能 xff1a freeRTOS系统 声明 xff1a 进行事件异步操作 xff
  • FATFS_API接口说明表

    FatFs API 应用程序接口 根据 FatFS 的教程手册来看 xff0c 将程序接口分为了四个部分 文件访问 目录访问 文件和目录管理 卷管理和系统配置 文件访问 名称简介f open打开 创建文件f close关闭已打开的文件f r
  • 利用C++ builder 调试RTKLIB简单介绍

    相信很多刚刚接触rtklib小伙伴 xff0c 对原代码进行改进时都会采用VS的教程 RTKLIB由日本东京海洋大学 xff08 Tokyo University of Marine Science and Technology xff09
  • 全志V40/A40I的lichee 的编译

    首先了解一下全志编译lichee的步骤 回顾编译方式 xff1a 一般来说都是先配置一下芯片所包含的信息 source build sh config 编译 source build sh 摘要 xff1a 正文 上面执行build sh