IMX6Ull内核移植详细过程讲解

news2024/11/27 2:21:41

文章目录

    • 一、安装相应依赖包
    • 二、下载相应的内核版本库
      • (1)讲解官网内核分支
      • (2)下载内核版本库
      • (3)内核目录文件讲解
    • 三、开始内核移植过程
      • (1)步骤一、修改默认架构和默认交叉编译器
      • (2)步骤二、添加需要忽略的文件类型
      • (3)步骤三、添加设备树以及补丁文件
        • 【1】添加设备树
        • 【2】添加补丁文件
      • (4)步骤四、添加 defconfig 配置文件
        • 【1】/arch/arm/configs
        • 【2】imx_v7_defconfig
    • 四、编译结果


借鉴学长的博客然后加上自己的理解:[内核移植]内核移植过程

  • 开发板介绍:
    IGKBoard(IoT Gateway Kit Board)ARM Linux物联网网关开发板。此开发板基于 NXP i.MX6ULL系列 Cortex-A7 高性能处理器设计。

  • 移植内核版本:

     root@igkboard:~# uname -a
     Linux igkboard 5.15.32 #3 SMP PREEMPT Sun Apr 9 16:17:47 CST 2023 armv7l armv7l armv7l GNU/Linux
    
  • 内核官网: The Linux Kernel Archives


一、安装相应依赖包

在移植 Linux 内核时,需要安装 lzop、libncurses5-dev 和 libssl-dev 这三个包如下:

  • lzopsudo apt-get install lzop 内核编译过程中需要使用到 lzop 压缩工具,以便将内核镜像等文件压缩成 .lzop 格式。
  • libncurses5-devsudo apt-get install libncurses5-dev 内核编译过程中需要使用 ncurses 库,以便在字符终端上显示菜单界面。
  • libssl-devsudo apt-get install libssl-dev 在内核中有一些功能需要使用 OpenSSL 库,例如 TLS 加密协议、数字证书等。

这三个包的安装是为了保证内核编译过程中所需的软件工具和库都具备。如果没有安装这些包,可能会导致在编译内核时出现相关的错误或警告信息。因此,在进行内核移植之前,需要先检查和安装相关的依赖包。


二、下载相应的内核版本库

(1)讲解官网内核分支

Kernel.org 是一个专门用于存储和发布 Linux 内核源代码的网站,也是 Linux 内核最早和最主要的代码托管平台之一。在 Kernel.org 上可以找到各个版本的 Linux 内核源码包以及相应的补丁包。另外,Kernel.org 还提供了内核开发和维护所需的各种工具和资源。

进入官网: The Linux Kernel Archives
在这里插入图片描述

  • Mainline 分支:也称为主线分支,是 Linux 内核开发的主要分支。这里的代码是最新、最先进的,包含了最新的特性、修复和改进。但也因此可能会不够稳定,存在一定的风险。
  • Stable 分支:该分支是针对针对生产环境的 bug 修复版本。一旦主线分支的代码出现问题,就会立刻在 Stable 分支中寻找并修复 bug。稳定版本相对来说比较可靠,但并不包含最新的特性。
  • Longterm 分支:该分支是长期维护版本,保持与主线分支相同的稳定性和实用性,并在此基础上提供长时间的维护支持。适合希望长期稳定运行的企业或组织使用。
  • Linux-next 分支:该分支包含了下一个内核版本的候选代码,也可以视为开发版的分支。优先考虑最新的特性、驱动程序和平台支持,但相较于 Mainline 分支更加不稳定。

所以我们一般选择比较稳定的长期维护的Lingtrem分支下的版本。

(2)下载内核版本库

点击你想下载的版本库:在这里插入图片描述
在这里插入图片描述
wget命令下载:
在这里插入图片描述
然后就可以看见我们的压缩包文件(我下载的是自己实验室版本的,大家根据自己的版本下载):

wangdengtao@wangdengtao-virtual-machine:~/kernel$ ls
linux-imx  linux-imx.tar.xz

要解压 .tar.xz 文件,可以使用 tar 命令行工具和 xz 工具一起进行解压。

如果系统尚未安装 tar 和 xz 工具,可以在 Ubuntu 或 Debian 系统上通过以下命令来安装:sudo apt-get install tar xz-utils

安装完成后,可以使用以下命令来解压 .tar.xz 文件:tar -xf filename.tar.xz

(3)内核目录文件讲解

我们进入解压缩的内核文件夹下,可以看见很多的文件,我们着重讲解一些比较重要的文件夹:

wangdengtao@wangdengtao-virtual-machine:~/kernel/linux-imx$ ls
arch     CREDITS        fs       Kbuild   LICENSES         mm                       modules.order   samples   System.map  vmlinux
block    crypto         include  Kconfig  MAINTAINERS      modules.builtin          Module.symvers  scripts   tools       vmlinux.o
certs    Documentation  init     kernel   MAINTAINERS.NXP  modules.builtin.modinfo  net             security  usr         vmlinux.symvers
COPYING  drivers        ipc      lib      Makefile         modules-only.symvers     README          sound     virt
  • arch:arch 目录是一个非常重要的目录,其中包含了 Linux 内核所有体系结构相关的代码,每一个体系结构(架构)都有一个相应的子目录。这些子目录包括了体系结构相关的代码、头文件和 Makefile 等。例如,在 arch/x86 这个目录下,存放的是 x86 架构的 CPU、设备驱动、指令集体系结构等代码,而在 arch/arm64 这个目录下则是 arm64 架构的代码和头文件等。
  • block:该目录包含块设备I/O和缓存管理的代码。
  • crypto:该目录包含了加密和 hash 算法的实现。
  • drivers:该目录包含了大部分设备驱动程序的源代码。
  • fs:该目录包含了 Linux 文件系统的代码,包括虚拟文件系统、磁盘文件系统和网络文件系统等。
  • include:该目录包含了内核头文件,为内核提供了各种数据类型与宏定义。
  • init:该目录包含内核启动和初始化代码。
  • kernel:该目录包含了大部分内核的核心功能,例如进程调度、内存管理、时间管理等。
  • mm:该目录包含了内存管理的代码,包括虚拟内存和物理内存的管理。
  • net:该目录包含了网络协议栈的实现。
  • security:该目录包含了 Linux 内核安全子系统的代码。

三、开始内核移植过程

i.MX6ULL是i.MX系列处理器中的一种,其内核移植的具体代码步骤如下:

  1. 下载 i.MX6ULL 平台的开发板原理图、CPU 手册、芯片手册等硬件资料,了解该平台的硬件信息。
  2. 下载适用于 i.MX6ULL 处理器的 Linux 内核源码,并将其解压到本地目录中。
  3. 安装交叉编译工具链,以便针对 i.MX6ULL 处理器进行交叉编译。可使用 Ubuntu 下的 apt-get 工具进行安装,例如:sudo apt-get install gcc-arm-linux-gnueabihf
  4. 使用 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- xxxconfig 命令配置内核选项,包括交叉编译器、CPU架构、驱动程序和文件系统等选项。这里需要根据实际硬件情况进行相应的配置,我们下面会详细讲解。
  5. 编译内核并生成 zImage 和 xxx.dtb 等文件。其中xxx.dtb 文件是设备树文件,需要根据开发板的硬件资料编写并编译。
  6. 将 zImage 和 xxx.dtb 文件拷贝到 TFTP 服务器的目录下。在开发板上启动 U-Boot 并设置启动参数,以便从 TFTP 服务器下载内核并启动。
  7. 启动开发板,观察内核启动过程,确保内核启动成功。如果内核启动失败,则需要检查设备树文件和配置选项是否正确,以及驱动程序是否正确编译和加载。

总体而言,在移植 i.MX6ULL 内核时,需要关注交叉编译工具链、内核选项配置、设备树的编写和使用等方面。需要根据实际硬件情况进行调试和优化。

(1)步骤一、修改默认架构和默认交叉编译器

针对 ARM 架构的处理器进行编译的相关命令,解释一下【ARCH 参数指定了编译的目标处理器架构为 ARM,CROSS_COMPILE 参数指定了交叉编译工具链的路径。】:

make ARCH=arm CROSS_COMPILE=/opt/buildroot/cortexA7/bin/arm-linux- distclean
make ARCH=arm CROSS_COMPILE=/opt/buildroot/cortexA7/bin/arm-linux- xxx_defconfig
make ARCH=arm CROSS_COMPILE=/opt/buildroot/cortexA7/bin/arm-linux- -j16

make ARCH=arm CROSS_COMPILE=/opt/buildroot/cortexA7/bin/arm-linux- distclean:该命令用于清理之前编译生成的文件,以便重新开始编译。

make ARCH=arm CROSS_COMPILE=/opt/buildroot/cortexA7/bin/arm-linux- xxx_defconfig:该命令用于生成配置文件,其中 xxx 表示具体的板子型号或配置文件名称。生成的配置文件包含了编译内核所需的各种选项和参数。如果不指定配置文件,则使用默认的配置。

make ARCH=arm CROSS_COMPILE=/opt/buildroot/cortexA7/bin/arm-linux- -j4:该命令用于编译内核,并指定同时使用的线程数为 4。其中,-j 参数用于指定并发编译的线程数。这样可以加速编译过程,提高编译效率。最终编译成功后,会在当前目录下生成内核镜像、设备树等文件。

总之,这些命令是在 Linux 系统下进行 ARM 架构的内核移植时常用的命令,需要根据具体的情况进行修改和适配。

但是为了方便,不打打这三串这么长的命令,我们需要在根源码目录下修改Makefile(添加下面的代码):

 386 ARCH = arm
 387 CROSS_COMPILE ?= /usr/bin/arm-linux-gnueabihf-

在这里插入图片描述
这里的交叉编译链的路径需要注意:如果你是直接用sudo apt-get install gcc-arm-linux-gnueabihf安装的交叉编译器的话就用我上面的路径,如果不是的话需要自己去找(你自己应该知道在哪儿的)

修改之后我们后面只需要执行下面的三个命令编译内核就可:

make distclean
make xxx_defconfig
make -j4

(2)步骤二、添加需要忽略的文件类型

打开Makefile,添加下面需要在编译过程中忽略的文件类型【有的话就补充,没有的话就添加】:

        -o -name '*.ko.*' \
        -o -name '*.dtbo' \
        -o -name '*.dtb' -o -name '*.dtbo' -o -name '*.dtb.S' -o -name '*.dt.yaml' \
        -o -name '*.dwo' -o -name '*.lst' \
        -o -name '*.su' -o -name '*.mod' \

在这里插入图片描述
解释:
内核 Makefile 中的这些 -o 选项是用于指定不需要编译或链接的文件类型,即需要忽略的文件类型。在编译内核时,由于内核代码量庞大,可能会生成大量的中间文件、临时文件和不必要的输出文件,这些文件会占用存储空间,造成混乱,同时也会增加编译时间和链接时间。为了避免这些问题,在内核 Makefile 中可以使用 -o 选项指定不需要编译或链接的文件类型,以达到减少文件存储和缩短编译时间的效果。

例如,在内核编译过程中,会生成大量的模块文件(.ko 文件)、设备树二进制文件(.dtb)、调试信息文件(.dwo)等,而这些文件对于内核的编译和链接来说并不是必需的,因此可以将它们忽略掉,从而减少编译和链接所需的时间和空间。

此外,某些后缀名为 .mod 的文件,如 .mod.c、.mod.o 和 *.mod.map 等文件,是由内核构建系统创建的,用于跟踪内核模块的依赖关系,并在模块加载时加载符号表等信息。这些文件不需要在编译过程中进行链接,因此也可以通过在 Makefile 中使用 -o 选项来排除它们。

在整个内核构建过程中,使用 -o 选项可以帮助开发者更好地管理内核代码和中间生成文件,保持代码库的整洁性,降低构建成本,提高构建效率。

(3)步骤三、添加设备树以及补丁文件

【1】添加设备树

打开 /arch/arm/boot/dts 添加 igkboard 自己的设备树文件 igkboard.dts 这个设备树文件【直接拿的开头介绍的学长博客中的代码】:

/*
 * Device Tree Source for LingYun IGKBoard(IoT Gateway Kit Board)
 * Based on imx6ul-14x14-evk.dts/imx6ul-14x14-evk.dtsi
 *
 * Copyright (C) 2022 LingYun IoT System Studio.
 * Author: Linke<731253265@qq.com>
 */

/dts-v1/;

#include "imx6ull.dtsi"

/ {
    model = "LingYun IoT System Studio IoT Gateway Board";
	compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";

	chosen {
		stdout-path = &uart1;
	};

	memory@80000000 {
		device_type = "memory";
		reg = <0x80000000 0x20000000>;
	};

	reserved-memory {
		#address-cells = <1>;
		#size-cells = <1>;
		ranges;

		linux,cma {
			compatible = "shared-dma-pool";
			reusable;
			size = <0xa000000>;
			linux,cma-default;
		};
	};

	mq2 {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "my_mq2";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_mq2>;
		mq2-gpio = <&gpio5 1 GPIO_ACTIVE_LOW>;
		interrupt-parent = <&gpio5>;
		interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
		status = "okay";
	};

	buzzer: pwm-buzzer {
		compatible = "pwm-beeper";
		pwms = <&pwm2 0 500000>;
		status = "okay";
	};

	pxp_v4l2 {
		compatible = "fsl,imx6ul-pxp-v4l2", "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";
		status = "okay";
	};

	reg_sd1_vmmc: regulator-sd1-vmmc {
		compatible = "regulator-fixed";
		regulator-name = "VSD_3V3";
		regulator-min-microvolt = <3300000>;
		regulator-max-microvolt = <3300000>;
		gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
		off-on-delay-us = <20000>;
		enable-active-high;
	};

	reg_peri_3v3: regulator-peri-3v3 {
		compatible = "regulator-fixed";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_peri_3v3>;
		regulator-name = "VPERI_3V3";
		regulator-min-microvolt = <3300000>;
		regulator-max-microvolt = <3300000>;
		gpio = <&gpio5 2 GPIO_ACTIVE_LOW>;
		/*
		 * If you want to want to make this dynamic please
		 * check schematics and test all affected peripherals:
		 *
		 * - sensors
		 * - ethernet phy
		 * - can
		 * - bluetooth
		 * - wm8960 audio codec
		 * - ov5640 camera
		 */
		regulator-always-on;
	};

	reg_can_3v3: regulator-can-3v3 {
		compatible = "regulator-fixed";
		regulator-name = "can-3v3";
		regulator-min-microvolt = <3300000>;
		regulator-max-microvolt = <3300000>;
	};

	reg_vref_adc: regulator@2 {
		compatible = "regulator-fixed";
		regulator-name = "VREF_3V3";
		regulator-min-microvolt = <3300000>;
		regulator-max-microvolt = <3300000>;
	};
};

/*+--------------+
  | Misc Modules |
  +--------------+*/

&snvs_poweroff {
	status = "okay";
};

&snvs_pwrkey {
	status = "okay";
};

&uart1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_uart1>;
	status = "okay";
};

&pwm2 { 
	#pwm-cells = <2>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_pwm2>;
	status = "okay";
};

/*+-------------------+
  | i2c Device Module |
  +-------------------+*/

&i2c1 {
	clock-frequency = <100000>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_i2c1>;
	status = "okay";
};

/*+-------------------+
  | iio Device Module |
  +-------------------+*/

&adc1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_adc1>;
	num-channels = <2>;
	vref-supply = <&reg_vref_adc>;
	status = "okay";
};

/*+---------------+
  | Camera Module |
  +---------------+*/

&i2c2 {
	clock-frequency = <100000>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_i2c2>;
	status = "okay";

	ov5640: ov5640@3c {
		compatible = "ovti,ov5640";
		reg = <0x3c>;
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_csi1 &pinctrl_camera_clock>;
		clocks = <&clks IMX6UL_CLK_CSI>;
		clock-names = "csi_mclk";
		csi_id = <0>;
		mclk = <24000000>;
		mclk_source = <0>;
		status = "disabled";
		port {
			ov5640_ep: endpoint {
				remote-endpoint = <&csi1_ep>;
			};
		};
	};

};

&csi {
	status = "disabled";

	port {
		csi1_ep: endpoint {
			remote-endpoint = <&ov5640_ep>;
		};
	};
};

/*+--------------+
  | Audio Module |
  +--------------+*/

&clks {
	assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
	assigned-clock-rates = <786432000>;
};

/*+------------------+
  | Ethernet Modules |
  +------------------+*/

&fec1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_enet1>;
	phy-mode = "rmii";
	phy-handle = <&ethphy0>;
	phy-supply = <&reg_peri_3v3>;
	status = "okay";
};

&fec2 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_enet2>;
	phy-mode = "rmii";
	phy-handle = <&ethphy1>;
	phy-supply = <&reg_peri_3v3>;
	status = "okay";

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

		ethphy0: ethernet-phy@0 {
			compatible = "ethernet-phy-id0022.1560";
			reg = <0>;
			micrel,led-mode = <1>;
			clocks = <&clks IMX6UL_CLK_ENET_REF>;
			clock-names = "rmii-ref";

		};

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

&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";
};

/*+---------------+
  | USB interface |
  +---------------+*/

&usbotg1 {
	dr_mode = "otg";
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_usb_otg1>;
	status = "okay";
};

&usbotg2 {
	dr_mode = "host";
	disable-over-current;
	status = "okay";
};

&usbphy1 {
	fsl,tx-d-cal = <106>;
};

&usbphy2 {
	fsl,tx-d-cal = <106>;
};

/*+------------------+
  | USDCHC interface |
  +------------------+*/

&usdhc1 {
	pinctrl-names = "default", "state_100mhz", "state_200mhz";
	pinctrl-0 = <&pinctrl_usdhc1>;
	pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
	pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
	cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
	keep-power-in-suspend;
	wakeup-source;
	vmmc-supply = <&reg_sd1_vmmc>;
	status = "okay";
};

&usdhc2 {
    pinctrl-names = "default", "state_100mhz", "state_200mhz";
	pinctrl-0 = <&pinctrl_usdhc2_8bit>;
	pinctrl-1 = <&pinctrl_usdhc2_8bit_100mhz>;
	pinctrl-2 = <&pinctrl_usdhc2_8bit_200mhz>;
    non-removable;
	bus-width = <8>;
    keep-power-in-suspend;
	wakeup-source;
	status = "okay";
};

/*+----------------------+
  | Basic pinctrl iomuxc |
  +----------------------+*/

&iomuxc {
	pinctrl-names = "default";

	pinctrl_camera_clock: cameraclockgrp {
		fsl,pins = <
			MX6UL_PAD_CSI_MCLK__CSI_MCLK		0x1b088
		>;
	};

	pinctrl_csi1: csi1grp {
		fsl,pins = <
			MX6UL_PAD_CSI_PIXCLK__CSI_PIXCLK	0x1b088
			MX6UL_PAD_CSI_VSYNC__CSI_VSYNC		0x1b088
			MX6UL_PAD_CSI_HSYNC__CSI_HSYNC		0x1b088
			MX6UL_PAD_CSI_DATA00__CSI_DATA02	0x1b088
			MX6UL_PAD_CSI_DATA01__CSI_DATA03	0x1b088
			MX6UL_PAD_CSI_DATA02__CSI_DATA04	0x1b088
			MX6UL_PAD_CSI_DATA03__CSI_DATA05	0x1b088
			MX6UL_PAD_CSI_DATA04__CSI_DATA06	0x1b088
			MX6UL_PAD_CSI_DATA05__CSI_DATA07	0x1b088
			MX6UL_PAD_CSI_DATA06__CSI_DATA08	0x1b088
			MX6UL_PAD_CSI_DATA07__CSI_DATA09	0x1b088
		>;
	};

	pinctrl_enet1: enet1grp {
		fsl,pins = <
			MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN	0x1b0b0
			MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER	0x1b0b0
			MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00	0x1b0b0
			MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01	0x1b0b0
			MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN	0x1b0b0
			MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00	0x1b0b0
			MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01	0x1b0b0
			MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1	0x4001b031
		>;
	};

	pinctrl_enet2: enet2grp {
		fsl,pins = <
			MX6UL_PAD_GPIO1_IO07__ENET2_MDC		0x1b0b0
			MX6UL_PAD_GPIO1_IO06__ENET2_MDIO	0x1b0b0
			MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN	0x1b0b0
			MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER	0x1b0b0
			MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00	0x1b0b0
			MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01	0x1b0b0
			MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN	0x1b0b0
			MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00	0x1b0b0
			MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01	0x1b0b0
			MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2	0x4001b031
		>;
	};

	pinctrl_flexcan1: flexcan1grp{
		fsl,pins = <
			MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX	0x1b020
			MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX	0x1b020
		>;
	};

	pinctrl_flexcan2: flexcan2grp{
		fsl,pins = <
			MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX	0x1b020
			MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX	0x1b020
		>;
	};

	pinctrl_i2c1: i2c1grp {
		fsl,pins = <
			MX6UL_PAD_GPIO1_IO02__I2C1_SCL	0x4001b8b0
			MX6UL_PAD_GPIO1_IO03__I2C1_SDA	0x4001b8b0
		>;
	};	

	pinctrl_i2c2: i2c2grp {
		fsl,pins = <
			MX6UL_PAD_UART5_TX_DATA__I2C2_SCL 0x4001b8b0
			MX6UL_PAD_UART5_RX_DATA__I2C2_SDA 0x4001b8b0
		>;
	};

	pinctrl_lcdif_dat: lcdifdatgrp {
		fsl,pins = <
			MX6UL_PAD_LCD_DATA00__LCDIF_DATA00  0x79
			MX6UL_PAD_LCD_DATA01__LCDIF_DATA01  0x79
			MX6UL_PAD_LCD_DATA02__LCDIF_DATA02  0x79
			MX6UL_PAD_LCD_DATA03__LCDIF_DATA03  0x79
			MX6UL_PAD_LCD_DATA04__LCDIF_DATA04  0x79
			MX6UL_PAD_LCD_DATA05__LCDIF_DATA05  0x79
			MX6UL_PAD_LCD_DATA06__LCDIF_DATA06  0x79
			MX6UL_PAD_LCD_DATA07__LCDIF_DATA07  0x79
			MX6UL_PAD_LCD_DATA08__LCDIF_DATA08  0x79
			MX6UL_PAD_LCD_DATA09__LCDIF_DATA09  0x79
			MX6UL_PAD_LCD_DATA10__LCDIF_DATA10  0x79
			MX6UL_PAD_LCD_DATA11__LCDIF_DATA11  0x79
			MX6UL_PAD_LCD_DATA12__LCDIF_DATA12  0x79
			MX6UL_PAD_LCD_DATA13__LCDIF_DATA13  0x79
			MX6UL_PAD_LCD_DATA14__LCDIF_DATA14  0x79
			MX6UL_PAD_LCD_DATA15__LCDIF_DATA15  0x79
			MX6UL_PAD_LCD_DATA16__LCDIF_DATA16  0x79
			MX6UL_PAD_LCD_DATA17__LCDIF_DATA17  0x79
			MX6UL_PAD_LCD_DATA18__LCDIF_DATA18  0x79
			MX6UL_PAD_LCD_DATA19__LCDIF_DATA19  0x79
			MX6UL_PAD_LCD_DATA20__LCDIF_DATA20  0x79
			MX6UL_PAD_LCD_DATA21__LCDIF_DATA21  0x79
			MX6UL_PAD_LCD_DATA22__LCDIF_DATA22  0x79
			MX6UL_PAD_LCD_DATA23__LCDIF_DATA23  0x79
		>;
	};

	pinctrl_lcdif_ctrl: lcdifctrlgrp {
		fsl,pins = <
			MX6UL_PAD_LCD_CLK__LCDIF_CLK	    0x79
			MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE  0x79
			MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC    0x79
			MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC    0x79
			/* used for lcd reset */
			MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09  0x79
		>;
	};

	pinctrl_peri_3v3: peri3v3grp {
		fsl,pins = <
			MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02	0x1b0b0
		>;
	};

	pinctrl_pwm1: pwm1grp {
		fsl,pins = <
			MX6UL_PAD_GPIO1_IO08__PWM1_OUT			0x110b0 
		>;
	};

	pinctrl_pwm7: pwm7grp {
		fsl,pins = <
			MX6UL_PAD_JTAG_TCK__PWM7_OUT	0x110b0
		>;
	};

	pinctrl_pwm8_nbiot: pwm8nbiotgrp {
		fsl,pins = <
			MX6UL_PAD_JTAG_TRST_B__PWM8_OUT	0x110b0
		>;
	};

	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
		>;
	};

	pinctrl_uart1: uart1grp {
		fsl,pins = <
			MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
			MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1
		>;
	};

	pinctrl_usb_otg1: usbotg1grp {
		fsl,pins = <
			MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID	0x17059
		>;
	};

	pinctrl_usdhc1: usdhc1grp {
		fsl,pins = <
			MX6UL_PAD_SD1_CMD__USDHC1_CMD     	0x17059
			MX6UL_PAD_SD1_CLK__USDHC1_CLK		0x10071
			MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 	0x17059
			MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 	0x17059
			MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 	0x17059
			MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 	0x17059
			MX6UL_PAD_UART1_RTS_B__GPIO1_IO19       0x17059 
			MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT    0x17059 
			MX6UL_PAD_GPIO1_IO09__GPIO1_IO09        0x17059 
		>;
	};

	pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
		fsl,pins = <
			MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x170b9
			MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x100b9
			MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170b9
			MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170b9
			MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170b9
			MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170b9

		>;
	};

	pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
		fsl,pins = <
			MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x170f9
			MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x100f9
			MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170f9
			MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170f9
			MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170f9
			MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170f9
		>;
	};

	pinctrl_usdhc2: usdhc2grp {
		fsl,pins = <
			MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x17059
			MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x17059
			MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
			MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
			MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
			MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
		>;
	};

	pinctrl_usdhc2_8bit: usdhc2grp_8bit {
		fsl,pins = <
			MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x10069
			MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x17059
			MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
			MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
			MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
			MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
			MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x17059
			MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x17059
			MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x17059
			MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x17059
		>;
	};

	pinctrl_usdhc2_8bit_100mhz: usdhc2grp_8bit_100mhz {
		fsl,pins = <
			MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x100b9
			MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x170b9
			MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170b9
			MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170b9
			MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170b9
			MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170b9
			MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170b9
			MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170b9
			MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170b9
			MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170b9
		>;
	};

	pinctrl_usdhc2_8bit_200mhz: usdhc2grp_8bit_200mhz {
		fsl,pins = <
			MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x100f9
			MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x170f9
			MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170f9
			MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170f9
			MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170f9
			MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170f9
			MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170f9
			MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170f9
			MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170f9
			MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170f9
		>;
	};

	pinctrl_spi_uart8: spi_uart8_grp {
		fsl,pins = <
			MX6UL_PAD_LCD_DATA20__ECSPI1_SCLK	0x10b0
			MX6UL_PAD_LCD_DATA22__ECSPI1_MOSI	0x10b0
			MX6UL_PAD_LCD_DATA23__ECSPI1_MISO	0x10b0
			MX6UL_PAD_LCD_DATA21__GPIO3_IO26	0x10b0
		>;
	};	

	pinctrl_mq2: mq2_grp {
		fsl,pins = <
			MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x17059 
		>;
	};

	pinctrl_pwm2: pwm2grp {
		fsl,pins = <
			MX6UL_PAD_GPIO1_IO09__PWM2_OUT 0x110b0
		>;
	};

	pinctrl_adc1: adc1grp {
		fsl,pins = <
			MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0xb0
		>;
	};
};

然后修改(添加)这个目录下的Makefile文件:

【定义 igkboard 设备树的编译选项和编译输出目录,并将 igkboard.dtb 添加到设备树文件列表中进行编译。同时,还将 overlays 目录添加到子目录列表中,表示编译完成后需要将该目录下的文件一同输出到内核镜像中】

DTC_FLAGS_igkboard := -@
dtb-$(CONFIG_SOC_IMX6UL) += igkboard.dtb
subdir-$(CONFIG_SOC_IMX6UL) += overlays

在内核的 Makefile 中定义了一个名为 DTC_FLAGS_igkboard 的变量,并将其设置为 -@。之后通过将 igkboard.dtb 添加到 dtb - $ (CONFIG_SOC_IMX6UL) 变量中,表示该设备树二进制文件将会被编译。同时,将 overlays 添加到 subdir-$(CONFIG_SOC_IMX6UL) 变量中,表示该目录下的文件也将会被编译。

具体来说,DTC_FLAGS_igkboard 是一个 DTC 程序(Device Tree Compiler)的编译选项,用于定义 igkboard 设备树的编译参数。其中,-@ 表示禁止 DTC 输出命令行信息。dtb-$ (CONFIG_SOC_IMX6UL) 是一个 Makefile 变量,表示在编译 soc_imx6ul 内核时需要生成的设备树文件列表。igkboard.dtb 是一个 igkboard 设备树的二进制文件,将会添加到设备树文件列表中进行编译。subdir-$ (CONFIG_SOC_IMX6UL) 则是一个 Makefile 变量,表示 soc_imx6ul 内核编译完成后需要生成的子目录列表。在该 Makefile 中,将 overlays 目录添加到 subdir-$(CONFIG_SOC_IMX6UL) 变量中,表示编译完成后需要将该目录下的文件一同输出到内核镜像中。

【2】添加补丁文件

/arch/arm/boot/dts下添加overlays 文件夹,在这个文件夹下的添加的 dts 文件,我们会在之后对其 Makefile 进行修改,并将其编译成 dtbo 文件。
如果对设备树插件不理解的可以参考这篇文章:
GIC中断控制器、设备树插件(Device Tree Overlay)以及内核定时器介绍

wangdengtao@wangdengtao-virtual-machine:~/kernel/linux-imx/arch/arm/boot/dts/overlays$ cat i2c1.dts
/dts-v1/;
/plugin/;

#include "../imx6ul-pinfunc.h"

/* 40-pin extended GPIO, I2C1 interfaces */

&i2c1 {
	clock-frequency = <100000>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_i2c1>;
	status = "okay";

	i2c_sht20@40{
		compatible = "imx_i2c_sht20";
		status = "okay";
		reg = <0x40>;
	};
};

&iomuxc {
pinctrl_i2c1: i2c1grp {
				  fsl,pins = <
					  MX6UL_PAD_GPIO1_IO02__I2C1_SCL	0x4001b8b0
					  MX6UL_PAD_GPIO1_IO03__I2C1_SDA	0x4001b8b0
					  >;
			  };	
};

我添加了这一个i2c的设备树插件。
/arch/arm/boot/dts/overlays 文件夹中添加 Makefile 文件,并添加如下内容,用于将该文件下的所有 dts 文件都编译成 dtbo 文件,作为备用,给 igkboard.dtb 打补丁:

# SPDX-License-Identifier: GPL-2.0

# required for overlay support
DTC_FLAGS += -@

dtb-y += i2c1.dtbo

(4)步骤四、添加 defconfig 配置文件

到目录/arch/arm/configs下,将imx_v7_defconfig修改为igkboard_defconfig即可。

【1】/arch/arm/configs

/arch/arm/configs 目录是 Linux 内核代码中专门用于存放 ARM 架构相关的配置文件的目录。在 Linux 内核的构建过程中,这些配置文件可以通过编译器和链接器的指定来生成可执行的内核镜像,并被用于驱动硬件设备和支持各种系统功能。

这些 ARM 架构的配置文件位于 /arch/arm/configs 目录下,以 .config 文件格式存储。这些配置文件通常包含内核构建选项、系统设置、外围设备驱动程序、虚拟文件系统等设置。在进行内核编译时,使用 make ARCH=arm menuconfig 命令可以通过菜单界面对这些选项进行选择和配置。

在 ARM 平台的开发中,使用这些预定义的 ARM 配置文件可以大大加快内核构建的速度,因为这些配置文件已经包含了 ARM 硬件平台的主要特性和功能。同时,这些 ARM 配置文件也为开发者提供了一个模板,可以调整内核的编译选项、功能和驱动程序,以满足特定的需求和限制。

总之,/arch/arm/configs 目录中存储着一些预定义的 ARM 架构配置文件,这些配置文件包含了内核构建选项、系统设置、外围设备驱动程序、虚拟文件系统等设置,可以帮助开发者快速构建适用于特定 ARM 硬件平台的 Linux 内核镜像。

【2】imx_v7_defconfig

imx_v7_defconfig 是 Linux 内核针对 i.MX 系列 ARMv7 处理器的一个默认配置文件。存放位置在 /arch/arm/configs/imx_v7_defconfig

该配置文件包含了内核编译所需的所有选项,以生成适用于 i.MX 系列 ARMv7 处理器的预定义内核二进制镜像。这些选项涵盖了以下方面:

  • CPU 架构和型号(ARMv7 Cortex-A 核心)
  • 内核启动参数(内核命令行等)
  • 内核功能开关(调试信息、内存管理、调度程序、定时器、时钟、IRQ 控制器、访问控制、加密支持、虚拟文件系统等)
  • 文件系统支持(EXT4、FAT、NTFS、SquashFS、JFFS2、UBIFS 等)
  • 块设备驱动程序(MMC/SD/SDIO、NAND、eMMC、SPI NOR 等)
  • 网络驱动程序(有线网卡、Wi-Fi、蓝牙等)
  • 开发者可以通过命令 make ARCH=arm imx_v7_defconfig生成内核配置文件 .config,然后可
  • 使用 make ARCH=arm menuconfig 或其他内核配置工具对其进行修改和优化。之后,运行 make ARCH=arm 即可开始编译 i.MX 系列 ARMv7 处理器的 Linux 内核。

总之,imx_v7_defconfig 是针对 i.MX 系列 ARMv7 处理器的默认内核配置文件,包含了所有内核编译所需的选项。它为开发者提供了一个快速生成适用于 i.MX 系列 ARMv7 处理器的 Linux 内核镜像的方式。


四、编译结果

使用之前提到的命令编译内核:

make distclean
make igkboard_defconfig
make -j4

等待一定的时间之后我们可以在内核源码文件夹下看到 vmlinux 以及 /arch/arm/boot 文件夹下看到 ImagezImage 文件。

对于内核文件,vmlinux 就是最原始的内核文件,但是该文件太大,不利于传输,因此对其进行压缩,这个过程是,先利用 objcopy 取消掉 vmlinux 中的一些信息,比如符号之类的,然后生成 Image 文件,然后用 gzip 工具,对=Image 文件进行压缩,最后生成 zImage 文件,然后将 zImage 烧录到开发板即可。
在这里插入图片描述

wangdengtao@wangdengtao-virtual-machine:~/kernel/linux-imx/arch/arm/boot$ ls
bootp  compressed  deflate_xip_data.sh  dts  Image  install.sh  Makefile  zImage

然后将igkboard.dts和zImage文件放在tftp目录下,tftp网络启动试着启动。
tftp网络启动不会的参考这篇文章:Linux嵌入式uboot使用tftp网络启动加载zImage、设备树


多余:对vlinux的理解:

vmlinux 是 Linux 内核编译成功后生成的一个文件,它是内核代码经过编译、链接后的可执行文件。

在 Linux 内核编译的过程中,内核源代码被先进行预处理、编译、汇编等过程生成目标文件,然后在链接阶段将这些目标文件链接成可执行文件。最终生成的可执行文件就是 vmlinux。

vmlinux 是一个非压缩的 ELF 格式(Executable and Linkable Format)的可执行文件,包含了内核的所有代码和数据。它不同于 bzImage 或 zImage,这两个文件是经过压缩的内核镜像文件,可以直接用于引导启动操作系统。

一般来说,如果用户要将内核文件放到 bootloader 中引导 bootloader 的话,需要将 vmlinux 文件进行压缩处理,然后生成 bzImage 或 zImage 文件。另外,内核开发者也可以通过 objdump 等工具分析 vmlinux 文件,以了解内核代码的结构和实现细节。


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

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

相关文章

modbus协议与nodejs modbus-serial实现

nodejs可通过modbus-serial库来实现modbus协议 npm install modbus-srial 安装完后在examples目录下有例子说明如何使用&#xff0c;本文主要讲述作为客户端的使用方式。 polling_RTU是使用485串口来实现modbus通信&#xff0c; polling_TCP和 polling_UDP则使用TCP/UDP来实现…

HBuilderX使用

HBuilderX使用&#xff08;Vue前后端分离&#xff09; 概述&#xff1a;DCloud开发者后台 DAccount Service 1、官网下载开发工具&#xff1a;HBuilderX-高效极客技巧 注意&#xff1a;安装目录路径中不能出现中文特殊字符&#xff0c;否则会造成项目无法编译。比如C:/Progr…

learn_C_deep_10 深刻认识C语言重点操作符

目录 注释符号 其他注释方法 注释建议 接续符和转义符 在续行符\之前或者之后带上空格&#xff0c;行不行&#xff1f; \n&#xff1a;换行符与\r&#xff1a;回车符之间的区别 两个小程序(旋转光标、倒计时) 单引号和双引号 ​编辑abcd这样写有问题吗? 特殊情况 为…

ThinkPHP6表单上传的数据获取的四种方式【请求对象调用,静态调用,助手函数调用,原生的get|post】

ThinkPHP6表单上传的数据获取 首先一个form表单中的Input控件需要存在对应的name值&#xff0c;然后method为post|get,action为要提交到的控制器的哪个方法 例如(本文的前端视图代码均为下面的html)&#xff1a; <form method"post" action"/index.php/lo…

Hard Patches Mining for Masked Image Modeling

摘要 蒙面图像建模&#xff08;MIM&#xff09;因其在学习可伸缩视觉表示方面的潜力而引起了广泛的研究关注。在典型的方法中&#xff0c;模型通常侧重于预测掩码补丁的特定内容&#xff0c;并且它们的性能与预定义的掩码策略高度相关。直观地说&#xff0c;这个过程可以被看作…

应用架构总结

架构目标 高可用性 整体系统可用性最低99.9%&#xff0c;目标99.99%。全年故障时间整个系统不超过500分钟&#xff0c;单个系统故障不超过50分钟。 高可扩展性 系统架构简单清晰&#xff0c;应用系统间耦合低&#xff0c;容易水平扩展&#xff0c;业务功能增改方便快捷。 低成…

IOS APP universal links 申请流程

一、背景 项目框架&#xff1a;APP h5 需求&#xff1a;APP首页可以选择微信&#xff0c;进行授权登录。 问题&#xff1a;在APP跳转到微信进行授权的时候&#xff0c;提示“由于应用universal link校验不通过&#xff0c;无法完成微信登录”。 二、申请流程 1. 苹果后台管…

XML语言简介和语法介绍

XML语言简介 文章目录 XML语言简介用途各部分注解声明元素属性注释CDATA转义字符 可拓展标记语言&#xff1b;是SGML的子集&#xff0c;可以描述很复杂的数据关系 用途 用于组织和存储数据&#xff0c;除此之外都和XML本身无关 配置文件(例子&#xff1a;Tomcat的web.xml,se…

Android 消息机制

消息机制相关API Message(消息) 可理解为线程之间通讯的数据单元, 可以通过message携带需要的数据 创建对象: Message.obtain(what) 封装数据 public int what public int arg public Object obj Handler(处理器) Handler是Message的处理器, 同时也负责消息的发送和移除的…

Linux内核(十四)Input 子系统详解 IV —— 配对的input设备与input事件处理器 input_register_handle

文章目录 input_handle结构体详解配对的input设备与input事件处理器实例input核心层对驱动层和事件层之间的框架建立流程图 本文章中与input子系统相关的结构体可参考input子系统结构体解析 input函数路径&#xff1a;drivers/input/input.c input_handle结构体详解 input_ha…

二十六:交易详细信息

功能需求 用户在交易主页面&#xff0c;点击交易名称超级链接&#xff0c;跳转到交易明细页面&#xff0c;完成查看交易明细的功能。 *显示交易的基本信息 *显示交易的备注信息 *显示交易的历史信息 *显示交易的阶段图标信息 流程图 后端代码实现 1.tran TranMapper /*…

实现Fast sigmoid和Softmax

Sigmoid 函数介绍 Sigmoid 函数&#xff08;Logistic 函数&#xff09;是神经网络中非常常用的激活函数&#xff0c;它的数学表示如下: 由于 e x e^x ex幂运算是非常耗时的计算&#xff0c;因此尝试通过替换sigmoid中的 e x e^x ex运算&#xff0c;来提高运行效率&#xff0c;同…

Linux篇4

Shell常用命令 1. 日期时间类1.1 date&#xff1a;日期时间类1.1.1 查看当前日期时间1.1.2 查看非当前日期时间1.1.3 设置系统日期时间 1.2 cal&#xff1a;日历类 2. 用户管理命令2.0 id&#xff1a;查看用户是否存在2.1 useradd&#xff1a;添加新用户2.2 passwd&#xff1a;…

Linux相关问题

中英文切换 super空格切换中英文&#xff1b;super指键盘上的Win键&#xff1b; 开机自启动服务设置 可视化方式&#xff1a;输入setup命令进入自启动服务配置&#xff1b;通过上下键选中服务&#xff0c;通过空格选择是否自启动该服务&#xff1b; 开启不同的终端 CTRLALT…

Jetson nano 之 ROS入门 - - 机器人坐标变换

文章目录 前言一、空间坐标变换原理1. 位姿描述2. 欧拉角与四元数 二、ROS中python实现坐标变换1. 坐标msg消息载体2. 乌龟跟随的程序实现 总结 前言 ROS给开发者们提供了很多集成度很高的开发工具&#xff0c;例如rviz和gazebo。rviz是三维可视化工具&#xff0c;可以显示图像…

【P23】JMeter 用户参数(User Parameters)

&#xff08;1&#xff09;、测试计划右键 <<< 添加 <<< 前置处理器 <<< 用户参数 如图&#xff0c;添加两个变量&#xff0c;每个变量包含两个用户 &#xff08;2&#xff09;、测试计划右键 <<< 添加 <<< 线程&#xff08;用户…

ChatGPT的工作原理(纯干货,万字长文)

ChatGPT 能够自动生成一些读起来表面上甚至像人写的文字的东西&#xff0c;这非常了不起&#xff0c;而且出乎意料。但它是如何做到的&#xff1f;为什么它能发挥作用&#xff1f;我在这里的目的是大致介绍一下 ChatGPT 内部的情况&#xff0c;然后探讨一下为什么它能很好地生成…

Python采集二手房源数据信息并做多线程

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 目录标题 前言环境使用:模块使用:代码展示多线程 尾语 &#x1f49d; 环境使用: Python 3.8 Pycharm 模块使用: requests >>> pip install requests 数据请求模块 parsel >>> pip install parsel 数据…

详述:冒泡排序

一、接下来讲解一下c语言中比较简单的排序方法&#xff1a;冒泡排序 1.冒泡排序的核心思想&#xff1a;是两两相邻的元素进行比较 动画演示&#xff1a; 应用冒泡排序需要明确2点&#xff1a; 1.需要进行多少趟冒泡排序 2.每趟冒泡排序&#xff0c;需要比较的对数 二、代码实…

发布 Copilot Chat Sample App

我们很高兴为您介绍 Semantic Kernel 的 Copilot Chat Sample App&#xff01;借助此应用程序&#xff0c;开发人员可以使用自然语言处理、语音识别和文件上传等高级功能轻松构建自己的聊天机器人。通过利用基于 LLM 的 AI&#xff0c;您可以通过 Semantic Kernel 使用您自己的…