diff --git a/APP_Framework/Applications/Kconfig b/APP_Framework/Applications/Kconfig index eb11622e7..1545222da 100644 --- a/APP_Framework/Applications/Kconfig +++ b/APP_Framework/Applications/Kconfig @@ -20,4 +20,5 @@ menu "Applications" source "$APP_DIR/Applications/sensor_app/Kconfig" source "$APP_DIR/Applications/embedded_database_app/Kconfig" source "$APP_DIR/Applications/webnet/Kconfig" + source "$APP_DIR/Applications/mongoose/Kconfig" endmenu diff --git a/APP_Framework/Applications/Makefile b/APP_Framework/Applications/Makefile index 334845b8a..ab9e2f59a 100644 --- a/APP_Framework/Applications/Makefile +++ b/APP_Framework/Applications/Makefile @@ -39,6 +39,10 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y) ifeq ($(CONFIG_APP_USING_WEBNET),y) SRC_DIR += webnet endif + + ifeq ($(CONFIG_USE_MONGOOSE),y) + SRC_DIR += mongoose + endif include $(KERNEL_ROOT)/compiler.mk endif \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/Kconfig b/APP_Framework/Applications/app_test/Kconfig index 74b6d0973..5a0d46740 100644 --- a/APP_Framework/Applications/app_test/Kconfig +++ b/APP_Framework/Applications/app_test/Kconfig @@ -281,6 +281,7 @@ menu "test app" menuconfig USER_TEST_MQTTCLIENT bool "Config test mqtt client" default n + select LIB_USING_CJSON menuconfig USER_TEST_FTPCLIENT bool "Config test ftp client" diff --git a/APP_Framework/Applications/app_test/Makefile b/APP_Framework/Applications/app_test/Makefile index c15e802a4..5416c3304 100644 --- a/APP_Framework/Applications/app_test/Makefile +++ b/APP_Framework/Applications/app_test/Makefile @@ -150,7 +150,9 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y) endif ifeq ($(CONFIG_USER_TEST_FTPCLIENT_RISCV),y) - SRC_FILES += test_ftpclient_riscv/test_ftpclient_riscv.c + ifeq ($(CONFIG_BSP_USING_W5500),y) + SRC_FILES += test_ftpclient_riscv/test_ftpclient_riscv.c + endif endif ifeq ($(CONFIG_USER_TEST_LORA_P2P),y) diff --git a/APP_Framework/Applications/app_test/test_can.c b/APP_Framework/Applications/app_test/test_can.c index c19abecdb..c6463bc27 100644 --- a/APP_Framework/Applications/app_test/test_can.c +++ b/APP_Framework/Applications/app_test/test_can.c @@ -60,7 +60,6 @@ void TestCAN(void) frame_send.stdid = 0x55; frame_send.rtr=0; frame_send.data_lenth=8; - frame_send.data = data_buff; struct CanSendConfigure frame_recv; uint8_t recv_buff[65U] = {0}; @@ -69,13 +68,20 @@ void TestCAN(void) // CAN write while (1) { - PrivTaskDelay(500); - PrivWrite(can_fd, &frame_send, NONE); - PrivTaskDelay(500); + // PrivTaskDelay(500); + // PrivWrite(can_fd, &frame_send, NONE); + // PrivTaskDelay(500); PrivRead(can_fd, &frame_recv, NONE); // if any data has received,Then printf message if(frame_recv.data_lenth > 0){ - printf("ID %08x:%s\n",frame_recv.exdid,frame_recv.data); + printf("ID %08x : \n",frame_recv.exdid); + for(int i = 0; i < frame_recv.data_lenth; i ++) { + printf("0x%x ", frame_recv.data[i]); + } + printf("\n"); + + frame_send.data = recv_buff; + PrivWrite(can_fd, &frame_send, NONE); } } diff --git a/APP_Framework/Applications/app_test/test_ethernet.c b/APP_Framework/Applications/app_test/test_ethernet.c index 9f4a4ce8f..59ef761c8 100644 --- a/APP_Framework/Applications/app_test/test_ethernet.c +++ b/APP_Framework/Applications/app_test/test_ethernet.c @@ -22,6 +22,7 @@ #include #ifdef ADD_XIZI_FEATURES +#ifdef BSP_USING_W5500 #include #define BUFF_SIZE 128 @@ -189,6 +190,6 @@ PRIV_SHELL_CMD_FUNCTION(TestSocketAsClient, a w5500 client-ip-port-msg test samp #endif - +#endif #endif \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/test_loraE220.c b/APP_Framework/Applications/app_test/test_loraE220.c index 90682c990..7fa2ace08 100644 --- a/APP_Framework/Applications/app_test/test_loraE220.c +++ b/APP_Framework/Applications/app_test/test_loraE220.c @@ -98,6 +98,7 @@ void TestLora(int argc, char *argv[]) uart_cfg.serial_buffer_size = SERIAL_RB_BUFSZ; uart_cfg.serial_timeout = 1000; uart_cfg.is_ext_uart = 0; + uart_cfg.dev_recv_callback = NULL; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; ioctl_cfg.args = (void *)&uart_cfg; diff --git a/APP_Framework/Applications/app_test/test_lora_net_final/lora_driver/e220.c b/APP_Framework/Applications/app_test/test_lora_net_final/lora_driver/e220.c index db094a145..be667f49d 100755 --- a/APP_Framework/Applications/app_test/test_lora_net_final/lora_driver/e220.c +++ b/APP_Framework/Applications/app_test/test_lora_net_final/lora_driver/e220.c @@ -62,6 +62,7 @@ static struct SerialDataCfg serial_cfg = .serial_buffer_size = SERIAL_RB_BUFSZ, .serial_timeout = E220_DAFAULT_SERIAL_TIMEOUT, // 串口超时配置 .is_ext_uart = 0, + .dev_recv_callback = NULL, }; enum LoraMode current_mode = -1; // 当前模块处于什么模式 diff --git a/APP_Framework/Applications/app_test/test_rs485_arm.c b/APP_Framework/Applications/app_test/test_rs485_arm.c index 0b562359c..de9571bbb 100644 --- a/APP_Framework/Applications/app_test/test_rs485_arm.c +++ b/APP_Framework/Applications/app_test/test_rs485_arm.c @@ -138,6 +138,7 @@ void Test485(void) uart_cfg.serial_buffer_size = SERIAL_RB_BUFSZ; uart_cfg.serial_timeout = -1; uart_cfg.is_ext_uart = 0; + uart_cfg.dev_recv_callback = NULL; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; ioctl_cfg.args = (void *)&uart_cfg; diff --git a/APP_Framework/Applications/app_test/test_rs485_riscv.c b/APP_Framework/Applications/app_test/test_rs485_riscv.c index a31035ebc..5c52ccce8 100644 --- a/APP_Framework/Applications/app_test/test_rs485_riscv.c +++ b/APP_Framework/Applications/app_test/test_rs485_riscv.c @@ -70,6 +70,7 @@ void Test485(void) uart_cfg.serial_buffer_size = SERIAL_RB_BUFSZ; uart_cfg.serial_timeout = 1000; uart_cfg.is_ext_uart = 0; + uart_cfg.dev_recv_callback = NULL; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; ioctl_cfg.args = (void *)&uart_cfg; diff --git a/APP_Framework/Applications/app_test/test_socket.c b/APP_Framework/Applications/app_test/test_socket.c index 2d4d10be9..d717ba251 100644 --- a/APP_Framework/Applications/app_test/test_socket.c +++ b/APP_Framework/Applications/app_test/test_socket.c @@ -76,10 +76,12 @@ struct IperfParam { static void* TestIperfServer(void* param) { struct IperfParam* iperf_param = (struct IperfParam*)param; - int sock = socket(AF_INET, SOCK_STREAM, 0); + int sock = socket(AF_INET, SOCK_STREAM, 6); if (sock < 0) { printf("[%s] Err: Can't create socker.\n", __func__); return NULL; + } else { + printf("[%s] Info Create server socket %d\n", __func__, sock); } uint8_t* recv_data = (uint8_t*)malloc(IPERF_BUFSZ); @@ -121,8 +123,9 @@ static void* TestIperfServer(void* param) socklen_t sin_size = sizeof(struct sockaddr_in); struct sockaddr_in client_addr; int connection = accept(sock, (struct sockaddr*)&client_addr, &sin_size); - printf("[%s] Info: New client connected from (%s, %d)\n", __func__, - inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); + printf("[%s] Info: New client connected from (%s, %d), connect: %d\n", __func__, + inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), + connection); int flag = 1; setsockopt(connection, @@ -141,8 +144,8 @@ static void* TestIperfServer(void* param) inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); break; } else if (bytes_received < 0) { - KPrintf("recv error, client: (%s, %d)\n", - inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); + KPrintf("recv error: %d, client: (%s, %d)\n", + bytes_received, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); break; } @@ -258,8 +261,6 @@ enum IperfParamEnum { void TestSocket(int argc, char* argv[]) { - lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, lwip_gwaddr); - static char usage_info[] = "Run either a iperf server or iperf client."; static char program_info[] = "Lwip socket test task, a simple iperf."; static const char* const usages[] = { diff --git a/APP_Framework/Applications/app_test/test_timer.c b/APP_Framework/Applications/app_test/test_timer.c index 35ec844e3..85059535e 100644 --- a/APP_Framework/Applications/app_test/test_timer.c +++ b/APP_Framework/Applications/app_test/test_timer.c @@ -23,12 +23,13 @@ void TimerFunction(union sigval sig_val) { static int cnt = 0; - printf("%s cnt %d\n", __func__, cnt++); + printf("%s cnt %d ms %d\n", __func__, cnt++, PrivGetTickTime()); } void TestTimer(void) { int ret = 0; + static int count = 0; int timer_flags; timer_t timer_id; struct sigevent evp; @@ -40,7 +41,9 @@ void TestTimer(void) evp.sigev_notify_function = TimerFunction; evp.sigev_notify_attributes = &timer_flags; - ret = timer_create(CLOCK_REALTIME, &evp, &timer_id); + count++; + + ret = PrivTimerCreate(count, &evp, &timer_id); if (ret < 0) { printf("%s create timer failed ret %d\n", __func__, ret); return; @@ -48,14 +51,14 @@ void TestTimer(void) struct itimerspec value; //active time interval - value.it_interval.tv_sec = 2; - value.it_interval.tv_nsec = 0; + value.it_interval.tv_sec = 0; + value.it_interval.tv_nsec = 1000000 * 10; //first timer set time value.it_value.tv_sec = 2; value.it_value.tv_nsec = 0; - ret = timer_settime(timer_id, 1, &value, NULL); + ret = PrivTimerModify(timer_id, 1, &value, NULL); if (ret < 0) { printf("%s set timer time failed ret %d\n", __func__, ret); return; diff --git a/APP_Framework/Applications/app_test/test_uart.c b/APP_Framework/Applications/app_test/test_uart.c index c714269ab..46624d355 100644 --- a/APP_Framework/Applications/app_test/test_uart.c +++ b/APP_Framework/Applications/app_test/test_uart.c @@ -68,6 +68,7 @@ void TestUart(int argc, char* argv[]) uart_cfg.serial_buffer_size = SERIAL_RB_BUFSZ; uart_cfg.serial_timeout = -1; uart_cfg.is_ext_uart = 0; + uart_cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; diff --git a/APP_Framework/Applications/mongoose/Kconfig b/APP_Framework/Applications/mongoose/Kconfig new file mode 100644 index 000000000..90a6f2fbb --- /dev/null +++ b/APP_Framework/Applications/mongoose/Kconfig @@ -0,0 +1,3 @@ +menuconfig USE_MONGOOSE + bool "Use mongoose as webserver" + default n \ No newline at end of file diff --git a/APP_Framework/Applications/mongoose/Makefile b/APP_Framework/Applications/mongoose/Makefile new file mode 100644 index 000000000..40f525b5e --- /dev/null +++ b/APP_Framework/Applications/mongoose/Makefile @@ -0,0 +1,3 @@ +SRC_FILES += project.c + +include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/APP_Framework/Applications/mongoose/lib/Makefile b/APP_Framework/Applications/mongoose/lib/Makefile new file mode 100644 index 000000000..0824ed779 --- /dev/null +++ b/APP_Framework/Applications/mongoose/lib/Makefile @@ -0,0 +1,3 @@ +SRC_FILES += mongoose.c + +include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/APP_Framework/Applications/mongoose/mongoose.a b/APP_Framework/Applications/mongoose/mongoose.a new file mode 100644 index 000000000..fd5000247 Binary files /dev/null and b/APP_Framework/Applications/mongoose/mongoose.a differ diff --git a/APP_Framework/Applications/mongoose/mongoose.h b/APP_Framework/Applications/mongoose/mongoose.h new file mode 100644 index 000000000..eaaf9c2a5 --- /dev/null +++ b/APP_Framework/Applications/mongoose/mongoose.h @@ -0,0 +1,1757 @@ +// Copyright (c) 2004-2013 Sergey Lyubka +// Copyright (c) 2013-2022 Cesanta Software Limited +// All rights reserved +// +// This software is dual-licensed: you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. For the terms of this +// license, see http://www.gnu.org/licenses/ +// +// You are free to use this software under the terms of the GNU General +// Public License, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License for more details. +// +// Alternatively, you can license this software under a commercial +// license, as set out in https://www.mongoose.ws/licensing/ +// +// SPDX-License-Identifier: GPL-2.0-only or commercial + +#ifndef MONGOOSE_H +#define MONGOOSE_H + +#define MG_VERSION "7.11" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MG_ARCH MG_ARCH_RTTHREAD +#define MG_ENABLE_LWIP 1 +#define MG_ENABLE_DIRLIST 1 +#define MG_ENABLE_FATFS 1 +#define MG_ENABLE_SSI 1 +// #define MG_ENABLE_PACKED_FS 1 + +#define MG_ARCH_CUSTOM 0 // User creates its own mongoose_custom.h +#define MG_ARCH_UNIX 1 // Linux, BSD, Mac, ... +#define MG_ARCH_WIN32 2 // Windows +#define MG_ARCH_ESP32 3 // ESP32 +#define MG_ARCH_ESP8266 4 // ESP8266 +#define MG_ARCH_FREERTOS 5 // FreeRTOS +#define MG_ARCH_AZURERTOS 6 // MS Azure RTOS +#define MG_ARCH_ZEPHYR 7 // Zephyr RTOS +#define MG_ARCH_NEWLIB 8 // Bare metal ARM +#define MG_ARCH_CMSIS_RTOS1 9 // CMSIS-RTOS API v1 (Keil RTX) +#define MG_ARCH_TIRTOS 10 // Texas Semi TI-RTOS +#define MG_ARCH_RP2040 11 // Raspberry Pi RP2040 +#define MG_ARCH_ARMCC 12 // Keil MDK-Core with Configuration Wizard +#define MG_ARCH_CMSIS_RTOS2 13 // CMSIS-RTOS API v2 (Keil RTX5, FreeRTOS) +#define MG_ARCH_RTTHREAD 14 // RT-Thread RTOS + +#if !defined(MG_ARCH) +#if defined(__unix__) || defined(__APPLE__) +#define MG_ARCH MG_ARCH_UNIX +#elif defined(_WIN32) +#define MG_ARCH MG_ARCH_WIN32 +#elif defined(ICACHE_FLASH) || defined(ICACHE_RAM_ATTR) +#define MG_ARCH MG_ARCH_ESP8266 +#elif defined(__ZEPHYR__) +#define MG_ARCH MG_ARCH_ZEPHYR +#elif defined(ESP_PLATFORM) +#define MG_ARCH MG_ARCH_ESP32 +#elif defined(FREERTOS_IP_H) +#define MG_ARCH MG_ARCH_FREERTOS +#define MG_ENABLE_FREERTOS_TCP 1 +#elif defined(AZURE_RTOS_THREADX) +#define MG_ARCH MG_ARCH_AZURERTOS +#elif defined(PICO_TARGET_NAME) +#define MG_ARCH MG_ARCH_RP2040 +#elif defined(__ARMCC_VERSION) +#define MG_ARCH MG_ARCH_ARMCC +#elif defined(__RTTHREAD__) +#define MG_ARCH MG_ARCH_RTTHREAD +#endif +#endif // !defined(MG_ARCH) + +// if the user did not specify an MG_ARCH, or specified a custom one, OR +// we guessed a known IDE, pull the customized config (Configuration Wizard) +#if !defined(MG_ARCH) || (MG_ARCH == MG_ARCH_CUSTOM) || MG_ARCH == MG_ARCH_ARMCC +#include "mongoose_custom.h" // keep this include +#endif + +#if !defined(MG_ARCH) +#error "MG_ARCH is not specified and we couldn't guess it. Set -D MG_ARCH=..." +#endif + +// http://esr.ibiblio.org/?p=5095 +#define MG_BIG_ENDIAN (*(uint16_t*)"\0\xff" < 0x100) + +#if MG_ARCH == MG_ARCH_AZURERTOS + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#define PATH_MAX FX_MAXIMUM_PATH +#define MG_DIRSEP '\\' + +#define socklen_t int +#define closesocket(x) soc_close(x) + +#undef FOPEN_MAX + +#endif + +#if MG_ARCH == MG_ARCH_ESP32 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MG_PATH_MAX 128 + +#endif + +#if MG_ARCH == MG_ARCH_ESP8266 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MG_PATH_MAX 128 + +#endif + +#if MG_ARCH == MG_ARCH_FREERTOS + +#include +#if !defined(MG_ENABLE_LWIP) || !MG_ENABLE_LWIP +#include +#endif +#include +#include +#include +#include +#include +#include // rand(), strtol(), atoi() +#include +#if defined(__ARMCC_VERSION) +#define mode_t size_t +#include +#else +#include +#endif + +#include +#include + +#ifndef MG_IO_SIZE +#define MG_IO_SIZE 512 +#endif + +#define calloc(a, b) mg_calloc(a, b) +#define free(a) vPortFree(a) +#define malloc(a) pvPortMalloc(a) +#define strdup(s) ((char*)mg_strdup(mg_str(s)).ptr) + +// Re-route calloc/free to the FreeRTOS's functions, don't use stdlib +static inline void* mg_calloc(size_t cnt, size_t size) +{ + void* p = pvPortMalloc(cnt * size); + if (p != NULL) + memset(p, 0, size * cnt); + return p; +} + +#define mkdir(a, b) mg_mkdir(a, b) +static inline int mg_mkdir(const char* path, mode_t mode) +{ + (void)path, (void)mode; + return -1; +} + +#endif // MG_ARCH == MG_ARCH_FREERTOS + +#if MG_ARCH == MG_ARCH_NEWLIB +#define _POSIX_TIMERS + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MG_PATH_MAX 100 +#define MG_ENABLE_SOCKET 0 +#define MG_ENABLE_DIRLIST 0 + +#endif + +#if MG_ARCH == MG_ARCH_RP2040 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +int mkdir(const char*, mode_t); +#endif + +#if MG_ARCH == MG_ARCH_RTTHREAD + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef MG_IO_SIZE +#define MG_IO_SIZE 1460 +#endif + +#endif // MG_ARCH == MG_ARCH_RTTHREAD + +#if MG_ARCH == MG_ARCH_ARMCC || MG_ARCH == MG_ARCH_CMSIS_RTOS1 || MG_ARCH == MG_ARCH_CMSIS_RTOS2 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if MG_ARCH == MG_ARCH_CMSIS_RTOS1 +#include "cmsis_os.h" // keep this include +// https://developer.arm.com/documentation/ka003821/latest +extern uint32_t rt_time_get(void); +#elif MG_ARCH == MG_ARCH_CMSIS_RTOS2 +#include "cmsis_os2.h" // keep this include +#endif + +#define strdup(s) ((char*)mg_strdup(mg_str(s)).ptr) + +#if defined(__ARMCC_VERSION) +#define mode_t size_t +#define mkdir(a, b) mg_mkdir(a, b) +static inline int mg_mkdir(const char* path, mode_t mode) +{ + (void)path, (void)mode; + return -1; +} +#endif + +#if (MG_ARCH == MG_ARCH_CMSIS_RTOS1 || MG_ARCH == MG_ARCH_CMSIS_RTOS2) && !defined MG_ENABLE_RL && (!defined(MG_ENABLE_LWIP) || !MG_ENABLE_LWIP) && (!defined(MG_ENABLE_TCPIP) || !MG_ENABLE_TCPIP) +#define MG_ENABLE_RL 1 +#endif + +#endif + +#if MG_ARCH == MG_ARCH_TIRTOS + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#endif + +#if MG_ARCH == MG_ARCH_UNIX + +#define _DARWIN_UNLIMITED_SELECT 1 // No limit on file descriptors + +#if defined(__APPLE__) +#include +#endif + +#if !defined(MG_ENABLE_EPOLL) && defined(__linux__) +#define MG_ENABLE_EPOLL 1 +#elif !defined(MG_ENABLE_POLL) +#define MG_ENABLE_POLL 1 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(MG_ENABLE_EPOLL) && MG_ENABLE_EPOLL +#include +#elif defined(MG_ENABLE_POLL) && MG_ENABLE_POLL +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include + +#ifndef MG_ENABLE_DIRLIST +#define MG_ENABLE_DIRLIST 1 +#endif + +#ifndef MG_PATH_MAX +#define MG_PATH_MAX FILENAME_MAX +#endif + +#endif + +#if MG_ARCH == MG_ARCH_WIN32 + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif + +#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS +#define _WINSOCK_DEPRECATED_NO_WARNINGS +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1700 +#define __func__ "" +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +typedef unsigned char uint8_t; +typedef char int8_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned int uint32_t; +typedef int int32_t; +typedef enum { false = 0, + true = 1 } bool; +#else +#include +#include +#include +#endif + +#include +#include +#include + +// Protect from calls like std::snprintf in app code +// See https://github.com/cesanta/mongoose/issues/1047 +#ifndef __cplusplus +#define snprintf _snprintf +#define vsnprintf _vsnprintf +#ifndef strdup // For MSVC with _DEBUG, see #1359 +#define strdup(x) _strdup(x) +#endif +#endif + +#define MG_INVALID_SOCKET INVALID_SOCKET +#define MG_SOCKET_TYPE SOCKET +typedef unsigned long nfds_t; +#if defined(_MSC_VER) +#pragma comment(lib, "ws2_32.lib") +#ifndef alloca +#define alloca(a) _alloca(a) +#endif +#endif +#define poll(a, b, c) WSAPoll((a), (b), (c)) +#define closesocket(x) closesocket(x) + +typedef int socklen_t; +#define MG_DIRSEP '\\' + +#ifndef MG_PATH_MAX +#define MG_PATH_MAX FILENAME_MAX +#endif + +#ifndef SO_EXCLUSIVEADDRUSE +#define SO_EXCLUSIVEADDRUSE ((int)(~SO_REUSEADDR)) +#endif + +#define MG_SOCK_ERR(errcode) ((errcode) < 0 ? WSAGetLastError() : 0) + +#define MG_SOCK_PENDING(errcode) \ + (((errcode) < 0) && (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK)) + +#define MG_SOCK_RESET(errcode) \ + (((errcode) < 0) && (WSAGetLastError() == WSAECONNRESET)) + +#define realpath(a, b) _fullpath((b), (a), MG_PATH_MAX) +#define sleep(x) Sleep((x) * 1000) +#define mkdir(a, b) _mkdir(a) + +#ifndef S_ISDIR +#define S_ISDIR(x) (((x) & _S_IFMT) == _S_IFDIR) +#endif + +#ifndef MG_ENABLE_DIRLIST +#define MG_ENABLE_DIRLIST 1 +#endif + +#ifndef SIGPIPE +#define SIGPIPE 0 +#endif + +#endif + +#if MG_ARCH == MG_ARCH_ZEPHYR + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MG_PUTCHAR(x) printk("%c", x) +#ifndef strdup +#define strdup(s) ((char*)mg_strdup(mg_str(s)).ptr) +#endif +#define strerror(x) zsock_gai_strerror(x) +#define FD_CLOEXEC 0 +#define F_SETFD 0 +#define MG_ENABLE_SSI 0 + +int rand(void); +int sscanf(const char*, const char*, ...); + +#endif + +#if defined(MG_ENABLE_FREERTOS_TCP) && MG_ENABLE_FREERTOS_TCP + +#include +#include + +#include +#include +#include // contents to be moved and file removed, some day + +#define MG_SOCKET_TYPE Socket_t +#define MG_INVALID_SOCKET FREERTOS_INVALID_SOCKET + +// Why FreeRTOS-TCP did not implement a clean BSD API, but its own thing +// with FreeRTOS_ prefix, is beyond me +#define IPPROTO_TCP FREERTOS_IPPROTO_TCP +#define IPPROTO_UDP FREERTOS_IPPROTO_UDP +#define AF_INET FREERTOS_AF_INET +#define SOCK_STREAM FREERTOS_SOCK_STREAM +#define SOCK_DGRAM FREERTOS_SOCK_DGRAM +#define SO_BROADCAST 0 +#define SO_ERROR 0 +#define SOL_SOCKET 0 +#define SO_REUSEADDR 0 + +#define MG_SOCK_ERR(errcode) ((errcode) < 0 ? (errcode) : 0) + +#define MG_SOCK_PENDING(errcode) \ + ((errcode) == -pdFREERTOS_ERRNO_EWOULDBLOCK || (errcode) == -pdFREERTOS_ERRNO_EISCONN || (errcode) == -pdFREERTOS_ERRNO_EINPROGRESS || (errcode) == -pdFREERTOS_ERRNO_EAGAIN) + +#define MG_SOCK_RESET(errcode) ((errcode) == -pdFREERTOS_ERRNO_ENOTCONN) + +// actually only if optional timeout is enabled +#define MG_SOCK_INTR(fd) (fd == NULL) + +#define sockaddr_in freertos_sockaddr +#define sockaddr freertos_sockaddr +#define accept(a, b, c) FreeRTOS_accept((a), (b), (c)) +#define connect(a, b, c) FreeRTOS_connect((a), (b), (c)) +#define bind(a, b, c) FreeRTOS_bind((a), (b), (c)) +#define listen(a, b) FreeRTOS_listen((a), (b)) +#define socket(a, b, c) FreeRTOS_socket((a), (b), (c)) +#define send(a, b, c, d) FreeRTOS_send((a), (b), (c), (d)) +#define recv(a, b, c, d) FreeRTOS_recv((a), (b), (c), (d)) +#define setsockopt(a, b, c, d, e) FreeRTOS_setsockopt((a), (b), (c), (d), (e)) +#define sendto(a, b, c, d, e, f) FreeRTOS_sendto((a), (b), (c), (d), (e), (f)) +#define recvfrom(a, b, c, d, e, f) \ + FreeRTOS_recvfrom((a), (b), (c), (d), (e), (f)) +#define closesocket(x) FreeRTOS_closesocket(x) +#define gethostbyname(x) FreeRTOS_gethostbyname(x) +#define getsockname(a, b, c) mg_getsockname((a), (b), (c)) +#define getpeername(a, b, c) mg_getpeername((a), (b), (c)) + +static inline int mg_getsockname(MG_SOCKET_TYPE fd, void* buf, socklen_t* len) +{ + (void)fd, (void)buf, (void)len; + return -1; +} + +static inline int mg_getpeername(MG_SOCKET_TYPE fd, void* buf, socklen_t* len) +{ + (void)fd, (void)buf, (void)len; + return 0; +} +#endif + +#if defined(MG_ENABLE_LWIP) && MG_ENABLE_LWIP + +#if defined(__GNUC__) && !defined(__ARMCC_VERSION) +#include +#endif + +struct timeval; + +#include + +#if !LWIP_TIMEVAL_PRIVATE +#if defined(__GNUC__) && !defined(__ARMCC_VERSION) // armclang sets both +#include +#else +struct timeval { + time_t tv_sec; + long tv_usec; +}; +#endif +#endif + +#if LWIP_SOCKET != 1 +// Sockets support disabled in LWIP by default +#error Set LWIP_SOCKET variable to 1 (in lwipopts.h) +#endif +#endif + +#if defined(MG_ENABLE_RL) && MG_ENABLE_RL +#include + +#define closesocket(x) closesocket(x) + +#define TCP_NODELAY SO_KEEPALIVE + +#define MG_SOCK_ERR(errcode) ((errcode) < 0 ? (errcode) : 0) + +#define MG_SOCK_PENDING(errcode) \ + ((errcode) == BSD_EWOULDBLOCK || (errcode) == BSD_EALREADY || (errcode) == BSD_EINPROGRESS) + +#define MG_SOCK_RESET(errcode) \ + ((errcode) == BSD_ECONNABORTED || (errcode) == BSD_ECONNRESET) + +// In blocking mode, which is enabled by default, accept() waits for a +// connection request. In non blocking mode, you must call accept() +// again if the error code BSD_EWOULDBLOCK is returned. +#define MG_SOCK_INTR(fd) (fd == BSD_EWOULDBLOCK) + +#define socklen_t int +#endif + +#ifndef MG_ENABLE_LOG +#define MG_ENABLE_LOG 1 +#endif + +#ifndef MG_ENABLE_TCPIP +#define MG_ENABLE_TCPIP 0 // Mongoose built-in network stack +#endif + +#ifndef MG_ENABLE_LWIP +#define MG_ENABLE_LWIP 0 // lWIP network stack +#endif + +#ifndef MG_ENABLE_FREERTOS_TCP +#define MG_ENABLE_FREERTOS_TCP 0 // Amazon FreeRTOS-TCP network stack +#endif + +#ifndef MG_ENABLE_RL +#define MG_ENABLE_RL 0 // ARM MDK network stack +#endif + +#ifndef MG_ENABLE_SOCKET +#define MG_ENABLE_SOCKET !MG_ENABLE_TCPIP +#endif + +#ifndef MG_ENABLE_POLL +#define MG_ENABLE_POLL 0 +#endif + +#ifndef MG_ENABLE_EPOLL +#define MG_ENABLE_EPOLL 0 +#endif + +#ifndef MG_ENABLE_FATFS +#define MG_ENABLE_FATFS 0 +#endif + +#ifndef MG_ENABLE_SSI +#define MG_ENABLE_SSI 0 +#endif + +#undef MG_ENABLE_IPV6 +#ifndef MG_ENABLE_IPV6 +#define MG_ENABLE_IPV6 0 +#endif + +#ifndef MG_IPV6_V6ONLY +#define MG_IPV6_V6ONLY 0 // IPv6 socket binds only to V6, not V4 address +#endif + +#ifndef MG_ENABLE_MD5 +#define MG_ENABLE_MD5 1 +#endif + +// Set MG_ENABLE_WINSOCK=0 for Win32 builds with external IP stack (like LWIP) +#ifndef MG_ENABLE_WINSOCK +#define MG_ENABLE_WINSOCK 1 +#endif + +#ifndef MG_ENABLE_DIRLIST +#define MG_ENABLE_DIRLIST 0 +#endif + +#ifndef MG_ENABLE_CUSTOM_RANDOM +#define MG_ENABLE_CUSTOM_RANDOM 0 +#endif + +#ifndef MG_ENABLE_CUSTOM_MILLIS +#define MG_ENABLE_CUSTOM_MILLIS 0 +#endif + +#ifndef MG_ENABLE_PACKED_FS +#define MG_ENABLE_PACKED_FS 0 +#endif + +#ifndef MG_ENABLE_ASSERT +#define MG_ENABLE_ASSERT 0 +#endif + +#ifndef MG_IO_SIZE +#define MG_IO_SIZE 2048 // Granularity of the send/recv IO buffer growth +#endif + +#ifndef MG_MAX_RECV_SIZE +#define MG_MAX_RECV_SIZE (8UL * 1024UL * 1024UL) // Maximum recv IO buffer size +#endif + +#ifndef MG_DATA_SIZE +#define MG_DATA_SIZE 32 // struct mg_connection :: data size +#endif + +#ifndef MG_MAX_HTTP_HEADERS +#define MG_MAX_HTTP_HEADERS 30 +#endif + +#ifndef MG_HTTP_INDEX +#define MG_HTTP_INDEX "index.html" +#endif + +#ifndef MG_PATH_MAX +#ifdef PATH_MAX +#define MG_PATH_MAX PATH_MAX +#else +#define MG_PATH_MAX 128 +#endif +#endif + +#ifndef MG_SOCK_LISTEN_BACKLOG_SIZE +#define MG_SOCK_LISTEN_BACKLOG_SIZE 5 +#endif + +#ifndef MG_DIRSEP +#define MG_DIRSEP '/' +#endif + +#ifndef MG_ENABLE_FILE +#if defined(FOPEN_MAX) +#define MG_ENABLE_FILE 1 +#else +#define MG_ENABLE_FILE 0 +#endif +#endif + +#ifndef MG_INVALID_SOCKET +#define MG_INVALID_SOCKET (-1) +#endif + +#ifndef MG_SOCKET_TYPE +#define MG_SOCKET_TYPE int +#endif + +#ifndef MG_SOCKET_ERRNO +#define MG_SOCKET_ERRNO errno +#endif + +#if MG_ENABLE_EPOLL +#define MG_EPOLL_ADD(c) \ + do { \ + struct epoll_event ev = { EPOLLIN | EPOLLERR | EPOLLHUP, { c } }; \ + epoll_ctl(c->mgr->epoll_fd, EPOLL_CTL_ADD, (int)(size_t)c->fd, &ev); \ + } while (0) +#define MG_EPOLL_MOD(c, wr) \ + do { \ + struct epoll_event ev = { EPOLLIN | EPOLLERR | EPOLLHUP, { c } }; \ + if (wr) \ + ev.events |= EPOLLOUT; \ + epoll_ctl(c->mgr->epoll_fd, EPOLL_CTL_MOD, (int)(size_t)c->fd, &ev); \ + } while (0) +#else +#define MG_EPOLL_ADD(c) +#define MG_EPOLL_MOD(c, wr) +#endif + +struct mg_str { + const char* ptr; // Pointer to string data + size_t len; // String len +}; + +#define MG_NULL_STR \ + { \ + NULL, 0 \ + } + +#define MG_C_STR(a) \ + { \ + (a), sizeof(a) - 1 \ + } + +// Using macro to avoid shadowing C++ struct constructor, see #1298 +#define mg_str(s) mg_str_s(s) + +struct mg_str mg_str(const char* s); +struct mg_str mg_str_n(const char* s, size_t n); +int mg_lower(const char* s); +int mg_ncasecmp(const char* s1, const char* s2, size_t len); +int mg_casecmp(const char* s1, const char* s2); +int mg_vcmp(const struct mg_str* s1, const char* s2); +int mg_vcasecmp(const struct mg_str* str1, const char* str2); +int mg_strcmp(const struct mg_str str1, const struct mg_str str2); +struct mg_str mg_strstrip(struct mg_str s); +struct mg_str mg_strdup(const struct mg_str s); +const char* mg_strstr(const struct mg_str haystack, const struct mg_str needle); +bool mg_match(struct mg_str str, struct mg_str pattern, struct mg_str* caps); +bool mg_globmatch(const char* pattern, size_t plen, const char* s, size_t n); +bool mg_commalist(struct mg_str* s, struct mg_str* k, struct mg_str* v); +bool mg_split(struct mg_str* s, struct mg_str* k, struct mg_str* v, char delim); +char* mg_hex(const void* buf, size_t len, char* dst); +void mg_unhex(const char* buf, size_t len, unsigned char* to); +unsigned long mg_unhexn(const char* s, size_t len); +bool mg_path_is_sane(const char* path); + +// Single producer, single consumer non-blocking queue + +struct mg_queue { + char* buf; + size_t size; + volatile size_t tail; + volatile size_t head; +}; + +void mg_queue_init(struct mg_queue*, char*, size_t); // Init queue +size_t mg_queue_book(struct mg_queue*, char** buf, size_t); // Reserve space +void mg_queue_add(struct mg_queue*, size_t); // Add new message +size_t mg_queue_next(struct mg_queue*, char**); // Get oldest message +void mg_queue_del(struct mg_queue*, size_t); // Delete oldest message + +typedef void (*mg_pfn_t)(char, void*); // Output function +typedef size_t (*mg_pm_t)(mg_pfn_t, void*, va_list*); // %M printer + +size_t mg_vxprintf(void (*)(char, void*), void*, const char* fmt, va_list*); +size_t mg_xprintf(void (*fn)(char, void*), void*, const char* fmt, ...); + +// Convenience wrappers around mg_xprintf +size_t mg_vsnprintf(char* buf, size_t len, const char* fmt, va_list* ap); +size_t mg_snprintf(char*, size_t, const char* fmt, ...); +char* mg_vmprintf(const char* fmt, va_list* ap); +char* mg_mprintf(const char* fmt, ...); +size_t mg_queue_vprintf(struct mg_queue*, const char* fmt, va_list*); +size_t mg_queue_printf(struct mg_queue*, const char* fmt, ...); + +// %M print helper functions +size_t mg_print_base64(void (*out)(char, void*), void* arg, va_list* ap); +size_t mg_print_esc(void (*out)(char, void*), void* arg, va_list* ap); +size_t mg_print_hex(void (*out)(char, void*), void* arg, va_list* ap); +size_t mg_print_ip(void (*out)(char, void*), void* arg, va_list* ap); +size_t mg_print_ip_port(void (*out)(char, void*), void* arg, va_list* ap); +size_t mg_print_ip4(void (*out)(char, void*), void* arg, va_list* ap); +size_t mg_print_ip6(void (*out)(char, void*), void* arg, va_list* ap); +size_t mg_print_mac(void (*out)(char, void*), void* arg, va_list* ap); + +// Various output functions +void mg_pfn_iobuf(char ch, void* param); // param: struct mg_iobuf * +void mg_pfn_stdout(char c, void* param); // param: ignored + +// A helper macro for printing JSON: mg_snprintf(buf, len, "%m", MG_ESC("hi")) +#define MG_ESC(str) mg_print_esc, 0, (str) + +enum { MG_LL_NONE, + MG_LL_ERROR, + MG_LL_INFO, + MG_LL_DEBUG, + MG_LL_VERBOSE }; +void mg_log(const char* fmt, ...); +bool mg_log_prefix(int ll, const char* file, int line, const char* fname); +void mg_log_set(int log_level); +void mg_hexdump(const void* buf, size_t len); +void mg_log_set_fn(mg_pfn_t fn, void* param); + +#if MG_ENABLE_LOG +#define MG_LOG(level, args) \ + do { \ + if (mg_log_prefix((level), __FILE__, __LINE__, __func__)) \ + mg_log args; \ + } while (0) +#else +#define MG_LOG(level, args) \ + do { \ + if (0) \ + mg_log args; \ + } while (0) +#endif + +#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args) +#define MG_INFO(args) MG_LOG(MG_LL_INFO, args) +#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args) +#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args) + +struct mg_timer { + unsigned long id; // Timer ID + uint64_t period_ms; // Timer period in milliseconds + uint64_t expire; // Expiration timestamp in milliseconds + unsigned flags; // Possible flags values below +#define MG_TIMER_ONCE 0 // Call function once +#define MG_TIMER_REPEAT 1 // Call function periodically +#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set + void (*fn)(void*); // Function to call + void* arg; // Function argument + struct mg_timer* next; // Linkage +}; + +void mg_timer_init(struct mg_timer** head, struct mg_timer* timer, + uint64_t milliseconds, unsigned flags, void (*fn)(void*), + void* arg); +void mg_timer_free(struct mg_timer** head, struct mg_timer*); +void mg_timer_poll(struct mg_timer** head, uint64_t new_ms); +bool mg_timer_expired(uint64_t* expiration, uint64_t period, uint64_t now); + +enum { MG_FS_READ = 1, + MG_FS_WRITE = 2, + MG_FS_DIR = 4 }; + +// Filesystem API functions +// st() returns MG_FS_* flags and populates file size and modification time +// ls() calls fn() for every directory entry, allowing to list a directory +// +// NOTE: UNIX-style shorthand names for the API functions are deliberately +// chosen to avoid conflicts with some libraries that make macros for e.g. +// stat(), write(), read() calls. +struct mg_fs { + int (*st)(const char* path, size_t* size, time_t* mtime); // stat file + void (*ls)(const char* path, void (*fn)(const char*, void*), void*); + void* (*op)(const char* path, int flags); // Open file + void (*cl)(void* fd); // Close file + size_t (*rd)(void* fd, void* buf, size_t len); // Read file + size_t (*wr)(void* fd, const void* buf, size_t len); // Write file + size_t (*sk)(void* fd, size_t offset); // Set file position + bool (*mv)(const char* from, const char* to); // Rename file + bool (*rm)(const char* path); // Delete file + bool (*mkd)(const char* path); // Create directory +}; + +extern struct mg_fs mg_fs_posix; // POSIX open/close/read/write/seek +extern struct mg_fs mg_fs_packed; // Packed FS, see examples/device-dashboard +extern struct mg_fs mg_fs_fat; // FAT FS + +// File descriptor +struct mg_fd { + void* fd; + struct mg_fs* fs; +}; + +struct mg_fd* mg_fs_open(struct mg_fs* fs, const char* path, int flags); +void mg_fs_close(struct mg_fd* fd); +char* mg_file_read(struct mg_fs* fs, const char* path, size_t* size); +bool mg_file_write(struct mg_fs* fs, const char* path, const void*, size_t); +bool mg_file_printf(struct mg_fs* fs, const char* path, const char* fmt, ...); + +// Packed API +const char* mg_unpack(const char* path, size_t* size, time_t* mtime); +const char* mg_unlist(size_t no); // Get no'th packed filename +struct mg_str mg_unpacked(const char* path); // Packed file as mg_str + +#if MG_ENABLE_ASSERT +#include +#elif !defined(assert) +#define assert(x) +#endif + +void mg_bzero(volatile unsigned char* buf, size_t len); +void mg_random(void* buf, size_t len); +char* mg_random_str(char* buf, size_t len); +uint16_t mg_ntohs(uint16_t net); +uint32_t mg_ntohl(uint32_t net); +uint32_t mg_crc32(uint32_t crc, const char* buf, size_t len); +uint64_t mg_millis(void); // Return milliseconds since boot +uint64_t mg_now(void); // Return milliseconds since Epoch + +#define mg_htons(x) mg_ntohs(x) +#define mg_htonl(x) mg_ntohl(x) + +#define MG_U32(a, b, c, d) \ + (((uint32_t)((a) & 255) << 24) | ((uint32_t)((b) & 255) << 16) | ((uint32_t)((c) & 255) << 8) | (uint32_t)((d) & 255)) + +// For printing IPv4 addresses: printf("%d.%d.%d.%d\n", MG_IPADDR_PARTS(&ip)) +#define MG_U8P(ADDR) ((uint8_t*)(ADDR)) +#define MG_IPADDR_PARTS(ADDR) \ + MG_U8P(ADDR) \ + [0], MG_U8P(ADDR)[1], MG_U8P(ADDR)[2], MG_U8P(ADDR)[3] + +#define MG_REG(x) ((volatile uint32_t*)(x))[0] +#define MG_BIT(x) (((uint32_t)1U) << (x)) +#define MG_SET_BITS(R, CLRMASK, SETMASK) (R) = ((R) & ~(CLRMASK)) | (SETMASK) + +#define MG_ROUND_UP(x, a) ((a) == 0 ? (x) : ((((x) + (a)-1) / (a)) * (a))) +#define MG_ROUND_DOWN(x, a) ((a) == 0 ? (x) : (((x) / (a)) * (a))) + +#ifdef __GNUC__ +#define MG_ARM_DISABLE_IRQ() asm volatile("cpsid i" : : : "memory") +#define MG_ARM_ENABLE_IRQ() asm volatile("cpsie i" : : : "memory") +#else +#define MG_ARM_DISABLE_IRQ() +#define MG_ARM_ENABLE_IRQ() +#endif + +struct mg_addr; +int mg_check_ip_acl(struct mg_str acl, struct mg_addr* remote_ip); + +// Linked list management macros +#define LIST_ADD_HEAD(type_, head_, elem_) \ + do { \ + (elem_)->next = (*head_); \ + *(head_) = (elem_); \ + } while (0) + +#define LIST_ADD_TAIL(type_, head_, elem_) \ + do { \ + type_** h = head_; \ + while (*h != NULL) \ + h = &(*h)->next; \ + *h = (elem_); \ + } while (0) + +#define LIST_DELETE(type_, head_, elem_) \ + do { \ + type_** h = head_; \ + while (*h != (elem_)) \ + h = &(*h)->next; \ + *h = (elem_)->next; \ + } while (0) + +unsigned short mg_url_port(const char* url); +int mg_url_is_ssl(const char* url); +struct mg_str mg_url_host(const char* url); +struct mg_str mg_url_user(const char* url); +struct mg_str mg_url_pass(const char* url); +const char* mg_url_uri(const char* url); + +struct mg_iobuf { + unsigned char* buf; // Pointer to stored data + size_t size; // Total size available + size_t len; // Current number of bytes + size_t align; // Alignment during allocation +}; + +int mg_iobuf_init(struct mg_iobuf*, size_t, size_t); +int mg_iobuf_resize(struct mg_iobuf*, size_t); +void mg_iobuf_free(struct mg_iobuf*); +size_t mg_iobuf_add(struct mg_iobuf*, size_t, const void*, size_t); +size_t mg_iobuf_del(struct mg_iobuf*, size_t ofs, size_t len); + +size_t mg_base64_update(unsigned char input_byte, char* buf, size_t len); +size_t mg_base64_final(char* buf, size_t len); +size_t mg_base64_encode(const unsigned char* p, size_t n, char* buf, size_t); +size_t mg_base64_decode(const char* src, size_t n, char* dst, size_t); + +typedef struct { + uint32_t buf[4]; + uint32_t bits[2]; + unsigned char in[64]; +} mg_md5_ctx; + +void mg_md5_init(mg_md5_ctx* c); +void mg_md5_update(mg_md5_ctx* c, const unsigned char* data, size_t len); +void mg_md5_final(mg_md5_ctx* c, unsigned char[16]); + +typedef struct { + uint32_t state[5]; + uint32_t count[2]; + unsigned char buffer[64]; +} mg_sha1_ctx; + +void mg_sha1_init(mg_sha1_ctx*); +void mg_sha1_update(mg_sha1_ctx*, const unsigned char* data, size_t len); +void mg_sha1_final(unsigned char digest[20], mg_sha1_ctx*); + +struct mg_connection; +typedef void (*mg_event_handler_t)(struct mg_connection*, int ev, + void* ev_data, void* fn_data); +void mg_call(struct mg_connection* c, int ev, void* ev_data); +void mg_error(struct mg_connection* c, const char* fmt, ...); + +enum { + MG_EV_ERROR, // Error char *error_message + MG_EV_OPEN, // Connection created NULL + MG_EV_POLL, // mg_mgr_poll iteration uint64_t *uptime_millis + MG_EV_RESOLVE, // Host name is resolved NULL + MG_EV_CONNECT, // Connection established NULL + MG_EV_ACCEPT, // Connection accepted NULL + MG_EV_TLS_HS, // TLS handshake succeeded NULL + MG_EV_READ, // Data received from socket long *bytes_read + MG_EV_WRITE, // Data written to socket long *bytes_written + MG_EV_CLOSE, // Connection closed NULL + MG_EV_HTTP_MSG, // HTTP request/response struct mg_http_message * + MG_EV_HTTP_CHUNK, // HTTP chunk (partial msg) struct mg_http_message * + MG_EV_WS_OPEN, // Websocket handshake done struct mg_http_message * + MG_EV_WS_MSG, // Websocket msg, text or bin struct mg_ws_message * + MG_EV_WS_CTL, // Websocket control msg struct mg_ws_message * + MG_EV_MQTT_CMD, // MQTT low-level command struct mg_mqtt_message * + MG_EV_MQTT_MSG, // MQTT PUBLISH received struct mg_mqtt_message * + MG_EV_MQTT_OPEN, // MQTT CONNACK received int *connack_status_code + MG_EV_SNTP_TIME, // SNTP time received uint64_t *epoch_millis + MG_EV_USER // Starting ID for user events +}; + +struct mg_dns { + const char* url; // DNS server URL + struct mg_connection* c; // DNS server connection +}; + +struct mg_addr { + uint8_t ip[16]; // Holds IPv4 or IPv6 address, in network byte order + uint16_t port; // TCP or UDP port in network byte order + bool is_ip6; // True when address is IPv6 address +}; + +struct mg_mgr { + struct mg_connection* conns; // List of active connections + struct mg_dns dns4; // DNS for IPv4 + struct mg_dns dns6; // DNS for IPv6 + int dnstimeout; // DNS resolve timeout in milliseconds + bool use_dns6; // Use DNS6 server by default, see #1532 + unsigned long nextid; // Next connection ID + unsigned long timerid; // Next timer ID + void* userdata; // Arbitrary user data pointer + void* tls_ctx; // TLS context shared by all TLS sessions + uint16_t mqtt_id; // MQTT IDs for pub/sub + void* active_dns_requests; // DNS requests in progress + struct mg_timer* timers; // Active timers + int epoll_fd; // Used when MG_EPOLL_ENABLE=1 + void* priv; // Used by the MIP stack + size_t extraconnsize; // Used by the MIP stack +#if MG_ENABLE_FREERTOS_TCP + SocketSet_t ss; // NOTE(lsm): referenced from socket struct +#endif +}; + +struct mg_connection { + struct mg_connection* next; // Linkage in struct mg_mgr :: connections + struct mg_mgr* mgr; // Our container + struct mg_addr loc; // Local address + struct mg_addr rem; // Remote address + void* fd; // Connected socket, or LWIP data + unsigned long id; // Auto-incrementing unique connection ID + struct mg_iobuf recv; // Incoming data + struct mg_iobuf send; // Outgoing data + mg_event_handler_t fn; // User-specified event handler function + void* fn_data; // User-specified function parameter + mg_event_handler_t pfn; // Protocol-specific handler function + void* pfn_data; // Protocol-specific function parameter + char data[MG_DATA_SIZE]; // Arbitrary connection data + void* tls; // TLS specific data + unsigned is_listening : 1; // Listening connection + unsigned is_client : 1; // Outbound (client) connection + unsigned is_accepted : 1; // Accepted (server) connection + unsigned is_resolving : 1; // Non-blocking DNS resolution is in progress + unsigned is_arplooking : 1; // Non-blocking ARP resolution is in progress + unsigned is_connecting : 1; // Non-blocking connect is in progress + unsigned is_tls : 1; // TLS-enabled connection + unsigned is_tls_hs : 1; // TLS handshake is in progress + unsigned is_udp : 1; // UDP connection + unsigned is_websocket : 1; // WebSocket connection + unsigned is_mqtt5 : 1; // For MQTT connection, v5 indicator + unsigned is_hexdumping : 1; // Hexdump in/out traffic + unsigned is_draining : 1; // Send remaining data, then close and free + unsigned is_closing : 1; // Close and free the connection immediately + unsigned is_full : 1; // Stop reads, until cleared + unsigned is_resp : 1; // Response is still being generated + unsigned is_readable : 1; // Connection is ready to read + unsigned is_writable : 1; // Connection is ready to write +}; + +void mg_mgr_poll(struct mg_mgr*, int ms); +void mg_mgr_init(struct mg_mgr*); +void mg_mgr_free(struct mg_mgr*); + +struct mg_connection* mg_listen(struct mg_mgr*, const char* url, + mg_event_handler_t fn, void* fn_data); +struct mg_connection* mg_connect(struct mg_mgr*, const char* url, + mg_event_handler_t fn, void* fn_data); +struct mg_connection* mg_wrapfd(struct mg_mgr* mgr, int fd, + mg_event_handler_t fn, void* fn_data); +void mg_connect_resolved(struct mg_connection*); +bool mg_send(struct mg_connection*, const void*, size_t); +size_t mg_printf(struct mg_connection*, const char* fmt, ...); +size_t mg_vprintf(struct mg_connection*, const char* fmt, va_list* ap); +bool mg_aton(struct mg_str str, struct mg_addr* addr); +int mg_mkpipe(struct mg_mgr*, mg_event_handler_t, void*, bool udp); + +// These functions are used to integrate with custom network stacks +struct mg_connection* mg_alloc_conn(struct mg_mgr*); +void mg_close_conn(struct mg_connection* c); +bool mg_open_listener(struct mg_connection* c, const char* url); + +// Utility functions +struct mg_timer* mg_timer_add(struct mg_mgr* mgr, uint64_t milliseconds, + unsigned flags, void (*fn)(void*), void* arg); + +// Low-level IO primives used by TLS layer +enum { MG_IO_ERR = -1, + MG_IO_WAIT = -2, + MG_IO_RESET = -3 }; +long mg_io_send(struct mg_connection* c, const void* buf, size_t len); +long mg_io_recv(struct mg_connection* c, void* buf, size_t len); + +struct mg_http_header { + struct mg_str name; // Header name + struct mg_str value; // Header value +}; + +struct mg_http_message { + struct mg_str method, uri, query, proto; // Request/response line + struct mg_http_header headers[MG_MAX_HTTP_HEADERS]; // Headers + struct mg_str body; // Body + struct mg_str head; // Request + headers + struct mg_str chunk; // Chunk for chunked encoding, or partial body + struct mg_str message; // Request + headers + body +}; + +// Parameter for mg_http_serve_dir() +struct mg_http_serve_opts { + const char* root_dir; // Web root directory, must be non-NULL + const char* ssi_pattern; // SSI file name pattern, e.g. #.shtml + const char* extra_headers; // Extra HTTP headers to add in responses + const char* mime_types; // Extra mime types, ext1=type1,ext2=type2,.. + const char* page404; // Path to the 404 page, or NULL by default + struct mg_fs* fs; // Filesystem implementation. Use NULL for POSIX +}; + +// Parameter for mg_http_next_multipart +struct mg_http_part { + struct mg_str name; // Form field name + struct mg_str filename; // Filename for file uploads + struct mg_str body; // Part contents +}; + +int mg_http_parse(const char* s, size_t len, struct mg_http_message*); +int mg_http_get_request_len(const unsigned char* buf, size_t buf_len); +void mg_http_printf_chunk(struct mg_connection* cnn, const char* fmt, ...); +void mg_http_write_chunk(struct mg_connection* c, const char* buf, size_t len); +void mg_http_delete_chunk(struct mg_connection* c, struct mg_http_message* hm); +struct mg_connection* mg_http_listen(struct mg_mgr*, const char* url, + mg_event_handler_t fn, void* fn_data); +struct mg_connection* mg_http_connect(struct mg_mgr*, const char* url, + mg_event_handler_t fn, void* fn_data); +void mg_http_serve_dir(struct mg_connection*, struct mg_http_message* hm, + const struct mg_http_serve_opts*); +void mg_http_serve_file(struct mg_connection*, struct mg_http_message* hm, + const char* path, const struct mg_http_serve_opts*); +void mg_http_reply(struct mg_connection*, int status_code, const char* headers, + const char* body_fmt, ...); +struct mg_str* mg_http_get_header(struct mg_http_message*, const char* name); +struct mg_str mg_http_var(struct mg_str buf, struct mg_str name); +int mg_http_get_var(const struct mg_str*, const char* name, char*, size_t); +int mg_url_decode(const char* s, size_t n, char* to, size_t to_len, int form); +size_t mg_url_encode(const char* s, size_t n, char* buf, size_t len); +void mg_http_creds(struct mg_http_message*, char*, size_t, char*, size_t); +bool mg_http_match_uri(const struct mg_http_message*, const char* glob); +long mg_http_upload(struct mg_connection* c, struct mg_http_message* hm, + struct mg_fs* fs, const char* path, size_t max_size); +void mg_http_bauth(struct mg_connection*, const char* user, const char* pass); +struct mg_str mg_http_get_header_var(struct mg_str s, struct mg_str v); +size_t mg_http_next_multipart(struct mg_str, size_t, struct mg_http_part*); +int mg_http_status(const struct mg_http_message* hm); +void mg_hello(const char* url); + +void mg_http_serve_ssi(struct mg_connection* c, const char* root, + const char* fullpath); + +#define MG_TLS_NONE 0 // No TLS support +#define MG_TLS_MBED 1 // mbedTLS +#define MG_TLS_OPENSSL 2 // OpenSSL +#define MG_TLS_BUILTIN 3 // Built-in +#define MG_TLS_CUSTOM 4 // Custom implementation + +#ifndef MG_TLS +#define MG_TLS MG_TLS_NONE +#endif + +struct mg_tls_opts { + struct mg_str ca; // PEM or DER + struct mg_str cert; // PEM or DER + struct mg_str key; // PEM or DER + struct mg_str name; // If not empty, enable host name verification +}; + +void mg_tls_init(struct mg_connection*, const struct mg_tls_opts* opts); +void mg_tls_free(struct mg_connection*); +long mg_tls_send(struct mg_connection*, const void* buf, size_t len); +long mg_tls_recv(struct mg_connection*, void* buf, size_t len); +size_t mg_tls_pending(struct mg_connection*); +void mg_tls_handshake(struct mg_connection*); + +// Private +void mg_tls_ctx_init(struct mg_mgr*); +void mg_tls_ctx_free(struct mg_mgr*); + +#if MG_TLS == MG_TLS_MBED +#include +#include +#include +#include + +struct mg_tls_ctx { + int dummy; +#ifdef MBEDTLS_SSL_SESSION_TICKETS + mbedtls_ssl_ticket_context tickets; +#endif +}; + +struct mg_tls { + mbedtls_x509_crt ca; // Parsed CA certificate + mbedtls_x509_crt cert; // Parsed certificate + mbedtls_pk_context pk; // Private key context + mbedtls_ssl_context ssl; // SSL/TLS context + mbedtls_ssl_config conf; // SSL-TLS config +#ifdef MBEDTLS_SSL_SESSION_TICKETS + mbedtls_ssl_ticket_context ticket; // Session tickets context +#endif +}; +#endif + +#if MG_TLS == MG_TLS_OPENSSL + +#include +#include + +struct mg_tls { + SSL_CTX* ctx; + SSL* ssl; +}; +#endif + +#define WEBSOCKET_OP_CONTINUE 0 +#define WEBSOCKET_OP_TEXT 1 +#define WEBSOCKET_OP_BINARY 2 +#define WEBSOCKET_OP_CLOSE 8 +#define WEBSOCKET_OP_PING 9 +#define WEBSOCKET_OP_PONG 10 + +struct mg_ws_message { + struct mg_str data; // Websocket message data + uint8_t flags; // Websocket message flags +}; + +struct mg_connection* mg_ws_connect(struct mg_mgr*, const char* url, + mg_event_handler_t fn, void* fn_data, + const char* fmt, ...); +void mg_ws_upgrade(struct mg_connection*, struct mg_http_message*, + const char* fmt, ...); +size_t mg_ws_send(struct mg_connection*, const void* buf, size_t len, int op); +size_t mg_ws_wrap(struct mg_connection*, size_t len, int op); +size_t mg_ws_printf(struct mg_connection* c, int op, const char* fmt, ...); +size_t mg_ws_vprintf(struct mg_connection* c, int op, const char* fmt, + va_list*); + +struct mg_connection* mg_sntp_connect(struct mg_mgr* mgr, const char* url, + mg_event_handler_t fn, void* fn_data); +void mg_sntp_request(struct mg_connection* c); +int64_t mg_sntp_parse(const unsigned char* buf, size_t len); + +#define MQTT_CMD_CONNECT 1 +#define MQTT_CMD_CONNACK 2 +#define MQTT_CMD_PUBLISH 3 +#define MQTT_CMD_PUBACK 4 +#define MQTT_CMD_PUBREC 5 +#define MQTT_CMD_PUBREL 6 +#define MQTT_CMD_PUBCOMP 7 +#define MQTT_CMD_SUBSCRIBE 8 +#define MQTT_CMD_SUBACK 9 +#define MQTT_CMD_UNSUBSCRIBE 10 +#define MQTT_CMD_UNSUBACK 11 +#define MQTT_CMD_PINGREQ 12 +#define MQTT_CMD_PINGRESP 13 +#define MQTT_CMD_DISCONNECT 14 +#define MQTT_CMD_AUTH 15 + +#define MQTT_PROP_PAYLOAD_FORMAT_INDICATOR 0x01 +#define MQTT_PROP_MESSAGE_EXPIRY_INTERVAL 0x02 +#define MQTT_PROP_CONTENT_TYPE 0x03 +#define MQTT_PROP_RESPONSE_TOPIC 0x08 +#define MQTT_PROP_CORRELATION_DATA 0x09 +#define MQTT_PROP_SUBSCRIPTION_IDENTIFIER 0x0B +#define MQTT_PROP_SESSION_EXPIRY_INTERVAL 0x11 +#define MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER 0x12 +#define MQTT_PROP_SERVER_KEEP_ALIVE 0x13 +#define MQTT_PROP_AUTHENTICATION_METHOD 0x15 +#define MQTT_PROP_AUTHENTICATION_DATA 0x16 +#define MQTT_PROP_REQUEST_PROBLEM_INFORMATION 0x17 +#define MQTT_PROP_WILL_DELAY_INTERVAL 0x18 +#define MQTT_PROP_REQUEST_RESPONSE_INFORMATION 0x19 +#define MQTT_PROP_RESPONSE_INFORMATION 0x1A +#define MQTT_PROP_SERVER_REFERENCE 0x1C +#define MQTT_PROP_REASON_STRING 0x1F +#define MQTT_PROP_RECEIVE_MAXIMUM 0x21 +#define MQTT_PROP_TOPIC_ALIAS_MAXIMUM 0x22 +#define MQTT_PROP_TOPIC_ALIAS 0x23 +#define MQTT_PROP_MAXIMUM_QOS 0x24 +#define MQTT_PROP_RETAIN_AVAILABLE 0x25 +#define MQTT_PROP_USER_PROPERTY 0x26 +#define MQTT_PROP_MAXIMUM_PACKET_SIZE 0x27 +#define MQTT_PROP_WILDCARD_SUBSCRIPTION_AVAILABLE 0x28 +#define MQTT_PROP_SUBSCRIPTION_IDENTIFIER_AVAILABLE 0x29 +#define MQTT_PROP_SHARED_SUBSCRIPTION_AVAILABLE 0x2A + +enum { + MQTT_PROP_TYPE_BYTE, + MQTT_PROP_TYPE_STRING, + MQTT_PROP_TYPE_STRING_PAIR, + MQTT_PROP_TYPE_BINARY_DATA, + MQTT_PROP_TYPE_VARIABLE_INT, + MQTT_PROP_TYPE_INT, + MQTT_PROP_TYPE_SHORT +}; + +enum { MQTT_OK, + MQTT_INCOMPLETE, + MQTT_MALFORMED }; + +struct mg_mqtt_prop { + uint8_t id; // Enumerated at MQTT5 Reference + uint32_t iv; // Integer value for 8-, 16-, 32-bit integers types + struct mg_str key; // Non-NULL only for user property type + struct mg_str val; // Non-NULL only for UTF-8 types and user properties +}; + +struct mg_mqtt_opts { + struct mg_str user; // Username, can be empty + struct mg_str pass; // Password, can be empty + struct mg_str client_id; // Client ID + struct mg_str topic; // message/subscription topic + struct mg_str message; // message content + uint8_t qos; // message quality of service + uint8_t version; // Can be 4 (3.1.1), or 5. If 0, assume 4 + uint16_t keepalive; // Keep-alive timer in seconds + bool retain; // Retain flag + bool clean; // Clean session flag + struct mg_mqtt_prop* props; // MQTT5 props array + size_t num_props; // number of props + struct mg_mqtt_prop* will_props; // Valid only for CONNECT packet (MQTT5) + size_t num_will_props; // Number of will props +}; + +struct mg_mqtt_message { + struct mg_str topic; // Parsed topic for PUBLISH + struct mg_str data; // Parsed message for PUBLISH + struct mg_str dgram; // Whole MQTT packet, including headers + uint16_t id; // For PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, PUBLISH + uint8_t cmd; // MQTT command, one of MQTT_CMD_* + uint8_t qos; // Quality of service + uint8_t ack; // CONNACK return code, 0 = success + size_t props_start; // Offset to the start of the properties (MQTT5) + size_t props_size; // Length of the properties +}; + +struct mg_connection* mg_mqtt_connect(struct mg_mgr*, const char* url, + const struct mg_mqtt_opts* opts, + mg_event_handler_t fn, void* fn_data); +struct mg_connection* mg_mqtt_listen(struct mg_mgr* mgr, const char* url, + mg_event_handler_t fn, void* fn_data); +void mg_mqtt_login(struct mg_connection* c, const struct mg_mqtt_opts* opts); +void mg_mqtt_pub(struct mg_connection* c, const struct mg_mqtt_opts* opts); +void mg_mqtt_sub(struct mg_connection*, const struct mg_mqtt_opts* opts); +int mg_mqtt_parse(const uint8_t*, size_t, uint8_t, struct mg_mqtt_message*); +void mg_mqtt_send_header(struct mg_connection*, uint8_t cmd, uint8_t flags, + uint32_t len); +void mg_mqtt_ping(struct mg_connection*); +void mg_mqtt_pong(struct mg_connection*); +void mg_mqtt_disconnect(struct mg_connection*, const struct mg_mqtt_opts*); +size_t mg_mqtt_next_prop(struct mg_mqtt_message*, struct mg_mqtt_prop*, + size_t ofs); + +// Mongoose sends DNS queries that contain only one question: +// either A (IPv4) or AAAA (IPv6) address lookup. +// Therefore, we expect zero or one answer. +// If `resolved` is true, then `addr` contains resolved IPv4 or IPV6 address. +struct mg_dns_message { + uint16_t txnid; // Transaction ID + bool resolved; // Resolve successful, addr is set + struct mg_addr addr; // Resolved address + char name[256]; // Host name +}; + +struct mg_dns_header { + uint16_t txnid; // Transaction ID + uint16_t flags; + uint16_t num_questions; + uint16_t num_answers; + uint16_t num_authority_prs; + uint16_t num_other_prs; +}; + +// DNS resource record +struct mg_dns_rr { + uint16_t nlen; // Name or pointer length + uint16_t atype; // Address type + uint16_t aclass; // Address class + uint16_t alen; // Address length +}; + +void mg_resolve(struct mg_connection*, const char* url); +void mg_resolve_cancel(struct mg_connection*); +bool mg_dns_parse(const uint8_t* buf, size_t len, struct mg_dns_message*); +size_t mg_dns_parse_rr(const uint8_t* buf, size_t len, size_t ofs, + bool is_question, struct mg_dns_rr*); + +#ifndef MG_JSON_MAX_DEPTH +#define MG_JSON_MAX_DEPTH 30 +#endif + +// Error return values - negative. Successful returns are >= 0 +enum { MG_JSON_TOO_DEEP = -1, + MG_JSON_INVALID = -2, + MG_JSON_NOT_FOUND = -3 }; +int mg_json_get(struct mg_str json, const char* path, int* toklen); + +bool mg_json_get_num(struct mg_str json, const char* path, double* v); +bool mg_json_get_bool(struct mg_str json, const char* path, bool* v); +long mg_json_get_long(struct mg_str json, const char* path, long dflt); +char* mg_json_get_str(struct mg_str json, const char* path); +char* mg_json_get_hex(struct mg_str json, const char* path, int* len); +char* mg_json_get_b64(struct mg_str json, const char* path, int* len); + +bool mg_json_unescape(struct mg_str str, char* buf, size_t len); + +// JSON-RPC request descriptor +struct mg_rpc_req { + struct mg_rpc** head; // RPC handlers list head + struct mg_rpc* rpc; // RPC handler being called + mg_pfn_t pfn; // Response printing function + void* pfn_data; // Response printing function data + void* req_data; // Arbitrary request data + struct mg_str frame; // Request, e.g. {"id":1,"method":"add","params":[1,2]} +}; + +// JSON-RPC method handler +struct mg_rpc { + struct mg_rpc* next; // Next in list + struct mg_str method; // Method pattern + void (*fn)(struct mg_rpc_req*); // Handler function + void* fn_data; // Handler function argument +}; + +void mg_rpc_add(struct mg_rpc** head, struct mg_str method_pattern, + void (*handler)(struct mg_rpc_req*), void* handler_data); +void mg_rpc_del(struct mg_rpc** head, void (*handler)(struct mg_rpc_req*)); +void mg_rpc_process(struct mg_rpc_req*); + +// Helper functions to print result or error frame +void mg_rpc_ok(struct mg_rpc_req*, const char* fmt, ...); +void mg_rpc_vok(struct mg_rpc_req*, const char* fmt, va_list* ap); +void mg_rpc_err(struct mg_rpc_req*, int code, const char* fmt, ...); +void mg_rpc_verr(struct mg_rpc_req*, int code, const char* fmt, va_list*); +void mg_rpc_list(struct mg_rpc_req* r); +// Copyright (c) 2023 Cesanta Software Limited +// All rights reserved + +#define MG_OTA_NONE 0 // No OTA support +#define MG_OTA_FLASH 1 // OTA via an internal flash +#define MG_OTA_CUSTOM 100 // Custom implementation + +#ifndef MG_OTA +#define MG_OTA MG_OTA_NONE +#endif + +// Firmware update API +bool mg_ota_begin(size_t new_firmware_size); // Start writing +bool mg_ota_write(const void* buf, size_t len); // Write chunk, aligned to 1k +bool mg_ota_end(void); // Stop writing + +enum { + MG_OTA_UNAVAILABLE = 0, // No OTA information is present + MG_OTA_FIRST_BOOT = 1, // Device booting the first time after the OTA + MG_OTA_UNCOMMITTED = 2, // Ditto, but marking us for the rollback + MG_OTA_COMMITTED = 3, // The firmware is good +}; +enum { MG_FIRMWARE_CURRENT = 0, + MG_FIRMWARE_PREVIOUS = 1 }; + +int mg_ota_status(int firmware); // Return firmware status MG_OTA_* +uint32_t mg_ota_crc32(int firmware); // Return firmware checksum +uint32_t mg_ota_timestamp(int firmware); // Firmware timestamp, UNIX UTC epoch +size_t mg_ota_size(int firmware); // Firmware size + +bool mg_ota_commit(void); // Commit current firmware +bool mg_ota_rollback(void); // Rollback to the previous firmware +// Copyright (c) 2023 Cesanta Software Limited +// All rights reserved + +#define MG_SYS_NONE 0 // Dummy system +#define MG_SYS_STM32H5 1 // STM32 H5 +#define MG_SYS_STM32H7 2 // STM32 H7 +#define MG_SYS_CUSTOM 100 // Custom implementation + +#ifndef MG_SYS +#define MG_SYS MG_SYS_NONE +#endif + +// Flash information +void* mg_flash_start(void); // Return flash start address +size_t mg_flash_size(void); // Return flash size +size_t mg_flash_sector_size(void); // Return flash sector size +size_t mg_flash_write_align(void); // Return flash write align, minimum 4 +int mg_flash_bank(void); // 0: not dual bank, 1: bank1, 2: bank2 + +// Write, erase, swap bank +bool mg_flash_write(void* addr, const void* buf, size_t len); +bool mg_flash_erase(void* addr); // Must be at sector boundary +bool mg_flash_swap_bank(void); + +// Convenience functions to store data on a flash sector with wear levelling +// If `sector` is NULL, then the last sector of flash is used +bool mg_flash_load(void* sector, uint32_t key, void* buf, size_t len); +bool mg_flash_save(void* sector, uint32_t key, const void* buf, size_t len); + +void mg_sys_reset(void); // Reboot device immediately + +#if defined(MG_ENABLE_TCPIP) && MG_ENABLE_TCPIP +struct mg_tcpip_if; // Mongoose TCP/IP network interface + +struct mg_tcpip_driver { + bool (*init)(struct mg_tcpip_if*); // Init driver + size_t (*tx)(const void*, size_t, struct mg_tcpip_if*); // Transmit frame + size_t (*rx)(void* buf, size_t len, struct mg_tcpip_if*); // Receive frame + bool (*up)(struct mg_tcpip_if*); // Up/down status +}; + +// Network interface +struct mg_tcpip_if { + uint8_t mac[6]; // MAC address. Must be set to a valid MAC + uint32_t ip, mask, gw; // IP address, mask, default gateway + struct mg_str tx; // Output (TX) buffer + bool enable_dhcp_client; // Enable DCHP client + bool enable_dhcp_server; // Enable DCHP server + bool enable_crc32_check; // Do a CRC check on RX frames and strip it + bool enable_mac_check; // Do a MAC check on RX frames + struct mg_tcpip_driver* driver; // Low level driver + void* driver_data; // Driver-specific data + struct mg_mgr* mgr; // Mongoose event manager + struct mg_queue recv_queue; // Receive queue + uint16_t mtu; // Interface MTU +#define MG_TCPIP_MTU_DEFAULT 1500 + + // Internal state, user can use it but should not change it + uint8_t gwmac[6]; // Router's MAC + uint64_t now; // Current time + uint64_t timer_1000ms; // 1000 ms timer: for DHCP and link state + uint64_t lease_expire; // Lease expiration time, in ms + uint16_t eport; // Next ephemeral port + volatile uint32_t ndrop; // Number of received, but dropped frames + volatile uint32_t nrecv; // Number of received frames + volatile uint32_t nsent; // Number of transmitted frames + volatile uint32_t nerr; // Number of driver errors + uint8_t state; // Current state +#define MG_TCPIP_STATE_DOWN 0 // Interface is down +#define MG_TCPIP_STATE_UP 1 // Interface is up +#define MG_TCPIP_STATE_REQ 2 // Interface is up and has requested an IP +#define MG_TCPIP_STATE_READY 3 // Interface is up and has an IP assigned +}; + +void mg_tcpip_init(struct mg_mgr*, struct mg_tcpip_if*); +void mg_tcpip_free(struct mg_tcpip_if*); +void mg_tcpip_qwrite(void* buf, size_t len, struct mg_tcpip_if* ifp); + +extern struct mg_tcpip_driver mg_tcpip_driver_stm32; +extern struct mg_tcpip_driver mg_tcpip_driver_w5500; +extern struct mg_tcpip_driver mg_tcpip_driver_tm4c; +extern struct mg_tcpip_driver mg_tcpip_driver_stm32h; +extern struct mg_tcpip_driver mg_tcpip_driver_imxrt; +extern struct mg_tcpip_driver mg_tcpip_driver_same54; + +// Drivers that require SPI, can use this SPI abstraction +struct mg_tcpip_spi { + void* spi; // Opaque SPI bus descriptor + void (*begin)(void*); // SPI begin: slave select low + void (*end)(void*); // SPI end: slave select high + uint8_t (*txn)(void*, uint8_t); // SPI transaction: write 1 byte, read reply +}; +#endif + +struct mg_tcpip_driver_imxrt1020_data { + // MDC clock divider. MDC clock is derived from IPS Bus clock (ipg_clk), + // must not exceed 2.5MHz. Configuration for clock range 2.36~2.50 MHz + // ipg_clk MSCR mdc_cr VALUE + // ------------------------------------- + // -1 <-- tell driver to guess the value + // 25 MHz 0x04 0 + // 33 MHz 0x06 1 + // 40 MHz 0x07 2 + // 50 MHz 0x09 3 + // 66 MHz 0x0D 4 <-- value for iMXRT1020-EVK at max freq. + int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4 +}; + +#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && MG_ENABLE_DRIVER_SAME54 + +struct mg_tcpip_driver_same54_data { + int mdc_cr; +}; + +#endif + +struct mg_tcpip_driver_stm32_data { + // MDC clock divider. MDC clock is derived from HCLK, must not exceed 2.5MHz + // HCLK range DIVIDER mdc_cr VALUE + // ------------------------------------- + // -1 <-- tell driver to guess the value + // 60-100 MHz HCLK/42 0 + // 100-150 MHz HCLK/62 1 + // 20-35 MHz HCLK/16 2 + // 35-60 MHz HCLK/26 3 + // 150-216 MHz HCLK/102 4 <-- value for Nucleo-F* on max speed + // 216-310 MHz HCLK/124 5 + // 110, 111 Reserved + int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5 +}; + +struct mg_tcpip_driver_stm32h_data { + // MDC clock divider. MDC clock is derived from HCLK, must not exceed 2.5MHz + // HCLK range DIVIDER mdc_cr VALUE + // ------------------------------------- + // -1 <-- tell driver to guess the value + // 60-100 MHz HCLK/42 0 + // 100-150 MHz HCLK/62 1 + // 20-35 MHz HCLK/16 2 + // 35-60 MHz HCLK/26 3 + // 150-250 MHz HCLK/102 4 <-- value for Nucleo-H* on max speed + // driven by HSI 250-300 MHz HCLK/124 5 <-- value for Nucleo-H* on + // max speed driven by CSI 110, 111 Reserved + int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5 +}; + +struct mg_tcpip_driver_tm4c_data { + // MDC clock divider. MDC clock is derived from SYSCLK, must not exceed 2.5MHz + // SYSCLK range DIVIDER mdc_cr VALUE + // ------------------------------------- + // -1 <-- tell driver to guess the value + // 60-100 MHz SYSCLK/42 0 + // 100-150 MHz SYSCLK/62 1 <-- value for EK-TM4C129* on max speed + // 20-35 MHz SYSCLK/16 2 + // 35-60 MHz SYSCLK/26 3 + // 0x4-0xF Reserved + int mdc_cr; // Valid values: -1, 0, 1, 2, 3 +}; + +#ifdef __cplusplus +} +#endif +#endif // MONGOOSE_H \ No newline at end of file diff --git a/APP_Framework/Applications/mongoose/project.c b/APP_Framework/Applications/mongoose/project.c new file mode 100644 index 000000000..cf05a4af9 --- /dev/null +++ b/APP_Framework/Applications/mongoose/project.c @@ -0,0 +1,142 @@ +// Copyright (c) 2022 Cesanta Software Limited +// All rights reserved +// +// UI example +// It implements the following endpoints: +// /api/config/get - respond with current config +// /api/config/set - POST a config change +// any other URI serves static files from s_root_dir +// Data and results are JSON strings + +#include "ip_addr.h" +#include "mongoose.h" +#include "netdev.h" + +char index_path[] = "login.html"; + +static const char* s_http_addr = "http://192.168.131.88:8000"; // HTTP port +static const char* s_root_dir = "webserver"; +static const char* s_enable_hexdump = "no"; +static const char* s_ssi_pattern = "#.html"; + +static const char* device_type = "Edu-ARM32"; +static const char* web_version = "XUOS Webserver 1.0"; +static int enable_4g = 0; + +static struct netdev* p_netdev; + +static struct config { + char *ip, *mask, *gw, *dns; +} s_config; + +// Try to update a single configuration value +static void update_config(struct mg_str json, const char* path, char** value) +{ + char* jval; + if ((jval = mg_json_get_str(json, path)) != NULL) { + free(*value); + *value = strdup(jval); + } +} + +static void fn(struct mg_connection* c, int ev, void* ev_data, void* fn_data) +{ + if (ev == MG_EV_HTTP_MSG) { + struct mg_http_message *hm = (struct mg_http_message*)ev_data, tmp = { 0 }; + if (mg_http_match_uri(hm, "/getSystemInfo")) { + mg_http_reply(c, 200, "Content-Type: application/json\r\n", + "{%m:%m, %m:%m, %m:%m, %m:%m, %m:%m, %m:%d}\n", + MG_ESC("ip"), MG_ESC(s_config.ip), + MG_ESC("deviceType"), MG_ESC(device_type), + MG_ESC("deviceNo"), MG_ESC("0"), + MG_ESC("systemTime"), MG_ESC("YYYY:MM:DD hh:mm:ss"), + MG_ESC("webVersion"), MG_ESC(web_version), + MG_ESC("statusOf4g"), enable_4g); + } else if (mg_http_match_uri(hm, "/net/get4gInfo")) { + mg_http_reply(c, 200, "Content-Type: application/json\r\n", + "{%m:%m}\n", + MG_ESC("enable4g"), MG_ESC(enable_4g)); + } else if (mg_http_match_uri(hm, "/net/set4gInfo")) { + struct mg_str json = hm->body; + enable_4g = mg_json_get_long(json, "$.enable4g", 0); + mg_http_reply(c, 200, "Content-Type: application/json\r\n", "{\"status\":\"success\"}\r\n"); + printf("Get enable 4g setting: %d\n", enable_4g); + } else if (mg_http_match_uri(hm, "/net/getEthernetInfo")) { + mg_http_reply(c, 200, "Content-Type: application/json\r\n", + "{%m:%m, %m:%m, %m:%m, %m:%m}\n", + MG_ESC("ip"), MG_ESC(s_config.ip), + MG_ESC("netmask"), MG_ESC(s_config.mask), + MG_ESC("gateway"), MG_ESC(s_config.gw), + MG_ESC("dns"), MG_ESC(s_config.dns)); + } else if (mg_http_match_uri(hm, "/net/setEthernetInfo")) { + struct mg_str json = hm->body; + printf("json: %s\n", json.ptr); + update_config(json, "$.ip", &s_config.ip); + update_config(json, "$.netmask", &s_config.mask); + update_config(json, "$.gateway", &s_config.gw); + update_config(json, "$.dns", &s_config.dns); + mg_http_reply(c, 200, "Content-Type: application/json\r\n", "{\"status\":\"success\"}\r\n"); + + ip_addr_t ipaddr, maskaddr, gwaddr; + inet_aton(s_config.ip, &ipaddr); + inet_aton(s_config.mask, &maskaddr); + inet_aton(s_config.gw, &gwaddr); + p_netdev->ops->set_addr_info(p_netdev, &ipaddr, &maskaddr, &gwaddr); + + printf("Board Net Configuration changed to [IP: %s, Mask: %s, GW: %s, DNS: %s]\n", + s_config.ip, + s_config.mask, + s_config.gw, + s_config.dns); + } else { + struct mg_str unknown = mg_str_n("?", 1), *cl; + struct mg_http_serve_opts opts = { .root_dir = s_root_dir, .ssi_pattern = s_ssi_pattern }; + mg_http_serve_dir(c, hm, &opts); + mg_http_parse((char*)c->send.buf, c->send.len, &tmp); + cl = mg_http_get_header(&tmp, "Content-Length"); + if (cl == NULL) + cl = &unknown; + MG_INFO(("%.*s %.*s %.*s %.*s", (int)hm->method.len, hm->method.ptr, + (int)hm->uri.len, hm->uri.ptr, (int)tmp.uri.len, tmp.uri.ptr, + (int)cl->len, cl->ptr)); + } + } + (void)fn_data; +} + +static void* do_webserver_demo(void* none) +{ + p_netdev = netdev_get_by_name("wz"); + if (p_netdev == NULL) { + MG_INFO(("Did nto find wz netdev, use default.\n")); + p_netdev = NETDEV_DEFAULT; + } + MG_INFO(("Use Netdev %s", p_netdev->name)); + s_config.ip = strdup(inet_ntoa(*p_netdev->ip_addr)); + s_config.mask = strdup(inet_ntoa(*p_netdev->netmask)); + s_config.gw = strdup(inet_ntoa(*p_netdev->gw)); + s_config.dns = strdup(inet_ntoa(p_netdev->dns_servers[0])); + + struct mg_mgr mgr; // Event manager + // mg_log_set(MG_LL_INFO); // Set to 3 to enable debug + mg_log_set(MG_LL_DEBUG); // Set to 3 to enable debug + mg_mgr_init(&mgr); // Initialise event manager + mg_http_listen(&mgr, s_http_addr, fn, NULL); // Create HTTP listener + for (;;) + mg_mgr_poll(&mgr, 50); // Infinite event loop + mg_mgr_free(&mgr); + return NULL; +} + +int webserver_demo(int argc, char* argv[]) +{ + pthread_t tid = -1; + pthread_attr_t attr; + attr.schedparam.sched_priority = 30; + attr.stacksize = 0x2000; + + PrivTaskCreate(&tid, &attr, do_webserver_demo, NULL); + + return 0; +} +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(5), Webserver, webserver_demo, webserver for project); \ No newline at end of file diff --git a/APP_Framework/Framework/connection/4g/ec200t/ec200t.c b/APP_Framework/Framework/connection/4g/ec200t/ec200t.c index c916f36f1..073ea8b93 100644 --- a/APP_Framework/Framework/connection/4g/ec200t/ec200t.c +++ b/APP_Framework/Framework/connection/4g/ec200t/ec200t.c @@ -175,6 +175,7 @@ static int Ec200tIoctl(struct Adapter *adapter, int cmd, void *args) serial_cfg.ext_uart_no = ADAPTER_EC200T_DRIVER_EXT_PORT; serial_cfg.port_configure = PORT_CFG_INIT; #endif + serial_cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; diff --git a/APP_Framework/Framework/connection/bluetooth/hc08/hc08.c b/APP_Framework/Framework/connection/bluetooth/hc08/hc08.c index d04b732b4..cb620679c 100644 --- a/APP_Framework/Framework/connection/bluetooth/hc08/hc08.c +++ b/APP_Framework/Framework/connection/bluetooth/hc08/hc08.c @@ -268,6 +268,7 @@ static int Hc08Open(struct Adapter *adapter) serial_cfg.ext_uart_no = ADAPTER_HC08_DRIVER_EXT_PORT; serial_cfg.port_configure = PORT_CFG_INIT; #endif + serial_cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; @@ -326,6 +327,7 @@ static int Hc08Ioctl(struct Adapter *adapter, int cmd, void *args) serial_cfg.ext_uart_no = ADAPTER_HC08_DRIVER_EXT_PORT; serial_cfg.port_configure = PORT_CFG_INIT; #endif + serial_cfg.dev_recv_callback = NULL; serial_cfg.serial_timeout = -1; diff --git a/APP_Framework/Framework/connection/ethernet/hfa21_ethernet/hfa21_ethernet.c b/APP_Framework/Framework/connection/ethernet/hfa21_ethernet/hfa21_ethernet.c index cb8a31040..a29d4bfe6 100644 --- a/APP_Framework/Framework/connection/ethernet/hfa21_ethernet/hfa21_ethernet.c +++ b/APP_Framework/Framework/connection/ethernet/hfa21_ethernet/hfa21_ethernet.c @@ -407,6 +407,7 @@ static int Hfa21EthernetIoctl(struct Adapter *adapter, int cmd, void *args) serial_cfg.ext_uart_no = ADAPTER_HFA21_DRIVER_EXT_PORT; serial_cfg.port_configure = PORT_CFG_INIT; #endif + serial_cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/Kconfig b/APP_Framework/Framework/connection/industrial_fieldbus/Kconfig index e69de29bb..0c1c0f3e5 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/Kconfig +++ b/APP_Framework/Framework/connection/industrial_fieldbus/Kconfig @@ -0,0 +1,10 @@ +config CONNECTION_MODBUS + bool "Using industrial fieldbus ModBus" + default n + +if CONNECTION_MODBUS + source "$APP_DIR/Framework/connection/industrial_fieldbus/modbus/Kconfig" +endif + + + diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/Makefile b/APP_Framework/Framework/connection/industrial_fieldbus/Makefile index e46dea29a..1ed0b9544 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/Makefile +++ b/APP_Framework/Framework/connection/industrial_fieldbus/Makefile @@ -1,3 +1,7 @@ SRC_DIR := +ifeq ($(CONFIG_CONNECTION_MODBUS),y) + SRC_DIR += modbus +endif + include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/demo.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/demo.c deleted file mode 100644 index 2ae19a65a..000000000 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/demo.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * FreeModbus Libary: BARE Demo Application - * Copyright (C) 2006 Christian Walter - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * File: $Id$ - */ - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mbport.h" - -/* ----------------------- Defines ------------------------------------------*/ -#define REG_INPUT_START 1000 -#define REG_INPUT_NREGS 4 - -/* ----------------------- Static variables ---------------------------------*/ -static USHORT usRegInputStart = REG_INPUT_START; -static USHORT usRegInputBuf[REG_INPUT_NREGS]; - -/* ----------------------- Start implementation -----------------------------*/ -int -main( void ) -{ - eMBErrorCode eStatus; - - eStatus = eMBInit( MB_RTU, 0x0A, 0, 38400, MB_PAR_EVEN ); - - /* Enable the Modbus Protocol Stack. */ - eStatus = eMBEnable( ); - - for( ;; ) - { - ( void )eMBPoll( ); - - /* Here we simply count the number of poll cycles. */ - usRegInputBuf[0]++; - } -} - -eMBErrorCode -eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs ) -{ - eMBErrorCode eStatus = MB_ENOERR; - int iRegIndex; - - if( ( usAddress >= REG_INPUT_START ) - && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) ) - { - iRegIndex = ( int )( usAddress - usRegInputStart ); - while( usNRegs > 0 ) - { - *pucRegBuffer++ = - ( unsigned char )( usRegInputBuf[iRegIndex] >> 8 ); - *pucRegBuffer++ = - ( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF ); - iRegIndex++; - usNRegs--; - } - } - else - { - eStatus = MB_ENOREG; - } - - return eStatus; -} - -eMBErrorCode -eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, - eMBRegisterMode eMode ) -{ - return MB_ENOREG; -} - - -eMBErrorCode -eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, - eMBRegisterMode eMode ) -{ - return MB_ENOREG; -} - -eMBErrorCode -eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete ) -{ - return MB_ENOREG; -} diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/port/port.h b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/port/port.h deleted file mode 100644 index c2a0f7d4b..000000000 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/port/port.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * FreeModbus Libary: BARE Port - * Copyright (C) 2006 Christian Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * File: $Id$ - */ - -#ifndef _PORT_H -#define _PORT_H - -#include -#include - -#define INLINE inline -#define PR_BEGIN_EXTERN_C extern "C" { -#define PR_END_EXTERN_C } - -#define ENTER_CRITICAL_SECTION( ) -#define EXIT_CRITICAL_SECTION( ) - -typedef uint8_t BOOL; - -typedef unsigned char UCHAR; -typedef char CHAR; - -typedef uint16_t USHORT; -typedef int16_t SHORT; - -typedef uint32_t ULONG; -typedef int32_t LONG; - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -#endif diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/port/portevent.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/port/portevent.c deleted file mode 100644 index e700a471c..000000000 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/port/portevent.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * FreeModbus Libary: BARE Port - * Copyright (C) 2006 Christian Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * File: $Id$ - */ - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mbport.h" - -/* ----------------------- Variables ----------------------------------------*/ -static eMBEventType eQueuedEvent; -static BOOL xEventInQueue; - -/* ----------------------- Start implementation -----------------------------*/ -BOOL -xMBPortEventInit( void ) -{ - xEventInQueue = FALSE; - return TRUE; -} - -BOOL -xMBPortEventPost( eMBEventType eEvent ) -{ - xEventInQueue = TRUE; - eQueuedEvent = eEvent; - return TRUE; -} - -BOOL -xMBPortEventGet( eMBEventType * eEvent ) -{ - BOOL xEventHappened = FALSE; - - if( xEventInQueue ) - { - *eEvent = eQueuedEvent; - xEventInQueue = FALSE; - xEventHappened = TRUE; - } - return xEventHappened; -} diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/port/portserial.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/port/portserial.c deleted file mode 100644 index f21c310b9..000000000 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/port/portserial.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * FreeModbus Libary: BARE Port - * Copyright (C) 2006 Christian Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * File: $Id$ - */ - - -#include - -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mbport.h" - -/* ----------------------- static functions ---------------------------------*/ -static void prvvUARTTxReadyISR( void ); -static void prvvUARTRxISR( void ); - -/* ----------------------- Start implementation -----------------------------*/ -void -vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable ) -{ - /* If xRXEnable enable serial receive interrupts. If xTxENable enable - * transmitter empty interrupts. - */ - - if(xRxEnable && !xTxEnable)//接收数据 - { - Set485Input(); - } - if(!xRxEnable && xTxEnable) - { - Set485Output(); - } - -} - -BOOL -xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity ) -{ - struct SerialDataCfg serial_cfg; - memset(&serial_cfg, 0 ,sizeof(struct SerialDataCfg)); - serial_cfg.serial_baud_rate = (uint32_t)ulBaudRate; - serial_cfg.serial_data_bits = (uint8_t)ucDataBits; - serial_cfg.serial_stop_bits = STOP_BITS_1; - serial_cfg.serial_buffer_size = SERIAL_RB_BUFSZ; - serial_cfg.serial_parity_mode = (uint8_t)eParity; - serial_cfg.serial_bit_order = STOP_BITS_1; - serial_cfg.serial_invert_mode = NRZ_NORMAL; - serial_cfg.is_ext_uart = 0; - - - - return FALSE; -} - -BOOL -xMBPortSerialPutByte( CHAR ucByte ) -{ - /* Put a byte in the UARTs transmit buffer. This function is called - * by the protocol stack if pxMBFrameCBTransmitterEmpty( ) has been - * called. */ - Set485Output(); - PrivTaskDelay(20); - - PrivWrite(uart_fd, ucByte, 1); - - PrivTaskDelay(15); - Set485Input(); - return TRUE; -} - -BOOL -xMBPortSerialGetByte( CHAR * pucByte ) -{ - /* Return the byte in the UARTs receive buffer. This function is called - * by the protocol stack after pxMBFrameCBByteReceived( ) has been called. - */ - - - - PrivRead(uart_fd, pucByte, 1);// - - //need to wait 30ms , make sure write cmd again and receive data successfully - PrivTaskDelay(30); - - return TRUE; -} - -/* Create an interrupt handler for the transmit buffer empty interrupt - * (or an equivalent) for your target processor. This function should then - * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that - * a new character can be sent. The protocol stack will then call - * xMBPortSerialPutByte( ) to send the character. - */ -static void prvvUARTTxReadyISR( void ) -{ - pxMBFrameCBTransmitterEmpty( ); -} - -/* Create an interrupt handler for the receive interrupt for your target - * processor. This function should then call pxMBFrameCBByteReceived( ). The - * protocol stack will then call xMBPortSerialGetByte( ) to retrieve the - * character. - */ -static void prvvUARTRxISR( void ) -{ - pxMBFrameCBByteReceived( ); -} - -static int pin_fd = 0; -static int uart_fd = 0; - -/** - * @description: Set Uart 485 Input - * @return - */ -static void Set485Input(void) -{ - struct PinStat pin_stat; - pin_stat.pin = 2;//CONTROL_FRAMEWORK_UART_485_DIR - pin_stat.val = GPIO_LOW; - PrivWrite(pin_fd, &pin_stat, 1); -} - -/** - * @description: Set Uart 485 Output - * @return - */ -static void Set485Output(void) -{ - struct PinStat pin_stat; - pin_stat.pin = 2;//CONTROL_FRAMEWORK_UART_485_DIR - pin_stat.val = GPIO_HIGH; - PrivWrite(pin_fd, &pin_stat, 1); -} diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/port/porttimer.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/port/porttimer.c deleted file mode 100644 index b31fa19e3..000000000 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/port/porttimer.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * FreeModbus Libary: BARE Port - * Copyright (C) 2006 Christian Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * File: $Id$ - */ - -/* ----------------------- Platform includes --------------------------------*/ -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mbport.h" - -/* ----------------------- static functions ---------------------------------*/ -static void prvvTIMERExpiredISR( void ); - -/* ----------------------- Start implementation -----------------------------*/ -BOOL -xMBPortTimersInit( USHORT usTim1Timerout50us ) -{ - PrivTaskDelay(usTim1Timerout50us); - return FALSE; -} - - -inline void -vMBPortTimersEnable( ) -{ - /* Enable the timer with the timeout passed to xMBPortTimersInit( ) */ - PrivTaskDelay(usTim1Timerout50us); -} - -inline void -vMBPortTimersDisable( ) -{ - /* Disable any pending timers. */ -} - -/* Create an ISR which is called whenever the timer has expired. This function - * must then call pxMBPortCBTimerExpired( ) to notify the protocol stack that - * the timer has expired. - */ -static void prvvTIMERExpiredISR( void ) -{ - ( void )pxMBPortCBTimerExpired( ); -} - diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/Kconfig b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/Kconfig index e69de29bb..8946da105 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/Kconfig +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/Kconfig @@ -0,0 +1,214 @@ +choice + prompt "choose ModBus type" + default CONNECTION_MODBUS_USING_RTU + + config CONNECTION_MODBUS_USING_RTU + bool "select ModBus_RTU function" + + config CONNECTION_MODBUS_USING_TCP + bool "select ModBus_TCP function" +endchoice + +if CONNECTION_MODBUS_USING_RTU + choice + prompt "choose ModBus_RTU work mode" + default CONNECTION_MODBUS_USING_RTU_MASTER + + config CONNECTION_MODBUS_USING_RTU_MASTER + bool "select ModBus_RTU master mode" + + config CONNECTION_MODBUS_USING_RTU_SLAVE + bool "select ModBus_RTU slave mode" + endchoice + + if CONNECTION_MODBUS_USING_RTU_MASTER + menu "ModBus_RTU Master Register Configure" + config X_M_DISCRETE_INPUT_START + int "master discrete input start address" + default 0 + + config X_M_DISCRETE_INPUT_NDISCRETES + int "master discrete input discretes numbers" + default 16 + + config X_M_COIL_START + int "master coil start address" + default 0 + + config X_M_COIL_NCOILS + int "master coil numbers" + default 64 + + config X_M_REG_INPUT_START + int "master input start address" + default 0 + + config X_M_REG_INPUT_NREGS + int "master input regs numbers" + default 100 + + config X_M_REG_HOLDING_START + int "master holding start address" + default 0 + + config X_M_REG_HOLDING_NREGS + int "master holding regs numbers" + default 100 + + config X_M_HD_RESERVE + int "master holding reserve numbers" + default 0 + + config X_M_IN_RESERVE + int "master input reserve numbers" + default 0 + + config X_M_CO_RESERVE + int "master coil reserve numbers" + default 0 + + config X_M_DI_RESERVE + int "master discrete reserve numbers" + default 0 + endmenu + endif + + if CONNECTION_MODBUS_USING_RTU_SLAVE + menu "ModBus_RTU Slave Register Configure" + config X_S_DISCRETE_INPUT_START + int "slave discrete input start address" + default 0 + + config X_S_DISCRETE_INPUT_NDISCRETES + int "slave discrete input discretes numbers" + default 16 + + config X_S_COIL_START + int "slave coil start address" + default 0 + + config X_S_COIL_NCOILS + int "slave coil numbers" + default 64 + + config X_S_REG_INPUT_START + int "slave input start address" + default 0 + + config X_S_REG_INPUT_NREGS + int "slave input regs numbers" + default 100 + + config X_S_REG_HOLDING_START + int "slave holding start address" + default 0 + + config X_S_REG_HOLDING_NREGS + int "slave holding regs numbers" + default 100 + + config X_S_HD_RESERVE + int "slave holding reserve numbers" + default 0 + + config X_S_IN_RESERVE + int "slave input reserve numbers" + default 0 + + config X_S_CO_RESERVE + int "slave coil reserve numbers" + default 0 + + config X_S_DI_RESERVE + int "slave discrete reserve numbers" + default 0 + endmenu + endif + + config CONNECTION_MODBUS_RTU_UART_485_DIR + int "serial 485 direction pin number" + default "67" + + config CONNECTION_MODBUS_RTU_PIN_DEV + string "device pin dev path for serial 485 DIR" + default "/dev/pin_dev" + + config CONNECTION_MODBUS_RTU_EXTUART + bool "Using extra uart to support serial 485" + default n + + config CONNECTION_MODBUS_RTU_UART_DEV + string "device uart dev path for serial 485" + default "/dev/usart4_dev4" + depends on !CONTROL_FRAMEWORK_DRIVER_EXTUART + + if CONTROL_FRAMEWORK_DRIVER_EXTUART + config CONNECTION_MODBUS_RTU_UART_DEV + string "device extra uart dev path for serial 485" + default "/dev/extuart_dev0" + + config CONNECTION_MODBUS_RTU_UART_DEV_EXT_PORT + int "if device using extuart, choose port" + default "0" + endif +endif + +if CONNECTION_MODBUS_USING_TCP + config CONNECTION_MODBUS_USING_TCP_SLAVE + bool "select ModBus_TCP slave mode" + default y + + if CONNECTION_MODBUS_USING_TCP_SLAVE + menu "ModBus_TCP Slave Register Configure" + config X_S_DISCRETE_INPUT_START + int "slave discrete input start address" + default 0 + + config X_S_DISCRETE_INPUT_NDISCRETES + int "slave discrete input discretes numbers" + default 16 + + config X_S_COIL_START + int "slave coil start address" + default 0 + + config X_S_COIL_NCOILS + int "slave coil numbers" + default 64 + + config X_S_REG_INPUT_START + int "slave input start address" + default 0 + + config X_S_REG_INPUT_NREGS + int "slave input regs numbers" + default 100 + + config X_S_REG_HOLDING_START + int "slave holding start address" + default 0 + + config X_S_REG_HOLDING_NREGS + int "slave holding regs numbers" + default 100 + + config X_S_HD_RESERVE + int "slave holding reserve numbers" + default 0 + + config X_S_IN_RESERVE + int "slave input reserve numbers" + default 0 + + config X_S_CO_RESERVE + int "slave coil reserve numbers" + default 0 + + config X_S_DI_RESERVE + int "slave discrete reserve numbers" + default 0 + endmenu + endif +endif + + diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/Makefile b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/Makefile index e46dea29a..363c085a0 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/Makefile +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/Makefile @@ -1,3 +1,11 @@ -SRC_DIR := +SRC_DIR := freemodbus-latest + +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_RTU),y) + SRC_FILES := +endif + +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_TCP),y) + SRC_FILES := +endif include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/adapter_modbus_rtu.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/adapter_modbus_rtu.c deleted file mode 100644 index e0b77d10e..000000000 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/adapter_modbus_rtu.c +++ /dev/null @@ -1,65 +0,0 @@ -/* -* 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 adapter_Modbus_rtu.c - * @brief Implement the connection 4G adapter function - * @version 1.1 - * @author AIIT XIUOS Lab - * @date 2021.06.25 - */ - -#include - - - -static int AdapterModbusRtuRegister(struct Adapter *adapter) -{ - int ret = 0; - - strncpy(adapter->name, ADAPTER_MODBUS_RTU_NAME, NAME_NUM_MAX); - - adapter->net_protocol = PROTOCOL_NONE;//IP层协议类型,串口没有此层 - adapter->net_role = SLAVE; - adapter->adapter_status = UNREGISTERED; - - ret = AdapterDeviceRegister(adapter); - if (ret < 0) { - printf("AdapterModbusRtu register error\n"); - return -1; - } - - return ret; -} - -int AdapterModbusRtuInit(void) -{ - int ret = 0; - - struct Adapter *adapter = PrivMalloc(sizeof(struct Adapter)); - if (!adapter) { - PrivFree(adapter); - return -1; - } - - memset(adapter, 0, sizeof(struct Adapter)); - - ret = AdapterModbusRtuRegister(adapter); - if (ret < 0) { - printf("AdapterModbusRtuInit register ModbusRtu adapter error\n"); - PrivFree(adapter); - return -1; - } - - return ret; -} - diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/Changelog.txt b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/Changelog.txt new file mode 100644 index 000000000..2816ea30f --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/Changelog.txt @@ -0,0 +1,329 @@ +2013-10-17 (REL_1_6_0) Armink + Notes: Added modbus master. + +2010-05-06 (REL_1_5_0) Christian Walter + Notes: Added support for Atmel AT91SAM3S (Cortex M3) for IAR. + + Detailed notes: + - FEATURES (ATSAM3S) : Added new port. + +2007-08-28 (REL_1_4_0) Christian Walter : + Notes: Added support for HCS08. Fixed some small bugs in the documentation + for the porting layer. + + Detailed notes: + - FEATURES (HCS08) : Added new port. + - BUGS (ALL) : Fixed some small bugs in the porting guide. + +2007-07-17 (REL_1_3_0) Christian Walter : + Notes: Added ARM7/AT91SAM7X port. Added Linux/TCP port from Steven Guo. + + Detailed notes: + - FEATURES (ARM7): Added ARM7/AT91SAM7x port. + - FEATURES (LINUX): Added Linux/TCP port from Steven Guo. + - BUGS (ALL): Fixed bug in where the high + byte of the register count was ignored. This does not have a + practical impact because the actual number of registers is always + lower. + +2007-07-17 (REL_1_3_0) Christian Walter : + Notes: Added Linux/TCP port. Fixed bug in MSP430 port. + Detailted notes: + - FEATURE (LINUX): Added Linux/TCP port. + - BUGS (MSP430): Fixed bug with calculating the timer value. + +2007-04-25 (REL_1_2_0) Christian Walter : + Notes: Added LPC214X ARM port with Keil compiler. Added Z8Encore port for + Z8F6422 microcontroller. + + Detailed notes: + - FEATURE (ARM): Added LPC214X ARM port for Keil ARM 2.41. + - FEATURE (Z8ENCORE): Added Z8F6422 for Z8Encore using the ZDS II - Z8 + Encore! development tools. + +2007-02-18 (REL_1_1_2) Christian Walter : + Notes: Fixed typo with the defined defining the supported Modbus + functions. Fixed bug when illegal slave address was passed to eMBInit + where the error was not detected. Fixed typo in the holding registers + where the frame for write multiple registers was parsed with the wrong + constants. The fix is not critical because the values matched. Fixed bug + in discrete input registers implementation where the frame was not parsed + correctly. Added new support for a CodeWarrior Coldfire port. + + Detailed notes: + - BUG (ALL): Modbus functions are compiled into the stack conditionally + by changing the MB_FUNC_XXX defines to either true(1) or false(0). + The defines for MB_FUNC_READ_HOLDING and MB_FUNC_WRITE_HOLDING + were wrong. + - BUG (ALL): eMBInit did not correctly check for addresses. Therefore + is was possible to start the Modbus stack with an address of 0 + or one > 247. + - BUG (ALL): eMBFuncWriteHoldingRegister should use + MB_PDU_FUNC_WRITE_MUL_ADDR_OFF and not MB_PDU_FUNC_READ_ADDR_OFF. + - BUG (ALL): eMBFuncReadDiscreteInputs calculated the number of discrete + registers to read wrong. + - FEATURE (ALL): Fixed some warnings in the code. + +2006-11-19 (REL_1_1_1) Christian Walter : + Notes: Fixed bug in Read/Write Multiple Registers function where + the registers addresses where calculated wrong. + Fixed bug in RTU and ASCII with the resource allocation in case of + an error. + Changed license to BSD style licsense. + + Detailed notes: + - OTHER (ALL): License is now BSD for protocol stack. + - BUG (ALL): The registers address received in a Modbus frame + must be converted to application addresses. The code for this + conversion was missing and therefore has lead to error when + this function was used (Registers of by one, Start at > 1). + - BUG (ALL): If the serial initialization within the porting fails + a timer is still allocated in eMBRTUInit and eMBASCIIInit. This + can lead to a memory leak depending upon the implementation of the + porting layer. + - FEATURE (MCF5235): Added sample shell scripts for testing. + - FEATURE (MSP430): Added sample shell script for testing and + changed default values to match the other ports. + +2006-10-30 (REL_1_1_0) Christian Walter : + Notes: Added support for Read/Write Multiple Registers function + (0x17). Added some tips to reduce memory requirements. + Added MSP430 Port for GCC and Rowley Crossworks. + + Detailed notes: + - FEATURE (MSP430): Added new MSP430 port. + - FEATURE (ALL): Added support for Read/Write Multiple Registers + function (0x17). The implementation simply makes two callbacks + to the eMBRegHoldingCB function where first the values are + written and then the other register values are read. + - FEATURE (ALL): Added some tips on reducing memory requirements + with the protocol stack. + +2006-10-30 (REL_1_0_5) Christian Walter : + Notes: eMBDisable and eMBClose can now be called multiple times + which makes shutdown of the protocol stack easier. + Fixed bug in RTU state machine where we switched from the + error state immediately to the idle state. Correct behaviour + would be to wait till the end of frame. + Added new STR71X GCC port which uses only freely available tools + like GNU ARM, OpenOCD (Wiggler) and GDB. + + Detailed notes: + - FEATURE (STR71X): Added GCC standalone port which does not + depend on the Rowley Crosswork tools. + - FEATURE (ALL): eMBDisable can now be called multiple times + and returns MB_ENOERR in case is was already disabled. + eMBClose also supports beeing called multiple times in + which pvMBFrameCloseCur( ) is called when the protocol stack + is in state STATE_DISABLED. + - BUG (RTU): Fixed bug in xMBRTUReceiveFSM where the error + state is immediately left because of a missing break. Instead + we should wait till the damaged frame is finished. + +2006-10-11 (REL_1_0_4) Christian Walter : + Notes: Fixed bug when more than 255 coils are requested. Fixed bug in + Linux/Cygwin port when not all bytes could be written by the first + call to write. Added support for removing previously registered + function handlers. + + Detailed notes: + - BUG (ALL): mbfunccoils contained a bug which limited the amount + of coils to read to 255. + - BUG (LINUX): prvbMBPortSerialWrite contained a bug in the loop + which writes the RTU/ASCII frame to the serial file descriptor. + If not all bytes where written in the first call or write was + interrupted the sent frame is corrupted. + - FEATURE (ALL): eMBRegisterCB now supports NULL as handler + argument in which case a previously registered function + handler is deregistered from the protocol stack. + +2006-09-27 (REL_1_0_3) Christian Walter : + Notes: Added new functions to support registering of custom callback + handlers. This makes it possible to implement new Modbus function + codes without touching the protocol stack. + New port for ATMega128 added. Thanks to Richard C Sandoz Jr. for + the patches. + + Detailed notes: + - FEATURE (ALL): Added support for registering new functions handlers + with eMBRegisterCB. + - FEATURE (AVR): Added patches from Richard C Sandoz Jr. for ATMega128 + +2006-09-06 (REL_1_0_2) Christian Walter : + Notes: Fixed bug in FreeRTOS porting layer for STR71X/lwIP target where + memory is not freed in the sys_arch_thread_remove function. + Synched MCF5235TCP port with the FreeRTOS/lwIP port for the STR71X. + + Detailed notes: + - BUG (STR71XTCP): Sys_arch_thread_remove did not free the memory from + the TCB. + - BUG (STR71XTCP): Unnecessary call to vTaskSuspendAll removed. + - BUG (STR71XTCP): Bug with counting variable. The first to lwIP tasks + got the same name (lwIP0). + - FEATURE (MCF5235TCP): Enhanced functions from the STR71X/lwIP port + merged into the Coldfire port. + +2006-09-04 (REL_1_0_1) Christian Walter : + Notes: Fixed bug in serial driver for STR71x target when the ring buffer + overflows. + + Detailed notes: + - BUG (STR71XTCP): Under high load the ring buffer in the serial driver + functions might overflow. There was an error with counting the number + of received characters which corrupted received frames. + Now receiver correctly recovers in case of dropped bytes. + +2006-09-04 (REL_1_0) Christian Walter : + Notes: Added support for ATmega8, ATmega16, ATmega32, ATmega169 and + RS485 drivers in the AVR support. Special thanks to Tran Minh Hoang + for his contribution. + Added a new lwIP port for the STR71X target which uses one serial + interface for a PPP connection. This can be used for remote Modbus/TCP + devices in combination with a Modem (E.g. GPRS or Analog). + + Detailed notes: + - FEATURES (AVR): Integrated patches from Tran Minh Hoang to support the + ATmega8, ATmega16, ATmega32, ATmega169 controllers. + - FEATURES (AVR): Added support for RS485 drivers in the AVR code. The + example supports the DS76176. + - FEATURES (STR71XTCP): implemented function in STR71X/lwIP porting layer + to remove running tasks. + - FEATURES (STR71XTCP): added new thread creation function in STR71X/lwIP + porting layer which allows specifing the stack size. + - BUGS (STR71XTCP): pppOpen defined in ppp.c does not check the return + value of sys_thread_new. If task creation fails the system crashes. + - BUGS (STR71XTCP): pppMain must not return - Instead it should remove + its task from the scheduler. + +2006-08-30 (REL_9) Christian Walter : + Notes: Added lwIP port for the MCF5235 target. The lwIP part is + generic and therefore FreeModbus now works on any target with + lwIP support. + + Detailed notes: + - FEATURES: Incoperated MCF5235 FreeRTOS/lwIP port done by the + author in this project. + - FEATURES: Added lwIP port for FreeModbus + - FEATURES: Added demo application for FreeModbus and lwIP. + +2006-08-22 (REL_0_82) Christian Walter + Notes: Fixed bug with Modbus ASCII support + + Detailed notes: + - BUG: During the last upgrade an error was introduced in the + initialization code of Modbus ASCII and therefore ASCII + support was broken. The bug is fixed now and was tested with + the Win32 port. + +2006-08-22 (REL_0_81) Christian Walter + Notes: Added porting guide + + Detailed notes: + - OTHER: Added a new porting guide to the documentation. + - OTHER: Added a empty example for new ports to the project as a + starting point. + +2006-08-01 (REL_0_8) Christian Walter + Notes: Added Linux RTU/ASCII port. + + Detailed notes: + - FEATURES: Added a new Linux RTU/ASCII port. The port should work + on any Linux distribution and it should be possible to run it + on uCLinux. + +2006-06-26 (REL_0_7) Christian Walter + Notes: Changed the WIN32 serial port to better fit into the design. + + Detailed notes: + - OTHER: Design of the WIN32 serial port changed. The polling function + for the serial device are now called from the event loop. + - OTHER: Debugging uses the same interface as the WIN32/TCP port. + +2006-06-25 Christian Walter + + Notes: Initial work on a Modbus/TCP port is available. The port includes + an example for a Win32 port which uses the Winsock API. + + Detailed notes: + - FEATURES: added required functions to core protocol stack to support + a Modbus/TCP implementation. + - FEATURES: added a Win32 port for the Modbus/TCP core. The port is + currently limited to one concurrent client. + - OTHER: The implementation of eMBClose to shutdown the protocol stack + was changed to unify it with the new Modbus/TCP code. + - + +2006-06-18 Christian Walter + + Detailed notes: + - OTHER: while working on the Win32 port some line feeds got + wrong. Also some source files used tabs instead of spaces. + - OTHER: prototypes for xMBUtilSetBits and xMBUtilGetBits fixed. + usNBits should be ucNBits by convention. + +2006-06-17 Christian Walter + + Notes: Fixed various bugs with the Win32 port + + Detailed notes: + - FEATURES: implement shutdown functionality for protocol stack. + - FEATURES: protocol stack can be enabled and disabled during runtime. + - FEATURES: interface functions now do more error checking. For + example if eMBPool is called in an uninitialized state. + - FEATURES: extended Win32 demo application to use the new features. + - BUG: fixed bug in Win32 demo for ASCII mode. + +2006-06-16 Christian Walter + Notes: The new version includes a new port for the + Win32 platform + + Detailed notes: + - FEATURES: added Win32 platform + +2006-05-14 Christian Walter + Notes: The new version includes a new port for the + Freescale MCF5235 processor. + + Detailed notes: + - FEATURES: added new MCF5235 port. + - OTHER: fixed some missing code headers. + +2006-05-01 Christian Walter + Notes: This version removes the t1.5 timers from the Modbus RTU + implementation because no one actually uses it and the CPU + load is very high. T + In addition some documentation cleanups has been done and the + ARM demo has been updated. + + Detailed notes: + + - FEATURES: the t1.5 timeout has been removed. Therefore only + one timer is required. + - BUG: the ARM demo project missed some files in the project + workspace and did not compile cleanly + +2006-02-28 Christian Walter + Notes: This version includes support for two new command + (write multiple coils, read discrete input) + + Detailed notes: + - BUG: some function used the wrong data types + - FEATURES: added support for write multiple coils function. + - FEATURES: added support for read discrete input. + - OTHER: some code cleanups with lint tool. + +2006-02-28 Christian Walter + + Notes: The new version 0.31 adds support for reading and writing the + coil registers and add some bug fixes. + + Detailed notes: + - BUG: fixed bug with to small modbus requests being ignored. + - FEATURES: added support for write single coil function. + - FEATURES: added support for working with byte packed bit fields + to support coils and discrete inputs better. + - API: API for set slave id functions changed. + +2006-02-26 Christian Walter + + Notes: First public release which includes an ARM and AVR port. diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/LICENSE b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/LICENSE new file mode 100644 index 000000000..4e6120999 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2006 Christian Walter +Copyright (c) 2013-2019 Armink +All rights reserved. + +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. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/Makefile b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/Makefile new file mode 100644 index 000000000..22a2564f2 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/Makefile @@ -0,0 +1,3 @@ +SRC_DIR := modbus port samples + +include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/README.md b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/README.md new file mode 100644 index 000000000..b70fb1291 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/README.md @@ -0,0 +1,307 @@ +# Freemodbus + +[中文页](README_ZH.md) | English + +## Introduction + +This is the Freemodbus protocol stack ported by armink. Support the functions of the master and slave at the same time. + +FreeModbus is an open source Modbus protocol stack, but only the slave is open source, and the host source code is **charged**. At the same time, no better open source Modbus host protocol stack was found on the Internet, so this FreeModbus protocol stack supporting host mode was developed. This version of FreeModbus has been changed to V1.6 and features are as follows: + +- The newly added host source code is consistent with the style and interface of the original slave; +- Support the host and slave to run in the same protocol stack; +- Support real-time operating system and bare metal transplantation; +- Provide a variety of request modes for applications, users can choose blocking or non-blocking mode, custom timeout time, etc., to facilitate flexible calls at the application layer; +- Support all common Modbus methods. + +### File structure + +| Source File | Description | +| --------------------------------------------- | ----------------------------------------------- | +| FreeModbus\modbus\mb.c | Provides Modbus slave settings and polling related interfaces for the application layer | +| FreeModbus\modbus\mb_m.c | Provides Modbus host settings and polling related interfaces for the application layer | +| FreeModbus\modbus\ascii\mbascii.c | ASCII mode settings and state machine | +| FreeModbus\modbus\functions\mbfunccoils.c | Slave coil related functions | +| FreeModbus\modbus\functions\mbfunccoils_m.c | Host coil related functions | +| FreeModbus\modbus\functions\mbfuncdisc.c | Slave Discrete Input Related Functions | +| FreeModbus\modbus\functions\mbfuncdisc_m.c | Discrete input related functions of the host | +| FreeModbus\modbus\functions\mbfuncholding.c | Slave holding register related functions | +| FreeModbus\modbus\functions\mbfuncholding_m.c | Host holding register related functions | +| FreeModbus\modbus\functions\mbfuncinput.c | Slave input register related functions | +| FreeModbus\modbus\functions\mbfuncinput_m.c | Host input register related functions | +| FreeModbus\modbus\functions\mbfuncother.c | Other Modbus functions | +| FreeModbus\modbus\functions\mbutils.c | Some small tools that need to be used in the protocol stack | +| FreeModbus\modbus\rtu\mbcrc.c | CRC check function | +| FreeModbus\modbus\rtu\mbrtu.c | Slave RTU mode settings and state machine | +| FreeModbus\modbus\rtu\mbrtu_m.c | Host RTU mode settings and state machine | +| FreeModbus\modbus\tcp\mbtcp.c | TCP mode settings and state machine | +| FreeModbus\port\port.c | Implement hardware porting part of the interface | +| FreeModbus\port\portevent.c | Implement slave event porting interface | +| FreeModbus\port\portevent_m.c | Implement host event and error handling porting interface | +| FreeModbus\port\portserial.c | Slave port porting | +| FreeModbus\port\portserial_m.c | Host serial port porting | +| FreeModbus\port\porttimer.c | Slave timer porting | +| FreeModbus\port\porttimer_m.c | Host timer porting | +| FreeModbus\port\user_mb_app.c | Define slave data buffer, realize the callback interface of slave Modbus function | +| FreeModbus\port\user_mb_app_m.c | Define host data buffer, realize the callback interface of host Modbus function | +| FreeModbus\samples\sample_mb_master.c | Sample code for host use | +| FreeModbus\samples\sample_mb_slave.c | Slave use sample code | +| FreeModbus\samples\README.md | Sample code description document | + +> Note: All files with the _m suffix are the files that must be used in the master mode. If the slave mode is used, these files are not required. + +### License + +The Freemodbus software package complies with the BSD license, see the `LICENSE` file for details. + +### Dependence + +- RT_Thread UART device + +## method of obtaining + +To use the Freemodbus software package, you need to select it in the RT-Thread package manager. The specific path is as follows: + +``` +RT-Thread online packages + IoT-internet of things ---> + [*] FreeModbus: Modbus master and slave stack ---> + [*] Master mode ---> + [*] Slave mode ---> +``` + +Finally, let RT-Thread's package manager automatically update, or use the `pkgs --update` command to update the package to the BSP. + +## Instructions + +### Data buffer + +The location defined by the data buffer is at the top of the `FreeModbus\port\user_mb_app_m.c` file, with a total of **4** data types. By default, FreeModbus slaves use **one-dimensional array** as the data structure of the buffer area. The host can store the data of all slaves in the network, so the host uses **two-dimensional array** to store all slave node data. The column number of the two-dimensional array represents the register, coil and discrete address, and the row number represents the slave node ID, but it needs to be reduced by one. For example, `usMRegHoldBuf[2][1]` means the slave ID is 3, and the register address is maintained The slave data is 1. + +### Modbus data processing callback interface + +Modbus has 4 different data types in total, and all Modbus functions operate around these data types. Since different user data buffer structures may be different, the corresponding Modbus data processing methods are also different, so users need to customize the operations corresponding to each data type according to their own data buffer structure. All Modbus data processing callback interfaces are as follows: + +| Interface | Function description | +| ---------------------- | ------------------ | +| eMBMasterRegInputCB | Input register callback interface | +| eMBMasterRegHoldingCB | Holding register callback interface | +| eMBMasterRegCoilsCB | Coil callback interface | +| eMBMasterRegDiscreteCB | Discrete input callback interface | + +> For the data buffer structure in the form of an array, the source code has already been transplanted and can be used directly. + +### Initial configuration process + +All configuration parameters of this protocol stack are located in `FreeModbus\modbus\include\mbconfig.h`, currently the protocol stack supports two modes of master and slave, and supports **both modes to be turned on at the same time**. The slave supports Modbus RTU, Modbus ASCII and Modbus TCP 3 modes, and the master now only supports the commonly used **Modbus RTU** mode. In the process of using the master, the user needs to configure the broadcast conversion delay time, command response timeout time and the number of slaves. It should be noted that the current protocol stack only supports continuous slave addresses, and the starting address starts from 1**. + +### Normal use process + +1. Call the `eMBMasterInit` method to initialize the Modbus host protocol stack, and some hardware related to the host is initialized at this time +2. Call the `eMBMasterEnable` method to start the Modbus master +3. By calling the `eMBMasterPoll` method in thread or timer polling, the polling cycle determines the response time of the command. +4. Call the host to request the API method, set a certain request timeout period, and will not return until the method has a result. If the method is executed successfully and the command is a read command, you can obtain the latest slave data by viewing the data buffer of the Modbus master. + +> For specific usage, please refer to the sample code in the `/samples` directory. Debugging the Modbus master-slave program can be debugged with Modbus Poll and Modbus slave software on the PC. + +### Exception handling process + +Exception handling mainly occurs during the normal use of the host. All the error codes of the host request API have been described at the beginning of Chapter 3. For these error codes, users need to complete different actions according to their own product features. It is recommended that users encapsulate and implement the retransmission mechanism of the host request method. This implementation is more flexible. Generally, retransmission is required when receiving frame data errors and command response timeout error codes. The number of retransmissions is automatically increased by one. If the set value is exceeded, the slave is considered to be offline, and all subsequent commands sent to this slave are intercepted in advance; if the second retransmission command response is successful, **automatically cleared** the slave retransmits frequency. All the above functions can be realized by using the host request method or using the callback interface in `FreeModbus\port\portevent_m.c`, and users can choose flexibly according to their needs. + +## API detailed + +The Modbus master is very different from the slave in the use process. The slave needs to passively wait for the request of the master, while the master actively sends out the request and receives and processes the response from the slave. When the host sends a broadcast request, the slave does not need to return a response, so the broadcast request is suitable for the master's write slave data command, not suitable for the read slave data command. The return value format of all methods in the host request API is the same, and the meaning of the return value is as follows. + +| Return value | Description | +| ------------------ | ------------------------------------------- | +| MB_MRE_NO_ERR | Normal, no error | +| MB_MRE_NO_REG | Register, coil or discrete input address error | +| MB_MRE_ILL_ARG | Incorrect input parameter format | +| MB_MRE_REV_DATA | Receive data error | +| MB_MRE_TIMEDOUT | Response timed out. The host did not receive the response from the slave within the set time. | +| MB_MRE_MASTER_BUSY | The host is busy. The request was not sent within the set time. | +| MB_MRE_EXE_FUN | After the host receives the response, an error occurs when executing the Modbus method (function). | + +> All host request methods are **thread safe** and **blocking mode**. During use, as long as the host resource is not obtained within the set timeout period, it will return that the host is busy; if the host resource is obtained within the set timeout period, it must wait for the request result before returning. + +### Write a single holding register + +Write data to a holding register of the slave + +``` +eMBMasterReqErrCode eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, + USHORT usRegAddr, + USHORT usRegData, + LONG lTimeOut ); +``` + +| Parameters | Description | +| --------- | ----------------------------------------------------------- | +| ucSndAddr | Requested slave address, 0 means broadcast. | +| usRegAddr | Write register address | +| usRegData | Write register data | +| lTimeOut | Request timeout time. To support permanent waiting, just use the permanent waiting parameter of the operating system. | + +### Write multiple holding registers + +Write data to multiple holding registers of the slave. + +``` +eMBMasterReqErrCode eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr, + USHORT usRegAddr, + USHORT usNRegs, + USHORT * pusDataBuffer, + LONG lTimeOut) +``` + +| Parameters | Description | +| ------------- | ----------------------------------------------------------- | +| ucSndAddr | Requested slave address, 0 means broadcast. | +| usRegAddr | Start address of write register | +| usNRegs | Total number of write registers | +| pusDataBuffer | Write register data | +| lTimeOut | Request timeout time. To support permanent waiting, just use the permanent waiting parameter of the operating system. | + +### Read multiple holding registers + +Read data in multiple holding registers + +``` +eMBMasterReqErrCode eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, + USHORT usRegAddr, + USHORT usNRegs, + LONG lTimeOut ); +``` + +| Parameters | Description | +| --------- | ----------------------------------------------------------- | +| ucSndAddr | Requested slave address, 0 means broadcast. | +| usRegAddr | Read register address | +| usRegData | Number of read registers | +| lTimeOut | Request timeout time. To support permanent waiting, just use the permanent waiting parameter of the operating system. | + +### Read and write multiple holding registers + +Read multiple registers first, and then write multiple registers. + +``` +eMBMasterReqErrCode eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr, + USHORT usReadRegAddr, + USHORT usNReadRegs, + USHORT * pusDataBuffer, + USHORT usWriteRegAddr, + USHORT usNWriteRegs, + LONG lTimeOut) +``` + +| Parameters | Description | +| -------------- | ----------------------------------------------------------- | +| ucSndAddr | Requested slave address, 0 means broadcast. | +| usReadRegAddr | Read register address | +| usNReadRegs | Number of read registers | +| pusDataBuffer | Write register data | +| usWriteRegAddr | Write register address | +| usNWriteRegs | Number of write registers | +| lTimeOut | Request timeout time. To support permanent waiting, just use the permanent waiting parameter of the operating system. | + +### Read multiple input registers + +Read data in multiple input registers + +``` +eMBMasterReqErrCode eMBMasterReqReadInputRegister( UCHAR ucSndAddr, + USHORT usRegAddr, + USHORT usNRegs, + LONG lTimeOut ); +``` + +| Parameters | Description | +| --------- | ----------------------------------------------------------- | +| ucSndAddr | Requested slave address, 0 means broadcast. | +| usRegAddr | Read register address | +| usRegData | Number of read registers | +| lTimeOut | Request timeout time. To support permanent waiting, just use the permanent waiting parameter of the operating system. | + +### Write a single coil + +Write data to a coil of the slave + +``` +eMBMasterReqErrCode eMBMasterReqWriteCoil( UCHAR ucSndAddr, + USHORT usCoilAddr, + USHORT usCoilData, + LONG lTimeOut) +``` + +| Parameters | Description | +| ---------- | ----------------------------------------------------------- | +| ucSndAddr | Requested slave address, 0 means broadcast. | +| usCoilAddr | Write the address of the coil | +| usCoilData | Number of write coils | +| lTimeOut | Request timeout time. To support permanent waiting, just use the permanent waiting parameter of the operating system. | + +### Write multiple coils + +Write data to multiple coils of the slave. + +``` +eMBMasterReqErrCode eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr, + USHORT usCoilAddr, + USHORT usNCoils, + UCHAR * pucDataBuffer, + LONG lTimeOut) +``` + +| Parameters | Description | +| ------------- | ----------------------------------------------------------- | +| ucSndAddr | Requested slave address, 0 means broadcast. | +| usCoilAddr | Write the start address of the coil | +| usNCoils | Total number of write coils | +| pucDataBuffer | Write coil data | +| lTimeOut | Request timeout time. To support permanent waiting, just use the permanent waiting parameter of the operating system. | + +### Read multiple coils + +Read data from multiple coils + +``` +eMBMasterReqErrCode eMBMasterReqReadCoils( UCHAR ucSndAddr, + USHORT usCoilAddr, + USHORT usNCoils, + LONG lTimeOut) +``` + +| Parameters | Description | +| ---------- | ------------------------------------------------------------ | +| ucSndAddr | Requested slave address, 0 means broadcast. | +| usCoilAddr | Read the address of the coil | +| usNCoils | Number of reading coils | +| lTimeOut | Request timeout time. To support permanent waiting, just use the permanent waiting parameter of the operating system. | + +### Read multiple discrete inputs + +Read data from multiple discrete inputs + +``` +eMBMasterReqErrCode eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, + USHORT usDiscreteAddr, + USHORT usNDiscreteIn, + LONG lTimeOut) +``` + +| Parameters | Description | +| -------------- | ------------------------------------------------------------ | +| ucSndAddr | Requested slave address, 0 means broadcast. | +| usDiscreteAddr | Read the address of discrete input | +| usNDiscreteIn | Read the number of discrete inputs | +| lTimeOut | Request timeout time. To support permanent waiting, just use the permanent waiting parameter of the operating system. | + +## Precautions + +- The slave supports Modbus RTU, Modbus ASCII and Modbus TCP 3 modes. The master now only supports the commonly used **Modbus RTU** mode. +- Currently the protocol stack only supports **continuous slave address**, and the starting address **starts from 1**. + +## Contact information + +- Maintenance: RT-Thread development team and community developers +- Homepage: diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/README_ZH.md b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/README_ZH.md new file mode 100644 index 000000000..ff40b6b12 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/README_ZH.md @@ -0,0 +1,308 @@ +# Freemodbus + +中文页 | [English](README.md) + +## 简介 + +这是 armink 大神移植的 Freemodbus 协议栈。同时支持主机和从机的功能。 + +FreeModbus 是一款开源的 Modbus 协议栈,但是只有从机开源,主机源码是需要**收费**的。同时网上也没有发现比较好的开源的 Modbus 主机协议栈,所以才开发这款支持主机模式的 FreeModbus 协议栈。本版 FreeModbus版本号更改为V1.6,特性如下: + +- 新增加的主机源码与原有从机的风格及接口保持一致; +- 支持主机与从机在同一协议栈运行; +- 支持实时操作系统及裸机移植; +- 为应用提供多种请求模式,用户可以选择阻塞还是非阻塞模式,自定义超时时间等,方便应用层灵活调用; +- 支持所有常用的Modbus方法。 + +### 文件结构 + +| 源文件 | 描述 | +| --------------------------------------------- | ------------------------------------------------ | +| FreeModbus\modbus\mb.c | 给应用层提供Modbus从机设置及轮询相关接口 | +| FreeModbus\modbus\mb_m.c | 给应用层提供Modbus主机设置及轮询相关接口 | +| FreeModbus\modbus\ascii\mbascii.c | ASCII模式设置及其状态机 | +| FreeModbus\modbus\functions\mbfunccoils.c | 从机线圈相关功能 | +| FreeModbus\modbus\functions\mbfunccoils_m.c | 主机线圈相关功能 | +| FreeModbus\modbus\functions\mbfuncdisc.c | 从机离散输入相关功能 | +| FreeModbus\modbus\functions\mbfuncdisc_m.c | 主机离散输入相关功能 | +| FreeModbus\modbus\functions\mbfuncholding.c | 从机保持寄存器相关功能 | +| FreeModbus\modbus\functions\mbfuncholding_m.c | 主机保持寄存器相关功能 | +| FreeModbus\modbus\functions\mbfuncinput.c | 从机输入寄存器相关功能 | +| FreeModbus\modbus\functions\mbfuncinput_m.c | 主机输入寄存器相关功能 | +| FreeModbus\modbus\functions\mbfuncother.c | 其余Modbus功能 | +| FreeModbus\modbus\functions\mbutils.c | 一些协议栈中需要用到的小工具 | +| FreeModbus\modbus\rtu\mbcrc.c | CRC校验功能 | +| FreeModbus\modbus\rtu\mbrtu.c | 从机RTU模式设置及其状态机 | +| FreeModbus\modbus\rtu\mbrtu_m.c | 主机RTU模式设置及其状态机 | +| FreeModbus\modbus\tcp\mbtcp.c | TCP模式设置及其状态机 | +| FreeModbus\port\port.c | 实现硬件移植部分接口 | +| FreeModbus\port\portevent.c | 实现从机事件移植接口 | +| FreeModbus\port\portevent_m.c | 实现主机事件及错误处理移植接口 | +| FreeModbus\port\portserial.c | 从机串口移植 | +| FreeModbus\port\portserial_m.c | 主机串口移植 | +| FreeModbus\port\porttimer.c | 从机定时器移植 | +| FreeModbus\port\porttimer_m.c | 主机定时器移植 | +| FreeModbus\port\user_mb_app.c | 定义从机数据缓冲区,实现从机Modbus功能的回调接口 | +| FreeModbus\port\user_mb_app_m.c | 定义主机数据缓冲区,实现主机Modbus功能的回调接口 | +| FreeModbus\samples\sample_mb_master.c | 主机使用示例代码 | +| FreeModbus\samples\sample_mb_slave.c | 从机使用示例代码 | +| FreeModbus\samples\README.md | 示例代码说明文档 | + +> 注:所有带_m后缀的文件为主机模式下必须使用的文件,如使用从机模式则无需这些文件。 + +### 许可证 + +Freemodbus 软件包遵循 BSD 许可,详见 `LICENSE` 文件。 + +### 依赖 + +- RT_Thread UART 设备 +- XiUOS UART 设备 + +## 获取方式 + +使用 Freemodbus 软件包 需要在 RT-Thread 的包管理器中选择它,具体路径如下: + +``` +RT-Thread online packages + IoT - internet of things ---> + [*] FreeModbus: Modbus master and slave stack ---> + [*] Master mode ---> + [*] Slave mode ---> +``` + +最后让 RT-Thread 的包管理器自动更新,或者使用 `pkgs --update` 命令更新包到 BSP 中。 + +## 使用方法 + +### 数据缓冲区 + +数据缓冲区定义的位置位于 `FreeModbus\port\user_mb_app_m.c` 文件顶部,共计 **4种** 数据类型。 FreeModbus从机默认使用 **一维数组** 作为缓存区数据结构,主机可以存储所有网内从机的数据,所以主机采用 **二维数组** 对所有从机节点数据进行存储。二维数组的列号代表寄存器、线圈及离散量地址,行号代表从机节点ID,但需要做减一处理,例如`usMRegHoldBuf[2][1]`代表从机ID为 3,保持寄存器地址为 1 的从机数据。 + +### Modbus 数据处理回调接口 + +Modbus 一共有4种不同的数据类型,所有的 Modbus 功能都围绕这些数据类型进行操作。由于不同的用户数据缓冲区结构可能有所不同,那么对应的 Modbus 数据处理方式也就存在差异,所以用户需要把每种数据类型对应的操作,按照自己的数据缓冲区结构进行定制实现。 所有的 Modbus 数据处理回调接口如下: + +| 接口 | 功能描述 | +| ---------------------- | ------------------ | +| eMBMasterRegInputCB | 输入寄存器回调接口 | +| eMBMasterRegHoldingCB | 保持寄存器回调接口 | +| eMBMasterRegCoilsCB | 线圈回调接口 | +| eMBMasterRegDiscreteCB | 离散输入回调接口 | + +> 对于数组形式的数据缓冲区结构,源码中已经做好了移植,直接使用即可。 + +### 初始化配置流程 + +本协议栈所有配置参数都位于`FreeModbus\modbus\include\mbconfig.h`,目前协议栈支持主机及从机两种模式,并且支持**两种模式同时开启**。从机支持Modbus RTU 、Modbus ASCII 及Modbus TCP 3种模式,主机现在只支持常用的**Modbus RTU**模式。在使用主机的过程中,用户需要对广播的转换延时时间、命令响应超时时间及从机数量做以配置。需要注意的是,目前协议栈只支持**从机地址连续**,并且起始地址**从1开始**。 + +### 正常使用流程 + +1. 调用`eMBMasterInit`方法初始化Modbus主机协议栈,主机涉及到的一些硬件就在这个时候做了初始化 +2. 调用`eMBMasterEnable`方法启动Modbus主机 +3. 通过在线程或者定时器轮询调用`eMBMasterPoll`方法,轮询周期决定了命令的响应时间。 +4. 调用主机请求API方法,设定一定的请求超时时间,直到方法有结果后才会返回。如果方法执行成功并且命令是读命令,可以通过查看Modbus主机的数据缓冲区,获取最新从机数据。 + +> 具体的使用方法,可以参考 `/samples` 目录下的示例代码。调试 Modbus 的主从机程序可以在 PC 上使用 Modbus Poll 和 Modbus slave 软件配合调试。 + +### 异常处理流程 + +异常处理主要出现在主机正常使用过程中,所有的主机请求API的错误码都在第三章开头已经做以描述,针对的这些错误码,用户需要根据自己的产品特征去完成不同的动作。建议用户自己封装实现主机请求方法的重发机制,这样实现方式比较灵活,一般是在接收到帧数据出错及命令响应超时的错误码时需要重发,重发次数自动加一,如果重发次数超过设定值则认为从机掉线,以后所有只要是发给这个从机命令都被提前拦截掉;如果第二次重发命令响应成功,则**自动清零**该从机重发次数。 上述所有功能可以利用主机请求方法或者使用`FreeModbus\port\portevent_m.c`中的回调接口来实现,用户可以根据自己的需求灵活选择。 + +## API 详解 + +Modbus 主机使用过程中与从机有很大不同,从机是需要被动等待主机请求,而主机则是主动发出请求,并接收处理从机响应。在主机发送广播请求的时候,从机不需要返回响应,所以广播请求适合主机的写从机数据命令,不适合读从机数据命令。 主机请求API中的所有方法的返回值格式都相同,返回值意义如下。 + +| 返回值 | 描述 | +| ------------------ | -------------------------------------------- | +| MB_MRE_NO_ERR | 正常,没错误 | +| MB_MRE_NO_REG | 寄存器、线圈或离散输入地址出错 | +| MB_MRE_ILL_ARG | 入参格式有误 | +| MB_MRE_REV_DATA | 接收数据出错 | +| MB_MRE_TIMEDOUT | 响应超时。主机在设定的时间内未收到从机响应。 | +| MB_MRE_MASTER_BUSY | 主机忙。在设定的时间内,请求没有被发送。 | +| MB_MRE_EXE_FUN | 主机收到响应后,执行Modbus方法(功能)出错。 | + +> 所有的主机请求方法都是 **线程安全** 的也是 **阻塞模式** 的。在使用过程中,只要在设定的超时时间内没有得到主机资源,就会返回主机忙;如果在设定的超时时间内得到主机资源,那么必须等待得到请求结果后才会返回。 + +### 写单个保持寄存器 + +往从机某个保持寄存器中写入数据 + +``` +eMBMasterReqErrCode eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, + USHORT usRegAddr, + USHORT usRegData, + LONG lTimeOut ); +``` + +| 参数 | 描述 | +| --------- | ------------------------------------------------------------ | +| ucSndAddr | 请求的从机地址,0代表广播。 | +| usRegAddr | 写寄存器的地址 | +| usRegData | 写寄存器的数据 | +| lTimeOut | 请求超时时间。支持永久等待,使用操作系统的永久等待参数即可。 | + +### 写多个保持寄存器 + +往从机多个保持寄存器中写入数据。 + +``` +eMBMasterReqErrCode eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr, + USHORT usRegAddr, + USHORT usNRegs, + USHORT * pusDataBuffer, + LONG lTimeOut ) +``` + +| 参数 | 描述 | +| ------------- | ------------------------------------------------------------ | +| ucSndAddr | 请求的从机地址,0代表广播。 | +| usRegAddr | 写寄存器的起始地址 | +| usNRegs | 写寄存器的总数 | +| pusDataBuffer | 写寄存器的数据 | +| lTimeOut | 请求超时时间。支持永久等待,使用操作系统的永久等待参数即可。 | + +### 读多个保持寄存器 + +读取多个保持寄存器中的数据 + +``` +eMBMasterReqErrCode eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, + USHORT usRegAddr, + USHORT usNRegs, + LONG lTimeOut ); +``` + +| 参数 | 描述 | +| --------- | ------------------------------------------------------------ | +| ucSndAddr | 请求的从机地址,0代表广播。 | +| usRegAddr | 读寄存器的地址 | +| usRegData | 读寄存器的数量 | +| lTimeOut | 请求超时时间。支持永久等待,使用操作系统的永久等待参数即可。 | + +### 读写多个保持寄存器 + +先读多个寄存器,然后再写多个寄存器。 + +``` +eMBMasterReqErrCode eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr, + USHORT usReadRegAddr, + USHORT usNReadRegs, + USHORT * pusDataBuffer, + USHORT usWriteRegAddr, + USHORT usNWriteRegs, + LONG lTimeOut ) +``` + +| 参数 | 描述 | +| -------------- | ------------------------------------------------------------ | +| ucSndAddr | 请求的从机地址,0代表广播。 | +| usReadRegAddr | 读寄存器的地址 | +| usNReadRegs | 读寄存器的数量 | +| pusDataBuffer | 写寄存器的数据 | +| usWriteRegAddr | 写寄存器的地址 | +| usNWriteRegs | 写寄存器的数量 | +| lTimeOut | 请求超时时间。支持永久等待,使用操作系统的永久等待参数即可。 | + +### 读多个输入寄存器 + +读取多个输入寄存器中的数据 + +``` +eMBMasterReqErrCode eMBMasterReqReadInputRegister( UCHAR ucSndAddr, + USHORT usRegAddr, + USHORT usNRegs, + LONG lTimeOut ); +``` + +| 参数 | 描述 | +| --------- | ------------------------------------------------------------ | +| ucSndAddr | 请求的从机地址,0代表广播。 | +| usRegAddr | 读寄存器的地址 | +| usRegData | 读寄存器的数量 | +| lTimeOut | 请求超时时间。支持永久等待,使用操作系统的永久等待参数即可。 | + +### 写单个线圈 + +往从机某个线圈中写入数据 + +``` +eMBMasterReqErrCode eMBMasterReqWriteCoil( UCHAR ucSndAddr, + USHORT usCoilAddr, + USHORT usCoilData, + LONG lTimeOut ) +``` + +| 参数 | 描述 | +| ---------- | ------------------------------------------------------------ | +| ucSndAddr | 请求的从机地址,0代表广播。 | +| usCoilAddr | 写线圈的地址 | +| usCoilData | 写线圈的数量 | +| lTimeOut | 请求超时时间。支持永久等待,使用操作系统的永久等待参数即可。 | + +### 写多个线圈 + +往从机多个线圈中写入数据。 + +``` +eMBMasterReqErrCode eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr, + USHORT usCoilAddr, + USHORT usNCoils, + UCHAR * pucDataBuffer, + LONG lTimeOut) +``` + +| 参数 | 描述 | +| ------------- | ------------------------------------------------------------ | +| ucSndAddr | 请求的从机地址,0代表广播。 | +| usCoilAddr | 写线圈的起始地址 | +| usNCoils | 写线圈的总数 | +| pucDataBuffer | 写线圈的数据 | +| lTimeOut | 请求超时时间。支持永久等待,使用操作系统的永久等待参数即可。 | + +### 读多个线圈 + +读取多个线圈中的数据 + +``` +eMBMasterReqErrCode eMBMasterReqReadCoils( UCHAR ucSndAddr, + USHORT usCoilAddr, + USHORT usNCoils , + LONG lTimeOut ) +``` + +| 参数 | 描述 | +| ---------- | ------------------------------------------------------------ | +| ucSndAddr | 请求的从机地址,0代表广播。 | +| usCoilAddr | 读线圈的地址 | +| usNCoils | 读线圈的数量 | +| lTimeOut | 请求超时时间。支持永久等待,使用操作系统的永久等待参数即可。 | + +### 读多个离散输入 + +读取多个离散输入中的数据 + +``` +eMBMasterReqErrCode eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, + USHORT usDiscreteAddr, + USHORT usNDiscreteIn, + LONG lTimeOut ) +``` + +| 参数 | 描述 | +| -------------- | ------------------------------------------------------------ | +| ucSndAddr | 请求的从机地址,0代表广播。 | +| usDiscreteAddr | 读离散输入的地址 | +| usNDiscreteIn | 读离散输入的数量 | +| lTimeOut | 请求超时时间。支持永久等待,使用操作系统的永久等待参数即可。 | + +## 注意事项 + +- 从机支持Modbus RTU 、Modbus ASCII 及Modbus TCP 3种模式,主机现在只支持常用的**Modbus RTU**模式。 +- 目前协议栈只支持**从机地址连续**,并且起始地址**从1开始**。 + +## 联系方式 + +- 维护:RT-Thread 开发团队及社区开发者 +- 主页: diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/SConscript b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/SConscript new file mode 100644 index 000000000..6514cf215 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/SConscript @@ -0,0 +1,69 @@ +Import('RTT_ROOT') +from building import * + +src = Split(""" +modbus/functions/mbfuncdiag.c +modbus/functions/mbutils.c +modbus/functions/mbfuncother.c +modbus/rtu/mbcrc.c +port/port.c +""") + +master_rtu_src = Split(""" +modbus/functions/mbfunccoils_m.c +modbus/functions/mbfuncdisc_m.c +modbus/functions/mbfuncholding_m.c +modbus/functions/mbfuncinput_m.c +modbus/rtu/mbrtu_m.c +modbus/mb_m.c +port/portevent_m.c +port/portserial_m.c +port/porttimer_m.c +port/user_mb_app_m.c +""") + +slave_src = Split(""" +modbus/functions/mbfunccoils.c +modbus/functions/mbfuncdisc.c +modbus/functions/mbfuncholding.c +modbus/functions/mbfuncinput.c +modbus/mb.c +port/portevent.c +port/portserial.c +port/porttcp.c +port/porttimer.c +port/user_mb_app.c +""") + +# The set of source files associated with this SConscript file. +path = [GetCurrentDir() + '/modbus/include', + GetCurrentDir() + '/modbus/rtu', + GetCurrentDir() + '/modbus/ascii', + GetCurrentDir() + '/modbus/tcp', + GetCurrentDir() + '/port'] + +if GetDepend(['PKG_MODBUS_MASTER_RTU']): + src += master_rtu_src + +if GetDepend(['PKG_MODBUS_SLAVE']): + src += slave_src + +if GetDepend(['PKG_MODBUS_SLAVE_RTU']): + src += ['modbus/rtu/mbrtu.c'] + +if GetDepend(['PKG_MODBUS_SLAVE_ASCII']): + src += ['modbus/ascii/mbascii.c'] + src += ['modbus/rtu/mbrtu.c'] + +if GetDepend(['PKG_MODBUS_SLAVE_TCP']): + src += ['modbus/tcp/mbtcp.c'] + +if GetDepend(['PKG_MODBUS_MASTER_SAMPLE']): + src += ['samples/sample_mb_master.c'] + +if GetDepend(['PKG_MODBUS_SLAVE_SAMPLE']): + src += ['samples/sample_mb_slave.c'] + +group = DefineGroup('FreeModbus', src, depend = ['PKG_USING_FREEMODBUS'], CPPPATH = path) + +Return('group') diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/bsd.txt b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/bsd.txt new file mode 100644 index 000000000..4e6120999 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/bsd.txt @@ -0,0 +1,26 @@ +Copyright (c) 2006 Christian Walter +Copyright (c) 2013-2019 Armink +All rights reserved. + +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. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/Makefile b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/Makefile new file mode 100644 index 000000000..3b37c0f3b --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/Makefile @@ -0,0 +1,25 @@ +SRC_DIR := functions + +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_RTU),y) + SRC_DIR += rtu + +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_RTU_MASTER),y) + SRC_FILES += mb_m.c +endif + +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_RTU_SLAVE),y) + SRC_FILES += mb.c +endif + +endif + +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_TCP),y) + SRC_DIR += tcp + +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_TCP_SLAVE),y) + SRC_FILES += mb.c +endif + +endif + +include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/ascii/mbascii.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/ascii/mbascii.c similarity index 99% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/ascii/mbascii.c rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/ascii/mbascii.c index b29f2bcc0..5ed4a2690 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/ascii/mbascii.c +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/ascii/mbascii.c @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,6 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mbascii.c,v 1.15 2007/02/18 23:46:48 wolti Exp $ */ /* ----------------------- System includes ----------------------------------*/ @@ -43,7 +44,7 @@ #include "mbcrc.h" #include "mbport.h" -#if MB_ASCII_ENABLED > 0 +#if MB_SLAVE_ASCII_ENABLED > 0 /* ----------------------- Defines ------------------------------------------*/ #define MB_ASCII_DEFAULT_CR '\r' /*!< Default CR character for Modbus ASCII. */ @@ -108,7 +109,7 @@ eMBASCIIInit( UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eP { eMBErrorCode eStatus = MB_ENOERR; ( void )ucSlaveAddress; - + ENTER_CRITICAL_SECTION( ); ucMBLFCharacter = MB_ASCII_DEFAULT_LF; diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/ascii/mbascii.h b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/ascii/mbascii.h similarity index 96% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/ascii/mbascii.h rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/ascii/mbascii.h index 20975e29b..d4607a926 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/ascii/mbascii.h +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/ascii/mbascii.h @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,6 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mbascii.h,v 1.8 2006/12/07 22:10:34 wolti Exp $ */ #ifndef _MB_ASCII_H @@ -34,7 +35,7 @@ PR_BEGIN_EXTERN_C #endif -#if MB_ASCII_ENABLED > 0 +#if MB_SLAVE_ASCII_ENABLED > 0 eMBErrorCode eMBASCIIInit( UCHAR slaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ); void eMBASCIIStart( void ); diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/Makefile b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/Makefile new file mode 100644 index 000000000..d319314f8 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/Makefile @@ -0,0 +1,15 @@ +SRC_FILES := mbfuncother.c mbutils.c mbfuncdiag.c + +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_RTU_MASTER),y) + SRC_FILES += mbfunccoils_m.c mbfuncdisc_m.c mbfuncholding_m.c mbfuncinput_m.c +endif + +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_RTU_SLAVE),y) + SRC_FILES += mbfunccoils.c mbfuncdisc.c mbfuncholding.c mbfuncinput.c +endif + +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_TCP_SLAVE),y) + SRC_FILES += mbfunccoils.c mbfuncdisc.c mbfuncholding.c mbfuncinput.c +endif + +include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbfunccoils.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfunccoils.c similarity index 98% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbfunccoils.c rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfunccoils.c index eb37ed6c0..6aac66624 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbfunccoils.c +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfunccoils.c @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,6 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mbfunccoils.c,v 1.8 2007/02/18 23:47:16 wolti Exp $ */ /* ----------------------- System includes ----------------------------------*/ @@ -85,7 +86,7 @@ eMBFuncReadCoils( UCHAR * pucFrame, USHORT * usLen ) usCoilCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF + 1] ); /* Check if the number of registers to read is valid. If not - * return Modbus illegal data value exception. + * return Modbus illegal data value exception. */ if( ( usCoilCount >= 1 ) && ( usCoilCount < MB_PDU_FUNC_READ_COILCNT_MAX ) ) @@ -123,7 +124,7 @@ eMBFuncReadCoils( UCHAR * pucFrame, USHORT * usLen ) else { /* The response contains the function code, the starting address - * and the quantity of registers. We reuse the old values in the + * and the quantity of registers. We reuse the old values in the * buffer because they are still valid. */ *usLen += ucNBytes;; } @@ -141,6 +142,7 @@ eMBFuncReadCoils( UCHAR * pucFrame, USHORT * usLen ) } return eStatus; } +#endif #if MB_FUNC_WRITE_COIL_ENABLED > 0 eMBException @@ -245,7 +247,7 @@ eMBFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen ) else { /* The response contains the function code, the starting address - * and the quantity of registers. We reuse the old values in the + * and the quantity of registers. We reuse the old values in the * buffer because they are still valid. */ *usLen = MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF; } @@ -265,5 +267,3 @@ eMBFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen ) } #endif - -#endif diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfunccoils_m.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfunccoils_m.c new file mode 100644 index 000000000..4366b4923 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfunccoils_m.c @@ -0,0 +1,390 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (C) 2013 Armink + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbfunccoils_m.c,v 1.60 2013/10/12 15:10:12 Armink Add Master Functions + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mb_m.h" +#include "mbframe.h" +#include "mbproto.h" +#include "mbconfig.h" + +/* ----------------------- Defines ------------------------------------------*/ +#define MB_PDU_REQ_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_REQ_READ_COILCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_REQ_READ_SIZE ( 4 ) +#define MB_PDU_FUNC_READ_COILCNT_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_FUNC_READ_VALUES_OFF ( MB_PDU_DATA_OFF + 1 ) +#define MB_PDU_FUNC_READ_SIZE_MIN ( 1 ) + +#define MB_PDU_REQ_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF ) +#define MB_PDU_REQ_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_REQ_WRITE_SIZE ( 4 ) +#define MB_PDU_FUNC_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF ) +#define MB_PDU_FUNC_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_WRITE_SIZE ( 4 ) + +#define MB_PDU_REQ_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF ) +#define MB_PDU_REQ_WRITE_MUL_COILCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF ( MB_PDU_DATA_OFF + 4 ) +#define MB_PDU_REQ_WRITE_MUL_VALUES_OFF ( MB_PDU_DATA_OFF + 5 ) +#define MB_PDU_REQ_WRITE_MUL_SIZE_MIN ( 5 ) +#define MB_PDU_REQ_WRITE_MUL_COILCNT_MAX ( 0x07B0 ) +#define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF ) +#define MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_WRITE_MUL_SIZE ( 5 ) + +/* ----------------------- Static functions ---------------------------------*/ +eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); + +/* ----------------------- Start implementation -----------------------------*/ +#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 +#if MB_FUNC_READ_COILS_ENABLED > 0 + +/** + * This function will request read coil. + * + * @param ucSndAddr salve address + * @param usCoilAddr coil start address + * @param usNCoils coil total number + * @param lTimeOut timeout (-1 will waiting forever) + * + * @return error code + */ +eMBMasterReqErrCode +eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils ,LONG lTimeOut ) +{ + UCHAR *ucMBFrame; + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + + if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; + else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; + else + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + vMBMasterSetDestAddress(ucSndAddr); + ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_COILS; + ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usCoilAddr >> 8; + ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usCoilAddr; + ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF ] = usNCoils >> 8; + ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF + 1] = usNCoils; + vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE ); + ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); + eErrStatus = eMBMasterWaitRequestFinish( ); + + } + return eErrStatus; +} + +eMBException +eMBMasterFuncReadCoils( UCHAR * pucFrame, USHORT * usLen ) +{ + UCHAR *ucMBFrame; + USHORT usRegAddress; + USHORT usCoilCount; + UCHAR ucByteCount; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + /* If this request is broadcast, and it's read mode. This request don't need execute. */ + if ( xMBMasterRequestIsBroadcast() ) + { + eStatus = MB_EX_NONE; + } + else if ( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN ) + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] ); + usRegAddress++; + + usCoilCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF] << 8 ); + usCoilCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF + 1] ); + + /* Test if the quantity of coils is a multiple of 8. If not last + * byte is only partially field with unused coils set to zero. */ + if( ( usCoilCount & 0x0007 ) != 0 ) + { + ucByteCount = ( UCHAR )( usCoilCount / 8 + 1 ); + } + else + { + ucByteCount = ( UCHAR )( usCoilCount / 8 ); + } + + /* Check if the number of registers to read is valid. If not + * return Modbus illegal data value exception. + */ + if( ( usCoilCount >= 1 ) && + ( ucByteCount == pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF] ) ) + { + /* Make callback to fill the buffer. */ + eRegStatus = eMBMasterRegCoilsCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usCoilCount, MB_REG_READ ); + + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid read coil register request because the length + * is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} +#endif + +#if MB_FUNC_WRITE_COIL_ENABLED > 0 + +/** + * This function will request write one coil. + * + * @param ucSndAddr salve address + * @param usCoilAddr coil start address + * @param usCoilData data to be written + * @param lTimeOut timeout (-1 will waiting forever) + * + * @return error code + * + * @see eMBMasterReqWriteMultipleCoils + */ +eMBMasterReqErrCode +eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData, LONG lTimeOut ) +{ + UCHAR *ucMBFrame; + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + + if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; + else if ( ( usCoilData != 0xFF00 ) && ( usCoilData != 0x0000 ) ) eErrStatus = MB_MRE_ILL_ARG; + else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; + else + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + vMBMasterSetDestAddress(ucSndAddr); + ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_SINGLE_COIL; + ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF] = usCoilAddr >> 8; + ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF + 1] = usCoilAddr; + ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF ] = usCoilData >> 8; + ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usCoilData; + vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE ); + ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); + eErrStatus = eMBMasterWaitRequestFinish( ); + } + return eErrStatus; +} + +eMBException +eMBMasterFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegAddress; + UCHAR ucBuf[2]; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if( *usLen == ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) ) + { + usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1] ); + usRegAddress++; + + if( ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF + 1] == 0x00 ) && + ( ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF ) || + ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0x00 ) ) ) + { + ucBuf[1] = 0; + if( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF ) + { + ucBuf[0] = 1; + } + else + { + ucBuf[0] = 0; + } + eRegStatus = + eMBMasterRegCoilsCB( &ucBuf[0], usRegAddress, 1, MB_REG_WRITE ); + + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid write coil register request because the length + * is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +#endif + +#if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0 + +/** + * This function will request write multiple coils. + * + * @param ucSndAddr salve address + * @param usCoilAddr coil start address + * @param usNCoils coil total number + * @param usCoilData data to be written + * @param lTimeOut timeout (-1 will waiting forever) + * + * @return error code + * + * @see eMBMasterReqWriteCoil + */ +eMBMasterReqErrCode +eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr, + USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer, LONG lTimeOut) +{ + UCHAR *ucMBFrame; + USHORT usRegIndex = 0; + UCHAR ucByteCount; + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + + if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; + else if ( usNCoils > MB_PDU_REQ_WRITE_MUL_COILCNT_MAX ) eErrStatus = MB_MRE_ILL_ARG; + else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; + else + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + vMBMasterSetDestAddress(ucSndAddr); + ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_MULTIPLE_COILS; + ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] = usCoilAddr >> 8; + ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1] = usCoilAddr; + ucMBFrame[MB_PDU_REQ_WRITE_MUL_COILCNT_OFF] = usNCoils >> 8; + ucMBFrame[MB_PDU_REQ_WRITE_MUL_COILCNT_OFF + 1] = usNCoils ; + if( ( usNCoils & 0x0007 ) != 0 ) + { + ucByteCount = ( UCHAR )( usNCoils / 8 + 1 ); + } + else + { + ucByteCount = ( UCHAR )( usNCoils / 8 ); + } + ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF] = ucByteCount; + ucMBFrame += MB_PDU_REQ_WRITE_MUL_VALUES_OFF; + while( ucByteCount > usRegIndex) + { + *ucMBFrame++ = pucDataBuffer[usRegIndex++]; + } + vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + ucByteCount ); + ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); + eErrStatus = eMBMasterWaitRequestFinish( ); + } + return eErrStatus; +} + +eMBException +eMBMasterFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegAddress; + USHORT usCoilCnt; + UCHAR ucByteCount; + UCHAR ucByteCountVerify; + UCHAR *ucMBFrame; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + /* If this request is broadcast, the *usLen is not need check. */ + if( ( *usLen == MB_PDU_FUNC_WRITE_MUL_SIZE ) || xMBMasterRequestIsBroadcast() ) + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1] ); + usRegAddress++; + + usCoilCnt = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF] << 8 ); + usCoilCnt |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF + 1] ); + + ucByteCount = ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF]; + + /* Compute the number of expected bytes in the request. */ + if( ( usCoilCnt & 0x0007 ) != 0 ) + { + ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 + 1 ); + } + else + { + ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 ); + } + + if( ( usCoilCnt >= 1 ) && ( ucByteCountVerify == ucByteCount ) ) + { + eRegStatus = + eMBMasterRegCoilsCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF], + usRegAddress, usCoilCnt, MB_REG_WRITE ); + + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid write coil register request because the length + * is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +#endif +#endif diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbfuncdiag.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncdiag.c similarity index 95% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbfuncdiag.c rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncdiag.c index 8c32e85b1..20be3fcc8 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbfuncdiag.c +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncdiag.c @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,4 +25,5 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mbfuncdiag.c,v 1.3 2006/12/07 22:10:34 wolti Exp $ */ diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbfuncdisc.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncdisc.c similarity index 98% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbfuncdisc.c rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncdisc.c index 1dc10e5c1..5f14129ac 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbfuncdisc.c +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncdisc.c @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -74,7 +74,7 @@ eMBFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen ) usDiscreteCnt |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF + 1] ); /* Check if the number of registers to read is valid. If not - * return Modbus illegal data value exception. + * return Modbus illegal data value exception. */ if( ( usDiscreteCnt >= 1 ) && ( usDiscreteCnt < MB_PDU_FUNC_READ_DISCCNT_MAX ) ) @@ -111,7 +111,7 @@ eMBFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen ) else { /* The response contains the function code, the starting address - * and the quantity of registers. We reuse the old values in the + * and the quantity of registers. We reuse the old values in the * buffer because they are still valid. */ *usLen += ucNBytes;; } diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncdisc_m.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncdisc_m.c new file mode 100644 index 000000000..ca666bbd5 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncdisc_m.c @@ -0,0 +1,162 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (C) 2013 Armink + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbfuncdisc_m.c,v 1.60 2013/10/15 8:48:20 Armink Add Master Functions Exp $ + */ + + + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mb_m.h" +#include "mbframe.h" +#include "mbproto.h" +#include "mbconfig.h" + +/* ----------------------- Defines ------------------------------------------*/ +#define MB_PDU_REQ_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_REQ_READ_DISCCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_REQ_READ_SIZE ( 4 ) +#define MB_PDU_FUNC_READ_DISCCNT_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_FUNC_READ_VALUES_OFF ( MB_PDU_DATA_OFF + 1 ) +#define MB_PDU_FUNC_READ_SIZE_MIN ( 1 ) + +/* ----------------------- Static functions ---------------------------------*/ +eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); + +/* ----------------------- Start implementation -----------------------------*/ +#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 +#if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED > 0 + +/** + * This function will request read discrete inputs. + * + * @param ucSndAddr salve address + * @param usDiscreteAddr discrete start address + * @param usNDiscreteIn discrete total number + * @param lTimeOut timeout (-1 will waiting forever) + * + * @return error code + */ +eMBMasterReqErrCode +eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn, LONG lTimeOut ) +{ + UCHAR *ucMBFrame; + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + + if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; + else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; + else + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + vMBMasterSetDestAddress(ucSndAddr); + ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_DISCRETE_INPUTS; + ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usDiscreteAddr >> 8; + ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usDiscreteAddr; + ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF ] = usNDiscreteIn >> 8; + ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF + 1] = usNDiscreteIn; + vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE ); + ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); + eErrStatus = eMBMasterWaitRequestFinish( ); + } + return eErrStatus; +} + +eMBException +eMBMasterFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegAddress; + USHORT usDiscreteCnt; + UCHAR ucNBytes; + UCHAR *ucMBFrame; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + /* If this request is broadcast, and it's read mode. This request don't need execute. */ + if ( xMBMasterRequestIsBroadcast() ) + { + eStatus = MB_EX_NONE; + } + else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN ) + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] ); + usRegAddress++; + + usDiscreteCnt = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF] << 8 ); + usDiscreteCnt |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF + 1] ); + + /* Test if the quantity of coils is a multiple of 8. If not last + * byte is only partially field with unused coils set to zero. */ + if( ( usDiscreteCnt & 0x0007 ) != 0 ) + { + ucNBytes = ( UCHAR )( usDiscreteCnt / 8 + 1 ); + } + else + { + ucNBytes = ( UCHAR )( usDiscreteCnt / 8 ); + } + + /* Check if the number of registers to read is valid. If not + * return Modbus illegal data value exception. + */ + if ((usDiscreteCnt >= 1) && ucNBytes == pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF]) + { + /* Make callback to fill the buffer. */ + eRegStatus = eMBMasterRegDiscreteCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usDiscreteCnt ); + + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid read coil register request because the length + * is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +#endif +#endif diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbfuncholding.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncholding.c similarity index 98% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbfuncholding.c rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncholding.c index 3974b3e68..717a91438 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbfuncholding.c +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncholding.c @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,6 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mbfuncholding.c,v 1.12 2007/02/18 23:48:22 wolti Exp $ */ /* ----------------------- System includes ----------------------------------*/ @@ -182,10 +183,10 @@ eMBFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) usRegAddress++; usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8 ); - usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] ); + usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] ); /* Check if the number of registers to read is valid. If not - * return Modbus illegal data value exception. + * return Modbus illegal data value exception. */ if( ( usRegCount >= 1 ) && ( usRegCount <= MB_PDU_FUNC_READ_REGCNT_MAX ) ) { diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncholding_m.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncholding_m.c new file mode 100644 index 000000000..999c9a17b --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncholding_m.c @@ -0,0 +1,455 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (C) 2013 Armink + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbfuncholding_m.c,v 1.60 2013/09/02 14:13:40 Armink Add Master Functions Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mb_m.h" +#include "mbframe.h" +#include "mbproto.h" +#include "mbconfig.h" + +/* ----------------------- Defines ------------------------------------------*/ +#define MB_PDU_REQ_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_REQ_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_REQ_READ_SIZE ( 4 ) +#define MB_PDU_FUNC_READ_REGCNT_MAX ( 0x007D ) +#define MB_PDU_FUNC_READ_BYTECNT_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_FUNC_READ_VALUES_OFF ( MB_PDU_DATA_OFF + 1 ) +#define MB_PDU_FUNC_READ_SIZE_MIN ( 1 ) + +#define MB_PDU_REQ_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 0) +#define MB_PDU_REQ_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_REQ_WRITE_SIZE ( 4 ) +#define MB_PDU_FUNC_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 0) +#define MB_PDU_FUNC_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_WRITE_SIZE ( 4 ) + +#define MB_PDU_REQ_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_REQ_WRITE_MUL_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF ( MB_PDU_DATA_OFF + 4 ) +#define MB_PDU_REQ_WRITE_MUL_VALUES_OFF ( MB_PDU_DATA_OFF + 5 ) +#define MB_PDU_REQ_WRITE_MUL_SIZE_MIN ( 5 ) +#define MB_PDU_REQ_WRITE_MUL_REGCNT_MAX ( 0x0078 ) +#define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_FUNC_WRITE_MUL_SIZE ( 4 ) + +#define MB_PDU_REQ_READWRITE_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_REQ_READWRITE_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 4 ) +#define MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF ( MB_PDU_DATA_OFF + 6 ) +#define MB_PDU_REQ_READWRITE_WRITE_BYTECNT_OFF ( MB_PDU_DATA_OFF + 8 ) +#define MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF ( MB_PDU_DATA_OFF + 9 ) +#define MB_PDU_REQ_READWRITE_SIZE_MIN ( 9 ) +#define MB_PDU_FUNC_READWRITE_READ_BYTECNT_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_FUNC_READWRITE_READ_VALUES_OFF ( MB_PDU_DATA_OFF + 1 ) +#define MB_PDU_FUNC_READWRITE_SIZE_MIN ( 1 ) + +/* ----------------------- Static functions ---------------------------------*/ +eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); + +/* ----------------------- Start implementation -----------------------------*/ +#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 +#if MB_FUNC_WRITE_HOLDING_ENABLED > 0 + +/** + * This function will request write holding register. + * + * @param ucSndAddr salve address + * @param usRegAddr register start address + * @param usRegData register data to be written + * @param lTimeOut timeout (-1 will waiting forever) + * + * @return error code + */ +eMBMasterReqErrCode +eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut ) +{ + UCHAR *ucMBFrame; + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + + if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; + else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; + else + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + vMBMasterSetDestAddress(ucSndAddr); + ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_REGISTER; + ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF] = usRegAddr >> 8; + ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF + 1] = usRegAddr; + ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF] = usRegData >> 8; + ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usRegData ; + vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE ); + ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); + eErrStatus = eMBMasterWaitRequestFinish( ); + } + return eErrStatus; +} + +eMBException +eMBMasterFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegAddress; + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if( *usLen == ( MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_SIZE ) ) + { + usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1] ); + usRegAddress++; + + /* Make callback to update the value. */ + eRegStatus = eMBMasterRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF], + usRegAddress, 1, MB_REG_WRITE ); + + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + /* Can't be a valid request because the length is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} +#endif + +#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0 + +/** + * This function will request write multiple holding register. + * + * @param ucSndAddr salve address + * @param usRegAddr register start address + * @param usNRegs register total number + * @param pusDataBuffer data to be written + * @param lTimeOut timeout (-1 will waiting forever) + * + * @return error code + */ +eMBMasterReqErrCode +eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr, + USHORT usRegAddr, USHORT usNRegs, USHORT * pusDataBuffer, LONG lTimeOut ) +{ + UCHAR *ucMBFrame; + USHORT usRegIndex = 0; + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + + if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; + else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; + else + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + vMBMasterSetDestAddress(ucSndAddr); + ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_MULTIPLE_REGISTERS; + ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] = usRegAddr >> 8; + ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1] = usRegAddr; + ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF] = usNRegs >> 8; + ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF + 1] = usNRegs ; + ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF] = usNRegs * 2; + ucMBFrame += MB_PDU_REQ_WRITE_MUL_VALUES_OFF; + while( usNRegs > usRegIndex) + { + *ucMBFrame++ = pusDataBuffer[usRegIndex] >> 8; + *ucMBFrame++ = pusDataBuffer[usRegIndex++] ; + } + vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + 2*usNRegs ); + ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); + eErrStatus = eMBMasterWaitRequestFinish( ); + } + return eErrStatus; +} + +eMBException +eMBMasterFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) +{ + UCHAR *ucMBFrame; + USHORT usRegAddress; + USHORT usRegCount; + UCHAR ucRegByteCount; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + /* If this request is broadcast, the *usLen is not need check. */ + if( ( *usLen == MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_MUL_SIZE ) || xMBMasterRequestIsBroadcast() ) + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1] ); + usRegAddress++; + + usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF] << 8 ); + usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF + 1] ); + + ucRegByteCount = ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF]; + + if( ucRegByteCount == 2 * usRegCount ) + { + /* Make callback to update the register values. */ + eRegStatus = + eMBMasterRegHoldingCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF], + usRegAddress, usRegCount, MB_REG_WRITE ); + + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid request because the length is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} +#endif + +#if MB_FUNC_READ_HOLDING_ENABLED > 0 + +/** + * This function will request read holding register. + * + * @param ucSndAddr salve address + * @param usRegAddr register start address + * @param usNRegs register total number + * @param lTimeOut timeout (-1 will waiting forever) + * + * @return error code + */ +eMBMasterReqErrCode +eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut ) +{ + UCHAR *ucMBFrame; + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + + if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; + else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; + else + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + vMBMasterSetDestAddress(ucSndAddr); + ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_HOLDING_REGISTER; + ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usRegAddr >> 8; + ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usRegAddr; + ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] = usNRegs >> 8; + ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs; + vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE ); + ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); + eErrStatus = eMBMasterWaitRequestFinish( ); + } + return eErrStatus; +} + +eMBException +eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) +{ + UCHAR *ucMBFrame; + USHORT usRegAddress; + USHORT usRegCount; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + /* If this request is broadcast, and it's read mode. This request don't need execute. */ + if ( xMBMasterRequestIsBroadcast() ) + { + eStatus = MB_EX_NONE; + } + else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN ) + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] ); + usRegAddress++; + + usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] << 8 ); + usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] ); + + /* Check if the number of registers to read is valid. If not + * return Modbus illegal data value exception. + */ + if( ( usRegCount >= 1 ) && ( 2 * usRegCount == pucFrame[MB_PDU_FUNC_READ_BYTECNT_OFF] ) ) + { + /* Make callback to fill the buffer. */ + eRegStatus = eMBMasterRegHoldingCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount, MB_REG_READ ); + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid request because the length is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +#endif + +#if MB_FUNC_READWRITE_HOLDING_ENABLED > 0 + +/** + * This function will request read and write holding register. + * + * @param ucSndAddr salve address + * @param usReadRegAddr read register start address + * @param usNReadRegs read register total number + * @param pusDataBuffer data to be written + * @param usWriteRegAddr write register start address + * @param usNWriteRegs write register total number + * @param lTimeOut timeout (-1 will waiting forever) + * + * @return error code + */ +eMBMasterReqErrCode +eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr, + USHORT usReadRegAddr, USHORT usNReadRegs, USHORT * pusDataBuffer, + USHORT usWriteRegAddr, USHORT usNWriteRegs, LONG lTimeOut ) +{ + UCHAR *ucMBFrame; + USHORT usRegIndex = 0; + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + + if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; + else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; + else + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + vMBMasterSetDestAddress(ucSndAddr); + ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READWRITE_MULTIPLE_REGISTERS; + ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF] = usReadRegAddr >> 8; + ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF + 1] = usReadRegAddr; + ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF] = usNReadRegs >> 8; + ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF + 1] = usNReadRegs ; + ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF] = usWriteRegAddr >> 8; + ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF + 1] = usWriteRegAddr; + ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF] = usNWriteRegs >> 8; + ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF + 1] = usNWriteRegs ; + ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_BYTECNT_OFF] = usNWriteRegs * 2; + ucMBFrame += MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF; + while( usNWriteRegs > usRegIndex) + { + *ucMBFrame++ = pusDataBuffer[usRegIndex] >> 8; + *ucMBFrame++ = pusDataBuffer[usRegIndex++] ; + } + vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READWRITE_SIZE_MIN + 2*usNWriteRegs ); + ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); + eErrStatus = eMBMasterWaitRequestFinish( ); + } + return eErrStatus; +} + +eMBException +eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) +{ + USHORT usRegReadAddress; + USHORT usRegReadCount; + USHORT usRegWriteAddress; + USHORT usRegWriteCount; + UCHAR *ucMBFrame; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + /* If this request is broadcast, and it's read mode. This request don't need execute. */ + if ( xMBMasterRequestIsBroadcast() ) + { + eStatus = MB_EX_NONE; + } + else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READWRITE_SIZE_MIN ) + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + usRegReadAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF] << 8U ); + usRegReadAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF + 1] ); + usRegReadAddress++; + + usRegReadCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF] << 8U ); + usRegReadCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF + 1] ); + + usRegWriteAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF] << 8U ); + usRegWriteAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF + 1] ); + usRegWriteAddress++; + + usRegWriteCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF] << 8U ); + usRegWriteCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF + 1] ); + + if( ( 2 * usRegReadCount ) == pucFrame[MB_PDU_FUNC_READWRITE_READ_BYTECNT_OFF] ) + { + /* Make callback to update the register values. */ + eRegStatus = eMBMasterRegHoldingCB( &ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF], + usRegWriteAddress, usRegWriteCount, MB_REG_WRITE ); + + if( eRegStatus == MB_ENOERR ) + { + /* Make the read callback. */ + eRegStatus = eMBMasterRegHoldingCB(&pucFrame[MB_PDU_FUNC_READWRITE_READ_VALUES_OFF], + usRegReadAddress, usRegReadCount, MB_REG_READ); + } + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + return eStatus; +} + +#endif +#endif + diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbfuncinput.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncinput.c similarity index 97% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbfuncinput.c rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncinput.c index 2cf1144f1..926055039 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbfuncinput.c +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncinput.c @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,6 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mbfuncinput.c,v 1.10 2007/09/12 10:15:56 wolti Exp $ */ /* ----------------------- System includes ----------------------------------*/ @@ -74,7 +75,7 @@ eMBFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen ) usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] ); /* Check if the number of registers to read is valid. If not - * return Modbus illegal data value exception. + * return Modbus illegal data value exception. */ if( ( usRegCount >= 1 ) && ( usRegCount < MB_PDU_FUNC_READ_REGCNT_MAX ) ) diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncinput_m.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncinput_m.c new file mode 100644 index 000000000..7e6cb19e2 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncinput_m.c @@ -0,0 +1,148 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (C) 2013 Armink + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbfuncinput_m.c,v 1.60 2013/10/12 14:23:40 Armink Add Master Functions Exp $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mb_m.h" +#include "mbframe.h" +#include "mbproto.h" +#include "mbconfig.h" + +/* ----------------------- Defines ------------------------------------------*/ +#define MB_PDU_REQ_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_REQ_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) +#define MB_PDU_REQ_READ_SIZE ( 4 ) +#define MB_PDU_FUNC_READ_BYTECNT_OFF ( MB_PDU_DATA_OFF + 0 ) +#define MB_PDU_FUNC_READ_VALUES_OFF ( MB_PDU_DATA_OFF + 1 ) +#define MB_PDU_FUNC_READ_SIZE_MIN ( 1 ) + +#define MB_PDU_FUNC_READ_RSP_BYTECNT_OFF ( MB_PDU_DATA_OFF ) + +/* ----------------------- Static functions ---------------------------------*/ +eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); + +/* ----------------------- Start implementation -----------------------------*/ +#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 +#if MB_FUNC_READ_INPUT_ENABLED > 0 + +/** + * This function will request read input register. + * + * @param ucSndAddr salve address + * @param usRegAddr register start address + * @param usNRegs register total number + * @param lTimeOut timeout (-1 will waiting forever) + * + * @return error code + */ +eMBMasterReqErrCode +eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut ) +{ + UCHAR *ucMBFrame; + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + + if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; + else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; + else + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + vMBMasterSetDestAddress(ucSndAddr); + ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_INPUT_REGISTER; + ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usRegAddr >> 8; + ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usRegAddr; + ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] = usNRegs >> 8; + ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs; + vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE ); + ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); + eErrStatus = eMBMasterWaitRequestFinish( ); + } + return eErrStatus; +} + +eMBException +eMBMasterFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen ) +{ + UCHAR *ucMBFrame; + USHORT usRegAddress; + USHORT usRegCount; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + /* If this request is broadcast, and it's read mode. This request don't need execute. */ + if ( xMBMasterRequestIsBroadcast() ) + { + eStatus = MB_EX_NONE; + } + else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN ) + { + vMBMasterGetPDUSndBuf(&ucMBFrame); + usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 ); + usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] ); + usRegAddress++; + + usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] << 8 ); + usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] ); + + /* Check if the number of registers to read is valid. If not + * return Modbus illegal data value exception. + */ + if( ( usRegCount >= 1 ) && ( 2 * usRegCount == pucFrame[MB_PDU_FUNC_READ_BYTECNT_OFF] ) ) + { + /* Make callback to fill the buffer. */ + eRegStatus = eMBMasterRegInputCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount ); + /* If an error occured convert it into a Modbus exception. */ + if( eRegStatus != MB_ENOERR ) + { + eStatus = prveMBError2Exception( eRegStatus ); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + /* Can't be a valid request because the length is incorrect. */ + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +#endif +#endif diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbfuncother.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncother.c similarity index 98% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbfuncother.c rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncother.c index adbc85da9..6161894a8 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbfuncother.c +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbfuncother.c @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,6 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mbfuncother.c,v 1.8 2006/12/07 22:10:34 wolti Exp $ */ /* ----------------------- System includes ----------------------------------*/ diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbutils.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbutils.c similarity index 93% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbutils.c rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbutils.c index be384fc52..0016d0ae4 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/functions/mbutils.c +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/functions/mbutils.c @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,6 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mbutils.c,v 1.6 2007/02/18 23:49:07 wolti Exp $ */ /* ----------------------- System includes ----------------------------------*/ @@ -52,8 +53,15 @@ xMBUtilSetBits( UCHAR * ucByteBuf, USHORT usBitOffset, UCHAR ucNBits, USHORT usNPreBits; USHORT usValue = ucValue; - assert( ucNBits <= 8 ); - assert( ( size_t )BITS_UCHAR == sizeof( UCHAR ) * 8 ); +#ifdef ADD_RTTHREAD_FEATURES + RT_ASSERT( ucNBits <= 8 ); + RT_ASSERT( ( size_t )BITS_UCHAR == sizeof( UCHAR ) * 8 ); +#endif + +#ifdef ADD_XIZI_FEATURES + MB_CHECK( ucNBits <= 8 ); + MB_CHECK( ( size_t )BITS_UCHAR == sizeof( UCHAR ) * 8 ); +#endif /* Calculate byte offset for first byte containing the bit values starting * at usBitOffset. */ diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mb.h b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mb.h similarity index 96% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mb.h rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mb.h index 1c09e77f5..f451d6535 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mb.h +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mb.h @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,6 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mb.h,v 1.17 2006/12/07 22:10:34 wolti Exp $ */ #ifndef _MB_H @@ -70,7 +71,7 @@ PR_BEGIN_EXTERN_C /*! \ingroup modbus * \brief Use the default Modbus TCP port (502) */ -#define MB_TCP_PORT_USE_DEFAULT 0 +#define MB_TCP_PORT_USE_DEFAULT 0 /* ----------------------- Type definitions ---------------------------------*/ @@ -96,7 +97,7 @@ PR_BEGIN_EXTERN_C * registers should be updated and reading means that the modbus protocol * stack needs to know the current register values. * - * \see eMBRegHoldingCB( ), eMBRegCoilsCB( ), eMBRegDiscreteCB( ) and + * \see eMBRegHoldingCB( ), eMBRegCoilsCB( ), eMBRegDiscreteCB( ) and * eMBRegInputCB( ). */ typedef enum @@ -141,7 +142,7 @@ typedef enum * * \return If no error occurs the function returns eMBErrorCode::MB_ENOERR. * The protocol is then in the disabled state and ready for activation - * by calling eMBEnable( ). Otherwise one of the following error codes + * by calling eMBEnable( ). Otherwise one of the following error codes * is returned: * - eMBErrorCode::MB_EINVAL If the slave address was not valid. Valid * slave addresses are in the range 1 - 247. @@ -170,10 +171,10 @@ eMBErrorCode eMBTCPInit( USHORT usTCPPort ); * \brief Release resources used by the protocol stack. * * This function disables the Modbus protocol stack and release all - * hardware resources. It must only be called when the protocol stack - * is disabled. + * hardware resources. It must only be called when the protocol stack + * is disabled. * - * \note Note all ports implement this function. A port which wants to + * \note Note all ports implement this function. A port which wants to * get an callback must define the macro MB_PORT_HAS_CLOSE to 1. * * \return If the resources where released it return eMBErrorCode::MB_ENOERR. @@ -188,8 +189,8 @@ eMBErrorCode eMBClose( void ); * This function enables processing of Modbus frames. Enabling the protocol * stack is only possible if it is in the disabled state. * - * \return If the protocol stack is now in the state enabled it returns - * eMBErrorCode::MB_ENOERR. If it was not in the disabled state it + * \return If the protocol stack is now in the state enabled it returns + * eMBErrorCode::MB_ENOERR. If it was not in the disabled state it * return eMBErrorCode::MB_EILLSTATE. */ eMBErrorCode eMBEnable( void ); @@ -199,7 +200,7 @@ eMBErrorCode eMBEnable( void ); * * This function disables processing of Modbus frames. * - * \return If the protocol stack has been disabled it returns + * \return If the protocol stack has been disabled it returns * eMBErrorCode::MB_ENOERR. If it was not in the enabled state it returns * eMBErrorCode::MB_EILLSTATE. */ @@ -211,10 +212,10 @@ eMBErrorCode eMBDisable( void ); * This function must be called periodically. The timer interval required * is given by the application dependent Modbus slave timeout. Internally the * function calls xMBPortEventGet() and waits for an event from the receiver or - * transmitter state machines. + * transmitter state machines. * * \return If the protocol stack is not in the enabled state the function - * returns eMBErrorCode::MB_EILLSTATE. Otherwise it returns + * returns eMBErrorCode::MB_EILLSTATE. Otherwise it returns * eMBErrorCode::MB_ENOERR. */ eMBErrorCode eMBPoll( void ); @@ -248,7 +249,7 @@ eMBErrorCode eMBSetSlaveID( UCHAR ucSlaveID, BOOL xIsRunning, * The callback handler supplied is responsible for interpreting the Modbus PDU and * the creation of an appropriate response. In case of an error it should return * one of the possible Modbus exceptions which results in a Modbus exception frame - * sent by the protocol stack. + * sent by the protocol stack. * * \param ucFunctionCode The Modbus function code for which this handler should * be registers. Valid function codes are in the range 1 to 127. @@ -261,7 +262,7 @@ eMBErrorCode eMBSetSlaveID( UCHAR ucSlaveID, BOOL xIsRunning, * case the values in mbconfig.h should be adjusted. If the argument was not * valid it returns eMBErrorCode::MB_EINVAL. */ -eMBErrorCode eMBRegisterCB( UCHAR ucFunctionCode, +eMBErrorCode eMBRegisterCB( UCHAR ucFunctionCode, pxMBFunctionHandler pxHandler ); /* ----------------------- Callback -----------------------------------------*/ @@ -299,7 +300,7 @@ eMBErrorCode eMBRegisterCB( UCHAR ucFunctionCode, * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal * Modbus response is sent. * - eMBErrorCode::MB_ENOREG If the application can not supply values - * for registers within this range. In this case a + * for registers within this range. In this case a * ILLEGAL DATA ADDRESS exception frame is sent as a response. * - eMBErrorCode::MB_ETIMEDOUT If the requested register block is * currently not available and the application dependent response @@ -323,18 +324,18 @@ eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, * this buffer. * \param usAddress The starting address of the register. * \param usNRegs Number of registers to read or write. - * \param eMode If eMBRegisterMode::MB_REG_WRITE the application register + * \param eMode If eMBRegisterMode::MB_REG_WRITE the application register * values should be updated from the values in the buffer. For example - * this would be the case when the Modbus master has issued an + * this would be the case when the Modbus master has issued an * WRITE SINGLE REGISTER command. - * If the value eMBRegisterMode::MB_REG_READ the application should copy + * If the value eMBRegisterMode::MB_REG_READ the application should copy * the current values into the buffer \c pucRegBuffer. * * \return The function must return one of the following error codes: * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal * Modbus response is sent. * - eMBErrorCode::MB_ENOREG If the application can not supply values - * for registers within this range. In this case a + * for registers within this range. In this case a * ILLEGAL DATA ADDRESS exception frame is sent as a response. * - eMBErrorCode::MB_ETIMEDOUT If the requested register block is * currently not available and the application dependent response @@ -369,7 +370,7 @@ eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal * Modbus response is sent. * - eMBErrorCode::MB_ENOREG If the application does not map an coils - * within the requested address range. In this case a + * within the requested address range. In this case a * ILLEGAL DATA ADDRESS is sent as a response. * - eMBErrorCode::MB_ETIMEDOUT If the requested register block is * currently not available and the application dependent response @@ -398,7 +399,7 @@ eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal * Modbus response is sent. * - eMBErrorCode::MB_ENOREG If no such discrete inputs exists. - * In this case a ILLEGAL DATA ADDRESS exception frame is sent + * In this case a ILLEGAL DATA ADDRESS exception frame is sent * as a response. * - eMBErrorCode::MB_ETIMEDOUT If the requested register block is * currently not available and the application dependent response diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mb_m.h b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mb_m.h new file mode 100644 index 000000000..b01e6357f --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mb_m.h @@ -0,0 +1,414 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (C) 2013 Armink + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mb_m.h,v 1.60 2013/09/03 10:20:05 Armink Add Master Functions $ + */ + +#ifndef _MB_M_H +#define _MB_M_H + +#ifdef __cplusplus +PR_BEGIN_EXTERN_C +#endif + +/*! \defgroup modbus Modbus + * \code #include "mb_m.h" \endcode + * + * This module defines the interface for the application. It contains + * the basic functions and types required to use the Modbus Master protocol stack. + * A typical application will want to call eMBMasterInit() first. If the device + * is ready to answer network requests it must then call eMBEnable() to activate + * the protocol stack. In the main loop the function eMBMasterPoll() must be called + * periodically. The time interval between pooling depends on the configured + * Modbus timeout. If an RTOS is available a separate task should be created + * and the task should always call the function eMBMasterPoll(). + * + * \code + * // Initialize protocol stack in RTU mode for a Master + * eMBMasterInit( MB_RTU, 38400, MB_PAR_EVEN ); + * // Enable the Modbus Protocol Stack. + * eMBMasterEnable( ); + * for( ;; ) + * { + * // Call the main polling loop of the Modbus Master protocol stack. + * eMBMasterPoll( ); + * ... + * } + * \endcode + */ + +/* ----------------------- Defines ------------------------------------------*/ + +/*! \ingroup modbus + * \brief Use the default Modbus Master TCP port (502) + */ +#define MB_MASTER_TCP_PORT_USE_DEFAULT 0 + +/* ----------------------- Type definitions ---------------------------------*/ +/*! \ingroup modbus + * \brief Errorcodes used by all function in the Master request. + */ +typedef enum +{ + MB_MRE_NO_ERR, /*!< no error. */ + MB_MRE_NO_REG, /*!< illegal register address. */ + MB_MRE_ILL_ARG, /*!< illegal argument. */ + MB_MRE_REV_DATA, /*!< receive data error. */ + MB_MRE_TIMEDOUT, /*!< timeout error occurred. */ + MB_MRE_MASTER_BUSY, /*!< master is busy now. */ + MB_MRE_EXE_FUN /*!< execute function error. */ +} eMBMasterReqErrCode; +/*! \ingroup modbus + * \brief TimerMode is Master 3 kind of Timer modes. + */ +typedef enum +{ + MB_TMODE_T35, /*!< Master receive frame T3.5 timeout. */ + MB_TMODE_RESPOND_TIMEOUT, /*!< Master wait respond for slave. */ + MB_TMODE_CONVERT_DELAY /*!< Master sent broadcast ,then delay sometime.*/ +}eMBMasterTimerMode; + +/* ----------------------- Function prototypes ------------------------------*/ +/*! \ingroup modbus + * \brief Initialize the Modbus Master protocol stack. + * + * This functions initializes the ASCII or RTU module and calls the + * init functions of the porting layer to prepare the hardware. Please + * note that the receiver is still disabled and no Modbus frames are + * processed until eMBMasterEnable( ) has been called. + * + * \param eMode If ASCII or RTU mode should be used. + * \param ucPort The port to use. E.g. 1 for COM1 on windows. This value + * is platform dependent and some ports simply choose to ignore it. + * \param ulBaudRate The baudrate. E.g. 19200. Supported baudrates depend + * on the porting layer. + * \param eParity Parity used for serial transmission. + * + * \return If no error occurs the function returns eMBErrorCode::MB_ENOERR. + * The protocol is then in the disabled state and ready for activation + * by calling eMBMasterEnable( ). Otherwise one of the following error codes + * is returned: + * - eMBErrorCode::MB_EPORTERR IF the porting layer returned an error. + */ +eMBErrorCode eMBMasterInit( eMBMode eMode, UCHAR ucPort, + ULONG ulBaudRate, eMBParity eParity ); + +/*! \ingroup modbus + * \brief Initialize the Modbus Master protocol stack for Modbus TCP. + * + * This function initializes the Modbus TCP Module. Please note that + * frame processing is still disabled until eMBEnable( ) is called. + * + * \param usTCPPort The TCP port to listen on. + * \return If the protocol stack has been initialized correctly the function + * returns eMBErrorCode::MB_ENOERR. Otherwise one of the following error + * codes is returned: + * - eMBErrorCode::MB_EINVAL If the slave address was not valid. Valid + * slave addresses are in the range 1 - 247. + * - eMBErrorCode::MB_EPORTERR IF the porting layer returned an error. + */ +eMBErrorCode eMBMasterTCPInit( USHORT usTCPPort ); + +/*! \ingroup modbus + * \brief Release resources used by the protocol stack. + * + * This function disables the Modbus Master protocol stack and release all + * hardware resources. It must only be called when the protocol stack + * is disabled. + * + * \note Note all ports implement this function. A port which wants to + * get an callback must define the macro MB_PORT_HAS_CLOSE to 1. + * + * \return If the resources where released it return eMBErrorCode::MB_ENOERR. + * If the protocol stack is not in the disabled state it returns + * eMBErrorCode::MB_EILLSTATE. + */ +eMBErrorCode eMBMasterClose( void ); + +/*! \ingroup modbus + * \brief Enable the Modbus Master protocol stack. + * + * This function enables processing of Modbus Master frames. Enabling the protocol + * stack is only possible if it is in the disabled state. + * + * \return If the protocol stack is now in the state enabled it returns + * eMBErrorCode::MB_ENOERR. If it was not in the disabled state it + * return eMBErrorCode::MB_EILLSTATE. + */ +eMBErrorCode eMBMasterEnable( void ); + +/*! \ingroup modbus + * \brief Disable the Modbus Master protocol stack. + * + * This function disables processing of Modbus frames. + * + * \return If the protocol stack has been disabled it returns + * eMBErrorCode::MB_ENOERR. If it was not in the enabled state it returns + * eMBErrorCode::MB_EILLSTATE. + */ +eMBErrorCode eMBMasterDisable( void ); + +/*! \ingroup modbus + * \brief Check the Modbus Master protocol stack has established or not. + * + * This function must be called and check the return value before calling + * any other functions. + * + * \return If the protocol stack has been established or not + * TRUE. the protocol stack has established + * FALSE. the protocol stack hasn't established + */ +BOOL eMBMasterIsEstablished( void ); + +/*! \ingroup modbus + * \brief The main pooling loop of the Modbus Master protocol stack. + * + * This function must be called periodically. The timer interval required + * is given by the application dependent Modbus slave timeout. Internally the + * function calls xMBMasterPortEventGet() and waits for an event from the receiver or + * transmitter state machines. + * + * \return If the protocol stack is not in the enabled state the function + * returns eMBErrorCode::MB_EILLSTATE. Otherwise it returns + * eMBErrorCode::MB_ENOERR. + */ +eMBErrorCode eMBMasterPoll( void ); + +/*! \ingroup modbus + * \brief Registers a callback handler for a given function code. + * + * This function registers a new callback handler for a given function code. + * The callback handler supplied is responsible for interpreting the Modbus PDU and + * the creation of an appropriate response. In case of an error it should return + * one of the possible Modbus exceptions which results in a Modbus exception frame + * sent by the protocol stack. + * + * \param ucFunctionCode The Modbus function code for which this handler should + * be registers. Valid function codes are in the range 1 to 127. + * \param pxHandler The function handler which should be called in case + * such a frame is received. If \c NULL a previously registered function handler + * for this function code is removed. + * + * \return eMBErrorCode::MB_ENOERR if the handler has been installed. If no + * more resources are available it returns eMBErrorCode::MB_ENORES. In this + * case the values in mbconfig.h should be adjusted. If the argument was not + * valid it returns eMBErrorCode::MB_EINVAL. + */ +eMBErrorCode eMBMasterRegisterCB( UCHAR ucFunctionCode, + pxMBFunctionHandler pxHandler ); + +/* ----------------------- Callback -----------------------------------------*/ + +/*! \defgroup modbus_master registers Modbus Registers + * \code #include "mb_m.h" \endcode + * The protocol stack does not internally allocate any memory for the + * registers. This makes the protocol stack very small and also usable on + * low end targets. In addition the values don't have to be in the memory + * and could for example be stored in a flash.
+ * Whenever the protocol stack requires a value it calls one of the callback + * function with the register address and the number of registers to read + * as an argument. The application should then read the actual register values + * (for example the ADC voltage) and should store the result in the supplied + * buffer.
+ * If the protocol stack wants to update a register value because a write + * register function was received a buffer with the new register values is + * passed to the callback function. The function should then use these values + * to update the application register values. + */ + +/*! \ingroup modbus_registers + * \brief Callback function used if the value of a Input Register + * is required by the protocol stack. The starting register address is given + * by \c usAddress and the last register is given by usAddress + + * usNRegs - 1. + * + * \param pucRegBuffer A buffer where the callback function should write + * the current value of the modbus registers to. + * \param usAddress The starting address of the register. Input registers + * are in the range 1 - 65535. + * \param usNRegs Number of registers the callback function must supply. + * + * \return The function must return one of the following error codes: + * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal + * Modbus response is sent. + * - eMBErrorCode::MB_ENOREG If the application does not map an coils + * within the requested address range. In this case a + * ILLEGAL DATA ADDRESS is sent as a response. + */ +eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs ); + +/*! \ingroup modbus_registers + * \brief Callback function used if a Holding Register value is + * read or written by the protocol stack. The starting register address + * is given by \c usAddress and the last register is given by + * usAddress + usNRegs - 1. + * + * \param pucRegBuffer If the application registers values should be updated the + * buffer points to the new registers values. If the protocol stack needs + * to now the current values the callback function should write them into + * this buffer. + * \param usAddress The starting address of the register. + * \param usNRegs Number of registers to read or write. + * \param eMode If eMBRegisterMode::MB_REG_WRITE the application register + * values should be updated from the values in the buffer. For example + * this would be the case when the Modbus master has issued an + * WRITE SINGLE REGISTER command. + * If the value eMBRegisterMode::MB_REG_READ the application should copy + * the current values into the buffer \c pucRegBuffer. + * + * \return The function must return one of the following error codes: + * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal + * Modbus response is sent. + * - eMBErrorCode::MB_ENOREG If the application does not map an coils + * within the requested address range. In this case a + * ILLEGAL DATA ADDRESS is sent as a response. + */ +eMBErrorCode eMBMasterRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs, eMBRegisterMode eMode ); + +/*! \ingroup modbus_registers + * \brief Callback function used if a Coil Register value is + * read or written by the protocol stack. If you are going to use + * this function you might use the functions xMBUtilSetBits( ) and + * xMBUtilGetBits( ) for working with bitfields. + * + * \param pucRegBuffer The bits are packed in bytes where the first coil + * starting at address \c usAddress is stored in the LSB of the + * first byte in the buffer pucRegBuffer. + * If the buffer should be written by the callback function unused + * coil values (I.e. if not a multiple of eight coils is used) should be set + * to zero. + * \param usAddress The first coil number. + * \param usNCoils Number of coil values requested. + * \param eMode If eMBRegisterMode::MB_REG_WRITE the application values should + * be updated from the values supplied in the buffer \c pucRegBuffer. + * If eMBRegisterMode::MB_REG_READ the application should store the current + * values in the buffer \c pucRegBuffer. + * + * \return The function must return one of the following error codes: + * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal + * Modbus response is sent. + * - eMBErrorCode::MB_ENOREG If the application does not map an coils + * within the requested address range. In this case a + * ILLEGAL DATA ADDRESS is sent as a response. + */ +eMBErrorCode eMBMasterRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNCoils, eMBRegisterMode eMode ); + +/*! \ingroup modbus_registers + * \brief Callback function used if a Input Discrete Register value is + * read by the protocol stack. + * + * If you are going to use his function you might use the functions + * xMBUtilSetBits( ) and xMBUtilGetBits( ) for working with bitfields. + * + * \param pucRegBuffer The buffer should be updated with the current + * coil values. The first discrete input starting at \c usAddress must be + * stored at the LSB of the first byte in the buffer. If the requested number + * is not a multiple of eight the remaining bits should be set to zero. + * \param usAddress The starting address of the first discrete input. + * \param usNDiscrete Number of discrete input values. + * \return The function must return one of the following error codes: + * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal + * Modbus response is sent. + * - eMBErrorCode::MB_ENOREG If the application does not map an coils + * within the requested address range. In this case a + * ILLEGAL DATA ADDRESS is sent as a response. + */ +eMBErrorCode eMBMasterRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNDiscrete ); + +/*! \ingroup modbus + *\brief These Modbus functions are called for user when Modbus run in Master Mode. + */ +eMBMasterReqErrCode +eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut ); +eMBMasterReqErrCode +eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut ); +eMBMasterReqErrCode +eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, + USHORT usNRegs, USHORT * pusDataBuffer, LONG lTimeOut ); +eMBMasterReqErrCode +eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut ); +eMBMasterReqErrCode +eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr, + USHORT usReadRegAddr, USHORT usNReadRegs, USHORT * pusDataBuffer, + USHORT usWriteRegAddr, USHORT usNWriteRegs, LONG lTimeOut ); +eMBMasterReqErrCode +eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils, LONG lTimeOut ); +eMBMasterReqErrCode +eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData, LONG lTimeOut ); +eMBMasterReqErrCode +eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr, + USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer, LONG lTimeOut ); +eMBMasterReqErrCode +eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn, LONG lTimeOut ); + +eMBException +eMBMasterFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen ); +eMBException +eMBMasterFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen ); +eMBException +eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen ); +eMBException +eMBMasterFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen ); +eMBException +eMBMasterFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ); +eMBException +eMBMasterFuncReadCoils( UCHAR * pucFrame, USHORT * usLen ); +eMBException +eMBMasterFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen ); +eMBException +eMBMasterFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen ); +eMBException +eMBMasterFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen ); +eMBException +eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ); + +/*\ingroup modbus + *\brief These functions are interface for Modbus Master + */ +void vMBMasterGetPDUSndBuf( UCHAR ** pucFrame ); +UCHAR ucMBMasterGetDestAddress( void ); +void vMBMasterSetDestAddress( UCHAR Address ); +BOOL xMBMasterGetCBRunInMasterMode( void ); +void vMBMasterSetCBRunInMasterMode( BOOL IsMasterMode ); +USHORT usMBMasterGetPDUSndLength( void ); +void vMBMasterSetPDUSndLength( USHORT SendPDULength ); +void vMBMasterSetCurTimerMode( eMBMasterTimerMode eMBTimerMode ); +BOOL xMBMasterRequestIsBroadcast( void ); +eMBMasterErrorEventType eMBMasterGetErrorType( void ); +void vMBMasterSetErrorType( eMBMasterErrorEventType errorType ); +eMBMasterReqErrCode eMBMasterWaitRequestFinish( void ); + +/* ----------------------- Callback -----------------------------------------*/ + +#ifdef __cplusplus +PR_END_EXTERN_C +#endif +#endif diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mbconfig.h b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mbconfig.h similarity index 63% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mbconfig.h rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mbconfig.h index 26354b435..48a9d8c7e 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mbconfig.h +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mbconfig.h @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,6 +25,8 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mbconfig.h,v 1.14 2006/12/07 22:10:34 wolti Exp $ + * $Id: mbconfig.h,v 1.60 2013/08/13 21:19:55 Armink Add Master Functions $ */ #ifndef _MB_CONFIG_H @@ -42,17 +44,67 @@ PR_BEGIN_EXTERN_C * * All of these settings are available in the file mbconfig.h */ +#include + +#ifdef ADD_RTTHREAD_FEATURES +#include +#endif + /*! \addtogroup modbus_cfg * @{ */ -/*! \brief If Modbus ASCII support is enabled. */ -#define MB_ASCII_ENABLED ( 0 )//gai +/*! \brief If Modbus Master ASCII support is enabled. */ +#define MB_MASTER_ASCII_ENABLED ( 0 ) +/*! \brief If Modbus Master RTU support is enabled. */ +#define MB_MASTER_RTU_ENABLED ( 1 ) +/*! \brief If Modbus Master TCP support is enabled. */ +#define MB_MASTER_TCP_ENABLED ( 0 ) -/*! \brief If Modbus RTU support is enabled. */ -#define MB_RTU_ENABLED ( 1 ) +#ifdef ADD_RTTHREAD_FEATURES +/*! \brief If Modbus Slave ASCII support is enabled. */ +#ifdef PKG_MODBUS_SLAVE_ASCII +#define MB_SLAVE_ASCII_ENABLED ( 1 ) +#else +#define MB_SLAVE_ASCII_ENABLED ( 0 ) +#endif -/*! \brief If Modbus TCP support is enabled. */ -#define MB_TCP_ENABLED ( 0 ) +/*! \brief If Modbus Slave RTU support is enabled. */ +#ifdef PKG_MODBUS_SLAVE_RTU +#define MB_SLAVE_RTU_ENABLED ( 1 ) +#else +#define MB_SLAVE_RTU_ENABLED ( 0 ) +#endif + +/*! \brief If Modbus Slave TCP support is enabled. */ +#ifdef PKG_MODBUS_SLAVE_TCP +#define MB_SLAVE_TCP_ENABLED ( 1 ) +#else +#define MB_SLAVE_TCP_ENABLED ( 0 ) +#endif +#endif + +#ifdef ADD_XIZI_FEATURES +/*! \brief If Modbus Slave ASCII support is enabled. */ +#ifdef CONNECTION_MODBUS_USING_ASCII_SLAVE +#define MB_SLAVE_ASCII_ENABLED ( 1 ) +#else +#define MB_SLAVE_ASCII_ENABLED ( 0 ) +#endif + +/*! \brief If Modbus Slave RTU support is enabled. */ +#ifdef CONNECTION_MODBUS_USING_RTU_SLAVE +#define MB_SLAVE_RTU_ENABLED ( 1 ) +#else +#define MB_SLAVE_RTU_ENABLED ( 0 ) +#endif + +/*! \brief If Modbus Slave TCP support is enabled. */ +#ifdef CONNECTION_MODBUS_USING_TCP_SLAVE +#define MB_SLAVE_TCP_ENABLED ( 1 ) +#else +#define MB_SLAVE_TCP_ENABLED ( 0 ) +#endif +#endif /*! \brief The character timeout value for Modbus ASCII. * @@ -61,20 +113,6 @@ PR_BEGIN_EXTERN_C * time of the network. */ #define MB_ASCII_TIMEOUT_SEC ( 1 ) - -/*! \brief Timeout to wait in ASCII prior to enabling transmitter. - * - * If defined the function calls vMBPortSerialDelay with the argument - * MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS to allow for a delay before - * the serial transmitter is enabled. This is required because some - * targets are so fast that there is no time between receiving and - * transmitting the frame. If the master is to slow with enabling its - * receiver then he will not receive the response correctly. - */ -#ifndef MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS -#define MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS ( 0 ) -#endif - /*! \brief Maximum number of Modbus functions codes the protocol stack * should support. * @@ -83,7 +121,6 @@ PR_BEGIN_EXTERN_C * handlers. If set to small adding more functions will fail. */ #define MB_FUNC_HANDLERS_MAX ( 16 ) - /*! \brief Number of bytes which should be allocated for the Report Slave ID * command. * @@ -93,39 +130,42 @@ PR_BEGIN_EXTERN_C * is set to 1. */ #define MB_FUNC_OTHER_REP_SLAVEID_BUF ( 32 ) - /*! \brief If the Report Slave ID function should be enabled. */ #define MB_FUNC_OTHER_REP_SLAVEID_ENABLED ( 1 ) - /*! \brief If the Read Input Registers function should be enabled. */ #define MB_FUNC_READ_INPUT_ENABLED ( 1 ) - /*! \brief If the Read Holding Registers function should be enabled. */ #define MB_FUNC_READ_HOLDING_ENABLED ( 1 ) - /*! \brief If the Write Single Register function should be enabled. */ #define MB_FUNC_WRITE_HOLDING_ENABLED ( 1 ) - /*! \brief If the Write Multiple registers function should be enabled. */ #define MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED ( 1 ) - /*! \brief If the Read Coils function should be enabled. */ #define MB_FUNC_READ_COILS_ENABLED ( 1 ) - /*! \brief If the Write Coils function should be enabled. */ #define MB_FUNC_WRITE_COIL_ENABLED ( 1 ) - /*! \brief If the Write Multiple Coils function should be enabled. */ #define MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED ( 1 ) - /*! \brief If the Read Discrete Inputs function should be enabled. */ #define MB_FUNC_READ_DISCRETE_INPUTS_ENABLED ( 1 ) - /*! \brief If the Read/Write Multiple Registers function should be enabled. */ #define MB_FUNC_READWRITE_HOLDING_ENABLED ( 1 ) - /*! @} */ #ifdef __cplusplus PR_END_EXTERN_C #endif + +#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 +/*! \brief If master send a broadcast frame,the master will wait time of convert to delay, + * then master can send other frame */ +#define MB_MASTER_DELAY_MS_CONVERT (200 ) +/*! \brief If master send a frame which is not broadcast,the master will wait sometime for slave. + * And if slave is not respond in this time,the master will process this timeout error. + * Then master can send other frame */ +#define MB_MASTER_TIMEOUT_MS_RESPOND (100 ) +/*! \brief The total slaves in Modbus Master system. Default 16. + * \note : The slave ID must be continuous from 1.*/ +#define MB_MASTER_TOTAL_SLAVE_NUM ( 16 ) +#endif + #endif diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mbframe.h b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mbframe.h similarity index 98% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mbframe.h rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mbframe.h index 69a76989a..e20c57320 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mbframe.h +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mbframe.h @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,6 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mbframe.h,v 1.9 2006/12/07 22:10:34 wolti Exp $ */ #ifndef _MB_FRAME_H diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mbfunc.h b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mbfunc.h similarity index 95% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mbfunc.h rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mbfunc.h index ccf54efe2..f25241379 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mbfunc.h +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mbfunc.h @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,8 +25,9 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mbfunc.h,v 1.12 2006/12/07 22:10:34 wolti Exp $ */ - + #ifndef _MB_FUNC_H #define _MB_FUNC_H @@ -34,7 +35,7 @@ PR_BEGIN_EXTERN_C #endif #if MB_FUNC_OTHER_REP_SLAVEID_BUF > 0 - eMBException eMBFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen ); +eMBException eMBFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen ); #endif #if MB_FUNC_READ_INPUT_ENABLED > 0 diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mbport.h b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mbport.h similarity index 52% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mbport.h rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mbport.h index 3198f1be6..f86fcd0fd 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mbport.h +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mbport.h @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,6 +25,8 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mbport.h,v 1.17 2006/12/07 22:10:34 wolti Exp $ + * mbport.h,v 1.60 2013/08/17 11:42:56 Armink Add Master Functions $ */ #ifndef _MB_PORT_H @@ -34,16 +36,38 @@ PR_BEGIN_EXTERN_C #endif +/* ----------------------- Defines ------------------------------------------*/ + /* ----------------------- Type definitions ---------------------------------*/ typedef enum { - EV_READY, /*!< Startup finished. */ - EV_FRAME_RECEIVED, /*!< Frame received. */ - EV_EXECUTE, /*!< Execute function. */ - EV_FRAME_SENT /*!< Frame sent. */ + EV_READY = 1<<0, /*!< Startup finished. */ + EV_FRAME_RECEIVED = 1<<1, /*!< Frame received. */ + EV_EXECUTE = 1<<2, /*!< Execute function. */ + EV_FRAME_SENT = 1<<3 /*!< Frame sent. */ } eMBEventType; +typedef enum +{ + EV_MASTER_READY = 1<<0, /*!< Startup finished. */ + EV_MASTER_FRAME_RECEIVED = 1<<1, /*!< Frame received. */ + EV_MASTER_EXECUTE = 1<<2, /*!< Execute function. */ + EV_MASTER_FRAME_SENT = 1<<3, /*!< Frame sent. */ + EV_MASTER_ERROR_PROCESS = 1<<4, /*!< Frame error process. */ + EV_MASTER_PROCESS_SUCESS = 1<<5, /*!< Request process success. */ + EV_MASTER_ERROR_RESPOND_TIMEOUT = 1<<6, /*!< Request respond timeout. */ + EV_MASTER_ERROR_RECEIVE_DATA = 1<<7, /*!< Request receive data error. */ + EV_MASTER_ERROR_EXECUTE_FUNCTION = 1<<8, /*!< Request execute function error. */ +} eMBMasterEventType; + +typedef enum +{ + EV_ERROR_RESPOND_TIMEOUT, /*!< Slave respond timeout. */ + EV_ERROR_RECEIVE_DATA, /*!< Receive frame data erroe. */ + EV_ERROR_EXECUTE_FUNCTION, /*!< Execute function error. */ +} eMBMasterErrorEventType; + /*! \ingroup modbus * \brief Parity used for characters in serial mode. * @@ -65,6 +89,18 @@ BOOL xMBPortEventPost( eMBEventType eEvent ); BOOL xMBPortEventGet( /*@out@ */ eMBEventType * eEvent ); +BOOL xMBMasterPortEventInit( void ); + +BOOL xMBMasterPortEventPost( eMBMasterEventType eEvent ); + +BOOL xMBMasterPortEventGet( /*@out@ */ eMBMasterEventType * eEvent ); + +void vMBMasterOsResInit( void ); + +BOOL xMBMasterRunResTake( int32_t time ); + +void vMBMasterRunResRelease( void ); + /* ----------------------- Serial port functions ----------------------------*/ BOOL xMBPortSerialInit( UCHAR ucPort, ULONG ulBaudRate, @@ -76,20 +112,55 @@ void xMBPortSerialClose( void ); void vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable ); -BOOL xMBPortSerialGetByte( CHAR * pucByte ); +INLINE BOOL xMBPortSerialGetByte( CHAR * pucByte ); -BOOL xMBPortSerialPutByte( CHAR ucByte ); +INLINE BOOL xMBPortSerialPutByte( CHAR ucByte ); + +BOOL xMBMasterPortSerialInit( UCHAR ucPort, ULONG ulBaudRate, + UCHAR ucDataBits, eMBParity eParity ); + +void vMBMasterPortClose( void ); + +void xMBMasterPortSerialClose( void ); + +void vMBMasterPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable ); + +INLINE BOOL xMBMasterPortSerialGetByte( CHAR * pucByte ); + +INLINE BOOL xMBMasterPortSerialPutByte( CHAR ucByte ); /* ----------------------- Timers functions ---------------------------------*/ BOOL xMBPortTimersInit( USHORT usTimeOut50us ); void xMBPortTimersClose( void ); -void vMBPortTimersEnable( void ); +INLINE void vMBPortTimersEnable( void ); -void vMBPortTimersDisable( void ); +INLINE void vMBPortTimersDisable( void ); -void vMBPortTimersDelay( USHORT usTimeOutMS ); +BOOL xMBMasterPortTimersInit( USHORT usTimeOut50us ); + +void xMBMasterPortTimersClose( void ); + +INLINE void vMBMasterPortTimersT35Enable( void ); + +INLINE void vMBMasterPortTimersConvertDelayEnable( void ); + +INLINE void vMBMasterPortTimersRespondTimeoutEnable( void ); + +INLINE void vMBMasterPortTimersDisable( void ); + +/* ----------------- Callback for the master error process ------------------*/ +void vMBMasterErrorCBRespondTimeout( UCHAR ucDestAddress, const UCHAR* pucPDUData, + USHORT ucPDULength ); + +void vMBMasterErrorCBReceiveData( UCHAR ucDestAddress, const UCHAR* pucPDUData, + USHORT ucPDULength ); + +void vMBMasterErrorCBExecuteFunction( UCHAR ucDestAddress, const UCHAR* pucPDUData, + USHORT ucPDULength ); + +void vMBMasterCBRequestScuuess( void ); /* ----------------------- Callback for the protocol stack ------------------*/ @@ -105,12 +176,24 @@ void vMBPortTimersDelay( USHORT usTimeOutMS ); * a new byte was received. The port implementation should wake up the * tasks which are currently blocked on the eventqueue. */ -extern BOOL( *pxMBFrameCBByteReceived ) ( void ); - extern BOOL( *pxMBFrameCBTransmitterEmpty ) ( void ); extern BOOL( *pxMBPortCBTimerExpired ) ( void ); +#ifdef ADD_RTTHREAD_FEATURES +extern BOOL( *pxMBFrameCBByteReceived ) ( void ); +extern BOOL( *pxMBMasterFrameCBByteReceived ) ( void ); +#endif + +#ifdef ADD_XIZI_FEATURES +extern BOOL( *pxMBFrameCBByteReceived ) ( CHAR pucByte ); +extern BOOL( *pxMBMasterFrameCBByteReceived ) ( CHAR pucByte ); +#endif + +extern BOOL( *pxMBMasterFrameCBTransmitterEmpty ) ( void ); + +extern BOOL( *pxMBMasterPortCBTimerExpired ) ( void ); + /* ----------------------- TCP port functions -------------------------------*/ BOOL xMBTCPPortInit( USHORT usTCPPort ); diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mbproto.h b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mbproto.h similarity index 98% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mbproto.h rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mbproto.h index e2d14cf05..aef31981e 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mbproto.h +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mbproto.h @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,6 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mbproto.h,v 1.14 2006/12/07 22:10:34 wolti Exp $ */ #ifndef _MB_PROTO_H diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mbutils.h b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mbutils.h similarity index 98% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mbutils.h rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mbutils.h index 385b8c156..a504303e6 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/include/mbutils.h +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include/mbutils.h @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,6 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mbutils.h,v 1.5 2006/12/07 22:10:34 wolti Exp $ */ #ifndef _MB_UTILS_H diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/mb.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/mb.c similarity index 95% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/mb.c rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/mb.c index e2450cc79..b24099a20 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/mb.c +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/mb.c @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,6 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mb.c,v 1.27 2007/02/18 23:45:41 wolti Exp $ */ /* ----------------------- System includes ----------------------------------*/ @@ -35,6 +36,7 @@ #include "port.h" /* ----------------------- Modbus includes ----------------------------------*/ + #include "mb.h" #include "mbconfig.h" #include "mbframe.h" @@ -42,13 +44,13 @@ #include "mbfunc.h" #include "mbport.h" -#if MB_RTU_ENABLED == 1 +#if MB_SLAVE_RTU_ENABLED == 1 #include "mbrtu.h" #endif -#if MB_ASCII_ENABLED == 1 +#if MB_SLAVE_ASCII_ENABLED == 1 #include "mbascii.h" #endif -#if MB_TCP_ENABLED == 1 +#if MB_SLAVE_TCP_ENABLED == 1 #include "mbtcp.h" #endif @@ -70,6 +72,7 @@ static enum /* Functions pointer which are initialized in eMBInit( ). Depending on the * mode (RTU or ASCII) the are set to the correct implementations. + * Using for Modbus Slave */ static peMBFrameSend peMBFrameSendCur; static pvMBFrameStart pvMBFrameStartCur; @@ -80,8 +83,14 @@ static pvMBFrameClose pvMBFrameCloseCur; /* Callback functions required by the porting layer. They are called when * an external event has happend which includes a timeout or the reception * or transmission of a character. + * Using for Modbus Slave */ +#ifdef ADD_RTTHREAD_FEATURES BOOL( *pxMBFrameCBByteReceived ) ( void ); +#endif +#ifdef ADD_XIZI_FEATURES +BOOL( *pxMBFrameCBByteReceived ) ( CHAR pucByte ); +#endif BOOL( *pxMBFrameCBTransmitterEmpty ) ( void ); BOOL( *pxMBPortCBTimerExpired ) ( void ); @@ -142,9 +151,9 @@ eMBInit( eMBMode eMode, UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eM switch ( eMode ) { -#if MB_RTU_ENABLED > 0 +#if MB_SLAVE_RTU_ENABLED > 0 case MB_RTU: - pvMBFrameStartCur = eMBRTUStart;//回调 + pvMBFrameStartCur = eMBRTUStart; pvMBFrameStopCur = eMBRTUStop; peMBFrameSendCur = eMBRTUSend; peMBFrameReceiveCur = eMBRTUReceive; @@ -156,7 +165,7 @@ eMBInit( eMBMode eMode, UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eM eStatus = eMBRTUInit( ucMBAddress, ucPort, ulBaudRate, eParity ); break; #endif -#if MB_ASCII_ENABLED > 0 +#if MB_SLAVE_ASCII_ENABLED > 0 case MB_ASCII: pvMBFrameStartCur = eMBASCIIStart; pvMBFrameStopCur = eMBASCIIStop; @@ -172,6 +181,7 @@ eMBInit( eMBMode eMode, UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eM #endif default: eStatus = MB_EINVAL; + break; } if( eStatus == MB_ENOERR ) @@ -191,7 +201,7 @@ eMBInit( eMBMode eMode, UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eM return eStatus; } -#if MB_TCP_ENABLED > 0 +#if MB_SLAVE_TCP_ENABLED > 0 eMBErrorCode eMBTCPInit( USHORT ucTCPPort ) { @@ -287,15 +297,16 @@ eMBClose( void ) return eStatus; } + eMBErrorCode eMBEnable( void ) { eMBErrorCode eStatus = MB_ENOERR; - if( eMBState == STATE_DISABLED )//init完成 + if( eMBState == STATE_DISABLED ) { /* Activate the protocol stack. */ - pvMBFrameStartCur( );//函数指针,在init中指向了eMBRTUStart + pvMBFrameStartCur( ); eMBState = STATE_ENABLED; } else @@ -327,8 +338,7 @@ eMBDisable( void ) return eStatus; } -eMBErrorCode -eMBPoll( void ) +eMBErrorCode eMBPoll( void ) { static UCHAR *ucMBFrame; static UCHAR ucRcvAddress; @@ -395,10 +405,6 @@ eMBPoll( void ) ucMBFrame[usLength++] = ( UCHAR )( ucFunctionCode | MB_FUNC_ERROR ); ucMBFrame[usLength++] = eException; } - if( ( eMBCurrentMode == MB_ASCII ) && MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS ) - { - vMBPortTimersDelay( MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS ); - } eStatus = peMBFrameSendCur( ucMBAddress, ucMBFrame, usLength ); } break; diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/mb_m.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/mb_m.c new file mode 100644 index 000000000..7488a0d90 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/mb_m.c @@ -0,0 +1,431 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (C) 2013 Armink + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbrtu_m.c,v 1.60 2013/08/20 11:18:10 Armink Add Master Functions $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ + +#include "mb.h" +#include "mb_m.h" +#include "mbconfig.h" +#include "mbframe.h" +#include "mbproto.h" +#include "mbfunc.h" + +#include "mbport.h" +#if MB_MASTER_RTU_ENABLED == 1 +#include "mbrtu.h" +#endif +#if MB_MASTER_ASCII_ENABLED == 1 +#include "mbascii.h" +#endif +#if MB_MASTER_TCP_ENABLED == 1 +#include "mbtcp.h" +#endif + +#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 + +#ifndef MB_PORT_HAS_CLOSE +#define MB_PORT_HAS_CLOSE 0 +#endif + +/* ----------------------- Static variables ---------------------------------*/ + +static UCHAR ucMBMasterDestAddress; +static BOOL xMBRunInMasterMode = FALSE; +static eMBMasterErrorEventType eMBMasterCurErrorType; + +static enum +{ + STATE_ENABLED, + STATE_DISABLED, + STATE_NOT_INITIALIZED, + STATE_ESTABLISHED, +} eMBState = STATE_NOT_INITIALIZED; + +/* Functions pointer which are initialized in eMBInit( ). Depending on the + * mode (RTU or ASCII) the are set to the correct implementations. + * Using for Modbus Master,Add by Armink 20130813 + */ +static peMBFrameSend peMBMasterFrameSendCur; +static pvMBFrameStart pvMBMasterFrameStartCur; +static pvMBFrameStop pvMBMasterFrameStopCur; +static peMBFrameReceive peMBMasterFrameReceiveCur; +static pvMBFrameClose pvMBMasterFrameCloseCur; + +/* Callback functions required by the porting layer. They are called when + * an external event has happend which includes a timeout or the reception + * or transmission of a character. + * Using for Modbus Master,Add by Armink 20130813 + */ +#ifdef ADD_RTTHREAD_FEATURES +BOOL( *pxMBMasterFrameCBByteReceived ) ( void ); +#endif +#ifdef ADD_XIZI_FEATURES +BOOL( *pxMBMasterFrameCBByteReceived ) ( CHAR pucByte ); +#endif +BOOL( *pxMBMasterFrameCBTransmitterEmpty ) ( void ); +BOOL( *pxMBMasterPortCBTimerExpired ) ( void ); + +BOOL( *pxMBMasterFrameCBReceiveFSMCur ) ( void ); +BOOL( *pxMBMasterFrameCBTransmitFSMCur ) ( void ); + +/* An array of Modbus functions handlers which associates Modbus function + * codes with implementing functions. + */ +static xMBFunctionHandler xMasterFuncHandlers[MB_FUNC_HANDLERS_MAX] = { +#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED > 0 + //TODO Add Master function define + {MB_FUNC_OTHER_REPORT_SLAVEID, eMBFuncReportSlaveID}, +#endif +#if MB_FUNC_READ_INPUT_ENABLED > 0 + {MB_FUNC_READ_INPUT_REGISTER, eMBMasterFuncReadInputRegister}, +#endif +#if MB_FUNC_READ_HOLDING_ENABLED > 0 + {MB_FUNC_READ_HOLDING_REGISTER, eMBMasterFuncReadHoldingRegister}, +#endif +#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0 + {MB_FUNC_WRITE_MULTIPLE_REGISTERS, eMBMasterFuncWriteMultipleHoldingRegister}, +#endif +#if MB_FUNC_WRITE_HOLDING_ENABLED > 0 + {MB_FUNC_WRITE_REGISTER, eMBMasterFuncWriteHoldingRegister}, +#endif +#if MB_FUNC_READWRITE_HOLDING_ENABLED > 0 + {MB_FUNC_READWRITE_MULTIPLE_REGISTERS, eMBMasterFuncReadWriteMultipleHoldingRegister}, +#endif +#if MB_FUNC_READ_COILS_ENABLED > 0 + {MB_FUNC_READ_COILS, eMBMasterFuncReadCoils}, +#endif +#if MB_FUNC_WRITE_COIL_ENABLED > 0 + {MB_FUNC_WRITE_SINGLE_COIL, eMBMasterFuncWriteCoil}, +#endif +#if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0 + {MB_FUNC_WRITE_MULTIPLE_COILS, eMBMasterFuncWriteMultipleCoils}, +#endif +#if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED > 0 + {MB_FUNC_READ_DISCRETE_INPUTS, eMBMasterFuncReadDiscreteInputs}, +#endif +}; + +/* ----------------------- Start implementation -----------------------------*/ +eMBErrorCode +eMBMasterInit( eMBMode eMode, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ) +{ + eMBErrorCode eStatus = MB_ENOERR; + + switch (eMode) + { +#if MB_MASTER_RTU_ENABLED > 0 + case MB_RTU: + pvMBMasterFrameStartCur = eMBMasterRTUStart; + pvMBMasterFrameStopCur = eMBMasterRTUStop; + peMBMasterFrameSendCur = eMBMasterRTUSend; + peMBMasterFrameReceiveCur = eMBMasterRTUReceive; + pvMBMasterFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBMasterPortClose : NULL; + pxMBMasterFrameCBByteReceived = xMBMasterRTUReceiveFSM; + pxMBMasterFrameCBTransmitterEmpty = xMBMasterRTUTransmitFSM; + pxMBMasterPortCBTimerExpired = xMBMasterRTUTimerExpired; + + eStatus = eMBMasterRTUInit(ucPort, ulBaudRate, eParity); + break; +#endif +#if MB_MASTER_ASCII_ENABLED > 0 + case MB_ASCII: + pvMBMasterFrameStartCur = eMBMasterASCIIStart; + pvMBMasterFrameStopCur = eMBMasterASCIIStop; + peMBMasterFrameSendCur = eMBMasterASCIISend; + peMBMasterFrameReceiveCur = eMBMasterASCIIReceive; + pvMBMasterFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBMasterPortClose : NULL; + pxMBMasterFrameCBByteReceived = xMBMasterASCIIReceiveFSM; + pxMBMasterFrameCBTransmitterEmpty = xMBMasterASCIITransmitFSM; + pxMBMasterPortCBTimerExpired = xMBMasterASCIITimerT1SExpired; + + eStatus = eMBMasterASCIIInit(ucPort, ulBaudRate, eParity ); + break; +#endif + default: + eStatus = MB_EINVAL; + break; + } + + if (eStatus == MB_ENOERR) + { + if (!xMBMasterPortEventInit()) + { + /* port dependent event module initalization failed. */ + eStatus = MB_EPORTERR; + } + else + { + eMBState = STATE_DISABLED; + } + /* initialize the OS resource for modbus master. */ + vMBMasterOsResInit(); + } + return eStatus; +} + +eMBErrorCode +eMBMasterClose( void ) +{ + eMBErrorCode eStatus = MB_ENOERR; + + if( eMBState == STATE_DISABLED ) + { + if( pvMBMasterFrameCloseCur != NULL ) + { + pvMBMasterFrameCloseCur( ); + } + } + else + { + eStatus = MB_EILLSTATE; + } + return eStatus; +} + +eMBErrorCode +eMBMasterEnable( void ) +{ + eMBErrorCode eStatus = MB_ENOERR; + + if( eMBState == STATE_DISABLED ) + { + /* Activate the protocol stack. */ + pvMBMasterFrameStartCur( ); + eMBState = STATE_ENABLED; + } + else + { + eStatus = MB_EILLSTATE; + } + return eStatus; +} + +eMBErrorCode +eMBMasterDisable( void ) +{ + eMBErrorCode eStatus; + + if(( eMBState == STATE_ENABLED ) || ( eMBState == STATE_ESTABLISHED)) + { + pvMBMasterFrameStopCur( ); + eMBState = STATE_DISABLED; + eStatus = MB_ENOERR; + } + else if( eMBState == STATE_DISABLED ) + { + eStatus = MB_ENOERR; + } + else + { + eStatus = MB_EILLSTATE; + } + return eStatus; +} + +BOOL +eMBMasterIsEstablished( void ) +{ + if(eMBState == STATE_ESTABLISHED) + { + return TRUE; + } + else + { + return FALSE; + } +} + + +eMBErrorCode +eMBMasterPoll( void ) +{ + static UCHAR *ucMBFrame; + static UCHAR ucRcvAddress; + static UCHAR ucFunctionCode; + static USHORT usLength; + static eMBException eException; + + int i , j; + eMBErrorCode eStatus = MB_ENOERR; + eMBMasterEventType eEvent; + eMBMasterErrorEventType errorType; + + /* Check if the protocol stack is ready. */ + if(( eMBState != STATE_ENABLED ) && ( eMBState != STATE_ESTABLISHED)) + { + return MB_EILLSTATE; + } + + /* Check if there is a event available. If not return control to caller. + * Otherwise we will handle the event. */ + if( xMBMasterPortEventGet( &eEvent ) == TRUE ) + { + switch ( eEvent ) + { + case EV_MASTER_READY: + eMBState = STATE_ESTABLISHED; + break; + + case EV_MASTER_FRAME_RECEIVED: + eStatus = peMBMasterFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength ); + /* Check if the frame is for us. If not ,send an error process event. */ + if ( ( eStatus == MB_ENOERR ) && ( ucRcvAddress == ucMBMasterGetDestAddress() ) ) + { + ( void ) xMBMasterPortEventPost( EV_MASTER_EXECUTE ); + } + else + { + vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA); + ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); + } + break; + + case EV_MASTER_EXECUTE: + ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF]; + eException = MB_EX_ILLEGAL_FUNCTION; + /* If receive frame has exception .The receive function code highest bit is 1.*/ + if(ucFunctionCode >> 7) { + eException = (eMBException)ucMBFrame[MB_PDU_DATA_OFF]; + } + else + { + for (i = 0; i < MB_FUNC_HANDLERS_MAX; i++) + { + /* No more function handlers registered. Abort. */ + if (xMasterFuncHandlers[i].ucFunctionCode == 0) { + break; + } + else if (xMasterFuncHandlers[i].ucFunctionCode == ucFunctionCode) { + vMBMasterSetCBRunInMasterMode(TRUE); + /* If master request is broadcast, + * the master need execute function for all slave. + */ + if ( xMBMasterRequestIsBroadcast() ) { + usLength = usMBMasterGetPDUSndLength(); + for(j = 1; j <= MB_MASTER_TOTAL_SLAVE_NUM; j++){ + vMBMasterSetDestAddress(j); + eException = xMasterFuncHandlers[i].pxHandler(ucMBFrame, &usLength); + } + } + else { + eException = xMasterFuncHandlers[i].pxHandler(ucMBFrame, &usLength); + } + vMBMasterSetCBRunInMasterMode(FALSE); + break; + } + } + } + /* If master has exception ,Master will send error process.Otherwise the Master is idle.*/ + if (eException != MB_EX_NONE) { + vMBMasterSetErrorType(EV_ERROR_EXECUTE_FUNCTION); + ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); + } + else { + vMBMasterCBRequestScuuess( ); + vMBMasterRunResRelease( ); + } + break; + + case EV_MASTER_FRAME_SENT: + /* Master is busy now. */ + vMBMasterGetPDUSndBuf( &ucMBFrame ); + eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBFrame, usMBMasterGetPDUSndLength() ); + break; + + case EV_MASTER_ERROR_PROCESS: + /* Execute specified error process callback function. */ + errorType = eMBMasterGetErrorType(); + vMBMasterGetPDUSndBuf( &ucMBFrame ); + switch (errorType) { + case EV_ERROR_RESPOND_TIMEOUT: + vMBMasterErrorCBRespondTimeout(ucMBMasterGetDestAddress(), + ucMBFrame, usMBMasterGetPDUSndLength()); + break; + case EV_ERROR_RECEIVE_DATA: + vMBMasterErrorCBReceiveData(ucMBMasterGetDestAddress(), + ucMBFrame, usMBMasterGetPDUSndLength()); + break; + case EV_ERROR_EXECUTE_FUNCTION: + vMBMasterErrorCBExecuteFunction(ucMBMasterGetDestAddress(), + ucMBFrame, usMBMasterGetPDUSndLength()); + break; + } + vMBMasterRunResRelease(); + break; + + default: + break; + } + + } + return MB_ENOERR; +} + +/* Get whether the Modbus Master is run in master mode.*/ +BOOL xMBMasterGetCBRunInMasterMode( void ) +{ + return xMBRunInMasterMode; +} +/* Set whether the Modbus Master is run in master mode.*/ +void vMBMasterSetCBRunInMasterMode( BOOL IsMasterMode ) +{ + xMBRunInMasterMode = IsMasterMode; +} +/* Get Modbus Master send destination address. */ +UCHAR ucMBMasterGetDestAddress( void ) +{ + return ucMBMasterDestAddress; +} +/* Set Modbus Master send destination address. */ +void vMBMasterSetDestAddress( UCHAR Address ) +{ + ucMBMasterDestAddress = Address; +} +/* Get Modbus Master current error event type. */ +eMBMasterErrorEventType eMBMasterGetErrorType( void ) +{ + return eMBMasterCurErrorType; +} +/* Set Modbus Master current error event type. */ +void vMBMasterSetErrorType( eMBMasterErrorEventType errorType ) +{ + eMBMasterCurErrorType = errorType; +} + + + +#endif diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/rtu/Makefile b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/rtu/Makefile new file mode 100644 index 000000000..e7ef887a1 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/rtu/Makefile @@ -0,0 +1,11 @@ +SRC_FILES := mbcrc.c + +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_RTU_MASTER),y) + SRC_FILES += mbrtu_m.c +endif + +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_RTU_SLAVE),y) + SRC_FILES += mbrtu.c +endif + +include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/rtu/mbcrc.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/rtu/mbcrc.c similarity index 97% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/rtu/mbcrc.c rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/rtu/mbcrc.c index 2f8445d12..5ed2a8032 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/rtu/mbcrc.c +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/rtu/mbcrc.c @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,6 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mbcrc.c,v 1.7 2007/02/18 23:50:27 wolti Exp $ */ /* ----------------------- Platform includes --------------------------------*/ @@ -42,12 +43,12 @@ static const UCHAR aucCRCHi[] = { 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, @@ -63,12 +64,12 @@ static const UCHAR aucCRCLo[] = { 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, - 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, + 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, - 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, + 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/rtu/mbcrc.h b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/rtu/mbcrc.h similarity index 96% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/rtu/mbcrc.h rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/rtu/mbcrc.h index b182e69d3..92168c277 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/rtu/mbcrc.h +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/rtu/mbcrc.h @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,6 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mbcrc.h,v 1.5 2006/12/07 22:10:34 wolti Exp $ */ #ifndef _MB_CRC_H diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/rtu/mbrtu.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/rtu/mbrtu.c similarity index 88% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/rtu/mbrtu.c rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/rtu/mbrtu.c index 738bdf24f..43e2578f2 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/rtu/mbrtu.c +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/rtu/mbrtu.c @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,6 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mbrtu.c,v 1.18 2007/09/12 10:15:56 wolti Exp $ */ /* ----------------------- System includes ----------------------------------*/ @@ -130,9 +131,9 @@ eMBRTUStart( void ) * to STATE_RX_IDLE. This makes sure that we delay startup of the * modbus protocol stack until the bus is free. */ - eRcvState = STATE_RX_INIT;//初始化状态 - vMBPortSerialEnable( TRUE, FALSE );//使能接收,禁止发送 - vMBPortTimersEnable( );//启动定时器 + eRcvState = STATE_RX_INIT; + vMBPortSerialEnable( TRUE, FALSE ); + vMBPortTimersEnable( ); EXIT_CRITICAL_SECTION( ); } @@ -149,11 +150,16 @@ eMBRTUStop( void ) eMBErrorCode eMBRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength ) { - BOOL xFrameReceived = FALSE; eMBErrorCode eStatus = MB_ENOERR; ENTER_CRITICAL_SECTION( ); - assert( usRcvBufferPos < MB_SER_PDU_SIZE_MAX ); +#ifdef ADD_RTTHREAD_FEATURES + RT_ASSERT( usRcvBufferPos <= MB_SER_PDU_SIZE_MAX ); +#endif + +#ifdef ADD_XIZI_FEATURES + MB_CHECK( usRcvBufferPos <= MB_SER_PDU_SIZE_MAX ); +#endif /* Length and CRC check */ if( ( usRcvBufferPos >= MB_SER_PDU_SIZE_MIN ) @@ -171,7 +177,6 @@ eMBRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength ) /* Return the start of the Modbus PDU to the caller. */ *pucFrame = ( UCHAR * ) & ucRTUBuf[MB_SER_PDU_PDU_OFF]; - xFrameReceived = TRUE; } else { @@ -221,16 +226,29 @@ eMBRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength ) return eStatus; } +#ifdef ADD_RTTHREAD_FEATURES BOOL xMBRTUReceiveFSM( void ) +#endif +#ifdef ADD_XIZI_FEATURES +BOOL +xMBRTUReceiveFSM( CHAR pucByte ) +#endif { BOOL xTaskNeedSwitch = FALSE; UCHAR ucByte; - assert( eSndState == STATE_TX_IDLE ); +#ifdef ADD_RTTHREAD_FEATURES + RT_ASSERT( eSndState == STATE_TX_IDLE ); +#endif + +#ifdef ADD_XIZI_FEATURES + MB_CHECK( eSndState == STATE_TX_IDLE ); +#endif /* Always read the character. */ - ( void )xMBPortSerialGetByte( ( CHAR * ) & ucByte ); + // ( void )xMBPortSerialGetByte( ( CHAR * ) & ucByte ); + ucByte = pucByte; switch ( eRcvState ) { @@ -238,14 +256,14 @@ xMBRTUReceiveFSM( void ) * wait until the frame is finished. */ case STATE_RX_INIT: - vMBPortTimersEnable( ); + vMBPortTimersEnable( ); break; /* In the error state we wait until all characters in the * damaged frame are transmitted. */ case STATE_RX_ERROR: - vMBPortTimersEnable( ); + vMBPortTimersEnable( ); break; /* In the idle state we wait for a new character. If a character @@ -253,12 +271,13 @@ xMBRTUReceiveFSM( void ) * receiver is in the state STATE_RX_RECEIVCE. */ case STATE_RX_IDLE: + vMBPortTimersDisable( ); usRcvBufferPos = 0; ucRTUBuf[usRcvBufferPos++] = ucByte; eRcvState = STATE_RX_RCV; /* Enable t3.5 timers. */ - vMBPortTimersEnable( ); + vMBPortTimersEnable( ); break; /* We are currently receiving a frame. Reset the timer after @@ -275,7 +294,7 @@ xMBRTUReceiveFSM( void ) { eRcvState = STATE_RX_ERROR; } - vMBPortTimersEnable( ); + //vMBPortTimersEnable(); break; } return xTaskNeedSwitch; @@ -286,7 +305,13 @@ xMBRTUTransmitFSM( void ) { BOOL xNeedPoll = FALSE; - assert( eRcvState == STATE_RX_IDLE ); +#ifdef ADD_RTTHREAD_FEATURES + RT_ASSERT( eRcvState == STATE_RX_IDLE ); +#endif + +#ifdef ADD_XIZI_FEATURES + MB_CHECK( eRcvState == STATE_RX_IDLE ); +#endif switch ( eSndState ) { @@ -318,7 +343,7 @@ xMBRTUTransmitFSM( void ) return xNeedPoll; } -//定时中断发生,触发的函数 + BOOL xMBRTUTimerT35Expired( void ) { @@ -328,7 +353,7 @@ xMBRTUTimerT35Expired( void ) { /* Timer t35 expired. Startup phase is finished. */ case STATE_RX_INIT: - xNeedPoll = xMBPortEventPost( EV_READY );//事件类型赋值 + xNeedPoll = xMBPortEventPost( EV_READY ); break; /* A frame was received and t35 expired. Notify the listener that @@ -343,8 +368,16 @@ xMBRTUTimerT35Expired( void ) /* Function called in an illegal state. */ default: - assert( ( eRcvState == STATE_RX_INIT ) || +#ifdef ADD_RTTHREAD_FEATURES + RT_ASSERT( ( eRcvState == STATE_RX_INIT ) || ( eRcvState == STATE_RX_RCV ) || ( eRcvState == STATE_RX_ERROR ) ); +#endif + +#ifdef ADD_XIZI_FEATURES + MB_CHECK( ( eRcvState == STATE_RX_INIT ) || + ( eRcvState == STATE_RX_RCV ) || ( eRcvState == STATE_RX_ERROR ) ); +#endif + break; } vMBPortTimersDisable( ); diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/rtu/mbrtu.h b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/rtu/mbrtu.h similarity index 66% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/rtu/mbrtu.h rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/rtu/mbrtu.h index 698168712..d72a7a2b9 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/rtu/mbrtu.h +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/rtu/mbrtu.h @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,7 +25,10 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mbrtu.h,v 1.9 2006/12/07 22:10:34 wolti Exp $ + * File: $Id: mbrtu.h,v 1.60 2013/08/17 13:11:42 Armink Add Master Functions $ */ +#include "mbconfig.h" #ifndef _MB_RTU_H #define _MB_RTU_H @@ -33,17 +36,38 @@ #ifdef __cplusplus PR_BEGIN_EXTERN_C #endif - eMBErrorCode eMBRTUInit( UCHAR slaveAddress, UCHAR ucPort, ULONG ulBaudRate, - eMBParity eParity ); +eMBErrorCode eMBRTUInit( UCHAR slaveAddress, UCHAR ucPort, ULONG ulBaudRate, + eMBParity eParity ); void eMBRTUStart( void ); void eMBRTUStop( void ); eMBErrorCode eMBRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength ); eMBErrorCode eMBRTUSend( UCHAR slaveAddress, const UCHAR * pucFrame, USHORT usLength ); +#ifdef ADD_RTTHREAD_FEATURES BOOL xMBRTUReceiveFSM( void ); +#endif +#ifdef ADD_XIZI_FEATURES +BOOL xMBRTUReceiveFSM( CHAR pucByte ); +#endif BOOL xMBRTUTransmitFSM( void ); BOOL xMBRTUTimerT15Expired( void ); BOOL xMBRTUTimerT35Expired( void ); +#if MB_MASTER_RTU_ENABLED > 0 +eMBErrorCode eMBMasterRTUInit( UCHAR ucPort, ULONG ulBaudRate,eMBParity eParity ); +void eMBMasterRTUStart( void ); +void eMBMasterRTUStop( void ); +eMBErrorCode eMBMasterRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength ); +eMBErrorCode eMBMasterRTUSend( UCHAR slaveAddress, const UCHAR * pucFrame, USHORT usLength ); +BOOL xMBMasterRTUTransmitFSM( void ); +#ifdef ADD_RTTHREAD_FEATURES +BOOL xMBMasterRTUReceiveFSM( void ); +#endif +#ifdef ADD_XIZI_FEATURES +BOOL xMBMasterRTUReceiveFSM( CHAR pucByte ); +#endif +BOOL xMBMasterRTUTimerExpired( void ); +#endif + #ifdef __cplusplus PR_END_EXTERN_C #endif diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/rtu/mbrtu_m.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/rtu/mbrtu_m.c new file mode 100644 index 000000000..b4ac79496 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/rtu/mbrtu_m.c @@ -0,0 +1,486 @@ +/* + * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. + * Copyright (c) 2013 China Beijing Armink + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * File: $Id: mbrtu_m.c,v 1.60 2013/08/17 11:42:56 Armink Add Master Functions $ + */ + +/* ----------------------- System includes ----------------------------------*/ +#include "stdlib.h" +#include "string.h" + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mb_m.h" +#include "mbrtu.h" +#include "mbframe.h" + +#include "mbcrc.h" +#include "mbport.h" + +#if MB_MASTER_RTU_ENABLED > 0 +/* ----------------------- Defines ------------------------------------------*/ +#define MB_SER_PDU_SIZE_MIN 4 /*!< Minimum size of a Modbus RTU frame. */ +#define MB_SER_PDU_SIZE_MAX 256 /*!< Maximum size of a Modbus RTU frame. */ +#define MB_SER_PDU_SIZE_CRC 2 /*!< Size of CRC field in PDU. */ +#define MB_SER_PDU_ADDR_OFF 0 /*!< Offset of slave address in Ser-PDU. */ +#define MB_SER_PDU_PDU_OFF 1 /*!< Offset of Modbus-PDU in Ser-PDU. */ + +/* ----------------------- Type definitions ---------------------------------*/ +typedef enum +{ + STATE_M_RX_INIT, /*!< Receiver is in initial state. */ + STATE_M_RX_IDLE, /*!< Receiver is in idle state. */ + STATE_M_RX_RCV, /*!< Frame is beeing received. */ + STATE_M_RX_ERROR, /*!< If the frame is invalid. */ +} eMBMasterRcvState; + +typedef enum +{ + STATE_M_TX_IDLE, /*!< Transmitter is in idle state. */ + STATE_M_TX_XMIT, /*!< Transmitter is in transfer state. */ + STATE_M_TX_XFWR, /*!< Transmitter is in transfer finish and wait receive state. */ +} eMBMasterSndState; + +/* ----------------------- Static variables ---------------------------------*/ +static volatile eMBMasterSndState eSndState; +static volatile eMBMasterRcvState eRcvState; + +static volatile UCHAR ucMasterRTUSndBuf[MB_PDU_SIZE_MAX]; +static volatile UCHAR ucMasterRTURcvBuf[MB_SER_PDU_SIZE_MAX]; +static volatile USHORT usMasterSendPDULength; + +static volatile UCHAR *pucMasterSndBufferCur; +static volatile USHORT usMasterSndBufferCount; + +static volatile USHORT usMasterRcvBufferPos; +static volatile BOOL xFrameIsBroadcast = FALSE; + +static volatile eMBMasterTimerMode eMasterCurTimerMode; + +/* ----------------------- Start implementation -----------------------------*/ +eMBErrorCode +eMBMasterRTUInit(UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ) +{ + eMBErrorCode eStatus = MB_ENOERR; + ULONG usTimerT35_50us; + + ENTER_CRITICAL_SECTION( ); + + /* Modbus RTU uses 8 Databits. */ + if( xMBMasterPortSerialInit( ucPort, ulBaudRate, 8, eParity ) != TRUE ) + { + eStatus = MB_EPORTERR; + } + else + { + /* If baudrate > 19200 then we should use the fixed timer values + * t35 = 1750us. Otherwise t35 must be 3.5 times the character time. + */ + if( ulBaudRate > 19200 ) + { + usTimerT35_50us = 35; /* 1800us. */ + } + else + { + /* The timer reload value for a character is given by: + * + * ChTimeValue = Ticks_per_1s / ( Baudrate / 11 ) + * = 11 * Ticks_per_1s / Baudrate + * = 220000 / Baudrate + * The reload for t3.5 is 1.5 times this value and similary + * for t3.5. + */ + usTimerT35_50us = ( 7UL * 220000UL ) / ( 2UL * ulBaudRate ); + } + if( xMBMasterPortTimersInit( ( USHORT ) usTimerT35_50us ) != TRUE ) + { + eStatus = MB_EPORTERR; + } + } + EXIT_CRITICAL_SECTION( ); + + return eStatus; +} + +void +eMBMasterRTUStart( void ) +{ + ENTER_CRITICAL_SECTION( ); + /* Initially the receiver is in the state STATE_M_RX_INIT. we start + * the timer and if no character is received within t3.5 we change + * to STATE_M_RX_IDLE. This makes sure that we delay startup of the + * modbus protocol stack until the bus is free. + */ + eRcvState = STATE_M_RX_INIT; + vMBMasterPortSerialEnable( TRUE, FALSE ); + vMBMasterPortTimersT35Enable( ); + + EXIT_CRITICAL_SECTION( ); +} + +void +eMBMasterRTUStop( void ) +{ + ENTER_CRITICAL_SECTION( ); + vMBMasterPortSerialEnable( FALSE, FALSE ); + vMBMasterPortTimersDisable( ); + EXIT_CRITICAL_SECTION( ); +} + +eMBErrorCode +eMBMasterRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength ) +{ + eMBErrorCode eStatus = MB_ENOERR; + + ENTER_CRITICAL_SECTION( ); +#ifdef ADD_RTTHREAD_FEATURES + RT_ASSERT( usMasterRcvBufferPos < MB_SER_PDU_SIZE_MAX ); +#endif + +#ifdef ADD_XIZI_FEATURES + MB_CHECK( usMasterRcvBufferPos < MB_SER_PDU_SIZE_MAX ); +#endif + + /* Length and CRC check */ + if( ( usMasterRcvBufferPos >= MB_SER_PDU_SIZE_MIN ) + && ( usMBCRC16( ( UCHAR * ) ucMasterRTURcvBuf, usMasterRcvBufferPos ) == 0 ) ) + { + /* Save the address field. All frames are passed to the upper layed + * and the decision if a frame is used is done there. + */ + *pucRcvAddress = ucMasterRTURcvBuf[MB_SER_PDU_ADDR_OFF]; + + /* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus + * size of address field and CRC checksum. + */ + *pusLength = ( USHORT )( usMasterRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC ); + + /* Return the start of the Modbus PDU to the caller. */ + *pucFrame = ( UCHAR * ) & ucMasterRTURcvBuf[MB_SER_PDU_PDU_OFF]; + } + else + { + eStatus = MB_EIO; + } + + EXIT_CRITICAL_SECTION( ); + return eStatus; +} + +eMBErrorCode +eMBMasterRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength ) +{ + eMBErrorCode eStatus = MB_ENOERR; + USHORT usCRC16; + + if ( ucSlaveAddress > MB_MASTER_TOTAL_SLAVE_NUM ) return MB_EINVAL; + + ENTER_CRITICAL_SECTION( ); + + /* Check if the receiver is still in idle state. If not we where to + * slow with processing the received frame and the master sent another + * frame on the network. We have to abort sending the frame. + */ + if( eRcvState == STATE_M_RX_IDLE ) + { + /* First byte before the Modbus-PDU is the slave address. */ + pucMasterSndBufferCur = ( UCHAR * ) pucFrame - 1; + usMasterSndBufferCount = 1; + + /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */ + pucMasterSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress; + usMasterSndBufferCount += usLength; + + /* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */ + usCRC16 = usMBCRC16( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount ); + ucMasterRTUSndBuf[usMasterSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF ); + ucMasterRTUSndBuf[usMasterSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 ); + + /* Activate the transmitter. */ + eSndState = STATE_M_TX_XMIT; + vMBMasterPortSerialEnable( FALSE, TRUE ); + } + else + { + eStatus = MB_EIO; + } + EXIT_CRITICAL_SECTION( ); + return eStatus; +} + +#ifdef ADD_RTTHREAD_FEATURES +BOOL +xMBMasterRTUReceiveFSM( void ) +#endif +#ifdef ADD_XIZI_FEATURES +BOOL +xMBMasterRTUReceiveFSM( CHAR pucByte ) +#endif +{ + BOOL xTaskNeedSwitch = FALSE; + UCHAR ucByte; + +#ifdef ADD_RTTHREAD_FEATURES + RT_ASSERT(( eSndState == STATE_M_TX_IDLE ) || ( eSndState == STATE_M_TX_XFWR )); +#endif + +#ifdef ADD_XIZI_FEATURES + MB_CHECK(( eSndState == STATE_M_TX_IDLE ) || ( eSndState == STATE_M_TX_XFWR )); +#endif + + // /* Always read the character. */ + // ( void )xMBMasterPortSerialGetByte( ( CHAR * ) & ucByte ); + ucByte = pucByte; + + switch ( eRcvState ) + { + /* If we have received a character in the init state we have to + * wait until the frame is finished. + */ + case STATE_M_RX_INIT: + vMBMasterPortTimersT35Enable( ); + break; + + /* In the error state we wait until all characters in the + * damaged frame are transmitted. + */ + case STATE_M_RX_ERROR: + vMBMasterPortTimersT35Enable( ); + break; + + /* In the idle state we wait for a new character. If a character + * is received the t1.5 and t3.5 timers are started and the + * receiver is in the state STATE_RX_RECEIVCE and disable early + * the timer of respond timeout . + */ + case STATE_M_RX_IDLE: + /* In time of respond timeout,the receiver receive a frame. + * Disable timer of respond timeout and change the transmiter state to idle. + */ + vMBMasterPortTimersDisable( ); + eSndState = STATE_M_TX_IDLE; + + usMasterRcvBufferPos = 0; + ucMasterRTURcvBuf[usMasterRcvBufferPos++] = ucByte; + eRcvState = STATE_M_RX_RCV; + + /* Enable t3.5 timers. */ + vMBMasterPortTimersT35Enable( ); + break; + + /* We are currently receiving a frame. Reset the timer after + * every character received. If more than the maximum possible + * number of bytes in a modbus frame is received the frame is + * ignored. + */ + case STATE_M_RX_RCV: + if( usMasterRcvBufferPos < MB_SER_PDU_SIZE_MAX ) + { + ucMasterRTURcvBuf[usMasterRcvBufferPos++] = ucByte; + } + else + { + eRcvState = STATE_M_RX_ERROR; + } + //vMBMasterPortTimersT35Enable(); + break; + } + return xTaskNeedSwitch; +} + +BOOL +xMBMasterRTUTransmitFSM( void ) +{ + BOOL xNeedPoll = FALSE; + +#ifdef ADD_RTTHREAD_FEATURES + RT_ASSERT( eRcvState == STATE_M_RX_IDLE ); +#endif + +#ifdef ADD_XIZI_FEATURES + MB_CHECK( eRcvState == STATE_M_RX_IDLE ); +#endif + + switch ( eSndState ) + { + /* We should not get a transmitter event if the transmitter is in + * idle state. */ + case STATE_M_TX_IDLE: + /* enable receiver/disable transmitter. */ + vMBMasterPortSerialEnable( TRUE, FALSE ); + break; + + case STATE_M_TX_XMIT: + /* check if we are finished. */ + if( usMasterSndBufferCount != 0 ) + { + xMBMasterPortSerialPutByte( ( CHAR )*pucMasterSndBufferCur ); + pucMasterSndBufferCur++; /* next byte in sendbuffer. */ + usMasterSndBufferCount--; + } + else + { + xFrameIsBroadcast = ( ucMasterRTUSndBuf[MB_SER_PDU_ADDR_OFF] == MB_ADDRESS_BROADCAST ) ? TRUE : FALSE; + /* Disable transmitter. This prevents another transmit buffer + * empty interrupt. */ + vMBMasterPortSerialEnable( TRUE, FALSE ); + eSndState = STATE_M_TX_XFWR; + /* If the frame is broadcast ,master will enable timer of convert delay, + * else master will enable timer of respond timeout. */ + if ( xFrameIsBroadcast == TRUE ) + { + vMBMasterPortTimersConvertDelayEnable( ); + } + else + { + vMBMasterPortTimersRespondTimeoutEnable( ); + } + } + break; + + default: + break; + } + + return xNeedPoll; +} + +BOOL +xMBMasterRTUTimerExpired(void) +{ + BOOL xNeedPoll = FALSE; + + switch (eRcvState) + { + /* Timer t35 expired. Startup phase is finished. */ + case STATE_M_RX_INIT: + xNeedPoll = xMBMasterPortEventPost(EV_MASTER_READY); + break; + + /* A frame was received and t35 expired. Notify the listener that + * a new frame was received. */ + case STATE_M_RX_RCV: + xNeedPoll = xMBMasterPortEventPost(EV_MASTER_FRAME_RECEIVED); + break; + + /* An error occured while receiving the frame. */ + case STATE_M_RX_ERROR: + vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA); + xNeedPoll = xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); + break; + + /* Function called in an illegal state. */ + default: +#ifdef ADD_RTTHREAD_FEATURES + RT_ASSERT( + ( eRcvState == STATE_M_RX_INIT ) || ( eRcvState == STATE_M_RX_RCV ) || + ( eRcvState == STATE_M_RX_ERROR ) || ( eRcvState == STATE_M_RX_IDLE )); +#endif + +#ifdef ADD_XIZI_FEATURES + MB_CHECK( + ( eRcvState == STATE_M_RX_INIT ) || ( eRcvState == STATE_M_RX_RCV ) || + ( eRcvState == STATE_M_RX_ERROR ) || ( eRcvState == STATE_M_RX_IDLE )); +#endif + break; + } + eRcvState = STATE_M_RX_IDLE; + + switch (eSndState) + { + /* A frame was send finish and convert delay or respond timeout expired. + * If the frame is broadcast,The master will idle,and if the frame is not + * broadcast.Notify the listener process error.*/ + case STATE_M_TX_XFWR: + if ( xFrameIsBroadcast == FALSE ) { + vMBMasterSetErrorType(EV_ERROR_RESPOND_TIMEOUT); + xNeedPoll = xMBMasterPortEventPost(EV_MASTER_ERROR_PROCESS); + } + break; + /* Function called in an illegal state. */ + default: +#ifdef ADD_RTTHREAD_FEATURES + RT_ASSERT( + ( eSndState == STATE_M_TX_XFWR ) || ( eSndState == STATE_M_TX_IDLE )); +#endif + +#ifdef ADD_XIZI_FEATURES + MB_CHECK( + ( eSndState == STATE_M_TX_XFWR ) || ( eSndState == STATE_M_TX_IDLE )); +#endif + break; + } + eSndState = STATE_M_TX_IDLE; + + vMBMasterPortTimersDisable( ); + /* If timer mode is convert delay, the master event then turns EV_MASTER_EXECUTE status. */ + if (eMasterCurTimerMode == MB_TMODE_CONVERT_DELAY) { + xNeedPoll = xMBMasterPortEventPost( EV_MASTER_EXECUTE ); + } + + return xNeedPoll; +} + +/* Get Modbus Master send RTU's buffer address pointer.*/ +void vMBMasterGetRTUSndBuf( UCHAR ** pucFrame ) +{ + *pucFrame = ( UCHAR * ) ucMasterRTUSndBuf; +} + +/* Get Modbus Master send PDU's buffer address pointer.*/ +void vMBMasterGetPDUSndBuf( UCHAR ** pucFrame ) +{ + *pucFrame = ( UCHAR * ) &ucMasterRTUSndBuf[MB_SER_PDU_PDU_OFF]; +} + +/* Set Modbus Master send PDU's buffer length.*/ +void vMBMasterSetPDUSndLength( USHORT SendPDULength ) +{ + usMasterSendPDULength = SendPDULength; +} + +/* Get Modbus Master send PDU's buffer length.*/ +USHORT usMBMasterGetPDUSndLength( void ) +{ + return usMasterSendPDULength; +} + +/* Set Modbus Master current timer mode.*/ +void vMBMasterSetCurTimerMode( eMBMasterTimerMode eMBTimerMode ) +{ + eMasterCurTimerMode = eMBTimerMode; +} + +/* The master request is broadcast? */ +BOOL xMBMasterRequestIsBroadcast( void ){ + return xFrameIsBroadcast; +} +#endif + diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/tcp/Makefile b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/tcp/Makefile new file mode 100644 index 000000000..c5ee2262a --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/tcp/Makefile @@ -0,0 +1,5 @@ +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_TCP_SLAVE),y) + SRC_FILES := mbtcp.c +endif + +include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/tcp/mbtcp.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/tcp/mbtcp.c similarity index 95% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/tcp/mbtcp.c rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/tcp/mbtcp.c index 5a75fda67..e6ce040b2 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/tcp/mbtcp.c +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/tcp/mbtcp.c @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,6 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mbtcp.c,v 1.3 2006/12/07 22:10:34 wolti Exp $ */ /* ----------------------- System includes ----------------------------------*/ @@ -41,7 +42,7 @@ #include "mbframe.h" #include "mbport.h" -#if MB_TCP_ENABLED > 0 +#if MB_SLAVE_TCP_ENABLED > 0 /* ----------------------- Defines ------------------------------------------*/ @@ -53,10 +54,10 @@ * +-----------+---------------+------------------------------------------+ * | TID | PID | Length | UID |Code | Data | * +-----------+---------------+------------------------------------------+ - * | | | | | - * (2) (3) (4) (5) (6) + * | | | | | + * (2) (3) (4) (5) (6) * - * (2) ... MB_TCP_TID = 0 (Transaction Identifier - 2 Byte) + * (2) ... MB_TCP_TID = 0 (Transaction Identifier - 2 Byte) * (3) ... MB_TCP_PID = 2 (Protocol Identifier - 2 Byte) * (4) ... MB_TCP_LEN = 4 (Number of bytes - 2 Byte) * (5) ... MB_TCP_UID = 6 (Unit Identifier - 1 Byte) @@ -140,9 +141,9 @@ eMBTCPSend( UCHAR _unused, const UCHAR * pucFrame, USHORT usLength ) USHORT usTCPLength = usLength + MB_TCP_FUNC; /* The MBAP header is already initialized because the caller calls this - * function with the buffer returned by the previous call. Therefore we - * only have to update the length in the header. Note that the length - * header includes the size of the Modbus PDU and the UID Byte. Therefore + * function with the buffer returned by the previous call. Therefore we + * only have to update the length in the header. Note that the length + * header includes the size of the Modbus PDU and the UID Byte. Therefore * the length is usLength plus one. */ pucMBTCPFrame[MB_TCP_LEN] = ( usLength + 1 ) >> 8U; diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/tcp/mbtcp.h b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/tcp/mbtcp.h similarity index 97% rename from APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/tcp/mbtcp.h rename to APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/tcp/mbtcp.h index 16b651ee5..7818b7667 100644 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/FreeModbus/modbus/tcp/mbtcp.h +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/tcp/mbtcp.h @@ -1,4 +1,4 @@ -/* +/* * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. * Copyright (c) 2006-2018 Christian Walter * All rights reserved. @@ -25,6 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * File: $Id: mbtcp.h,v 1.2 2006/12/07 22:10:34 wolti Exp $ */ #ifndef _MB_TCP_H diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/Makefile b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/Makefile new file mode 100644 index 000000000..ef2d1c301 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/Makefile @@ -0,0 +1,15 @@ +SRC_FILES := port.c + +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_RTU_MASTER),y) + SRC_FILES += portevent_m.c portserial_m.c porttimer_m.c user_mb_app_m.c +endif + +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_RTU_SLAVE),y) + SRC_FILES += portevent.c portserial.c porttimer.c user_mb_app.c +endif + +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_TCP_SLAVE),y) + SRC_FILES += porttcp.c portevent.c porttimer.c user_mb_app.c +endif + +include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/port.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/port.c new file mode 100644 index 000000000..bcfb1c852 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/port.c @@ -0,0 +1,92 @@ + /* + * FreeModbus Libary: RT-Thread Port + * Copyright (C) 2013 Armink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * File: $Id: port.c,v 1.60 2015/02/01 9:18:05 Armink $ + */ + +/** +* @file port.c +* @brief support freemodbus port for XiUOS +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-10-12 +*/ + +/************************************************* +File name: port.c +Description: support freemodbus port for XiUOS +Others: +History: +1. Date: 2023-10-12 +Author: AIIT XUOS Lab +Modification: +1、support XiUOS sem. +*************************************************/ + +/* ----------------------- System includes --------------------------------*/ + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "port.h" +/* ----------------------- Variables ----------------------------------------*/ +#ifdef ADD_RTTHREAD_FEATURES +static struct rt_semaphore lock; +#endif + +#ifdef ADD_XIZI_FEATURES +static sem_t sem; +#endif + +static int is_inited = 0; +/* ----------------------- Start implementation -----------------------------*/ +#ifdef ADD_RTTHREAD_FEATURES +void EnterCriticalSection(void) +{ + rt_err_t err; + if(!is_inited) + { + err = rt_sem_init(&lock, "fmb_lock", 1, RT_IPC_FLAG_PRIO); + if(err != RT_EOK) + { + rt_kprintf("Freemodbus Critical init failed!\n"); + } + is_inited = 1; + } + rt_sem_take(&lock, RT_WAITING_FOREVER); +} + +void ExitCriticalSection(void) +{ + rt_sem_release(&lock); +} +#endif + +#ifdef ADD_XIZI_FEATURES +void EnterCriticalSection(void) +{ + if(!is_inited) { + PrivSemaphoreCreate(&sem, 0, 1); + is_inited = 1; + } + PrivSemaphoreObtainWait(&sem, NULL); +} + +void ExitCriticalSection(void) +{ + PrivSemaphoreAbandon(&sem); +} +#endif diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/port.h b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/port.h new file mode 100644 index 000000000..28a5dec25 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/port.h @@ -0,0 +1,95 @@ +/* + * FreeModbus Libary: BARE Port + * Copyright (C) 2013 Armink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * File: $Id: port.h ,v 1.60 2013/08/13 15:07:05 Armink add Master Functions $ + */ + +/** +* @file port.h +* @brief support freemodbus port for XiUOS +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-10-12 +*/ + +/************************************************* +File name: port.h +Description: support freemodbus port for XiUOS +Others: +History: +1. Date: 2023-10-12 +Author: AIIT XUOS Lab +Modification: +1、add transform.h to support XiUOS. +*************************************************/ + +#ifndef _PORT_H +#define _PORT_H + +#include +#include "mbconfig.h" + +#ifdef ADD_RTTHREAD_FEATURES +#include +#include +#endif + +#include +#include + +#define INLINE +#define PR_BEGIN_EXTERN_C extern "C" { +#define PR_END_EXTERN_C } + +#define ENTER_CRITICAL_SECTION() EnterCriticalSection() +#define EXIT_CRITICAL_SECTION() ExitCriticalSection() + +typedef uint8_t BOOL; + +typedef unsigned char UCHAR; +typedef char CHAR; + +typedef uint16_t USHORT; +typedef int16_t SHORT; + +typedef uint32_t ULONG; +typedef int32_t LONG; + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifdef ADD_XIZI_FEATURES +#define MB_CHECK(TRUE_CONDITION) \ + do { \ + if (!(TRUE_CONDITION)) { \ + KPrintf("%s CHECK condition is false at line[%d] of [%s] func.\n", #TRUE_CONDITION, __LINE__, __FUNCTION__); \ + while (RET_TRUE) \ + ; \ + } \ + } while (0) +#endif + +void EnterCriticalSection(void); +void ExitCriticalSection(void); + +#endif diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/portevent.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/portevent.c new file mode 100644 index 000000000..0ac6536ad --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/portevent.c @@ -0,0 +1,136 @@ +/* + * FreeModbus Libary: RT-Thread Port + * Copyright (C) 2013 Armink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * File: $Id: portevent.c,v 1.60 2013/08/13 15:07:05 Armink $ + */ + +/** +* @file portevent.c +* @brief support freemodbus port for XiUOS +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-10-12 +*/ + +/************************************************* +File name: portevent.c +Description: support freemodbus port for XiUOS +Others: +History: +1. Date: 2023-10-12 +Author: AIIT XUOS Lab +Modification: +1、support XiUOS event for slave. +*************************************************/ + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mbport.h" + +#ifdef ADD_RTTHREAD_FEATURES +/* ----------------------- Variables ----------------------------------------*/ +static struct rt_event xSlaveOsEvent; +/* ----------------------- Start implementation -----------------------------*/ +BOOL +xMBPortEventInit( void ) +{ + rt_event_init(&xSlaveOsEvent,"slave event",RT_IPC_FLAG_PRIO); + return TRUE; +} + +BOOL +xMBPortEventPost( eMBEventType eEvent ) +{ + rt_event_send(&xSlaveOsEvent, eEvent); + return TRUE; +} + +BOOL +xMBPortEventGet( eMBEventType * eEvent ) +{ + rt_uint32_t recvedEvent; + /* waiting forever OS event */ + rt_event_recv(&xSlaveOsEvent, + EV_READY | EV_FRAME_RECEIVED | EV_EXECUTE | EV_FRAME_SENT, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, + &recvedEvent); + switch (recvedEvent) + { + case EV_READY: + *eEvent = EV_READY; + break; + case EV_FRAME_RECEIVED: + *eEvent = EV_FRAME_RECEIVED; + break; + case EV_EXECUTE: + *eEvent = EV_EXECUTE; + break; + case EV_FRAME_SENT: + *eEvent = EV_FRAME_SENT; + break; + } + return TRUE; +} +#endif + +#ifdef ADD_XIZI_FEATURES +/* ----------------------- Variables ----------------------------------------*/ +static int xSlaveOsEvent; +/* ----------------------- Start implementation -----------------------------*/ +BOOL +xMBPortEventInit( void ) +{ + xSlaveOsEvent = PrivEventCreate(LINKLIST_FLAG_PRIO); + return TRUE; +} + +BOOL +xMBPortEventPost( eMBEventType eEvent ) +{ + PrivEvenTrigger(xSlaveOsEvent, eEvent); + return TRUE; +} + +BOOL +xMBPortEventGet( eMBEventType * eEvent ) +{ + unsigned int recvedEvent; + + /* waiting forever OS event */ + PrivEventProcess(xSlaveOsEvent, + EV_READY | EV_FRAME_RECEIVED | EV_EXECUTE | EV_FRAME_SENT, + EVENT_OR | EVENT_AUTOCLEAN, 0, &recvedEvent); + + switch (recvedEvent) + { + case EV_READY: + *eEvent = EV_READY; + break; + case EV_FRAME_RECEIVED: + *eEvent = EV_FRAME_RECEIVED; + break; + case EV_EXECUTE: + *eEvent = EV_EXECUTE; + break; + case EV_FRAME_SENT: + *eEvent = EV_FRAME_SENT; + break; + } + return TRUE; +} +#endif diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/portevent_m.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/portevent_m.c new file mode 100644 index 000000000..97489625a --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/portevent_m.c @@ -0,0 +1,483 @@ +/* + * FreeModbus Libary: RT-Thread Port + * Copyright (C) 2013 Armink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * File: $Id: portevent_m.c v 1.60 2013/08/13 15:07:05 Armink add Master Functions$ + */ + +/** +* @file portevent_m.c +* @brief support freemodbus port for XiUOS +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-10-12 +*/ + +/************************************************* +File name: portevent_m.c +Description: support freemodbus port for XiUOS +Others: +History: +1. Date: 2023-10-12 +Author: AIIT XUOS Lab +Modification: +1、support XiUOS event for master. +*************************************************/ + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mb_m.h" +#include "mbport.h" +#include "port.h" + +#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 + +#ifdef ADD_RTTHREAD_FEATURES +/* ----------------------- Defines ------------------------------------------*/ +/* ----------------------- Variables ----------------------------------------*/ +static struct rt_semaphore xMasterRunRes; +static struct rt_event xMasterOsEvent; +/* ----------------------- Start implementation -----------------------------*/ +BOOL +xMBMasterPortEventInit( void ) +{ + rt_event_init(&xMasterOsEvent,"master event",RT_IPC_FLAG_PRIO); + return TRUE; +} + +BOOL +xMBMasterPortEventPost( eMBMasterEventType eEvent ) +{ + rt_event_send(&xMasterOsEvent, eEvent); + return TRUE; +} + +BOOL +xMBMasterPortEventGet( eMBMasterEventType * eEvent ) +{ + rt_uint32_t recvedEvent; + + /* waiting forever OS event */ + rt_event_recv(&xMasterOsEvent, + EV_MASTER_READY | EV_MASTER_FRAME_RECEIVED | EV_MASTER_EXECUTE | + EV_MASTER_FRAME_SENT | EV_MASTER_ERROR_PROCESS, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, + &recvedEvent); + + /* the enum type couldn't convert to int type */ + switch (recvedEvent) + { + case EV_MASTER_READY: + *eEvent = EV_MASTER_READY; + break; + case EV_MASTER_FRAME_RECEIVED: + *eEvent = EV_MASTER_FRAME_RECEIVED; + break; + case EV_MASTER_EXECUTE: + *eEvent = EV_MASTER_EXECUTE; + break; + case EV_MASTER_FRAME_SENT: + *eEvent = EV_MASTER_FRAME_SENT; + break; + case EV_MASTER_ERROR_PROCESS: + *eEvent = EV_MASTER_ERROR_PROCESS; + break; + default: + *eEvent = EV_MASTER_FRAME_RECEIVED; + break; + } + return TRUE; +} +/** + * This function is initialize the OS resource for modbus master. + * Note:The resource is define by OS.If you not use OS this function can be empty. + * + */ +void vMBMasterOsResInit( void ) +{ + rt_sem_init(&xMasterRunRes, "master res", 0x01 , RT_IPC_FLAG_PRIO); +} + +/** + * This function is take Mobus Master running resource. + * Note:The resource is define by Operating System.If you not use OS this function can be just return TRUE. + * + * @param lTimeOut the waiting time. + * + * @return resource taked result + */ +BOOL xMBMasterRunResTake( LONG lTimeOut ) +{ + /*If waiting time is -1 .It will wait forever */ + return rt_sem_take(&xMasterRunRes, lTimeOut) ? FALSE : TRUE ; +} + +/** + * This function is release Mobus Master running resource. + * Note:The resource is define by Operating System.If you not use OS this function can be empty. + * + */ +void vMBMasterRunResRelease( void ) +{ + /* release resource */ + rt_sem_release(&xMasterRunRes); +} + +/** + * This is modbus master respond timeout error process callback function. + * @note There functions will block modbus master poll while execute OS waiting. + * So,for real-time of system.Do not execute too much waiting process. + * + * @param ucDestAddress destination salve address + * @param pucPDUData PDU buffer data + * @param ucPDULength PDU buffer length + * + */ +void vMBMasterErrorCBRespondTimeout(UCHAR ucDestAddress, const UCHAR* pucPDUData, + USHORT ucPDULength) { + /** + * @note This code is use OS's event mechanism for modbus master protocol stack. + * If you don't use OS, you can change it. + */ + rt_event_send(&xMasterOsEvent, EV_MASTER_ERROR_RESPOND_TIMEOUT); + + /* You can add your code under here. */ + +} + +/** + * This is modbus master receive data error process callback function. + * @note There functions will block modbus master poll while execute OS waiting. + * So,for real-time of system.Do not execute too much waiting process. + * + * @param ucDestAddress destination salve address + * @param pucPDUData PDU buffer data + * @param ucPDULength PDU buffer length + * + */ +void vMBMasterErrorCBReceiveData(UCHAR ucDestAddress, const UCHAR* pucPDUData, + USHORT ucPDULength) { + /** + * @note This code is use OS's event mechanism for modbus master protocol stack. + * If you don't use OS, you can change it. + */ + rt_event_send(&xMasterOsEvent, EV_MASTER_ERROR_RECEIVE_DATA); + + /* You can add your code under here. */ + +} + +/** + * This is modbus master execute function error process callback function. + * @note There functions will block modbus master poll while execute OS waiting. + * So,for real-time of system.Do not execute too much waiting process. + * + * @param ucDestAddress destination salve address + * @param pucPDUData PDU buffer data + * @param ucPDULength PDU buffer length + * + */ +void vMBMasterErrorCBExecuteFunction(UCHAR ucDestAddress, const UCHAR* pucPDUData, + USHORT ucPDULength) { + /** + * @note This code is use OS's event mechanism for modbus master protocol stack. + * If you don't use OS, you can change it. + */ + rt_event_send(&xMasterOsEvent, EV_MASTER_ERROR_EXECUTE_FUNCTION); + + /* You can add your code under here. */ + +} + +/** + * This is modbus master request process success callback function. + * @note There functions will block modbus master poll while execute OS waiting. + * So,for real-time of system.Do not execute too much waiting process. + * + */ +void vMBMasterCBRequestScuuess( void ) { + /** + * @note This code is use OS's event mechanism for modbus master protocol stack. + * If you don't use OS, you can change it. + */ + rt_event_send(&xMasterOsEvent, EV_MASTER_PROCESS_SUCESS); + + /* You can add your code under here. */ + +} + +/** + * This function is wait for modbus master request finish and return result. + * Waiting result include request process success, request respond timeout, + * receive data error and execute function error.You can use the above callback function. + * @note If you are use OS, you can use OS's event mechanism. Otherwise you have to run + * much user custom delay for waiting. + * + * @return request error code + */ +eMBMasterReqErrCode eMBMasterWaitRequestFinish( void ) { + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + rt_uint32_t recvedEvent; + /* waiting for OS event */ + rt_event_recv(&xMasterOsEvent, + EV_MASTER_PROCESS_SUCESS | EV_MASTER_ERROR_RESPOND_TIMEOUT + | EV_MASTER_ERROR_RECEIVE_DATA + | EV_MASTER_ERROR_EXECUTE_FUNCTION, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, + &recvedEvent); + switch (recvedEvent) + { + case EV_MASTER_PROCESS_SUCESS: + break; + case EV_MASTER_ERROR_RESPOND_TIMEOUT: + { + eErrStatus = MB_MRE_TIMEDOUT; + break; + } + case EV_MASTER_ERROR_RECEIVE_DATA: + { + eErrStatus = MB_MRE_REV_DATA; + break; + } + case EV_MASTER_ERROR_EXECUTE_FUNCTION: + { + eErrStatus = MB_MRE_EXE_FUN; + break; + } + } + return eErrStatus; +} +#endif + +#ifdef ADD_XIZI_FEATURES +/* ----------------------- Defines ------------------------------------------*/ +/* ----------------------- Variables ----------------------------------------*/ +static sem_t xMasterRunRes; +static int xMasterOsEvent; +/* ----------------------- Start implementation -----------------------------*/ +BOOL +xMBMasterPortEventInit( void ) +{ + xMasterOsEvent = PrivEventCreate(LINKLIST_FLAG_PRIO); + return TRUE; +} + +BOOL +xMBMasterPortEventPost( eMBMasterEventType eEvent ) +{ + PrivEvenTrigger(xMasterOsEvent, eEvent); + return TRUE; +} + +BOOL +xMBMasterPortEventGet( eMBMasterEventType * eEvent ) +{ + unsigned int recvedEvent = EV_MASTER_ERROR_PROCESS; + + /* waiting forever OS event */ + PrivEventProcess(xMasterOsEvent, + EV_MASTER_READY | EV_MASTER_FRAME_RECEIVED | EV_MASTER_EXECUTE | + EV_MASTER_FRAME_SENT | EV_MASTER_ERROR_PROCESS, + EVENT_OR | EVENT_AUTOCLEAN, 0, &recvedEvent); + + /* the enum type couldn't convert to int type */ + switch (recvedEvent) + { + case EV_MASTER_READY: + *eEvent = EV_MASTER_READY; + break; + case EV_MASTER_FRAME_RECEIVED: + *eEvent = EV_MASTER_FRAME_RECEIVED; + break; + case EV_MASTER_EXECUTE: + *eEvent = EV_MASTER_EXECUTE; + break; + case EV_MASTER_FRAME_SENT: + *eEvent = EV_MASTER_FRAME_SENT; + break; + case EV_MASTER_ERROR_PROCESS: + *eEvent = EV_MASTER_ERROR_PROCESS; + break; + default: + *eEvent = EV_MASTER_FRAME_RECEIVED; + break; + } + return TRUE; +} +/** + * This function is initialize the OS resource for modbus master. + * Note:The resource is define by OS.If you not use OS this function can be empty. + * + */ +void vMBMasterOsResInit( void ) +{ + PrivSemaphoreCreate(&xMasterRunRes, 0, 1); +} + +/** + * This function is take Mobus Master running resource. + * Note:The resource is define by Operating System.If you not use OS this function can be just return TRUE. + * + * @param lTimeOut the waiting time. + * + * @return resource taked result + */ +BOOL xMBMasterRunResTake( LONG lTimeOut ) +{ + /*If waiting time is -1 .It will wait forever */ + return PrivSemaphoreObtainWait(&xMasterRunRes, NULL) ? FALSE : TRUE ; +} + +/** + * This function is release Mobus Master running resource. + * Note:The resource is define by Operating System.If you not use OS this function can be empty. + * + */ +void vMBMasterRunResRelease( void ) +{ + /* release resource */ + PrivSemaphoreAbandon(&xMasterRunRes); +} + +/** + * This is modbus master respond timeout error process callback function. + * @note There functions will block modbus master poll while execute OS waiting. + * So,for real-time of system.Do not execute too much waiting process. + * + * @param ucDestAddress destination salve address + * @param pucPDUData PDU buffer data + * @param ucPDULength PDU buffer length + * + */ +void vMBMasterErrorCBRespondTimeout(UCHAR ucDestAddress, const UCHAR* pucPDUData, + USHORT ucPDULength) { + /** + * @note This code is use OS's event mechanism for modbus master protocol stack. + * If you don't use OS, you can change it. + */ + PrivEvenTrigger(xMasterOsEvent, EV_MASTER_ERROR_RESPOND_TIMEOUT); + + /* You can add your code under here. */ + +} + +/** + * This is modbus master receive data error process callback function. + * @note There functions will block modbus master poll while execute OS waiting. + * So,for real-time of system.Do not execute too much waiting process. + * + * @param ucDestAddress destination salve address + * @param pucPDUData PDU buffer data + * @param ucPDULength PDU buffer length + * + */ +void vMBMasterErrorCBReceiveData(UCHAR ucDestAddress, const UCHAR* pucPDUData, + USHORT ucPDULength) { + /** + * @note This code is use OS's event mechanism for modbus master protocol stack. + * If you don't use OS, you can change it. + */ + PrivEvenTrigger(xMasterOsEvent, EV_MASTER_ERROR_RECEIVE_DATA); + + /* You can add your code under here. */ + +} + +/** + * This is modbus master execute function error process callback function. + * @note There functions will block modbus master poll while execute OS waiting. + * So,for real-time of system.Do not execute too much waiting process. + * + * @param ucDestAddress destination salve address + * @param pucPDUData PDU buffer data + * @param ucPDULength PDU buffer length + * + */ +void vMBMasterErrorCBExecuteFunction(UCHAR ucDestAddress, const UCHAR* pucPDUData, + USHORT ucPDULength) { + /** + * @note This code is use OS's event mechanism for modbus master protocol stack. + * If you don't use OS, you can change it. + */ + PrivEvenTrigger(xMasterOsEvent, EV_MASTER_ERROR_EXECUTE_FUNCTION); + + /* You can add your code under here. */ + +} + +/** + * This is modbus master request process success callback function. + * @note There functions will block modbus master poll while execute OS waiting. + * So,for real-time of system.Do not execute too much waiting process. + * + */ +void vMBMasterCBRequestScuuess( void ) { + /** + * @note This code is use OS's event mechanism for modbus master protocol stack. + * If you don't use OS, you can change it. + */ + PrivEvenTrigger(xMasterOsEvent, EV_MASTER_PROCESS_SUCESS); + + /* You can add your code under here. */ + +} + +/** + * This function is wait for modbus master request finish and return result. + * Waiting result include request process success, request respond timeout, + * receive data error and execute function error.You can use the above callback function. + * @note If you are use OS, you can use OS's event mechanism. Otherwise you have to run + * much user custom delay for waiting. + * + * @return request error code + */ +eMBMasterReqErrCode eMBMasterWaitRequestFinish( void ) { + eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; + unsigned int recvedEvent; + + /* waiting forever OS event */ + PrivEventProcess(xMasterOsEvent, + EV_MASTER_PROCESS_SUCESS | EV_MASTER_ERROR_RESPOND_TIMEOUT + | EV_MASTER_ERROR_RECEIVE_DATA + | EV_MASTER_ERROR_EXECUTE_FUNCTION, + EVENT_OR | EVENT_AUTOCLEAN, 0, &recvedEvent); + + switch (recvedEvent) + { + case EV_MASTER_PROCESS_SUCESS: + break; + case EV_MASTER_ERROR_RESPOND_TIMEOUT: + { + eErrStatus = MB_MRE_TIMEDOUT; + break; + } + case EV_MASTER_ERROR_RECEIVE_DATA: + { + eErrStatus = MB_MRE_REV_DATA; + break; + } + case EV_MASTER_ERROR_EXECUTE_FUNCTION: + { + eErrStatus = MB_MRE_EXE_FUN; + break; + } + } + return eErrStatus; +} +#endif + +#endif diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/portserial.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/portserial.c new file mode 100644 index 000000000..32ea82059 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/portserial.c @@ -0,0 +1,509 @@ +/* + * FreeModbus Libary: RT-Thread Port + * Copyright (C) 2013 Armink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * File: $Id: portserial.c,v 1.60 2013/08/13 15:07:05 Armink $ + */ + +/** +* @file portserial.c +* @brief support freemodbus port for XiUOS +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-10-12 +*/ + +/************************************************* +File name: portserial.c +Description: support freemodbus port for XiUOS +Others: +History: +1. Date: 2023-10-12 +Author: AIIT XUOS Lab +Modification: +1、support XiUOS serial for slave. +*************************************************/ + +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mbport.h" + +#ifdef ADD_RTTHREAD_FEATURES +#include "rtdevice.h" +#include "board.h" + +/* ----------------------- Static variables ---------------------------------*/ +/* software simulation serial transmit IRQ handler thread stack */ +#ifdef rt_align +rt_align(RT_ALIGN_SIZE) +#else +ALIGN(RT_ALIGN_SIZE) +#endif +static rt_uint8_t serial_soft_trans_irq_stack[512]; +/* software simulation serial transmit IRQ handler thread */ +static struct rt_thread thread_serial_soft_trans_irq; +/* serial event */ +static struct rt_event event_serial; +/* modbus slave serial device */ +static struct rt_serial_device *serial; + +/* ----------------------- Defines ------------------------------------------*/ +/* serial transmit event */ +#define EVENT_SERIAL_TRANS_START (1<<0) + +/* ----------------------- static functions ---------------------------------*/ +static void prvvUARTTxReadyISR(void); +static void prvvUARTRxISR(void); +static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size); +static void serial_soft_trans_irq(void* parameter); + +/* ----------------------- Start implementation -----------------------------*/ +BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, + eMBParity eParity) +{ + rt_device_t dev = RT_NULL; + char uart_name[20]; + /** + * set 485 mode receive and transmit control IO + * @note MODBUS_SLAVE_RT_CONTROL_PIN_INDEX need be defined by user + */ +#if defined(RT_MODBUS_SLAVE_USE_CONTROL_PIN) + rt_pin_mode(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_MODE_OUTPUT); +#endif + /* set serial name */ + rt_snprintf(uart_name,sizeof(uart_name), "uart%d", ucPORT); + + dev = rt_device_find(uart_name); + if(dev == RT_NULL) + { + /* can not find uart */ + return FALSE; + } + else + { + serial = (struct rt_serial_device*)dev; + } + + /* set serial configure parameter */ + serial->config.baud_rate = ulBaudRate; + serial->config.stop_bits = STOP_BITS_1; + switch(eParity){ + case MB_PAR_NONE: { + serial->config.data_bits = DATA_BITS_8; + serial->config.parity = PARITY_NONE; + break; + } + case MB_PAR_ODD: { + serial->config.data_bits = DATA_BITS_9; + serial->config.parity = PARITY_ODD; + break; + } + case MB_PAR_EVEN: { + serial->config.data_bits = DATA_BITS_9; + serial->config.parity = PARITY_EVEN; + break; + } + } + /* set serial configure */ + serial->ops->configure(serial, &(serial->config)); + + /* open serial device */ + if (!rt_device_open(&serial->parent, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX)) { + rt_device_set_rx_indicate(&serial->parent, serial_rx_ind); + } else { + return FALSE; + } + + /* software initialize */ + rt_event_init(&event_serial, "slave event", RT_IPC_FLAG_PRIO); + rt_thread_init(&thread_serial_soft_trans_irq, + "slave trans", + serial_soft_trans_irq, + RT_NULL, + serial_soft_trans_irq_stack, + sizeof(serial_soft_trans_irq_stack), + 10, 5); + rt_thread_startup(&thread_serial_soft_trans_irq); + + return TRUE; +} + +void vMBPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable) +{ + rt_uint32_t recved_event; + if (xRxEnable) + { + /* enable RX interrupt */ + serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX); + /* switch 485 to receive mode */ +#if defined(RT_MODBUS_SLAVE_USE_CONTROL_PIN) + rt_pin_write(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_LOW); +#endif + } + else + { + /* switch 485 to transmit mode */ +#if defined(RT_MODBUS_SLAVE_USE_CONTROL_PIN) + rt_pin_write(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_HIGH); +#endif + /* disable RX interrupt */ + serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX); + } + if (xTxEnable) + { + /* start serial transmit */ + rt_event_send(&event_serial, EVENT_SERIAL_TRANS_START); + } + else + { + /* stop serial transmit */ + rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 0, + &recved_event); + } +} + +void vMBPortClose(void) +{ + serial->parent.close(&(serial->parent)); +} + +BOOL xMBPortSerialPutByte(CHAR ucByte) +{ + serial->parent.write(&(serial->parent), 0, &ucByte, 1); + return TRUE; +} + +BOOL xMBPortSerialGetByte(CHAR * pucByte) +{ + serial->parent.read(&(serial->parent), 0, pucByte, 1); + return TRUE; +} + +/* + * Create an interrupt handler for the transmit buffer empty interrupt + * (or an equivalent) for your target processor. This function should then + * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that + * a new character can be sent. The protocol stack will then call + * xMBPortSerialPutByte( ) to send the character. + */ +void prvvUARTTxReadyISR(void) +{ + pxMBFrameCBTransmitterEmpty(); +} + +/* + * Create an interrupt handler for the receive interrupt for your target + * processor. This function should then call pxMBFrameCBByteReceived( ). The + * protocol stack will then call xMBPortSerialGetByte( ) to retrieve the + * character. + */ +void prvvUARTRxISR(void) +{ + pxMBFrameCBByteReceived(); +} + +/** + * Software simulation serial transmit IRQ handler. + * + * @param parameter parameter + */ +static void serial_soft_trans_irq(void* parameter) { + rt_uint32_t recved_event; + while (1) + { + /* waiting for serial transmit start */ + rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, RT_EVENT_FLAG_OR, + RT_WAITING_FOREVER, &recved_event); + /* execute modbus callback */ + prvvUARTTxReadyISR(); + } +} + +/** + * This function is serial receive callback function + * + * @param dev the device of serial + * @param size the data size that receive + * + * @return return RT_EOK + */ +static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size) { + while(size--) + prvvUARTRxISR(); + return RT_EOK; +} +#endif + +#ifdef ADD_XIZI_FEATURES +/* ----------------------- Static variables ---------------------------------*/ +/* software simulation serial transmit IRQ handler thread */ +static pthread_t thread_serial_soft_trans_irq; +static pthread_t thread_serial_recv_irq; +/* serial event */ +static int event_serial; +/* modbus slave serial device */ +static int pin_fd = 0; +static int uart_fd = 0; + +/* ----------------------- Defines ------------------------------------------*/ +/* serial transmit event */ +#define EVENT_SERIAL_TRANS_START (1<<0) +#define RTU_RECV_DATA_LENGTH 8 + +/* ----------------------- static functions ---------------------------------*/ +static void prvvUARTTxReadyISR(void); +static void prvvUARTRxISR(CHAR pucByte); + +static void *serial_soft_trans_irq(void* parameter); +static void *serial_recv_irq(void* parameter); + +/* ----------------------- Start implementation -----------------------------*/ +BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, + eMBParity eParity) +{ + int ret = 0; + uint32_t baud_rate; + uint8_t data_bits, parity; + + baud_rate = ulBaudRate; + data_bits = ucDataBits; + /* set serial configure parameter */ + switch(eParity){ + case MB_PAR_NONE: { + parity = PARITY_NONE; + break; + } + case MB_PAR_ODD: { + parity = PARITY_ODD; + break; + } + case MB_PAR_EVEN: { + parity = PARITY_EVEN; + break; + } + } + + pin_fd = PrivOpen(CONNECTION_MODBUS_RTU_PIN_DEV, O_RDWR); + if (pin_fd < 0) { + printf("open %s error\n", CONNECTION_MODBUS_RTU_PIN_DEV); + return FALSE; + } + + struct PinParam pin_param; + pin_param.cmd = GPIO_CONFIG_MODE; + pin_param.mode = GPIO_CFG_OUTPUT; + pin_param.pin = CONNECTION_MODBUS_RTU_UART_485_DIR; + + struct PrivIoctlCfg ioctl_cfg; + ioctl_cfg.ioctl_driver_type = PIN_TYPE; + ioctl_cfg.args = &pin_param; + PrivIoctl(pin_fd, OPE_CFG, &ioctl_cfg); + + uart_fd = PrivOpen(CONNECTION_MODBUS_RTU_UART_DEV, O_RDWR); + if (uart_fd < 0) { + printf("open fd error %d\n", uart_fd); + return FALSE; + } + printf("%s open fd %d baud_rate %d data_bits %d check_mode %d\n", + __func__, uart_fd, baud_rate, data_bits, parity); + + struct SerialDataCfg cfg; + cfg.serial_baud_rate = baud_rate; + cfg.serial_data_bits = data_bits; + cfg.serial_stop_bits = STOP_BITS_1; + cfg.serial_buffer_size = 128; + cfg.serial_parity_mode = parity; + cfg.serial_bit_order = 1; + cfg.serial_invert_mode = 1; +#ifdef CONNECTION_MODBUS_RTU_EXTUART + cfg.ext_uart_no = CONNECTION_MODBUS_RTU_UART_DEV_EXT_PORT; + cfg.port_configure = PORT_CFG_INIT; +#endif + cfg.serial_timeout = -1; + cfg.dev_recv_callback = NULL; + + ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; + ioctl_cfg.args = &cfg; + ret = PrivIoctl(uart_fd, OPE_INT, &ioctl_cfg); + if (0 != ret) { + printf("ioctl fd error %d\n", ret); + return FALSE; + } + + printf("%s serial init done!\n", __func__); + + /* software initialize */ + event_serial = PrivEventCreate(LINKLIST_FLAG_PRIO); + + pthread_attr_t attr; + attr.schedparam.sched_priority = 21; + attr.stacksize = 1024; + + char task_name[] = "slave_trans"; + pthread_args_t args; + args.pthread_name = task_name; + + PrivTaskCreate(&thread_serial_soft_trans_irq, &attr, &serial_soft_trans_irq, (void *)&args); + PrivTaskStartup(&thread_serial_soft_trans_irq); + + attr.schedparam.sched_priority = 22; + attr.stacksize = 2048; + + char task2_name[] = "slave_recv"; + args.pthread_name = task2_name; + + PrivTaskCreate(&thread_serial_recv_irq, &attr, &serial_recv_irq, (void *)&args); + PrivTaskStartup(&thread_serial_recv_irq); + + return TRUE; +} + +/** + * @description: Set Uart 485 Input + * @return + */ +static void Set485Input(void) +{ + PrivTaskDelay(15); + + struct PinStat pin_stat; + pin_stat.pin = CONNECTION_MODBUS_RTU_UART_485_DIR; + pin_stat.val = GPIO_LOW; + PrivWrite(pin_fd, &pin_stat, 1); +} + +/** + * @description: Set Uart 485 Output + * @return + */ +static void Set485Output(void) +{ + struct PinStat pin_stat; + pin_stat.pin = CONNECTION_MODBUS_RTU_UART_485_DIR; + pin_stat.val = GPIO_HIGH; + PrivWrite(pin_fd, &pin_stat, 1); + + PrivTaskDelay(20); +} + +void vMBPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable) +{ + unsigned int recved_event; + if (xRxEnable) { + /* switch 485 to receive mode */ + Set485Input(); + } else { + /* switch 485 to transmit mode */ + Set485Output(); + } + if (xTxEnable) { + /* start serial transmit */ + PrivEvenTrigger(event_serial, EVENT_SERIAL_TRANS_START); + } else { + /* stop serial transmit */ + PrivEventProcess(event_serial, EVENT_SERIAL_TRANS_START, EVENT_OR | EVENT_AUTOCLEAN, 0, &recved_event); + } +} + +void vMBPortClose(void) +{ + +} + +BOOL xMBPortSerialPutByte(CHAR ucByte) +{ + PrivWrite(uart_fd, &ucByte, 1); + return TRUE; +} + +BOOL xMBPortSerialGetByte(CHAR * pucByte) +{ + PrivRead(uart_fd, pucByte, 1); + + PrivTaskDelay(30); + + return TRUE; +} + +/* + * Create an interrupt handler for the transmit buffer empty interrupt + * (or an equivalent) for your target processor. This function should then + * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that + * a new character can be sent. The protocol stack will then call + * xMBPortSerialPutByte( ) to send the character. + */ +void prvvUARTTxReadyISR(void) +{ + pxMBFrameCBTransmitterEmpty(); +} + +/* + * Create an interrupt handler for the receive interrupt for your target + * processor. This function should then call pxMBFrameCBByteReceived( ). The + * protocol stack will then call xMBPortSerialGetByte( ) to retrieve the + * character. + */ +void prvvUARTRxISR(CHAR pucByte) +{ + pxMBFrameCBByteReceived(pucByte); +} + +/** + * Software simulation serial transmit IRQ handler. + * + * @param parameter parameter + */ +static void *serial_soft_trans_irq(void* parameter) { + unsigned int recved_event; + while (1) { + /* waiting for serial transmit start */ + if (0 == PrivEventProcess(event_serial, EVENT_SERIAL_TRANS_START, EVENT_OR, 0, &recved_event)) { + /* execute modbus callback */ + prvvUARTTxReadyISR(); + } + } +} + +/** + * Software simulation serial receive data IRQ handler. + * + * @param parameter parameter + */ +static void *serial_recv_irq(void* parameter) { + int i; + int data_size = 0; + int data_recv_size = 0; + char recv_data[RTU_RECV_DATA_LENGTH] = {0}; + + while (1) { + while (data_size < RTU_RECV_DATA_LENGTH) { + data_recv_size = PrivRead(uart_fd, recv_data + data_size, RTU_RECV_DATA_LENGTH - data_size); + data_size += data_recv_size; + } + /* execute modbus recv callback */ + for (i = 0; i < RTU_RECV_DATA_LENGTH; i ++) { + prvvUARTRxISR(recv_data[i]); + } + data_size = 0; + data_recv_size = 0; + } +} + +#endif diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/portserial_m.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/portserial_m.c new file mode 100644 index 000000000..55724b99a --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/portserial_m.c @@ -0,0 +1,515 @@ +/* + * FreeModbus Libary: RT-Thread Port + * Copyright (C) 2013 Armink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * File: $Id: portserial_m.c,v 1.60 2013/08/13 15:07:05 Armink add Master Functions $ + */ + +/** +* @file portserial_m.c +* @brief support freemodbus port for XiUOS +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-10-12 +*/ + +/************************************************* +File name: portserial_m.c +Description: support freemodbus port for XiUOS +Others: +History: +1. Date: 2023-10-12 +Author: AIIT XUOS Lab +Modification: +1、support XiUOS serial for master. +*************************************************/ + +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mbport.h" + +#ifdef ADD_RTTHREAD_FEATURES +#include "rtdevice.h" +#include "board.h" +#endif + +#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 +#ifdef ADD_RTTHREAD_FEATURES +/* ----------------------- Static variables ---------------------------------*/ +/* software simulation serial transmit IRQ handler thread stack */ +#ifdef rt_align +rt_align(RT_ALIGN_SIZE) +#else +ALIGN(RT_ALIGN_SIZE) +#endif +static rt_uint8_t serial_soft_trans_irq_stack[512]; +/* software simulation serial transmit IRQ handler thread */ +static struct rt_thread thread_serial_soft_trans_irq; +/* serial event */ +static struct rt_event event_serial; +/* modbus master serial device */ +static struct rt_serial_device *serial; + +/* ----------------------- Defines ------------------------------------------*/ +/* serial transmit event */ +#define EVENT_SERIAL_TRANS_START (1<<0) + +/* ----------------------- static functions ---------------------------------*/ +static void prvvUARTTxReadyISR(void); +static void prvvUARTRxISR(void); +static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size); +static void serial_soft_trans_irq(void* parameter); + +/* ----------------------- Start implementation -----------------------------*/ +BOOL xMBMasterPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, + eMBParity eParity) +{ + rt_device_t dev = RT_NULL; + char uart_name[20]; + + /** + * set 485 mode receive and transmit control IO + * @note MODBUS_MASTER_RT_CONTROL_PIN_INDEX need be defined by user + */ +#if defined(RT_MODBUS_MASTER_USE_CONTROL_PIN) + rt_pin_mode(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_MODE_OUTPUT); +#endif + /* set serial name */ + rt_snprintf(uart_name,sizeof(uart_name), "uart%d", ucPORT); + + dev = rt_device_find(uart_name); + if(dev == RT_NULL) + { + /* can not find uart */ + return FALSE; + } + else + { + serial = (struct rt_serial_device*)dev; + } + + /* set serial configure parameter */ + serial->config.baud_rate = ulBaudRate; + serial->config.stop_bits = STOP_BITS_1; + switch(eParity){ + case MB_PAR_NONE: { + serial->config.data_bits = DATA_BITS_8; + serial->config.parity = PARITY_NONE; + break; + } + case MB_PAR_ODD: { + serial->config.data_bits = DATA_BITS_9; + serial->config.parity = PARITY_ODD; + break; + } + case MB_PAR_EVEN: { + serial->config.data_bits = DATA_BITS_9; + serial->config.parity = PARITY_EVEN; + break; + } + } + /* set serial configure */ + serial->ops->configure(serial, &(serial->config)); + + /* open serial device */ + if (!rt_device_open(&serial->parent, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX)) { + rt_device_set_rx_indicate(&serial->parent, serial_rx_ind); + } else { + return FALSE; + } + + /* software initialize */ + rt_event_init(&event_serial, "master event", RT_IPC_FLAG_PRIO); + rt_thread_init(&thread_serial_soft_trans_irq, + "master trans", + serial_soft_trans_irq, + RT_NULL, + serial_soft_trans_irq_stack, + sizeof(serial_soft_trans_irq_stack), + 10, 5); + rt_thread_startup(&thread_serial_soft_trans_irq); + + return TRUE; +} + +void vMBMasterPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable) +{ + rt_uint32_t recved_event; + if (xRxEnable) + { + /* enable RX interrupt */ + serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX); + /* switch 485 to receive mode */ +#if defined(RT_MODBUS_MASTER_USE_CONTROL_PIN) + rt_pin_write(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_LOW); +#endif + } + else + { + /* switch 485 to transmit mode */ +#if defined(RT_MODBUS_MASTER_USE_CONTROL_PIN) + rt_pin_write(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_HIGH); +#endif + /* disable RX interrupt */ + serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX); + } + if (xTxEnable) + { + /* start serial transmit */ + rt_event_send(&event_serial, EVENT_SERIAL_TRANS_START); + } + else + { + /* stop serial transmit */ + rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 0, + &recved_event); + } +} + +void vMBMasterPortClose(void) +{ + serial->parent.close(&(serial->parent)); +} + +BOOL xMBMasterPortSerialPutByte(CHAR ucByte) +{ + serial->parent.write(&(serial->parent), 0, &ucByte, 1); + return TRUE; +} + +BOOL xMBMasterPortSerialGetByte(CHAR * pucByte) +{ + serial->parent.read(&(serial->parent), 0, pucByte, 1); + return TRUE; +} + +/* + * Create an interrupt handler for the transmit buffer empty interrupt + * (or an equivalent) for your target processor. This function should then + * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that + * a new character can be sent. The protocol stack will then call + * xMBPortSerialPutByte( ) to send the character. + */ +void prvvUARTTxReadyISR(void) +{ + pxMBMasterFrameCBTransmitterEmpty(); +} + +/* + * Create an interrupt handler for the receive interrupt for your target + * processor. This function should then call pxMBFrameCBByteReceived( ). The + * protocol stack will then call xMBPortSerialGetByte( ) to retrieve the + * character. + */ +void prvvUARTRxISR(void) +{ + pxMBMasterFrameCBByteReceived(); +} + +/** + * Software simulation serial transmit IRQ handler. + * + * @param parameter parameter + */ +static void serial_soft_trans_irq(void* parameter) { + rt_uint32_t recved_event; + while (1) + { + /* waiting for serial transmit start */ + rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, RT_EVENT_FLAG_OR, + RT_WAITING_FOREVER, &recved_event); + /* execute modbus callback */ + prvvUARTTxReadyISR(); + } +} + +/** + * This function is serial receive callback function + * + * @param dev the device of serial + * @param size the data size that receive + * + * @return return RT_EOK + */ +static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size) { + prvvUARTRxISR(); + return RT_EOK; +} + +#endif + +#ifdef ADD_XIZI_FEATURES +/* ----------------------- Static variables ---------------------------------*/ +/* software simulation serial transmit IRQ handler thread */ +static pthread_t thread_serial_soft_trans_irq; +static pthread_t thread_serial_recv_irq; +/* serial event */ +static int event_serial; +/* modbus master serial device */ +static int pin_fd = 0; +static int uart_fd = 0; + +/* ----------------------- Defines ------------------------------------------*/ +/* serial transmit event */ +#define EVENT_SERIAL_TRANS_START (1<<0) +#define RTU_RECV_DATA_LENGTH 8 + +/* ----------------------- static functions ---------------------------------*/ +static void prvvUARTTxReadyISR(void); +static void prvvUARTRxISR(CHAR pucByte); + +static void *serial_soft_trans_irq(void* parameter); +static void *serial_recv_irq(void* parameter); + +/* ----------------------- Start implementation -----------------------------*/ +BOOL xMBMasterPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, + eMBParity eParity) +{ + int ret = 0; + uint32_t baud_rate; + uint8_t data_bits, parity; + + baud_rate = ulBaudRate; + data_bits = ucDataBits; + /* set serial configure parameter */ + switch(eParity){ + case MB_PAR_NONE: { + parity = PARITY_NONE; + break; + } + case MB_PAR_ODD: { + parity = PARITY_ODD; + break; + } + case MB_PAR_EVEN: { + parity = PARITY_EVEN; + break; + } + } + + pin_fd = PrivOpen(CONNECTION_MODBUS_RTU_PIN_DEV, O_RDWR); + if (pin_fd < 0) { + printf("open %s error\n", CONNECTION_MODBUS_RTU_PIN_DEV); + return FALSE; + } + + struct PinParam pin_param; + pin_param.cmd = GPIO_CONFIG_MODE; + pin_param.mode = GPIO_CFG_OUTPUT; + pin_param.pin = CONNECTION_MODBUS_RTU_UART_485_DIR; + + struct PrivIoctlCfg ioctl_cfg; + ioctl_cfg.ioctl_driver_type = PIN_TYPE; + ioctl_cfg.args = &pin_param; + PrivIoctl(pin_fd, OPE_CFG, &ioctl_cfg); + + uart_fd = PrivOpen(CONNECTION_MODBUS_RTU_UART_DEV, O_RDWR); + if (uart_fd < 0) { + printf("open fd error %d\n", uart_fd); + return FALSE; + } + printf("%s open fd %d baud_rate %d data_bits %d check_mode %d\n", + __func__, uart_fd, baud_rate, data_bits, parity); + + struct SerialDataCfg cfg; + cfg.serial_baud_rate = baud_rate; + cfg.serial_data_bits = data_bits; + cfg.serial_stop_bits = STOP_BITS_1; + cfg.serial_buffer_size = 128; + cfg.serial_parity_mode = parity; + cfg.serial_bit_order = 1; + cfg.serial_invert_mode = 1; +#ifdef CONNECTION_MODBUS_RTU_EXTUART + cfg.ext_uart_no = 0; + cfg.port_configure = PORT_CFG_INIT; +#endif + cfg.serial_timeout = -1; + cfg.dev_recv_callback = NULL; + + ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; + ioctl_cfg.args = &cfg; + ret = PrivIoctl(uart_fd, OPE_INT, &ioctl_cfg); + if (0 != ret) { + printf("ioctl fd error %d\n", ret); + return FALSE; + } + + printf("%s serial init done!\n", __func__); + + /* software initialize */ + event_serial = PrivEventCreate(LINKLIST_FLAG_PRIO); + + pthread_attr_t attr; + attr.schedparam.sched_priority = 21; + attr.stacksize = 2048; + + char task1_name[] = "master_trans"; + pthread_args_t args; + args.pthread_name = task1_name; + + PrivTaskCreate(&thread_serial_soft_trans_irq, &attr, &serial_soft_trans_irq, (void *)&args); + PrivTaskStartup(&thread_serial_soft_trans_irq); + + attr.schedparam.sched_priority = 22; + attr.stacksize = 2048; + + char task2_name[] = "master_recv"; + args.pthread_name = task2_name; + + PrivTaskCreate(&thread_serial_recv_irq, &attr, &serial_recv_irq, (void *)&args); + PrivTaskStartup(&thread_serial_recv_irq); + + return TRUE; +} + +/** + * @description: Set Uart 485 Input + * @return + */ +static void Set485Input(void) +{ + PrivTaskDelay(15); + + struct PinStat pin_stat; + pin_stat.pin = CONNECTION_MODBUS_RTU_UART_485_DIR; + pin_stat.val = GPIO_LOW; + PrivWrite(pin_fd, &pin_stat, 1); +} + +/** + * @description: Set Uart 485 Output + * @return + */ +static void Set485Output(void) +{ + struct PinStat pin_stat; + pin_stat.pin = CONNECTION_MODBUS_RTU_UART_485_DIR; + pin_stat.val = GPIO_HIGH; + PrivWrite(pin_fd, &pin_stat, 1); + + PrivTaskDelay(20); +} + +void vMBMasterPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable) +{ + unsigned int recved_event; + if (xRxEnable) { + /* switch 485 to receive mode */ + Set485Input(); + } else { + /* switch 485 to transmit mode */ + Set485Output(); + } + if (xTxEnable) { + /* start serial transmit */ + PrivEvenTrigger(event_serial, EVENT_SERIAL_TRANS_START); + } else { + /* stop serial transmit */ + PrivEventProcess(event_serial, EVENT_SERIAL_TRANS_START, EVENT_OR | EVENT_AUTOCLEAN, 0, &recved_event); + } +} + +void vMBMasterPortClose(void) +{ + +} + +BOOL xMBMasterPortSerialPutByte(CHAR ucByte) +{ + PrivWrite(uart_fd, &ucByte, 1); + return TRUE; +} + +BOOL xMBMasterPortSerialGetByte(CHAR * pucByte) +{ + PrivRead(uart_fd, pucByte, 1); + + PrivTaskDelay(30); + + return TRUE; +} + +/* + * Create an interrupt handler for the transmit buffer empty interrupt + * (or an equivalent) for your target processor. This function should then + * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that + * a new character can be sent. The protocol stack will then call + * xMBPortSerialPutByte( ) to send the character. + */ +void prvvUARTTxReadyISR(void) +{ + pxMBMasterFrameCBTransmitterEmpty(); +} + +/* + * Create an interrupt handler for the receive interrupt for your target + * processor. This function should then call pxMBFrameCBByteReceived( ). The + * protocol stack will then call xMBPortSerialGetByte( ) to retrieve the + * character. + */ +void prvvUARTRxISR(CHAR pucByte) +{ + pxMBMasterFrameCBByteReceived(pucByte); +} + +/** + * Software simulation serial transmit IRQ handler. + * + * @param parameter parameter + */ +static void *serial_soft_trans_irq(void* parameter) { + unsigned int recved_event; + while (1) { + /* waiting for serial transmit start */ + if (0 == PrivEventProcess(event_serial, EVENT_SERIAL_TRANS_START, EVENT_OR, 0, &recved_event)) { + /* execute modbus callback */ + prvvUARTTxReadyISR(); + } + } +} + +/** + * Software simulation serial receive data IRQ handler. + * + * @param parameter parameter + */ +static void *serial_recv_irq(void* parameter) { + int i; + int data_size = 0; + int data_recv_size = 0; + char recv_data[RTU_RECV_DATA_LENGTH] = {0}; + + while (1) { + while (data_size < RTU_RECV_DATA_LENGTH) { + data_recv_size = PrivRead(uart_fd, recv_data + data_size, RTU_RECV_DATA_LENGTH - data_size); + data_size += data_recv_size; + } + /* execute modbus recv callback */ + for (i = 0; i < RTU_RECV_DATA_LENGTH; i ++) { + prvvUARTRxISR(recv_data[i]); + } + data_size = 0; + data_recv_size = 0; + } +} + +#endif + +#endif diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/porttcp.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/porttcp.c new file mode 100644 index 000000000..01963935e --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/porttcp.c @@ -0,0 +1,134 @@ +/* + * FreeModbus Libary: RT-Thread Port + * Copyright (C) 2019 flybreak + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * File: $Id: portserial.c,v 1.60 2019/07/11 17:04:32 flybreak $ + */ + +#include "port.h" + +#ifdef PKG_MODBUS_SLAVE_TCP +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mbport.h" +#include "tcpserver.h" + +/* ----------------------- Defines -----------------------------------------*/ +#define MB_TCP_DEFAULT_PORT 502 +#define MB_TCP_BUF_SIZE ( 256 + 7 ) + +/* ----------------------- Static variables ---------------------------------*/ +static tcpclient_t mb_client; +static UCHAR prvvTCPBuf[MB_TCP_BUF_SIZE]; +static USHORT prvvTCPLength; + +static void tcpserver_event_notify(tcpclient_t client, rt_uint8_t event) +{ + static rt_tick_t recv_tick = 0; + switch (event) + { + case TCPSERVER_EVENT_CONNECT: + if (mb_client == RT_NULL) + { + mb_client = client; + } + else + { + if(rt_tick_get() - recv_tick > 30 * RT_TICK_PER_SECOND) /* set timeout as 30s */ + { + tcpserver_close(mb_client); + mb_client = client; + recv_tick = rt_tick_get(); + } + else + { + tcpserver_close(client); + rt_kprintf("Multi-host is not supported, please disconnect the current host first!\n"); + } + } + break; + case TCPSERVER_EVENT_RECV: + if( mb_client == client) + { + recv_tick = rt_tick_get(); + prvvTCPLength = tcpserver_recv(mb_client, &prvvTCPBuf, MB_TCP_BUF_SIZE, 100); + if (prvvTCPLength) + { + xMBPortEventPost(EV_FRAME_RECEIVED); + } + } + break; + case TCPSERVER_EVENT_DISCONNECT: + if (mb_client == client) + mb_client = RT_NULL; + break; + default: + break; + } +} + +BOOL +xMBTCPPortInit(USHORT usTCPPort) +{ + struct tcpserver *serv; + + if (usTCPPort == 0) + usTCPPort = MB_TCP_DEFAULT_PORT; + + serv = tcpserver_create(0, usTCPPort); + + tcpserver_set_notify_callback(serv, tcpserver_event_notify); + + return TRUE; +} + +void +vMBTCPPortClose(void) +{ + tcpserver_destroy(mb_client->server); +} + +void +vMBTCPPortDisable(void) +{ + tcpserver_close(mb_client); +} + +BOOL +xMBTCPPortGetRequest(UCHAR **ppucMBTCPFrame, USHORT *usTCPLength) +{ + *ppucMBTCPFrame = &prvvTCPBuf[0]; + *usTCPLength = prvvTCPLength; + + return TRUE; +} + +BOOL +xMBTCPPortSendResponse(const UCHAR *pucMBTCPFrame, USHORT usTCPLength) +{ + rt_int16_t ret; + BOOL bFrameSent = FALSE; + + if (mb_client) + { + ret = tcpserver_send(mb_client, (void *)pucMBTCPFrame, usTCPLength, 0); + if (ret == usTCPLength) + bFrameSent = TRUE; + } + return bFrameSent; +} +#endif diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/porttimer.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/porttimer.c new file mode 100644 index 000000000..d0ac4e2a8 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/porttimer.c @@ -0,0 +1,141 @@ +/* + * FreeModbus Libary: RT-Thread Port + * Copyright (C) 2013 Armink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * File: $Id: porttimer.c,v 1.60 2013/08/13 15:07:05 Armink $ + */ + +/** +* @file porttimer.c +* @brief support freemodbus port for XiUOS +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-10-12 +*/ + +/************************************************* +File name: porttimer.c +Description: support freemodbus port for XiUOS +Others: +History: +1. Date: 2023-10-12 +Author: AIIT XUOS Lab +Modification: +1、support XiUOS timer for slave. +*************************************************/ + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mbport.h" + +#ifdef ADD_RTTHREAD_FEATURES +/* ----------------------- static functions ---------------------------------*/ +static struct rt_timer timer; +static void prvvTIMERExpiredISR(void); +static void timer_timeout_ind(void* parameter); + +/* ----------------------- Start implementation -----------------------------*/ +BOOL xMBPortTimersInit(USHORT usTim1Timerout50us) +{ + rt_timer_init(&timer, "slave timer", + timer_timeout_ind, /* bind timeout callback function */ + RT_NULL, + (50 * usTim1Timerout50us) / (1000 * 1000 / RT_TICK_PER_SECOND) + 1, + RT_TIMER_FLAG_ONE_SHOT); /* one shot */ + return TRUE; +} + +void vMBPortTimersEnable() +{ + rt_timer_start(&timer); +} + +void vMBPortTimersDisable() +{ + rt_timer_stop(&timer); +} + +void prvvTIMERExpiredISR(void) +{ + (void) pxMBPortCBTimerExpired(); +} + +static void timer_timeout_ind(void* parameter) +{ + prvvTIMERExpiredISR(); +} +#endif + +#ifdef ADD_XIZI_FEATURES +/* ----------------------- static functions ---------------------------------*/ +static timer_t timer_id; +static void prvvTIMERExpiredISR(void); +static void timer_timeout_ind(union sigval sig_val); + +/* ----------------------- Start implementation -----------------------------*/ +BOOL xMBPortTimersInit(USHORT usTim1Timerout50us) +{ + int ret = 0; + int timer_flags; + static int count = 0; + + struct sigevent evp; + memset(&evp, 0, sizeof(struct sigevent)); + + timer_flags = TIMER_TRIGGER_ONCE; + + count++; + + evp.sigev_notify = SIGEV_THREAD; + evp.sigev_notify_function = timer_timeout_ind; + evp.sigev_notify_attributes = &timer_flags; + + ret = PrivTimerCreate(count, &evp, &timer_id); + if (ret < 0) { + printf("%s create timer failed ret %d\n", __func__, ret); + return FALSE; + } + + UserTimerModify(timer_id, (50 * usTim1Timerout50us) / (1000 * 1000 / TICK_PER_SECOND) + 1); + + return TRUE; +} + +void vMBPortTimersEnable() +{ + PrivTimerStartRun(timer_id); +} + +void vMBPortTimersDisable() +{ + PrivTimerQuitRun(timer_id); +} + +void prvvTIMERExpiredISR(void) +{ + (void) pxMBPortCBTimerExpired(); +} + +static void timer_timeout_ind(union sigval sig_val) +{ + prvvTIMERExpiredISR(); +} +#endif + diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/porttimer_m.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/porttimer_m.c new file mode 100644 index 000000000..76ab4c708 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/porttimer_m.c @@ -0,0 +1,222 @@ +/* + * FreeModbus Libary: RT-Thread Port + * Copyright (C) 2013 Armink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * File: $Id: porttimer_m.c,v 1.60 2013/08/13 15:07:05 Armink add Master Functions$ + */ + +/** +* @file porttimer_m.c +* @brief support freemodbus port for XiUOS +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-10-12 +*/ + +/************************************************* +File name: porttimer_m.c +Description: support freemodbus port for XiUOS +Others: +History: +1. Date: 2023-10-12 +Author: AIIT XUOS Lab +Modification: +1、support XiUOS timer for master. +*************************************************/ + +/* ----------------------- Platform includes --------------------------------*/ +#include "port.h" + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mb_m.h" +#include "mbport.h" + +#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 +#ifdef ADD_RTTHREAD_FEATURES +/* ----------------------- Variables ----------------------------------------*/ +static USHORT usT35TimeOut50us; +static struct rt_timer timer; +static void prvvTIMERExpiredISR(void); +static void timer_timeout_ind(void* parameter); + +/* ----------------------- static functions ---------------------------------*/ +static void prvvTIMERExpiredISR(void); + +/* ----------------------- Start implementation -----------------------------*/ +BOOL xMBMasterPortTimersInit(USHORT usTimeOut50us) +{ + /* backup T35 ticks */ + usT35TimeOut50us = usTimeOut50us; + + rt_timer_init(&timer, "master timer", + timer_timeout_ind, /* bind timeout callback function */ + RT_NULL, + (50 * usT35TimeOut50us) / (1000 * 1000 / RT_TICK_PER_SECOND) + 1, + RT_TIMER_FLAG_ONE_SHOT); /* one shot */ + + return TRUE; +} + +void vMBMasterPortTimersT35Enable() +{ + rt_tick_t timer_tick = (50 * usT35TimeOut50us) + / (1000 * 1000 / RT_TICK_PER_SECOND) + 1; + + /* Set current timer mode, don't change it.*/ + vMBMasterSetCurTimerMode(MB_TMODE_T35); + + rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick); + + rt_timer_start(&timer); +} + +void vMBMasterPortTimersConvertDelayEnable() +{ + rt_tick_t timer_tick = MB_MASTER_DELAY_MS_CONVERT * RT_TICK_PER_SECOND / 1000; + + /* Set current timer mode, don't change it.*/ + vMBMasterSetCurTimerMode(MB_TMODE_CONVERT_DELAY); + + rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick); + + rt_timer_start(&timer); +} + +void vMBMasterPortTimersRespondTimeoutEnable() +{ + rt_tick_t timer_tick = MB_MASTER_TIMEOUT_MS_RESPOND * RT_TICK_PER_SECOND / 1000; + + /* Set current timer mode, don't change it.*/ + vMBMasterSetCurTimerMode(MB_TMODE_RESPOND_TIMEOUT); + + rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick); + + rt_timer_start(&timer); +} + +void vMBMasterPortTimersDisable() +{ + rt_timer_stop(&timer); +} + +void prvvTIMERExpiredISR(void) +{ + (void) pxMBMasterPortCBTimerExpired(); +} + +static void timer_timeout_ind(void* parameter) +{ + prvvTIMERExpiredISR(); +} +#endif + + +#ifdef ADD_XIZI_FEATURES +/* ----------------------- Variables ----------------------------------------*/ +static USHORT usT35TimeOut50us; +static timer_t timer_id; +static void prvvTIMERExpiredISR(void); +static void timer_timeout_ind(union sigval sig_val); + +/* ----------------------- static functions ---------------------------------*/ +static void prvvTIMERExpiredISR(void); + +/* ----------------------- Start implementation -----------------------------*/ +BOOL xMBMasterPortTimersInit(USHORT usTimeOut50us) +{ + /* backup T35 ticks */ + usT35TimeOut50us = usTimeOut50us; + + int ret = 0; + int timer_flags; + static int count = 0; + + struct sigevent evp; + memset(&evp, 0, sizeof(struct sigevent)); + + timer_flags = TIMER_TRIGGER_ONCE; + + count++; + + evp.sigev_notify = SIGEV_THREAD; + evp.sigev_notify_function = timer_timeout_ind; + evp.sigev_notify_attributes = &timer_flags; + + ret = PrivTimerCreate(count, &evp, &timer_id); + if (ret < 0) { + printf("%s create timer failed ret %d\n", __func__, ret); + return FALSE; + } + + return TRUE; +} + +void vMBMasterPortTimersT35Enable() +{ + int timer_tick = (50 * usT35TimeOut50us) + / (1000 * 1000 / TICK_PER_SECOND) + 1; + + /* Set current timer mode, don't change it.*/ + vMBMasterSetCurTimerMode(MB_TMODE_T35); + + UserTimerModify(timer_id, timer_tick); + + UserTimerStartRun(timer_id); +} + +void vMBMasterPortTimersConvertDelayEnable() +{ + int timer_tick = MB_MASTER_DELAY_MS_CONVERT * TICK_PER_SECOND / 1000; + + /* Set current timer mode, don't change it.*/ + vMBMasterSetCurTimerMode(MB_TMODE_CONVERT_DELAY); + + UserTimerModify(timer_id, timer_tick); + + UserTimerStartRun(timer_id); +} + +void vMBMasterPortTimersRespondTimeoutEnable() +{ + int timer_tick = MB_MASTER_TIMEOUT_MS_RESPOND * TICK_PER_SECOND / 1000; + + /* Set current timer mode, don't change it.*/ + vMBMasterSetCurTimerMode(MB_TMODE_RESPOND_TIMEOUT); + + UserTimerModify(timer_id, timer_tick); + + UserTimerStartRun(timer_id); +} + +void vMBMasterPortTimersDisable() +{ + PrivTimerQuitRun(timer_id); +} + +void prvvTIMERExpiredISR(void) +{ + (void) pxMBMasterPortCBTimerExpired(); +} + +static void timer_timeout_ind(union sigval sig_val) +{ + prvvTIMERExpiredISR(); +} +#endif + +#endif diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/user_mb_app.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/user_mb_app.c new file mode 100644 index 000000000..8da737633 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/user_mb_app.c @@ -0,0 +1,286 @@ +/* + * FreeModbus Libary: user callback functions and buffer define in slave mode + * Copyright (C) 2013 Armink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * File: $Id: user_mb_app.c,v 1.60 2013/11/23 11:49:05 Armink $ + */ +#include "user_mb_app.h" + +/*------------------------Slave mode use these variables----------------------*/ +//Slave mode:DiscreteInputs variables +USHORT usSDiscInStart = S_DISCRETE_INPUT_START; +#if S_DISCRETE_INPUT_NDISCRETES%8 +UCHAR ucSDiscInBuf[S_DISCRETE_INPUT_NDISCRETES/8+1]; +#else +UCHAR ucSDiscInBuf[S_DISCRETE_INPUT_NDISCRETES/8] ; +#endif +//Slave mode:Coils variables +USHORT usSCoilStart = S_COIL_START; +#if S_COIL_NCOILS%8 +UCHAR ucSCoilBuf[S_COIL_NCOILS/8+1] ; +#else +UCHAR ucSCoilBuf[S_COIL_NCOILS/8] ; +#endif +//Slave mode:InputRegister variables +USHORT usSRegInStart = S_REG_INPUT_START; +USHORT usSRegInBuf[S_REG_INPUT_NREGS] ; +//Slave mode:HoldingRegister variables +USHORT usSRegHoldStart = S_REG_HOLDING_START; +USHORT usSRegHoldBuf[S_REG_HOLDING_NREGS] ; + +/** + * Modbus slave input register callback function. + * + * @param pucRegBuffer input register buffer + * @param usAddress input register address + * @param usNRegs input register number + * + * @return result + */ +eMBErrorCode eMBRegInputCB(UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs ) +{ + eMBErrorCode eStatus = MB_ENOERR; + USHORT iRegIndex; + USHORT * pusRegInputBuf; + USHORT REG_INPUT_START; + USHORT REG_INPUT_NREGS; + USHORT usRegInStart; + + pusRegInputBuf = usSRegInBuf; + REG_INPUT_START = S_REG_INPUT_START; + REG_INPUT_NREGS = S_REG_INPUT_NREGS; + usRegInStart = usSRegInStart; + + /* it already plus one in modbus function method. */ + usAddress--; + + if ((usAddress >= REG_INPUT_START) + && (usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS)) + { + iRegIndex = usAddress - usRegInStart; + while (usNRegs > 0) + { + *pucRegBuffer++ = (UCHAR) (pusRegInputBuf[iRegIndex] >> 8); + *pucRegBuffer++ = (UCHAR) (pusRegInputBuf[iRegIndex] & 0xFF); + iRegIndex++; + usNRegs--; + } + } + else + { + eStatus = MB_ENOREG; + } + + return eStatus; +} + +/** + * Modbus slave holding register callback function. + * + * @param pucRegBuffer holding register buffer + * @param usAddress holding register address + * @param usNRegs holding register number + * @param eMode read or write + * + * @return result + */ +eMBErrorCode eMBRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs, eMBRegisterMode eMode) +{ + eMBErrorCode eStatus = MB_ENOERR; + USHORT iRegIndex; + USHORT * pusRegHoldingBuf; + USHORT REG_HOLDING_START; + USHORT REG_HOLDING_NREGS; + USHORT usRegHoldStart; + + pusRegHoldingBuf = usSRegHoldBuf; + REG_HOLDING_START = S_REG_HOLDING_START; + REG_HOLDING_NREGS = S_REG_HOLDING_NREGS; + usRegHoldStart = usSRegHoldStart; + + /* it already plus one in modbus function method. */ + usAddress--; + + if ((usAddress >= REG_HOLDING_START) + && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS)) + { + iRegIndex = usAddress - usRegHoldStart; + switch (eMode) + { + /* read current register values from the protocol stack. */ + case MB_REG_READ: + while (usNRegs > 0) + { + *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8); + *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF); + iRegIndex++; + usNRegs--; + } + break; + + /* write current register values with new values from the protocol stack. */ + case MB_REG_WRITE: + while (usNRegs > 0) + { + pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8; + pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++; + iRegIndex++; + usNRegs--; + } + break; + } + } + else + { + eStatus = MB_ENOREG; + } + return eStatus; +} + +/** + * Modbus slave coils callback function. + * + * @param pucRegBuffer coils buffer + * @param usAddress coils address + * @param usNCoils coils number + * @param eMode read or write + * + * @return result + */ +eMBErrorCode eMBRegCoilsCB(UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNCoils, eMBRegisterMode eMode) +{ + eMBErrorCode eStatus = MB_ENOERR; + USHORT iRegIndex , iRegBitIndex , iNReg; + UCHAR * pucCoilBuf; + USHORT COIL_START; + USHORT COIL_NCOILS; + USHORT usCoilStart; + iNReg = usNCoils / 8 + 1; + + pucCoilBuf = ucSCoilBuf; + COIL_START = S_COIL_START; + COIL_NCOILS = S_COIL_NCOILS; + usCoilStart = usSCoilStart; + + /* it already plus one in modbus function method. */ + usAddress--; + + if( ( usAddress >= COIL_START ) && + ( usAddress + usNCoils <= COIL_START + COIL_NCOILS ) ) + { + iRegIndex = (USHORT) (usAddress - usCoilStart) / 8; + iRegBitIndex = (USHORT) (usAddress - usCoilStart) % 8; + switch ( eMode ) + { + /* read current coil values from the protocol stack. */ + case MB_REG_READ: + while (iNReg > 0) + { + *pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++], + iRegBitIndex, 8); + iNReg--; + } + pucRegBuffer--; + /* last coils */ + usNCoils = usNCoils % 8; + /* filling zero to high bit */ + *pucRegBuffer = *pucRegBuffer << (8 - usNCoils); + *pucRegBuffer = *pucRegBuffer >> (8 - usNCoils); + break; + + /* write current coil values with new values from the protocol stack. */ + case MB_REG_WRITE: + while (iNReg > 1) + { + xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, 8, + *pucRegBuffer++); + iNReg--; + } + /* last coils */ + usNCoils = usNCoils % 8; + /* xMBUtilSetBits has bug when ucNBits is zero */ + if (usNCoils != 0) + { + xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils, + *pucRegBuffer++); + } + break; + } + } + else + { + eStatus = MB_ENOREG; + } + return eStatus; +} + +/** + * Modbus slave discrete callback function. + * + * @param pucRegBuffer discrete buffer + * @param usAddress discrete address + * @param usNDiscrete discrete number + * + * @return result + */ +eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete ) +{ + eMBErrorCode eStatus = MB_ENOERR; + USHORT iRegIndex , iRegBitIndex , iNReg; + UCHAR * pucDiscreteInputBuf; + USHORT DISCRETE_INPUT_START; + USHORT DISCRETE_INPUT_NDISCRETES; + USHORT usDiscreteInputStart; + iNReg = usNDiscrete / 8 + 1; + + pucDiscreteInputBuf = ucSDiscInBuf; + DISCRETE_INPUT_START = S_DISCRETE_INPUT_START; + DISCRETE_INPUT_NDISCRETES = S_DISCRETE_INPUT_NDISCRETES; + usDiscreteInputStart = usSDiscInStart; + + /* it already plus one in modbus function method. */ + usAddress--; + + if ((usAddress >= DISCRETE_INPUT_START) + && (usAddress + usNDiscrete <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES)) + { + iRegIndex = (USHORT) (usAddress - usDiscreteInputStart) / 8; + iRegBitIndex = (USHORT) (usAddress - usDiscreteInputStart) % 8; + + while (iNReg > 0) + { + *pucRegBuffer++ = xMBUtilGetBits(&pucDiscreteInputBuf[iRegIndex++], + iRegBitIndex, 8); + iNReg--; + } + pucRegBuffer--; + /* last discrete */ + usNDiscrete = usNDiscrete % 8; + /* filling zero to high bit */ + *pucRegBuffer = *pucRegBuffer << (8 - usNDiscrete); + *pucRegBuffer = *pucRegBuffer >> (8 - usNDiscrete); + } + else + { + eStatus = MB_ENOREG; + } + + return eStatus; +} + diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/user_mb_app.h b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/user_mb_app.h new file mode 100644 index 000000000..4701b1772 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/user_mb_app.h @@ -0,0 +1,108 @@ +/** +* @file user_mb_app.h +* @brief support freemodbus port for XiUOS +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-10-12 +*/ + +/************************************************* +File name: user_mb_app.h +Description: support freemodbus port for XiUOS +Others: +History: +1. Date: 2023-10-12 +Author: AIIT XUOS Lab +Modification: +1、support XiUOS for Defines. +*************************************************/ + +#ifndef USER_APP +#define USER_APP + +#include + +/* ----------------------- Modbus includes ----------------------------------*/ +#include "mb.h" +#include "mb_m.h" +#include "mbconfig.h" +#include "mbframe.h" +#include "mbutils.h" + +#ifdef ADD_RTTHREAD_FEATURES +/* -----------------------Slave Defines -------------------------------------*/ +#define S_DISCRETE_INPUT_START RT_S_DISCRETE_INPUT_START +#define S_DISCRETE_INPUT_NDISCRETES RT_S_DISCRETE_INPUT_NDISCRETES +#define S_COIL_START RT_S_COIL_START +#define S_COIL_NCOILS RT_S_COIL_NCOILS +#define S_REG_INPUT_START RT_S_REG_INPUT_START +#define S_REG_INPUT_NREGS RT_S_REG_INPUT_NREGS +#define S_REG_HOLDING_START RT_S_REG_HOLDING_START +#define S_REG_HOLDING_NREGS RT_S_REG_HOLDING_NREGS +/* salve mode: holding register's all address */ +#define S_HD_RESERVE RT_S_HD_RESERVE +/* salve mode: input register's all address */ +#define S_IN_RESERVE RT_S_IN_RESERVE +/* salve mode: coil's all address */ +#define S_CO_RESERVE RT_S_CO_RESERVE +/* salve mode: discrete's all address */ +#define S_DI_RESERVE RT_S_DI_RESERVE + +/* -----------------------Master Defines -------------------------------------*/ +#define M_DISCRETE_INPUT_START RT_M_DISCRETE_INPUT_START +#define M_DISCRETE_INPUT_NDISCRETES RT_M_DISCRETE_INPUT_NDISCRETES +#define M_COIL_START RT_M_COIL_START +#define M_COIL_NCOILS RT_M_COIL_NCOILS +#define M_REG_INPUT_START RT_M_REG_INPUT_START +#define M_REG_INPUT_NREGS RT_M_REG_INPUT_NREGS +#define M_REG_HOLDING_START RT_M_REG_HOLDING_START +#define M_REG_HOLDING_NREGS RT_M_REG_HOLDING_NREGS +/* master mode: holding register's all address */ +#define M_HD_RESERVE RT_M_HD_RESERVE +/* master mode: input register's all address */ +#define M_IN_RESERVE RT_M_IN_RESERVE +/* master mode: coil's all address */ +#define M_CO_RESERVE RT_M_CO_RESERVE +/* master mode: discrete's all address */ +#define M_DI_RESERVE RT_M_DI_RESERVE +#endif + +#ifdef ADD_XIZI_FEATURES +/* -----------------------Slave Defines -------------------------------------*/ +#define S_DISCRETE_INPUT_START X_S_DISCRETE_INPUT_START +#define S_DISCRETE_INPUT_NDISCRETES X_S_DISCRETE_INPUT_NDISCRETES +#define S_COIL_START X_S_COIL_START +#define S_COIL_NCOILS X_S_COIL_NCOILS +#define S_REG_INPUT_START X_S_REG_INPUT_START +#define S_REG_INPUT_NREGS X_S_REG_INPUT_NREGS +#define S_REG_HOLDING_START X_S_REG_HOLDING_START +#define S_REG_HOLDING_NREGS X_S_REG_HOLDING_NREGS +/* salve mode: holding register's all address */ +#define S_HD_RESERVE X_S_HD_RESERVE +/* salve mode: input register's all address */ +#define S_IN_RESERVE X_S_IN_RESERVE +/* salve mode: coil's all address */ +#define S_CO_RESERVE X_S_CO_RESERVE +/* salve mode: discrete's all address */ +#define S_DI_RESERVE X_S_DI_RESERVE + +/* -----------------------Master Defines -------------------------------------*/ +#define M_DISCRETE_INPUT_START X_M_DISCRETE_INPUT_START +#define M_DISCRETE_INPUT_NDISCRETES X_M_DISCRETE_INPUT_NDISCRETES +#define M_COIL_START X_M_COIL_START +#define M_COIL_NCOILS X_M_COIL_NCOILS +#define M_REG_INPUT_START X_M_REG_INPUT_START +#define M_REG_INPUT_NREGS X_M_REG_INPUT_NREGS +#define M_REG_HOLDING_START X_M_REG_HOLDING_START +#define M_REG_HOLDING_NREGS X_M_REG_HOLDING_NREGS +/* master mode: holding register's all address */ +#define M_HD_RESERVE X_M_HD_RESERVE +/* master mode: input register's all address */ +#define M_IN_RESERVE X_M_IN_RESERVE +/* master mode: coil's all address */ +#define M_CO_RESERVE X_M_CO_RESERVE +/* master mode: discrete's all address */ +#define M_DI_RESERVE X_M_DI_RESERVE +#endif + +#endif diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/user_mb_app_m.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/user_mb_app_m.c new file mode 100644 index 000000000..12fabf21a --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port/user_mb_app_m.c @@ -0,0 +1,294 @@ +/* + * FreeModbus Libary: user callback functions and buffer define in master mode + * Copyright (C) 2013 Armink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * File: $Id: user_mb_app_m.c,v 1.60 2013/11/23 11:49:05 Armink $ + */ +#include "user_mb_app.h" + +/*-----------------------Master mode use these variables----------------------*/ +#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 +//Master mode:DiscreteInputs variables +USHORT usMDiscInStart = M_DISCRETE_INPUT_START; +#if M_DISCRETE_INPUT_NDISCRETES%8 +UCHAR ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8+1]; +#else +UCHAR ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8]; +#endif +//Master mode:Coils variables +USHORT usMCoilStart = M_COIL_START; +#if M_COIL_NCOILS%8 +UCHAR ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8+1]; +#else +UCHAR ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8]; +#endif +//Master mode:InputRegister variables +USHORT usMRegInStart = M_REG_INPUT_START; +USHORT usMRegInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_INPUT_NREGS]; +//Master mode:HoldingRegister variables +USHORT usMRegHoldStart = M_REG_HOLDING_START; +USHORT usMRegHoldBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_HOLDING_NREGS]; + +/** + * Modbus master input register callback function. + * + * @param pucRegBuffer input register buffer + * @param usAddress input register address + * @param usNRegs input register number + * + * @return result + */ +eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs ) +{ + eMBErrorCode eStatus = MB_ENOERR; + USHORT iRegIndex; + USHORT * pusRegInputBuf; + USHORT REG_INPUT_START; + USHORT REG_INPUT_NREGS; + USHORT usRegInStart; + + pusRegInputBuf = usMRegInBuf[ucMBMasterGetDestAddress() - 1]; + REG_INPUT_START = M_REG_INPUT_START; + REG_INPUT_NREGS = M_REG_INPUT_NREGS; + usRegInStart = usMRegInStart; + + /* it already plus one in modbus function method. */ + usAddress--; + + if ((usAddress >= REG_INPUT_START) + && (usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS)) + { + iRegIndex = usAddress - usRegInStart; + while (usNRegs > 0) + { + pusRegInputBuf[iRegIndex] = *pucRegBuffer++ << 8; + pusRegInputBuf[iRegIndex] |= *pucRegBuffer++; + iRegIndex++; + usNRegs--; + } + } + else + { + eStatus = MB_ENOREG; + } + + return eStatus; +} + +/** + * Modbus master holding register callback function. + * + * @param pucRegBuffer holding register buffer + * @param usAddress holding register address + * @param usNRegs holding register number + * @param eMode read or write + * + * @return result + */ +eMBErrorCode eMBMasterRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs, eMBRegisterMode eMode) +{ + eMBErrorCode eStatus = MB_ENOERR; + USHORT iRegIndex; + USHORT * pusRegHoldingBuf; + USHORT REG_HOLDING_START; + USHORT REG_HOLDING_NREGS; + USHORT usRegHoldStart; + + pusRegHoldingBuf = usMRegHoldBuf[ucMBMasterGetDestAddress() - 1]; + REG_HOLDING_START = M_REG_HOLDING_START; + REG_HOLDING_NREGS = M_REG_HOLDING_NREGS; + usRegHoldStart = usMRegHoldStart; + /* if mode is read, the master will write the received date to buffer. */ + eMode = MB_REG_WRITE; + + /* it already plus one in modbus function method. */ + usAddress--; + + if ((usAddress >= REG_HOLDING_START) + && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS)) + { + iRegIndex = usAddress - usRegHoldStart; + switch (eMode) + { + /* read current register values from the protocol stack. */ + case MB_REG_READ: + while (usNRegs > 0) + { + *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8); + *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF); + iRegIndex++; + usNRegs--; + } + break; + /* write current register values with new values from the protocol stack. */ + case MB_REG_WRITE: + while (usNRegs > 0) + { + pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8; + pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++; + iRegIndex++; + usNRegs--; + } + break; + } + } + else + { + eStatus = MB_ENOREG; + } + return eStatus; +} + +/** + * Modbus master coils callback function. + * + * @param pucRegBuffer coils buffer + * @param usAddress coils address + * @param usNCoils coils number + * @param eMode read or write + * + * @return result + */ +eMBErrorCode eMBMasterRegCoilsCB(UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNCoils, eMBRegisterMode eMode) +{ + eMBErrorCode eStatus = MB_ENOERR; + USHORT iRegIndex , iRegBitIndex , iNReg; + UCHAR * pucCoilBuf; + USHORT COIL_START; + USHORT COIL_NCOILS; + USHORT usCoilStart; + iNReg = usNCoils / 8 + 1; + + pucCoilBuf = ucMCoilBuf[ucMBMasterGetDestAddress() - 1]; + COIL_START = M_COIL_START; + COIL_NCOILS = M_COIL_NCOILS; + usCoilStart = usMCoilStart; + + /* if mode is read,the master will write the received date to buffer. */ + eMode = MB_REG_WRITE; + + /* it already plus one in modbus function method. */ + usAddress--; + + if ((usAddress >= COIL_START) + && (usAddress + usNCoils <= COIL_START + COIL_NCOILS)) + { + iRegIndex = (USHORT) (usAddress - usCoilStart) / 8; + iRegBitIndex = (USHORT) (usAddress - usCoilStart) % 8; + switch (eMode) + { + /* read current coil values from the protocol stack. */ + case MB_REG_READ: + while (iNReg > 0) + { + *pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++], + iRegBitIndex, 8); + iNReg--; + } + pucRegBuffer--; + /* last coils */ + usNCoils = usNCoils % 8; + /* filling zero to high bit */ + *pucRegBuffer = *pucRegBuffer << (8 - usNCoils); + *pucRegBuffer = *pucRegBuffer >> (8 - usNCoils); + break; + + /* write current coil values with new values from the protocol stack. */ + case MB_REG_WRITE: + while (iNReg > 1) + { + xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, 8, + *pucRegBuffer++); + iNReg--; + } + /* last coils */ + usNCoils = usNCoils % 8; + /* xMBUtilSetBits has bug when ucNBits is zero */ + if (usNCoils != 0) + { + xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils, + *pucRegBuffer++); + } + break; + } + } + else + { + eStatus = MB_ENOREG; + } + return eStatus; +} + +/** + * Modbus master discrete callback function. + * + * @param pucRegBuffer discrete buffer + * @param usAddress discrete address + * @param usNDiscrete discrete number + * + * @return result + */ +eMBErrorCode eMBMasterRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete ) +{ + eMBErrorCode eStatus = MB_ENOERR; + USHORT iRegIndex , iRegBitIndex , iNReg; + UCHAR * pucDiscreteInputBuf; + USHORT DISCRETE_INPUT_START; + USHORT DISCRETE_INPUT_NDISCRETES; + USHORT usDiscreteInputStart; + iNReg = usNDiscrete / 8 + 1; + + pucDiscreteInputBuf = ucMDiscInBuf[ucMBMasterGetDestAddress() - 1]; + DISCRETE_INPUT_START = M_DISCRETE_INPUT_START; + DISCRETE_INPUT_NDISCRETES = M_DISCRETE_INPUT_NDISCRETES; + usDiscreteInputStart = usMDiscInStart; + + /* it already plus one in modbus function method. */ + usAddress--; + + if ((usAddress >= DISCRETE_INPUT_START) + && (usAddress + usNDiscrete <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES)) + { + iRegIndex = (USHORT) (usAddress - usDiscreteInputStart) / 8; + iRegBitIndex = (USHORT) (usAddress - usDiscreteInputStart) % 8; + + /* write current discrete values with new values from the protocol stack. */ + while (iNReg > 1) + { + xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex, 8, + *pucRegBuffer++); + iNReg--; + } + /* last discrete */ + usNDiscrete = usNDiscrete % 8; + /* xMBUtilSetBits has bug when ucNBits is zero */ + if (usNDiscrete != 0) + { + xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex, + usNDiscrete, *pucRegBuffer++); + } + } + else + { + eStatus = MB_ENOREG; + } + + return eStatus; +} +#endif diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/Makefile b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/Makefile new file mode 100644 index 000000000..fba1741d8 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/Makefile @@ -0,0 +1,13 @@ +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_RTU_MASTER),y) + SRC_FILES := sample_mb_master.c +endif + +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_RTU_SLAVE),y) + SRC_FILES := sample_mb_slave.c +endif + +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_TCP_SLAVE),y) + SRC_FILES := sample_mb_slave.c +endif + +include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/README.md b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/README.md new file mode 100644 index 000000000..25bfaa978 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/README.md @@ -0,0 +1,57 @@ +# 示例代码说明 + +## 运行方法 + +### 配置工程 + +使用 Freemodbus 软件包示例代码,需要在 RT-Thread 的包管理器中选择它,并根据需要进行配置,具体路径如下: + +``` +RT-Thread online packages + IoT - internet of things ---> + [*] FreeModbus: Modbus master and slave stack ---> + [*] Master mode ---> + [*] Enable RTU master mode + [*] Enable master sample + (1) Test slave device address + (2) uart number used by master sample, e.g. 2 means uart2 + (115200) uart baudrate used by master sample + [*] Slave mode ---> + [*] Enable RTU slave mode + [ ] Enable ASCII slave mode + [ ] Use Contorl Pin + [*] Enable slave sample + (1) Slave device address + (2) uart number used by slave sample, e.g. 2 means uart2 + (115200) uart baudrate used by slave sample +``` + +添加示例代码到工程中,并编译下载之后,可以在控制台中看到这两个命令,分别是 Modbus 主机和从机的示例代码。要看代码运行的效果还需要 PC 端 Modbus Poll 和 Modbus slave 这两个软件的配合。 + +![1561348568591](figures/run.png) + +### 运行主机示例 + +首先下载安装和主机示例代码配合的 Modbus slave 软件。 + +然后,在命令行输入 `mb_master_sample` 命令就可以运行主机的示例代码。 + +运行之后,打开 Modbus slave 软件,点击菜单“Setup”中“Slave Definition.. F2”进行参数设置。 + +![img](figures/slave_cfg.png) + +点击菜单“Connection”中“Connect.. F3”进行连接。弹出连接对话框,根据具体情况配置: + +![1561351899477](figures/slave_con.png) + +连接成功,可以看到寄存器列表中的第 2、3个寄存器的数值在不断变化。 + +![1561352048209](figures/slave_run.png) + +### 运行从机示例 + +从机的运行示例和主机相差不大,只是 PC 端配合调试的软件,换成 Modbus Poll 即可。不再赘述。 + +## 注意事项 + +- 暂无 diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/figures/run.png b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/figures/run.png new file mode 100644 index 000000000..188449395 Binary files /dev/null and b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/figures/run.png differ diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/figures/slave_cfg.png b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/figures/slave_cfg.png new file mode 100644 index 000000000..1d6aa94e4 Binary files /dev/null and b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/figures/slave_cfg.png differ diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/figures/slave_con.png b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/figures/slave_con.png new file mode 100644 index 000000000..925bd9e2d Binary files /dev/null and b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/figures/slave_con.png differ diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/figures/slave_run.png b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/figures/slave_run.png new file mode 100644 index 000000000..859184ae5 Binary files /dev/null and b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/figures/slave_run.png differ diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/sample_mb_master.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/sample_mb_master.c new file mode 100644 index 000000000..e0394d965 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/sample_mb_master.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-06-21 flybreak first version + */ + +/** +* @file sample_mb_master.c +* @brief support freemodbus port for XiUOS +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-10-12 +*/ + +/************************************************* +File name: sample_mb_master.c +Description: support freemodbus port for XiUOS +Others: +History: +1. Date: 2023-10-12 +Author: AIIT XUOS Lab +Modification: +1、support XiUOS for master demo. +*************************************************/ + +#include + +#ifdef ADD_RTTHREAD_FEATURES +#include +#endif + +#include "mb.h" +#include "mb_m.h" + +#ifdef ADD_RTTHREAD_FEATURES +#ifdef PKG_MODBUS_MASTER_SAMPLE +#define SLAVE_ADDR MB_SAMPLE_TEST_SLAVE_ADDR +#define PORT_NUM MB_MASTER_USING_PORT_NUM +#define PORT_BAUDRATE MB_MASTER_USING_PORT_BAUDRATE +#else +#define SLAVE_ADDR 0x01 +#define PORT_NUM 3 +#define PORT_BAUDRATE 115200 +#endif +#define PORT_PARITY MB_PAR_EVEN + +#define MB_POLL_THREAD_PRIORITY 10 +#define MB_SEND_THREAD_PRIORITY RT_THREAD_PRIORITY_MAX - 1 + +#define MB_SEND_REG_START 2 +#define MB_SEND_REG_NUM 2 + +#define MB_POLL_CYCLE_MS 500 + +static void send_thread_entry(void *parameter) +{ + eMBMasterReqErrCode error_code = MB_MRE_NO_ERR; + rt_uint16_t error_count = 0; + USHORT data[MB_SEND_REG_NUM] = {0}; + + while (1) + { + /* Test Modbus Master */ + data[0] = (USHORT)(rt_tick_get() / 10); + data[1] = (USHORT)(rt_tick_get() % 10); + + error_code = eMBMasterReqWriteMultipleHoldingRegister(SLAVE_ADDR, /* salve address */ + MB_SEND_REG_START, /* register start address */ + MB_SEND_REG_NUM, /* register total number */ + data, /* data to be written */ + RT_WAITING_FOREVER); /* timeout */ + + /* Record the number of errors */ + if (error_code != MB_MRE_NO_ERR) + { + error_count++; + } + } +} + +static void mb_master_poll(void *parameter) +{ + eMBMasterInit(MB_RTU, PORT_NUM, PORT_BAUDRATE, PORT_PARITY); + eMBMasterEnable(); + + while (1) + { + eMBMasterPoll(); + rt_thread_mdelay(MB_POLL_CYCLE_MS); + } +} + +static int mb_master_sample(int argc, char **argv) +{ + static rt_uint8_t is_init = 0; + rt_thread_t tid1 = RT_NULL, tid2 = RT_NULL; + + if (is_init > 0) + { + rt_kprintf("sample is running\n"); + return -RT_ERROR; + } + tid1 = rt_thread_create("md_m_poll", mb_master_poll, RT_NULL, 512, MB_POLL_THREAD_PRIORITY, 10); + if (tid1 != RT_NULL) + { + rt_thread_startup(tid1); + } + else + { + goto __exit; + } + + tid2 = rt_thread_create("md_m_send", send_thread_entry, RT_NULL, 512, MB_SEND_THREAD_PRIORITY, 10); + if (tid2 != RT_NULL) + { + rt_thread_startup(tid2); + } + else + { + goto __exit; + } + + is_init = 1; + return RT_EOK; + +__exit: + if (tid1) + rt_thread_delete(tid1); + if (tid2) + rt_thread_delete(tid2); + + return -RT_ERROR; +} +MSH_CMD_EXPORT(mb_master_sample, run a modbus master sample); +#endif + +#ifdef ADD_XIZI_FEATURES +#define SLAVE_ADDR 0x01 +#define PORT_NUM 4 +#define PORT_BAUDRATE 115200 +#define PORT_PARITY MB_PAR_NONE + +#define MB_POLL_THREAD_PRIORITY 22 +#define MB_SEND_THREAD_PRIORITY 22 + +#define MB_SEND_REG_START 2 +#define MB_SEND_REG_NUM 2 + +#define MB_POLL_CYCLE_MS 500 + +static pthread_t tid1, tid2; + +static void *send_thread_entry(void *parameter) +{ + eMBMasterReqErrCode error_code = MB_MRE_NO_ERR; + uint16_t error_count = 0; + USHORT data[MB_SEND_REG_NUM] = {0}; + + while (1) { + /* Test Modbus Master */ + data[0] = (USHORT)(PrivGetTickTime() / 10); + data[1] = (USHORT)(PrivGetTickTime() % 10); + + error_code = eMBMasterReqWriteMultipleHoldingRegister(SLAVE_ADDR, /* salve address */ + MB_SEND_REG_START, /* register start address */ + MB_SEND_REG_NUM, /* register total number */ + data, /* data to be written */ + 0); /* timeout */ + + /* Record the number of errors */ + if (error_code != MB_MRE_NO_ERR) { + error_count++; + } + } +} + +static void *mb_master_poll(void *parameter) +{ + eMBMasterInit(MB_RTU, PORT_NUM, PORT_BAUDRATE, PORT_PARITY); + eMBMasterEnable(); + + while (1) { + eMBMasterPoll(); + PrivTaskDelay(MB_POLL_CYCLE_MS); + } +} + +static int mb_master_sample(void) +{ + static uint8_t is_init = 0; + + if (is_init > 0) { + printf("sample is running\n"); + return -1; + } + + pthread_attr_t attr; + attr.schedparam.sched_priority = MB_POLL_THREAD_PRIORITY; + attr.stacksize = 2048; + + char task1_name[] = "md_m_poll"; + pthread_args_t args; + args.pthread_name = task1_name; + + PrivTaskCreate(&tid1, &attr, &mb_master_poll, (void *)&args); + PrivTaskStartup(&tid1); + + attr.schedparam.sched_priority = MB_SEND_THREAD_PRIORITY; + attr.stacksize = 2048; + + char task2_name[] = "md_m_send"; + args.pthread_name = task2_name; + + PrivTaskCreate(&tid2, &attr, &send_thread_entry, (void *)&args); + PrivTaskStartup(&tid2); + + is_init = 1; + return 0; +} +PRIV_SHELL_CMD_FUNCTION(mb_master_sample, run a modbus master sample, PRIV_SHELL_CMD_MAIN_ATTR); +#endif + diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/sample_mb_slave.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/sample_mb_slave.c new file mode 100644 index 000000000..90faa5db9 --- /dev/null +++ b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/samples/sample_mb_slave.c @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-06-21 flybreak first version + */ + +/** +* @file sample_mb_slave.c +* @brief support freemodbus port for XiUOS +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-10-12 +*/ + +/************************************************* +File name: sample_mb_slave.c +Description: support freemodbus port for XiUOS +Others: +History: +1. Date: 2023-10-12 +Author: AIIT XUOS Lab +Modification: +1、support XiUOS for slave demo. +*************************************************/ + +#include + +#ifdef ADD_RTTHREAD_FEATURES +#include +#endif + +#include "mb.h" +#include "user_mb_app.h" + +#ifdef ADD_RTTHREAD_FEATURES +#ifdef PKG_MODBUS_SLAVE_SAMPLE +#define SLAVE_ADDR MB_SAMPLE_SLAVE_ADDR +#define PORT_NUM MB_SLAVE_USING_PORT_NUM +#define PORT_BAUDRATE MB_SLAVE_USING_PORT_BAUDRATE +#else +#define SLAVE_ADDR 0x01 +#define PORT_NUM 2 +#define PORT_BAUDRATE 115200 +#endif + +#define PORT_PARITY MB_PAR_EVEN + +#define MB_POLL_THREAD_PRIORITY 10 +#define MB_SEND_THREAD_PRIORITY RT_THREAD_PRIORITY_MAX - 1 + +#define MB_POLL_CYCLE_MS 200 + +extern USHORT usSRegHoldBuf[S_REG_HOLDING_NREGS]; + +static void send_thread_entry(void *parameter) +{ + USHORT *usRegHoldingBuf; + usRegHoldingBuf = usSRegHoldBuf; + rt_base_t level; + + while (1) + { + /* Test Modbus Master */ + level = rt_hw_interrupt_disable(); + + usRegHoldingBuf[3] = (USHORT)(rt_tick_get() / 100); + + rt_hw_interrupt_enable(level); + + rt_thread_mdelay(1000); + } +} + +static void mb_slave_poll(void *parameter) +{ + if (rt_strstr(parameter, "RTU")) + { +#ifdef PKG_MODBUS_SLAVE_RTU + eMBInit(MB_RTU, SLAVE_ADDR, PORT_NUM, PORT_BAUDRATE, PORT_PARITY); +#else + rt_kprintf("Error: Please open RTU mode first"); +#endif + } + else if (rt_strstr(parameter, "ASCII")) + { +#ifdef PKG_MODBUS_SLAVE_ASCII + eMBInit(MB_ASCII, SLAVE_ADDR, PORT_NUM, PORT_BAUDRATE, PORT_PARITY); +#else + rt_kprintf("Error: Please open ASCII mode first"); +#endif + } + else if (rt_strstr(parameter, "TCP")) + { +#ifdef PKG_MODBUS_SLAVE_TCP + eMBTCPInit(0); +#else + rt_kprintf("Error: Please open TCP mode first"); +#endif + } + else + { + rt_kprintf("Error: unknown parameter"); + } + eMBEnable(); + while (1) + { + eMBPoll(); + rt_thread_mdelay(MB_POLL_CYCLE_MS); + } +} + +static int mb_slave_sample(int argc, char **argv) +{ + static rt_uint8_t is_init = 0; + rt_thread_t tid1 = RT_NULL, tid2 = RT_NULL; + + if (is_init > 0) + { + rt_kprintf("sample is running\n"); + return -RT_ERROR; + } + if (argc < 2) + { + rt_kprintf("Usage: mb_slave_sample RTU/ASCII/TCP\n"); + return -1; + } + + tid1 = rt_thread_create("md_s_poll", mb_slave_poll, argv[1], 1024, MB_POLL_THREAD_PRIORITY, 10); + if (tid1 != RT_NULL) + { + rt_thread_startup(tid1); + } + else + { + goto __exit; + } + + tid2 = rt_thread_create("md_s_send", send_thread_entry, RT_NULL, 512, MB_SEND_THREAD_PRIORITY, 10); + if (tid2 != RT_NULL) + { + rt_thread_startup(tid2); + } + else + { + goto __exit; + } + + is_init = 1; + return RT_EOK; + +__exit: + if (tid1) + rt_thread_delete(tid1); + if (tid2) + rt_thread_delete(tid2); + + return -RT_ERROR; +} +MSH_CMD_EXPORT(mb_slave_sample, run a modbus slave sample); +#endif + +#ifdef ADD_XIZI_FEATURES +#define SLAVE_ADDR 0x01 +#define PORT_NUM 4 +#define PORT_BAUDRATE 115200 + +#define PORT_PARITY MB_PAR_NONE + +#define MB_POLL_THREAD_PRIORITY 22 +#define MB_SEND_THREAD_PRIORITY 22 + +#define MB_POLL_CYCLE_MS 200 + +extern USHORT usSRegHoldBuf[S_REG_HOLDING_NREGS]; + +static pthread_t tid1, tid2; + +static void *send_thread_entry(void *parameter) +{ + USHORT *usRegHoldingBuf; + usRegHoldingBuf = usSRegHoldBuf; + int level; + + while (1) { + /* Test Modbus Master */ + level = DISABLE_INTERRUPT(); + + usRegHoldingBuf[3] = (USHORT)(PrivGetTickTime() / 100); + + ENABLE_INTERRUPT(level); + + PrivTaskDelay(1000); + } +} + +static void *mb_slave_poll(void *parameter) +{ + eMBInit(MB_RTU, SLAVE_ADDR, PORT_NUM, PORT_BAUDRATE, PORT_PARITY); + eMBEnable(); + + while (1) { + eMBPoll(); + PrivTaskDelay(MB_POLL_CYCLE_MS); + } +} + +static int mb_slave_sample(void) +{ + static uint8_t is_init = 0; + + if (is_init > 0) { + printf("sample is running\n"); + return -1; + } + + pthread_attr_t attr; + attr.schedparam.sched_priority = MB_POLL_THREAD_PRIORITY; + attr.stacksize = 2048; + + char task1_name[] = "md_s_poll"; + pthread_args_t args; + args.arg = NULL; + args.pthread_name = task1_name; + + PrivTaskCreate(&tid1, &attr, &mb_slave_poll, (void *)&args); + PrivTaskStartup(&tid1); + + attr.schedparam.sched_priority = MB_SEND_THREAD_PRIORITY; + attr.stacksize = 2048; + + char task2_name[] = "md_s_send"; + args.arg = NULL; + args.pthread_name = task2_name; + + PrivTaskCreate(&tid2, &attr, &send_thread_entry, (void *)&args); + PrivTaskStartup(&tid2); + + is_init = 1; + return 0; +} +PRIV_SHELL_CMD_FUNCTION(mb_slave_sample, run a modbus slave sample, PRIV_SHELL_CMD_MAIN_ATTR); +#endif diff --git a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/modbus_rtu.c b/APP_Framework/Framework/connection/industrial_fieldbus/modbus/modbus_rtu.c deleted file mode 100644 index 13dca9165..000000000 --- a/APP_Framework/Framework/connection/industrial_fieldbus/modbus/modbus_rtu.c +++ /dev/null @@ -1,144 +0,0 @@ -/* -* 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 modbus_rtu.c - * @brief Implement the connection Modbus RTU adapter function, using Modbus rtu device - * @version 1.1 - * @author AIIT XUOS Lab - * @date 2021.07.08 - */ - -#include -#define PLC_DATA_LENGTH 1024 -struct CircularAreaApp *g_circular_area; -static pthread_t recv_plc_data_task; -/** - * @description: Open modbus rtu function - * @param adapter - Modbus RTU device pointer - * @return success: 0, failure: -1 - */ -static int ModbusRtuOpen(struct Adapter *adapter) -{ - - /* open serial port*/ - adapter->fd = PrivOpen("/dev/tty3", 2);//2 read and write - if (adapter->fd < 0) { - printf("ModbusRtuOpen get serial %s fd error\n", "/dev/tty3"); - return -1; - } - - PrivTaskDelay(2500); - - ADAPTER_DEBUG("Modbus rtu open done\n"); - - return 0; -} - -/** - * @description: Close modbus rtu function - * @param adapter - Modbus RTu device pointer - * @return success: 0, failure: -1 - */ -static int ModbusRtuClose(struct Adapter *adapter) -{ - /*step1: close modbus serial port*/ - int ret; - ret = PrivClose(adapter->fd); - if(ret < 0){ - printf("ModbusRtuOpen close serial %s fd error\n", "/dev/tty3"); - return -1; - } - - ADAPTER_DEBUG("Modbus rtu Close done\n"); - - return 0; -} - -static int ModbusRtuIoctl(struct Adapter *adapter, int cmd) -{ - - // uint32_t baud_rate = *((uint32_t *)args); - - struct SerialDataCfg serial_cfg; - memset(&serial_cfg, 0 ,sizeof(struct SerialDataCfg)); - serial_cfg.serial_baud_rate = BAUD_RATE_9600 ; - serial_cfg.serial_data_bits = DATA_BITS_8; - serial_cfg.serial_stop_bits = STOP_BITS_1; - serial_cfg.serial_buffer_size = SERIAL_RB_BUFSZ; - serial_cfg.serial_parity_mode = PARITY_EVEN; - serial_cfg.serial_bit_order = STOP_BITS_1; - serial_cfg.serial_invert_mode = NRZ_NORMAL; - serial_cfg.is_ext_uart = 0; - - struct PrivIoctlCfg ioctl_cfg; - ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; - ioctl_cfg.args = &serial_cfg; - PrivIoctl(adapter->fd, OPE_INT, &ioctl_cfg); - - return 0; -} - -static int ModbusRtuSend(struct Adapter *adapter, const void *buf, size_t len) -{ - int ret; - ret = PrivWrite(adapter->fd, buf, len); - if(ret < 0){ - printf("send failed %d!\n", ret); - } - - return ret; -} - -static int ModbusRtuRecv(struct Adapter *adapter, void *buf, size_t len) -{ - int recv_len=0, recv_len_continue=0; - - uint8 *recv_buf = PrivMalloc(len); - - recv_len = PrivRead(adapter->fd, recv_buf, len); - if (recv_len) { - while (recv_len < len) { - recv_len_continue = PrivRead(adapter->fd, recv_buf + recv_len, len - recv_len); - if (recv_len_continue) { - recv_len += recv_len_continue; - } else { - recv_len = 0; - break; - } - } - memcpy(buf, recv_buf, len); - } - - PrivFree(recv_buf); - - return recv_len; -} - - -static const struct IpProtocolDone ec200t_done = -{ - .open = ModbusRtuOpen, - .close = ModbusRtuClose, - .ioctl = ModbusRtuIoctl, - .setup = NULL, - .setdown = NULL, - .setaddr = NULL, - .setdns = NULL, - .setdhcp = NULL, - .ping = NULL, - .netstat = NULL, - .connect = NULL, - .send = ModbusRtuSend, - .recv = ModbusRtuRecv, - .disconnect = NULL, -}; \ No newline at end of file diff --git a/APP_Framework/Framework/connection/lora/e22/e22.c b/APP_Framework/Framework/connection/lora/e22/e22.c index 677c02083..4cf16f88f 100644 --- a/APP_Framework/Framework/connection/lora/e22/e22.c +++ b/APP_Framework/Framework/connection/lora/e22/e22.c @@ -290,6 +290,7 @@ static int E22Open(struct Adapter *adapter) //serial receive wait forever cfg.serial_timeout = -1; #endif + cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; diff --git a/APP_Framework/Framework/connection/lora/e220/e220.c b/APP_Framework/Framework/connection/lora/e220/e220.c index 9a6bbf3c6..a94f24623 100644 --- a/APP_Framework/Framework/connection/lora/e220/e220.c +++ b/APP_Framework/Framework/connection/lora/e220/e220.c @@ -374,6 +374,7 @@ static int E220Open(struct Adapter *adapter) //serial receive wait forever cfg.serial_timeout = -1; #endif + cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; @@ -428,6 +429,7 @@ static int E220Open(struct Adapter *adapter) //serial receive wait forever cfg.serial_timeout = -1; #endif + cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; diff --git a/APP_Framework/Framework/connection/nbiot/bc28/bc28.c b/APP_Framework/Framework/connection/nbiot/bc28/bc28.c index fb2887d7a..03eca2666 100644 --- a/APP_Framework/Framework/connection/nbiot/bc28/bc28.c +++ b/APP_Framework/Framework/connection/nbiot/bc28/bc28.c @@ -63,6 +63,7 @@ static int BC28UartOpen(struct Adapter *adapter) cfg.ext_uart_no = ADAPTER_BC28_DRIVER_EXT_PORT; cfg.port_configure = PORT_CFG_INIT; #endif + cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; diff --git a/APP_Framework/Framework/connection/wifi/esp07s_wifi/esp07s_wifi.c b/APP_Framework/Framework/connection/wifi/esp07s_wifi/esp07s_wifi.c index 4a1aa830d..7c49dc539 100755 --- a/APP_Framework/Framework/connection/wifi/esp07s_wifi/esp07s_wifi.c +++ b/APP_Framework/Framework/connection/wifi/esp07s_wifi/esp07s_wifi.c @@ -81,6 +81,7 @@ static int Esp07sUartOpen(struct Adapter *adapter) cfg.ext_uart_no = ADAPTER_ESP07S_DRIVER_EXT_PORT; cfg.port_configure = PORT_CFG_INIT; #endif + cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; @@ -527,6 +528,7 @@ static int Esp07sWifiIoctl(struct Adapter *adapter, int cmd, void *args) cfg.serial_invert_mode = NRZ_NORMAL; cfg.serial_buffer_size = SERIAL_RB_BUFSZ; cfg.is_ext_uart = 0; + cfg.dev_recv_callback = NULL; #ifdef ADAPTER_ESP07S_DRIVER_EXT_PORT cfg.is_ext_uart = 1; cfg.ext_uart_no = ADAPTER_ESP07S_DRIVER_EXT_PORT; diff --git a/APP_Framework/Framework/connection/wifi/esp8285_wifi/esp8285_wifi.c b/APP_Framework/Framework/connection/wifi/esp8285_wifi/esp8285_wifi.c index 3c87225f1..32aa23933 100644 --- a/APP_Framework/Framework/connection/wifi/esp8285_wifi/esp8285_wifi.c +++ b/APP_Framework/Framework/connection/wifi/esp8285_wifi/esp8285_wifi.c @@ -81,6 +81,7 @@ static int Esp8285UartOpen(struct Adapter *adapter) cfg.ext_uart_no = ADAPTER_ESP8285_DRIVER_EXT_PORT; cfg.port_configure = PORT_CFG_INIT; #endif + cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; @@ -507,6 +508,7 @@ static int Esp8285WifiIoctl(struct Adapter *adapter, int cmd, void *args) cfg.serial_invert_mode = NRZ_NORMAL; cfg.serial_buffer_size = SERIAL_RB_BUFSZ; cfg.is_ext_uart = 0; + cfg.dev_recv_callback = NULL; #ifdef ADAPTER_ESP8285_DRIVER_EXT_PORT cfg.is_ext_uart = 1; cfg.ext_uart_no = ADAPTER_ESP8285_DRIVER_EXT_PORT; diff --git a/APP_Framework/Framework/connection/wifi/hfa21_wifi/hfa21_wifi.c b/APP_Framework/Framework/connection/wifi/hfa21_wifi/hfa21_wifi.c index 82545d96a..048a52f94 100755 --- a/APP_Framework/Framework/connection/wifi/hfa21_wifi/hfa21_wifi.c +++ b/APP_Framework/Framework/connection/wifi/hfa21_wifi/hfa21_wifi.c @@ -479,6 +479,7 @@ static int Hfa21WifiIoctl(struct Adapter *adapter, int cmd, void *args) serial_cfg.ext_uart_no = ADAPTER_HFA21_DRIVER_EXT_PORT; serial_cfg.port_configure = PORT_CFG_INIT; #endif + serial_cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; diff --git a/APP_Framework/Framework/connection/zigbee/e18/e18.c b/APP_Framework/Framework/connection/zigbee/e18/e18.c index 4ebc8aed9..f7fd7c74d 100644 --- a/APP_Framework/Framework/connection/zigbee/e18/e18.c +++ b/APP_Framework/Framework/connection/zigbee/e18/e18.c @@ -160,6 +160,7 @@ static int E18UartOpen(struct Adapter *adapter) cfg.ext_uart_no = ADAPTER_E18_DRIVER_EXT_PORT; cfg.port_configure = PORT_CFG_INIT; #endif + cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; diff --git a/APP_Framework/Framework/control/shared/control_io.c b/APP_Framework/Framework/control/shared/control_io.c index f66917152..d99d4b03f 100644 --- a/APP_Framework/Framework/control/shared/control_io.c +++ b/APP_Framework/Framework/control/shared/control_io.c @@ -97,6 +97,7 @@ void Uart485Init(uint32_t baud_rate, uint8_t data_bits, uint8_t stop_bits, uint8 cfg.port_configure = PORT_CFG_INIT; #endif cfg.serial_timeout = 10000; + cfg.dev_recv_callback = NULL; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; ioctl_cfg.args = &cfg; diff --git a/APP_Framework/Framework/sensor/ch4/as830/as830.c b/APP_Framework/Framework/sensor/ch4/as830/as830.c index 50b3a1c5c..9afb24000 100644 --- a/APP_Framework/Framework/sensor/ch4/as830/as830.c +++ b/APP_Framework/Framework/sensor/ch4/as830/as830.c @@ -58,6 +58,7 @@ static int SensorDeviceOpen(struct SensorDevice *sdev) cfg.ext_uart_no = SENSOR_DEVICE_AS830_DEV_EXT_PORT; cfg.port_configure = PORT_CFG_INIT; #endif + cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; diff --git a/APP_Framework/Framework/sensor/co2/g8s/g8s.c b/APP_Framework/Framework/sensor/co2/g8s/g8s.c index e0764c4b3..6a45081b2 100644 --- a/APP_Framework/Framework/sensor/co2/g8s/g8s.c +++ b/APP_Framework/Framework/sensor/co2/g8s/g8s.c @@ -62,6 +62,7 @@ static int SensorDeviceOpen(struct SensorDevice *sdev) cfg.ext_uart_no = SENSOR_DEVICE_G8S_DEV_EXT_PORT; cfg.port_configure = PORT_CFG_INIT; #endif + cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; diff --git a/APP_Framework/Framework/sensor/co2/zg09/zg09.c b/APP_Framework/Framework/sensor/co2/zg09/zg09.c index 3f5bcb925..852287757 100644 --- a/APP_Framework/Framework/sensor/co2/zg09/zg09.c +++ b/APP_Framework/Framework/sensor/co2/zg09/zg09.c @@ -62,6 +62,7 @@ static int SensorDeviceOpen(struct SensorDevice *sdev) cfg.ext_uart_no = SENSOR_DEVICE_ZG09_DEV_EXT_PORT; cfg.port_configure = PORT_CFG_INIT; #endif + cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; diff --git a/APP_Framework/Framework/sensor/hcho/tb600b_wq_hcho1os/tb600b_wq_hcho1os.c b/APP_Framework/Framework/sensor/hcho/tb600b_wq_hcho1os/tb600b_wq_hcho1os.c index d1b0d3d28..2ef38611f 100644 --- a/APP_Framework/Framework/sensor/hcho/tb600b_wq_hcho1os/tb600b_wq_hcho1os.c +++ b/APP_Framework/Framework/sensor/hcho/tb600b_wq_hcho1os/tb600b_wq_hcho1os.c @@ -59,6 +59,7 @@ static int SensorDeviceOpen(struct SensorDevice *sdev) cfg.ext_uart_no = SENSOR_DEVICE_TB600B_WQ_HCHO1OS_DEV_EXT_PORT; cfg.port_configure = PORT_CFG_INIT; #endif + cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; diff --git a/APP_Framework/Framework/sensor/iaq/tb600b_iaq10/tb600b_iaq10.c b/APP_Framework/Framework/sensor/iaq/tb600b_iaq10/tb600b_iaq10.c index 4d0a99ed3..1b97653f4 100644 --- a/APP_Framework/Framework/sensor/iaq/tb600b_iaq10/tb600b_iaq10.c +++ b/APP_Framework/Framework/sensor/iaq/tb600b_iaq10/tb600b_iaq10.c @@ -67,6 +67,7 @@ static int SensorDeviceOpen(struct SensorDevice *sdev) cfg.ext_uart_no = SENSOR_DEVICE_TB600B_IAQ10_DEV_EXT_PORT; cfg.port_configure = PORT_CFG_INIT; #endif + cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; diff --git a/APP_Framework/Framework/sensor/pm/ps5308/ps5308.c b/APP_Framework/Framework/sensor/pm/ps5308/ps5308.c index e1c405c0d..651c4705a 100644 --- a/APP_Framework/Framework/sensor/pm/ps5308/ps5308.c +++ b/APP_Framework/Framework/sensor/pm/ps5308/ps5308.c @@ -77,6 +77,7 @@ static int SensorDeviceOpen(struct SensorDevice *sdev) cfg.ext_uart_no = SENSOR_DEVICE_PS5308_DEV_EXT_PORT; cfg.port_configure = PORT_CFG_INIT; #endif + cfg.dev_recv_callback = NULL; result = PrivIoctl(sdev->fd, OPE_INT, &cfg); diff --git a/APP_Framework/Framework/sensor/tvoc/tb600b_tvoc10/tb600b_tvoc10.c b/APP_Framework/Framework/sensor/tvoc/tb600b_tvoc10/tb600b_tvoc10.c index 136597121..53a21f457 100644 --- a/APP_Framework/Framework/sensor/tvoc/tb600b_tvoc10/tb600b_tvoc10.c +++ b/APP_Framework/Framework/sensor/tvoc/tb600b_tvoc10/tb600b_tvoc10.c @@ -59,6 +59,7 @@ static int SensorDeviceOpen(struct SensorDevice *sdev) cfg.ext_uart_no = SENSOR_DEVICE_TB600B_TVOC10_DEV_EXT_PORT; cfg.port_configure = PORT_CFG_INIT; #endif + cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; diff --git a/APP_Framework/Framework/sensor/voice/d124/d124.c b/APP_Framework/Framework/sensor/voice/d124/d124.c index cdbf3895e..7032ad208 100644 --- a/APP_Framework/Framework/sensor/voice/d124/d124.c +++ b/APP_Framework/Framework/sensor/voice/d124/d124.c @@ -107,6 +107,7 @@ static int SensorDeviceOpen(struct SensorDevice *sdev) cfg.ext_uart_no = SENSOR_DEVICE_D124_DEV_EXT_PORT; cfg.port_configure = PORT_CFG_INIT; #endif + cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; diff --git a/APP_Framework/Framework/sensor/winddirection/qs-fx/qs-fx.c b/APP_Framework/Framework/sensor/winddirection/qs-fx/qs-fx.c index d26c44e80..e3af110ad 100644 --- a/APP_Framework/Framework/sensor/winddirection/qs-fx/qs-fx.c +++ b/APP_Framework/Framework/sensor/winddirection/qs-fx/qs-fx.c @@ -60,6 +60,7 @@ static int SensorDeviceOpen(struct SensorDevice *sdev) cfg.ext_uart_no = SENSOR_DEVICE_QS_FX_DEV_EXT_PORT; cfg.port_configure = PORT_CFG_INIT; #endif + cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; diff --git a/APP_Framework/Framework/sensor/windspeed/qs-fs/qs-fs.c b/APP_Framework/Framework/sensor/windspeed/qs-fs/qs-fs.c index ff8651fcb..a2d304377 100644 --- a/APP_Framework/Framework/sensor/windspeed/qs-fs/qs-fs.c +++ b/APP_Framework/Framework/sensor/windspeed/qs-fs/qs-fs.c @@ -59,6 +59,7 @@ static int SensorDeviceOpen(struct SensorDevice *sdev) cfg.ext_uart_no = SENSOR_DEVICE_QS_FS_DEV_EXT_PORT; cfg.port_configure = PORT_CFG_INIT; #endif + cfg.dev_recv_callback = NULL; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; diff --git a/Ubiquitous/XiZi_IIoT/Makefile b/Ubiquitous/XiZi_IIoT/Makefile index de3ea3e86..4ecef27a7 100755 --- a/Ubiquitous/XiZi_IIoT/Makefile +++ b/Ubiquitous/XiZi_IIoT/Makefile @@ -50,6 +50,7 @@ export SRC_DIR:= $(SRC_APP_DIR) $(SRC_KERNEL_DIR) export LIBCC export MUSL_DIR := $(KERNEL_ROOT)/lib/musllib export LWIP_DIR := $(KERNEL_ROOT)/resources/ethernet +export MONGOOSE_DIR := $(KERNEL_ROOT)/../../APP_Framework/Applications/mongoose/lib PART:= @@ -74,6 +75,10 @@ ifeq ($(CONFIG_RESOURCES_LWIP), y) PART += COMPILE_LWIP endif +ifeq ($(CONFIG_USE_MONGOOSE), y) +# PART += COMPILE_MONGOOSE +endif + ifeq ($(CONFIG_MCUBOOT_BOOTLOADER), y) PART += COMPILE_BOOTLOADER else ifeq ($(CONFIG_MCUBOOT_APPLICATION), y) @@ -130,6 +135,15 @@ COMPILE_LWIP: @cp build/liblwip.a $(KERNEL_ROOT)/resources/ethernet/LwIP/liblwip.a @rm build/Makefile build/make.obj +COMPILE_MONGOOSE: + @for dir in $(MONGOOSE_DIR);do \ + $(MAKE) -C $$dir COMPILE_TYPE=$@; \ + done + @cp link_mongoose.mk build/Makefile + @$(MAKE) -C build TARGET=mongoose.a LINK_FLAGS=LFLAGS + @cp build/mongoose.a $(KERNEL_ROOT)/../../APP_Framework/Applications/mongoose/mongoose.a + @rm build/Makefile build/make.obj + COMPILE_KERNEL: @for dir in $(SRC_KERNEL_DIR);do \ $(MAKE) -C $$dir; \ diff --git a/Ubiquitous/XiZi_IIoT/board/edu-arm32/config.mk b/Ubiquitous/XiZi_IIoT/board/edu-arm32/config.mk index bb44261da..af0254884 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-arm32/config.mk +++ b/Ubiquitous/XiZi_IIoT/board/edu-arm32/config.mk @@ -1,10 +1,10 @@ export CROSS_COMPILE ?=/usr/bin/arm-none-eabi- -export CFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -fgnu89-inline -Wa,-mimplicit-it=thumb -Werror -Wuninitialized +export CFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O2 -gdwarf-2 -g -fgnu89-inline -Wa,-mimplicit-it=thumb # export CFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g -fgnu89-inline -Wa,-mimplicit-it=thumb -Werror export AFLAGS := -c -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -x assembler-with-cpp -Wa,-mimplicit-it=thumb -gdwarf-2 export LFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Wl,--gc-sections,-Map=XiZi-edu-arm32.map,-cref,-u,Reset_Handler -T $(BSP_ROOT)/link.lds -export CXXFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -Werror +export CXXFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O2 -Werror # export CXXFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g -Werror export APPLFLAGS := diff --git a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/can/connect_can.c b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/can/connect_can.c index 088892e67..df7842f50 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/can/connect_can.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/can/connect_can.c @@ -24,27 +24,29 @@ Others: connect_can.c for references #define CAN_X (CM_CAN2) -#define CAN_TX_PORT (GPIO_PORT_D) -#define CAN_TX_PIN (GPIO_PIN_07) -#define CAN_RX_PORT (GPIO_PORT_D) -#define CAN_RX_PIN (GPIO_PIN_06) -#define CAN_TX_PIN_FUNC (GPIO_FUNC_62) -#define CAN_RX_PIN_FUNC (GPIO_FUNC_63) +#define CAN_TX_PORT (GPIO_PORT_D) +#define CAN_TX_PIN (GPIO_PIN_07) +#define CAN_RX_PORT (GPIO_PORT_D) +#define CAN_RX_PIN (GPIO_PIN_06) +#define CAN_TX_PIN_FUNC (GPIO_FUNC_62) +#define CAN_RX_PIN_FUNC (GPIO_FUNC_63) #define INTSEL_REG ((uint32_t)(&CM_INTC->SEL0)) #define CANX_IRQ_SRC INT_SRC_CAN2_HOST #define CANX_IRQ_NUM 17 #define IRQ_NUM_OFFSET 16 -#define CAN_AF1_ID (0x123UL) -#define CAN_AF1_ID_MSK (0xFFFUL) -#define CAN_AF1_MSK_TYPE CAN_ID_STD -#define CAN_AF2_ID (0x005UL) -#define CAN_AF2_ID_MSK (0x00FUL) -#define CAN_AF2_MSK_TYPE CAN_ID_STD -#define CAN_AF3_ID (0x23UL) -#define CAN_AF3_ID_MSK (0xFFUL) -#define CAN_AF3_MSK_TYPE CAN_ID_STD +#define CAN_AF1_ID (0x123UL) +#define CAN_AF1_ID_MSK (0xFFFUL) +#define CAN_AF1_MSK_TYPE CAN_ID_STD + +#define CAN_AF2_ID (0x005UL) +#define CAN_AF2_ID_MSK (0x00FUL) +#define CAN_AF2_MSK_TYPE CAN_ID_STD + +#define CAN_AF3_ID (0x23UL) +#define CAN_AF3_ID_MSK (0xFFUL) +#define CAN_AF3_MSK_TYPE CAN_ID_STD #ifdef CAN_USING_INTERRUPT void CanIrqHandler(int vector, void *param) @@ -95,18 +97,9 @@ static void CanInit(struct CanDriverConfigure *can_drv_config) stcInit.stcBitCfg.u32TimeSeg2 = can_drv_config->tbs2; stcInit.u8WorkMode = can_drv_config->mode; -#ifdef CAN_USING_FD - stcInit.stcFDCfg.u8TDCSSP = 16U; - stcInit.stcFDCfg.u8CANFDMode = CAN_FD_MODE_ISO_11898; - stcInit.stcFDCfg.stcFBT.u32SEG1 = 16U; - stcInit.stcFDCfg.stcFBT.u32SEG2 = 4U; - stcInit.stcFDCfg.stcFBT.u32SJW = 4U; - stcInit.stcFDCfg.stcFBT.u32Prescaler = 1U; - (void)CAN_FD_Init(APP_CAN_UNIT, &stcInit); -#else FCG_Fcg1PeriphClockCmd(PWC_FCG1_CAN2, ENABLE); (void)CAN_Init(CAN_X, &stcInit); -#endif + CAN_ClearStatus(CAN_X, 0xFFFFFFFFU); #ifdef CAN_USING_INTERRUPT diff --git a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/eth_driver.c b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/eth_driver.c index 25d106209..9b07b399d 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/eth_driver.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/eth_driver.c @@ -278,10 +278,7 @@ struct pbuf* low_level_input(struct netif* netif) return p; } -extern void LwipSetIPTest(int argc, char* argv[]); int HwEthInit(void) { - // lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, lwip_gwaddr); - LwipSetIPTest(1, NULL); return EOK; } diff --git a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/eth_netdev.c b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/eth_netdev.c index 1c5c9d3c5..875a35db0 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/eth_netdev.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/eth_netdev.c @@ -76,6 +76,7 @@ static int lwip_netdev_set_addr_info(struct netdev* netdev, ip_addr_t* ip_addr, netif_set_gw((struct netif*)netdev->user_data, ip_2_ip4(gw)); } } + return 0; } #ifdef LWIP_DNS @@ -92,7 +93,7 @@ static int lwip_netdev_set_dns_server(struct netdev* netdev, uint8_t dns_num, ip } #endif -#ifdef LWIP_DHCP +#if LWIP_DHCP static int lwip_netdev_set_dhcp(struct netdev* netdev, bool is_enabled) { netdev_low_level_set_dhcp_status(netdev, is_enabled); @@ -120,7 +121,7 @@ static const struct netdev_ops lwip_netdev_ops = { #ifdef LWIP_DNS .set_dns_server = lwip_netdev_set_dns_server, #endif -#ifdef LWIP_DHCP +#if LWIP_DHCP .set_dhcp = lwip_netdev_set_dhcp, #endif .set_default = lwip_netdev_set_default, @@ -179,9 +180,9 @@ int lwip_netdev_add(struct netif* lwip_netif) netdev->ops = &lwip_netdev_ops; netdev->hwaddr_len = lwip_netif->hwaddr_len; memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len); - netdev->ip_addr = lwip_netif->ip_addr; - netdev->gw = lwip_netif->gw; - netdev->netmask = lwip_netif->netmask; + netdev->ip_addr = &lwip_netif->ip_addr; + netdev->gw = &lwip_netif->gw; + netdev->netmask = &lwip_netif->netmask; return result; } diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/Makefile b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/Makefile index e994ce1ad..a7dae3fce 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/Makefile @@ -1,4 +1,4 @@ # SRC_FILES := socket.c connect_w5500.c w5500.c wizchip_conf.c spi_interface.c wiz_ping.c connect_w5500_test.c wiz_iperf.c -SRC_FILES := socket.c connect_w5500.c w5500.c wizchip_conf.c spi_interface.c wiz_ping.c connect_w5500_test.c w5x00_lwip.c wiz_iperf.c +SRC_FILES := socket.c connect_w5500.c w5500.c wizchip_conf.c spi_interface.c w5x00_lwip.c include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c index dc29ff22d..ee99dcb78 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c @@ -328,8 +328,12 @@ int HwWiznetInit(void) setSHAR(wiz_mac); ctlwizchip(CW_RESET_PHY, 0); + network_init(); + wiz_interrupt_init(0, wiz_irq_handler); + network_init(); + setSn_RXBUF_SIZE(0, 16); setSn_TXBUF_SIZE(0, 16); #define SOCK_ANY_PORT_NUM 0xC000 @@ -349,7 +353,5 @@ int HwWiznetInit(void) } } - network_init(); - return EOK; } \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500_test.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/test/connect_w5500_test.c similarity index 100% rename from Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500_test.c rename to Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/test/connect_w5500_test.c diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/wiz_iperf.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/test/wiz_iperf.c similarity index 100% rename from Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/wiz_iperf.c rename to Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/test/wiz_iperf.c diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/wiz_ping.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/test/wiz_ping.c similarity index 100% rename from Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/wiz_ping.c rename to Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/test/wiz_ping.c diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/wiz_ping.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/test/wiz_ping.h similarity index 100% rename from Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/wiz_ping.h rename to Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/test/wiz_ping.h diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/connect_spi.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/connect_spi.c index 8811d2856..75e666a6b 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/connect_spi.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/connect_spi.c @@ -152,6 +152,9 @@ static uint32 SpiDrvConfigure(void *drv, struct BusConfigureInfo *configure_info static uint32 SpiWriteData(struct SpiHardwareDevice *spi_dev, struct SpiDataStandard *spi_datacfg) { +#define WRITE_BUF_SIZE 1600 + static uint32_t write_buf[4 * WRITE_BUF_SIZE] = { 0 }; + SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_dev->haldev.private_data); uint8 device_id = dev_param->spi_slave_param->spi_slave_id; @@ -184,10 +187,15 @@ static uint32 SpiWriteData(struct SpiHardwareDevice *spi_dev, struct SpiDataStan dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_txchannel, &dummy, (void *)(&spi_instance[device_master_id]->dr[0]), DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE, DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, spi_datacfg->length); } else { - tx_buff = x_malloc(spi_datacfg->length * 4); - if (!tx_buff) { - goto transfer_done; + if (spi_datacfg->length > WRITE_BUF_SIZE) { + tx_buff = x_malloc(spi_datacfg->length * 4); + if (!tx_buff) { + goto transfer_done; + } + } else { + tx_buff = write_buf; } + for (i = 0; i < spi_datacfg->length; i++) { tx_buff[i] = ((uint8_t *)spi_datacfg->tx_buff)[i]; } @@ -201,10 +209,10 @@ static uint32 SpiWriteData(struct SpiHardwareDevice *spi_dev, struct SpiDataStan spi_instance[device_master_id]->ser = 0x00; spi_instance[device_master_id]->ssienr = 0x00; - transfer_done: - if (tx_buff != NULL) { - x_free(tx_buff); - } + transfer_done: + if (tx_buff != NULL && spi_datacfg->length > WRITE_BUF_SIZE) { + x_free(tx_buff); + } } if (spi_datacfg->spi_cs_release) { @@ -219,6 +227,9 @@ static uint32 SpiWriteData(struct SpiHardwareDevice *spi_dev, struct SpiDataStan static uint32 SpiReadData(struct SpiHardwareDevice *spi_dev, struct SpiDataStandard *spi_datacfg) { +#define READ_BUF_SIZE 1600 + static uint32_t read_buf[4 * READ_BUF_SIZE] = { 0 }; + SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_dev->haldev.private_data); uint32 spi_read_length = 0;; @@ -251,12 +262,15 @@ static uint32 SpiReadData(struct SpiHardwareDevice *spi_dev, struct SpiDataStand dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_rxchannel, (void *)(&spi_instance[device_master_id]->dr[0]), &dummy, DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE, DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, spi_datacfg->length); } else { - rx_buff = x_calloc(spi_datacfg->length * 4, 1); - if(!rx_buff) - { - goto transfer_done; + if (spi_datacfg->length > READ_BUF_SIZE) { + rx_buff = x_calloc(spi_datacfg->length * 4, 1); + if (!rx_buff) { + goto transfer_done; + } + } else { + rx_buff = read_buf; } - + dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_rxchannel, (void *)(&spi_instance[device_master_id]->dr[0]), rx_buff, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT, DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, spi_datacfg->length); } @@ -273,8 +287,8 @@ static uint32 SpiReadData(struct SpiHardwareDevice *spi_dev, struct SpiDataStand } } - transfer_done: - if (rx_buff) { + transfer_done: + if (rx_buff && spi_datacfg->length > READ_BUF_SIZE) { x_free(rx_buff); } } diff --git a/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/ethernet/eth_netdev.c b/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/ethernet/eth_netdev.c index 03ca27594..09957b854 100644 --- a/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/ethernet/eth_netdev.c +++ b/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/ethernet/eth_netdev.c @@ -76,6 +76,7 @@ static int lwip_netdev_set_addr_info(struct netdev* netdev, ip_addr_t* ip_addr, netif_set_gw((struct netif*)netdev->user_data, ip_2_ip4(gw)); } } + return 0; } #ifdef LWIP_DNS @@ -92,7 +93,7 @@ static int lwip_netdev_set_dns_server(struct netdev* netdev, uint8_t dns_num, ip } #endif -#ifdef LWIP_DHCP +#if LWIP_DHCP static int lwip_netdev_set_dhcp(struct netdev* netdev, bool is_enabled) { netdev_low_level_set_dhcp_status(netdev, is_enabled); @@ -120,7 +121,7 @@ static const struct netdev_ops lwip_netdev_ops = { #ifdef LWIP_DNS .set_dns_server = lwip_netdev_set_dns_server, #endif -#ifdef LWIP_DHCP +#if LWIP_DHCP .set_dhcp = lwip_netdev_set_dhcp, #endif .set_default = lwip_netdev_set_default, @@ -180,9 +181,9 @@ int lwip_netdev_add(struct netif* lwip_netif) netdev->ops = &lwip_netdev_ops; netdev->hwaddr_len = lwip_netif->hwaddr_len; memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len); - netdev->ip_addr = lwip_netif->ip_addr; - netdev->gw = lwip_netif->gw; - netdev->netmask = lwip_netif->netmask; + netdev->ip_addr = &lwip_netif->ip_addr; + netdev->gw = &lwip_netif->gw; + netdev->netmask = &lwip_netif->netmask; return result; } diff --git a/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/ethernet/eth_netdev.c b/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/ethernet/eth_netdev.c index 03ca27594..09957b854 100644 --- a/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/ethernet/eth_netdev.c +++ b/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/ethernet/eth_netdev.c @@ -76,6 +76,7 @@ static int lwip_netdev_set_addr_info(struct netdev* netdev, ip_addr_t* ip_addr, netif_set_gw((struct netif*)netdev->user_data, ip_2_ip4(gw)); } } + return 0; } #ifdef LWIP_DNS @@ -92,7 +93,7 @@ static int lwip_netdev_set_dns_server(struct netdev* netdev, uint8_t dns_num, ip } #endif -#ifdef LWIP_DHCP +#if LWIP_DHCP static int lwip_netdev_set_dhcp(struct netdev* netdev, bool is_enabled) { netdev_low_level_set_dhcp_status(netdev, is_enabled); @@ -120,7 +121,7 @@ static const struct netdev_ops lwip_netdev_ops = { #ifdef LWIP_DNS .set_dns_server = lwip_netdev_set_dns_server, #endif -#ifdef LWIP_DHCP +#if LWIP_DHCP .set_dhcp = lwip_netdev_set_dhcp, #endif .set_default = lwip_netdev_set_default, @@ -180,9 +181,9 @@ int lwip_netdev_add(struct netif* lwip_netif) netdev->ops = &lwip_netdev_ops; netdev->hwaddr_len = lwip_netif->hwaddr_len; memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len); - netdev->ip_addr = lwip_netif->ip_addr; - netdev->gw = lwip_netif->gw; - netdev->netmask = lwip_netif->netmask; + netdev->ip_addr = &lwip_netif->ip_addr; + netdev->gw = &lwip_netif->gw; + netdev->netmask = &lwip_netif->netmask; return result; } diff --git a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/config.mk b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/config.mk index 4085d6c06..a77d87ab0 100644 --- a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/config.mk +++ b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/config.mk @@ -30,7 +30,7 @@ export CXXFLAGS := -mcpu=cortex-m7 -mthumb -ffunction-sections -fdata-sections - export APPLFLAGS := -mcpu=cortex-m7 -mthumb -ffunction-sections -fdata-sections -Wl,--gc-sections,-Map=XiZi-app.map,-cref,-u, -T $(BSP_ROOT)/link_userspace.lds -export DEFINES := -DHAVE_CCONFIG_H -DCPU_MIMXRT1052CVL5B -DSKIP_SYSCLK_INIT -DEVK_MCIMXRM -DFSL_SDK_ENABLE_DRIVER_CACHE_CONTROL=1 -DXIP_EXTERNAL_FLASH=1 -D__STARTUP_INITIALIZE_NONCACHEDATA -D__STARTUP_CLEAR_BSS +export DEFINES := -DHAVE_CCONFIG_H -DCPU_MIMXRT1052CVL5B -DSKIP_SYSCLK_INIT -DEVK_MCIMXRM -DFSL_SDK_ENABLE_DRIVER_CACHE_CONTROL=1 -DXIP_EXTERNAL_FLASH=1 -D__STARTUP_INITIALIZE_NONCACHEDATA -D__STARTUP_CLEAR_BSS -DCHECKSUM_BY_HARDWARE ifeq ($(CONFIG_MCUBOOT_BOOTLOADER),y) export DEFINES += -D__BOOTLOADER diff --git a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/ethernet/eth_netdev.c b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/ethernet/eth_netdev.c index 03ca27594..09957b854 100644 --- a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/ethernet/eth_netdev.c +++ b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/ethernet/eth_netdev.c @@ -76,6 +76,7 @@ static int lwip_netdev_set_addr_info(struct netdev* netdev, ip_addr_t* ip_addr, netif_set_gw((struct netif*)netdev->user_data, ip_2_ip4(gw)); } } + return 0; } #ifdef LWIP_DNS @@ -92,7 +93,7 @@ static int lwip_netdev_set_dns_server(struct netdev* netdev, uint8_t dns_num, ip } #endif -#ifdef LWIP_DHCP +#if LWIP_DHCP static int lwip_netdev_set_dhcp(struct netdev* netdev, bool is_enabled) { netdev_low_level_set_dhcp_status(netdev, is_enabled); @@ -120,7 +121,7 @@ static const struct netdev_ops lwip_netdev_ops = { #ifdef LWIP_DNS .set_dns_server = lwip_netdev_set_dns_server, #endif -#ifdef LWIP_DHCP +#if LWIP_DHCP .set_dhcp = lwip_netdev_set_dhcp, #endif .set_default = lwip_netdev_set_default, @@ -180,9 +181,9 @@ int lwip_netdev_add(struct netif* lwip_netif) netdev->ops = &lwip_netdev_ops; netdev->hwaddr_len = lwip_netif->hwaddr_len; memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len); - netdev->ip_addr = lwip_netif->ip_addr; - netdev->gw = lwip_netif->gw; - netdev->netmask = lwip_netif->netmask; + netdev->ip_addr = &lwip_netif->ip_addr; + netdev->gw = &lwip_netif->gw; + netdev->netmask = &lwip_netif->netmask; return result; } diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/board.c b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/board.c index 01e9685d2..fb9dbba04 100644 --- a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/board.c +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/board.c @@ -210,7 +210,7 @@ struct InitSequenceDesc _board_init[] = { #ifdef BSP_USING_CAN { "can", HwCanInit }, #endif -#ifdef BSP_USING_LWIP +#ifdef BSP_USING_W5500 { "wiz", HwWiznetInit }, #endif { " NONE ", NONE }, diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/config.mk b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/config.mk index b5b98fd35..6b0534d25 100644 --- a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/config.mk +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/config.mk @@ -15,4 +15,8 @@ ifeq ($(CONFIG_RESOURCES_LWIP), y) export LINK_LWIP := $(KERNEL_ROOT)/resources/ethernet/LwIP/liblwip.a endif +ifeq ($(CONFIG_USE_MONGOOSE), y) +export LINK_MONGOOSE := $(KERNEL_ROOT)/../../APP_Framework/Applications/mongoose/mongoose.a +endif + export ARCH = arm diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/Kconfig b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/Kconfig index ac81ec8ae..d0b82dc0d 100644 --- a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/Kconfig +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/Kconfig @@ -14,14 +14,29 @@ menuconfig BSP_USING_GPIO source "$BSP_DIR/third_party_driver/gpio/Kconfig" endif -menuconfig BSP_USING_LWIP - bool "Using LwIP by ethernet device" +menuconfig BSP_USING_ETHERNET + bool "Using MAC ethernet device" default n - select RESOURCES_LWIP - if BSP_USING_LWIP + select BSP_USING_LWIP + if BSP_USING_ETHERNET source "$BSP_DIR/third_party_driver/ethernet/Kconfig" endif +menuconfig BSP_USING_W5500 + bool "Using W5500 ethernet device" + default n + select BSP_USING_LWIP + select BSP_USING_SPI + select BSP_USING_SPI1 + if BSP_USING_W5500 + source "$BSP_DIR/third_party_driver/ethernet_wiz/Kconfig" + endif + +config BSP_USING_LWIP + bool + default n + select RESOURCES_LWIP + menuconfig BSP_USING_SDIO bool "Using SD CARD device" default n @@ -30,3 +45,10 @@ menuconfig BSP_USING_SDIO source "$BSP_DIR/third_party_driver/sdio/Kconfig" endif +menuconfig BSP_USING_SPI + bool "Using SPI device" + default n + select RESOURCES_SPI + if BSP_USING_SPI + source "$BSP_DIR/third_party_driver/spi/Kconfig" + endif diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/Makefile b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/Makefile index f0d540750..e14fadbf6 100644 --- a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/Makefile @@ -8,12 +8,20 @@ ifeq ($(CONFIG_BSP_USING_GPIO),y) SRC_DIR += gpio endif -ifeq ($(CONFIG_BSP_USING_LWIP),y) - SRC_DIR += ethernet ethernet_wiz +ifeq ($(CONFIG_BSP_USING_ETHERNET),y) + SRC_DIR += ethernet +endif + +ifeq ($(CONFIG_BSP_USING_W5500),y) + SRC_DIR += ethernet_wiz endif ifeq ($(CONFIG_BSP_USING_SDIO),y) SRC_DIR += sdio endif +ifeq ($(CONFIG_BSP_USING_SPI),y) + SRC_DIR += spi +endif + include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/common/hc32_ll_driver/src/Makefile b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/common/hc32_ll_driver/src/Makefile index 7254a2cb6..3bba69d86 100644 --- a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/common/hc32_ll_driver/src/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/common/hc32_ll_driver/src/Makefile @@ -28,7 +28,7 @@ ifeq ($(CONFIG_BSP_USING_I2C),y) SRC_FILES += hc32_ll_i2c.c endif -ifeq ($(CONFIG_BSP_USING_LWIP),y) +ifeq ($(CONFIG_BSP_USING_ETHERNET),y) SRC_FILES += hc32_ll_eth.c endif diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/ethernet/eth_driver.c b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/ethernet/eth_driver.c index 9ad1468d0..a1e94307c 100644 --- a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/ethernet/eth_driver.c +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/ethernet/eth_driver.c @@ -277,10 +277,7 @@ struct pbuf* low_level_input(struct netif* netif) return p; } -extern void LwipSetIPTest(int argc, char* argv[]); int HwEthInit(void) { - // lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, lwip_gwaddr); - LwipSetIPTest(1, NULL); return EOK; } diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/ethernet/eth_netdev.c b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/ethernet/eth_netdev.c index 862d80bd8..0f6a8df37 100644 --- a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/ethernet/eth_netdev.c +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/ethernet/eth_netdev.c @@ -76,6 +76,7 @@ static int lwip_netdev_set_addr_info(struct netdev* netdev, ip_addr_t* ip_addr, netif_set_gw((struct netif*)netdev->user_data, ip_2_ip4(gw)); } } + return 0; } #ifdef LWIP_DNS @@ -92,7 +93,7 @@ static int lwip_netdev_set_dns_server(struct netdev* netdev, uint8_t dns_num, ip } #endif -#ifdef LWIP_DHCP +#if LWIP_DHCP static int lwip_netdev_set_dhcp(struct netdev* netdev, bool is_enabled) { netdev_low_level_set_dhcp_status(netdev, is_enabled); @@ -120,7 +121,7 @@ static const struct netdev_ops lwip_netdev_ops = { #ifdef LWIP_DNS .set_dns_server = lwip_netdev_set_dns_server, #endif -#ifdef LWIP_DHCP +#if LWIP_DHCP .set_dhcp = lwip_netdev_set_dhcp, #endif .set_default = lwip_netdev_set_default, @@ -183,9 +184,9 @@ int lwip_netdev_add(struct netif* lwip_netif) netdev->ops = &lwip_netdev_ops; netdev->hwaddr_len = lwip_netif->hwaddr_len; memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len); - netdev->ip_addr = lwip_netif->ip_addr; - netdev->gw = lwip_netif->gw; - netdev->netmask = lwip_netif->netmask; + netdev->ip_addr = &lwip_netif->ip_addr; + netdev->gw = &lwip_netif->gw; + netdev->netmask = &lwip_netif->netmask; return result; } diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/ethernet/ethernetif.c b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/ethernet/ethernetif.c index 0e1c2a9ed..c5d1309b4 100644 --- a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/ethernet/ethernetif.c +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/ethernet/ethernetif.c @@ -204,7 +204,6 @@ void ethernetif_input(void* netif_arg) /* Move received packet into a new pbuf */ while (1) { sys_arch_sem_wait(get_eth_recv_sem(), WAITING_FOREVER); - KPrintf("%s -->\n", netif->name); while (1) { p = low_level_input(netif); #ifndef ETHERNET_LOOPBACK_TEST diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/ethernet_wiz/Kconfig b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/ethernet_wiz/Kconfig index 2941c9434..f32bb08e5 100644 --- a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/ethernet_wiz/Kconfig +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/ethernet_wiz/Kconfig @@ -1,19 +1,5 @@ # Kconfig file -config BSP_USING_W5500 - bool "Using w5500" - select BSP_USING_LWIP - default y - -config BSP_WIZ_RST_PIN - int - default 13 - config BSP_WIZ_INT_PIN int - default 14 - -menuconfig BSP_USING_LWIP - bool "Using LwIP device" - default n - select RESOURCES_LWIP \ No newline at end of file + default 106 diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/ethernet_wiz/w5x00_lwip.c b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/ethernet_wiz/w5x00_lwip.c index 2494cdb32..357a9e404 100644 --- a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/ethernet_wiz/w5x00_lwip.c +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/ethernet_wiz/w5x00_lwip.c @@ -113,7 +113,6 @@ void ethernetif_input2(void* netif_arg) struct pbuf* p = NULL; for (;;) { sys_arch_sem_wait(get_eth_recv_sem2(), WAITING_FOREVER); - KPrintf("%s -->\n", netif->name); sys_mutex_lock(&wiz_trans_mtx); while (1) { diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_adc.h b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_adc.h new file mode 100644 index 000000000..d961b5611 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_adc.h @@ -0,0 +1,42 @@ +/* +* 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 connect_uart.h +* @brief define edu-arm32-board usart function and struct +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2023-02-09 +*/ + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +struct HwAdc +{ + CM_ADC_TypeDef *ADCx; + uint8 adc_channel; +}; + +int HwAdcInit(void); + +#ifdef __cplusplus +} +#endif + + diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_can.h b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_can.h new file mode 100644 index 000000000..2a7369c42 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_can.h @@ -0,0 +1,40 @@ +/* +* 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. +*/ + +/** +* @file connect_can.h +* @brief define edu-arm32-board can function and struct +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2023-02-21 +*/ + +#ifndef CONNECT_CAN_H +#define CONNECT_CAN_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +int HwCanInit(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_dac.h b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_dac.h new file mode 100644 index 000000000..c99f28010 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_dac.h @@ -0,0 +1,43 @@ +/* +* 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 connect_uart.h +* @brief define edu-arm32-board usart function and struct +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2023-02-09 +*/ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct HwDac +{ + CM_DAC_TypeDef *DACx; + uint16 digital_data; +}; + +int HwDacInit(void); + +#ifdef __cplusplus +} +#endif + + diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_ethernet.h b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_ethernet.h index 6b2c2bb86..110d18852 100644 --- a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_ethernet.h +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_ethernet.h @@ -26,13 +26,16 @@ #include #include +#ifdef BSP_USING_W5500 #include "connect_ethernet_wiz.h" #include "connect_w5500.h" +#endif #ifdef __cplusplus extern "C" { #endif +#ifdef BSP_USING_ETHERNET struct hc32_irq_config { IRQn_Type irq_num; uint32_t irq_prio; @@ -64,11 +67,12 @@ int32_t low_level_init(struct netif* netif); err_t low_level_output(struct netif* netif, struct pbuf* p); struct pbuf* low_level_input(struct netif* netif); +int HwEthInit(void); +#endif + int lwip_netdev_add(struct netif* lwip_netif); void lwip_netdev_del(struct netif* lwip_netif); -int HwEthInit(void); - #ifdef __cplusplus } #endif diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_flash.h b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_flash.h new file mode 100644 index 000000000..63d59eb16 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_flash.h @@ -0,0 +1,40 @@ +/* +* 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 connect_flash.h +* @brief define edu-arm32-board qspi-flash function and struct +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2022-10-17 +*/ + +#ifndef CONNECT_FLASH_H +#define CONNECT_FLASH_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int FlashW25qxxSpiDeviceInit(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_hwtimer.h b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_hwtimer.h new file mode 100644 index 000000000..0ec541003 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_hwtimer.h @@ -0,0 +1,40 @@ +/* +* 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 connect_hwtimer.h +* @brief define edu-arm32-board hwtimer function and struct +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2023-02-16 +*/ + +#ifndef CONNECT_HWTIMER_H +#define CONNECT_HWTIMER_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int HwTimerInit(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_i2c.h b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_i2c.h new file mode 100644 index 000000000..3b0ab7c45 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_i2c.h @@ -0,0 +1,42 @@ +/* +* 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 connect_i2c.h +* @brief define edu-arm32-board i2c function and struct +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2022-12-05 +*/ + +#ifndef CONNECT_I2C_H +#define CONNECT_I2C_H + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int HwI2cInit(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_rtc.h b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_rtc.h new file mode 100644 index 000000000..fc0512bd8 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_rtc.h @@ -0,0 +1,37 @@ +/* +* 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 connect_rtc.h +* @brief define edu-arm32-board rtc function and struct +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-02-02 +*/ + +#ifndef CONNECT_RTC_H +#define CONNECT_RTC_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int HwRtcInit(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_spi.h b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_spi.h new file mode 100644 index 000000000..d3335a486 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_spi.h @@ -0,0 +1,39 @@ +/* +* 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 connect_spi.h +* @brief define xishutong-arm32-board spi function and struct +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2022-10-17 +*/ + +#ifndef CONNECT_SPI_H +#define CONNECT_SPI_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int HwSpiInit(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_spi_lora.h b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_spi_lora.h new file mode 100644 index 000000000..d696ccf4b --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_spi_lora.h @@ -0,0 +1,61 @@ +/* +* 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 connect_spi_lora.h +* @brief define spi lora dev function and struct using bus driver framework +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2022-10-31 +*/ + +#ifndef CONNECT_SPI_LORA_H +#define CONNECT_SPI_LORA_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +//#define SPI_LORA_FREQUENCY 10000000 +#define SPI_LORA_BUFFER_SIZE 256 + +typedef struct SpiLoraDevice *SpiLoraDeviceType; + +struct LoraDevDone +{ + uint32 (*open) (void *dev); + uint32 (*close) (void *dev); + uint32 (*write) (void *dev, struct BusBlockWriteParam *write_param); + uint32 (*read) (void *dev, struct BusBlockReadParam *read_param); +}; + +struct SpiLoraDevice +{ + struct SpiHardwareDevice *spi_dev; + struct SpiHardwareDevice lora_dev; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_usb.h b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_usb.h new file mode 100644 index 000000000..2d17a181f --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_usb.h @@ -0,0 +1,54 @@ +/* +* 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 connect_usb.h +* @brief define edu-arm32-board usb function and struct +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2022-11-07 +*/ + +#ifndef CONNECT_USB_H +#define CONNECT_USB_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(FS_VFS) +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define USB_HOST_STACK_SIZE 4096 + +#define USB_SINGLE_BLOCK_SIZE 512 + +int HwUsbHostInit(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_wdt.h b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_wdt.h new file mode 100644 index 000000000..c0c7b3cd6 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/include/connect_wdt.h @@ -0,0 +1,37 @@ +/* +* 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 connect_wdt.h +* @brief define edu-arm32-board watchdog function and struct +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-02-02 +*/ + +#ifndef CONNECT_WDT_H +#define CONNECT_WDT_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int HwWdtInit(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/spi/Kconfig b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/spi/Kconfig new file mode 100644 index 000000000..32d2ea101 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/spi/Kconfig @@ -0,0 +1,33 @@ +if BSP_USING_SPI + config BSP_USING_SPI1 + bool "Using spi1 for W5500" + default y + + if BSP_USING_SPI1 + config SPI_BUS_NAME_1 + string "spi bus 1 name" + default "spi1" + config SPI_1_DEVICE_NAME_0 + string "spi bus 1 device 0 name" + default "spi1_dev0" + config SPI_1_DRV_NAME + string "spi bus 1 driver name" + default "spi1_drv" + endif + + config BSP_USING_SPI6 + bool "Using spi6" + default n + + if BSP_USING_SPI6 + config SPI_BUS_NAME_6 + string "spi bus 6 name" + default "spi6" + config SPI_6_DEVICE_NAME_0 + string "spi bus 6 device 0 name" + default "spi6_dev0" + config SPI_6_DRV_NAME + string "spi bus 6 driver name" + default "spi6_drv" + endif +endif diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/spi/Makefile b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/spi/Makefile new file mode 100644 index 000000000..0d5545809 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/spi/Makefile @@ -0,0 +1,3 @@ +SRC_FILES := connect_spi.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/spi/connect_spi.c b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/spi/connect_spi.c new file mode 100644 index 000000000..33fe9aba0 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/xishutong-arm32/third_party_driver/spi/connect_spi.c @@ -0,0 +1,582 @@ +/* + * 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 connect_spi.c + * @brief support edu-arm32-board spi function and register to bus framework + * @version 2.0 + * @author AIIT XUOS Lab + * @date 2022-10-17 + */ + +/************************************************* +File name: connect_spi.c +Description: support xishutong-arm32-board spi function and register to bus framework +Others: +History: +1. Date: 2022-10-17 +Author: AIIT XUOS Lab +Modification: +1. support xishutong-arm32-board spi configure, write and read +2. support xishutong-arm32-board spi bus device and driver register +3. SPI1 for W5500, SPI6 using J12-pin-header to connect +*************************************************/ + +#include + +#define SPI1_MASTER_SLAVE_MODE (SPI_MASTER) + +/* SPI1 definition */ +#define SPI1_UNIT (CM_SPI1) +#define SPI1_CLK (FCG1_PERIPH_SPI1) + +/* CS = PG3 */ +#define SPI1_SS_PORT (GPIO_PORT_G) +#define SPI1_SS_PIN (GPIO_PIN_03) +/* SCLK = PG5 */ +#define SPI1_SCK_PORT (GPIO_PORT_G) +#define SPI1_SCK_PIN (GPIO_PIN_05) +#define SPI1_SCK_FUNC (GPIO_FUNC_40) +/* MOSI = PG4 */ +#define SPI1_MOSI_PORT (GPIO_PORT_G) +#define SPI1_MOSI_PIN (GPIO_PIN_04) +#define SPI1_MOSI_FUNC (GPIO_FUNC_41) +/* MISO = PG6 */ +#define SPI1_MISO_PORT (GPIO_PORT_G) +#define SPI1_MISO_PIN (GPIO_PIN_06) +#define SPI1_MISO_FUNC (GPIO_FUNC_42) + +#define SPI1_DEVICE_SLAVE_ID_0 0 + +/* SPI6 definition */ +#define SPI6_UNIT (CM_SPI6) +#define SPI6_CLK (FCG1_PERIPH_SPI6) + +/* SS = PE02 */ +#define SPI6_SS_PORT (GPIO_PORT_E) +#define SPI6_SS_PIN (GPIO_PIN_02) +/* SCK = PE03 */ +#define SPI6_SCK_PORT (GPIO_PORT_E) +#define SPI6_SCK_PIN (GPIO_PIN_03) +#define SPI6_SCK_FUNC (GPIO_FUNC_46) +/* MOSI = PE04 */ +#define SPI6_MOSI_PORT (GPIO_PORT_E) +#define SPI6_MOSI_PIN (GPIO_PIN_04) +#define SPI6_MOSI_FUNC (GPIO_FUNC_47) +/* MISO = PE05 */ +#define SPI6_MISO_PORT (GPIO_PORT_E) +#define SPI6_MISO_PIN (GPIO_PIN_05) +#define SPI6_MISO_FUNC (GPIO_FUNC_48) + +#define SPI6_DEVICE_SLAVE_ID_0 0 + +static void HwSpiEnable(CM_SPI_TypeDef* SPIx) +{ + /* Check if the SPI is already enabled */ + if (SPI_CR1_SPE != (SPIx->CR1 & SPI_CR1_SPE)) { + SPI_Cmd(SPIx, ENABLE); + } +} + +/*Init the spi sdk intetface */ +static uint32 SpiSdkInit(struct SpiDriver* spi_drv) +{ + NULL_PARAM_CHECK(spi_drv); + + stc_spi_init_t stcSpiInit; + stc_gpio_init_t stcGpioInit; + + SpiDeviceParam* dev_param = (SpiDeviceParam*)(spi_drv->driver.private_data); + +#ifdef BSP_USING_SPI1 + /* Configure Port */ + (void)GPIO_StructInit(&stcGpioInit); + stcGpioInit.u16PinState = PIN_STAT_RST; + stcGpioInit.u16PinDir = PIN_DIR_OUT; + (void)GPIO_Init(SPI1_SS_PORT, SPI1_SS_PIN, &stcGpioInit); + GPIO_SetPins(SPI1_SS_PORT, SPI1_SS_PIN); + + GPIO_SetFunc(SPI1_SCK_PORT, SPI1_SCK_PIN, SPI1_SCK_FUNC); + GPIO_SetFunc(SPI1_MOSI_PORT, SPI1_MOSI_PIN, SPI1_MOSI_FUNC); + GPIO_SetFunc(SPI1_MISO_PORT, SPI1_MISO_PIN, SPI1_MISO_FUNC); + + /* Configuration SPI */ + FCG_Fcg1PeriphClockCmd(SPI1_CLK, ENABLE); + SPI_StructInit(&stcSpiInit); + + stcSpiInit.u32WireMode = SPI_4_WIRE; + stcSpiInit.u32TransMode = SPI_FULL_DUPLEX; + stcSpiInit.u32MasterSlave = SPI1_MASTER_SLAVE_MODE; + stcSpiInit.u32Parity = SPI_PARITY_INVD; + + if (SPI_MODE_0 == dev_param->spi_master_param->spi_work_mode & 0x3) { + stcSpiInit.u32SpiMode = SPI_MD_0; + } else if (SPI_MODE_1 == dev_param->spi_master_param->spi_work_mode & 0x3) { + stcSpiInit.u32SpiMode = SPI_MD_1; + } else if (SPI_MODE_2 == dev_param->spi_master_param->spi_work_mode & 0x3) { + stcSpiInit.u32SpiMode = SPI_MD_2; + } else if (SPI_MODE_3 == dev_param->spi_master_param->spi_work_mode & 0x3) { + stcSpiInit.u32SpiMode = SPI_MD_3; + } + + stcSpiInit.u32BaudRatePrescaler = SPI_BR_CLK_DIV64; + + if (8 == dev_param->spi_master_param->spi_data_bit_width) { + stcSpiInit.u32DataBits = SPI_DATA_SIZE_8BIT; + } else if (7 == dev_param->spi_master_param->spi_data_bit_width) { + stcSpiInit.u32DataBits = SPI_DATA_SIZE_7BIT; + } + + if (SPI_LSB == dev_param->spi_master_param->spi_work_mode & 0x4) { + stcSpiInit.u32FirstBit = SPI_FIRST_LSB; + } else if (SPI_MSB == dev_param->spi_master_param->spi_work_mode & 0x4) { + stcSpiInit.u32FirstBit = SPI_FIRST_MSB; + } + + stcSpiInit.u32FrameLevel = SPI_1_FRAME; + + (void)SPI_Init(SPI1_UNIT, &stcSpiInit); + SPI_Cmd(SPI1_UNIT, ENABLE); +#endif + +#ifdef BSP_USING_SPI6 + /* Configure Port */ + (void)GPIO_StructInit(&stcGpioInit); + stcGpioInit.u16PinState = PIN_STAT_RST; + stcGpioInit.u16PinDir = PIN_DIR_OUT; + (void)GPIO_Init(SPI6_SS_PORT, SPI6_SS_PIN, &stcGpioInit); + GPIO_SetPins(SPI6_SS_PORT, SPI6_SS_PIN); + + GPIO_SetFunc(SPI6_SCK_PORT, SPI6_SCK_PIN, SPI6_SCK_FUNC); + GPIO_SetFunc(SPI6_MOSI_PORT, SPI6_MOSI_PIN, SPI6_MOSI_FUNC); + GPIO_SetFunc(SPI6_MISO_PORT, SPI6_MISO_PIN, SPI6_MISO_FUNC); + + /* Configuration SPI */ + FCG_Fcg1PeriphClockCmd(SPI6_CLK, ENABLE); + SPI_StructInit(&stcSpiInit); + + stcSpiInit.u32WireMode = SPI_4_WIRE; + stcSpiInit.u32TransMode = SPI_FULL_DUPLEX; + stcSpiInit.u32MasterSlave = SPI1_MASTER_SLAVE_MODE; + stcSpiInit.u32Parity = SPI_PARITY_INVD; + + if (SPI_MODE_0 == dev_param->spi_master_param->spi_work_mode & 0x3) { + stcSpiInit.u32SpiMode = SPI_MD_0; + } else if (SPI_MODE_1 == dev_param->spi_master_param->spi_work_mode & 0x3) { + stcSpiInit.u32SpiMode = SPI_MD_1; + } else if (SPI_MODE_2 == dev_param->spi_master_param->spi_work_mode & 0x3) { + stcSpiInit.u32SpiMode = SPI_MD_2; + } else if (SPI_MODE_3 == dev_param->spi_master_param->spi_work_mode & 0x3) { + stcSpiInit.u32SpiMode = SPI_MD_3; + } + + stcSpiInit.u32BaudRatePrescaler = SPI_BR_CLK_DIV64; + + if (8 == dev_param->spi_master_param->spi_data_bit_width) { + stcSpiInit.u32DataBits = SPI_DATA_SIZE_8BIT; + } else if (7 == dev_param->spi_master_param->spi_data_bit_width) { + stcSpiInit.u32DataBits = SPI_DATA_SIZE_7BIT; + } + + if (SPI_LSB == dev_param->spi_master_param->spi_work_mode & 0x4) { + stcSpiInit.u32FirstBit = SPI_FIRST_LSB; + } else if (SPI_MSB == dev_param->spi_master_param->spi_work_mode & 0x4) { + stcSpiInit.u32FirstBit = SPI_FIRST_MSB; + } + + stcSpiInit.u32FrameLevel = SPI_1_FRAME; + + (void)SPI_Init(SPI6_UNIT, &stcSpiInit); + SPI_Cmd(SPI6_UNIT, ENABLE); +#endif + + return EOK; +} + +static uint32 SpiSdkCfg(struct SpiDriver* spi_drv, struct SpiMasterParam* spi_param) +{ + NULL_PARAM_CHECK(spi_drv); + NULL_PARAM_CHECK(spi_param); + + SpiDeviceParam* dev_param = (SpiDeviceParam*)(spi_drv->driver.private_data); + + dev_param->spi_master_param = spi_param; + dev_param->spi_master_param->spi_work_mode = dev_param->spi_master_param->spi_work_mode & SPI_MODE_MASK; + + return EOK; +} + +/*Configure the spi device param, make sure struct (configure_info->private_data) = (SpiMasterParam)*/ +static uint32 SpiDrvConfigure(void* drv, struct BusConfigureInfo* configure_info) +{ + NULL_PARAM_CHECK(drv); + NULL_PARAM_CHECK(configure_info); + + x_err_t ret = EOK; + struct SpiDriver* spi_drv = (struct SpiDriver*)drv; + struct SpiMasterParam* spi_param; + + switch (configure_info->configure_cmd) { + case OPE_INT: + ret = SpiSdkInit(spi_drv); + break; + case OPE_CFG: + spi_param = (struct SpiMasterParam*)configure_info->private_data; + ret = SpiSdkCfg(spi_drv, spi_param); + break; + default: + break; + } + + return ret; +} + +static uint32 SpiWriteData(struct SpiHardwareDevice* spi_dev, struct SpiDataStandard* spi_datacfg) +{ + SpiDeviceParam* dev_param = (SpiDeviceParam*)(spi_dev->haldev.private_data); + + uint8 cs_gpio_pin = dev_param->spi_slave_param->spi_cs_gpio_pin; + uint8 cs_gpio_port = dev_param->spi_slave_param->spi_cs_gpio_port; + CM_SPI_TypeDef* spi = spi_dev->haldev.owner_bus->private_data; + + int i = 0; + uint32 ret = EOK; + int32 spi_write_status = 0; + + while (NONE != spi_datacfg) { + if (spi_datacfg->spi_chip_select) { + GPIO_ResetPins(cs_gpio_port, cs_gpio_pin); + } + + if (spi_datacfg->length) { + uint8* tx_buff = x_malloc(spi_datacfg->length); + if ((spi_datacfg->tx_buff) && (tx_buff)) { + memset(tx_buff, 0, spi_datacfg->length); + + for (i = 0; i < spi_datacfg->length; i++) { + tx_buff[i] = ((uint8*)spi_datacfg->tx_buff)[i]; + } + + HwSpiEnable(spi); + spi_write_status = SPI_Trans(spi, tx_buff, spi_datacfg->length, 1000); + + while (RESET != SPI_GetStatus(spi, SPI_FLAG_IDLE)) + ; + + if (LL_OK == spi_write_status) { + ret = ERROR; + } + } + + if (tx_buff) { + x_free(tx_buff); + } + + SPI_ClearStatus(spi, SPI_FLAG_CLR_ALL | SPI_FLAG_RX_BUF_FULL); + } + + if (spi_datacfg->spi_cs_release) { + GPIO_SetPins(cs_gpio_port, cs_gpio_pin); + } + + spi_datacfg = spi_datacfg->next; + } + + return ret; +} + +static uint32 SpiReadData(struct SpiHardwareDevice* spi_dev, struct SpiDataStandard* spi_datacfg) +{ + SpiDeviceParam* dev_param = (SpiDeviceParam*)(spi_dev->haldev.private_data); + + uint8 cs_gpio_pin = dev_param->spi_slave_param->spi_cs_gpio_pin; + uint8 cs_gpio_port = dev_param->spi_slave_param->spi_cs_gpio_port; + CM_SPI_TypeDef* spi = spi_dev->haldev.owner_bus->private_data; + + int i = 0; + int32 spi_read_status = 0; + uint32 spi_read_length = 0; + + while (NONE != spi_datacfg) { + if (spi_datacfg->spi_chip_select) { + GPIO_ResetPins(cs_gpio_port, cs_gpio_pin); + } + + if (spi_datacfg->length) { + uint8_t* rx_buff = x_malloc(spi_datacfg->length); + if ((spi_datacfg->rx_buff) && (rx_buff)) { + memset(rx_buff, 0xFF, spi_datacfg->length); + + HwSpiEnable(spi); + spi_read_status = SPI_Receive(spi, rx_buff, spi_datacfg->length, 1000); + + while (RESET != SPI_GetStatus(spi, SPI_FLAG_IDLE)) + ; + if (LL_OK == spi_read_status) { + for (i = 0; i < spi_datacfg->length; i++) { + ((uint8_t*)spi_datacfg->rx_buff)[i] = rx_buff[i]; + } + } + } + if (rx_buff) { + x_free(rx_buff); + } + + SPI_ClearStatus(spi, SPI_FLAG_CLR_ALL | SPI_FLAG_RX_BUF_FULL); + } + + if (spi_datacfg->spi_cs_release) { + GPIO_SetPins(cs_gpio_port, cs_gpio_pin); + } + + spi_read_length += spi_datacfg->length; + spi_datacfg = spi_datacfg->next; + } + + return spi_read_length; +} + +/*manage the spi device operations*/ +static const struct SpiDevDone spi_dev_done = { + .dev_open = NONE, + .dev_close = NONE, + .dev_write = SpiWriteData, + .dev_read = SpiReadData, +}; + +static int BoardSpiBusInit(struct SpiBus* spi_bus, struct SpiDriver* spi_driver, const char* bus_name, const char* drv_name) +{ + x_err_t ret = EOK; + + /*Init the spi bus */ + ret = SpiBusInit(spi_bus, bus_name); + if (EOK != ret) { + KPrintf("Board_Spi_init SpiBusInit error %d\n", ret); + return ERROR; + } + + /*Init the spi driver*/ + ret = SpiDriverInit(spi_driver, drv_name); + if (EOK != ret) { + KPrintf("Board_Spi_init SpiDriverInit error %d\n", ret); + return ERROR; + } + + /*Attach the spi driver to the spi bus*/ + ret = SpiDriverAttachToBus(drv_name, bus_name); + if (EOK != ret) { + KPrintf("Board_Spi_init SpiDriverAttachToBus error %d\n", ret); + return ERROR; + } + + return ret; +} + +/*Attach the spi device to the spi bus*/ +static int BoardSpiDevBend(void) +{ + x_err_t ret = EOK; + +#ifdef SPI_1_DEVICE_NAME_0 + static struct SpiHardwareDevice spi1_device0; + memset(&spi1_device0, 0, sizeof(struct SpiHardwareDevice)); + + static struct SpiSlaveParam spi1_slaveparam0; + memset(&spi1_slaveparam0, 0, sizeof(struct SpiSlaveParam)); + + spi1_slaveparam0.spi_slave_id = SPI1_DEVICE_SLAVE_ID_0; + spi1_slaveparam0.spi_cs_gpio_pin = SPI1_SS_PIN; + spi1_slaveparam0.spi_cs_gpio_port = SPI1_SS_PORT; + + spi1_device0.spi_param.spi_slave_param = &spi1_slaveparam0; + + spi1_device0.spi_dev_done = &(spi_dev_done); + + ret = SpiDeviceRegister(&spi1_device0, (void*)(&spi1_device0.spi_param), SPI_1_DEVICE_NAME_0); + if (EOK != ret) { + KPrintf("BoardSpiDevBend SpiDeviceRegister device %s error %d\n", SPI_1_DEVICE_NAME_0, ret); + return ERROR; + } + + ret = SpiDeviceAttachToBus(SPI_1_DEVICE_NAME_0, SPI_BUS_NAME_1); + if (EOK != ret) { + KPrintf("BoardSpiDevBend SpiDeviceAttachToBus device %s error %d\n", SPI_1_DEVICE_NAME_0, ret); + return ERROR; + } +#endif + +#ifdef SPI_6_DEVICE_NAME_0 + static struct SpiHardwareDevice spi6_device0; + memset(&spi6_device0, 0, sizeof(struct SpiHardwareDevice)); + + static struct SpiSlaveParam spi6_slaveparam0; + memset(&spi6_slaveparam0, 0, sizeof(struct SpiSlaveParam)); + + spi6_slaveparam0.spi_slave_id = SPI1_DEVICE_SLAVE_ID_0; + spi6_slaveparam0.spi_cs_gpio_pin = SPI6_SS_PIN; + spi6_slaveparam0.spi_cs_gpio_port = SPI6_SS_PORT; + + spi6_device0.spi_param.spi_slave_param = &spi6_slaveparam0; + + spi6_device0.spi_dev_done = &(spi_dev_done); + + ret = SpiDeviceRegister(&spi6_device0, (void*)(&spi6_device0.spi_param), SPI_6_DEVICE_NAME_0); + if (EOK != ret) { + KPrintf("BoardSpiDevBend SpiDeviceRegister device %s error %d\n", SPI_6_DEVICE_NAME_0, ret); + return ERROR; + } + + ret = SpiDeviceAttachToBus(SPI_6_DEVICE_NAME_0, SPI_BUS_NAME_6); + if (EOK != ret) { + KPrintf("BoardSpiDevBend SpiDeviceAttachToBus device %s error %d\n", SPI_6_DEVICE_NAME_0, ret); + return ERROR; + } +#endif + + return ret; +} + +int HwSpiInit(void) +{ + x_err_t ret = EOK; + +#ifdef BSP_USING_SPI1 + static struct SpiBus spi1_bus; + memset(&spi1_bus, 0, sizeof(struct SpiBus)); + + static struct SpiDriver spi1_driver; + memset(&spi1_driver, 0, sizeof(struct SpiDriver)); + + spi1_bus.private_data = SPI1_UNIT; + spi1_driver.configure = SpiDrvConfigure; + + ret = BoardSpiBusInit(&spi1_bus, &spi1_driver, SPI_BUS_NAME_1, SPI_1_DRV_NAME); + if (EOK != ret) { + KPrintf("BoardSpiBusInit error ret %u\n", ret); + return ERROR; + } + +#endif + +#ifdef BSP_USING_SPI6 + static struct SpiBus spi6_bus; + memset(&spi6_bus, 0, sizeof(struct SpiBus)); + + static struct SpiDriver spi6_driver; + memset(&spi6_driver, 0, sizeof(struct SpiDriver)); + + spi6_bus.private_data = SPI6_UNIT; + spi6_driver.configure = SpiDrvConfigure; + + ret = BoardSpiBusInit(&spi6_bus, &spi6_driver, SPI_BUS_NAME_6, SPI_6_DRV_NAME); + if (EOK != ret) { + KPrintf("BoardSpiBusInit error ret %u\n", ret); + return ERROR; + } + +#endif + + ret = BoardSpiDevBend(); + if (EOK != ret) { + KPrintf("BoardSpiDevBend error ret %u\n", ret); + return ERROR; + } + + return ret; +} + +#ifdef TEST_SPI +/*Just for lora test*/ +static struct Bus* bus; +static struct HardwareDev* dev; +static struct Driver* drv; + +static uint32 TestSpiLoraOpen(void) +{ + NULL_PARAM_CHECK(drv); + + KPrintf("SpiLoraOpen start\n"); + + x_err_t ret = EOK; + + struct BusConfigureInfo configure_info; + struct SpiMasterParam spi_master_param; + spi_master_param.spi_data_bit_width = 8; + spi_master_param.spi_work_mode = SPI_MODE_0 | SPI_MSB; + + configure_info.configure_cmd = OPE_CFG; + configure_info.private_data = (void*)&spi_master_param; + ret = BusDrvConfigure(drv, &configure_info); + if (ret) { + KPrintf("spi drv OPE_CFG error drv %8p cfg %8p\n", drv, &spi_master_param); + return ERROR; + } + + configure_info.configure_cmd = OPE_INT; + ret = BusDrvConfigure(drv, &configure_info); + if (ret) { + KPrintf("spi drv OPE_INT error drv %8p\n", drv); + return ERROR; + } + + return ret; +} + +static void TestSpiRead(void) +{ + struct BusBlockWriteParam write_param; + struct BusBlockReadParam read_param; + + uint8 write_addr = 0x06 & 0x7F; + uint8 read_data = 0; + + BusDevOpen(dev); + + write_param.buffer = (void*)&write_addr; + write_param.size = 1; + BusDevWriteData(dev, &write_param); + + read_param.buffer = (void*)&read_data; + read_param.size = 1; + BusDevReadData(dev, &read_param); + + BusDevClose(dev); + + KPrintf("read data from lora 0x06 register, receive data 0x%x\n", read_data); +} +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), + TestSpiRead, TestSpiRead, read data from lora register); + +void TestLoraOpen(void) +{ + x_err_t ret = EOK; + + bus = BusFind(SPI_BUS_NAME_1); + dev = BusFindDevice(bus, SPI_1_DEVICE_NAME_0); + drv = BusFindDriver(bus, SPI_1_DRV_NAME); + + bus->match(drv, dev); + + ret = TestSpiLoraOpen(); + if (EOK != ret) { + KPrintf("LoRa init failed\n"); + return; + } + + KPrintf("LoRa init succeed\n"); + + return; +} +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), + TestLoraOpen, TestLoraOpen, open lora device and read parameters); + +#endif diff --git a/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/ethernet/eth_netdev.c b/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/ethernet/eth_netdev.c index 03ca27594..09957b854 100644 --- a/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/ethernet/eth_netdev.c +++ b/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/ethernet/eth_netdev.c @@ -76,6 +76,7 @@ static int lwip_netdev_set_addr_info(struct netdev* netdev, ip_addr_t* ip_addr, netif_set_gw((struct netif*)netdev->user_data, ip_2_ip4(gw)); } } + return 0; } #ifdef LWIP_DNS @@ -92,7 +93,7 @@ static int lwip_netdev_set_dns_server(struct netdev* netdev, uint8_t dns_num, ip } #endif -#ifdef LWIP_DHCP +#if LWIP_DHCP static int lwip_netdev_set_dhcp(struct netdev* netdev, bool is_enabled) { netdev_low_level_set_dhcp_status(netdev, is_enabled); @@ -120,7 +121,7 @@ static const struct netdev_ops lwip_netdev_ops = { #ifdef LWIP_DNS .set_dns_server = lwip_netdev_set_dns_server, #endif -#ifdef LWIP_DHCP +#if LWIP_DHCP .set_dhcp = lwip_netdev_set_dhcp, #endif .set_default = lwip_netdev_set_default, @@ -180,9 +181,9 @@ int lwip_netdev_add(struct netif* lwip_netif) netdev->ops = &lwip_netdev_ops; netdev->hwaddr_len = lwip_netif->hwaddr_len; memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len); - netdev->ip_addr = lwip_netif->ip_addr; - netdev->gw = lwip_netif->gw; - netdev->netmask = lwip_netif->netmask; + netdev->ip_addr = &lwip_netif->ip_addr; + netdev->gw = &lwip_netif->gw; + netdev->netmask = &lwip_netif->netmask; return result; } diff --git a/Ubiquitous/XiZi_IIoT/compiler.mk b/Ubiquitous/XiZi_IIoT/compiler.mk index 87aba0280..4a91b1ba0 100644 --- a/Ubiquitous/XiZi_IIoT/compiler.mk +++ b/Ubiquitous/XiZi_IIoT/compiler.mk @@ -2,6 +2,8 @@ ifeq ($(COMPILE_TYPE), COMPILE_MUSL) SRC_DIR_TEMP := $(MUSL_DIR) else ifeq ($(COMPILE_TYPE), COMPILE_LWIP) SRC_DIR_TEMP := $(LWIP_DIR) +else ifeq ($(COMPILE_TYPE), COMPILE_MONGOOSE) +SRC_DIR_TEMP := $(MONGOOSE_DIR) else SRC_DIR_TEMP := $(SRC_DIR) endif @@ -9,6 +11,7 @@ endif SRC_DIR := MUSL_DIR := LWIP_DIR := +MONGOOSE_DIR := ifeq ($(USE_APP_INCLUDEPATH), y) include $(KERNEL_ROOT)/path_app.mk diff --git a/Ubiquitous/XiZi_IIoT/fs/shared/include/iot-vfs_posix.h b/Ubiquitous/XiZi_IIoT/fs/shared/include/iot-vfs_posix.h index 00f67aaee..80df49507 100644 --- a/Ubiquitous/XiZi_IIoT/fs/shared/include/iot-vfs_posix.h +++ b/Ubiquitous/XiZi_IIoT/fs/shared/include/iot-vfs_posix.h @@ -15,7 +15,8 @@ #include -typedef void DIR; +#include +// typedef void void; #if defined(LIB_NEWLIB) && defined(_EXFUN) _READ_WRITE_RETURN_TYPE _EXFUN(read, (int __fd, void *__buf, size_t __nbyte)); @@ -39,15 +40,15 @@ int fsync(int fd); int ftruncate(int fd, off_t length); int mkdir(const char *path, mode_t mode); -DIR *opendir(const char *path); -int closedir(DIR *dirp); -struct dirent *readdir(DIR *dirp); +void* opendir(const char* path); +int closedir(void* dirp); +struct dirent* readdir(void* dirp); int rmdir(const char *path); int chdir(const char *path); char *getcwd(char *buf, size_t size); -long telldir(DIR *dirp); -void seekdir(DIR *dirp, off_t offset); -void rewinddir(DIR *dirp); +long telldir(void* dirp); +void seekdir(void* dirp, off_t offset); +void rewinddir(void* dirp); int statfs(const char *path, struct statfs *buf); diff --git a/Ubiquitous/XiZi_IIoT/fs/shared/src/iot-vfs.c b/Ubiquitous/XiZi_IIoT/fs/shared/src/iot-vfs.c index 2d3421d1a..e8835ef94 100644 --- a/Ubiquitous/XiZi_IIoT/fs/shared/src/iot-vfs.c +++ b/Ubiquitous/XiZi_IIoT/fs/shared/src/iot-vfs.c @@ -906,7 +906,7 @@ err: return 0; } -DIR *opendir(const char *path) +void* opendir(const char* path) { struct FileDescriptor *fdp; struct MountPoint *mp; @@ -968,7 +968,7 @@ err: return fdp; } -int closedir(DIR *dirp) +int closedir(void* dirp) { struct FileDescriptor *fdp = dirp; int ret; @@ -999,7 +999,7 @@ int closedir(DIR *dirp) } static struct dirent dirent; -struct dirent *readdir(DIR *dirp) +struct dirent* readdir(void* dirp) { struct FileDescriptor *fdp = dirp; int ret; @@ -1036,7 +1036,7 @@ int rmdir(const char *path) int chdir(const char *path) { char *abspath; - DIR *dirp; + void* dirp; if (path == NULL) { SYS_ERR("%s: invalid path\n", __func__); @@ -1074,7 +1074,7 @@ char *getcwd(char *buf, size_t size) return buf; } -void seekdir(DIR *dirp, off_t offset) +void seekdir(void* dirp, off_t offset) { struct FileDescriptor *fdp = dirp; @@ -1093,7 +1093,7 @@ void seekdir(DIR *dirp, off_t offset) fdp->mntp->fs->seekdir(fdp, offset); } -void rewinddir(DIR *dirp) +void rewinddir(void* dirp) { struct FileDescriptor *fdp = dirp; diff --git a/Ubiquitous/XiZi_IIoT/kernel/include/xs_kdbg.h b/Ubiquitous/XiZi_IIoT/kernel/include/xs_kdbg.h index afd6dd617..c4cf2c162 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/include/xs_kdbg.h +++ b/Ubiquitous/XiZi_IIoT/kernel/include/xs_kdbg.h @@ -44,15 +44,16 @@ extern "C" { #define MSGQUEUE_DEBUG 0 #define FILESYS_DEBUG 0 -#define NETDEV_DEBUG 0 +#define NETDEV_DEBUG 1 #define WEBNET_DEBUG 0 #define WIZNET_DEBUG 0 -#define SYS_KDEBUG_LOG(section, information) \ - do { \ - if (section) { \ - KPrintf information; \ - } \ +#define SYS_KDEBUG_LOG(section, information) \ + do { \ + if (section) { \ + KPrintf("[%s:%d] ", __func__, __LINE__); \ + KPrintf information; \ + } \ } while (0) #define KDYN_NONE 0 diff --git a/Ubiquitous/XiZi_IIoT/link.mk b/Ubiquitous/XiZi_IIoT/link.mk index a2bdd07d4..09e643226 100644 --- a/Ubiquitous/XiZi_IIoT/link.mk +++ b/Ubiquitous/XiZi_IIoT/link.mk @@ -3,7 +3,7 @@ OBJS := $(shell cat make.obj) $(TARGET): $(OBJS) @echo ------------------------------------------------ @echo link $(TARGET) - @$(CROSS_COMPILE)g++ -o $@ $($(LINK_FLAGS)) $(OBJS) $(LINK_LWIP) $(LINK_MUSLLIB) $(LIBCC) + @$(CROSS_COMPILE)g++ -o $@ $($(LINK_FLAGS)) $(OBJS) $(LINK_LWIP) $(LINK_MUSLLIB) $(LINK_MONGOOSE) $(LIBCC) @echo ------------------------------------------------ @$(CROSS_COMPILE)objcopy -O binary $@ XiZi-$(BOARD)$(COMPILE_TYPE).bin @$(CROSS_COMPILE)objdump -S $@ > XiZi-$(BOARD)$(COMPILE_TYPE).asm diff --git a/Ubiquitous/XiZi_IIoT/link_mongoose.mk b/Ubiquitous/XiZi_IIoT/link_mongoose.mk new file mode 100644 index 000000000..568c910b0 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/link_mongoose.mk @@ -0,0 +1,9 @@ +OBJS := $(shell cat make.obj) + +$(TARGET): $(OBJS) + @echo ------------------------------------------------ + @echo link $(TARGET) + @$(CROSS_COMPILE)ar -r $@ $(OBJS) + @echo ------------------------------------------------ + @$(CROSS_COMPILE)objcopy $@ $(TARGET) + @$(CROSS_COMPILE)size $@ \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/path_kernel.mk b/Ubiquitous/XiZi_IIoT/path_kernel.mk index 9c3815c52..adb080b5d 100755 --- a/Ubiquitous/XiZi_IIoT/path_kernel.mk +++ b/Ubiquitous/XiZi_IIoT/path_kernel.mk @@ -535,6 +535,19 @@ endif ifeq ($(CONFIG_SUPPORT_CONNECTION_FRAMEWORK), y) KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/connection # KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/connection/zigbee # + +ifeq ($(CONFIG_CONNECTION_MODBUS), y) +KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/include # +KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/port # + +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_RTU), y) +KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/rtu # +endif + +ifeq ($(CONFIG_CONNECTION_MODBUS_USING_TCP), y) +KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/connection/industrial_fieldbus/modbus/freemodbus-latest/modbus/tcp # +endif +endif endif ifeq ($(CONFIG_ADAPTER_HFA21_ETHERCAT), y) diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/api/sockets.c b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/api/sockets.c index 3ddd778f5..5f458d8f0 100644 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/api/sockets.c +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/api/sockets.c @@ -640,7 +640,8 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s)); sock = get_socket(s); if (!sock) { - return -1; + KPrintf("sock = get_socket(s);\n"); + return -1; } /* wait for a new connection */ @@ -655,6 +656,7 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) sock_set_errno(sock, err_to_errno(err)); } done_socket(sock); + KPrintf("err = netconn_accept(sock->conn, &newconn);\n"); return -1; } LWIP_ASSERT("newconn != NULL", newconn != NULL); @@ -664,6 +666,7 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) netconn_delete(newconn); sock_set_errno(sock, ENFILE); done_socket(sock); + KPrintf("newsock = alloc_socket(newconn, 1);\n"); return -1; } LWIP_ASSERT("invalid socket index", (newsock >= LWIP_SOCKET_OFFSET) && (newsock < NUM_SOCKETS + LWIP_SOCKET_OFFSET)); @@ -701,6 +704,7 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) free_socket(nsock, 1); sock_set_errno(sock, err_to_errno(err)); done_socket(sock); + KPrintf("err = netconn_peer(newconn, &naddr, &port);\n"); return -1; } @@ -1242,6 +1246,8 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags, if (err != ERR_OK) { LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom[UDP/RAW](%d): buf == NULL, error is \"%s\"!\n", s, lwip_strerr(err))); + KPrintf("lwip_recvfrom[UDP/RAW](%d): buf == NULL, error is \"%s\"!\n", + s, lwip_strerr(err)); sock_set_errno(sock, err_to_errno(err)); done_socket(sock); return -1; diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/lwipopts.h b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/lwipopts.h index 72106e022..ffbb51d74 100644 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/lwipopts.h +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/lwipopts.h @@ -36,6 +36,7 @@ #ifndef LWIP_DEBUG #define LWIP_DEBUG 1 // #define LWIP_SOCKET_DEBUG +// #define LWIP_SOCKETS_DEBUG // #define LWIP_TCPIP_DEBUG // #define LWIP_MEMP_DEBUG // #define LWIP_PBUF_DEBUG @@ -271,13 +272,16 @@ a lot of data that needs to be copied, this should be set high. */ #define MEMP_NUM_PBUF 32 /* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One per active UDP "connection". */ -#define MEMP_NUM_UDP_PCB 4 +#define MEMP_NUM_UDP_PCB 32 /* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. */ -#define MEMP_NUM_TCP_PCB 64 +#define MEMP_NUM_TCP_PCB 32 +#define MEMP_NUM_RAW_PCB 32 +#define MEMP_NUM_REASSDATA 32 +#define MEMP_NUM_NETCONN 32 /* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. */ -#define MEMP_NUM_TCP_PCB_LISTEN 2 +#define MEMP_NUM_TCP_PCB_LISTEN 32 /* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. */ #define MEMP_NUM_TCP_SEG 256 @@ -383,12 +387,6 @@ a lot of data that needs to be copied, this should be set high. */ /* ---------- ICMP options ---------- */ #define LWIP_ICMP 1 -/* ---------- DHCP options ---------- */ -/* Define LWIP_DHCP to 1 if you want DHCP configuration of - interfaces. DHCP is not implemented in lwIP 0.5.1, however, so - turning this on does currently not work. */ -#define LWIP_DHCP 1 - /* ---------- UDP options ---------- */ #define LWIP_UDP 1 #define UDP_TTL 255 @@ -412,7 +410,7 @@ The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums - To use this feature let the following define uncommented. - To disable it and process by CPU comment the the checksum. */ -#define CHECKSUM_BY_HARDWARE +// #define CHECKSUM_BY_HARDWARE #ifdef CHECKSUM_BY_HARDWARE /* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/ @@ -520,7 +518,7 @@ The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums /* ---------- DHCP options ---------- */ /* Define LWIP_DHCP to 1 if you want DHCP configuration of interfaces. */ -#define LWIP_DHCP 1 +#define LWIP_DHCP 0 /* 1 if you want to do an ARP check on the offered address (recommended). */ diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/sys_arch.c b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/sys_arch.c index 99b1c8579..788e7e3e3 100644 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/sys_arch.c +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/sys_arch.c @@ -76,9 +76,9 @@ char lwip_eth0_ipaddr[20] = { 192, 168, 130, 77 }; char lwip_eth0_netmask[20] = { 255, 255, 254, 0 }; char lwip_eth0_gwaddr[20] = { 192, 168, 130, 1 }; -char lwip_eth1_ipaddr[20] = { 192, 168, 130, 99 }; +char lwip_eth1_ipaddr[20] = { 192, 168, 131, 88 }; char lwip_eth1_netmask[20] = { 255, 255, 254, 0 }; -char lwip_eth1_gwaddr[20] = { 192, 168, 130, 23 }; +char lwip_eth1_gwaddr[20] = { 192, 168, 130, 1 }; char lwip_flag = 0; @@ -93,6 +93,13 @@ sys_sem_t* get_eth_recv_sem() return &g_recv_sem; } +struct netif gnetif2; +sys_sem_t* get_eth_recv_sem2() +{ + static sys_sem_t g_recv_sem = 0; + return &g_recv_sem; +} + void sys_init(void) { // do nothing @@ -332,136 +339,104 @@ ip4_addr_t ipaddr; ip4_addr_t netmask; ip4_addr_t gw; -void lwip_config_input(struct netif* net) +void lwip_config_input(int eport, struct netif* net) { sys_thread_t th_id = 0; - th_id = sys_thread_new("eth_input", ethernetif_input, net, LWIP_TASK_STACK_SIZE, 30); - - // if (th_id >= 0) { - // lw_print("%s %d successfully!\n", __func__, th_id); - // } else { - // lw_print("%s failed!\n", __func__); - // } + if (eport == 0) { + th_id = sys_thread_new("eth_input", ethernetif_input, net, LWIP_TASK_STACK_SIZE, 30); + } else if (eport == 1) { +#ifdef NETIF_ENET1_INIT_FUNC + th_id = sys_thread_new("eth_input2", ethernetif_input2, net, LWIP_TASK_STACK_SIZE, 30); +#endif + } } void lwip_config_tcp(uint8_t enet_port, char* ip, char* mask, char* gw) { - static char is_init = 0; - if (is_init != 0) { - return; + static char is_init_0 = 0; + static char is_init_1 = 0; + if (is_init_0 == 0 && is_init_1 == 0) { + sys_sem_new(get_eth_recv_sem(), 0); + sys_sem_new(get_eth_recv_sem2(), 0); + + if (chk_lwip_bit(LWIP_INIT_FLAG)) { + lw_print("lw: [%s] already ...\n", __func__); + } + + set_lwip_bit(LWIP_INIT_FLAG); + + tcpip_init(NULL, NULL); } - is_init = 1; - - sys_sem_new(get_eth_recv_sem(), 0); - - ip4_addr_t net_ipaddr, net_netmask, net_gw; - char* eth_cfg; - - eth_cfg = ethernetif_config_enet_set(enet_port); - - if (chk_lwip_bit(LWIP_INIT_FLAG)) { - lw_print("lw: [%s] already ...\n", __func__); - return; - } - - set_lwip_bit(LWIP_INIT_FLAG); - - tcpip_init(NULL, NULL); lw_print("lw: [%s] start ...\n", __func__); + char* eth_cfg = ethernetif_config_enet_set(enet_port); + ip4_addr_t net_ipaddr, net_netmask, net_gw; IP4_ADDR(&net_ipaddr, ip[0], ip[1], ip[2], ip[3]); IP4_ADDR(&net_netmask, mask[0], mask[1], mask[2], mask[3]); IP4_ADDR(&net_gw, gw[0], gw[1], gw[2], gw[3]); if (0 == enet_port) { + if (is_init_0 == 1) { + return; + } +#ifndef NETIF_ENET0_INIT_FUNC + lw_print("Not Netif driver for Eport 0\n"); + return; +#endif #ifdef NETIF_ENET0_INIT_FUNC + lw_print("Add netif eport 0\n"); netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET0_INIT_FUNC, tcpip_input); -#endif - } else if (1 == enet_port) { -#ifdef NETIF_ENET1_INIT_FUNC - netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET1_INIT_FUNC, - tcpip_input); -#endif - } - netif_set_default(&gnetif); - netif_set_up(&gnetif); - - lw_print("\r\n************************************************\r\n"); - lw_print(" Network Configuration\r\n"); - lw_print("************************************************\r\n"); - lw_print(" IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t*)&net_ipaddr)[0], ((u8_t*)&net_ipaddr)[1], - ((u8_t*)&net_ipaddr)[2], ((u8_t*)&net_ipaddr)[3]); - lw_print(" IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t*)&net_netmask)[0], ((u8_t*)&net_netmask)[1], - ((u8_t*)&net_netmask)[2], ((u8_t*)&net_netmask)[3]); - lw_print(" IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t*)&net_gw)[0], ((u8_t*)&net_gw)[1], - ((u8_t*)&net_gw)[2], ((u8_t*)&net_gw)[3]); - lw_print("************************************************\r\n"); - - lwip_config_input(&gnetif); -} - -void lwip_config_net(uint8_t enet_port, char* ip, char* mask, char* gw) -{ - ip4_addr_t net_ipaddr, net_netmask, net_gw; - char* eth_cfg; - - eth_cfg = ethernetif_config_enet_set(enet_port); - - if (chk_lwip_bit(LWIP_INIT_FLAG)) { - lw_print("lw: [%s] already ...\n", __func__); - - IP4_ADDR(&net_ipaddr, ip[0], ip[1], ip[2], ip[3]); - IP4_ADDR(&net_netmask, mask[0], mask[1], mask[2], mask[3]); - IP4_ADDR(&net_gw, gw[0], gw[1], gw[2], gw[3]); - - // update ip addr - netif_set_down(&gnetif); - netif_set_gw(&gnetif, &net_gw); - netif_set_netmask(&gnetif, &net_netmask); - netif_set_ipaddr(&gnetif, &net_ipaddr); + netif_set_default(&gnetif); netif_set_up(&gnetif); - return; - } - set_lwip_bit(LWIP_INIT_FLAG); - lw_print("lw: [%s] start ...\n", __func__); - - IP4_ADDR(&net_ipaddr, ip[0], ip[1], ip[2], ip[3]); - IP4_ADDR(&net_netmask, mask[0], mask[1], mask[2], mask[3]); - IP4_ADDR(&net_gw, gw[0], gw[1], gw[2], gw[3]); - - lwip_init(); - - if (0 == enet_port) { -#ifdef NETIF_ENET0_INIT_FUNC - netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET0_INIT_FUNC, - ethernet_input); -#endif - } else if (1 == enet_port) { -#ifdef NETIF_ENET1_INIT_FUNC - netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET1_INIT_FUNC, - ethernet_input); -#endif - } - - netif_set_default(&gnetif); - netif_set_up(&gnetif); - - if (chk_lwip_bit(LWIP_PRINT_FLAG)) { - lw_notice("\r\n************************************************\r\n"); - lw_notice(" Network Configuration\r\n"); - lw_notice("************************************************\r\n"); - lw_notice(" IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t*)&net_ipaddr)[0], ((u8_t*)&net_ipaddr)[1], + lw_print("\r\n************************************************\r\n"); + lw_print(" Network Configuration\r\n"); + lw_print("************************************************\r\n"); + lw_print(" IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t*)&net_ipaddr)[0], ((u8_t*)&net_ipaddr)[1], ((u8_t*)&net_ipaddr)[2], ((u8_t*)&net_ipaddr)[3]); - lw_notice(" IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t*)&net_netmask)[0], ((u8_t*)&net_netmask)[1], + lw_print(" IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t*)&net_netmask)[0], ((u8_t*)&net_netmask)[1], ((u8_t*)&net_netmask)[2], ((u8_t*)&net_netmask)[3]); - lw_notice(" IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t*)&net_gw)[0], ((u8_t*)&net_gw)[1], + lw_print(" IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t*)&net_gw)[0], ((u8_t*)&net_gw)[1], ((u8_t*)&net_gw)[2], ((u8_t*)&net_gw)[3]); - lw_notice("************************************************\r\n"); + lw_print("************************************************\r\n"); + + lwip_config_input(enet_port, &gnetif); + is_init_0 = 1; +#endif + + } else if (1 == enet_port) { + if (is_init_1 == 1) { + return; + } +#ifndef NETIF_ENET1_INIT_FUNC + lw_print("Not Netif driver for Eport 1\n"); + return; +#endif +#ifdef NETIF_ENET1_INIT_FUNC + lw_print("Add netif eport 1\n"); + netif_add(&gnetif2, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET1_INIT_FUNC, + tcpip_input); + + // netif_set_default(&gnetif2); + netif_set_up(&gnetif2); + + lw_print("\r\n************************************************\r\n"); + lw_print(" Network Configuration\r\n"); + lw_print("************************************************\r\n"); + lw_print(" IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t*)&net_ipaddr)[0], ((u8_t*)&net_ipaddr)[1], + ((u8_t*)&net_ipaddr)[2], ((u8_t*)&net_ipaddr)[3]); + lw_print(" IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t*)&net_netmask)[0], ((u8_t*)&net_netmask)[1], + ((u8_t*)&net_netmask)[2], ((u8_t*)&net_netmask)[3]); + lw_print(" IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t*)&net_gw)[0], ((u8_t*)&net_gw)[1], + ((u8_t*)&net_gw)[2], ((u8_t*)&net_gw)[3]); + lw_print("************************************************\r\n"); + + lwip_config_input(enet_port, &gnetif2); + is_init_1 = 1; +#endif } - lwip_config_input(&gnetif); -} +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/sys_arch.h b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/sys_arch.h index 384b85b1a..bbcef28ac 100644 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/sys_arch.h +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/sys_arch.h @@ -101,6 +101,8 @@ extern char lwip_eth1_gwaddr[]; extern struct netif gnetif; extern sys_sem_t* get_eth_recv_sem(); +extern struct netif gnetif2; +extern sys_sem_t* get_eth_recv_sem2(); void lwip_tcp_init(void); void lwip_config_net(uint8_t enet_port, char *ip, char *mask, char *gw); diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/core/ipv4/ip4.c b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/core/ipv4/ip4.c index 036457afe..3cb0ca16f 100644 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/core/ipv4/ip4.c +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/core/ipv4/ip4.c @@ -228,6 +228,95 @@ ip4_route(const ip4_addr_t *dest) return netif_default; } +/** + * Finds the appropriate network interface for a given IP address. It + * searches the list of network interfaces linearly. A match is found + * if the masked IP address of the network interface equals the masked + * IP address given to the function. + * + * @param dest the destination IP address for which to find the route + * @return the netif on which to send to reach dest + */ +struct netif* +ip4_route2(const ip4_addr_t* src, const ip4_addr_t* dest) +{ +#if !LWIP_SINGLE_NETIF + struct netif* netif; + LWIP_ASSERT_CORE_LOCKED(); + +#if LWIP_MULTICAST_TX_OPTIONS + /* Use administratively selected interface for multicast by default */ + if (ip4_addr_ismulticast(dest) && ip4_default_multicast_netif) { + return ip4_default_multicast_netif; + } +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + + /* bug #54569: in case LWIP_SINGLE_NETIF=1 and LWIP_DEBUGF() disabled, the following loop is optimized away */ + LWIP_UNUSED_ARG(dest); + + /* iterate through netifs */ + NETIF_FOREACH(netif) + { + /* is the netif up, does it have a link and a valid address? */ + if (netif_is_up(netif) && netif_is_link_up(netif) && !ip4_addr_isany_val(*netif_ip4_addr(netif))) { + + /* network mask matches? */ + // if (ip4_addr_netcmp(dest, netif_ip4_addr(netif), netif_ip4_netmask(netif))) { + if (ip4_addr_cmp(src, netif_ip4_addr(netif))) { + /* return netif on which to forward IP packet */ + return netif; + } + /* gateway matches on a non broadcast interface? (i.e. peer in a point to point interface) */ + if (((netif->flags & NETIF_FLAG_BROADCAST) == 0) && ip4_addr_cmp(dest, netif_ip4_gw(netif))) { + /* return netif on which to forward IP packet */ + return netif; + } + } + } + +#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF + /* loopif is disabled, looopback traffic is passed through any netif */ + if (ip4_addr_isloopback(dest)) { + /* don't check for link on loopback traffic */ + if (netif_default != NULL && netif_is_up(netif_default)) { + return netif_default; + } + /* default netif is not up, just use any netif for loopback traffic */ + NETIF_FOREACH(netif) + { + if (netif_is_up(netif)) { + return netif; + } + } + return NULL; + } +#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ + +#ifdef LWIP_HOOK_IP4_ROUTE_SRC + netif = LWIP_HOOK_IP4_ROUTE_SRC(NULL, dest); + if (netif != NULL) { + return netif; + } +#elif defined(LWIP_HOOK_IP4_ROUTE) + netif = LWIP_HOOK_IP4_ROUTE(dest); + if (netif != NULL) { + return netif; + } +#endif +#endif /* !LWIP_SINGLE_NETIF */ + + if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default) || ip4_addr_isany_val(*netif_ip4_addr(netif_default)) || ip4_addr_isloopback(dest)) { + /* No matching netif found and default netif is not usable. + If this is not good enough for you, use LWIP_HOOK_IP4_ROUTE() */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_route: No route to %" U16_F ".%" U16_F ".%" U16_F ".%" U16_F "\n", ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + MIB2_STATS_INC(mib2.ipoutnoroutes); + return NULL; + } + + return netif_default; +} + #if IP_FORWARD /** * Determine whether an IP address is in a reserved set of addresses diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/include/lwip/ip4.h b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/include/lwip/ip4.h index fd35a3369..d3789a9be 100644 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/include/lwip/ip4.h +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/include/lwip/ip4.h @@ -63,39 +63,41 @@ extern "C" { #define ip_init() /* Compatibility define, no init needed. */ struct netif *ip4_route(const ip4_addr_t *dest); +struct netif* ip4_route2(const ip4_addr_t* src, const ip4_addr_t* dest); #if LWIP_IPV4_SRC_ROUTING -struct netif *ip4_route_src(const ip4_addr_t *src, const ip4_addr_t *dest); +struct netif* ip4_route_src(const ip4_addr_t* src, const ip4_addr_t* dest); #else /* LWIP_IPV4_SRC_ROUTING */ -#define ip4_route_src(src, dest) ip4_route(dest) +// #define ip4_route_src(src, dest) ip4_route(dest) +#define ip4_route_src(src, dest) ip4_route2(src, dest) #endif /* LWIP_IPV4_SRC_ROUTING */ -err_t ip4_input(struct pbuf *p, struct netif *inp); -err_t ip4_output(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto); -err_t ip4_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, struct netif *netif); -err_t ip4_output_if_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, struct netif *netif); +err_t ip4_input(struct pbuf* p, struct netif* inp); +err_t ip4_output(struct pbuf* p, const ip4_addr_t* src, const ip4_addr_t* dest, + u8_t ttl, u8_t tos, u8_t proto); +err_t ip4_output_if(struct pbuf* p, const ip4_addr_t* src, const ip4_addr_t* dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif* netif); +err_t ip4_output_if_src(struct pbuf* p, const ip4_addr_t* src, const ip4_addr_t* dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif* netif); #if LWIP_NETIF_USE_HINTS -err_t ip4_output_hinted(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, struct netif_hint *netif_hint); + err_t ip4_output_hinted(struct pbuf* p, const ip4_addr_t* src, const ip4_addr_t* dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif_hint* netif_hint); #endif /* LWIP_NETIF_USE_HINTS */ #if IP_OPTIONS_SEND -err_t ip4_output_if_opt(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, - u16_t optlen); -err_t ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, - u16_t optlen); + err_t ip4_output_if_opt(struct pbuf* p, const ip4_addr_t* src, const ip4_addr_t* dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif* netif, void* ip_options, + u16_t optlen); + err_t ip4_output_if_opt_src(struct pbuf* p, const ip4_addr_t* src, const ip4_addr_t* dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif* netif, void* ip_options, + u16_t optlen); #endif /* IP_OPTIONS_SEND */ #if LWIP_MULTICAST_TX_OPTIONS -void ip4_set_default_multicast_netif(struct netif* default_multicast_netif); + void ip4_set_default_multicast_netif(struct netif* default_multicast_netif); #endif /* LWIP_MULTICAST_TX_OPTIONS */ #define ip4_netif_get_local_ip(netif) (((netif) != NULL) ? netif_ip_addr4(netif) : NULL) #if IP_DEBUG -void ip4_debug_print(struct pbuf *p); + void ip4_debug_print(struct pbuf* p); #else #define ip4_debug_print(p) #endif /* IP_DEBUG */ diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/include/lwip/opt.h b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/include/lwip/opt.h index a304c67c2..55c840233 100644 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/include/lwip/opt.h +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/include/lwip/opt.h @@ -521,7 +521,7 @@ * (only needed if you use the sequential API, like api_lib.c) */ #if !defined MEMP_NUM_NETBUF || defined __DOXYGEN__ -#define MEMP_NUM_NETBUF 2 +#define MEMP_NUM_NETBUF 8 #endif /** @@ -529,7 +529,7 @@ * (only needed if you use the sequential API, like api_lib.c) */ #if !defined MEMP_NUM_NETCONN || defined __DOXYGEN__ -#define MEMP_NUM_NETCONN 4 +#define MEMP_NUM_NETCONN 8 #endif /** @@ -538,7 +538,7 @@ * In that case, you need one per thread calling lwip_select.) */ #if !defined MEMP_NUM_SELECT_CB || defined __DOXYGEN__ -#define MEMP_NUM_SELECT_CB 4 +#define MEMP_NUM_SELECT_CB 4 #endif /** @@ -547,7 +547,7 @@ * (only needed if you use tcpip.c) */ #if !defined MEMP_NUM_TCPIP_MSG_API || defined __DOXYGEN__ -#define MEMP_NUM_TCPIP_MSG_API 8 +#define MEMP_NUM_TCPIP_MSG_API 8 #endif /** @@ -556,7 +556,7 @@ * (only needed if you use tcpip.c) */ #if !defined MEMP_NUM_TCPIP_MSG_INPKT || defined __DOXYGEN__ -#define MEMP_NUM_TCPIP_MSG_INPKT 8 +#define MEMP_NUM_TCPIP_MSG_INPKT 8 #endif /** @@ -564,7 +564,7 @@ * (before freeing the corresponding memory using lwip_freeaddrinfo()). */ #if !defined MEMP_NUM_NETDB || defined __DOXYGEN__ -#define MEMP_NUM_NETDB 1 +#define MEMP_NUM_NETDB 2 #endif /** @@ -572,7 +572,7 @@ * if DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1. */ #if !defined MEMP_NUM_LOCALHOSTLIST || defined __DOXYGEN__ -#define MEMP_NUM_LOCALHOSTLIST 1 +#define MEMP_NUM_LOCALHOSTLIST 2 #endif /** diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/Makefile b/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/Makefile index 5cb85ac11..0536f5329 100755 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/Makefile +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/Makefile @@ -1,4 +1,3 @@ -# SRC_FILES := ping.c lwip_ping_demo.c lwip_config_demo.c lwip_dhcp_demo.c iperf.c http_test.c -SRC_FILES := ping.c lwip_ping_demo.c lwip_udp_demo.c tcpecho_raw.c lwip_config_demo.c lwip_dhcp_demo.c +SRC_FILES := ping.c lwip_ping_demo.c tcpecho_raw.c lwip_config_demo.c lwip_tcp_demo.c include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/lwip_config_demo.c b/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/lwip_config_demo.c index b1b145648..1d6aa94e8 100755 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/lwip_config_demo.c +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/lwip_config_demo.c @@ -25,104 +25,145 @@ #include #include -#include +#include "argparse.h" + +#include "inet.h" +#include "netdev.h" /******************************************************************************/ -uint8_t enet_id = 0; -static void LwipSetIPTask(void* param) -{ - uint8_t enet_port = *(uint8_t*)param; ///< test enet port - printf("lw: [%s] config netport id[%d]\n", __func__, enet_port); - // lwip_config_net(enet_port, lwip_ipaddr, lwip_netmask, lwip_gwaddr); - lwip_config_tcp(enet_port, lwip_ipaddr, lwip_netmask, lwip_gwaddr); -} +enum NETWORK_ACTIVE_E { + LWIP_ACTIVE = 'e', + LWIP_ACTIVE_ALL = 'a', +}; -void LwipSetIPTest(int argc, char* argv[]) +void LwipNetworkActive(int argc, char* argv[]) { - if (argc >= 4) { - printf("lw: [%s] ip %s mask %s gw %s netport %s\n", __func__, argv[1], argv[2], argv[3], argv[4]); - sscanf(argv[1], "%hhd.%hhd.%hhd.%hhd", &lwip_ipaddr[0], &lwip_ipaddr[1], &lwip_ipaddr[2], &lwip_ipaddr[3]); - sscanf(argv[2], "%hhd.%hhd.%hhd.%hhd", &lwip_netmask[0], &lwip_netmask[1], &lwip_netmask[2], &lwip_netmask[3]); - sscanf(argv[3], "%hhd.%hhd.%hhd.%hhd", &lwip_gwaddr[0], &lwip_gwaddr[1], &lwip_gwaddr[2], &lwip_gwaddr[3]); - sscanf(argv[4], "%hhd", &enet_id); + static char usage_info[] = "select a eport to start."; + static char program_info[] = "Active lwip network function."; + static const char* const net_active_usages[] = { + "LwipNetworkActive -e 0", + "LwipNetworkActive -e 1", + "LwipNetworkActive -a", + }; - if (0 == enet_id) { - printf("save eth0 info\n"); - memcpy(lwip_eth0_ipaddr, lwip_ipaddr, 20); - memcpy(lwip_eth0_netmask, lwip_netmask, 20); - memcpy(lwip_eth0_gwaddr, lwip_gwaddr, 20); - } else if (1 == enet_id) { - printf("save eth1 info\n"); - memcpy(lwip_eth1_ipaddr, lwip_ipaddr, 20); - memcpy(lwip_eth1_netmask, lwip_netmask, 20); - memcpy(lwip_eth1_gwaddr, lwip_gwaddr, 20); - } - } else if (argc == 2) { - printf("lw: [%s] set eth0 ipaddr %s \n", __func__, argv[1]); - sscanf(argv[1], "%hhd.%hhd.%hhd.%hhd", &lwip_ipaddr[0], &lwip_ipaddr[1], &lwip_ipaddr[2], &lwip_ipaddr[3]); - memcpy(lwip_eth0_ipaddr, lwip_ipaddr, strlen(lwip_ipaddr)); + int eport = -1; + bool all = false; + bool is_help = false; + struct argparse_option options[] = { + OPT_HELP(&is_help), + OPT_INTEGER(LWIP_ACTIVE, "eport", &eport, "eport to start network.", NULL, 0, 0), + OPT_BIT(LWIP_ACTIVE_ALL, "all", &all, "start network at both eport 0 and 1.", NULL, true, 0), + OPT_END(), + }; + + struct argparse argparse; + argparse_init(&argparse, options, net_active_usages, 0); + argparse_describe(&argparse, usage_info, program_info); + argc = argparse_parse(&argparse, argc, (const char**)argv); + if (is_help) { + return; } - // sys_thread_new("SET ip address", LwipSetIPTask, &enet_id, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); - LwipSetIPTask(&enet_id); -} + if (all) { + lwip_config_tcp(0, lwip_eth0_ipaddr, lwip_eth0_netmask, lwip_eth0_gwaddr); + lwip_config_tcp(1, lwip_eth1_ipaddr, lwip_eth1_netmask, lwip_eth1_gwaddr); + return; + } + + if (eport != 0 && eport != 1) { + printf("[%s] Err: Support only eport 0 and eport 1.\n", __func__); + } + + if (eport == 0) { + lwip_config_tcp(0, lwip_eth0_ipaddr, lwip_eth0_netmask, lwip_eth0_gwaddr); + } else if (eport == 1) { + lwip_config_tcp(1, lwip_eth1_ipaddr, lwip_eth1_netmask, lwip_eth1_gwaddr); + } +} SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(5), - setip, LwipSetIPTest, setip[IP][Netmask][Gateway][port]); + LwipNetworkActive, LwipNetworkActive, start lwip); -void LwipShowIPTask(int argc, char* argv[]) +enum NETWORK_CONFIG_E { + NETWORK_DEV = 'd', + NETWORK_IP = 'i', + NETWORK_NM = 'n', + NETWORK_GW = 'g', +}; + +void LwipSetNetwork(int argc, char* argv[]) { -#ifdef configMAC_ADDR - char mac_addr0[] = configMAC_ADDR; -#endif + static char usage_info[] = "config network information."; + static char program_info[] = "set network ip, netmask, gateway"; + static const char* const net_set_usages[] = { + "LwipSetNetwork -d [dev] -i [ip]", + "LwipSetNetwork -d [dev] -n [netmask]", + "LwipSetNetwork -d [dev] -g [gw]", + "LwipSetNetwork -d [dev] -i [ip] -n [netmask] -g [gw]", + }; - // find default netdev - struct netdev* netdev = netdev_get_by_name("en\0"); + char* dev_ptr = NULL; + char* ip_ptr = NULL; + char* nm_ptr = NULL; + char* gw_ptr = NULL; + bool is_help = false; + struct argparse_option options[] = { + OPT_HELP(&is_help), + OPT_GROUP("Param Options"), + OPT_STRING(NETWORK_DEV, "dev", &dev_ptr, "netdev", NULL, 0, 0), + OPT_STRING(NETWORK_IP, "ip", &ip_ptr, "change ip", NULL, 0, 0), + OPT_STRING(NETWORK_NM, "nm", &nm_ptr, "change netmask", NULL, 0, 0), + OPT_STRING(NETWORK_GW, "gw", &gw_ptr, "change gateway", NULL, 0, 0), + OPT_END(), + }; + + struct argparse argparse; + argparse_init(&argparse, options, net_set_usages, 0); + argparse_describe(&argparse, usage_info, program_info); + argc = argparse_parse(&argparse, argc, (const char**)argv); + /* help task */ + if (is_help) { + return; + } + + if (dev_ptr == NULL) { + printf("[%s] Err: must given a netdev name.\n", __func__); + return; + } + struct netdev* netdev = netdev_get_by_name(dev_ptr); if (netdev == NULL) { - lw_notice("[%s] Netdev not found by name en\n"); - struct netdev* default_netdev = NETDEV_DEFAULT; + printf("[%s] Err: Netdev not found by name: %s\n", __func__, dev_ptr); + return; } - lw_notice("\r\n************************************************\r\n"); - lw_notice(" Network Configuration\r\n"); - lw_notice("************************************************\r\n"); - // lw_notice(" ETH0 IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_eth0_ipaddr)[0], ((u8_t*)&lwip_eth0_ipaddr)[1], - // ((u8_t*)&lwip_eth0_ipaddr)[2], ((u8_t*)&lwip_eth0_ipaddr)[3]); - // lw_notice(" ETH0 IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_eth0_netmask)[0], ((u8_t*)&lwip_eth0_netmask)[1], - // ((u8_t*)&lwip_eth0_netmask)[2], ((u8_t*)&lwip_eth0_netmask)[3]); - // lw_notice(" ETH0 IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_gwaddr)[0], ((u8_t*)&lwip_eth0_gwaddr)[1], - // ((u8_t*)&lwip_eth0_gwaddr)[2], ((u8_t*)&lwip_eth0_gwaddr)[3]); - // #ifdef configMAC_ADDR - // lw_notice(" ETH0 MAC Address : %x:%x:%x:%x:%x:%x\r\n", mac_addr0[0], mac_addr0[1], mac_addr0[2], - // mac_addr0[3], mac_addr0[4], mac_addr0[5]); - // #endif - - lw_notice(" ETH0 IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_eth0_ipaddr)[0], ((u8_t*)&lwip_eth0_ipaddr)[1], - ((u8_t*)&lwip_eth0_ipaddr)[2], ((u8_t*)&lwip_eth0_ipaddr)[3]); - lw_notice(" ETH0 IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_eth0_netmask)[0], ((u8_t*)&lwip_eth0_netmask)[1], - ((u8_t*)&lwip_eth0_netmask)[2], ((u8_t*)&lwip_eth0_netmask)[3]); - lw_notice(" ETH0 IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_gwaddr)[0], ((u8_t*)&lwip_eth0_gwaddr)[1], - ((u8_t*)&lwip_eth0_gwaddr)[2], ((u8_t*)&lwip_eth0_gwaddr)[3]); -#ifdef configMAC_ADDR - lw_notice(" ETH0 MAC Address : %x:%x:%x:%x:%x:%x\r\n", mac_addr0[0], mac_addr0[1], mac_addr0[2], - mac_addr0[3], mac_addr0[4], mac_addr0[5]); -#endif - -#ifdef BOARD_NET_COUNT - if (BOARD_NET_COUNT > 1) { - char mac_addr1[] = configMAC_ADDR_ETH1; - lw_notice("\r\n"); - lw_notice(" ETH1 IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_eth1_ipaddr)[0], ((u8_t*)&lwip_eth1_ipaddr)[1], - ((u8_t*)&lwip_eth1_ipaddr)[2], ((u8_t*)&lwip_eth1_ipaddr)[3]); - lw_notice(" ETH1 IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_eth1_netmask)[0], ((u8_t*)&lwip_eth1_netmask)[1], - ((u8_t*)&lwip_eth1_netmask)[2], ((u8_t*)&lwip_eth1_netmask)[3]); - lw_notice(" ETH1 IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_eth1_gwaddr)[0], ((u8_t*)&lwip_eth1_gwaddr)[1], - ((u8_t*)&lwip_eth1_gwaddr)[2], ((u8_t*)&lwip_eth1_gwaddr)[3]); - lw_notice(" ETH1 MAC Address : %x:%x:%x:%x:%x:%x\r\n", mac_addr1[0], mac_addr1[1], mac_addr1[2], - mac_addr1[3], mac_addr1[4], mac_addr1[5]); + ip_addr_t ipaddr, maskaddr, gwaddr; + if (ip_ptr != NULL) { + inet_aton(ip_ptr, &ipaddr); + if (0 != netdev_set_ipaddr(netdev, &ipaddr)) { + printf("[%s] Err: set ip: %s failed.\n", __func__, ip_ptr); + } } -#endif - lw_notice("************************************************\r\n"); + if (nm_ptr != NULL) { + inet_aton(nm_ptr, &maskaddr); + if (0 != netdev_set_netmask(netdev, &maskaddr)) { + printf("[%s] Err: set netmask: %s failed.\n", __func__, nm_ptr); + } + } + if (gw_ptr != NULL) { + inet_aton(gw_ptr, &gwaddr); + if (0 != netdev_set_gw(netdev, &gwaddr)) { + printf("[%s] Err: set gateway: %s failed.\n", __func__, gw_ptr); + } + } +} + +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(11), + LwipSetNetwork, LwipSetNetwork, config lwip); + +void LwipShowNetwork(int argc, char* argv[]) +{ + extern void netdev_list_dev(); + netdev_list_dev(); } SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0), - showip, LwipShowIPTask, GetIp[IP][Netmask][Gateway]); + LwipShowNetwork, LwipShowNetwork, show lwip network configuration); diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_lowlevel.c b/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_lowlevel.c index c1d4e0fa4..8cd2b0fde 100644 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_lowlevel.c +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_lowlevel.c @@ -43,8 +43,8 @@ void netdev_low_level_set_ipaddr(struct netdev* netdev, const ip_addr_t* ip_addr { CHECK(ip_addr); - if (netdev && ip_addr_cmp(&(netdev->ip_addr), ip_addr) == 0) { - ip_addr_copy(netdev->ip_addr, *ip_addr); + if (netdev && ip_addr_cmp((netdev->ip_addr), ip_addr) == 0) { + ip_addr_copy(*netdev->ip_addr, *ip_addr); /* execute IP address change callback function */ if (netdev->addr_callback) { @@ -64,8 +64,8 @@ void netdev_low_level_set_netmask(struct netdev* netdev, const ip_addr_t* netmas { CHECK(netmask); - if (netdev && ip_addr_cmp(&(netdev->netmask), netmask) == 0) { - ip_addr_copy(netdev->netmask, *netmask); + if (netdev && ip_addr_cmp((netdev->netmask), netmask) == 0) { + ip_addr_copy(*netdev->netmask, *netmask); /* execute netmask address change callback function */ if (netdev->addr_callback) { @@ -85,8 +85,8 @@ void netdev_low_level_set_gw(struct netdev* netdev, const ip_addr_t* gw) { CHECK(gw); - if (netdev && ip_addr_cmp(&(netdev->gw), gw) == 0) { - ip_addr_copy(netdev->gw, *gw); + if (netdev && ip_addr_cmp((netdev->gw), gw) == 0) { + ip_addr_copy(*netdev->gw, *gw); /* execute gateway address change callback function */ if (netdev->addr_callback) { diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_manipulate.c b/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_manipulate.c index 97e15d3a1..283261a1b 100644 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_manipulate.c +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_manipulate.c @@ -28,8 +28,12 @@ Modification: 1. support net dev set-ip, set-netmask, set-gw, set-addr-callback, set-status-callback, set-up and set-down *************************************************/ +#include + #include #include + +#include #include #include @@ -273,7 +277,7 @@ struct netdev* netdev_get_by_ipaddr(ip_addr_t* ip_addr) struct netdev* current_dev = NETDEV_LISTHEAD; SINGLE_LINKLIST_FOR_EACH_ENTRY(current_dev, &(NETDEV_LISTHEAD->list), list) { - if (NULL != current_dev && ip_addr_cmp(&(current_dev->ip_addr), ip_addr)) { + if (NULL != current_dev && ip_addr_cmp((current_dev->ip_addr), ip_addr)) { ENABLE_INTERRUPT(lock); return current_dev; } @@ -298,6 +302,8 @@ struct netdev* netdev_get_by_name(const char* name) return NULL; } + uint32_t search_name_len = strlen(name); + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("Netdev search name: %s, len: %d\n", name, search_name_len)); // get netdev from list x_base lock = DISABLE_INTERRUPT(); struct netdev* current_dev = NETDEV_LISTHEAD; @@ -306,8 +312,10 @@ struct netdev* netdev_get_by_name(const char* name) if (NULL == current_dev) { continue; } + uint32_t name_len = strlen(current_dev->name); - if (NULL != current_dev && (strncmp(current_dev->name, name, strlen(current_dev->name) < NAME_NUM_MAX ? strlen(current_dev->name) : NAME_NUM_MAX) == 0)) { + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("Netdev current dev name: %s, len: %d\n", current_dev->name, name_len)); + if (NULL != current_dev && name_len == search_name_len && 0 == strncmp(current_dev->name, name, name_len)) { ENABLE_INTERRUPT(lock); return current_dev; } @@ -316,3 +324,35 @@ struct netdev* netdev_get_by_name(const char* name) return NULL; } + +void netdev_list_dev() +{ + if (NETDEV_LISTHEAD == NULL) { + return; + } + + char ip[IP4ADDR_STRLEN_MAX], netmask[IP4ADDR_STRLEN_MAX], gw[IP4ADDR_STRLEN_MAX], dns[IP4ADDR_STRLEN_MAX]; + + // get netdev from list + x_base lock = DISABLE_INTERRUPT(); + struct netdev* current_dev = NETDEV_LISTHEAD; + SINGLE_LINKLIST_FOR_EACH_ENTRY(current_dev, &(NETDEV_LISTHEAD->list), list) + { + if (NULL == current_dev) { + continue; + } + + strncpy(ip, inet_ntoa(*current_dev->ip_addr), IP4ADDR_STRLEN_MAX); + strncpy(netmask, inet_ntoa(*current_dev->netmask), IP4ADDR_STRLEN_MAX); + strncpy(gw, inet_ntoa(*current_dev->gw), IP4ADDR_STRLEN_MAX); + strncpy(dns, inet_ntoa(current_dev->dns_servers[0]), IP4ADDR_STRLEN_MAX); + KPrintf("Netdev %s: ip: %s, mask: %s, gw: %s, dns: %s\n", + current_dev->name, + ip, netmask, gw, dns); + } + ENABLE_INTERRUPT(lock); + + return; +} +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(5), + netdev_list, netdev_list_dev, list sys netdev); \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_register.c b/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_register.c index 73ef0ed88..e6196feb6 100644 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_register.c +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_register.c @@ -38,7 +38,16 @@ Modification: struct netdev** get_netdev_listhead() { - static struct netdev* netdev_listhead = NULL; + static bool init = false; + static struct netdev* netdev_listhead; + if (!init) { + static struct netdev netdev_guard; + strncpy(netdev_guard.name, "guard\0", 6); + InitSingleLinkList(&(netdev_guard.list)); + netdev_listhead = &netdev_guard; + } + init = true; + return &netdev_listhead; } struct netdev** get_default_netdev() @@ -56,17 +65,13 @@ int netdev_register(struct netdev* netdev, const char* name, void* user_data) // set flag mask, assert network is down uint16_t flag_mask = 0; - flag_mask = NETDEV_FLAG_UP | NETDEV_FLAG_LINK_UP | NETDEV_FLAG_INTERNET_UP | NETDEV_FLAG_DHCP; + flag_mask = NETDEV_FLAG_UP | NETDEV_FLAG_LINK_UP | NETDEV_FLAG_INTERNET_UP; netdev->flags &= ~flag_mask; // clear dev setting - ip_addr_set_zero(&(netdev->ip_addr)); - ip_addr_set_zero(&(netdev->netmask)); - ip_addr_set_zero(&(netdev->gw)); - - IP_SET_TYPE_VAL(netdev->ip_addr, IPADDR_TYPE_V4); - IP_SET_TYPE_VAL(netdev->netmask, IPADDR_TYPE_V4); - IP_SET_TYPE_VAL(netdev->gw, IPADDR_TYPE_V4); + netdev->ip_addr = NULL; + netdev->netmask = NULL; + netdev->gw = NULL; #if NETDEV_IPV6 for (index = 0; index < NETDEV_IPV6_NUM_ADDRESSES; index++) { @@ -78,7 +83,6 @@ int netdev_register(struct netdev* netdev, const char* name, void* user_data) // clear DNS servers for (uint16_t idx = 0; idx < NETDEV_DNS_SERVERS_NUM; idx++) { ip_addr_set_zero(&(netdev->dns_servers[idx])); - IP_SET_TYPE_VAL(netdev->ip_addr, IPADDR_TYPE_V4); } // clear callback fn netdev->addr_callback = NULL; @@ -87,7 +91,8 @@ int netdev_register(struct netdev* netdev, const char* name, void* user_data) // validate name uint32_t name_len = strlen(name); if (name_len < NAME_NUM_MAX) { - strncpy(netdev->name, name, name_len); + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("Register Netdev %s, name len: %d.\n", name, name_len)); + strncpy(netdev->name, name, (name_len > 31 ? 31 : name_len)); netdev->name[name_len] = '\0'; } else { SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] name too long.\n", __func__)); @@ -103,6 +108,7 @@ int netdev_register(struct netdev* netdev, const char* name, void* user_data) x_base lock = DISABLE_INTERRUPT(); if (NETDEV_LISTHEAD == NULL) { NETDEV_LISTHEAD = netdev; + } else { SingleLinkListNodeInsert(&(NETDEV_LISTHEAD->list), &(netdev->list)); } @@ -110,7 +116,7 @@ int netdev_register(struct netdev* netdev, const char* name, void* user_data) if (NETDEV_DEFAULT == NULL) { // set first met netdev to default netdev - netdev_set_default(NETDEV_LISTHEAD); + netdev_set_default(netdev); } if (g_netdev_register_callback) { diff --git a/Ubiquitous/XiZi_IIoT/resources/include/netdev/netdev.h b/Ubiquitous/XiZi_IIoT/resources/include/netdev/netdev.h index e3007fd9e..468a1a68e 100644 --- a/Ubiquitous/XiZi_IIoT/resources/include/netdev/netdev.h +++ b/Ubiquitous/XiZi_IIoT/resources/include/netdev/netdev.h @@ -93,9 +93,9 @@ struct netdev { SysSingleLinklistType list; char name[NAME_NUM_MAX]; /* network interface device name */ - ip_addr_t ip_addr; /* IP address */ - ip_addr_t netmask; /* subnet mask */ - ip_addr_t gw; /* gateway */ + ip_addr_t* ip_addr; /* IP address */ + ip_addr_t* netmask; /* subnet mask */ + ip_addr_t* gw; /* gateway */ #if NETDEV_IPV6 ip_addr_t ip6_addr[NETDEV_IPV6_NUM_ADDRESSES]; /* array of IPv6 addresses */ #endif /* NETDEV_IPV6 */