Merge branch 'bugfix/fix_compilation_warnings' into 'main'

fix static analyzer warnings

See merge request idf/esp-modbus!125
This commit is contained in:
Alex Lisitsyn
2025-07-28 13:15:57 +01:00
93 changed files with 2524 additions and 2460 deletions

View File

@@ -1,4 +1,5 @@
stages:
- pre_check
- build
- target_test
- deploy
@@ -18,6 +19,8 @@ variables:
.options_list:
# versions:
# IDF_VER: ["latest", "v5.3", "v5.2", "v5.0"]
analyzers:
ANALYZER_TYPE: [gcc, clang]
markers:
TEST_MARKER:
- "tcp"
@@ -117,6 +120,7 @@ after_script:
- *build_cur_folder
variables:
TEST_TARGETS: "esp32"
dependencies: []
artifacts:
name: artifacts_${CI_JOB_NAME}
paths:
@@ -133,9 +137,42 @@ after_script:
- "**/build*/partition_table/*.bin"
- "**/idf_version_info.txt"
- "**/test_dir*.txt"
- "**/warnings.txt"
- $SIZE_INFO_LOCATION
when: always
expire_in: 3 weeks
needs: []
.before_static_analyzer_build:
before_script:
- pip install --upgrade pyclang
- ${IDF_PATH}/tools/idf_tools.py --non-interactive install esp-clang
- . $IDF_PATH/export.sh
build_static_analyzer_idf_latest:
tags:
- build
stage: pre_check
extends:
- .before_static_analyzer_build
image: espressif/idf:latest
artifacts:
name: artifacts_${CI_JOB_NAME}
paths:
- "${TEST_DIR}/**/idf_version_info.txt"
- "${TEST_DIR}/**/warnings.txt"
- "${TEST_DIR}/**/sdkconfig"
when: always
expire_in: 3 weeks
parallel:
matrix:
- !reference [.options_list, analyzers]
script:
- *check_idf_ver
- cd ${TEST_DIR}/examples
- ${TEST_DIR}/tools/static_analyzer_check.sh ${ANALYZER_TYPE}
needs: []
after_script: []
build_idf_latest:
extends: .build_pytest_template

View File

@@ -91,4 +91,9 @@ endforeach()
# target_link_options(${COMPONENT_LIB} INTERFACE -fsanitize=address)
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-strict-aliasing -Wno-write-strings -Werror)
if(CONFIG_FMB_COMPILER_STATIC_ANALYZER_ENABLE AND CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_compile_options(${COMPONENT_LIB} PRIVATE "-fanalyzer")
message(STATUS "Static analyzer option `-analyzer` is applied for ${COMPONENT_NAME}.")
endif()
message(STATUS "The mdns included is: ${MB_MDNS_IS_INCLUDED}")

View File

@@ -232,4 +232,13 @@ menu "Modbus configuration"
This option defines the maximum number of Modbus command handlers for Modbus master and slave.
The option can be useful to register additional commands and its handlers.
config FMB_COMPILER_STATIC_ANALYZER_ENABLE
bool "Enable compiler static analyzer for Modbus library"
default "n"
depends on IDF_TOOLCHAIN_GCC
help
Enable compiler static analyzer for Modbus library.
This is workaround to avoid false-positives for some IDF related components.
When enabled, the library files will be analysed with GCC static analyzer.
endmenu

View File

@@ -2,3 +2,9 @@ set(PROJECT_NAME "modbus_serial_master")
idf_component_register(SRCS "serial_master.c"
INCLUDE_DIRS ".")
# Workaround to avoid static analysis false positives for some components.
if(CONFIG_FMB_COMPILER_STATIC_ANALYZER_ENABLE AND CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_compile_options(${COMPONENT_LIB} PRIVATE "-fanalyzer")
message(STATUS "Static analyzer build for ${PROJECT_NAME}.")
endif()

View File

@@ -56,7 +56,7 @@
#define OPTS(min_val, max_val, step_val) { .opt1 = min_val, .opt2 = max_val, .opt3 = step_val }
#define EACH_ITEM(array, length) \
(typeof(*(array)) *pitem = (array); (pitem < &((array)[length])); pitem++)
(typeof(*(array)) *item_ptr = (array); (item_ptr < &((array)[length])); item_ptr++)
#define MB_CUST_DATA_LEN 100 // The length of custom command buffer
@@ -259,50 +259,50 @@ static void *master_get_param_data(const mb_parameter_descriptor_t *param_descri
return instance_ptr;
}
#define TEST_VERIFY_VALUES(handle, pdescr, pinst) (__extension__( \
#define TEST_VERIFY_VALUES(handle, descr, inst) (__extension__( \
{ \
assert(pinst); \
assert(pdescr); \
assert(inst); \
assert(descr); \
uint8_t type = 0; \
esp_err_t err = ESP_FAIL; \
err = mbc_master_get_parameter(handle, pdescr->cid, \
(uint8_t *)pinst, &type); \
err = mbc_master_get_parameter(handle, descr->cid, \
(uint8_t *)inst, &type); \
if (err == ESP_OK) { \
bool is_correct = true; \
if (pdescr->param_opts.opt3) { \
for EACH_ITEM(pinst, pdescr->param_size / sizeof(*pitem)) { \
if (*pitem != (typeof(*(pinst)))pdescr->param_opts.opt3) { \
*pitem = (typeof(*(pinst)))pdescr->param_opts.opt3; \
if (descr->param_opts.opt3) { \
for EACH_ITEM(inst, descr->param_size / sizeof(*item_ptr)) { \
if (*item_ptr != (typeof(*(inst)))descr->param_opts.opt3) { \
*item_ptr = (typeof(*(inst)))descr->param_opts.opt3; \
ESP_LOGD(TAG, "Characteristic #%d (%s), initialize to 0x%" PRIx16 ".", \
(int)pdescr->cid, \
(char *)pdescr->param_key, \
(uint16_t)pdescr->param_opts.opt3); \
(int)descr->cid, \
(char *)descr->param_key, \
(uint16_t)descr->param_opts.opt3); \
is_correct = false; \
} \
} \
} \
if (!is_correct) { \
ESP_LOGE(TAG, "Characteristic #%d (%s), initialize.", \
(int)pdescr->cid, \
(char *)pdescr->param_key); \
err = mbc_master_set_parameter(handle, cid, (uint8_t *)pinst, &type); \
(int)descr->cid, \
(char *)descr->param_key); \
err = mbc_master_set_parameter(handle, cid, (uint8_t *)inst, &type); \
if (err != ESP_OK) { \
ESP_LOGE(TAG, "Characteristic #%d (%s) write fail, err = 0x%x (%s).", \
(int)pdescr->cid, \
(char *)pdescr->param_key, \
(int)descr->cid, \
(char *)descr->param_key, \
(int)err, \
(char *)esp_err_to_name(err)); \
} else { \
ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (..) write successful.", \
(int)pdescr->cid, \
(char *)pdescr->param_key, \
(char *)pdescr->param_units); \
(int)descr->cid, \
(char *)descr->param_key, \
(char *)descr->param_units); \
} \
} \
} else { \
ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).", \
(int)pdescr->cid, \
(char *)pdescr->param_key, \
(int)descr->cid, \
(char *)descr->param_key, \
(int)err, \
(char *)esp_err_to_name(err)); \
} \
@@ -494,15 +494,15 @@ static void master_operation_func(void *arg)
// This is the custom function handler for the command.
// The handler is executed from the context of modbus controller event task and should be as simple as possible.
// Parameters: frame_ptr - the pointer to the incoming ADU frame from slave starting from function code,
// plen - the pointer to length of the frame. After return from the handler the modbus object will
// len - the pointer to length of the frame. After return from the handler the modbus object will
// handle the end of transaction according to the exception returned.
mb_exception_t my_custom_handler(void *inst, uint8_t *frame_ptr, uint16_t *plen)
mb_exception_t my_custom_handler(void *inst, uint8_t *frame_ptr, uint16_t *len)
{
MB_RETURN_ON_FALSE((frame_ptr && plen && *plen && *plen < (MB_CUST_DATA_LEN - 1)), MB_EX_ILLEGAL_DATA_VALUE, TAG,
MB_RETURN_ON_FALSE((frame_ptr && len && *len && *len < (MB_CUST_DATA_LEN - 1)), MB_EX_ILLEGAL_DATA_VALUE, TAG,
"incorrect custom frame buffer");
ESP_LOGD(TAG, "Custom handler, Frame ptr: %p, len: %u", frame_ptr, *plen);
ESP_LOGD(TAG, "Custom handler, Frame ptr: %p, len: %u", frame_ptr, *len);
strncpy((char *)&my_custom_data[0], (char *)&frame_ptr[1], MB_CUST_DATA_LEN);
ESP_LOG_BUFFER_HEXDUMP("CUSTOM_DATA", &my_custom_data[0], (*plen - 1), ESP_LOG_WARN);
ESP_LOG_BUFFER_HEXDUMP("CUSTOM_DATA", &my_custom_data[0], (*len - 1), ESP_LOG_WARN);
return MB_EX_NONE;
}
@@ -539,9 +539,9 @@ static esp_err_t master_init(void)
err = mbc_set_handler(master_handle, override_command, my_custom_handler);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
"could not override handler, returned (0x%x).", (int)err);
mb_fn_handler_fp phandler = NULL;
err = mbc_get_handler(master_handle, override_command, &phandler);
MB_RETURN_ON_FALSE((err == ESP_OK && phandler == my_custom_handler), ESP_ERR_INVALID_STATE, TAG,
mb_fn_handler_fp handler = NULL;
err = mbc_get_handler(master_handle, override_command, &handler);
MB_RETURN_ON_FALSE((err == ESP_OK && handler == my_custom_handler), ESP_ERR_INVALID_STATE, TAG,
"could not get handler for command %d, returned (0x%x).", (int)override_command, (int)err);
// Set UART pin numbers

View File

@@ -7,3 +7,4 @@ CONFIG_FMB_TIMER_USE_ISR_DISPATCH_METHOD=y
CONFIG_FMB_EXT_TYPE_SUPPORT=y
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
CONFIG_HEAP_TRACING_OFF=y

View File

@@ -0,0 +1,9 @@
CONFIG_MB_COMM_MODE_ASCII=n
CONFIG_MB_COMM_MODE_RTU=y
CONFIG_MB_UART_BAUD_RATE=115200
CONFIG_FMB_MASTER_DELAY_MS_CONVERT=200
CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=400
CONFIG_FMB_TIMER_USE_ISR_DISPATCH_METHOD=y
CONFIG_FMB_EXT_TYPE_SUPPORT=y
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
CONFIG_HEAP_TRACING_OFF=y

View File

@@ -1,4 +1,10 @@
set(PROJECT_NAME "modbus_serial_slave")
idf_component_register(SRCS "serial_slave.c"
INCLUDE_DIRS ".")
set(PROJECT_NAME "modbus_serial_slave")
# Workaround to avoid static analysis false positives for some components.
if(CONFIG_FMB_COMPILER_STATIC_ANALYZER_ENABLE AND CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_compile_options(${COMPONENT_LIB} PRIVATE "-fanalyzer")
message(STATUS "Static analyzer build for ${PROJECT_NAME}.")
endif()

View File

@@ -83,15 +83,15 @@ static void setup_reg_data(void)
discrete_reg_params.discrete_input6 = 1;
discrete_reg_params.discrete_input7 = 0;
holding_reg_params.holding_data0 = 1.34;
holding_reg_params.holding_data1 = 2.56;
holding_reg_params.holding_data2 = 3.78;
holding_reg_params.holding_data3 = 4.90;
holding_reg_params.holding_data0 = 1.34F;
holding_reg_params.holding_data1 = 2.56F;
holding_reg_params.holding_data2 = 3.78F;
holding_reg_params.holding_data3 = 4.90F;
holding_reg_params.holding_data4 = 5.67;
holding_reg_params.holding_data5 = 6.78;
holding_reg_params.holding_data6 = 7.79;
holding_reg_params.holding_data7 = 8.80;
holding_reg_params.holding_data4 = 5.67F;
holding_reg_params.holding_data5 = 6.78F;
holding_reg_params.holding_data6 = 7.79F;
holding_reg_params.holding_data7 = 8.80F;
#if CONFIG_FMB_EXT_TYPE_SUPPORT
mb_set_uint8_a((val_16_arr *)&holding_reg_params.holding_u8_a[0], (uint8_t)0x55);
@@ -134,32 +134,32 @@ static void setup_reg_data(void)
coil_reg_params.coils_port0 = 0x55;
coil_reg_params.coils_port1 = 0xAA;
input_reg_params.input_data0 = 1.12;
input_reg_params.input_data1 = 2.34;
input_reg_params.input_data2 = 3.56;
input_reg_params.input_data3 = 4.78;
input_reg_params.input_data0 = 1.12F;
input_reg_params.input_data1 = 2.34F;
input_reg_params.input_data2 = 3.56F;
input_reg_params.input_data3 = 4.78F;
input_reg_params.input_data4 = 1.12;
input_reg_params.input_data5 = 2.34;
input_reg_params.input_data6 = 3.56;
input_reg_params.input_data7 = 4.78;
input_reg_params.input_data4 = 1.12F;
input_reg_params.input_data5 = 2.34F;
input_reg_params.input_data6 = 3.56F;
input_reg_params.input_data7 = 4.78F;
}
// This is a simple custom function handler for the command.
// The handler is executed from the context of modbus controller event task and should be as simple as possible.
// Parameters: frame_ptr - the pointer to the incoming ADU request frame from master starting from function code,
// plen - the pointer to length of the frame. The handler body can override the buffer and return the length of data.
// len - the pointer to length of the frame. The handler body can override the buffer and return the length of data.
// After return from the handler the modbus object will handle the end of transaction according to the exception returned,
// then builds the response frame and send it back to the master. If the whole transaction time including the response
// latency exceeds the configured slave response time set in the master configuration the master will ignore the transaction.
mb_exception_t my_custom_fc_handler(void *pinst, uint8_t *frame_ptr, uint16_t *plen)
mb_exception_t my_custom_fc_handler(void *inst, uint8_t *frame_ptr, uint16_t *len)
{
char *str_append = ":Slave";
MB_RETURN_ON_FALSE((frame_ptr && plen && *plen < (MB_CUST_DATA_MAX_LEN - strlen(str_append))), MB_EX_ILLEGAL_DATA_VALUE, TAG,
MB_RETURN_ON_FALSE((frame_ptr && len && *len < (MB_CUST_DATA_MAX_LEN - strlen(str_append))), MB_EX_ILLEGAL_DATA_VALUE, TAG,
"incorrect custom frame");
frame_ptr[*plen] = '\0';
frame_ptr[*len] = '\0';
strcat((char *)&frame_ptr[1], str_append);
*plen = (strlen(str_append) + *plen); // the length of (response + command)
*len = (strlen(str_append) + *len); // the length of (response + command)
return MB_EX_NONE; // Set the exception code for modbus object appropriately
}
@@ -200,9 +200,9 @@ void app_main(void)
err = mbc_set_handler(mbc_slave_handle, custom_command, my_custom_fc_handler);
MB_RETURN_ON_FALSE((err == ESP_OK), ;, TAG,
"could not set or override handler, returned (0x%x).", (int)err);
mb_fn_handler_fp phandler = NULL;
err = mbc_get_handler(mbc_slave_handle, custom_command, &phandler);
MB_RETURN_ON_FALSE((err == ESP_OK && phandler == my_custom_fc_handler), ;, TAG,
mb_fn_handler_fp handler = NULL;
err = mbc_get_handler(mbc_slave_handle, custom_command, &handler);
MB_RETURN_ON_FALSE((err == ESP_OK && handler == my_custom_fc_handler), ;, TAG,
"could not get handler for command %d, returned (0x%x).", (int)custom_command, (int)err);
// The code below initializes Modbus register area descriptors
@@ -283,7 +283,7 @@ void app_main(void)
uint8_t is_running = (bool)(err == ESP_OK);
// This is the way to set Slave ID fields to retrieve it by master using report slave ID command.
err = mbc_set_slave_id(mbc_slave_handle, comm_config.ser_opts.uid, is_running, (uint8_t *)&new_id_struct.length, new_id_struct.length);
err = mbc_set_slave_id(mbc_slave_handle, comm_config.ser_opts.uid, is_running, &new_id_struct.length, new_id_struct.length);
if (err == ESP_OK) {
ESP_LOGW("SET_SLAVE_ID", "dev_name: %s", (char*)new_id_struct.dev_name);
ESP_LOG_BUFFER_HEX_LEVEL("SET_SLAVE_ID", (void*)&new_id_struct.length, new_id_struct.length, ESP_LOG_WARN);
@@ -344,7 +344,10 @@ void app_main(void)
(unsigned)reg_info.type,
(uint32_t)reg_info.address,
(unsigned)reg_info.size);
if (coil_reg_params.coils_port1 == 0xFF) break;
if (coil_reg_params.coils_port1 == 0xFF) {
ESP_LOGI(TAG, "Stop polling.");
break;
}
}
}
// Destroy of Modbus controller on alarm

View File

@@ -9,3 +9,4 @@ CONFIG_FMB_TIMER_USE_ISR_DISPATCH_METHOD=y
CONFIG_FMB_EXT_TYPE_SUPPORT=y
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
CONFIG_HEAP_TRACING_OFF=y

View File

@@ -2,3 +2,9 @@ set(PROJECT_NAME "modbus_tcp_master")
idf_component_register(SRCS "tcp_master.c"
INCLUDE_DIRS ".")
# Workaround to avoid static analysis false positives for some components.
if(CONFIG_FMB_COMPILER_STATIC_ANALYZER_ENABLE AND CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_compile_options(${COMPONENT_LIB} PRIVATE "-fanalyzer")
message(STATUS "Static analyzer build for ${PROJECT_NAME}.")
endif()

View File

@@ -66,7 +66,7 @@
#define OPTS(min_val, max_val, step_val) { .opt1 = min_val, .opt2 = max_val, .opt3 = step_val }
#define EACH_ITEM(array, length) \
(typeof(*(array)) *pitem = (array); (pitem < &((array)[length])); pitem++)
(typeof(*(array)) *item_ptr = (array); (item_ptr < &((array)[length])); item_ptr++)
#define MB_ID_BYTE0(id) ((uint8_t)(id))
#define MB_ID_BYTE1(id) ((uint8_t)(((uint16_t)(id) >> 8) & 0xFF))
@@ -399,49 +399,49 @@ static void *master_get_param_data(const mb_parameter_descriptor_t *param_descri
return instance_ptr;
}
#define TEST_VERIFY_VALUES(handle, pdescr, pinst) (__extension__( \
#define TEST_VERIFY_VALUES(handle, descr, inst) (__extension__( \
{ \
assert(pinst); \
assert(pdescr); \
assert(inst); \
assert(descr); \
uint8_t type = 0; \
esp_err_t err = ESP_FAIL; \
err = mbc_master_get_parameter(handle, pdescr->cid, (uint8_t *)pinst, &type); \
err = mbc_master_get_parameter(handle, descr->cid, (uint8_t *)inst, &type); \
if (err == ESP_OK) { \
bool is_correct = true; \
if (pdescr->param_opts.opt3) { \
for EACH_ITEM(pinst, pdescr->param_size / sizeof(*pitem)) { \
if (*pitem != (typeof(*(pinst)))pdescr->param_opts.opt3) { \
*pitem = (typeof(*(pinst)))pdescr->param_opts.opt3; \
if (descr->param_opts.opt3) { \
for EACH_ITEM(inst, descr->param_size / sizeof(*item_ptr)) { \
if (*item_ptr != (typeof(*(inst)))descr->param_opts.opt3) { \
*item_ptr = (typeof(*(inst)))descr->param_opts.opt3; \
ESP_LOGD(TAG, "Characteristic #%d (%s), initialize to 0x%" PRIx16 ".", \
(int)pdescr->cid, \
(char *)pdescr->param_key, \
(uint16_t)pdescr->param_opts.opt3); \
(int)descr->cid, \
(char *)descr->param_key, \
(uint16_t)descr->param_opts.opt3); \
is_correct = false; \
} \
} \
} \
if (!is_correct) { \
ESP_LOGE(TAG, "Characteristic #%d (%s), initialize.", \
(int)pdescr->cid, \
(char *)pdescr->param_key); \
err = mbc_master_set_parameter(handle, cid, (uint8_t *)pinst, &type); \
(int)descr->cid, \
(char *)descr->param_key); \
err = mbc_master_set_parameter(handle, cid, (uint8_t *)inst, &type); \
if (err != ESP_OK) { \
ESP_LOGE(TAG, "Characteristic #%d (%s) write fail, err = 0x%x (%s).", \
(int)pdescr->cid, \
(char *)pdescr->param_key, \
(int)descr->cid, \
(char *)descr->param_key, \
(int)err, \
(char *)esp_err_to_name(err)); \
} else { \
ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (..) write successful.", \
(int)pdescr->cid, \
(char *)pdescr->param_key, \
(char *)pdescr->param_units); \
(int)descr->cid, \
(char *)descr->param_key, \
(char *)descr->param_units); \
} \
} \
} else { \
ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).", \
(int)pdescr->cid, \
(char *)pdescr->param_key, \
(int)descr->cid, \
(char *)descr->param_key, \
(int)err, \
(char *)esp_err_to_name(err)); \
} \
@@ -684,15 +684,15 @@ static esp_err_t destroy_services(void)
// This is the custom function handler for the command.
// The handler is executed from the context of modbus controller event task and should be as simple as possible.
// Parameters: frame_ptr - the pointer to the incoming ADU frame from slave starting from function code,
// plen - the pointer to length of the frame. After return from the handler the modbus object will
// len - the pointer to length of the frame. After return from the handler the modbus object will
// handle the end of transaction according to the exception returned.
mb_exception_t my_custom_fc_handler(void *inst, uint8_t *frame_ptr, uint16_t *plen)
mb_exception_t my_custom_fc_handler(void *inst, uint8_t *frame_ptr, uint16_t *len)
{
MB_RETURN_ON_FALSE((frame_ptr && plen && *plen && *plen < (MB_CUST_DATA_LEN - 1)), MB_EX_ILLEGAL_DATA_VALUE, TAG,
MB_RETURN_ON_FALSE((frame_ptr && len && *len && *len < (MB_CUST_DATA_LEN - 1)), MB_EX_ILLEGAL_DATA_VALUE, TAG,
"incorrect custom frame buffer");
ESP_LOGI(TAG, "Custom handler, Frame ptr: %p, len: %u", frame_ptr, *plen);
ESP_LOGI(TAG, "Custom handler, Frame ptr: %p, len: %u", frame_ptr, *len);
strncpy((char *)&my_custom_data[0], (char *)&frame_ptr[1], MB_CUST_DATA_LEN);
ESP_LOG_BUFFER_HEXDUMP("CUSTOM_DATA", &my_custom_data[0], (*plen - 1), ESP_LOG_INFO);
ESP_LOG_BUFFER_HEXDUMP("CUSTOM_DATA", &my_custom_data[0], (*len - 1), ESP_LOG_INFO);
return MB_EX_NONE;
}
@@ -717,9 +717,9 @@ static esp_err_t master_init(mb_communication_info_t *pcomm_info)
err = mbc_set_handler(master_handle, custom_command, my_custom_fc_handler);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
"could not override handler, returned (0x%x).", (int)err);
mb_fn_handler_fp phandler = NULL;
err = mbc_get_handler(master_handle, custom_command, &phandler);
MB_RETURN_ON_FALSE((err == ESP_OK && phandler == my_custom_fc_handler), ESP_ERR_INVALID_STATE, TAG,
mb_fn_handler_fp handler = NULL;
err = mbc_get_handler(master_handle, custom_command, &handler);
MB_RETURN_ON_FALSE((err == ESP_OK && handler == my_custom_fc_handler), ESP_ERR_INVALID_STATE, TAG,
"could not get handler for command %d, returned (0x%x).", (int)custom_command, (int)err);
err = mbc_master_set_descriptor(master_handle, &device_parameters[0], num_device_parameters);

View File

@@ -34,3 +34,4 @@ CONFIG_ETH_USE_SPI_ETHERNET=n
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
CONFIG_HEAP_TRACING_OFF=y

View File

@@ -21,3 +21,4 @@ CONFIG_EXAMPLE_WIFI_PASSWORD="${CI_WIFI_PASSW}"
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
CONFIG_HEAP_TRACING_OFF=y

View File

@@ -2,3 +2,9 @@ set(PROJECT_NAME "modbus_tcp_slave")
idf_component_register(SRCS "tcp_slave.c"
INCLUDE_DIRS ".")
# Workaround to avoid static analysis false positives for some components.
if(CONFIG_FMB_COMPILER_STATIC_ANALYZER_ENABLE AND CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_compile_options(${COMPONENT_LIB} PRIVATE "-fanalyzer")
message(STATUS "Static analyzer build for ${PROJECT_NAME}.")
endif()

View File

@@ -72,15 +72,15 @@ static void setup_reg_data(void)
discrete_reg_params.discrete_input6 = 1;
discrete_reg_params.discrete_input7 = 0;
holding_reg_params.holding_data0 = 1.34;
holding_reg_params.holding_data1 = 2.56;
holding_reg_params.holding_data2 = 3.78;
holding_reg_params.holding_data3 = 4.90;
holding_reg_params.holding_data0 = 1.34F;
holding_reg_params.holding_data1 = 2.56F;
holding_reg_params.holding_data2 = 3.78F;
holding_reg_params.holding_data3 = 4.90F;
holding_reg_params.holding_data4 = 5.67;
holding_reg_params.holding_data5 = 6.78;
holding_reg_params.holding_data6 = 7.79;
holding_reg_params.holding_data7 = 8.80;
holding_reg_params.holding_data4 = 5.67F;
holding_reg_params.holding_data5 = 6.78F;
holding_reg_params.holding_data6 = 7.79F;
holding_reg_params.holding_data7 = 8.80F;
#if CONFIG_FMB_EXT_TYPE_SUPPORT
mb_set_uint8_a((val_16_arr *)&holding_reg_params.holding_u8_a[0], (uint8_t)0x55);
@@ -123,14 +123,14 @@ static void setup_reg_data(void)
coil_reg_params.coils_port0 = 0x55;
coil_reg_params.coils_port1 = 0xAA;
input_reg_params.input_data0 = 1.12;
input_reg_params.input_data1 = 2.34;
input_reg_params.input_data2 = 3.56;
input_reg_params.input_data3 = 4.78;
input_reg_params.input_data4 = 1.12;
input_reg_params.input_data5 = 2.34;
input_reg_params.input_data6 = 3.56;
input_reg_params.input_data7 = 4.78;
input_reg_params.input_data0 = 1.12F;
input_reg_params.input_data1 = 2.34F;
input_reg_params.input_data2 = 3.56F;
input_reg_params.input_data3 = 4.78F;
input_reg_params.input_data4 = 1.12F;
input_reg_params.input_data5 = 2.34F;
input_reg_params.input_data6 = 3.56F;
input_reg_params.input_data7 = 4.78F;
}
static void slave_operation_func(void *arg)
@@ -268,18 +268,18 @@ static esp_err_t destroy_services(void)
// This is a simple custom function handler for the command.
// The handler is executed from the context of modbus controller event task and should be as simple as possible.
// Parameters: frame_ptr - the pointer to the incoming ADU request frame from master starting from function code,
// plen - the pointer to length of the frame. The handler body can override the buffer and return the length of data.
// len - the pointer to length of the frame. The handler body can override the buffer and return the length of data.
// After return from the handler the modbus object will handle the end of transaction according to the exception returned,
// then builds the response frame and send it back to the master. If the whole transaction time including the response
// latency exceeds the configured slave response time set in the master configuration the master will ignore the transaction.
mb_exception_t my_custom_fc_handler(void *pinst, uint8_t *frame_ptr, uint16_t *plen)
mb_exception_t my_custom_fc_handler(void *inst, uint8_t *frame_ptr, uint16_t *len)
{
char *str_append = ":Slave";
MB_RETURN_ON_FALSE((frame_ptr && plen && *plen < (MB_CUST_DATA_MAX_LEN - strlen(str_append))), MB_EX_ILLEGAL_DATA_VALUE, TAG,
MB_RETURN_ON_FALSE((frame_ptr && len && *len < (MB_CUST_DATA_MAX_LEN - strlen(str_append))), MB_EX_ILLEGAL_DATA_VALUE, TAG,
"incorrect custom frame");
frame_ptr[*plen] = '\0';
frame_ptr[*len] = '\0';
strcat((char *)&frame_ptr[1], str_append);
*plen = (strlen(str_append) + *plen); // the length of (response + command)
*len = (strlen(str_append) + *len); // the length of (response + command)
return MB_EX_NONE; // Set the exception code for modbus object appropriately
}
@@ -302,9 +302,9 @@ static esp_err_t slave_init(mb_communication_info_t *pcomm_info)
err = mbc_set_handler(slave_handle, custom_command, my_custom_fc_handler);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
"could not set or override handler, returned (0x%x).", (int)err);
mb_fn_handler_fp phandler = NULL;
err = mbc_get_handler(slave_handle, custom_command, &phandler);
MB_RETURN_ON_FALSE((err == ESP_OK && phandler == my_custom_fc_handler), ESP_ERR_INVALID_STATE, TAG,
mb_fn_handler_fp handler = NULL;
err = mbc_get_handler(slave_handle, custom_command, &handler);
MB_RETURN_ON_FALSE((err == ESP_OK && handler == my_custom_fc_handler), ESP_ERR_INVALID_STATE, TAG,
"could not get handler for command %d, returned (0x%x).", (int)custom_command, (int)err);
// The code below initializes Modbus register area descriptors

View File

@@ -33,3 +33,4 @@ CONFIG_ETH_USE_SPI_ETHERNET=n
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
CONFIG_HEAP_TRACING_OFF=y

View File

@@ -20,3 +20,4 @@ CONFIG_EXAMPLE_WIFI_PASSWORD="${CI_WIFI_PASSW}"
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
CONFIG_HEAP_TRACING_OFF=y

View File

@@ -13,19 +13,19 @@ static const char TAG[] __attribute__((unused)) = "MB_CONTROLLER_COMMON";
/**
* Register or override command handler for the command in object command handler table
*/
esp_err_t mbc_set_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp phandler)
esp_err_t mbc_set_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp handler)
{
MB_RETURN_ON_FALSE((ctx && phandler && func_code), ESP_ERR_INVALID_STATE, TAG,
MB_RETURN_ON_FALSE((ctx && handler && func_code), ESP_ERR_INVALID_STATE, TAG,
"Incorrect arguments for the function.");
mb_err_enum_t ret = MB_EINVAL;
mb_controller_common_t *mb_controller = (mb_controller_common_t *)(ctx);
mb_base_t *pmb_obj = (mb_base_t *)mb_controller->mb_base;
MB_RETURN_ON_FALSE(pmb_obj, ESP_ERR_INVALID_STATE, TAG,
mb_base_t *mb_obj = (mb_base_t *)mb_controller->mb_base;
MB_RETURN_ON_FALSE(mb_obj, ESP_ERR_INVALID_STATE, TAG,
"Controller interface is not correctly initialized.");
if (pmb_obj->descr.is_master) {
ret = mbm_set_handler(mb_controller->mb_base, func_code, phandler);
if (mb_obj->descr.is_master) {
ret = mbm_set_handler(mb_controller->mb_base, func_code, handler);
} else {
ret = mbs_set_handler(mb_controller->mb_base, func_code, phandler);
ret = mbs_set_handler(mb_controller->mb_base, func_code, handler);
}
return MB_ERR_TO_ESP_ERR(ret);
}
@@ -33,19 +33,19 @@ esp_err_t mbc_set_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp phandle
/**
* Get command handler from the command handler table of the object
*/
esp_err_t mbc_get_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp *phandler)
esp_err_t mbc_get_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp *handler)
{
MB_RETURN_ON_FALSE((ctx && func_code && phandler), ESP_ERR_INVALID_STATE, TAG,
MB_RETURN_ON_FALSE((ctx && func_code && handler), ESP_ERR_INVALID_STATE, TAG,
"Incorrect arguments for the function.");
mb_err_enum_t ret = MB_EINVAL;
mb_controller_common_t *mb_controller = (mb_controller_common_t *)(ctx);
mb_base_t *pmb_obj = (mb_base_t *)mb_controller->mb_base;
MB_RETURN_ON_FALSE(pmb_obj, ESP_ERR_INVALID_STATE, TAG,
mb_base_t *mb_obj = (mb_base_t *)mb_controller->mb_base;
MB_RETURN_ON_FALSE(mb_obj, ESP_ERR_INVALID_STATE, TAG,
"Controller interface is not correctly initialized.");
if (pmb_obj->descr.is_master) {
ret = mbm_get_handler(mb_controller->mb_base, func_code, phandler);
if (mb_obj->descr.is_master) {
ret = mbm_get_handler(mb_controller->mb_base, func_code, handler);
} else {
ret = mbs_get_handler(mb_controller->mb_base, func_code, phandler);
ret = mbs_get_handler(mb_controller->mb_base, func_code, handler);
}
return MB_ERR_TO_ESP_ERR(ret);
}
@@ -59,10 +59,10 @@ esp_err_t mbc_delete_handler(void *ctx, uint8_t func_code)
"Incorrect arguments for the function.");
mb_err_enum_t ret = MB_EINVAL;
mb_controller_common_t *mb_controller = (mb_controller_common_t *)(ctx);
mb_base_t *pmb_obj = (mb_base_t *)mb_controller->mb_base;
MB_RETURN_ON_FALSE(pmb_obj, ESP_ERR_INVALID_STATE, TAG,
mb_base_t *mb_obj = (mb_base_t *)mb_controller->mb_base;
MB_RETURN_ON_FALSE(mb_obj, ESP_ERR_INVALID_STATE, TAG,
"Controller interface is not correctly initialized.");
if (pmb_obj->descr.is_master) {
if (mb_obj->descr.is_master) {
ret = mbm_delete_handler(mb_controller->mb_base, func_code);
} else {
ret = mbs_delete_handler(mb_controller->mb_base, func_code);
@@ -73,19 +73,19 @@ esp_err_t mbc_delete_handler(void *ctx, uint8_t func_code)
/**
* Get number of registered command handlers for the object
*/
esp_err_t mbc_get_handler_count(void *ctx, uint16_t *pcount)
esp_err_t mbc_get_handler_count(void *ctx, uint16_t *count)
{
MB_RETURN_ON_FALSE((ctx && pcount), ESP_ERR_INVALID_STATE, TAG,
MB_RETURN_ON_FALSE((ctx && count), ESP_ERR_INVALID_STATE, TAG,
"Controller interface is not correctly initialized.");
mb_err_enum_t ret = MB_EINVAL;
mb_controller_common_t *mb_controller = (mb_controller_common_t *)(ctx);
mb_base_t *pmb_obj = (mb_base_t *)mb_controller->mb_base;
MB_RETURN_ON_FALSE(pmb_obj, ESP_ERR_INVALID_STATE, TAG,
mb_base_t *mb_obj = (mb_base_t *)mb_controller->mb_base;
MB_RETURN_ON_FALSE(mb_obj, ESP_ERR_INVALID_STATE, TAG,
"Controller interface is not correctly initialized.");
if (pmb_obj->descr.is_master) {
ret = mbm_get_handler_count(mb_controller->mb_base, pcount);
if (mb_obj->descr.is_master) {
ret = mbm_get_handler_count(mb_controller->mb_base, count);
} else {
ret = mbs_get_handler_count(mb_controller->mb_base, pcount);
ret = mbs_get_handler_count(mb_controller->mb_base, count);
}
return MB_ERR_TO_ESP_ERR(ret);
}

View File

@@ -40,10 +40,10 @@ esp_err_t mbc_master_lock(void *ctx)
MB_RETURN_ON_FALSE(ctx, ESP_ERR_INVALID_STATE, TAG,
"Master interface is not correctly initialized.");
mbm_controller_iface_t *mbm_controller = MB_MASTER_GET_IFACE(ctx);
mb_base_t *pmb_obj = (mb_base_t *)mbm_controller->mb_base;
MB_RETURN_ON_FALSE((pmb_obj && pmb_obj->lock), ESP_ERR_INVALID_STATE, TAG,
mb_base_t *mb_obj = mbm_controller->mb_base;
MB_RETURN_ON_FALSE((mb_obj && mb_obj->lock), ESP_ERR_INVALID_STATE, TAG,
"Master interface is not correctly initialized.");
CRITICAL_SECTION_LOCK(pmb_obj->lock);
CRITICAL_SECTION_LOCK(mb_obj->lock);
return ESP_OK;
}
@@ -55,10 +55,10 @@ esp_err_t mbc_master_unlock(void *ctx)
MB_RETURN_ON_FALSE(ctx, ESP_ERR_INVALID_STATE, TAG,
"Master interface is not correctly initialized.");
mbm_controller_iface_t *mbm_controller = MB_MASTER_GET_IFACE(ctx);
mb_base_t *pmb_obj = (mb_base_t *)mbm_controller->mb_base;
MB_RETURN_ON_FALSE((pmb_obj && pmb_obj->lock), ESP_ERR_INVALID_STATE, TAG,
mb_base_t *mb_obj = mbm_controller->mb_base;
MB_RETURN_ON_FALSE((mb_obj && mb_obj->lock), ESP_ERR_INVALID_STATE, TAG,
"Master interface is not correctly initialized.");
CRITICAL_SECTION_UNLOCK(pmb_obj->lock);
CRITICAL_SECTION_UNLOCK(mb_obj->lock);
return ESP_OK;
}
@@ -231,17 +231,17 @@ esp_err_t mbc_master_stop(void *ctx)
/* ----------------------- Callback functions for Modbus stack ---------------------------------*/
// These are executed by modbus stack to read appropriate type of registers.
mb_err_enum_t mbc_reg_common_cb(mb_base_t *inst, uint8_t *pdata, uint16_t address, uint16_t bytes)
mb_err_enum_t mbc_reg_common_cb(mb_base_t *inst, uint8_t *data_ptr, uint16_t address, uint16_t bytes)
{
MB_RETURN_ON_FALSE((pdata), MB_EINVAL, TAG, "incorrect parameters provided.");
MB_RETURN_ON_FALSE((data_ptr), MB_EINVAL, TAG, "incorrect parameters provided.");
mb_master_options_t *popts = MB_MASTER_GET_OPTS(MB_MASTER_GET_IFACE_FROM_BASE(inst));
uint16_t reg_len = popts->reg_buffer_size;
uint8_t *ppar_buffer = (uint8_t *)popts->reg_buffer_ptr; // Get instance address
mb_master_options_t *opts = MB_MASTER_GET_OPTS(MB_MASTER_GET_IFACE_FROM_BASE(inst));
uint16_t reg_len = opts->reg_buffer_size;
uint8_t *par_buffer = opts->reg_buffer_ptr; // Get instance address
mb_err_enum_t status = MB_ENOERR;
if (ppar_buffer && !address && (bytes >= 2) && (((reg_len << 1) >= bytes))){
if (par_buffer&& !address && (bytes >= 2) && (((reg_len << 1) >= bytes))){
CRITICAL_SECTION(inst->lock) {
memmove(ppar_buffer, pdata, bytes);
memmove(par_buffer, data_ptr, bytes);
}
} else {
status = MB_ENORES;
@@ -267,8 +267,8 @@ mb_err_enum_t mbc_reg_input_master_cb(mb_base_t *inst, uint8_t *reg_buffer, uint
"Master stack processing error.");
mb_master_options_t *mbm_opts = MB_MASTER_GET_OPTS(MB_MASTER_GET_IFACE_FROM_BASE(inst));
// Number of input registers to be transferred
uint16_t num_input_regs = (uint16_t)mbm_opts->reg_buffer_size;
uint8_t *input_reg_buf = (uint8_t *)mbm_opts->reg_buffer_ptr; // Get instance address
uint16_t num_input_regs = mbm_opts->reg_buffer_size;
uint8_t *input_reg_buf = mbm_opts->reg_buffer_ptr; // Get instance address
uint16_t regs_cnt = num_regs;
mb_err_enum_t status = MB_ENOERR;
// If input or configuration parameters are incorrect then return an error to stack layer
@@ -309,8 +309,8 @@ mb_err_enum_t mbc_reg_holding_master_cb(mb_base_t *inst, uint8_t *reg_buffer, ui
{
MB_RETURN_ON_FALSE((reg_buffer), MB_EINVAL, TAG, "Master stack processing error.");
mb_master_options_t *mbm_opts = MB_MASTER_GET_OPTS(MB_MASTER_GET_IFACE_FROM_BASE(inst));
uint16_t num_hold_regs = (uint16_t)mbm_opts->reg_buffer_size;
uint8_t *holding_buf = (uint8_t *)mbm_opts->reg_buffer_ptr;
uint16_t num_hold_regs = mbm_opts->reg_buffer_size;
uint8_t *holding_buf = mbm_opts->reg_buffer_ptr;
mb_err_enum_t status = MB_ENOERR;
uint16_t regs_cnt = num_regs;
// Check input and configuration parameters for correctness
@@ -349,7 +349,7 @@ mb_err_enum_t mbc_reg_holding_master_cb(mb_base_t *inst, uint8_t *reg_buffer, ui
}
/**
* Modbus master coils callback function.
* @brief Modbus master coils read callback function.
*
* @param inst interface context pointer
* @param reg_buffer coils buffer
@@ -359,15 +359,13 @@ mb_err_enum_t mbc_reg_holding_master_cb(mb_base_t *inst, uint8_t *reg_buffer, ui
*
* @return result
*/
// Callback function for reading of MB Coils Registers
// mbm_reg_coils_cb_serial
mb_err_enum_t mbc_reg_coils_master_cb(mb_base_t *inst, uint8_t *reg_buffer, uint16_t reg_addr,
uint16_t ncoils, mb_reg_mode_enum_t mode)
{
MB_RETURN_ON_FALSE((reg_buffer), MB_EINVAL, TAG, "Master stack processing error.");
mb_master_options_t *mbm_opts = MB_MASTER_GET_OPTS(MB_MASTER_GET_IFACE_FROM_BASE(inst));
uint16_t num_coil_regs = (uint16_t)mbm_opts->reg_buffer_size;
uint8_t *coils_buf = (uint8_t *)mbm_opts->reg_buffer_ptr;
uint16_t num_coil_regs = mbm_opts->reg_buffer_size;
uint8_t *coils_buf = mbm_opts->reg_buffer_ptr;
mb_err_enum_t status = MB_ENOERR;
uint16_t reg_index;
uint16_t coils_cnt = ncoils;
@@ -382,7 +380,7 @@ mb_err_enum_t mbc_reg_coils_master_cb(mb_base_t *inst, uint8_t *reg_buffer, uint
{
while (coils_cnt > 0)
{
uint8_t result = mb_util_get_bits((uint8_t *)coils_buf, reg_index - (reg_addr % 8), 1);
uint8_t result = mb_util_get_bits(coils_buf, reg_index - (reg_addr % 8), 1);
mb_util_set_bits(reg_buffer, reg_index - (reg_addr % 8), 1, result);
reg_index++;
coils_cnt--;
@@ -395,7 +393,7 @@ mb_err_enum_t mbc_reg_coils_master_cb(mb_base_t *inst, uint8_t *reg_buffer, uint
while (coils_cnt > 0)
{
uint8_t result = mb_util_get_bits(reg_buffer, reg_index - (reg_addr % 8), 1);
mb_util_set_bits((uint8_t *)coils_buf, reg_index - (reg_addr % 8), 1, result);
mb_util_set_bits(coils_buf, reg_index - (reg_addr % 8), 1, result);
reg_index++;
coils_cnt--;
}
@@ -428,18 +426,18 @@ mb_err_enum_t mbc_reg_discrete_master_cb(mb_base_t *inst, uint8_t *reg_buffer, u
{
MB_RETURN_ON_FALSE((reg_buffer), MB_EINVAL, TAG, "Master stack processing error.");
mb_master_options_t *mbm_opts = MB_MASTER_GET_OPTS(MB_MASTER_GET_IFACE_FROM_BASE(inst));
uint16_t num_discr_regs = (uint16_t)mbm_opts->reg_buffer_size;
uint8_t *discr_buf = (uint8_t *)mbm_opts->reg_buffer_ptr;
uint16_t num_discr_regs = mbm_opts->reg_buffer_size;
uint8_t *discr_buf = mbm_opts->reg_buffer_ptr;
mb_err_enum_t status = MB_ENOERR;
uint16_t bit_index, num_reg;
uint8_t *temp_discr_buf;
num_reg = n_discrete;
temp_discr_buf = (uint8_t *)discr_buf;
temp_discr_buf = discr_buf;
// It is already plus one in Modbus function method.
reg_addr--;
if ((num_discr_regs >= 1) && (discr_buf) && (n_discrete >= 1) && (n_discrete == num_discr_regs))
{
bit_index = (uint16_t)(reg_addr) % 8; // Get bit index
bit_index = (reg_addr) % 8; // Get bit index
CRITICAL_SECTION(inst->lock)
{
while (num_reg > 0)
@@ -464,265 +462,265 @@ esp_err_t mbc_master_set_param_data(void* dest, void* src, mb_descr_type_t param
esp_err_t err = ESP_OK;
MB_RETURN_ON_FALSE((src), ESP_ERR_INVALID_STATE, TAG,"incorrect data pointer.");
MB_RETURN_ON_FALSE((dest), ESP_ERR_INVALID_STATE, TAG,"incorrect data pointer.");
void *pdest = dest;
void *psrc = src;
void *dest_ptr = dest;
void *src_ptr = src;
// Transfer parameter data into value of characteristic
switch(param_type)
{
case PARAM_TYPE_U8:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_U8) {
*((uint8_t *)pdest) = *((uint8_t*)psrc);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_U8) {
*((uint8_t *)dest_ptr) = *((uint8_t*)src_ptr);
}
break;
case PARAM_TYPE_U16:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_U16) {
*((uint16_t *)pdest) = *((uint16_t*)psrc);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_U16) {
*((uint16_t *)dest_ptr) = *((uint16_t*)src_ptr);
}
break;
case PARAM_TYPE_U32:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_U32) {
*((uint32_t *)pdest) = *((uint32_t*)psrc);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_U32) {
*((uint32_t *)dest_ptr) = *((uint32_t*)src_ptr);
}
break;
case PARAM_TYPE_FLOAT:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_FLOAT) {
*((float *)pdest) = *(float*)psrc;
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_FLOAT) {
*((float *)dest_ptr) = *(float*)src_ptr;
}
break;
case PARAM_TYPE_ASCII:
case PARAM_TYPE_BIN:
memcpy((void *)dest, (void*)src, (size_t)param_size);
memcpy(dest, src, param_size);
break;
#if CONFIG_FMB_EXT_TYPE_SUPPORT
case PARAM_TYPE_I8_A:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_U8_REG) {
mb_set_int8_a((val_16_arr *)pdest, (*(int8_t*)psrc));
ESP_LOGV(TAG, "Convert uint8 B[%d] 0x%04" PRIx16 " = 0x%04" PRIx16, i, *(uint16_t *)psrc, *(uint16_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_U8_REG) {
mb_set_int8_a((val_16_arr *)dest_ptr, (*(int8_t*)src_ptr));
ESP_LOGV(TAG, "Convert uint8 B[%d] 0x%04" PRIx16 " = 0x%04" PRIx16, i, *(uint16_t *)src_ptr, *(uint16_t *)dest_ptr);
}
break;
case PARAM_TYPE_I8_B:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_U8_REG) {
mb_set_int8_b((val_16_arr *)pdest, (int8_t)((*(uint16_t*)psrc) >> 8));
ESP_LOGV(TAG, "Convert int8 A[%d] 0x%02" PRIx16 " = 0x%02" PRIx16, i, *(uint16_t *)psrc, *(uint16_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_U8_REG) {
mb_set_int8_b((val_16_arr *)dest_ptr, (int8_t)((*(uint16_t*)src_ptr) >> 8));
ESP_LOGV(TAG, "Convert int8 A[%d] 0x%02" PRIx16 " = 0x%02" PRIx16, i, *(uint16_t *)src_ptr, *(uint16_t *)dest_ptr);
}
break;
case PARAM_TYPE_U8_A:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_U8_REG) {
mb_set_uint8_a((val_16_arr *)pdest, (*(uint8_t*)psrc));
ESP_LOGV(TAG, "Convert uint8 A[%d] 0x%02" PRIx16 " = %02" PRIx16, i, *(uint16_t *)psrc, *(uint16_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_U8_REG) {
mb_set_uint8_a((val_16_arr *)dest_ptr, (*(uint8_t*)src_ptr));
ESP_LOGV(TAG, "Convert uint8 A[%d] 0x%02" PRIx16 " = %02" PRIx16, i, *(uint16_t *)src_ptr, *(uint16_t *)dest_ptr);
}
break;
case PARAM_TYPE_U8_B:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_U8_REG) {
uint8_t data = (uint8_t)((*(uint16_t*)psrc) >> 8);
mb_set_uint8_b((val_16_arr *)pdest, data);
ESP_LOGV(TAG, "Convert uint8 B[%d] 0x%02" PRIx16 " = 0x%02" PRIx16, i, *(uint16_t *)psrc, *(uint16_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_U8_REG) {
uint8_t data = (uint8_t)((*(uint16_t*)src_ptr) >> 8);
mb_set_uint8_b((val_16_arr *)dest_ptr, data);
ESP_LOGV(TAG, "Convert uint8 B[%d] 0x%02" PRIx16 " = 0x%02" PRIx16, i, *(uint16_t *)src_ptr, *(uint16_t *)dest_ptr);
}
break;
case PARAM_TYPE_I16_AB:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_I16) {
mb_set_int16_ab((val_16_arr *)pdest, *(int16_t*)psrc);
ESP_LOGV(TAG, "Convert int16 AB[%d] 0x%04" PRIx16 " = 0x%04" PRIx16, i, *(uint16_t *)psrc, *(uint16_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_I16) {
mb_set_int16_ab((val_16_arr *)dest_ptr, *(int16_t*)src_ptr);
ESP_LOGV(TAG, "Convert int16 AB[%d] 0x%04" PRIx16 " = 0x%04" PRIx16, i, *(uint16_t *)src_ptr, *(uint16_t *)dest_ptr);
}
break;
case PARAM_TYPE_I16_BA:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_I16) {
mb_set_int16_ba((val_16_arr *)pdest, *(int16_t*)psrc);
ESP_LOGV(TAG, "Convert int16 BA[%d] 0x%04" PRIx16 " = 0x%04" PRIx16, i, *(uint16_t *)psrc, *(uint16_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_I16) {
mb_set_int16_ba((val_16_arr *)dest_ptr, *(int16_t*)src_ptr);
ESP_LOGV(TAG, "Convert int16 BA[%d] 0x%04" PRIx16 " = 0x%04" PRIx16, i, *(uint16_t *)src_ptr, *(uint16_t *)dest_ptr);
}
break;
case PARAM_TYPE_U16_AB:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_U16) {
mb_set_uint16_ab((val_16_arr *)pdest, *(uint16_t*)psrc);
ESP_LOGV(TAG, "Convert uint16 AB[%d] 0x%02" PRIx16 " = 0x%02" PRIx16, i, *(uint16_t *)psrc, *(uint16_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_U16) {
mb_set_uint16_ab((val_16_arr *)dest_ptr, *(uint16_t*)src_ptr);
ESP_LOGV(TAG, "Convert uint16 AB[%d] 0x%02" PRIx16 " = 0x%02" PRIx16, i, *(uint16_t *)src_ptr, *(uint16_t *)dest_ptr);
}
break;
case PARAM_TYPE_U16_BA:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_U16) {
mb_set_uint16_ba((val_16_arr *)pdest, *(uint16_t*)psrc);
ESP_LOGV(TAG, "Convert uint16 BA[%d] 0x%02" PRIx16 " = 0x%02" PRIx16, i, *(uint16_t *)psrc, *(uint16_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_U16) {
mb_set_uint16_ba((val_16_arr *)dest_ptr, *(uint16_t*)src_ptr);
ESP_LOGV(TAG, "Convert uint16 BA[%d] 0x%02" PRIx16 " = 0x%02" PRIx16, i, *(uint16_t *)src_ptr, *(uint16_t *)dest_ptr);
}
break;
case PARAM_TYPE_I32_ABCD:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_I32) {
mb_set_int32_abcd((val_32_arr *)pdest, *(int32_t *)psrc);
ESP_LOGV(TAG, "Convert int32 ABCD[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)psrc, *(uint32_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_I32) {
mb_set_int32_abcd((val_32_arr *)dest_ptr, *(int32_t *)src_ptr);
ESP_LOGV(TAG, "Convert int32 ABCD[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)src_ptr, *(uint32_t *)dest_ptr);
}
break;
case PARAM_TYPE_U32_ABCD:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_U32) {
mb_set_uint32_abcd((val_32_arr *)pdest, *(uint32_t *)psrc);
ESP_LOGV(TAG, "Convert uint32 ABCD[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)psrc, *(uint32_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_U32) {
mb_set_uint32_abcd((val_32_arr *)dest_ptr, *(uint32_t *)src_ptr);
ESP_LOGV(TAG, "Convert uint32 ABCD[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)src_ptr, *(uint32_t *)dest_ptr);
}
break;
case PARAM_TYPE_FLOAT_ABCD:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_FLOAT) {
mb_set_float_abcd((val_32_arr *)pdest, *(float *)psrc);
ESP_LOGV(TAG, "Convert float ABCD[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)psrc, *(uint32_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_FLOAT) {
mb_set_float_abcd((val_32_arr *)dest_ptr, *(float *)src_ptr);
ESP_LOGV(TAG, "Convert float ABCD[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)src_ptr, *(uint32_t *)dest_ptr);
}
break;
case PARAM_TYPE_I32_CDAB:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_I32) {
mb_set_int32_cdab((val_32_arr *)pdest, *(int32_t *)psrc);
ESP_LOGV(TAG, "Convert int32 CDAB[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)psrc, *(uint32_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_I32) {
mb_set_int32_cdab((val_32_arr *)dest_ptr, *(int32_t *)src_ptr);
ESP_LOGV(TAG, "Convert int32 CDAB[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)src_ptr, *(uint32_t *)dest_ptr);
}
break;
case PARAM_TYPE_U32_CDAB:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_U32) {
mb_set_uint32_cdab((val_32_arr *)pdest, *(uint32_t *)psrc);
ESP_LOGV(TAG, "Convert uint32 CDAB[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)psrc, *(uint32_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_U32) {
mb_set_uint32_cdab((val_32_arr *)dest_ptr, *(uint32_t *)src_ptr);
ESP_LOGV(TAG, "Convert uint32 CDAB[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)src_ptr, *(uint32_t *)dest_ptr);
}
break;
case PARAM_TYPE_FLOAT_CDAB:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_FLOAT) {
mb_set_float_cdab((val_32_arr *)pdest, *(float *)psrc);
ESP_LOGV(TAG, "Convert float CDAB[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)psrc, *(uint32_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_FLOAT) {
mb_set_float_cdab((val_32_arr *)dest_ptr, *(float *)src_ptr);
ESP_LOGV(TAG, "Convert float CDAB[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)src_ptr, *(uint32_t *)dest_ptr);
}
break;
case PARAM_TYPE_I32_BADC:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_I32) {
mb_set_int32_badc((val_32_arr *)pdest, *(int32_t *)psrc);
ESP_LOGV(TAG, "Convert int32 BADC[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)psrc, *(uint32_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_I32) {
mb_set_int32_badc((val_32_arr *)dest_ptr, *(int32_t *)src_ptr);
ESP_LOGV(TAG, "Convert int32 BADC[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)src_ptr, *(uint32_t *)dest_ptr);
}
break;
case PARAM_TYPE_U32_BADC:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_U32) {
mb_set_uint32_badc((val_32_arr *)pdest, *(uint32_t *)psrc);
ESP_LOGV(TAG, "Convert uint32 BADC[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)psrc, *(uint32_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_U32) {
mb_set_uint32_badc((val_32_arr *)dest_ptr, *(uint32_t *)src_ptr);
ESP_LOGV(TAG, "Convert uint32 BADC[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)src_ptr, *(uint32_t *)dest_ptr);
}
break;
case PARAM_TYPE_FLOAT_BADC:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_FLOAT) {
mb_set_float_badc((val_32_arr *)pdest, *(float *)psrc);
ESP_LOGV(TAG, "Convert float BADC[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)psrc, *(uint32_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_FLOAT) {
mb_set_float_badc((val_32_arr *)dest_ptr, *(float *)src_ptr);
ESP_LOGV(TAG, "Convert float BADC[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)src_ptr, *(uint32_t *)dest_ptr);
}
break;
case PARAM_TYPE_I32_DCBA:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_I32) {
mb_set_int32_dcba((val_32_arr *)pdest, *(int32_t *)psrc);
ESP_LOGV(TAG, "Convert int32 DCBA[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)psrc, *(uint32_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_I32) {
mb_set_int32_dcba((val_32_arr *)dest_ptr, *(int32_t *)src_ptr);
ESP_LOGV(TAG, "Convert int32 DCBA[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)src_ptr, *(uint32_t *)dest_ptr);
}
break;
case PARAM_TYPE_U32_DCBA:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_U32) {
mb_set_uint32_dcba((val_32_arr *)pdest, *(uint32_t *)psrc);
ESP_LOGV(TAG, "Convert uint32 DCBA[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)psrc, *(uint32_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_U32) {
mb_set_uint32_dcba((val_32_arr *)dest_ptr, *(uint32_t *)src_ptr);
ESP_LOGV(TAG, "Convert uint32 DCBA[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)src_ptr, *(uint32_t *)dest_ptr);
}
break;
case PARAM_TYPE_FLOAT_DCBA:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_FLOAT) {
mb_set_float_dcba((val_32_arr *)pdest, *(float *)psrc);
ESP_LOGV(TAG, "Convert float DCBA[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)psrc, *(uint32_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_FLOAT) {
mb_set_float_dcba((val_32_arr *)dest_ptr, *(float *)src_ptr);
ESP_LOGV(TAG, "Convert float DCBA[%d] 0x%04" PRIx32 " = 0x%04" PRIx32, i, *(uint32_t *)src_ptr, *(uint32_t *)dest_ptr);
}
break;
case PARAM_TYPE_I64_ABCDEFGH:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_I64) {
mb_set_int64_abcdefgh((val_64_arr *)pdest, *(int64_t *)psrc);
ESP_LOGV(TAG, "Convert int64 ABCDEFGH[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)psrc, *(uint64_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_I64) {
mb_set_int64_abcdefgh((val_64_arr *)dest_ptr, *(int64_t *)src_ptr);
ESP_LOGV(TAG, "Convert int64 ABCDEFGH[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)src_ptr, *(uint64_t *)dest_ptr);
}
break;
case PARAM_TYPE_U64_ABCDEFGH:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_U64) {
mb_set_uint64_abcdefgh((val_64_arr *)pdest, *(uint64_t *)psrc);
ESP_LOGV(TAG, "Convert double ABCDEFGH[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)psrc, *(uint64_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_U64) {
mb_set_uint64_abcdefgh((val_64_arr *)dest_ptr, *(uint64_t *)src_ptr);
ESP_LOGV(TAG, "Convert double ABCDEFGH[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)src_ptr, *(uint64_t *)dest_ptr);
}
break;
case PARAM_TYPE_DOUBLE_ABCDEFGH:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_DOUBLE) {
mb_set_double_abcdefgh((val_64_arr *)pdest, *(double *)psrc);
ESP_LOGV(TAG, "Convert double ABCDEFGH[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)psrc, *(uint64_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_DOUBLE) {
mb_set_double_abcdefgh((val_64_arr *)dest_ptr, *(double *)src_ptr);
ESP_LOGV(TAG, "Convert double ABCDEFGH[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)src_ptr, *(uint64_t *)dest_ptr);
}
break;
case PARAM_TYPE_I64_HGFEDCBA:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_I64) {
mb_set_int64_hgfedcba((val_64_arr *)pdest, *(int64_t *)psrc);
ESP_LOGV(TAG, "Convert int64 HGFEDCBA[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)psrc, *(uint64_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_I64) {
mb_set_int64_hgfedcba((val_64_arr *)dest_ptr, *(int64_t *)src_ptr);
ESP_LOGV(TAG, "Convert int64 HGFEDCBA[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)src_ptr, *(uint64_t *)dest_ptr);
}
break;
case PARAM_TYPE_U64_HGFEDCBA:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_U64) {
mb_set_uint64_hgfedcba((val_64_arr *)pdest, *(uint64_t *)psrc);
ESP_LOGV(TAG, "Convert double HGFEDCBA[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)psrc, *(uint64_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_U64) {
mb_set_uint64_hgfedcba((val_64_arr *)dest_ptr, *(uint64_t *)src_ptr);
ESP_LOGV(TAG, "Convert double HGFEDCBA[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)src_ptr, *(uint64_t *)dest_ptr);
}
break;
case PARAM_TYPE_DOUBLE_HGFEDCBA:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_DOUBLE) {
mb_set_double_hgfedcba((val_64_arr *)pdest, *(double *)psrc);
ESP_LOGV(TAG, "Convert double HGFEDCBA[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)psrc, *(uint64_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_DOUBLE) {
mb_set_double_hgfedcba((val_64_arr *)dest_ptr, *(double *)src_ptr);
ESP_LOGV(TAG, "Convert double HGFEDCBA[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)src_ptr, *(uint64_t *)dest_ptr);
}
break;
case PARAM_TYPE_I64_GHEFCDAB:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_I64) {
mb_set_int64_ghefcdab((val_64_arr *)pdest, *(int64_t *)psrc);
ESP_LOGV(TAG, "Convert int64 GHEFCDAB[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)psrc, *(uint64_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_I64) {
mb_set_int64_ghefcdab((val_64_arr *)dest_ptr, *(int64_t *)src_ptr);
ESP_LOGV(TAG, "Convert int64 GHEFCDAB[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)src_ptr, *(uint64_t *)dest_ptr);
}
break;
case PARAM_TYPE_U64_GHEFCDAB:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_U64) {
mb_set_uint64_ghefcdab((val_64_arr *)pdest, *(uint64_t *)psrc);
ESP_LOGV(TAG, "Convert uint64 GHEFCDAB[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)psrc, *(uint64_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_U64) {
mb_set_uint64_ghefcdab((val_64_arr *)dest_ptr, *(uint64_t *)src_ptr);
ESP_LOGV(TAG, "Convert uint64 GHEFCDAB[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)src_ptr, *(uint64_t *)dest_ptr);
}
break;
case PARAM_TYPE_DOUBLE_GHEFCDAB:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_DOUBLE) {
mb_set_double_ghefcdab((val_64_arr *)pdest, *(double *)psrc);
ESP_LOGV(TAG, "Convert double GHEFCDAB[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)psrc, *(uint64_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_DOUBLE) {
mb_set_double_ghefcdab((val_64_arr *)dest_ptr, *(double *)src_ptr);
ESP_LOGV(TAG, "Convert double GHEFCDAB[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)src_ptr, *(uint64_t *)dest_ptr);
}
break;
case PARAM_TYPE_I64_BADCFEHG:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_I64) {
mb_set_int64_badcfehg((val_64_arr *)pdest, *(int64_t *)psrc);
ESP_LOGV(TAG, "Convert int64 BADCFEHG[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)psrc, *(uint64_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_I64) {
mb_set_int64_badcfehg((val_64_arr *)dest_ptr, *(int64_t *)src_ptr);
ESP_LOGV(TAG, "Convert int64 BADCFEHG[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)src_ptr, *(uint64_t *)dest_ptr);
}
break;
case PARAM_TYPE_U64_BADCFEHG:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_U64) {
mb_set_uint64_badcfehg((val_64_arr *)pdest, *(uint64_t *)psrc);
ESP_LOGV(TAG, "Convert uint64 BADCFEHG[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)psrc, *(uint64_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_U64) {
mb_set_uint64_badcfehg((val_64_arr *)dest_ptr, *(uint64_t *)src_ptr);
ESP_LOGV(TAG, "Convert uint64 BADCFEHG[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)src_ptr, *(uint64_t *)dest_ptr);
}
break;
case PARAM_TYPE_DOUBLE_BADCFEHG:
for MB_EACH_ELEM(psrc, pdest, param_size, PARAM_SIZE_DOUBLE) {
mb_set_double_badcfehg((val_64_arr *)pdest, *(double *)psrc);
ESP_LOGV(TAG, "Convert double BADCFEHG[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)psrc, *(uint64_t *)pdest);
for MB_EACH_ELEM(src_ptr, dest_ptr, param_size, PARAM_SIZE_DOUBLE) {
mb_set_double_badcfehg((val_64_arr *)dest_ptr, *(double *)src_ptr);
ESP_LOGV(TAG, "Convert double BADCFEHG[%d] 0x%" PRIx64 " = 0x%" PRIx64, i, *(uint64_t *)src_ptr, *(uint64_t *)dest_ptr);
}
break;
@@ -740,34 +738,34 @@ esp_err_t mbc_master_set_param_data(void* dest, void* src, mb_descr_type_t param
// Supports custom command options using the PAR_PERMS_CUST_CMD permission.
// The MB_PARAM_CUSTOM register type mimics the custom commands specificly handled with
// custom command handlers which have to be defined in command handling table.
uint8_t mbc_master_get_command(const mb_parameter_descriptor_t *pdescr, mb_param_mode_t mode)
uint8_t mbc_master_get_command(const mb_parameter_descriptor_t *descr, mb_param_mode_t mode)
{
MB_RETURN_ON_FALSE((pdescr), 0, TAG, "incorrect data pointer.");
MB_RETURN_ON_FALSE((descr), 0, TAG, "incorrect data pointer.");
uint8_t command = 0;
switch(pdescr->mb_param_type)
switch(descr->mb_param_type)
{
case MB_PARAM_HOLDING:
command = GET_CMD(mode, pdescr->access, MB_FUNC_READ_HOLDING_REGISTER, MB_FUNC_WRITE_MULTIPLE_REGISTERS);
command = GET_CMD(mode, descr->access, MB_FUNC_READ_HOLDING_REGISTER, MB_FUNC_WRITE_MULTIPLE_REGISTERS);
break;
case MB_PARAM_INPUT:
command = GET_CMD(mode, pdescr->access, MB_FUNC_READ_INPUT_REGISTER, 0);
command = GET_CMD(mode, descr->access, MB_FUNC_READ_INPUT_REGISTER, 0);
break;
case MB_PARAM_COIL:
command = GET_CMD(mode, pdescr->access, MB_FUNC_READ_COILS, MB_FUNC_WRITE_MULTIPLE_COILS);
command = GET_CMD(mode, descr->access, MB_FUNC_READ_COILS, MB_FUNC_WRITE_MULTIPLE_COILS);
break;
case MB_PARAM_DISCRETE:
command = GET_CMD(mode, pdescr->access, MB_FUNC_READ_DISCRETE_INPUTS, 0);
command = GET_CMD(mode, descr->access, MB_FUNC_READ_DISCRETE_INPUTS, 0);
break;
case MB_PARAM_CUSTOM:
if (pdescr->access & PAR_PERMS_CUST_CMD) {
if (descr->access & PAR_PERMS_CUST_CMD) {
// Use custom command in the request for read or write
command = GET_CMD(mode, pdescr->access, (uint8_t)pdescr->param_opts.cust_cmd_read, (uint8_t)pdescr->param_opts.cust_cmd_write);
command = GET_CMD(mode, descr->access, (uint8_t)descr->param_opts.cust_cmd_read, (uint8_t)descr->param_opts.cust_cmd_write);
} else {
command = 0;
}
break;
default:
ESP_LOGE(TAG, "%s: Incorrect param type (%u)", __FUNCTION__, (unsigned)pdescr->mb_param_type);
ESP_LOGE(TAG, "%s: Incorrect param type (%u)", __FUNCTION__, (unsigned)descr->mb_param_type);
break;
}
return command;

View File

@@ -16,21 +16,20 @@
/**
* Initialization of Modbus master serial
*/
esp_err_t mbc_master_create_serial(mb_communication_info_t *config, void **handler)
esp_err_t mbc_master_create_serial(mb_communication_info_t *config, void **ctx)
{
void *ctx = NULL;
void *obj = NULL;
esp_err_t error = ESP_ERR_NOT_SUPPORTED;
switch(config->mode) {
case MB_RTU:
case MB_ASCII:
error = mbc_serial_master_create(config, &ctx);
error = mbc_serial_master_create(config, &obj);
break;
default:
return ESP_ERR_NOT_SUPPORTED;
}
if ((ctx) && (error == ESP_OK)) {
//mbc_master_init_iface(ctx);
*handler = ctx;
if ((obj) && (error == ESP_OK)) {
*ctx = obj;
}
return error;
}

View File

@@ -14,13 +14,13 @@
/**
* Initialization of Modbus TCP Master controller interface
*/
esp_err_t mbc_master_create_tcp(mb_communication_info_t *config, void **handler)
esp_err_t mbc_master_create_tcp(mb_communication_info_t *config, void **ctx)
{
void *ctx = NULL;
esp_err_t error = mbc_tcp_master_create(config, &ctx);
void *obj = NULL;
esp_err_t error = mbc_tcp_master_create(config, &obj);
if ((ctx) && (error == ESP_OK)) {
*handler = ctx;
if ((obj) && (error == ESP_OK)) {
*ctx = obj;
}
return error;
}

View File

@@ -116,10 +116,10 @@ esp_err_t mbc_slave_lock(void *ctx)
MB_RETURN_ON_FALSE(ctx, ESP_ERR_INVALID_STATE, TAG,
"Slave interface is not correctly initialized.");
mbs_controller_iface_t *mbs_controller = MB_SLAVE_GET_IFACE(ctx);
mb_base_t *pmb_obj = (mb_base_t *)mbs_controller->mb_base;
MB_RETURN_ON_FALSE((pmb_obj && pmb_obj->lock), ESP_ERR_INVALID_STATE, TAG,
mb_base_t *mb_obj = mbs_controller->mb_base;
MB_RETURN_ON_FALSE((mb_obj && mb_obj->lock), ESP_ERR_INVALID_STATE, TAG,
"Slave interface is not correctly initialized.");
CRITICAL_SECTION_LOCK(pmb_obj->lock);
CRITICAL_SECTION_LOCK(mb_obj->lock);
return ESP_OK;
}
@@ -131,10 +131,10 @@ esp_err_t mbc_slave_unlock(void *ctx)
MB_RETURN_ON_FALSE(ctx, ESP_ERR_INVALID_STATE, TAG,
"Slave interface is not correctly initialized.");
mbs_controller_iface_t *mbs_controller = MB_SLAVE_GET_IFACE(ctx);
mb_base_t *pmb_obj = (mb_base_t *)mbs_controller->mb_base;
MB_RETURN_ON_FALSE((pmb_obj && pmb_obj->lock), ESP_ERR_INVALID_STATE, TAG,
mb_base_t *mb_obj = mbs_controller->mb_base;
MB_RETURN_ON_FALSE((mb_obj && mb_obj->lock), ESP_ERR_INVALID_STATE, TAG,
"Slave interface is not correctly initialized.");
CRITICAL_SECTION_UNLOCK(pmb_obj->lock);
CRITICAL_SECTION_UNLOCK(mb_obj->lock);
return ESP_OK;
}
@@ -142,15 +142,15 @@ esp_err_t mbc_slave_unlock(void *ctx)
/**
* Set object ID for the Modbus controller
*/
esp_err_t mbc_set_slave_id(void *ctx, uint8_t slave_addr, bool is_running, uint8_t const *pdata, uint8_t data_len)
esp_err_t mbc_set_slave_id(void *ctx, uint8_t uid, bool is_running, uint8_t const *data_ptr, uint8_t data_len)
{
MB_RETURN_ON_FALSE(ctx, ESP_ERR_INVALID_STATE, TAG,
"Slave interface is not correctly initialized.");
mbs_controller_iface_t *pmbs_controller = MB_SLAVE_GET_IFACE(ctx);
mbs_controller_iface_t *mbs_controller = MB_SLAVE_GET_IFACE(ctx);
// The Report Slave ID functionality is useful for TCP and gateway,
// so the design decision is to keep this functionality for all slaves
// Set the slave ID if the KConfig option is selected
mb_err_enum_t status = mbs_set_slave_id(pmbs_controller->mb_base, slave_addr, is_running, (uint8_t *)pdata, data_len);
mb_err_enum_t status = mbs_set_slave_id(mbs_controller->mb_base, uid, is_running, (uint8_t *)data_ptr, data_len);
MB_RETURN_ON_FALSE((status == MB_ENOERR), ESP_ERR_INVALID_STATE, TAG, "mb stack set slave ID failure.");
return MB_ERR_TO_ESP_ERR(status);
}
@@ -158,12 +158,12 @@ esp_err_t mbc_set_slave_id(void *ctx, uint8_t slave_addr, bool is_running, uint8
/**
* Get object ID from the Modbus controller
*/
esp_err_t mbc_get_slave_id(void *ctx, uint8_t const *pdata, uint8_t *pdata_len)
esp_err_t mbc_get_slave_id(void *ctx, uint8_t const *data_ptr, uint8_t *data_len)
{
MB_RETURN_ON_FALSE(ctx, ESP_ERR_INVALID_STATE, TAG,
"Slave interface is not correctly initialized.");
mbs_controller_iface_t *pmbs_controller = MB_SLAVE_GET_IFACE(ctx);
mb_err_enum_t status = mbs_get_slave_id(pmbs_controller->mb_base, (uint8_t *)pdata, pdata_len);
mbs_controller_iface_t *mbs_controller = MB_SLAVE_GET_IFACE(ctx);
mb_err_enum_t status = mbs_get_slave_id(mbs_controller->mb_base, (uint8_t *)data_ptr, data_len);
MB_RETURN_ON_FALSE((status == MB_ENOERR), ESP_ERR_INVALID_STATE, TAG, "mb stack get slave ID failure.");
return MB_ERR_TO_ESP_ERR(status);
}
@@ -348,7 +348,7 @@ mb_err_enum_t mbc_reg_input_slave_cb(mb_base_t *inst, uint8_t *reg_buffer, uint1
address--; // address of register is already +1
mb_descr_entry_t *it = mbc_slave_find_reg_descriptor(ctx, MB_PARAM_INPUT, address, n_regs);
if (it) {
uint16_t input_reg_start = (uint16_t)it->start_offset; // Get Modbus start address
uint16_t input_reg_start = it->start_offset; // Get Modbus start address
uint8_t *input_buffer = (uint8_t *)it->p_data; // Get instance address
uint16_t regs = n_regs;
uint16_t reg_index;
@@ -368,8 +368,7 @@ mb_err_enum_t mbc_reg_input_slave_cb(mb_base_t *inst, uint8_t *reg_buffer, uint1
// Send access notification
(void)mbc_slave_send_param_access_notification(ctx, MB_EVENT_INPUT_REG_RD);
// Send parameter info to application task
(void)mbc_slave_send_param_info(ctx, MB_EVENT_INPUT_REG_RD, address,
(uint8_t *)buffer_start, n_regs);
(void)mbc_slave_send_param_info(ctx, MB_EVENT_INPUT_REG_RD, address, buffer_start, n_regs);
} else {
status = MB_ENOREG;
}
@@ -387,8 +386,8 @@ mb_err_enum_t mbc_reg_holding_slave_cb(mb_base_t *inst, uint8_t *reg_buffer, uin
address--; // address of register is already +1
mb_descr_entry_t *it = mbc_slave_find_reg_descriptor(ctx, MB_PARAM_HOLDING, address, n_regs);
if (it) {
uint16_t reg_holding_start = (uint16_t)it->start_offset; // Get Modbus start address
uint8_t *holding_buffer = (uint8_t *)it->p_data; // Get instance address
uint16_t reg_holding_start = it->start_offset; // Get Modbus start address
uint8_t *holding_buffer = it->p_data; // Get instance address
uint16_t regs = n_regs;
reg_index = (uint16_t) (address - reg_holding_start);
reg_index <<= 1; // register Address to byte address
@@ -408,8 +407,7 @@ mb_err_enum_t mbc_reg_holding_slave_cb(mb_base_t *inst, uint8_t *reg_buffer, uin
// Send access notification
(void)mbc_slave_send_param_access_notification(ctx, MB_EVENT_HOLDING_REG_RD);
// Send parameter info
(void)mbc_slave_send_param_info(ctx, MB_EVENT_HOLDING_REG_RD, address,
(uint8_t *)buffer_start, n_regs);
(void)mbc_slave_send_param_info(ctx, MB_EVENT_HOLDING_REG_RD, address, buffer_start, n_regs);
} else {
status = MB_EINVAL;
}
@@ -428,8 +426,7 @@ mb_err_enum_t mbc_reg_holding_slave_cb(mb_base_t *inst, uint8_t *reg_buffer, uin
// Send access notification
(void)mbc_slave_send_param_access_notification(ctx, MB_EVENT_HOLDING_REG_WR);
// Send parameter info
(void)mbc_slave_send_param_info(ctx, MB_EVENT_HOLDING_REG_WR, (uint16_t)address,
(uint8_t *)buffer_start, (uint16_t)n_regs);
(void)mbc_slave_send_param_info(ctx, MB_EVENT_HOLDING_REG_WR, address, buffer_start, n_regs);
} else {
status = MB_EINVAL;
}
@@ -453,8 +450,8 @@ mb_err_enum_t mbc_reg_coils_slave_cb(mb_base_t *inst, uint8_t *reg_buffer, uint1
address--; // The address is already +1
mb_descr_entry_t *it = mbc_slave_find_reg_descriptor(ctx, MB_PARAM_COIL, address, n_coils);
if (it) {
uint16_t reg_coils_start = (uint16_t)it->start_offset; // MB offset of coils
uint8_t *reg_coils_buf = (uint8_t *)it->p_data;
uint16_t reg_coils_start = it->start_offset; // MB offset of coils
uint8_t *reg_coils_buf = it->p_data;
reg_index = (uint16_t) (address - it->start_offset);
char *coils_data_buf = (char *)(reg_coils_buf + (reg_index >> 3));
switch (mode) {
@@ -463,7 +460,7 @@ mb_err_enum_t mbc_reg_coils_slave_cb(mb_base_t *inst, uint8_t *reg_buffer, uint1
CRITICAL_SECTION(inst->lock)
{
while (coils > 0) {
uint8_t result = mb_util_get_bits((uint8_t *)reg_coils_buf, reg_index, 1);
uint8_t result = mb_util_get_bits(reg_coils_buf, reg_index, 1);
mb_util_set_bits(reg_buffer, reg_index - (address - reg_coils_start), 1, result);
reg_index++;
coils--;
@@ -484,7 +481,7 @@ mb_err_enum_t mbc_reg_coils_slave_cb(mb_base_t *inst, uint8_t *reg_buffer, uint1
while (coils > 0) {
uint8_t result = mb_util_get_bits(reg_buffer,
reg_index - (address - reg_coils_start), 1);
mb_util_set_bits((uint8_t *)reg_coils_buf, reg_index, 1, result);
mb_util_set_bits(reg_coils_buf, reg_index, 1, result);
reg_index++;
coils--;
}
@@ -519,7 +516,7 @@ mb_err_enum_t mbc_reg_discrete_slave_cb(mb_base_t *inst, uint8_t *reg_buffer, ui
address--;
mb_descr_entry_t *it = mbc_slave_find_reg_descriptor(ctx, MB_PARAM_DISCRETE, address, n_discrete);
if (it) {
uint16_t reg_discrete_start = (uint16_t)it->start_offset; // MB offset of registers
uint16_t reg_discrete_start = it->start_offset; // MB offset of registers
n_reg = (n_discrete >> 3) + 1;
discrete_input_buf = (uint8_t *)it->p_data; // the storage address
reg_index = (uint16_t) (address - reg_discrete_start) / 8; // Get register index in the buffer for bit number
@@ -540,8 +537,7 @@ mb_err_enum_t mbc_reg_discrete_slave_cb(mb_base_t *inst, uint8_t *reg_buffer, ui
*reg_buffer = *reg_buffer >> (8 - n_discrete);
// Send an event to notify application task about event
(void)mbc_slave_send_param_access_notification(ctx, MB_EVENT_DISCRETE_RD);
(void)mbc_slave_send_param_info(ctx, MB_EVENT_DISCRETE_RD, address,
(uint8_t *)temp_buf, n_discrete);
(void)mbc_slave_send_param_info(ctx, MB_EVENT_DISCRETE_RD, address, temp_buf, n_discrete);
} else {
status = MB_ENOREG;
}

View File

@@ -17,23 +17,23 @@
/**
* Initialization of Modbus Serial slave controller
*/
esp_err_t mbc_slave_create_serial(mb_communication_info_t *config, void **handler)
esp_err_t mbc_slave_create_serial(mb_communication_info_t *config, void **ctx)
{
void *ctx = NULL;
void *obj = NULL;
esp_err_t error = ESP_ERR_NOT_SUPPORTED;
switch(config->mode)
{
case MB_RTU:
case MB_ASCII:
// Call constructor function of actual port implementation
error = mbc_serial_slave_create(config, &ctx);
error = mbc_serial_slave_create(config, &obj);
break;
default:
return ESP_ERR_NOT_SUPPORTED;
}
if ((ctx) && (error == ESP_OK)) {
mbc_slave_init_iface(ctx);
*handler = ctx;
if ((obj) && (error == ESP_OK)) {
mbc_slave_init_iface(obj);
*ctx = obj;
}
return error;
}

View File

@@ -15,14 +15,14 @@
/**
* Initialization of Modbus TCP Slave controller
*/
esp_err_t mbc_slave_create_tcp(mb_communication_info_t *config, void **handler)
esp_err_t mbc_slave_create_tcp(mb_communication_info_t *config, void **ctx)
{
void *ctx = NULL;
esp_err_t error = mbc_tcp_slave_create(config, &ctx);
void *obj = NULL;
esp_err_t error = mbc_tcp_slave_create(config, &obj);
if ((ctx) && (error == ESP_OK)) {
mbc_slave_init_iface(ctx);
*handler = ctx;
if ((obj) && (error == ESP_OK)) {
mbc_slave_init_iface(obj);
*ctx = obj;
}
return error;
}

View File

@@ -159,14 +159,14 @@ typedef enum {
MB_PARAM_UNKNOWN = 0xFF
} mb_param_type_t;
typedef enum _mb_comm_mode mb_mode_type_t;
typedef enum mb_comm_mode_enum mb_mode_type_t;
typedef struct mb_base_t mb_base_t;
/*!
* \brief Modbus TCP type of address for communication.
*/
typedef enum _addr_type_enum mb_tcp_addr_type_t;
typedef enum addr_type_enum mb_tcp_addr_type_t;
/*!
* \brief Modbus TCP communication options structure.
@@ -217,7 +217,7 @@ typedef struct {
*
* @param[in] ctx context pointer to the controller object (master or slave)
* @param[in] func_code the function code for the handler
* @param[in] phandler the pointer to function handler being used for command
* @param[in] handler the pointer to function handler being used for command
*
* @return
* - esp_err_t ESP_OK - the function handler is correctly set the handler
@@ -225,21 +225,21 @@ typedef struct {
* - esp_err_t ESP_ERR_INVALID_STATE - can not register non-existent handler or can not
* - esp_err_t ESP_ERR_NOT_FOUND - the requested slave is not found (not connected or not configured)
*/
esp_err_t mbc_set_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp phandler);
esp_err_t mbc_set_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp handler);
/**
* @brief The function gets function handler for specified command from the controller object handler table.
*
* @param[in] ctx context pointer to the controller object (master or slave)
* @param[in] func_code the function code for the handler
* @param[out] phandler the pointer to function handler being returned
* @param[out] handler the pointer to function handler being returned
*
* @return
* - esp_err_t ESP_OK - the function handler is returned
* - esp_err_t ESP_ERR_INVALID_ARG - invalid argument of function or parameter descriptor
* esp_err_t ESP_ERR_INVALID_STATE - can not register non-existent handler or incorrect configuration
*/
esp_err_t mbc_get_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp *phandler);
esp_err_t mbc_get_handler(void *ctx, uint8_t func_code, mb_fn_handler_fp *handler);
/**
* @brief The function deletes function handler for specified command from the controller object command handler table.
@@ -258,14 +258,14 @@ esp_err_t mbc_delete_handler(void *ctx, uint8_t func_code);
* @brief The function gets the number of registered function handlers for the controller object.
*
* @param[in] ctx context pointer to the controller object (master or slave)
* @param[out] pcount the pointer to returned counter
* @param[out] count the pointer to returned counter
*
* @return
* - esp_err_t ESP_OK - the function handler is returned in the
* - esp_err_t ESP_ERR_INVALID_ARG - invalid argument of function or parameter descriptor
* esp_err_t ESP_ERR_INVALID_STATE - can not register non-existent handler or incorrect configuration
*/
esp_err_t mbc_get_handler_count(void *ctx, uint16_t *pcount);
esp_err_t mbc_get_handler_count(void *ctx, uint16_t *count);
#ifdef __cplusplus
}

View File

@@ -30,10 +30,10 @@ extern "C" {
#define MB_MASTER_IS_ACTIVE(pctx) ((bool)(MB_MASTER_GET_IFACE(pctx)->is_active))
#define MB_MASTER_GET_IFACE_FROM_BASE(pinst) (__extension__( \
#define MB_MASTER_GET_IFACE_FROM_BASE(inst) (__extension__( \
{ \
MB_MASTER_ASSERT(pinst); \
mb_base_t *pbase = (mb_base_t *)pinst; \
MB_MASTER_ASSERT(inst); \
mb_base_t *pbase = (mb_base_t *)inst; \
MB_RETURN_ON_FALSE(pbase->descr.parent, MB_EILLSTATE, TAG, "Master interface is not correctly initialized."); \
((mbm_controller_iface_t*)pbase->descr.parent); \
} \
@@ -42,8 +42,8 @@ extern "C" {
/*!
* \brief The macro to access arrays of elements for type conversion.
*/
#define MB_EACH_ELEM(psrc, pdest, arr_size, elem_size) \
(int i = 0; (i < (arr_size / elem_size)); i++, pdest += elem_size, psrc += elem_size)
#define MB_EACH_ELEM(src_ptr, dest_ptr, arr_size, elem_size) \
(int i = 0; (i < (arr_size / elem_size)); i++, dest_ptr += elem_size, src_ptr += elem_size)
/**
* @brief Request mode for parameter to use in data dictionary
@@ -195,7 +195,7 @@ typedef struct {
* - ESP_ERR_NOT_SUPPORTED Port type not supported
* - ESP_ERR_INVALID_STATE Initialization failure
*/
esp_err_t mbc_master_create_tcp(mb_communication_info_t *config, void ** ctx);
esp_err_t mbc_master_create_tcp(mb_communication_info_t *config, void **ctx);
/**
* @brief Initialize Modbus Master controller and stack for Serial port
@@ -208,7 +208,7 @@ esp_err_t mbc_master_create_tcp(mb_communication_info_t *config, void ** ctx);
* - ESP_ERR_NOT_SUPPORTED Port type not supported
* - ESP_ERR_INVALID_STATE Initialization failure
*/
esp_err_t mbc_master_create_serial(mb_communication_info_t *config, void ** ctx);
esp_err_t mbc_master_create_serial(mb_communication_info_t *config, void **ctx);
/**
* @brief Deletes Modbus controller and stack engine
@@ -413,58 +413,58 @@ esp_err_t mbc_master_set_parameter_with(void *ctx, uint16_t cid, uint8_t uid, ui
*
* @param[in] inst the pointer of the initialized modbus base
* @param[in] reg_buffer input buffer of registers
* @param[in] address - start address of register
* @param[in] reg_address - start address of register
* @param[in] mode - parameter access mode (MB_REG_READ, MB_REG_WRITE)
* @param[in] n_regs - number of registers
* @param[in] num_regs - number of registers
*
* @return
* - MB_ENOERR: Read write is successful
* - MB_ENOREG: The argument is incorrect
*/
mb_err_enum_t mbc_reg_holding_master_cb(mb_base_t *inst, uint8_t *reg_buffer, uint16_t address, uint16_t n_regs, mb_reg_mode_enum_t mode) __attribute__ ((weak));
mb_err_enum_t mbc_reg_holding_master_cb(mb_base_t *inst, uint8_t *reg_buffer, uint16_t reg_address, uint16_t num_regs, mb_reg_mode_enum_t mode) __attribute__ ((weak));
/**
* @brief Input register read/write callback function
*
* @param[in] inst the pointer of the initialized modbus base
* @param[in] reg_buffer input buffer of registers
* @param[in] address - start address of register
* @param[in] n_regs - number of registers
* @param[in] reg_address - start address of register
* @param[in] num_regs - number of registers
*
* @return
* - MB_ENOERR: Read write is successful
* - MB_ENOREG: The argument is incorrect
*/
mb_err_enum_t mbc_reg_input_master_cb(mb_base_t *inst, uint8_t *reg_buffer, uint16_t address, uint16_t n_regs) __attribute__ ((weak));
mb_err_enum_t mbc_reg_input_master_cb(mb_base_t *inst, uint8_t *reg_buffer, uint16_t reg_address, uint16_t num_regs) __attribute__ ((weak));
/**
* @brief Discrete register read/write callback function
*
* @param[in] inst the pointer of the initialized modbus base
* @param[in] reg_buffer input buffer of registers
* @param[in] address - start address of register
* @param[in] reg_address - start address of register
* @param[in] n_discrete - number of discrete registers
*
* @return
* - MB_ENOERR: Read write is successful
* - MB_ENOREG: The argument is incorrect
*/
mb_err_enum_t mbc_reg_discrete_master_cb(mb_base_t *inst, uint8_t *reg_buffer, uint16_t address, uint16_t n_discrete) __attribute__ ((weak));
mb_err_enum_t mbc_reg_discrete_master_cb(mb_base_t *inst, uint8_t *reg_buffer, uint16_t reg_address, uint16_t n_discrete) __attribute__ ((weak));
/**
* @brief Coil register read/write callback function
*
* @param[in] inst the pointer of the initialized modbus base
* @param[in] reg_buffer input buffer of registers
* @param[in] address - start address of register
* @param[in] n_coils - number of coil registers
* @param[in] reg_addr - start address of register
* @param[in] ncoils - number of coil registers
* @param[in] mode - parameter access mode (MB_REG_READ, MB_REG_WRITE)
*
* @return
* - MB_ENOERR: Read write is successful
* - MB_ENOREG: The argument is incorrect
*/
mb_err_enum_t mbc_reg_coils_master_cb(mb_base_t *inst, uint8_t *reg_buffer, uint16_t address, uint16_t n_coils, mb_reg_mode_enum_t mode) __attribute__ ((weak));
mb_err_enum_t mbc_reg_coils_master_cb(mb_base_t *inst, uint8_t *reg_buffer, uint16_t reg_addr, uint16_t ncoils, mb_reg_mode_enum_t mode) __attribute__ ((weak));
/**
* @brief The helper function to set data of parameters according to its type
@@ -486,14 +486,14 @@ esp_err_t mbc_master_set_param_data(void* dest, void* src, mb_descr_type_t param
/**
* @brief The helper function to get supported modbus function code (command) according to parameter type
*
* @param[in] pdescr the pointer to the characteristic descriptor in data dictionary
* @param[in] descr the pointer to the characteristic descriptor in data dictionary
* @param[in] mode access mode for characteristic
*
* @return
* - modbus function code, if the command is correctly configured
* - 0 - invalid argument or command not found
*/
uint8_t mbc_master_get_command(const mb_parameter_descriptor_t *pdescr, mb_param_mode_t mode);
uint8_t mbc_master_get_command(const mb_parameter_descriptor_t *descr, mb_param_mode_t mode);
#ifdef __cplusplus

View File

@@ -35,10 +35,10 @@ extern "C" {
#define MB_SLAVE_IS_ACTIVE(pctx) ((bool)(MB_SLAVE_GET_IFACE(pctx)->is_active))
#define MB_SLAVE_GET_IFACE_FROM_BASE(pinst) (__extension__( \
#define MB_SLAVE_GET_IFACE_FROM_BASE(inst) (__extension__( \
{ \
MB_SLAVE_ASSERT(pinst); \
mb_base_t *pbase = (mb_base_t*)pinst; \
MB_SLAVE_ASSERT(inst); \
mb_base_t *pbase = (mb_base_t*)inst; \
MB_RETURN_ON_FALSE(pbase->descr.parent, MB_EILLSTATE, TAG, "Slave interface is not correctly initialized."); \
((mbs_controller_iface_t*)pbase->descr.parent); \
} \
@@ -209,29 +209,29 @@ esp_err_t mbc_slave_set_descriptor(void *ctx, mb_register_area_descriptor_t desc
* @param[in] ctx context pointer of the initialized modbus interface
* @param[in] uid - unit identifier (short slave address) for Modbus slave
* @param[in] is_running - Modbus slave running status
* @param[in] pdata - pointer to data buffer for extended context (vendor specific)
* @param[in] data_ptr - pointer to data buffer for extended context (vendor specific)
* @param[in] data_len - length of data buffer (the length of the extended context)
*
* @return
* - ESP_OK: The appropriate identificator is set
* - ESP_ERR_INVALID_ARG: The argument is incorrect
*/
esp_err_t mbc_set_slave_id(void *ctx, uint8_t uid, bool is_running, uint8_t const *pdata, uint8_t data_len);
esp_err_t mbc_set_slave_id(void *ctx, uint8_t uid, bool is_running, uint8_t const *data_ptr, uint8_t data_len);
/*! \brief Get slave identificator from the modbus object.
*
* This function is used to get the Slave ID array for modbus object.
*
* \param ctx - context pointer of the initialized modbus interface
* \param pdata - the pointer to store object ID array from the modbus object
* \param[in/out] pdata_len - in: length of the allocated pdata array,
* \param data_ptr - the pointer to store object ID array from the modbus object
* \param[in/out] data_len - in: length of the allocated data_ptr array,
* out: returns the actual length of object id.
* returns the modbus error code = ESP_OK, if set correctly,
* ESP_ERR_INVALID_RESPONSE - if the object ID is not set,
* ESP_ERR_INVALID_STATE - no space to store object ID in the pdata buffer,
* ESP_ERR_INVALID_STATE - no space to store object ID in the data_ptr buffer,
* or incorrect arguments are provided
*/
esp_err_t mbc_get_slave_id(void *ctx, uint8_t const *pdata, uint8_t *pdata_len);
esp_err_t mbc_get_slave_id(void *ctx, uint8_t const *data_ptr, uint8_t *data_len);
#endif
/**

View File

@@ -10,9 +10,9 @@
#define INLINE inline __attribute__((always_inline))
static INLINE int16_t mb_get_int16_generic(int n0, int n1, val_16_arr *psrc)
static INLINE int16_t mb_get_int16_generic(int n0, int n1, val_16_arr *src_ptr)
{
val_16_arr *pv = psrc;
val_16_arr *pv = src_ptr;
union {
val_16_arr arr;
int16_t value;
@@ -22,9 +22,9 @@ static INLINE int16_t mb_get_int16_generic(int n0, int n1, val_16_arr *psrc)
return (bov.value);
}
static INLINE uint16_t mb_get_uint16_generic(int n0, int n1, val_16_arr *psrc)
static INLINE uint16_t mb_get_uint16_generic(int n0, int n1, val_16_arr *src_ptr)
{
val_16_arr *pv = psrc;
val_16_arr *pv = src_ptr;
union {
val_16_arr arr;
uint16_t value;
@@ -34,9 +34,9 @@ static INLINE uint16_t mb_get_uint16_generic(int n0, int n1, val_16_arr *psrc)
return (bov.value);
}
static INLINE uint16_t mb_set_uint16_generic(int n0, int n1, val_16_arr *pdest, uint16_t val)
static INLINE uint16_t mb_set_uint16_generic(int n0, int n1, val_16_arr *dest_ptr, uint16_t val)
{
val_16_arr *pv = pdest;
val_16_arr *pv = dest_ptr;
union {
val_16_arr arr;
uint16_t value;
@@ -47,9 +47,9 @@ static INLINE uint16_t mb_set_uint16_generic(int n0, int n1, val_16_arr *pdest,
return (*((uint16_t *)pv));
}
static INLINE int16_t mb_set_int16_generic(int n0, int n1, val_16_arr *pdest, int16_t val)
static INLINE int16_t mb_set_int16_generic(int n0, int n1, val_16_arr *dest_ptr, int16_t val)
{
val_16_arr *pv = pdest;
val_16_arr *pv = dest_ptr;
union {
val_16_arr arr;
int16_t value;
@@ -60,9 +60,9 @@ static INLINE int16_t mb_set_int16_generic(int n0, int n1, val_16_arr *pdest, in
return (*((uint16_t *)pv));
}
static INLINE uint32_t mb_get_uint32_generic(int n0, int n1, int n2, int n3, val_32_arr *psrc)
static INLINE uint32_t mb_get_uint32_generic(int n0, int n1, int n2, int n3, val_32_arr *src_ptr)
{
val_32_arr *pv = psrc;
val_32_arr *pv = src_ptr;
union {
val_32_arr arr;
uint32_t value;
@@ -74,9 +74,9 @@ static INLINE uint32_t mb_get_uint32_generic(int n0, int n1, int n2, int n3, val
return (bov.value);
}
static INLINE int32_t mb_get_int32_generic(int n0, int n1, int n2, int n3, val_32_arr *psrc)
static INLINE int32_t mb_get_int32_generic(int n0, int n1, int n2, int n3, val_32_arr *src_ptr)
{
val_32_arr *pv = psrc;
val_32_arr *pv = src_ptr;
union {
val_32_arr arr;
int32_t value;
@@ -88,9 +88,9 @@ static INLINE int32_t mb_get_int32_generic(int n0, int n1, int n2, int n3, val_3
return (bov.value);
}
static INLINE float mb_get_float_generic(int n0, int n1, int n2, int n3, val_32_arr *psrc)
static INLINE float mb_get_float_generic(int n0, int n1, int n2, int n3, val_32_arr *src_ptr)
{
val_32_arr *pv = psrc;
val_32_arr *pv = src_ptr;
union {
val_32_arr arr;
float value;
@@ -102,9 +102,9 @@ static INLINE float mb_get_float_generic(int n0, int n1, int n2, int n3, val_32_
return (bov.value);
}
static INLINE uint32_t mb_set_int32_generic(int n0, int n1, int n2, int n3, val_32_arr *pdest, int32_t val)
static INLINE uint32_t mb_set_int32_generic(int n0, int n1, int n2, int n3, val_32_arr *dest_ptr, int32_t val)
{
val_32_arr *pv = pdest;
val_32_arr *pv = dest_ptr;
union {
val_32_arr arr;
int32_t value;
@@ -117,9 +117,9 @@ static INLINE uint32_t mb_set_int32_generic(int n0, int n1, int n2, int n3, val_
return (*((uint32_t *)pv));
}
static INLINE uint32_t mb_set_uint32_generic(int n0, int n1, int n2, int n3, val_32_arr *pdest, uint32_t val)
static INLINE uint32_t mb_set_uint32_generic(int n0, int n1, int n2, int n3, val_32_arr *dest_ptr, uint32_t val)
{
val_32_arr *pv = pdest;
val_32_arr *pv = dest_ptr;
union {
val_32_arr arr;
uint32_t value;
@@ -132,9 +132,9 @@ static INLINE uint32_t mb_set_uint32_generic(int n0, int n1, int n2, int n3, val
return (*((uint32_t *)pv));
}
static INLINE uint32_t mb_set_float_generic(int n0, int n1, int n2, int n3, val_32_arr *pdest, float val)
static INLINE uint32_t mb_set_float_generic(int n0, int n1, int n2, int n3, val_32_arr *dest_ptr, float val)
{
val_32_arr *pv = pdest;
val_32_arr *pv = dest_ptr;
union {
val_32_arr arr;
float value;
@@ -147,9 +147,9 @@ static INLINE uint32_t mb_set_float_generic(int n0, int n1, int n2, int n3, val_
return (*((uint32_t *)pv));
}
static INLINE int64_t mb_get_int64_generic(int n0, int n1, int n2, int n3, int n4, int n5, int n6, int n7, val_64_arr *psrc)
static INLINE int64_t mb_get_int64_generic(int n0, int n1, int n2, int n3, int n4, int n5, int n6, int n7, val_64_arr *src_ptr)
{
val_64_arr *pv64 = psrc;
val_64_arr *pv64 = src_ptr;
union {
val_64_arr arr;
int64_t value;
@@ -165,9 +165,9 @@ static INLINE int64_t mb_get_int64_generic(int n0, int n1, int n2, int n3, int n
return (bo64.value);
}
static INLINE uint64_t mb_get_uint64_generic(int n0, int n1, int n2, int n3, int n4, int n5, int n6, int n7, val_64_arr *psrc)
static INLINE uint64_t mb_get_uint64_generic(int n0, int n1, int n2, int n3, int n4, int n5, int n6, int n7, val_64_arr *src_ptr)
{
val_64_arr *pv64 = psrc;
val_64_arr *pv64 = src_ptr;
union {
val_64_arr arr;
uint64_t value;
@@ -183,9 +183,9 @@ static INLINE uint64_t mb_get_uint64_generic(int n0, int n1, int n2, int n3, int
return (bo64.value);
}
static INLINE double mb_get_double_generic(int n0, int n1, int n2, int n3, int n4, int n5, int n6, int n7, val_64_arr *psrc)
static INLINE double mb_get_double_generic(int n0, int n1, int n2, int n3, int n4, int n5, int n6, int n7, val_64_arr *src_ptr)
{
val_64_arr *pv64 = psrc;
val_64_arr *pv64 = src_ptr;
union {
val_64_arr arr;
double value;
@@ -201,9 +201,9 @@ static INLINE double mb_get_double_generic(int n0, int n1, int n2, int n3, int n
return (bo64.value);
}
static INLINE uint64_t mb_set_int64_generic(int n0, int n1, int n2, int n3, int n4, int n5, int n6, int n7, val_64_arr *pdest, int64_t val)
static INLINE uint64_t mb_set_int64_generic(int n0, int n1, int n2, int n3, int n4, int n5, int n6, int n7, val_64_arr *dest_ptr, int64_t val)
{
val_64_arr *pv = pdest;
val_64_arr *pv = dest_ptr;
union {
val_64_arr arr;
int64_t value;
@@ -220,9 +220,9 @@ static INLINE uint64_t mb_set_int64_generic(int n0, int n1, int n2, int n3, int
return (*((uint64_t *)pv));
}
static INLINE uint64_t mb_set_uint64_generic(int n0, int n1, int n2, int n3, int n4, int n5, int n6, int n7, val_64_arr *pdest, uint64_t val)
static INLINE uint64_t mb_set_uint64_generic(int n0, int n1, int n2, int n3, int n4, int n5, int n6, int n7, val_64_arr *dest_ptr, uint64_t val)
{
val_64_arr *pv = pdest;
val_64_arr *pv = dest_ptr;
union {
val_64_arr arr;
uint64_t value;
@@ -239,9 +239,9 @@ static INLINE uint64_t mb_set_uint64_generic(int n0, int n1, int n2, int n3, int
return (*((uint64_t *)pv));
}
static INLINE uint64_t mb_set_double_generic(int n0, int n1, int n2, int n3, int n4, int n5, int n6, int n7, val_64_arr *pdest, double val)
static INLINE uint64_t mb_set_double_generic(int n0, int n1, int n2, int n3, int n4, int n5, int n6, int n7, val_64_arr *dest_ptr, double val)
{
val_64_arr *pv = pdest;
val_64_arr *pv = dest_ptr;
union {
val_64_arr arr;
double value;
@@ -258,426 +258,330 @@ static INLINE uint64_t mb_set_double_generic(int n0, int n1, int n2, int n3, int
return (*((uint64_t *)pv));
}
int8_t mb_get_int8_a(pi16)
val_16_arr *pi16;
int8_t mb_get_int8_a(val_16_arr *pi16)
{
return((int8_t)(*pi16)[MB_BO16_0]);
}
uint16_t mb_set_int8_a(pi16, i8)
val_16_arr *pi16;
int8_t i8;
uint16_t mb_set_int8_a(val_16_arr *pi16, int8_t i8)
{
(*pi16)[MB_BO16_0] = (char)i8;
(*pi16)[MB_BO16_1] = 0;
return (*((uint16_t *)pi16));
}
int8_t mb_get_int8_b(pi16)
val_16_arr *pi16;
int8_t mb_get_int8_b(val_16_arr *pi16)
{
return((int8_t)(*pi16)[MB_BO16_1]);
}
uint16_t mb_set_int8_b(pi16, i8)
val_16_arr *pi16;
int8_t i8;
uint16_t mb_set_int8_b(val_16_arr *pi16, int8_t i8)
{
(*pi16)[MB_BO16_0] = 0;
(*pi16)[MB_BO16_1] = (char)i8;
return (*((uint16_t *)pi16));
}
uint8_t mb_get_uint8_a(pu16)
val_16_arr *pu16;
uint8_t mb_get_uint8_a(val_16_arr *pu16)
{
return((uint8_t)(*pu16)[MB_BO16_0]);
return((*pu16)[MB_BO16_0]);
}
uint16_t mb_set_uint8_a(pu16, u8)
val_16_arr *pu16;
uint8_t u8;
uint16_t mb_set_uint8_a(val_16_arr *pu16, uint8_t u8)
{
(*pu16)[MB_BO16_0] = (char)u8;
(*pu16)[MB_BO16_1] = 0;
return (*((uint16_t *)pu16));
}
uint8_t mb_get_uint8_b(pu16)
val_16_arr *pu16;
uint8_t mb_get_uint8_b(val_16_arr *pu16)
{
return((uint8_t)(*pu16)[MB_BO16_1]);
return((*pu16)[MB_BO16_1]);
}
uint16_t mb_set_uint8_b(pu16, u8)
val_16_arr *pu16;
uint8_t u8;
uint16_t mb_set_uint8_b(val_16_arr *pu16, uint8_t u8)
{
(*pu16)[MB_BO16_0] = 0;
(*pu16)[MB_BO16_1] = (char)u8;
return (*((uint16_t *)pu16));
}
int16_t mb_get_int16_ab(pi16)
val_16_arr *pi16;
int16_t mb_get_int16_ab(val_16_arr *pi16)
{
return mb_get_int16_generic(0, 1, pi16);
}
uint16_t mb_set_int16_ab(pi16, i16)
val_16_arr *pi16;
int16_t i16;
uint16_t mb_set_int16_ab(val_16_arr *pi16, int16_t i16)
{
return mb_set_int16_generic(0, 1, pi16, i16);
}
uint16_t mb_get_uint16_ab(pu16)
val_16_arr *pu16;
uint16_t mb_get_uint16_ab(val_16_arr *pu16)
{
return mb_get_uint16_generic(0, 1, pu16);
}
uint16_t mb_set_uint16_ab(pu16, u16)
val_16_arr *pu16;
uint16_t u16;
uint16_t mb_set_uint16_ab(val_16_arr *pu16, uint16_t u16)
{
return mb_set_uint16_generic(0, 1, pu16, u16);
}
int16_t mb_get_int16_ba(pi16)
val_16_arr *pi16;
int16_t mb_get_int16_ba(val_16_arr *pi16)
{
return mb_get_int16_generic(1, 0, pi16);
}
uint16_t mb_set_int16_ba(pi16, i16)
val_16_arr *pi16;
int16_t i16;
uint16_t mb_set_int16_ba(val_16_arr *pi16, int16_t i16)
{
return mb_set_int16_generic(1, 0, pi16, i16);
}
uint16_t mb_get_uint16_ba(pu16)
val_16_arr *pu16;
uint16_t mb_get_uint16_ba(val_16_arr *pu16)
{
return mb_get_int16_generic(1, 0, pu16);
}
uint16_t mb_set_uint16_ba(pu16, u16)
val_16_arr *pu16;
uint16_t u16;
uint16_t mb_set_uint16_ba(val_16_arr *pu16, uint16_t u16)
{
return mb_set_int16_generic(1, 0, pu16, u16);
}
int32_t mb_get_int32_abcd(pi32)
val_32_arr *pi32;
int32_t mb_get_int32_abcd(val_32_arr *pi32)
{
return mb_get_int32_generic(0, 1, 2, 3, pi32);
}
uint32_t mb_set_int32_abcd(pi32, i32)
val_32_arr *pi32;
int32_t i32;
uint32_t mb_set_int32_abcd(val_32_arr *pi32, int32_t i32)
{
return mb_set_int32_generic(0, 1, 2, 3, pi32, i32);
}
uint32_t mb_get_uint32_abcd(pu32)
val_32_arr *pu32;
uint32_t mb_get_uint32_abcd(val_32_arr *pu32)
{
return mb_get_uint32_generic(0, 1, 2, 3, pu32);
}
uint32_t mb_set_uint32_abcd(pu32, u32)
val_32_arr *pu32;
uint32_t u32;
uint32_t mb_set_uint32_abcd(val_32_arr *pu32, uint32_t u32)
{
return mb_set_uint32_generic(0, 1, 2, 3, pu32, u32);
}
int32_t mb_get_int32_badc(pi32)
val_32_arr *pi32;
int32_t mb_get_int32_badc(val_32_arr *pi32)
{
return mb_get_int32_generic(1, 0, 3, 2, pi32);
}
uint32_t mb_set_int32_badc(pi32, i32)
val_32_arr *pi32;
int32_t i32;
uint32_t mb_set_int32_badc(val_32_arr *pi32, int32_t i32)
{
return mb_set_int32_generic(1, 0, 3, 2, pi32, i32);
}
uint32_t mb_get_uint32_badc(pu32)
val_32_arr *pu32;
uint32_t mb_get_uint32_badc(val_32_arr *pu32)
{
return mb_get_uint32_generic(1, 0, 3, 2, pu32);
}
uint32_t mb_set_uint32_badc(pu32, u32)
val_32_arr *pu32;
uint32_t u32;
uint32_t mb_set_uint32_badc(val_32_arr *pu32, uint32_t u32)
{
return mb_set_uint32_generic(1, 0, 3, 2, pu32, u32);
}
int32_t mb_get_int32_cdab(pi32)
val_32_arr *pi32;
int32_t mb_get_int32_cdab(val_32_arr *pi32)
{
return mb_get_int32_generic(2, 3, 0, 1, pi32);
}
uint32_t mb_set_int32_cdab(pi32, i32)
val_32_arr *pi32;
int32_t i32;
uint32_t mb_set_int32_cdab(val_32_arr *pi32, int32_t i32)
{
return mb_set_int32_generic(2, 3, 0, 1, pi32, i32);
}
uint32_t mb_get_uint32_cdab(pu32)
val_32_arr *pu32;
uint32_t mb_get_uint32_cdab(val_32_arr *pu32)
{
return mb_get_uint32_generic(2, 3, 0, 1, pu32);
}
uint32_t mb_set_uint32_cdab(pu32, u32)
val_32_arr *pu32;
uint32_t u32;
uint32_t mb_set_uint32_cdab(val_32_arr *pu32, uint32_t u32)
{
return mb_set_uint32_generic(2, 3, 0, 1, pu32, u32);
}
int32_t mb_get_int32_dcba(pi32)
val_32_arr *pi32;
int32_t mb_get_int32_dcba(val_32_arr *pi32)
{
return mb_get_int32_generic(3, 2, 1, 0, pi32);
}
uint32_t mb_set_int32_dcba(pi32, i32)
val_32_arr *pi32;
int32_t i32;
uint32_t mb_set_int32_dcba(val_32_arr *pi32, int32_t i32)
{
return mb_set_int32_generic(3, 2, 1, 0, pi32, i32);
}
uint32_t mb_get_uint32_dcba(pu32)
val_32_arr *pu32;
uint32_t mb_get_uint32_dcba(val_32_arr *pu32)
{
return mb_get_uint32_generic(3, 2, 1, 0, pu32);
}
uint32_t mb_set_uint32_dcba(pu32, u32)
val_32_arr *pu32;
uint32_t u32;
uint32_t mb_set_uint32_dcba(val_32_arr *pu32, uint32_t u32)
{
return mb_set_uint32_generic(3, 2, 1, 0, pu32, u32);
}
float mb_get_float_abcd(pf)
val_32_arr *pf;
float mb_get_float_abcd(val_32_arr *pf)
{
return mb_get_float_generic(0, 1, 2, 3, pf);
}
uint32_t mb_set_float_abcd(pf, f)
val_32_arr *pf;
float f;
uint32_t mb_set_float_abcd(val_32_arr *pf, float f)
{
return mb_set_float_generic(0, 1, 2, 3, pf, f);
}
float mb_get_float_badc(pf)
val_32_arr *pf;
float mb_get_float_badc(val_32_arr *pf)
{
return mb_get_float_generic(1, 0, 3, 2, pf);
}
uint32_t mb_set_float_badc(pf, f)
val_32_arr *pf;
float f;
uint32_t mb_set_float_badc(val_32_arr *pf, float f)
{
return mb_set_float_generic(1, 0, 3, 2, pf, f);
}
float mb_get_float_cdab(pf)
val_32_arr *pf;
float mb_get_float_cdab(val_32_arr *pf)
{
return mb_get_float_generic(2, 3, 0, 1, pf);
}
uint32_t mb_set_float_cdab(pf, f)
val_32_arr *pf;
float f;
uint32_t mb_set_float_cdab(val_32_arr *pf, float f)
{
return mb_set_float_generic(2, 3, 0, 1, pf, f);
}
float mb_get_float_dcba(pf)
val_32_arr *pf;
float mb_get_float_dcba(val_32_arr *pf)
{
return mb_get_float_generic(3, 2, 1, 0, pf);
}
uint32_t mb_set_float_dcba(pf, f)
val_32_arr *pf;
float f;
uint32_t mb_set_float_dcba(val_32_arr *pf, float f)
{
return mb_set_float_generic(3, 2, 1, 0, pf, f);
}
double mb_get_double_abcdefgh(pd)
val_64_arr *pd;
double mb_get_double_abcdefgh(val_64_arr *pd)
{
return mb_get_double_generic(0, 1, 2, 3, 4, 5, 6, 7, pd);
}
uint64_t mb_set_double_abcdefgh(pd, d)
val_64_arr *pd;
double d;
uint64_t mb_set_double_abcdefgh(val_64_arr *pd, double d)
{
return mb_set_double_generic(0, 1, 2, 3, 4, 5, 6, 7, pd, d);
}
double mb_get_double_hgfedcba(pd)
val_64_arr *pd;
double mb_get_double_hgfedcba(val_64_arr *pd)
{
return mb_get_double_generic(7, 6, 5, 4, 3, 2, 1, 0, pd);
}
uint64_t mb_set_double_hgfedcba(pd, d)
val_64_arr *pd;
double d;
uint64_t mb_set_double_hgfedcba(val_64_arr *pd, double d)
{
return mb_set_double_generic(7, 6, 5, 4, 3, 2, 1, 0, pd, d);
}
double mb_get_double_ghefcdab(pd)
val_64_arr *pd;
double mb_get_double_ghefcdab(val_64_arr *pd)
{
return mb_get_double_generic(6, 7, 4, 5, 2, 3, 0, 1, pd);
}
uint64_t mb_set_double_ghefcdab(pd, d)
val_64_arr *pd;
double d;
uint64_t mb_set_double_ghefcdab(val_64_arr *pd, double d)
{
return mb_set_double_generic(6, 7, 4, 5, 2, 3, 0, 1, pd, d);
}
double mb_get_double_badcfehg(pd)
val_64_arr *pd;
double mb_get_double_badcfehg(val_64_arr *pd)
{
return mb_get_double_generic(1, 0, 3, 2, 5, 4, 7, 6, pd);
}
uint64_t mb_set_double_badcfehg(pd, d)
val_64_arr *pd;
double d;
uint64_t mb_set_double_badcfehg(val_64_arr *pd, double d)
{
return mb_set_double_generic(1, 0, 3, 2, 5, 4, 7, 6, pd, d);
}
int64_t mb_get_int64_abcdefgh(pi64)
val_64_arr *pi64;
int64_t mb_get_int64_abcdefgh(val_64_arr *pi64)
{
return mb_get_int64_generic(0, 1, 2, 3, 4, 5, 6, 7, pi64);
}
uint64_t mb_set_int64_abcdefgh(pi, i)
val_64_arr *pi;
int64_t i;
uint64_t mb_set_int64_abcdefgh(val_64_arr *pi, int64_t i)
{
return mb_set_int64_generic(0, 1, 2, 3, 4, 5, 6, 7, pi, i);
}
int64_t mb_get_int64_hgfedcba(pi64)
val_64_arr *pi64;
int64_t mb_get_int64_hgfedcba(val_64_arr *pi64)
{
return mb_get_int64_generic(7, 6, 5, 4, 3, 2, 1, 0, pi64);
}
uint64_t mb_set_int64_hgfedcba(pi, i)
val_64_arr *pi;
int64_t i;
uint64_t mb_set_int64_hgfedcba(val_64_arr *pi, int64_t i)
{
return mb_set_int64_generic(7, 6, 5, 4, 3, 2, 1, 0, pi, i);
}
int64_t mb_get_int64_ghefcdab(pi64)
val_64_arr *pi64;
int64_t mb_get_int64_ghefcdab(val_64_arr *pi64)
{
return mb_get_int64_generic(6, 7, 4, 5, 2, 3, 0, 1, pi64);
}
uint64_t mb_set_int64_ghefcdab(pi, i)
val_64_arr *pi;
int64_t i;
uint64_t mb_set_int64_ghefcdab(val_64_arr *pi, int64_t i)
{
return mb_set_int64_generic(6, 7, 4, 5, 2, 3, 0, 1, pi, i);
}
int64_t mb_get_int64_badcfehg(pi64)
val_64_arr *pi64;
int64_t mb_get_int64_badcfehg(val_64_arr *pi64)
{
return mb_get_int64_generic(1, 0, 3, 2, 5, 4, 7, 6, pi64);
}
uint64_t mb_set_int64_badcfehg(pi, i)
val_64_arr *pi;
int64_t i;
uint64_t mb_set_int64_badcfehg(val_64_arr *pi, int64_t i)
{
return mb_set_int64_generic(1, 0, 3, 2, 5, 4, 7, 6, pi, i);
}
uint64_t mb_get_uint64_abcdefgh(pui)
val_64_arr *pui;
uint64_t mb_get_uint64_abcdefgh(val_64_arr *pui)
{
return mb_get_uint64_generic(0, 1, 2, 3, 4, 5, 6, 7, pui);
}
uint64_t mb_set_uint64_abcdefgh(pui, ui)
val_64_arr *pui;
uint64_t ui;
uint64_t mb_set_uint64_abcdefgh(val_64_arr *pui, uint64_t ui)
{
return mb_set_uint64_generic(0, 1, 2, 3, 4, 5, 6, 7, pui, ui);
}
uint64_t mb_get_uint64_hgfedcba(pui)
val_64_arr *pui;
uint64_t mb_get_uint64_hgfedcba(val_64_arr *pui)
{
return mb_get_uint64_generic(7, 6, 5, 4, 3, 2, 1, 0, pui);
}
uint64_t mb_set_uint64_hgfedcba(pui, ui)
val_64_arr *pui;
uint64_t ui;
uint64_t mb_set_uint64_hgfedcba(val_64_arr *pui, uint64_t ui)
{
return mb_set_uint64_generic(7, 6, 5, 4, 3, 2, 1, 0, pui, ui);
}
uint64_t mb_get_uint64_ghefcdab(pui)
val_64_arr *pui;
uint64_t mb_get_uint64_ghefcdab(val_64_arr *pui)
{
return mb_get_uint64_generic(6, 7, 4, 5, 2, 3, 0, 1, pui);
}
uint64_t mb_set_uint64_ghefcdab(pui, ui)
val_64_arr *pui;
uint64_t ui;
uint64_t mb_set_uint64_ghefcdab(val_64_arr *pui, uint64_t ui)
{
return mb_set_uint64_generic(6, 7, 4, 5, 2, 3, 0, 1, pui, ui);
}
uint64_t mb_get_uint64_badcfehg(pui)
val_64_arr *pui;
uint64_t mb_get_uint64_badcfehg(val_64_arr *pui)
{
return mb_get_int64_generic(1, 0, 3, 2, 5, 4, 7, 6, pui);
}
uint64_t mb_set_uint64_badcfehg(pui, ui)
val_64_arr *pui;
uint64_t ui;
uint64_t mb_set_uint64_badcfehg(val_64_arr *pui, uint64_t ui)
{
return mb_set_uint64_generic(1, 0, 3, 2, 5, 4, 7, 6, pui, ui);
}

View File

@@ -184,81 +184,71 @@ static esp_err_t mbc_serial_master_send_request(void *ctx, mb_param_request_t *r
#if MB_FUNC_READ_COILS_ENABLED
case MB_FUNC_READ_COILS:
mb_error = mbm_rq_read_coils(mbm_controller_iface->mb_base, (uint8_t)mb_slave_addr, (uint16_t)mb_offset,
(uint16_t)mb_size,
pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
mb_error = mbm_rq_read_coils(mbm_controller_iface->mb_base, mb_slave_addr, mb_offset,
mb_size, pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
break;
#endif
#if MB_FUNC_WRITE_COIL_ENABLED
case MB_FUNC_WRITE_SINGLE_COIL:
mb_error = mbm_rq_write_coil(mbm_controller_iface->mb_base, (uint8_t)mb_slave_addr, (uint16_t)mb_offset,
*(uint16_t *)data_ptr,
pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
mb_error = mbm_rq_write_coil(mbm_controller_iface->mb_base, mb_slave_addr, mb_offset,
*(uint16_t *)data_ptr, pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
break;
#endif
#if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED
case MB_FUNC_WRITE_MULTIPLE_COILS:
mb_error = mbm_rq_write_multi_coils(mbm_controller_iface->mb_base, (uint8_t)mb_slave_addr, (uint16_t)mb_offset,
(uint16_t)mb_size, (uint8_t *)data_ptr,
pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
mb_error = mbm_rq_write_multi_coils(mbm_controller_iface->mb_base, mb_slave_addr, mb_offset,
mb_size, (uint8_t *)data_ptr, pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
break;
#endif
#if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED
case MB_FUNC_READ_DISCRETE_INPUTS:
mb_error = mbm_rq_read_discrete_inputs(mbm_controller_iface->mb_base, (uint8_t)mb_slave_addr, (uint16_t)mb_offset,
(uint16_t)mb_size,
pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
mb_error = mbm_rq_read_discrete_inputs(mbm_controller_iface->mb_base, mb_slave_addr, mb_offset,
mb_size, pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
break;
#endif
#if MB_FUNC_READ_HOLDING_ENABLED
case MB_FUNC_READ_HOLDING_REGISTER:
mb_error = mbm_rq_read_holding_reg(mbm_controller_iface->mb_base, (uint8_t)mb_slave_addr, (uint16_t)mb_offset,
(uint16_t)mb_size,
pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
mb_error = mbm_rq_read_holding_reg(mbm_controller_iface->mb_base, mb_slave_addr, mb_offset,
mb_size, pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
break;
#endif
#if MB_FUNC_WRITE_HOLDING_ENABLED
case MB_FUNC_WRITE_REGISTER:
mb_error = mbm_rq_write_holding_reg(mbm_controller_iface->mb_base, (uint8_t)mb_slave_addr, (uint16_t)mb_offset,
*(uint16_t *)data_ptr,
pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
mb_error = mbm_rq_write_holding_reg(mbm_controller_iface->mb_base, mb_slave_addr, mb_offset,
*(uint16_t *)data_ptr, pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
break;
#endif
#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED
case MB_FUNC_WRITE_MULTIPLE_REGISTERS:
mb_error = mbm_rq_write_multi_holding_reg(mbm_controller_iface->mb_base, (uint8_t)mb_slave_addr,
(uint16_t)mb_offset, (uint16_t)mb_size,
(uint16_t *)data_ptr,
pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
mb_error = mbm_rq_write_multi_holding_reg(mbm_controller_iface->mb_base, mb_slave_addr,
mb_offset, mb_size, (uint16_t *)data_ptr, pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
break;
#endif
#if MB_FUNC_READWRITE_HOLDING_ENABLED
case MB_FUNC_READWRITE_MULTIPLE_REGISTERS:
mb_error = mbm_rq_rw_multi_holding_reg(mbm_controller_iface->mb_base, (uint8_t)mb_slave_addr, (uint16_t)mb_offset,
(uint16_t)mb_size, (uint16_t *)data_ptr,
(uint16_t)mb_offset, (uint16_t)mb_size,
pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
mb_error = mbm_rq_rw_multi_holding_reg(mbm_controller_iface->mb_base, mb_slave_addr, mb_offset,
mb_size, (uint16_t *)data_ptr,
mb_offset, mb_size, pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
break;
#endif
#if MB_FUNC_READ_INPUT_ENABLED
case MB_FUNC_READ_INPUT_REGISTER:
mb_error = mbm_rq_read_inp_reg(mbm_controller_iface->mb_base, (uint8_t)mb_slave_addr, (uint16_t)mb_offset,
(uint16_t)mb_size,
pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
mb_error = mbm_rq_read_inp_reg(mbm_controller_iface->mb_base, mb_slave_addr, mb_offset,
mb_size, pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
break;
#endif
default:
mb_fn_handler_fp phandler = NULL;
mb_fn_handler_fp handler = NULL;
// check registered function handler
mb_error = mbm_get_handler(mbm_controller_iface->mb_base, mb_command, &phandler);
mb_error = mbm_get_handler(mbm_controller_iface->mb_base, mb_command, &handler);
if (mb_error == MB_ENOERR) {
// send the request for custom command
mb_error = mbm_rq_custom(mbm_controller_iface->mb_base, mb_slave_addr, mb_command,
@@ -339,21 +329,21 @@ static esp_err_t mbc_serial_master_get_parameter(void *ctx, uint16_t cid, uint8_
esp_err_t error = ESP_ERR_INVALID_RESPONSE;
mb_param_request_t request ;
mb_parameter_descriptor_t reg_info = { 0 };
uint8_t *pdata = NULL;
uint8_t *data_ptr = NULL;
error = mbc_serial_master_set_request(ctx, cid, MB_PARAM_READ, &request, &reg_info);
if ((error == ESP_OK) && (cid == reg_info.cid) && (request.slave_addr != MB_SLAVE_ADDR_PLACEHOLDER)) {
MB_MASTER_ASSERT(xPortGetFreeHeapSize() > (reg_info.mb_size << 1));
// alloc buffer to store parameter data
pdata = calloc(1, (reg_info.mb_size << 1));
if (!pdata) {
data_ptr = calloc(1, (reg_info.mb_size << 1));
if (!data_ptr) {
return ESP_ERR_INVALID_STATE;
}
error = mbc_serial_master_send_request(ctx, &request, pdata);
error = mbc_serial_master_send_request(ctx, &request, data_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) {
error = mbc_master_set_param_data((void *)value, (void *)pdata,
error = mbc_master_set_param_data((void *)value, (void *)data_ptr,
reg_info.param_type, reg_info.param_size);
if (error != ESP_OK) {
ESP_LOGE(TAG, "fail to set parameter data.");
@@ -367,7 +357,7 @@ static esp_err_t mbc_serial_master_get_parameter(void *ctx, uint16_t cid, uint8_
ESP_LOGD(TAG, "%s: Bad response to get cid(%u) = %s",
__FUNCTION__, (unsigned)reg_info.cid, (char *)esp_err_to_name(error));
}
free(pdata);
free(data_ptr);
// Set the type of parameter found in the table
*type = reg_info.param_type;
} else {
@@ -386,7 +376,7 @@ static esp_err_t mbc_serial_master_get_parameter_with(void *ctx, uint16_t cid, u
esp_err_t error = ESP_ERR_INVALID_RESPONSE;
mb_param_request_t request;
mb_parameter_descriptor_t reg_info = {0};
uint8_t *pdata = NULL;
uint8_t *data_ptr = NULL;
error = mbc_serial_master_set_request(ctx, cid, MB_PARAM_READ, &request, &reg_info);
if ((error == ESP_OK) && (cid == reg_info.cid))
@@ -399,17 +389,17 @@ static esp_err_t mbc_serial_master_get_parameter_with(void *ctx, uint16_t cid, u
request.slave_addr = uid; // override the UID
MB_MASTER_ASSERT(xPortGetFreeHeapSize() > (reg_info.mb_size << 1));
// alloc buffer to store parameter data
pdata = calloc(1, (reg_info.mb_size << 1));
if (!pdata) {
data_ptr = calloc(1, (reg_info.mb_size << 1));
if (!data_ptr) {
return ESP_ERR_INVALID_STATE;
}
// Send request to read characteristic data
error = mbc_serial_master_send_request(ctx, &request, pdata);
error = mbc_serial_master_send_request(ctx, &request, data_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_ptr) {
error = mbc_master_set_param_data((void *)value_ptr, (void *)pdata,
error = mbc_master_set_param_data((void *)value_ptr, (void *)data_ptr,
reg_info.param_type, reg_info.param_size);
if (error != ESP_OK) {
ESP_LOGE(TAG, "fail to set parameter data.");
@@ -425,7 +415,7 @@ static esp_err_t mbc_serial_master_get_parameter_with(void *ctx, uint16_t cid, u
ESP_LOGD(TAG, "%s: Bad response to get cid(%u) = %s",
__FUNCTION__, (unsigned)reg_info.cid, (char *)esp_err_to_name(error));
}
free(pdata);
free(data_ptr);
// Set the type of parameter found in the table
*type = reg_info.param_type;
}
@@ -446,25 +436,25 @@ static esp_err_t mbc_serial_master_set_parameter(void *ctx, uint16_t cid, uint8_
esp_err_t error = ESP_ERR_INVALID_RESPONSE;
mb_param_request_t request ;
mb_parameter_descriptor_t reg_info = { 0 };
uint8_t *pdata = NULL;
uint8_t *data_ptr = NULL;
error = mbc_serial_master_set_request(ctx, cid, MB_PARAM_WRITE, &request, &reg_info);
if ((error == ESP_OK) && (cid == reg_info.cid) && (request.slave_addr != MB_SLAVE_ADDR_PLACEHOLDER)) {
MB_MASTER_ASSERT(xPortGetFreeHeapSize() > (reg_info.mb_size << 1));
pdata = calloc(1, (reg_info.mb_size << 1)); // alloc parameter buffer
if (!pdata) {
data_ptr = calloc(1, (reg_info.mb_size << 1)); // alloc parameter buffer
if (!data_ptr) {
return ESP_ERR_INVALID_STATE;
}
// Transfer value of characteristic into parameter buffer
error = mbc_master_set_param_data((void *)pdata, (void *)value,
error = mbc_master_set_param_data((void *)data_ptr, (void *)value,
reg_info.param_type, reg_info.param_size);
if (error != ESP_OK) {
ESP_LOGE(TAG, "fail to set parameter data.");
free(pdata);
free(data_ptr);
return ESP_ERR_INVALID_STATE;
}
// Send request to write characteristic data
error = mbc_serial_master_send_request(ctx, &request, pdata);
error = mbc_serial_master_send_request(ctx, &request, data_ptr);
if (error == ESP_OK) {
ESP_LOGD(TAG, "%s: Good response for set cid(%u) = %s",
__FUNCTION__, (unsigned)reg_info.cid, (char *)esp_err_to_name(error));
@@ -472,7 +462,7 @@ static esp_err_t mbc_serial_master_set_parameter(void *ctx, uint16_t cid, uint8_
ESP_LOGD(TAG, "%s: Bad response to set cid(%u) = %s",
__FUNCTION__, (unsigned)reg_info.cid, (char *)esp_err_to_name(error));
}
free(pdata);
free(data_ptr);
// Set the type of parameter found in the table
*type = reg_info.param_type;
} else {
@@ -492,7 +482,7 @@ static esp_err_t mbc_serial_master_set_parameter_with(void *ctx, uint16_t cid, u
esp_err_t error = ESP_ERR_INVALID_RESPONSE;
mb_param_request_t request;
mb_parameter_descriptor_t reg_info = {0};
uint8_t *pdata = NULL;
uint8_t *data_ptr = NULL;
error = mbc_serial_master_set_request(ctx, cid, MB_PARAM_WRITE, &request, &reg_info);
if ((error == ESP_OK) && (cid == reg_info.cid))
{
@@ -503,16 +493,16 @@ static esp_err_t mbc_serial_master_set_parameter_with(void *ctx, uint16_t cid, u
}
request.slave_addr = uid; // override the UID
MB_MASTER_ASSERT(xPortGetFreeHeapSize() > (reg_info.mb_size << 1));
pdata = calloc(1, (reg_info.mb_size << 1)); // alloc parameter buffer
if (!pdata) {
data_ptr = calloc(1, (reg_info.mb_size << 1)); // alloc parameter buffer
if (!data_ptr) {
return ESP_ERR_INVALID_STATE;
}
// Transfer value of characteristic into parameter buffer
error = mbc_master_set_param_data((void *)pdata, (void *)value_ptr,
error = mbc_master_set_param_data((void *)data_ptr, (void *)value_ptr,
reg_info.param_type, reg_info.param_size);
if (error != ESP_OK) {
ESP_LOGE(TAG, "fail to set parameter data.");
free(pdata);
free(data_ptr);
return ESP_ERR_INVALID_STATE;
}
// Send request to write characteristic data
@@ -527,7 +517,7 @@ static esp_err_t mbc_serial_master_set_parameter_with(void *ctx, uint16_t cid, u
ESP_LOGD(TAG, "%s: Bad response to set cid(%u) = %s",
__FUNCTION__, (unsigned)reg_info.cid, (char *)esp_err_to_name(error));
}
free(pdata);
free(data_ptr);
// Set the type of parameter found in the table
*type = reg_info.param_type;
}
@@ -574,6 +564,7 @@ static esp_err_t mbc_serial_master_controller_create(void **ctx)
// Initialize interface properties
mb_master_options_t *mbm_opts = &mbm_controller_iface->opts;
mbm_opts->task_handle = NULL;
// Initialization of active context of the modbus controller
mbm_opts->event_group_handle = xEventGroupCreate();
@@ -648,12 +639,12 @@ esp_err_t mbc_serial_master_create(mb_communication_info_t *config, void **ctx)
// Initialize Modbus stack using mbcontroller parameters
mb_err_enum_t err = MB_EILLSTATE;
void *pinst = (void *)mbm_controller_iface;
void *inst = (void *)mbm_controller_iface;
if (pcomm_info->mode == MB_RTU)
{
#if ( CONFIG_FMB_COMM_MODE_RTU_EN )
err = mbm_rtu_create(pcomm_info, &pinst);
err = mbm_rtu_create(pcomm_info, &inst);
#else
ESP_LOGE(TAG, "RTU mode is not enabled in the configuration.");
ret = ESP_ERR_NOT_SUPPORTED;
@@ -663,7 +654,7 @@ esp_err_t mbc_serial_master_create(mb_communication_info_t *config, void **ctx)
else if (pcomm_info->mode == MB_ASCII)
{
#if ( CONFIG_FMB_COMM_MODE_ASCII_EN )
err = mbm_ascii_create(pcomm_info, &pinst);
err = mbm_ascii_create(pcomm_info, &inst);
#else
ESP_LOGE(TAG, "ASCII mode is not enabled in the configuration.");
ret = ESP_ERR_NOT_SUPPORTED;
@@ -672,7 +663,7 @@ esp_err_t mbc_serial_master_create(mb_communication_info_t *config, void **ctx)
}
MB_GOTO_ON_FALSE((err == MB_ENOERR), ESP_ERR_INVALID_STATE, error, TAG,
"mb object create returns (0x%x).", (int)err);
mbm_controller_iface->mb_base = (mb_base_t *)pinst;
mbm_controller_iface->mb_base = (mb_base_t *)inst;
const mb_rw_callbacks_t rw_cbs = {
.reg_input_cb = mbc_reg_input_master_cb,

View File

@@ -181,6 +181,7 @@ static esp_err_t mbc_serial_slave_controller_create(void **ctx)
mb_slave_options_t *mbs_opts = &mbs_controller_iface->opts;
mbs_opts->port_type = MB_PORT_SERIAL_SLAVE; // set interface port type
mbs_opts->task_handle = NULL;
// Initialization of active context of the Modbus controller
BaseType_t status = 0;
@@ -250,13 +251,13 @@ esp_err_t mbc_serial_slave_create(mb_communication_info_t *config, void **ctx)
mbs_opts->port_type = MB_PORT_SERIAL_SLAVE;
mbs_opts->comm_opts = *config;
mb_err_enum_t err = MB_ENOERR;
void *pinst = (void *)mbs_controller_iface;
void *inst = (void *)mbs_controller_iface;
// Initialize Modbus stack using mbcontroller parameters
if (pcomm_info->mode == MB_RTU)
{
#if (CONFIG_FMB_COMM_MODE_RTU_EN)
err = mbs_rtu_create(pcomm_info, &pinst);
err = mbs_rtu_create(pcomm_info, &inst);
#else
ESP_LOGE(TAG, "RTU mode is not enabled in the configuration.");
ret = ESP_ERR_NOT_SUPPORTED;
@@ -266,7 +267,7 @@ esp_err_t mbc_serial_slave_create(mb_communication_info_t *config, void **ctx)
else if (pcomm_info->mode == MB_ASCII)
{
#if (CONFIG_FMB_COMM_MODE_ASCII_EN)
err = mbs_ascii_create(pcomm_info, &pinst);
err = mbs_ascii_create(pcomm_info, &inst);
#else
ESP_LOGE(TAG, "ASCII mode is not enabled in the configuration.");
ret = ESP_ERR_NOT_SUPPORTED;
@@ -275,7 +276,7 @@ esp_err_t mbc_serial_slave_create(mb_communication_info_t *config, void **ctx)
}
MB_GOTO_ON_FALSE((err == MB_ENOERR), ESP_ERR_INVALID_STATE, error, TAG,
"mbs create returns (0x%x).", (int)err);
mbs_controller_iface->mb_base = (mb_base_t *)pinst;
mbs_controller_iface->mb_base = (mb_base_t *)inst;
// Configure Modbus read/write callbacks for the base modbus object
const mb_rw_callbacks_t rw_cbs = {

View File

@@ -36,8 +36,6 @@ static const char *TAG = "mbc_tcp.master";
#define MB_TCP_CONNECTION_TOUT pdMS_TO_TICKS(CONFIG_FMB_TCP_CONNECTION_TOUT_SEC * 1000)
//typedef enum _mb_sock_state mb_sock_state_t;
// Modbus event processing task
static void modbus_tcp_master_task(void *param)
{
@@ -135,7 +133,7 @@ static esp_err_t mbc_tcp_master_set_descriptor(void *ctx, const mb_parameter_des
MB_RETURN_ON_FALSE((comm_ip_table), ESP_ERR_INVALID_ARG, TAG, "mb ip table address is incorrect.");
const mb_parameter_descriptor_t *reg_ptr = descriptor;
mb_uid_info_t *paddr_info = NULL;
mb_uid_info_t *addr_info = NULL;
// Go through all items in the table to check all Modbus registers
for (int idx = 0; idx < (num_elements); idx++, reg_ptr++) {
@@ -149,8 +147,8 @@ static esp_err_t mbc_tcp_master_set_descriptor(void *ctx, const mb_parameter_des
}
// Is the slave with the UID already in the list?
paddr_info = mbm_port_tcp_get_slave_info(mbm_controller_iface->mb_base->port_obj, reg_ptr->mb_slave_addr, MB_SOCK_STATE_OPENED);
MB_RETURN_ON_FALSE((paddr_info), ESP_ERR_INVALID_ARG, TAG,
addr_info = mbm_port_tcp_get_slave_info(mbm_controller_iface->mb_base->port_obj, reg_ptr->mb_slave_addr, MB_SOCK_STATE_OPENED);
MB_RETURN_ON_FALSE((addr_info), ESP_ERR_INVALID_ARG, TAG,
"mb missing IP address configuration for cid #%u, uid=%d.", (unsigned)reg_ptr->cid, (int)reg_ptr->mb_slave_addr);
ESP_LOGI(TAG, "mb found config for cid #%d, uid=%d.", (int)reg_ptr->cid, (int)reg_ptr->mb_slave_addr);
}
@@ -183,15 +181,14 @@ static esp_err_t mbc_tcp_master_send_request(void *ctx, mb_param_request_t *requ
switch(mb_command) {
#if MB_FUNC_READ_COILS_ENABLED
case MB_FUNC_READ_COILS:
mb_error = mbm_rq_read_coils(mbm_controller_iface->mb_base, (uint8_t)mb_slave_addr, (uint16_t)mb_offset,
(uint16_t)mb_size ,
pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
mb_error = mbm_rq_read_coils(mbm_controller_iface->mb_base, mb_slave_addr,
mb_offset, mb_size , pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
break;
#endif
#if MB_FUNC_WRITE_COIL_ENABLED
case MB_FUNC_WRITE_SINGLE_COIL:
mb_error = mbm_rq_write_coil(mbm_controller_iface->mb_base, (uint8_t)mb_slave_addr, (uint16_t)mb_offset,
mb_error = mbm_rq_write_coil(mbm_controller_iface->mb_base, mb_slave_addr, mb_offset,
*(uint16_t *)data_ptr,
pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
break;
@@ -199,31 +196,29 @@ static esp_err_t mbc_tcp_master_send_request(void *ctx, mb_param_request_t *requ
#if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED
case MB_FUNC_WRITE_MULTIPLE_COILS:
mb_error = mbm_rq_write_multi_coils(mbm_controller_iface->mb_base, (uint8_t)mb_slave_addr, (uint16_t)mb_offset,
(uint16_t)mb_size, (uint8_t *)data_ptr,
mb_error = mbm_rq_write_multi_coils(mbm_controller_iface->mb_base, mb_slave_addr, mb_offset,
mb_size, (uint8_t *)data_ptr,
pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
break;
#endif
#if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED
case MB_FUNC_READ_DISCRETE_INPUTS:
mb_error = mbm_rq_read_discrete_inputs(mbm_controller_iface->mb_base, (uint8_t)mb_slave_addr, (uint16_t)mb_offset,
(uint16_t)mb_size,
pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
mb_error = mbm_rq_read_discrete_inputs(mbm_controller_iface->mb_base, mb_slave_addr, mb_offset,
mb_size, pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
break;
#endif
#if MB_FUNC_READ_HOLDING_ENABLED
case MB_FUNC_READ_HOLDING_REGISTER:
mb_error = mbm_rq_read_holding_reg(mbm_controller_iface->mb_base, (uint8_t)mb_slave_addr, (uint16_t)mb_offset,
(uint16_t)mb_size,
pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
mb_error = mbm_rq_read_holding_reg(mbm_controller_iface->mb_base, mb_slave_addr, mb_offset,
mb_size, pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
break;
#endif
#if MB_FUNC_WRITE_HOLDING_ENABLED
case MB_FUNC_WRITE_REGISTER:
mb_error = mbm_rq_write_holding_reg(mbm_controller_iface->mb_base, (uint8_t)mb_slave_addr, (uint16_t)mb_offset,
mb_error = mbm_rq_write_holding_reg(mbm_controller_iface->mb_base, mb_slave_addr, mb_offset,
*(uint16_t *)data_ptr,
pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
break;
@@ -231,33 +226,28 @@ static esp_err_t mbc_tcp_master_send_request(void *ctx, mb_param_request_t *requ
#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED
case MB_FUNC_WRITE_MULTIPLE_REGISTERS:
mb_error = mbm_rq_write_multi_holding_reg(mbm_controller_iface->mb_base, (uint8_t)mb_slave_addr,
(uint16_t)mb_offset, (uint16_t)mb_size,
(uint16_t *)data_ptr,
pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
mb_error = mbm_rq_write_multi_holding_reg(mbm_controller_iface->mb_base, mb_slave_addr,
mb_offset, mb_size, (uint16_t *)data_ptr, pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
break;
#endif
#if MB_FUNC_READWRITE_HOLDING_ENABLED
case MB_FUNC_READWRITE_MULTIPLE_REGISTERS:
mb_error = mbm_rq_rw_multi_holding_reg(mbm_controller_iface->mb_base, (uint8_t)mb_slave_addr, (uint16_t)mb_offset,
(uint16_t)mb_size, (uint16_t *)data_ptr,
(uint16_t)mb_offset, (uint16_t)mb_size,
pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
mb_error = mbm_rq_rw_multi_holding_reg(mbm_controller_iface->mb_base, mb_slave_addr, mb_offset,
mb_size, (uint16_t *)data_ptr, mb_offset, mb_size, pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
break;
#endif
#if MB_FUNC_READ_INPUT_ENABLED
case MB_FUNC_READ_INPUT_REGISTER:
mb_error = mbm_rq_read_inp_reg(mbm_controller_iface->mb_base, (uint8_t)mb_slave_addr, (uint16_t)mb_offset,
(uint16_t)mb_size,
pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
mb_error = mbm_rq_read_inp_reg(mbm_controller_iface->mb_base, mb_slave_addr, mb_offset,
mb_size, pdMS_TO_TICKS(MB_MAX_RESP_DELAY_MS));
break;
#endif
default:
mb_fn_handler_fp phandler = NULL;
mb_fn_handler_fp handler = NULL;
// check registered function handler
mb_error = mbm_get_handler(mbm_controller_iface->mb_base, mb_command, &phandler);
mb_error = mbm_get_handler(mbm_controller_iface->mb_base, mb_command, &handler);
if (mb_error == MB_ENOERR) {
// send the request for custom command
mb_error = mbm_rq_custom(mbm_controller_iface->mb_base, mb_slave_addr, mb_command,
@@ -334,27 +324,27 @@ static esp_err_t mbc_tcp_master_get_parameter(void *ctx, uint16_t cid, uint8_t *
esp_err_t error = ESP_ERR_INVALID_RESPONSE;
mb_param_request_t request ;
mb_parameter_descriptor_t reg_info = { 0 };
uint8_t *pdata = NULL;
uint8_t *data_ptr = NULL;
error = mbc_tcp_master_set_request(ctx, cid, MB_PARAM_READ, &request, &reg_info);
if ((error == ESP_OK) && (cid == reg_info.cid) && (request.slave_addr != MB_SLAVE_ADDR_PLACEHOLDER)) {
mb_uid_info_t *paddr_info = mbm_port_tcp_get_slave_info(mbm_controller_iface->mb_base->port_obj,
mb_uid_info_t *addr_info = mbm_port_tcp_get_slave_info(mbm_controller_iface->mb_base->port_obj,
request.slave_addr, MB_SOCK_STATE_CONNECTED);
if (!paddr_info) {
if (!addr_info) {
ESP_LOGW(TAG, "Try to send request for cid #%u with uid = %d, node is disconnected.",
(unsigned)reg_info.cid, (int)request.slave_addr);
}
MB_MASTER_ASSERT(xPortGetFreeHeapSize() > (reg_info.mb_size << 1));
// alloc buffer to store parameter data
pdata = calloc(1, (reg_info.mb_size << 1));
if (!pdata) {
data_ptr = calloc(1, (reg_info.mb_size << 1));
if (!data_ptr) {
return ESP_ERR_INVALID_STATE;
}
error = mbc_tcp_master_send_request(ctx, &request, pdata);
error = mbc_tcp_master_send_request(ctx, &request, data_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) {
error = mbc_master_set_param_data((void *)value, (void *)pdata,
error = mbc_master_set_param_data((void *)value, (void *)data_ptr,
reg_info.param_type, reg_info.param_size);
if (error != ESP_OK) {
ESP_LOGE(TAG, "fail to set parameter data.");
@@ -368,7 +358,7 @@ static esp_err_t mbc_tcp_master_get_parameter(void *ctx, uint16_t cid, uint8_t *
ESP_LOGD(TAG, "%s: Bad response to get cid(%u) = %s",
__FUNCTION__, (unsigned)reg_info.cid, (char *)esp_err_to_name(error));
}
free(pdata);
free(data_ptr);
// Set the type of parameter found in the table
*type = reg_info.param_type;
} else {
@@ -388,14 +378,14 @@ static esp_err_t mbc_tcp_master_get_parameter_with(void *ctx, uint16_t cid, uint
esp_err_t error = ESP_ERR_INVALID_RESPONSE;
mb_param_request_t request;
mb_parameter_descriptor_t reg_info = { 0 };
uint8_t *pdata = NULL;
uint8_t *data_ptr = NULL;
error = mbc_tcp_master_set_request(ctx, cid, MB_PARAM_READ, &request, &reg_info);
if ((error == ESP_OK) && (cid == reg_info.cid)) {
// check that the requested uid is connected (call to port iface)
mb_uid_info_t *paddr_info = mbm_port_tcp_get_slave_info(mbm_controller_iface->mb_base->port_obj,
mb_uid_info_t *addr_info = mbm_port_tcp_get_slave_info(mbm_controller_iface->mb_base->port_obj,
uid, MB_SOCK_STATE_CONNECTED);
if (!paddr_info) {
if (!addr_info) {
ESP_LOGW(TAG, "Try to send request for cid #%u with uid = %d, node is disconnected.",
(unsigned)reg_info.cid, (int)request.slave_addr);
}
@@ -406,15 +396,15 @@ static esp_err_t mbc_tcp_master_get_parameter_with(void *ctx, uint16_t cid, uint
request.slave_addr = uid; // override the UID
MB_MASTER_ASSERT(xPortGetFreeHeapSize() > (reg_info.mb_size << 1));
// alloc buffer to store parameter data
pdata = calloc(1, (reg_info.mb_size << 1));
if (!pdata) {
data_ptr = calloc(1, (reg_info.mb_size << 1));
if (!data_ptr) {
return ESP_ERR_INVALID_STATE;
}
error = mbc_tcp_master_send_request(ctx, &request, pdata);
error = mbc_tcp_master_send_request(ctx, &request, data_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) {
error = mbc_master_set_param_data((void *)value, (void *)pdata,
error = mbc_master_set_param_data((void *)value, (void *)data_ptr,
reg_info.param_type, reg_info.param_size);
if (error != ESP_OK) {
ESP_LOGE(TAG, "fail to set parameter data.");
@@ -428,7 +418,7 @@ static esp_err_t mbc_tcp_master_get_parameter_with(void *ctx, uint16_t cid, uint
ESP_LOGD(TAG, "%s: Bad response to get cid(%u) = %s",
__FUNCTION__, (unsigned)reg_info.cid, (char *)esp_err_to_name(error));
}
free(pdata);
free(data_ptr);
// Set the type of parameter found in the table
*type = reg_info.param_type;
} else {
@@ -448,31 +438,31 @@ static esp_err_t mbc_tcp_master_set_parameter(void *ctx, uint16_t cid, uint8_t *
esp_err_t error = ESP_ERR_INVALID_RESPONSE;
mb_param_request_t request ;
mb_parameter_descriptor_t reg_info = { 0 };
uint8_t *pdata = NULL;
uint8_t *data_ptr = NULL;
error = mbc_tcp_master_set_request(ctx, cid, MB_PARAM_WRITE, &request, &reg_info);
if ((error == ESP_OK) && (cid == reg_info.cid) && (request.slave_addr != MB_SLAVE_ADDR_PLACEHOLDER)) {
mb_uid_info_t *paddr_info = mbm_port_tcp_get_slave_info(mbm_controller_iface->mb_base->port_obj,
mb_uid_info_t *addr_info = mbm_port_tcp_get_slave_info(mbm_controller_iface->mb_base->port_obj,
request.slave_addr, MB_SOCK_STATE_CONNECTED);
if (!paddr_info) {
if (!addr_info) {
ESP_LOGW(TAG, "Try to send request for cid #%u with uid = %d, node is disconnected.",
(unsigned)reg_info.cid, (int)request.slave_addr);
}
MB_MASTER_ASSERT(xPortGetFreeHeapSize() > (reg_info.mb_size << 1));
pdata = calloc(1, (reg_info.mb_size << 1)); // alloc parameter buffer
if (!pdata) {
data_ptr = calloc(1, (reg_info.mb_size << 1)); // alloc parameter buffer
if (!data_ptr) {
return ESP_ERR_INVALID_STATE;
}
// Transfer value of characteristic into parameter buffer
error = mbc_master_set_param_data((void *)pdata, (void *)value,
error = mbc_master_set_param_data((void *)data_ptr, (void *)value,
reg_info.param_type, reg_info.param_size);
if (error != ESP_OK) {
ESP_LOGE(TAG, "fail to set parameter data.");
free(pdata);
free(data_ptr);
return ESP_ERR_INVALID_STATE;
}
// Send request to write characteristic data
error = mbc_tcp_master_send_request(ctx, &request, pdata);
error = mbc_tcp_master_send_request(ctx, &request, data_ptr);
if (error == ESP_OK) {
ESP_LOGD(TAG, "%s: Good response for set cid(%u) = %s",
__FUNCTION__, (unsigned)reg_info.cid, (char *)esp_err_to_name(error));
@@ -480,7 +470,7 @@ static esp_err_t mbc_tcp_master_set_parameter(void *ctx, uint16_t cid, uint8_t *
ESP_LOGD(TAG, "%s: Bad response to set cid(%u) = %s",
__FUNCTION__, (unsigned)reg_info.cid, (char *)esp_err_to_name(error));
}
free(pdata);
free(data_ptr);
// Set the type of parameter found in the table
*type = reg_info.param_type;
} else {
@@ -500,14 +490,14 @@ static esp_err_t mbc_tcp_master_set_parameter_with(void *ctx, uint16_t cid, uint
esp_err_t error = ESP_ERR_INVALID_RESPONSE;
mb_param_request_t request ;
mb_parameter_descriptor_t reg_info = { 0 };
uint8_t *pdata = NULL;
uint8_t *data_ptr = NULL;
error = mbc_tcp_master_set_request(ctx, cid, MB_PARAM_WRITE, &request, &reg_info);
if ((error == ESP_OK) && (cid == reg_info.cid)) {
// check that the requested uid is connected (call to port iface)
mb_uid_info_t *paddr_info = mbm_port_tcp_get_slave_info(mbm_controller_iface->mb_base->port_obj,
mb_uid_info_t *addr_info = mbm_port_tcp_get_slave_info(mbm_controller_iface->mb_base->port_obj,
uid, MB_SOCK_STATE_CONNECTED);
if (!paddr_info) {
if (!addr_info) {
ESP_LOGW(TAG, "Try to send request for cid #%u with uid = %d, node is disconnected.",
(unsigned)reg_info.cid, (int)request.slave_addr);
}
@@ -518,20 +508,20 @@ static esp_err_t mbc_tcp_master_set_parameter_with(void *ctx, uint16_t cid, uint
request.slave_addr = uid; // override the UID
MB_MASTER_ASSERT(xPortGetFreeHeapSize() > (reg_info.mb_size << 1));
pdata = calloc(1, (reg_info.mb_size << 1)); // alloc parameter buffer
if (!pdata) {
data_ptr = calloc(1, (reg_info.mb_size << 1)); // alloc parameter buffer
if (!data_ptr) {
return ESP_ERR_INVALID_STATE;
}
// Transfer value of characteristic into parameter buffer
error = mbc_master_set_param_data((void *)pdata, (void *)value,
error = mbc_master_set_param_data((void *)data_ptr, (void *)value,
reg_info.param_type, reg_info.param_size);
if (error != ESP_OK) {
ESP_LOGE(TAG, "fail to set parameter data.");
free(pdata);
free(data_ptr);
return ESP_ERR_INVALID_STATE;
}
// Send request to write characteristic data
error = mbc_tcp_master_send_request(ctx, &request, pdata);
error = mbc_tcp_master_send_request(ctx, &request, data_ptr);
if (error == ESP_OK) {
ESP_LOGD(TAG, "%s: Good response for set cid(%u) = %s",
__FUNCTION__, (unsigned)reg_info.cid, (char *)esp_err_to_name(error));
@@ -539,7 +529,7 @@ static esp_err_t mbc_tcp_master_set_parameter_with(void *ctx, uint16_t cid, uint
ESP_LOGD(TAG, "%s: Bad response to set cid(%u) = %s",
__FUNCTION__, (unsigned)reg_info.cid, (char *)esp_err_to_name(error));
}
free(pdata);
free(data_ptr);
// Set the type of parameter found in the table
*type = reg_info.param_type;
} else {
@@ -596,6 +586,7 @@ esp_err_t mbc_tcp_master_controller_create(void ** ctx)
// Initialize interface properties
mb_master_options_t *mbm_opts = MB_MASTER_GET_OPTS(mbm_controller_iface);
mbm_opts->task_handle = NULL;
// Initialization of active context of the modbus controller
BaseType_t status = 0;
@@ -685,16 +676,16 @@ esp_err_t mbc_tcp_master_create(mb_communication_info_t *config, void **ctx)
}
mb_err_enum_t err = MB_EILLSTATE;
void *pinst = (void *)mbm_controller_iface; // set as descr.parent object
void *inst = (void *)mbm_controller_iface; // set as descr.parent object
// Initialize Modbus stack using mbcontroller parameters
if (tcp_opts.mode == MB_TCP) {
err = mbm_tcp_create(&tcp_opts, &pinst);
err = mbm_tcp_create(&tcp_opts, &inst);
}
MB_GOTO_ON_FALSE((err == MB_ENOERR), ESP_ERR_INVALID_STATE, error, TAG,
"mbm create returns (0x%x).", (int)ret);
mbm_controller_iface->mb_base = (mb_base_t *)pinst;
mbm_controller_iface->mb_base = (mb_base_t *)inst;
const mb_rw_callbacks_t rw_cbs = {
.reg_input_cb = mbc_reg_input_master_cb,
@@ -714,7 +705,7 @@ esp_err_t mbc_tcp_master_create(mb_communication_info_t *config, void **ctx)
return ESP_OK;
error:
if (mbm_controller_iface->mb_base) {
if (mbm_controller_iface && mbm_controller_iface->mb_base) {
mbm_controller_iface->mb_base->delete(mbm_controller_iface->mb_base);
mbm_controller_iface->mb_base = NULL;
}

View File

@@ -153,6 +153,7 @@ esp_err_t mbc_tcp_slave_controller_create(void ** ctx)
mb_slave_options_t *mbs_opts = &mbs_controller_iface->opts;
mbs_opts->port_type = MB_PORT_TCP_SLAVE; // set interface port type
mbs_opts->task_handle = NULL;
// Initialization of active context of the Modbus controller
BaseType_t status = 0;
@@ -243,13 +244,13 @@ esp_err_t mbc_tcp_slave_create(mb_communication_info_t *config, void **ctx)
mbs_opts->comm_opts.tcp_opts = tcp_opts;
mb_err_enum_t err = MB_ENOERR;
void *pinst = (void *)mbs_controller_iface;
void *inst = (void *)mbs_controller_iface;
// Initialize Modbus stack using mbcontroller parameters
err = mbs_tcp_create(&tcp_opts, &pinst);
err = mbs_tcp_create(&tcp_opts, &inst);
MB_GOTO_ON_FALSE((err == MB_ENOERR), ESP_ERR_INVALID_STATE, error, TAG,
"mbscreate returns (0x%x).", (uint16_t)err);
mbs_controller_iface->mb_base = (mb_base_t *)pinst;
mbs_controller_iface->mb_base = (mb_base_t *)inst;
mbs_controller_iface->mb_base->descr.is_master = false;
// Configure Modbus read/write callbacks for the base modbus object
@@ -265,7 +266,7 @@ esp_err_t mbc_tcp_slave_create(mb_communication_info_t *config, void **ctx)
return ESP_OK;
error:
if (mbs_controller_iface->mb_base) {
if (mbs_controller_iface && mbs_controller_iface->mb_base) {
mbs_controller_iface->mb_base->delete(mbs_controller_iface->mb_base);
mbs_controller_iface->mb_base = NULL;
}

View File

@@ -33,7 +33,7 @@ static_assert(
#define MB_ATTR_WEAK __attribute__ ((weak))
typedef enum _mb_comm_mode mb_mode_type_t;
typedef enum mb_comm_mode_enum mb_mode_type_t;
#if (CONFIG_FMB_COMM_MODE_ASCII_EN || CONFIG_FMB_COMM_MODE_RTU_EN)
@@ -55,7 +55,7 @@ typedef struct port_serial_opts_s mb_serial_opts_t;
#endif
typedef enum _addr_type_enum {
typedef enum addr_type_enum {
MB_NOIP = 0,
MB_IPV4 = 1, /*!< TCP IPV4 addressing */
MB_IPV6 = 2 /*!< TCP IPV6 addressing */
@@ -85,7 +85,7 @@ struct port_tcp_opts_s {
typedef struct port_tcp_opts_s mb_tcp_opts_t;
// The common object descriptor struture (common for mb, transport, port objects)
struct _obj_descr {
struct obj_descr_s {
char *parent_name; /*!< Name of the parent (base) object */
char *obj_name; /*!< Name of the object */
void *parent; /*!< Pointer to the parent (base) object */
@@ -93,9 +93,9 @@ struct _obj_descr {
bool is_master; /*!< The current object is master or slave (false) */
};
typedef struct _obj_descr obj_descr_t;
typedef struct obj_descr_s obj_descr_t;
typedef enum _mb_sock_state {
typedef enum mb_sock_state_enum {
MB_SOCK_STATE_UNDEF = 0x0000, /*!< Default init state */
MB_SOCK_STATE_CLOSED, /*!< Node is closed */
MB_SOCK_STATE_READY, /*!< Node is ready for communication */
@@ -106,7 +106,7 @@ typedef enum _mb_sock_state {
MB_SOCK_STATE_ACCEPTED /*!< Slave node accepted the connection */
} mb_sock_state_t;
typedef struct _uid_info {
typedef struct uid_info_s {
uint16_t index; /*!< index of the address info */
int fd; /*!< node global FD for VFS (reserved) */
char *node_name_str; /*!< node name string (host name of node to resolve) */

View File

@@ -43,7 +43,7 @@ extern "C" {
* a low jitter. ASCII is slower and more reliable on slower links (E.g. modems)
* The TCP or UDP mode is used for communication over ethernet.
*/
typedef enum _mb_comm_mode
typedef enum mb_comm_mode_enum
{
MB_RTU, /*!< RTU transmission mode. */
MB_ASCII, /*!< ASCII transmission mode. */
@@ -71,7 +71,7 @@ typedef enum
/*! \ingroup modbus
* \brief Event types used by all function in the protocol stack.
*/
typedef enum _mb_event_enum {
typedef enum mb_event_enum {
EV_TRANS_START = 0x0001, /*!< Start of transaction. */
EV_READY = 0x0002, /*!< Startup finished. */
EV_FRAME_RECEIVED = 0x0004, /*!< Frame received. */
@@ -88,7 +88,7 @@ typedef enum _mb_event_enum {
/*! \ingroup modbus
* \brief Modbus exception types used in the stack.
*/
typedef enum _mb_exception_enum
typedef enum mb_exception_enum
{
MB_EX_NONE = 0x00,
MB_EX_ILLEGAL_FUNCTION = 0x01,
@@ -108,7 +108,7 @@ typedef mb_exception_t (*mb_fn_handler_fp)(void *, uint8_t *frame_ptr, uint16_t
/*! \ingroup modbus
* \brief Error event type
*/
typedef enum _mb_err_event_enum {
typedef enum mb_err_event_enum {
EV_ERROR_INIT, /*!< No error, initial state. */
EV_ERROR_RESPOND_TIMEOUT, /*!< Slave respond timeout. */
EV_ERROR_RECEIVE_DATA, /*!< Receive frame data error. */
@@ -116,11 +116,11 @@ typedef enum _mb_err_event_enum {
EV_ERROR_OK /*!< No error, processing completed. */
} mb_err_event_t;
typedef struct _mb_event_t {
typedef struct mb_event_s {
mb_event_enum_t event; /*!< event itself. */
uint64_t trans_id; /*!< unique transaction id */
uint16_t length; /*!< length of data accociated with the event */
void *pdata; /*!< data accociated with the event */
void *data_ptr; /*!< data accociated with the event */
mb_err_event_t type; /*!< error type accociated with the event */
uint64_t post_ts; /*!< timestamp of event posted */
uint64_t get_ts; /*!< timestamp of event receved */

View File

@@ -10,50 +10,49 @@
#define MB_IS_VALID_FUNC_CODE(fc) ((fc) >= MB_FUNC_CODE_MIN && (fc) <= MB_FUNC_CODE_MAX)
static const char TAG[] __attribute__((unused)) = "MB_FUNC_HANDLING";
mb_err_enum_t mb_set_handler(handler_descriptor_t *pdescriptor, uint8_t func_code, mb_fn_handler_fp phandler)
mb_err_enum_t mb_set_handler(handler_descriptor_t *descriptor, uint8_t func_code, mb_fn_handler_fp handler)
{
MB_RETURN_ON_FALSE((pdescriptor && phandler && pdescriptor->instance), MB_EINVAL, TAG, "invalid arguments.");
MB_RETURN_ON_FALSE((descriptor && handler && descriptor->instance), MB_EINVAL, TAG, "invalid arguments.");
MB_RETURN_ON_FALSE(MB_IS_VALID_FUNC_CODE(func_code), MB_EINVAL, TAG,
"invalid function code (0x%x)", (int)func_code);
mb_command_entry_t *pitem = NULL;
LIST_FOREACH(pitem, &pdescriptor->head, entries) {
if (pitem && pitem->func_code == func_code) {
mb_command_entry_t *item_ptr = NULL;
LIST_FOREACH(item_ptr, &descriptor->head, entries) {
if (item_ptr && item_ptr->func_code == func_code) {
// The handler for the function already exists, rewrite it.
pitem->handler = phandler;
ESP_LOGD(TAG, "Inst: %p, set handler: 0x%x, %p", pdescriptor->instance, pitem->func_code, pitem->handler);
item_ptr->handler = handler;
ESP_LOGD(TAG, "Inst: %p, set handler: 0x%x, %p", descriptor->instance, item_ptr->func_code, item_ptr->handler);
return MB_ENOERR;
}
}
// Insert new handler entry into list
if (pdescriptor->count >= MB_FUNC_HANDLERS_MAX) {
if (descriptor->count >= MB_FUNC_HANDLERS_MAX) {
return MB_ENORES;
} else {
pdescriptor->count += 1;
}
pitem = (mb_command_entry_t *) heap_caps_malloc(sizeof(mb_command_entry_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
descriptor->count += 1;
item_ptr = (mb_command_entry_t *) heap_caps_malloc(sizeof(mb_command_entry_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
MB_RETURN_ON_FALSE(pitem, MB_ENORES, TAG, "mb can not allocate memory for command handler 0x%x.", func_code);
pitem->func_code = func_code;
pitem->handler = phandler;
LIST_INSERT_HEAD(&pdescriptor->head, pitem, entries);
ESP_LOGD(TAG, "Inst: %p, add handler: 0x%x, %p", pdescriptor->instance, pitem->func_code, pitem->handler);
MB_RETURN_ON_FALSE(item_ptr, MB_ENORES, TAG, "mb can not allocate memory for command handler 0x%x.", func_code);
item_ptr->func_code = func_code;
item_ptr->handler = handler;
LIST_INSERT_HEAD(&descriptor->head, item_ptr, entries);
ESP_LOGD(TAG, "Inst: %p, add handler: 0x%x, %p", descriptor->instance, item_ptr->func_code, item_ptr->handler);
return MB_ENOERR;
}
mb_err_enum_t mb_get_handler(handler_descriptor_t *pdescriptor, uint8_t func_code, mb_fn_handler_fp *phandler)
mb_err_enum_t mb_get_handler(handler_descriptor_t *descriptor, uint8_t func_code, mb_fn_handler_fp *handler)
{
MB_RETURN_ON_FALSE((pdescriptor && phandler && pdescriptor->instance), MB_EINVAL, TAG, "invalid arguments.");
MB_RETURN_ON_FALSE((descriptor && handler && descriptor->instance), MB_EINVAL, TAG, "invalid arguments.");
MB_RETURN_ON_FALSE(MB_IS_VALID_FUNC_CODE(func_code), MB_EINVAL, TAG,
"invalid function code (0x%x)", (int)func_code);
mb_command_entry_t *pitem = NULL;
LIST_FOREACH(pitem, &pdescriptor->head, entries) {
if (pitem && pitem->func_code == func_code) {
*phandler = pitem->handler;
ESP_LOGD(TAG, "Inst: %p, get handler: 0x%x, %p", pdescriptor->instance, pitem->func_code, pitem->handler);
mb_command_entry_t *item_ptr = NULL;
LIST_FOREACH(item_ptr, &descriptor->head, entries) {
if (item_ptr && item_ptr->func_code == func_code) {
*handler = item_ptr->handler;
ESP_LOGD(TAG, "Inst: %p, get handler: 0x%x, %p", descriptor->instance, item_ptr->func_code, item_ptr->handler);
return MB_ENOERR;
}
}
@@ -61,25 +60,25 @@ mb_err_enum_t mb_get_handler(handler_descriptor_t *pdescriptor, uint8_t func_cod
}
// Helper function to get handler
mb_err_enum_t mb_delete_handler(handler_descriptor_t *pdescriptor, uint8_t func_code)
mb_err_enum_t mb_delete_handler(handler_descriptor_t *descriptor, uint8_t func_code)
{
MB_RETURN_ON_FALSE((pdescriptor && pdescriptor->instance), MB_EINVAL, TAG, "invalid arguments.");
MB_RETURN_ON_FALSE((descriptor && descriptor->instance), MB_EINVAL, TAG, "invalid arguments.");
MB_RETURN_ON_FALSE(MB_IS_VALID_FUNC_CODE(func_code), MB_EINVAL, TAG,
"invalid function code (0x%x)", (int)func_code);
if (LIST_EMPTY(&pdescriptor->head)) {
if (LIST_EMPTY(&descriptor->head)) {
return MB_EINVAL;
}
mb_command_entry_t *pitem = NULL;
mb_command_entry_t *item_ptr = NULL;
mb_command_entry_t *ptemp = NULL;
LIST_FOREACH_SAFE(pitem, &pdescriptor->head, entries, ptemp) {
if (pitem && pitem->func_code == func_code) {
ESP_LOGD(TAG, "Inst: %p, remove handler: 0x%x, %p", pdescriptor->instance, pitem->func_code, pitem->handler);
LIST_REMOVE(pitem, entries);
free(pitem);
if (pdescriptor->count) {
pdescriptor->count--;
LIST_FOREACH_SAFE(item_ptr, &descriptor->head, entries, ptemp) {
if (item_ptr && item_ptr->func_code == func_code) {
ESP_LOGD(TAG, "Inst: %p, remove handler: 0x%x, %p", descriptor->instance, item_ptr->func_code, item_ptr->handler);
LIST_REMOVE(item_ptr, entries);
free(item_ptr);
if (descriptor->count) {
descriptor->count--;
}
return MB_ENOERR;
}
@@ -89,21 +88,21 @@ mb_err_enum_t mb_delete_handler(handler_descriptor_t *pdescriptor, uint8_t func_
}
// Helper function to close all registered handlers in the list
mb_err_enum_t mb_delete_command_handlers(handler_descriptor_t *pdescriptor)
mb_err_enum_t mb_delete_command_handlers(handler_descriptor_t *descriptor)
{
MB_RETURN_ON_FALSE((pdescriptor), MB_EINVAL, TAG, "invalid arguments.");
MB_RETURN_ON_FALSE((descriptor), MB_EINVAL, TAG, "invalid arguments.");
if (LIST_EMPTY(&pdescriptor->head)) {
if (LIST_EMPTY(&descriptor->head)) {
return MB_EINVAL;
}
mb_command_entry_t *pitem = NULL;
while ((pitem = LIST_FIRST(&pdescriptor->head))) {
ESP_LOGD(TAG, "Inst: %p, close handler: 0x%x, %p", pdescriptor->instance, pitem->func_code, pitem->handler);
LIST_REMOVE(pitem, entries);
free(pitem);
if (pdescriptor->count) {
pdescriptor->count--;
mb_command_entry_t *item_ptr = NULL;
while ((item_ptr = LIST_FIRST(&descriptor->head))) {
ESP_LOGD(TAG, "Inst: %p, close handler: 0x%x, %p", descriptor->instance, item_ptr->func_code, item_ptr->handler);
LIST_REMOVE(item_ptr, entries);
free(item_ptr);
if (descriptor->count) {
descriptor->count--;
}
}
return MB_ENOERR;

View File

@@ -96,18 +96,18 @@ mb_err_enum_t mbm_rq_report_slave_id(mb_base_t *inst, uint8_t slave_addr, uint32
return err;
}
mb_exception_t mbm_fn_report_slave_id(mb_base_t *inst, uint8_t *pframe, uint16_t *plen)
mb_exception_t mbm_fn_report_slave_id(mb_base_t *inst, uint8_t *frame, uint16_t *len)
{
uint8_t byte_count = 0;
mb_exception_t status = MB_EX_NONE;
mb_err_enum_t err;
if (!inst || !plen || !pframe) {
if (!inst || !len || !frame) {
status = MB_EX_SLAVE_DEVICE_FAILURE;
} else if (*plen <= MB_BUFFER_SIZE - 2) {
byte_count = pframe[MB_PDU_BYTECNT_OFF];
} else if (*len <= MB_BUFFER_SIZE - 2) {
byte_count = frame[MB_PDU_BYTECNT_OFF];
// Transfer data from command buffer.
err = mbc_reg_common_cb(inst, &pframe[MB_PDU_FUNC_DATA_OFF], 0, byte_count);
err = mbc_reg_common_cb(inst, &frame[MB_PDU_FUNC_DATA_OFF], 0, byte_count);
// If an err occured convert it into a Modbus exception.
if (err != MB_ENOERR) {
status = mb_error_to_exception(err);
@@ -119,19 +119,19 @@ mb_exception_t mbm_fn_report_slave_id(mb_base_t *inst, uint8_t *pframe, uint16_t
return status;
}
mb_exception_t mbs_fn_report_slave_id(mb_base_t *inst, uint8_t *pframe, uint16_t *plen_buf)
mb_exception_t mbs_fn_report_slave_id(mb_base_t *inst, uint8_t *frame, uint16_t *len_buf)
{
mb_exception_t status = MB_EX_NONE;
if (!inst || !pframe || !plen_buf || !inst->pobj_id || !inst->obj_id_len) {
if (!inst || !frame || !len_buf || !inst->obj_id || !inst->obj_id_len) {
status = MB_EX_SLAVE_DEVICE_FAILURE;
} else if ((inst->obj_id_len <= MB_BUFFER_SIZE - 2)
&& (*plen_buf == MB_CMD_SL_ID_LEN)) {
&& (*len_buf == MB_CMD_SL_ID_LEN)) {
CRITICAL_SECTION(inst->lock) {
pframe[MB_PDU_FUNC_OFF] = MB_FUNC_OTHER_REPORT_SLAVEID; // rewrite the FC
*plen_buf = (uint16_t)(inst->obj_id_len);
pframe[MB_PDU_BYTECNT_OFF] = *plen_buf;
memcpy(&pframe[MB_PDU_FUNC_DATA_OFF], inst->pobj_id, (size_t)inst->obj_id_len);
*plen_buf += 2; // count function code + length in frame length
frame[MB_PDU_FUNC_OFF] = MB_FUNC_OTHER_REPORT_SLAVEID; // rewrite the FC
*len_buf = inst->obj_id_len;
frame[MB_PDU_BYTECNT_OFF] = *len_buf;
memcpy(&frame[MB_PDU_FUNC_DATA_OFF], inst->obj_id, (size_t)inst->obj_id_len);
*len_buf += 2; // count function code + length in frame length
}
} else {
status = MB_EX_ILLEGAL_DATA_VALUE;
@@ -139,7 +139,7 @@ mb_exception_t mbs_fn_report_slave_id(mb_base_t *inst, uint8_t *pframe, uint16_t
return status;
}
mb_err_enum_t mbs_set_slave_id(mb_base_t *inst, uint8_t slave_id, bool is_running, uint8_t const *pdata, uint8_t data_len)
mb_err_enum_t mbs_set_slave_id(mb_base_t *inst, uint8_t slave_id, bool is_running, uint8_t const *data_ptr, uint8_t data_len)
{
mb_err_enum_t status = MB_ENOERR;
// the first byte and second byte in the buffer is reserved for
@@ -147,20 +147,20 @@ mb_err_enum_t mbs_set_slave_id(mb_base_t *inst, uint8_t slave_id, bool is_runnin
// the buffer is available for additional data.
if (inst && inst->lock && (data_len + 2 <= MB_FUNC_OTHER_REP_SLAVEID_BUF)) {
uint8_t chunk_num = ((data_len + 2) / MB_SLAVE_ID_CHUNK_SIZE) + 1;
if (!inst->pobj_id || inst->obj_id_chunks != chunk_num) {
if (!inst->obj_id || inst->obj_id_chunks != chunk_num) {
CRITICAL_SECTION(inst->lock) {
inst->pobj_id = realloc(inst->pobj_id, (chunk_num * MB_SLAVE_ID_CHUNK_SIZE));
inst->obj_id = realloc(inst->obj_id, (chunk_num * MB_SLAVE_ID_CHUNK_SIZE));
}
}
if (!inst->pobj_id) {
if (!inst->obj_id) {
return MB_ENORES;
}
CRITICAL_SECTION(inst->lock) {
inst->obj_id_len = 0;
inst->pobj_id[inst->obj_id_len++] = slave_id;
inst->pobj_id[inst->obj_id_len++] = (uint8_t)(is_running ? 0xFF : 0x00);
inst->obj_id[inst->obj_id_len++] = slave_id;
inst->obj_id[inst->obj_id_len++] = (uint8_t)(is_running ? 0xFF : 0x00);
if (data_len > 0) {
memcpy(&inst->pobj_id[inst->obj_id_len], pdata, (size_t)data_len);
memcpy(&inst->obj_id[inst->obj_id_len], data_ptr, (size_t)data_len);
inst->obj_id_len += data_len;
inst->obj_id_chunks = chunk_num;
}
@@ -171,21 +171,21 @@ mb_err_enum_t mbs_set_slave_id(mb_base_t *inst, uint8_t slave_id, bool is_runnin
return status;
}
mb_err_enum_t mbs_get_slave_id(mb_base_t *inst, uint8_t *pdata, uint8_t *pdata_len)
mb_err_enum_t mbs_get_slave_id(mb_base_t *inst, uint8_t *data_ptr, uint8_t *data_len)
{
mb_err_enum_t status = MB_ENOERR;
if (inst && inst->lock && pdata_len) {
if (!inst->pobj_id) {
if (inst && inst->lock && data_len) {
if (!inst->obj_id) {
return MB_ENOREG;
}
if (pdata && (*pdata_len >= inst->obj_id_len)) {
if (data_ptr && (*data_len >= inst->obj_id_len)) {
CRITICAL_SECTION(inst->lock) {
memcpy(pdata, &inst->pobj_id[0],(size_t)inst->obj_id_len);
memcpy(data_ptr, &inst->obj_id[0],(size_t)inst->obj_id_len);
}
} else {
status = MB_ENORES;
}
*pdata_len = inst->obj_id_len;
*data_len = inst->obj_id_len;
} else {
status = MB_EINVAL;
}

View File

@@ -18,7 +18,7 @@ typedef mb_err_enum_t (*reg_holding_cb_fp)(mb_base_t *inst, uint8_t *reg_buff, u
typedef mb_err_enum_t (*reg_coils_cb_fp)(mb_base_t *inst, uint8_t *reg_buff, uint16_t reg_addr, uint16_t coil_num, mb_reg_mode_enum_t mode);
typedef mb_err_enum_t (*reg_discrete_cb_fp)(mb_base_t *inst, uint8_t *reg_buff, uint16_t reg_addr, uint16_t disc_num);
typedef struct _mb_rw_callbacks {
typedef struct mb_rw_callbacks_s {
reg_input_cb_fp reg_input_cb;
reg_holding_cb_fp reg_holding_cb;
reg_coils_cb_fp reg_coils_cb;

View File

@@ -68,43 +68,41 @@ extern "C" {
#define SEMA_SECTION(sema, tout) for (int st = (int)xSemaphoreTake(sema, tout); (st > 0); xSemaphoreGive(sema), st = -1)
#define MB_STR_CAT(pref, message) (__extension__( \
#define MB_PRT_BUF(pref, message, buffer, length, level) (__extension__( \
{ \
char buf##__FUNCTION__##__LINE__[MB_CAT_BUF_SIZE]; \
strncpy(&(buf##__FUNCTION__##__LINE__)[0], pref, (MB_CAT_BUF_SIZE - 1)); \
strncat((buf##__FUNCTION__##__LINE__), message, (MB_CAT_BUF_SIZE - 1)); \
(&((buf##__FUNCTION__##__LINE__)[0])); \
assert(buffer); \
char str_buf##__FUNCTION__##__LINE__[MB_CAT_BUF_SIZE]; \
strncpy(&(str_buf##__FUNCTION__##__LINE__)[0], pref, (MB_CAT_BUF_SIZE - 1)); \
strncat((str_buf##__FUNCTION__##__LINE__), message, (MB_CAT_BUF_SIZE - 1)); \
ESP_LOG_BUFFER_HEX_LEVEL(&((str_buf##__FUNCTION__##__LINE__)[0]), \
(void *)buffer, (uint16_t)length, level); \
(&((str_buf##__FUNCTION__##__LINE__)[0])); \
} \
))
#define MB_OBJ_FMT "%p"
#define MB_GET_OBJ_CTX(pinst, type, base) (__extension__( \
#define MB_GET_OBJ_CTX(inst, type, base) (__extension__( \
{ \
assert(pinst); \
((type *)__containerof(pinst, type, base)); \
assert(inst); \
((type *)__containerof(inst, type, base)); \
} \
))
#define MB_OBJ(pinst) (__extension__( \
#define MB_OBJ(inst) (__extension__( \
{ \
assert(pinst); \
((typeof(pinst))(pinst)); \
assert(inst); \
((typeof(inst))(inst)); \
} \
))
#define MB_OBJ_PARENT(pinst) (__extension__( \
{ \
assert(pinst); \
(((obj_descr_t*)(pinst))->parent); \
} \
))
#define MB_OBJ_PARENT(inst) (((obj_descr_t*)(inst))->parent)
#define MB_BASE2PORT(pinst) (__extension__( \
#define MB_BASE2PORT(inst) (__extension__( \
{ \
assert(pinst); \
assert(((mb_base_t *)pinst)->port_obj); \
(((mb_base_t *)pinst)->port_obj); \
assert(inst); \
assert(((mb_base_t *)inst)->port_obj); \
(((mb_base_t *)inst)->port_obj); \
} \
))
@@ -129,7 +127,7 @@ typedef struct mb_handler_descriptor_s {
typedef struct mb_base_t mb_base_t;
typedef struct mb_trans_base_t mb_trans_base_t;
typedef struct mb_port_base_t mb_port_base_t;
typedef struct _obj_descr obj_descr_t;
typedef struct obj_descr_s obj_descr_t;
typedef mb_err_enum_t (*mb_delete_fp)(mb_base_t *inst);
typedef mb_err_enum_t (*mb_enable_fp)(mb_base_t *inst);
@@ -139,7 +137,7 @@ typedef void (*mb_set_addr_fp)(mb_base_t *inst, uint8_t dest_addr);
typedef uint8_t (*mb_get_addr_fp)(mb_base_t *inst);
typedef void (*mb_set_send_len_fp)(mb_base_t *inst, uint16_t len);
typedef uint16_t (*mb_get_send_len_fp)(mb_base_t *inst);
typedef void (*mb_get_send_buf_fp)(mb_base_t *inst, uint8_t **pbuf);
typedef void (*mb_get_send_buf_fp)(mb_base_t *inst, uint8_t **buf);
typedef enum
{
@@ -156,7 +154,7 @@ struct mb_base_t
mb_port_base_t *port_obj;
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
uint8_t *pobj_id;
uint8_t *obj_id;
uint16_t obj_id_len;
uint8_t obj_id_chunks;
#endif
@@ -175,10 +173,10 @@ struct mb_base_t
};
// Helper functions for command handlers registration
mb_err_enum_t mb_set_handler(handler_descriptor_t *pdescriptor, uint8_t func_code, mb_fn_handler_fp phandler);
mb_err_enum_t mb_get_handler(handler_descriptor_t *pdescriptor, uint8_t func_code, mb_fn_handler_fp *phandler);
mb_err_enum_t mb_delete_handler(handler_descriptor_t *pdescriptor, uint8_t func_code);
mb_err_enum_t mb_delete_command_handlers(handler_descriptor_t *pdescriptor);
mb_err_enum_t mb_set_handler(handler_descriptor_t *descriptor, uint8_t func_code, mb_fn_handler_fp handler);
mb_err_enum_t mb_get_handler(handler_descriptor_t *descriptor, uint8_t func_code, mb_fn_handler_fp *handler);
mb_err_enum_t mb_delete_handler(handler_descriptor_t *descriptor, uint8_t func_code);
mb_err_enum_t mb_delete_command_handlers(handler_descriptor_t *descriptor);
#if (CONFIG_FMB_COMM_MODE_ASCII_EN || CONFIG_FMB_COMM_MODE_RTU_EN)

View File

@@ -18,8 +18,8 @@ extern "C" {
typedef struct mb_base_t mb_base_t;
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
mb_exception_t mbs_fn_report_slave_id(mb_base_t *inst, uint8_t *frame_ptr,uint16_t *len_buf);
mb_exception_t mbm_fn_report_slave_id(mb_base_t *inst, uint8_t *frame_ptr,uint16_t *len_buf);
mb_exception_t mbs_fn_report_slave_id(mb_base_t *inst, uint8_t *frame, uint16_t *len_buf);
mb_exception_t mbm_fn_report_slave_id(mb_base_t *inst, uint8_t *frame, uint16_t *len);
#endif
#if MB_FUNC_READ_INPUT_ENABLED

View File

@@ -14,7 +14,7 @@ typedef struct mb_base_t mb_base_t; /*!< Type of modbus object */
mb_err_enum_t mbm_rq_read_inp_reg(mb_base_t *inst, uint8_t snd_addr, uint16_t reg_addr, uint16_t reg_num, uint32_t tout);
mb_err_enum_t mbm_rq_write_holding_reg(mb_base_t *inst, uint8_t snd_addr, uint16_t reg_addr, uint16_t reg_data, uint32_t tout);
mb_err_enum_t mbm_rq_write_multi_holding_reg(mb_base_t *inst, uint8_t snd_addr, uint16_t reg_addr, uint16_t reg_wr_addr, uint16_t *data_ptr, uint32_t tout);
mb_err_enum_t mbm_rq_write_multi_holding_reg(mb_base_t *inst, uint8_t snd_addr, uint16_t reg_addr, uint16_t reg_num, uint16_t *data_ptr, uint32_t tout);
mb_err_enum_t mbm_rq_read_holding_reg(mb_base_t *inst, uint8_t snd_addr, uint16_t reg_addr, uint16_t reg_num, uint32_t tout);
mb_err_enum_t mbm_rq_rw_multi_holding_reg(mb_base_t *inst, uint8_t snd_addr, uint16_t rd_reg_addr,
uint16_t rd_reg_num, uint16_t *data_ptr, uint16_t wr_reg_addr, uint16_t wr_reg_num, uint32_t tout);
@@ -26,12 +26,12 @@ mb_err_enum_t mbm_rq_custom(mb_base_t *inst, uint8_t uid, uint8_t fc, uint8_t *b
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
mb_err_enum_t mbm_rq_report_slave_id(mb_base_t *inst, uint8_t slave_addr, uint32_t timeout);
mb_exception_t mbm_fn_report_slave_id(mb_base_t *inst, uint8_t * pframe, uint16_t *usLen);
mb_exception_t mbm_fn_report_slave_id(mb_base_t *inst, uint8_t * frame, uint16_t *len);
/*! \ingroup modbus_registers
* \brief The common callback function used to transfer common data as bytes from command buffer in little endian format.
*
* \param pdata A pointer to data in command buffer to be transferred.
* \param data_ptr A pointer to data in command buffer to be transferred.
* \param address Unused for this function == 0.
* \param bytes Number of bytes the callback function must supply.
*
@@ -42,20 +42,20 @@ mb_exception_t mbm_fn_report_slave_id(mb_base_t *inst, uint8_t * pframe, uint16_
* - mb_err_enum_t::MB_EILLSTATE if can not procceed with data transfer due to critical error
* - mb_err_enum_t::MB_EINVAL if value data can not be transferred
*/
mb_err_enum_t mbc_reg_common_cb(mb_base_t *inst, uint8_t *pdata, uint16_t address, uint16_t bytes);
mb_err_enum_t mbc_reg_common_cb(mb_base_t *inst, uint8_t *data_ptr, uint16_t address, uint16_t bytes);
#endif
// The function to register custom function handler for master
mb_err_enum_t mbm_set_handler(mb_base_t *inst, uint8_t func_code, mb_fn_handler_fp phandler);
mb_err_enum_t mbm_set_handler(mb_base_t *inst, uint8_t func_code, mb_fn_handler_fp handler);
// The helper function to get custom function handler for master
mb_err_enum_t mbm_get_handler(mb_base_t *inst, uint8_t func_code, mb_fn_handler_fp *phandler);
mb_err_enum_t mbm_get_handler(mb_base_t *inst, uint8_t func_code, mb_fn_handler_fp *handler);
// The helper function to delete custom function handler for master
mb_err_enum_t mbm_delete_handler(mb_base_t *inst, uint8_t func_code);
// The helper function to get count of handlers for master
mb_err_enum_t mbm_get_handler_count(mb_base_t *inst, uint16_t *pcount);
mb_err_enum_t mbm_get_handler_count(mb_base_t *inst, uint16_t *count);
#ifdef __cplusplus
}

View File

@@ -17,7 +17,7 @@ extern "C" {
#define MB_ADDRESS_MIN ( 1 ) /*! Smallest possible slave address. */
#define MB_ADDRESS_MAX ( 247 ) /*! Biggest possible slave address. */
typedef enum _mb_commands_enum
typedef enum mb_commands_enum
{
MB_FUNC_NONE = ( 0 ),
MB_FUNC_READ_COILS = ( 1 ),

View File

@@ -12,20 +12,20 @@ extern "C" {
#endif
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
mb_exception_t mbs_fn_report_slave_id(mb_base_t *inst, uint8_t *frame_ptr, uint16_t *plen_buf);
mb_exception_t mbs_fn_report_slave_id(mb_base_t *inst, uint8_t *frame, uint16_t *len_buf);
#endif
// The helper function to register custom function handler for slave
mb_err_enum_t mbs_set_handler(mb_base_t *inst, uint8_t func_code, mb_fn_handler_fp phandler);
mb_err_enum_t mbs_set_handler(mb_base_t *inst, uint8_t func_code, mb_fn_handler_fp handler);
// The helper function to get custom function handler for slave
mb_err_enum_t mbs_get_handler(mb_base_t *inst, uint8_t func_code, mb_fn_handler_fp *phandler);
mb_err_enum_t mbs_get_handler(mb_base_t *inst, uint8_t func_code, mb_fn_handler_fp *handler);
// The helper function to delete custom function handler for slave
mb_err_enum_t mbs_delete_handler(mb_base_t *inst, uint8_t func_code);
// The helper function to get count of handlers for slave
mb_err_enum_t mbs_get_handler_count(mb_base_t *inst, uint16_t *pcount);
mb_err_enum_t mbs_get_handler_count(mb_base_t *inst, uint16_t *count);
#ifdef __cplusplus
}

View File

@@ -109,13 +109,13 @@ uint8_t mb_util_get_bits(uint8_t *byte_buf, uint16_t bit_offset, uint8_t but_num
* \param inst - instance pointer to base modbus object
* \param slave_id - slave short address.
* \param is_running - true, if the slave is running, false otherwise
* \param pdata - the pointer to slave ID array to set in the modbus object
* \param data_ptr - the pointer to slave ID array to set in the modbus object
* \param len - slave ID array length
*
* returns the modbus error code = MB_ENOERR, if set correctly, MB_ENOREG, otherwise
* \endcode
*/
mb_err_enum_t mbs_set_slave_id(mb_base_t *inst, uint8_t sl_id, bool is_running, uint8_t const *pdata, uint16_t len);
mb_err_enum_t mbs_set_slave_id(mb_base_t *inst, uint8_t sl_id, bool is_running, uint8_t const *data_ptr, uint16_t len);
/*! \brief Standard function to get slave ID from the modbus object.
*
@@ -123,15 +123,15 @@ mb_err_enum_t mbs_set_slave_id(mb_base_t *inst, uint8_t sl_id, bool is_running,
* This ID can then be read over Modbus.
*
* \param inst - instance pointer to base modbus object
* \param pdata - the pointer to store object ID array from the modbus object
* \param[in/out] pdata_len - input length of the allocated pdata array,
* \param data_ptr - the pointer to store object ID array from the modbus object
* \param[in/out] data_len - input length of the allocated data_ptr array,
* returns the actual length of object id.
* returns the modbus error code = MB_ENOERR, if set correctly,
* MB_ENOREG - if the object ID is not set,
* MB_ENORES - no space to store object ID in the pdata buffer,
* MB_ENORES - no space to store object ID in the data_ptr buffer,
* MB_EINVAL - the arguments are not correct
*/
mb_err_enum_t mbs_get_slave_id(mb_base_t *inst, uint8_t *pdata, uint8_t *pdata_len);
mb_err_enum_t mbs_get_slave_id(mb_base_t *inst, uint8_t *data_ptr, uint8_t *data_len);
#endif
#ifdef __cplusplus

View File

@@ -53,26 +53,26 @@ static void mbm_set_pdu_send_length(mb_base_t *inst, uint16_t length);
static uint16_t mbm_get_pdu_send_length(mb_base_t *inst);
static void mbm_set_dest_addr(mb_base_t *inst, uint8_t dest_addr);
static uint8_t mbm_get_dest_addr(mb_base_t *inst);
static void mbm_get_pdu_send_buf(mb_base_t *inst, uint8_t **pbuf);
static void mbm_get_pdu_send_buf(mb_base_t *inst, uint8_t **buf);
mb_err_enum_t mbm_set_handler(mb_base_t *inst, uint8_t func_code, mb_fn_handler_fp phandler)
mb_err_enum_t mbm_set_handler(mb_base_t *inst, uint8_t func_code, mb_fn_handler_fp handler)
{
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);
mb_err_enum_t status = MB_EILLSTATE;
SEMA_SECTION(mbm_obj->handler_descriptor.sema, MB_HANDLER_UNLOCK_TICKS) {
status = mb_set_handler(&mbm_obj->handler_descriptor, func_code, phandler);
status = mb_set_handler(&mbm_obj->handler_descriptor, func_code, handler);
}
return status;
}
// The helper function to register custom function handler for master
mb_err_enum_t mbm_get_handler(mb_base_t *inst, uint8_t func_code, mb_fn_handler_fp *phandler)
mb_err_enum_t mbm_get_handler(mb_base_t *inst, uint8_t func_code, mb_fn_handler_fp *handler)
{
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);
mb_err_enum_t status = MB_EILLSTATE;
if (phandler) {
if (handler) {
SEMA_SECTION(mbm_obj->handler_descriptor.sema, MB_HANDLER_UNLOCK_TICKS) {
status = mb_get_handler(&mbm_obj->handler_descriptor, func_code, phandler);
status = mb_get_handler(&mbm_obj->handler_descriptor, func_code, handler);
}
}
return status;
@@ -88,32 +88,32 @@ mb_err_enum_t mbm_delete_handler(mb_base_t *inst, uint8_t func_code)
return status;
}
mb_err_enum_t mbm_get_handler_count(mb_base_t *inst, uint16_t *pcount)
mb_err_enum_t mbm_get_handler_count(mb_base_t *inst, uint16_t *count)
{
MB_RETURN_ON_FALSE((pcount && inst), MB_EINVAL, TAG, "get handler count wrong arguments.");
MB_RETURN_ON_FALSE((count && inst), MB_EINVAL, TAG, "get handler count wrong arguments.");
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);
SEMA_SECTION(mbm_obj->handler_descriptor.sema, MB_HANDLER_UNLOCK_TICKS) {
*pcount = mbm_obj->handler_descriptor.count;
*count = mbm_obj->handler_descriptor.count;
}
return MB_ENOERR;
}
static mb_err_enum_t mbm_check_invoke_handler(mb_base_t *inst, uint8_t func_code, uint8_t *pbuf, uint16_t *plen)
static mb_err_enum_t mbm_check_invoke_handler(mb_base_t *inst, uint8_t func_code, uint8_t *buf, uint16_t *len)
{
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);
mb_exception_t exception = MB_EX_ILLEGAL_FUNCTION;
if (!func_code || !pbuf) {
if (!func_code || !buf) {
return MB_EX_ILLEGAL_FUNCTION;
}
if (func_code & MB_FUNC_ERROR) {
exception = (mb_exception_t)pbuf[MB_PDU_DATA_OFF];
exception = (mb_exception_t)buf[MB_PDU_DATA_OFF];
return exception;
}
SEMA_SECTION(mbm_obj->handler_descriptor.sema, MB_HANDLER_UNLOCK_TICKS) {
mb_fn_handler_fp phandler = NULL;
mb_err_enum_t status = mb_get_handler(&mbm_obj->handler_descriptor, func_code, &phandler);
if ((status == MB_ENOERR) && phandler) {
exception = phandler(inst, pbuf, plen);
mb_fn_handler_fp handler = NULL;
mb_err_enum_t status = mb_get_handler(&mbm_obj->handler_descriptor, func_code, &handler);
if ((status == MB_ENOERR) && handler) {
exception = handler(inst, buf, len);
}
}
return exception;
@@ -126,7 +126,7 @@ static mb_err_enum_t mbm_register_default_handlers(mb_base_t *inst)
LIST_INIT(&mbm_obj->handler_descriptor.head);
mbm_obj->handler_descriptor.sema = xSemaphoreCreateBinary();
(void)xSemaphoreGive(mbm_obj->handler_descriptor.sema);
mbm_obj->handler_descriptor.instance = (void *)inst->descr.parent;
mbm_obj->handler_descriptor.instance = inst->descr.parent;
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
err = mbm_set_handler(inst, MB_FUNC_OTHER_REPORT_SLAVEID, (void *)mbm_fn_report_slave_id);
MB_RETURN_ON_FALSE((err == MB_ENOERR), err, TAG, "handler registration error = (0x%x).", (int)err);
@@ -190,6 +190,7 @@ mb_err_enum_t mbm_rtu_create(mb_serial_opts_t *ser_opts, void **in_out_obj)
MB_RETURN_ON_FALSE((ser_opts->mode == MB_RTU), MB_EILLSTATE, TAG, "incorrect mode != RTU.");
mb_err_enum_t ret = MB_ENOERR;
mbm_object_t *mbm_obj = NULL;
mb_trans_base_t *transp_obj = NULL;
mbm_obj = (mbm_object_t *)calloc(1, sizeof(mbm_object_t));
MB_GOTO_ON_FALSE((mbm_obj), MB_EILLSTATE, error, TAG, "no mem for mb master instance.");
CRITICAL_SECTION_INIT(mbm_obj->base.lock);
@@ -208,21 +209,21 @@ mb_err_enum_t mbm_rtu_create(mb_serial_opts_t *ser_opts, void **in_out_obj)
mbm_obj->base.descr.obj_name = (char *)TAG;
mbm_obj->base.descr.inst_index = mb_port_get_inst_counter_inc();
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
mbm_obj->base.pobj_id = NULL;
mbm_obj->base.obj_id = NULL;
mbm_obj->base.obj_id_len = 0;
mbm_obj->base.obj_id_chunks = 0;
#endif
int res = asprintf(&mbm_obj->base.descr.parent_name, "mbm_rtu@%p", mbm_obj->base.descr.parent);
MB_GOTO_ON_FALSE((res), MB_EILLSTATE, error,
TAG, "name alloc fail, err: %d", (int)res);
mb_trans_base_t *transp_obj = (mb_trans_base_t *)mbm_obj;
transp_obj = (mb_trans_base_t *)mbm_obj;
ret = mbm_rtu_transp_create(ser_opts, (void **)&transp_obj);
MB_GOTO_ON_FALSE((transp_obj && (ret == MB_ENOERR)), MB_EILLSTATE, error,
TAG, "transport creation, err: %d", (int)ret);
mbm_obj->cur_mode = ser_opts->mode;
mbm_obj->cur_state = STATE_DISABLED;
transp_obj->get_tx_frm(transp_obj, (uint8_t **)&mbm_obj->snd_frame);
transp_obj->get_rx_frm(transp_obj, (uint8_t **)&mbm_obj->rcv_frame);
transp_obj->get_tx_frm(transp_obj, &mbm_obj->snd_frame);
transp_obj->get_rx_frm(transp_obj, &mbm_obj->rcv_frame);
mbm_obj->curr_trans_id = 0;
mbm_obj->base.port_obj = transp_obj->port_obj;
mbm_obj->base.transp_obj = transp_obj;
@@ -255,6 +256,7 @@ mb_err_enum_t mbm_ascii_create(mb_serial_opts_t *ser_opts, void **in_out_obj)
MB_RETURN_ON_FALSE((ser_opts->mode == MB_ASCII), MB_EILLSTATE, TAG, "incorrect option mode != ASCII.");
mb_err_enum_t ret = MB_ENOERR;
mbm_object_t *mbm_obj = NULL;
mb_trans_base_t *transp_obj = NULL;
mbm_obj = (mbm_object_t *)calloc(1, sizeof(mbm_object_t));
MB_GOTO_ON_FALSE((mbm_obj), MB_EILLSTATE, error, TAG, "no mem for mb master instance.");
CRITICAL_SECTION_INIT(mbm_obj->base.lock);
@@ -273,14 +275,14 @@ mb_err_enum_t mbm_ascii_create(mb_serial_opts_t *ser_opts, void **in_out_obj)
mbm_obj->base.descr.obj_name = (char *)TAG;
mbm_obj->base.descr.inst_index = mb_port_get_inst_counter_inc();
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
mbm_obj->base.pobj_id = NULL;
mbm_obj->base.obj_id = NULL;
mbm_obj->base.obj_id_len = 0;
mbm_obj->base.obj_id_chunks = 0;
#endif
int res = asprintf(&mbm_obj->base.descr.parent_name, "mbm_ascii@%p", mbm_obj->base.descr.parent);
MB_GOTO_ON_FALSE((res), MB_EILLSTATE, error,
TAG, "name alloc fail, err: %d", (int)res);
mb_trans_base_t *transp_obj = (mb_trans_base_t *)mbm_obj;
transp_obj = (mb_trans_base_t *)mbm_obj;
ret = mbm_ascii_transp_create(ser_opts, (void **)&transp_obj);
MB_GOTO_ON_FALSE((transp_obj && (ret == MB_ENOERR)), MB_EILLSTATE, error,
TAG, "transport creation, err: %d", (int)ret);
@@ -289,8 +291,8 @@ mb_err_enum_t mbm_ascii_create(mb_serial_opts_t *ser_opts, void **in_out_obj)
TAG, "default handlers registration fail, err: %d", (int)ret);
mbm_obj->cur_mode = ser_opts->mode;
mbm_obj->cur_state = STATE_DISABLED;
transp_obj->get_tx_frm(transp_obj, (uint8_t **)&mbm_obj->snd_frame);
transp_obj->get_rx_frm(transp_obj, (uint8_t **)&mbm_obj->rcv_frame);
transp_obj->get_tx_frm(transp_obj, &mbm_obj->snd_frame);
transp_obj->get_rx_frm(transp_obj, &mbm_obj->rcv_frame);
mbm_obj->base.port_obj = transp_obj->port_obj; // binding of the modbus object with port object
mbm_obj->base.transp_obj = transp_obj;
*in_out_obj = (void *)&(mbm_obj->base);
@@ -320,6 +322,7 @@ mb_err_enum_t mbm_tcp_create(mb_tcp_opts_t *tcp_opts, void **in_out_obj)
MB_RETURN_ON_FALSE((tcp_opts->mode == MB_TCP), MB_EILLSTATE, TAG, "incorrect option mode != TCP.");
mb_err_enum_t ret = MB_ENOERR;
mbm_object_t *mbm_obj = NULL;
mb_trans_base_t *transp_obj = NULL;
mbm_obj = (mbm_object_t *)calloc(1, sizeof(mbm_object_t));
MB_RETURN_ON_FALSE(mbm_obj, MB_EILLSTATE, TAG, "no mem for mb master instance.");
CRITICAL_SECTION_INIT(mbm_obj->base.lock);
@@ -338,14 +341,14 @@ mb_err_enum_t mbm_tcp_create(mb_tcp_opts_t *tcp_opts, void **in_out_obj)
mbm_obj->base.descr.obj_name = (char *)TAG;
mbm_obj->base.descr.inst_index = mb_port_get_inst_counter_inc();
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
mbm_obj->base.pobj_id = NULL;
mbm_obj->base.obj_id = NULL;
mbm_obj->base.obj_id_len = 0;
mbm_obj->base.obj_id_chunks = 0;
#endif
int res = asprintf(&mbm_obj->base.descr.parent_name, "mbm_tcp#%p", mbm_obj->base.descr.parent);
MB_GOTO_ON_FALSE((res), MB_EILLSTATE, error,
TAG, "name alloc fail, err: %d", (int)res);
mb_trans_base_t *transp_obj = (mb_trans_base_t *)mbm_obj;
transp_obj = (mb_trans_base_t *)mbm_obj;
ret = mbm_tcp_transp_create(tcp_opts, (void **)&transp_obj);
MB_GOTO_ON_FALSE((transp_obj && (ret == MB_ENOERR)), MB_EILLSTATE, error,
TAG, "transport creation, err: %d", (int)ret);
@@ -354,8 +357,8 @@ mb_err_enum_t mbm_tcp_create(mb_tcp_opts_t *tcp_opts, void **in_out_obj)
TAG, "default handlers registration fail, err: %d", (int)ret);
mbm_obj->cur_mode = tcp_opts->mode;
mbm_obj->cur_state = STATE_DISABLED;
transp_obj->get_tx_frm(transp_obj, (uint8_t **)&mbm_obj->snd_frame);
transp_obj->get_rx_frm(transp_obj, (uint8_t **)&mbm_obj->rcv_frame);
transp_obj->get_tx_frm(transp_obj, &mbm_obj->snd_frame);
transp_obj->get_rx_frm(transp_obj, &mbm_obj->rcv_frame);
mbm_obj->base.port_obj = transp_obj->port_obj; // binding of the modbus object with port object
mbm_obj->base.transp_obj = transp_obj;
*in_out_obj = (void *)&(mbm_obj->base);
@@ -387,9 +390,9 @@ mb_err_enum_t mbm_delete(mb_base_t *inst)
}
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
// check object ID
if (mbm_obj->base.pobj_id) {
free(mbm_obj->base.pobj_id);
mbm_obj->base.pobj_id = NULL;
if (mbm_obj->base.obj_id) {
free(mbm_obj->base.obj_id);
mbm_obj->base.obj_id = NULL;
mbm_obj->base.obj_id_len = 0;
mbm_obj->base.obj_id_chunks = 0;
ESP_LOGW(TAG, "%p, Master object ID is not supported!", mbm_obj);
@@ -449,17 +452,17 @@ mb_err_enum_t mbm_disable(mb_base_t *inst)
return status;
}
static void mbm_get_pdu_send_buf(mb_base_t *inst, uint8_t **pbuf)
static void mbm_get_pdu_send_buf(mb_base_t *inst, uint8_t **buf)
{
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);
MB_OBJ(mbm_obj->base.transp_obj)->get_tx_frm(mbm_obj->base.transp_obj, pbuf);
MB_OBJ(mbm_obj->base.transp_obj)->get_tx_frm(mbm_obj->base.transp_obj, buf);
}
__attribute__((unused))
static void mbm_get_pdu_recv_buf(mb_base_t *inst, uint8_t **pbuf)
static void mbm_get_pdu_recv_buf(mb_base_t *inst, uint8_t **buf)
{
mbm_object_t *mbm_obj = MB_GET_OBJ_CTX(inst, mbm_object_t, base);;
MB_OBJ(mbm_obj->base.transp_obj)->get_rx_frm(mbm_obj->base.transp_obj, pbuf);
MB_OBJ(mbm_obj->base.transp_obj)->get_rx_frm(mbm_obj->base.transp_obj, buf);
}
static void mbm_set_pdu_send_length(mb_base_t *inst, uint16_t length)
@@ -542,8 +545,8 @@ mb_err_enum_t mbm_poll(mb_base_t *inst)
case EV_FRAME_TRANSMIT:
mbm_get_pdu_send_buf(inst, &mbm_obj->snd_frame);
ESP_LOG_BUFFER_HEX_LEVEL(MB_STR_CAT(inst->descr.parent_name, ":MB_TRANSMIT"),
(void *)mbm_obj->snd_frame, mbm_obj->pdu_snd_len, ESP_LOG_DEBUG);
MB_PRT_BUF(inst->descr.parent_name, ":MB_TRANSMIT",
mbm_obj->snd_frame, mbm_obj->pdu_snd_len, ESP_LOG_DEBUG);
status = MB_OBJ(inst->transp_obj)->frm_send(inst->transp_obj, mbm_obj->master_dst_addr,
mbm_obj->snd_frame, mbm_obj->pdu_snd_len);
if (status != MB_ENOERR) {
@@ -571,8 +574,8 @@ mb_err_enum_t mbm_poll(mb_base_t *inst)
|| (mbm_obj->rcv_addr == MB_TCP_PSEUDO_ADDRESS))) {
if ((mbm_obj->rcv_frame[MB_PDU_FUNC_OFF] & ~MB_FUNC_ERROR) == (mbm_obj->snd_frame[MB_PDU_FUNC_OFF])) {
ESP_LOGD(TAG, MB_OBJ_FMT", frame data received successfully, (%d).", MB_OBJ_PARENT(inst), (int)status);
ESP_LOG_BUFFER_HEX_LEVEL(MB_STR_CAT(inst->descr.parent_name, ":MB_RECV"), (void *)mbm_obj->rcv_frame,
(uint16_t)mbm_obj->pdu_rcv_len, ESP_LOG_DEBUG);
MB_PRT_BUF(inst->descr.parent_name, ":MB_RECV",
mbm_obj->rcv_frame, mbm_obj->pdu_rcv_len, ESP_LOG_DEBUG);
(void)mb_port_event_post(MB_OBJ(inst->port_obj), EVENT(EV_EXECUTE));
} else {
ESP_LOGE(TAG, MB_OBJ_FMT", drop incorrect frame, receive_func(%u) != send_func(%u)",

View File

@@ -46,24 +46,24 @@ mb_err_enum_t mbs_disable(mb_base_t *inst);
mb_err_enum_t mbs_poll(mb_base_t *inst);
// The helper function to register custom function handler for slave
mb_err_enum_t mbs_set_handler(mb_base_t *inst, uint8_t func_code, mb_fn_handler_fp phandler)
mb_err_enum_t mbs_set_handler(mb_base_t *inst, uint8_t func_code, mb_fn_handler_fp handler)
{
mbs_object_t *mbs_obj = MB_GET_OBJ_CTX(inst, mbs_object_t, base);
mb_err_enum_t status = MB_EINVAL;
SEMA_SECTION(mbs_obj->handler_descriptor.sema, MB_HANDLER_UNLOCK_TICKS) {
status = mb_set_handler(&mbs_obj->handler_descriptor, func_code, phandler);
status = mb_set_handler(&mbs_obj->handler_descriptor, func_code, handler);
}
return status;
}
// The helper function to register custom function handler for slave
mb_err_enum_t mbs_get_handler(mb_base_t *inst, uint8_t func_code, mb_fn_handler_fp *phandler)
mb_err_enum_t mbs_get_handler(mb_base_t *inst, uint8_t func_code, mb_fn_handler_fp *handler)
{
mbs_object_t *mbs_obj = MB_GET_OBJ_CTX(inst, mbs_object_t, base);
mb_err_enum_t status = MB_EINVAL;
if (phandler) {
if (handler) {
SEMA_SECTION(mbs_obj->handler_descriptor.sema, MB_HANDLER_UNLOCK_TICKS) {
status = mb_get_handler(&mbs_obj->handler_descriptor, func_code, phandler);
status = mb_get_handler(&mbs_obj->handler_descriptor, func_code, handler);
}
}
return status;
@@ -79,17 +79,17 @@ mb_err_enum_t mbs_delete_handler(mb_base_t *inst, uint8_t func_code)
return status;
}
mb_err_enum_t mbs_get_handler_count(mb_base_t *inst, uint16_t *pcount)
mb_err_enum_t mbs_get_handler_count(mb_base_t *inst, uint16_t *count)
{
MB_RETURN_ON_FALSE((pcount && inst), MB_EINVAL, TAG, "get handler count wrong arguments");
MB_RETURN_ON_FALSE((count && inst), MB_EINVAL, TAG, "get handler count wrong arguments");
mbs_object_t *mbs_obj = MB_GET_OBJ_CTX(inst, mbs_object_t, base);
SEMA_SECTION(mbs_obj->handler_descriptor.sema, MB_HANDLER_UNLOCK_TICKS) {
*pcount = mbs_obj->handler_descriptor.count;
*count = mbs_obj->handler_descriptor.count;
}
return MB_ENOERR;
}
static mb_exception_t mbs_check_invoke_handler(mb_base_t *inst, uint8_t func_code, uint8_t *pbuf, uint16_t *plen)
static mb_exception_t mbs_check_invoke_handler(mb_base_t *inst, uint8_t func_code, uint8_t *buf, uint16_t *len)
{
mbs_object_t *mbs_obj = MB_GET_OBJ_CTX(inst, mbs_object_t, base);
mb_exception_t exception = MB_EX_ILLEGAL_FUNCTION;
@@ -97,11 +97,11 @@ static mb_exception_t mbs_check_invoke_handler(mb_base_t *inst, uint8_t func_cod
return MB_EX_ILLEGAL_FUNCTION;
}
SEMA_SECTION(mbs_obj->handler_descriptor.sema, MB_HANDLER_UNLOCK_TICKS) {
mb_fn_handler_fp phandler = NULL;
mb_err_enum_t status = mb_get_handler(&mbs_obj->handler_descriptor, func_code, &phandler);
if ((status == MB_ENOERR) && phandler) {
exception = phandler(inst, pbuf, plen);
ESP_LOGD(TAG, MB_OBJ_FMT": function (0x%x), invoke handler %p.", MB_OBJ_PARENT(inst), (int)func_code, phandler);
mb_fn_handler_fp handler = NULL;
mb_err_enum_t status = mb_get_handler(&mbs_obj->handler_descriptor, func_code, &handler);
if ((status == MB_ENOERR) && handler) {
exception = handler(inst, buf, len);
ESP_LOGD(TAG, MB_OBJ_FMT": function (0x%x), invoke handler %p.", MB_OBJ_PARENT(inst), (int)func_code, handler);
}
}
return exception;
@@ -114,7 +114,7 @@ static mb_err_enum_t mbs_register_default_handlers(mb_base_t *inst)
LIST_INIT(&mbs_obj->handler_descriptor.head);
mbs_obj->handler_descriptor.sema = xSemaphoreCreateBinary();
(void)xSemaphoreGive(mbs_obj->handler_descriptor.sema);
mbs_obj->handler_descriptor.instance = (void *)inst->descr.parent;
mbs_obj->handler_descriptor.instance = inst->descr.parent;
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
err = mbs_set_handler(inst, MB_FUNC_OTHER_REPORT_SLAVEID, (void *)mbs_fn_report_slave_id);
MB_RETURN_ON_FALSE((err == MB_ENOERR), err, TAG, "handler registration error = (0x%x).", (int)err);
@@ -178,6 +178,7 @@ mb_err_enum_t mbs_rtu_create(mb_serial_opts_t *ser_opts, void **in_out_obj)
MB_RETURN_ON_FALSE(ser_opts, MB_EINVAL, TAG, "invalid options for the instance.");
MB_RETURN_ON_FALSE((ser_opts->mode == MB_RTU), MB_EILLSTATE, TAG, "incorrect mode != RTU.");
mbs_object_t *mbs_obj = NULL;
mb_trans_base_t *transp_obj = NULL;
mbs_obj = (mbs_object_t*)calloc(1, sizeof(mbs_object_t));
MB_GOTO_ON_FALSE((mbs_obj), MB_EILLSTATE, error, TAG, "no mem for mb slave instance.");
CRITICAL_SECTION_INIT(mbs_obj->base.lock);
@@ -191,14 +192,14 @@ mb_err_enum_t mbs_rtu_create(mb_serial_opts_t *ser_opts, void **in_out_obj)
mbs_obj->base.descr.obj_name = (char *)TAG;
mbs_obj->base.descr.inst_index = mb_port_get_inst_counter_inc();
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
mbs_obj->base.pobj_id = NULL;
mbs_obj->base.obj_id = NULL;
mbs_obj->base.obj_id_len = 0;
mbs_obj->base.obj_id_chunks = 0;
#endif
int res = asprintf(&mbs_obj->base.descr.parent_name, "mbs_rtu@%p", *in_out_obj);
MB_GOTO_ON_FALSE((res), MB_EILLSTATE, error,
TAG, "name alloc fail, err: %d", (int)res);
mb_trans_base_t *transp_obj = (mb_trans_base_t *)mbs_obj;
transp_obj = (mb_trans_base_t *)mbs_obj;
ret = mbs_rtu_transp_create(ser_opts, (void **)&transp_obj);
MB_GOTO_ON_FALSE((transp_obj && (ret == MB_ENOERR)), MB_EILLSTATE, error,
TAG, "transport creation, err: %d", (int)ret);
@@ -208,7 +209,7 @@ mb_err_enum_t mbs_rtu_create(mb_serial_opts_t *ser_opts, void **in_out_obj)
mbs_obj->cur_mode = ser_opts->mode;
mbs_obj->mb_address = ser_opts->uid;
mbs_obj->cur_state = STATE_DISABLED;
transp_obj->get_tx_frm(transp_obj, (uint8_t **)&mbs_obj->frame);
transp_obj->get_tx_frm(transp_obj, &mbs_obj->frame);
mbs_obj->base.port_obj = transp_obj->port_obj;
mbs_obj->base.transp_obj = transp_obj;
*in_out_obj = (void *)&(mbs_obj->base);
@@ -237,6 +238,7 @@ mb_err_enum_t mbs_ascii_create(mb_serial_opts_t *ser_opts, void **in_out_obj)
MB_RETURN_ON_FALSE(ser_opts, MB_EINVAL, TAG, "invalid options for %s instance.", TAG);
MB_RETURN_ON_FALSE((ser_opts->mode == MB_ASCII), MB_EILLSTATE, TAG, "incorrect mode != ASCII.");
mbs_object_t *mbs_obj = NULL;
mb_trans_base_t *transp_obj = NULL;
mbs_obj = (mbs_object_t*)calloc(1, sizeof(mbs_object_t));
MB_GOTO_ON_FALSE((mbs_obj), MB_EILLSTATE, error, TAG, "no mem for mb slave instance.");
CRITICAL_SECTION_INIT(mbs_obj->base.lock);
@@ -249,14 +251,14 @@ mb_err_enum_t mbs_ascii_create(mb_serial_opts_t *ser_opts, void **in_out_obj)
mbs_obj->base.descr.obj_name = (char *)TAG;
mbs_obj->base.descr.inst_index = mb_port_get_inst_counter_inc();
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
mbs_obj->base.pobj_id = NULL;
mbs_obj->base.obj_id = NULL;
mbs_obj->base.obj_id_len = 0;
mbs_obj->base.obj_id_chunks = 0;
#endif
int res = asprintf(&mbs_obj->base.descr.parent_name, "mbs_ascii@%p", *in_out_obj);
MB_GOTO_ON_FALSE((res), MB_EILLSTATE, error,
TAG, "name alloc fail, err: %d", (int)res);
mb_trans_base_t *transp_obj = (mb_trans_base_t *)mbs_obj;
transp_obj = (mb_trans_base_t *)mbs_obj;
ret = mbs_ascii_transp_create(ser_opts, (void **)&transp_obj);
MB_GOTO_ON_FALSE((transp_obj && (ret == MB_ENOERR)), MB_EILLSTATE, error,
TAG, "transport creation, err: %d", (int)ret);
@@ -266,7 +268,7 @@ mb_err_enum_t mbs_ascii_create(mb_serial_opts_t *ser_opts, void **in_out_obj)
mbs_obj->cur_mode = ser_opts->mode;
mbs_obj->mb_address = ser_opts->uid;
mbs_obj->cur_state = STATE_DISABLED;
transp_obj->get_tx_frm(transp_obj, (uint8_t **)&mbs_obj->frame);
transp_obj->get_tx_frm(transp_obj, &mbs_obj->frame);
mbs_obj->base.port_obj = transp_obj->port_obj;
mbs_obj->base.transp_obj = transp_obj;
*in_out_obj = (void *)&(mbs_obj->base);
@@ -295,6 +297,7 @@ mb_err_enum_t mbs_tcp_create(mb_tcp_opts_t *tcp_opts, void **in_out_obj)
MB_RETURN_ON_FALSE(tcp_opts, MB_EINVAL, TAG, "invalid options for the instance.");
MB_RETURN_ON_FALSE((tcp_opts->mode == MB_TCP), MB_EILLSTATE, TAG, "incorrect mode != TCP.");
mbs_object_t *mbs_obj = NULL;
mb_trans_base_t *transp_obj = NULL;
mbs_obj = (mbs_object_t*)calloc(1, sizeof(mbs_object_t));
MB_GOTO_ON_FALSE((mbs_obj), MB_EILLSTATE, error, TAG, "no mem for mb slave instance.");
CRITICAL_SECTION_INIT(mbs_obj->base.lock);
@@ -308,14 +311,14 @@ mb_err_enum_t mbs_tcp_create(mb_tcp_opts_t *tcp_opts, void **in_out_obj)
mbs_obj->base.descr.obj_name = (char *)TAG;
mbs_obj->base.descr.inst_index = mb_port_get_inst_counter_inc();
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
mbs_obj->base.pobj_id = NULL;
mbs_obj->base.obj_id = NULL;
mbs_obj->base.obj_id_len = 0;
mbs_obj->base.obj_id_chunks = 0;
#endif
int res = asprintf(&mbs_obj->base.descr.parent_name, "mbs_tcp@%p", *in_out_obj);
MB_GOTO_ON_FALSE((res), MB_EILLSTATE, error,
TAG, "name alloc fail, err: %d", (int)res);
mb_trans_base_t *transp_obj = (mb_trans_base_t *)mbs_obj;
transp_obj = (mb_trans_base_t *)mbs_obj;
ret = mbs_tcp_transp_create(tcp_opts, (void **)&transp_obj);
MB_GOTO_ON_FALSE((transp_obj && (ret == MB_ENOERR)), MB_EILLSTATE, error,
TAG, "transport creation, err: %d", (int)ret);
@@ -325,7 +328,7 @@ mb_err_enum_t mbs_tcp_create(mb_tcp_opts_t *tcp_opts, void **in_out_obj)
mbs_obj->cur_mode = tcp_opts->mode;
mbs_obj->mb_address = tcp_opts->uid;
mbs_obj->cur_state = STATE_DISABLED;
transp_obj->get_tx_frm(transp_obj, (uint8_t **)&mbs_obj->frame);
transp_obj->get_tx_frm(transp_obj, &mbs_obj->frame);
mbs_obj->base.port_obj = transp_obj->port_obj;
mbs_obj->base.transp_obj = transp_obj;
*in_out_obj = (void *)&(mbs_obj->base);
@@ -357,9 +360,9 @@ mb_err_enum_t mbs_delete(mb_base_t *inst)
}
#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
// delete allocated slave ID
if (mbs_obj->base.pobj_id) {
free(mbs_obj->base.pobj_id);
mbs_obj->base.pobj_id = NULL;
if (mbs_obj->base.obj_id) {
free(mbs_obj->base.obj_id);
mbs_obj->base.obj_id = NULL;
mbs_obj->base.obj_id_len = 0;
mbs_obj->base.obj_id_chunks = 0;
}
@@ -452,8 +455,8 @@ mb_err_enum_t mbs_poll(mb_base_t *inst)
|| (mbs_obj->rcv_addr == MB_TCP_PSEUDO_ADDRESS)) {
mbs_obj->curr_trans_id = event.get_ts;
(void)mb_port_event_post(MB_OBJ(inst->port_obj), EVENT(EV_EXECUTE | EV_TRANS_START));
ESP_LOG_BUFFER_HEX_LEVEL(MB_STR_CAT(inst->descr.parent_name, ":MB_RECV"), &mbs_obj->frame[MB_PDU_FUNC_OFF],
(uint16_t)mbs_obj->length, ESP_LOG_DEBUG);
MB_PRT_BUF(inst->descr.parent_name, ":MB_RECV",
&mbs_obj->frame[MB_PDU_FUNC_OFF], mbs_obj->length, ESP_LOG_DEBUG);
}
}
break;
@@ -474,7 +477,8 @@ mb_err_enum_t mbs_poll(mb_base_t *inst)
if ((mbs_obj->cur_mode == MB_ASCII) && MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS) {
mb_port_timer_delay(MB_OBJ(inst->port_obj), MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS);
}
ESP_LOG_BUFFER_HEX_LEVEL(MB_STR_CAT(inst->descr.parent_name, ":MB_SEND"), (void *)mbs_obj->frame, mbs_obj->length, ESP_LOG_DEBUG);
MB_PRT_BUF(inst->descr.parent_name, ":MB_SEND", (void *)mbs_obj->frame,
(uint16_t)mbs_obj->length, ESP_LOG_DEBUG);
status = MB_OBJ(inst->transp_obj)->frm_send(inst->transp_obj, mbs_obj->rcv_addr, mbs_obj->frame, mbs_obj->length);
if (status != MB_ENOERR) {
ESP_LOGE(TAG, MB_OBJ_FMT":frame send error. %d", MB_OBJ_PARENT(inst), (int)status);

View File

@@ -150,7 +150,7 @@ uint8_t *transaction_item_get_data(transaction_item_handle_t item, size_t *len,
if (node_id) {
*node_id = item->node_id;
}
return (uint8_t *)item->buffer;
return item->buffer;
}
return NULL;
}

View File

@@ -48,7 +48,7 @@ typedef enum pending_state {
transaction_handle_t transaction_init(void);
transaction_item_handle_t transaction_enqueue(transaction_handle_t transaction, transaction_message_handle_t message, transaction_tick_t tick);
transaction_item_handle_t transaction_dequeue(transaction_handle_t transaction, pending_state_t pending, transaction_tick_t *tick);
transaction_item_handle_t transaction_dequeue(transaction_handle_t transaction, pending_state_t state, transaction_tick_t *tick);
transaction_item_handle_t transaction_get(transaction_handle_t transaction, int msg_id);
transaction_item_handle_t transaction_get_first(transaction_handle_t transaction);
uint8_t *transaction_item_get_data(transaction_item_handle_t item, size_t *len, uint16_t *msg_id, int *node_id);
@@ -62,7 +62,7 @@ int transaction_delete_expired(transaction_handle_t transaction, transaction_tic
* @return msg id of the deleted message, -1 if no expired message in the transaction
*/
int transaction_delete_single_expired(transaction_handle_t transaction, transaction_tick_t current_tick, transaction_tick_t timeout);
esp_err_t transaction_set_state(transaction_handle_t transaction, int msg_id, pending_state_t pending);
esp_err_t transaction_set_state(transaction_handle_t transaction, int msg_id, pending_state_t state);
pending_state_t transaction_item_get_state(transaction_item_handle_t item);
esp_err_t transaction_item_set_state(transaction_item_handle_t item, pending_state_t state);
esp_err_t transaction_set_tick(transaction_handle_t transaction, int msg_id, transaction_tick_t tick);

View File

@@ -30,8 +30,8 @@ extern "C" {
#define MB_EVENT_QUEUE_TIMEOUT_MAX (pdMS_TO_TICKS(MB_EVENT_QUEUE_TIMEOUT_MAX_MS))
#define MB_MS_TO_TICKS(time_ms) (pdMS_TO_TICKS(time_ms))
int lock_obj(_lock_t *plock);
void unlock_obj(_lock_t *plock);
int lock_obj(_lock_t *lock_ptr);
void unlock_obj(_lock_t *lock_ptr);
#define CRITICAL_SECTION_INIT(lock) \
do \
@@ -104,9 +104,9 @@ void unlock_obj(_lock_t *plock);
#define EVENT_2(_1, _2) \
(mb_event_t) { .event = _1, .length = _2 }
#define EVENT_3(_1, _2, _3) \
(mb_event_t) { .event = _1, .length = _2, .pdata = _3 }
(mb_event_t) { .event = _1, .length = _2, .data_ptr = _3 }
#define EVENT_4(_1, _2, _3, _4) \
(mb_event_t) { .event = _1, .length = _2, .pdata = _3, .type = _4 }
(mb_event_t) { .event = _1, .length = _2, .data_ptr = _3, .type = _4 }
typedef struct mb_port_base_t mb_port_base_t;
@@ -136,14 +136,14 @@ typedef struct
typedef struct mb_port_event_t mb_port_event_t;
typedef struct mb_port_timer_t mb_port_timer_t;
typedef struct _obj_descr obj_descr_t;
typedef struct obj_descr_s obj_descr_t;
typedef struct _frame_queue_entry
typedef struct frame_queue_entry_s
{
uint16_t tid; /*!< Transaction identifier (TID) for slave */
uint16_t pid; /*!< Protocol ID field of MBAP frame */
uint16_t uid; /*!< Slave unit ID (UID) field for MBAP frame */
uint8_t *pbuf; /*!< Points to the buffer for the frame */
uint8_t *buf; /*!< Points to the buffer for the frame */
uint16_t len; /*!< Length of the frame in the buffer */
bool check; /*!< Checked flag */
} frame_entry_t;
@@ -160,7 +160,7 @@ struct mb_port_base_t
};
// Port event functions
mb_err_enum_t mb_port_event_create(mb_port_base_t *port_obj);
mb_err_enum_t mb_port_event_create(mb_port_base_t *inst);
bool mb_port_event_post(mb_port_base_t *inst, mb_event_t event);
bool mb_port_event_get(mb_port_base_t *inst, mb_event_t *event);
bool mb_port_event_res_take(mb_port_base_t *inst, uint32_t timeout);
@@ -196,8 +196,8 @@ QueueHandle_t queue_create(int queue_size);
void queue_delete(QueueHandle_t queue);
void queue_flush(QueueHandle_t queue);
bool queue_is_empty(QueueHandle_t queue);
esp_err_t queue_push(QueueHandle_t queue, void *pbuf, size_t len, frame_entry_t *pframe);
ssize_t queue_pop(QueueHandle_t queue, void *pbuf, size_t len, frame_entry_t *pframe);
esp_err_t queue_push(QueueHandle_t queue, void *buf, size_t len, frame_entry_t *frame);
ssize_t queue_pop(QueueHandle_t queue, void *buf, size_t len, frame_entry_t *frame);
#ifdef __cplusplus

View File

@@ -27,40 +27,40 @@ struct mb_port_event_t
mb_err_enum_t mb_port_event_create(mb_port_base_t *inst)
{
mb_port_event_t *pevent = NULL;
mb_port_event_t *event_obj = NULL;
mb_err_enum_t ret = MB_EILLSTATE;
MB_RETURN_ON_FALSE((inst), MB_EILLSTATE, TAG, "mb event creation error.");
pevent = (mb_port_event_t *)calloc(1, sizeof(mb_port_event_t));
MB_RETURN_ON_FALSE((pevent), MB_EILLSTATE, TAG, "mb event creation error.");
event_obj = (mb_port_event_t *)calloc(1, sizeof(mb_port_event_t));
MB_RETURN_ON_FALSE((event_obj), MB_EILLSTATE, TAG, "mb event creation error.");
// Create modbus semaphore (mb resource).
pevent->resource_hdl = xSemaphoreCreateBinary();
MB_GOTO_ON_FALSE((pevent->resource_hdl), MB_EILLSTATE, error, TAG,
event_obj->resource_hdl = xSemaphoreCreateBinary();
MB_GOTO_ON_FALSE((event_obj->resource_hdl), MB_EILLSTATE, error, TAG,
"%s, mb resource create failure.", inst->descr.parent_name);
pevent->event_group_hdl = xEventGroupCreate();
MB_GOTO_ON_FALSE((pevent->event_group_hdl), MB_EILLSTATE, error, TAG,
event_obj->event_group_hdl = xEventGroupCreate();
MB_GOTO_ON_FALSE((event_obj->event_group_hdl), MB_EILLSTATE, error, TAG,
"%s, event group create error.", inst->descr.parent_name);
pevent->event_hdl = xQueueCreate(MB_EVENT_QUEUE_SIZE, sizeof(mb_event_t));
MB_GOTO_ON_FALSE((pevent->event_hdl), MB_EILLSTATE, error, TAG, "%s, event queue create error.", inst->descr.parent_name);
vQueueAddToRegistry(pevent->event_hdl, TAG);
inst->event_obj = pevent;
atomic_init(&pevent->curr_err_type, EV_ERROR_INIT);
ESP_LOGD(TAG, "initialized object @%p", pevent);
event_obj->event_hdl = xQueueCreate(MB_EVENT_QUEUE_SIZE, sizeof(mb_event_t));
MB_GOTO_ON_FALSE((event_obj->event_hdl), MB_EILLSTATE, error, TAG, "%s, event queue create error.", inst->descr.parent_name);
vQueueAddToRegistry(event_obj->event_hdl, TAG);
inst->event_obj = event_obj;
atomic_init(&event_obj->curr_err_type, EV_ERROR_INIT);
ESP_LOGD(TAG, "initialized object @%p", event_obj);
return MB_ENOERR;
error:
if(pevent->event_hdl) {
vQueueDelete(pevent->event_hdl);
pevent->event_hdl = NULL;
if(event_obj->event_hdl) {
vQueueDelete(event_obj->event_hdl);
event_obj->event_hdl = NULL;
}
if (pevent->event_group_hdl) {
vEventGroupDelete(pevent->event_group_hdl);
pevent->event_group_hdl = NULL;
if (event_obj->event_group_hdl) {
vEventGroupDelete(event_obj->event_group_hdl);
event_obj->event_group_hdl = NULL;
}
if (pevent->resource_hdl) {
vSemaphoreDelete(pevent->resource_hdl);
pevent->resource_hdl = NULL;
if (event_obj->resource_hdl) {
vSemaphoreDelete(event_obj->resource_hdl);
event_obj->resource_hdl = NULL;
}
free(inst->event_obj);
free(event_obj);
inst->event_obj = NULL;
return ret;
}
@@ -104,40 +104,35 @@ bool mb_port_event_post(mb_port_base_t *inst, mb_event_t event)
result = xQueueSendFromISR(inst->event_obj->event_hdl,
(const void*)&temp_event, &high_prio_task_woken);
// Was the message posted successfully?
if (result == pdPASS) {
if (result != pdPASS) {
ESP_EARLY_LOGV(TAG, "%s, post message %x failure .", inst->descr.parent_name, temp_event.event);
return false;
}
// If high_prio_task_woken is now set to pdTRUE
// then a context switch should be requested.
if (high_prio_task_woken) {
portYIELD_FROM_ISR();
}
return true;
} else {
ESP_EARLY_LOGV(TAG, "%s, post message %x failure .", inst->descr.parent_name, temp_event.event);
return false;
}
if (high_prio_task_woken) {
portYIELD_FROM_ISR();
}
} else {
result = xQueueSend(inst->event_obj->event_hdl, (const void*)&temp_event, MB_EVENT_QUEUE_TIMEOUT_MAX);
if (result != pdTRUE) {
xQueueReset(inst->event_obj->event_hdl);
ESP_LOGE(TAG, "%s, post message failure.", inst->descr.parent_name);
return false;
}
}
return true;
}
bool mb_port_event_get(mb_port_base_t *inst, mb_event_t *pevent)
bool mb_port_event_get(mb_port_base_t *inst, mb_event_t *event)
{
MB_RETURN_ON_FALSE((inst && pevent && inst->event_obj && inst->event_obj->event_hdl), false, TAG,
MB_RETURN_ON_FALSE((inst && event && inst->event_obj && inst->event_obj->event_hdl), false, TAG,
"incorrect object handle.");
bool event_happened = false;
if (xQueueReceive(inst->event_obj->event_hdl, pevent, MB_EVENT_QUEUE_TIMEOUT_MAX) == pdTRUE) {
pevent->trans_id = atomic_load(&inst->event_obj->curr_trans_id);
pevent->get_ts = esp_timer_get_time();
if (xQueueReceive(inst->event_obj->event_hdl, event, MB_EVENT_QUEUE_TIMEOUT_MAX) == pdTRUE) {
event->trans_id = atomic_load(&inst->event_obj->curr_trans_id);
event->get_ts = esp_timer_get_time();
event_happened = true;
} else {
ESP_LOGD(TAG, "%s, get event timeout.", inst->descr.parent_name);
@@ -152,7 +147,7 @@ bool mb_port_event_res_take(mb_port_base_t *inst, uint32_t timeout)
BaseType_t status = pdTRUE;
status = xSemaphoreTake(inst->event_obj->resource_hdl, timeout);
ESP_LOGD(TAG, "%s, mb take resource, (%" PRIu32 " ticks).", inst->descr.parent_name, timeout);
return status;
return (bool)status;
}
void mb_port_event_res_release(mb_port_base_t *inst)
@@ -178,11 +173,11 @@ mb_err_enum_t mb_port_event_wait_req_finish(mb_port_base_t *inst)
"incorrect object handle.");
mb_err_enum_t err_status = MB_ENOERR;
mb_event_enum_t rcv_event;
EventBits_t bits = xEventGroupWaitBits(inst->event_obj->event_group_hdl, // The event group being tested.
EventBits_t bits = xEventGroupWaitBits(inst->event_obj->event_group_hdl,// The event group being tested.
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.
MB_EVENT_QUEUE_TIMEOUT_MAX); // Wait forever for either bit to be set.
MB_EVENT_QUEUE_TIMEOUT_MAX);// Wait forever for either bit to be set.
rcv_event = (mb_event_enum_t)(bits);
if (rcv_event) {
ESP_LOGD(TAG, "%s, %s: returned event = 0x%x", inst->descr.parent_name, __func__, (int)rcv_event);

View File

@@ -14,15 +14,15 @@
static _Atomic(uint32_t) inst_counter = 0;
/* ----------------------- Start implementation -----------------------------*/
int lock_obj(_lock_t *plock)
int lock_obj(_lock_t *lock_ptr)
{
_lock_acquire(plock);
_lock_acquire(lock_ptr);
return 1;
}
void unlock_obj(_lock_t *plock)
void unlock_obj(_lock_t *lock_ptr)
{
_lock_release(plock);
_lock_release(lock_ptr);
}
__attribute__((unused))
@@ -58,27 +58,27 @@ void queue_delete(QueueHandle_t queue)
vQueueDelete(queue);
}
esp_err_t queue_push(QueueHandle_t queue, void *pbuf, size_t len, frame_entry_t *pframe)
esp_err_t queue_push(QueueHandle_t queue, void *buf, size_t len, frame_entry_t *frame)
{
frame_entry_t frame_info = {0};
if (!queue) { // || !pbuf || (len <= 0)
if (!queue) { // || !buf || (len <= 0)
return -1;
}
if (pframe) {
frame_info = *pframe;
if (frame) {
frame_info = *frame;
}
if (pbuf && (len > 0)) {
if (!frame_info.pbuf) {
frame_info.pbuf = calloc(1, len);
if (buf && (len > 0)) {
if (!frame_info.buf) {
frame_info.buf = calloc(1, len);
}
if (!frame_info.pbuf) {
if (!frame_info.buf) {
return ESP_ERR_NO_MEM;
}
frame_info.len = len;
memcpy(frame_info.pbuf, pbuf, len);
memcpy(frame_info.buf, buf, len);
}
// try send to queue and check if the queue is full
@@ -88,25 +88,25 @@ esp_err_t queue_push(QueueHandle_t queue, void *pbuf, size_t len, frame_entry_t
return ESP_OK;
}
ssize_t queue_pop(QueueHandle_t queue, void *pbuf, size_t len, frame_entry_t *pframe)
ssize_t queue_pop(QueueHandle_t queue, void *buf, size_t len, frame_entry_t *frame)
{
TickType_t timeout = portMAX_DELAY;
frame_entry_t frame_info = {0};
if (xQueueReceive(queue, &frame_info, timeout) == pdTRUE) {
if (pframe) {
*pframe = frame_info;
if (frame) {
*frame = frame_info;
}
if (len > frame_info.len) {
len = frame_info.len;
}
// if the input buffer pointer is defined copy the data and free queued buffer,
// otherwise just return the frame entry
if (frame_info.pbuf && pbuf) {
memcpy(pbuf, frame_info.pbuf, len);
if (!pframe) {
free(frame_info.pbuf); // must free the buffer manually!
if (frame_info.buf && buf) {
memcpy(buf, frame_info.buf, len);
if (!frame) {
free(frame_info.buf); // must free the buffer manually!
}
}
} else {
@@ -126,8 +126,8 @@ void queue_flush(QueueHandle_t queue)
{
frame_entry_t frame_info;
while (xQueueReceive(queue, &frame_info, 0) == pdTRUE) {
if ((frame_info.len > 0) && frame_info.pbuf) {
free(frame_info.pbuf);
if ((frame_info.len > 0) && frame_info.buf) {
free(frame_info.buf);
}
}
}

View File

@@ -206,18 +206,19 @@ static void mb_port_ser_task(void *p_args)
mb_err_enum_t mb_port_ser_create(mb_serial_opts_t *ser_opts, mb_port_base_t **in_out_obj)
{
mb_ser_port_t *pserial = NULL;
mb_ser_port_t *ser_port = NULL;
esp_err_t err = ESP_OK;
__attribute__((unused)) mb_err_enum_t ret = MB_EILLSTATE;
pserial = (mb_ser_port_t*)calloc(1, sizeof(mb_ser_port_t));
MB_RETURN_ON_FALSE((pserial && in_out_obj), MB_EILLSTATE, TAG, "mb serial port creation error.");
CRITICAL_SECTION_INIT(pserial->base.lock);
pserial->base.descr = ((mb_port_base_t*)*in_out_obj)->descr;
ser_port = (mb_ser_port_t*)calloc(1, sizeof(mb_ser_port_t));
MB_GOTO_ON_FALSE((ser_port && in_out_obj), MB_EILLSTATE, error, TAG, "mb serial port creation error.");
CRITICAL_SECTION_INIT(ser_port->base.lock);
ser_port->base.descr = (*in_out_obj)->descr;
ser_opts->data_bits = ((ser_opts->data_bits > UART_DATA_5_BITS)
&& (ser_opts->data_bits < UART_DATA_BITS_MAX))
? ser_opts->data_bits : UART_DATA_8_BITS;
// Keep the UART communication options
pserial->ser_opts = *ser_opts;
ser_port->ser_opts = *ser_opts;
// Configure serial communication parameters
uart_config_t uart_cfg = {
.baud_rate = ser_opts->baudrate,
@@ -233,46 +234,46 @@ mb_err_enum_t mb_port_ser_create(mb_serial_opts_t *ser_opts, mb_port_base_t **in
#endif
};
// Set UART config
err = uart_param_config(pserial->ser_opts.port, &uart_cfg);
err = uart_param_config(ser_port->ser_opts.port, &uart_cfg);
MB_GOTO_ON_FALSE((err == ESP_OK), MB_EILLSTATE, error, TAG,
"%s, mb config failure, uart_param_config() returned (0x%x).", pserial->base.descr.parent_name, (int)err);
"%s, mb config failure, uart_param_config() returned (0x%x).", ser_port->base.descr.parent_name, (int)err);
// Install UART driver, and get the queue.
err = uart_driver_install(pserial->ser_opts.port, MB_BUFFER_SIZE, MB_BUFFER_SIZE,
MB_QUEUE_LENGTH, &pserial->uart_queue, MB_PORT_SERIAL_ISR_FLAG);
err = uart_driver_install(ser_port->ser_opts.port, MB_BUFFER_SIZE, MB_BUFFER_SIZE,
MB_QUEUE_LENGTH, &ser_port->uart_queue, MB_PORT_SERIAL_ISR_FLAG);
MB_GOTO_ON_FALSE((err == ESP_OK), MB_EILLSTATE, error, TAG,
"%s, mb serial driver failure, retuned (0x%x).", pserial->base.descr.parent_name, (int)err);
err = uart_set_rx_timeout(pserial->ser_opts.port, MB_SERIAL_TOUT);
"%s, mb serial driver failure, retuned (0x%x).", ser_port->base.descr.parent_name, (int)err);
err = uart_set_rx_timeout(ser_port->ser_opts.port, MB_SERIAL_TOUT);
MB_GOTO_ON_FALSE((err == ESP_OK), MB_EILLSTATE, error, TAG,
"%s, mb serial set rx timeout failure, returned (0x%x).", pserial->base.descr.parent_name, (int)err);
"%s, mb serial set rx timeout failure, returned (0x%x).", ser_port->base.descr.parent_name, (int)err);
// Set always timeout flag to trigger timeout interrupt even after rx fifo full
uart_set_always_rx_timeout(pserial->ser_opts.port, true);
MB_GOTO_ON_FALSE((mb_port_ser_bus_sema_init(&pserial->base)), MB_EILLSTATE, error, TAG,
"%s, mb serial bus semaphore create fail.", pserial->base.descr.parent_name);
uart_set_always_rx_timeout(ser_port->ser_opts.port, true);
MB_GOTO_ON_FALSE((mb_port_ser_bus_sema_init(&ser_port->base)), MB_EILLSTATE, error, TAG,
"%s, mb serial bus semaphore create fail.", ser_port->base.descr.parent_name);
// Suspend task on start and then resume when initialization is completed
atomic_store(&(pserial->enabled), false);
atomic_store(&(ser_port->enabled), false);
// Create a task to handle UART events
BaseType_t status = xTaskCreatePinnedToCore(mb_port_ser_task, "port_serial_task",
MB_SERIAL_TASK_STACK_SIZE,
&pserial->base, CONFIG_FMB_PORT_TASK_PRIO,
&pserial->task_handle, CONFIG_FMB_PORT_TASK_AFFINITY);
&ser_port->base, CONFIG_FMB_PORT_TASK_PRIO,
&ser_port->task_handle, CONFIG_FMB_PORT_TASK_AFFINITY);
// Force exit from function with failure
MB_GOTO_ON_FALSE((status == pdPASS), MB_EILLSTATE, error, TAG,
"%s, mb stack serial task creation error, returned (0x%x).",
pserial->base.descr.parent_name, (int)status);
*in_out_obj = &(pserial->base);
ESP_LOGD(TAG, "created object @%p", pserial);
ser_port->base.descr.parent_name, (int)status);
*in_out_obj = &(ser_port->base);
ESP_LOGD(TAG, "created object @%p", ser_port);
return MB_ENOERR;
error:
if (pserial) {
if (pserial->task_handle) {
vTaskDelete(pserial->task_handle);
if (ser_port) {
if (ser_port->task_handle) {
vTaskDelete(ser_port->task_handle);
}
uart_driver_delete(pserial->ser_opts.port);
CRITICAL_SECTION_CLOSE(pserial->base.lock);
mb_port_ser_bus_sema_close(&pserial->base);
uart_driver_delete(ser_port->ser_opts.port);
CRITICAL_SECTION_CLOSE(ser_port->base.lock);
mb_port_ser_bus_sema_close(&ser_port->base);
}
free(pserial);
free(ser_port);
return MB_EILLSTATE;
}
@@ -286,24 +287,23 @@ void mb_port_ser_delete(mb_port_base_t *inst)
free(port_obj);
}
bool mb_port_ser_recv_data(mb_port_base_t *inst, uint8_t **pp_ser_frame, uint16_t *p_ser_length)
bool mb_port_ser_recv_data(mb_port_base_t *inst, uint8_t **ser_frame, uint16_t *p_ser_length)
{
MB_RETURN_ON_FALSE((pp_ser_frame && p_ser_length), false, TAG, "mb serial get buffer failure.");
MB_RETURN_ON_FALSE((ser_frame && p_ser_length), false, TAG, "mb serial get buffer failure.");
mb_ser_port_t *port_obj = __containerof(inst, mb_ser_port_t, base);
uint16_t counter = *p_ser_length ? *p_ser_length : port_obj->recv_length;
bool status = false;
status = mb_port_ser_bus_sema_take(inst, pdMS_TO_TICKS(mb_port_timer_get_response_time_ms(inst)));
if (status && counter && *pp_ser_frame && atomic_load(&(port_obj->enabled))) {
if (status && counter && *ser_frame && atomic_load(&(port_obj->enabled))) {
// Read frame data from the ringbuffer of receiver
counter = uart_read_bytes(port_obj->ser_opts.port, (uint8_t *)*pp_ser_frame,
counter, MB_SERIAL_RX_TOUT_TICKS);
counter = uart_read_bytes(port_obj->ser_opts.port, *ser_frame, counter, MB_SERIAL_RX_TOUT_TICKS);
// Stop timer because the new data is received
mb_port_timer_disable(inst);
// Store the timestamp of received frame
port_obj->recv_time_stamp = esp_timer_get_time();
ESP_LOGD(TAG, "%s, received data: %d bytes.", inst->descr.parent_name, (int)counter);
ESP_LOG_BUFFER_HEX_LEVEL(MB_STR_CAT(inst->descr.parent_name, ":PORT_RECV"), (void *)*pp_ser_frame, counter, ESP_LOG_DEBUG);
MB_PRT_BUF(inst->descr.parent_name, ":PORT_RECV", ser_frame, counter, ESP_LOG_DEBUG);
int64_t time_delta = (port_obj->recv_time_stamp > port_obj->send_time_stamp) ?
(port_obj->recv_time_stamp - port_obj->send_time_stamp) :
(port_obj->send_time_stamp - port_obj->recv_time_stamp);
@@ -335,8 +335,7 @@ bool mb_port_ser_send_data(mb_port_base_t *inst, uint8_t *p_ser_frame, uint16_t
ESP_LOGD(TAG, "%s, tx buffer sent: (%d) bytes.", inst->descr.parent_name, (int)count);
MB_RETURN_ON_FALSE((status == ESP_OK), false, TAG, "%s, mb serial sent buffer failure.",
inst->descr.parent_name);
ESP_LOG_BUFFER_HEX_LEVEL(MB_STR_CAT(inst->descr.parent_name, ":PORT_SEND"),
(void *)p_ser_frame, ser_length, ESP_LOG_DEBUG);
MB_PRT_BUF(inst->descr.parent_name, ":PORT_SEND", p_ser_frame, ser_length, ESP_LOG_DEBUG);
port_obj->send_time_stamp = esp_timer_get_time();
} else {
ESP_LOGE(TAG, "%s, send fail state:%d, %p, %u. ", inst->descr.parent_name, (int)port_obj->tx_state_en, p_ser_frame, (unsigned)ser_length);
@@ -346,4 +345,3 @@ bool mb_port_ser_send_data(mb_port_base_t *inst, uint8_t *p_ser_frame, uint16_t
}
#endif

View File

@@ -18,13 +18,13 @@ extern "C" {
#endif
typedef enum _mb_comm_mode mb_mode_type_t;
typedef enum mb_comm_mode_enum mb_mode_type_t;
typedef struct mb_port_base_t mb_port_base_t;
#if (CONFIG_FMB_COMM_MODE_ASCII_EN || CONFIG_FMB_COMM_MODE_RTU_EN)
mb_err_enum_t mb_port_ser_create(mb_serial_opts_t *ser_opts, mb_port_base_t **port_obj);
bool mb_port_ser_recv_data(mb_port_base_t *inst, uint8_t **pp_ser_frame, uint16_t *p_ser_length);
mb_err_enum_t mb_port_ser_create(mb_serial_opts_t *ser_opts, mb_port_base_t **in_out_obj);
bool mb_port_ser_recv_data(mb_port_base_t *inst, uint8_t **ser_frame, uint16_t *p_ser_length);
bool mb_port_ser_send_data(mb_port_base_t *inst, uint8_t *p_ser_frame, uint16_t ser_length);
void mb_port_ser_enable(mb_port_base_t *inst);
void mb_port_ser_disable(mb_port_base_t *inst);

View File

@@ -36,16 +36,16 @@ mb_err_enum_t mbm_port_tcp_create(mb_tcp_opts_t *tcp_opts, mb_port_base_t **port
void mbm_port_tcp_delete(mb_port_base_t *inst);
void mbm_port_tcp_enable(mb_port_base_t *inst);
void mbm_port_tcp_disable(mb_port_base_t *inst);
bool mbm_port_tcp_send_data(mb_port_base_t *inst, uint8_t address, uint8_t *pframe, uint16_t length);
bool mbm_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **ppframe, uint16_t *plength);
bool mbm_port_tcp_send_data(mb_port_base_t *inst, uint8_t address, uint8_t *frame, uint16_t length);
bool mbm_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **frame, uint16_t *length);
bool mbm_port_tcp_add_slave_info(mb_port_base_t *inst, const uint16_t index, const char *ip_str, uint8_t uid);
mb_err_enum_t mbs_port_tcp_create(mb_tcp_opts_t *tcp_opts, mb_port_base_t **port_obj);
void mbs_port_tcp_delete(mb_port_base_t *inst);
void mbs_port_tcp_enable(mb_port_base_t *inst);
void mbs_port_tcp_disable(mb_port_base_t *inst);
bool mbs_port_tcp_send_data(mb_port_base_t *inst, uint8_t *pframe, uint16_t length);
bool mbs_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **ppframe, uint16_t *plength);
bool mbs_port_tcp_send_data(mb_port_base_t *inst, uint8_t *frame, uint16_t length);
bool mbs_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **frame, uint16_t *length);
#endif

View File

@@ -60,7 +60,7 @@ const char *driver_event_to_name_r(mb_driver_event_t event)
static esp_err_t init_event_fd(void *ctx)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
if (!mb_drv_loop_inst_counter) {
esp_vfs_eventfd_config_t config = MB_EVENTFD_CONFIG();
esp_err_t err = esp_vfs_eventfd_register(&config);
@@ -68,50 +68,50 @@ static esp_err_t init_event_fd(void *ctx)
ESP_LOGE(TAG, "eventfd registration fail.");
}
}
pdrv_ctx->event_fd = eventfd(0, 0);
MB_RETURN_ON_FALSE((pdrv_ctx->event_fd > 0), ESP_ERR_INVALID_STATE, TAG, "eventfd init error.");
return (pdrv_ctx->event_fd > 0) ? ESP_OK : ESP_ERR_INVALID_STATE;
drv_obj->event_fd = eventfd(0, 0);
MB_RETURN_ON_FALSE((drv_obj->event_fd > 0), ESP_ERR_INVALID_STATE, TAG, "eventfd init error.");
return (drv_obj->event_fd > 0) ? ESP_OK : ESP_ERR_INVALID_STATE;
}
static esp_err_t close_event_fd(void *ctx)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
if (mb_drv_loop_inst_counter) {
close(pdrv_ctx->event_fd);
close(drv_obj->event_fd);
} else {
ESP_LOGD(TAG, "close eventfd (%d).", (int)pdrv_ctx->event_fd);
ESP_LOGD(TAG, "close eventfd (%d).", (int)drv_obj->event_fd);
return esp_vfs_eventfd_unregister();
}
return ESP_OK;
}
int32_t write_event(void *ctx, mb_event_info_t *pevent)
int32_t write_event(void *ctx, mb_event_info_t *event)
{
MB_RETURN_ON_FALSE((pevent && ctx), -1, TAG, "wrong arguments.");
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
MB_RETURN_ON_FALSE((event && ctx), -1, TAG, "wrong arguments.");
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
esp_err_t err = esp_event_post_to(mb_drv_loop_handle,
MB_EVENT_BASE(ctx), (int32_t)pevent->event_id, pevent,
MB_EVENT_BASE(ctx), event->event_id, event,
sizeof(mb_event_info_t), MB_EVENT_TOUT);
if ((err != ESP_OK)) {
ESP_LOGE(TAG, "%p, event loop send fail, err = %d.", ctx, (int)err);
return -1;
}
// send eventfd to just trigger select
int32_t ret = write(pdrv_ctx->event_fd, (char *)&pevent->val, sizeof(mb_event_info_t));
return (ret == sizeof(mb_event_info_t)) ? pevent->event_id : -1;
int32_t ret = write(drv_obj->event_fd, (char *)&event->val, sizeof(mb_event_info_t));
return (ret == sizeof(mb_event_info_t)) ? event->event_id : -1;
}
static int32_t read_event(void *ctx, mb_event_info_t *pevent)
static int32_t read_event(void *ctx, mb_event_info_t *event)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
MB_RETURN_ON_FALSE(pevent, ESP_ERR_INVALID_STATE, TAG, "cannot get event.");
int ret = read(pdrv_ctx->event_fd, (char *)&pevent->val, sizeof(mb_event_info_t));
return (ret == sizeof(mb_event_info_t)) ? pevent->event_id : -1;
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
MB_RETURN_ON_FALSE(event, ESP_ERR_INVALID_STATE, TAG, "cannot get event.");
int ret = read(drv_obj->event_fd, (char *)&event->val, sizeof(mb_event_info_t));
return (ret == sizeof(mb_event_info_t)) ? event->event_id : -1;
}
static esp_err_t mb_drv_event_loop_init(void *ctx)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
esp_err_t err = ESP_OK;
/* Create Event loop without task (will be created separately)*/
esp_event_loop_args_t loop_args = {
@@ -123,8 +123,8 @@ static esp_err_t mb_drv_event_loop_init(void *ctx)
MB_RETURN_ON_FALSE(((err == ESP_OK) && mb_drv_loop_handle), ESP_ERR_INVALID_STATE,
TAG, "create event loop failed, err=%d.", (int)err);
}
pdrv_ctx->event_loop_hdl = mb_drv_loop_handle;
if (asprintf(&pdrv_ctx->loop_name, "loop:%p", ctx) == -1) {
drv_obj->event_loop_hdl = mb_drv_loop_handle;
if (asprintf(&drv_obj->loop_name, "loop:%p", ctx) == -1) {
abort();
}
return err;
@@ -132,15 +132,15 @@ static esp_err_t mb_drv_event_loop_init(void *ctx)
static esp_err_t mb_drv_event_loop_deinit(void *ctx)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
esp_err_t err = ESP_OK;
// delete event loop
MB_RETURN_ON_FALSE((mb_drv_loop_handle), ESP_ERR_INVALID_STATE,
TAG, "delete event loop failed.");
if (mb_drv_loop_inst_counter) {
ESP_LOGD(TAG, "delete loop inst: %s.", pdrv_ctx->loop_name);
free(pdrv_ctx->loop_name);
pdrv_ctx->loop_name = NULL;
ESP_LOGD(TAG, "delete loop inst: %s.", drv_obj->loop_name);
free(drv_obj->loop_name);
drv_obj->loop_name = NULL;
mb_drv_loop_inst_counter--;
}
if (!mb_drv_loop_inst_counter) {
@@ -155,38 +155,38 @@ static esp_err_t mb_drv_event_loop_deinit(void *ctx)
esp_err_t mb_drv_register_handler(void *ctx, mb_driver_event_num_t event_num, mb_event_handler_fp fp)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
esp_err_t ret = ESP_ERR_INVALID_STATE;
mb_driver_event_t event = MB_EVENT_FROM_NUM(event_num);
ESP_LOGD(TAG, "%p, event #%d, 0x%x, register.", pdrv_ctx, (int)event_num, (int)event);
MB_RETURN_ON_FALSE((pdrv_ctx->event_handler[event_num] == NULL), ESP_ERR_INVALID_ARG,
TAG, "%p, event handler %p, for event %x, is not empty.", pdrv_ctx, pdrv_ctx->event_handler[event_num], (int)event);
ESP_LOGD(TAG, "%p, event #%d, 0x%x, register.", drv_obj, (int)event_num, (int)event);
MB_RETURN_ON_FALSE((drv_obj->event_handler[event_num] == NULL), ESP_ERR_INVALID_ARG,
TAG, "%p, event handler %p, for event %x, is not empty.", drv_obj, drv_obj->event_handler[event_num], (int)event);
ret = esp_event_handler_instance_register_with(mb_drv_loop_handle, MB_EVENT_BASE(ctx), event,
fp, ctx, &pdrv_ctx->event_handler[event_num]);
ESP_LOGD(TAG, "%p, registered event handler %p, event 0x%x", pdrv_ctx, pdrv_ctx->event_handler[event_num], (int)event);
fp, ctx, &drv_obj->event_handler[event_num]);
ESP_LOGD(TAG, "%p, registered event handler %p, event 0x%x", drv_obj, drv_obj->event_handler[event_num], (int)event);
MB_RETURN_ON_FALSE((ret == ESP_OK), ESP_ERR_INVALID_STATE,
TAG, "%p, event handler %p, registration error.", pdrv_ctx, pdrv_ctx->event_handler[event_num]);
TAG, "%p, event handler %p, registration error.", drv_obj, drv_obj->event_handler[event_num]);
return ESP_OK;
}
esp_err_t mb_drv_unregister_handler(void *ctx, mb_driver_event_num_t event_num)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
esp_err_t ret = ESP_ERR_INVALID_STATE;
mb_driver_event_t event = MB_EVENT_FROM_NUM(event_num);
ESP_LOGD(TAG, "%p, event handler %p, event 0x%x, unregister.", pdrv_ctx, pdrv_ctx->event_handler[event_num], (int)event);
MB_RETURN_ON_FALSE((pdrv_ctx->event_handler[event_num]), ESP_ERR_INVALID_ARG,
TAG, "%p, event handler %p, for event %x, is incorrect.", pdrv_ctx, pdrv_ctx->event_handler[event_num], (int)event);
ESP_LOGD(TAG, "%p, event handler %p, event 0x%x, unregister.", drv_obj, drv_obj->event_handler[event_num], (int)event);
MB_RETURN_ON_FALSE((drv_obj->event_handler[event_num]), ESP_ERR_INVALID_ARG,
TAG, "%p, event handler %p, for event %x, is incorrect.", drv_obj, drv_obj->event_handler[event_num], (int)event);
ret = esp_event_handler_instance_unregister_with(mb_drv_loop_handle,
MB_EVENT_BASE(ctx), (int32_t)event, pdrv_ctx->event_handler[event_num]);
pdrv_ctx->event_handler[event_num] = NULL;
MB_EVENT_BASE(ctx), (int32_t)event, drv_obj->event_handler[event_num]);
drv_obj->event_handler[event_num] = NULL;
MB_RETURN_ON_FALSE((ret == ESP_OK), ESP_ERR_INVALID_STATE ,
TAG, "%p, event handler %p, instance unregister with, error = %d", pdrv_ctx, pdrv_ctx->event_handler[event_num], (int)ret);
TAG, "%p, event handler %p, instance unregister with, error = %d", drv_obj, drv_obj->event_handler[event_num], (int)ret);
return ESP_OK;
}
@@ -222,37 +222,37 @@ static void delete_queues(mb_node_info_t *pmb_node)
inline void mb_drv_lock(void *ctx)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
CRITICAL_SECTION_LOCK(pdrv_ctx->lock);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
CRITICAL_SECTION_LOCK(drv_obj->lock);
}
inline void mb_drv_unlock(void *ctx)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
CRITICAL_SECTION_UNLOCK(pdrv_ctx->lock);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
CRITICAL_SECTION_UNLOCK(drv_obj->lock);
}
__attribute__((unused))
mb_sock_state_t mb_drv_get_node_state(void *ctx, int fd)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mb_node_info_t *pnode = pdrv_ctx->mb_nodes[fd];
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
mb_node_info_t *pnode = drv_obj->mb_nodes[fd];
return (pnode) ? atomic_load(&pnode->addr_info.state) : MB_SOCK_STATE_UNDEF;
}
void mb_drv_check_suspend_shutdown(void *ctx)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
if (pdrv_ctx->close_done_sema) {
if (drv_obj->close_done_sema) {
mb_status_flags_t status = mb_drv_wait_status_flag(ctx, (MB_FLAG_SHUTDOWN | MB_FLAG_SUSPEND), 0);
ESP_LOGD(TAG, "%p, driver check shutdown (%d)...", ctx, (int)status);
if (status & MB_FLAG_SHUTDOWN) {
xSemaphoreGive(pdrv_ctx->close_done_sema);
xSemaphoreGive(drv_obj->close_done_sema);
ESP_LOGD(TAG, "%p, driver task shutdown...", ctx);
vTaskDelete(NULL);
} else if (status & MB_FLAG_SUSPEND) {
xSemaphoreGive(pdrv_ctx->close_done_sema);
xSemaphoreGive(drv_obj->close_done_sema);
ESP_LOGD(TAG, "%p, driver task is suspended...", ctx);
vTaskSuspend(NULL);
}
@@ -261,20 +261,20 @@ void mb_drv_check_suspend_shutdown(void *ctx)
mb_status_flags_t mb_drv_set_status_flag(void *ctx, mb_status_flags_t mask)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
return (mb_status_flags_t)xEventGroupSetBits(pdrv_ctx->status_flags_hdl, (EventBits_t)mask);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
return (mb_status_flags_t)xEventGroupSetBits(drv_obj->status_flags_hdl, (EventBits_t)mask);
}
mb_status_flags_t mb_drv_clear_status_flag(void *ctx, mb_status_flags_t mask)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
return (mb_status_flags_t)xEventGroupClearBits(pdrv_ctx->status_flags_hdl, (EventBits_t)mask);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
return (mb_status_flags_t)xEventGroupClearBits(drv_obj->status_flags_hdl, (EventBits_t)mask);
}
mb_status_flags_t mb_drv_wait_status_flag(void *ctx, mb_status_flags_t mask, TickType_t ticks)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
return (mb_status_flags_t)xEventGroupWaitBits(pdrv_ctx->status_flags_hdl,
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
return (mb_status_flags_t)xEventGroupWaitBits(drv_obj->status_flags_hdl,
(BaseType_t)(mask),
pdFALSE,
pdFALSE,
@@ -284,87 +284,87 @@ mb_status_flags_t mb_drv_wait_status_flag(void *ctx, mb_status_flags_t mask, Tic
int mb_drv_open(void *ctx, mb_uid_info_t addr_info, int flags)
{
int fd = UNDEF_FD;
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mb_node_info_t *pnode_info = NULL;
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
mb_node_info_t *node_ptr = NULL;
// Find free fd and initialize
for (fd = 0; fd < MB_MAX_FDS; fd++) {
pnode_info = pdrv_ctx->mb_nodes[fd];
if (!pnode_info) {
pnode_info = calloc(1, sizeof(mb_node_info_t));
node_ptr = drv_obj->mb_nodes[fd];
if (!node_ptr) {
node_ptr = calloc(1, sizeof(mb_node_info_t));
mb_drv_lock(ctx);
if (!pnode_info) {
if (!node_ptr) {
goto err;
}
ESP_LOGD(TAG, "%p, open vfd: %d, sl_addr: %02x, node: %s:%u",
ctx, fd, (int8_t)addr_info.uid,
addr_info.ip_addr_str, (unsigned)addr_info.port);
if (init_queues(pnode_info) != ESP_OK) {
if (init_queues(node_ptr) != ESP_OK) {
goto err;
}
if (pdrv_ctx->mb_node_open_count > MB_MAX_FDS) {
ESP_LOGD(TAG, "Exceeded maximum node count: %d", pdrv_ctx->mb_node_open_count);
if (drv_obj->mb_node_open_count > MB_MAX_FDS) {
ESP_LOGD(TAG, "Exceeded maximum node count: %d", drv_obj->mb_node_open_count);
goto err;
}
pdrv_ctx->mb_node_open_count++;
pnode_info->index = fd;
pnode_info->fd = fd;
pnode_info->sock_id = addr_info.fd;
pnode_info->error = -1;
pnode_info->recv_err = -1;
pnode_info->addr_info = addr_info;
//pnode_info->addr_info.ip_addr_str = NULL;
pnode_info->addr_info.index = fd;
pnode_info->send_time = esp_timer_get_time();
pnode_info->recv_time = esp_timer_get_time();
pnode_info->tid_counter = 0;
pnode_info->send_counter = 0;
pnode_info->recv_counter = 0;
pnode_info->is_blocking = ((flags & O_NONBLOCK) == 0);
pdrv_ctx->mb_nodes[fd] = pnode_info;
drv_obj->mb_node_open_count++;
node_ptr->index = fd;
node_ptr->fd = fd;
node_ptr->sock_id = addr_info.fd;
node_ptr->error = -1;
node_ptr->recv_err = -1;
node_ptr->addr_info = addr_info;
//node_ptr->addr_info.ip_addr_str = NULL;
node_ptr->addr_info.index = fd;
node_ptr->send_time = esp_timer_get_time();
node_ptr->recv_time = esp_timer_get_time();
node_ptr->tid_counter = 0;
node_ptr->send_counter = 0;
node_ptr->recv_counter = 0;
node_ptr->is_blocking = ((flags & O_NONBLOCK) == 0);
drv_obj->mb_nodes[fd] = node_ptr;
// mark opened node in the open set
FD_SET(fd, &pdrv_ctx->open_set);
FD_SET(fd, &drv_obj->open_set);
mb_drv_unlock(ctx);
MB_SET_NODE_STATE(pnode_info, MB_SOCK_STATE_OPENED);
MB_SET_NODE_STATE(node_ptr, MB_SOCK_STATE_OPENED);
DRIVER_SEND_EVENT(ctx, MB_EVENT_OPEN, fd);
return fd;
}
}
err:
delete_queues(pnode_info);
free(pnode_info);
pdrv_ctx->mb_nodes[fd] = NULL;
delete_queues(node_ptr);
free(node_ptr);
drv_obj->mb_nodes[fd] = NULL;
mb_drv_unlock(ctx);
return UNDEF_FD;
}
mb_node_info_t *mb_drv_get_node(void *ctx, int fd)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
return pdrv_ctx->mb_nodes[fd];
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
return drv_obj->mb_nodes[fd];
}
// writes data into tx queue
ssize_t mb_drv_write(void *ctx, int fd, const void *data, size_t size)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
ssize_t ret = -1;
if (size == 0) {
return 0;
}
mb_node_info_t *pnode_info = pdrv_ctx->mb_nodes[fd];
if (!pnode_info) {
mb_node_info_t *node_ptr = drv_obj->mb_nodes[fd];
if (!node_ptr) {
errno = EBADF;
return 0;
}
if (MB_GET_NODE_STATE(pnode_info) >= MB_SOCK_STATE_CONNECTED) {
if (queue_push(pnode_info->tx_queue, (void *)data, size, NULL) == ESP_OK) {
if (MB_GET_NODE_STATE(node_ptr) >= MB_SOCK_STATE_CONNECTED) {
if (queue_push(node_ptr->tx_queue, (void *)data, size, NULL) == ESP_OK) {
ret = size;
// Inform FSM that is new frame data is ready to be send
DRIVER_SEND_EVENT(ctx, MB_EVENT_SEND_DATA, pnode_info->index);
DRIVER_SEND_EVENT(ctx, MB_EVENT_SEND_DATA, node_ptr->index);
} else {
// I/O error
errno = EIO;
@@ -379,15 +379,15 @@ ssize_t mb_drv_write(void *ctx, int fd, const void *data, size_t size)
// reads data from rx queue
ssize_t mb_drv_read(void *ctx, int fd, void *data, size_t size)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mb_node_info_t *pnode_info = pdrv_ctx->mb_nodes[fd];
if (!pnode_info) {
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
mb_node_info_t *node_ptr = drv_obj->mb_nodes[fd];
if (!node_ptr) {
errno = EBADF;
return 0;
}
// fd might be in process of closing (close was already called but preempted)
if (MB_GET_NODE_STATE(pnode_info) < MB_SOCK_STATE_CONNECTED) {
if (MB_GET_NODE_STATE(node_ptr) < MB_SOCK_STATE_CONNECTED) {
// bad file desc
errno = EBADF;
return -1;
@@ -398,7 +398,7 @@ ssize_t mb_drv_read(void *ctx, int fd, void *data, size_t size)
}
ssize_t actual_size = -1;
if ((actual_size = queue_pop(pnode_info->rx_queue, data, size, NULL)) < 0) {
if ((actual_size = queue_pop(node_ptr->rx_queue, data, size, NULL)) < 0) {
errno = EAGAIN;
}
@@ -407,109 +407,109 @@ ssize_t mb_drv_read(void *ctx, int fd, void *data, size_t size)
int mb_drv_close(void *ctx, int fd)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mb_node_info_t *pnode_info = pdrv_ctx->mb_nodes[fd]; // get address of configuration
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
mb_node_info_t *node_ptr = drv_obj->mb_nodes[fd]; // get address of configuration
if (!pnode_info) {
if (!node_ptr) {
// not valid opened fd
errno = EBADF;
return -1;
}
mb_drv_lock(ctx);
// stop socket
if (MB_GET_NODE_STATE(pnode_info) != MB_SOCK_STATE_CLOSED) {
if (MB_GET_NODE_STATE(node_ptr) != MB_SOCK_STATE_CLOSED) {
// Do we need to close connection, if the close event is not run
if ((pnode_info->sock_id > 0) && (FD_ISSET(pnode_info->sock_id, &pdrv_ctx->conn_set)))
if ((node_ptr->sock_id > 0) && (FD_ISSET(node_ptr->sock_id, &drv_obj->conn_set)))
{
FD_CLR(pnode_info->sock_id, &pdrv_ctx->conn_set);
if (pdrv_ctx->node_conn_count)
FD_CLR(node_ptr->sock_id, &drv_obj->conn_set);
if (drv_obj->node_conn_count)
{
pdrv_ctx->node_conn_count--;
drv_obj->node_conn_count--;
}
}
port_close_connection((mb_node_info_t *)pnode_info);
port_close_connection(node_ptr);
}
MB_SET_NODE_STATE(pnode_info, MB_SOCK_STATE_CLOSED);
FD_CLR(fd, &pdrv_ctx->open_set);
delete_queues(pnode_info);
if (pdrv_ctx->mb_node_open_count) {
pdrv_ctx->mb_node_open_count--;
MB_SET_NODE_STATE(node_ptr, MB_SOCK_STATE_CLOSED);
FD_CLR(fd, &drv_obj->open_set);
delete_queues(node_ptr);
if (drv_obj->mb_node_open_count) {
drv_obj->mb_node_open_count--;
}
if (pnode_info->addr_info.node_name_str != pnode_info->addr_info.ip_addr_str) {
free((void *)pnode_info->addr_info.ip_addr_str); // node ip addr string shall be freed
if (node_ptr->addr_info.node_name_str != node_ptr->addr_info.ip_addr_str) {
free((void *)node_ptr->addr_info.ip_addr_str); // node ip addr string shall be freed
}
free((void *)pnode_info->addr_info.node_name_str);
pnode_info->addr_info.node_name_str = NULL;
pnode_info->addr_info.ip_addr_str = NULL;
free(pnode_info);
pdrv_ctx->mb_nodes[fd] = NULL;
free((void *)node_ptr->addr_info.node_name_str);
node_ptr->addr_info.node_name_str = NULL;
node_ptr->addr_info.ip_addr_str = NULL;
free(node_ptr);
drv_obj->mb_nodes[fd] = NULL;
mb_drv_unlock(ctx);
return 0;
}
mb_node_info_t *mb_drv_get_next_node_from_set(void *ctx, int *pfd, fd_set *pfdset)
mb_node_info_t *mb_drv_get_next_node_from_set(void *ctx, int *fd_ptr, fd_set *fdset)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
if (!pfdset || !pfd) {
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
if (!fdset || !fd_ptr) {
return NULL;
}
mb_node_info_t *pnode_info = NULL;
for (int fd = *pfd; fd < MB_MAX_FDS; fd++) {
pnode_info = pdrv_ctx->mb_nodes[fd];
if (pnode_info && (pnode_info->sock_id > 0)
&& (MB_GET_NODE_STATE(pnode_info) >= MB_SOCK_STATE_CONNECTED)
&& (FD_ISSET(pnode_info->index, pfdset) || (FD_ISSET(pnode_info->sock_id, pfdset)))) {
*pfd = fd;
//FD_CLR(pnode_info->sock_id, pfdset);
return pnode_info;
mb_node_info_t *node_ptr = NULL;
for (int fd = *fd_ptr; fd < MB_MAX_FDS; fd++) {
node_ptr = drv_obj->mb_nodes[fd];
if (node_ptr && (node_ptr->sock_id > 0)
&& (MB_GET_NODE_STATE(node_ptr) >= MB_SOCK_STATE_CONNECTED)
&& (FD_ISSET(node_ptr->index, fdset) || (FD_ISSET(node_ptr->sock_id, fdset)))) {
*fd_ptr = fd;
//FD_CLR(node_ptr->sock_id, fdset);
return node_ptr;
}
}
return NULL;
}
mb_node_info_t *mb_drv_get_node_info_from_addr(void *ctx, uint8_t node_addr)
mb_node_info_t *mb_drv_get_node_info_from_addr(void *ctx, uint8_t uid)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mb_node_info_t *pnode_info = NULL;
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
mb_node_info_t *node_ptr = NULL;
for (int fd = 0; fd < MB_MAX_FDS; fd++) {
pnode_info = pdrv_ctx->mb_nodes[fd];
if (pnode_info && pnode_info->addr_info.uid == node_addr) {
return pnode_info;
node_ptr = drv_obj->mb_nodes[fd];
if (node_ptr && node_ptr->addr_info.uid == uid) {
return node_ptr;
}
}
return NULL;
}
static int mb_drv_register_fds(void *ctx, fd_set *pfdset)
static int mb_drv_register_fds(void *ctx, fd_set *fdset)
{
mb_node_info_t *pnode_info = NULL;
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mb_node_info_t *node_ptr = NULL;
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
// Setup select waiting for eventfd && socket events
FD_ZERO(pfdset);
FD_ZERO(fdset);
int max_fd = UNDEF_FD;
// Add to the set all connected slaves
for (int i = 0; i < MB_MAX_FDS; i++) {
pnode_info = pdrv_ctx->mb_nodes[i];
if (pnode_info && pnode_info->sock_id && (MB_GET_NODE_STATE(pnode_info) >= MB_SOCK_STATE_CONNECTED)) {
MB_ADD_FD(pnode_info->sock_id, max_fd, pfdset);
node_ptr = drv_obj->mb_nodes[i];
if (node_ptr && node_ptr->sock_id && (MB_GET_NODE_STATE(node_ptr) >= MB_SOCK_STATE_CONNECTED)) {
MB_ADD_FD(node_ptr->sock_id, max_fd, fdset);
}
}
// Add event fd events to the set to handle them in one select
MB_ADD_FD(pdrv_ctx->event_fd, max_fd, pfdset);
MB_ADD_FD(drv_obj->event_fd, max_fd, fdset);
// Add listen socket to handle incoming connections (for slave only)
MB_ADD_FD(pdrv_ctx->listen_sock_fd, max_fd, pfdset);
MB_ADD_FD(drv_obj->listen_sock_fd, max_fd, fdset);
return max_fd;
}
// Wait socket ready event during timeout
static int mb_drv_wait_fd_events(void *ctx, fd_set *pfdset, fd_set *perrset, int time_ms)
static int mb_drv_wait_fd_events(void *ctx, fd_set *fdset, fd_set *perrset, int time_ms)
{
fd_set readset = *pfdset;
fd_set readset = *fdset;
int ret = 0;
struct timeval tv;
if (!ctx || !pfdset) {
if (!ctx || !fdset) {
return -1;
}
@@ -529,52 +529,52 @@ static int mb_drv_wait_fd_events(void *ctx, fd_set *pfdset, fd_set *perrset, int
} else if (ret < 0) {
ret = -1;
}
*pfdset = readset;
*fdset = readset;
return ret;
}
esp_err_t mb_drv_start_task(void *ctx)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
(void)mb_drv_clear_status_flag(ctx, MB_FLAG_SUSPEND);
ESP_LOGD(TAG, "%p, resume tcp driver task.", ctx);
vTaskResume(pdrv_ctx->mb_tcp_task_handle);
vTaskResume(drv_obj->mb_tcp_task_handle);
return ESP_OK;
}
esp_err_t mb_drv_stop_task(void *ctx)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
esp_err_t err = ESP_ERR_TIMEOUT;
if (!pdrv_ctx->close_done_sema) {
pdrv_ctx->close_done_sema = xSemaphoreCreateBinary();
if (!drv_obj->close_done_sema) {
drv_obj->close_done_sema = xSemaphoreCreateBinary();
}
(void)mb_drv_set_status_flag(ctx, MB_FLAG_SUSPEND);
// Check if we can safely suspend the port task (workaround for issue with deadlock in suspend)
if (!pdrv_ctx->close_done_sema
if (!drv_obj->close_done_sema
|| !(mb_drv_wait_status_flag(ctx, MB_FLAG_SUSPEND, 1) & MB_FLAG_SUSPEND)
|| (xSemaphoreTake(pdrv_ctx->close_done_sema, pdMS_TO_TICKS(MB_WAIT_DONE_MS)) != pdTRUE)
|| (xSemaphoreTake(drv_obj->close_done_sema, pdMS_TO_TICKS(MB_WAIT_DONE_MS)) != pdTRUE)
) {
ESP_LOGD(TAG, "%p, could not stop driver task during timeout.", ctx);
vTaskSuspend(pdrv_ctx->mb_tcp_task_handle);
vTaskSuspend(drv_obj->mb_tcp_task_handle);
err = ESP_OK;
}
ESP_LOGD(TAG, "%p, stop tcp driver task.", ctx);
if (pdrv_ctx->close_done_sema) {
vSemaphoreDelete(pdrv_ctx->close_done_sema);
pdrv_ctx->close_done_sema = NULL;
if (drv_obj->close_done_sema) {
vSemaphoreDelete(drv_obj->close_done_sema);
drv_obj->close_done_sema = NULL;
}
return err;
}
err_t mb_drv_check_node_state(void *ctx, int *pfd, uint32_t timeout_ms)
err_t mb_drv_check_node_state(void *ctx, int *fd_ptr, uint32_t timeout_ms)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
mb_node_info_t *pnode = NULL;
err_t err = ERR_TIMEOUT;
pnode = mb_drv_get_next_node_from_set(ctx, pfd, &pdrv_ctx->conn_set);
if (pnode && FD_ISSET(pnode->sock_id, &pdrv_ctx->conn_set)) {
pnode = mb_drv_get_next_node_from_set(ctx, fd_ptr, &drv_obj->conn_set);
if (pnode && FD_ISSET(pnode->sock_id, &drv_obj->conn_set)) {
uint64_t last_read_div_us = (esp_timer_get_time() - pnode->recv_time);
ESP_LOGD(TAG, "%p, node: %d, sock: %d, IP:%s, check connection timeout = %" PRId64 ", rcv_time: %" PRId64 " %" PRId32,
ctx, (int)pnode->index, (int)pnode->sock_id, pnode->addr_info.ip_addr_str,
@@ -597,10 +597,12 @@ err_t mb_drv_check_node_state(void *ctx, int *pfd, uint32_t timeout_ms)
void mb_drv_tcp_task(void *ctx)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
ESP_LOGD(TAG, "Start of driver task.");
while (1) {
fd_set readset, errorset;
FD_ZERO(&readset);
FD_ZERO(&errorset);
// check all active socket and fd events
int ret = mb_drv_wait_fd_events(ctx, &readset, &errorset, MB_SELECT_WAIT_MS);
if (ret == ERR_TIMEOUT) {
@@ -614,7 +616,7 @@ void mb_drv_tcp_task(void *ctx)
ESP_LOGD(TAG, "%p, socket error, fdset: %" PRIx64, ctx, *(uint64_t *)&errorset);
} else {
// Is the fd event triggered, process the event
if (pdrv_ctx->event_fd && FD_ISSET(pdrv_ctx->event_fd, &readset)) {
if (drv_obj->event_fd && FD_ISSET(drv_obj->event_fd, &readset)) {
mb_event_info_t mb_event = {0};
int32_t event_id = read_event(ctx, &mb_event);
ESP_LOGD(TAG, "%p, fd event get: 0x%02x:%d, %s",
@@ -625,15 +627,15 @@ void mb_drv_tcp_task(void *ctx)
if (err != ESP_OK) {
ESP_LOGE(TAG, "%p, event loop run, returns fail: %x", ctx, (int)err);
}
} else if (pdrv_ctx->listen_sock_fd && FD_ISSET(pdrv_ctx->listen_sock_fd, &readset)) {
} else if (drv_obj->listen_sock_fd && FD_ISSET(drv_obj->listen_sock_fd, &readset)) {
// If something happened on the listen socket, then it is an incoming connection.
ESP_LOGD(TAG, "%p, listen_sock is active.", ctx);
mb_uid_info_t node_info;
int sock_id = port_accept_connection(pdrv_ctx->listen_sock_fd, &node_info);
int sock_id = port_accept_connection(drv_obj->listen_sock_fd, &node_info);
if (sock_id) {
int fd = mb_drv_open(pdrv_ctx, node_info, 0);
int fd = mb_drv_open(drv_obj, node_info, 0);
if (fd < 0) {
ESP_LOGE(TAG, "%p, unable to open node: %s", pdrv_ctx, node_info.ip_addr_str);
ESP_LOGE(TAG, "%p, unable to open node: %s", drv_obj, node_info.ip_addr_str);
} else {
DRIVER_SEND_EVENT(ctx, MB_EVENT_CONNECT, fd);
}
@@ -642,38 +644,38 @@ void mb_drv_tcp_task(void *ctx)
// socket event is ready, process each socket event
mb_drv_check_suspend_shutdown(ctx);
int curr_fd = 0;
mb_node_info_t *pnode_info = NULL;
mb_node_info_t *node_ptr = NULL;
ESP_LOGD(TAG, "%p, socket event active: %" PRIx64, ctx, *(uint64_t *)&readset);
while(((pnode_info = mb_drv_get_next_node_from_set(ctx, &curr_fd, &readset))
while(((node_ptr = mb_drv_get_next_node_from_set(ctx, &curr_fd, &readset))
&& (curr_fd < MB_MAX_FDS))) {
if (FD_ISSET(pnode_info->sock_id, &pdrv_ctx->conn_set)) {
if (FD_ISSET(node_ptr->sock_id, &drv_obj->conn_set)) {
// The data is ready in the socket, read frame and queue
FD_CLR(pnode_info->sock_id, &readset);
int ret = port_read_packet(pnode_info);
FD_CLR(node_ptr->sock_id, &readset);
int ret = port_read_packet(node_ptr);
if (ret > 0) {
ESP_LOGD(TAG, "%p, "MB_NODE_FMT(", frame received."), ctx, (int)pnode_info->fd,
(int)pnode_info->sock_id, pnode_info->addr_info.ip_addr_str);
ESP_LOGD(TAG, "%p, "MB_NODE_FMT(", frame received."), ctx, (int)node_ptr->fd,
(int)node_ptr->sock_id, node_ptr->addr_info.ip_addr_str);
mb_drv_lock(ctx);
pnode_info->recv_time = esp_timer_get_time();
node_ptr->recv_time = esp_timer_get_time();
mb_drv_unlock(ctx);
DRIVER_SEND_EVENT(ctx, MB_EVENT_RECV_DATA, pnode_info->index);
DRIVER_SEND_EVENT(ctx, MB_EVENT_RECV_DATA, node_ptr->index);
} else if (ret == ERR_TIMEOUT) {
ESP_LOGD(TAG, "%p, "MB_NODE_FMT(", frame read timeout or closed connection."), ctx, (int)pnode_info->fd,
(int)pnode_info->sock_id, pnode_info->addr_info.ip_addr_str);
ESP_LOGD(TAG, "%p, "MB_NODE_FMT(", frame read timeout or closed connection."), ctx, (int)node_ptr->fd,
(int)node_ptr->sock_id, node_ptr->addr_info.ip_addr_str);
} else if (ret == ERR_BUF) {
// After retries a response with incorrect TID received, process failure.
pdrv_ctx->event_cbs.mb_sync_event_cb(pdrv_ctx->event_cbs.port_arg, MB_SYNC_EVENT_RECV_FAIL);
ESP_LOGD(TAG, "%p, "MB_NODE_FMT(", frame error."), ctx, (int)pnode_info->fd,
(int)pnode_info->sock_id, pnode_info->addr_info.ip_addr_str);
drv_obj->event_cbs.mb_sync_event_cb(drv_obj->event_cbs.port_arg, MB_SYNC_EVENT_RECV_FAIL);
ESP_LOGD(TAG, "%p, "MB_NODE_FMT(", frame error."), ctx, (int)node_ptr->fd,
(int)node_ptr->sock_id, node_ptr->addr_info.ip_addr_str);
} else {
if (ret == ERR_CONN) {
ESP_LOGD(TAG, "%p, "MB_NODE_FMT(", connection lost."), ctx, (int)pnode_info->fd,
(int)pnode_info->sock_id, pnode_info->addr_info.ip_addr_str);
DRIVER_SEND_EVENT(ctx, MB_EVENT_ERROR, pnode_info->index);
ESP_LOGD(TAG, "%p, "MB_NODE_FMT(", connection lost."), ctx, (int)node_ptr->fd,
(int)node_ptr->sock_id, node_ptr->addr_info.ip_addr_str);
DRIVER_SEND_EVENT(ctx, MB_EVENT_ERROR, node_ptr->index);
} else {
ESP_LOGD(TAG, "%p, "MB_NODE_FMT(", critical read error=%d, errno=%u."), ctx, (int)pnode_info->fd,
(int)pnode_info->sock_id, pnode_info->addr_info.ip_addr_str, (int)ret, (unsigned)errno);
DRIVER_SEND_EVENT(ctx, MB_EVENT_ERROR, pnode_info->index);
ESP_LOGD(TAG, "%p, "MB_NODE_FMT(", critical read error=%d, errno=%u."), ctx, (int)node_ptr->fd,
(int)node_ptr->sock_id, node_ptr->addr_info.ip_addr_str, (int)ret, (unsigned)errno);
DRIVER_SEND_EVENT(ctx, MB_EVENT_ERROR, node_ptr->index);
}
}
}
@@ -768,24 +770,24 @@ error:
esp_err_t mb_drv_unregister(void *ctx)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
ESP_LOGD(TAG, "%p, driver unregister.", pdrv_ctx);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
ESP_LOGD(TAG, "%p, driver unregister.", drv_obj);
(void)mb_drv_set_status_flag(ctx, MB_FLAG_SHUTDOWN);
pdrv_ctx->close_done_sema = xSemaphoreCreateBinary();
drv_obj->close_done_sema = xSemaphoreCreateBinary();
// if no semaphore (alloc issues) or couldn't acquire it, just delete the task
if (!pdrv_ctx->close_done_sema
if (!drv_obj->close_done_sema
|| !(mb_drv_wait_status_flag(ctx, MB_FLAG_SHUTDOWN, 0) & MB_FLAG_SHUTDOWN)
|| (xSemaphoreTake(pdrv_ctx->close_done_sema, pdMS_TO_TICKS(MB_WAIT_DONE_MS)) != pdTRUE)
|| (xSemaphoreTake(drv_obj->close_done_sema, pdMS_TO_TICKS(MB_WAIT_DONE_MS)) != pdTRUE)
) {
ESP_LOGD(TAG, "%p, driver tasks couldn't exit within timeout -> abruptly deleting the task.", pdrv_ctx);
vTaskDelete(pdrv_ctx->mb_tcp_task_handle);
ESP_LOGD(TAG, "%p, driver tasks couldn't exit within timeout -> abruptly deleting the task.", drv_obj);
vTaskDelete(drv_obj->mb_tcp_task_handle);
}
mb_drv_event_loop_deinit(ctx);
if (pdrv_ctx->close_done_sema) {
vSemaphoreDelete(pdrv_ctx->close_done_sema);
pdrv_ctx->close_done_sema = NULL;
if (drv_obj->close_done_sema) {
vSemaphoreDelete(drv_obj->close_done_sema);
drv_obj->close_done_sema = NULL;
}
esp_err_t err = close_event_fd(ctx);
@@ -793,38 +795,38 @@ esp_err_t mb_drv_unregister(void *ctx)
ESP_LOGE(TAG, "could not close the eventfd handle, err = %d. Already closed?", err);
}
if (pdrv_ctx->listen_sock_fd) {
shutdown(pdrv_ctx->listen_sock_fd, SHUT_RDWR);
close(pdrv_ctx->listen_sock_fd);
pdrv_ctx->listen_sock_fd = UNDEF_FD;
if (drv_obj->listen_sock_fd) {
shutdown(drv_obj->listen_sock_fd, SHUT_RDWR);
close(drv_obj->listen_sock_fd);
drv_obj->listen_sock_fd = UNDEF_FD;
}
for (int i = 0; i < MB_MAX_FDS; i++) {
mb_node_info_t *pnode_info = pdrv_ctx->mb_nodes[i];
if (pnode_info) {
ESP_LOGD(TAG, "%p, close node instance #%d(%s).", ctx, i, pnode_info->addr_info.node_name_str);
mb_node_info_t *node_ptr = drv_obj->mb_nodes[i];
if (node_ptr) {
ESP_LOGD(TAG, "%p, close node instance #%d(%s).", ctx, i, node_ptr->addr_info.node_name_str);
mb_drv_close(ctx, i);
}
}
free(pdrv_ctx->mb_nodes); // free the node info address array
pdrv_ctx->mb_nodes = NULL;
free(drv_obj->mb_nodes); // free the node info address array
drv_obj->mb_nodes = NULL;
vEventGroupDelete(pdrv_ctx->status_flags_hdl);
vEventGroupDelete(drv_obj->status_flags_hdl);
pdrv_ctx->is_registered = false;
CRITICAL_SECTION_CLOSE(pdrv_ctx->lock);
free(pdrv_ctx);
drv_obj->is_registered = false;
CRITICAL_SECTION_CLOSE(drv_obj->lock);
free(drv_obj);
return ESP_OK;
}
void mb_drv_set_cb(void *ctx, void *conn_cb, void *arg)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
mb_drv_lock(ctx);
pdrv_ctx->event_cbs.on_conn_done_cb = conn_cb;
pdrv_ctx->event_cbs.arg = arg;
drv_obj->event_cbs.on_conn_done_cb = conn_cb;
drv_obj->event_cbs.arg = arg;
mb_drv_unlock(ctx);
}

View File

@@ -90,15 +90,15 @@ typedef struct _port_driver port_driver_t;
#define MB_EVENT_BASE(context) (__extension__( \
{ \
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(context); \
(pdrv_ctx->loop_name) ? (esp_event_base_t)(pdrv_ctx->loop_name) : "UNK_BASE"; \
port_driver_t *drv_obj = MB_GET_DRV_PTR(context); \
(drv_obj->loop_name) ? (esp_event_base_t)(drv_obj->loop_name) : "UNK_BASE"; \
} \
))
#define MB_ADD_FD(fd, max_fd, pfdset) do { \
#define MB_ADD_FD(fd, max_fd, fdset) do { \
if (fd) { \
(max_fd = (fd > max_fd) ? fd : max_fd); \
FD_SET(fd, pfdset); \
FD_SET(fd, fdset); \
} \
} while(0)
@@ -106,15 +106,15 @@ typedef struct _port_driver port_driver_t;
// Macro for atomic operations
#define MB_ATOMIC_LOAD(ctx, addr) (__extension__( \
{ \
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx); \
(CRITICAL_LOAD(pdrv_ctx->lock, addr)); \
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx); \
(CRITICAL_LOAD(drv_obj->lock, addr)); \
} \
))
#define MB_ATOMIC_STORE(ctx, addr, val) (__extension__( \
{ \
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx); \
CRITICAL_STORE(pdrv_ctx->lock, addr, val); \
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx); \
CRITICAL_STORE(drv_obj->lock, addr, val); \
} \
))
@@ -122,11 +122,11 @@ typedef struct _port_driver port_driver_t;
// So, the eventfd value keeps last event and its fd.
#define DRIVER_SEND_EVENT(ctx, event, fd) (__extension__( \
{ \
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx); \
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx); \
mb_event_info_t (event_info##__FUNCTION__##__LINE__); \
(event_info##__FUNCTION__##__LINE__).event_id = (int32_t)event; \
(event_info##__FUNCTION__##__LINE__).opt_fd = fd; \
((write_event((void *)pdrv_ctx, &(event_info##__FUNCTION__##__LINE__)) > 0) \
((write_event((void *)drv_obj, &(event_info##__FUNCTION__##__LINE__)) > 0) \
? ((event_info##__FUNCTION__##__LINE__)).event_id : UNDEF_FD); \
} \
))
@@ -177,7 +177,7 @@ typedef union {
uint64_t val;
} mb_event_info_t;
typedef struct _mb_node_info {
typedef struct mb_node_info_s {
int index; /*!< slave information index */
int fd; /*!< slave global file descriptor */
int sock_id; /*!< socket ID of slave */
@@ -263,7 +263,7 @@ typedef struct _port_driver {
* @return esp_err_t
* - ESP_OK on success
*/
esp_err_t mb_drv_register(port_driver_t **config);
esp_err_t mb_drv_register(port_driver_t **ctx);
/**
* @brief Unregister modbus driver
@@ -317,7 +317,7 @@ ssize_t mb_drv_read(void *ctx, int fd, void *data, size_t size);
int mb_drv_close(void *ctx, int fd);
int32_t write_event(void *ctx, mb_event_info_t *pevent);
int32_t write_event(void *ctx, mb_event_info_t *event);
const char *driver_event_to_name_r(mb_driver_event_t event);
@@ -335,7 +335,7 @@ void mb_drv_lock(void *ctx);
void mb_drv_unlock(void *ctx);
mb_node_info_t *mb_drv_get_next_node_from_set(void *ctx, int *pfd, fd_set *pfdset);
mb_node_info_t *mb_drv_get_next_node_from_set(void *ctx, int *fd_ptr, fd_set *fdset);
mb_status_flags_t mb_drv_set_status_flag(void *ctx, mb_status_flags_t mask);

View File

@@ -19,45 +19,45 @@ typedef struct
// TCP communication properties
mb_tcp_opts_t tcp_opts;
uint8_t ptemp_buf[MB_TCP_BUFF_MAX_SIZE];
port_driver_t *pdriver;
port_driver_t *drv_obj;
} mbm_tcp_port_t;
/* ----------------------- Static variables & functions ----------------------*/
static const char *TAG = "mb_port.tcp.master";
static uint64_t mbm_port_tcp_sync_event(void *inst, mb_sync_event_t sync_event);
bool mbm_port_timer_expired(void *inst);
extern int port_scan_addr_string(char *buffer, mb_uid_info_t *pslave_info);
extern int port_scan_addr_string(char *buffer, mb_uid_info_t *info_ptr);
static esp_err_t mbm_port_tcp_register_handlers(void *ctx)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
esp_err_t ret = ESP_ERR_INVALID_STATE;
ret = mb_drv_register_handler(pdrv_ctx, MB_EVENT_READY_NUM, mbm_on_ready);
ret = mb_drv_register_handler(drv_obj, MB_EVENT_READY_NUM, mbm_on_ready);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_READY);
ret = mb_drv_register_handler(pdrv_ctx, MB_EVENT_OPEN_NUM, mbm_on_open);
ret = mb_drv_register_handler(drv_obj, MB_EVENT_OPEN_NUM, mbm_on_open);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_OPEN);
ret = mb_drv_register_handler(pdrv_ctx, MB_EVENT_RESOLVE_NUM, mbm_on_resolve);
ret = mb_drv_register_handler(drv_obj, MB_EVENT_RESOLVE_NUM, mbm_on_resolve);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_RESOLVE);
ret = mb_drv_register_handler(pdrv_ctx, MB_EVENT_CONNECT_NUM, mbm_on_connect);
ret = mb_drv_register_handler(drv_obj, MB_EVENT_CONNECT_NUM, mbm_on_connect);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_CONNECT);
ret = mb_drv_register_handler(pdrv_ctx, MB_EVENT_ERROR_NUM, mbm_on_error);
ret = mb_drv_register_handler(drv_obj, MB_EVENT_ERROR_NUM, mbm_on_error);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_ERROR);
ret = mb_drv_register_handler(pdrv_ctx, MB_EVENT_SEND_DATA_NUM, mbm_on_send_data);
ret = mb_drv_register_handler(drv_obj, MB_EVENT_SEND_DATA_NUM, mbm_on_send_data);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_SEND_DATA);
ret = mb_drv_register_handler(pdrv_ctx, MB_EVENT_RECV_DATA_NUM, mbm_on_recv_data);
ret = mb_drv_register_handler(drv_obj, MB_EVENT_RECV_DATA_NUM, mbm_on_recv_data);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_RECV_DATA);
ret = mb_drv_register_handler(pdrv_ctx, MB_EVENT_CLOSE_NUM, mbm_on_close);
ret = mb_drv_register_handler(drv_obj, MB_EVENT_CLOSE_NUM, mbm_on_close);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_CLOSE);
ret = mb_drv_register_handler(pdrv_ctx, MB_EVENT_TIMEOUT_NUM, mbm_on_timeout);
ret = mb_drv_register_handler(drv_obj, MB_EVENT_TIMEOUT_NUM, mbm_on_timeout);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_TIMEOUT);
return ESP_OK;
@@ -65,35 +65,35 @@ static esp_err_t mbm_port_tcp_register_handlers(void *ctx)
static esp_err_t mbm_port_tcp_unregister_handlers(void *ctx)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
esp_err_t ret = ESP_ERR_INVALID_STATE;
ESP_LOGD(TAG, "%p, event handler %p, unregister.", pdrv_ctx, pdrv_ctx->event_handler);
ESP_LOGD(TAG, "%p, event handler %p, unregister.", drv_obj, drv_obj->event_handler);
ret = mb_drv_unregister_handler(pdrv_ctx, MB_EVENT_READY_NUM);
ret = mb_drv_unregister_handler(drv_obj, MB_EVENT_READY_NUM);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_READY);
ret = mb_drv_unregister_handler(pdrv_ctx, MB_EVENT_OPEN_NUM);
ret = mb_drv_unregister_handler(drv_obj, MB_EVENT_OPEN_NUM);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_OPEN);
ret = mb_drv_unregister_handler(pdrv_ctx, MB_EVENT_RESOLVE_NUM);
ret = mb_drv_unregister_handler(drv_obj, MB_EVENT_RESOLVE_NUM);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_RESOLVE);
ret = mb_drv_unregister_handler(pdrv_ctx, MB_EVENT_CONNECT_NUM);
ret = mb_drv_unregister_handler(drv_obj, MB_EVENT_CONNECT_NUM);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_CONNECT);
ret = mb_drv_unregister_handler(pdrv_ctx, MB_EVENT_ERROR_NUM);
ret = mb_drv_unregister_handler(drv_obj, MB_EVENT_ERROR_NUM);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_ERROR);
ret = mb_drv_unregister_handler(pdrv_ctx, MB_EVENT_SEND_DATA_NUM);
ret = mb_drv_unregister_handler(drv_obj, MB_EVENT_SEND_DATA_NUM);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_SEND_DATA);
ret = mb_drv_unregister_handler(pdrv_ctx, MB_EVENT_RECV_DATA_NUM);
ret = mb_drv_unregister_handler(drv_obj, MB_EVENT_RECV_DATA_NUM);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_RECV_DATA);
ret = mb_drv_unregister_handler(pdrv_ctx, MB_EVENT_CLOSE_NUM);
ret = mb_drv_unregister_handler(drv_obj, MB_EVENT_CLOSE_NUM);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_CLOSE);
ret = mb_drv_unregister_handler(pdrv_ctx, MB_EVENT_TIMEOUT_NUM);
ret = mb_drv_unregister_handler(drv_obj, MB_EVENT_TIMEOUT_NUM);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_TIMEOUT);
return ESP_OK;
@@ -108,27 +108,27 @@ mb_err_enum_t mbm_port_tcp_create(mb_tcp_opts_t *tcp_opts, mb_port_base_t **port
ptcp = (mbm_tcp_port_t*)calloc(1, sizeof(mbm_tcp_port_t));
MB_GOTO_ON_FALSE(ptcp, MB_EILLSTATE, error, TAG, "mb tcp port creation error.");
ptcp->pdriver = NULL;
ptcp->drv_obj = NULL;
CRITICAL_SECTION_INIT(ptcp->base.lock);
ptcp->base.descr = ((mb_port_base_t *)*port_obj)->descr;
ptcp->base.descr = (*port_obj)->descr;
err = mb_drv_register(&ptcp->pdriver);
MB_GOTO_ON_FALSE(((err == ESP_OK) && ptcp->pdriver), MB_EILLSTATE, error,
err = mb_drv_register(&ptcp->drv_obj);
MB_GOTO_ON_FALSE(((err == ESP_OK) && ptcp->drv_obj), MB_EILLSTATE, error,
TAG, "mb tcp port driver registration failed, err = (%x).", (int)err);
ptcp->pdriver->parent = ptcp;
ptcp->drv_obj->parent = ptcp;
err = mbm_port_tcp_register_handlers(ptcp->pdriver);
MB_GOTO_ON_FALSE(((err == ESP_OK) && ptcp->pdriver), MB_EILLSTATE, error,
err = mbm_port_tcp_register_handlers(ptcp->drv_obj);
MB_GOTO_ON_FALSE(((err == ESP_OK) && ptcp->drv_obj), MB_EILLSTATE, error,
TAG, "mb tcp port driver event handlers registration failed, err = (%x).", (int)err);
ptcp->pdriver->network_iface_ptr = tcp_opts->ip_netif_ptr;
ptcp->pdriver->mb_proto = tcp_opts->mode;
ptcp->pdriver->port = tcp_opts->port;
ptcp->pdriver->uid = tcp_opts->uid;
ptcp->pdriver->is_master = true;
ptcp->pdriver->dns_name = tcp_opts->dns_name;
ptcp->pdriver->event_cbs.mb_sync_event_cb = mbm_port_tcp_sync_event;
ptcp->pdriver->event_cbs.port_arg = (void *)ptcp;
ptcp->drv_obj->network_iface_ptr = tcp_opts->ip_netif_ptr;
ptcp->drv_obj->mb_proto = tcp_opts->mode;
ptcp->drv_obj->port = tcp_opts->port;
ptcp->drv_obj->uid = tcp_opts->uid;
ptcp->drv_obj->is_master = true;
ptcp->drv_obj->dns_name = tcp_opts->dns_name;
ptcp->drv_obj->event_cbs.mb_sync_event_cb = mbm_port_tcp_sync_event;
ptcp->drv_obj->event_cbs.port_arg = (void *)ptcp;
ptcp->base.cb.tmr_expired = mbm_port_timer_expired;
ptcp->base.cb.tx_empty = NULL;
@@ -142,26 +142,26 @@ mb_err_enum_t mbm_port_tcp_create(mb_tcp_opts_t *tcp_opts, mb_port_base_t **port
int fd = 0;
while(*paddr_table) {
int res = port_scan_addr_string((char *)*paddr_table, &slave_address_info);
int res = port_scan_addr_string(*paddr_table, &slave_address_info);
if (res > 0) {
ESP_LOGD(TAG, "Config: %s, IP: %s, port: %d, slave_addr: %d, ip_ver: %s",
(char *)*paddr_table, slave_address_info.ip_addr_str, slave_address_info.port,
slave_address_info.uid, (slave_address_info.addr_type == MB_IPV4 ? "IPV4" : "IPV6"));
fd = mb_drv_open(ptcp->pdriver, slave_address_info, 0);
fd = mb_drv_open(ptcp->drv_obj, slave_address_info, 0);
if (fd < 0) {
ESP_LOGE(TAG, "%p, unable to open slave: %s", ptcp->pdriver, slave_address_info.ip_addr_str);
ESP_LOGE(TAG, "%p, unable to open slave: %s", ptcp->drv_obj, slave_address_info.ip_addr_str);
} else {
ESP_LOGD(TAG, "%p, open slave: %d, %s:%d",
ptcp->pdriver, fd, slave_address_info.ip_addr_str, slave_address_info.port);
ptcp->drv_obj, fd, slave_address_info.ip_addr_str, slave_address_info.port);
}
} else {
ESP_LOGE(TAG, "%p, unable to open slave: %s, check configuration.", ptcp->pdriver, (char *)*paddr_table);
ESP_LOGE(TAG, "%p, unable to open slave: %s, check configuration.", ptcp->drv_obj, (char *)*paddr_table);
}
paddr_table++;
}
#ifdef MB_MDNS_IS_INCLUDED
err = port_start_mdns_service(&ptcp->pdriver->dns_name, true, tcp_opts->uid, ptcp->pdriver->network_iface_ptr);
err = port_start_mdns_service(&ptcp->drv_obj->dns_name, true, tcp_opts->uid, ptcp->drv_obj->network_iface_ptr);
MB_GOTO_ON_FALSE((err == ESP_OK), MB_EILLSTATE, error,
TAG, "mb tcp port mdns service init failure.");
#endif
@@ -171,12 +171,12 @@ mb_err_enum_t mbm_port_tcp_create(mb_tcp_opts_t *tcp_opts, mb_port_base_t **port
return MB_ENOERR;
error:
if (ptcp && ptcp->drv_obj) {
#ifdef MB_MDNS_IS_INCLUDED
port_stop_mdns_service(&ptcp->pdriver->dns_name);
port_stop_mdns_service(&ptcp->drv_obj->dns_name);
#endif
if (ptcp && ptcp->pdriver) {
(void)mbm_port_tcp_unregister_handlers(ptcp->pdriver);
(void)mb_drv_unregister(ptcp->pdriver);
(void)mbm_port_tcp_unregister_handlers(ptcp->drv_obj);
(void)mb_drv_unregister(ptcp->drv_obj);
CRITICAL_SECTION_CLOSE(ptcp->base.lock);
// if the MDNS resolving is enabled, then free it
}
@@ -188,12 +188,12 @@ void mbm_port_tcp_delete(mb_port_base_t *inst)
{
mbm_tcp_port_t *port_obj = __containerof(inst, mbm_tcp_port_t, base);
esp_err_t err = MB_EILLSTATE;
err = mbm_port_tcp_unregister_handlers(port_obj->pdriver);
err = mbm_port_tcp_unregister_handlers(port_obj->drv_obj);
MB_RETURN_ON_FALSE((err == ESP_OK), ;, TAG, "mb tcp port can not unregister handlers.");
#ifdef MB_MDNS_IS_INCLUDED
port_stop_mdns_service(&port_obj->pdriver->dns_name);
port_stop_mdns_service(&port_obj->drv_obj->dns_name);
#endif
err = mb_drv_unregister(port_obj->pdriver);
err = mb_drv_unregister(port_obj->drv_obj);
if (err != ESP_OK) {
ESP_LOGE(TAG, "driver unregister fail, returns (0x%d).", (uint16_t)err);
}
@@ -204,75 +204,75 @@ void mbm_port_tcp_delete(mb_port_base_t *inst)
void mbm_port_tcp_enable(mb_port_base_t *inst)
{
mbm_tcp_port_t *port_obj = __containerof(inst, mbm_tcp_port_t, base);
(void)mb_drv_start_task(port_obj->pdriver);
(void)mb_drv_clear_status_flag(port_obj->pdriver, MB_FLAG_DISCONNECTED);
DRIVER_SEND_EVENT(port_obj->pdriver, MB_EVENT_RESOLVE, UNDEF_FD);
(void)mb_drv_start_task(port_obj->drv_obj);
(void)mb_drv_clear_status_flag(port_obj->drv_obj, MB_FLAG_DISCONNECTED);
DRIVER_SEND_EVENT(port_obj->drv_obj, MB_EVENT_RESOLVE, UNDEF_FD);
}
void mbm_port_tcp_disable(mb_port_base_t *inst)
{
mbm_tcp_port_t *port_obj = __containerof(inst, mbm_tcp_port_t, base);
// Change the state of all slaves to close
DRIVER_SEND_EVENT(port_obj->pdriver, MB_EVENT_CLOSE, UNDEF_FD);
(void)mb_drv_wait_status_flag(port_obj->pdriver, MB_FLAG_DISCONNECTED, pdMS_TO_TICKS(MB_RECONNECT_TIME_MS));
DRIVER_SEND_EVENT(port_obj->drv_obj, MB_EVENT_CLOSE, UNDEF_FD);
(void)mb_drv_wait_status_flag(port_obj->drv_obj, MB_FLAG_DISCONNECTED, pdMS_TO_TICKS(MB_RECONNECT_TIME_MS));
}
bool mbm_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **ppframe, uint16_t *plength)
bool mbm_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **frame, uint16_t *length)
{
mbm_tcp_port_t *port_obj = __containerof(inst, mbm_tcp_port_t, base);
mb_node_info_t *pinfo = port_obj->pdriver->mb_node_curr;
MB_RETURN_ON_FALSE((pinfo), false, TAG, "incorrect current slave pointer.");
mb_node_info_t *info_ptr = port_obj->drv_obj->mb_node_curr;
MB_RETURN_ON_FALSE((info_ptr), false, TAG, "incorrect current slave pointer.");
bool status = false;
size_t sz = mb_drv_read(port_obj->pdriver, pinfo->fd, port_obj->ptemp_buf, MB_BUFFER_SIZE);
size_t sz = mb_drv_read(port_obj->drv_obj, info_ptr->fd, port_obj->ptemp_buf, MB_BUFFER_SIZE);
if (sz > MB_TCP_FUNC) {
uint16_t tid_counter = MB_TCP_MBAP_GET_FIELD(port_obj->ptemp_buf, MB_TCP_TID);
if (tid_counter == (pinfo->tid_counter - 1)) {
*ppframe = port_obj->ptemp_buf;
*plength = sz;
if (tid_counter == (info_ptr->tid_counter - 1)) {
*frame = port_obj->ptemp_buf;
*length = sz;
ESP_LOGD(TAG, "%p, "MB_NODE_FMT(", get packet TID: 0x%04" PRIx16 ":0x%04" PRIx16 ", %p."),
port_obj->pdriver, pinfo->index, pinfo->sock_id, pinfo->addr_info.ip_addr_str,
(unsigned)tid_counter, (unsigned)pinfo->tid_counter, *ppframe);
port_obj->drv_obj, info_ptr->index, info_ptr->sock_id, info_ptr->addr_info.ip_addr_str,
(unsigned)tid_counter, (unsigned)info_ptr->tid_counter, *frame);
uint64_t time = 0;
time = port_get_timestamp() - pinfo->send_time;
ESP_LOGD(TAG, "%p, "MB_NODE_FMT(", processing time[us] = %ju."), port_obj->pdriver, pinfo->index,
pinfo->sock_id, pinfo->addr_info.ip_addr_str, time);
time = port_get_timestamp() - info_ptr->send_time;
ESP_LOGD(TAG, "%p, "MB_NODE_FMT(", processing time[us] = %ju."), port_obj->drv_obj, info_ptr->index,
info_ptr->sock_id, info_ptr->addr_info.ip_addr_str, time);
status = true;
} else {
ESP_LOGE(TAG, "%p, "MB_NODE_FMT(", drop packet TID: 0x%04" PRIx16 ":0x%04" PRIx16 ", %p."),
port_obj->pdriver, pinfo->index, pinfo->sock_id,
pinfo->addr_info.ip_addr_str, (unsigned)tid_counter, (unsigned)pinfo->tid_counter, *ppframe);
port_obj->drv_obj, info_ptr->index, info_ptr->sock_id,
info_ptr->addr_info.ip_addr_str, (unsigned)tid_counter, (unsigned)info_ptr->tid_counter, *frame);
}
}
return status;
}
bool mbm_port_tcp_send_data(mb_port_base_t *inst, uint8_t address, uint8_t *pframe, uint16_t length)
bool mbm_port_tcp_send_data(mb_port_base_t *inst, uint8_t address, uint8_t *frame, uint16_t length)
{
mbm_tcp_port_t *port_obj = __containerof(inst, mbm_tcp_port_t, base);
bool frame_sent = false;
// get slave descriptor from its address
mb_node_info_t *pinfo = (mb_node_info_t *)mb_drv_get_node_info_from_addr(port_obj->pdriver, address);
mb_node_info_t *info_ptr = mb_drv_get_node_info_from_addr(port_obj->drv_obj, address);
bool all_nodes_connected = mb_drv_wait_status_flag(port_obj->pdriver, MB_FLAG_CONNECTED, pdMS_TO_TICKS(MB_RECONNECT_TIME_MS));
bool all_nodes_connected = mb_drv_wait_status_flag(port_obj->drv_obj, MB_FLAG_CONNECTED, pdMS_TO_TICKS(MB_RECONNECT_TIME_MS));
MB_RETURN_ON_FALSE((all_nodes_connected && pinfo && (MB_GET_NODE_STATE(pinfo) >= MB_SOCK_STATE_CONNECTED)),
MB_RETURN_ON_FALSE((all_nodes_connected && info_ptr && (MB_GET_NODE_STATE(info_ptr) >= MB_SOCK_STATE_CONNECTED)),
false, TAG, "The node UID #%d, is not connected.", address);
if (pinfo && pframe) {
if (info_ptr && frame) {
// Apply TID field to the frame before send
MB_TCP_MBAP_SET_FIELD(pframe, MB_TCP_TID, pinfo->tid_counter);
pframe[MB_TCP_UID] = (uint8_t)(pinfo->addr_info.uid);
MB_TCP_MBAP_SET_FIELD(frame, MB_TCP_TID, info_ptr->tid_counter);
frame[MB_TCP_UID] = (uint8_t)(info_ptr->addr_info.uid);
}
ESP_LOGD(TAG, "%p, send fd: %d, sock_id: %d[%s], %p, len: %d",
port_obj->pdriver, pinfo->fd, pinfo->sock_id, pinfo->addr_info.ip_addr_str, pframe, length);
port_obj->drv_obj, info_ptr->fd, info_ptr->sock_id, info_ptr->addr_info.ip_addr_str, frame, length);
// Write data to the modbus driver send queue of the slave
int write_length = mb_drv_write(port_obj->pdriver, pinfo->fd, pframe, length);
int write_length = mb_drv_write(port_obj->drv_obj, info_ptr->fd, frame, length);
if (write_length) {
frame_sent = true;
} else {
@@ -286,7 +286,7 @@ bool mbm_port_tcp_send_data(mb_port_base_t *inst, uint8_t address, uint8_t *pfra
void mbm_port_tcp_set_conn_cb(mb_port_base_t *inst, void *conn_fp, void *arg)
{
mbm_tcp_port_t *port_obj = __containerof(inst, mbm_tcp_port_t, base);
mb_drv_set_cb(port_obj->pdriver, conn_fp, arg);
mb_drv_set_cb(port_obj->drv_obj, conn_fp, arg);
}
// Timer handler to check timeout of socket response
@@ -303,8 +303,8 @@ bool mbm_port_timer_expired(void *inst)
if (mb_port_get_cur_timer_mode(inst) == MB_TMODE_RESPOND_TIMEOUT) {
// It is now to check solution.
mb_event.event_id = MB_EVENT_TIMEOUT;
mb_event.opt_fd = port_obj->pdriver->curr_node_index;
err = esp_event_isr_post_to(port_obj->pdriver->event_loop_hdl, MB_EVENT_BASE(port_obj->pdriver),
mb_event.opt_fd = port_obj->drv_obj->curr_node_index;
err = esp_event_isr_post_to(port_obj->drv_obj->event_loop_hdl, MB_EVENT_BASE(port_obj->drv_obj),
(int32_t)MB_EVENT_TIMEOUT, (void *)&mb_event, sizeof(mb_event_info_t*), &task_unblocked);
if (err != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Timeout event send error: %d", err);
@@ -316,15 +316,15 @@ bool mbm_port_timer_expired(void *inst)
return need_poll;
}
mb_uid_info_t *mbm_port_tcp_get_slave_info(mb_port_base_t *inst, uint8_t slave_addr, mb_sock_state_t exp_state)
mb_uid_info_t *mbm_port_tcp_get_slave_info(mb_port_base_t *inst, uint8_t uid, mb_sock_state_t exp_state)
{
mbm_tcp_port_t *port_obj = __containerof(inst, mbm_tcp_port_t, base);
mb_uid_info_t *paddr_info = NULL;
mb_node_info_t *pinfo = mb_drv_get_node_info_from_addr(port_obj->pdriver, slave_addr);
if (pinfo && (MB_GET_NODE_STATE(pinfo) >= exp_state)) {
paddr_info = &pinfo->addr_info;
mb_uid_info_t *addr_info = NULL;
mb_node_info_t *info_ptr = mb_drv_get_node_info_from_addr(port_obj->drv_obj, uid);
if (info_ptr && (MB_GET_NODE_STATE(info_ptr) >= exp_state)) {
addr_info = &info_ptr->addr_info;
}
return paddr_info;
return addr_info;
}
static uint64_t mbm_port_tcp_sync_event(void *inst, mb_sync_event_t sync_event)
@@ -354,30 +354,30 @@ static uint64_t mbm_port_tcp_sync_event(void *inst, mb_sync_event_t sync_event)
MB_EVENT_HANDLER(mbm_on_ready)
{
// The driver is registered
mb_event_info_t *pevent_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)pevent_info->opt_fd);
mb_event_info_t *event_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)event_info->opt_fd);
}
MB_EVENT_HANDLER(mbm_on_open)
{
mb_event_info_t *pevent_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)pevent_info->opt_fd);
mb_event_info_t *event_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)event_info->opt_fd);
}
MB_EVENT_HANDLER(mbm_on_resolve)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mb_event_info_t *pevent_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)pevent_info->opt_fd);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
mb_event_info_t *event_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)event_info->opt_fd);
if (MB_CHECK_FD_RANGE(pevent_info->opt_fd)) {
ESP_LOGD(TAG, "%p, Node: %d, resolve.", ctx, (int)pevent_info->opt_fd);
if (MB_CHECK_FD_RANGE(event_info->opt_fd)) {
ESP_LOGD(TAG, "%p, Node: %d, resolve.", ctx, (int)event_info->opt_fd);
// The mdns is not used in the main app, then can use manually defined IPs
int fd = pevent_info->opt_fd;
mb_node_info_t *pslave = mb_drv_get_node(pdrv_ctx, fd);
int fd = event_info->opt_fd;
mb_node_info_t *pslave = mb_drv_get_node(drv_obj, fd);
if (pslave && (MB_GET_NODE_STATE(pslave) == MB_SOCK_STATE_OPENED)
&& FD_ISSET(pslave->index, &pdrv_ctx->open_set)) {
mb_status_flags_t status = mb_drv_wait_status_flag(pdrv_ctx, MB_FLAG_DISCONNECTED, 0);
&& FD_ISSET(pslave->index, &drv_obj->open_set)) {
mb_status_flags_t status = mb_drv_wait_status_flag(drv_obj, MB_FLAG_DISCONNECTED, 0);
if ((status & MB_FLAG_DISCONNECTED)) {
ESP_LOGV(TAG, "%p, slave: %d, sock: %d, IP:%s, disconnected.",
ctx, (int)pslave->index, (int)pslave->sock_id, pslave->addr_info.ip_addr_str);
@@ -391,7 +391,7 @@ MB_EVENT_HANDLER(mbm_on_resolve)
DRIVER_SEND_EVENT(ctx, MB_EVENT_CONNECT, pslave->index);
} else {
#ifdef MB_MDNS_IS_INCLUDED
int ret = port_resolve_mdns_host(pslave->addr_info.node_name_str, (char **)&pslave->addr_info.ip_addr_str);
int ret = port_resolve_mdns_host(pslave->addr_info.node_name_str, &pslave->addr_info.ip_addr_str);
if (ret > 0) {
ESP_LOGI(TAG, "%p, slave: %d, resolved with IP:%s.", ctx, (int)fd, pslave->addr_info.ip_addr_str);
MB_SET_NODE_STATE(pslave, MB_SOCK_STATE_RESOLVED);
@@ -406,17 +406,17 @@ MB_EVENT_HANDLER(mbm_on_resolve)
#endif
}
}
} else if (pevent_info->opt_fd < 0) {
} else if (event_info->opt_fd < 0) {
// Todo: query for services is removed from this version
// #ifdef MB_MDNS_IS_INCLUDED
// // If the mDNS feature support is enabled, use it to resolve the slave IP
// res = mb_drv_resolve_mdns_service(ctx, "_modbus", "_tcp", pdrv_ctx->addr_type);
// ESP_LOGD(TAG, "%p, use mdns to resolve slave: %d, resolved: %d devices.", ctx, (int)pevent_info->opt_fd, res);
// res = mb_drv_resolve_mdns_service(ctx, "_modbus", "_tcp", drv_obj->addr_type);
// ESP_LOGD(TAG, "%p, use mdns to resolve slave: %d, resolved: %d devices.", ctx, (int)event_info->opt_fd, res);
// #else
for (int fd = 0; fd < pdrv_ctx->mb_node_open_count; fd++) {
mb_node_info_t *pslave = mb_drv_get_node(pdrv_ctx, fd);
for (int fd = 0; fd < drv_obj->mb_node_open_count; fd++) {
mb_node_info_t *pslave = mb_drv_get_node(drv_obj, fd);
if (pslave && (MB_GET_NODE_STATE(pslave) == MB_SOCK_STATE_OPENED)
&& FD_ISSET(pslave->index, &pdrv_ctx->open_set)) {
&& FD_ISSET(pslave->index, &drv_obj->open_set)) {
DRIVER_SEND_EVENT(ctx, MB_EVENT_RESOLVE, pslave->index);
}
mb_drv_check_suspend_shutdown(ctx);
@@ -427,74 +427,74 @@ MB_EVENT_HANDLER(mbm_on_resolve)
MB_EVENT_HANDLER(mbm_on_connect)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mb_node_info_t *pnode_info = NULL;
mb_event_info_t *pevent_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)pevent_info->opt_fd);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
mb_node_info_t *node_ptr = NULL;
mb_event_info_t *event_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)event_info->opt_fd);
err_t err = ERR_CONN;
if (MB_CHECK_FD_RANGE(pevent_info->opt_fd)) {
pnode_info = mb_drv_get_node(pdrv_ctx, pevent_info->opt_fd);
if (pnode_info &&
(MB_GET_NODE_STATE(pnode_info) < MB_SOCK_STATE_CONNECTED) &&
(MB_GET_NODE_STATE(pnode_info) >= MB_SOCK_STATE_RESOLVED)) {
if (MB_CHECK_FD_RANGE(event_info->opt_fd)) {
node_ptr = mb_drv_get_node(drv_obj, event_info->opt_fd);
if (node_ptr &&
(MB_GET_NODE_STATE(node_ptr) < MB_SOCK_STATE_CONNECTED) &&
(MB_GET_NODE_STATE(node_ptr) >= MB_SOCK_STATE_RESOLVED)) {
ESP_LOGD(TAG, "%p, connection phase, slave: #%d(%d) [%s].",
ctx, (int)pevent_info->opt_fd, (int)pnode_info->sock_id, pnode_info->addr_info.ip_addr_str);
err = port_connect(ctx, pnode_info);
ctx, (int)event_info->opt_fd, (int)node_ptr->sock_id, node_ptr->addr_info.ip_addr_str);
err = port_connect(ctx, node_ptr);
switch (err) {
case ERR_OK:
FD_SET(pnode_info->sock_id, &pdrv_ctx->conn_set);
FD_SET(node_ptr->sock_id, &drv_obj->conn_set);
mb_drv_lock(ctx);
pdrv_ctx->node_conn_count++;
drv_obj->node_conn_count++;
// Update time stamp for connected slaves
pnode_info->send_time = esp_timer_get_time();
pnode_info->recv_time = esp_timer_get_time();
node_ptr->send_time = esp_timer_get_time();
node_ptr->recv_time = esp_timer_get_time();
mb_drv_unlock(ctx);
ESP_LOGI(TAG, "%p, slave: #%d, sock:%d, IP: %s, is connected.",
ctx, (int)pevent_info->opt_fd, (int)pnode_info->sock_id,
pnode_info->addr_info.ip_addr_str);
MB_SET_NODE_STATE(pnode_info, MB_SOCK_STATE_CONNECTED);
(void)port_keep_alive(pnode_info->sock_id);
ctx, (int)event_info->opt_fd, (int)node_ptr->sock_id,
node_ptr->addr_info.ip_addr_str);
MB_SET_NODE_STATE(node_ptr, MB_SOCK_STATE_CONNECTED);
(void)port_keep_alive(node_ptr->sock_id);
ESP_LOGD(TAG, "Opened/connected: %u, %u.",
(unsigned)pdrv_ctx->mb_node_open_count, (unsigned)pdrv_ctx->node_conn_count);
if (pdrv_ctx->mb_node_open_count == pdrv_ctx->node_conn_count) {
if (pdrv_ctx->event_cbs.on_conn_done_cb) {
pdrv_ctx->event_cbs.on_conn_done_cb(pdrv_ctx->event_cbs.arg);
(unsigned)drv_obj->mb_node_open_count, (unsigned)drv_obj->node_conn_count);
if (drv_obj->mb_node_open_count == drv_obj->node_conn_count) {
if (drv_obj->event_cbs.on_conn_done_cb) {
drv_obj->event_cbs.on_conn_done_cb(drv_obj->event_cbs.arg);
}
ESP_LOGI(TAG, "%p, Connected: %u, %u, start polling.",
ctx, (unsigned)pdrv_ctx->mb_node_open_count, (unsigned)pdrv_ctx->node_conn_count);
ctx, (unsigned)drv_obj->mb_node_open_count, (unsigned)drv_obj->node_conn_count);
mb_drv_set_status_flag(ctx, MB_FLAG_CONNECTED);
}
break;
case ERR_INPROGRESS:
if (FD_ISSET(pnode_info->sock_id, &pdrv_ctx->conn_set)) {
FD_CLR(pnode_info->sock_id, &pdrv_ctx->conn_set);
if (FD_ISSET(node_ptr->sock_id, &drv_obj->conn_set)) {
FD_CLR(node_ptr->sock_id, &drv_obj->conn_set);
ESP_LOGD(TAG, "%p, slave: #%d, sock:%d, IP:%s, connect fail error = %d.",
ctx, (int)pevent_info->opt_fd, (int)pnode_info->sock_id,
pnode_info->addr_info.ip_addr_str, (int)err);
ctx, (int)event_info->opt_fd, (int)node_ptr->sock_id,
node_ptr->addr_info.ip_addr_str, (int)err);
mb_drv_lock(ctx);
if (pdrv_ctx->node_conn_count) {
pdrv_ctx->node_conn_count--;
if (drv_obj->node_conn_count) {
drv_obj->node_conn_count--;
}
mb_drv_unlock(ctx);
DRIVER_SEND_EVENT(ctx, MB_EVENT_CLOSE, pevent_info->opt_fd);
port_close_connection(pnode_info);
DRIVER_SEND_EVENT(ctx, MB_EVENT_CLOSE, event_info->opt_fd);
port_close_connection(node_ptr);
} else {
ESP_LOGD(TAG, "%p, slave: #%d, sock:%d, IP:%s, connection is in progress.",
ctx, (int)pevent_info->opt_fd, (int)pnode_info->sock_id,
pnode_info->addr_info.ip_addr_str);
MB_SET_NODE_STATE(pnode_info, MB_SOCK_STATE_CONNECTING);
ctx, (int)event_info->opt_fd, (int)node_ptr->sock_id,
node_ptr->addr_info.ip_addr_str);
MB_SET_NODE_STATE(node_ptr, MB_SOCK_STATE_CONNECTING);
vTaskDelay(MB_CONN_TICK_TIMEOUT);
// try to connect to slave and check connection again if it is not connected
DRIVER_SEND_EVENT(ctx, MB_EVENT_CONNECT, pevent_info->opt_fd);
DRIVER_SEND_EVENT(ctx, MB_EVENT_CONNECT, event_info->opt_fd);
}
break;
case ERR_CONN:
ESP_LOGE(TAG, "Modbus connection phase, slave: %d (%s), connection error (%d).",
(int)pevent_info->opt_fd, pnode_info->addr_info.ip_addr_str, (int)err);
(int)event_info->opt_fd, node_ptr->addr_info.ip_addr_str, (int)err);
break;
default:
ESP_LOGE(TAG, "Invalid error state, slave: %d (%s), error = %d.",
(int)pevent_info->opt_fd, pnode_info->addr_info.ip_addr_str, (int)err);
(int)event_info->opt_fd, node_ptr->addr_info.ip_addr_str, (int)err);
break;
}
}
@@ -502,13 +502,13 @@ MB_EVENT_HANDLER(mbm_on_connect)
// if the event fd is UNDEF_FD (an event for all slaves),
// then perform connection phase for all resolved slaves sending the connection event
for (int node = 0; (node < MB_TCP_PORT_MAX_CONN); node++) {
pnode_info = mb_drv_get_node(pdrv_ctx, node);
if (pnode_info &&
(MB_GET_NODE_STATE(pnode_info) < MB_SOCK_STATE_CONNECTED) &&
(MB_GET_NODE_STATE(pnode_info) >= MB_SOCK_STATE_RESOLVED)) {
if (((pnode_info->sock_id < 0) || !FD_ISSET(pnode_info->sock_id, &pdrv_ctx->conn_set))
&& FD_ISSET(node, &pdrv_ctx->open_set)) {
DRIVER_SEND_EVENT(ctx, MB_EVENT_CONNECT, pnode_info->index);
node_ptr = mb_drv_get_node(drv_obj, node);
if (node_ptr &&
(MB_GET_NODE_STATE(node_ptr) < MB_SOCK_STATE_CONNECTED) &&
(MB_GET_NODE_STATE(node_ptr) >= MB_SOCK_STATE_RESOLVED)) {
if (((node_ptr->sock_id < 0) || !FD_ISSET(node_ptr->sock_id, &drv_obj->conn_set))
&& FD_ISSET(node, &drv_obj->open_set)) {
DRIVER_SEND_EVENT(ctx, MB_EVENT_CONNECT, node_ptr->index);
}
}
mb_drv_check_suspend_shutdown(ctx);
@@ -518,39 +518,39 @@ MB_EVENT_HANDLER(mbm_on_connect)
MB_EVENT_HANDLER(mbm_on_error)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mb_event_info_t *pevent_info = (mb_event_info_t *)data;
mb_node_info_t *pnode_info = NULL;
if (MB_CHECK_FD_RANGE(pevent_info->opt_fd)) {
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
mb_event_info_t *event_info = (mb_event_info_t *)data;
mb_node_info_t *node_ptr = NULL;
if (MB_CHECK_FD_RANGE(event_info->opt_fd)) {
mb_drv_check_suspend_shutdown(ctx);
mb_status_flags_t status = mb_drv_wait_status_flag(pdrv_ctx, MB_FLAG_DISCONNECTED, 1);
mb_status_flags_t status = mb_drv_wait_status_flag(drv_obj, MB_FLAG_DISCONNECTED, 1);
if ((status & MB_FLAG_DISCONNECTED)) {
ESP_LOGE(TAG, "%p, node: %d, is in disconnected state.", ctx, (int)pevent_info->opt_fd);
ESP_LOGE(TAG, "%p, node: %d, is in disconnected state.", ctx, (int)event_info->opt_fd);
mb_drv_clear_status_flag(ctx, MB_FLAG_CONNECTED);
return;
}
int ret = mb_drv_check_node_state(pdrv_ctx, (int *)&pevent_info->opt_fd, MB_RECONNECT_TIME_MS);
int ret = mb_drv_check_node_state(drv_obj, (int *)&event_info->opt_fd, MB_RECONNECT_TIME_MS);
if ((ret != ERR_OK) && (ret != ERR_TIMEOUT)) {
pnode_info = mb_drv_get_node(pdrv_ctx, pevent_info->opt_fd);
ESP_LOGW(TAG, "%p, "MB_NODE_FMT(", error handling."), ctx, (int)pnode_info->fd,
(int)pnode_info->sock_id, pnode_info->addr_info.ip_addr_str);
ESP_LOGE(TAG, "Node: %d, try to repair lost connection, err= %d", (int)pevent_info->opt_fd, ret);
FD_CLR(pnode_info->sock_id, &pdrv_ctx->conn_set);
node_ptr = mb_drv_get_node(drv_obj, event_info->opt_fd);
ESP_LOGW(TAG, "%p, "MB_NODE_FMT(", error handling."), ctx, (int)node_ptr->fd,
(int)node_ptr->sock_id, node_ptr->addr_info.ip_addr_str);
ESP_LOGE(TAG, "Node: %d, try to repair lost connection, err= %d", (int)event_info->opt_fd, ret);
FD_CLR(node_ptr->sock_id, &drv_obj->conn_set);
mb_drv_lock(ctx);
if (pdrv_ctx->node_conn_count) {
pdrv_ctx->node_conn_count--;
if (drv_obj->node_conn_count) {
drv_obj->node_conn_count--;
}
mb_drv_unlock(ctx);
port_close_connection(pnode_info);
DRIVER_SEND_EVENT(ctx, MB_EVENT_RESOLVE, pnode_info->index);
port_close_connection(node_ptr);
DRIVER_SEND_EVENT(ctx, MB_EVENT_RESOLVE, node_ptr->index);
}
} else if (pevent_info->opt_fd < 0) {
} else if (event_info->opt_fd < 0) {
// send resolve event to all slaves
for (int fd = 0; fd < pdrv_ctx->mb_node_open_count; fd++) {
for (int fd = 0; fd < drv_obj->mb_node_open_count; fd++) {
mb_drv_check_suspend_shutdown(ctx);
mb_node_info_t *pslave = mb_drv_get_node(pdrv_ctx, fd);
mb_node_info_t *pslave = mb_drv_get_node(drv_obj, fd);
if (pslave && (MB_GET_NODE_STATE(pslave) == MB_SOCK_STATE_OPENED)
&& FD_ISSET(pslave->index, &pdrv_ctx->open_set)) {
&& FD_ISSET(pslave->index, &drv_obj->open_set)) {
DRIVER_SEND_EVENT(ctx, MB_EVENT_RESOLVE, pslave->index);
}
}
@@ -559,48 +559,48 @@ MB_EVENT_HANDLER(mbm_on_error)
MB_EVENT_HANDLER(mbm_on_send_data)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mb_event_info_t *pevent_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)pevent_info->opt_fd);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
mb_event_info_t *event_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)event_info->opt_fd);
mb_drv_check_suspend_shutdown(ctx);
mb_node_info_t *pinfo = mb_drv_get_node(pdrv_ctx, pevent_info->opt_fd);
if (pinfo && !queue_is_empty(pinfo->tx_queue)) {
mb_node_info_t *info_ptr = mb_drv_get_node(drv_obj, event_info->opt_fd);
if (info_ptr && !queue_is_empty(info_ptr->tx_queue)) {
uint8_t tx_buffer[MB_TCP_BUFF_MAX_SIZE] = {0};
ESP_LOGD(TAG, "%p, get info: %d, sock_id: %d, queue_state: %d, state: %d.",
ctx, (int)pevent_info->opt_fd, (int)pinfo->sock_id,
(int)queue_is_empty(pinfo->tx_queue), (int)MB_GET_NODE_STATE(pinfo));
size_t sz = queue_pop(pinfo->tx_queue, tx_buffer, sizeof(tx_buffer), NULL);
if (MB_GET_NODE_STATE(pinfo) < MB_SOCK_STATE_CONNECTED) {
ctx, (int)event_info->opt_fd, (int)info_ptr->sock_id,
(int)queue_is_empty(info_ptr->tx_queue), (int)MB_GET_NODE_STATE(info_ptr));
size_t sz = queue_pop(info_ptr->tx_queue, tx_buffer, sizeof(tx_buffer), NULL);
if (MB_GET_NODE_STATE(info_ptr) < MB_SOCK_STATE_CONNECTED) {
// if slave is not connected, drop data.
ESP_LOGE(TAG, "%p, "MB_NODE_FMT(", is invalid, drop send data."),
ctx, (int)pinfo->index, (int)pinfo->sock_id, pinfo->addr_info.ip_addr_str);
ctx, (int)info_ptr->index, (int)info_ptr->sock_id, info_ptr->addr_info.ip_addr_str);
return;
}
int ret = port_write_poll(pinfo, tx_buffer, sz, MB_TCP_SEND_TIMEOUT_MS);
int ret = port_write_poll(info_ptr, tx_buffer, sz, MB_TCP_SEND_TIMEOUT_MS);
if (ret < 0) {
ESP_LOGE(TAG, "%p, "MB_NODE_FMT(", send data failure, err(errno) = %d(%u)."),
ctx, (int)pinfo->index, (int)pinfo->sock_id,
pinfo->addr_info.ip_addr_str, (int)ret, (unsigned)errno);
DRIVER_SEND_EVENT(ctx, MB_EVENT_ERROR, pinfo->index);
pinfo->error = ret;
ctx, (int)info_ptr->index, (int)info_ptr->sock_id,
info_ptr->addr_info.ip_addr_str, (int)ret, (unsigned)errno);
DRIVER_SEND_EVENT(ctx, MB_EVENT_ERROR, info_ptr->index);
info_ptr->error = ret;
} else {
ESP_LOGD(TAG, "%p, "MB_NODE_FMT(", send data successful: TID:0x%04x, %d (bytes), errno %d"),
ctx, (int)pinfo->index, (int)pinfo->sock_id,
pinfo->addr_info.ip_addr_str, (unsigned)pinfo->tid_counter, (int)ret, (unsigned)errno);
pinfo->error = 0;
ctx, (int)info_ptr->index, (int)info_ptr->sock_id,
info_ptr->addr_info.ip_addr_str, (unsigned)info_ptr->tid_counter, (int)ret, (unsigned)errno);
info_ptr->error = 0;
// Every successful write increase TID counter
if (pinfo->tid_counter < (USHRT_MAX - 1)) {
pinfo->tid_counter++;
if (info_ptr->tid_counter < (USHRT_MAX - 1)) {
info_ptr->tid_counter++;
} else {
pinfo->tid_counter = (uint16_t)(pinfo->index << 8U);
info_ptr->tid_counter = (uint16_t)(info_ptr->index << 8U);
}
}
pdrv_ctx->event_cbs.mb_sync_event_cb(pdrv_ctx->event_cbs.port_arg, MB_SYNC_EVENT_SEND_OK);
drv_obj->event_cbs.mb_sync_event_cb(drv_obj->event_cbs.port_arg, MB_SYNC_EVENT_SEND_OK);
mb_drv_lock(ctx);
pdrv_ctx->mb_node_curr = pinfo;
pdrv_ctx->curr_node_index = pinfo->index;
pinfo->send_time = esp_timer_get_time();
pinfo->send_counter = (pinfo->send_counter < (USHRT_MAX - 1)) ? (pinfo->send_counter + 1) : 0;
drv_obj->mb_node_curr = info_ptr;
drv_obj->curr_node_index = info_ptr->index;
info_ptr->send_time = esp_timer_get_time();
info_ptr->send_counter = (info_ptr->send_counter < (USHRT_MAX - 1)) ? (info_ptr->send_counter + 1) : 0;
mb_drv_unlock(ctx);
// Get send buffer from stack
ESP_LOG_BUFFER_HEX_LEVEL("SENT", tx_buffer, sz, ESP_LOG_DEBUG);
@@ -609,30 +609,30 @@ MB_EVENT_HANDLER(mbm_on_send_data)
MB_EVENT_HANDLER(mbm_on_recv_data)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mb_event_info_t *pevent_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)pevent_info->opt_fd);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
mb_event_info_t *event_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)event_info->opt_fd);
size_t sz = 0;
uint8_t pbuf[MB_TCP_BUFF_MAX_SIZE] = {0};
uint8_t buf[MB_TCP_BUFF_MAX_SIZE] = {0};
mb_drv_check_suspend_shutdown(ctx);
// Get frame from queue, check for correctness, push back correct frame and generate receive condition.
// Removes incorrect or expired frames from the queue, leave just correct one then sent sync event
mb_node_info_t *pnode_info = mb_drv_get_node(pdrv_ctx, pevent_info->opt_fd);
if (pnode_info) {
ESP_LOGD(TAG, "%p, slave #%d(%d) [%s], receive data ready.", ctx, (int)pevent_info->opt_fd,
(int)pnode_info->sock_id, pnode_info->addr_info.ip_addr_str);
while ((sz <= 0) && !queue_is_empty(pnode_info->rx_queue)) {
size_t sz = queue_pop(pnode_info->rx_queue, pbuf, MB_TCP_BUFF_MAX_SIZE, NULL);
if ((sz > MB_TCP_FUNC) && (sz < sizeof(pbuf))) {
uint16_t tid = MB_TCP_MBAP_GET_FIELD(pbuf, MB_TCP_TID);
mb_node_info_t *node_ptr = mb_drv_get_node(drv_obj, event_info->opt_fd);
if (node_ptr) {
ESP_LOGD(TAG, "%p, slave #%d(%d) [%s], receive data ready.", ctx, (int)event_info->opt_fd,
(int)node_ptr->sock_id, node_ptr->addr_info.ip_addr_str);
while ((sz <= 0) && !queue_is_empty(node_ptr->rx_queue)) {
size_t sz = queue_pop(node_ptr->rx_queue, buf, MB_TCP_BUFF_MAX_SIZE, NULL);
if ((sz > MB_TCP_FUNC) && (sz < sizeof(buf))) {
uint16_t tid = MB_TCP_MBAP_GET_FIELD(buf, MB_TCP_TID);
ESP_LOGD(TAG, "%p, packet TID: 0x%04" PRIx16 " received.", ctx, tid);
if (tid == (pnode_info->tid_counter - 1)) {
queue_push(pnode_info->rx_queue, pbuf, sz, NULL);
if (tid == (node_ptr->tid_counter - 1)) {
queue_push(node_ptr->rx_queue, buf, sz, NULL);
mb_drv_lock(ctx);
pnode_info->recv_time = esp_timer_get_time();
node_ptr->recv_time = esp_timer_get_time();
mb_drv_unlock(ctx);
// send receive event to modbus object
pdrv_ctx->event_cbs.mb_sync_event_cb(pdrv_ctx->event_cbs.port_arg, MB_SYNC_EVENT_RECV_OK);
drv_obj->event_cbs.mb_sync_event_cb(drv_obj->event_cbs.port_arg, MB_SYNC_EVENT_RECV_OK);
break;
}
}
@@ -643,32 +643,32 @@ MB_EVENT_HANDLER(mbm_on_recv_data)
MB_EVENT_HANDLER(mbm_on_close)
{
mb_event_info_t *pevent_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s, fd: %d", (char *)base, __func__, (int)pevent_info->opt_fd);
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mb_event_info_t *event_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s, fd: %d", (char *)base, __func__, (int)event_info->opt_fd);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
mb_node_info_t *pnode = NULL;
// if close all sockets event is received
if (pevent_info->opt_fd < 0) {
if (event_info->opt_fd < 0) {
ESP_LOGD(TAG, "%p, Close all nodes...", ctx);
(void)mb_drv_clear_status_flag(pdrv_ctx, MB_FLAG_DISCONNECTED);
(void)mb_drv_clear_status_flag(drv_obj, MB_FLAG_DISCONNECTED);
for (int fd = 0; fd < MB_MAX_FDS; fd++) {
mb_node_info_t *pnode = mb_drv_get_node(pdrv_ctx, fd);
mb_node_info_t *pnode = mb_drv_get_node(drv_obj, fd);
if (pnode && (MB_GET_NODE_STATE(pnode) >= MB_SOCK_STATE_OPENED)
&& FD_ISSET(pnode->index, &pdrv_ctx->open_set)) {
&& FD_ISSET(pnode->index, &drv_obj->open_set)) {
// Close node immediately
mb_drv_close(pdrv_ctx, fd);
mb_drv_close(drv_obj, fd);
MB_SET_NODE_STATE(pnode, MB_SOCK_STATE_READY);
ESP_LOGD(TAG, "%p, Close node %d, sock #%d.", ctx, fd, pnode->sock_id);
}
}
(void)mb_drv_set_status_flag(pdrv_ctx, MB_FLAG_DISCONNECTED);
(void)mb_drv_set_status_flag(drv_obj, MB_FLAG_DISCONNECTED);
mb_drv_check_suspend_shutdown(ctx);
} else if (MB_CHECK_FD_RANGE(pevent_info->opt_fd)) {
pnode = mb_drv_get_node(pdrv_ctx, pevent_info->opt_fd);
} else if (MB_CHECK_FD_RANGE(event_info->opt_fd)) {
pnode = mb_drv_get_node(drv_obj, event_info->opt_fd);
if (pnode && (MB_GET_NODE_STATE(pnode) >= MB_SOCK_STATE_OPENED)) {
ESP_LOGD(TAG, "%p, Close node %d, sock #%d, intentionally.", ctx, (int)pevent_info->opt_fd, pnode->sock_id);
if ((pnode->sock_id < 0) && FD_ISSET(pnode->sock_id, &pdrv_ctx->open_set)) {
mb_drv_close(pdrv_ctx, pevent_info->opt_fd);
ESP_LOGD(TAG, "%p, Close node %d, sock #%d, intentionally.", ctx, (int)event_info->opt_fd, pnode->sock_id);
if ((pnode->sock_id < 0) && FD_ISSET(pnode->sock_id, &drv_obj->open_set)) {
mb_drv_close(drv_obj, event_info->opt_fd);
}
}
mb_drv_check_suspend_shutdown(ctx);
@@ -678,8 +678,8 @@ MB_EVENT_HANDLER(mbm_on_close)
MB_EVENT_HANDLER(mbm_on_timeout)
{
// Socket read/write timeout is triggered
mb_event_info_t *pevent_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)pevent_info->opt_fd);
mb_event_info_t *event_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)event_info->opt_fd);
// Todo: this event can be used to check network state (kkep empty for now)
mb_drv_check_suspend_shutdown(ctx);
}

View File

@@ -23,8 +23,8 @@ extern "C" {
#if (CONFIG_FMB_COMM_MODE_TCP_EN)
typedef enum _mb_sock_state mb_sock_state_t;
typedef struct _uid_info mb_uid_info_t;
typedef enum mb_sock_state_enum mb_sock_state_t;
typedef struct uid_info_s mb_uid_info_t;
void mbm_port_tcp_set_conn_cb(mb_port_base_t *inst, void *conn_fp, void *arg);
mb_uid_info_t *mbm_port_tcp_get_slave_info(mb_port_base_t *inst, uint8_t uid, mb_sock_state_t exp_state);

View File

@@ -26,7 +26,7 @@ typedef struct
mb_uid_info_t addr_info;
uint8_t ptemp_buf[MB_TCP_BUFF_MAX_SIZE];
// The driver object for the slave
port_driver_t *pdriver;
port_driver_t *drv_obj;
transaction_handle_t transaction;
uint16_t trans_count;
} mbs_tcp_port_t;
@@ -38,31 +38,31 @@ static uint64_t mbs_port_tcp_sync_event(void *inst, mb_sync_event_t sync_event);
static esp_err_t mbs_port_tcp_register_handlers(void *ctx)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
esp_err_t ret = ESP_ERR_INVALID_STATE;
ret = mb_drv_register_handler(pdrv_ctx, MB_EVENT_READY_NUM, mbs_on_ready);
ret = mb_drv_register_handler(drv_obj, MB_EVENT_READY_NUM, mbs_on_ready);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_READY);
ret = mb_drv_register_handler(pdrv_ctx, MB_EVENT_OPEN_NUM, mbs_on_open);
ret = mb_drv_register_handler(drv_obj, MB_EVENT_OPEN_NUM, mbs_on_open);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_OPEN);
ret = mb_drv_register_handler(pdrv_ctx, MB_EVENT_CONNECT_NUM, mbs_on_connect);
ret = mb_drv_register_handler(drv_obj, MB_EVENT_CONNECT_NUM, mbs_on_connect);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_CONNECT);
ret = mb_drv_register_handler(pdrv_ctx, MB_EVENT_ERROR_NUM, mbs_on_error);
ret = mb_drv_register_handler(drv_obj, MB_EVENT_ERROR_NUM, mbs_on_error);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_ERROR);
ret = mb_drv_register_handler(pdrv_ctx, MB_EVENT_SEND_DATA_NUM, mbs_on_send_data);
ret = mb_drv_register_handler(drv_obj, MB_EVENT_SEND_DATA_NUM, mbs_on_send_data);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_SEND_DATA);
ret = mb_drv_register_handler(pdrv_ctx, MB_EVENT_RECV_DATA_NUM, mbs_on_recv_data);
ret = mb_drv_register_handler(drv_obj, MB_EVENT_RECV_DATA_NUM, mbs_on_recv_data);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_RECV_DATA);
ret = mb_drv_register_handler(pdrv_ctx, MB_EVENT_CLOSE_NUM, mbs_on_close);
ret = mb_drv_register_handler(drv_obj, MB_EVENT_CLOSE_NUM, mbs_on_close);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_CLOSE);
ret = mb_drv_register_handler(pdrv_ctx, MB_EVENT_TIMEOUT_NUM, mbs_on_timeout);
ret = mb_drv_register_handler(drv_obj, MB_EVENT_TIMEOUT_NUM, mbs_on_timeout);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_TIMEOUT);
return ESP_OK;
@@ -70,29 +70,29 @@ static esp_err_t mbs_port_tcp_register_handlers(void *ctx)
static esp_err_t mbs_port_tcp_unregister_handlers(void *ctx)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
esp_err_t ret = ESP_ERR_INVALID_STATE;
ESP_LOGD(TAG, "%p, event handler %p, unregister.", pdrv_ctx, pdrv_ctx->event_handler);
ESP_LOGD(TAG, "%p, event handler %p, unregister.", drv_obj, drv_obj->event_handler);
ret = mb_drv_unregister_handler(pdrv_ctx, MB_EVENT_READY_NUM);
ret = mb_drv_unregister_handler(drv_obj, MB_EVENT_READY_NUM);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_READY);
ret = mb_drv_unregister_handler(pdrv_ctx, MB_EVENT_OPEN_NUM);
ret = mb_drv_unregister_handler(drv_obj, MB_EVENT_OPEN_NUM);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_OPEN);
ret = mb_drv_unregister_handler(pdrv_ctx, MB_EVENT_CONNECT_NUM);
ret = mb_drv_unregister_handler(drv_obj, MB_EVENT_CONNECT_NUM);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_CONNECT);
ret = mb_drv_unregister_handler(pdrv_ctx, MB_EVENT_SEND_DATA_NUM);
ret = mb_drv_unregister_handler(drv_obj, MB_EVENT_SEND_DATA_NUM);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_SEND_DATA);
ret = mb_drv_unregister_handler(pdrv_ctx, MB_EVENT_RECV_DATA_NUM);
ret = mb_drv_unregister_handler(drv_obj, MB_EVENT_RECV_DATA_NUM);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_RECV_DATA);
ret = mb_drv_unregister_handler(pdrv_ctx, MB_EVENT_CLOSE_NUM);
ret = mb_drv_unregister_handler(drv_obj, MB_EVENT_CLOSE_NUM);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_CLOSE);
ret = mb_drv_unregister_handler(pdrv_ctx, MB_EVENT_TIMEOUT_NUM);
ret = mb_drv_unregister_handler(drv_obj, MB_EVENT_TIMEOUT_NUM);
MB_RETURN_ON_FALSE((ret == ESP_OK), MB_EINVAL, TAG,
"%x, mb tcp port event registration failed.", (int)MB_EVENT_TIMEOUT);
return ESP_OK;
@@ -103,39 +103,40 @@ mb_err_enum_t mbs_port_tcp_create(mb_tcp_opts_t *tcp_opts, mb_port_base_t **port
MB_RETURN_ON_FALSE((port_obj && tcp_opts), MB_EINVAL, TAG, "mb tcp port invalid arguments.");
mbs_tcp_port_t *ptcp = NULL;
esp_err_t err = ESP_ERR_INVALID_STATE;
ptcp = (mbs_tcp_port_t *)calloc(1, sizeof(mbs_tcp_port_t));
MB_RETURN_ON_FALSE((ptcp && port_obj), MB_EILLSTATE, TAG, "mb tcp port creation error.");
CRITICAL_SECTION_INIT(ptcp->base.lock);
mb_err_enum_t ret = MB_EILLSTATE;
ptcp = (mbs_tcp_port_t *)calloc(1, sizeof(mbs_tcp_port_t));
MB_GOTO_ON_FALSE((ptcp && port_obj), MB_EILLSTATE, error, TAG, "mb tcp port creation error.");
CRITICAL_SECTION_INIT(ptcp->base.lock);
// Copy object descriptor from parent object (is used for logging)
ptcp->base.descr = ((mb_port_base_t *)*port_obj)->descr;
ptcp->pdriver = NULL;
ptcp->base.descr = (*port_obj)->descr;
ptcp->drv_obj = NULL;
ptcp->transaction = transaction_init();
MB_GOTO_ON_FALSE((ptcp->transaction), MB_EILLSTATE, error,
TAG, "mb transaction init failed.");
ESP_MEM_CHECK(TAG, ptcp->transaction, goto error);
err = mb_drv_register(&ptcp->pdriver);
MB_GOTO_ON_FALSE(((err == ESP_OK) && ptcp->pdriver), MB_EILLSTATE, error,
err = mb_drv_register(&ptcp->drv_obj);
MB_GOTO_ON_FALSE(((err == ESP_OK) && ptcp->drv_obj), MB_EILLSTATE, error,
TAG, "mb tcp port driver registration failed, err = (%x).", (int)err);
err = mbs_port_tcp_register_handlers(ptcp->pdriver);
MB_GOTO_ON_FALSE(((err == ESP_OK) && ptcp->pdriver), MB_EILLSTATE, error,
err = mbs_port_tcp_register_handlers(ptcp->drv_obj);
MB_GOTO_ON_FALSE(((err == ESP_OK) && ptcp->drv_obj), MB_EILLSTATE, error,
TAG, "mb tcp port driver registration failed, err = (%x).", (int)err);
ptcp->pdriver->parent = ptcp; // just for logging purposes
ptcp->drv_obj->parent = ptcp; // just for logging purposes
ptcp->tcp_opts = *tcp_opts;
ptcp->pdriver->network_iface_ptr = tcp_opts->ip_netif_ptr;
ptcp->pdriver->mb_proto = tcp_opts->mode;
ptcp->pdriver->uid = tcp_opts->uid;
ptcp->pdriver->is_master = false;
ptcp->pdriver->event_cbs.mb_sync_event_cb = mbs_port_tcp_sync_event;
ptcp->pdriver->event_cbs.port_arg = (void *)ptcp;
ptcp->drv_obj->network_iface_ptr = tcp_opts->ip_netif_ptr;
ptcp->drv_obj->mb_proto = tcp_opts->mode;
ptcp->drv_obj->uid = tcp_opts->uid;
ptcp->drv_obj->is_master = false;
ptcp->drv_obj->event_cbs.mb_sync_event_cb = mbs_port_tcp_sync_event;
ptcp->drv_obj->event_cbs.port_arg = (void *)ptcp;
#ifdef MB_MDNS_IS_INCLUDED
err = port_start_mdns_service(&ptcp->pdriver->dns_name, false, tcp_opts->uid, ptcp->pdriver->network_iface_ptr);
err = port_start_mdns_service(&ptcp->drv_obj->dns_name, false, tcp_opts->uid, ptcp->drv_obj->network_iface_ptr);
MB_GOTO_ON_FALSE((err == ESP_OK), MB_EILLSTATE, error,
TAG, "mb tcp port mdns service init failure.");
ESP_LOGD(TAG, "Start mdns for @%p", ptcp);
@@ -153,15 +154,14 @@ error:
{
transaction_destroy(ptcp->transaction);
}
if (ptcp && ptcp->drv_obj) {
#ifdef MB_MDNS_IS_INCLUDED
port_stop_mdns_service(&ptcp->pdriver->dns_name);
port_stop_mdns_service(&ptcp->drv_obj->dns_name);
#endif
if (ptcp && ptcp->pdriver)
{
if (ptcp->pdriver->event_handler[0]) {
mbs_port_tcp_unregister_handlers(ptcp->pdriver);
if (ptcp->drv_obj->event_handler[0]) {
mbs_port_tcp_unregister_handlers(ptcp->drv_obj);
}
(void)mb_drv_unregister(ptcp->pdriver);
(void)mb_drv_unregister(ptcp->drv_obj);
CRITICAL_SECTION_CLOSE(ptcp->base.lock);
}
free(ptcp);
@@ -171,20 +171,17 @@ error:
void mbs_port_tcp_delete(mb_port_base_t *inst)
{
mbs_tcp_port_t *port_obj = __containerof(inst, mbs_tcp_port_t, base);
if (port_obj && port_obj->transaction)
{
if (port_obj && port_obj->transaction) {
transaction_destroy(port_obj->transaction);
}
if (port_obj && port_obj->drv_obj) {
#ifdef MB_MDNS_IS_INCLUDED
port_stop_mdns_service(&port_obj->pdriver->dns_name);
port_stop_mdns_service(&port_obj->drv_obj->dns_name);
#endif
if (port_obj && port_obj->pdriver)
{
if (port_obj->pdriver->event_handler[0])
{
mbs_port_tcp_unregister_handlers(port_obj->pdriver);
if (port_obj->drv_obj->event_handler[0]) {
mbs_port_tcp_unregister_handlers(port_obj->drv_obj);
}
(void)mb_drv_unregister(port_obj->pdriver);
(void)mb_drv_unregister(port_obj->drv_obj);
}
CRITICAL_SECTION_CLOSE(inst->lock);
free(port_obj);
@@ -193,46 +190,42 @@ void mbs_port_tcp_delete(mb_port_base_t *inst)
void mbs_port_tcp_enable(mb_port_base_t *inst)
{
mbs_tcp_port_t *port_obj = __containerof(inst, mbs_tcp_port_t, base);
(void)mb_drv_start_task(port_obj->pdriver);
DRIVER_SEND_EVENT(port_obj->pdriver, MB_EVENT_READY, UNDEF_FD);
(void)mb_drv_start_task(port_obj->drv_obj);
DRIVER_SEND_EVENT(port_obj->drv_obj, MB_EVENT_READY, UNDEF_FD);
}
void mbs_port_tcp_disable(mb_port_base_t *inst)
{
mbs_tcp_port_t *port_obj = __containerof(inst, mbs_tcp_port_t, base);
// Change the state of all slaves to close
DRIVER_SEND_EVENT(port_obj->pdriver, MB_EVENT_CLOSE, UNDEF_FD);
(void)mb_drv_wait_status_flag(port_obj->pdriver, MB_FLAG_DISCONNECTED, pdMS_TO_TICKS(MB_RECONNECT_TIME_MS));
DRIVER_SEND_EVENT(port_obj->drv_obj, MB_EVENT_CLOSE, UNDEF_FD);
(void)mb_drv_wait_status_flag(port_obj->drv_obj, MB_FLAG_DISCONNECTED, pdMS_TO_TICKS(MB_RECONNECT_TIME_MS));
}
bool mbs_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **ppframe, uint16_t *plength)
bool mbs_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **frame, uint16_t *length)
{
mbs_tcp_port_t *port_obj = __containerof(inst, mbs_tcp_port_t, base);
port_driver_t *pdrv_ctx = port_obj->pdriver;
port_driver_t *drv_obj = port_obj->drv_obj;
mb_node_info_t *pnode = NULL;
bool status = false;
transaction_item_handle_t item;
if (plength && ppframe && *ppframe)
{
mb_drv_lock(pdrv_ctx);
if (length && frame && *frame) {
mb_drv_lock(drv_obj);
item = transaction_get_first(port_obj->transaction);
if (item && (transaction_item_get_state(item) == ACKNOWLEDGED))
{
if (item && (transaction_item_get_state(item) == ACKNOWLEDGED)) {
uint16_t tid = 0;
int node_id = 0;
size_t len = 0;
uint8_t *pbuf = transaction_item_get_data(item, &len, &tid, &node_id);
pnode = mb_drv_get_node(pdrv_ctx, node_id);
if (pbuf && pnode && (MB_GET_NODE_STATE(pnode) >= MB_SOCK_STATE_CONNECTED))
{
memcpy(*ppframe, pbuf, len);
//*ppframe = pbuf;
*plength = (uint16_t)len;
uint8_t *buf = transaction_item_get_data(item, &len, &tid, &node_id);
pnode = mb_drv_get_node(drv_obj, node_id);
if (buf && pnode && (MB_GET_NODE_STATE(pnode) >= MB_SOCK_STATE_CONNECTED)) {
memcpy(*frame, buf, len);
*length = (uint16_t)len;
status = true;
ESP_LOGD(TAG, "%p, " MB_NODE_FMT(", get packet TID: 0x%04" PRIx16 ", %p."),
port_obj, pnode->index, pnode->sock_id,
pnode->addr_info.ip_addr_str, (unsigned)pnode->tid_counter, *ppframe);
pnode->addr_info.ip_addr_str, (unsigned)pnode->tid_counter, *frame);
if (ESP_OK != transaction_item_set_state(item, CONFIRMED)) {
ESP_LOGE(TAG, "transaction queue set state fail.");
}
@@ -246,40 +239,40 @@ bool mbs_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **ppframe, uint16_t *p
ESP_LOGE(TAG, "Deleted %d expired frames.", frame_cnt);
}
}
mb_drv_unlock(pdrv_ctx);
mb_drv_unlock(drv_obj);
}
return status;
}
bool mbs_port_tcp_send_data(mb_port_base_t *inst, uint8_t *pframe, uint16_t length)
bool mbs_port_tcp_send_data(mb_port_base_t *inst, uint8_t *frame, uint16_t length)
{
mbs_tcp_port_t *port_obj = __containerof(inst, mbs_tcp_port_t, base);
MB_RETURN_ON_FALSE((pframe && (length > 0)), false, TAG, "incorrect arguments.");
MB_RETURN_ON_FALSE((frame && (length > 0)), false, TAG, "incorrect arguments.");
bool frame_sent = false;
uint16_t tid = MB_TCP_MBAP_GET_FIELD(pframe, MB_TCP_TID);
port_driver_t *pdrv_ctx = port_obj->pdriver;
uint16_t tid = MB_TCP_MBAP_GET_FIELD(frame, MB_TCP_TID);
port_driver_t *drv_obj = port_obj->drv_obj;
transaction_item_handle_t item;
mb_drv_lock(pdrv_ctx);
mb_drv_lock(drv_obj);
item = transaction_dequeue(port_obj->transaction, CONFIRMED, NULL);
if (item) {
uint16_t msg_id = 0;
int node_id = 0;
uint8_t *pbuf = transaction_item_get_data(item, NULL, &msg_id, &node_id);
if (pbuf && (tid == msg_id)) {
mb_node_info_t *pnode = mb_drv_get_node(pdrv_ctx, node_id);
int write_length = mb_drv_write(pdrv_ctx, node_id, pframe, length);
uint8_t *buf = transaction_item_get_data(item, NULL, &msg_id, &node_id);
if (buf && (tid == msg_id)) {
mb_node_info_t *pnode = mb_drv_get_node(drv_obj, node_id);
int write_length = mb_drv_write(drv_obj, node_id, frame, length);
if (pnode && write_length) {
frame_sent = true;
ESP_LOGD(TAG, "%p, node: #%d, socket(#%d)[%s], send packet TID: 0x%04" PRIx16 ":0x%04" PRIx16 ", %p, len: %d, ",
pdrv_ctx, pnode->index, pnode->sock_id,
pnode->addr_info.node_name_str, (unsigned)tid, (unsigned)msg_id, pframe, length);
drv_obj, pnode->index, pnode->sock_id,
pnode->addr_info.node_name_str, (unsigned)tid, (unsigned)msg_id, frame, length);
} else {
ESP_LOGE(TAG, "%p, node: #%d, socket(#%d)[%s], mbs_write fail, TID: 0x%04" PRIx16 ":0x%04" PRIx16 ", %p, len: %d, ",
pdrv_ctx, pnode->index, pnode->sock_id,
pnode->addr_info.node_name_str, (unsigned)tid, (unsigned)msg_id, pframe, length);
drv_obj, pnode->index, pnode->sock_id,
pnode->addr_info.node_name_str, (unsigned)tid, (unsigned)msg_id, frame, length);
}
if (ESP_OK != transaction_item_set_state(item, REPLIED)) {
ESP_LOGE(TAG, "transaction queue set state fail.");
@@ -288,10 +281,9 @@ bool mbs_port_tcp_send_data(mb_port_base_t *inst, uint8_t *pframe, uint16_t leng
} else {
ESP_LOGE(TAG, "queue can not find the item to send.");
}
mb_drv_unlock(pdrv_ctx);
mb_drv_unlock(drv_obj);
if (!frame_sent)
{
if (!frame_sent) {
ESP_LOGE(TAG, "incorrect frame to send.");
}
return frame_sent;
@@ -325,10 +317,10 @@ static uint64_t mbs_port_tcp_sync_event(void *inst, mb_sync_event_t sync_event)
MB_EVENT_HANDLER(mbs_on_ready)
{
// The driver is registered
mb_event_info_t *pevent_info = (mb_event_info_t *)data;
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mbs_tcp_port_t *port_obj = __containerof(pdrv_ctx->parent, mbs_tcp_port_t, base);
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)pevent_info->opt_fd);
mb_event_info_t *event_info = (mb_event_info_t *)data;
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
mbs_tcp_port_t *port_obj = __containerof(drv_obj->parent, mbs_tcp_port_t, base);
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)event_info->opt_fd);
ESP_LOGD(TAG, "addr_table:%p, addr_type:%d, mode:%d, port:%d", port_obj->tcp_opts.ip_addr_table,
(int)port_obj->tcp_opts.addr_type,
(int)port_obj->tcp_opts.mode,
@@ -338,14 +330,13 @@ MB_EVENT_HANDLER(mbs_on_ready)
port_obj->tcp_opts.addr_type,
port_obj->tcp_opts.mode,
port_obj->tcp_opts.port);
if (listen_sock < 0)
{
if (listen_sock < 0) {
mb_drv_check_suspend_shutdown(ctx);
ESP_LOGE(TAG, "%s, sock: %d, bind error", (char *)base, listen_sock);
mb_drv_lock(pdrv_ctx);
if (pdrv_ctx->retry_cnt) pdrv_ctx->retry_cnt--;
mb_drv_unlock(pdrv_ctx);
if (pdrv_ctx->retry_cnt) {
mb_drv_lock(drv_obj);
if (drv_obj->retry_cnt) drv_obj->retry_cnt--;
mb_drv_unlock(drv_obj);
if (drv_obj->retry_cnt) {
vTaskDelay(TRANSACTION_TICKS);
DRIVER_SEND_EVENT(ctx, MB_EVENT_READY, UNDEF_FD);
} else {
@@ -353,107 +344,98 @@ MB_EVENT_HANDLER(mbs_on_ready)
ESP_LOGE(TAG, "%s, stop binding.", (char *)base);
// mbs_port_tcp_disable(&port_obj->base);
}
}
else
{
} else {
mb_drv_lock(ctx);
pdrv_ctx->listen_sock_fd = listen_sock;
drv_obj->listen_sock_fd = listen_sock;
// so, all accepted sockets will inherit the keep-alive feature
(void)port_keep_alive(pdrv_ctx->listen_sock_fd);
(void)port_keep_alive(drv_obj->listen_sock_fd);
mb_drv_unlock(ctx);
ESP_LOGI(TAG, "%s %s: fd: %d, bind is done", (char *)base, __func__, (int)pevent_info->opt_fd);
ESP_LOGI(TAG, "%s %s: fd: %d, bind is done", (char *)base, __func__, (int)event_info->opt_fd);
}
}
MB_EVENT_HANDLER(mbs_on_open)
{
mb_event_info_t *pevent_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)pevent_info->opt_fd);
mb_event_info_t *event_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)event_info->opt_fd);
}
MB_EVENT_HANDLER(mbs_on_connect)
{
mb_event_info_t *pevent_info = (mb_event_info_t *)data;
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)pevent_info->opt_fd);
mb_node_info_t *pnode = mb_drv_get_node(pdrv_ctx, pevent_info->opt_fd);
mb_event_info_t *event_info = (mb_event_info_t *)data;
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)event_info->opt_fd);
mb_node_info_t *pnode = mb_drv_get_node(drv_obj, event_info->opt_fd);
if (!pnode) {
ESP_LOGD(TAG, "%s %s: fd: %d, is closed.", (char *)base, __func__, (int)pevent_info->opt_fd);
ESP_LOGD(TAG, "%s %s: fd: %d, is closed.", (char *)base, __func__, (int)event_info->opt_fd);
return;
}
(void)port_keep_alive(pnode->sock_id);
mb_drv_lock(ctx);
MB_SET_NODE_STATE(pnode, MB_SOCK_STATE_CONNECTED);
FD_SET(pnode->sock_id, &pdrv_ctx->conn_set);
if (pdrv_ctx->node_conn_count < MB_MAX_FDS) {
pdrv_ctx->node_conn_count++;
FD_SET(pnode->sock_id, &drv_obj->conn_set);
if (drv_obj->node_conn_count < MB_MAX_FDS) {
drv_obj->node_conn_count++;
}
mb_drv_unlock(ctx);
}
MB_EVENT_HANDLER(mbs_on_recv_data)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mb_event_info_t *pevent_info = (mb_event_info_t *)data;
mbs_tcp_port_t *port_obj = (mbs_tcp_port_t *)pdrv_ctx->parent;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)pevent_info->opt_fd);
mb_node_info_t *pnode = mb_drv_get_node(pdrv_ctx, pevent_info->opt_fd);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
mb_event_info_t *event_info = (mb_event_info_t *)data;
mbs_tcp_port_t *port_obj = (mbs_tcp_port_t *)drv_obj->parent;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)event_info->opt_fd);
mb_node_info_t *pnode = mb_drv_get_node(drv_obj, event_info->opt_fd);
transaction_item_handle_t item = NULL;
if (pnode)
{
if (!queue_is_empty(pnode->rx_queue))
{
ESP_LOGD(TAG, "%p, node #%d(%d) [%s], receive data ready.", ctx, (int)pevent_info->opt_fd,
if (pnode) {
if (!queue_is_empty(pnode->rx_queue)) {
ESP_LOGD(TAG, "%p, node #%d(%d) [%s], receive data ready.", ctx, (int)event_info->opt_fd,
(int)pnode->sock_id, pnode->addr_info.ip_addr_str);
frame_entry_t frame_entry;
size_t sz = queue_pop(pnode->rx_queue, NULL, MB_BUFFER_SIZE, &frame_entry);
if (sz > MB_TCP_FUNC)
{
uint16_t tid_counter = MB_TCP_MBAP_GET_FIELD(frame_entry.pbuf, MB_TCP_TID);
if (sz > MB_TCP_FUNC) {
uint16_t tid_counter = MB_TCP_MBAP_GET_FIELD(frame_entry.buf, MB_TCP_TID);
ESP_LOGD(TAG, "%p, " MB_NODE_FMT(", received packet TID: 0x%04" PRIx16 ", %p."),
pdrv_ctx, pnode->index, pnode->sock_id,
pnode->addr_info.ip_addr_str, (unsigned)tid_counter, frame_entry.pbuf);
mb_drv_lock(pdrv_ctx);
drv_obj, pnode->index, pnode->sock_id,
pnode->addr_info.ip_addr_str, (unsigned)tid_counter, frame_entry.buf);
mb_drv_lock(drv_obj);
transaction_message_t msg;
msg.buffer = frame_entry.pbuf;
msg.buffer = frame_entry.buf;
msg.len = frame_entry.len;
msg.msg_id = frame_entry.tid;
msg.node_id = pnode->index;
msg.pnode = pnode;
item = transaction_enqueue(port_obj->transaction, &msg, port_get_timestamp());
pnode->tid_counter = tid_counter; // assign the TID from frame to use it on send
mb_drv_unlock(pdrv_ctx);
mb_drv_unlock(drv_obj);
}
}
mb_drv_lock(pdrv_ctx);
mb_drv_lock(drv_obj);
item = transaction_get_first(port_obj->transaction);
if (item)
{
if (transaction_item_get_state(item) == QUEUED)
{
if (item) {
if (transaction_item_get_state(item) == QUEUED) {
// send receive event to modbus object to get the new data
uint16_t msg_id = 0;
uint64_t tick = 0;
(void)transaction_item_get_data(item, NULL, &msg_id, NULL);
tick = port_get_timestamp();
pdrv_ctx->event_cbs.mb_sync_event_cb(pdrv_ctx->event_cbs.port_arg, MB_SYNC_EVENT_RECV_OK);
drv_obj->event_cbs.mb_sync_event_cb(drv_obj->event_cbs.port_arg, MB_SYNC_EVENT_RECV_OK);
transaction_set_tick(port_obj->transaction, msg_id, (transaction_tick_t)tick);
if (ESP_OK == transaction_item_set_state(item, ACKNOWLEDGED)) {
ESP_LOGD(TAG, "%p, " MB_NODE_FMT(", acknoledged packet TID: 0x%04" PRIx16 "."),
pdrv_ctx, pnode->index, pnode->sock_id,
drv_obj, pnode->index, pnode->sock_id,
pnode->addr_info.ip_addr_str, (unsigned)msg_id);
}
}
else
{
} else {
if (transaction_item_get_state(item) != TRANSMITTED) {
// Todo: for test removing expired item
transaction_delete_expired(port_obj->transaction, port_get_timestamp(), 1000 * 1000);
}
if (MB_FLAG_TRANSACTION_DONE == mb_drv_wait_status_flag(port_obj->pdriver,
if (MB_FLAG_TRANSACTION_DONE == mb_drv_wait_status_flag(port_obj->drv_obj,
MB_FLAG_TRANSACTION_DONE,
TRANSACTION_TICKS)) {
(void)mb_drv_clear_status_flag(pdrv_ctx, MB_FLAG_TRANSACTION_DONE);
(void)mb_drv_clear_status_flag(drv_obj, MB_FLAG_TRANSACTION_DONE);
}
// postpone the packet processing
DRIVER_SEND_EVENT(ctx, MB_EVENT_RECV_DATA, pnode->index);
@@ -461,20 +443,19 @@ MB_EVENT_HANDLER(mbs_on_recv_data)
} else {
ESP_LOGE(TAG, "%p, no queued items found", ctx);
}
mb_drv_unlock(pdrv_ctx);
mb_drv_unlock(drv_obj);
}
mb_drv_check_suspend_shutdown(ctx);
}
MB_EVENT_HANDLER(mbs_on_send_data)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mb_event_info_t *pevent_info = (mb_event_info_t *)data;
mbs_tcp_port_t *port_obj = (mbs_tcp_port_t *)pdrv_ctx->parent;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)pevent_info->opt_fd);
mb_node_info_t *pnode = mb_drv_get_node(pdrv_ctx, pevent_info->opt_fd);
if (pnode && !queue_is_empty(pnode->tx_queue))
{
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
mb_event_info_t *event_info = (mb_event_info_t *)data;
mbs_tcp_port_t *port_obj = (mbs_tcp_port_t *)drv_obj->parent;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)event_info->opt_fd);
mb_node_info_t *pnode = mb_drv_get_node(drv_obj, event_info->opt_fd);
if (pnode && !queue_is_empty(pnode->tx_queue)) {
frame_entry_t frame_entry;
// pop the frame entry, keep the buffer
size_t sz = queue_pop(pnode->tx_queue, NULL, MB_BUFFER_SIZE, &frame_entry);
@@ -483,94 +464,88 @@ MB_EVENT_HANDLER(mbs_on_send_data)
ctx, (int)pnode->index, (int)pnode->sock_id, pnode->addr_info.ip_addr_str);
return;
}
uint16_t tid = MB_TCP_MBAP_GET_FIELD(frame_entry.pbuf, MB_TCP_TID);
uint16_t tid = MB_TCP_MBAP_GET_FIELD(frame_entry.buf, MB_TCP_TID);
pnode->error = 0;
int ret = port_write_poll(pnode, frame_entry.pbuf, sz, MB_TCP_SEND_TIMEOUT_MS);
if (ret < 0)
{
int ret = port_write_poll(pnode, frame_entry.buf, sz, MB_TCP_SEND_TIMEOUT_MS);
if (ret < 0) {
ESP_LOGE(TAG, "%p, " MB_NODE_FMT(", send data failure, err(errno) = %d(%u)."),
ctx, (int)pnode->index, (int)pnode->sock_id,
pnode->addr_info.ip_addr_str, (int)ret, (unsigned)errno);
DRIVER_SEND_EVENT(ctx, MB_EVENT_ERROR, pnode->index);
pnode->error = ret;
}
else
{
} else {
pnode->error = 0;
if (tid != pnode->tid_counter)
{
if (tid != pnode->tid_counter) {
ESP_LOGE(TAG, "%p, " MB_NODE_FMT(", send incorrect frame TID:0x%04" PRIx16 "!= 0x%04" PRIx16 ", %d (bytes), errno %d"),
ctx, (int)pnode->index, (int)pnode->sock_id,
pnode->addr_info.ip_addr_str, pnode->tid_counter, tid, (int)ret, (unsigned)errno);
}
else
{
} else {
ESP_LOGD(TAG, "%p, " MB_NODE_FMT(", send data successful: TID:0x%04" PRIx16 ":0x%04" PRIx16 ", %d (bytes), errno %d"),
ctx, (int)pnode->index, (int)pnode->sock_id,
pnode->addr_info.ip_addr_str, pnode->tid_counter, tid, (int)ret, (unsigned)errno);
}
ESP_LOG_BUFFER_HEX_LEVEL("SENT", frame_entry.pbuf, ret, ESP_LOG_DEBUG);
ESP_LOG_BUFFER_HEX_LEVEL("SENT", frame_entry.buf, ret, ESP_LOG_DEBUG);
}
(void)mb_drv_set_status_flag(pdrv_ctx, MB_FLAG_TRANSACTION_DONE);
pdrv_ctx->event_cbs.mb_sync_event_cb(pdrv_ctx->event_cbs.port_arg, MB_SYNC_EVENT_SEND_OK);
mb_drv_lock(pdrv_ctx);
(void)mb_drv_set_status_flag(drv_obj, MB_FLAG_TRANSACTION_DONE);
drv_obj->event_cbs.mb_sync_event_cb(drv_obj->event_cbs.port_arg, MB_SYNC_EVENT_SEND_OK);
mb_drv_lock(drv_obj);
transaction_set_state(port_obj->transaction, tid, TRANSMITTED);
if (transaction_delete(port_obj->transaction, tid) != ESP_OK) {
ESP_LOGE(TAG, "Failed to remove queued TID:0x%04" PRIx16, tid);
} else {
ESP_LOGD(TAG, "Remove the message TID:0x%04" PRIx16, tid);
}
free(frame_entry.pbuf);
free(frame_entry.buf);
pnode->send_time = esp_timer_get_time();
pnode->send_counter = (pnode->send_counter < (USHRT_MAX - 1)) ? (pnode->send_counter + 1) : 0;
mb_drv_unlock(pdrv_ctx);
mb_drv_unlock(drv_obj);
}
}
MB_EVENT_HANDLER(mbs_on_error)
{
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mb_event_info_t *pevent_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)pevent_info->opt_fd);
mb_node_info_t *pnode = mb_drv_get_node(pdrv_ctx, pevent_info->opt_fd);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
mb_event_info_t *event_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s: fd: %d", (char *)base, __func__, (int)event_info->opt_fd);
mb_node_info_t *pnode = mb_drv_get_node(drv_obj, event_info->opt_fd);
if (!pnode) {
ESP_LOGD(TAG, "%s %s: fd: %d, is closed.", (char *)base, __func__, (int)pevent_info->opt_fd);
ESP_LOGD(TAG, "%s %s: fd: %d, is closed.", (char *)base, __func__, (int)event_info->opt_fd);
return;
}
// Check if the node is not alive for timeout
int ret = mb_drv_check_node_state(pdrv_ctx, (int *)&pevent_info->opt_fd, MB_TCP_EVENT_LOOP_TICK_MS);
int ret = mb_drv_check_node_state(drv_obj, (int *)&event_info->opt_fd, MB_TCP_EVENT_LOOP_TICK_MS);
if ((ret != ERR_OK) && (ret != ERR_TIMEOUT)) {
ESP_LOGE(TAG, "Node: #%d is not alive, err= %d", (int)pevent_info->opt_fd, ret);
mb_drv_close(pdrv_ctx, pevent_info->opt_fd);
ESP_LOGE(TAG, "Node: #%d is not alive, err= %d", (int)event_info->opt_fd, ret);
mb_drv_close(drv_obj, event_info->opt_fd);
}
}
MB_EVENT_HANDLER(mbs_on_close)
{
mb_event_info_t *pevent_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s, fd: %d", (char *)base, __func__, (int)pevent_info->opt_fd);
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
mb_event_info_t *event_info = (mb_event_info_t *)data;
ESP_LOGD(TAG, "%s %s, fd: %d", (char *)base, __func__, (int)event_info->opt_fd);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
mb_node_info_t *pnode =NULL;
// if close all sockets event is received
if (pevent_info->opt_fd < 0)
if (event_info->opt_fd < 0)
{
(void)mb_drv_clear_status_flag(pdrv_ctx, MB_FLAG_DISCONNECTED);
(void)mb_drv_clear_status_flag(drv_obj, MB_FLAG_DISCONNECTED);
for (int fd = 0; fd < MB_MAX_FDS; fd++)
{
mb_node_info_t *pnode = mb_drv_get_node(pdrv_ctx, fd);
mb_node_info_t *pnode = mb_drv_get_node(drv_obj, fd);
if (pnode && (MB_GET_NODE_STATE(pnode) >= MB_SOCK_STATE_OPENED)
&& FD_ISSET(pnode->index, &pdrv_ctx->open_set))
&& FD_ISSET(pnode->index, &drv_obj->open_set))
{
mb_drv_close(pdrv_ctx, fd);
mb_drv_close(drv_obj, fd);
}
}
(void)mb_drv_set_status_flag(pdrv_ctx, MB_FLAG_DISCONNECTED);
(void)mb_drv_set_status_flag(drv_obj, MB_FLAG_DISCONNECTED);
mb_drv_check_suspend_shutdown(ctx);
} else if (MB_CHECK_FD_RANGE(pevent_info->opt_fd)) {
pnode = mb_drv_get_node(pdrv_ctx, pevent_info->opt_fd);
} else if (MB_CHECK_FD_RANGE(event_info->opt_fd)) {
pnode = mb_drv_get_node(drv_obj, event_info->opt_fd);
if (pnode && (MB_GET_NODE_STATE(pnode) >= MB_SOCK_STATE_OPENED)) {
if ((pnode->sock_id < 0) && FD_ISSET(pnode->sock_id, &pdrv_ctx->open_set)) {
mb_drv_close(ctx, pevent_info->opt_fd);
if ((pnode->sock_id < 0) && FD_ISSET(pnode->sock_id, &drv_obj->open_set)) {
mb_drv_close(ctx, event_info->opt_fd);
}
}
mb_drv_check_suspend_shutdown(ctx);
@@ -580,17 +555,17 @@ MB_EVENT_HANDLER(mbs_on_close)
MB_EVENT_HANDLER(mbs_on_timeout)
{
// Slave timeout triggered
//mb_event_info_t *pevent_info = (mb_event_info_t *)data;
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
static int curr_fd = 0;
ESP_LOGD(TAG, "%s %s: fd: %d, %d", (char *)base, __func__, (int)curr_fd, pdrv_ctx->node_conn_count);
ESP_LOGD(TAG, "%s %s: fd: %d, %d", (char *)base, __func__, (int)curr_fd, drv_obj->node_conn_count);
mb_drv_check_suspend_shutdown(ctx);
int ret = mb_drv_check_node_state(pdrv_ctx, &curr_fd, MB_RECONNECT_TIME_MS);
int ret = mb_drv_check_node_state(drv_obj, &curr_fd, MB_RECONNECT_TIME_MS);
if ((ret != ERR_OK) && (ret != ERR_TIMEOUT)) {
ESP_LOGE(TAG, "Node: %d, connection lost, err= %d", curr_fd, ret);
mb_drv_close(pdrv_ctx, curr_fd);
mb_drv_close(drv_obj, curr_fd);
}
if ((curr_fd + 1) >= (pdrv_ctx->node_conn_count)) {
if ((curr_fd + 1) >= (drv_obj->node_conn_count)) {
curr_fd = 0;
} else {
curr_fd++;

View File

@@ -25,10 +25,10 @@ bool port_check_host_addr(const char *host_str, ip_addr_t *host_addr)
{
MB_RETURN_ON_FALSE((host_str), false, TAG, "wrong host name or IP.");
char cstr[HOST_STR_MAX_LEN];
char *pstr = &cstr[0];
char *string_ptr = &cstr[0];
ip_addr_t target_addr;
struct addrinfo hint;
struct addrinfo *paddr_list;
struct addrinfo *addr_list;
memset(&hint, 0, sizeof(hint));
// Do name resolution for both protocols
hint.ai_family = AF_UNSPEC;
@@ -38,53 +38,53 @@ bool port_check_host_addr(const char *host_str, ip_addr_t *host_addr)
// convert domain name to IP address
// Todo: check EAI_FAIL error when resolve host name
int ret = getaddrinfo(host_str, NULL, &hint, &paddr_list);
int ret = getaddrinfo(host_str, NULL, &hint, &addr_list);
if (ret != 0) {
ESP_LOGD(TAG, "Incorrect host IP: %s", host_str);
return false;
}
if (paddr_list->ai_family == AF_INET) {
struct in_addr addr4 = ((struct sockaddr_in *)(paddr_list->ai_addr))->sin_addr;
if (addr_list->ai_family == AF_INET) {
struct in_addr addr4 = ((struct sockaddr_in *)(addr_list->ai_addr))->sin_addr;
inet_addr_to_ip4addr(ip_2_ip4(&target_addr), &addr4);
pstr = ip4addr_ntoa_r(ip_2_ip4(&target_addr), cstr, sizeof(cstr));
string_ptr = ip4addr_ntoa_r(ip_2_ip4(&target_addr), cstr, sizeof(cstr));
}
#if CONFIG_LWIP_IPV6
else {
struct in6_addr addr6 = ((struct sockaddr_in6 *)(paddr_list->ai_addr))->sin6_addr;
struct in6_addr addr6 = ((struct sockaddr_in6 *)(addr_list->ai_addr))->sin6_addr;
inet6_addr_to_ip6addr(ip_2_ip6(&target_addr), &addr6);
pstr = ip6addr_ntoa_r(ip_2_ip6(&target_addr), cstr, sizeof(cstr));
string_ptr = ip6addr_ntoa_r(ip_2_ip6(&target_addr), cstr, sizeof(cstr));
}
#endif
if (host_addr) {
*host_addr = target_addr;
}
ESP_LOGD(TAG, "Check name[IP]: \"%s\"[%s]", paddr_list->ai_canonname ? paddr_list->ai_canonname : "UNK", pstr);
freeaddrinfo(paddr_list);
ESP_LOGD(TAG, "Check name[IP]: \"%s\"[%s]", addr_list->ai_canonname ? addr_list->ai_canonname : "UNK", string_ptr);
freeaddrinfo(addr_list);
return true;
}
bool port_close_connection(mb_node_info_t *pinfo)
bool port_close_connection(mb_node_info_t *info_ptr)
{
if (!pinfo) {
if (!info_ptr) {
return false;
}
if (pinfo->sock_id <= 0) {
ESP_LOGD(TAG, "wrong socket info or disconnected socket: %d, skip.", pinfo->index);
if (info_ptr->sock_id <= 0) {
ESP_LOGD(TAG, "wrong socket info or disconnected socket: %d, skip.", info_ptr->index);
return false;
}
uint8_t tmp_buff[MB_PDU_SIZE_MAX];
// Empty tcp buffer before shutdown
(void)recv(pinfo->sock_id, &tmp_buff[0], MB_PDU_SIZE_MAX, MSG_DONTWAIT);
queue_flush(pinfo->rx_queue);
queue_flush(pinfo->tx_queue);
(void)recv(info_ptr->sock_id, &tmp_buff[0], MB_PDU_SIZE_MAX, MSG_DONTWAIT);
queue_flush(info_ptr->rx_queue);
queue_flush(info_ptr->tx_queue);
if (shutdown(pinfo->sock_id, SHUT_RDWR) == -1) {
ESP_LOGV(TAG, "Shutdown failed sock %d, errno=%d", pinfo->sock_id, (int)errno);
if (shutdown(info_ptr->sock_id, SHUT_RDWR) == -1) {
ESP_LOGV(TAG, "Shutdown failed sock %d, errno=%d", info_ptr->sock_id, (int)errno);
}
close(pinfo->sock_id);
MB_SET_NODE_STATE(pinfo, MB_SOCK_STATE_OPENED);
pinfo->sock_id = UNDEF_FD;
close(info_ptr->sock_id);
MB_SET_NODE_STATE(info_ptr, MB_SOCK_STATE_OPENED);
info_ptr->sock_id = UNDEF_FD;
return true;
}
@@ -101,47 +101,45 @@ static void port_ms_to_tv(uint16_t timeout_ms, struct timeval *tv)
tv->tv_usec = (timeout_ms - (tv->tv_sec * 1000)) * 1000;
}
int port_enqueue_packet(QueueHandle_t queue, uint8_t *pbuf, uint16_t len)
int port_enqueue_packet(QueueHandle_t queue, uint8_t *buf, uint16_t len)
{
frame_entry_t frame_info = {0};
esp_err_t ret = ESP_ERR_INVALID_STATE;
if (queue && pbuf) {
frame_info.tid = MB_TCP_MBAP_GET_FIELD(pbuf, MB_TCP_TID);
frame_info.uid = pbuf[MB_TCP_UID];
frame_info.pid = MB_TCP_MBAP_GET_FIELD(pbuf, MB_TCP_PID);
frame_info.len = MB_TCP_MBAP_GET_FIELD(pbuf, MB_TCP_LEN) + MB_TCP_UID;
if (queue && buf) {
frame_info.tid = MB_TCP_MBAP_GET_FIELD(buf, MB_TCP_TID);
frame_info.uid = buf[MB_TCP_UID];
frame_info.pid = MB_TCP_MBAP_GET_FIELD(buf, MB_TCP_PID);
frame_info.len = MB_TCP_MBAP_GET_FIELD(buf, MB_TCP_LEN) + MB_TCP_UID;
if (len != frame_info.len) {
ESP_LOGE(TAG, "Packet TID (%x), length in frame %u != %u expected.", frame_info.tid, frame_info.len, len);
}
assert(xPortGetFreeHeapSize() > frame_info.len);
ret = queue_push(queue, pbuf, frame_info.len, &frame_info);
ret = queue_push(queue, buf, frame_info.len, &frame_info);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Packet TID (%x), data enqueue failed.", frame_info.tid);
// The packet send fail or the task which is waiting for event is already unblocked
return ERR_BUF;
} else {
}
ESP_LOGD(TAG, "Enqueue data, length=%d, TID=0x%" PRIx16, frame_info.len, frame_info.tid);
return (int)frame_info.len;
}
} else {
ESP_LOGE(TAG, "Enqueue data fail, %p, length=%d.", pbuf, len);
}
ESP_LOGE(TAG, "Enqueue data fail, %p, length=%d.", buf, len);
return ERR_BUF;
}
int port_dequeue_packet(QueueHandle_t queue, frame_entry_t *pframe_info)
int port_dequeue_packet(QueueHandle_t queue, frame_entry_t *frame_info_ptr)
{
frame_entry_t frame_info = {0};
esp_err_t ret = ESP_ERR_INVALID_STATE;
if (queue && pframe_info) {
if (queue && frame_info_ptr) {
ret = queue_pop(queue, NULL, MB_TCP_BUFF_MAX_SIZE, &frame_info);
if (ret == ESP_OK) {
if ((frame_info.pid == 0) && (frame_info.uid < MB_ADDRESS_MAX)) {
*pframe_info = frame_info;
ESP_LOGD(TAG, "Dequeue data, length=%d, TID=0x%" PRIx16, (int)pframe_info->len, (int)pframe_info->tid);
*frame_info_ptr = frame_info;
ESP_LOGD(TAG, "Dequeue data, length=%d, TID=0x%" PRIx16, (int)frame_info_ptr->len, (int)frame_info_ptr->tid);
return ERR_OK;
}
} else {
@@ -151,65 +149,67 @@ int port_dequeue_packet(QueueHandle_t queue, frame_entry_t *pframe_info)
return ERR_BUF;
}
static int port_get_buf(mb_node_info_t *pinfo, uint8_t *pdst_buf, uint16_t len, uint16_t read_tick_ms)
static int port_get_buf(mb_node_info_t *info_ptr, uint8_t *pdst_buf, uint16_t len, uint16_t read_tick_ms)
{
int ret = 0;
uint8_t *pbuf = pdst_buf;
uint8_t *buf = pdst_buf;
uint16_t bytes_left = len;
struct timeval time_val;
MB_RETURN_ON_FALSE((pinfo && (pinfo->sock_id > UNDEF_FD)), -1, TAG, "Try to read incorrect socket = #%d.", pinfo->sock_id);
MB_RETURN_ON_FALSE((info_ptr && (info_ptr->sock_id > UNDEF_FD)), -1, TAG, "Try to read incorrect socket = #%d.", info_ptr->sock_id);
// Set receive timeout for socket <= slave respond time
time_val.tv_sec = read_tick_ms / 1000;
time_val.tv_usec = (read_tick_ms % 1000) * 1000;
setsockopt(pinfo->sock_id, SOL_SOCKET, SO_RCVTIMEO, &time_val, sizeof(time_val));
setsockopt(info_ptr->sock_id, SOL_SOCKET, SO_RCVTIMEO, &time_val, sizeof(time_val));
// blocking read of data from socket
ret = recv(pinfo->sock_id, pbuf, bytes_left, 0);
ret = recv(info_ptr->sock_id, buf, bytes_left, 0);
if (ret < 0) {
if (errno == EINPROGRESS || errno == EAGAIN || errno == EWOULDBLOCK) {
// Read timeout occurred, check the timeout and return
return 0;
} else if ((errno == ENOTCONN) || (errno == ECONNRESET)) {
}
if ((errno == ENOTCONN) || (errno == ECONNRESET)) {
ESP_LOGD(TAG, "socket(#%d)(%s) connection closed, ret=%d, errno=%d.",
pinfo->sock_id, pinfo->addr_info.ip_addr_str, ret, (int)errno);
info_ptr->sock_id, info_ptr->addr_info.ip_addr_str, ret, (int)errno);
// Socket connection closed
return ERR_CONN;
} else {
}
// Other error occurred during receiving
ESP_LOGD(TAG, "Socket(#%d)(%s) receive error, ret = %d, errno = %d(%s)",
pinfo->sock_id, pinfo->addr_info.ip_addr_str, ret, (int)errno, strerror(errno));
return -1;
}
info_ptr->sock_id, info_ptr->addr_info.ip_addr_str, ret, (int)errno, strerror(errno));
ret = -1;
}
return ret;
}
int port_read_packet(mb_node_info_t *pinfo)
int port_read_packet(mb_node_info_t *info_ptr)
{
uint16_t temp = 0;
int ret = 0;
uint8_t ptemp_buf[MB_TCP_BUFF_MAX_SIZE] = {0};
// Receive data from connected client
if (pinfo) {
MB_RETURN_ON_FALSE((pinfo->sock_id > 0), -1, TAG, "try to read incorrect socket = #%d.", pinfo->sock_id);
if (info_ptr) {
MB_RETURN_ON_FALSE((info_ptr->sock_id > 0), -1, TAG, "try to read incorrect socket = #%d", info_ptr->sock_id);
// Read packet header
ret = port_get_buf(pinfo, ptemp_buf, MB_TCP_UID, MB_READ_TICK);
ret = port_get_buf(info_ptr, ptemp_buf, MB_TCP_UID, MB_READ_TICK);
if (ret < 0) {
pinfo->recv_err = ret;
info_ptr->recv_err = ret;
return ret;
} else if (ret != MB_TCP_UID) {
}
if (ret != MB_TCP_UID) {
ESP_LOGD(TAG, "Socket (#%d)(%s), fail to read modbus header. ret=%d",
pinfo->sock_id, pinfo->addr_info.ip_addr_str, ret);
pinfo->recv_err = ERR_VAL;
info_ptr->sock_id, info_ptr->addr_info.ip_addr_str, ret);
info_ptr->recv_err = ERR_VAL;
return ERR_VAL;
}
temp = MB_TCP_MBAP_GET_FIELD(ptemp_buf, MB_TCP_PID);
if (temp != 0) {
pinfo->recv_err = ERR_BUF;
info_ptr->recv_err = ERR_BUF;
return ERR_BUF;
}
@@ -219,53 +219,54 @@ int port_read_packet(mb_node_info_t *pinfo)
if (temp > MB_TCP_BUFF_MAX_SIZE) {
ESP_LOGD(TAG, "Incorrect packet length: %d", temp);
ESP_LOG_BUFFER_HEX_LEVEL(TAG, ptemp_buf, MB_TCP_FUNC, ESP_LOG_DEBUG);
pinfo->recv_err = ERR_BUF;
info_ptr->recv_err = ERR_BUF;
temp = MB_TCP_BUFF_MAX_SIZE; // read all remaining data from buffer
}
ret = port_get_buf(pinfo, &ptemp_buf[MB_TCP_UID], temp, MB_READ_TICK);
ret = port_get_buf(info_ptr, &ptemp_buf[MB_TCP_UID], temp, MB_READ_TICK);
if (ret < 0) {
pinfo->recv_err = ret;
info_ptr->recv_err = ret;
return ret;
} else if (ret != temp) {
pinfo->recv_err = ERR_VAL;
}
if (ret != temp) {
info_ptr->recv_err = ERR_VAL;
return ERR_VAL;
}
if (ptemp_buf[MB_TCP_UID] > MB_ADDRESS_MAX) {
pinfo->recv_err = ERR_BUF;
info_ptr->recv_err = ERR_BUF;
return ERR_BUF;
}
ret = port_enqueue_packet(pinfo->rx_queue, ptemp_buf, temp + MB_TCP_UID);
ret = port_enqueue_packet(info_ptr->rx_queue, ptemp_buf, temp + MB_TCP_UID);
if (ret < 0) {
pinfo->recv_err = ret;
info_ptr->recv_err = ret;
return ret;
}
pinfo->recv_counter++;
info_ptr->recv_counter++;
pinfo->recv_err = ERR_OK;
info_ptr->recv_err = ERR_OK;
return ret + MB_TCP_FUNC;
}
return -1;
}
err_t port_set_blocking(mb_node_info_t *pinfo, bool is_blocking)
err_t port_set_blocking(mb_node_info_t *info_ptr, bool is_blocking)
{
if (!pinfo) {
if (!info_ptr) {
return ERR_CONN;
}
// Set non blocking attribute for socket
uint32_t flags = fcntl(pinfo->sock_id, F_GETFL);
uint32_t flags = fcntl(info_ptr->sock_id, F_GETFL);
flags = is_blocking ? flags & ~O_NONBLOCK : flags | O_NONBLOCK;
if (fcntl(pinfo->sock_id, F_SETFL, flags) == -1) {
if (fcntl(info_ptr->sock_id, F_SETFL, flags) == -1) {
ESP_LOGE(TAG, "Socket(#%d)(%s), fcntl() call error=%d",
pinfo->sock_id, pinfo->addr_info.ip_addr_str, (int)errno);
info_ptr->sock_id, info_ptr->addr_info.ip_addr_str, (int)errno);
return ERR_WOULDBLOCK;
} else {
pinfo->is_blocking = ((flags & O_NONBLOCK) != O_NONBLOCK);
}
info_ptr->is_blocking = ((flags & O_NONBLOCK) != O_NONBLOCK);
return ERR_OK;
}
@@ -303,45 +304,45 @@ int port_keep_alive(int sock)
}
// Check connection for timeout helper
err_t port_check_alive(mb_node_info_t *pinfo, uint32_t timeout_ms)
err_t port_check_alive(mb_node_info_t *info_ptr, uint32_t timeout_ms)
{
fd_set write_set;
fd_set err_set;
err_t err = -1;
struct timeval time_val;
if (pinfo && pinfo->sock_id != -1) {
if (info_ptr && info_ptr->sock_id != -1) {
FD_ZERO(&write_set);
FD_ZERO(&err_set);
FD_SET(pinfo->sock_id, &write_set);
FD_SET(pinfo->sock_id, &err_set);
FD_SET(info_ptr->sock_id, &write_set);
FD_SET(info_ptr->sock_id, &err_set);
port_ms_to_tv(timeout_ms, &time_val);
// Check if the socket is writable
err = select(pinfo->sock_id + 1, NULL, &write_set, &err_set, &time_val);
if ((err < 0) || FD_ISSET(pinfo->sock_id, &err_set)) {
err = select(info_ptr->sock_id + 1, NULL, &write_set, &err_set, &time_val);
if ((err < 0) || FD_ISSET(info_ptr->sock_id, &err_set)) {
if (errno == EINPROGRESS) {
err = ERR_INPROGRESS;
} else {
ESP_LOGV(TAG, MB_NODE_FMT(" connection, select write err(errno) = %d(%d)."),
pinfo->index, pinfo->sock_id, pinfo->addr_info.ip_addr_str, err, (int)errno);
info_ptr->index, info_ptr->sock_id, info_ptr->addr_info.ip_addr_str, err, (int)errno);
err = ERR_CONN;
}
} else if (err == 0) {
ESP_LOGV(TAG, "Socket(#%d)(%s), connection timeout occurred, err(errno) = %d(%d).",
pinfo->sock_id, pinfo->addr_info.ip_addr_str, err, (int)errno);
info_ptr->sock_id, info_ptr->addr_info.ip_addr_str, err, (int)errno);
return ERR_INPROGRESS;
} else {
int opt_err = 0;
uint32_t opt_len = sizeof(opt_err);
// Check socket error
err = getsockopt(pinfo->sock_id, SOL_SOCKET, SO_ERROR, (void *)&opt_err, (socklen_t *)&opt_len);
err = getsockopt(info_ptr->sock_id, SOL_SOCKET, SO_ERROR, (void *)&opt_err, (socklen_t *)&opt_len);
if (opt_err != 0) {
ESP_LOGD(TAG, "Socket(#%d)(%s), sock error occurred (%d).",
pinfo->sock_id, pinfo->addr_info.ip_addr_str, opt_err);
info_ptr->sock_id, info_ptr->addr_info.ip_addr_str, opt_err);
return ERR_CONN;
}
ESP_LOGV(TAG, "Socket(#%d)(%s), is alive.",
pinfo->sock_id, pinfo->addr_info.ip_addr_str);
info_ptr->sock_id, info_ptr->addr_info.ip_addr_str);
return ERR_OK;
}
} else {
@@ -351,130 +352,132 @@ err_t port_check_alive(mb_node_info_t *pinfo, uint32_t timeout_ms)
}
// Unblocking connect function
err_t port_connect(void *ctx, mb_node_info_t *pinfo)
err_t port_connect(void *ctx, mb_node_info_t *info_ptr)
{
if (!pinfo) {
if (!info_ptr) {
return ERR_CONN;
}
port_driver_t *pdrv_ctx = MB_GET_DRV_PTR(ctx);
port_driver_t *drv_obj = MB_GET_DRV_PTR(ctx);
err_t err = ERR_OK;
char str[HOST_STR_MAX_LEN];
char *pstr = NULL;
char *string_ptr = NULL;
ip_addr_t target_addr;
struct addrinfo hint;
struct addrinfo *addr_list;
struct addrinfo *pcur_addr;
struct addrinfo *cur_addr;
memset(&hint, 0, sizeof(hint));
// Do name resolution for both protocols
hint.ai_flags = AI_ADDRCONFIG | AI_CANONNAME; // get IPV6 address if supported, otherwise IPV4
hint.ai_family = (pinfo->addr_info.addr_type == MB_IPV4) ? AF_INET : AF_INET6;
hint.ai_socktype = (pinfo->addr_info.proto == MB_UDP) ? SOCK_DGRAM : SOCK_STREAM;
hint.ai_protocol = (pinfo->addr_info.proto == MB_UDP) ? IPPROTO_UDP : IPPROTO_TCP;
hint.ai_family = (info_ptr->addr_info.addr_type == MB_IPV4) ? AF_INET : AF_INET6;
hint.ai_socktype = (info_ptr->addr_info.proto == MB_UDP) ? SOCK_DGRAM : SOCK_STREAM;
hint.ai_protocol = (info_ptr->addr_info.proto == MB_UDP) ? IPPROTO_UDP : IPPROTO_TCP;
memset(&target_addr, 0, sizeof(target_addr));
if (asprintf(&pstr, "%u", pinfo->addr_info.port) == -1) {
if (asprintf(&string_ptr, "%u", info_ptr->addr_info.port) == -1) {
abort();
}
// convert domain name to IP address
int ret = getaddrinfo(pinfo->addr_info.ip_addr_str, pstr, &hint, &addr_list);
free(pstr);
int ret = getaddrinfo(info_ptr->addr_info.ip_addr_str, string_ptr, &hint, &addr_list);
free(string_ptr);
if (ret != 0) {
ESP_LOGE(TAG, "Cannot resolve host: %s", pinfo->addr_info.ip_addr_str);
ESP_LOGE(TAG, "Cannot resolve host: %s", info_ptr->addr_info.ip_addr_str);
return ERR_CONN;
}
for (pcur_addr = addr_list; pcur_addr != NULL; pcur_addr = pcur_addr->ai_next) {
if (pcur_addr->ai_family == AF_INET) {
struct in_addr addr4 = ((struct sockaddr_in *)(pcur_addr->ai_addr))->sin_addr;
for (cur_addr = addr_list; cur_addr != NULL; cur_addr = cur_addr->ai_next) {
if (cur_addr->ai_family == AF_INET) {
struct in_addr addr4 = ((struct sockaddr_in *)(cur_addr->ai_addr))->sin_addr;
inet_addr_to_ip4addr(ip_2_ip4(&target_addr), &addr4);
pstr = ip4addr_ntoa_r(ip_2_ip4(&target_addr), str, sizeof(str));
string_ptr = ip4addr_ntoa_r(ip_2_ip4(&target_addr), str, sizeof(str));
}
#if CONFIG_LWIP_IPV6
else if (pcur_addr->ai_family == AF_INET6) {
struct in6_addr addr6 = ((struct sockaddr_in6 *)(pcur_addr->ai_addr))->sin6_addr;
else if (cur_addr->ai_family == AF_INET6) {
struct in6_addr addr6 = ((struct sockaddr_in6 *)(cur_addr->ai_addr))->sin6_addr;
inet6_addr_to_ip6addr(ip_2_ip6(&target_addr), &addr6);
pstr = ip6addr_ntoa_r(ip_2_ip6(&target_addr), str, sizeof(str));
string_ptr = ip6addr_ntoa_r(ip_2_ip6(&target_addr), str, sizeof(str));
// Set scope id to fix routing issues with local address
((struct sockaddr_in6 *)(pcur_addr->ai_addr))->sin6_scope_id =
esp_netif_get_netif_impl_index(pdrv_ctx->network_iface_ptr);
((struct sockaddr_in6 *)(cur_addr->ai_addr))->sin6_scope_id =
esp_netif_get_netif_impl_index(drv_obj->network_iface_ptr);
}
#endif
if (pinfo->sock_id <= 0) {
pinfo->sock_id = socket(pcur_addr->ai_family, pcur_addr->ai_socktype, pcur_addr->ai_protocol);
if (pinfo->sock_id < 0) {
ESP_LOGE(TAG, "Unable to create socket: #%d, errno %d", pinfo->sock_id, (int)errno);
if (info_ptr->sock_id <= 0) {
info_ptr->sock_id = socket(cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol);
if (info_ptr->sock_id < 0) {
ESP_LOGE(TAG, "Unable to create socket: #%d, errno %d", info_ptr->sock_id, (int)errno);
err = ERR_IF;
continue;
}
} else {
ESP_LOGV(TAG, "Socket (#%d)(%s) created.", pinfo->sock_id, str);
ESP_LOGV(TAG, "Socket (#%d)(%s) created.", info_ptr->sock_id, str);
}
// Set non blocking attribute for socket
port_set_blocking(pinfo, false);
port_set_blocking(info_ptr, false);
// Can return EINPROGRESS as an error which means
// that connection is in progress and should be checked later
err = connect(pinfo->sock_id, (struct sockaddr *)pcur_addr->ai_addr, pcur_addr->ai_addrlen);
err = connect(info_ptr->sock_id, cur_addr->ai_addr, cur_addr->ai_addrlen);
if ((err < 0) && (errno == EINPROGRESS || errno == EALREADY)) {
// The unblocking connect is pending (check status later) or already connected
ESP_LOGD(TAG, "Socket(#%d)(%s) connection is pending, errno %d (%s).",
pinfo->sock_id, str, (int)errno, strerror(errno));
info_ptr->sock_id, str, (int)errno, strerror(errno));
// Set keepalive option
(void)port_keep_alive(pinfo->sock_id);
err = port_check_alive(pinfo, MB_TCP_CHECK_ALIVE_TOUT_MS);
// Set keep alive flag in socket options
(void)port_keep_alive(info_ptr->sock_id);
err = port_check_alive(info_ptr, MB_TCP_CHECK_ALIVE_TOUT_MS);
continue;
} else if ((err < 0) && (errno == EISCONN)) {
}
if ((err < 0) && (errno == EISCONN)) {
// Socket already connected
err = ERR_OK;
continue;
} else if (err != ERR_OK) {
}
if (err != ERR_OK) {
// Other error occurred during connection
ESP_LOGV(TAG, "%p, "MB_NODE_FMT(" unable to connect, error=%d, errno %d (%s)"),
ctx, pinfo->index, pinfo->sock_id, str, err, (int)errno, strerror(errno));
port_close_connection(pinfo);
ctx, info_ptr->index, info_ptr->sock_id, str, err, (int)errno, strerror(errno));
port_close_connection(info_ptr);
err = ERR_CONN;
} else {
ESP_LOGI(TAG, "%p, "MB_NODE_FMT(", successfully connected."),
ctx, pinfo->index, pinfo->sock_id, str);
ctx, info_ptr->index, info_ptr->sock_id, str);
continue;
}
}
freeaddrinfo(addr_list);
port_set_blocking(pinfo, true);
port_set_blocking(info_ptr, true);
return err;
}
int port_write_poll(mb_node_info_t *pinfo, const uint8_t *pframe, uint16_t frame_len, uint32_t timeout)
int port_write_poll(mb_node_info_t *info_ptr, const uint8_t *frame, uint16_t frame_len, uint32_t timeout)
{
// Check if the socket is alive (writable and SO_ERROR == 0)
int res = (int)port_check_alive(pinfo, timeout);
int res = (int)port_check_alive(info_ptr, timeout);
if ((res < 0) && (res != ERR_INPROGRESS)) {
ESP_LOGE(TAG, MB_NODE_FMT(", is not writable, error: %d, errno %d"),
pinfo->index, pinfo->sock_id, pinfo->addr_info.ip_addr_str, res, (int)errno);
info_ptr->index, info_ptr->sock_id, info_ptr->addr_info.ip_addr_str, res, (int)errno);
return res;
}
res = send(pinfo->sock_id, pframe, frame_len, TCP_NODELAY);
res = send(info_ptr->sock_id, frame, frame_len, TCP_NODELAY);
if (res < 0) {
ESP_LOGE(TAG, MB_NODE_FMT(", send data error: %d, errno %d"),
pinfo->index, pinfo->sock_id, pinfo->addr_info.ip_addr_str, res, (int)errno);
info_ptr->index, info_ptr->sock_id, info_ptr->addr_info.ip_addr_str, res, (int)errno);
}
return res;
}
// Scan IP address according to IPV settings
int port_scan_addr_string(char *buffer, mb_uid_info_t *pinfo)
int port_scan_addr_string(char *buffer, mb_uid_info_t *info_ptr)
{
char *phost_str = NULL;
char *host_str = NULL;
unsigned int a[8] = {0};
int ret = 0;
uint16_t index = 0;
uint16_t port = 0;
MB_RETURN_ON_FALSE((buffer && (strlen(buffer) < (HOST_STR_MAX_LEN - 8)) && pinfo),
MB_RETURN_ON_FALSE((buffer && (strlen(buffer) < (HOST_STR_MAX_LEN - 8)) && info_ptr),
-1, TAG, "check input parameters fail.");
#if CONFIG_LWIP_IPV6
@@ -483,16 +486,16 @@ int port_scan_addr_string(char *buffer, mb_uid_info_t *pinfo)
// "12:2001:0db8:85a3:0000:0000:8a2e:0370:7334"
ret = sscanf(buffer, "%" PRIu16 ";" IPV6STR ";%" PRIu16, &index, &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6], &a[7], &port);
if ((ret == MB_STR_LEN_IDX_IP6) || (ret == MB_STR_LEN_IDX_IP6_PORT)) {
if (-1 == asprintf(&phost_str, IPV6STR, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7])) {
if (-1 == asprintf(&host_str, IPV6STR, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7])) {
abort();
}
pinfo->node_name_str = phost_str;
pinfo->ip_addr_str = phost_str;
pinfo->uid = index;
pinfo->fd = UNDEF_FD;
pinfo->port = (ret == MB_STR_LEN_IDX_IP6_PORT) ? port : CONFIG_FMB_TCP_PORT_DEFAULT;
pinfo->addr_type = MB_IPV6;
pinfo->proto = MB_TCP;
info_ptr->node_name_str = host_str;
info_ptr->ip_addr_str = host_str;
info_ptr->uid = index;
info_ptr->fd = UNDEF_FD;
info_ptr->port = (ret == MB_STR_LEN_IDX_IP6_PORT) ? port : CONFIG_FMB_TCP_PORT_DEFAULT;
info_ptr->addr_type = MB_IPV6;
info_ptr->proto = MB_TCP;
return ret;
}
@@ -500,16 +503,16 @@ int port_scan_addr_string(char *buffer, mb_uid_info_t *pinfo)
// "2001:0db8:85a3:0000:0000:8a2e:0370:7334"
ret = sscanf(buffer, IPV6STR, &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6], &a[7]);
if (ret == MB_STR_LEN_IP6_ONLY) {
if (-1 == asprintf(&phost_str, IPV6STR, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7])) {
if (-1 == asprintf(&host_str, IPV6STR, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7])) {
abort();
}
pinfo->node_name_str = phost_str;
pinfo->ip_addr_str = phost_str;
pinfo->uid = 0;
pinfo->fd = UNDEF_FD;
pinfo->port = CONFIG_FMB_TCP_PORT_DEFAULT;
pinfo->addr_type = MB_IPV6;
pinfo->proto = MB_TCP;
info_ptr->node_name_str = host_str;
info_ptr->ip_addr_str = host_str;
info_ptr->uid = 0;
info_ptr->fd = UNDEF_FD;
info_ptr->port = CONFIG_FMB_TCP_PORT_DEFAULT;
info_ptr->addr_type = MB_IPV6;
info_ptr->proto = MB_TCP;
return ret;
}
#endif
@@ -517,16 +520,16 @@ int port_scan_addr_string(char *buffer, mb_uid_info_t *pinfo)
// "192.168.1.1"
ret = sscanf(buffer, IPSTR, &a[0], &a[1], &a[2], &a[3]);
if (ret == MB_STR_LEN_IP4_ONLY) {
if (-1 == asprintf(&phost_str, IPSTR, a[0], a[1], a[2], a[3])) {
if (-1 == asprintf(&host_str, IPSTR, a[0], a[1], a[2], a[3])) {
abort();
}
pinfo->node_name_str = phost_str;
pinfo->ip_addr_str = phost_str;
pinfo->uid = 0;
pinfo->fd = UNDEF_FD;
pinfo->port = CONFIG_FMB_TCP_PORT_DEFAULT;
pinfo->addr_type = MB_IPV4;
pinfo->proto = MB_TCP;
info_ptr->node_name_str = host_str;
info_ptr->ip_addr_str = host_str;
info_ptr->uid = 0;
info_ptr->fd = UNDEF_FD;
info_ptr->port = CONFIG_FMB_TCP_PORT_DEFAULT;
info_ptr->addr_type = MB_IPV4;
info_ptr->proto = MB_TCP;
return ret;
}
@@ -534,45 +537,45 @@ int port_scan_addr_string(char *buffer, mb_uid_info_t *pinfo)
// "1:192.168.1.1:502"
ret = sscanf(buffer, "%" PRIu16 ";"IPSTR";%" PRIu16, &index, &a[0], &a[1], &a[2], &a[3], &port);
if ((ret == MB_STR_LEN_IDX_IP4_PORT) || (ret == MB_STR_LEN_IDX_IP4)) {
if (-1 == asprintf(&phost_str, IPSTR, a[0], a[1], a[2], a[3])) {
if (-1 == asprintf(&host_str, IPSTR, a[0], a[1], a[2], a[3])) {
abort();
}
pinfo->node_name_str = phost_str;
pinfo->ip_addr_str = phost_str;
pinfo->uid = index;
pinfo->fd = UNDEF_FD;
pinfo->port = (ret == MB_STR_LEN_IDX_IP4_PORT) ? port : CONFIG_FMB_TCP_PORT_DEFAULT;
pinfo->addr_type = MB_IPV4;
pinfo->proto = MB_TCP;
info_ptr->node_name_str = host_str;
info_ptr->ip_addr_str = host_str;
info_ptr->uid = index;
info_ptr->fd = UNDEF_FD;
info_ptr->port = (ret == MB_STR_LEN_IDX_IP4_PORT) ? port : CONFIG_FMB_TCP_PORT_DEFAULT;
info_ptr->addr_type = MB_IPV4;
info_ptr->proto = MB_TCP;
return ret;
}
// Configuration format:
// "01:mb_node_tcp_01:502"
ret = sscanf(buffer, "%" PRIu16 ";%m[a-z0-9_];%" PRIu16, (uint16_t*)&index, &phost_str, &port);
ret = sscanf(buffer, "%" PRIu16 ";%m[a-z0-9_];%" PRIu16, &index, &host_str, &port);
if ((ret == MB_STR_LEN_HOST) || (ret == MB_STR_LEN_IDX_HOST_PORT)) {
pinfo->node_name_str = (phost_str && strlen(phost_str)) ? phost_str : pinfo->node_name_str;
pinfo->ip_addr_str = (pinfo->node_name_str) ? pinfo->node_name_str : pinfo->ip_addr_str;
pinfo->uid = index;
pinfo->fd = UNDEF_FD;
pinfo->port = (ret == MB_STR_LEN_IDX_HOST_PORT) ? port : CONFIG_FMB_TCP_PORT_DEFAULT;
pinfo->addr_type = MB_IPV4;
pinfo->proto = MB_TCP;
info_ptr->node_name_str = (host_str && strlen(host_str)) ? host_str : info_ptr->node_name_str;
info_ptr->ip_addr_str = (info_ptr->node_name_str) ? info_ptr->node_name_str : info_ptr->ip_addr_str;
info_ptr->uid = index;
info_ptr->fd = UNDEF_FD;
info_ptr->port = (ret == MB_STR_LEN_IDX_HOST_PORT) ? port : CONFIG_FMB_TCP_PORT_DEFAULT;
info_ptr->addr_type = MB_IPV4;
info_ptr->proto = MB_TCP;
return ret;
}
// Configuration format:
// "mb_node_tcp_01"
ret = sscanf(buffer, "%m[a-z0-9_]", &phost_str);
ret = sscanf(buffer, "%m[a-z0-9_]", &host_str);
if (ret == MB_STR_LEN_HOST) {
pinfo->node_name_str = (phost_str && strlen(phost_str)) ? phost_str : pinfo->node_name_str;
pinfo->ip_addr_str = (pinfo->node_name_str) ? pinfo->node_name_str : pinfo->ip_addr_str;
pinfo->uid = index;
pinfo->fd = UNDEF_FD;
pinfo->port = CONFIG_FMB_TCP_PORT_DEFAULT;
pinfo->addr_type = MB_IPV4;
pinfo->proto = MB_TCP;
info_ptr->node_name_str = (host_str && strlen(host_str)) ? host_str : info_ptr->node_name_str;
info_ptr->ip_addr_str = (info_ptr->node_name_str) ? info_ptr->node_name_str : info_ptr->ip_addr_str;
info_ptr->uid = index;
info_ptr->fd = UNDEF_FD;
info_ptr->port = CONFIG_FMB_TCP_PORT_DEFAULT;
info_ptr->addr_type = MB_IPV4;
info_ptr->proto = MB_TCP;
return ret;
}
@@ -584,20 +587,20 @@ int port_scan_addr_string(char *buffer, mb_uid_info_t *pinfo)
static int mdns_instance_count = 0;
// This function has limitation of working with IP6 address only
esp_err_t port_start_mdns_service(char **ppdns_name, bool is_master, int uid, void *pnode_netif)
esp_err_t port_start_mdns_service(char **dns_name, bool is_master, int uid, void *node_netif)
{
char temp_str[HOST_STR_MAX_LEN] = {0};
esp_ip6_addr_t ip6[LWIP_IPV6_NUM_ADDRESSES];
int ip6_addrs_count = 0;
esp_err_t err = ESP_ERR_INVALID_STATE;
MB_RETURN_ON_FALSE((pnode_netif),
MB_RETURN_ON_FALSE((node_netif),
err, TAG, "Invalid parameters for dns.");
// initialize mDNS
err = mdns_init(); // if the mdns is already initialized on higher layer, just returns
MB_RETURN_ON_FALSE(((err == ESP_OK) && pnode_netif), err, TAG, "mdns init fail, err = %d.", (int)err);
MB_RETURN_ON_FALSE(((err == ESP_OK) && node_netif), err, TAG, "mdns init fail, err = %d.", (int)err);
esp_netif_t *pnetif = (esp_netif_t*)pnode_netif;
esp_netif_t *pnetif = (esp_netif_t*)node_netif;
// set mDNS hostname (required if need to advertise services)
err = mdns_hostname_get(temp_str);
if (err != ESP_OK) {
@@ -614,9 +617,9 @@ esp_err_t port_start_mdns_service(char **ppdns_name, bool is_master, int uid, vo
err, TAG, "mdns instance name set fail, err = %d.", (int)err);
}
// Check if the default mdns name is defined in the configuration
if (ppdns_name && *ppdns_name && (strlen(*ppdns_name) >= MB_MDNS_STR_MIN_LENGTH)) {
strncpy(temp_str, *ppdns_name, strlen(*ppdns_name));
*ppdns_name[strlen(*ppdns_name)] = '\0';
if (dns_name && *dns_name && (strlen(*dns_name) >= MB_MDNS_STR_MIN_LENGTH)) {
strncpy(temp_str, *dns_name, strlen(*dns_name));
*dns_name[strlen(*dns_name)] = '\0';
} else {
if (snprintf(temp_str, sizeof(temp_str), "%s_%02x", MB_MDNS_INST_NAME(is_master), uid) <= 0) {
return ESP_ERR_INVALID_STATE;
@@ -624,8 +627,8 @@ esp_err_t port_start_mdns_service(char **ppdns_name, bool is_master, int uid, vo
}
// Setup the real assigned dns_name instead of constant string
if (ppdns_name) {
*ppdns_name = strdup(temp_str);
if (dns_name) {
*dns_name = strdup(temp_str);
}
esp_netif_ip_info_t ip_info;
@@ -669,12 +672,12 @@ esp_err_t port_start_mdns_service(char **ppdns_name, bool is_master, int uid, vo
return ESP_OK;
}
void port_stop_mdns_service(char **ppdns_name)
void port_stop_mdns_service(char **dns_name)
{
if (ppdns_name && *ppdns_name) {
mdns_delegate_hostname_remove(*ppdns_name);
free(*ppdns_name);
*ppdns_name = NULL;
if (dns_name && *dns_name) {
mdns_delegate_hostname_remove(*dns_name);
free(*dns_name);
*dns_name = NULL;
if (mdns_instance_count) {
mdns_instance_count--;
}
@@ -755,12 +758,12 @@ void port_stop_mdns_service(char **ppdns_name)
// return ESP_ERR_NOT_FOUND;
// }
int port_resolve_mdns_host(const char *host_name, char **paddr_str)
int port_resolve_mdns_host(const char *host_name, char **addr_str)
{
ESP_LOGD(TAG, "Query A: %s.local", host_name);
esp_ip_addr_t addr;
char *pstr = NULL;
char *string_ptr = NULL;
bzero(&addr, sizeof(esp_ip_addr_t));
// Try to send query to obtain the IPv4 address
@@ -774,7 +777,7 @@ int port_resolve_mdns_host(const char *host_name, char **paddr_str)
return -1;
}
addr.type = ESP_IPADDR_TYPE_V6;
if (asprintf(&pstr, IPV6STR, IPV62STR(addr.u_addr.ip6) == -1)) {
if (asprintf(&string_ptr, IPV6STR, IPV62STR(addr.u_addr.ip6)) == -1) {
abort();
}
} else {
@@ -782,15 +785,15 @@ int port_resolve_mdns_host(const char *host_name, char **paddr_str)
}
} else {
addr.type = ESP_IPADDR_TYPE_V4;
if (asprintf(&pstr, IPSTR, IP2STR(&addr.u_addr.ip4)) == -1) {
if (asprintf(&string_ptr, IPSTR, IP2STR(&addr.u_addr.ip4)) == -1) {
abort();
}
}
if (paddr_str) {
ESP_LOGD(TAG, "Node: %s, was resolved with IP: %s", host_name, pstr);
*paddr_str = pstr;
if (addr_str) {
ESP_LOGD(TAG, "Node: %s, was resolved with IP: %s", host_name, string_ptr);
*addr_str = string_ptr;
}
return strlen(pstr);
return strlen(string_ptr);
}
#endif // #ifdef MB_MDNS_IS_INCLUDED
@@ -801,9 +804,9 @@ int port_bind_addr(const char *pbind_ip, mb_addr_type_t addr_type, mb_comm_mode_
int temp_par, ret;
int listen_sock_fd = -1;
struct addrinfo hint;
struct addrinfo *paddr_list;
struct addrinfo *pcur_addr;
char* pstr = NULL;
struct addrinfo *addr_list;
struct addrinfo *cur_addr;
char* string_ptr = NULL;
memset(&hint, 0, sizeof(hint));
@@ -816,22 +819,22 @@ int port_bind_addr(const char *pbind_ip, mb_addr_type_t addr_type, mb_comm_mode_
hint.ai_protocol = (proto == MB_UDP) ? IPPROTO_UDP : IPPROTO_TCP;
hint.ai_flags = AI_NUMERICSERV | AI_PASSIVE | AI_CANONNAME;
if (asprintf(&pstr, "%u", port) == -1) {
if (asprintf(&string_ptr, "%u", port) == -1) {
abort();
}
ret = getaddrinfo(pbind_ip, pstr, &hint, &paddr_list);
free(pstr);
ret = getaddrinfo(pbind_ip, string_ptr, &hint, &addr_list);
free(string_ptr);
if ((ret != 0) ) {
return -1;
}
// Try the sockaddr until a binding succeeds
for (pcur_addr = paddr_list; pcur_addr != NULL; pcur_addr = pcur_addr->ai_next)
for (cur_addr = addr_list; cur_addr!= NULL; cur_addr = cur_addr->ai_next)
{
listen_sock_fd = (int)socket(pcur_addr->ai_family, pcur_addr->ai_socktype,
pcur_addr->ai_protocol);
listen_sock_fd = socket(cur_addr->ai_family, cur_addr->ai_socktype,
cur_addr->ai_protocol);
if (listen_sock_fd < 0)
{
continue;
@@ -847,8 +850,8 @@ int port_bind_addr(const char *pbind_ip, mb_addr_type_t addr_type, mb_comm_mode_
continue;
}
if (bind(listen_sock_fd, (struct sockaddr *)pcur_addr->ai_addr,
(socklen_t)pcur_addr->ai_addrlen) != 0 )
if (bind(listen_sock_fd, cur_addr->ai_addr,
(socklen_t)cur_addr->ai_addrlen) != 0 )
{
close(listen_sock_fd);
listen_sock_fd = UNDEF_FD;
@@ -868,19 +871,19 @@ int port_bind_addr(const char *pbind_ip, mb_addr_type_t addr_type, mb_comm_mode_
}
}
// Bind was successful
pstr = (pcur_addr->ai_canonname == NULL) ? (char *)"\0" : pcur_addr->ai_canonname;
string_ptr = (cur_addr->ai_canonname == NULL) ? (char *)"\0" : cur_addr->ai_canonname;
ESP_LOGI(TAG, "Socket (#%d), listener %s on port: %u, errno=%u",
(int)listen_sock_fd, pstr, (unsigned)port, (unsigned)errno);
(int)listen_sock_fd, string_ptr, (unsigned)port, (unsigned)errno);
break;
}
freeaddrinfo(paddr_list);
freeaddrinfo(addr_list);
return(listen_sock_fd);
}
int port_accept_connection(int listen_sock_id, mb_uid_info_t *pinfo)
int port_accept_connection(int listen_sock_id, mb_uid_info_t *info_ptr)
{
MB_RETURN_ON_FALSE((pinfo), -1, TAG, "Wrong parameter pointer.");
MB_RETURN_ON_FALSE((info_ptr), -1, TAG, "Wrong parameter pointer.");
MB_RETURN_ON_FALSE((listen_sock_id > 0), -1, TAG, "Incorrect listen socket ID.");
// Address structure large enough for both IPv4 or IPv6 address
@@ -900,28 +903,28 @@ int port_accept_connection(int listen_sock_id, mb_uid_info_t *pinfo)
// Get the sender's ip address as string
if (src_addr.ss_family == PF_INET) {
inet_ntoa_r(((struct sockaddr_in *)&src_addr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1);
pinfo->port = ntohs(((struct sockaddr_in *)&src_addr)->sin_port);
pinfo->addr_type = MB_IPV4;
info_ptr->port = ntohs(((struct sockaddr_in *)&src_addr)->sin_port);
info_ptr->addr_type = MB_IPV4;
}
#if CONFIG_LWIP_IPV6
else if (src_addr.ss_family == PF_INET6) {
inet6_ntoa_r(((struct sockaddr_in6 *)&src_addr)->sin6_addr, addr_str, sizeof(addr_str) - 1);
pinfo->port = ntohs(((struct sockaddr_in6 *)&src_addr)->sin6_port);
pinfo->addr_type = MB_IPV6;
info_ptr->port = ntohs(((struct sockaddr_in6 *)&src_addr)->sin6_port);
info_ptr->addr_type = MB_IPV6;
}
#endif
else {
// Make sure ss_family is valid
abort();
}
ESP_LOGI(TAG, "Socket (#%d), accept client connection from address[port]: %s[%d]", (int)sock_id, addr_str, pinfo->port);
ESP_LOGI(TAG, "Socket (#%d), accept client connection from address[port]: %s[%d]", (int)sock_id, addr_str, info_ptr->port);
paddr = strdup(addr_str);
if (paddr) {
pinfo->fd = sock_id;
pinfo->ip_addr_str = paddr;
pinfo->node_name_str = paddr;
pinfo->proto = MB_TCP;
pinfo->uid = 0;
info_ptr->fd = sock_id;
info_ptr->ip_addr_str = paddr;
info_ptr->node_name_str = paddr;
info_ptr->proto = MB_TCP;
info_ptr->uid = 0;
}
}
return sock_id;

View File

@@ -80,48 +80,48 @@ extern "C" {
} \
))
typedef struct _frame_queue_entry frame_entry_t;
typedef struct _mb_node_info mb_node_info_t;
typedef enum _addr_type_enum mb_tcp_addr_type_t;
typedef struct frame_queue_entry_s frame_entry_t;
typedef struct mb_node_info_s mb_node_info_t;
typedef enum addr_type_enum mb_tcp_addr_type_t;
bool port_check_host_addr(const char *host_str, ip_addr_t* host_addr);
mb_node_info_t* port_get_current_info(void *ctx);
void port_check_shutdown(void *ctx);
int64_t port_get_resp_time_left(mb_node_info_t* pinfo);
int port_enqueue_packet(QueueHandle_t queue, uint8_t *pbuf, uint16_t len);
int port_dequeue_packet(QueueHandle_t queue, frame_entry_t* pframe_info);
int port_read_packet(mb_node_info_t* pinfo);
err_t port_set_blocking(mb_node_info_t* pinfo, bool is_blocking);
int64_t port_get_resp_time_left(mb_node_info_t* info_ptr);
int port_enqueue_packet(QueueHandle_t queue, uint8_t *buf, uint16_t len);
int port_dequeue_packet(QueueHandle_t queue, frame_entry_t* frame_info);
int port_read_packet(mb_node_info_t* info_ptr);
err_t port_set_blocking(mb_node_info_t* info_ptr, bool is_blocking);
int port_keep_alive(int sock);
err_t port_check_alive(mb_node_info_t* pinfo, uint32_t timeout_ms);
err_t port_connect(void *ctx, mb_node_info_t* pinfo);
bool port_close_connection(mb_node_info_t* pinfo);
int port_write_poll(mb_node_info_t* pinfo, const uint8_t *pframe, uint16_t frame_len, uint32_t timeout);
err_t port_check_alive(mb_node_info_t* info_ptr, uint32_t timeout_ms);
err_t port_connect(void *ctx, mb_node_info_t* info_ptr);
bool port_close_connection(mb_node_info_t* info_ptr);
int port_write_poll(mb_node_info_t* info_ptr, const uint8_t *frame, uint16_t frame_len, uint32_t timeout);
int64_t port_get_timestamp(void);
typedef struct _uid_info mb_uid_info_t;
typedef struct uid_info_s mb_uid_info_t;
int port_scan_addr_string(char *buffer, mb_uid_info_t *pnode_info);
int port_scan_addr_string(char *buffer, mb_uid_info_t *info_ptr);
#if MB_MDNS_IS_INCLUDED
// Init mdns service
esp_err_t port_start_mdns_service(char **ppdns_name, bool is_master, int uid, void *pnode_netif);
void port_stop_mdns_service(char **ppdns_name);
esp_err_t port_start_mdns_service(char **dns_name, bool is_master, int uid, void *node_netif);
void port_stop_mdns_service(char **dns_name);
typedef struct mdns_ip_addr_s mdns_ip_addr_t;
typedef struct mdns_result_s mdns_result_t;
char *port_get_node_ip_str(mdns_ip_addr_t *address, mb_addr_type_t addr_type);
esp_err_t port_resolve_slave(uint8_t short_addr, mdns_result_t *result, char **resolved_ip, mb_addr_type_t addr_type);
int port_resolve_mdns_host(const char *host_name, char **paddr_str);
int port_resolve_mdns_host(const char *host_name, char **addr_str);
#endif
// Modbus slave utility functions
int port_bind_addr(const char *pbind_ip, mb_addr_type_t addr_type, mb_comm_mode_t proto, uint16_t port);
int port_accept_connection(int listen_sock_id, mb_uid_info_t *pnode_info);
int port_accept_connection(int listen_sock_id, mb_uid_info_t *info_ptr);
#ifdef __cplusplus
}

View File

@@ -11,34 +11,35 @@
/* ----------------------- functions ---------------------------------*/
uint8_t mb_char2bin(uint8_t char_val)
{
uint8_t symb = 0xFF;
if ((char_val >= '0') && (char_val <= '9')) {
return (uint8_t)(char_val - '0');
symb = (uint8_t)(char_val - '0');
} else if ((char_val >= 'A') && (char_val <= 'F')) {
return (uint8_t)(char_val - 'A' + 0x0A);
} else {
return 0xFF;
symb = (uint8_t)(char_val - 'A' + 0x0A);
}
return symb;
}
uint8_t mb_bin2char(uint8_t byte_val)
{
uint8_t symb = '0';
if (byte_val <= 0x09) {
return (uint8_t)('0' + byte_val);
symb = (uint8_t)('0' + byte_val);
} else if ((byte_val >= 0x0A) && (byte_val <= 0x0F)) {
return (uint8_t)(byte_val - 0x0A + 'A');
symb = (uint8_t)(byte_val - 0x0A + 'A');
} else {
/* Programming error. */
assert(0);
}
return '0';
return symb;
}
uint8_t __attribute__ ((unused)) mb_lrc(uint8_t *pframe, uint16_t length)
uint8_t __attribute__ ((unused)) mb_lrc(uint8_t *frame, uint16_t length)
{
uint8_t lrc = 0; /* LRC char initialized */
while (length--) {
lrc += *pframe++; /* Add buffer byte without carry */
lrc += *frame++; /* Add buffer byte without carry */
}
/* Return twos complement */
@@ -47,41 +48,41 @@ uint8_t __attribute__ ((unused)) mb_lrc(uint8_t *pframe, uint16_t length)
}
// The helper function to fill ASCII frame buffer
int mb_ascii_set_buf(const uint8_t *pdata, uint8_t *pbuf, int bin_length)
int mb_ascii_set_buf(const uint8_t *data_ptr, uint8_t *buf, int bin_length)
{
int bin_idx = 0;
int frm_idx = 0;
uint8_t lrc = 0;
assert(pdata && pbuf);
assert(data_ptr && buf);
pbuf[0] = MB_ASCII_START;
buf[0] = MB_ASCII_START;
for (frm_idx = 1; (bin_idx < bin_length); bin_idx++) {
pbuf[frm_idx++] = mb_bin2char((uint8_t)(pdata[bin_idx] >> 4)); // High nibble
pbuf[frm_idx++] = mb_bin2char((uint8_t)(pdata[bin_idx] & 0X0F)); // Low nibble
lrc += pdata[bin_idx];
buf[frm_idx++] = mb_bin2char((uint8_t)(data_ptr[bin_idx] >> 4)); // High nibble
buf[frm_idx++] = mb_bin2char((uint8_t)(data_ptr[bin_idx] & 0X0F)); // Low nibble
lrc += data_ptr[bin_idx];
}
lrc = (uint8_t)(-((char)lrc));
pbuf[frm_idx++] = mb_bin2char((uint8_t)(lrc >> 4));
pbuf[frm_idx++] = mb_bin2char((uint8_t)(lrc & 0X0F));
pbuf[frm_idx++] = MB_ASCII_CR;
pbuf[frm_idx++] = MB_ASCII_LF;
buf[frm_idx++] = mb_bin2char((uint8_t)(lrc >> 4));
buf[frm_idx++] = mb_bin2char((uint8_t)(lrc & 0X0F));
buf[frm_idx++] = MB_ASCII_CR;
buf[frm_idx++] = MB_ASCII_LF;
return frm_idx;
}
int mb_ascii_get_binary_buf(uint8_t *pdata, int length)
int mb_ascii_get_binary_buf(uint8_t *data_ptr, int length)
{
int bin_idx = 0;
uint8_t lrc = 0;
assert(pdata);
assert(data_ptr);
if ((pdata[0] == ':') && (pdata[length - 1] == '\n') && (pdata[length - 2] == '\r')) {
for (int str_idx = 1; (str_idx < length) && (pdata[str_idx] > ' '); str_idx += 2) {
pdata[bin_idx] = (mb_char2bin(pdata[str_idx]) << 4); // High nibble
pdata[bin_idx] |= mb_char2bin(pdata[str_idx + 1]); // Low nibble
lrc += pdata[bin_idx++];
if ((data_ptr[0] == ':') && (data_ptr[length - 1] == '\n') && (data_ptr[length - 2] == '\r')) {
for (int str_idx = 1; (str_idx < length) && (data_ptr[str_idx] > ' '); str_idx += 2) {
data_ptr[bin_idx] = (mb_char2bin(data_ptr[str_idx]) << 4); // High nibble
data_ptr[bin_idx] |= mb_char2bin(data_ptr[str_idx + 1]); // Low nibble
lrc += data_ptr[bin_idx++];
}
}

View File

@@ -15,6 +15,6 @@
/* ----------------------- Static functions ---------------------------------*/
uint8_t mb_char2bin(uint8_t char_val);
uint8_t mb_bin2char(uint8_t byte_val);
uint8_t mb_lrc(uint8_t *frame_ptr, uint16_t len_buf);
int mb_ascii_get_binary_buf(uint8_t *pdata, int length);
int mb_ascii_set_buf(const uint8_t *pdata, uint8_t *pbuf, int bin_length);
uint8_t mb_lrc(uint8_t *frame, uint16_t length);
int mb_ascii_get_binary_buf(uint8_t *data_ptr, int length);
int mb_ascii_set_buf(const uint8_t *data_ptr, uint8_t *buf, int bin_length);

View File

@@ -28,12 +28,12 @@ typedef struct
volatile mb_timer_mode_enum_t cur_timer_mode;
} mbm_ascii_trasp_t;
static mb_err_enum_t mbm_ascii_transp_receive(mb_trans_base_t *inst, uint8_t *rcv_addr_buf, uint8_t **frame_ptr_buf, uint16_t *len_buf);
static mb_err_enum_t mbm_ascii_transp_receive(mb_trans_base_t *inst, uint8_t *recv_addr, uint8_t **frame_buf, uint16_t *buf_len);
static mb_err_enum_t mbm_ascii_transp_send(mb_trans_base_t *inst, uint8_t slv_addr, const uint8_t *frame_ptr, uint16_t len);
static void mbm_ascii_transp_start(mb_trans_base_t *inst);
static void mbm_ascii_transp_stop(mb_trans_base_t *inst);
static void mbm_ascii_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf);
static void mbm_ascii_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf);
static void mbm_ascii_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_buf);
static void mbm_ascii_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_buf);
static bool mbm_ascii_transp_timer_expired(void *inst);
static bool mbm_ascii_transp_rq_is_bcast(mb_trans_base_t *inst);
@@ -42,9 +42,11 @@ mb_err_enum_t mbm_ascii_transp_create(mb_serial_opts_t *ser_opts, void **in_out_
MB_RETURN_ON_FALSE((ser_opts && in_out_inst), MB_EINVAL, TAG, "invalid options for the instance.");
mb_err_enum_t ret = MB_ENOERR;
mbm_ascii_trasp_t *transp = NULL;
mb_port_base_t *port_obj = NULL;
transp = (mbm_ascii_trasp_t *)calloc(1, sizeof(mbm_ascii_trasp_t));
MB_GOTO_ON_FALSE((transp), MB_EILLSTATE, error, TAG, "no mem for transport instance.");
transp->pascii_puf = calloc(1, MB_ASCII_SER_PDU_SIZE_MAX);
MB_RETURN_ON_FALSE((transp && transp->pascii_puf), MB_EILLSTATE, TAG, "no mem for ascii master transport instance.");
MB_GOTO_ON_FALSE((transp->pascii_puf), MB_EILLSTATE, error, TAG, "no mem for ascii master transport instance.");
CRITICAL_SECTION_INIT(transp->base.lock);
CRITICAL_SECTION_LOCK(transp->base.lock);
transp->base.frm_rcv = mbm_ascii_transp_receive;
@@ -57,7 +59,7 @@ mb_err_enum_t mbm_ascii_transp_create(mb_serial_opts_t *ser_opts, void **in_out_
transp->base.frm_is_bcast = mbm_ascii_transp_rq_is_bcast;
transp->base.descr = ((mb_port_base_t *)*in_out_inst)->descr;
transp->base.descr.obj_name = (char *)TAG;
mb_port_base_t *port_obj = (mb_port_base_t *)*in_out_inst;
port_obj = (mb_port_base_t *)*in_out_inst;
ret = mb_port_ser_create(ser_opts, &port_obj);
MB_GOTO_ON_FALSE((ret == MB_ENOERR), MB_EPORTERR, error, TAG, "serial port creation, err: %d", ret);
ret = mb_port_timer_create(port_obj, (MB_ASCII_TIMEOUT_MS * MB_TIMER_TICS_PER_MS));
@@ -81,15 +83,17 @@ mb_err_enum_t mbm_ascii_transp_create(mb_serial_opts_t *ser_opts, void **in_out_
return MB_ENOERR;
error:
if (transp) {
free((void *)transp->pascii_puf);
transp->pascii_puf = NULL;
CRITICAL_SECTION_UNLOCK(transp->base.lock);
CRITICAL_SECTION_CLOSE(transp->base.lock);
}
if (port_obj) {
free(port_obj->event_obj);
free(port_obj->timer_obj);
}
free(port_obj);
CRITICAL_SECTION_UNLOCK(transp->base.lock);
CRITICAL_SECTION_CLOSE(transp->base.lock);
free(transp);
return ret;
}
@@ -129,19 +133,19 @@ static void mbm_ascii_transp_stop(mb_trans_base_t *inst)
};
}
static mb_err_enum_t mbm_ascii_transp_receive(mb_trans_base_t *inst, uint8_t *prcv_addr, uint8_t **ppframe_buf, uint16_t *pbuf_len)
static mb_err_enum_t mbm_ascii_transp_receive(mb_trans_base_t *inst, uint8_t *recv_addr, uint8_t **frame_buf, uint16_t *buf_len)
{
mbm_ascii_trasp_t *transp = __containerof(inst, mbm_ascii_trasp_t, base);
mb_err_enum_t status = MB_ENOERR;
if (!pbuf_len) {
if (!buf_len) {
return MB_EIO;
}
uint8_t *pbuf = (uint8_t *)transp->rcv_buf;
uint16_t length = *pbuf_len;
uint8_t *buf = (uint8_t *)transp->rcv_buf;
uint16_t length = *buf_len;
if (mb_port_ser_recv_data(inst->port_obj, &pbuf, &length) == false)
if (mb_port_ser_recv_data(inst->port_obj, &buf, &length) == false)
{
return MB_EPORTERR;
}
@@ -149,23 +153,23 @@ static mb_err_enum_t mbm_ascii_transp_receive(mb_trans_base_t *inst, uint8_t *pr
assert(length < MB_ASCII_SER_PDU_SIZE_MAX);
// Convert the received ascii frame buffer to the binary representation
int ret = mb_ascii_get_binary_buf(pbuf, length);
int ret = mb_ascii_get_binary_buf(buf, length);
/* Check length and LRC checksum */
if (ret >= MB_ASCII_SER_PDU_SIZE_MIN) {
/* Save the address field. All frames are passed to the upper layed
* and the decision if a frame is used is done there.
*/
*prcv_addr = pbuf[MB_SER_PDU_ADDR_OFF];
*recv_addr = buf[MB_SER_PDU_ADDR_OFF];
/* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
* size of address field and LRC checksum.
*/
*pbuf_len = (uint16_t)(ret - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_LRC);
*buf_len = (uint16_t)(ret - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_LRC);
transp->rcv_buf_pos = ret;
/* Return the start of the Modbus PDU to the caller. */
*ppframe_buf = (uint8_t *)&pbuf[MB_SER_PDU_PDU_OFF];
*frame_buf = &buf[MB_SER_PDU_PDU_OFF];
} else {
status = MB_EIO;
}
@@ -191,9 +195,9 @@ static mb_err_enum_t mbm_ascii_transp_send(mb_trans_base_t *inst, uint8_t slv_ad
transp->snd_buf_cnt += frame_len;
/* Prepare the ASCII buffer and send it to port */
int ascii_len = mb_ascii_set_buf(transp->snd_buf_cur, (uint8_t *)transp->pascii_puf, transp->snd_buf_cnt);
int ascii_len = mb_ascii_set_buf(transp->snd_buf_cur, transp->pascii_puf, transp->snd_buf_cnt);
if (ascii_len > MB_ASCII_SER_PDU_SIZE_MIN) {
bool ret = mb_port_ser_send_data(inst->port_obj, (uint8_t *)transp->pascii_puf, ascii_len);
bool ret = mb_port_ser_send_data(inst->port_obj, transp->pascii_puf, ascii_len);
if (!ret) {
return MB_EPORTERR;
}
@@ -264,19 +268,19 @@ static bool mbm_ascii_transp_timer_expired(void *inst)
return need_poll;
}
static void mbm_ascii_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf)
static void mbm_ascii_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_buf)
{
mbm_ascii_trasp_t *transp = __containerof(inst, mbm_ascii_trasp_t, base);
CRITICAL_SECTION(inst->lock) {
*frame_ptr_buf = (uint8_t *)&transp->rcv_buf[MB_PDU_FUNC_OFF];
*frame_buf = &transp->rcv_buf[MB_PDU_FUNC_OFF];
}
}
static void mbm_ascii_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf)
static void mbm_ascii_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_buf)
{
mbm_ascii_trasp_t *transp = __containerof(inst, mbm_ascii_trasp_t, base);
CRITICAL_SECTION(inst->lock) {
*frame_ptr_buf = (uint8_t *)&transp->snd_buf[MB_ASCII_SER_PDU_PDU_OFF];
*frame_buf = &transp->snd_buf[MB_ASCII_SER_PDU_PDU_OFF];
}
}

View File

@@ -31,23 +31,24 @@ typedef struct
mb_err_enum_t mbs_ascii_transp_create(mb_serial_opts_t *ser_opts, void **in_out_inst);
static void mbs_ascii_transp_start(mb_trans_base_t *inst);
static void mbs_ascii_transp_stop(mb_trans_base_t *inst);
static mb_err_enum_t mbs_ascii_transp_receive(mb_trans_base_t *inst, uint8_t *rcv_addr_buf, uint8_t **frame_ptr_buf, uint16_t *len_buf);
static mb_err_enum_t mbs_ascii_transp_receive(mb_trans_base_t *inst, uint8_t *recv_addr, uint8_t **frame_buf, uint16_t *buf_len);
static mb_err_enum_t mbs_ascii_transp_send(mb_trans_base_t *inst, uint8_t slv_addr, const uint8_t *frame_ptr, uint16_t len);
static bool mbs_ascii_transp_rcv_fsm(mb_trans_base_t *inst);
static bool mbs_ascii_transp_snd_fsm(mb_trans_base_t *inst);
static bool mbs_ascii_transp_timer_expired(void *inst);
void mbs_ascii_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf);
static void mbs_ascii_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf);
void mbs_ascii_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_buf);
static void mbs_ascii_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_buf);
mb_err_enum_t mbs_ascii_transp_create(mb_serial_opts_t *ser_opts, void **in_out_inst)
{
MB_RETURN_ON_FALSE((ser_opts && in_out_inst), MB_EINVAL, TAG, "invalid options for the instance.");
mb_err_enum_t ret = MB_ENOERR;
mbs_ascii_trasp_t *transp = NULL;
mb_port_base_t *port_obj = NULL;
transp = (mbs_ascii_trasp_t *)calloc(1, sizeof(mbs_ascii_trasp_t));
MB_RETURN_ON_FALSE(transp, MB_EILLSTATE, TAG, "no mem for the %s instance.", TAG);
MB_GOTO_ON_FALSE(transp, MB_EILLSTATE, error, TAG, "no mem for the %s instance.", TAG);
transp->pascii_puf = calloc(1, MB_ASCII_SER_PDU_SIZE_MAX);
MB_RETURN_ON_FALSE((transp && transp->pascii_puf), MB_EILLSTATE, TAG, "no mem for the %s instance.", TAG);
MB_GOTO_ON_FALSE((transp->pascii_puf), MB_EILLSTATE, error, TAG, "no mem for the %s instance.", TAG);
CRITICAL_SECTION_INIT(transp->base.lock);
transp->base.frm_rcv = mbs_ascii_transp_receive;
transp->base.frm_send = mbs_ascii_transp_send;
@@ -59,7 +60,7 @@ mb_err_enum_t mbs_ascii_transp_create(mb_serial_opts_t *ser_opts, void **in_out_
transp->base.frm_is_bcast = NULL;
transp->base.descr = ((mb_port_base_t *)*in_out_inst)->descr;
transp->base.descr.obj_name = (char *)TAG;
mb_port_base_t *port_obj = (mb_port_base_t *)*in_out_inst;
port_obj = (mb_port_base_t *)*in_out_inst;
ret = mb_port_ser_create(ser_opts, &port_obj);
MB_GOTO_ON_FALSE((ret == MB_ENOERR), MB_EPORTERR, error, TAG, "serial port creation, err: %d", ret);
ret = mb_port_timer_create(port_obj, (MB_ASCII_TIMEOUT_MS * MB_TIMER_TICS_PER_MS));
@@ -79,14 +80,17 @@ mb_err_enum_t mbs_ascii_transp_create(mb_serial_opts_t *ser_opts, void **in_out_
return MB_ENOERR;
error:
if (transp) {
free(transp->pascii_puf);
transp->pascii_puf = NULL;
CRITICAL_SECTION_UNLOCK(transp->base.lock);
CRITICAL_SECTION_CLOSE(transp->base.lock);
}
if (port_obj) {
free(port_obj->event_obj);
free(port_obj->timer_obj);
}
free(port_obj);
CRITICAL_SECTION_CLOSE(transp->base.lock);
free(transp);
return ret;
}
@@ -125,39 +129,39 @@ static void mbs_ascii_transp_stop(mb_trans_base_t *inst)
};
}
static mb_err_enum_t mbs_ascii_transp_receive(mb_trans_base_t *inst, uint8_t *prcv_addr, uint8_t **ppframe_buf, uint16_t *pbuf_len)
static mb_err_enum_t mbs_ascii_transp_receive(mb_trans_base_t *inst, uint8_t *recv_addr, uint8_t **frame_buf, uint16_t *buf_len)
{
mbs_ascii_trasp_t *transp = __containerof(inst, mbs_ascii_trasp_t, base);
mb_err_enum_t status = MB_ENOERR;
assert(transp->rcv_buf);
uint8_t *pbuf = (uint8_t *)transp->rcv_buf;
uint16_t length = *pbuf_len;
uint8_t *buf = transp->rcv_buf;
uint16_t length = *buf_len;
if (mb_port_ser_recv_data(inst->port_obj, &pbuf, &length) == false) {
if (mb_port_ser_recv_data(inst->port_obj, &buf, &length) == false) {
return MB_EPORTERR;
}
assert(length < MB_ASCII_SER_PDU_SIZE_MAX);
// Convert the received ascii frame buffer to the binary representation
int ret = mb_ascii_get_binary_buf(pbuf, length);
int ret = mb_ascii_get_binary_buf(buf, length);
/* Check length and CRC checksum */
if (ret >= MB_ASCII_SER_PDU_SIZE_MIN) {
/* Save the address field. All frames are passed to the upper layed
* and the decision if a frame is used is done there.
*/
*prcv_addr = pbuf[MB_SER_PDU_ADDR_OFF];
*recv_addr = buf[MB_SER_PDU_ADDR_OFF];
/* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
* size of address field and LRC checksum.
*/
*pbuf_len = (uint16_t)(ret - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_LRC);
*buf_len = (uint16_t)(ret - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_LRC);
transp->rcv_buf_pos = ret;
/* Return the start of the Modbus PDU to the caller. */
*ppframe_buf = (uint8_t *)&pbuf[MB_SER_PDU_PDU_OFF];
*frame_buf = &buf[MB_SER_PDU_PDU_OFF];
} else {
status = MB_EIO;
}
@@ -183,9 +187,9 @@ static mb_err_enum_t mbs_ascii_transp_send(mb_trans_base_t *inst, uint8_t slv_ad
transp->snd_buf_cnt += frame_len;
/* Prepare the ASCII buffer and send it to port */
int ascii_len = mb_ascii_set_buf(transp->snd_buf_cur, (uint8_t *)transp->pascii_puf, transp->snd_buf_cnt);
int ascii_len = mb_ascii_set_buf(transp->snd_buf_cur, transp->pascii_puf, transp->snd_buf_cnt);
if (ascii_len > MB_ASCII_SER_PDU_SIZE_MIN) {
bool ret = mb_port_ser_send_data(inst->port_obj, (uint8_t *)transp->pascii_puf, ascii_len);
bool ret = mb_port_ser_send_data(inst->port_obj, transp->pascii_puf, ascii_len);
if (!ret) {
return MB_EPORTERR;
}
@@ -218,22 +222,22 @@ static bool mbs_ascii_transp_timer_expired(void *inst)
return false;
}
void mbs_ascii_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf)
void mbs_ascii_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_buf)
{
mbs_ascii_trasp_t *transp = __containerof(inst, mbs_ascii_trasp_t, base);
assert(transp->rcv_buf);
CRITICAL_SECTION(inst->lock) {
*frame_ptr_buf = (uint8_t *)&transp->rcv_buf[MB_PDU_FUNC_OFF];
*frame_buf = &transp->rcv_buf[MB_PDU_FUNC_OFF];
}
}
static void mbs_ascii_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf)
static void mbs_ascii_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_buf)
{
mbs_ascii_trasp_t *transp = __containerof(inst, mbs_ascii_trasp_t, base);
CRITICAL_SECTION(inst->lock) {
*frame_ptr_buf = (uint8_t *)&transp->pdu_buf[MB_PDU_FUNC_OFF];
*frame_buf = (uint8_t *)&transp->pdu_buf[MB_PDU_FUNC_OFF];
}
}

View File

@@ -31,13 +31,13 @@ typedef struct
mb_err_enum_t mbm_rtu_transp_create(mb_serial_opts_t *ser_opts, void **in_out_inst);
static void mbm_rtu_transp_start(mb_trans_base_t *inst);
static void mbm_rtu_transp_stop(mb_trans_base_t *inst);
static mb_err_enum_t mbm_rtu_transp_receive(mb_trans_base_t *inst, uint8_t *rcv_addr_buf, uint8_t **frame_ptr_buf, uint16_t *len_buf);
static mb_err_enum_t mbm_rtu_transp_receive(mb_trans_base_t *inst, uint8_t *rcv_addr_buf, uint8_t **frame_buf, uint16_t *buf_len);
static mb_err_enum_t mbm_rtu_transp_send(mb_trans_base_t *inst, uint8_t slv_addr, const uint8_t *frame_ptr, uint16_t len);
static bool mbm_rtu_transp_rcv_fsm(mb_trans_base_t *inst);
static bool mbm_rtu_transp_snd_fsm(mb_trans_base_t *inst);
static bool mbm_rtu_transp_timer_expired(void *inst);
static void mbm_rtu_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf);
static void mbm_rtu_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf);
static void mbm_rtu_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_buf);
static void mbm_rtu_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_buf);
// static uint16_t mbm_rtu_transp_get_snd_len(mb_trans_base_t *inst);
static void mbm_rtu_transp_set_snd_len(mb_trans_base_t *inst, uint16_t snd_pdu_len);
static bool mbm_rtu_transp_rq_is_bcast(mb_trans_base_t *inst);
@@ -48,8 +48,9 @@ mb_err_enum_t mbm_rtu_transp_create(mb_serial_opts_t *ser_opts, void **in_out_in
MB_RETURN_ON_FALSE((ser_opts && in_out_inst), MB_EINVAL, TAG, "invalid options for the instance.");
mb_err_enum_t ret = MB_ENOERR;
mbm_rtu_transp_t *transp = NULL;
mb_port_base_t *port_obj = NULL;
transp = (mbm_rtu_transp_t *)calloc(1, sizeof(mbm_rtu_transp_t));
MB_RETURN_ON_FALSE(transp, MB_EILLSTATE, TAG, "no mem for %s instance.", TAG);
MB_GOTO_ON_FALSE(transp, MB_EILLSTATE, error, TAG, "no mem for %s instance.", TAG);
CRITICAL_SECTION_INIT(transp->base.lock);
CRITICAL_SECTION_LOCK(transp->base.lock);
transp->base.frm_rcv = mbm_rtu_transp_receive;
@@ -63,7 +64,7 @@ mb_err_enum_t mbm_rtu_transp_create(mb_serial_opts_t *ser_opts, void **in_out_in
// Copy parent object descriptor
transp->base.descr = ((mb_port_base_t *)*in_out_inst)->descr;
transp->base.descr.obj_name = (char *)TAG;
mb_port_base_t *port_obj = (mb_port_base_t *)*in_out_inst;
port_obj = (mb_port_base_t *)*in_out_inst;
ret = mb_port_ser_create(ser_opts, &port_obj);
MB_GOTO_ON_FALSE((ret == MB_ENOERR), MB_EILLSTATE, error, TAG, "serial port creation, err: %d", ret);
ret = mb_port_timer_create(port_obj, MB_RTU_GET_T35_VAL(ser_opts->baudrate));
@@ -87,16 +88,19 @@ mb_err_enum_t mbm_rtu_transp_create(mb_serial_opts_t *ser_opts, void **in_out_in
return MB_ENOERR;
error:
if (port_obj) {
if (port_obj->timer_obj) {
mb_port_timer_delete(port_obj);
}
if (port_obj->event_obj) {
mb_port_event_delete(port_obj);
}
if (port_obj) {
mb_port_ser_delete(port_obj);
}
if (transp) {
CRITICAL_SECTION_UNLOCK(transp->base.lock);
CRITICAL_SECTION_CLOSE(transp->base.lock);
}
free(transp);
return ret;
}
@@ -134,43 +138,43 @@ static void mbm_rtu_transp_stop(mb_trans_base_t *inst)
};
}
static mb_err_enum_t mbm_rtu_transp_receive(mb_trans_base_t *inst, uint8_t *prcv_addr, uint8_t **ppframe_buf, uint16_t *pbuf_len)
static mb_err_enum_t mbm_rtu_transp_receive(mb_trans_base_t *inst, uint8_t *rcv_addr_buf, uint8_t **frame_buf, uint16_t *buf_len)
{
mbm_rtu_transp_t *transp = __containerof(inst, mbm_rtu_transp_t, base);
if (!pbuf_len || !prcv_addr || !ppframe_buf || !pbuf_len) {
if (!buf_len || !rcv_addr_buf || !frame_buf || !buf_len) {
return MB_EIO;
}
mb_err_enum_t status = MB_ENOERR;
uint8_t *pbuf = (uint8_t *)transp->rcv_buf;
uint16_t length = *pbuf_len;
uint8_t *buf = (uint8_t *)transp->rcv_buf;
uint16_t length = *buf_len;
if (mb_port_ser_recv_data(inst->port_obj, &pbuf, &length) == false) {
*pbuf_len = 0;
if (mb_port_ser_recv_data(inst->port_obj, &buf, &length) == false) {
*buf_len = 0;
return MB_EPORTERR;
}
assert(length < MB_RTU_SER_PDU_SIZE_MAX);
assert(pbuf);
assert(buf);
/* Check length and CRC checksum */
if ((length >= MB_RTU_SER_PDU_SIZE_MIN)
&& (mb_crc16((uint8_t *)pbuf, length) == 0)) {
&& (mb_crc16(buf, length) == 0)) {
/* Save the address field. All frames are passed to the upper layed
* and the decision if a frame is used is done there.
*/
*prcv_addr = pbuf[MB_SER_PDU_ADDR_OFF];
*rcv_addr_buf = buf[MB_SER_PDU_ADDR_OFF];
/* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
* size of address field and CRC checksum.
*/
*pbuf_len = (uint16_t)(length - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC);
*buf_len = (uint16_t)(length - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC);
transp->rcv_buf_pos = length;
/* Return the start of the Modbus PDU to the caller. */
*ppframe_buf = (uint8_t *)&pbuf[MB_SER_PDU_PDU_OFF];
*frame_buf = &buf[MB_SER_PDU_PDU_OFF];
} else {
status = MB_EIO;
}
@@ -196,11 +200,11 @@ static mb_err_enum_t mbm_rtu_transp_send(mb_trans_base_t *inst, uint8_t slv_addr
transp->snd_buf_cur[MB_SER_PDU_ADDR_OFF] = slv_addr;
transp->snd_buf_cnt += frame_len;
/* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */
crc16 = mb_crc16((uint8_t *) transp->snd_buf_cur, transp->snd_buf_cnt);
crc16 = mb_crc16(transp->snd_buf_cur, transp->snd_buf_cnt);
transp->snd_buf_cur[transp->snd_buf_cnt++] = (uint8_t)(crc16 & 0xFF);
transp->snd_buf_cur[transp->snd_buf_cnt++] = (uint8_t)(crc16 >> 8);
bool ret = mb_port_ser_send_data(inst->port_obj, (uint8_t *)transp->snd_buf_cur, transp->snd_buf_cnt);
bool ret = mb_port_ser_send_data(inst->port_obj, transp->snd_buf_cur, transp->snd_buf_cnt);
if (!ret) {
return MB_EPORTERR;
}
@@ -267,19 +271,19 @@ static bool mbm_rtu_transp_timer_expired(void *inst)
return need_poll;
}
static void mbm_rtu_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf)
static void mbm_rtu_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_buf)
{
mbm_rtu_transp_t *transp = __containerof(inst, mbm_rtu_transp_t, base);
CRITICAL_SECTION(inst->lock) {
*frame_ptr_buf = (uint8_t *)&transp->rcv_buf[MB_PDU_FUNC_OFF];
*frame_buf = &transp->rcv_buf[MB_PDU_FUNC_OFF];
}
}
static void mbm_rtu_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf)
static void mbm_rtu_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_buf)
{
mbm_rtu_transp_t *transp = __containerof(inst, mbm_rtu_transp_t, base);
CRITICAL_SECTION(inst->lock) {
*frame_ptr_buf = (uint8_t *)&transp->snd_buf[MB_RTU_SER_PDU_PDU_OFF];
*frame_buf = &transp->snd_buf[MB_RTU_SER_PDU_PDU_OFF];
}
}

View File

@@ -28,13 +28,13 @@ typedef struct
mb_err_enum_t mbs_rtu_transp_create(mb_serial_opts_t *ser_opts, void **in_out_inst);
static void mbs_rtu_transp_start(mb_trans_base_t *inst);
static void mbs_rtu_transp_stop(mb_trans_base_t *inst);
static mb_err_enum_t mbs_rtu_transp_receive(mb_trans_base_t *inst, uint8_t *rcv_addr_buf, uint8_t **frame_ptr_buf, uint16_t *len_buf);
static mb_err_enum_t mbs_rtu_transp_receive(mb_trans_base_t *inst, uint8_t *recv_addr, uint8_t **frame_buf, uint16_t *buf_len);
static mb_err_enum_t mbs_rtu_transp_send(mb_trans_base_t *inst, uint8_t slv_addr, const uint8_t *frame_ptr, uint16_t len);
static bool mbs_rtu_transp_rcv_fsm(mb_trans_base_t *inst);
static bool mbs_rtu_transp_snd_fsm(mb_trans_base_t *inst);
static bool mbs_rtu_transp_timer_expired(void *inst);
static void mbs_rtu_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf);
void mbs_rtu_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf);
static void mbs_rtu_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_buf);
void mbs_rtu_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_buf);
static uint16_t mbs_rtu_transp_get_snd_len(mb_trans_base_t *inst);
static void mbs_rtu_transp_set_snd_len(mb_trans_base_t *inst, uint16_t snd_pdu_len);
bool mbs_rtu_transp_delete(mb_trans_base_t *inst);
@@ -82,8 +82,11 @@ error:
free(port_obj->event_obj);
free(port_obj->timer_obj);
}
free(port_obj);
if (transp) {
CRITICAL_SECTION_UNLOCK(transp->base.lock);
CRITICAL_SECTION_CLOSE(transp->base.lock);
}
free(port_obj);
free(transp);
return ret;
}
@@ -121,42 +124,42 @@ static void mbs_rtu_transp_stop(mb_trans_base_t *inst)
};
}
static mb_err_enum_t mbs_rtu_transp_receive(mb_trans_base_t *inst, uint8_t *prcv_addr, uint8_t **ppframe_buf, uint16_t *pbuf_len)
static mb_err_enum_t mbs_rtu_transp_receive(mb_trans_base_t *inst, uint8_t *recv_addr, uint8_t **frame_buf, uint16_t *buf_len)
{
if (!pbuf_len || !prcv_addr || !ppframe_buf || !pbuf_len) {
if (!buf_len || !recv_addr || !frame_buf || !buf_len) {
return MB_EIO;
}
mbs_rtu_transp_t *transp = __containerof(inst, mbs_rtu_transp_t, base);
mb_err_enum_t status = MB_ENOERR;
uint8_t *pbuf = (uint8_t *)transp->rcv_buf;
uint16_t length = *pbuf_len;
uint8_t *buf = (uint8_t *)transp->rcv_buf;
uint16_t length = *buf_len;
if (mb_port_ser_recv_data(inst->port_obj, &pbuf, &length) == false){
*pbuf_len = 0;
if (mb_port_ser_recv_data(inst->port_obj, &buf, &length) == false){
*buf_len = 0;
return MB_EPORTERR;
}
assert(length < MB_RTU_SER_PDU_SIZE_MAX);
assert(pbuf);
assert(buf);
/* Check length and CRC checksum */
if ((length >= MB_RTU_SER_PDU_SIZE_MIN)
&& (mb_crc16((uint8_t *)pbuf, length) == 0)) {
&& (mb_crc16(buf, length) == 0)) {
/* Save the address field. All frames are passed to the upper layed
* and the decision if a frame is used is done there.
*/
*prcv_addr = pbuf[MB_SER_PDU_ADDR_OFF];
*recv_addr = buf[MB_SER_PDU_ADDR_OFF];
/* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
* size of address field and CRC checksum.
*/
*pbuf_len = (uint16_t)(length - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC);
*buf_len = (uint16_t)(length - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC);
transp->rcv_buf_pos = length;
/* Return the start of the Modbus PDU to the caller. */
*ppframe_buf = (uint8_t *)&pbuf[MB_SER_PDU_PDU_OFF];
*frame_buf = &buf[MB_SER_PDU_PDU_OFF];
} else {
status = MB_EIO;
}
@@ -182,11 +185,11 @@ static mb_err_enum_t mbs_rtu_transp_send(mb_trans_base_t *inst, uint8_t slv_addr
transp->snd_buf_cur[MB_SER_PDU_ADDR_OFF] = slv_addr;
transp->snd_buf_cnt += frame_len;
/* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */
crc16 = mb_crc16((uint8_t *) transp->snd_buf_cur, transp->snd_buf_cnt);
crc16 = mb_crc16(transp->snd_buf_cur, transp->snd_buf_cnt);
transp->snd_buf_cur[transp->snd_buf_cnt++] = (uint8_t)(crc16 & 0xFF);
transp->snd_buf_cur[transp->snd_buf_cnt++] = (uint8_t)(crc16 >> 8);
bool ret = mb_port_ser_send_data(inst->port_obj, (uint8_t *)transp->snd_buf_cur, transp->snd_buf_cnt);
bool ret = mb_port_ser_send_data(inst->port_obj, transp->snd_buf_cur, transp->snd_buf_cnt);
if (!ret) {
return MB_EPORTERR;
}
@@ -219,19 +222,19 @@ static bool mbs_rtu_transp_timer_expired(void *inst)
return need_poll;
}
static void mbs_rtu_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf)
static void mbs_rtu_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_buf)
{
mbs_rtu_transp_t *transp = __containerof(inst, mbs_rtu_transp_t, base);
CRITICAL_SECTION(inst->lock) {
*frame_ptr_buf = (uint8_t *)&transp->snd_buf[MB_RTU_SER_PDU_PDU_OFF];
*frame_buf = &transp->snd_buf[MB_RTU_SER_PDU_PDU_OFF];
}
}
void mbs_rtu_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf)
void mbs_rtu_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_buf)
{
mbs_rtu_transp_t *transp = __containerof(inst, mbs_rtu_transp_t, base);
CRITICAL_SECTION(inst->lock) {
*frame_ptr_buf = (uint8_t *)&transp->rcv_buf[MB_PDU_FUNC_OFF];
*frame_buf = &transp->rcv_buf[MB_PDU_FUNC_OFF];
}
}

View File

@@ -28,10 +28,10 @@ typedef struct
mb_err_enum_t mbm_tcp_transp_create(mb_tcp_opts_t *tcp_opts, void **in_out_inst);
static void mbm_tcp_transp_start(mb_trans_base_t *inst);
static void mbm_tcp_transp_stop(mb_trans_base_t *inst);
static mb_err_enum_t mbm_tcp_transp_receive(mb_trans_base_t *inst, uint8_t *rcv_addr_buf, uint8_t **frame_ptr_buf, uint16_t *pbuf_len);
static mb_err_enum_t mbm_tcp_transp_send(mb_trans_base_t *inst, uint8_t _unused, const uint8_t *pframe, uint16_t len);
static void mbm_tcp_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf);
static void mbm_tcp_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf);
static mb_err_enum_t mbm_tcp_transp_receive(mb_trans_base_t *inst, uint8_t *rcv_addr_buf, uint8_t **frame_buf, uint16_t *buf_len);
static mb_err_enum_t mbm_tcp_transp_send(mb_trans_base_t *inst, uint8_t address, const uint8_t *frame, uint16_t len);
static void mbm_tcp_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_buf);
static void mbm_tcp_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_buf);
bool mbm_tcp_transp_delete(mb_trans_base_t *inst);
static bool mbm_tcp_transp_rq_is_bcast(mb_trans_base_t *inst);
@@ -123,11 +123,11 @@ static void mbm_tcp_transp_stop(mb_trans_base_t *inst)
};
}
static mb_err_enum_t mbm_tcp_transp_receive(mb_trans_base_t *inst, uint8_t *rcv_addr, uint8_t **frame_ptr_buf, uint16_t *pbuf_len)
static mb_err_enum_t mbm_tcp_transp_receive(mb_trans_base_t *inst, uint8_t *rcv_addr, uint8_t **frame_buf, uint16_t *buf_len)
{
mb_err_enum_t status = MB_EIO;
uint8_t *frame_ptr;
uint16_t len = *pbuf_len;
uint16_t len = *buf_len;
uint16_t pid;
if (mbm_port_tcp_recv_data(inst->port_obj, &frame_ptr, &len) != false) {
@@ -135,8 +135,8 @@ static mb_err_enum_t mbm_tcp_transp_receive(mb_trans_base_t *inst, uint8_t *rcv_
pid |= frame_ptr[MB_TCP_PID + 1];
if (pid == MB_TCP_PROTOCOL_ID) {
*frame_ptr_buf = &frame_ptr[MB_TCP_FUNC];
*pbuf_len = len - MB_TCP_FUNC;
*frame_buf = &frame_ptr[MB_TCP_FUNC];
*buf_len = len - MB_TCP_FUNC;
status = MB_ENOERR;
/* Get MBAP UID field if its support is enabled.
@@ -154,10 +154,10 @@ static mb_err_enum_t mbm_tcp_transp_receive(mb_trans_base_t *inst, uint8_t *rcv_
return status;
}
static mb_err_enum_t mbm_tcp_transp_send(mb_trans_base_t *inst, uint8_t address, const uint8_t *pframe, uint16_t len)
static mb_err_enum_t mbm_tcp_transp_send(mb_trans_base_t *inst, uint8_t address, const uint8_t *frame, uint16_t len)
{
mb_err_enum_t status = MB_ENOERR;
uint8_t *frame_ptr = (uint8_t *)pframe - MB_TCP_FUNC;
uint8_t *frame_ptr = (uint8_t *)frame - MB_TCP_FUNC;
uint16_t tcp_len = len + MB_TCP_FUNC;
/* The MBAP header is already initialized because the caller calls this
@@ -185,19 +185,19 @@ static mb_err_enum_t mbm_tcp_transp_send(mb_trans_base_t *inst, uint8_t address,
return status;
}
static void mbm_tcp_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf)
static void mbm_tcp_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_buf)
{
mbm_tcp_transp_t *transp = __containerof(inst, mbm_tcp_transp_t, base);
CRITICAL_SECTION(inst->lock) {
*frame_ptr_buf = transp->recv_buf + MB_TCP_FUNC;
*frame_buf = transp->recv_buf + MB_TCP_FUNC;
}
}
static void mbm_tcp_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf)
static void mbm_tcp_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_buf)
{
mbm_tcp_transp_t *transp = __containerof(inst, mbm_tcp_transp_t, base);
CRITICAL_SECTION(inst->lock) {
*frame_ptr_buf = transp->send_buf + MB_TCP_FUNC;
*frame_buf = transp->send_buf + MB_TCP_FUNC;
}
}

View File

@@ -26,10 +26,10 @@ typedef struct
/* ----------------------- Function prototypes ------------------------------*/
static void mbs_tcp_transp_start(mb_trans_base_t *inst);
static void mbs_tcp_transp_stop(mb_trans_base_t *inst);
static mb_err_enum_t mbs_tcp_transp_receive(mb_trans_base_t *inst, uint8_t *rcv_addr, uint8_t **frame_ptr_buf, uint16_t *pbuf_len);
static mb_err_enum_t mbs_tcp_transp_send(mb_trans_base_t *inst, uint8_t _unused, const uint8_t *frame_ptr, uint16_t len);
static void mbs_tcp_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf);
static void mbs_tcp_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf);
static mb_err_enum_t mbs_tcp_transp_receive(mb_trans_base_t *inst, uint8_t *rcv_addr, uint8_t **frame_buf, uint16_t *buf_len);
static mb_err_enum_t mbs_tcp_transp_send(mb_trans_base_t *inst, uint8_t _unused, const uint8_t *frame, uint16_t len);
static void mbs_tcp_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_buf);
static void mbs_tcp_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_buf);
bool mbs_tcp_transp_delete(mb_trans_base_t *inst);
static bool mbs_tcp_transp_timer_expired(void *inst);
@@ -119,16 +119,16 @@ static void mbs_tcp_transp_stop(mb_trans_base_t *inst)
};
}
static mb_err_enum_t mbs_tcp_transp_receive(mb_trans_base_t *inst, uint8_t *rcv_addr, uint8_t **frame_ptr_buf, uint16_t *pbuf_len)
static mb_err_enum_t mbs_tcp_transp_receive(mb_trans_base_t *inst, uint8_t *rcv_addr, uint8_t **frame_buf, uint16_t *buf_len)
{
if (!pbuf_len || !frame_ptr_buf || !pbuf_len) {
if (!buf_len || !frame_buf || !buf_len) {
return MB_EIO;
}
mbs_tcp_transp_t *transp = __containerof(inst, mbs_tcp_transp_t, base);
uint8_t *frame_ptr = (uint8_t *)transp->recv_buf;
uint16_t length = *pbuf_len;
uint16_t length = *buf_len;
mb_err_enum_t status = MB_EIO;
uint16_t pid;
@@ -137,8 +137,8 @@ static mb_err_enum_t mbs_tcp_transp_receive(mb_trans_base_t *inst, uint8_t *rcv_
pid |= frame_ptr[MB_TCP_PID + 1];
if (pid == MB_TCP_PROTOCOL_ID) {
*frame_ptr_buf = &frame_ptr[MB_TCP_FUNC];
*pbuf_len = length - MB_TCP_FUNC;
*frame_buf = &frame_ptr[MB_TCP_FUNC];
*buf_len = length - MB_TCP_FUNC;
status = MB_ENOERR;
/* Get MBAP UID field if its support is enabled.
@@ -156,10 +156,10 @@ static mb_err_enum_t mbs_tcp_transp_receive(mb_trans_base_t *inst, uint8_t *rcv_
return status;
}
static mb_err_enum_t mbs_tcp_transp_send(mb_trans_base_t *inst, uint8_t _unused, const uint8_t *pframe, uint16_t len)
static mb_err_enum_t mbs_tcp_transp_send(mb_trans_base_t *inst, uint8_t _unused, const uint8_t *frame, uint16_t len)
{
mb_err_enum_t status = MB_ENOERR;
uint8_t *frame_ptr = (uint8_t *)pframe - MB_TCP_FUNC;
uint8_t *frame_ptr = (uint8_t *)frame - MB_TCP_FUNC;
uint16_t tcp_len = len + MB_TCP_FUNC;
/* The MBAP header is already initialized because the caller calls this
@@ -212,19 +212,19 @@ static bool mbs_tcp_transp_timer_expired(void *inst)
return need_poll;
}
static void mbs_tcp_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf)
static void mbs_tcp_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_buf)
{
mbs_tcp_transp_t *transp = __containerof(inst, mbs_tcp_transp_t, base);
CRITICAL_SECTION(inst->lock) {
*frame_ptr_buf = transp->recv_buf + MB_TCP_FUNC;
*frame_buf = transp->recv_buf + MB_TCP_FUNC;
}
}
static void mbs_tcp_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf)
static void mbs_tcp_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_buf)
{
mbs_tcp_transp_t *transp = __containerof(inst, mbs_tcp_transp_t, base);
CRITICAL_SECTION(inst->lock) {
*frame_ptr_buf = transp->send_buf + MB_TCP_FUNC;
*frame_buf = transp->send_buf + MB_TCP_FUNC;
}
}

View File

@@ -14,14 +14,14 @@ extern "C" {
#endif
typedef struct mb_trans_base_t mb_trans_base_t; /*!< Type of moddus transport object */
typedef struct _obj_descr obj_descr_t;
typedef struct obj_descr_s obj_descr_t;
typedef void (*mb_frm_start_fp)(mb_trans_base_t *transport);
typedef void (*mb_frm_stop_fp)(mb_trans_base_t *transport);
typedef mb_err_enum_t (*mb_frm_rcv_fp)(mb_trans_base_t *transport, uint8_t *rcv_addr_buf, uint8_t **frame_ptr_buf, uint16_t *len_buf);
typedef mb_err_enum_t (*mb_frm_rcv_fp)(mb_trans_base_t *transport, uint8_t *rcv_addr_buf, uint8_t **frame_buf, uint16_t *len_buf);
typedef mb_err_enum_t (*mb_frm_snd_fp)(mb_trans_base_t *transport, uint8_t slv_addr, const uint8_t *frame_ptr, uint16_t len);
typedef void (*mb_get_rx_frm_fp) (mb_trans_base_t *transport, uint8_t **frame_ptr_buf);
typedef void (*mb_get_tx_frm_fp) (mb_trans_base_t *transport, uint8_t **frame_ptr_buf);
typedef void (*mb_get_rx_frm_fp) (mb_trans_base_t *transport, uint8_t **frame_buf);
typedef void (*mb_get_tx_frm_fp) (mb_trans_base_t *transport, uint8_t **frame_buf);
typedef bool (*mb_get_fp)(mb_trans_base_t *inst);
struct mb_trans_base_t

View File

@@ -1,3 +1,5 @@
set(PROJECT_NAME "test_comm_adapter")
set(srcs "test_app_main.c"
"test_modbus_adapter_serial.c"
"test_modbus_adapter_tcp.c"
@@ -10,3 +12,9 @@ idf_component_register(SRCS ${srcs}
set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u mb_test_include_adapter_impl_serial")
set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u mb_test_include_adapter_impl_tcp")
# Workaround to avoid static analysis false positives for some components.
if(CONFIG_FMB_COMPILER_STATIC_ANALYZER_ENABLE AND CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_compile_options(${COMPONENT_LIB} PRIVATE "-fanalyzer")
message(STATUS "Static analyzer build for ${PROJECT_NAME}.")
endif()

View File

@@ -2,5 +2,11 @@
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
# The workaround to expliciply remove the component from dependency list.
# This should allow to avoid GNU static analizer warnings for the esp_http_server component.
set(EXCLUDE_COMPONENTS esp_http_server)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(mb_serial_cpp)

View File

@@ -1,2 +1,12 @@
set(PROJECT_NAME "mb_serial_cpp")
idf_component_register(SRCS "serial_test.cpp"
REQUIRES esp-modbus nvs_flash esp_event esp_timer lwip
INCLUDE_DIRS ".")
# Workaround to avoid static analysis false positives for some components.
if(CONFIG_FMB_COMPILER_STATIC_ANALYZER_ENABLE AND CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_compile_options(${COMPONENT_LIB} PRIVATE "-fanalyzer")
message(STATUS "Static analyzer build for ${PROJECT_NAME}.")
endif()

View File

@@ -21,8 +21,8 @@ enum {
#define STR(fieldname) ((const char*)( fieldname ))
#define OPTS(min_val, max_val, step_val) { .opt1 = min_val, .opt2 = max_val, .opt3 = step_val }
static void *pmaster_handle = NULL;
static void *pslave_handle = NULL;
static void *pmaster_handle = nullptr;
static void *pslave_handle = nullptr;
// Example Data (Object) Dictionary for Modbus parameters
const mb_parameter_descriptor_t dummy_dict[] = {
@@ -36,7 +36,7 @@ const mb_parameter_descriptor_t dummy_dict[] = {
const uint16_t num_device_parameters = (sizeof(dummy_dict)/sizeof(dummy_dict[0]));
// Modbus serial master initialization
static esp_err_t master_serial_init(void **pinst)
static esp_err_t master_serial_init(void **inst)
{
mb_communication_info_t comm;
comm.ser_opts.port = (uart_port_t)TEST_PORT_NUM;
@@ -48,24 +48,24 @@ static esp_err_t master_serial_init(void **pinst)
comm.ser_opts.data_bits = UART_DATA_8_BITS;
comm.ser_opts.stop_bits = UART_STOP_BITS_1;
// Initialize Modbus controller
esp_err_t err = mbc_master_create_serial(&comm, pinst);
MB_RETURN_ON_FALSE((pinst != NULL), ESP_ERR_INVALID_STATE, TAG,
esp_err_t err = mbc_master_create_serial(&comm, inst);
MB_RETURN_ON_FALSE((inst), ESP_ERR_INVALID_STATE, TAG,
"mbc master initialization fail.");
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
"mbc master initialization fail, returns(0x%x).", (int)err);
err = mbc_master_set_descriptor(*pinst, &dummy_dict[0], num_device_parameters);
err = mbc_master_set_descriptor(*inst, &dummy_dict[0], num_device_parameters);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
"mbc master set descriptor fail, returns(0x%x).", (int)err);
err = mbc_master_start(*pinst);
err = mbc_master_start(*inst);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
"mbc master start fail, returned (0x%x).", (int)err);
const mb_parameter_descriptor_t *pdescriptor = NULL;
err = mbc_master_get_cid_info(*pinst, CID_DEV_REG0, &pdescriptor);
MB_RETURN_ON_FALSE(((err != ESP_ERR_NOT_FOUND) && (pdescriptor != NULL)), ESP_ERR_INVALID_STATE, TAG,
const mb_parameter_descriptor_t *descriptor = nullptr;
err = mbc_master_get_cid_info(*inst, CID_DEV_REG0, &descriptor);
MB_RETURN_ON_FALSE(((err != ESP_ERR_NOT_FOUND) && descriptor), ESP_ERR_INVALID_STATE, TAG,
"mbc master get descriptor fail, returned (0x%x).", (int)err);
uint16_t regs[] = {0x1111, 0x2222};
uint8_t type = 0;
err = mbc_master_get_parameter(*pinst, pdescriptor->cid, (uint8_t *)&regs[0], &type);
err = mbc_master_get_parameter(*inst, descriptor->cid, (uint8_t *)&regs[0], &type);
MB_RETURN_ON_FALSE((err != ESP_ERR_INVALID_STATE), ESP_ERR_INVALID_STATE, TAG,
"mbc master get parameter fail, returned (0x%x).", (int)err);
ESP_LOGI(TAG, "Modbus master stack initialized...");
@@ -73,7 +73,7 @@ static esp_err_t master_serial_init(void **pinst)
}
// Modbus serial slave initialization
static esp_err_t slave_serial_init(void **pinst)
static esp_err_t slave_serial_init(void **inst)
{
mb_register_area_descriptor_t reg_area;
mb_communication_info_t comm;
@@ -86,8 +86,8 @@ static esp_err_t slave_serial_init(void **pinst)
comm.ser_opts.data_bits = UART_DATA_8_BITS;
comm.ser_opts.stop_bits = UART_STOP_BITS_1;
// Initialize Modbus controller
esp_err_t err = mbc_slave_create_serial(&comm, pinst);
MB_RETURN_ON_FALSE((pinst != NULL), ESP_ERR_INVALID_STATE, TAG,
esp_err_t err = mbc_slave_create_serial(&comm, inst);
MB_RETURN_ON_FALSE(inst, ESP_ERR_INVALID_STATE, TAG,
"mbc slave initialization fail.");
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
"mbc slave initialization fail, returns(0x%x).", (int)err);
@@ -97,45 +97,44 @@ static esp_err_t slave_serial_init(void **pinst)
reg_area.address = (void*)&holding_regs[0];
reg_area.size = sizeof(holding_regs);
reg_area.access = MB_ACCESS_RW;
ESP_ERROR_CHECK(mbc_slave_set_descriptor(*pinst, reg_area));
err = mbc_slave_start(*pinst);
ESP_ERROR_CHECK(mbc_slave_set_descriptor(*inst, reg_area));
err = mbc_slave_start(*inst);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
"mbc slave start fail, returned (0x%x).", (int)err);
ESP_LOGI(TAG, "Modbus slave stack initialized...");
return err;
}
mb_exception_t test_handler(void *pinst, uint8_t *frame_ptr, uint16_t *plen)
mb_exception_t test_handler(void *inst, uint8_t *frame_ptr, uint16_t *len)
{
return MB_EX_CRITICAL; // Set the exception code for slave appropriately
}
static int check_custom_handlers(void *pinst)
static int check_custom_handlers(void *inst)
{
mb_fn_handler_fp phandler = NULL;
mb_fn_handler_fp handler = nullptr;
int entry;
uint16_t count = 0;
esp_err_t err = ESP_FAIL;
err = mbc_get_handler_count(pinst, &count);
err = mbc_get_handler_count(inst, &count);
MB_RETURN_ON_FALSE((err == ESP_OK), 0, TAG,
"mbc slave get handler count, returns(0x%x).", (int)err);
ESP_LOGI(TAG,"Object %p, custom handler test, (registered:max) handlers: %d:%d.", pinst, count, CONFIG_FMB_FUNC_HANDLERS_MAX);
ESP_LOGI(TAG,"Object %p, custom handler test, (registered:max) handlers: %d:%d.", inst, count, CONFIG_FMB_FUNC_HANDLERS_MAX);
for (entry = 0x01; entry < CONFIG_FMB_FUNC_HANDLERS_MAX; entry++) {
// Try to remove the handler
err = mbc_delete_handler(pinst, (uint8_t)entry);
err = mbc_delete_handler(inst, (uint8_t)entry);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Could not remove handler for command: (0x%x), returned (0x%x), already empty?", entry, (int)err);
}
err = mbc_set_handler(pinst, (uint8_t)entry, test_handler);
err = mbc_set_handler(inst, (uint8_t)entry, test_handler);
if (err != ESP_OK) {
ESP_LOGE(TAG,"Could not set handler for command 0x%x, returned (0x%x).", entry, (int)err);
break;
} else {
ESP_LOGI(TAG,"Set handler for command 0x%x, returned (0x%x).", entry, (int)err);
}
err = mbc_get_handler(pinst, (uint8_t)entry, &phandler);
if (err != ESP_OK || phandler != test_handler) {
ESP_LOGE(TAG, "Could not get handler for command (0x%x) = (%p), returned (0x%x).", entry, phandler, (int)err);
ESP_LOGI(TAG,"Set handler for command 0x%x, returned (0x%x).", entry, (int)err);
err = mbc_get_handler(inst, (uint8_t)entry, &handler);
if (err != ESP_OK || handler != test_handler) {
ESP_LOGE(TAG, "Could not get handler for command (0x%x) = (%p), returned (0x%x).", entry, handler, (int)err);
break;
}
}

View File

@@ -1,3 +1,4 @@
# General options for test
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
CONFIG_HEAP_TRACING_OFF=y

View File

@@ -1,3 +1,5 @@
set(PROJECT_NAME "test_modbus_comm_multi_dev")
set(srcs "test_app_main.c"
"test_modbus_rs485_comm_master_slave.c"
"test_modbus_tcp_comm_master_slave.c"
@@ -12,3 +14,8 @@ idf_component_register(SRCS ${srcs}
set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u mb_test_include_phys_impl_tcp")
set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u mb_test_include_phys_impl_serial")
# Workaround to avoid static analysis false positives for some components.
if(CONFIG_FMB_COMPILER_STATIC_ANALYZER_ENABLE AND CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_compile_options(${COMPONENT_LIB} PRIVATE "-fanalyzer")
message(STATUS "Static analyzer build for ${PROJECT_NAME}.")
endif()

View File

@@ -64,7 +64,7 @@ const char *slave_tcp_addr_table[] = {
NULL // End of table condition (must be included)
};
static esp_err_t test_tcp_services_init(void **pnetif)
static esp_err_t test_tcp_services_init(void **netif)
{
esp_err_t result = nvs_flash_init();
if ((result == ESP_ERR_NVS_NO_FREE_PAGES) || (result == ESP_ERR_NVS_NEW_VERSION_FOUND)) {
@@ -106,8 +106,8 @@ static esp_err_t test_tcp_services_init(void **pnetif)
// "esp_wifi_set_ps fail, returns(0x%x).",
// (int)result);
#endif
if (pnetif) {
*pnetif = get_example_netif();
if (netif) {
*netif = get_example_netif();
}
return ESP_OK;
}
@@ -146,9 +146,9 @@ static esp_err_t test_tcp_services_destroy(void)
static void test_modbus_tcp_slave(void)
{
void *pnetif = NULL;
TEST_ASSERT_TRUE(test_tcp_services_init(&pnetif) == ESP_OK);
TEST_ASSERT_NOT_NULL(pnetif);
void *netif = NULL;
TEST_ASSERT_TRUE(test_tcp_services_init(&netif) == ESP_OK);
TEST_ASSERT_NOT_NULL(netif);
test_common_start();
mb_communication_info_t tcp_slave_cfg_1 = {
@@ -160,7 +160,7 @@ static void test_modbus_tcp_slave(void)
.tcp_opts.start_disconnected = true,
.tcp_opts.response_tout_ms = 1,
.tcp_opts.test_tout_us = TEST_TCP_SLAVE_SEND_TOUT_US,
.tcp_opts.ip_netif_ptr = pnetif
.tcp_opts.ip_netif_ptr = netif
};
TEST_ASSERT_NOT_NULL(test_common_slave_tcp_create(&tcp_slave_cfg_1, 0));
@@ -176,7 +176,7 @@ static void test_modbus_tcp_slave(void)
.tcp_opts.start_disconnected = true,
.tcp_opts.response_tout_ms = 1,
.tcp_opts.test_tout_us = TEST_TCP_SLAVE_SEND_TOUT_US,
.tcp_opts.ip_netif_ptr = pnetif
.tcp_opts.ip_netif_ptr = netif
};
TEST_ASSERT_NOT_NULL(test_common_slave_tcp_create(&tcp_slave_cfg_2, 0));
@@ -198,9 +198,9 @@ static void test_modbus_tcp_slave(void)
static void test_modbus_tcp_master(void)
{
void *pnetif = NULL;
TEST_ASSERT_TRUE(test_tcp_services_init(&pnetif) == ESP_OK);
TEST_ASSERT_NOT_NULL(pnetif);
void *netif = NULL;
TEST_ASSERT_TRUE(test_tcp_services_init(&netif) == ESP_OK);
TEST_ASSERT_NOT_NULL(netif);
test_common_start();
@@ -218,7 +218,7 @@ static void test_modbus_tcp_master(void)
.tcp_opts.start_disconnected = false,
.tcp_opts.response_tout_ms = TEST_MASTER_RESPOND_TOUT_MS,
.tcp_opts.test_tout_us = TEST_TCP_MASTER_SEND_TOUT_US,
.tcp_opts.ip_netif_ptr = pnetif
.tcp_opts.ip_netif_ptr = netif
};
TEST_ASSERT_NOT_NULL(test_common_master_tcp_create(&tcp_master_cfg_1, 0, &descriptors[0], num_descriptors));

View File

@@ -66,9 +66,9 @@ void test_common_stop();
// TaskHandle_t test_common_slave_serial_create(mb_communication_info_t *pconfig);
TaskHandle_t test_common_slave_serial_create(mb_communication_info_t *pconfig, uint32_t priority);
TaskHandle_t test_common_master_serial_create(mb_communication_info_t *pconfig,uint32_t priority, const mb_parameter_descriptor_t *pdescr, uint16_t descr_size);
TaskHandle_t test_common_master_serial_create(mb_communication_info_t *pconfig,uint32_t priority, const mb_parameter_descriptor_t *descr, uint16_t descr_size);
TaskHandle_t test_common_slave_tcp_create(mb_communication_info_t *pconfig, uint32_t priority);
TaskHandle_t test_common_master_tcp_create(mb_communication_info_t *pconfig, uint32_t priority, const mb_parameter_descriptor_t *pdescr, uint16_t descr_size);
TaskHandle_t test_common_master_tcp_create(mb_communication_info_t *pconfig, uint32_t priority, const mb_parameter_descriptor_t *descr, uint16_t descr_size);
TaskHandle_t test_common_start_busy_task(uint32_t priority);
/**

View File

@@ -112,42 +112,42 @@ void mb_port_adapter_set_response_time(mb_port_base_t *inst, uint64_t resp_time)
atomic_store(&(port_obj->test_timeout_us), resp_time);
}
int mb_port_adapter_get_rx_buffer(mb_port_base_t *inst, uint8_t **ppfame, int *plen)
int mb_port_adapter_get_rx_buffer(mb_port_base_t *inst, uint8_t **frame_ptr, int *len)
{
MB_RETURN_ON_FALSE((ppfame && plen), -1, TAG, "mb serial get buffer failure.");
MB_RETURN_ON_FALSE((frame_ptr && len), -1, TAG, "mb serial get buffer failure.");
mb_port_adapter_t *port_obj = __containerof(inst, mb_port_adapter_t, base);
int sz = port_obj->recv_length;
if (*ppfame && *plen >= port_obj->recv_length)
if (*frame_ptr && *len >= port_obj->recv_length)
{
CRITICAL_SECTION(inst->lock)
{
memcpy(*ppfame, port_obj->rx_buffer, sz);
memcpy(*frame_ptr, port_obj->rx_buffer, sz);
}
}
else
{
*ppfame = port_obj->rx_buffer;
*plen = sz;
*frame_ptr = port_obj->rx_buffer;
*len = sz;
}
return sz;
}
int mb_port_adapter_get_tx_buffer(mb_port_base_t *inst, uint8_t **ppfame, int *plen)
int mb_port_adapter_get_tx_buffer(mb_port_base_t *inst, uint8_t **frame_ptr, int *len)
{
MB_RETURN_ON_FALSE((ppfame && plen), -1, TAG, "mb serial get buffer failure.");
MB_RETURN_ON_FALSE((frame_ptr && len), -1, TAG, "mb serial get buffer failure.");
mb_port_adapter_t *port_obj = __containerof(inst, mb_port_adapter_t, base);
int sz = port_obj->recv_length;
if (*ppfame && *plen >= port_obj->recv_length)
if (*frame_ptr && *len >= port_obj->recv_length)
{
CRITICAL_SECTION(inst->lock)
{
memcpy(*ppfame, port_obj->rx_buffer, sz);
memcpy(*frame_ptr, port_obj->rx_buffer, sz);
}
}
else
{
*ppfame = port_obj->rx_buffer;
*plen = sz;
*frame_ptr = port_obj->rx_buffer;
*len = sz;
}
return sz;
}
@@ -216,7 +216,7 @@ bool mb_port_adapter_is_connected(void *inst)
return false;
}
static void mb_port_adapter_conn_logic(void *inst, mb_uid_info_t *paddr_info)
static void mb_port_adapter_conn_logic(void *inst, mb_uid_info_t *addr_info)
{
bool slave_found = false;
mb_port_adapter_t *slave = NULL;
@@ -224,15 +224,15 @@ static void mb_port_adapter_conn_logic(void *inst, mb_uid_info_t *paddr_info)
if (port_obj->base.descr.is_master) { // master object
LIST_FOREACH(slave, &s_port_list, entries) {
if ((paddr_info->uid == slave->addr_info.uid)
if ((addr_info->uid == slave->addr_info.uid)
&& !slave->base.descr.is_master
&& (paddr_info->port == slave->addr_info.port)) {
&& (addr_info->port == slave->addr_info.port)) {
// Register each slave object
ESP_LOGD(TAG, "Check connection state of object #%d(%s), uid: %d, port: %d, %s",
paddr_info->index, paddr_info->node_name_str,
paddr_info->uid, paddr_info->port,
(paddr_info->state == MB_SOCK_STATE_CONNECTED) ? "CONNECTED" : "DISCONNECTED");
if ((paddr_info->state != MB_SOCK_STATE_CONNECTED) || (paddr_info->inst != inst)) {
addr_info->index, addr_info->node_name_str,
addr_info->uid, addr_info->port,
(addr_info->state == MB_SOCK_STATE_CONNECTED) ? "CONNECTED" : "DISCONNECTED");
if ((addr_info->state != MB_SOCK_STATE_CONNECTED) || (addr_info->inst != inst)) {
(void)xQueueSend(slave->conn_queue, &port_obj->addr_info, MB_ADAPTER_QUEUE_TIMEOUT);
} else {
mb_port_adapter_set_flag(inst, MB_QUEUE_FLAG_CONNECTED);
@@ -244,19 +244,19 @@ static void mb_port_adapter_conn_logic(void *inst, mb_uid_info_t *paddr_info)
if (!slave_found) {
// reactivate the connection set
ESP_LOGE(TAG, "Slave #%d(%s), uid: %d, port: %d is not found, reconnect.",
paddr_info->index, paddr_info->node_name_str, paddr_info->uid, paddr_info->port);
(void)xQueueSend(port_obj->conn_queue, paddr_info, MB_ADAPTER_QUEUE_TIMEOUT);
addr_info->index, addr_info->node_name_str, addr_info->uid, addr_info->port);
(void)xQueueSend(port_obj->conn_queue, addr_info, MB_ADAPTER_QUEUE_TIMEOUT);
vTaskDelay(MB_ADAPTER_CONN_TIMEOUT);
}
} else { // slave connection logic
ESP_LOGD(TAG, "Register connection in adapter object #%d(%s), uid: %d, port: %d, to master %s",
port_obj->addr_info.index, port_obj->addr_info.node_name_str,
port_obj->addr_info.uid, port_obj->addr_info.port, paddr_info->node_name_str);
port_obj->addr_info.uid, port_obj->addr_info.port, addr_info->node_name_str);
// Mimic connection logic for each slave here
//mb_port_adapter_slave_connect(it);
port_obj->addr_info.state = MB_SOCK_STATE_CONNECTED;
mb_port_adapter_t *master = (mb_port_adapter_t *)(paddr_info->inst);
port_obj->addr_info.inst = paddr_info->inst; // link slave with master
mb_port_adapter_t *master = (mb_port_adapter_t *)(addr_info->inst);
port_obj->addr_info.inst = addr_info->inst; // link slave with master
(void)xQueueSend(master->conn_queue, &port_obj->addr_info, MB_ADAPTER_QUEUE_TIMEOUT);
}
}
@@ -297,11 +297,11 @@ static void mb_port_adapter_task(void *p_args)
vTaskDelete(NULL);
}
static mb_err_enum_t mb_port_adapter_connect(mb_tcp_opts_t *tcp_opts, void *pobject)
static mb_err_enum_t mb_port_adapter_connect(mb_tcp_opts_t *tcp_opts, void *object)
{
char **paddr_table = tcp_opts->ip_addr_table;
mb_uid_info_t uid_info;
mb_port_adapter_t *port_obj = __containerof(pobject, mb_port_adapter_t, base);
mb_port_adapter_t *port_obj = __containerof(object, mb_port_adapter_t, base);
MB_RETURN_ON_FALSE((paddr_table && *paddr_table && (tcp_opts->mode == MB_TCP)),
MB_EINVAL, TAG,
@@ -325,7 +325,7 @@ static mb_err_enum_t mb_port_adapter_connect(mb_tcp_opts_t *tcp_opts, void *pobj
};
// Mimic connection event
if (!tcp_opts->start_disconnected) {
uint16_t event = mb_port_adapter_wait_flag(pobject, MB_QUEUE_FLAG_CONNECTED, MB_ADAPTER_CONN_TIMEOUT);
uint16_t event = mb_port_adapter_wait_flag(object, MB_QUEUE_FLAG_CONNECTED, MB_ADAPTER_CONN_TIMEOUT);
if (!event) {
ESP_LOGE(TAG, "Could not connect to slave %s during timeout.", (char *)*paddr_table);
}
@@ -341,34 +341,34 @@ static mb_err_enum_t mb_port_adapter_connect(mb_tcp_opts_t *tcp_opts, void *pobj
return count ? MB_ENOERR : MB_EINVAL;
}
mb_err_enum_t mb_port_adapter_create(mb_uid_info_t *paddr_info, mb_port_base_t **in_out_obj)
mb_err_enum_t mb_port_adapter_create(mb_uid_info_t *addr_info, mb_port_base_t **in_out_obj)
{
mb_port_adapter_t *padapter = NULL;
mb_port_adapter_t *adapter_obj = NULL;
mb_err_enum_t ret = MB_EILLSTATE;
padapter = (mb_port_adapter_t *)calloc(1, sizeof(mb_port_adapter_t));
adapter_obj = (mb_port_adapter_t *)calloc(1, sizeof(mb_port_adapter_t));
MB_GOTO_ON_FALSE((padapter && paddr_info && in_out_obj), MB_EILLSTATE, error, TAG, "mb serial port creation error.");
MB_GOTO_ON_FALSE((adapter_obj && addr_info && in_out_obj), MB_EILLSTATE, error, TAG, "mb serial port creation error.");
CRITICAL_SECTION_INIT(padapter->base.lock);
padapter->base.descr = ((mb_port_base_t *)*in_out_obj)->descr;
padapter->addr_info = *paddr_info;
CRITICAL_SECTION_INIT(adapter_obj->base.lock);
adapter_obj->base.descr = ((mb_port_base_t *)*in_out_obj)->descr;
adapter_obj->addr_info = *addr_info;
esp_timer_create_args_t timer_conf = {
.callback = mb_port_adapter_timer_cb,
.arg = padapter,
.arg = adapter_obj,
.dispatch_method = ESP_TIMER_TASK,
.name = padapter->base.descr.parent_name
.name = adapter_obj->base.descr.parent_name
};
// Create Modbus timer handlers for streams
MB_GOTO_ON_ERROR(esp_timer_create(&timer_conf, &padapter->timer_handle),
MB_GOTO_ON_ERROR(esp_timer_create(&timer_conf, &adapter_obj->timer_handle),
error, TAG, "create input stream timer failed.");
padapter->rx_queue = queue_create(MB_ADAPTER_RX_QUEUE_MAX_SIZE);
MB_GOTO_ON_FALSE(padapter->rx_queue, MB_EILLSTATE, error, TAG, "create rx queue failed");
padapter->tx_queue = queue_create(MB_ADAPTER_TX_QUEUE_MAX_SIZE);
MB_GOTO_ON_FALSE(padapter->tx_queue, MB_EILLSTATE, error, TAG, "create tx queue failed");
padapter->event_group_handle = xEventGroupCreate();
MB_GOTO_ON_FALSE((padapter->event_group_handle), MB_EILLSTATE, error, TAG,
adapter_obj->rx_queue = queue_create(MB_ADAPTER_RX_QUEUE_MAX_SIZE);
MB_GOTO_ON_FALSE(adapter_obj->rx_queue, MB_EILLSTATE, error, TAG, "create rx queue failed");
adapter_obj->tx_queue = queue_create(MB_ADAPTER_TX_QUEUE_MAX_SIZE);
MB_GOTO_ON_FALSE(adapter_obj->tx_queue, MB_EILLSTATE, error, TAG, "create tx queue failed");
adapter_obj->event_group_handle = xEventGroupCreate();
MB_GOTO_ON_FALSE((adapter_obj->event_group_handle), MB_EILLSTATE, error, TAG,
"%p, event group create error.", *in_out_obj);
if (!s_port_list_counter)
@@ -376,7 +376,7 @@ mb_err_enum_t mb_port_adapter_create(mb_uid_info_t *paddr_info, mb_port_base_t *
// Create a task to handle UART events
BaseType_t status = xTaskCreatePinnedToCore(mb_port_adapter_task, "adapt_rx_task",
MB_ADAPTER_TASK_STACK_SIZE,
&padapter->base, CONFIG_FMB_PORT_TASK_PRIO,
&adapter_obj->base, CONFIG_FMB_PORT_TASK_PRIO,
&adapter_task_handle, CONFIG_FMB_PORT_TASK_AFFINITY);
// Force exit from function with failure
MB_GOTO_ON_FALSE((status == pdPASS), MB_EILLSTATE, error, TAG,
@@ -386,41 +386,41 @@ mb_err_enum_t mb_port_adapter_create(mb_uid_info_t *paddr_info, mb_port_base_t *
MB_GOTO_ON_FALSE((queue_set), MB_EILLSTATE, error, TAG, "can not create queue set.");
}
// Add connection set for master object only
padapter->conn_queue = xQueueCreate(MB_ADAPTER_MAX_PORTS, sizeof(mb_uid_info_t));
MB_GOTO_ON_FALSE(padapter->conn_queue, MB_EILLSTATE, error, TAG, "create conn queue failed");
MB_GOTO_ON_FALSE((queue_set && xQueueAddToSet(padapter->conn_queue, queue_set)),
adapter_obj->conn_queue = xQueueCreate(MB_ADAPTER_MAX_PORTS, sizeof(mb_uid_info_t));
MB_GOTO_ON_FALSE(adapter_obj->conn_queue, MB_EILLSTATE, error, TAG, "create conn queue failed");
MB_GOTO_ON_FALSE((queue_set && xQueueAddToSet(adapter_obj->conn_queue, queue_set)),
MB_EILLSTATE, error, TAG, "can not add conn queue to queue set.");
// Add rx queue to set
MB_GOTO_ON_FALSE((queue_set && xQueueAddToSet(padapter->rx_queue, queue_set)),
MB_GOTO_ON_FALSE((queue_set && xQueueAddToSet(adapter_obj->rx_queue, queue_set)),
MB_EILLSTATE, error, TAG, "can not add rx queue to queue set.");
MB_GOTO_ON_FALSE((s_port_list_counter <= MB_ADAPTER_MAX_PORTS), MB_EILLSTATE, error,
TAG, "adapter exceeded maximum number of ports = %d", MB_ADAPTER_MAX_PORTS);
// register new port instance in the list
LIST_INSERT_HEAD(&s_port_list, padapter, entries);
LIST_INSERT_HEAD(&s_port_list, adapter_obj, entries);
s_port_list_counter++;
char *pstr;
int res = asprintf(&pstr, "%d;%s;%u", (unsigned)paddr_info->uid,
padapter->base.descr.parent_name, (unsigned)paddr_info->port);
char *string_ptr;
int res = asprintf(&string_ptr, "%d;%s;%u", (unsigned)addr_info->uid,
adapter_obj->base.descr.parent_name, (unsigned)addr_info->port);
MB_GOTO_ON_FALSE((res), MB_EILLSTATE, error,
TAG, "object adress info alloc fail, err: %d", (int)res);
padapter->base.cb.tmr_expired = mb_port_adapter_timer_expired;
padapter->base.cb.tx_empty = NULL;
padapter->base.cb.byte_rcvd = NULL;
padapter->base.arg = (void *)padapter;
adapter_obj->base.cb.tmr_expired = mb_port_adapter_timer_expired;
adapter_obj->base.cb.tx_empty = NULL;
adapter_obj->base.cb.byte_rcvd = NULL;
adapter_obj->base.arg = (void *)adapter_obj;
padapter->addr_info.state = MB_SOCK_STATE_CONNECTING;
padapter->addr_info.inst = padapter;
padapter->addr_info.node_name_str = pstr;
padapter->addr_info.ip_addr_str = pstr;
*in_out_obj = &(padapter->base);
ESP_LOGD(TAG, "created object @%p, from parent %p", padapter, padapter->base.descr.parent);
adapter_obj->addr_info.state = MB_SOCK_STATE_CONNECTING;
adapter_obj->addr_info.inst = adapter_obj;
adapter_obj->addr_info.node_name_str = string_ptr;
adapter_obj->addr_info.ip_addr_str = string_ptr;
*in_out_obj = &(adapter_obj->base);
ESP_LOGD(TAG, "created object @%p, from parent %p", adapter_obj, adapter_obj->base.descr.parent);
return MB_ENOERR;
error:
if (padapter) {
mb_port_adapter_delete(&padapter->base);
if (adapter_obj) {
mb_port_adapter_delete(&adapter_obj->base);
}
return ret;
}
@@ -437,26 +437,26 @@ mb_err_enum_t mb_port_adapter_tcp_create(mb_tcp_opts_t *tcp_opts, mb_port_base_t
.state = MB_SOCK_STATE_UNDEF
};
mb_port_base_t *pobj = *in_out_obj;
mb_err_enum_t ret = mb_port_adapter_create(&addr_info, &pobj);
mb_port_base_t *obj = *in_out_obj;
mb_err_enum_t ret = mb_port_adapter_create(&addr_info, &obj);
if ((ret == MB_ENOERR) && pobj) {
if ((ret == MB_ENOERR) && obj) {
// Parse master config and register dependent objects
if (pobj->descr.is_master) {
ESP_LOGI(TAG, "Parsing of config for %s", pobj->descr.parent_name);
ret |= mb_port_adapter_connect(tcp_opts, pobj);
if (obj->descr.is_master) {
ESP_LOGI(TAG, "Parsing of config for %s", obj->descr.parent_name);
ret |= mb_port_adapter_connect(tcp_opts, obj);
MB_GOTO_ON_FALSE((ret == MB_ENOERR), MB_EILLSTATE, error, TAG,
"%s, could not parse config, err=%x.", pobj->descr.parent_name, (int)ret);
"%s, could not parse config, err=%x.", obj->descr.parent_name, (int)ret);
}
ESP_LOGD(TAG, "%s, set test time to %" PRIu64, pobj->descr.parent_name, tcp_opts->test_tout_us);
mb_port_adapter_set_response_time(pobj, (tcp_opts->test_tout_us));
ESP_LOGD(TAG, "%s, set test time to %" PRIu64, obj->descr.parent_name, tcp_opts->test_tout_us);
mb_port_adapter_set_response_time(obj, (tcp_opts->test_tout_us));
}
*in_out_obj = pobj;
*in_out_obj = obj;
return ret;
error:
if (pobj) {
mb_port_adapter_delete(pobj);
if (obj) {
mb_port_adapter_delete(obj);
}
return ret;
}
@@ -476,12 +476,12 @@ mb_err_enum_t mb_port_adapter_ser_create(mb_serial_opts_t *ser_opts, mb_port_bas
.state = MB_SOCK_STATE_UNDEF
};
mb_port_base_t *pobj = *in_out_obj;
mb_err_enum_t ret = mb_port_adapter_create(&addr_info, &pobj);
if ((ret == MB_ENOERR) && pobj) {
ESP_LOGD(TAG, "%s, set test time to %d", pobj->descr.parent_name, (int)(ser_opts->test_tout_us));
mb_port_adapter_set_response_time(pobj, (ser_opts->test_tout_us));
*in_out_obj = pobj;
mb_port_base_t *obj = *in_out_obj;
mb_err_enum_t ret = mb_port_adapter_create(&addr_info, &obj);
if ((ret == MB_ENOERR) && obj) {
ESP_LOGD(TAG, "%s, set test time to %d", obj->descr.parent_name, (int)(ser_opts->test_tout_us));
mb_port_adapter_set_response_time(obj, (ser_opts->test_tout_us));
*in_out_obj = obj;
}
return ret;
}
@@ -565,47 +565,44 @@ static esp_err_t mb_port_adapter_set_timer(mb_port_base_t *inst, uint64_t time_d
return ESP_OK;
}
bool mb_port_adapter_recv_data(mb_port_base_t *inst, uint8_t **ppframe, uint16_t *plength)
bool mb_port_adapter_recv_data(mb_port_base_t *inst, uint8_t **frame_ptr, uint16_t *len_ptr)
{
MB_RETURN_ON_FALSE((ppframe && plength), false, TAG, "mb serial get buffer failure.");
MB_RETURN_ON_FALSE((frame_ptr && len_ptr), false, TAG, "mb serial get buffer failure.");
mb_port_adapter_t *port_obj = __containerof(inst, mb_port_adapter_t, base);
int length = *plength ? *plength : port_obj->recv_length;
int rx_len = *len_ptr ? *len_ptr : port_obj->recv_length;
bool ret = false;
if (length)
{
if (rx_len) {
CRITICAL_SECTION_LOCK(inst->lock);
int length = queue_pop(port_obj->rx_queue, &port_obj->rx_buffer[0], CONFIG_FMB_BUFFER_SIZE, NULL);
if (length)
{
rx_len = queue_pop(port_obj->rx_queue, &port_obj->rx_buffer[0], CONFIG_FMB_BUFFER_SIZE, NULL);
if (rx_len) {
mb_port_timer_disable(inst);
ESP_LOGD(TAG, "%s, received data: %d bytes.", inst->descr.parent_name, length);
ESP_LOGD(TAG, "%s, received data: %d bytes.", inst->descr.parent_name, rx_len);
// Stop timer because the new data is received
// Store the timestamp of received frame
port_obj->recv_time_stamp = esp_timer_get_time();
*ppframe = &port_obj->rx_buffer[0];
ESP_LOG_BUFFER_HEX_LEVEL(MB_STR_CAT(inst->descr.parent_name, ":PORT_RECV"),
(void *)&port_obj->rx_buffer[0], (uint16_t)length, ESP_LOG_DEBUG);
*frame_ptr = &port_obj->rx_buffer[0];
MB_PRT_BUF(inst->descr.parent_name, ":PORT_RECV",
&port_obj->rx_buffer[0], rx_len, ESP_LOG_DEBUG);
}
CRITICAL_SECTION_UNLOCK(inst->lock);
*len_ptr = rx_len;
ret = true;
} else {
ESP_LOGE(TAG, "%s: junk data (%d bytes) received. ", inst->descr.parent_name, rx_len);
}
else
{
ESP_LOGE(TAG, "%s: junk data (%d bytes) received. ", inst->descr.parent_name, length);
}
*plength = length;
return true;
return ret;
}
bool mb_port_adapter_send_data(mb_port_base_t *inst, uint8_t address, uint8_t *pframe, uint16_t length)
bool mb_port_adapter_send_data(mb_port_base_t *inst, uint8_t addrets, uint8_t *frame_ptr, uint16_t length)
{
bool res = false;
bool ret = false;
mb_port_adapter_t *port_obj = __containerof(inst, mb_port_adapter_t, base);
uint64_t time_diff = atomic_load(&port_obj->test_timeout_us);
if (pframe && length)
{
if (frame_ptr && length) {
CRITICAL_SECTION_LOCK(inst->lock);
esp_err_t err = queue_push(port_obj->tx_queue, (void *)pframe, length, NULL);
esp_err_t err = queue_push(port_obj->tx_queue, (void *)frame_ptr, length, NULL);
CRITICAL_SECTION_UNLOCK(inst->lock);
MB_RETURN_ON_FALSE((err == ESP_OK),
false, TAG, "%s, could not send the data into queue.", inst->descr.parent_name);
@@ -615,18 +612,17 @@ bool mb_port_adapter_send_data(mb_port_base_t *inst, uint8_t address, uint8_t *p
uint16_t flags = mb_port_adapter_wait_flag(inst, MB_QUEUE_FLAG_SENT, MB_EVENT_QUEUE_TIMEOUT_MAX);
port_obj->send_time_stamp = esp_timer_get_time();
// Print sent packet, the tag used is more clear to see
ESP_LOG_BUFFER_HEX_LEVEL(MB_STR_CAT(inst->descr.parent_name, ":PORT_SEND"),
(void *)pframe, length, ESP_LOG_DEBUG);
MB_PRT_BUF(inst->descr.parent_name, ":PORT_SEND", frame_ptr, length, ESP_LOG_DEBUG);
(void)mb_port_event_post(inst, EVENT(EV_FRAME_SENT));
ESP_LOGD(TAG, "%s, tx completed, flags = 0x%04x.", inst->descr.parent_name, (int)flags);
res = true;
ret = true;
}
else
{
ESP_LOGE(TAG, "send callback %p, %u. ", pframe, (unsigned)length);
ESP_LOGE(TAG, "send callback %p, %u. ", frame_ptr, (unsigned)length);
}
return res;
return ret;
}
void mb_port_adapter_enable(mb_port_base_t *inst)

View File

@@ -24,7 +24,7 @@ typedef enum
#define MB_QUEUE_FLAGS (MB_QUEUE_FLAG_SENT | MB_QUEUE_FLAG_RECV | MB_QUEUE_FLAG_CONNECTED)
typedef struct _uid_info mb_uid_info_t;
typedef struct uid_info_s mb_uid_info_t;
#if (CONFIG_FMB_COMM_MODE_ASCII_EN || CONFIG_FMB_COMM_MODE_RTU_EN)
mb_err_enum_t mb_port_adapter_ser_create(mb_serial_opts_t *ser_opts, mb_port_base_t **in_out_obj);
@@ -36,10 +36,10 @@ mb_err_enum_t mb_port_adapter_tcp_create(mb_tcp_opts_t *tcp_opts, mb_port_base_t
void mb_port_adapter_delete(mb_port_base_t *inst);
void mb_port_adapter_set_response_time(mb_port_base_t *inst, uint64_t resp_time);
int mb_port_adapter_get_rx_buffer(mb_port_base_t *inst, uint8_t **ppfame, int *plength);
int mb_port_adapter_get_rx_buffer(mb_port_base_t *inst, uint8_t **ppfame, int *length);
bool mb_port_adapter_send_data(mb_port_base_t *inst, uint8_t address, uint8_t *pframe, uint16_t length);
bool mb_port_adapter_recv_data(mb_port_base_t *inst, uint8_t **ppframe, uint16_t *plength);
bool mb_port_adapter_send_data(mb_port_base_t *inst, uint8_t address, uint8_t *frame, uint16_t length);
bool mb_port_adapter_recv_data(mb_port_base_t *inst, uint8_t **frame, uint16_t *length);
void mb_port_adapter_enable(mb_port_base_t *inst);
void mb_port_adapter_disable(mb_port_base_t *inst);
void mb_port_adapter_tcp_set_conn_cb(mb_port_base_t *inst, void *conn_fp, void *arg);

View File

@@ -49,14 +49,14 @@ void __wrap_mb_port_ser_delete(mb_port_base_t *inst)
mb_port_adapter_delete(inst);
}
bool __wrap_mb_port_ser_recv_data(mb_port_base_t *inst, uint8_t **ppframe, uint16_t *plength)
bool __wrap_mb_port_ser_recv_data(mb_port_base_t *inst, uint8_t **frame, uint16_t *length)
{
return mb_port_adapter_recv_data(inst, ppframe, plength);
return mb_port_adapter_recv_data(inst, frame, length);
}
bool __wrap_mb_port_ser_send_data(mb_port_base_t *inst, uint8_t *pframe, uint16_t length)
bool __wrap_mb_port_ser_send_data(mb_port_base_t *inst, uint8_t *frame, uint16_t length)
{
return mb_port_adapter_send_data(inst, 0, pframe, length);
return mb_port_adapter_send_data(inst, 0, frame, length);
}
void __wrap_mb_port_ser_enable(mb_port_base_t *inst)
@@ -72,10 +72,10 @@ void __wrap_mb_port_ser_disable(mb_port_base_t *inst)
#endif
IRAM_ATTR
bool __wrap_mb_port_event_get(mb_port_base_t *inst, mb_event_t *pevent)
bool __wrap_mb_port_event_get(mb_port_base_t *inst, mb_event_t *event)
{
bool result = __real_mb_port_event_get(inst, pevent);
ESP_LOGD(TAG, "%s, get event:%x.", inst->descr.parent_name, pevent->event);
bool result = __real_mb_port_event_get(inst, event);
ESP_LOGD(TAG, "%s, get event:%x.", inst->descr.parent_name, event->event);
return result;
}
@@ -95,14 +95,14 @@ mb_err_enum_t __wrap_mbm_port_tcp_create(mb_tcp_opts_t *tcp_opts, mb_port_base_t
return mb_port_adapter_tcp_create(tcp_opts, in_out_obj);
}
bool __wrap_mbm_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **ppframe, uint16_t *plength)
bool __wrap_mbm_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **frame, uint16_t *length)
{
return mb_port_adapter_recv_data(inst, ppframe, plength);
return mb_port_adapter_recv_data(inst, frame, length);
}
bool __wrap_mbm_port_tcp_send_data(mb_port_base_t *inst, uint8_t address, uint8_t *pframe, uint16_t length)
bool __wrap_mbm_port_tcp_send_data(mb_port_base_t *inst, uint8_t address, uint8_t *frame, uint16_t length)
{
return mb_port_adapter_send_data(inst, address, pframe, length);
return mb_port_adapter_send_data(inst, address, frame, length);
}
void __wrap_mbm_port_tcp_delete(mb_port_base_t *inst)
@@ -140,14 +140,14 @@ mb_err_enum_t __wrap_mbs_port_tcp_create(mb_tcp_opts_t *tcp_opts, mb_port_base_t
return mb_port_adapter_tcp_create(tcp_opts, in_out_obj);
}
bool __wrap_mbs_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **ppframe, uint16_t *plength)
bool __wrap_mbs_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **frame, uint16_t *length)
{
return mb_port_adapter_recv_data(inst, ppframe, plength);
return mb_port_adapter_recv_data(inst, frame, length);
}
bool __wrap_mbs_port_tcp_send_data(mb_port_base_t *inst, uint8_t *pframe, uint16_t length)
bool __wrap_mbs_port_tcp_send_data(mb_port_base_t *inst, uint8_t *frame, uint16_t length)
{
return mb_port_adapter_send_data(inst, 0, pframe, length);
return mb_port_adapter_send_data(inst, 0, frame, length);
}
void __wrap_mbs_port_tcp_delete(mb_port_base_t *inst)

View File

@@ -13,9 +13,9 @@
// Serial port function wrappers
bool __wrap_mb_port_event_get(mb_port_base_t *inst, mb_event_t *pevent);
bool __wrap_mb_port_event_get(mb_port_base_t *inst, mb_event_t *event);
bool __wrap_mb_port_event_post(mb_port_base_t *inst, mb_event_t event);
extern bool __real_mb_port_event_get(mb_port_base_t *inst, mb_event_t *pevent);
extern bool __real_mb_port_event_get(mb_port_base_t *inst, mb_event_t *event);
extern bool __real_mb_port_event_post(mb_port_base_t *inst, mb_event_t event);
#if (CONFIG_FMB_COMM_MODE_ASCII_EN || CONFIG_FMB_COMM_MODE_RTU_EN)
@@ -23,14 +23,14 @@ extern bool __real_mb_port_event_post(mb_port_base_t *inst, mb_event_t event);
extern void __real_mb_port_ser_enable(mb_port_base_t *inst);
extern void __real_mb_port_ser_disable(mb_port_base_t *inst);
extern bool __real_mb_port_ser_send_data(mb_port_base_t *inst, uint8_t *p_ser_frame, uint16_t ser_length);
extern bool __real_mb_port_ser_recv_data(mb_port_base_t *inst, uint8_t **pp_ser_frame, uint16_t *p_ser_length);
extern bool __real_mb_port_ser_recv_data(mb_port_base_t *inst, uint8_t **ser_frame, uint16_t *p_ser_length);
extern void __real_mb_port_ser_delete(mb_port_base_t *inst);
mb_err_enum_t __wrap_mb_port_ser_create(mb_serial_opts_t *ser_opts, mb_port_base_t **in_out_obj);
void __wrap_mb_port_ser_enable(mb_port_base_t *inst);
void __wrap_mb_port_ser_disable(mb_port_base_t *inst);
bool __wrap_mb_port_ser_send_data(mb_port_base_t *inst, uint8_t *p_ser_frame, uint16_t ser_length);
bool __wrap_mb_port_ser_recv_data(mb_port_base_t *inst, uint8_t **pp_ser_frame, uint16_t *p_ser_length);
bool __wrap_mb_port_ser_recv_data(mb_port_base_t *inst, uint8_t **ser_frame, uint16_t *p_ser_length);
void __wrap_mb_port_ser_delete(mb_port_base_t *inst);
#endif
@@ -40,8 +40,8 @@ void __wrap_mb_port_ser_delete(mb_port_base_t *inst);
mb_err_enum_t __wrap_mbm_port_tcp_create(mb_tcp_opts_t *tcp_opts, mb_port_base_t **in_out_obj);
void __wrap_mbm_port_tcp_delete(mb_port_base_t *inst);
bool __wrap_mbm_port_tcp_send_data(mb_port_base_t *inst, uint8_t address, uint8_t *pframe, uint16_t length);
bool __wrap_mbm_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **ppframe, uint16_t *plength);
bool __wrap_mbm_port_tcp_send_data(mb_port_base_t *inst, uint8_t address, uint8_t *frame, uint16_t length);
bool __wrap_mbm_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **frame, uint16_t *length);
void __wrap_mbm_port_tcp_enable(mb_port_base_t *inst);
void __wrap_mbm_port_tcp_disable(mb_port_base_t *inst);
void __wrap_mbm_port_tcp_set_conn_cb(mb_port_base_t *inst, void *conn_fp, void *arg);
@@ -52,19 +52,19 @@ extern void __real_mbm_port_tcp_enable(mb_port_base_t *inst);
extern void __real_mbm_port_tcp_disable(mb_port_base_t *inst);
extern void __real_mbm_port_tcp_set_conn_cb(mb_port_base_t *inst, void *conn_fp, void *arg);
extern mb_uid_info_t *__real_mbm_port_tcp_get_slave_info(mb_port_base_t *inst, uint8_t uid, mb_sock_state_t exp_state);
extern bool __real_mbm_port_tcp_send_data(mb_port_base_t *inst, uint8_t address, uint8_t *pframe, uint16_t length);
extern bool __real_mbm_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **ppframe, uint16_t *plength);
extern bool __real_mbm_port_tcp_send_data(mb_port_base_t *inst, uint8_t address, uint8_t *frame, uint16_t length);
extern bool __real_mbm_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **frame, uint16_t *length);
mb_err_enum_t __wrap_mbs_port_tcp_create(mb_tcp_opts_t *tcp_opts, mb_port_base_t **in_out_obj);
void __wrap_mbs_port_tcp_delete(mb_port_base_t *inst);
bool __wrap_mbs_port_tcp_send_data(mb_port_base_t *inst, uint8_t *pframe, uint16_t length);
bool __wrap_mbs_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **ppframe, uint16_t *plength);
bool __wrap_mbs_port_tcp_send_data(mb_port_base_t *inst, uint8_t *frame, uint16_t length);
bool __wrap_mbs_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **frame, uint16_t *length);
void __wrap_mbs_port_tcp_enable(mb_port_base_t *inst);
void __wrap_mbs_port_tcp_disable(mb_port_base_t *inst);
mb_err_enum_t __real_mbs_port_tcp_create(mb_tcp_opts_t *tcp_opts, mb_port_base_t **in_out_obj);
extern void __real_mbs_port_tcp_delete(mb_port_base_t *inst);
extern bool __real_mbs_port_tcp_send_data(mb_port_base_t *inst, uint8_t *pframe, uint16_t length);
extern bool __real_mbs_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **ppframe, uint16_t *plength);
extern bool __real_mbs_port_tcp_send_data(mb_port_base_t *inst, uint8_t *frame, uint16_t length);
extern bool __real_mbs_port_tcp_recv_data(mb_port_base_t *inst, uint8_t **frame, uint16_t *length);
extern void __real_mbs_port_tcp_enable(mb_port_base_t *inst);
extern void __real_mbs_port_tcp_disable(mb_port_base_t *inst);

View File

@@ -120,7 +120,7 @@ static bool task_wait_done_and_remove(task_entry_t *task_entry, TickType_t tout_
return (is_done);
}
static void test_task_add_entry(TaskHandle_t task_handle, void *pinst)
static void test_task_add_entry(TaskHandle_t task_handle, void *inst)
{
TEST_ASSERT_TRUE(task_handle);
task_entry_t *new_entry = (task_entry_t*) calloc(1, sizeof(task_entry_t));
@@ -128,7 +128,7 @@ static void test_task_add_entry(TaskHandle_t task_handle, void *pinst)
portENTER_CRITICAL(&s_list_spinlock);
new_entry->task_handle = task_handle;
new_entry->task_sema_handle = xSemaphoreCreateBinary();
new_entry->inst_handle = pinst;
new_entry->inst_handle = inst;
LIST_INSERT_HEAD(&s_task_list, new_entry, entries);
portEXIT_CRITICAL(&s_list_spinlock);
xSemaphoreTake(new_entry->task_sema_handle, 1);
@@ -561,10 +561,10 @@ void test_common_slave_setup_start(void *mbs_handle)
TaskHandle_t test_common_master_serial_create(mb_communication_info_t *pconfig,
uint32_t priority,
const mb_parameter_descriptor_t *pdescr,
const mb_parameter_descriptor_t *descr,
uint16_t descr_size)
{
if (!pconfig || !pdescr) {
if (!pconfig || !descr) {
ESP_LOGI(TAG, "invalid master configuration.");
}
@@ -574,7 +574,7 @@ TaskHandle_t test_common_master_serial_create(mb_communication_info_t *pconfig,
TEST_ESP_OK(mbc_master_create_serial(pconfig, &mbm_handle));
mbm_controller_iface_t *pbase = mbm_handle;
TEST_ESP_OK(mbc_master_set_descriptor(mbm_handle, pdescr, descr_size));
TEST_ESP_OK(mbc_master_set_descriptor(mbm_handle, descr, descr_size));
ESP_LOGI(TAG, "%p, modbus master stack is initialized", mbm_handle);
TEST_ESP_OK(mbc_master_start(mbm_handle));
@@ -624,9 +624,9 @@ TaskHandle_t test_common_slave_serial_create(mb_communication_info_t *pconfig, u
#if (CONFIG_FMB_COMM_MODE_TCP_EN)
TaskHandle_t test_common_master_tcp_create(mb_communication_info_t *pconfig, uint32_t priority, const mb_parameter_descriptor_t *pdescr, uint16_t descr_size)
TaskHandle_t test_common_master_tcp_create(mb_communication_info_t *pconfig, uint32_t priority, const mb_parameter_descriptor_t *descr, uint16_t descr_size)
{
if (!pconfig || !pdescr) {
if (!pconfig || !descr) {
ESP_LOGI(TAG, "invalid master configuration.");
}
@@ -636,7 +636,7 @@ TaskHandle_t test_common_master_tcp_create(mb_communication_info_t *pconfig, uin
TEST_ESP_OK(mbc_master_create_tcp(pconfig, &mbm_handle));
mbm_controller_iface_t *pbase = mbm_handle;
TEST_ESP_OK(mbc_master_set_descriptor(mbm_handle, pdescr, descr_size));
TEST_ESP_OK(mbc_master_set_descriptor(mbm_handle, descr, descr_size));
ESP_LOGI(TAG, "%p, modbus master stack is initialized", mbm_handle);
TEST_ESP_OK(mbc_master_start(mbm_handle));

View File

@@ -22,7 +22,7 @@ extern "C" {
typedef struct mb_base_t mb_base_t; /*!< Type of modbus object */
typedef struct mb_port_base_t mb_port_base_t;
bool mb_port_event_get(mb_port_base_t *inst, mb_event_t *pevent);
bool mb_port_event_get(mb_port_base_t *inst, mb_event_t *event);
bool mb_port_event_post(mb_port_base_t *inst, mb_event_t event);
bool mb_port_event_res_take(mb_port_base_t *inst, uint32_t timeout);
void mb_port_event_res_release(mb_port_base_t *inst);

View File

@@ -88,11 +88,11 @@ TEST(unit_test_controller, test_setup_destroy_master_tcp)
ESP_LOGI(TAG, "TEST: Verify master create-destroy sequence TCP.");
void *mbm_handle = NULL;
mb_base_t *pmb_base = NULL;
TEST_ESP_ERR(MB_ENOERR, mb_stub_tcp_create(&master_config.tcp_opts, (void *)&pmb_base));
mb_base_t *mb_base = NULL;
TEST_ESP_ERR(MB_ENOERR, mb_stub_tcp_create(&master_config.tcp_opts, (void *)&mb_base));
mbm_tcp_create_ExpectAnyArgsAndReturn(MB_ENOERR);
mbm_tcp_create_ReturnThruPtr_in_out_obj((void **)&pmb_base);
mbm_tcp_create_ReturnThruPtr_in_out_obj((void **)&mb_base);
mbm_port_tcp_get_slave_info_IgnoreAndReturn((void *)(0x11223344));
TEST_ESP_OK(mbc_master_create_tcp(&master_config, &mbm_handle));
TEST_ESP_OK(mbc_master_set_descriptor(mbm_handle, &descriptors[0], num_descriptors));
@@ -121,18 +121,18 @@ TEST(unit_test_controller, test_setup_destroy_master_serial)
ESP_LOGI(TAG, "TEST: Verify master create-destroy sequence.");
void *mbm_handle = NULL;
mb_base_t *pmb_base = NULL;
TEST_ESP_ERR(MB_ENOERR, mb_stub_serial_create(&master_config.ser_opts, (void *)&pmb_base));
mb_base_t *mb_base = NULL;
TEST_ESP_ERR(MB_ENOERR, mb_stub_serial_create(&master_config.ser_opts, (void *)&mb_base));
mbm_rtu_create_ExpectAnyArgsAndReturn(MB_ENOERR);
mbm_rtu_create_ReturnThruPtr_in_out_obj((void **)&pmb_base);
mbm_rtu_create_ReturnThruPtr_in_out_obj((void **)&mb_base);
TEST_ESP_OK(mbc_master_create_serial(&master_config, &mbm_handle));
TEST_ESP_OK(mbc_master_set_descriptor(mbm_handle, &descriptors[0], num_descriptors));
TEST_ESP_OK(mbc_master_delete(mbm_handle));
master_config.ser_opts.mode = MB_ASCII;
mbm_handle = NULL;
pmb_base = NULL;
mb_base = NULL;
mbm_ascii_create_ExpectAnyArgsAndReturn(MB_EINVAL);
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, mbc_master_create_serial(&master_config, &mbm_handle));
@@ -157,11 +157,11 @@ TEST(unit_test_controller, test_setup_destroy_slave_serial)
ESP_LOGI(TAG, "TEST: Verify slave create-destroy sequence.");
void *mbs_handle = NULL;
mb_base_t *pmb_base = mbs_handle;
TEST_ESP_ERR(MB_ENOERR, mb_stub_serial_create(&slave_config.ser_opts, (void *)&pmb_base));
mbs_rtu_create_ExpectAndReturn(&slave_config.ser_opts, (void *)pmb_base, MB_ENOERR);
mb_base_t *mb_base = mbs_handle;
TEST_ESP_ERR(MB_ENOERR, mb_stub_serial_create(&slave_config.ser_opts, (void *)&mb_base));
mbs_rtu_create_ExpectAndReturn(&slave_config.ser_opts, (void *)mb_base, MB_ENOERR);
mbs_rtu_create_IgnoreArg_in_out_obj();
mbs_rtu_create_ReturnThruPtr_in_out_obj((void **)&pmb_base);
mbs_rtu_create_ReturnThruPtr_in_out_obj((void **)&mb_base);
TEST_ESP_OK(mbc_slave_create_serial(&slave_config, &mbs_handle));
TEST_ESP_OK(mbc_slave_delete(mbs_handle));
@@ -186,13 +186,13 @@ esp_err_t test_master_registers(int par_index, mb_err_enum_t mb_err)
.ser_opts.response_tout_ms = 1,
.ser_opts.test_tout_us = TEST_SLAVE_SEND_TOUT_US
};
mb_base_t *pmb_base = NULL; // fake mb_base handle
mb_base_t *mb_base = NULL; // fake mb_base handle
void *mbm_handle = NULL;
TEST_ESP_ERR(MB_ENOERR, mb_stub_serial_create(&master_config.ser_opts, (void *)&pmb_base));
pmb_base->port_obj = (mb_port_base_t *)0x44556677;
TEST_ESP_ERR(MB_ENOERR, mb_stub_serial_create(&master_config.ser_opts, (void *)&mb_base));
mb_base->port_obj = (mb_port_base_t *)0x44556677;
mbm_rtu_create_ExpectAnyArgsAndReturn(MB_ENOERR);
mbm_rtu_create_ReturnThruPtr_in_out_obj((void **)&pmb_base);
mbm_rtu_create_ReturnThruPtr_in_out_obj((void **)&mb_base);
TEST_ESP_OK(mbc_master_create_serial(&master_config, &mbm_handle));
TEST_ESP_OK(mbc_master_set_descriptor(mbm_handle, &descriptors[0], num_descriptors));
mb_port_event_res_take_ExpectAnyArgsAndReturn(true);
@@ -205,12 +205,12 @@ esp_err_t test_master_registers(int par_index, mb_err_enum_t mb_err)
{
TEST_ASSERT_EQUAL_HEX32(&descriptors[par_index], param_descriptor);
uint8_t type = 0; // type of parameter from dictionary
uint8_t *pdata = (uint8_t *)calloc(1, param_descriptor->mb_size + 1);
uint8_t *data_ptr = (uint8_t *)calloc(1, param_descriptor->mb_size + 1);
ESP_LOGI(TAG, "Test CID #%d, %s, %s", param_descriptor->cid, param_descriptor->param_key, param_descriptor->param_units);
// This is to check the request function is called with appropriate params.
switch(param_descriptor->mb_param_type) { \
case MB_PARAM_INPUT: \
mbm_rq_read_inp_reg_ExpectAndReturn(pmb_base, \
mbm_rq_read_inp_reg_ExpectAndReturn(mb_base, \
param_descriptor->mb_slave_addr, \
param_descriptor->mb_reg_start, \
param_descriptor->mb_size, \
@@ -219,7 +219,7 @@ esp_err_t test_master_registers(int par_index, mb_err_enum_t mb_err)
mbm_rq_read_inp_reg_IgnoreArg_tout(); \
break; \
case MB_PARAM_HOLDING:
mbm_rq_read_holding_reg_ExpectAndReturn(pmb_base, \
mbm_rq_read_holding_reg_ExpectAndReturn(mb_base, \
param_descriptor->mb_slave_addr, \
param_descriptor->mb_reg_start, \
param_descriptor->mb_size, \
@@ -228,7 +228,7 @@ esp_err_t test_master_registers(int par_index, mb_err_enum_t mb_err)
mbm_rq_read_holding_reg_IgnoreArg_tout(); \
break; \
case MB_PARAM_COIL: \
mbm_rq_read_coils_ExpectAndReturn(pmb_base, \
mbm_rq_read_coils_ExpectAndReturn(mb_base, \
param_descriptor->mb_slave_addr, \
param_descriptor->mb_reg_start, \
param_descriptor->mb_size, \
@@ -237,7 +237,7 @@ esp_err_t test_master_registers(int par_index, mb_err_enum_t mb_err)
mbm_rq_read_coils_IgnoreArg_tout(); \
break; \
case MB_PARAM_DISCRETE: \
mbm_rq_read_discrete_inputs_ExpectAndReturn(pmb_base, \
mbm_rq_read_discrete_inputs_ExpectAndReturn(mb_base, \
param_descriptor->mb_slave_addr, \
param_descriptor->mb_reg_start, \
param_descriptor->mb_size, \
@@ -249,8 +249,8 @@ esp_err_t test_master_registers(int par_index, mb_err_enum_t mb_err)
TEST_FAIL(); \
break; \
}
err = mbc_master_get_parameter(mbm_handle, par_index, pdata, &type); \
free(pdata);
err = mbc_master_get_parameter(mbm_handle, par_index, data_ptr, &type); \
free(data_ptr);
}
TEST_ESP_OK(mbc_master_stop(mbm_handle));
TEST_ESP_OK(mbc_master_delete(mbm_handle));

View File

@@ -73,7 +73,7 @@ extern "C" {
typedef struct mb_base_t mb_base_t; /*!< Type of modbus object */
typedef struct mb_port_base_t mb_port_base_t;
bool mb_port_event_get(mb_port_base_t *inst, mb_event_t *pevent);
bool mb_port_event_get(mb_port_base_t *inst, mb_event_t *event);
bool mb_port_event_post(mb_port_base_t *inst, mb_event_t event);
bool mb_port_event_res_take(mb_port_base_t *inst, uint32_t timeout);
void mb_port_event_res_release(mb_port_base_t *inst);

View File

@@ -104,51 +104,51 @@ static void test_slave_check_descriptor(int par_index)
};
void *mbs_handle = NULL;
mb_base_t *pmb_base = NULL; // fake mb_base handle
mb_base_t *mb_base = NULL; // fake mb_base handle
TEST_ESP_ERR(MB_ENOERR, mb_stub_serial_create(&slave_config.ser_opts, (void *)&pmb_base));
pmb_base->port_obj = (mb_port_base_t *)0x44556677;
TEST_ESP_ERR(MB_ENOERR, mb_stub_serial_create(&slave_config.ser_opts, (void *)&mb_base));
mb_base->port_obj = (mb_port_base_t *)0x44556677;
mbs_rtu_create_ExpectAnyArgsAndReturn(MB_ENOERR);
mbs_rtu_create_ReturnThruPtr_in_out_obj((void **)&pmb_base);
mbs_rtu_create_ReturnThruPtr_in_out_obj((void **)&mb_base);
TEST_ESP_OK(mbc_slave_create_serial(&slave_config, &mbs_handle));
TEST_ASSERT(mbs_handle);
mbs_controller_iface_t *mbs_iface = (mbs_controller_iface_t *)mbs_handle;
//mb_slave_options_t *mbs_opts = MB_SLAVE_GET_OPTS(mbs_iface);
TEST_ASSERT_EQUAL_HEX32(mbs_iface->mb_base, pmb_base);
TEST_ASSERT_EQUAL_HEX32(mbs_iface->mb_base, mb_base);
TEST_ASSERT_EQUAL_HEX32(pmb_base->rw_cbs.reg_input_cb, mbc_reg_input_slave_cb);
TEST_ASSERT_EQUAL_HEX32(pmb_base->rw_cbs.reg_holding_cb, mbc_reg_holding_slave_cb);
TEST_ASSERT_EQUAL_HEX32(pmb_base->rw_cbs.reg_coils_cb, mbc_reg_coils_slave_cb);
TEST_ASSERT_EQUAL_HEX32(pmb_base->rw_cbs.reg_discrete_cb, mbc_reg_discrete_slave_cb);
TEST_ASSERT_EQUAL_HEX32(mb_base->rw_cbs.reg_input_cb, mbc_reg_input_slave_cb);
TEST_ASSERT_EQUAL_HEX32(mb_base->rw_cbs.reg_holding_cb, mbc_reg_holding_slave_cb);
TEST_ASSERT_EQUAL_HEX32(mb_base->rw_cbs.reg_coils_cb, mbc_reg_coils_slave_cb);
TEST_ASSERT_EQUAL_HEX32(mb_base->rw_cbs.reg_discrete_cb, mbc_reg_discrete_slave_cb);
mb_parameter_descriptor_t *pdescr = (mb_parameter_descriptor_t *)&descriptors[par_index];
mb_parameter_descriptor_t *descr = (mb_parameter_descriptor_t *)&descriptors[par_index];
mb_register_area_descriptor_t reg_area;
ESP_LOGI(TAG, "Test CID #%d, %s, %s", pdescr->cid, pdescr->param_key, pdescr->param_units);
ESP_LOGI(TAG, "Test CID #%d, %s, %s", descr->cid, descr->param_key, descr->param_units);
uint16_t n_bytes = ((pdescr->mb_param_type == MB_PARAM_INPUT) || (pdescr->mb_param_type == MB_PARAM_HOLDING))
? (pdescr->mb_size << 1) : ((pdescr->mb_size >> 3) + 1);
uint16_t n_bytes = ((descr->mb_param_type == MB_PARAM_INPUT) || (descr->mb_param_type == MB_PARAM_HOLDING))
? (descr->mb_size << 1) : ((descr->mb_size >> 3) + 1);
// First define the correct area
reg_area.type = pdescr->mb_param_type;
reg_area.start_offset = pdescr->mb_reg_start;
reg_area.address = (void *)pdescr->param_offset;
reg_area.type = descr->mb_param_type;
reg_area.start_offset = descr->mb_reg_start;
reg_area.address = (void *)descr->param_offset;
reg_area.size = n_bytes;
ESP_LOGI(TAG, "Area (type, reg_start, address, size): %d, %u, 0x%" PRIx32 ", %d, is defined.",
(int)reg_area.type, (unsigned)reg_area.start_offset, (uint32_t)reg_area.address, (int)reg_area.size);
TEST_ESP_OK(mbc_slave_set_descriptor(mbs_handle, reg_area));
// Check additional area overlapped
reg_area.start_offset = (pdescr->mb_reg_start + pdescr->mb_size - 2);
reg_area.start_offset = (descr->mb_reg_start + descr->mb_size - 2);
reg_area.size = 2;
ESP_LOGI(TAG, "Area overlapped (type, reg_start, address, size): %d, %u, 0x%" PRIx32 ", %d.",
(int)reg_area.type, (unsigned)reg_area.start_offset, (uint32_t)reg_area.address, (int)reg_area.size);
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, mbc_slave_set_descriptor(mbs_handle, reg_area));
reg_area.start_offset = pdescr->mb_reg_start;
reg_area.start_offset = descr->mb_reg_start;
reg_area.size = n_bytes;
reg_area.address = (void *)pdescr->param_offset - 2;
reg_area.address = (void *)descr->param_offset - 2;
ESP_LOGI(TAG, "Area redefine (type, reg_start, address, size): %d, %u, 0x%" PRIx32 ", %d.",
(int)reg_area.type, (unsigned)reg_area.start_offset, (uint32_t)reg_area.address, (int)reg_area.size);
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, mbc_slave_set_descriptor(mbs_handle, reg_area));
@@ -170,24 +170,24 @@ static esp_err_t test_master_read_req(int par_index, mb_err_enum_t mb_err)
.ser_opts.parity = UART_PARITY_DISABLE,
.ser_opts.response_tout_ms = 1,
.ser_opts.test_tout_us = TEST_SLAVE_SEND_TOUT_US};
mb_base_t *pmb_base = NULL; // fake mb_base handle
mb_base_t *mb_base = NULL; // fake mb_base handle
void *mbm_handle = NULL;
TEST_ESP_ERR(MB_ENOERR, mb_stub_serial_create(&master_config.ser_opts, (void *)&pmb_base));
pmb_base->port_obj = (mb_port_base_t *)0x44556677;
TEST_ESP_ERR(MB_ENOERR, mb_stub_serial_create(&master_config.ser_opts, (void *)&mb_base));
mb_base->port_obj = (mb_port_base_t *)0x44556677;
mbm_rtu_create_ExpectAnyArgsAndReturn(MB_ENOERR);
mbm_rtu_create_ReturnThruPtr_in_out_obj((void **)&pmb_base);
mbm_rtu_create_ReturnThruPtr_in_out_obj((void **)&mb_base);
TEST_ESP_OK(mbc_master_create_serial(&master_config, &mbm_handle));
TEST_ESP_OK(mbc_master_set_descriptor(mbm_handle, &descriptors[0], num_descriptors));
mb_port_event_post_ExpectAndReturn(pmb_base->port_obj, EVENT(EV_FRAME_TRANSMIT | EV_TRANS_START), true);
mb_port_event_post_ExpectAndReturn(mb_base->port_obj, EVENT(EV_FRAME_TRANSMIT | EV_TRANS_START), true);
TEST_ESP_OK(mbc_master_start(mbm_handle));
mb_port_event_wait_req_finish_ExpectAndReturn(pmb_base->port_obj, mb_err);
mb_port_event_wait_req_finish_ExpectAndReturn(mb_base->port_obj, mb_err);
const mb_parameter_descriptor_t *param_descriptor = NULL;
TEST_ESP_OK(mbc_master_get_cid_info(mbm_handle, par_index, &param_descriptor));
TEST_ASSERT_EQUAL_HEX32(&descriptors[par_index], param_descriptor);
uint8_t type = 0; // type of parameter from dictionary
uint8_t pdata[100] = {0};
uint8_t data_ptr[100] = {0};
ESP_LOGI(TAG, "Test CID #%d, %s, %s", param_descriptor->cid, param_descriptor->param_key, param_descriptor->param_units);
mb_port_event_res_take_ExpectAnyArgsAndReturn(true);
mb_port_event_res_release_ExpectAnyArgs();
@@ -195,12 +195,12 @@ static esp_err_t test_master_read_req(int par_index, mb_err_enum_t mb_err)
mb_port_event_res_release_ExpectAnyArgs();
// Call the read method of modbus controller
esp_err_t err = mbc_master_get_parameter(mbm_handle, par_index, pdata, &type);
esp_err_t err = mbc_master_get_parameter(mbm_handle, par_index, data_ptr, &type);
uint8_t *mb_frame_ptr = NULL;
// get send buffer back using the fake mb_object
pmb_base->get_send_buf(pmb_base, &mb_frame_ptr);
TEST_ASSERT_EQUAL_HEX8(pmb_base->get_dest_addr(pmb_base), param_descriptor->mb_slave_addr);
uint8_t send_len = pmb_base->get_send_len(pmb_base);
mb_base->get_send_buf(mb_base, &mb_frame_ptr);
TEST_ASSERT_EQUAL_HEX8(mb_base->get_dest_addr(mb_base), param_descriptor->mb_slave_addr);
uint8_t send_len = mb_base->get_send_len(mb_base);
TEST_ASSERT_EQUAL_HEX8(send_len, (MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE));
// Check that request function forms correct buffer
switch (param_descriptor->mb_param_type)
@@ -261,17 +261,17 @@ static esp_err_t test_master_write_req(int par_index, mb_err_enum_t mb_err)
.ser_opts.parity = UART_PARITY_DISABLE,
.ser_opts.response_tout_ms = 1,
.ser_opts.test_tout_us = TEST_SLAVE_SEND_TOUT_US};
mb_base_t *pmb_base = NULL; // fake mb_base handle
mb_base_t *mb_base = NULL; // fake mb_base handle
void *mbm_handle = NULL;
TEST_ESP_ERR(MB_ENOERR, mb_stub_serial_create(&master_config.ser_opts, (void *)&pmb_base));
pmb_base->port_obj = (mb_port_base_t *)0x44556677;
TEST_ESP_ERR(MB_ENOERR, mb_stub_serial_create(&master_config.ser_opts, (void *)&mb_base));
mb_base->port_obj = (mb_port_base_t *)0x44556677;
mbm_rtu_create_ExpectAnyArgsAndReturn(MB_ENOERR);
mbm_rtu_create_ReturnThruPtr_in_out_obj((void **)&pmb_base);
mbm_rtu_create_ReturnThruPtr_in_out_obj((void **)&mb_base);
TEST_ESP_OK(mbc_master_create_serial(&master_config, &mbm_handle));
TEST_ESP_OK(mbc_master_set_descriptor(mbm_handle, &descriptors[0], num_descriptors));
mb_port_event_post_ExpectAndReturn(pmb_base->port_obj, EVENT(EV_FRAME_TRANSMIT | EV_TRANS_START), true);
mb_port_event_wait_req_finish_ExpectAndReturn(pmb_base->port_obj, mb_err);
mb_port_event_post_ExpectAndReturn(mb_base->port_obj, EVENT(EV_FRAME_TRANSMIT | EV_TRANS_START), true);
mb_port_event_wait_req_finish_ExpectAndReturn(mb_base->port_obj, mb_err);
TEST_ESP_OK(mbc_master_start(mbm_handle));
const mb_parameter_descriptor_t *param_descriptor = NULL;
@@ -289,9 +289,9 @@ static esp_err_t test_master_write_req(int par_index, mb_err_enum_t mb_err)
esp_err_t err = mbc_master_set_parameter(mbm_handle, par_index, reg_data, &type);
uint8_t *mb_frame_ptr = NULL;
// get send buffer back using the fake mb_object
pmb_base->get_send_buf(pmb_base, &mb_frame_ptr);
TEST_ASSERT_EQUAL_HEX8(pmb_base->get_dest_addr(pmb_base), param_descriptor->mb_slave_addr);
uint8_t send_len = pmb_base->get_send_len(pmb_base);
mb_base->get_send_buf(mb_base, &mb_frame_ptr);
TEST_ASSERT_EQUAL_HEX8(mb_base->get_dest_addr(mb_base), param_descriptor->mb_slave_addr);
uint8_t send_len = mb_base->get_send_len(mb_base);
// Check that request function forms correct buffer
switch (param_descriptor->mb_param_type)
{
@@ -310,7 +310,7 @@ static esp_err_t test_master_write_req(int par_index, mb_err_enum_t mb_err)
TEST_ASSERT_EQUAL_HEX8(reg_data[1], mb_frame_ptr[MB_PDU_REQ_WRITE_MUL_VALUES_OFF]);
}
ESP_LOG_BUFFER_HEX_LEVEL(TAG, (void *)mb_frame_ptr, send_len, ESP_LOG_INFO);
// TEST_ESP_ERR(MB_ENOERR, mbs_fn_write_holding_reg(pmb_base, mb_frame_ptr, &send_len));
// TEST_ESP_ERR(MB_ENOERR, mbs_fn_write_holding_reg(mb_base, mb_frame_ptr, &send_len));
break;
case MB_PARAM_COIL:
TEST_ASSERT_EQUAL_HEX8(mb_frame_ptr[MB_PDU_FUNC_OFF], MB_FUNC_WRITE_MULTIPLE_COILS);
@@ -347,23 +347,23 @@ static esp_err_t test_master_check_callback(int par_index, mb_err_enum_t mb_err)
.ser_opts.parity = UART_PARITY_DISABLE,
.ser_opts.response_tout_ms = 1,
.ser_opts.test_tout_us = TEST_SLAVE_SEND_TOUT_US};
mb_base_t *pmb_base = NULL; // fake mb_base handle
mb_base_t *mb_base = NULL; // fake mb_base handle
void *mbm_handle = NULL;
TEST_ESP_ERR(MB_ENOERR, mb_stub_serial_create(&master_config.ser_opts, (void *)&pmb_base));
pmb_base->port_obj = (mb_port_base_t *)0x44556677;
TEST_ESP_ERR(MB_ENOERR, mb_stub_serial_create(&master_config.ser_opts, (void *)&mb_base));
mb_base->port_obj = (mb_port_base_t *)0x44556677;
mbm_rtu_create_ExpectAnyArgsAndReturn(MB_ENOERR);
mbm_rtu_create_ReturnThruPtr_in_out_obj((void **)&pmb_base);
mbm_rtu_create_ReturnThruPtr_in_out_obj((void **)&mb_base);
TEST_ESP_OK(mbc_master_create_serial(&master_config, &mbm_handle));
TEST_ESP_OK(mbc_master_set_descriptor(mbm_handle, &descriptors[0], num_descriptors));
mbm_controller_iface_t *mbm_controller_iface = (mbm_controller_iface_t *)mbm_handle;
mb_master_options_t *mbm_opts = MB_MASTER_GET_OPTS(mbm_controller_iface);
TEST_ASSERT_EQUAL_HEX32(mbm_controller_iface->mb_base, pmb_base);
TEST_ASSERT_EQUAL_HEX32(mbm_controller_iface->mb_base, mb_base);
TEST_ASSERT_EQUAL_HEX32(pmb_base->rw_cbs.reg_input_cb, mbc_reg_input_master_cb);
TEST_ASSERT_EQUAL_HEX32(pmb_base->rw_cbs.reg_holding_cb, mbc_reg_holding_master_cb);
TEST_ASSERT_EQUAL_HEX32(pmb_base->rw_cbs.reg_coils_cb, mbc_reg_coils_master_cb);
TEST_ASSERT_EQUAL_HEX32(pmb_base->rw_cbs.reg_discrete_cb, mbc_reg_discrete_master_cb);
TEST_ASSERT_EQUAL_HEX32(mb_base->rw_cbs.reg_input_cb, mbc_reg_input_master_cb);
TEST_ASSERT_EQUAL_HEX32(mb_base->rw_cbs.reg_holding_cb, mbc_reg_holding_master_cb);
TEST_ASSERT_EQUAL_HEX32(mb_base->rw_cbs.reg_coils_cb, mbc_reg_coils_master_cb);
TEST_ASSERT_EQUAL_HEX32(mb_base->rw_cbs.reg_discrete_cb, mbc_reg_discrete_master_cb);
TEST_ESP_OK(mbc_master_start(mbm_handle));
@@ -380,7 +380,7 @@ static esp_err_t test_master_check_callback(int par_index, mb_err_enum_t mb_err)
switch (param_descriptor->mb_param_type)
{
case MB_PARAM_HOLDING:
err = mbc_reg_holding_master_cb(pmb_base, reg_data_in, param_descriptor->mb_reg_start,
err = mbc_reg_holding_master_cb(mb_base, reg_data_in, param_descriptor->mb_reg_start,
param_descriptor->mb_size, MB_REG_READ);
for (int i = 0; (i < param_descriptor->mb_size); i++)
{
@@ -392,7 +392,7 @@ static esp_err_t test_master_check_callback(int par_index, mb_err_enum_t mb_err)
break;
case MB_PARAM_INPUT:
err = mbc_reg_input_master_cb(pmb_base, reg_data_in, param_descriptor->mb_reg_start,
err = mbc_reg_input_master_cb(mb_base, reg_data_in, param_descriptor->mb_reg_start,
param_descriptor->mb_size);
ESP_LOG_BUFFER_HEX_LEVEL(TAG ", INPUT_BUFF", (void *)reg_data_in, (param_descriptor->mb_size << 1), ESP_LOG_INFO);
for (int i = 0; (i < param_descriptor->mb_size); i++)
@@ -406,7 +406,7 @@ static esp_err_t test_master_check_callback(int par_index, mb_err_enum_t mb_err)
case MB_PARAM_COIL:
reg_data_in[0] = 0xFF;
reg_data_in[1] = 0xFF;
err = mbc_reg_coils_master_cb(pmb_base, reg_data_in, param_descriptor->mb_reg_start, param_descriptor->mb_size, MB_REG_READ);
err = mbc_reg_coils_master_cb(mb_base, reg_data_in, param_descriptor->mb_reg_start, param_descriptor->mb_size, MB_REG_READ);
byte_cnt = (param_descriptor->mb_size & 0x0007) ? ((param_descriptor->mb_size >> 3) + 1) : (param_descriptor->mb_size >> 3);
ESP_LOG_BUFFER_HEX_LEVEL(TAG ", INPUT_BUFF", (void *)reg_data_in, byte_cnt, ESP_LOG_INFO);
TEST_ASSERT_EQUAL_HEX8((reg_data_out[0] & param_descriptor->param_opts.opt1), param_descriptor->param_opts.opt1);
@@ -417,7 +417,7 @@ static esp_err_t test_master_check_callback(int par_index, mb_err_enum_t mb_err)
case MB_PARAM_DISCRETE:
reg_data_in[0] = 0xFF;
reg_data_in[1] = 0xFF;
err = mbc_reg_discrete_master_cb(pmb_base, reg_data_in, param_descriptor->mb_reg_start, param_descriptor->mb_size);
err = mbc_reg_discrete_master_cb(mb_base, reg_data_in, param_descriptor->mb_reg_start, param_descriptor->mb_size);
byte_cnt = (param_descriptor->mb_size & 0x0007) ? ((param_descriptor->mb_size >> 3) + 1) : (param_descriptor->mb_size >> 3);
ESP_LOG_BUFFER_HEX_LEVEL(TAG ", INPUT_BUFF", (void *)reg_data_in, byte_cnt, ESP_LOG_INFO);
TEST_ASSERT_EQUAL_HEX8((reg_data_out[0] & param_descriptor->param_opts.opt1), param_descriptor->param_opts.opt1);

View File

@@ -14,14 +14,14 @@ extern "C" {
#endif
typedef struct mb_trans_base_t mb_trans_base_t; /*!< Type of moddus transport object */
typedef struct _obj_descr obj_descr_t;
typedef struct obj_descr_s obj_descr_t;
typedef void (*mb_frm_start_fp)(mb_trans_base_t *transport);
typedef void (*mb_frm_stop_fp)(mb_trans_base_t *transport);
typedef mb_err_enum_t (*mb_frm_rcv_fp)(mb_trans_base_t *transport, uint8_t *rcv_addr_buf, uint8_t **frame_ptr_buf, uint16_t *len_buf);
typedef mb_err_enum_t (*mb_frm_rcv_fp)(mb_trans_base_t *transport, uint8_t *rcv_addr_buf, uint8_t **frame_buf, uint16_t *len_buf);
typedef mb_err_enum_t (*mb_frm_snd_fp)(mb_trans_base_t *transport, uint8_t slv_addr, const uint8_t *frame_ptr, uint16_t len);
typedef void (*mb_get_rx_frm_fp) (mb_trans_base_t *transport, uint8_t **frame_ptr_buf);
typedef void (*mb_get_tx_frm_fp) (mb_trans_base_t *transport, uint8_t **frame_ptr_buf);
typedef void (*mb_get_rx_frm_fp) (mb_trans_base_t *transport, uint8_t **frame_buf);
typedef void (*mb_get_tx_frm_fp) (mb_trans_base_t *transport, uint8_t **frame_buf);
typedef bool (*mb_get_fp)(mb_trans_base_t *inst);
struct mb_trans_base_t

View File

@@ -37,7 +37,7 @@ static void mb_set_pdu_send_length(mb_base_t *inst, uint16_t length);
static uint16_t mb_get_pdu_send_length(mb_base_t *inst);
static void mb_set_dest_addr(mb_base_t *inst, uint8_t dest_addr);
static uint8_t mb_get_dest_addr(mb_base_t *inst);
static void mb_get_pdu_send_buf(mb_base_t *inst, uint8_t **pbuf);
static void mb_get_pdu_send_buf(mb_base_t *inst, uint8_t **buf);
//mb_err_enum_t mb_tcp_create(mb_tcp_opts_t *tcp_opts, void **in_out_obj);
@@ -140,16 +140,16 @@ mb_err_enum_t mb_disable(mb_base_t *inst)
return status;
}
static void mb_get_pdu_send_buf(mb_base_t *inst, uint8_t **pbuf)
static void mb_get_pdu_send_buf(mb_base_t *inst, uint8_t **buf)
{
mb_object_t *mb_obj = __containerof(inst, mb_object_t, base);
if (pbuf) {
*pbuf = mb_obj->snd_buf;
if (buf) {
*buf = mb_obj->snd_buf;
}
}
// __attribute__((unused))
// static void mb_get_pdu_recv_buf(mb_base_t *inst, uint8_t **pbuf)
// static void mb_get_pdu_recv_buf(mb_base_t *inst, uint8_t **buf)
// {
// //mb_object_t *mb_obj = __containerof(inst, mb_object_t, base);
// }

View File

@@ -32,13 +32,13 @@ typedef struct
mb_err_enum_t mbm_rtu_transp_create(mb_serial_opts_t *ser_opts, void **in_out_inst);
static void mbm_rtu_transp_start(mb_trans_base_t *inst);
static void mbm_rtu_transp_stop(mb_trans_base_t *inst);
static mb_err_enum_t mbm_rtu_transp_receive(mb_trans_base_t *inst, uint8_t *rcv_addr_buf, uint8_t **frame_ptr_buf, uint16_t *len_buf);
static mb_err_enum_t mbm_rtu_transp_receive(mb_trans_base_t *inst, uint8_t *rcv_addr_buf, uint8_t **frame_buf, uint16_t *len_buf);
static mb_err_enum_t mbm_rtu_transp_send(mb_trans_base_t *inst, uint8_t slv_addr, const uint8_t *frame_ptr, uint16_t len);
static bool mbm_rtu_transp_rcv_fsm(mb_trans_base_t *inst);
static bool mbm_rtu_transp_snd_fsm(mb_trans_base_t *inst);
static bool mbm_rtu_transp_timer_expired(void *inst);
static void mbm_rtu_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf);
static void mbm_rtu_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf);
static void mbm_rtu_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_buf);
static void mbm_rtu_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_buf);
// static uint16_t mbm_rtu_transp_get_snd_len(mb_trans_base_t *inst);
static void mbm_rtu_transp_set_snd_len(mb_trans_base_t *inst, uint16_t snd_pdu_len);
static bool mbm_rtu_transp_rq_is_bcast(mb_trans_base_t *inst);
@@ -133,43 +133,43 @@ static void mbm_rtu_transp_stop(mb_trans_base_t *inst)
};
}
static mb_err_enum_t mbm_rtu_transp_receive(mb_trans_base_t *inst, uint8_t *prcv_addr, uint8_t **ppframe_buf, uint16_t *pbuf_len)
static mb_err_enum_t mbm_rtu_transp_receive(mb_trans_base_t *inst, uint8_t *recv_addr, uint8_t **frame_buf, uint16_t *buf_len)
{
mbm_rtu_transp_t *transp = __containerof(inst, mbm_rtu_transp_t, base);
if (!pbuf_len || !prcv_addr || !ppframe_buf || !pbuf_len) {
if (!buf_len || !recv_addr || !frame_buf || !buf_len) {
return MB_EIO;
}
mb_err_enum_t status = MB_ENOERR;
uint8_t *pbuf = (uint8_t *)transp->rcv_buf;
uint16_t length = *pbuf_len;
uint8_t *buf = (uint8_t *)transp->rcv_buf;
uint16_t length = *buf_len;
if (mb_port_ser_recv_data(inst->port_obj, &pbuf, &length) == false) {
*pbuf_len = 0;
if (mb_port_ser_recv_data(inst->port_obj, &buf, &length) == false) {
*buf_len = 0;
return MB_EPORTERR;
}
assert(length < MB_RTU_SER_PDU_SIZE_MAX);
assert(pbuf);
assert(buf);
/* Check length and CRC checksum */
if ((length >= MB_RTU_SER_PDU_SIZE_MIN)
&& (mb_crc16((uint8_t *)pbuf, length) == 0)) {
&& (mb_crc16((uint8_t *)buf, length) == 0)) {
/* Save the address field. All frames are passed to the upper layed
* and the decision if a frame is used is done there.
*/
*prcv_addr = pbuf[MB_SER_PDU_ADDR_OFF];
*recv_addr = buf[MB_SER_PDU_ADDR_OFF];
/* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
* size of address field and CRC checksum.
*/
*pbuf_len = (uint16_t)(length - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC);
*buf_len = (uint16_t)(length - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC);
transp->rcv_buf_pos = length;
/* Return the start of the Modbus PDU to the caller. */
*ppframe_buf = (uint8_t *)&pbuf[MB_SER_PDU_PDU_OFF];
*frame_buf = (uint8_t *)&buf[MB_SER_PDU_PDU_OFF];
} else {
status = MB_EIO;
}
@@ -266,19 +266,19 @@ static bool mbm_rtu_transp_timer_expired(void *inst)
return need_poll;
}
static void mbm_rtu_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf)
static void mbm_rtu_transp_get_rcv_buf(mb_trans_base_t *inst, uint8_t **frame_buf)
{
mbm_rtu_transp_t *transp = __containerof(inst, mbm_rtu_transp_t, base);
CRITICAL_SECTION(inst->lock) {
*frame_ptr_buf = (uint8_t *)&transp->rcv_buf[MB_PDU_FUNC_OFF];
*frame_buf = (uint8_t *)&transp->rcv_buf[MB_PDU_FUNC_OFF];
}
}
static void mbm_rtu_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_ptr_buf)
static void mbm_rtu_transp_get_snd_buf(mb_trans_base_t *inst, uint8_t **frame_buf)
{
mbm_rtu_transp_t *transp = __containerof(inst, mbm_rtu_transp_t, base);
CRITICAL_SECTION(inst->lock) {
*frame_ptr_buf = (uint8_t *)&transp->snd_buf[MB_RTU_SER_PDU_PDU_OFF];
*frame_buf = (uint8_t *)&transp->snd_buf[MB_RTU_SER_PDU_PDU_OFF];
}
}

24
tools/.clang-tidy Normal file
View File

@@ -0,0 +1,24 @@
---
Checks: >
-*,
bugprone-argument-comment,
bugprone-too-small-loop-variable,
google-explicit-constructor,
misc-unused-using-decls,
modernize-loop-convert,
modernize-use-bool-literals,
modernize-use-equals-default,
modernize-use-equals-delete,
modernize-use-nullptr,
readability-avoid-const-params-in-decls,
readability-make-member-function-const,
readability-redundant-control-flow,
readability-redundant-member-init,
readability-simplify-boolean-expr,
readability-static-accessed-through-instance,
readability-else-after-return,
readability-inconsistent-declaration-parameter-name,
WarningsAsErrors: '*'
HeaderFilterRegex: '(examples|include|src).*(?<!third_party.*repo)'

46
tools/static_analyzer_check.sh Executable file
View File

@@ -0,0 +1,46 @@
#!/bin/bash
SCRIPT_DIR="$( cd "$(dirname "$0")" ; pwd -P )"
${IDF_PATH}/tools/idf_tools.py --non-interactive install esp-clang
export APPS=$( find . -type d ! -path "*build*" ! -path "*espressif__*" ! -path "*managed_components*" ! -path "*arch*" \
\( -exec test -f '{}/CMakeLists.txt' \; -and -exec test -d '{}/main' \; -and -exec test -f '{}/main/CMakeLists.txt' \; \
\) -print )
if [ $# -gt 1 ]; then
echo "Incorrect number of parameters."
exit 1
fi
echo "Found applications to check: ${APPS}"
for APP_DIR in ${APPS}
do
pushd ${APP_DIR}
case "$1" in
"" | "clang")
echo "CLANG build"
export IDF_TOOLCHAIN="clang"
. ${IDF_PATH}/export.sh
echo "Clang check folder: ${PWD}, managed comp dir: ${APP_DIR}/managed_components"
${IDF_PATH}/tools/idf.py clang-check \
--include-paths ${SCRIPT_DIR}/../modbus \
--exclude-paths ./managed_components \
--run-clang-tidy-py run-clang-tidy \
--run-clang-tidy-options "-config-file=${SCRIPT_DIR}/.clang-tidy"
;;
"gcc")
rm -f sdkconfig
export IDF_TOOLCHAIN="gcc"
. ${IDF_PATH}/export.sh
echo "GCC check folder: ${PWD}"
echo "CONFIG_FMB_COMPILER_STATIC_ANALYZER_ENABLE=y" >> ${PWD}/sdkconfig.defaults
idf.py set-target "esp32"
idf.py build || die "CMake build in ${PWD} has failed"
;;
*)
echo "Incorrect parameter provided: $1, should be 'gcc' or 'clang'."
exit 1
;;
esac
popd
done