当前位置: 首页 > news >正文

bootloaders

什么是BootLoader?

一般来说,bootloader是一种软件/固件,它在SoC上电后立即运行。bootloader的主要职责是启动软件的后续部分,例如操作系统、baremetal应用程序或在某些情况下另一个bootloader。当涉及到嵌入式时,bootloader通常与底层SoC体系结构密切相关。bootloader通常存储在一个受保护的、非易失性的片上存储器中。通常bootloader执行各种硬件检查,初始化处理器和配置SoC寄存器等。由于bootloader的主要目的是加载下一个软件,因此它需要与外部通信以接收此固件/应用程序映像。这可以通过许多协议- USB, UART, SPI, I2C,外部闪存,内部闪存,SD卡,以太网,can等。bootloader也是嵌入式安全性中的一个关键组件。硬件信任根通常被传递到bootloader,并沿着线路传递。

在MCU+SDK支持的设备中,第一bootloader被刻录到设备的只读存储器中,被认为是设备固件/ ROM。在MCU+SDK中,所说的“bootloader”大多指的是二级bootloader,或SBL。

Multi-Stage Bootloader

出于安全考虑,第一个bootloader通常保存在安全的只读内存中,并且在应用程序软件启动之前总是有一个已知的状态。因此,保持这个bootloader的简单性并让它只执行所需的最低配置是有意义的。这个辅助引导加载程序可以很复杂,也可以进行配置,以满足应用程序的需要。与第一阶段bootloader相比,这也可以很容易地更新。事实上,对于MCU+SDK中的设备,我们有两个阶段的引导加载程序——第一个阶段的bootloader称为ROM bootloader (RBL),第二个阶段的bootloader称为Secondary bootloader (SBL)。

Multi-Core BootLoading

当有多阶段引导加载时,多核引导加载几乎总是一个后续。在这种情况下,第一个bootloader技术上可能甚至不知道其他核心,它只会引导下一个阶段的bootloader,而第二个阶段的bootloader将负责不同核心上的复杂引导加载
加载多核应用程序比加载单核应用程序稍微复杂一些。在映像准备、共享内存访问等方面存在一些问题。大多数情况下,会有一种特定的格式来创建各个核心图像,然后它们可能会/可能不会被连接到单个图像中供SBL加载。无论应用程序图像的格式是什么,SBL都应该知道它,以便正确地解析和加载图像。

Hit any key to stop autoboot:  0
=> mmc list
mmc@fa10000: 0
mmc@fa00000: 1 (SD)
=> printenv partitions
partitions=name=rootfs,start=0,size=-,uuid=${uuid_gpt_rootfs}
=> uuidgen
Unknown command 'uuidgen' - try 'help'
=> uuidgen -try
Unknown command 'uuidgen' - try 'help'
=> mmc partPartition Map for MMC device 0  --   Partition Type: DOSPart    Start Sector    Num Sectors     UUID            Type1     1               522240          f9b70d9c-01     0c Boot2     522241          4700160         f9b70d9c-02     83
=>
=> mmc dev
switch to partitions #0, OK
mmc0(part 0) is current device
=> mmc list
mmc@fa10000: 0 (eMMC)
mmc@fa00000: 1 (SD)
=> mmc dev
switch to partitions #0, OK
mmc0(part 0) is current device
=> mmc read
mmc - MMC sub systemUsage:
mmc info - display info of the current MMC device
mmc read addr blk# cnt
mmc write addr blk# cnt
mmc erase blk# cnt
mmc rescan [mode]
mmc part - lists available partition on current mmc device
mmc dev [dev] [part] [mode] - show or set current mmc device [partition] and set mode- the required speed mode is passed as the index from the following list[MMC_LEGACY, MMC_HS, SD_HS, MMC_HS_52, MMC_DDR_52, UHS_SDR12, UHS_SDR25,UHS_SDR50, UHS_DDR50, UHS_SDR104, MMC_HS_200, MMC_HS_400, MMC_HS_400_ES]
mmc list - lists available devices
mmc wp - power on write protect boot partitions
mmc hwpartition [args...] - does hardware partitioningarguments (sizes in 512-byte blocks):[user [enh start cnt] [wrrel {on|off}]] - sets user data area attributes[gp1|gp2|gp3|gp4 cnt [enh] [wrrel {on|off}]] - general purpose partition[check|set|complete] - mode, complete set partitioning completedWARNING: Partitioning is a write-once setting once it is set to complete.Power cycling is required to initialize partitions after set to complete.
mmc bootbus dev boot_bus_width reset_boot_bus_width boot_mode- Set the BOOT_BUS_WIDTH field of the specified device
mmc bootpart-resize <dev> <boot part size MB> <RPMB part size MB>- Change sizes of boot and RPMB partitions of specified device
mmc partconf dev [boot_ack boot_partition partition_access]- Show or change the bits of the PARTITION_CONFIG field of the specified device
mmc rst-function dev value- Change the RST_n_FUNCTION field of the specified deviceWARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.
mmc setdsr <value> - set DSR register value=> printenv
addr_fit=0x90000000
arch=arm
args_all=setenv optargs ${optargs} earlycon=ns16550a,mmio32,0x02800000 ${mtdparts}
args_mmc=run finduuid;setenv bootargs console=${console} ${optargs} root=PARTUUID=${uuid} rw rootfstype=${mmcrootfstype}
args_nand=setenv bootargs console=${console} ${optargs} ubi.mtd=${nbootpart} root=${nbootvolume} rootfstype=ubifs
args_usb=run finduuid;setenv bootargs console=${console} ${optargs} root=PARTUUID=${uuid} rw rootfstype=${mmcrootfstype}
baudrate=115200
board=am64x
board_name=am64x_gpevm
board_rev=A
board_serial=0230
board_software_revision=01
boot=mmc
boot_fdt=try
boot_fit=0
bootcmd=run findfdt; run envboot; run init_${boot}; if test ${boot_fit} -eq 1; then run get_fit_${boot}; run get_overlaystring; run run_fit; else; run get_kern_${boot}; run get_fdt_${boot}; run get_overlay_${boot}; run run_kern; fi;
bootdelay=2
bootdir=/boot
bootenvfile=uEnv.txt
bootm_size=0x10000000
bootpart=1:2
bootscript=echo Running bootscript from mmc${mmcdev} ...; source ${loadaddr}
console=ttyS2,115200n8
cpu=armv8
dfu_alt_info_emmc=rawemmc raw 0 0x800000 mmcpart 1;rootfs part 0 1 mmcpart 0;tiboot3.bin.raw raw 0x0 0x800 mmcpart 1;tispl.bin.raw raw 0x800 0x1000 mmcpart 1;u-boot.img.raw raw 0x1800 0x2000 mmcpart 1;u-env.raw raw 0x3800 0x100 mmcpart 1
dfu_alt_info_mmc=boot part 1 1;rootfs part 1 2;tiboot3.bin fat 1 1;tispl.bin fat 1 1;u-boot.img fat 1 1;uEnv.txt fat 1 1;sysfw.itb fat 1 1
dfu_alt_info_ospi=tiboot3.bin raw 0x0 0x100000;tispl.bin raw 0x100000 0x200000;u-boot.img raw 0x300000 0x400000;u-boot-env raw 0x700000 0x020000;rootfs raw 0x800000 0x3800000
dfu_alt_info_ram=tispl.bin ram 0x80080000 0x200000;u-boot.img ram 0x81000000 0x400000
dtboaddr=0x89000000
envboot=mmc dev ${mmcdev}; if mmc rescan; then echo SD/MMC found on device ${mmcdev};if run loadbootscript; then run bootscript;else if run loadbootenv; then echo Loaded env from ${bootenvfile};run importbootenv;fi;if test -n $uenvcmd; then echo Running uenvcmd ...;run uenvcmd;fi;fi;fi;
eth1addr=70:ff:76:1e:28:b8
eth2addr=70:ff:76:1e:28:b9
ethaddr=f4:84:4c:f9:7d:05
fdt_addr_r=0x88000000
fdtaddr=0x88000000
fdtcontroladdr=edeb7880
fdtoverlay_addr_r=0x80200000
findfdt=if test $board_name = am64x_gpevm; then setenv fdtfile k3-am642-evm.dtb; fi; if test $board_name = am64x_skevm; then setenv fdtfile k3-am642-sk.dtb; fi;if test $fdtfile = undefined; then echo WARNING: Could not determine device tree to use; fi;
finduuid=part uuid ${boot} ${bootpart} uuid
get_fdt_mmc=load mmc ${bootpart} ${fdtaddr} ${bootdir}/${fdtfile}
get_fdt_nand=ubifsload ${fdtaddr} ${bootdir}/${fdtfile};
get_fdt_usb=load usb ${bootpart} ${fdtaddr} ${bootdir}/${fdtfile}
get_fit_mmc=load mmc ${bootpart} ${addr_fit} ${bootdir}/${name_fit}
get_fit_nand=ubifsload ${addr_fit} ${bootdir}/${name_fit}
get_fit_usb=load usb ${bootpart} ${addr_fit} ${bootdir}/${name_fit}
get_kern_mmc=load mmc ${bootpart} ${loadaddr} ${bootdir}/${name_kern}
get_kern_nand=ubifsload ${loadaddr} ${bootdir}/${name_kern}
get_kern_usb=load usb ${bootpart} ${loadaddr} ${bootdir}/${name_kern}
get_overlay_mmc=fdt address ${fdtaddr};fdt resize 0x100000;for overlay in $name_overlays;do;load mmc ${bootpart} ${dtboaddr} ${bootdir}/${overlay} && fdt apply ${dtboaddr};done;
get_overlay_nand=fdt address ${fdtaddr};fdt resize 0x100000;for overlay in $name_overlays;do;ubifsload ${dtboaddr} ${bootdir}/${overlay} && fdt apply ${dtboaddr};done;
get_overlay_usb=fdt address ${fdtaddr};fdt resize 0x100000;for overlay in $name_overlays;do;load usb ${bootpart} ${dtboaddr} ${bootdir}/${overlay} && fdt apply ${dtboaddr};done;
get_overlaystring=for overlay in $name_overlays;do;setenv overlaystring ${overlaystring}'#'${overlay};done;
importbootenv=echo Importing environment from mmc${mmcdev} ...; env import -t ${loadaddr} ${filesize}
init_mmc=run args_all args_mmc
init_nand=run args_all args_nand ubi_init
init_usb=run args_all args_usb
kernel_addr_r=0x82000000
loadaddr=0x82000000
loadbootenv=fatload mmc ${mmcdev} ${loadaddr} ${bootenvfile}
loadbootscript=load mmc ${mmcdev} ${loadaddr} boot.scr
loadfdt=load ${devtype} ${bootpart} ${fdtaddr} ${bootdir}/${fdtfile}
loadimage=load ${devtype} ${bootpart} ${loadaddr} ${bootdir}/${bootfile}
mmcboot=mmc dev ${mmcdev}; devnum=${mmcdev}; devtype=mmc; if mmc rescan; then echo SD/MMC found on device ${mmcdev};if run loadimage; then run args_mmc; if test ${boot_fit} -eq 1; then run run_fit; else run mmcloados;fi;fi;fi;
mmcdev=1
mmcloados=if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if run loadfdt; then bootz ${loadaddr} - ${fdtaddr}; else if test ${boot_fdt} = try; then bootz; else echo WARN: Cannot load the DT; fi; fi; else bootz; fi;
mmcrootfstype=ext4 rootwait
mtdids=nor0=fc40000.spi.0,nand0=omap2-nand.0
mtdparts=mtdparts=fc40000.spi.0:1m(ospi.tiboot3),2m(ospi.tispl),4m(ospi.u-boot),256k(ospi.env),256k(ospi.env.backup),57088k@8m(ospi.rootfs),256k(ospi.phypattern);omap2-nand.0:2m(NAND.tiboot3),2m(NAND.tispl),2m(NAND.tiboot3.backup),4m(NAND.u-boot),256k(NAND.u-boot-env),256k(NAND.u-boot-env.backup),-(NAND.file-system)
name_fit=fitImage
name_kern=Image
nbootpart=NAND.file-system
nbootvolume=ubi0:rootfs
partitions=name=rootfs,start=0,size=-,uuid=${uuid_gpt_rootfs}
pxefile_addr_r=0x80100000
ramdisk_addr_r=0x88080000
rd_spec=-
rdaddr=0x88080000
run_fit=bootm ${addr_fit}#${fdtfile}${overlaystring}
run_kern=booti ${loadaddr} ${rd_spec} ${fdtaddr}
scriptaddr=0x80000000
serial#=0000000000000230
soc=k3
stderr=serial@2800000
stdin=serial@2800000
stdout=serial@2800000
ubi_init=ubi part ${nbootpart}; ubifsmount ${nbootvolume};
update_to_fit=setenv loadaddr ${addr_fit}; setenv bootfile ${name_fit}
usbboot=setenv boot usb;setenv bootpart 0:2;usb start;run findfdt;run init_usb;run get_kern_usb;run get_fdt_usb;run run_kern
vendor=tiEnvironment size: 5742/131068 bytes

错误记录:以下流程并不能成功的从eMMC启动,分区存在问题,应按照Flash Linux to eMMc进行

root@am64xx-evm:~# uuidgen
b8988730-0989-4d66-9951-175b5874a726
root@am64xx-evm:~# uuidgen
7d70f57d-5c14-4264-a117-354ab179f85a

Partitioning eMMC from U-Boot

=> printenv partitions
partitions=name=rootfs,start=0,size=-,uuid=${uuid_gpt_rootfs}
=> setenv uuid_gpt_disk b8988730-0989-4d66-9951-175b5874a726
=> setenv uuid_gpt_disk 7d70f57d-5c14-4264-a117-354ab179f85a
=> mmc list
mmc@fa10000: 0
mmc@fa00000: 1 (SD)=> gpt write mmc 0 ${partitions}
Writing GPT: success!=> mmc partPartition Map for MMC device 0  --   Partition Type: EFIPart    Start LBA       End LBA         NameAttributesType GUIDPartition GUID1     0x00000022      0x01da3fde      "rootfs"attrs:  0x0000000000000000type:   ebd0a0a2-b9e5-4433-87c0-68b6b72699c7guid:   76a96b6e-570c-2344-96f9-059fa509c224
=> setenv uuid_gpt_disk b8988730-0989-4d66-9951-175b5874a726
=> setenv uuid_gpt_rootfs 7d70f57d-5c14-4264-a117-354ab179f85a
=> gpt write mmc 0 ${partitions}
Writing GPT: success!
=> mmc partPartition Map for MMC device 0  --   Partition Type: EFIPart    Start LBA       End LBA         NameAttributesType GUIDPartition GUID1     0x00000022      0x01da3fde      "rootfs"attrs:  0x0000000000000000type:   ebd0a0a2-b9e5-4433-87c0-68b6b72699c7guid:   7d70f57d-5c14-4264-a117-354ab179f85a
=> printenv dfu_alt_info_mmc
dfu_alt_info_mmc=boot part 1 1;rootfs part 1 2;tiboot3.bin fat 1 1;tispl.bin fat 1 1;u-boot.img fat 1 1;uEnv.txt fat 1 1;sysfw.itb fat 1 1
=> mmc dev 0
switch to partitions #0, OK
mmc0(part 0) is current device
=> printenv dfu_alt_info_mmc
dfu_alt_info_mmc=boot part 1 1;rootfs part 1 2;tiboot3.bin fat 1 1;tispl.bin fat 1 1;u-boot.img fat 1 1;uEnv.txt fat 1 1;sysfw.itb fat 1 1
=> mmc dev 1
switch to partitions #0, OK
mmc1 is current device
=> printenv dfu_alt_info_mmc
dfu_alt_info_mmc=boot part 1 1;rootfs part 1 2;tiboot3.bin fat 1 1;tispl.bin fat 1 1;u-boot.img fat 1 1;uEnv.txt fat 1 1;sysfw.itb fat 1 1
=> setenv dfu_alt_info ${dfu_alt_info_mmc}
=> dfu 0 mmc 0
Couldn't find part #2 on mmc device #1
DFU entities configuration failed!
(partition table does not match dfu_alt_info?)
dfu - Device Firmware UpgradeUsage:
dfu <USB_controller> [<interface> <dev>] [list]- device firmware upgrade via <USB_controller>on device <dev>, attached to interface<interface>[list] - list available alt settings=> mmc dev 0
switch to partitions #0, OK
mmc0(part 0) is current device
=> setenv dfu_alt_info ${dfu_alt_info_mmc}
=> dfu 0 mmc 0
Couldn't find part #2 on mmc device #1
DFU entities configuration failed!
(partition table does not match dfu_alt_info?)
dfu - Device Firmware UpgradeUsage:
dfu <USB_controller> [<interface> <dev>] [list]- device firmware upgrade via <USB_controller>on device <dev>, attached to interface<interface>[list] - list available alt settings=> mmc dev 0 1
switch to partitions #1, OK
mmc0(part 1) is current device
=> fatload mmc 1 ${loadaddr} tispl.bin
855435 bytes read in 37 ms (22 MiB/s)
=> mmc write ${loadaddr} 0x0 0x800MMC write: dev # 0, block # 0, count 2048 ... 2048 blocks written: OK
=> fatload mmc 1 ${loadaddr} tiboot3.bin
563594 bytes read in 25 ms (21.5 MiB/s)
=> mmc write ${loadaddr} 0x0 0x800MMC write: dev # 0, block # 0, count 2048 ... 2048 blocks written: OK
=> fatload mmc 1 ${loadaddr} tispl.bin
855435 bytes read in 37 ms (22 MiB/s)
=> mmc write ${loadaddr} 0x800 0x1000MMC write: dev # 0, block # 2048, count 4096 ... 4096 blocks written: OK
=> fatload mmc 1 ${loadaddr} u-boot.img
1119679 bytes read in 49 ms (21.8 MiB/s)
=> mmc write ${loadaddr} 0x1800 0x2000MMC write: dev # 0, block # 6144, count 8192 ... 8192 blocks written: OK
=> mmc partPartition Map for MMC device 0  --   Partition Type: EFIGUID Partition Table Header signature is wrong: 0x32472641DEEE9E91 != 0x5452415020494645
find_valid_gpt: *** ERROR: Invalid GPT ***
GUID Partition Table Header signature is wrong: 0x0 != 0x5452415020494645
find_valid_gpt: *** ERROR: Invalid Backup GPT ***
=> mmc partconf 0 1 1 1
=> mmc bootbus 0 2 0 0
=> mmc partPartition Map for MMC device 0  --   Partition Type: EFIGUID Partition Table Header signature is wrong: 0x32472641DEEE9E91 != 0x5452415020494645
find_valid_gpt: *** ERROR: Invalid GPT ***
GUID Partition Table Header signature is wrong: 0x0 != 0x5452415020494645
find_valid_gpt: *** ERROR: Invalid Backup GPT ***
=> mmc info
Device: mmc@fa10000
Manufacturer ID: 13
OEM: 14e
Name: S0J56
Bus Speed: 200000000
Mode: HS400 (200MHz)
Rd Block Len: 512
MMC version 5.1
High Capacity: Yes
Capacity: 14.8 GiB
Bus Width: 8-bit DDR
Erase Group Size: 512 KiB
HC WP Group Size: 8 MiB
User Capacity: 14.8 GiB WRREL
Boot Capacity: 31.5 MiB ENH
RPMB Capacity: 4 MiB ENH
Boot area 0 is not write protected
Boot area 1 is not write protected
=> mmc list
mmc@fa10000: 0 (eMMC)
mmc@fa00000: 1 (SD)
=> mmc dev 1
switch to partitions #0, OK
mmc1 is current device
=> mmc info
Device: mmc@fa00000
Manufacturer ID: 3
OEM: 5344
Name: SB16G
Bus Speed: 50000000
Mode: SD High Speed (50MHz)
Rd Block Len: 512
SD version 3.0
High Capacity: Yes
Capacity: 14.8 GiB
Bus Width: 4-bit
Erase Group Size: 512 Bytes// fatinfo 命令用于查询指定 MMC 设置指定分区的文件系统信息,格式如下:
=> fatinfo mmc 1:1
Interface:  MMCDevice 1: Vendor: Man 000003 Snr 4e29fe01 Rev: 10.4 Prod: SB16G▒Type: Removable Hard DiskCapacity: 15193.5 MB = 14.8 GB (31116288 x 512)
Filesystem: FAT16 "boot       "// fatls 命令用于查询 FAT 格式设备的目录和文件信息,命令格式如下
=> fatls mmc 1:11490   uEnv.txt318   wificfgSystem Volume Information/131072   uboot.env1   .psdk_setup563594   tiboot3.bin855435   tispl.bin1119679   u-boot.img7 file(s), 1 dir(s)//fstype 用于查看 MMC 设备某个分区的文件系统格式,命令格式如下:
=> fstype mmc 1:1
fat
=> fstype mmc 1:2
ext4
=>  mmc partPartition Map for MMC device 0  --   Partition Type: EFIPart    Start LBA       End LBA         NameAttributesType GUIDPartition GUID1     0x00000022      0x01da3fde      "rootfs"attrs:  0x0000000000000000type:   ebd0a0a2-b9e5-4433-87c0-68b6b72699c7guid:   7d70f57d-5c14-4264-a117-354ab179f85a
=> mmc dev 1
switch to partitions #0, OK
mmc1 is current device
=>  mmc partPartition Map for MMC device 1  --   Partition Type: DOSPart    Start Sector    Num Sectors     UUID            Type1     2048            275610          ade9031b-01     0c Boot2     278528          5151216         ade9031b-02     83
=> mmc dev 0
switch to partitions #0, OK
mmc0(part 0) is current device
=>  mmc partPartition Map for MMC device 0  --   Partition Type: EFIPart    Start LBA       End LBA         NameAttributesType GUIDPartition GUID1     0x00000022      0x01da3fde      "rootfs"attrs:  0x0000000000000000type:   ebd0a0a2-b9e5-4433-87c0-68b6b72699c7guid:   7d70f57d-5c14-4264-a117-354ab179f85a
=> printenv dfu_alt_info_mmc
dfu_alt_info_mmc=boot part 1 1;rootfs part 1 2;tiboot3.bin fat 1 1;tispl.bin fat 1 1;u-boot.img fat 1 1;uEnv.txt fat 1 1;sysfw.itb fat 1 1
=> mmc dev 1
switch to partitions #0, OK
mmc1 is current device
=> printenv dfu_alt_info_mmc
dfu_alt_info_mmc=boot part 1 1;rootfs part 1 2;tiboot3.bin fat 1 1;tispl.bin fat 1 1;u-boot.img fat 1 1;uEnv.txt fat 1 1;sysfw.itb fat 1 1
=> mmc dev 01
switch to partitions #0, OK
mmc1 is current device
=> mmc dev 0 1
switch to partitions #1, OK
mmc0(part 1) is current device
=> fatload mmc 1 ${loadaddr} tiboot3.bin
563594 bytes read in 26 ms (20.7 MiB/s)
=> mmc write ${loadaddr} 0x0 0x800MMC write: dev # 0, block # 0, count 2048 ... 2048 blocks written: OK
=> fatload mmc 1 ${loadaddr} tispl.bin
855435 bytes read in 37 ms (22 MiB/s)
=> mmc write ${loadaddr} 0x800 0x1000MMC write: dev # 0, block # 2048, count 4096 ... 4096 blocks written: OK
=> fatload mmc 1 ${loadaddr} u-boot.img
1119679 bytes read in 49 ms (21.8 MiB/s)
=> mmc write ${loadaddr} 0x1800 0x2000MMC write: dev # 0, block # 6144, count 8192 ... 8192 blocks written: OK
=> mmc partconf 0 1 1 1
=> mmc bootbus 0 2 0 0
=> saveenv
Saving Environment to FAT... OK
=> setenv mmcdev 0
=> setenv bootpart 0
=> saveenv
Saving Environment to FAT... OK
=> mmc partPartition Map for MMC device 0  --   Partition Type: EFIGUID Partition Table Header signature is wrong: 0x32472641DEEE9E91 != 0x5452415020494645
find_valid_gpt: *** ERROR: Invalid GPT ***
GUID Partition Table Header signature is wrong: 0x0 != 0x5452415020494645
find_valid_gpt: *** ERROR: Invalid Backup GPT ***=> boot
switch to partitions #0, OK
mmc0(part 0) is current device
SD/MMC found on device 0
** Unrecognized filesystem type **
** Unrecognized filesystem type **
** Unrecognized filesystem type **
** Unrecognized filesystem type **
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
No FDT memory address configured. Please configure
the FDT address via "fdt addr <address>" command.
Aborting!
Bad Linux ARM64 Image magic!

相关文章:

bootloaders

什么是BootLoader? 一般来说&#xff0c;bootloader是一种软件/固件&#xff0c;它在SoC上电后立即运行。bootloader的主要职责是启动软件的后续部分&#xff0c;例如操作系统、baremetal应用程序或在某些情况下另一个bootloader。当涉及到嵌入式时&#xff0c;bootloader通常…...

PC或服务器装双系统

1. 准备工作 1.1U盘启动盘的制作 ①准备一个 4G 以上的 U 盘&#xff0c;备份好U盘资料&#xff0c;后面会对 U 盘进行格式化。 ②去CentOS官网下载你想要安装的 ISO 格式镜像文件&#xff0c;现在通常是CentOS6、7或者8。如果你英文不太好&#xff0c;可以选择使用edge浏览…...

嵌入式代码查看分析利器---Understand

平时在开发嵌入式程序的时候大多数使用的都是keil软件&#xff0c;一般小的工程使用keil没感觉到有什么问题&#xff0c;但是当工程比较大的时候&#xff0c;比如移植了FreeRTOS系统或者LWIP网络系统时&#xff0c;代码全部编译一次就要花费很长世间&#xff0c;特别是开启了点…...

人群计数经典方法Density Map Estimation,密度图估计

&#xff08;3&#xff09;Density Map Estimation&#xff08;主流&#xff09; 这是crowd counting的主流方法 传统方法不好在哪里&#xff1f;object detection-based method和regression-based method无法从图像中提取更抽象的有助于完成人群计数任务的语义特征 概况&…...

【华为】Smart-Link基础知识

Smark-Link技术 Smark-Link(灵活链路or备份链路&#xff0c;华为/华三 私有用) Smark-Link定义 Smark-Link&#xff0c;又叫备份链路。一个Smark Link由两个接口组组成&#xff0c;其中一个接口作为另一个的备份。Smark-Link常用于双上行组网&#xff0c;提供可靠高效的备份与…...

分享24个强大的HTML属性 —— 建议每位前端工程师都应该掌握

前期回顾 是不是在为 API 烦恼 &#xff1f;好用免费的api接口大全呼之欲出_0.活在风浪里的博客-CSDN博客APi、常用框架、UI、文档—— 整理合并https://blog.csdn.net/m0_57904695/article/details/130459417?spm1001.2014.3001.5501 &#x1f44d; 本文专栏&#xff1a;…...

NIO基础 - 网络编程

non-blocking io 非阻塞 IO 1. 三大组件 1.1 Channel & Buffer channel 有一点类似于 stream&#xff0c;它就是读写数据的双向通道&#xff0c;可以从 channel 将数据读入 buffer&#xff0c;也可以将 buffer 的数据写入 channel&#xff0c;而之前的 stream 要么是输入…...

06.toRef 和 toRefs

学习要点&#xff1a; 1.toRef 和 toRefs 本节课我们来要了解一下 Vue3.x 中的 ref 两个周边 API 的用法&#xff1b; 一&#xff0e;toRef 和 toRefs 1. toRef 可以将源响应式对象上的 property 创建一个 ref 对象&#xff1b; const obj reactive({ name : Mr.Lee, age : 10…...

RabbitMq、Kafka、RocketMq整理

MQ的主要作用:异步提高性能、解耦提高扩展性、削峰。 一、常见中间件对比 Kafka、RocketMq和RabbitMq最大的区别就是:前两个是分布式存储。 1.1、ActiveMq 优点:1)完全支持jms规范的消息中间件 ,2)提供丰富的api, 3)多种集群构建模式。 缺点:)在高并发的场景下,性能可…...

Python多元线性回归预测模型实验完整版

多元线性回归预测模型 实验目的 通过多元线性回归预测模型&#xff0c;掌握预测模型的建立和应用方法&#xff0c;了解线性回归模型的基本原理 实验内容 多元线性回归预测模型 实验步骤和过程 (1)第一步&#xff1a;学习多元线性回归预测模型相关知识。 一元线性回归模型…...

C#基础 变量在内存中的存储空间

变量存储空间&#xff08;内存中&#xff09; // 1byte 8bit // 1KB 1024byte // 1MB 1024KB // 1GB 1024MB // 1TB 1024GB // 通过sizeof方法 可以获取变量类型所占的内存空间&#xff08;单位&#xff1a;字节&#xff09; 有…...

你最关心的4个零代码问题,ChatGPT 帮你解答了!

作为人工智能&#xff08;AI&#xff09;新型聊天机器人模型 ChatGPT&#xff0c;刚上线5天就突破100万用户&#xff0c;两个多月全球用户量破亿&#xff0c;不愧为业界最炙热的当红炸子鸡。 ChatGPT 是一种语言生成模型&#xff0c;由 OpenAI 开发和训练。它是基于 Transform…...

linux的环境变量

目录 一、自定义变量和环境变量的区别 二、自定义变量 三、环境变量 四、查看所有变量&#xff08;自定义变量、环境变量&#xff09; 五、记录环境变量到相关的系统文件 &#xff08;1&#xff09;为什么要这样做&#xff1f; &#xff08;2&#xff09;环境变量相关系统…...

openQA----基于openSUSE部署openQA

【原文链接】openQA----基于openSUSE部署openQA &#xff08;1&#xff09;下载 openqa-bootstrap 脚本并执行 cd /opt/ curl -s https://raw.githubusercontent.com/os-autoinst/openQA/master/script/openqa-bootstrap | bash -x&#xff08;2&#xff09;配置apache proxy…...

正则表达式基础一

BRE(basic regular expression)&#xff1a;匹配数据流中的文本字符 普通文本匹配 特殊字符 正则表达式存在一些特殊字符&#xff0c;如需当成普通文本来匹配&#xff0c;必须加上转义&#xff0c;即反斜杠\&#xff0c;如下所示 .*[]^${}?|() 指定出现位置的字符 ^ 指定行首…...

Java中的内存泄露、内存溢出与栈溢出

内存泄露、内存溢出与栈溢出 1、概述2、内存泄漏、内存溢出和栈溢出2.1、内存泄漏2.2、内存溢出2.3、栈溢出 2、总结 1、概述 大家好&#xff0c;我是欧阳方超。本次就Java中几个相似而又不同的概念做一下介绍。内存泄漏、内存溢出和栈溢出都是与内存相关的问题&#xff0c;但…...

时序预测 | Matlab实现SSA-GRU、GRU麻雀算法优化门控循环单元时间序列预测(含优化前后对比)

时序预测 | Matlab实现SSA-GRU、GRU麻雀算法优化门控循环单元时间序列预测(含优化前后对比) 目录 时序预测 | Matlab实现SSA-GRU、GRU麻雀算法优化门控循环单元时间序列预测(含优化前后对比)预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab实现SSA-GRU、GRU麻雀算法…...

Java+springboot开发的医院HIS信息管理系统实现,系统部署于云端,支持多租户SaaS模式

一、项目技术框架 前端&#xff1a;AngularNginx 后台&#xff1a;JavaSpring&#xff0c;SpringBoot&#xff0c;SpringMVC&#xff0c;SpringSecurity&#xff0c;MyBatisPlus&#xff0c;等 数据库&#xff1a;MySQL MyCat 缓存&#xff1a;RedisJ2Cache 消息队列&…...

【前端面经】Vue-Vue中的 $nextTick 有什么作用?

Vue.js 是一个流行的 JavaScript 框架&#xff0c;它提供了许多实用的功能&#xff0c;其中之一就是 $nextTick 方法。 在 Vue.js 中&#xff0c; $nextTick 方法可以确保我们在更新 DOM 之后再去执行某些操作&#xff0c;从而避免由于 DOM 更新而导致的问题。这个方法非常实用…...

基于STATCOM的风力发电机稳定性问题仿真分析(Simulink)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

Vue ③-生命周期 || 脚手架

生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09; 什么时候可以开始操作dom&#xff1f;&#xff08;至少dom得渲染出来&#xff09; Vue生命周期&#xff1a; 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...

uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)

UniApp 集成腾讯云 IM 富媒体消息全攻略&#xff08;地理位置/文件&#xff09; 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型&#xff0c;核心实现方式&#xff1a; 标准消息类型&#xff1a;直接使用 SDK 内置类型&#xff08;文件、图片等&#xff09;自…...