mirror of
https://github.com/espressif/esp-modbus.git
synced 2025-07-29 18:07:17 +02:00
Merge branch 'bugfix/modbus_serial_fix_event_misalingnment' into 'master'
fix modbus serial event misalingnment Closes IDFGH-5107 and IDFGH-5108 See merge request idf/esp-modbus!9
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
|
||||
|
||||
extensions += ['sphinx_copybutton',
|
||||
@ -12,8 +23,7 @@ github_repo = 'espressif/esp-modbus'
|
||||
# context used by sphinx_idf_theme
|
||||
html_context['github_user'] = 'espressif'
|
||||
html_context['github_repo'] = 'esp-modbus'
|
||||
|
||||
html_static_path = ["../_static"]
|
||||
html_static_path = ['../_static']
|
||||
|
||||
# Extra options required by sphinx_idf_theme
|
||||
project_slug = 'esp-modbus'
|
||||
|
@ -154,7 +154,7 @@ eMBASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
|
||||
UCHAR *pucMBASCIIFrame = ( UCHAR* ) ucASCIIBuf;
|
||||
USHORT usFrameLength = usRcvBufferPos;
|
||||
|
||||
if( xMBSerialPortGetRequest( &pucMBASCIIFrame, &usFrameLength ) == FALSE )
|
||||
if( xMBPortSerialGetRequest( &pucMBASCIIFrame, &usFrameLength ) == FALSE )
|
||||
{
|
||||
return MB_EIO;
|
||||
}
|
||||
@ -217,7 +217,7 @@ eMBASCIISend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength )
|
||||
eSndState = STATE_TX_START;
|
||||
EXIT_CRITICAL_SECTION( );
|
||||
|
||||
if ( xMBSerialPortSendResponse( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ) == FALSE )
|
||||
if ( xMBPortSerialSendResponse( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ) == FALSE )
|
||||
{
|
||||
eStatus = MB_EIO;
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ eMBMasterASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLen
|
||||
UCHAR *pucMBASCIIFrame = ( UCHAR* ) ucMasterASCIIRcvBuf;
|
||||
USHORT usFrameLength = usMasterRcvBufferPos;
|
||||
|
||||
if( xMBMasterSerialPortGetResponse( &pucMBASCIIFrame, &usFrameLength ) == FALSE )
|
||||
if( xMBMasterPortSerialGetResponse( &pucMBASCIIFrame, &usFrameLength ) == FALSE )
|
||||
{
|
||||
return MB_EIO;
|
||||
}
|
||||
@ -181,8 +181,8 @@ eMBMasterASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLen
|
||||
|
||||
/* Return the start of the Modbus PDU to the caller. */
|
||||
*pucFrame = ( UCHAR * ) & pucMBASCIIFrame[MB_SER_PDU_PDU_OFF];
|
||||
} else {
|
||||
eStatus = MB_EIO;
|
||||
} else {
|
||||
eStatus = MB_EIO;
|
||||
}
|
||||
EXIT_CRITICAL_SECTION( );
|
||||
return eStatus;
|
||||
@ -219,7 +219,7 @@ eMBMasterASCIISend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLengt
|
||||
eSndState = STATE_M_TX_START;
|
||||
EXIT_CRITICAL_SECTION( );
|
||||
|
||||
if ( xMBMasterSerialPortSendRequest( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount ) == FALSE )
|
||||
if ( xMBMasterPortSerialSendRequest( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount ) == FALSE )
|
||||
{
|
||||
eStatus = MB_EIO;
|
||||
}
|
||||
|
@ -408,6 +408,7 @@ BOOL xMBMasterRequestIsBroadcast( void );
|
||||
eMBMasterErrorEventType eMBMasterGetErrorType( void );
|
||||
void vMBMasterSetErrorType( eMBMasterErrorEventType errorType );
|
||||
eMBMasterReqErrCode eMBMasterWaitRequestFinish( void );
|
||||
eMBMode ucMBMasterGetCommMode( void );
|
||||
|
||||
/* ----------------------- Callback -----------------------------------------*/
|
||||
|
||||
|
@ -145,9 +145,9 @@ BOOL xMBPortSerialGetByte( CHAR * pucByte );
|
||||
|
||||
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
|
||||
BOOL xMBMasterPortSerialInit( UCHAR ucPort, ULONG ulBaudRate,
|
||||
@ -163,9 +163,11 @@ BOOL xMBMasterPortSerialGetByte( CHAR * pucByte );
|
||||
|
||||
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
|
||||
|
||||
|
@ -310,11 +310,13 @@ eMBMasterDisable( void )
|
||||
eMBErrorCode
|
||||
eMBMasterPoll( void )
|
||||
{
|
||||
static UCHAR *ucMBFrame = NULL;
|
||||
static UCHAR *ucMBSendFrame = NULL;
|
||||
static UCHAR *ucMBRcvFrame = NULL;
|
||||
static UCHAR ucRcvAddress;
|
||||
static UCHAR ucFunctionCode;
|
||||
static USHORT usLength;
|
||||
static eMBException eException;
|
||||
static BOOL xTransactionIsActive = FALSE;
|
||||
int i;
|
||||
int j;
|
||||
eMBErrorCode eStatus = MB_ENOERR;
|
||||
@ -340,49 +342,63 @@ eMBMasterPoll( void )
|
||||
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_TRANSMIT ) ) {
|
||||
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_FRAME_TRANSMIT", __func__);
|
||||
/* Master is busy now. */
|
||||
vMBMasterGetPDUSndBuf( &ucMBFrame );
|
||||
ESP_LOG_BUFFER_HEX_LEVEL("POLL transmit buffer", (void*)ucMBFrame, usMBMasterGetPDUSndLength(), ESP_LOG_DEBUG);
|
||||
eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBFrame, usMBMasterGetPDUSndLength() );
|
||||
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)
|
||||
{
|
||||
vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
|
||||
( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
|
||||
ESP_LOGE( MB_PORT_TAG, "%s:Frame send error. %d", __func__, 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*)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 );
|
||||
} 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.
|
||||
if ( ( eStatus == MB_ENOERR ) && ( ( ucRcvAddress == ucMBMasterGetDestAddress() )
|
||||
|| ( ucRcvAddress == MB_TCP_PSEUDO_ADDRESS ) ) )
|
||||
{
|
||||
( void ) xMBMasterPortEventPost( EV_MASTER_EXECUTE );
|
||||
ESP_LOGD(MB_PORT_TAG, "%s: Packet data received successfully (%u).", __func__, eStatus);
|
||||
ESP_LOG_BUFFER_HEX_LEVEL("POLL receive buffer", (void*)ucMBFrame, (uint16_t)usLength, ESP_LOG_DEBUG);
|
||||
}
|
||||
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__, ucRcvAddress, eStatus);
|
||||
( void ) xMBMasterPortEventPost( EV_MASTER_EXECUTE );
|
||||
} else {
|
||||
ESP_LOGE( MB_PORT_TAG, "Drop incorrect frame, receive_func(%u) != send_func(%u)",
|
||||
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__, 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 );
|
||||
} else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_EXECUTE ) ) {
|
||||
if ( !ucMBFrame )
|
||||
{
|
||||
return MB_EILLSTATE;
|
||||
}
|
||||
MB_PORT_CHECK(ucMBRcvFrame, MB_EILLSTATE, "receive buffer initialization fail.");
|
||||
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;
|
||||
/* If receive frame has exception. The receive function code highest bit is 1.*/
|
||||
if (ucFunctionCode & MB_FUNC_ERROR)
|
||||
{
|
||||
eException = (eMBException)ucMBFrame[MB_PDU_DATA_OFF];
|
||||
eException = (eMBException)ucMBRcvFrame[MB_PDU_DATA_OFF];
|
||||
} else {
|
||||
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++)
|
||||
{
|
||||
vMBMasterSetDestAddress(j);
|
||||
eException = xMasterFuncHandlers[i].pxHandler(ucMBFrame, &usLength);
|
||||
eException = xMasterFuncHandlers[i].pxHandler(ucMBRcvFrame, &usLength);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
eException = xMasterFuncHandlers[i].pxHandler( ucMBFrame, &usLength );
|
||||
eException = xMasterFuncHandlers[i].pxHandler( ucMBRcvFrame, &usLength );
|
||||
}
|
||||
vMBMasterSetCBRunInMasterMode( FALSE );
|
||||
break;
|
||||
@ -434,20 +450,20 @@ eMBMasterPoll( void )
|
||||
ESP_LOGD( MB_PORT_TAG, "%s:EV_MASTER_ERROR_PROCESS", __func__ );
|
||||
/* Execute specified error process callback function. */
|
||||
errorType = eMBMasterGetErrorType( );
|
||||
vMBMasterGetPDUSndBuf( &ucMBFrame );
|
||||
vMBMasterGetPDUSndBuf( &ucMBSendFrame );
|
||||
switch ( errorType )
|
||||
{
|
||||
case EV_ERROR_RESPOND_TIMEOUT:
|
||||
vMBMasterErrorCBRespondTimeout( ucMBMasterGetDestAddress( ),
|
||||
ucMBFrame, usMBMasterGetPDUSndLength( ) );
|
||||
ucMBSendFrame, usMBMasterGetPDUSndLength( ) );
|
||||
break;
|
||||
case EV_ERROR_RECEIVE_DATA:
|
||||
vMBMasterErrorCBReceiveData( ucMBMasterGetDestAddress( ),
|
||||
ucMBFrame, usMBMasterGetPDUSndLength( ) );
|
||||
ucMBSendFrame, usMBMasterGetPDUSndLength( ) );
|
||||
break;
|
||||
case EV_ERROR_EXECUTE_FUNCTION:
|
||||
vMBMasterErrorCBExecuteFunction( ucMBMasterGetDestAddress( ),
|
||||
ucMBFrame, usMBMasterGetPDUSndLength( ) );
|
||||
ucMBSendFrame, usMBMasterGetPDUSndLength( ) );
|
||||
break;
|
||||
case EV_ERROR_OK:
|
||||
vMBMasterCBRequestSuccess( );
|
||||
@ -456,6 +472,7 @@ eMBMasterPoll( void )
|
||||
ESP_LOGE( MB_PORT_TAG, "%s: incorrect error type = %d.", __func__, errorType);
|
||||
break;
|
||||
}
|
||||
vMBMasterPortTimersDisable( );
|
||||
vMBMasterSetErrorType( EV_ERROR_INIT );
|
||||
MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_ERROR_PROCESS );
|
||||
vMBMasterRunResRelease( );
|
||||
@ -542,8 +559,15 @@ BOOL MB_PORT_ISR_ATTR xMBMasterRequestIsBroadcast( void )
|
||||
}
|
||||
|
||||
/* The master request is broadcast? */
|
||||
void vMBMasterRequestSetType( BOOL xIsBroadcast ){
|
||||
void vMBMasterRequestSetType( BOOL 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
|
||||
|
@ -158,7 +158,7 @@ eMBRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
|
||||
UCHAR *pucMBRTUFrame = ( UCHAR* ) ucRTUBuf;
|
||||
USHORT usFrameLength = usRcvBufferPos;
|
||||
|
||||
if( xMBSerialPortGetRequest( &pucMBRTUFrame, &usFrameLength ) == FALSE )
|
||||
if( xMBPortSerialGetRequest( &pucMBRTUFrame, &usFrameLength ) == FALSE )
|
||||
{
|
||||
return MB_EIO;
|
||||
}
|
||||
@ -222,7 +222,7 @@ eMBRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength )
|
||||
eSndState = STATE_TX_XMIT;
|
||||
EXIT_CRITICAL_SECTION( );
|
||||
|
||||
if( xMBSerialPortSendResponse( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ) == FALSE )
|
||||
if( xMBPortSerialSendResponse( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ) == FALSE )
|
||||
{
|
||||
eStatus = MB_EIO;
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ eMBMasterRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLengt
|
||||
UCHAR *pucMBRTUFrame = ( UCHAR* ) ucMasterRTURcvBuf;
|
||||
USHORT usFrameLength = usMasterRcvBufferPos;
|
||||
|
||||
if( xMBMasterSerialPortGetResponse( &pucMBRTUFrame, &usFrameLength ) == FALSE )
|
||||
if( xMBMasterPortSerialGetResponse( &pucMBRTUFrame, &usFrameLength ) == FALSE )
|
||||
{
|
||||
return MB_EIO;
|
||||
}
|
||||
@ -231,7 +231,7 @@ eMBMasterRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength
|
||||
/* Activate the transmitter. */
|
||||
eSndState = STATE_M_TX_XMIT;
|
||||
|
||||
if ( xMBMasterSerialPortSendRequest( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount ) == FALSE )
|
||||
if ( xMBMasterPortSerialSendRequest( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount ) == FALSE )
|
||||
{
|
||||
eStatus = MB_EIO;
|
||||
}
|
||||
|
@ -73,13 +73,61 @@ vMBPortSetMode( UCHAR ucMode )
|
||||
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 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;
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
// This function is kept to realize legacy freemodbus frame logging functionality
|
||||
|
@ -260,17 +260,6 @@ BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate,
|
||||
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)vTaskSuspend(xMbTaskHandle);
|
||||
|
@ -52,6 +52,9 @@
|
||||
#include "port_serial_master.h"
|
||||
|
||||
/* ----------------------- 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 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 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)
|
||||
{
|
||||
// This function can be called from xMBRTUTransmitFSM() of different task
|
||||
if (bTxEnable) {
|
||||
vMBMasterRxFlush();
|
||||
bTxStateEnabled = TRUE;
|
||||
} else {
|
||||
bTxStateEnabled = FALSE;
|
||||
}
|
||||
if (bRxEnable) {
|
||||
bRxStateEnabled = TRUE;
|
||||
vMBMasterRxSemaRelease();
|
||||
vTaskResume(xMbTaskHandle); // Resume receiver task
|
||||
} else {
|
||||
vTaskSuspend(xMbTaskHandle); // Block receiver task
|
||||
@ -88,12 +142,12 @@ static USHORT usMBMasterPortSerialRxPoll(size_t xEventSize)
|
||||
BOOL xStatus = TRUE;
|
||||
USHORT usCnt = 0;
|
||||
|
||||
if (bRxStateEnabled) {
|
||||
xStatus = xMBMasterPortRxSemaTake(MB_SERIAL_RX_SEMA_TOUT);
|
||||
if (xStatus) {
|
||||
while(xStatus && (usCnt++ <= xEventSize)) {
|
||||
// Call the Modbus stack callback function and let it fill the stack buffers.
|
||||
xStatus = pxMBMasterFrameCBByteReceived(); // callback to receive FSM
|
||||
}
|
||||
|
||||
// The buffer is transferred into Modbus stack and is not needed here any more
|
||||
uart_flush_input(ucUartNumber);
|
||||
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
|
||||
// data received during configured timeout and UART TOUT feature is triggered
|
||||
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
|
||||
ESP_ERROR_CHECK(uart_get_buffered_data_len(ucUartNumber, &xEvent.size));
|
||||
// Read received data and send it to modbus stack
|
||||
usResult = usMBMasterPortSerialRxPoll(xEvent.size);
|
||||
ESP_LOGD(TAG,"Timeout occured, processed: %d bytes", usResult);
|
||||
// Block receiver task until data is not processed
|
||||
vTaskSuspend(NULL);
|
||||
}
|
||||
break;
|
||||
//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
|
||||
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
|
||||
BaseType_t xStatus = xTaskCreatePinnedToCore(vUartTask, "uart_queue_task",
|
||||
MB_SERIAL_TASK_STACK_SIZE,
|
||||
@ -272,24 +331,6 @@ BOOL xMBMasterPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
|
||||
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)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.
|
||||
url: https://github.com/espressif/esp-modbus
|
||||
dependencies:
|
||||
|
Reference in New Issue
Block a user