一、操作环境
PC:win10
虚拟机:Ubuntu14.04 LTS 64bit
板端:DOPI 3516EV200 (Hi3516EV200)NAND 128MB
需要liteOs SDK(Hi3516EV200_SDK_V5.0.1.1.tgz)、以及海思的开发文档。
二、SDK框架
在SDK下有一下的文件夹:
drv目录:分为两个目录一个interdrv,用于存放板级相关的外设驱动以及系统时钟的配置。extdrv一般存放的是外部的设别驱动,如touch screen通过iic或者其他板级外设进行通信的驱动。对于liteos,是将所有的内部和外部驱动文件打包成库文件放在sdk/mpp/lib下,下面会讲解。
mpp目录:相关的目录结构:
component里面有fbdev和isp的驱动,isp里面包含了还是摄像头的初始化驱动,这些数据编译后会在mpp/lib里面产生对应的库文件,然后自己的app需要的时候链接便可以。init目录下主要是sdk的一个初始化函数用来调用还是的框架初始化函数以及在sdk/drv/interdrv下的初始化板级相关的函数,后面讲mpp/sample时会说到。lib文件夹海思媒体框架所有的库文件包括sdk/drv下的所有驱动都会在make的时候生成库文件存放在mpp/lib里面,以供sample下的例子能有链接以及调用。sample目录下有一些还是的例子以及一些共有的目录,如mpp/sample/liteos/app_init.c,对于SDK的mpp/sample下的历程所编译的bin都是从app_init.c开始启动,通过app_init这个函数先后初始化板级的外设、挂载文件系统、网络以及usb,调用mpp/init里面的SDK_init函数对还是框架进行初始化,然后通过sample_command函数注册一个命令,最后初始化终端。当终端敲入对应的命令,会调用回掉函数app_sample,然后再app_sample函数里面创建一个 com_app的任务,至此跳入我们的app里面的main函数。
三、创建一个hello word 初步装备
上述分析可见,mpp/init与mpp/sample/liteos下的文件是多个例子所公有的文件,为了防止对sdk其他例程产生影响,在创建helloword之前先将其拷贝出来,在sample下新创建一个文件夹helloword,用于存放我自己的app,将sample/liteos/app_init.c拷贝到helloword下,拷贝sample/aduio/makefile拷贝到helloword下,创建一个src、out文件夹,src用于存放自己的源码,out用于存放编译的中间文件以及编译后的二进制文件,在out下创建bin、dbg、obj用于存放不同的编译中间文件以及最终的二进制文件。修改下makefile:
include ../Makefile.param
USE_SPECAWB=n
SDK_DIR=$(shell pwd)/../../..
REL_DIR=$(SDK_DIR)/mpp
REL_LIB=$(REL_DIR)/lib
LITEOSTOPDIR=$(SDK_DIR)/osdrv/platform/liteos/liteos
CROSS=arm-himix100-linux-
HIARCH=hi3516ev200
include $(LITEOSTOPDIR)/config.mk
CPP = $(CROSS)g++
CC = $(CROSS)gcc
AS = $(CROSS)as
AR = $(CROSS)ar
LD = $(CROSS)ld
GPP = $(CROSS)g++
OBJCOPY = $(CROSS)objcopy
OBJDUMP = $(CROSS)objdump
SAMPLE_OUT = $(shell pwd)/out
ROOT_DIR := $(shell pwd)
SDK_LIB_PATH := -L$(REL_LIB) -L$(REL_LIB)/extdrv
ifeq ($(USE_SPECAWB),y)
AWB_LIB=_hiawb_natura
else
AWB_LIB=_hiawb
endif
SDK_LIB := $(SDK_LIB_PATH) --start-group -lhi_osal -lmpi -l$(HIARCH)_base -l$(HIARCH)_sys -lhi_user -l$(HIARCH)_isp -l$(HIARCH)_vi \
-l$(HIARCH)_vo -l$(HIARCH)_vpss -l$(HIARCH)_vgs -l$(HIARCH)_ive -lhi_mipi_rx -lhifb -lsys_config -lhi_cipher \
-l$(HIARCH)_chnl -l$(HIARCH)_rc -l$(HIARCH)_rgn -l$(HIARCH)_vedu \
-l$(HIARCH)_venc -l$(HIARCH)_h265e -l$(HIARCH)_jpege -l$(HIARCH)_h264e \
-l_hidehaze -l_hidrc -l_hildci -l$(AWB_LIB) -l_hiae -lisp -lhi_sensor_i2c -lhi_piris\
-laacdec -laacenc -lupvqe -ldnvqe -lVoiceEngine -l$(HIARCH)_ai -l$(HIARCH)_ao -l$(HIARCH)_aio -l$(HIARCH)_aenc -l$(HIARCH)_adec -l$(HIARCH)_acodec \
-lhi_sensor_spi -lhi_pwm -lhi_sil9024 -l$(HIARCH)_tde \
-l$(HIARCH)_ive -live -lmd -livp\
-lhi_ssp_st7789\
# -ltools \
--end-group
SDK_LIB += $(SENSOR_LIBS)
LITEOS_LIBDEPS = --start-group $(LITEOS_LIBDEP) --end-group $(LITEOS_TABLES_LDFLAGS)
LDFLAGS := $(LITEOS_LDFLAGS) --gc-sections
LIBS_CFLAGS := -fno-aggressive-loop-optimizations -ldl -ffunction-sections -fdata-sections
MPP_CFLAGS := -Wall
CFLAGS ?=
CFLAGS += -O2
CFLAGS += $(LITEOS_CFLAGS)
CFLAGS += $(LIBS_CFLAGS)
CFLAGS += $(MPP_CFLAGS)
CFLAGS += -D__HuaweiLite__ -D__KERNEL__
ifeq ($(USE_SPECAWB),y)
CFLAGS += -D__USE_SPECAWB__
endif
CFLAGS += $(COMM_INC)
CFLAGS += -I$(REL_DIR)/include
CFLAGS += -I$(REL_DIR)/component/isp/ext_inc
CFLAGS += -I$(REL_DIR)/component/isp/kernel/arch/hi3516ev200/include
CFLAGS += -I$(REL_DIR)/component/isp/user/firmware/arch/hi3516ev200/include
CFLAGS += -I$(REL_DIR)/component/isp/user/firmware/include
CFLAGS += -I$(REL_DIR)/component/isp/kernel/mkp/include
CFLAGS += -I$(SDK_DIR)/osal/include
CFLAGS += -I$(REL_DIR)/sample/common
CFLAGS += -I.
CFLAGS += -I./include -I./lib
CFLAGS += -I$(REL_DIR)/../tools/toolchains/hisi-linux/x86-arm/arm-himix100-linux/target/usr/include
# target c source
SRCS += $(wildcard $(REL_DIR)/sample/common/*.c)
SRCS += $(REL_DIR)/init/sdk_init.c
SRCS += $(REL_DIR)/init/sdk_exit.c
# target c++ source
CPP_SRCS :=
#自动搜索app目录下以及子目录下所有.c .cpp文件
ALL_DIRS = $(shell find . -type d)
SRCS += $(foreach dir, $(ALL_DIRS), $(wildcard $(dir)/*.c))
CPP_SRCS += $(foreach dir, $(ALL_DIRS), $(wildcard $(dir)/*.cpp))
INCLUDE := $(patsubst %,-I%,$(ALL_DIRS))
CFLAGS += $(INCLUDE)
OBJS += $(patsubst %.c,%.o,$(SRCS))
#cpp objs
CPP_OBJS += $(patsubst %.cpp,%.o,$(CPP_SRCS))
OBJS_DIR := $(SAMPLE_OUT)/obj
BIN_DIR := $(SAMPLE_OUT)/bin
DBG_DIR := $(SAMPLE_OUT)/dbg
TARGET := sdk_sample
BIN := $(BIN_DIR)/$(TARGET).bin
MAP := $(DBG_DIR)/$(TARGET).map
ASM := $(DBG_DIR)/$(TARGET).asm
TARGET_BIN := $(DBG_DIR)/$(TARGET)
CPPFLAGS += $(CFLAGS)
.PHONY : clean all
all: DEBUG $(OBJS) $(CPP_OBJS) $(BIN)
DEBUG:
@$(shell if [ ! -d $(SAMPLE_OUT) ];then mkdir $(SAMPLE_OUT); fi;)
@$(shell if [ ! -d $(OBJS_DIR) ];then mkdir $(OBJS_DIR); fi;)
@$(shell if [ ! -d $(BIN_DIR) ];then mkdir $(BIN_DIR); fi;)
@$(shell if [ ! -d $(DBG_DIR) ];then mkdir $(DBG_DIR); fi;)
$(BIN):$(TARGET)
$(OBJCOPY) -O binary $(TARGET_BIN) $(BIN)
$(TARGET):
@$(LD) $(LDFLAGS) -Map=$(MAP) -o $(TARGET_BIN) $(OBJS_DIR)/*.o $(SDK_LIB) $(LITEOS_LIBDEPS) $(REL_LIB)/libsecurec.a
@$(OBJDUMP) -d $(TARGET_BIN) > $(ASM)
$(OBJS):%.o:%.c
@$(CC) $(CFLAGS) -c $< -o $(OBJS_DIR)/$(notdir $@)
$(CPP_OBJS):%.o:%.cpp
@$(CPP) $(CPPFLAGS) -c $< -o $(OBJS_DIR)/$(notdir $@)
clean:
@rm -f $(TARGET_BIN) $(BIN) $(MAP) $(ASM)
@rm -f $(OBJS_DIR)/*.o
@rm -f $(OBJS)
@rm -f $(CPP_OBJS)
相关makefile的语法可以看这篇博文:点我,然后再helloword/src下创建一个main.c文件,用于编写我们app应用,我就简单的创建三个线程,然后分别打印:
#include
#include "sample_comm.h"
#include
pthread_t thread1,thread2,thread3;
void *thread1_func(void *arg)
{
while(1)
{
sleep(1);
printf("this thread 1 ,run..\n");
}
}
void *thread2_func(void *arg)
{
while(1)
{
sleep(2);
printf("this thread 2 ,run..\n");
}
}
void *thread3_func(void *arg)
{
while(1)
{
sleep(3);
printf("this thread 3 ,run..\n");
}
}
int app_main(int argc, char **argv )
{
printf("--- test app compiled:%s %s---\n",__DATE__,__TIME__);
pthread_attr_t attr;
struct sched_param param;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr,SCHED_FIFO);
param.sched_priority = 2;
pthread_attr_setschedparam(&attr, ¶m);
pthread_create(&thread1,&attr,thread1_func,NULL);
pthread_create(&thread2,&attr,thread2_func,NULL);
pthread_create(&thread3,&attr,thread3_func,NULL);
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
pthread_join(thread3,NULL);
return 0;
}
直接make,然后会在helloword/out/bin下生成对应的二进制文件,暂时的测试只要烧写uboot以及 helloword/out/bin编译好的bin文件。在app_init.c里面注册的命令是:
void sample_command(void)
{
osCmdReg(CMD_TYPE_EX,"get", 0, (CMD_CBK_FUNC)app_sample);
}
所以在烧录后按照先前搭建环境写好的uboot引导环境变量便能跑我们编译好的sample_main.bin,在终端敲入get :
可见app运行成功了。
四、挂载文件系统
这次需要制作的是yaffs文件系统,在sdk/osdrv/tools/pc/mkyaffs2image下有第三方的工具包,根据readme.txt下载对应的工具源码压缩包,接着进入这个mkyaffs2image目录make,最终在mkyaffs2image/bin生成二进制文件mkyaffs2image100。将其放在sdk/osdrv/pub/tools下,在sdk的制作文件系统脚本里面添加制作的命令:
echo "make hi3516ev200_64k.jffs2 rootfs..."
./osdrv/pub/tools/mkyaffs2image100 ./osdrv/pub/rootfs/rootfs ./osdrv/pub/rootfs/bin/rootfs_hi3516ev200_2k_4bit.yaffs2 1 2
最好在sdk/osdrv/pub/rootfs/rootfs下创建一个test文件将,用于测试,然后在sample/helloword/app_init.c添加挂载yaffs操作。
if (!nand_init())
{
extern int add_mtd_partition( char * type, UINT32 start_addr, UINT32 length, UINT32 partition_num);
add_mtd_partition("nand", 0xB00000, 30*0x100000, 0);
//add_mtd_partition("nand", 0x200000 + 32 * 0x100000, 32 * 0x100000, 1);
extern int mount(const char * source, const char * target,
const char * filesystemtype, unsigned long mountflags,
const void * data);
mount("/dev/nandblk0", "/sharefs", "yaffs", 0, NULL);
//mount("/dev/nandblk0", "/yaffs1", "yaffs", 0, NULL);
}
add_mtd_partition("nand", 0xB00000, 30*0x100000, 0)用于将0xB00000处长度为30*0x100000的文件系统添加到分区,然后通过mount命令挂载到sharefs,为了确保存在sharefs文件夹,实现使用chdir("/sharefs"),要针对dev下的nand产生的节点来设置将那个节点设备挂载在sharefs文件夹。make烧录。得到的结果是:
可见sharefs有我们在虚拟机创建的 sdk/osdrv/pub/rootfs/rootfs/test目录,说明创建以及挂载文件系统是没有问题的。至此启动、app、文件系统已经完成,可以做自己的应用了。
五、友情链接
DOPI官方群:735884031
购买链接:https://item.taobao.com/item.htm?spm=a230r.1.14.1.71ee4becDs9H02&id=618882047300&ns=1&abbucket=0#detail