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()
This commit is contained in:
parent
135aa51d06
commit
3abdd2207d
26 changed files with 387 additions and 305 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
/* 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 );
|
||||
}
|
||||
/* If an error occured convert it into a Modbus exception. */
|
||||
if( eRegStatus != MB_ENOERR )
|
||||
{
|
||||
eStatus = prveMBError2Exception( eRegStatus );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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, ...) \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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, ®_info);
|
||||
if ((error == ESP_OK) && (cid == reg_info.cid)) {
|
||||
error = mbc_serial_master_send_request(&request, ¶m_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*)¶m_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, ®_info);
|
||||
if ((error == ESP_OK) && (cid == reg_info.cid)) {
|
||||
// Transfer value of characteristic into parameter buffer
|
||||
error = mbc_serial_master_set_param_data((void*)¶m_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, ¶m_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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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]+'
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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))) {
|
||||
alarm_state = true;
|
||||
break;
|
||||
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 {
|
||||
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));
|
||||
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 {
|
||||
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));
|
||||
}
|
||||
}
|
||||
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,
|
||||
|
|
|
@ -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...");
|
||||
|
|
Loading…
Reference in a new issue