目录

  • 前言
  • 文档
    • 用户指南
    • uboot应用开发指南
  • SDK中相关脚本学习
    • sdk.cleanup阅读
    • sdk.unpack阅读
    • scripts/common.sh
  • osdrv

前言

SDK中会做好很多功能,如果对SDK不熟悉那么很可能花很长一段时间进行开发结果发现SDK已经提供了接口。
所以在项目开始前,对SDK进行学习非常有必要。

文档

用户指南


介绍了环境搭建相关内容


本次学习采用的HI3528E开发板主要使用了串口线及网线进行调试。
JTAG虽然也提供了,但是没有用到。一般JTAG用于较为底层(uboot)的功能调试。

uboot是海思官方已经开发好的,在实战和工作当中很少去调试,除非是基于海思的uboot去开发一些更高级的功能。

uboot应用开发指南


提供了uboot移植相关内容指导

SDK中相关脚本学习

目录在Hi3518E V200R001C01SPC030\01.software\board

解压开进入文件夹

这两个是脚本文件
scripts中也有一个脚本文件

我们首先需要研究这三个脚本文件
这三个脚本文件的内容是我们整个package中所有内容怎么解压开,怎么去配置编译的,怎么编译uboot,怎么编译内核这些东西的指导,是别人已经做好了的。

我们只要将这三个脚本文件研究清楚,那么我们就能随便玩这个SDK了。

于是我们需要去分析这个脚本文件,然后再根据脚本文件的内容和我们自己的理解去实现一定的功能。

功能方面,从文件名不难看出

  • sdk.cleanup——清理
  • sdk.unpack——解压

sdk.cleanup阅读

内容如下

#!/bin/sh
source scripts/common.shECHO "Cleanup SDK" COLOR_YELLOW   ECHO ""
WARN "ALL THE SOUCE FILES WILL BE DELETED, FILES YOU MOTIFIED/ADDED WILL BE LOST !!!"
ECHO ""#ECHO "To continue, type 'Yes' and then press ENTER ..."#read choice
#[ x$choice != xYes ] && exit 1set +eECHO "cleanup drv"
pushd .
run_command_progress_float "rm drv -frv" 0 "find drv | wc -l"
popdECHO "cleanup mpp"
pushd .
run_command_progress_float "rm mpp* -frv" 0 "find mpp* | wc -l"
popdECHO "cleanup osdrv"
pushd .
run_command_progress_float "rm osdrv -frv" 0 "find osdrv | wc -l"
popd

第一行的#!/bin/sh说明这是一个shell脚本

第二行source scripts/common.sh是将scripts/common.sh复制到这里,和include的头文件包含类似。
scripts文件夹中的common.sh中定义了很多函数。可以理解为common.sh是库函数,另外两个为main函数。

第三行ECHO "Cleanup SDK" COLOR_YELLOW先打印一个 Cleanup SDK,颜色为黄色

后面几行一样是打印
WARN “ALL THE SOUCE FILES WILL BE DELETED, FILES YOU MOTIFIED/ADDED WILL BE LOST !!!”
所有源文件将删除,你添加/修改的文件将丢失

这里说的是解压开的文件。我们需要在执行cleanup之前将修改过的文件做备份。

#ECHO "To continue, type 'Yes' and then press ENTER ..."#read choice
#[ x$choice != xYes ] && exit 1

后面读取输入的指令,不等于yes就退出

最后一部分
pushd . 是保存当前目录
然后执行scripts/common.shrun_command_progress_float 函数

执行这个脚本,效果如下


发现./不能执行,但是source可以执行。
具体没有去了解,以结果为导向的话能用就可以了

sdk.unpack阅读

#!/bin/sh
source scripts/common.shECHO "Unpacking SDK" COLOR_YELLOWWARN "Be sure you have installed the cross-compiler. if not, install it first!"
WARN "ALL THE SOUCE FILES WILL BE OVERWRITED, FILES YOU MOTIFIED WILL BE LOST !!!"
ECHO ""#ECHO "To continue, type 'Yes' and then press ENTER ..."#read choice
#[ x$choice != xYes ] && exit 1set +e#ECHO "install cross toolchain"
#./tools/toolchains/cross.installECHO "unpacking osdrv"
mkdir -p osdrv/
run_command_progress_float "tar -xvzf package/osdrv.tgz" 0 "tar -tzf package/osdrv.tgz | wc -l"ECHO "unpacking kernel"
mkdir -p osdrv/
run_command_progress_float "tar -xvzf osdrv/opensource/kernel/linux-3.4.y.tgz -C osdrv/opensource/kernel/" 0 "tar -tzf osdrv/opensource/kernel/linux-3.4.y.tgz | wc -l"if [ "$SDK_CHIP" = "hi3519" ]; then
#ECHO "unpacking mpp_single"
#mkdir -pv mpp_single
#run_command_progress_float "tar -xvzf package/mpp_single.tgz" 0 "tar -tzf package/mpp_single.tgz | wc -l"ECHO "unpacking mpp_big-little"
mkdir -pv mpp_big-little
run_command_progress_float "tar -xvzf package/mpp_big-little.tgz" 0 "tar -tzf package/mpp_big-little.tgz | wc -l"
else
ECHO "unpacking mpp"
mkdir -pv mpp
run_command_progress_float "tar -xvzf package/mpp.tgz" 0 "tar -tzf package/mpp.tgz | wc -l"
fiECHO "unpacking drv"
mkdir -pv drv
run_command_progress_float "tar -xvzf package/drv.tgz" 0  "tar -tzf package/drv.tgz | wc -l"

阅读完上面的cleanup后,这里就粗略的阅读一下

首先打印出来,要求使用者先安装交叉编译工具链。
如果之前解压过修改过,再执行unpack的话,会将原来的文件覆盖掉。

mkdir -p osdrv/

在当前目录下创建osdrv这个目录
运行run_command_progress_float这个函数
解压package/osdrv.tgz

下面对芯片的型号进行判断,显然我们使用的不是3519。
于是进入else
解压mpp.tgz
最后解压package/drv.tgz

执行如下

虽然上面的打印让我们先安装交叉编译工具链,但是通过阅读发现,脚本后面的内容都是解压没有编译,所以没有关系。

解压完前后对比如下

  • drv——驱动
  • mpp——一些库
  • osdrv——uboot和kernel

于是我们需要重点研究osdrv中的内容

scripts/common.sh

#!/bin/sh#set -e# for debug
DEBUG_LOG_FILE='&2'
DEBUG_LOG_LEVEL=0# ANSI COLORS
COLOR_CRE="[K"
COLOR_NORMAL="[0;39m"
COLOR_RED="[1;31m"
COLOR_GREEN="[1;32m"
COLOR_YELLOW="[1;33m"
COLOR_BLUE="[1;34m"
COLOR_MAGENTA="[1;35m"
COLOR_CYAN="[1;36m"
COLOR_WHITE="[1;37m"# Shell command
TAR=tar
CP=/bin/cp
RM=/bin/rm
GREP=grep
SED=sed
MKDIR=mkdir
CHMOD=chmod
MV=mv
CD=cd
LN=ln
MAKE=make
MKNOD=mknod
PUSHD=pushd
POPD=popd
RMDIR=rmdir
DEPMOD=/sbin/depmod
RMDIR=rmdir
MKIMG=mkimage
PATCH=patch
DIFF=diff
TOUCH=touch
CAT=cate_blank='[        ][      ]*'
e_year='20[0-9][0-9]'
e_month='([1-9]|0[1-9]|1[0-2])'
e_day='([1-9]|0[1-9]|[12][0-9]|3[0-1])'
e_time='([01][0-9]|2[0-3]):[0-5][0-9]'
e_employid='[a-zA-Z][a-zA-Z]*[0-9]{4,}'#$1: string
#$2: color
ECHO()
{[ -n "$2" ] && eval echo -n \"\${${2}}\";echo "${1}${COLOR_NORMAL}"
}ERR()
{echo "${COLOR_RED} ERR: ${1}${COLOR_NORMAL}" >&2
}WARN()
{echo "${COLOR_YELLOW}WARN: ${1}${COLOR_NORMAL}" >&2
}# $1:
LOG()
{echo "$1"
}#$1: string
#$2: level
DEBUG()
{local level=$2[ -z "$level" ] && { level=0; }[ $level -lt $DEBUG_LOG_LEVEL ] && return 0;echo "$COLOR_WHITE$1$COLOR_NORMAL" > $DEBUG_LOG_FILE
}# $1: command
# $2: LR/CR steps
run_command_progress()
{local n=0local steps=$2local progress_bar=""local counter=0local files=0ECHO "run_command_progress: '$1'" [ -z "$steps" ] && { steps=1; }[ -n "$3" ] && [ -d "$3" ] && { steps=`find $3 | wc -l`; steps=`expr $steps / 50`; }eval $1 | while read linedo#((n++))#((files++))((++n))((++files))if [ $n -ge $steps ] ;then#((counter++))((++counter))if [ $counter -le 50 ] ;thenprogress_bar="$progress_bar#";printf "     --------------------------------------------------|\r[%03d]$progress_bar\r" $stepselseprintf "[%03d#$progress_bar|\r" `expr $files / 50`fin=0fidoneecho ""
}# $1: command
# $2: total
# $3: command to calc totals
run_command_progress_float()
{local readonly RCP_RANGE=50local rcp_lines=0local rcp_nextpos=1local rcp_total=0local progress_bar=local rcp_prog=0local rcp_tmp=0local prog_bar_base=local rcp_percent=0ECHO "run_command_progress_float: '$1'" if [ -n "$3" ] ;thenecho -n "Initializing progress bar ..."rcp_total=`eval $3`;echo -n "\r"[ -z "$rcp_total" ] && rcp_total=1else[ -n "$2" ] && rcp_total=$2fi[ -z "$rcp_total" ] && rcp_total=1[ $rcp_total -le 0 ] && rcp_total=1prog_bar_base="[    ]"while [ $rcp_tmp -lt $RCP_RANGE ]doprog_bar_base="$prog_bar_base-"#((rcp_tmp++)) ((++rcp_tmp)) doneprog_bar_base="${prog_bar_base}|"printf "\r$prog_bar_base\r"set +eeval $1 | while read linedo#((rcp_lines++))((++rcp_lines))if [ $rcp_lines -ge $rcp_nextpos ]thenrcp_percent=`expr \( $rcp_lines \* 101 - 1 \) / $rcp_total `rcp_prog=`expr \( $rcp_lines \* \( $RCP_RANGE + 1 \) - 1 \) / $rcp_total `[ $rcp_prog -gt $RCP_RANGE ] && rcp_prog=$RCP_RANGErcp_nextpos=`expr \( \( $rcp_percent + 1 \) \* $rcp_total \) / 100`[ $rcp_nextpos -gt $rcp_total ] && rcp_nextpos=$rcp_totalrcp_tmp=0progress_bar=""while [ $rcp_tmp -lt $rcp_prog ]doprogress_bar="$progress_bar#"((rcp_tmp++))doneprintf "\r$prog_bar_base\r[%3d%%]$progress_bar\r" $rcp_percentfidoneset -eecho ""
}#$1: path
abs_path()
{pushd "$1" >/dev/null[ $? -ne 0 ] && return 1;pwdpopd >/dev/null
}#$1: $cfg_moddir is multi
prepare_unpacking_cleanup()
{$CAT >> $HCM_SH_SDKINSTALL << EOFECHO "unpacking $cfg_moddir"
mkdir -pv $module_basedir
run_command_progress_float "tar -xvzf `sub_dir $dir_postbuild_srctarball $HCM_DESTDIR`/$module_dirname.tgz -C $module_basedir/" 0 \"tar -tzf `sub_dir $dir_postbuild_srctarball $HCM_DESTDIR`/$module_dirname.tgz | wc -l"
EOFif [ -z "$1" ] ;
then$CAT >> $HCM_SH_SDKCLEANUP << EOFECHO "cleanup $cfg_moddir"
run_command_progress_float "rm $cfg_moddir -frv" 0 "find $cfg_moddir | wc -l"
EOF
else$CAT >> $HCM_SH_SDKCLEANUP << EOFECHO "cleanup $cfg_moddir"
pushd $module_basedir
run_command_progress_float "rm $cfg_moddir -frv" 0 "find $cfg_moddir | wc -l"
popd
EOF
fi}# $1: prefix
# $2..$n: dirs list
make_dirs()
{local make_dirs_count=2local make_dirs_dir=[ -z "$1" ] && { ERR "make_dirs mast have a prefix dir!"; return 1; }$MKDIR $1 -pwhile truedoeval make_dirs_dir=\${$make_dirs_count}[ -z "$make_dirs_dir" ] && break;$MKDIR $1/$make_dirs_dir -p#((make_dirs_count++))((++make_dirs_count))done
}check_dir_empty()
{[ -z "$1" ] && return 0;! [ -d $1 ] && return 0;[ -z "`find $1/ -maxdepth 1 -mindepth 1`" ] && return 0;return 1
}# $1 - $2
# $3: frefix for '/', like "\\\\/"
sub_dir()
{local subdir=local dirA=`dirname $1/stub`local dirB=`dirname $2/stub`while [ "$dirA" != "$dirB" ] && [ "$dirA" != "." ] && [ "$dirA" != "/" ] doif [ -z "$subdir" ] ; thensubdir=`basename $dirA`elsesubdir=`basename $dirA`$3/$subdirfidirA=`dirname $dirA`done[ -z "$subdir" ] && subdir=.dirname $subdir/stub
}# $1: base dir
# $2: dest dir
# $3: frefix for '/', like "\\\\/"
base_offset_dir()
{local ofstdir=`sub_dir $2 $1`local bodofst=while [ "$ofstdir" != "." ] && [ "$ofstdir" != "/" ] doif [ -z "$bodofst" ] ; thenbodofst=..elsebodofst=..$3/$bodofstfiofstdir=`dirname $ofstdir`donedirname $bodofst/stub
}#$1: dir
set_drv_kbuild()
{local cc_file=Makefilelocal mbdir= for mbdir in $1 $1/*doif [ -f $mbdir/$cc_file ] ;thenlocal kbuild_dir_adj="`base_offset_dir $HCM_DESTDIR $mbdir "\\\\"`\\/`echo "$HCM_SDKDIR_KBUILD" | \sed -n "s/\//\\\\\\\\\//gp"`"$SED -i "s/^KERNEL_MAKE[ \t]*:=.*/KERNEL_MAKE := -C $kbuild_dir_adj/" $mbdir/$cc_filefidone
}#$1: name
#$2: level
write_rootfs_level()
{local rlevel_config=$HCM_DESTDIR/$HCM_SDKDIR_RESOURCE/rlevel.config$TOUCH $rlevel_config[ -n "`grep "^\[[0-9A-Za-z][0-9A-Za-z\-]*\]    $1$" < $rlevel_config`" ] && { \WARN "$rlevel_config already have item '$1'"return 0;}echo "[$2] $1" >> $rlevel_config
}#$1:
remove_all_cvsdir()
{! [ -d "$1" ] && { WARN "'$1' not found when remove 'CVS' directories."; return ; }ECHO "Remove: 'CVS' directories in $1"find $1 -type d -name "CVS" | xargs rm -fr
}#$1: strip command
#$2: file list
strip_elf()
{for file in $2do[ -z "`file $file | grep "ELF .* executable, .*, not stripped"`" ] && continueECHO "$1 $file"$1 $filedone
}#$1: strip command
#$2: file list
strip_lib()
{for file in $2do[ -z "`file $file | grep "ELF .* shared object, .*, not stripped"`" ] && continueECHO "strip not really done: $file"done
}# $1: rootfs base
# $2: modules list
install_extern_kmod()
{local iek_installed_modules=local iek_dest_module=local iek_depend_info=local iek_install_base=pushd $1 >/dev/nulliek_install_base=$PWDpopd >/dev/nullfor iek_extmod in `find $2`doiek_dest_module=/$HCM_INROOTFS_EXTKMOD/`basename $iek_extmod`[ -f $HCM_DESTDIR/$HCM_KERNEL_INSTALL_RESOURCE/$iek_dest_module ] && \{ WARN "Extern module $iek_extmod conflict: $iek_dest_module"; sleep 1; }iek_installed_modules="$iek_installed_modules $iek_dest_module"$CP -uf $iek_extmod $HCM_DESTDIR/$HCM_KERNEL_INSTALL_RESOURCE/$iek_dest_moduledonepushd $HCM_DESTDIR/$HCM_KERNEL_INSTALL_RESOURCE >/dev/nullECHO "Generating modules dependency ..."$DEPMOD -ae -b ./ -r -F $HCM_DESTDIR/$HCM_SDKDIR_KBUILD/System.map $HCM_KERNEL_RELEASEfor iek_extmod in $iek_installed_modulesdoiek_depend_info=`grep "^$iek_extmod:" < $HCM_DESTDIR/$HCM_KERNEL_INSTALL_RESOURCE/$HCM_INROOTFS_DEPKMOD/modules.dep | sed "s/\://"`for iek_extmod in $iek_depend_infodo$CP -uf --parents .$iek_extmod $iek_install_base/[ x$cfg_install_strip == xyes ] && $HCM_CROSS_COMPILE-strip $iek_install_base$ikm_kmod -g -S -ddonedonepopd >/dev/null
}# $1: dest rootfs based
# $2: module list
install_kernel_module()
{local ikm_kmod_resdir=$HCM_DESTDIR/$HCM_KERNEL_INSTALL_RESOURCElocal ikm_install_basedir=local ikm_kmod=pushd $1 >/dev/nullikm_install_basedir=$PWDpopd  >/dev/nullpushd $ikm_kmod_resdir >/dev/null$DEPMOD -ae -b ./ -r -F $HCM_DESTDIR/$HCM_SDKDIR_KBUILD/System.map $HCM_KERNEL_RELEASEwhile read ikm_kmoddoikm_depend_info=`grep "^$ikm_kmod:" < $HCM_DESTDIR/$HCM_KERNEL_INSTALL_RESOURCE/$HCM_INROOTFS_DEPKMOD/modules.dep | sed "s/\://"`for ikm_kmod in $ikm_depend_infodo$CP -uf --parents .$ikm_kmod $ikm_install_basedir[ x$cfg_install_strip == xyes ] && $HCM_CROSS_COMPILE-strip $ikm_install_basedir$ikm_kmod -g -S -ddonedone << EOF`pushd $HCM_INROOTFS_KERNMOD >/dev/null; \eval find "$2" -type f -printf \"/$HCM_INROOTFS_KERNMOD/%p\\\n\"; \popd >/dev/null`
EOFpopd >/dev/null
}string_to_varname()
{echo "$1" | sed 's/[^a-zA-Z0-9_]/_/g'
}patchset_get_param()
{echo "$1" | cut -d')' -f1 | sed 's/[\(\|]/ /g'
}patchset_get_name()
{echo "$file" | cut -d')' -f2
}

内容较长,一部分一部分的看。

这个脚本里边主要定义了一些函数。

这部分是颜色数值,像我们之前在操作linux的时候出现的很多有颜色的字符就是这么来的。


这部分定义了一些命令。
为什么要定义这些命令?
和宏定义类似,这个脚本可能不光在sh里用,将来可能在别的里面用,命令可能需要替换,所以定义。

另外两个脚本都用到的run_command_progress函数,实际上就是显示解压进度条。
还有另一个进度条相关的函数

# $1: command
# $2: total
# $3: command to calc totals
run_command_progress_float()

有三个参数,一个是命令,一个是总量,一个是计算百分比
这个函数是通过小数点显示

运行的效果如下

关于脚本,只需要能看懂它大概是干什么的就可以,实际工作场景中脚本都是写好的,用就行了

osdrv

上面说的,解压出来的重点就是osdrv这个文件夹

接下来对ubootkernel进行学习
osdrv中有一个readmemakefile,先看这两个

makefile中写了

这边做了两个交叉编译选项来选择对应的交叉编译工具链。

uclibc和glibc的区别

  • glibc功能全,但是占空间大
  • uclibc是glibc的精简版本,保留了必要的功能,体积非常小

实际产品的flash只有8兆,在这种情况下只能使用uclibcglibc光是这个库都放不下就更不用说其他的东西了。

使用glibc的产品大多为板载的不是SPI Flash,用的是TF卡或者EMMC。所以不用考虑glibc的两三百兆。

其他内容就是一些命令


执行发现交叉编译工具链没有找到,此时需要查看makefile

可以看到,虽然编译选项中给了交叉编译工具链的选择,但是makefile中没有绝对路径。
makefile中的写法就是访问当前目录,所以找不到
继续浏览

发现,需要在当前目录下有一个arm-hisiv300-linux目录,这个目录下放对应的交叉编译工具链才行。

交叉编译工具链的脚本文件中给出了安装工具链的路径,我们可以改makefile或者这里的路径,再或者直接把压缩包拷贝到相应路径中

我们选择最简单的方式

于是我们需要将交叉编译工具链安装到osdrv底下

交叉编译工具链在/osdrv/opensource/toolchain/

接着,我们将其中的压缩包移动到/osdr底下并解压

有了这个路径,这样makefile就可以找到它,如下图

然后这样配置了之后还是报错找不到交叉编译工具链

这是由于32位的工具链和64位工具链不同导致的

下一期给出解决方案

海思3518E开发笔记1.2——海思SDK脚本学习相关推荐

  1. 海思3518E开发笔记2.5——海思VI(video input)模块详解

    目录 海思video input模块架构介绍 海思video input模块功能介绍 结构体说明 函数调用关系 流程分析 step 1: mipi configure step 2: configur ...

  2. 海思3518E开发笔记2.7——海思VENC(Video Encode)模块详解

    目录 海思Video Encode模块架构介绍 海思Video Encode相关概念 码率控制 海思Video Encode模块功能介绍 编码通道 ROI 裁剪编码 函数调用关系 相关数据结构 流程分 ...

  3. 海思3518E开发笔记1.6——rootfs及其启动流程分析

    3518E的根文件系统 /etc/fstab fs-version group profile udev init rcS S00devs S01udev S80network S90hibernat ...

  4. 海思3518E开发笔记1.5——flash分区及uboot、kernel、rootfs烧写并部署

    目录 规划分区 烧写流程 tftp更新并重新烧写uboot的命令序列 tftp更新并重新烧写kernel的命令序列 tftp更新并重新烧写rootfs的命令序列: 裸机烧录uboot 什么是裸机 烧录 ...

  5. 海思3518E开发笔记1.1——HI3518E方案整体架构介绍

    目录 前言 硬件 软件 前言 在做一个项目之前,需要对这个项目在一个比较高的高度进行了解. 如,硬件构成.软件是裸机的还是带操作系统的,带操作系统的是怎么样一个开发流程. 得对项目由打到校进行了解,知 ...

  6. 海思3518E开发笔记4.2——sensor数据交互接口(MIPI、LVDS、DVP并口),以AR0130和OV9712为例

    目录 前言 DVP(并口) LVDS MIPI(MIPI-CSI2) 总结 前言 摄像头是一个独立的芯片,和主控芯片是弧线独立的,两者通过接口进行交互,交互的信息有控制信号和数据信号 控制信号常用I2 ...

  7. ZYNQ LINUX开发笔记——windows下用xilinx SDK编译zynq linux app小程序

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 ZYNQ LINUX开发笔记--windows下用xilinx SDK编译zynq linux app小程序 前言 操作方法 总结 前 ...

  8. ROS开发笔记(10)——ROS 深度强化学习dqn应用之tensorflow版本(double dqn/dueling dqn/prioritized replay dqn)

    ROS开发笔记(10)--ROS 深度强化学习dqn应用之tensorflow版本(double dqn/dueling dqn/prioritized replay dqn) 在ROS开发笔记(9) ...

  9. 海康摄像头开发笔记(一):连接防爆摄像头、配置摄像头网段、设置rtsp码流、播放rtsp流、获取rtsp流、调优rtsp流播放延迟以及录像存储

    文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/131679108 红胖子(红模仿)的博文大全:开发技术集合( ...

  10. 大数据开发笔记(九):Flink综合学习

      ✨大数据开发笔记推荐: 大数据开发面试知识点总结_GoAI的博客-CSDN博客_大数据开发面试​本文详细介绍大数据hadoop生态圈各部分知识,包括不限于hdfs.yarn.mapreduce.h ...

最新文章

  1. 资深程序员不一定当得了软件架构师
  2. B. The Cake Is a Lie
  3. Uva1343-The Rotation Game-IDA*算法
  4. python 百度搜索结果_Python洗涤百度搜索结果
  5. php输出字符unicode码,PHP解码unicode编码的中文字符代码分享
  6. win2008r2 惠普g160鼠标_分享 HP 原机附带 WIN2008 R2 标准版 64位
  7. LINUX获取当前用户及信息的命令
  8. 二进制二进制编辑器_为什么十六进制编辑器称为二进制编辑器?
  9. 红帽linux考证时间,红帽认证考试时间
  10. 九九乘法表打印Python
  11. win10 WIFI连接无选项时的解决方法
  12. 20140925百度校园招聘二面
  13. vue+element 压缩上传图片
  14. CSS3各个模块详解
  15. 自定义gii生成模块
  16. word中添加背景色
  17. 图像,log处理的一点经验
  18. 手工折纸作品展示:送别的花束
  19. Flag壁纸生成器诞生记
  20. porphet论文_时间序列神器之争:Prophet VS LSTM

热门文章

  1. 最新最全自己动手做一个富文本编辑器(附源码 api)
  2. CSS边框boder
  3. 上海大学计算机专业就业薪资,人均月薪过万?985、211、普通大学毕业生薪资水平大起底!和你想的不一样……...
  4. activemq_CVE-2015-5254_漏洞复现_源码分析
  5. 摩尔条纹拯救我的3D检测
  6. 服务器使用笔记本网络连接外网
  7. vue路由守卫,路由拦截,导航守卫
  8. 同比增长和环比增长的区别
  9. ht for web(图扑)加载模型
  10. 计算机网络:循环冗余码CRC