From a0e6a2758cf7e46bf5175427b1c7b22b0d32c0a8 Mon Sep 17 00:00:00 2001 From: wangbo Date: Mon, 28 Jul 2025 09:11:31 +0000 Subject: [PATCH] =?UTF-8?q?ADD=201.=E4=BC=98=E5=8C=96modbus=E5=8D=8F?= =?UTF-8?q?=E8=AE=AE;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/include/common.h | 2 + app/include/dbg.h | 2 + app/include/file_fifo.h | 72 +++++ app/include/hwgpio.h | 13 + app/include/pd_csg.h | 56 +++- app/include/pd_modbus.h | 28 +- app/lib/a_process/pd_csg.c | 539 ++++++++++++++++++++++++++++++- app/lib/a_process/pd_main.c | 1 + app/lib/a_process/pd_modbus.c | 101 +++++- app/lib/m_management/dbg.c | 6 +- app/lib/m_management/file_fifo.c | 243 ++++++++++++++ app/lib/z_hardware/hwgpio.c | 58 ++++ 12 files changed, 1087 insertions(+), 34 deletions(-) create mode 100755 app/include/file_fifo.h create mode 100755 app/lib/m_management/file_fifo.c diff --git a/app/include/common.h b/app/include/common.h index 9212e45..3818295 100755 --- a/app/include/common.h +++ b/app/include/common.h @@ -65,6 +65,8 @@ #define E_NOT_IDENTIFY -7 #define E_TIMEOUT -8 #define E_SAME -9 +#define E_EMPTY -10 +#define E_FULL -11 #define OUT diff --git a/app/include/dbg.h b/app/include/dbg.h index efad35c..80dff38 100755 --- a/app/include/dbg.h +++ b/app/include/dbg.h @@ -71,6 +71,8 @@ typedef enum DBG_M_SERIAL, DBG_M_PD_MODBUS, DBG_M_PD_MODBUS_ERR, + DBG_M_FILE_FIFO, + DBG_M_FILE_FIFO_ERR, DBG_M_COUNT } DBG_MODULE_E; diff --git a/app/include/file_fifo.h b/app/include/file_fifo.h new file mode 100755 index 0000000..e10ac64 --- /dev/null +++ b/app/include/file_fifo.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * file include/file_fifo.h + * author YuLiang + * version 1.0.0 + * date 10-Jun-2025 + * brief This file provides all the headers of the file fifo functions. + + ****************************************************************************** + * Attention + * + *

© COPYRIGHT(c) 2025 LandPower

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of LandPower nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +#ifndef _FILE_FIFO_H_ +#define _FILE_FIFO_H_ + +/* Includes ------------------------------------------------------------------*/ + +/* Define --------------------------------------------------------------------*/ +#define FILE_FIFO_PATH_LEN 256 + +/* Exported types ------------------------------------------------------------*/ +/* 配置文件结构体 */ +typedef struct +{ + char dir[FILE_FIFO_PATH_LEN]; // 目录路径 + int32_t files_max; // 存储最大文件数量 + int64_t index_min; // 目录当前最小索引 + int64_t index_max; // 目录当前最大索引, 该索引为下次下入的文件名 +} file_fifo_t; + +typedef struct +{ + uint32_t len; + char *content; +} fifo_arr; + +/* Exported macro ------------------------------------------------------------*/ + +/* Extern global variables ---------------------------------------------------*/ + +/* Extern functions ----------------------------------------------------------*/ +extern int32_t file_fifo_write(file_fifo_t *config, const char *content, int32_t len); +extern int32_t file_fifo_read(file_fifo_t *config, char *content, int32_t *len); +extern void file_fifo_delete_by_min_index(file_fifo_t *config); +extern int32_t file_fifo_init(file_fifo_t *config); + +#endif +/************************ (C) COPYRIGHT LandPower ***** END OF FILE ****************/ diff --git a/app/include/hwgpio.h b/app/include/hwgpio.h index 7d9dc19..30de754 100755 --- a/app/include/hwgpio.h +++ b/app/include/hwgpio.h @@ -45,6 +45,12 @@ #define GPIO_WATCHDONG 915 #define GPIO_485_BUS 154 // GPIO4_D2 (4*32+3*8+2) +#define GPIO_DAU1 95 // GPIO2_D7 +#define GPIO_DAU2 18 // GPIO0_C2 +#define GPIO_DAU3 20 // GPIO0_C4 +#define GPIO_DAU4 14 // GPIO0_B6 +#define GPIO_DAU5 65 // GPIO2_A1 +#define GPIO_DAU6 81 // GPIO2_C1 /* Exported types ------------------------------------------------------------*/ /* 记录每个打开的gpio信息 */ @@ -59,9 +65,16 @@ typedef struct /* Exported macro ------------------------------------------------------------*/ #define GPIO_485BUS(_v_) gpio_val_set(gpio_485bus_idx, _v_) +#define GPIO_DAU1_VAL() gpio_val_get(gpio_dau1_idx) /* Extern global variables ---------------------------------------------------*/ extern int32_t gpio_485bus_idx; +extern int32_t gpio_dau1_idx; +extern int32_t gpio_dau2_idx; +extern int32_t gpio_dau3_idx; +extern int32_t gpio_dau4_idx; +extern int32_t gpio_dau5_idx; +extern int32_t gpio_dau6_idx; /* Extern functions ----------------------------------------------------------*/ extern int32_t gpio_val_set(uint16_t gpio, uint8_t value); diff --git a/app/include/pd_csg.h b/app/include/pd_csg.h index 35a6e47..32dbc83 100755 --- a/app/include/pd_csg.h +++ b/app/include/pd_csg.h @@ -43,6 +43,8 @@ #include #include +#include "file_fifo.h" +#include "pd_hf.h" /* Define --------------------------------------------------------------------*/ #define CSG_FIFO_CMD "CSG_FIFO_CMD" @@ -61,12 +63,19 @@ #define CSG_TREND_PRPD_PORT_LEN (0X20000) // 128K #define CSG_TREND_ORIG_PORT_LEN (0X20400) // 129K +#define CSG_TREND_NAME "/media/Data/Trend" +#define CSG_EVENT_NAME "/media/Data/Event" + +#define CSG_SEND_TIMEOUT (2) +#define CSG_SEND_ERR_CNT (3) +#define CSG_FILE_FIFO_PATH_LEN 256 + -#define MAX_FILES (128) -#define MAX_PATH_LEN (256) -#define THRESHOLD_MS 10 // 时间差阈值 -#define CSG_SEND_TIMEOUT (2) -#define CSG_SEND_ERR_CNT (3) +//#define MAX_FILES (128) +//#define MAX_PATH_LEN (256) +//#define THRESHOLD_MS 10 // 时间差阈值 +//#define CSG_SEND_TIMEOUT (2) +//#define CSG_SEND_ERR_CNT (3) #define CSG_FILE_NAME_LEN (128) #define DAU_INSERT 1 @@ -123,6 +132,7 @@ enum CSG_TREND_TYPE typedef int32_t (*csg_send_cb)(uint8_t, uint8_t, void*); typedef int32_t (*csg_send_fun_cb)(uint8_t, void*); +typedef int32_t (*csg_write_file_cb)(uint8_t, void *); // 定义命令字常量 @@ -153,6 +163,14 @@ typedef struct { uint32_t port; /* 端口号 0 ~ 7 */ uint32_t length; /* 端口数据长度 */ }port_info_t; + +typedef struct +{ + char dir[CSG_FILE_FIFO_PATH_LEN]; // 目录路径 + int32_t files_max; // 存储最大文件数量 + int64_t index_min; // 目录当前最小索引 + int64_t index_max; // 目录当前最大索引, 该索引为下次下入的文件名 +} csg_file_fifo_t; /* . */ typedef struct @@ -181,6 +199,8 @@ typedef struct uint32_t event_booster_id; time_t heartbeat_timeout; time_t heartbeat_timeout_cnt; + file_fifo_t event_file; + csg_file_fifo_t trend_file; sem_t event_sem; sem_t trend_sem; sem_t event_booster_sem; @@ -188,6 +208,8 @@ typedef struct pthread_mutex_t mutex; pthread_mutex_t lock; csg_send_cb send_cb; + csg_write_file_cb event_write_file_cb; + csg_write_file_cb trend_write_file_cb; } csg_t; /* 报文头结构. */ @@ -332,6 +354,18 @@ typedef struct{ uint32_t utc; // 同步时间 uint32_t len; // 当前包长度 } csg_trend_t; + +typedef struct +{ + uint8_t type; // 数据类型 TREND_TYPE 0:prpd 1:原始波形 2:10秒prps 3:统计数据 + uint8_t vport; // 通道号 + uint8_t port_num; // 通道数 + uint8_t slot; // 槽位号,保存文件使用 + uint32_t identifier; // 数据编号 + uint32_t utc; // 同步时间 + uint32_t len; // data长度 +} csg_trend_file_t; + typedef struct{ uint16_t data_cnt; // 数据计数. int16_t max; // 通道的最大值. @@ -351,7 +385,8 @@ typedef struct { int16_t max; // 通道的最大值. uint32_t power_fre; // 工频周期. uint8_t type; // 事件类型. - uint8_t reserved[3]; // 保留 + uint8_t slot; // 槽位,保存文件使用 + uint8_t reserved[2]; // 保留 uint32_t identifier; // 数据编号: 0 - (2^32-1) 循环. uint32_t utc; // UTC 时标. uint32_t cnt; // 通道每秒脉冲计数值. @@ -359,7 +394,13 @@ typedef struct { uint16_t avg; // 脉冲平均值. uint32_t point_cnt; // 数据累计点数 uint32_t len; // 当前包长度 -} csg_event_t; +} csg_event_head_t; + +typedef struct { + csg_event_head_t head; + hf_data_point_t point[PD_EVENT_POINT_MAX]; +} csg_event_t; + /* 升级文件包结构体 */ typedef struct { uint8_t type; // 升级类型 @@ -441,7 +482,6 @@ typedef struct uint8_t reserved[2]; uint8_t result; } csg_add_dau_ack_t; - /* Exported macro ------------------------------------------------------------*/ diff --git a/app/include/pd_modbus.h b/app/include/pd_modbus.h index 832c3ca..9bbb4db 100755 --- a/app/include/pd_modbus.h +++ b/app/include/pd_modbus.h @@ -6,10 +6,11 @@ #define WRITE 1 #define READ 0 -#define MODBUS_IR_CURRENT_ADDR 0x0 // 铁芯 -#define MODBUS_IR_CURRENT_LEN 2 -#define MODBUS_DC_CURRENT_ADDR 0x34 // 直流偏磁 -#define MODBUS_DC_CURRENT_LEN 2 +#define MODBUS_DEVICE_TYPE_ADDR 0x0 +#define MODBUS_IR_CURRENT_ADDR 0x10 // 铁芯 +#define MODBUS_IR_CURRENT_LEN 2 +#define MODBUS_DC_CURRENT_ADDR 0x34 // 直流偏磁 +#define MODBUS_DC_CURRENT_LEN 2 #define MODBUS_UNIT_IR 0x01 @@ -17,6 +18,23 @@ #define MODBUS_ADDR_ALARM 0x32 #define MODBUS_ALARM_LEN 2 +#define DEVICE_IR_TYPE 0x0304 +#define DEVICE_DC_TYPE 0x0305 + +#define POS_UINT_ID 6 +#define POS_FUNCTION 7 + +#define MAX_SLOT 6 + +typedef struct +{ + uint8_t unit_id; + uint8_t status; + uint16_t type; + uint32_t current; + uint16_t alarm; +} stat_t; + // 定义Modbus TCP MBAP头 //#pragma pack(push, 1) @@ -42,8 +60,10 @@ typedef struct int fd; uint8_t txbuf[512]; uint8_t rxbuf[512]; + stat_t stat[MAX_SLOT]; }modbus_t; +extern int32_t modbus_handle_init(void); extern int32_t modbus_handle_init_after(void); #endif #endif diff --git a/app/lib/a_process/pd_csg.c b/app/lib/a_process/pd_csg.c index 042b959..d4b5ea6 100755 --- a/app/lib/a_process/pd_csg.c +++ b/app/lib/a_process/pd_csg.c @@ -75,6 +75,7 @@ /* Private variables ---------------------------------------------------------*/ csg_t csg; +static csg_event_t _csg_event; /* Private function prototypes -----------------------------------------------*/ void _csg_server_set(int32_t ip, uint16_t port); @@ -1015,8 +1016,8 @@ int32_t _csg_send_prps_data(uint8_t slot, void *data) int32_t _csg_send_event_data(uint8_t slot, void *data) { char *pkt = csg.event_buf; - csg_event_t *head = (csg_event_t *)(pkt + sizeof(csg_pkt_head_t)); - char *pdata = pkt + sizeof(csg_pkt_head_t) + sizeof(csg_event_t); + csg_event_head_t *head = (csg_event_head_t *)(pkt + sizeof(csg_pkt_head_t)); + char *pdata = pkt + sizeof(csg_pkt_head_t) + sizeof(csg_event_head_t); hf_event_t *event = (hf_event_t *)data; struct timespec ts; uint8_t err_cnt = 0; @@ -1062,7 +1063,7 @@ int32_t _csg_send_event_data(uint8_t slot, void *data) head->index = index; memcpy(pdata, event->point + index * CSG_PKT_LEN, head->len); - _csg_send_data(CSG_PRV_REPLY, CSG_PRV_EVENT, pkt, head->len + sizeof(csg_event_t), slot + 1); + _csg_send_data(CSG_PRV_REPLY, CSG_PRV_EVENT, pkt, head->len + sizeof(csg_event_head_t), slot + 1); clock_gettime(CLOCK_REALTIME, &ts); ts.tv_sec += CSG_SEND_TIMEOUT; // 设置 3 秒超时 @@ -1085,6 +1086,180 @@ int32_t _csg_send_event_data(uint8_t slot, void *data) return E_NONE; } +int32_t _csg_event_file_send(void) +{ + struct timespec ts; + csg_event_head_t *head = NULL; + char *pdata = NULL; + char *pkt = csg.event_booster_buf; + csg_event_head_t *pack = (csg_event_head_t *)(pkt + sizeof(csg_pkt_head_t)); + char *data = pkt + sizeof(csg_pkt_head_t) + sizeof(csg_event_head_t); + uint8_t err_cnt = 0; + uint32_t index = 0; + uint32_t event_len = 0; + uint32_t sum = 0; + uint8_t slot = 0; + + head = &_csg_event.head; + pdata = (char *)_csg_event.point; + event_len = head->point_cnt * sizeof(pd_data_point_t); + sum = event_len / CSG_PKT_LEN; + if (event_len % CSG_PKT_LEN) + { + sum += 1; + } + + slot = head->slot; + pack->sum = sum; + pack->vport = head->vport; + pack->boosterpack = 1; + pack->power_fre = head->power_fre; + pack->type = head->type; + pack->max = head->max; + pack->identifier = head->index; + pack->utc = head->utc; + pack->cnt = head->cnt; + pack->avg_o = head->avg_o; + pack->avg = head->avg; + pack->point_cnt = head->point_cnt; + + while (index < sum) + { + csg.event_booster_id = index; + pack->len = event_len > CSG_PKT_LEN ? CSG_PKT_LEN : event_len; + pack->index = index; + + memcpy(data, pdata + index * CSG_PKT_LEN, pack->len); + _csg_send_data(CSG_PRV_REPLY, CSG_PRV_EVENT, pkt, pack->len + sizeof(csg_event_head_t), slot + 1); + + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += CSG_SEND_TIMEOUT; // 设置 3 秒超时 + if (sem_timedwait(&csg.event_booster_sem, &ts) != 0) + { + err_cnt++; + if (err_cnt >= CSG_SEND_ERR_CNT) + { + _csg_disconnect_set(__FUNCTION__); + return E_TIMEOUT; + } + DBG(DBG_M_PD_CSG_ERR, "event sem error:%s\r\n", strerror(errno)); + continue; + } + + event_len -= pack->len; + index++; + err_cnt = 0; + } + + return E_NONE; +} + +/* 趋势文件发送 */ +int32_t _csg_trend_file_send(char *filename) +{ + struct timespec ts; + FILE *file = NULL; + csg_trend_file_t filehead = {0}; + char *pkt = csg.trend_booster_buf; + csg_trend_t *pack = (csg_trend_t *)(pkt + sizeof(csg_pkt_head_t)); + char *data = pkt + sizeof(csg_pkt_head_t) + sizeof(csg_trend_t); + uint8_t err_cnt = 0; + uint32_t index = 0; + uint32_t prps_len = 0; + uint32_t sum = 0; + uint32_t len = 0; + uint32_t readbyte = 0; + int offset = 0; + uint8_t slot; + + if (csg.trend_file.index_min == csg.trend_file.index_max) + { + return E_EMPTY; + } + + file = fopen(filename, "r"); + if (!file) + { + DBG(DBG_M_PD_CSG_ERR, "Open failed!\r\n"); + return E_NONE; + } + + while(1) + { + fseek(file, offset, SEEK_SET); + readbyte = fread(&filehead, 1, sizeof(csg_trend_file_t), file); + if (readbyte != sizeof(csg_trend_file_t)) + { + if (readbyte != 0) + { + DBG(DBG_M_PD_CSG_ERR,"read %d != %d\r\n", len, readbyte, strerror(errno)); + } + fclose(file); + return E_NONE; + } + + printf("#1 %d %d %d %d %d\r\n", filehead.vport, filehead.type, filehead.len, filehead.identifier, filehead.utc); + pack->type = filehead.type; + pack->vport = filehead.vport; + pack->boosterpack = 1; + pack->identifier = filehead.identifier; + pack->utc = filehead.utc; + slot = filehead.slot; + prps_len = filehead.len; + sum = prps_len / CSG_PKT_LEN; + if (prps_len % CSG_PKT_LEN) + { + sum += 1; + } + pack->sum = sum; + + offset += sizeof(csg_trend_file_t); + index = 0; + while (index < sum) + { + fseek(file, offset, SEEK_SET); + csg.trend_booster_id = index; + len = prps_len > CSG_PKT_LEN ? CSG_PKT_LEN : prps_len; + + pack->len = len; + pack->index = index; + + readbyte = fread(data, 1, len, file); + if (readbyte != len) + { + DBG(DBG_M_PD_CSG_ERR,"read %d != %d err:%s\r\n", len, readbyte, strerror(errno)); + fclose(file); + return E_NONE; + } + + _csg_send_data(CSG_PRV_REPLY, CSG_PRV_TREND, pkt, len + sizeof(csg_trend_t), slot + 1); + + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += CSG_SEND_TIMEOUT; // 设置 3 秒超时 + if (sem_timedwait(&csg.trend_booster_sem, &ts) != 0) + { + err_cnt++; + if (err_cnt >= CSG_SEND_ERR_CNT) + { + fclose(file); + _csg_disconnect_set(__FUNCTION__); + return E_TIMEOUT; + } + DBG(DBG_M_PD_CSG_ERR, "trend sem error:%s\r\n", strerror(errno)); + continue; + } + + prps_len -= len; + index++; + err_cnt = 0; + offset += len; + } + } + + fclose(file); + return E_NONE; +} + int32_t _csg_send_trend_prps_data(uint8_t slot, void *data) { struct timespec ts; @@ -1332,6 +1507,282 @@ int32_t _csg_send_process(uint8_t type, uint8_t slot, void *data) return E_NONE; } +/* 创建目录 */ +int32_t _csg_create_dir(char *dir) +{ + uint32_t i = 0; + uint32_t len = 0; + + len = strlen(dir); + + /* 循环创建前级目录 */ + for(i = 0; i < len; i++) + { + if(dir[i] == '/') + { + dir[i] = '\0'; + if(access(dir, 0) != 0) + { + mkdir(dir, 744); + } + dir[i] ='/'; + } + } + + /* 创建最后级目录 */ + if(len > 0 && access(dir, 0) != 0) + { + mkdir(dir, 744); + } + + return E_NONE; +} + +/* 在文件末尾写入数据 */ +int32_t _csg_write_file(char *filename, char *filehead, int headsize, char *filedata, int datasize) +{ + /* 写入文件 */ + FILE *file = fopen(filename, "ab"); + if (!file) + { + DBG(DBG_M_PD_CSG_ERR, "Open error.\r\n"); + return E_SYS_CALL; + } + + fseek(file, 0, SEEK_END); // 移动到文件末尾 + + size_t bytes_written = fwrite(filehead, 1, headsize, file); + if (bytes_written != headsize) + { + DBG(DBG_M_PD_CSG_ERR, "Write error.\r\n"); + fclose(file); + unlink(filename); // 删除不完整文件 + return E_SYS_CALL; + } + + bytes_written = fwrite(filedata, 1, datasize, file); + if (bytes_written != datasize) + { + DBG(DBG_M_PD_CSG_ERR, "Write error.\r\n"); + fclose(file); + unlink(filename); // 删除不完整文件 + return E_SYS_CALL; + } + + /* 确保数据落盘 */ + fsync(fileno(file)); + fclose(file); + return E_NONE; +} + +/* 趋势 prps 写入文件 */ +int32_t _csg_trend_prps_write_file(uint8_t slot, uint8_t port, char *filepath) +{ + hf_trend_prps_port_t *data_port = NULL; + csg_trend_file_t file_head = {0}; + + dau_t *dau = &daus[slot]; + hf_data_t *hf_data = (hf_data_t*)dau->private_data; + hf_trend_prps_t *prps = &hf_data->trend.prps; + hf_trend_col_t *col = &hf_data->trend.col; + + data_port = &prps->port[port]; + + file_head.type = CSG_TREND_TYPE_PRPS; + file_head.vport = port + 1; + file_head.port_num = 1; + file_head.slot = slot; + file_head.identifier = col->index; + file_head.utc = col->utc; + file_head.len = data_port->point_cnt * sizeof(pd_data_point_t); + + LD_E_RETURN(DBG_M_PD_CSG_ERR, _csg_write_file(filepath, (char *)&file_head, sizeof(file_head), (char*)data_port->point, file_head.len)); + + return E_NONE; +} + +/* 趋势 prpd 写入文件 */ +int32_t _csg_trend_prpd_write_file(uint8_t slot, uint8_t port, char *filepath) +{ + pd_trend_prpd_port_t *data_port = NULL; + csg_trend_file_t file_head = {0}; + + dau_t *dau = &daus[slot]; + hf_data_t *hf_data = (hf_data_t*)dau->private_data; + hf_trend_prpd_t *prpd = &hf_data->trend.prpd; + hf_trend_col_t *col = &hf_data->trend.col; + + data_port = &prpd->port[port]; + + file_head.type = CSG_TREND_TYPE_PRPD; + file_head.vport = port + 1; + file_head.port_num = 1; + file_head.slot = slot; + file_head.identifier = col->index; + file_head.utc = col->utc; + file_head.len = sizeof(pd_trend_prpd_port_t); + + LD_E_RETURN(DBG_M_PD_CSG_ERR, _csg_write_file(filepath, (char *)&file_head, sizeof(file_head), (char*)data_port, file_head.len)); + + return E_NONE; +} + +/* 趋势统计数据写入文件 */ +int32_t _csg_trend_statistics_write_file(uint8_t slot, uint8_t port, char *filepath) +{ + hf_trend_stat *data_port = NULL; + csg_trend_file_t file_head = {0}; + csg_trend_stat stat = {0}; + + dau_t *dau = &daus[slot]; + hf_data_t *hf_data = (hf_data_t*)dau->private_data; + hf_trend_col_t *col = &hf_data->trend.col; + + data_port = &col->port[port]; + + file_head.type = CSG_TREND_TYPE_STAT; + file_head.vport = port + 1; + file_head.port_num = 1; + file_head.slot = slot; + file_head.identifier = col->index; + file_head.utc = col->utc; + file_head.len = sizeof(csg_trend_stat); + + stat.data_cnt = data_port->data_cnt; + stat.max = data_port->max; + stat.avg = data_port->avg; + stat.cnt = data_port->cnt; + stat.phase = data_port->phase; + stat.noise = data_port->noise; + stat.event_cnt = data_port->event_cnt; + + LD_E_RETURN(DBG_M_PD_CSG_ERR, _csg_write_file(filepath, (char *)&file_head, sizeof(file_head), (char *)&stat, file_head.len)); + + + return E_NONE; +} + +int32_t _csg_event_write_file(uint8_t slot, void *data) +{ + int32_t len = 0; + hf_event_t *event = (hf_event_t *)data; + if (NULL == event) + { + return E_BAD_PARAM; + } + + csg_event_head_t *head = (csg_event_head_t *)data; + head->slot = slot; + + len = sizeof(event->head) + event->head.point_cnt * sizeof(hf_data_point_t); + file_fifo_write(&csg.event_file, (char*)event, len); + return E_NONE; +} + +/* 趋势数据写入文件 */ +int32_t _csg_trend_write_file(uint8_t slot, void *data) +{ + int ret = E_NONE; + char filepath[CSG_FILE_FIFO_PATH_LEN] = {0}; + + uint8_t port = *(uint32_t *)data; + if (port >= 8) + return E_BAD_PARAM; + + if (csg.trend_file.index_max - csg.trend_file.index_min >= csg.trend_file.files_max) + { + return E_FULL; + } + + snprintf(filepath, 128, "%s/%ld", CSG_TREND_NAME, csg.trend_file.index_max); + + ret |= _csg_trend_prps_write_file(slot, port, filepath); + ret |= _csg_trend_prpd_write_file(slot, port, filepath); + ret |= _csg_trend_statistics_write_file(slot, port, filepath); + if (E_NONE == ret) + { + csg.trend_file.index_max++; + } + + return ret; +} + + +/* 初始化最大最小索引 */ +int32_t _csg_file_fifo_init(csg_file_fifo_t *config) +{ + DIR *dir = opendir(config->dir); + struct dirent *entry; + uint8_t first = 1; + int64_t index = 0; + + /* 初始化最大最小 index */ + config->index_max = 0; + config->index_min = 0; + + if (!dir) + { + _csg_create_dir(config->dir); + } + else + { + while ((entry = readdir(dir)) != NULL) + { + if (entry->d_type != DT_REG) + { + continue; + } + + if (!isdigit(entry->d_name[0])) + { + continue; + } + //printf("filename:%s\n", entry->d_name); + + index = strtoll(entry->d_name, NULL, 10); + if (first) + { + config->index_max = config->index_min = index; + first = 0; + } + else + { + if (index > config->index_max) + { + config->index_max = index; + } + + if (index < config->index_min) + { + config->index_min = index; + } + } + } + + /* 非空目录最大索引要加一 */ + if (!first) + { + config->index_max++; + } + + closedir(dir); + } + + return E_NONE; +} + +/* 删除最小索引文件 */ +void _csg_file_fifo_delete_by_min_index(csg_file_fifo_t *config) +{ + char filename[512]; + + snprintf(filename, sizeof(filename), "%s/%ld", config->dir, config->index_min); + remove(filename); + + /* 更新最小索引 */ + config->index_min++; +} + /* 普通命令发送平台线程 */ void *_csg_send_cmd_handle(void *arg) { @@ -1418,10 +1869,17 @@ void *_csg_send_trend_handle(void *arg) } /* 响应其他报文 */ - if (csg.send_cb) - { - csg.send_cb(recv_msg->type, recv_msg->slot, recv_msg->data); - } + if (csg.is_connect) + { + if (csg.send_cb) + { + csg.send_cb(recv_msg->type, recv_msg->slot, recv_msg->data); + } + } + else + { + csg.trend_write_file_cb(recv_msg->slot, recv_msg->data); + } /* 释放数据内存, 注意一定要在 fifo_push 之前调用, 因为 fifo_push 后 recv_msg 已被释放. */ XFREE(MTYPE_CSG, recv_msg->data); @@ -1451,10 +1909,17 @@ void *_csg_send_event_handle(void *arg) } /* 响应其他报文 */ - if (csg.send_cb) - { - csg.send_cb(recv_msg->type, recv_msg->slot, recv_msg->data); - } + if (csg.is_connect) + { + if (csg.send_cb) + { + csg.send_cb(recv_msg->type, recv_msg->slot, recv_msg->data); + } + } + else + { + csg.event_write_file_cb(recv_msg->slot, recv_msg->data); + } /* 释放数据内存, 注意一定要在 fifo_push 之前调用, 因为 fifo_push 后 recv_msg 已被释放. */ XFREE(MTYPE_CSG, recv_msg->data); @@ -1463,6 +1928,48 @@ void *_csg_send_event_handle(void *arg) return NULL; } + +void *_csg_boosterpack_handle(void *arg) +{ + char filepath[260]; + int32_t len = 0; + + /* 等待初始化完成 */ + while(!is_system_init) + { + sleep(1); + } + + while (1) + { + sleep(1); + + if (!csg.is_connect) + { + continue; + } + + /* 事件重发 */ + len = sizeof(_csg_event); + if (E_NONE == file_fifo_read(&csg.event_file, (char*)(&_csg_event), &len)) + { + if (E_NONE == _csg_event_file_send()) + { + file_fifo_delete_by_min_index(&csg.event_file); + } + continue; + } + + /* 趋势重发 */ + snprintf(filepath, sizeof(filepath), "%s/%ld", csg.trend_file.dir, csg.trend_file.index_min); + if (E_NONE == _csg_trend_file_send(filepath)) + { + _csg_file_fifo_delete_by_min_index(&csg.trend_file); + } + } + return NULL; +} + /* 后台接收处理函数. */ void *_csg_recv_handle(void *arg) @@ -1681,7 +2188,17 @@ int32_t csg_handle_init_after(void) sem_init(&csg.event_booster_sem, 0, 0); sem_init(&csg.trend_booster_sem, 0, 0); + snprintf(csg.event_file.dir, FILE_FIFO_PATH_LEN, "%s", CSG_EVENT_NAME); + csg.event_file.files_max = pd_config.config.event_storage; + file_fifo_init(&csg.event_file); + + snprintf(csg.trend_file.dir, CSG_FILE_FIFO_PATH_LEN, "%s", CSG_TREND_NAME); + csg.trend_file.files_max = pd_config.config.trend_storage; + _csg_file_fifo_init(&csg.trend_file); + csg.send_cb = _csg_send_process; + csg.event_write_file_cb = _csg_event_write_file; + csg.trend_write_file_cb = _csg_trend_write_file; param.arg = NULL; param.log_module = LOG_CSG; diff --git a/app/lib/a_process/pd_main.c b/app/lib/a_process/pd_main.c index fe35d8b..63647d4 100755 --- a/app/lib/a_process/pd_main.c +++ b/app/lib/a_process/pd_main.c @@ -625,6 +625,7 @@ int32_t pd_main(void) rv |= dau_handle_init(); rv |= csg_handle_init(); rv |= debug_handle_init(); + rv |= modbus_handle_init(); return E_NONE; } diff --git a/app/lib/a_process/pd_modbus.c b/app/lib/a_process/pd_modbus.c index bccf3a1..5fb0bbd 100755 --- a/app/lib/a_process/pd_modbus.c +++ b/app/lib/a_process/pd_modbus.c @@ -15,8 +15,7 @@ /* Private variables ---------------------------------------------------------*/ modbus_t modbus; -int32_t _modbus_tcp_transaction(uint16_t transaction_id, uint8_t unit_id, - uint16_t start_addr, uint16_t data_num) +int32_t _modbus_tcp_transaction(uint16_t transaction_id, uint8_t unit_id, uint16_t start_addr, uint16_t data_num) { int txlen = 0; int rxlen = 0; @@ -37,7 +36,7 @@ int32_t _modbus_tcp_transaction(uint16_t transaction_id, uint8_t unit_id, pdata[datalen++] = data_num & 0xFF; // 数据数量低字节 txlen = datalen + sizeof(modbus_tcp_t); - + // 发送请求帧 GPIO_485BUS(WRITE); if (serial_write(modbus.fd, modbus.txbuf, txlen) < 0) @@ -45,7 +44,7 @@ int32_t _modbus_tcp_transaction(uint16_t transaction_id, uint8_t unit_id, DBG(DBG_M_PD_MODBUS_ERR, "Modbus write error\r\n"); return E_ERROR; } - DBG(DBG_M_PD_MODBUS_ERR, "Modbus write len = %d\r\n", txlen); + DBG(DBG_M_PD_MODBUS, "Modbus write len = %d\r\n", txlen); buf_print((char *)modbus.txbuf, txlen); // 等待传输完成 @@ -55,11 +54,17 @@ int32_t _modbus_tcp_transaction(uint16_t transaction_id, uint8_t unit_id, rxlen = serial_read(modbus.fd, modbus.rxbuf, sizeof(modbus.rxbuf)); if (rxlen > 0) { - DBG(DBG_M_PD_MODBUS_ERR, "Modbus read len = %d\r\n", rxlen); + DBG(DBG_M_PD_MODBUS, "Modbus read len = %d\r\n", rxlen); buf_print((char *)modbus.rxbuf, rxlen); + uint16_t trans_id = (modbus.rxbuf[0] << 8) + modbus.rxbuf[1]; + if (trans_id == transaction_id + && modbus.rxbuf[POS_UINT_ID] == unit_id) + { + return E_NONE; + } } - return E_NONE; + return E_ERROR; } int32_t _modbus_rtu_transaction(void) @@ -97,8 +102,61 @@ int32_t _modbus_rtu_transaction(void) return E_NONE; } +int32_t _modbus_get_device_type(uint8_t unit, uint16_t *type) +{ + uint16_t device_type = 0; + if (!_modbus_tcp_transaction(5, unit, MODBUS_DEVICE_TYPE_ADDR, 1)) + { + device_type = modbus.rxbuf[9] << 8; + device_type += modbus.rxbuf[10]; + } + *type = device_type; + return E_NONE; +} + +int32_t _modbus_get_current(uint8_t unit, uint16_t addr, uint16_t len, uint32_t *current) +{ + uint32_t cur = 0; + if (!_modbus_tcp_transaction(5, unit, addr, len)) + { + //cur = modbus.rxbuf[9] << 24; + //cur += modbus.rxbuf[10] << 16; + //cur += modbus.rxbuf[11] << 8; + //cur += modbus.rxbuf[12]; + memcpy(&cur, &modbus.rxbuf[9], sizeof(uint32_t)); + } + *current = cur; + return E_NONE; +} + +void _modbus_read_slot_stat(stat_t *pstat) +{ + stat_t *ptmp = pstat; + for (int slot = 0; slot < MAX_SLOT; slot++) + { + //pstat[slot].status = 0; + ptmp->status = 0; + ptmp++; + } + + ptmp = pstat; + gpio_val_get(gpio_dau1_idx, &ptmp->status); + ptmp++; + gpio_val_get(gpio_dau2_idx, &ptmp->status); + ptmp++; + gpio_val_get(gpio_dau3_idx, &ptmp->status); + ptmp++; + gpio_val_get(gpio_dau4_idx, &ptmp->status); + ptmp++; + gpio_val_get(gpio_dau5_idx, &ptmp->status); + ptmp++; + gpio_val_get(gpio_dau6_idx, &ptmp->status); +} + + void *_modbus_send_handle() { + stat_t *pstat = NULL; while (1) { #if 0 @@ -115,9 +173,30 @@ void *_modbus_send_handle() } } #else - //_modbus_rtu_transaction(); - - _modbus_tcp_transaction(5, MODBUS_UNIT_IR, MODBUS_IR_CURRENT_ADDR, MODBUS_IR_CURRENT_LEN); + pstat = modbus.stat; + _modbus_read_slot_stat(pstat); + + for (int slot = 0; slot < MAX_SLOT; slot++) + { + if (pstat->status) + { + _modbus_get_device_type(pstat->unit_id, &pstat->type); + + if (DEVICE_IR_TYPE == pstat->type) + { + _modbus_get_current(pstat->unit_id, + MODBUS_IR_CURRENT_ADDR, MODBUS_IR_CURRENT_LEN, &pstat->current); + DBG(DBG_M_PD_MODBUS, "current:%d\n", pstat->current); + } + else if (DEVICE_DC_TYPE == pstat->type) + { + _modbus_get_current(pstat->unit_id, + MODBUS_DC_CURRENT_ADDR, MODBUS_DC_CURRENT_LEN, &pstat->current); + } + } + pstat++; + } + #endif sleep(2); } @@ -132,6 +211,10 @@ void *_modbus_send_handle() int32_t modbus_handle_init(void) { memset(&modbus, 0, sizeof(modbus)); + for (int slot = 0; slot < MAX_SLOT; slot++) + { + modbus.stat[slot].unit_id = slot + 1; + } modbus.fd = -1; return E_NONE; } diff --git a/app/lib/m_management/dbg.c b/app/lib/m_management/dbg.c index e477dc3..8b0b842 100755 --- a/app/lib/m_management/dbg.c +++ b/app/lib/m_management/dbg.c @@ -73,8 +73,10 @@ dbg_module_t _dbg_module[DBG_M_COUNT] = {DBG_M_PD_HF, FALSE, "pd_hf"}, {DBG_M_PD_HF_ERR, TRUE, "pd_hf_err"}, {DBG_M_SERIAL, TRUE, "serial"}, - {DBG_M_PD_MODBUS, TRUE, "pd_modbus"}, - {DBG_M_PD_MODBUS_ERR, TRUE, "pd_modbus_err"}, + {DBG_M_PD_MODBUS, FALSE, "pd_modbus"}, + {DBG_M_PD_MODBUS_ERR, FALSE, "pd_modbus_err"}, + {DBG_M_FILE_FIFO, TRUE, "file_fifo"}, + {DBG_M_FILE_FIFO_ERR, TRUE, "file_fifo_err"}, }; /* Private function prototypes -----------------------------------------------*/ diff --git a/app/lib/m_management/file_fifo.c b/app/lib/m_management/file_fifo.c new file mode 100755 index 0000000..d7b4d52 --- /dev/null +++ b/app/lib/m_management/file_fifo.c @@ -0,0 +1,243 @@ +/****************************************************************************** + * file lib/management/file_fifo.c + * author YuLiang + * version 1.0.0 + * date 10-Jun-2025 + * brief This file provides all the file fifo operation functions. + * + ****************************************************************************** + * Attention + * + *

© COPYRIGHT(c) 2025 LandPower

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of LandPower nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +/* Includes ------------------------------------------------------------------*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* 标准C库头文件. */ +#include +#include +#include +#include + +/* 用户代码头文件. */ +#include + +/* Private define ------------------------------------------------------------*/ + +/* Private macro -------------------------------------------------------------*/ + +/* Private typedef -----------------------------------------------------------*/ + +/* Private variables ---------------------------------------------------------*/ + +/* Private function prototypes -----------------------------------------------*/ + +/* Internal functions --------------------------------------------------------*/ +/* 创建目录 */ +int32_t _file_fifo_dir_create(char *dir) +{ + uint32_t i = 0; + uint32_t len = 0; + + len = strlen(dir); + + /* 循环创建前级目录 */ + for(i = 0; i < len; i++) + { + if(dir[i] == '/') + { + dir[i] = '\0'; + if(access(dir, 0) != 0) + { + mkdir(dir, 744); + } + dir[i] ='/'; + } + } + + /* 创建最后级目录 */ + if(len > 0 && access(dir, 0) != 0) + { + mkdir(dir, 744); + } + + return E_NONE; +} + +/* Interface functions -------------------------------------------------------*/ +/* 写函数 */ +int32_t file_fifo_write(file_fifo_t *config, const char *content, int32_t len) +{ + FILE *fp = NULL; + char filename[512]; + int32_t size = 0; + + if (config->index_max - config->index_min >= config->files_max) + { + return E_FULL; + } + + /* 确认文件名 */ + snprintf(filename, sizeof(filename), "%s/%ld", config->dir, config->index_max); + + /* 写入文件 */ + fp = fopen(filename, "w+"); + if (!fp) + { + DBG(DBG_M_FILE_FIFO_ERR, "Open %s ERROR\r\n", filename); + return E_SYS_CALL; + } + + size = fwrite(content, 1, len, fp); + if (size != len) + { + fclose(fp); + DBG(DBG_M_FILE_FIFO_ERR, "Write %s ERROR\r\n", filename); + return E_SYS_CALL; + } + fclose(fp); + + config->index_max++; + return E_NONE; +} + +/* 读函数 */ +int32_t file_fifo_read(file_fifo_t *config, char *content, int32_t *len) +{ + FILE *fp = NULL; + char filename[512]; + int32_t size = 0; + + if (config->index_max == config->index_min) + { + return E_EMPTY; + } + + /* 确认文件名 */ + snprintf(filename, sizeof(filename), "%s/%ld", config->dir, config->index_min); + + /* 打开文件 */ + fp = fopen(filename, "r"); + if (!fp) + { + file_fifo_delete_by_min_index(config); + DBG(DBG_M_FILE_FIFO_ERR, "Open %s ERROR\r\n", filename); + return E_SYS_CALL; + } + + size = fread(content, 1, *len, fp); + if (size <= 0) + { + fclose(fp); + file_fifo_delete_by_min_index(config); + DBG(DBG_M_FILE_FIFO_ERR, "Read %s ERROR\r\n", filename); + return E_SYS_CALL; + } + *len = size; + fclose(fp); + + return E_NONE; +} + +/* 删除最小索引文件 */ +void file_fifo_delete_by_min_index(file_fifo_t *config) +{ + char filename[512]; + + snprintf(filename, sizeof(filename), "%s/%ld", config->dir, config->index_min); + remove(filename); + + /* 更新最小索引 */ + config->index_min++; +} + +/* 初始化最大最小索引, 这套接口不能在不同线程同时调用, 例如 write 接口只能在单一线程调用, read可以在另一个线程调用, + 但是 write 接口不能同时在两个线程调用 */ +int32_t file_fifo_init(file_fifo_t *config) +{ + DIR *dir = opendir(config->dir); + struct dirent *entry; + uint8_t first = 1; + int64_t index = 0; + + config->index_max = 0; + config->index_min = 0; + + if (!dir) + { + /* 创建目录 */ + _file_fifo_dir_create(config->dir); + } + else + { + /* 初始化最大最小 index */ + while ((entry = readdir(dir)) != NULL) + { + if (entry->d_type != DT_REG) + { + continue; + } + + if (!isdigit(entry->d_name[0])) + { + continue; + } + + index = strtoll(entry->d_name, NULL, 10); + if (first) + { + config->index_max = config->index_min = index; + first = 0; + } + else + { + if (index > config->index_max) + { + config->index_max = index; + } + + if (index < config->index_min) + { + config->index_min = index; + } + } + } + + /* 非空目录最大索引要加一 */ + if (!first) + { + config->index_max++; + } + + closedir(dir); + } + + return E_NONE; +} +/************************ (C) COPYRIGHT LandPower ***** END OF FILE ****************/ diff --git a/app/lib/z_hardware/hwgpio.c b/app/lib/z_hardware/hwgpio.c index c0a3f9b..b2c9495 100755 --- a/app/lib/z_hardware/hwgpio.c +++ b/app/lib/z_hardware/hwgpio.c @@ -56,6 +56,13 @@ static array_t *gpios = NULL; int32_t gpio_485bus_idx; +int32_t gpio_dau1_idx; +int32_t gpio_dau2_idx; +int32_t gpio_dau3_idx; +int32_t gpio_dau4_idx; +int32_t gpio_dau5_idx; +int32_t gpio_dau6_idx; + /* Private function prototypes -----------------------------------------------*/ @@ -329,6 +336,9 @@ int32_t gpio_export(uint16_t gpio) int32_t gpio_init(void) { gpios = array_init(ARRAY_MIN_SIZE, MTYPE_GPIO); + + cmd_install_element(COMMON_NODE, &gpio_show_cmd); + gpio_485bus_idx = gpio_export(GPIO_485_BUS); if (gpio_485bus_idx < 0) { @@ -336,6 +346,54 @@ int32_t gpio_init(void) return E_BAD_PARAM; } LD_E_RETURN(DBG_M_GPIO, gpio_dir_set(gpio_485bus_idx, GPIO_DIR_OUT)); + + gpio_dau1_idx = gpio_export(GPIO_DAU1); + if (gpio_dau1_idx < 0) + { + DBG(DBG_M_GPIO, "ERROR return %d!\r\n", gpio_dau1_idx); + return E_BAD_PARAM; + } + LD_E_RETURN(DBG_M_GPIO, gpio_dir_set(gpio_dau1_idx, GPIO_DIR_IN)); + + gpio_dau2_idx = gpio_export(GPIO_DAU2); + if (gpio_dau2_idx < 0) + { + DBG(DBG_M_GPIO, "ERROR return %d!\r\n", gpio_dau2_idx); + return E_BAD_PARAM; + } + LD_E_RETURN(DBG_M_GPIO, gpio_dir_set(gpio_dau2_idx, GPIO_DIR_IN)); + + gpio_dau3_idx = gpio_export(GPIO_DAU3); + if (gpio_dau3_idx < 0) + { + DBG(DBG_M_GPIO, "ERROR return %d!\r\n", gpio_dau3_idx); + return E_BAD_PARAM; + } + LD_E_RETURN(DBG_M_GPIO, gpio_dir_set(gpio_dau3_idx, GPIO_DIR_IN)); + + gpio_dau4_idx = gpio_export(GPIO_DAU4); + if (gpio_dau4_idx < 0) + { + DBG(DBG_M_GPIO, "ERROR return %d!\r\n", gpio_dau4_idx); + return E_BAD_PARAM; + } + LD_E_RETURN(DBG_M_GPIO, gpio_dir_set(gpio_dau4_idx, GPIO_DIR_IN)); + + gpio_dau5_idx = gpio_export(GPIO_DAU5); + if (gpio_dau5_idx < 0) + { + DBG(DBG_M_GPIO, "ERROR return %d!\r\n", gpio_dau5_idx); + return E_BAD_PARAM; + } + LD_E_RETURN(DBG_M_GPIO, gpio_dir_set(gpio_dau5_idx, GPIO_DIR_IN)); + + gpio_dau6_idx = gpio_export(GPIO_DAU6); + if (gpio_dau6_idx < 0) + { + DBG(DBG_M_GPIO, "ERROR return %d!\r\n", gpio_dau6_idx); + return E_BAD_PARAM; + } + LD_E_RETURN(DBG_M_GPIO, gpio_dir_set(gpio_dau6_idx, GPIO_DIR_IN)); return E_NONE; }