本文介绍的是拿到海思芯片的开发板和海思的SDK开发包,在裸机上部署uboot、kernel、rootfs、mpp的过程,其中不涉及uboot、kernel、rootfs、mpp的细节,主要是介绍如何使用开发包快速的将海思芯片跑起来。(这里的裸机是指海思芯片就是出厂的状态,连uboot都没有)。本文大体上是从逻辑上讲解如何部署海思SDK,并不能保证你能按着文章讲解的顺序就能畅通无阻的完成SDK的部署。光是编译uboot、kernel、rootfs就可能遇到很多错误,每个人的开发环境不同,遇到的错误也不一样,在这里不讲解可能遇到的错误,有问题就去百度。
我用的是HI3518EV200这款芯片,现在来看这款芯片的性能并不算好,但是只用该芯片做单纯录像的监控设备,性能还是足够的,如果想要跑算法就显得性能不足了。该款芯片内置64M的内存,可以不用外接内存就可以运行,SDRAM的地址范围:80000000-83FFFFFF,我的开发板是外接的16M的spi flash,将来uboot、kernel、rootfs都烧录到spi flash中。
(1)首先是搭建开发环境,我是用PC端来开发的,要自己装虚拟机搭建环境,比较麻烦,公司开发都是服务器上进行开发,不用自己搭建环境;
(2)熟悉SDK包,了解目录的结构,找到与编译生成uboot、kernel、rootf1s相关的内容,看文档和编译脚本。
(3)在虚拟机中编译生成uboot、kernel、rootf1s的镜像,;
(4)将uboot、kernel、rootf1s烧录进海思芯片里;
(5)部署mpp:将海思相关的.ko文件和.so文件都拷贝到设备的目录里加载好;
(6)编译SDK包里的sample程序,如果示例程序能在海思芯片上正常运行,说明此次部署已经成功;
(7)后期展望:按照SDK去部署系统是比较基础的,没有针对设备进行优化,比如uboot、kernel、rootfs都是可以针对设备进行精简的,这样可以节省内存,用不上的.ko和.so也不必拷贝到设备里。
(1)编译环境:Windows+VMware+Ubuntu;
(2)在虚拟机里搭建好samba服务器、tftp服务器、nfs服务器,调试好网络,确认设备可以通过网络连接上虚拟机;
(3)确认PC和设备可以通过终端模拟软件进行串口通信;
(1)游览《Hi3518EV20X/Hi3516CV200 U-boot 移植应用开发指南》和《Hi3518EV20X/Hi3516CV200 Linux开发环境用户指南》,里面讲解的是开发环境的搭建和U-boot的移植;
(2)将“Hi3518E_SDK_V1.0.3.0.tgz”压缩包拷贝到Linux环境中进行解压,可以通过共享文件夹或者Samba服务器,推荐共享文件夹;
(3)将压缩包解压开后,可以看到两个脚本文件:sdk.cleanup和sdk.unpack。先执行source sdk.cleanup清除掉整个目录里的中间文件、解压文件、目标文件,确保目录里的文件都是干净的;然后执行source sdk.unpack,将目录里的压缩包都解压开。
(1)安装交叉工具编译链:交叉工具编译链在“Hi3518E_SDK_V1.0.3.0/osdrv/opensource/toolchain/”路径下,有arm-hisiv300-linux和arm-hisiv400-linux两个交叉工具编译链,arm-hisiv300-linux对应uclibc库,arm-hisiv400-linux对应glibc库,自己根据需求选择一个安装。在交叉工具编译链的目录下有个cross.install.v300脚本文件,执行该脚本文件会自动安装交叉工具编译链。该脚本会安装交叉工具编译链并创建链接符号,我们需要将创建的那个路径导出到环境变量PATH里。具体的细节查看cross.install.v300文件。对交叉工具编译链安装不熟悉的可以参考《交叉编译工具链的安装以及介绍》。
(2)安装32位的兼容包:交叉工具编译链是32位的,我的Ubuntu是64位的,所以需要安装lib32z1,因为编译还涉及C++编译还需要装lib32stdc++6-4.8-dbg,推荐使用aptitude进行安装。
(3)将“Hi3518E_SDK_V1.0.3.0/osdrv/opensource/uboot/u-boot-2010.06/tools”路径下的mkimage拷贝到**/usr/local/lib目录下,这是制作镜像需要用到的。
(4)制作uboot、kernel、rootfs:“Hi3518E_SDK_V1.0.3.0/osdrv”目录里的内容就是制作镜像的,Makefile文件是编译脚本,该Makefile的使用方法看同目录下的readme_cn.txt**文件。理论上来说,按照readme_cn.txt的说明可以直接一条命令就可以生成uboot、kernel、rootfs三个镜像文件,实际编译过程会遇到很多问题。遇到问题就研究Makefile文件或者百度,我反正当时被折磨的够呛。
(5)最终得到三个镜像文件:rootfs_hi3518ev200_64k.jffs2、u-boot-hi3518ev200.bin、uImage_hi3518ev200。
特别提醒:制作rootfs时注意文件系统的格式和flash的块大小,这些在readme_cn.txt都有说明。
1.uboot的烧写参考博客《海思烧录工具HiTool的使用方法以及烧录uboot》和《用HiTool烧写uboot到spi flash的原理》。
2.将uboot烧写到0x0起始地址处;
已经部署好uboot就不用再使用HiTool进行烧录了,用uboot进行烧写更方便,下面将uboot、kernel、rootfs都再重新烧写一遍。
分区名 分区大小 起始地址 截至地址
bootloader: 1M 0x00000000 0x00100000
kernel: 3M 0x00100000 0x00400000
rootfs: 12M 0x00400000 0x01000000
解析:spi flash总共有16M,uboot有266kb,kerner有2.6M,rootfs有4.8M。所以uboot分配1M的地址空间,kernel分配3M,剩下的12M全部分配给rootfs。分区的原则有两个:首先是每个分区要能放得下镜像文件,还有就是有扩展余地,适当多分配一点。
在前期的环境搭建中就在虚拟机中搭建好了tftp服务器,现在只需要将uboot中的serverip改为虚拟机的ip地址,确保开发板可以ping通虚拟机。将uboot、kernel、rootfs的镜像放到虚拟机的tftp目录下,接下来就利用tftp下载烧录镜像。
本次是利用uboot的命令进行烧录,因为前面已经将uboot烧录到了开发板,但是为了烧录的完整性,接下来还会把uboot重新烧录一遍。这里有一些隐含的知识点:1.HI3518EV200芯片的内置内存的地址范围是80000000-83FFFFFF;2.spi flash的起始地址是0x0,且只外接了一块spi flash;spi flash的写操作顺序:选中、擦除、写入;3.uboot、kernel、rootfs烧录到flash的位置要严格按照分区表进行;4.海思芯片的内存是分为系统内存和mmz内存,系统内存由kernel管理,mmz由海思内部管理;5.接下来的操作都是进入到uboot里输入命令进行烧录;
tftp更新并重新烧写uboot的命令序列:
(1)mw.b 0x82000000 ff 0x100000 //擦除内存:在0x82000000起始地址处按字节写入ff,长度为0x100000(1M)
(2)tftp 0x82000000 u-boot-hi3518ev200.bin //通过tftp命令,将虚拟机tftp目录下的uboot镜像烧录到0x82000000起始的内存处
(3)sf probe 0 //选中spi flash,因为只外接了一片flash,所以是probe 0
(4)sf erase 0x0 0x100000 //从0x0起始,擦除1M大小的地址空间
(5)sf write 0x82000000 0x0 0x100000 //将从0x82000000地址处开始,长度为1M大小的数据写入到0x0地址起始处。也就是把刚才写到内存里的uboot镜像写入到flash中
tftp更新并重新烧写kernel的命令序列:
(1)mw.b 0x82000000 ff 0x300000
(2)tftp 0x82000000 uImage_hi3518ev200
(3)sf probe 0
(4)sf erase 0x100000 0x300000
(5)sf write 0x82000000 0x100000 0x300000
备注:以上命令不再解释,和烧录uboot是一样的,只是烧写的地址不一样,结合分区表来看就很容易理解。
tftp更新并重新烧写rootfs的命令序列:
(1)mw.b 0x82000000 ff 0xc00000
(2)tftp 0x82000000 rootfs_hi3518ev200_64k.jffs2
(3)sf probe 0
(4)sf erase 0x400000 0xc00000
(5)sf write 0x82000000 0x400000 0xc00000
备注:以上命令不再解释,和烧录uboot是一样的,只是烧写的地址不一样,结合分区表来看就很容易理解。
命令:set bootcmd ‘sf probe 0;sf read 0x82000000 0x100000 0x300000;bootm 0x82000000’
解析:这是uboot启动的命令,作用是加载kernel。
(1)sf probe 0:选中spi flash;
(2)sf read 0x82000000 0x100000 0x300000:从0x100000地址处读取0x300000(3M)大小的数据到0x82000000地址处。就是将保存到flash的kernel读取到内存中,刚好和我们的烧录是逆过程。
(3)bootm 0x82000000:加载kernel。
命令:set bootargs mem=32M console=ttyAMA0,115200 root=/dev/mtdblock2 rootfstype=jffs2 mtdparts=hi_sfc:1024K(boot),3072K(kernel),12288K(rootfs)
解析:这是启动uboot的传参,指定一些关键的参数。
(1)mem=32M:这里指明系统分配内存32M(总共有64M的内存);
(2)console=ttyAMA0,115200:系统控制台的波特率是115200
(3)root=/dev/mtdblock2:rootfs在第二个分区(按0、1、2来计数的),对应分区表的第三个分区;
(4)rootfstype=jffs2 :根文件系统的格式是jffs2;
(5)mtdparts=hi_sfc:1024K(boot),3072K(kernel),12288K(rootfs):系统有三个分区:uboot占1M、kernel占3M、rootfs占12M,刚好分配完16M的flash;
mpp的部署参考博客《海思芯片部署MPP并验证功能》。