我是靠谱客的博主 迷你眼神,最近开发中收集的这篇文章主要介绍rv1108 sdk app层上电初始化流程,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

当系统上电启动后,会执行应用层的逻辑,应用层的代码入口是

appvideouicvrcamera_ui.c :MiniGUIMain

MiniGUIMain
    api_poweron_init(ui_msg_manager_cb);

应用层的初始化,主要是在函数api_poweron_init(ui_msg_manager_cb);中,实现的功能主要是系统参数的初始化,注册回调函数,以及wifi的的初始化。

下面分析具体过程:

api_poweron_init(ui_msg_manager_cb);
    android_usb_init();//开启adb功能
    parameter_init();//初始化flash参数
    video_record_init_lock(); //must before uevent init ,the function is to get camera info,and include the number of the chip camera 。directly use camerahal member function
    thermal_init();//this function is used for realize the related fun of temperature
    usb_reg_event_callback(usb_event_callback);//this function implements a callback function for registering usb-related events。
    uevent_monitor_run();//Event monitoring thread,will involve some socket netlink
    REC_RegEventCallback(record_event_callback);//register the callback function as in file video.cpp rec_event_call
    set_video_init_complete_cb(notify_videos_inited);//register the callback function as in video.cpp video_rec_state 
    sd_reg_event_callback(sd_event_callback);//register the callback function as file usb_sd_ctrl.c sdcard_evnet_call
    USER_RegEventCallback(user_event_callback);//the file user.cpp  user_event_call 
    VIDEOPLAY_RegEventCallback(videoplay_event_callback);//videoplay.c videoplay_event_call
    fs_msg_file_reg_callback(fsfile_event_callbak);//fs_msg.c fs_msg_file_call
    wifi_management_start();//wifi init 
    storage_setting_reg_event_callback(storage_setting_callback);public_interface.c storage_filesize_event_call
    storage_setting_event_callback(0, NULL, NULL);

video_record_init_lock();

video_record_init_lock();
    memset(&g_test_cam_infos, 0, sizeof(g_test_cam_infos));
    CamHwItf::getCameraInfos(&g_test_cam_infos);//CamHwItf.cpp the class of CamHwItf member function getCameraInfo
        

这里面调用的是libcamerahal库代码中的externallibcamerahalCameraHal10_ReleaseCameraHalHALsourceCamHwItf.cpp函数:CamHwItf::getCameraInfos(struct rk_cams_dev_info* cam_infos)。

这个函数实现方式是论寻dev/video%d,目录下的video设备节点,并依次打开这些设备节点,打开成功后通过ioctl系统调用的VIDIOC_QUERYCAP命令获取v4l2_capability数据内容,并通过strstr查看capability.driver中的设备类型:rkisp,cif,UVC。然后在各个设备类型下面使用ioctl的VIDIOC_ENUMINPUT获取v4l2_input的数据内容。

snprintf(video_dev_path, sizeof(video_dev_path), "/dev/video%d", i);
fd = open(video_dev_path, O_RDONLY);
ioctl(fd, VIDIOC_QUERYCAP, &capability)
if (strstr((char*)(capability.driver), "rkisp"))
ioctl(fd, VIDIOC_ENUMINPUT, &input)
else if (strstr((char*)(capability.driver), "cif"))
ioctl(fd, VIDIOC_ENUMINPUT, &input)
else if (strstr((char*)(capability.driver), "UVC"))
ioctl(fd, VIDIOC_ENUMINPUT, &input)

只有通过上上面的调用CamHwItf::getCameraInfos(struct rk_cams_dev_info* cam_infos),以及之后调用的initrec函数的api_video_init接口初始化摄像头在飞机的的空中端口接受到拍照指令后执行的 video_record_takephoto(unsigned int num)中video_cur = getfastvideo();才会有相应的video设备节点返回。

其中api_video_init进有一次调用就是在初始化的时候,并且此时是设置为VIDEO_MODE_REC模式的,如果在初始化的时候这个地方被设置成VIDEO_MODE_PHOTO模式,拍摄的图片就会偏暗。如下图所示:

/home/highgreat-xyw2018/Documents/share-2018xyw/aa/20160121_090346_picture124A00.jpg

获取支持的camera的类型,cif isp usb,支持的个数


thermal_init();

soc的温度检测功能的初始化


usb_reg_event_callback(usb_event_callback);

这里注册的回调函数是执行在链表msg_list_manager.c中的g_listHead上的回调函数。


uevent_monitor_run();

建立监控线程,主要监控内核发送到应用层的消息,设计到netlink的使用。


REC_RegEventCallback(record_event_callback);

void record_event_callback(int cmd, void *msg0, void *msg1)
{
    switch (cmd) {
    case CMD_UPDATETIME:
        api_send_msg(MSG_VIDEO_UPDATETIME, TYPE_BROADCAST, msg0, NULL);
        break;
        break;
    case CMD_PHOTOEND:
        api_send_msg(MSG_VIDEO_PHOTO_END, TYPE_BROADCAST, msg0, msg1);
        break;
    }
}

api_send_msg:执行在链表msg_list_manager.c中的g_listHead上的回调函数。


set_video_init_complete_cb(notify_videos_inited);

static void notify_videos_inited(int is_record_mode)
{
    int mode = is_record_mode ? MODE_RECORDING : MODE_PHOTO;
    assert(mode == cur_mode);
    api_send_msg(MSG_MODE_CHANGE_NOTIFY, TYPE_WIFI, (void *)pre_mode, (void *)mode);
}

sd_reg_event_callback(sd_event_callback);

sd卡改变的时候,需要做的一些sd卡的挂载,初始化等操作。


USER_RegEventCallback(user_event_callback);

user_event_callback回调函数的作用处理用户事件的回调。


VIDEOPLAY_RegEventCallback(videoplay_event_callback);

videoplay_event_callback回调函数的视频播放的推出和更新。


fs_msg_file_reg_callback(fsfile_event_callbak);

fsfile_event_callbak:处理文件系统的事件


storage_setting_reg_event_callback(storage_setting_callback);

storage_setting_callback:设置文件的大小和路径。


wifi_management_start:

代码流程:

wifi_management_start
    Set_CPUSerial_forSSID()//obtain ssid from cpu
    Set_system_Version_param();//set version param
    reg_msg_manager_cb();//register the function of callback wifi_msg_manager_cb in the file wifi_setting_interface.c   -------msg_list_manager.c  g_listHead
    wifi_driver_reboot_thread();//
    parameter_getwifiinfo(SSID, PASSWD);//get wifi ssid and passwd
    socket_thread_create();

这里比较重要的是socket_thread_create(void),主要是建立了几个线程。

下面主要分析此函数:

建立的线程:udp_server_thread,hg_cgi_request_thread,hg_cgi_response_thread,daemon_thread。

下面依次分析:

udp_server_thread:创建端口号为8888的udp服务端用于接收手机app发送的消息,并且解析消息中的数据数据帧,根据消息的数据帧的id调用对应的命令执行函数。

 1.建立udp服务器端口号8888---创建socket udp_server_fd,bind udp sockaddr

2.创建线程UdpSend_Thread---调用hg_api_send_udp_response向app发送心跳包(1s的频率)和温度信息(10s的频率)

hg_api_send_udp_response
    SendResultMessage(messageID, messageFlag, messageLength);//the function organizes the information to be sent
    sendto(udp_server_fd, GetMessageBuff(), 31*sizeof(char), 0, (struct sockaddr *)&server_add, sizeof(server_add));//send info to app
    memset(GetMessageBuff(), 0, sizeof(char)*1024);

3.recvMsg(udp_server_fd, data, recbytes);----从接收到的数据消息中解析出具体的完整的信息帧以0x7e 0x7e开头的,并解析出信息帧中的命令参数等信息。

recvMsg(int nfp, char *data, int recbytes)
    hg_parameter_resolve(buffer);
    cmd_resolve(nfp, buffer);

hg_parameter_resolve(buffer);

解析出接受到的消息帧buffer中的messageBodyID,根据messageBodyID的不同作出不同的判断,如:录像的打开关闭,实时视频的开始结束,拍照模式的设置,,曝光,白平衡以及adb msc模式的切换的命令等等。完成后再将相对应的命令的字符串copy到buffer中。

cmd_resolve(nfp, buffer);

将上面的函数hg_parameter_resolve(buffer);解析出来的命令字符串

cmd_resolve(nfp, buffer);

具体代码如下所示,主要是根据参数cmdstr命令字符串和命令执行函数的对照表cmd_tab作出对比,并调用相应的命令函数执行。

static int cmd_resolve(int fd, char *cmdstr)
{
    size_t i = 0;

    for (i = 0; i < sizeof(cmd_tab) / sizeof(cmd_tab[1]); i++) {
        char *result = strstr(cmdstr, CMD_PREFIX);
        if (result != NULL) {
            size_t cmdlen = strlen(cmd_tab[i].cmd);
            if (strncmp(result, cmd_tab[i].cmd, cmdlen) == 0) {
                if (cmd_tab[i].func != NULL)
                    cmd_tab[i].func(fd, result);
                cmdstr = result + cmdlen;
                if (*cmdstr == '' || strstr(cmdstr, CMD_PREFIX) == NULL)
                    return 0;
                printf("handle continuous cmd: %sn", cmdstr);
                i = 0;
            }
        }
	}
    return -1;
}

 当地面端手机app wifi链接上飞机后,app就会向飞机发送消息,会执行tcp_func_start_rtsp_live回调函数,执行rtsp实时视频的传输。

hg_cgi_request_thread hg_cgi_response_thread

 以上两个线程通过管道文件/tmp/media_response_fifo相互交换数据。涉及到一些http的使用

daemon_thread

这个线程中主要是一直轮讯是否有8888端口的udp链接存在,也就是 udp_server_thread  创建的socket udp的链接是否断开,如果断开则删除udp_server_thread线程,并继续从新创建udp_server_thread线程函数。具体代码如下:

static void *daemon_thread(void *arg)
{

    pthread_detach(pthread_self());

	while(true){
		if (false == is_video_port_used())
		{
			printf("%s %s %d bebugn", __FILE__, __FUNCTION__, __LINE__);
			pthread_cancel(udp_server_tid);	//delete the thread udp_server_thread
			pthread_join(udp_server_tid,NULL);//wait thread udp_server_thread exit

	 		if (pthread_create(&udp_server_tid, NULL, udp_server_thread, NULL) != 0)//从新创建线程udp_server_thread
	        	printf("Createthread error!n");
			sleep(2);
	    }
	}
    return NULL;
}

其中判断相应的udp是否处于链接状态的代码如下:通过执行netstat命令,可以查看当前的网络链接状态信息然后,将输出的信息重定位到一个文件中,然后调用strstr函数,查看是否有相应的端口号,就知道是否还处于链接状态。

system("busybox rm /tmp/netstat8888.txt");
system("busybox netstat -an |grep -i 8888 > /tmp/netstat8888.txt");

busybox netstat -an
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 0.0.0.0:554             0.0.0.0:*               LISTEN      
tcp        0      0 0.0.0.0:5037            0.0.0.0:*               LISTEN      
tcp        0      0 0.0.0.0:12346           0.0.0.0:*               LISTEN      
udp        0      0 0.0.0.0:9000            0.0.0.0:*                           
udp        0      0 0.0.0.0:67              0.0.0.0:*                           
udp        0      0 0.0.0.0:8888            0.0.0.0:*                           
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags       Type       State         I-Node Path
unix  2      [ ACC ]     STREAM     LISTENING       3518 @jdwp-control
unix  2      [ ]         DGRAM                      3578 /var/run/hostapd/wlan0
unix  3      [ ]         STREAM     CONNECTED       3519 
unix  3      [ ]         STREAM     CONNECTED       3523 
unix  2      [ ]         DGRAM                      3456 
unix  3      [ ]         STREAM     CONNECTED       3516 
unix  3      [ ]         STREAM     CONNECTED       3520 
unix  3      [ ]         STREAM     CONNECTED       3515 
unix  3      [ ]         STREAM     CONNECTED       3524 

 

最后

以上就是迷你眼神为你收集整理的rv1108 sdk app层上电初始化流程的全部内容,希望文章能够帮你解决rv1108 sdk app层上电初始化流程所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(78)

评论列表共有 0 条评论

立即
投稿
返回
顶部