ARMv8架构u-boot启动流程详细分析

一起学嵌入式 2023-05-05 07:50

扫描关注一起学嵌入式,一起学习,一起成长

本文基于 armv8 架构来对 u-boot 进行启动流程分析,u-boot版本为2022-01。

1 概述

首先引用wiki上的简介:u-boot 是一个主要用于嵌入式系统的引导加载程序,可以支持多种不同的计算机系统结构。

u-boot最先是由德国DENX软件中心团队开发,后续众多有志于开放源码bootloader移植工作的嵌入式开发人员将各个不同系列嵌入式处理器的移植工作不断展开和深入,以支持了更多的嵌入式操作系统的装载与引导。

选择u-boot的理由:

开放源码;支持多种嵌入式操作系统内核的引导,如Linux、NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS, android;支持多个处理器系列,如PowerPC、ARM、x86、MIPS;

较高的可靠性和稳定性;高度灵活的功能设置,适合U-Boot调试、操作系统不同引导要求、产品发布等;

丰富的设备驱动源码,如串口、以太网、SDRAM、FLASH、LCD、NVRAM、EEPROM、RTC、键盘等;

较为丰富的开发调试文档与强大的网络技术支持;

基于以上理由本篇文章对现在主流的armv8架构的u-boot启动流程进行详细分析,以便所有人快速学习和理解u-boot的工作流程。

2 armv8 u-boot的启动

先看arm官网提供的一张图:

上图详细概括了arm官方推荐的armv8的启动层次结构:

官方将启动分为了BL1,BL2,BL31,BL32,BL33阶段,根据顺序,芯片启动后首先执行BL1阶段代码,接着验签启动BL2,BL2根据具体设计启动BL31或者BL33,BL32只有在有BL31时才可能会存在并被验签加载启动。

armv8分为Secure World和Non-Secure World(Normal World),四种异常级别从高到低分别为EL3,EL2,EL1,EL0。

Secure World就是可以执行可信的firmware和app,比如密码支付,指纹识别等一系列依赖安全保证的服务。Non-Secure World就是我们常见的u-boot,linux,qnx等裸机程序或者操作系统。

EL3具有最高管理权限,负责安全监测和安全模式切换。EL2主要提供了对虚拟化的支持。EL1是一个特权模式,能够执行一些特权指令,用于运行各类操作系统,在安全模式则是可信任OS。EL0是无特权模式,所有APP应用都在EL0。

上图中的BL1,BL2,BL31,BL32,BL33分别对应如下功能:

BL1:是一切信任的根,一般就是固化在ROM中的一段启动加载代码,用于引导bl2,并对bl2进行验签保证可信任执行;

BL2:一般是在flash中的一段可信安全启动代码,它的可信建立在bl1对它的验证,主要完成一些平台相关的初始化,比如对ddr的初始化等,并在完成初始化后寻找BL31或者BL33进行执行;如果找到了BL31则不会继续调用BL33,如果没有BL31则BL33必须有;

BL31:BL31不像BL1和BL2是一次性运行的,它作为最后一道可信任固件存在,在系统运行时通过smc指令陷入EL3调用系统安全服务或者在Secure World和Non-Secure World之间进行切换;在完成BL31初始化后会去寻找BL32或者BL33进行验签后加载执行;

BL32:OPTee OS + 安全app,它是一个可信安全的OS运行在EL1并在EL0启动可信任APP(上述的指纹验证等app),并在Trust OS运行完成后通过smc指令返回BL31,BL31切换到Non-Seucre World继续执行BL33;

BL33:非安全固件,也就是我们常见的UEFI firmware或者u-boot也可能是直接启动Linux kernel;

启动BL1,BL2,BL31,BL32则是一个完整的ATF信任链建立流程(ARM Trusted Firmware),像常见的PSCI(Power State Coordination Interface)功能则是在ATF的BL31上实现;

最后一张图完整展示整个调用流程:

BL2根据是否存在BL31和BL32可选择性的加载不同firmware;

综上所述,可知u-boot是一个运行在非安全世界的bootloader,负责加载各类操作系统,并提供丰富的驱动接口;并根据是否存在安全固件还可以进行不同的boot流程,如下。

u-boot,u-boot-spl,u-boot-tpl的关系:对于一般嵌入式而言只需要一个u-boot作为bootloader即可,但是在小内存,或者有atf的情况下还可以有spl,tpl;

spl:Secondary Program Loader,二级加载器 

tpl:Tertiary Program Loader,三级加载器

出现spl和tpl的原因最开始是因为系统sram太小,rom无法在ddr未初始化的情况下一次性把所有代码从flash,emmc,usb等搬运到sram中执行,也或者是flash太小,无法完整放下整个u-boot来进行片上执行。

所以u-boot又定义了spl和tpl,spl和tpl走u-boot完全相同的boot流程,不过在spl和tpl中大多数驱动和功能被去除了,根据需要只保留一部分spl和tpl需要的功能,通过CONFIG_SPL_BUILD和CONFIG_TPL_BUILD控制;

一般只用spl就足够了,spl完成ddr初始化,并完成一些外设驱动初始化,比如usb,emmc,以此从其他外围设备加载u-boot,但是如果对于小系统spl还是太大了,则可以继续加入tpl,tpl只做ddr等的特定初始化保证代码体积极小,以此再次从指定位置加载spl,spl再去加载u-boot。

从目前来看,spl可以取代上图中bl2的位置,或者bl1,根据具体厂商实现来决定,有一些芯片厂商会将spl固化在rom中,使其具有从emmc,usb等设备加载u-boot或者其他固件的能力。

当然在有atf的情况下可以由atf加载u-boot,或者由spl加载atf,atf再去加载u-boot。甚至在快速启动的系统中可以直接由spl启动加载linux等操作系统而跳过启动u-boot;在上图中arm官方只是给出了一个建议的启动信任链,具体实现都需要芯片厂商来决定;

后续分析启动流程中会在具有SPL和TPL的地方拓展它们的分叉执行路径尽量把SPL和TPL的功能也一并分析;

3 u-boot源码整体结构和一些编译配置方式

3.1 编译配置方式

u-boot使用了同Linux一样的编译配置方式,即使用kbuild系统来管理整体代码的配置和编译,通过defconfig来定制各种不同厂商的芯片bootloader二进制程序。编译只需要注意通过环境变量或者命令行参数的方式引入一个交叉编译工具即可:

CROSS_COMPILE:定义交叉编译工具链,可以是aarch64-linux-gnu-,arm-none-eabi-或者ppc-linux-gnu-等等;u-boot有几个配置是需要由对应board配置的。

SYS_ARCH,SYS_CPU,SYS_SOC,SYS_BOARD,SYS_VENDOR,SYS_CONFIG_NAME;一般在board/vendor/board/Kconfig中可全部定义,部分SYS_CPU,SYS_SOC也可以在arch/xxx/Kconfig中定义,根据这几个配置即可确定使用的cpu架构,厂商,板级信息,soc信息。

Makefile会自动根据上述信息进入对应目录组织编译规则,一般如果没有自己对应的这些board信息,需要自己在对应目录建立这些Kconfig和在configs中建立defconfig。

在configs目录中保存了uboot中所有支持的board配置,比如要使用rk3399的evb板的配置信息使用如下方式即可编译出来:

make CROSS_COMPILE=aarch64-linux-gnu- evb-rk3399_defconfig
make

如果没有对应的defconfig可以找一个与自己板级信息类似的defconfig生成一个.config,再通过menuconfig来完成自己board的配置,并最后通过savedefconfig保存为自己board的defconfig:

make CROSS_COMPILE=aarch64-linux-gnu- evb-rk3399_defconfig
make menuconfig
make savedefconfig
cp defconfig configs/my_defconfig

下面是evb rk3399的定义:

CONFIG_SYS_ARCH="arm"
CONFIG_SYS_CPU="armv8"
CONFIG_SYS_SOC="rk3399"
CONFIG_SYS_VENDOR="rockchip"
CONFIG_SYS_BOARD="evb_rk3399"
CONFIG_SYS_CONFIG_NAME="evb_rk3399"

根据CONFIG_SYS_BOARD的定义还会为每个源文件自动包含include/configs/xxxx.h头文件,evb rk3399则是include/configs/evb_rk3399.h头文件。这个头文件可在其中定义board的一些关键配置,系统的ram大小,环境变量的起始地址和大小,GIC基地址,时钟频率,是否开启看门狗等定义,可根据具体需求来定义。

u-boot使用Kconfig和include/configs/xxx.h来灵活的确定u-boot编译流程及最终生成的文件。比如当定义CONFIG_SYS_CPU为"armv8",CONFIG_SYS_ARCH为"arm"时,即确定了目标架构为armv8会自动根据Makefile进入对应目录进行编译链接。

3.2 u-boot源码结构

这里只对一些常用的目录进行说明:

arch:各种架构的启动初始化流程代码,链接脚本等均在此目录对应的架构中存放;

board:包含了大部分厂商的board初始化代码,基本平台化相关的代码都在对应的board目录中,早期的一些board代码在arch/xxx/xxx-mach中,现在基本不会放在arch目录下面了;

cmd:包含了大量实用的u-boot命令的实现,比如md,cp,cmp,tftp,fastboot,ext4load等命令的实现,我们也可以在此处添加自己实现的命令;

common:包含了u-boot的核心初始化代码,包括board_f,board_r,spl等一系列代码;

configs:包含了所有board的配置文件,可直接使用;

drivers:大量驱动代码的存放处;

dts:编译生成dtb,内嵌dtb到u-boot的编译规则定义目录;

env:环境变量功能实现代码;

fs:文件系统读写功能的实现,里面包含了各类文件系统的实现;

include:所有公用头文件的存放路径;

lib:大量通用功能实现,提供给各个模块使用;

net:网络相关功能的实现;

scripts:编译,配置文件的脚本文件存放处;

tools:测试和实用工具的实现,比如mkimage的实现代码在此处;

4 u-boot armv8链接脚本

在进行源码分析之前,首先看看u-boot的链接脚本,通过链接脚本可以从整体了解一个u-boot的组成,并且可以在启动分析中知道某些逻辑是在完成什么工作。

在armv8中,u-boot使用arch/arm/cpu/armv8/u-boot.lds进行链接。

u-boot-spl和u-boot-tpl使用arch/arm/cpu/armv8/u-boot-spl.lds进行链接,因为每个board的情况可能不同,所以u-boot可以通过Kconfig来自定义u-boot-spl.lds和u-boot-tpl.lds。

4.1 u-boot.lds

/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * (C) Copyright 2013
 * David Feng 
 *
 * (C) Copyright 2002
 * Gary Jennejohn, DENX Software Engineering, 
 */


#include 
#include 

OUTPUT_FORMAT("elf64-littleaarch64""elf64-littleaarch64""elf64-littleaarch64")
OUTPUT_ARCH(aarch64)
ENTRY(_start) -------------------------------------------------------------------- (1)
/*
 *(1)首先定义了二进制程序的输出格式为"elf64-littleaarch64",
 *    架构是"aarch64",程序入口为"_start"符号;
 */

SECTIONS
{
#ifdef CONFIG_ARMV8_SECURE_BASE -------------------------------------------------- (2)
/*
 *(2)ARMV8_SECURE_BASE是u-boot对PSCI的支持,在定义时可以将PSCI的文本段,
 *    数据段,堆栈段重定向到指定的内存,而不是内嵌到u-boot中。
 *    不过一般厂商实现会使用atf方式使其与bootloader分离,这个功能不常用;
 */

 /DISCARD/ : { *(.rela._secure*) }
#endif
 . = 0x00000000; -------------------------------------------------------------- (3)
/*
 *(3)定义了程序链接的基地址,默认是0,通过配置CONFIG_SYS_TEXT_BASE可修改
 *    这个默认值。
 */

 . = ALIGN(8);
 .text :
 {
  *(.__image_copy_start) --------------------------------------------------- (4)
/*
 *(4)__image_copy_start和__image_copy_end用于定义需要重定向的段,
 *    u-boot是一个分为重定向前初始化和重定向后初始化的bootloader,
 *    所以此处会定义在完成重定向前初始化后需要搬运到ddr中数据的起始地址和结束地址;
 *
 *    大多数时候u-boot是运行在受限的sram或者只读的flash上,
 *    u-boot为了启动流程统一会在ddr未初始化和重定位之前不去访问全局变量,
 *    但是又为了保证u-boot能够正常读写全局变量,内存,调用各类驱动能力,
 *    所以u-boot将启动初始化分为了两个部分,重定向前初始化board_f和
 *    重定向后初始化  board_r,在重定向之前完成一些必要初始化,
 *    包括可能的ddr初始化,然后通过__image_copy_start和__image_copy_end
 *    将u-boot搬运到ddr中,并在ddr中进行重定向后初始化,这个时候的u-boot就可以
 *    正常访问全局变量等信息了。
 * 
 *    如果想要在board_f过程中读写一些全局变量信息该怎么办呢?
 *    u-boot通过定义global_data(gd)来完成此功能,
 *    后续在分析到时会详细讲解实现方式。
 */

  CPUDIR/start.o (.text*) -------------------------------------------------- (5)
/*
 *(5)定义了链接程序的头部文本段,armv8就是
 *    arch/arm/cpu/armv8/start.S, 
 *    start.S中所有文本段将会链接到此段中并且段入口符号就是_start;
 */

 }

 /* This needs to come before *(.text*) */
 .efi_runtime : { ------------------------------------------------------------ (6)
/*
 *(6)在定义了efi运行时相关支持时才会出现使用的段,一般不用关心;
 */

        __efi_runtime_start = .;
  *(.text.efi_runtime*)
  *(.rodata.efi_runtime*)
  *(.data.efi_runtime*)
        __efi_runtime_stop = .;
 }

 .text_rest : ---------------------------------------------------------------- (7)
/*
 *(7)除了start.o,其他的所有文本段将会链接到此段中;
 */

 {
  *(.text*)
 }

#ifdef CONFIG_ARMV8_PSCI -------------------------------------------------------- (8)
/*
 *(8)同(2),是PSCI相关功能的支持,一般不会使用;
 */

 .__secure_start :
#ifndef CONFIG_ARMV8_SECURE_BASE
  ALIGN(CONSTANT(COMMONPAGESIZE))
#endif
 {
  KEEP(*(.__secure_start))
 }

#ifndef CONFIG_ARMV8_SECURE_BASE
#define CONFIG_ARMV8_SECURE_BASE
#define __ARMV8_PSCI_STACK_IN_RAM
#endif
 .secure_text CONFIG_ARMV8_SECURE_BASE :
  AT(ADDR(.__secure_start) + SIZEOF(.__secure_start))
 {
  *(._secure.text)
  . = ALIGN(8);
  __secure_svc_tbl_start = .;
  KEEP(*(._secure_svc_tbl_entries))
  __secure_svc_tbl_end = .;
 }

 .secure_data : AT(LOADADDR(.secure_text) + SIZEOF(.secure_text))
 {
  *(._secure.data)
 }

 .secure_stack ALIGN(ADDR(.secure_data) + SIZEOF(.secure_data),
       CONSTANT(COMMONPAGESIZE))
 (NOLOAD) :
#ifdef __ARMV8_PSCI_STACK_IN_RAM
  AT(ADDR(.secure_stack))
#else
  AT(LOADADDR(.secure_data) + SIZEOF(.secure_data))
#endif
 
{
  KEEP(*(.__secure_stack_start))

  . = . + CONFIG_ARMV8_PSCI_NR_CPUS * ARM_PSCI_STACK_SIZE;

  . = ALIGN(CONSTANT(COMMONPAGESIZE));

  KEEP(*(.__secure_stack_end))
 }

#ifndef __ARMV8_PSCI_STACK_IN_RAM
 . = LOADADDR(.secure_stack);
#endif

 .__secure_end : AT(ADDR(.__secure_end)) {
  KEEP(*(.__secure_end))
  LONG(0x1d1071c); /* Must output something to reset LMA */
 }
#endif

 . = ALIGN(8);
 .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } ------------------- (9)
/*
 *(9)所有仅读数据将会在这个段中对齐排序存放好;
 */


 . = ALIGN(8);
 .data : { -------------------------------------------------------------------- (10)
/*
 *(10)所有数据段将会链接到此段中;
 */

  *(.data*)
 }

 . = ALIGN(8);

 . = .;

 . = ALIGN(8);
 .u_boot_list : { ------------------------------------------------------------- (11)
/*
 *(11)u_boot_list段定义了系统中当前支持的所有命令和设备驱动,此段把散落在各个文件中
 *     通过U_BOOT_CMD的一系列拓展宏定义的命令和U_BOOT_DRIVER的拓展宏定义的设备驱动收集到一起,
 *     并按照名字排序存放,以便后续在命令行快速检索到命令并执行和检测注册的设备和设备树匹配
 *     probe设备驱动初始化;(设备驱动的probe只在定义了dm模块化驱动时有效)
 */

  KEEP(*(SORT(.u_boot_list*)));
 }

 . = ALIGN(8);

 .efi_runtime_rel : {
                __efi_runtime_rel_start = .;
  *(.rel*.efi_runtime)
  *(.rel*.efi_runtime.*)
                __efi_runtime_rel_stop = .;
 }

 . = ALIGN(8);

 .image_copy_end :
 {
  *(.__image_copy_end)
 }

 . = ALIGN(8);

 .rel_dyn_start : -------------------------------------------------------- (12)
/*
 *(12)一般u-boot运行时是根据定义的基地址开始执行,如果加载地址和链接地址
 *     不一致则会出现不能执行u-boot的问题。通过一个
 *     配置CONFIG_POSITION_INDEPENDENT即可打开地址无关功能,
 *     此选项会在链接u-boot时添加-PIE参数。此参数会在u-boot ELF文件中
 *     生成rela*段,u-boot通过读取此段中表的相对地址值与实际运行时地址值
 *     依次遍历进行修复当前所有需要重定向地址,使其可以实现地址无关运行;
 *     即无论链接基地址如何定义,u-boot也可以在任意ram地址
 *     运行(一般需要满足最低4K或者64K地址对齐);
 * 
 *     注意此功能只能在sram上实现,因为此功能会在运行时修改文本段数据段中的地址,
 *     如果此时运行在片上flash,则不能写flash,导致功能失效无法实现地址无关;
 */

 {
  *(.__rel_dyn_start)
 }

 .rela.dyn : {
  *(.rela*)
 }

 .rel_dyn_end :
 {
  *(.__rel_dyn_end)
 }

 _end = .;

 . = ALIGN(8);

 .bss_start : { -------------------------------------------------------- (13)
/*
 *(13)众所周知的bbs段;
 */

  KEEP(*(.__bss_start));
 }

 .bss : {
  *(.bss*)
   . = ALIGN(8);
 }

 .bss_end : {
  KEEP(*(.__bss_end));
 }

 /DISCARD/ : { *(.dynsym) } -------------------------------------------- (14)
/*
 *(14)一些在链接时无用需要丢弃的段;
 */

 /DISCARD/ : { *(.dynstr*) }
 /DISCARD/ : { *(.dynamic*) }
 /DISCARD/ : { *(.plt*) }
 /DISCARD/ : { *(.interp*) }
 /DISCARD/ : { *(.gnu*) }

#ifdef CONFIG_LINUX_KERNEL_IMAGE_HEADER ----------------------------------- (15)
/*
 *(15)在efi加载时会很有用,主要在u-boot的二进制头部添加了一些头部信息,
 *     包括大小端,数据段文本段大小等,以便于efi相关的加载器读取信息,
 *     此头部信息来自于Linux arm64的Image的头部信息;该头部也不属于u-boot的
 *     一部分只是被附加上去的;
 */

#include "linux-kernel-image-header-vars.h"
#endif
}

4.2 u-boot-spl.lds

此链接脚本是标准的spl链接脚本,还包含了u_boot_list段,如果对应自己board不需要命令行或者模块化驱动设备,只作为一个加载器则可以自定义更简略的链接脚本。

/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * (C) Copyright 2013
 * David Feng 
 *
 * (C) Copyright 2002
 * Gary Jennejohn, DENX Software Engineering, 
 *
 * (C) Copyright 2010
 * Texas Instruments, 
 * Aneesh V 
 */


MEMORY { .sram : ORIGIN = IMAGE_TEXT_BASE, ---------------------------------------- (1)
/*
 *(1)\>XXX 的形式可以将指定段放入XXX规定的内存中;一般u-boot-spl只有
 *    很小的可运行内存块,所以spl中会舍去大量不需要用的段只保留关键的
 *    文本段数据段等,并且通过>.sram的形式将不在ddr初始化前用到的段定义到sdram中,
 *    后续只需在完成ddr初始化后将这些段搬运到ddr中即可,而不需要额外的
 *    地址修复逻辑,如下:有一个sram 0x18000-0x19000,
 *    一个sdram 0x80000000 - 0x90000000,
 *    那么通过>.sram方式则map文件可能如下:
 *       0x18000 stext
 *       ...
 *       0x18100 sdata
 *       ...
 *       0x80000000 sbss
 *       ...
 */

  LENGTH = IMAGE_MAX_SIZE }
MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR,
  LENGTH = CONFIG_SPL_BSS_MAX_SIZE }

OUTPUT_FORMAT("elf64-littleaarch64""elf64-littleaarch64""elf64-littleaarch64")
OUTPUT_ARCH(aarch64)
ENTRY(_start) -------------------------------------------------------------------- (2)
/*
 *(2)同u-boot.lds一致,共用一套逻辑入口_start;
 */

SECTIONS
{
 .text : {
  . = ALIGN(8);
  *(.__image_copy_start) -------------------------------------------------- (3)
/*
 *(3)同样的,如果spl需要重定向则会使用此段定义,大多数情况下spl中会用上重定向;
 */

  CPUDIR/start.o (.text*)
  *(.text*)
 } >.sram

 .rodata : {
  . = ALIGN(8);
  *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
 } >.sram

 .data : {
  . = ALIGN(8);
  *(.data*)
 } >.sram

#ifdef CONFIG_SPL_RECOVER_DATA_SECTION ---------------------------------------- (4)
/*
 *(4)SPL_RECOVER_DATA_SECTION段用于保存数据段数据,
 *    一些board在初始化时修改data段数据,并在后续某个阶段
 *    从此段中恢复data的原始数据;
 */

 .data_save : {
  *(.__data_save_start)
  . = SIZEOF(.data);
  *(.__data_save_end)
 } >.sram
#endif

 .u_boot_list : {
  . = ALIGN(8);
  KEEP(*(SORT(.u_boot_list*)));
 } >.sram

 .image_copy_end : {
  . = ALIGN(8);
  *(.__image_copy_end)
 } >.sram

 .end : {
  . = ALIGN(8);
  *(.__end)
 } >.sram

 _image_binary_end = .;

 .bss_start (NOLOAD) : {
  . = ALIGN(8);
  KEEP(*(.__bss_start));
 } >.sdram -------------------------------------------------------------- (5)
/*
 *(5)将bss段数据定义到>.sdram中,即可在初始化ddr后直接对此段地址清零
 *    即可使用全局未初始化变量,并且不会带来副作用。
 */


 .bss (NOLOAD) : {
  *(.bss*)
   . = ALIGN(8);
 } >.sdram

 .bss_end (NOLOAD) : {
  KEEP(*(.__bss_end));
 } >.sdram

 /DISCARD/ : { *(.rela*) }
 /DISCARD/ : { *(.dynsym) }
 /DISCARD/ : { *(.dynstr*) }
 /DISCARD/ : { *(.dynamic*) }
 /DISCARD/ : { *(.plt*) }
 /DISCARD/ : { *(.interp*) }
 /DISCARD/ : { *(.gnu*) }
}

从上述的链接脚本可以看出,armv8的u-boot的启动是从arch/arm/cpu/armv8/start.S中的_start开始的,并在后续初始化中调用了很多链接脚本中定义的地址符号表。

原文:https://blog.csdn.net/maybeYoc/article/details/122937844

文章来源于网络,版权归原作者所有,如有侵权,请联系删除。



关注我【一起学嵌入式】,一起学习,一起成长。


觉得文章不错,点击“分享”、“”、“在看” 呗!

一起学嵌入式 公众号【一起学嵌入式】,RTOS、Linux编程、C/C++,以及经验分享、行业资讯、物联网等技术知
评论
  • 在谐振器(无源晶振)S&A250B测试软件中,DLD1到DLD7主要用于分析晶体在不同驱动功率下的阻抗变化。此外,还有其他DLD参数用于反映晶振的磁滞现象,以及其频率和功率特性。这些参数可以帮助工程师全面了解KOAN晶振在不同功率条件下的动态特性,从而优化其应用和性能。磁滞现象晶振的磁滞现象(Hysteresis)是指在驱动功率变化时,晶体的阻抗或频率无法立即恢复至初始状态,而表现出滞后效应。1. DLDH: Hysteresis Ratio (MaxR/MinR)在不同驱动
    koan-xtal 2024-12-26 12:41 49浏览
  • 据IDTechEx最新预计,到2034年,全球汽车舱内传感(In-Cabin Sensing,ICS)市场将超过85亿美元。若按照增长幅度来看,包含驾驶员监控系统(DMS)、乘员监控系统(OMS)、手势控制和生命体征监测等高级功能在内的舱内传感市场预计2020年到2034年将增长11倍。感光百科:ICS中的光源选择01、政策推动带来的“硬”增长作为其中的增长主力,舱内监控系统应用(包含DMS和OMS等)被推动增长的首要因素正是法规。据统计,中国、欧盟、美国、韩国、印度等主要汽车国家或地区已推出相
    艾迈斯欧司朗 2024-12-25 19:56 50浏览
  • 今年AI技术的话题不断,随着相关应用服务的陆续推出,AI的趋势已经是一个明确的趋势及方向,这也连带使得AI服务器的出货量开始加速成长。AI服务器因为有着极高的运算效能,伴随而来的即是大量的热能产生,因此散热效能便成为一个格外重要的议题。其实不只AI服务器有着散热的问题,随着Intel及AMD 的CPU规格也不断地在提升,非AI应用的服务器的散热问题也是不容小觑的潜在问题。即便如此,由于目前的液冷技术仍有许多待克服的地方,例如像是建置成本昂贵,机壳、轨道、水路、数据中心等项目都得重新设计来过,维修
    百佳泰测试实验室 2024-12-26 16:33 11浏览
  • 本文介绍瑞芯微RK3588主板/开发板Android12系统下,APK签名文件生成方法。触觉智能EVB3588开发板演示,搭载了瑞芯微RK3588芯片,该开发板是核心板加底板设计,音视频接口、通信接口等各类接口一应俱全,可帮助企业提高产品开发效率,缩短上市时间,降低成本和设计风险。工具准备下载Keytool-ImportKeyPair工具在源码:build/target/product/security/系统初始签名文件目录中,将以下三个文件拷贝出来:platform.pem;platform.
    Industio_触觉智能 2024-12-26 09:19 74浏览
  • “金字招牌”的户外叙事。2024年的夏天似乎异常炙热,体育迷们的心跳也随之澎湃,全球瞩目的体育盛宴——巴黎奥运会在此刻上映。在这个充满荣耀与梦想的夏天,我们见证了无数激动人心的瞬间:男子4X100米混合泳接力决赛中,潘展乐的最后一棒,气壮山河,中国队的历史性夺冠,让整个泳池沸腾;射击10米气步枪混合团体决赛,黄雨婷和盛李豪的精准射击,为中国队射落首金,展现了年轻一代的力量;乒乓球男单四分之一比赛中,樊振东的惊天逆转令人难以忘怀,凭借坚韧不拔的意志和卓越的技术,成功挺进半决赛,并最终夺冠……在这一
    艾迈斯欧司朗 2024-12-25 19:30 47浏览
  • 新能源汽车市场潮起潮落,只有潮水退去,才能看清谁在裸泳。十年前,一批新能源汽车新势力带着创新的理念和先进的技术,如雨后春笋般涌入中国汽车市场,掀起一场新旧势力的角逐。经历市场的激烈洗礼与投资泡沫的挤压,蔚来、理想、小鹏等新势力车企脱颖而出,刷爆网络。不曾想,今年新势力车企杀出一匹“超级黑马”,爬上新势力车企销量榜前三,将蔚来、小鹏等昔日强者甩在了身后,它就是零跑汽车。公开数据显示,11月份,零跑汽车实现新车交付量约4.02万辆,同比增长117%,单月销量首次突破4万辆;小鹏汽车当月共交付新车约3
    刘旷 2024-12-26 10:53 75浏览
  • 本文介绍瑞芯微开发板/主板Android系统APK签名文件使用方法,触觉智能EVB3588开发板演示,搭载了瑞芯微RK3588芯片,各类接口一应俱全,帮助企业提高产品开发效率,缩短上市时间,降低成本和设计风险。系统签名文件生成APK系统签名文件,具体可参考此文章方法RK3588主板/开发板Android12系统APK签名文件生成方法,干货满满使用方法第一步,修改APK工程文件app/src/build.gradle,并添加以下内容: android {     na
    Industio_触觉智能 2024-12-26 09:20 52浏览
  • 引言  LIN(Local Interconnect Network)是一种针对汽车电子系统应用的串行通信协议,主要用于汽车电子控制单元(ECU)之间的通信。LIN总线的特点是成本低、速率低、通信距离短、连接节点少,主要用于对带块要求低、实时性要求不高的控制任务,例如车门控制、天窗控制、座椅控制、车内照明等功能。LIN总线采用的是主从式架构,由主节点基于调度表调度网络中的通信。  LIN总线的错误类型  尽管LIN协议设计简单,具有低带
    北汇信息 2024-12-25 14:18 41浏览
  • 全球照明技术创新领航者艾迈斯欧司朗,于2024年广州国际照明展览会同期,举办【智慧之光】· 艾迈斯欧司朗-照明应用研讨会,以持续的技术创新,推动光+概念的全面落地。现场还演示了多款领先照明技术,且由资深工程师倾情解读,另有行业大咖深度洞察分享,助你开启“光的无限可能”探索之旅!精彩大咖分享引领未来照明无限遐想艾迈斯欧司朗精心准备了照明领域专业大咖的深度分享,无论是照明领域的资深从业者,还是对照明科技充满好奇的探索者,在这里,您都将大有所获。在艾迈斯欧司朗照明全球产品市场VP Geral
    艾迈斯欧司朗 2024-12-25 20:05 41浏览
  • 概述 Intel 要求用户为其10代FPGA器件使用特定的上电和掉电顺序,这就要求用户在进行FPGA硬件设计的时候必须选择恰当的FPGA供电方案,并合理控制完整的供电上电顺序。经过在Cyclone 10 GX测试板上实际验证,统一上电确实会导致FPGA无法正常工作,具体表现为JTAG接口无法探测或识别到目标器件。上电顺序要求 Cyclone 10 GX,Arria 10以及Stratix 10系列器件所有的电源轨被划分成了三个组合,三组电源轨要求依次上电,如图1所示,为三组电源轨上电顺序示意图。
    coyoo 2024-12-25 14:13 37浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦