• 海思3559万能平台搭建:ini定制协议输入①校正系统时间


    前言

      平台的搭建除了海思本身对于音视频的处理,难免需要串口网口之类收发指令并做出处理;每个甲方爸爸对于协议的规定肯定有所差异,以最简单的校对系统时间为例,用网口发送协议,通过ini配置文件加载协议变量的方式实现免编译,只更新ini配置文件就可移植产品功能的作用

    配置文件的使用

      最关键的变量加载办法详见
      海思3559万能平台搭建:配置文件iniparser的引入

    配置文件编写

      新建配置文件如protocol.ini,按照约定格式编写配置文件内容,规定包长21位 包头为0x55,0xAA,识别时间校对的功能码为0xAB

    [attr]
    ini_cmd_length_total = 21;
    
    [content]
    ini_cmd_head1 = 0x55;
    ini_cmd_head2 = 0xAA;
    
    [func_osd]
    ini_cmd_func_osdenable = 0xA5;
    ini_cmd_data_mode_osdoff = 1;
    ini_cmd_data_mode_osdon = 2;
    ;2开1关
    [func_time]
    ini_cmd_func_timecorrect = 0xAB;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    配置文件的加载

      按照约定的用法加载配置文件

    static int ini_cmd_length_total;//协议规定的包长度
    static int ini_cmd_head1;//协议规定的第一个包头B1
    static int ini_cmd_head2;//协议规定的第二个包头B2
    static int ini_cmd_length;//协议包内的的包长B3
    // static int ini_cmd_func;//协议规定的功能码B4
    // static int ini_cmd_data_mode;//协议规定的数据区工作模式B5
    
    static int ini_cmd_func_osdenable = 0;//协议规定的OSD功能码B4
    static int ini_cmd_data_mode_osdon = 0;//协议规定的OSD数据区工作模式B5
    
    static int ini_cmd_func_timecorrect = 0;//协议规定的时间校正B4
    static int ini_cmd_data_mode_timetype = 0;//协议规定的时间校正类型B5
    HI_S32 protocol_ini_init()
    {
        dictionary  *   ini ;
        ini = iniparser_load(PROTOCOLPATH);
        if (ini==NULL) {
            fprintf(stderr, "cannot parse file: %s\n", PROTOCOLPATH);
            return -1 ;
        }
        SAMPLE_PRT("config protocol file load success!\n");
        ini_cmd_length_total           = iniparser_getint(ini,"attr:ini_cmd_length_total",-1);
        ini_cmd_head1                  = iniparser_getint(ini,"content:ini_cmd_head1",-1);
        ini_cmd_head2                  = iniparser_getint(ini,"content:ini_cmd_head2",-1);
        ini_cmd_func_osdenable         = iniparser_getint(ini,"func_osd:ini_cmd_func_osdenable",-1);
        ini_cmd_data_mode_osdon        = iniparser_getint(ini,"func_osd:ini_cmd_data_mode_osdon",-1);
        ini_cmd_func_timecorrect       = iniparser_getint(ini,"func_time:ini_cmd_func_timecorrect",-1);
      
        SAMPLE_PRT("ini_cmd_head1 is 0x%x\n",ini_cmd_head1);
        SAMPLE_PRT("ini_cmd_head2 is 0x%x\n",ini_cmd_head2);
        SAMPLE_PRT("ini_cmd_func_osdenable is 0x%x\n",ini_cmd_func_osdenable);
        SAMPLE_PRT("ini_cmd_data_mode_osdon is %d\n",ini_cmd_data_mode_osdon);
        SAMPLE_PRT("ini_cmd_func_timecorrect is 0x%x\n",ini_cmd_func_timecorrect);
      
        iniparser_freedict(ini);//释放dictionary对象(内存)  
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    协议处理

      以网口为例,收到数据后进入协议解析函数

    /*描述  :网口接收线程
     *参数  :arg 无参数传入
     *返回值:无
     *注意  :使用需打开网口服务器端
     */
    HI_VOID * eth_client_recv_task(HI_VOID *arg)
    {
    	cpu_set_t mask;//cpu核的集合
        cpu_set_t get;//获取在集合中的cpu
    
        int num = sysconf(_SC_NPROCESSORS_CONF);
        printf("frame_check_task:system has %d processor(s)\n", num);
    
        CPU_ZERO(&mask);//置空
        CPU_SET(0, &mask);//设置亲和力值
         
        if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0)//设置线程CPU亲和力
        {
            fprintf(stderr, "set thread affinity failed\n");
        }
    
        if (pthread_getaffinity_np(pthread_self(), sizeof(get), &get) < 0)//获取线程CPU亲和力
        {
            fprintf(stderr, "get thread affinity failed\n");
        }
    	int connect_fd = -1;
        int recv_len;
    	struct sockaddr_in server;
    	socklen_t saddrlen = sizeof(server);
    	// uint8 data_header[] = {0x55, 0xAA};
    	// unsigned char addchk=0;
    	// uint8 data_header[] = {0x55, 0xAA};
    	// printf("\nbeforen DataParser\n ");
    	// DataParser *data_parser = parser_init(data_header, sizeof(data_header), NULL, 0, CMD_LENGTH);
    	// printf("\nDataParser INIT SUCCESS\n ");
    	// char* tmp_cmd=(char*)&g_trk_cmd;
    	memset(&server, 0, sizeof(server));
    	
    	connect_fd = socket(AF_INET, SOCK_STREAM, 0);
    	if (connect_fd < 0)
    	{
    		printf("socket error!\n");
    		// return NULL;
    	}
        printf("\nETH CLIENT RECV TEST\n");
    	server.sin_family = AF_INET;
    	server.sin_port = htons(SERVER_PORT);
    	// server.sin_addr.s_addr = inet_addr(SERVER_IP);
    	server.sin_addr.s_addr = inet_addr(server_ip);
     
    	if (connect(connect_fd, (struct sockaddr *)&server, saddrlen) < 0)
    	{
    		printf("connect failed!\n");
    		// return -1;
    	}
    	// char PLATFORM_IP_SET[64]={0};
    	// char PLATFORM_IP_CMD[]="192.168.0.168";
    	// sprintf(PLATFORM_IP_SET,"ifconfig eth0 %s up",PLATFORM_IP_CMD);
    	// system(PLATFORM_IP_SET);
    	else
    	{
    		char recvbuf[1024]={0};
    		while (1)
    		{
    			recv_len = read(connect_fd, recvbuf, sizeof(recvbuf));
    			if(recv_len)
    			{
    				// printf("\nEth:recv origin data: ");
    				// recvbuf[len] = '\0';  
    				for (int i = 0;i < recv_len ;i++)
    				{
    					printf("%02x  ",recvbuf[i]);  
    				}
    				printf("\n"); 
    				protocol_parser(recvbuf,recv_len);
    				
    			}
    			
    		}
    		close(connect_fd);
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

      解析方法也很简单,规定一下协议
    在这里插入图片描述
      时间类型:uint8,当前版本固定为0x00;
      年:uint8,年份-2000;
      月:uint8,月份,取值范围1-12;
      日:uint8,日期,取值范围1-31;
      毫秒:uint32,当前时间的毫秒计数。

    HI_S32 protocol_parser(char* recvbuf,int recv_len)
    {
        HI_S32 i;
        // HI_U8 data_header[] = {0x55, 0xAA};
        HI_U8 data_header[] = {ini_cmd_head1, ini_cmd_head2};
    	HI_U8 addchk=0;
    	DataParser *data_parser = parser_init(data_header, sizeof(data_header), NULL, 0, ini_cmd_length_total);
    	char* tmp_cmd=(char*)&g_trk_cmd;
        /* 解析协议内容 */
        for (i = 0;i < recv_len ;i++)
        {
            // printf("%02x  ",recvbuf[i]);  
            if(parser_put_data(data_parser, recvbuf[i]) == RESULT_TRUE)
            {
                /* 赋值给临时结构体tmp_cmd */
                tmp_cmd=(char*)&g_trk_cmd;
                addchk = 0;
                for(int jj=0;jj<sizeof(g_trk_cmd)-sizeof(data_header);jj++)
                {
                    tmp_cmd[jj+2]=parser_get_data(data_parser, jj);
                    // printf("%x ",tmp_cmd[jj+2]);
                }
                // printf("\n");
                 /* 校验尾 */
                for(int kk = 2;kk < sizeof(g_trk_cmd)-1;kk++)
                {
                    // addchk += parser_get_data(data_parser, kk);
                    addchk+=tmp_cmd[kk];
                    // printf("%x ",tmp_cmd[kk]);
                }
                // printf("\n");
               
                g_trk_cmd.addchk = parser_get_data(data_parser,(ini_cmd_length_total-1-2));//第19个数,从0开始计18,故-1,又因为去头在-2
                // printf("g_trk_cmd.addchk is %x\n",g_trk_cmd.addchk);
                if(addchk != g_trk_cmd.addchk )
                {
                    printf("warning:please check format :tail\n");
                    printf("addchk is %x\n",addchk);
                    memset_s(((uint8_t*)&g_trk_cmd)+2,
                               sizeof(g_trk_cmd)-sizeof(data_header),
                               0,
                               sizeof(g_trk_cmd)-sizeof(data_header));
                    continue;
                }
                else
                {
                    /* 校验成功则往结构体赋值 */
                    g_trk_cmd.length  = tmp_cmd[2];
                    // printf(" tmp_cmd[2]is %x\n",tmp_cmd[2]);
                    g_trk_cmd.CmdType = tmp_cmd[3];
                    // printf(" tmp_cmd[3]is %x\n",tmp_cmd[3]);
                    for (int ii = 0; ii < (ini_cmd_length_total-1-2-2) ;ii++)//去头-2去尾-1去功能-1从0开始计数-1
                    {
                        g_trk_cmd.Para[ii] = tmp_cmd[ii+4];;
                    }
                }
            }
        }
      
        if (g_trk_cmd.CmdType == ini_cmd_func_timecorrect)
        {
            printf("time correct\n");
            unsigned char tmp_year  = g_trk_cmd.Para[1];
            unsigned char tmp_month = g_trk_cmd.Para[2];
            unsigned char tmp_day   = g_trk_cmd.Para[3];
            unsigned int  tmp_ms    = (g_trk_cmd.Para[4]<<24)|(g_trk_cmd.Para[5]<<16)|(g_trk_cmd.Para[6]<<8)|(g_trk_cmd.Para[7]);
            SetSystemTime(tmp_year,tmp_month,tmp_day,tmp_ms);
        }
    
        return 0;
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72

      没有直接传入时分秒,直接传入ms值也可以计算时间

    /* 
     *描述  :协议规定的时间校准功能
     *参数  :uint32_t tyear  要设的年
     *        uint32_t tmonth 要设的月
     *        uint32_t tday   要设的日
     *        uint32_t tmsecs 要设的毫秒,用于转成时分秒
     *返回值:成功返回0
     *注意  :无
     */
    int SetSystemTime(uint32_t tyear,uint32_t tmonth,uint32_t tday,uint32_t tmsecs)
    {
        struct tm t_tm;
        struct timeval tv;
        time_t timep;
        uint32_t thour=0;
        uint32_t tminutes=0;
        uint32_t tseconds=0;
    
        thour = tmsecs / (1000 * 60 * 60);
        tminutes = (tmsecs % (1000 * 60 * 60)) / (1000 * 60);
        tseconds = (tmsecs % (1000 * 60)) / 1000;
    
        t_tm.tm_sec  = tseconds;
        t_tm.tm_min  = tminutes;
        t_tm.tm_hour = thour;
        t_tm.tm_mday = tday;
        t_tm.tm_mon  = tmonth - 1;
        t_tm.tm_year = tyear +2000- 1900;
    
        timep=mktime(&t_tm);
        stime(&timep);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
  • 相关阅读:
    【数据结构初阶】单链表(附全部码源)
    华为MateBook X Pro笔记本录屏办法
    59 分割等和子集
    npm run serve启动报错npm ERR! Missing script: “serve“
    坚叔:让科幻片的概念变成产品丨编程挑战赛 x 嘉宾分享
    Python「面向对象基本语法2」引用概念、方法中的self参数、代码示例
    NFT的价值 怎么玩NFT NFT定制开发
    R语言dplyr包group_by函数和summarise_at函数计算dataframe计算不同分组的计数个数和均值、使用%>%符号将多个函数串起来
    CVPR2022 | 简单高效的语义分割体系结构
    大二Web课程设计:服装网页设计题材——HTML+CSS汉服文化带背景音乐素材带视频(12页)
  • 原文地址:https://blog.csdn.net/qq_42330920/article/details/127688988