U-boot(五):启动内核
本文主要探讨210的uboot启动内核过程。
嵌入式系统状态启动
未上电时bootloader、kernel、rootfs以镜像形式存储在启动介质中(X210为iNand/SD卡),运行时搬运到DDR中
未上电时u-boot.bin,zImage,rootfs在SD卡中各自对应的分区中,启动时去对应分区寻找(分区表一致)
动态启动为从SD卡到DDR内存,并且运行启动代码进行硬/软件初始化
uboo在第一阶段重定位时将第二阶段(整个uboot镜像)加载到DDR的0xc3e00000地址处(uboot链接地址)
uboot启动内核时从SD卡读取内核到DDR地址是0x30008000(内核链接地址)
uboot启动内核:将内核搬移到DDR中,校验内核格式、CRC等,准备传参,跳转执行内核
启动内核主要函数是:do_boom,do_bootm_linux
uboot能启动的内核格式:zImage,uImage,fdt
image_header_t
typedef struct image_header {uint32_t ih_magic; /* Image Header Magic Number */uint32_t ih_hcrc; /* Image Header CRC Checksum */uint32_t ih_time; /* Image Creation Timestamp */uint32_t ih_size; /* Image Data Size */uint32_t ih_load; /* Data Load Address */uint32_t ih_ep; /* Entry Point Address */uint32_t ih_dcrc; /* Image Data CRC Checksum */uint8_t ih_os; /* Operating System */uint8_t ih_arch; /* CPU architecture */uint8_t ih_type; /* Image Type */uint8_t ih_comp; /* Compression Type */uint8_t ih_name[IH_NMLEN]; /* Image Name */
} image_header_t;
image_header_t *hdr;
uboot启动内核使用的数据结构(镜像头部信息)
内核启动
内核不能自主开机,uboot帮助内核重定位到链接地址(SD卡到DDR)并且给内核传递启动参数
210的iNand版本uboot使用movi命令完成内核重定位(movi read kernel 30008000),kernel为uboot中kernel分区
do_bootm(cmd_bootm.c)
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])/* find out kernel image address */if (argc < 2) {addr = load_addr;debug ("* kernel: default image load address = 0x%08lx\n",load_addr);} else {addr = simple_strtoul(argv[1], NULL, 16);debug ("* kernel: cmdline image address = 0x%08lx\n", img_addr);}
ulong load_addr = CFG_LOAD_ADDR; /* Default Load Address */#define CFG_LOAD_ADDR MEMORY_BASE_ADDRESS /* default load address */#define MEMORY_BASE_ADDRESS 0x30000000
启动命令:bootm 0x30008000,故do_boom的argc=2,argv[0]=bootm,argv[1]=0x30008000
启动命令:bootm,从CFG_LOAD_ADDR地址启动(x210_sd.h)
vmlinuz,zImage,uImage
uboot编译生成u-boot(elf格式),由u-boot用arm-linux-objcopy工具加工得到u-boot.bin(镜像)用来烧录
linux内核编译生成vmlinux或vmlinuz(几十M)(elf格式),用objcopy工具加工成烧录Image镜像(几M),对Image压缩,在image压缩后的文件前端附加解压缩代码构成zImage
uImage是由zImage加工得到,mkimage工具由zImage加工生成uImage给uboot启动,在zImage前加64字节头信息即可得到
zImage启动
#ifdef CONFIG_ZIMAGE_BOOT
#define LINUX_ZIMAGE_MAGIC 0x016f2818/* find out kernel image address */if (argc < 2) {addr = load_addr;debug ("* kernel: default image load address = 0x%08lx\n",load_addr);} else {addr = simple_strtoul(argv[1], NULL, 16);debug ("* kernel: cmdline image address = 0x%08lx\n", img_addr);}if (*(ulong *)(addr + 9*4) == LINUX_ZIMAGE_MAGIC) {printf("Boot with zImage\n");addr = virt_to_phys(addr);hdr = (image_header_t *)addr;hdr->ih_os = IH_OS_LINUX;hdr->ih_ep = ntohl(addr);memmove (&images.legacy_hdr_os_copy, hdr, sizeof(image_header_t));/* save pointer to image header */images.legacy_hdr_os = hdr;images.legacy_hdr_valid = 1;goto after_header_check;}
#endif
CONFIG_ZIMAGE_BOOT(x210_sd.h)用宏控制编译支持zImage格式的内核启动
LINUX_ZIMAGE_MAGIC是魔数(0x016f2818)来表示zImage,即zImage格式镜像在头部存放该数作为标记辨别它是否是zImage(是否等于LINUX_ZIMAGE_MAGIC),若为在Image则对头部信息改造,用头信息初始化images,完成了校验
after_header_check
#if defined(CONFIG_ZIMAGE_BOOT)
after_header_check:os = hdr->ih_os;
#endifswitch (os) {default: /* handled by (original) Linux case */case IH_OS_LINUX:
#ifdef CONFIG_SILENT_CONSOLEfixup_silent_linux();
#endifdo_bootm_linux (cmdtp, flag, argc, argv, &images);break;case IH_OS_NETBSD:do_bootm_netbsd (cmdtp, flag, argc, argv, &images);break;#ifdef CONFIG_LYNXKDIcase IH_OS_LYNXOS:do_bootm_lynxkdi (cmdtp, flag, argc, argv, &images);break;
#endifcase IH_OS_RTEMS:do_bootm_rtems (cmdtp, flag, argc, argv, &images);break;#if defined(CONFIG_CMD_ELF)case IH_OS_VXWORKS:do_bootm_vxworks (cmdtp, flag, argc, argv, &images);break;case IH_OS_QNX:do_bootm_qnxelf (cmdtp, flag, argc, argv, &images);break;
#endif#ifdef CONFIG_ARTOScase IH_OS_ARTOS:do_bootm_artos (cmdtp, flag, argc, argv, &images);break;
#endif}show_boot_progress (-9);
#ifdef DEBUGputs ("\n## Control returned to monitor - resetting...\n");do_reset (cmdtp, flag, argc, argv);
#endifif (iflag)enable_interrupts();return 1;
}
确定image类型,依据类型进行头信息校验,校验通过则准备启动内核
uImage启动和设备数启动
/* get kernel image header, start address and length */os_hdr = boot_get_kernel (cmdtp, flag, argc, argv,&images, &os_data, &os_len);if (os_len == 0) {puts ("ERROR: can't get kernel image!\n");return 1;}/* get image parameters */switch (genimg_get_format (os_hdr)) {case IMAGE_FORMAT_LEGACY:type = image_get_type (os_hdr);comp = image_get_comp (os_hdr);os = image_get_os (os_hdr);image_end = image_get_image_end (os_hdr);load_start = image_get_load (os_hdr);break;
#if defined(CONFIG_FIT)case IMAGE_FORMAT_FIT:if (fit_image_get_type (images.fit_hdr_os,images.fit_noffset_os, &type)) {puts ("Can't get image type!\n");show_boot_progress (-109);return 1;}if (fit_image_get_comp (images.fit_hdr_os,images.fit_noffset_os, &comp)) {puts ("Can't get image compression!\n");show_boot_progress (-110);return 1;}if (fit_image_get_os (images.fit_hdr_os,images.fit_noffset_os, &os)) {puts ("Can't get image OS!\n");show_boot_progress (-111);return 1;}break;
#endifdefault:puts ("ERROR: unknown image format type!\n");return 1;}image_start = (ulong)os_hdr;load_end = 0;type_name = genimg_get_type_name (type);
static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],bootm_headers_t *images, ulong *os_data, ulong *os_len){image_header_t *hdr;ulong img_addr;
#if defined(CONFIG_FIT)void *fit_hdr;const char *fit_uname_config = NULL;const char *fit_uname_kernel = NULL;const void *data;size_t len;int cfg_noffset;int os_noffset;
#endif/* find out kernel image address */if (argc < 2) {img_addr = load_addr;debug ("* kernel: default image load address = 0x%08lx\n",load_addr);
#if defined(CONFIG_FIT)} else if (fit_parse_conf (argv[1], load_addr, &img_addr,&fit_uname_config)) {debug ("* kernel: config '%s' from image at 0x%08lx\n",fit_uname_config, img_addr);} else if (fit_parse_subimage (argv[1], load_addr, &img_addr,&fit_uname_kernel)) {debug ("* kernel: subimage '%s' from image at 0x%08lx\n",fit_uname_kernel, img_addr);
#endif} else {img_addr = simple_strtoul(argv[1], NULL, 16);debug ("* kernel: cmdline image address = 0x%08lx\n", img_addr);}show_boot_progress (1);/* copy from dataflash if needed */img_addr = genimg_get_image (img_addr);/* check image type, for FIT images get FIT kernel node */*os_data = *os_len = 0;switch (genimg_get_format ((void *)img_addr)) {case IMAGE_FORMAT_LEGACY:printf ("## Booting kernel from Legacy Image at %08lx ...\n",img_addr);hdr = image_get_kernel (img_addr, images->verify);if (!hdr)return NULL;show_boot_progress (5);/* get os_data and os_len */switch (image_get_type (hdr)) {case IH_TYPE_KERNEL:*os_data = image_get_data (hdr);*os_len = image_get_data_size (hdr);break;case IH_TYPE_MULTI:image_multi_getimg (hdr, 0, os_data, os_len);break;default:printf ("Wrong Image Type for %s command\n", cmdtp->name);show_boot_progress (-5);return NULL;}/** copy image header to allow for image overwrites during kernel* decompression.*/memmove (&images->legacy_hdr_os_copy, hdr, sizeof(image_header_t));/* save pointer to image header */images->legacy_hdr_os = hdr;images->legacy_hdr_valid = 1;show_boot_progress (6);break;
#if defined(CONFIG_FIT)case IMAGE_FORMAT_FIT:fit_hdr = (void *)img_addr;printf ("## Booting kernel from FIT Image at %08lx ...\n",img_addr);if (!fit_check_format (fit_hdr)) {puts ("Bad FIT kernel image format!\n");show_boot_progress (-100);return NULL;}show_boot_progress (100);if (!fit_uname_kernel) {/** no kernel image node unit name, try to get config* node first. If config unit node name is NULL* fit_conf_get_node() will try to find default config node*/show_boot_progress (101);cfg_noffset = fit_conf_get_node (fit_hdr, fit_uname_config);if (cfg_noffset < 0) {show_boot_progress (-101);return NULL;}/* save configuration uname provided in the first* bootm argument*/images->fit_uname_cfg = fdt_get_name (fit_hdr, cfg_noffset, NULL);printf (" Using '%s' configuration\n", images->fit_uname_cfg);show_boot_progress (103);os_noffset = fit_conf_get_kernel_node (fit_hdr, cfg_noffset);fit_uname_kernel = fit_get_name (fit_hdr, os_noffset, NULL);} else {/* get kernel component image node offset */show_boot_progress (102);os_noffset = fit_image_get_node (fit_hdr, fit_uname_kernel);}if (os_noffset < 0) {show_boot_progress (-103);return NULL;}printf (" Trying '%s' kernel subimage\n", fit_uname_kernel);show_boot_progress (104);if (!fit_check_kernel (fit_hdr, os_noffset, images->verify))return NULL;/* get kernel image data address and length */if (fit_image_get_data (fit_hdr, os_noffset, &data, &len)) {puts ("Could not find kernel subimage data!\n");show_boot_progress (-107);return NULL;}show_boot_progress (108);*os_len = len;*os_data = (ulong)data;images->fit_hdr_os = fit_hdr;images->fit_uname_os = fit_uname_kernel;images->fit_noffset_os = os_noffset;break;
#endifdefault:printf ("Wrong Image Format for %s command\n", cmdtp->name);show_boot_progress (-108);return NULL;}debug (" kernel data at 0x%08lx, len = 0x%08lx (%ld)\n",*os_data, *os_len, *os_len);return (void *)img_addr;
}
IMAGE_FORMAT_LEGACY为uImage启动方式,启动校验在boot_get_kernel函数:校验uImage头信息,得kernel起始位置去启动
CONFIG_FIT:设备树方式启动
do_bootm_linux(zImage)
void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],bootm_headers_t *images){ulong initrd_start, initrd_end;ulong ep = 0;bd_t *bd = gd->bd;char *s;int machid = bd->bi_arch_number;void (*theKernel)(int zero, int arch, uint params);int ret;#ifdef CONFIG_CMDLINE_TAGchar *commandline = getenv ("bootargs");
#endif/* find kernel entry point */if (images->legacy_hdr_valid) {ep = image_get_ep (&images->legacy_hdr_os_copy);
#if defined(CONFIG_FIT)} else if (images->fit_uname_os) {ret = fit_image_get_entry (images->fit_hdr_os,images->fit_noffset_os, &ep);if (ret) {puts ("Can't get entry point property!\n");goto error;}
#endif} else {puts ("Could not find kernel entry point!\n");goto error;}theKernel = (void (*)(int, int, uint))ep;s = getenv ("machid");if (s) {machid = simple_strtoul (s, NULL, 16);printf ("Using machid 0x%x from environment\n", machid);}ret = boot_get_ramdisk (argc, argv, images, IH_ARCH_ARM,&initrd_start, &initrd_end);if (ret)goto error;show_boot_progress (15);debug ("## Transferring control to Linux (at address %08lx) ...\n",(ulong) theKernel);#if defined (CONFIG_SETUP_MEMORY_TAGS) || \defined (CONFIG_CMDLINE_TAG) || \defined (CONFIG_INITRD_TAG) || \defined (CONFIG_SERIAL_TAG) || \defined (CONFIG_REVISION_TAG) || \defined (CONFIG_LCD) || \defined (CONFIG_VFD) || \defined (CONFIG_MTDPARTITION)setup_start_tag (bd);
#ifdef CONFIG_SERIAL_TAGsetup_serial_tag (¶ms);
#endif
#ifdef CONFIG_REVISION_TAGsetup_revision_tag (¶ms);
#endif
#ifdef CONFIG_SETUP_MEMORY_TAGSsetup_memory_tags (bd);
#endif
#ifdef CONFIG_CMDLINE_TAGsetup_commandline_tag (bd, commandline);
#endif
#ifdef CONFIG_INITRD_TAGif (initrd_start && initrd_end)setup_initrd_tag (bd, initrd_start, initrd_end);
#endif
#if defined (CONFIG_VFD) || defined (CONFIG_LCD)setup_videolfb_tag ((gd_t *) gd);
#endif#ifdef CONFIG_MTDPARTITIONsetup_mtdpartition_tag();
#endifsetup_end_tag (bd);
#endif/* we assume that the kernel is in place */printf ("\nStarting kernel ...\n\n");#ifdef CONFIG_USB_DEVICE{extern void udc_disconnect (void);udc_disconnect ();}
#endifcleanup_before_linux ();theKernel (0, machid, bd->bi_boot_params);/* does not return */return;error:do_reset (cmdtp, flag, argc, argv);return;
}
ulong ep = 0;ep(entrypoint)是程序入口,镜像文件起始执行部分不在镜像开头,在镜像开头某个字节处(有偏移量)
运行镜像过程:读取头信息MAGIC_NUM来确定镜像种类,镜像校验,读取头信息获取镜像信息(镜像长度,种类,入口地址),去entrypoint处运行镜像
theKernel = (void (*)(int, int, uint))ep;将ep赋值给theKernel,函数指向OS镜像真正入口地址(操作系统运行首代码)。
int machid = bd->bi_arch_number;uboot启动内核时,机器码传给内核,uboot通过全局变量gd->bd->bi_arch_num将x210_sd.h定义的机器码传给uboot
函数(110-144)是uboot给linux内核传递参数处理
Starting kernel标志uboot加载内核镜像,校验通过,获得内核入口地址
tag传参
struct tag {struct tag_header hdr;union { struct tag_core core;struct tag_mem32 mem;struct tag_videotext videotext;struct tag_ramdisk ramdisk;struct tag_initrd initrd;struct tag_serialnr serialnr;struct tag_revision revision;struct tag_videolfb videolfb;struct tag_cmdline cmdline;/** Acorn specific*/struct tag_acorn acorn;/** DC21285 specific*/struct tag_memclk memclk;struct tag_mtdpart mtdpart_info;} u;
};
struct tag_header {u32 size;u32 tag;
};
static struct tag *params;
tag_header中有tag的size和类型编码
tag函数参宏
ATAG_NONE tag_header tag结束
ATAG_CORE tag_core
ATAG_MEM tag_mem32 内存配置信息
ATAG_VIDEOTEXT tag_videotext
ATAG_RAMDISK tag_ramdisk
ATAG_INITRD tag_initrd
ATAG_SERIAL tag_serialnr
ATAG_REVISION tag_revision
ATAG_VIDEOLFB tag_videolfb
ATAG_CMDLINE tag_cmdline 启动命令参数(的bootargs)
ATAG_ACORN tag_acorn tag起始
ATAG_MEMCLK tag_memclk
ATAG_MTDPART tag_mtdpart iNand/SD卡分区表
/* The list must start with an ATAG_CORE node */
#define ATAG_CORE 0x54410001struct tag_core {u32 flags; /* bit 0 = read-only */u32 pagesize;u32 rootdev;
};
theKernel (0, machid, bd->bi_boot_params);/* does not return */
uboot调用theKernel函数来运行linux内核,uboot调用时传递3个参数:(0,机器码,tag首地址)
demo:
编译uImage
ubuntu:
root@kaxi-virtual-machine:~/qt_x210v3s/kernel# cat mk
#!/bin/sh#QT_KERNEL_CONFIG=x210_jffs_defconfig
QT_KERNEL_CONFIG=x210ii_qt_defconfigCPU_NUM=$(cat /proc/cpuinfo |grep processor|wc -l)
CPU_NUM=$((CPU_NUM+1))make distclean
make cleanmake ${QT_KERNEL_CONFIG}
make -j${CPU_NUM}
cd qt_x210v3s/kernelvim MakefileCROSS_COMPILE ?= /root/arm-2009q3/bin/arm-none-linux-gnueabi-make clean &> /dev/null && make distclean &> /dev/nullcp ../uboot/tools/mkimage /usr/local/bin/vim mkQT_KERNEL_CONFIG=x210ii_qt_defconfig生成zImage./mk &>/dev/nullmake uImage &>/dev/nullcp arch/arm/boot/uImage /root/tftp
uboot:
tftp 30008000 uImagemovi read kernel 30008000bootm 30008000
结果示例:


相关文章:
U-boot(五):启动内核
本文主要探讨210的uboot启动内核过程。 嵌入式系统状态启动 未上电时bootloader、kernel、rootfs以镜像形式存储在启动介质中(X210为iNand/SD卡),运行时搬运到DDR中 未上电时u-boot.bin,zImage,rootfs在SD卡中各自对应的分区中,启动时去对应分区寻找(分区表一…...
tp8 使用rabbitMQ(2)工作队列
代码的参数说明在 第一小节的代码中,如果需要可移步到第一节中查看 工作队列 工作队列(又称:任务队列——Task Queues)是为了避免等待一些占用大量资源、时间的操作。当我们把任务(Task)当作消息发送到队列…...
ZKP11.4 Use CI to instantiate Fiat-Shamir
ZKP学习笔记 ZK-Learning MOOC课程笔记 Lecture 11: From Practice to Theory (Guest Lecturer: Alex Lombardi) 11.4 Use CI to instantiate Fiat-Shamir Avoid Bad Challenges Def: Given false claim x x x and a first message α \alpha α, a challenge β \beta …...
华为云编译构建CodeArts Build常见问答汇总
1.【Build】公有云编译构建是否支持导入外部机器做执行机 答:参考链接:https://support.huaweicloud.com/usermanual-devcloud/devcloud_01_0017.html • 使用代理机功能,需要配备1台4U8G或以上规格、磁盘>80GB的主机。 • 安装代理的…...
009 OpenCV 二值化 threshold
一、环境 本文使用环境为: Windows10Python 3.9.17opencv-python 4.8.0.74 二、二值化算法 2.1、概述 在机器视觉应用中,OpenCV的二值化函数threshold具有不可忽视的作用。主要的功能是将一幅灰度图进行二值化处理,以此大幅降低图像的数…...
基于python的NBA球员数据可视化分析的设计与实现
完整下载:基于python的NBA球员数据可视化分析的设计与实现.docx 基于python的NBA球员数据可视化分析的设计与实现 Design and Implementation of NBA Player Data Visualization Analysis based on Python 目录 目录 2 摘要 3 关键词 4 第一章 引言 4 1.1 研究背景 …...
《使用Python将Excel数据批量写入MongoDB数据库》
在数据分析及处理过程中,我们经常需要将数据写入数据库。而MongoDB作为一种NoSQL数据库,其具有强大的可扩展性、高性能以及支持复杂查询等特性,广泛用于大规模数据存储和分析。在这篇文章中,我们将使用Python编写一个将Excel数据批…...
leetcode_828_统计子串中的唯一字符
题意:所有子串中单个字符出现的次数和 问题转化:对于串中的每个字符,只包含其一次的所有子串的个数和 关于求只包含某位置字符一次的子串个数 class Solution { public:int uniqueLetterString(string s) {/* ...A...A...A...*/int n s.size…...
「Java开发中文指南」IntelliJ IDEA插件安装(一)
IntelliJ IDEA是java编程语言开发的集成环境。IntelliJ在业界被公认为最好的Java开发工具,尤其在智能代码助手、代码自动提示、重构、JavaEE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面的功能是非常强大的。 插件扩展了Intel…...
单机多卡训练
参考几个不错的帖子(还没来得及整理): 基于pytorch多GPU单机多卡训练实践_多卡训练效果不如单卡-CSDN博客 关于PyTorch单机多卡训练_能用torch.device()实现多卡训练吗-CSDN博客 Pytorch多机多卡分布式训练 - 知乎 (zhihu.com) 当代研究生…...
数据库基础教程之数据库的创建(一)
双击打开Navicat,点击:文件-》新建连接-》PostgreSQL 在下图新建连接中输入各参数,然后点击:连接测试,连接成功后再点击确定。 点击新建数据库 数据库设置如下:...
Python教程:DataFrame列数据类型的转换
Pandas提供了多种数据类型转换方法。可以使用astype()函数来转换数据类型。例如,可以将字符串类型的列转换为整数类型的列: # Author : 小红牛 # 微信公众号:wdPython import pandas as pd# 创建包含字符串类型列的DataFrame df pd.DataFra…...
4-Python与设计模式--抽象工厂模式
4-Python与设计模式–抽象工厂模式 一、快餐点餐系统 想必大家一定见过类似于麦当劳自助点餐台一类的点餐系统吧。在一个大的触摸显示屏上, 有三类可以选择的上餐品: 汉堡等主餐、小食、饮料。当我们选择好自己需要的食物,支付完成后&#…...
STM32 默认时钟更改 +debug调试
STM32时钟 文章目录 STM32时钟前言一、修改系统时钟二、DEBUG 前言 为什么我们要改STM32的时钟呢,打个比方在做SPI驱动的时候,需要16M的时钟,但是stm32默认是72的分频分不出来,这个时候我们就要改系统时钟了,那么怎么…...
转成String类型的几种方式
文章目录 1. String.valueOf()2. 包装类-toString()3. 使用字符串拼接4. 强制类型转换 (String) object5. 总结:6. 基本数据类型和包装类 1. String.valueOf() String.valueOf():基本数据类型或包装类都可以通过 String.valueOf() 方法转为字符串表示形…...
Android BSP 开发之六
1.设定Android settings中某个xml文件(包括其子项)或者某个Preference不被搜索到 设定某个xml文件(包括子项)不被搜索到 找到该xml文件对应的fragment java文件中的SEARCH_INDEX_DATA_PROVIDER,在该provider中对isPageSearchEnabled方法进行重写并…...
mybatis的使用,mybatis的实现原理,mybatis的优缺点,MyBatis缓存,MyBatis运行的原理,MyBatis的编写方式
文章目录 MyBatis简介结构图Mybatis缓存(一级缓存、二级缓存)MyBatis是什么?mybatis的实现原理JDBC编程有哪些不足之处,MyBatis是如何解决这些问题的?Mybatis优缺点优点缺点映射关系 MyBatis的解析和运行原理MyBatis的…...
Effective Modern C++(1.顶层const与底层const)
1.顶层const与底层const的定义 const修饰的变量不可以改变,那么他就是顶层const,如: const int a 10; 那么,对于 const int *const p new int(10); 第二个const就是顶层const,因为他修饰的是p;第一个…...
mmsegmentation学习笔记
mmsegmentation教程 下载预训练权重 github–>mmsegmentation–>model zoo–>XXX model(如:PSPNet)–>找到预选连权重与config的前缀一致:pspnet_r50-d8_4xb2-40k_cityscapes-512x1024 (model) 了解配置文件 查看…...
RabbitMQ简易安装
一般来说安装 RabbitMQ 之前要安装 Erlang ,可以去Erlang官网下载。接着去RabbitMQ官网下载安装包,之后解压缩即可。 Erlang官方下载地址:Downloads - Erlang/OTP RabbitMQ官方下载地址:Downloading and Installing RabbitMQ —…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
