freemodbus: allow address gaps in master data dictionary (support of UID field in MBAP) (backport v4.3)
This commit is contained in:
committed by
Jiang Jiang Jian
parent
5bad27d0d5
commit
073da59d27
@@ -18,6 +18,8 @@
|
||||
#include "esp_modbus_master.h" // for public interface defines
|
||||
#include "esp_modbus_callbacks.h" // for callback functions
|
||||
|
||||
static const char TAG[] __attribute__((unused)) = "MB_CONTROLLER_MASTER";
|
||||
|
||||
// This file implements public API for Modbus master controller.
|
||||
// These functions are wrappers for interface functions of the controller
|
||||
static mb_master_interface_t* master_interface_ptr = NULL;
|
||||
|
||||
@@ -43,6 +43,7 @@ static uint8_t mb_slave_id[] = { MB_ID_BYTE0(MB_CONTROLLER_SLAVE_ID),
|
||||
|
||||
// Common interface pointer for slave port
|
||||
static mb_slave_interface_t* slave_interface_ptr = NULL;
|
||||
static const char TAG[] __attribute__((unused)) = "MB_CONTROLLER_SLAVE";
|
||||
|
||||
// Searches the register in the area specified by type, returns descriptor if found, else NULL
|
||||
static mb_descr_entry_t* mbc_slave_find_reg_descriptor(mb_param_type_t type, uint16_t addr, size_t regs)
|
||||
@@ -259,11 +260,11 @@ static esp_err_t mbc_slave_send_param_info(mb_event_group_t par_type, uint16_t m
|
||||
par_info.mb_offset = mb_offset;
|
||||
BaseType_t status = xQueueSend(mbs_opts->mbs_notification_queue_handle, &par_info, MB_PAR_INFO_TOUT);
|
||||
if (pdTRUE == status) {
|
||||
ESP_LOGD(MB_SLAVE_TAG, "Queue send parameter info (type, address, size): %d, 0x%.4x, %d",
|
||||
ESP_LOGD(TAG, "Queue send parameter info (type, address, size): %d, 0x%.4x, %d",
|
||||
par_type, (uint32_t)par_address, par_size);
|
||||
error = ESP_OK;
|
||||
} else if (errQUEUE_FULL == status) {
|
||||
ESP_LOGD(MB_SLAVE_TAG, "Parameter queue is overflowed.");
|
||||
ESP_LOGD(TAG, "Parameter queue is overflowed.");
|
||||
}
|
||||
return error;
|
||||
}
|
||||
@@ -276,7 +277,7 @@ static esp_err_t mbc_slave_send_param_access_notification(mb_event_group_t event
|
||||
esp_err_t err = ESP_FAIL;
|
||||
mb_event_group_t bits = (mb_event_group_t)xEventGroupSetBits(mbs_opts->mbs_event_group, (EventBits_t)event);
|
||||
if (bits & event) {
|
||||
ESP_LOGD(MB_SLAVE_TAG, "The MB_REG_CHANGE_EVENT = 0x%.2x is set.", (uint8_t)event);
|
||||
ESP_LOGD(TAG, "The MB_REG_CHANGE_EVENT = 0x%.2x is set.", (uint8_t)event);
|
||||
err = ESP_OK;
|
||||
}
|
||||
return err;
|
||||
|
||||
@@ -22,6 +22,24 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if __has_include("esp_check.h")
|
||||
#include "esp_check.h"
|
||||
|
||||
#define MB_RETURN_ON_FALSE(a, err_code, tag, format, ...) ESP_RETURN_ON_FALSE(a, err_code, tag, format __VA_OPT__(,) __VA_ARGS__)
|
||||
|
||||
#else
|
||||
|
||||
// if cannot include esp_check then use custom check macro
|
||||
|
||||
#define MB_RETURN_ON_FALSE(a, err_code, tag, format, ...) do { \
|
||||
if (!(a)) { \
|
||||
ESP_LOGE(tag, "%s(%d): " format, __FUNCTION__, __LINE__ __VA_OPT__(,) __VA_ARGS__); \
|
||||
return err_code; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#endif
|
||||
|
||||
#define MB_CONTROLLER_STACK_SIZE (CONFIG_FMB_CONTROLLER_STACK_SIZE) // Stack size for Modbus controller
|
||||
#define MB_CONTROLLER_PRIORITY (CONFIG_FMB_PORT_TASK_PRIO - 1) // priority of MB controller task
|
||||
|
||||
|
||||
@@ -25,6 +25,12 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MB_MASTER_CHECK(a, err_code, format, ...) MB_RETURN_ON_FALSE(a, err_code, TAG, format __VA_OPT__(,) __VA_ARGS__)
|
||||
|
||||
#define MB_MASTER_ASSERT(con) do { \
|
||||
if (!(con)) { ESP_LOGE(TAG, "assert errno:%d, errno_str: !(%s)", errno, strerror(errno)); assert(0 && #con); } \
|
||||
} while (0)
|
||||
|
||||
/*!
|
||||
* \brief Modbus descriptor table parameter type defines.
|
||||
*/
|
||||
|
||||
@@ -28,6 +28,12 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MB_SLAVE_CHECK(a, err_code, format, ...) MB_RETURN_ON_FALSE(a, err_code, TAG, format __VA_OPT__(,) __VA_ARGS__)
|
||||
|
||||
#define MB_SLAVE_ASSERT(con) do { \
|
||||
if (!(con)) { ESP_LOGE(TAG, "assert errno:%d, errno_str: !(%s)", errno, strerror(errno)); assert(0 && #con); } \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief Parameter access event information type
|
||||
*/
|
||||
|
||||
@@ -12,9 +12,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _MB_CONTROLLER_MASTER_H
|
||||
#define _MB_CONTROLLER_MASTER_H
|
||||
|
||||
#include <sys/queue.h> // for list
|
||||
#include "freertos/FreeRTOS.h" // for task creation and queue access
|
||||
#include "freertos/task.h" // for task api access
|
||||
#include "freertos/event_groups.h" // for event groups
|
||||
@@ -28,18 +30,6 @@
|
||||
|
||||
/* ----------------------- Defines ------------------------------------------*/
|
||||
|
||||
#define MB_MASTER_TAG "MB_CONTROLLER_MASTER"
|
||||
|
||||
#define MB_MASTER_CHECK(a, ret_val, str, ...) \
|
||||
if (!(a)) { \
|
||||
ESP_LOGE(MB_MASTER_TAG, "%s(%u): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
|
||||
return (ret_val); \
|
||||
}
|
||||
|
||||
#define MB_MASTER_ASSERT(con) do { \
|
||||
if (!(con)) { ESP_LOGE(MB_MASTER_TAG, "assert errno:%d, errno_str: !(%s)", errno, strerror(errno)); assert(0 && #con); } \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief Request mode for parameter to use in data dictionary
|
||||
*/
|
||||
@@ -59,6 +49,19 @@ typedef struct {
|
||||
uart_parity_t parity; /*!< Modbus UART parity settings */
|
||||
} mb_master_comm_info_t;
|
||||
|
||||
#if MB_MASTER_TCP_ENABLED
|
||||
/**
|
||||
* @brief Modbus slave addr list item for the master
|
||||
*/
|
||||
typedef struct mb_slave_addr_entry_s{
|
||||
uint16_t index; /*!< Index of the slave address */
|
||||
const char* ip_address; /*!< IP address string of the slave */
|
||||
uint8_t slave_addr; /*!< Short slave address */
|
||||
void* p_data; /*!< pointer to data structure */
|
||||
LIST_ENTRY(mb_slave_addr_entry_s) entries; /*!< The slave address entry */
|
||||
} mb_slave_addr_entry_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Modbus controller handler structure
|
||||
*/
|
||||
@@ -71,6 +74,10 @@ typedef struct {
|
||||
EventGroupHandle_t mbm_event_group; /*!< Modbus controller event group */
|
||||
const mb_parameter_descriptor_t* mbm_param_descriptor_table; /*!< Modbus controller parameter description table */
|
||||
size_t mbm_param_descriptor_size; /*!< Modbus controller parameter description table size*/
|
||||
#if MB_MASTER_TCP_ENABLED
|
||||
LIST_HEAD(mbm_slave_addr_info_, mb_slave_addr_entry_s) mbm_slave_list; /*!< Slave address information list */
|
||||
uint16_t mbm_slave_list_count;
|
||||
#endif
|
||||
} mb_master_options_t;
|
||||
|
||||
typedef esp_err_t (*iface_get_cid_info)(uint16_t, const mb_parameter_descriptor_t**); /*!< Interface get_cid_info method */
|
||||
|
||||
@@ -31,18 +31,6 @@
|
||||
#define MB_CONTROLLER_NOTIFY_QUEUE_SIZE (CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE) // Number of messages in parameter notification queue
|
||||
#define MB_CONTROLLER_NOTIFY_TIMEOUT (pdMS_TO_TICKS(CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT)) // notification timeout
|
||||
|
||||
#define MB_SLAVE_TAG "MB_CONTROLLER_SLAVE"
|
||||
|
||||
#define MB_SLAVE_CHECK(a, ret_val, str, ...) \
|
||||
if (!(a)) { \
|
||||
ESP_LOGE(MB_SLAVE_TAG, "%s(%u): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
|
||||
return (ret_val); \
|
||||
}
|
||||
|
||||
#define MB_SLAVE_ASSERT(con) do { \
|
||||
if (!(con)) { ESP_LOGE(MB_SLAVE_TAG, "assert errno:%d, errno_str: !(%s)", errno, strerror(errno)); assert(0 && #con); } \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief Device communication parameters for master
|
||||
*/
|
||||
|
||||
@@ -40,6 +40,7 @@ extern BOOL xMBMasterPortSerialTxPoll(void);
|
||||
|
||||
|
||||
static mb_master_interface_t* mbm_interface_ptr = NULL; //&default_interface_inst;
|
||||
static const char *TAG = "MB_CONTROLLER_MASTER";
|
||||
|
||||
// Modbus event processing task
|
||||
static void modbus_master_task(void *pvParameters)
|
||||
@@ -238,7 +239,7 @@ static esp_err_t mbc_serial_master_send_request(mb_param_request_t* request, voi
|
||||
(USHORT)mb_size, (LONG) MB_RESPONSE_TICS );
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect function in request (%u) ",
|
||||
ESP_LOGE(TAG, "%s: Incorrect function in request (%u) ",
|
||||
__FUNCTION__, mb_command);
|
||||
mb_error = MB_MRE_NO_REG;
|
||||
break;
|
||||
@@ -269,7 +270,7 @@ static esp_err_t mbc_serial_master_send_request(mb_param_request_t* request, voi
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect return code (%x) ",
|
||||
ESP_LOGE(TAG, "%s: Incorrect return code (%x) ",
|
||||
__FUNCTION__, mb_error);
|
||||
error = ESP_FAIL;
|
||||
break;
|
||||
@@ -324,12 +325,12 @@ static uint8_t mbc_serial_master_get_command(mb_param_type_t param_type, mb_para
|
||||
if (mode != MB_PARAM_WRITE) {
|
||||
command = MB_FUNC_READ_DISCRETE_INPUTS;
|
||||
} else {
|
||||
ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect mode (%u)",
|
||||
ESP_LOGE(TAG, "%s: Incorrect mode (%u)",
|
||||
__FUNCTION__, (uint8_t)mode);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect param type (%u)",
|
||||
ESP_LOGE(TAG, "%s: Incorrect param type (%u)",
|
||||
__FUNCTION__, param_type);
|
||||
break;
|
||||
}
|
||||
@@ -401,16 +402,16 @@ static esp_err_t mbc_serial_master_get_parameter(uint16_t cid, char* name,
|
||||
// Send request to read characteristic data
|
||||
error = mbc_serial_master_send_request(&request, value_ptr);
|
||||
if (error == ESP_OK) {
|
||||
ESP_LOGD(MB_MASTER_TAG, "%s: Good response for get cid(%u) = %s",
|
||||
ESP_LOGD(TAG, "%s: Good response for get cid(%u) = %s",
|
||||
__FUNCTION__, (int)reg_info.cid, (char*)esp_err_to_name(error));
|
||||
} else {
|
||||
ESP_LOGD(MB_MASTER_TAG, "%s: Bad response to get cid(%u) = %s",
|
||||
ESP_LOGD(TAG, "%s: Bad response to get cid(%u) = %s",
|
||||
__FUNCTION__, reg_info.cid, (char*)esp_err_to_name(error));
|
||||
}
|
||||
// Set the type of parameter found in the table
|
||||
*type = reg_info.param_type;
|
||||
} else {
|
||||
ESP_LOGE(MB_MASTER_TAG, "%s: The cid(%u) not found in the data dictionary.",
|
||||
ESP_LOGE(TAG, "%s: The cid(%u) not found in the data dictionary.",
|
||||
__FUNCTION__, reg_info.cid);
|
||||
error = ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
@@ -436,16 +437,16 @@ static esp_err_t mbc_serial_master_set_parameter(uint16_t cid, char* name,
|
||||
// Send request to write characteristic data
|
||||
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",
|
||||
ESP_LOGD(TAG, "%s: Good response for set cid(%u) = %s",
|
||||
__FUNCTION__, (int)reg_info.cid, (char*)esp_err_to_name(error));
|
||||
} else {
|
||||
ESP_LOGD(MB_MASTER_TAG, "%s: Bad response to set cid(%u) = %s",
|
||||
ESP_LOGD(TAG, "%s: Bad response to set cid(%u) = %s",
|
||||
__FUNCTION__, reg_info.cid, (char*)esp_err_to_name(error));
|
||||
}
|
||||
// Set the type of parameter found in the table
|
||||
*type = reg_info.param_type;
|
||||
} else {
|
||||
ESP_LOGE(MB_MASTER_TAG, "%s: The requested cid(%u) not found in the data dictionary.",
|
||||
ESP_LOGE(TAG, "%s: The requested cid(%u) not found in the data dictionary.",
|
||||
__FUNCTION__, reg_info.cid);
|
||||
error = ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
// Shared pointer to interface structure
|
||||
static mb_slave_interface_t* mbs_interface_ptr = NULL;
|
||||
static const char *TAG = "MB_CONTROLLER_SLAVE";
|
||||
|
||||
// Modbus task function
|
||||
static void modbus_slave_task(void *pvParameters)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <sys/time.h> // for calculation of time stamp in milliseconds
|
||||
#include "esp_log.h" // for log_write
|
||||
#include <string.h> // for memcpy
|
||||
#include <sys/queue.h> // for list
|
||||
#include "freertos/FreeRTOS.h" // for task creation and queue access
|
||||
#include "freertos/task.h" // for task api access
|
||||
#include "freertos/event_groups.h" // for event groups
|
||||
@@ -42,6 +43,59 @@
|
||||
#define MB_TCP_CONNECTION_TOUT pdMS_TO_TICKS(CONFIG_FMB_TCP_CONNECTION_TOUT_SEC * 1000)
|
||||
|
||||
static mb_master_interface_t* mbm_interface_ptr = NULL;
|
||||
static const char *TAG = "MB_CONTROLLER_MASTER";
|
||||
|
||||
// Searches the slave address in the address info list and returns address info if found, else NULL
|
||||
static mb_slave_addr_entry_t* mbc_tcp_master_find_slave_addr(uint8_t slave_addr)
|
||||
{
|
||||
mb_slave_addr_entry_t* it;
|
||||
mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts;
|
||||
|
||||
if (LIST_EMPTY(&mbm_opts->mbm_slave_list)) {
|
||||
return NULL;
|
||||
}
|
||||
LIST_FOREACH(it, &mbm_opts->mbm_slave_list, entries) {
|
||||
if (slave_addr == it->slave_addr) {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static esp_err_t mbc_tcp_master_add_slave(uint16_t index, uint8_t slave_addr, const char* ip_addr)
|
||||
{
|
||||
MB_MASTER_ASSERT(mbm_interface_ptr != NULL);
|
||||
// Initialize interface properties
|
||||
mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts;
|
||||
|
||||
mb_slave_addr_entry_t* new_slave_entry = (mb_slave_addr_entry_t*) heap_caps_malloc(sizeof(mb_slave_addr_entry_t),
|
||||
MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
MB_MASTER_CHECK((new_slave_entry != NULL), ESP_ERR_NO_MEM, "mb can not allocate memory for slave entry.");
|
||||
new_slave_entry->index = index;
|
||||
new_slave_entry->ip_address = ip_addr;
|
||||
new_slave_entry->slave_addr = slave_addr;
|
||||
new_slave_entry->p_data = NULL;
|
||||
LIST_INSERT_HEAD(&mbm_opts->mbm_slave_list, new_slave_entry, entries);
|
||||
MB_MASTER_CHECK((mbm_opts->mbm_slave_list_count < (MB_TCP_PORT_MAX_CONN - 1)),
|
||||
ESP_ERR_INVALID_STATE, "mb max number of slaves < %d.", MB_TCP_PORT_MAX_CONN);
|
||||
mbm_opts->mbm_slave_list_count++;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void mbc_tcp_master_free_slave_list(void)
|
||||
{
|
||||
mb_slave_addr_entry_t* it;
|
||||
MB_MASTER_ASSERT(mbm_interface_ptr != NULL);
|
||||
|
||||
// Initialize interface properties
|
||||
mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts;
|
||||
|
||||
LIST_FOREACH(it, &mbm_opts->mbm_slave_list, entries) {
|
||||
LIST_REMOVE(it, entries);
|
||||
mbm_opts->mbm_slave_list_count--;
|
||||
free(it);
|
||||
}
|
||||
}
|
||||
|
||||
// Modbus event processing task
|
||||
static void modbus_tcp_master_task(void *pvParameters)
|
||||
@@ -113,21 +167,21 @@ static esp_err_t mbc_tcp_master_start(void)
|
||||
vMBTCPPortMasterSetNetOpt(comm_info->ip_netif_ptr, ip_ver, proto);
|
||||
vMBTCPPortMasterTaskStart();
|
||||
|
||||
// Add slave IP address for each slave to initialise connection
|
||||
for (int idx = 0; *comm_ip_table != NULL; idx++, comm_ip_table++)
|
||||
{
|
||||
result = (BOOL)xMBTCPPortMasterAddSlaveIp(*comm_ip_table);
|
||||
// Add slave IP address for each slave to initialize connection
|
||||
mb_slave_addr_entry_t *p_slave_info;
|
||||
|
||||
LIST_FOREACH(p_slave_info, &mbm_opts->mbm_slave_list, entries) {
|
||||
result = (BOOL)xMBTCPPortMasterAddSlaveIp(p_slave_info->index, p_slave_info->ip_address, p_slave_info->slave_addr);
|
||||
MB_MASTER_CHECK(result, ESP_ERR_INVALID_STATE, "mb stack add slave IP failed: %s.", *comm_ip_table);
|
||||
}
|
||||
// Init polling event handlers and wait before start polling
|
||||
xMBTCPPortMasterWaitEvent(mbm_opts->mbm_event_group, (EventBits_t)MB_EVENT_STACK_STARTED, 1);
|
||||
|
||||
// Add end of list condition
|
||||
(void)xMBTCPPortMasterAddSlaveIp(0xFF, NULL, 0xFF);
|
||||
|
||||
status = eMBMasterEnable();
|
||||
MB_MASTER_CHECK((status == MB_ENOERR), ESP_ERR_INVALID_STATE,
|
||||
"mb stack set slave ID failure, eMBMasterEnable() returned (0x%x).", (uint32_t)status);
|
||||
|
||||
// Send end of list condition to start connection phase
|
||||
(void)xMBTCPPortMasterAddSlaveIp(NULL);
|
||||
|
||||
// Wait for connection done event
|
||||
bool start = (bool)xMBTCPPortMasterWaitEvent(mbm_opts->mbm_event_group,
|
||||
@@ -160,6 +214,7 @@ static esp_err_t mbc_tcp_master_destroy(void)
|
||||
mbm_opts->mbm_task_handle = NULL;
|
||||
(void)vEventGroupDelete(mbm_opts->mbm_event_group);
|
||||
mbm_opts->mbm_event_group = NULL;
|
||||
mbc_tcp_master_free_slave_list();
|
||||
free(mbm_interface_ptr); // free the memory allocated for options
|
||||
vMBPortSetMode((UCHAR)MB_PORT_INACTIVE);
|
||||
mbm_interface_ptr = NULL;
|
||||
@@ -179,14 +234,25 @@ static esp_err_t mbc_tcp_master_set_descriptor(const mb_parameter_descriptor_t*
|
||||
MB_MASTER_CHECK((comm_ip_table != NULL), ESP_ERR_INVALID_ARG, "mb ip table address is incorrect.");
|
||||
|
||||
const mb_parameter_descriptor_t *reg_ptr = descriptor;
|
||||
uint16_t slave_cnt = 0;
|
||||
mb_slave_addr_entry_t* p_slave = NULL;
|
||||
|
||||
// Go through all items in the table to check all Modbus registers
|
||||
for (uint16_t counter = 0; counter < (num_elements); counter++, reg_ptr++)
|
||||
for (int idx = 0; idx < (num_elements); idx++, reg_ptr++)
|
||||
{
|
||||
MB_MASTER_CHECK((comm_ip_table[reg_ptr->mb_slave_addr - 1] != NULL), ESP_ERR_INVALID_ARG, "mb ip table address is incorrect.");
|
||||
// Below is the code to check consistency of the table format and required fields.
|
||||
MB_MASTER_CHECK((reg_ptr->cid == counter), ESP_ERR_INVALID_ARG, "mb descriptor cid field is incorrect.");
|
||||
MB_MASTER_CHECK((reg_ptr->cid == idx), ESP_ERR_INVALID_ARG, "mb descriptor cid field is incorrect.");
|
||||
MB_MASTER_CHECK((reg_ptr->param_key != NULL), ESP_ERR_INVALID_ARG, "mb descriptor param key is incorrect.");
|
||||
MB_MASTER_CHECK((reg_ptr->mb_size > 0), ESP_ERR_INVALID_ARG, "mb descriptor param size is incorrect.");
|
||||
// Is the slave already in the list?
|
||||
p_slave = mbc_tcp_master_find_slave_addr(reg_ptr->mb_slave_addr);
|
||||
// Add it to slave list if not there.
|
||||
if (!p_slave) {
|
||||
// Is the IP address correctly defined for the slave?
|
||||
MB_MASTER_CHECK((comm_ip_table[slave_cnt]), ESP_ERR_INVALID_STATE, "mb missing IP address for cid #%d.", reg_ptr->cid);
|
||||
// Add slave to the list
|
||||
MB_MASTER_ASSERT(mbc_tcp_master_add_slave(idx, reg_ptr->mb_slave_addr, comm_ip_table[slave_cnt++]) == ESP_OK);
|
||||
}
|
||||
}
|
||||
mbm_opts->mbm_param_descriptor_table = descriptor;
|
||||
mbm_opts->mbm_param_descriptor_size = num_elements;
|
||||
@@ -258,7 +324,7 @@ static esp_err_t mbc_tcp_master_send_request(mb_param_request_t* request, void*
|
||||
(USHORT)mb_size, (LONG) MB_RESPONSE_TIMEOUT );
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect function in request (%u) ",
|
||||
ESP_LOGE(TAG, "%s: Incorrect function in request (%u) ",
|
||||
__FUNCTION__, mb_command);
|
||||
mb_error = MB_MRE_NO_REG;
|
||||
break;
|
||||
@@ -289,7 +355,7 @@ static esp_err_t mbc_tcp_master_send_request(mb_param_request_t* request, void*
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect return code (%x) ", __FUNCTION__, mb_error);
|
||||
ESP_LOGE(TAG, "%s: Incorrect return code (%x) ", __FUNCTION__, mb_error);
|
||||
error = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
@@ -333,11 +399,11 @@ static uint8_t mbc_tcp_master_get_command(mb_param_type_t param_type, mb_param_m
|
||||
if (mode != MB_PARAM_WRITE) {
|
||||
command = MB_FUNC_READ_DISCRETE_INPUTS;
|
||||
} else {
|
||||
ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect mode (%u)", __FUNCTION__, (uint8_t)mode);
|
||||
ESP_LOGE(TAG, "%s: Incorrect mode (%u)", __FUNCTION__, (uint8_t)mode);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect param type (%u)", __FUNCTION__, param_type);
|
||||
ESP_LOGE(TAG, "%s: Incorrect param type (%u)", __FUNCTION__, param_type);
|
||||
break;
|
||||
}
|
||||
return command;
|
||||
@@ -368,7 +434,7 @@ static esp_err_t mbc_tcp_master_set_param_data(void* dest, void* src, mb_descr_t
|
||||
memcpy((void*)dest, (void*)src, (size_t)param_size);
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect param type (%u).",
|
||||
ESP_LOGE(TAG, "%s: Incorrect param type (%u).",
|
||||
__FUNCTION__, (uint16_t)param_type);
|
||||
err = ESP_ERR_NOT_SUPPORTED;
|
||||
break;
|
||||
@@ -420,31 +486,43 @@ static esp_err_t mbc_tcp_master_get_parameter(uint16_t cid, char* name, uint8_t*
|
||||
{
|
||||
MB_MASTER_CHECK((name != NULL), ESP_ERR_INVALID_ARG, "mb incorrect descriptor.");
|
||||
MB_MASTER_CHECK((type != NULL), ESP_ERR_INVALID_ARG, "type pointer is incorrect.");
|
||||
MB_MASTER_CHECK((value != NULL), ESP_ERR_INVALID_ARG, "value 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 };
|
||||
uint8_t* pdata = NULL;
|
||||
|
||||
error = mbc_tcp_master_set_request(name, MB_PARAM_READ, &request, ®_info);
|
||||
if ((error == ESP_OK) && (cid == reg_info.cid)) {
|
||||
error = mbc_tcp_master_send_request(&request, ¶m_buffer[0]);
|
||||
// alloc buffer to store parameter data
|
||||
pdata = calloc(1, (reg_info.mb_size << 1));
|
||||
if (!pdata) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
error = mbc_tcp_master_send_request(&request, pdata);
|
||||
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_tcp_master_set_param_data((void*)value, (void*)¶m_buffer[0],
|
||||
error = mbc_tcp_master_set_param_data((void*)value, (void*)pdata,
|
||||
reg_info.param_type, reg_info.param_size);
|
||||
MB_MASTER_CHECK((error == ESP_OK), ESP_ERR_INVALID_STATE, "fail to set parameter data.");
|
||||
if (error != ESP_OK) {
|
||||
ESP_LOGE(TAG, "fail to set parameter data.");
|
||||
error = ESP_ERR_INVALID_STATE;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "%s: Good response for get cid(%u) = %s",
|
||||
__FUNCTION__, (unsigned)reg_info.cid, (char*)esp_err_to_name(error));
|
||||
}
|
||||
}
|
||||
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 {
|
||||
ESP_LOGD(MB_MASTER_TAG, "%s: Bad response to get cid(%u) = %s",
|
||||
ESP_LOGD(TAG, "%s: Bad response to get cid(%u) = %s",
|
||||
__FUNCTION__, reg_info.cid, (char*)esp_err_to_name(error));
|
||||
error = ESP_ERR_INVALID_RESPONSE;
|
||||
}
|
||||
free(pdata);
|
||||
// Set the type of parameter found in the table
|
||||
*type = reg_info.param_type;
|
||||
} else {
|
||||
ESP_LOGE(MB_MASTER_TAG, "%s: The cid(%u) not found in the data dictionary.",
|
||||
ESP_LOGE(TAG, "%s: The cid(%u) not found in the data dictionary.",
|
||||
__FUNCTION__, reg_info.cid);
|
||||
error = ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
@@ -461,27 +539,36 @@ static esp_err_t mbc_tcp_master_set_parameter(uint16_t cid, char* name, uint8_t*
|
||||
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 };
|
||||
uint8_t* pdata = NULL;
|
||||
|
||||
error = mbc_tcp_master_set_request(name, MB_PARAM_WRITE, &request, ®_info);
|
||||
if ((error == ESP_OK) && (cid == reg_info.cid)) {
|
||||
pdata = calloc(1, (reg_info.mb_size << 1)); // alloc parameter buffer
|
||||
if (!pdata) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
// Transfer value of characteristic into parameter buffer
|
||||
error = mbc_tcp_master_set_param_data((void*)¶m_buffer[0], (void*)value,
|
||||
error = mbc_tcp_master_set_param_data((void*)pdata, (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.");
|
||||
if (error != ESP_OK) {
|
||||
ESP_LOGE(TAG, "fail to set parameter data.");
|
||||
free(pdata);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
// Send request to write characteristic data
|
||||
error = mbc_tcp_master_send_request(&request, ¶m_buffer[0]);
|
||||
error = mbc_tcp_master_send_request(&request, pdata);
|
||||
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));
|
||||
ESP_LOGD(TAG, "%s: Good response for set cid(%u) = %s",
|
||||
__FUNCTION__, (unsigned)reg_info.cid, (char*)esp_err_to_name(error));
|
||||
} else {
|
||||
ESP_LOGD(MB_MASTER_TAG, "%s: Bad response to set cid(%u) = %s",
|
||||
ESP_LOGD(TAG, "%s: Bad response to set cid(%u) = %s",
|
||||
__FUNCTION__, reg_info.cid, (char*)esp_err_to_name(error));
|
||||
}
|
||||
free(pdata);
|
||||
// Set the type of parameter found in the table
|
||||
*type = reg_info.param_type;
|
||||
} else {
|
||||
ESP_LOGE(MB_MASTER_TAG, "%s: The requested cid(%u) not found in the data dictionary.",
|
||||
ESP_LOGE(TAG, "%s: The requested cid(%u) not found in the data dictionary.",
|
||||
__FUNCTION__, reg_info.cid);
|
||||
error = ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
@@ -709,6 +796,9 @@ esp_err_t mbc_tcp_master_create(void** handler)
|
||||
}
|
||||
MB_MASTER_ASSERT(mbm_opts->mbm_task_handle != NULL); // The task is created but handle is incorrect
|
||||
|
||||
LIST_INIT(&mbm_opts->mbm_slave_list); // Init slave address list
|
||||
mbm_opts->mbm_slave_list_count = 0;
|
||||
|
||||
// Initialize public interface methods of the interface
|
||||
mbm_interface_ptr->init = mbc_tcp_master_create;
|
||||
mbm_interface_ptr->destroy = mbc_tcp_master_destroy;
|
||||
|
||||
@@ -66,7 +66,6 @@
|
||||
#define MB_TCP_CONNECTION_TIMEOUT_MS ( 20 ) // Connection timeout in mS
|
||||
#define MB_TCP_RECONNECT_TIMEOUT ( 5000000 ) // Connection timeout in uS
|
||||
|
||||
#define MB_TCP_MASTER_PORT_TAG "MB_TCP_MASTER_PORT"
|
||||
#define MB_EVENT_REQ_DONE_MASK ( EV_MASTER_PROCESS_SUCCESS | \
|
||||
EV_MASTER_ERROR_RESPOND_TIMEOUT | \
|
||||
EV_MASTER_ERROR_RECEIVE_DATA | \
|
||||
@@ -84,6 +83,7 @@
|
||||
void vMBPortEventClose( void );
|
||||
|
||||
/* ----------------------- Static variables ---------------------------------*/
|
||||
static const char *TAG = "MB_TCP_MASTER_PORT";
|
||||
static MbPortConfig_t xMbPortConfig;
|
||||
static EventGroupHandle_t xMasterEventHandle = NULL;
|
||||
static SemaphoreHandle_t xShutdownSemaphore = NULL;
|
||||
@@ -114,7 +114,7 @@ xMBMasterTCPPortInit( USHORT usTCPPort )
|
||||
|
||||
xMbPortConfig.pxMbSlaveInfo = calloc(MB_TCP_PORT_MAX_CONN, sizeof(MbSlaveInfo_t*));
|
||||
if (!xMbPortConfig.pxMbSlaveInfo) {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "TCP slave info alloc failure.");
|
||||
ESP_LOGE(TAG, "TCP slave info alloc failure.");
|
||||
return FALSE;
|
||||
}
|
||||
for(int idx = 0; idx < MB_TCP_PORT_MAX_CONN; xMbPortConfig.pxMbSlaveInfo[idx] = NULL, idx++);
|
||||
@@ -123,12 +123,13 @@ xMBMasterTCPPortInit( USHORT usTCPPort )
|
||||
xMbPortConfig.usPort = usTCPPort;
|
||||
xMbPortConfig.usMbSlaveInfoCount = 0;
|
||||
xMbPortConfig.ucCurSlaveIndex = 1;
|
||||
xMbPortConfig.pxMbSlaveCurrInfo = NULL;
|
||||
|
||||
xMbPortConfig.xConnectQueue = xQueueCreate(2, sizeof(CHAR*));
|
||||
xMbPortConfig.xConnectQueue = xQueueCreate(2, sizeof(MbSlaveAddrInfo_t));
|
||||
if (xMbPortConfig.xConnectQueue == 0)
|
||||
{
|
||||
// Queue was not created and must not be used.
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "TCP master queue creation failure.");
|
||||
ESP_LOGE(TAG, "TCP master queue creation failure.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -142,10 +143,10 @@ xMBMasterTCPPortInit( USHORT usTCPPort )
|
||||
MB_PORT_TASK_AFFINITY);
|
||||
if (xErr != pdTRUE)
|
||||
{
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "TCP master task creation failure.");
|
||||
ESP_LOGE(TAG, "TCP master task creation failure.");
|
||||
(void)vTaskDelete(xMbPortConfig.xMbTcpTaskHandle);
|
||||
} else {
|
||||
ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "TCP master stack initialized.");
|
||||
ESP_LOGI(TAG, "TCP master stack initialized.");
|
||||
bOkay = TRUE;
|
||||
}
|
||||
|
||||
@@ -153,9 +154,30 @@ xMBMasterTCPPortInit( USHORT usTCPPort )
|
||||
return bOkay;
|
||||
}
|
||||
|
||||
static MbSlaveInfo_t* vMBTCPPortMasterFindSlaveInfo(UCHAR ucSlaveAddr)
|
||||
{
|
||||
int xIndex;
|
||||
BOOL xFound = false;
|
||||
for (xIndex = 0; xIndex < xMbPortConfig.usMbSlaveInfoCount; xIndex++) {
|
||||
if (xMbPortConfig.pxMbSlaveInfo[xIndex]->ucSlaveAddr == ucSlaveAddr) {
|
||||
xMbPortConfig.pxMbSlaveCurrInfo = xMbPortConfig.pxMbSlaveInfo[xIndex];
|
||||
xFound = TRUE;
|
||||
xMbPortConfig.ucCurSlaveIndex = xIndex;
|
||||
}
|
||||
}
|
||||
if (!xFound) {
|
||||
xMbPortConfig.pxMbSlaveCurrInfo = NULL;
|
||||
ESP_LOGE(TAG, "Slave info for short address %d not found.", ucSlaveAddr);
|
||||
}
|
||||
return xMbPortConfig.pxMbSlaveCurrInfo;
|
||||
}
|
||||
|
||||
static MbSlaveInfo_t* vMBTCPPortMasterGetCurrInfo(void)
|
||||
{
|
||||
return xMbPortConfig.pxMbSlaveInfo[xMbPortConfig.ucCurSlaveIndex - 1];
|
||||
if (!xMbPortConfig.pxMbSlaveCurrInfo) {
|
||||
ESP_LOGE(TAG, "Incorrect current slave info.");
|
||||
}
|
||||
return xMbPortConfig.pxMbSlaveCurrInfo;
|
||||
}
|
||||
|
||||
// Start Modbus event state machine
|
||||
@@ -166,10 +188,10 @@ static void vMBTCPPortMasterStartPoll(void)
|
||||
EventBits_t xFlags = xEventGroupSetBits(xMasterEventHandle,
|
||||
(EventBits_t)xMasterEvent);
|
||||
if (!(xFlags & xMasterEvent)) {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to start TCP stack.");
|
||||
ESP_LOGE(TAG, "Fail to start TCP stack.");
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to start polling. Incorrect event handle...");
|
||||
ESP_LOGE(TAG, "Fail to start polling. Incorrect event handle...");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,10 +203,10 @@ static void vMBTCPPortMasterStopPoll(void)
|
||||
EventBits_t xFlags = xEventGroupClearBits(xMasterEventHandle,
|
||||
(EventBits_t)xMasterEvent);
|
||||
if (!(xFlags & xMasterEvent)) {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to stop polling.");
|
||||
ESP_LOGE(TAG, "Fail to stop polling.");
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to stop polling. Incorrect event handle...");
|
||||
ESP_LOGE(TAG, "Fail to stop polling. Incorrect event handle...");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,11 +237,11 @@ static BOOL xMBTCPPortMasterCloseConnection(MbSlaveInfo_t* pxInfo)
|
||||
return FALSE;
|
||||
}
|
||||
if (pxInfo->xSockId == -1) {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Wrong socket info or disconnected socket: %d, skip.", pxInfo->xSockId);
|
||||
ESP_LOGE(TAG, "Wrong socket info or disconnected socket: %d, skip.", pxInfo->xSockId);
|
||||
return FALSE;
|
||||
}
|
||||
if (shutdown(pxInfo->xSockId, SHUT_RDWR) == -1) {
|
||||
ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Shutdown failed sock %d, errno=%d", pxInfo->xSockId, errno);
|
||||
ESP_LOGV(TAG, "Shutdown failed sock %d, errno=%d", pxInfo->xSockId, errno);
|
||||
}
|
||||
close(pxInfo->xSockId);
|
||||
pxInfo->xSockId = -1;
|
||||
@@ -289,12 +311,12 @@ static int xMBTCPPortMasterGetBuf(MbSlaveInfo_t* pxInfo, UCHAR* pucDstBuf, USHOR
|
||||
continue;
|
||||
} else if (errno == ENOTCONN) {
|
||||
// Socket connection closed
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s) connection closed.",
|
||||
ESP_LOGE(TAG, "Socket(#%d)(%s) connection closed.",
|
||||
pxInfo->xSockId, pxInfo->pcIpAddr);
|
||||
return ERR_CONN;
|
||||
} else {
|
||||
// Other error occurred during receiving
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s) receive error, length=%d, errno=%d",
|
||||
ESP_LOGE(TAG, "Socket(#%d)(%s) receive error, length=%d, errno=%d",
|
||||
pxInfo->xSockId, pxInfo->pcIpAddr, xLength, errno);
|
||||
return -1;
|
||||
}
|
||||
@@ -325,7 +347,7 @@ static int vMBTCPPortMasterReadPacket(MbSlaveInfo_t* pxInfo)
|
||||
pxInfo->xRcvErr = xRet;
|
||||
return xRet;
|
||||
} else if (xRet != MB_TCP_UID) {
|
||||
ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Socket (#%d)(%s), Fail to read modbus header. ret=%d",
|
||||
ESP_LOGD(TAG, "Socket (#%d)(%s), Fail to read modbus header. ret=%d",
|
||||
pxInfo->xSockId, pxInfo->pcIpAddr, xRet);
|
||||
pxInfo->xRcvErr = ERR_VAL;
|
||||
return ERR_VAL;
|
||||
@@ -339,7 +361,7 @@ static int vMBTCPPortMasterReadPacket(MbSlaveInfo_t* pxInfo)
|
||||
return xRet;
|
||||
} else if (xRet != xLength) {
|
||||
// Received incorrect or fragmented packet.
|
||||
ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s) incorrect packet, length=%d, TID=0x%02x, errno=%d(%s)",
|
||||
ESP_LOGD(TAG, "Socket(#%d)(%s) incorrect packet, length=%d, TID=0x%02x, errno=%d(%s)",
|
||||
pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->usRcvPos,
|
||||
usTidRcv, errno, strerror(errno));
|
||||
pxInfo->xRcvErr = ERR_VAL;
|
||||
@@ -349,13 +371,13 @@ static int vMBTCPPortMasterReadPacket(MbSlaveInfo_t* pxInfo)
|
||||
|
||||
// Check transaction identifier field in the incoming packet.
|
||||
if ((pxInfo->usTidCnt - 1) != usTidRcv) {
|
||||
ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Socket (#%d)(%s), incorrect TID(0x%02x)!=(0x%02x) received, discard data.",
|
||||
ESP_LOGD(TAG, "Socket (#%d)(%s), incorrect TID(0x%02x)!=(0x%02x) received, discard data.",
|
||||
pxInfo->xSockId, pxInfo->pcIpAddr, usTidRcv, (pxInfo->usTidCnt - 1));
|
||||
pxInfo->xRcvErr = ERR_BUF;
|
||||
return ERR_BUF;
|
||||
}
|
||||
pxInfo->usRcvPos += xRet + MB_TCP_UID;
|
||||
ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s) get data, length=%d, TID=0x%02x, errno=%d(%s)",
|
||||
ESP_LOGD(TAG, "Socket(#%d)(%s) get data, length=%d, TID=0x%02x, errno=%d(%s)",
|
||||
pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->usRcvPos,
|
||||
usTidRcv, errno, strerror(errno));
|
||||
pxInfo->xRcvErr = ERR_OK;
|
||||
@@ -372,7 +394,7 @@ static err_t xMBTCPPortMasterSetNonBlocking(MbSlaveInfo_t* pxInfo)
|
||||
// Set non blocking attribute for socket
|
||||
ULONG ulFlags = fcntl(pxInfo->xSockId, F_GETFL);
|
||||
if (fcntl(pxInfo->xSockId, F_SETFL, ulFlags | O_NONBLOCK) == -1) {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s), fcntl() call error=%d",
|
||||
ESP_LOGE(TAG, "Socket(#%d)(%s), fcntl() call error=%d",
|
||||
pxInfo->xSockId, pxInfo->pcIpAddr, errno);
|
||||
return ERR_WOULDBLOCK;
|
||||
}
|
||||
@@ -405,12 +427,12 @@ static err_t xMBTCPPortMasterCheckAlive(MbSlaveInfo_t* pxInfo, ULONG xTimeoutMs)
|
||||
if (errno == EINPROGRESS) {
|
||||
xErr = ERR_INPROGRESS;
|
||||
} else {
|
||||
ESP_LOGV(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(" connection, select write err(errno) = %d(%d)."),
|
||||
ESP_LOGV(TAG, MB_SLAVE_FMT(" connection, select write err(errno) = %d(%d)."),
|
||||
pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xErr, errno);
|
||||
xErr = ERR_CONN;
|
||||
}
|
||||
} else if (xErr == 0) {
|
||||
ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s), connection timeout occurred, err(errno) = %d(%d).",
|
||||
ESP_LOGV(TAG, "Socket(#%d)(%s), connection timeout occurred, err(errno) = %d(%d).",
|
||||
pxInfo->xSockId, pxInfo->pcIpAddr, xErr, errno);
|
||||
return ERR_INPROGRESS;
|
||||
} else {
|
||||
@@ -419,11 +441,11 @@ static err_t xMBTCPPortMasterCheckAlive(MbSlaveInfo_t* pxInfo, ULONG xTimeoutMs)
|
||||
// Check socket error
|
||||
xErr = getsockopt(pxInfo->xSockId, SOL_SOCKET, SO_ERROR, (void*)&xOptErr, (socklen_t*)&ulOptLen);
|
||||
if (xOptErr != 0) {
|
||||
ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s), sock error occurred (%d).",
|
||||
ESP_LOGD(TAG, "Socket(#%d)(%s), sock error occurred (%d).",
|
||||
pxInfo->xSockId, pxInfo->pcIpAddr, xOptErr);
|
||||
return ERR_CONN;
|
||||
}
|
||||
ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s), is alive.",
|
||||
ESP_LOGV(TAG, "Socket(#%d)(%s), is alive.",
|
||||
pxInfo->xSockId, pxInfo->pcIpAddr);
|
||||
return ERR_OK;
|
||||
}
|
||||
@@ -453,7 +475,7 @@ static BOOL xMBTCPPortMasterCheckHost(const CHAR* pcHostStr, ip_addr_t* pxHostAd
|
||||
int xRet = getaddrinfo(pcHostStr, NULL, &xHint, &pxAddrList);
|
||||
|
||||
if (xRet != 0) {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Incorrect host name or IP: %s", pcHostStr);
|
||||
ESP_LOGE(TAG, "Incorrect host name or IP: %s", pcHostStr);
|
||||
return FALSE;
|
||||
}
|
||||
if (pxAddrList->ai_family == AF_INET) {
|
||||
@@ -471,20 +493,24 @@ static BOOL xMBTCPPortMasterCheckHost(const CHAR* pcHostStr, ip_addr_t* pxHostAd
|
||||
if (pxHostAddr) {
|
||||
*pxHostAddr = xTargetAddr;
|
||||
}
|
||||
ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "Host[IP]: \"%s\"[%s]", pxAddrList->ai_canonname, pcStr);
|
||||
ESP_LOGI(TAG, "Host[IP]: \"%s\"[%s]", pxAddrList->ai_canonname, pcStr);
|
||||
freeaddrinfo(pxAddrList);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL xMBTCPPortMasterAddSlaveIp(const CHAR* pcIpStr)
|
||||
BOOL xMBTCPPortMasterAddSlaveIp(const USHORT usIndex, const CHAR* pcIpStr, UCHAR ucSlaveAddress)
|
||||
{
|
||||
BOOL xRes = FALSE;
|
||||
MbSlaveAddrInfo_t xSlaveAddrInfo = { 0 };
|
||||
MB_PORT_CHECK(xMbPortConfig.xConnectQueue != NULL, FALSE, "Wrong slave IP address to add.");
|
||||
if (pcIpStr) {
|
||||
if (pcIpStr && (usIndex != 0xFF)) {
|
||||
xRes = xMBTCPPortMasterCheckHost(pcIpStr, NULL);
|
||||
}
|
||||
if (xRes || !pcIpStr) {
|
||||
BaseType_t xStatus = xQueueSend(xMbPortConfig.xConnectQueue, (const void*)&pcIpStr, 100);
|
||||
xSlaveAddrInfo.pcIPAddr = pcIpStr;
|
||||
xSlaveAddrInfo.usIndex = usIndex;
|
||||
xSlaveAddrInfo.ucSlaveAddr = ucSlaveAddress;
|
||||
BaseType_t xStatus = xQueueSend(xMbPortConfig.xConnectQueue, (void*)&xSlaveAddrInfo, 100);
|
||||
MB_PORT_CHECK((xStatus == pdTRUE), FALSE, "FAIL to add slave IP address: [%s].", pcIpStr);
|
||||
}
|
||||
return xRes;
|
||||
@@ -522,7 +548,7 @@ static err_t xMBTCPPortMasterConnect(MbSlaveInfo_t* pxInfo)
|
||||
int xRet = getaddrinfo(pxInfo->pcIpAddr, pcStr, &xHint, &pxAddrList);
|
||||
free(pcStr);
|
||||
if (xRet != 0) {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Cannot resolve host: %s", pxInfo->pcIpAddr);
|
||||
ESP_LOGE(TAG, "Cannot resolve host: %s", pxInfo->pcIpAddr);
|
||||
return ERR_CONN;
|
||||
}
|
||||
|
||||
@@ -545,12 +571,12 @@ static err_t xMBTCPPortMasterConnect(MbSlaveInfo_t* pxInfo)
|
||||
if (pxInfo->xSockId <= 0) {
|
||||
pxInfo->xSockId = socket(pxCurAddr->ai_family, pxCurAddr->ai_socktype, pxCurAddr->ai_protocol);
|
||||
if (pxInfo->xSockId < 0) {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Unable to create socket: #%d, errno %d", pxInfo->xSockId, errno);
|
||||
ESP_LOGE(TAG, "Unable to create socket: #%d, errno %d", pxInfo->xSockId, errno);
|
||||
xErr = ERR_IF;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Socket (#%d)(%s) created.", pxInfo->xSockId, cStr);
|
||||
ESP_LOGV(TAG, "Socket (#%d)(%s) created.", pxInfo->xSockId, cStr);
|
||||
}
|
||||
|
||||
// Set non blocking attribute for socket
|
||||
@@ -561,7 +587,7 @@ static err_t xMBTCPPortMasterConnect(MbSlaveInfo_t* pxInfo)
|
||||
xErr = connect(pxInfo->xSockId, (struct sockaddr*)pxCurAddr->ai_addr, pxCurAddr->ai_addrlen);
|
||||
if ((xErr < 0) && (errno == EINPROGRESS || errno == EALREADY)) {
|
||||
// The unblocking connect is pending (check status later) or already connected
|
||||
ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s) connection is pending, errno %d (%s).",
|
||||
ESP_LOGV(TAG, "Socket(#%d)(%s) connection is pending, errno %d (%s).",
|
||||
pxInfo->xSockId, cStr, errno, strerror(errno));
|
||||
|
||||
// Set keep alive flag in socket options
|
||||
@@ -574,12 +600,12 @@ static err_t xMBTCPPortMasterConnect(MbSlaveInfo_t* pxInfo)
|
||||
continue;
|
||||
} else if (xErr != ERR_OK) {
|
||||
// Other error occurred during connection
|
||||
ESP_LOGV(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(" unable to connect, error=%d, errno %d (%s)"),
|
||||
ESP_LOGV(TAG, MB_SLAVE_FMT(" unable to connect, error=%d, errno %d (%s)"),
|
||||
pxInfo->xIndex, pxInfo->xSockId, cStr, xErr, errno, strerror(errno));
|
||||
xMBTCPPortMasterCloseConnection(pxInfo);
|
||||
xErr = ERR_CONN;
|
||||
} else {
|
||||
ESP_LOGI(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", successfully connected."),
|
||||
ESP_LOGI(TAG, MB_SLAVE_FMT(", successfully connected."),
|
||||
pxInfo->xIndex, pxInfo->xSockId, cStr);
|
||||
continue;
|
||||
}
|
||||
@@ -621,7 +647,7 @@ static int xMBTCPPortMasterCheckConnState(fd_set* pxFdSet)
|
||||
xErr = xMBTCPPortMasterCheckAlive(pxInfo, 0);
|
||||
if ((xErr < 0) && (((xTime - pxInfo->xRecvTimeStamp) > MB_TCP_RECONNECT_TIMEOUT) ||
|
||||
((xTime - pxInfo->xSendTimeStamp) > MB_TCP_RECONNECT_TIMEOUT))) {
|
||||
ESP_LOGI(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", slave is down, off_time[r][w](us) = [%ju][%ju]."),
|
||||
ESP_LOGI(TAG, MB_SLAVE_FMT(", slave is down, off_time[r][w](us) = [%ju][%ju]."),
|
||||
pxInfo->xIndex,
|
||||
pxInfo->xSockId,
|
||||
pxInfo->pcIpAddr,
|
||||
@@ -643,9 +669,9 @@ static void xMBTCPPortMasterFsmSetError(eMBMasterErrorEventType xErrType, eMBMas
|
||||
|
||||
static void vMBTCPPortMasterTask(void *pvParameters)
|
||||
{
|
||||
CHAR* pcAddrStr = NULL;
|
||||
MbSlaveInfo_t* pxInfo;
|
||||
MbSlaveInfo_t* pxCurrInfo;
|
||||
|
||||
fd_set xConnSet;
|
||||
fd_set xReadSet;
|
||||
int xMaxSd = 0;
|
||||
@@ -655,51 +681,53 @@ static void vMBTCPPortMasterTask(void *pvParameters)
|
||||
|
||||
// Register each slave in the connection info structure
|
||||
while (1) {
|
||||
BaseType_t xStatus = xQueueReceive(xMbPortConfig.xConnectQueue, (void*)&pcAddrStr, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS));
|
||||
xMBTCPPortMasterCheckShutdown();
|
||||
MbSlaveAddrInfo_t xSlaveAddrInfo = { 0 };
|
||||
BaseType_t xStatus = xQueueReceive(xMbPortConfig.xConnectQueue, (void*)&xSlaveAddrInfo, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS));
|
||||
xMBTCPPortMasterCheckShutdown();
|
||||
if (xStatus != pdTRUE) {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to register slave IP.");
|
||||
ESP_LOGE(TAG, "Fail to register slave IP.");
|
||||
} else {
|
||||
if (pcAddrStr == NULL && xMbPortConfig.usMbSlaveInfoCount) {
|
||||
if (xSlaveAddrInfo.pcIPAddr == NULL && xMbPortConfig.usMbSlaveInfoCount && xSlaveAddrInfo.usIndex == 0xFF) {
|
||||
break;
|
||||
}
|
||||
if (xMbPortConfig.usMbSlaveInfoCount > MB_TCP_PORT_MAX_CONN) {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Exceeds maximum connections limit=%d.", MB_TCP_PORT_MAX_CONN);
|
||||
ESP_LOGE(TAG, "Exceeds maximum connections limit=%d.", MB_TCP_PORT_MAX_CONN);
|
||||
break;
|
||||
}
|
||||
pxInfo = calloc(1, sizeof(MbSlaveInfo_t));
|
||||
if (!pxInfo) {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Slave(#%d), info structure allocation fail.",
|
||||
ESP_LOGE(TAG, "Slave(#%d), info structure allocation fail.",
|
||||
xMbPortConfig.usMbSlaveInfoCount);
|
||||
free(pxInfo);
|
||||
break;
|
||||
}
|
||||
pxInfo->pucRcvBuf = calloc(MB_TCP_BUF_SIZE, sizeof(UCHAR));
|
||||
if (!pxInfo->pucRcvBuf) {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Slave(#%d), receive buffer allocation fail.",
|
||||
ESP_LOGE(TAG, "Slave(#%d), receive buffer allocation fail.",
|
||||
xMbPortConfig.usMbSlaveInfoCount);
|
||||
free(pxInfo->pucRcvBuf);
|
||||
break;
|
||||
}
|
||||
pxInfo->usRcvPos = 0;
|
||||
pxInfo->pcIpAddr = pcAddrStr;
|
||||
pxInfo->pcIpAddr = xSlaveAddrInfo.pcIPAddr;
|
||||
pxInfo->xSockId = -1;
|
||||
pxInfo->xError = -1;
|
||||
pxInfo->xRecvTimeStamp = xMBTCPGetTimeStamp();
|
||||
pxInfo->xSendTimeStamp = xMBTCPGetTimeStamp();
|
||||
pxInfo->xMbProto = MB_PROTO_TCP;
|
||||
pxInfo->xIndex = xMbPortConfig.usMbSlaveInfoCount;
|
||||
pxInfo->ucSlaveAddr = xSlaveAddrInfo.ucSlaveAddr;
|
||||
pxInfo->xIndex = xSlaveAddrInfo.usIndex;
|
||||
pxInfo->usTidCnt = (USHORT)(xMbPortConfig.usMbSlaveInfoCount << 8U);
|
||||
// Register slave
|
||||
xMbPortConfig.pxMbSlaveInfo[xMbPortConfig.usMbSlaveInfoCount++] = pxInfo;
|
||||
ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "Add slave IP: %s", pcAddrStr);
|
||||
ESP_LOGI(TAG, "Add slave IP: %s", xSlaveAddrInfo.pcIPAddr);
|
||||
}
|
||||
}
|
||||
|
||||
// Main connection cycle
|
||||
while (1)
|
||||
{
|
||||
ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "Connecting to slaves...");
|
||||
ESP_LOGI(TAG, "Connecting to slaves...");
|
||||
xTime = xMBTCPGetTimeStamp();
|
||||
usSlaveConnCnt = 0;
|
||||
CHAR ucDot = '.';
|
||||
@@ -712,7 +740,7 @@ static void vMBTCPPortMasterTask(void *pvParameters)
|
||||
pxInfo = xMbPortConfig.pxMbSlaveInfo[ucCnt];
|
||||
// if slave descriptor is NULL then it is end of list or connection closed.
|
||||
if (!pxInfo) {
|
||||
ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Index: %d is not initialized, skip.", ucCnt);
|
||||
ESP_LOGV(TAG, "Index: %d is not initialized, skip.", ucCnt);
|
||||
if (xMbPortConfig.usMbSlaveInfoCount) {
|
||||
continue;
|
||||
}
|
||||
@@ -727,12 +755,12 @@ static void vMBTCPPortMasterTask(void *pvParameters)
|
||||
// In case of connection errors remove the socket from set
|
||||
if (FD_ISSET(pxInfo->xSockId, &xConnSet)) {
|
||||
FD_CLR(pxInfo->xSockId, &xConnSet);
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(" connect failed, error = %d."),
|
||||
ESP_LOGE(TAG, MB_SLAVE_FMT(" connect failed, error = %d."),
|
||||
pxInfo->xIndex, pxInfo->xSockId,
|
||||
(char*)pxInfo->pcIpAddr, xErr);
|
||||
if (usSlaveConnCnt) {
|
||||
usSlaveConnCnt--;
|
||||
}
|
||||
if (usSlaveConnCnt) {
|
||||
usSlaveConnCnt--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ERR_OK:
|
||||
@@ -741,7 +769,7 @@ static void vMBTCPPortMasterTask(void *pvParameters)
|
||||
FD_SET(pxInfo->xSockId, &xConnSet);
|
||||
usSlaveConnCnt++;
|
||||
xMaxSd = (pxInfo->xSockId > xMaxSd) ? pxInfo->xSockId : xMaxSd;
|
||||
ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", connected %d slave(s), error = %d."),
|
||||
ESP_LOGD(TAG, MB_SLAVE_FMT(", connected %d slave(s), error = %d."),
|
||||
pxInfo->xIndex, pxInfo->xSockId,
|
||||
pxInfo->pcIpAddr,
|
||||
usSlaveConnCnt, xErr);
|
||||
@@ -751,7 +779,7 @@ static void vMBTCPPortMasterTask(void *pvParameters)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", unexpected error = %d."),
|
||||
ESP_LOGE(TAG, MB_SLAVE_FMT(", unexpected error = %d."),
|
||||
pxInfo->xIndex,
|
||||
pxInfo->xSockId,
|
||||
pxInfo->pcIpAddr, xErr);
|
||||
@@ -763,7 +791,7 @@ static void vMBTCPPortMasterTask(void *pvParameters)
|
||||
xMBTCPPortMasterCheckShutdown();
|
||||
}
|
||||
}
|
||||
ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "Connected %d slaves, start polling...", usSlaveConnCnt);
|
||||
ESP_LOGI(TAG, "Connected %d slaves, start polling...", usSlaveConnCnt);
|
||||
|
||||
vMBTCPPortMasterStartPoll(); // Send event to start stack
|
||||
|
||||
@@ -774,26 +802,26 @@ static void vMBTCPPortMasterTask(void *pvParameters)
|
||||
xMBMasterPortFsmWaitConfirmation(EV_MASTER_FRAME_TRANSMIT, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS));
|
||||
// Synchronize state machine with send packet event
|
||||
if (xMBMasterPortFsmWaitConfirmation(EV_MASTER_FRAME_SENT, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS))) {
|
||||
ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "FSM Synchronized with sent event.");
|
||||
ESP_LOGD(TAG, "FSM Synchronized with sent event.");
|
||||
}
|
||||
// Get slave info for the current slave.
|
||||
pxCurrInfo = vMBTCPPortMasterGetCurrInfo();
|
||||
if (!pxCurrInfo) {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Incorrect connection options for slave index: %d.",
|
||||
ESP_LOGE(TAG, "Incorrect connection options for slave index: %d.",
|
||||
xMbPortConfig.ucCurSlaveIndex);
|
||||
vMBTCPPortMasterStopPoll();
|
||||
xMBTCPPortMasterCheckShutdown();
|
||||
break; // incorrect slave descriptor, reconnect.
|
||||
}
|
||||
xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo);
|
||||
ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Set select timeout, left time: %ju ms.",
|
||||
ESP_LOGD(TAG, "Set select timeout, left time: %ju ms.",
|
||||
xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo));
|
||||
// Wait respond from current slave during respond timeout
|
||||
int xRes = vMBTCPPortMasterRxCheck(pxCurrInfo->xSockId, &xReadSet, xTime);
|
||||
if (xRes == ERR_TIMEOUT) {
|
||||
// No respond from current slave, process timeout.
|
||||
// Need to drop response later if it is received after timeout.
|
||||
ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Select timeout, left time: %ju ms.",
|
||||
ESP_LOGD(TAG, "Select timeout, left time: %ju ms.",
|
||||
xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo));
|
||||
xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo);
|
||||
// Wait completion of last transaction
|
||||
@@ -802,7 +830,7 @@ static void vMBTCPPortMasterTask(void *pvParameters)
|
||||
continue;
|
||||
} else if (xRes < 0) {
|
||||
// Select error (slave connection or r/w failure).
|
||||
ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", socket select error. Slave disconnected?"),
|
||||
ESP_LOGD(TAG, MB_SLAVE_FMT(", socket select error. Slave disconnected?"),
|
||||
pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr);
|
||||
xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo);
|
||||
// Wait completion of last transaction
|
||||
@@ -816,30 +844,30 @@ static void vMBTCPPortMasterTask(void *pvParameters)
|
||||
} else {
|
||||
// Check to make sure that active slave data is ready
|
||||
if (FD_ISSET(pxCurrInfo->xSockId, &xReadSet)) {
|
||||
xErr = ERR_BUF;
|
||||
for (int retry = 0; (xErr == ERR_BUF) && (retry < MB_TCP_READ_BUF_RETRY_CNT); retry++) {
|
||||
xErr = vMBTCPPortMasterReadPacket(pxCurrInfo);
|
||||
int xRet = ERR_BUF;
|
||||
for (int retry = 0; (xRet == ERR_BUF) && (retry < MB_TCP_READ_BUF_RETRY_CNT); retry++) {
|
||||
xRet = vMBTCPPortMasterReadPacket(pxCurrInfo);
|
||||
// The error ERR_BUF means received response to previous request
|
||||
// (due to timeout) with the same socket ID and incorrect TID,
|
||||
// then ignore it and try to get next response buffer.
|
||||
}
|
||||
if (xErr > 0) {
|
||||
if (xRet > 0) {
|
||||
// Response received correctly, send an event to stack
|
||||
xMBTCPPortMasterFsmSetError(EV_ERROR_INIT, EV_MASTER_FRAME_RECEIVED);
|
||||
ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", frame received."),
|
||||
ESP_LOGD(TAG, MB_SLAVE_FMT(", frame received."),
|
||||
pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr);
|
||||
} else if ((xErr == ERR_TIMEOUT) || (xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo) == 0)) {
|
||||
} else if ((xRet == ERR_TIMEOUT) || (xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo) == 0)) {
|
||||
// Timeout occurred when receiving frame, process respond timeout
|
||||
ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", frame read timeout."),
|
||||
ESP_LOGD(TAG, MB_SLAVE_FMT(", frame read timeout."),
|
||||
pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr);
|
||||
} else if (xErr == ERR_BUF) {
|
||||
} else if (xRet == ERR_BUF) {
|
||||
// After retries a response with incorrect TID received, process failure.
|
||||
xMBTCPPortMasterFsmSetError(EV_ERROR_RECEIVE_DATA, EV_MASTER_ERROR_PROCESS);
|
||||
ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", frame error."),
|
||||
ESP_LOGD(TAG, MB_SLAVE_FMT(", frame error."),
|
||||
pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr);
|
||||
} else {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", critical error=%d."),
|
||||
pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr, xErr);
|
||||
ESP_LOGE(TAG, MB_SLAVE_FMT(", critical error=%d."),
|
||||
pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr, xRet);
|
||||
// Stop polling process
|
||||
vMBTCPPortMasterStopPoll();
|
||||
xMBTCPPortMasterCheckShutdown();
|
||||
@@ -848,14 +876,14 @@ static void vMBTCPPortMasterTask(void *pvParameters)
|
||||
break;
|
||||
}
|
||||
xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo);
|
||||
ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Slave #%d, data processing left time %ju [ms].", pxCurrInfo->xIndex, xTime);
|
||||
ESP_LOGD(TAG, "Slave #%d, data processing left time %ju [ms].", pxCurrInfo->xIndex, xTime);
|
||||
// Wait completion of Modbus frame processing before start of new transaction.
|
||||
if (xMBMasterPortFsmWaitConfirmation(MB_EVENT_REQ_DONE_MASK, pdMS_TO_TICKS(xTime))) {
|
||||
ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", data processing completed."),
|
||||
ESP_LOGD(TAG, MB_SLAVE_FMT(", data processing completed."),
|
||||
pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr);
|
||||
}
|
||||
xTime = xMBTCPGetTimeStamp() - pxCurrInfo->xSendTimeStamp;
|
||||
ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", processing time[us] = %ju."),
|
||||
ESP_LOGD(TAG, MB_SLAVE_FMT(", processing time[us] = %ju."),
|
||||
pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr, xTime);
|
||||
}
|
||||
}
|
||||
@@ -892,7 +920,7 @@ vMBMasterTCPPortClose(void)
|
||||
xShutdownSemaphore = xSemaphoreCreateBinary();
|
||||
// if no semaphore (alloc issues) or couldn't acquire it, just delete the task
|
||||
if (xShutdownSemaphore == NULL || xSemaphoreTake(xShutdownSemaphore, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS)) != pdTRUE) {
|
||||
ESP_LOGW(MB_TCP_MASTER_PORT_TAG, "Modbus port task couldn't exit gracefully within timeout -> abruptly deleting the task.");
|
||||
ESP_LOGW(TAG, "Modbus port task couldn't exit gracefully within timeout -> abruptly deleting the task.");
|
||||
vTaskDelete(xMbPortConfig.xMbTcpTaskHandle);
|
||||
}
|
||||
if (xShutdownSemaphore) {
|
||||
@@ -930,13 +958,13 @@ int xMBMasterTCPPortWritePoll(MbSlaveInfo_t* pxInfo, const UCHAR * pucMBTCPFrame
|
||||
int xRes = (int)xMBTCPPortMasterCheckAlive(pxInfo, xTimeout);
|
||||
if ((xRes < 0) && (xRes != ERR_INPROGRESS))
|
||||
{
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", is not writable, error: %d, errno %d"),
|
||||
ESP_LOGE(TAG, MB_SLAVE_FMT(", is not writable, error: %d, errno %d"),
|
||||
pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xRes, errno);
|
||||
return xRes;
|
||||
}
|
||||
xRes = send(pxInfo->xSockId, pucMBTCPFrame, usTCPLength, TCP_NODELAY);
|
||||
if (xRes < 0) {
|
||||
ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", send data error: %d, errno %d"),
|
||||
ESP_LOGE(TAG, MB_SLAVE_FMT(", send data error: %d, errno %d"),
|
||||
pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xRes, errno);
|
||||
}
|
||||
return xRes;
|
||||
@@ -946,36 +974,41 @@ BOOL
|
||||
xMBMasterTCPPortSendResponse( UCHAR * pucMBTCPFrame, USHORT usTCPLength )
|
||||
{
|
||||
BOOL bFrameSent = FALSE;
|
||||
xMbPortConfig.ucCurSlaveIndex = ucMBMasterGetDestAddress();
|
||||
MbSlaveInfo_t* pxInfo = vMBTCPPortMasterGetCurrInfo();
|
||||
USHORT ucCurSlaveIndex = ucMBMasterGetDestAddress();
|
||||
MbSlaveInfo_t* pxInfo = vMBTCPPortMasterFindSlaveInfo(ucCurSlaveIndex);
|
||||
|
||||
// If socket active then send data
|
||||
if (pxInfo->xSockId > -1) {
|
||||
// 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(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", send data failure, err(errno) = %d(%d)."),
|
||||
pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xRes, errno);
|
||||
bFrameSent = FALSE;
|
||||
pxInfo->xError = xRes;
|
||||
} else {
|
||||
bFrameSent = TRUE;
|
||||
ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", send data successful: TID=0x%02x, %d (bytes), errno %d"),
|
||||
pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->usTidCnt, xRes, errno);
|
||||
pxInfo->xError = 0;
|
||||
pxInfo->usRcvPos = 0;
|
||||
if (pxInfo->usTidCnt < (USHRT_MAX - 1)) {
|
||||
pxInfo->usTidCnt++;
|
||||
} else {
|
||||
pxInfo->usTidCnt = (USHORT)(pxInfo->xIndex << 8U);
|
||||
}
|
||||
}
|
||||
pxInfo->xSendTimeStamp = xMBTCPGetTimeStamp();
|
||||
} else {
|
||||
ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", send to died slave, error = %d"),
|
||||
// If the slave is correct and active then send data
|
||||
// otherwise treat slave as died and skip
|
||||
if (pxInfo != NULL) {
|
||||
if (pxInfo->xSockId < 0) {
|
||||
ESP_LOGD(TAG, MB_SLAVE_FMT(", send to died slave, error = %d"),
|
||||
pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->xError);
|
||||
} else {
|
||||
// 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)."),
|
||||
pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xRes, errno);
|
||||
bFrameSent = FALSE;
|
||||
pxInfo->xError = xRes;
|
||||
} else {
|
||||
bFrameSent = TRUE;
|
||||
ESP_LOGD(TAG, MB_SLAVE_FMT(", send data successful: TID=0x%02x, %d (bytes), errno %d"),
|
||||
pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->usTidCnt, xRes, errno);
|
||||
pxInfo->xError = 0;
|
||||
pxInfo->usRcvPos = 0;
|
||||
if (pxInfo->usTidCnt < (USHRT_MAX - 1)) {
|
||||
pxInfo->usTidCnt++;
|
||||
} else {
|
||||
pxInfo->usTidCnt = (USHORT)(pxInfo->xIndex << 8U);
|
||||
}
|
||||
}
|
||||
pxInfo->xSendTimeStamp = xMBTCPGetTimeStamp();
|
||||
}
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Send data to died slave, address = %d", ucCurSlaveIndex);
|
||||
}
|
||||
vMBMasterPortTimersRespondTimeoutEnable();
|
||||
xMBMasterPortEventPost(EV_MASTER_FRAME_SENT);
|
||||
|
||||
@@ -74,6 +74,7 @@ typedef struct {
|
||||
int xError; /*!< Socket error */
|
||||
int xRcvErr; /*!< Socket receive error */
|
||||
const char* pcIpAddr; /*!< TCP/UDP IP address */
|
||||
UCHAR ucSlaveAddr; /*!< Slave short address */
|
||||
UCHAR* pucRcvBuf; /*!< Receive buffer pointer */
|
||||
USHORT usRcvPos; /*!< Receive buffer position */
|
||||
int pcPort; /*!< TCP/UDP port number */
|
||||
@@ -84,28 +85,37 @@ typedef struct {
|
||||
} MbSlaveInfo_t;
|
||||
|
||||
typedef struct {
|
||||
TaskHandle_t xMbTcpTaskHandle; /*!< Master TCP/UDP handling task handle */
|
||||
QueueHandle_t xConnectQueue; /*!< Master connection queue */
|
||||
USHORT usPort; /*!< Master TCP/UDP port number */
|
||||
USHORT usMbSlaveInfoCount; /*!< Master count of connected slaves */
|
||||
USHORT ucCurSlaveIndex; /*!< Master current processing slave index */
|
||||
eMBPortIpVer eMbIpVer; /*!< Master IP version */
|
||||
eMBPortProto eMbProto; /*!< Master protocol type */
|
||||
void* pvNetIface; /*!< Master netif interface pointer */
|
||||
MbSlaveInfo_t** pxMbSlaveInfo; /*!< Master information structure for each connected slave */
|
||||
TaskHandle_t xMbTcpTaskHandle; /*!< Master TCP/UDP handling task handle */
|
||||
QueueHandle_t xConnectQueue; /*!< Master connection queue */
|
||||
USHORT usPort; /*!< Master TCP/UDP port number */
|
||||
USHORT usMbSlaveInfoCount; /*!< Master count of connected slaves */
|
||||
USHORT ucCurSlaveIndex; /*!< Master current processing slave index */
|
||||
eMBPortIpVer eMbIpVer; /*!< Master IP version */
|
||||
eMBPortProto eMbProto; /*!< Master protocol type */
|
||||
void* pvNetIface; /*!< Master netif interface pointer */
|
||||
MbSlaveInfo_t** pxMbSlaveInfo; /*!< Master information structure for each connected slave */
|
||||
MbSlaveInfo_t* pxMbSlaveCurrInfo; /*!< Master current slave information */
|
||||
} MbPortConfig_t;
|
||||
|
||||
typedef struct {
|
||||
USHORT usIndex; /*!< index of the address info */
|
||||
const char* pcIPAddr; /*!< represents the IP address of the slave */
|
||||
UCHAR ucSlaveAddr; /*!< slave unit ID (UID) field for MBAP frame */
|
||||
} MbSlaveAddrInfo_t;
|
||||
|
||||
/* ----------------------- Function prototypes ------------------------------*/
|
||||
|
||||
// The functions below are used by Modbus controller interface to configure Modbus port.
|
||||
/**
|
||||
* Registers slave IP address
|
||||
*
|
||||
* @param usIndex index of element in the configuration
|
||||
* @param pcIpStr IP address to register
|
||||
* @param ucSlaveAddress slave element index
|
||||
*
|
||||
* @return TRUE if address registered successfully, else FALSE
|
||||
*/
|
||||
BOOL xMBTCPPortMasterAddSlaveIp(const CHAR* pcIpStr);
|
||||
BOOL xMBTCPPortMasterAddSlaveIp(const USHORT usIndex, const CHAR* pcIpStr, UCHAR ucSlaveAddress);
|
||||
|
||||
/**
|
||||
* Keeps FSM event handle and mask then wait for Master stack to start
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
// Shared pointer to interface structure
|
||||
static mb_slave_interface_t* mbs_interface_ptr = NULL;
|
||||
static const char *TAG = "MB_CONTROLLER_SLAVE";
|
||||
|
||||
// Modbus task function
|
||||
static void modbus_tcp_slave_task(void *pvParameters)
|
||||
|
||||
@@ -68,13 +68,13 @@
|
||||
/* ----------------------- Defines -----------------------------------------*/
|
||||
#define MB_TCP_DISCONNECT_TIMEOUT ( CONFIG_FMB_TCP_CONNECTION_TOUT_SEC * 1000000 ) // disconnect timeout in uS
|
||||
#define MB_TCP_RESP_TIMEOUT_MS ( MB_MASTER_TIMEOUT_MS_RESPOND - 2 ) // slave response time limit
|
||||
#define MB_TCP_SLAVE_PORT_TAG "MB_TCP_SLAVE_PORT"
|
||||
#define MB_TCP_NET_LISTEN_BACKLOG ( SOMAXCONN )
|
||||
|
||||
/* ----------------------- Prototypes ---------------------------------------*/
|
||||
void vMBPortEventClose( void );
|
||||
|
||||
/* ----------------------- Static variables ---------------------------------*/
|
||||
static const char *TAG = "MB_TCP_SLAVE_PORT";
|
||||
static int xListenSock = -1;
|
||||
static MbSlavePortConfig_t xConfig = { 0 };
|
||||
|
||||
@@ -136,14 +136,14 @@ xMBTCPPortInit( USHORT usTCPPort )
|
||||
|
||||
xConfig.pxMbClientInfo = calloc(MB_TCP_PORT_MAX_CONN + 1, sizeof(MbClientInfo_t*));
|
||||
if (!xConfig.pxMbClientInfo) {
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "TCP client info allocation failure.");
|
||||
ESP_LOGE(TAG, "TCP client info allocation failure.");
|
||||
return FALSE;
|
||||
}
|
||||
for(int idx = 0; idx < MB_TCP_PORT_MAX_CONN; xConfig.pxMbClientInfo[idx] = NULL, idx++);
|
||||
|
||||
xConfig.xRespQueueHandle = xMBTCPPortRespQueueCreate();
|
||||
if (!xConfig.xRespQueueHandle) {
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Response queue allocation failure.");
|
||||
ESP_LOGE(TAG, "Response queue allocation failure.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -164,10 +164,10 @@ xMBTCPPortInit( USHORT usTCPPort )
|
||||
vTaskSuspend(xConfig.xMbTcpTaskHandle);
|
||||
if (xErr != pdTRUE)
|
||||
{
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Server task creation failure.");
|
||||
ESP_LOGE(TAG, "Server task creation failure.");
|
||||
vTaskDelete(xConfig.xMbTcpTaskHandle);
|
||||
} else {
|
||||
ESP_LOGI(MB_TCP_SLAVE_PORT_TAG, "Protocol stack initialized.");
|
||||
ESP_LOGI(TAG, "Protocol stack initialized.");
|
||||
bOkay = TRUE;
|
||||
}
|
||||
return bOkay;
|
||||
@@ -202,7 +202,7 @@ static int xMBTCPPortAcceptConnection(int xListenSockId, char** pcIPAddr)
|
||||
// Accept new socket connection if not active
|
||||
xSockId = accept(xListenSockId, (struct sockaddr *)&xSrcAddr, &xSize);
|
||||
if (xSockId < 0) {
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Unable to accept connection: errno=%d", errno);
|
||||
ESP_LOGE(TAG, "Unable to accept connection: errno=%d", errno);
|
||||
close(xSockId);
|
||||
} else {
|
||||
// Get the sender's ip address as string
|
||||
@@ -214,7 +214,7 @@ static int xMBTCPPortAcceptConnection(int xListenSockId, char** pcIPAddr)
|
||||
inet6_ntoa_r(((struct sockaddr_in6 *)&xSrcAddr)->sin6_addr, cAddrStr, sizeof(cAddrStr) - 1);
|
||||
}
|
||||
#endif
|
||||
ESP_LOGI(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d), accept client connection from address: %s", xSockId, cAddrStr);
|
||||
ESP_LOGI(TAG, "Socket (#%d), accept client connection from address: %s", xSockId, cAddrStr);
|
||||
pcStr = calloc(1, strlen(cAddrStr) + 1);
|
||||
if (pcStr && pcIPAddr) {
|
||||
memcpy(pcStr, cAddrStr, strlen(cAddrStr));
|
||||
@@ -230,11 +230,11 @@ static BOOL xMBTCPPortCloseConnection(MbClientInfo_t* pxInfo)
|
||||
MB_PORT_CHECK(pxInfo, FALSE, "Client info is NULL.");
|
||||
|
||||
if (pxInfo->xSockId == -1) {
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Wrong socket info or disconnected socket: %d.", pxInfo->xSockId);
|
||||
ESP_LOGE(TAG, "Wrong socket info or disconnected socket: %d.", pxInfo->xSockId);
|
||||
return FALSE;
|
||||
}
|
||||
if (shutdown(pxInfo->xSockId, SHUT_RDWR) == -1) {
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d), shutdown failed: errno %d", pxInfo->xSockId, errno);
|
||||
ESP_LOGE(TAG, "Socket (#%d), shutdown failed: errno %d", pxInfo->xSockId, errno);
|
||||
}
|
||||
close(pxInfo->xSockId);
|
||||
pxInfo->xSockId = -1;
|
||||
@@ -271,7 +271,7 @@ static int xMBTCPPortRxPoll(MbClientInfo_t* pxClientInfo, ULONG xTimeoutMs)
|
||||
} else if (xRet == 0) {
|
||||
// timeout occurred
|
||||
if ((xStartTimeStamp + xTimeoutMs * 1000) > xMBTCPGetTimeStamp()) {
|
||||
ESP_LOGD(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d) Read timeout.", pxClientInfo->xSockId);
|
||||
ESP_LOGD(TAG, "Socket (#%d) Read timeout.", pxClientInfo->xSockId);
|
||||
xRet = ERR_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
@@ -286,12 +286,12 @@ static int xMBTCPPortRxPoll(MbClientInfo_t* pxClientInfo, ULONG xTimeoutMs)
|
||||
pxClientInfo->usTCPFrameBytesLeft, MSG_DONTWAIT);
|
||||
if (xLength < 0) {
|
||||
// If an error occurred during receiving
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Receive failed: length=%d, errno=%d", xLength, errno);
|
||||
ESP_LOGE(TAG, "Receive failed: length=%d, errno=%d", xLength, errno);
|
||||
xRet = (err_t)xLength;
|
||||
break;
|
||||
} else if (xLength == 0) {
|
||||
// Socket connection closed
|
||||
ESP_LOGD(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d)(%s), connection closed.",
|
||||
ESP_LOGD(TAG, "Socket (#%d)(%s), connection closed.",
|
||||
pxClientInfo->xSockId, pxClientInfo->pcIpAddr);
|
||||
xRet = ERR_CLSD;
|
||||
break;
|
||||
@@ -309,14 +309,14 @@ static int xMBTCPPortRxPoll(MbClientInfo_t* pxClientInfo, ULONG xTimeoutMs)
|
||||
pxClientInfo->usTCPFrameBytesLeft = xLength + MB_TCP_UID - pxClientInfo->usTCPBufPos;
|
||||
} else if (pxClientInfo->usTCPBufPos == (MB_TCP_UID + xLength)) {
|
||||
#if MB_TCP_DEBUG
|
||||
prvvMBTCPLogFrame(MB_TCP_SLAVE_PORT_TAG, (UCHAR*)&pxClientInfo->pucTCPBuf[0], pxClientInfo->usTCPBufPos);
|
||||
prvvMBTCPLogFrame(TAG, (UCHAR*)&pxClientInfo->pucTCPBuf[0], pxClientInfo->usTCPBufPos);
|
||||
#endif
|
||||
// Copy TID field from incoming packet
|
||||
pxClientInfo->usTidCnt = MB_TCP_GET_FIELD(pxClientInfo->pucTCPBuf, MB_TCP_TID);
|
||||
xRet = pxClientInfo->usTCPBufPos;
|
||||
break;
|
||||
} else if ((pxClientInfo->usTCPBufPos + xLength) >= MB_TCP_BUF_SIZE) {
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Incorrect buffer received (%u) bytes.", xLength);
|
||||
ESP_LOGE(TAG, "Incorrect buffer received (%u) bytes.", xLength);
|
||||
// This should not happen. We can't deal with such a client and
|
||||
// drop the connection for security reasons.
|
||||
xRet = ERR_BUF;
|
||||
@@ -401,7 +401,7 @@ vMBTCPPortBindAddr(const CHAR* pcBindIp)
|
||||
{
|
||||
if (listen(xListenSockFd, MB_TCP_NET_LISTEN_BACKLOG) != 0)
|
||||
{
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Error occurred during listen: errno=%d", errno);
|
||||
ESP_LOGE(TAG, "Error occurred during listen: errno=%d", errno);
|
||||
close(xListenSockFd);
|
||||
xListenSockFd = -1;
|
||||
continue;
|
||||
@@ -409,7 +409,7 @@ vMBTCPPortBindAddr(const CHAR* pcBindIp)
|
||||
}
|
||||
// Bind was successful
|
||||
pcStr = (pxCurAddr->ai_canonname == NULL) ? (CHAR*)"\0" : pxCurAddr->ai_canonname;
|
||||
ESP_LOGI(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d), listener %s on port: %d, errno=%d",
|
||||
ESP_LOGI(TAG, "Socket (#%d), listener %s on port: %d, errno=%d",
|
||||
xListenSockFd, pcStr, xConfig.usPort, errno);
|
||||
break;
|
||||
}
|
||||
@@ -475,11 +475,11 @@ static void vMBTCPPortServerTask(void *pvParameters)
|
||||
xErr = select(xMaxSd + 1 , &xReadSet , NULL , NULL , NULL);
|
||||
if ((xErr < 0) && (errno != EINTR)) {
|
||||
// error occurred during wait for read
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "select() errno = %d.", errno);
|
||||
ESP_LOGE(TAG, "select() errno = %d.", errno);
|
||||
continue;
|
||||
} else if (xErr == 0) {
|
||||
// If timeout happened, something is wrong
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "select() timeout, errno = %d.", errno);
|
||||
ESP_LOGE(TAG, "select() timeout, errno = %d.", errno);
|
||||
}
|
||||
|
||||
// If something happened on the master socket, then its an incoming connection.
|
||||
@@ -495,21 +495,21 @@ static void vMBTCPPortServerTask(void *pvParameters)
|
||||
// if request for new connection but no space left
|
||||
if (pxClientInfo != NULL) {
|
||||
if (xConfig.pxMbClientInfo[MB_TCP_PORT_MAX_CONN] == NULL) {
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Fail to accept connection %d, only %d connections supported.", i + 1, MB_TCP_PORT_MAX_CONN);
|
||||
ESP_LOGE(TAG, "Fail to accept connection %d, only %d connections supported.", i + 1, MB_TCP_PORT_MAX_CONN);
|
||||
}
|
||||
xConfig.pxMbClientInfo[MB_TCP_PORT_MAX_CONN] = pxClientInfo; // set last connection info
|
||||
} else {
|
||||
// allocate memory for new client info
|
||||
pxClientInfo = calloc(1, sizeof(MbClientInfo_t));
|
||||
if (!pxClientInfo) {
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Client info allocation fail.");
|
||||
ESP_LOGE(TAG, "Client info allocation fail.");
|
||||
vMBTCPPortFreeClientInfo(pxClientInfo);
|
||||
pxClientInfo = NULL;
|
||||
} else {
|
||||
// Accept new client connection
|
||||
pxClientInfo->xSockId = xMBTCPPortAcceptConnection(xListenSock, &pcClientIp);
|
||||
if (pxClientInfo->xSockId < 0) {
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Fail to accept connection for client %d.", (xConfig.usClientCount - 1));
|
||||
ESP_LOGE(TAG, "Fail to accept connection for client %d.", (xConfig.usClientCount - 1));
|
||||
// Accept connection fail, then free client info and continue polling.
|
||||
vMBTCPPortFreeClientInfo(pxClientInfo);
|
||||
pxClientInfo = NULL;
|
||||
@@ -517,7 +517,7 @@ static void vMBTCPPortServerTask(void *pvParameters)
|
||||
}
|
||||
pxClientInfo->pucTCPBuf = calloc(MB_TCP_BUF_SIZE, sizeof(UCHAR));
|
||||
if (!pxClientInfo->pucTCPBuf) {
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Fail to allocate buffer for client %d.", (xConfig.usClientCount - 1));
|
||||
ESP_LOGE(TAG, "Fail to allocate buffer for client %d.", (xConfig.usClientCount - 1));
|
||||
vMBTCPPortFreeClientInfo(pxClientInfo);
|
||||
pxClientInfo = NULL;
|
||||
continue;
|
||||
@@ -551,17 +551,17 @@ static void vMBTCPPortServerTask(void *pvParameters)
|
||||
switch(xErr)
|
||||
{
|
||||
case ERR_TIMEOUT:
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d)(%s), data receive timeout, time[us]: %d, close active connection.",
|
||||
ESP_LOGE(TAG, "Socket (#%d)(%s), data receive timeout, time[us]: %d, close active connection.",
|
||||
pxClientInfo->xSockId, pxClientInfo->pcIpAddr,
|
||||
(int)(xTimeStamp - pxClientInfo->xRecvTimeStamp));
|
||||
break;
|
||||
case ERR_CLSD:
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d)(%s), connection closed by peer.",
|
||||
ESP_LOGE(TAG, "Socket (#%d)(%s), connection closed by peer.",
|
||||
pxClientInfo->xSockId, pxClientInfo->pcIpAddr);
|
||||
break;
|
||||
case ERR_BUF:
|
||||
default:
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d)(%s), read data error: %d",
|
||||
ESP_LOGE(TAG, "Socket (#%d)(%s), read data error: %d",
|
||||
pxClientInfo->xSockId, pxClientInfo->pcIpAddr, xErr);
|
||||
break;
|
||||
}
|
||||
@@ -586,26 +586,26 @@ static void vMBTCPPortServerTask(void *pvParameters)
|
||||
// Complete frame received, inform state machine to process frame
|
||||
xMBPortEventPost(EV_FRAME_RECEIVED);
|
||||
|
||||
ESP_LOGD(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d)(%s), get packet TID=0x%X, %d bytes.",
|
||||
ESP_LOGD(TAG, "Socket (#%d)(%s), get packet TID=0x%X, %d bytes.",
|
||||
pxClientInfo->xSockId, pxClientInfo->pcIpAddr,
|
||||
pxClientInfo->usTidCnt, xErr);
|
||||
|
||||
// Wait while response is not processed by stack by timeout
|
||||
UCHAR* pucSentBuffer = vxMBTCPPortRespQueueRecv(xConfig.xRespQueueHandle);
|
||||
if (pucSentBuffer == NULL) {
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Response time exceeds configured %d [ms], ignore packet.",
|
||||
ESP_LOGE(TAG, "Response time exceeds configured %d [ms], ignore packet.",
|
||||
MB_TCP_RESP_TIMEOUT_MS);
|
||||
} else {
|
||||
USHORT usSentTid = MB_TCP_GET_FIELD(pucSentBuffer, MB_TCP_TID);
|
||||
if (usSentTid != pxClientInfo->usTidCnt) {
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Sent TID(%x) != Recv TID(%x), ignore packet.",
|
||||
ESP_LOGE(TAG, "Sent TID(%x) != Recv TID(%x), ignore packet.",
|
||||
usSentTid, pxClientInfo->usTidCnt);
|
||||
}
|
||||
}
|
||||
|
||||
// Get time stamp of last data update
|
||||
pxClientInfo->xSendTimeStamp = xMBTCPGetTimeStamp();
|
||||
ESP_LOGD(MB_TCP_SLAVE_PORT_TAG, "Client %d, Socket(#%d), processing time = %d (us).",
|
||||
ESP_LOGD(TAG, "Client %d, Socket(#%d), processing time = %d (us).",
|
||||
pxClientInfo->xIndex, pxClientInfo->xSockId,
|
||||
(int)(pxClientInfo->xSendTimeStamp - pxClientInfo->xRecvTimeStamp));
|
||||
}
|
||||
@@ -614,7 +614,7 @@ static void vMBTCPPortServerTask(void *pvParameters)
|
||||
// client is not ready to be read
|
||||
int64_t xTime = xMBTCPGetTimeStamp() - pxClientInfo->xRecvTimeStamp;
|
||||
if (xTime > MB_TCP_DISCONNECT_TIMEOUT) {
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Client %d, Socket(#%d) do not answer for %d (us). Drop connection...",
|
||||
ESP_LOGE(TAG, "Client %d, Socket(#%d) do not answer for %d (us). Drop connection...",
|
||||
pxClientInfo->xIndex, pxClientInfo->xSockId, (int)(xTime));
|
||||
xMBTCPPortCloseConnection(pxClientInfo);
|
||||
|
||||
@@ -623,7 +623,7 @@ static void vMBTCPPortServerTask(void *pvParameters)
|
||||
xConfig.pxMbClientInfo[i] = NULL;
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Client %d is disconnected.", i);
|
||||
ESP_LOGE(TAG, "Client %d is disconnected.", i);
|
||||
}
|
||||
}
|
||||
} // if ((pxClientInfo != NULL)
|
||||
@@ -693,7 +693,7 @@ xMBTCPPortSendResponse( UCHAR * pucMBTCPFrame, USHORT usTCPLength )
|
||||
// Check if socket writable
|
||||
xErr = select(xConfig.pxCurClientInfo->xSockId + 1, NULL, &xWriteSet, &xErrorSet, &xTimeVal);
|
||||
if ((xErr == -1) || FD_ISSET(xConfig.pxCurClientInfo->xSockId, &xErrorSet)) {
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket(#%d) , send select() error = %d.",
|
||||
ESP_LOGE(TAG, "Socket(#%d) , send select() error = %d.",
|
||||
xConfig.pxCurClientInfo->xSockId, errno);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -705,7 +705,7 @@ xMBTCPPortSendResponse( UCHAR * pucMBTCPFrame, USHORT usTCPLength )
|
||||
// Write message into socket and disable Nagle's algorithm
|
||||
xErr = send(xConfig.pxCurClientInfo->xSockId, pucMBTCPFrame, usTCPLength, TCP_NODELAY);
|
||||
if (xErr < 0) {
|
||||
ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket(#%d), fail to send data, errno = %d",
|
||||
ESP_LOGE(TAG, "Socket(#%d), fail to send data, errno = %d",
|
||||
xConfig.pxCurClientInfo->xSockId, errno);
|
||||
xConfig.pxCurClientInfo->xError = xErr;
|
||||
} else {
|
||||
@@ -713,7 +713,7 @@ xMBTCPPortSendResponse( UCHAR * pucMBTCPFrame, USHORT usTCPLength )
|
||||
vxMBTCPPortRespQueueSend(xConfig.xRespQueueHandle, (void*)pucMBTCPFrame);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGD(MB_TCP_SLAVE_PORT_TAG, "Port is not active. Release lock.");
|
||||
ESP_LOGD(TAG, "Port is not active. Release lock.");
|
||||
vxMBTCPPortRespQueueSend(xConfig.xRespQueueHandle, (void*)pucMBTCPFrame);
|
||||
}
|
||||
return bFrameSent;
|
||||
|
||||
Reference in New Issue
Block a user