/****************************************************************************** 版权所有: 文件名称: equ.c 文件版本: 01.01 创建作者: sunxi 创建日期: 2013-03-25 功能说明: 装置信息管理维护 其它说明: 修改记录: */ /*------------------------------- 头文件 -------------------------------------- */ #include "head.h" /*------------------------------- 宏定义 -------------------------------------- */ /*------------------------------ 类型结构 ------------------------------------- */ /*------------------------------ 全局变量 ------------------------------------- */ // 装置通道配置文件 struct equ_config g_equ_config_null; // 全0结构,防止访问异常 struct equ_config *g_equ_config = &g_equ_config_null; // 装置配置文件头 struct equ_config_di *g_equ_config_di; // 开入配置数组 struct equ_config_do *g_equ_config_do; // 开出配置数组 struct equ_config_ac *g_equ_config_ac; // 模拟量配置数组 // 采样通道取反,以ADC为索引 u8 g_equ_adc_inv[CFG_ADC_CHANNEL]; int g_equ_adc_inv_num; // ADC通道是否配置 u8 g_equ_adc_config[CFG_ADC_CHANNEL]; // 板卡资源文件 struct board_res_head g_board_res_head_null; // 全0结构,防止访问异常 struct board_res_head *g_board_res_head = &g_board_res_head_null; // 板卡资源文件头 struct board_res *g_board_res; // 板卡资源数组 #if defined(CAN_SLAVE_BOARD) struct board_info g_board_info[EQU_SLOT_NUM_MAX+CAN_BOARD_NUM]; // 板卡实时信息 #else struct board_info g_board_info[EQU_SLOT_NUM_MAX]; // 板卡实时信息 #endif //已配置的开关数 u32 g_sw_num; int g_slot_addr; // 插槽地址 int g_hw_version; // 硬件版本 u16 g_crc_brd_res; u16 g_crc_equ_cfg; // LED配置,按插槽配置 struct led_config g_led_slot[EQU_SLOT_NUM_MAX]; // equ文件比较用 struct file_contrast g_equ_contrast; int g_sw_ac_num[SWITCH_NUM_MAX+1]; int g_pub_ac_num; /*------------------------------ 函数声明 ------------------------------------- */ int _equ_get_di_num(u32 slot); int _equ_get_do_num(u32 slot); int _equ_get_ac_num(u32 slot); /*------------------------------ 外部函数 ------------------------------------- 外部函数供其它实体文件引用,必须仔细检查传入参数的合法性. */ char * equ_info_brd_type(int type) { int i; for(i=0; ibr_num; i++) { if(g_board_res[i].type == type) { return g_board_res[i].name; } } return 0; } /****************************************************************************** 函数名称: equ_init_file_brd_res 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-08 函数说明: 从板卡资源文件装载板卡资源。 参数说明: 返回值: 0: 成功 其它: 失败 修改记录: */ int equ_init_file_brd_res(void) { u32 len; u8 *buf; struct board_res_head *brh; struct file * pfile; loff_t pos; // 打开文件 pfile = rt_file_open("/app/data/brd_res.bin",O_RDONLY ,0); if(IS_ERR(pfile)) { return -1; } // 得到文件长度 len = rt_file_getfile_size(pfile); if(len <= 0) { rt_file_close(pfile,0); return -11; } // 分配内存 buf = rt_malloc(len); if((buf) == NULL) { rt_file_close(pfile,0); return -2; } // 读出内容 pos = 0; if(rt_file_read(pfile,buf,len,&pos) != len) { rt_file_close(pfile,0); rt_free(buf); return -3; } // 关闭文件 rt_file_close(pfile,0); // 检查CRC g_crc_brd_res = CrcStr(buf,len-2); if(g_crc_brd_res != *(u16*)(buf+len-2)) { rt_free(buf); return -4; } // 检查文件签名 brh = (struct board_res_head*)buf; if(brh->cfh.signature != SIG_EQU_RES_FILE) { rt_free(buf); return -5; } // 检查文件长度 if(len < sizeof(*brh) + brh->br_num*sizeof(struct board_res)+ 2) { rt_free(buf); return -6; } // 装置板卡资源 g_board_res_head = (struct board_res_head *)buf; g_board_res = (struct board_res *)(buf + brh->br_addr); return 0; } /****************************************************************************** 函数名称: equ_init_file_config 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-08 函数说明: 从装置配置文件装载装置配置。 参数说明: 返回值: 0: 成功 其它: 失败 修改记录: */ int equ_init_file_config(void) { u32 len,i; u8 *buf; struct file * pfile; loff_t pos; struct equ_config *ec; // 打开文件 pfile = rt_file_open("/app/data/equ_cfg.bin",O_RDONLY ,0); if(IS_ERR(pfile)) { return -1; } // 得到文件长度 len = rt_file_getfile_size(pfile); if(len < sizeof(struct equ_config) + 2) { rt_file_close(pfile,0); return -11; } // 分配内存 buf = rt_malloc(len); if((buf) == NULL) { rt_file_close(pfile,0); return -2; } // 读出内容 pos = 0; if(rt_file_read(pfile,buf,len,&pos) != len) { rt_file_close(pfile,0); rt_free(buf); return -3; } // 关闭文件 rt_file_close(pfile,0); // 检查CRC g_crc_equ_cfg = CrcStr(buf,len-2); if(g_crc_equ_cfg != *(u16*)(buf+len-2)) { rt_free(buf); return -4; } // 检查文件签名 ec = (struct equ_config *)buf; if(ec->cfh.signature != SIG_EQU_CFG_FILE) { rt_free(buf); return -5; } // 文件比较内容赋值 g_equ_contrast.version = ec->cfh.version; g_equ_contrast.signature = ec->cfh.signature; g_equ_contrast.length = len; g_equ_contrast.crc = g_crc_equ_cfg; //比对资源表文件 if ((ec->rsc_version != rsc_contrast.version) || (ec->rsc_signature != rsc_contrast.signature) || (ec->rsc_length != rsc_contrast.length) || (ec->rsc_crc != rsc_contrast.crc)) { rt_printf("equ_version = 0x%x, rsc_version = 0x%x\r\n",ec->rsc_version, rsc_contrast.version); rt_printf("equ_signature = 0x%x, rsc_signature = 0x%x\r\n",ec->rsc_signature, rsc_contrast.signature); rt_printf("equ_length = 0x%x, rsc_length = 0x%x\r\n",ec->rsc_length, rsc_contrast.length); rt_printf("equ_crc = 0x%x, rsc_crc = 0x%x\r\n",ec->rsc_crc, rsc_contrast.crc); rt_free(buf); return -6; } // 装载配置 g_equ_config = ec; g_equ_config_di = (struct equ_config_di *)(buf + g_equ_config->di_addr); g_equ_config_do = (struct equ_config_do *)(buf + g_equ_config->do_addr); g_equ_config_ac = (struct equ_config_ac *)(buf + g_equ_config->ac_addr); // 得到开关数量 g_sw_num = 0; for(i=0;idi_num;i++) { if(g_equ_config_di[i].owner > g_sw_num && g_equ_config_di[i].index ) { g_sw_num = g_equ_config_di[i].owner; } } for(i=0;ido_num;i++) { if(g_equ_config_do[i].owner > g_sw_num && g_equ_config_do[i].index ) { g_sw_num = g_equ_config_do[i].owner; } } for(i=0;iac_num;i++) { if( g_equ_config_ac[i].type == 0) { continue; } if(g_equ_config_ac[i].owner > g_sw_num && g_equ_config_ac[i].index ) { g_sw_num = g_equ_config_ac[i].owner; } if( g_equ_config_ac[i].owner == 0) { g_pub_ac_num++; } else { g_sw_ac_num[ g_equ_config_ac[i].owner-1]++; } g_sw_ac_num[SWITCH_NUM_MAX]++;//总配置数 } rt_printf("线路开关数量:程序=%d,配置=%d.\r\n",SWITCH_NUM_MAX,g_sw_num); if(g_sw_num > SWITCH_NUM_MAX) { return -7; } return 0; } /****************************************************************************** 函数名称: equ_led_init 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2015-04-16 函数说明: 开出类型LED初始化,找到对应的灯配置索引的GPIO 参数说明: 无 返回值: 成功返回0. 修改记录: */ int equ_led_init(void) { int i,j; // 默认没有配置任何灯 for(i=0;i g_led_slot[slot].num) { g_led_slot[slot].num = index; } } } // 初始化开关灯 for(sw=0; sw g_led_slot[slot].num) { g_led_slot[slot].num = index; } } } } #endif return 0; } int equ_config_check(void) { int i; bool b_err=false; const int bank_cfg[EQU_SLOT_NUM_MAX]= { BOARD_TYPE_FUXI_DI, BOARD_TYPE_FUXI_DO, BOARD_TYPE_FUXI_AC, -1, -1, -1, -1, -1, -1, -1, -1, }; for(i=0;iequ_slot_num; i++) { if(equ_info_brd_type(g_equ_config->brd_type[i]) == 0) { equ_led_init(); dp_err_n_c_rt("板卡类型不存在(type=%d)!\r\n",g_equ_config->brd_type[i]); return -3; } g_board_info[i].type = g_equ_config->brd_type[i]; g_board_info[i].di_num = _equ_get_di_num(i); g_board_info[i].do_num = _equ_get_do_num(i); g_board_info[i].ac_num = _equ_get_ac_num(i); if((g_board_info[i].type < BOARD_TYPE_GROUP_RS) && (g_board_info[i].di_num || g_board_info[i].do_num || g_board_info[i].ac_num)) { // 板卡需要周期性的检查是否正常工作。 g_board_info[i].is_check = 1; } g_board_info[i].us0 = ustimer_get_origin(); g_board_info[i].is_ok = 1; // 主板信息 if(g_board_info[i].type == BOARD_TYPE_MAIN || g_board_info[i].type == BOARD_TYPE_FTUMAIN || g_board_info[i].type == BOARD_TYPE_FBDTU_MAIN|| g_board_info[i].type == BOARD_TYPE_FBDTU_MAIN1) { g_board_info[i].crc = m_CodeCrc; g_board_info[i].version = VER_NUM; } } // 模拟通道配置 memset(g_equ_adc_inv,0,sizeof(g_equ_adc_inv)); for(i=0; iac_num; i++) { u32 adc; adc = equ_get_ac_channel(g_equ_config_ac[i].slot,g_equ_config_ac[i].index); if (adc= g_equ_config->equ_slot_num) { return 0; } type = g_equ_config->brd_type[slot]; for(i=0; ibr_num; i++) { if(g_board_res[i].type == type) { return g_board_res[i].di_num; } } return 0; } int equ_get_di_num(u32 slot) { return (slot >=EQU_SLOT_NUM_MAX) ? 0 : g_board_info[slot].di_num; } /****************************************************************************** 函数名称: equ_get_do_num 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-08 函数说明: 得到插槽中子板的开出资源个数 参数说明: slot 插槽索引号 返回值: 开出资源个数 修改记录: */ int _equ_get_do_num(u32 slot) { int i; u8 type; if(slot >= g_equ_config->equ_slot_num) { return 0; } type = g_equ_config->brd_type[slot]; for(i=0; ibr_num; i++) { if(g_board_res[i].type == type) { return g_board_res[i].do_num; } } return 0; } int equ_get_do_num(u32 slot) { return (slot >=EQU_SLOT_NUM_MAX) ? 0 : g_board_info[slot].do_num; } /****************************************************************************** 函数名称: equ_get_ac_num 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-08 函数说明: 得到插槽中子板的模拟量资源个数 参数说明: slot 插槽索引号 返回值: 模拟量资源个数 修改记录: */ int _equ_get_ac_num(u32 slot) { int i; u8 type; if(slot >= g_equ_config->equ_slot_num) { return 0; } type = g_equ_config->brd_type[slot]; for(i=0; ibr_num; i++) { if(g_board_res[i].type == type) { return g_board_res[i].ac_num; } } return 0; } int equ_get_ac_num(u32 slot) { return (slot >=EQU_SLOT_NUM_MAX) ? 0 : g_board_info[slot].ac_num; } int equ_get_ac_scale(u8 slot,u8 no) { int i; for(i=0; i< g_equ_config->ac_num; i++) { if((g_equ_config_ac[i].slot==slot)&&(g_equ_config_ac[i].index==no)) { return g_equ_config_ac[i].scale; } } return -1; } /****************************************************************************** 函数名称: equ_get_slot_by_type 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-08 函数说明: 通过子板的类型查找插槽。 参数说明: type 子板类型。 返回值: 插槽号 修改记录: */ u32 equ_get_slot_by_type(u8 type) { u32 i; struct board_info *bi; bi = g_board_info; for(i=0; iequ_slot_num; i++) { if(equ_slot_check(i) != 0) { continue; } if(g_board_info[i].type == type) { return i; } } return 0; } /****************************************************************************** 函数名称: equ_slot_check 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-08 函数说明: 检查对应插槽中的子板是否正常。 参数说明: slot 插槽索引号 返回值: 插槽号 0: 成功 其它: 失败 修改记录: */ int equ_slot_check(u32 slot) { if(slot >= g_equ_config->equ_slot_num) { return -1; } if(g_board_info[slot].is_ok == 0) { return -2; } return 0; } /****************************************************************************** 函数名称: equ_di_name 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-08 函数说明: 从板卡号和硬件编号得到开入点的名称 参数说明: slot 插槽索引号 index 子板上开入索引号 返回值: 开入点的名称 修改记录: */ char * equ_di_name(u8 slot,u8 no) { int i; for(i=0; i< g_equ_config->di_num; i++) { if((g_equ_config_di[i].slot==slot)&&(g_equ_config_di[i].index==no)) { return shield_str(&g_equ_config_di[i]); } } return 0; } u8 equ_di_type(u8 slot,u8 no) { int i; for(i=0; i< g_equ_config->di_num; i++) { if((g_equ_config_di[i].slot==slot)&&(g_equ_config_di[i].index==no)&&(g_equ_config_di[i].owner>0)) //只有开关遥信才返回真正类型 { return g_equ_config_di[i].type; } } return 0; } u8 equ_pub_di_type(u8 slot,u8 no) { int i; for(i=0; i< g_equ_config->di_num; i++) { if((g_equ_config_di[i].slot==slot)&&(g_equ_config_di[i].index==no)&&(g_equ_config_di[i].owner==0)) //公共类型 { return g_equ_config_di[i].type; } } return 0; } /*------------------------------ 内部函数 ------------------------------------- 内部函数以下划线‘_’开头,不需要检查参数的合法性. */ /*------------------------------ 测试函数 ------------------------------------- 一个实体文件必须带一个本模块的测试函数来进行单元测试,如果的确不方便在本模块中 进行单元测试,必须在此注明实际的测试位置(例如在哪个实体文件中使用哪个测试函数). */ int equ_info_printf(void) { int i; struct rtc_time_t rtc; struct timespec ts; struct board_res *br; struct board_info *bi; rt_printf("板卡资源信息:%s(可配置开关:%d,实际配置开关:%d):slot=%d\r\n",g_equ_config->equ_name,g_equ_config->equ_sw_num,g_sw_num,g_equ_config->equ_slot_num); br = g_board_res; rt_printf("name\t\ttype\tdi_num\tdo_num\tac_num\r\n"); for(i=0; ibr_num; i++) { rt_printf("%-9s\t%03d\t%02d\t%02d\t%02d\r\n",br[i].name,br[i].type,br[i].di_num,br[i].do_num,br[i].ac_num); } bi = g_board_info; rt_printf("\r\nslot\ttype\tcan\tstatus\terrcode\tcrc\tversion\t\ttime\r\n"); for(i=0; iequ_slot_num; i++) { rt_printf("%02d %s[%02d]\t%02d\t%02d\t%02d\t%04x\t%08x\t",i,equ_info_brd_type(bi[i].type),bi[i].type,bi[i].can_bus,bi[i].status,bi[i].errcode,bi[i].crc,bi[i].version); timespec_to_rtc(bi[i].update_time,&rtc,0); rt_printf("%04d-%02d-%02d %02d:%02d:%02d:%09d\r\n", rtc.year + 2000, rtc.month, rtc.day, rtc.hour, rtc.min, rtc.ms/1000,bi[i].update_time.tv_nsec ); } clk_time_get(&ts); timespec_to_rtc(ts,&rtc,0); rt_printf("now:%04d-%02d-%02d %02d:%02d:%02d:%09d\r\n", rtc.year + 2000, rtc.month, rtc.day, rtc.hour, rtc.min, rtc.ms/1000,ts.tv_nsec ); return 0; } int equ_info_printf_di(void) { int i; struct equ_config_di *cdi; cdi = g_equ_config_di; rt_printf("\r\nslot\tindex\ttype\towner\tfilter\tis_inv\tname\r\n"); for(i=0; idi_num; i++) { rt_printf("%02d\t%02d\t%02d\t%d\t%d\t%d\t%s\r\n", cdi[i].slot,cdi[i].index+1,cdi[i].type,cdi[i].owner,cdi[i].filter_time,cdi[i].is_Inverse,cdi[i].name); } return 0; } int equ_info_printf_do(void) { int i; struct equ_config_do *cdo; cdo = g_equ_config_do; rt_printf("\r\nslot\tindex\ttype\towner\tpulse_t\tname\r\n"); for(i=0; ido_num; i++) { rt_printf("%02d\t%02d\t%02d\t%d\t%d\t%s\r\n", cdo[i].slot,cdo[i].index+1,cdo[i].type,cdo[i].owner, cdo[i].time_pulse,cdo[i].name); } return 0; } int equ_info_printf_ac(void) { int i; struct equ_config_ac *cac; cac = g_equ_config_ac; rt_printf("\r\nslot\tindex\ttype\towner\tct_inv\tscale\tname\r\n"); for(i=0; iac_num; i++) { rt_printf("%02d\t%02d\t%02d\t%d\t%d\t%d\t%s\r\n", cac[i].slot,cac[i].index+1,cac[i].type,cac[i].owner, cac[i].is_ct_inverse,cac[i].scale,cac[i].name); } return 0; } /*------------------------------ 文件结束 ------------------------------------- */