Linux系统移植篇4:STM32MP1微处理器之Bootloader移植
BootLoader(Uboot)移植
实验原理
概念
简单地说,Bootloader就是在操作系统内核运行之前运行的一段程序,它类似于PC机中的BIOS程序。通过这段程序,可以完成硬件设备的初始化,并建立内存空间的映射图的功能,从而将系统的软硬件环境带到一个合适的状态,为最终调用系统内核做好准备。
通常,Bootloader是严重地依赖于硬件实现的,特别是在嵌入式中。因此,在嵌入式世界里建立一个通用的Bootloader几乎是不可能的。尽管如此,仍然可以对Bootloader归纳出一些通用的概念来指导用户特定的Bootloader设计与实现。
(1)Bootloader所支持的CPU和嵌入式开发板
每种不同的CPU体系结构都有不同的Bootloader。有些Bootloader也支持多种体系结构的CPU,如后面要介绍的U-Boot就同时支持ARM体系结构和MIPS体系结构。除了依赖于CPU的体系结构外,Bootloader实际上也依赖于具体的嵌入式板级设备的配置。
(2)Bootloader的安装媒介
系统加电或复位后,所有的CPU通常都从某个由CPU制造商预先安排的地址上取指令。而基于CPU构建的嵌入式系统通常都有某种类型的固态存储设备(比如ROM、EEPROM或FLASH等)被映射到这个预先安排的地址上。因此在系统加电后,CPU将首先执行Bootloader程序。
(3)Bootloader的启动过程分为单阶段和多阶段两种。通常多阶段的Bootloader能提供更为复杂的功能,以及更好的可移植性。
(4)Bootloader的操作模式。大多数Bootloader都包含两种不同的操作模式:“启动加载”模式和“下载”模式,这种区别仅对于开发人员才有意义。
• 启动加载模式:这种模式也称为“自主”模式。也就是Bootloader从目标机上的某个固态存储设备上将操作系统加载到RAM中运行,整个过程并没有用户的介入。这种模式是嵌入式产品发布时的通用模式。
• 下载模式:在这种模式下,目标机上的Bootloader将通过串口连接或网络连接等通信手段从主机(Host)下载文件,比如:下载内核映像和根文件系统映像等。从主机下载的文件通常首先被Bootloader保存到目标机的RAM中,然后再被Bootloader写到目标机上的FLASH类固态存储设备中。Bootloader的这种模系统是在更新时使用。工作于这种模式下的Bootloader通常都会向它的终端用户提供一个简单的命令行接口。
(5)Bootloader与主机之间进行文件传输所用的通信设备及协议,最常见的情况就是,目标机上的Bootloader通过串口与主机之间进行文件传输,传输协议通常是xmodem/ ymodem/zmodem协议中的一种。但是,串口传输的速度是有限的,因此通过以太网连接并借助TFTP协议来下载文件是个更好的选择。
Bootloader启动流程
Bootloader的启动流程一般分为两个阶段:stage1和stage2,下面分别对这两个阶段进行讲解:
(1)Bootloader的stage1
在stage1中Bootloader主要完成以下工作。
• 基本的硬件初始化,包括屏蔽所有的中断、设置CPU的速度和时钟频率、RAM初始化、初始化LED、关闭CPU内部指令和数据cache灯。
• 为加载stage2准备RAM空间,通常为了获得更快的执行速度,通常把stage2加载到RAM空间中来执行,因此必须为加载Bootloader的stage2准备好一段可用的RAM空间范围。
• 拷贝stage2到RAM中,在这里要确定两点:①stage2的可执行映像在固态存储设备的存放起始地址和终止地址;②RAM空间的起始地址。
• 设置堆栈指针sp,这是为执行stage2的C语言代码做好准备。
(2)Bootloader的stage2
在stage2中Bootloader主要完成以下工作。
• 用汇编语言跳转到main入口函数
由于stage2的代码通常用C语言来实现,目的是实现更复杂的功能和取得更好的代码可读性和可移植性。但是与普通C语言应用程序不同的是,在编译和链接Bootloader这样的程序时,不能使用glibc库中的任何支持函数。
• 初始化本阶段要使用到的硬件设备,包括初始化串口、初始化计时器等。在初始化这些设备之前、可以输出一些打印信息。
• 检测系统的内存映射,所谓内存映射就是指在整个4GB物理地址空间中有指出哪些地址范围被分配用来寻址系统的RAM单元。
• 加载内核映像和根文件系统映像,这里包括规划内存占用的布局和从Flash上拷贝数据。
• 设置内核的启动参数。
Bootloader的种类
嵌入式系统世界已经有各种各样的Bootloader,种类划分也有多种方式。除了按照处理器体系结构不同划分以外,还有功能复杂程度的不同。
首先区分一下“Bootloader”和“Monitor”的概念。严格来说,“Bootloader”只是引导设备并且执行主程序的固件;而“Monitor”还提供了更多的命令行接口,可以进行调试、读写内存、烧写Flash、配置环境变量等。“Monitor”在嵌入式系统开发过程中可以提供很好的调试功能,开发完成以后,就完全设置成了一个“Bootloader”。所以,习惯上大家把它们统称为Bootloader。
下表列出了Linux的开放源码引导程序及其支持的体系结构。表中给出了X86、ARM、PowerPC体系结构的常用引导程序,并且注明了每一种引导程序是不是“Monitor”。
Bootloader
Monitor
描 述
X86
ARM
PowerPC
LILO
否
Linux磁盘引导程序
是
否
否
GRUB
否
GNU的LILO替代程序
是
否
否
Loadlin
否
从DOS引导Linux
是
否
否
ROLO
否
从ROM引导Linux而不需要BIOS
是
否
否
Etherboot
否
通过以太网卡启动Linux系统的固件
是
否
否
LinuxBIOS
否
完全替代BUIS的Linux引导程序
是
否
否
BLOB
否
LART等硬件平台的引导程序
否
是
否
U-Boot
是
通用引导程序
是
是
是
RedBoot
是
基于eCos的引导程序
是
是
是
对于每种体系结构,都有一系列开放源码Bootloader可以选用。
(1)X86
X86的工作站和服务器上一般使用LILO和GRUB。LILO是Linux发行版主流的Bootloader。不过Redhat Linux发行版已经使用了GRUB,GRUB比LILO有更友好的显示接口,使用配置也更加灵活方便。
在某些X86嵌入式单板机或者特殊设备上,会采用其他的Bootloader,如ROLO。这些Bootloader可以取代BIOS的功能,能够从Flash中直接引导Linux启动。现在ROLO支持的开发板已经并入U-Boot,所以U-Boot也可以支持X86平台。
(2)ARM
ARM处理器的芯片商很多,所以每种芯片的开发板都有自己的Bootloader。结果ARM Bootloader也变得多种多样。最早有为ARM720处理器的开发板的固件,又有了armboot,StrongARM平台的BLOB,还有S3C2410处理器开发板上的vivi等。现在armboot已经并入了U-Boot,所以U-Boot也支持ARM/XSCALE平台。U-Boot已经成为ARM平台事实上的标准Bootloader。
(3)PowerPC
PowerPC平台的处理器有标准的Bootloader,就是PPCBOOT。PPCBOOT在合并armboot等之后,创建了U-Boot,成为各种体系结构开发板的通用引导程序。U-Boot仍然是PowerPC平台的主要Bootloader。
(4)MIPS
MIPS公司开发的YAMON是标准的Bootloader,也有许多MIPS芯片商为自己的开发板写了Bootloader。现在,U-Boot也已经支持MIPS平台。
(5)SH
SH平台的标准Bootloader是sh-boot。RedBoot在这种平台上也很好用。
(6)M68K
M68K平台没有标准的Bootloader。RedBoot能够支持M68K系列的系统。
值得说明的是RedBoot,它几乎能够支持所有的体系结构,包括MIPS、SH、M68K等。RedBoot是以eCos为基础,采用GPL许可的开源软件工程。现在由core eCos的开发人员维护,源码下载网站是http://www.ecoscentric.com/snapshots。RedBoot的文档也相当完善,有详细的使用手册《RedBoot User’s Guide》。
U-Boot概述
U-Boot(UniversalBootloader),是遵循GPL条款的开放源码项目。它是从FADSROM、8xxROM、PPCBOOT逐步发展演化而来。其源码目录、编译形式与Linux内核很相似,事实上,不少U-Boot源码就是相应的Linux内核源程序的简化,尤其是一些设备的驱动程序,这从U-Boot源码的注释中能体现这一点。但是U-Boot不仅仅支持嵌入式Linux系统的引导,而且还支持NetBSD、VxWorks、QNX、RTEMS、ARTOS、LynxOS嵌入式操作系统。其目前要支持的目标操作系统是OpenBSD、NetBSD、FreeBSD、4.4BSD、Linux、SVR4、Esix、Solaris、Irix、SCO、Dell、NCR、VxWorks,LynxOS、pSOS、QNX、RTEMS、ARTOS。这是U-Boot中Universal的一层含义,另外一层含义则是U-Boot除了支持PowerPC系列的处理器外,还能支持MIPS、x86、ARM、NIOS、XScale等诸多常用系列的处理器。这两个特点正是U-Boot项目的开发目标,即支持尽可能多的嵌入式处理器和嵌入式操作系统。就目前为止,U-Boot对PowerPC系列处理器支持最为丰富,对Linux的支持最完善。
U-Boot的特点如下。
• 开放源码;
• 支持多种嵌入式操作系统内核,如Linux、NetBSD、VxWorks、QNX、RTEMS、ARTOS、LynxOS;
• 支持多个处理器系列,如PowerPC、ARM、x86、MIPS、XScale;
• 较高的可靠性和稳定性;
• 高度灵活的功能设置,适合U-Boot调试,操作系统不同引导要求,产品发布等;
• 丰富的设备驱动源码,如串口、以太网、SDRAM、FLASH、LCD、NVRAM、EEPROM、RTC、键盘等;
• 较为丰富的开发调试文档与强大的网络技术支持。
U-Boot可支持的主要功能列表。
• 系统引导:支持NFS挂载、RAMDISK(压缩或非压缩)形式的根文件系统。支持NFS挂载,并从FLASH中引导压缩或非压缩系统内核。
• 基本辅助功能:强大的操作系统接口功能;可灵活设置、传递多个关键参数给操作系统,适合系统在不同开发阶段的调试要求与产品发布,尤其对Linux支持最为强劲;支持目标板环境参数多种存储方式,如FLASH、NVRAM、EEPROM;CRC32校验,可校验FLASH中内核、RAMDISK镜像文件是否完好。
• 设备驱动:串口、SDRAM、FLASH、以太网、LCD、NVRAM、EEPROM、键盘、USB、PCMCIA、PCI、RTC等驱动支持。
• 上电自检功能:SDRAM、FLASH大小自动检测;SDRAM故障检测;CPU型号。
• 特殊功能:XIP内核引导。
U-Boot的常用命令
U-Boot上电启动后,按任意键可以退出自动启动状态,进入命令行。
U-Boot 2020.01-stm32mp-r1 (Aug 05 2020 - 05:32:37 +0000)
CPU: STM32MP157AAA Rev.B
Model: HQYJ FS-MP1A Discovery Board
Board: stm32mp1 in trusted mode (st,stm32mp157a-fsmp1a)
DRAM: 512 MiB
Clocks:
- MPU : 650 MHz
- MCU : 208.878 MHz
- AXI : 266.500 MHz
- PER : 24 MHz
- DDR : 533 MHz
WDT: Started with servicing (32s timeout)
NAND: 0 MiB
MMC: STM32 SD/MMC: 0, STM32 SD/MMC: 1
Loading Environment from MMC... OK
In: serial
Out: serial
Err: serial
Net: eth0: ethernet@5800a000
Hit any key to stop autoboot: 0
STM32MP>
在命令行提示符下,可以输入U-Boot的命令并执行。U-Boot可以支持几十个常用命令,通过这些命令,可以对开发板进行调试,可以引导Linux内核,还可以擦写Flash完成系统部署等功能。掌握这些命令的使用,才能够顺利地进行嵌入式系统的开发。
输入help命令,可以得到当前U-Boot的所有命令列表。每一条命令后面是简单的命令说明。
STM32MP> help
? - alias for 'help'
adc - ADC sub-system
base - print or set address offset
bdinfo - print Board Info structure
blkcache- block cache diagnostics and control
bmp - manipulate BMP image data
bootefi - Boots an EFI payload from memory
bootm - boot application image from memory
bootp - boot image via network using BOOTP/TFTP protocol
bootz - boot Linux zImage image from memory
chpart - change active partition
clk - CLK sub-system
cls - clear screen
cmp - memory compare
coninfo - print console devices and information
cp - memory copy
crc32 - checksum calculation
date - get/set/reset date & time
dcache - enable or disable data cache
dfu - Device Firmware Upgrade
dhcp - boot image via network using DHCP/TFTP protocol
dm - Driver model low level access
dtimg - manipulate dtb/dtbo Android image
echo - echo args to console
editenv - edit environment variable
env - environment handling commands
erase - erase FLASH memory
exit - exit script
ext2load- load binary file from a Ext2 filesystem
ext2ls - list files in a directory (default /)
ext4load- load binary file from a Ext4 filesystem
ext4ls - list files in a directory (default /)
ext4size- determine a file's size
ext4write- create a file in the root directory
false - do nothing, unsuccessfully
fastboot- run as a fastboot usb or udp device
fatinfo - print information about filesystem
fatload - load binary file from a dos filesystem
fatls - list files in a directory (default /)
fatsize - determine a file's size
fdt - flattened device tree utility commands
flinfo - print FLASH memory information
fstype - Look up a filesystem type
fuse - Fuse sub-system
go - start application at address 'addr'
gpio - query and control gpio pins
gpt - GUID Partition Table
help - print command description/usage
i2c - I2C sub-system
icache - enable or disable instruction cache
itest - return true/false on integer compare
lcdputs - print string on video framebuffer
led - manage LEDs
load - load binary file from a filesystem
loadb - load binary file over serial line (kermit mode)
loads - load S-Record file over serial line
loadx - load binary file over serial line (xmodem mode)
loady - load binary file over serial line (ymodem mode)
loop - infinite loop on address range
ls - list files in a directory (default /)
md - memory display
mdio - MDIO utility commands
meminfo - display memory information
mii - MII utility commands
mm - memory modify (auto-incrementing address)
mmc - MMC sub system
mmcinfo - display MMC info
mtdparts- define flash/nand partitions
mtest - simple RAM read/write test
mw - memory write (fill)
nand - NAND sub-system
nboot - boot from NAND device
nfs - boot image via network using NFS protocol
nm - memory modify (constant address)
part - disk partition related commands
ping - send ICMP ECHO_REQUEST to network host
pinmux - show pin-controller muxing
pmic - PMIC sub-system
poweroff- Perform POWEROFF of the device
printenv- print environment variables
protect - enable or disable FLASH write protection
pxe - commands to get and boot from pxe files
regulator- uclass operations
reset - Perform RESET of the CPU
rproc - Control operation of remote processors in an SoC
run - run commands in an environment variable
save - save file to a filesystem
saveenv - save environment variables to persistent storage
setcurs - set cursor position within screen
setenv - set environment variables
setexpr - set environment variable as the result of eval expression
sf - SPI flash sub-system
showvar - print local hushshell variables
size - determine a file's size
sleep - delay execution for some time
source - run script from memory
sspi - SPI utility command
stboard - read/write board reference in OTP
stm32key- Fuse ST Hash key
stm32prog- <link> <dev> [<addr>] [<size>]
start communication with tools STM32Cubeprogrammer on <link> with Flashlayout at <addr>
sysboot - command to get and boot from syslinux files
test - minimal test like /bin/sh
tftpboot- boot image via network using TFTP protocol
time - run commands and summarize execution time
timer - access the system timer
true - do nothing, successfully
ubi - ubi commands
ubifsload- load file from an UBIFS filesystem
ubifsls - list files in a directory
ubifsmount- mount UBIFS volume
ubifsumount- unmount UBIFS volume
ums - Use the UMS [USB Mass Storage]
usb - USB sub-system
usbboot - boot from USB device
version - print monitor, compiler and linker version
STM32MP>
U-Boot还提供了更加详细的命令帮助,通过help命令还可以查看每个命令的参数说明。由于开发过程的需要,有必要先把U-Boot命令的用法弄清楚。
实验目的
熟悉交叉工具链的使用、u-boot常用命令、u-boot的代码结构和移植方法。
实验平台
华清远见开发环境,FS-MP1A平台
实验步骤
本实验基于u-boot 2020.01版本,然后添加意法半导体提供的补丁文件。在意法半导体官方的u-boot中移植我们自己的u-boot。
导入源码
建立源码目录
linux@ubuntu:$ cd ~
linux@ubuntu:$ mkdir FS-MP1A
将【华清远见-FS-MP1A开发资料\02-程序源码\04-Linux系统移植\01-官方源码】下的en.SOURCES-stm32mp1-openstlinux-5-4-dunfell-mp1-20-06-24.tar.xz压缩包,导入到ubuntu下的${HOME}/FS-MP1A目录下。
解压缩源码包
linux@ubuntu:$ tar xvf en.SOURCES-stm32mp1-openstlinux-5-4-dunfell-mp1-20-06-24.tar.xz
解压完成后得到“stm32mp1-openstlinux-5.4-dunfell-mp1-20-06-24”目录
进入uboot目录下
linux@ubuntu:$ cd ~/FS-MP1A/stm32mp1-openstlinux-5.4-dunfell-mp1-20-06-24/sources/arm-ostl-linux-gnueabi/u-boot-stm32mp-2020.01-r0
该目录下以patch结尾的文件为ST官方提供的补丁文件;u-boot-stm32mp-2020.01-r0.tar.gz为标准u-boot源码包。
解压标准u-boot源码包
linux@ubuntu:$ tar -xvf u-boot-stm32mp-2020.01-r0.tar.gz
解压完成后得到u-boot-stm32mp-2020.01目录
进入u-boot源码目录下:
linux@ubuntu:$ cd u-boot-stm32mp-2020.01
将ST官方补丁文件打到u-boot源码中:
linux@ubuntu:$ for p in `ls -1 ../*.patch`; do patch -p1 < $p; done
TF卡分区
要对TF卡进行烧录,需要先将TF接入到ubuntu系统中。
查看TF卡分区
linux@ubuntu:$ ls /dev/sd*
由上图所示只有“/dev/sdb1”一个分区则需要重新进行分区。
首先删除原有分区
linux@ubuntu:$ sudo parted -s /dev/sdb mklabel msdos
如果显示如下内容,则表示设备已经被挂载,需要卸载掉设备再删除分区。
卸载设备
linux@ubuntu:$ umount /dev/sdb1
卸载完成后重新执行删除分区命令
linux@ubuntu:$ sudo parted -s /dev/sdb mklabel msdos
对tf进行重新分区
linux@ubuntu:$ sudo sgdisk --resize-table=128 -a 1 -n 1:34:545 -c 1:fsbl1 -n 2:546:1057 -c 2:fsbl2 -n 3:1058:5153 -c 3:ssbl -n 4:5154:136225 -c 4:bootfs -n 5:136226 -c 5:rootfs -A 4:set:2 -p /dev/sdb -g
注意:最后-p /dev/sdb参数中的/dev/sdb需要按照实际ubuntu中的tf节点为准,否则可能发生不可预料的后果。
建立自己的平台
配置工具链导入交叉编译工具链(如果还未安装SDK可参考《SDK工具链安装》章节进行安装)
linux@ubuntu:$ source /opt/st/stm32mp1/3.1-openstlinux-5.4-dunfell-mp1-20-06-24/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi
验证开发工具是否安装正确,显示版本信息如下图所示。
linux@ubuntu:$ $CC --version
进入到u-boot源码目录
linux@ubuntu:$ cd ~/FS-MP1A/stm32mp1-openstlinux-5.4-dunfell-mp1-20-06-24/sources/arm-ostl-linux-gnueabi/u-boot-stm32mp-2020.01-r0/u-boot-stm32mp-2020.01/
添加自己的默认配置文件
linux@ubuntu:$ cp configs/stm32mp15_basic_defconfig configs/stm32mp15_fsmp1a_basic_defconfig
添加设备树文件
linux@ubuntu:$ cp arch/arm/dts/stm32mp15xx-dkx.dtsi arch/arm/dts/stm32mp15xx-fsmp1x.dtsi
linux@ubuntu:$ cp arch/arm/dts/stm32mp157a-dk1.dts arch/arm/dts/stm32mp157a-fsmp1a.dts
linux@ubuntu:$ cp arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi arch/arm/dts/stm32mp157a-fsmp1a-u-boot.dtsi
修改arch/arm/dts/stm32mp157a-fsmp1a.dts将
#include "stm32mp15xx-dkx.dtsi"
修改为
#include "stm32mp15xx-fsmp1x.dtsi"
修改arch/arm/dts/Makefile,在stm32mp157a-dk1.dtb下添加stm32mp157a-fsmp1a的内容:
使用新添加的默认配置:
linux@ubuntu:$ make stm32mp15_fsmp1a_basic_defconfig
可以使用make menuconfig进行图形化配置
执行如下指令编译u-boot:
linux@ubuntu:$ make DEVICE_TREE=stm32mp157a-fsmp1a all
编译成功后,最后显示内容(部分截图)如下:
编译完成后会得到如下文件:
由于在移植过程中会多次烧写固件并且会导致正常u-boot无法启动,因此推荐使用TF卡启动的方式来验证。
将TF接入ubuntu系统后,查看TF卡分区
linux@ubuntu:$ ls /dev/sd*
/dev/sdb为TF卡设备。如果该设备下只有/dev/sdb1一个分区则重新分区。
执行如下指令烧写u-boot:
linux@ubuntu:$ sudo dd if=u-boot-spl.stm32 of=/dev/sdb1 conv=fdatasync
linux@ubuntu:$ sudo dd if=u-boot-spl.stm32 of=/dev/sdb2 conv=fdatasync
linux@ubuntu:$ sudo dd if=u-boot.img of=/dev/sdb3 conv=fdatasync
启动开发板将拨码开关设置为SD卡启动方式:
Boot mode
BOOT2
BOOT1
BOOT0
Engineering boot
1
0
0
Forced USB bootfor flashing
0
0
0
eMMC
0
1
0
SDCARD
1
0
1
将制作好的TF卡插入开发板,上电后会出现如下错误提示:
错误提示电源初始化错误,需重新调整电源相关配置
调整设备树电源配置
由于官方参考板DK1采用电源管理芯片做电源管理,而FS-MP1A采用分离电路作为电源管理,本例需要将文件中原有电源管理芯片相关内容去掉,增加上固定电源相关内容
去掉原有电源管理内容DK1参考板电源管理芯片挂在I2C4上,而FS-MP1A并未使用I2C4总线,所以直接将I2C4相关内容完全删除即可。
修改arch/arm/dts/stm32mp15xx-fsmp1x.dtsi文件
将文件中i2c4节点相关内容整体删除,删除内容如下:
&i2c4 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c4_pins_a>;
pinctrl-1 = <&i2c4_pins_sleep_a>;
i2c-scl-rising-time-ns = <185>;
i2c-scl-falling-time-ns = <20>;
clock-frequency = <400000>;
status = "disabled";
/*内容太长此处省略*/
watchdog {
compatible = "st,stpmic1-wdt";
status = "disabled";
};
};
};
修改arch/arm/dts/stm32mp15xx-fsmp1x.dtsi文件,删除如下内容:
&cpu0{
cpu-supply = <&vddcore>;
};
&cpu1{
cpu-supply = <&vddcore>;
};
修改arch/arm/dts/stm32mp157a-fsmp1a-u-boot.dtsi
文件
删除如下内容:
&pmic {
u-boot,dm-pre-reloc;
};
由于官方参考板DK1 I2C4总线上有个USB type C的控制器,上文删除I2C4节点的同时将type C控制器的描述删除,所以需要将引用type C控制器的内容删掉。
修改arch/arm/dts/stm32mp15xx-fsmp1x.dtsi文件,删除红色部分内容:
&usbotg_hs {
phys = <&usbphyc_port1 0>;
phy-names = "usb2-phy";
usb-role-switch;
status = "okay";
port {
usbotg_hs_ep: endpoint {
remote-endpoint = <&con_usbotg_hs_ep>;
};
};
};
添加固定电源配置修改arch/arm/dts/stm32mp15xx-fsmp1x.dtsi文件
固定电源配置通常添加在根节点下,在根节点末尾位置添加如下内容(红色字体为需要添加的内容):
vin: vin {
compatible = "regulator-fixed";
regulator-name = "vin";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-always-on;
};
v3v3: regulator-3p3v {
compatible = "regulator-fixed";
regulator-name = "v3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
};
v1v8_audio: regulator-v1v8-audio {
compatible = "regulator-fixed";
regulator-name = "v1v8_audio";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
regulator-boot-on;
};
v3v3_hdmi: regulator-v3v3-hdmi {
compatible = "regulator-fixed";
regulator-name = "v3v3_hdmi";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
};
v1v2_hdmi: regulator-v1v2-hdmi {
compatible = "regulator-fixed";
regulator-name = "v1v2_hdmi";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
regulator-always-on;
regulator-boot-on;
};
vdd: regulator-vdd {
compatible = "regulator-fixed";
regulator-name = "vdd";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
};
vdd_usb: regulator-vdd-usb {
compatible = "regulator-fixed";
regulator-name = "vdd_usb";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
};
};
配置ubootlinux@ubuntu:$ make menuconfig
去掉PMIC的配置选项,按空格将方括号内*号去掉:
Device Drivers --->
Power --->
[ ] Enable support for STMicroelectronics STPMIC1 PMIC
更新配置文件linux@ubuntu:$ cp .config configs/stm32mp15_fsmp1a_basic_defconfig
重新编译源码linux@ubuntu:$ make DEVICE_TREE=stm32mp157a-fsmp1a all
烧写后启动重新烧写后启动现象如下:
提示显示TF卡未被检测到。
TF卡支持
系统检测TF卡拔插是通过CD脚的状态确认,通过原理图可知,TF卡对应MMC1的CD脚是与STM32MP1的PH3连接
对照设备树中MMC1的描述,发现设备树种原有CD脚的配置与FS-MP1A板子不一致,需调整为PH3。
修改arch/arm/dts/stm32mp15xx-fsmp1x.dtsi文件,调整MMC1中CD的配置:
将如下内容
&sdmmc1 {
pinctrl-names = "default", "opendrain", "sleep";
pinctrl-0 = <&sdmmc1_b4_pins_a>;
pinctrl-1 = <&sdmmc1_b4_od_pins_a>;
pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>;
cd-gpios = <&gpiob 7 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
disable-wp;
st,neg-edge;
bus-width = <4>;
vmmc-supply = <&v3v3>;
status = "okay";
};
修改为
&sdmmc1 {
pinctrl-names = "default", "opendrain", "sleep";
pinctrl-0 = <&sdmmc1_b4_pins_a>;
pinctrl-1 = <&sdmmc1_b4_od_pins_a>;
pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>;
cd-gpios = <&gpioh 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
disable-wp;
st,neg-edge;
bus-width = <4>;
vmmc-supply = <&v3v3>;
status = "okay";
};
重新编译烧写后现象如下:
去掉ADC功能
上一小节已经成功启动到了u-boot的控制终端,但是可以看到还有一些错误。本小节将解决如下错误。
官方参考板DK1通过ADC检测开机电流,如果供电电流不足3A则启动失败,FS-MP1A没有设计这个功能,所以需要去掉这部分功能,否则就会报上图中显示的错误,由于u-boot期间ADC主要功能是检测开机电流,这里直接去掉ADC功能即可。
配置uboot去掉ADC功能:按空格键去掉[ ]的星号
linux@ubuntu:$ make menuconfig
Command line interface --->
Device access commands --->
[ ] adc - Access Analog to Digital Converters info and data
Device Drivers --->
[ ] Enable ADC drivers using Driver Model
更新配置文件
linux@ubuntu:$ cp .config configs/stm32mp15_fsmp1a_basic_defconfig
重新编译烧写后adc相关错误已经没有了。
关闭ltdc
由于在u-boot阶段我们不使用显示设备,因此需要将ltdc相关配置关闭。
修改arch/arm/dts/stm32mp15xx-fsmp1x.dtsi文件
<dc {
pinctrl-names = "default", "sleep";
pinctrl-0 = <<dc_pins_a>;
pinctrl-1 = <<dc_pins_sleep_a>;
status = "okay";
port {
#address-cells = <1>;
#size-cells = <0>;
ltdc_ep0_out: endpoint@0 {
reg = <0>;
remote-endpoint = <&sii9022_in>;
};
};
};
修改为
<dc {
pinctrl-names = "default", "sleep";
pinctrl-0 = <<dc_pins_a>;
pinctrl-1 = <<dc_pins_sleep_a>;
status = "disabled";
port {
#address-cells = <1>;
#size-cells = <0>;
ltdc_ep0_out: endpoint@0 {
reg = <0>;
remote-endpoint = <&sii9022_in>;
};
};
};
然后重新编译烧写
有线网卡配置
启动设备进入u-boot控制台之后,可以发现启动信息中有网卡未被发现的错误信息,这个错误是由于u-boot没有设置正确的MAC地址,由启动信息可以看到,启动后网卡的MAC为00:00:00:00:00:00。这是由于在OTP中没有固化默认的MAC地址,解决这个问题可以通过烧写OTP配置来进行默认MAC地址配置,但是由于操作OTP配置的风险较高,如果操作不当可能会导致不可预料的结果。
如果u-boot期间不使用网卡这个错误可以忽略。
如果需要使用网卡解决这个问题比较简单的方法有两个:
U-boot启动后通过命令设置一个MAC地址STM32MP> env set -f ethaddr 1A:1F:DB:0E:69:FD
这种方式设置完成后即刻生效,重启后网卡即可正常工作。
修改include/configs/stm32mp1.h,增加默认环境变量修改如下内容:
#define CONFIG_EXTRA_ENV_SETTINGS \
"bootdelay=1\0" \
"kernel_addr_r=0xc2000000\0" \
"fdt_addr_r=0xc4000000\0" \
"scriptaddr=0xc4100000\0" \
为:
#define CONFIG_EXTRA_ENV_SETTINGS \
"bootdelay=1\0" \
"ethaddr=00:80:E1:42:60:17\0" \
"kernel_addr_r=0xc2000000\0" \
"fdt_addr_r=0xc4000000\0" \
"scriptaddr=0xc4100000\0" \
这种方式需重新编译烧写后才能生效。
重新编译烧写后网卡即可正常工作:
将网线插入开发板中可以进行网络测试。
使用dhcp命令获取ip地址:
STM32MP> dhcp
可以看到这里获取到的ip地址为192.168.11.81
Ping网关测试:
Board gt; ping 192.168.11.1
Ping外网测试:
Board gt; ping 8.8.8.8
eMMC移植
参考原理图可知eMMC使用的是SDMMC2总线,当前所使用的设备树文件中没有SDMMC2的支持,所以需要增加相关内容才能正常驱动eMMC。
由于在使STM32MP1芯片很多管脚为多功能复用管脚,且很多管脚具备同样的功能,所以移植eMMC时需要确认硬件设计是使用的是那些管脚,根据原理图确认后管脚对应关系为:
原理图网络编号
对应管脚
管脚功能
管脚功能码
SD2_DATA0
PB14
SDMMC2_D0
AF9
SD2_DATA1
PB15
SDMMC2_D1
AF9
SD2_DATA2
PB3
SDMMC2_D2
AF9
SD2_DATA3
PB4
SDMMC2_D3
AF9
SD2_DATA4
PA8
SDMMC2_D4
AF9
SD2_DATA5
PA9
SDMMC2_D5
AF10
SD2_DATA6
PE5
SDMMC2_D6
AF9
SD2_DATA7
PD3
SDMMC2_D7
AF9
SD2_CLK
PE3
SDMMC2_CK
AF9
SD2_CMD
PG6
SDMMC2_CMD
AF10
管脚定义在u-boot中STM32MP1默认管脚定义在文件arch/arm/dts/stm32mp15-pinctrl.dtsi中,查看文件中是否有需要的管脚定义:
查看后确认有SDMMC2的管脚定义,且与FS-MP1A硬件使用情况一致,定义如下:
sdmmc2_b4_pins_a: sdmmc2-b4-0 {
pins1 {
pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
<STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
<STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
<STM32_PINMUX('B', 4, AF9)>, /* SDMMC2_D3 */
<STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
slew-rate = <1>;
drive-push-pull;
bias-pull-up;
};
pins2 {
pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
slew-rate = <2>;
drive-push-pull;
bias-pull-up;
};
};
sdmmc2_b4_od_pins_a: sdmmc2-b4-od-0 {
pins1 {
pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
<STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
<STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
<STM32_PINMUX('B', 4, AF9)>; /* SDMMC2_D3 */
slew-rate = <1>;
drive-push-pull;
bias-pull-up;
};
pins2 {
pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
slew-rate = <2>;
drive-push-pull;
bias-pull-up;
};
pins3 {
pinmux = <STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
slew-rate = <1>;
drive-open-drain;
bias-pull-up;
};
};
sdmmc2_b4_sleep_pins_a: sdmmc2-b4-sleep-0 {
pins {
pinmux = <STM32_PINMUX('B', 14, ANALOG)>, /* SDMMC2_D0 */
<STM32_PINMUX('B', 15, ANALOG)>, /* SDMMC2_D1 */
<STM32_PINMUX('B', 3, ANALOG)>, /* SDMMC2_D2 */
<STM32_PINMUX('B', 4, ANALOG)>, /* SDMMC2_D3 */
<STM32_PINMUX('E', 3, ANALOG)>, /* SDMMC2_CK */
<STM32_PINMUX('G', 6, ANALOG)>; /* SDMMC2_CMD */
};
};
sdmmc2_b4_pins_b: sdmmc2-b4-1 {
pins1 {
pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
<STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
<STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
<STM32_PINMUX('B', 4, AF9)>, /* SDMMC2_D3 */
<STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
slew-rate = <1>;
drive-push-pull;
bias-disable;
};
pins2 {
pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
slew-rate = <2>;
drive-push-pull;
bias-disable;
};
};
sdmmc2_b4_od_pins_b: sdmmc2-b4-od-1 {
pins1 {
pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
<STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
<STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
<STM32_PINMUX('B', 4, AF9)>; /* SDMMC2_D3 */
slew-rate = <1>;
drive-push-pull;
bias-disable;
};
pins2 {
pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
slew-rate = <2>;
drive-push-pull;
bias-disable;
};
pins3 {
pinmux = <STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
slew-rate = <1>;
drive-open-drain;
bias-disable;
};
};
sdmmc2_d47_pins_a: sdmmc2-d47-0 {
pins {
pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */
<STM32_PINMUX('A', 9, AF10)>, /* SDMMC2_D5 */
<STM32_PINMUX('E', 5, AF9)>, /* SDMMC2_D6 */
<STM32_PINMUX('D', 3, AF9)>; /* SDMMC2_D7 */
slew-rate = <1>;
drive-push-pull;
bias-pull-up;
};
};
sdmmc2_d47_sleep_pins_a: sdmmc2-d47-sleep-0 {
pins {
pinmux = <STM32_PINMUX('A', 8, ANALOG)>, /* SDMMC2_D4 */
<STM32_PINMUX('A', 9, ANALOG)>, /* SDMMC2_D5 */
<STM32_PINMUX('E', 5, ANALOG)>, /* SDMMC2_D6 */
<STM32_PINMUX('D', 3, ANALOG)>; /* SDMMC2_D7 */
};
};
增加SDMMC2节点信息修改 arch/arm/dts/stm32mp15xx-fsmp1x.dtsi增加SDMMC2的信息
在原有sdmmc1节点下增加sdmmc2的内容,添加内容可参考arch/arm/dts/stm32mp15xx-edx.dtsi中sdmmc2的写法,内容如下:
&sdmmc2 {
pinctrl-names = "default", "opendrain", "sleep";
pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>;
pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_d47_pins_a>;
pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_d47_sleep_pins_a>;
non-removable;
no-sd;
no-sdio;
st,neg-edge;
bus-width = <8>;
vmmc-supply = <&v3v3>;
vqmmc-supply = <&vdd>;
mmc-ddr-3_3v;
status = "okay";
};
增加mmc映射修改arch/arm/dts/stm32mp157a-fsmp1a-u-boot.dtsi文件,调整启动通道。
修改如下内容:
aliases {
i2c3 = &i2c4;
mmc0 = &sdmmc1;
usb0 = &usbotg_hs;
};
修改为(红色字体为增加内容):
aliases {
i2c3 = &i2c4;
mmc0 = &sdmmc1;
mmc1 = &sdmmc2;
usb0 = &usbotg_hs;
};
在sdmmc1节点后sdmmc2的内容(红色字体部分为添加内容):
&sdmmc1 {
u-boot,dm-spl;
};
&sdmmc2 {
u-boot,dm-spl;
};
测试重新编译烧写后启动信息对比前文多一个MMC:
eMMC的验证需要通过linux更新,相关操作可参考《通过linux更新eMMC中的u-boot》章节。
生成Trusted镜像
前面我们做的相关配置都是基于basic的配置,而实际FS-MP1A使用的uboot是基于Trusted配置的镜像,后边的《Trusted Firmware-A移植》章节会使用到Trusted镜像。
建立基础的Trusted配置文件linux@ubuntu:$ cp configs/stm32mp15_trusted_defconfig configs/stm32mp15_fsmp1a_trusted _defconfig
linux@ubuntu:$ make stm32mp15_fsmp1a_trusted_defconfig
去掉PMIC的配置选项,按空格将方括号内*号去掉:linux@ubuntu:$ make menuconfig
Device Drivers --->
Power --->
[ ] Enable support for STMicroelectronics STPMIC1 PMIC
去掉ADC功能:按空格键去掉[ ]的星号linux@ubuntu:$ make menuconfig
Command line interface --->
Device access commands --->
[ ] adc - Access Analog to Digital Converters info and data
Device Drivers --->
[ ] Enable ADC drivers using Driver Model
修改配置文件linux@ubuntu:$ cp .config configs/stm32mp15_fsmp1a_trusted_defconfig
修改上层目录下的Makefile.sdk编译脚本在UBOOT_CONFIGS配置项中添加“stm32mp15_fsmp1a_trusted_defconfig,trusted,u-boot.stm32”在DEVICE_TREE配置项中添加“stm32mp157a-fsmp1a”UBOOT_CONFIGS ?= stm32mp15_fsmp1a_trusted_defconfig,trusted,u-boot.stm32 stm32mp15_trusted_defconfig,trusted,u-boot.stm32 stm32mp15_trusted_defconfig,optee,u-boot.stm32 stm32mp15_basic_defconfig,basic,u-boot.img
DEVICE_TREE ?= stm32mp157a-fsmp1a stm32mp157a-dk1 stm32mp157d-dk1 stm32mp157c-dk2 stm32mp157f-dk2 stm32mp157c-ed1 stm32mp157f-ed1 stm32mp157a-ev1 stm32mp157c-ev1 stm32mp157d-ev1 stm32mp157f-ev1
编译trusted镜像linux@ubuntu:$ make distclean
linux@ubuntu:$ make -f $PWD/../Makefile.sdk all UBOOT_CONFIGS=stm32mp15_fsmp1a_trusted_defconfig,trusted,u-boot.stm32
linux@ubuntu:$ cd ../ build-trusted
linux@ubuntu:$ ls
u-boot-stm32mp157a-fsmp1a-trusted.stm32即为我们后续会使用的镜像文件。
和主机厂打交道,你怎么能不知道这些英文缩写的意思呢(通用篇)
ADV, APQP, KCDS这些都代表什么意思呢?我们一起看看这些英文缩写。
AAR——外观件批准报告
ADV-DV——ADV设计验证
ADV-P&R——ADV计划和报告
ADV-PV——ADV产品验证
ADV——分析/开发/验证
ALAG——汽车工业行为集团
APO——亚太分部
APQP Project Plan ——APQP项目策划
APQP——产品质量先期策划
APQP——先期产品质量策划
AP——先期采购
AQC——属性质量特性
ASQE——先期供应商质量工程师
BIW——白车身
BOM——材料清单
BOP——过程清单
Brownfield Site——扩建场地
CMM——三坐标测试仪
Complex system/subassembly 复杂系统/分总成
Consignment——集成供货(外协供应商)
CPIP——现行产品改进程序(Current product improvement process)
CPK——过程能力指数
CPV——每辆车索赔费用(cost per vehicle)
CS1——一级受控发运
CS2——二级受控发运
CTC——零部件时间表(DRE)文件
CTS——零件技术规范
CVER——概念车工程发布
CVIS——整车检验标准(complete vehicle inspection standard)
DC——设计完成
Defect outflow detection——缺陷检测
DFM/DFA——可制造/可装配性涉及
DFM/EA——设计失效模式分析
DPV——每辆车缺陷数
DR——DR特性
DRE——设计释放工程师
DRL——一次生产通过率损失
DR——生产质量综合指数(Direct Run)
DV——设计验证
E&APSP——工程&先期采购定点程序
EP——电子采购流程
Error Occurrence Prevention——防错
EWO——工程更改(engineering work order)
EWO——工程更改指令
FE1,2,3——1,2,3功能评估
FMEA——失效模式和后果分析(DFMEA设计;PFMEA生产,MFMEA设备维护)
FTQ——一次通过质量
FTQ——一次质量合格率(First Time Quality)
GA——总装
GCA——全球顾客评审规范(Global customer audit)
GD&T——几何公差&尺寸
GDS——全球交付审查(Global delivery survey)
GM1411—— PPAP临时批准
GMAP——通用汽车亚太
GME——通用汽车欧洲
GMNA——通用汽车欧洲
GM——通用汽车公司、
GP-10——实验室认可
GP-10——试验室认可程序
GP-11——样件批转
GP-11——样件批准
GP-12——早期生产遏制
GP-12——早期生产遏制
GP-4——生产件批准程序
GP-5——供应商质量过程和测量
GP-5——供应商质量过程和测量(问题回复及解决)
GP-8——持续改进
GP-8——持续改进
GP-9——按节拍生产
GP-9——按节拍生产
GPDS——全球产品描述系统
GPSC——全球采购及供应链
GPS——全球采购系统
GP——通用程序
GQTS——全球质量跟踪系统
GR&R——量具的重复性与在再现性
Greenfield Site——新建工厂
GVDP——全球整车开发流程
IPTV——每千辆车缺陷数
IPTV——千辆车故障率(incidents per thousand vehicles)
IVEP——集成车工程发布
IV——OTS
JIS——作业指导书(Job instruction sheets)
KCC——关键控制特性
KCDS——关键特性指示系统
Kick-off Meeting——启动会议(第一次APQP供应商项目评审)
KPC——关键产品特性
LAAM——(通用汽车)拉丁美洲、非洲及中东
LAO——拉丁美洲分部
Layered Process Audit 分层审核
Layered Process Audit——分层审核
LCR——正常生产能力
MC1——FE2
MC2——FE3
MCB——FE1
MCR——最大生产能力
MC——匹配
MOP——制造/采购
MPCE——欧洲物料生产控制
MPC——物料生产控制
MRD——物料需求日期(首次正式交样)
MSA——测量系统分析
MVBns(原NS)——非销售车制造验证
MVBs(原S)——销售车制造验证
N.O.D——决议通知
NAO——北美分部
NBH——停止新业务
OEM——主机客户
OTS——外购国产化零部件和/或系统工程认可程序
PAA——生产行动授权(Production action authorization)
PAD——生产装配文件
PC&L——生产控制&物流
PCR——问题交流报告(Problem Communication Report)
PDI——发运前检查(pre-delivery inspection)、
PDT——产品开发小组
PFMEA——过程失效模式和后果分析
PPAP——生产件批准程序
PPAP——生产件审批
PPK——过程能力指数
PPM——1)项目经理;2)每白万件的产品缺陷数
PPV——产品及过程验证
PQC——产品质量特性
PR/R——问题报告及解决
Pre-Production——预生产
PRR——问题报告和解决(problem report and resolution
PRR——问题交流与解决程序(Problem resolution report)
PSA——潜在供应商评审
PTR——零部件试生产
PTR——生产试运行(Production trial run)
PVV——Trgout
QSA——质量体系评审
QSB——质量体系基础、
QTC——工装报价能力
R&R——按节拍生产
RASIC——负责,批准,支持,通知,讨论
RFQ——报价要求
RPN reduction plan——降低RPN值计划
RPN——风险顺序数
S&R——车辆行驶时摩擦、振动噪音,泛指异响(Squeak&Rattle)
S.T.E.P——采购定点小组评估过程
SDE——供应商开发工程师
SFMEA——系统失效模式分析
SIL——单一问题清单(Single issues list)
SMT——系统管理小组
SOA——加速开始
SOR——(供应商质量)要求声明
SORP——正式生产
SOS——标准作业单(Standardized operation sheets)
SPA——发运前检查(Shipping priority aduit)
SPC——统计过程控制
SPO——(通用汽车)零件与服务分部
SQE——供应商质量工程师
SQIP——供应商质量改进过程
SQ——供应商质量
SSF——系统填充开始
SSTS——分系统技术规范
Sub contactor——分供方
Sub-Assembly/Sub-System
SVER——结构车工程车
SVE——子系统验证工程师
Team feasibility commitment——小组可行性承诺
TKO——模具启动会议
UG——UG工程绘图造型系统
VAP——每辆车开发过程
VLE——车辆平台负责人
VTC——验证试验完成
WDPV——平均每辆车不符合项与权重乘积的综合(平均每辆车扣分值)weighted discrepancies per vehicle
WO——工程工作质量
WWP——全球采购
相关问答
商品管理英文简称?英文缩写:cmmg英文全称:commoditymanagement中文音译:商品管理1、系统按功能横向划分为商品管理子系统、会员管理子系统、管理员子系统。Accordingtoth...
saswell温控器上 system 是什么意思-ZOL问答system是系统的意思有用(0)回复Yuanliqiao代表辅助输显示sub1代表第辅助输触点作状态有用(0)回复kele1977alarm报警reset复位有用(0)...
控制柜并柜是什么意思?电气控制柜[网络]ElectricalCabinet;[例句]电控系统:电气控制柜,分站及气动系统。控制台对控制台咨询的分时Electricalcontrolsystem:electri...
vb怎么使用定时器定时?你说的前面意思没听懂,后面希望毫秒到是可以实现,但微秒不会。上代码:加一个label和一个timer:PrivateDeclareSubGetLocalTimeLib"kerne...
金士顿公司是一家什么样的企业?金士顿(Kingston)科技公司,于1987年由两位工程师杜纪川(JohnTu)和孙大卫(DavidSun)创立于美国。在此之前,两人就曾经拥有从事提供DEC系统相关产品的Camin...
诸位老师 有没有人能告诉我 外贸专业line翻译软件好用吗,li...[回答]上面说360的,360才是真正的垃圾,装了你就别想卸载,垃圾流氓软件从合作到后期的服务做的还是非常周全的。Thesystemconstituteswithinterdependent...
ads是什么?ads是自动化设备规范。在BeckhoffTwinCAT系统中,各个软件模块(如TwinCATPLC、TwinCATNC、Windows应用程序等)的工作模式类似于硬件设备,它们能够独立工...
英语翻译扩散泵电流真空镀膜机总电压蒸发电压蒸发电流轰击电...[回答]扩散泵电流真空镀膜机总电压蒸发电压蒸发电流轰击电流手动/自动轰击选择紧急停车Theproliferationofpumpcurrentvacuumcoatingmachi...
systenmsofequivalentwattage(1 sub -systermperMWP)Everysu...[最佳回答]保留的设计图案分开安置进入相同瓦数的子系统中(每一个工作压力的一个系统).每一个变电所将装两个转换器,允许每一个三位相位器能流通50赫兹的电流...
应该是系统设置,能用U盘启动但windows下决绝访-ZOL问答REGADDHKLM\SYSTEM\CurrentControlSet\Services\USBSTOR/vstart/tREG_DWORD/d3/fcacls%systemro...