52、U-boot2023的移植教程

news2024/11/25 0:40:55

uboot:https://ftp.denx.de/pub/u-boot/
nxp-uboot:https://github.com/nxp-imx/uboot-imx

1、顶层Makefile

 文件加入编译的两种方式:以xxx/xxx.c文件为例
        1、使用menuconfig:
              先编辑.c所在目录下的Kconfig,加入配置项xxx
              再编辑.c所在目录下的Makefile,添加obj-$(CONFIG_xxx) = xxx.o
        2、不使用menuconfig:
              直接编辑.c所在目录下的Makefile,添加obj-y = xxx.o
        说明:$(libs-y)依赖每个文件夹下的xxx-in.o,而每个文件夹下的xxx-in.o又依赖当前文件夹的所有.o文件。

2、Kbuild框架

<1>在scripts文件夹下,有一个Kbuild.include文件中定义了如下几个关键的变量:

   181: build := -f $(srctree)/scripts/Makefile.build obj
   187: modbuiltin := -f $(srctree)/scripts/Makefile.modbuiltin obj
   193: dtbinst := -f $(srctree)/scripts/Makefile.dtbinst obj
   199: clean := -f $(srctree)/scripts/Makefile.clean obj
   205  hdr-inst := -f $(srctree)/scripts/Makefile.headersinst obj
   217: echo-cmd = $(if $($(quiet)cmd_$(1)),\
	        echo '  $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
   .....

<2>在顶层Makefile文件的391-393行有如下:

   # We need some generic definitions (do not try to remake the file).
   scripts/Kbuild.include: ;
   include scripts/Kbuild.include                   # 包含<1>中定义的变量
   
<3>在顶层Makefile文件的1232-1234行有如下:

   %.imx: $(IMX_DEPS) %.bin
       $(Q)$(MAKE) $(build)=arch/arm/mach-imx $@    # <1>中定义的build被使用
       $(BOARD_SIZE_CHECK)

<4>在顶层Makefile文件的1255-1259行有如下:(make dtbs命令)
   PHONY += dtbs
   dtbs: dts/dt.dtb
	   @:
   dts/dt.dtb: u-boot
	   $(Q)$(MAKE) $(build)=dts dtbs  
 
  展开得:
       @ make -f $(srctree)/scripts/Makefile.build obj=dts dtbs
  其中:obj=dts是一个传入的变量, dtbs是要构建的目标

2、u-boot.map文件

反汇编:arm-linux-gnueabihf-objdump -D -m arm u-boot > u-boot.dis

./scripts/dtc/dtc -I dtb -O dts -o ./itop.dts ./arch/arm/dts/imx6ull-14x14-itop.dtb

./scripts/dtc/dtc -I dtb -O dts -o ./evk.dts ./arch/arm/dts/imx6ull-14x14-evk.dtb

注意:如何确定哪个.c文件的哪个函数被编译?
        通过函数名在u-boot.map、u-boot.dis这两个文件中搜索。先在u-boot.dis找到函数的链接地址,以此链接地址在u-boot.map中搜索,即可确定是哪个.c文件下的函数被编译。

save_boot_params_ret:
    /* disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode, except if in HYP mode already */
	/* 禁用中断(FIQ 和 IRQ),同时将处理器设置为 SVC32 模式,除非已经处于 HYP 模式。 */
	mrs	r0, cpsr            @ 将当前程序状态寄存器(CPSR)的值加载到寄存器r0中
	and	r1, r0, #0x1f		@ 使用掩码操作提取r0的低5位,即当前的处理器模式
	teq	r1, #0x1a		    @ 测试是否当前处理器模式为HYP模式(Hypervisor mode)
	bicne	r0, r0, #0x1f	@ 如果不在HYP模式,清除 CPSR 中的所有模式位
	orrne	r0, r0, #0x13	@ 如果不在HYP模式,设置 CPSR 的模式为SVC模式
	orr	r0, r0, #0xc0		@ 禁用FIQ和IRQ中断,将 CPSR 的FIQ和IRQ位设置为 1
	msr	cpsr,r0             @ 将修改后的 CPSR 的值写回 CPSR 寄存器,完成设置

	/* Set V=0 in CP15 SCTLR register - for VBAR to point to vector */
    /* 将 CP15 的 SCTLR 寄存器中将 V 位设置为0,以便将 VBAR 指向向量表 */
	mrc	p15, 0, r0, c1, c0, 0	@ 读取 CP15 SCTLR 寄存器里面的值
	bic	r0, #CR_V		        @ 将 CP15 SCTLR 寄存器中的 V 位清零
	mcr	p15, 0, r0, c1, c0, 0	@ 写回修改后的值到 CP15 SCTLR 寄存器

   	/* Set vector address in CP15 VBAR register */
    /* 在 CP15 的 VBAR 寄存器中设置向量表的地址   */
	ldr	r0, =_start             @ 将 _start 符号的地址加载到寄存器 r0 中
	mcr	p15, 0, r0, c12, c0, 0	@ 将 r0 中的地址写入 CP15 VBAR 寄存器,设置异常向量表基地址

    bl	cpu_init_cp15
    bl	cpu_init_crit
    bl	_main

注:对于CP15协处理器的操作,CP15有c0-c15共16个寄存器组,每个组里面含有多个寄存器
mcr	p15, 0, r0, c12, c0, 0  @读操作,读取c12寄存器组里面的c0,0对应的寄存器到r0中
注意:c0,0并不是偏移的意思,而是由具体的表决定的,不要以为c0,1就是组里的第1个寄存器,
     这是不一定的。具体的cx,x对应组里面的第几个寄存器,参考手册上有写。
/*************************************************************************************
 * cpu_init_cp15
 * 设置 CP15 寄存器(缓存、MMU、TLBs)。如果定义了 CONFIG_SYS_ICACHE_OFF,则打开 I-cache。
 *************************************************************************************/
cpu_init_cp15:
    /* Invalidate L1 I/D */
	mov	r0, #0			        @ set up for MCR (r0 = 0)
	mcr	p15, 0, r0, c8, c7, 0	@ invalidate TLBs (置零)
	mcr	p15, 0, r0, c7, c5, 0	@ invalidate icache (置零)
	mcr	p15, 0, r0, c7, c5, 6	@ invalidate BP array (置零)
	dsb
	isb

    /* disable MMU stuff and caches */
	mrc	p15, 0, r0, c1, c0, 0  @ 读 SCTLR => r0 
	bic	r0, r0, #0x00002000	   @ clear bits 13 (--V-)
	bic	r0, r0, #0x00000007	   @ clear bits 2:0 (-CAM)
	orr	r0, r0, #0x00000002	   @ set bit 1 (--A-) Align
	orr	r0, r0, #0x00000800	   @ set bit 11 (Z---) BTB
	orr	r0, r0, #0x00001000	   @ set bit 12 (I) I-cache
    mcr	p15, 0, r0, c1, c0, 0  @ 写 r0 => SCTLR

    mov	r5, lr			       @ Store my Caller (r5 = lr)(跳转)

	mrc	p15, 0, r1, c0, c0, 0  @ r1 has Read Main ID Register (r1 = MIDR)
	mov	r3, r1, lsr #20		   @ get variant field (r3 = r1>>20)
	and	r3, r3, #0xf		   @ r3 has CPU variant (r3 = r3&0xf)
	and	r4, r1, #0xf		   @ r4 has CPU revision (r4 = r1&0xf)
	mov	r2, r3, lsl #4		   @ shift variant field for combined value(r2 = r3<<4)
	orr	r2, r4, r2		       @ r2 has combined CPU variant + revision(r2 = r4|r2)

    /* Early stack for ERRATA that needs into call C code */
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
	ldr	r0, =(CONFIG_SPL_STACK)
#else
	ldr	r0, =(SYS_INIT_SP_ADDR)
#endif
	bic	r0, r0, #7	 @ 8-byte alignment for ABI compliance(将r0最低的三个比特位清零)
	mov	sp, r0       @ SP = r0
    
    mov	pc, r5	     @ back to my caller ( pc=r5 )(返回)
cpu_init_crit:
    b lowlevel_init   #(注意:这是一个无返回跳转)

# 下面具体分析lowlevel_init -------------------------------------------------
lowlevel_init:
    /*Setup a temporary stack. Global data is not available yet. */
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
	ldr	sp, =CONFIG_SPL_STACK  @ 设置堆栈指针
#else
	ldr	sp, =SYS_INIT_SP_ADDR  @ 设置堆栈指针
#endif
	bic	sp, sp, #7    @ 8字节对齐 for ABI compliance(将sp最低的三个比特位清零) 
#ifdef CONFIG_SPL_DM
	mov	r9, #0        @ r9 = 0
#else
    push  {ip, lr}    @ 压ip入栈、压lr入栈

	bl	s_init        @ 调用s_init(C函数)初始化处理器的时钟
	pop	{ip, pc}      @ 出栈




#include <asm/io.h>
#include <asm/arch/imx-regs.h>
_main:
#if defined(CONFIG_TPL_BUILD) && defined(CONFIG_TPL_NEEDS_SEPARATE_STACK)
    ldr	r0, =(CONFIG_TPL_STACK)
#elif defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
	ldr	r0, =(CONFIG_SPL_STACK)
#else
	ldr	r0, =(SYS_INIT_SP_ADDR)
#endif
	bic	r0, r0, #7	/* 8-byte alignment for ABI compliance */
	mov	sp, r0                       @ sp = r0 (设置栈指针)
	bl	board_init_f_alloc_reserve   @ 在栈中,分配早期的malloc区域和gd区域(r0为函数的参数)
	mov	sp, r0                       @ sp = r0 (r0为函数的返回值)
	/* set up gd here, outside any C code */
	mov	r9, r0                       @ r9 = r0
	bl	board_init_f_init_reserve    @ 对早期的malloc区域和gd区域进行初始化(r0为函数的参数)

#if defined(CONFIG_DEBUG_UART) && CONFIG_IS_ENABLED(SERIAL)
	bl	debug_uart_init
#endif

#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_EARLY_BSS)
	CLEAR_BSS
#endif
    mov	r0, #0
	bl	board_init_f

    ldr	r0, [r9, #GD_START_ADDR_SP]	/* sp = gd->start_addr_sp */
	bic	r0, r0, #7	/* 8-byte alignment for ABI compliance */
	mov	sp, r0
	ldr	r9, [r9, #GD_NEW_GD]		/* r9 <- gd->new_gd */
	adr	lr, here
    
    ......
    bl relocate_code
    ......
struct driver *drv = ll_entry_start(struct driver, driver);

struct driver *drv = ({									\
	static char start[0] __aligned(CONFIG_LINKER_LIST_ALIGN)	\
		__attribute__((unused))					\
		__section("__u_boot_list_2_driver_1");			\
	struct driver * tmp = (struct driver *)&start;					\
	asm("":"+r"(tmp));						\
	tmp;								\
});

//说明:返回__u_boot_list_2_driver_1段的第一个元素的起始地址

3.1、添加自己的单板<主>

1、添加头文件
    cp ./include/configs/mx6ullevk.h   ./include/configs/mx6ullitop.h
    vim  ./include/configs/mx6ullitop.h
    修改.h开头的宏定义

2、添加板级文件夹
    cp -r ./board/freescale/mx6ullevk   ./board/freescale/mx6ullitop
    mv ./board/freescale/mx6ullitop/mx6ullevk.c ./board/freescale/mx6ullitop/mx6ullitop.c
    vim ./board/freescale/mx6ullitop/Kconfig
    vim ./board/freescale/mx6ullitop/Makefile
    vim ./board/freescale/mx6ullitop/MAINTAINERS
    vim ./board/freescale/mx6ullitop/imximage.cfg

3、添加设备树文件1
    cp  ./arch/arm/dts/imx6ull-14x14-evk.dts  ./arch/arm/dts/imx6ull-14x14-itop.dts
    vim ./arch/arm/dts/imx6ull-14x14-itop.dts
    vim ./arch/arm/dts/Makefile
    在 dtb-$(CONFIG_MX6ULL) 添加一项
    imx6ull-14x14-itop.dtb \   (为了使能dtb的编译)

4、添加设备树文件2 
   cp ./arch/arm/dts/imx6ull-14x14-evk-u-boot.dtsi ./arch/arm/dts/imx6ull-14x14-itop-u-boot.dtsi

5、添加默认配置文件
    cp ./configs/mx6ull_14x14_evk_defconfig ./configs/mx6ull_14x14_itop_defconfig
    vim configs/mx6ull_14x14_itop_defconfig
    <1>找到 CONFIG_TARGET_MX6ULL_14X14_EVK=y​
    <1>改为 CONFIG_TARGET_MX6ULL_14X14_ITOP=y
    <2>找到 CONFIG_DEFAULT_DEVICE_TREE="imx6ull-14x14-evk"
    <2>改为 ​CONFIG_DEFAULT_DEVICE_TREE="imx6ull-14x14-itop"​​

6、修改Kconfig文件
    vim ./arch/arm/mach-imx/mx6/Kconfig
    添加
    config TARGET_MX6ULL_14X14_ITOP
	    bool "Support mx6ull_14x14_itop"
	    depends on MX6ULL
	    select BOARD_LATE_INIT
	    select DM
	    select DM_THERMAL
	    select MX6ULL
	    imply CMD_DM
    添加
        source "board/freescale/mx6ullitop/Kconfig"
7、修改 ./arch/arm/mach-imx/cpu.c,在reset_cpu函数中添加如下代码:
 
方法一:注释掉此函数,此时会链接drivers/watchdog/imx_watchdog.c中的reset_cpu函数
/*
__weak void reset_cpu(void)
{
	return;
}
*/
方法二:修改函数如下
__weak void reset_cpu(void)
{
	#include <fsl_wdog.h>
	struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
	//do not assert internal reset
	u16 wcr = 0x04|0x10; // WCR_WDE|WCR_SRS 
	//Write 3 times to ensure it works, due to IMX6Q errata ERR004346 
	writew(wcr, &wdog->wcr);
	writew(wcr, &wdog->wcr);
	writew(wcr, &wdog->wcr);
	//Start while 
	for(;;);
	return;
}

3.2、移植网络的驱动<主>

< 1 >设备树:imx6ull-14x14-itop.dts

一、设备树:目录
[arch/arm/dts/imx6ull-14x14-itop.dts]
    |-->#include "imx6ull.dtsi"
        |-->#include "imx6ul.dtsi"
            |-->#include <dt-bindings/clock/imx6ul-clock.h>
            |-->#include <dt-bindings/gpio/gpio.h>
            |-->#include <dt-bindings/input/input.h>
            |-->#include <dt-bindings/interrupt-controller/arm-gic.h>
            |-->#include "imx6ul-pinfunc.h"
        |-->#include "imx6ull-pinfunc.h"
        |-->#include "imx6ull-pinfunc-snvs.h"
    |-->#include "imx6ul-14x14-evk.dtsi"
[arch/arm/dts/imx6ull-14x14-evk-u-boot.dtsi]
二、设备树:网络相关
[arch/arm/dts/imx6ull-14x14-itop.dts]
    |-->#include "imx6ull.dtsi"
        |-->#include "imx6ul.dtsi"

//Fast Ethernet Controller 1 (CPU内部资源)
&fec1 { 
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_enet1 
			     &pinctrl_enet1_reset>; //zjh add
	phy-mode = "rmii";
	phy-handle = <&ethphy0>;
	phy-supply = <&reg_peri_3v3>;
	phy-reset-gpios = <&gpio5 7 GPIO_ACTIVE_LOW>; //zjh add
	phy-reset-duration = <200>;                   //zjh add
	status = "okay";
};
//Fast Ethernet Controller 2 (CPU内部资源)
&fec2 { 
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_enet2 
				 &pinctrl_enet2_reset>; //zjh add
	phy-mode = "rmii";
	phy-handle = <&ethphy1>;
	phy-supply = <&reg_peri_3v3>;
	phy-reset-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>; //zjh add
	phy-reset-duration = <200>;                   //zjh add
	status = "okay";
	mdio { //MDIO总线:用于连接 FEC 和 PHY 设备
		#address-cells = <1>;
		#size-cells = <0>;
		ethphy0: ethernet-phy@2 { //(网口1)
			compatible = "ethernet-phy-id0022.1560";
			reg = <2>;                //phy芯片地址(硬件电路决定)
			micrel,led-mode = <1>;
			clocks = <&clks IMX6UL_CLK_ENET_REF>;
			clock-names = "rmii-ref";
		};
		ethphy1: ethernet-phy@1 { //(网口2)
			compatible = "ethernet-phy-id0022.1560";
			reg = <1>;                //phy芯片地址(硬件电路决定)
			micrel,led-mode = <1>;
			clocks = <&clks IMX6UL_CLK_ENET2_REF>;
			clock-names = "rmii-ref";
		};
	};
};			

< 2 >迅为开发板硬件原理图

5、DM框架

DM 是 U-Boot 中的驱动框架,全称 Driver Mode。
Linux 中 platform bus 模型的驱动有着三要素:device 、bus 、driver 
Uboot 中 Driver Mode 模型的驱动也有三要素:udevice、uclass、driver。

1、udevice 描述具体的某一个硬件设备。
  struct udevice {
	const struct driver *driver;
	const char *name;
    ......
  };
  通过三种路径生成:
  a、dts设备节点。(大多数使用)
  b、U_BOOT_DEVICE(__name) 宏申明 (少部分使用)
  c、主动调用 device_bind_xxx 系列 API (极少部分使用)

2、driver 是与这个设备匹配的驱动。
  通过 U_BOOT_DRIVER(__name) 宏声明。如果 driver 实现了 bind 接口,
  该 bind 将在 device_bind_common 中 device 和 driver 匹配上后
  被调用, 而且在 device_bind_common 中会完成 udevice 和 driver 的绑定。

  driver 一般都有对应的 probe 接口,通过 device_probe(struct udevice *dev) 调用,
  要注意的是driver 的 bind 接口调用的比 probe 接口早, 大部分在 dm_init_and_scan 中就被调用了

  driver 一般会提供 ops 操作接口,供上一层调用。
  
  需要说明的是,driver 一般都不需要把自己注册到 uclass 中,
  而是在 device_bind_common 阶段实现 driver 、uclass、device 三者的对接,
  然后 uclass 层通过 udevice->driver->ops 获取对应 driver 的操作接口。

3、uclass 是同一类设备的抽象,提供管理同一类设备的抽象接口
  主要包括两个类型的结构体:struct uclass_driver 和 struct uclass
  其中struct uclass_driver 为 struct uclass 的驱动
  struct uclass_driver {  //由UCLASS_DRIVER(__name)定义
     const char *name; 
     enum uclass_id id;
	 int (*post_bind)(struct udevice *dev);
     ......
  };

  struct uclass {
	 void *priv_;                  //类本身私有数据
	 struct uclass_driver *uc_drv; //类本身的驱动程序
	 struct list_head dev_head;    //该类中的设备列表
	 struct list_head sibling_node;//类链表中的下一个类
  };

uclass和udevice都是动态生成的

1、在解析设备树中的设备或直接定义的平台设备的时候,会动态生成udevice。
2、然后找到udevice对应的driver,通过driver中的uclass id得到uclass_driver id。
3、从uclass链表中查找对应的uclass是否已经生成,没有生成的话则动态生成uclass。
注:uclass链表的起点是gd的一个成员:gd->uclass_root        (*全局变量gd的很重要*)

设备驱动的使用(应用层使用驱动)

1、首先需要通过 uclass_get_device_xxx 系列 API 拿到该设备的 udevice。
2、然后通过该设备的 uclass 提供的 API 操作该设备。
<+>uclass_get_device_xxx 拿到该设备的 udevice 后会调用该设备的 probe 接口。
以驱动[ pwm backlight ]为例:

/**
 * drivers/video/simple_panel.c
 */
struct udevice *bldev;
uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, "backlight", &bldev);
backlight_enable(bldev);
backlight_set_brightness(bldev, percent);

x、启动分析(基于IMX6ULL)

u-boot2023:启动详细的代码调用流程
u-boot.lds:  [arch/arm/cpu/u-boot.lds]
-->_start:  [arch/arm/lib/vectors.S]
   -->reset:  [arch/arm/cpu/armv7/start.S]    
      -->save_boot_params:  [arch/arm/cpu/armv7/start.S] /*将引导参数保存到内存中*/
         -->save_boot_params_ret:   [arch/arm/cpu/armv7/start.S]
            |-->cpu_init_cp15:      [arch/arm/cpu/armv7/start.S]
            |-->cpu_init_crit:      [arch/arm/cpu/armv7/start.S]
                |-->lowlevel_init:  [arch/arm/cpu/armv7/lowlevel_init.S]
            |-->ENTRY(_main)              [arch/arm/lib/crt0.S]
                |-->board_init_f_alloc_reserve [common/init/board_init.c) /*为u-boot的gd结构体分配空间*/
                |-->board_init_f_init_reserve  [common/init/board_init.c) /*将gd结构体清零*/
                |-->board_init_f               [common/board_f.c]
                    |-->initcall_run_list      [include/initcall.h]       /*初始化序列函数*/
                        |-->init_sequence_f[]  [common/board_f.c]         /*初始化序列函数数组 */
						    |-->setup_mon_len
							|-->fdtdec_setup
							|-->initf_malloc
							|-->log_init
							|-->...
							|-->arch_cpu_init
							|-->mach_cpu_init
							|-->initf_dm
							|-->board_early_init_f
							|-->...
							|-->env_init
							|-->init_baud_rate
							|-->serial_init
							|-->console_init_f
							|-->...
							|-->dram_init
                            |-->...
                ---------------------------------------------------------------------------分界线							
                |-->relocate_code       [arch/arm/lib/relocate.S]    /*主要完成镜像拷贝和重定位*/
				---------------------------------------------------------------------------分界线
				|-->relocate_vectors                        [arch/arm/lib/relocate.S]  /*重定位向量表*/
				|-->board_init_r                            [common/board_r.c]         /*重定向后板级初始化*/
				    |-->initcall_run_list(init_sequence_r)  [include/initcall.h]       /*初始化序列函数*/
					    |-->init_sequence_r[]               [common/board_r.c]         /*初始化序列函数数组*/
						    |-->...
							|-->initr_dm					/*DM初始化*/ 
							|-->board_init                  
							|-->...
							|-->initr_dm_devices            /*DM设备初始化*/
						    |-->stdio_init_tables
							|-->serial_initialize           /*串口初始化*/
						    |-->initr_announce					      
						    |-->dm_announce                 
							|-->...	
							|-->initr_mmc                   /*MMC初始化*/
							|-->initr_env                   /*环境初始化*/
							|-->...	
							|-->interrupt_init
							|-->board_late_init
							|-->initr_net                   /*网络初始化*/
							|-->...
							|-->run_main_loop     [common/board_r.c] /* It does not return */								

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

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

相关文章

element-plus form表单组件之el-date-picker日期选择器组件

el-date-picker日期选择器组件可根据年&#xff0c;月&#xff0c;日期&#xff0c;时间范围来进行选择&#xff0c;可以自定义日期格式&#xff0c;和样式&#xff0c;还提供多种内置事件。 主要属性如下 属性名说明类型可选值默认值model-value / v-model绑定值&#xff0c…

江协科技51单片机学习- p11 Proteus安装模拟51单片机

前言&#xff1a; 本文是根据哔哩哔哩网站上“江协科技51单片机”视频的学习笔记&#xff0c;在这里会记录下江协科技51单片机开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了江协科技51单片机教学视频和链接中的内容。 引用&#xff1a; Proteus快速入门&…

想更好应对突发网络与业务问题?您需要一款“全流量”

全流量分析&#xff0c;能为我做什么&#xff1f; 在生活中遇到问题&#xff0c;我们的第一反应可能是拿出手机拍照记录&#xff0c;方便后续处理。这些问题是临时的、突发的。 流量分析&#xff0c;就是网络中的“手机”&#xff0c;针对突发的网络故障和安全事件&#xff0…

骑砍战团mod制作所需工具

骑砍战团mod制作所需工具 多去骑砍中文站&#xff0c;最底下mod制作专区那边就可以找到大部分资源 文章目录 骑砍战团mod制作所需工具编译环境骑砍源码模型工具模型素材位置骑砍mod学习位置 编译环境 python2.7下载 根据界面安装完成之后&#xff0c;然后配置系统环境&#x…

【Python机器学习】NMF——将NMF应用于人脸图像

将NMF应用于之前用过的Wild数据集中的Labeled Faces。NMF的主要参数是我们想要提取的分量个数。通常来说&#xff0c;这个数字要小于输入特征的个数&#xff08;否则的话&#xff0c;将每个像素作为单独的分量就可以对数据进行解释&#xff09;。 首先&#xff0c;观察分类个数…

pandas处理天气数据

题目分析 一、题目要求 使用Pandas读取数据&#xff1b;现有的“date”列没有包含星期信息&#xff0c;需要根据其额外生成一列“week”&#xff0c;表示星 期&#xff0c;例如“星期一”&#xff1b;将温度处理成整型&#xff0c;例如将5℃处理成5&#xff0c;注意&#xff…

DAY11-力扣刷题

1.最小路径和 给定一个包含非负整数的 m x n 网格 grid &#xff0c;请找出一条从左上角到右下角的路径&#xff0c;使得路径上的数字总和为最小。 说明&#xff1a;每次只能向下或者向右移动一步。 64. 最小路径和 - 力扣&#xff08;LeetCode&#xff09; class Solution {p…

链接脚本文件入门介绍

本文框架 1. Why<为什么需要链接文件>2.What<是什么及组成>2.1 MEMORY介绍2.2 SECTIONS介绍 3.How<链接文件应用>3.1 定义特定字段3.2 将变量定义在指定段3.3 将变量定义在不同的段3.4 将变量定义在指定地址3.5 将函数定义在指定段3.6 将函数定义在指定地址 …

在 iPhone 上恢复已删除联系人的 5 种简便方法

想象一下&#xff1a;您正在 iPhone 上滚动并搜索要拨打的联系人&#xff0c;但却找不到任何结果。然后您想起昨晚您试图删除一个名字相似的联系人&#xff0c;但不知何故删除了错误的联系人。或者您的孩子错误地删除了一些联系人。这些情况足以让您感到迷茫。但别担心&#xf…

TI毫米波雷达可以用串口调试助理来获取原始数据吗?

摘要&#xff1a;本文介绍一下如何使用普通的串口调试助理来读取到AWR1843毫米波雷达的数据的。 使用的硬件如下图所示。 软件就是普通的串口助理&#xff0c;我用的是SSCOM&#xff0c;其他串口助理也是可以的&#xff0c;核心作用其实就是发送一行行的指令而已。 操作方法&am…

如何识别商业电子邮件诈骗

复制此链接到微信打开阅读全部已发布文章 不要关闭它标签&#xff01;我知道很少有词组比商业、电子邮件和妥协更无趣。 但这不是一篇无聊的文章&#xff1a;这是一篇关于电子邮件骗子的文章&#xff0c;根据联邦调查局的说法&#xff0c;他们每年通过诈骗人们赚取 260 亿美元…

EtherCAT数据包抓取(wireshark)

目录 1、twincat配置 2、选择正确的网卡 3、过滤条件示例 (1) 过滤逻辑读的数据帧 (2) 过滤邮箱等配置数据 (3) 抓取读EtherCAT状态的数据帧 1、twincat配置 勾选 Device2->Adapter->Promiscuous Mode&#xff0c;重新激活配置。 2、选择正确的网卡 3、过滤条件示…

用含成员函数的类,分别输入和输出各对象中的时间(时:分:秒)

编写程序&#xff1a; 运行结果&#xff1a; 注意&#xff1a; &#xff08;1&#xff09;在主函数中调用两个成员函数时&#xff0c;应指明对象名(t1,t2)。表示调用的是哪一个对象的成员函数。t1.display()和t2.display()虽然都是调用同一个 display函数&#xff0c;但…

修复 pprof ---node_exproter访问漏洞(go-pprof-leak)

前言&#xff1a; ** 在Go语言中&#xff0c;pprof和debug包是用来检测和避免goroutine泄漏&#xff0c;避免导致goroutine泄漏&#xff0c;进而消耗大量系统资源。不过对于安全而言确又存在一定风险&#xff0c;** 风险&#xff1a; 通过node_exporter web发现 190.168.46.1…

【C++】————类和对象(中)

作者主页&#xff1a; 作者主页 本篇博客专栏&#xff1a;C 创作时间 &#xff1a;2024年6月22日 一、类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。空类中什么都没有吗&#xff1f;并不是的&#xff0c;任何一个类在我们不写的情 况下&#x…

道路 Road(百练,POJ)

题目链接: 1724 -- ROADS (poj.org) 题目描述: 思路: 这题目乍一看&#xff0c;是一个含有2个标尺的单源最短路问题&#xff0c;挺难处理的。 既然没法直接用最短路处理&#xff0c;那我们就“记录信息”&#xff0c;将花费的时间也记录进dp数组&#xff0c;然后跑“状态最短…

2024年【化工自动化控制仪表】考试及化工自动化控制仪表新版试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 化工自动化控制仪表考试是安全生产模拟考试一点通总题库中生成的一套化工自动化控制仪表新版试题&#xff0c;安全生产模拟考试一点通上化工自动化控制仪表作业手机同步练习。2024年【化工自动化控制仪表】考试及化工…

基于vue3 + ant-design 使用阿里图标库iconfont.cn

对于使用 iconfont.cn 的用户&#xff0c;通过设置 createFromIconfontCN 方法参数对象中的 scriptUrl 字段&#xff0c; 即可轻松地使用已有项目中的图标。 组件封装 IconFont <template><IconFont :type"iconType" /> </template><script se…

记一道MO数学练习题

手玩发现&#xff0c; 要么是行共线&#xff0c; 也就是说&#xff08;1,1&#xff09;填1之后&#xff0c;&#xff08;1,4&#xff09;要填1&#xff0c;&#xff08;1,7&#xff09;要填1&#xff0c; 事实上&#xff0c;可以给&#xff08;1&#xff0c;x&#xff09;&a…

docker搭建mongo副本集

1、mongo集群分类 MongoDB集群有4种类型&#xff0c;分别是主从复制、副本集、分片集群和混合集群。 MongoDB的主从复制是指在一个MongoDB集群中&#xff0c;一个节点&#xff08;主节点&#xff09;将数据写入并同步到其他节点&#xff08;从节点&#xff09;。主从复制提供…