forked from espressif/esp-modbus
modbus tcp fix uid settings
This commit is contained in:
10
Kconfig
10
Kconfig
@ -16,7 +16,7 @@ menu "Modbus configuration"
|
||||
|
||||
config FMB_TCP_PORT_MAX_CONN
|
||||
int "Maximum allowed connections for TCP stack"
|
||||
range 1 6
|
||||
range 1 8
|
||||
default 5
|
||||
depends on FMB_COMM_MODE_TCP_EN
|
||||
help
|
||||
@ -34,6 +34,14 @@ menu "Modbus configuration"
|
||||
Modbus TCP connection timeout in seconds.
|
||||
Once expired the current connection with the client will be closed
|
||||
and Modbus slave will be waiting for new connection to accept.
|
||||
|
||||
config FMB_TCP_UID_ENABLED
|
||||
bool "Modbus TCP enable UID (Unit Identifier) support"
|
||||
default n
|
||||
depends on FMB_COMM_MODE_TCP_EN
|
||||
help
|
||||
If this option is set the Modbus stack uses UID (Unit Identifier) field in MBAP frame.
|
||||
Else the UID is ignored by master and slave.
|
||||
|
||||
config FMB_COMM_MODE_RTU_EN
|
||||
bool "Enable Modbus stack support for RTU mode"
|
||||
|
@ -143,6 +143,7 @@ typedef union {
|
||||
// TCP/UDP communication structure
|
||||
struct {
|
||||
mb_mode_type_t ip_mode; /*!< Modbus communication mode */
|
||||
uint8_t slave_uid; /*!< Modbus slave address field for UID */
|
||||
uint16_t ip_port; /*!< Modbus port */
|
||||
mb_tcp_addr_type_t ip_addr_type; /*!< Modbus address type */
|
||||
void* ip_addr; /*!< Modbus address table for connection */
|
||||
|
@ -165,6 +165,7 @@ eMBErrorCode eMBInit( eMBMode eMode, UCHAR ucSlaveAddress,
|
||||
* frame processing is still disabled until eMBEnable( ) is called.
|
||||
*
|
||||
* \param usTCPPort The TCP port to listen on.
|
||||
* \param ucSlaveUid The UID field for slave to listen on.
|
||||
* \return If the protocol stack has been initialized correctly the function
|
||||
* returns eMBErrorCode::MB_ENOERR. Otherwise one of the following error
|
||||
* codes is returned:
|
||||
@ -172,7 +173,7 @@ eMBErrorCode eMBInit( eMBMode eMode, UCHAR ucSlaveAddress,
|
||||
* slave addresses are in the range 1 - 247.
|
||||
* - eMBErrorCode::MB_EPORTERR IF the porting layer returned an error.
|
||||
*/
|
||||
eMBErrorCode eMBTCPInit( USHORT usTCPPort );
|
||||
eMBErrorCode eMBTCPInit( UCHAR ucSlaveUid, USHORT usTCPPort );
|
||||
|
||||
/*! \ingroup modbus
|
||||
* \brief Release resources used by the protocol stack.
|
||||
|
@ -86,6 +86,10 @@ PR_BEGIN_EXTERN_C
|
||||
|
||||
#endif
|
||||
|
||||
/*! \brief The option is required for support of RTU over TCP.
|
||||
*/
|
||||
#define MB_TCP_UID_ENABLED ( CONFIG_FMB_TCP_UID_ENABLED )
|
||||
|
||||
/*! \brief This option defines the number of data bits per ASCII character.
|
||||
*
|
||||
* A parity bit is added before the stop bit which keeps the actual byte size at 10 bits.
|
||||
|
@ -202,11 +202,16 @@ eMBInit( eMBMode eMode, UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eM
|
||||
|
||||
#if MB_TCP_ENABLED > 0
|
||||
eMBErrorCode
|
||||
eMBTCPInit( USHORT ucTCPPort )
|
||||
eMBTCPInit( UCHAR ucSlaveUid, USHORT ucTCPPort )
|
||||
{
|
||||
eMBErrorCode eStatus = MB_ENOERR;
|
||||
|
||||
if( ( eStatus = eMBTCPDoInit( ucTCPPort ) ) != MB_ENOERR )
|
||||
/* Check preconditions */
|
||||
if( ucSlaveUid > MB_ADDRESS_MAX )
|
||||
{
|
||||
eStatus = MB_EINVAL;
|
||||
}
|
||||
else if( ( eStatus = eMBTCPDoInit( ucTCPPort ) ) != MB_ENOERR )
|
||||
{
|
||||
eMBState = STATE_DISABLED;
|
||||
}
|
||||
@ -222,7 +227,7 @@ eMBTCPInit( USHORT ucTCPPort )
|
||||
peMBFrameReceiveCur = eMBTCPReceive;
|
||||
peMBFrameSendCur = eMBTCPSend;
|
||||
pvMBFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBTCPPortClose : NULL;
|
||||
ucMBAddress = MB_TCP_PSEUDO_ADDRESS;
|
||||
ucMBAddress = ucSlaveUid;
|
||||
eMBCurrentMode = MB_TCP;
|
||||
eMBState = STATE_DISABLED;
|
||||
}
|
||||
@ -371,7 +376,8 @@ eMBPoll( void )
|
||||
if( eStatus == MB_ENOERR )
|
||||
{
|
||||
/* Check if the frame is for us. If not ignore the frame. */
|
||||
if( ( ucRcvAddress == ucMBAddress ) || ( ucRcvAddress == MB_ADDRESS_BROADCAST ) )
|
||||
if( ( ucRcvAddress == ucMBAddress ) || ( ucRcvAddress == MB_ADDRESS_BROADCAST )
|
||||
|| ( ucRcvAddress == MB_TCP_PSEUDO_ADDRESS ) )
|
||||
{
|
||||
( void )xMBPortEventPost( EV_EXECUTE );
|
||||
ESP_LOG_BUFFER_HEX_LEVEL(MB_PORT_TAG, &ucMBFrame[MB_PDU_FUNC_OFF], usLength, ESP_LOG_DEBUG);
|
||||
@ -401,8 +407,8 @@ eMBPoll( void )
|
||||
}
|
||||
|
||||
/* If the request was not sent to the broadcast address we
|
||||
* return a reply. */
|
||||
if( ucRcvAddress != MB_ADDRESS_BROADCAST )
|
||||
* return a reply. In case of TCP the slave answers to broadcast address. */
|
||||
if( ( ucRcvAddress != MB_ADDRESS_BROADCAST ) || ( eMBCurrentMode == MB_TCP ) )
|
||||
{
|
||||
if( eException != MB_EX_NONE )
|
||||
{
|
||||
|
@ -124,10 +124,14 @@ eMBTCPReceive( UCHAR * pucRcvAddress, UCHAR ** ppucFrame, USHORT * pusLength )
|
||||
*pusLength = usLength - MB_TCP_FUNC;
|
||||
eStatus = MB_ENOERR;
|
||||
|
||||
/* Modbus TCP does not use any addresses. Fake the source address such
|
||||
* that the processing part deals with this frame.
|
||||
/* The regular Modbus TCP does not use any addresses. Fake the MBAP UID in this case.
|
||||
* The MBAP UID field support is used for RTU over TCP option if enabled.
|
||||
*/
|
||||
#if MB_TCP_UID_ENABLED
|
||||
*pucRcvAddress = pucMBTCPFrame[MB_TCP_UID];
|
||||
#else
|
||||
*pucRcvAddress = MB_TCP_PSEUDO_ADDRESS;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -152,6 +156,7 @@ eMBTCPSend( UCHAR _unused, const UCHAR * pucFrame, USHORT usLength )
|
||||
*/
|
||||
pucMBTCPFrame[MB_TCP_LEN] = ( usLength + 1 ) >> 8U;
|
||||
pucMBTCPFrame[MB_TCP_LEN + 1] = ( usLength + 1 ) & 0xFF;
|
||||
|
||||
if( xMBTCPPortSendResponse( pucMBTCPFrame, usTCPLength ) == FALSE )
|
||||
{
|
||||
eStatus = MB_EIO;
|
||||
|
@ -123,10 +123,14 @@ eMBMasterTCPReceive( UCHAR * pucRcvAddress, UCHAR ** ppucFrame, USHORT * pusLeng
|
||||
*pusLength = usLength - MB_TCP_FUNC;
|
||||
eStatus = MB_ENOERR;
|
||||
|
||||
/* Modbus TCP does not use any addresses. Fake the source address such
|
||||
* that the processing part deals with this frame.
|
||||
/* Get MBAP UID field if its support is enabled.
|
||||
* Otherwise just ignore this field.
|
||||
*/
|
||||
#if MB_TCP_UID_ENABLED
|
||||
*pucRcvAddress = pucMBTCPFrame[MB_TCP_UID];
|
||||
#else
|
||||
*pucRcvAddress = MB_TCP_PSEUDO_ADDRESS;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -137,20 +141,27 @@ eMBMasterTCPReceive( UCHAR * pucRcvAddress, UCHAR ** ppucFrame, USHORT * pusLeng
|
||||
}
|
||||
|
||||
eMBErrorCode
|
||||
eMBMasterTCPSend( UCHAR _unused, const UCHAR * pucFrame, USHORT usLength )
|
||||
eMBMasterTCPSend( UCHAR ucAddress, const UCHAR * pucFrame, USHORT usLength )
|
||||
{
|
||||
eMBErrorCode eStatus = MB_ENOERR;
|
||||
UCHAR *pucMBTCPFrame = ( UCHAR * ) pucFrame - MB_TCP_FUNC;
|
||||
USHORT usTCPLength = usLength + MB_TCP_FUNC;
|
||||
|
||||
/* The MBAP header is already initialized because the caller calls this
|
||||
* function with the buffer returned by the previous call. Therefore we
|
||||
* only have to update the length in the header. Note that the length
|
||||
* header includes the size of the Modbus PDU and the UID Byte. Therefore
|
||||
* the length is usLength plus one.
|
||||
/* Note that the length in the MBAP header includes the size of the Modbus PDU
|
||||
* and the UID Byte. Therefore the length is usLength plus one.
|
||||
*/
|
||||
pucMBTCPFrame[MB_TCP_LEN] = ( usLength + 1 ) >> 8U;
|
||||
pucMBTCPFrame[MB_TCP_LEN + 1] = ( usLength + 1 ) & 0xFF;
|
||||
|
||||
/* Set UID field in the MBAP if it is supported.
|
||||
* If the RTU over TCP is not supported, the UID = 0 or 0xFF.
|
||||
*/
|
||||
#if MB_TCP_UID_ENABLED
|
||||
pucMBTCPFrame[MB_TCP_UID] = ucAddress;
|
||||
#else
|
||||
pucMBTCPFrame[MB_TCP_UID] = 0x00;
|
||||
#endif
|
||||
|
||||
if( xMBMasterTCPPortSendResponse( pucMBTCPFrame, usTCPLength ) == FALSE )
|
||||
{
|
||||
eStatus = MB_EIO;
|
||||
|
@ -50,7 +50,7 @@ void eMBMasterTCPStart( void );
|
||||
void eMBMasterTCPStop( void );
|
||||
eMBErrorCode eMBMasterTCPReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame,
|
||||
USHORT * pusLength );
|
||||
eMBErrorCode eMBMasterTCPSend( UCHAR _unused, const UCHAR * pucFrame,
|
||||
eMBErrorCode eMBMasterTCPSend( UCHAR ucAddress, const UCHAR * pucFrame,
|
||||
USHORT usLength );
|
||||
BOOL xMBMasterTCPTimerExpired(void);
|
||||
|
||||
|
@ -989,6 +989,7 @@ xMBMasterTCPPortSendResponse( UCHAR * pucMBTCPFrame, USHORT usTCPLength )
|
||||
// Apply TID field to the frame before send
|
||||
pucMBTCPFrame[MB_TCP_TID] = (UCHAR)(pxInfo->usTidCnt >> 8U);
|
||||
pucMBTCPFrame[MB_TCP_TID + 1] = (UCHAR)(pxInfo->usTidCnt & 0xFF);
|
||||
|
||||
int xRes = xMBMasterTCPPortWritePoll(pxInfo, pucMBTCPFrame, usTCPLength, MB_TCP_SEND_TIMEOUT_MS);
|
||||
if (xRes < 0) {
|
||||
ESP_LOGE(TAG, MB_SLAVE_FMT(", send data failure, err(errno) = %d(%d)."),
|
||||
|
@ -72,7 +72,7 @@ static esp_err_t mbc_tcp_slave_start(void)
|
||||
eMBErrorCode status = MB_EIO;
|
||||
|
||||
// Initialize Modbus stack using mbcontroller parameters
|
||||
status = eMBTCPInit((USHORT)mbs_opts->mbs_comm.ip_port);
|
||||
status = eMBTCPInit((UCHAR)mbs_opts->mbs_comm.slave_uid, (USHORT)mbs_opts->mbs_comm.ip_port);
|
||||
MB_SLAVE_CHECK((status == MB_ENOERR), ESP_ERR_INVALID_STATE,
|
||||
"mb stack initialization failure, eMBInit() returns (0x%x).", status);
|
||||
|
||||
|
@ -106,8 +106,9 @@ static void* vxMBTCPPortRespQueueRecv(QueueHandle_t xRespQueueHandle)
|
||||
BaseType_t xStatus = xQueueReceive(xRespQueueHandle,
|
||||
(void*)&pvResp,
|
||||
pdMS_TO_TICKS(MB_TCP_RESP_TIMEOUT_MS));
|
||||
MB_PORT_CHECK((xStatus == pdTRUE), NULL, "Could not get respond confirmation.");
|
||||
MB_PORT_CHECK((pvResp), NULL, "Incorrect response processing.");
|
||||
if (xStatus != pdTRUE) {
|
||||
ESP_LOGD(TAG, "Could not get respond confirmation.");
|
||||
}
|
||||
return pvResp;
|
||||
}
|
||||
|
||||
@ -599,7 +600,7 @@ static void vMBTCPPortServerTask(void *pvParameters)
|
||||
// Wait while response is not processed by stack by timeout
|
||||
UCHAR* pucSentBuffer = vxMBTCPPortRespQueueRecv(xConfig.xRespQueueHandle);
|
||||
if (pucSentBuffer == NULL) {
|
||||
ESP_LOGE(TAG, "Response time exceeds configured %d [ms], ignore packet.",
|
||||
ESP_LOGD(TAG, "Response is ignored, time exceeds configured %d [ms].",
|
||||
MB_TCP_RESP_TIMEOUT_MS);
|
||||
} else {
|
||||
USHORT usSentTid = MB_TCP_GET_FIELD(pucSentBuffer, MB_TCP_TID);
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: "1.0.8"
|
||||
version: "1.0.9"
|
||||
description: ESP-MODBUS is the official Modbus library for Espressif SoCs.
|
||||
url: https://github.com/espressif/esp-modbus
|
||||
dependencies:
|
||||
|
@ -73,7 +73,7 @@ static const char *TAG = "MASTER_TEST";
|
||||
// Enumeration of modbus device addresses accessed by master device
|
||||
// Each address in the table is a index of TCP slave ip address in mb_communication_info_t::tcp_ip_addr table
|
||||
enum {
|
||||
MB_DEVICE_ADDR1 = 1, // Slave address 1
|
||||
MB_DEVICE_ADDR1 = 1, // Slave UID = 1
|
||||
MB_DEVICE_ADDR2 = 200,
|
||||
MB_DEVICE_ADDR3 = 35
|
||||
};
|
||||
@ -750,7 +750,6 @@ void app_main(void)
|
||||
comm_info.ip_netif_ptr = (void*)get_example_netif();
|
||||
|
||||
ESP_ERROR_CHECK(master_init(&comm_info));
|
||||
vTaskDelay(50);
|
||||
|
||||
master_operation_func(NULL);
|
||||
ESP_ERROR_CHECK(master_destroy());
|
||||
|
@ -8,6 +8,7 @@ CONFIG_FMB_COMM_MODE_ASCII_EN=n
|
||||
CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=3000
|
||||
CONFIG_FMB_MASTER_DELAY_MS_CONVERT=300
|
||||
CONFIG_FMB_TIMER_PORT_ENABLED=y
|
||||
CONFIG_FMB_TCP_UID_ENABLED=n
|
||||
CONFIG_MB_MDNS_IP_RESOLVER=n
|
||||
CONFIG_MB_SLAVE_IP_FROM_STDIN=y
|
||||
CONFIG_EXAMPLE_CONNECT_IPV6=n
|
||||
|
@ -13,6 +13,7 @@ CONFIG_FMB_MASTER_DELAY_MS_CONVERT=300
|
||||
CONFIG_FMB_TIMER_PORT_ENABLED=y
|
||||
CONFIG_FMB_TIMER_ISR_IN_IRAM=y
|
||||
CONFIG_FMB_TIMER_USE_ISR_DISPATCH_METHOD=y
|
||||
CONFIG_FMB_TCP_UID_ENABLED=n
|
||||
CONFIG_MB_MDNS_IP_RESOLVER=n
|
||||
CONFIG_MB_SLAVE_IP_FROM_STDIN=y
|
||||
CONFIG_MB_SLAVE_ADDR=1
|
||||
|
@ -2,7 +2,8 @@ menu "Modbus Example Configuration"
|
||||
|
||||
config MB_SLAVE_ADDR
|
||||
int "Modbus slave address"
|
||||
range 1 255
|
||||
range 1 247 if !FMB_TCP_UID_ENABLED
|
||||
range 0 247 if FMB_TCP_UID_ENABLED
|
||||
default 1
|
||||
help
|
||||
This is the Modbus slave address in the network.
|
||||
|
@ -52,6 +52,8 @@
|
||||
| MB_EVENT_COILS_WR)
|
||||
#define MB_READ_WRITE_MASK (MB_READ_MASK | MB_WRITE_MASK)
|
||||
|
||||
#define MB_SLAVE_ADDR (CONFIG_MB_SLAVE_ADDR)
|
||||
|
||||
static const char *TAG = "SLAVE_TEST";
|
||||
|
||||
static portMUX_TYPE param_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
@ -69,8 +71,6 @@ static portMUX_TYPE param_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
#define MB_DEVICE_ID (uint32_t)CONFIG_FMB_CONTROLLER_SLAVE_ID
|
||||
#endif
|
||||
|
||||
#define MB_SLAVE_ADDR (CONFIG_MB_SLAVE_ADDR)
|
||||
|
||||
#define MB_MDNS_INSTANCE(pref) pref"mb_slave_tcp"
|
||||
|
||||
// convert mac from binary format to string
|
||||
@ -315,6 +315,7 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info)
|
||||
|
||||
comm_info->ip_addr = NULL; // Bind to any address
|
||||
comm_info->ip_netif_ptr = (void*)get_example_netif();
|
||||
comm_info->slave_uid = MB_SLAVE_ADDR;
|
||||
|
||||
// Setup communication parameters and start stack
|
||||
err = mbc_slave_setup((void*)comm_info);
|
||||
@ -423,6 +424,7 @@ void app_main(void)
|
||||
ESP_ERROR_CHECK(init_services());
|
||||
|
||||
// Set UART log level
|
||||
|
||||
esp_log_level_set(TAG, ESP_LOG_INFO);
|
||||
|
||||
mb_communication_info_t comm_info = { 0 };
|
||||
|
Reference in New Issue
Block a user