52、U-boot2023的移植教程

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.mfbz.cn/a/735412.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CCS提示No XDCtools,equivalent...怎么办

摘要&#xff1a;本文介绍CCS( Version: 12.7.0.00007 )编译TI毫米波雷达遇到的No XDCtools&#xff0c;equivalent to the specified version 3.50.8.24_core,are available - defaulting to 3.62.1.16_core.问题的解决方法。 解决这个问题的方法是下载所需要的版本。上图所示…

38 - 换座位(高频 SQL 50 题基础版)

38 - 换座位 -- 方法一 select(casewhen id%21 and id(select max(id) from seat) then idwhen id%20 then id-1else id1end) as id, student fromseat order byid;-- 方法二selectif(id%20,id-1,if(id(select max(id) from Seat),id,id1)) as id,student fromSeat order by id…

1996年-2023年 全国298个地级市-外商直接投资FDI(数据收集)

外商直接投资&#xff08;FDI&#xff09;是一种跨国界的经济活动&#xff0c;它涉及外国投资者在中国境内进行的直接投资行为。这种投资行为不仅包括以货币、实物、技术等形式的资本投入&#xff0c;还可能包括开办独资企业、合资企业、合作企业&#xff0c;以及参与资源开发等…

【网络安全常用术语解读 :什么是0day、1day、nday漏洞】

脆弱性攻击的时间窗被称作脆弱性窗口。通常情况下&#xff0c;一个安全漏洞的时间越久&#xff0c;攻击者就会有更多的机会去攻击它。 2. 0day 漏洞 0天漏洞&#xff0c;也被称作"零日漏洞"&#xff0c;是指尚未由供应商公布的缺陷&#xff0c;表示攻击者已知晓该缺…

CentOS 7、Debian、Ubuntu,这些是什么意思

CentOS 7、Debian、Ubuntu 都是基于 Linux 内核的操作系统&#xff0c;它们各自有不同的特性和用途。以下是对它们的详细解释&#xff1a; CentOS 7 CentOS&#xff08;Community ENTerprise Operating System&#xff09; 是一个基于开源的 Linux 发行版。CentOS 7 是 CentOS …

摄像头画面显示于unity场景

&#x1f43e; 个人主页 &#x1f43e; &#x1faa7;阿松爱睡觉&#xff0c;横竖醒不来 &#x1f3c5;你可以不屠龙&#xff0c;但不能不磨剑&#x1f5e1; 目录 一、前言二、UI画面三、显示于场景四、结语 一、前言 由于标题限制&#xff0c;这篇文章主要是讲在unity中调用摄…

基于JSP的教学质量评价系统

开头语&#xff1a; 你好&#xff0c;我是计算机学长猫哥。如果您对教学质量评价系统感兴趣或有相关需求&#xff0c;欢迎随时联系我。 开发语言&#xff1a; Java 数据库&#xff1a; MySQL 技术&#xff1a; JSP技术 Java语言 工具&#xff1a; MyEclipse、Tomcat服…

华为Mate 70系列,将首发搭载纯血鸿蒙正式版,第四季度登场

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 更多资源欢迎关注 6月22日消息&#xff0c;华为在HDC 2024上已经宣布&#xff0c;HarmonyOS NEXT开启开发者先锋用户Beta测试。 首批覆盖Mate 60系列、Mate X5系列、MatePad Pro 13.2英寸。 根据官方公布的时间表&…

oracle发送https请求

参照 https://docs.oracle.com/cd/E11882_01/appdev.112/e40758/u_http.htm#i1025869 https://docs.oracle.com/cd/E11882_01/network.112/e40393/asowalet.htm#ASOAG160 https://docs.oracle.com/cd/E11882_01/appdev.112/e40758/d_networkacl_adm.htm#ARPLS148 https://d…

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

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

OneNote for Windows 10 下载

OneNote for Windows 10 安装 1.在浏览器中输入地址&#xff1a;https://apps.microsoft.com/detail/9wzdncrfhvjl?hlzh-cn&glUS2OneNote for Windows 10 - 在 Windows 上免费下载并安装 |Microsoft StoreOneNote 是用于在设备上捕获和组织你的一切内容的数字笔记本。快速…

打破数据分析壁垒:SPSS复习必备(六)

一、数据的报表呈现 1.报表概述 (1).SPSS中的报表功能 1&#xff09;Base 模块 2&#xff09;Custom Tables 模块 3) Original Tables 模块 (2).报表的基本绘制步骤 步骤一:确定基本结构 步骤二:使用对话框绘制表格的基本结构 步骤三:完善细节 步骤四:添加其余变…

java课程设计GUI学生信息管理系统

目录 系统内容.. 3 用户界面模块... 4 数据存储模块... 4 信息管理模块... 4 管理模块.. 4 主要模块的算法描述... 4 –简要的语言描述... 4 运行及调试分析&#xff08;测试数据及测试结果&#xff09;.. 5 课程设计总结... 7 参考文献&#xff08;至少三个&#xf…

基于CSDN的Markdown文本编辑器的博客界面优化 | HTML | 文本标签 | 图像标签 | 个人主页引导

&#x1f64b;大家好&#xff01;我是毛毛张! &#x1f308;个人首页&#xff1a; 神马都会亿点点的毛毛张 今天毛毛张分享的内容是如何在CSDN的Markdown编辑器中实现上图的效果&#xff0c;如果觉得能帮助到你的话就点击个人主页点点关注吧❗ 文章目录 1.前言2.基础知识3.字…

Sword and Shield Animations(劈砍防御剑盾带动画动作)

这是一个动画资产包,为剑和盾牌用户提供手工制作的成对动画和空闲。包括8向步行和跑步动画、攻击、跳跃、冲刺、向下状态移动和过渡、躲避、阻挡、蹒跚、各种配对终结者动画等。 一切你需要把剑和盾牌战士带到生活中。 动画总数:115 攻击19 区块5 关闭状态14 Evade 5 怠速9 跳…

Sequelize入门及简单的增删改查

前言 学习一下NodeJS怎么使用Sequelize怎么查询数据库数据 一、Sequelize是什么&#xff1f; Sequelize 是一个基于 promise 的 Node.js ORM, 二、搭建项目 1.安装过程 npm i -g sequelize-cli //全局安装sequelize-clinpm i sequelize mysql2 //安装sequelize和mysql2…

AI视频教程下载-与ChatGPT结合的UX用户体验/UI用户界面设计策略

Revolutionize UX_UI_ AI-Design Strategies with ChatGPT 提升你的设计工具包&#xff1a;使用ChatGPT、Figma和Miro的AI驱动UX/UI策略 50个创新UX提示 了解人工智能的基础知识。介绍ChatGPT及其底层技术。区分不同AI模型及其在设计中的应用。将AI工具融入设计工作流程的策略…

【Java基础】

Java基础常见面试题总结(上) 基础概念与常识 Java 语言有哪些特点? 简单易学&#xff08;语法简单&#xff0c;上手容易&#xff09;&#xff1b;面向对象&#xff08;封装&#xff0c;继承&#xff0c;多态&#xff09;&#xff1b;平台无关性&#xff08; Java 虚拟机实现…

JAVA期末复习2

目录 一、Java基础知识 1. 下面几个标识符中&#xff0c;哪些是命名正确的 (A) 2. 分析以下代码&#xff0c;哪些是合法的 (C) 3. 以下代码的执行结果是&#xff08; B &#xff09; 4. 下面哪个不是java中的关键字&#xff1f;&#xff08; B &#xff09; 5. 下面对数组…

Javase.图书管理系统基本框架

图书管理系统基本框架 1.核心类介绍2. book包详解2.1 Book 类2.1.2 代码展示2.1.2 代码解析 2.2 BookList 类2.2.2 代码展示2.2.2 代码解析 2.3Book类和BookList类的联系 3. 用户角色与管理3.1 User 类3.1.1 代码展示3.1.2 代码解析 3.2 adminUser 类3.2.1 代码展示3.2.2代码解…