工程师实地讲解:剖析基于nanoPC-T3的U-Boot移植过程

嵌入式ARM 2020-03-19 00:00

  导读:前文对U-Boot架构设计做了分析,本文来梳理一下U-Boot在具体板子上的移植工作,主要记录整体思路、要点,以触类旁通而记之。


1.收集Boot相关信息

NanoPC-T3 是友善之臂为企业用户设计的主板,采用三星八核Cortex -A53架构的S5P6818处理器。其主要技术参数:

  • CPU: S5P6818, 动态运行主频400Mhz--1.4GHz  8核

  • DDR3 RAM: 1GB,采用2片K4B4G1646D

  • SD: 标准SD卡槽一个

  • eMMC:8GB

  • HDMI: HDMI 1.4a, Type A型口,1080P高清显示

  • DVP Camera接口: 24pin, 0.5mm间距,FPC贴片竖座

  • GPIO扩展接口: 4个UART, 1路I2C, 1路SPI, 3路PWM,9个GPIO


详细参见http://www.arm9.net/nanopc-t3.asp

 

  1. 1   SOC Boot相关信息

需要将采用该SOC的方式以U-Boot引导,那么首先应该将Boot的相关信息进行收集分析。

支持的Boot模式:

  • 外部静态存储器ExternalStatic Memory Boot



复位首条指令直接从外部静态存储器引导。

  • 内部ROM boot

  • NAND boot with Error Correction

  • SD/MMC/SDFS (SD FAT File system) boot

  • SPI Serial EEPROM boot

  • UART boot

  • USB Boot

< SEC_S5P6818X_Users_Manual_preliminary_Ver_0.00.pdf>

SOC内置了20KBiROMBOOT,这是一段固化的boot程序,通过识别外部Boot配置进入相应的Boot模式,完成内部boot到用户boot程序的第一阶段Boot

datasheet 看见该SOC内部实现了iROMBOOT,而SPLSecondaryprogramloader)是u-boot第一阶段执行的代码。主要负责搬移u-boot第二阶段的代码到。iROMBOOT已经实现了这一功能,故不需要用户实现SPL了。


1.2 NanoPC-T3 板级信息


由于boot一般与板子的设计配置相关,大多由IO口配置进行选择,既然支持上述如何之多的Boot模式,那么拿到的板子又支持哪些引导模式呢?


从上图中可看出

可见nanoPC T3仅支持SDMMC Boot模式,进入对应的章节,可看出支持三个SD通道。通过从SD存储卡,MMC存储卡和eMMC中读取iROMBOOT并通过使用SDHC模块将其加载到内存中,iROMBOOT执行用户启动代码。此方法称为SDHCBOOTSDCLK输出400 kHz用于识别,输出24 MHz用于数据传输。



那么如何进入对应的通道呢?

SD3已经电路下拉为低:

  • 默认CAM1_D3为高,用户boot通道默认为CH0,电路板设计为SD

SD卡是(secure digital memory card)安全数码卡,是一种基于半导体快闪记忆器的新一代记忆设备,是在MMC基础上发展起来的,其内部存储介质大都为NAND Flash增加了两个主要特色:

可以设置所存储的使用权限,防止数据被他人复制;第二是传输速度比2.11版mmc卡快。

特性:

1)可选通信协议:SD模式和SPI模式

2)可变时钟频率:0~25MHz

3)通信电压范围:2.0~3.6V

4)数据寿命:10万次编程/擦除

5)正向兼容MMC卡;

6)运行在25M的频率上,数据带宽是4位,因此最大传输速率是12.5MHz(12.5兆字节每秒) <自百度知道>

  • 按住BOOT按键,将板子上电,此时用户boot通道为SD CH2,此时为板载eMMC

eMMC (Embedded Multi Media Card)是MMC协会订立、主要针对手机或平板电脑等产品的内嵌式存储器标准规格。eMMC在封装中集成了一个控制器,提供标准接口并管理闪存,使得手机厂商就能专注于产品开发的其它部分,并缩短向市场推出产品的时间。其内部存储介质大都为NAND Flash。

硬件地址空间:

SOC具有两个内存控制器:

  • MCU-ADDR3 / LVDDR3(低压DDR3/ LPDDR3 / LPDDR2

  • MCU-ADREXDDRPHY组成

  • 支持DDR3 /LVDDR3(低压DDR3/ LPDDR3 / LPDDR2内存

  • 支持2 GB8/16/32SDRAM

  • 单个存储区(32位数据总线宽度)

  • 支持掉电模式

  • 支持自我刷新模式

  • MCU-S:静态存储器

  • 静态内存

  • Static两个静态存储芯片选择

  • NAND闪存接口

  • 23位地址支持使用锁存器地址

  • SLC NAND,带ECCMLC NAND(支持BCH算法)

  • 静态内存映射阴影

故地址空间为:0x4000 0000—7FFF FFFF

开发调试需要实现串口交互,那么串口是哪一个?

板上网口采用什么芯片需要,RTL8211E-VB-CG    集成 10/100/1000M 以太网收发器,显示接口:RGB LCD接口/HDMI

  

至此,第一阶段收集了那些为移植需要准备的信息?

  • S5P6818 8核,armv8,64SOC

  • Boot模式,SDMMC Boot模式,支持两个通道,默认通道Ch0板载eMMC, 按住Boot 按键,CH0:SD Boot,不需要SPL

  • 内存地址:0x40000000—7FFF FFFF  1G DDR3(2K4B4G1646D 4Gbit/chip)

  • 控制台:UART0

  • 网口:RTL8211E-VB-CG   集成10/100/1000M 以太网收发器。

  • LCDRGB LCD接口/HDMI


2.移植

2.1 明确移植内容

在具体实施之前,首先须总体上明确How to do

2.2明确Boot流程

明确Boot流程,需要明确有哪些地方需要根据所选SOC,板级硬件设计做出移植:

如前文分析,u-boot的启动流程主要分亮部分。

第一阶段:芯片复位,执行复位跳转,从自各自芯片的start.S开始执行汇编代码

一般而言,start.S 位于- arch/ic_xxx/cpu/start.S

如:

- arch/arm/cpu/armv7/start.S

- arch/powerpc/cpu/mpc83xx/start.S

-arch/mips/cpu/start.S

为什么这是复位入口呢?这取决于如何链接,由u-boot.lds指定:


链接文件位于./arch/arm/cpu/armv8/u-boot.lds

注:因为nanoPC-T3 S5P6818的SOC是一颗8核A53核,A53是armv8架构。

第二阶段:lowlevel_init()board_init_f()board_init_r()

lowlevel_init()

  • 目的:允许执行达到oard_init_f()的基本初始化

  • 没有global_dataBSS

  • 没有堆栈(ARMv7可能有一个堆栈,但是很快就会被删除)

  • 不得设置SDRAM或使用控制台

  • 必须只做最少的工作,以允许执行继续到board_init_f()

  • 几乎不需要

  • 从此函数正常返回

board_init_f()

  • 目的:初始化CPU运行环境以准备运行board_init_r():即初始化SDRAMUART

  • global_data可用

  • 堆栈位于SRAM

  • BSS不可用,因此您不能使用全局/静态变量,只能使用堆栈变量和global_data

  • SPL特定说明:

  • 调用dram_init()设置DRAM 如果已经在SPL中完成,则无法执行任何操作

 

  • SPL特定说明:

  • 可以根据需要使用自己的版本覆盖整个board_init_f()函数。

  • preloader_console_init()可以在依据需要调用

  • 须初始化SDRAM,以及初始化UART

  • -不需要清除BSS段,由crt0.S完成

  • -必须从此函数正常返回(不要直接调用board_init_r())

 

此处清除了BSS。对于SPL,如果定义了CONFIG_SPL_STACK_R,则此时将堆栈和global_data重定位到CONFIG_SPL_STACK_R_ADDR之下。 对于非SPLU-Boot被重定位以在内存顶部运行。

board_init_r():

  • 目的:主要执行,通用代码

  • global_data可用

  • SDRAM可用

  • BSS可用,可以使用所有静态/全局变量

  • 执行最终继续到main_loop() 


  • SPL特定说明:

    • U-Boot重定位到内存顶部,并且现在从那里开始运行。 

  • SPL特定说明:

    • 如果定义了CONFIG_SPL_STACK_R并且

      CONFIG_SPL_STACK_R_ADDR指向SDRAM,则堆栈可选地位于SDRAM

    • 在这里可以调用preloader_console_init()-通常是通过定义CONFIG_SPL_BOARD_INIT然后提供包含此调用的spl_board_init()函数来完成的

    • 加载U-Boot(falcon模式下)Linux

以上关于lowlevel_init()board_init_f()board_init_r()翻译自./README


这里有几个概念需要进一步解析,方便下面理解:

  • (heap):堆的管理由C库实现的,Linux中是一般由Glibc,取决于选用什么C库。内存的获取与释放由程序员通过调用C库中的malloc/free进行操作,C库中的动态内存管理单元具体实现。大体上在工程中指定堆的大小,C库中的堆管理器将这片内存进行动态管理,这里需要用到一些数据结构算法对这片内存区进行动态管理。如果要对堆的管理实现进行分析,可以参考glibc的源代码。

  • (stack):由编译器实现栈的管理,由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。


/栈的大小由下面的宏定义:

  • CONFIG_SYS_MALLOC_LEN    指定堆大小

  • CONFIG_SYS_RESERVE_MEM_SIZE/ CONFIG_SYS_MALLOC_LEN 一起指定栈大小

Stack size= CONFIG_SYS_RESERVE_MEM_SIZE-

                   CONFIG_SYS_MALLOC_LEN

如下图所示:

这几个宏定义了内存上界、堆上下界、栈的上下界有编译器、C库实现越界保护机制。

global_data

该结构体收集板子的基本信息,内存,名称,CPU时钟,环境变量,标准IO,设备驱动句柄等等。

红色部分信息将堆分配情况与U-Boot全局数据结构关联。

  • bss段:bss段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。bss是英文Block Started by Symbol的简称。bss段属于静态内存分配。

 

  • data段:数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。  数据段属于静态内存分配。


 

  • text段:代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。  这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读(某些架构也允许代码段为可写,即允许修改程序)。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

    一个程序本质上由这三个段由链接器链接而成。


2.3 创建板子文件

位置board/my_vendor/my_board/my_board.c, 对于nanoPC-T3而言

./board/s5p6818/nanopi3/ board.c

  • dram_init 实现内存初始化

  • board_init 实现GPIO初始化、启动设备初始化等操作,这与板子的硬件息息相关。

    需声明DECLARE_GLOBAL_DATA_PTR指针,因为本模块需要对gd成员进行初始化,ARM32等价于r9寄存器,ARM64等价于寄存器x18

位于./arch/arm/include/asm/global_data.h


2.4 创建Kconfig配置文件


board/my_vendor/my_board/Kconfig

需定义Kconfig对于board需要的相关变量SYS_BOARDSYS_VENDORSYS_CONFIG_NAME

由于S5P6818是一颗64位芯片,那么32/64位将变成可选配置。故这里新创建了S5P6818_FEATURES用以配置32/64位,当取值为no表示为32位配置。

  • SYS_BOARDSYS_VENDOR 用于给kuild识别在那个board,verder目录需去编译相应源文件

  • SYS_CONFIG_NAME 用于给kuild识别在哪里去寻找板子头文件

include/configs/SYS_CONFIG_NAME.h

其工作原理如下:


2.6 创建板子Makefile


board/my_vendor/my_board/Makefile nanoPC-T3而言:

obj-y:=board.o hwrev.o onewire.o lcds.o

由于需要实现LCD以及单线触摸控制器,则需要将上述文件编译。


2.7 创建板子defconfig

configs/my_board_defconfig, nanoPC-T3而言:

s5p6818_nanopi3

_defconfig

对于新版的U-boot已支持make menuconfig,可以运行该命令进行其他配置,然后将生成的.config文件拷贝至此。

mv .config ./configs/s5p6818_nanopi3_defconfig

主要裁剪支持的驱动,以及shell命令等

注:旧版本的U-Boot使用boards.cfg添加板子。


2.8 创建板子头文件

include/confi gs/my_board.h,对nanoPC-T3而言:

include/confi gs/ s5p6818_nanopi3.h

描述

必须?

CONFIG_SYS_TEXT_BASE

0x43C00000

Text段在内存中基址

CONFIG_SYS_INIT_SP_ADDR

0x43C00000

初始栈指针地址

CONFIG_SYS_MONITOR_BASE

0x43C00000

系统内存监控基址

CONFIG_SYS_MEM_SIZE

0x40000000

系统内存大小1G

CONFIG_SYS_RESERVE_MEM_SIZE

0x02500000

自定义用于计算用户内存大小

u-boot.cfg用到

CONFIG_SYS_SDRAM_BASE

0x40000000

内存基址

CONFIG_SYS_SDRAM_SIZE

0x3DB00000

系统可用内存大小

=总内存大小-堆及栈大小

CONFIG_SYS_MALLOC_LEN

0x2000000

32M堆大小

CONFIG_FB_ADDR

0x46000000

显示缓存,当使能

图片显存地址

CONFIG_DISPLAY_PORT->

CONFIG_LCD

CONFIG_BMP_LOAD_ADDR

0x47000000

CONFIG_NR_DRAM_BANKS

2

板子有两个Bank内存

CONFIG_SYS_LOAD_ADDR

0x48000000

内核装载地址

CONFIG_KERNEL_DTB_ADDR

0x49000000

设备树装载地址

CONFIG_FASTBOOT_BUF_ADDR

0x4A000000

Fastboot缓存地址,使能fastboot

CONFIG_FASTBOOT_BUF_SIZE

0x30000000

Fastboot缓存大小

=系统内存大小-0x10000000

COUNTER_FREQUENCY

200000000

定时器频率

CPU_RELEASE_ADDR

0x43C00000

CONFIG_SYS_INIT_SP_ADDR

用于多核切换在start.S中使用

CONFIG_SYS_MEMTEST_START

0x40000000

内存自检起址,用于命令mtest

CONFIG_SYS_MEMTEST_END

0x3DB00000

内存自检终址,用于命令mtest

CONFIG_USE_IRQ


开启IRQ

CONFIG_SYS_HZ

1000

CPU频率

CONFIG_ARCH_CPU_INIT


CPU初始化使能

CONFIG_BOARD_LATE_INIT


使能函数board_late_init()

CONFIG_DISPLAY_CPUINFO


使能board_init_f->init_sequence,

以调用 print_cpuinfo

CONFIG_DISPLAY_BOARDINFO


使能board_init_f->init_sequence, 调用show_board_info

CONFIG_SYS_DCACHE_OFF


board_init_f,

中关闭D cahche

CONFIG_ARCH_MISC_INIT


使能arch_misc_init

CONFIG_CMD_MEMTEST


开启mtest

CONFIG_BOOTDELAY

1

引导时延

CONFIG_ZERO_BOOTDELAY_CHECK


引导时延检查

CONFIG_SYS_PROMPT




 环境变量:

这些定义由./common下环境变量管理模块负责维护,其结构体定义如下,主要为字符串常量。


2.8 引导分析

为了能够重新映射内存,U-Boot随后跳至其链接地址。为了能够在C中实现初始化代码,在内部双端RAM中设置了一个(很小的)初始堆栈(如果CPU提供了诸如MPC8xxMPC8260之类的功能),或者在数据的锁定部分中缓存。之后,U-Boot初始化CPU内核,缓存和SIU

 

接下来,使用初步映射来映射所有可用的存储体。例如,将它们放在512 MB边界上(0x20000000的倍数:0x000000000x20000000上的SDRAM0x400000000x60000000上的Flash0x80000000上的SRAM)。然后,将UPMA编程用于SDRAM访问。使用临时配置,将运行简单的内存测试,以确定SDRAM存储区的大小。

 

如果有多个SDRAM存储区,并且存储区的大小不同,则首先映射最大的存储区。对于相等的大小,将首先映射第一个存储区(CS2#)。第一个映射始终是针对地址0x00000000的,后面紧跟着任何其他存储区以创建从0开始的连续存储器。

 

然后,监视器将自身安装在SDRAM区域的高端,并分配内存供malloc()和全局Board Info数据使用;同样,将异常矢量代码复制到低RAM页面中,并建立最终堆栈。

 

只有在此重定位之后,才能拥有“正常”的C环境。由于受到多种方式的限制,主要是因为从ROM运行,并且必须将代码重定位到RAM中的新地址运行。

 

至于上述过程重定向,主要利用链接绑定以实现符号表位置可知,从将u-boot映象拷贝到内存可实现运行切换。

/*指定输出格式elf64-littleaarch64*/OUTPUT_FORMAT("elf64-littleaarch64""elf64-littleaarch64""elf64-littleaarch64")OUTPUT_ARCH(aarch64) /*指定arch类型*/ENTRY(_start) /*指定入口为start.oSECTIONS{  . = 0x00000000;/**/
. = ALIGN(8);/*64位 故应8字节对齐*/  .text : /*text段*/ { *(.__image_copy_start) /*映象拷贝起始位置*/ CPUDIR/start.o (.text*) *(.text*) }
  /*定义只读数据段*/ . = ALIGN(8); .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
. = ALIGN(8); .data : {/*定义数据段*/ *(.data*) }
. = ALIGN(8);
. = .; /* .u_boot_list:所有以u_boot_list名称开始的段, 都链接于此,主要是一些uboot 命令相关代码;  KEEP关键字是为了保证所有的段都被加进来, SORT表示按照u_boot_list*后的段名子进行排序 */ . = ALIGN(8); .u_boot_list : { KEEP(*(SORT(.u_boot_list*))); }
. = ALIGN(8);/*__image_copy_ end存放了一个地址,取值待链接时确定, 相当于创建一个位置标签;  代表程序重定位(relocate)时拷贝的结束地址 */ .image_copy_end : { *(.__image_copy_end) }
. = ALIGN(8);/* 此处含义与__image_copy_start相同,定义一个位置标签, 表示重定位时全局变量的LABLE的起始地址; 关于重定位代码的说明需要另外说明 */ .rel_dyn_start : { *(.__rel_dyn_start) } /*.rel.dyn:存放重定位代码时全局变量的位置信息*/ .rela.dyn : { *(.rela*) }
/*  __rel_dyn_end存放了一个地址,取值待链接时确定, 相当于创建一个位置标签; 表示重定位时全局变量的LABLE的结束地址 */ .rel_dyn_end : { *(.__rel_dyn_end) }  /*.end代码结束段*/ _end = .;
. = ALIGN(8); /*bss段起始*/ .bss_start : { KEEP(*(.__bss_start)); }
.bss : { *(.bss*) . = ALIGN(8); }
 /*bss段结束*/ .bss_end : { KEEP(*(.__bss_end)); }
  /*.dynstr动态连接符号表的字符串部分,与.dynsym联用*/ /DISCARD/ : { *(.dynsym) } /DISCARD/ : { *(.dynstr*) } /DISCARD/ : { *(.dynamic*) }
/DISCARD/ : { *(.plt*) } /*过程连接表(Procedure Linking Table)*/ /DISCARD/ : { *(.interp*) } /DISCARD/ : { *(.gnu*) }}

而在./arch/arm/lib/sections.c 定义了对应的全局符号,这样就实现了链接地址绑定:

char __bss_start[0] __attribute__((section(".__bss_start")));char __bss_end[0] __attribute__((section(".__bss_end")));char __image_copy_start[0] __attribute__((section(".__image_copy_start")));char __image_copy_end[0] __attribute__((section(".__image_copy_end")));char __rel_dyn_start[0] __attribute__((section(".__rel_dyn_start")));char __rel_dyn_end[0] __attribute__((section(".__rel_dyn_end")));char __secure_start[0] __attribute__((section(".__secure_start")));char __secure_end[0] __attribute__((section(".__secure_end")));char _end[0] __attribute__((section(".__end")));


下面对crt0_64.S 汇编代码做简要注释帮助理解重定向过程:

ENTRY(_main) /*声明入口*//* * Set up initial C runtime environment and call board_init_f(0). */ /*利用load/store指令装载   CONFIG_SYS_INIT_SP_ADDR地址 给SP指针   为调用board_init_f创建C运行环境*/#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) ldr x0, =(CONFIG_SPL_STACK)#else ldr x0, =(CONFIG_SYS_INIT_SP_ADDR)#endif bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */ bl board_init_f_mem mov sp, x0
mov x0, #0 bl board_init_f /*调用board_init_f*//*注:B或BL指令引起处理器转移到“子程序名”处开始执行。两者的不同之处在于BL指令在转移到子程序执行之前,将其下一条指令的地址拷贝到R14(LR,链接寄存器)。由于BL指令保存了下条指令的地址,因此使用指令“MOV PC ,LR”即可实现子程序的返回。而B指令则无法实现子程序的返回,只能实现单纯的跳转。 用户在编程的时候,可根据具体应用选用合适的子程序调用语句。*/
/*如果SPL没有使能*/#if !defined(CONFIG_SPL_BUILD)/* * Set up intermediate environment (new sp and gd) and call * relocate_code(addr_moni). Trick here is that we'll return * 'here' but relocated. */ ldr x0, [x18, #GD_START_ADDR_SP] /* x0 <- gd->start_addr_sp */ bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */ ldr x18, [x18, #GD_BD] /* x18 <- gd->bd */ sub x18, x18, #GD_SIZE /* new GD is below bd */
adr lr, relocation_return ldr x9, [x18, #GD_RELOC_OFF] /* x9 <- gd->reloc_off */ add lr, lr, x9 /* new return address after relocation */ ldr x0, [x18, #GD_RELOCADDR] /* x0 <- gd->relocaddr */ b relocate_code
relocation_return:
/* Set up final (full) environment  */ bl c_runtime_cpu_setup /* still call old routine */
/* TODO: For SPL, call spl_relocate_stack_gd() to alloc stack relocation */
/* Clear BSS section */ ldr x0, =__bss_start /* this is auto-relocated! */ ldr x1, =__bss_end /* this is auto-relocated! */ mov x2, #0clear_loop: str x2, [x0] add x0, x0, #8 cmp x0, x1 b.lo clear_loop
/* call board_init_r(gd_t *id, ulong dest_addr) */ mov x0, x18 /* gd_t */ ldr x1, [x18, #GD_RELOCADDR] /* dest_addr */ b board_init_r /* PC relative jump */
/* NOTREACHED - board_init_r() does not return */
#endif /* !CONFIG_SPL_BUILD */
ENDPROC(_main)

总结:

  • 思路须清楚,不要一开始关注细节

  • 采用渐进明细、逐步迭代的方法论

  • u-boot 其核心在于将系统成功引导。


本文授权转载自公众号 “嵌入式客栈”,作者逸珺

嵌入式ARM 关注这个时代最火的嵌入式ARM,你想知道的都在这里。
评论
  •  在全球能源结构加速向清洁、可再生方向转型的今天,风力发电作为一种绿色能源,已成为各国新能源发展的重要组成部分。然而,风力发电系统在复杂的环境中长时间运行,对系统的安全性、稳定性和抗干扰能力提出了极高要求。光耦(光电耦合器)作为一种电气隔离与信号传输器件,凭借其优秀的隔离保护性能和信号传输能力,已成为风力发电系统中不可或缺的关键组件。 风力发电系统对隔离与控制的需求风力发电系统中,包括发电机、变流器、变压器和控制系统等多个部分,通常工作在高压、大功率的环境中。光耦在这里扮演了
    晶台光耦 2025-01-08 16:03 66浏览
  • 这篇内容主要讨论三个基本问题,硅电容是什么,为什么要使用硅电容,如何正确使用硅电容?1.  硅电容是什么首先我们需要了解电容是什么?物理学上电容的概念指的是给定电位差下自由电荷的储藏量,记为C,单位是F,指的是容纳电荷的能力,C=εS/d=ε0εrS/4πkd(真空)=Q/U。百度百科上电容器的概念指的是两个相互靠近的导体,中间夹一层不导电的绝缘介质。通过观察电容本身的定义公式中可以看到,在各个变量中比较能够改变的就是εr,S和d,也就是介质的介电常数,金属板有效相对面积以及距离。当前
    知白 2025-01-06 12:04 227浏览
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球无人机锂电池产值达到2457百万美元,2024-2030年期间年复合增长率CAGR为9.6%。 无人机锂电池是无人机动力系统中存储并释放能量的部分。无人机使用的动力电池,大多数是锂聚合物电池,相较其他电池,锂聚合物电池具有较高的能量密度,较长寿命,同时也具有良好的放电特性和安全性。 全球无人机锂电池核心厂商有宁德新能源科技、欣旺达、鹏辉能源、深圳格瑞普和EaglePicher等,前五大厂商占有全球
    GIRtina 2025-01-07 11:02 127浏览
  • 故障现象一辆2017款东风风神AX7车,搭载DFMA14T发动机,累计行驶里程约为13.7万km。该车冷起动后怠速运转正常,热机后怠速运转不稳,组合仪表上的发动机转速表指针上下轻微抖动。 故障诊断 用故障检测仪检测,发动机控制单元中无故障代码存储;读取发动机数据流,发现进气歧管绝对压力波动明显,有时能达到69 kPa,明显偏高,推断可能的原因有:进气系统漏气;进气歧管绝对压力传感器信号失真;发动机机械故障。首先从节气门处打烟雾,没有发现进气管周围有漏气的地方;接着拔下进气管上的两个真空
    虹科Pico汽车示波器 2025-01-08 16:51 79浏览
  • 「他明明跟我同梯进来,为什么就是升得比我快?」许多人都有这样的疑问:明明就战绩也不比隔壁同事差,升迁之路却比别人苦。其实,之间的差异就在于「领导力」。並非必须当管理者才需要「领导力」,而是散发领导力特质的人,才更容易被晓明。许多领导力和特质,都可以通过努力和学习获得,因此就算不是天生的领导者,也能成为一个具备领导魅力的人,进而被老板看见,向你伸出升迁的橘子枝。领导力是什么?领导力是一种能力或特质,甚至可以说是一种「影响力」。好的领导者通常具备影响和鼓励他人的能力,并导引他们朝着共同的目标和愿景前
    优思学院 2025-01-08 14:54 74浏览
  • 在智能家居领域中,Wi-Fi、蓝牙、Zigbee、Thread与Z-Wave等无线通信协议是构建短距物联局域网的关键手段,它们常在实际应用中交叉运用,以满足智能家居生态系统多样化的功能需求。然而,这些协议之间并未遵循统一的互通标准,缺乏直接的互操作性,在进行组网时需要引入额外的网关作为“翻译桥梁”,极大地增加了系统的复杂性。 同时,Apple HomeKit、SamSung SmartThings、Amazon Alexa、Google Home等主流智能家居平台为了提升市占率与消费者
    华普微HOPERF 2025-01-06 17:23 209浏览
  • 本文介绍编译Android13 ROOT权限固件的方法,触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。关闭selinux修改此文件("+"号为修改内容)device/rockchip/common/BoardConfig.mkBOARD_BOOT_HEADER_VERSION ?= 2BOARD_MKBOOTIMG_ARGS :=BOARD_PREBUILT_DTB
    Industio_触觉智能 2025-01-08 00:06 95浏览
  • 每日可见的315MHz和433MHz遥控模块,你能分清楚吗?众所周知,一套遥控设备主要由发射部分和接收部分组成,发射器可以将控制者的控制按键经过编码,调制到射频信号上面,然后经天线发射出无线信号。而接收器是将天线接收到的无线信号进行解码,从而得到与控制按键相对应的信号,然后再去控制相应的设备工作。当前,常见的遥控设备主要分为红外遥控与无线电遥控两大类,其主要区别为所采用的载波频率及其应用场景不一致。红外遥控设备所采用的射频信号频率一般为38kHz,通常应用在电视、投影仪等设备中;而无线电遥控设备
    华普微HOPERF 2025-01-06 15:29 172浏览
  • By Toradex 秦海1). 简介嵌入式平台设备基于Yocto Linux 在开发后期量产前期,为了安全以及提高启动速度等考虑,希望将 ARM 处理器平台的 Debug Console 输出关闭,本文就基于 NXP i.MX8MP ARM 处理器平台来演示相关流程。 本文所示例的平台来自于 Toradex Verdin i.MX8MP 嵌入式平台。  2. 准备a). Verdin i.MX8MP ARM核心版配合Dahlia载板并
    hai.qin_651820742 2025-01-07 14:52 111浏览
  • 村田是目前全球量产硅电容的领先企业,其在2016年收购了法国IPDiA头部硅电容器公司,并于2023年6月宣布投资约100亿日元将硅电容产能提升两倍。以下内容主要来自村田官网信息整理,村田高密度硅电容器采用半导体MOS工艺开发,并使用3D结构来大幅增加电极表面,因此在给定的占位面积内增加了静电容量。村田的硅技术以嵌入非结晶基板的单片结构为基础(单层MIM和多层MIM—MIM是指金属 / 绝缘体/ 金属) 村田硅电容采用先进3D拓扑结构在100um内,使开发的有效静电容量面积相当于80个
    知白 2025-01-07 15:02 145浏览
  • 大模型的赋能是指利用大型机器学习模型(如深度学习模型)来增强或改进各种应用和服务。这种技术在许多领域都显示出了巨大的潜力,包括但不限于以下几个方面: 1. 企业服务:大模型可以用于构建智能客服系统、知识库问答系统等,提升企业的服务质量和运营效率。 2. 教育服务:在教育领域,大模型被应用于个性化学习、智能辅导、作业批改等,帮助教师减轻工作负担,提高教学质量。 3. 工业智能化:大模型有助于解决工业领域的复杂性和不确定性问题,尽管在认知能力方面尚未完全具备专家级的复杂决策能力。 4. 消费
    丙丁先生 2025-01-07 09:25 122浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦