mirror of
https://github.com/espressif/esp-modbus.git
synced 2026-08-03 20:24:09 +02:00
modbus master fix event loop and kconfig
This commit is contained in:
@@ -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 + 1] = usNCoils;
|
||||
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( );
|
||||
|
||||
}
|
||||
@@ -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 + 1] = usCoilData;
|
||||
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( );
|
||||
}
|
||||
return eErrStatus;
|
||||
@@ -327,7 +327,7 @@ eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr,
|
||||
*ucMBFrame++ = pucDataBuffer[usRegIndex++];
|
||||
}
|
||||
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( );
|
||||
}
|
||||
return eErrStatus;
|
||||
|
||||
@@ -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 + 1] = usNDiscreteIn;
|
||||
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( );
|
||||
}
|
||||
return eErrStatus;
|
||||
|
||||
@@ -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 + 1] = usRegData ;
|
||||
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( );
|
||||
}
|
||||
return eErrStatus;
|
||||
@@ -200,7 +200,7 @@ eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr,
|
||||
*ucMBFrame++ = pusDataBuffer[usRegIndex++] ;
|
||||
}
|
||||
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( );
|
||||
}
|
||||
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 + 1] = usNRegs;
|
||||
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( );
|
||||
}
|
||||
return eErrStatus;
|
||||
@@ -392,7 +392,7 @@ eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr,
|
||||
*ucMBFrame++ = pusDataBuffer[usRegIndex++] ;
|
||||
}
|
||||
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( );
|
||||
}
|
||||
return eErrStatus;
|
||||
|
||||
@@ -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 + 1] = usNRegs;
|
||||
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( );
|
||||
}
|
||||
return eErrStatus;
|
||||
|
||||
@@ -103,7 +103,7 @@ typedef enum
|
||||
MB_TMODE_T35, /*!< Master receive frame T3.5 timeout. */
|
||||
MB_TMODE_RESPOND_TIMEOUT, /*!< Master wait respond for slave. */
|
||||
MB_TMODE_CONVERT_DELAY /*!< Master sent broadcast ,then delay sometime.*/
|
||||
}eMBMasterTimerMode;
|
||||
} eMBMasterTimerMode;
|
||||
|
||||
/* ----------------------- Function prototypes ------------------------------*/
|
||||
/*! \ingroup modbus
|
||||
|
||||
@@ -99,6 +99,9 @@ PR_BEGIN_EXTERN_C
|
||||
#define MB_ASCII_BITS_PER_SYMB ( CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB )
|
||||
#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.
|
||||
*
|
||||
* The character timeout value is not fixed for Modbus ASCII and is therefore
|
||||
|
||||
@@ -70,17 +70,18 @@ typedef enum
|
||||
#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED
|
||||
typedef enum {
|
||||
EV_MASTER_NO_EVENT = 0x0000,
|
||||
EV_MASTER_READY = 0x0001, /*!< Startup finished. */
|
||||
EV_MASTER_FRAME_RECEIVED = 0x0002, /*!< Frame received. */
|
||||
EV_MASTER_EXECUTE = 0x0004, /*!< Execute function. */
|
||||
EV_MASTER_FRAME_SENT = 0x0008, /*!< Frame sent. */
|
||||
EV_MASTER_FRAME_TRANSMIT = 0x0010, /*!< Frame transmission. */
|
||||
EV_MASTER_ERROR_PROCESS = 0x0020, /*!< Frame error process. */
|
||||
EV_MASTER_PROCESS_SUCCESS = 0x0040, /*!< Request process success. */
|
||||
EV_MASTER_ERROR_RESPOND_TIMEOUT = 0x0080, /*!< Request respond timeout. */
|
||||
EV_MASTER_ERROR_RECEIVE_DATA = 0x0100, /*!< Request receive data error. */
|
||||
EV_MASTER_ERROR_EXECUTE_FUNCTION = 0x0200 /*!< Request execute function error. */
|
||||
} eMBMasterEventType;
|
||||
EV_MASTER_TRANS_START = 0x0001, /*!< Transaction start flag */
|
||||
EV_MASTER_READY = 0x0002, /*!< Startup finished. */
|
||||
EV_MASTER_FRAME_RECEIVED = 0x0004, /*!< Frame received. */
|
||||
EV_MASTER_EXECUTE = 0x0008, /*!< Execute function. */
|
||||
EV_MASTER_FRAME_SENT = 0x0010, /*!< Frame sent. */
|
||||
EV_MASTER_FRAME_TRANSMIT = 0x0020, /*!< Frame transmission. */
|
||||
EV_MASTER_ERROR_PROCESS = 0x0040, /*!< Frame error process. */
|
||||
EV_MASTER_PROCESS_SUCCESS = 0x0080, /*!< Request process success. */
|
||||
EV_MASTER_ERROR_RESPOND_TIMEOUT = 0x0100, /*!< Request respond timeout. */
|
||||
EV_MASTER_ERROR_RECEIVE_DATA = 0x0200, /*!< Request receive data error. */
|
||||
EV_MASTER_ERROR_EXECUTE_FUNCTION = 0x0400 /*!< Request execute function error. */
|
||||
} eMBMasterEventEnum;
|
||||
|
||||
typedef enum {
|
||||
EV_ERROR_INIT, /*!< No error, initial state. */
|
||||
@@ -89,6 +90,14 @@ typedef enum {
|
||||
EV_ERROR_EXECUTE_FUNCTION, /*!< Execute function error. */
|
||||
EV_ERROR_OK /*!< No error, processing completed. */
|
||||
} 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
|
||||
|
||||
/*! \ingroup modbus
|
||||
@@ -115,18 +124,21 @@ BOOL xMBPortEventGet( /*@out@ */ eMBEventType * eEvent );
|
||||
#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED
|
||||
BOOL xMBMasterPortEventInit( void );
|
||||
|
||||
BOOL xMBMasterPortEventPost( eMBMasterEventType eEvent );
|
||||
BOOL xMBMasterPortEventPost( eMBMasterEventEnum eEvent );
|
||||
|
||||
BOOL xMBMasterPortEventGet( /*@out@ */ eMBMasterEventType * eEvent );
|
||||
BOOL xMBMasterPortEventGet( /*@out@ */ xMBMasterEventType * eEvent );
|
||||
|
||||
eMBMasterEventType
|
||||
xMBMasterPortFsmWaitConfirmation( eMBMasterEventType eEventMask, ULONG ulTimeout);
|
||||
eMBMasterEventEnum
|
||||
xMBMasterPortFsmWaitConfirmation( eMBMasterEventEnum eEventMask, ULONG ulTimeout);
|
||||
|
||||
void vMBMasterOsResInit( void );
|
||||
|
||||
BOOL xMBMasterRunResTake( LONG time );
|
||||
|
||||
void vMBMasterRunResRelease( void );
|
||||
|
||||
uint64_t xMBMasterPortGetTransactionId( void );
|
||||
|
||||
#endif // MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_MASTER_TCP_ENABLED
|
||||
/* ----------------------- Serial port functions ----------------------------*/
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ PR_BEGIN_EXTERN_C
|
||||
#define MB_FUNC_OTHER_REPORT_SLAVEID ( 17 )
|
||||
#define MB_FUNC_ERROR ( 128u )
|
||||
/* ----------------------- Type definitions ---------------------------------*/
|
||||
typedef enum
|
||||
typedef enum
|
||||
{
|
||||
MB_EX_NONE = 0x00,
|
||||
MB_EX_ILLEGAL_FUNCTION = 0x01,
|
||||
|
||||
+123
-122
@@ -36,8 +36,9 @@
|
||||
*/
|
||||
|
||||
/* ----------------------- System includes ----------------------------------*/
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include <stdatomic.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* ----------------------- Platform includes --------------------------------*/
|
||||
#include "port.h"
|
||||
@@ -316,171 +317,171 @@ eMBMasterPoll( void )
|
||||
static UCHAR ucFunctionCode;
|
||||
static USHORT usLength;
|
||||
static eMBException eException;
|
||||
static BOOL xTransactionIsActive = FALSE;
|
||||
static uint64_t xCurTransactionId = 0;
|
||||
int i;
|
||||
int j;
|
||||
eMBErrorCode eStatus = MB_ENOERR;
|
||||
eMBMasterEventType eEvent;
|
||||
xMBMasterEventType xEvent;
|
||||
eMBMasterErrorEventType errorType;
|
||||
|
||||
/* Check if the protocol stack is ready. */
|
||||
if( eMBState != STATE_ENABLED )
|
||||
{
|
||||
if( eMBState != STATE_ENABLED ) {
|
||||
return MB_EILLSTATE;
|
||||
}
|
||||
|
||||
/* Check if there is a event available. If not return control to caller.
|
||||
* Otherwise we will handle the event. */
|
||||
if ( xMBMasterPortEventGet( &eEvent ) == TRUE )
|
||||
{
|
||||
while( eEvent ) {
|
||||
if ( xMBMasterPortEventGet( &xEvent ) == TRUE ) {
|
||||
switch( xEvent.eEvent ) {
|
||||
// In some cases it is possible that more than one event set
|
||||
// together (even from one subset mask) than process them consistently
|
||||
if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_READY ) ) {
|
||||
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_READY", __func__);
|
||||
case EV_MASTER_READY:
|
||||
ESP_LOGD(MB_PORT_TAG, "%" PRIu64 ":EV_MASTER_READY", xEvent.xTransactionId);
|
||||
vMBMasterSetErrorType( EV_ERROR_INIT );
|
||||
vMBMasterRunResRelease( );
|
||||
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_READY );
|
||||
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_TRANSMIT ) ) {
|
||||
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_FRAME_TRANSMIT", __func__);
|
||||
break;
|
||||
case EV_MASTER_FRAME_TRANSMIT:
|
||||
ESP_LOGD(MB_PORT_TAG, "%" PRIu64 ":EV_MASTER_FRAME_TRANSMIT", xEvent.xTransactionId);
|
||||
/* Master is busy now. */
|
||||
vMBMasterGetPDUSndBuf( &ucMBSendFrame );
|
||||
ESP_LOG_BUFFER_HEX_LEVEL("POLL transmit buffer", (void*)ucMBSendFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG);
|
||||
eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBSendFrame, usMBMasterGetPDUSndLength() );
|
||||
if (eStatus != MB_ENOERR)
|
||||
{
|
||||
if (eStatus != MB_ENOERR) {
|
||||
vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
|
||||
( 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 );
|
||||
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_SENT ) ) {
|
||||
ESP_LOGD( MB_PORT_TAG, "%s:EV_MASTER_FRAME_SENT", __func__ );
|
||||
ESP_LOG_BUFFER_HEX_LEVEL("POLL sent buffer", (void*)ucMBSendFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG);
|
||||
xTransactionIsActive = TRUE;
|
||||
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_SENT );
|
||||
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_RECEIVED ) ) {
|
||||
if (xTransactionIsActive) {
|
||||
ESP_LOGD( MB_PORT_TAG, "%s:EV_MASTER_FRAME_RECEIVED", __func__ );
|
||||
eStatus = peMBMasterFrameReceiveCur( &ucRcvAddress, &ucMBRcvFrame, &usLength);
|
||||
xCurTransactionId = xEvent.xTransactionId;
|
||||
break;
|
||||
case EV_MASTER_FRAME_SENT:
|
||||
if (xCurTransactionId == xEvent.xTransactionId) {
|
||||
ESP_LOGD( MB_PORT_TAG, "%" PRIu64 ":EV_MASTER_FRAME_SENT", xEvent.xTransactionId );
|
||||
ESP_LOG_BUFFER_HEX_LEVEL("POLL sent buffer", (void*)ucMBSendFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG);
|
||||
}
|
||||
break;
|
||||
case EV_MASTER_FRAME_RECEIVED:
|
||||
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.");
|
||||
// Check if the frame is for us. If not ,send an error process event.
|
||||
if ( ( eStatus == MB_ENOERR ) && ( ( ucRcvAddress == ucMBMasterGetDestAddress() )
|
||||
|| ( ucRcvAddress == MB_TCP_PSEUDO_ADDRESS) ) ) {
|
||||
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_LOG_BUFFER_HEX_LEVEL("POLL receive buffer", (void*)ucMBRcvFrame, (unsigned)usLength, ESP_LOG_DEBUG);
|
||||
|
||||
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, (uint16_t)usLength, ESP_LOG_DEBUG);
|
||||
( void ) xMBMasterPortEventPost( EV_MASTER_EXECUTE );
|
||||
} else {
|
||||
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);
|
||||
( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
|
||||
}
|
||||
} else {
|
||||
vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
|
||||
( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
|
||||
ESP_LOGD( MB_PORT_TAG, "%s: Packet data receive failed (addr=%u)(%u).",
|
||||
__func__, (unsigned)ucRcvAddress, (unsigned)eStatus);
|
||||
ESP_LOGD( MB_PORT_TAG, "%" PRIu64 ": Packet data receive failed (addr=%u)(%u).",
|
||||
xEvent.xTransactionId, (unsigned)ucRcvAddress, (unsigned)eStatus);
|
||||
}
|
||||
} else {
|
||||
// Ignore the `EV_MASTER_FRAME_RECEIVED` event because the respond timeout occurred
|
||||
// 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 );
|
||||
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_EXECUTE ) ) {
|
||||
MB_PORT_CHECK(ucMBRcvFrame, MB_EILLSTATE, "receive buffer initialization fail.");
|
||||
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_EXECUTE", __func__);
|
||||
ucFunctionCode = ucMBRcvFrame[MB_PDU_FUNC_OFF];
|
||||
eException = MB_EX_ILLEGAL_FUNCTION;
|
||||
/* 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];
|
||||
} else {
|
||||
for ( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ )
|
||||
{
|
||||
/* No more function handlers registered. Abort. */
|
||||
if (xMasterFuncHandlers[i].ucFunctionCode == 0)
|
||||
break;
|
||||
case EV_MASTER_EXECUTE:
|
||||
if (xCurTransactionId == xEvent.xTransactionId) {
|
||||
MB_PORT_CHECK(ucMBRcvFrame, MB_EILLSTATE, "receive buffer initialization fail.");
|
||||
ESP_LOGD(MB_PORT_TAG, "%" PRIu64 ":EV_MASTER_EXECUTE", xEvent.xTransactionId);
|
||||
ucFunctionCode = ucMBRcvFrame[MB_PDU_FUNC_OFF];
|
||||
eException = MB_EX_ILLEGAL_FUNCTION;
|
||||
/* 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];
|
||||
} else {
|
||||
for ( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ )
|
||||
{
|
||||
break;
|
||||
}
|
||||
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(ucMBRcvFrame, &usLength);
|
||||
/* No more function handlers registered. Abort. */
|
||||
if (xMasterFuncHandlers[i].ucFunctionCode == 0) {
|
||||
break;
|
||||
}
|
||||
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(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 ( eException != MB_EX_NONE )
|
||||
{
|
||||
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__ );
|
||||
/* If master has exception, will send error process event. Otherwise the master is idle.*/
|
||||
if ( eException != MB_EX_NONE ) {
|
||||
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, "%" 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 );
|
||||
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_ERROR_PROCESS ) ) {
|
||||
ESP_LOGD( MB_PORT_TAG, "%s:EV_MASTER_ERROR_PROCESS", __func__ );
|
||||
/* Execute specified error process callback function. */
|
||||
errorType = eMBMasterGetErrorType( );
|
||||
vMBMasterGetPDUSndBuf( &ucMBSendFrame );
|
||||
switch ( errorType )
|
||||
{
|
||||
case EV_ERROR_RESPOND_TIMEOUT:
|
||||
vMBMasterErrorCBRespondTimeout( ucMBMasterGetDestAddress( ),
|
||||
ucMBSendFrame, usMBMasterGetPDUSndLength( ) );
|
||||
break;
|
||||
case EV_ERROR_RECEIVE_DATA:
|
||||
vMBMasterErrorCBReceiveData( ucMBMasterGetDestAddress( ),
|
||||
ucMBSendFrame, usMBMasterGetPDUSndLength( ) );
|
||||
break;
|
||||
case EV_ERROR_EXECUTE_FUNCTION:
|
||||
vMBMasterErrorCBExecuteFunction( ucMBMasterGetDestAddress( ),
|
||||
ucMBSendFrame, usMBMasterGetPDUSndLength( ) );
|
||||
break;
|
||||
case EV_ERROR_OK:
|
||||
vMBMasterCBRequestSuccess( );
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE( MB_PORT_TAG, "%s: incorrect error type = %u.", __func__, (unsigned)errorType);
|
||||
break;
|
||||
break;
|
||||
case EV_MASTER_ERROR_PROCESS:
|
||||
if (xCurTransactionId == xEvent.xTransactionId) {
|
||||
ESP_LOGD( MB_PORT_TAG, "%" PRIu64 ":EV_MASTER_ERROR_PROCESS", xEvent.xTransactionId);
|
||||
/* Execute specified error process callback function. */
|
||||
errorType = eMBMasterGetErrorType( );
|
||||
vMBMasterGetPDUSndBuf( &ucMBSendFrame );
|
||||
switch ( errorType )
|
||||
{
|
||||
case EV_ERROR_RESPOND_TIMEOUT:
|
||||
vMBMasterErrorCBRespondTimeout( ucMBMasterGetDestAddress( ),
|
||||
ucMBSendFrame, usMBMasterGetPDUSndLength( ) );
|
||||
break;
|
||||
case EV_ERROR_RECEIVE_DATA:
|
||||
vMBMasterErrorCBReceiveData( ucMBMasterGetDestAddress( ),
|
||||
ucMBSendFrame, usMBMasterGetPDUSndLength( ) );
|
||||
break;
|
||||
case EV_ERROR_EXECUTE_FUNCTION:
|
||||
vMBMasterErrorCBExecuteFunction( ucMBMasterGetDestAddress( ),
|
||||
ucMBSendFrame, usMBMasterGetPDUSndLength( ) );
|
||||
break;
|
||||
case EV_ERROR_OK:
|
||||
vMBMasterCBRequestSuccess( );
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE( MB_PORT_TAG, "%" PRIu64 ":incorrect error type = %d.", xEvent.xTransactionId, (int)errorType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
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 );
|
||||
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_ERROR_PROCESS );
|
||||
vMBMasterRunResRelease( );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE( MB_PORT_TAG, "%" PRIu64 ":Unexpected event triggered 0x%02x.", xEvent.xTransactionId, (int)xEvent.eEvent );
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// 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;
|
||||
}
|
||||
return eStatus;
|
||||
@@ -489,37 +490,37 @@ eMBMasterPoll( void )
|
||||
// Get whether the Modbus Master is run in master mode.
|
||||
BOOL xMBMasterGetCBRunInMasterMode( void )
|
||||
{
|
||||
return xMBRunInMasterMode;
|
||||
return atomic_load(&xMBRunInMasterMode);
|
||||
}
|
||||
|
||||
// Set whether the Modbus Master is run in master mode.
|
||||
void vMBMasterSetCBRunInMasterMode( BOOL IsMasterMode )
|
||||
{
|
||||
xMBRunInMasterMode = IsMasterMode;
|
||||
atomic_store(&(xMBRunInMasterMode), IsMasterMode);
|
||||
}
|
||||
|
||||
// Get Modbus Master send destination address.
|
||||
UCHAR ucMBMasterGetDestAddress( void )
|
||||
{
|
||||
return ucMBMasterDestAddress;
|
||||
return atomic_load(&ucMBMasterDestAddress);
|
||||
}
|
||||
|
||||
// Set Modbus Master send destination address.
|
||||
void vMBMasterSetDestAddress( UCHAR Address )
|
||||
{
|
||||
ucMBMasterDestAddress = Address;
|
||||
atomic_store(&(ucMBMasterDestAddress), Address);
|
||||
}
|
||||
|
||||
// Get Modbus Master current error event type.
|
||||
eMBMasterErrorEventType inline eMBMasterGetErrorType( void )
|
||||
{
|
||||
return eMBMasterCurErrorType;
|
||||
return atomic_load(&eMBMasterCurErrorType);
|
||||
}
|
||||
|
||||
// Set Modbus Master current error event type.
|
||||
void IRAM_ATTR vMBMasterSetErrorType( eMBMasterErrorEventType errorType )
|
||||
{
|
||||
eMBMasterCurErrorType = errorType;
|
||||
atomic_store(&(eMBMasterCurErrorType), errorType);
|
||||
}
|
||||
|
||||
/* 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.*/
|
||||
void vMBMasterSetPDUSndLength( USHORT SendPDULength )
|
||||
{
|
||||
usMasterSendPDULength = SendPDULength;
|
||||
atomic_store(&(usMasterSendPDULength), SendPDULength);
|
||||
}
|
||||
|
||||
/* Get Modbus Master send PDU's buffer length.*/
|
||||
USHORT usMBMasterGetPDUSndLength( void )
|
||||
{
|
||||
return usMasterSendPDULength;
|
||||
return atomic_load(&usMasterSendPDULength);
|
||||
}
|
||||
|
||||
/* Set Modbus Master current timer mode.*/
|
||||
void vMBMasterSetCurTimerMode( eMBMasterTimerMode eMBTimerMode )
|
||||
{
|
||||
eMasterCurTimerMode = eMBTimerMode;
|
||||
atomic_store(&(eMasterCurTimerMode), eMBTimerMode);
|
||||
}
|
||||
|
||||
/* Get Modbus Master current timer mode.*/
|
||||
eMBMasterTimerMode MB_PORT_ISR_ATTR xMBMasterGetCurTimerMode( void )
|
||||
{
|
||||
return eMasterCurTimerMode;
|
||||
return atomic_load(&eMasterCurTimerMode);
|
||||
}
|
||||
|
||||
/* The master request is broadcast? */
|
||||
@@ -561,7 +562,7 @@ BOOL MB_PORT_ISR_ATTR xMBMasterRequestIsBroadcast( void )
|
||||
/* The master request is broadcast? */
|
||||
void vMBMasterRequestSetType( BOOL xIsBroadcast )
|
||||
{
|
||||
xFrameIsBroadcast = xIsBroadcast;
|
||||
atomic_store(&(xFrameIsBroadcast), xIsBroadcast);
|
||||
}
|
||||
|
||||
// Get Modbus Master communication mode.
|
||||
|
||||
@@ -252,7 +252,9 @@ xMBMasterRTUReceiveFSM( void )
|
||||
BOOL xStatus = FALSE;
|
||||
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. */
|
||||
xStatus = xMBMasterPortSerialGetByte( ( CHAR * ) & ucByte );
|
||||
@@ -328,7 +330,9 @@ xMBMasterRTUTransmitFSM( void )
|
||||
BOOL xNeedPoll = TRUE;
|
||||
BOOL xFrameIsBroadcast = FALSE;
|
||||
|
||||
assert( eRcvState == STATE_M_RX_IDLE );
|
||||
if ( eRcvState != STATE_M_RX_IDLE ) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch ( eSndState )
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user