/***************************************************************************** * file lib/process/pd_dau.c * author YuLiang * version 1.0.0 * date 03-Feb-2023 * brief This file provides all the dau related operation functions. ****************************************************************************** * Attention * *

© COPYRIGHT(c) 2021 LandPower

* * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of LandPower nor the names of its contributors may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ******************************************************************************/ /* Includes ------------------------------------------------------------------*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef CFG_DEV_TYPE_LAND_PD /* 标准C库头文件. */ #include #include #include #include #include #include #include #include #include #include "vty.h" #include "cmd.h" #include "fifo.h" #include "mtimer.h" #include "hwgpio.h" #include "process.h" #include "pd_main.h" #include "pd_csg.h" #include "pd_dau.h" #include "pd_storage.h" #include "pd_cpld.h" #include "pd_dbg.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ //#define DAU_IPC_FIFO #define DAU_ERR_MAX 5 // DAU 连续发送失败次数. #define DAU_SEND_ERR_MAX 3 // DAU 发送重发次数. #define DAU_SEND_TIMEOUT 100000000 // DAU 发送报文超时时间 100ms = 100000000ns. #define DAU_SEND_TIMEOUT_U 3 // DAU 发送报文超时时间 3s. #define DAU_ADC_RATE 50 // DAU ADC 采样速率 50MHz. #define DAU_RECV_FIFO "DAU_RECV_FIFO" /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ dau_ctrl_t dau_ctrl; dau_t *dau[PD_DAU_SUM]; /* DAU 端口类型分类. */ static const char *dau_port_type_str[PD_PORT_TYPE_COUNT] = { "", "uhf", "ae", "tev", "hf" }; /* DAU 工作模式. */ static const char *dau_mode_str[PD_DAU_MODE_COUNT] = { "auto", "master", "slave" }; extern dau_port_func_t gis_func; /* Private function prototypes -----------------------------------------------*/ extern int32_t _dau_add(uint8_t unit, uint8_t port_num); extern void _dau_del(uint8_t unit); extern void *_dau_send_handle(void *arg); extern void vtycmd_send(char *pbuf); /* Internal functions --------------------------------------------------------*/ /* DAU 模块数量设置命令. */ CMD(dau_add, dau_add_cmd, "dau <1-2> port-num <1-8>", "DAU\n" "Unit id\n" "Port\n" "Port number\n") { return CMD_SUCCESS; uint8_t unit = 0; uint8_t port_num = 0; unit = strtol(argv[0], NULL, 10) - 1; port_num = strtol(argv[1], NULL, 10); _dau_add(unit, port_num); return CMD_SUCCESS; } CMD(no_dau_add, no_dau_add_cmd, "no dau <1-2>", "no\n" "DAU\n" "Unit id\n" "Port\n" "Port number\n") { return CMD_SUCCESS; uint8_t unit = 0; unit = strtol(argv[0], NULL, 10) - 1; _dau_del(unit); return CMD_SUCCESS; } /* DAU 同步主备方式. */ CMD(dau_master_slave_mode, dau_master_slave_mode_cmd, "dau <1-2> mode (auto|master|slave)", "DAU\n" "Unit id\n" "Master slave mode\n" "auto\n" "master\n" "slave\n") { return CMD_SUCCESS; dau_t *dau_node = NULL; uint8_t unit = 0; uint8_t mode = 0; uint16_t temp = 0; uint16_t GCR = 0; unit = strtol(argv[0], NULL, 10) - 1; dau_node = dau[unit]; if (!dau_node) { return CMD_WARNING; } for(mode = PD_DAU_MODE_AUTO; mode < PD_DAU_MODE_COUNT; mode++) { if (strncmp(argv[1], dau_mode_str[mode], strlen(dau_mode_str[mode]))) { continue; } GCR = dau_node->reg.GCR; temp = (mode << DAU_GCR_MODE_Pos); MODIFY_REG(dau_node->reg.GCR, DAU_GCR_MODE_Msk, temp); } /* 配置恢复过程中不进行寄存器下发. */ if (is_system_init) { if (dau_reg_global_write(unit) != E_NONE) { dau_node->reg.GCR = GCR; return CMD_WARNING; } } return CMD_SUCCESS; } /* 配置端口模式. */ CMD(dau_port_type, dau_port_type_cmd, "port-type (uhf|ae|tev|hf)", "DAU port type\n" "UHF\n" "AE\n" "TEV\n" "HF\n") { return CMD_SUCCESS; dau_t *dau_node = NULL; uint8_t unit = 0; uint8_t port = 0; uint8_t port_type = 0; uint16_t temp = 0; /* 取出端口号. */ if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE) { return CMD_ERR_NO_MATCH; } for(port_type = PD_PORT_TYPE_UHF; port_type < PD_PORT_TYPE_COUNT; port_type++) { if (strncmp(argv[0], dau_port_type_str[port_type], strlen(dau_port_type_str[port_type]))) { continue; } dau_node = dau[unit]; temp = (port_type << DAU_CR_PT_Pos); MODIFY_REG(dau_node->port_reg[port].CR, DAU_CR_PT_Msk, temp); if (PD_PORT_TYPE_UHF == port_type) { dau_node->port_func[port] = &gis_func; } else { dau_node->port_func[port] = &gis_func; } } return CMD_SUCCESS; } /* 通道采样频率模式. */ CMD(dau_sample_rate, dau_sample_rate_cmd, "sample-rate <1-50>", "Port sample rate\n" "Sample rate\n") { return CMD_SUCCESS; dau_t *dau_node = NULL; uint8_t unit = 0; uint8_t port = 0; uint8_t rate = 0; uint16_t temp = 0; /* 取出端口号. */ if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE) { return CMD_ERR_NO_MATCH; } rate = strtol(argv[0], NULL, 10); if (DAU_ADC_RATE % rate) { return CMD_WARNING; } rate = DAU_ADC_RATE / rate; dau_node = dau[unit]; temp = (rate << DAU_CR_SR_Pos); MODIFY_REG(dau_node->port_reg[port].CR, DAU_CR_SR_Msk, temp); pd_config.port_config[unit][port].config.sample_rate = rate * 1000000; return CMD_SUCCESS; } /* 通道滤波类型. */ CMD(dau_filter_type, dau_filter_type_cmd, "filtrate-type (none|ff|fr|lf|hf)", "Port filtrate type\n" "None\n" "Full frequency \n" "Full frequency resistor\n" "Low frequency\n" "High frequency\n") { return CMD_SUCCESS; dau_t *dau_node = NULL; uint8_t unit = 0; uint8_t port = 0; uint8_t filter = 0; uint8_t filter_csg = 0; uint16_t temp = 0; /* 取出端口号. */ if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE) { return CMD_ERR_NO_MATCH; } if (0 == strncmp(argv[0], "hf", 2)) { filter = PD_FILTER_TYPE_HF; filter_csg = CSG_FILTER_TYPE_HF; } else if (0 == strncmp(argv[0], "lf", 2)) { filter = PD_FILTER_TYPE_LF; filter_csg = CSG_FILTER_TYPE_LF; } else if (0 == strncmp(argv[0], "fr", 2)) { filter = PD_FILTER_TYPE_FR; filter_csg = CSG_FILTER_TYPE_FR; } else if (0 == strncmp(argv[0], "ff", 2)) { filter = PD_FILTER_TYPE_FF; filter_csg = CSG_FILTER_TYPE_FF; } else { filter = 0; } dau_node = dau[unit]; temp = (filter << DAU_FTR_FT_Pos); MODIFY_REG(dau_node->port_reg[port].FTR, DAU_FTR_FT_Msk, temp); pd_config.port_config[unit][port].config.filter = filter_csg; pd_config.port_config[unit][port].filter_cfg = filter_csg; return CMD_SUCCESS; } /* 通道滤波类型. */ CMD(dau_port_sync, dau_port_sync_cmd, "port-sync", "DAU port reg sync\n") { return CMD_SUCCESS; uint8_t unit = 0; uint8_t port = 0; /* 取出端口号. */ if (dau_vport_to_port(pd_port_node.param_num, &unit, &port) != E_NONE) { return CMD_ERR_NO_MATCH; } if (dau_reg_port_write(unit, port) != E_NONE) { return CMD_WARNING; } return CMD_SUCCESS; } /* 显示 DAU 状态. */ CMD(show_dau_status_all, show_dau_status_all_cmd, "show dau", "Show\n" "DAU\n") { return CMD_SUCCESS; uint8_t unit = 0; for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_show(unit); } return CMD_SUCCESS; } /* 显示 DAU 校准系数. */ CMD(show_dau_adj_all, show_dau_adj_all_cmd, "show dau adj", "Show\n" "DAU\n" "ADJ\n") { return CMD_SUCCESS; uint8_t unit = 0; for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_show_adj(unit); } return CMD_SUCCESS; } /* 显示 DAU 全局寄存器. */ CMD(show_dau_reg_all, show_dau_reg_all_cmd, "show dau reg", "Show\n" "DAU\n" "Reg\n") { return CMD_SUCCESS; uint8_t unit = 0; for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_show_reg(unit); } return CMD_SUCCESS; } /* 显示 DAU 全局寄存器. */ CMD(show_dau_reg_port, show_dau_reg_port_cmd, "show dau port <1-16>", "Show\n" "DAU\n" "Port Reg\n" "Port number") { return CMD_SUCCESS; uint8_t vport = 0; uint8_t unit = 0; uint8_t port = 0; vport = strtol(argv[0], NULL, 10); /* 取出端口号. */ if (dau_vport_to_port(vport, &unit, &port) != E_NONE) { return CMD_ERR_NO_MATCH; } dau_show_reg_port(unit, port); return CMD_SUCCESS; } /* 根据 IP 查找 DAU. */ int32_t _dau_unit_get_by_ip(uint32_t ip, uint8_t *unit) { uint8_t i = 0; bool is_find = FALSE; for(i = 0; i < PD_DAU_SUM; i++) { if (!dau[i]) { continue; } if (ip == dau[i]->ip_addr) { *unit = i; is_find = TRUE; break; } } if (is_find) { return E_NONE; } else { return E_BAD_PARAM; } } /* 根据 IP 查找 DAU. */ int32_t _dau_unit_get_by_slave(uint8_t id, uint8_t *unit) { uint8_t i = 0; bool is_find = FALSE; for(i = 0; i < PD_DAU_SUM; i++) { if (!dau[i]) { continue; } if (id == dau[i]->unit) { *unit = dau[i]->unit; is_find = TRUE; break; } } if (is_find) { return E_NONE; } else { return E_BAD_PARAM; } } int32_t _dau_lock_timeout(uint8_t unit, uint32_t sec, uint32_t nsec) { struct timespec time_out; dau_t *dau_node = dau[unit]; clock_gettime(CLOCK_REALTIME, &time_out); time_out.tv_sec += sec; time_out.tv_nsec += nsec; if (time_out.tv_nsec >= 1000000000) { time_out.tv_nsec -= 1000000000; time_out.tv_sec++; } return pthread_mutex_timedlock(&dau_node->mutex, &time_out); } void _dau_unlock(uint8_t unit) { dau_t *dau_node = dau[unit]; pthread_mutex_unlock(&dau_node->mutex); } /* 复位 fpga. */ void _dau_reset(void) { //FPGAResetEnable usleep(1000); //FPGAResetDisable } /* 读 DAU 寄存器. */ int32_t _dau_reg_read(uint8_t unit, uint16_t addr, uint16_t len) { dau_send_msg_t send_msg; dau_pkt_t *pkt = NULL; dau_t *dau_node = dau[unit]; uint16_t data_len = 8; if (dau_ctrl.is_update) { return E_NONE; } if (!dau_node->is_valid) { return E_NONE; } /* 申请报文空间, 8是报文总长度. */ pkt = XMALLOC_Q(MTYPE_DAU, data_len); if (!pkt) { return E_MEM; } /* 组装报文. */ pkt->slave_id = 0x0B; pkt->func = 0x01; pkt->addr = addr; pkt->len = len; pkt->data[0] = crc16_modbus((uint8_t*)pkt, data_len - 2); /* 封装消息. */ memset(&send_msg, 0, sizeof(dau_send_msg_t)); send_msg.type = dau_node->msg_send_type; send_msg.data.send_type = DAU_SEND_TYPE_REG_RD; send_msg.data.send_len = data_len; send_msg.data.data = pkt; /* 发送消息 */ if ((msgsnd(recv_qid, &send_msg, sizeof(dau_send_msg_data_t), 0)) < 0) { DBG(DBG_M_PD_DAU_ERR, "DAU msgsnd ERROR return %s!\r\n", safe_strerror(errno)); XFREE(MTYPE_DAU, pkt); return E_SYS_CALL; } return E_NONE; } /* 写 DAU 寄存器. */ int32_t _dau_reg_write(uint8_t unit, uint16_t addr, uint16_t len, uint16_t *data) { dau_send_msg_t send_msg; dau_pkt_t *pkt = NULL; dau_t *dau_node = dau[unit]; uint16_t data_len = 8 + (len << 1); if (dau_ctrl.is_update) { return E_NONE; } if (!dau_node->is_valid) { return E_NONE; } /* 申请报文空间 */ pkt = XMALLOC_Q(MTYPE_DAU, data_len); if (!pkt) { return E_MEM; } /* 组装报文. */ pkt->slave_id = 0x0B; pkt->func = DAU_PKT_CMD_WR; pkt->addr = addr; pkt->len = len; memcpy(pkt->data, data, (len << 1)); pkt->data[len] = crc16_modbus((uint8_t*)pkt, data_len - 2); /* 封装消息. */ memset(&send_msg, 0, sizeof(dau_send_msg_t)); send_msg.type = dau_node->msg_send_type; send_msg.data.send_type = DAU_SEND_TYPE_REG_WR; send_msg.data.send_len = data_len; send_msg.data.data = pkt; /* 发送消息. */ if ((msgsnd(recv_qid, &send_msg, sizeof(dau_send_msg_data_t), 0)) < 0) { DBG(DBG_M_PD_DAU_ERR, "DAU msgsnd ERROR return %s!\r\n", safe_strerror(errno)); XFREE(MTYPE_DAU, pkt); return E_SYS_CALL; } return E_NONE; } /* 全局寄存器读取. */ int32_t _dau_reg_global_read(uint8_t unit) { DBG(DBG_M_PD_DAU, "Entry: unit %d\r\n", unit); LD_E_RETURN(DBG_M_PD_DAU_ERR, _dau_reg_read(unit, DAU_REG_ADDR_GSCR, sizeof(dau_reg_t) >> 1)); DBG(DBG_M_PD_DAU, "Leave\r\n"); return E_NONE; } /* 端口寄存器读取. */ int32_t _dau_reg_port_read(uint8_t unit, uint8_t port) { uint16_t addr = DAU_REG_PORT_ADDR_GET(port); DBG(DBG_M_PD_DAU, "Entry: unit %d port %d\r\n", unit, port); LD_E_RETURN(DBG_M_PD_DAU_ERR, _dau_reg_read(unit, addr, sizeof(dau_port_reg_t) >> 1)); DBG(DBG_M_PD_DAU, "Leave\r\n"); return E_NONE; } /* 读通道校准系数. */ int32_t _dau_param_get(uint8_t unit) { uint8_t port = 0; DBG(DBG_M_PD_DAU, "Entry: unit %d\r\n", unit); for(port = 0; port < PD_DAU_PORT_SUM; port++) { LD_E_RETURN(DBG_M_PD_DAU_ERR, _dau_reg_port_read(unit, port)); } DBG(DBG_M_PD_DAU, "Leave\r\n"); return E_NONE; } /* 每秒获取 DAU 状态寄存器. */ void* _dau_time_state_get(void *arg) { dau_t *dau_node = (dau_t*)arg; /* 读取端口状态寄存器, 长度 16. */ _dau_reg_global_read(dau_node->unit); mtimer_add(_dau_time_state_get, (void *)dau_node, 10, "DAU_STATE_GET"); return NULL; } /* DAU 模块添加处理函数. */ int32_t _dau_add(uint8_t unit, uint8_t port_num) { dau_t *dau_node = dau[unit]; pthread_t pid; struct sched_param param; pthread_attr_t attr; char name[THREAD_M_NAME_LEN]; char ip[32]; uint8_t i = 0; uint16_t temp = 0; int32_t rv = 0; DBG(DBG_M_PD_DAU, "Entry: unit %d port_num %d\r\n", unit, port_num); /* 申请配置节点空间. */ if (!dau_node) { dau_node = XMALLOC(MTYPE_DAU, sizeof(dau_t)); if (!dau_node) { dau_node = NULL; return E_MEM; } } else { return E_NONE; } /* 初始化 DAU 结构体. */ dau_node->unit = unit; dau_node->port_num = port_num; snprintf(ip, 32, "192.168.7.%d", unit + 10); dau_node->ip_addr = inet_addr(ip); dau_node->ip_port = 7001; dau_node->msg_send_type = unit + 1; dau_node->is_connect = TRUE; for(i = 0; i < dau_node->port_num; i++) { temp = (PD_PORT_TYPE_UHF << DAU_CR_PT_Pos); MODIFY_REG(dau_node->port_reg[i].CR, DAU_CR_PT_Msk, temp); temp = (1 << DAU_CR_SR_Pos); MODIFY_REG(dau_node->port_reg[i].CR, DAU_CR_SR_Msk, temp); temp = (PD_FILTER_TYPE_FR << DAU_FTR_FT_Pos); MODIFY_REG(dau_node->port_reg[i].FTR, DAU_FTR_FT_Msk, temp); dau_node->port_func[i] = &gis_func; } dau[unit] = dau_node; /* 初始化配置端口号. */ for(i = 0; i < dau_node->port_num; i++) { pd_config.port_config[unit][i].config.vport = dau_port_to_vport(unit, i); } mtimer_add(_dau_time_state_get, (void *)dau[unit], 10, "DAU_STATE_GET"); /* 初始化线程锁, 用于发包线程与首保线程同步. */ pthread_mutex_init(&dau_node->mutex, NULL); pthread_mutex_lock(&dau_node->mutex); /* 初始化发送线程. */ /* 配置线程RR调度, 优先级78 */ pthread_attr_init(&attr); param.sched_priority = 78; pthread_attr_setschedpolicy(&attr, SCHED_RR); pthread_attr_setschedparam(&attr, ¶m); pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); rv = pthread_create(&pid, &attr, _dau_send_handle, dau_node); if (rv != 0) { log_err(LOG_DAU, "DAU%d can't create send pthread %d!", unit, rv); XFREE(MTYPE_DAU, dau_node); dau_node = NULL; return E_SYS_CALL; } else { snprintf(name, THREAD_M_NAME_LEN, "DAU_SEND_%d", unit); thread_m_add(name, pid); } pthread_attr_destroy(&attr); /* 初始化后, 添加 DAU, 需要重启DAU. */ if (is_system_init) { dau_shutdown(); dau_start(); } DBG(DBG_M_PD_DAU, "Leave\r\n"); return E_NONE; } /* DAU 模块删除处理函数. */ void _dau_del(uint8_t unit) { dau_t *dau_node = dau[unit]; if (!dau_node) { return; } dau_node->is_valid = FALSE; } /* 发送数据到后台通讯进程. */ int32_t _dau_msg_send(uint32_t type, void *data) { pd_csg_msg_t up_msg; /* 封装消息. */ up_msg.type = type; up_msg.data = data; /* 发送消息 */ if (fifo_write(csg.data_fifo_id, (void*)(&up_msg), sizeof(pd_csg_msg_t)) != sizeof(pd_csg_msg_t)) { DBG(DBG_M_PD_DAU_ERR, "DAU write ERROR!\r\n"); return E_ERROR; } return E_NONE; } /* 发送数据到本地存储进程 */ int32_t _dau_msg_send_storage(uint32_t type, void *data) { pd_storage_msg_t storage_msg; /* 封装消息. */ storage_msg.type = type; storage_msg.data = data; /* 发送消息 */ if (fifo_write(storage.storage_fifo_id, (void*)(&storage_msg), sizeof(pd_storage_msg_t)) != sizeof(pd_storage_msg_t)) { DBG(DBG_M_PD_DAU_ERR, "DAU write ERROR!\r\n"); return E_ERROR; } return E_NONE; } /* PRPS 数据完整性检查. */ void _dau_prps_complete_check(void) { uint8_t unit = 0; uint8_t port = 0; for(unit = 0; unit < PD_DAU_SUM; unit++) { if (!dau[unit]) { continue; } for(port = 0; port < dau[unit]->port_num; port++) { if (dau[unit]->port_state[port].prps_index != 0) { dau[unit]->port_state[port].is_complete = FALSE; if (!dau_ctrl.data_err_cnt) { log_err(LOG_DAU, "DAU%d port %d prps ERRORR!", unit, port); } dau_ctrl.data_err_cnt++; DBG_Q(DBG_M_PD_DAU_ERR, "DAU%d port %d prps ERRORR!\r\n", unit, port); } else { dau[unit]->port_state[port].is_complete = TRUE; } } } } /* 发送降噪数据到后台通讯进程. */ void _dau_prps_denoise_send(void) { if (_dau_msg_send(PD_SEND_TYPE_PRPS, pd_data.denoise) != E_NONE) { XFREE(MTYPE_CSG, pd_data.denoise); } } /* PRPS 数据实时显示数据降噪处理. */ void _dau_denoise_process(void) { dau_t *dau_node = NULL; uint8_t unit = 0; uint8_t port = 0; /* 没有端口被关注或者没有连接服务器不用计算. */ if (!pd_config.concern_bitmap || !csg.is_connect) { return; } /* 申请 PRPS 数据空间. */ pd_data.denoise = XMALLOC_Q(MTYPE_CSG, sizeof(pd_prps_t)); if (!pd_data.denoise) { return; } /* 自动 / 手动降噪 (PRPS 显示). */ for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_node) { continue; } for(port = 0; port < dau_node->port_num; port++) { if (!dau_node->port_func[port]->denoise) { continue; } dau_node->port_func[port]->denoise(unit, port); } } /* 关联降噪 (PRPS 显示). */ for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_node) { continue; } for(port = 0; port < dau_node->port_num; port++) { if (!dau_node->port_func[port]->denoise_r) { continue; } dau_node->port_func[port]->denoise_r(unit, port); } } /* 降噪数据统计 (PRPS 显示). */ for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_node) { continue; } for(port = 0; port < dau_node->port_num; port++) { if (!dau_node->port_func[port]->denoise_state) { continue; } dau_node->port_func[port]->denoise_state(unit, port); } } /* 将降噪后的 PRPS 数据发送到后台服务器. */ _dau_prps_denoise_send(); } /* 实时数据降噪处理. */ void _dau_real_process(void) { static uint16_t prps_sec = 0; pd_prps_t *storaged_data = NULL; dau_t *dau_node = NULL; uint8_t unit = 0; uint8_t port = 0; uint32_t now = time(NULL); /* 定时PRPS计算 */ prps_sec++; /* 自动 / 手动降噪. */ for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_node) { continue; } for(port = 0; port < dau_node->port_num; port++) { if (!dau_node->port_func[port]->denoise_real) { continue; } dau_node->port_func[port]->denoise_real(unit, port); } } /* 关联降噪. */ for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_node) { continue; } for(port = 0; port < dau_node->port_num; port++) { if (!dau_node->port_func[port]->denoise_real_r) { continue; } dau_node->port_func[port]->denoise_real_r(unit, port); } } /* 降噪数据统计 (PRPS 显示). */ for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_node) { continue; } for(port = 0; port < dau_node->port_num; port++) { if (!dau_node->port_func[port]->denoise_real_state) { continue; } dau_node->port_func[port]->denoise_real_state(unit, port); } } pd_data.real.index = dau_ctrl.real_idx++; pd_data.real.utc = now; pd_data.real.is_denoise = TRUE; /* 将降噪后的 PRPS 数据发送到本地存储进程 */ if (prps_sec >= pd_config.config.real_period * 60) { prps_sec = 0; storaged_data = XMALLOC_Q( MTYPE_STORAGE, sizeof(pd_prps_t) ); if (!storaged_data) { return; } memcpy( storaged_data, &pd_data.real, sizeof(pd_prps_t) ); if (_dau_msg_send_storage(STORAGE_TYPE_FIXEDTIMERPRPS, storaged_data) != E_NONE) { XFREE(MTYPE_STORAGE, storaged_data); } } } /* 事件计算. */ void _dau_event_process(void) { dau_t *dau_node = NULL; pd_event_t *data = NULL; pd_event_t *storaged_data = NULL; uint8_t unit = 0; uint8_t port = 0; /* 事件计算. */ for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_node) { continue; } for(port = 0; port < dau_node->port_num; port++) { if (!dau_node->port_func[port]->event) { continue; } dau_node->port_func[port]->event(unit, port); if (pd_data.event[unit][port].cnt <= pd_config.port_config[unit][port].config.event_counter) { continue; } /* 事件处理. */ memcpy(pd_data.event[unit][port].data, pd_data.real.data[unit][port].data, PD_PRPS_NUM << 1); pd_data.event[unit][port].vport = dau_port_to_vport(unit, port); pd_data.event[unit][port].second = 1; pd_data.event[unit][port].index = dau_ctrl.event_index[unit][port]++; pd_data.event[unit][port].utc = time(NULL); data = XMALLOC_Q(MTYPE_CSG, sizeof(pd_event_t)); if (!data) { return; } memcpy(data, &pd_data.event[unit][port], sizeof(pd_event_t)); if (_dau_msg_send(PD_SEND_TYPE_EVENT, data) != E_NONE) { XFREE(MTYPE_CSG, data); } storaged_data = XMALLOC_Q(MTYPE_STORAGE, sizeof(pd_event_t)); if (!storaged_data) { return; } memcpy(storaged_data, &pd_data.event[unit][port], sizeof(pd_event_t)); if (_dau_msg_send_storage(STORAGE_TYPE_EVENT, storaged_data) != E_NONE) { XFREE(MTYPE_STORAGE, storaged_data); } } } } /* 趋势数据处理. */ void _dau_trend_process(void) { static uint16_t trend_sec = 0; dau_t *dau_node = NULL; pd_trend_t *data = NULL; pd_trend_t *storaged_data = NULL; uint8_t unit = 0; uint8_t port = 0; /* 事件计算. */ trend_sec++; for(unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_node) { continue; } for(port = 0; port < dau_node->port_num; port++) { if (!dau_node->port_func[port]->trend) { continue; } dau_node->port_func[port]->trend(unit, port, trend_sec); } } if (trend_sec >= pd_config.config.trend_period * 60) { trend_sec = 0; data = XMALLOC_Q(MTYPE_CSG, sizeof(pd_trend_t)); if (!data) { return; } memcpy(data, &pd_data.trend, sizeof(pd_trend_t)); if (_dau_msg_send(PD_SEND_TYPE_TREND, data) != E_NONE) { XFREE(MTYPE_CSG, data); } storaged_data = XMALLOC_Q(MTYPE_STORAGE, sizeof(pd_trend_t)); if (!storaged_data) { return; } memcpy(storaged_data, &pd_data.trend, sizeof(pd_trend_t)); if (_dau_msg_send_storage(STORAGE_TYPE_TREND, storaged_data) != E_NONE) { XFREE(MTYPE_STORAGE, storaged_data); } } } /* 1s prps 数据处理. */ void _dau_prps_process(void) { static uint8_t data_cnt = 0; /* 上电非稳定期间的数据丢弃, 收到 10 次端口 1 的数据, 大概 10s. */ if (data_cnt < 5) { data_cnt++; return; } /* PRPS 数据实时显示数据处理. */ _dau_denoise_process(); /* 实时数据降噪处理. */ _dau_real_process(); /* 事件处理. */ _dau_event_process(); /* 趋势数据处理 */ _dau_trend_process(); } /* 报文头检查. */ int32_t _dau_pkt_check(dau_pkt_t *pkt, uint32_t len) { if ((pkt->len << 1) + 8 != len && pkt->func != DAU_PKT_CMD_WR && pkt->func != DAU_PKT_CMD_UPD) { return E_ERROR; } /* 验证 CRC32. */ //if (crc32(cmd, head->len) != (*(uint32_t*)(cmd + head->len))) //{ // vty_print("@3: %x %x\r\n", crc32(cmd, head->len), *(uint32_t*)(cmd + head->len)); // return HAL_ERROR; //} return E_NONE; } /* PRPS 数据处理. */ int32_t _dau_pkt_prps(uint8_t unit, dau_pkt_t *pkt, uint32_t len) { static bool is_updata = FALSE; uint8_t port = pkt->addr; dau_pkt_prps_t *data = (dau_pkt_prps_t *)pkt->data; dau_t *dau_node = dau[unit]; dau_port_state_t *port_state = NULL; /* 参数检查. */ if (port >= dau_node->port_num) { return E_ERROR; } if (len != 1292) { return E_ERROR; } /* 检查是否连续, 不连续说明丢包. */ port_state = &dau_node->port_state[port]; /* 预留调试打印, 用于查看板卡报文是否同步. */ //struct timeval tv; //if (port == 3) //{ // gettimeofday(&tv, NULL); // printf("%d %d %d/t %d\r\n", unit, tv.tv_sec, tv.tv_usec, data->power_fre_cnt); // //printf("%d\r\n", tv.tv_usec); //} if (port_state->prps_cnt != data->power_fre_cnt) { port_state->prps_index = (data->power_fre_cnt % 50) / 5; if (!dau_ctrl.data_err_cnt) { log_err(LOG_DAU, "DAU%d utc %d_%d ERRORR!", unit, port_state->prps_cnt, data->power_fre_cnt); } dau_ctrl.data_err_cnt++; DBG_Q(DBG_M_PD_DAU_ERR, "DAU%d utc %d_%d ERRORR!\r\n", unit, port_state->prps_cnt, data->power_fre_cnt); } /* 检查是否读到完整的 1s 数据. */ if (0 == port_state->prps_index) { /* 保证只在 0 == port_state->prps_index 时只进入一次.*/ if (is_updata) { is_updata = FALSE; _dau_prps_complete_check(); _dau_prps_process(); } dau_node->port_func[port]->data_default(port_state->prps); } /* 复制数据. */ memcpy(port_state->prps + port_state->prps_index * DAU_PKT_PRPS_LEN, data->data, DAU_PKT_PRPS_DATA_LEN); /* 更新状态 */ port_state->prps_cnt = data->power_fre_cnt + 5; if (port_state->prps_cnt >= 2000000000) { port_state->prps_cnt = 0; } port_state->prps_index++; if (5 == port_state->prps_index) { is_updata = TRUE; } else if (10 == port_state->prps_index) { port_state->prps_index = 0; } return E_NONE; } /* 读取寄存器处理. */ int32_t _dau_pkt_reg_rd(uint8_t unit, dau_pkt_t *pkt, uint32_t len) { dau_t *dau_node = dau[unit]; uint8_t port = 0; /* 保存数据. */ if (DAU_REG_ADDR_GSCR == pkt->addr) { memcpy(&dau_node->reg_dau, pkt->data, pkt->len << 1); dau_node->reg.GSCR = dau_node->reg_dau.GSCR; dau_node->reg.GSVR = dau_node->reg_dau.GSVR; dau_node->reg.GSR = dau_node->reg_dau.GSR; dau_node->reg.GPFPCCR = dau_node->reg_dau.GPFPCCR; dau_node->reg.GPFPCR = dau_node->reg_dau.GPFPCR; dau_node->reg.GNSCR = dau_node->reg_dau.GNSCR; } else if (DAU_REG_PORT_ADDR_MSRR == pkt->addr) { memcpy(&dau_node->port_state_reg, pkt->data, pkt->len << 1); debug_pkt_port_state_post(); } else if(DAU_REG_PORT_BASE <= pkt->addr && pkt->addr < DAU_REG_PORT_ADDR_MSRR) { port = pkt->addr >> 12; memcpy(&dau_node->port_reg_dau[port - 1].CR, pkt->data, pkt->len << 1); memcpy(&dau_node->port_reg[port - 1].ASPR[0], &dau_node->port_reg_dau[port - 1].ASPR[0], 60); } if (DAU_SEND_TYPE_REG_RD == dau_node->send_type) { dau_node->send_type = 0; _dau_unlock(unit); } return E_NONE; } /* 写寄存器处理. */ int32_t _dau_pkt_reg_wr(uint8_t unit, dau_pkt_t *pkt, uint32_t len) { dau_t *dau_node = dau[unit]; if (DAU_SEND_TYPE_REG_WR == dau_node->send_type) { dau_node->send_type = 0; _dau_unlock(unit); } return E_NONE; } /* 读取寄存器处理. */ int32_t _dau_pkt_update(uint8_t unit, dau_pkt_t *pkt, uint32_t len) { dau_t *dau_node = dau[unit]; /* 保存数据. */ if (dau_ctrl.update_idx != pkt->addr) { return E_ERROR; } dau_ctrl.update_idx++; if (DAU_SEND_TYPE_UPDATE == dau_node->send_type) { _dau_unlock(unit); } return E_NONE; } /* DAU 报文处理 */ int32_t _dau_data_process(uint32_t ip, dau_pkt_t *pkt, uint32_t len) { uint8_t unit = 0; /* 查找 DAU. */ if (_dau_unit_get_by_slave(pkt->slave_id, &unit) != E_NONE) { if (!dau_ctrl.data_err_cnt) { log_err(LOG_DAU, "DAU%d id %d ERRORR!", unit, pkt->slave_id); } dau_ctrl.data_err_cnt++; DBG_Q(DBG_M_PD_DAU_ERR, "DAU%d id %d ERRORR!\r\n", unit, pkt->slave_id); return E_BAD_PARAM; } if (!dau[unit]->is_valid) { return E_NONE; } /* 报文头和 CRC 校验. */ if (_dau_pkt_check(pkt, len) != E_NONE) { if (!dau_ctrl.data_err_cnt) { log_err(LOG_DAU, "DAU%d len %d_%d ERRORR!", unit, pkt->len, len); } dau_ctrl.data_err_cnt++; DBG_Q(DBG_M_PD_DAU_ERR, "DAU%d len %d_%d ERRORR!\r\n", unit, pkt->len, len); return E_BAD_PARAM; } /* 共有命令处理. */ switch (pkt->func) { case DAU_PKT_CMD_RD: _dau_pkt_reg_rd(unit, pkt, len); break; case DAU_PKT_CMD_WR: case DAU_PKT_CMD_SAV: _dau_pkt_reg_wr(unit, pkt, len); break; case DAU_PKT_CMD_UPD: _dau_pkt_update(unit, pkt, len); break; case DAU_PKT_CMD_PRPS: _dau_pkt_prps(unit, pkt, len); break; default: if (!dau_ctrl.data_err_cnt) { log_err(LOG_DAU, "DAU%d func %d ERRORR!", unit, pkt->func); } dau_ctrl.data_err_cnt++; DBG_Q(DBG_M_PD_DAU_ERR, "DAU%d func %d ERRORR!\r\n", unit, pkt->func); break; } return E_NONE; } int32_t _dau_send_handle_pkt(dau_t *dau_node, dau_send_msg_t *send_msg) { struct sockaddr_in server; uint8_t err_cnt = 0; int32_t rv = 0; /* 发送数据. */ bzero(&server, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = dau_node->ip_addr; server.sin_port = htons(dau_node->ip_port); err_cnt = 0; while(1) { /* 多次发送失败退出发送. */ if (DAU_SEND_ERR_MAX == err_cnt) { if (!dau_ctrl.send_err_cnt) { log_err(LOG_DAU, "DAU%d send ERRORR!", dau_node->unit); } dau_ctrl.send_err_cnt++; DBG_Q(DBG_M_PD_DAU_ERR, "DAU%d send ERRORR!\r\n", dau_node->unit); break; } /* 调试打印报文. */ DBG(DBG_M_PD_DAU_SEND, "DAU(%d) send(%d):\r\n", dau_node->unit, send_msg->data.send_len); if (dbg_stat_get(DBG_M_PD_DAU_SEND)) { buf_print( send_msg->data.data, send_msg->data.send_len > 32 ? 32 : send_msg->data.send_len); printh("\r\n"); } /* 发送数据. */ rv = sendto(dau_ctrl.fd, (char*) send_msg->data.data, send_msg->data.send_len, 0, (struct sockaddr*)&server, sizeof(server)); if (rv < 0) { err_cnt++; DBG_Q(DBG_M_PD_DAU_ERR, "DAU%d sendto ERRORR!\r\n", dau_node->unit); continue; } /* 等待命令完成. */ rv = _dau_lock_timeout(dau_node->unit, 0, DAU_SEND_TIMEOUT); /* 超时处理. */ if (rv != 0) { err_cnt++; DBG_Q(DBG_M_PD_DAU_ERR, "DAU%d timeout ERRORR!\r\n", dau_node->unit); continue; } return E_NONE; } return E_ERROR; } int32_t _dau_send_handle_update(dau_t *dau_node, dau_send_msg_t *send_msg) { struct sockaddr_in server; dau_pkt_t *pkt = (dau_pkt_t*)send_msg->data.data; char *data = (char*)pkt->data; uint8_t is_end = 0; uint8_t err_cnt = 0; int fd = 0; uint16_t len = 0; int32_t rv = 0; fd = open(DEBUG_DAU_FILE, O_RDONLY); if (fd <= 0) { DBG_Q(DBG_M_PD_DAU_ERR, "DAU%d open ERR!\r\n", dau_node->unit); dau_ctrl.update_ret = -1; return E_SYS_CALL; } /* 发送数据. */ bzero(&server, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = dau_node->ip_addr; server.sin_port = htons(dau_node->ip_port); err_cnt = 0; while(1) { /* 多次发送失败退出发送. */ if (DAU_SEND_ERR_MAX == err_cnt) { if (!dau_ctrl.send_err_cnt) { log_err(LOG_DAU, "DAU%d send ERRORR!", dau_node->unit); } dau_ctrl.send_err_cnt++; DBG_Q(DBG_M_PD_DAU_ERR, "DAU%d send ERRORR!\r\n", dau_node->unit); dau_ctrl.update_ret = -2; break; } /* 组装报文. */ pkt->slave_id = 0x0B; pkt->func = DAU_PKT_CMD_UPD; pkt->addr = dau_ctrl.update_idx; pkt->len = 512; len = read(fd, data, 1024); if (len < 0) { DBG_Q(DBG_M_PD_DAU_ERR, "DAU%d read ERR!\r\n", dau_node->unit); dau_ctrl.update_ret = -3; break; } else if (0 == len) { dau_ctrl.update_ret = DAU_UPD_OK; close(fd); return E_NONE; } else if (len < 1024) { memset(data + len, 0xff, 1024 - len); is_end = TRUE; } pkt->data[512] = crc16_modbus((uint8_t*)pkt, send_msg->data.send_len - 2); /* 发送数据. */ rv = sendto(dau_ctrl.fd, (char*) send_msg->data.data, send_msg->data.send_len, 0, (struct sockaddr*)&server, sizeof(server)); if (rv < 0) { DBG_Q(DBG_M_PD_DAU_ERR, "DAU%d sendto ERR!\r\n", dau_node->unit); err_cnt++; continue; } /* 等待命令完成. */ rv = _dau_lock_timeout(dau_node->unit, DAU_SEND_TIMEOUT_U, 0); /* 超时处理. */ if (rv != 0) { DBG_Q(DBG_M_PD_DAU_ERR, "DAU%d timeout ERR!\r\n", dau_node->unit); err_cnt++; continue; } if (is_end) { dau_ctrl.update_ret = DAU_UPD_OK; close(fd); return E_NONE; } } close(fd); return E_ERROR; } /* DAU 报文发送处理函数. */ void *_dau_send_handle(void *arg) { dau_t *dau_node = (dau_t*)arg; dau_send_msg_t send_msg; uint8_t adu_err_cnt = 0; int32_t rv = 0; /* 主循环. */ while (1) { /* 读取消息队列. */ memset(&send_msg.data, 0, sizeof(dau_send_msg_data_t)); if (-1 == msgrcv(recv_qid, (void*)&send_msg, sizeof(dau_send_msg_data_t), dau_node->msg_send_type, 0)) { if (!dau_ctrl.send_err_cnt) { log_err(LOG_DAU, "DAU%d msgrcv ERRORR!", dau_node->unit); } dau_ctrl.send_err_cnt++; DBG_Q(DBG_M_PD_DAU_ERR, "DAU%d msgrcv ERRORR!\r\n", dau_node->unit); continue; } /* 记录当前的发送状态, 用于在收包时判断是否释放信号量. */ dau_node->send_type = send_msg.data.send_type; /* 发送报文. */ if (DAU_SEND_TYPE_UPDATE == dau_node->send_type) { rv = _dau_send_handle_update(dau_node, &send_msg); } else { rv = _dau_send_handle_pkt(dau_node, &send_msg); } /* 记录 DAU 连接状态. */ if (rv == E_NONE) { adu_err_cnt = 0; } else { if (adu_err_cnt <= DAU_ERR_MAX) { adu_err_cnt++; } } dau_node->is_connect = (adu_err_cnt < DAU_ERR_MAX); /* 释放数据内存. */ XFREE(MTYPE_DAU, send_msg.data.data); } return NULL; } /* DAU 报文接收处理函数. */ void *_dau_recv_handle(void *arg) { struct sockaddr_in server; socklen_t server_len; dau_recv_msg_data_t recv_msg; char *pkt = NULL; uint16_t data_len = 0; //dau_pkt_t *temp = NULL; //uint16_t temp1 = 0; #ifdef DAU_IPC_FIFO int fd = 0; fd = open(DAU_RECV_FIFO, O_WRONLY | O_CREAT, 0644); if (fd == -1) { log_err(LOG_DAU, "Open write fifo file " DAU_RECV_FIFO " error!"); return NULL; } #endif while(1) { /* 读取数据. */ data_len = recvfrom(dau_ctrl.fd, dau_ctrl.recv_buf, DAU_PKT_LEN, 0, (struct sockaddr*)&server, &server_len); if (data_len <= 0) { if (!dau_ctrl.recv_err_cnt) { log_err(LOG_DAU, "DAU receive ERRORR!"); } dau_ctrl.recv_err_cnt++; DBG_Q(DBG_M_PD_DAU_ERR, "DAU recvfrom ERROR\r\n"); continue; } dau_ctrl.recv_cnt++; /* 申请报文空间, 8是报文总长度. */ pkt = XMALLOC_Q(MTYPE_DAU, data_len); if (!pkt) { continue; } /* 封装消息. */ memcpy(pkt, dau_ctrl.recv_buf, data_len); recv_msg.ip_addr = server.sin_addr.s_addr; recv_msg.recv_len = data_len; recv_msg.data = pkt; /* 发送消息 */ #ifdef DAU_IPC_FIFO if (write(fd, (char*)(&recv_msg), sizeof(dau_recv_msg_data_t)) != sizeof(dau_recv_msg_data_t)) { DBG(DBG_M_PD_DAU_ERR, "DAU write ERROR return %s!\r\n", safe_strerror(errno)); XFREE(MTYPE_DAU, pkt); continue; } #endif /* DAU 收报同步调试打印. */ // temp = (dau_pkt_t*)pkt; // if (temp->func == 0x81 && temp->addr == 0) // { // printf("%x ", *(uint32_t*)(&temp->data[0])); // temp1++; // if (temp1 >= 20) // { // temp1 = 0; // printf("\r\n"); // } // } if (fifo_write(dau_ctrl.recv_fifo_id, (void*)(&recv_msg), sizeof(dau_recv_msg_data_t)) != sizeof(dau_recv_msg_data_t)) { if (!dau_ctrl.recv_err_cnt) { log_err(LOG_DAU, "DAU fifo write ERROR!"); } dau_ctrl.recv_err_cnt++; DBG_Q(DBG_M_PD_DAU_ERR, "DAU fifo write ERROR\r\n"); XFREE(MTYPE_DAU, pkt); continue; } } return NULL; } /* DAU 报文处理函数. */ void *_dau_data_handle(void *arg) { dau_recv_msg_data_t *recv_msg = NULL; #ifdef DAU_IPC_FIFO int fd = 0; fd = open(DAU_RECV_FIFO, O_RDONLY); if (fd == -1) { log_err(LOG_DAU, "Open read fifo file " DAU_RECV_FIFO " error!"); return NULL; } #endif while(1) { /* 读取数据. */ #ifdef DAU_IPC_FIFO if (read(fd, (char*)(&recv_msg), sizeof(dau_recv_msg_data_t)) != sizeof(dau_recv_msg_data_t)) { DBG(DBG_M_PD_DAU_ERR, "ERROR at msgrcv return %s\r\n!", safe_strerror(errno)); continue; } #endif if (fifo_read(dau_ctrl.recv_fifo_id, (void**)&recv_msg) != 0) { if (!dau_ctrl.data_err_cnt) { log_err(LOG_DAU, "DAU%d fifo read ERRORR!", dau_ctrl.recv_fifo_id); } dau_ctrl.data_err_cnt++; DBG_Q(DBG_M_PD_DAU_ERR, "DAU%d fifo read ERRORR!\r\n", dau_ctrl.recv_fifo_id); continue; } /* 数据处理. */ _dau_data_process(recv_msg->ip_addr, (dau_pkt_t*)recv_msg->data, recv_msg->recv_len); /* 释放数据内存, 注意一定要在 fifo_push 之前调用, 因为 fifo_push 后 recv_msg 已被释放. */ XFREE(MTYPE_DAU, recv_msg->data); fifo_push(dau_ctrl.recv_fifo_id); } return NULL; } /* 配置保存函数. */ int _dau_config_save(vty_t* vty) { dau_t *dau_node = NULL; int16_t i = 0; uint8_t unit = 0; uint8_t mode = 0; /* 遍历所有 DAU. */ for (unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_node) { continue; } if (!dau_node->is_valid) { continue; } vty_out(vty, "dau %d port-num %d%s", unit + 1, dau_node->port_num, VTY_NEWLINE); i++; mode = (dau_node->reg.GCR & DAU_GCR_MODE_Msk) >> DAU_GCR_MODE_Pos; vty_out(vty, "dau %d mode %s%s", unit + 1, dau_mode_str[mode], VTY_NEWLINE); i++; } return i; } /* config模式配置保存函数: vty -- 相应的终端 */ int _dau_port_config_save(vty_t *vty, uint8_t unit, uint8_t port) { dau_t *dau_node = NULL; uint16_t field = 0; char str[5] ={0}; dau_node = dau[unit]; field = (dau_node->port_reg[port].CR & DAU_CR_PT_Msk) >> DAU_CR_PT_Pos; vty_out(vty, " port-type %s%s", dau_port_type_str[field], VTY_NEWLINE); field = (dau_node->port_reg[port].CR & DAU_CR_SR_Msk) >> DAU_CR_SR_Pos; vty_out(vty, " sample-rate %d%s", DAU_ADC_RATE / field, VTY_NEWLINE); field = pd_config.port_config[unit][port].config.filter; switch(field) { case CSG_FILTER_TYPE_HF: snprintf(str, 5, "hf"); break; case CSG_FILTER_TYPE_LF: snprintf(str, 5, "lf"); break; case CSG_FILTER_TYPE_FR: snprintf(str, 5, "fr"); break; case CSG_FILTER_TYPE_FF: snprintf(str, 5, "ff"); break; default: snprintf(str, 5, "none"); break; } vty_out(vty, " filtrate-type %s%s", str, VTY_NEWLINE); return E_NONE; } /* DAU 内部公共部分初始化. */ int32_t _dau_handle_init_common(void) { struct sockaddr_in server; struct sched_param param; pthread_attr_t attr; pthread_t pid; int32_t rv = 0; int fd = 0; /* 创建协议 socket 与 DAU 通讯. */ if (0 == dau_ctrl.fd) { /* 创建socket */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { log_err(LOG_DAU, "ERROR at socket create return %s!", safe_strerror(errno)); return E_SYS_CALL; } /* 绑定端口 */ bzero(&server, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons(7000); if(bind(fd, (struct sockaddr*)&server, sizeof(server)) < 0) { log_err(LOG_DAU, "ERROR at socket bind return %s!", safe_strerror(errno)); close(fd); return E_SYS_CALL; } /* 保存 socket. */ dau_ctrl.fd = fd; } /* 创建消息队列, 用于将 DAU 收到的数据发送到处理线程, 这里使用队列是为了缓冲数据. */ #ifdef DAU_IPC_FIFO if (-1 == access(DAU_RECV_FIFO, F_OK)) { if (mkfifo(DAU_RECV_FIFO, 0666) < 0) { log_err(LOG_DAU, "Cannot create fifo file " DAU_RECV_FIFO "!"); return E_SYS_CALL; } } else { remove(DAU_RECV_FIFO); if (mkfifo(DAU_RECV_FIFO, 0666) < 0) { log_err(LOG_DAU, "Cannot create fifo file " DAU_RECV_FIFO "!"); return E_SYS_CALL; } } #endif dau_ctrl.recv_fifo_id = fifo_create(DAU_RECV_FIFO, 128); if (dau_ctrl.recv_fifo_id < 0) { log_err(LOG_DAU, "Open fifo " DAU_RECV_FIFO " error!"); return E_NONE; } /* 初始化 DAU 报文处理线程. */ /* 配置线程RR调度, 优先级79 */ pthread_attr_init(&attr); param.sched_priority = 79; pthread_attr_setschedpolicy(&attr, SCHED_RR); pthread_attr_setschedparam(&attr, ¶m); pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); rv = pthread_create(&pid, &attr, _dau_data_handle, NULL); if (rv != 0) { log_err(LOG_DAU, "PD can't create DAU data pthread %d!", rv); return E_SYS_CALL; } else { thread_m_add("PD_DAU_DATA", pid); } pthread_attr_destroy(&attr); /* 初始化 DAU 收包线程. */ /* 配置线程RR调度, 优先级80 */ pthread_attr_init(&attr); param.sched_priority = 80; pthread_attr_setschedpolicy(&attr, SCHED_RR); pthread_attr_setschedparam(&attr, ¶m); pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); rv = pthread_create(&pid, &attr, _dau_recv_handle, NULL); if (rv != 0) { log_err(LOG_DAU, "DAU can't create recv pthread %d!", rv); return E_SYS_CALL; } else { thread_m_add("PD_DAU_RECV", pid); } pthread_attr_destroy(&attr); /* 复位 fpga. */ _dau_reset(); return E_NONE; } /* Interface functions -------------------------------------------------------*/ /* DAU 模块初始化. */ int32_t dau_handle_init(void) { int32_t rv = 0; #if 0 /* 初始化 DAU 模块. */ LD_E_RETURN(DBG_M_PD_DAU_ERR, _dau_handle_init_common()); #endif /* 注册命令行 */ cmd_install_element(CONFIG_NODE, &dau_add_cmd); cmd_install_element(CONFIG_NODE, &no_dau_add_cmd); cmd_install_element(CONFIG_NODE, &dau_master_slave_mode_cmd); cmd_install_element(PORT_NODE, &dau_port_type_cmd); cmd_install_element(PORT_NODE, &dau_sample_rate_cmd); cmd_install_element(PORT_NODE, &dau_filter_type_cmd); cmd_install_element(PORT_NODE, &dau_port_sync_cmd); cmd_install_element(COMMON_NODE, &show_dau_status_all_cmd); cmd_install_element(COMMON_NODE, &show_dau_adj_all_cmd); cmd_install_element(COMMON_NODE, &show_dau_reg_all_cmd); cmd_install_element(COMMON_NODE, &show_dau_reg_port_cmd); #if 0 /* 注册配置保存函数 */ rv = cmd_config_node_config_register(CONFIG_PRI_DAU, _dau_config_save); if (rv != E_NONE) { log_err(LOG_DAU, "Command save register ERROR %d!", rv); return rv; } rv = pd_port_cmd_config_register(PD_PORT_CMD_PRI_DAU, _dau_port_config_save); if (rv != E_NONE) { log_err(LOG_DAU, "DAU port command save register ERROR %d!", rv); return rv; } #endif return E_NONE; } /* 将 unit port 转换成 vport. */ int32_t dau_port_to_vport(uint8_t unit, uint8_t port) { uint8_t i = 0; uint8_t vport = 0; if (unit >= PD_DAU_SUM) { return E_BAD_PARAM; } for(i = 0; i < unit; i++) { if (!dau[i]) { continue; } vport += dau[i]->port_num; } if (!dau[i]) { return E_BAD_PARAM; } if (port >= dau[i]->port_num) { return E_BAD_PARAM; } return vport += port + 1; } /* 将 unit port 转换成 vport. */ int32_t dau_vport_to_port(uint8_t vport, uint8_t *unit, uint8_t *port) { uint8_t i = 0; for(i = 0; i < PD_DAU_SUM; i++) { if (!dau[i]) { continue; } if (vport <= dau[i]->port_num && vport != 0) { *unit = i; *port = vport - 1; return E_NONE; } else { vport -= dau[i]->port_num; } } return E_BAD_PARAM; } /* 端口配置刷新对外接口. */ int32_t dau_port_config_set(uint8_t unit, uint8_t port) { dau_t *dau_node = NULL; uint16_t temp = 0; if (unit >= PD_DAU_SUM) { return E_BAD_PARAM; } if (NULL == (dau_node = dau[unit])) { return E_BAD_PARAM; } if (port >= dau_node->port_num) { return E_BAD_PARAM; } temp = pd_config.port_config[unit][port].config.sample_rate / 1000000; temp = (temp << DAU_CR_SR_Pos); MODIFY_REG(dau_node->port_reg[port].CR, DAU_CR_SR_Msk, temp); temp = pd_config.port_config[unit][port].filter_cfg; switch(temp) { case CSG_FILTER_TYPE_FF: temp = PD_FILTER_TYPE_FF; break; case CSG_FILTER_TYPE_FR: temp = PD_FILTER_TYPE_FR; break; case CSG_FILTER_TYPE_LF: temp = PD_FILTER_TYPE_LF; break; case CSG_FILTER_TYPE_HF: temp = PD_FILTER_TYPE_HF; break; default: return E_BAD_PARAM; } temp = (temp << DAU_FTR_FT_Pos); MODIFY_REG(dau_node->port_reg[port].FTR, DAU_FTR_FT_Msk, temp); return E_NONE; } /* 端口类型设置. */ int32_t dau_port_type_set(uint8_t unit, uint8_t port, uint8_t type) { dau_t *dau_node = NULL; uint16_t temp = 0; if (unit >= PD_DAU_SUM) { return E_BAD_PARAM; } if (NULL == (dau_node = dau[unit])) { return E_BAD_PARAM; } if (port >= dau_node->port_num) { return E_BAD_PARAM; } temp = (type << DAU_CR_PT_Pos); MODIFY_REG(dau_node->port_reg[port].CR, DAU_CR_PT_Msk, temp); if (PD_PORT_TYPE_UHF == type) { dau_node->port_func[port] = &gis_func; } else { dau_node->port_func[port] = &gis_func; } return E_NONE; } /* 获取工频周期. */ uint8_t dau_power_frequency_state_get(void) { dau_t *dau_node = NULL; if (NULL == (dau_node = dau[0])) { return 0; } return (dau_node->reg.GSR & DAU_GSR_SYNC_Msk) >> DAU_GSR_SYNC_Pos; } /* 获取工频周期. */ float dau_power_frequency_get(void) { dau_t *dau_node = NULL; float temp = 100000000.00; if (NULL == (dau_node = dau[0])) { return 0; } return dau_node->reg.GPFPCCR ? (temp / (dau_node->reg.GPFPCCR / 50)) : 0; } /* 获取工频周期. */ uint8_t dau_connect_get(void) { uint8_t unit = 0; uint8_t state = 0; for(unit = 0; unit < PD_DAU_SUM; unit++) { if (!dau[unit]) { continue; } if (dau[unit]->is_connect) { state |= 1 << unit; } } return state; } /* 获取端口状态寄存器. */ void* dau_port_state_get(void *arg) { uint8_t unit = 0; if (!dau_ctrl.is_update && debug_ctrl.is_manual_col) { for(unit = 0; unit < PD_DAU_SUM; unit++) { if (!dau[unit]) { continue; } _dau_reg_read(dau[unit]->unit, DAU_REG_PORT_ADDR_MSRR, PD_DAU_PORT_SUM << 1); } } return NULL; } /* 配置全局控制寄存器. */ int32_t dau_reg_global_write(uint8_t unit) { dau_t *dau_node = NULL; DBG(DBG_M_PD_DAU, "Entry: unit %d\r\n", unit); if (unit >= PD_DAU_SUM) { return E_BAD_PARAM; } if (NULL == (dau_node = dau[unit])) { return E_BAD_PARAM; } LD_E_RETURN(DBG_M_PD_DAU_ERR, _dau_reg_write(unit, DAU_REG_ADDR_GCR, 1, &dau_node->reg.GCR)); DBG(DBG_M_PD_DAU, "Leave\r\n"); return E_NONE; } /* 获取端口状态寄存器. */ int32_t dau_reg_port_write(uint8_t unit, uint8_t port) { dau_t *dau_node = NULL; uint16_t addr = DAU_REG_PORT_ADDR_GET(port); DBG(DBG_M_PD_DAU, "Entry: unit %d port %d\r\n", unit, port); if (unit >= PD_DAU_SUM) { return E_BAD_PARAM; } if (NULL == (dau_node = dau[unit])) { return E_BAD_PARAM; } if (port >= dau_node->port_num) { return E_BAD_PARAM; } LD_E_RETURN(DBG_M_PD_DAU_ERR, _dau_reg_write(unit, addr, sizeof(dau_port_reg_t) >> 1, &dau_node->port_reg[port].CR)); DBG(DBG_M_PD_DAU, "Leave\r\n"); return E_NONE; } /* 获取端口状态寄存器. */ int32_t dau_param_save(uint8_t unit) { dau_send_msg_t send_msg; dau_pkt_t *pkt = NULL; dau_t *dau_node = dau[unit]; if (unit >= PD_DAU_SUM) { return E_BAD_PARAM; } if (NULL == (dau_node = dau[unit])) { return E_BAD_PARAM; } if (dau_ctrl.is_update) { return E_NONE; } if (!dau_node->is_valid) { return E_NONE; } /* 申请报文空间 */ pkt = XMALLOC_Q(MTYPE_DAU, 8); if (!pkt) { return E_MEM; } /* 组装报文. */ pkt->slave_id = 0x0B; pkt->func = DAU_PKT_CMD_SAV; pkt->addr = 0; pkt->len = 0; pkt->data[0] = crc16_modbus((uint8_t*)pkt, 6); /* 封装消息. */ memset(&send_msg, 0, sizeof(dau_send_msg_t)); send_msg.type = dau_node->msg_send_type; send_msg.data.send_type = DAU_SEND_TYPE_REG_WR; send_msg.data.send_len = 8; send_msg.data.data = pkt; /* 发送消息. */ if ((msgsnd(recv_qid, &send_msg, sizeof(dau_send_msg_data_t), 0)) < 0) { DBG(DBG_M_PD_DAU_ERR, "DAU msgsnd ERROR return %s!\r\n", safe_strerror(errno)); XFREE(MTYPE_DAU, pkt); return E_SYS_CALL; } return E_NONE; } void dau_utc_enable(void) { uint8_t i = 0; uint16_t dau_bitmap = 0; for(i = 0; i < PD_DAU_SUM; i++) { if (!dau[i]) { continue; } BITMAP_SET(dau_bitmap, i); } cpld_write(0x0c, 1, &dau_bitmap); } void dau_utc_disable(void) { uint16_t temp = 0; cpld_write(0x0c, 1, &temp); } void dau_shutdown(void) { uint8_t i = 0; for(i = 0; i < PD_DAU_SUM; i++) { if (!dau[i]) { continue; } dau[i]->is_valid = FALSE; } GPIO_DAU1_POW_OFF; GPIO_DAU2_POW_OFF; dau_utc_disable(); sleep(1); } int32_t dau_start(void) { uint8_t i = 0; uint8_t j = 0; uint8_t cnt = 0; /* DAU 上电. */ for(i = 0; i < PD_DAU_SUM; i++) { if (!dau[i]) { continue; } if (0 == i) { GPIO_DAU1_POW_ON; } else if(1 == i) { GPIO_DAU2_POW_ON; } } sleep(4); /* 设置为有效. */ for(i = 0; i < PD_DAU_SUM; i++) { if (!dau[i]) { continue; } dau[i]->is_valid = TRUE; } for(i = 0; i < PD_DAU_SUM; i++) { if (!dau[i]) { continue; } /* 读取写入全局状态寄存器. */ _dau_reg_global_read(i); dau_reg_global_write(i); /* 读通道校准系数. */ LD_E_RETURN(DBG_M_PD_DAU_ERR, _dau_param_get(i)); /* 将端口配置同步到 DAU. */ for (j = 0; j < dau[i]->port_num; j++) { dau_reg_port_write(i, j); } /* 等待工频同步成功. */ while(1) { cnt++; if ((dau[i]->reg.GSR & DAU_GSR_SYNC_Msk) >> DAU_GSR_SYNC_Pos) { break; } if (0 == (cnt & 0x7)) { DBG(DBG_M_PD_DAU_ERR, "DAU%d can't sync!\r\n", i); break; } sleep(1); _dau_reg_global_read(i); } } /* 使能同步采样. */ dau_utc_enable(); return E_NONE; } /* DAU 远程升级处理, 升级所有 DAU. */ int32_t dau_update(void) { dau_send_msg_t send_msg; dau_pkt_t *pkt = NULL; dau_t *dau_node = NULL; uint8_t unit = 0; uint8_t cnt = 0; uint16_t data_len = 1032; // 8byte 数据头 + 1024byte 数据. int32_t rv = E_ERROR; /* 更新标志, 设置为升级状态 */ if (dau_ctrl.is_update) { return E_TIMEOUT; } dau_ctrl.is_update = TRUE; /* 关闭 UTC 同步采集. */ dau_utc_disable(); /* 遍历 DAU, 串行升级. */ for(unit = 0; unit < PD_DAU_SUM; unit++) { /* 检查 DAU 是否存在. */ dau_node = dau[unit]; if (!dau_node) { continue; } if (!dau_node->is_valid) { continue; } /* 初始化状态. */ dau_ctrl.update_ret = DAU_UPD_PROCESS; dau_ctrl.update_idx = 0; /* 申请报文空间. */ pkt = XMALLOC_Q(MTYPE_DAU, data_len); if (!pkt) { rv = E_MEM; break; } /* 封装消息. */ memset(&send_msg, 0, sizeof(dau_send_msg_t)); send_msg.type = dau_node->msg_send_type; send_msg.data.send_type = DAU_SEND_TYPE_UPDATE; send_msg.data.send_len = data_len; send_msg.data.data = pkt; /* 发送消息 */ if ((msgsnd(recv_qid, &send_msg, sizeof(dau_send_msg_data_t), 0)) < 0) { DBG(DBG_M_PD_DAU_ERR, "DAU msgsnd ERROR return %s!\r\n", safe_strerror(errno)); XFREE(MTYPE_DAU, pkt); break; } log_notice(LOG_DAU, "DAU%d update start!", unit); /* 等待升级完成. */ while(1) { sleep(1); if (dau_ctrl.update_ret < 0) { dau_ctrl.is_update = FALSE; dau_utc_enable(); return E_ERROR; } else if(DAU_UPD_OK == dau_ctrl.update_ret) { log_notice(LOG_DAU, "DAU%d update OK!", unit); rv = E_NONE; break; } cnt++; if (cnt >= 30) { dau_ctrl.is_update = FALSE; dau_utc_enable(); return E_TIMEOUT; } } } dau_ctrl.is_update = FALSE; dau_utc_enable(); return rv; } /* 显示 DAU 状态. */ void dau_show(uint8_t unit) { dau_t *dau_node = NULL; dau_node = dau[unit]; if (!dau_node) { return; } printh("DAU %d: \r\n", unit + 1); printh(" Version: %d.%d\r\n", (dau_node->reg.GSVR & DAU_GSVR_PRIMARY_Msk) >> DAU_GSVR_PRIMARY_Pos, (dau_node->reg.GSVR & DAU_GSVR_SECONDARY_Msk) >> DAU_GSVR_SECONDARY_Pos); printh(" Mode: %s\r\n", (dau_node->reg.GSR & DAU_GSR_MODE_Msk) >> DAU_GSR_MODE_Pos ? "master" : "slave"); printh(" Synchronization: %s\r\n", (dau_node->reg.GSR & DAU_GSR_SYNC_Msk) >> DAU_GSR_SYNC_Pos ? "valid" : "invalid"); printh(" Power frequency period: %.2f\r\n", dau_power_frequency_get()); printh(" Power frequency count: %d\r\n", dau_node->reg.GPFPCR); printh(" Clock ns: %d\r\n", dau_node->reg.GNSCR); printh(" Valid: %d\r\n", dau_node->is_valid); printh(" connected: %d\r\n\n", dau_node->is_connect); return; } /* 显示 DAU 校准系数. */ void dau_show_adj(uint8_t unit) { dau_t *dau_node = NULL; dau_port_reg_t *reg = NULL; uint8_t port = 0; dau_node = dau[unit]; if (!dau_node) { return; } printh("DAU %d: \r\n", unit + 1); for(port = 0; port < dau_node->port_num; port++) { reg = &dau_node->port_reg[port]; printh("%d | %05d %05d %05d | %05d %05d %05d | %05d %05d %05d |", port + 1, reg->AFAR[0], reg->AFBR[0], reg->ASPR[0], reg->AFAR[1], reg->AFBR[1], reg->ASPR[1], reg->AFAR[2], reg->AFBR[2], reg->ASPR[2]); printh(" %05d %05d %05d | %05d %05d %05d |\r\n", reg->AFAR[3], reg->AFBR[3], reg->ASPR[3], reg->AFAR[4], reg->AFBR[4], reg->ASPR[4]); } printh("\r\n"); } /* 显示 DAU 全局寄存器. */ void dau_show_reg(uint8_t unit) { dau_t *dau_node = NULL; uint16_t *reg = NULL; uint8_t num = sizeof(dau_reg_t) >> 1; uint8_t row = 0; uint8_t col = 0; uint8_t i = 0; uint8_t j = 0; dau_node = dau[unit]; if (!dau_node) { return; } row = num >> 4; if (num & 0x0f) { row++; } printh("DAU %d: \r\n", unit + 1); for(i = 0; i < row; i++) { col = num - (i << 4); col = col > 16 ? 16 : col; printh(" "); for(j = 0; j < col; j++) { printh("%04x ", (i << 4) + j); } reg = &dau_node->reg.GSCR; reg += (i << 4); printh("\r\nC "); for(j = 0; j < col; j++) { printh("%04x ", reg[j]); } reg = &dau_node->reg_dau.GSCR; reg += (i << 4); printh("\r\nD "); for(j = 0; j < col; j++) { printh("%04x ", reg[j]); } printh("\r\n\n"); } } /* 显示 DAU 端口寄存器. */ void dau_show_reg_port(uint8_t unit, uint8_t port) { dau_t *dau_node = NULL; uint16_t *reg = NULL; uint8_t num = sizeof(dau_port_reg_t) >> 1; uint8_t row = 0; uint8_t col = 0; uint8_t i = 0; uint8_t j = 0; dau_node = dau[unit]; if (!dau_node) { return; } _dau_reg_port_read(unit, port); usleep(100000); row = num >> 4; if (num & 0x0f) { row++; } printh("DAU %d port %d: \r\n", unit + 1, port + 1); for(i = 0; i < row; i++) { col = num - (i << 4); col = col > 16 ? 16 : col; printh(" "); for(j = 0; j < col; j++) { printh("%04x ", (i << 4) + j); } reg = &dau_node->port_reg[port].CR; reg += (i << 4); printh("\r\nC "); for(j = 0; j < col; j++) { printh("%04x ", reg[j]); } reg = &dau_node->port_reg_dau[port].CR; reg += (i << 4); printh("\r\nD "); for(j = 0; j < col; j++) { printh("%04x ", reg[j]); } printh("\r\n\n"); } } #endif /************************ (C) COPYRIGHT LandPower ***** END OF FILE ****/