Hi3518E_V200 SDK编译笔记 第一季

第一季
1.视频压缩算法有哪些,h.264 mjpeg目前主流的是h.264,压缩就编码,编码就是压缩,3518e内部专门用一个DSP来做视频编码。
2.视频经过压缩之后变成了h.264视频流,压缩的目的就是为了好传输,可以通过有线或无线网络,USB等传输。
3.网络传输协议:http/rtsp等
4.接收端一般有两种处理方法,一种存储,例如把h.264流打包成mp4格式存储;另一种是直接显示。
5.视频回放:解码+播放 解码成原始的图像,位图的图像,播放就是直接把位图的图像丢到LCD里面去播放。
6.视频行业的商业角度分段
(1)主芯片商、sensor、镜头等分立元器件厂商。
(2)模组厂商
(3)视频服务器厂商
(4)面向解决方案的方案开发商
(5)工程商或销售商
7.视频为什么要编码和解码?
    原始视频太大,网络带宽有限,
8.主芯片3518e主要解决什么问题?
    编解码及ISP
9.视频传到传输为什么要用Linux
    Linux里面网络的协议栈是最全的,Linux里面关于网络这一块的开发是最多的。但是在ISP及编码这一段
    安霸用的是rtos,在视频的网络传输这一段用的是LINUX。海思整个过程全部用Linux。
3518e方案系统整体架构介绍
1.硬件 
(1)CPU(ARM9)+DSP+512Mb(64MB)DDR2
(2)外置SPI Flash用来存放程序(uboot、kernel、rootfs、app)
    为什么不用NOR FLASH?太贵
    为什么不用NAND FLAHS?没必要,容量用不了那么大
    为什么不用EMMC?太贵,容量太大浪费。入门级的4GB的二十多块。
    16MB的SPI两块人民币,而且程序(uboot、kernel、rootfs、app)不超过16MB
(3)SD卡扩展提供用户数据区  
    行车记录肯定要
    IPC可以不要,视频可以通过网卡或者WIFI传输
(4)sensor接口 并行接口或者串行接口(MIPI CSI 及LVDS)
(5)串口
2. 软件
(1)SPIFlash分区烧录uboot.bin、zImage、rootfs
 每一段都有预留余量空间
(2)驱动支持
(3)app实现视频采集、编码压缩、网络传输等核心工作
(4)各种专业工作(例如内置DSP实现h.264编码压缩)都由海思开发好并以ko的形式提供,应用开发人员
    只要去调用API实现。
3.SDK
(1)JTAG主要用来调试非常底层的东西的,其实就是UBOOT的,但是实际工作中UBOOT不用从头开始开发。
    所有平时用不到。
(2)uClibc比较精简,它通过glibc库精简出来的,只留下了一些必要的东西,它认为用处不大的东西全部精简掉了,缺点就是功能不全,海思的
    方案SPIflash都是配的是16MB,在这种情况下,你只能用uclibc库。
     glibc比较庞杂,是gcc里面的标准库,什么功能都有,缺点就是太大了,适用于板载emmc等大容量的flash
(3)arm-hisiv300-linux基于uclibc的,编译出来的程序较小  推荐使用arm-hisiv300-linux
    arm-hisiv400-linux是基于glibc的,编译出来的程序较大
(4)把Hi3518E_SDK_V1.0.3.0.tgz复制到Samba共享目录 /opt/share/
(5) 在目录/opt/share/解压 tar xzvf Hi3518E_SDK_V1.0.3.0.tgz 
(6)在目录下/opt/share/Hi3518E_SDK_V1.0.3.0执行  source sdk.cleanup   (这里必须用source才行)
Cleanup SDK

WARN: ALL THE SOUCE FILES WILL BE DELETED, FILES YOU MOTIFIED/ADDED WILL BE LOST !!!

cleanup drv
/opt/share/Hi3518E_SDK_V1.0.3.0 /opt/share/Hi3518E_SDK_V1.0.3.0
run_command_progress_float: 'rm drv -frv'
Initializing progress bar ...find: 'drv': No such file or directory
[    ]--------------------------------------------------|
/opt/share/Hi3518E_SDK_V1.0.3.0
cleanup mpp
/opt/share/Hi3518E_SDK_V1.0.3.0 /opt/share/Hi3518E_SDK_V1.0.3.0
run_command_progress_float: 'rm mpp* -frv'
Initializing progress bar ...find: 'mpp*': No such file or directory
[    ]--------------------------------------------------|
/opt/share/Hi3518E_SDK_V1.0.3.0
cleanup osdrv
/opt/share/Hi3518E_SDK_V1.0.3.0 /opt/share/Hi3518E_SDK_V1.0.3.0
run_command_progress_float: 'rm osdrv -frv'
Initializing progress bar ...find: 'osdrv': No such file or directory
[    ]--------------------------------------------------|
/opt/share/Hi3518E_SDK_V1.0.3.0
         注意:sdk.cleanup里面的这句注释不能去#[ x$choice != xYes ] && exit 1,注释去除后执行 source sdk.cleanup终端自动退出。
(7)source sdk.unpack
Unpacking SDK
WARN: Be sure you have installed the cross-compiler. if not, install it first!
WARN: ALL THE SOUCE FILES WILL BE OVERWRITED, FILES YOU MOTIFIED WILL BE LOST !!!

unpacking osdrv
run_command_progress_float: 'tar -xvzf package/osdrv.tgz'
[100%]##################################################|
unpacking kernel
run_command_progress_float: 'tar -xvzf osdrv/opensource/kernel/linux-3.4.y.tgz -C osdrv/opensource/kernel/'
[100%]##################################################|
unpacking mpp
mkdir: created directory 'mpp'
run_command_progress_float: 'tar -xvzf package/mpp.tgz'
[100%]##################################################|
unpacking drv
mkdir: created directory 'drv'
run_command_progress_float: 'tar -xvzf package/drv.tgz'
[100%]##################################################|

4. osdrv学习
(1)进入osdrv目录,在里面搞uboot、kernel、rootfs等
(2)在osdrv目录下先make OSDRV_CROSS=arm-hisiv300-linux CHIP=hi3518ev200 distclean,把之前的所有中间文件、目录、依赖等全部清除,以防别人别人编译过留下中间文件。
(3)清理完后开始整个编译make OSDRV_CROSS=arm-hisiv300-linux CHIP=hi3518ev200 all
     注意:海思的交叉编译工具链是32位的,环境最好装Ubuntu16.04 32位系统,如果使用64位系统,则需要安装32位兼容包
(4)到/opt/share/Hi3518E_SDK_V1.0.3.0/osdrv/opensource/toolchain/arm-hisiv300-linux目录下执行./cross.install.v300
     符号链接被创建在/opt/hisi-linux/x86-arm/arm-hisiv300-linux/target/bin目录下面
     在此目录下执行arm-hisiv300-linux-gcc -v可以看到版本 
(5)把路径/opt/hisi-linux/x86-arm/arm-hisiv300-linux/target/bin添加到环境变量PATH中,具体为在~/.bashrc里最后一行添加
     export PATH=/opt/hisi-linux/x86-arm/arm-hisiv300-linux/target/bin:$PATH  然后 source ~/.bashrc使其生效
(6)继续编译make OSDRV_CROSS=arm-hisiv300-linux CHIP=hi3518ev200 all
(7)制作文件系统镜像
     SPI flash目前是使用64KB为大小来擦除的,所以下面0x40000改为0X10000 这里的单位都是B,64KB=64*1024B=65536(0x10000)
     osdrv/pub/bin/pc/mkfs.jffs2 -d osdrv/pub/rootfs_uclibc -l -e 0x40000 -o osdrv/pub/rootfs_uclibc_256k.jffs2
(8)fatal error: zlib.h: No such file or directory 报错需要安装 sudo apt-get install zlib1g-dev
(9)手工单独制作rootfs
     手动拷贝cp /osdrv/tools/pc/jffs2_tool/tmp/mtd-utils-1.5.0/mkfs.jffs2 /osdrv/pub/bin/pc
     /osdrv/pub/bin/pc下面的mkyaffs2image100可以删除,我们不需要yaffs的镜像,删除后在osdrv/pub/image_uclibc下面也不会出现yaffs的镜像
     修改osdrv/下的Makefile  
     hipctools: prepare下面值保留 
        @echo "---------task [5] build tools which run on pc"
    保存,重新编译 make OSDRV_CROSS=arm-hisiv300-linux CHIP=hi3518ev200 all
     制作参数为:osdrv/pub/bin/pc/mkfs.jffs2 -d osdrv/pub/rootfs_uclibc -l -e 0x10000 -o osdrv/pub/rootfs_uclibc_64k.jffs2
     
(10)编译最终完成的标准
     在/opt/share/Hi3518E_SDK_V1.0.3.0/osdrv/pub/image_uclibc目录下得到uboot、uImage和roorfs即是我们要的uboot镜像、kernel的
     uImage镜像和文件系统。u-boot-hi3518ev200.bin(268K)  uImage_hi3518ev200(2.6M)  rootfs_hi3518ev200_64k.jffs2(4.8MB)
5. 烧录
(1)各种常见flash的简单讲解
        flash存储颗粒+外部封装的控制器(决定接口类型)
(2)像EMMC、SD、MMC、SPIFLASH、NANDFLASH等差异都在于控制器,内部的存储颗粒都是NAND颗粒。NANDFLASH控制复杂,主芯片内部必须要
    集成NAND控制器,器控制器是最老的最原始的,其实NANDFLASH是即将淘汰的产品,像EMMC(板载)及SD(tf卡)这种都比NANDFLASH要更新一些,
    如果需求是512M或者1G以上的这种大容量的建议选择EMMC(板载)及SD(tf卡)。现在的手机都逐渐由外扩的SD(tf卡)转为EMMC(板载)了。原始的
    NANDFLASH现在用的越来越少了,因为NANDFLASH的兼容性不好。EMMC是无缝替换,不同容量的封装兼容,换一个容量或厂家什么都不用改。
    SPIFLASH控制简单,主芯片只要支持SPI协议即可,在8M、16M、32M、64M这个级别占优势。容量小,成本低。
    比SPIFLASH容量更小,成本更低的有EEPROM
(3)运行Hitool前先安装jre-6u45-windows-i586,一定是这个版本,因为Hitool是基于这个版本来开发的
(4)烧录uboot成功,print查看默认的环境变量
(5)因为嵌入式系统为了简化,没有使用分区表来自动管理flash,所有都是事先定死的,所以在部署一个嵌入式系统前都要人为的定下一个分区,原则为:
     每个分区要足够放镜像;尽量留一点扩展余地;在满足前面两条的情况下你随便搞。
(6)我定的分区:
     分区名              分区大小          起始地址                截止地址     
     bootloader             1M             0X00000000               0x00100000   (1024*1024)B
     kernel:                3M             0X00100000               0X00400000
     rootfs                 12M            0X00400000               0X01000000
(7)烧录kernel及rootfs
    3518EV200 DDR2地址范围为 80000000-83FFFFFF  手册上有
    在这个地址范围内挑一个大小为4.8MB的内存,因为rootfs_hi3518ev200_64k.jffs2(4.8MB)最大,官方推荐从0x82000000开始
    ==============================================================================================================================================
    tftp更新并重新烧写uboot的命令序列:
    mw.b 0x82000000 ff 0x100000           (mw.b 写内存,以字节为单位操作,0x82000000 ff内存从0x82000000开始清成全ff,0x100000为清理的大小为1MB
    tftp 0x82000000 u-boot-hi3518ev200.bin  从服务器(Ubuntu)下载文件(u-boot-hi3518ev200.bin)到内存0x82000000
    sf probe 0  先选中spiflash ,0代表第一个,板上可能有多个flash
    sf erase 0x0 0x100000
    sf write 0x82000000 0x0 0x100000
    ==============================================================================================================================================
    tftp更新并重新烧写kernel的命令序列:
    mw.b 0x82000000 ff 0x300000           (mw.b 写内存,以字节为单位操作,0x82000000 ff内存从0x82000000开始清成全ff,0x300000为清理的大小为1MB
    tftp 0x82000000   uImage_hi3518ev200 从服务器(Ubuntu)下载文件(uImage_hi3518ev200)到内存0x82000000
    sf probe 0  先选中spiflash ,0代表第一个,板上可能有多个flash
    sf erase 0x100000 0x300000
    sf write 0x82000000 0x100000 0x300000
    ==============================================================================================================================================
    tftp更新并重新烧写rootfs的命令序列:
    mw.b 0x82000000 ff 0xc00000           (mw.b 写内存,以字节为单位操作,0x82000000 ff内存从0x82000000开始清成全ff,0xa00000为清理的大小为1MB
    tftp 0x82000000 rootfs_hi3518ev200_64k.jffs2  从服务器(Ubuntu)下载文件(rootfs_hi3518ev200_64k.jffs2)到内存0x82000000
    sf probe 0  先选中spiflash ,0代表第一个,板上可能有多个flash
    sf erase 0x400000 0xc00000
    sf write 0x82000000 0x400000 0xc00000
    ==============================================================================================================================================
(8)修改uboot环境变量并烧录
printenv
    bootargs=mem=96M console=ttyAMA0,115200    
    bootcmd=bootm 0x82000000
    bootdelay=1
    baudrate=115200
    ethaddr=00:00:23:34:45:66
    ipaddr=192.168.1.10
    serverip=192.168.1.2
    netmask=255.255.255.0
    bootfile="uImage"
    stdin=serial
    stdout=serial
    stderr=serial
    verify=n
    ver=U-Boot 2010.06 (Sep 17 2018 - 20:12:12)
    serverip需要修改为服务器ubuntu的IP(192.168.1.141)修改方法为 :setenv serverip 192.168.1.141 然后保存一下 saveenv
    ping 192.168.1.141可以ping通,就可以下载kernel了
    一条一条执行kernel的命令序列:
    一条一条执行rootfs的命令序列:
    kernel和rootfs烧录完成以后,需要设置bootcmd bootargs 设置完成saveen一下,reset后系统启动成功
    附2:正确的bootcmd和bootargs对应的设置命令:
    set bootcmd 'sf probe 0;sf read 0x82000000 0x100000 0x300000;bootm 0x82000000'
    set bootargs mem=32M console=ttyAMA0,115200 root=/dev/mtdblock2 rootfstype=jffs2 mtdparts=hi_sfc:1024K(boot),3072K(kernel),12288K(rootfs)
(9)总结
    SPIFLASH擦除比较慢,读写的速度倒是挺快的。

6. rootfs启动之后做了什么
(1)挂载根文件系统后第一个启动的就是/etc/init.d/rcS文件
(2)/etc/fstab :与挂载的各种虚拟文件系统有关
(3)fs-version:版本号相关
(4)group :管理用户组的  里面的值为root::0:导致开发板登入时为root用户
(5)profile :启动的时候会默认去调用里面的东西
    与环境变量设置相关,echo &PATH   /usr/bin:/usr/sbin:/bin:/sbin
    echo "${GREEN}Welcome to HiLinux.${NORMAL}"  表示开始启动的Welcome to HiLinux.这句话用绿色打印出来
    然后再把颜色设置为NORMAL,
(6)udev目录用来做即插即用的,usb、sd卡等
(7)init.d目录 :rcS是总的纲领,rcS去调用S00devs S01udev S80network S90hibernate
    这些文件命令都是用大写的S开头就是为了能够用一个for循环去执行,后面的数字是为了
    把它们区分开的,数字后面在加这些名字是为了告诉你这些文件是干什么的,S00devs 一看
    就是和devs有关的,
#! /bin/sh

/bin/mount -a

echo "
            _ _ _ _ _ _ _ _ _ _ _ _
            \  _  _   _  _ _ ___
            / /__/ \ |_/
           / __   /  -  _ ___
          / /  / /  / /
  _ _ _ _/ /  /  \_/  \_ ______
___________\___\__________________
"
for initscript in /etc/init.d/S[0-9][0-9]*   //那几个文件都是以大S开头就是为了这里能够用for循环去执行,依次S[0][0]*  S[0][1]* ...
do
    if [ -x $initscript ] ;          //-x表示这个文件存在且可执行则为真
    then
        echo "[RCS]: $initscript"    //这个文件名打印出来
        $initscript                  //并执行这个文件
    fi
done

S00devs文件内容如下:创建设备节点
#!/bin/sh

mknod /dev/console c 5 1
mknod /dev/ttyAMA0 c 204 64
mknod /dev/ttyAMA1 c 204 65
mknod /dev/ttyS000 c 204 64
mknod /dev/null       c 1 3

注意:其实我们在做文件系统的时候已经做了console、ttyAMA0、null打印就会提示文件已经存在
mknod: /dev/console: File exists
mknod: /dev/ttyAMA0: File exists
mknod: /dev/null: File exists

S01udev文件内容如下:
#!/bin/sh

mkdir /dev/pts
mount -t devpts devpts /dev/pts

mkdir -p /dev/.udev        
udevd --daemon       #udevd是一个应用程序,--daemon 就是创建那个守护进程,进程创建后内核就可以检测
                     #即插即拔的设备
udevadm trigger

S80network文件内容如下:

#!/bin/sh

ipaddr=
bootp=
gateway=
netmask=
hostname=
netdev=
autoconf=           #定义变量

for ipinfo in `cat /proc/cmdline`     #cmdline里面内容为mem=32M console=ttyAMA0,115200 root=/dev/mtdblock2 rootfstype=jffs2 rw mtdparts=hi_sfc:1M(boot),3M(kernel),12M(rootfs)
do
        case "$ipinfo" in
        ip=*)
                for var in  ipaddr bootp gateway netmask hostname netdev autoconf
                do
                        eval read $var
                done << EOF
                `echo "$ipinfo" | sed "s/:/\n/g" | sed "s/^[    ]*$/-/g"`
EOF
                ipaddr=`echo "$ipaddr" | cut -d = -f 2`
                [ x$ipaddr == x ] && ipaddr=x
                ;;
        esac
done            #cmdline里面没有ip=*,没有case到

[ -z "$ipaddr" ] && exit 0       #-z用于测试ipaddr长度是否为0,如果ipaddr长度为0则成立,则执行exit 0退出。

echo "      IP: $ipaddr"
echo "   BOOTP: $bootp"
echo " GATEWAY: $gateway"
echo " NETMASK: $netmask"
echo "HOSTNAME: $hostname"
echo "  NETDEV: $netdev"
echo "AUTOCONF: $autoconf"       #这一堆都没有得到执行,因为前面exit 0得到执行已经退出了

if [ x$ipaddr == x- ] ; then     
        # use DHCP
        :
else
        cmd="ifconfig $netdev $ipaddr"
        [ x$netmask != x- ] && cmd="$cmd netmask $netmask"
        eval $cmd
        [ x$gateway != x- ] && route add default gw $gateway
fi                           #没有得到执行

ifconfig lo 127.0.0.1        #没有得到执行


我们可以通过ifconfig -a查看所有的网卡,发现eth0和lo两个网卡都没有打开,因为S80network文件到[ -z "$ipaddr" ] && exit 0 
这里就已经退出了,什么事也没有干,所以我们要设置网卡的时候,我们的命令语句要放在[ -z "$ipaddr" ] && exit 0 的前面

eth0      Link encap:Ethernet  HWaddr 36:9C:26:23:1C:BD  
          BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interrupt:28 

lo        Link encap:Local Loopback  
          LOOPBACK  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

          
          
          
S90hibernate文件内容如下:
          
#!/bin/sh

echo "/root/pm_callback" > /proc/sys/kernel/pm_notifier  #好像是与电源管理相关的,

cmdline=`cat /proc/cmdline`
hbtype=resume

for str in $cmdline
do
    case $str in 
         hbtype=*)
         hbtype=`echo "$str" | awk -F"=" '{print $2}'`
    esac
done

if [ "$hbtype"x = "snap"x ]; then
    echo "hibernate start"
    echo disk > /sys/power/state
fi          

总结:默认的根文件系统提供的这些还远远不够,还需要往里面添加东西
例如我们可以在S80network中把网卡给设置上,就可以在[ -z "$ipaddr" ] && exit 0前面把
ifconfig lo 127.0.0.1
ifconfig eth0 192.168.1.10
给加上

#!/bin/sh

ipaddr=
bootp=
gateway=
netmask=
hostname=
netdev=
autoconf=

for ipinfo in `cat /proc/cmdline`
do
    case "$ipinfo" in
    ip=*)
        for var in  ipaddr bootp gateway netmask hostname netdev autoconf
        do
            eval read $var
        done << EOF
        `echo "$ipinfo" | sed "s/:/\n/g" | sed "s/^[     ]*$/-/g"`
EOF
        ipaddr=`echo "$ipaddr" | cut -d = -f 2`
        [ x$ipaddr == x ] && ipaddr=x
        ;;
    esac
done

ifconfig lo 127.0.0.1
ifconfig eth0 192.168.1.10

[ -z "$ipaddr" ] && exit 0

echo "      IP: $ipaddr"
echo "   BOOTP: $bootp"
echo " GATEWAY: $gateway"
echo " NETMASK: $netmask"
echo "HOSTNAME: $hostname"
echo "  NETDEV: $netdev"
echo "AUTOCONF: $autoconf"

if [ x$ipaddr == x- ] ; then
    # use DHCP
    :
else
    cmd="ifconfig $netdev $ipaddr"
    [ x$netmask != x- ] && cmd="$cmd netmask $netmask"
    eval $cmd
    [ x$gateway != x- ] && route add default gw $gateway
fi

ifconfig lo 127.0.0.1


7. mpp
    \Hi3518E_SDK_V1.0.3.0\mpp\ko目录下的ko文件都是海思预先编译好的模块,用ko的形式提供主要是海思不想开源。
    一是为了版权保护;二是即使给你源码你也玩不来。所以海思预先开发好,预编译成一个库文件提供给我们,我们
    把这些库文件拿到我们的系统里面部署好,部署好之后在系统启动的时候采用insmod方式去安装这些模块,这些
    模块安装了之后呢我们的内核里面就多了这些驱动了,多了这些驱动之后呢我们就可以去调用它们来完成相应的一些
    工作。
    这些ko文件的安装不用我们自己来操作的,ko目录下面有一个load3516ev100文件,这是一个sh文件。
    用法文件的第二行有提示:
    # Useage: ./load3516ev100 [ -r|-i|-a ] [ sensor ]
    
####################MMZ config####################################   定义变量 

mem_total=64;              # 64M, total mem
mem_start=0x80000000;       # phy mem start
os_mem_size=32;             # 32M, os mem
mmz_start=0x82000000;       # mmz start addr
mmz_size=32M;              # 32M, mmz size

##################################################################

####################sensor config#################################   sensor选择

#sensor list: imx290, imx323, ov2718, ar0237, jxf22, sc2235
SNS_TYPE=imx290;            # sensor type

##################################################################


insert_ko()
{
    insert_sns
    insmod sys_config.ko vi_vpss_online=$b_arg_online

    # driver load
    insmod hi_osal.ko mmz=anonymous,0,$mmz_start,$mmz_size anony=1 || report_error
    insmod hi3516cv300_base.ko

    insmod hi3516cv300_sys.ko vi_vpss_online=$b_arg_online sensor=$SNS_TYPE mem_total=$mem_total

    insmod hi3516cv300_region.ko
    insmod hi3516cv300_vgs.ko vgs_clk_frequency=$vgs_frequency

    insmod hi3516cv300_viu.ko detect_err_frame=10 viu_clk_frequency=$viu_frequency isp_div=$isp_div input_mode=$intf_mode
    insert_isp;
    insmod hi3516cv300_vpss.ko vpss_clk_frequency=$vpss_frequency
    insmod hi3516cv300_vou.ko vou_mode=$vou_intf_mode
    #insmod hi3516cv300_vou.ko detectCycle=0 vou_mode=$vou_intf_mode #close dac detect
    #insmod hi3516cv300_vou.ko transparentTransmit=1 vou_mode=$vou_intf_mode #enable transparentTransmit

    insmod hi3516cv300_rc.ko
    insmod hi3516cv300_venc.ko
    insmod hi3516cv300_chnl.ko
    insmod hi3516cv300_vedu.ko vedu_clk_frequency=$vedu_frequency
    insmod hi3516cv300_h264e.ko
    insmod hi3516cv300_h265e.ko
    insmod hi3516cv300_jpege.ko
    insmod hi3516cv300_ive.ko save_power=1 ive_clk_frequency=$ive_frequency
    insmod hi3516cv300_sensor.ko sensor_bus_type=$bus_type sensor_clk_frequency=$sensor_clk_freq sensor_pinmux_mode=$pinmux_mode
    insmod hi3516cv300_pwm.ko

    insmod extdrv/hi_piris.ko
    insert_audio

    insmod hi_mipi.ko

    echo "==== Your input Sensor type is $SNS_TYPE ===="

}
    
    himm:Hisilicon memery modify 海思内存修改工具  这个工具事先已经编译到根文件系统里面去了。
    himm 0x80040000 0x123   
         寄存器地址  寄存器值
    意思就往地址0x80040000 写入值0x123 
    mmz.ko内存管理相关,3518ev200里面Linux系统和mpp内存是分开的,他们两个占用的内存要小于等于64MB
    insmod mmz.ko mmz=anonymous,0,$mmz_start,$mmz_size anony=1 || report_error 让mpp从总内存64MB分一部分。
    3518EV200 DDR2地址范围为 80000000-83FFFFFF
    mmz_start=0x82000000;       # mmz start addr   可以看出mmz的范围0x82000000-0x83FFFFFF    32MB
    mem_start=0x80000000;       # phy mem start    可以看出Linux内存的范围0x80000000-0x81FFFFFF   32MB
    各自的大小看情况定,不一定要一样大。操作系统这边我们可以决定,mpp那边是海思定的,我们可以在满足操作系统
    这边的前提下,尽量多给mmz内存。
8. 在开发板上部署ko、lib
    ./load3518e -i -sensor ar0130 -osmem 32 -total 64    注意:装载sensor是不能动态装载的,要重启
    根文件系统需要部署ko、库lib             注意:.a是静态库,.so动态库,做产品用到得留下,用不到的删除。
    挂载上之后先把ko拷贝到根目录下,个人习惯,cp ko / -rf
    lib拷贝到/usr/lib/(用户库)下面   个人习惯,  cp lib/* /usr/lib/ -f  因为/lib是系统的库,用在系统的库下面不太合适
    你也可以另外建一个文件来存放这些库,然后通过export导出
    还不如直接放在/usr/lib下面,反正这个目录已经导出了
    
    通过命令查询服务器nfs的共享目录:sudo showmount -e
    在/etc/profile最后一行添加
    ifconfig lo 127.0.0.1
    ifconfig eth0 192.168.10.1  这里要隔一下,等通了再挂载
    mount -t nfs -o nolock 192.168.1.101:/opt/nfs /mnt
    部署ko及lib到挂载目录
    最终在/etc/profile添加的是
    ifconfig lo 127.0.0.1
    ifconfig eth0 192.168.1.10
    cd /ko
                                                 
    ./load3518e -i -sensor ar0130 -osmem 32 -total 64 
                                            
    mount -t nfs -o nolock 192.168.1.101:/opt/nfs /mnt
    cd /mnt
    至此,板上ko及lib部署完成。
9. 测试海思的sampe
    编译sampe之前要先修改/mpp/sample/Makefile.param  
    使能下面
    CHIP_ID ?= CHIP_HI3518E_V200
    SENSOR_TYPE ?= APTINA_AR0130_DC_720P_30FPS
    进入/mpp/sample/venc下面make
    在当前目录下编译得到可执行文件sample_venc 把它拷贝到挂载目录/opt/nfs在开发板上执行
    ./sampe_venc 0 选择第一种模式,
    c 选择第一种码流模式
    按两次回车,停止录像,在当前目录下得到三段h.264视频,分别对应1、2、3通道视频,内容一样,分辨率不一样。
    1920*1080*20+720*576*20=49766400    1920*1080*25=51840000算出来差不多  
    子码流的能力可以折合到主码流中
    
10. 制作完成的根文件系统,
    如果希望ko lib提前部署到根文件系统里面,
    (1)在osdrv/pub目录下解压rootfs_uclibc.tgz,得到目录rootfs_uclibc,进入目录rootfs_uclibc,提前把/mpp下的ko及/mpp/lib下的库复制到rootfs_uclibc及user/lib下
    (2)更改rootfs_uclibc/etc/profile,与第八点更改一致即可。
    (3)手工制作rootfs
        退到Hi3518E_SDK_V1.0.3.0目录下执行
         osdrv/pub/bin/pc/mkfs.jffs2 -d osdrv/pub/rootfs_uclibc -l -e 0x10000 -o osdrv/pub/rootfs_uclibc_64k.jffs2   注意:这里SPI block大小为64KB,block大小在uboot开始几行打印出来
        则在/osdrv/pub下生成rootfs_uclibc_64k.jffs2文件,然后烧录即可。
    注意
    (1)./load3516ev100 -i imx323  提示没有执行权限,要在拷贝到rootfs_uclibc目录下之前就把权限修改好。
    (2)==== Your input Sensor type is imx290 ====串口打印还是imx290,
    因为文件load3516ev100没有改为对应型号imx323
           ####################sensor config#################################   sensor选择

           #sensor list: imx290, imx323, ov2718, ar0237, jxf22, sc2235
           SNS_TYPE=imx290;            # sensor type
 

    


    

    进入目录Z:\Hi3518E_V200R001C01SPC020\Hi3518E V200R001C01SPC020\01.software\board
把Hi3518E_SDK_V1.0.2.0.tgz拷贝到自己的工作目录
解压Hi3518E_SDK_V1.0.2.0.tgz得到文件夹Hi3518E_SDK_V1.0.2.0
cd Hi3518E_SDK_V1.0.2.0 
执行source sdk.cleanup清除之前的文件,./sdk.cleanup不行。
然后执行source sdk.unpack解压文件,./sdk.unpack不行。
make OSDRV_CROSS=arm-hisiv300-linux CHIP=hi3518ev200 all  编译osdrv整个目录
报错/bin/sh: 1: popd: not found 
进入/bin目录,查看sh的链接文件,显示如下:表示sh命令链接到的是dash,而pushd命令需要在bash的环境中执行。
执行sudo dpkg-reconfigure dash 命令,将dash设置为No。
再执行make OSDRV_CROSS=arm-hisiv300-linux CHIP=hi3518ev200 all 
报错arm-hisiv300-linux-gcc: Command not found 
可能是Makefile里面arm-hisiv300-linux-gcc路径不对
cp arm-hisiv300-linux.tar.bz2 /data/Hi3518E_SDK_V1.0.2.0/osdrv 把交叉编译工具拷贝到当前目录
tar xjvf arm-hisiv300-linux.tar.bz2 解压工具链
再执行make OSDRV_CROSS=arm-hisiv300-linux CHIP=hi3518ev200 all
报错arm-hisiv300-linux-gcc: Command not found还是找不到,有两种可能一是路径还是不对,二是32位和64位的问题
看一下交叉编译工具链是32还是64位的,因为系统是64位,
其实最终是要找到osdrv/arm-hisiv300-linux/bin下面的工具链,发现下面的工具链的名称arm-hisiv300-linux-uclibcgnueabi
都是以uclibcgnueabi结尾,file arm-hisiv300-linux-uclibcgnueabi-gcc  发现工具链都是32位的,在64位的机器上是不能运行的
解决方法
(1)方法1:换32位ubuntu
(2)方法2:装32位兼容包(windows的64位是兼容32位的,但是在ubuntu里面不行,必须要安装兼容包)
给ubuntu16.0403X64安装32位兼容包
(1)参考:http://blog.csdn.net/ma57457/article/details/68923623
或者:https://www.cnblogs.com/leaven/p/5084902.html
(2)用apt-get install lib32z1 或者apt install lib32z1安装lib32z1。如果发现装不了请用 aptitude方式安装lib32z1。原因是ubuntu太新了,里面很多库都是新版本的,但是基于这个新版本的lib32z1还没有,所以不能装。解决方案就是用aptitude工具来装。看前导课程《嵌入式linux开发环境搭建》的第6节的6.3部分。
(3)测试执行arm-xxx-gcc -v,提示找不到stdc++错误:
./arm-hisiv300-linux-uclibcgnueabi-gcc -v
./arm-hisiv300-linux-uclibcgnueabi-gcc: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory
(4)再用aptitude方式安装lib32stdc++6-4.8-dbg
sudo aptitude install lib32stdc++6-4.8-dbg或者sudo apt install lib32stdc++6-4.8-dbg
再次测试arm-xxx-gcc -v,终于可以运行了。
再次测试整体编译osdrv
make OSDRV_CROSS=arm-hisiv300-linux CHIP=hi3518ev200 all 
(1)仍然提示找不到arm-hisiv300-linux-gcc
(2)修改Makefile中OSDRV_CROSS的路径,结果不行,分析原因是:命令行传参覆盖了
(3)export导出到环境变量,参考裸机课程1.4节,格式为:
echo $PATH先导出原来的环境变量
再添加环境变量
export PATH=/data/Hi3518E_SDK_V1.0.2.0/osdrv/arm-hisiv300-linux/bin:$PATH
arm-hisiv300-linux-uclibcgnueabi-gcc -v在非arm-hisiv300-linux/bin目录下来执行成功,说明环境变量导出成功
cd ~ 切换到对应用户的家目录
vim .bashrc
export PATH=/data/Hi3518E_SDK_V1.0.2.0/osdrv/arm-hisiv300-linux/bin:$PATH 直接写入.bashrc
这样以后每次打开终端环境变量都生效

再次测试整体编译 make OSDRV_CROSS=arm-hisiv300-linux CHIP=hi3518ev200 all 
直接测试可以执行了,但是编译还是出错。分析原因:名字不对make里面是arm-hisiv300-linux但是我们直接执行的是arm-hisiv300-linux-uclibcgnueabi
(4)解决方案有2个:一种是修改make时传参的名字,另一种是给安装好的交叉编译工具链创建符号链接。实际尝试后发现第一种Makefile要改的太多,所以走第2种。
rm -fr arm-hisiv300-linux rm -f arm-hisiv300-linux.tar.bz2 删除刚刚解压的arm-hisiv300-linux,因为在Hi3518E_SDK_V1.0.2.0/目录下执行sdk.cleanup  sdk.unpack任意一个文件,下面的所有的文件都将被清空
切换到/osdrv/opensource/toolchain/arm-hisiv300-linux目录执行./cross.v300.install 
然后到/opt/hisi-linux/x86-arm/arm-hisiv300-linux/target/bin下执行./arm-hisiv300-linux-gcc -v 执行成功后
添加环境变量到~/.bashrc中export PATH=/opt/hisi-linux/x86-arm/arm-hisiv300-linux/target/bin:$PATH
source ~/.bashrc使其生效
在非arm-hisiv300-linux/target/bin目录下执行arm-hisiv300-linux-gcc -v成功
切换回osdrv目录下执行make OSDRV_CROSS=arm-hisiv300-linux CHIP=hi3518ev200 all 再次编译

使用install脚本安装交叉编译工具链
(1)install到/opt目录下并建立符号链接
(2)导出到PATH并测试可以执行
(3)再次编译

11.驱动是什么
驱动就是操作系统的一部分,操作系统不是写好的?没错,操作系统的大体是写好的,操作系统里面局部是有扩展的,比如
说驱动就是一个典型的,它是操作系统的一部分,但是它是可以扩展的。操作系统就是所谓的底层。
12.BSP
Bord suport package 板级支持包
用来支持开发板的一些软件,比如官方给的一些驱动,这些是根据这个板移植过的。还是属于底层的。
应用软件怎么操控硬件,通过BSP里面的驱动来调用,操作系统来调用BSP,操作系统是个中间人。
操作系统里面的驱动层负责与硬件沟通,反馈给应用程序。

13. uboot
虽然不属于操作系统,但是它是操作系统的狗腿子,跟着操作系统混的,用来引导操作系统的。

14. 交互性
Linux的交互性不好,Android的交互性好,所以目前的所有的有交互性需求的都使用Android,比如手机,平板。
Linux天生就适合在后台跑。

15. 对称多核与大小核
比如三星4412里面的A9就是对称4核,每一个核都是一样的
FPGA(核)+ARM(核)   DSP(主运算)+ARM (主控)

16.交叉编译
非嵌入式开发,A类机器编写源代码,编译得到可执行程序,发布给A类机器执行。
嵌入式开发,A类机器编写源代码,编译得到可执行程序,发布给B类机器执行。这叫交叉编译。在A和B之间来交叉。

17.为何使用交叉编译
嵌入式开发的CPU比较简单,本身无法搭建开发环境,有些甚至操作系统都没有。
交叉编译可以用高性能机器为低性能机器开发软件(包括软件软件、系统级和应用及软件)

18.交叉编译工具与交叉编译工具链
我们默认交叉编译工具就是交叉编译工具链,工具链是一大串,包括gcc g++ gdb ld等等,
我们叫编译软件包,我们一般就把这个软件包叫做交叉编译,虽然这是错误的叫法,习惯了大家都。
由于可执行程序不能本地运行调试,因此必须配合一定手段(专用调试器、JTAG调试器、USB下载
、串口下载、SD启动、网络共享等)将可执行程序加载到目标嵌入式设备上运行及调试。

19.什么是IO
input and output 是输入输出接口,是CPU和其他外部设备(如串口
、LCD、触摸屏、LED等)之间通信的道路。一般的IO就是指CPU的各种内部或
外部设。进一步理解就是这些外部设备里面的寄存器。

20.IO的访问方式


CPU访问各种外设有2种方式:
一种是类似于访问内存的方式,即把外设的寄存器当做一个内存地址
来读写,从而以访问内存相同的方式来操作外设,叫IO与内存统一编址方式;
这种方式与操作外设与操作内存没有什么区别。(ARM 里面都是这种方式,精简指令集,指令集少)
优势:IO当做内存来访问,编程简单;
缺点:IO也需要占用一定的CPU地址空间,而CPU的地址空间是有限资源

另一种是使用专用的CPU指令来访问某种特定外设,叫IO与内存独立编址。
这时候外设的没有地址,不能像访问内存一样访问外设。只能通过专门的CPU指令来读写。
(Intel CPU 发生在复杂指令集,指令集很多)
优势:不占用CPU地址空间
缺点:是CPU设计变复杂了,一个指令对应一个CPU内部的电路,指令集越多,CPU设计越复杂。


21.程序和数据
程序运行时两大核心元素:程序+数据
程序是我们写好的源代码经过编译、汇编之后得到的机器码,这些
机器码可以拿给CPU去解码执行。CPU不会也不应该去修改程序,所以
程序是只读的。写的代码(程序)实际就是数据处理器,数据就是原材料。

数据是程序运行过程中定义和产生的变量的值。是可以读写的,程序
运行实际就是为了改变数据的值。

22. 冯诺依曼结构与哈佛结构
冯诺依曼
程序和数据都在放内存中,且不彼此分开,Intel CPU

特点:程序在运行的过程中其实是不需要去改变的,CPU只要去读
它就好了,这里你读写都可以了,那么我可以人为的写代码去读写程序段,
这就解释了这种结构容易受到攻击,有很多病毒就是利用这个特点想办法去
写你的程序段。存在安全和稳定性问题。好处是处理起来简单,程序和数据
不做区分就简单。桌面的程序死了不会造成多少伤害,但是嵌入式就不行,
比如工业设备要是出问题就会造成很大伤害的。


哈佛结构
程序和数据分开独立放在不同的内存块中,彼此完全分离的结构称为哈佛结构
51单片机和ARM

特点:哈佛结构中程序(一般放在ROM flash中)和数据(一般放在
RAM中)独立分开存放,因此好处是安全和稳定性高,缺点是软件处理
复杂一些(需要统一规范链接地址等)

23 寄存器
软件编程控制硬件的关键-寄存器
寄存器属于CPU外设的硬件组成部分
CPU可以像访问内存一样访问寄存器
寄存器时CPU的硬件设计者制定的,目的是留作外设被编程控制的‘活动开关’
使用软件编程控制某一硬件,其实就是编程读写该硬件的寄存器

编程操作寄存器类似于访问内存
寄存器中每个bit位都有特定含义,因此编程操作时需要位操作
单个寄存器的位宽一般和CPU的位宽一样,以实现最佳访问效率
    
24.两类寄存器
Soc中有2类寄存器:通用寄存器和SFR
通用寄存器(ARM中有37个)是CPU的组成部分,CPU的很多活动都需要
通用寄存器的支持和参与

SFR特殊功能寄存器不在CPU中,而在CPU的外设中,    
    
25. 什么是内存映射
32根地址线决定了CPU的地址空间为4G,需要注意的是CPU的地址线
与数据线不一定相等,一般都是相等的。

32根地址线决定了CPU的地址空间为4G,那么这4G空间如何分配使用?
这个问题就是内存映射问题(准确点应该叫地址映射)

地址映射是CPU设计者说了算

CPU的运算性能和它的内存要匹配的,

33. 一些专用的术语
ROM: read only memory 只读存储器    
    比如硬盘  
    这里的只读不是真的不能写,其实硬盘是可以写的,但是不能
    通过地址总线和数据总线来写,硬盘是通过其他数据接口来写的
RAM: ramdom access memory 随机访问存储器
    什么是随机,随机是相对于顺序来说的,随机就是我想访问那个地址就
    访问那个地址,而不用按照顺序去排。
    flash是按顺序访问的,flash是按页访问的,比如说一页是512B,
    这512B你是不能随意访问的,你要访问第四个字节,你得从第0个字节
    开始访问,依次访问到第四个字节。你想直接访问第四个字节,不可能。
    你得先访问前面那几个没用的字节后再说,然后才能访问到第四个字节。
    
34. 内存与外存
内存   内部存储器  用来运行程序的, RAM 举例(DRAM SRAM DDR)
外存   外部存储器  用来存储东西的,ROM 举例(硬盘 Flash (NAND iNand ...U盘、SSD)光盘)

CPU连接内存和外存的连接方式不同,
内存需要直接地址访问,所以是通过地址总线&数据总线的总
线式访问连接的(好处是直接访问,随机访问;坏处是占用CPU的地址空间,大小受限);

外存是通过CPU的外存接口来连接的(好处是不占用CPU的地址空间,坏处是访问速度没有总线式快,访问时序较复杂)

35. Soc常用外部存储器
NorFlash 
    可以总线式访问,访问方式与RAM无差异,三星的S210就接到SROM bank,优点是可以总线式访问,
    一般用来启动,一般的台式机的BIOS就是放在NorFlash里面。
    NorFlash贵,但是可靠

下面这五种本质都是NAND FLASH 
NandFlash
eMMC/iNand/moviNand   eMMc (embeded MMC,可以自动帮你管理坏块) iNand是SanDisk公司出产的eMMC,moviNand是三星公司出产的eMMC
oneNAND   oneNand是三星公司出的一种Nand,用的不多
SD卡/TF卡/MMC卡
eSSD

NandFlash不能通过总线式访问,只能通过时序去访问,通过时序去访问一般不能用来做启动,
但是后来的技术支持从NandFlash来启动了
NandFlash便宜但是不可靠,容易出现坏块,分为SLC(比较可靠,不容易出现坏块)和MLC(不太
可靠,一般要做ECC校验,编程比较麻烦,需要管理坏块,容量大,成本低)

硬盘
SATA硬盘(机械式访问、磁存储原理、SATA是接口)


36. 启动过程
内存:
    SRAM  静态内存   特点:容量小,价格高,几十KB,优点:不需要软件初始化直接上电就能用
    DRAM  动态内存   特点:容量大,价格低,缺点:需要软件初始化,需要软件初始化后才能使用
单片机中:内存需求量小,而且希望开发尽量简单,适合全部用SRAM,
嵌入式系统:内存需求量大,
PC机:内存需求量大,而且软件复杂,不在乎DRAM的初始化开销,适合全部用DRAM
        
外存:
    NorFlash:特点是容量小,价格高,优点是可以和CPU直接总线式相连,CPU上电后可以直接读取,所以一般用作启动介质,
    
    NandFlash(跟硬盘一样):特点是容量大,价格低,缺点是不能总线式访问(也就是说不能上电CPU直接读取
    需要CPU先运行一些初始化软件,初始化硬盘,然后通过时序接口读写)
    
    
所以一般PC机都是:很小容量的BIOS(NorFlash)+ 很大容量的硬盘(类似于NandFlash,使用前一定要初始化,谁来初始化它,BIOS)+大容量的DRAM(使用前一定要初始化,谁来初始化它,BIOS)
一般的单片机:很小容量的NorFlash+很小容量的SRAM,做单片机的根本就不知道硬件还要初始化啊,因为你
单片机用的都是上电就能用的东西。单片机里面就是不需要很大容量的硬盘,不需要很大容量的DRAM,所用才用了很小容量的NorFlash+很小容量的SRAM这种架构。
嵌入式系统:因为NorFlash很贵,现在很多嵌入式系统倾向于不能NorFlash,
            直接用:外接的大容量Nand+外接大容量DRAM+soc内置SRAM(开机的时候利用CPU的一些特殊设计,开机的时候把外接的大容量Nand一小段代码读取到里面来运行
            ,大家都知道SRAM是不需要开机初始化的,可以开机直接运行的,内部的SRAM是可以直接运行外接的大容量Nand一小段代码的,这一运行就可以去初始化外部的Nand
            Flash,也可以去初始化外部的DRAM,这两个东西经过初始化之后就活了,)

S5PV210使用的启动方式是:外接的大容量Nand+外接大容量DRAM+Soc内置SRAM
实际上210的启动过程还要更好玩一些,210内置了一块96KB的SRAM(叫iram),同时还有一块内置的64KB的NorFlash(叫iROM),
210的启动过程大致是:
第一步:
CPU上电后先从内部IROM中读取预先设置的代码(BL0),执行。这一段IROM代码首先做了一些基本的初始化(CPU时钟、
关看门狗...)(这一段IROM代码是三星出厂前设置的,三星也不知道我们板子上将来接的是什么样的DRAM,因此这一段
IROM是不能负责初始化外接的DRAM的,因此这一段代码只能初始化soc内部的东西);然后这一段代码会判断我们选择的
启动模式(我们通过引进跳线可以更改板子的启动模式),然后从相应的外部存储器去读取第一部分启动代码(BL1,
大小为16KB)到内部SRAM。
第二步:从IRAM去运行刚上一步读取来的BL1(16KB),然后执行。BL1负责初始NANDflash,然后将BL2读取到IRAM(剩余80KB
)然后运行。
第三步:从IRAM运行BL2,BL2初始化DRAM,然后将OS读取到DRAM中,然后启动OS,启动过程结束。
三星的解决方案是:把启动代码分2半(BL1和BL2),这两部协同工作来完成启动。

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值