锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

Hi3518E_V200 SDK编译笔记 第一季

时间:2023-06-09 09:07:00 sc380005z1集成电路

第一季
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 一、注释去除后执行 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'
#############################################################################################################################################################################################################################################################################|
unpacking kernel
run_command_progress_float: 'tar -xvzf osdrv/opensource/kernel/linux-3.4.y.tgz -C osdrv/opensource/kernel/'
#############################################################################################################################################################################################################################################################################|
unpacking mpp
mkdir: created directory 'mpp'
run_command_progress_float: 'tar -xvzf package/mpp.tgz'
#############################################################################################################################################################################################################################################################################|
unpacking drv
mkdir: created directory 'drv'
run_command_progress_float: 'tar -xvzf package/drv.tgz'
#############################################################################################################################################################################################################################################################################|

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 如果使用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:$PAT  然后 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),这两部协同工作来完成启动。

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章