modbus serial fix events misalingnment

This commit is contained in:
aleks
2022-05-12 15:48:55 +02:00
parent 22bd218b10
commit 9ea75ab793
8 changed files with 127 additions and 48 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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,9 @@ 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 );
#endif

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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;
}
static 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,7 +142,8 @@ static USHORT usMBMasterPortSerialRxPoll(size_t xEventSize)
BOOL xReadStatus = TRUE;
USHORT usCnt = 0;
if (bRxStateEnabled) {
xReadStatus = xMBMasterPortRxSemaTake(MB_SERIAL_RX_SEMA_TOUT);
if (xReadStatus) {
while(xReadStatus && (usCnt++ <= xEventSize)) {
// Call the Modbus stack callback function and let it fill the stack buffers.
xReadStatus = pxMBMasterFrameCBByteReceived(); // callback to receive FSM
@ -143,13 +198,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
@ -249,7 +308,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,
@ -268,24 +328,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);