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.

1776 lines
51 KiB
C

/******************************************************************************
* file Core/Src/dau.c
* author YuLiang
* version 1.0.0
* date 15-Aug-2024
* brief This file provides all the DAU related operation functions.
******************************************************************************
* Attention
*
* <h2><center>&copy; COPYRIGHT(c) 2024 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 WTOE 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 ------------------------------------------------------------------*/
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "time.h"
#include "math.h"
#include "spi.h"
#include "usart.h"
#include "common.h"
#include "dev_config.h"
#include "flash_if.h"
#include "flash_log.h"
#include "ADC_collect.h"
#include "dau.h"
#include "wireless.h"
#include "RS485_debug.h"
/* Private define ------------------------------------------------------------*/
#define DAU_WAVE_WAIT_MAX 8 // DAU 波形等待次数
#define DAU_ID 0x0702 // DAU 软件识别码
/* Private typedef -----------------------------------------------------------*/
/* 波形触发源 */
typedef enum
{
DAU_SOURCE_FAULT = 0,
DAU_SOURCE_REG,
DAU_SOURCE_CNT,
} DAU_SOURCE_E;
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* DAU 任务参数 */
const osThreadAttr_t dau_attributes =
{
.name = "DAU",
.stack_size = 160 * 4,
.priority = (osPriority_t) osPriorityRealtime,
};
const osThreadAttr_t dau_gps_attributes =
{
.name = "GPS",
.stack_size = 160 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
const osThreadAttr_t dau_adj_attributes =
{
.name = "ADJ",
.stack_size = 160 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* DAU 全局结构体 */
dau_ctrl_t dau_ctrl;
static struct tm _dau_tm;
int8_t _dau_spi_rw;
uint16_t _dau_spi_addr;
uint16_t _dau_spi_len;
uint8_t dau_adj_state = 0; // 1:采集 2:采集完成
extern dev_adj_fault_zero_t debug_adj_fault;
/* Private function prototypes -----------------------------------------------*/
extern int32_t _dau_adj_reg_write_port(uint32_t port);
/* Internal functions --------------------------------------------------------*/
/* description: DAU 写寄存器报文发送
param: addr -- 寄存器地址
len -- 写长度
return: HAL_xxx */
int32_t _dau_reg_write(uint16_t addr, uint16_t len)
{
uint8_t *pkt_tx = dau_ctrl.buf_dau_tx;
uint8_t *pkt_rx = dau_ctrl.buf_dau_rx;
uint32_t notify_value = 0xff;
int32_t rv = 0;
/* 发送数据. */
/* 组装报文, 报文头是大端模式 */
pkt_tx[0] = (addr >> 8) & 0x7f; // 最高位为 0 表示读
pkt_tx[1] = addr & 0x00ff;
len +=2;
/* 调试打印报文 */
DBG(DBG_M_DAU_TXRX, "DAU write send(%d):\r\n", len);
if (dbg_stat_get(DBG_M_DAU_TXRX))
{
buf_print(pkt_tx, len > 32 ? 32 : len);
}
/* 发送数据. */
DAU_CS_ENABLE();
rv = HAL_SPI_TransmitReceive_DMA(dau_ctrl.spi, pkt_tx, pkt_rx, len);
if (rv != HAL_OK)
{
DBG(DBG_M_DAU, "DAU spi read err %d\r\n", rv);
return rv;
}
/* 等待收包完成. */
notify_value = ulTaskNotifyTake(pdTRUE, 1000);
if (0 == notify_value)
{
/* 收包超时 */
DAU_CS_DISABLE();
DBG(DBG_M_DAU, "DAU spi read timeout\r\n");
return HAL_TIMEOUT;
}
return HAL_OK;
}
/* description: DAU 读取寄存器报文发送
param: addr -- 寄存器地址
len -- 读取长度
return: HAL_xxx */
int32_t _dau_reg_read(uint16_t addr, uint16_t len)
{
uint8_t *pkt_tx = dau_ctrl.buf_dau_tx;
uint8_t *pkt_rx = dau_ctrl.buf_dau_rx;
uint32_t notify_value = 0xff;
int32_t rv = 0;
/* 发送数据. */
/* 组装报文, 报文头是大端模式 */
pkt_tx[0] = (addr >> 8) | 0x80; // 最高位为 1 表示读
pkt_tx[1] = addr & 0x00ff;
/* 调试打印报文 */
DBG(DBG_M_DAU_TXRX, "DAU read send:\r\n");
if (dbg_stat_get(DBG_M_DAU_TXRX))
{
buf_print(pkt_tx, 2);
}
/* 发送数据. */
DAU_CS_ENABLE();
rv = HAL_SPI_TransmitReceive_DMA(dau_ctrl.spi, pkt_tx, pkt_rx, len + 2);
if (rv != HAL_OK)
{
DAU_CS_DISABLE();
DBG(DBG_M_DAU, "DAU spi read err %d\r\n", rv);
return rv;
}
/* 等待收包完成. */
notify_value = ulTaskNotifyTake(pdTRUE, 1000);
if (0 == notify_value)
{
/* 收包超时 */
DBG(DBG_M_DAU, "DAU spi read timeout\r\n");
return HAL_TIMEOUT;
}
/* 调试打印报文. */
DBG(DBG_M_DAU_TXRX, "DAU read recv(%d):\r\n", len);
if (dbg_stat_get(DBG_M_DAU_TXRX))
{
buf_print(pkt_rx + 2, len > 32 ? 32 : len);
vty_print("\r\n");
}
return HAL_OK;
}
/* description: DAU 读取全局状态寄存器报文发送
param:
return: HAL_xxx */
int32_t _dau_reg_read_global_state(void)
{
dau_reg_global_t *p = (dau_reg_global_t*)(dau_ctrl.buf_dau_rx + 2);
int32_t rv = HAL_ERROR;
/* 读取全局寄存器 */
E_RETURN(_dau_reg_read(DAU_REG_ADDR_GSCR, sizeof(dau_reg_global_t)));
if (p->GSCR != DAU_ID)
{
DBG(DBG_M_DAU, "DAU read 0x0 data %x err\r\n", p->GSCR);
return HAL_ERROR;
}
memcpy(&dau_ctrl.reg_global, p, sizeof(dau_reg_global_t));
if ((dau_ctrl.reg_global.GFTR & DAU_GFTR_FAULT_Msk) >> DAU_GFTR_FAULT_Pos)
{
dau_ctrl.is_fault = TRUE;
}
return rv;
}
/* description: DAU 读取端口状态寄存器报文发送
param:
return: HAL_xxx */
int32_t _dau_reg_read_port_state(void)
{
int32_t rv = HAL_ERROR;
/* 读取全局寄存器 */
E_RETURN(_dau_reg_read(DAU_REG_ADDR_PMSR, sizeof(dau_port_state_reg_t)));
memcpy(&dau_ctrl.reg_port_state, dau_ctrl.buf_dau_rx + 2, sizeof(dau_port_state_reg_t));
return rv;
}
/* description: DAU 写端口配置寄存器报文发送
param:
return: HAL_xxx */
int32_t _dau_reg_write_port(uint32_t port)
{
uint16_t *temp = (uint16_t*)&dau_ctrl.buf_dau_tx[2];
uint16_t addr = 0;
int32_t rv = HAL_ERROR;
/* 缺陷校准系数 */
addr = (port + 1) * DAU_REG_ADDR_PORT_BASE + DAU_REG_ADDR_PORT_DEFECT_BASE;
/* 零点值用的是16位的 */
*temp = dev_config.defect_base[port] << 4;
E_RETURN(_dau_reg_write(addr, sizeof(uint16_t)));
addr = (port + 1) * DAU_REG_ADDR_PORT_BASE + DAU_REG_ADDR_PORT_DEFECT_ADJ;
*temp = dev_config.defect_adj[port];
E_RETURN(_dau_reg_write(addr, sizeof(uint16_t)));
/* 故障校准系数 */
addr = (port + 1) * DAU_REG_ADDR_PORT_BASE + DAU_REG_ADDR_PORT_FAULT_BASE;
*temp = dev_config.fault_base[port];
E_RETURN(_dau_reg_write(addr, sizeof(uint16_t)));
addr = (port + 1) * DAU_REG_ADDR_PORT_BASE + DAU_REG_ADDR_PORT_FAULT_ADJ;
*temp = dev_config.fault_adj[port];
E_RETURN(_dau_reg_write(addr, sizeof(uint16_t)));
return rv;
}
/* description: DAU 写端口配置寄存器报文发送
param:
return: HAL_xxx */
int32_t _dau_reg_write_cfg(void)
{
uint16_t *temp = (uint16_t*)&dau_ctrl.buf_dau_tx[2];
int32_t rv = HAL_ERROR;
/* 触发阈值 */
*temp = dev_config.fault_threshold / 3 * 32768 * 16 / dev_config.fault_adj[0];
E_RETURN(_dau_reg_write(DAU_REG_ADDR_GCFTTR, sizeof(uint16_t)));
/* 触发间隔 */
*temp = dev_config.fault_interval;
E_RETURN(_dau_reg_write(DAU_REG_ADDR_GCFTIR, sizeof(uint16_t)));
return rv;
}
/* description: DAU 历史数据保存
param:
return: */
static void _dau_data_save(void)
{
uint8_t i = 0;
/* 装填数据. */
fd_data.temperature = ADC_ctrl.ADCi_temp;
fd_data.vbat = ADC_ctrl.ADCi_vbat;
fd_data.vin = ADC_ctrl.ADCi_vin;
fd_data.vsc = ADC_ctrl.ADCi_vsc;
for(i = 0; i < DAU_PORT_FAULT_MAX; i++)
{
fd_data.fault[i] = dau_ctrl.fault_max[i];
}
for(i = 0; i < DAU_PORT_DEFECT_MAX; i++)
{
fd_data.defect[i] = dau_ctrl.reg_defect_max[i];
}
for(i = 0; i < DAU_PORT_POWER_CNT; i++)
{
fd_data.elec[i] = dau_ctrl.reg_elec[i];
}
fd_data.col_flag = dau_ctrl.col_flag;
fd_data.is_bat_charge = st_data.is_bat_charge;
fd_data.is_utc_valid = dau_ctrl.is_utc_valid;
fd_data.state_wir = wl_ctrl.state;
fd_write(&fd_data);
}
/* description: DAU UTC 对时处理
param:
return: */
int32_t _dau_update(void)
{
uint8_t *data = (uint8_t*)&dau_ctrl.buf_dau_tx[2];
uint16_t *reg = (uint16_t*)&dau_ctrl.buf_dau_tx[2];
uint16_t cnt = 0;
uint16_t page_cnt = 0;
uint32_t app_len = dau_ctrl.update_len;
uint32_t len = 0;
uint32_t addr = TFTP_APP_ADDRESS;
int32_t rv = HAL_ERROR;
/* 校验报文. */
E_RETURN(debug_app_check(TFTP_APP_ADDRESS, app_len, 3));
/* 发送升级数据 */
while(1)
{
/* 组装数据报文, 报文头是大端模式 DAU_REG_ADDR_GSUDR */
len = app_len < 1024 ? app_len : 1024;
if (0 == len)
{
/* 无数据, 直接结束 */
break;
}
/* 读取固件数据 */
E_RETURN(spi_flash_read(addr, data, 1024));
/* 先发送数据报文, 0x0e00 */
E_RETURN(_dau_reg_write(DAU_REG_ADDR_GSUDR, 1024));
/* 再发送页报文, 0x0202 */
*reg = page_cnt;
E_RETURN(_dau_reg_write(DAU_REG_ADDR_GSUPR, 2));
/* 向 0x0200 写 1, 表示固件升级 */
*reg = 1;
E_RETURN(_dau_reg_write(DAU_REG_ADDR_GFWSR, sizeof(uint16_t)));
/* 等待 spi flash 完成, 0x0002 bit2 为高 */
cnt = 0;
while(1)
{
osDelay(5);
/* 读取 spi flash 状态 DAU_REG_ADDR_GSR */
E_RETURN(_dau_reg_read_global_state());
/* 0 - 忙, 1 - 空闲 */
if ((dau_ctrl.reg_global.GSR & DAU_GSR_FLASH_Msk) >> DAU_GSR_FLASH_Pos)
{
break;
}
osDelay(50);
cnt++;
if (cnt > 8)
{
DBG(DBG_M_DAU, "DAU update timeout\r\n");
return HAL_TIMEOUT;
}
}
common_watchdog_set(COM_WDG_DAU);
/* 结束直接返回 */
if (len < 1024)
{
break;
}
/* 更新参数 */
app_len -= len;
page_cnt++;
addr += 1024;
}
return HAL_OK;
}
/* description: DAU UTC 对时处理
param:
return: */
void _dau_utc(void)
{
uint32_t *utc = (uint32_t*)&dau_ctrl.buf_dau_tx[2];
/* dau 主循环大概 250ms 运行一次, 在第 3 次循环 (500 ~ 750ms) 对时, 此时 GPS 对时一定是可用的 */
if (50000000 < dau_ctrl.reg_global.GNR && dau_ctrl.reg_global.GNR <= 75000000
&& dau_ctrl.is_utc_valid
&& dau_ctrl.reg_global.GUR != dau_ctrl.utc)
{
*utc = dau_ctrl.utc;
_dau_reg_write(DAU_REG_ADDR_GCUR, sizeof(uint32_t));
vty_print("#D Change %d %d %d %d\r\n", dau_ctrl.reg_global.GUR, dau_ctrl.reg_global.GNR, dau_ctrl.is_utc_valid, dau_ctrl.utc);
}
}
/* description: 寄存器触发波形采集开始
param:
return: HAL_xxx */
int32_t _dau_wave_col_start(void)
{
uint16_t *reg = (uint16_t*)&dau_ctrl.buf_dau_tx[2];
uint8_t i = 0;
int32_t rv = HAL_ERROR;
/* 请求录波 */
*reg = DAU_GCRTR_START_WAVE_Msk;
E_RETURN(_dau_reg_write(DAU_REG_ADDR_GCRTR, sizeof(uint16_t)));
/* 等待录波完成 */
while(1)
{
if (i >= DAU_WAVE_WAIT_MAX)
{
DBG(DBG_M_DAU, "DAU wave err\r\n", rv);
return HAL_TIMEOUT;
}
osDelay(1000);
E_RETURN(_dau_reg_read_global_state());
if ((dau_ctrl.reg_global.GRTR & DAU_GRTR_COMPLETE_Msk) >> DAU_GRTR_COMPLETE_Pos)
{
break;
}
i++;
//vty_print("#D start wait %d\r\n", i);
}
return rv;
}
/* description: 故障波形采集
param:
return: HAL_xxx */
int32_t _dau_wave_col_fault(void)
{
uint16_t *reg = (uint16_t*)&dau_ctrl.buf_dau_tx[2];
uint8_t i = 0;
uint8_t j = 0;
uint32_t addr = 0;
int32_t temp = 0;
int32_t rv = HAL_ERROR;
dau_ctrl.fault_utc = dau_ctrl.reg_global.GFTUR;
dau_ctrl.fault_ns = dau_ctrl.reg_global.GFTNR;
dau_ctrl.fault_utc_max = dau_ctrl.reg_global.GFMUR;
dau_ctrl.fault_ns_max = dau_ctrl.reg_global.GFMNR;
dau_ctrl.PPS_cnt = dau_ctrl.reg_global.GGPCR;
vty_print("#D utc %d.%d %d %d\r\n", dau_ctrl.fault_utc, dau_ctrl.fault_ns, dau_ctrl.PPS_cnt, dev_config.fault_time_adj);
dau_ctrl.fault_ns = (uint64_t)dau_ctrl.fault_ns * 100000000 / dau_ctrl.PPS_cnt;
vty_print(" #D %d ", dau_ctrl.fault_ns);
dau_ctrl.fault_ns += dev_config.fault_time_adj;
vty_print("%d\r\n", dau_ctrl.fault_ns);
/* 擦除 flash */
addr = dau_ctrl.addr_fault;
vty_print("#DF reg start addr %x\r\n", addr);
for(i = 0; i < 2; i++)
{
E_RETURN(spi_flash_erase(addr, SPI_CMD_BLOCK64_ERASE));
addr += SPI_FLASH_BLOCK64_SIZE;
}
/* 读取触发电流值 */
E_RETURN(_dau_reg_read_port_state());
/* 数据地址应该是被擦除过的地址 (当前地址向前偏移 128k). */
addr = dau_ctrl.addr_fault;
/* 读取故障数据 */
for(i = 0; i < DAU_PORT_FAULT_CNT; i++)
{
vty_print("#DF %d %d\r\n", i, dau_ctrl.reg_port_state.FMAX[i]);
temp = dau_ctrl.reg_port_state.FMAX[i] - dev_config.fault_base[i];
dau_ctrl.fault_max[i] = dev_config.fault_adj[i] * temp / 32768 / 16 * 3;
vty_print(" #DF %d %d %d\r\n", dau_ctrl.fault_max[i], dev_config.fault_adj[i], temp);
/* 请求读取故障波形 */
*reg = DAU_GCFTR_FAULT_WAVE_Msk | (i << DAU_GCFTR_PORT_Pos);
E_RETURN(_dau_reg_write(DAU_REG_ADDR_GCFTR, sizeof(uint16_t)));
/* 等待 DAU 准备故障数据 */
j = 0;
while(1)
{
if (j >= DAU_WAVE_WAIT_MAX)
{
DBG(DBG_M_DAU, "DAU fault wave err\r\n");
return HAL_TIMEOUT;
}
osDelay(5);
E_RETURN(_dau_reg_read_global_state());
if ((dau_ctrl.reg_global.GFTR & DAU_GFTR_FAULT_WAVE_Msk) >> DAU_GFTR_FAULT_WAVE_Pos)
{
break;
}
vty_print("#D8 %d\r\n", j);
j++;
}
for(j = 0; j < DAU_PKT_FAULT_CNT; j++)
{
E_RETURN(_dau_reg_read(DAU_REG_ADDR_PPWR, DAU_PKT_FAULT_BYTE_CNT));
E_RETURN(spi_flash_write(addr, &dau_ctrl.buf_dau_rx[2], DAU_PKT_FAULT_BYTE_CNT));
addr += DAU_PKT_FAULT_BYTE_CNT;
}
}
return HAL_OK;
}
/* description: 缺陷波形采集
param:
return: HAL_xxx */
int32_t _dau_wave_col_defect(void)
{
uint16_t *reg = (uint16_t*)&dau_ctrl.buf_dau_tx[2];
uint8_t i = 0;
uint8_t j = 0;
uint8_t is_exceed = FALSE;
uint32_t addr = 0;
int32_t rv = HAL_ERROR;
/* 比较缺陷波形是否超过阈值 */
E_RETURN(_dau_reg_read_port_state());
vty_print("#D defect max");
for(i = 0; i < DAU_PORT_DEFECT_CNT; i++)
{
dau_ctrl.reg_defect_max[i] = abs(dau_ctrl.reg_port_state.DMAX[i]);
vty_print(" %d %d ", dau_ctrl.reg_defect_max[i], dau_ctrl.reg_port_state.DAVR[i]);
if (dau_ctrl.reg_defect_max[i] > dev_config.defect_threshold)
{
is_exceed = TRUE;
}
}
vty_print(" %d\r\n", is_exceed);
/* 没有超过阈值并没有强制录波直接返回 */
if (!is_exceed && !IS_MONITOR_BIT_SET(dau_ctrl.col_flag, DAU_COL_FLAG_WAVE_FORCE))
{
MONITOR_BITMAP_RESET(dau_ctrl.col_flag, DAU_COL_FLAG_REG_DEFECT);
return HAL_OK;
}
/* 擦除 flash */
addr = dau_ctrl.addr_reg;
vty_print("#D reg start addr %x\r\n", addr);
for(i = 0; i < 2; i++)
{
E_RETURN(spi_flash_erase(addr, SPI_CMD_BLOCK64_ERASE));
addr += SPI_FLASH_BLOCK64_SIZE;
}
/* 数据地址应该是被擦除过的地址 (当前地址向前偏移 128k). */
addr = dau_ctrl.addr_reg;
/* 读取缺陷数据 */
for(i = 0; i < DAU_PORT_DEFECT_CNT; i++)
{
/* 请求读取缺陷波形 */
*reg = DAU_GCRTR_DEFECT_WAVE_Msk | (i << DAU_GCRTR_PORT_Pos);
E_RETURN(_dau_reg_write(DAU_REG_ADDR_GCRTR, sizeof(uint16_t)));
/* 等待 DAU 准备缺陷数据 */
j = 0;
while(1)
{
if (j >= DAU_WAVE_WAIT_MAX)
{
DBG(DBG_M_DAU, "DAU defect wave err\r\n", rv);
return HAL_TIMEOUT;
}
osDelay(5);
E_RETURN(_dau_reg_read_global_state());
if ((dau_ctrl.reg_global.GRTR & DAU_GRTR_DEFECT_WAVE_Msk) >> DAU_GRTR_DEFECT_WAVE_Pos)
{
break;
}
j++;
vty_print("#D reg d wait %d\r\n", j);
}
for(j = 0; j < DAU_PKT_DEFECT_CNT; j++)
{
E_RETURN(_dau_reg_read(DAU_REG_ADDR_PPWR, DAU_PKT_DEFECT_BYTE_CNT));
E_RETURN(spi_flash_write(addr, &dau_ctrl.buf_dau_rx[2], DAU_PKT_DEFECT_BYTE_CNT));
addr += DAU_PKT_DEFECT_BYTE_CNT;
}
}
vty_print("#D reg end addr %x\r\n", addr);
MONITOR_BITMAP_SET(dau_ctrl.col_flag, DAU_COL_FLAG_REG_DEFECT);
return rv;
}
/* description: 工频波形采集
param: flag - 采集来源见 DAU_COL_FLAG_E
return: HAL_xxx */
int32_t _dau_wave_col_power(DAU_SOURCE_E source)
{
uint16_t *reg = (uint16_t*)&dau_ctrl.buf_dau_tx[2];
int16_t *power = NULL;
uint8_t i = 0;
uint8_t j = 0;
int32_t rv = HAL_ERROR;
/* 读取工频数据 */
for(i = 0; i < DAU_PORT_POWER_CNT; i++)
{
/* 请求读取工频波形 */
if (DAU_SOURCE_FAULT == source)
{
*reg = DAU_GCFTR_POWER_WAVE_Msk | (i << DAU_GCFTR_PORT_Pos);
E_RETURN(_dau_reg_write(DAU_REG_ADDR_GCFTR, sizeof(uint16_t)));
}
else
{
*reg = DAU_GCRTR_POWER_WAVE_Msk | (i << DAU_GCRTR_PORT_Pos);
E_RETURN(_dau_reg_write(DAU_REG_ADDR_GCRTR, sizeof(uint16_t)));
}
/* 等待 DAU 准备工频数据 */
j = 0;
while(1)
{
if (j >= DAU_WAVE_WAIT_MAX)
{
DBG(DBG_M_DAU, "DAU power wave err\r\n");
return HAL_TIMEOUT;
}
osDelay(5);
E_RETURN(_dau_reg_read_global_state());
if (DAU_SOURCE_FAULT == source)
{
if ((dau_ctrl.reg_global.GFTR & DAU_GFTR_POWER_WAVE_Msk) >> DAU_GFTR_POWER_WAVE_Pos)
{
break;
}
}
else
{
if ((dau_ctrl.reg_global.GRTR & DAU_GRTR_POWER_WAVE_Msk) >> DAU_GRTR_POWER_WAVE_Pos)
{
break;
}
}
j++;
vty_print("#D reg p wait %d\r\n", j);
}
/* 选择存储位置, 读取数据 */
power = (DAU_SOURCE_FAULT == source) ? dau_ctrl.fault_power[i] : dau_ctrl.reg_power[i];
for(j = 0; j < DAU_PKT_POWER_CNT; j++)
{
E_RETURN(_dau_reg_read(DAU_REG_ADDR_PPWR, DAU_PKT_POWER_BYTE_CNT));
memcpy(power, &dau_ctrl.buf_dau_rx[2], DAU_PKT_POWER_BYTE_CNT);
power += DAU_PKT_POWER_BYTE_CNT >> 1;
}
}
return HAL_OK;
#if 0
int16_t *power = NULL;
uint8_t i = 0;
uint8_t j = 0;
/* 读取工频数据 */
for(i = 0; i < DAU_PORT_POWER_CNT; i++)
{
/* 选择存储位置, 读取数据 */
power = (DAU_SOURCE_FAULT == source) ? dau_ctrl.fault_power[i] : dau_ctrl.reg_power[i];
memset(&dau_ctrl.buf_dau_rx[2], i, DAU_PKT_POWER_BYTE_CNT);
for(j = 0; j < DAU_PKT_POWER_CNT; j++)
{
memcpy(power, &dau_ctrl.buf_dau_rx[2], DAU_PKT_POWER_BYTE_CNT);
power += DAU_PKT_POWER_BYTE_CNT >> 1;
}
}
return HAL_OK;
#endif
}
/* description: DAU 工频电流计算
param:
return: */
void _dau_power_calculate(DAU_SOURCE_E source)
{
int16_t (*val)[DAU_POWER_DATE_LEN] = (DAU_SOURCE_FAULT == source) ? dau_ctrl.fault_power : dau_ctrl.reg_power;
uint32_t *power = (DAU_SOURCE_FAULT == source) ? dau_ctrl.fault_elec : dau_ctrl.reg_elec;
uint8_t ch = 0;
uint16_t i = 0;
uint64_t square_sum = 0;
int32_t mean = 0;
float temp = 0;
/* 遍历通道, 计算有效值 */
for(ch = 0; ch < DAU_PORT_POWER_CNT; ch++)
{
/* 计算所有值的算术平均值 */
mean = 0;
for(i = 0; i < DAU_POWER_DATE_LEN; i++)
{
mean += val[ch][i];
}
mean = mean / DAU_POWER_DATE_LEN;
vty_print("#DP%d %d", ch, mean);
/* 遍历通道所有值, 求和, 并计算出最大值和最小值. */
square_sum = 0;
for(i = 0; i < DAU_POWER_DATE_LEN; i++)
{
val[ch][i] -= mean;
square_sum += val[ch][i] * val[ch][i];
}
/* 根据数据查找数据落在哪个分段点上. */
temp = (double)sqrt(square_sum / DAU_POWER_DATE_LEN);
/* 根据分段点计算有效值. */
if (ch < 4)
{
power[ch] = (uint32_t)(temp * 800000 / dev_config.power_adj[ch]);
}
else
{
power[ch] = (uint32_t)(temp * 12000000 / dev_config.power_adj[ch]);
}
vty_print(" %f %d %d\r\n", temp, dev_config.power_adj[ch], power[ch]);
}
if (DAU_SOURCE_REG == source)
{
/* 固定前 4 个通道是接地电流, 判断接地电流有没有突变 */
for(ch = 0; ch < DAU_PORT_GROUND_CNT; ch++)
{
/* 判断工频录波上传阈值 */
if (abs_cal_u(power[ch], fd_data.elec[ch]) >= (uint32_t)dev_config.power_threshold * 10)
{
MONITOR_BITMAP_SET(dau_ctrl.col_flag, DAU_COL_FLAG_REG_POWER);
break;
}
}
if (DAU_PORT_GROUND_CNT == ch)
{
/* 没有超过阈值, 不传输波形 */
MONITOR_BITMAP_RESET(dau_ctrl.col_flag, DAU_COL_FLAG_REG_POWER);
}
if (IS_MONITOR_BIT_SET(dau_ctrl.col_flag, DAU_COL_FLAG_WAVE_FORCE))
{
/* 强制录波, 传输波形 */
MONITOR_BITMAP_SET(dau_ctrl.col_flag, DAU_COL_FLAG_REG_POWER);
MONITOR_BITMAP_RESET(dau_ctrl.col_flag, DAU_COL_FLAG_WAVE_FORCE);
}
}
/* 计算工频录波每个点的电流值 */
if (DAU_SOURCE_FAULT == source
|| IS_MONITOR_BIT_SET(dau_ctrl.col_flag, DAU_COL_FLAG_REG_POWER))
{
for(ch = 0; ch < DAU_PORT_POWER_CNT; ch++)
{
for(i = 0; i < DAU_POWER_DATE_LEN; i++)
{
if (ch < 4)
{
val[ch][i] = val[ch][i] * 8000 / dev_config.power_adj_point[ch];
}
else
{
val[ch][i] = val[ch][i] * 12000 / dev_config.power_adj_point[ch];
}
}
}
}
}
/* description: 故障触发波形采集
param:
return: HAL_xxx */
int32_t _dau_wave_col_trigger_by_fault(void)
{
int32_t rv = HAL_ERROR;
/* 上次触发没有完成直接退出 */
if (!IS_MONITOR_BIT_SET(dau_ctrl.col_flag, DAU_COL_FLAG_FAULT_CMP))
{
return HAL_OK;
}
/* 没有触发直接退出 */
if (!dau_ctrl.is_fault)
{
return HAL_OK;
}
dau_ctrl.is_fault = FALSE;
dau_ctrl.fault_port = (dau_ctrl.reg_global.GFTR & DAU_GFTR_PORT_Msk) >> DAU_GFTR_PORT_Pos;
flash_log_write(FLASH_LOG_TYPE_WARNING, "Fhault triggering port %d!\r\n", dau_ctrl.fault_port);
/* 采集波形 */
E_RETURN(_dau_wave_col_fault());
E_RETURN(_dau_wave_col_power(DAU_SOURCE_FAULT));
_dau_power_calculate(DAU_SOURCE_FAULT);
/* 置标志位 */
MONITOR_BITMAP_RESET(dau_ctrl.col_flag, DAU_COL_FLAG_FAULT_CMP);
_dau_data_save();
#if 0
uint16_t *buf = (uint16_t*)(&dau_ctrl.buf_dau_rx[2]);
uint8_t i = 0;
uint8_t j = 0;
uint16_t k = 0;
uint32_t addr = dau_ctrl.addr_fault;
for(i = 0; i < 1; i++)
{
common_watchdog_set(COM_WDG_DAU);
vty_print("FAULT %x %d\r\n", addr, i);
//for(j = 0; j < DAU_PKT_FAULT_CNT; j++)
for(j = 0; j < 1; j++)
{
spi_flash_read(addr, &dau_ctrl.buf_dau_rx[2], 1024);
addr += DAU_PKT_FAULT_BYTE_CNT;
for(k = 0; k < 512;)
{
common_watchdog_set(COM_WDG_DAU);
vty_print("%04x ", buf[k++]);
if(0 == k % 32)
{
osDelay(100);
vty_print("\r\n");
}
}
if(k % 32 != 0)
{
osDelay(100);
vty_print("\r\n");
}
}
vty_print("\r\n");
}
#endif
#if 0
uint16_t *buf = NULL;
uint8_t i = 0;
uint8_t j = 0;
uint16_t k = 0;
for(i = 0; i < DAU_PORT_POWER_CNT; i++)
{
common_watchdog_set(COM_WDG_DAU);
vty_print("POWER %d\r\n", i);
buf = (uint16_t*)dau_ctrl.fault_power[i];
for(j = 0; j < DAU_PKT_POWER_CNT; j++)
{
for(k = 0; k < 512;)
{
vty_print("%-04x ", buf[k++]);
if(0 == (j*512+k ) % 40)
{
osDelay(100);
vty_print("\r\n");
}
}
buf += 512;
}
vty_print("\r\n");
}
#endif
return HAL_OK;
}
/* description: 寄存器触发波形采集
param:
return: HAL_xxx */
int32_t _dau_wave_col_trigger_by_reg(void)
{
uint32_t tick = 0;
int32_t rv = HAL_ERROR;
/* 上次触发没有完成直接退出 */
if (!IS_MONITOR_BIT_SET(dau_ctrl.col_flag, DAU_COL_FLAG_REG_CMP))
{
return HAL_OK;
}
/* 定时开始采集 */
tick = HAL_GetTick();
if ((tick - dau_ctrl.col_time) < (dev_config.collect_interval * 60000)
&& !IS_MONITOR_BIT_SET(dau_ctrl.col_flag, DAU_COL_FLAG_WAVE_FORCE))
{
return HAL_OK;
}
E_RETURN(_dau_wave_col_start());
E_RETURN(_dau_wave_col_defect());
E_RETURN(_dau_wave_col_power(DAU_SOURCE_REG));
_dau_power_calculate(DAU_SOURCE_REG);
/* 置标志位, 保存数据 */
MONITOR_BITMAP_RESET(dau_ctrl.col_flag, DAU_COL_FLAG_REG_CMP);
dau_ctrl.col_time = tick;
_dau_data_save();
#if 0
int16_t *buf = (int16_t*)(&dau_ctrl.buf_dau_rx[2]);
uint32_t addr = dau_ctrl.addr_reg;
uint32_t cnt = 0;
uint8_t i = 0;
uint8_t j = 0;
uint16_t k = 0;
for(i = 0; i < DAU_PORT_DEFECT_CNT; i++)
//for(i = 0; i < 1; i++)
{
vty_print("DEFECT %x %d\r\n", addr, i);
for(j = 0; j < DAU_PKT_DEFECT_CNT; j++)
{
spi_flash_read(addr, &dau_ctrl.buf_dau_rx[2], 1024);
addr += DAU_PKT_DEFECT_BYTE_CNT;
common_watchdog_set(COM_WDG_DAU);
for(k = 0; k < 512; k++)
{
if (buf[k] > 0)
{
cnt++;
}
if (j != 0 || k >= 128)
{
continue;
}
vty_print("%04d ", buf[k]);
if(0 == k % 32)
{
osDelay(100);
vty_print("\r\n");
}
}
if(k % 32 != 0)
{
osDelay(100);
vty_print("\r\n");
}
}
vty_print("%d\r\n", cnt);
cnt = 0;
}
#endif
#if 0
uint16_t *buf = (uint16_t*)(&dau_ctrl.buf_dau_rx[2]);
uint8_t i = 0;
uint8_t j = 0;
uint16_t k = 0;
//for(i = 5; i < DAU_PORT_POWER_CNT; i++)
for(i = 5; i < 6; i++)
{
common_watchdog_set(COM_WDG_DAU);
vty_print("POWER %d\r\n", i);
buf = (uint16_t*)dau_ctrl.reg_power[i];
for(j = 0; j < DAU_PKT_POWER_CNT; j++)
{
for(k = 0; k < 512;)
{
vty_print("%-04x ", buf[k++]);
if(0 == (j*512+k ) % 40)
{
osDelay(100);
vty_print("\r\n");
}
}
buf += 512;
}
vty_print("\r\n");
}
#endif
return rv;
}
/* description: DAU 初始化
param:
return: */
static void _dau_init(void)
{
uint16_t *temp = (uint16_t*)&dau_ctrl.buf_dau_tx[2];
char version[DEV_COMPILE_TIME_LEN] = {0};
uint8_t i = 0;
dau_ctrl.spi = &hspi1;
if (st_data.addr_fault >= WARE_FAULT_ADDRESS && st_data.addr_fault < WARE_FAULT_ADDRESS_END
&& 0 == (st_data.addr_fault & 0x1ffff))
{
dau_ctrl.addr_fault = st_data.addr_fault;
}
else
{
dau_ctrl.addr_fault = WARE_FAULT_ADDRESS;
}
vty_print("#D fault addr %x %x\r\n", st_data.addr_fault, dau_ctrl.addr_fault);
if (st_data.addr_reg >= WARE_REG_ADDRESS && st_data.addr_reg < WARE_REG_ADDRESS_END
&& 0 == (st_data.addr_reg & 0x1ffff))
{
dau_ctrl.addr_reg = st_data.addr_reg;
}
else
{
dau_ctrl.addr_reg = WARE_REG_ADDRESS;
}
vty_print("#D reg addr %x %x\r\n", st_data.addr_reg, dau_ctrl.addr_reg);
/* 开启第一次采集前, 默认上传完成 */
dau_ctrl.col_time = 600000;
MONITOR_BITMAP_SET(dau_ctrl.col_flag, DAU_COL_FLAG_FAULT_CMP);
MONITOR_BITMAP_SET(dau_ctrl.col_flag, DAU_COL_FLAG_REG_CMP);
HAL_GPIO_WritePin(DAU_RST_GPIO_Port, DAU_RST_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(POWER_DAU_GPIO_Port, POWER_DAU_Pin, GPIO_PIN_SET);
osDelay(2000);
/* 读取 FPGA 版本信息 */
if (HAL_OK == _dau_reg_read_global_state())
{
snprintf(version, DEV_COMPILE_TIME_LEN, "%d.%d", dau_ctrl.reg_global.GSVR >> 8, dau_ctrl.reg_global.GSVR & 0xff);
if (strncmp((char*)dev_info.FPGA_version, version, DEV_COMPILE_TIME_LEN - 1) != 0)
{
strncpy((char*)dev_info.FPGA_version, version, DEV_COMPILE_TIME_LEN - 1);
common_sys_set(COM_SYS_SAVE_INFO, 0);
}
}
if (!IS_MONITOR_BIT_SET(dev_config.flag, DEV_FLAG_ADJ))
{
/* 配置校准系数, 缺陷和故障因为都是 3 路, 统一使用一个寄存器组. */
for(i = 0; i < DAU_PORT_DEFECT_CNT; i++)
{
_dau_reg_write_port(i);
}
/* 故障触发配置 */
_dau_reg_write_cfg();
osDelay(500);
/* 开启 */
*temp = 1;
_dau_reg_write(0x0209, sizeof(uint16_t));
}
}
/* description: DAU 主任务循环
param:
return: */
static void _dau_start(void *argument)
{
uint16_t *temp = (uint16_t*)&dau_ctrl.buf_dau_tx[2];
int32_t rv = HAL_ERROR;
/* 等待完成首次 ADC 采样 */
while(1)
{
if (IS_MONITOR_BIT_SET(system_init_flag, SYS_INIT_ADC))
{
break;
}
osDelay(200);
}
osDelay(2000);
/* 状态初始化 */
_dau_init();
vty_print("DAU start...\r\n");
for (;;)
{
common_watchdog_set(COM_WDG_DAU);
osDelay(250);
/* 读取全局状态寄存器 */
rv = _dau_reg_read_global_state();
if (rv != HAL_OK)
{
continue;
}
/* utc 对时处理 */
_dau_utc();
/* 故障电流采集 */
_dau_wave_col_trigger_by_fault();
/* 循环工频缺陷电流采集 */
_dau_wave_col_trigger_by_reg();
/* 处理升级 */
if (dau_ctrl.update_flag)
{
flash_log_write(FLASH_LOG_TYPE_NOTIFY, "FPGA update start!\r\n");
dau_ctrl.update_flag = FALSE;
if (HAL_OK == _dau_update())
{
dau_ctrl.update_rt = DAU_UPD_OK;
dau_ctrl.update_rt_dbg = DAU_UPD_OK;
}
else
{
dau_ctrl.update_rt = DAU_UPD_ERROR;
dau_ctrl.update_rt_dbg = DAU_UPD_ERROR;
}
flash_log_write(FLASH_LOG_TYPE_NOTIFY, "FPGA update %s!\r\n", dau_ctrl.update_rt == 1 ? "OK" : "ERROR");
}
/* FPGA 配置下发 */
if (IS_MONITOR_BIT_SET(dau_ctrl.reg_flag, DAU_REG_PORT_WRITE))
{
MONITOR_BITMAP_RESET(dau_ctrl.reg_flag, DAU_REG_PORT_WRITE);
_dau_reg_write_cfg();
}
/* 命令行 FPGA 寄存器读写操作 */
if (1 == _dau_spi_rw)
{
dbg_cmd_hander(DBG_CMD_ON, DBG_M_DAU_TXRX);
_dau_spi_rw = 0;
_dau_reg_read(_dau_spi_addr, _dau_spi_len << 1);
dbg_cmd_hander(DBG_CMD_OFF, DBG_M_DAU_TXRX);
}
else if(2 == _dau_spi_rw)
{
dbg_cmd_hander(DBG_CMD_ON, DBG_M_DAU_TXRX);
*temp = _dau_spi_len;
_dau_spi_rw = 0;
_dau_reg_write(_dau_spi_addr, 2);
dbg_cmd_hander(DBG_CMD_OFF, DBG_M_DAU_TXRX);
}
}
}
/* description: DAU 写端口配置寄存器报文发送
param:
return: HAL_xxx */
int32_t _dau_adj_reg_write_port(uint32_t port)
{
uint16_t *temp = (uint16_t*)&dau_ctrl.buf_dau_tx[2];
uint16_t addr = 0;
int32_t rv = HAL_ERROR;
/* 缺陷校准系数 */
addr = (port + 1) * DAU_REG_ADDR_PORT_BASE + DAU_REG_ADDR_PORT_DEFECT_BASE;
*temp = 0;
E_RETURN(_dau_reg_write(addr, sizeof(uint16_t)));
addr = (port + 1) * DAU_REG_ADDR_PORT_BASE + DAU_REG_ADDR_PORT_DEFECT_ADJ;
*temp = 32768;
E_RETURN(_dau_reg_write(addr, sizeof(uint16_t)));
/* 故障校准系数 */
addr = (port + 1) * DAU_REG_ADDR_PORT_BASE + DAU_REG_ADDR_PORT_FAULT_BASE;
*temp = 0;
E_RETURN(_dau_reg_write(addr, sizeof(uint16_t)));
addr = (port + 1) * DAU_REG_ADDR_PORT_BASE + DAU_REG_ADDR_PORT_FAULT_ADJ;
*temp = 32768;
E_RETURN(_dau_reg_write(addr, sizeof(uint16_t)));
return rv;
}
/* description: 缺陷波形采集
param:
return: HAL_xxx */
int32_t _dau_adj_wave_col_defect(void)
{
uint16_t *reg = (uint16_t*)&dau_ctrl.buf_dau_tx[2];
int16_t *data = (int16_t*)&dau_ctrl.buf_dau_rx[2];
uint8_t i = 0;
uint8_t j = 0;
uint16_t k = 0;
uint32_t mean = 0;
int32_t rv = HAL_ERROR;
/* 比较缺陷波形是否超过阈值 */
E_RETURN(_dau_reg_read_port_state());
vty_print("#D defect max");
for(i = 0; i < DAU_PORT_DEFECT_CNT; i++)
{
dau_ctrl.reg_defect_max[i] = abs(dau_ctrl.reg_port_state.DMAX[i]);
vty_print(" %d", dau_ctrl.reg_defect_max[i]);
vty_print(" %d ", dau_ctrl.reg_port_state.DAVR[i]);
}
vty_print("\r\n");
/* 读取缺陷数据 */
for(i = 0; i < DAU_PORT_DEFECT_CNT; i++)
{
/* 请求读取缺陷波形 */
*reg = DAU_GCRTR_DEFECT_WAVE_Msk | (i << DAU_GCRTR_PORT_Pos);
E_RETURN(_dau_reg_write(DAU_REG_ADDR_GCRTR, sizeof(uint16_t)));
/* 等待 DAU 准备缺陷数据 */
j = 0;
while(1)
{
if (j >= DAU_WAVE_WAIT_MAX)
{
DBG(DBG_M_DAU, "DAU defect wave err\r\n", rv);
return HAL_TIMEOUT;
}
osDelay(5);
E_RETURN(_dau_reg_read_global_state());
if ((dau_ctrl.reg_global.GRTR & DAU_GRTR_DEFECT_WAVE_Msk) >> DAU_GRTR_DEFECT_WAVE_Pos)
{
break;
}
j++;
vty_print("#D reg d wait %d\r\n", j);
}
mean = 0;
for(j = 0; j < DAU_PKT_DEFECT_CNT; j++)
{
E_RETURN(_dau_reg_read(DAU_REG_ADDR_PPWR, DAU_PKT_DEFECT_BYTE_CNT));
for(k = 0; k < 512; k++)
{
mean += abs(data[k]);
}
}
mean = mean / 20480;
dau_ctrl.reg_defect_max[i] = mean;
}
/* 直接返回 */
MONITOR_BITMAP_RESET(dau_ctrl.col_flag, DAU_COL_FLAG_REG_DEFECT);
return HAL_OK;
}
/* description: 寄存器触发波形采集
param:
return: HAL_xxx */
int32_t _dau_adj_wave_col_trigger_by_reg(void)
{
int32_t rv = HAL_ERROR;
E_RETURN(_dau_wave_col_start());
E_RETURN(_dau_adj_wave_col_defect());
E_RETURN(_dau_wave_col_power(DAU_SOURCE_REG));
return rv;
}
/* description: DAU 校准任务循环
param:
return: */
static void _dau_adj_start(void *argument)
{
uint16_t *temp = (uint16_t*)&dau_ctrl.buf_dau_tx[2];
uint8_t i = 0;
/* 状态初始化 */
_dau_init();
for (;;)
{
if (DAU_ADJ_STATE_POWER == dau_adj_state)
{
_dau_adj_wave_col_trigger_by_reg();
dau_adj_state = DAU_ADJ_STATE_NONE;
}
else if(DAU_ADJ_STATE_DEFECT_ZERO == dau_adj_state
|| DAU_ADJ_STATE_DEFECT == dau_adj_state)
{
for(i = 0; i < DAU_PORT_DEFECT_CNT; i++)
{
_dau_adj_reg_write_port(i);
}
osDelay(5000);
_dau_reg_read_port_state();
dau_adj_state = DAU_ADJ_STATE_NONE;
}
else if(DAU_ADJ_STATE_FAULT_ZERO == dau_adj_state)
{
/* 恢复初始值 */
for(i = 0; i < DAU_PORT_DEFECT_CNT; i++)
{
_dau_adj_reg_write_port(i);
}
osDelay(5000);
/* 采集平均值 */
_dau_reg_read_port_state();
/* 下发零点采样值 */
for(i = 0; i < DAU_PORT_FAULT_CNT; i++)
{
if (!IS_MONITOR_BIT_SET(debug_adj_fault.bitmap, i))
{
continue;
}
dev_config.fault_base[i] = dau_ctrl.reg_port_state.FAVR[i];
}
/* 重启 FPGA 触发故障采集 */
HAL_GPIO_WritePin(POWER_DAU_GPIO_Port, POWER_DAU_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(DAU_RST_GPIO_Port, DAU_RST_Pin, GPIO_PIN_RESET);
osDelay(1000);
HAL_GPIO_WritePin(DAU_RST_GPIO_Port, DAU_RST_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(POWER_DAU_GPIO_Port, POWER_DAU_Pin, GPIO_PIN_SET);
osDelay(2000);
for(i = 0; i < DAU_PORT_FAULT_CNT; i++)
{
_dau_reg_write_port(i);
}
/* 触发阈值 */
*temp = 0x800;
_dau_reg_write(DAU_REG_ADDR_GCFTTR, sizeof(uint16_t));
/* 开启 */
osDelay(500);
*temp = 1;
_dau_reg_write(0x0209, sizeof(uint16_t));
dau_adj_state = DAU_ADJ_STATE_NONE;
}
else if(DAU_ADJ_STATE_FAULT == dau_adj_state)
{
osDelay(5000);
/* 读取全局寄存器判断故障是否被触发. */
_dau_reg_read_global_state();
/* 读取最大值. */
_dau_reg_read_port_state();
/* 关闭触发 */
osDelay(500);
*temp = 0;
_dau_reg_write(0x0209, sizeof(uint16_t));
dau_adj_state = DAU_ADJ_STATE_NONE;
}
else
{
osDelay(1000);
common_watchdog_set(COM_WDG_DAU);
}
}
}
/* description: 故障波形采集
param:
return: HAL_xxx */
int32_t _dau_continue_wave_col_fault(void)
{
uint8_t i = 0;
int32_t temp = 0;
int32_t rv = HAL_ERROR;
dau_ctrl.fault_utc = dau_ctrl.reg_global.GFTUR;
dau_ctrl.fault_ns = dau_ctrl.reg_global.GFTNR;
dau_ctrl.fault_utc_max = dau_ctrl.reg_global.GFMUR;
dau_ctrl.fault_ns_max = dau_ctrl.reg_global.GFMNR;
dau_ctrl.PPS_cnt = dau_ctrl.reg_global.GGPCR;
vty_print("#D utc %d.%d %d %d\r\n", dau_ctrl.fault_utc, dau_ctrl.fault_ns, dau_ctrl.PPS_cnt, dev_config.fault_time_adj);
dau_ctrl.fault_ns = (uint64_t)dau_ctrl.fault_ns * 100000000 / dau_ctrl.PPS_cnt;
vty_print(" #D %d ", dau_ctrl.fault_ns);
dau_ctrl.fault_ns += dev_config.fault_time_adj;
vty_print("%d\r\n", dau_ctrl.fault_ns);
/* 读取触发电流值 */
E_RETURN(_dau_reg_read_port_state());
/* 读取故障数据 */
for(i = 0; i < DAU_PORT_FAULT_CNT; i++)
{
temp = dau_ctrl.reg_port_state.FMAX[i] - dev_config.fault_base[i];
dau_ctrl.fault_max[i] = dev_config.fault_adj[i] * temp / 32768 / 16 * 3;
vty_print("#DF %d %d %d\r\n", dau_ctrl.fault_max[i], dau_ctrl.reg_port_state.FMAX[i], temp);
}
return HAL_OK;
}
/* description: 故障触发波形采集
param:
return: HAL_xxx */
int32_t _dau_continue_wave_col_trigger_by_fault(void)
{
int32_t rv = HAL_ERROR;
/* 没有触发直接退出 */
if (!dau_ctrl.is_fault)
{
return HAL_OK;
}
/* 采集波形 */
dau_ctrl.is_fault = FALSE;
dau_ctrl.fault_port = (dau_ctrl.reg_global.GFTR & DAU_GFTR_PORT_Msk) >> DAU_GFTR_PORT_Pos;
E_RETURN(_dau_continue_wave_col_fault());
E_RETURN(_dau_wave_col_power(DAU_SOURCE_FAULT));
_dau_power_calculate(DAU_SOURCE_FAULT);
return HAL_OK;
}
/* description: DAU 主任务循环
param:
return: */
static void _dau_continue_start(void *argument)
{
uint16_t *temp = (uint16_t*)&dau_ctrl.buf_dau_tx[2];
int32_t rv = HAL_ERROR;
/* 状态初始化 */
_dau_init();
vty_print("DAU start...\r\n");
for (;;)
{
common_watchdog_set(COM_WDG_DAU);
osDelay(4250);
/* 读取全局状态寄存器 */
rv = _dau_reg_read_global_state();
if (rv != HAL_OK)
{
continue;
}
/* utc 对时处理 */
_dau_utc();
/* 故障电流采集 */
_dau_continue_wave_col_trigger_by_fault();
/* 循环工频缺陷电流采集 */
_dau_adj_wave_col_trigger_by_reg();
_dau_power_calculate(DAU_SOURCE_REG);
/* 处理升级 */
if (dau_ctrl.update_flag)
{
flash_log_write(FLASH_LOG_TYPE_NOTIFY, "FPGA update start!\r\n");
dau_ctrl.update_flag = FALSE;
if (HAL_OK == _dau_update())
{
dau_ctrl.update_rt = DAU_UPD_OK;
dau_ctrl.update_rt_dbg = DAU_UPD_OK;
}
else
{
dau_ctrl.update_rt = DAU_UPD_ERROR;
dau_ctrl.update_rt_dbg = DAU_UPD_ERROR;
}
flash_log_write(FLASH_LOG_TYPE_NOTIFY, "FPGA update %s!\r\n", dau_ctrl.update_rt == 1 ? "OK" : "ERROR");
}
if (IS_MONITOR_BIT_SET(dau_ctrl.reg_flag, DAU_REG_PORT_WRITE))
{
MONITOR_BITMAP_RESET(dau_ctrl.reg_flag, DAU_REG_PORT_WRITE);
_dau_reg_write_cfg();
}
/* 命令行 FPGA 寄存器读写操作 */
if (1 == _dau_spi_rw)
{
dbg_cmd_hander(DBG_CMD_ON, DBG_M_DAU_TXRX);
_dau_spi_rw = 0;
_dau_reg_read(_dau_spi_addr, _dau_spi_len << 1);
dbg_cmd_hander(DBG_CMD_OFF, DBG_M_DAU_TXRX);
}
else if(2 == _dau_spi_rw)
{
dbg_cmd_hander(DBG_CMD_ON, DBG_M_DAU_TXRX);
*temp = _dau_spi_len;
_dau_spi_rw = 0;
_dau_reg_write(_dau_spi_addr, 2);
dbg_cmd_hander(DBG_CMD_OFF, DBG_M_DAU_TXRX);
}
}
}
/* description: GPS 报文处理 ($GNZDA,235949.012,05,01,1980,,*4F)
param:
return: */
static int32_t _dau_gps_process(void)
{
char *pkt = (char*)dau_ctrl.buf_gps;
uint8_t GB_cnt = 0;
uint8_t n = 0;
uint16_t i = 0;
uint32_t hour = 0;
uint32_t min = 0;
uint32_t sec = 0;
uint32_t day = 0;
uint32_t mon = 0;
uint32_t year = 0;
uint32_t ms = 0;
/* 遍历字符串 */
while(pkt[i])
{
if (pkt[i] != '$')
{
i++;
continue;
}
/* 查找对时字符串 "$GNZDA" */
if (0 == strncmp(&pkt[i], "$GBGSV", 6))
{
i++;
GB_cnt++;
continue;
}
/* 查找对时字符串 "$GNZDA" */
if (strncmp(&pkt[i], "$GNZDA", 6) != 0)
{
i++;
continue;
}
/* 查找时分秒日月年 */
n = sscanf(&pkt[i], "$GNZDA,%02d%02d%02d.%d,%02d,%02d,%04d", &hour, &min, &sec, &ms, &day, &mon, &year);
if (n != 7)
{
return HAL_ERROR;
}
DBG(DBG_M_GPS, "%d/%d/%d %d:%d:%d\r\n", year, mon, day, hour, min, sec);
/* 小于 2024 说明对时不成功. */
if (year < 2024)
{
return HAL_ERROR;
}
_dau_tm.tm_year = year - 1900;
_dau_tm.tm_mon = mon - 1;
_dau_tm.tm_mday = day;
_dau_tm.tm_hour = hour;
_dau_tm.tm_min = min;
_dau_tm.tm_sec = sec;
dau_ctrl.utc = mktime(&_dau_tm);
rtc_time_set(dau_ctrl.utc);
dau_ctrl.GB_cnt = GB_cnt;
return HAL_OK;
}
return HAL_ERROR;
}
/* description: GPS 初始化
param:
return: */
static void _dau_gps_init(void)
{
dau_ctrl.uart = &huart2;
HAL_GPIO_WritePin(POWER_GPS_GPIO_Port, POWER_GPS_Pin, GPIO_PIN_SET);
osDelay(1000);
HAL_GPIO_WritePin(GPS_RST_GPIO_Port, GPS_RST_Pin, GPIO_PIN_RESET);
osDelay(100);
HAL_GPIO_WritePin(GPS_RST_GPIO_Port, GPS_RST_Pin, GPIO_PIN_SET);
}
/* description: GPS 主任务循环
param:
return: */
static void _dau_gps_start(void *argument)
{
uint32_t notify_value = 0xff;
uint32_t err_cnt = 5;
/* 等待完成首次 ADC 采样 */
while(1)
{
if (IS_MONITOR_BIT_SET(system_init_flag, SYS_INIT_ADC))
{
break;
}
osDelay(200);
}
osDelay(1000);
/* 状态初始化 */
_dau_gps_init();
for (;;)
{
/* 连续 5 次失败才认为对时失败 */
dau_ctrl.is_utc_ok = (err_cnt < 5);
common_watchdog_set(COM_WDG_GPS);
/* 开启串口空闲中断收包 */
if (HAL_OK == HAL_UARTEx_ReceiveToIdle_DMA(dau_ctrl.uart, dau_ctrl.buf_gps, DAU_GPS_BUF_LEN))
{
dau_ctrl.len_buf_gps = 0;
dau_ctrl.is_half_buf_gps = FALSE;
}
/* 等待收包完成. */
notify_value = ulTaskNotifyTake(pdTRUE, 10000);
if (0 == notify_value)
{
/* 收包超时 */
dau_ctrl.is_utc_valid = FALSE;
err_cnt++;
continue;
}
DBG(DBG_M_GPS, "Len %d\r\n", dau_ctrl.len_buf_gps);
/* 命令过长. */
if (dau_ctrl.len_buf_gps >= DAU_GPS_BUF_LEN)
{
dau_ctrl.is_utc_valid = FALSE;
err_cnt++;
continue;
}
/* 字符串结束标志 */
dau_ctrl.buf_gps[dau_ctrl.len_buf_gps] = 0;
if (HAL_OK == _dau_gps_process())
{
dau_ctrl.is_utc_valid = TRUE;
err_cnt = 0;
}
else
{
dau_ctrl.is_utc_valid = FALSE;
err_cnt++;
}
}
}
/* Interface functions -------------------------------------------------------*/
/* description: DAU 采集任务初始化
param:
return: */
void dau_init(void)
{
if (IS_MONITOR_BIT_SET(dev_config.flag, DEV_FLAG_ADJ))
{
dau_ctrl.dau_handle = osThreadNew(_dau_adj_start, NULL, &dau_adj_attributes);
}
else if(IS_MONITOR_BIT_SET(dev_config.flag, DEV_FLAG_FACTORY))
{
dau_ctrl.dau_handle = osThreadNew(_dau_continue_start, NULL, &dau_adj_attributes);
}
else
{
/* 初始化 DAU 任务. */
dau_ctrl.dau_handle = osThreadNew(_dau_start, NULL, &dau_attributes);
}
dau_ctrl.gps_handle = osThreadNew(_dau_gps_start, NULL, &dau_gps_attributes);
}
/* description: spi 接口测试函数
param:
return: */
void dau_spi_rw(int8_t rw, uint16_t addr, uint16_t len)
{
_dau_spi_rw = rw;
_dau_spi_addr = addr;
_dau_spi_len = len;
}
/* description: dau 显示接口
param:
return: */
void dau_show(void)
{
struct tm *day = NULL;
uint32_t utc = dau_ctrl.utc;
vty_print("state: %d GB: %d\r\n", dau_ctrl.is_utc_ok, dau_ctrl.GB_cnt);
if (dau_ctrl.is_utc_valid)
{
utc += 28800;
day = localtime(&utc);
vty_print("date: %d/%d/%d %d:%d:%d\r\n", day->tm_year - 100, day->tm_mon + 1, day->tm_mday,
day->tm_hour, day->tm_min, day->tm_sec);
}
vty_print("\n");
/* DAU 全局寄存器. */
vty_print("Global state reg\r\n");
vty_print("0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n");
vty_print("%04x %04x %04x %04x ", dau_ctrl.reg_global.GSCR, dau_ctrl.reg_global.GSVR, dau_ctrl.reg_global.GSR, dau_ctrl.reg_global.GFTR);
vty_print("%04x %04x ", dau_ctrl.reg_global.GFTUR & 0xffff, (dau_ctrl.reg_global.GFTUR >> 16) & 0xffff);
vty_print("%04x %04x ", dau_ctrl.reg_global.GFTNR & 0xffff, (dau_ctrl.reg_global.GFTNR >> 16) & 0xffff);
vty_print("%04x %04x ", dau_ctrl.reg_global.GRTR, dau_ctrl.reg_global.reserve);
vty_print("%04x %04x ", dau_ctrl.reg_global.GUR & 0xffff, (dau_ctrl.reg_global.GUR >> 16) & 0xffff);
vty_print("%04x %04x\r\n\n", dau_ctrl.reg_global.GNR & 0xffff, (dau_ctrl.reg_global.GNR >> 16) & 0xffff);
}
/* description: dau 显示接口
param:
return: */
void dau_adj_show(void)
{
uint8_t i = 0;
vty_print("Vin: %d\r\n\n", dev_config.vin_adj);
vty_print("POWER\r\nCH C CP\r\n");
for(i = 0; i < DAU_PORT_POWER_CNT - 1; i++)
{
vty_print("%-02d %-05d %-05d\r\n", i + 1, dev_config.power_adj[i], dev_config.power_adj_point[i]);
}
vty_print("\n");
vty_print("DEFECT\r\nCH C CP\r\n");
for(i = 0; i < DAU_PORT_DEFECT_CNT; i++)
{
vty_print("%-02d %-05d %-05d\r\n", i + 1, dev_config.defect_base[i], dev_config.defect_adj[i]);
}
vty_print("\n");
vty_print("FAULT\r\nCH C CP\r\n");
for(i = 0; i < DAU_PORT_FAULT_CNT; i++)
{
vty_print("%-02d %-05d %-05d\r\n", i + 1, dev_config.fault_base[i], dev_config.fault_adj[i]);
}
vty_print("\n");
}
/******************* (C) COPYRIGHT LandPower ***** END OF FILE ****************/