I.MX6UL系统移植(一)—— U-Boot

1、U-Boot简介
   uboot的全称是Universal Boot Loader,uboot是一个遵循GPL协议的开源软件,uboot是一个裸机代码,可以看作是一个裸机综合例程。现在的uboot已经指出液晶屏、网络、
   USB等高级功能。

2、U-Boot编译
   ①、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- -j4

3、U-Boot烧写与启动
   uboot启动的时候会输出一些信息
   ①、U-Boot 2016.03 (Apr 12 2019 - 02:33:00 +0800)
       uboot的版本号和编译时间,当前的uboot版本是2016.03,编译时间是2019年4月12日凌晨2点33。
   ②、CPU: Freescale i.MX6ULL rev1.1 69 MHz (running at 396 MHz)
       CPU: Industrial temperature grade (-40C to 105C) at 46C
       CPU信息,当前使用的CPU是飞思卡尔的I.MX6ULL,如果时间528MHz的I.MX6ULL,此处会显示主频为528MHz。这颗芯片是工业级的,可以工作在-40℃~105℃。
   ③、Reset cause: POR
       复位原因,当前的复位原因是POR。I.MX6ULL芯片上有个POR_B引脚,将这个引脚拉低即可复位I.MX6ULL。
   ④、Board: MX6ULL 14x14 EVK
       板子名字,当前的板子名字为MX6ULL 14x14 EVK。 
   ⑤、I2C: ready
       提示I2C准备就绪。 
   ⑥、DRAM: 512 MiB
       提示当前板子的DRAM(内存)为512MB,如果是NAND版本的话内存为256MB。
   ⑦、MMC: FSL_SDHC: 0, FSL_SDHC: 1
       提示当前有两个MMC/SD卡控制器:FSL_SDHC(0)和FSL_SDHC(1)。I.MX6ULL支持两个MMC/SD,正点原子的I.MX6ULL EMMC核心板上FSL_SDHC(0)接的EMMC,FSL_SDHC(1)
       接的SD(TF)卡。
   ⑧、Display: ATK-LCD-7-1024x600 (1024x600)
       Video: 1024x600x24
       LCD型号,当前的LCD型号是ATK-LCD-7-1024x600(1024x600),分辨率为1024x600,格式为RGB888(24位)。
   ⑨、In: serial
       Out: serial
       Err: serial
       标准输入、标准输出和标准错误所使用的终端,这里都使用串口(serial)作为终端。
   A、switch to partitions #0, OK
       mmc0 is current device
       切换到emmc的第0个分区上,因为当前的uboot是emmc版本的,也就是从emmc启动的。只是为了方便烧写到了SD卡上,但是它的内心还是EMMC的。所以uboot启动以后
       会将emmc作为默认存储器,当然也可以将SD卡作为uboot的存储器。
   B、Net: FEC1
       网口信息,提示我们当前使用的FEC1这个网口,I.MX6ULL支持两个网口。
   C、Normal Boot
       提示正常启动,就是说uboot要从emmc里面读取环境变量和参数信息启动Linux内核了。
   D、Hit any key to stop autoboot: 0
       倒计时提示,默认倒计时3秒,倒计时结束之前按下回车键就会进入Linux命令模式。如果在倒计时结束以后没有按下回车键,那么Linux内核就会启动,Linux内核一
       旦启动,uboot就会寿终正寝。

4、U-Boot命令使用
(1)信息查询命令
     ①、bdinfo
         用于查看板子信息。
     ②、printenv
         用于输出环境变量信息。
     ③、version
         用于查看uboot的版本号。
(2)环境变量操作命令
     ①、修改环境变量
         setenv:修改DRAM中的环境变量值。
         saveenv:将修改后的环境变量保存到flash中。
         PS1:将环境变量bootdelay改为5
         命令:setenv bootdelay 5
               saveenv
         PS2:修改环境变量bootargs的值
         命令:setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
               saveenv
     ②、新建环境变量
         PS1:新建命令author
         命令:setenv author zuozhongkai
               saveenv
     ③、删除环境变量
         PS1:删除命令author(通过给author赋空值)
         命令:setenv author
               saveenv
(3)内存操作命令
     ①、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命令中的数字都是十六进制的,不是十进制的。
         PS1:查看以0X80000000开始的20个字节的内存值,显示格式为.b
         命令:md.b 80000000 14
     ②、nm命令
         nm命令用于修改指定地址的内存值,格式:nm [.b,.w,.l] address
         PS1:修改0X80000000地址的值为0X12345678
         命令:=> nm.l 80000000         
               80000000: ffffff00 ? 12345678 #修改为0X12345678
               80000000: 12345678 ? q        #q退出修改
     ③、mm命令
         mm命令也是修改指定内存值的,使用mm修改内存值的时候地址会自增,而使用nm的话地址不会自增。
         PS1:修改以0X80000000地址开始的连续3个内存块(3*4=12个字节)的数据为0X05050505
         命令:=> mm.l 80000000
               80000000: 12345678 ? 05050505
               80000004: ffffafff ? 05050505
               80000008: fff9ffff ? 05050505
               8000000c: ffbffeff ? q
     ④、mw命令
         命令mw用于使用一个指定的数据填充一段内存,格式:mw [.b,.w,.l] address value [count]
         mw命令同样可以用.b、.w和.l来指定操作格式,address表示要填充的内存起始地址,value为要填充的数据,count是填充的长度。
         PS1:使用.l格式将以0X80000000为起始地址的0X10个内存块(0x10*4=64字节)填充为0X0A0A0A0A
         命令:mw.l 80000000 0A0A0A0A 10
     ⑤、cp命令
         cp是数据拷贝命令,用于将DRAM中的数据从一段内存拷贝到另一段内存中,或者把Nor Flash中的数据拷贝到DRAM中。
         命令:cp [.b,.w,.l] source target count
         cp命令同样可以以.b、.w和.l来指定操作格式,source为源地址,target为目的地址,count为拷贝的长度。
         PS1:使用.l格式将0X80000000处的地址拷贝到0X80000100处,长度为0X10个内存块(0X10*4=64个字节)
         命令:cp.l 80000000 80000100 10
     ⑥、cmp命令
         cmp是比较命令,用于比较两段内存的数据是否相等。
         命令:cmp [.b,.w,.l] addr1 addr2 count
         cmp命令同样可以以.b、.w和.l来指定操作格式,addr1为第一段内存首地址,addr2为第二段内存首地址,count为要比较的长度。
         PS1:使用.l格式来比较0X80000000和0X80000100这两个地址数据是否相等,比较长度为0x10个内存块(16*4=64个字节)
         命令:=> cmp.l 80000000 80000100 10
               Total of 16 word(s) were the same
         PS2:使用.l格式来比较0X80002000和0X80003000这两个地址数据是否相等,比较长度为0x10个内存块(16*4=64个字节)
         命令:=> cmp.l 80002000 80003000 10
               word at 0x80002000 (0xffff7ff7) != word at 0x80003000(0xfffff7ff)
               Total of 0 word(s) were the same
(4)网络操作命令
     首先保证开发板和Ubuntu通信正常,需要设置以下环境变量:
     setenv ipaddr 192.168.1.50        #设置开发板ip地址为192.168.1.50,可以不设置,使用dhcp命令来从路由器获取IP地址
     setenv ethaddr 00:04:9f:04:d2:35   #设置开发板的MAC地址,一定要设置
     setenv gatewayip 192.168.1.1       #网关地址
     setenv netmask 255.255.255.0       #子网掩码
     setenv serverip 192.168.1.250      #服务器IP地址,也就是Ubuntu主机IP地址,用于调试代码
     saveenv
     ①、ping命令
         查看开发板与Ubuntu是否通信,直接ping Ubuntu地址即可。
         命令:=> ping 192.168.1.250
               Using FEC1 device
               host 192.168.1.250 is alive
         注意!只能在uboot中ping其他的机器,其他机器不能ping uboot,因为uboot没有对ping命令做处理,如果用其他机器ping uboot的话会失败!
     ②、dhcp命令
         dhcp用于从路由器获取IP地址,前提得开发板链接到路由器上,如果开发板是和电脑直接连接的,那么dhcp命令就会失效。
         PS1:输入dhcp命令即可通过路由器获取到IP地址
         命令:=> dhcp
               BOOTP broadcast 1
               *** Unhandled DHCP Option in OFFER//ACK:50
               *** Unhandled DHCP Option in OFFER//ACK:50
               DHCP client bound to address 192.168.1.50(10 ms)
               *** Warning: no boot file name; using 'c0A80132.img'
               Using FEC1 device
               TFTP from server 192.168.1.1; our IP address is 192.168.1.50  #通过TFTP来启动linux内核
               Filename 'c0A80132.img'.
               Load address: 0x80800000
               Loading: ┬ ┬ ┬ ┬ ┬ ┬ 
      ③、nfs命令
          nfs(Network File System)网络文件系统,通过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目录中。
          uboot中的nfs命令格式:nfs [loadAddress] [[hostIPaddr:]bootfilename]
          loadAddress是要保存的DRAM地址,[[hostIPaddr:]bootdilename]是要下载的文件地址。
          PS1:将文件Linux镜像文件zImage下载到开发板DRAM的0x80800000这个地址处
          命令:=> nfs 80800000 192.168.1.250:/home/zuozhongkai/linux/nfs/zImage
                Using FEC1 device
                File transfer via NFS from server 192.168.1.250; our IP address is 192.168.1.50
                Filename '/home/zuozhongkai/linux/nfs/zImage'.
                Load address: 0x80800000
                Loading: ######################################################################
                done
                Bytes transferred = 6071136 (5ca360 hex)
      ④、tftp命令
          tftp命令的作用和nfs命令一样,都是通过网络下载东西到DRAM中,只是tftp命令使用的是TFTP协议,Ubuntu主机作为TFTP服务器(Ubuntu搭建TFTP服务器省略)。
          uboot中的tftp命令格式:tftp [loadAddress] [[hostIPaddr:]bootfilename]
          看起来和nfs命令格式一样的,loadAddress是文件的DRAM中的存放地址,[loadAddress] [[hostIPaddr:]bootfilename]是要从Ubuntu中下载的文件。但是和nfs命令的
          区别在于,tftp命令不需要输入文件在Ubuntu中的完整路径,只需要输入文件名即可。
          PS1:将tftpboot文件夹里面的zImage文件下载到开发板DRAM的0x80800000地址处
          命令:=> tftp 80800000 zImage
                Using FEC1 device
                TFTP from server 192.168.1.250; our IP address is 192.168.1.50
                Filename 'zImage'
                Load address: 0x80800000
                Loading: #####################################################
                         1.4 MiB/s
                done
                Bytes transferred = 6071136 (5ca360 hex)
(5)EMMC和SD卡操作命令
     uboot支持EMMC和SD卡,因此也要提供EMMC和SD卡的操作命令。一般认为EMMC和SD卡是同一个东西,所以没有特殊说明,统一使用MMC来代指EMMC和SD卡。uboot中常用于操作
     MMC设备的命令为mmc。mmc是一系列的命令,其后可以跟不同的参数
     ①、mmc info命令(mmcinfo功能与mmc info相同)
         mmc info命令用于输出当前选中的mmc info设备的信息。
         命令:=> mmc info
               Device: FSL_SDHC             #当前选中的MMC设备是EMMC
               Mannufacturer ID: 45         #厂商ID为45
               OEM: 100                     #设备OEM号
               Name: SEM04                  #设备名称SEM04
               Tran Speed: 52000000        #速度为52000000Hz=52MHz
               Rd Block Len: 512            #块大小512Kb
               MMC version 4.5              #版本为4.5
               High Capacity: Yes
               Capacity: 3.7 GiB            #容量为3.7GiB
               Bus Width: 8-bit             #8位宽的总线
               Erase Group Size: 256 KiB
               HC WP Group Size: 8 MiB
               User Capacity: 3.7 GiB WRREL 
               Boot Capacity: 2 MiB
               RPMB Capacity: 2 MiB
     ②、mmc rescan命令
         用于扫描开发板上所有MMC设备,包括EMMC和SD卡。
     ③、mmc list命令
         mmc list命令用于查看当前开发板一共有几个MMC设备。
         命令:=> mmc list
               FSL_SDHC: 0
               FSL_SDHC: 1 (eMMC)
         当前开发板有两个MMC设备:EMMC和SD卡。默认会将EMMC设置为当前MMC设备,而不是SD卡。如果想查看SD卡信息,就要使用命令mmc dev将SD卡设置为当前的MMC设备。
     ④、mmc dev命令
         mmc dev命令用于切换当前MMC设备,格式:mmc dev [dev] [part]
         [dev]用来设置要切换的MMC设备号,[part]是分区号。如果不写分区号的话默认为分区0。
         PS1:切换到SD卡
         命令:=> mmc dev 0     #切换到SD卡,0为SD卡,1为eMMC
               switch to partitions #0, OK
               mmc0 is current device
     ⑤、mmc part命令
         mmc part命令用来查看设备分区情况。
         PS1:查看EMMC的分区情况
         命令:=> mmc dev 1
               switch to partitions #0, OK
               mmc1(part 0) is current device
               => mmc part
               Partition Map for MMC device 1 -- Partition Type: DOS
               Part    Start Sector    Num Sectors    UUID          Type
                 1     20480           1024000        488db264-01   0c
                 2     1228800         6504448        488db264-02   83
         EMMC有两个分区,扇区20480~1024000为第一个分区,扇区1228800~6504448为第二个分区。如果EMMC里面烧写了Linux系统的话,EMMC是由3个分区的,第0个分区存放
         uboot,第2个分区存放Linux镜像文件和设备树,第2个分区存放根文件系统。但是当前只有两个分区,因为第0个分区没有格式化,所有识别不出来,实际上第0个分区
         是存在的。一个新的SD卡默认只有一个分区,那就是分区0,所以将uboot烧写到SD卡就是将u-boot.bin烧写到SD卡的分区0里面。
         PS2:将EMMC的分区2设置为当前MMC设备
         命令:=> mmc dev 1 2
               switch to partitions #2, OK
               mmc1(part 2) is current device
     ⑥、mmc read命令
         mmc read命令用于读取mmc设备的数据,格式:mmc read address blk# cnt
         addr是数据读取到DRAM中的地址,blk是要读取的块起始地址(十六进制),一个块是512字节,这里的块和扇区是一个意思,在MMC设备中我们通常说扇区,cnt是要读
         取得块数量(十六进制)。
         PS1:从EMMC的第1536(0x600)个块开始,读取16(0x10)个块的数据到DRAM的0X80800000地址处。
         命令:=> mmc dev 1 0                  #切换到MMC分区0
               switch to partitions #0, OK
               mmc1(part 0) is current device
               => mmc read 80800000 600 10     #读取数据
               MMC read: dev # 1, block # 1536, coutn 16 ... 16 block read: OK
     ⑦、mmc write命令
         mmc write命令用于将数据写到MMC设备里,格式:mmc write addr blk# cnt
         addr是要写入MMC中的数据在DRAM中的起始地址,blk是要写入MMC的块起始地址(十六进制),cnt是要写入的块大小,一个块512字节。
         PS1:升级uboot,也就是在uboot中更新uboot。这里要用到nfs或者tftp命令,通过nfs或这tftp命令将新的u-boot.bin下载到开发板的DRAM中,然后再使用命令
              mmc write将其写入到MMC设备中。更新SD中的uboot,先查看SD卡中的uboot版本号。
         命令:=> mmc dev 0                                    #切换到SD卡
               switch to partitions #0, OK
               mmc0 is current device
               => version                                #当前SD卡中的uboot是2019年4月15日12:52:04编译的
               U-Boot 2016.03 (Apr 15 2019 - 12:52:04 +0800)
               arm-linux-gnueabihf-gcc (Linaro GCC 4.9-2017.01) 4.9.4
               GNU ld (Linaro_Binutils-2017.01)2.24.0.20141017 Linaro 2014_11-3-git
               => tftp 80800000 u-boot.imx                                              #使用tftp命令将u-boot.imx下载到0x80800000地址处
               Using FEC1 device
               TFTP from server 192.168.1.250; our IP address is 192.168.1.50
               Filename 'u-boot.imx'
               Load address: 0x80800000
               Loading: #############################
                        2.2 MiB/s
               done
               Bytes transferred = 416768 (65c00 hex)                    #u-boot.imx大小为416768字节,416768/512=814,所以要向SD卡中写入814个块
               => mmc dev 0 0                                                           #如果有小数,块数量要加一。
               switch to partitions #0, OK
               mmc0 is current device
               => mmc write 80800000 2 32E                                              #将DRAM的0x8080000地址上的数据写入SD卡0x2地址处,写入814个块
               MMC write: dev # 0, block # 2, count 814 ... 814 blocks written: OK
              
               #烧写完成后重启开发板(从SD卡启动)
               => version     
               U-Boot 2016.03 (Apr 21 2019 - 18:05:59 +0800)                            #当前SD卡中的uboot是2019年4月21日18:02:59编译的,说明更新uboot成功
               arm-linux-gnueabihf-gcc (Linaro GCC 4.9-2017.01) 4.9.4
               GNU ld (Linaro_Binutils-2017.01)2.24.0.20141017 Linaro 2014_11-3-git
         PS2:更新EMMC中的uboot。
         命令:mmc dev 1 0                    #切换到EMMC分区0
               tftp 80800000 u-boot.imx        #下载u-boot.imx到DRAM
               mmc write 80800000 2 32E         #烧写u-boot.imx到EMMC中,从2开始是因为SD卡或EMMC的前两个块用于保存分区表!!!
               mmc partconf 1 1 0 0             #分区配置,EMMC需要这一步!
      ⑧、mmc erase命令
          mmc erase命令用于擦除MMC设备的指定块,格式:mmc erase blk# cnt
          blk为要擦除的起始块,cnt是要擦除的块数量。没事不要用mmc erase来擦除MMC设备!!!
(6)FAT格式文件系统操作命令
     有时候需要在uboot中对SD卡或者EMMC中存储的文件进行操作,这时候就要用到文件操作命令。
     ①、fatinfo命令
         fatinfo命令用于查询指定MMC设置指定分区的文件系统信息,格式:fatinfo []
         interface表示接口,比如mmc,dev是查询的设备号,part是要查询的分区。
         PS1:查询EMMC分区1的文件系统信息。
         命令:=> fatinfo mmc 1:1
               Interface: MMC
                  Device: Vendor: Man 000045 Snr 91ef8153 Rev: 3.10 Prod: SEM04G
                          Type: Removable Hard Disk
                          Capacity: 3776.0 MB = 3.6 GB (7733248 x 512)
               Filesystem: FAT16 "NO NAME     "
               EMMC分区1的文件系统为FAT16格式的。
     ②、fatls命令
         fatls命令用于查询FAT格式设备的目录和文件信息,格式:fatls [] [directory]
         interface是要查询的接口,比如mmc,dev是要查询的设备号,part是要查询的分区,directory是要查询的目录。
         PS1:查询EMMC分区1中的所有的目录和文件。
         命令:=> fatls mmc 1:1
               6071136    zimage
                 37099    imx6ull-14x14-evk.dtb
               2 file(s), 0 dir(s)
         emmc的分区1中存放着两个文件:zimage和imx6ull-14x14-evk.dtb,这两个文件分别是linux镜像文件和设备树。并且在emmc的分区1中有两个文件,没有目录。
     ③、fstype命令
         fstype命令用于查看MMC设备某个分区的文件系统格式,格式:fstype :
         PS1:正点原子EMMC核心板上的EMMC默认有3个分区,查看三个分区的文件系统格式
         命令:=> fstype mmc 1:0
               Failed to mount ext2 filesystem...
               ** Unrecognized filesystem type **
               => fstype mmc 1:1
               fat
               => fstype mmc 1:2
               ext4
         分区0格式为止,因为分区0存放的uboot,并且分区0没有格式化,所以文件系统格式未知。分区1的格式为fat,分区1用于存放linux镜像和设备树。分区2的格式为
         ext4,用于存放Linux的跟文件系统(rootfs)。
     ④、fatload命令
         fatload命令用于将指定的文件读取到DRAM中,格式:fatload [] [[[bytes[pos]]]]
         interface为接口,比如mmc,dev是设备号,part是分区,addr是保存在DRAM中的起始地址,filename是要读取的文件名字,bytes表示读取多少个字节的数据,如果
         bytes为0或者省略的话表示读取整个文件。pos是要读的文件相对于文件首地址的偏移,如果为0或者省略的话表示从文件地址开始读取。
         PS1:将EMMC分区中的zImage文件读取到DRAM中我的0X80800000地址处。
         命令:=> fatload mmc 1:1 80800000 zImage 
               reading zImage
               6071136 bytes read in 153 ms (37.8 MiB/s)
         在153ms内读取了6071136个字节的数据,速度为37.8MiB/s,速度是非常快的,因为这是从EMMC里面读取的,而EMMC是8位的,速度肯定会很快的。
     ⑤、fatwrite命令
         注意!uboot默认没有使能fatwrite命令,需要修改板子配置头文件,比如mx6ullevk.h、mx6ull_alientek_emmc.h等等,板子不同,其配置头文件也不同。找到自己开
         发板对应的配置头文件后添加如下一行宏定义来使能fatwrite命令:#define CONFIG_FAT_WRITE /* 使能 fatwrite 命令 */
         fatwrite命令用于将DRAM中的数据写入到MMC设备中,格式:fatwrite
         interface为接口,比如mmc,dev是设备号,part是分区,addr是要写入的数据在DRAM中的起始地址,filename是写入的数据文件名字,bytes表示要写入多少字节的数
         据。
         PS1:通过fatwrite命令在uboot中更新linux镜像文件和设备树。
         命令:=> tftp 80800000 zImage
               Using FEC1 device
               TFTP from server 192.168.1.250; our IP address is 192.168.1.50
               Filename 'zImage'
               Load address: 0x80800000
               Loading: #####################################################
                        2.2 MiB/s
               done
               Bytes transferred = 6039328 (5c2720 hex)
               => fatwrite mmc 1:1 80800000 zImage 0x5c2720
               writing zImage
               6039328 bytes written
               => fatls mmc 1:1
                  6039328    zimage
                    37099    imx6ull-14x14-evk.dtb
               2 file(s), 0 dir(s)
(7)EXT格式文件系统操作命令
     uboot 有 ext2 和 ext4 这两种格式的文件系统的操作命令,常用的就四个命令,分别为:ext2load、 ext2ls、 ext4load、 ext4ls 和 ext4write。这些命令的含义和使用
     与 fatload、 fatls 和 fatwrit一样,只是 ext2 和 ext4 都是针对 ext 文件系统的。   
     PS1:查询EMMC的分区2中的文件和目录。
     命令:ext4ls mmc 1:2
(8)NAND操作命令
     使用NAND版本的核心板可以了解一下。
(9)BOOT操作命令
     ①、bootz命令
         要启动Linux,需要先将Linux镜像文件拷贝到DRAM中,如果使用到设备树的话也需要将设备树拷贝到DRAM中。可以从EMMC或者NAND等存储设备中将Linux镜像和设备树文件
         拷贝到DRAM,也可以通过nfs或者tftp将Linux镜像文件和设备树文件下载到DRAM中。不管用那种方法,只要能将Linux镜像和设备树文件存到DRAM中就行,然后使用bootz
         命令来启动,bootz命令用于自动zImage镜像文件,格式:bootz [addr [initrd[:size]] [fdt]]
         addr是Linux镜像文件在DRAM中的位置,initrd是initrd文件在DRAM中的地址,如果不使用initrd的话使用‘-’替代即可,fdt就是设备树文件在DRAM中的地址。
         PS1:使用网络的方法来启动Linux系统。
         命令:=> tftp 80800000 zImage                        #下载zImage到DRAM
               Using FEC1 device
               TFTP from server 192.168.1.250; our IP address is 192.168.1.50
               Filename 'zImage'.
               Load address: 0x80800000
               Loading: #####################################################
                        2.3 MiB/s
               done
               Bytes transferred = 6039328 (5c2720 hex)
               => tftp 83000000 imx6ull-alientek-emmc.dtb            #下载imx6ull-alientek-emmc.dtb到DRAM
               Using FEC1 device
               TFTP from server 192.168.1.1250; our IP address is 192.168.1.50
               Filename 'imx6ull-alientek-emmc.dtb'.
               Load address: 0x83000000
               Loading: ###
                        1.6 MiB/s
               done
               Bytes transferred = 37331 (91d3 hex)
               => bootz 80800000 - 83000000                    #启动Linux镜像和设备树
               Kernel image & 0x80800000 [ 0x000000 - 0x5c2720 ]
               ## Flattened Device Tree blob at 83000000
                  Booting using the fdt blob at 0x83000000
                  Using Device Tree in place at 83000000, end 8300cld2
               Modify /soc/aips-bus@021000000/sim@0218c000:status disabled
               ft_system_setup for mx6
               #启动内核
               Starting kernel ...
          PS2:从EMMC中启动Linux系统。
          命令:=> fatload mmc 1:1 80800000 zImage                #从EMMC中加载zImage
                reading zImage
                6039328 bytes read in 152 ms (37.9 MiB/s)
                => fatload mmc 1:1 83000000 imx6ull-alientek-emmc.dtb        #从EMMC中加载imx6ull-alientek-emmc.dtb
                reading imx6ull-alientek-emmc.dtb
                37331 bytes read in 18 ms (2 MiB/s)
                => bootz 80800000 - 83000000                    #启动Linux镜像和设备树
               Kernel image & 0x80800000 [ 0x000000 - 0x5c2720 ]
               ## Flattened Device Tree blob at 83000000
                  Booting using the fdt blob at 0x83000000
                  Using Device Tree in place at 83000000, end 8300cld2
               Modify /soc/aips-bus@021000000/sim@0218c000:status disabled
               ft_system_setup for mx6
               #启动内核
               Starting kernel ...
     ②、bootm命令
         bootm命令和bootz功能类似,但是bootm用于启动uImage镜像文件。如果不使用设备树的话启动Linux内核的命令如下:bootm addr
         addr是uImage镜像在DRAM中的首地址。
         如果要使用设备树,那么bootm命令和bootz一样,格式:bootm [addr [initrd[:size]] [fdt]]
         其中addr是uImage在DRAM中的首地址,initrd是initrd的地址,fdt是设备树(.dtb)文件在DRAM中的首地址,如果initrd为空的话,同样是用-来替代。
     ③、boot命令
         boot命令也是用来启动Linux系统的,只是boot会读取环境变量bootcmd来启动Linux系统,bootcmd是一个很重要的环境变量!其名字分为boot和cmd,也就是引导和命令,
         说明这个环境变量保存着引导命令,其实就是启动的命令集合,具体的引导命令内容是可修改的。比如我们要想使用tftp命令从网络启动Linux那么就可以设置bootcmd为
         tftp 80800000 zImage;tftp 83000000 imx6ull-alientek-emmc.dtb;bootz 8080000 - 83000000,然后使用saveenv将bootcmd保存起来。然后直接输入boot命令即可从
         网络启动Linux系统,命令如下:
         setenv bootcmd 'tftp 8080000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000'
         saveenv
         boot
         前面说过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'
         saveenv
         boot
         如果不修改bootcmd的话,每次开机uboot倒计时结束以后都会从EMMC里面读取zImage和imx6ull-alientek_emmc.dtb,然后启动Linux。
         在启动Linux内核的时候可能会遇到如下错误:
         Kernel panic - not Syncing: VFS:Unable to mount root fs on unknown-block(0,0)
         这个错误的原因是linux内核没有找到根文件系统,这个很正常,因为没有设置uboot的bootargs环境变量。
(10)其他常用命令
     ①、reset命令
         reset命令顾名思义就是复位的,输入reset即可复位重启。
     ②、go命令
         go命令用于调到指定的地址处执行应用,格式:go addr [arg...]
         addr是应用在DRAM中的首地址,可以将裸机例程的.bin文件拷贝到Ubuntu的tftpboot文件夹里面,然后通过tftp命令将.bin下载到开发板DRAM的0X87800000地址处,因为
         裸机例程的链接首地址就是0X87800000,最后使用go命令启动.bin应用。
         命令:tftp 87800000 printf.bin
               go 87800000
     ③、run命令
         run命令用于运行环境变量中定义的命令,比如可以通过run bootcmd来运行bootcmd中的启动命令,但是run命令最大的作用在于运行我们自定义的环境变量。在后面调试
         Linux系统的时候常常要在网络启动和EMMC/NAND启动之间来回切换,而bootcmd只能保存一种启动方式,如果要换另外一种启动方式的话就得重写bootcmd,会很麻烦。这
         里我们就可以通过自定义环境变量来实现不同的启动方式,比如定义环境变量mybootemmc表示从emmc启动,定义mybootnet表示从网络启动,定义mybootnand表示从NAND
         启动。如果要切换启动方式的话需要运行run mybootxxx(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来实现不同的启动:
         run mybootemmc 或 run mybootnand 或 run mybootnet
     ④、mtest命令
         mtest命令是一个简单的内存读写测试命令,可以用来测试自己开发板上的DDR,格式:mtest [start [end[pattern [iterations]]]]
         start是要测试的DRAM开始地址,end是结束地址。
         PS1:测试0X80000000~0X80001000这段内存。
         命令:=> mtest 80000000 80001000
               Testing 80000000 ... 80001000:
               Pattern FFFFFFFF Writing...   ading...Iteration:   486
         测试范围为0X80000000~0X80001000,已经测试了486次,如果要结束测试就按下键盘上的Ctrl+C键。

5、U-Boot目录
   api:与硬件无关的API函数
   arch:与架构体系有关的代码
   board:不同板子(开发板)的定制代码
   cmd:命令相关代码
   common:通用代码
   configs:配置文件
   disk:磁盘分区相关代码
   doc:文档
   drivers:驱动代码
   dts:设备树
   examples:实例代码
   fs:文件系统
   include:头文件
   lib:库文件
   Licenses:许可证相关文件
   net:网络相关代码
   post:上电自检程序
   scripts:脚本文件
   test:测试代码
   tools:工具文件夹
   .config:配置文件,重要的文件
   .gitignore:git工具相关文件
   .mailmap:邮件列表
   .u-boot.xxx.cmd(一系列):这是一系列的文件,用于保存一些命令
   config.mk:某个Makefile会调用此文件
   imxdownload:正点原子编写的SD卡烧写软件
   Kbuild:用于生成一些和汇编有关的文件
   Kconfig:图形配置界面描述文件
   MAINTAINERS:维护者联系方式文件
   MAKEALL:一个shell脚本,帮组编译uboot的
   Makefile:主Makefile,重要文件
   mx6ull_alientek_emmc.sh:正点原子的编译脚本文件
   mx6ull_alientek_nand.sh:正点原子的编译脚本文件
   README:相当于帮助文档
   snapshot.commint:???
   System.map:系统映射文件
   u-boot:编译出来的u-boot文件
   u-boot.xxx(一系列):生成的一些u-boot相关文件,包括u-boot.bin、u-boot.imx等      

6、U-Boot的移植过程简述:
(1)不管是购买的开发板还是自己做的开发板,基本都是参考半导体厂商的demo板,而半导体厂商会在他们自己的开发板上移植好uboot、linux kernel和rootfs等,最终
     制作好BSP包提供给用户。我们可以在官方提供的BSP包的基础上添加我们的板子,也就是俗称的移植。
(2)我们购买的开发板或自己做的板子一般都不会原封不动的照抄半导体产商的demo板,都会根据实际的情况来做修改,既然有修改就必然涉及到uboot下驱动的移植。
(3)一般uboot中需要解决串口、NAND、EMMC或SD卡、网络和LCD驱动,因为uboot的主要目的就是启动Linux内核,所以不需要考虑太多的外设驱动。
(4)在uboot中添加自己的板子信息,根据自己板子的实际情况来修改uboot中的驱动。

7、在U-Boot的图形化配置中添加自定义菜单
(1)在主界面中添加一个名为My test menu,此菜单内部有一个配置项。
(2)配置项为MY_TESTCONFIG,此配置项处于菜单My test menu中。
(3)配置项的变量类型为bool,默认值为y。
(4)配置项菜单名字为This is my test config。
(5)配置项的帮组内容为This is a empty config,just for test!

你可能感兴趣的:(I.MX6UL,linux,嵌入式)