Browse Source

Merge pull request #427 from armink/master

更新FreeModbus主机及从机
Bernard Xiong 10 years ago
parent
commit
15129278d7

+ 4 - 1
components/net/freemodbus-v1.6.0/SConscript

@@ -7,7 +7,6 @@ modbus/functions/mbutils.c
 modbus/functions/mbfuncother.c
 modbus/rtu/mbcrc.c
 port/port.c
-port/user_mb_app.c
 """)
 
 master_rtu_src = Split("""
@@ -20,6 +19,7 @@ modbus/mb_m.c
 port/portevent_m.c
 port/portserial_m.c
 port/porttimer_m.c
+port/user_mb_app_m.c
 """)
 
 slave_rtu_src = Split("""
@@ -32,6 +32,7 @@ modbus/mb.c
 port/portevent.c
 port/portserial.c
 port/porttimer.c
+port/user_mb_app.c
 """)
 
 master_slave_rtu_src = Split("""
@@ -53,6 +54,8 @@ port/portserial.c
 port/portserial_m.c
 port/porttimer.c
 port/porttimer_m.c
+port/user_mb_app.c
+port/user_mb_app_m.c
 """)
 
 # The set of source files associated with this SConscript file.

+ 59 - 14
components/net/freemodbus-v1.6.0/modbus/functions/mbfunccoils_m.c

@@ -74,14 +74,24 @@ eMBException    prveMBError2Exception( eMBErrorCode eErrorCode );
 #if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
 #if MB_FUNC_READ_COILS_ENABLED > 0
 
+/**
+ * This function will request read coil.
+ *
+ * @param ucSndAddr salve address
+ * @param usCoilAddr coil start address
+ * @param usNCoils coil total number
+ * @param lTimeOut timeout (-1 will waiting forever)
+ *
+ * @return error code
+ */
 eMBMasterReqErrCode
-eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils )
+eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils ,LONG lTimeOut )
 {
     UCHAR                 *ucMBFrame;
     eMBMasterReqErrCode    eErrStatus = MB_MRE_NO_ERR;
 
-    if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
-    else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+    if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+    else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
     else
     {
 		vMBMasterGetPDUSndBuf(&ucMBFrame);
@@ -93,6 +103,8 @@ eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils )
 		ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF + 1] = usNCoils;
 		vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
 		( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
+		eErrStatus = eMBMasterWaitRequestFinish( );
+
     }
     return eErrStatus;
 }
@@ -108,7 +120,12 @@ eMBMasterFuncReadCoils( UCHAR * pucFrame, USHORT * usLen )
     eMBException    eStatus = MB_EX_NONE;
     eMBErrorCode    eRegStatus;
 
-    if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
+    /* If this request is broadcast, and it's read mode. This request don't need execute. */
+    if ( xMBMasterRequestIsBroadcast() )
+    {
+    	eStatus = MB_EX_NONE;
+    }
+    else if ( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
     {
     	vMBMasterGetPDUSndBuf(&ucMBFrame);
         usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 );
@@ -136,7 +153,7 @@ eMBMasterFuncReadCoils( UCHAR * pucFrame, USHORT * usLen )
             ( ucByteCount == pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF] ) )
         {
         	/* Make callback to fill the buffer. */
-            eRegStatus = eMBRegCoilsCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usCoilCount, MB_REG_READ );
+            eRegStatus = eMBMasterRegCoilsCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usCoilCount, MB_REG_READ );
 
             /* If an error occured convert it into a Modbus exception. */
             if( eRegStatus != MB_ENOERR )
@@ -161,15 +178,27 @@ eMBMasterFuncReadCoils( UCHAR * pucFrame, USHORT * usLen )
 
 #if MB_FUNC_WRITE_COIL_ENABLED > 0
 
+/**
+ * This function will request write one coil.
+ *
+ * @param ucSndAddr salve address
+ * @param usCoilAddr coil start address
+ * @param usCoilData data to be written
+ * @param lTimeOut timeout (-1 will waiting forever)
+ *
+ * @return error code
+ *
+ * @see eMBMasterReqWriteMultipleCoils
+ */
 eMBMasterReqErrCode
-eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData )
+eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData, LONG lTimeOut )
 {
     UCHAR                 *ucMBFrame;
     eMBMasterReqErrCode    eErrStatus = MB_MRE_NO_ERR;
 
-    if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
-    else if ( usCoilAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+    if ( usCoilAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
     else if ( ( usCoilData != 0xFF00 ) && ( usCoilData != 0x0000 ) ) eErrStatus = MB_MRE_ILL_ARG;
+    else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
     else
     {
 		vMBMasterGetPDUSndBuf(&ucMBFrame);
@@ -181,6 +210,7 @@ eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData )
 		ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usCoilData;
 		vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE );
 		( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
+		eErrStatus = eMBMasterWaitRequestFinish( );
     }
     return eErrStatus;
 }
@@ -214,7 +244,7 @@ eMBMasterFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen )
                 ucBuf[0] = 0;
             }
             eRegStatus =
-                eMBRegCoilsCB( &ucBuf[0], usRegAddress, 1, MB_REG_WRITE );
+                eMBMasterRegCoilsCB( &ucBuf[0], usRegAddress, 1, MB_REG_WRITE );
 
             /* If an error occured convert it into a Modbus exception. */
             if( eRegStatus != MB_ENOERR )
@@ -240,18 +270,31 @@ eMBMasterFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen )
 
 #if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0
 
+/**
+ * This function will request write multiple coils.
+ *
+ * @param ucSndAddr salve address
+ * @param usCoilAddr coil start address
+ * @param usNCoils coil total number
+ * @param usCoilData data to be written
+ * @param lTimeOut timeout (-1 will waiting forever)
+ *
+ * @return error code
+ *
+ * @see eMBMasterReqWriteCoil
+ */
 eMBMasterReqErrCode
 eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr,
-		USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer )
+		USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer, LONG lTimeOut)
 {
     UCHAR                 *ucMBFrame;
     USHORT                 usRegIndex = 0;
     UCHAR                  ucByteCount;
     eMBMasterReqErrCode    eErrStatus = MB_MRE_NO_ERR;
 
-    if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
-    else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+    if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
     else if ( usNCoils > MB_PDU_REQ_WRITE_MUL_COILCNT_MAX ) eErrStatus = MB_MRE_ILL_ARG;
+    else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
     else
     {
 		vMBMasterGetPDUSndBuf(&ucMBFrame);
@@ -277,6 +320,7 @@ eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr,
 		}
 		vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + ucByteCount );
 		( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
+		eErrStatus = eMBMasterWaitRequestFinish( );
     }
     return eErrStatus;
 }
@@ -293,7 +337,8 @@ eMBMasterFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen )
     eMBException    eStatus = MB_EX_NONE;
     eMBErrorCode    eRegStatus;
 
-    if( *usLen == MB_PDU_FUNC_WRITE_MUL_SIZE )
+    /* If this request is broadcast, the *usLen is not need check. */
+    if( ( *usLen == MB_PDU_FUNC_WRITE_MUL_SIZE ) || xMBMasterRequestIsBroadcast() )
     {
     	vMBMasterGetPDUSndBuf(&ucMBFrame);
         usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8 );
@@ -318,7 +363,7 @@ eMBMasterFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen )
         if( ( usCoilCnt >= 1 ) && ( ucByteCountVerify == ucByteCount ) )
         {
             eRegStatus =
-                eMBRegCoilsCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF],
+                eMBMasterRegCoilsCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF],
                                usRegAddress, usCoilCnt, MB_REG_WRITE );
 
             /* If an error occured convert it into a Modbus exception. */

+ 22 - 6
components/net/freemodbus-v1.6.0/modbus/functions/mbfuncdisc_m.c

@@ -57,16 +57,26 @@ eMBException    prveMBError2Exception( eMBErrorCode eErrorCode );
 
 /* ----------------------- Start implementation -----------------------------*/
 #if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
-#if MB_FUNC_READ_COILS_ENABLED > 0
+#if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED > 0
 
+/**
+ * This function will request read discrete inputs.
+ *
+ * @param ucSndAddr salve address
+ * @param usDiscreteAddr discrete start address
+ * @param usNDiscreteIn discrete total number
+ * @param lTimeOut timeout (-1 will waiting forever)
+ *
+ * @return error code
+ */
 eMBMasterReqErrCode
-eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn )
+eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn, LONG lTimeOut )
 {
     UCHAR                 *ucMBFrame;
     eMBMasterReqErrCode    eErrStatus = MB_MRE_NO_ERR;
 
-    if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
-    else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+    if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+    else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
     else
     {
 		vMBMasterGetPDUSndBuf(&ucMBFrame);
@@ -78,6 +88,7 @@ eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT u
 		ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF + 1] = usNDiscreteIn;
 		vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
 		( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
+		eErrStatus = eMBMasterWaitRequestFinish( );
     }
     return eErrStatus;
 }
@@ -93,7 +104,12 @@ eMBMasterFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen )
     eMBException    eStatus = MB_EX_NONE;
     eMBErrorCode    eRegStatus;
 
-    if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
+    /* If this request is broadcast, and it's read mode. This request don't need execute. */
+    if ( xMBMasterRequestIsBroadcast() )
+    {
+    	eStatus = MB_EX_NONE;
+    }
+    else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
     {
     	vMBMasterGetPDUSndBuf(&ucMBFrame);
         usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 );
@@ -120,7 +136,7 @@ eMBMasterFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen )
 		if ((usDiscreteCnt >= 1) && ucNBytes == pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF])
         {
 	       	/* Make callback to fill the buffer. */
-			eRegStatus = eMBRegDiscreteCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usDiscreteCnt );
+			eRegStatus = eMBMasterRegDiscreteCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usDiscreteCnt );
 
 			/* If an error occured convert it into a Modbus exception. */
 			if( eRegStatus != MB_ENOERR )

+ 80 - 21
components/net/freemodbus-v1.6.0/modbus/functions/mbfuncholding_m.c

@@ -86,14 +86,24 @@ eMBException    prveMBError2Exception( eMBErrorCode eErrorCode );
 #if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
 #if MB_FUNC_WRITE_HOLDING_ENABLED > 0
 
+/**
+ * This function will request write holding register.
+ *
+ * @param ucSndAddr salve address
+ * @param usRegAddr register start address
+ * @param usRegData register data to be written
+ * @param lTimeOut timeout (-1 will waiting forever)
+ *
+ * @return error code
+ */
 eMBMasterReqErrCode
-eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData )
+eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut )
 {
     UCHAR                 *ucMBFrame;
     eMBMasterReqErrCode    eErrStatus = MB_MRE_NO_ERR;
 
-    if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
-    else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+    if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+    else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
     else
     {
 		vMBMasterGetPDUSndBuf(&ucMBFrame);
@@ -105,6 +115,7 @@ eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRe
 		ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usRegData ;
 		vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE );
 		( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
+		eErrStatus = eMBMasterWaitRequestFinish( );
     }
     return eErrStatus;
 }
@@ -123,7 +134,7 @@ eMBMasterFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
         usRegAddress++;
 
         /* Make callback to update the value. */
-        eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF],
+        eRegStatus = eMBMasterRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF],
                                       usRegAddress, 1, MB_REG_WRITE );
 
         /* If an error occured convert it into a Modbus exception. */
@@ -143,16 +154,27 @@ eMBMasterFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
 
 #if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0
 
+/**
+ * This function will request write multiple holding register.
+ *
+ * @param ucSndAddr salve address
+ * @param usRegAddr register start address
+ * @param usNRegs register total number
+ * @param pusDataBuffer data to be written
+ * @param lTimeOut timeout (-1 will waiting forever)
+ *
+ * @return error code
+ */
 eMBMasterReqErrCode
 eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr,
-		USHORT usRegAddr, USHORT usNRegs, USHORT * pusDataBuffer )
+		USHORT usRegAddr, USHORT usNRegs, USHORT * pusDataBuffer, LONG lTimeOut )
 {
     UCHAR                 *ucMBFrame;
     USHORT                 usRegIndex = 0;
     eMBMasterReqErrCode    eErrStatus = MB_MRE_NO_ERR;
 
-    if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
-    else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+    if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+    else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
     else
     {
 		vMBMasterGetPDUSndBuf(&ucMBFrame);
@@ -171,6 +193,7 @@ eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr,
 		}
 		vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + 2*usNRegs );
 		( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
+		eErrStatus = eMBMasterWaitRequestFinish( );
     }
     return eErrStatus;
 }
@@ -186,7 +209,8 @@ eMBMasterFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
     eMBException    eStatus = MB_EX_NONE;
     eMBErrorCode    eRegStatus;
 
-    if( *usLen == MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_MUL_SIZE )
+    /* If this request is broadcast, the *usLen is not need check. */
+    if( ( *usLen == MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_MUL_SIZE ) || xMBMasterRequestIsBroadcast() )
     {
 		vMBMasterGetPDUSndBuf(&ucMBFrame);
         usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] << 8 );
@@ -202,7 +226,7 @@ eMBMasterFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
         {
             /* Make callback to update the register values. */
             eRegStatus =
-                eMBRegHoldingCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF],
+                eMBMasterRegHoldingCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF],
                                  usRegAddress, usRegCount, MB_REG_WRITE );
 
             /* If an error occured convert it into a Modbus exception. */
@@ -227,14 +251,24 @@ eMBMasterFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
 
 #if MB_FUNC_READ_HOLDING_ENABLED > 0
 
+/**
+ * This function will request read holding register.
+ *
+ * @param ucSndAddr salve address
+ * @param usRegAddr register start address
+ * @param usNRegs register total number
+ * @param lTimeOut timeout (-1 will waiting forever)
+ *
+ * @return error code
+ */
 eMBMasterReqErrCode
-eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs )
+eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut )
 {
     UCHAR                 *ucMBFrame;
     eMBMasterReqErrCode    eErrStatus = MB_MRE_NO_ERR;
 
-    if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
-    else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+    if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+    else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
     else
     {
 		vMBMasterGetPDUSndBuf(&ucMBFrame);
@@ -246,6 +280,7 @@ eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRe
 		ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs;
 		vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
 		( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
+		eErrStatus = eMBMasterWaitRequestFinish( );
     }
     return eErrStatus;
 }
@@ -260,7 +295,12 @@ eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
     eMBException    eStatus = MB_EX_NONE;
     eMBErrorCode    eRegStatus;
 
-    if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
+    /* If this request is broadcast, and it's read mode. This request don't need execute. */
+    if ( xMBMasterRequestIsBroadcast() )
+    {
+    	eStatus = MB_EX_NONE;
+    }
+    else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
     {
 		vMBMasterGetPDUSndBuf(&ucMBFrame);
         usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 );
@@ -268,7 +308,7 @@ eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
         usRegAddress++;
 
         usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] << 8 );
-        usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] );
+        usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] );
 
         /* Check if the number of registers to read is valid. If not
          * return Modbus illegal data value exception.
@@ -276,7 +316,7 @@ eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
         if( ( usRegCount >= 1 ) && ( 2 * usRegCount == pucFrame[MB_PDU_FUNC_READ_BYTECNT_OFF] ) )
         {
             /* Make callback to fill the buffer. */
-            eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount, MB_REG_READ );
+            eRegStatus = eMBMasterRegHoldingCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount, MB_REG_READ );
             /* If an error occured convert it into a Modbus exception. */
             if( eRegStatus != MB_ENOERR )
             {
@@ -300,17 +340,30 @@ eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
 
 #if MB_FUNC_READWRITE_HOLDING_ENABLED > 0
 
+/**
+ * This function will request read and write holding register.
+ *
+ * @param ucSndAddr salve address
+ * @param usReadRegAddr read register start address
+ * @param usNReadRegs read register total number
+ * @param pusDataBuffer data to be written
+ * @param usWriteRegAddr write register start address
+ * @param usNWriteRegs write register total number
+ * @param lTimeOut timeout (-1 will waiting forever)
+ *
+ * @return error code
+ */
 eMBMasterReqErrCode
 eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr,
 		USHORT usReadRegAddr, USHORT usNReadRegs, USHORT * pusDataBuffer,
-		USHORT usWriteRegAddr, USHORT usNWriteRegs )
+		USHORT usWriteRegAddr, USHORT usNWriteRegs, LONG lTimeOut )
 {
     UCHAR                 *ucMBFrame;
     USHORT                 usRegIndex = 0;
     eMBMasterReqErrCode    eErrStatus = MB_MRE_NO_ERR;
 
-    if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
-    else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+    if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+    else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
     else
     {
 		vMBMasterGetPDUSndBuf(&ucMBFrame);
@@ -333,6 +386,7 @@ eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr,
 		}
 		vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READWRITE_SIZE_MIN + 2*usNWriteRegs );
 		( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
+		eErrStatus = eMBMasterWaitRequestFinish( );
     }
     return eErrStatus;
 }
@@ -349,7 +403,12 @@ eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen
     eMBException    eStatus = MB_EX_NONE;
     eMBErrorCode    eRegStatus;
 
-    if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READWRITE_SIZE_MIN)
+    /* If this request is broadcast, and it's read mode. This request don't need execute. */
+    if ( xMBMasterRequestIsBroadcast() )
+    {
+    	eStatus = MB_EX_NONE;
+    }
+    else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READWRITE_SIZE_MIN )
     {
     	vMBMasterGetPDUSndBuf(&ucMBFrame);
         usRegReadAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF] << 8U );
@@ -369,13 +428,13 @@ eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen
         if( ( 2 * usRegReadCount ) == pucFrame[MB_PDU_FUNC_READWRITE_READ_BYTECNT_OFF] )
         {
             /* Make callback to update the register values. */
-            eRegStatus = eMBRegHoldingCB( &ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF],
+            eRegStatus = eMBMasterRegHoldingCB( &ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF],
                                            usRegWriteAddress, usRegWriteCount, MB_REG_WRITE );
 
             if( eRegStatus == MB_ENOERR )
             {
                 /* Make the read callback. */
-				eRegStatus = eMBRegHoldingCB(&pucFrame[MB_PDU_FUNC_READWRITE_READ_VALUES_OFF],
+				eRegStatus = eMBMasterRegHoldingCB(&pucFrame[MB_PDU_FUNC_READWRITE_READ_VALUES_OFF],
 						                      usRegReadAddress, usRegReadCount, MB_REG_READ);
             }
             if( eRegStatus != MB_ENOERR )

+ 22 - 6
components/net/freemodbus-v1.6.0/modbus/functions/mbfuncinput_m.c

@@ -59,14 +59,24 @@ eMBException    prveMBError2Exception( eMBErrorCode eErrorCode );
 #if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
 #if MB_FUNC_READ_INPUT_ENABLED > 0
 
+/**
+ * This function will request read input register.
+ *
+ * @param ucSndAddr salve address
+ * @param usRegAddr register start address
+ * @param usNRegs register total number
+ * @param lTimeOut timeout (-1 will waiting forever)
+ *
+ * @return error code
+ */
 eMBMasterReqErrCode
-eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs )
+eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut )
 {
     UCHAR                 *ucMBFrame;
     eMBMasterReqErrCode    eErrStatus = MB_MRE_NO_ERR;
 
-    if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY;
-    else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+    if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG;
+    else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
     else
     {
 		vMBMasterGetPDUSndBuf(&ucMBFrame);
@@ -78,6 +88,7 @@ eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs
 		ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs;
 		vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
 		( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT );
+		eErrStatus = eMBMasterWaitRequestFinish( );
     }
     return eErrStatus;
 }
@@ -92,7 +103,12 @@ eMBMasterFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen )
     eMBException    eStatus = MB_EX_NONE;
     eMBErrorCode    eRegStatus;
 
-    if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN)
+    /* If this request is broadcast, and it's read mode. This request don't need execute. */
+	if ( xMBMasterRequestIsBroadcast() )
+	{
+		eStatus = MB_EX_NONE;
+	}
+	else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
     {
 		vMBMasterGetPDUSndBuf(&ucMBFrame);
         usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 );
@@ -100,7 +116,7 @@ eMBMasterFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen )
         usRegAddress++;
 
         usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] << 8 );
-        usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] );
+        usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] );
 
         /* Check if the number of registers to read is valid. If not
          * return Modbus illegal data value exception.
@@ -108,7 +124,7 @@ eMBMasterFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen )
         if( ( usRegCount >= 1 ) && ( 2 * usRegCount == pucFrame[MB_PDU_FUNC_READ_BYTECNT_OFF] ) )
         {
             /* Make callback to fill the buffer. */
-            eRegStatus = eMBRegInputCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount );
+            eRegStatus = eMBMasterRegInputCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount );
             /* If an error occured convert it into a Modbus exception. */
             if( eRegStatus != MB_ENOERR )
             {

+ 162 - 18
components/net/freemodbus-v1.6.0/modbus/include/mb_m.h

@@ -77,13 +77,10 @@ typedef enum
     MB_MRE_NO_ERR,                  /*!< no error. */
     MB_MRE_NO_REG,                  /*!< illegal register address. */
     MB_MRE_ILL_ARG,                 /*!< illegal argument. */
-    MB_MRE_PORT_ERR,                /*!< porting layer error. */
-    MB_MRE_NO_RES,                  /*!< insufficient resources. */
-    MB_MRE_IO,                      /*!< I/O error. */
-    MB_MRE_ILL_STATE,               /*!< protocol stack in illegal state. */
+    MB_MRE_REV_DATA,                /*!< receive data error. */
     MB_MRE_TIMEDOUT,                /*!< timeout error occurred. */
     MB_MRE_MASTER_BUSY,             /*!< master is busy now. */
-    MB_MRE_SLAVE_EXCE               /*!< slave has exception. */
+    MB_MRE_EXE_FUN                  /*!< execute function error. */
 } eMBMasterReqErrCode;
 /*! \ingroup modbus
  *  \brief TimerMode is Master 3 kind of Timer modes.
@@ -189,31 +186,176 @@ eMBErrorCode    eMBMasterDisable( void );
  */
 eMBErrorCode    eMBMasterPoll( void );
 
+/*! \ingroup modbus
+ * \brief Registers a callback handler for a given function code.
+ *
+ * This function registers a new callback handler for a given function code.
+ * The callback handler supplied is responsible for interpreting the Modbus PDU and
+ * the creation of an appropriate response. In case of an error it should return
+ * one of the possible Modbus exceptions which results in a Modbus exception frame
+ * sent by the protocol stack.
+ *
+ * \param ucFunctionCode The Modbus function code for which this handler should
+ *   be registers. Valid function codes are in the range 1 to 127.
+ * \param pxHandler The function handler which should be called in case
+ *   such a frame is received. If \c NULL a previously registered function handler
+ *   for this function code is removed.
+ *
+ * \return eMBErrorCode::MB_ENOERR if the handler has been installed. If no
+ *   more resources are available it returns eMBErrorCode::MB_ENORES. In this
+ *   case the values in mbconfig.h should be adjusted. If the argument was not
+ *   valid it returns eMBErrorCode::MB_EINVAL.
+ */
+eMBErrorCode    eMBMasterRegisterCB( UCHAR ucFunctionCode,
+                               pxMBFunctionHandler pxHandler );
+
+/* ----------------------- Callback -----------------------------------------*/
+
+/*! \defgroup modbus_master registers Modbus Registers
+ * \code #include "mb_m.h" \endcode
+ * The protocol stack does not internally allocate any memory for the
+ * registers. This makes the protocol stack very small and also usable on
+ * low end targets. In addition the values don't have to be in the memory
+ * and could for example be stored in a flash.<br>
+ * Whenever the protocol stack requires a value it calls one of the callback
+ * function with the register address and the number of registers to read
+ * as an argument. The application should then read the actual register values
+ * (for example the ADC voltage) and should store the result in the supplied
+ * buffer.<br>
+ * If the protocol stack wants to update a register value because a write
+ * register function was received a buffer with the new register values is
+ * passed to the callback function. The function should then use these values
+ * to update the application register values.
+ */
+
+/*! \ingroup modbus_registers
+ * \brief Callback function used if the value of a <em>Input Register</em>
+ *   is required by the protocol stack. The starting register address is given
+ *   by \c usAddress and the last register is given by <tt>usAddress +
+ *   usNRegs - 1</tt>.
+ *
+ * \param pucRegBuffer A buffer where the callback function should write
+ *   the current value of the modbus registers to.
+ * \param usAddress The starting address of the register. Input registers
+ *   are in the range 1 - 65535.
+ * \param usNRegs Number of registers the callback function must supply.
+ *
+ * \return The function must return one of the following error codes:
+ *   - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
+ *       Modbus response is sent.
+ *   - eMBErrorCode::MB_ENOREG If the application does not map an coils
+ *       within the requested address range. In this case a
+ *       <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
+ */
+eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress,
+		USHORT usNRegs );
+
+/*! \ingroup modbus_registers
+ * \brief Callback function used if a <em>Holding Register</em> value is
+ *   read or written by the protocol stack. The starting register address
+ *   is given by \c usAddress and the last register is given by
+ *   <tt>usAddress + usNRegs - 1</tt>.
+ *
+ * \param pucRegBuffer If the application registers values should be updated the
+ *   buffer points to the new registers values. If the protocol stack needs
+ *   to now the current values the callback function should write them into
+ *   this buffer.
+ * \param usAddress The starting address of the register.
+ * \param usNRegs Number of registers to read or write.
+ * \param eMode If eMBRegisterMode::MB_REG_WRITE the application register
+ *   values should be updated from the values in the buffer. For example
+ *   this would be the case when the Modbus master has issued an
+ *   <b>WRITE SINGLE REGISTER</b> command.
+ *   If the value eMBRegisterMode::MB_REG_READ the application should copy
+ *   the current values into the buffer \c pucRegBuffer.
+ *
+ * \return The function must return one of the following error codes:
+ *   - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
+ *       Modbus response is sent.
+ *   - eMBErrorCode::MB_ENOREG If the application does not map an coils
+ *       within the requested address range. In this case a
+ *       <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
+ */
+eMBErrorCode eMBMasterRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress,
+		USHORT usNRegs, eMBRegisterMode eMode );
+
+/*! \ingroup modbus_registers
+ * \brief Callback function used if a <em>Coil Register</em> value is
+ *   read or written by the protocol stack. If you are going to use
+ *   this function you might use the functions xMBUtilSetBits(  ) and
+ *   xMBUtilGetBits(  ) for working with bitfields.
+ *
+ * \param pucRegBuffer The bits are packed in bytes where the first coil
+ *   starting at address \c usAddress is stored in the LSB of the
+ *   first byte in the buffer <code>pucRegBuffer</code>.
+ *   If the buffer should be written by the callback function unused
+ *   coil values (I.e. if not a multiple of eight coils is used) should be set
+ *   to zero.
+ * \param usAddress The first coil number.
+ * \param usNCoils Number of coil values requested.
+ * \param eMode If eMBRegisterMode::MB_REG_WRITE the application values should
+ *   be updated from the values supplied in the buffer \c pucRegBuffer.
+ *   If eMBRegisterMode::MB_REG_READ the application should store the current
+ *   values in the buffer \c pucRegBuffer.
+ *
+ * \return The function must return one of the following error codes:
+ *   - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
+ *       Modbus response is sent.
+ *   - eMBErrorCode::MB_ENOREG If the application does not map an coils
+ *       within the requested address range. In this case a
+ *       <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
+ */
+eMBErrorCode eMBMasterRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress,
+		USHORT usNCoils, eMBRegisterMode eMode );
+
+/*! \ingroup modbus_registers
+ * \brief Callback function used if a <em>Input Discrete Register</em> value is
+ *   read by the protocol stack.
+ *
+ * If you are going to use his function you might use the functions
+ * xMBUtilSetBits(  ) and xMBUtilGetBits(  ) for working with bitfields.
+ *
+ * \param pucRegBuffer The buffer should be updated with the current
+ *   coil values. The first discrete input starting at \c usAddress must be
+ *   stored at the LSB of the first byte in the buffer. If the requested number
+ *   is not a multiple of eight the remaining bits should be set to zero.
+ * \param usAddress The starting address of the first discrete input.
+ * \param usNDiscrete Number of discrete input values.
+ * \return The function must return one of the following error codes:
+ *   - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal
+ *       Modbus response is sent.
+ *   - eMBErrorCode::MB_ENOREG If the application does not map an coils
+ *       within the requested address range. In this case a
+ *       <b>ILLEGAL DATA ADDRESS</b> is sent as a response.
+ */
+eMBErrorCode eMBMasterRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress,
+		USHORT usNDiscrete );
 
 /*! \ingroup modbus
  *\brief These Modbus functions are called for user when Modbus run in Master Mode.
  */
 eMBMasterReqErrCode
-eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs );
+eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut );
 eMBMasterReqErrCode
-eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData );
+eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut );
 eMBMasterReqErrCode
-eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, USHORT * pusDataBuffer );
+eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr,
+		USHORT usNRegs, USHORT * pusDataBuffer, LONG lTimeOut );
 eMBMasterReqErrCode
-eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs );
+eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut );
 eMBMasterReqErrCode
 eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr,
 		USHORT usReadRegAddr, USHORT usNReadRegs, USHORT * pusDataBuffer,
-		USHORT usWriteRegAddr, USHORT usNWriteRegs );
+		USHORT usWriteRegAddr, USHORT usNWriteRegs, LONG lTimeOut );
 eMBMasterReqErrCode
-eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils );
+eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils, LONG lTimeOut );
 eMBMasterReqErrCode
-eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData );
+eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData, LONG lTimeOut );
 eMBMasterReqErrCode
 eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr,
-		USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer );
+		USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer, LONG lTimeOut );
 eMBMasterReqErrCode
-eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn );
+eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn, LONG lTimeOut );
 
 eMBException
 eMBMasterFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen );
@@ -239,16 +381,18 @@ eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen
 /*£¡ \ingroup modbus
  *\brief These functions are interface for Modbus Master
  */
-BOOL xMBMasterGetIsBusy( void );
 void vMBMasterGetPDUSndBuf( UCHAR ** pucFrame );
 UCHAR ucMBMasterGetDestAddress( void );
 void vMBMasterSetDestAddress( UCHAR Address );
-void vMBMasterSetIsBusy( BOOL IsBusy );
 BOOL xMBMasterGetCBRunInMasterMode( void );
 void vMBMasterSetCBRunInMasterMode( BOOL IsMasterMode );
-UCHAR ucMBMasterGetPDUSndLength( void );
-void vMBMasterSetPDUSndLength( UCHAR SendPDULength );
+USHORT usMBMasterGetPDUSndLength( void );
+void vMBMasterSetPDUSndLength( USHORT SendPDULength );
 void vMBMasterSetCurTimerMode( eMBMasterTimerMode eMBTimerMode );
+BOOL xMBMasterRequestIsBroadcast( void );
+eMBMasterErrorEventType eMBMasterGetErrorType( void );
+void vMBMasterSetErrorType( eMBMasterErrorEventType errorType );
+eMBMasterReqErrCode eMBMasterWaitRequestFinish( void );
 
 /* ----------------------- Callback -----------------------------------------*/
 

+ 3 - 3
components/net/freemodbus-v1.6.0/modbus/include/mbconfig.h

@@ -115,9 +115,9 @@ PR_BEGIN_EXTERN_C
 /*! \brief If master send a frame which is not broadcast,the master will wait sometime for slave.
  * And if slave is not respond in this time,the master will process this timeout error.
  * Then master can send other frame */
-#define MB_MASTER_TIMEOUT_MS_RESPOND            (2000)
-/*! \brief The total slaves in Modbus Master system.Default 16.
- * Note : The slave ID must be continuous from 0.*/
+#define MB_MASTER_TIMEOUT_MS_RESPOND            (100 )
+/*! \brief The total slaves in Modbus Master system. Default 16.
+ * \note : The slave ID must be continuous from 1.*/
 #define MB_MASTER_TOTAL_SLAVE_NUM               ( 16 )
 #endif
 

+ 40 - 10
components/net/freemodbus-v1.6.0/modbus/include/mbport.h

@@ -36,25 +36,38 @@
 PR_BEGIN_EXTERN_C
 #endif
 
+/* ----------------------- Defines ------------------------------------------*/
+
 /* ----------------------- Type definitions ---------------------------------*/
 
 typedef enum
 {
-    EV_READY,                   /*!< Startup finished. */
-    EV_FRAME_RECEIVED,          /*!< Frame received. */
-    EV_EXECUTE,                 /*!< Execute function. */
-    EV_FRAME_SENT               /*!< Frame sent. */
+    EV_READY            = 1<<0,         /*!< Startup finished. */
+    EV_FRAME_RECEIVED   = 1<<1,         /*!< Frame received. */
+    EV_EXECUTE          = 1<<2,         /*!< Execute function. */
+    EV_FRAME_SENT       = 1<<3          /*!< Frame sent. */
 } eMBEventType;
 
 typedef enum
 {
-    EV_MASTER_READY,                   /*!< Startup finished. */
-    EV_MASTER_FRAME_RECEIVED,          /*!< Frame received. */
-    EV_MASTER_EXECUTE,                 /*!< Execute function. */
-    EV_MASTER_FRAME_SENT,              /*!< Frame sent. */
-    EV_MASTER_ERROR_PROCESS            /*!< Frame error process*/
+    EV_MASTER_READY                    = 1<<0,  /*!< Startup finished. */
+    EV_MASTER_FRAME_RECEIVED           = 1<<1,  /*!< Frame received. */
+    EV_MASTER_EXECUTE                  = 1<<2,  /*!< Execute function. */
+    EV_MASTER_FRAME_SENT               = 1<<3,  /*!< Frame sent. */
+    EV_MASTER_ERROR_PROCESS            = 1<<4,  /*!< Frame error process. */
+    EV_MASTER_PROCESS_SUCESS           = 1<<5,  /*!< Request process success. */
+    EV_MASTER_ERROR_RESPOND_TIMEOUT    = 1<<6,  /*!< Request respond timeout. */
+    EV_MASTER_ERROR_RECEIVE_DATA       = 1<<7,  /*!< Request receive data error. */
+    EV_MASTER_ERROR_EXECUTE_FUNCTION   = 1<<8,  /*!< Request execute function error. */
 } eMBMasterEventType;
 
+typedef enum
+{
+    EV_ERROR_RESPOND_TIMEOUT,         /*!< Slave respond timeout. */
+    EV_ERROR_RECEIVE_DATA,            /*!< Receive frame data erroe. */
+    EV_ERROR_EXECUTE_FUNCTION,        /*!< Execute function error. */
+} eMBMasterErrorEventType;
+
 /*! \ingroup modbus
  * \brief Parity used for characters in serial mode.
  *
@@ -82,6 +95,12 @@ BOOL            xMBMasterPortEventPost( eMBMasterEventType eEvent );
 
 BOOL            xMBMasterPortEventGet(  /*@out@ */ eMBMasterEventType * eEvent );
 
+void            vMBMasterOsResInit( void );
+
+BOOL            xMBMasterRunResTake( int32_t time );
+
+void            vMBMasterRunResRelease( void );
+
 /* ----------------------- Serial port functions ----------------------------*/
 
 BOOL            xMBPortSerialInit( UCHAR ucPort, ULONG ulBaudRate,
@@ -97,7 +116,6 @@ INLINE BOOL     xMBPortSerialGetByte( CHAR * pucByte );
 
 INLINE BOOL     xMBPortSerialPutByte( CHAR ucByte );
 
-
 BOOL            xMBMasterPortSerialInit( UCHAR ucPort, ULONG ulBaudRate,
                                    UCHAR ucDataBits, eMBParity eParity );
 
@@ -132,6 +150,18 @@ INLINE void     vMBMasterPortTimersRespondTimeoutEnable( void );
 
 INLINE void     vMBMasterPortTimersDisable( void );
 
+/* ----------------- Callback for the master error process ------------------*/
+void            vMBMasterErrorCBRespondTimeout( UCHAR ucDestAddress, const UCHAR* pucPDUData,
+                                                USHORT ucPDULength );
+
+void            vMBMasterErrorCBReceiveData( UCHAR ucDestAddress, const UCHAR* pucPDUData,
+                                             USHORT ucPDULength );
+
+void            vMBMasterErrorCBExecuteFunction( UCHAR ucDestAddress, const UCHAR* pucPDUData,
+                                                 USHORT ucPDULength );
+
+void            vMBMasterCBRequestScuuess( void );
+
 /* ----------------------- Callback for the protocol stack ------------------*/
 
 /*!

+ 79 - 35
components/net/freemodbus-v1.6.0/modbus/mb_m.c

@@ -65,7 +65,7 @@
 
 static UCHAR    ucMBMasterDestAddress;
 static BOOL     xMBRunInMasterMode = FALSE;
-static BOOL     xMasterIsBusy = FALSE;
+static eMBMasterErrorEventType eMBMasterCurErrorType;
 
 static enum
 {
@@ -185,6 +185,8 @@ eMBMasterInit( eMBMode eMode, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity
 		{
 			eMBState = STATE_DISABLED;
 		}
+		/* initialize the OS resource for modbus master. */
+		vMBMasterOsResInit();
 	}
 	return eStatus;
 }
@@ -257,9 +259,10 @@ eMBMasterPoll( void )
     static USHORT   usLength;
     static eMBException eException;
 
-    int             i;
+    int             i , j;
     eMBErrorCode    eStatus = MB_ENOERR;
     eMBMasterEventType    eEvent;
+    eMBMasterErrorEventType errorType;
 
     /* Check if the protocol stack is ready. */
     if( eMBState != STATE_ENABLED )
@@ -285,6 +288,7 @@ eMBMasterPoll( void )
 			}
 			else
 			{
+				vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
 				( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
 			}
 			break;
@@ -292,52 +296,80 @@ eMBMasterPoll( void )
         case EV_MASTER_EXECUTE:
             ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF];
             eException = MB_EX_ILLEGAL_FUNCTION;
-            for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ )
-            {
-                /* No more function handlers registered. Abort. */
-                if( xMasterFuncHandlers[i].ucFunctionCode == 0 )
-                {
-                    break;
-                }
-                else if( xMasterFuncHandlers[i].ucFunctionCode == ucFunctionCode )
-                {
-                	vMBMasterSetCBRunInMasterMode(TRUE);
-                    eException = xMasterFuncHandlers[i].pxHandler( ucMBFrame, &usLength );
-                    vMBMasterSetCBRunInMasterMode(FALSE);
-                    break;
-                }
-            }
             /* If receive frame has exception .The receive function code highest bit is 1.*/
-            if(ucFunctionCode >> 7) eException = (eMBException)ucMBFrame[MB_PDU_DATA_OFF];
+            if(ucFunctionCode >> 7) {
+            	eException = (eMBException)ucMBFrame[MB_PDU_DATA_OFF];
+            }
+			else
+			{
+				for (i = 0; i < MB_FUNC_HANDLERS_MAX; i++)
+				{
+					/* No more function handlers registered. Abort. */
+					if (xMasterFuncHandlers[i].ucFunctionCode == 0)	{
+						break;
+					}
+					else if (xMasterFuncHandlers[i].ucFunctionCode == ucFunctionCode) {
+						vMBMasterSetCBRunInMasterMode(TRUE);
+						/* If master request is broadcast,
+						 * the master need execute function for all slave.
+						 */
+						if ( xMBMasterRequestIsBroadcast() ) {
+							usLength = usMBMasterGetPDUSndLength();
+							for(j = 1; j <= MB_MASTER_TOTAL_SLAVE_NUM; j++){
+								vMBMasterSetDestAddress(j);
+								eException = xMasterFuncHandlers[i].pxHandler(ucMBFrame, &usLength);
+							}
+						}
+						else {
+							eException = xMasterFuncHandlers[i].pxHandler(ucMBFrame, &usLength);
+						}
+						vMBMasterSetCBRunInMasterMode(FALSE);
+						break;
+					}
+				}
+			}
             /* If master has exception ,Master will send error process.Otherwise the Master is idle.*/
-            if (eException != MB_EX_NONE) ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
-            else vMBMasterSetIsBusy( FALSE );
+            if (eException != MB_EX_NONE) {
+            	vMBMasterSetErrorType(EV_ERROR_EXECUTE_FUNCTION);
+            	( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
+            }
+            else {
+            	vMBMasterCBRequestScuuess( );
+            	vMBMasterRunResRelease( );
+            }
             break;
 
         case EV_MASTER_FRAME_SENT:
         	/* Master is busy now. */
-        	vMBMasterSetIsBusy( TRUE );
         	vMBMasterGetPDUSndBuf( &ucMBFrame );
-			eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBFrame, ucMBMasterGetPDUSndLength() );
+			eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBFrame, usMBMasterGetPDUSndLength() );
             break;
 
         case EV_MASTER_ERROR_PROCESS:
-        	vMBMasterSetIsBusy( FALSE );
+        	/* Execute specified error process callback function. */
+			errorType = eMBMasterGetErrorType();
+			vMBMasterGetPDUSndBuf( &ucMBFrame );
+			switch (errorType) {
+			case EV_ERROR_RESPOND_TIMEOUT:
+				vMBMasterErrorCBRespondTimeout(ucMBMasterGetDestAddress(),
+						ucMBFrame, usMBMasterGetPDUSndLength());
+				break;
+			case EV_ERROR_RECEIVE_DATA:
+				vMBMasterErrorCBReceiveData(ucMBMasterGetDestAddress(),
+						ucMBFrame, usMBMasterGetPDUSndLength());
+				break;
+			case EV_ERROR_EXECUTE_FUNCTION:
+				vMBMasterErrorCBExecuteFunction(ucMBMasterGetDestAddress(),
+						ucMBFrame, usMBMasterGetPDUSndLength());
+				break;
+			}
+			vMBMasterRunResRelease();
         	break;
         }
     }
     return MB_ENOERR;
 }
-/* Get whether the Modbus Master is busy.*/
-BOOL xMBMasterGetIsBusy( void )
-{
-	return xMasterIsBusy;
-}
-/* Set whether the Modbus Master is busy.*/
-void vMBMasterSetIsBusy( BOOL IsBusy )
-{
-	xMasterIsBusy = IsBusy;
-}
+
 /* Get whether the Modbus Master is run in master mode.*/
 BOOL xMBMasterGetCBRunInMasterMode( void )
 {
@@ -348,15 +380,27 @@ void vMBMasterSetCBRunInMasterMode( BOOL IsMasterMode )
 {
 	xMBRunInMasterMode = IsMasterMode;
 }
-/* Get Modbus Master send destination address*/
+/* Get Modbus Master send destination address. */
 UCHAR ucMBMasterGetDestAddress( void )
 {
 	return ucMBMasterDestAddress;
 }
-/* Set Modbus Master send destination address*/
+/* Set Modbus Master send destination address. */
 void vMBMasterSetDestAddress( UCHAR Address )
 {
 	ucMBMasterDestAddress = Address;
 }
+/* Get Modbus Master current error event type. */
+eMBMasterErrorEventType eMBMasterGetErrorType( void )
+{
+	return eMBMasterCurErrorType;
+}
+/* Set Modbus Master current error event type. */
+void vMBMasterSetErrorType( eMBMasterErrorEventType errorType )
+{
+	eMBMasterCurErrorType = errorType;
+}
+
+
 
 #endif

+ 25 - 11
components/net/freemodbus-v1.6.0/modbus/rtu/mbrtu_m.c

@@ -74,7 +74,7 @@ static volatile eMBMasterRcvState eRcvState;
 
 static volatile UCHAR  ucMasterRTUSndBuf[MB_PDU_SIZE_MAX];
 static volatile UCHAR  ucMasterRTURcvBuf[MB_SER_PDU_SIZE_MAX];
-static volatile UCHAR  ucMasterSendPDULength;
+static volatile USHORT usMasterSendPDULength;
 
 static volatile UCHAR *pucMasterSndBufferCur;
 static volatile USHORT usMasterSndBufferCount;
@@ -235,7 +235,7 @@ xMBMasterRTUReceiveFSM( void )
     BOOL            xTaskNeedSwitch = FALSE;
     UCHAR           ucByte;
 
-    assert_param( eSndState == STATE_M_TX_IDLE );
+    assert_param(( eSndState == STATE_M_TX_IDLE ) || ( eSndState == STATE_M_TX_XFWR ));
 
     /* Always read the character. */
     ( void )xMBMasterPortSerialGetByte( ( CHAR * ) & ucByte );
@@ -364,12 +364,15 @@ xMBMasterRTUTimerExpired(void)
 
 		/* An error occured while receiving the frame. */
 	case STATE_M_RX_ERROR:
+		vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
+		xNeedPoll = xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
 		break;
 
 		/* Function called in an illegal state. */
 	default:
 		assert_param(
-				( eRcvState == STATE_M_RX_INIT ) || ( eRcvState == STATE_M_RX_RCV ) || ( eRcvState == STATE_M_RX_ERROR ));
+				( eRcvState == STATE_M_RX_INIT ) || ( eRcvState == STATE_M_RX_RCV ) ||
+				( eRcvState == STATE_M_RX_ERROR ) || ( eRcvState == STATE_M_RX_IDLE ));
 		break;
 	}
 	eRcvState = STATE_M_RX_IDLE;
@@ -380,18 +383,24 @@ xMBMasterRTUTimerExpired(void)
 		 * If the frame is broadcast,The master will idle,and if the frame is not
 		 * broadcast.Notify the listener process error.*/
 	case STATE_M_TX_XFWR:
-		if ( xFrameIsBroadcast == FALSE ) xNeedPoll = xMBMasterPortEventPost(EV_MASTER_ERROR_PROCESS);
+		if ( xFrameIsBroadcast == FALSE ) {
+			vMBMasterSetErrorType(EV_ERROR_RESPOND_TIMEOUT);
+			xNeedPoll = xMBMasterPortEventPost(EV_MASTER_ERROR_PROCESS);
+		}
 		break;
 		/* Function called in an illegal state. */
 	default:
-		assert_param( eSndState == STATE_M_TX_XFWR );
+		assert_param(
+				( eSndState == STATE_M_TX_XFWR ) || ( eSndState == STATE_M_TX_IDLE ));
 		break;
 	}
 	eSndState = STATE_M_TX_IDLE;
 
 	vMBMasterPortTimersDisable( );
-	/* If timer mode is convert delay ,then Master is idel now. */
-	if (eMasterCurTimerMode == MB_TMODE_CONVERT_DELAY) vMBMasterSetIsBusy( FALSE );
+	/* If timer mode is convert delay, the master event then turns EV_MASTER_EXECUTE status. */
+	if (eMasterCurTimerMode == MB_TMODE_CONVERT_DELAY) {
+		xNeedPoll = xMBMasterPortEventPost( EV_MASTER_EXECUTE );
+	}
 
 	return xNeedPoll;
 }
@@ -409,15 +418,15 @@ void vMBMasterGetPDUSndBuf( UCHAR ** pucFrame )
 }
 
 /* Set Modbus Master send PDU's buffer length.*/
-void vMBMasterSetPDUSndLength( UCHAR SendPDULength )
+void vMBMasterSetPDUSndLength( USHORT SendPDULength )
 {
-	ucMasterSendPDULength = SendPDULength;
+	usMasterSendPDULength = SendPDULength;
 }
 
 /* Get Modbus Master send PDU's buffer length.*/
-UCHAR ucMBMasterGetPDUSndLength( void )
+USHORT usMBMasterGetPDUSndLength( void )
 {
-	return ucMasterSendPDULength;
+	return usMasterSendPDULength;
 }
 
 /* Set Modbus Master current timer mode.*/
@@ -425,5 +434,10 @@ void vMBMasterSetCurTimerMode( eMBMasterTimerMode eMBTimerMode )
 {
 	eMasterCurTimerMode = eMBTimerMode;
 }
+
+/* The master request is broadcast? */
+BOOL xMBMasterRequestIsBroadcast( void ){
+	return xFrameIsBroadcast;
+}
 #endif
 

+ 7 - 8
components/net/freemodbus-v1.6.0/port/port.c

@@ -1,6 +1,6 @@
  /*
-  * FreeModbus Libary: LPC214X Port
-  * Copyright (C) 2007 Tiago Prado Lone <tiago@maxwellbohr.com.br>
+  * FreeModbus Libary: RT-Thread Port
+  * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
@@ -16,7 +16,7 @@
   * License along with this library; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   *
-  * File: $Id: port.c,v 1.1 2007/04/24 23:15:18 wolti Exp $
+  * File: $Id: port.c,v 1.60 2015/02/01 9:18:05 Armink $
   */
 
 /* ----------------------- System includes --------------------------------*/
@@ -24,16 +24,15 @@
 /* ----------------------- Modbus includes ----------------------------------*/
 #include "port.h"
 /* ----------------------- Variables ----------------------------------------*/
-
+static rt_base_t level;
 /* ----------------------- Start implementation -----------------------------*/
 void EnterCriticalSection(void)
 {
-	//关闭全局中断
-	__disable_irq();
+    level = rt_hw_interrupt_disable();
 }
 
 void ExitCriticalSection(void)
 {
-	//开启全局中断
-	__enable_irq();
+    rt_hw_interrupt_enable(level);
 }
+

+ 7 - 13
components/net/freemodbus-v1.6.0/port/port.h

@@ -1,6 +1,6 @@
 /*
  * FreeModbus Libary: BARE Port
- * Copyright (C) 2006 Christian Walter <wolti@sil.at>
+ * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -30,22 +30,13 @@
 #include <assert.h>
 #include <inttypes.h>
 
-#define	INLINE
+#define INLINE
 #define PR_BEGIN_EXTERN_C           extern "C" {
-#define	PR_END_EXTERN_C             }
+#define PR_END_EXTERN_C             }
 
-//TODO  暂时先写B13引脚,等组网测试时再确认
-#define SLAVE_RS485_SEND_MODE  GPIO_SetBits(GPIOB,GPIO_Pin_13)
-#define SLAVE_RS485_RECEIVE_MODE  GPIO_ResetBits(GPIOB,GPIO_Pin_13)
-#define MASTER_RS485_SEND_MODE  GPIO_SetBits(GPIOB,GPIO_Pin_13)
-#define MASTER_RS485_RECEIVE_MODE  GPIO_ResetBits(GPIOB,GPIO_Pin_13)
-
-#define ENTER_CRITICAL_SECTION()	EnterCriticalSection()
+#define ENTER_CRITICAL_SECTION()    EnterCriticalSection()
 #define EXIT_CRITICAL_SECTION()    ExitCriticalSection()
 
-void EnterCriticalSection(void);
-void ExitCriticalSection(void);
-
 typedef uint8_t BOOL;
 
 typedef unsigned char UCHAR;
@@ -65,4 +56,7 @@ typedef int32_t LONG;
 #define FALSE           0
 #endif
 
+void EnterCriticalSection(void);
+void ExitCriticalSection(void);
+
 #endif

+ 24 - 14
components/net/freemodbus-v1.6.0/port/portevent.c

@@ -1,5 +1,5 @@
 /*
- * FreeModbus Libary: STM32 Port
+ * FreeModbus Libary: RT-Thread Port
  * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
@@ -24,35 +24,45 @@
 #include "mbport.h"
 
 /* ----------------------- Variables ----------------------------------------*/
-static eMBEventType eQueuedEvent;
-static BOOL     xEventInQueue;
-
+static struct rt_event     xSlaveOsEvent;
 /* ----------------------- Start implementation -----------------------------*/
 BOOL
 xMBPortEventInit( void )
 {
-    xEventInQueue = FALSE;
+    rt_event_init(&xSlaveOsEvent,"slave event",RT_IPC_FLAG_PRIO);
     return TRUE;
 }
 
 BOOL
 xMBPortEventPost( eMBEventType eEvent )
 {
-    xEventInQueue = TRUE;
-    eQueuedEvent = eEvent;
+    rt_event_send(&xSlaveOsEvent, eEvent);
     return TRUE;
 }
 
 BOOL
 xMBPortEventGet( eMBEventType * eEvent )
 {
-    BOOL            xEventHappened = FALSE;
-
-    if( xEventInQueue )
+    rt_uint32_t recvedEvent;
+    /* waiting forever OS event */
+    rt_event_recv(&xSlaveOsEvent,
+            EV_READY | EV_FRAME_RECEIVED | EV_EXECUTE | EV_FRAME_SENT,
+            RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER,
+            &recvedEvent);
+    switch (recvedEvent)
     {
-        *eEvent = eQueuedEvent;
-        xEventInQueue = FALSE;
-        xEventHappened = TRUE;
+    case EV_READY:
+        *eEvent = EV_READY;
+        break;
+    case EV_FRAME_RECEIVED:
+        *eEvent = EV_FRAME_RECEIVED;
+        break;
+    case EV_EXECUTE:
+        *eEvent = EV_EXECUTE;
+        break;
+    case EV_FRAME_SENT:
+        *eEvent = EV_FRAME_SENT;
+        break;
     }
-    return xEventHappened;
+    return TRUE;
 }

+ 192 - 14
components/net/freemodbus-v1.6.0/port/portevent_m.c

@@ -1,5 +1,5 @@
 /*
- * FreeModbus Libary: STM32 Port
+ * FreeModbus Libary: RT-Thread Port
  * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
@@ -21,41 +21,219 @@
 
 /* ----------------------- Modbus includes ----------------------------------*/
 #include "mb.h"
+#include "mb_m.h"
 #include "mbport.h"
+#include "port.h"
 
-#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED
+#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
+/* ----------------------- Defines ------------------------------------------*/
 /* ----------------------- Variables ----------------------------------------*/
-static eMBMasterEventType eMasterQueuedEvent;
-static BOOL     xMasterEventInQueue;
-
+static struct rt_semaphore xMasterRunRes;
+static struct rt_event     xMasterOsEvent;
 /* ----------------------- Start implementation -----------------------------*/
 BOOL
 xMBMasterPortEventInit( void )
 {
-    xMasterEventInQueue = FALSE;
+    rt_event_init(&xMasterOsEvent,"master event",RT_IPC_FLAG_PRIO);
     return TRUE;
 }
 
 BOOL
 xMBMasterPortEventPost( eMBMasterEventType eEvent )
 {
-    xMasterEventInQueue = TRUE;
-    eMasterQueuedEvent = eEvent;
+    rt_event_send(&xMasterOsEvent, eEvent);
     return TRUE;
 }
 
 BOOL
 xMBMasterPortEventGet( eMBMasterEventType * eEvent )
 {
-    BOOL            xEventHappened = FALSE;
+    rt_uint32_t recvedEvent;
+    /* waiting forever OS event */
+    rt_event_recv(&xMasterOsEvent,
+            EV_MASTER_READY | EV_MASTER_FRAME_RECEIVED | EV_MASTER_EXECUTE |
+            EV_MASTER_FRAME_SENT | EV_MASTER_ERROR_PROCESS,
+            RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER,
+            &recvedEvent);
+    /* the enum type couldn't convert to int type */
+    switch (recvedEvent)
+    {
+    case EV_MASTER_READY:
+        *eEvent = EV_MASTER_READY;
+        break;
+    case EV_MASTER_FRAME_RECEIVED:
+        *eEvent = EV_MASTER_FRAME_RECEIVED;
+        break;
+    case EV_MASTER_EXECUTE:
+        *eEvent = EV_MASTER_EXECUTE;
+        break;
+    case EV_MASTER_FRAME_SENT:
+        *eEvent = EV_MASTER_FRAME_SENT;
+        break;
+    case EV_MASTER_ERROR_PROCESS:
+        *eEvent = EV_MASTER_ERROR_PROCESS;
+        break;
+    }
+    return TRUE;
+}
+/**
+ * This function is initialize the OS resource for modbus master.
+ * Note:The resource is define by OS.If you not use OS this function can be empty.
+ *
+ */
+void vMBMasterOsResInit( void )
+{
+    rt_sem_init(&xMasterRunRes, "master res", 0x01 , RT_IPC_FLAG_PRIO);
+}
+
+/**
+ * This function is take Mobus Master running resource.
+ * Note:The resource is define by Operating System.If you not use OS this function can be just return TRUE.
+ *
+ * @param lTimeOut the waiting time.
+ *
+ * @return resource taked result
+ */
+BOOL xMBMasterRunResTake( LONG lTimeOut )
+{
+    /*If waiting time is -1 .It will wait forever */
+    return rt_sem_take(&xMasterRunRes, lTimeOut) ? FALSE : TRUE ;
+}
+
+/**
+ * This function is release Mobus Master running resource.
+ * Note:The resource is define by Operating System.If you not use OS this function can be empty.
+ *
+ */
+void vMBMasterRunResRelease( void )
+{
+    /* release resource */
+    rt_sem_release(&xMasterRunRes);
+}
+
+/**
+ * This is modbus master respond timeout error process callback function.
+ * @note There functions will block modbus master poll while execute OS waiting.
+ * So,for real-time of system.Do not execute too much waiting process.
+ *
+ * @param ucDestAddress destination salve address
+ * @param pucPDUData PDU buffer data
+ * @param ucPDULength PDU buffer length
+ *
+ */
+void vMBMasterErrorCBRespondTimeout(UCHAR ucDestAddress, const UCHAR* pucPDUData,
+        USHORT ucPDULength) {
+    /**
+     * @note This code is use OS's event mechanism for modbus master protocol stack.
+     * If you don't use OS, you can change it.
+     */
+    rt_event_send(&xMasterOsEvent, EV_MASTER_ERROR_RESPOND_TIMEOUT);
+
+    /* You can add your code under here. */
 
-    if( xMasterEventInQueue )
+}
+
+/**
+ * This is modbus master receive data error process callback function.
+ * @note There functions will block modbus master poll while execute OS waiting.
+ * So,for real-time of system.Do not execute too much waiting process.
+ *
+ * @param ucDestAddress destination salve address
+ * @param pucPDUData PDU buffer data
+ * @param ucPDULength PDU buffer length
+ *
+ */
+void vMBMasterErrorCBReceiveData(UCHAR ucDestAddress, const UCHAR* pucPDUData,
+        USHORT ucPDULength) {
+    /**
+     * @note This code is use OS's event mechanism for modbus master protocol stack.
+     * If you don't use OS, you can change it.
+     */
+    rt_event_send(&xMasterOsEvent, EV_MASTER_ERROR_RECEIVE_DATA);
+
+    /* You can add your code under here. */
+
+}
+
+/**
+ * This is modbus master execute function error process callback function.
+ * @note There functions will block modbus master poll while execute OS waiting.
+ * So,for real-time of system.Do not execute too much waiting process.
+ *
+ * @param ucDestAddress destination salve address
+ * @param pucPDUData PDU buffer data
+ * @param ucPDULength PDU buffer length
+ *
+ */
+void vMBMasterErrorCBExecuteFunction(UCHAR ucDestAddress, const UCHAR* pucPDUData,
+        USHORT ucPDULength) {
+    /**
+     * @note This code is use OS's event mechanism for modbus master protocol stack.
+     * If you don't use OS, you can change it.
+     */
+    rt_event_send(&xMasterOsEvent, EV_MASTER_ERROR_EXECUTE_FUNCTION);
+
+    /* You can add your code under here. */
+
+}
+
+/**
+ * This is modbus master request process success callback function.
+ * @note There functions will block modbus master poll while execute OS waiting.
+ * So,for real-time of system.Do not execute too much waiting process.
+ *
+ */
+void vMBMasterCBRequestScuuess( void ) {
+    /**
+     * @note This code is use OS's event mechanism for modbus master protocol stack.
+     * If you don't use OS, you can change it.
+     */
+    rt_event_send(&xMasterOsEvent, EV_MASTER_PROCESS_SUCESS);
+
+    /* You can add your code under here. */
+
+}
+
+/**
+ * This function is wait for modbus master request finish and return result.
+ * Waiting result include request process success, request respond timeout,
+ * receive data error and execute function error.You can use the above callback function.
+ * @note If you are use OS, you can use OS's event mechanism. Otherwise you have to run
+ * much user custom delay for waiting.
+ *
+ * @return request error code
+ */
+eMBMasterReqErrCode eMBMasterWaitRequestFinish( void ) {
+    eMBMasterReqErrCode    eErrStatus = MB_MRE_NO_ERR;
+    rt_uint32_t recvedEvent;
+    /* waiting for OS event */
+    rt_event_recv(&xMasterOsEvent,
+            EV_MASTER_PROCESS_SUCESS | EV_MASTER_ERROR_RESPOND_TIMEOUT
+                    | EV_MASTER_ERROR_RECEIVE_DATA
+                    | EV_MASTER_ERROR_EXECUTE_FUNCTION,
+            RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER,
+            &recvedEvent);
+    switch (recvedEvent)
     {
-        *eEvent = eMasterQueuedEvent;
-        xMasterEventInQueue = FALSE;
-        xEventHappened = TRUE;
+    case EV_MASTER_PROCESS_SUCESS:
+        break;
+    case EV_MASTER_ERROR_RESPOND_TIMEOUT:
+    {
+        eErrStatus = MB_MRE_TIMEDOUT;
+        break;
+    }
+    case EV_MASTER_ERROR_RECEIVE_DATA:
+    {
+        eErrStatus = MB_MRE_REV_DATA;
+        break;
+    }
+    case EV_MASTER_ERROR_EXECUTE_FUNCTION:
+    {
+        eErrStatus = MB_MRE_EXE_FUN;
+        break;
+    }
     }
-    return xEventHappened;
+    return eErrStatus;
 }
 
 #endif

+ 155 - 122
components/net/freemodbus-v1.6.0/port/portserial.c

@@ -1,5 +1,5 @@
 /*
- * FreeModbus Libary: STM32 Port
+ * FreeModbus Libary: RT-Thread Port
  * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
@@ -24,122 +24,148 @@
 /* ----------------------- Modbus includes ----------------------------------*/
 #include "mb.h"
 #include "mbport.h"
+#include "rtdevice.h"
+#include "board.h"
+
+/* ----------------------- Static variables ---------------------------------*/
+ALIGN(RT_ALIGN_SIZE)
+/* software simulation serial transmit IRQ handler thread stack */
+static rt_uint8_t serial_soft_trans_irq_stack[512];
+/* software simulation serial transmit IRQ handler thread */
+static struct rt_thread thread_serial_soft_trans_irq;
+/* serial event */
+static struct rt_event event_serial;
+/* modbus slave serial device */
+static rt_serial_t *serial;
+
+/* ----------------------- Defines ------------------------------------------*/
+/* serial transmit event */
+#define EVENT_SERIAL_TRANS_START    (1<<0)
+
 /* ----------------------- static functions ---------------------------------*/
 static void prvvUARTTxReadyISR(void);
 static void prvvUARTRxISR(void);
+static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size);
+static void serial_soft_trans_irq(void* parameter);
+
 /* ----------------------- Start implementation -----------------------------*/
+BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
+        eMBParity eParity)
+{
+    /**
+     * set 485 mode receive and transmit control IO
+     * @note MODBUS_SLAVE_RT_CONTROL_PIN_INDEX need be defined by user
+     */
+    rt_pin_mode(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_MODE_OUTPUT);
+
+    /* set serial name */
+    if (ucPORT == 1) {
+#if defined(RT_USING_UART1) || defined(RT_USING_REMAP_UART1)
+        extern struct rt_serial_device serial1;
+        serial = &serial1;
+#endif
+    } else if (ucPORT == 2) {
+#if defined(RT_USING_UART2)
+        extern struct rt_serial_device serial2;
+        serial = &serial2;
+#endif
+    } else if (ucPORT == 3) {
+#if defined(RT_USING_UART3)
+        extern struct rt_serial_device serial3;
+        serial = &serial3;
+#endif
+    }
+    /* set serial configure parameter */
+    serial->config.baud_rate = ulBaudRate;
+    serial->config.stop_bits = STOP_BITS_1;
+    switch(eParity){
+    case MB_PAR_NONE: {
+        serial->config.data_bits = DATA_BITS_8;
+        serial->config.parity = PARITY_NONE;
+        break;
+    }
+    case MB_PAR_ODD: {
+        serial->config.data_bits = DATA_BITS_9;
+        serial->config.parity = PARITY_ODD;
+        break;
+    }
+    case MB_PAR_EVEN: {
+        serial->config.data_bits = DATA_BITS_9;
+        serial->config.parity = PARITY_EVEN;
+        break;
+    }
+    }
+    /* set serial configure */
+    serial->ops->configure(serial, &(serial->config));
+
+    /* open serial device */
+    if (!serial->parent.open(&serial->parent,
+            RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX )) {
+        serial->parent.rx_indicate = serial_rx_ind;
+    } else {
+        return FALSE;
+    }
+
+    /* software initialize */
+    rt_thread_init(&thread_serial_soft_trans_irq,
+                   "slave trans",
+                   serial_soft_trans_irq,
+                   RT_NULL,
+                   serial_soft_trans_irq_stack,
+                   sizeof(serial_soft_trans_irq_stack),
+                   10, 5);
+    rt_thread_startup(&thread_serial_soft_trans_irq);
+    rt_event_init(&event_serial, "slave event", RT_IPC_FLAG_PRIO);
+
+    return TRUE;
+}
 
 void vMBPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable)
 {
-	if (xRxEnable)
-	{
-		SLAVE_RS485_RECEIVE_MODE;
-		USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
-	}
-	else
-	{
-		SLAVE_RS485_SEND_MODE;
-		USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
-	}
-	if (xTxEnable)
-	{
-		USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
-	}
-	else
-	{
-		USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
-	}
+    rt_uint32_t recved_event;
+    if (xRxEnable)
+    {
+        /* enable RX interrupt */
+        serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX);
+        /* switch 485 to receive mode */
+        rt_pin_write(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_LOW);
+    }
+    else
+    {
+        /* switch 485 to transmit mode */
+        rt_pin_write(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_HIGH);
+        /* disable RX interrupt */
+        serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX);
+    }
+    if (xTxEnable)
+    {
+        /* start serial transmit */
+        rt_event_send(&event_serial, EVENT_SERIAL_TRANS_START);
+    }
+    else
+    {
+        /* stop serial transmit */
+        rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START,
+                RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 0,
+                &recved_event);
+    }
 }
 
 void vMBPortClose(void)
 {
-	USART_ITConfig(USART1, USART_IT_TXE | USART_IT_RXNE, DISABLE);
-	USART_Cmd(USART1, DISABLE);
-}
-//默认一个从机 串口1 波特率可设置  奇偶检验可设置
-BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
-		eMBParity eParity)
-{
-	GPIO_InitTypeDef GPIO_InitStructure;
-	USART_InitTypeDef USART_InitStructure;
-	NVIC_InitTypeDef NVIC_InitStructure;
-	//======================时钟初始化=======================================
-	RCC_APB2PeriphClockCmd(
-			RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_USART1,
-			ENABLE);
-	//======================IO初始化=======================================	
-	//USART1_TX
-	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
-	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
-	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
-	GPIO_Init(GPIOA, &GPIO_InitStructure);
-	//USART1_RX
-	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
-	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
-	GPIO_Init(GPIOA, &GPIO_InitStructure);
-	//配置485发送和接收模式
-//    TODO   暂时先写B13 等之后组网测试时再修改
-	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
-	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
-	GPIO_Init(GPIOB, &GPIO_InitStructure);
-	//======================串口初始化=======================================
-	USART_InitStructure.USART_BaudRate = ulBaudRate;
-	//设置校验模式
-	switch (eParity)
-	{
-	case MB_PAR_NONE: //无校验
-		USART_InitStructure.USART_Parity = USART_Parity_No;
-		USART_InitStructure.USART_WordLength = USART_WordLength_8b;
-		break;
-	case MB_PAR_ODD: //奇校验
-		USART_InitStructure.USART_Parity = USART_Parity_Odd;
-		USART_InitStructure.USART_WordLength = USART_WordLength_9b;
-		break;
-	case MB_PAR_EVEN: //偶校验
-		USART_InitStructure.USART_Parity = USART_Parity_Even;
-		USART_InitStructure.USART_WordLength = USART_WordLength_9b;
-		break;
-	default:
-		return FALSE;
-	}
-
-	USART_InitStructure.USART_StopBits = USART_StopBits_1;
-	USART_InitStructure.USART_HardwareFlowControl =
-			USART_HardwareFlowControl_None;
-	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
-	if (ucPORT != 1)
-		return FALSE;
-
-	ENTER_CRITICAL_SECTION(); //关全局中断
-
-	USART_Init(USART1, &USART_InitStructure);
-	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
-	USART_Cmd(USART1, ENABLE);
-
-	//=====================中断初始化======================================
-	//设置NVIC优先级分组为Group2:0-3抢占式优先级,0-3的响应式优先级
-	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
-	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
-	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
-	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
-	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
-	NVIC_Init(&NVIC_InitStructure);
-
-	EXIT_CRITICAL_SECTION(); //开全局中断
-
-	return TRUE;
+    serial->parent.close(&(serial->parent));
 }
 
 BOOL xMBPortSerialPutByte(CHAR ucByte)
 {
-	USART_SendData(USART1, ucByte);
-	return TRUE;
+    serial->parent.write(&(serial->parent), 0, &ucByte, 1);
+    return TRUE;
 }
 
 BOOL xMBPortSerialGetByte(CHAR * pucByte)
 {
-	*pucByte = USART_ReceiveData(USART1);
-	return TRUE;
+    serial->parent.read(&(serial->parent), 0, pucByte, 1);
+    return TRUE;
 }
 
 /* 
@@ -151,7 +177,7 @@ BOOL xMBPortSerialGetByte(CHAR * pucByte)
  */
 void prvvUARTTxReadyISR(void)
 {
-	pxMBFrameCBTransmitterEmpty();
+    pxMBFrameCBTransmitterEmpty();
 }
 
 /* 
@@ -162,28 +188,35 @@ void prvvUARTTxReadyISR(void)
  */
 void prvvUARTRxISR(void)
 {
-	pxMBFrameCBByteReceived();
+    pxMBFrameCBByteReceived();
 }
-/*******************************************************************************
- * Function Name  : USART1_IRQHandler
- * Description    : This function handles USART1 global interrupt request.
- * Input          : None
- * Output         : None
- * Return         : None
- *******************************************************************************/
-void USART1_IRQHandler(void)
-{
-	rt_interrupt_enter();
-	//接收中断
-	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
-	{
-		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
-		prvvUARTRxISR();
-	}
-	//发送中断
-	if (USART_GetITStatus(USART1, USART_IT_TXE) == SET)
-	{
-		prvvUARTTxReadyISR();
-	}
-	rt_interrupt_leave();
+
+/**
+ * Software simulation serial transmit IRQ handler.
+ *
+ * @param parameter parameter
+ */
+static void serial_soft_trans_irq(void* parameter) {
+    rt_uint32_t recved_event;
+    while (1)
+    {
+        /* waiting for serial transmit start */
+        rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, RT_EVENT_FLAG_OR,
+                RT_WAITING_FOREVER, &recved_event);
+        /* execute modbus callback */
+        prvvUARTTxReadyISR();
+    }
+}
+
+/**
+ * This function is serial receive callback function
+ *
+ * @param dev the device of serial
+ * @param size the data size that receive
+ *
+ * @return return RT_EOK
+ */
+static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size) {
+    prvvUARTRxISR();
+    return RT_EOK;
 }

+ 155 - 122
components/net/freemodbus-v1.6.0/port/portserial_m.c

@@ -1,5 +1,5 @@
 /*
- * FreeModbus Libary: STM32 Port
+ * FreeModbus Libary: RT-Thread Port
  * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
@@ -24,123 +24,149 @@
 /* ----------------------- Modbus includes ----------------------------------*/
 #include "mb.h"
 #include "mbport.h"
+#include "rtdevice.h"
+#include "board.h"
+
+#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
+/* ----------------------- Static variables ---------------------------------*/
+ALIGN(RT_ALIGN_SIZE)
+/* software simulation serial transmit IRQ handler thread stack */
+static rt_uint8_t serial_soft_trans_irq_stack[512];
+/* software simulation serial transmit IRQ handler thread */
+static struct rt_thread thread_serial_soft_trans_irq;
+/* serial event */
+static struct rt_event event_serial;
+/* modbus slave serial device */
+static rt_serial_t *serial;
+
+/* ----------------------- Defines ------------------------------------------*/
+/* serial transmit event */
+#define EVENT_SERIAL_TRANS_START    (1<<0)
 
-#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED
 /* ----------------------- static functions ---------------------------------*/
 static void prvvUARTTxReadyISR(void);
 static void prvvUARTRxISR(void);
+static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size);
+static void serial_soft_trans_irq(void* parameter);
+
 /* ----------------------- Start implementation -----------------------------*/
+BOOL xMBMasterPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
+        eMBParity eParity)
+{
+    /**
+     * set 485 mode receive and transmit control IO
+     * @note MODBUS_MASTER_RT_CONTROL_PIN_INDEX need be defined by user
+     */
+    rt_pin_mode(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_MODE_OUTPUT);
+
+    /* set serial name */
+    if (ucPORT == 1) {
+#if defined(RT_USING_UART1) || defined(RT_USING_REMAP_UART1)
+        extern struct rt_serial_device serial1;
+        serial = &serial1;
+#endif
+    } else if (ucPORT == 2) {
+#if defined(RT_USING_UART2)
+        extern struct rt_serial_device serial2;
+        serial = &serial2;
+#endif
+    } else if (ucPORT == 3) {
+#if defined(RT_USING_UART3)
+        extern struct rt_serial_device serial3;
+        serial = &serial3;
+#endif
+    }
+    /* set serial configure parameter */
+    serial->config.baud_rate = ulBaudRate;
+    serial->config.stop_bits = STOP_BITS_1;
+    switch(eParity){
+    case MB_PAR_NONE: {
+        serial->config.data_bits = DATA_BITS_8;
+        serial->config.parity = PARITY_NONE;
+        break;
+    }
+    case MB_PAR_ODD: {
+        serial->config.data_bits = DATA_BITS_9;
+        serial->config.parity = PARITY_ODD;
+        break;
+    }
+    case MB_PAR_EVEN: {
+        serial->config.data_bits = DATA_BITS_9;
+        serial->config.parity = PARITY_EVEN;
+        break;
+    }
+    }
+    /* set serial configure */
+    serial->ops->configure(serial, &(serial->config));
+
+    /* open serial device */
+    if (!serial->parent.open(&serial->parent,
+            RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX )) {
+        serial->parent.rx_indicate = serial_rx_ind;
+    } else {
+        return FALSE;
+    }
+
+    /* software initialize */
+    rt_thread_init(&thread_serial_soft_trans_irq,
+                   "slave trans",
+                   serial_soft_trans_irq,
+                   RT_NULL,
+                   serial_soft_trans_irq_stack,
+                   sizeof(serial_soft_trans_irq_stack),
+                   10, 5);
+    rt_thread_startup(&thread_serial_soft_trans_irq);
+    rt_event_init(&event_serial, "slave event", RT_IPC_FLAG_PRIO);
+
+    return TRUE;
+}
 
 void vMBMasterPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable)
 {
-	if (xRxEnable)
-	{
-		MASTER_RS485_RECEIVE_MODE;
-		USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
-	}
-	else
-	{
-		MASTER_RS485_SEND_MODE;
-		USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
-	}
-	if (xTxEnable)
-	{
-		USART_ITConfig(USART2, USART_IT_TXE, ENABLE);
-	}
-	else
-	{
-		USART_ITConfig(USART2, USART_IT_TXE, DISABLE);
-	}
+    rt_uint32_t recved_event;
+    if (xRxEnable)
+    {
+        /* enable RX interrupt */
+        serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX);
+        /* switch 485 to receive mode */
+        rt_pin_write(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_LOW);
+    }
+    else
+    {
+        /* switch 485 to transmit mode */
+        rt_pin_write(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_HIGH);
+        /* disable RX interrupt */
+        serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX);
+    }
+    if (xTxEnable)
+    {
+        /* start serial transmit */
+        rt_event_send(&event_serial, EVENT_SERIAL_TRANS_START);
+    }
+    else
+    {
+        /* stop serial transmit */
+        rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START,
+                RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 0,
+                &recved_event);
+    }
 }
 
 void vMBMasterPortClose(void)
 {
-	USART_ITConfig(USART2, USART_IT_TXE | USART_IT_RXNE, DISABLE);
-	USART_Cmd(USART2, DISABLE);
-}
-//默认一个主机 串口2 波特率可设置  奇偶检验可设置
-BOOL xMBMasterPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
-		eMBParity eParity)
-{
-	GPIO_InitTypeDef GPIO_InitStructure;
-	USART_InitTypeDef USART_InitStructure;
-	NVIC_InitTypeDef NVIC_InitStructure;
-	//======================时钟初始化=======================================
-	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
-	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
-	//======================IO初始化=======================================	
-	//USART2_TX
-	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
-	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
-	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
-	GPIO_Init(GPIOA, &GPIO_InitStructure);
-	//USART2_RX
-	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
-	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
-	GPIO_Init(GPIOA, &GPIO_InitStructure);
-	//配置485发送和接收模式
-//    TODO   暂时先写B13 等之后组网测试时再修改
-	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
-	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
-	GPIO_Init(GPIOB, &GPIO_InitStructure);
-	//======================串口初始化=======================================
-	USART_InitStructure.USART_BaudRate = ulBaudRate;
-	//设置校验模式
-	switch (eParity)
-	{
-	case MB_PAR_NONE: //无校验
-		USART_InitStructure.USART_Parity = USART_Parity_No;
-		USART_InitStructure.USART_WordLength = USART_WordLength_8b;
-		break;
-	case MB_PAR_ODD: //奇校验
-		USART_InitStructure.USART_Parity = USART_Parity_Odd;
-		USART_InitStructure.USART_WordLength = USART_WordLength_9b;
-		break;
-	case MB_PAR_EVEN: //偶校验
-		USART_InitStructure.USART_Parity = USART_Parity_Even;
-		USART_InitStructure.USART_WordLength = USART_WordLength_9b;
-		break;
-	default:
-		return FALSE;
-	}
-
-	USART_InitStructure.USART_StopBits = USART_StopBits_1;
-	USART_InitStructure.USART_HardwareFlowControl =
-			USART_HardwareFlowControl_None;
-	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
-	if (ucPORT != 2)
-		return FALSE;
-
-	ENTER_CRITICAL_SECTION(); //关全局中断
-
-	USART_Init(USART2, &USART_InitStructure);
-	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
-	USART_Cmd(USART2, ENABLE);
-
-	//=====================中断初始化======================================
-	//设置NVIC优先级分组为Group2:0-3抢占式优先级,0-3的响应式优先级
-	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
-	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
-	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
-	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
-	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
-	NVIC_Init(&NVIC_InitStructure);
-
-	EXIT_CRITICAL_SECTION(); //开全局中断
-
-	return TRUE;
+    serial->parent.close(&(serial->parent));
 }
 
 BOOL xMBMasterPortSerialPutByte(CHAR ucByte)
 {
-	USART_SendData(USART2, ucByte);
-	return TRUE;
+    serial->parent.write(&(serial->parent), 0, &ucByte, 1);
+    return TRUE;
 }
 
 BOOL xMBMasterPortSerialGetByte(CHAR * pucByte)
 {
-	*pucByte = USART_ReceiveData(USART2);
-	return TRUE;
+    serial->parent.read(&(serial->parent), 0, pucByte, 1);
+    return TRUE;
 }
 
 /* 
@@ -152,7 +178,7 @@ BOOL xMBMasterPortSerialGetByte(CHAR * pucByte)
  */
 void prvvUARTTxReadyISR(void)
 {
-	pxMBMasterFrameCBTransmitterEmpty();
+    pxMBMasterFrameCBTransmitterEmpty();
 }
 
 /* 
@@ -163,30 +189,37 @@ void prvvUARTTxReadyISR(void)
  */
 void prvvUARTRxISR(void)
 {
-	pxMBMasterFrameCBByteReceived();
+    pxMBMasterFrameCBByteReceived();
 }
-/*******************************************************************************
- * Function Name  : USART2_IRQHandler
- * Description    : This function handles USART2 global interrupt request.
- * Input          : None
- * Output         : None
- * Return         : None
- *******************************************************************************/
-void USART2_IRQHandler(void)
-{
-	rt_interrupt_enter();
-	//接收中断
-	if (USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
-	{
-		USART_ClearITPendingBit(USART2, USART_IT_RXNE);
-		prvvUARTRxISR();
-	}
-	//发送中断
-	if (USART_GetITStatus(USART2, USART_IT_TXE) == SET)
-	{
-		prvvUARTTxReadyISR();
-	}
-	rt_interrupt_leave();
+
+/**
+ * Software simulation serial transmit IRQ handler.
+ *
+ * @param parameter parameter
+ */
+static void serial_soft_trans_irq(void* parameter) {
+    rt_uint32_t recved_event;
+    while (1)
+    {
+        /* waiting for serial transmit start */
+        rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, RT_EVENT_FLAG_OR,
+                RT_WAITING_FOREVER, &recved_event);
+        /* execute modbus callback */
+        prvvUARTTxReadyISR();
+    }
+}
+
+/**
+ * This function is serial receive callback function
+ *
+ * @param dev the device of serial
+ * @param size the data size that receive
+ *
+ * @return return RT_EOK
+ */
+static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size) {
+    prvvUARTRxISR();
+    return RT_EOK;
 }
 
 #endif

+ 14 - 58
components/net/freemodbus-v1.6.0/port/porttimer.c

@@ -1,5 +1,5 @@
 /*
- * FreeModbus Libary: STM32 Port
+ * FreeModbus Libary: RT-Thread Port
  * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
@@ -27,81 +27,37 @@
 #include "mbport.h"
 
 /* ----------------------- static functions ---------------------------------*/
+static struct rt_timer timer;
 static void prvvTIMERExpiredISR(void);
+static void timer_timeout_ind(void* parameter);
 
 /* ----------------------- Start implementation -----------------------------*/
 BOOL xMBPortTimersInit(USHORT usTim1Timerout50us)
 {
-
-	uint16_t PrescalerValue = 0;
-	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
-	NVIC_InitTypeDef NVIC_InitStructure;
-	//====================================时钟初始化===========================
-	//使能定时器3时钟
-	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
-	//====================================定时器初始化===========================
-	//定时器时间基配置说明
-	//HCLK为72MHz,APB1经过2分频为36MHz
-	//TIM3的时钟倍频后为72MHz(硬件自动倍频,达到最大)
-	//TIM3的分频系数为3599,时间基频率为72 / (1 + Prescaler) = 20KHz,基准为50us
-	//TIM最大计数值为usTim1Timerout50u
-	
-	PrescalerValue = (uint16_t) (SystemCoreClock / 20000) - 1;
-	//定时器1初始化
-	TIM_TimeBaseStructure.TIM_Period = (uint16_t) usTim1Timerout50us;
-	TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
-	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
-	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
-	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
-	//预装载使能
-	TIM_ARRPreloadConfig(TIM3, ENABLE);
-	//====================================中断初始化===========================
-	//设置NVIC优先级分组为Group2:0-3抢占式优先级,0-3的响应式优先级
-	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
-	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
-	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
-	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
-	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
-	NVIC_Init(&NVIC_InitStructure);
-	//清除溢出中断标志位
-	TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
-	//定时器3溢出中断关闭
-	TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);
-	//定时器3禁能
-	TIM_Cmd(TIM3, DISABLE);
-	return TRUE;
+    rt_timer_init(&timer, "slave timer",
+                   timer_timeout_ind, /* bind timeout callback function */
+                   RT_NULL,
+                   (50*usTim1Timerout50us)/(1000*1000/RT_TICK_PER_SECOND),
+                   RT_TIMER_FLAG_ONE_SHOT); /* one shot */
+    return TRUE;
 }
 
 void vMBPortTimersEnable()
 {
-	TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
-	TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
-	TIM_SetCounter(TIM3, 0);
-	TIM_Cmd(TIM3, ENABLE);
+    rt_timer_start(&timer);
 }
 
 void vMBPortTimersDisable()
 {
-	TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
-	TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);
-	TIM_SetCounter(TIM3, 0);
-	TIM_Cmd(TIM3, DISABLE);
+    rt_timer_stop(&timer);
 }
 
 void prvvTIMERExpiredISR(void)
 {
-	(void) pxMBPortCBTimerExpired();
+    (void) pxMBPortCBTimerExpired();
 }
 
-void TIM3_IRQHandler(void)
+static void timer_timeout_ind(void* parameter)
 {
-	rt_interrupt_enter();
-	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
-	{
-		
-		TIM_ClearFlag(TIM3, TIM_FLAG_Update);	     //清中断标记
-		TIM_ClearITPendingBit(TIM3, TIM_IT_Update);	 //清除定时器T3溢出中断标志位
-		prvvTIMERExpiredISR();
-	}
-	rt_interrupt_leave();
+    prvvTIMERExpiredISR();
 }

+ 35 - 85
components/net/freemodbus-v1.6.0/port/porttimer_m.c

@@ -1,5 +1,5 @@
 /*
- * FreeModbus Libary: STM32 Port
+ * FreeModbus Libary: RT-Thread Port
  * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
@@ -27,10 +27,12 @@
 #include "mb_m.h"
 #include "mbport.h"
 
-#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED
+#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
 /* ----------------------- Variables ----------------------------------------*/
 static USHORT usT35TimeOut50us;
-static USHORT usPrescalerValue = 0;
+static struct rt_timer timer;
+static void prvvTIMERExpiredISR(void);
+static void timer_timeout_ind(void* parameter);
 
 /* ----------------------- static functions ---------------------------------*/
 static void prvvTIMERExpiredISR(void);
@@ -38,120 +40,68 @@ static void prvvTIMERExpiredISR(void);
 /* ----------------------- Start implementation -----------------------------*/
 BOOL xMBMasterPortTimersInit(USHORT usTimeOut50us)
 {
-	NVIC_InitTypeDef NVIC_InitStructure;
-	//====================================时钟初始化===========================
-	//使能定时器2时钟
-	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
-	//====================================定时器初始化===========================
-	//定时器时间基配置说明
-	//HCLK为72MHz,APB1经过2分频为36MHz
-	//TIM2的时钟倍频后为72MHz(硬件自动倍频,达到最大)
-	//TIM2的分频系数为3599,时间基频率为72 / (1 + Prescaler) = 20KHz,基准为50us
-	//TIM最大计数值为usTim1Timerout50u	
-	usPrescalerValue = (uint16_t) (SystemCoreClock / 20000) - 1;
-	//保存T35定时器计数值
-	usT35TimeOut50us = usTimeOut50us; 
-
-	//预装载使能
-	TIM_ARRPreloadConfig(TIM2, ENABLE);
-	//====================================中断初始化===========================
-	//设置NVIC优先级分组为Group2:0-3抢占式优先级,0-3的响应式优先级
-	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
-	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
-	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
-	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
-	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
-	NVIC_Init(&NVIC_InitStructure);
-	//清除溢出中断标志位
-	TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
-	//定时器3溢出中断关闭
-	TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
-	//定时器3禁能
-	TIM_Cmd(TIM2, DISABLE);
-	return TRUE;
+    /* backup T35 ticks */
+    usT35TimeOut50us = usTimeOut50us;
+
+    rt_timer_init(&timer, "master timer",
+                   timer_timeout_ind, /* bind timeout callback function */
+                   RT_NULL,
+                   (50 * usT35TimeOut50us) / (1000 * 1000 / RT_TICK_PER_SECOND),
+                   RT_TIMER_FLAG_ONE_SHOT); /* one shot */
+
+    return TRUE;
 }
 
 void vMBMasterPortTimersT35Enable()
 {
-	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
+    rt_tick_t timer_tick = (50 * usT35TimeOut50us)
+            / (1000 * 1000 / RT_TICK_PER_SECOND);
 
-	/* Set current timer mode,don't change it.*/
-	vMBMasterSetCurTimerMode(MB_TMODE_T35);
+    /* Set current timer mode, don't change it.*/
+    vMBMasterSetCurTimerMode(MB_TMODE_T35);
 
-	TIM_TimeBaseStructure.TIM_Prescaler = usPrescalerValue;
-	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
-	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
-	TIM_TimeBaseStructure.TIM_Period = (uint16_t) usT35TimeOut50us;
-	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
+    rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick);
 
-	TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
-	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
-	TIM_SetCounter(TIM2, 0);
-	TIM_Cmd(TIM2, ENABLE);
+    rt_timer_start(&timer);
 }
 
 void vMBMasterPortTimersConvertDelayEnable()
 {
-	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
+    rt_tick_t timer_tick = MB_MASTER_DELAY_MS_CONVERT * RT_TICK_PER_SECOND / 1000;
 
-	/* Set current timer mode,don't change it.*/
-	vMBMasterSetCurTimerMode(MB_TMODE_CONVERT_DELAY);
+    /* Set current timer mode, don't change it.*/
+    vMBMasterSetCurTimerMode(MB_TMODE_CONVERT_DELAY);
 
-	TIM_TimeBaseStructure.TIM_Prescaler = usPrescalerValue;
-	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
-	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
-	TIM_TimeBaseStructure.TIM_Period = (uint16_t)(MB_MASTER_DELAY_MS_CONVERT * 1000 / 50);
-	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
+    rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick);
 
-	TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
-	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
-	TIM_SetCounter(TIM2, 0);
-	TIM_Cmd(TIM2, ENABLE);
+    rt_timer_start(&timer);
 }
 
 void vMBMasterPortTimersRespondTimeoutEnable()
 {
-	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
+    rt_tick_t timer_tick = MB_MASTER_TIMEOUT_MS_RESPOND * RT_TICK_PER_SECOND / 1000;
 
-	/* Set current timer mode,don't change it.*/
-	vMBMasterSetCurTimerMode(MB_TMODE_RESPOND_TIMEOUT);
+    /* Set current timer mode, don't change it.*/
+    vMBMasterSetCurTimerMode(MB_TMODE_RESPOND_TIMEOUT);
 
-	TIM_TimeBaseStructure.TIM_Prescaler = usPrescalerValue;
-	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
-	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
-	TIM_TimeBaseStructure.TIM_Period = (uint16_t)(MB_MASTER_TIMEOUT_MS_RESPOND * 1000 / 50);
-	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
+    rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick);
 
-	TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
-	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
-	TIM_SetCounter(TIM2, 0);
-	TIM_Cmd(TIM2, ENABLE);
+    rt_timer_start(&timer);
 }
 
 void vMBMasterPortTimersDisable()
 {
-	TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
-	TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
-	TIM_SetCounter(TIM2, 0);
-	TIM_Cmd(TIM2, DISABLE);
+    rt_timer_stop(&timer);
 }
 
 void prvvTIMERExpiredISR(void)
 {
-	(void) pxMBMasterPortCBTimerExpired();
+    (void) pxMBMasterPortCBTimerExpired();
 }
 
-void TIM2_IRQHandler(void)
+static void timer_timeout_ind(void* parameter)
 {
-	rt_interrupt_enter();
-	if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
-	{
-		
-		TIM_ClearFlag(TIM2, TIM_FLAG_Update);	     //清中断标记
-		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);	 //清除定时器TIM2溢出中断标志位
-		prvvTIMERExpiredISR();
-	}
-	rt_interrupt_leave();
+    prvvTIMERExpiredISR();
 }
 
 #endif

+ 175 - 238
components/net/freemodbus-v1.6.0/port/user_mb_app.c

@@ -1,4 +1,25 @@
+/*
+ * FreeModbus Libary: user callback functions and buffer define in slave mode
+ * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * File: $Id: user_mb_app.c,v 1.60 2013/11/23 11:49:05 Armink $
+ */
 #include "user_mb_app.h"
+
 /*------------------------Slave mode use these variables----------------------*/
 //Slave mode:DiscreteInputs variables
 USHORT   usSDiscInStart                               = S_DISCRETE_INPUT_START;
@@ -20,81 +41,41 @@ USHORT   usSRegInBuf[S_REG_INPUT_NREGS]               ;
 //Slave mode:HoldingRegister variables
 USHORT   usSRegHoldStart                              = S_REG_HOLDING_START;
 USHORT   usSRegHoldBuf[S_REG_HOLDING_NREGS]           ;
-/*-----------------------Master mode use these variables----------------------*/
-#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
-//Master mode:DiscreteInputs variables
-USHORT   usMDiscInStart                             = M_DISCRETE_INPUT_START;
-#if      M_DISCRETE_INPUT_NDISCRETES%8
-UCHAR    ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8+1];
-#else
-UCHAR    ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8];
-#endif
-//Master mode:Coils variables
-USHORT   usMCoilStart                               = M_COIL_START;
-#if      M_COIL_NCOILS%8
-UCHAR    ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8+1];
-#else
-UCHAR    ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8];
-#endif
-//Master mode:InputRegister variables
-USHORT   usMRegInStart                              = M_REG_INPUT_START;
-USHORT   usMRegInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_INPUT_NREGS];
-//Master mode:HoldingRegister variables
-USHORT   usMRegHoldStart                            = M_REG_HOLDING_START;
-USHORT   usMRegHoldBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_HOLDING_NREGS];
-#endif
-//******************************输入寄存器回调函数**********************************
-//函数定义: eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
-//描    述:输入寄存器相关的功能(读、连续读)
-//入口参数:pucRegBuffer : 回调函数将Modbus寄存器的当前值写入的缓冲区
-//			usAddress    : 寄存器的起始地址,输入寄存器的地址范围是1-65535。
-//			usNRegs      : 寄存器数量
-//出口参数:eMBErrorCode : 这个函数将返回的错误码
-//备    注:Editor:Armink 2010-10-31    Company: BXXJS
-//**********************************************************************************
-eMBErrorCode
-eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
+
+/**
+ * Modbus slave input register callback function.
+ *
+ * @param pucRegBuffer input register buffer
+ * @param usAddress input register address
+ * @param usNRegs input register number
+ *
+ * @return result
+ */
+eMBErrorCode eMBRegInputCB(UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
 {
     eMBErrorCode    eStatus = MB_ENOERR;
-    int             iRegIndex;
+    USHORT          iRegIndex;
     USHORT *        pusRegInputBuf;
-    UCHAR           REG_INPUT_START;
-    UCHAR           REG_INPUT_NREGS;
-    UCHAR           usRegInStart;
+    USHORT          REG_INPUT_START;
+    USHORT          REG_INPUT_NREGS;
+    USHORT          usRegInStart;
 
-    //Determine the master or slave
-    if (xMBMasterGetCBRunInMasterMode())
-    {
-    	pusRegInputBuf = usMRegInBuf[ucMBMasterGetDestAddress()];
-    	REG_INPUT_START = M_REG_INPUT_START;
-    	REG_INPUT_NREGS = M_REG_INPUT_NREGS;
-    	usRegInStart = usMRegInStart;
-    }
-    else
-    {
-    	pusRegInputBuf = usSRegInBuf;
-    	REG_INPUT_START = S_REG_INPUT_START;
-    	REG_INPUT_NREGS = S_REG_INPUT_NREGS;
-    	usRegInStart = usSRegInStart;
-    }
+    pusRegInputBuf = usSRegInBuf;
+    REG_INPUT_START = S_REG_INPUT_START;
+    REG_INPUT_NREGS = S_REG_INPUT_NREGS;
+    usRegInStart = usSRegInStart;
 
-    if( ( usAddress >= REG_INPUT_START )
-        && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
+    /* it already plus one in modbus function method. */
+    usAddress--;
+
+    if ((usAddress >= REG_INPUT_START)
+            && (usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS))
     {
-        iRegIndex = ( int )( usAddress - usRegInStart );
-        while( usNRegs > 0 )
+        iRegIndex = usAddress - usRegInStart;
+        while (usNRegs > 0)
         {
-            //Determine the master or slave
-            if (xMBMasterGetCBRunInMasterMode())
-            {
-            	pusRegInputBuf[iRegIndex] = *pucRegBuffer++ << 8;
-                pusRegInputBuf[iRegIndex] |= *pucRegBuffer++;
-            }
-            else
-            {
-				*pucRegBuffer++ = ( unsigned char )( pusRegInputBuf[iRegIndex] >> 8 );
-				*pucRegBuffer++ = ( unsigned char )( pusRegInputBuf[iRegIndex] & 0xFF );
-            }
+            *pucRegBuffer++ = (UCHAR) (pusRegInputBuf[iRegIndex] >> 8);
+            *pucRegBuffer++ = (UCHAR) (pusRegInputBuf[iRegIndex] & 0xFF);
             iRegIndex++;
             usNRegs--;
         }
@@ -106,67 +87,55 @@ eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
 
     return eStatus;
 }
-//******************************保持寄存器回调函数**********************************
-//函数定义: eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
-//描    述:保持寄存器相关的功能(读、连续读、写、连续写)
-//入口参数:pucRegBuffer : 如果需要更新用户寄存器数值,这个缓冲区必须指向新的寄存器数值。
-//                         如果协议栈想知道当前的数值,回调函数必须将当前值写入这个缓冲区
-//			usAddress    : 寄存器的起始地址。
-//			usNRegs      : 寄存器数量
-//          eMode        : 如果该参数为eMBRegisterMode::MB_REG_WRITE,用户的应用数值将从pucRegBuffer中得到更新。
-//                         如果该参数为eMBRegisterMode::MB_REG_READ,用户需要将当前的应用数据存储在pucRegBuffer中
-//出口参数:eMBErrorCode : 这个函数将返回的错误码
-//备    注:Editor:Armink 2010-10-31    Company: BXXJS
-//**********************************************************************************
-eMBErrorCode
-eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
+
+/**
+ * Modbus slave holding register callback function.
+ *
+ * @param pucRegBuffer holding register buffer
+ * @param usAddress holding register address
+ * @param usNRegs holding register number
+ * @param eMode read or write
+ *
+ * @return result
+ */
+eMBErrorCode eMBRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress,
+        USHORT usNRegs, eMBRegisterMode eMode)
 {
     eMBErrorCode    eStatus = MB_ENOERR;
-    int             iRegIndex;
+    USHORT          iRegIndex;
     USHORT *        pusRegHoldingBuf;
-    UCHAR           REG_HOLDING_START;
-    UCHAR           REG_HOLDING_NREGS;
-    UCHAR           usRegHoldStart;
+    USHORT          REG_HOLDING_START;
+    USHORT          REG_HOLDING_NREGS;
+    USHORT          usRegHoldStart;
 
-    //Determine the master or slave
-    if (xMBMasterGetCBRunInMasterMode())
-    {
-    	pusRegHoldingBuf = usMRegHoldBuf[ucMBMasterGetDestAddress()];
-    	REG_HOLDING_START = M_REG_HOLDING_START;
-    	REG_HOLDING_NREGS = M_REG_HOLDING_NREGS;
-    	usRegHoldStart = usMRegHoldStart;
-    	//If mode is read,the master will wirte the received date to bufffer.
-    	eMode = MB_REG_WRITE;
-    }
-    else
-    {
-    	pusRegHoldingBuf = usSRegHoldBuf;
-    	REG_HOLDING_START = S_REG_HOLDING_START;
-    	REG_HOLDING_NREGS = S_REG_HOLDING_NREGS;
-    	usRegHoldStart = usSRegHoldStart;
-    }
+    pusRegHoldingBuf = usSRegHoldBuf;
+    REG_HOLDING_START = S_REG_HOLDING_START;
+    REG_HOLDING_NREGS = S_REG_HOLDING_NREGS;
+    usRegHoldStart = usSRegHoldStart;
 
-    if( ( usAddress >= REG_HOLDING_START ) &&
-        ( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) )
+    /* it already plus one in modbus function method. */
+    usAddress--;
+
+    if ((usAddress >= REG_HOLDING_START)
+            && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS))
     {
-        iRegIndex = ( int )( usAddress - usRegHoldStart );
-        switch ( eMode )
+        iRegIndex = usAddress - usRegHoldStart;
+        switch (eMode)
         {
-            /* Pass current register values to the protocol stack. */
+        /* read current register values from the protocol stack. */
         case MB_REG_READ:
-            while( usNRegs > 0 )
+            while (usNRegs > 0)
             {
-				*pucRegBuffer++ = ( unsigned char )( pusRegHoldingBuf[iRegIndex] >> 8 );
-				*pucRegBuffer++ = ( unsigned char )( pusRegHoldingBuf[iRegIndex] & 0xFF );
+                *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8);
+                *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF);
                 iRegIndex++;
                 usNRegs--;
             }
             break;
 
-            /* Update current register values with new values from the
-             * protocol stack. */
+        /* write current register values with new values from the protocol stack. */
         case MB_REG_WRITE:
-            while( usNRegs > 0 )
+            while (usNRegs > 0)
             {
                 pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
                 pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
@@ -182,83 +151,76 @@ eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegi
     }
     return eStatus;
 }
-//****************************线圈状态寄存器回调函数********************************
-//函数定义: eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
-//描    述:线圈状态寄存器相关的功能(读、连续读、写、连续写)
-//入口参数:pucRegBuffer : 位组成一个字节,起始寄存器对应的位处于该字节pucRegBuffer的最低位LSB。
-//                         如果回调函数要写这个缓冲区,没有用到的线圈(例如不是8个一组的线圈状态)对应的位的数值必须设置位0。
-//			usAddress    : 第一个线圈地址。
-//			usNCoils     : 请求的线圈个数
-//          eMode        ;如果该参数为eMBRegisterMode::MB_REG_WRITE,用户的应用数值将从pucRegBuffer中得到更新。
-//                         如果该参数为eMBRegisterMode::MB_REG_READ,用户需要将当前的应用数据存储在pucRegBuffer中
-//出口参数:eMBErrorCode : 这个函数将返回的错误码
-//备    注:Editor:Armink 2010-10-31    Company: BXXJS
-//**********************************************************************************
-eMBErrorCode
-eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
+
+/**
+ * Modbus slave coils callback function.
+ *
+ * @param pucRegBuffer coils buffer
+ * @param usAddress coils address
+ * @param usNCoils coils number
+ * @param eMode read or write
+ *
+ * @return result
+ */
+eMBErrorCode eMBRegCoilsCB(UCHAR * pucRegBuffer, USHORT usAddress,
+        USHORT usNCoils, eMBRegisterMode eMode)
 {
     eMBErrorCode    eStatus = MB_ENOERR;
-    int             iRegIndex , iRegBitIndex , iNReg;
-	UCHAR *         pucCoilBuf;
-    UCHAR           COIL_START;
-    UCHAR           COIL_NCOILS;
-    UCHAR           usCoilStart;
-    iNReg =  usNCoils / 8 + 1;        //占用寄存器数量
+    USHORT          iRegIndex , iRegBitIndex , iNReg;
+    UCHAR *         pucCoilBuf;
+    USHORT          COIL_START;
+    USHORT          COIL_NCOILS;
+    USHORT          usCoilStart;
+    iNReg =  usNCoils / 8 + 1;
 
+    pucCoilBuf = ucSCoilBuf;
+    COIL_START = S_COIL_START;
+    COIL_NCOILS = S_COIL_NCOILS;
+    usCoilStart = usSCoilStart;
 
-    //Determine the master or slave
-    if (xMBMasterGetCBRunInMasterMode())
-    {
-    	pucCoilBuf = ucMCoilBuf[ucMBMasterGetDestAddress()];
-    	COIL_START = M_COIL_START;
-    	COIL_NCOILS = M_COIL_NCOILS;
-    	usCoilStart = usMCoilStart;
-    	//If mode is read,the master will wirte the received date to bufffer.
-    	eMode = MB_REG_WRITE;
-    }
-    else
-    {
-    	pucCoilBuf = ucSCoilBuf;
-    	COIL_START = S_COIL_START;
-    	COIL_NCOILS = S_COIL_NCOILS;
-    	usCoilStart = usSCoilStart;
-    }
+    /* it already plus one in modbus function method. */
+    usAddress--;
 
     if( ( usAddress >= COIL_START ) &&
         ( usAddress + usNCoils <= COIL_START + COIL_NCOILS ) )
     {
-        iRegIndex    = ( int )( usAddress - usCoilStart ) / 8 ;    //每个寄存器存8个
-		iRegBitIndex = ( int )( usAddress - usCoilStart ) % 8 ;	   //相对于寄存器内部的位地址
+        iRegIndex = (USHORT) (usAddress - usCoilStart) / 8;
+        iRegBitIndex = (USHORT) (usAddress - usCoilStart) % 8;
         switch ( eMode )
         {
-            /* Pass current coil values to the protocol stack. */
+        /* read current coil values from the protocol stack. */
         case MB_REG_READ:
-            while( iNReg > 0 )
+            while (iNReg > 0)
             {
-				*pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++] , iRegBitIndex , 8);
-                iNReg --;
+                *pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++],
+                        iRegBitIndex, 8);
+                iNReg--;
             }
-			pucRegBuffer --;
-			usNCoils = usNCoils % 8;                        //余下的线圈数	
-			*pucRegBuffer = *pucRegBuffer <<(8 - usNCoils); //高位补零
-			*pucRegBuffer = *pucRegBuffer >>(8 - usNCoils);
+            pucRegBuffer--;
+            /* last coils */
+            usNCoils = usNCoils % 8;
+            /* filling zero to high bit */
+            *pucRegBuffer = *pucRegBuffer << (8 - usNCoils);
+            *pucRegBuffer = *pucRegBuffer >> (8 - usNCoils);
             break;
 
-            /* Update current coil values with new values from the
-             * protocol stack. */
+            /* write current coil values with new values from the protocol stack. */
         case MB_REG_WRITE:
-            while(iNReg > 1)									 //最后面余下来的数单独算
+            while (iNReg > 1)
             {
-				xMBUtilSetBits(&pucCoilBuf[iRegIndex++] , iRegBitIndex  , 8 , *pucRegBuffer++);
+                xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, 8,
+                        *pucRegBuffer++);
                 iNReg--;
             }
-			usNCoils = usNCoils % 8;                            //余下的线圈数
-			if (usNCoils != 0)                                  //xMBUtilSetBits方法 在操作位数量为0时存在bug
-			{
-				xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils,
-						*pucRegBuffer++);
-			}
-			break;
+            /* last coils */
+            usNCoils = usNCoils % 8;
+            /* xMBUtilSetBits has bug when ucNBits is zero */
+            if (usNCoils != 0)
+            {
+                xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils,
+                        *pucRegBuffer++);
+            }
+            break;
         }
     }
     else
@@ -267,78 +229,52 @@ eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegis
     }
     return eStatus;
 }
-//****************************离散输入寄存器回调函数********************************
-//函数定义: eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
-//描    述:离散输入寄存器相关的功能(读、连续读)
-//入口参数:pucRegBuffer : 用当前的线圈数据更新这个寄存器,起始寄存器对应的位处于该字节pucRegBuffer的最低位LSB。
-//                         如果回调函数要写这个缓冲区,没有用到的线圈(例如不是8个一组的线圈状态)对应的位的数值必须设置为0。
-//			usAddress    : 离散输入的起始地址
-//			usNDiscrete  : 离散输入点数量
-//出口参数:eMBErrorCode : 这个函数将返回的错误码
-//备    注:Editor:Armink 2010-10-31    Company: BXXJS
-//**********************************************************************************
-eMBErrorCode
-eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
+
+/**
+ * Modbus slave discrete callback function.
+ *
+ * @param pucRegBuffer discrete buffer
+ * @param usAddress discrete address
+ * @param usNDiscrete discrete number
+ *
+ * @return result
+ */
+eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
 {
     eMBErrorCode    eStatus = MB_ENOERR;
-	int             iRegIndex , iRegBitIndex , iNReg;
-	UCHAR *         pucDiscreteInputBuf;
-    UCHAR           DISCRETE_INPUT_START;
-    UCHAR           DISCRETE_INPUT_NDISCRETES;
-    UCHAR           usDiscreteInputStart;
-	iNReg =  usNDiscrete / 8 + 1;        //占用寄存器数量
+    USHORT          iRegIndex , iRegBitIndex , iNReg;
+    UCHAR *         pucDiscreteInputBuf;
+    USHORT          DISCRETE_INPUT_START;
+    USHORT          DISCRETE_INPUT_NDISCRETES;
+    USHORT          usDiscreteInputStart;
+    iNReg =  usNDiscrete / 8 + 1;
 
-    //Determine the master or slave
-    if (xMBMasterGetCBRunInMasterMode())
-    {
-    	pucDiscreteInputBuf = ucMDiscInBuf[ucMBMasterGetDestAddress()];
-    	DISCRETE_INPUT_START = M_DISCRETE_INPUT_START;
-    	DISCRETE_INPUT_NDISCRETES = M_DISCRETE_INPUT_NDISCRETES;
-    	usDiscreteInputStart = usMDiscInStart;
-    }
-    else
-    {
-    	pucDiscreteInputBuf = ucSDiscInBuf;
-    	DISCRETE_INPUT_START = S_DISCRETE_INPUT_START;
-    	DISCRETE_INPUT_NDISCRETES = S_DISCRETE_INPUT_NDISCRETES;
-    	usDiscreteInputStart = usSDiscInStart;
-    }
+    pucDiscreteInputBuf = ucSDiscInBuf;
+    DISCRETE_INPUT_START = S_DISCRETE_INPUT_START;
+    DISCRETE_INPUT_NDISCRETES = S_DISCRETE_INPUT_NDISCRETES;
+    usDiscreteInputStart = usSDiscInStart;
+
+    /* it already plus one in modbus function method. */
+    usAddress--;
 
-    if( ( usAddress >= DISCRETE_INPUT_START )
-        && ( usAddress + usNDiscrete <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES ) )
+    if ((usAddress >= DISCRETE_INPUT_START)
+            && (usAddress + usNDiscrete    <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES))
     {
-        iRegIndex    = ( int )( usAddress - usDiscreteInputStart ) / 8 ;    //每个寄存器存8个
-		iRegBitIndex = ( int )( usAddress - usDiscreteInputStart ) % 8 ;	   //相对于寄存器内部的位地址
+        iRegIndex = (USHORT) (usAddress - usDiscreteInputStart) / 8;
+        iRegBitIndex = (USHORT) (usAddress - usDiscreteInputStart) % 8;
 
-	    //Determine the master or slave
-	    if (xMBMasterGetCBRunInMasterMode())
-	    {
-			/* Update current coil values with new values from the
-			 * protocol stack. */
-			while(iNReg > 1)									 //最后面余下来的数单独算
-			{
-				xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++] , iRegBitIndex  , 8 , *pucRegBuffer++);
-				iNReg--;
-			}
-			usNDiscrete = usNDiscrete % 8;                        //余下的线圈数
-			if (usNDiscrete != 0)                                 //xMBUtilSetBits方法 在操作位数量为0时存在bug
-			{
-				xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex,
-						usNDiscrete, *pucRegBuffer++);
-			}
-	    }
-	    else
-	    {
-			while( iNReg > 0 )
-			{
-				*pucRegBuffer++ = xMBUtilGetBits(&pucDiscreteInputBuf[iRegIndex++] , iRegBitIndex , 8);
-				iNReg --;
-			}
-			pucRegBuffer --;
-			usNDiscrete = usNDiscrete % 8;                     //余下的线圈数
-			*pucRegBuffer = *pucRegBuffer <<(8 - usNDiscrete); //高位补零
-			*pucRegBuffer = *pucRegBuffer >>(8 - usNDiscrete);
-	    }
+        while (iNReg > 0)
+        {
+            *pucRegBuffer++ = xMBUtilGetBits(&pucDiscreteInputBuf[iRegIndex++],
+                    iRegBitIndex, 8);
+            iNReg--;
+        }
+        pucRegBuffer--;
+        /* last discrete */
+        usNDiscrete = usNDiscrete % 8;
+        /* filling zero to high bit */
+        *pucRegBuffer = *pucRegBuffer << (8 - usNDiscrete);
+        *pucRegBuffer = *pucRegBuffer >> (8 - usNDiscrete);
     }
     else
     {
@@ -347,3 +283,4 @@ eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
 
     return eStatus;
 }
+

+ 25 - 33
components/net/freemodbus-v1.6.0/port/user_mb_app.h

@@ -1,4 +1,4 @@
-#ifndef	USER_APP
+#ifndef    USER_APP
 #define USER_APP
 /* ----------------------- Modbus includes ----------------------------------*/
 #include "mb.h"
@@ -8,47 +8,39 @@
 #include "mbutils.h"
 
 /* -----------------------Slave Defines -------------------------------------*/
-#define S_DISCRETE_INPUT_START        1
+#define S_DISCRETE_INPUT_START        0
 #define S_DISCRETE_INPUT_NDISCRETES   16
-#define S_COIL_START                  1
+#define S_COIL_START                  0
 #define S_COIL_NCOILS                 64
-#define S_REG_INPUT_START             1
+#define S_REG_INPUT_START             0
 #define S_REG_INPUT_NREGS             100
-#define S_REG_HOLDING_START           1
+#define S_REG_HOLDING_START           0
 #define S_REG_HOLDING_NREGS           100
-//从机模式:在保持寄存器中,各个地址对应的功能定义
-#define          S_HD_RESERVE                     0		  //保留
-#define          S_HD_CPU_USAGE_MAJOR             1         //当前CPU利用率的整数位
-#define          S_HD_CPU_USAGE_MINOR             2         //当前CPU利用率的小数位
-
-//从机模式:在输入寄存器中,各个地址对应的功能定义
-#define          S_IN_RESERVE                     0		  //保留
-
-//从机模式:在线圈中,各个地址对应的功能定义
-#define          S_CO_RESERVE                     2		  //保留
-
-//从机模式:在离散输入中,各个地址对应的功能定义
-#define          S_DI_RESERVE                     1		  //保留
+/* salve mode: holding register's all address */
+#define          S_HD_RESERVE                     0
+/* salve mode: input register's all address */
+#define          S_IN_RESERVE                     0
+/* salve mode: coil's all address */
+#define          S_CO_RESERVE                     0
+/* salve mode: discrete's all address */
+#define          S_DI_RESERVE                     0
 
 /* -----------------------Master Defines -------------------------------------*/
-#define M_DISCRETE_INPUT_START        1
+#define M_DISCRETE_INPUT_START        0
 #define M_DISCRETE_INPUT_NDISCRETES   16
-#define M_COIL_START                  1
+#define M_COIL_START                  0
 #define M_COIL_NCOILS                 64
-#define M_REG_INPUT_START             1
+#define M_REG_INPUT_START             0
 #define M_REG_INPUT_NREGS             100
-#define M_REG_HOLDING_START           1
+#define M_REG_HOLDING_START           0
 #define M_REG_HOLDING_NREGS           100
-//主机模式:在保持寄存器中,各个地址对应的功能定义
-#define          M_HD_RESERVE                     0		  //保留
-
-//主机模式:在输入寄存器中,各个地址对应的功能定义
-#define          M_IN_RESERVE                     0		  //保留
-
-//主机模式:在线圈中,各个地址对应的功能定义
-#define          M_CO_RESERVE                     2		  //保留
-
-//主机模式:在离散输入中,各个地址对应的功能定义
-#define          M_DI_RESERVE                     1		  //保留
+/* master mode: holding register's all address */
+#define          M_HD_RESERVE                     0
+/* master mode: input register's all address */
+#define          M_IN_RESERVE                     0
+/* master mode: coil's all address */
+#define          M_CO_RESERVE                     0
+/* master mode: discrete's all address */
+#define          M_DI_RESERVE                     0
 
 #endif

+ 294 - 0
components/net/freemodbus-v1.6.0/port/user_mb_app_m.c

@@ -0,0 +1,294 @@
+/*
+ * FreeModbus Libary: user callback functions and buffer define in master mode
+ * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * File: $Id: user_mb_app_m.c,v 1.60 2013/11/23 11:49:05 Armink $
+ */
+#include "user_mb_app.h"
+
+/*-----------------------Master mode use these variables----------------------*/
+#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
+//Master mode:DiscreteInputs variables
+USHORT   usMDiscInStart                             = M_DISCRETE_INPUT_START;
+#if      M_DISCRETE_INPUT_NDISCRETES%8
+UCHAR    ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8+1];
+#else
+UCHAR    ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8];
+#endif
+//Master mode:Coils variables
+USHORT   usMCoilStart                               = M_COIL_START;
+#if      M_COIL_NCOILS%8
+UCHAR    ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8+1];
+#else
+UCHAR    ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8];
+#endif
+//Master mode:InputRegister variables
+USHORT   usMRegInStart                              = M_REG_INPUT_START;
+USHORT   usMRegInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_INPUT_NREGS];
+//Master mode:HoldingRegister variables
+USHORT   usMRegHoldStart                            = M_REG_HOLDING_START;
+USHORT   usMRegHoldBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_HOLDING_NREGS];
+
+/**
+ * Modbus master input register callback function.
+ *
+ * @param pucRegBuffer input register buffer
+ * @param usAddress input register address
+ * @param usNRegs input register number
+ *
+ * @return result
+ */
+eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
+{
+    eMBErrorCode    eStatus = MB_ENOERR;
+    USHORT          iRegIndex;
+    USHORT *        pusRegInputBuf;
+    USHORT          REG_INPUT_START;
+    USHORT          REG_INPUT_NREGS;
+    USHORT          usRegInStart;
+
+    pusRegInputBuf = usMRegInBuf[ucMBMasterGetDestAddress() - 1];
+    REG_INPUT_START = M_REG_INPUT_START;
+    REG_INPUT_NREGS = M_REG_INPUT_NREGS;
+    usRegInStart = usMRegInStart;
+
+    /* it already plus one in modbus function method. */
+    usAddress--;
+
+    if ((usAddress >= REG_INPUT_START)
+            && (usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS))
+    {
+        iRegIndex = usAddress - usRegInStart;
+        while (usNRegs > 0)
+        {
+            pusRegInputBuf[iRegIndex] = *pucRegBuffer++ << 8;
+            pusRegInputBuf[iRegIndex] |= *pucRegBuffer++;
+            iRegIndex++;
+            usNRegs--;
+        }
+    }
+    else
+    {
+        eStatus = MB_ENOREG;
+    }
+
+    return eStatus;
+}
+
+/**
+ * Modbus master holding register callback function.
+ *
+ * @param pucRegBuffer holding register buffer
+ * @param usAddress holding register address
+ * @param usNRegs holding register number
+ * @param eMode read or write
+ *
+ * @return result
+ */
+eMBErrorCode eMBMasterRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress,
+        USHORT usNRegs, eMBRegisterMode eMode)
+{
+    eMBErrorCode    eStatus = MB_ENOERR;
+    USHORT          iRegIndex;
+    USHORT *        pusRegHoldingBuf;
+    USHORT          REG_HOLDING_START;
+    USHORT          REG_HOLDING_NREGS;
+    USHORT          usRegHoldStart;
+
+    pusRegHoldingBuf = usMRegHoldBuf[ucMBMasterGetDestAddress() - 1];
+    REG_HOLDING_START = M_REG_HOLDING_START;
+    REG_HOLDING_NREGS = M_REG_HOLDING_NREGS;
+    usRegHoldStart = usMRegHoldStart;
+    /* if mode is read, the master will write the received date to buffer. */
+    eMode = MB_REG_WRITE;
+
+    /* it already plus one in modbus function method. */
+    usAddress--;
+
+    if ((usAddress >= REG_HOLDING_START)
+            && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS))
+    {
+        iRegIndex = usAddress - usRegHoldStart;
+        switch (eMode)
+        {
+        /* read current register values from the protocol stack. */
+        case MB_REG_READ:
+            while (usNRegs > 0)
+            {
+                *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8);
+                *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF);
+                iRegIndex++;
+                usNRegs--;
+            }
+            break;
+        /* write current register values with new values from the protocol stack. */
+        case MB_REG_WRITE:
+            while (usNRegs > 0)
+            {
+                pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
+                pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
+                iRegIndex++;
+                usNRegs--;
+            }
+            break;
+        }
+    }
+    else
+    {
+        eStatus = MB_ENOREG;
+    }
+    return eStatus;
+}
+
+/**
+ * Modbus master coils callback function.
+ *
+ * @param pucRegBuffer coils buffer
+ * @param usAddress coils address
+ * @param usNCoils coils number
+ * @param eMode read or write
+ *
+ * @return result
+ */
+eMBErrorCode eMBMasterRegCoilsCB(UCHAR * pucRegBuffer, USHORT usAddress,
+        USHORT usNCoils, eMBRegisterMode eMode)
+{
+    eMBErrorCode    eStatus = MB_ENOERR;
+    USHORT          iRegIndex , iRegBitIndex , iNReg;
+    UCHAR *         pucCoilBuf;
+    USHORT          COIL_START;
+    USHORT          COIL_NCOILS;
+    USHORT          usCoilStart;
+    iNReg =  usNCoils / 8 + 1;
+
+    pucCoilBuf = ucMCoilBuf[ucMBMasterGetDestAddress() - 1];
+    COIL_START = M_COIL_START;
+    COIL_NCOILS = M_COIL_NCOILS;
+    usCoilStart = usMCoilStart;
+
+    /* if mode is read,the master will write the received date to buffer. */
+    eMode = MB_REG_WRITE;
+
+    /* it already plus one in modbus function method. */
+    usAddress--;
+
+    if ((usAddress >= COIL_START)
+            && (usAddress + usNCoils <= COIL_START + COIL_NCOILS))
+    {
+        iRegIndex = (USHORT) (usAddress - usCoilStart) / 8;
+        iRegBitIndex = (USHORT) (usAddress - usCoilStart) % 8;
+        switch (eMode)
+        {
+         /* read current coil values from the protocol stack. */
+        case MB_REG_READ:
+            while (iNReg > 0)
+            {
+                *pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++],
+                        iRegBitIndex, 8);
+                iNReg--;
+            }
+            pucRegBuffer--;
+            /* last coils */
+            usNCoils = usNCoils % 8;
+            /* filling zero to high bit */
+            *pucRegBuffer = *pucRegBuffer << (8 - usNCoils);
+            *pucRegBuffer = *pucRegBuffer >> (8 - usNCoils);
+            break;
+
+        /* write current coil values with new values from the protocol stack. */
+        case MB_REG_WRITE:
+            while (iNReg > 1)
+            {
+                xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, 8,
+                        *pucRegBuffer++);
+                iNReg--;
+            }
+            /* last coils */
+            usNCoils = usNCoils % 8;
+            /* xMBUtilSetBits has bug when ucNBits is zero */
+            if (usNCoils != 0)
+            {
+                xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils,
+                        *pucRegBuffer++);
+            }
+            break;
+        }
+    }
+    else
+    {
+        eStatus = MB_ENOREG;
+    }
+    return eStatus;
+}
+
+/**
+ * Modbus master discrete callback function.
+ *
+ * @param pucRegBuffer discrete buffer
+ * @param usAddress discrete address
+ * @param usNDiscrete discrete number
+ *
+ * @return result
+ */
+eMBErrorCode eMBMasterRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
+{
+    eMBErrorCode    eStatus = MB_ENOERR;
+    USHORT          iRegIndex , iRegBitIndex , iNReg;
+    UCHAR *         pucDiscreteInputBuf;
+    USHORT          DISCRETE_INPUT_START;
+    USHORT          DISCRETE_INPUT_NDISCRETES;
+    USHORT          usDiscreteInputStart;
+    iNReg =  usNDiscrete / 8 + 1;
+
+    pucDiscreteInputBuf = ucMDiscInBuf[ucMBMasterGetDestAddress() - 1];
+    DISCRETE_INPUT_START = M_DISCRETE_INPUT_START;
+    DISCRETE_INPUT_NDISCRETES = M_DISCRETE_INPUT_NDISCRETES;
+    usDiscreteInputStart = usMDiscInStart;
+
+    /* it already plus one in modbus function method. */
+    usAddress--;
+
+    if ((usAddress >= DISCRETE_INPUT_START)
+            && (usAddress + usNDiscrete    <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES))
+    {
+        iRegIndex = (USHORT) (usAddress - usDiscreteInputStart) / 8;
+        iRegBitIndex = (USHORT) (usAddress - usDiscreteInputStart) % 8;
+
+        /* write current discrete values with new values from the protocol stack. */
+        while (iNReg > 1)
+        {
+            xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex, 8,
+                    *pucRegBuffer++);
+            iNReg--;
+        }
+        /* last discrete */
+        usNDiscrete = usNDiscrete % 8;
+        /* xMBUtilSetBits has bug when ucNBits is zero */
+        if (usNDiscrete != 0)
+        {
+            xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex,
+                    usNDiscrete, *pucRegBuffer++);
+        }
+    }
+    else
+    {
+        eStatus = MB_ENOREG;
+    }
+
+    return eStatus;
+}
+#endif