Ver Fonte

freemodbus: fix long buffer failure

check master read write functions with array of registers)
fix master serial processing code and modbus controller to work with register array
modbus_master: add reading and writing of test value array (58 registers) to check failure is gone
remove parameter temporary buffer from modbus controller to allow more than 24 byte writes
driver: fix issue with TOUT feature
driver: fix uart_rx_timeout issue
driver: fix issue with rxfifo_tout_int_raw not triggered when received fifo_len = 120 byte and all bytes read out of fifo as result of rxfifo_full_int_raw
driver: add function uart_internal_set_always_rx_timeout() to always handle tout interrupt
examples: call uart_internal_set_always_rx_timeout() to handle tout interrupt correctly
examples: update examples to use tout feature
driver: reflect changes of uart_set_always_rx_timeout() function, change uart.c
driver: change conditions to trigger workaround for tout feature in uart.c
driver: change uart_set_always_rx_timeout()
freemodbus: fix tabs, remove commented code
driver: remove uart_ll_is_rx_idle()
Alex Lisitsyn há 5 anos atrás
pai
commit
3abdd2207d
26 ficheiros alterados com 387 adições e 305 exclusões
  1. 17 0
      components/driver/include/driver/uart.h
  2. 18 1
      components/driver/uart.c
  3. 0 2
      components/freemodbus/modbus/ascii/mbascii.c
  4. 23 23
      components/freemodbus/modbus/functions/mbfuncdisc_m.c
  5. 68 68
      components/freemodbus/modbus/functions/mbfuncholding_m.c
  6. 16 16
      components/freemodbus/modbus/functions/mbfuncinput_m.c
  7. 4 2
      components/freemodbus/modbus/include/mbframe.h
  8. 1 0
      components/freemodbus/modbus/include/mbport.h
  9. 1 1
      components/freemodbus/modbus/mb.c
  10. 7 4
      components/freemodbus/modbus/mb_m.c
  11. 3 1
      components/freemodbus/modbus/rtu/mbrtu.c
  12. 3 1
      components/freemodbus/modbus/rtu/mbrtu_m.c
  13. 14 1
      components/freemodbus/port/port.h
  14. 2 2
      components/freemodbus/port/portevent_m.c
  15. 28 39
      components/freemodbus/port/portserial.c
  16. 25 39
      components/freemodbus/port/portserial_m.c
  17. 5 5
      components/freemodbus/port/porttimer.c
  18. 7 55
      components/freemodbus/serial_master/modbus_controller/mbc_serial_master.c
  19. 23 4
      components/soc/include/hal/uart_hal.h
  20. 24 4
      components/soc/src/esp32/include/hal/uart_ll.h
  21. 16 0
      components/soc/src/esp32s2/include/hal/uart_ll.h
  22. 3 3
      components/soc/src/hal/uart_hal_iram.c
  23. 1 1
      examples/protocols/modbus/serial/example_test.py
  24. 1 0
      examples/protocols/modbus/serial/mb_example_common/include/modbus_params.h
  25. 76 32
      examples/protocols/modbus/serial/mb_master/main/master.c
  26. 1 1
      examples/protocols/modbus/serial/mb_slave/main/slave.c

+ 17 - 0
components/driver/include/driver/uart.h

@@ -70,6 +70,8 @@ typedef enum {
 typedef struct {
     uart_event_type_t type; /*!< UART event type */
     size_t size;            /*!< UART data size for UART_DATA event*/
+    bool timeout_flag;      /*!< UART data read timeout flag for UART_DATA event (no new data received during configured RX TOUT)*/
+                            /*!< If the event is caused by FIFO-full interrupt, then there will be no event with the timeout flag before the next byte coming.*/
 } uart_event_t;
 
 typedef intr_handle_t uart_isr_handle_t;
@@ -845,6 +847,21 @@ esp_err_t uart_wait_tx_idle_polling(uart_port_t uart_num);
   */
 esp_err_t uart_set_loop_back(uart_port_t uart_num, bool loop_back_en);
 
+/**
+  * @brief Configure behavior of UART RX timeout interrupt.
+  *
+  * When always_rx_timeout is true, timeout interrupt is triggered even if FIFO is full.
+  * This function can cause extra timeout interrupts triggered only to send the timeout event.
+  * Call this function only if you want to ensure timeout interrupt will always happen after a byte stream.
+  *
+  * @param uart_num UART number
+  * @param always_rx_timeout_en Set to false enable the default behavior of timeout interrupt,
+  *                             set it to true to always trigger timeout interrupt.
+  *
+  * * @return None
+  */
+void uart_set_always_rx_timeout(uart_port_t uart_num, bool always_rx_timeout_en);
+
 #ifdef __cplusplus
 }
 #endif

+ 18 - 1
components/driver/uart.c

@@ -104,6 +104,7 @@ typedef struct {
     intr_handle_t intr_handle;          /*!< UART interrupt handle*/
     uart_mode_t uart_mode;              /*!< UART controller actual mode set by uart_set_mode() */
     bool coll_det_flg;                  /*!< UART collision detection flag */
+    bool rx_always_timeout_flg;         /*!< UART always detect rx timeout flag */
 
     //rx parameters
     int rx_buffered_len;                  /*!< UART cached data length */
@@ -808,6 +809,10 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
                 pat_flg = 0;
             }
             if (p_uart->rx_buffer_full_flg == false) {
+                rx_fifo_len = uart_hal_get_rxfifo_len(&(uart_context[uart_num].hal));
+                if ((p_uart_obj[uart_num]->rx_always_timeout_flg) && !(uart_intr_status & UART_INTR_RXFIFO_TOUT)) {
+                    rx_fifo_len--; // leave one byte in the fifo in order to trigger uart_intr_rxfifo_tout
+                }
                 uart_hal_read_rxfifo(&(uart_context[uart_num].hal), p_uart->rx_data_buf, &rx_fifo_len);
                 uint8_t pat_chr = 0;
                 uint8_t pat_num = 0;
@@ -825,6 +830,7 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
                     uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_RXFIFO_TOUT | UART_INTR_RXFIFO_FULL);
                     uart_event.type = UART_DATA;
                     uart_event.size = rx_fifo_len;
+                    uart_event.timeout_flag = (uart_intr_status & UART_INTR_RXFIFO_TOUT) ? true : false;
                     UART_ENTER_CRITICAL_ISR(&uart_selectlock);
                     if (p_uart->uart_select_notif_callback) {
                         p_uart->uart_select_notif_callback(uart_num, UART_SELECT_READ_NOTIF, &HPTaskAwoken);
@@ -1296,6 +1302,7 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b
         p_uart_obj[uart_num]->uart_num = uart_num;
         p_uart_obj[uart_num]->uart_mode = UART_MODE_UART;
         p_uart_obj[uart_num]->coll_det_flg = false;
+        p_uart_obj[uart_num]->rx_always_timeout_flg = false;
         p_uart_obj[uart_num]->tx_fifo_sem = xSemaphoreCreateBinary();
         xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem);
         p_uart_obj[uart_num]->tx_done_sem = xSemaphoreCreateBinary();
@@ -1342,7 +1349,7 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b
         .intr_enable_mask = UART_INTR_CONFIG_FLAG,
         .rxfifo_full_thresh = UART_FULL_THRESH_DEFAULT,
         .rx_timeout_thresh = UART_TOUT_THRESH_DEFAULT,
-        .txfifo_empty_intr_thresh = UART_EMPTY_THRESH_DEFAULT
+        .txfifo_empty_intr_thresh = UART_EMPTY_THRESH_DEFAULT,
     };
     uart_module_enable(uart_num);
     uart_hal_disable_intr_mask(&(uart_context[uart_num].hal), UART_INTR_MASK);
@@ -1549,3 +1556,13 @@ esp_err_t uart_set_loop_back(uart_port_t uart_num, bool loop_back_en)
     uart_hal_set_loop_back(&(uart_context[uart_num].hal), loop_back_en);
     return ESP_OK;
 }
+
+void uart_set_always_rx_timeout(uart_port_t uart_num, bool always_rx_timeout)
+{
+    uint16_t rx_tout = uart_hal_get_rx_tout_thr(&(uart_context[uart_num].hal));
+    if (rx_tout) {
+        p_uart_obj[uart_num]->rx_always_timeout_flg = always_rx_timeout;
+    } else {
+        p_uart_obj[uart_num]->rx_always_timeout_flg = false;
+    }
+}

+ 0 - 2
components/freemodbus/modbus/ascii/mbascii.c

@@ -382,8 +382,6 @@ xMBASCIITransmitFSM( void )
         eSndState = STATE_TX_IDLE;
         xMBPortEventPost( EV_FRAME_TRANSMIT );
         xNeedPoll = FALSE;
-
-        eSndState = STATE_TX_IDLE;
         break;
 
         /* We should not get a transmitter event if the transmitter is in

+ 23 - 23
components/freemodbus/modbus/functions/mbfuncdisc_m.c

@@ -79,16 +79,16 @@ eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT u
     else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
     else
     {
-		vMBMasterGetPDUSndBuf(&ucMBFrame);
-		vMBMasterSetDestAddress(ucSndAddr);
-		ucMBFrame[MB_PDU_FUNC_OFF]                 = MB_FUNC_READ_DISCRETE_INPUTS;
-		ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF]        = usDiscreteAddr >> 8;
-		ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1]    = usDiscreteAddr;
-		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 );
-		eErrStatus = eMBMasterWaitRequestFinish( );
+        vMBMasterGetPDUSndBuf(&ucMBFrame);
+        vMBMasterSetDestAddress(ucSndAddr);
+        ucMBFrame[MB_PDU_FUNC_OFF]                 = MB_FUNC_READ_DISCRETE_INPUTS;
+        ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF]        = usDiscreteAddr >> 8;
+        ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1]    = usDiscreteAddr;
+        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 );
+        eErrStatus = eMBMasterWaitRequestFinish( );
     }
     return eErrStatus;
 }
@@ -107,11 +107,11 @@ eMBMasterFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen )
     /* If this request is broadcast, and it's read mode. This request don't need execute. */
     if ( xMBMasterRequestIsBroadcast() )
     {
-    	eStatus = MB_EX_NONE;
+        eStatus = MB_EX_NONE;
     }
     else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
     {
-    	vMBMasterGetPDUSndBuf(&ucMBFrame);
+        vMBMasterGetPDUSndBuf(&ucMBFrame);
         usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 );
         usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] );
         usRegAddress++;
@@ -123,26 +123,26 @@ eMBMasterFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen )
          * byte is only partially field with unused coils set to zero. */
         if( ( usDiscreteCnt & 0x0007 ) != 0 )
         {
-        	ucNBytes = ( UCHAR )( usDiscreteCnt / 8 + 1 );
+            ucNBytes = ( UCHAR )( usDiscreteCnt / 8 + 1 );
         }
         else
         {
-        	ucNBytes = ( UCHAR )( usDiscreteCnt / 8 );
+            ucNBytes = ( UCHAR )( usDiscreteCnt / 8 );
         }
 
         /* Check if the number of registers to read is valid. If not
          * return Modbus illegal data value exception. 
          */
-		if ((usDiscreteCnt >= 1) && ucNBytes == pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF])
+        if ((usDiscreteCnt >= 1) && ucNBytes == pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF])
         {
-	       	/* Make callback to fill the buffer. */
-			eRegStatus = eMBMasterRegDiscreteCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usDiscreteCnt );
-
-			/* If an error occured convert it into a Modbus exception. */
-			if( eRegStatus != MB_ENOERR )
-			{
-				eStatus = prveMBError2Exception( eRegStatus );
-			}
+            /* Make callback to fill the buffer. */
+            eRegStatus = eMBMasterRegDiscreteCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usDiscreteCnt );
+
+            /* If an error occured convert it into a Modbus exception. */
+            if( eRegStatus != MB_ENOERR )
+            {
+                eStatus = prveMBError2Exception( eRegStatus );
+            }
         }
         else
         {

+ 68 - 68
components/freemodbus/modbus/functions/mbfuncholding_m.c

@@ -107,16 +107,16 @@ eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRe
     else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
     else
     {
-		vMBMasterGetPDUSndBuf(&ucMBFrame);
-		vMBMasterSetDestAddress(ucSndAddr);
-		ucMBFrame[MB_PDU_FUNC_OFF]                = MB_FUNC_WRITE_REGISTER;
-		ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF]      = usRegAddr >> 8;
-		ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF + 1]  = usRegAddr;
-		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 );
-		eErrStatus = eMBMasterWaitRequestFinish( );
+        vMBMasterGetPDUSndBuf(&ucMBFrame);
+        vMBMasterSetDestAddress(ucSndAddr);
+        ucMBFrame[MB_PDU_FUNC_OFF]                = MB_FUNC_WRITE_REGISTER;
+        ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF]      = usRegAddr >> 8;
+        ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF + 1]  = usRegAddr;
+        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 );
+        eErrStatus = eMBMasterWaitRequestFinish( );
     }
     return eErrStatus;
 }
@@ -168,7 +168,7 @@ eMBMasterFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
  */
 eMBMasterReqErrCode
 eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr,
-		USHORT usRegAddr, USHORT usNRegs, USHORT * pusDataBuffer, LONG lTimeOut )
+        USHORT usRegAddr, USHORT usNRegs, USHORT * pusDataBuffer, LONG lTimeOut )
 {
     UCHAR                 *ucMBFrame;
     USHORT                 usRegIndex = 0;
@@ -178,23 +178,23 @@ eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr,
     else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
     else
     {
-		vMBMasterGetPDUSndBuf(&ucMBFrame);
-		vMBMasterSetDestAddress(ucSndAddr);
-		ucMBFrame[MB_PDU_FUNC_OFF]                     = MB_FUNC_WRITE_MULTIPLE_REGISTERS;
-		ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF]       = usRegAddr >> 8;
-		ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1]   = usRegAddr;
-		ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF]     = usNRegs >> 8;
-		ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF + 1] = usNRegs ;
-		ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF]    = usNRegs * 2;
-		ucMBFrame += MB_PDU_REQ_WRITE_MUL_VALUES_OFF;
-		while( usNRegs > usRegIndex)
-		{
-			*ucMBFrame++ = pusDataBuffer[usRegIndex] >> 8;
-			*ucMBFrame++ = pusDataBuffer[usRegIndex++] ;
-		}
-		vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + 2*usNRegs );
-		( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT );
-		eErrStatus = eMBMasterWaitRequestFinish( );
+        vMBMasterGetPDUSndBuf(&ucMBFrame);
+        vMBMasterSetDestAddress(ucSndAddr);
+        ucMBFrame[MB_PDU_FUNC_OFF]                     = MB_FUNC_WRITE_MULTIPLE_REGISTERS;
+        ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF]       = usRegAddr >> 8;
+        ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1]   = usRegAddr;
+        ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF]     = usNRegs >> 8;
+        ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF + 1] = usNRegs ;
+        ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF]    = usNRegs * 2;
+        ucMBFrame += MB_PDU_REQ_WRITE_MUL_VALUES_OFF;
+        while( usNRegs > usRegIndex)
+        {
+            *ucMBFrame++ = pusDataBuffer[usRegIndex] >> 8;
+            *ucMBFrame++ = pusDataBuffer[usRegIndex++] ;
+        }
+        vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + 2*usNRegs );
+        ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT );
+        eErrStatus = eMBMasterWaitRequestFinish( );
     }
     return eErrStatus;
 }
@@ -213,7 +213,7 @@ eMBMasterFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
     /* If this request is broadcast, the *usLen is not need check. */
     if( ( *usLen == MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_MUL_SIZE ) || xMBMasterRequestIsBroadcast() )
     {
-		vMBMasterGetPDUSndBuf(&ucMBFrame);
+        vMBMasterGetPDUSndBuf(&ucMBFrame);
         usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] << 8 );
         usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1] );
         usRegAddress++;
@@ -271,16 +271,16 @@ eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRe
     else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
     else
     {
-		vMBMasterGetPDUSndBuf(&ucMBFrame);
-		vMBMasterSetDestAddress(ucSndAddr);
-		ucMBFrame[MB_PDU_FUNC_OFF]                = MB_FUNC_READ_HOLDING_REGISTER;
-		ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF]       = usRegAddr >> 8;
-		ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1]   = usRegAddr;
-		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 );
-		eErrStatus = eMBMasterWaitRequestFinish( );
+        vMBMasterGetPDUSndBuf(&ucMBFrame);
+        vMBMasterSetDestAddress(ucSndAddr);
+        ucMBFrame[MB_PDU_FUNC_OFF]                = MB_FUNC_READ_HOLDING_REGISTER;
+        ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF]       = usRegAddr >> 8;
+        ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1]   = usRegAddr;
+        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 );
+        eErrStatus = eMBMasterWaitRequestFinish( );
     }
     return eErrStatus;
 }
@@ -298,11 +298,11 @@ eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
     /* If this request is broadcast, and it's read mode. This request don't need execute. */
     if ( xMBMasterRequestIsBroadcast() )
     {
-    	eStatus = MB_EX_NONE;
+        eStatus = MB_EX_NONE;
     }
     else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
     {
-		vMBMasterGetPDUSndBuf(&ucMBFrame);
+        vMBMasterGetPDUSndBuf(&ucMBFrame);
         usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 );
         usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] );
         usRegAddress++;
@@ -355,8 +355,8 @@ eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
  */
 eMBMasterReqErrCode
 eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr,
-		USHORT usReadRegAddr, USHORT usNReadRegs, USHORT * pusDataBuffer,
-		USHORT usWriteRegAddr, USHORT usNWriteRegs, LONG lTimeOut )
+        USHORT usReadRegAddr, USHORT usNReadRegs, USHORT * pusDataBuffer,
+        USHORT usWriteRegAddr, USHORT usNWriteRegs, LONG lTimeOut )
 {
     UCHAR                 *ucMBFrame;
     USHORT                 usRegIndex = 0;
@@ -366,27 +366,27 @@ eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr,
     else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
     else
     {
-		vMBMasterGetPDUSndBuf(&ucMBFrame);
-		vMBMasterSetDestAddress(ucSndAddr);
-		ucMBFrame[MB_PDU_FUNC_OFF]                           = MB_FUNC_READWRITE_MULTIPLE_REGISTERS;
-		ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF]        = usReadRegAddr >> 8;
-		ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF + 1]    = usReadRegAddr;
-		ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF]      = usNReadRegs >> 8;
-		ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF + 1]  = usNReadRegs ;
-		ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF]       = usWriteRegAddr >> 8;
-		ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF + 1]   = usWriteRegAddr;
-		ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF]     = usNWriteRegs >> 8;
-		ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF + 1] = usNWriteRegs ;
-		ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_BYTECNT_OFF]    = usNWriteRegs * 2;
-		ucMBFrame += MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF;
-		while( usNWriteRegs > usRegIndex)
-		{
-			*ucMBFrame++ = pusDataBuffer[usRegIndex] >> 8;
-			*ucMBFrame++ = pusDataBuffer[usRegIndex++] ;
-		}
-		vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READWRITE_SIZE_MIN + 2*usNWriteRegs );
-		( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT );
-		eErrStatus = eMBMasterWaitRequestFinish( );
+        vMBMasterGetPDUSndBuf(&ucMBFrame);
+        vMBMasterSetDestAddress(ucSndAddr);
+        ucMBFrame[MB_PDU_FUNC_OFF]                           = MB_FUNC_READWRITE_MULTIPLE_REGISTERS;
+        ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF]        = usReadRegAddr >> 8;
+        ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF + 1]    = usReadRegAddr;
+        ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF]      = usNReadRegs >> 8;
+        ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF + 1]  = usNReadRegs ;
+        ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF]       = usWriteRegAddr >> 8;
+        ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF + 1]   = usWriteRegAddr;
+        ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF]     = usNWriteRegs >> 8;
+        ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF + 1] = usNWriteRegs ;
+        ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_BYTECNT_OFF]    = usNWriteRegs * 2;
+        ucMBFrame += MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF;
+        while( usNWriteRegs > usRegIndex)
+        {
+            *ucMBFrame++ = pusDataBuffer[usRegIndex] >> 8;
+            *ucMBFrame++ = pusDataBuffer[usRegIndex++] ;
+        }
+        vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READWRITE_SIZE_MIN + 2*usNWriteRegs );
+        ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_TRANSMIT );
+        eErrStatus = eMBMasterWaitRequestFinish( );
     }
     return eErrStatus;
 }
@@ -406,11 +406,11 @@ eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen
     /* If this request is broadcast, and it's read mode. This request don't need execute. */
     if ( xMBMasterRequestIsBroadcast() )
     {
-    	eStatus = MB_EX_NONE;
+        eStatus = MB_EX_NONE;
     }
     else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READWRITE_SIZE_MIN )
     {
-    	vMBMasterGetPDUSndBuf(&ucMBFrame);
+        vMBMasterGetPDUSndBuf(&ucMBFrame);
         usRegReadAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF] << 8U );
         usRegReadAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF + 1] );
         usRegReadAddress++;
@@ -434,8 +434,8 @@ eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen
             if( eRegStatus == MB_ENOERR )
             {
                 /* Make the read callback. */
-				eRegStatus = eMBMasterRegHoldingCB(&pucFrame[MB_PDU_FUNC_READWRITE_READ_VALUES_OFF],
-						                      usRegReadAddress, usRegReadCount, MB_REG_READ);
+                eRegStatus = eMBMasterRegHoldingCB(&pucFrame[MB_PDU_FUNC_READWRITE_READ_VALUES_OFF],
+                                              usRegReadAddress, usRegReadCount, MB_REG_READ);
             }
             if( eRegStatus != MB_ENOERR )
             {

+ 16 - 16
components/freemodbus/modbus/functions/mbfuncinput_m.c

@@ -78,16 +78,16 @@ eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs
     else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY;
     else
     {
-		vMBMasterGetPDUSndBuf(&ucMBFrame);
-		vMBMasterSetDestAddress(ucSndAddr);
-		ucMBFrame[MB_PDU_FUNC_OFF]                = MB_FUNC_READ_INPUT_REGISTER;
-		ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF]       = usRegAddr >> 8;
-		ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1]   = usRegAddr;
-		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 );
-		eErrStatus = eMBMasterWaitRequestFinish( );
+        vMBMasterGetPDUSndBuf(&ucMBFrame);
+        vMBMasterSetDestAddress(ucSndAddr);
+        ucMBFrame[MB_PDU_FUNC_OFF]                = MB_FUNC_READ_INPUT_REGISTER;
+        ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF]       = usRegAddr >> 8;
+        ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1]   = usRegAddr;
+        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 );
+        eErrStatus = eMBMasterWaitRequestFinish( );
     }
     return eErrStatus;
 }
@@ -103,13 +103,13 @@ eMBMasterFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen )
     eMBErrorCode    eRegStatus;
 
     /* If this request is broadcast, and it's read mode. This request don't need execute. */
-	if ( xMBMasterRequestIsBroadcast() )
-	{
-		eStatus = MB_EX_NONE;
-	}
-	else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
+    if ( xMBMasterRequestIsBroadcast() )
     {
-		vMBMasterGetPDUSndBuf(&ucMBFrame);
+        eStatus = MB_EX_NONE;
+    }
+    else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN )
+    {
+        vMBMasterGetPDUSndBuf(&ucMBFrame);
         usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 );
         usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] );
         usRegAddress++;

+ 4 - 2
components/freemodbus/modbus/include/mbframe.h

@@ -31,6 +31,8 @@
 #ifndef _MB_FRAME_H
 #define _MB_FRAME_H
 
+#include "port.h"
+
 #ifdef __cplusplus
 PR_BEGIN_EXTERN_C
 #endif
@@ -61,12 +63,12 @@ PR_BEGIN_EXTERN_C
  */
 
 /* ----------------------- Defines ------------------------------------------*/
-#define MB_PDU_SIZE_MAX     253 /*!< Maximum size of a PDU. */
+#define MB_PDU_SIZE_MAX     ( 253 ) /*!< Maximum size of a PDU. */
 #define MB_PDU_SIZE_MIN     1   /*!< Function Code */
 #define MB_PDU_FUNC_OFF     0   /*!< Offset of function code in PDU. */
 #define MB_PDU_DATA_OFF     1   /*!< Offset for response data in PDU. */
 
-#define MB_SER_PDU_SIZE_MAX 256 /*!< Maximum size of a Modbus frame. */
+#define MB_SER_PDU_SIZE_MAX ( MB_SERIAL_BUF_SIZE ) /*!< Maximum size of a Modbus frame. */
 #define MB_SER_PDU_SIZE_LRC 1   /*!< Size of LRC field in PDU. */
 #define MB_SER_PDU_ADDR_OFF 0   /*!< Offset of slave address in Ser-PDU. */
 #define MB_SER_PDU_PDU_OFF  1   /*!< Offset of Modbus-PDU in Ser-PDU. */

+ 1 - 0
components/freemodbus/modbus/include/mbport.h

@@ -81,6 +81,7 @@ typedef enum {
     EV_ERROR_RESPOND_TIMEOUT,  /*!< Slave respond timeout. */
     EV_ERROR_RECEIVE_DATA,     /*!< Receive frame data erroe. */
     EV_ERROR_EXECUTE_FUNCTION, /*!< Execute function error. */
+    EV_ERROR_OK,               /*!< Data processed. */
 } eMBMasterErrorEventType;
 #endif
 

+ 1 - 1
components/freemodbus/modbus/mb.c

@@ -62,7 +62,7 @@
 static UCHAR    ucMBAddress;
 static eMBMode  eMBCurrentMode;
 
-volatile UCHAR ucMbSlaveBuf[MB_SER_PDU_SIZE_MAX];
+volatile UCHAR ucMbSlaveBuf[MB_SERIAL_BUF_SIZE];
 
 static enum
 {

+ 7 - 4
components/freemodbus/modbus/mb_m.c

@@ -69,8 +69,8 @@ static volatile USHORT  usMasterSendPDULength;
 
 /*------------------------ Shared variables ---------------------------------*/
 
-volatile UCHAR  ucMasterSndBuf[MB_PDU_SIZE_MAX];
-volatile UCHAR  ucMasterRcvBuf[MB_SER_PDU_SIZE_MAX];
+volatile UCHAR  ucMasterSndBuf[MB_SERIAL_BUF_SIZE];
+volatile UCHAR  ucMasterRcvBuf[MB_SERIAL_BUF_SIZE];
 volatile eMBMasterTimerMode eMasterCurTimerMode;
 volatile BOOL   xFrameIsBroadcast = FALSE;
 
@@ -359,8 +359,8 @@ eMBMasterPoll( void )
             }
             else
             {
-                vMBMasterCBRequestSuccess( );
-                vMBMasterRunResRelease( );
+                vMBMasterSetErrorType(EV_ERROR_OK);
+                ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS );
             }
             MB_PORT_CLEAR_EVENT( eEvent, EV_MASTER_EXECUTE );
         } else if ( MB_PORT_CHECK_EVENT( eEvent, EV_MASTER_FRAME_TRANSMIT ) ) {
@@ -395,6 +395,9 @@ eMBMasterPoll( void )
                     vMBMasterErrorCBExecuteFunction( ucMBMasterGetDestAddress( ),
                             ucMBFrame, usMBMasterGetPDUSndLength( ) );
                     break;
+                case EV_ERROR_OK:
+                    vMBMasterCBRequestSuccess( );
+                    break;
                 default:
                     ESP_LOGE( MB_PORT_TAG, "%s: incorrect error type = %d.", __func__, errorType);
                     break;

+ 3 - 1
components/freemodbus/modbus/rtu/mbrtu.c

@@ -265,7 +265,9 @@ xMBRTUReceiveFSM( void )
     case STATE_RX_RCV:
         if( usRcvBufferPos < MB_SER_PDU_SIZE_MAX )
         {
-            ucRTUBuf[usRcvBufferPos++] = ucByte;
+            if ( xStatus ) {
+                ucRTUBuf[usRcvBufferPos++] = ucByte;
+            }
         }
         else
         {

+ 3 - 1
components/freemodbus/modbus/rtu/mbrtu_m.c

@@ -281,7 +281,9 @@ xMBMasterRTUReceiveFSM( void )
     case STATE_M_RX_RCV:
         if( usMasterRcvBufferPos < MB_SER_PDU_SIZE_MAX )
         {
-            ucMasterRTURcvBuf[usMasterRcvBufferPos++] = ucByte;
+            if ( xStatus ) {
+                ucMasterRTURcvBuf[usMasterRcvBufferPos++] = ucByte;
+            }
         }
         else
         {

+ 14 - 1
components/freemodbus/port/port.h

@@ -19,6 +19,7 @@
 #include "freertos/FreeRTOS.h"
 #include "freertos/xtensa_api.h"
 #include "esp_log.h"                // for ESP_LOGE macro
+#include "sdkconfig.h"
 
 #define INLINE                      inline
 #define PR_BEGIN_EXTERN_C           extern "C" {
@@ -26,10 +27,22 @@
 
 #define MB_PORT_TAG "MB_PORT_COMMON"
 
+#define MB_BAUD_RATE_DEFAULT        (115200)
+#define MB_QUEUE_LENGTH             (CONFIG_FMB_QUEUE_LENGTH)
+
+#define MB_SERIAL_TASK_PRIO         (CONFIG_FMB_SERIAL_TASK_PRIO)
+#define MB_SERIAL_TASK_STACK_SIZE   (CONFIG_FMB_SERIAL_TASK_STACK_SIZE)
+#define MB_SERIAL_TOUT              (3) // 3.5*8 = 28 ticks, TOUT=3 -> ~24..33 ticks
+
+// Set buffer size for transmission
+#define MB_SERIAL_BUF_SIZE          (CONFIG_FMB_SERIAL_BUF_SIZE)
+
 // common definitions for serial port implementations
 #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_RX_TOUT_TICKS     pdMS_TO_TICKS(1) // timeout for rx from buffer
+#define MB_SERIAL_RX_TOUT_MS        (1)
+#define MB_SERIAL_RX_TOUT_TICKS     pdMS_TO_TICKS(MB_SERIAL_RX_TOUT_MS) // timeout for receive
+
 #define MB_SERIAL_RESP_LEN_MIN      (4)
 
 #define MB_PORT_CHECK(a, ret_val, str, ...) \

+ 2 - 2
components/freemodbus/port/portevent_m.c

@@ -217,7 +217,7 @@ void vMBMasterErrorCBExecuteFunction(UCHAR ucDestAddress, const UCHAR* pucPDUDat
 {
     BOOL ret = xMBMasterPortEventPost(EV_MASTER_ERROR_EXECUTE_FUNCTION);
     MB_PORT_CHECK((ret == TRUE), ; , "%s: Post event 'EV_MASTER_ERROR_EXECUTE_FUNCTION' failed!", __func__);
-    ESP_LOGD(MB_PORT_TAG,"%s:Callback execute data timeout failure.", __func__);
+    ESP_LOGD(MB_PORT_TAG,"%s:Callback execute data handler failure.", __func__);
 }
 
 /**
@@ -252,7 +252,7 @@ eMBMasterReqErrCode eMBMasterWaitRequestFinish( void ) {
                                                 MB_EVENT_REQ_MASK,  // The bits within the event group to wait for.
                                                 pdTRUE,             // Masked bits should be cleared before returning.
                                                 pdFALSE,            // Don't wait for both bits, either bit will do.
-                                                portMAX_DELAY );    // Wait forever for either bit to be set.
+                                                1000 );             // Wait forever for either bit to be set. //portMAX_DELAY
     xRecvedEvent = (eMBMasterEventType)(uxBits);
     if (xRecvedEvent) {
         ESP_LOGD(MB_PORT_TAG,"%s: returned event = 0x%x", __func__, xRecvedEvent);

+ 28 - 39
components/freemodbus/port/portserial.c

@@ -55,25 +55,6 @@
 #include "sdkconfig.h"              // for KConfig options
 #include "port_serial_slave.h"
 
-// Definitions of UART default pin numbers
-#define MB_UART_RXD   (CONFIG_MB_UART_RXD)
-#define MB_UART_TXD   (CONFIG_MB_UART_TXD)
-#define MB_UART_RTS   (CONFIG_MB_UART_RTS)
-
-#define MB_BAUD_RATE_DEFAULT        (115200)
-#define MB_QUEUE_LENGTH             (CONFIG_FMB_QUEUE_LENGTH)
-
-#define MB_SERIAL_TASK_PRIO         (CONFIG_FMB_SERIAL_TASK_PRIO)
-#define MB_SERIAL_TASK_STACK_SIZE   (CONFIG_FMB_SERIAL_TASK_STACK_SIZE)
-#define MB_SERIAL_TOUT              (3) // 3.5*8 = 28 ticks, TOUT=3 -> ~24..33 ticks
-
-#define MB_SERIAL_TX_TOUT_MS        (100)
-#define MB_SERIAL_TX_TOUT_TICKS     pdMS_TO_TICKS(MB_SERIAL_TX_TOUT_MS) // timeout for transmission
-// Set buffer size for transmission
-#define MB_SERIAL_BUF_SIZE          (CONFIG_FMB_SERIAL_BUF_SIZE)
-
-// Note: This code uses mixed coding standard from legacy IDF code and used freemodbus stack
-
 // A queue to handle UART event.
 static QueueHandle_t xMbUartQueue;
 static TaskHandle_t  xMbTaskHandle;
@@ -103,28 +84,26 @@ void vMBPortSerialEnable(BOOL bRxEnable, BOOL bTxEnable)
     }
 }
 
-static void vMBPortSerialRxPoll(size_t xEventSize)
+static USHORT usMBPortSerialRxPoll(size_t xEventSize)
 {
     BOOL xReadStatus = TRUE;
     USHORT usCnt = 0;
 
     if (bRxStateEnabled) {
-        if (xEventSize > MB_SERIAL_RESP_LEN_MIN) {
-            xEventSize = (xEventSize > MB_SERIAL_BUF_SIZE) ?  MB_SERIAL_BUF_SIZE : xEventSize;
-            // Get received packet into Rx buffer
-            for(usCnt = 0; xReadStatus && (usCnt < xEventSize); usCnt++ ) {
-                // Call the Modbus stack callback function and let it fill the buffers.
-                xReadStatus = pxMBFrameCBByteReceived(); // callback to execute receive FSM state machine
-            }
-            uart_flush_input(ucUartNumber);
-            // Send event EV_FRAME_RECEIVED to allow stack process packet
-#ifndef MB_TIMER_PORT_ENABLED
-            // Let the stack know that T3.5 time is expired and data is received
-            (void)pxMBPortCBTimerExpired(); // calls callback xMBRTUTimerT35Expired();
-#endif
-            ESP_LOGD(TAG, "RX: %d bytes\n", usCnt);
+        // Get received packet into Rx buffer
+        while(xReadStatus && (usCnt++ <= MB_SERIAL_BUF_SIZE)) {
+            // Call the Modbus stack callback function and let it fill the buffers.
+            xReadStatus = pxMBFrameCBByteReceived(); // callback to execute receive FSM
         }
+        uart_flush_input(ucUartNumber);
+        // Send event EV_FRAME_RECEIVED to allow stack process packet
+#if !CONFIG_FMB_TIMER_PORT_ENABLED
+        // Let the stack know that T3.5 time is expired and data is received
+        (void)pxMBPortCBTimerExpired(); // calls callback xMBRTUTimerT35Expired();
+#endif
+        ESP_LOGD(TAG, "RX: %d bytes\n", usCnt);
     }
+    return usCnt;
 }
 
 BOOL xMBPortSerialTxPoll(void)
@@ -136,7 +115,7 @@ BOOL xMBPortSerialTxPoll(void)
         // Continue while all response bytes put in buffer or out of buffer
         while((bNeedPoll) && (usCount++ < MB_SERIAL_BUF_SIZE)) {
             // Calls the modbus stack callback function to let it fill the UART transmit buffer.
-            bNeedPoll = pxMBFrameCBTransmitterEmpty( ); // callback to transmit FSM state machine
+            bNeedPoll = pxMBFrameCBTransmitterEmpty( ); // callback to transmit FSM
         }
         ESP_LOGD(TAG, "MB_TX_buffer send: (%d) bytes\n", (uint16_t)usCount);
         // Waits while UART sending the packet
@@ -151,15 +130,21 @@ BOOL xMBPortSerialTxPoll(void)
 static void vUartTask(void *pvParameters)
 {
     uart_event_t xEvent;
+    USHORT usResult = 0;
     for(;;) {
         if (xQueueReceive(xMbUartQueue, (void*)&xEvent, portMAX_DELAY) == pdTRUE) {
             ESP_LOGD(TAG, "MB_uart[%d] event:", ucUartNumber);
             switch(xEvent.type) {
                 //Event of UART receving data
                 case UART_DATA:
-                    ESP_LOGD(TAG,"Receive data, len: %d", xEvent.size);
-                    // Read received data and send it to modbus stack
-                    vMBPortSerialRxPoll(xEvent.size);
+                    ESP_LOGD(TAG,"Data event, length: %d", xEvent.size);
+                    // 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) {
+                        // Read received data and send it to modbus stack
+                        usResult = usMBPortSerialRxPoll(xEvent.size);
+                        ESP_LOGD(TAG,"Timeout occured, processed: %d bytes", usResult);
+                    }
                     break;
                 //Event of HW FIFO overflow detected
                 case UART_FIFO_OVF:
@@ -249,12 +234,16 @@ BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate,
                                     MB_QUEUE_LENGTH, &xMbUartQueue, MB_PORT_SERIAL_ISR_FLAG);
     MB_PORT_CHECK((xErr == ESP_OK), FALSE,
             "mb serial driver failure, uart_driver_install() returned (0x%x).", xErr);
-#ifndef MB_TIMER_PORT_ENABLED
+#if !CONFIG_FMB_TIMER_PORT_ENABLED
     // Set timeout for TOUT interrupt (T3.5 modbus time)
     xErr = uart_set_rx_timeout(ucUartNumber, MB_SERIAL_TOUT);
     MB_PORT_CHECK((xErr == ESP_OK), FALSE,
             "mb serial set rx timeout failure, uart_set_rx_timeout() returned (0x%x).", xErr);
 #endif
+
+    // Set always timeout flag to trigger timeout interrupt even after rx fifo full
+    uart_set_always_rx_timeout(ucUartNumber, true);
+
     // Create a task to handle UART events
     BaseType_t xStatus = xTaskCreate(vUartTask, "uart_queue_task", MB_SERIAL_TASK_STACK_SIZE,
                                         NULL, MB_SERIAL_TASK_PRIO, &xMbTaskHandle);

+ 25 - 39
components/freemodbus/port/portserial_m.c

@@ -51,18 +51,6 @@
 #include "sdkconfig.h"
 #include "port_serial_master.h"
 
-/* ----------------------- Defines ------------------------------------------*/
-
-#define MB_BAUD_RATE_DEFAULT        (115200)
-#define MB_QUEUE_LENGTH             (CONFIG_FMB_QUEUE_LENGTH)
-
-#define MB_SERIAL_TASK_PRIO         (CONFIG_FMB_SERIAL_TASK_PRIO)
-#define MB_SERIAL_TASK_STACK_SIZE   (CONFIG_FMB_SERIAL_TASK_STACK_SIZE)
-#define MB_SERIAL_TOUT              (3) // 3.5*8 = 28 ticks, TOUT=3 -> ~24..33 ticks
-
-// Set buffer size for transmission
-#define MB_SERIAL_BUF_SIZE          (CONFIG_FMB_SERIAL_BUF_SIZE)
-
 /* ----------------------- Static variables ---------------------------------*/
 static const CHAR *TAG = "MB_MASTER_SERIAL";
 
@@ -76,9 +64,6 @@ static UCHAR ucUartNumber = UART_NUM_MAX - 1;
 static BOOL bRxStateEnabled = FALSE; // Receiver 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)
 {
     // This function can be called from xMBRTUTransmitFSM() of different task
@@ -96,28 +81,23 @@ void vMBMasterPortSerialEnable(BOOL bRxEnable, BOOL bTxEnable)
     }
 }
 
-static void vMBMasterPortSerialRxPoll(size_t xEventSize)
+static USHORT usMBMasterPortSerialRxPoll(size_t xEventSize)
 {
     BOOL xReadStatus = TRUE;
     USHORT usCnt = 0;
 
     if (bRxStateEnabled) {
-        if (xEventSize > MB_SERIAL_RESP_LEN_MIN) {
-            xEventSize = (xEventSize > MB_SERIAL_BUF_SIZE) ?  MB_SERIAL_BUF_SIZE : xEventSize;
-            // Get received packet into Rx buffer
-            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.
-                xReadStatus = pxMBMasterFrameCBByteReceived(); // callback to receive FSM state machine
-            }
-            // 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);
+        while(xReadStatus && (usCnt++ <= MB_SERIAL_BUF_SIZE)) {
+            // Call the Modbus stack callback function and let it fill the stack buffers.
+            xReadStatus = 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);
     } else {
         ESP_LOGE(TAG, "%s: bRxState disabled but junk data (%d bytes) received. ", __func__, xEventSize);
     }
+    return usCnt;
 }
 
 BOOL xMBMasterPortSerialTxPoll(void)
@@ -127,9 +107,9 @@ BOOL xMBMasterPortSerialTxPoll(void)
 
     if( bTxStateEnabled ) {
         // 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.
-            bNeedPoll = pxMBMasterFrameCBTransmitterEmpty( ); // callback to transmit FSM state machine
+            bNeedPoll = pxMBMasterFrameCBTransmitterEmpty( ); // callback to transmit FSM
         }
         ESP_LOGD(TAG, "MB_TX_buffer sent: (%d) bytes.", (uint16_t)(usCount - 1));
         // Waits while UART sending the packet
@@ -145,15 +125,21 @@ BOOL xMBMasterPortSerialTxPoll(void)
 static void vUartTask(void* pvParameters)
 {
     uart_event_t xEvent;
+    USHORT usResult = 0;
     for(;;) {
         if (xQueueReceive(xMbUartQueue, (void*)&xEvent, portMAX_DELAY) == pdTRUE) {
             ESP_LOGD(TAG, "MB_uart[%d] event:", ucUartNumber);
             switch(xEvent.type) {
                 //Event of UART receiving data
                 case UART_DATA:
-                    ESP_LOGD(TAG,"Receive data, len: %d.", xEvent.size);
-                    // Read received data and send it to modbus stack
-                    vMBMasterPortSerialRxPoll(xEvent.size);
+                    ESP_LOGD(TAG,"Data event, len: %d.", xEvent.size);
+                    // 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) {
+                        // Read received data and send it to modbus stack
+                        usResult = usMBMasterPortSerialRxPoll(xEvent.size);
+                        ESP_LOGD(TAG,"Timeout occured, processed: %d bytes", usResult);
+                    }
                     break;
                 //Event of HW FIFO overflow detected
                 case UART_FIFO_OVF:
@@ -247,6 +233,10 @@ BOOL xMBMasterPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
     xErr = uart_set_rx_timeout(ucUartNumber, MB_SERIAL_TOUT);
     MB_PORT_CHECK((xErr == ESP_OK), FALSE,
             "mb serial set rx timeout failure, uart_set_rx_timeout() returned (0x%x).", xErr);
+
+    // Set always timeout flag to trigger timeout interrupt even after rx fifo full
+    uart_set_always_rx_timeout(ucUartNumber, true);
+
     // Create a task to handle UART events
     BaseType_t xStatus = xTaskCreate(vUartTask, "uart_queue_task", MB_SERIAL_TASK_STACK_SIZE,
                                         NULL, MB_SERIAL_TASK_PRIO, &xMbTaskHandle);
@@ -259,7 +249,6 @@ BOOL xMBMasterPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
     } else {
         vTaskSuspend(xMbTaskHandle); // Suspend serial task while stack is not started
     }
-    uiRxBufferPos = 0;
     ESP_LOGD(MB_PORT_TAG,"%s Init serial.", __func__);
     return TRUE;
 }
@@ -282,9 +271,6 @@ BOOL xMBMasterPortSerialPutByte(CHAR ucByte)
 BOOL xMBMasterPortSerialGetByte(CHAR* pucByte)
 {
     assert(pucByte != NULL);
-    MB_PORT_CHECK((uiRxBufferPos < MB_SERIAL_BUF_SIZE),
-            FALSE, "mb stack serial get byte failure.");
-    *pucByte = ucBuffer[uiRxBufferPos];
-    uiRxBufferPos++;
-    return TRUE;
+    USHORT usLength = uart_read_bytes(ucUartNumber, (uint8_t*)pucByte, 1, MB_SERIAL_RX_TOUT_TICKS);
+    return (usLength == 1);
 }

+ 5 - 5
components/freemodbus/port/porttimer.c

@@ -52,7 +52,7 @@
 #include "port_serial_slave.h"
 #include "sdkconfig.h"
 
-#ifdef CONFIG_FMB_TIMER_PORT_ENABLED
+#if CONFIG_FMB_TIMER_PORT_ENABLED
 
 #define MB_US50_FREQ            (20000) // 20kHz 1/20000 = 50mks
 #define MB_DISCR_TIME_US        (50)    // 50uS = one discreet for timer
@@ -80,7 +80,7 @@ static void IRAM_ATTR vTimerGroupIsr(void *param)
 
 BOOL xMBPortTimersInit(USHORT usTim1Timerout50us)
 {
-#ifdef CONFIG_FMB_TIMER_PORT_ENABLED
+#if CONFIG_FMB_TIMER_PORT_ENABLED
     MB_PORT_CHECK((usTim1Timerout50us > 0), FALSE,
             "Modbus timeout discreet is incorrect.");
     esp_err_t xErr;
@@ -121,7 +121,7 @@ BOOL xMBPortTimersInit(USHORT usTim1Timerout50us)
 
 void vMBPortTimersEnable(void)
 {
-#ifdef CONFIG_FMB_TIMER_PORT_ENABLED
+#if CONFIG_FMB_TIMER_PORT_ENABLED
     ESP_ERROR_CHECK(timer_pause(usTimerGroupIndex, usTimerIndex));
     ESP_ERROR_CHECK(timer_set_counter_value(usTimerGroupIndex, usTimerIndex, 0ULL));
     ESP_ERROR_CHECK(timer_enable_intr(usTimerGroupIndex, usTimerIndex));
@@ -132,9 +132,9 @@ void vMBPortTimersEnable(void)
 void MB_PORT_ISR_ATTR
 vMBPortTimersDisable(void)
 {
-#ifdef CONFIG_FMB_TIMER_PORT_ENABLED
+#if CONFIG_FMB_TIMER_PORT_ENABLED
     if( (BOOL)xPortInIsrContext() ) {
-            timer_group_set_counter_enable_in_isr(usTimerGroupIndex, usTimerIndex, TIMER_PAUSE);
+        timer_group_set_counter_enable_in_isr(usTimerGroupIndex, usTimerIndex, TIMER_PAUSE);
     } else {
         ESP_ERROR_CHECK(timer_pause(usTimerGroupIndex, usTimerIndex));
         ESP_ERROR_CHECK(timer_set_counter_value(usTimerGroupIndex, usTimerIndex, 0ULL));

+ 7 - 55
components/freemodbus/serial_master/modbus_controller/mbc_serial_master.c

@@ -36,7 +36,7 @@
 extern BOOL xMBMasterPortSerialTxPoll(void);
 
 /*-----------------------Master mode use these variables----------------------*/
-#define MB_RESPONSE_TICS pdMS_TO_TICKS(CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND)
+#define MB_RESPONSE_TICS pdMS_TO_TICKS(CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND + 10)
 
 
 static mb_master_interface_t* mbm_interface_ptr = NULL; //&default_interface_inst;
@@ -333,41 +333,6 @@ static uint8_t mbc_serial_master_get_command(mb_param_type_t param_type, mb_para
     return command;
 }
 
-// Helper function to set parameter buffer according to its type
-static esp_err_t mbc_serial_master_set_param_data(void* dest, void* src, mb_descr_type_t param_type, size_t param_size)
-{
-    esp_err_t err = ESP_OK;
-    MB_MASTER_CHECK((dest != NULL), 
-                        ESP_ERR_INVALID_ARG, "incorrect parameter pointer.");
-    MB_MASTER_CHECK((src != NULL), 
-                        ESP_ERR_INVALID_ARG, "incorrect parameter pointer.");
-    // Transfer parameter data into value of characteristic
-    switch(param_type)
-    {
-        case PARAM_TYPE_U8:
-            *((uint8_t*)dest) = *((uint8_t*)src);
-            break;
-        case PARAM_TYPE_U16:
-            *((uint16_t*)dest) = *((uint16_t*)src);
-            break;
-        case PARAM_TYPE_U32:
-            *((uint32_t*)dest) = *((uint32_t*)src);
-            break;
-        case PARAM_TYPE_FLOAT:
-            *((float*)dest) = *(float*)src;
-            break;
-        case PARAM_TYPE_ASCII:
-            memcpy((void*)dest, (void*)src, (size_t)param_size);
-            break;
-        default:
-            ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect param type (%u).",
-                        __FUNCTION__, (uint16_t)param_type);
-            err = ESP_ERR_NOT_SUPPORTED;
-            break;
-    }
-    return err;
-}
-
 // Helper to search parameter by name in the parameter description table 
 // and fills Modbus request fields accordingly
 static esp_err_t mbc_serial_master_set_request(char* name, mb_param_mode_t mode, 
@@ -418,7 +383,7 @@ static esp_err_t mbc_serial_master_set_request(char* name, mb_param_mode_t mode,
 
 // Get parameter data for corresponding characteristic
 static esp_err_t mbc_serial_master_get_parameter(uint16_t cid, char* name, 
-                                                    uint8_t* value, uint8_t *type)
+                                                    uint8_t* value_ptr, uint8_t *type)
 {
     MB_MASTER_CHECK((name != NULL), 
                         ESP_ERR_INVALID_ARG, "mb incorrect descriptor.");
@@ -427,19 +392,12 @@ static esp_err_t mbc_serial_master_get_parameter(uint16_t cid, char* name,
     esp_err_t error = ESP_ERR_INVALID_RESPONSE;
     mb_param_request_t request ;
     mb_parameter_descriptor_t reg_info = { 0 };
-    uint8_t param_buffer[PARAM_MAX_SIZE] = { 0 };
 
     error = mbc_serial_master_set_request(name, MB_PARAM_READ, &request, &reg_info);
     if ((error == ESP_OK) && (cid == reg_info.cid)) {
-        error = mbc_serial_master_send_request(&request, &param_buffer[0]);
+        // Send request to read characteristic data
+        error = mbc_serial_master_send_request(&request, value_ptr);
         if (error == ESP_OK) {
-            // If data pointer is NULL then we don't need to set value 
-            // (it is still in the cache of cid)
-            if (value != NULL) {
-                error = mbc_serial_master_set_param_data((void*)value, (void*)&param_buffer[0],
-                                                    reg_info.param_type, reg_info.param_size);
-                MB_MASTER_CHECK((error == ESP_OK), ESP_ERR_INVALID_STATE, "fail to set parameter data.");
-            }
             ESP_LOGD(MB_MASTER_TAG, "%s: Good response for get cid(%u) = %s",
                                     __FUNCTION__, (int)reg_info.cid, (char*)esp_err_to_name(error));
         } else {
@@ -457,28 +415,22 @@ static esp_err_t mbc_serial_master_get_parameter(uint16_t cid, char* name,
 
 // Set parameter value for characteristic selected by name and cid
 static esp_err_t mbc_serial_master_set_parameter(uint16_t cid, char* name, 
-                                                    uint8_t* value, uint8_t *type)
+                                                    uint8_t* value_ptr, uint8_t *type)
 {
     MB_MASTER_CHECK((name != NULL), 
                         ESP_ERR_INVALID_ARG, "mb incorrect descriptor.");
-    MB_MASTER_CHECK((value != NULL), 
+    MB_MASTER_CHECK((value_ptr != NULL),
                         ESP_ERR_INVALID_ARG, "value pointer is incorrect.");
     MB_MASTER_CHECK((type != NULL), 
                         ESP_ERR_INVALID_ARG, "type pointer is incorrect.");
     esp_err_t error = ESP_ERR_INVALID_RESPONSE;
     mb_param_request_t request ;
     mb_parameter_descriptor_t reg_info = { 0 };
-    uint8_t param_buffer[PARAM_MAX_SIZE] = { 0 };
 
     error = mbc_serial_master_set_request(name, MB_PARAM_WRITE, &request, &reg_info);
     if ((error == ESP_OK) && (cid == reg_info.cid)) {
-        // Transfer value of characteristic into parameter buffer
-        error = mbc_serial_master_set_param_data((void*)&param_buffer[0], (void*)value,
-                                                reg_info.param_type, reg_info.param_size);
-        MB_MASTER_CHECK((error == ESP_OK), 
-                            ESP_ERR_INVALID_STATE, "failure to set parameter data.");
         // Send request to write characteristic data
-        error = mbc_serial_master_send_request(&request, &param_buffer[0]);
+        error = mbc_serial_master_send_request(&request, value_ptr);
         if (error == ESP_OK) {
             ESP_LOGD(MB_MASTER_TAG, "%s: Good response for set cid(%u) = %s",
                                     __FUNCTION__, (int)reg_info.cid, (char*)esp_err_to_name(error));

+ 23 - 4
components/soc/include/hal/uart_hal.h

@@ -127,13 +127,14 @@ typedef struct {
 /**
  * @brief  Read data from the UART rxfifo
  *
- * @param  hal Context of the HAL layer
- * @param  buf Pointer to the buffer used to store the read data. The buffer size should be large than 128 byts
- * @param  rd_len The length has been read out from the rxfifo
+ * @param[in] hal Context of the HAL layer
+ * @param[in] buf Pointer to the buffer used to store the read data. The buffer size should be large than 128 byte
+ * @param[inout] inout_rd_len As input, the size of output buffer to read (set to 0 to read all available data).
+ *                            As output, returns the actual size written into the output buffer.
  *
  * @return None
  */
-void uart_hal_read_rxfifo(uart_hal_context_t *hal, uint8_t *buf, int *rd_len);
+void uart_hal_read_rxfifo(uart_hal_context_t *hal, uint8_t *buf, int *inout_rd_len);
 
 /**
  * @brief  Write data into the UART txfifo
@@ -448,6 +449,24 @@ uint8_t uart_hal_get_symb_len(uart_hal_context_t *hal);
  */
 uint16_t uart_hal_get_max_rx_timeout_thrd(uart_hal_context_t *hal);
 
+/**
+ * @brief  Get the timeout threshold value set for receiver.
+ *
+ * @param  hw Beginning address of the peripheral registers.
+ *
+ * @return tout_thr The timeout value. If timeout is disabled then returns 0.
+ */
+#define uart_hal_get_rx_tout_thr(hal) uart_ll_get_rx_tout_thr((hal)->dev)
+
+/**
+ * @brief  Get the length of readable data in UART rxfifo.
+ *
+ * @param  hw Beginning address of the peripheral registers.
+ *
+ * @return The readable data length in rxfifo.
+ */
+#define uart_hal_get_rxfifo_len(hal) uart_ll_get_rxfifo_len((hal)->dev)
+
 #ifdef __cplusplus
 }
 #endif

+ 24 - 4
components/soc/src/esp32/include/hal/uart_ll.h

@@ -807,6 +807,26 @@ static inline void uart_ll_set_rx_tout(uart_dev_t *hw, uint16_t tout_thr)
     }
 }
 
+/**
+ * @brief  Get the timeout value for receiver receiving a byte.
+ *
+ * @param  hw Beginning address of the peripheral registers.
+ *
+ * @return tout_thr The timeout threshold value. If timeout feature is disabled returns 0.
+ */
+static inline uint16_t uart_ll_get_rx_tout_thr(uart_dev_t *hw)
+{
+    uint16_t tout_thrd = 0;
+    if (hw->conf1.rx_tout_en > 0) {
+        if (hw->conf0.tick_ref_always_on == 0) {
+            tout_thrd = (uint16_t)(hw->conf1.rx_tout_thrhd / UART_LL_TOUT_REF_FACTOR_DEFAULT);
+        } else {
+            tout_thrd = (uint16_t)(hw->conf1.rx_tout_thrhd  << 3);
+        }
+    }
+    return tout_thrd;
+}
+
 /**
  * @brief  Get UART maximum timeout threshold.
  *
@@ -816,13 +836,13 @@ static inline void uart_ll_set_rx_tout(uart_dev_t *hw, uint16_t tout_thr)
  */
 static inline uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw)
 {
-    uint16_t tout_sym = 0;
+    uint16_t tout_thrd = 0;
     if (hw->conf0.tick_ref_always_on == 0) {
-        tout_sym = (uint16_t)(UART_RX_TOUT_THRHD_V / UART_LL_TOUT_REF_FACTOR_DEFAULT);
+        tout_thrd = (uint16_t)(UART_RX_TOUT_THRHD_V / UART_LL_TOUT_REF_FACTOR_DEFAULT);
     } else {
-        tout_sym = (uint16_t)(UART_RX_TOUT_THRHD_V  << 3);
+        tout_thrd = (uint16_t)(UART_RX_TOUT_THRHD_V  << 3);
     }
-    return tout_sym;
+    return tout_thrd;
 }
 
 #undef UART_LL_TOUT_REF_FACTOR_DEFAULT

+ 16 - 0
components/soc/src/esp32s2/include/hal/uart_ll.h

@@ -772,6 +772,22 @@ static inline void uart_ll_set_rx_tout(uart_dev_t *hw, uint16_t tout_thrd)
     }
 }
 
+/**
+ * @brief  Get the timeout value for receiver receiving a byte.
+ *
+ * @param  hw Beginning address of the peripheral registers.
+ *
+ * @return tout_thr The timeout threshold value. If timeout feature is disabled returns 0.
+ */
+static inline uint16_t uart_ll_get_rx_tout_thr(uart_dev_t *hw)
+{
+    uint16_t tout_thrd = 0;
+    if(hw->conf1.rx_tout_en > 0) {
+        tout_thrd = hw->mem_conf.rx_tout_thrhd;
+    }
+    return tout_thrd;
+}
+
 /**
  * @brief  Get UART maximum timeout threshold.
  *

+ 3 - 3
components/soc/src/hal/uart_hal_iram.c

@@ -40,9 +40,9 @@ void uart_hal_write_txfifo(uart_hal_context_t *hal, const uint8_t *buf, uint32_t
     uart_ll_write_txfifo(hal->dev, buf, fill_len);
 }
 
-void uart_hal_read_rxfifo(uart_hal_context_t *hal, uint8_t *buf, int *rd_len)
+void uart_hal_read_rxfifo(uart_hal_context_t *hal, uint8_t *buf, int *inout_rd_len)
 {
-    uint16_t read_len = uart_ll_get_rxfifo_len(hal->dev);
-    *rd_len = read_len;
+    uint16_t read_len = (*inout_rd_len > 0) ? *inout_rd_len : uart_ll_get_rxfifo_len(hal->dev);
+    *inout_rd_len = read_len;
     uart_ll_read_rxfifo(hal->dev, buf, read_len);
 }

+ 1 - 1
examples/protocols/modbus/serial/example_test.py

@@ -41,7 +41,7 @@ expect_dict_master_err = {"READ_PAR_ERR": (u'263', u'ESP_ERR_TIMEOUT'),
 # The dictionary for regular expression patterns to check in listing
 pattern_dict_master_ok = {"START": (r'.*I \([0-9]+\) MASTER_TEST: Start modbus test...'),
                           "READ_PAR_OK": (r'.*I\s\([0-9]+\) MASTER_TEST: Characteristic #[0-9]+ [a-zA-Z0-9_]+'
-                                          r'\s\([a-zA-Z\%\/]+\) value = [a-zA-Z0-9\.]+ \(0x[a-zA-Z0-9]+\) read successful.'),
+                                          r'\s\([a-zA-Z\%\/]+\) value = [a-zA-Z0-9\.\s]*\(0x[a-zA-Z0-9]+\) read successful.'),
                           "ALARM_MSG": (r'.*I \([0-9]*\) MASTER_TEST: Alarm triggered by cid #([0-9]+).')}
 
 pattern_dict_master_err = {"READ_PAR_ERR_TOUT": (r'.*E \([0-9]+\) MASTER_TEST: Characteristic #[0-9]+'

+ 1 - 0
examples/protocols/modbus/serial/mb_example_common/include/modbus_params.h

@@ -49,6 +49,7 @@ typedef struct
     float holding_data1;
     float holding_data2;
     float holding_data3;
+    uint16_t test_regs[150];
 } holding_reg_params_t;
 #pragma pack(pop)
 

+ 76 - 32
examples/protocols/modbus/serial/mb_master/main/master.c

@@ -70,6 +70,7 @@ enum {
     CID_HOLD_DATA_1,
     CID_INP_DATA_2,
     CID_HOLD_DATA_2,
+    CID_HOLD_TEST_REG,
     CID_RELAY_P1,
     CID_RELAY_P2,
     CID_COUNT
@@ -98,6 +99,8 @@ const mb_parameter_descriptor_t device_parameters[] = {
             INPUT_OFFSET(input_data2), PARAM_TYPE_FLOAT, 4, OPTS( -40, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
     { CID_HOLD_DATA_2, STR("Humidity_3"), STR("%rH"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 4, 2,
             HOLD_OFFSET(holding_data2), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
+    { CID_HOLD_TEST_REG, STR("Test_regs"), STR("__"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 10, 58,
+            HOLD_OFFSET(test_regs), PARAM_TYPE_ASCII, 116, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
     { CID_RELAY_P1, STR("RelayP1"), STR("on/off"), MB_DEVICE_ADDR1, MB_PARAM_COIL, 0, 8,
             COIL_OFFSET(coils_port0), PARAM_TYPE_U16, 2, OPTS( BIT1, 0, 0 ), PAR_PERMS_READ_WRITE_TRIGGER },
     { CID_RELAY_P2, STR("RelayP2"), STR("on/off"), MB_DEVICE_ADDR1, MB_PARAM_COIL, 8, 8,
@@ -160,43 +163,83 @@ static void master_operation_func(void *arg)
                 void* temp_data_ptr = master_get_param_data(param_descriptor);
                 assert(temp_data_ptr);
                 uint8_t type = 0;
-                err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key, 
-                                                    (uint8_t*)&value, &type);
-                if (err == ESP_OK) {
-                    *(float*)temp_data_ptr = value;
-                    if ((param_descriptor->mb_param_type == MB_PARAM_HOLDING) ||
-                        (param_descriptor->mb_param_type == MB_PARAM_INPUT)) {
-                        ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = %f (0x%x) read successful.",
-                                        param_descriptor->cid,
-                                        (char*)param_descriptor->param_key, 
-                                        (char*)param_descriptor->param_units,
-                                        value, 
-                                        *(uint32_t*)temp_data_ptr);
-                        if (((value > param_descriptor->param_opts.max) ||
-                            (value < param_descriptor->param_opts.min))) {
+                if ((param_descriptor->param_type == PARAM_TYPE_ASCII) &&
+                        (param_descriptor->cid == CID_HOLD_TEST_REG)) {
+                   // Check for long array of registers of type PARAM_TYPE_ASCII
+                    err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key,
+                                                                            (uint8_t*)temp_data_ptr, &type);
+                    if (err == ESP_OK) {
+                        ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = (0x%08x) read successful.",
+                                                 param_descriptor->cid,
+                                                 (char*)param_descriptor->param_key,
+                                                 (char*)param_descriptor->param_units,
+                                                 *(uint32_t*)temp_data_ptr);
+                        // Initialize data of test array and write to slave
+                        if (*(uint32_t*)temp_data_ptr != 0xAAAAAAAA) {
+                            memset((void*)temp_data_ptr, 0xAA, param_descriptor->param_size);
+                            *(uint32_t*)temp_data_ptr = 0xAAAAAAAA;
+                            err = mbc_master_set_parameter(cid, (char*)param_descriptor->param_key,
+                                                              (uint8_t*)temp_data_ptr, &type);
+                            if (err == ESP_OK) {
+                                ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = (0x%08x), write successful.",
+                                                            param_descriptor->cid,
+                                                            (char*)param_descriptor->param_key,
+                                                            (char*)param_descriptor->param_units,
+                                                            *(uint32_t*)temp_data_ptr);
+                            } else {
+                                ESP_LOGE(MASTER_TAG, "Characteristic #%d (%s) write fail, err = 0x%x (%s).",
+                                                        param_descriptor->cid,
+                                                        (char*)param_descriptor->param_key,
+                                                        (int)err,
+                                                        (char*)esp_err_to_name(err));
+                            }
+                        }
+                    } else {
+                        ESP_LOGE(MASTER_TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).",
+                                                param_descriptor->cid,
+                                                (char*)param_descriptor->param_key,
+                                                (int)err,
+                                                (char*)esp_err_to_name(err));
+                    }
+                } else {
+                    err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key,
+                                                        (uint8_t*)&value, &type);
+                    if (err == ESP_OK) {
+                        *(float*)temp_data_ptr = value;
+                        if ((param_descriptor->mb_param_type == MB_PARAM_HOLDING) ||
+                            (param_descriptor->mb_param_type == MB_PARAM_INPUT)) {
+                            ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = %f (0x%x) read successful.",
+                                            param_descriptor->cid,
+                                            (char*)param_descriptor->param_key,
+                                            (char*)param_descriptor->param_units,
+                                            value,
+                                            *(uint32_t*)temp_data_ptr);
+                            if (((value > param_descriptor->param_opts.max) ||
+                                (value < param_descriptor->param_opts.min))) {
+                                    alarm_state = true;
+                                    break;
+                            }
+                        } else {
+                            uint16_t state = *(uint16_t*)temp_data_ptr;
+                            const char* rw_str = (state & param_descriptor->param_opts.opt1) ? "ON" : "OFF";
+                            ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = %s (0x%x) read successful.",
+                                            param_descriptor->cid,
+                                            (char*)param_descriptor->param_key,
+                                            (char*)param_descriptor->param_units,
+                                            (const char*)rw_str,
+                                            *(uint16_t*)temp_data_ptr);
+                            if (state & param_descriptor->param_opts.opt1) {
                                 alarm_state = true;
                                 break;
+                            }
                         }
                     } else {
-                        uint16_t state = *(uint16_t*)temp_data_ptr;
-                        const char* rw_str = (state & param_descriptor->param_opts.opt1) ? "ON" : "OFF";
-                        ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = %s (0x%x) read successful.",
-                                        param_descriptor->cid,
-                                        (char*)param_descriptor->param_key, 
-                                        (char*)param_descriptor->param_units,
-                                        (const char*)rw_str,
-                                        *(uint16_t*)temp_data_ptr);
-                        if (state & param_descriptor->param_opts.opt1) {
-                            alarm_state = true;
-                            break;
-                        }
+                        ESP_LOGE(MASTER_TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).",
+                                            param_descriptor->cid,
+                                            (char*)param_descriptor->param_key,
+                                            (int)err,
+                                            (char*)esp_err_to_name(err));
                     }
-                } else {
-                    ESP_LOGE(MASTER_TAG, "Characteristic #%d (%s) read fail, err = %d (%s).",
-                                        param_descriptor->cid,
-                                        (char*)param_descriptor->param_key,
-                                        (int)err,
-                                        (char*)esp_err_to_name(err));
                 }
                 vTaskDelay(POLL_TIMEOUT_TICS); // timeout between polls
             }
@@ -257,6 +300,7 @@ static esp_err_t master_init(void)
     err = uart_set_mode(MB_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX);
     MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE,
             "mb serial set mode failure, uart_set_mode() returned (0x%x).", (uint32_t)err);
+
     vTaskDelay(5);
     err = mbc_master_set_descriptor(&device_parameters[0], num_device_parameters);
     MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE,

+ 1 - 1
examples/protocols/modbus/serial/mb_slave/main/slave.c

@@ -135,7 +135,7 @@ void app_main(void)
                             UART_PIN_NO_CHANGE));
 
     // Set UART driver mode to Half Duplex
-    ESP_ERROR_CHECK(uart_set_mode(MB_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX));  
+    ESP_ERROR_CHECK(uart_set_mode(MB_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX));
                                     
     ESP_LOGI(SLAVE_TAG, "Modbus slave stack initialized.");
     ESP_LOGI(SLAVE_TAG, "Start modbus test...");