mirror of
https://github.com/espressif/esp-modbus.git
synced 2026-05-04 03:40:52 +02:00
fix static analyzer warnings, add analyzer (gcc, clang) tool and ci jobs to check
This commit is contained in:
+41
-4
@@ -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,15 +137,48 @@ 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
|
||||
image: espressif/idf:latest
|
||||
variables:
|
||||
TEST_TARGETS: "esp32 esp32s2 esp32s3 esp32c2 esp32c3 esp32c5 esp32c6 esp32h2"
|
||||
extends: .build_pytest_template
|
||||
image: espressif/idf:latest
|
||||
variables:
|
||||
TEST_TARGETS: "esp32 esp32s2 esp32s3 esp32c2 esp32c3 esp32c5 esp32c6 esp32h2"
|
||||
|
||||
build_idf_v5.3:
|
||||
extends: .build_pytest_template
|
||||
|
||||
@@ -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}")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,55 +259,55 @@ static void *master_get_param_data(const mb_parameter_descriptor_t *param_descri
|
||||
return instance_ptr;
|
||||
}
|
||||
|
||||
#define TEST_VERIFY_VALUES(handle, pdescr, pinst) (__extension__( \
|
||||
{ \
|
||||
assert(pinst); \
|
||||
assert(pdescr); \
|
||||
uint8_t type = 0; \
|
||||
esp_err_t err = ESP_FAIL; \
|
||||
err = mbc_master_get_parameter(handle, pdescr->cid, \
|
||||
(uint8_t *)pinst, &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; \
|
||||
ESP_LOGD(TAG, "Characteristic #%d (%s), initialize to 0x%" PRIx16 ".", \
|
||||
(int)pdescr->cid, \
|
||||
(char *)pdescr->param_key, \
|
||||
(uint16_t)pdescr->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); \
|
||||
if (err != ESP_OK) { \
|
||||
ESP_LOGE(TAG, "Characteristic #%d (%s) write fail, err = 0x%x (%s).", \
|
||||
(int)pdescr->cid, \
|
||||
(char *)pdescr->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); \
|
||||
} \
|
||||
} \
|
||||
} else { \
|
||||
ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).", \
|
||||
(int)pdescr->cid, \
|
||||
(char *)pdescr->param_key, \
|
||||
(int)err, \
|
||||
(char *)esp_err_to_name(err)); \
|
||||
} \
|
||||
(err); \
|
||||
} \
|
||||
#define TEST_VERIFY_VALUES(handle, descr, inst) (__extension__( \
|
||||
{ \
|
||||
assert(inst); \
|
||||
assert(descr); \
|
||||
uint8_t type = 0; \
|
||||
esp_err_t err = ESP_FAIL; \
|
||||
err = mbc_master_get_parameter(handle, descr->cid, \
|
||||
(uint8_t *)inst, &type); \
|
||||
if (err == ESP_OK) { \
|
||||
bool is_correct = true; \
|
||||
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)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)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)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)descr->cid, \
|
||||
(char *)descr->param_key, \
|
||||
(char *)descr->param_units); \
|
||||
} \
|
||||
} \
|
||||
} else { \
|
||||
ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).", \
|
||||
(int)descr->cid, \
|
||||
(char *)descr->param_key, \
|
||||
(int)err, \
|
||||
(char *)esp_err_to_name(err)); \
|
||||
} \
|
||||
(err); \
|
||||
} \
|
||||
))
|
||||
|
||||
// User operation function to read slave values and check alarm
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -5,4 +5,4 @@ CONFIG_MB_UART_BAUD_RATE=115200
|
||||
CONFIG_FMB_TIMER_USE_ISR_DISPATCH_METHOD=y
|
||||
CONFIG_FMB_EXT_TYPE_SUPPORT=y
|
||||
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
|
||||
CONFIG_HEAP_TRACING_OFF=y
|
||||
CONFIG_HEAP_TRACING_OFF=y
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
@@ -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,54 +399,54 @@ static void *master_get_param_data(const mb_parameter_descriptor_t *param_descri
|
||||
return instance_ptr;
|
||||
}
|
||||
|
||||
#define TEST_VERIFY_VALUES(handle, pdescr, pinst) (__extension__( \
|
||||
{ \
|
||||
assert(pinst); \
|
||||
assert(pdescr); \
|
||||
uint8_t type = 0; \
|
||||
esp_err_t err = ESP_FAIL; \
|
||||
err = mbc_master_get_parameter(handle, pdescr->cid, (uint8_t *)pinst, &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; \
|
||||
ESP_LOGD(TAG, "Characteristic #%d (%s), initialize to 0x%" PRIx16 ".", \
|
||||
(int)pdescr->cid, \
|
||||
(char *)pdescr->param_key, \
|
||||
(uint16_t)pdescr->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); \
|
||||
if (err != ESP_OK) { \
|
||||
ESP_LOGE(TAG, "Characteristic #%d (%s) write fail, err = 0x%x (%s).", \
|
||||
(int)pdescr->cid, \
|
||||
(char *)pdescr->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); \
|
||||
} \
|
||||
} \
|
||||
} else { \
|
||||
ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).", \
|
||||
(int)pdescr->cid, \
|
||||
(char *)pdescr->param_key, \
|
||||
(int)err, \
|
||||
(char *)esp_err_to_name(err)); \
|
||||
} \
|
||||
(err); \
|
||||
} \
|
||||
#define TEST_VERIFY_VALUES(handle, descr, inst) (__extension__( \
|
||||
{ \
|
||||
assert(inst); \
|
||||
assert(descr); \
|
||||
uint8_t type = 0; \
|
||||
esp_err_t err = ESP_FAIL; \
|
||||
err = mbc_master_get_parameter(handle, descr->cid, (uint8_t *)inst, &type); \
|
||||
if (err == ESP_OK) { \
|
||||
bool is_correct = true; \
|
||||
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)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)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)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)descr->cid, \
|
||||
(char *)descr->param_key, \
|
||||
(char *)descr->param_units); \
|
||||
} \
|
||||
} \
|
||||
} else { \
|
||||
ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).", \
|
||||
(int)descr->cid, \
|
||||
(char *)descr->param_key, \
|
||||
(int)err, \
|
||||
(char *)esp_err_to_name(err)); \
|
||||
} \
|
||||
(err); \
|
||||
} \
|
||||
))
|
||||
|
||||
// User operation function to read slave values and check alarm
|
||||
@@ -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);
|
||||
|
||||
@@ -34,3 +34,4 @@ CONFIG_ETH_USE_SPI_ETHERNET=n
|
||||
|
||||
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
|
||||
CONFIG_HEAP_TRACING_OFF=y
|
||||
|
||||
|
||||
@@ -21,3 +21,4 @@ CONFIG_EXAMPLE_WIFI_PASSWORD="${CI_WIFI_PASSW}"
|
||||
|
||||
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
|
||||
CONFIG_HEAP_TRACING_OFF=y
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -33,3 +33,4 @@ CONFIG_ETH_USE_SPI_ETHERNET=n
|
||||
|
||||
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
|
||||
CONFIG_HEAP_TRACING_OFF=y
|
||||
|
||||
|
||||
@@ -20,3 +20,4 @@ CONFIG_EXAMPLE_WIFI_PASSWORD="${CI_WIFI_PASSW}"
|
||||
|
||||
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
|
||||
CONFIG_HEAP_TRACING_OFF=y
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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, ®_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, ®_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, ®_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, ®_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,
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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, ®_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, ®_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, ®_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, ®_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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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__( \
|
||||
{ \
|
||||
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])); \
|
||||
} \
|
||||
#define MB_PRT_BUF(pref, message, buffer, length, level) (__extension__( \
|
||||
{ \
|
||||
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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 ),
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)",
|
||||
@@ -686,4 +689,4 @@ mb_err_enum_t mbm_poll(mb_base_t *inst)
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -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);
|
||||
@@ -505,4 +509,4 @@ mb_err_enum_t mbs_poll(mb_base_t *inst)
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* (MB_SLAVE_ASCII_ENABLED || MB_SLAVE_RTU_ENABLED || MB_TCP_ENABLED) */
|
||||
#endif /* (MB_SLAVE_ASCII_ENABLED || MB_SLAVE_RTU_ENABLED || MB_TCP_ENABLED) */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -117,7 +117,7 @@ typedef struct
|
||||
|
||||
//((mb_port_base_t *)(((mb_common_iface_t *)pctx)->mb_base)->lock);
|
||||
|
||||
#define MB_OBJ_GET_LOCK(pctx) (__extension__( \
|
||||
#define MB_OBJ_GET_LOCK(pctx) (__extension__( \
|
||||
{ \
|
||||
assert((pctx)); \
|
||||
mb_common_iface_t *iface = (mb_common_iface_t *)pctx; \
|
||||
@@ -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
|
||||
|
||||
@@ -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 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 {
|
||||
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();
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#define MB_QUEUE_LENGTH (20)
|
||||
#define MB_SERIAL_TOUT (3)
|
||||
#define MB_SERIAL_TX_TOUT_TICKS (pdMS_TO_TICKS(400))
|
||||
#define MB_SERIAL_TASK_STACK_SIZE (CONFIG_FMB_PORT_TASK_STACK_SIZE)
|
||||
#define MB_SERIAL_TASK_STACK_SIZE (CONFIG_FMB_PORT_TASK_STACK_SIZE)
|
||||
#define MB_SERIAL_RX_TOUT_TICKS (pdMS_TO_TICKS(100))
|
||||
|
||||
#define MB_SERIAL_MIN_PATTERN_INTERVAL (9)
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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_LOGD(TAG, "Enqueue data, length=%d, TID=0x%" PRIx16, frame_info.len, frame_info.tid);
|
||||
return (int)frame_info.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;
|
||||
}
|
||||
}
|
||||
// Other error occurred during receiving
|
||||
ESP_LOGD(TAG, "Socket(#%d)(%s) receive error, ret = %d, errno = %d(%s)",
|
||||
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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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++];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
@@ -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:
|
||||
free((void *)transp->pascii_puf);
|
||||
transp->pascii_puf = NULL;
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
free(transp->pascii_puf);
|
||||
transp->pascii_puf = NULL;
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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->timer_obj) {
|
||||
mb_port_timer_delete(port_obj);
|
||||
}
|
||||
if (port_obj->event_obj) {
|
||||
mb_port_event_delete(port_obj);
|
||||
}
|
||||
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);
|
||||
}
|
||||
mb_port_ser_delete(port_obj);
|
||||
}
|
||||
CRITICAL_SECTION_CLOSE(transp->base.lock);
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
if (transp) {
|
||||
CRITICAL_SECTION_UNLOCK(transp->base.lock);
|
||||
CRITICAL_SECTION_CLOSE(transp->base.lock);
|
||||
}
|
||||
free(port_obj);
|
||||
CRITICAL_SECTION_CLOSE(transp->base.lock);
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -1,2 +1,12 @@
|
||||
set(PROJECT_NAME "mb_serial_cpp")
|
||||
|
||||
idf_component_register(SRCS "serial_test.cpp"
|
||||
INCLUDE_DIRS ".")
|
||||
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()
|
||||
|
||||
|
||||
@@ -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 *)®s[0], &type);
|
||||
err = mbc_master_get_parameter(*inst, descriptor->cid, (uint8_t *)®s[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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# General options for test
|
||||
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
|
||||
CONFIG_HEAP_TRACING_OFF=y
|
||||
|
||||
|
||||
@@ -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()
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
@@ -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));
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
@@ -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, ¶m_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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
// }
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)'
|
||||
|
||||
|
||||
Executable
+46
@@ -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
|
||||
Reference in New Issue
Block a user