【北京迅为】iTOP-4412全能版使用手册-第六十八章 U-boot基础知识
iTOP-4412全能版采用四核Cortex-A9,主频为1.4GHz-1.6GHz,配备S5M8767 电源管理,集成USB HUB,选用高品质板对板连接器稳定可靠,大厂生产,做工精良。接口一应俱全,开发更简单,搭载全网通4G、支持WIFI、蓝牙、陀螺仪、CAN总线、RS485总线、500万摄像头等模块,稳定运行Android 4.0.3/Android 4.4操作,系统通用Linux-3.0.15+Qt操作系统(QT支持5.7版本),Ubuntu版本:12.04,接口智能分配 方便好用。
第五部分 Linux系统移植
本部分将会逐步介绍U-boot基础知识,驱动移植的方法,以及移植Linux内核的步骤(虽然迅为的 4412 开发板已经得到Linux官方(www.kernel.org)的默认支持,但这并不意味这下载完以后可以直接使用,仍需要一些基本的配置和编译)。
第六十八章 U-boot基础知识
68.1 Bootloader简介
在专用的嵌入式目标板上运行 Linux 系统已经变得越来越流行。一个嵌入式 Linux 系统从软件的角度,通常可以分为四个层次。
(1)引导加载程序。包括固化在固件(firmware)中的 boot 代码(可选),和 BootLoader 两大部分。
(2)Linux 内核。特定于目标板的定制内核以及内核的启动参数。
(3)文件系统。包括根文件系统和建立于 Flash 内存设备之上的文件系统。
(4)用户应用程序。特定于用户的应用程序。有时在用户应用程序和内核层之间可能还会包括一个嵌入式图形用户界面。
引导加载程序是系统加电后运行的第一段软件代码。例如没在 PC 机中的引导加载程序由BIOS(其本质就是一段固件程序)和位于硬盘 MBR 中的 OS BootLoader(比如,LILO 和GRUB 等)一起组成。BIOS 在完成硬件检测和资源分配后,将硬盘 MBR 中的 BootLoader 读到系统的 RAM 中,然后将控制权交给 OS BootLoader。BootLoader 的主要运行任务就是将内核映象从硬盘上读到 RAM 中,然后跳转到内核的入口点去运行,也即开始启动操作系统。
而在嵌入式系统中,通常并没有像 BIOS 那样的固件程序(注,有的嵌入式 CPU 也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由 BootLoader 来完成。
简单地说,BootLoader 就是在操作系统内核运行之前运行的一段小程序,功能类似BIOS。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。
注意由于 BootLoader 是严重地依赖于硬件而实现的,因此,在嵌入式世界里建立一个通用的 BootLoader 几乎是不可能的。
68.2 Bootloader的种类
嵌入式系统世界已经有各种各样的 Bootloader,种类划分也有多种方式。除了按照处理器体系结构不同划分以外,还有功能复杂程度的不同。
首先区分一下“Bootloader”和“Monitor”的概念。严格来说,“Bootloader”只是引导设备并且执行主程序的固件;而“Monitor”还提供了更多的命令行接口,可以进行调试、读写内存、烧写 Flash、配置环境变量等。“Monitor”在嵌入式系统开发过程中可以提供很好的调试功能,开发完成以后,就完全设置成了一个“Bootloader”。所以,习惯上大家把它们统称为 Bootloader。下表列出了 Linux 的开放源码引导程序及其支持的体系结构。表中给出了 X86 、ARM、PowerPC 体系结构的常用引导程序。
Bootloader | 描述 | 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 可以选用。
68.3 U-boot源码结构
解压就可以得到全部 Uboot 源程序。在顶层目录下有 18 个子目录,分别存放和管理不同的源程序。这些目录中所要存放的文件有其规则,可以分为 3 类。
第 1 类目录与处理器体系结构或者开发板硬件直接相关;
第 2 类目录是一些通用的函数或者驱动程序;
第 3 类目录是 Uboot 的应用程序、工具或者文档。下表列出了 Uboot 顶层目录下各级目录存放原则。
下表列出了 Uboot 顶层目录下各级目录存放原则。
目 录 | 特 性 | 解 释 说 明 |
board | 平台依赖 | 存放电路板相关的目录文件,例如:cpu86、smdk210、samsung 等目录 |
cpu | 平台依赖 | 存放 CPU 相关的目录文件,例如:mpc8xx、ppc4xx、arm720t、mips、xscale、i386 等目录 |
lib_ppc | 平台依赖 | 存放对 PowerPC 体系结构通用的文件,主要用于实现PowerPC 平台通用的函数 |
lib_arm | 平台依赖 | 存放对 ARM 体系结构通用的文件,主要用于实现 ARM 平台通用的函数 |
lib_i386 | 平台依赖 | 存放对 X86 体系结构通用的文件,主要用于实现 X86 平台通用的函数 |
include | 通用 | 头文件和开发板配置文件,所有开发板的配置文件都在configs 目录下 |
common | 通用 | 通用的多功能函数实现 |
lib_generic | 通用 | 通用库函数的实现 |
net | 通用 | 存放网络的程序 |
fs | 通用 | 存放文件系统的程序 |
post | 通用 | 存放上电自检程序 |
drivers | 通用 | 通用的设备驱动程序 |
disk | 通用 | 硬盘接口程序 |
examples | 应用例程 | 一些独立运行的应用程序例子 |
tools | 工具 | 存放制作 S-Record 或者 U-Boot 格式的映像等工具,例如 mkimage |
doc | 文档 | 开发使用文档 |
U-boot 的源代码包含对几十种处理器、数百种开发板的支持。对于特定的开发板,配置编译过程只需要其中部分程序。
68.4 U-boot分析
本节从理论上分析关于 Uboot 启动的一些基础知识。
下图中可以看出,Uboot 引导程序分为 BL1、BL2、U-boot、TZSW 四个部分。
另外可以看到 Booting 分区有严格的规定,BL1 部分是 15KB,BL2 部分是 16KB,U- boot 是 328K。例如,Uboot 部分最终需要做补齐的,就是补齐到 328K。Uboot 不论怎么编译都是 328K。
Uboot 分段启动
下图是 exnoys4412 Datasheet 中和启动相关的框图。
如上图所示,通过控制启动模式(OM),处理器上电以后,开始执行 IROM 中的代码, 这段代码是原厂三星固化在芯片中,是无法修改的。
由上图可知,BL1 可以放在 4 个引导设备中:NAND、SD/MMC、eMMC、USB。
IROM 启动以后,会去找 BL1,也就是 bootloader1,BL1 执行完以后会去找 BL2。BL2 会运行 Uboot,Uboot 引导 Linux 内核,内核启动完毕,Uboot 的生命周期完全结束。运行顺 序 为 :IROM--->BL1----->BL2---->Uboot >Linux 。
整个 Uboot 是分段启动。BL1 运行在 IRAM(不是 IROM)中,不要将 IRAM 误解为DDR3 内存,因为这个时候 DDR3 还没有被初始化,就是说 DDR3 的控制器还没有初始化。IRAM 是可以上电就能使用的,可以这样理解,iRAM 就是 4412 芯片内部特殊的 RAM,不用初始化就能用。iRAM 造价高,所以很小,总共才 256K,所以不能把操作系统装进来,甚至无法将 Uboot 全部运行,要分段去启动,这样就分成了 BL1 和 BL2。
BL1 的安全性分析
bootloader 在系统启动的最前面运行,如果 bootloader 被攻破的话,危险级别几乎都会是致命的,所以这部分内容也一直是黑客们进行漏洞挖掘的领域。
智能机的安全问题越来越重要,手机中如果在 Uboot 中被“种”了病毒,病毒把通讯录或者私密视频到处网上发等,关键是“种”的病毒是无法杀掉的。可以这么说如果能够控制bootloader,那么 iphone 的越狱、Android 的 root 以及在手机上安装第三方的 ROM 就都不成问题。bootloader 是安全问题的重中之重,要保护 bootloader 的安全,防止bootloader 被篡改。
出于安全性考虑,在上电启动执行 IROM 程序以后,加载 BL1 的时候,要对 BL1 进行多种安全检验,防止 BL1 是假的,然后 BL1 会对 BL2 进行各种检验,直至操作系统 Linux ,这样保证整个系统是干净五毒的!下图是 BL1 的结构。
如下图所示,最上面的 16 个字节,number of sector(BL1 size) 也就是 BL1 的大小, Checksum Value 也就是累加和校验。就是说把整个 BL1 主体部分的内容累加和放到这里,然后实际计算下整个累加和,做对比,如果不对,就说明 BL1 是假的或错误的,不予执行。
然后是 BL1 的第二部分,如下图所示。就算第一部分能作假,看下 BL1 的第二部分Encrypted BL1,实际就是经过加密的 BL1 代码,在 Uboot 中这部分没有源码,只有二进制文件,这段二进制文件由三星提供。
如下图所示,BL1 的第三部分,这里放了客户和三星的公钥以及签名文件。
经过分析可知,在三星 bootloader 给用户提供了三重安全保障。
BL2 分析
BL2 的结构如下图所示。BL2 Binary 部分其实就是 14K,然后下面是 chechsum(校 验),signature(签名),Padding(补齐)。可以看到 BL2 的主体部分没有加密,但下面有签名。
Padding(补齐),需要将 BL2 代码扩充到 16K,补齐部分全部使用 00000000。在 Uboot 的 makefile 编 译 文 件 中 , 有 下 面 几 句 编 译 命 令 :
@./sdfuse_q/chksum
@./sdfuse_q/add_padding
@rm bl2a*
当 Uboot 生成以后,会通过 add_padding 进行后续处理,通过这个处理后,就补齐了。
需要注意的是,用户的 BL1 和 BL2 是没有经过 secure boot 的,也就是没有的安全认证内容,但是 BL1 和 BL2 本身还是安全的,三星提供了安全保障,BL1 不再对 BL2 进行 secure 认证了。
在 iTOP-4412 开发板 Uboot 源码中,有两个文件需要注意。E4412.TZ.SSCR.EVT1.1.bin 这个就是一个要求认证的 BL1,它会对下级的 BL2 进行签名认证。
Exynos4412_V21.prv BL2这个是私钥来签名,用于对 BL2 的签名
68.5 U-boot 常用命令
Uboot 在硬件初始化完成之后,会进入一个无限循环,等待用户输入命令。U-boot 发展到现在,它的命令行模式已经非常接近 Linux 下的 shell 了。
如下图所示,在控制台使用命令 help 可以查看所有默认支持的命令。
在 iTOP-4412 开发板中,命令如下表所示。
命令 | 功能介绍 |
bdinfo | 打印开发的信息 |
boot | 加载和启动镜像 |
bootd | 同 boot |
bootelf | 引导一段代码到内存 |
bootm | 加载和启动一个应用到内存 |
bootvx | 引导虚拟机的镜像 |
coninfo | 打印串口设备信息 |
echo | 打印变量到控制台 |
ext2load | 加载 Ext2 格式二进制文件 |
ext2ls | 显示目录默认列表 |
go | 启动固定地址的应用 |
iminfo | 打印映像头部信息 |
reset | 重启 |
68.6 裸机程序
裸机程序是指不依赖 Linux 等操作系统,直接在硬件之上运行的程序。比如单片机开发的时候我们写的代码就属于裸机程序。
另外我们也可以把 bootloader 看成是一个裸机程序。因为它的运行不需要操作系统的支持,也是个直接运行在板子硬件之上的程序。
对于初学者来讲,并不推荐学习更多的裸机程序,因为在高端的 ARM 系统开发中一般要基于 Linux 来进行;用裸机程序来开发产品并不能发挥硬件的性能,对自己嵌入式技术的学习也没有多大的帮助。
我们需要用 DNW 驱动来烧写裸机程序,下面我们首先介绍一下 DNW 驱动的安装:
68.6.1 安装DNW驱动
DNW 驱动在网盘“iTOP-4412 开发板视频教程及其相关\09-裸机程序实验文档以及工具文件\tools\USB 驱动\dnw_driver”目录下面,我们提供了 xp 系统、win7-32 位、win7-64 位三种系统下面的驱动。下面我们以 win7 64 位系统的驱动为例来讲解一下DNW 驱动的安装。
首先使用串口线连接 iTOP-4412 开发板的调试串口到 PC 机,使用 USB 连接线连接iTOP-4412 开发板的 USB OTG 接口到 PC 机的 USB 口。
打开“tools”目录下的 dnw.exe 软件。
选择“Serial Port->Connect",连接到 iTOP-4412 开发板的串口,启动开发板,可以看到 dnw 软件会输出启动信息,在 Uboot 进入”倒数秒“的时候,按键盘的任意按键,将进入Uboot 命令行。在 Uboot 的命令行输入“dnw”, 如下图所示。
在 PC 上右键点击“计算机”,选择“管理”, 打开”计算机管理“,然后鼠标点击上图左侧一栏里面的“设备管理器”,将会列出设备列表。
在中间一栏的“其他设备”里,可以看到“SEC S3C6400X Test B/D”这个未知设备, 需要为这个设备安装 DNW 驱动,鼠标右键点击“SEC S3C6400X Test B/D”选择“更新驱动程序软件(P)...”,如下图所示。
打开“更新驱动程序软件”对话框,然后选择“浏览计算机以查找驱动程序软件(R)”, 将会显示弹出如下图所示对话框。
点击上图的”浏览“,找到驱动,将会出现“windows 安全”的对话框,然后点击的“始终安装此驱动程序软件”,开始安装驱动。
安装完成后,点击“关闭”按钮,关闭对话框。
在设备管理器里面看到 DNW 的设备了,如下图所示:
通过上面的操作,DNW 的驱动已经安装完成了,现在可以使用 DNW 下载裸机程序到开发板。
68.6.2 下载裸机程序到开发板上
重新启动我们的开发板,进入到 Uboot 命令行下面,然后输入“dnw 40008000”(这句的意思是启动 DNW,设置程序下载到 0x40008000 地址), 如下图所示:
然后选择“USB Port->Transmit->Transmit”,如下图所示:
弹出传输文件对话框之后,选择裸机程序,这里选择的是”led.bin“程序。led.bin 文件在在网盘“iTOP4412开发板资料汇总(不含光盘内容)\iTOP-4412 开发板视频教程及其相关\09-裸机程序实验文档以及工具文件\tools\例程\led“目录下面。
然后点击“打开”按钮,这时我们在打开“USB Port->Transmit”,可以看到刚才选择的 led.bin,如下图所示。
然后选择上图红色方框内的 led.bin,下载到内存,下载完成后,串口输出如下图所示:
从上图我们可以看到 led.bin 下载到了内存 0x40008000 的地址,接下来在 dnw 软件上输入“go 40008000”使 cpu 从 0x40008000 地址开始运行,如下图所示。
运行上面的命令后,就可以看到 iTOP-4412 开发板上的两个 led 开始交替闪烁了。
68.6.3 裸机led 的程序实现
裸机 led 的程序实现需要启动文件 start.S、代码文件 led.c 和编译文件 Makefile。start.S 文件:
.global _start
_start:
//disable watch dog
ldrr0, =0x10060000
mov r1, #0
str r1, [r0]
//turn on icache
mrc p15, 0, r0, c1, c0, 0
//bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
//bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B CAM) */
//orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
//orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
#ifdef CONFIG_SYS_ICACHE_OFF
// clear bit 12 (I) I-cache
bic r0, r0, #0x00001000
#else
// set bit 12 (I) I-cache
orr r0, r0, #0x00001000
#endif
mcr p15, 0, r0, c1, c0, 0
//mcr p15, 0, r0, c7, c5, 0@ invalidate icache
//set stack
ldrsp, =0x02050000
bl led_blink
halt:
b halt
bl led_blink
halt:
b halt
led.c 文件:
#define GPL2CON (*(volatile unsigned long *) 0x11000100)
#define GPL2DAT (*(volatile unsigned long *) 0x11000104)
#define GPK1CON (*(volatile unsigned long *) 0x11000060)
#define GPK1DAT (*(volatile unsigned long *) 0x11000064)
//GPL2_0, GPK1_1
void delay(int r0)
{
volatile int count = r0;
while (count--)
;
}
void led_blink()
{
GPL2CON = 0x00000001;
GPK1CON = 0x00000010;
while(1)
{
GPL2DAT = 1;
GPK1DAT = 0;
delay(0x80000);
GPL2DAT = 0;
GPK1DAT = 0x2;
delay(0x80000);
}
}
Makefile 文件:
led.bin: start.o led.o
arm-none-linux-gnueabi-ld -Ttext 0x0 -o led.elf $^
arm-none-linux-gnueabi-objcopy -O binary led.elf led.bin
arm-none-linux-gnueabi-objdump -D led.elf > led_elf.dis
%.o : %.S
arm-none-linux-gnueabi-gcc -o $@ $< -c -nostdlib
%.o : %.c
arm-none-linux-gnueabi-gcc -o $@ $< -c -nostdlib clean:
rm *.o *.elf *.bin *.dis -f
68.7 U-boot移植实例
移植需要的资料在文档同一路径下,SEC_Android_Exynos4x12_TC4_uboot.dvt.01.ics.rtm1.0.0.tar.bz2为三星原厂源码,TC4_U-boot.tar.gz为本章移植好的uboot。
本章移植的uboot仅供用来了解uboot,其他用途请使用光盘资料的uboot源码。
68.7.1 移植环境搭建
编译环境使用搭建好的Ubuntu12.04,编译器为arm-2009q3,安装方法参考Android4.0编译章节。
在三星提供的U-boot源码中有三星4412官方开发板(TC4)的移植实例,我们可以参考此开发板的移植方法来移植自己的U-boot。在此实例中以iTOP-4412精英板-SCP-1G为例移植Uboot,参考文档(uboot移植文件夹下):《SEC_[SSCR][TC4]Exynos4x12 driver_developers_guide-uboot_RTM1.0.0.PDF》
将三星提供的U-boot源码压缩包拷贝到ubuntu虚拟机,输入以下命令解压:
tar -vxf SEC_Android_Exynos4x12_TC4_uboot.dvt.01.ics.rtm1.0.0.tar.bz2
如下图:
完成后如下图,
将光盘资料里的06_源码_uboot 和 kernel 下的文件夹CodeSign4SecureBoot_SCP拷贝到与TC4_uboot同一目录下,CodeSign4SecureBoot_SCP文件夹内为三星原厂提供的二进制文件,因为这些二进制文件主要目的是为了保障bootloader 的安全,为用户提供安全保障,所以没有开放源代码。
cp -rf /home/4412/CodeSign4SecureBoot_SCP ./
然后检验搭建的环境是否正确,进入TC4_uboot目录,
修改执行脚本,vi build_uboot.sh,将sec_path改为CodeSign4SecureBoot_SCP,如下图:
保存退出,执行 ./build_uboot.sh tc4_plus,开始编译uboot镜像
完成后生成了 u-boot.bin文件如下图:
生成u-boot.bin说明编译环境没有问题,下面就可以参考TC4的编译脚本build_uboot.sh开始移植自己的uboot。
68.7.2 添加自己的板级文件夹
进入源码顶层的board目录,此下存放着不同芯片厂家板级文件,进入samsung目录,如下图:
cd board/samsung
复制smdkc210为itop4412,itop4412文件夹为自己的板级文件夹,
cp -rf smdkc210 itop4412
进入到itop4412目录,执行以下命令,修改文件名:
mv lowlevel_init.S lowlevel_init_SCP.S
mv smdkc210.c itop4412.c
mv smdkc210_val.h itop4412_val.h
修改Makefile第31行和第33行,改为自己的文件名,
vi Makefile
回到源码顶层目录,进入include/configs目录下,查看TC4开发板的配置文件:
在TC4的基础上改为自己开发板的配置文件,输入以下拷贝命令:
cp tc4_android.h itop_4412.h
回到源码顶层目录,打开链接脚本,
vi cpu/arm_cortexa9/u-boot.lds
如下图:
修改第39行为自己的板级文件夹内的lowlevel_init_SCP.S,
board/samsung/itop4412/lowlevel_init_SCP.o (.text)
完成后回到顶层源码目录 vi Makefile,搜索“tc4”,发现有相关的编译信息,在tc4开发板的上方添加自己开发板的编译选项:
itop_4412_config: unconfig
@$(MKCONFIG) $(@:_config=) arm arm_cortexa9 itop4412 samsung s5pc210
如下图:
itop_4412_config
因为include/configs/下板级配置头文件名字为itop_4412.h,所以Makefile中 添加的是itop_4412_config,该参数在mkconfig中会定义 $1为itop_4412
在脚本末尾会根据$1寻找 include/configs/$1.h,即include/configs/itop_4412.h,
arm arm_cortexa9 itop4412 samsung s5pc210参数含义:
参数 | 释义 | |
$2 | arm | ARCH |
$3 | arm_cortexa9 | CPU |
$4 | itop4412 | 板级文件夹 |
$5 | samsung | Include/samsung/ |
在mkconfig中会根据¥4参数判断板级文件夹为board/samsung/itop4412
mkconfi中第86行$5/$4解析为samsung/itop4412,编译时就会找到自己的文件夹。
68.7.3 配置文件itop4412.h
在include/configs/目录下是各芯片厂家的板级文件夹,itop_4412.h是我们将要修改的文件,与开发板相关的信息如波特率,调试串口,分区相关,fastboot,时钟相关等的宏定义基本上保存在此文件,
vi itop4412.h
修改第33行CONFIG_DEVICE_STRING宏定义,可改成任意字符串,这里改为“iTOP-4412 board”,如下图:
修改第254行CONFIG_SYS_PROMPT行定义为“TOPEET > ”,可任意
修改第294行内存相关的SDRAM_BANK_SIZE定义,SCP1G改为0x10000000/2,SCP2G和POP1G不用改,因为使用精英板SCP1G测试,,所以改为0x10000000/2,如下图,
修改第351行宏定义CONFIG_IDENT_STRING,可任意:
修改第459行CONFIG_BOOTDELAY宏定义为5,uboot命令行等待时间改为5秒,
修改第490行CONFIG_4412_BOOTLOADER和491行CONFIG_4412_DVT_BOOTLOADER宏定义为“u-boot-iTOP-4412.bin”,如下图,
参考include/sdmkc210.h,在文件末尾添加以下时钟相关内容,
#define CONFIG_EVT0_PERFORMANCE
#ifdef CONFIG_EVT0_STABLE
#define CONFIG_IV_SIZE 0x1D
#else
#define CONFIG_IV_SIZE 0x7
#endif#define S5PV310_POWER_BASE 0x10020000/** CLOCK*/
#define ELFIN_CLOCK_BASE 0x10030000#define CLK_SRC_LEFTBUS_OFFSET 0x04200
#define CLK_MUX_STAT_LEFTBUS_OFFSET 0x04400
#define CLK_DIV_LEFTBUS_OFFSET 0x04500#define CLK_SRC_RIGHTBUS_OFFSET 0x08200
#define CLK_MUX_STAT_RIGHTBUS_OFFSET 0x08400
#define CLK_DIV_RIGHTBUS_OFFSET 0x08500#define EPLL_LOCK_OFFSET 0x0C010
#define VPLL_LOCK_OFFSET 0x0C020
#define EPLL_CON0_OFFSET 0x0C110
#define EPLL_CON1_OFFSET 0x0C114
#ifdef CONFIG_SMDKC220
#define EPLL_CON2_OFFSET 0x0C118
#endif
#define VPLL_CON0_OFFSET 0x0C120
#define VPLL_CON1_OFFSET 0x0C124
#ifdef CONFIG_SMDKC220
#define VPLL_CON2_OFFSET 0x0C128
#endif#define CLK_SRC_TOP0_OFFSET 0x0C210
#define CLK_SRC_TOP1_OFFSET 0x0C214
#define CLK_SRC_FSYS_OFFSET 0x0C240
#define CLK_SRC_PERIL0_OFFSET 0x0C250
#define CLK_MUX_STAT_TOP_OFFSET 0x0C410
#define CLK_MUX_STAT_TOP1_OFFSET 0x0C414
#define CLK_DIV_TOP_OFFSET 0x0C510
#define CLK_DIV_FSYS1_OFFSET 0x0C544
#define CLK_DIV_FSYS2_OFFSET 0x0C548
#define CLK_DIV_FSYS3_OFFSET 0x0C54C
#define CLK_DIV_PERIL0_OFFSET 0x0C550#define CLK_SRC_DMC_OFFSET 0x10200
#define CLK_MUX_STAT_DMC_OFFSET 0x10400
#define CLK_DIV_DMC0_OFFSET 0x10500
#define CLK_DIV_DMC1_OFFSET 0x10504#define CLK_GATE_IP_DMC_OFFSET 0x10900#if defined(CONFIG_SMDKC220) || defined(CONFIG_EXYNOS4412)
#define CLK_GATE_IP_PERIR_OFFSET 0x08960
#elif defined(CONFIG_SMDKC210)
#define CLK_GATE_IP_PERIR_OFFSET 0x0C960
#endif#define APLL_LOCK_OFFSET 0x14000
#define APLL_CON0_OFFSET 0x14100
#define APLL_CON1_OFFSET 0x14104#if defined(CONFIG_SMDKC220) || defined(CONFIG_EXYNOS4412)
#define MPLL_LOCK_OFFSET 0x10008
#define MPLL_CON0_OFFSET 0x10108
#define MPLL_CON1_OFFSET 0x1010C
#elif defined(CONFIG_SMDKC210)
#define MPLL_LOCK_OFFSET 0x14008
#define MPLL_CON0_OFFSET 0x14108
#define MPLL_CON1_OFFSET 0x1410C
#endif#define CLK_SRC_CPU_OFFSET 0x14200
#define CLK_MUX_STAT_CPU_OFFSET 0x14400
#define CLK_DIV_CPU0_OFFSET 0x14500
#define CLK_DIV_CPU1_OFFSET 0x14504#define CLK_SRC_FSYS __REG(ELFIN_CLOCK_BASE+CLK_SRC_FSYS_OFFSET)
#define CLK_DIV_FSYS1 __REG(ELFIN_CLOCK_BASE+CLK_DIV_FSYS1_OFFSET)
#define CLK_DIV_FSYS2 __REG(ELFIN_CLOCK_BASE+CLK_DIV_FSYS2_OFFSET)
#define CLK_DIV_FSYS3 __REG(ELFIN_CLOCK_BASE+CLK_DIV_FSYS3_OFFSET)
#define APLL_CON0_REG __REG(ELFIN_CLOCK_BASE+APLL_CON0_OFFSET)
#define MPLL_CON0_REG __REG(ELFIN_CLOCK_BASE+MPLL_CON0_OFFSET)
#define EPLL_CON0_REG __REG(ELFIN_CLOCK_BASE+EPLL_CON0_OFFSET)
#define VPLL_CON0_REG __REG(ELFIN_CLOCK_BASE+VPLL_CON0_OFFSET)#define USB_PHY_CONTROL_OFFSET 0x0704
#define USB_PHY_CONTROL (0x10020000+USB_PHY_CONTROL_OFFSET)
完成后如下图:
68.7.4 修改eMMC分区信息
回到源码顶层目录,默认分区相关的宏定义在include/movi.h内,打开该文件,找到17,18行PART_SIZE_UBOOT和PART_SIZE_KERNEL宏定义,改为:
#define PART_SIZE_UBOOT (495 * 1024)
#define PART_SIZE_KERNEL (6 * 1024 * 1024)
如下图:
回到源码顶层目录,打开drivers/mmc/mmc.c,找到857行,修改对eMMC版本号的判断,将5改为8,
回到源码顶层目录,打开board/samsung/itop4412/itop412.c,将249行启动信息注释,改为自己的启动命令:
sprintf(boot_cmd, "movi read kernel 40008000;bootm 40008000");
到313行,添加“return 0”,执行完run_command后返回,如下图:
回到源码顶层目录,打开common/cmd_mmc_fdisk.c,这个文件里包含了分区操作函数,找到第26行SYSTEM_PART_SIZE宏定义,改为
#define SYSTEM_PART_SIZE _1GB
完成后如下图:
下面要修改的地方是分区相关操作解析找到如下内容:
将红框圈住的代码改为以下内容:
if (flag)
block_offset = calc_unit((unsigned long long)simple_strtoul(argv[3], NULL, 0)*1024*1024, sdInfo);
else
block_offset = calc_unit(SYSTEM_PART_SIZE, sdInfo);
完成后如下图:
找到如下内容:
将红框内的内容改为如下所示:
if (flag)block_offset = calc_unit((unsigned long long)simple_strtoul(argv[4], NULL, 0)*1024*1024, sdInfo);else{if (strcmp(argv[2], "1") == 0)// TF cardblock_offset = calc_unit(_300MB, sdInfo);elseblock_offset = calc_unit(USER_DATA_PART_SIZE, sdInfo);
}
如下图:
找到如下内容:
将红框内容改为如下所示:
if(flag)
block_offset = calc_unit((unsigned long long)simple_strtoul(argv[5], NULL, 0)*1024*1024, sdInfo);
else
block_offset = calc_unit(CACHE_PART_SIZE, sdInfo);
改完后如下图:
使用int类型不能正常进行分区,改为无符号整型unsigned int类型,修改如下三个地方:
回到顶层源码目录,打开cpu/arm_cortexa9/s5pc210/recovery.c文件,注释掉165到268行,
在注释掉的内容下方添加如下内容,0x2代表拨码开关为eMMC启动。:
else{/* add by cym 20141211 GPX1_1 */int value = 0;char run_cmd[50];value = __REG(GPX1DAT);if(0x2 == (value & 0x2))//not press{printf("SYSTEM ENTER NORMAL BOOT MODE\n");}else //press{printf("SYSTEM ENTER Updating MODE\n");sprintf(run_cmd, "sdfuse flashall");run_command(run_cmd, 0);}/* end add */return 0;}
添加完后如下图:
68.7.5 其他修改
本小节修改的内容可参考uboot视频(iTOP4412开发板资料汇总(不含光盘内容)\iTOP-4412开发板视频教程\05-迅为电子uboot视频教程\10-uboot启动分析),回到源码顶层目录,打开cpu/arm_cortexa9/s5pc210/cpu_init.S,在31行添加如下内容:
#define DMC_IVCONTROL 0xF0
wait_phy_state:
ldr r1, [r0, #DMC_PHYSTATUS]
tst r1, #(1<<2)
beq wait_phy_state
mov pc, lr
dmc_delay:
push {lr}
1: subs r2, r2, #1
bne 1b
pop {pc}
完成后如下图:
回到源码顶层目录,打开board/samsung/itop4412/lowlevel_init_SCP.S,在_TEXT_BASE上方添加如下时钟初始化相关内容:
wait_mux_state:ldr r1, [r0, r2]cmp r1, r3bne wait_mux_statemov pc, lrwait_pll_lock:ldr r1, [r0, r2]tst r1, #(1<<29)beq wait_pll_lockmov pc, lrwait_phy_state:ldr r1, [r0, #DMC_PHYSTATUS]tst r1, #(1<<2)beq wait_phy_statemov pc, lr
如下图:
找到system_clock_init函数,将里面CMU_BASE改为ELFIN_CLOCK_BASE,ELFIN_CLOCK_BASE在include/configs/itop_4412.h中定义,改完后如下图:
68.7.6 烧写测试
先在开发板成功运行Qt系统,然后进行测试。
回到U-boot源码顶层目录,执行make itop_4412_config进行配置,
执行make 编译,
完成后如下图:
执行 cp checksum_bl2_14k.bin u-boot.bin ../CodeSign4SecureBoot_SCP/将u-boot.bin,checksum_bl2_14k.bin拷贝到CodeSign4SecureBoot_SCP文件夹,并进入此文件夹,cd ../CodeSign4SecureBoot_SCP/
E4412_N.bl1.SCP2G.bin是三星提供的BL1文件,如果想分析,可以输入arm-none-linux-gnueabi-objdump -D -b binary -m arm E4412_N.bl1.SCP2G.bin > b1.asm命令生成反汇编文件,查看bl1.asm,初始化化环境如中断初始化,设置堆栈等,并搬移bl2代码到RAM中。
Bl2.bin是三星提供的BL2文件,完成基本硬件初始化,如Low_init.s 时钟串口内存flash等。
u-boot.bin不能单独运行,需使用三星提供的BL1 BL2进行打包加密校验。
如果之前生成过镜像一定要先删除:rm -r u-boot-iTOP-4412.bin,然后执行以下命令生成4412的U-boot镜像:
cat E4412_N.bl1.SCP2G.bin bl2.bin all00_padding.bin u-boot.bin tzsw_SMDK4412_SCP_2GB.bin > u-boot-iTOP-4412.bin
参考手册TF卡烧写章节,将光盘资料中的uboot烧写到TF卡上,将我们自己生成的u-boot-iTOP-4412.bin拷贝到sdupdate文件夹内,如下图:
将TF卡插到开发板上,设置拨码开关TF启动,对eMMC进行分区(参考TF卡烧写章节这里不再重复赘述),然后执行sdfuse flash bootloader u-boot-iTOP-4412.bin 将自己生成的uboot镜像烧写到开发板eMMC,如下图:
然后断电,拔掉TF卡,将开发板设置成eMMC启动,发现uboot命令行等待时间变成了5s,打印信息如下,内存和eMMC容量均识别正常:
输入printenv查看环境变量:
bootcmd环境变量与board/samsung/itop4412/itop4412.c中设置的对应,
movi命令在common/cmd_movi内实现,可以看到movi命令将uboot的结束地址作为kernel的开始地址,读取地址,读取PART_SIZE_KERNEL个数据做为内核,如下图:
PART_SIZE_KERNEL在include/movi.h内定义,movi read kernel 40008000代表将内核从eMMC读到内存地址40008000,bootm 40008000代表从内存地址4008000处读取内核,从而完成系统启动。U-boot的目的是为了启动内核,内核启动后U-boot阶段结束。
相关文章:
【北京迅为】iTOP-4412全能版使用手册-第六十八章 U-boot基础知识
iTOP-4412全能版采用四核Cortex-A9,主频为1.4GHz-1.6GHz,配备S5M8767 电源管理,集成USB HUB,选用高品质板对板连接器稳定可靠,大厂生产,做工精良。接口一应俱全,开发更简单,搭载全网通4G、支持WIFI、蓝牙、…...
go 中线程安全map
在 Go 语言中,官方包 sync.Map 确实提供了线程安全的映射数据结构。然而,正如你所提到的,使用 sync.Map 时,有时需要进行类型断言,这可能会让代码显得冗长或不直观。 如果你希望使用一个更加易用的线程安全映射&#…...
封装类与普通类的区别
1 封装类的好处 数据隐藏:通过封装,我们可以将类的内部实现细节隐藏起来,只暴露有限的接口。这样,外部代码就不能直接访问或修改类的内部状态,从而保证了数据的安全性和完整性。 数据保护:封装可以…...
StarRocks-hive数据类型导致的分区问题
背景: 有个hive的表,是月分区的(month_id),分区字段用的是string类型。数据量比较大,为了保证计算性能,所以把数据导入到SR里,构建一个内部表。但是在建表的时候想使用月分区使用pa…...
Java面试题精选:设计模式(二)
1、装饰器模式与代理模式的区别 1)代理模式(Proxy Design Pattern ) 原始定义是:让你能够提供对象的替代品或其占位符。代理控制着对于原对象的访问,并允许将请求提交给对象前后进行一些处理。 代理模式的适用场景 功能增强 当需要对一个对…...
【JavaEE】多线程(7)
一、JUC的常见类 JUC→java.util.concurrent,放了和多线程相关的组件 1.1 Callable 接口 看以下从计算从1加到1000的代码: public class Demo {public static int sum;public static void main(String[] args) throws InterruptedException {Thread …...
技术型企业如何高效搭建企业博客以增强品牌影响力和市场竞争力
在数字化时代,技术型企业面临着激烈的市场竞争和快速变化的行业环境。为了在这场竞争中脱颖而出,企业需要寻找新的营销渠道和品牌建设工具。企业博客作为一种低成本、高效率的在线内容平台,已经成为技术型企业增强品牌影响力和市场竞争力的重…...
【qt环境配置】windows下的qt与vs工具集安装\版本对应关系
vs工具集安装通过vs的在线安装器勾选工具集即可 工具包下载路径:https://www.microsoft.com/zh-cn/download/details.aspx?id40784 配置工具集在qt中可以自动扫描到 《正确在 Windows 上配置 MSVC(2019) 作为 Qt 编译器》https://b3logfile.com/pdf/article/15922…...
XTuner 微调实践微调
步骤 0. 使用 conda 先构建一个 Python-3.10 的虚拟环境 cd ~ #git clone 本repo git clone https://github.com/InternLM/Tutorial.git -b camp4 mkdir -p /root/finetune && cd /root/finetune conda create -n xtuner-env python3.10 -y conda activate xtuner-env…...
docker compose
Docker的理念是一个容器只运行一个服务。而 Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具 1 2。通过 docker-compose.yml 文件,用户可以配置应用程序服务,并使用简单的一条命令便可以创建和启动所有服务。这是关于 Docker Compose …...
Java 中的方法重写
在 Java 中,方法重写(Method Overriding)是面向对象编程的一个重要概念,它指的是子类中存在一个与父类中相同名称、相同参数列表和相同返回类型的方法。方法重写使得子类可以提供特定的实现,从而覆盖(或改变…...
阿里云ECS服务器域名解析
阿里云ECS服务器域名解析,以前添加两条A记录类型,主机记录分别为www和,这2条记录都解析到服务器IP地址。 1.进入阿里云域名控制台,找到域名 ->“解析设置”->“添加记录” 2.添加一条记录类型为A,主机记录为www,…...
非父子通信(扩展)-- event bus 事件总线
创建一个空实例Bus, export default 导出Bus 过程:由A组件对Bus组件进行监听,B组件触发Bus对应的事件,由于A组件进行监听,触发事件之后就会进行A组件的回调,那么就可以将消息发送给A了 在src文件夹下新建utils文件夹&a…...
【Linux系列】获取当前目录
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
大模型:把GPT搬回家 - chatGPT的本地化API -Node.js调用
chatGPT拒绝了中国大陆和中国香港的访问,包括api的调用。这使得我们无法使用目前来讲确实YYLX的生产工具,仔细想一下其实还是可以曲线解决的,本文的介绍仅供学习参考。 用Node.jschatGPT提供的API,就可以在自己本地或者自己的服务…...
【Qt项目实战】使用脚本拓展CPP应用程序(2)——Lua脚本及编辑器
考古 《【Qt项目实战 】:使用脚本拓展CPP应用程序(1)——Lua脚本及编辑器》 一、LuaBridge 最近在项目的某个模块再次使用Lua作为程序拓展语言,开发了一些新的功能。 这里借助 LuaBridge 轻松实现Qt调用C类成员函数及成员对象等…...
【RBF SBN READ】hadoop社区基于RBF的SBN READ请求流转
读写分离功能的背景及架构 当前联邦生产集群的各个子集群只有Active NameNode在工作,当读写任务变得繁忙的时候,只有一个Active负责处理的话,此时集群的响应和处理能力业务侧感知会明显下降,为此,我们将引入Observer架构,实现读写功能的分离,使得Active只负责写请求,而…...
【教学类-36-08】20241210对称蝴蝶——去白边(图案最大化)一大和一大二小
背景需求 前期制作了对称蝴蝶,用来涂色,幼儿很喜欢 【教学类-36-07】20230707三只对称蝴蝶(midjounery-niji)(涂色、裁剪、游戏(飞舞的蝴蝶))_对称图案涂色-CSDN博客文章浏览阅读49…...
Flume——sink连接hdfs的参数配置(属性参数+时间参数)
这可不是目录 配置文件官网说明属性参数时间参数 配置文件官网说明 可以参考官网的说明 属性参数 属性名称默认值说明channel-type-组件类型名称,必须是hdfshdfs.path-HDFS路径,例如:hdfs://mycluster/flume/mydatahdfs.filePrefixFlumeDa…...
lc字符串相加——模拟
415. 字符串相加 - 力扣(LeetCode) 不准调用封装好的那些库。手动模拟两数相加,记录进位。主要当其中短的数字计算完了怎么办,技巧为下标为负数时就当做0,相当于补0一样。 class Solution {public String addStrings…...
框架建设实战6——缓存组件
说起分布式缓存,如今redis大行其道。不过,我们在创建缓存组件时,需要着重考虑如下几点: 1.客户端选型 本组件基于springboot2的默认实现,即lettuce客户端。不同客户端区别如下: 名称描述 优缺点分析 jedis1.springboot1.5.*默认 2.老牌客户端,使用稳定…...
基于springboot使用Caffeine
Caffeine 是一个基于 Java 的高性能、现代化的缓存库。它由 Ben Manes 开发,受 Google Guava 缓存库的启发,但具有更好的性能和更多的功能。 Caffeine 的核心特点 高性能 基于 Java 8 的现代化设计,利用高级并发算法,提供极低的延…...
深入解析 JavaScript 中的 Blob 对象:二进制数据处理的核心
文章目录 1.Blob是什么2.Blob用法实例属性Blob方法slice方法text方法 示例1:字符串 Blob示例2:数组和字符串 Blob示例3:从文件输入创建 3.使用场景1.创建 Blob 并生成 URL,下载文件2.文件上传3.切片上传3.Blob用于URL在线预览PDF文…...
fastboot
Fastboot 是 Android 和嵌入式开发中常见的一个低级工具,它允许通过 USB 与设备直接交互,用于分区的管理和系统的刷写等任务。以下是其工作原理和核心机制的解析: 1. Fastboot 的基本概念 Fastboot 是一种通信协议,通常在设备的引…...
yosys内部数据结构
一、参考链接 1.Yosys内部结构doxygen文件 yosys-master: RTLIL Namespace Reference 2.yosys内部结构介绍 https://yosyshq.readthedocs.io/projects/yosys/en/docs-preview-cellhelp/yosys_internals/formats/rtlil_rep.html 二、概览 图 1 网表核心数据结构 如图 1所示…...
前端导出excel实战(xlsx库和exceljs库)
一. 概览 前端导出excel是比较常见的需求,比如下载excel模板和批量导出excel。目前比较常用的库有xlsx和excel,接下来就着两种方式进行梳理。 二. 下载模板 xlsx库实现: 示例核心代码如下: const excelColumn {details: {ma…...
TCP/IP杂记
TCP三次握手、四次挥手 从应用角度,不用多考虑为什么有三次,遵循标准即可。 ubuntu 下 wireshark安装: sudo add-apt-repository universe sudo apt install wireshark 三次握手实证: 第一次握手的情况如下:&#…...
深入解析 Spring Security —— 打造高效安全的权限管理体系
目录 前言1. 初识 Spring Security1.1 Spring Security 的两大核心功能1.2 Spring Security 的主要特点 2. 配置 Spring Security2.1 配置类概述2.2 基础配置示例2.3 示例解析 3. Spring Security 的进阶功能3.1 自定义用户服务3.2 注解式权限控制3.3 动态权限控制 4. 实战应用…...
PostGIS分区表学习相关
在Postgresql中对空间数据进行表分区的实践_postgresql空间数据-CSDN博客文章浏览阅读1.4k次,点赞26次,收藏21次。Postgresql的分区功能允许将一个大表按照特定的规则拆分成多个小的分区表。这样做的好处在于,在查询数据时,可以只…...
避大坑!Vue3中reactive丢失响应式的问题
在vue3中,我们定义响应式数据无非是ref和reactive。 但是有的小伙伴会踩雷!导致定义的响应式丢失的问题。 reactive丢失响应式的情况1(直接赋值) 场景: 1.你定义了一个数据:let datareactive({name:"",age:"" }) 2.然后你…...
绿虫光伏设计系统:清洁能源的未来
煤炭、石油、天然气是我们现在依赖的重要能源,但这些能源难以再生,而且开采过程中会产生污染。太阳能发电作为清洁能源的一种重要形式,受到了越来越多的关注。绿虫光伏发电系统,不仅考虑到其发电效率,还可以考虑其经济…...
Python中的文件操作与数据处理
一、前言 文件操作是数据处理和持久化存储的基础。Python内置了强大的文件操作能力,并提供了丰富的库支持复杂数据处理需求。本文将从基础的文件读写到高效的数据处理,带您全面掌握Python文件操作技能。 二、文件操作基础 1. 文件的读写 # 写入文件 with open("examp…...
在huggingface.co的Spaces中推理,得到错误:No space left on device
如果你的前几次或者上一次推理运行成功了,或者至少GPU加载过了,导致你这次问题的原因可能是某种缓存文件太大 删除它试试,如果你的推理没有在运行,这不影响任何东西 rm -rf /data-nvme/zerogpu-offload/如果有帮助,请…...
el-table expand-row-keys默认展开,数据更新后默认展开的问题
开发项目时遇到个问题,菜单展开后,刷新数据,再次点击收起按钮不好用了,要点两次才好使,解决方案如下: 1、table设置 <el-table:loading"load":data"menuDataList":load"load…...
Linux下redis环境的搭建
1.redis的下载 redis官网下载redis的linux压缩包,官网地址:Redis下载 网盘链接: 通过网盘分享的文件:redis-5.0.4.tar.gz 链接: https://pan.baidu.com/s/1cz3ifYrDcHWZXmT1fNzBrQ?pwdehgj 提取码: ehgj 2.redis安装与配置 将包上传到 /…...
海外的bug-hunters,不一样的403bypass
一种绕过403的新技术,跟大家分享一下。研究HTTP协议已经有一段时间了。发现HTTP协议的1.0版本可以绕过403。于是开始对lyncdiscover.microsoft.com域做FUZZ并且发现了几个403Forbidden的文件。 (访问fsip.svc为403) 在经过尝试后࿰…...
使用 EasyExcel 提升 Excel 处理效率
目录 前言1. EasyExcel 的优点2. EasyExcel 的功能3. 在项目中使用 EasyExcel3.1 引入依赖3.2 实体类的定义与注解3.3 工具类方法的实现3.4 在 Controller 中使用 4. 总结5. 参考地址 前言 在日常开发中,Excel 文件的处理是不可避免的一项任务,特别是在…...
驱鸟器自定义播放音乐,低成本语音方案选型-N9305九芯电子
一、开发背景: 随着农业现代化的不断推进,鸟类对农作物的侵扰问题愈发严重。传统的驱鸟方法,如人工驱赶或使用化学药剂,不仅效率低下,而且可能对环境造成污染。因此,开发一种高效、环保、低成本的驱鸟器成…...
【html css选择器】
在 CSS 中,你可以通过选择器来选择 HTML 元素,并为其设置样式。以下是一些常见的 CSS 选择器和样式设置方法: 1. 基本选择器 元素选择器:选择特定的 HTML 元素。 p {color: blue;font-size: 16px; }类选择器:选择具有…...
mongoDb的读session和写session权限报错问题
go在使用mongoDb时用到了全局会话,发现在创建的session的逻辑相同,首先会进行数据的查询,此时获取了全局session执行读操作,查询所有文档,则当前会话为读会话,当再去插入时发现会报错,此时sessi…...
如何避免缓存击穿?超融合常驻缓存和多存储池方案对比
作者:SmartX 解决方案专家 钟锦锌 很多运维人员都知道,混合存储介质配置可能会带来“缓存击穿”的问题,尤其是大数据分析、数据仓库等需要频繁访问“冷数据”的应用场景,缓存击穿可能会更频繁地出现,影响业务运行。除…...
c语言专题之单链表的实现
在之前的博客中小编已经讲解了顺序表及其应用,所以在将讲单链表之前,我们先来重新思考一下顺序表,这里我先来讲顺序表的几个小缺点: 1.顺序表中在我们数据时,如头插、在指定位置插入等,我们通常需要整体挪动…...
Spring 源码学习(七)——注解后处理器
通过之前对注解式配置的解析(Spring 源码学习(三)—— 注解式配置解析_spring源码学习-CSDN博客)可以发现其使用 AnnotationConfigUtils 类的 registerAnnotationConfigProcessors 静态方法对象注解后处理器对象进行注册ÿ…...
GEE训练教程——基于 Sentinel-1 数据对 Felső-Kiskunság 湖区的可视化分析
目录 简介 代码解释 代码 结果 简介 GEE训练教程——基于 Sentinel-1 数据对 Felső-Kiskunsg 湖区的可视化分析 此处打开后运行后直接在script界面上就可以输入指定的年份和月份,但不是GEE APP的运算,是直接在弹出的框内输入即可。 代码解释 以下是您提供的 Google …...
docker 相关操作
1. 以下是一些常见的 Docker 命令: docker --version显示安装的 Docker 版本。 docker pull <image_name>从 Docker Hub 或其他镜像仓库下载镜像。 docker build -t <image_name> <path>从指定路径的 Dockerfile 构建 Docker 镜像。 docker i…...
【汽车】-- 燃油发动机3缸和4缸
3缸和4缸燃油发动机是小轿车常见的发动机配置。以下从结构特点、性能、经济性等方面对两者进行对比,并分析优缺点及使用注意事项: 1. 结构与运行原理 3缸发动机 特点:少一个气缸,内部零部件更少,整体结构更紧凑。优点…...
Python - 处理包含非utf-8 的字符编码
有这样的字符串,utf-8 编码中包含 ascii 编码内容 你好\x0a\x0a哈哈s 你好\x0a\x0a哈哈 b s.encode(utf-8) b.decode(utf-8)其它尝试 >>> b s.encode(utf-8) >>> b.decode(ascii) Traceback (most recent call last):File "<stdin&g…...
主坐标分析(PCoA)
主坐标分析(PCoA)是一种多变量统计方法,用于研究样本间的相似性或差异性,是一种非约束性的数据降维分析方法。以下是PCoA的关键点和实施步骤: 什么是PCoA? PCoA通过将样本距离矩阵转换为坐标,…...
Linux 网络接口配置
在 Linux 中,网络接口配置文件用于控制系统中的软件网络接口,并通过接口实现对网络设备的控制。当系统启动时,系统通过这些接口配置文件决定启动哪些接口,以及如此对这些接口进行配置. 在 Linux 中,网络接口配置文件用于控制系统中的软件网络接口,并通过这些接口实现对网络…...
Netty客户端接收不到服务端发送的数据问题
文章目录 前言问题描述相关代码解决方法 前言 环境 JDK:64位 jdk1.8.0_201 Netty:4.1.39.Final 问题描述 项目中使用Netty接受客户端的消息,客户端为硬件设备,在接受数据后发送数据到服务端。 同时因为客户端没有联网ÿ…...