modbus master fix event loop and kconfig

This commit is contained in:
Alex Lisitsyn
2023-06-20 02:38:53 +08:00
parent 2d79f8cc67
commit bf34b5bb8d
22 changed files with 337 additions and 301 deletions

View File

@ -118,12 +118,6 @@ build_idf_v4.3:
variables: variables:
TEST_TARGETS: "esp32 esp32s2 esp32c3" TEST_TARGETS: "esp32 esp32s2 esp32c3"
build_idf_v4.2:
extends: .build_pytest_template
image: espressif/idf:release-v4.2
variables:
TEST_TARGETS: "esp32 esp32s2"
.target_test_template: .target_test_template:
image: $TARGET_TEST_ENV_IMAGE image: $TARGET_TEST_ENV_IMAGE
stage: target_test stage: target_test
@ -200,7 +194,7 @@ build_docs:
script: script:
- cd docs - cd docs
- pip install -r requirements.txt - pip install -r requirements.txt
- build-docs -l en -t esp32 - ./generate_docs
.deploy_docs_template: .deploy_docs_template:
stage: deploy stage: deploy

View File

@ -57,8 +57,8 @@ menu "Modbus configuration"
config FMB_MASTER_TIMEOUT_MS_RESPOND config FMB_MASTER_TIMEOUT_MS_RESPOND
int "Slave respond timeout (Milliseconds)" int "Slave respond timeout (Milliseconds)"
default 150 default 3000
range 50 3000 range 150 15000
help help
If master sends a frame which is not broadcast, it has to wait sometime for slave response. If master sends a frame which is not broadcast, it has to wait sometime for slave response.
if slave is not respond in this time, the master will process timeout error. if slave is not respond in this time, the master will process timeout error.
@ -66,7 +66,7 @@ menu "Modbus configuration"
config FMB_MASTER_DELAY_MS_CONVERT config FMB_MASTER_DELAY_MS_CONVERT
int "Slave conversion delay (Milliseconds)" int "Slave conversion delay (Milliseconds)"
default 200 default 200
range 50 400 range 150 2000
help help
If master sends a broadcast frame, it has to wait conversion time to delay, If master sends a broadcast frame, it has to wait conversion time to delay,
then master can send next frame. then master can send next frame.
@ -107,7 +107,7 @@ menu "Modbus configuration"
config FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS config FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS
int "Response timeout for ASCII communication mode (ms)" int "Response timeout for ASCII communication mode (ms)"
default 1000 default 1000
range 300 2000 range 200 5000
depends on FMB_COMM_MODE_ASCII_EN depends on FMB_COMM_MODE_ASCII_EN
help help
This option defines response timeout of slave in milliseconds for ASCII communication mode. This option defines response timeout of slave in milliseconds for ASCII communication mode.

View File

@ -1,16 +1,14 @@
var DOCUMENTATION_VERSIONS = { var DOCUMENTATION_VERSIONS = {
DEFAULTS: { has_targets: true,
supported_targets: [ "esp32", "esp32s2", "esp32s3", "esp32c3" ]
},
VERSIONS: [ VERSIONS: [
{ name: "latest" }, { name: "latest", has_targets: true, supported_targets: [ "esp32", "esp32s2", "esp32s3", "esp32c2", "esp32c3", "esp32c6", "esp32h2" ] },
{ name: "v1.0.1", old:false },
{ name: "v1.0.0", old:true }
], ],
IDF_TARGETS: [ IDF_TARGETS: [
{ text: "ESP32", value: "esp32"}, { text: "ESP32", value: "esp32"},
{ text: "ESP32-S2", value: "esp32s2"}, { text: "ESP32-S2", value: "esp32s2"},
{ text: "ESP32-S3", value: "esp32s3"}, { text: "ESP32-S3", value: "esp32s3"},
{ text: "ESP32-C3", value: "esp32c3"} { text: "ESP32-C2", value: "esp32c2"},
{ text: "ESP32-C3", value: "esp32c3"},
{ text: "ESP32-C6", value: "esp32c6"},
{ text: "ESP32-H2", value: "esp32h2"}
] ]
}; };

View File

@ -29,5 +29,5 @@ html_static_path = ['../_static']
project_slug = 'esp-modbus' project_slug = 'esp-modbus'
versions_url = './_static/modbus_docs_versions.js' versions_url = './_static/modbus_docs_versions.js'
idf_targets = ['esp32', 'esp32s2', 'esp32c3'] idf_targets = [ 'esp32' ]
languages = ['en'] languages = ['en']

27
docs/generate_docs Executable file
View File

@ -0,0 +1,27 @@
#!/bin/bash
rm -rf docs
build-docs --target esp32 --language en
# Modifes target field of html files
ELEMENT="<script type='text/javascript'>
window.onload =(function() {
var myAnchor = document.getElementById('target-select');
var mySpan = document.createElement('input');
mySpan.style.float = 'left';
mySpan.setAttribute('type', 'text');
mySpan.setAttribute('maxLength', '10');
mySpan.value = 'all targets';
mySpan.setAttribute('disabled', true);
myAnchor.parentNode.replaceChild(mySpan, myAnchor);
})();
</script>"
FILES=$(find . -path "*/_build/en/esp32/html/*.html")
for FILE in ${FILES}
do
echo ${ELEMENT} >> "${FILE}"
done

View File

@ -110,7 +110,7 @@ eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils, LONG
ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF ] = usNCoils >> 8; ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF ] = usNCoils >> 8;
ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF + 1] = usNCoils; ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF + 1] = usNCoils;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE ); vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT ); ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT | EV_MASTER_TRANS_START );
eErrStatus = eMBMasterWaitRequestFinish( ); eErrStatus = eMBMasterWaitRequestFinish( );
} }
@ -217,7 +217,7 @@ eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData, LO
ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF ] = usCoilData >> 8; ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF ] = usCoilData >> 8;
ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usCoilData; ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usCoilData;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE ); vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT ); ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT | EV_MASTER_TRANS_START );
eErrStatus = eMBMasterWaitRequestFinish( ); eErrStatus = eMBMasterWaitRequestFinish( );
} }
return eErrStatus; return eErrStatus;
@ -327,7 +327,7 @@ eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr,
*ucMBFrame++ = pucDataBuffer[usRegIndex++]; *ucMBFrame++ = pucDataBuffer[usRegIndex++];
} }
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + ucByteCount ); vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + ucByteCount );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT ); ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT | EV_MASTER_TRANS_START );
eErrStatus = eMBMasterWaitRequestFinish( ); eErrStatus = eMBMasterWaitRequestFinish( );
} }
return eErrStatus; return eErrStatus;

View File

@ -92,7 +92,7 @@ eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT u
ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF ] = usNDiscreteIn >> 8; ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF ] = usNDiscreteIn >> 8;
ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF + 1] = usNDiscreteIn; ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF + 1] = usNDiscreteIn;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE ); vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT ); ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT | EV_MASTER_TRANS_START );
eErrStatus = eMBMasterWaitRequestFinish( ); eErrStatus = eMBMasterWaitRequestFinish( );
} }
return eErrStatus; return eErrStatus;

View File

@ -122,7 +122,7 @@ eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRe
ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF] = usRegData >> 8; ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF] = usRegData >> 8;
ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usRegData ; ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usRegData ;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE ); vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT ); ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT | EV_MASTER_TRANS_START );
eErrStatus = eMBMasterWaitRequestFinish( ); eErrStatus = eMBMasterWaitRequestFinish( );
} }
return eErrStatus; return eErrStatus;
@ -200,7 +200,7 @@ eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr,
*ucMBFrame++ = pusDataBuffer[usRegIndex++] ; *ucMBFrame++ = pusDataBuffer[usRegIndex++] ;
} }
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + 2*usNRegs ); vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + 2*usNRegs );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT ); ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT | EV_MASTER_TRANS_START );
eErrStatus = eMBMasterWaitRequestFinish( ); eErrStatus = eMBMasterWaitRequestFinish( );
} }
return eErrStatus; return eErrStatus;
@ -286,7 +286,7 @@ eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRe
ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] = usNRegs >> 8; ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] = usNRegs >> 8;
ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs; ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE ); vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT ); ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT | EV_MASTER_TRANS_START );
eErrStatus = eMBMasterWaitRequestFinish( ); eErrStatus = eMBMasterWaitRequestFinish( );
} }
return eErrStatus; return eErrStatus;
@ -392,7 +392,7 @@ eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr,
*ucMBFrame++ = pusDataBuffer[usRegIndex++] ; *ucMBFrame++ = pusDataBuffer[usRegIndex++] ;
} }
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READWRITE_SIZE_MIN + 2*usNWriteRegs ); vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READWRITE_SIZE_MIN + 2*usNWriteRegs );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT ); ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT | EV_MASTER_TRANS_START );
eErrStatus = eMBMasterWaitRequestFinish( ); eErrStatus = eMBMasterWaitRequestFinish( );
} }
return eErrStatus; return eErrStatus;

View File

@ -93,7 +93,7 @@ eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs
ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] = usNRegs >> 8; ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] = usNRegs >> 8;
ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs; ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs;
vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE ); vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE );
( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT ); ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT | EV_MASTER_TRANS_START );
eErrStatus = eMBMasterWaitRequestFinish( ); eErrStatus = eMBMasterWaitRequestFinish( );
} }
return eErrStatus; return eErrStatus;

View File

@ -103,7 +103,7 @@ typedef enum
MB_TMODE_T35, /*!< Master receive frame T3.5 timeout. */ MB_TMODE_T35, /*!< Master receive frame T3.5 timeout. */
MB_TMODE_RESPOND_TIMEOUT, /*!< Master wait respond for slave. */ MB_TMODE_RESPOND_TIMEOUT, /*!< Master wait respond for slave. */
MB_TMODE_CONVERT_DELAY /*!< Master sent broadcast ,then delay sometime.*/ MB_TMODE_CONVERT_DELAY /*!< Master sent broadcast ,then delay sometime.*/
}eMBMasterTimerMode; } eMBMasterTimerMode;
/* ----------------------- Function prototypes ------------------------------*/ /* ----------------------- Function prototypes ------------------------------*/
/*! \ingroup modbus /*! \ingroup modbus

View File

@ -99,6 +99,9 @@ PR_BEGIN_EXTERN_C
#define MB_ASCII_BITS_PER_SYMB ( CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB ) #define MB_ASCII_BITS_PER_SYMB ( CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB )
#endif #endif
#define MB_EVENT_QUEUE_SIZE ( CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE )
#define MB_EVENT_QUEUE_TIMEOUT ( pdMS_TO_TICKS( CONFIG_FMB_EVENT_QUEUE_TIMEOUT ) )
/*! \brief The character timeout value for Modbus ASCII. /*! \brief The character timeout value for Modbus ASCII.
* *
* The character timeout value is not fixed for Modbus ASCII and is therefore * The character timeout value is not fixed for Modbus ASCII and is therefore

View File

@ -70,17 +70,18 @@ typedef enum
#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED #if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED
typedef enum { typedef enum {
EV_MASTER_NO_EVENT = 0x0000, EV_MASTER_NO_EVENT = 0x0000,
EV_MASTER_READY = 0x0001, /*!< Startup finished. */ EV_MASTER_TRANS_START = 0x0001, /*!< Transaction start flag */
EV_MASTER_FRAME_RECEIVED = 0x0002, /*!< Frame received. */ EV_MASTER_READY = 0x0002, /*!< Startup finished. */
EV_MASTER_EXECUTE = 0x0004, /*!< Execute function. */ EV_MASTER_FRAME_RECEIVED = 0x0004, /*!< Frame received. */
EV_MASTER_FRAME_SENT = 0x0008, /*!< Frame sent. */ EV_MASTER_EXECUTE = 0x0008, /*!< Execute function. */
EV_MASTER_FRAME_TRANSMIT = 0x0010, /*!< Frame transmission. */ EV_MASTER_FRAME_SENT = 0x0010, /*!< Frame sent. */
EV_MASTER_ERROR_PROCESS = 0x0020, /*!< Frame error process. */ EV_MASTER_FRAME_TRANSMIT = 0x0020, /*!< Frame transmission. */
EV_MASTER_PROCESS_SUCCESS = 0x0040, /*!< Request process success. */ EV_MASTER_ERROR_PROCESS = 0x0040, /*!< Frame error process. */
EV_MASTER_ERROR_RESPOND_TIMEOUT = 0x0080, /*!< Request respond timeout. */ EV_MASTER_PROCESS_SUCCESS = 0x0080, /*!< Request process success. */
EV_MASTER_ERROR_RECEIVE_DATA = 0x0100, /*!< Request receive data error. */ EV_MASTER_ERROR_RESPOND_TIMEOUT = 0x0100, /*!< Request respond timeout. */
EV_MASTER_ERROR_EXECUTE_FUNCTION = 0x0200 /*!< Request execute function error. */ EV_MASTER_ERROR_RECEIVE_DATA = 0x0200, /*!< Request receive data error. */
} eMBMasterEventType; EV_MASTER_ERROR_EXECUTE_FUNCTION = 0x0400 /*!< Request execute function error. */
} eMBMasterEventEnum;
typedef enum { typedef enum {
EV_ERROR_INIT, /*!< No error, initial state. */ EV_ERROR_INIT, /*!< No error, initial state. */
@ -89,6 +90,14 @@ typedef enum {
EV_ERROR_EXECUTE_FUNCTION, /*!< Execute function error. */ EV_ERROR_EXECUTE_FUNCTION, /*!< Execute function error. */
EV_ERROR_OK /*!< No error, processing completed. */ EV_ERROR_OK /*!< No error, processing completed. */
} eMBMasterErrorEventType; } eMBMasterErrorEventType;
typedef struct _MbEventType {
eMBMasterEventEnum eEvent; /*!< event itself. */
uint64_t xTransactionId; /*!< ID of the transaction */
uint64_t xPostTimestamp; /*!< timestamp of event posted */
uint64_t xGetTimestamp; /*!< timestamp of event get */
} xMBMasterEventType;
#endif #endif
/*! \ingroup modbus /*! \ingroup modbus
@ -115,18 +124,21 @@ BOOL xMBPortEventGet( /*@out@ */ eMBEventType * eEvent );
#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED #if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED
BOOL xMBMasterPortEventInit( void ); BOOL xMBMasterPortEventInit( void );
BOOL xMBMasterPortEventPost( eMBMasterEventType eEvent ); BOOL xMBMasterPortEventPost( eMBMasterEventEnum eEvent );
BOOL xMBMasterPortEventGet( /*@out@ */ eMBMasterEventType * eEvent ); BOOL xMBMasterPortEventGet( /*@out@ */ xMBMasterEventType * eEvent );
eMBMasterEventType eMBMasterEventEnum
xMBMasterPortFsmWaitConfirmation( eMBMasterEventType eEventMask, ULONG ulTimeout); xMBMasterPortFsmWaitConfirmation( eMBMasterEventEnum eEventMask, ULONG ulTimeout);
void vMBMasterOsResInit( void ); void vMBMasterOsResInit( void );
BOOL xMBMasterRunResTake( LONG time ); BOOL xMBMasterRunResTake( LONG time );
void vMBMasterRunResRelease( void ); void vMBMasterRunResRelease( void );
uint64_t xMBMasterPortGetTransactionId( void );
#endif // MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED #endif // MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED
/* ----------------------- Serial port functions ----------------------------*/ /* ----------------------- Serial port functions ----------------------------*/

View File

@ -62,7 +62,7 @@ PR_BEGIN_EXTERN_C
#define MB_FUNC_OTHER_REPORT_SLAVEID ( 17 ) #define MB_FUNC_OTHER_REPORT_SLAVEID ( 17 )
#define MB_FUNC_ERROR ( 128u ) #define MB_FUNC_ERROR ( 128u )
/* ----------------------- Type definitions ---------------------------------*/ /* ----------------------- Type definitions ---------------------------------*/
typedef enum typedef enum
{ {
MB_EX_NONE = 0x00, MB_EX_NONE = 0x00,
MB_EX_ILLEGAL_FUNCTION = 0x01, MB_EX_ILLEGAL_FUNCTION = 0x01,

View File

@ -36,8 +36,9 @@
*/ */
/* ----------------------- System includes ----------------------------------*/ /* ----------------------- System includes ----------------------------------*/
#include "stdlib.h" #include <stdatomic.h>
#include "string.h" #include <stdlib.h>
#include <string.h>
/* ----------------------- Platform includes --------------------------------*/ /* ----------------------- Platform includes --------------------------------*/
#include "port.h" #include "port.h"
@ -316,171 +317,171 @@ eMBMasterPoll( void )
static UCHAR ucFunctionCode; static UCHAR ucFunctionCode;
static USHORT usLength; static USHORT usLength;
static eMBException eException; static eMBException eException;
static BOOL xTransactionIsActive = FALSE; static uint64_t xCurTransactionId = 0;
int i; int i;
int j; int j;
eMBErrorCode eStatus = MB_ENOERR; eMBErrorCode eStatus = MB_ENOERR;
eMBMasterEventType eEvent; xMBMasterEventType xEvent;
eMBMasterErrorEventType errorType; eMBMasterErrorEventType errorType;
/* Check if the protocol stack is ready. */ /* Check if the protocol stack is ready. */
if( eMBState != STATE_ENABLED ) if( eMBState != STATE_ENABLED ) {
{
return MB_EILLSTATE; return MB_EILLSTATE;
} }
/* Check if there is a event available. If not return control to caller. /* Check if there is a event available. If not return control to caller.
* Otherwise we will handle the event. */ * Otherwise we will handle the event. */
if ( xMBMasterPortEventGet( &eEvent ) == TRUE ) if ( xMBMasterPortEventGet( &xEvent ) == TRUE ) {
{ switch( xEvent.eEvent ) {
while( eEvent ) {
// In some cases it is possible that more than one event set // In some cases it is possible that more than one event set
// together (even from one subset mask) than process them consistently // together (even from one subset mask) than process them consistently
if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_READY ) ) { case EV_MASTER_READY:
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_READY", __func__); ESP_LOGD(MB_PORT_TAG, "%" PRIu64 ":EV_MASTER_READY", xEvent.xTransactionId);
vMBMasterSetErrorType( EV_ERROR_INIT ); vMBMasterSetErrorType( EV_ERROR_INIT );
vMBMasterRunResRelease( ); vMBMasterRunResRelease( );
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_READY ); break;
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_TRANSMIT ) ) { case EV_MASTER_FRAME_TRANSMIT:
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_FRAME_TRANSMIT", __func__); ESP_LOGD(MB_PORT_TAG, "%" PRIu64 ":EV_MASTER_FRAME_TRANSMIT", xEvent.xTransactionId);
/* Master is busy now. */ /* Master is busy now. */
vMBMasterGetPDUSndBuf( &ucMBSendFrame ); vMBMasterGetPDUSndBuf( &ucMBSendFrame );
ESP_LOG_BUFFER_HEX_LEVEL("POLL transmit buffer", (void*)ucMBSendFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG); ESP_LOG_BUFFER_HEX_LEVEL("POLL transmit buffer", (void*)ucMBSendFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG);
eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBSendFrame, usMBMasterGetPDUSndLength() ); eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBSendFrame, usMBMasterGetPDUSndLength() );
if (eStatus != MB_ENOERR) if (eStatus != MB_ENOERR) {
{
vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA); vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
ESP_LOGE( MB_PORT_TAG, "%s:Frame send error. %u", __func__, (unsigned)eStatus ); ESP_LOGE( MB_PORT_TAG, "%" PRIu64 ":Frame send error = %d", xEvent.xTransactionId, (unsigned)eStatus );
} }
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_TRANSMIT ); xCurTransactionId = xEvent.xTransactionId;
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_SENT ) ) { break;
ESP_LOGD( MB_PORT_TAG, "%s:EV_MASTER_FRAME_SENT", __func__ ); case EV_MASTER_FRAME_SENT:
ESP_LOG_BUFFER_HEX_LEVEL("POLL sent buffer", (void*)ucMBSendFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG); if (xCurTransactionId == xEvent.xTransactionId) {
xTransactionIsActive = TRUE; ESP_LOGD( MB_PORT_TAG, "%" PRIu64 ":EV_MASTER_FRAME_SENT", xEvent.xTransactionId );
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_SENT ); ESP_LOG_BUFFER_HEX_LEVEL("POLL sent buffer", (void*)ucMBSendFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG);
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_RECEIVED ) ) { }
if (xTransactionIsActive) { break;
ESP_LOGD( MB_PORT_TAG, "%s:EV_MASTER_FRAME_RECEIVED", __func__ ); case EV_MASTER_FRAME_RECEIVED:
eStatus = peMBMasterFrameReceiveCur( &ucRcvAddress, &ucMBRcvFrame, &usLength); ESP_LOGD( MB_PORT_TAG, "%" PRIu64 ":EV_MASTER_FRAME_RECEIVED", xEvent.xTransactionId );
eStatus = peMBMasterFrameReceiveCur( &ucRcvAddress, &ucMBRcvFrame, &usLength);
if (xCurTransactionId == xEvent.xTransactionId) {
MB_PORT_CHECK(ucMBSendFrame, MB_EILLSTATE, "Send buffer initialization fail."); MB_PORT_CHECK(ucMBSendFrame, MB_EILLSTATE, "Send buffer initialization fail.");
// Check if the frame is for us. If not ,send an error process event. // Check if the frame is for us. If not ,send an error process event.
if ( ( eStatus == MB_ENOERR ) && ( ( ucRcvAddress == ucMBMasterGetDestAddress() ) if ( ( eStatus == MB_ENOERR ) && ( ( ucRcvAddress == ucMBMasterGetDestAddress() )
|| ( ucRcvAddress == MB_TCP_PSEUDO_ADDRESS) ) ) { || ( ucRcvAddress == MB_TCP_PSEUDO_ADDRESS) ) ) {
if ( ( ucMBRcvFrame[MB_PDU_FUNC_OFF] & ~MB_FUNC_ERROR ) == ( ucMBSendFrame[MB_PDU_FUNC_OFF] ) ) { if ( ( ucMBRcvFrame[MB_PDU_FUNC_OFF] & ~MB_FUNC_ERROR ) == ( ucMBSendFrame[MB_PDU_FUNC_OFF] ) ) {
ESP_LOGD(MB_PORT_TAG, "%s: Packet data received successfully (%u).", __func__, (unsigned)eStatus); ESP_LOGD(MB_PORT_TAG, "%" PRIu64 ": Packet data received successfully (%u).", xEvent.xTransactionId, (unsigned)eStatus);
ESP_LOG_BUFFER_HEX_LEVEL("POLL receive buffer", (void*)ucMBRcvFrame, (unsigned)usLength, ESP_LOG_DEBUG); ESP_LOG_BUFFER_HEX_LEVEL("POLL receive buffer", (void*)ucMBRcvFrame, (uint16_t)usLength, ESP_LOG_DEBUG);
( void ) xMBMasterPortEventPost( EV_MASTER_EXECUTE ); ( void ) xMBMasterPortEventPost( EV_MASTER_EXECUTE );
} else { } else {
ESP_LOGE( MB_PORT_TAG, "Drop incorrect frame, receive_func(%u) != send_func(%u)", ESP_LOGE( MB_PORT_TAG, "Drop incorrect frame, receive_func(%u) != send_func(%u)",
(UCHAR)ucMBRcvFrame[MB_PDU_FUNC_OFF], (UCHAR)ucMBSendFrame[MB_PDU_FUNC_OFF]); ucMBRcvFrame[MB_PDU_FUNC_OFF], ucMBSendFrame[MB_PDU_FUNC_OFF]);
vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA); vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
} }
} else { } else {
vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA); vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
ESP_LOGD( MB_PORT_TAG, "%s: Packet data receive failed (addr=%u)(%u).", ESP_LOGD( MB_PORT_TAG, "%" PRIu64 ": Packet data receive failed (addr=%u)(%u).",
__func__, (unsigned)ucRcvAddress, (unsigned)eStatus); xEvent.xTransactionId, (unsigned)ucRcvAddress, (unsigned)eStatus);
} }
} else { } else {
// Ignore the `EV_MASTER_FRAME_RECEIVED` event because the respond timeout occurred // Ignore the `EV_MASTER_FRAME_RECEIVED` event because the respond timeout occurred
// and this is likely respond to previous transaction // and this is likely respond to previous transaction
ESP_LOGE( MB_PORT_TAG, "Drop data received outside of transaction."); ESP_LOGE( MB_PORT_TAG, "Drop data received outside of transaction (%" PRIu64 ")", xEvent.xTransactionId );
} }
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_RECEIVED ); break;
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_EXECUTE ) ) { case EV_MASTER_EXECUTE:
MB_PORT_CHECK(ucMBRcvFrame, MB_EILLSTATE, "receive buffer initialization fail."); if (xCurTransactionId == xEvent.xTransactionId) {
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_EXECUTE", __func__); MB_PORT_CHECK(ucMBRcvFrame, MB_EILLSTATE, "receive buffer initialization fail.");
ucFunctionCode = ucMBRcvFrame[MB_PDU_FUNC_OFF]; ESP_LOGD(MB_PORT_TAG, "%" PRIu64 ":EV_MASTER_EXECUTE", xEvent.xTransactionId);
eException = MB_EX_ILLEGAL_FUNCTION; ucFunctionCode = ucMBRcvFrame[MB_PDU_FUNC_OFF];
/* If receive frame has exception. The receive function code highest bit is 1.*/ eException = MB_EX_ILLEGAL_FUNCTION;
if (ucFunctionCode & MB_FUNC_ERROR) /* If receive frame has exception. The receive function code highest bit is 1.*/
{ if (ucFunctionCode & MB_FUNC_ERROR) {
eException = (eMBException)ucMBRcvFrame[MB_PDU_DATA_OFF]; eException = (eMBException)ucMBRcvFrame[MB_PDU_DATA_OFF];
} else { } else {
for ( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ) for ( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ )
{
/* No more function handlers registered. Abort. */
if (xMasterFuncHandlers[i].ucFunctionCode == 0)
{ {
break; /* No more function handlers registered. Abort. */
} if (xMasterFuncHandlers[i].ucFunctionCode == 0) {
if (xMasterFuncHandlers[i].ucFunctionCode == ucFunctionCode) break;
{ }
vMBMasterSetCBRunInMasterMode(TRUE); if (xMasterFuncHandlers[i].ucFunctionCode == ucFunctionCode) {
/* If master request is broadcast, vMBMasterSetCBRunInMasterMode(TRUE);
* the master need execute function for all slave. /* If master request is broadcast,
*/ * the master need execute function for all slave.
if ( xMBMasterRequestIsBroadcast() ) */
{ if ( xMBMasterRequestIsBroadcast() ) {
usLength = usMBMasterGetPDUSndLength(); usLength = usMBMasterGetPDUSndLength();
for(j = 1; j <= MB_MASTER_TOTAL_SLAVE_NUM; j++) for(j = 1; j <= MB_MASTER_TOTAL_SLAVE_NUM; j++)
{ {
vMBMasterSetDestAddress(j); vMBMasterSetDestAddress(j);
eException = xMasterFuncHandlers[i].pxHandler(ucMBRcvFrame, &usLength); eException = xMasterFuncHandlers[i].pxHandler(ucMBRcvFrame, &usLength);
}
} else {
eException = xMasterFuncHandlers[i].pxHandler( ucMBRcvFrame, &usLength );
} }
vMBMasterSetCBRunInMasterMode( FALSE );
break;
} }
else
{
eException = xMasterFuncHandlers[i].pxHandler( ucMBRcvFrame, &usLength );
}
vMBMasterSetCBRunInMasterMode( FALSE );
break;
} }
} }
} /* If master has exception, will send error process event. Otherwise the master is idle.*/
/* If master has exception, will send error process event. Otherwise the master is idle.*/ if ( eException != MB_EX_NONE ) {
if ( eException != MB_EX_NONE ) vMBMasterSetErrorType( EV_ERROR_EXECUTE_FUNCTION );
{
vMBMasterSetErrorType( EV_ERROR_EXECUTE_FUNCTION );
( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
}
else
{
if ( eMBMasterGetErrorType( ) == EV_ERROR_INIT ) {
vMBMasterSetErrorType(EV_ERROR_OK);
ESP_LOGD( MB_PORT_TAG, "%s: set event EV_ERROR_OK", __func__ );
( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
} else {
if ( eMBMasterGetErrorType( ) == EV_ERROR_INIT ) {
vMBMasterSetErrorType(EV_ERROR_OK);
ESP_LOGD( MB_PORT_TAG, "%" PRIu64 ":set event EV_ERROR_OK", xEvent.xTransactionId );
( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
}
} }
} else {
ESP_LOGD( MB_PORT_TAG, "%" PRIu64 ":EV_MASTER_EXECUTE is expired", xEvent.xTransactionId );
} }
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_EXECUTE ); break;
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_ERROR_PROCESS ) ) { case EV_MASTER_ERROR_PROCESS:
ESP_LOGD( MB_PORT_TAG, "%s:EV_MASTER_ERROR_PROCESS", __func__ ); if (xCurTransactionId == xEvent.xTransactionId) {
/* Execute specified error process callback function. */ ESP_LOGD( MB_PORT_TAG, "%" PRIu64 ":EV_MASTER_ERROR_PROCESS", xEvent.xTransactionId);
errorType = eMBMasterGetErrorType( ); /* Execute specified error process callback function. */
vMBMasterGetPDUSndBuf( &ucMBSendFrame ); errorType = eMBMasterGetErrorType( );
switch ( errorType ) vMBMasterGetPDUSndBuf( &ucMBSendFrame );
{ switch ( errorType )
case EV_ERROR_RESPOND_TIMEOUT: {
vMBMasterErrorCBRespondTimeout( ucMBMasterGetDestAddress( ), case EV_ERROR_RESPOND_TIMEOUT:
ucMBSendFrame, usMBMasterGetPDUSndLength( ) ); vMBMasterErrorCBRespondTimeout( ucMBMasterGetDestAddress( ),
break; ucMBSendFrame, usMBMasterGetPDUSndLength( ) );
case EV_ERROR_RECEIVE_DATA: break;
vMBMasterErrorCBReceiveData( ucMBMasterGetDestAddress( ), case EV_ERROR_RECEIVE_DATA:
ucMBSendFrame, usMBMasterGetPDUSndLength( ) ); vMBMasterErrorCBReceiveData( ucMBMasterGetDestAddress( ),
break; ucMBSendFrame, usMBMasterGetPDUSndLength( ) );
case EV_ERROR_EXECUTE_FUNCTION: break;
vMBMasterErrorCBExecuteFunction( ucMBMasterGetDestAddress( ), case EV_ERROR_EXECUTE_FUNCTION:
ucMBSendFrame, usMBMasterGetPDUSndLength( ) ); vMBMasterErrorCBExecuteFunction( ucMBMasterGetDestAddress( ),
break; ucMBSendFrame, usMBMasterGetPDUSndLength( ) );
case EV_ERROR_OK: break;
vMBMasterCBRequestSuccess( ); case EV_ERROR_OK:
break; vMBMasterCBRequestSuccess( );
default: break;
ESP_LOGE( MB_PORT_TAG, "%s: incorrect error type = %u.", __func__, (unsigned)errorType); default:
break; ESP_LOGE( MB_PORT_TAG, "%" PRIu64 ":incorrect error type = %d.", xEvent.xTransactionId, (int)errorType);
break;
}
} }
vMBMasterPortTimersDisable( ); vMBMasterPortTimersDisable( );
uint64_t xProcTime = xCurTransactionId ? ( xEvent.xPostTimestamp - xCurTransactionId ) : 0;
ESP_LOGD( MB_PORT_TAG, "Transaction (%" PRIu64 "), processing time(us) = %" PRId64, xCurTransactionId, xProcTime );
xCurTransactionId = 0;
vMBMasterSetErrorType( EV_ERROR_INIT ); vMBMasterSetErrorType( EV_ERROR_INIT );
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_ERROR_PROCESS );
vMBMasterRunResRelease( ); vMBMasterRunResRelease( );
} break;
default:
ESP_LOGE( MB_PORT_TAG, "%" PRIu64 ":Unexpected event triggered 0x%02x.", xEvent.xTransactionId, (int)xEvent.eEvent );
break;
} }
} else { } else {
// Something went wrong and task unblocked but there are no any correct events set // Something went wrong and task unblocked but there are no any correct events set
ESP_LOGE( MB_PORT_TAG, "%s: Unexpected event triggered 0x%02x.", __func__, (int)eEvent ); ESP_LOGE( MB_PORT_TAG, "%" PRIu64 ": Unexpected event triggered 0x%02x.", xEvent.xTransactionId, (int)xEvent.eEvent );
eStatus = MB_EILLSTATE; eStatus = MB_EILLSTATE;
} }
return eStatus; return eStatus;
@ -489,37 +490,37 @@ eMBMasterPoll( void )
// Get whether the Modbus Master is run in master mode. // Get whether the Modbus Master is run in master mode.
BOOL xMBMasterGetCBRunInMasterMode( void ) BOOL xMBMasterGetCBRunInMasterMode( void )
{ {
return xMBRunInMasterMode; return atomic_load(&xMBRunInMasterMode);
} }
// Set whether the Modbus Master is run in master mode. // Set whether the Modbus Master is run in master mode.
void vMBMasterSetCBRunInMasterMode( BOOL IsMasterMode ) void vMBMasterSetCBRunInMasterMode( BOOL IsMasterMode )
{ {
xMBRunInMasterMode = IsMasterMode; atomic_store(&(xMBRunInMasterMode), IsMasterMode);
} }
// Get Modbus Master send destination address. // Get Modbus Master send destination address.
UCHAR ucMBMasterGetDestAddress( void ) UCHAR ucMBMasterGetDestAddress( void )
{ {
return ucMBMasterDestAddress; return atomic_load(&ucMBMasterDestAddress);
} }
// Set Modbus Master send destination address. // Set Modbus Master send destination address.
void vMBMasterSetDestAddress( UCHAR Address ) void vMBMasterSetDestAddress( UCHAR Address )
{ {
ucMBMasterDestAddress = Address; atomic_store(&(ucMBMasterDestAddress), Address);
} }
// Get Modbus Master current error event type. // Get Modbus Master current error event type.
eMBMasterErrorEventType inline eMBMasterGetErrorType( void ) eMBMasterErrorEventType inline eMBMasterGetErrorType( void )
{ {
return eMBMasterCurErrorType; return atomic_load(&eMBMasterCurErrorType);
} }
// Set Modbus Master current error event type. // Set Modbus Master current error event type.
void IRAM_ATTR vMBMasterSetErrorType( eMBMasterErrorEventType errorType ) void IRAM_ATTR vMBMasterSetErrorType( eMBMasterErrorEventType errorType )
{ {
eMBMasterCurErrorType = errorType; atomic_store(&(eMBMasterCurErrorType), errorType);
} }
/* Get Modbus Master send PDU's buffer address pointer.*/ /* Get Modbus Master send PDU's buffer address pointer.*/
@ -531,25 +532,25 @@ void vMBMasterGetPDUSndBuf( UCHAR ** pucFrame )
/* Set Modbus Master send PDU's buffer length.*/ /* Set Modbus Master send PDU's buffer length.*/
void vMBMasterSetPDUSndLength( USHORT SendPDULength ) void vMBMasterSetPDUSndLength( USHORT SendPDULength )
{ {
usMasterSendPDULength = SendPDULength; atomic_store(&(usMasterSendPDULength), SendPDULength);
} }
/* Get Modbus Master send PDU's buffer length.*/ /* Get Modbus Master send PDU's buffer length.*/
USHORT usMBMasterGetPDUSndLength( void ) USHORT usMBMasterGetPDUSndLength( void )
{ {
return usMasterSendPDULength; return atomic_load(&usMasterSendPDULength);
} }
/* Set Modbus Master current timer mode.*/ /* Set Modbus Master current timer mode.*/
void vMBMasterSetCurTimerMode( eMBMasterTimerMode eMBTimerMode ) void vMBMasterSetCurTimerMode( eMBMasterTimerMode eMBTimerMode )
{ {
eMasterCurTimerMode = eMBTimerMode; atomic_store(&(eMasterCurTimerMode), eMBTimerMode);
} }
/* Get Modbus Master current timer mode.*/ /* Get Modbus Master current timer mode.*/
eMBMasterTimerMode MB_PORT_ISR_ATTR xMBMasterGetCurTimerMode( void ) eMBMasterTimerMode MB_PORT_ISR_ATTR xMBMasterGetCurTimerMode( void )
{ {
return eMasterCurTimerMode; return atomic_load(&eMasterCurTimerMode);
} }
/* The master request is broadcast? */ /* The master request is broadcast? */
@ -561,7 +562,7 @@ BOOL MB_PORT_ISR_ATTR xMBMasterRequestIsBroadcast( void )
/* The master request is broadcast? */ /* The master request is broadcast? */
void vMBMasterRequestSetType( BOOL xIsBroadcast ) void vMBMasterRequestSetType( BOOL xIsBroadcast )
{ {
xFrameIsBroadcast = xIsBroadcast; atomic_store(&(xFrameIsBroadcast), xIsBroadcast);
} }
// Get Modbus Master communication mode. // Get Modbus Master communication mode.

View File

@ -252,7 +252,9 @@ xMBMasterRTUReceiveFSM( void )
BOOL xStatus = FALSE; BOOL xStatus = FALSE;
UCHAR ucByte; UCHAR ucByte;
assert(( eSndState == STATE_M_TX_IDLE ) || ( eSndState == STATE_M_TX_XFWR )); if ( ( eSndState != STATE_M_TX_IDLE ) && ( eSndState != STATE_M_TX_XFWR ) ) {
return FALSE;
}
/* Always read the character. */ /* Always read the character. */
xStatus = xMBMasterPortSerialGetByte( ( CHAR * ) & ucByte ); xStatus = xMBMasterPortSerialGetByte( ( CHAR * ) & ucByte );
@ -328,7 +330,9 @@ xMBMasterRTUTransmitFSM( void )
BOOL xNeedPoll = TRUE; BOOL xNeedPoll = TRUE;
BOOL xFrameIsBroadcast = FALSE; BOOL xFrameIsBroadcast = FALSE;
assert( eRcvState == STATE_M_RX_IDLE ); if ( eRcvState != STATE_M_RX_IDLE ) {
return FALSE;
}
switch ( eSndState ) switch ( eSndState )
{ {

View File

@ -91,6 +91,10 @@
#define MB_TCP_SEND_TIMEOUT (pdMS_TO_TICKS(MB_TCP_SEND_TIMEOUT_MS)) #define MB_TCP_SEND_TIMEOUT (pdMS_TO_TICKS(MB_TCP_SEND_TIMEOUT_MS))
#define MB_TCP_PORT_MAX_CONN (CONFIG_FMB_TCP_PORT_MAX_CONN) #define MB_TCP_PORT_MAX_CONN (CONFIG_FMB_TCP_PORT_MAX_CONN)
// Set the API unlock time to maximum response time
// The actual release time will be dependent on the timer time
#define MB_MAX_RESPONSE_TIME_MS (5000)
#define MB_TCP_FRAME_LOG_BUFSIZE (256) #define MB_TCP_FRAME_LOG_BUFSIZE (256)
#define MB_PORT_HAS_CLOSE (1) // Define to explicitly close port on destroy #define MB_PORT_HAS_CLOSE (1) // Define to explicitly close port on destroy

View File

@ -44,14 +44,11 @@
#include "mb.h" #include "mb.h"
#include "mbport.h" #include "mbport.h"
#include "port.h" #include "port.h"
#include "sdkconfig.h" #include "mbconfig.h"
#include "port_serial_slave.h" #include "port_serial_slave.h"
/* ----------------------- Variables ----------------------------------------*/ /* ----------------------- Variables ----------------------------------------*/
static QueueHandle_t xQueueHdl; static QueueHandle_t xQueueHdl;
#define MB_EVENT_QUEUE_SIZE (6)
#define MB_EVENT_QUEUE_TIMEOUT (pdMS_TO_TICKS(CONFIG_FMB_EVENT_QUEUE_TIMEOUT))
/* ----------------------- Start implementation -----------------------------*/ /* ----------------------- Start implementation -----------------------------*/
BOOL BOOL
xMBPortEventInit( void ) xMBPortEventInit( void )

View File

@ -35,26 +35,24 @@
*/ */
/* ----------------------- Modbus includes ----------------------------------*/ /* ----------------------- Modbus includes ----------------------------------*/
#include "mb_m.h"
#include "mbport.h" #include <stdatomic.h>
#include "mbconfig.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/event_groups.h" #include "freertos/event_groups.h"
#include "freertos/semphr.h"
#include "mb_m.h"
#include "mbport.h"
#include "mbconfig.h"
#include "port.h" #include "port.h"
#include "mbport.h" #include "mbport.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED #if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED
/* ----------------------- Defines ------------------------------------------*/ /* ----------------------- Defines ------------------------------------------*/
// Event bit mask for xMBMasterPortEventGet()
#define MB_EVENT_POLL_MASK (EventBits_t)( EV_MASTER_READY | \
EV_MASTER_FRAME_RECEIVED | \
EV_MASTER_EXECUTE | \
EV_MASTER_FRAME_SENT | \
EV_MASTER_FRAME_TRANSMIT | \
EV_MASTER_ERROR_PROCESS )
// Event bit mask for eMBMasterWaitRequestFinish() // Event bit mask for eMBMasterWaitRequestFinish()
#define MB_EVENT_REQ_MASK (EventBits_t)( EV_MASTER_PROCESS_SUCCESS | \ #define MB_EVENT_REQ_MASK (EventBits_t)( EV_MASTER_PROCESS_SUCCESS | \
@ -62,12 +60,13 @@
EV_MASTER_ERROR_RECEIVE_DATA | \ EV_MASTER_ERROR_RECEIVE_DATA | \
EV_MASTER_ERROR_EXECUTE_FUNCTION ) EV_MASTER_ERROR_EXECUTE_FUNCTION )
#define MB_EVENT_RESOURCE (EventBits_t)( 0x0080 )
/* ----------------------- Variables ----------------------------------------*/ /* ----------------------- Variables ----------------------------------------*/
static EventGroupHandle_t xResourceMasterHdl; static SemaphoreHandle_t xResourceMasterHdl;
static EventGroupHandle_t xEventGroupMasterHdl; static EventGroupHandle_t xEventGroupMasterHdl;
static EventGroupHandle_t xEventGroupMasterConfirmHdl; static EventGroupHandle_t xEventGroupMasterConfirmHdl;
static QueueHandle_t xQueueMasterHdl;
static uint64_t xTransactionID = 0;
/* ----------------------- Start implementation -----------------------------*/ /* ----------------------- Start implementation -----------------------------*/
@ -78,45 +77,60 @@ xMBMasterPortEventInit( void )
xEventGroupMasterConfirmHdl = xEventGroupCreate(); xEventGroupMasterConfirmHdl = xEventGroupCreate();
MB_PORT_CHECK((xEventGroupMasterHdl != NULL) && (xEventGroupMasterConfirmHdl != NULL), MB_PORT_CHECK((xEventGroupMasterHdl != NULL) && (xEventGroupMasterConfirmHdl != NULL),
FALSE, "mb stack event group creation error."); FALSE, "mb stack event group creation error.");
xQueueMasterHdl = xQueueCreate(MB_EVENT_QUEUE_SIZE, sizeof(xMBMasterEventType));
MB_PORT_CHECK(xQueueMasterHdl, FALSE, "mb stack event group creation error.");
vQueueAddToRegistry(xQueueMasterHdl, "MbMasterPortEventQueue");
xTransactionID = 0;
return TRUE; return TRUE;
} }
BOOL MB_PORT_ISR_ATTR BOOL MB_PORT_ISR_ATTR
xMBMasterPortEventPost( eMBMasterEventType eEvent ) xMBMasterPortEventPost( eMBMasterEventEnum eEvent)
{ {
BOOL bStatus = FALSE; BaseType_t xStatus, xHigherPriorityTaskWoken = pdFALSE;
eMBMasterEventType eTempEvent = eEvent; assert(xQueueMasterHdl != NULL);
xMBMasterEventType xEvent;
xEvent.xPostTimestamp = esp_timer_get_time();
if (eEvent & EV_MASTER_TRANS_START) {
atomic_store(&(xTransactionID), xEvent.xPostTimestamp);
}
xEvent.eEvent = (eEvent & ~EV_MASTER_TRANS_START);
if( (BOOL)xPortInIsrContext() == TRUE ) if( (BOOL)xPortInIsrContext() == TRUE ) {
{ xStatus = xQueueSendFromISR(xQueueMasterHdl, (const void*)&xEvent, &xHigherPriorityTaskWoken);
BaseType_t xHigherPriorityTaskWoken = pdFALSE; if ( xHigherPriorityTaskWoken ) {
BaseType_t xResult = xEventGroupSetBitsFromISR( xEventGroupMasterHdl, portYIELD_FROM_ISR();
(EventBits_t) eTempEvent,
&xHigherPriorityTaskWoken );
// Was the message posted successfully?
if( xResult == pdPASS ) {
// If xHigherPriorityTaskWoken is now set to pdTRUE
// then a context switch should be requested.
if (xHigherPriorityTaskWoken) portYIELD_FROM_ISR();
bStatus = TRUE;
} else {
bStatus = FALSE;
} }
if (xStatus != pdTRUE) {
ESP_EARLY_LOGV(MB_PORT_TAG, "%s: Post message failure = %d.", __func__, xStatus);
return FALSE;
}
} else {
xStatus = xQueueSend(xQueueMasterHdl, (const void*)&xEvent, MB_EVENT_QUEUE_TIMEOUT);
MB_PORT_CHECK((xStatus == pdTRUE), FALSE, "%s: Post message failure.", __func__);
} }
else return TRUE;
{
// Set event bits if the function is called from task
// The return result is not checked here because
// It might be that event bit was cleared automatically as a
// task that was waiting for the bit was removed from the Blocked state.
(void) xEventGroupSetBits( xEventGroupMasterHdl, (EventBits_t)eTempEvent );
bStatus = TRUE;
}
return bStatus;
} }
eMBMasterEventType BOOL
xMBMasterPortFsmWaitConfirmation( eMBMasterEventType eEventMask, ULONG ulTimeout) xMBMasterPortEventGet(xMBMasterEventType *peEvent)
{
assert(xQueueMasterHdl != NULL);
BOOL xEventHappened = FALSE;
if (xQueueReceive(xQueueMasterHdl, peEvent, portMAX_DELAY) == pdTRUE) {
peEvent->xTransactionId = atomic_load(&xTransactionID);
// Set event bits in confirmation group (for synchronization with port task)
xEventGroupSetBits(xEventGroupMasterConfirmHdl, peEvent->eEvent);
peEvent->xGetTimestamp = esp_timer_get_time();
xEventHappened = TRUE;
}
return xEventHappened;
}
eMBMasterEventEnum
xMBMasterPortFsmWaitConfirmation( eMBMasterEventEnum eEventMask, ULONG ulTimeout)
{ {
EventBits_t uxBits; EventBits_t uxBits;
uxBits = xEventGroupWaitBits( xEventGroupMasterConfirmHdl, // The event group being tested. uxBits = xEventGroupWaitBits( xEventGroupMasterConfirmHdl, // The event group being tested.
@ -128,38 +142,19 @@ xMBMasterPortFsmWaitConfirmation( eMBMasterEventType eEventMask, ULONG ulTimeout
// Clear confirmation events that where set in the mask // Clear confirmation events that where set in the mask
xEventGroupClearBits( xEventGroupMasterConfirmHdl, (uxBits & eEventMask) ); xEventGroupClearBits( xEventGroupMasterConfirmHdl, (uxBits & eEventMask) );
} }
return (eMBMasterEventType)(uxBits & eEventMask); return (eMBMasterEventEnum)(uxBits & eEventMask);
} }
BOOL uint64_t xMBMasterPortGetTransactionId( )
xMBMasterPortEventGet( eMBMasterEventType* eEvent )
{ {
EventBits_t uxBits; return atomic_load(&xTransactionID);
BOOL xEventHappened = FALSE;
uxBits = xEventGroupWaitBits( xEventGroupMasterHdl, // The event group being tested.
MB_EVENT_POLL_MASK, // The bits within the event group to wait for.
pdTRUE, // Masked bits should be cleared before returning.
pdFALSE, // Don't wait for both bits, either bit will do.
portMAX_DELAY); // Wait forever for either bit to be set.
// Check if poll event is correct
if (MB_PORT_CHECK_EVENT(uxBits, MB_EVENT_POLL_MASK)) {
*eEvent = (eMBMasterEventType)(uxBits & MB_EVENT_POLL_MASK);
// Set event bits in confirmation group (for synchronization with port task)
xEventGroupSetBits( xEventGroupMasterConfirmHdl, *eEvent );
xEventHappened = TRUE;
} else {
ESP_LOGE(MB_PORT_TAG,"%s: Incorrect event triggered = %u.", __func__, (unsigned)uxBits);
*eEvent = (eMBMasterEventType)uxBits;
xEventHappened = FALSE;
}
return xEventHappened;
} }
// This function is initialize the OS resource for modbus master. // This function is initialize the OS resource for modbus master.
void vMBMasterOsResInit( void ) void vMBMasterOsResInit( void )
{ {
xResourceMasterHdl = xEventGroupCreate(); xResourceMasterHdl = xSemaphoreCreateBinary();
MB_PORT_CHECK((xResourceMasterHdl != NULL), ; , "Resource create error."); MB_PORT_CHECK((xResourceMasterHdl != NULL), ; , "%s: Resource create error.", __func__);
} }
/** /**
@ -172,14 +167,10 @@ void vMBMasterOsResInit( void )
*/ */
BOOL xMBMasterRunResTake( LONG lTimeOut ) BOOL xMBMasterRunResTake( LONG lTimeOut )
{ {
EventBits_t uxBits; BaseType_t xStatus = pdTRUE;
uxBits = xEventGroupWaitBits( xResourceMasterHdl, // The event group being tested. xStatus = xSemaphoreTake( xResourceMasterHdl, lTimeOut );
MB_EVENT_RESOURCE, // The bits within the event group to wait for. MB_PORT_CHECK((xStatus == pdTRUE), FALSE , "%s: Resource take failure.", __func__);
pdTRUE, // Masked bits should be cleared before returning. ESP_LOGD(MB_PORT_TAG,"%s:Take MB resource (%lu ticks).", __func__, lTimeOut);
pdFALSE, // Don't wait for both bits, either bit will do.
lTimeOut); // Resource wait timeout.
MB_PORT_CHECK((uxBits == MB_EVENT_RESOURCE), FALSE , "Take resource failure.");
ESP_LOGD(MB_PORT_TAG,"%s:Take resource (%" PRIx32 ") (%" PRIu32 " ticks).", __func__, (uint32_t)uxBits, (uint32_t)lTimeOut);
return TRUE; return TRUE;
} }
@ -189,11 +180,10 @@ BOOL xMBMasterRunResTake( LONG lTimeOut )
*/ */
void vMBMasterRunResRelease( void ) void vMBMasterRunResRelease( void )
{ {
EventBits_t uxBits = xEventGroupSetBits( xResourceMasterHdl, MB_EVENT_RESOURCE ); BaseType_t xStatus = pdFALSE;
if (uxBits != MB_EVENT_RESOURCE) { xStatus = xSemaphoreGive( xResourceMasterHdl );
// The returned resource mask may be = 0, if the task waiting for it is unblocked. if (xStatus != pdTRUE) {
// This is not an error but expected behavior. ESP_LOGD(MB_PORT_TAG,"%s: Release resource fail.", __func__);
ESP_LOGD(MB_PORT_TAG,"%s: Release resource (%" PRIx32 ") fail.", __func__, (uint32_t)uxBits);
} }
} }
@ -208,8 +198,7 @@ void vMBMasterRunResRelease( void )
*/ */
void vMBMasterErrorCBRespondTimeout(UCHAR ucDestAddress, const UCHAR* pucPDUData, USHORT ucPDULength) void vMBMasterErrorCBRespondTimeout(UCHAR ucDestAddress, const UCHAR* pucPDUData, USHORT ucPDULength)
{ {
BOOL ret = xMBMasterPortEventPost(EV_MASTER_ERROR_RESPOND_TIMEOUT); (void)xEventGroupSetBits( xEventGroupMasterHdl, EV_MASTER_ERROR_RESPOND_TIMEOUT );
MB_PORT_CHECK((ret == TRUE), ; , "%s: Post event 'EV_MASTER_ERROR_RESPOND_TIMEOUT' failed!", __func__);
ESP_LOGD(MB_PORT_TAG,"%s:Callback respond timeout.", __func__); ESP_LOGD(MB_PORT_TAG,"%s:Callback respond timeout.", __func__);
} }
@ -223,8 +212,7 @@ void vMBMasterErrorCBRespondTimeout(UCHAR ucDestAddress, const UCHAR* pucPDUData
*/ */
void vMBMasterErrorCBReceiveData(UCHAR ucDestAddress, const UCHAR* pucPDUData, USHORT ucPDULength) void vMBMasterErrorCBReceiveData(UCHAR ucDestAddress, const UCHAR* pucPDUData, USHORT ucPDULength)
{ {
BOOL ret = xMBMasterPortEventPost(EV_MASTER_ERROR_RECEIVE_DATA); (void)xEventGroupSetBits( xEventGroupMasterHdl, EV_MASTER_ERROR_RECEIVE_DATA );
MB_PORT_CHECK((ret == TRUE), ; , "%s: Post event 'EV_MASTER_ERROR_RECEIVE_DATA' failed!", __func__);
ESP_LOGD(MB_PORT_TAG,"%s:Callback receive data timeout failure.", __func__); ESP_LOGD(MB_PORT_TAG,"%s:Callback receive data timeout failure.", __func__);
ESP_LOG_BUFFER_HEX_LEVEL("Err rcv buf", (void *)pucPDUData, (USHORT)ucPDULength, ESP_LOG_DEBUG); ESP_LOG_BUFFER_HEX_LEVEL("Err rcv buf", (void *)pucPDUData, (USHORT)ucPDULength, ESP_LOG_DEBUG);
} }
@ -241,8 +229,7 @@ void vMBMasterErrorCBReceiveData(UCHAR ucDestAddress, const UCHAR* pucPDUData, U
*/ */
void vMBMasterErrorCBExecuteFunction(UCHAR ucDestAddress, const UCHAR* pucPDUData, USHORT ucPDULength) void vMBMasterErrorCBExecuteFunction(UCHAR ucDestAddress, const UCHAR* pucPDUData, USHORT ucPDULength)
{ {
BOOL ret = xMBMasterPortEventPost(EV_MASTER_ERROR_EXECUTE_FUNCTION); xEventGroupSetBits( xEventGroupMasterHdl, EV_MASTER_ERROR_EXECUTE_FUNCTION );
MB_PORT_CHECK((ret == TRUE), ; , "%s: Post event 'EV_MASTER_ERROR_EXECUTE_FUNCTION' failed!", __func__);
ESP_LOGD(MB_PORT_TAG,"%s:Callback execute data handler failure.", __func__); ESP_LOGD(MB_PORT_TAG,"%s:Callback execute data handler failure.", __func__);
ESP_LOG_BUFFER_HEX_LEVEL("Exec func buf", (void*)pucPDUData, (USHORT)ucPDULength, ESP_LOG_DEBUG); ESP_LOG_BUFFER_HEX_LEVEL("Exec func buf", (void*)pucPDUData, (USHORT)ucPDULength, ESP_LOG_DEBUG);
} }
@ -252,13 +239,9 @@ void vMBMasterErrorCBExecuteFunction(UCHAR ucDestAddress, const UCHAR* pucPDUDat
* @note There functions will block modbus master poll while execute OS waiting. * @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. * So,for real-time of system. Do not execute too much waiting process.
*/ */
void vMBMasterCBRequestSuccess( void ) { void vMBMasterCBRequestSuccess( void )
/** {
* @note This code is use OS's event mechanism for modbus master protocol stack. (void)xEventGroupSetBits( xEventGroupMasterHdl, EV_MASTER_PROCESS_SUCCESS );
* If you don't use OS, you can change it.
*/
BOOL ret = xMBMasterPortEventPost(EV_MASTER_PROCESS_SUCCESS);
MB_PORT_CHECK((ret == TRUE), ; , "%s: Post event 'EV_MASTER_PROCESS_SUCCESS' failed!", __func__);
ESP_LOGD(MB_PORT_TAG,"%s: Callback request success.", __func__); ESP_LOGD(MB_PORT_TAG,"%s: Callback request success.", __func__);
} }
@ -273,14 +256,14 @@ void vMBMasterCBRequestSuccess( void ) {
*/ */
eMBMasterReqErrCode eMBMasterWaitRequestFinish( void ) { eMBMasterReqErrCode eMBMasterWaitRequestFinish( void ) {
eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR;
eMBMasterEventType xRecvedEvent; eMBMasterEventEnum xRecvedEvent;
EventBits_t uxBits = xEventGroupWaitBits( xEventGroupMasterHdl, // The event group being tested. EventBits_t uxBits = xEventGroupWaitBits( xEventGroupMasterHdl, // The event group being tested.
MB_EVENT_REQ_MASK, // The bits within the event group to wait for. MB_EVENT_REQ_MASK, // The bits within the event group to wait for.
pdTRUE, // Masked bits should be cleared before returning. pdTRUE, // Masked bits should be cleared before returning.
pdFALSE, // Don't wait for both bits, either bit will do. pdFALSE, // Don't wait for both bits, either bit will do.
portMAX_DELAY ); // Wait forever for either bit to be set. portMAX_DELAY ); // Wait forever for either bit to be set.
xRecvedEvent = (eMBMasterEventType)(uxBits); xRecvedEvent = (eMBMasterEventEnum)(uxBits);
if (xRecvedEvent) { if (xRecvedEvent) {
ESP_LOGD(MB_PORT_TAG,"%s: returned event = 0x%x", __func__, (int)xRecvedEvent); ESP_LOGD(MB_PORT_TAG,"%s: returned event = 0x%x", __func__, (int)xRecvedEvent);
if (!(xRecvedEvent & MB_EVENT_REQ_MASK)) { if (!(xRecvedEvent & MB_EVENT_REQ_MASK)) {
@ -298,7 +281,7 @@ eMBMasterReqErrCode eMBMasterWaitRequestFinish( void ) {
eErrStatus = MB_MRE_EXE_FUN; eErrStatus = MB_MRE_EXE_FUN;
} }
} else { } else {
ESP_LOGE(MB_PORT_TAG,"%s: Incorrect event or timeout xRecvedEvent = 0x%" PRIx32 "", __func__, (uint32_t)uxBits); ESP_LOGE(MB_PORT_TAG,"%s: Incorrect event or timeout xRecvedEvent = 0x%x", __func__, (int)uxBits);
// https://github.com/espressif/esp-idf/issues/5275 // https://github.com/espressif/esp-idf/issues/5275
// if a no event is received, that means vMBMasterPortEventClose() // if a no event is received, that means vMBMasterPortEventClose()
// has been closed, so event group has been deleted by FreeRTOS, which // has been closed, so event group has been deleted by FreeRTOS, which
@ -311,9 +294,22 @@ eMBMasterReqErrCode eMBMasterWaitRequestFinish( void ) {
void vMBMasterPortEventClose(void) void vMBMasterPortEventClose(void)
{ {
vEventGroupDelete(xEventGroupMasterHdl); if (xQueueMasterHdl) {
vEventGroupDelete(xEventGroupMasterConfirmHdl); vEventGroupDelete(xEventGroupMasterHdl);
vEventGroupDelete(xResourceMasterHdl); xQueueMasterHdl = NULL;
}
if (xQueueMasterHdl) {
vQueueDelete(xQueueMasterHdl);
xQueueMasterHdl = NULL;
}
if (xEventGroupMasterConfirmHdl) {
vEventGroupDelete(xEventGroupMasterConfirmHdl);
xEventGroupMasterConfirmHdl = NULL;
}
if (xResourceMasterHdl) {
vSemaphoreDelete(xResourceMasterHdl);
xResourceMasterHdl = NULL;
}
} }
#endif #endif

View File

@ -27,8 +27,8 @@
extern BOOL xMBMasterPortSerialTxPoll(void); extern BOOL xMBMasterPortSerialTxPoll(void);
/*-----------------------Master mode use these variables----------------------*/ /*-----------------------Master mode use these variables----------------------*/
#define MB_RESPONSE_TICS pdMS_TO_TICKS(CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND + 10) // Actual wait time depends on the response timer
#define MB_SERIAL_API_RESP_TICS (pdMS_TO_TICKS(MB_MAX_RESPONSE_TIME_MS))
static mb_master_interface_t* mbm_interface_ptr = NULL; static mb_master_interface_t* mbm_interface_ptr = NULL;
static const char *TAG = "MB_CONTROLLER_MASTER"; static const char *TAG = "MB_CONTROLLER_MASTER";
@ -176,7 +176,7 @@ static esp_err_t mbc_serial_master_send_request(mb_param_request_t* request, voi
eMBMasterReqErrCode mb_error = MB_MRE_MASTER_BUSY; eMBMasterReqErrCode mb_error = MB_MRE_MASTER_BUSY;
esp_err_t error = ESP_FAIL; esp_err_t error = ESP_FAIL;
if (xMBMasterRunResTake(MB_RESPONSE_TICS)) { if (xMBMasterRunResTake(MB_SERIAL_API_RESP_TICS)) {
uint8_t mb_slave_addr = request->slave_addr; uint8_t mb_slave_addr = request->slave_addr;
uint8_t mb_command = request->command; uint8_t mb_command = request->command;
@ -194,43 +194,43 @@ static esp_err_t mbc_serial_master_send_request(mb_param_request_t* request, voi
{ {
case MB_FUNC_READ_COILS: case MB_FUNC_READ_COILS:
mb_error = eMBMasterReqReadCoils((UCHAR)mb_slave_addr, (USHORT)mb_offset, mb_error = eMBMasterReqReadCoils((UCHAR)mb_slave_addr, (USHORT)mb_offset,
(USHORT)mb_size , (LONG)MB_RESPONSE_TICS ); (USHORT)mb_size , (LONG)MB_SERIAL_API_RESP_TICS );
break; break;
case MB_FUNC_WRITE_SINGLE_COIL: case MB_FUNC_WRITE_SINGLE_COIL:
mb_error = eMBMasterReqWriteCoil((UCHAR)mb_slave_addr, (USHORT)mb_offset, mb_error = eMBMasterReqWriteCoil((UCHAR)mb_slave_addr, (USHORT)mb_offset,
*(USHORT*)data_ptr, (LONG)MB_RESPONSE_TICS ); *(USHORT*)data_ptr, (LONG)MB_SERIAL_API_RESP_TICS );
break; break;
case MB_FUNC_WRITE_MULTIPLE_COILS: case MB_FUNC_WRITE_MULTIPLE_COILS:
mb_error = eMBMasterReqWriteMultipleCoils((UCHAR)mb_slave_addr, (USHORT)mb_offset, mb_error = eMBMasterReqWriteMultipleCoils((UCHAR)mb_slave_addr, (USHORT)mb_offset,
(USHORT)mb_size, (UCHAR*)data_ptr, (LONG)MB_RESPONSE_TICS); (USHORT)mb_size, (UCHAR*)data_ptr, (LONG)MB_SERIAL_API_RESP_TICS);
break; break;
case MB_FUNC_READ_DISCRETE_INPUTS: case MB_FUNC_READ_DISCRETE_INPUTS:
mb_error = eMBMasterReqReadDiscreteInputs((UCHAR)mb_slave_addr, (USHORT)mb_offset, mb_error = eMBMasterReqReadDiscreteInputs((UCHAR)mb_slave_addr, (USHORT)mb_offset,
(USHORT)mb_size, (LONG)MB_RESPONSE_TICS ); (USHORT)mb_size, (LONG)MB_SERIAL_API_RESP_TICS );
break; break;
case MB_FUNC_READ_HOLDING_REGISTER: case MB_FUNC_READ_HOLDING_REGISTER:
mb_error = eMBMasterReqReadHoldingRegister((UCHAR)mb_slave_addr, (USHORT)mb_offset, mb_error = eMBMasterReqReadHoldingRegister((UCHAR)mb_slave_addr, (USHORT)mb_offset,
(USHORT)mb_size, (LONG)MB_RESPONSE_TICS ); (USHORT)mb_size, (LONG)MB_SERIAL_API_RESP_TICS );
break; break;
case MB_FUNC_WRITE_REGISTER: case MB_FUNC_WRITE_REGISTER:
mb_error = eMBMasterReqWriteHoldingRegister( (UCHAR)mb_slave_addr, (USHORT)mb_offset, mb_error = eMBMasterReqWriteHoldingRegister( (UCHAR)mb_slave_addr, (USHORT)mb_offset,
*(USHORT*)data_ptr, (LONG)MB_RESPONSE_TICS ); *(USHORT*)data_ptr, (LONG)MB_SERIAL_API_RESP_TICS );
break; break;
case MB_FUNC_WRITE_MULTIPLE_REGISTERS: case MB_FUNC_WRITE_MULTIPLE_REGISTERS:
mb_error = eMBMasterReqWriteMultipleHoldingRegister( (UCHAR)mb_slave_addr, mb_error = eMBMasterReqWriteMultipleHoldingRegister( (UCHAR)mb_slave_addr,
(USHORT)mb_offset, (USHORT)mb_size, (USHORT)mb_offset, (USHORT)mb_size,
(USHORT*)data_ptr, (LONG)MB_RESPONSE_TICS ); (USHORT*)data_ptr, (LONG)MB_SERIAL_API_RESP_TICS );
break; break;
case MB_FUNC_READWRITE_MULTIPLE_REGISTERS: case MB_FUNC_READWRITE_MULTIPLE_REGISTERS:
mb_error = eMBMasterReqReadWriteMultipleHoldingRegister( (UCHAR)mb_slave_addr, (USHORT)mb_offset, mb_error = eMBMasterReqReadWriteMultipleHoldingRegister( (UCHAR)mb_slave_addr, (USHORT)mb_offset,
(USHORT)mb_size, (USHORT*)data_ptr, (USHORT)mb_size, (USHORT*)data_ptr,
(USHORT)mb_offset, (USHORT)mb_size, (USHORT)mb_offset, (USHORT)mb_size,
(LONG)MB_RESPONSE_TICS ); (LONG)MB_SERIAL_API_RESP_TICS );
break; break;
case MB_FUNC_READ_INPUT_REGISTER: case MB_FUNC_READ_INPUT_REGISTER:
mb_error = eMBMasterReqReadInputRegister( (UCHAR)mb_slave_addr, (USHORT)mb_offset, mb_error = eMBMasterReqReadInputRegister( (UCHAR)mb_slave_addr, (USHORT)mb_offset,
(USHORT)mb_size, (LONG) MB_RESPONSE_TICS ); (USHORT)mb_size, (LONG) MB_SERIAL_API_RESP_TICS );
break; break;
default: default:
ESP_LOGE(TAG, "%s: Incorrect function in request (%u) ", __FUNCTION__, (unsigned)mb_command); ESP_LOGE(TAG, "%s: Incorrect function in request (%u) ", __FUNCTION__, (unsigned)mb_command);

View File

@ -29,9 +29,10 @@
/*-----------------------Master mode use these variables----------------------*/ /*-----------------------Master mode use these variables----------------------*/
// The response time is average processing time + data transmission #define MB_TCP_CONNECTION_TOUT (pdMS_TO_TICKS(CONFIG_FMB_TCP_CONNECTION_TOUT_SEC * 1000))
#define MB_RESPONSE_TIMEOUT pdMS_TO_TICKS(CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND)
#define MB_TCP_CONNECTION_TOUT pdMS_TO_TICKS(CONFIG_FMB_TCP_CONNECTION_TOUT_SEC * 1000) // Actual wait time depends on the response timer
#define MB_TCP_API_RESP_TICS (pdMS_TO_TICKS(MB_MAX_RESPONSE_TIME_MS))
static mb_master_interface_t* mbm_interface_ptr = NULL; static mb_master_interface_t* mbm_interface_ptr = NULL;
static const char *TAG = "MB_CONTROLLER_MASTER"; static const char *TAG = "MB_CONTROLLER_MASTER";
@ -257,7 +258,7 @@ static esp_err_t mbc_tcp_master_send_request(mb_param_request_t* request, void*
eMBMasterReqErrCode mb_error = MB_MRE_MASTER_BUSY; eMBMasterReqErrCode mb_error = MB_MRE_MASTER_BUSY;
esp_err_t error = ESP_FAIL; esp_err_t error = ESP_FAIL;
if (xMBMasterRunResTake(MB_RESPONSE_TIMEOUT)) { if (xMBMasterRunResTake(MB_TCP_API_RESP_TICS)) {
uint8_t mb_slave_addr = request->slave_addr; uint8_t mb_slave_addr = request->slave_addr;
uint8_t mb_command = request->command; uint8_t mb_command = request->command;
@ -275,44 +276,44 @@ static esp_err_t mbc_tcp_master_send_request(mb_param_request_t* request, void*
{ {
case MB_FUNC_READ_COILS: case MB_FUNC_READ_COILS:
mb_error = eMBMasterReqReadCoils((UCHAR)mb_slave_addr, (USHORT)mb_offset, mb_error = eMBMasterReqReadCoils((UCHAR)mb_slave_addr, (USHORT)mb_offset,
(USHORT)mb_size, (LONG)MB_RESPONSE_TIMEOUT); (USHORT)mb_size, (LONG)MB_TCP_API_RESP_TICS);
break; break;
case MB_FUNC_WRITE_SINGLE_COIL: case MB_FUNC_WRITE_SINGLE_COIL:
mb_error = eMBMasterReqWriteCoil((UCHAR)mb_slave_addr, (USHORT)mb_offset, mb_error = eMBMasterReqWriteCoil((UCHAR)mb_slave_addr, (USHORT)mb_offset,
*(USHORT *)data_ptr, (LONG)MB_RESPONSE_TIMEOUT); *(USHORT *)data_ptr, (LONG)MB_TCP_API_RESP_TICS);
break; break;
case MB_FUNC_WRITE_MULTIPLE_COILS: case MB_FUNC_WRITE_MULTIPLE_COILS:
mb_error = eMBMasterReqWriteMultipleCoils((UCHAR)mb_slave_addr, (USHORT)mb_offset, mb_error = eMBMasterReqWriteMultipleCoils((UCHAR)mb_slave_addr, (USHORT)mb_offset,
(USHORT)mb_size, (UCHAR *)data_ptr, (USHORT)mb_size, (UCHAR *)data_ptr,
(LONG)MB_RESPONSE_TIMEOUT); (LONG)MB_TCP_API_RESP_TICS);
break; break;
case MB_FUNC_READ_DISCRETE_INPUTS: case MB_FUNC_READ_DISCRETE_INPUTS:
mb_error = eMBMasterReqReadDiscreteInputs((UCHAR)mb_slave_addr, (USHORT)mb_offset, mb_error = eMBMasterReqReadDiscreteInputs((UCHAR)mb_slave_addr, (USHORT)mb_offset,
(USHORT)mb_size, (LONG)MB_RESPONSE_TIMEOUT); (USHORT)mb_size, (LONG)MB_TCP_API_RESP_TICS);
break; break;
case MB_FUNC_READ_HOLDING_REGISTER: case MB_FUNC_READ_HOLDING_REGISTER:
mb_error = eMBMasterReqReadHoldingRegister((UCHAR)mb_slave_addr, (USHORT)mb_offset, mb_error = eMBMasterReqReadHoldingRegister((UCHAR)mb_slave_addr, (USHORT)mb_offset,
(USHORT)mb_size, (LONG)MB_RESPONSE_TIMEOUT); (USHORT)mb_size, (LONG)MB_TCP_API_RESP_TICS);
break; break;
case MB_FUNC_WRITE_REGISTER: case MB_FUNC_WRITE_REGISTER:
mb_error = eMBMasterReqWriteHoldingRegister((UCHAR)mb_slave_addr, (USHORT)mb_offset, mb_error = eMBMasterReqWriteHoldingRegister((UCHAR)mb_slave_addr, (USHORT)mb_offset,
*(USHORT *)data_ptr, (LONG)MB_RESPONSE_TIMEOUT); *(USHORT *)data_ptr, (LONG)MB_TCP_API_RESP_TICS);
break; break;
case MB_FUNC_WRITE_MULTIPLE_REGISTERS: case MB_FUNC_WRITE_MULTIPLE_REGISTERS:
mb_error = eMBMasterReqWriteMultipleHoldingRegister((UCHAR)mb_slave_addr, mb_error = eMBMasterReqWriteMultipleHoldingRegister((UCHAR)mb_slave_addr,
(USHORT)mb_offset, (USHORT)mb_size, (USHORT)mb_offset, (USHORT)mb_size,
(USHORT *)data_ptr, (LONG)MB_RESPONSE_TIMEOUT); (USHORT *)data_ptr, (LONG)MB_TCP_API_RESP_TICS);
break; break;
case MB_FUNC_READWRITE_MULTIPLE_REGISTERS: case MB_FUNC_READWRITE_MULTIPLE_REGISTERS:
mb_error = eMBMasterReqReadWriteMultipleHoldingRegister((UCHAR)mb_slave_addr, (USHORT)mb_offset, mb_error = eMBMasterReqReadWriteMultipleHoldingRegister((UCHAR)mb_slave_addr, (USHORT)mb_offset,
(USHORT)mb_size, (USHORT *)data_ptr, (USHORT)mb_size, (USHORT *)data_ptr,
(USHORT)mb_offset, (USHORT)mb_size, (USHORT)mb_offset, (USHORT)mb_size,
(LONG)MB_RESPONSE_TIMEOUT); (LONG)MB_TCP_API_RESP_TICS);
break; break;
case MB_FUNC_READ_INPUT_REGISTER: case MB_FUNC_READ_INPUT_REGISTER:
mb_error = eMBMasterReqReadInputRegister((UCHAR)mb_slave_addr, (USHORT)mb_offset, mb_error = eMBMasterReqReadInputRegister((UCHAR)mb_slave_addr, (USHORT)mb_offset,
(USHORT)mb_size, (LONG)MB_RESPONSE_TIMEOUT); (USHORT)mb_size, (LONG)MB_TCP_API_RESP_TICS);
break; break;
default: default:
ESP_LOGE(TAG, "%s: Incorrect function in request (%u) ", __FUNCTION__, (unsigned)mb_command); ESP_LOGE(TAG, "%s: Incorrect function in request (%u) ", __FUNCTION__, (unsigned)mb_command);
@ -507,7 +508,6 @@ static esp_err_t mbc_tcp_master_get_parameter(uint16_t cid, char* name, uint8_t*
} else { } else {
ESP_LOGD(TAG, "%s: Bad response to get cid(%u) = %s", ESP_LOGD(TAG, "%s: Bad response to get cid(%u) = %s",
__FUNCTION__, (unsigned)reg_info.cid, (char*)esp_err_to_name(error)); __FUNCTION__, (unsigned)reg_info.cid, (char*)esp_err_to_name(error));
error = ESP_ERR_INVALID_RESPONSE;
} }
free(pdata); free(pdata);
// Set the type of parameter found in the table // Set the type of parameter found in the table

View File

@ -655,7 +655,7 @@ static int xMBTCPPortMasterCheckConnState(fd_set *pxFdSet)
return xCount; return xCount;
} }
static void xMBTCPPortMasterFsmSetError(eMBMasterErrorEventType xErrType, eMBMasterEventType xPostEvent) static void xMBTCPPortMasterFsmSetError(eMBMasterErrorEventType xErrType, eMBMasterEventEnum xPostEvent)
{ {
vMBMasterPortTimersDisable(); vMBMasterPortTimersDisable();
vMBMasterSetErrorType(xErrType); vMBMasterSetErrorType(xErrType);
@ -861,7 +861,7 @@ static void vMBTCPPortMasterTask(void *pvParameters)
} else if (xRet == ERR_BUF) { } else if (xRet == ERR_BUF) {
// After retries a response with incorrect TID received, process failure. // After retries a response with incorrect TID received, process failure.
xMBTCPPortMasterFsmSetError(EV_ERROR_RECEIVE_DATA, EV_MASTER_ERROR_PROCESS); xMBTCPPortMasterFsmSetError(EV_ERROR_RECEIVE_DATA, EV_MASTER_ERROR_PROCESS);
ESP_LOGW(TAG, MB_SLAVE_FMT(", frame error."), ESP_LOGD(TAG, MB_SLAVE_FMT(", frame error."),
(int)pxCurrInfo->xIndex, (int)pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); (int)pxCurrInfo->xIndex, (int)pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr);
} else { } else {
ESP_LOGE(TAG, MB_SLAVE_FMT(", critical error=%d."), ESP_LOGE(TAG, MB_SLAVE_FMT(", critical error=%d."),

View File

@ -1,8 +1,8 @@
version: "1.0.10" version: "1.0.11"
description: ESP-MODBUS is the official Modbus library for Espressif SoCs. description: ESP-MODBUS is the official Modbus library for Espressif SoCs.
url: https://github.com/espressif/esp-modbus url: https://github.com/espressif/esp-modbus
dependencies: dependencies:
idf: ">=4.1" idf: ">=4.3"
files: files:
exclude: exclude:
- "docs/**/*" - "docs/**/*"