freemodbus: update poll event processing

update modbus poll event loop processing to process multiple events
This commit is contained in:
Alex Lisitsyn 2019-12-10 14:27:09 +08:00 committed by Angus Gratton
parent f50df36ebf
commit 44444208b7
10 changed files with 100 additions and 99 deletions

View file

@ -73,6 +73,8 @@ PR_BEGIN_EXTERN_C
*/ */
#define MB_TCP_PORT_USE_DEFAULT 0 #define MB_TCP_PORT_USE_DEFAULT 0
#define MB_FUNC_CODE_MAX 127
/* ----------------------- Type definitions ---------------------------------*/ /* ----------------------- Type definitions ---------------------------------*/
#ifndef _MB_M_H #ifndef _MB_M_H

View file

@ -376,7 +376,8 @@ eMBPoll( void )
if ( !ucMBFrame ) { if ( !ucMBFrame ) {
return MB_EILLSTATE; return MB_EILLSTATE;
} }
ESP_LOGD(MB_PORT_TAG, "%s:EV_EXECUTE", __func__); ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF]; ESP_LOGD(MB_PORT_TAG, "%s:EV_EXECUTE", __func__);
ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF];
eException = MB_EX_ILLEGAL_FUNCTION; eException = MB_EX_ILLEGAL_FUNCTION;
for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ) for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ )
{ {
@ -385,7 +386,7 @@ eMBPoll( void )
{ {
break; break;
} }
else if( xFuncHandlers[i].ucFunctionCode == ucFunctionCode ) if( xFuncHandlers[i].ucFunctionCode == ucFunctionCode )
{ {
eException = xFuncHandlers[i].pxHandler( ucMBFrame, &usLength ); eException = xFuncHandlers[i].pxHandler( ucMBFrame, &usLength );
break; break;

View file

@ -269,7 +269,6 @@ eMBMasterPoll( void )
static UCHAR ucFunctionCode; static UCHAR ucFunctionCode;
static USHORT usLength; static USHORT usLength;
static eMBException eException; static eMBException eException;
int i; int i;
int j; int j;
eMBErrorCode eStatus = MB_ENOERR; eMBErrorCode eStatus = MB_ENOERR;
@ -286,30 +285,14 @@ eMBMasterPoll( void )
* Otherwise we will handle the event. */ * Otherwise we will handle the event. */
if ( xMBMasterPortEventGet( &eEvent ) == TRUE ) if ( xMBMasterPortEventGet( &eEvent ) == TRUE )
{ {
switch ( eEvent ) // In some cases it is possible that more than one event set
{ // together (even from one subset mask) than process them consistently
case EV_MASTER_NO_EVENT: if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_READY ) ) {
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_NO_EVENT", __func__);
// Something went wrong and task unblocked but there are no any events set
assert(0);
break;
case EV_MASTER_PROCESS_SUCCESS:
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_PROCESS_SUCCESS", __func__);
break;
case EV_MASTER_ERROR_RESPOND_TIMEOUT:
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_ERROR_RESPOND_TIMEOUT", __func__);
break;
case EV_MASTER_ERROR_RECEIVE_DATA:
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_ERROR_RECEIVE_DATA", __func__);
break;
case EV_MASTER_ERROR_EXECUTE_FUNCTION:
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_ERROR_EXECUTE_FUNCTION", __func__);
break;
case EV_MASTER_READY:
ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_READY", __func__); ESP_LOGD(MB_PORT_TAG, "%s:EV_MASTER_READY", __func__);
break; MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_READY );
case EV_MASTER_FRAME_RECEIVED: } else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_RECEIVED ) ) {
eStatus = peMBMasterFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength); eStatus = peMBMasterFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength);
ESP_LOG_BUFFER_HEX_LEVEL("POLL RCV buffer:", (void*)ucMBFrame, (uint16_t)usLength, ESP_LOG_DEBUG);
// Check if the frame is for us. If not ,send an error process event. // Check if the frame is for us. If not ,send an error process event.
if ( ( eStatus == MB_ENOERR ) && ( ucRcvAddress == ucMBMasterGetDestAddress() ) ) if ( ( eStatus == MB_ENOERR ) && ( ucRcvAddress == ucMBMasterGetDestAddress() ) )
{ {
@ -319,11 +302,12 @@ eMBMasterPoll( void )
else else
{ {
vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA); vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA);
ESP_LOGD(MB_PORT_TAG, "%s: Packet data receive failed (addr=%u)(%u).", __func__, ucRcvAddress, eStatus); ESP_LOGD( MB_PORT_TAG, "%s: Packet data receive failed (addr=%u)(%u).",
__func__, ucRcvAddress, eStatus);
( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
} }
break; MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_RECEIVED );
case EV_MASTER_EXECUTE: } else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_EXECUTE ) ) {
if ( !ucMBFrame ) if ( !ucMBFrame )
{ {
return MB_EILLSTATE; return MB_EILLSTATE;
@ -335,9 +319,7 @@ eMBMasterPoll( void )
if (ucFunctionCode & MB_FUNC_ERROR) if (ucFunctionCode & MB_FUNC_ERROR)
{ {
eException = (eMBException)ucMBFrame[MB_PDU_DATA_OFF]; eException = (eMBException)ucMBFrame[MB_PDU_DATA_OFF];
} } else {
else
{
for ( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ) for ( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ )
{ {
/* No more function handlers registered. Abort. */ /* No more function handlers registered. Abort. */
@ -380,21 +362,21 @@ eMBMasterPoll( void )
vMBMasterCBRequestSuccess( ); vMBMasterCBRequestSuccess( );
vMBMasterRunResRelease( ); vMBMasterRunResRelease( );
} }
break; MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_EXECUTE );
case 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( &ucMBFrame );
eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBFrame, usMBMasterGetPDUSndLength() ); eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBFrame, usMBMasterGetPDUSndLength() );
if (eStatus != MB_ENOERR) if (eStatus != MB_ENOERR)
{ {
ESP_LOGD(MB_PORT_TAG, "%s:Frame send error. %d", __func__, eStatus); ESP_LOGE( MB_PORT_TAG, "%s:Frame send error. %d", __func__, eStatus );
} }
break; MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_TRANSMIT );
case 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__ );
break; MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_FRAME_SENT );
case EV_MASTER_ERROR_PROCESS: } else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_ERROR_PROCESS ) ) {
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( );
@ -414,20 +396,24 @@ eMBMasterPoll( void )
ucMBFrame, usMBMasterGetPDUSndLength( ) ); ucMBFrame, usMBMasterGetPDUSndLength( ) );
break; break;
default: default:
ESP_LOGD(MB_PORT_TAG, "%s: incorrect error type.", __func__); ESP_LOGE( MB_PORT_TAG, "%s: incorrect error type = %d.", __func__, errorType);
break; break;
} }
vMBMasterRunResRelease( ); vMBMasterRunResRelease( );
break; MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_ERROR_PROCESS );
default: }
ESP_LOGD(MB_PORT_TAG, "%s: incorrect event triggered = %d.", __func__, eEvent); if ( eEvent ) {
break; // Event processing is done, but some poll events still set then
// postpone its processing for next poll cycle (rare case).
ESP_LOGW( MB_PORT_TAG, "%s: Unprocessed event %d.", __func__, eEvent );
( void ) xMBMasterPortEventPost( eEvent );
} }
} else { } else {
// xMBMasterPortEventGet has unbloked the task but the event bits are not set // Something went wrong and task unblocked but there are no any correct events set
ESP_LOGD(MB_PORT_TAG, "%s: task event wait failure.", __func__); ESP_LOGE( MB_PORT_TAG, "%s: Unexpected event triggered %d.", __func__, eEvent );
eStatus = MB_EILLSTATE;
} }
return MB_ENOERR; return eStatus;
} }
// Get whether the Modbus Master is run in master mode. // Get whether the Modbus Master is run in master mode.
@ -497,7 +483,8 @@ eMBMasterTimerMode MB_PORT_ISR_ATTR xMBMasterGetCurTimerMode( void )
} }
/* The master request is broadcast? */ /* The master request is broadcast? */
BOOL MB_PORT_ISR_ATTR xMBMasterRequestIsBroadcast( void ){ BOOL MB_PORT_ISR_ATTR xMBMasterRequestIsBroadcast( void )
{
return xFrameIsBroadcast; return xFrameIsBroadcast;
} }

View file

@ -31,6 +31,7 @@
#define MB_SERIAL_TX_TOUT_MS (100) #define MB_SERIAL_TX_TOUT_MS (100)
#define MB_SERIAL_TX_TOUT_TICKS pdMS_TO_TICKS(MB_SERIAL_TX_TOUT_MS) // timeout for transmission #define MB_SERIAL_TX_TOUT_TICKS pdMS_TO_TICKS(MB_SERIAL_TX_TOUT_MS) // timeout for transmission
#define MB_SERIAL_RX_TOUT_TICKS pdMS_TO_TICKS(1) // timeout for rx from buffer #define MB_SERIAL_RX_TOUT_TICKS pdMS_TO_TICKS(1) // timeout for rx from buffer
#define MB_SERIAL_RESP_LEN_MIN (4)
#define MB_PORT_CHECK(a, ret_val, str, ...) \ #define MB_PORT_CHECK(a, ret_val, str, ...) \
if (!(a)) { \ if (!(a)) { \
@ -70,6 +71,9 @@ void vMBPortExitCritical(void);
#define EXIT_CRITICAL_SECTION( ) { vMBPortExitCritical(); \ #define EXIT_CRITICAL_SECTION( ) { vMBPortExitCritical(); \
ESP_LOGD(MB_PORT_TAG,"%s: Port exit critical", __func__); } ESP_LOGD(MB_PORT_TAG,"%s: Port exit critical", __func__); }
#define MB_PORT_CHECK_EVENT( event, mask ) ( event & mask )
#define MB_PORT_CLEAR_EVENT( event, mask ) do { event &= ~mask; } while(0)
#ifdef __cplusplus #ifdef __cplusplus
PR_END_EXTERN_C PR_END_EXTERN_C
#endif /* __cplusplus */ #endif /* __cplusplus */

View file

@ -62,7 +62,6 @@
EV_MASTER_ERROR_RECEIVE_DATA | \ EV_MASTER_ERROR_RECEIVE_DATA | \
EV_MASTER_ERROR_EXECUTE_FUNCTION ) EV_MASTER_ERROR_EXECUTE_FUNCTION )
#define MB_CHECK_EVENT(event, mask) (event & mask)
/* ----------------------- Variables ----------------------------------------*/ /* ----------------------- Variables ----------------------------------------*/
static SemaphoreHandle_t xSemaphorMasterHdl; static SemaphoreHandle_t xSemaphorMasterHdl;
@ -118,19 +117,19 @@ xMBMasterPortEventGet( eMBMasterEventType * eEvent)
{ {
EventBits_t uxBits; EventBits_t uxBits;
BOOL xEventHappened = FALSE; BOOL xEventHappened = FALSE;
uxBits = xEventGroupWaitBits( uxBits = xEventGroupWaitBits( xEventGroupMasterHdl, // The event group being tested.
xEventGroupMasterHdl, // The event group being tested.
MB_EVENT_POLL_MASK, // The bits within the event group to wait for. MB_EVENT_POLL_MASK, // The bits within the event group to wait for.
pdTRUE, // Masked bits should be cleared before returning. pdTRUE, // Masked bits should be cleared before returning.
pdFALSE, // Don't wait for both bits, either bit will do. pdFALSE, // Don't wait for both bits, either bit will do.
portMAX_DELAY); // Wait forever for either bit to be set. portMAX_DELAY); // Wait forever for either bit to be set.
// Check if poll event is correct // Check if poll event is correct
if (uxBits & MB_EVENT_POLL_MASK) { if (MB_PORT_CHECK_EVENT(uxBits, MB_EVENT_POLL_MASK)) {
*eEvent = (eMBMasterEventType)(uxBits); *eEvent = (eMBMasterEventType)(uxBits & MB_EVENT_POLL_MASK);
xEventHappened = TRUE; xEventHappened = TRUE;
} else { } else {
ESP_LOGE(MB_PORT_TAG,"%s: Incorrect event triggered = %d.", __func__, uxBits); ESP_LOGE(MB_PORT_TAG,"%s: Incorrect event triggered = %d.", __func__, uxBits);
*eEvent = (eMBMasterEventType)uxBits;
xEventHappened = FALSE; xEventHappened = FALSE;
} }
return xEventHappened; return xEventHappened;
@ -258,16 +257,16 @@ eMBMasterReqErrCode eMBMasterWaitRequestFinish( void ) {
if (xRecvedEvent) { if (xRecvedEvent) {
ESP_LOGD(MB_PORT_TAG,"%s: returned event = 0x%x", __func__, xRecvedEvent); ESP_LOGD(MB_PORT_TAG,"%s: returned event = 0x%x", __func__, xRecvedEvent);
if (!(xRecvedEvent & MB_EVENT_REQ_MASK)) { if (!(xRecvedEvent & MB_EVENT_REQ_MASK)) {
// if we wait for certain event bits but get other then set in mask // if we wait for certain event bits but get from poll subset
ESP_LOGE(MB_PORT_TAG,"%s: incorrect event set = 0x%x", __func__, xRecvedEvent); ESP_LOGE(MB_PORT_TAG,"%s: incorrect event set = 0x%x", __func__, xRecvedEvent);
} }
if MB_CHECK_EVENT(xRecvedEvent, EV_MASTER_PROCESS_SUCCESS) { if (MB_PORT_CHECK_EVENT(xRecvedEvent, EV_MASTER_PROCESS_SUCCESS)) {
eErrStatus = MB_MRE_NO_ERR; eErrStatus = MB_MRE_NO_ERR;
} else if MB_CHECK_EVENT(xRecvedEvent, EV_MASTER_ERROR_RESPOND_TIMEOUT){ } else if (MB_PORT_CHECK_EVENT(xRecvedEvent, EV_MASTER_ERROR_RESPOND_TIMEOUT)) {
eErrStatus = MB_MRE_TIMEDOUT; eErrStatus = MB_MRE_TIMEDOUT;
} else if MB_CHECK_EVENT(xRecvedEvent, EV_MASTER_ERROR_RECEIVE_DATA){ } else if (MB_PORT_CHECK_EVENT(xRecvedEvent, EV_MASTER_ERROR_RECEIVE_DATA)) {
eErrStatus = MB_MRE_REV_DATA; eErrStatus = MB_MRE_REV_DATA;
} else if MB_CHECK_EVENT(xRecvedEvent, EV_MASTER_ERROR_EXECUTE_FUNCTION){ } else if (MB_PORT_CHECK_EVENT(xRecvedEvent, EV_MASTER_ERROR_EXECUTE_FUNCTION)) {
eErrStatus = MB_MRE_EXE_FUN; eErrStatus = MB_MRE_EXE_FUN;
} }
} else { } else {

View file

@ -109,7 +109,7 @@ static void vMBPortSerialRxPoll(size_t xEventSize)
USHORT usCnt = 0; USHORT usCnt = 0;
if (bRxStateEnabled) { if (bRxStateEnabled) {
if (xEventSize > 0) { if (xEventSize > MB_SERIAL_RESP_LEN_MIN) {
xEventSize = (xEventSize > MB_SERIAL_BUF_SIZE) ? MB_SERIAL_BUF_SIZE : xEventSize; xEventSize = (xEventSize > MB_SERIAL_BUF_SIZE) ? MB_SERIAL_BUF_SIZE : xEventSize;
// Get received packet into Rx buffer // Get received packet into Rx buffer
for(usCnt = 0; xReadStatus && (usCnt < xEventSize); usCnt++ ) { for(usCnt = 0; xReadStatus && (usCnt < xEventSize); usCnt++ ) {

View file

@ -76,6 +76,9 @@ 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 UCHAR ucBuffer[MB_SERIAL_BUF_SIZE]; // Temporary buffer to transfer received data to modbus stack
static USHORT uiRxBufferPos = 0; // position in the receiver buffer
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
@ -99,12 +102,14 @@ static void vMBMasterPortSerialRxPoll(size_t xEventSize)
USHORT usCnt = 0; USHORT usCnt = 0;
if (bRxStateEnabled) { if (bRxStateEnabled) {
if (xEventSize > 0) { if (xEventSize > MB_SERIAL_RESP_LEN_MIN) {
xEventSize = (xEventSize > MB_SERIAL_BUF_SIZE) ? MB_SERIAL_BUF_SIZE : xEventSize; xEventSize = (xEventSize > MB_SERIAL_BUF_SIZE) ? MB_SERIAL_BUF_SIZE : xEventSize;
// Get received packet into Rx buffer // Get received packet into Rx buffer
for(usCnt = 0; xReadStatus && (usCnt < xEventSize); usCnt++ ) { USHORT usLength = uart_read_bytes(ucUartNumber, &ucBuffer[0], xEventSize, portMAX_DELAY);
uiRxBufferPos = 0;
for(usCnt = 0; xReadStatus && (usCnt < usLength); usCnt++ ) {
// 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.
xReadStatus = pxMBMasterFrameCBByteReceived(); // calls callback xMBRTUReceiveFSM() xReadStatus = pxMBMasterFrameCBByteReceived(); // callback to receive FSM state machine
} }
// 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);
@ -124,7 +129,7 @@ BOOL xMBMasterPortSerialTxPoll(void)
// Continue while all response bytes put in buffer or out of buffer // Continue while all response bytes put in buffer or out of buffer
while((bNeedPoll) && (usCount++ < MB_SERIAL_BUF_SIZE)) { while((bNeedPoll) && (usCount++ < MB_SERIAL_BUF_SIZE)) {
// Calls the modbus stack callback function to let it fill the UART transmit buffer. // Calls the modbus stack callback function to let it fill the UART transmit buffer.
bNeedPoll = pxMBMasterFrameCBTransmitterEmpty( ); // calls callback xMBRTUTransmitFSM(); bNeedPoll = pxMBMasterFrameCBTransmitterEmpty( ); // callback to transmit FSM state machine
} }
ESP_LOGD(TAG, "MB_TX_buffer sent: (%d) bytes.", (uint16_t)(usCount - 1)); ESP_LOGD(TAG, "MB_TX_buffer sent: (%d) bytes.", (uint16_t)(usCount - 1));
// Waits while UART sending the packet // Waits while UART sending the packet
@ -254,6 +259,7 @@ BOOL xMBMasterPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
} else { } else {
vTaskSuspend(xMbTaskHandle); // Suspend serial task while stack is not started vTaskSuspend(xMbTaskHandle); // Suspend serial task while stack is not started
} }
uiRxBufferPos = 0;
ESP_LOGD(MB_PORT_TAG,"%s Init serial.", __func__); ESP_LOGD(MB_PORT_TAG,"%s Init serial.", __func__);
return TRUE; return TRUE;
} }
@ -276,6 +282,9 @@ BOOL xMBMasterPortSerialPutByte(CHAR ucByte)
BOOL xMBMasterPortSerialGetByte(CHAR* pucByte) BOOL xMBMasterPortSerialGetByte(CHAR* pucByte)
{ {
assert(pucByte != NULL); assert(pucByte != NULL);
USHORT usLength = uart_read_bytes(ucUartNumber, (uint8_t*)pucByte, 1, MB_SERIAL_RX_TOUT_TICKS); MB_PORT_CHECK((uiRxBufferPos < MB_SERIAL_BUF_SIZE),
return (usLength == 1); FALSE, "mb stack serial get byte failure.");
*pucByte = ucBuffer[uiRxBufferPos];
uiRxBufferPos++;
return TRUE;
} }

View file

@ -145,7 +145,6 @@ static BOOL xMBMasterPortTimersEnable(USHORT usTimerTics50us)
MB_PORT_CHECK((xErr == ESP_OK), FALSE, MB_PORT_CHECK((xErr == ESP_OK), FALSE,
"timer start failure, timer_start() returned (0x%x).", "timer start failure, timer_start() returned (0x%x).",
(uint32_t)xErr); (uint32_t)xErr);
ESP_LOGD(MB_PORT_TAG,"%s Init timer.", __func__);
return TRUE; return TRUE;
} }

View file

@ -165,7 +165,7 @@ def test_check_mode(dut=None, mode_str=None, value=None):
return False return False
@ttfw_idf.idf_example_test(env_tag='Example_T2_RS485') @ttfw_idf.idf_example_test(env_tag='UT_T2_RS485')
def test_modbus_communication(env, comm_mode): def test_modbus_communication(env, comm_mode):
global logger global logger

View file

@ -276,7 +276,7 @@ example_test_011:
extends: .example_debug_template extends: .example_debug_template
tags: tags:
- ESP32 - ESP32
- Example_T2_RS485 - UT_T2_RS485
artifacts: artifacts:
when: always when: always
expire_in: 1 week expire_in: 1 week