From d8bbb5f1264c58c600d7f1fb1f1e95fbbfb94115 Mon Sep 17 00:00:00 2001 From: armink Date: Thu, 5 Feb 2015 17:36:11 +0800 Subject: [PATCH] [modbus]update modbus master and slave source code to lastest. --- .../modbus/functions/mbfunccoils_m.c | 73 +++++-- .../modbus/functions/mbfuncdisc_m.c | 28 ++- .../modbus/functions/mbfuncholding_m.c | 101 ++++++++-- .../modbus/functions/mbfuncinput_m.c | 28 ++- .../freemodbus-v1.6.0/modbus/include/mb_m.h | 180 ++++++++++++++++-- .../modbus/include/mbconfig.h | 6 +- .../freemodbus-v1.6.0/modbus/include/mbport.h | 50 ++++- .../net/freemodbus-v1.6.0/modbus/mb_m.c | 114 +++++++---- .../freemodbus-v1.6.0/modbus/rtu/mbrtu_m.c | 36 ++-- 9 files changed, 492 insertions(+), 124 deletions(-) diff --git a/components/net/freemodbus-v1.6.0/modbus/functions/mbfunccoils_m.c b/components/net/freemodbus-v1.6.0/modbus/functions/mbfunccoils_m.c index 553f57b1b7..f6bb51cdf6 100644 --- a/components/net/freemodbus-v1.6.0/modbus/functions/mbfunccoils_m.c +++ b/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. */ diff --git a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncdisc_m.c b/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncdisc_m.c index 187872c2a6..6c8d6c4741 100644 --- a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncdisc_m.c +++ b/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 ) diff --git a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncholding_m.c b/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncholding_m.c index faefbbbb40..e1fe69e383 100644 --- a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncholding_m.c +++ b/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 ) diff --git a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncinput_m.c b/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncinput_m.c index e5f362bbec..2127efef67 100644 --- a/components/net/freemodbus-v1.6.0/modbus/functions/mbfuncinput_m.c +++ b/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 ) { diff --git a/components/net/freemodbus-v1.6.0/modbus/include/mb_m.h b/components/net/freemodbus-v1.6.0/modbus/include/mb_m.h index 9c4fa43e60..f6b25e2cf3 100644 --- a/components/net/freemodbus-v1.6.0/modbus/include/mb_m.h +++ b/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.
+ * Whenever the protocol stack requires a value it calls one of the callback + * function with the register address and the number of registers to read + * as an argument. The application should then read the actual register values + * (for example the ADC voltage) and should store the result in the supplied + * buffer.
+ * If the protocol stack wants to update a register value because a write + * register function was received a buffer with the new register values is + * passed to the callback function. The function should then use these values + * to update the application register values. + */ + +/*! \ingroup modbus_registers + * \brief Callback function used if the value of a Input Register + * is required by the protocol stack. The starting register address is given + * by \c usAddress and the last register is given by usAddress + + * usNRegs - 1. + * + * \param pucRegBuffer A buffer where the callback function should write + * the current value of the modbus registers to. + * \param usAddress The starting address of the register. Input registers + * are in the range 1 - 65535. + * \param usNRegs Number of registers the callback function must supply. + * + * \return The function must return one of the following error codes: + * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal + * Modbus response is sent. + * - eMBErrorCode::MB_ENOREG If the application does not map an coils + * within the requested address range. In this case a + * ILLEGAL DATA ADDRESS is sent as a response. + */ +eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs ); + +/*! \ingroup modbus_registers + * \brief Callback function used if a Holding Register value is + * read or written by the protocol stack. The starting register address + * is given by \c usAddress and the last register is given by + * usAddress + usNRegs - 1. + * + * \param pucRegBuffer If the application registers values should be updated the + * buffer points to the new registers values. If the protocol stack needs + * to now the current values the callback function should write them into + * this buffer. + * \param usAddress The starting address of the register. + * \param usNRegs Number of registers to read or write. + * \param eMode If eMBRegisterMode::MB_REG_WRITE the application register + * values should be updated from the values in the buffer. For example + * this would be the case when the Modbus master has issued an + * WRITE SINGLE REGISTER command. + * If the value eMBRegisterMode::MB_REG_READ the application should copy + * the current values into the buffer \c pucRegBuffer. + * + * \return The function must return one of the following error codes: + * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal + * Modbus response is sent. + * - eMBErrorCode::MB_ENOREG If the application does not map an coils + * within the requested address range. In this case a + * ILLEGAL DATA ADDRESS is sent as a response. + */ +eMBErrorCode eMBMasterRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNRegs, eMBRegisterMode eMode ); + +/*! \ingroup modbus_registers + * \brief Callback function used if a Coil Register value is + * read or written by the protocol stack. If you are going to use + * this function you might use the functions xMBUtilSetBits( ) and + * xMBUtilGetBits( ) for working with bitfields. + * + * \param pucRegBuffer The bits are packed in bytes where the first coil + * starting at address \c usAddress is stored in the LSB of the + * first byte in the buffer pucRegBuffer. + * If the buffer should be written by the callback function unused + * coil values (I.e. if not a multiple of eight coils is used) should be set + * to zero. + * \param usAddress The first coil number. + * \param usNCoils Number of coil values requested. + * \param eMode If eMBRegisterMode::MB_REG_WRITE the application values should + * be updated from the values supplied in the buffer \c pucRegBuffer. + * If eMBRegisterMode::MB_REG_READ the application should store the current + * values in the buffer \c pucRegBuffer. + * + * \return The function must return one of the following error codes: + * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal + * Modbus response is sent. + * - eMBErrorCode::MB_ENOREG If the application does not map an coils + * within the requested address range. In this case a + * ILLEGAL DATA ADDRESS is sent as a response. + */ +eMBErrorCode eMBMasterRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNCoils, eMBRegisterMode eMode ); + +/*! \ingroup modbus_registers + * \brief Callback function used if a Input Discrete Register value is + * read by the protocol stack. + * + * If you are going to use his function you might use the functions + * xMBUtilSetBits( ) and xMBUtilGetBits( ) for working with bitfields. + * + * \param pucRegBuffer The buffer should be updated with the current + * coil values. The first discrete input starting at \c usAddress must be + * stored at the LSB of the first byte in the buffer. If the requested number + * is not a multiple of eight the remaining bits should be set to zero. + * \param usAddress The starting address of the first discrete input. + * \param usNDiscrete Number of discrete input values. + * \return The function must return one of the following error codes: + * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal + * Modbus response is sent. + * - eMBErrorCode::MB_ENOREG If the application does not map an coils + * within the requested address range. In this case a + * ILLEGAL DATA ADDRESS is sent as a response. + */ +eMBErrorCode eMBMasterRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, + USHORT usNDiscrete ); /*! \ingroup modbus *\brief These Modbus functions are called for user when Modbus run in Master Mode. */ eMBMasterReqErrCode -eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs ); +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 -----------------------------------------*/ diff --git a/components/net/freemodbus-v1.6.0/modbus/include/mbconfig.h b/components/net/freemodbus-v1.6.0/modbus/include/mbconfig.h index c5434de47e..89030b7abd 100644 --- a/components/net/freemodbus-v1.6.0/modbus/include/mbconfig.h +++ b/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 diff --git a/components/net/freemodbus-v1.6.0/modbus/include/mbport.h b/components/net/freemodbus-v1.6.0/modbus/include/mbport.h index a4c0a24dd4..11794a2929 100644 --- a/components/net/freemodbus-v1.6.0/modbus/include/mbport.h +++ b/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 ------------------*/ /*! diff --git a/components/net/freemodbus-v1.6.0/modbus/mb_m.c b/components/net/freemodbus-v1.6.0/modbus/mb_m.c index 8f86f54182..4e7c4b2b74 100644 --- a/components/net/freemodbus-v1.6.0/modbus/mb_m.c +++ b/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 diff --git a/components/net/freemodbus-v1.6.0/modbus/rtu/mbrtu_m.c b/components/net/freemodbus-v1.6.0/modbus/rtu/mbrtu_m.c index fffbb23f9f..987c9a3156 100644 --- a/components/net/freemodbus-v1.6.0/modbus/rtu/mbrtu_m.c +++ b/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