资讯
HOME
资讯
正文内容
nand read 格式 「正点原子Linux连载」第三十章U-Boot使用实验(二)
发布时间 : 2024-11-24
作者 : 小编
访问数量 : 23
扫码分享至微信

「正点原子Linux连载」第三十章U-Boot使用实验(二)

1)实验平台:正点原子Linux开发板

2)摘自《正点原子 I.MX6U嵌入式Linux驱动开发指南

关注官方微信号公众号,获取更多资料:正点原子

30.4.7 EXT格式文件系统操作命令

uboot有ext2和ext4这两种格式的文件系统的操作命令,常用的就四个命令,分别为:ext2load、ext2ls、ext4load、ext4ls和ext4write。这些命令的含义和使用与fatload、fatls和fatwrit一样,只是ext2和ext4都是针对ext文件系统的。比如ext4ls命令,EMMC的分区2就是ext4格式的,使用ext4ls就可以查询EMMC的分区2中的文件和目录,输入命令:

ext4ls mmc 1:2

结果如图30.4.7.1所示:

图30.4.7.1ext4ls命令

关于ext格式文件系统其他命令的操作参考30.4.6小节的即可,这里就不讲解了。

30.4.8 NAND操作命令

uboot是支持NAND Flash的,所以也有NAND Flash的操作命令,前提是使用的NAND版本的核心板,并且编译NAND核心板对应的uboot,然后使用imxdownload软件将u-boot.bin烧写到SD卡中,最后通过SD卡启动。一般情况下NAND版本的核心板已经烧写好了uboot、linux kernel和rootfs这些文件,所以可以将BOOT拨到NAND,然后直接从NAND Flash启动即可。

NAND版核心板启动信息如图30.4.8.1所示:

图30.4.8.1 NAND核心板启动信息

从图30.4.8.1可以看出,当前开发板的NAND容量为512MiB。输入“? nand”即可查看所有有关NAND令,如图30.4.8.2所示:

图30.4.8.2 NAND相关操作命令

可以看出,NAND相关的操作命令少,本节我们讲解一些常用的命令。

1、nand info命令

此命令用户打印NAND Flash信息,输入“nandinfo”,结果如图30.4.8.3所示:

图30.4.8.3 nand信息

图30.4.8.3中给出了NAND的页大小、OOB域大小,擦除大小等信息。可以对照着所使用的NAND Flash数据手册来查看一下这些信息是否正确。

2、nanddevice命令

nanddevice用于切换NAND Flash,如果你的板子支持多片NAND的话就可以使用此命令来设置当前所使用的NAND。这个需要你的CPU有两个NAND控制器,并且两个NAND控制器各接一片NAND Flash。就跟I.MX6U有两个SDIO接口,这两个SDIO接口可以接两个MMC设备一样。不过一般情况下CPU只有一个NAND接口,而且在使用中只接一片NAND。

3、nanderase命令

nanderase命令用于擦除NAND Flash,NAND Flash的特性决定了在向NAND Flash写数据之前一定要先对要写入的区域进行擦除。“nanderase”命令有三种形式:

nand erase[.spread] [clean] off size //从指定地址开始(off)开始,擦除指定大小(size)的区域。

nand erase.part [clean] partition //擦除指定的分区

nand erase.chip [clean] //全篇擦除

NAND的擦除命令一般是配合写命令的,后面讲解NAND写命令的时候在演示如何使用“nand erase”。

4、nandwrite命令

此命令用于向NAND指定地址写入指定的数据,一般和“nanderase”命令配置使用来更新NAND中的uboot、linuxkernel或设备树等文件,命令格式如下:

nand write addr off size

addr是要写入的数据首地址,off是NAND中的目的地址,size是要写入的数据大小。

以更新NAND中的uboot为例,讲解一下如何使用此命令。先编译出来NAND版本的u-boot.imx文件,在烧写之前要先对NAND进行分区,也就是规划好uboot、linuxkernel、设备树和根文件系统的存储区域,I.MX6U-ALPHA开发板的NAND分区如下:

0x000000000000-0x000004000000 : "boot"

0x000004000000-0x000006000000 : "kernel"

0x000006000000-0x000007000000 : "dtb"

0x000007000000-0x000020000000 : "rootfs"

一共有四个分区,第一个分区存放uboot,地址范围为0x0~0x4000000(共64MB);第二个分区存放kernel(也就是linuxkernel),地址范围为0x4000000~0x6000000(共32MB);第三个分区存放dtb(设备树),地址范围为0x6000000~0x7000000(共16MB);剩下的所有存储空间全部作为最后一个分区,存放rootfs(根文件系统)。

uboot是从地址0开始存放的,其实用不了这么大的区域,但是为了好管理才分配了这么大的,将NAND版本的u-boot.imx文件放到Ubuntu中的tftpboot目录中,然后使用tftp命令将其下载到开发板的0X87800000地址处,最终使用“nandwrite”将其烧写到NAND中,命令如下:

tftp 0x87800000 u-boot.imx //下载u-boot.imx到DRAM中

nand erase 0x0 0x100000 //从地址0开始擦除1MB的空间

nand write 0x87800000 0x0 0x100000 //将接收到的u-boot.imx写到NAND中

u-boot.imx很小,一般就是4,5百KB,所以擦除1MB的空间就可以了。写入的时候也是按照1M的数据写入的,所以肯定会写入一些无效的数据。你也可以将写入的大小改为u-boot.imx这个文件的大小,这样写入的数据量就是u-boot.imx的实际大小了。

同理我们也可以更新NAND中的linuxkernel和设备树(dtb)文件,命令如下:

tftp 0x87800000 zImage //下载zImage到DRAM中

nand erase 0x4000000 0xA00000 //从地址0x4000000开始擦除10MB的空间

nand write 0x87800000 0x4000000 0xA00000 //将接收到的zImage写到NAND中

这里我们擦出了10MB的空间,因为一般zImage就是6,7MB左右,10MB肯定够了,如果不够的话就将在多擦除一点就行了。

最后烧写设备树(dtb)文件文件,命令如下:

tftp 0x87800000 imx6ull-alientek-nand.dtb //下载dtb到DRAM中

nand erase 0x6000000 0x100000 //从地址0x6000000开始擦除1MB的空间

nand write 0x87800000 0x6000000 0x100000 //将接收到的dtb写到NAND中

dtb文件一般只有几十KB,所以擦除1M是绰绰有余的了。

根文件系统(rootfs)就不要在uboot中更新了,还是使用NXP提供的MFGTool工具来烧写,因为根文件系统太大!很有可能超过开发板DRAM的大小,这样连下载都没法下载,更别说更新了。

4、nand read命令

此命令用于从NAND中的指定地址读取指定大小的数据到DRAM中,命令格式如下:

nand read addr off size

addr是目的地址,off是要读取的NAND中的数据源地址,size是要读取的数据大小。比如我们读取设备树(dtb)文件到0x83000000地址处,命令如下:

nand read 0x83000000 0x6000000 0x19000

过程如图30.4.8.4所示:

图30.4.8.4 nandread读取过程

设备树文件读取到DRAM中以后就可以使用fdt命令来对设备树进行操作了,首先设置fdt的地址,fdt地址就是DRAM中设备树的首地址,命令如下:

fdtaddr 83000000

设置好以后可以使用“fdtheader”来查看设备树的头信息,输入命令:

fdtheader

结果如图30.4.8.5所示:

图30.4.8.5 设备树头信息

输入命令“fdtprint”就可以查看设备树文件的内容,输入命令:

fdtprint

结果如图30.4.8.6所示:

图30.4.8.6 设备树文件

图30.4.8.6中的文件就是我们写到NAND中的设备树文件,至于设备树文件的详细内容我们后面会有专门的章节来讲解,这里大家知道这个文件就行了。

NAND常用的操作命令就是擦除、读和写,至于其他的命令大家可以自行研究一下,一定不要尝试全片擦除NAND的指令!!否则NAND就被全部擦除掉了,什么都没有了,又得重头烧整个系统。

30.4.9 BOOT操作命令

uboot的本质工作是引导Linux,所以uboot肯定有相关的boot(引导)命令来启动Linux。常用的跟boot有关的命令有:bootz、bootm和boot。

1、bootz命令

要启动Linux,需要先将Linux镜像文件拷贝到DRAM中,如果使用到设备树的话也需要将设备树拷贝到DRAM中。可以从EMMC或者NAND等存储设备中将Linux镜像和设备树文件拷贝到DRAM,也可以通过nfs或者tftp将Linux镜像文件和设备树文件下载到DRAM中。不管用那种方法,只要能将Linux镜像和设备树文件存到DRAM中就行,然后使用bootz命令来启动,bootz命令用于自动zImage镜像文件,bootz命令格式如下:

bootz [addr [initrd[:size]] [fdt]]

命令bootz有三个参数,addr是Linux镜像文件在DRAM中的位置,initrd是initrd文件在DRAM中的地址,如果不使用initrd的话使用‘-’代替即可,fdt就是设备树文件在DRAM中的地址。现在我们使用网络和EMMC两种方法来启动Linux系统,首先将I.MX6U-ALPHA开发板的Linux镜像和设备树发送到Ubuntu主机中的tftpboot文件夹下。Linux镜像文件前面已经放到了tftpboot文件夹中,现在把设备树文件放到tftpboot文件夹里面。以EMMC核心板为例,将开发板光盘->8、开发板系统镜像->imx6ull-alientek-emmc.dtb文件发送到Ubuntu主机中的tftpboot文件夹里面,完成以后的tftpboot文件夹如图30.4.9.1所示:

图30.4.9.1tftpboot文件夹

下载Linux镜像文件和设备树都准备好了,我们先学习如何通过网络启动Linux,使用tftp命令将zImage下载到DRAM的0X80800000地址处,然后将设备树imx6ull-alientek-emmc.dtb下载到DRAM中的0X83000000地址处,最后之后命令bootz启动,命令如下:

tftp 80800000 zImage

tftp 83000000 imx6ull-alientek-emmc.dtb

bootz 80800000 – 83000000

命令运行结果如图30.4.9.2所示:

图30.4.9.2通过网络启动Linux

上图就是我们通过tftp和bootz命令来从网络启动Linux系统,如果我们要从EMMC中启动Linux系统的话只需要使用命令fatload将zImage和imx6ull-alientek-emmc.dtb从EMMC的分区1中拷贝到DRAM中,然后使用命令bootz启动即可。先使用命令fatls查看要下EMMC的分区1中有没有Linux镜像文件和设备树文件,如果没有的话参考30.4.6小节中讲解的fatwrite命令将tftpboot中的zImage和imx6ull-alientek-emmc.dtb文件烧写到EMMC的分区1中。然后使用命令fatload将zImage和imx6ull-alientek-emmc.dtb文件拷贝到DRAM中,地址分别为0X80800000和0X83000000,最后使用bootz启动,命令如下:

fatload mmc 1:1 80800000 zImage

fatload mmc 1:1 83000000 imx6ull-alientek-emmc.dtb

bootz 80800000 - 83000000

命令运行结果如图30.4.9.3所示:

图30.4.6.3从EMMC中启动Linux

2、bootm命令

bootm和bootz功能类似,但是bootm用于启动uImage镜像文件。如果不使用设备树的话启动Linux内核的命令如下:

bootmaddr

addr是uImage镜像在DRAM中的首地址。

如果要使用设备树,那么bootm命令和bootz一样,命令格式如下:

bootm [addr [initrd[:size]] [fdt]]

其中addr是uImage在DRAM中的首地址,initrd是initrd的地址,fdt是设备树(.dtb)文件在DRAM中的首地址,如果initrd为空的话,同样是用“-”来替代。

3、boot命令

boot命令也是用来启动Linux系统的,只是boot会读取环境变量bootcmd来启动Linux系统,bootcmd是一个很重要的环境变量!其名字分为“boot”和“cmd”,也就是“引导”和“命令”,说明这个环境变量保存着引导命令,其实就是启动的命令集合,具体的引导命令内容是可以修改的。比如我们要想使用tftp命令从网络启动Linux那么就可以设置bootcmd为“tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000”,然后使用saveenv将bootcmd保存起来。然后直接输入boot命令即可从网络启动Linux系统,命令如下:

setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000'

saveenv

boot

运行结果如图30.4.6.4所示:

图30.4.6.4设置bootcmd从网络启动Linux

前面说过uboot倒计时结束以后就会启动Linux系统,其实就是执行的bootcmd中的启动命令。只要不修改bootcmd中的内容,以后每次开机uboot倒计时结束以后都会使用tftp命令从网络下载zImage和imx6ull-alientek-emmc.dtb,然后启动Linux。

如果想从EMMC启动那就设置bootcmd为“fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-alientek_emmc.dtb; bootz 80800000 - 83000000”,然后使用boot命令启动即可,命令如下:

setenv bootcmd 'fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-alientek_emmc.dtb; bootz 80800000 - 83000000'

savenev

boot

运行结果如图30.4.6.5所示:

图30.4.6.5设置bootcmd从EMMC启动Linux

如果不修改bootcmd的话,每次开机uboot倒计时结束以后都会自动从EMMC里面读取zImage和imx6ull-alientek-emmc.dtb,然后启动Linux。

30.4.10其他常用命令

uboot中还有其他一些常用的命令,比如reset、go、run和mtest等。

1、reset命令

reset命令顾名思义就是复位的,输入“reset”即可复位重启,如图30.4.10.1所示:

图30.4.10.1reset命令运行结果

2、go命令

go命令用于跳到指定的地址处执行应用,命令格式如下:

go addr [arg ...]

addr是应用在DRAM中的首地址,我们可以编译一下裸机例程的实验13_printf,然后将编译出来的printf.bin拷贝到Ubuntu中的tftpboot文件夹里面,注意,这里要拷贝printf.bin文件,不需要在前面添加IVT信息,因为uboot已经初始化好了DDR了。使用tftp命令将printf.bin下载到开发板DRAM的0X87800000地址处,因为裸机例程的链接首地址就是0X87800000,最后使用go命令启动printf.bin这个应用,命令如下:

tftp 87800000 printf.bin

go 87800000

结果如图30.4.10.2所示:

图30.4.10.2go命令运行裸机例程

从图30.4.10.2可以看出,通过go命令我们就可以在uboot中运行裸机例程。

3、run命令

run命令用于运行环境变量中定义的命令,比如可以通过“runbootcmd”来运行bootcmd中的启动命令,但是run命令最大的作用在于运行我们自定义的环境变量。在后面调试Linux系统的时候常常要在网络启动和EMMC/NAND启动之间来回切换,而bootcmd只能保存一种启动方式,如果要换另外一种启动方式的话就得重写bootcmd,会很麻烦。这里我们就可以通过自定义环境变量来实现不同的启动方式,比如定义环境变量mybootemmc表示从emmc启动,定义mybootnet表示从网络启动,定义mybootnand表示从NAND启动。如果要切换启动方式的话只需要运行“runmybootxxx(xxx为emmc、net或nand)”即可。

说干就干,创建环境变量mybootemmc、mybootnet和mybootnand,命令如下:

setenv mybootemmc 'fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-alientek-emmc.dtb;bootz 80800000 - 83000000'

setenv mybootnand 'nand read 80800000 4000000 800000;nand read 83000000 6000000 100000;bootz 80800000 - 83000000'

setenv mybootnet 'tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000'

saveenv

创建环境变量成功以后就可以使用run命令来运行mybootemmc、mybootnet或mybootnand来实现不同的启动:

runmybootemmc

run mytoobnand

run mybootnet

4、mtest命令

mtest命令是一个简单的内存读写测试命令,可以用来测试自己开发板上的DDR,命令格式如下:

mtest [start [end [pattern [iterations]]]]

start是要测试的DRAM开始地址,end是结束地址,比如我们测试0X80000000~0X80001000这段内存,输入“mtest8000000080001000”,结果如图30.4.10.3所示:

图30.4.10.3mtest命令运行结果

从图30.4.10.3可以看出,测试范围为0X80000000~0X80001000,已经测试了486次,如果要结束测试就按下键盘上的“Ctrl+C”键。

至此,uboot常用的命令就讲解完了,如果要使用uboot的其他命令,可以查看uboot中的帮助信息,或者上网查询一下相应的资料。

图30.1.1uboot官网

我们可以在uboot官网下载uboot源码,点击图30.1.1中左侧Topics中的“Source Code”,打开如图30.1.2所示界面:

图30.1.2uboot源码界面

点击图30.1.2中的“FTP Server”,进入其FTP服务器即可看到uboot源码,如图30.1.3所示:

图30.1.3uboot源码

图30.1.3中就是uboot原汁原味的源码文件,目前最新的版本是2019.04。但是我们一般不会直接用uboot官方的U-Boot源码的。uboot官方的uboot源码是给半导体厂商准备的,半导体厂商会下载uboot官方的uboot源码,然后将自家相应的芯片移植进去。也就是说半导体厂商会自己维护一个版本的uboot,这个版本的uboot相当于是他们定制的。既然是定制的,那么肯定对自家的芯片支持会很全,虽然uboot官网的源码中一般也会支持他们的芯片,但是绝对是没有半导体厂商自己维护的uboot全面。

NXP就维护的2016.03这个版本的uboot,下载地址为:http://git.freescale.com/git/cgit.cgi/imx/uboot-imx.git/tag/?h=imx_v2016.03_4.1.15_2.0.0_ga&id=

rel_imx_4.1.15_2.1.0_ga,下载界面如图30.1.4所示:

图30.1.4 NXP官方uboot下载界面

图30.1.4中的uboot-imx_rel_imx4.1.15_2.1.0_ga.xx(xx为zip、tar.gz或tar.bz2)就是NXP官方维护的uboott,后面我们学习uboot移植的时候就是使用的图30.1.4中的uboot,下载uboot-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2。我们已经放到了开发板光盘中,路径为:开发板光盘->1、程序源码->4、NXP官方原版Uboot和Linux->uboot-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2。图30.1.4中的uboot基本支持了NXP当前所有可以跑Linux的芯片,而且支持各种启动方式,比如EMMC、NAND、NOR FLASH等等,这些都是uboot官方所不支持的。但是图30.1.4中的uboot是针对NXP自家评估板的,如果是我们自己做的板子就需要修改NXP官方的uboot,使其支持我们自己做的板子,正点原子的I.MX6U开发板就是自己做的板子,虽然大部分都参考了NXP官方的I.MX6ULL EVK开发板,但是还是有很多不同的地方,所以需要修改NXP官方的uboot,使其适配正点原子的I.MX6U开发板。所以当我们拿到开发板以后,是有三种uboot的,这三种uboot的区别如表30.1.1所示:

种类

描述

uboot官方的uboot代码

由uboot官方维护开发的uboot版本,版本更新快,基本包含所有常用的芯片。

半导体厂商的uboot代码

半导体厂商维护的一个uboot,专门针对自家的芯片,在对自家芯片支持上要比uboot官方的好。

开发板厂商的uboot代码

开发板厂商在半导体厂商提供的uboot基础上加入了对自家开发板的支持。

表30.1.1三种uboot的区别

那么这三种uboot该如何选择呢?首先uboot官方的基本是不会用的,因为支持太弱了。最常用的就是半导体厂商或者开发板厂商的uboot,如果你用的半导体厂商的评估板,那么就使用半导体厂商的uboot,如果你是购买的第三方开发板,比如正点原子的I.MX6ULL开发板,那么就使用正点原子提供的uboot源码(也是在半导体厂商的uboot上修改的)。当然了,你也可以在购买了第三方开发板以后使用半导体厂商提供的uboot,只不过有些外设驱动可能不支持,需要自己移植,这个就是我们常说的uboot移植。

本节是uboot的使用,所以就直接使用正点原子已经移植好的uboot,这个已经放到了开发板光盘中了,路径为:开发板光盘->1、程序源码->3、正点原子修改后的Uboot和Linux->uboot-imx-rel_imx_4.1.15_2.1.0_ga_alientek.tar.bz2。

30.2U-Boot初次编译

在Ubuntu中创建存放uboot的目录,比如我的是/home/$USER/linux/uboot,然后在此目录下新建一个名为“alientek_uboot”的文件夹用于存放正点原子提供的uboot源码。alientek_uboot文件夹创建成功以后使用FileZilla软件将正点原子提供的uboot源码拷贝到此目录中,正点原子提供的uboot源码已经放到了开发板光盘中,路径为:开发板光盘->1、例程源码->3、正点原子修改后的Uboot和Linux-> uboot-imx-2016.03-2.1.0-g8b546e4.tar.bz2。将其拷贝到Ubuntu中新建的alientek_uboot文件夹下,完成以后如图30.2.1所示:

图30.2.1将uboot拷贝到Ubuntu中

使用如下命令对其进行解压缩:

tar -vxjf uboot-imx-2016.03-2.1.0-g8b546e4.tar.bz2

解压完成以后alientek_uboot文件夹内容如图30.2.2所示:

图30.2.2 解压后的uboot

图30.2.2中除了uboot-imx-2016.03-2.1.0-g8b546e4.tar.bz2这个正点原子提供的uboot源码压缩包以外,其他的文件和文件夹都是解压出来的uboot源码。

1、512MB(DDR3)+8GB(EMMC)核心板

如果使用的是512MB+8G的EMMC核心板,使用如下命令来编译对应的uboot:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-

mx6ull_14x14_ddr512_emmc_defconfig

make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j12

这三条命令中ARCH=arm设置目标为arm架构,CROSS_COMPILE指定所使用的交叉编译器。第一条命令相当于“makedistclean”,目的是清除工程,一般在第一次编译的时候最好清理一下工程。第二条指令相当于“make mx6ull_14x14_ddr512_emmc_defconfig”,用于配置uboot,配置文件为mx6ull_14x14_ddr512_emmc_defconfig。最后一条指令相当于“make -j12”也就是使用12核来编译uboot。当这三条命令执行完以后uboot也就编译成功了,如图30.2.3所示:

图30.2.3 编译完成

编译完成以后的alentek_uboot文件夹内容如图30.2.4所示:

图30.2.4 编译后的uboot源码

可以看出,编译完成以后uboot源码多了一些文件,其中u-boot.bin就是编译出来的uboot二进制文件。uboot是个裸机程序,因此需要在其前面加上头部(IVT、DCD等数据)才能在I.MX6U上执行,图30.2.4中的u-boot.imx文件就是添加头部以后的u-boot.bin,u-boot.imx就是我们最终要烧写到开发板中的uboot镜像文件。

每次编译uboot都要输入一长串命令,为了简单起见,我们可以新建一个shell脚本文件,将这些命令写到shell脚本文件里面,然后每次只需要执行shell脚本即可完成编译工作。新建名为mx6ull_alientek_emmc.sh的shell脚本文件,然后在里面输入如下内容:

示例代码30.2.1 mx6ull_alientek_emmc.sh文件代码

1 #!/bin/bash

2 make ARCH= arm CROSS_COMPILE= arm- linux- gnueabihf- distclean

3 make ARCH= arm CROSS_COMPILE= arm- linux- gnueabihf- mx6ull_14x14_ddr512_emmc_defconfig

4 make V= 1 ARCH= arm CROSS_COMPILE= arm- linux- gnueabihf-- j12

第1行是shell脚本要求的,必须是“#!/bin/bash”或者“#!/bin/sh”。

第2行使用了make命令,用于清理工程,也就是每次在编译uboot之前都清理一下工程。这里的make命令带有三个参数,第一个是ARCH,也就是指定架构,这里肯定是arm;第二个参数CROSS_COMPILE用于指定编译器,只需要指明编译器前缀就行了,比如arm-linux-gnueabihf-gcc编译器的前缀就是“arm-linux-gnueabihf-”;最后一个参数distclean就是清除工程。

第3行也使用了make命令,用于配置uboot。同样有三个参数,不同的是,最后一个参数是mx6ull_alientek_emmc_defconfig。前面说了uboot是bootloader的一种,可以用来引导Linux,但是uboot除了引导Linux以外还可以引导其它的系统,而且uboot还支持其它的架构和外设,比如USB、网络、SD卡等。这些都是可以配置的,需要什么功能就使能什么功能。所以在编译uboot之前,一定要根据自己的需求配置uboot。mx6ull_alientek_emmc_defconfig就是正点原子针对I.MX6U-ALPHA的EMMC核心板编写的配置文件,这个配置文件在uboot-imx-rel_imx_4.1.15_2.1.0_ga_alientek /configs目录中。在uboot中,通过“makexxx_defconfig”来配置uboot,xxx_defconfig就是不同板子的配置文件,这些配置文件都在uboot/configs目录中。

第4行有4个参数,用于编译uboot,通过第3行配置好uboot以后就可以直接“make”编译uboot了。其中V=1用于设置编译过程的信息输出级别;-j用于设置主机使用多少线程编译uboot,最好设置成我们虚拟机所设置的核心数,如果在VMware里面给虚拟就分配了4个核,那么使用-j4是最合适的,这样4个核都会一起编译。

使用chmod命令给予mx6ull_alientek_emmc.sh文件可执行权限,然后就可以使用这个shell脚本文件来重新编译uboot,命令如下:

./mx6ull_alientek_emmc.sh

1、256MB(DDR3)+256MB/512MB(NAND)核心板

如果用的256MB+256MB/512MB的NAND核心板,新建名为mx6ull_alientek_nand.sh的shell脚本文件,然后在里面输入如下内容:

示例代码30.2.2 mx6ull_alientek_nand.sh文件代码

1 #!/bin/bash

2 make ARCH= arm CROSS_COMPILE= arm- linux- gnueabihf- distclean

3 make ARCH= arm CROSS_COMPILE= arm- linux- gnueabihf- mx6ull_14x14_ddr256_nand_defconfig

4 make V= 1 ARCH= arm CROSS_COMPILE= arm- linux- gnueabihf-- j12

完成以后同样使用chmod指令给予mx6ull_alientek_nand.sh可执行权限,然后输入如下命令即可编译NAND版本的uboot:

./mx6ull_alientek_nand.sh

mx6ull_alientek_nand.sh和mx6ull_alientek_emmc.sh类似,只是uboot配置文件不同,这里就不详细介绍了。

30.3 U-Boot烧写与启动

uboot编译好以后就可以烧写到板子上使用了,这里我们跟前面裸机例程一样,将uboot烧写到SD卡中,然后通过SD卡来启动来运行uboot。使用imxdownload软件烧写,命令如下:

chmod 777 imxdownload //给予imxdownload可执行权限,一次即可

./imxdownload u-boot.bin /dev/sdd

等待烧写完成,完成以后将SD卡插到I.MX6U-ALPHA开发板上,BOOT设置从SD卡启动,使用USB线将USB_TTL和电脑连接,也就是将开发板的串口1连接到电脑上。打开SecureCRT,设置好串口参数并打开,最后复位开发板。在SecureCRT上出现“Hit any key to stop autoboot: ”倒计时的时候按下键盘上的回车键,默认是3秒倒计时,在3秒倒计时结束以后如果没有按下回车键的话uboot就会使用默认参数来启动Linux内核了。如果在3秒倒计时结束之前按下回车键,那么就会进入uboot的命令行模式,如图30.3.1所示:

图30.3.1 uboot启动过程

从图30.3.1可以看出,当进入到uboot的命令行模式以后,左侧会出现一个“=>”标志。uboot启动的时候会输出一些信息,这些信息如下所示:

示例代码30.3.1 uboot输出信息

1 U-Boot 2016.03 (Apr 12 2019 - 02:33:00 +0800)

2

3 CPU: Freescale i.MX6ULL rev1.1 69 MHz (running at 396 MHz)

4 CPU: Industrial temperature grade (-40C to 105C) at 46C

5 Reset cause: POR

6 Board: MX6ULL 14x14 EVK

7 I2C: ready

8 DRAM: 512 MiB

9 MMC: FSL_SDHC: 0, FSL_SDHC: 1

10 Display: ATK-LCD-7-1024x600 (1024x600)

11 Video: 1024x600x24

12 ** Unrecognized filesystem type **

13 In: serial

14 Out: serial

15 Err: serial

16 switch to partitions #0, OK

17 mmc0 is current device

18 Net: FEC1

19 Normal Boot

20 Hit any key to stop autoboot: 0

21 =>

第1行是uboot版本号和编译时间,可以看出,当前的uboot版本号是2016.03,编译时间是2019年4月12日凌晨2点33(没错!为了赶教程和例程,我这一年多以来基本每天晚上工作到凌晨两三点!看到这里一定要记得到论坛夸我一下!)。

第3和第4行是CPU信息,可以看出当前使用的CPU是飞思卡尔的I.MX6ULL(I.MX以前属于飞思卡尔,然而飞思卡尔被NXP收购了),如果使用528MHz的I.MX6ULL,此处会显示主频为528MHz。但是如果使用800MHz的I.MX6ULL的话此处会显示69MHz,这个是uboot内部主频读取错误,但是不影响运行,可以不用管。不管是528MHz还是800MHz的I.MX6ULL,此时都运行在396MHz。这颗芯片是工业级的,可以工作在-40°C~105°C。

第5行是复位原因,当前的复位原因是POR。I.MX6ULL芯片上有个POR_B引脚,将这个引脚拉低即可复位I.MX6ULL。

第6行是板子名字,当前的板子名字为“MX6ULL 14x14 EVK”。

第7行提示I2C准备就绪。

第8行提示当前板子的DRAM(内存)为512MB,如果是NAND版本的话内存为256MB。

第9行提示当前有两个MMC/SD卡控制器:FSL_SDHC(0)和FSL_SDHC(1)。I.MX6ULL支持两个MMC/SD,正点原子的I.MX6ULL EMMC核心板上FSL_SDHC(0)接的EMMC,FSL_SDHC(1)接的SD(TF)卡。

第10和第11行是LCD型号,当前的LCD型号是ATK-LCD-7-1024x600 (1024x600),分辨率为1024x600,格式为RGB888(24位)。

第13~15是标准输入、标准输出和标准错误所使用的终端,这里都使用串口(serial)作为终端。

第16和17行是切换到emmc的第0个分区上,因为当前的uboot是emmc版本的,也就是从emmc启动的。我们只是为了方便将其烧写到了SD卡上,但是它的“内心”还是EMMC的。所以uboot启动以后会将emmc作为默认存储器,当然了,你也可以将SD卡作为uboot的存储器,这个我们后面会讲解怎么做。

第18行是网口信息,提示我们当前使用的FEC1这个网口,I.MX6ULL支持两个网口。

第19行提示正常启动,也就是说uboot要从emmc里面读取环境变量和参数信息启动Linux内核了。

第20行是倒计时提示,默认倒计时3秒,倒计时结束之前按下回车键就会进入Linux命令行模式。如果在倒计时结束以后没有按下回车键,那么Linux内核就会启动,Linux内核一旦启动,uboot就会寿终正寝。

这个就是uboot默认输出信息的含义,NAND版本的uboot也是类似的,只是NAND版本的就没有EMMC/SD相关信息了,取而代之的就是NAND的信息,比如NAND容量大小信息。

uboot是来干活的,我们现在已经进入uboot的命令行模式了,进入命令行模式以后就可以给uboot发号施令了。当然了,不能随便发号施令,得看看uboot支持哪些命令,然后使用这些uboot所支持的命令来做一些工作。下一节就讲解uboot命令的使用。

30.4U-Boot命令使用

进入uboot的命令行模式以后输入“help”或者“?”,然后按下回车即可查看当前uboot所支持的命令,如图30.4.1所示:

图30.4.1 uboot命令列表

图30.4.1中只是uboot的一部分命令,具体的命令列表以实际为准。图30.4.1中的命令并不是uboot所支持的所有命令,前面说过uboot是可配置的,需要什么命令就使能什么命令。所以图30.4.1中的命令是正点原子提供的uboot中使能的命令,uboot支持的命令还有很多,而且也可以在uboot中自定义命令。这些命令后面都跟有命令说明,用于描述此命令的作用,但是命令具体怎么用呢?我们输入“help(或?)命令名”既可以查看命令的详细用法,以“bootz”这个命令为例,我们输入如下命令即可查看“bootz”这个命令的用法:

? bootz 或 helpbootz

结果如图30.4.2所示:

图30.4.2bootz命令使用说明

图30.4.2中就详细的列出了“bootz”这个命令的详细,其它的命令也可以使用此方法查询具体的使用方法。接下来我们学习一下一些常用的uboot命令。

30.4.1信息查询命令

常用的和信息查询有关的命令有3个:bdinfo、printenv和version。先来看一下bdinfo命令,此命令用于查看板子信息,直接输入“bdinfo”即可,结果如图30.4.1.1所示:

图30.4.1.1bdinfo命令

从图30.4.1.1中可以得出DRAM的其实地址和大小、启动参数保存起始地址、波特率、sp(堆栈指针)起始地址等信息。

命令“printenv”用于输出环境变量信息,uboot也支持TAB键自动补全功能,输入“print”然后按下TAB键就会自动补全命令,直接输入“print”也可以。输入“print”,然后按下回车键,环境变量如图30.4.1.2所示:

图30.4.1.2printenv命令结果

在图30.4.1.2中有很多的环境变量,比如baudrate、board_name、board_rec、boot_fdt、bootcmd等等。uboot中的环境变量都是字符串,既然叫做环境变量,那么它的作用就和“变量”一样。比如bootdelay这个环境变量就表示uboot启动延时时间,默认bootdelay=3,也就默认延时3秒。前面说的3秒倒计时就是由bootdelay定义的,如果将bootdelay改为5的话就会倒计时5s了。uboot中的环境变量是可以修改的,有专门的命令来修改环境变量的值,稍后我们会讲解。

命令version用于查看uboot的版本号,输入“version”,uboot版本号如图30.4.1.3所示:

图30.4.1.3version命令结果

从图30.4.1.3可以看出,当前uboot版本号为2016.03,2019年4月12日编译的,编译器为arm-linux-gnueabihf-gcc等信息。

30.4.2环境变量操作命令

1、修改环境变量

环境变量的操作涉及到两个命令:setenv和saveenv,命令setenv用于设置或者修改环境变量的值。命令saveenv用于保存修改后的环境变量,一般环境变量是存放在外部flash中的,uboot启动的时候会将环境变量从flash读取到DRAM中。所以使用命令setenv修改的是DRAM中的环境变量值,修改以后要使用saveenv命令将修改后的环境变量保存到flash中,否则的话uboot下一次重启会继续使用以前的环境变量值。

命令saveenv使用起来很简单,格式为:

saveenv命令值

saveenv命令‘值1值2值3’

比如我们要将环境变量bootdelay改为5,就可以使用如下所示命令:

setenvbootdelay5

saveenv

上述命令执行过程如图30.4.2.1所示:

图30.4.2.1环境变量修改

在图30.4.2.1中,当我们使用命令saveenv保存修改后的环境变量的话会有保存过程提示信息,根据提示可以看出环境变量保存到了MMC(1)中,也就是EMMC中。因为我用的EMMC版本的核心板,所以会保存到MMC(1)中,如果是NAND版本核心板的话就会提示保存到NAND中。

修改bootdelay以后,重启开发板,uboot就是变为5秒倒计时,如图30.4.2.2所示:

图30.4.2.25秒倒计时

有时候我们修改的环境变量值可能会有空格,比如bootcmd、bootargs等,这个时候环境变量值就得用单引号括起来,比如下面修改环境变量bootcmd的值:

setenv bootcmd 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'

saveenv

上面命令设置bootcmd的值为“console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw”,其中“console=ttymxc0,115200”、“root=/dev/mmcblk1p2”、“rootwait”和“rw”相当于四组“值”,这四组“值”之间用空格隔开,所以需要使用单引号‘’将其括起来,表示这四组“值”都属于环境变量bootcmd。

2、新建环境变量

命令setenv也可以用于新建命令,用法就是修改环境变量一样,比如我们新建一个环境变量author,author的值为我的名字拼音:zuozhongkai,那么就可以使用如下命令:

setenv author zuozhongkai

saveenv

新建命令author完成以后重启uboot,然后使用命令printenv查看当前环境变量,如图30.4.2.3所示:

图30.4.2.3环境变量

从图30.4.2.3可以看到新建的环境变量:author,其值为:zuozhongkai。

3、删除环境变量

既然可以新建环境变量,那么就可以删除环境变量,删除环境变量也是使用命令setenv,要删除一个环境变量只要给这个环境变量赋空值即可,比如我们删除掉上面新建的author这个环境变量,命令如下:

setenv author

saveenv

上面命令中通过setenv给author赋空值,也就是什么都不写来删除环境变量author。重启uboot就会发现环境变量author没有了。

30.4.3内存操作命令

内存操作命令就是用于直接对DRAM进行读写操作的,常用的内存操作命令有md、nm、mm、mw、cp和cmp。我们依次来看一下这些命令都是做什么的。

1、md命令

md命令用于显示内存值,格式如下:

md[.b, .w, .l] address [# of objects]

命令中的[.b .w .l]对应byte、word和long,也就是分别以1个字节、2个字节、4个字节来显示内存值。address就是要查看的内存起始地址,[# of objects]表示要查看的数据长度,这个数据长度单位不是字节,而是跟你所选择的显示格式有关。比如你设置要查看的内存长度为20(十六进制为0x14),如果显示格式为.b的话那就表示20个字节;如果显示格式为.w的话就表示20个word,也就是20*2=40个字节;如果显示格式为.l的话就表示20个long,也就是20*4=80个字节。另外要注意:

uboot命令中的数字都是十六进制的!不是十进制的!

比如你想查看以0X80000000开始的20个字节的内存值,显示格式为.b的话,应该使用如下所示命令:

md.b 80000000 14

而不是:

md.b 80000000 20

上面说了,uboot命令里面的数字都是十六进制的,所以可以不用写“0x”前缀,十进制的20其十六进制为0x14,所以命令md后面的个数应该是14,如果写成20的话就表示查看32(十六进制为0x20)个字节的数据。分析下面三个命令的区别:

md.b 80000000 10

md.w 80000000 10

md.l 80000000 10

上面这三个命令都是查看以0X80000000为起始地址的内存数据,第一个命令以.b格式显示,长度为0x10,也就是16个字节;第二个命令以.w格式显示,长度为0x10,也就是16*2=32个字节;最后一个命令以.l格式显示,长度也是0x10,也就是16*4=64个字节。这三个命令的执行结果如图30.4.3.1所示:

图30.4.3.1md命令使用示例

2、nm命令

nm命令用于修改指定地址的内存值,命令格式如下:

nm [.b, .w, .l] address

nm命令同样可以以.b、.w和.l来指定操作格式,比如现在以.l格式修改0x80000000地址的数据为0x12345678。输入命令:

nm.l 80000000

输入上述命令以后如图30.4.3.2所示:

图30.4.3.2nm命令

在图30.4.3.2中,80000000表示现在要修改的内存地址,ffffff00表示地址0x80000000现在的数据,?后面就可以输入要修改后的数据0x12345678,输入完成以后按下回车,然后再输入‘q’即可退出,如图30.4.3.3所示:

图30.4.3.3修改内存数据

修改完成以后在使用命令md来查看一下有没有修改成功,如图30.4.3.4所示:

图30.4.3.4查看修改后的值

从图30.4.3.4可以看出,此时地址0X80000000的值变为了0x12345678。

3、mm命令

mm命令也是修改指定地址内存值的,使用mm修改内存值的时候地址会自增,而使用命令nm的话地址不会自增。比如以.l格式修改从地址0x80000000开始的连续3个内存块(3*4=12个字节)的数据为0X05050505,操作如图30.4.3.5所示:

图30.4.3.5命令mm

从图30.4.3.5可以看出,修改了地址0X80000000、0X80000004和0X8000000C的内容为0x05050505。使用命令md查看修改后的值,结果如图30.4.3.6所示:

图30.4.3.6查看修改后的内存数据

从图30.4.3.6可以看出内存数据修改成功。

4、mw命令

命令mw用于使用一个指定的数据填充一段内存,命令格式如下:

mw [.b, .w, .l] address value [count]

mw命令同样可以以.b、.w和.l来指定操作格式,address表示要填充的内存起始地址,value为要填充的数据,count是填充的长度。比如使用.l格式将以0X80000000为起始地址的0x10个内存块(0x10 * 4=64字节)填充为0X0A0A0A0A,命令如下:

mw.l 80000000 0A0A0A0A 10

然后使用命令md来查看,如图30.4.3.7所示:

图30.4.3.7查看修改后的内存数据

从图30.4.3.7可以看出内存数据修改成功。

5、cp命令

cp是数据拷贝命令,用于将DRAM中的数据从一段内存拷贝到另一段内存中,或者把Nor Flash中的数据拷贝到DRAM中。命令格式如下:

cp [.b, .w, .l] source target count

cp命令同样可以以.b、.w和.l来指定操作格式,source为源地址,target为目的地址,count为拷贝的长度。我们使用.l格式将0x80000000处的地址拷贝到0X80000100处,长度为0x10个内存块(0x10*4=64个字节),命令如下所示:

cp.l 80000000 80000100 10

结果如图30.4.3.8所示:

图30.4.3.8cp命令操作结果

在图30.4.3.8中,先使用md.l命令打印出地址0x80000000和0x80000100处的数据,然后使用命令cp.l将0x80000100处的数据拷贝到0x80000100处。最后使用命令md.l查看0x80000100处的数据有没有变化,检查拷贝是否成功。

6、cmp命令

cmp是比较命令,用于比较两段内存的数据是否相等,命令格式如下:

cmp [.b, .w, .l] addr1 addr2 count

cmp命令同样可以以.b、.w和.l来指定操作格式,addr1为第一段内存首地址,addr2为第二段内存首地址,count为要比较的长度。我们使用.l格式来比较0x80000000和0X80000100这两个地址数据是否相等,比较长度为0x10个内存块(16*4=64个字节),命令如下所示:

cmp.l 80000000 80000100 10

结果如图30.4.3.9所示:

图30.4.3.9 cmp命令比较结果

从图30.4.3.9可以看出两段内存的数据相等。我们再随便挑两段内存比较一下,比如地址0x80002000和0x800003000,长度为0X10,比较结果如图30.4.3.10所示:

图30.4.3.10cmp命令比较结果

从图30.4.3.10可以看出,0x80002000处的数据和0x80003000处的数据就不一样。

30.4.4网络操作命令

uboot是支持网络的,我们在移植uboot的时候一般都要调通网络功能,因为在移植linuxkernel的时候需要使用到uboot的网络功能做调试。uboot支持大量的网络相关命令,比如dhcp、ping、nfs和tftpboot,我们接下来依次学习一下这几个和网络有关的命令。

在使用uboot的网络功能之前先用网线将开发板的ENET2接口和电脑或者路由器连接起来,I.MX6U-ALPHA开发板有两个网口:ENET1和ENET2,一定要连接ENET2,不能连接错了,ENET2接口如图30.4.4.1所示。

图30.4.4.1 ENET2网络接口

建议开发板和主机PC都连接到同一个路由器上!最后设置表30.4.4.1中所示的几个环境变量。

环境变量

描述

ipaddr

开发板ip地址,可以不设置,使用dhcp命令来从路由器获取IP地址。

ethaddr

开发板的MAC地址,一定要设置。

gatewayip

网关地址。

netmask

子网掩码。

serverip

服务器IP地址,也就是Ubuntu主机IP地址,用于调试代码。

表30.4.4.1网络相关环境变量

表30.4.4.1中环境变量设置命令如下所示:

setenv ipaddr 192.168.1.50

setenv ethaddr 00:04:9f:04:d2:35

setenv gatewayip 192.168.1.1

setenv netmask 255.255.255.0

setenv serverip 192.168.1.250

saveenv

注意,网络地址环境变量的设置要根据自己的实际情况,确保Ubuntu主机和开发板的IP地址在同一个网段内,比如我现在的开发板和电脑都在192.168.1.0这个网段内,所以设置开发板的IP地址为192.168.1.50,我的Ubuntu主机的地址为192.168.1.250,因此serverip就是192.168.1.250。ethaddr为网络MAC地址,是一个48bit的地址,如果在同一个网段内有多个开发板的话一定要保证每个开发板的ethaddr是不同的,否则通信会有问题!设置好网络相关的环境变量以后就可以使用网络相关命令了。

1、ping命令

开发板的网络能否使用,是否可以和服务器(Ubuntu主机)进行通信,通过ping命令就可以验证,直接ping服务器的IP地址即可,比如我的服务器IP地址为192.168.1.250,命令如下:

ping192.168.1.250

结果如图30.4.4.2所示:

图30.4.4.2ping命令

从图30.4.4.2可以看出,192.168.1.250这个主机存在,说明ping成功,uboot的网络工作正常。

2、dhcp命令

dhcp用于从路由器获取IP地址,前提得开发板连接到路由器上的,如果开发板是和电脑直连的,那么dhcp命令就会失效。直接输入dhcp命令即可通过路由器获取到IP地址,如图30.4.4.3所示:

图30.4.4.3dhcp命令

从图30.4.4.3可以看出,开发板通过dhcp获取到的IP地址为192.168.1.50,和我们手动设置的一样,这很正常。同时在图30.4.4.3中可以看到“warning:nobootfilename;”、“TFTP fromserver192.168.1.1”这样的字样。这是因为DHCP不单单是获取IP地址,其还会通过TFTP来启动linux内核,输入“? dhcp”即可查看dhcp命令详细的信息,如图30.4.4.4所示:

图30.4.4.4dhcp命令使用查询

3、nfs命令

nfs也就是网络文件系统,通过nfs可以在计算机之间通过网络来分享资源,比如我们将linux镜像和设备树文件放到Ubuntu中,然后在uboot中使用nfs命令将Ubuntu中的linux镜像和设备树下载到开发板的DRAM中。这样做的目的是为了方便调试linux镜像和设备树,也就是网络调试,通过网络调试是Linux开发中最常用的调试方法。原因是嵌入式linux开发不像单片机开发,可以直接通过JLINK或STLink等仿真器将代码直接烧写到单片机内部的flash中,嵌入式Linux通常是烧写到EMMC、NAND Flash、SPI Flash等外置flash中,但是嵌入式Linux开发也没有MDK,IAR这样的IDE,更没有烧写算法,因此不可能通过点击一个“download”按钮就将固件烧写到外部flash中。虽然半导体厂商一般都会提供一个烧写固件的软件,但是这个软件使用起来比较复杂,这个烧写软件一般用于量产的。其远没有MDK、IAR的一键下载方便,在Linux内核调试阶段,如果用这个烧写软件的话将会非常浪费时间,而这个时候网络调试的优势就显现出来了,可以通过网络将编译好的linux镜像和设备树文件下载到DRAM中,然后就可以直接运行。

我们一般使用uboot中的nfs命令将Ubuntu中的文件下载到开发板的DRAM中,在使用之前需要开启Ubuntu主机的NFS服务,并且要新建一个NFS使用的目录,以后所有要通过NFS访问的文件都需要放到这个NFS目录中。Ubuntu的NFS服务开启我们在4.2.1小节已经详细讲解过了,包括NFS文件目录的创建,如果忘记的话可以去查看一下4.2.1小节。我设置的/home/zuozhongkai/linux/nfs这个目录为我的NFS文件目录。uboot中的nfs命令格式如下所示:

nfs [loadAddress] [[hostIPaddr:]bootfilename]

loadAddress是要保存的DRAM地址,[[hostIPaddr:]bootfilename]是要下载的文件地址。这里我们将正点原子官方编译出来的Linux镜像文件zImage下载到开发板DRAM的0x80800000这个地址处。正点原子编译出来的zImage文件已经放到了开发板光盘中,路径为:8、开发板系统镜像->zImage。将文件zImage通过FileZilla发送到Ubuntu中的NFS目录下,比如我的就是放到/home/zuozhongkai/linux/nfs这个目录下,完成以后的NFS目录如图30.4.4.5所示:

图30.4.4.5 NFS目录中的zImage文件

准备好以后就可以使用nfs命令来将zImage下载到开发板DRAM的0X80800000地址处,命令如下:

nfs 80800000 192.168.1.250:/home/zuozhongkai/linux/nfs/zImage

命令中的“80800000”表示zImage保存地址,“192.168.1.250:/home/zuozhongkai/linux/nfs/zImage”表示zImage在192.168.1.250这个主机中,路径为/home/zuozhongkai/linux/nfs/zImage。下载过程如图30.4.4.6所示:

图30.4.4.6nfs命令下载zImage过程

在图30.4.4.6中会以“#”提示下载过程,下载完成以后会提示下载的数据大小,这里下载的6071136字节,而zImage的大小就是6071136字节,如图30.4.4.7所示:

图30.4.4.7zImage大小

下载完成以后查看0x80800000地址处的数据,使用命令md.b来查看前100个字节的数据,如图30.4.4.8所示:

图30.4.4.8下载的数据

在使用winhex软件来查看zImage,检查一下前面的数据是否和图30.4.4.8只的一致,结果如图30.4.4.9所示:

图30.4.4.9winhex查看zImage

可以看出图30.4.4.8和图30.4.4.9中的前100个字节的数据一致,说明nfs命令下载到的zImage是正确的。

4、tftp命令

tftp命令的作用和nfs命令一样,都是用于通过网络下载东西到DRAM中,只是tftp命令使用的TFTP协议,Ubuntu主机作为TFTP服务器。因此需要在Ubuntu上搭建TFTP服务器,需要安装tftp-hpa和tftpd-hpa,命令如下:

sudo apt-get install tftp-hpa tftpd-hpa

和NFS一样,TFTP也需要一个文件夹来存放文件,在用户目录下新建一个目录,命令如下:

mkdir/home/zuozhongkai/linux/tftpboot

chmod 777 /home/zuozhongkai/linux/tftpboot

这样我就在我的电脑上创建了一个名为tftpboot的目录(文件夹),路径为/home/zuozhongkai/linux/tftpboot。注意!我们要给tftpboot文件夹权限,否则的话uboot不能从tftpboot文件夹里面下载文件。

最后配置tftp,打开文件安装完成以后新建文件/etc/xinetd.d/tftp,然后在里面输入如下内容:

示例代码30.4.4.1 /etc/xinetd.d/tftp文件内容

1 server tftp

2{

3 socket_type = dgram

4 protocol = udp

5 wait = yes

6 user = root

7 server =/usr/sbin/ in. tftpd

8 server_args =- s / home/ zuozhongkai/ linux/ tftpboot/

9 disable = no

10 per_source = 11

11 cps = 1002

12 flags = IPv4

13}

完了以后启动tftp服务,命令如下:

sudo service tftpd-hpa start

打开/etc/default/tftpd-hpa文件,将其修改为如下所示内容:

示例代码30.4.4.2 /etc/default/tftpd-hpa文件内容

1 # / etc/default/ tftpd- hpa

2

3 TFTP_USERNAME= "tftp"

4 TFTP_DIRECTORY= "/home/zuozhongkai/linux/tftpboot"

5 TFTP_ADDRESS= ":69"

6 TFTP_OPTIONS= "-l -c -s"

TFTP_DIRECTORY就是我们上面创建的tftp文件夹目录,以后我们就将所有需要通过TFTP传输的文件都放到这个文件夹里面,并且要给予这些文件相应的权限。

最后输入如下命令,重启tftp服务器:

sudo service tftpd-hpa restart

tftp服务器已经搭建好了,接下来就是使用了。将zImage镜像文件拷贝到tftpboot文件夹中,并且给予zImage相应的权限,命令如下:

cp zImage /home/zuozhongkai/linux/tftpboot/

cd /home/zuozhongkai/linux/tftpboot/

chmod 777 zImage

万事俱备,只剩验证了,uboot中的tftp命令格式如下:

tftpboot [loadAddress] [[hostIPaddr:]bootfilename]

看起来和nfs命令格式一样的,loadAddress是文件在DRAM中的存放地址,[[hostIPaddr:]bootfilename]是要从Ubuntu中下载的文件。但是和nfs命令的区别在于,tftp命令不需要输入文件在Ubuntu中的完整路径,只需要输入文件名即可。比如我们现在将tftpboot文件夹里面的zImage文件下载到开发板DRAM的0X80800000地址处,命令如下:

tftp 80800000 zImage

下载过程如图30.4.4.10所示:

图30.4.4.10 tftp命令下载过程

从图30.4.4.10可以看出,zImage下载成功了,网速为1.4MibB/s,文件大小为6071136字节。同样的,可以使用md.b命令来查看前100个字节的数据是否和图30.4.4.9中的相等。有时候使用fttp命令从Ubuntu中下载文件的时候会出现如图30.4.4.11所示的错误提示:

图30.4.4.11 tftp下载出错

在图30.4.4.11中可以看到“TFTP error: 'Permission denied' (0)”这样的错误提示,提示没有权限,出现这个错误一般有两个原因:

①、在Ubuntu中创建tftpboot目录的时候没有给予tftboot相应的权限。

②、tftpboot目录中要下载的文件没有给予相应的权限。

针对上述两个问题,使用命令“chmod777xxx”来给予权限,其中“xxx”就是要给予权限的文件或文件夹。

好了,uboot中关于网络的命令就讲解到这里,我们最常用的就是ping、nfs和tftp这三个命令。使用ping命令来查看网络的连接状态,使用nfs和tftp命令来从Ubuntu主机中下载文件。

30.4.5 EMMC和SD卡操作命令

uboot支持EMMC和SD卡,因此也要提供EMMC和SD卡的操作命令。一般认为EMMC和SD卡是同一个东西,所以没有特殊说明,本教程统一使用MMC来代指EMMC和SD卡。uboot中常用于操作MMC设备的命令为“mmc”。

mmc是一系列的命令,其后可以跟不同的参数,输入“?mmc”即可查看mmc有关的命令,如图30.4.5.1所示:

图30.4.5.1mmc命令

从图30.4.5.1可以看出,mmc后面跟不同的参数可以实现不同的功能,如表30.4.5.1所示:

命令

描述

mmc info

输出MMC设备信息

mmc read

读取MMC中的数据。

mmc wirte

向MMC设备写入数据。

mmc rescan

扫描MMC设备。

mmcpart

列出MMC设备的分区。

mmc dev

切换MMC设备。

mmc list

列出当前有效的所有MMC设备。

mmc hwpartition

设置MMC设备的分区。

mmc bootbus……

设置指定MMC设备的BOOT_BUS_WIDTH域的值。

mmc bootpart……

设置指定MMC设备的boot和RPMB分区的大小。

mmc partconf……

设置指定MMC设备的PARTITION_CONFG域的值。

mmc rst

复位MMC设备

mmc setdsr

设置DSR寄存器的值。

表30.4.5.1mmc命令

1、mmcinfo命令

mmcinfo命令用于输出当前选中的mmcinfo设备的信息,输入命令“mmcinfo”即可,如图30.4.5.2所示:

图30.4.5.2mmcinfo命令

从图30.4.5.2可以看出,当前选中的MMC设备是EMMC,版本为4.5,容量为3.7GiB(EMMC为4GB),速度为52000000Hz=52MHz,8位宽的总线。还有一个与mmcinfo命令相同功能的命令:mmcinfo,“mmc”和“info”之间没有空格。

2、mmcrescan命令

mmcrescan命令用于扫描当前开发板上所有的MMC设备,包括EMMC和SD卡,输入“mmcrescan”即可。

3、mmclist命令

mmclist命令用于来查看当前开发板一共有几个MMC设备,输入“mmclist”,结果如图30.4.5.3所示:

图30.4.5.3扫描MMC设备

可以看出当前开发板有两个MMC设备:FSL_SDHC:0和FSL_SDHC:1 (eMMC),这是因为我现在用的是EMMC版本的核心板,加上SD卡一共有两个MMC设备,FSL_SDHC:0是SD卡,FSL_SDHC:1(eMMC)是EMMC,。默认会将EMMC设置为当前MMC设备,这就是为什么输入“mmcinfo”查询到的是EMMC设备信息,而不是SD卡。要想查看SD卡信息,就要使用命令“mmcdev”来将SD卡设置为当前的MMC设备。

4、mmcdev命令

mmcdev命令用于切换当前MMC设备,命令格式如下:

mmc dev [dev] [part]

[dev]用来设置要切换的MMC设备号,[part]是分区号。如果不写分区号的话默认为分区0。使用如下命令切换到SD卡:

mmc dev 0 //切换到SD卡,0为SD卡,1为eMMC

结果如图30.4.5.4所示:

图30.4.5.4切换到SD卡

从图30.4.5.4可以看出,切换到SD卡成功,mmc0为当前的MMC设备,输入命令“mmcinfo”即可查看SD卡的信息,结果如图30.4.5.5所示:

图30.4.5.5SD信息

从图30.4.5.5可以看出当前SD卡为3.0版本的,容量为14.8GiB(16GB的SD卡),4位宽的总线。

5、mmcpart命令

有时候SD卡或者EMMC会有多个分区,可以使用命令“mmcpart”来查看其分区,比如查看EMMC的分区情况,输入如下命令:

mmcdev1 //切换到EMMC

mmcpart //查看EMMC分区

结果如图30.4.5.6所示:

图30.4.5.6查看EMMC分区

从图30.4.5.6中可以看出,此时EMMC有两个分区,扇区20480~1024000为第一个分区,扇区1228800~6504448为第二个分区。如果EMMC里面烧写了Linux系统的话,EMMC是有3个分区的,第0个分区存放uboot,第1个分区存放Linux镜像文件和设备树,第2个分区存放根文件系统。但是在图30.4.5.6中只有两个分区,那是因为第0个分区没有格式化,所以识别不出来,实际上第0个分区是存在的。一个新的SD卡默认只有一个分区,那就是分区0,所以前面讲解的uboot烧写到SD卡,其实就是将u-boot.bin烧写到了SD卡的分区0里面。后面学习Linux内核移植的时候再讲解怎么在SD卡中创建并格式化第二个分区,并将Linux镜像文件和设备树文件存放到第二个分区中。

如果要将EMMC的分区2设置为当前MMC设置,可以使用如下命令:

mmcdev12

结果如图30.4.5.7所示:

图30.4.5.7设置EMMC分区2为当前设备

6、mmcread命令

mmc read命令用于读取mmc设备的数据,命令格式如下:

mmc read addr blk# cnt

addr是数据读取到DRAM中的地址,blk是要读取的块起始地址(十六进制),一个块是512字节,这里的块和扇区是一个意思,在MMC设备中我们通常说扇区,cnt是要读取的块数量(十六进制)。比如从EMMC的第1536(0x600)个块开始,读取16(0x10)个块的数据到DRAM的0X80800000地址处,命令如下:

mmc dev 1 0 //切换到MMC分区0

mmc read 80800000 600 10 //读取数据

结果如图30.4.5.8所示:

图30.4.5.8mmcread命令

这里我们还看不出来读取是否正确,通过md.b命令查看0x80800000处的数据就行了,查看16*512=8192(0x2000)个字节的数据,命令如下:

md.b 80800000 2000

结果如图30.4.5.9所示:

图30.4.5.9读取到的数据(部分截图)

从图30.4.5.9可以看到“D$..baudrate=115200.board_name=EVK.board_rev=14X14.”等字样,这个就是uboot中的环境变量。EMMC核心板uboot环境变量的存储起始地址就是1536*512=786432。

7、mmcwrite命令

要将数据写到MMC设备里面,可以使用命令“mmcwrite”,格式如下:

mmc write addr blk# cnt

addr是要写入MMC中的数据在DRAM中的起始地址,blk是要写入MMC的块起始地址(十六进制),cnt是要写入的块大小,一个块为512字节。我们可以使用命令“mmcwrite”来升级uboot,也就是在uboot中更新uboot。这里要用到nfs或者tftp命令,通过nfs或者tftp命令将新的u-boot.bin下载到开发板的DRAM中,然后再使用命令“mmcwrite”将其写入到MMC设备中。我们就来更新一下SD中的uboot,先查看一下SD卡中的uboot版本号,注意编译时间,输入命令:

mmcdev0 //切换到SD卡

version //查看版本号

结果如图30.4.5.10所示:

图30.4.5.10uboot版本查询

可以看出当前SD卡中的uboot是2019年4月15日12:52:04编译的。我们现在重新编译一下uboot,然后将编译出来的u-boot.imx(u-boot.bin前面加了一些头文件)拷贝到Ubuntu中的tftpboot目录下。最后使用tftp命令将其下载到0x80800000地址处,命令如下:

tftp 80800000 u-boot.imx

下载过程如图30.4.5.11所示:

图30.4.5.11u-boot.imx下载过程

可以看出,u-boot.imx大小为 416768字节,416768/512=814,所以我们要向SD卡中写入814个块,如果有小数的话就要加1个块。使用命令“mmcwrite”从SD卡分区0第2个块(扇区)开始烧写,一共烧写814(0x32E)个块,命令如下:

mmc dev 0 0

mmc write 80800000 2 32E

烧写过程如图30.4.5.12所示:

图30.4.5.12烧写过程

烧写成功,重启开发板(从SD卡启动),重启以后再输入version来查看版本号,结果如图30.4.5.13所示:

图30.4.5.13uboot版本号

从图30.4.5.13可以看出,此时的uboot是2019年4月21号18:05:59编译的,这个时间就是我刚刚编译uboot的时间,说明uboot更新成功。这里我们就学会了如何在uboot中更新uboot了,如果要更新EMMC中的uboot也是一样的。

千万不要写SD卡或者EMMC的前两个块(扇区),里面保存着分区表!

千万不要写SD卡或者EMMC的前两个块(扇区),里面保存着分区表!

千万不要写SD卡或者EMMC的前两个块(扇区),里面保存着分区表!

8、mmcerase命令

如果要擦除MMC设备的指定块就是用命令“mmcerase”,命令格式如下:

mmc erase blk# cnt

blk为要擦除的起始块,cnt是要擦除的数量。没事不要用mmcerase来擦除MMC设备!!!

关于MMC设备相关的命令就讲解到这里,表30.4.5.1中还有一些跟MMC设备操作有关的命令,但是很少用到,这里就不讲解了,感兴趣的可以上网查一下,或者在uboot中查看这些命令的使用方法。

30.4.6 FAT格式文件系统操作命令

有时候需要在uboot中对SD卡或者EMMC中存储的文件进行操作,这时候就要用到文件操作命令,跟文件操作相关的命令有:fatinfo、fatls、fstype、fatload和fatwrite,但是这些文件操作命令只支持FAT格式的文件系统!!

1、fatinfo命令

fatinfo命令用于查询指定MMC设置指定分区的文件系统信息,格式如下:

fatinfo <interface> [<dev[:part]>]

interface表示接口,比如mmc,dev是查询的设备号,part是要查询的分区。比如我们要查询EMMC分区1的文件系统信息,命令如下:

fatinfo mmc 1:1

结果如图30.4.6.1所示:

图30.4.6.1emmc分区1文件系统信息

从上图可以看出,EMMC分区1的文件系统为FAT16格式的。

2、fatls命令

fatls命令用于查询FAT格式设备的目录和文件信息,命令格式如下:

fatls <interface> [<dev[:part]>] [directory]

interface是要查询的接口,比如mmc,dev是要查询的设备号,part是要查询的分区,directory是要查询的目录。比如查询EMMC分区1中的所有的目录和文件,输入命令:

fatls mmc 1:1

结果如图30.4.6.2所示:

图30.4.6.2 EMMC分区1文件查询

从上图可以看出,emmc的分区1中存放着两个文件:zimage和imx6ull-14x14-evk.dtb,这两个文件分别是linux镜像文件和设备树。并且在emmc的分区1中有两个文件,没有目录

3、fstype命令

fstype用于查看MMC设备某个分区的文件系统格式,命令格式如下:

fstype <interface><dev>:<part>

正点原子EMMC核心板上的EMMC默认有3个分区,我们来查看一下这三个分区的文件系统格式,输入命令:

fstypemmc1:0

fstype mmc 1:1

fstype mmc 1:2

结果如图30.4.6.3所示:

图30.4.6.3fstype命令

从上图可以看出,分区0格式未知,因为分区0存放的uboot,并且分区0没有格式化,所以文件系统格式未知。分区1的格式为fat,分区1用于存放linux镜像和设备树。分区2的格式为ext4,用于存放Linux的跟文件系统。

4、fatload命令

fatload命令用于将指定的文件读取到DRAM中,命令格式如下:

fatload <interface> [<dev[:part]> [<addr> [<filename> [bytes [pos]]]]]

interface为接口,比如mmc,dev是设备号,part是分区,addr是保存在DRAM中的起始地址,filename是要读取的文件名字。bytes表示读取多少字节的数据,如果bytes为0或者省略的话表示读取整个文件。pos是要读的文件相对于文件首地址的偏移,如果为0或者省略的话表示从文件首地址开始读取。我们将EMMC分区1中的zImage文件读取到DRAM中的0X80800000地址处,命令如下:

fatload mmc 1:1 80800000 zImage

操作过程如图30.4.6.4所示:

图30.4.6.4读取过程

从上图可以看出在153ms内读取了6071136个字节的数据,速度为37.8MiB/s,速度是非常快的,因为这是从EMMC里面读取的,而EMMC是8位的,速度肯定会很快的。

5、fatwrite命令

fatwirte命令用于将DRAM中的数据写入到MMC设备中,命令格式如下:

fatwrite <interface><dev[:part]><addr><filename><bytes>

interface为接口,比如mmc,dev是设备号,part是分区,addr是要写入的数据在DRAM中的起始地址,filename是写入的数据文件名字,bytes表示要写入多少自己的数据。我们可以通过fatwrite命令在uboot中更新linux镜像文件和设备树。我们以更新linux镜像文件zImage为例,首先将正点原子I.MX6U-ALPHA开发板提供的zImage镜像文件拷贝到Ubuntu中的tftpboot目录下,zImage镜像文件放到了开发板光盘中,路径为:开发板光盘->8、开发板系统镜像->zImage。拷贝完成以后的tftpboot目录如图30.4.6.5所示:

图30.4.6.5zImage放到tftpboot目录中。

使用命令tftp将zImage下载到DRAM的0X80800000地址处,命令如下:

tftp 80800000 zImage

下载过程如图30.4.6.6所示:

图30.4.6.6zImage下载过程

zImage大小为6039328(0X5C2720)个字节,接下来使用命令fatwrite将其写入到EMMC的分区1中,文件名字为zImage,命令如下:

fatwrite mmc 1:1 80800000 zImage 0x5c2720

结果如图30.4.6.7所示:

图30.4.6.7将zImage烧写到EMMC扇区1中

完成以后使用“fatls”命令查看一下EMMC分区1里面的文件,结果如图30.4.6.8所示:

图30.4.6.8 EMMC分区1里面的文件

30.4.7 EXT格式文件系统操作命令

uboot有ext2和ext4这两种格式的文件系统的操作命令,常用的就四个命令,分别为:ext2load、ext2ls、ext4load、ext4ls和ext4write。这些命令的含义和使用与fatload、fatls和fatwrit一样,只是ext2和ext4都是针对ext文件系统的。比如ext4ls命令,EMMC的分区2就是ext4格式的,使用ext4ls就可以查询EMMC的分区2中的文件和目录,输入命令:

ext4ls mmc 1:2

结果如图30.4.7.1所示:

图30.4.7.1ext4ls命令

关于ext格式文件系统其他命令的操作参考30.4.6小节的即可,这里就不讲解了。

30.4.8 NAND操作命令

uboot是支持NAND Flash的,所以也有NAND Flash的操作命令,前提是使用的NAND版本的核心板,并且编译NAND核心板对应的uboot,然后使用imxdownload软件将u-boot.bin烧写到SD卡中,最后通过SD卡启动。一般情况下NAND版本的核心板已经烧写好了uboot、linux kernel和rootfs这些文件,所以可以将BOOT拨到NAND,然后直接从NAND Flash启动即可。

NAND版核心板启动信息如图30.4.8.1所示:

图30.4.8.1 NAND核心板启动信息

从图30.4.8.1可以看出,当前开发板的NAND容量为512MiB。输入“? nand”即可查看所有有关NAND令,如图30.4.8.2所示:

图30.4.8.2 NAND相关操作命令

可以看出,NAND相关的操作命令少,本节我们讲解一些常用的命令。

1、nand info命令

此命令用户打印NAND Flash信息,输入“nandinfo”,结果如图30.4.8.3所示:

图30.4.8.3 nand信息

图30.4.8.3中给出了NAND的页大小、OOB域大小,擦除大小等信息。可以对照着所使用的NAND Flash数据手册来查看一下这些信息是否正确。

2、nanddevice命令

nanddevice用于切换NAND Flash,如果你的板子支持多片NAND的话就可以使用此命令来设置当前所使用的NAND。这个需要你的CPU有两个NAND控制器,并且两个NAND控制器各接一片NAND Flash。就跟I.MX6U有两个SDIO接口,这两个SDIO接口可以接两个MMC设备一样。不过一般情况下CPU只有一个NAND接口,而且在使用中只接一片NAND。

3、nanderase命令

nanderase命令用于擦除NAND Flash,NAND Flash的特性决定了在向NAND Flash写数据之前一定要先对要写入的区域进行擦除。“nanderase”命令有三种形式:

nand erase[.spread] [clean] off size //从指定地址开始(off)开始,擦除指定大小(size)的区域。

nand erase.part [clean] partition //擦除指定的分区

nand erase.chip [clean] //全篇擦除

NAND的擦除命令一般是配合写命令的,后面讲解NAND写命令的时候在演示如何使用“nand erase”。

4、nandwrite命令

此命令用于向NAND指定地址写入指定的数据,一般和“nanderase”命令配置使用来更新NAND中的uboot、linuxkernel或设备树等文件,命令格式如下:

nand write addr off size

addr是要写入的数据首地址,off是NAND中的目的地址,size是要写入的数据大小。

以更新NAND中的uboot为例,讲解一下如何使用此命令。先编译出来NAND版本的u-boot.imx文件,在烧写之前要先对NAND进行分区,也就是规划好uboot、linuxkernel、设备树和根文件系统的存储区域,I.MX6U-ALPHA开发板的NAND分区如下:

0x000000000000-0x000004000000 : "boot"

0x000004000000-0x000006000000 : "kernel"

0x000006000000-0x000007000000 : "dtb"

0x000007000000-0x000020000000 : "rootfs"

一共有四个分区,第一个分区存放uboot,地址范围为0x0~0x4000000(共64MB);第二个分区存放kernel(也就是linuxkernel),地址范围为0x4000000~0x6000000(共32MB);第三个分区存放dtb(设备树),地址范围为0x6000000~0x7000000(共16MB);剩下的所有存储空间全部作为最后一个分区,存放rootfs(根文件系统)。

uboot是从地址0开始存放的,其实用不了这么大的区域,但是为了好管理才分配了这么大的,将NAND版本的u-boot.imx文件放到Ubuntu中的tftpboot目录中,然后使用tftp命令将其下载到开发板的0X87800000地址处,最终使用“nandwrite”将其烧写到NAND中,命令如下:

tftp 0x87800000 u-boot.imx //下载u-boot.imx到DRAM中

nand erase 0x0 0x100000 //从地址0开始擦除1MB的空间

nand write 0x87800000 0x0 0x100000 //将接收到的u-boot.imx写到NAND中

u-boot.imx很小,一般就是4,5百KB,所以擦除1MB的空间就可以了。写入的时候也是按照1M的数据写入的,所以肯定会写入一些无效的数据。你也可以将写入的大小改为u-boot.imx这个文件的大小,这样写入的数据量就是u-boot.imx的实际大小了。

同理我们也可以更新NAND中的linuxkernel和设备树(dtb)文件,命令如下:

tftp 0x87800000 zImage //下载zImage到DRAM中

nand erase 0x4000000 0xA00000 //从地址0x4000000开始擦除10MB的空间

nand write 0x87800000 0x4000000 0xA00000 //将接收到的zImage写到NAND中

这里我们擦出了10MB的空间,因为一般zImage就是6,7MB左右,10MB肯定够了,如果不够的话就将在多擦除一点就行了。

最后烧写设备树(dtb)文件文件,命令如下:

tftp 0x87800000 imx6ull-alientek-nand.dtb //下载dtb到DRAM中

nand erase 0x6000000 0x100000 //从地址0x6000000开始擦除1MB的空间

nand write 0x87800000 0x6000000 0x100000 //将接收到的dtb写到NAND中

dtb文件一般只有几十KB,所以擦除1M是绰绰有余的了。

根文件系统(rootfs)就不要在uboot中更新了,还是使用NXP提供的MFGTool工具来烧写,因为根文件系统太大!很有可能超过开发板DRAM的大小,这样连下载都没法下载,更别说更新了。

4、nand read命令

此命令用于从NAND中的指定地址读取指定大小的数据到DRAM中,命令格式如下:

nand read addr off size

addr是目的地址,off是要读取的NAND中的数据源地址,size是要读取的数据大小。比如我们读取设备树(dtb)文件到0x83000000地址处,命令如下:

nand read 0x83000000 0x6000000 0x19000

过程如图30.4.8.4所示:

图30.4.8.4 nandread读取过程

设备树文件读取到DRAM中以后就可以使用fdt命令来对设备树进行操作了,首先设置fdt的地址,fdt地址就是DRAM中设备树的首地址,命令如下:

fdtaddr 83000000

设置好以后可以使用“fdtheader”来查看设备树的头信息,输入命令:

fdtheader

结果如图30.4.8.5所示:

图30.4.8.5 设备树头信息

输入命令“fdtprint”就可以查看设备树文件的内容,输入命令:

fdtprint

结果如图30.4.8.6所示:

图30.4.8.6 设备树文件

图30.4.8.6中的文件就是我们写到NAND中的设备树文件,至于设备树文件的详细内容我们后面会有专门的章节来讲解,这里大家知道这个文件就行了。

NAND常用的操作命令就是擦除、读和写,至于其他的命令大家可以自行研究一下,一定不要尝试全片擦除NAND的指令!!否则NAND就被全部擦除掉了,什么都没有了,又得重头烧整个系统。

30.4.9 BOOT操作命令

uboot的本质工作是引导Linux,所以uboot肯定有相关的boot(引导)命令来启动Linux。常用的跟boot有关的命令有:bootz、bootm和boot。

1、bootz命令

要启动Linux,需要先将Linux镜像文件拷贝到DRAM中,如果使用到设备树的话也需要将设备树拷贝到DRAM中。可以从EMMC或者NAND等存储设备中将Linux镜像和设备树文件拷贝到DRAM,也可以通过nfs或者tftp将Linux镜像文件和设备树文件下载到DRAM中。不管用那种方法,只要能将Linux镜像和设备树文件存到DRAM中就行,然后使用bootz命令来启动,bootz命令用于自动zImage镜像文件,bootz命令格式如下:

bootz [addr [initrd[:size]] [fdt]]

命令bootz有三个参数,addr是Linux镜像文件在DRAM中的位置,initrd是initrd文件在DRAM中的地址,如果不使用initrd的话使用‘-’代替即可,fdt就是设备树文件在DRAM中的地址。现在我们使用网络和EMMC两种方法来启动Linux系统,首先将I.MX6U-ALPHA开发板的Linux镜像和设备树发送到Ubuntu主机中的tftpboot文件夹下。Linux镜像文件前面已经放到了tftpboot文件夹中,现在把设备树文件放到tftpboot文件夹里面。以EMMC核心板为例,将开发板光盘->8、开发板系统镜像->imx6ull-alientek-emmc.dtb文件发送到Ubuntu主机中的tftpboot文件夹里面,完成以后的tftpboot文件夹如图30.4.9.1所示:

图30.4.9.1tftpboot文件夹

下载Linux镜像文件和设备树都准备好了,我们先学习如何通过网络启动Linux,使用tftp命令将zImage下载到DRAM的0X80800000地址处,然后将设备树imx6ull-alientek-emmc.dtb下载到DRAM中的0X83000000地址处,最后之后命令bootz启动,命令如下:

tftp 80800000 zImage

tftp 83000000 imx6ull-alientek-emmc.dtb

bootz 80800000 – 83000000

命令运行结果如图30.4.9.2所示:

图30.4.9.2通过网络启动Linux

上图就是我们通过tftp和bootz命令来从网络启动Linux系统,如果我们要从EMMC中启动Linux系统的话只需要使用命令fatload将zImage和imx6ull-alientek-emmc.dtb从EMMC的分区1中拷贝到DRAM中,然后使用命令bootz启动即可。先使用命令fatls查看要下EMMC的分区1中有没有Linux镜像文件和设备树文件,如果没有的话参考30.4.6小节中讲解的fatwrite命令将tftpboot中的zImage和imx6ull-alientek-emmc.dtb文件烧写到EMMC的分区1中。然后使用命令fatload将zImage和imx6ull-alientek-emmc.dtb文件拷贝到DRAM中,地址分别为0X80800000和0X83000000,最后使用bootz启动,命令如下:

fatload mmc 1:1 80800000 zImage

fatload mmc 1:1 83000000 imx6ull-alientek-emmc.dtb

bootz 80800000 - 83000000

命令运行结果如图30.4.9.3所示:

图30.4.6.3从EMMC中启动Linux

2、bootm命令

bootm和bootz功能类似,但是bootm用于启动uImage镜像文件。如果不使用设备树的话启动Linux内核的命令如下:

bootmaddr

addr是uImage镜像在DRAM中的首地址。

如果要使用设备树,那么bootm命令和bootz一样,命令格式如下:

bootm [addr [initrd[:size]] [fdt]]

其中addr是uImage在DRAM中的首地址,initrd是initrd的地址,fdt是设备树(.dtb)文件在DRAM中的首地址,如果initrd为空的话,同样是用“-”来替代。

3、boot命令

boot命令也是用来启动Linux系统的,只是boot会读取环境变量bootcmd来启动Linux系统,bootcmd是一个很重要的环境变量!其名字分为“boot”和“cmd”,也就是“引导”和“命令”,说明这个环境变量保存着引导命令,其实就是启动的命令集合,具体的引导命令内容是可以修改的。比如我们要想使用tftp命令从网络启动Linux那么就可以设置bootcmd为“tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000”,然后使用saveenv将bootcmd保存起来。然后直接输入boot命令即可从网络启动Linux系统,命令如下:

setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000'

saveenv

boot

运行结果如图30.4.6.4所示:

图30.4.6.4设置bootcmd从网络启动Linux

前面说过uboot倒计时结束以后就会启动Linux系统,其实就是执行的bootcmd中的启动命令。只要不修改bootcmd中的内容,以后每次开机uboot倒计时结束以后都会使用tftp命令从网络下载zImage和imx6ull-alientek-emmc.dtb,然后启动Linux。

如果想从EMMC启动那就设置bootcmd为“fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-alientek_emmc.dtb; bootz 80800000 - 83000000”,然后使用boot命令启动即可,命令如下:

setenv bootcmd 'fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-alientek_emmc.dtb; bootz 80800000 - 83000000'

savenev

boot

运行结果如图30.4.6.5所示:

图30.4.6.5设置bootcmd从EMMC启动Linux

如果不修改bootcmd的话,每次开机uboot倒计时结束以后都会自动从EMMC里面读取zImage和imx6ull-alientek-emmc.dtb,然后启动Linux。

30.4.10其他常用命令

uboot中还有其他一些常用的命令,比如reset、go、run和mtest等。

1、reset命令

reset命令顾名思义就是复位的,输入“reset”即可复位重启,如图30.4.10.1所示:

图30.4.10.1reset命令运行结果

2、go命令

go命令用于跳到指定的地址处执行应用,命令格式如下:

go addr [arg ...]

addr是应用在DRAM中的首地址,我们可以编译一下裸机例程的实验13_printf,然后将编译出来的printf.bin拷贝到Ubuntu中的tftpboot文件夹里面,注意,这里要拷贝printf.bin文件,不需要在前面添加IVT信息,因为uboot已经初始化好了DDR了。使用tftp命令将printf.bin下载到开发板DRAM的0X87800000地址处,因为裸机例程的链接首地址就是0X87800000,最后使用go命令启动printf.bin这个应用,命令如下:

tftp 87800000 printf.bin

go 87800000

结果如图30.4.10.2所示:

图30.4.10.2go命令运行裸机例程

从图30.4.10.2可以看出,通过go命令我们就可以在uboot中运行裸机例程。

3、run命令

run命令用于运行环境变量中定义的命令,比如可以通过“runbootcmd”来运行bootcmd中的启动命令,但是run命令最大的作用在于运行我们自定义的环境变量。在后面调试Linux系统的时候常常要在网络启动和EMMC/NAND启动之间来回切换,而bootcmd只能保存一种启动方式,如果要换另外一种启动方式的话就得重写bootcmd,会很麻烦。这里我们就可以通过自定义环境变量来实现不同的启动方式,比如定义环境变量mybootemmc表示从emmc启动,定义mybootnet表示从网络启动,定义mybootnand表示从NAND启动。如果要切换启动方式的话只需要运行“runmybootxxx(xxx为emmc、net或nand)”即可。

说干就干,创建环境变量mybootemmc、mybootnet和mybootnand,命令如下:

setenv mybootemmc 'fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-alientek-emmc.dtb;bootz 80800000 - 83000000'

setenv mybootnand 'nand read 80800000 4000000 800000;nand read 83000000 6000000 100000;bootz 80800000 - 83000000'

setenv mybootnet 'tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000'

saveenv

创建环境变量成功以后就可以使用run命令来运行mybootemmc、mybootnet或mybootnand来实现不同的启动:

runmybootemmc

run mytoobnand

run mybootnet

4、mtest命令

mtest命令是一个简单的内存读写测试命令,可以用来测试自己开发板上的DDR,命令格式如下:

mtest [start [end [pattern [iterations]]]]

start是要测试的DRAM开始地址,end是结束地址,比如我们测试0X80000000~0X80001000这段内存,输入“mtest8000000080001000”,结果如图30.4.10.3所示:

图30.4.10.3mtest命令运行结果

从图30.4.10.3可以看出,测试范围为0X80000000~0X80001000,已经测试了486次,如果要结束测试就按下键盘上的“Ctrl+C”键。

至此,uboot常用的命令就讲解完了,如果要使用uboot的其他命令,可以查看uboot中的帮助信息,或者上网查询一下相应的资料。

2022高三复习资料:历年高考书信分类范文+万能句型+万能模板

向学霸进军整理出2022高三复习资料之历年高考书信分类范文+万能句型+万能模板,希望给2021高考生和家长带来帮助。

告知信

Part 1

范文赏析(2019全国II卷)

假定你是校排球队队长李华。请写封邮件告知你的队友Chris球队近期将参加比赛, 内容包括:

1. 比赛信息;

2. 赛前准备;

3. 表达期待。

注意:

1. 词数100左右;

2. 可以适当增加细节,以使行文连贯。

Dear Chris,

I’m writing to let you know that we will have a volleyball match next month.

The match will take place in our school gym on the morning of July 8th. We will play against a team from Lingnan High School. For good performance in the match, we mustget fully prepared and practice hard. So starting tomorrow, we all need to train for two hours after school every day. In addition , we should avoid getting hurt during the training and have a healthy diet to keep fit .

You’re an excellent player. With you on the team, we have every hope of beating Lingnan. Let’s try hard together!

Cheers,

Li Hua

亲爱的克里斯,

我写信是想告诉你我们下个月将有一场排球比赛。比赛将于7月8日上午在我校体育馆举行。我们将和岭南中学的一个队比赛。为了在比赛中有好的表现,我们必须做好充分的准备,努力练习。所以从明天开始,我们每天放学后都要训练两个小时。此外,我们还应避免在训练中受伤,并且合理膳食保持身体健康。

你是个优秀的运动员。有你在队里,我们完全有希望打败岭南。让我们一起努力!

祝好,

李华

精选词块

take place 发生

play against 同……比赛

get fully prepared 充分准备

in addition 另外

keep fit 保持(身体)健康

精选句式

I’m writing to let you know that ...

我写信是想让你知道……

The match will take place in ...

比赛将在……举行。

For good performance in the ..., we must get fully prepared and practice hard.

为了在……中取得好成绩,我们必须做好充分的准备,努力练习。

Let’s try hard together!

让我们一起努力!

Part 2

万能句式

① I m writing in reply to ...

我写此信是为了答复……

② Joyfully, I’d like to bring you a piece of good news.

我很高兴地告诉你一个好消息。

③ It’s my honor to inform you of an upcoming event.

我很荣幸地通知你即将举行的活动。

④ It is to be held + 地点 + 时间 + and lasts about … ( + from ... to ... / during which period we could …)

活动将在……举行,并持续大约……(在此期间我们可以……)

⑤ You are particularly welcome to ..., which will definitely add color and fun to ...

特别欢迎你……,这一定会给……增添色彩和乐趣。

⑥ Please be present on time and you might take a notebook and a pen with you.

请准时到场,你可以随身带着笔记本和笔。

⑦ With your participation, we will ...

有你的参与,我们将……

邀请信

Part 1

范文赏析(2017全国III卷)

假定你是李华。你所在的校乒乓球队正在招收新队员。请给你的留学生朋友Eric写封邮件邀请他加入,内容包括:

1. 球队活动;

2. 报名方式及截止日期。

注意:

1. 词数100左右;

2. 可以适当增加细节,以使行文连贯。

Dear Eric,

How’s everything going? The table-tennis team of our school is admitting new players. I’m sure it will appeal to you, for you have been enthusiastic about sports. Therefore, I’d like to invite you to join the team. Now the information in detail .

The team will hold a range of activities, including some training and matches. And some world-famous players will be invited to give lessons. If you are interested in it, you may either send an email to 123456@sina.com orsign up in person. The deadline is June 25th, 2017. I sincerely hope you could join us. Don’t hesitate to ask me if you have any questions.

I’m looking forward to your early reply.

Yours,

Li Hua

亲爱的埃里克,

一切都好吗?我们学校的乒乓球队正在招收新队员。我相信这一定很吸引你,因为你一直热衷于体育运动。因此,我想邀请你加入我们的团队。详情如下。

该队将举行一系列活动,包括一些训练和比赛。还会邀请一些世界著名的运动员来授课。如果你有兴趣,可以发邮件到123456@sina.com或亲自报名。截止日期是2017年6月25日。我真诚地希望你能加入我们。如果你有任何问题,尽管问我。

期待你的早日回复。

你的,

李华

精选词块

appeal to 对……有吸引力

either ... or ... 或者……或者……

a range of 一系列

in detail 详细地

sign up 报名

精选句式

How’s everything going?

一切都好吗?

I’d like to invite you to join ...

我想邀请你加入……

Now the information in detail.

详情如下。

I sincerely hope you could join us.

我真诚地希望你能加入我们。

Looking forward to your early reply.

期待您的早日回复。

Part 2

万能句式

① I am writing to invite you to ... / I’m writing to tell you that there will be a ...

我写信邀请你…… / 我写信告诉你将有……

② I am very pleased to invite you to participate in ... to be held from ... to ... in ...

我很高兴邀请你参加从……到……在……举行的……

③ I have been admiring your deep appreciation of ... and wondering whether you will be so kind as to guide us on ...

我一直很欣赏您对……的深刻理解,不知道您能否给我们介绍一下……

④ I think it would be a great idea if you could participate in ...

我想你要是能来参加……那就太好了

⑤ It is my pleasure / a great honor for me to invite you to ...

能邀请你参加……是我(莫大)的荣幸。

⑥ If you are interested in it, let me know and I’ll send you more information.

如果你感兴趣,告诉我,我会给你发送更多的信息。

⑦Sorry for occupying your spare time, but we do hope you could join us and give us some advice.

很抱歉占用了您的时间,但我们真的希望您能加入我们,给我们一些建议。

⑧ I am sure you will have a good time at ...

我相信你在……将会玩得开心。

⑨ Here are some details about this activity. / The following are some details about this activity. / Some details about this activity are as follows.

本次活动的一些细节内容如下。

求助信

Part 1

范文赏析(2016全国I卷)

假定你是李华,暑假想去一家外资公司兼职,已写好申请书和个人简历(resume)。给外教Ms Jenkins写信,请她帮你修改所附材料的文字和格式(format)。

注意:

1. 词数100左右;

2. 可以适当增加细节,以使行文连贯。

Dear Ms Jenkins,

I’m Li Hua from your English writing class last term. I’m writing to ask for your help. I’m applying for a part-time job at a foreign company in my city during the summer vacation, and I have just completed my application letter and resume. However, I am not quite sure of the language and the format I’ve used. I know you have a very busy schedule, and I’d be very grateful if you could take some time to go through them and make necessary changes. Please find my application letter and resume in the attachment.

Thank you for your kindness!

Yours,

Li Hua

亲爱的詹金斯女士,

我是上学期上您英语写作课的李华。我写信来请求您的帮助。我正在申请暑假期间在我所在城市的一家外企做兼职,我刚刚完成了我的求职信和简历。然而,我不太确定我所使用的语言和格式。我知道您的日程安排得很紧,所以如果您能花点时间检查一下,并做些必要的修改,我将不胜感激。附件是我的申请信和简历,请查收。

谢谢您的好意!

你的,

李华

精选词块

ask for 请求

apply for 申请

go through 仔细检查

精选句式

I’m writing to ask for your help.

我写信来请求您的帮助。

I know you have a very busy schedule, and I’d be very grateful if you could take some time to ...

我知道您的日程安排得很紧,所以如果您能花点时间……,我将不胜感激。

Thank you for your kindness!

谢谢您的好意!

Part 2

万能句式

① Would you be so kind as to do me a favor?

你能帮我一个忙吗?

② I would appreciate it if you could do me a favor ...

如果你能帮我……,我将不胜感激。

③ Would you please be so kind as to ...

可以烦请您……

④ Sorry to trouble you again.

很抱歉再次打扰你。

致歉信

Part 1

范文赏析(2016全国III卷)

假定你是李华,与留学生朋友Bob约好一起去书店,因故不能赴约。请给他写封邮件,内容包括:

1. 表示歉意;

2. 说明原因;

3. 另约时间。

注意:

1. 词数100左右;

2. 可以适当增加细节,以使行文连贯。

Dear Bob,

I’m sorry to say that I cannot go to the bookstore with you on Friday afternoon. I have just found that I have to attend an important class meeting that afternoon. I hope the change will not cause you too much trouble.

Shall we go on Saturday morning? We can set out early so that we’ll have more time to read and select books. If it’s convenient for you, let’s meet at 8:30 outside the school gate. If not, let me know what time suits you best. I should be available any time after school next week.

Yours,

Li Hua

亲爱的鲍勃,

很抱歉,星期五下午我不能和你一起去书店了。我刚发现我那天下午要参加一个重要的班会。我希望这个变动不会给你带来太多的麻烦。

我们星期六上午去好吗?我们可以早点出发,这样我们就有更多的时间来读书和选书。如果你方便的话,我们8点半在校门口见。如果不方便,请告诉我什么时间对你最合适。下周放学后我随时都有空。

你的,

李华

精选词块

set out 出发

精选句式

I’m sorry to say that ...

很抱歉我……

I hope the change will not cause you too much trouble.

我希望这个变动不会给你带来太多的麻烦。

If it is convenient for you ...

如果你方便的话……

Shall we ...?

我们……好吗?

Part 2

万能句式

① I am sorry to tell you about some changes.

我很抱歉地告诉你一些变化。

② I’m terribly sorry to tell you that ... / I regret to inform you that ...

我非常抱歉地告诉你…… / 我很遗憾地通知你…

③ I am not be able to do ... as planned / scheduled / arranged.

我不能按原计划 / 计划 / 安排 ……

④ I apologize for the inconvenience I have caused.

我为我造成的不便道歉。

⑤ Please accept my sincerest and deepest apology for ...

请接受我对……最真诚和最深切的歉意。

⑥ I wish I could be given a chance to make up for my inconsideration.

我希望我能有机会弥补我的疏忽。

约稿信

Part 1

范文赏析(2015全国I卷)

假定你是李华,你校英文报“外国文化”栏目拟刊登介绍美国节日风俗和中学生生活的短文。请给美国朋友彼得写信约稿,要点如下:

1. 栏目介绍;

2. 稿件内容;

3. 稿件长度:约400词;

4. 交稿日期:6月28日前。

注意:

1. 词数100左右;

2. 可以适当增加细节,以使行文连贯;

3. 开头语已为你写好。

Dear Peter,

I’d like to ask you to write an article for our school’s English newspaper.

The “Foreign Cultures” section in our newspaper is very popularamong us students. It carries articles written by foreign friends about the cultures of their home countries. Would you please write something about the culture in your part of the United States? And we would especially welcome articles about how Americans spend their holidays and festivals, and the life of American high school students. You can writeanything relevantso long as it’s interesting and informative. 400 words would be fine. Could we have your article before June 28?

I’m looking forward to hearing from you.

Yours,

Li Hua

亲爱的彼得,

我想请你为我们学校的英文报纸写一篇文章。

我们报纸的“外国文化”栏目很受我们学生的欢迎。它刊登外国朋友写的关于他们祖国文化的文章。你可以写一些关于美国本土文化的东西吗?我们尤其欢迎关于美国人如何度过假期和节日,以及美国高中生的生活的文章。只要是寓教于乐的任何相关内容都可以。400字就可以了。我们能在6月28日前收到你的文章吗?

我期待着你的消息。

你的,

李华

精选词块

be popular among 受……欢迎;在……中很流行

anything relevant 任何相关内容

so long as 只要

look forward to 期待;盼望

精选句式

I’d like to ask you to ...

我想请你……

It carries articles written by ... about the ...

它刊登……写的关于……的文章。

Would you please write something about ...?

请你写一些关于……的内容好吗?

We would especially welcome articles about ...

我们特别欢迎关于……的文章。

You can write anything relevant so long as it’s interesting and informative.

只要是寓教于乐的任何相关内容都可以。

400 words would be fine.

400字就可以了。

Could we have your article before ...?

我们能在……前收到你的文章吗?

Part 2

万能句式

① I would like to ask you to write an article for ...

我想请你为……写一篇文章。

② You can write something about ...

你可以写一些关于……的内容

③ What attracts us most about the characteristics of the column is that ...

这个专栏最吸引我们的特色是……

④ We will extend the deadline if you consider the time is not enough.

如果你认为时间不够,我们将延长最后期限。

⑤ Your article is supposed to be written within *** words.

你的文章的字数应控制在***字以内。

⑥ I am looking forward to your reply at your earliest convenience.

我期待着您尽早的回复。

申请信

Part 1

范文赏析(2019全国I卷)

假定你是李华,暑期在伦敦学习,得知当地美术馆要举办中国画展览。请写一封信申请做志愿者,内容包括:

1. 写信目的;

2. 个人优势;

3. 能做的事情。

注意:

1. 词数100左右;

2. 可以适当增加细节,以使行文连贯;

3. 结束语已为你写好。

Dear Sir or Madam,

I am writing to apply to be a volunteer for the Chinese Painting Exhibition which will be held in your art gallery. I think I am qualified for this job, because I have learned Chinese painting since childhood. Equally important , I am fluent in both Chinese and English, so Ihave no difficulty incommunicating with others. If I am lucky enough to be chosen as a volunteer, I can show visitors around the gallery and answer their questions about the paintings, after some proper training.

I would be very grateful if you could offer me the opportunity. I’m looking forward to your reply.

Yours,

Li Hua

尊敬的先生/女士:

我写这封信是为了申请成为一名中国画展览的志愿者,这次展览将在你们的美术馆举行。我认为我能胜任这份工作,因为我从小就学习中国画。同样重要的是,我的中文和英文都很流利,所以我在与人交流时没有困难。如果我有幸被选为志愿者,经过适当的培训,我可以带游客参观美术馆,并回答他们关于画作的问题。

如果您能给我这个机会,我将不胜感激。期待您的回复。

你的,

李华

精选词块

be qualified for 胜任

equally important 同样重要的是

be fluent in 流利;精通

have no difficulty in sth / doing sth 做某事没有困难

communicate with 和……沟通;交流

show sb around 领某人参观

精选句式

I am writing to apply to ...

我写信是为了申请……

I think I am qualified for this job, because ...

我认为我胜任这份工作,因为……

If I am lucky enough to be chosen as a volunteer, I can ...

如果我有幸被选为志愿者,我能……

I would be very grateful if you could offer me the opportunity.

如果您能给我这个机会,我将不胜感激。

Part 2

万能句式

① I’m confident that I’m qualified for the job and the reasons are as follows.

我相信我能胜任这份工作,原因如下。

② I have a good command of ... and I am good at ...

我很擅长……并且善于……

③ Also, my good communication skills enable me to keep a good relationship with others.

此外,我良好的沟通能力使我能够与他人保持良好的关系。

④ I would appreciate it if my application is taken into account.

如果您能考虑我的申请,我将不胜感激。

⑤ I would really appreciate it if you could take my application into consideration and reply to me at your earliest convenience.

如果您能考虑我的申请,并在您方便的时候尽早回复我,我将不胜感激。

通知

Part 1

范文赏析(2018全国II卷)

你受学生会委托为校宣传栏“英语天地”写一则通知,请大家观看一部英文短片Growing Together, 内容包括:

1. 短片内容:学校的发展;

2. 放映时间、地点;

3. 欢迎对短片提出意见。

注意:

1. 词数100左右;

2. 可以适当增加细节,以使行文连贯。

Notice

In order to learn more about the development of our school, all the students are welcome to watch the short film Growing Together, which is a documentary on the history of our school. Produced by our teachers and us senior students, it reflects years of hard work. If you are curious about the history of our school or concerned about its future, you mustn’t miss this excellent opportunity ! We encourage any kind of feedback on the film from our viewers.

It will be shown in Room 1, First Teaching Building, from 7:00 pm to 8:00 pm, June 10, Sunday.

We are looking forward to your participation.

The Students’ Union

June 8, 2018

通知

为了更多地了解我们学校的发展,我们欢迎所有的学生观看短片《共同成长》,这是一部关于我们学校历史的纪录片。由我们的老师和高年级学生制作,它反映了多年的艰苦奋斗。如果你对我们学校的历史感到好奇,或者关注我们学校未来的发展,千万不要错过这个好机会!我们鼓励观众对电影提出任何形式的反馈。

短片将于6月10日(星期日)晚上7点到8点在第一教学楼1号教室放映。

我们期待您的参与。

学生会

2018年6月8日

精选词块

in order to 为了

be concerned about 关注

excellent opportunity 良机

any kind of 任何形式的

精选句式

In order to learn more about the ..., all the students are welcome to ...

为了更多地了解……,欢迎所有的学生来……

If you are curious about the ... or concerned about ... you mustn’t miss this excellent opportunity!

如果你对……感到好奇或关注……,你千万不要错过这个好机会!

We encourage any kind of feedback on ...

我们鼓励对……提出任何形式的反馈。

Part 2

万能句式

① May I have your attention please? I would like to inform you of the ... to be held ...

请大家注意一下。我想通知你们在……举行……

② The meeting will be held in ... / A lecture will be given at ...

会议将在……举行 / 一个讲座将在……举行。

③ All the teachers and students are welcome to attend …

欢迎所有的老师和学生参加……

④ There is going to be a talk on ...

将有一个关于……的报告。

⑤ All the members are expected to attend it.

全体成员都要参加。

⑥ You are required to take notes during the lecture.

讲座期间需要记笔记。

⑦ We will get together at the school gate at ... and probably come back at ...

我们上午……将在学校门口集合,大概下午……返回。

⑧ Please be there on time. / Please attend it on time.

请准时到场。/ 请准时参加。

本文由公众号《向学霸进军》整理编辑于网络

相关问答

read 的所有 格式 ?

read可以以不同的格式出现。最常见的格式是书本、杂志、报纸等印刷媒体。此外,read还可以以电子书、电子杂志、博客、社交媒体、网站、论坛、电子邮件等数字媒...

填入1,2,.....N×N个数,并要求构成如下的 格式 :如N=4101...

[最佳回答]Programshe;constmax=10;vard,i,j,m,N:integer;A:array[1..10,1..10]ofinteger;beginwrite('...

【ERROR:constantsandexpressionsareinvalidinread-onlyI/Ol...

[回答]data.txt10.00.00.020.10.10.130.20.20.2programmainimplicitreal*8(a-h,o-z)dimensionx(3),y(...

readlines函数的文件 格式 ?

readlines函数可以用于读取文件,它将文件中的内容按行读取并返回一个包含各行内容的列表。readlines函数适用于文本文件,其中每行都以换行符''结尾。因此,read...

learnhowtoreadpDfs是什么意思_作业帮

[回答]learnhowtoreadpDfs学习如何阅读便携式文档格式文件

【请你把 read 转换为ing的 格式 .】作业帮

[最佳回答]reading,绝对正确

doc文件是什么意思?

DOC是MicrosoftWord文字处理软件使用的默认文件格式,全称为Document文件。它保存了文字内容、格式以及图片等信息。DOC文件主要有以下几个特征:1.跨...

writeon与writein的区别?

1.Writein是输出语句,输出语句有三种格式:①Write(输出项1,输出项2);{执行输出后光标不换行}②Writeln(输出项1,输出项2);{执行输出后光标换到...R...

英语中,诗名、书名、歌曲名的书写 格式 ?_作业帮

[最佳回答]英文题目的写法题目应写在第一行的中间,题目左右两边的空白距离大致相等.题目的第一个单词的第一个字母必须大写.从第二个单词起,其中每个实义词的...

0x00000000指令引用的"0x00000000"内存。该内存不能为" read "...

内存不能为read修复工具可以有效修复计算机运行应用程序时提示:该内存不能为read要终止程序的问题,一般XP系统才会出现这个问题。指令修复法:开始菜单,运行...

 玩乐吧  house nation 
王经理: 180-0000-0000(微信同号)
10086@qq.com
北京海淀区西三旗街道国际大厦08A座
©2024  上海羊羽卓进出口贸易有限公司  版权所有.All Rights Reserved.  |  程序由Z-BlogPHP强力驱动
网站首页
电话咨询
微信号

QQ

在线咨询真诚为您提供专业解答服务

热线

188-0000-0000
专属服务热线

微信

二维码扫一扫微信交流
顶部