mirror of
https://github.com/espressif/esp-modbus.git
synced 2025-07-30 10:27:16 +02:00
fix modbus serial event misalingnment
This commit is contained in:
@ -1,3 +1,14 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Common (non-language-specific) configuration for Sphinx
|
||||||
|
#
|
||||||
|
|
||||||
|
# type: ignore
|
||||||
|
# pylint: disable=wildcard-import
|
||||||
|
# pylint: disable=undefined-variable
|
||||||
|
|
||||||
|
from __future__ import print_function, unicode_literals
|
||||||
|
|
||||||
from esp_docs.conf_docs import * # noqa: F403,F401
|
from esp_docs.conf_docs import * # noqa: F403,F401
|
||||||
|
|
||||||
extensions += ['sphinx_copybutton',
|
extensions += ['sphinx_copybutton',
|
||||||
@ -12,8 +23,7 @@ github_repo = 'espressif/esp-modbus'
|
|||||||
# context used by sphinx_idf_theme
|
# context used by sphinx_idf_theme
|
||||||
html_context['github_user'] = 'espressif'
|
html_context['github_user'] = 'espressif'
|
||||||
html_context['github_repo'] = 'esp-modbus'
|
html_context['github_repo'] = 'esp-modbus'
|
||||||
|
html_static_path = ['../_static']
|
||||||
html_static_path = ["../_static"]
|
|
||||||
|
|
||||||
# Extra options required by sphinx_idf_theme
|
# Extra options required by sphinx_idf_theme
|
||||||
project_slug = 'esp-modbus'
|
project_slug = 'esp-modbus'
|
||||||
|
@ -154,7 +154,7 @@ eMBASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
|
|||||||
UCHAR *pucMBASCIIFrame = ( UCHAR* ) ucASCIIBuf;
|
UCHAR *pucMBASCIIFrame = ( UCHAR* ) ucASCIIBuf;
|
||||||
USHORT usFrameLength = usRcvBufferPos;
|
USHORT usFrameLength = usRcvBufferPos;
|
||||||
|
|
||||||
if( xMBSerialPortGetRequest( &pucMBASCIIFrame, &usFrameLength ) == FALSE )
|
if( xMBPortSerialGetRequest( &pucMBASCIIFrame, &usFrameLength ) == FALSE )
|
||||||
{
|
{
|
||||||
return MB_EIO;
|
return MB_EIO;
|
||||||
}
|
}
|
||||||
@ -217,7 +217,7 @@ eMBASCIISend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength )
|
|||||||
eSndState = STATE_TX_START;
|
eSndState = STATE_TX_START;
|
||||||
EXIT_CRITICAL_SECTION( );
|
EXIT_CRITICAL_SECTION( );
|
||||||
|
|
||||||
if ( xMBSerialPortSendResponse( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ) == FALSE )
|
if ( xMBPortSerialSendResponse( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ) == FALSE )
|
||||||
{
|
{
|
||||||
eStatus = MB_EIO;
|
eStatus = MB_EIO;
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,7 @@ eMBMasterASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLen
|
|||||||
UCHAR *pucMBASCIIFrame = ( UCHAR* ) ucMasterASCIIRcvBuf;
|
UCHAR *pucMBASCIIFrame = ( UCHAR* ) ucMasterASCIIRcvBuf;
|
||||||
USHORT usFrameLength = usMasterRcvBufferPos;
|
USHORT usFrameLength = usMasterRcvBufferPos;
|
||||||
|
|
||||||
if( xMBMasterSerialPortGetResponse( &pucMBASCIIFrame, &usFrameLength ) == FALSE )
|
if( xMBMasterPortSerialGetResponse( &pucMBASCIIFrame, &usFrameLength ) == FALSE )
|
||||||
{
|
{
|
||||||
return MB_EIO;
|
return MB_EIO;
|
||||||
}
|
}
|
||||||
@ -181,8 +181,8 @@ eMBMasterASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLen
|
|||||||
|
|
||||||
/* Return the start of the Modbus PDU to the caller. */
|
/* Return the start of the Modbus PDU to the caller. */
|
||||||
*pucFrame = ( UCHAR * ) & pucMBASCIIFrame[MB_SER_PDU_PDU_OFF];
|
*pucFrame = ( UCHAR * ) & pucMBASCIIFrame[MB_SER_PDU_PDU_OFF];
|
||||||
} else {
|
} else {
|
||||||
eStatus = MB_EIO;
|
eStatus = MB_EIO;
|
||||||
}
|
}
|
||||||
EXIT_CRITICAL_SECTION( );
|
EXIT_CRITICAL_SECTION( );
|
||||||
return eStatus;
|
return eStatus;
|
||||||
@ -219,7 +219,7 @@ eMBMasterASCIISend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLengt
|
|||||||
eSndState = STATE_M_TX_START;
|
eSndState = STATE_M_TX_START;
|
||||||
EXIT_CRITICAL_SECTION( );
|
EXIT_CRITICAL_SECTION( );
|
||||||
|
|
||||||
if ( xMBMasterSerialPortSendRequest( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount ) == FALSE )
|
if ( xMBMasterPortSerialSendRequest( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount ) == FALSE )
|
||||||
{
|
{
|
||||||
eStatus = MB_EIO;
|
eStatus = MB_EIO;
|
||||||
}
|
}
|
||||||
|
@ -408,6 +408,7 @@ BOOL xMBMasterRequestIsBroadcast( void );
|
|||||||
eMBMasterErrorEventType eMBMasterGetErrorType( void );
|
eMBMasterErrorEventType eMBMasterGetErrorType( void );
|
||||||
void vMBMasterSetErrorType( eMBMasterErrorEventType errorType );
|
void vMBMasterSetErrorType( eMBMasterErrorEventType errorType );
|
||||||
eMBMasterReqErrCode eMBMasterWaitRequestFinish( void );
|
eMBMasterReqErrCode eMBMasterWaitRequestFinish( void );
|
||||||
|
eMBMode ucMBMasterGetCommMode( void );
|
||||||
|
|
||||||
/* ----------------------- Callback -----------------------------------------*/
|
/* ----------------------- Callback -----------------------------------------*/
|
||||||
|
|
||||||
|
@ -145,9 +145,9 @@ BOOL xMBPortSerialGetByte( CHAR * pucByte );
|
|||||||
|
|
||||||
BOOL xMBPortSerialPutByte( CHAR ucByte );
|
BOOL xMBPortSerialPutByte( CHAR ucByte );
|
||||||
|
|
||||||
BOOL xMBSerialPortGetRequest( UCHAR **ppucMBSerialFrame, USHORT * pusSerialLength ) __attribute__ ((weak));
|
BOOL xMBPortSerialGetRequest( UCHAR **ppucMBSerialFrame, USHORT * pusSerialLength ) __attribute__ ((weak));
|
||||||
|
|
||||||
BOOL xMBSerialPortSendResponse( UCHAR *pucMBSerialFrame, USHORT usSerialLength ) __attribute__ ((weak));
|
BOOL xMBPortSerialSendResponse( UCHAR *pucMBSerialFrame, USHORT usSerialLength ) __attribute__ ((weak));
|
||||||
|
|
||||||
#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED
|
#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED
|
||||||
BOOL xMBMasterPortSerialInit( UCHAR ucPort, ULONG ulBaudRate,
|
BOOL xMBMasterPortSerialInit( UCHAR ucPort, ULONG ulBaudRate,
|
||||||
@ -163,9 +163,11 @@ BOOL xMBMasterPortSerialGetByte( CHAR * pucByte );
|
|||||||
|
|
||||||
BOOL xMBMasterPortSerialPutByte( CHAR ucByte );
|
BOOL xMBMasterPortSerialPutByte( CHAR ucByte );
|
||||||
|
|
||||||
BOOL xMBMasterSerialPortGetResponse( UCHAR **ppucMBSerialFrame, USHORT * usSerialLength );
|
BOOL xMBMasterPortSerialGetResponse( UCHAR **ppucMBSerialFrame, USHORT * usSerialLength );
|
||||||
|
|
||||||
BOOL xMBMasterSerialPortSendRequest( UCHAR *pucMBSerialFrame, USHORT usSerialLength );
|
BOOL xMBMasterPortSerialSendRequest( UCHAR *pucMBSerialFrame, USHORT usSerialLength );
|
||||||
|
|
||||||
|
void vMBMasterRxFlush( void );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -310,11 +310,13 @@ eMBMasterDisable( void )
|
|||||||
eMBErrorCode
|
eMBErrorCode
|
||||||
eMBMasterPoll( void )
|
eMBMasterPoll( void )
|
||||||
{
|
{
|
||||||
static UCHAR *ucMBFrame = NULL;
|
static UCHAR *ucMBSendFrame = NULL;
|
||||||
|
static UCHAR *ucMBRcvFrame = NULL;
|
||||||
static UCHAR ucRcvAddress;
|
static UCHAR ucRcvAddress;
|
||||||
static UCHAR ucFunctionCode;
|
static UCHAR ucFunctionCode;
|
||||||
static USHORT usLength;
|
static USHORT usLength;
|
||||||
static eMBException eException;
|
static eMBException eException;
|
||||||
|
static BOOL xTransactionIsActive = FALSE;
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
eMBErrorCode eStatus = MB_ENOERR;
|
eMBErrorCode eStatus = MB_ENOERR;
|
||||||
@ -340,49 +342,63 @@ eMBMasterPoll( void )
|
|||||||
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_TRANSMIT ) ) {
|
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_TRANSMIT ) ) {
|
||||||
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_FRAME_TRANSMIT", __func__);
|
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_FRAME_TRANSMIT", __func__);
|
||||||
/* Master is busy now. */
|
/* Master is busy now. */
|
||||||
vMBMasterGetPDUSndBuf( &ucMBFrame );
|
vMBMasterGetPDUSndBuf( &ucMBSendFrame );
|
||||||
ESP_LOG_BUFFER_HEX_LEVEL("POLL transmit buffer", (void*)ucMBFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG);
|
ESP_LOG_BUFFER_HEX_LEVEL("POLL transmit buffer", (void*)ucMBSendFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG);
|
||||||
eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBFrame, usMBMasterGetPDUSndLength() );
|
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. %d", __func__, eStatus );
|
ESP_LOGE( MB_PORT_TAG, "%s:Frame send error. %d", __func__, eStatus );
|
||||||
}
|
}
|
||||||
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_TRANSMIT );
|
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_TRANSMIT );
|
||||||
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_SENT ) ) {
|
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_SENT ) ) {
|
||||||
ESP_LOGD( MB_PORT_TAG, "%s:EV_MASTER_FRAME_SENT", __func__ );
|
ESP_LOGD( MB_PORT_TAG, "%s:EV_MASTER_FRAME_SENT", __func__ );
|
||||||
ESP_LOG_BUFFER_HEX_LEVEL("POLL sent buffer", (void*)ucMBFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG);
|
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 );
|
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_SENT );
|
||||||
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_RECEIVED ) ) {
|
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_RECEIVED ) ) {
|
||||||
eStatus = peMBMasterFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength);
|
if (xTransactionIsActive) {
|
||||||
|
eStatus = peMBMasterFrameReceiveCur( &ucRcvAddress, &ucMBRcvFrame, &usLength);
|
||||||
|
MB_PORT_CHECK(ucMBRcvFrame, MB_EILLSTATE, "Receive 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.
|
||||||
|
if ( ( eStatus == MB_ENOERR ) && ( ucRcvAddress == ucMBMasterGetDestAddress() ) )
|
||||||
|
{
|
||||||
|
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__, eStatus);
|
||||||
|
ESP_LOG_BUFFER_HEX_LEVEL("POLL receive buffer", (void*)ucMBRcvFrame, (uint16_t)usLength, ESP_LOG_DEBUG);
|
||||||
|
|
||||||
// Check if the frame is for us. If not ,send an error process event.
|
( void ) xMBMasterPortEventPost( EV_MASTER_EXECUTE );
|
||||||
if ( ( eStatus == MB_ENOERR ) && ( ( ucRcvAddress == ucMBMasterGetDestAddress() )
|
} else {
|
||||||
|| ( ucRcvAddress == MB_TCP_PSEUDO_ADDRESS ) ) )
|
ESP_LOGE( MB_PORT_TAG, "Drop incorrect frame, receive_func(%u) != send_func(%u)",
|
||||||
{
|
ucMBRcvFrame[MB_PDU_FUNC_OFF], ucMBSendFrame[MB_PDU_FUNC_OFF]);
|
||||||
( void ) xMBMasterPortEventPost( EV_MASTER_EXECUTE );
|
vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
|
||||||
ESP_LOGD(MB_PORT_TAG, "%s: Packet data received successfully (%u).", __func__, eStatus);
|
( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
|
||||||
ESP_LOG_BUFFER_HEX_LEVEL("POLL receive buffer", (void*)ucMBFrame, (uint16_t)usLength, ESP_LOG_DEBUG);
|
}
|
||||||
}
|
}
|
||||||
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, "%s: Packet data receive failed (addr=%u)(%u).",
|
||||||
__func__, ucRcvAddress, eStatus);
|
__func__, ucRcvAddress, 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.");
|
||||||
}
|
}
|
||||||
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_RECEIVED );
|
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_RECEIVED );
|
||||||
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_EXECUTE ) ) {
|
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_EXECUTE ) ) {
|
||||||
if ( !ucMBFrame )
|
MB_PORT_CHECK(ucMBRcvFrame, MB_EILLSTATE, "receive buffer initialization fail.");
|
||||||
{
|
|
||||||
return MB_EILLSTATE;
|
|
||||||
}
|
|
||||||
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_EXECUTE", __func__);
|
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_EXECUTE", __func__);
|
||||||
ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF];
|
ucFunctionCode = ucMBRcvFrame[MB_PDU_FUNC_OFF];
|
||||||
eException = MB_EX_ILLEGAL_FUNCTION;
|
eException = MB_EX_ILLEGAL_FUNCTION;
|
||||||
/* If receive frame has exception. The receive function code highest bit is 1.*/
|
/* If receive frame has exception. The receive function code highest bit is 1.*/
|
||||||
if (ucFunctionCode & MB_FUNC_ERROR)
|
if (ucFunctionCode & MB_FUNC_ERROR)
|
||||||
{
|
{
|
||||||
eException = (eMBException)ucMBFrame[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++ )
|
||||||
{
|
{
|
||||||
@ -403,12 +419,12 @@ eMBMasterPoll( void )
|
|||||||
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(ucMBFrame, &usLength);
|
eException = xMasterFuncHandlers[i].pxHandler(ucMBRcvFrame, &usLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
eException = xMasterFuncHandlers[i].pxHandler( ucMBFrame, &usLength );
|
eException = xMasterFuncHandlers[i].pxHandler( ucMBRcvFrame, &usLength );
|
||||||
}
|
}
|
||||||
vMBMasterSetCBRunInMasterMode( FALSE );
|
vMBMasterSetCBRunInMasterMode( FALSE );
|
||||||
break;
|
break;
|
||||||
@ -434,20 +450,20 @@ eMBMasterPoll( void )
|
|||||||
ESP_LOGD( MB_PORT_TAG, "%s:EV_MASTER_ERROR_PROCESS", __func__ );
|
ESP_LOGD( MB_PORT_TAG, "%s:EV_MASTER_ERROR_PROCESS", __func__ );
|
||||||
/* Execute specified error process callback function. */
|
/* Execute specified error process callback function. */
|
||||||
errorType = eMBMasterGetErrorType( );
|
errorType = eMBMasterGetErrorType( );
|
||||||
vMBMasterGetPDUSndBuf( &ucMBFrame );
|
vMBMasterGetPDUSndBuf( &ucMBSendFrame );
|
||||||
switch ( errorType )
|
switch ( errorType )
|
||||||
{
|
{
|
||||||
case EV_ERROR_RESPOND_TIMEOUT:
|
case EV_ERROR_RESPOND_TIMEOUT:
|
||||||
vMBMasterErrorCBRespondTimeout( ucMBMasterGetDestAddress( ),
|
vMBMasterErrorCBRespondTimeout( ucMBMasterGetDestAddress( ),
|
||||||
ucMBFrame, usMBMasterGetPDUSndLength( ) );
|
ucMBSendFrame, usMBMasterGetPDUSndLength( ) );
|
||||||
break;
|
break;
|
||||||
case EV_ERROR_RECEIVE_DATA:
|
case EV_ERROR_RECEIVE_DATA:
|
||||||
vMBMasterErrorCBReceiveData( ucMBMasterGetDestAddress( ),
|
vMBMasterErrorCBReceiveData( ucMBMasterGetDestAddress( ),
|
||||||
ucMBFrame, usMBMasterGetPDUSndLength( ) );
|
ucMBSendFrame, usMBMasterGetPDUSndLength( ) );
|
||||||
break;
|
break;
|
||||||
case EV_ERROR_EXECUTE_FUNCTION:
|
case EV_ERROR_EXECUTE_FUNCTION:
|
||||||
vMBMasterErrorCBExecuteFunction( ucMBMasterGetDestAddress( ),
|
vMBMasterErrorCBExecuteFunction( ucMBMasterGetDestAddress( ),
|
||||||
ucMBFrame, usMBMasterGetPDUSndLength( ) );
|
ucMBSendFrame, usMBMasterGetPDUSndLength( ) );
|
||||||
break;
|
break;
|
||||||
case EV_ERROR_OK:
|
case EV_ERROR_OK:
|
||||||
vMBMasterCBRequestSuccess( );
|
vMBMasterCBRequestSuccess( );
|
||||||
@ -456,6 +472,7 @@ eMBMasterPoll( void )
|
|||||||
ESP_LOGE( MB_PORT_TAG, "%s: incorrect error type = %d.", __func__, errorType);
|
ESP_LOGE( MB_PORT_TAG, "%s: incorrect error type = %d.", __func__, errorType);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
vMBMasterPortTimersDisable( );
|
||||||
vMBMasterSetErrorType( EV_ERROR_INIT );
|
vMBMasterSetErrorType( EV_ERROR_INIT );
|
||||||
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_ERROR_PROCESS );
|
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_ERROR_PROCESS );
|
||||||
vMBMasterRunResRelease( );
|
vMBMasterRunResRelease( );
|
||||||
@ -542,8 +559,15 @@ 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;
|
xFrameIsBroadcast = xIsBroadcast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get Modbus Master communication mode.
|
||||||
|
eMBMode ucMBMasterGetCommMode(void)
|
||||||
|
{
|
||||||
|
return eMBMasterCurrentMode;
|
||||||
|
}
|
||||||
|
|
||||||
#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
|
||||||
|
@ -158,7 +158,7 @@ eMBRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
|
|||||||
UCHAR *pucMBRTUFrame = ( UCHAR* ) ucRTUBuf;
|
UCHAR *pucMBRTUFrame = ( UCHAR* ) ucRTUBuf;
|
||||||
USHORT usFrameLength = usRcvBufferPos;
|
USHORT usFrameLength = usRcvBufferPos;
|
||||||
|
|
||||||
if( xMBSerialPortGetRequest( &pucMBRTUFrame, &usFrameLength ) == FALSE )
|
if( xMBPortSerialGetRequest( &pucMBRTUFrame, &usFrameLength ) == FALSE )
|
||||||
{
|
{
|
||||||
return MB_EIO;
|
return MB_EIO;
|
||||||
}
|
}
|
||||||
@ -222,7 +222,7 @@ eMBRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength )
|
|||||||
eSndState = STATE_TX_XMIT;
|
eSndState = STATE_TX_XMIT;
|
||||||
EXIT_CRITICAL_SECTION( );
|
EXIT_CRITICAL_SECTION( );
|
||||||
|
|
||||||
if( xMBSerialPortSendResponse( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ) == FALSE )
|
if( xMBPortSerialSendResponse( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ) == FALSE )
|
||||||
{
|
{
|
||||||
eStatus = MB_EIO;
|
eStatus = MB_EIO;
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ eMBMasterRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLengt
|
|||||||
UCHAR *pucMBRTUFrame = ( UCHAR* ) ucMasterRTURcvBuf;
|
UCHAR *pucMBRTUFrame = ( UCHAR* ) ucMasterRTURcvBuf;
|
||||||
USHORT usFrameLength = usMasterRcvBufferPos;
|
USHORT usFrameLength = usMasterRcvBufferPos;
|
||||||
|
|
||||||
if( xMBMasterSerialPortGetResponse( &pucMBRTUFrame, &usFrameLength ) == FALSE )
|
if( xMBMasterPortSerialGetResponse( &pucMBRTUFrame, &usFrameLength ) == FALSE )
|
||||||
{
|
{
|
||||||
return MB_EIO;
|
return MB_EIO;
|
||||||
}
|
}
|
||||||
@ -231,7 +231,7 @@ eMBMasterRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength
|
|||||||
/* Activate the transmitter. */
|
/* Activate the transmitter. */
|
||||||
eSndState = STATE_M_TX_XMIT;
|
eSndState = STATE_M_TX_XMIT;
|
||||||
|
|
||||||
if ( xMBMasterSerialPortSendRequest( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount ) == FALSE )
|
if ( xMBMasterPortSerialSendRequest( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount ) == FALSE )
|
||||||
{
|
{
|
||||||
eStatus = MB_EIO;
|
eStatus = MB_EIO;
|
||||||
}
|
}
|
||||||
|
@ -73,13 +73,61 @@ vMBPortSetMode( UCHAR ucMode )
|
|||||||
EXIT_CRITICAL_SECTION();
|
EXIT_CRITICAL_SECTION();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED || MB_SLAVE_RTU_ENABLED || MB_SLAVE_ASCII_ENABLED
|
||||||
|
|
||||||
BOOL xMBPortSerialWaitEvent(QueueHandle_t xMbUartQueue, uart_event_t* pxEvent, ULONG xTimeout)
|
BOOL xMBPortSerialWaitEvent(QueueHandle_t xMbUartQueue, uart_event_t* pxEvent, ULONG xTimeout)
|
||||||
{
|
{
|
||||||
BOOL xResult = (BaseType_t)xQueueReceive(xMbUartQueue, (void*)pxEvent, (TickType_t) xTimeout);
|
BOOL xResult = (BaseType_t)xQueueReceive(xMbUartQueue, (void*)pxEvent, (TickType_t) xTimeout);
|
||||||
ESP_LOGD(__func__, "UART event: %d ", pxEvent->type);
|
ESP_LOGD(MB_PORT_TAG, "%s, UART event: %d ", __func__, pxEvent->type);
|
||||||
return xResult;
|
return xResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The function is called from ASCII/RTU module to get processed data buffer. Sets the
|
||||||
|
* received buffer and its length using parameters.
|
||||||
|
*/
|
||||||
|
__attribute__ ((weak))
|
||||||
|
BOOL xMBMasterPortSerialGetResponse( UCHAR **ppucMBSerialFrame, USHORT * usSerialLength )
|
||||||
|
{
|
||||||
|
ESP_LOGD(MB_PORT_TAG, " %s default", __func__);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The function is called from ASCII/RTU module to set processed data buffer
|
||||||
|
* to be sent in transmitter state machine.
|
||||||
|
*/
|
||||||
|
__attribute__ ((weak))
|
||||||
|
BOOL xMBMasterPortSerialSendRequest( UCHAR *pucMBSerialFrame, USHORT usSerialLength )
|
||||||
|
{
|
||||||
|
ESP_LOGD(MB_PORT_TAG, "%s default", __func__);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MB_SLAVE_RTU_ENABLED || MB_SLAVE_ASCII_ENABLED
|
||||||
|
|
||||||
|
__attribute__ ((weak))
|
||||||
|
BOOL xMBPortSerialGetRequest( UCHAR **ppucMBSerialFrame, USHORT * usSerialLength )
|
||||||
|
{
|
||||||
|
ESP_LOGD(MB_PORT_TAG, "%s default", __func__);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__ ((weak))
|
||||||
|
BOOL xMBPortSerialSendResponse( UCHAR *pucMBSerialFrame, USHORT usSerialLength )
|
||||||
|
{
|
||||||
|
ESP_LOGD(MB_PORT_TAG, "%s default", __func__);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#if MB_TCP_DEBUG
|
#if MB_TCP_DEBUG
|
||||||
|
|
||||||
// This function is kept to realize legacy freemodbus frame logging functionality
|
// This function is kept to realize legacy freemodbus frame logging functionality
|
||||||
|
@ -260,17 +260,6 @@ BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL xMBSerialPortGetRequest( UCHAR **ppucMBSerialFrame, USHORT * usSerialLength )
|
|
||||||
{
|
|
||||||
BOOL eStatus = TRUE;
|
|
||||||
return eStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL xMBSerialPortSendResponse( UCHAR *pucMBSerialFrame, USHORT usSerialLength )
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vMBPortSerialClose(void)
|
void vMBPortSerialClose(void)
|
||||||
{
|
{
|
||||||
(void)vTaskSuspend(xMbTaskHandle);
|
(void)vTaskSuspend(xMbTaskHandle);
|
||||||
|
@ -52,6 +52,9 @@
|
|||||||
#include "port_serial_master.h"
|
#include "port_serial_master.h"
|
||||||
|
|
||||||
/* ----------------------- Defines ------------------------------------------*/
|
/* ----------------------- Defines ------------------------------------------*/
|
||||||
|
#define MB_SERIAL_RX_SEMA_TOUT_MS (1000)
|
||||||
|
#define MB_SERIAL_RX_SEMA_TOUT (pdMS_TO_TICKS(MB_SERIAL_RX_SEMA_TOUT_MS))
|
||||||
|
#define MB_SERIAL_RX_FLUSH_RETRY (2)
|
||||||
|
|
||||||
/* ----------------------- Static variables ---------------------------------*/
|
/* ----------------------- Static variables ---------------------------------*/
|
||||||
static const CHAR *TAG = "MB_MASTER_SERIAL";
|
static const CHAR *TAG = "MB_MASTER_SERIAL";
|
||||||
@ -66,16 +69,67 @@ static UCHAR ucUartNumber = UART_NUM_MAX - 1;
|
|||||||
static BOOL bRxStateEnabled = FALSE; // Receiver enabled flag
|
static BOOL bRxStateEnabled = FALSE; // Receiver enabled flag
|
||||||
static BOOL bTxStateEnabled = FALSE; // Transmitter enabled flag
|
static BOOL bTxStateEnabled = FALSE; // Transmitter enabled flag
|
||||||
|
|
||||||
|
static SemaphoreHandle_t xMasterSemaRxHandle; // Rx blocking semaphore handle
|
||||||
|
|
||||||
|
static BOOL xMBMasterPortRxSemaInit( void )
|
||||||
|
{
|
||||||
|
xMasterSemaRxHandle = xSemaphoreCreateBinary();
|
||||||
|
MB_PORT_CHECK((xMasterSemaRxHandle != NULL), FALSE , "%s: RX semaphore create failure.", __func__);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL xMBMasterPortRxSemaTake( LONG lTimeOut )
|
||||||
|
{
|
||||||
|
BaseType_t xStatus = pdTRUE;
|
||||||
|
xStatus = xSemaphoreTake(xMasterSemaRxHandle, lTimeOut );
|
||||||
|
MB_PORT_CHECK((xStatus == pdTRUE), FALSE , "%s: RX semaphore take failure.", __func__);
|
||||||
|
ESP_LOGV(MB_PORT_TAG,"%s:Take RX semaphore (%lu ticks).", __func__, lTimeOut);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vMBMasterRxSemaRelease( void )
|
||||||
|
{
|
||||||
|
BaseType_t xStatus = pdFALSE;
|
||||||
|
xStatus = xSemaphoreGive(xMasterSemaRxHandle);
|
||||||
|
if (xStatus != pdTRUE) {
|
||||||
|
ESP_LOGD(MB_PORT_TAG,"%s:RX semaphore is free.", __func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL vMBMasterRxSemaIsBusy( void )
|
||||||
|
{
|
||||||
|
BaseType_t xStatus = pdFALSE;
|
||||||
|
xStatus = (uxSemaphoreGetCount(xMasterSemaRxHandle) == 0) ? TRUE : FALSE;
|
||||||
|
return xStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vMBMasterRxFlush( void )
|
||||||
|
{
|
||||||
|
size_t xSize = 1;
|
||||||
|
esp_err_t xErr = ESP_OK;
|
||||||
|
for (int xCount = 0; (xCount < MB_SERIAL_RX_FLUSH_RETRY) && xSize; xCount++) {
|
||||||
|
xErr = uart_get_buffered_data_len(ucUartNumber, &xSize);
|
||||||
|
MB_PORT_CHECK((xErr == ESP_OK), ; , "mb flush serial fail, error = 0x%x.", xErr);
|
||||||
|
BaseType_t xStatus = xQueueReset(xMbUartQueue);
|
||||||
|
if (xStatus) {
|
||||||
|
xErr = uart_flush_input(ucUartNumber);
|
||||||
|
MB_PORT_CHECK((xErr == ESP_OK), ; , "mb flush serial fail, error = 0x%x.", xErr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void vMBMasterPortSerialEnable(BOOL bRxEnable, BOOL bTxEnable)
|
void vMBMasterPortSerialEnable(BOOL bRxEnable, BOOL bTxEnable)
|
||||||
{
|
{
|
||||||
// This function can be called from xMBRTUTransmitFSM() of different task
|
// This function can be called from xMBRTUTransmitFSM() of different task
|
||||||
if (bTxEnable) {
|
if (bTxEnable) {
|
||||||
|
vMBMasterRxFlush();
|
||||||
bTxStateEnabled = TRUE;
|
bTxStateEnabled = TRUE;
|
||||||
} else {
|
} else {
|
||||||
bTxStateEnabled = FALSE;
|
bTxStateEnabled = FALSE;
|
||||||
}
|
}
|
||||||
if (bRxEnable) {
|
if (bRxEnable) {
|
||||||
bRxStateEnabled = TRUE;
|
bRxStateEnabled = TRUE;
|
||||||
|
vMBMasterRxSemaRelease();
|
||||||
vTaskResume(xMbTaskHandle); // Resume receiver task
|
vTaskResume(xMbTaskHandle); // Resume receiver task
|
||||||
} else {
|
} else {
|
||||||
vTaskSuspend(xMbTaskHandle); // Block receiver task
|
vTaskSuspend(xMbTaskHandle); // Block receiver task
|
||||||
@ -88,12 +142,12 @@ static USHORT usMBMasterPortSerialRxPoll(size_t xEventSize)
|
|||||||
BOOL xStatus = TRUE;
|
BOOL xStatus = TRUE;
|
||||||
USHORT usCnt = 0;
|
USHORT usCnt = 0;
|
||||||
|
|
||||||
if (bRxStateEnabled) {
|
xStatus = xMBMasterPortRxSemaTake(MB_SERIAL_RX_SEMA_TOUT);
|
||||||
|
if (xStatus) {
|
||||||
while(xStatus && (usCnt++ <= xEventSize)) {
|
while(xStatus && (usCnt++ <= xEventSize)) {
|
||||||
// Call the Modbus stack callback function and let it fill the stack buffers.
|
// Call the Modbus stack callback function and let it fill the stack buffers.
|
||||||
xStatus = pxMBMasterFrameCBByteReceived(); // callback to receive FSM
|
xStatus = pxMBMasterFrameCBByteReceived(); // callback to receive FSM
|
||||||
}
|
}
|
||||||
|
|
||||||
// The buffer is transferred into Modbus stack and is not needed here any more
|
// The buffer is transferred into Modbus stack and is not needed here any more
|
||||||
uart_flush_input(ucUartNumber);
|
uart_flush_input(ucUartNumber);
|
||||||
ESP_LOGD(TAG, "Received data: %d(bytes in buffer)\n", (uint32_t)usCnt);
|
ESP_LOGD(TAG, "Received data: %d(bytes in buffer)\n", (uint32_t)usCnt);
|
||||||
@ -147,13 +201,17 @@ static void vUartTask(void* pvParameters)
|
|||||||
// This flag set in the event means that no more
|
// This flag set in the event means that no more
|
||||||
// data received during configured timeout and UART TOUT feature is triggered
|
// data received during configured timeout and UART TOUT feature is triggered
|
||||||
if (xEvent.timeout_flag) {
|
if (xEvent.timeout_flag) {
|
||||||
|
// Response is received but previous packet processing is pending
|
||||||
|
// Do not wait completion of processing and just discard received data as incorrect
|
||||||
|
if (vMBMasterRxSemaIsBusy()) {
|
||||||
|
vMBMasterRxFlush();
|
||||||
|
break;
|
||||||
|
}
|
||||||
// Get buffered data length
|
// Get buffered data length
|
||||||
ESP_ERROR_CHECK(uart_get_buffered_data_len(ucUartNumber, &xEvent.size));
|
ESP_ERROR_CHECK(uart_get_buffered_data_len(ucUartNumber, &xEvent.size));
|
||||||
// Read received data and send it to modbus stack
|
// Read received data and send it to modbus stack
|
||||||
usResult = usMBMasterPortSerialRxPoll(xEvent.size);
|
usResult = usMBMasterPortSerialRxPoll(xEvent.size);
|
||||||
ESP_LOGD(TAG,"Timeout occured, processed: %d bytes", usResult);
|
ESP_LOGD(TAG,"Timeout occured, processed: %d bytes", usResult);
|
||||||
// Block receiver task until data is not processed
|
|
||||||
vTaskSuspend(NULL);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
//Event of HW FIFO overflow detected
|
//Event of HW FIFO overflow detected
|
||||||
@ -253,7 +311,8 @@ BOOL xMBMasterPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
|
|||||||
|
|
||||||
// Set always timeout flag to trigger timeout interrupt even after rx fifo full
|
// Set always timeout flag to trigger timeout interrupt even after rx fifo full
|
||||||
uart_set_always_rx_timeout(ucUartNumber, true);
|
uart_set_always_rx_timeout(ucUartNumber, true);
|
||||||
|
MB_PORT_CHECK((xMBMasterPortRxSemaInit()), FALSE,
|
||||||
|
"mb serial RX semaphore create fail.");
|
||||||
// Create a task to handle UART events
|
// Create a task to handle UART events
|
||||||
BaseType_t xStatus = xTaskCreatePinnedToCore(vUartTask, "uart_queue_task",
|
BaseType_t xStatus = xTaskCreatePinnedToCore(vUartTask, "uart_queue_task",
|
||||||
MB_SERIAL_TASK_STACK_SIZE,
|
MB_SERIAL_TASK_STACK_SIZE,
|
||||||
@ -272,24 +331,6 @@ BOOL xMBMasterPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* The function is called from ASCII/RTU module to get processed data buffer. Sets the
|
|
||||||
* received buffer and its length using parameters.
|
|
||||||
*/
|
|
||||||
BOOL xMBMasterSerialPortGetResponse( UCHAR **ppucMBSerialFrame, USHORT * usSerialLength )
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The function is called from ASCII/RTU module to set processed data buffer
|
|
||||||
* to be sent in transmitter state machine.
|
|
||||||
*/
|
|
||||||
BOOL xMBMasterSerialPortSendRequest( UCHAR *pucMBSerialFrame, USHORT usSerialLength )
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vMBMasterPortSerialClose(void)
|
void vMBMasterPortSerialClose(void)
|
||||||
{
|
{
|
||||||
(void)vTaskDelete(xMbTaskHandle);
|
(void)vTaskDelete(xMbTaskHandle);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
version: "1.0.5"
|
version: "1.0.6"
|
||||||
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:
|
||||||
|
Reference in New Issue
Block a user