From 5623b7861709e083b864fddd553a995e17efa2c3 Mon Sep 17 00:00:00 2001 From: zhangzheng <1358745329@qq.com> Date: Tue, 3 Oct 2023 15:51:31 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0modbus&=E4=BF=AE=E6=94=B9sysc?= =?UTF-8?q?all=E5=87=BD=E6=95=B0=E5=90=8D&=E4=BF=AE=E6=94=B9ns=E6=B3=A8?= =?UTF-8?q?=E5=86=8C=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 4 +- mkrtos_user/lib/CMakeLists.txt | 1 + mkrtos_user/lib/modbus/CMakeLists.txt | 49 + mkrtos_user/lib/modbus/inc/MD_RTU_Config.h | 39 + .../lib/modbus/inc/modbus_base/MD_RTU_CRC16.h | 29 + .../lib/modbus/inc/modbus_base/MD_RTU_Error.h | 28 + .../modbus/inc/modbus_base/MD_RTU_MapTable.h | 55 + .../lib/modbus/inc/modbus_base/MD_RTU_Queue.h | 51 + .../lib/modbus/inc/modbus_base/MD_RTU_Tool.h | 52 + .../lib/modbus/inc/modbus_base/MD_RTU_Type.h | 43 + .../inc/modbus_rtu_master/MDM_RTU_Fun.h | 246 +++ .../inc/modbus_rtu_master/MDM_RTU_RW_Man.h | 34 + .../inc/modbus_rtu_master/MDM_RTU_User_Fun.h | 10 + .../modbus/inc/modbus_rtu_slave/MDS_RTU_Fun.h | 136 ++ .../inc/modbus_rtu_slave/MDS_RTU_User_Fun.h | 41 + .../lib/modbus/inc/port/MD_RTU_SysInterface.h | 57 + .../lib/modbus/src/modbus_base/MD_RTU_CRC16.c | 85 + .../modbus/src/modbus_base/MD_RTU_MapTable.c | 61 + .../lib/modbus/src/modbus_base/MD_RTU_Queue.c | 224 +++ .../src/modbus_rtu_master/MDM_RTU_Fun.c | 1386 +++++++++++++++++ .../src/modbus_rtu_master/MDM_RTU_RW_Man.c | 158 ++ .../src/modbus_rtu_master/MDM_RTU_User_Fun.c | 103 ++ .../modbus/src/modbus_rtu_slave/MDS_RTU_Fun.c | 695 +++++++++ .../src/modbus_rtu_slave/MDS_RTU_User_Fun.c | 225 +++ .../lib/modbus/src/port/MD_RTU_SysInterface.c | 75 + mkrtos_user/lib/sys/inc/u_types.h | 20 + mkrtos_user/lib/sys/src/syscall.S | 8 +- mkrtos_user/lib/sys/src/u_factory.c | 8 +- mkrtos_user/lib/sys/src/u_ipc.c | 8 +- mkrtos_user/lib/sys/src/u_irq_sender.c | 6 +- mkrtos_user/lib/sys/src/u_log.c | 4 +- mkrtos_user/lib/sys/src/u_mm.c | 6 +- mkrtos_user/lib/sys/src/u_sys.c | 2 +- mkrtos_user/lib/sys/src/u_task.c | 8 +- mkrtos_user/lib/sys/src/u_thread.c | 10 +- mkrtos_user/lib/sys_svr/inc/ns_types.h | 8 +- mkrtos_user/lib/sys_svr/src/fs_cli.c | 49 +- mkrtos_user/lib/sys_svr/src/ns_cli.c | 23 +- mkrtos_user/lib/sys_util/inc/u_rpc.h | 4 +- mkrtos_user/lib/sys_util/src/u_app_loader.c | 8 +- mkrtos_user/server/app/CMakeLists.txt | 11 + mkrtos_user/server/app/drv/drv.c | 12 +- mkrtos_user/server/app/modbus/MDM_RTU_APP.c | 229 +++ mkrtos_user/server/app/modbus/MDM_RTU_APP.h | 8 + .../server/app/modbus/MDM_RTU_Serial.c | 124 ++ .../server/app/modbus/MDM_RTU_Serial.h | 30 + mkrtos_user/server/fs/fatfs/main.c | 3 +- mkrtos_user/server/hello/src/main.c | 6 +- mkrtos_user/server/init/src/main.c | 2 - mkrtos_user/server/init/src/namespace.c | 5 +- 50 files changed, 4400 insertions(+), 89 deletions(-) create mode 100644 mkrtos_user/lib/modbus/CMakeLists.txt create mode 100644 mkrtos_user/lib/modbus/inc/MD_RTU_Config.h create mode 100644 mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_CRC16.h create mode 100644 mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_Error.h create mode 100644 mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_MapTable.h create mode 100644 mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_Queue.h create mode 100644 mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_Tool.h create mode 100644 mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_Type.h create mode 100644 mkrtos_user/lib/modbus/inc/modbus_rtu_master/MDM_RTU_Fun.h create mode 100644 mkrtos_user/lib/modbus/inc/modbus_rtu_master/MDM_RTU_RW_Man.h create mode 100644 mkrtos_user/lib/modbus/inc/modbus_rtu_master/MDM_RTU_User_Fun.h create mode 100644 mkrtos_user/lib/modbus/inc/modbus_rtu_slave/MDS_RTU_Fun.h create mode 100644 mkrtos_user/lib/modbus/inc/modbus_rtu_slave/MDS_RTU_User_Fun.h create mode 100644 mkrtos_user/lib/modbus/inc/port/MD_RTU_SysInterface.h create mode 100644 mkrtos_user/lib/modbus/src/modbus_base/MD_RTU_CRC16.c create mode 100644 mkrtos_user/lib/modbus/src/modbus_base/MD_RTU_MapTable.c create mode 100644 mkrtos_user/lib/modbus/src/modbus_base/MD_RTU_Queue.c create mode 100644 mkrtos_user/lib/modbus/src/modbus_rtu_master/MDM_RTU_Fun.c create mode 100644 mkrtos_user/lib/modbus/src/modbus_rtu_master/MDM_RTU_RW_Man.c create mode 100644 mkrtos_user/lib/modbus/src/modbus_rtu_master/MDM_RTU_User_Fun.c create mode 100644 mkrtos_user/lib/modbus/src/modbus_rtu_slave/MDS_RTU_Fun.c create mode 100644 mkrtos_user/lib/modbus/src/modbus_rtu_slave/MDS_RTU_User_Fun.c create mode 100644 mkrtos_user/lib/modbus/src/port/MD_RTU_SysInterface.c create mode 100644 mkrtos_user/server/app/modbus/MDM_RTU_APP.c create mode 100644 mkrtos_user/server/app/modbus/MDM_RTU_APP.h create mode 100644 mkrtos_user/server/app/modbus/MDM_RTU_Serial.c create mode 100644 mkrtos_user/server/app/modbus/MDM_RTU_Serial.h diff --git a/.vscode/settings.json b/.vscode/settings.json index a0047cb00..d27cf1970 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -186,7 +186,9 @@ "spi2.h": "c", "wk2xx.h": "c", "cwchar": "c", - "test.h": "c" + "test.h": "c", + "uart5.h": "c", + "wk2xx_hw.h": "c" }, "cortex-debug.showRTOS": false, "cortex-debug.variableUseNaturalFormat": true, diff --git a/mkrtos_user/lib/CMakeLists.txt b/mkrtos_user/lib/CMakeLists.txt index eb920e4a0..58611ac2b 100644 --- a/mkrtos_user/lib/CMakeLists.txt +++ b/mkrtos_user/lib/CMakeLists.txt @@ -9,6 +9,7 @@ set(CMAKE_ASM_FLAGS ${CMAKE_C_FLAGS}) add_subdirectory(sys) add_subdirectory(sys_util) add_subdirectory(sys_svr) +add_subdirectory(modbus) add_subdirectory(stm32f1_bsp) add_subdirectory(libc_backend) add_subdirectory(mlibc) diff --git a/mkrtos_user/lib/modbus/CMakeLists.txt b/mkrtos_user/lib/modbus/CMakeLists.txt new file mode 100644 index 000000000..f1fd5f7fe --- /dev/null +++ b/mkrtos_user/lib/modbus/CMakeLists.txt @@ -0,0 +1,49 @@ +cmake_minimum_required(VERSION 3.13) + + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} \ +-fPIC -n -pie -fpie -fpic -msingle-pic-base -mno-pic-data-is-text-relative \ +-Wl,--gc-sections -D__dietlibc__ -D__arm__ -D__WORDSIZE=32 -D__ARM_ARCH_7M__ \ +" ) +set(CMAKE_ASM_FLAGS ${CMAKE_C_FLAGS}) + + +file(GLOB_RECURSE deps *.c *.S) +add_library( + xtinymodbus + STATIC + ${deps} +) +target_include_directories( + xtinymodbus + PUBLIC + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/modbus/inc/modbus_base + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/modbus/inc/modbus_rtu_master + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/modbus/inc/modbus_rtu_slave + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/modbus/inc/port + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/modbus/inc/serial + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/modbus/inc + + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/sys/inc + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/sys_util/inc + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/cpio + + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/mlibc/arch/arm/ + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/mlibc/arch/generic + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/mlibc/obj/src/internal + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/mlibc/src/include + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/mlibc/src/internal + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/mlibc/obj/include + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/mlibc/include +) +target_link_libraries( + xtinymodbus + PUBLIC + sys + sys_util + muslc +) +add_dependencies(xtinymodbus sys) +add_dependencies(xtinymodbus muslc) + + diff --git a/mkrtos_user/lib/modbus/inc/MD_RTU_Config.h b/mkrtos_user/lib/modbus/inc/MD_RTU_Config.h new file mode 100644 index 000000000..c87fa846b --- /dev/null +++ b/mkrtos_user/lib/modbus/inc/MD_RTU_Config.h @@ -0,0 +1,39 @@ +/** + *@brief Modbus configuration file. + *@file MD_RTU_Config.h + *@author zspace + */ +#ifndef _MD_RTU_CONFIG_H__ +#define _MD_RTU_CONFIG_H__ + +#define MD_RTU_USED_OS 0 ///< Whether modbus RTU USES an operating system + +#define MD_RTU_CRC16_FAST_MODE 1 ///< CRC check mode configuration + +///< Configuration related to the slave +#define MDS_REG_COIL_ITEM_NUM 20 ///< Maximum number of discrete maps +#define MDS_RTU_CMD_SIZE 256 ///< Single instruction length +#define MDS_RTU_SEND_CACHE_SIZE 256 ///< Send buffer length +#define MDS_USE_SEND_CACHE 1 ///< Whether to enable sending cache +#define MDS_RTU_QUEUE_SIZE 256 ///< Buffer queue size + +///< Host related configuration +#define MDM_REG_COIL_ITEM_NUM 20 ///< Maximum number of discrete maps +#define MDM_RTU_SEND_CACHE_SIZE 256 ///< Send buffer length +#define MDM_USE_SEND_CACHE 1 ///< Whether to enable sending cache +#define MDM_RTU_QUEUE_SIZE 256 ///< Buffer queue size + +#define MDM_MIX_CALL_DELAY 500 ///< The delay time before the mix call + +///< Configuration related to blocking read-write controller +#define MDM_RW_CTRL_LIST_SIZE 20 ///< Maximum number of controllers + +#define MDS_USE_IDENTICAL_MAPPING 1 ///< Different slaves use the same mapping source + +#ifdef MDS_USE_IDENTICAL_MAPPING +#define STATIC_T static +#else +#define STATIC_T +#endif + +#endif diff --git a/mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_CRC16.h b/mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_CRC16.h new file mode 100644 index 000000000..bc64d3bc6 --- /dev/null +++ b/mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_CRC16.h @@ -0,0 +1,29 @@ +/**@file MD_RTU_CRC16.h +* @brief Modbus RTU CRC16 Check module +* @author zspace +* @date 2020-4-10 +* @version V1.0 +********************************************************************************** +* @par Open source address +* https://github.com/lotoohe-space/XTinyModbus +* @par modify log: +* +*
Date Version Author Description +*
2020-4-10 1.0 zspace First version +*
+* +********************************************************************************** +*/ +#ifndef _MD_RTU_CRC16_H__ +#define _MD_RTU_CRC16_H__ + +/*********************************HEAD FILE************************************/ +#include "MD_RTU_Type.h" +#include "MD_RTU_Config.h" +/*********************************END******************************************/ + +/*********************************Function declaration************************/ +//uint16 MD_CRC16Update(uint16 CRC, uint8 byte); +/*********************************END******************************************/ + +#endif diff --git a/mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_Error.h b/mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_Error.h new file mode 100644 index 000000000..762cf4a4d --- /dev/null +++ b/mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_Error.h @@ -0,0 +1,28 @@ +#ifndef _MDM_RTU_ERROR_H__ +#define _MDM_RTU_ERROR_H__ + +typedef enum{ + ERR_VOID=0, /*Null pointer error*/ + ERR_NONE=1, /*No error*/ + ERR_CTE_OBJ, /*Object creation error*/ + ERR_IDLE, /*The block is currently free*/ + ERR_QUEUE, /*Queue write error*/ + ERR_OVER_TIME, /*Timeout error*/ + ERR_SEND_FIN, /*Send complete*/ + ERR_RW_OV_TIME_ERR, /*Send timeout error*/ + ERR_DEV_DIS, /*Device disconnection*/ + ERR_SLAVE_ADDR, /*The slave address does not match*/ + ERR_DATA_LEN, /*Data length error*/ + ERR_DATA_SAVE, /*Data saving error*/ + + /*The following error is returned from the slave machine.*/ + ERR_READ_COIL, /*Read coil error*/ + ERR_READ_INPUT, /*Read input error*/ + ERR_READ_HOLD_REG, /*Read holding register error*/ + ERR_READ_INPUT_REG, /*Error reading input register*/ + ERR_WRITE_COIL, /*Write coil error*/ + ERR_WRITE_REG, /*Write register error*/ + ERR_RW_FIN, /*The slave receives and the master receives the correct response*/ +}MDError; + +#endif diff --git a/mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_MapTable.h b/mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_MapTable.h new file mode 100644 index 000000000..fce64eca3 --- /dev/null +++ b/mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_MapTable.h @@ -0,0 +1,55 @@ +/**@file MD_RTU_MapTable.h +* @brief Modbus RTU Discrete mapping management module +* @author zspace +* @date 2020-4-10 +* @version V1.0 +********************************************************************************** +* @par Open source address +* https://github.com/lotoohe-space/XTinyModbus +* @par modify log: +* +*
Date Version Author Description +*
2020-4-10 1.0 zspace First version +*
+* +********************************************************************************** +*/ + +#ifndef _MD_RTU_REGCOIL_H__ +#define _MD_RTU_REGCOIL_H__ + +/*********************************HEAD FILE************************************/ +#include "MD_RTU_Type.h" +/*********************************END******************************************/ + +/*********************************CUSTOM DATA TYPE************************************/ + +/**@enum AddrType +* @brief Modbus RTU types +*/ +typedef enum{ + COILS_TYPE=1, ///< coil type + INPUT_TYPE=2, ///< input type + HOLD_REGS_TYPE=3, ///< hold reg type + INPUT_REGS_TYPE=4 ///< input reg type +}AddrType; + +/**@struct MapTableItem +* @brief Discrete mapping structure \n +* Map modbus addresses to memory addresses +*/ +typedef struct{ + uint16 modbusAddr; ///< Modbus address + uint16* modbusData; ///< Stored data + uint16 modbusDataSize; ///< Map size + AddrType addrType; ///< Address type,Reference @see :: AddrType + uint8 devAddr; ///< Indicate which device the mapping item belongs to. For the time being, only the master uses this variable and the slave ignores it +}*PMapTableItem,MapTableItem; +/*********************************END******************************************/ + +/*********************************FUNCTION DECLARATION************************************/ +uint8 MapTableAdd(void* obj,PMapTableItem pMapTableItem,uint16 tabSize); +uint8 MapTableDel(void* obj,PMapTableItem pMapTableItem,uint16 tabSize); +/*********************************END******************************************/ + +#endif diff --git a/mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_Queue.h b/mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_Queue.h new file mode 100644 index 000000000..0cd98c0ef --- /dev/null +++ b/mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_Queue.h @@ -0,0 +1,51 @@ +/******************************************************************************** +* @File name: MD_RTU_Queue.c +* @Author: zspace +* @Emial: 1358745329@qq.com +* @Version: 1.0 +* @Date: 2020-4-10 +* @Description: Modbus RTU Queue function module +********************************************************************************/ +#ifndef _SQQUEUE_H__ +#define _SQQUEUE_H__ + +/*********************************HEAD FILE************************************/ +#include "MD_RTU_Type.h" +#include "MD_RTU_Config.h" +/*********************************END******************************************/ + +/*********************************TYPE DEFINITION**************************************/ +//typedef uint8 MDQueueDateType; +typedef void MDQueueDataType; +typedef struct { + //MDQueueDateType data[MD_RTU_QUEUE_SIZE+1]; + MDQueueDataType *data; + uint16 maxVal; + int16 front, rear; + uint8 valid; +}*PMDSqQueue, MDSqQueue; +/*********************************END******************************************/ + +/*user used data type.*/ +typedef enum{ + CHAR_TYPE=0, + UINT8_TYPE, + SHORT_TYPE, + INT_TYPE, + FLOAT_TYPE +}*PSqQueueType,SqQueueType; + +/*********************************FUNCTION DECLARATION**************************************/ +uint8 MDInitQueue(MDSqQueue *q,MDQueueDataType* data,uint16 maxVal); +uint16 MDQueueLength(MDSqQueue* q); +void MDResetQueue(MDSqQueue* q); +uint8 MDQueueEmpty(MDSqQueue* q); +uint8 MDenQueueH(MDSqQueue* q, MDQueueDataType *e,SqQueueType type); +uint8 MDenQueue(MDSqQueue* q, MDQueueDataType *e,SqQueueType type); +uint8 MDdeQueue(MDSqQueue* q, MDQueueDataType *e,SqQueueType type); +uint8 MDdeQueueF(MDSqQueue* q, MDQueueDataType *e,SqQueueType type); +uint8 MDgetTailQueue(MDSqQueue* q, MDQueueDataType* e,SqQueueType type); +/*********************************END******************************************/ + +#endif + diff --git a/mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_Tool.h b/mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_Tool.h new file mode 100644 index 000000000..df210c805 --- /dev/null +++ b/mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_Tool.h @@ -0,0 +1,52 @@ +#ifndef _MD_RTU_TOOL_H__ +#define _MD_RTU_TOOL_H__ + +#include "MD_RTU_Type.h" + +typedef void (*MDS_RTU_TimeHandlerFunction)(void* obj + ,uint32 times + ); +typedef void (*MDS_RTU_SendBytesFunction)(uint8 *byte,uint16 num); +typedef void (*MDS_RTU_RecByteFunction)(void* obj, uint8 byte); +typedef void (*MDS_RTU_RecSendConv)(uint8 mode); + +typedef void (*MD_RTU_SerialInit)(void* obj,uint32 baud,uint8 dataBits,uint8 stopBit,uint8 parity); + +typedef struct{ + /*Data sending and receiving related functions*/ + MDS_RTU_SendBytesFunction mdRTUSendBytesFunction; + MDS_RTU_RecByteFunction mdRTURecByteFunction; + MDS_RTU_RecSendConv mdRTURecSendConv; + /*Timer callback function*/ + MDS_RTU_TimeHandlerFunction mdRTUTimeHandlerFunction; +}*PModbusBase,ModbusBase; + +/*Convert to ModbusBase*/ +#define TO_MDBase(a) ((PModbusBase)(a)) + +/*Get the variables in RegCoilItem*/ +#define MDS_RTU_REG_COIL_LIST(a) ((a)->pRegCoilList) +#define MDS_RTU_REG_COIL_ITEM_ADDR(a) ((a)->modbusAddr) +#define MDS_RTU_REG_COIL_ITEM_DATA(a) ((a)->modbusData) +#define MDS_RTU_REG_COIL_ITEM_Data_Size(a) ((a)->modbusDataSize) +#define MDS_RTU_REG_COIL_ITEM_ADDR_TYPE(a) ((a)->addrType) + +/*The following macros are used to manipulate the bits of variables*/ +#define MD_GET_BIT(a,b) (((a)>>(b))&0x1) +#define MD_SET_BIT(a,b) (a)|=(1<<(b)) +#define MD_CLR_BIT(a,b) (a)&=(~(1<<(b))) + +/*Transceiver mode conversion*/ +#define MD_RTU_SEND_MODE(a) while((a)->lastTimesTick!=0xFFFFFFFF);\ +if((a)->modbusBase.mdRTURecSendConv)(a)->modbusBase.mdRTURecSendConv(TRUE) +#define MD_RTU_RECV_MODE(a) while((a)->lastTimesTick!=0xFFFFFFFF);\ +if((a)->modbusBase.mdRTURecSendConv)(a)->modbusBase.mdRTURecSendConv(FALSE) + +/*Swap the high and low bytes of a halfword*/ +#define MD_SWAP_HL(a) (a)=((((a)&0xff)<<8)|(((a)>>8)&0xff)) + +/*Take high and low byte*/ +#define MD_H_BYTE(a) (((a)>>8)&0xff) +#define MD_L_BYTE(a) ((a)&0xff) + +#endif diff --git a/mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_Type.h b/mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_Type.h new file mode 100644 index 000000000..6d49e1d6d --- /dev/null +++ b/mkrtos_user/lib/modbus/inc/modbus_base/MD_RTU_Type.h @@ -0,0 +1,43 @@ +/** + * @file MD_RTU_Type.h + * @brief None + * @details None + * @author zspace + * @date 2020/3/23 + * @version A001 + * @par History: None + */ +#ifndef _MD_RTU_TYPE_H__ +#define _MD_RTU_TYPE_H__ + +#include "MD_RTU_Config.h" + +#if MD_RTU_USED_OS +#include "RTOS_Type.h" +#else +typedef unsigned char uchar; +typedef unsigned char uint8; +typedef char int8; +typedef unsigned int uint32; +typedef int int32; +typedef unsigned short uint16; +typedef short int16; + +typedef uint8 BOOL; + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#define BOOL uint8 +#endif + +#endif diff --git a/mkrtos_user/lib/modbus/inc/modbus_rtu_master/MDM_RTU_Fun.h b/mkrtos_user/lib/modbus/inc/modbus_rtu_master/MDM_RTU_Fun.h new file mode 100644 index 000000000..b78dfc196 --- /dev/null +++ b/mkrtos_user/lib/modbus/inc/modbus_rtu_master/MDM_RTU_Fun.h @@ -0,0 +1,246 @@ +/******************************************************************************** +* @File name: MD_RTU_Fun.h +* @Author: zspace +* @Emial: 1358745329@qq.com +* @Version: 1.0 +* @Date: 2020-4-10 +* @Description: Modbus RTU Host function module +********************************************************************************/ + +#ifndef _MEM_RTU_FUN_H__ +#define _MEM_RTU_FUN_H__ +/*********************************HEAD FILE************************************/ +#include "MD_RTU_Queue.h" +#include "MD_RTU_Type.h" +#include "MD_RTU_Error.h" +#include "MD_RTU_Tool.h" +#include "MD_RTU_MapTable.h" +#include "MD_RTU_Config.h" +#include "MD_RTU_SysInterface.h" + +/*********************************END******************************************/ + +/*********************************CUSTOM DATA TYPE************************************/ +/*Function code in Modbus RTU*/ +typedef enum{ + READ_COIL=1, + READ_INPUT=2, + READ_HOLD_REG=3, + READ_INPUT_REG=4, + WRITE_SIN_COIL=5, + WRITE_SIN_REG=6, + WRITE_COILS=15, + WRITE_REGS=16 +}ModbusFunCode; + +typedef struct{ + /*Inherit modbusBase*/ + ModbusBase modbusBase; + /*Discrete mapping list, the data read is stored in it*/ + PMapTableItem pMapTableList[MDM_REG_COIL_ITEM_NUM]; + /*Data receiving queue*/ + MDSqQueue mdSqQueue; +#if MD_RTU_USED_OS + /**/ + MD_RTU_LOCK_HANDLE mdRTULockHandle; + MD_RTU_LOCK_HANDLE mdRTULockObjHandle; + MD_RTU_LOCK_HANDLE mdRTULockObj1Handle; + MD_RTU_TASK_HANDLE mdRTUTaskHandle; + MD_RTU_MSG_HANDLE mdRTUMsgHandle; +#endif +#if MDM_USE_SEND_CACHE + uint8 serialSendCache[MDM_RTU_SEND_CACHE_SIZE]; /*Send cache*/ + uint16 serialSendCount; /*Number of bytes sent*/ +#endif + + /*The time of the last reception, 0xFFFFFFF means that the detection frame has not started*/ + uint32 lastTimesTick; + /*Current real-time time unit 100US*/ + uint32 timesTick; + + /*Frame interval time 3.5T*/ + uint16 frameIntervalTime; + + /*CRC16 received*/ + uint16 CRC16Update; + + /*Parent class address, used to distinguish time slice occupation during non-blocking read*/ + void * parentObj; + + /*1 means one frame of data is received*/ + uint8 recvFlag; + + /*last mode*/ + uint8 blockMode; +}*PModbus_RTU,Modbus_RTU; + +#if MD_RTU_USED_OS +#define MD_RTU_LOCK_HANDLE_ARG(a) (a)->mdRTULockHandle +#define MD_RTU_LOCK_OBJ_HANDLE_ARG(a) (a)->mdRTULockObjHandle +#define MD_RTU_LOCK_OBJ1_HANDLE_ARG(a) (a)->mdRTULockObj1Handle +#define MD_RTU_TASK_HANDLE_ARG(a) (a)->mdRTUTaskHandle +#define MD_RTU_MSG_HANDLE_ARG(a) (a)->mdRTUMsgHandle +#else +#define MD_RTU_LOCK_HANDLE_ARG(a) +#define MD_RTU_LOCK_OBJ_HANDLE_ARG(a) +#define MD_RTU_LOCK_OBJ1_HANDLE_ARG(a) +//#define MD_RTU_SEM_HANDLE_ARG(a) +#define MD_RTU_MSG_HANDLE_ARG(a) +#endif + +/*Send control block*/ +typedef struct{ + PModbus_RTU pModbus_RTU;/*modbus rtu*/ + + uint32 sendIntervalTime;/*The sending interval, that is, sending once for a long time.*/ + + uint32 sendTimeTick;/*Time when sending*/ + uint8 RTCount;/*Number of retransmissions*/ + + uint32 sendOverTime;/*Set sending timeout time*/ + + uint8 RTTimes;/*The set number of retransmissions. When it is 255, it means that retransmissions will continue.*/ + uint8 sendFlag;/*Send flag + 0 Unsent + 1 Already sent + 2 Sent successfully + 3 Failed to send + */ + uint8 flag; /* + bit0:Device offline polling flag (when flag is 1, the control block will not be polled when the device is offline). + bit1:Device offline polling enable + */ +}*PModbus_RTU_CB,Modbus_RTU_CB; + +/*Get device offline flag*/ +#define MD_CB_GET_DIS_FLAG(a) MD_GET_BIT(a->flag,0) +#define MD_CB_SET_DIS_FLAG(a) MD_SET_BIT(a->flag,0) +#define MD_CB_CLR_DIS_FLAG(a) MD_CLR_BIT(a->flag,0) + +/*Device enable flag*/ +#define MD_CB_GET_DIS_FLAG_EN(a) MD_GET_BIT(a->flag,1) +#define MD_CB_SET_DIS_FLAG_EN(a) MD_SET_BIT(a->flag,1) +#define MD_CB_CLR_DIS_FLAG_EN(a) MD_CLR_BIT(a->flag,1) + + + + +/*********************************END******************************************/ + +/*********************************MACRO DEFINITION************************************/ +#if MDM_USE_SEND_CACHE + +#define MEM_RTU_START_EN(a) {uint16 CRCUpdate1=0xFFFF;(a)->serialSendCount=0 + +#define MEM_RTU_EN_QUEUE(a,b) (a)->serialSendCache[(a)->serialSendCount++]=(b);\ +CRCUpdate1=MD_CRC16Update(CRCUpdate1,(b)) + +#define MEM_RTU_END_EN(a) a->serialSendCache[a->serialSendCount++]=(uint8)(CRCUpdate1);\ + a->serialSendCache[a->serialSendCount++]=(uint8)(CRCUpdate1>>8);\ +(TO_MDBase(a))->mdRTUSendBytesFunction(a->serialSendCache,a->serialSendCount);} + +#else +#define MEM_RTU_START_EN() {uint16 CRCUpdate=0xFFFF; +#define MEM_RTU_EN_QUEUE(a,b) MDM_RTU_SendByte((a),(b));\ +CRCUpdate=MD_CRC16Update(CRCUpdate,(b)) +#define MEM_RTU_END_EN(a) MDM_RTU_SendByte(a,(uint8)CRCUpdate);\ + MDM_RTU_SendByte(a,(uint8)(CRCUpdate>>8));\ +} +#endif +/*********************************END******************************************/ + +/*********************************FUNCTION DEFINITION************************************/ + +#if MD_RTU_USED_OS ///< used os +void MDM_RTU_SysProcessTask(void *arg); +#endif + +/*Modbus RTU block initialization function*/ +MDError MDM_RTU_Init( + PModbus_RTU pModbusRTU, + MD_RTU_SerialInit mdRTUSerialInitFun, + uint32 baud, + uint8 dataBits, + uint8 stopBits, + uint8 parity +); +/*Control block initialization function*/ +void MDM_RTU_CB_Init( + PModbus_RTU_CB pModbusRTUCB + ,PModbus_RTU pModbusRTU + ,uint32 sendIntervalTime + ,uint32 sendOverTime/*Send timeout*/ + ,uint8 RTTimes/*The number of retransmissions, when it is 255, it means that retransmissions have been performed.*/ +); +void MDM_RTU_QueueInit(PModbus_RTU pModbus_RTU, + uint8* recvQueueData, + uint16 recvQueueSize +); + +/*Called in the timer interrupt function, the time unit is 100us*/ +void MDM_RTU_TimeHandler(void *obj,uint32 timesTick); +/*Called in the serial port receive interrupt function*/ +void MDM_RTU_RecvByte(void *obj,uint8 byte); + +/*Control block timeout reset*/ +void MDM_RTU_CB_OverTimeReset(PModbus_RTU_CB pModbusRTUCB); +void MDM_RTU_CB_ClrDisFlag(PModbus_RTU_CB pModbusRTUCB); +void MDM_RTU_CB_SetDisPollEnFlag(PModbus_RTU_CB pModbusRTUCB,BOOL state); + +BOOL MDM_RTU_AddMapItem(PModbus_RTU pModbusRTU,PMapTableItem pRegCoilItem); + +/*Get data from the queue*/ +MDError MDM_RTU_ReadByte(PModbus_RTU pModbusRTU,uint8 *res,uint8 len); +MDError MDM_RTU_ReadUint16(PModbus_RTU pModbusRTU,uint16 *res,uint8 len); + +///*Non-blocking read and write basis functions*/ +//MDError MDM_RTU_NB_RW(PModbus_RTU_CB pModbus_RTU_CB,ModbusFunCode funCode,uint8 slaveAddr,uint16 startAddr,uint16 numOf,void *wData); +///*Blocking read and write basis functions*/ +//MDError MDM_RTU_RW(PModbus_RTU_CB pModbus_RTU_CB,ModbusFunCode funCode,uint8 slaveAddr,uint16 startAddr,uint16 numOf,void *wData); + +/*The following is non-blocking read and write*/ +MDError MDM_RTU_NB_ReadCoil(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf); +MDError MDM_RTU_NB_ReadInput(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf); +MDError MDM_RTU_NB_ReadHoldReg(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf); +MDError MDM_RTU_NB_ReadInputReg(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf); +MDError MDM_RTU_NB_WriteSingleCoil( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,BOOL boolVal); +MDError MDM_RTU_NB_WriteSingleReg( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 val); +MDError MDM_RTU_NB_WriteCoils( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf,uint8* val); +MDError MDM_RTU_NB_WriteRegs( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf,uint16* val); + +/*The following is a blocking read and write*/ +MDError MDM_RTU_ReadCoil(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf); +MDError MDM_RTU_ReadInput(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf); +MDError MDM_RTU_ReadHoldReg(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf); +MDError MDM_RTU_ReadInputReg(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf); +MDError MDM_RTU_WriteSingleCoil( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,BOOL boolVal); +MDError MDM_RTU_WriteSingleReg( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 val); +MDError MDM_RTU_WriteCoils( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf,uint8* val); +MDError MDM_RTU_WriteRegs( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf,uint16* val); + +/*The following API is used to be blocking, but can be mixed with non-blocking calls, +you may need to set the value of the MDM_MIX_CALL_DELAY parameter.*/ +MDError MDM_RTU_MixReadCoil(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf); +MDError MDM_RTU_MixReadInput(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf); +MDError MDM_RTU_MixReadHoldReg(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf); +MDError MDM_RTU_MixReadInputReg(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf); +MDError MDM_RTU_MixWriteSingleCoil( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,BOOL boolVal); +MDError MDM_RTU_MixWriteSingleReg( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 val); +MDError MDM_RTU_MixWriteCoils( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf,uint8* val); +MDError MDM_RTU_MixWriteRegs( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf,uint16* val); + +/*********************************END******************************************/ + +#endif diff --git a/mkrtos_user/lib/modbus/inc/modbus_rtu_master/MDM_RTU_RW_Man.h b/mkrtos_user/lib/modbus/inc/modbus_rtu_master/MDM_RTU_RW_Man.h new file mode 100644 index 000000000..b4bea8d86 --- /dev/null +++ b/mkrtos_user/lib/modbus/inc/modbus_rtu_master/MDM_RTU_RW_Man.h @@ -0,0 +1,34 @@ +#ifndef _MDM_RTU_RW_MAN_H__ +#define _MDM_RTU_RW_MAN_H__ + +#include "MD_RTU_Type.h" +#include "MD_RTU_Config.h" + +typedef enum{ + RW_NONE=0, + RW_ERR, + RW_OK +}MDM_RW_CtrlErr; + +typedef MDM_RW_CtrlErr (*MDMSendReadCallBack)(void*arg); + +/*Host's non-blocking mode sending controller*/ +typedef struct{ + + MDMSendReadCallBack MDMSendReadFun; /*Read and write functions called cyclically*/ + void *arg; /*parameter*/ + const char *RWCtrlName; /*Send control name*/ + uint8 flag; /*Flag + bit:0 Is it used + bit:1 Single send + bit:7 The slave is disconnected or a single transmission is completed. + */ +}*PMDM_RW_Ctrl,MDM_RW_Ctrl; + +PMDM_RW_Ctrl MDM_RW_CtrlAddRW(MDMSendReadCallBack cbFun,void *arg,const char *RWCtrlName); +void MDM_RW_CtrlSetRWOnceFlag(PMDM_RW_Ctrl pMDM_RW_Ctrl,BOOL flag); +void MDM_RW_CtrlResetRetranFlag(PMDM_RW_Ctrl pMDM_RW_Ctrl); +void MDM_RW_CtrlSetRWOnceFlag(PMDM_RW_Ctrl pMDM_RW_Ctrl,BOOL flag); +void MDM_RW_CtrlLoop(void); + +#endif diff --git a/mkrtos_user/lib/modbus/inc/modbus_rtu_master/MDM_RTU_User_Fun.h b/mkrtos_user/lib/modbus/inc/modbus_rtu_master/MDM_RTU_User_Fun.h new file mode 100644 index 000000000..d99f0e054 --- /dev/null +++ b/mkrtos_user/lib/modbus/inc/modbus_rtu_master/MDM_RTU_User_Fun.h @@ -0,0 +1,10 @@ +#ifndef _MDM_RTU_USER_FUN_H_ +#define _MDM_RTU_USER_FUN_H_ + +#include "MD_RTU_Type.h" +#include "MD_RTU_MapTable.h" + +BOOL MDM_RTU_ReadBits(void* obj,uint16 modbusAddr,uint16 numOf, uint8 *res, AddrType opAddrType,uint8 devAddr); +BOOL MDM_RTU_ReadRegs(void* obj,uint16 modbusAddr,uint16 numOf, uint16 *res, AddrType opAddrType,uint8 devAddr); + +#endif diff --git a/mkrtos_user/lib/modbus/inc/modbus_rtu_slave/MDS_RTU_Fun.h b/mkrtos_user/lib/modbus/inc/modbus_rtu_slave/MDS_RTU_Fun.h new file mode 100644 index 000000000..e69faba13 --- /dev/null +++ b/mkrtos_user/lib/modbus/inc/modbus_rtu_slave/MDS_RTU_Fun.h @@ -0,0 +1,136 @@ +/** + * @file name: MD_RTU_Fun.h + * @author zspace + * @version 1.0 + * @date 2020-4-10 + * @brief MModbus RTU Slave receiving function module. + */ + +#ifndef _MD_RTU_FUN_H__ +#define _MD_RTU_FUN_H__ +/*********************************HEAD FILE************************************/ +#include "MD_RTU_Queue.h" +#include "MD_RTU_MapTable.h" +#include "MD_RTU_Type.h" +#include "MD_RTU_Tool.h" +#include "MD_RTU_Config.h" +/*********************************END******************************************/ + +/*********************************VARIABLE TYPE DECLARATION***********************************/ +typedef void (*MDSWriteFunciton)(void *obj, uint16 modbusAddr, uint16 wLen, AddrType addrType); + +typedef struct +{ + ModbusBase modbusBase; /*Inherit modbusBase*/ + MDSWriteFunciton mdsWriteFun; /*Slave write callback function*/ + MDSqQueue mdSqQueue; /*Data receiving queue*/ + MDSqQueue mdMsgSqQueue; /*Message processing queue*/ + uint8 salveAddr; /*Slave address*/ + + uint8 serialReadCache[MDS_RTU_CMD_SIZE]; /*Single instruction read queue*/ + uint16 serialReadCount; /*Instruction length*/ +#if MDS_USE_SEND_CACHE + uint8 serialSendCache[MDS_RTU_SEND_CACHE_SIZE]; /*Send buffer*/ + uint16 serialSendCount; /*Number of bytes sent*/ +#endif + PMapTableItem pMapTableList[MDS_REG_COIL_ITEM_NUM]; /*Register registry*/ + + /*The time of the last reception, 0xFFFFFFFF means that the detection frame has not started*/ + uint32 lastTimesTick; + /*Current real-time time unit 100US*/ + uint32 timesTick; + + /*Last sent time*/ + uint32 lastSendTimes; + + /*Frame interval time 3.5T*/ + uint16 frameIntervalTime; + + /*CRC16 received*/ + uint16 CRC16Update; + +} *PModbusS_RTU, ModbusS_RTU; + +/*Exception code*/ +typedef enum +{ + READ_COIL_ANL = 0x81, + READ_INPUT_ANL = 0x82, + READ_HOLD_REGS = 0x83, + READ_INPUT_REGS = 0X84, + WRITE_SIN_COIL = 0X85, + WRITE_SIN_REG = 0x86, + WRITE_COILS = 0X8F, + WRITE_REGS = 0X90 +} ANLCode; + +/*error code*/ +typedef enum +{ + ILLEGAL_FUN = 0x01, /*Not yet supported*/ + ILLEGAL_DAT_ADDR = 0x2, + ILLEGAL_DAT_VAL = 0x3, + SLAVE_DEV_FAILURE = 0x4, /*Not yet supported*/ + /*There is an error code behind, but it is not used yet*/ +} ErrorCode; +/*********************************END******************************************/ + +/*********************************MACRO DEFINITION****************************************/ +#define MDS_RTU_FUN_CODE(a) (((PModbusS_RTU)(a))->serialReadCache[1]) +#define MDS_RTU_CRC16(a) (((((PModbusS_RTU)(a))->serialReadCache[a->serialReadCount - 1]) << 8) | \ + (((PModbusS_RTU)(a))->serialReadCache[a->serialReadCount])) + +#define MDS_RTU_START_REG(a) (((((PModbusS_RTU)(a))->serialReadCache[2]) << 8) | \ + (((PModbusS_RTU)(a))->serialReadCache[3])) +#define MDS_RTU_REGS_NUM(a) (((((PModbusS_RTU)(a))->serialReadCache[4]) << 8) | \ + (((PModbusS_RTU)(a))->serialReadCache[5])) +#define MDS_RTU_BYTES_NUM(a) ((a)->serialReadCache[6]) + +#if MDS_USE_SEND_CACHE +/*Start sending*/ +#define MDS_START_SEND(a) \ + { \ + uint16 CRC16 = 0xFFFF; \ + a->serialSendCount = 0 +/*Send a byte*/ +#define MDS_SEND_BYTE(a, b) \ + CRC16 = MD_CRC16Update(CRC16, (b)); \ + a->serialSendCache[a->serialSendCount++] = b +/*End sending*/ +#define MDS_SEND_END(a) \ + a->serialSendCache[a->serialSendCount++] = (uint8)(CRC16); \ + a->serialSendCache[a->serialSendCount++] = (uint8)(CRC16 >> 8); \ + (TO_MDBase(a))->mdRTUSendBytesFunction(a->serialSendCache, a->serialSendCount); \ + } +#else +/*The following macro is used to send modbus data and calculate the check at the same time*/ +#define MDS_START_SEND(a) \ + { \ + uint8 CRC16Temp; \ + uint16 CRC16 = 0xFFFF; +#define MDS_SEND_BYTE(a, b) \ + CRC16 = MD_CRC16Update(CRC16, (b)); \ + MDS_RTU_SendByte(a, b) +#define MDS_SEND_END(a) \ + CRC16Temp = CRC16 & 0xFF; \ + (TO_MDBase(a))->mdRTUSendBytesFunction((uint8 *)(&(CRC16Temp)), 1); \ + CRC16Temp = (CRC16 >> 8) & 0xFF; \ + (TO_MDBase(a))->mdRTUSendBytesFunction((uint8 *)(&(CRC16Temp)), 1); \ + } +#endif +/*********************************END******************************************/ + +/*********************************FUNCTION DECLARATION************************************/ +void MDS_RTU_Init(PModbusS_RTU pModbusRTU, MD_RTU_SerialInit mdRTUSerialInitFun, uint8 salveAddr, + uint32 baud, uint8 dataBits, uint8 stopBits, uint8 parity); +void MDS_RTU_QueueInit(PModbusS_RTU pModbus_RTU, + uint8 *recvQueueData, + uint16 recvQueueSize, + uint8 *msgProcessQueueData, + uint16 msgProcessQueueSize); +void MDS_RTU_SetWriteListenFun(PModbusS_RTU pModbus_RTU, MDSWriteFunciton wFun); +BOOL MDS_RTU_AddMapItem(PModbusS_RTU pModbusRTU, PMapTableItem pRegCoilItem); +void MDS_RTU_Process(PModbusS_RTU pModbus_RTU); +/*********************************END******************************************/ + +#endif diff --git a/mkrtos_user/lib/modbus/inc/modbus_rtu_slave/MDS_RTU_User_Fun.h b/mkrtos_user/lib/modbus/inc/modbus_rtu_slave/MDS_RTU_User_Fun.h new file mode 100644 index 000000000..78b272148 --- /dev/null +++ b/mkrtos_user/lib/modbus/inc/modbus_rtu_slave/MDS_RTU_User_Fun.h @@ -0,0 +1,41 @@ +/******************************************************************************** + * @File name: MD_RTU_User_Fun.h + * @Author: zspace + * @Version: 1.0 + * @Date: 2020-4-10 + * @Description: Modbus RTU host user calling function + ********************************************************************************/ + +#ifndef _MD_RTU_USER_FUN_H__ +#define _MD_RTU_USER_FUN_H__ + +/*********************************HEAD FILE************************************/ +#include "MD_RTU_Type.h" +#include "MD_RTU_MapTable.h" +/*********************************END******************************************/ + +/*********************************Function declaration************************************/ +/*General users do not need to call the following functions*/ +BOOL MDS_RTU_ReadBits(void *obj, uint16 modbusAddr, uint16 numOf, uint8 *res, AddrType opAddrType); +BOOL MDS_RTU_ReadRegs(void *obj, uint16 modbusAddr, uint16 numOf, uint16 *res, AddrType opAddrType); +BOOL MDS_RTU_WriteBit(void *obj, uint16 modbusAddr, uint8 bit, AddrType opAddrType); +BOOL MDS_RTU_WriteBits(void *obj, uint16 modbusAddr, uint16 numOf, uint16 *bit, AddrType opAddrType); +BOOL MDS_RTU_WriteReg(void *obj, uint16 modbusAddr, uint16 reg, AddrType opAddrType); +BOOL MDS_RTU_WriteRegs(void *obj, uint16 modbusAddr, uint16 numOf, uint16 *reg, uint8 isBigE, AddrType opAddrType); + +/*The following function user calls*/ +BOOL MDS_RTU_WriteCoil(void *obj, uint16 modbusAddr, uint8 bit); +BOOL MDS_RTU_WriteInput(void *obj, uint16 modbusAddr, uint8 bit); +BOOL MDS_RTU_WriteCoils(void *obj, uint16 modbusAddr, uint16 numOf, uint16 *bit); +BOOL MDS_RTU_WriteInputs(void *obj, uint16 modbusAddr, uint16 numOf, uint16 *bit); +BOOL MDS_RTU_WriteHoldReg(void *obj, uint16 modbusAddr, uint16 reg); +BOOL MDS_RTU_WriteHoldRegs(void *obj, uint16 modbusAddr, uint16 numOf, uint16 *reg); +BOOL MDS_RTU_WriteInputReg(void *obj, uint16 modbusAddr, uint16 reg); +BOOL MDS_RTU_WriteInputRegs(void *obj, uint16 modbusAddr, uint16 numOf, uint16 *reg); +BOOL MDS_RTU_ReadCoils(void *obj, uint16 modbusAddr, uint16 numOf, uint8 *res); +BOOL MDS_RTU_ReadInput(void *obj, uint16 modbusAddr, uint16 numOf, uint8 *res); +BOOL MDS_RTU_ReadHoldRegs(void *obj, uint16 modbusAddr, uint16 numOf, uint16 *res); +BOOL MDS_RTU_ReadInputRegs(void *obj, uint16 modbusAddr, uint16 numOf, uint16 *res); +/*********************************END******************************************/ + +#endif diff --git a/mkrtos_user/lib/modbus/inc/port/MD_RTU_SysInterface.h b/mkrtos_user/lib/modbus/inc/port/MD_RTU_SysInterface.h new file mode 100644 index 000000000..45aa22f91 --- /dev/null +++ b/mkrtos_user/lib/modbus/inc/port/MD_RTU_SysInterface.h @@ -0,0 +1,57 @@ +#ifndef _MD_SYS_INTERFACE_H__ +#define _MD_SYS_INTERFACE_H__ +#include "MD_RTU_Config.h" + +#if MD_RTU_USED_OS + +#include "MD_RTU_Type.h" +#include "MD_RTU_Tool.h" +#include "MD_RTU_Queue.h" + +///< RTOS files +#include "RTOS_msg.h" +#include "RTOS_mutex.h" +#include "RTOS_task.h" + +#define MD_RTU_LOCK_HANDLE PMUTEX_CB ///< Locked object name +#define MD_RTU_MSG_HANDLE PMSG_CB ///< Msg oobject name +#define MD_RTU_TASK_HANDLE PTASK_TCB ///< task oobject name + +#define MD_RTU_TASK_LEVEL 6 +#define MD_RTU_TASK_STACK_SIZE 128 + +#define MD_RTU_WAIT_UNLESS 0xFFFFFFFF ///< always waiting +#define MD_RTU_MSG_BOX_LENGTH 32 + +uint8 MD_RTU_CreateThread(PModbusBase pModbusBase, void (*funTask)(void *arg), MD_RTU_TASK_HANDLE *pTaskObj); +void MD_RTU_Delay(uint32 ms); + +uint8 MD_RTU_CreateMsg(PModbusBase pModbusBase, MD_RTU_MSG_HANDLE *pMsgObj, + uint32 msgBoxLength); +uint8 MD_RTU_MsgPut(PModbusBase pModbusBase, MD_RTU_MSG_HANDLE pMsgObj, void *msg, uint32 msgPutDelay); +uint8 MD_RTU_MsgGet(PModbusBase pModbusBase, MD_RTU_MSG_HANDLE pMsgObj, void **msg, uint32 msgGetDelay); + +uint8 MD_RTU_CreateLock(PModbusBase pModbusBase, MD_RTU_LOCK_HANDLE *pLockObj); +uint8 MD_RTU_Lock(PModbusBase pModbusBase, MD_RTU_LOCK_HANDLE lockObj, uint32 mutexWaitDelay); +uint8 MD_RTU_Unlock(PModbusBase pModbusBase, MD_RTU_LOCK_HANDLE lockObj); + +uint32 MD_RTU_GetSysTick(void); +#endif + +#if MD_RTU_USED_OS +#define MD_RTU_LOCK(a, b) MD_RTU_Lock(a, b, MD_RTU_WAIT_UNLESS) +#define MD_RTU_UNLOCK(a, b) MD_RTU_Unlock(a, b) +#define MD_RTU_MSG_PUT(a, b, c, d) MD_RTU_MsgPut(a, b, c, d) +#define MD_RTU_MSG_GET(a, b, c, d) MD_RTU_MsgGet(a, b, c, d) +#else +#include "u_sys.h" +#include "u_sleep.h" +#define MD_RTU_LOCK(a, b) +#define MD_RTU_UNLOCK(a, b) +#define MD_RTU_MSG_PUT(a, b, c, d) +#define MD_RTU_MSG_GET(a, b, c, d) +#define MD_RTU_GetSysTick() (sys_read_tick()) +#define MD_RTU_Delay(a) u_sleep_ms(a) +#endif + +#endif diff --git a/mkrtos_user/lib/modbus/src/modbus_base/MD_RTU_CRC16.c b/mkrtos_user/lib/modbus/src/modbus_base/MD_RTU_CRC16.c new file mode 100644 index 000000000..97a4d3aa0 --- /dev/null +++ b/mkrtos_user/lib/modbus/src/modbus_base/MD_RTU_CRC16.c @@ -0,0 +1,85 @@ +/**@file MD_RTU_CRC16.c +* @brief Modbus RTU CRC16 Check module +* @author zspace +* @date 2020-4-10 +* @version V1.0 +********************************************************************************** +* @par Open source address +* https://github.com/lotoohe-space/XTinyModbus +* @par modify log: +* +*
Date Version Author Description +*
2020-4-10 1.0 zspace First version +*
+* +********************************************************************************** +*/ +/*********************************HEAD FILE************************************/ +#include "MD_RTU_CRC16.h" +/*********************************END******************************************/ + +/*********************************VARIABLE DECLARATION************************************/ +#if MD_RTU_CRC16_FAST_MODE +static const uint16 crc16_table[256]= +{ + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 +}; +#endif +/*********************************END******************************************/ + +/** +* @brief This function needs to get the value of CRC16 through cumulative calculation +* @param[in] CRC CRC16 value calculated last time. +* @param[in] byte Need to participate in the calculation of a byte. +* @return None +*/ +uint16 MD_CRC16Update(uint16 CRC, uint8 byte) +{ +#if MD_RTU_CRC16_FAST_MODE + return ((CRC) >> 8) ^ crc16_table[((CRC) ^ byte) & 0xff]; +#else + int i; + + CRC ^= byte; + for (i = 0; i < 8; ++i) + { + if (CRC & 1) + CRC = (CRC >> 1) ^ 0xA001; + else + CRC = (CRC >> 1); + } + + return CRC; +#endif +} diff --git a/mkrtos_user/lib/modbus/src/modbus_base/MD_RTU_MapTable.c b/mkrtos_user/lib/modbus/src/modbus_base/MD_RTU_MapTable.c new file mode 100644 index 000000000..7b0f2851c --- /dev/null +++ b/mkrtos_user/lib/modbus/src/modbus_base/MD_RTU_MapTable.c @@ -0,0 +1,61 @@ +/**@file MD_RTU_MapTable.c +* @brief Modbus RTU Discrete mapping management module +* @author zspace +* @date 2020-4-10 +* @version V1.0 +********************************************************************************** +* @par Open source address +* https://github.com/lotoohe-space/XTinyModbus +* @par modify log: +* +*
Date Version Author Description +*
2020-4-10 1.0 zspace First version +*
+* +********************************************************************************** +*/ +/*********************************HEAD FILE************************************/ +#include "MD_RTU_MapTable.h" +/*********************************END******************************************/ + +/** +* @brief Add a mapping to master or slave +* @param[in] obj Slave or host object pointer +* @param[in] pRegCoilItem Slave or host object pointer +* @return +* - TRUE success +* - FALSE fail +*/ +uint8 MapTableAdd(void* obj,PMapTableItem pMapTableItem,uint16 tabSize){ + uint16 i=0; + PMapTableItem *pMapTableList=obj; + if(!obj){return FALSE;} + for(i=0;idata=data; + q->maxVal = maxVal; + q->front = q->rear = 0; + q->valid = TRUE; + return TRUE; +} +/** +* @brief Get the length of the data in the queue +* @param[in] q Queue object pointer +* @return The length of valid data in the queue +*/ +uint16 MDQueueLength(MDSqQueue* q) { + if (q == NULL) { return 0; } + return (q->rear - q->front + q->maxVal) % q->maxVal; +} +/** +* @brief Queue reset (cleared) +* @param q Queue object pointer +* @return None +*/ +void MDResetQueue(MDSqQueue* q) { + if (q == NULL) { return ; } + q->front = q->rear = 0; +} +/** +* @brief Whether the queue is empty +* @param q Queue object pointer +* @return +* - TRUE empty +* - FALSE Not empty +*/ +uint8 MDQueueEmpty(MDSqQueue* q) { + if (q == NULL) { return 1; } + return (q->front == q->rear); +} +/** +* @brief Insert at the end of the queue +* @param[in] q Queue object pointer +* @param[in] e Inserted element +* @return +* - TRUE success +* - FALSE fail +*/ +uint8 MDenQueue(MDSqQueue* q, MDQueueDataType *e,SqQueueType type) { + if ((q->rear + 1) % q->maxVal == q->front) { + return FALSE; + } + q->rear = (q->rear + 1) % q->maxVal; + switch(type){ + case CHAR_TYPE: + ((char*)(q->data))[q->rear] = *((char*)e); + break; + case UINT8_TYPE: + ((uint8*)(q->data))[q->rear] = *((uint8*)e); + break; + case SHORT_TYPE: + ((short*)(q->data))[q->rear] = *((short*)e); + break; + case INT_TYPE: + ((int*)(q->data))[q->rear] = *((int*)e); + break; + case FLOAT_TYPE: + ((float*)(q->data))[q->rear] = *((float*)e); + break; + } + + return TRUE; +} +/** +* @brief Queue head insertion +* @param[in] q Queue object pointer +* @param[in] e Inserted element +* @return +* - TRUE success +* - FALSE fail +*/ +uint8 MDenQueueH(MDSqQueue* q, MDQueueDataType *e,SqQueueType type){ + if((q->front - 1 + q->maxVal) % q->maxVal == q->rear) + return FALSE; + + switch(type){ + case CHAR_TYPE: + ((char*)(q->data))[q->front] = *((char*)e); + break; + case UINT8_TYPE: + ((uint8*)(q->data))[q->front] = *((uint8*)e); + break; + case SHORT_TYPE: + ((short*)(q->data))[q->front] = *((short*)e); + break; + case INT_TYPE: + ((int*)(q->data))[q->front] = *((int*)e); + break; + case FLOAT_TYPE: + ((float*)(q->data))[q->front] = *((float*)e); + break; + } + q->front = (q->front - 1 + q->maxVal) % q->maxVal; + return TRUE; +} +/** +* @brief Queue head out of the queue +* @param[in] q Queue object pointer +* @param[in] e Obtained elements +* @return +* - TRUE success +* - FALSE fail +*/ +uint8 MDdeQueue(MDSqQueue* q, MDQueueDataType *e,SqQueueType type) { + if (q->front == q->rear) { /*Empty, return an error*/ + return FALSE; + } + q->front = (q->front + 1) % q->maxVal; + + switch(type){ + case CHAR_TYPE: + *((char*)e)=((char*)(q->data))[q->front]; + break; + case UINT8_TYPE: + *((uint8*)e)=((uint8*)(q->data))[q->front]; + break; + case SHORT_TYPE: + *((short*)e)=((short*)(q->data))[q->front]; + break; + case INT_TYPE: + *((int*)e)=((int*)(q->data))[q->front]; + break; + case FLOAT_TYPE: + *((int*)e)=((float*)(q->data))[q->front]; + break; + } + return TRUE; +} +/** +* @brief Queue tail out +* @param[in] q Queue object pointer +* @param[in] e Obtained elements +* @return +* - TRUE success +* - FALSE fail +*/ +uint8 MDdeQueueF(MDSqQueue* q, MDQueueDataType *e,SqQueueType type) { + if(q->front == q->rear){ + return FALSE; + } + switch(type){ + case CHAR_TYPE: + *((char*)e)=((char*)(q->data))[q->rear]; + break; + case UINT8_TYPE: + *((uint8*)e)=((uint8*)(q->data))[q->rear]; + break; + case SHORT_TYPE: + *((short*)e)=((short*)(q->data))[q->rear]; + break; + case INT_TYPE: + *((int*)e)=((int*)(q->data))[q->rear]; + break; + case FLOAT_TYPE: + *((int*)e)=((float*)(q->data))[q->rear]; + break; + } + q->rear = (q->rear - 1 + q->maxVal) % q->maxVal; + return TRUE; +} +/** +* @brief Get the element at the end of the queue without affecting the queue, only the element +* @param[in] q Queue object pointer +* @param[in] e Obtained elements +* @return +* - TRUE succes +* - FALSE fail +*/ +uint8 MDgetTailQueue(MDSqQueue* q, MDQueueDataType* e,SqQueueType type) { + if (q->front == q->rear) { /*Empty, return an error*/ + return FALSE; + } + + switch(type){ + case CHAR_TYPE: + *((char*)e)=((char*)(q->data))[(q->front + 1) % q->maxVal]; + break; + case UINT8_TYPE: + *((uint8*)e)=((uint8*)(q->data))[(q->front + 1) % q->maxVal]; + break; + case SHORT_TYPE: + *((short*)e)=((short*)(q->data))[(q->front + 1) % q->maxVal]; + break; + case INT_TYPE: + *((int*)e)=((int*)(q->data))[(q->front + 1) % q->maxVal]; + break; + case FLOAT_TYPE: + *((int*)e)=((float*)(q->data))[(q->front + 1) % q->maxVal]; + break; + } + return TRUE; +} + + diff --git a/mkrtos_user/lib/modbus/src/modbus_rtu_master/MDM_RTU_Fun.c b/mkrtos_user/lib/modbus/src/modbus_rtu_master/MDM_RTU_Fun.c new file mode 100644 index 000000000..10b83740d --- /dev/null +++ b/mkrtos_user/lib/modbus/src/modbus_rtu_master/MDM_RTU_Fun.c @@ -0,0 +1,1386 @@ +/******************************************************************************** +* @File name: MDM_RTU_Fun.c +* @Author: zspace +* @Emial: 1358745329@qq.com +* @Version: 1.0 +* @Date: 2020-4-10 +* @Description: Modbus RTU host function module +* Open source address: https://github.com/lotoohe-space/XTinyModbus +********************************************************************************/ + +/*********************************THE HEADER FILE CONTAINS************************************/ +#include "MDM_RTU_Fun.h" +// #include "MDM_RTU_Serial.h" +#include "MD_RTU_Tool.h" +#include "MD_RTU_CRC16.h" +#include "MD_RTU_SysInterface.h" +#include "MD_RTU_Type.h" +#include +/*********************************END******************************************/ + +/*********************************FUNCTION DECLARATION************************************/ +#if !MDM_USE_SEND_CACHE +static void MDM_RTU_SendByte(PModbus_RTU pModbus_RTU,uint8 byte); +#endif +void MDM_RTU_RecvByte(void *obj,uint8 byte); +/*********************************END******************************************/ + +/******************************************************* +* +* Function name :MDM_RTU_Init +* Description :Modbus RTU Host initialization +* Parameter : +* @pModbusRTU Host object pointer +* @mdRTUSerialInitFun Serial port initialization function +* @baud Baud rate +* @dataBits Data bit +* @stopBits Stop bit +* @parity Parity bit +* Return : reference[MDError] +**********************************************************/ +MDError MDM_RTU_Init( + PModbus_RTU pModbusRTU, + MD_RTU_SerialInit mdRTUSerialInitFun, + uint32 baud, + uint8 dataBits, + uint8 stopBits, + uint8 parity +){ + float T; + uint8 i; + if(pModbusRTU==NULL){return ERR_VOID;} + +#if MD_RTU_USED_OS + if(pModbusRTU->mdRTUMsgHandle==NULL){ + if(!MD_RTU_CreateMsg((PModbusBase)pModbusRTU, &(pModbusRTU->mdRTUMsgHandle),MD_RTU_MSG_BOX_LENGTH)){ + return ERR_CTE_OBJ; + } + } + if(pModbusRTU->mdRTULockHandle==NULL){ + if(!MD_RTU_CreateLock((PModbusBase)pModbusRTU, &(MD_RTU_LOCK_HANDLE_ARG(pModbusRTU)))){ + return ERR_CTE_OBJ; + } + } + if(pModbusRTU->mdRTULockObjHandle==NULL){ + if(!MD_RTU_CreateLock((PModbusBase)pModbusRTU, &(MD_RTU_LOCK_OBJ_HANDLE_ARG(pModbusRTU)))){ + return ERR_CTE_OBJ; + } + } + if(pModbusRTU->mdRTULockObj1Handle==NULL){ + if(!MD_RTU_CreateLock((PModbusBase)pModbusRTU, &(MD_RTU_LOCK_OBJ1_HANDLE_ARG(pModbusRTU)))){ + return ERR_CTE_OBJ; + } + } + if(pModbusRTU->mdRTUTaskHandle==NULL){ + if(!MD_RTU_CreateThread((PModbusBase)pModbusRTU,MDM_RTU_SysProcessTask,&MD_RTU_TASK_HANDLE_ARG(pModbusRTU))){ + return ERR_CTE_OBJ; + } + } +#endif + + MD_RTU_LOCK((PModbusBase)pModbusRTU,MD_RTU_LOCK_HANDLE_ARG(pModbusRTU)); + //MDInitQueue(&(pModbusRTU->mdSqQueue),UINT8_TYPE); + pModbusRTU->mdSqQueue.data=NULL; + pModbusRTU->mdSqQueue.maxVal=0; + MD_RTU_UNLOCK((PModbusBase)pModbusRTU,MD_RTU_LOCK_HANDLE_ARG(pModbusRTU)); + + MD_RTU_LOCK((PModbusBase)pModbusRTU,MD_RTU_LOCK_OBJ_HANDLE_ARG(pModbusRTU)); + for(i=0;ipMapTableList[i] = NULL; + } + TO_MDBase(pModbusRTU)->mdRTUTimeHandlerFunction=MDM_RTU_TimeHandler; + /*Data sending and receiving related functions*/ + TO_MDBase(pModbusRTU)->mdRTUSendBytesFunction=NULL; + TO_MDBase(pModbusRTU)->mdRTURecByteFunction=MDM_RTU_RecvByte; + TO_MDBase(pModbusRTU)->mdRTURecSendConv=NULL; +#if MDM_USE_SEND_CACHE + pModbusRTU->serialSendCount=0; +#endif + /*The time of the last reception, 0xFFFFFFF means that the detection frame has not started*/ + pModbusRTU->lastTimesTick=0xFFFFFFFF; + /*Current real-time time unit 100US*/ + pModbusRTU->timesTick=0; + + T=(1.0/(float)baud)*10000; + uint16 time=0; + time=T*(dataBits+(parity?1:0)); + if(stopBits==0){ + time+=T; + }else if(stopBits==1){ + time+=T*1.5f; + }else if(stopBits==2){ + time+=T*2; + } + pModbusRTU->frameIntervalTime=time;/*This parameter needs to be set according to the baud rate*/ + + pModbusRTU->recvFlag=0;/*Receive flag*/ + if(mdRTUSerialInitFun!=NULL){ + mdRTUSerialInitFun(pModbusRTU,baud, dataBits,stopBits,parity); + } + MD_RTU_UNLOCK((PModbusBase)pModbusRTU,MD_RTU_LOCK_OBJ_HANDLE_ARG(pModbusRTU)); + return ERR_NONE; +} +/** +* @brief This function init queue. +* @param[in] recvQueueData ???? +* @param[in] recvQueueSize ???? +* @result None +*/ +void MDM_RTU_QueueInit(PModbus_RTU pModbus_RTU, + uint8* recvQueueData, + uint16 recvQueueSize +){ + if(pModbus_RTU==NULL){ + return ; + } + MD_RTU_LOCK((PModbusBase)pModbus_RTU,MD_RTU_LOCK_HANDLE_ARG(pModbus_RTU)); + MDInitQueue(&(pModbus_RTU->mdSqQueue),recvQueueData,recvQueueSize); + MD_RTU_UNLOCK((PModbusBase)pModbus_RTU,MD_RTU_LOCK_HANDLE_ARG(pModbus_RTU)); +} +/******************************************************* +* +* Function name :MDM_RTU_CB_Init +* Description :Modbus RTU host sends the control block initialization, +* the control block mainly contains information maintenance +* such as the time and frequency of slave transmission +* Parameter : +* @pModbusRTUCB Send control block object pointer +* @pModbusRTU Host object pointer +* @sendIntervalTime Send interval time +* @sendOverTime Send timeout +* @RTTimes Number of retransmissions +* Return : None +**********************************************************/ +void MDM_RTU_CB_Init( + PModbus_RTU_CB pModbusRTUCB + ,PModbus_RTU pModbusRTU + ,uint32 sendIntervalTime + ,uint32 sendOverTime + ,uint8 RTTimes +){ + if(pModbusRTUCB==NULL){return ;} + MD_RTU_LOCK((PModbusBase)pModbusRTU,MD_RTU_LOCK_OBJ_HANDLE_ARG(pModbusRTU)); + pModbusRTUCB->sendIntervalTime=sendIntervalTime; + pModbusRTUCB->pModbus_RTU=pModbusRTU; + pModbusRTUCB->sendTimeTick=MD_RTU_GetSysTick(); + pModbusRTUCB->sendOverTime=sendOverTime; + pModbusRTUCB->RTTimes=RTTimes; + pModbusRTUCB->sendFlag=0; + pModbusRTU->parentObj=NULL; + MD_RTU_UNLOCK((PModbusBase)pModbusRTU,MD_RTU_LOCK_OBJ_HANDLE_ARG(pModbusRTU)); +} +/******************************************************* +* +* Function name : MDM_RTU_CB_OverTimeReset +* Description : Send control block timeout reset +* Parameter : +* @pModbusRTUCB Send control block object pointer +* Return : None +**********************************************************/ +void MDM_RTU_CB_OverTimeReset(PModbus_RTU_CB pModbusRTUCB){ + if(pModbusRTUCB==NULL){return ;} + MD_RTU_LOCK((PModbusBase)(pModbusRTUCB->pModbus_RTU),MD_RTU_LOCK_OBJ_HANDLE_ARG((pModbusRTUCB->pModbus_RTU))); + pModbusRTUCB->RTCount=0; + pModbusRTUCB->sendFlag=0; + pModbusRTUCB->sendTimeTick=pModbusRTUCB->pModbus_RTU->timesTick; + MD_RTU_UNLOCK((PModbusBase)(pModbusRTUCB->pModbus_RTU),MD_RTU_LOCK_OBJ_HANDLE_ARG((pModbusRTUCB->pModbus_RTU))); +} +/******************************************************* +* +* Function name :MDM_RTU_CB_ClrDisFlag +* Description :Clear disconnection signs +* Parameter : +* @pModbusRTUCB Send control block object pointer +* Return : �� +**********************************************************/ +void MDM_RTU_CB_ClrDisFlag(PModbus_RTU_CB pModbusRTUCB){ + if(pModbusRTUCB==NULL){return ;} + MD_RTU_LOCK((PModbusBase)(pModbusRTUCB->pModbus_RTU),MD_RTU_LOCK_OBJ_HANDLE_ARG((pModbusRTUCB->pModbus_RTU))); + MD_CB_CLR_DIS_FLAG(pModbusRTUCB); + MD_RTU_UNLOCK((PModbusBase)(pModbusRTUCB->pModbus_RTU),MD_RTU_LOCK_OBJ_HANDLE_ARG((pModbusRTUCB->pModbus_RTU))); +} +/******************************************************* +* +* Function name :MDM_RTU_CB_SetDisPollEnFlag +* Description : Set the offline polling enable flag bit. +* Parameter : +* @pModbusRTUCB Send control block object pointer. +* @state The state to be set. +* Return : None +**********************************************************/ +void MDM_RTU_CB_SetDisPollEnFlag(PModbus_RTU_CB pModbusRTUCB,BOOL state){ + if(pModbusRTUCB==NULL){return ;} + MD_RTU_LOCK((PModbusBase)(pModbusRTUCB->pModbus_RTU),MD_RTU_LOCK_OBJ_HANDLE_ARG((pModbusRTUCB->pModbus_RTU))); + if(state){ + MD_CB_SET_DIS_FLAG_EN(pModbusRTUCB); + }else{ + MD_CB_CLR_DIS_FLAG_EN(pModbusRTUCB); + } + MD_RTU_UNLOCK((PModbusBase)(pModbusRTUCB->pModbus_RTU),MD_RTU_LOCK_OBJ_HANDLE_ARG((pModbusRTUCB->pModbus_RTU))); +} +/******************************************************* +* +* Function name :MDM_RTU_TimeHandler +* Description :Timing processing function, timing unit 100US +* Parameter : +* @obj Host object pointer +* Return : None +**********************************************************/ +void MDM_RTU_TimeHandler(void *obj,uint32 timesTick){ + PModbus_RTU pModbusRTU=obj; + if(!pModbusRTU){ return; } + //pModbusRTU->timesTick++; + MD_RTU_LOCK((PModbusBase)pModbusRTU,MD_RTU_LOCK_OBJ_HANDLE_ARG(pModbusRTU)); + pModbusRTU->timesTick=timesTick; + /*No need to deal with*/ + if(pModbusRTU->lastTimesTick==0xFFFFFFFF){ + MD_RTU_UNLOCK((PModbusBase)pModbusRTU,MD_RTU_LOCK_OBJ_HANDLE_ARG(pModbusRTU)); + return ; + } + if(pModbusRTU->timesTick-pModbusRTU->lastTimesTick>=pModbusRTU->frameIntervalTime){ + if(pModbusRTU->CRC16Update!=0x0000){ + /*CRC error*/ + MD_RTU_LOCK((PModbusBase)(pModbusRTU),MD_RTU_LOCK_HANDLE_ARG((pModbusRTU))); + MDResetQueue(&(pModbusRTU->mdSqQueue)); + MD_RTU_UNLOCK((PModbusBase)(pModbusRTU),MD_RTU_LOCK_HANDLE_ARG((pModbusRTU))); + pModbusRTU->lastTimesTick=0xFFFFFFFF; + MD_RTU_UNLOCK((PModbusBase)pModbusRTU,MD_RTU_LOCK_OBJ_HANDLE_ARG(pModbusRTU)); + return ; + } + /*End of one frame*/ + pModbusRTU->recvFlag=1; + pModbusRTU->lastTimesTick=0xFFFFFFFF; + } + MD_RTU_UNLOCK((PModbusBase)pModbusRTU,MD_RTU_LOCK_OBJ_HANDLE_ARG(pModbusRTU)); +} +/******************************************************* +* +* Function name :MDM_RTU_RecvByte +* Description :This function receives data and puts it in the queue +* Parameter : +* @obj Host object pointer +* @byte A byte received +* Return : None +**********************************************************/ +void MDM_RTU_RecvByte(void *obj,uint8 byte){ + PModbus_RTU pModbusRTU=obj; + if(!pModbusRTU){ return; } + MD_RTU_LOCK((PModbusBase)(pModbusRTU),MD_RTU_LOCK_HANDLE_ARG((pModbusRTU))); + if(MDenQueue(&(pModbusRTU->mdSqQueue),&byte,UINT8_TYPE)==FALSE){ + MD_RTU_UNLOCK((PModbusBase)(pModbusRTU),MD_RTU_LOCK_HANDLE_ARG((pModbusRTU))); + return ; + } + MD_RTU_UNLOCK((PModbusBase)(pModbusRTU),MD_RTU_LOCK_HANDLE_ARG((pModbusRTU))); + MD_RTU_LOCK((PModbusBase)pModbusRTU,MD_RTU_LOCK_OBJ_HANDLE_ARG(pModbusRTU)); + if(pModbusRTU->lastTimesTick==0xFFFFFFFF){ + pModbusRTU->CRC16Update=0xFFFF; + } + pModbusRTU->CRC16Update=MD_CRC16Update(pModbusRTU->CRC16Update,byte); + /*Save the timestamp of the last character received*/ + pModbusRTU->lastTimesTick=pModbusRTU->timesTick; + MD_RTU_UNLOCK((PModbusBase)pModbusRTU,MD_RTU_LOCK_OBJ_HANDLE_ARG(pModbusRTU)); +} + +#if MD_RTU_USED_OS ///< used os +void MDM_RTU_SysProcessTask(void *arg){ + PModbus_RTU pModbusRTU=(PModbus_RTU)arg; + for(;;){ + void *msg=NULL; + while(1){ + if(MD_RTU_MSG_GET((PModbusBase)pModbusRTU,MD_RTU_MSG_HANDLE_ARG(pModbusRTU),&msg,0)){ + MDM_RTU_RecvByte((void*)pModbusRTU,(uint8)(msg)); + }else{ + break; + } + } + MDM_RTU_TimeHandler((void*)pModbusRTU,MD_RTU_GetSysTick()); + MD_RTU_Delay(5); + } +} +#endif + +#if !MDM_USE_SEND_CACHE +/******************************************************* +* +* Function name :MDM_RTU_SendByte +* Description :����һ���ֽ� +* Parameter : +* @pModbus_RTU ��������ָ�� +* @byte ���͵�һ���ֽ� +* Return : �� +**********************************************************/ +static void MDM_RTU_SendByte(PModbus_RTU pModbus_RTU,uint8 byte){ + if(!pModbus_RTU){ return; } + TO_MDBase(pModbus_RTU)->mdRTUSendBytesFunction(&byte,1); +} +#endif +/******************************************************* +* +* Function name :MDM_RTU_AddMapItem +* Description :This function adds a mapping record to the discrete mapping table +* Parameter : +* @pModbusRTU Host structure pointer +* @pRegCoilItem Items to be added +* Return : None +**********************************************************/ +BOOL MDM_RTU_AddMapItem(PModbus_RTU pModbusRTU,PMapTableItem pMapTableItem){ + BOOL res; + if(pModbusRTU==NULL || pMapTableItem==NULL){ + return FALSE; + } + MD_RTU_LOCK((PModbusBase)(pModbusRTU),MD_RTU_LOCK_OBJ_HANDLE_ARG((pModbusRTU))); + res=MapTableAdd(pModbusRTU->pMapTableList, pMapTableItem,MDM_REG_COIL_ITEM_NUM); + MD_RTU_UNLOCK((PModbusBase)(pModbusRTU),MD_RTU_LOCK_OBJ_HANDLE_ARG((pModbusRTU))); + return res; +} + +/******************************************************* +* +* Function name :MDM_RTU_ReadByte +* Description :Get data from the receiving queue +* Parameter : +* @pModbus_RTU Host object pointer +* @res Get the data cache +* @len The length of the data obtained +* Return : None +**********************************************************/ +MDError MDM_RTU_ReadByte(PModbus_RTU pModbusRTU,uint8 *res,uint8 len){ + uint8 i; + uint8 resI; + if(res==NULL){return ERR_VOID;} + for(i=0;imdSqQueue),(res+i),UINT8_TYPE); + MD_RTU_UNLOCK((PModbusBase)(pModbusRTU),MD_RTU_LOCK_HANDLE_ARG((pModbusRTU))); + if(!resI){ + return ERR_QUEUE; + } + } + return ERR_NONE; +} +/******************************************************* +* +* Function name :MDM_RTU_ReadUint16 +* Description :Get data from the receiving queue +* Parameter : +* @pModbus_RTU Host object pointer +* @res Get data cache +* @len The length of the data obtained +* Return : None +**********************************************************/ +MDError MDM_RTU_ReadUint16(PModbus_RTU pModbusRTU,uint16 *res,uint8 len){ + uint8 i; + uint8 byte; + if(res==NULL){return ERR_VOID;} + MD_RTU_LOCK((PModbusBase)(pModbusRTU),MD_RTU_LOCK_HANDLE_ARG((pModbusRTU))); + for(i=0;imdSqQueue),&byte,UINT8_TYPE)){ + MD_RTU_UNLOCK((PModbusBase)(pModbusRTU),MD_RTU_LOCK_HANDLE_ARG((pModbusRTU))); + return ERR_QUEUE; + } + res[i]=byte<<8; + if(!MDdeQueue(&(pModbusRTU->mdSqQueue),&byte,UINT8_TYPE)){ + MD_RTU_UNLOCK((PModbusBase)(pModbusRTU),MD_RTU_LOCK_HANDLE_ARG((pModbusRTU))); + return ERR_QUEUE; + } + res[i]|=byte; + } + MD_RTU_UNLOCK((PModbusBase)(pModbusRTU),MD_RTU_LOCK_HANDLE_ARG((pModbusRTU))); + return ERR_NONE; +} +/******************************************************* +* +* Function name :MDM_RTU_ReadFun +* Description :This function sends commands related to the read function +* Parameter : +* @pModbus_RTU Host object pointer +* @funCode function code +* @slaveAddr Slave address +* @startAddr Read start address +* @numOf Number of reads +* Return : None +**********************************************************/ +static void MDM_RTU_ReadFun(PModbus_RTU pModbus_RTU,uint8 funCode,uint8 slaveAddr,uint16 startAddr,uint16 numOf){ + MD_RTU_SEND_MODE(pModbus_RTU); + MEM_RTU_START_EN(pModbus_RTU); + MEM_RTU_EN_QUEUE(pModbus_RTU,slaveAddr); + MEM_RTU_EN_QUEUE(pModbus_RTU,funCode); + MEM_RTU_EN_QUEUE(pModbus_RTU,MD_H_BYTE(startAddr)); + MEM_RTU_EN_QUEUE(pModbus_RTU,MD_L_BYTE(startAddr)); + MEM_RTU_EN_QUEUE(pModbus_RTU,MD_H_BYTE(numOf)); + MEM_RTU_EN_QUEUE(pModbus_RTU,MD_L_BYTE(numOf)); + MEM_RTU_END_EN(pModbus_RTU); + MD_RTU_RECV_MODE(pModbus_RTU); +} +/******************************************************* +* +* Function name :MDM_RTU_WriteSingleFun +* Description :Write single coil and register function +* Parameter : +* @pModbus_RTU Host object pointer +* @funCode function code +* @slaveAddr Slave address +* @startAddr Write start address +* @value Value written +* Return : None +**********************************************************/ +static void MDM_RTU_WriteSingleFun(PModbus_RTU pModbus_RTU,uint8 funCode,uint8 slaveAddr,uint16 startAddr,uint16 value){ + MD_RTU_SEND_MODE(pModbus_RTU); + MEM_RTU_START_EN(pModbus_RTU); + MEM_RTU_EN_QUEUE(pModbus_RTU,slaveAddr); + MEM_RTU_EN_QUEUE(pModbus_RTU,funCode); + MEM_RTU_EN_QUEUE(pModbus_RTU,MD_H_BYTE(startAddr)); + MEM_RTU_EN_QUEUE(pModbus_RTU,MD_L_BYTE(startAddr)); + MEM_RTU_EN_QUEUE(pModbus_RTU,MD_H_BYTE(value)); + MEM_RTU_EN_QUEUE(pModbus_RTU,MD_L_BYTE(value)); + MEM_RTU_END_EN(pModbus_RTU); + MD_RTU_RECV_MODE(pModbus_RTU); +} +/******************************************************* +* +* Function name :MDM_RTU_WriteFun +* Description :Write multiple coils and multiple registers +* Parameter : +* @pModbus_RTU Host object pointer +* @funCode function code +* @slaveAddr Slave address +* @startAddr Write start address +* @numOf Number of data written +* @data Data written +* Return : None +**********************************************************/ +static void MDM_RTU_WriteFun(PModbus_RTU pModbus_RTU, + uint8 funCode,uint8 slaveAddr,uint16 startAddr,uint8 numOf,uint8 *data){ + uint16 i; + uint8 wLen; + MD_RTU_SEND_MODE(pModbus_RTU); + MEM_RTU_START_EN(pModbus_RTU); + MEM_RTU_EN_QUEUE(pModbus_RTU,slaveAddr); + MEM_RTU_EN_QUEUE(pModbus_RTU,funCode); + MEM_RTU_EN_QUEUE(pModbus_RTU,MD_H_BYTE(startAddr)); + MEM_RTU_EN_QUEUE(pModbus_RTU,MD_L_BYTE(startAddr)); + MEM_RTU_EN_QUEUE(pModbus_RTU,MD_H_BYTE(numOf)); + MEM_RTU_EN_QUEUE(pModbus_RTU,MD_L_BYTE(numOf)); + if(funCode==15){ + wLen=(numOf>>3) + ((numOf%8)?1:0); + }else if(funCode==16){ + wLen=numOf<<1; + } + MEM_RTU_EN_QUEUE(pModbus_RTU,wLen); + if(funCode == 15){ + for(i=0;i>8)); + MEM_RTU_EN_QUEUE(pModbus_RTU,(tempData[i]&0xff)); + } + } + MEM_RTU_END_EN(pModbus_RTU); + MD_RTU_RECV_MODE(pModbus_RTU); +} +/******************************************************* +* +* Function name :MDM_RTU_InsideWriteBits +* Description :Write bits to the discrete map +* Parameter : +* @obj Host object pointer +* @modbusAddr Discretely mapped modbus address +* @numOf Write number +* @bit Data written +* @opAddrType Write address type (COILS_TYPE, INPUT_TYPE), see [AddrType] +* Return : TRUE , FALSE +**********************************************************/ +BOOL MDM_RTU_InsideWriteBits( + void* obj, + uint16 modbusAddr, + uint16 numOf, + uint8 *bit, + AddrType opAddrType, + uint8 devAddr +){ + uint16 i; + PModbus_RTU pModbus_RTU = obj; + if(pModbus_RTU==NULL){return FALSE;} + if(opAddrType != COILS_TYPE && opAddrType != INPUT_TYPE){return FALSE;} + + for(i=0;ipMapTableList[i]==NULL){ + continue; + } + /*Check the device number*/ + if(devAddr!=pModbus_RTU->pMapTableList[i]->devAddr){continue;} + + if(pModbus_RTU->pMapTableList[i]->modbusAddr<=modbusAddr&& + (pModbus_RTU->pMapTableList[i]->modbusAddr+pModbus_RTU->pMapTableList[i]->modbusDataSize)>=(modbusAddr+numOf) + ){ + if(pModbus_RTU->pMapTableList[i]->addrType==opAddrType){/*Must be BIT type*/ + uint16 offsetAddr=modbusAddr-MDS_RTU_REG_COIL_ITEM_ADDR(pModbus_RTU->pMapTableList[i]); + uint16 j; + MD_RTU_LOCK((PModbusBase)(pModbus_RTU),MD_RTU_LOCK_OBJ_HANDLE_ARG((pModbus_RTU))); + for(j=0;j>3] ,j%8) + ){ + MD_SET_BIT( + MDS_RTU_REG_COIL_ITEM_DATA( + pModbus_RTU->pMapTableList[i])[(offsetAddr+j)>>4] + ,(j+offsetAddr)%16); + }else{ + MD_CLR_BIT( + MDS_RTU_REG_COIL_ITEM_DATA( + pModbus_RTU->pMapTableList[i])[(offsetAddr+j)>>4] + ,(j+offsetAddr)%16); + } + } + MD_RTU_UNLOCK((PModbusBase)(pModbus_RTU),MD_RTU_LOCK_OBJ_HANDLE_ARG((pModbus_RTU))); + return TRUE; + } + } + } + return FALSE; +} +/******************************************************* +* +* Function name :MDM_RTU_InsideWriteRegs +* Description :Write discrete register +* Parameter : +* @obj Host object pointer +* @modbusAddr Discretely mapped modbus address +* @numOf Write number +* @reg Data written +* @isBigE Big-endian or little-endian +* @opAddrType Write address type (HOLD_REGS_TYPE, INPUT_REGS_TYPE), see [AddrType] +* Return : TRUE , FALSE +**********************************************************/ +BOOL MDM_RTU_InsideWriteRegs( +void* obj, +uint16 modbusAddr, +uint16 numOf, +uint16 *reg, +uint8 isBigE, +AddrType opAddrType, +uint8 devAddr +){ + uint16 i; + PModbus_RTU pModbus_RTU = obj; + if(pModbus_RTU==NULL){return FALSE;} + if(opAddrType != HOLD_REGS_TYPE && opAddrType != INPUT_REGS_TYPE){return FALSE;} + + for(i=0;ipMapTableList[i]==NULL){ + continue; + } + /*Check the device number*/ + if(devAddr!=pModbus_RTU->pMapTableList[i]->devAddr){continue;} + + if(pModbus_RTU->pMapTableList[i]->modbusAddr<=modbusAddr&& + (pModbus_RTU->pMapTableList[i]->modbusAddr+pModbus_RTU->pMapTableList[i]->modbusDataSize)>=(modbusAddr+numOf) + ){ + if(pModbus_RTU->pMapTableList[i]->addrType==opAddrType){/*������REG����*/ + uint16 offsetAddr=modbusAddr-MDS_RTU_REG_COIL_ITEM_ADDR(pModbus_RTU->pMapTableList[i]); + uint16 j=0; + MD_RTU_LOCK((PModbusBase)(pModbus_RTU),MD_RTU_LOCK_OBJ_HANDLE_ARG((pModbus_RTU))); + for(j=0;jpMapTableList[i])[offsetAddr+j]= + isBigE?MD_SWAP_HL(reg[j]):reg[j]; + } + MD_RTU_UNLOCK((PModbusBase)(pModbus_RTU),MD_RTU_LOCK_OBJ_HANDLE_ARG((pModbus_RTU))); + return TRUE; + } + } + } + return FALSE; +} +/******************************************************* +* +* Function name :MDM_RTU_NB_RW +* Description :Non-blocking read and write +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @funCode Function code, see [ModbusFunCode] +* @slaveAddr Slave address +* @startAddr Read and write start address +* @numOf Number of read and write data +* @wData If it is a write function code, then it is the written data +* Return : See [MDError] +**********************************************************/ +static MDError MDM_RTU_NB_RW( + PModbus_RTU_CB pModbus_RTU_CB, + ModbusFunCode funCode, + uint8 slaveAddr, + uint16 startAddr, + uint16 numOf, + void *wData +){ + MDError errRes; + uint8 index; + uint16 wAddr; + errRes = ERR_NONE; + if(pModbus_RTU_CB==NULL){return ERR_VOID;} + if(pModbus_RTU_CB->pModbus_RTU==NULL){return ERR_VOID;} + + if(MD_CB_GET_DIS_FLAG_EN(pModbus_RTU_CB)/*Enable the drop-off non-polling flag*/ + &&MD_CB_GET_DIS_FLAG(pModbus_RTU_CB)){/*Device dropped*/ + return ERR_DEV_DIS; + } + + if( pModbus_RTU_CB->pModbus_RTU->parentObj!=NULL && + pModbus_RTU_CB!=pModbus_RTU_CB->pModbus_RTU->parentObj){ + //Check if you are using the current Modbus + return ERR_IDLE; + } + pModbus_RTU_CB->pModbus_RTU->blockMode=1;/*set to non-block*/ + if(pModbus_RTU_CB->sendFlag==0){/*Has not been sent, or has been sent successfully*/ + /*Clear the receive queue*/ + MD_RTU_LOCK((PModbusBase)(pModbus_RTU_CB->pModbus_RTU), + MD_RTU_LOCK_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + MDResetQueue(&(pModbus_RTU_CB->pModbus_RTU->mdSqQueue)); + MD_RTU_UNLOCK((PModbusBase)(pModbus_RTU_CB->pModbus_RTU), + MD_RTU_LOCK_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + if(funCode>=1 && funCode<=4){ + /*Have not sent, then send*/ + MDM_RTU_ReadFun(pModbus_RTU_CB->pModbus_RTU,funCode,slaveAddr,startAddr,numOf); + } + else if(funCode==5||funCode==6){ + if(numOf>=1){/*The length must be greater than or equal to 1*/ + MDM_RTU_WriteSingleFun(pModbus_RTU_CB->pModbus_RTU,funCode,slaveAddr,startAddr,((uint16*)(wData))[0]); + } + }else if(funCode==15||funCode==16){ + MDM_RTU_WriteFun(pModbus_RTU_CB->pModbus_RTU,funCode,slaveAddr,startAddr,numOf,(uint8*)(wData)); + } + /*Set the start point of timeout*/ + pModbus_RTU_CB->sendTimeTick=pModbus_RTU_CB->pModbus_RTU->timesTick; + + /*Data has been sent, waiting for timeout detection*/ + //MD_SET_SENDED_FLAG(pModbus_RTU_CB); + pModbus_RTU_CB->sendFlag=1; + /*Set the block to be working*/ + pModbus_RTU_CB->pModbus_RTU->parentObj=pModbus_RTU_CB; + return ERR_SEND_FIN; + }else if(pModbus_RTU_CB->RTCountRTTimes){/*It has been sent, and there is no sending error*/ + + if(pModbus_RTU_CB->pModbus_RTU->recvFlag){/*Data received*/ + uint8 byte; + uint8 funCodeByte=0; + /*Clear sign*/ + pModbus_RTU_CB->pModbus_RTU->recvFlag=0; + MD_RTU_LOCK((PModbusBase)(pModbus_RTU_CB->pModbus_RTU), + MD_RTU_LOCK_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + if(!MDdeQueue(&(pModbus_RTU_CB->pModbus_RTU->mdSqQueue),&byte,UINT8_TYPE)){ + errRes = ERR_DATA_LEN; + MD_RTU_UNLOCK((PModbusBase)(pModbus_RTU_CB->pModbus_RTU), + MD_RTU_LOCK_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + goto _exit; + } + MD_RTU_UNLOCK((PModbusBase)(pModbus_RTU_CB->pModbus_RTU), + MD_RTU_LOCK_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + /*If data is received, process the data*/ + if(slaveAddr!=byte){ + errRes = ERR_SLAVE_ADDR; + goto _exit; + } + MD_RTU_LOCK((PModbusBase)(pModbus_RTU_CB->pModbus_RTU), + MD_RTU_LOCK_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + if(!MDdeQueue(&(pModbus_RTU_CB->pModbus_RTU->mdSqQueue),&funCodeByte,UINT8_TYPE)){ + errRes = ERR_DATA_LEN; + MD_RTU_UNLOCK((PModbusBase)(pModbus_RTU_CB->pModbus_RTU), + MD_RTU_LOCK_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + goto _exit; + } + MD_RTU_UNLOCK((PModbusBase)(pModbus_RTU_CB->pModbus_RTU), + MD_RTU_LOCK_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + switch(funCodeByte){ + case 0x1:/*Read the coil successfully*/ + case 0x2:/*Read input discrete*/ + { + uint16 i; + MD_RTU_LOCK((PModbusBase)(pModbus_RTU_CB->pModbus_RTU), + MD_RTU_LOCK_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + MDdeQueue(&(pModbus_RTU_CB->pModbus_RTU->mdSqQueue),&byte,UINT8_TYPE); + if((byte+2)!=MDQueueLength(&(pModbus_RTU_CB->pModbus_RTU->mdSqQueue))){ + /*Wrong length*/ + errRes = ERR_DATA_LEN; + MD_RTU_UNLOCK((PModbusBase)(pModbus_RTU_CB->pModbus_RTU), + MD_RTU_LOCK_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + goto _exit; + } + MD_RTU_UNLOCK((PModbusBase)(pModbus_RTU_CB->pModbus_RTU), + MD_RTU_LOCK_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + index = numOf; + wAddr=startAddr; + for(i=0;ipModbus_RTU), + MD_RTU_LOCK_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + if(!MDdeQueue(&(pModbus_RTU_CB->pModbus_RTU->mdSqQueue),&rByte,UINT8_TYPE)){ + /*Wrong length*/ + errRes = ERR_DATA_LEN; + MD_RTU_UNLOCK((PModbusBase)(pModbus_RTU_CB->pModbus_RTU), + MD_RTU_LOCK_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + goto _exit; + } + MD_RTU_UNLOCK((PModbusBase)(pModbus_RTU_CB->pModbus_RTU), + MD_RTU_LOCK_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + /*Single deposit is less than or equal to 8bit*/ + if(!MDM_RTU_InsideWriteBits(pModbus_RTU_CB->pModbus_RTU,wAddr,((index<8)?index:8), &rByte,(AddrType)funCodeByte,slaveAddr)){ + errRes= ERR_DATA_SAVE; + goto _exit; + } + wAddr += ((index<8)?index:8); + index-=8; + } +// /*Release channel*/ +// pModbus_RTU_CB->pModbus_RTU->parentObj=NULL; + /*Received from the machine*/ + pModbus_RTU_CB->sendFlag=2; + errRes= ERR_RW_FIN; + goto _exit; + } + case 0x3:/*Read holding register*/ + case 0x4:/*Read input register*/ + { + uint16 i; + uint16 len; + MD_RTU_LOCK((PModbusBase)(pModbus_RTU_CB->pModbus_RTU), + MD_RTU_LOCK_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + MDdeQueue(&(pModbus_RTU_CB->pModbus_RTU->mdSqQueue),&byte,UINT8_TYPE); + MD_RTU_UNLOCK((PModbusBase)(pModbus_RTU_CB->pModbus_RTU), + MD_RTU_LOCK_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + if((byte+2)!=MDQueueLength(&(pModbus_RTU_CB->pModbus_RTU->mdSqQueue))){ + /*Wrong length*/ + errRes= ERR_DATA_LEN; + goto _exit; + } + len=byte>>1; + for(i=0;ipModbus_RTU), + MD_RTU_LOCK_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + MDdeQueue(&(pModbus_RTU_CB->pModbus_RTU->mdSqQueue),&rByte,UINT8_TYPE); + wTemp=(rByte<<8); + MDdeQueue(&(pModbus_RTU_CB->pModbus_RTU->mdSqQueue),&rByte,UINT8_TYPE); + wTemp|=rByte; + MD_RTU_UNLOCK((PModbusBase)(pModbus_RTU_CB->pModbus_RTU), + MD_RTU_LOCK_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + if(!MDM_RTU_InsideWriteRegs(pModbus_RTU_CB->pModbus_RTU,startAddr+i,1,&wTemp,0,(AddrType)funCodeByte,slaveAddr)){ + errRes= ERR_DATA_SAVE; + goto _exit; + } + } + pModbus_RTU_CB->sendFlag=2; + errRes= ERR_RW_FIN; + goto _exit; + } + + case 0x5:/*Write single coil*/ + case 0x6: /*Write a single register*/ + { + uint16 res; + if(MDM_RTU_ReadUint16(pModbus_RTU_CB->pModbus_RTU,&res,1)!=ERR_NONE){ + errRes= ERR_DATA_LEN; + goto _exit; + } + /*Return address mismatch error*/ + if(res!=startAddr){ + errRes= ERR_WRITE_COIL; + goto _exit; + } + if(MDM_RTU_ReadUint16(pModbus_RTU_CB->pModbus_RTU,&res,1)!=ERR_NONE){ + errRes= ERR_DATA_LEN; + goto _exit; + } + /*Return data does not match*/ + if(res!=*((uint16*)wData)){ + errRes= ERR_WRITE_COIL; + goto _exit; + } + pModbus_RTU_CB->sendFlag=2; + errRes= ERR_RW_FIN; + goto _exit; + } + case 0x0F: /*Write multiple coils*/ + case 0x10:{ /*Write multiple registers*/ + uint16 res; + if(MDM_RTU_ReadUint16(pModbus_RTU_CB->pModbus_RTU,&res,1)!=ERR_NONE){ + errRes= ERR_DATA_LEN; + goto _exit; + } + /*Return address mismatch error*/ + if(res!=startAddr){ + errRes= ERR_WRITE_COIL; + goto _exit; + } + if(MDM_RTU_ReadUint16(pModbus_RTU_CB->pModbus_RTU,&res,1)!=ERR_NONE){ + errRes= ERR_DATA_LEN; + goto _exit; + } + /*Return data does not match*/ + if(res!=numOf){ + errRes= ERR_WRITE_COIL; + goto _exit; + } + pModbus_RTU_CB->sendFlag=2; + errRes= ERR_RW_FIN; + goto _exit; + } + case 0x81: pModbus_RTU_CB->sendFlag=3; errRes= ERR_READ_COIL; goto _exit; /*Abnormal reading coil*/ + case 0x82: pModbus_RTU_CB->sendFlag=3; errRes= ERR_READ_INPUT; goto _exit; /*Read input discrete quantity abnormal*/ + case 0x83: pModbus_RTU_CB->sendFlag=3; errRes= ERR_READ_HOLD_REG; goto _exit; /*Read holding register error*/ + case 0x84: pModbus_RTU_CB->sendFlag=3; errRes= ERR_READ_INPUT_REG; goto _exit; /*Error reading input register*/ + case 0x85: pModbus_RTU_CB->sendFlag=3; errRes= ERR_WRITE_COIL; goto _exit; /*Write single coil error*/ + case 0x86: pModbus_RTU_CB->sendFlag=3; errRes= ERR_WRITE_REG; goto _exit; /*Error writing order*/ + case 0x8F: pModbus_RTU_CB->sendFlag=3; errRes= ERR_WRITE_COIL; goto _exit; /*Write multiple coil error*/ + case 0x90: pModbus_RTU_CB->sendFlag=3; errRes= ERR_WRITE_REG; goto _exit; /*Write multiple register error*/ + } + + } + if(pModbus_RTU_CB->sendFlag==2){/*If the sending is successful, send again*/ + /*Timing resend processing*/ + if(pModbus_RTU_CB->pModbus_RTU->timesTick-pModbus_RTU_CB->sendTimeTick + >=pModbus_RTU_CB->sendIntervalTime){ + /*Resend*/ + //MD_CLR_SENDED_FLAG(pModbus_RTU_CB); + pModbus_RTU_CB->sendFlag=0; + // /*Release channel*/ + // pModbus_RTU_CB->pModbus_RTU->parentObj=NULL; + errRes= ERR_NONE; + goto _exit; + } + }else if(pModbus_RTU_CB->sendFlag==1 || pModbus_RTU_CB->sendFlag==3){/*�Ѿ������ˣ����ǻ�û�յ���������ִ�г�ʱ���*/ + /*Receive timeout detection*/ + if(pModbus_RTU_CB->pModbus_RTU->timesTick-pModbus_RTU_CB->sendTimeTick + >=pModbus_RTU_CB->sendOverTime){ + /*Set the start point of timeout*/ + pModbus_RTU_CB->sendTimeTick=pModbus_RTU_CB->pModbus_RTU->timesTick; + /*Resend*/ + pModbus_RTU_CB->sendFlag=0; + /*Increase the number of retransmissions by 1*/ + pModbus_RTU_CB->RTCount++; + + /*Release channel*/ + pModbus_RTU_CB->pModbus_RTU->parentObj=NULL; + + if(pModbus_RTU_CB->RTCount>=pModbus_RTU_CB->RTTimes){ + /*The number of retransmissions exceeded*/ + errRes= ERR_RW_OV_TIME_ERR; + if(MD_CB_GET_DIS_FLAG_EN(pModbus_RTU_CB)){/*No polling when disconnected is enabled*/ + MD_CB_SET_DIS_FLAG(pModbus_RTU_CB);/*Device disconnection*/ + } + goto _exit; + } + /*Timed out*/ + errRes= ERR_OVER_TIME; + goto _exit; + } + } + }else { + /*The number of retransmissions exceeded*/ + errRes= ERR_RW_OV_TIME_ERR; + goto _exit; + } + + if(pModbus_RTU_CB->sendFlag==1){/*If it has been sent, it will return the sending completion flag*/ + return ERR_SEND_FIN; + } +_exit: +// MD_CLR_SENDED_FLAG(pModbus_RTU_CB); +// if(errRes == ERR_RW_FIN){ +// pModbus_RTU_CB->RTCount=0; +// } + /*Release channel*/ + pModbus_RTU_CB->pModbus_RTU->parentObj=NULL; + return errRes; +} +/******************************************************* +* +* Function name :MDM_RTU_RW +* Description :Blocking read and write +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @funCode Function code, see [ModbusFunCode] +* @slaveAddr Slave address +* @startAddr Read and write start address +* @numOf Number of read and write data +* @wData If it is a write function code, then it is the written data +* Return : See [MDError] +**********************************************************/ +static MDError MDM_RTU_RW( + PModbus_RTU_CB pModbus_RTU_CB, + ModbusFunCode funCode, + uint8 slaveAddr, + uint16 startAddr, + uint16 numOf, + void *wData +){ + MDError res; + void* tempObj; + if(pModbus_RTU_CB==NULL){ + return ERR_VOID; + } + MD_RTU_LOCK((PModbusBase)(pModbus_RTU_CB->pModbus_RTU),MD_RTU_LOCK_OBJ1_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + tempObj=pModbus_RTU_CB->pModbus_RTU->parentObj; + pModbus_RTU_CB->pModbus_RTU->parentObj=NULL;/*Set to empty, so that non-blocking and blocking can be mixed calls*/ + do{ + res = MDM_RTU_NB_RW(pModbus_RTU_CB,funCode,slaveAddr,startAddr,numOf,wData); + if(res != ERR_RW_FIN){ /*An error occurred*/ + if(res == ERR_RW_OV_TIME_ERR){ /*Retransmission timed out*/ + MDM_RTU_CB_OverTimeReset(pModbus_RTU_CB);/*Enable retransmission*/ + goto exit; + }else if(res==ERR_DEV_DIS){ + goto exit; + } + } + #if MD_RTU_USED_OS + MD_RTU_Delay(5); + #endif + }while(res!=ERR_RW_FIN); + MDM_RTU_CB_OverTimeReset(pModbus_RTU_CB); + exit: + pModbus_RTU_CB->pModbus_RTU->parentObj=tempObj;/*Restore settings*/ + MD_RTU_UNLOCK((PModbusBase)(pModbus_RTU_CB->pModbus_RTU),MD_RTU_LOCK_OBJ1_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + return res; +} +/** +* Clear the RTU parameters. +*/ +void ModubusRTUClear(PModbus_RTU pOldModbus){ + pOldModbus->lastTimesTick=0xFFFFFFF; + pOldModbus->recvFlag=0; + pOldModbus->serialSendCount=0; + pOldModbus->mdSqQueue.rear=pOldModbus->mdSqQueue.front=0; + pOldModbus->mdSqQueue.valid = TRUE; +} +/******************************************************* +* +* Function name :MDM_RTU_RW_ex +* Description :Blocking read and write +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @funCode Function code, see [ModbusFunCode] +* @slaveAddr Slave address +* @startAddr Read and write start address +* @numOf Number of read and write data +* @wData If it is a write function code, then it is the written data +* Return : See [MDError] +**********************************************************/ +static MDError MDM_RTU_RW_MIX( + PModbus_RTU_CB pModbus_RTU_CB, + ModbusFunCode funCode, + uint8 slaveAddr, + uint16 startAddr, + uint16 numOf, + void *wData +){ + MDError res; + void* tempObj; + if(pModbus_RTU_CB==NULL){ + return ERR_VOID; + } + MD_RTU_LOCK((PModbusBase)(pModbus_RTU_CB->pModbus_RTU),MD_RTU_LOCK_OBJ1_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + + tempObj=pModbus_RTU_CB->pModbus_RTU->parentObj; + pModbus_RTU_CB->pModbus_RTU->parentObj=NULL;/*Set to empty, so that non-blocking and blocking can be mixed calls*/ + if (pModbus_RTU_CB->pModbus_RTU->blockMode){ + /* + * Last time in non-blocking mode. + * If the mode was previously non-blocking, all states need to + * be cleared and a delay may be required, + * as data may have been sent previously. + */ + ModubusRTUClear(pModbus_RTU_CB->pModbus_RTU); + MDM_RTU_CB_OverTimeReset(pModbus_RTU_CB); + MD_RTU_Delay(MDM_MIX_CALL_DELAY); + } + pModbus_RTU_CB->pModbus_RTU->blockMode=0;/*Currently in blocking mode*/ + do{ + res = MDM_RTU_NB_RW(pModbus_RTU_CB,funCode,slaveAddr,startAddr,numOf,wData); + if(res != ERR_RW_FIN){ /*An error occurred*/ + if(res == ERR_RW_OV_TIME_ERR){ /*Retransmission timed out*/ + MDM_RTU_CB_OverTimeReset(pModbus_RTU_CB);/*Enable retransmission*/ + goto exit; + }else if(res==ERR_DEV_DIS){ + goto exit; + } + } + #if MD_RTU_USED_OS + MD_RTU_Delay(5); + #endif + }while(res!=ERR_RW_FIN); + MDM_RTU_CB_OverTimeReset(pModbus_RTU_CB); + exit: + ModubusRTUClear(pModbus_RTU_CB->pModbus_RTU); + pModbus_RTU_CB->pModbus_RTU->parentObj=tempObj;/*Restore settings*/ + MD_RTU_UNLOCK((PModbusBase)(pModbus_RTU_CB->pModbus_RTU),MD_RTU_LOCK_OBJ1_HANDLE_ARG((pModbus_RTU_CB->pModbus_RTU))); + return res; +} +/******************************************************* +* +* Function name :MDM_RTU_ReadCoil +* Description :Read coil +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @numOf Number of read data +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_ReadCoil(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf){ + return MDM_RTU_RW(pModbus_RTU_CB,READ_COIL,slaveAddr,startAddr,numOf,NULL); +} +/******************************************************* +* +* Function name :MDM_RTU_ReadInput +* Description :Read input +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @numOf Number of read data +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_ReadInput(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf){ + return MDM_RTU_RW(pModbus_RTU_CB,READ_INPUT,slaveAddr,startAddr,numOf,NULL); +} +/******************************************************* +* +* Function name :MDM_RTU_ReadHoldReg +* Description :Read holding register +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @numOf Number of read data +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_ReadHoldReg(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf){ + return MDM_RTU_RW(pModbus_RTU_CB,READ_HOLD_REG,slaveAddr,startAddr,numOf,NULL); +} +/******************************************************* +* +* Function name :MDM_RTU_ReadInputReg +* Description :Read input register +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @numOf Number of read data +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_ReadInputReg(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf){ + return MDM_RTU_RW(pModbus_RTU_CB,READ_INPUT_REG,slaveAddr,startAddr,numOf,NULL); +} +/******************************************************* +* +* Function name :MDM_RTU_WriteSingleCoil +* Description :Write a single coil +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @boolVal TRUE , FALSE +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_WriteSingleCoil( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,BOOL boolVal){ + uint16 temp; + temp=boolVal?0xFF00:0x0000; + return MDM_RTU_RW(pModbus_RTU_CB,WRITE_SIN_COIL,slaveAddr,startAddr,1,(void*)(&temp)); +} +/******************************************************* +* +* Function name :MDM_RTU_WriteSingleReg +* Description :Write a single register +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @boolVal TRUE , FALSE +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_WriteSingleReg( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 val){ + return MDM_RTU_RW(pModbus_RTU_CB,WRITE_SIN_REG,slaveAddr,startAddr,1,(void*)(&val)); +} + +/******************************************************* +* +* Function name :MDM_RTU_WriteCoils +* Description :Write coil +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @numOf Number of write data +* @boolVal TRUE , FALSE +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_WriteCoils( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf,uint8* val){ + return MDM_RTU_RW(pModbus_RTU_CB,WRITE_COILS,slaveAddr,startAddr,numOf,(void*)(val)); +} +/******************************************************* +* +* Function name :MDM_RTU_WriteRegs +* Description :Write register +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @numOf Number of write data +* @boolVal TRUE , FALSE +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_WriteRegs( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf,uint16* val){ + return MDM_RTU_RW(pModbus_RTU_CB,WRITE_REGS,slaveAddr,startAddr,numOf,(void*)(val)); +} + + +/******************************************************* +* +* Function name :MDM_RTU_MixReadCoil +* Description :Read coil +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @numOf Number of read data +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_MixReadCoil(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf){ + return MDM_RTU_RW_MIX(pModbus_RTU_CB,READ_COIL,slaveAddr,startAddr,numOf,NULL); +} +/******************************************************* +* +* Function name :MDM_RTU_MixReadInput +* Description :Read input +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @numOf Number of read data +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_MixReadInput(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf){ + return MDM_RTU_RW_MIX(pModbus_RTU_CB,READ_INPUT,slaveAddr,startAddr,numOf,NULL); +} +/******************************************************* +* +* Function name :MDM_RTU_MixReadHoldReg +* Description :Read holding register +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @numOf Number of read data +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_MixReadHoldReg(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf){ + return MDM_RTU_RW_MIX(pModbus_RTU_CB,READ_HOLD_REG,slaveAddr,startAddr,numOf,NULL); +} +/******************************************************* +* +* Function name :MDM_RTU_MixReadInputReg +* Description :Read input register +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @numOf Number of read data +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_MixReadInputReg(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf){ + return MDM_RTU_RW_MIX(pModbus_RTU_CB,READ_INPUT_REG,slaveAddr,startAddr,numOf,NULL); +} +/******************************************************* +* +* Function name :MDM_RTU_MixWriteSingleCoil +* Description :Write a single coil +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @boolVal TRUE , FALSE +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_MixWriteSingleCoil( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,BOOL boolVal){ + uint16 temp; + temp=boolVal?0xFF00:0x0000; + return MDM_RTU_RW_MIX(pModbus_RTU_CB,WRITE_SIN_COIL,slaveAddr,startAddr,1,(void*)(&temp)); +} +/******************************************************* +* +* Function name :MDM_RTU_MixWriteSingleReg +* Description :Write a single register +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @boolVal TRUE , FALSE +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_MixWriteSingleReg( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 val){ + return MDM_RTU_RW_MIX(pModbus_RTU_CB,WRITE_SIN_REG + ,slaveAddr,startAddr,1,(void*)(&val)); +} + +/******************************************************* +* +* Function name :MDM_RTU_MixWriteCoils +* Description :Write coil +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @numOf Number of write data +* @boolVal TRUE , FALSE +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_MixWriteCoils( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf,uint8* val){ + return MDM_RTU_RW_MIX(pModbus_RTU_CB,WRITE_COILS,slaveAddr,startAddr,numOf,(void*)(val)); +} +/******************************************************* +* +* Function name :MDM_RTU_MixWriteRegs +* Description :Write register +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @numOf Number of write data +* @boolVal TRUE , FALSE +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_MixWriteRegs( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf,uint16* val){ + return MDM_RTU_RW_MIX(pModbus_RTU_CB,WRITE_REGS,slaveAddr,startAddr,numOf,(void*)(val)); +} + +/******************************************************* +* +* Function name :MDM_RTU_ReadCoil +* Description :Non-blocking read coil +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @numOf Number of read data +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_NB_ReadCoil(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf){ + return MDM_RTU_NB_RW(pModbus_RTU_CB,READ_COIL,slaveAddr,startAddr,numOf,NULL); +} +/******************************************************* +* +* Function name :MDM_RTU_ReadInput +* Description :Non-blocking read input +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @numOf Number of read data +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_NB_ReadInput(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf){ + return MDM_RTU_NB_RW(pModbus_RTU_CB,READ_INPUT,slaveAddr,startAddr,numOf,NULL); +} +/******************************************************* +* +* Function name :MDM_RTU_ReadHoldReg +* Description :Non-blocking read holding register +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @numOf Number of read data +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_NB_ReadHoldReg(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf){ + return MDM_RTU_NB_RW(pModbus_RTU_CB,READ_HOLD_REG,slaveAddr,startAddr,numOf,NULL); +} +/******************************************************* +* +* Function name :MDM_RTU_ReadHoldReg +* Description :Non-blocking read input register +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @numOf Number of read data +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_NB_ReadInputReg(PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf){ + return MDM_RTU_NB_RW(pModbus_RTU_CB,READ_INPUT_REG,slaveAddr,startAddr,numOf,NULL); +} +/******************************************************* +* +* Function name :MDM_RTU_WriteSingleCoil +* Description :Non-blocking write single coil +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @boolVal TRUE , FALSE +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_NB_WriteSingleCoil( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,BOOL boolVal){ + uint16 temp; + temp=boolVal?0xFF00:0x0000; + return MDM_RTU_NB_RW(pModbus_RTU_CB,WRITE_SIN_COIL,slaveAddr,startAddr,1,(void*)(&temp)); +} +/******************************************************* +* +* Function name :MDM_RTU_WriteSingleReg +* Description :Non-blocking write to a single register +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @boolVal TRUE , FALSE +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_NB_WriteSingleReg( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 val){ + return MDM_RTU_NB_RW(pModbus_RTU_CB,WRITE_SIN_REG,slaveAddr,startAddr,1,(void*)(&val)); +} +/******************************************************* +* +* Function name :MDM_RTU_WriteCoils +* Description :Non-blocking write coil +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @numOf Number of write data +* @boolVal TRUE , FALSE +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_NB_WriteCoils( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf,uint8* val){ + return MDM_RTU_NB_RW(pModbus_RTU_CB,WRITE_COILS,slaveAddr,startAddr,numOf,(void*)(val)); +} +/******************************************************* +* +* Function name :MDM_RTU_WriteRegs +* Description :Non-blocking write register +* Parameter : +* @pModbus_RTU_CB Write control block object pointer +* @slaveAddr Slave address +* @startAddr Read start address +* @numOf Number of write data +* @boolVal TRUE , FALSE +* Return : See [MDError] +**********************************************************/ +MDError MDM_RTU_NB_WriteRegs( + PModbus_RTU_CB pModbus_RTU_CB,uint8 slaveAddr,uint16 startAddr,uint16 numOf,uint16* val){ + return MDM_RTU_NB_RW(pModbus_RTU_CB,WRITE_REGS,slaveAddr,startAddr,numOf,(void*)(val)); +} + diff --git a/mkrtos_user/lib/modbus/src/modbus_rtu_master/MDM_RTU_RW_Man.c b/mkrtos_user/lib/modbus/src/modbus_rtu_master/MDM_RTU_RW_Man.c new file mode 100644 index 000000000..433a74b40 --- /dev/null +++ b/mkrtos_user/lib/modbus/src/modbus_rtu_master/MDM_RTU_RW_Man.c @@ -0,0 +1,158 @@ +/******************************************************************************** + * @File name: MD_RTU_RW_Man.c + * @Author: zspace + * @Email: 1358745329@qq.com + * @Version: 1.0 + * @Date: 2020-10-22 + * @Description: ???? + ********************************************************************************/ + +#include "MDM_RTU_RW_Man.h" +#include "MDM_RTU_Fun.h" +#include "MD_RTU_Tool.h" + +MDM_RW_Ctrl MDM_RW_CtrlList[MDM_RW_CTRL_LIST_SIZE] = { 0 }; + +/******************************************************* + * + * Function name: MDM_RW_CtrlNew + * Description: Create a new control block + * Parameter: + * None + * Return: New control block + **********************************************************/ +static PMDM_RW_Ctrl MDM_RW_CtrlNew(void) { + uint16 i; + for (i = 0; i < MDM_RW_CTRL_LIST_SIZE; i++) { + if (!MD_GET_BIT(MDM_RW_CtrlList[i].flag, 0)) { + MD_SET_BIT(MDM_RW_CtrlList[i].flag, 0); + return &(MDM_RW_CtrlList[i]); + } + } + return NULL; +} + +/******************************************************* + * + * Function name: MDM_RW_CtrlFindByFunAddr + * Description: Find the control block by the function address + * Parameter: + * @cbFun A function pointer + * Return: Found function control block + ******************************************************/ +static PMDM_RW_Ctrl MDM_RW_CtrlFindByFunAddr(MDMSendReadCallBack cbFun) { + uint16 i; + for (i = 0; i < MDM_RW_CTRL_LIST_SIZE; i++) { + if (MD_GET_BIT(MDM_RW_CtrlList[i].flag, 0)) { + if (MDM_RW_CtrlList[i].MDMSendReadFun == cbFun) { + return &(MDM_RW_CtrlList[i]); + } + } + } + return NULL; +} + +/******************************************************* + * + * Function name: MDM_RW_CtrlDelRW + * Description: Delete a RW interface + * Parameter: + * @pMDM_RW_Ctrl Which control block's interface needs to be removed + * Return: None + ******************************************************/ +void MDM_RW_CtrlDelRW(PMDM_RW_Ctrl pMDM_RW_Ctrl) { + if (pMDM_RW_Ctrl == NULL) { + return; + } + pMDM_RW_Ctrl->arg = NULL; + pMDM_RW_Ctrl->flag = 0; + pMDM_RW_Ctrl->MDMSendReadFun = NULL; + pMDM_RW_Ctrl->RWCtrlName = NULL; +} + +/******************************************************* + * + * Function name: MDM_RW_CtrlAddRW + * Description: Add a read-write + * Parameter: + * @cbFun A function that is called in a loop + * @arg The parameters passed to the function + * @RWCtrlName Name of the control block + * Return: Returns a control block to the user + ******************************************************/ +PMDM_RW_Ctrl MDM_RW_CtrlAddRW(MDMSendReadCallBack cbFun, void *arg, const char *RWCtrlName) { + PMDM_RW_Ctrl pMDM_RW_Ctrl = MDM_RW_CtrlNew(); + if (pMDM_RW_Ctrl == NULL) { + return NULL; + } + pMDM_RW_Ctrl->MDMSendReadFun = cbFun; + pMDM_RW_Ctrl->RWCtrlName = RWCtrlName; + pMDM_RW_Ctrl->arg = arg; + return pMDM_RW_Ctrl; +} + +/******************************************************* + * + * Function name: MDM_RW_CtrlSetRWOnceFlag + * Description: Set whether to send once or cyclically + * Parameter: + * @pMDM_RW_Ctrl A pointer to a control block object + * @flag Whether read only or write once + * Return: None + ******************************************************/ +void MDM_RW_CtrlSetRWOnceFlag(PMDM_RW_Ctrl pMDM_RW_Ctrl, BOOL flag) { + if (pMDM_RW_Ctrl == NULL) { + return; + } + if (flag) { + MD_SET_BIT(pMDM_RW_Ctrl->flag, 1); + } else { + MD_CLR_BIT(pMDM_RW_Ctrl->flag, 1); + } +} + +/******************************************************* + * + * Function name: MDM_RW_CtrlResetRetranFlag + * Description: Reset slave offline flag + * Parameter: + * @pMDM_RW_Ctrl A pointer to a control block object + * Return: None + ******************************************************/ +void MDM_RW_CtrlResetRetranFlag(PMDM_RW_Ctrl pMDM_RW_Ctrl) { + if (pMDM_RW_Ctrl == NULL) { + return; + } + MD_CLR_BIT(pMDM_RW_Ctrl->flag, 7); +} + +/******************************************************* + * + * Function name: MDM_RW_CtrlLoop + * Description: This function cyclically processes the host bare-metal transceiver control function + * Parameter: + * None + * Return: None + ******************************************************/ +void MDM_RW_CtrlLoop(void) { + uint16 i; + MDM_RW_CtrlErr res; + for (i = 0; i < MDM_RW_CTRL_LIST_SIZE; i++) { + if (MD_GET_BIT(MDM_RW_CtrlList[i].flag,0) && (!MD_GET_BIT(MDM_RW_CtrlList[i].flag, 7)) // If the slave is disconnected or a single transmission is completed, it will no longer be traversed + ) { + if (MDM_RW_CtrlList[i].MDMSendReadFun == NULL) { + continue; + } + + res = MDM_RW_CtrlList[i].MDMSendReadFun(MDM_RW_CtrlList[i].arg); // Loop call + if (res == RW_ERR) { // Do not send if sending fails + MD_SET_BIT(MDM_RW_CtrlList[i].flag, 7); + } + if (res != RW_NONE) { // Single send and send success or failure + if (MD_GET_BIT(MDM_RW_CtrlList[i].flag, 1)) { // Single send + MD_SET_BIT(MDM_RW_CtrlList[i].flag, 7); + } + } + } + } +} diff --git a/mkrtos_user/lib/modbus/src/modbus_rtu_master/MDM_RTU_User_Fun.c b/mkrtos_user/lib/modbus/src/modbus_rtu_master/MDM_RTU_User_Fun.c new file mode 100644 index 000000000..d6040e772 --- /dev/null +++ b/mkrtos_user/lib/modbus/src/modbus_rtu_master/MDM_RTU_User_Fun.c @@ -0,0 +1,103 @@ +/******************************************************************************** +* @File name: MD_RTU_User_Fun.c +* @Author: zspace +* @Emial: 1358745329@qq.com +* @Version: 1.0 +* @Date: 2020-4-10 +* @Description: Modbus RTU Host user call function +* Open source address: https://github.com/lotoohe-space/XTinyModbus +********************************************************************************/ + +/*********************************HEAD FILE************************************/ +#include "MDM_RTU_User_Fun.h" +#include "MDM_RTU_Fun.h" +/*********************************END******************************************/ + +/******************************************************* +* +* Function name :MDM_RTU_ReadBits +* Description :Read discretely mapped bits, you can read one or multiple +* Parameter : +* @obj Host object pointer +* @modbusAddr modbus address +* @numOf The number to be read +* @opAddrType Address type(COILS_TYPE,INPUT_TYPE),See[AddrType] +* @devAddr Slave number to be read +* Return : +* @res Returned value TRUE success , FALSE fail +**********************************************************/ +BOOL MDM_RTU_ReadBits(void* obj,uint16 modbusAddr,uint16 numOf, uint8 *res, AddrType opAddrType,uint8 devAddr){ + uint16 i; + PModbus_RTU pModbusS_RTU = obj; + if(pModbusS_RTU==NULL){return FALSE;} + if(opAddrType != COILS_TYPE && opAddrType != INPUT_TYPE){return FALSE;} + + for(i=0;ipMapTableList[i]==NULL){ + continue; + } + /*Check the device number*/ + if(devAddr!=pModbusS_RTU->pMapTableList[i]->devAddr){continue;} + + if(pModbusS_RTU->pMapTableList[i]->modbusAddr<=modbusAddr&& + (pModbusS_RTU->pMapTableList[i]->modbusAddr+pModbusS_RTU->pMapTableList[i]->modbusDataSize)>=(modbusAddr+numOf) + ){ + if(pModbusS_RTU->pMapTableList[i]->addrType==opAddrType){/*Must be Bit type*/ + uint16 j; + uint16 offsetAddr=modbusAddr-MDS_RTU_REG_COIL_ITEM_ADDR(pModbusS_RTU->pMapTableList[i]); + for(j=offsetAddr; jpMapTableList[i])[j>>4],j%16) + ){ + MD_SET_BIT(res[j>>3],j%8); + }else{ + MD_CLR_BIT(res[j>>3],j%8); + } + } + return TRUE; + } + } + } + return FALSE; +} +/******************************************************* +* +* Function name :MDM_RTU_ReadRegs +* Description :Read discretely mapped registers, you can read one or multiple +* Parameter : +* @obj Host object pointer +* @modbusAddr modbus address +* @numOf The number to be read +* @opAddrType Address type(HOLD_REGS_TYPE,INPUT_REGS_TYPE),See[AddrType] +* @devAddr Slave number to be read +* Return : +* @res TRUE success , FALSE fail +**********************************************************/ +BOOL MDM_RTU_ReadRegs(void* obj,uint16 modbusAddr,uint16 numOf, uint16 *res, AddrType opAddrType,uint8 devAddr){ + uint16 i; + PModbus_RTU pModbusS_RTU = obj; + if(pModbusS_RTU==NULL){return FALSE;} + if(opAddrType != HOLD_REGS_TYPE && opAddrType != INPUT_REGS_TYPE){return FALSE;} + + for(i=0;ipMapTableList[i]==NULL){ + continue; + } + /*Check the device number*/ + if(devAddr!=pModbusS_RTU->pMapTableList[i]->devAddr){continue;} + if(pModbusS_RTU->pMapTableList[i]->modbusAddr<=modbusAddr&& + (pModbusS_RTU->pMapTableList[i]->modbusAddr+pModbusS_RTU->pMapTableList[i]->modbusDataSize)>=(modbusAddr+numOf) + ){ + if(pModbusS_RTU->pMapTableList[i]->addrType==opAddrType){/*Must be BIT type*/ + uint16 j; + uint16 offsetAddr=modbusAddr-MDS_RTU_REG_COIL_ITEM_ADDR(pModbusS_RTU->pMapTableList[i]); + for(j=0;jpMapTableList[i])[offsetAddr+j]; + } + return TRUE; + } + } + } + return FALSE; +} diff --git a/mkrtos_user/lib/modbus/src/modbus_rtu_slave/MDS_RTU_Fun.c b/mkrtos_user/lib/modbus/src/modbus_rtu_slave/MDS_RTU_Fun.c new file mode 100644 index 000000000..48dc9851b --- /dev/null +++ b/mkrtos_user/lib/modbus/src/modbus_rtu_slave/MDS_RTU_Fun.c @@ -0,0 +1,695 @@ +/******************************************************************************** + * @File name: MD_RTU_Fun.c + * @Author: zspace + * @Emial: 1358745329@qq.com + * @Version: 1.0 + * @Date: 2020-4-10 + * @Description: Modbus RTU Slave slave receiving function. + ********************************************************************************/ + +/*********************************HEAD FILE************************************/ +#include "MDS_RTU_Fun.h" +#include "MD_RTU_CRC16.h" +// #include "MDS_RTU_Serial.h" +#include "MDS_RTU_User_Fun.h" +/*********************************END******************************************/ + +/**********************************FUNCTION DECLARATION*************************************/ +void MDS_RTU_RecvByte(void *obj, uint8 byte); +void MDS_RTU_TimeHandler(void *obj, uint32 times); + +static void MDS_RTU_SendErrorCode(PModbusS_RTU pModbus_RTU, ANLCode anlCode, ErrorCode errCode); +uint8 MDS_RTU_ReadDataProcess(PModbusS_RTU pModbus_RTU, uint16 reg, uint16 regNum, uint8 funCode); +uint8 MDS_RTU_WriteDataProcess(PModbusS_RTU pModbus_RTU, uint16 reg, uint16 regNum, uint8 funCode, uint16 *data, uint8 byteCount); +/*********************************END******************************************/ + +/******************************************************* + * + * Function name :MDS_RTU_Init + * Description :Initialize a slave + * Parameter : + * @pModbusRTU Slave structure pointer + * @mdRTUSerialInitFun Hardware serial port initialization function + * @salveAddr Slave address + * @baud Baud rate + * @dataBits Data bit + * @stopBits Stop bit + * @parity Parity bit + * Return : None + **********************************************************/ +void MDS_RTU_Init(PModbusS_RTU pModbusRTU, MD_RTU_SerialInit mdRTUSerialInitFun, uint8 salveAddr, + uint32 baud, uint8 dataBits, uint8 stopBits, uint8 parity) +{ + uint8 i; + float T; + if (pModbusRTU == NULL) + { + return; + } + /*Init is queue.*/ + pModbusRTU->mdMsgSqQueue.data = NULL; + pModbusRTU->mdMsgSqQueue.maxVal = 0; + pModbusRTU->mdSqQueue.data = NULL; + pModbusRTU->mdSqQueue.maxVal = 0; + + pModbusRTU->salveAddr = salveAddr; + pModbusRTU->serialReadCount = 0; +#if MDS_USE_SEND_CACHE + pModbusRTU->serialSendCount = 0; +#endif + for (i = 0; i < MDS_REG_COIL_ITEM_NUM; i++) + { + pModbusRTU->pMapTableList[i] = NULL; + } + + TO_MDBase(pModbusRTU)->mdRTUTimeHandlerFunction = MDS_RTU_TimeHandler; + TO_MDBase(pModbusRTU)->mdRTURecByteFunction = MDS_RTU_RecvByte; + TO_MDBase(pModbusRTU)->mdRTUSendBytesFunction = NULL; + TO_MDBase(pModbusRTU)->mdRTURecSendConv = NULL; + + pModbusRTU->mdsWriteFun = NULL; + pModbusRTU->lastTimesTick = 0xFFFFFFFF; + pModbusRTU->lastSendTimes = 0x00000000; + pModbusRTU->timesTick = 0x00000000; + + T = (1.0 / (float)baud) * 100000; // 100us + uint16 time = 0; + time = T * (dataBits + (parity ? 1 : 0)); + if (stopBits == 0) + { + time += T; + } + else if (stopBits == 1) + { + time += T * 1.5f; + } + else if (stopBits == 2) + { + time += T * 2; + } + pModbusRTU->frameIntervalTime = time; /*This parameter needs to be set according to the baud rate*/ + + pModbusRTU->CRC16Update = 0xFFFF; + + if (mdRTUSerialInitFun != NULL) + { + mdRTUSerialInitFun(pModbusRTU, baud, dataBits, stopBits, parity); + } + return; +} +/** + * @brief This function init queue. + * @param[in] recvQueueData ???? + * @param[in] recvQueueSize ???? + * @param[in] msgProcessQueueData ???? + * @param[in] msgProcessQueueSize ???? + * @result None + */ +void MDS_RTU_QueueInit(PModbusS_RTU pModbus_RTU, + uint8 *recvQueueData, + uint16 recvQueueSize, + uint8 *msgProcessQueueData, + uint16 msgProcessQueueSize) +{ + if (pModbus_RTU == NULL) + { + return; + } + MDInitQueue(&(pModbus_RTU->mdSqQueue), recvQueueData, recvQueueSize); + MDInitQueue(&(pModbus_RTU->mdMsgSqQueue), msgProcessQueueData, msgProcessQueueSize); +} +/******************************************************* + * + * Function name :MDS_RTU_SetWriteListenFun + * Description :This function can set a callback function, when the master writes the slave address, the set function will be called. + * Parameter : + * @pModbus_RTU Object pointer of slave + * @wFun Set callback function + * Return : �� + **********************************************************/ +void MDS_RTU_SetWriteListenFun(PModbusS_RTU pModbus_RTU, MDSWriteFunciton wFun) +{ + if (pModbus_RTU == NULL) + { + return; + } + pModbus_RTU->mdsWriteFun = wFun; +} +/******************************************************* + * + * Function name :MDS_RTU_TimeHandler + * Description :This function needs to be called in the timer interrupt, the interrupt interval time is 100US. + * Parameter : + * @obj Object pointer of slave + * Return : None + **********************************************************/ +void MDS_RTU_TimeHandler(void *obj, uint32 times) +{ + uint32 tempTick = 0; + uint8 overFlag = 0; + PModbusS_RTU pModbusRTU = obj; + if (!pModbusRTU) + { + return; + } + + // pModbusRTU->timesTick++; + pModbusRTU->timesTick = times; + + if (pModbusRTU->timesTick == 0xFFFFFFFF) + { /*Overflowed pModbusRTU->lastTimesTick==0xFFFFFFFF*/ + tempTick = 0xFFFFFFFF - pModbusRTU->lastSendTimes; + pModbusRTU->timesTick = tempTick; /*System time offset*/ + pModbusRTU->lastSendTimes = 0; /*Clear the last sending time*/ + overFlag = 1; + } + + if (pModbusRTU->lastTimesTick == 0xFFFFFFFF) + { + return; + } /*Has started receiving packets*/ + if (overFlag) + { + pModbusRTU->timesTick += 0xFFFFFFFF - pModbusRTU->lastTimesTick; /*Time offset when sending*/ + pModbusRTU->lastTimesTick = tempTick; + } + if ((pModbusRTU->timesTick - pModbusRTU->lastTimesTick >= pModbusRTU->frameIntervalTime)) + { + uint16 msgLen; + uint16 i; + uint8 byte; + if (pModbusRTU->CRC16Update != 0x0000) + { + /*CRC error*/ + MDResetQueue(&(pModbusRTU->mdSqQueue)); + pModbusRTU->lastTimesTick = 0xFFFFFFFF; + return; + } + /*End of one frame*/ + /*The messages of the data processing queue are moved to the message processing queue*/ + msgLen = MDQueueLength(&(pModbusRTU->mdSqQueue)); + MDenQueue(&(pModbusRTU->mdMsgSqQueue), &msgLen, UINT8_TYPE); /*Save frame length*/ + for (i = 0; i < msgLen; i++) + { + /*take out*/ + if (MDdeQueue(&(pModbusRTU->mdSqQueue), &byte, UINT8_TYPE) == FALSE) + { + return; + } + /*put in*/ + if (MDenQueue(&(pModbusRTU->mdMsgSqQueue), &byte, UINT8_TYPE) == FALSE) + { + return; + } + } + pModbusRTU->lastTimesTick = 0xFFFFFFFF; + } +} + +/******************************************************* + * + * Function name :MDS_RTU_RecvByte + * Description :This function is called in the serial port interrupt, when a byte is received, this function is called + * Parameter : + * @obj Object pointer of slave + * @byte Single byte received + * Return : None + **********************************************************/ +void MDS_RTU_RecvByte(void *obj, uint8 byte) +{ + PModbusS_RTU pModbusRTU = obj; + if (!pModbusRTU) + { + return; + } + /*Put in the queue here*/ + if (MDenQueue(&(pModbusRTU->mdSqQueue), &byte, UINT8_TYPE) == FALSE) + { + return; + } + if (pModbusRTU->lastTimesTick == 0xFFFFFFFF) + { + pModbusRTU->CRC16Update = 0xFFFF; + } + pModbusRTU->CRC16Update = MD_CRC16Update(pModbusRTU->CRC16Update, byte); + /*Save the timestamp of the last character received*/ + pModbusRTU->lastTimesTick = pModbusRTU->timesTick; +} +/******************************************************* + * + * Function name :MDS_RTU_AddMapItem + * Description :This function adds a mapping record to the discrete mapping table. + * Parameter : + * @obj Object pointer of slave + * @byte Mapping item added + * Return : None + **********************************************************/ +BOOL MDS_RTU_AddMapItem(PModbusS_RTU pModbusRTU, PMapTableItem pMapTableItem) +{ + if (pModbusRTU == NULL || pMapTableItem == NULL) + { + return FALSE; + } + return MapTableAdd(pModbusRTU->pMapTableList, pMapTableItem, MDS_REG_COIL_ITEM_NUM); +} +#if !MDS_USE_SEND_CACHE +/******************************************************* + * + * Function name :MDS_RTU_SendByte + * Description :Slave sends a byte + * Parameter : + * @pModbusRTU Object pointer of slave + * @byte Bytes to be sent + * Return : TRUE success , FALSE fail + **********************************************************/ +static void MDS_RTU_SendByte(PModbusS_RTU pModbusRTU, uint8 byte) +{ + if (!pModbusRTU) + { + return; + } + TO_MDBase(pModbusRTU)->mdRTUSendBytesFunction(&byte, 1); +} +#endif +/******************************************************* + * + * Function name :MDS_RTU_SerialProcess + * Description :This function is called internally to get a packet data received. + * Parameter : + * @pModbus_RTU Object pointer of slave + * Return : None + **********************************************************/ +static BOOL MDS_RTU_SerialProcess(PModbusS_RTU pModbus_RTU) +{ + uint8 byte; + uint8 recvLen; + uint16 i; + if (!pModbus_RTU) + { + return FALSE; + } + + if (MDdeQueue(&(pModbus_RTU->mdMsgSqQueue), &recvLen, UINT8_TYPE) == FALSE) + { + return FALSE; + } + for (i = 0; i < recvLen; i++) + { + /*Read a byte from the queue*/ + if (MDdeQueue(&(pModbus_RTU->mdMsgSqQueue), &byte, UINT8_TYPE) == FALSE) + { + return FALSE; + } + if (pModbus_RTU->serialReadCount > MDS_RTU_CMD_SIZE - 1) + { /**/ + continue; + } + pModbus_RTU->serialReadCache[pModbus_RTU->serialReadCount] = byte; /*save a byte*/ + pModbus_RTU->serialReadCount++; + } + + if (pModbus_RTU->serialReadCount >= 1) + { /*Function code has been read*/ + if (pModbus_RTU->serialReadCache[1] == 1 || pModbus_RTU->serialReadCache[1] == 2 || pModbus_RTU->serialReadCache[1] == 3 || pModbus_RTU->serialReadCache[1] == 4 || pModbus_RTU->serialReadCache[1] == 5 || pModbus_RTU->serialReadCache[1] == 6) + { + if (pModbus_RTU->serialReadCount == 8) + { + return TRUE; + } + } + else if (pModbus_RTU->serialReadCache[1] == 15 || pModbus_RTU->serialReadCache[1] == 16) + { + if (pModbus_RTU->serialReadCount >= 9) + { + uint8 bytesNum = MDS_RTU_BYTES_NUM(pModbus_RTU); + if (bytesNum + 9 == pModbus_RTU->serialReadCount) + { + return TRUE; + } + } + } + else + { + return FALSE; + } + } + + return TRUE; +} +/******************************************************* + * + * Function name :MDS_RTU_Process + * Description :This function processes the received packet data + * Parameter : + * @pModbus_RTU Object pointer of slave + * Return : None + **********************************************************/ +void MDS_RTU_Process(PModbusS_RTU pModbus_RTU) +{ + BOOL res; + if (!pModbus_RTU) + { + return; + } + + if (pModbus_RTU->timesTick - pModbus_RTU->lastSendTimes < pModbus_RTU->frameIntervalTime) + { + /*Frame interval time, 3.5T processing one frame*/ + return; + } + + res = MDS_RTU_SerialProcess(pModbus_RTU); /*Read an instruction from the queue*/ + if (!res) + { + goto __exit; + } + + if ( + !(pModbus_RTU->serialReadCache[0] == 0x00 /*Broadcast address*/ + || + pModbus_RTU->serialReadCache[0] == pModbus_RTU->salveAddr)) + { + /*Not belong to this slave, discard*/ + goto __exit; + } + + /*Function code 01-04 has a basically similar transmission structure*/ + /*01 Read the coil status to obtain the current status of a group of logic coils (ON/OFF)*/ + /*02 Read input status to obtain the current status of a group of switch inputs (ON/OFF)*/ + /*03 Read the holding register Get the current binary value in one or more holding registers*/ + /*04 Read input register Get the current binary value in one or more input registers*/ + if (MDS_RTU_FUN_CODE(pModbus_RTU) >= 0x1 && MDS_RTU_FUN_CODE(pModbus_RTU) <= 0x4) + { + uint16 startReg = MDS_RTU_START_REG(pModbus_RTU); + uint16 regNum = MDS_RTU_REGS_NUM(pModbus_RTU); + MDS_RTU_ReadDataProcess(pModbus_RTU, startReg, regNum, MDS_RTU_FUN_CODE(pModbus_RTU)); + } + else if ( + MDS_RTU_FUN_CODE(pModbus_RTU) == 0x5 || + MDS_RTU_FUN_CODE(pModbus_RTU) == 0x6) + { + /*05 Force a single coil to force the on-off status of a logic coil*/ + /*06 Preset single register Load specific binary value into a holding register*/ + uint16 startReg = MDS_RTU_START_REG(pModbus_RTU); + uint16 val = ((pModbus_RTU->serialReadCache[4]) << 8) | pModbus_RTU->serialReadCache[5]; + + MDS_RTU_WriteDataProcess(pModbus_RTU, startReg, 1, MDS_RTU_FUN_CODE(pModbus_RTU), &val, 2); + } + else if ( + MDS_RTU_FUN_CODE(pModbus_RTU) == 15 || + MDS_RTU_FUN_CODE(pModbus_RTU) == 16) + { + /*15 Force multiple coils to force a series of continuous logic coils on and off*/ + /*16 Preset multiple registers to load specific binary values into a series of continuous holding registers*/ + uint16 startReg = MDS_RTU_START_REG(pModbus_RTU); + uint16 regNum = MDS_RTU_REGS_NUM(pModbus_RTU); + uint8 bytesNum = MDS_RTU_BYTES_NUM(pModbus_RTU); + if (MDS_RTU_FUN_CODE(pModbus_RTU) == 15) + { + if (((regNum >> 3) + ((regNum % 8) ? 1 : 0)) != bytesNum) + { + MDS_RTU_SendErrorCode(pModbus_RTU, WRITE_COILS, ILLEGAL_DAT_VAL); + /*A length mismatch error occurred, discard it*/ + goto __exit0; + } + } + else + { // 16 + if ((regNum << 1) != bytesNum) + { + MDS_RTU_SendErrorCode(pModbus_RTU, WRITE_REGS, ILLEGAL_DAT_VAL); + /*A length mismatch error occurred, discard*/ + goto __exit0; + } + } + + MDS_RTU_WriteDataProcess(pModbus_RTU, startReg, regNum, MDS_RTU_FUN_CODE(pModbus_RTU), + (uint16 *)(&(pModbus_RTU->serialReadCache[7])), pModbus_RTU->serialReadCache[6]); + } + +__exit0: + pModbus_RTU->lastSendTimes = pModbus_RTU->timesTick; +__exit: + pModbus_RTU->serialReadCount = 0; + + return; +} + +/******************************************************* + * + * Function name :MDS_RTU_SendErrorCode + * Description :This function returns the error code information received and processed to the host + * Parameter : + * @pModbus_RTU Object pointer of slave + * @anlCode Exception code, see [ANLCode] + * @errCode Error code, see [ErrorCode] + * Return : None + **********************************************************/ +static void MDS_RTU_SendErrorCode(PModbusS_RTU pModbus_RTU, ANLCode anlCode, ErrorCode errCode) +{ + MD_RTU_SEND_MODE(pModbus_RTU); + MDS_START_SEND(pModbus_RTU); + MDS_SEND_BYTE(pModbus_RTU, pModbus_RTU->salveAddr); + MDS_SEND_BYTE(pModbus_RTU, anlCode); + MDS_SEND_BYTE(pModbus_RTU, errCode); + MDS_SEND_END(pModbus_RTU); + MD_RTU_RECV_MODE(pModbus_RTU); +} +/******************************************************* + * + * Function name :MDS_RTU_ReadDataProcess + * Description :This function handles the host's read data request + * Parameter : + * @pModbus_RTU Object pointer of slave + * @reg Start of read address + * @regNum Number of data read + * @funCode Function code of operation + * Return : TRUE success , FALSE fail + **********************************************************/ +uint8 MDS_RTU_ReadDataProcess(PModbusS_RTU pModbus_RTU, uint16 reg, uint16 regNum, uint8 funCode) +{ + uint16 i = 0; + if (pModbus_RTU == NULL) + { + return FALSE; + } + + for (i = 0; i < MDS_REG_COIL_ITEM_NUM; i++) + { + if (pModbus_RTU->pMapTableList[i] == NULL) + { + continue; + } + if (pModbus_RTU->pMapTableList[i]->modbusAddr <= reg && + (pModbus_RTU->pMapTableList[i]->modbusAddr + pModbus_RTU->pMapTableList[i]->modbusDataSize) >= (reg + regNum)) + { + /*Ensure that the read range is within the memory range*/ + if ((funCode == 1 && pModbus_RTU->pMapTableList[i]->addrType == COILS_TYPE) || + (funCode == 2 && pModbus_RTU->pMapTableList[i]->addrType == INPUT_TYPE)) + { + /*Make sure it is the read BIT*/ + /*Get bit offset*/ + uint16 offsetAddr = reg - MDS_RTU_REG_COIL_ITEM_ADDR(pModbus_RTU->pMapTableList[i]); + uint16 j; + uint16 lastIndex = 0; + uint8 tempByte = 0; + MD_RTU_SEND_MODE(pModbus_RTU); + MDS_START_SEND(pModbus_RTU); + MDS_SEND_BYTE(pModbus_RTU, pModbus_RTU->salveAddr); + MDS_SEND_BYTE(pModbus_RTU, funCode); + MDS_SEND_BYTE(pModbus_RTU, (regNum >> 3) + ((regNum % 8) > 0 ? 1 : 0)); + for (j = offsetAddr; j < offsetAddr + regNum; j++) + { + if (((j - offsetAddr) >> 3) != lastIndex) + { + MDS_SEND_BYTE(pModbus_RTU, tempByte); + tempByte = 0; + /*The current write byte position is different from the last time, it means that a byte needs to be sent*/ + lastIndex = (j - offsetAddr) >> 3; + } + if ( + MD_GET_BIT( + MDS_RTU_REG_COIL_ITEM_DATA(pModbus_RTU->pMapTableList[i])[j >> 4], j % 16)) + { + MD_SET_BIT(tempByte, j % 8); + } + else + { + MD_CLR_BIT(tempByte, j % 8); + } + } + MDS_SEND_BYTE(pModbus_RTU, tempByte); + MDS_SEND_END(pModbus_RTU); + MD_RTU_RECV_MODE(pModbus_RTU); + } + else if ((funCode == 3 && pModbus_RTU->pMapTableList[i]->addrType == HOLD_REGS_TYPE) || + (funCode == 4 && pModbus_RTU->pMapTableList[i]->addrType == INPUT_REGS_TYPE)) + { + /*Make sure to read REG.*/ + /*Get two bytes offset*/ + uint16 j = 0; + uint16 offsetAddr = reg - MDS_RTU_REG_COIL_ITEM_ADDR(pModbus_RTU->pMapTableList[i]); + MD_RTU_SEND_MODE(pModbus_RTU); + MDS_START_SEND(pModbus_RTU); + MDS_SEND_BYTE(pModbus_RTU, pModbus_RTU->salveAddr); + MDS_SEND_BYTE(pModbus_RTU, funCode); + MDS_SEND_BYTE(pModbus_RTU, regNum << 1); + for (j = 0; j < regNum << 1; j += 2) + { + uint16 temp = MDS_RTU_REG_COIL_ITEM_DATA(pModbus_RTU->pMapTableList[i])[offsetAddr + (j >> 1)]; + MDS_SEND_BYTE(pModbus_RTU, (temp >> 8) & 0xff); + MDS_SEND_BYTE(pModbus_RTU, (temp)&0xff); + } + MDS_SEND_END(pModbus_RTU); + MD_RTU_RECV_MODE(pModbus_RTU); + } + else + { + /*Address cannot be read*/ + continue; + } + return TRUE; + } + } + /*Address is abnormal*/ + MDS_RTU_SendErrorCode(pModbus_RTU, (ANLCode)(0x80 + funCode), ILLEGAL_DAT_ADDR); + return FALSE; +} +/******************************************************* + * + * Function name :MDS_RTU_WriteDataProcess + * Description :This function handles the host's write data request + * Parameter : + * @pModbus_RTU Object pointer of slave + * @reg Start of read address + * @regNum Number of data read + * @funCode Function code of operation + * @data Data written + * @byteCount How many bytes are the data written + * Return : TRUE success , FALSE fail + **********************************************************/ +uint8 MDS_RTU_WriteDataProcess(PModbusS_RTU pModbus_RTU, uint16 reg, + uint16 regNum, uint8 funCode, uint16 *data, uint8 byteCount) +{ + uint8 res = FALSE; + switch (funCode) + { + case 5: /*Write single coil*/ + { + if (data[0] == 0xFF00 || data[0] == 0x0000) + { + if (data[0] == 0xFF00) + { + res = MDS_RTU_WriteBit(pModbus_RTU, reg, 1, COILS_TYPE); + } + else + { + res = MDS_RTU_WriteBit(pModbus_RTU, reg, 0, COILS_TYPE); + } + if (res) + { + MD_RTU_SEND_MODE(pModbus_RTU); + MDS_START_SEND(pModbus_RTU); + MDS_SEND_BYTE(pModbus_RTU, pModbus_RTU->salveAddr); + MDS_SEND_BYTE(pModbus_RTU, funCode); + MDS_SEND_BYTE(pModbus_RTU, (reg >> 8) & 0xff); + MDS_SEND_BYTE(pModbus_RTU, (reg)&0xff); + MDS_SEND_BYTE(pModbus_RTU, ((*data) >> 8) & 0xff); + MDS_SEND_BYTE(pModbus_RTU, (*data) & 0xff); + MDS_SEND_END(pModbus_RTU); + MD_RTU_RECV_MODE(pModbus_RTU); + if (pModbus_RTU->mdsWriteFun) + { + pModbus_RTU->mdsWriteFun(pModbus_RTU, reg, 1, COILS_TYPE); + } + } + else + { + MDS_RTU_SendErrorCode(pModbus_RTU, WRITE_SIN_COIL, ILLEGAL_DAT_ADDR); + } + } + else + { + MDS_RTU_SendErrorCode(pModbus_RTU, WRITE_SIN_COIL, ILLEGAL_DAT_VAL); + } + } + break; + case 15: /*Write multiple coils*/ + res = MDS_RTU_WriteBits(pModbus_RTU, reg, regNum, data, COILS_TYPE); + if (res) + { + MD_RTU_SEND_MODE(pModbus_RTU); + MDS_START_SEND(pModbus_RTU); + MDS_SEND_BYTE(pModbus_RTU, pModbus_RTU->salveAddr); + MDS_SEND_BYTE(pModbus_RTU, funCode); + MDS_SEND_BYTE(pModbus_RTU, (reg >> 8) & 0xff); + MDS_SEND_BYTE(pModbus_RTU, (reg)&0xff); + MDS_SEND_BYTE(pModbus_RTU, ((regNum) >> 8) & 0xff); + MDS_SEND_BYTE(pModbus_RTU, (regNum)&0xff); + MDS_SEND_END(pModbus_RTU); + MD_RTU_RECV_MODE(pModbus_RTU); + if (pModbus_RTU->mdsWriteFun) + { + pModbus_RTU->mdsWriteFun(pModbus_RTU, reg, regNum, COILS_TYPE); + } + } + else + { + MDS_RTU_SendErrorCode(pModbus_RTU, WRITE_COILS, ILLEGAL_DAT_ADDR); + } + break; + case 6: /*Write single register*/ + res = MDS_RTU_WriteReg(pModbus_RTU, reg, data[0], HOLD_REGS_TYPE); + if (res) + { + MD_RTU_SEND_MODE(pModbus_RTU); + MDS_START_SEND(pModbus_RTU); + MDS_SEND_BYTE(pModbus_RTU, pModbus_RTU->salveAddr); + MDS_SEND_BYTE(pModbus_RTU, funCode); + MDS_SEND_BYTE(pModbus_RTU, (reg >> 8) & 0xff); + MDS_SEND_BYTE(pModbus_RTU, (reg)&0xff); + MDS_SEND_BYTE(pModbus_RTU, ((*data) >> 8) & 0xff); + MDS_SEND_BYTE(pModbus_RTU, (*data) & 0xff); + MDS_SEND_END(pModbus_RTU); + MD_RTU_RECV_MODE(pModbus_RTU); + if (pModbus_RTU->mdsWriteFun) + { + pModbus_RTU->mdsWriteFun(pModbus_RTU, reg, 1, HOLD_REGS_TYPE); + } + } + else + { + MDS_RTU_SendErrorCode(pModbus_RTU, WRITE_SIN_REG, ILLEGAL_DAT_ADDR); + } + break; + case 16: /*Write multiple registers*/ + res = MDS_RTU_WriteRegs(pModbus_RTU, reg, regNum, data, 1, HOLD_REGS_TYPE); + if (res) + { + MD_RTU_SEND_MODE(pModbus_RTU); + MDS_START_SEND(pModbus_RTU); + MDS_SEND_BYTE(pModbus_RTU, pModbus_RTU->salveAddr); + MDS_SEND_BYTE(pModbus_RTU, funCode); + MDS_SEND_BYTE(pModbus_RTU, (reg >> 8) & 0xff); + MDS_SEND_BYTE(pModbus_RTU, (reg)&0xff); + MDS_SEND_BYTE(pModbus_RTU, ((regNum) >> 8) & 0xff); + MDS_SEND_BYTE(pModbus_RTU, (regNum)&0xff); + MDS_SEND_END(pModbus_RTU); + MD_RTU_RECV_MODE(pModbus_RTU); + if (pModbus_RTU->mdsWriteFun) + { + pModbus_RTU->mdsWriteFun(pModbus_RTU, reg, regNum, HOLD_REGS_TYPE); + } + } + else + { + MDS_RTU_SendErrorCode(pModbus_RTU, WRITE_REGS, ILLEGAL_DAT_ADDR); + } + break; + } + if (!res) + { + return FALSE; + } + return TRUE; +} diff --git a/mkrtos_user/lib/modbus/src/modbus_rtu_slave/MDS_RTU_User_Fun.c b/mkrtos_user/lib/modbus/src/modbus_rtu_slave/MDS_RTU_User_Fun.c new file mode 100644 index 000000000..c760bbbf9 --- /dev/null +++ b/mkrtos_user/lib/modbus/src/modbus_rtu_slave/MDS_RTU_User_Fun.c @@ -0,0 +1,225 @@ +/******************************************************************************** +* @File name: MD_RTU_User_Fun.c +* @Author: zspace +* @Emial: 1358745329@qq.com +* @Version: 1.0 +* @Date: 2020-4-28 +* @Description: Modbus RTU user related functions +* Open source address: https://github.com/lotoohe-space/XTinyModbus +********************************************************************************/ +#include "MDS_RTU_User_Fun.h" +#include "MDS_RTU_Fun.h" + +/*Read bits, you can read one or multiple*/ +BOOL MDS_RTU_ReadBits(void* obj,uint16 modbusAddr,uint16 numOf, uint8 *res, AddrType opAddrType){ + uint16 i; + PModbusS_RTU pModbusS_RTU = obj; + if(pModbusS_RTU==NULL){return FALSE;} + /*Only operate bits*/ + if(opAddrType != COILS_TYPE && opAddrType != INPUT_TYPE){return FALSE;} + + for(i=0;ipMapTableList[i]==NULL){ + continue; + } + if(pModbusS_RTU->pMapTableList[i]->modbusAddr<=modbusAddr&& + (pModbusS_RTU->pMapTableList[i]->modbusAddr+pModbusS_RTU->pMapTableList[i]->modbusDataSize)>=(modbusAddr+numOf) + ){ + if(pModbusS_RTU->pMapTableList[i]->addrType==opAddrType){/*Specified type*/ + uint16 j; + uint16 offsetAddr=modbusAddr-MDS_RTU_REG_COIL_ITEM_ADDR(pModbusS_RTU->pMapTableList[i]); + for(j=offsetAddr; jpMapTableList[i])[j>>4],j%16) + ){ + MD_SET_BIT(res[j>>3],j%8); + }else{ + MD_CLR_BIT(res[j>>3],j%8); + } + } + return TRUE; + } + } + } + return FALSE; +} +BOOL MDS_RTU_ReadRegs(void* obj,uint16 modbusAddr,uint16 numOf, uint16 *res, AddrType opAddrType){ + uint16 i; + PModbusS_RTU pModbusS_RTU = obj; + if(pModbusS_RTU==NULL){return FALSE;} + /*Can only manipulate registers*/ + if(opAddrType != HOLD_REGS_TYPE && opAddrType != INPUT_REGS_TYPE){return FALSE;} + + for(i=0;ipMapTableList[i]==NULL){ + continue; + } + if(pModbusS_RTU->pMapTableList[i]->modbusAddr<=modbusAddr&& + (pModbusS_RTU->pMapTableList[i]->modbusAddr+pModbusS_RTU->pMapTableList[i]->modbusDataSize)>=(modbusAddr+numOf) + ){ + if(pModbusS_RTU->pMapTableList[i]->addrType == opAddrType){ + uint16 j; + uint16 offsetAddr=modbusAddr-MDS_RTU_REG_COIL_ITEM_ADDR(pModbusS_RTU->pMapTableList[i]); + for(j=0;jpMapTableList[i])[offsetAddr+j]; + } + return TRUE; + } + } + } + return FALSE; +} +BOOL MDS_RTU_WriteBit(void* obj,uint16 modbusAddr,uint8 bit, AddrType opAddrType){ + uint16 i; + PModbusS_RTU pModbusS_RTU = obj; + if(pModbusS_RTU==NULL){return FALSE;} + if(opAddrType != COILS_TYPE && opAddrType != INPUT_TYPE){return FALSE;} + + for(i=0;ipMapTableList[i]==NULL){ + continue; + } + if(pModbusS_RTU->pMapTableList[i]->modbusAddr<=modbusAddr&& + (pModbusS_RTU->pMapTableList[i]->modbusAddr+pModbusS_RTU->pMapTableList[i]->modbusDataSize)>=(modbusAddr+1) + ){ + if(pModbusS_RTU->pMapTableList[i]->addrType==opAddrType){ + uint16 offsetAddr=modbusAddr-MDS_RTU_REG_COIL_ITEM_ADDR(pModbusS_RTU->pMapTableList[i]); + if(bit){ + MD_SET_BIT( + MDS_RTU_REG_COIL_ITEM_DATA(pModbusS_RTU->pMapTableList[i])[offsetAddr>>4],offsetAddr%16); + }else{ + MD_CLR_BIT( + MDS_RTU_REG_COIL_ITEM_DATA(pModbusS_RTU->pMapTableList[i])[offsetAddr>>4],offsetAddr%16); + } + return TRUE; + } + } + } + return FALSE; +} +BOOL MDS_RTU_WriteBits(void* obj,uint16 modbusAddr,uint16 numOf, uint16 *bit, AddrType opAddrType){ + uint16 i; + PModbusS_RTU pModbusS_RTU = obj; + if(pModbusS_RTU==NULL){return FALSE;} + if(opAddrType != COILS_TYPE && opAddrType != INPUT_TYPE){return FALSE;} + + for(i=0;ipMapTableList[i]==NULL){ + continue; + } + if(pModbusS_RTU->pMapTableList[i]->modbusAddr<=modbusAddr&& + (pModbusS_RTU->pMapTableList[i]->modbusAddr+pModbusS_RTU->pMapTableList[i]->modbusDataSize)>=(modbusAddr+numOf) + ){ + if(pModbusS_RTU->pMapTableList[i]->addrType==opAddrType){/*Must be BIT type*/ + uint16 offsetAddr=modbusAddr-MDS_RTU_REG_COIL_ITEM_ADDR(pModbusS_RTU->pMapTableList[i]); + uint16 j; + for(j=0;j>3] ,j%8) + ){ + MD_SET_BIT( + MDS_RTU_REG_COIL_ITEM_DATA( + pModbusS_RTU->pMapTableList[i])[(offsetAddr+j)>>4] + ,(j+offsetAddr)%16); + }else{ + MD_CLR_BIT( + MDS_RTU_REG_COIL_ITEM_DATA( + pModbusS_RTU->pMapTableList[i])[(offsetAddr+j)>>4] + ,(j+offsetAddr)%16); + } + } + return TRUE; + } + } + } + return FALSE; +} +BOOL MDS_RTU_WriteReg(void* obj,uint16 modbusAddr,uint16 reg, AddrType opAddrType){ + uint16 i; + PModbusS_RTU pModbusS_RTU = obj; + if(pModbusS_RTU==NULL){return FALSE;} + if(opAddrType != HOLD_REGS_TYPE && opAddrType != INPUT_REGS_TYPE){return FALSE;} + + for(i=0;ipMapTableList[i]==NULL){ + continue; + } + if(pModbusS_RTU->pMapTableList[i]->modbusAddr<=modbusAddr&& + (pModbusS_RTU->pMapTableList[i]->modbusAddr+pModbusS_RTU->pMapTableList[i]->modbusDataSize)>=(modbusAddr+1) + ){ + if(pModbusS_RTU->pMapTableList[i]->addrType==opAddrType){ + uint16 offsetAddr=modbusAddr-MDS_RTU_REG_COIL_ITEM_ADDR(pModbusS_RTU->pMapTableList[i]); + MDS_RTU_REG_COIL_ITEM_DATA(pModbusS_RTU->pMapTableList[i])[offsetAddr]=reg; + return TRUE; + } + } + } + return FALSE; +} +BOOL MDS_RTU_WriteRegs(void* obj,uint16 modbusAddr,uint16 numOf, uint16 *reg,uint8 isBigE, AddrType opAddrType){ + uint16 i; + PModbusS_RTU pModbusS_RTU = obj; + if(pModbusS_RTU==NULL){return FALSE;} + if(opAddrType != HOLD_REGS_TYPE && opAddrType != INPUT_REGS_TYPE){return FALSE;} + + for(i=0;ipMapTableList[i]==NULL){ + continue; + } + if(pModbusS_RTU->pMapTableList[i]->modbusAddr<=modbusAddr&& + (pModbusS_RTU->pMapTableList[i]->modbusAddr+pModbusS_RTU->pMapTableList[i]->modbusDataSize)>=(modbusAddr+numOf) + ){ + if(pModbusS_RTU->pMapTableList[i]->addrType==opAddrType){/*Must be REG type*/ + uint16 offsetAddr=modbusAddr-MDS_RTU_REG_COIL_ITEM_ADDR(pModbusS_RTU->pMapTableList[i]); + uint16 j=0; + for(j=0;jpMapTableList[i])[offsetAddr+j]= + isBigE?MD_SWAP_HL(reg[j]):reg[j]; + } + return TRUE; + } + } + } + return FALSE; +} + + + +BOOL MDS_RTU_WriteCoil(void* obj,uint16 modbusAddr,uint8 bit){ + return MDS_RTU_WriteBit( obj, modbusAddr, bit, COILS_TYPE); +} +BOOL MDS_RTU_WriteInput(void* obj,uint16 modbusAddr,uint8 bit){ + return MDS_RTU_WriteBit( obj, modbusAddr, bit, INPUT_TYPE); +} +BOOL MDS_RTU_WriteCoils(void* obj,uint16 modbusAddr,uint16 numOf, uint16 *bit){ + return MDS_RTU_WriteBits( obj, modbusAddr, numOf,bit, COILS_TYPE); +} +BOOL MDS_RTU_WriteInputs(void* obj,uint16 modbusAddr,uint16 numOf, uint16 *bit){ + return MDS_RTU_WriteBits( obj, modbusAddr, numOf,bit, INPUT_TYPE); +} +BOOL MDS_RTU_WriteHoldReg(void* obj,uint16 modbusAddr,uint16 reg){ + return MDS_RTU_WriteReg( obj, modbusAddr, reg, HOLD_REGS_TYPE); +} +BOOL MDS_RTU_WriteHoldRegs(void* obj,uint16 modbusAddr,uint16 numOf, uint16 *reg){ + return MDS_RTU_WriteRegs( obj, modbusAddr, numOf, reg,0, HOLD_REGS_TYPE); +} +BOOL MDS_RTU_WriteInputReg(void* obj,uint16 modbusAddr,uint16 reg){ + return MDS_RTU_WriteReg( obj, modbusAddr, reg, INPUT_REGS_TYPE); +} +BOOL MDS_RTU_WriteInputRegs(void* obj,uint16 modbusAddr,uint16 numOf, uint16 *reg){ + return MDS_RTU_WriteRegs( obj, modbusAddr, numOf, reg,0, INPUT_REGS_TYPE); +} +BOOL MDS_RTU_ReadCoils(void *obj,uint16 modbusAddr,uint16 numOf,uint8 *res){ + return MDS_RTU_ReadBits( obj, modbusAddr, numOf,res, COILS_TYPE); +} +BOOL MDS_RTU_ReadInput(void *obj,uint16 modbusAddr,uint16 numOf,uint8 *res){ + return MDS_RTU_ReadBits( obj, modbusAddr, numOf,res, INPUT_TYPE); +} +BOOL MDS_RTU_ReadHoldRegs(void* obj,uint16 modbusAddr,uint16 numOf, uint16 *res){ + return MDS_RTU_ReadRegs( obj, modbusAddr, numOf, res, HOLD_REGS_TYPE); +} +BOOL MDS_RTU_ReadInputRegs(void* obj,uint16 modbusAddr,uint16 numOf, uint16 *res){ + return MDS_RTU_ReadRegs( obj, modbusAddr, numOf, res, INPUT_REGS_TYPE); +} diff --git a/mkrtos_user/lib/modbus/src/port/MD_RTU_SysInterface.c b/mkrtos_user/lib/modbus/src/port/MD_RTU_SysInterface.c new file mode 100644 index 000000000..e74a8eebb --- /dev/null +++ b/mkrtos_user/lib/modbus/src/port/MD_RTU_SysInterface.c @@ -0,0 +1,75 @@ +#include "MD_RTU_SysInterface.h" + +#if MD_RTU_USED_OS + +uint8 MD_RTU_CreateThread(PModbusBase pModbusBase,void(*funTask)(void* arg),MD_RTU_TASK_HANDLE *pTaskObj){ + if(pModbusBase==NULL){ + return FALSE; + } + *pTaskObj=OSCreateTask(funTask,pModbusBase,MD_RTU_TASK_LEVEL,MD_RTU_TASK_STACK_SIZE); + return (*pTaskObj)!=NULL;; +} +void MD_RTU_Delay(uint32 ms){ + OSTaskDelay(ms); +} +uint8 MD_RTU_CreateMsg(PModbusBase pModbusBase, MD_RTU_MSG_HANDLE *pMsgObj, + uint32 msgBoxLength +){ + if(pModbusBase==NULL){ + return FALSE; + } + *pMsgObj=MsgCreate(); + return (*pMsgObj)!=NULL; +} +uint8 MD_RTU_MsgPut(PModbusBase pModbusBase, MD_RTU_MSG_HANDLE pMsgObj,void* msg,uint32 msgPutDelay){ + return MsgPut(pMsgObj,msg,msgPutDelay); +} +uint8 MD_RTU_MsgGet(PModbusBase pModbusBase, MD_RTU_MSG_HANDLE pMsgObj,void **msg,uint32 msgGetDelay){ + return MsgGet(pMsgObj,msg,msgGetDelay); +} +/** +* @brief Create the locked object +* @param[in] pModbusBase modbus object +* @param[in] pLockObj Lock object pointer +* @return +* - TRUE success +* - FALSE fail +*/ +uint8 MD_RTU_CreateLock(PModbusBase pModbusBase, MD_RTU_LOCK_HANDLE *pLockObj){ + if(pModbusBase==NULL){ + return FALSE; + } + *pLockObj=MutexCreate(); + return (*pLockObj)!=NULL; +} +/** +* @brief Lock the modbus rtu object +* @param[in] pModbusBase modbus object +* @param[in] lockObj lock Object +* @return +* - TRUE success +* - FALSE fail +*/ +uint8 MD_RTU_Lock(PModbusBase pModbusBase, MD_RTU_LOCK_HANDLE lockObj,uint32 mutexWaitDelay){ + return MutexLock(lockObj,mutexWaitDelay); +} +/** +* @brief Unlock the modbus rtu object +* @param[in] pModbusBase modbus object +* @param[in] lockObj lock Object +* @return +* - TRUE success +* - FALSE fail +*/ +uint8 MD_RTU_Unlock(PModbusBase pModbusBase, MD_RTU_LOCK_HANDLE lockObj){ + return MutexUnlock(lockObj); +} +/** +* @brief Modbus RTU get system tick (100us). +* @return system tick. +*/ +uint32 MD_RTU_GetSysTick(void){ + return sys_tick_100us; +} +#endif + diff --git a/mkrtos_user/lib/sys/inc/u_types.h b/mkrtos_user/lib/sys/inc/u_types.h index 9288c6c1a..3e5eab8bd 100755 --- a/mkrtos_user/lib/sys/inc/u_types.h +++ b/mkrtos_user/lib/sys/inc/u_types.h @@ -12,6 +12,26 @@ typedef char bool_t; typedef unsigned long obj_addr_t; typedef unsigned long obj_handler_t; typedef umword_t addr_t; + +/** + * @brief 资源描述符定义 + * + */ +typedef umword_t sd_t; // 16bit(hd)|16bit(fd) +typedef union mk_sd +{ + umword_t raw; + struct + { + uhmword_t hd; + uhmword_t fd; + }; +} mk_sd_t; +#define mk_sd_init_raw(val) ((mk_sd_t){.raw = val}) +#define mk_sd_init3(h, f) ((mk_sd_t){.hd = h, .fd = f}) +#define mk_sd_get_hd(sd) ((obj_handler_t)((sd).hd)) +#define mk_sd_get_fd(sd) ((int)((sd).fd)) + #ifndef NULL #define NULL ((void *)0) #endif diff --git a/mkrtos_user/lib/sys/src/syscall.S b/mkrtos_user/lib/sys/src/syscall.S index 3b6efd17d..fc8be995f 100644 --- a/mkrtos_user/lib/sys/src/syscall.S +++ b/mkrtos_user/lib/sys/src/syscall.S @@ -2,11 +2,11 @@ .text /* -int syscall(int nr, ...) +int mk_syscall(int nr, ...) */ -.global syscall -.type syscall, %function -syscall: +.global mk_syscall +.type mk_syscall, %function +mk_syscall: push {r4-r7} mov r7, r0 mov r0, r1 diff --git a/mkrtos_user/lib/sys/src/u_factory.c b/mkrtos_user/lib/sys/src/u_factory.c index 2bea114e0..401af7c55 100644 --- a/mkrtos_user/lib/sys/src/u_factory.c +++ b/mkrtos_user/lib/sys/src/u_factory.c @@ -10,7 +10,7 @@ msg_tag_t factory_create_irq_sender(obj_handler_t obj, vpage_t vpage) { register volatile umword_t r0 asm("r0"); - syscall(syscall_prot_create(FACTORY_CREATE_KOBJ, FACTORY_PROT, obj), + mk_syscall(syscall_prot_create(FACTORY_CREATE_KOBJ, FACTORY_PROT, obj), 0, IRQ_PROT, vpage.raw, @@ -25,7 +25,7 @@ msg_tag_t factory_create_thread(obj_handler_t obj, vpage_t vpage) { register volatile umword_t r0 asm("r0"); - syscall(syscall_prot_create(FACTORY_CREATE_KOBJ, FACTORY_PROT, obj), + mk_syscall(syscall_prot_create(FACTORY_CREATE_KOBJ, FACTORY_PROT, obj), 0, THREAD_PROT, vpage.raw, @@ -40,7 +40,7 @@ msg_tag_t factory_create_task(obj_handler_t obj, vpage_t vpage) { register volatile umword_t r0 asm("r0"); - syscall(syscall_prot_create(FACTORY_CREATE_KOBJ, FACTORY_PROT, obj), + mk_syscall(syscall_prot_create(FACTORY_CREATE_KOBJ, FACTORY_PROT, obj), 0, TASK_PROT, vpage.raw, @@ -55,7 +55,7 @@ msg_tag_t factory_create_ipc(obj_handler_t obj, vpage_t vpage) { register volatile umword_t r0 asm("r0"); - syscall(syscall_prot_create(FACTORY_CREATE_KOBJ, FACTORY_PROT, obj), + mk_syscall(syscall_prot_create(FACTORY_CREATE_KOBJ, FACTORY_PROT, obj), 0, IPC_PROT, vpage.raw, diff --git a/mkrtos_user/lib/sys/src/u_ipc.c b/mkrtos_user/lib/sys/src/u_ipc.c index 347cf5498..17b13b059 100644 --- a/mkrtos_user/lib/sys/src/u_ipc.c +++ b/mkrtos_user/lib/sys/src/u_ipc.c @@ -14,7 +14,7 @@ msg_tag_t ipc_bind(obj_handler_t obj, obj_handler_t tag_th, umword_t user_obj) { register volatile umword_t r0 asm("r0"); - syscall(syscall_prot_create(IPC_BIND, IPC_PROT, obj), + mk_syscall(syscall_prot_create(IPC_BIND, IPC_PROT, obj), 0, tag_th, user_obj, @@ -34,7 +34,7 @@ msg_tag_t ipc_wait(obj_handler_t obj, umword_t *user_obj) register volatile umword_t r0 asm("r0"); register volatile umword_t r1 asm("r1"); - syscall(syscall_prot_create(IPC_WAIT, IPC_PROT, obj), + mk_syscall(syscall_prot_create(IPC_WAIT, IPC_PROT, obj), 0, 0, 0, @@ -55,7 +55,7 @@ msg_tag_t ipc_reply(obj_handler_t obj, msg_tag_t in_tag) { register volatile umword_t r0 asm("r0"); - syscall(syscall_prot_create(IPC_REPLY, IPC_PROT, obj), + mk_syscall(syscall_prot_create(IPC_REPLY, IPC_PROT, obj), in_tag.raw, 0, 0, @@ -74,7 +74,7 @@ msg_tag_t ipc_call(obj_handler_t obj, msg_tag_t in_tag, ipc_timeout_t timeout) { register volatile umword_t r0 asm("r0"); - syscall(syscall_prot_create(IPC_CALL, IPC_PROT, obj), + mk_syscall(syscall_prot_create(IPC_CALL, IPC_PROT, obj), in_tag.raw, timeout.raw, 0, diff --git a/mkrtos_user/lib/sys/src/u_irq_sender.c b/mkrtos_user/lib/sys/src/u_irq_sender.c index e4043f43d..f71493360 100644 --- a/mkrtos_user/lib/sys/src/u_irq_sender.c +++ b/mkrtos_user/lib/sys/src/u_irq_sender.c @@ -22,7 +22,7 @@ msg_tag_t uirq_bind(obj_handler_t obj_inx, umword_t irq_no, umword_t prio_sub_pr { register volatile umword_t r0 asm("r0"); - syscall(syscall_prot_create(BIND_IRQ, IRQ_PROT, obj_inx), + mk_syscall(syscall_prot_create(BIND_IRQ, IRQ_PROT, obj_inx), 0, irq_no, 0, @@ -41,7 +41,7 @@ msg_tag_t uirq_wait(obj_handler_t obj_inx, int flags) { register volatile umword_t r0 asm("r0"); - syscall(syscall_prot_create(WAIT_IRQ, IRQ_PROT, obj_inx), + mk_syscall(syscall_prot_create(WAIT_IRQ, IRQ_PROT, obj_inx), 0, flags, 0, @@ -60,7 +60,7 @@ msg_tag_t uirq_ack(obj_handler_t obj_inx, umword_t irq_no) { register volatile umword_t r0 asm("r0"); - syscall(syscall_prot_create(ACK_IRQ, IRQ_PROT, obj_inx), + mk_syscall(syscall_prot_create(ACK_IRQ, IRQ_PROT, obj_inx), 0, irq_no, 0, diff --git a/mkrtos_user/lib/sys/src/u_log.c b/mkrtos_user/lib/sys/src/u_log.c index 5fd00f1dc..0ed6d5412 100644 --- a/mkrtos_user/lib/sys/src/u_log.c +++ b/mkrtos_user/lib/sys/src/u_log.c @@ -19,7 +19,7 @@ static msg_tag_t ulog_read_bytes_raw(obj_handler_t obj_inx, umword_t data[5], in register volatile umword_t r3 asm("r3"); register volatile umword_t r4 asm("r4"); register volatile umword_t r5 asm("r5"); - syscall(syscall_prot_create(READ_DATA, LOG_PROT, obj_inx), + mk_syscall(syscall_prot_create(READ_DATA, LOG_PROT, obj_inx), msg_tag_init4(0, 0, 0, 0).raw, len, 0, @@ -71,7 +71,7 @@ void ulog_write_bytes(obj_handler_t obj_inx, const uint8_t *data, umword_t len) if (i > 0) { umword_t *write_word_buf = (umword_t *)write_buf; - syscall(syscall_prot_create(WRITE_DATA, LOG_PROT, obj_inx), + mk_syscall(syscall_prot_create(WRITE_DATA, LOG_PROT, obj_inx), msg_tag_init4(0, ROUND_UP(i, WORD_BYTES), 0, 0).raw, write_word_buf[0], write_word_buf[1], diff --git a/mkrtos_user/lib/sys/src/u_mm.c b/mkrtos_user/lib/sys/src/u_mm.c index 66d5e7251..6becbf2b2 100644 --- a/mkrtos_user/lib/sys/src/u_mm.c +++ b/mkrtos_user/lib/sys/src/u_mm.c @@ -16,7 +16,7 @@ void *mm_alloc_page(obj_handler_t obj_inx, umword_t pnf_nr, uint8_t attrs) register volatile umword_t r1 asm("r1"); register volatile umword_t r2 asm("r2"); register volatile umword_t r3 asm("r3"); - syscall(syscall_prot_create(MM_ALLOC, MM_PROT, obj_inx), + mk_syscall(syscall_prot_create(MM_ALLOC, MM_PROT, obj_inx), 0, pnf_nr, attrs, @@ -40,7 +40,7 @@ void *mm_alloc_page(obj_handler_t obj_inx, umword_t pnf_nr, uint8_t attrs) } void mm_free_page(obj_handler_t obj_inx, void *addr, umword_t pfn_nr) { - syscall(syscall_prot_create(MM_FREE, MM_PROT, obj_inx), + mk_syscall(syscall_prot_create(MM_FREE, MM_PROT, obj_inx), 0, addr, pfn_nr, @@ -52,7 +52,7 @@ msg_tag_t mm_align_alloc(obj_handler_t obj_inx, void *addr, umword_t size) { register volatile umword_t r0 asm("r0"); - syscall(syscall_prot_create(MM_ALIGN_ALLOC, MM_PROT, obj_inx), + mk_syscall(syscall_prot_create(MM_ALIGN_ALLOC, MM_PROT, obj_inx), 0, addr, size, diff --git a/mkrtos_user/lib/sys/src/u_sys.c b/mkrtos_user/lib/sys/src/u_sys.c index cb0ae5ba4..e7ab82420 100644 --- a/mkrtos_user/lib/sys/src/u_sys.c +++ b/mkrtos_user/lib/sys/src/u_sys.c @@ -19,7 +19,7 @@ msg_tag_t sys_read_info(obj_handler_t obj, sys_info_t *info) register volatile umword_t r1 asm("r1"); register volatile umword_t r2 asm("r2"); - syscall(syscall_prot_create(SYS_INFO_GET, SYS_PROT, obj), + mk_syscall(syscall_prot_create(SYS_INFO_GET, SYS_PROT, obj), 0, 0, 0, diff --git a/mkrtos_user/lib/sys/src/u_task.c b/mkrtos_user/lib/sys/src/u_task.c index 0640347be..1c5fc0824 100644 --- a/mkrtos_user/lib/sys/src/u_task.c +++ b/mkrtos_user/lib/sys/src/u_task.c @@ -12,7 +12,7 @@ msg_tag_t task_obj_valid(obj_handler_t dst_task, obj_handler_t obj_inx) { register volatile umword_t r0 asm("r0"); - syscall(syscall_prot_create(TASK_OBJ_MAP, TASK_PROT, dst_task), + mk_syscall(syscall_prot_create(TASK_OBJ_MAP, TASK_PROT, dst_task), 0, obj_inx, 0, @@ -32,7 +32,7 @@ msg_tag_t task_map(obj_handler_t dst_task, obj_handler_t src_obj, obj_handler_t { register volatile umword_t r0 asm("r0"); - syscall(syscall_prot_create(TASK_OBJ_MAP, TASK_PROT, dst_task), + mk_syscall(syscall_prot_create(TASK_OBJ_MAP, TASK_PROT, dst_task), 0, src_obj, dst_obj, @@ -52,7 +52,7 @@ msg_tag_t task_unmap(obj_handler_t task_han, vpage_t vpage) { register volatile umword_t r0 asm("r0"); - syscall(syscall_prot_create(TASK_OBJ_UNMAP, TASK_PROT, task_han), + mk_syscall(syscall_prot_create(TASK_OBJ_UNMAP, TASK_PROT, task_han), 0, vpage.raw, 0, @@ -68,7 +68,7 @@ msg_tag_t task_alloc_ram_base(obj_handler_t task_han, umword_t size, addr_t *all register volatile umword_t r0 asm("r0"); register volatile umword_t r1 asm("r1"); - syscall(syscall_prot_create(TASK_ALLOC_RAM_BASE, TASK_PROT, task_han), + mk_syscall(syscall_prot_create(TASK_ALLOC_RAM_BASE, TASK_PROT, task_han), 0, size, 0, diff --git a/mkrtos_user/lib/sys/src/u_thread.c b/mkrtos_user/lib/sys/src/u_thread.c index 9256020b7..c18454359 100644 --- a/mkrtos_user/lib/sys/src/u_thread.c +++ b/mkrtos_user/lib/sys/src/u_thread.c @@ -15,7 +15,7 @@ msg_tag_t thread_msg_buf_set(obj_handler_t obj, void *msg) register volatile umword_t r1 asm("r1"); register volatile umword_t r2 asm("r2"); - syscall(syscall_prot_create(MSG_BUG_SET, THREAD_PROT, obj), + mk_syscall(syscall_prot_create(MSG_BUG_SET, THREAD_PROT, obj), 0, msg, 0, @@ -34,7 +34,7 @@ msg_tag_t thread_msg_buf_get(obj_handler_t obj, umword_t *msg, umword_t *len) register volatile umword_t r1 asm("r1"); register volatile umword_t r2 asm("r2"); - syscall(syscall_prot_create4(MSG_BUG_GET, THREAD_PROT, obj, TRUE), + mk_syscall(syscall_prot_create4(MSG_BUG_GET, THREAD_PROT, obj, TRUE), 0, 0, 0, @@ -60,7 +60,7 @@ msg_tag_t thread_exec_regs(obj_handler_t obj, umword_t pc, umword_t sp, umword_t { register volatile umword_t r0 asm("r0"); - syscall(syscall_prot_create(SET_EXEC_REGS, THREAD_PROT, obj), + mk_syscall(syscall_prot_create(SET_EXEC_REGS, THREAD_PROT, obj), 0, pc, sp, @@ -79,7 +79,7 @@ msg_tag_t thread_run(obj_handler_t obj, uint8_t prio) { register volatile umword_t r0 asm("r0"); - syscall(syscall_prot_create(RUN_THREAD, THREAD_PROT, obj), + mk_syscall(syscall_prot_create(RUN_THREAD, THREAD_PROT, obj), 0, prio, 0, @@ -94,7 +94,7 @@ msg_tag_t thread_bind_task(obj_handler_t obj, obj_handler_t tk_obj) { register volatile umword_t r0 asm("r0"); - syscall(syscall_prot_create(BIND_TASK, THREAD_PROT, obj), + mk_syscall(syscall_prot_create(BIND_TASK, THREAD_PROT, obj), 0, tk_obj, 0, diff --git a/mkrtos_user/lib/sys_svr/inc/ns_types.h b/mkrtos_user/lib/sys_svr/inc/ns_types.h index a9a66f8e1..d8f92ad44 100644 --- a/mkrtos_user/lib/sys_svr/inc/ns_types.h +++ b/mkrtos_user/lib/sys_svr/inc/ns_types.h @@ -4,6 +4,10 @@ #define NAMESPACE_PATH_LEN 32 #define NAMESAPCE_NR 8 +/** + * @brief 非常简单的方式实现路径管理 + * + */ typedef struct namespace_entry { char path[NAMESPACE_PATH_LEN]; //!< 服务的路径名 @@ -14,6 +18,6 @@ typedef struct ns { rpc_svr_obj_t svr; namespace_entry_t ne_list[NAMESAPCE_NR]; //!< 服务列表 - obj_handler_t hd; - obj_handler_t ipc_hd; //!< 服务的ipc hd + obj_handler_t hd; //!< 存储临时用于映射的hd + obj_handler_t ipc_hd; //!< 服务的ipc hd } ns_t; \ No newline at end of file diff --git a/mkrtos_user/lib/sys_svr/src/fs_cli.c b/mkrtos_user/lib/sys_svr/src/fs_cli.c index c4b29bc78..1c4f9153e 100644 --- a/mkrtos_user/lib/sys_svr/src/fs_cli.c +++ b/mkrtos_user/lib/sys_svr/src/fs_cli.c @@ -30,10 +30,11 @@ RPC_GENERATION_CALL3(fs_t, FS_LSEEK, lseek, rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, fd, rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, offs, rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, whence) -int fs_open(const char *path, int flags, int mode) + +sd_t fs_open(const char *path, int flags, int mode) { obj_handler_t hd; - int ret = ns_query("fs", &hd); + int ret = ns_query(path, &hd); if (ret < 0) { @@ -59,15 +60,10 @@ int fs_open(const char *path, int flags, int mode) return msg_tag_get_val(tag); } -int fs_read(int fd, void *buf, size_t len) +int fs_read(sd_t _fd, void *buf, size_t len) { - obj_handler_t hd; - int ret = ns_query("fs", &hd); - - if (ret < 0) - { - return ret; - } + obj_handler_t hd = mk_sd_init_raw(_fd).hd; + int fd = mk_sd_init_raw(_fd).fd; rpc_int_t rpc_fd = { .data = fd, @@ -102,15 +98,10 @@ int fs_read(int fd, void *buf, size_t len) return rlen; } -int fs_write(int fd, void *buf, size_t len) +int fs_write(sd_t _fd, void *buf, size_t len) { - obj_handler_t hd; - int ret = ns_query("fs", &hd); - - if (ret < 0) - { - return ret; - } + obj_handler_t hd = mk_sd_init_raw(_fd).hd; + int fd = mk_sd_init_raw(_fd).fd; rpc_int_t rpc_fd = { .data = fd, @@ -143,15 +134,10 @@ int fs_write(int fd, void *buf, size_t len) return wlen; } -int fs_close(int fd) +int fs_close(sd_t _fd) { - obj_handler_t hd; - int ret = ns_query("fs", &hd); - - if (ret < 0) - { - return ret; - } + obj_handler_t hd = mk_sd_init_raw(_fd).hd; + int fd = mk_sd_init_raw(_fd).fd; rpc_int_t rpc_fd = { .data = fd, @@ -165,15 +151,10 @@ int fs_close(int fd) return msg_tag_get_val(tag); } -int fs_lseek(int fd, int offs, int whence) +int fs_lseek(sd_t _fd, int offs, int whence) { - obj_handler_t hd; - int ret = ns_query("fs", &hd); - - if (ret < 0) - { - return ret; - } + obj_handler_t hd = mk_sd_init_raw(_fd).hd; + int fd =mk_sd_init_raw(_fd).fd; rpc_int_t rpc_fd = { .data = fd, diff --git a/mkrtos_user/lib/sys_svr/src/ns_cli.c b/mkrtos_user/lib/sys_svr/src/ns_cli.c index 08fcff208..2779d7ffa 100644 --- a/mkrtos_user/lib/sys_svr/src/ns_cli.c +++ b/mkrtos_user/lib/sys_svr/src/ns_cli.c @@ -23,7 +23,14 @@ typedef struct ns_cli_cache static ns_cli_cache_t ns_cli_cache; -static obj_handler_t find_hd(const char *path) +/** + * @brief TODO:加锁 + * + * @param path + * @param split_pos + * @return obj_handler_t + */ +static obj_handler_t find_hd(const char *path, int *split_pos) { int i = 0; int empty = -1; @@ -31,8 +38,13 @@ static obj_handler_t find_hd(const char *path) { if (ns_cli_cache.cache[i].path[0] != 0) { - if (strcmp(ns_cli_cache.cache[i].path, path) == 0) + char *new_str = strstr(ns_cli_cache.cache[i].path, path); + if (new_str && (new_str == ns_cli_cache.cache[i].path)) { + if (split_pos) + { + *split_pos = (int)(new_str - ns_cli_cache.cache[i].path); + } return ns_cli_cache.cache[i].hd; } } @@ -81,12 +93,13 @@ int ns_register(const char *path, obj_handler_t svr_hd) } int ns_query(const char *path, obj_handler_t *svr_hd) { + int inx = 0; assert(path); assert(svr_hd); obj_handler_t newfd; - newfd = find_hd(path); + newfd = find_hd(path, &inx); if (newfd != HANDLER_INVALID) { *svr_hd = newfd; @@ -101,8 +114,8 @@ int ns_query(const char *path, obj_handler_t *svr_hd) } rpc_ref_array_uint32_t_uint8_t_32_t rpc_path = { - .data = path, - .len = strlen(path) + 1, + .data = &path[inx], + .len = strlen(&path[inx]) + 1, }; rpc_obj_handler_t_t rpc_svr_hd = { .data = newfd, diff --git a/mkrtos_user/lib/sys_util/inc/u_rpc.h b/mkrtos_user/lib/sys_util/inc/u_rpc.h index deca319dc..42eca4343 100644 --- a/mkrtos_user/lib/sys_util/inc/u_rpc.h +++ b/mkrtos_user/lib/sys_util/inc/u_rpc.h @@ -326,7 +326,7 @@ RPC_ARRAY_DEF(uint32_t, uint8_t, 32) len += d->len * sizeof(d->data[0]); \ return len; \ } \ - RPC_CLI_BUF_TO_MSG_WITHOUT_IMPL(rpc_ref_array_uint32_t_uint8_t_32_t, int) \ + RPC_CLI_BUF_TO_MSG_WITHOUT_IMPL(rpc_ref_array_##len_type##_##data_type##_##length##_t, int) \ { \ if (rpc_align(len, __alignof(d->len)) > \ max) \ @@ -355,6 +355,8 @@ RPC_ARRAY_DEF(uint32_t, uint8_t, 32) * */ RPC_REF_ARRAY_DEF(uint32_t, uint8_t, 32) +RPC_REF_ARRAY_DEF(uint32_t, uint8_t, 48) +RPC_REF_ARRAY_DEF(uint32_t, uint8_t, 64) /** * @brief Construct a new rpc type def object diff --git a/mkrtos_user/lib/sys_util/src/u_app_loader.c b/mkrtos_user/lib/sys_util/src/u_app_loader.c index 838d8b6b9..31fdd1352 100644 --- a/mkrtos_user/lib/sys_util/src/u_app_loader.c +++ b/mkrtos_user/lib/sys_util/src/u_app_loader.c @@ -107,12 +107,12 @@ int app_load(const char *name, uenv_t *cur_env) { goto end_del_obj; } - tag = task_map(hd_task, LOG_PROT, LOG_PROT, 0); + tag = task_map(hd_task, LOG_PROT, LOG_PROT, KOBJ_DELETE_RIGHT); if (msg_tag_get_prot(tag) < 0) { goto end_del_obj; } - tag = task_map(hd_task, SYS_PROT, SYS_PROT, 0); + tag = task_map(hd_task, SYS_PROT, SYS_PROT, KOBJ_DELETE_RIGHT); if (msg_tag_get_prot(tag) < 0) { goto end_del_obj; @@ -127,12 +127,12 @@ int app_load(const char *name, uenv_t *cur_env) { goto end_del_obj; } - tag = task_map(hd_task, FACTORY_PROT, FACTORY_PROT, 0); + tag = task_map(hd_task, FACTORY_PROT, FACTORY_PROT, KOBJ_DELETE_RIGHT); if (msg_tag_get_prot(tag) < 0) { goto end_del_obj; } - tag = task_map(hd_task, MM_PROT, MM_PROT, 0); + tag = task_map(hd_task, MM_PROT, MM_PROT, KOBJ_DELETE_RIGHT); if (msg_tag_get_prot(tag) < 0) { goto end_del_obj; diff --git a/mkrtos_user/server/app/CMakeLists.txt b/mkrtos_user/server/app/CMakeLists.txt index 8bc4dbda3..209082b58 100644 --- a/mkrtos_user/server/app/CMakeLists.txt +++ b/mkrtos_user/server/app/CMakeLists.txt @@ -16,6 +16,7 @@ target_link_libraries(app.elf sys sys_util sys_svr + xtinymodbus stm32f1_bsp ${GCC_LIB_PATH}/libgcc.a ) @@ -28,6 +29,16 @@ target_include_directories( ${CMAKE_SOURCE_DIR}/mkrtos_user/server/app/drv ${CMAKE_SOURCE_DIR}/mkrtos_user/server/app/test + ${CMAKE_SOURCE_DIR}/mkrtos_user/server/app/modbus +#xtinymodbus + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/modbus/inc/modbus_base + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/modbus/inc/modbus_rtu_master + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/modbus/inc/modbus_rtu_slave + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/modbus/inc/port + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/modbus/inc/serial + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/modbus/inc +#end + ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/mlibc/arch/arm/ ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/mlibc/arch/generic ${CMAKE_SOURCE_DIR}/mkrtos_user/lib/mlibc/obj/src/internal diff --git a/mkrtos_user/server/app/drv/drv.c b/mkrtos_user/server/app/drv/drv.c index a5de1e47a..ce50c5cd8 100644 --- a/mkrtos_user/server/app/drv/drv.c +++ b/mkrtos_user/server/app/drv/drv.c @@ -19,14 +19,15 @@ #include "wk2xx_hw.h" #include "hmi_lcd_process.h" #include "music_control.h" +#include "MDM_RTU_APP.h" #include void music2_send_bytes(u8 *bytes, int len) { - /*在下面调用bsp的发送函数*/ - wk_TxChars(2,len,bytes); - //等待发送完成 - wk_wait_tx_done(2); + /*在下面调用bsp的发送函数*/ + wk_TxChars(2, len, bytes); + // 等待发送完成 + wk_wait_tx_done(2); } void drv_init(void) @@ -40,7 +41,6 @@ void drv_init(void) init_usart2(115200); init_usart3(115200); init_uart4(115200); - init_uart5(115200); ext_input_check(); wk2xx_hw_init(); Wk_DeInit(1); @@ -65,4 +65,6 @@ void drv_init(void) bluetooth_init_cfg(0, usart2_send_bytes); bluetooth_init_cfg(1, music2_send_bytes); + + MDM_RTU_APPInit(); } diff --git a/mkrtos_user/server/app/modbus/MDM_RTU_APP.c b/mkrtos_user/server/app/modbus/MDM_RTU_APP.c new file mode 100644 index 000000000..fff733e9e --- /dev/null +++ b/mkrtos_user/server/app/modbus/MDM_RTU_APP.c @@ -0,0 +1,229 @@ +/** + * @file MDM_RTU_APP.c + * @author zhangzheng (1358745329@qq.com) + * @brief https://github.com/lotoohe-space/XTinyModbus + * @version 0.1 + * @date 2023-10-03 + * + * @copyright Copyright (c) 2023 + * + */ + +/*********************************HEAD FILE************************************/ +#include "MDM_RTU_APP.h" +#include "MDM_RTU_Fun.h" +#include "MDM_RTU_Serial.h" +#include "MDM_RTU_User_Fun.h" +#include "MDM_RTU_RW_Man.h" +#include "u_sys.h" +#include "sysinfo.h" +/*********************************END******************************************/ +#define USE_RS485_DB 1 +/*********************************全局变量************************************/ +uint16 regDataMaster0[32] = {0}; +MapTableItem mapTableItemMaster0 = { + .modbusAddr = 0x0000, /*MODBUS中的地址*/ + .modbusData = regDataMaster0, /*映射的内存单元*/ + .modbusDataSize = 32, /*映射的大小*/ + .addrType = HOLD_REGS_TYPE, /*映射的类型*/ + .devAddr = 6, /*被哪个从机使用*/ +}; +uint16 regDataMaster1[32] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; +MapTableItem mapTableItemMaster1 = { + .modbusAddr = 0x0000, /*MODBUS中的地址*/ + .modbusData = regDataMaster1, /*映射的内存单元*/ + .modbusDataSize = 32, /*映射的大小*/ + .addrType = HOLD_REGS_TYPE, /*映射的类型*/ + .devAddr = 7, /*被哪个从机使用*/ +}; +uint16 regDataMaster2[32] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; +MapTableItem mapTableItemMaster2 = { + .modbusAddr = 0x0000, /*MODBUS中的地址*/ + .modbusData = regDataMaster2, /*映射的内存单元*/ + .modbusDataSize = 32, /*映射的大小*/ + .addrType = HOLD_REGS_TYPE, /*映射的类型*/ + .devAddr = 8, /*被哪个从机使用*/ +}; + +Modbus_RTU modbus_RTU = {0}; +Modbus_RTU_CB modbusRWRTUCB = {0}; +Modbus_RTU_CB modbusRWRTUCB1 = {0}; +Modbus_RTU_CB modbusRWRTUCB2 = {0}; +Modbus_RTU_CB modbusRWRTUCB3 = {0}; +Modbus_RTU_CB modbusRWRTUCB4 = {0}; +static uint8_t recv_buf[257]; +/*********************************结束******************************************/ + +/******************************************************* + * + * Function name :MDM_RTU_APPInit + * Description :主机用户APP初始化函数 + * Parameter :无 + * Return : TRUE success , FALSE fail + **********************************************************/ +BOOL MDM_RTU_APPInit(void) +{ + if (MDM_RTU_Init(&modbus_RTU, MDMInitSerial, 9600, 8, 1, 0) != ERR_NONE) + { + return FALSE; + } + MDM_RTU_QueueInit(&modbus_RTU, + recv_buf, + sizeof(recv_buf)); + + if (MDM_RTU_AddMapItem(&modbus_RTU, &mapTableItemMaster0) == FALSE) + { + return FALSE; + } + if (MDM_RTU_AddMapItem(&modbus_RTU, &mapTableItemMaster1) == FALSE) + { + return FALSE; + } + if (MDM_RTU_AddMapItem(&modbus_RTU, &mapTableItemMaster2) == FALSE) + { + return FALSE; + } + + /*RW控制块*/ + MDM_RTU_CB_Init(&modbusRWRTUCB, &modbus_RTU, 3000, 3000, 1); + MDM_RTU_CB_Init(&modbusRWRTUCB1, &modbus_RTU, 3000, 3000, 1); + MDM_RTU_CB_Init(&modbusRWRTUCB2, &modbus_RTU, 3000, 3000, 1); + MDM_RTU_CB_Init(&modbusRWRTUCB3, &modbus_RTU, 3000, 3000, 1); + MDM_RTU_CB_Init(&modbusRWRTUCB4, &modbus_RTU, 3000, 3000, 1); + return TRUE; +} +// uint16 temp = ~(0x5555); +// uint16 temp2 = 0x5555; +// uint16 temp1 = 1234; +// uint16 data1[] = {1, 2, 3, 4, 5, 6}; +#define MD_NB_MODE_TEST 1 +/*用户读取数据*/ +static void MDM_RTUUserRead(void) +{ + uint16 resTemp; +#if USE_RS485_DB +#if MD_NB_MODE_TEST + MDError res; + res = MDM_RTU_NB_ReadHoldReg(&modbusRWRTUCB, 6, 0, 11); + if (res != ERR_IDLE) + { + if (res != ERR_RW_FIN) + { /*出现错误*/ + if (res == ERR_RW_OV_TIME_ERR) + { /*超时了*/ + /*使能重传*/ + MDM_RTU_CB_OverTimeReset(&modbusRWRTUCB); + } + } + else + { + + /*读成功*/ + MDM_RTU_ReadRegs(modbusRWRTUCB.pModbus_RTU, 0x0000, 1, &resTemp, HOLD_REGS_TYPE, 6); + sys_info.noise[0] = (float)(resTemp) / 10.0f; + + MDM_RTU_ReadRegs(modbusRWRTUCB.pModbus_RTU, 10, 1, &resTemp, HOLD_REGS_TYPE, 6); + sys_info.noise_temp[0] = (float)(resTemp); + } + } + res = MDM_RTU_NB_ReadHoldReg(&modbusRWRTUCB1, 7, 0, 11); + if (res != ERR_IDLE) + { + if (res != ERR_RW_FIN) + { /*出现错误*/ + if (res == ERR_RW_OV_TIME_ERR) + { /*超时了*/ + /*使能重传*/ + MDM_RTU_CB_OverTimeReset(&modbusRWRTUCB1); + } + } + else + { + /*读成功*/ + MDM_RTU_ReadRegs(modbusRWRTUCB1.pModbus_RTU, 0x0000, 1, &resTemp, HOLD_REGS_TYPE, 7); + sys_info.noise[1] = (float)(resTemp) / 10.0f; + + MDM_RTU_ReadRegs(modbusRWRTUCB1.pModbus_RTU, 10, 1, &resTemp, HOLD_REGS_TYPE, 7); + sys_info.noise_temp[1] = (float)(resTemp); + } + } + res = MDM_RTU_NB_ReadHoldReg(&modbusRWRTUCB2, 8, 0, 11); + if (res != ERR_IDLE) + { + if (res != ERR_RW_FIN) + { /*出现错误*/ + if (res == ERR_RW_OV_TIME_ERR) + { /*超时了*/ + /*使能重传*/ + MDM_RTU_CB_OverTimeReset(&modbusRWRTUCB2); + } + } + else + { + /*读成功*/ + MDM_RTU_ReadRegs(modbusRWRTUCB2.pModbus_RTU, 0x0000, 1, &resTemp, HOLD_REGS_TYPE, 8); + sys_info.noise[2] = (float)(resTemp) / 10.0f; + + MDM_RTU_ReadRegs(modbusRWRTUCB2.pModbus_RTU, 10, 1, &resTemp, HOLD_REGS_TYPE, 8); + sys_info.noise_temp[2] = (float)(resTemp); + } + } +#else + + if (MDM_RTU_ReadCoil(&modbusRWRTUCB, 0x1, 0x0000, 16) == ERR_RW_FIN) + { + MDM_RTU_ReadBits(modbusRWRTUCB.pModbus_RTU, 0x0000, 16, (uint8 *)&resTemp, COILS_TYPE, 0x1); + resTemp = resTemp; + } +#endif +#endif +} + +// static void MDM_RTUUserWrite(void) +// { +// MDError res; +// #if MD_NB_MODE_TEST +// res = MDM_RTU_NB_WriteCoils(&modbusRWRTUCB1, 0x1, 0, 16, (uint8 *)(&temp)); +// if (res != ERR_IDLE) +// { +// if (res != ERR_RW_FIN) +// { /*出现错误*/ +// if (res == ERR_RW_OV_TIME_ERR) +// { /*超时了*/ +// /*使能重传*/ +// MDM_RTU_CB_OverTimeReset(&modbusRWRTUCB1); +// } +// } +// } +// res = MDM_RTU_NB_WriteCoils(&modbusRWRTUCB4, 0x1, 0, 16, (uint8 *)(&temp2)); +// if (res != ERR_IDLE) +// { +// if (res != ERR_RW_FIN) +// { /*出现错误*/ +// if (res == ERR_RW_OV_TIME_ERR) +// { /*超时了*/ +// /*使能重传*/ +// MDM_RTU_CB_OverTimeReset(&modbusRWRTUCB4); +// } +// } +// } +// #else +// MDM_RTU_WriteCoils(&modbusRWRTUCB1, 0x1, 0, 16, (uint8 *)(&temp)); +// MDM_RTU_WriteCoils(&modbusRWRTUCB4, 0x1, 0, 16, (uint8 *)(&temp2)); + +// // MDM_RTU_WriteRegs(&modbusRWRTUCB4,0x1,0,6,data1); +// #endif +// } +/*用户数据的读写*/ +static void MDM_RTU_UserUpdate(void) +{ + MDM_RTUUserRead(); + // MDM_RTUUserWrite(); +} + +/*Loop call*/ +void MDM_RTU_Loop(void) +{ + MDMTimeHandler100US(sys_read_tick() * 10); + MDM_RTU_UserUpdate(); +} diff --git a/mkrtos_user/server/app/modbus/MDM_RTU_APP.h b/mkrtos_user/server/app/modbus/MDM_RTU_APP.h new file mode 100644 index 000000000..b7fec4c2f --- /dev/null +++ b/mkrtos_user/server/app/modbus/MDM_RTU_APP.h @@ -0,0 +1,8 @@ +#ifndef _MDM_RTU_APP_H__ +#define _MDM_RTU_APP_H__ +#include "MD_RTU_Type.h" + +BOOL MDM_RTU_APPInit(void); +void MDM_RTU_Loop(void); + +#endif diff --git a/mkrtos_user/server/app/modbus/MDM_RTU_Serial.c b/mkrtos_user/server/app/modbus/MDM_RTU_Serial.c new file mode 100644 index 000000000..7dc2e8b58 --- /dev/null +++ b/mkrtos_user/server/app/modbus/MDM_RTU_Serial.c @@ -0,0 +1,124 @@ +/******************************************************************************** + * @File name: MD_RTU_Serial.c + * @Author: zspace + * @Emial: 1358745329@qq.com + * @Version: 1.0 + * @Date: 2020-4-10 + * @Description: Modbus RTU Serial related modules + * Open source address: https://github.com/lotoohe-space/XTinyModbus + ********************************************************************************/ + +/*********************************HEAD FILE************************************/ +#include "MDM_RTU_Serial.h" +#include "MD_RTU_Tool.h" +#include "wk2xx_hw.h" +#include "uart5.h" +#include "rs485.h" +#include +/*User-related header files*/ + +/*********************************END******************************************/ +#define WK_UART_NUM1 4 +/*********************************GLOBAL VARIABLE************************************/ +PModbusBase pModbusMBase = NULL; /*Modbus of the current serial port*/ +/*********************************END******************************************/ + +/*********************************FUNCTION DECLARATION************************************/ + +// void MDMTimeHandler100US(void); +/*********************************END******************************************/ + +/******************************************************* + * + * Function name :MDMInitSerial + * Description :Hardware initialization function, you can initialize the serial port here + * Parameter : + * @obj Host object pointer + * @baud Baud rate + * @dataBits Data bit + * @stopBit Stop bit + * @parity Parity bit + * Return :None + **********************************************************/ +void MDMInitSerial(void *obj, uint32 baud, uint8 dataBits, uint8 stopBit, uint8 parity) +{ + pModbusMBase = obj; + if (obj == NULL) + { + return; + } + + pModbusMBase->mdRTUSendBytesFunction = MDMSerialSendBytes; + pModbusMBase->mdRTURecSendConv = MDMSerialSWRecv_Send; + + /*Hardware initialization*/ + assert(baud == 9600); + Wk_SetBaud(WK_UART_NUM1, B9600); + init_uart5(B9600); +} +/******************************************************* + * + * Function name :MDMTimeHandler100US + * Description :Call this function in the timer + * Parameter :None + * Return :None + **********************************************************/ +void MDMTimeHandler100US(uint32 times) +{ + if (pModbusMBase == NULL) + { + return; + } + pModbusMBase->mdRTUTimeHandlerFunction(pModbusMBase, times); +} +/******************************************************* + * + * Function name :MDMSerialRecvByte + * Description :Bsp layer serial port interrupt receiving call this function + * Parameter : + * @byte Byte received + * Return : None + **********************************************************/ +void MDMSerialRecvByte(uint8 byte) +{ + if (pModbusMBase == NULL) + { + return; + } + pModbusMBase->mdRTURecByteFunction(pModbusMBase, byte); +} +/******************************************************* + * + * Function name :MDMSerialRecvByte + * Description :Switch to receive or send + * Parameter : + * @mode TRUE send, FALSE receive + * Return : None + **********************************************************/ +void MDMSerialSWRecv_Send(uint8 mode) +{ + /*Send and receive conversion*/ + /*Fill in the converted code below*/ + RS4850_RW_CONV = mode; + RS4851_RW_CONV = mode; + /*Different hardware may require a little delay after setting conversion*/ +} +/******************************************************* + * + * Function name :MDMSerialSendBytes + * Description :Send function + * Parameter : + * @bytes Data sent + * @num How many bytes to send + * Return : None + **********************************************************/ +void MDMSerialSendBytes(uint8 *bytes, uint16 num) +{ + + uart5_send_bytes(bytes, num); + + /*在下面调用bsp的发送函数*/ + wk_TxChars(WK_UART_NUM1, num, bytes); + // 等待发送完成 + wk_wait_tx_done(WK_UART_NUM1); +} diff --git a/mkrtos_user/server/app/modbus/MDM_RTU_Serial.h b/mkrtos_user/server/app/modbus/MDM_RTU_Serial.h new file mode 100644 index 000000000..33326abaf --- /dev/null +++ b/mkrtos_user/server/app/modbus/MDM_RTU_Serial.h @@ -0,0 +1,30 @@ +/******************************************************************************** + * @File name: MD_RTU_Serial.h + * @Author: zspace + * @Emial: 1358745329@qq.com + * @Version: 1.0 + * @Date: 2020-4-10 + * @Description: Modbus RTU Serial related modules + ********************************************************************************/ + +#ifndef _MDM_RTU_SERIAL_H__ +#define _MDM_RTU_SERIAL_H__ + +/*********************************HEAD FILE************************************/ +#include "MD_RTU_Type.h" +#include "MD_RTU_Config.h" +/*********************************END******************************************/ + +/*********************************Function declaration************************************/ +/*Hardware initialization function, you can initialize the serial port here*/ +void MDMInitSerial(void *obj, uint32 baud, uint8 dataBits, uint8 stopBit, uint8 parity); +/*Bsp layer interrupt receiving call this function*/ +void MDMSerialRecvByte(uint8 byte); +/*Call this function in the timer*/ +void MDMTimeHandler100US(uint32 times); + +void MDMSerialSendBytes(uint8 *bytes, uint16 num); +void MDMSerialSWRecv_Send(uint8 mode); +/*********************************END******************************************/ + +#endif diff --git a/mkrtos_user/server/fs/fatfs/main.c b/mkrtos_user/server/fs/fatfs/main.c index f85fe6646..2eed07216 100644 --- a/mkrtos_user/server/fs/fatfs/main.c +++ b/mkrtos_user/server/fs/fatfs/main.c @@ -17,13 +17,14 @@ int main(int args, char *argv[]) obj_handler_t ipc_hd; int ret = rpc_creaite_bind_ipc(THREAD_MAIN, NULL, &ipc_hd); assert(ret >= 0); - ns_register("fs", ipc_hd); + ns_register("/mnt", ipc_hd); fs_svr_init(ipc_hd); FRESULT res = f_mount(&fs, "0:", 1); if (res != FR_OK) { + assert(sizeof(FIL) >= FF_MAX_SS); res = f_mkfs("0:", &defopt, file_temp_buf_get(), FF_MAX_SS); // 第三个参数可以设置成NULL,默认使用heap memory if (res != FR_OK) { diff --git a/mkrtos_user/server/hello/src/main.c b/mkrtos_user/server/hello/src/main.c index 9310d92e6..4f923ddcd 100644 --- a/mkrtos_user/server/hello/src/main.c +++ b/mkrtos_user/server/hello/src/main.c @@ -1,8 +1,10 @@ -#include +// #include #include "u_log.h" +#include "u_env.h" int main(int argc, char *args[]) { - printf("Hello world.\n"); + // printf("Hello world.\n"); + ulog_write_str(u_get_global_env()->log_hd, "Hello world.\n"); return 0; } diff --git a/mkrtos_user/server/init/src/main.c b/mkrtos_user/server/init/src/main.c index 75145a3cb..60060effe 100644 --- a/mkrtos_user/server/init/src/main.c +++ b/mkrtos_user/server/init/src/main.c @@ -56,9 +56,7 @@ int main(int argc, char *args[]) printf("app load fail, 0x%x\n", ret); } // u_sleep_ms(500); - // u_sleep_ms(500); - ret = app_load("hello", &env); if (ret < 0) { diff --git a/mkrtos_user/server/init/src/namespace.c b/mkrtos_user/server/init/src/namespace.c index 07cecafb5..c14d72856 100644 --- a/mkrtos_user/server/init/src/namespace.c +++ b/mkrtos_user/server/init/src/namespace.c @@ -68,10 +68,11 @@ int namespace_query(const char *path, obj_handler_t *hd) { if (ns.ne_list[i].hd != HANDLER_INVALID) { - if (strncmp(ns.ne_list[i].path, path, NAMESPACE_PATH_LEN) == 0) + char *split_str = strstr(ns.ne_list[i].path, path); + if (split_str && (split_str == ns.ne_list[i].path)) { *hd = ns.ne_list[i].hd; - return 0; + return (int)(split_str - ns.ne_list[i].path); } } }