From 5346d8401f082f35028d00adab5675ca2ed7888a Mon Sep 17 00:00:00 2001 From: wlyu Date: Sun, 30 Jan 2022 22:51:00 +0800 Subject: [PATCH] support PLC bus and opcua API --- .../control_app/opcua_demo/opcua_demo.c | 2 +- .../plc/interoperability/opcua/Makefile | 2 +- .../plc/interoperability/opcua/ua_api.c | 68 +++++ .../plc/interoperability/opcua/ua_api.h | 7 + .../Framework/control/plc/shared/Makefile | 2 +- .../Framework/control/plc/shared/plc.c | 154 +++++++++++- .../Framework/control/plc/shared/plc.h | 19 +- .../Framework/control/plc/shared/plc_bus.c | 117 +++++++++ .../Framework/control/plc/shared/plc_bus.h | 66 +++++ .../Framework/control/plc/shared/plc_dev.c | 235 ++++++++++++++++++ .../Framework/control/plc/shared/plc_dev.h | 139 +++++++++++ .../Framework/control/plc/shared/plc_drv.c | 67 +++++ .../Framework/control/shared/Makefile | 3 +- .../Framework/control/shared/config.json | 38 +++ .../Framework/control/shared/control.c | 10 + Ubiquitous/XiUOS/kernel/include/xs_poll.h | 7 +- Ubiquitous/XiUOS/path_app.mk | 1 + Ubiquitous/XiUOS/path_kernel.mk | 2 + Ubiquitous/XiUOS/resources/include/bus.h | 3 + 19 files changed, 913 insertions(+), 29 deletions(-) create mode 100755 APP_Framework/Framework/control/plc/interoperability/opcua/ua_api.c create mode 100755 APP_Framework/Framework/control/plc/shared/plc_bus.c create mode 100755 APP_Framework/Framework/control/plc/shared/plc_bus.h create mode 100755 APP_Framework/Framework/control/plc/shared/plc_dev.c create mode 100755 APP_Framework/Framework/control/plc/shared/plc_dev.h create mode 100755 APP_Framework/Framework/control/plc/shared/plc_drv.c create mode 100755 APP_Framework/Framework/control/shared/config.json diff --git a/APP_Framework/Applications/control_app/opcua_demo/opcua_demo.c b/APP_Framework/Applications/control_app/opcua_demo/opcua_demo.c index 9e948c81f..51dd2cecd 100755 --- a/APP_Framework/Applications/control_app/opcua_demo/opcua_demo.c +++ b/APP_Framework/Applications/control_app/opcua_demo/opcua_demo.c @@ -202,7 +202,7 @@ void *test_sh_ua_get_info(int argc, char *argv[]) ETH_BSP_Config(); lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip); - sys_thread_new("ua object", test_ua_browser_objects, NULL, 4096, 15); + sys_thread_new("ua object", test_ua_get_info, NULL, 4096, 15); return NULL; } diff --git a/APP_Framework/Framework/control/plc/interoperability/opcua/Makefile b/APP_Framework/Framework/control/plc/interoperability/opcua/Makefile index 531b181ed..74c252d73 100755 --- a/APP_Framework/Framework/control/plc/interoperability/opcua/Makefile +++ b/APP_Framework/Framework/control/plc/interoperability/opcua/Makefile @@ -1,3 +1,3 @@ -SRC_FILES := ua_data.c open62541.c ua_client.c ua_server.c +SRC_FILES := ua_data.c open62541.c ua_client.c ua_server.c ua_api.c include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Framework/control/plc/interoperability/opcua/ua_api.c b/APP_Framework/Framework/control/plc/interoperability/opcua/ua_api.c new file mode 100755 index 000000000..c4950862f --- /dev/null +++ b/APP_Framework/Framework/control/plc/interoperability/opcua/ua_api.c @@ -0,0 +1,68 @@ +/* +* Copyright (c) 2021 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +#include "open62541.h" +#include +#include "ua_api.h" + + +#define UA_DEV_IP_LEN 128 +#define UA_NODE_LEN 50 + +typedef struct _ua_dev_t +{ + char ua_remote_ip[UA_DEV_IP_LEN]; + char ua_node[UA_NODE_LEN]; + UA_Client *client; +}ua_dev_t; + + +int ua_open(void *dev) +{ + ua_dev_t *pdev = (ua_dev_t *)dev; + + pdev->client = UA_Client_new(); + UA_StatusCode retval = UA_Client_connect(pdev->client, pdev->ua_remote_ip); + if(retval != UA_STATUSCODE_GOOD) { + UA_Client_delete(pdev->client); + return (int)retval; + } + return EOK; +} + +void ua_close(void *dev) +{ + ua_dev_t *pdev = (ua_dev_t *)dev; + UA_Client_disconnect(pdev->client); + UA_Client_delete(pdev->client); /* Disconnects the client internally */ +} + +int ua_read(void* dev, void *buf, size_t len) +{ + ua_dev_t *pdev = (ua_dev_t *)dev; + ua_get_server_info(pdev->client); + return EOK; +} + +int ua_write(void* dev, const void *buf, size_t len) +{ + ua_dev_t *pdev = (ua_dev_t *)dev; + + return EOK; +} + +int ua_ioctl(void* dev, int cmd, void *arg) +{ + return EOK; +} + + diff --git a/APP_Framework/Framework/control/plc/interoperability/opcua/ua_api.h b/APP_Framework/Framework/control/plc/interoperability/opcua/ua_api.h index 30345d4c5..38135fef1 100755 --- a/APP_Framework/Framework/control/plc/interoperability/opcua/ua_api.h +++ b/APP_Framework/Framework/control/plc/interoperability/opcua/ua_api.h @@ -28,4 +28,11 @@ void ua_browser_nodes(UA_Client *client); void ua_read_time(UA_Client *client); int16 ua_test(void); + +int ua_open(void *dev); // open and connect PLC device +void ua_close(void* dev); // close and disconnect PLC device +int ua_read(void* dev, void *buf, size_t len); // read data from PLC +int ua_write(void* dev, const void *buf, size_t len); // write data from PLC +int ua_ioctl(void* dev, int cmd, void *arg); // send control command to PLC + #endif diff --git a/APP_Framework/Framework/control/plc/shared/Makefile b/APP_Framework/Framework/control/plc/shared/Makefile index 03bb1bbf7..1f0543f9a 100755 --- a/APP_Framework/Framework/control/plc/shared/Makefile +++ b/APP_Framework/Framework/control/plc/shared/Makefile @@ -1,4 +1,4 @@ -SRC_FILES := plc.c +SRC_FILES := plc.c plc_dev.c plc_bus.c plc_drv.c include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Framework/control/plc/shared/plc.c b/APP_Framework/Framework/control/plc/shared/plc.c index b30206836..0ea0c220c 100755 --- a/APP_Framework/Framework/control/plc/shared/plc.c +++ b/APP_Framework/Framework/control/plc/shared/plc.c @@ -18,40 +18,168 @@ * @date 2021.12.15 */ -#include "../interoperability/opcua/open62541.h" +#include "open62541.h" +#include "ua_api.h" #include "plc.h" +#include "plc_bus.h" +#include "plc_dev.h" struct PlcDevice plc_device; -// open and connect PLC device -void plc_open(struct PlcDevice *pdev) +static DoubleLinklistType plcdev_list; + +int PlcDevConfigure(struct HardwareDev *dev, uint8 plc_chip_select, uint8 plc_cs_release); + + +/*Create the plc device linklist*/ +static void PlcDeviceLinkInit() { + InitDoubleLinkList(&plcdev_list); } -// close and disconnect PLC device -void plc_close(struct PlcDevice *pdev) +static int PlcDeviceOpen(void *dev) { + NULL_PARAM_CHECK(dev); + + struct PlcDevice *plc_dev = (struct PlcDevice *)dev; + + if(plc_dev->net == PLC_IND_ENET_OPCUA) + { + return ua_open(dev); + } + + return EOK; } -// read data from PLC -void plc_read(struct PlcDevice *pdev, void *buf, size_t len) +static void PlcDeviceClose(void *dev) { + NULL_PARAM_CHECK(dev); + + struct PlcDevice *plc_dev = (struct PlcDevice *)dev; + + if(plc_dev->net == PLC_IND_ENET_OPCUA) + { + ua_close(dev); + } } -// write data from PLC -void plc_write(struct PlcDevice *pdev, const void *buf, size_t len) +static int PlcDeviceWrite(void *dev, const void *buf, size_t len) { + NULL_PARAM_CHECK(dev); + NULL_PARAM_CHECK(write_param); + + int ret; + struct PlcDevice *plc_dev = (struct PlcDevice *)dev; + + if(plc_dev->net == PLC_IND_ENET_OPCUA) + { + ret = ua_write(dev, buf, len); + } + + return ret; } -// send control command to PLC -void plc_ioctl(struct PlcDevice *pdev, int cmd, void *arg) +static int PlcDeviceRead(void *dev, void *buf, size_t len) { + NULL_PARAM_CHECK(dev); + NULL_PARAM_CHECK(read_param); + + int ret; + struct PlcDevice *plc_dev = (struct PlcDevice *)dev; + + if(plc_dev->net == PLC_IND_ENET_OPCUA) + { + ret = ua_read(dev, buf, len); + } + + return ret; } - -void plc_init(struct PlcDevice *plc_dev) +static const struct PlcOps plc_done = { + .open = PlcDeviceOpen, + .close = PlcDeviceClose, + .write = PlcDeviceWrite, + .read = PlcDeviceRead, +}; + +struct PlcDevice *PlcDevFind(const char *dev_name, enum DevType dev_type) +{ + NULL_PARAM_CHECK(dev_name); + + struct PlcDevice *device = NONE; + + DoubleLinklistType *node = NONE; + DoubleLinklistType *head = &plcdev_list; + + for (node = head->node_next; node != head; node = node->node_next) { + device = SYS_DOUBLE_LINKLIST_ENTRY(node, struct PlcDevice, link); + if ((!strcmp(device->name, dev_name)) && (dev_type == device->type)) { + return device; + } + } + + KPrintf("PlcDevFind cannot find the %s device.return NULL\n", dev_name); + return NONE; } +int PlcDevRegister(struct PlcDevice *plc_device, void *plc_param, const char *device_name) +{ + NULL_PARAM_CHECK(plc_device); + NULL_PARAM_CHECK(device_name); + + x_err_t ret = EOK; + static x_bool dev_link_flag = RET_FALSE; + + if (!dev_link_flag) { + PlcDeviceLinkInit(); + dev_link_flag = RET_TRUE; + } + + if (DEV_INSTALL != plc_device->state) { + strncpy(plc_device->name, device_name, strlen(device_name)); + DoubleLinkListInsertNodeAfter(&plcdev_list, &(plc_device->link)); + plc_device->state = DEV_INSTALL; + } else { + KPrintf("PlcDevRegister device has been register state%u\n", plc_device->type); + } + + return ret; +} + +int PlcDeviceAttachToBus(const char *dev_name, const char *bus_name) +{ + NULL_PARAM_CHECK(dev_name); + NULL_PARAM_CHECK(bus_name); + + x_err_t ret = EOK; + + struct Bus *bus; + struct HardwareDev *device; + + bus = BusFind(bus_name); + if (NONE == bus) { + KPrintf("PlcDeviceAttachToBus find plc bus error!name %s\n", bus_name); + return ERROR; + } + + if (TYPE_PLC_BUS == bus->bus_type) { + device = PlcHardwareDevFind(dev_name, TYPE_PLC_DEV); + if (NONE == device) { + KPrintf("PlcDeviceAttachToBus find plc device error!name %s\n", dev_name); + return ERROR; + } + + if (TYPE_PLC_DEV == device->dev_type) { + ret = DeviceRegisterToBus(bus, device); + if (EOK != ret) { + KPrintf("PlcDeviceAttachToBus DeviceRegisterToBus error %u\n", ret); + return ERROR; + } + } + } + + return EOK; +} diff --git a/APP_Framework/Framework/control/plc/shared/plc.h b/APP_Framework/Framework/control/plc/shared/plc.h index a36ef33b8..c8c8726fc 100755 --- a/APP_Framework/Framework/control/plc/shared/plc.h +++ b/APP_Framework/Framework/control/plc/shared/plc.h @@ -18,6 +18,7 @@ * @date 2021.12.15 */ +#include "bus.h" #include "xs_klist.h" #define IP_ADDR_SIZE 32 @@ -56,11 +57,11 @@ struct PlcDevice; // operation API struct PlcOps { - int (*open)(struct PlcDevice *pdev); // open and connect PLC device - void (*close)(struct PlcDevice*pdev); // close and disconnect PLC device - int (*read)(struct PlcDevice* pdev, void *buf, size_t len); // read data from PLC - int (*write)(struct PlcDevice* pdev, const void *buf, size_t len); // write data from PLC - int (*ioctl)(struct PlcDevice* pdev, int cmd, void *arg); // send control command to PLC + int (*open)(void *dev); // open and connect PLC device + void (*close)(void* dev); // close and disconnect PLC device + int (*read)(void* dev, void *buf, size_t len); // read data from PLC + int (*write)(void* dev, const void *buf, size_t len); // write data from PLC + int (*ioctl)(void* dev, int cmd, void *arg); // send control command to PLC }; enum PlcCtlType { @@ -105,16 +106,18 @@ enum PlcTransType //communication interface struct PlcInterface { - enum PlcIndHybridNet net; - enum PlcTransType trans; char ip_addr[IP_ADDR_SIZE]; char attrib; }; // identify PLC device struct PlcDevice { - const char name[PLC_NAME_SIZE]; /* name of the device */ + char name[PLC_NAME_SIZE]; /* name of the device */ enum PlcCtlType type; /* PLC Control Type */ + enum DevState state; + enum PlcIndHybridNet net; + enum PlcTransType trans; + struct PlcInfo info;/* Plc info, such as vendor name and model name */ union PlcCfg cfg; struct PlcOps ops; /* filesystem-like APIs for data transferring */ diff --git a/APP_Framework/Framework/control/plc/shared/plc_bus.c b/APP_Framework/Framework/control/plc/shared/plc_bus.c new file mode 100755 index 000000000..24697b59e --- /dev/null +++ b/APP_Framework/Framework/control/plc/shared/plc_bus.c @@ -0,0 +1,117 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file plc_bus.c +* @brief register plc bus function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2021-04-24 +*/ + +#include "plc_bus.h" +#include "plc_dev.h" + +int PlcBusInit(struct PlcBus *plc_bus, const char *bus_name) +{ + NULL_PARAM_CHECK(plc_bus); + NULL_PARAM_CHECK(bus_name); + + x_err_t ret = EOK; + + if (BUS_INSTALL != plc_bus->bus.bus_state) { + strncpy(plc_bus->bus.bus_name, bus_name, NAME_NUM_MAX); + + plc_bus->bus.bus_type = TYPE_PLC_BUS; + plc_bus->bus.bus_state = BUS_INSTALL; + plc_bus->bus.private_data = plc_bus->private_data; + + ret = BusRegister(&plc_bus->bus); + if (EOK != ret) { + KPrintf("PlcBusInit BusRegister error %u\n", ret); + return ret; + } + } else { + KPrintf("PlcBusInit BusRegister bus has been register state%u\n", plc_bus->bus.bus_state); + } + + return ret; +} + +int PlcDriverInit(struct PlcDriver *plc_driver, const char *driver_name) +{ + NULL_PARAM_CHECK(plc_driver); + NULL_PARAM_CHECK(driver_name); + + x_err_t ret = EOK; + + if (DRV_INSTALL != plc_driver->driver.driver_state) { + plc_driver->driver.driver_type = TYPE_PLC_DRV; + plc_driver->driver.driver_state = DRV_INSTALL; + + strncpy(plc_driver->driver.drv_name, driver_name, NAME_NUM_MAX); + + plc_driver->driver.configure = plc_driver->configure; + + ret = PlcDriverRegister(&plc_driver->driver); + if (EOK != ret) { + KPrintf("PlcDriverInit DriverRegister error %u\n", ret); + return ret; + } + } else { + KPrintf("PlcDriverInit DriverRegister driver has been register state%u\n", plc_driver->driver.driver_state); + } + + return ret; +} + +int PlcReleaseBus(struct PlcBus *plc_bus) +{ + NULL_PARAM_CHECK(plc_bus); + + return BusRelease(&plc_bus->bus); +} + +int PlcDriverAttachToBus(const char *drv_name, const char *bus_name) +{ + NULL_PARAM_CHECK(drv_name); + NULL_PARAM_CHECK(bus_name); + + x_err_t ret = EOK; + + struct Bus *bus; + struct Driver *driver; + + bus = BusFind(bus_name); + if (NONE == bus) { + KPrintf("PlcDriverAttachToBus find plc bus error!name %s\n", bus_name); + return ERROR; + } + + if (TYPE_PLC_BUS == bus->bus_type) { + driver = PlcDriverFind(drv_name, TYPE_PLC_DRV); + if (NONE == driver) { + KPrintf("PlcDriverAttachToBus find plc driver error!name %s\n", drv_name); + return ERROR; + } + + if (TYPE_PLC_DRV == driver->driver_type) { + ret = DriverRegisterToBus(bus, driver); + if (EOK != ret) { + KPrintf("PlcDriverAttachToBus DriverRegisterToBus error %u\n", ret); + return ERROR; + } + } + } + + return ret; +} diff --git a/APP_Framework/Framework/control/plc/shared/plc_bus.h b/APP_Framework/Framework/control/plc/shared/plc_bus.h new file mode 100755 index 000000000..6bed62b22 --- /dev/null +++ b/APP_Framework/Framework/control/plc/shared/plc_bus.h @@ -0,0 +1,66 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file plc_bus.h +* @brief define plc bus and drv function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2021-04-24 +*/ + +#ifndef __PLC_BUS_H_ +#define __PLC_BUS_H_ + +#include "bus.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PlcDriver +{ + struct Driver driver; + + uint32 (*configure) (void *drv, struct BusConfigureInfo *configure_info); +}; + +struct PlcBus +{ + struct Bus bus; + + void *private_data; +}; + +/*Register the plc bus*/ +int PlcBusInit(struct PlcBus *plc_bus, const char *bus_name); + +/*Register the plc driver*/ +int PlcDriverInit(struct PlcDriver *plc_driver, const char *driver_name); + +/*Release the plc device*/ +int PlcReleaseBus(struct PlcBus *plc_bus); + +/*Register the plc driver to the plc bus*/ +int PlcDriverAttachToBus(const char *drv_name, const char *bus_name); + +/*Register the driver, manage with the double linklist*/ +int PlcDriverRegister(struct Driver *driver); + +/*Find the register driver*/ +DriverType PlcDriverFind(const char *drv_name, enum DriverType_e drv_type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/APP_Framework/Framework/control/plc/shared/plc_dev.c b/APP_Framework/Framework/control/plc/shared/plc_dev.c new file mode 100755 index 000000000..da28a5ba0 --- /dev/null +++ b/APP_Framework/Framework/control/plc/shared/plc_dev.c @@ -0,0 +1,235 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file plc_dev.c +* @brief register plc dev function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2021-04-24 +*/ + +#include "plc_bus.h" +#include "plc_dev.h" + +static DoubleLinklistType plcdev_linklist; + +/*Create the plc device linklist*/ +static void PlcHardwareDevLinkInit() +{ + InitDoubleLinkList(&plcdev_linklist); +} + +static uint32 PlcHardwareDevOpen(void *dev) +{ + NULL_PARAM_CHECK(dev); + + PlcHardwareDevConfigureCs(dev, 1, 0); + + return EOK; +} + +static uint32 PlcHardwareDevClose(void *dev) +{ + NULL_PARAM_CHECK(dev); + + PlcHardwareDevConfigureCs(dev, 0, 1); + + return EOK; +} + +static uint32 PlcHardwareDevWrite(void *dev, struct BusBlockWriteParam *write_param) +{ + NULL_PARAM_CHECK(dev); + NULL_PARAM_CHECK(write_param); + + int ret; + struct PlcHardwareDevice *plc_dev = (struct PlcHardwareDevice *)dev; + struct PlcDataStandard *plc_msg; + + plc_msg = (struct PlcDataStandard *)x_malloc(sizeof(struct PlcDataStandard)); + if (NONE == plc_msg) { + KPrintf("PlcHardwareDevWrite x_malloc msg error\n"); + x_free(plc_msg); + return ERROR; + } + + //memset(plc_msg, 0, sizeof(struct PlcDataStandard)); + + plc_msg->tx_buff = (uint8 *)write_param->buffer; + plc_msg->rx_buff = NONE; + plc_msg->length = write_param->size; + plc_msg->plc_chip_select = 0; + plc_msg->plc_cs_release = 0; + plc_msg->next = NONE; + + ret = plc_dev->plc_dev_done->dev_write(plc_dev, plc_msg); + x_free(plc_msg); + + return ret; +} + +static uint32 PlcHardwareDevRead(void *dev, struct BusBlockReadParam *read_param) +{ + NULL_PARAM_CHECK(dev); + NULL_PARAM_CHECK(read_param); + + int ret; + struct PlcHardwareDevice *plc_dev = (struct PlcHardwareDevice *)dev; + struct PlcDataStandard *plc_msg; + + plc_msg = (struct PlcDataStandard *)x_malloc(sizeof(struct PlcDataStandard)); + if (NONE == plc_msg) { + KPrintf("PlcHardwareDevRead x_malloc msg error\n"); + x_free(plc_msg); + return ERROR; + } + + //memset(plc_msg, 0, sizeof(struct PlcDataStandard)); + + plc_msg->tx_buff = NONE; + plc_msg->rx_buff = (uint8 *)read_param->buffer; + plc_msg->length = read_param->size; + plc_msg->plc_chip_select = 0; + plc_msg->plc_cs_release = 0; + plc_msg->next = NONE; + + ret = plc_dev->plc_dev_done->dev_read(plc_dev, plc_msg); + x_free(plc_msg); + + return ret; +} + +static const struct HalDevDone dev_done = +{ + .open = PlcHardwareDevOpen, + .close = PlcHardwareDevClose, + .write = PlcHardwareDevWrite, + .read = PlcHardwareDevRead, +}; + +HardwareDevType PlcHardwareDevFind(const char *dev_name, enum DevType dev_type) +{ + NULL_PARAM_CHECK(dev_name); + + struct HardwareDev *device = NONE; + + DoubleLinklistType *node = NONE; + DoubleLinklistType *head = &plcdev_linklist; + + for (node = head->node_next; node != head; node = node->node_next) { + device = SYS_DOUBLE_LINKLIST_ENTRY(node, struct HardwareDev, dev_link); + if ((!strcmp(device->dev_name, dev_name)) && (dev_type == device->dev_type)) { + return device; + } + } + + KPrintf("PlcHardwareDevFind cannot find the %s device.return NULL\n", dev_name); + return NONE; +} + +int PlcHardwareDevRegister(struct PlcHardwareDevice *plc_device, void *plc_param, const char *device_name) +{ + NULL_PARAM_CHECK(plc_device); + NULL_PARAM_CHECK(device_name); + + x_err_t ret = EOK; + static x_bool dev_link_flag = RET_FALSE; + + if (!dev_link_flag) { + PlcHardwareDevLinkInit(); + dev_link_flag = RET_TRUE; + } + + if (DEV_INSTALL != plc_device->haldev.dev_state) { + strncpy(plc_device->haldev.dev_name, device_name, NAME_NUM_MAX); + plc_device->haldev.dev_type = TYPE_PLC_DEV; + plc_device->haldev.dev_state = DEV_INSTALL; + + //only plc bus dev need to register dev_done + if (RET_TRUE != plc_device->plc_dev_flag) { + plc_device->haldev.dev_done = &dev_done; + } + + plc_device->haldev.private_data = plc_param; + + DoubleLinkListInsertNodeAfter(&plcdev_linklist, &(plc_device->haldev.dev_link)); + } else { + KPrintf("PlcHardwareDevRegister device has been register state%u\n", plc_device->haldev.dev_state); + } + + return ret; +} + +int PlcHardwareDevAttachToBus(const char *dev_name, const char *bus_name) +{ + NULL_PARAM_CHECK(dev_name); + NULL_PARAM_CHECK(bus_name); + + x_err_t ret = EOK; + + struct Bus *bus; + struct HardwareDev *device; + + bus = BusFind(bus_name); + if (NONE == bus) { + KPrintf("PlcHardwareDevAttachToBus find plc bus error!name %s\n", bus_name); + return ERROR; + } + + if (TYPE_PLC_BUS == bus->bus_type) { + device = PlcHardwareDevFind(dev_name, TYPE_PLC_DEV); + if (NONE == device) { + KPrintf("PlcHardwareDevAttachToBus find plc device error!name %s\n", dev_name); + return ERROR; + } + + if (TYPE_PLC_DEV == device->dev_type) { + ret = DeviceRegisterToBus(bus, device); + if (EOK != ret) { + KPrintf("PlcHardwareDevAttachToBus DeviceRegisterToBus error %u\n", ret); + return ERROR; + } + } + } + + return EOK; +} + +int PlcHardwareDevConfigureCs(struct HardwareDev *dev, uint8 plc_chip_select, uint8 plc_cs_release) +{ + NULL_PARAM_CHECK(dev); + + int ret; + struct PlcHardwareDevice *plc_dev = (struct PlcHardwareDevice *)dev; + struct PlcDataStandard *msg; + + msg = (struct PlcDataStandard *)x_malloc(sizeof(struct PlcDataStandard)); + if (NONE == msg) { + KPrintf("PlcHardwareDevConfigureCs x_malloc msg error\n"); + x_free(msg); + return ERROR; + } + + //memset(msg, 0, sizeof(struct PlcDataStandard)); + msg->length = 0; + msg->rx_buff = NONE; + msg->tx_buff = NONE; + msg->next = NONE; + msg->plc_chip_select = plc_chip_select; + msg->plc_cs_release = plc_cs_release; + + ret = plc_dev->plc_dev_done->dev_write(plc_dev, msg); + + x_free(msg); + return ret; +} diff --git a/APP_Framework/Framework/control/plc/shared/plc_dev.h b/APP_Framework/Framework/control/plc/shared/plc_dev.h new file mode 100755 index 000000000..f9eec1ffa --- /dev/null +++ b/APP_Framework/Framework/control/plc/shared/plc_dev.h @@ -0,0 +1,139 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file plc_dev.h +* @brief define plc dev function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2021-04-24 +*/ + +#ifndef __PLC_DEV_H_ +#define __PLC_DEV_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define PLC_MAX_CLOCK 40000000 +#define plc_device_max_num 4 + +#define PLC_LINE_CPHA (1<<0) +#define PLC_LINE_CPOL (1<<1) + +#define PLC_LSB (0<<2) +#define PLC_MSB (1<<2) + +#define PLC_MASTER (0<<3) +#define DEV_PLC_SLAVE (1<<3) + +#define PLC_MODE_0 (0 | 0) +#define PLC_MODE_1 (0 | PLC_LINE_CPHA) +#define PLC_MODE_2 (PLC_LINE_CPOL | 0) +#define PLC_MODE_3 (PLC_LINE_CPOL | PLC_LINE_CPHA) +#define PLC_MODE_MASK (PLC_LINE_CPHA | PLC_LINE_CPOL | PLC_MSB) + +#define PLC_CS_HIGH (1<<4) +#define PLC_NO_CS (1<<5) +#define PLC_3WIRE (1<<6) +#define PLC_READY (1<<7) + +struct PlcDataStandard +{ + uint8 plc_chip_select; + uint8 plc_cs_release; + + const uint8 *tx_buff; + uint32 tx_len; + + uint8 *rx_buff; + uint32 rx_len; + + uint32 length; + struct PlcDataStandard *next; +}; + +struct PlcMasterParam +{ + uint8 plc_work_mode;//CPOL CPHA + uint8 plc_frame_format;//frame format + uint8 plc_data_bit_width;//bit width + uint8 plc_data_endian;//little endian:0,big endian:1 + uint32 plc_maxfrequency;//work frequency +}; + +struct PlcDmaParam +{ + uint8 plc_master_id; + uint8 plc_dmac_txchannel; + uint8 plc_dmac_rxchannel; +}; + +struct PlcSlaveParam +{ + uint8 plc_slave_id; + uint8 plc_cs_gpio_pin; + uint8 plc_cs_select_id; +}; + +typedef struct +{ + struct PlcDmaParam *plc_dma_param; + + struct PlcSlaveParam *plc_slave_param; + + struct PlcMasterParam *plc_master_param; + +}PlcDeviceParam; + +struct PlcHardwareDevice; + +struct PlcDevDone +{ + uint32 (*dev_open) (struct PlcHardwareDevice *dev); + uint32 (*dev_close) (struct PlcHardwareDevice *dev); + uint32 (*dev_write) (struct PlcHardwareDevice *dev, struct PlcDataStandard *msg); + uint32 (*dev_read) (struct PlcHardwareDevice *dev, struct PlcDataStandard *msg); +}; + +struct PlcHardwareDevice +{ + struct HardwareDev haldev; + PlcDeviceParam plc_param; + + x_bool plc_dev_flag; + + const struct PlcDevDone *plc_dev_done; + + void *private_data; +}; + +/*Register the plc device*/ +int PlcHardwareDevRegister(struct PlcHardwareDevice *plc_device, void *plc_param, const char *device_name); + +/*Register the plc device to the plc bus*/ +int PlcHardwareDeviceAttachToBus(const char *dev_name, const char *bus_name); + +/*Find the register plc device*/ +HardwareDevType PlcHardwareDevFind(const char *dev_name, enum DevType dev_type); + +/*Configure the cs pin of plc dev*/ +int PlcHardwareDevConfigureCs(struct HardwareDev *dev, uint8 plc_chip_select, uint8 plc_cs_release); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/APP_Framework/Framework/control/plc/shared/plc_drv.c b/APP_Framework/Framework/control/plc/shared/plc_drv.c new file mode 100755 index 000000000..2f934fdb8 --- /dev/null +++ b/APP_Framework/Framework/control/plc/shared/plc_drv.c @@ -0,0 +1,67 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file plc_drv.c +* @brief register plc drv function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2021-04-24 +*/ + +#include "plc_bus.h" +#include "plc_dev.h" + +static DoubleLinklistType plcdrv_linklist; + +/*Create the driver linklist*/ +static void PlcDrvLinkInit() +{ + InitDoubleLinkList(&plcdrv_linklist); +} + +DriverType PlcDriverFind(const char *drv_name, enum DriverType_e drv_type) +{ + NULL_PARAM_CHECK(drv_name); + + struct Driver *driver = NONE; + + DoubleLinklistType *node = NONE; + DoubleLinklistType *head = &plcdrv_linklist; + + for (node = head->node_next; node != head; node = node->node_next) { + driver = SYS_DOUBLE_LINKLIST_ENTRY(node, struct Driver, driver_link); + if ((!strcmp(driver->drv_name, drv_name)) && (drv_type == driver->driver_type)) { + return driver; + } + } + + KPrintf("PlcDriverFind cannot find the %s driver.return NULL\n", drv_name); + return NONE; +} + +int PlcDriverRegister(struct Driver *driver) +{ + NULL_PARAM_CHECK(driver); + + x_err_t ret = EOK; + static x_bool driver_link_flag = RET_FALSE; + + if (!driver_link_flag) { + PlcDrvLinkInit(); + driver_link_flag = RET_TRUE; + } + + DoubleLinkListInsertNodeAfter(&plcdrv_linklist, &(driver->driver_link)); + + return ret; +} diff --git a/APP_Framework/Framework/control/shared/Makefile b/APP_Framework/Framework/control/shared/Makefile index f16a4f9b9..4890d7675 100755 --- a/APP_Framework/Framework/control/shared/Makefile +++ b/APP_Framework/Framework/control/shared/Makefile @@ -1,5 +1,4 @@ -SRC_DIR := +SRC_FILES := control.c include $(KERNEL_ROOT)/compiler.mk - diff --git a/APP_Framework/Framework/control/shared/config.json b/APP_Framework/Framework/control/shared/config.json new file mode 100755 index 000000000..05b79a6a3 --- /dev/null +++ b/APP_Framework/Framework/control/shared/config.json @@ -0,0 +1,38 @@ +{ +"siemens plc": +{ + "device type": "PLC", + "control type": "HSC", + "info": + { + "plc ability" : 1, + "plc device id": 1, + "soft version" : 1, + "hardware version": 1, + "date": "2022-1-28", + "vendor": "siemens", + "model":"S300" + }, + + "serial config": + { + "serial type":"485", + "station id" : "station1", + "serial port" : 1 + }, + + "network config": + { + "ip addr" : "192.168.250.5", + "ip port" : 4840 + }, + + "interface": + { + "inhybridnet":"OPCUA", + "transport":"TCP", + "ip address": "192.168.250.5", + "attribute" : "1" + } +} +} diff --git a/APP_Framework/Framework/control/shared/control.c b/APP_Framework/Framework/control/shared/control.c index 4ec32b19d..2d86a2d6b 100755 --- a/APP_Framework/Framework/control/shared/control.c +++ b/APP_Framework/Framework/control/shared/control.c @@ -1,4 +1,8 @@ +#include "cJSON.h" + + + void control_init(void) { @@ -6,6 +10,12 @@ void control_init(void) void control_read_file() { + + + + } + + diff --git a/Ubiquitous/XiUOS/kernel/include/xs_poll.h b/Ubiquitous/XiUOS/kernel/include/xs_poll.h index df228c830..22563436b 100644 --- a/Ubiquitous/XiUOS/kernel/include/xs_poll.h +++ b/Ubiquitous/XiUOS/kernel/include/xs_poll.h @@ -26,6 +26,8 @@ #include #include +typedef unsigned long NfdsType; + #if !defined(POLLIN) && !defined(POLLOUT) #define POLLIN 0x001 @@ -36,8 +38,6 @@ #define POLLMASK_DEFAULT (POLLIN | POLLOUT ) -typedef unsigned long NfdsType; - struct pollfd { int fd; @@ -54,6 +54,7 @@ typedef struct Pollreq } pollreqType; void PollAdd(WaitQueueType *wq, pollreqType *req); +#ifndef poll int poll(struct pollfd *fds, NfdsType nfds, int timeout); - +#endif #endif diff --git a/Ubiquitous/XiUOS/path_app.mk b/Ubiquitous/XiUOS/path_app.mk index 38f5f080a..f33f74060 100644 --- a/Ubiquitous/XiUOS/path_app.mk +++ b/Ubiquitous/XiUOS/path_app.mk @@ -26,6 +26,7 @@ endif ifeq ($(CONFIG_SUPPORT_CONTROL_FRAMEWORK), y) APPPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control # APPPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/plc/interoperability/opcua # +APPPATHS += -I$(KERNEL_ROOT)/../../APP_Framework\lib\cJSON endif ifeq ($(CONFIG_CRYPTO), y) diff --git a/Ubiquitous/XiUOS/path_kernel.mk b/Ubiquitous/XiUOS/path_kernel.mk index a618d3ad3..7f198a49a 100755 --- a/Ubiquitous/XiUOS/path_kernel.mk +++ b/Ubiquitous/XiUOS/path_kernel.mk @@ -189,6 +189,7 @@ KERNELPATHS :=-I$(BSP_ROOT) \ -I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/priv \ -I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/prot \ -I$(KERNEL_ROOT)/resources/ethernet/LwIP/arch \ + -I$(KERNEL_ROOT)/resources/include \ -I$(BSP_ROOT)/include # endif @@ -258,6 +259,7 @@ endif ifeq ($(CONFIG_SUPPORT_CONTROL_FRAMEWORK), y) KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control # KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/plc/interoperability/opcua # +KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/lib/cJSON endif ifeq ($(CONFIG_CRYPTO), y) diff --git a/Ubiquitous/XiUOS/resources/include/bus.h b/Ubiquitous/XiUOS/resources/include/bus.h index 5cd0fd314..a9147f690 100644 --- a/Ubiquitous/XiUOS/resources/include/bus.h +++ b/Ubiquitous/XiUOS/resources/include/bus.h @@ -54,6 +54,7 @@ enum BusType_e TYPE_SERIAL_BUS, TYPE_ADC_BUS, TYPE_DAC_BUS, + TYPE_PLC_BUS, TYPE_BUS_END, }; @@ -80,6 +81,7 @@ enum DevType TYPE_SERIAL_DEV, TYPE_ADC_DEV, TYPE_DAC_DEV, + TYPE_PLC_DEV, TYPE_DEV_END, }; @@ -106,6 +108,7 @@ enum DriverType_e TYPE_SERIAL_DRV, TYPE_ADC_DRV, TYPE_DAC_DRV, + TYPE_PLC_DRV, TYPE_DRV_END, };