You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2684 lines
64 KiB
C
2684 lines
64 KiB
C
/*****************************************************************************
|
|
* 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
|
|
*
|
|
* <h2><center>© COPYRIGHT(c) 2021 LandPower</center></h2>
|
|
*
|
|
* 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 <sys/types.h>
|
|
#include <sys/ipc.h>
|
|
#include <sys/msg.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/socket.h>
|
|
#include <fcntl.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#include <pthread.h>
|
|
|
|
#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;
|
|
}
|
|
|
|
/* 配置端口模式. */
|
|
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;
|
|
}
|
|
|
|
/* 通道采样频率模式. */
|
|
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_vaule,
|
|
show_dau_vaule_cmd,
|
|
"show dau vaule",
|
|
"Show\n"
|
|
"DAU\n"
|
|
"Vaule\n")
|
|
{
|
|
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(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_vaule_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 ****/
|