mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-10-31 04:59:55 +00:00 
			
		
		
		
	freemodbus: allow address gaps in master data dictionary (support of UID field in MBAP) (backport v4.3)
This commit is contained in:
		 Alex Lisitsyn
					Alex Lisitsyn
				
			
				
					committed by
					
						 Jiang Jiang Jian
						Jiang Jiang Jian
					
				
			
			
				
	
			
			
			 Jiang Jiang Jian
						Jiang Jiang Jian
					
				
			
						parent
						
							5bad27d0d5
						
					
				
				
					commit
					073da59d27
				
			| @@ -18,6 +18,8 @@ | |||||||
| #include "esp_modbus_master.h"  // for public interface defines | #include "esp_modbus_master.h"  // for public interface defines | ||||||
| #include "esp_modbus_callbacks.h"   // for callback functions | #include "esp_modbus_callbacks.h"   // for callback functions | ||||||
|  |  | ||||||
|  | static const char TAG[] __attribute__((unused)) = "MB_CONTROLLER_MASTER"; | ||||||
|  |  | ||||||
| // This file implements public API for Modbus master controller. | // This file implements public API for Modbus master controller. | ||||||
| // These functions are wrappers for interface functions of the controller | // These functions are wrappers for interface functions of the controller | ||||||
| static mb_master_interface_t* master_interface_ptr = NULL; | static mb_master_interface_t* master_interface_ptr = NULL; | ||||||
|   | |||||||
| @@ -43,6 +43,7 @@ static uint8_t mb_slave_id[] = { MB_ID_BYTE0(MB_CONTROLLER_SLAVE_ID), | |||||||
|  |  | ||||||
| // Common interface pointer for slave port | // Common interface pointer for slave port | ||||||
| static mb_slave_interface_t* slave_interface_ptr = NULL; | static mb_slave_interface_t* slave_interface_ptr = NULL; | ||||||
|  | static const char TAG[] __attribute__((unused)) = "MB_CONTROLLER_SLAVE"; | ||||||
|  |  | ||||||
| // Searches the register in the area specified by type, returns descriptor if found, else NULL | // Searches the register in the area specified by type, returns descriptor if found, else NULL | ||||||
| static mb_descr_entry_t* mbc_slave_find_reg_descriptor(mb_param_type_t type, uint16_t addr, size_t regs) | static mb_descr_entry_t* mbc_slave_find_reg_descriptor(mb_param_type_t type, uint16_t addr, size_t regs) | ||||||
| @@ -259,11 +260,11 @@ static esp_err_t mbc_slave_send_param_info(mb_event_group_t par_type, uint16_t m | |||||||
|     par_info.mb_offset = mb_offset; |     par_info.mb_offset = mb_offset; | ||||||
|     BaseType_t status = xQueueSend(mbs_opts->mbs_notification_queue_handle, &par_info, MB_PAR_INFO_TOUT); |     BaseType_t status = xQueueSend(mbs_opts->mbs_notification_queue_handle, &par_info, MB_PAR_INFO_TOUT); | ||||||
|     if (pdTRUE == status) { |     if (pdTRUE == status) { | ||||||
|         ESP_LOGD(MB_SLAVE_TAG, "Queue send parameter info (type, address, size): %d, 0x%.4x, %d", |         ESP_LOGD(TAG, "Queue send parameter info (type, address, size): %d, 0x%.4x, %d", | ||||||
|                 par_type, (uint32_t)par_address, par_size); |                 par_type, (uint32_t)par_address, par_size); | ||||||
|         error = ESP_OK; |         error = ESP_OK; | ||||||
|     } else if (errQUEUE_FULL == status) { |     } else if (errQUEUE_FULL == status) { | ||||||
|         ESP_LOGD(MB_SLAVE_TAG, "Parameter queue is overflowed."); |         ESP_LOGD(TAG, "Parameter queue is overflowed."); | ||||||
|     } |     } | ||||||
|     return error; |     return error; | ||||||
| } | } | ||||||
| @@ -276,7 +277,7 @@ static esp_err_t mbc_slave_send_param_access_notification(mb_event_group_t event | |||||||
|     esp_err_t err = ESP_FAIL; |     esp_err_t err = ESP_FAIL; | ||||||
|     mb_event_group_t bits = (mb_event_group_t)xEventGroupSetBits(mbs_opts->mbs_event_group, (EventBits_t)event); |     mb_event_group_t bits = (mb_event_group_t)xEventGroupSetBits(mbs_opts->mbs_event_group, (EventBits_t)event); | ||||||
|     if (bits & event) { |     if (bits & event) { | ||||||
|         ESP_LOGD(MB_SLAVE_TAG, "The MB_REG_CHANGE_EVENT = 0x%.2x is set.", (uint8_t)event); |         ESP_LOGD(TAG, "The MB_REG_CHANGE_EVENT = 0x%.2x is set.", (uint8_t)event); | ||||||
|         err = ESP_OK; |         err = ESP_OK; | ||||||
|     } |     } | ||||||
|     return err; |     return err; | ||||||
|   | |||||||
| @@ -22,6 +22,24 @@ | |||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #if __has_include("esp_check.h") | ||||||
|  | #include "esp_check.h" | ||||||
|  |  | ||||||
|  | #define MB_RETURN_ON_FALSE(a, err_code, tag, format, ...) ESP_RETURN_ON_FALSE(a, err_code, tag, format __VA_OPT__(,) __VA_ARGS__) | ||||||
|  |  | ||||||
|  | #else | ||||||
|  |  | ||||||
|  | // if cannot include esp_check then use custom check macro | ||||||
|  |  | ||||||
|  | #define MB_RETURN_ON_FALSE(a, err_code, tag, format, ...) do {                                         \ | ||||||
|  |         if (!(a)) {                                                                              \ | ||||||
|  |             ESP_LOGE(tag, "%s(%d): " format, __FUNCTION__, __LINE__ __VA_OPT__(,) __VA_ARGS__);        \ | ||||||
|  |             return err_code;                                                                               \ | ||||||
|  |         }                                                                                                  \ | ||||||
|  | } while(0) | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #define MB_CONTROLLER_STACK_SIZE            (CONFIG_FMB_CONTROLLER_STACK_SIZE)   // Stack size for Modbus controller | #define MB_CONTROLLER_STACK_SIZE            (CONFIG_FMB_CONTROLLER_STACK_SIZE)   // Stack size for Modbus controller | ||||||
| #define MB_CONTROLLER_PRIORITY              (CONFIG_FMB_PORT_TASK_PRIO - 1)    // priority of MB controller task | #define MB_CONTROLLER_PRIORITY              (CONFIG_FMB_PORT_TASK_PRIO - 1)    // priority of MB controller task | ||||||
|  |  | ||||||
|   | |||||||
| @@ -25,6 +25,12 @@ | |||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #define MB_MASTER_CHECK(a, err_code, format, ...) MB_RETURN_ON_FALSE(a, err_code, TAG, format __VA_OPT__(,) __VA_ARGS__) | ||||||
|  |  | ||||||
|  | #define MB_MASTER_ASSERT(con) do { \ | ||||||
|  |         if (!(con)) { ESP_LOGE(TAG, "assert errno:%d, errno_str: !(%s)", errno, strerror(errno)); assert(0 && #con); } \ | ||||||
|  |     } while (0) | ||||||
|  |  | ||||||
| /*! | /*! | ||||||
|  * \brief Modbus descriptor table parameter type defines. |  * \brief Modbus descriptor table parameter type defines. | ||||||
|  */ |  */ | ||||||
|   | |||||||
| @@ -28,6 +28,12 @@ | |||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #define MB_SLAVE_CHECK(a, err_code, format, ...) MB_RETURN_ON_FALSE(a, err_code, TAG, format __VA_OPT__(,) __VA_ARGS__) | ||||||
|  |  | ||||||
|  | #define MB_SLAVE_ASSERT(con) do { \ | ||||||
|  |         if (!(con)) { ESP_LOGE(TAG, "assert errno:%d, errno_str: !(%s)", errno, strerror(errno)); assert(0 && #con); } \ | ||||||
|  |     } while (0) | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @brief Parameter access event information type |  * @brief Parameter access event information type | ||||||
|  */ |  */ | ||||||
|   | |||||||
| @@ -12,9 +12,11 @@ | |||||||
|  * See the License for the specific language governing permissions and |  * See the License for the specific language governing permissions and | ||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifndef _MB_CONTROLLER_MASTER_H | #ifndef _MB_CONTROLLER_MASTER_H | ||||||
| #define _MB_CONTROLLER_MASTER_H | #define _MB_CONTROLLER_MASTER_H | ||||||
|  |  | ||||||
|  | #include <sys/queue.h>              // for list | ||||||
| #include "freertos/FreeRTOS.h"      // for task creation and queue access | #include "freertos/FreeRTOS.h"      // for task creation and queue access | ||||||
| #include "freertos/task.h"          // for task api access | #include "freertos/task.h"          // for task api access | ||||||
| #include "freertos/event_groups.h"  // for event groups | #include "freertos/event_groups.h"  // for event groups | ||||||
| @@ -28,18 +30,6 @@ | |||||||
|  |  | ||||||
| /* ----------------------- Defines ------------------------------------------*/ | /* ----------------------- Defines ------------------------------------------*/ | ||||||
|  |  | ||||||
| #define MB_MASTER_TAG "MB_CONTROLLER_MASTER" |  | ||||||
|  |  | ||||||
| #define MB_MASTER_CHECK(a, ret_val, str, ...) \ |  | ||||||
|     if (!(a)) { \ |  | ||||||
|         ESP_LOGE(MB_MASTER_TAG, "%s(%u): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ |  | ||||||
|         return (ret_val); \ |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| #define MB_MASTER_ASSERT(con) do { \ |  | ||||||
|         if (!(con)) { ESP_LOGE(MB_MASTER_TAG, "assert errno:%d, errno_str: !(%s)", errno, strerror(errno)); assert(0 && #con); } \ |  | ||||||
|     } while (0) |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @brief Request mode for parameter to use in data dictionary |  * @brief Request mode for parameter to use in data dictionary | ||||||
|  */ |  */ | ||||||
| @@ -59,6 +49,19 @@ typedef struct { | |||||||
|     uart_parity_t parity;                   /*!< Modbus UART parity settings */ |     uart_parity_t parity;                   /*!< Modbus UART parity settings */ | ||||||
| } mb_master_comm_info_t; | } mb_master_comm_info_t; | ||||||
|  |  | ||||||
|  | #if MB_MASTER_TCP_ENABLED | ||||||
|  | /** | ||||||
|  |  * @brief Modbus slave addr list item for the master | ||||||
|  |  */ | ||||||
|  | typedef struct mb_slave_addr_entry_s{ | ||||||
|  |     uint16_t index;                             /*!< Index of the slave address */ | ||||||
|  |     const char* ip_address;                     /*!< IP address string of the slave */ | ||||||
|  |     uint8_t slave_addr;                         /*!< Short slave address */ | ||||||
|  |     void* p_data;                               /*!< pointer to data structure */ | ||||||
|  |     LIST_ENTRY(mb_slave_addr_entry_s) entries;  /*!< The slave address entry */ | ||||||
|  | } mb_slave_addr_entry_t; | ||||||
|  | #endif | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @brief Modbus controller handler structure |  * @brief Modbus controller handler structure | ||||||
|  */ |  */ | ||||||
| @@ -71,6 +74,10 @@ typedef struct { | |||||||
|     EventGroupHandle_t mbm_event_group;                 /*!< Modbus controller event group */ |     EventGroupHandle_t mbm_event_group;                 /*!< Modbus controller event group */ | ||||||
|     const mb_parameter_descriptor_t* mbm_param_descriptor_table; /*!< Modbus controller parameter description table */ |     const mb_parameter_descriptor_t* mbm_param_descriptor_table; /*!< Modbus controller parameter description table */ | ||||||
|     size_t mbm_param_descriptor_size;                   /*!< Modbus controller parameter description table size*/ |     size_t mbm_param_descriptor_size;                   /*!< Modbus controller parameter description table size*/ | ||||||
|  | #if MB_MASTER_TCP_ENABLED | ||||||
|  |     LIST_HEAD(mbm_slave_addr_info_, mb_slave_addr_entry_s) mbm_slave_list; /*!< Slave address information list */ | ||||||
|  |     uint16_t mbm_slave_list_count; | ||||||
|  | #endif | ||||||
| } mb_master_options_t; | } mb_master_options_t; | ||||||
|  |  | ||||||
| typedef esp_err_t (*iface_get_cid_info)(uint16_t, const mb_parameter_descriptor_t**); /*!< Interface get_cid_info method */ | typedef esp_err_t (*iface_get_cid_info)(uint16_t, const mb_parameter_descriptor_t**); /*!< Interface get_cid_info method */ | ||||||
|   | |||||||
| @@ -31,18 +31,6 @@ | |||||||
| #define MB_CONTROLLER_NOTIFY_QUEUE_SIZE     (CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE) // Number of messages in parameter notification queue | #define MB_CONTROLLER_NOTIFY_QUEUE_SIZE     (CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE) // Number of messages in parameter notification queue | ||||||
| #define MB_CONTROLLER_NOTIFY_TIMEOUT        (pdMS_TO_TICKS(CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT)) // notification timeout | #define MB_CONTROLLER_NOTIFY_TIMEOUT        (pdMS_TO_TICKS(CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT)) // notification timeout | ||||||
|  |  | ||||||
| #define MB_SLAVE_TAG "MB_CONTROLLER_SLAVE" |  | ||||||
|  |  | ||||||
| #define MB_SLAVE_CHECK(a, ret_val, str, ...) \ |  | ||||||
|     if (!(a)) { \ |  | ||||||
|         ESP_LOGE(MB_SLAVE_TAG, "%s(%u): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ |  | ||||||
|         return (ret_val); \ |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| #define MB_SLAVE_ASSERT(con) do { \ |  | ||||||
|         if (!(con)) { ESP_LOGE(MB_SLAVE_TAG, "assert errno:%d, errno_str: !(%s)", errno, strerror(errno)); assert(0 && #con); } \ |  | ||||||
|     } while (0) |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @brief Device communication parameters for master |  * @brief Device communication parameters for master | ||||||
|  */ |  */ | ||||||
|   | |||||||
| @@ -40,6 +40,7 @@ extern BOOL xMBMasterPortSerialTxPoll(void); | |||||||
|  |  | ||||||
|  |  | ||||||
| static mb_master_interface_t* mbm_interface_ptr = NULL; //&default_interface_inst; | static mb_master_interface_t* mbm_interface_ptr = NULL; //&default_interface_inst; | ||||||
|  | static const char *TAG = "MB_CONTROLLER_MASTER"; | ||||||
|  |  | ||||||
| // Modbus event processing task | // Modbus event processing task | ||||||
| static void modbus_master_task(void *pvParameters) | static void modbus_master_task(void *pvParameters) | ||||||
| @@ -238,7 +239,7 @@ static esp_err_t mbc_serial_master_send_request(mb_param_request_t* request, voi | |||||||
|                                                         (USHORT)mb_size, (LONG) MB_RESPONSE_TICS ); |                                                         (USHORT)mb_size, (LONG) MB_RESPONSE_TICS ); | ||||||
|             break; |             break; | ||||||
|         default: |         default: | ||||||
|             ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect function in request (%u) ", |             ESP_LOGE(TAG, "%s: Incorrect function in request (%u) ", | ||||||
|                                                     __FUNCTION__, mb_command); |                                                     __FUNCTION__, mb_command); | ||||||
|             mb_error = MB_MRE_NO_REG; |             mb_error = MB_MRE_NO_REG; | ||||||
|             break; |             break; | ||||||
| @@ -269,7 +270,7 @@ static esp_err_t mbc_serial_master_send_request(mb_param_request_t* request, voi | |||||||
|             break; |             break; | ||||||
|  |  | ||||||
|         default: |         default: | ||||||
|             ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect return code (%x) ", |             ESP_LOGE(TAG, "%s: Incorrect return code (%x) ", | ||||||
|                                                                 __FUNCTION__, mb_error); |                                                                 __FUNCTION__, mb_error); | ||||||
|             error = ESP_FAIL; |             error = ESP_FAIL; | ||||||
|             break; |             break; | ||||||
| @@ -324,12 +325,12 @@ static uint8_t mbc_serial_master_get_command(mb_param_type_t param_type, mb_para | |||||||
|             if (mode != MB_PARAM_WRITE) { |             if (mode != MB_PARAM_WRITE) { | ||||||
|                 command = MB_FUNC_READ_DISCRETE_INPUTS; |                 command = MB_FUNC_READ_DISCRETE_INPUTS; | ||||||
|             } else { |             } else { | ||||||
|                 ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect mode (%u)", |                 ESP_LOGE(TAG, "%s: Incorrect mode (%u)", | ||||||
|                             __FUNCTION__, (uint8_t)mode); |                             __FUNCTION__, (uint8_t)mode); | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         default: |         default: | ||||||
|             ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect param type (%u)", |             ESP_LOGE(TAG, "%s: Incorrect param type (%u)", | ||||||
|                             __FUNCTION__, param_type); |                             __FUNCTION__, param_type); | ||||||
|             break; |             break; | ||||||
|     } |     } | ||||||
| @@ -401,16 +402,16 @@ static esp_err_t mbc_serial_master_get_parameter(uint16_t cid, char* name, | |||||||
|         // Send request to read characteristic data |         // Send request to read characteristic data | ||||||
|         error = mbc_serial_master_send_request(&request, value_ptr); |         error = mbc_serial_master_send_request(&request, value_ptr); | ||||||
|         if (error == ESP_OK) { |         if (error == ESP_OK) { | ||||||
|             ESP_LOGD(MB_MASTER_TAG, "%s: Good response for get cid(%u) = %s", |             ESP_LOGD(TAG, "%s: Good response for get cid(%u) = %s", | ||||||
|                                     __FUNCTION__, (int)reg_info.cid, (char*)esp_err_to_name(error)); |                                     __FUNCTION__, (int)reg_info.cid, (char*)esp_err_to_name(error)); | ||||||
|         } else { |         } else { | ||||||
|             ESP_LOGD(MB_MASTER_TAG, "%s: Bad response to get cid(%u) = %s", |             ESP_LOGD(TAG, "%s: Bad response to get cid(%u) = %s", | ||||||
|                                             __FUNCTION__, reg_info.cid, (char*)esp_err_to_name(error)); |                                             __FUNCTION__, reg_info.cid, (char*)esp_err_to_name(error)); | ||||||
|         } |         } | ||||||
|         // Set the type of parameter found in the table |         // Set the type of parameter found in the table | ||||||
|         *type = reg_info.param_type; |         *type = reg_info.param_type; | ||||||
|     } else { |     } else { | ||||||
|         ESP_LOGE(MB_MASTER_TAG, "%s: The cid(%u) not found in the data dictionary.", |         ESP_LOGE(TAG, "%s: The cid(%u) not found in the data dictionary.", | ||||||
|                                                     __FUNCTION__, reg_info.cid); |                                                     __FUNCTION__, reg_info.cid); | ||||||
|         error = ESP_ERR_INVALID_ARG; |         error = ESP_ERR_INVALID_ARG; | ||||||
|     } |     } | ||||||
| @@ -436,16 +437,16 @@ static esp_err_t mbc_serial_master_set_parameter(uint16_t cid, char* name, | |||||||
|         // Send request to write characteristic data |         // Send request to write characteristic data | ||||||
|         error = mbc_serial_master_send_request(&request, value_ptr); |         error = mbc_serial_master_send_request(&request, value_ptr); | ||||||
|         if (error == ESP_OK) { |         if (error == ESP_OK) { | ||||||
|             ESP_LOGD(MB_MASTER_TAG, "%s: Good response for set cid(%u) = %s", |             ESP_LOGD(TAG, "%s: Good response for set cid(%u) = %s", | ||||||
|                                     __FUNCTION__, (int)reg_info.cid, (char*)esp_err_to_name(error)); |                                     __FUNCTION__, (int)reg_info.cid, (char*)esp_err_to_name(error)); | ||||||
|         } else { |         } else { | ||||||
|             ESP_LOGD(MB_MASTER_TAG, "%s: Bad response to set cid(%u) = %s", |             ESP_LOGD(TAG, "%s: Bad response to set cid(%u) = %s", | ||||||
|                                     __FUNCTION__, reg_info.cid, (char*)esp_err_to_name(error)); |                                     __FUNCTION__, reg_info.cid, (char*)esp_err_to_name(error)); | ||||||
|         } |         } | ||||||
|         // Set the type of parameter found in the table |         // Set the type of parameter found in the table | ||||||
|         *type = reg_info.param_type; |         *type = reg_info.param_type; | ||||||
|     } else { |     } else { | ||||||
|         ESP_LOGE(MB_MASTER_TAG, "%s: The requested cid(%u) not found in the data dictionary.", |         ESP_LOGE(TAG, "%s: The requested cid(%u) not found in the data dictionary.", | ||||||
|                                     __FUNCTION__, reg_info.cid); |                                     __FUNCTION__, reg_info.cid); | ||||||
|         error = ESP_ERR_INVALID_ARG; |         error = ESP_ERR_INVALID_ARG; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -29,6 +29,7 @@ | |||||||
|  |  | ||||||
| // Shared pointer to interface structure | // Shared pointer to interface structure | ||||||
| static mb_slave_interface_t* mbs_interface_ptr = NULL; | static mb_slave_interface_t* mbs_interface_ptr = NULL; | ||||||
|  | static const char *TAG = "MB_CONTROLLER_SLAVE"; | ||||||
|  |  | ||||||
| // Modbus task function | // Modbus task function | ||||||
| static void modbus_slave_task(void *pvParameters) | static void modbus_slave_task(void *pvParameters) | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ | |||||||
| #include <sys/time.h>               // for calculation of time stamp in milliseconds | #include <sys/time.h>               // for calculation of time stamp in milliseconds | ||||||
| #include "esp_log.h"                // for log_write | #include "esp_log.h"                // for log_write | ||||||
| #include <string.h>                 // for memcpy | #include <string.h>                 // for memcpy | ||||||
|  | #include <sys/queue.h>              // for list | ||||||
| #include "freertos/FreeRTOS.h"      // for task creation and queue access | #include "freertos/FreeRTOS.h"      // for task creation and queue access | ||||||
| #include "freertos/task.h"          // for task api access | #include "freertos/task.h"          // for task api access | ||||||
| #include "freertos/event_groups.h"  // for event groups | #include "freertos/event_groups.h"  // for event groups | ||||||
| @@ -42,6 +43,59 @@ | |||||||
| #define MB_TCP_CONNECTION_TOUT pdMS_TO_TICKS(CONFIG_FMB_TCP_CONNECTION_TOUT_SEC * 1000) | #define MB_TCP_CONNECTION_TOUT pdMS_TO_TICKS(CONFIG_FMB_TCP_CONNECTION_TOUT_SEC * 1000) | ||||||
|  |  | ||||||
| static mb_master_interface_t* mbm_interface_ptr = NULL; | static mb_master_interface_t* mbm_interface_ptr = NULL; | ||||||
|  | static const char *TAG = "MB_CONTROLLER_MASTER"; | ||||||
|  |  | ||||||
|  | // Searches the slave address in the address info list and returns address info if found, else NULL | ||||||
|  | static mb_slave_addr_entry_t* mbc_tcp_master_find_slave_addr(uint8_t slave_addr) | ||||||
|  | { | ||||||
|  |     mb_slave_addr_entry_t* it; | ||||||
|  |     mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts; | ||||||
|  |  | ||||||
|  |     if (LIST_EMPTY(&mbm_opts->mbm_slave_list)) { | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  |     LIST_FOREACH(it, &mbm_opts->mbm_slave_list, entries) { | ||||||
|  |         if (slave_addr == it->slave_addr) { | ||||||
|  |             return it; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static esp_err_t mbc_tcp_master_add_slave(uint16_t index, uint8_t slave_addr, const char* ip_addr) | ||||||
|  | { | ||||||
|  |     MB_MASTER_ASSERT(mbm_interface_ptr != NULL); | ||||||
|  |     // Initialize interface properties | ||||||
|  |     mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts; | ||||||
|  |  | ||||||
|  |     mb_slave_addr_entry_t* new_slave_entry = (mb_slave_addr_entry_t*) heap_caps_malloc(sizeof(mb_slave_addr_entry_t), | ||||||
|  |                                                MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); | ||||||
|  |     MB_MASTER_CHECK((new_slave_entry != NULL), ESP_ERR_NO_MEM, "mb can not allocate memory for slave entry."); | ||||||
|  |     new_slave_entry->index = index; | ||||||
|  |     new_slave_entry->ip_address = ip_addr; | ||||||
|  |     new_slave_entry->slave_addr = slave_addr; | ||||||
|  |     new_slave_entry->p_data = NULL; | ||||||
|  |     LIST_INSERT_HEAD(&mbm_opts->mbm_slave_list, new_slave_entry, entries); | ||||||
|  |     MB_MASTER_CHECK((mbm_opts->mbm_slave_list_count < (MB_TCP_PORT_MAX_CONN - 1)), | ||||||
|  |                         ESP_ERR_INVALID_STATE, "mb max number of slaves < %d.", MB_TCP_PORT_MAX_CONN); | ||||||
|  |     mbm_opts->mbm_slave_list_count++; | ||||||
|  |     return ESP_OK; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void mbc_tcp_master_free_slave_list(void) | ||||||
|  | { | ||||||
|  |     mb_slave_addr_entry_t* it; | ||||||
|  |     MB_MASTER_ASSERT(mbm_interface_ptr != NULL); | ||||||
|  |  | ||||||
|  |     // Initialize interface properties | ||||||
|  |     mb_master_options_t* mbm_opts = &mbm_interface_ptr->opts; | ||||||
|  |  | ||||||
|  |     LIST_FOREACH(it, &mbm_opts->mbm_slave_list, entries) { | ||||||
|  |         LIST_REMOVE(it, entries); | ||||||
|  |         mbm_opts->mbm_slave_list_count--; | ||||||
|  |         free(it); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| // Modbus event processing task | // Modbus event processing task | ||||||
| static void modbus_tcp_master_task(void *pvParameters) | static void modbus_tcp_master_task(void *pvParameters) | ||||||
| @@ -113,21 +167,21 @@ static esp_err_t mbc_tcp_master_start(void) | |||||||
|     vMBTCPPortMasterSetNetOpt(comm_info->ip_netif_ptr, ip_ver, proto); |     vMBTCPPortMasterSetNetOpt(comm_info->ip_netif_ptr, ip_ver, proto); | ||||||
|     vMBTCPPortMasterTaskStart(); |     vMBTCPPortMasterTaskStart(); | ||||||
|  |  | ||||||
|     // Add slave IP address for each slave to initialise connection |     // Add slave IP address for each slave to initialize connection | ||||||
|     for (int idx = 0; *comm_ip_table != NULL; idx++, comm_ip_table++) |     mb_slave_addr_entry_t *p_slave_info; | ||||||
|     { |  | ||||||
|         result = (BOOL)xMBTCPPortMasterAddSlaveIp(*comm_ip_table); |     LIST_FOREACH(p_slave_info, &mbm_opts->mbm_slave_list, entries) { | ||||||
|  |         result = (BOOL)xMBTCPPortMasterAddSlaveIp(p_slave_info->index, p_slave_info->ip_address, p_slave_info->slave_addr); | ||||||
|         MB_MASTER_CHECK(result, ESP_ERR_INVALID_STATE, "mb stack add slave IP failed: %s.", *comm_ip_table); |         MB_MASTER_CHECK(result, ESP_ERR_INVALID_STATE, "mb stack add slave IP failed: %s.", *comm_ip_table); | ||||||
|     } |     } | ||||||
|     // Init polling event handlers and wait before start polling |  | ||||||
|     xMBTCPPortMasterWaitEvent(mbm_opts->mbm_event_group, (EventBits_t)MB_EVENT_STACK_STARTED, 1); |     // Add end of list condition | ||||||
|  |     (void)xMBTCPPortMasterAddSlaveIp(0xFF, NULL, 0xFF); | ||||||
|  |  | ||||||
|     status = eMBMasterEnable(); |     status = eMBMasterEnable(); | ||||||
|     MB_MASTER_CHECK((status == MB_ENOERR), ESP_ERR_INVALID_STATE, |     MB_MASTER_CHECK((status == MB_ENOERR), ESP_ERR_INVALID_STATE, | ||||||
|             "mb stack set slave ID failure, eMBMasterEnable() returned (0x%x).", (uint32_t)status); |             "mb stack set slave ID failure, eMBMasterEnable() returned (0x%x).", (uint32_t)status); | ||||||
|  |  | ||||||
|     // Send end of list condition to start connection phase |  | ||||||
|     (void)xMBTCPPortMasterAddSlaveIp(NULL); |  | ||||||
|  |  | ||||||
|     // Wait for connection done event |     // Wait for connection done event | ||||||
|     bool start = (bool)xMBTCPPortMasterWaitEvent(mbm_opts->mbm_event_group, |     bool start = (bool)xMBTCPPortMasterWaitEvent(mbm_opts->mbm_event_group, | ||||||
| @@ -160,6 +214,7 @@ static esp_err_t mbc_tcp_master_destroy(void) | |||||||
|     mbm_opts->mbm_task_handle = NULL; |     mbm_opts->mbm_task_handle = NULL; | ||||||
|     (void)vEventGroupDelete(mbm_opts->mbm_event_group); |     (void)vEventGroupDelete(mbm_opts->mbm_event_group); | ||||||
|     mbm_opts->mbm_event_group = NULL; |     mbm_opts->mbm_event_group = NULL; | ||||||
|  |     mbc_tcp_master_free_slave_list(); | ||||||
|     free(mbm_interface_ptr); // free the memory allocated for options |     free(mbm_interface_ptr); // free the memory allocated for options | ||||||
|     vMBPortSetMode((UCHAR)MB_PORT_INACTIVE); |     vMBPortSetMode((UCHAR)MB_PORT_INACTIVE); | ||||||
|     mbm_interface_ptr = NULL; |     mbm_interface_ptr = NULL; | ||||||
| @@ -179,14 +234,25 @@ static esp_err_t mbc_tcp_master_set_descriptor(const mb_parameter_descriptor_t* | |||||||
|     MB_MASTER_CHECK((comm_ip_table != NULL), ESP_ERR_INVALID_ARG, "mb ip table address is incorrect."); |     MB_MASTER_CHECK((comm_ip_table != NULL), ESP_ERR_INVALID_ARG, "mb ip table address is incorrect."); | ||||||
|  |  | ||||||
|     const mb_parameter_descriptor_t *reg_ptr = descriptor; |     const mb_parameter_descriptor_t *reg_ptr = descriptor; | ||||||
|  |     uint16_t slave_cnt = 0; | ||||||
|  |     mb_slave_addr_entry_t* p_slave = NULL; | ||||||
|  |  | ||||||
|     // Go through all items in the table to check all Modbus registers |     // Go through all items in the table to check all Modbus registers | ||||||
|     for (uint16_t counter = 0; counter < (num_elements); counter++, reg_ptr++) |     for (int idx = 0; idx < (num_elements); idx++, reg_ptr++) | ||||||
|     { |     { | ||||||
|         MB_MASTER_CHECK((comm_ip_table[reg_ptr->mb_slave_addr - 1] != NULL), ESP_ERR_INVALID_ARG, "mb ip table address is incorrect."); |  | ||||||
|         // Below is the code to check consistency of the table format and required fields. |         // Below is the code to check consistency of the table format and required fields. | ||||||
|         MB_MASTER_CHECK((reg_ptr->cid == counter), ESP_ERR_INVALID_ARG, "mb descriptor cid field is incorrect."); |         MB_MASTER_CHECK((reg_ptr->cid == idx), ESP_ERR_INVALID_ARG, "mb descriptor cid field is incorrect."); | ||||||
|         MB_MASTER_CHECK((reg_ptr->param_key != NULL), ESP_ERR_INVALID_ARG, "mb descriptor param key is incorrect."); |         MB_MASTER_CHECK((reg_ptr->param_key != NULL), ESP_ERR_INVALID_ARG, "mb descriptor param key is incorrect."); | ||||||
|         MB_MASTER_CHECK((reg_ptr->mb_size > 0), ESP_ERR_INVALID_ARG, "mb descriptor param size is incorrect."); |         MB_MASTER_CHECK((reg_ptr->mb_size > 0), ESP_ERR_INVALID_ARG, "mb descriptor param size is incorrect."); | ||||||
|  |         // Is the slave already in the list? | ||||||
|  |         p_slave = mbc_tcp_master_find_slave_addr(reg_ptr->mb_slave_addr); | ||||||
|  |         // Add it to slave list if not there. | ||||||
|  |         if (!p_slave) { | ||||||
|  |             // Is the IP address correctly defined for the slave? | ||||||
|  |             MB_MASTER_CHECK((comm_ip_table[slave_cnt]), ESP_ERR_INVALID_STATE, "mb missing IP address for cid #%d.", reg_ptr->cid); | ||||||
|  |             // Add slave to the list | ||||||
|  |             MB_MASTER_ASSERT(mbc_tcp_master_add_slave(idx, reg_ptr->mb_slave_addr, comm_ip_table[slave_cnt++]) == ESP_OK); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     mbm_opts->mbm_param_descriptor_table = descriptor; |     mbm_opts->mbm_param_descriptor_table = descriptor; | ||||||
|     mbm_opts->mbm_param_descriptor_size = num_elements; |     mbm_opts->mbm_param_descriptor_size = num_elements; | ||||||
| @@ -258,7 +324,7 @@ static esp_err_t mbc_tcp_master_send_request(mb_param_request_t* request, void* | |||||||
|                                                         (USHORT)mb_size, (LONG) MB_RESPONSE_TIMEOUT ); |                                                         (USHORT)mb_size, (LONG) MB_RESPONSE_TIMEOUT ); | ||||||
|             break; |             break; | ||||||
|         default: |         default: | ||||||
|             ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect function in request (%u) ", |             ESP_LOGE(TAG, "%s: Incorrect function in request (%u) ", | ||||||
|                                                     __FUNCTION__, mb_command); |                                                     __FUNCTION__, mb_command); | ||||||
|             mb_error = MB_MRE_NO_REG; |             mb_error = MB_MRE_NO_REG; | ||||||
|             break; |             break; | ||||||
| @@ -289,7 +355,7 @@ static esp_err_t mbc_tcp_master_send_request(mb_param_request_t* request, void* | |||||||
|             break; |             break; | ||||||
|  |  | ||||||
|         default: |         default: | ||||||
|             ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect return code (%x) ", __FUNCTION__, mb_error); |             ESP_LOGE(TAG, "%s: Incorrect return code (%x) ", __FUNCTION__, mb_error); | ||||||
|             error = ESP_FAIL; |             error = ESP_FAIL; | ||||||
|             break; |             break; | ||||||
|     } |     } | ||||||
| @@ -333,11 +399,11 @@ static uint8_t mbc_tcp_master_get_command(mb_param_type_t param_type, mb_param_m | |||||||
|             if (mode != MB_PARAM_WRITE) { |             if (mode != MB_PARAM_WRITE) { | ||||||
|                 command = MB_FUNC_READ_DISCRETE_INPUTS; |                 command = MB_FUNC_READ_DISCRETE_INPUTS; | ||||||
|             } else { |             } else { | ||||||
|                 ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect mode (%u)", __FUNCTION__, (uint8_t)mode); |                 ESP_LOGE(TAG, "%s: Incorrect mode (%u)", __FUNCTION__, (uint8_t)mode); | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         default: |         default: | ||||||
|             ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect param type (%u)", __FUNCTION__, param_type); |             ESP_LOGE(TAG, "%s: Incorrect param type (%u)", __FUNCTION__, param_type); | ||||||
|             break; |             break; | ||||||
|     } |     } | ||||||
|     return command; |     return command; | ||||||
| @@ -368,7 +434,7 @@ static esp_err_t mbc_tcp_master_set_param_data(void* dest, void* src, mb_descr_t | |||||||
|             memcpy((void*)dest, (void*)src, (size_t)param_size); |             memcpy((void*)dest, (void*)src, (size_t)param_size); | ||||||
|             break; |             break; | ||||||
|         default: |         default: | ||||||
|             ESP_LOGE(MB_MASTER_TAG, "%s: Incorrect param type (%u).", |             ESP_LOGE(TAG, "%s: Incorrect param type (%u).", | ||||||
|                         __FUNCTION__, (uint16_t)param_type); |                         __FUNCTION__, (uint16_t)param_type); | ||||||
|             err = ESP_ERR_NOT_SUPPORTED; |             err = ESP_ERR_NOT_SUPPORTED; | ||||||
|             break; |             break; | ||||||
| @@ -420,31 +486,43 @@ static esp_err_t mbc_tcp_master_get_parameter(uint16_t cid, char* name, uint8_t* | |||||||
| { | { | ||||||
|     MB_MASTER_CHECK((name != NULL), ESP_ERR_INVALID_ARG, "mb incorrect descriptor."); |     MB_MASTER_CHECK((name != NULL), ESP_ERR_INVALID_ARG, "mb incorrect descriptor."); | ||||||
|     MB_MASTER_CHECK((type != NULL), ESP_ERR_INVALID_ARG, "type pointer is incorrect."); |     MB_MASTER_CHECK((type != NULL), ESP_ERR_INVALID_ARG, "type pointer is incorrect."); | ||||||
|  |     MB_MASTER_CHECK((value != NULL), ESP_ERR_INVALID_ARG, "value pointer is incorrect."); | ||||||
|     esp_err_t error = ESP_ERR_INVALID_RESPONSE; |     esp_err_t error = ESP_ERR_INVALID_RESPONSE; | ||||||
|     mb_param_request_t request ; |     mb_param_request_t request ; | ||||||
|     mb_parameter_descriptor_t reg_info = { 0 }; |     mb_parameter_descriptor_t reg_info = { 0 }; | ||||||
|     uint8_t param_buffer[PARAM_MAX_SIZE] = { 0 }; |     uint8_t* pdata = NULL; | ||||||
|  |  | ||||||
|     error = mbc_tcp_master_set_request(name, MB_PARAM_READ, &request, ®_info); |     error = mbc_tcp_master_set_request(name, MB_PARAM_READ, &request, ®_info); | ||||||
|     if ((error == ESP_OK) && (cid == reg_info.cid)) { |     if ((error == ESP_OK) && (cid == reg_info.cid)) { | ||||||
|         error = mbc_tcp_master_send_request(&request, ¶m_buffer[0]); |         // alloc buffer to store parameter data | ||||||
|  |         pdata = calloc(1, (reg_info.mb_size << 1)); | ||||||
|  |         if (!pdata) { | ||||||
|  |             return ESP_ERR_INVALID_STATE; | ||||||
|  |         } | ||||||
|  |         error = mbc_tcp_master_send_request(&request, pdata); | ||||||
|         if (error == ESP_OK) { |         if (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 data pointer is NULL then we don't need to set value (it is still in the cache of cid) | ||||||
|             if (value != NULL) { |             if (value != NULL) { | ||||||
|                 error = mbc_tcp_master_set_param_data((void*)value, (void*)¶m_buffer[0], |                 error = mbc_tcp_master_set_param_data((void*)value, (void*)pdata, | ||||||
|                                                     reg_info.param_type, reg_info.param_size); |                                                     reg_info.param_type, reg_info.param_size); | ||||||
|                 MB_MASTER_CHECK((error == ESP_OK), ESP_ERR_INVALID_STATE, "fail to set parameter data."); |                 if (error != ESP_OK) { | ||||||
|  |                     ESP_LOGE(TAG, "fail to set parameter data."); | ||||||
|  |                     error = ESP_ERR_INVALID_STATE; | ||||||
|  |                 } else { | ||||||
|  |                     ESP_LOGD(TAG, "%s: Good response for get cid(%u) = %s", | ||||||
|  |                                                         __FUNCTION__, (unsigned)reg_info.cid, (char*)esp_err_to_name(error)); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|             ESP_LOGD(MB_MASTER_TAG, "%s: Good response for get cid(%u) = %s", |  | ||||||
|                                     __FUNCTION__, (int)reg_info.cid, (char*)esp_err_to_name(error)); |  | ||||||
|         } else { |         } else { | ||||||
|             ESP_LOGD(MB_MASTER_TAG, "%s: Bad response to get cid(%u) = %s", |             ESP_LOGD(TAG, "%s: Bad response to get cid(%u) = %s", | ||||||
|                                             __FUNCTION__, reg_info.cid, (char*)esp_err_to_name(error)); |                                             __FUNCTION__, reg_info.cid, (char*)esp_err_to_name(error)); | ||||||
|  |             error = ESP_ERR_INVALID_RESPONSE; | ||||||
|         } |         } | ||||||
|  |         free(pdata); | ||||||
|         // Set the type of parameter found in the table |         // Set the type of parameter found in the table | ||||||
|         *type = reg_info.param_type; |         *type = reg_info.param_type; | ||||||
|     } else { |     } else { | ||||||
|         ESP_LOGE(MB_MASTER_TAG, "%s: The cid(%u) not found in the data dictionary.", |         ESP_LOGE(TAG, "%s: The cid(%u) not found in the data dictionary.", | ||||||
|                                                     __FUNCTION__, reg_info.cid); |                                                     __FUNCTION__, reg_info.cid); | ||||||
|         error = ESP_ERR_INVALID_ARG; |         error = ESP_ERR_INVALID_ARG; | ||||||
|     } |     } | ||||||
| @@ -461,27 +539,36 @@ static esp_err_t mbc_tcp_master_set_parameter(uint16_t cid, char* name, uint8_t* | |||||||
|     esp_err_t error = ESP_ERR_INVALID_RESPONSE; |     esp_err_t error = ESP_ERR_INVALID_RESPONSE; | ||||||
|     mb_param_request_t request ; |     mb_param_request_t request ; | ||||||
|     mb_parameter_descriptor_t reg_info = { 0 }; |     mb_parameter_descriptor_t reg_info = { 0 }; | ||||||
|     uint8_t param_buffer[PARAM_MAX_SIZE] = { 0 }; |     uint8_t* pdata = NULL; | ||||||
|  |  | ||||||
|     error = mbc_tcp_master_set_request(name, MB_PARAM_WRITE, &request, ®_info); |     error = mbc_tcp_master_set_request(name, MB_PARAM_WRITE, &request, ®_info); | ||||||
|     if ((error == ESP_OK) && (cid == reg_info.cid)) { |     if ((error == ESP_OK) && (cid == reg_info.cid)) { | ||||||
|  |         pdata = calloc(1, (reg_info.mb_size << 1)); // alloc parameter buffer | ||||||
|  |         if (!pdata) { | ||||||
|  |             return ESP_ERR_INVALID_STATE; | ||||||
|  |         } | ||||||
|         // Transfer value of characteristic into parameter buffer |         // Transfer value of characteristic into parameter buffer | ||||||
|         error = mbc_tcp_master_set_param_data((void*)¶m_buffer[0], (void*)value, |         error = mbc_tcp_master_set_param_data((void*)pdata, (void*)value, | ||||||
|                                                 reg_info.param_type, reg_info.param_size); |                                                 reg_info.param_type, reg_info.param_size); | ||||||
|         MB_MASTER_CHECK((error == ESP_OK), ESP_ERR_INVALID_STATE, "failure to set parameter data."); |         if (error != ESP_OK) { | ||||||
|  |             ESP_LOGE(TAG, "fail to set parameter data."); | ||||||
|  |             free(pdata); | ||||||
|  |             return ESP_ERR_INVALID_STATE; | ||||||
|  |         } | ||||||
|         // Send request to write characteristic data |         // Send request to write characteristic data | ||||||
|         error = mbc_tcp_master_send_request(&request, ¶m_buffer[0]); |         error = mbc_tcp_master_send_request(&request, pdata); | ||||||
|         if (error == ESP_OK) { |         if (error == ESP_OK) { | ||||||
|             ESP_LOGD(MB_MASTER_TAG, "%s: Good response for set cid(%u) = %s", |             ESP_LOGD(TAG, "%s: Good response for set cid(%u) = %s", | ||||||
|                                     __FUNCTION__, (int)reg_info.cid, (char*)esp_err_to_name(error)); |                                     __FUNCTION__, (unsigned)reg_info.cid, (char*)esp_err_to_name(error)); | ||||||
|         } else { |         } else { | ||||||
|             ESP_LOGD(MB_MASTER_TAG, "%s: Bad response to set cid(%u) = %s", |             ESP_LOGD(TAG, "%s: Bad response to set cid(%u) = %s", | ||||||
|                                     __FUNCTION__, reg_info.cid, (char*)esp_err_to_name(error)); |                                     __FUNCTION__, reg_info.cid, (char*)esp_err_to_name(error)); | ||||||
|         } |         } | ||||||
|  |         free(pdata); | ||||||
|         // Set the type of parameter found in the table |         // Set the type of parameter found in the table | ||||||
|         *type = reg_info.param_type; |         *type = reg_info.param_type; | ||||||
|     } else { |     } else { | ||||||
|         ESP_LOGE(MB_MASTER_TAG, "%s: The requested cid(%u) not found in the data dictionary.", |         ESP_LOGE(TAG, "%s: The requested cid(%u) not found in the data dictionary.", | ||||||
|                                     __FUNCTION__, reg_info.cid); |                                     __FUNCTION__, reg_info.cid); | ||||||
|         error = ESP_ERR_INVALID_ARG; |         error = ESP_ERR_INVALID_ARG; | ||||||
|     } |     } | ||||||
| @@ -709,6 +796,9 @@ esp_err_t mbc_tcp_master_create(void** handler) | |||||||
|     } |     } | ||||||
|     MB_MASTER_ASSERT(mbm_opts->mbm_task_handle != NULL); // The task is created but handle is incorrect |     MB_MASTER_ASSERT(mbm_opts->mbm_task_handle != NULL); // The task is created but handle is incorrect | ||||||
|  |  | ||||||
|  |     LIST_INIT(&mbm_opts->mbm_slave_list); // Init slave address list | ||||||
|  |     mbm_opts->mbm_slave_list_count = 0; | ||||||
|  |  | ||||||
|     // Initialize public interface methods of the interface |     // Initialize public interface methods of the interface | ||||||
|     mbm_interface_ptr->init = mbc_tcp_master_create; |     mbm_interface_ptr->init = mbc_tcp_master_create; | ||||||
|     mbm_interface_ptr->destroy = mbc_tcp_master_destroy; |     mbm_interface_ptr->destroy = mbc_tcp_master_destroy; | ||||||
|   | |||||||
| @@ -66,7 +66,6 @@ | |||||||
| #define MB_TCP_CONNECTION_TIMEOUT_MS    ( 20 )      // Connection timeout in mS | #define MB_TCP_CONNECTION_TIMEOUT_MS    ( 20 )      // Connection timeout in mS | ||||||
| #define MB_TCP_RECONNECT_TIMEOUT        ( 5000000 ) // Connection timeout in uS | #define MB_TCP_RECONNECT_TIMEOUT        ( 5000000 ) // Connection timeout in uS | ||||||
|  |  | ||||||
| #define MB_TCP_MASTER_PORT_TAG          "MB_TCP_MASTER_PORT" |  | ||||||
| #define MB_EVENT_REQ_DONE_MASK          (   EV_MASTER_PROCESS_SUCCESS | \ | #define MB_EVENT_REQ_DONE_MASK          (   EV_MASTER_PROCESS_SUCCESS | \ | ||||||
|                                             EV_MASTER_ERROR_RESPOND_TIMEOUT | \ |                                             EV_MASTER_ERROR_RESPOND_TIMEOUT | \ | ||||||
|                                             EV_MASTER_ERROR_RECEIVE_DATA | \ |                                             EV_MASTER_ERROR_RECEIVE_DATA | \ | ||||||
| @@ -84,6 +83,7 @@ | |||||||
| void vMBPortEventClose( void ); | void vMBPortEventClose( void ); | ||||||
|  |  | ||||||
| /* ----------------------- Static variables ---------------------------------*/ | /* ----------------------- Static variables ---------------------------------*/ | ||||||
|  | static const char *TAG = "MB_TCP_MASTER_PORT"; | ||||||
| static MbPortConfig_t xMbPortConfig; | static MbPortConfig_t xMbPortConfig; | ||||||
| static EventGroupHandle_t xMasterEventHandle = NULL; | static EventGroupHandle_t xMasterEventHandle = NULL; | ||||||
| static SemaphoreHandle_t xShutdownSemaphore = NULL; | static SemaphoreHandle_t xShutdownSemaphore = NULL; | ||||||
| @@ -114,7 +114,7 @@ xMBMasterTCPPortInit( USHORT usTCPPort ) | |||||||
|  |  | ||||||
|     xMbPortConfig.pxMbSlaveInfo = calloc(MB_TCP_PORT_MAX_CONN, sizeof(MbSlaveInfo_t*)); |     xMbPortConfig.pxMbSlaveInfo = calloc(MB_TCP_PORT_MAX_CONN, sizeof(MbSlaveInfo_t*)); | ||||||
|     if (!xMbPortConfig.pxMbSlaveInfo) { |     if (!xMbPortConfig.pxMbSlaveInfo) { | ||||||
|         ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "TCP slave info alloc failure."); |         ESP_LOGE(TAG, "TCP slave info alloc failure."); | ||||||
|         return FALSE; |         return FALSE; | ||||||
|     } |     } | ||||||
|     for(int idx = 0; idx < MB_TCP_PORT_MAX_CONN; xMbPortConfig.pxMbSlaveInfo[idx] = NULL, idx++); |     for(int idx = 0; idx < MB_TCP_PORT_MAX_CONN; xMbPortConfig.pxMbSlaveInfo[idx] = NULL, idx++); | ||||||
| @@ -123,12 +123,13 @@ xMBMasterTCPPortInit( USHORT usTCPPort ) | |||||||
|     xMbPortConfig.usPort = usTCPPort; |     xMbPortConfig.usPort = usTCPPort; | ||||||
|     xMbPortConfig.usMbSlaveInfoCount = 0; |     xMbPortConfig.usMbSlaveInfoCount = 0; | ||||||
|     xMbPortConfig.ucCurSlaveIndex = 1; |     xMbPortConfig.ucCurSlaveIndex = 1; | ||||||
|  |     xMbPortConfig.pxMbSlaveCurrInfo = NULL; | ||||||
|  |  | ||||||
|     xMbPortConfig.xConnectQueue = xQueueCreate(2, sizeof(CHAR*)); |     xMbPortConfig.xConnectQueue = xQueueCreate(2, sizeof(MbSlaveAddrInfo_t)); | ||||||
|     if (xMbPortConfig.xConnectQueue == 0) |     if (xMbPortConfig.xConnectQueue == 0) | ||||||
|     { |     { | ||||||
|         // Queue was not created and must not be used. |         // Queue was not created and must not be used. | ||||||
|         ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "TCP master queue creation failure."); |         ESP_LOGE(TAG, "TCP master queue creation failure."); | ||||||
|         return FALSE; |         return FALSE; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -142,10 +143,10 @@ xMBMasterTCPPortInit( USHORT usTCPPort ) | |||||||
|                                     MB_PORT_TASK_AFFINITY); |                                     MB_PORT_TASK_AFFINITY); | ||||||
|     if (xErr != pdTRUE) |     if (xErr != pdTRUE) | ||||||
|     { |     { | ||||||
|         ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "TCP master task creation failure."); |         ESP_LOGE(TAG, "TCP master task creation failure."); | ||||||
|         (void)vTaskDelete(xMbPortConfig.xMbTcpTaskHandle); |         (void)vTaskDelete(xMbPortConfig.xMbTcpTaskHandle); | ||||||
|     } else { |     } else { | ||||||
|         ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "TCP master stack initialized."); |         ESP_LOGI(TAG, "TCP master stack initialized."); | ||||||
|         bOkay = TRUE; |         bOkay = TRUE; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -153,9 +154,30 @@ xMBMasterTCPPortInit( USHORT usTCPPort ) | |||||||
|     return bOkay; |     return bOkay; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static MbSlaveInfo_t* vMBTCPPortMasterFindSlaveInfo(UCHAR ucSlaveAddr) | ||||||
|  | { | ||||||
|  |     int xIndex; | ||||||
|  |     BOOL xFound = false; | ||||||
|  |     for (xIndex = 0; xIndex < xMbPortConfig.usMbSlaveInfoCount; xIndex++) { | ||||||
|  |         if (xMbPortConfig.pxMbSlaveInfo[xIndex]->ucSlaveAddr == ucSlaveAddr) { | ||||||
|  |             xMbPortConfig.pxMbSlaveCurrInfo = xMbPortConfig.pxMbSlaveInfo[xIndex]; | ||||||
|  |             xFound = TRUE; | ||||||
|  |             xMbPortConfig.ucCurSlaveIndex = xIndex; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     if (!xFound) { | ||||||
|  |         xMbPortConfig.pxMbSlaveCurrInfo = NULL; | ||||||
|  |         ESP_LOGE(TAG, "Slave info for short address %d not found.", ucSlaveAddr); | ||||||
|  |     } | ||||||
|  |     return xMbPortConfig.pxMbSlaveCurrInfo; | ||||||
|  | } | ||||||
|  |  | ||||||
| static MbSlaveInfo_t* vMBTCPPortMasterGetCurrInfo(void) | static MbSlaveInfo_t* vMBTCPPortMasterGetCurrInfo(void) | ||||||
| { | { | ||||||
|     return xMbPortConfig.pxMbSlaveInfo[xMbPortConfig.ucCurSlaveIndex - 1]; |     if (!xMbPortConfig.pxMbSlaveCurrInfo) { | ||||||
|  |         ESP_LOGE(TAG, "Incorrect current slave info."); | ||||||
|  |     } | ||||||
|  |     return xMbPortConfig.pxMbSlaveCurrInfo; | ||||||
| } | } | ||||||
|  |  | ||||||
| // Start Modbus event state machine | // Start Modbus event state machine | ||||||
| @@ -166,10 +188,10 @@ static void vMBTCPPortMasterStartPoll(void) | |||||||
|         EventBits_t xFlags = xEventGroupSetBits(xMasterEventHandle, |         EventBits_t xFlags = xEventGroupSetBits(xMasterEventHandle, | ||||||
|                                                 (EventBits_t)xMasterEvent); |                                                 (EventBits_t)xMasterEvent); | ||||||
|         if (!(xFlags & xMasterEvent)) { |         if (!(xFlags & xMasterEvent)) { | ||||||
|             ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to start TCP stack."); |             ESP_LOGE(TAG, "Fail to start TCP stack."); | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to start polling. Incorrect event handle..."); |         ESP_LOGE(TAG, "Fail to start polling. Incorrect event handle..."); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -181,10 +203,10 @@ static void vMBTCPPortMasterStopPoll(void) | |||||||
|         EventBits_t xFlags = xEventGroupClearBits(xMasterEventHandle, |         EventBits_t xFlags = xEventGroupClearBits(xMasterEventHandle, | ||||||
|                                                 (EventBits_t)xMasterEvent); |                                                 (EventBits_t)xMasterEvent); | ||||||
|         if (!(xFlags & xMasterEvent)) { |         if (!(xFlags & xMasterEvent)) { | ||||||
|             ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to stop polling."); |             ESP_LOGE(TAG, "Fail to stop polling."); | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to stop polling. Incorrect event handle..."); |         ESP_LOGE(TAG, "Fail to stop polling. Incorrect event handle..."); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -215,11 +237,11 @@ static BOOL xMBTCPPortMasterCloseConnection(MbSlaveInfo_t* pxInfo) | |||||||
|         return FALSE; |         return FALSE; | ||||||
|     } |     } | ||||||
|     if (pxInfo->xSockId == -1) { |     if (pxInfo->xSockId == -1) { | ||||||
|         ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Wrong socket info or disconnected socket: %d, skip.", pxInfo->xSockId); |         ESP_LOGE(TAG, "Wrong socket info or disconnected socket: %d, skip.", pxInfo->xSockId); | ||||||
|         return FALSE; |         return FALSE; | ||||||
|     } |     } | ||||||
|     if (shutdown(pxInfo->xSockId, SHUT_RDWR) == -1) { |     if (shutdown(pxInfo->xSockId, SHUT_RDWR) == -1) { | ||||||
|         ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Shutdown failed sock %d, errno=%d", pxInfo->xSockId, errno); |         ESP_LOGV(TAG, "Shutdown failed sock %d, errno=%d", pxInfo->xSockId, errno); | ||||||
|     } |     } | ||||||
|     close(pxInfo->xSockId); |     close(pxInfo->xSockId); | ||||||
|     pxInfo->xSockId = -1; |     pxInfo->xSockId = -1; | ||||||
| @@ -289,12 +311,12 @@ static int xMBTCPPortMasterGetBuf(MbSlaveInfo_t* pxInfo, UCHAR* pucDstBuf, USHOR | |||||||
|                 continue; |                 continue; | ||||||
|             } else if (errno == ENOTCONN) { |             } else if (errno == ENOTCONN) { | ||||||
|                 // Socket connection closed |                 // Socket connection closed | ||||||
|                 ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s) connection closed.", |                 ESP_LOGE(TAG, "Socket(#%d)(%s) connection closed.", | ||||||
|                                             pxInfo->xSockId, pxInfo->pcIpAddr); |                                             pxInfo->xSockId, pxInfo->pcIpAddr); | ||||||
|                 return ERR_CONN; |                 return ERR_CONN; | ||||||
|             } else { |             } else { | ||||||
|                 // Other error occurred during receiving |                 // Other error occurred during receiving | ||||||
|                 ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s) receive error, length=%d, errno=%d", |                 ESP_LOGE(TAG, "Socket(#%d)(%s) receive error, length=%d, errno=%d", | ||||||
|                                             pxInfo->xSockId, pxInfo->pcIpAddr, xLength, errno); |                                             pxInfo->xSockId, pxInfo->pcIpAddr, xLength, errno); | ||||||
|                 return -1; |                 return -1; | ||||||
|             } |             } | ||||||
| @@ -325,7 +347,7 @@ static int vMBTCPPortMasterReadPacket(MbSlaveInfo_t* pxInfo) | |||||||
|             pxInfo->xRcvErr = xRet; |             pxInfo->xRcvErr = xRet; | ||||||
|             return xRet; |             return xRet; | ||||||
|         } else if (xRet != MB_TCP_UID) { |         } else if (xRet != MB_TCP_UID) { | ||||||
|             ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Socket (#%d)(%s), Fail to read modbus header. ret=%d", |             ESP_LOGD(TAG, "Socket (#%d)(%s), Fail to read modbus header. ret=%d", | ||||||
|                                                                 pxInfo->xSockId, pxInfo->pcIpAddr, xRet); |                                                                 pxInfo->xSockId, pxInfo->pcIpAddr, xRet); | ||||||
|             pxInfo->xRcvErr = ERR_VAL; |             pxInfo->xRcvErr = ERR_VAL; | ||||||
|             return ERR_VAL; |             return ERR_VAL; | ||||||
| @@ -339,7 +361,7 @@ static int vMBTCPPortMasterReadPacket(MbSlaveInfo_t* pxInfo) | |||||||
|             return xRet; |             return xRet; | ||||||
|         } else if (xRet != xLength) { |         } else if (xRet != xLength) { | ||||||
|             // Received incorrect or fragmented packet. |             // Received incorrect or fragmented packet. | ||||||
|             ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s) incorrect packet, length=%d, TID=0x%02x, errno=%d(%s)", |             ESP_LOGD(TAG, "Socket(#%d)(%s) incorrect packet, length=%d, TID=0x%02x, errno=%d(%s)", | ||||||
|                                                pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->usRcvPos, |                                                pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->usRcvPos, | ||||||
|                                                usTidRcv, errno, strerror(errno)); |                                                usTidRcv, errno, strerror(errno)); | ||||||
|             pxInfo->xRcvErr = ERR_VAL; |             pxInfo->xRcvErr = ERR_VAL; | ||||||
| @@ -349,13 +371,13 @@ static int vMBTCPPortMasterReadPacket(MbSlaveInfo_t* pxInfo) | |||||||
|  |  | ||||||
|         // Check transaction identifier field in the incoming packet. |         // Check transaction identifier field in the incoming packet. | ||||||
|         if ((pxInfo->usTidCnt - 1) != usTidRcv) { |         if ((pxInfo->usTidCnt - 1) != usTidRcv) { | ||||||
|             ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Socket (#%d)(%s), incorrect TID(0x%02x)!=(0x%02x) received, discard data.", |             ESP_LOGD(TAG, "Socket (#%d)(%s), incorrect TID(0x%02x)!=(0x%02x) received, discard data.", | ||||||
|                                                 pxInfo->xSockId, pxInfo->pcIpAddr, usTidRcv, (pxInfo->usTidCnt - 1)); |                                                 pxInfo->xSockId, pxInfo->pcIpAddr, usTidRcv, (pxInfo->usTidCnt - 1)); | ||||||
|             pxInfo->xRcvErr = ERR_BUF; |             pxInfo->xRcvErr = ERR_BUF; | ||||||
|             return ERR_BUF; |             return ERR_BUF; | ||||||
|         } |         } | ||||||
|         pxInfo->usRcvPos += xRet + MB_TCP_UID; |         pxInfo->usRcvPos += xRet + MB_TCP_UID; | ||||||
|         ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s) get data, length=%d, TID=0x%02x, errno=%d(%s)", |         ESP_LOGD(TAG, "Socket(#%d)(%s) get data, length=%d, TID=0x%02x, errno=%d(%s)", | ||||||
|                                            pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->usRcvPos, |                                            pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->usRcvPos, | ||||||
|                                            usTidRcv, errno, strerror(errno)); |                                            usTidRcv, errno, strerror(errno)); | ||||||
|         pxInfo->xRcvErr = ERR_OK; |         pxInfo->xRcvErr = ERR_OK; | ||||||
| @@ -372,7 +394,7 @@ static err_t xMBTCPPortMasterSetNonBlocking(MbSlaveInfo_t* pxInfo) | |||||||
|     // Set non blocking attribute for socket |     // Set non blocking attribute for socket | ||||||
|     ULONG ulFlags = fcntl(pxInfo->xSockId, F_GETFL); |     ULONG ulFlags = fcntl(pxInfo->xSockId, F_GETFL); | ||||||
|     if (fcntl(pxInfo->xSockId, F_SETFL, ulFlags | O_NONBLOCK) == -1) { |     if (fcntl(pxInfo->xSockId, F_SETFL, ulFlags | O_NONBLOCK) == -1) { | ||||||
|         ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s), fcntl() call error=%d", |         ESP_LOGE(TAG, "Socket(#%d)(%s), fcntl() call error=%d", | ||||||
|                                               pxInfo->xSockId, pxInfo->pcIpAddr, errno); |                                               pxInfo->xSockId, pxInfo->pcIpAddr, errno); | ||||||
|         return ERR_WOULDBLOCK; |         return ERR_WOULDBLOCK; | ||||||
|     } |     } | ||||||
| @@ -405,12 +427,12 @@ static err_t xMBTCPPortMasterCheckAlive(MbSlaveInfo_t* pxInfo, ULONG xTimeoutMs) | |||||||
|             if (errno == EINPROGRESS) { |             if (errno == EINPROGRESS) { | ||||||
|                 xErr = ERR_INPROGRESS; |                 xErr = ERR_INPROGRESS; | ||||||
|             } else { |             } else { | ||||||
|                 ESP_LOGV(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(" connection, select write err(errno) = %d(%d)."), |                 ESP_LOGV(TAG, MB_SLAVE_FMT(" connection, select write err(errno) = %d(%d)."), | ||||||
|                                                     pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xErr, errno); |                                                     pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xErr, errno); | ||||||
|                 xErr = ERR_CONN; |                 xErr = ERR_CONN; | ||||||
|             } |             } | ||||||
|         } else if (xErr == 0) { |         } else if (xErr == 0) { | ||||||
|             ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s), connection timeout occurred, err(errno) = %d(%d).", |             ESP_LOGV(TAG, "Socket(#%d)(%s), connection timeout occurred, err(errno) = %d(%d).", | ||||||
|                                         pxInfo->xSockId, pxInfo->pcIpAddr, xErr, errno); |                                         pxInfo->xSockId, pxInfo->pcIpAddr, xErr, errno); | ||||||
|             return ERR_INPROGRESS; |             return ERR_INPROGRESS; | ||||||
|         } else { |         } else { | ||||||
| @@ -419,11 +441,11 @@ static err_t xMBTCPPortMasterCheckAlive(MbSlaveInfo_t* pxInfo, ULONG xTimeoutMs) | |||||||
|             // Check socket error |             // Check socket error | ||||||
|             xErr = getsockopt(pxInfo->xSockId, SOL_SOCKET, SO_ERROR, (void*)&xOptErr, (socklen_t*)&ulOptLen); |             xErr = getsockopt(pxInfo->xSockId, SOL_SOCKET, SO_ERROR, (void*)&xOptErr, (socklen_t*)&ulOptLen); | ||||||
|             if (xOptErr != 0) { |             if (xOptErr != 0) { | ||||||
|                 ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s), sock error occurred (%d).", |                 ESP_LOGD(TAG, "Socket(#%d)(%s), sock error occurred (%d).", | ||||||
|                                             pxInfo->xSockId, pxInfo->pcIpAddr, xOptErr); |                                             pxInfo->xSockId, pxInfo->pcIpAddr, xOptErr); | ||||||
|                 return ERR_CONN; |                 return ERR_CONN; | ||||||
|             } |             } | ||||||
|             ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s), is alive.", |             ESP_LOGV(TAG, "Socket(#%d)(%s), is alive.", | ||||||
|                                         pxInfo->xSockId, pxInfo->pcIpAddr); |                                         pxInfo->xSockId, pxInfo->pcIpAddr); | ||||||
|             return ERR_OK; |             return ERR_OK; | ||||||
|         } |         } | ||||||
| @@ -453,7 +475,7 @@ static BOOL xMBTCPPortMasterCheckHost(const CHAR* pcHostStr, ip_addr_t* pxHostAd | |||||||
|     int xRet = getaddrinfo(pcHostStr, NULL, &xHint, &pxAddrList); |     int xRet = getaddrinfo(pcHostStr, NULL, &xHint, &pxAddrList); | ||||||
|  |  | ||||||
|     if (xRet != 0) { |     if (xRet != 0) { | ||||||
|         ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Incorrect host name or IP: %s", pcHostStr); |         ESP_LOGE(TAG, "Incorrect host name or IP: %s", pcHostStr); | ||||||
|         return FALSE; |         return FALSE; | ||||||
|     } |     } | ||||||
|     if (pxAddrList->ai_family == AF_INET) { |     if (pxAddrList->ai_family == AF_INET) { | ||||||
| @@ -471,20 +493,24 @@ static BOOL xMBTCPPortMasterCheckHost(const CHAR* pcHostStr, ip_addr_t* pxHostAd | |||||||
|     if (pxHostAddr) { |     if (pxHostAddr) { | ||||||
|         *pxHostAddr = xTargetAddr; |         *pxHostAddr = xTargetAddr; | ||||||
|     } |     } | ||||||
|     ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "Host[IP]: \"%s\"[%s]", pxAddrList->ai_canonname, pcStr); |     ESP_LOGI(TAG, "Host[IP]: \"%s\"[%s]", pxAddrList->ai_canonname, pcStr); | ||||||
|     freeaddrinfo(pxAddrList); |     freeaddrinfo(pxAddrList); | ||||||
|     return TRUE; |     return TRUE; | ||||||
| } | } | ||||||
|  |  | ||||||
| BOOL xMBTCPPortMasterAddSlaveIp(const CHAR* pcIpStr) | BOOL xMBTCPPortMasterAddSlaveIp(const USHORT usIndex, const CHAR* pcIpStr, UCHAR ucSlaveAddress) | ||||||
| { | { | ||||||
|     BOOL xRes = FALSE; |     BOOL xRes = FALSE; | ||||||
|  |     MbSlaveAddrInfo_t xSlaveAddrInfo = { 0 }; | ||||||
|     MB_PORT_CHECK(xMbPortConfig.xConnectQueue != NULL, FALSE, "Wrong slave IP address to add."); |     MB_PORT_CHECK(xMbPortConfig.xConnectQueue != NULL, FALSE, "Wrong slave IP address to add."); | ||||||
|     if (pcIpStr) { |     if (pcIpStr && (usIndex != 0xFF)) { | ||||||
|         xRes = xMBTCPPortMasterCheckHost(pcIpStr, NULL); |         xRes = xMBTCPPortMasterCheckHost(pcIpStr, NULL); | ||||||
|     } |     } | ||||||
|     if (xRes || !pcIpStr) { |     if (xRes || !pcIpStr) { | ||||||
|         BaseType_t xStatus = xQueueSend(xMbPortConfig.xConnectQueue, (const void*)&pcIpStr, 100); |         xSlaveAddrInfo.pcIPAddr = pcIpStr; | ||||||
|  |         xSlaveAddrInfo.usIndex = usIndex; | ||||||
|  |         xSlaveAddrInfo.ucSlaveAddr = ucSlaveAddress; | ||||||
|  |         BaseType_t xStatus = xQueueSend(xMbPortConfig.xConnectQueue, (void*)&xSlaveAddrInfo, 100); | ||||||
|         MB_PORT_CHECK((xStatus == pdTRUE), FALSE, "FAIL to add slave IP address: [%s].", pcIpStr); |         MB_PORT_CHECK((xStatus == pdTRUE), FALSE, "FAIL to add slave IP address: [%s].", pcIpStr); | ||||||
|     } |     } | ||||||
|     return xRes; |     return xRes; | ||||||
| @@ -522,7 +548,7 @@ static err_t xMBTCPPortMasterConnect(MbSlaveInfo_t* pxInfo) | |||||||
|     int xRet = getaddrinfo(pxInfo->pcIpAddr, pcStr, &xHint, &pxAddrList); |     int xRet = getaddrinfo(pxInfo->pcIpAddr, pcStr, &xHint, &pxAddrList); | ||||||
|     free(pcStr); |     free(pcStr); | ||||||
|     if (xRet != 0) { |     if (xRet != 0) { | ||||||
|         ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Cannot resolve host: %s", pxInfo->pcIpAddr); |         ESP_LOGE(TAG, "Cannot resolve host: %s", pxInfo->pcIpAddr); | ||||||
|         return ERR_CONN; |         return ERR_CONN; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -545,12 +571,12 @@ static err_t xMBTCPPortMasterConnect(MbSlaveInfo_t* pxInfo) | |||||||
|         if (pxInfo->xSockId <= 0) { |         if (pxInfo->xSockId <= 0) { | ||||||
|             pxInfo->xSockId = socket(pxCurAddr->ai_family, pxCurAddr->ai_socktype, pxCurAddr->ai_protocol); |             pxInfo->xSockId = socket(pxCurAddr->ai_family, pxCurAddr->ai_socktype, pxCurAddr->ai_protocol); | ||||||
|             if (pxInfo->xSockId < 0) { |             if (pxInfo->xSockId < 0) { | ||||||
|                 ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Unable to create socket: #%d, errno %d", pxInfo->xSockId, errno); |                 ESP_LOGE(TAG, "Unable to create socket: #%d, errno %d", pxInfo->xSockId, errno); | ||||||
|                 xErr = ERR_IF; |                 xErr = ERR_IF; | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Socket (#%d)(%s) created.", pxInfo->xSockId, cStr); |             ESP_LOGV(TAG, "Socket (#%d)(%s) created.", pxInfo->xSockId, cStr); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Set non blocking attribute for socket |         // Set non blocking attribute for socket | ||||||
| @@ -561,7 +587,7 @@ static err_t xMBTCPPortMasterConnect(MbSlaveInfo_t* pxInfo) | |||||||
|         xErr = connect(pxInfo->xSockId, (struct sockaddr*)pxCurAddr->ai_addr, pxCurAddr->ai_addrlen); |         xErr = connect(pxInfo->xSockId, (struct sockaddr*)pxCurAddr->ai_addr, pxCurAddr->ai_addrlen); | ||||||
|         if ((xErr < 0) && (errno == EINPROGRESS || errno == EALREADY)) { |         if ((xErr < 0) && (errno == EINPROGRESS || errno == EALREADY)) { | ||||||
|             // The unblocking connect is pending (check status later) or already connected |             // The unblocking connect is pending (check status later) or already connected | ||||||
|             ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Socket(#%d)(%s) connection is pending, errno %d (%s).", |             ESP_LOGV(TAG, "Socket(#%d)(%s) connection is pending, errno %d (%s).", | ||||||
|                                         pxInfo->xSockId, cStr, errno, strerror(errno)); |                                         pxInfo->xSockId, cStr, errno, strerror(errno)); | ||||||
|  |  | ||||||
|             // Set keep alive flag in socket options |             // Set keep alive flag in socket options | ||||||
| @@ -574,12 +600,12 @@ static err_t xMBTCPPortMasterConnect(MbSlaveInfo_t* pxInfo) | |||||||
|             continue; |             continue; | ||||||
|         } else if (xErr != ERR_OK) { |         } else if (xErr != ERR_OK) { | ||||||
|             // Other error occurred during connection |             // Other error occurred during connection | ||||||
|             ESP_LOGV(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(" unable to connect, error=%d, errno %d (%s)"), |             ESP_LOGV(TAG, MB_SLAVE_FMT(" unable to connect, error=%d, errno %d (%s)"), | ||||||
|                                                 pxInfo->xIndex, pxInfo->xSockId, cStr, xErr, errno, strerror(errno)); |                                                 pxInfo->xIndex, pxInfo->xSockId, cStr, xErr, errno, strerror(errno)); | ||||||
|             xMBTCPPortMasterCloseConnection(pxInfo); |             xMBTCPPortMasterCloseConnection(pxInfo); | ||||||
|             xErr = ERR_CONN; |             xErr = ERR_CONN; | ||||||
|         } else { |         } else { | ||||||
|             ESP_LOGI(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", successfully connected."), |             ESP_LOGI(TAG, MB_SLAVE_FMT(", successfully connected."), | ||||||
|                                                   pxInfo->xIndex, pxInfo->xSockId, cStr); |                                                   pxInfo->xIndex, pxInfo->xSockId, cStr); | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
| @@ -621,7 +647,7 @@ static int xMBTCPPortMasterCheckConnState(fd_set* pxFdSet) | |||||||
|             xErr = xMBTCPPortMasterCheckAlive(pxInfo, 0); |             xErr = xMBTCPPortMasterCheckAlive(pxInfo, 0); | ||||||
|             if ((xErr < 0) && (((xTime - pxInfo->xRecvTimeStamp) > MB_TCP_RECONNECT_TIMEOUT) || |             if ((xErr < 0) && (((xTime - pxInfo->xRecvTimeStamp) > MB_TCP_RECONNECT_TIMEOUT) || | ||||||
|                                 ((xTime - pxInfo->xSendTimeStamp) > MB_TCP_RECONNECT_TIMEOUT))) { |                                 ((xTime - pxInfo->xSendTimeStamp) > MB_TCP_RECONNECT_TIMEOUT))) { | ||||||
|                 ESP_LOGI(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", slave is down, off_time[r][w](us) = [%ju][%ju]."), |                 ESP_LOGI(TAG, MB_SLAVE_FMT(", slave is down, off_time[r][w](us) = [%ju][%ju]."), | ||||||
|                                                             pxInfo->xIndex, |                                                             pxInfo->xIndex, | ||||||
|                                                             pxInfo->xSockId, |                                                             pxInfo->xSockId, | ||||||
|                                                             pxInfo->pcIpAddr, |                                                             pxInfo->pcIpAddr, | ||||||
| @@ -643,9 +669,9 @@ static void xMBTCPPortMasterFsmSetError(eMBMasterErrorEventType xErrType, eMBMas | |||||||
|  |  | ||||||
| static void vMBTCPPortMasterTask(void *pvParameters) | static void vMBTCPPortMasterTask(void *pvParameters) | ||||||
| { | { | ||||||
|     CHAR* pcAddrStr = NULL; |  | ||||||
|     MbSlaveInfo_t* pxInfo; |     MbSlaveInfo_t* pxInfo; | ||||||
|     MbSlaveInfo_t* pxCurrInfo; |     MbSlaveInfo_t* pxCurrInfo; | ||||||
|  |  | ||||||
|     fd_set xConnSet; |     fd_set xConnSet; | ||||||
|     fd_set xReadSet; |     fd_set xReadSet; | ||||||
|     int xMaxSd = 0; |     int xMaxSd = 0; | ||||||
| @@ -655,51 +681,53 @@ static void vMBTCPPortMasterTask(void *pvParameters) | |||||||
|  |  | ||||||
|     // Register each slave in the connection info structure |     // Register each slave in the connection info structure | ||||||
|     while (1) { |     while (1) { | ||||||
|         BaseType_t xStatus = xQueueReceive(xMbPortConfig.xConnectQueue, (void*)&pcAddrStr, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS)); |         MbSlaveAddrInfo_t xSlaveAddrInfo = { 0 }; | ||||||
|         xMBTCPPortMasterCheckShutdown(); |         BaseType_t xStatus = xQueueReceive(xMbPortConfig.xConnectQueue, (void*)&xSlaveAddrInfo, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS)); | ||||||
|  | 	    xMBTCPPortMasterCheckShutdown(); | ||||||
|         if (xStatus != pdTRUE) { |         if (xStatus != pdTRUE) { | ||||||
|             ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to register slave IP."); |             ESP_LOGE(TAG, "Fail to register slave IP."); | ||||||
|         } else { |         } else { | ||||||
|             if (pcAddrStr == NULL && xMbPortConfig.usMbSlaveInfoCount) { |             if (xSlaveAddrInfo.pcIPAddr == NULL && xMbPortConfig.usMbSlaveInfoCount && xSlaveAddrInfo.usIndex == 0xFF) { | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             if (xMbPortConfig.usMbSlaveInfoCount > MB_TCP_PORT_MAX_CONN) { |             if (xMbPortConfig.usMbSlaveInfoCount > MB_TCP_PORT_MAX_CONN) { | ||||||
|                 ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Exceeds maximum connections limit=%d.", MB_TCP_PORT_MAX_CONN); |                 ESP_LOGE(TAG, "Exceeds maximum connections limit=%d.", MB_TCP_PORT_MAX_CONN); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             pxInfo = calloc(1, sizeof(MbSlaveInfo_t)); |             pxInfo = calloc(1, sizeof(MbSlaveInfo_t)); | ||||||
|             if (!pxInfo) { |             if (!pxInfo) { | ||||||
|                 ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Slave(#%d), info structure allocation fail.", |                 ESP_LOGE(TAG, "Slave(#%d), info structure allocation fail.", | ||||||
|                                                     xMbPortConfig.usMbSlaveInfoCount); |                                                     xMbPortConfig.usMbSlaveInfoCount); | ||||||
|                 free(pxInfo); |                 free(pxInfo); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             pxInfo->pucRcvBuf = calloc(MB_TCP_BUF_SIZE, sizeof(UCHAR)); |             pxInfo->pucRcvBuf = calloc(MB_TCP_BUF_SIZE, sizeof(UCHAR)); | ||||||
|             if (!pxInfo->pucRcvBuf) { |             if (!pxInfo->pucRcvBuf) { | ||||||
|                 ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Slave(#%d), receive buffer allocation fail.", |                 ESP_LOGE(TAG, "Slave(#%d), receive buffer allocation fail.", | ||||||
|                                                     xMbPortConfig.usMbSlaveInfoCount); |                                                     xMbPortConfig.usMbSlaveInfoCount); | ||||||
|                 free(pxInfo->pucRcvBuf); |                 free(pxInfo->pucRcvBuf); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             pxInfo->usRcvPos = 0; |             pxInfo->usRcvPos = 0; | ||||||
|             pxInfo->pcIpAddr = pcAddrStr; |             pxInfo->pcIpAddr = xSlaveAddrInfo.pcIPAddr; | ||||||
|             pxInfo->xSockId = -1; |             pxInfo->xSockId = -1; | ||||||
|             pxInfo->xError = -1; |             pxInfo->xError = -1; | ||||||
|             pxInfo->xRecvTimeStamp = xMBTCPGetTimeStamp(); |             pxInfo->xRecvTimeStamp = xMBTCPGetTimeStamp(); | ||||||
|             pxInfo->xSendTimeStamp = xMBTCPGetTimeStamp(); |             pxInfo->xSendTimeStamp = xMBTCPGetTimeStamp(); | ||||||
|             pxInfo->xMbProto = MB_PROTO_TCP; |             pxInfo->xMbProto = MB_PROTO_TCP; | ||||||
|             pxInfo->xIndex = xMbPortConfig.usMbSlaveInfoCount; |             pxInfo->ucSlaveAddr = xSlaveAddrInfo.ucSlaveAddr; | ||||||
|  |             pxInfo->xIndex = xSlaveAddrInfo.usIndex; | ||||||
|             pxInfo->usTidCnt = (USHORT)(xMbPortConfig.usMbSlaveInfoCount << 8U); |             pxInfo->usTidCnt = (USHORT)(xMbPortConfig.usMbSlaveInfoCount << 8U); | ||||||
|             // Register slave |             // Register slave | ||||||
|             xMbPortConfig.pxMbSlaveInfo[xMbPortConfig.usMbSlaveInfoCount++] = pxInfo; |             xMbPortConfig.pxMbSlaveInfo[xMbPortConfig.usMbSlaveInfoCount++] = pxInfo; | ||||||
|             ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "Add slave IP: %s", pcAddrStr); |             ESP_LOGI(TAG, "Add slave IP: %s", xSlaveAddrInfo.pcIPAddr); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Main connection cycle |     // Main connection cycle | ||||||
|     while (1) |     while (1) | ||||||
|     { |     { | ||||||
|         ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "Connecting to slaves..."); |         ESP_LOGI(TAG, "Connecting to slaves..."); | ||||||
|         xTime = xMBTCPGetTimeStamp(); |         xTime = xMBTCPGetTimeStamp(); | ||||||
|         usSlaveConnCnt = 0; |         usSlaveConnCnt = 0; | ||||||
|         CHAR ucDot = '.'; |         CHAR ucDot = '.'; | ||||||
| @@ -712,7 +740,7 @@ static void vMBTCPPortMasterTask(void *pvParameters) | |||||||
|                 pxInfo = xMbPortConfig.pxMbSlaveInfo[ucCnt]; |                 pxInfo = xMbPortConfig.pxMbSlaveInfo[ucCnt]; | ||||||
|                 // if slave descriptor is NULL then it is end of list or connection closed. |                 // if slave descriptor is NULL then it is end of list or connection closed. | ||||||
|                 if (!pxInfo) { |                 if (!pxInfo) { | ||||||
|                     ESP_LOGV(MB_TCP_MASTER_PORT_TAG, "Index: %d is not initialized, skip.", ucCnt); |                     ESP_LOGV(TAG, "Index: %d is not initialized, skip.", ucCnt); | ||||||
|                     if (xMbPortConfig.usMbSlaveInfoCount) { |                     if (xMbPortConfig.usMbSlaveInfoCount) { | ||||||
|                         continue; |                         continue; | ||||||
|                     } |                     } | ||||||
| @@ -727,12 +755,12 @@ static void vMBTCPPortMasterTask(void *pvParameters) | |||||||
|                         // In case of connection errors remove the socket from set |                         // In case of connection errors remove the socket from set | ||||||
|                         if (FD_ISSET(pxInfo->xSockId, &xConnSet)) { |                         if (FD_ISSET(pxInfo->xSockId, &xConnSet)) { | ||||||
|                             FD_CLR(pxInfo->xSockId, &xConnSet); |                             FD_CLR(pxInfo->xSockId, &xConnSet); | ||||||
|                             ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(" connect failed, error = %d."), |                             ESP_LOGE(TAG, MB_SLAVE_FMT(" connect failed, error = %d."), | ||||||
|                                                                             pxInfo->xIndex, pxInfo->xSockId, |                                                                             pxInfo->xIndex, pxInfo->xSockId, | ||||||
|                                                                             (char*)pxInfo->pcIpAddr, xErr); |                                                                             (char*)pxInfo->pcIpAddr, xErr); | ||||||
|                                 if (usSlaveConnCnt) { |                             if (usSlaveConnCnt) { | ||||||
|                                     usSlaveConnCnt--; |                                 usSlaveConnCnt--; | ||||||
|                                 } |                             } | ||||||
|                         } |                         } | ||||||
|                         break; |                         break; | ||||||
|                     case ERR_OK: |                     case ERR_OK: | ||||||
| @@ -741,7 +769,7 @@ static void vMBTCPPortMasterTask(void *pvParameters) | |||||||
|                             FD_SET(pxInfo->xSockId, &xConnSet); |                             FD_SET(pxInfo->xSockId, &xConnSet); | ||||||
|                             usSlaveConnCnt++; |                             usSlaveConnCnt++; | ||||||
|                             xMaxSd = (pxInfo->xSockId > xMaxSd) ? pxInfo->xSockId : xMaxSd; |                             xMaxSd = (pxInfo->xSockId > xMaxSd) ? pxInfo->xSockId : xMaxSd; | ||||||
|                             ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", connected %d slave(s), error = %d."), |                             ESP_LOGD(TAG, MB_SLAVE_FMT(", connected %d slave(s), error = %d."), | ||||||
|                                                                 pxInfo->xIndex, pxInfo->xSockId, |                                                                 pxInfo->xIndex, pxInfo->xSockId, | ||||||
|                                                                 pxInfo->pcIpAddr, |                                                                 pxInfo->pcIpAddr, | ||||||
|                                                                 usSlaveConnCnt, xErr); |                                                                 usSlaveConnCnt, xErr); | ||||||
| @@ -751,7 +779,7 @@ static void vMBTCPPortMasterTask(void *pvParameters) | |||||||
|                         } |                         } | ||||||
|                         break; |                         break; | ||||||
|                     default: |                     default: | ||||||
|                         ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", unexpected error = %d."), |                         ESP_LOGE(TAG, MB_SLAVE_FMT(", unexpected error = %d."), | ||||||
|                                                             pxInfo->xIndex, |                                                             pxInfo->xIndex, | ||||||
|                                                             pxInfo->xSockId, |                                                             pxInfo->xSockId, | ||||||
|                                                             pxInfo->pcIpAddr, xErr); |                                                             pxInfo->pcIpAddr, xErr); | ||||||
| @@ -763,7 +791,7 @@ static void vMBTCPPortMasterTask(void *pvParameters) | |||||||
|                 xMBTCPPortMasterCheckShutdown(); |                 xMBTCPPortMasterCheckShutdown(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "Connected %d slaves, start polling...", usSlaveConnCnt); |         ESP_LOGI(TAG, "Connected %d slaves, start polling...", usSlaveConnCnt); | ||||||
|  |  | ||||||
|         vMBTCPPortMasterStartPoll(); // Send event to start stack |         vMBTCPPortMasterStartPoll(); // Send event to start stack | ||||||
|  |  | ||||||
| @@ -774,26 +802,26 @@ static void vMBTCPPortMasterTask(void *pvParameters) | |||||||
|             xMBMasterPortFsmWaitConfirmation(EV_MASTER_FRAME_TRANSMIT, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS)); |             xMBMasterPortFsmWaitConfirmation(EV_MASTER_FRAME_TRANSMIT, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS)); | ||||||
|             // Synchronize state machine with send packet event |             // Synchronize state machine with send packet event | ||||||
|             if (xMBMasterPortFsmWaitConfirmation(EV_MASTER_FRAME_SENT, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS))) { |             if (xMBMasterPortFsmWaitConfirmation(EV_MASTER_FRAME_SENT, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS))) { | ||||||
|                 ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "FSM Synchronized with sent event."); |                 ESP_LOGD(TAG, "FSM Synchronized with sent event."); | ||||||
|             } |             } | ||||||
|             // Get slave info for the current slave. |             // Get slave info for the current slave. | ||||||
|             pxCurrInfo = vMBTCPPortMasterGetCurrInfo(); |             pxCurrInfo = vMBTCPPortMasterGetCurrInfo(); | ||||||
|             if (!pxCurrInfo) { |             if (!pxCurrInfo) { | ||||||
|                 ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Incorrect connection options for slave index: %d.", |                 ESP_LOGE(TAG, "Incorrect connection options for slave index: %d.", | ||||||
|                                             xMbPortConfig.ucCurSlaveIndex); |                                             xMbPortConfig.ucCurSlaveIndex); | ||||||
|                 vMBTCPPortMasterStopPoll(); |                 vMBTCPPortMasterStopPoll(); | ||||||
|                 xMBTCPPortMasterCheckShutdown(); |                 xMBTCPPortMasterCheckShutdown(); | ||||||
|                 break; // incorrect slave descriptor, reconnect. |                 break; // incorrect slave descriptor, reconnect. | ||||||
|             } |             } | ||||||
|             xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo); |             xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo); | ||||||
|             ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Set select timeout, left time: %ju ms.", |             ESP_LOGD(TAG, "Set select timeout, left time: %ju ms.", | ||||||
|                                         xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo)); |                                         xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo)); | ||||||
|             // Wait respond from current slave during respond timeout |             // Wait respond from current slave during respond timeout | ||||||
|             int xRes = vMBTCPPortMasterRxCheck(pxCurrInfo->xSockId, &xReadSet, xTime); |             int xRes = vMBTCPPortMasterRxCheck(pxCurrInfo->xSockId, &xReadSet, xTime); | ||||||
|             if (xRes == ERR_TIMEOUT) { |             if (xRes == ERR_TIMEOUT) { | ||||||
|                 // No respond from current slave, process timeout. |                 // No respond from current slave, process timeout. | ||||||
|                 // Need to drop response later if it is received after timeout. |                 // Need to drop response later if it is received after timeout. | ||||||
|                 ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Select timeout, left time: %ju ms.", |                 ESP_LOGD(TAG, "Select timeout, left time: %ju ms.", | ||||||
|                                                     xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo)); |                                                     xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo)); | ||||||
|                 xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo); |                 xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo); | ||||||
|                 // Wait completion of last transaction |                 // Wait completion of last transaction | ||||||
| @@ -802,7 +830,7 @@ static void vMBTCPPortMasterTask(void *pvParameters) | |||||||
|                 continue; |                 continue; | ||||||
|             } else if (xRes < 0) { |             } else if (xRes < 0) { | ||||||
|                 // Select error (slave connection or r/w failure). |                 // Select error (slave connection or r/w failure). | ||||||
|                 ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", socket select error. Slave disconnected?"), |                 ESP_LOGD(TAG, MB_SLAVE_FMT(", socket select error. Slave disconnected?"), | ||||||
|                             pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); |                             pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); | ||||||
|                 xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo); |                 xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo); | ||||||
|                 // Wait completion of last transaction |                 // Wait completion of last transaction | ||||||
| @@ -816,30 +844,30 @@ static void vMBTCPPortMasterTask(void *pvParameters) | |||||||
|             } else { |             } else { | ||||||
|                 // Check to make sure that active slave data is ready |                 // Check to make sure that active slave data is ready | ||||||
|                 if (FD_ISSET(pxCurrInfo->xSockId, &xReadSet)) { |                 if (FD_ISSET(pxCurrInfo->xSockId, &xReadSet)) { | ||||||
|                     xErr = ERR_BUF; |                     int xRet = ERR_BUF; | ||||||
|                     for (int retry = 0; (xErr == ERR_BUF) && (retry < MB_TCP_READ_BUF_RETRY_CNT); retry++) { |                     for (int retry = 0; (xRet == ERR_BUF) && (retry < MB_TCP_READ_BUF_RETRY_CNT); retry++) { | ||||||
|                         xErr = vMBTCPPortMasterReadPacket(pxCurrInfo); |                         xRet = vMBTCPPortMasterReadPacket(pxCurrInfo); | ||||||
|                         // The error ERR_BUF means received response to previous request |                         // The error ERR_BUF means received response to previous request | ||||||
|                         // (due to timeout) with the same socket ID and incorrect TID, |                         // (due to timeout) with the same socket ID and incorrect TID, | ||||||
|                         // then ignore it and try to get next response buffer. |                         // then ignore it and try to get next response buffer. | ||||||
|                     } |                     } | ||||||
|                     if (xErr > 0) { |                     if (xRet > 0) { | ||||||
|                         // Response received correctly, send an event to stack |                         // Response received correctly, send an event to stack | ||||||
|                         xMBTCPPortMasterFsmSetError(EV_ERROR_INIT, EV_MASTER_FRAME_RECEIVED); |                         xMBTCPPortMasterFsmSetError(EV_ERROR_INIT, EV_MASTER_FRAME_RECEIVED); | ||||||
|                         ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", frame received."), |                         ESP_LOGD(TAG, MB_SLAVE_FMT(", frame received."), | ||||||
|                                     pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); |                                     pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); | ||||||
|                     } else if ((xErr == ERR_TIMEOUT) || (xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo) == 0)) { |                     } else if ((xRet == ERR_TIMEOUT) || (xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo) == 0)) { | ||||||
|                         // Timeout occurred when receiving frame, process respond timeout |                         // Timeout occurred when receiving frame, process respond timeout | ||||||
|                         ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", frame read timeout."), |                         ESP_LOGD(TAG, MB_SLAVE_FMT(", frame read timeout."), | ||||||
|                                     pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); |                                     pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); | ||||||
|                     } else if (xErr == ERR_BUF) { |                     } else if (xRet == ERR_BUF) { | ||||||
|                         // After retries a response with incorrect TID received, process failure. |                         // After retries a response with incorrect TID received, process failure. | ||||||
|                         xMBTCPPortMasterFsmSetError(EV_ERROR_RECEIVE_DATA, EV_MASTER_ERROR_PROCESS); |                         xMBTCPPortMasterFsmSetError(EV_ERROR_RECEIVE_DATA, EV_MASTER_ERROR_PROCESS); | ||||||
|                         ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", frame error."), |                         ESP_LOGD(TAG, MB_SLAVE_FMT(", frame error."), | ||||||
|                                     pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); |                                     pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); | ||||||
|                     } else { |                     } else { | ||||||
|                         ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", critical error=%d."), |                         ESP_LOGE(TAG, MB_SLAVE_FMT(", critical error=%d."), | ||||||
|                                     pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr, xErr); |                                     pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr, xRet); | ||||||
|                         // Stop polling process |                         // Stop polling process | ||||||
|                         vMBTCPPortMasterStopPoll(); |                         vMBTCPPortMasterStopPoll(); | ||||||
|                         xMBTCPPortMasterCheckShutdown(); |                         xMBTCPPortMasterCheckShutdown(); | ||||||
| @@ -848,14 +876,14 @@ static void vMBTCPPortMasterTask(void *pvParameters) | |||||||
|                         break; |                         break; | ||||||
|                     } |                     } | ||||||
|                     xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo); |                     xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo); | ||||||
|                     ESP_LOGD(MB_TCP_MASTER_PORT_TAG, "Slave #%d, data processing left time %ju [ms].", pxCurrInfo->xIndex, xTime); |                     ESP_LOGD(TAG, "Slave #%d, data processing left time %ju [ms].", pxCurrInfo->xIndex, xTime); | ||||||
|                     // Wait completion of Modbus frame processing before start of new transaction. |                     // Wait completion of Modbus frame processing before start of new transaction. | ||||||
|                     if (xMBMasterPortFsmWaitConfirmation(MB_EVENT_REQ_DONE_MASK, pdMS_TO_TICKS(xTime))) { |                     if (xMBMasterPortFsmWaitConfirmation(MB_EVENT_REQ_DONE_MASK, pdMS_TO_TICKS(xTime))) { | ||||||
|                         ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", data processing completed."), |                         ESP_LOGD(TAG, MB_SLAVE_FMT(", data processing completed."), | ||||||
|                                 pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); |                                 pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr); | ||||||
|                     } |                     } | ||||||
|                     xTime = xMBTCPGetTimeStamp() - pxCurrInfo->xSendTimeStamp; |                     xTime = xMBTCPGetTimeStamp() - pxCurrInfo->xSendTimeStamp; | ||||||
|                     ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", processing time[us] = %ju."), |                     ESP_LOGD(TAG, MB_SLAVE_FMT(", processing time[us] = %ju."), | ||||||
|                                                     pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr, xTime); |                                                     pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr, xTime); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @@ -892,7 +920,7 @@ vMBMasterTCPPortClose(void) | |||||||
|     xShutdownSemaphore = xSemaphoreCreateBinary(); |     xShutdownSemaphore = xSemaphoreCreateBinary(); | ||||||
|     // if no semaphore (alloc issues) or couldn't acquire it, just delete the task |     // if no semaphore (alloc issues) or couldn't acquire it, just delete the task | ||||||
|     if (xShutdownSemaphore == NULL || xSemaphoreTake(xShutdownSemaphore, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS)) != pdTRUE) { |     if (xShutdownSemaphore == NULL || xSemaphoreTake(xShutdownSemaphore, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS)) != pdTRUE) { | ||||||
|         ESP_LOGW(MB_TCP_MASTER_PORT_TAG, "Modbus port task couldn't exit gracefully within timeout -> abruptly deleting the task."); |         ESP_LOGW(TAG, "Modbus port task couldn't exit gracefully within timeout -> abruptly deleting the task."); | ||||||
|         vTaskDelete(xMbPortConfig.xMbTcpTaskHandle); |         vTaskDelete(xMbPortConfig.xMbTcpTaskHandle); | ||||||
|     } |     } | ||||||
|     if (xShutdownSemaphore) { |     if (xShutdownSemaphore) { | ||||||
| @@ -930,13 +958,13 @@ int xMBMasterTCPPortWritePoll(MbSlaveInfo_t* pxInfo, const UCHAR * pucMBTCPFrame | |||||||
|     int xRes = (int)xMBTCPPortMasterCheckAlive(pxInfo, xTimeout); |     int xRes = (int)xMBTCPPortMasterCheckAlive(pxInfo, xTimeout); | ||||||
|     if ((xRes < 0) && (xRes != ERR_INPROGRESS)) |     if ((xRes < 0) && (xRes != ERR_INPROGRESS)) | ||||||
|     { |     { | ||||||
|         ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", is not writable, error: %d, errno %d"), |         ESP_LOGE(TAG, MB_SLAVE_FMT(", is not writable, error: %d, errno %d"), | ||||||
|                                     pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xRes, errno); |                                     pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xRes, errno); | ||||||
|         return xRes; |         return xRes; | ||||||
|     } |     } | ||||||
|     xRes = send(pxInfo->xSockId, pucMBTCPFrame, usTCPLength, TCP_NODELAY); |     xRes = send(pxInfo->xSockId, pucMBTCPFrame, usTCPLength, TCP_NODELAY); | ||||||
|     if (xRes < 0) { |     if (xRes < 0) { | ||||||
|         ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", send data error: %d, errno %d"), |         ESP_LOGE(TAG, MB_SLAVE_FMT(", send data error: %d, errno %d"), | ||||||
|                                         pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xRes, errno); |                                         pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xRes, errno); | ||||||
|     } |     } | ||||||
|     return xRes; |     return xRes; | ||||||
| @@ -946,36 +974,41 @@ BOOL | |||||||
| xMBMasterTCPPortSendResponse( UCHAR * pucMBTCPFrame, USHORT usTCPLength ) | xMBMasterTCPPortSendResponse( UCHAR * pucMBTCPFrame, USHORT usTCPLength ) | ||||||
| { | { | ||||||
|     BOOL bFrameSent = FALSE; |     BOOL bFrameSent = FALSE; | ||||||
|     xMbPortConfig.ucCurSlaveIndex = ucMBMasterGetDestAddress(); |     USHORT ucCurSlaveIndex = ucMBMasterGetDestAddress(); | ||||||
|     MbSlaveInfo_t* pxInfo = vMBTCPPortMasterGetCurrInfo(); |     MbSlaveInfo_t* pxInfo = vMBTCPPortMasterFindSlaveInfo(ucCurSlaveIndex); | ||||||
|  |  | ||||||
|     // If socket active then send data |     // If the slave is correct and active then send data | ||||||
|     if (pxInfo->xSockId > -1) { |     // otherwise treat slave as died and skip | ||||||
|         // Apply TID field to the frame before send |     if (pxInfo != NULL) { | ||||||
|         pucMBTCPFrame[MB_TCP_TID] = (UCHAR)(pxInfo->usTidCnt >> 8U); |         if (pxInfo->xSockId < 0) { | ||||||
|         pucMBTCPFrame[MB_TCP_TID + 1] = (UCHAR)(pxInfo->usTidCnt & 0xFF); |             ESP_LOGD(TAG, MB_SLAVE_FMT(", send to died slave, error = %d"), | ||||||
|         int xRes = xMBMasterTCPPortWritePoll(pxInfo, pucMBTCPFrame, usTCPLength, MB_TCP_SEND_TIMEOUT_MS); |  | ||||||
|         if (xRes < 0) { |  | ||||||
|             ESP_LOGE(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", send data failure, err(errno) = %d(%d)."), |  | ||||||
|                                            pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xRes, errno); |  | ||||||
|             bFrameSent = FALSE; |  | ||||||
|             pxInfo->xError = xRes; |  | ||||||
|         } else { |  | ||||||
|             bFrameSent = TRUE; |  | ||||||
|             ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", send data successful: TID=0x%02x, %d (bytes), errno %d"), |  | ||||||
|                                                 pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->usTidCnt, xRes, errno); |  | ||||||
|             pxInfo->xError = 0; |  | ||||||
|             pxInfo->usRcvPos = 0; |  | ||||||
|             if (pxInfo->usTidCnt < (USHRT_MAX - 1)) { |  | ||||||
|                 pxInfo->usTidCnt++; |  | ||||||
|             } else { |  | ||||||
|                 pxInfo->usTidCnt = (USHORT)(pxInfo->xIndex << 8U); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         pxInfo->xSendTimeStamp = xMBTCPGetTimeStamp(); |  | ||||||
|     } else { |  | ||||||
|         ESP_LOGD(MB_TCP_MASTER_PORT_TAG, MB_SLAVE_FMT(", send to died slave, error = %d"), |  | ||||||
|                                                   pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->xError); |                                                   pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->xError); | ||||||
|  |         } else { | ||||||
|  |             // Apply TID field to the frame before send | ||||||
|  |             pucMBTCPFrame[MB_TCP_TID] = (UCHAR)(pxInfo->usTidCnt >> 8U); | ||||||
|  |             pucMBTCPFrame[MB_TCP_TID + 1] = (UCHAR)(pxInfo->usTidCnt & 0xFF); | ||||||
|  |             int xRes = xMBMasterTCPPortWritePoll(pxInfo, pucMBTCPFrame, usTCPLength, MB_TCP_SEND_TIMEOUT_MS); | ||||||
|  |             if (xRes < 0) { | ||||||
|  |                 ESP_LOGE(TAG, MB_SLAVE_FMT(", send data failure, err(errno) = %d(%d)."), | ||||||
|  |                                             pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, xRes, errno); | ||||||
|  |                 bFrameSent = FALSE; | ||||||
|  |                 pxInfo->xError = xRes; | ||||||
|  |             } else { | ||||||
|  |                 bFrameSent = TRUE; | ||||||
|  |                 ESP_LOGD(TAG, MB_SLAVE_FMT(", send data successful: TID=0x%02x, %d (bytes), errno %d"), | ||||||
|  |                                                     pxInfo->xIndex, pxInfo->xSockId, pxInfo->pcIpAddr, pxInfo->usTidCnt, xRes, errno); | ||||||
|  |                 pxInfo->xError = 0; | ||||||
|  |                 pxInfo->usRcvPos = 0; | ||||||
|  |                 if (pxInfo->usTidCnt < (USHRT_MAX - 1)) { | ||||||
|  |                     pxInfo->usTidCnt++; | ||||||
|  |                 } else { | ||||||
|  |                     pxInfo->usTidCnt = (USHORT)(pxInfo->xIndex << 8U); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             pxInfo->xSendTimeStamp = xMBTCPGetTimeStamp(); | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         ESP_LOGD(TAG, "Send data to died slave, address = %d", ucCurSlaveIndex); | ||||||
|     } |     } | ||||||
|     vMBMasterPortTimersRespondTimeoutEnable(); |     vMBMasterPortTimersRespondTimeoutEnable(); | ||||||
|     xMBMasterPortEventPost(EV_MASTER_FRAME_SENT); |     xMBMasterPortEventPost(EV_MASTER_FRAME_SENT); | ||||||
|   | |||||||
| @@ -74,6 +74,7 @@ typedef struct { | |||||||
|     int xError;                 /*!< Socket error */ |     int xError;                 /*!< Socket error */ | ||||||
|     int xRcvErr;                /*!< Socket receive error */ |     int xRcvErr;                /*!< Socket receive error */ | ||||||
|     const char* pcIpAddr;       /*!< TCP/UDP IP address */ |     const char* pcIpAddr;       /*!< TCP/UDP IP address */ | ||||||
|  |     UCHAR ucSlaveAddr;          /*!< Slave short address */ | ||||||
|     UCHAR* pucRcvBuf;           /*!< Receive buffer pointer */ |     UCHAR* pucRcvBuf;           /*!< Receive buffer pointer */ | ||||||
|     USHORT usRcvPos;            /*!< Receive buffer position */ |     USHORT usRcvPos;            /*!< Receive buffer position */ | ||||||
|     int pcPort;                 /*!< TCP/UDP port number */ |     int pcPort;                 /*!< TCP/UDP port number */ | ||||||
| @@ -84,28 +85,37 @@ typedef struct { | |||||||
| } MbSlaveInfo_t; | } MbSlaveInfo_t; | ||||||
|  |  | ||||||
| typedef struct { | typedef struct { | ||||||
|     TaskHandle_t  xMbTcpTaskHandle; /*!< Master TCP/UDP handling task handle */ |     TaskHandle_t  xMbTcpTaskHandle;     /*!< Master TCP/UDP handling task handle */ | ||||||
|     QueueHandle_t xConnectQueue;    /*!< Master connection queue */ |     QueueHandle_t xConnectQueue;        /*!< Master connection queue */ | ||||||
|     USHORT usPort;                  /*!< Master TCP/UDP port number */ |     USHORT usPort;                      /*!< Master TCP/UDP port number */ | ||||||
|     USHORT usMbSlaveInfoCount;      /*!< Master count of connected slaves */ |     USHORT usMbSlaveInfoCount;          /*!< Master count of connected slaves */ | ||||||
|     USHORT ucCurSlaveIndex;         /*!< Master current processing slave index */ |     USHORT ucCurSlaveIndex;             /*!< Master current processing slave index */ | ||||||
|     eMBPortIpVer eMbIpVer;          /*!< Master IP version */ |     eMBPortIpVer eMbIpVer;              /*!< Master IP version */ | ||||||
|     eMBPortProto eMbProto;          /*!< Master protocol type */ |     eMBPortProto eMbProto;              /*!< Master protocol type */ | ||||||
|     void* pvNetIface;               /*!< Master netif interface pointer */ |     void* pvNetIface;                   /*!< Master netif interface pointer */ | ||||||
|     MbSlaveInfo_t** pxMbSlaveInfo;  /*!< Master information structure for each connected slave */ |     MbSlaveInfo_t** pxMbSlaveInfo;      /*!< Master information structure for each connected slave */ | ||||||
|  |     MbSlaveInfo_t* pxMbSlaveCurrInfo;   /*!< Master current slave information */ | ||||||
| } MbPortConfig_t; | } MbPortConfig_t; | ||||||
|  |  | ||||||
|  | typedef struct { | ||||||
|  |     USHORT usIndex;                     /*!< index of the address info */ | ||||||
|  |     const char* pcIPAddr;               /*!< represents the IP address of the slave */ | ||||||
|  |     UCHAR ucSlaveAddr;                  /*!< slave unit ID (UID) field for MBAP frame  */ | ||||||
|  | } MbSlaveAddrInfo_t; | ||||||
|  |  | ||||||
| /* ----------------------- Function prototypes ------------------------------*/ | /* ----------------------- Function prototypes ------------------------------*/ | ||||||
|  |  | ||||||
| // The functions below are used by Modbus controller interface to configure Modbus port. | // The functions below are used by Modbus controller interface to configure Modbus port. | ||||||
| /** | /** | ||||||
|  * Registers slave IP address |  * Registers slave IP address | ||||||
|  * |  * | ||||||
|  |  * @param usIndex index of element in the configuration | ||||||
|  * @param pcIpStr IP address to register |  * @param pcIpStr IP address to register | ||||||
|  |  * @param ucSlaveAddress slave element index | ||||||
|  * |  * | ||||||
|  * @return TRUE if address registered successfully, else FALSE |  * @return TRUE if address registered successfully, else FALSE | ||||||
|  */ |  */ | ||||||
| BOOL xMBTCPPortMasterAddSlaveIp(const CHAR* pcIpStr); | BOOL xMBTCPPortMasterAddSlaveIp(const USHORT usIndex, const CHAR* pcIpStr, UCHAR ucSlaveAddress); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Keeps FSM event handle and mask then wait for Master stack to start |  * Keeps FSM event handle and mask then wait for Master stack to start | ||||||
|   | |||||||
| @@ -32,6 +32,7 @@ | |||||||
|  |  | ||||||
| // Shared pointer to interface structure | // Shared pointer to interface structure | ||||||
| static mb_slave_interface_t* mbs_interface_ptr = NULL; | static mb_slave_interface_t* mbs_interface_ptr = NULL; | ||||||
|  | static const char *TAG = "MB_CONTROLLER_SLAVE"; | ||||||
|  |  | ||||||
| // Modbus task function | // Modbus task function | ||||||
| static void modbus_tcp_slave_task(void *pvParameters) | static void modbus_tcp_slave_task(void *pvParameters) | ||||||
|   | |||||||
| @@ -68,13 +68,13 @@ | |||||||
| /* ----------------------- Defines  -----------------------------------------*/ | /* ----------------------- Defines  -----------------------------------------*/ | ||||||
| #define MB_TCP_DISCONNECT_TIMEOUT       ( CONFIG_FMB_TCP_CONNECTION_TOUT_SEC * 1000000 ) // disconnect timeout in uS | #define MB_TCP_DISCONNECT_TIMEOUT       ( CONFIG_FMB_TCP_CONNECTION_TOUT_SEC * 1000000 ) // disconnect timeout in uS | ||||||
| #define MB_TCP_RESP_TIMEOUT_MS          ( MB_MASTER_TIMEOUT_MS_RESPOND - 2 ) // slave response time limit | #define MB_TCP_RESP_TIMEOUT_MS          ( MB_MASTER_TIMEOUT_MS_RESPOND - 2 ) // slave response time limit | ||||||
| #define MB_TCP_SLAVE_PORT_TAG           "MB_TCP_SLAVE_PORT" |  | ||||||
| #define MB_TCP_NET_LISTEN_BACKLOG       ( SOMAXCONN ) | #define MB_TCP_NET_LISTEN_BACKLOG       ( SOMAXCONN ) | ||||||
|  |  | ||||||
| /* ----------------------- Prototypes ---------------------------------------*/ | /* ----------------------- Prototypes ---------------------------------------*/ | ||||||
| void vMBPortEventClose( void ); | void vMBPortEventClose( void ); | ||||||
|  |  | ||||||
| /* ----------------------- Static variables ---------------------------------*/ | /* ----------------------- Static variables ---------------------------------*/ | ||||||
|  | static const char *TAG = "MB_TCP_SLAVE_PORT"; | ||||||
| static int xListenSock = -1; | static int xListenSock = -1; | ||||||
| static MbSlavePortConfig_t xConfig = { 0 }; | static MbSlavePortConfig_t xConfig = { 0 }; | ||||||
|  |  | ||||||
| @@ -136,14 +136,14 @@ xMBTCPPortInit( USHORT usTCPPort ) | |||||||
|  |  | ||||||
|     xConfig.pxMbClientInfo = calloc(MB_TCP_PORT_MAX_CONN + 1, sizeof(MbClientInfo_t*)); |     xConfig.pxMbClientInfo = calloc(MB_TCP_PORT_MAX_CONN + 1, sizeof(MbClientInfo_t*)); | ||||||
|     if (!xConfig.pxMbClientInfo) { |     if (!xConfig.pxMbClientInfo) { | ||||||
|         ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "TCP client info allocation failure."); |         ESP_LOGE(TAG, "TCP client info allocation failure."); | ||||||
|         return FALSE; |         return FALSE; | ||||||
|     } |     } | ||||||
|     for(int idx = 0; idx < MB_TCP_PORT_MAX_CONN; xConfig.pxMbClientInfo[idx] = NULL, idx++); |     for(int idx = 0; idx < MB_TCP_PORT_MAX_CONN; xConfig.pxMbClientInfo[idx] = NULL, idx++); | ||||||
|  |  | ||||||
|     xConfig.xRespQueueHandle = xMBTCPPortRespQueueCreate(); |     xConfig.xRespQueueHandle = xMBTCPPortRespQueueCreate(); | ||||||
|     if (!xConfig.xRespQueueHandle) { |     if (!xConfig.xRespQueueHandle) { | ||||||
|         ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Response queue allocation failure."); |         ESP_LOGE(TAG, "Response queue allocation failure."); | ||||||
|         return FALSE; |         return FALSE; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -164,10 +164,10 @@ xMBTCPPortInit( USHORT usTCPPort ) | |||||||
|     vTaskSuspend(xConfig.xMbTcpTaskHandle); |     vTaskSuspend(xConfig.xMbTcpTaskHandle); | ||||||
|     if (xErr != pdTRUE) |     if (xErr != pdTRUE) | ||||||
|     { |     { | ||||||
|         ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Server task creation failure."); |         ESP_LOGE(TAG, "Server task creation failure."); | ||||||
|         vTaskDelete(xConfig.xMbTcpTaskHandle); |         vTaskDelete(xConfig.xMbTcpTaskHandle); | ||||||
|     } else { |     } else { | ||||||
|         ESP_LOGI(MB_TCP_SLAVE_PORT_TAG, "Protocol stack initialized."); |         ESP_LOGI(TAG, "Protocol stack initialized."); | ||||||
|         bOkay = TRUE; |         bOkay = TRUE; | ||||||
|     } |     } | ||||||
|     return bOkay; |     return bOkay; | ||||||
| @@ -202,7 +202,7 @@ static int xMBTCPPortAcceptConnection(int xListenSockId, char** pcIPAddr) | |||||||
|     // Accept new socket connection if not active |     // Accept new socket connection if not active | ||||||
|     xSockId = accept(xListenSockId, (struct sockaddr *)&xSrcAddr, &xSize); |     xSockId = accept(xListenSockId, (struct sockaddr *)&xSrcAddr, &xSize); | ||||||
|     if (xSockId < 0) { |     if (xSockId < 0) { | ||||||
|         ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Unable to accept connection: errno=%d", errno); |         ESP_LOGE(TAG, "Unable to accept connection: errno=%d", errno); | ||||||
|         close(xSockId); |         close(xSockId); | ||||||
|     } else { |     } else { | ||||||
|         // Get the sender's ip address as string |         // Get the sender's ip address as string | ||||||
| @@ -214,7 +214,7 @@ static int xMBTCPPortAcceptConnection(int xListenSockId, char** pcIPAddr) | |||||||
|             inet6_ntoa_r(((struct sockaddr_in6 *)&xSrcAddr)->sin6_addr, cAddrStr, sizeof(cAddrStr) - 1); |             inet6_ntoa_r(((struct sockaddr_in6 *)&xSrcAddr)->sin6_addr, cAddrStr, sizeof(cAddrStr) - 1); | ||||||
|         } |         } | ||||||
| #endif | #endif | ||||||
|         ESP_LOGI(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d), accept client connection from address: %s", xSockId, cAddrStr); |         ESP_LOGI(TAG, "Socket (#%d), accept client connection from address: %s", xSockId, cAddrStr); | ||||||
|         pcStr = calloc(1, strlen(cAddrStr) + 1); |         pcStr = calloc(1, strlen(cAddrStr) + 1); | ||||||
|         if (pcStr && pcIPAddr) { |         if (pcStr && pcIPAddr) { | ||||||
|             memcpy(pcStr, cAddrStr, strlen(cAddrStr)); |             memcpy(pcStr, cAddrStr, strlen(cAddrStr)); | ||||||
| @@ -230,11 +230,11 @@ static BOOL xMBTCPPortCloseConnection(MbClientInfo_t* pxInfo) | |||||||
|     MB_PORT_CHECK(pxInfo, FALSE, "Client info is NULL."); |     MB_PORT_CHECK(pxInfo, FALSE, "Client info is NULL."); | ||||||
|  |  | ||||||
|     if (pxInfo->xSockId == -1) { |     if (pxInfo->xSockId == -1) { | ||||||
|         ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Wrong socket info or disconnected socket: %d.", pxInfo->xSockId); |         ESP_LOGE(TAG, "Wrong socket info or disconnected socket: %d.", pxInfo->xSockId); | ||||||
|         return FALSE; |         return FALSE; | ||||||
|     } |     } | ||||||
|     if (shutdown(pxInfo->xSockId, SHUT_RDWR) == -1) { |     if (shutdown(pxInfo->xSockId, SHUT_RDWR) == -1) { | ||||||
|         ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d), shutdown failed: errno %d", pxInfo->xSockId, errno); |         ESP_LOGE(TAG, "Socket (#%d), shutdown failed: errno %d", pxInfo->xSockId, errno); | ||||||
|     } |     } | ||||||
|     close(pxInfo->xSockId); |     close(pxInfo->xSockId); | ||||||
|     pxInfo->xSockId = -1; |     pxInfo->xSockId = -1; | ||||||
| @@ -271,7 +271,7 @@ static int xMBTCPPortRxPoll(MbClientInfo_t* pxClientInfo, ULONG xTimeoutMs) | |||||||
|             } else if (xRet == 0) { |             } else if (xRet == 0) { | ||||||
|                 // timeout occurred |                 // timeout occurred | ||||||
|                 if ((xStartTimeStamp + xTimeoutMs * 1000) > xMBTCPGetTimeStamp()) { |                 if ((xStartTimeStamp + xTimeoutMs * 1000) > xMBTCPGetTimeStamp()) { | ||||||
|                     ESP_LOGD(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d) Read timeout.", pxClientInfo->xSockId); |                     ESP_LOGD(TAG, "Socket (#%d) Read timeout.", pxClientInfo->xSockId); | ||||||
|                     xRet = ERR_TIMEOUT; |                     xRet = ERR_TIMEOUT; | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
| @@ -286,12 +286,12 @@ static int xMBTCPPortRxPoll(MbClientInfo_t* pxClientInfo, ULONG xTimeoutMs) | |||||||
|                                       pxClientInfo->usTCPFrameBytesLeft, MSG_DONTWAIT); |                                       pxClientInfo->usTCPFrameBytesLeft, MSG_DONTWAIT); | ||||||
|                 if (xLength < 0) { |                 if (xLength < 0) { | ||||||
|                     // If an error occurred during receiving |                     // If an error occurred during receiving | ||||||
|                     ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Receive failed: length=%d, errno=%d", xLength, errno); |                     ESP_LOGE(TAG, "Receive failed: length=%d, errno=%d", xLength, errno); | ||||||
|                     xRet = (err_t)xLength; |                     xRet = (err_t)xLength; | ||||||
|                     break; |                     break; | ||||||
|                 } else if (xLength == 0) { |                 } else if (xLength == 0) { | ||||||
|                     // Socket connection closed |                     // Socket connection closed | ||||||
|                     ESP_LOGD(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d)(%s), connection closed.", |                     ESP_LOGD(TAG, "Socket (#%d)(%s), connection closed.", | ||||||
|                                                         pxClientInfo->xSockId, pxClientInfo->pcIpAddr); |                                                         pxClientInfo->xSockId, pxClientInfo->pcIpAddr); | ||||||
|                     xRet = ERR_CLSD; |                     xRet = ERR_CLSD; | ||||||
|                     break; |                     break; | ||||||
| @@ -309,14 +309,14 @@ static int xMBTCPPortRxPoll(MbClientInfo_t* pxClientInfo, ULONG xTimeoutMs) | |||||||
|                             pxClientInfo->usTCPFrameBytesLeft = xLength + MB_TCP_UID - pxClientInfo->usTCPBufPos; |                             pxClientInfo->usTCPFrameBytesLeft = xLength + MB_TCP_UID - pxClientInfo->usTCPBufPos; | ||||||
|                         } else if (pxClientInfo->usTCPBufPos == (MB_TCP_UID + xLength)) { |                         } else if (pxClientInfo->usTCPBufPos == (MB_TCP_UID + xLength)) { | ||||||
| #if MB_TCP_DEBUG | #if MB_TCP_DEBUG | ||||||
|                             prvvMBTCPLogFrame(MB_TCP_SLAVE_PORT_TAG, (UCHAR*)&pxClientInfo->pucTCPBuf[0], pxClientInfo->usTCPBufPos); |                             prvvMBTCPLogFrame(TAG, (UCHAR*)&pxClientInfo->pucTCPBuf[0], pxClientInfo->usTCPBufPos); | ||||||
| #endif | #endif | ||||||
|                             // Copy TID field from incoming packet |                             // Copy TID field from incoming packet | ||||||
|                             pxClientInfo->usTidCnt = MB_TCP_GET_FIELD(pxClientInfo->pucTCPBuf, MB_TCP_TID); |                             pxClientInfo->usTidCnt = MB_TCP_GET_FIELD(pxClientInfo->pucTCPBuf, MB_TCP_TID); | ||||||
|                             xRet = pxClientInfo->usTCPBufPos; |                             xRet = pxClientInfo->usTCPBufPos; | ||||||
|                             break; |                             break; | ||||||
|                         } else if ((pxClientInfo->usTCPBufPos + xLength) >= MB_TCP_BUF_SIZE) { |                         } else if ((pxClientInfo->usTCPBufPos + xLength) >= MB_TCP_BUF_SIZE) { | ||||||
|                             ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Incorrect buffer received (%u) bytes.", xLength); |                             ESP_LOGE(TAG, "Incorrect buffer received (%u) bytes.", xLength); | ||||||
|                             // This should not happen. We can't deal with such a client and |                             // This should not happen. We can't deal with such a client and | ||||||
|                             // drop the connection for security reasons. |                             // drop the connection for security reasons. | ||||||
|                             xRet = ERR_BUF; |                             xRet = ERR_BUF; | ||||||
| @@ -401,7 +401,7 @@ vMBTCPPortBindAddr(const CHAR* pcBindIp) | |||||||
|         { |         { | ||||||
|             if (listen(xListenSockFd, MB_TCP_NET_LISTEN_BACKLOG) != 0) |             if (listen(xListenSockFd, MB_TCP_NET_LISTEN_BACKLOG) != 0) | ||||||
|             { |             { | ||||||
|                 ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Error occurred during listen: errno=%d", errno); |                 ESP_LOGE(TAG, "Error occurred during listen: errno=%d", errno); | ||||||
|                 close(xListenSockFd); |                 close(xListenSockFd); | ||||||
|                 xListenSockFd = -1; |                 xListenSockFd = -1; | ||||||
|                 continue; |                 continue; | ||||||
| @@ -409,7 +409,7 @@ vMBTCPPortBindAddr(const CHAR* pcBindIp) | |||||||
|         } |         } | ||||||
|         // Bind was successful |         // Bind was successful | ||||||
|         pcStr = (pxCurAddr->ai_canonname == NULL) ? (CHAR*)"\0" : pxCurAddr->ai_canonname; |         pcStr = (pxCurAddr->ai_canonname == NULL) ? (CHAR*)"\0" : pxCurAddr->ai_canonname; | ||||||
|         ESP_LOGI(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d), listener %s on port: %d, errno=%d", |         ESP_LOGI(TAG, "Socket (#%d), listener %s on port: %d, errno=%d", | ||||||
|                                             xListenSockFd, pcStr, xConfig.usPort, errno); |                                             xListenSockFd, pcStr, xConfig.usPort, errno); | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| @@ -475,11 +475,11 @@ static void vMBTCPPortServerTask(void *pvParameters) | |||||||
|             xErr = select(xMaxSd + 1 , &xReadSet , NULL , NULL , NULL); |             xErr = select(xMaxSd + 1 , &xReadSet , NULL , NULL , NULL); | ||||||
|             if ((xErr < 0) && (errno != EINTR)) { |             if ((xErr < 0) && (errno != EINTR)) { | ||||||
|                 // error occurred during wait for read |                 // error occurred during wait for read | ||||||
|                 ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "select() errno = %d.", errno); |                 ESP_LOGE(TAG, "select() errno = %d.", errno); | ||||||
|                 continue; |                 continue; | ||||||
|             } else if (xErr == 0) { |             } else if (xErr == 0) { | ||||||
|                 // If timeout happened, something is wrong |                 // If timeout happened, something is wrong | ||||||
|                 ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "select() timeout, errno = %d.", errno); |                 ESP_LOGE(TAG, "select() timeout, errno = %d.", errno); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             // If something happened on the master socket, then its an incoming connection. |             // If something happened on the master socket, then its an incoming connection. | ||||||
| @@ -495,21 +495,21 @@ static void vMBTCPPortServerTask(void *pvParameters) | |||||||
|                 // if request for new connection but no space left |                 // if request for new connection but no space left | ||||||
|                 if (pxClientInfo != NULL) { |                 if (pxClientInfo != NULL) { | ||||||
|                     if (xConfig.pxMbClientInfo[MB_TCP_PORT_MAX_CONN] == NULL) { |                     if (xConfig.pxMbClientInfo[MB_TCP_PORT_MAX_CONN] == NULL) { | ||||||
|                         ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Fail to accept connection %d, only %d connections supported.", i + 1, MB_TCP_PORT_MAX_CONN); |                         ESP_LOGE(TAG, "Fail to accept connection %d, only %d connections supported.", i + 1, MB_TCP_PORT_MAX_CONN); | ||||||
|                     } |                     } | ||||||
|                     xConfig.pxMbClientInfo[MB_TCP_PORT_MAX_CONN] = pxClientInfo; // set last connection info |                     xConfig.pxMbClientInfo[MB_TCP_PORT_MAX_CONN] = pxClientInfo; // set last connection info | ||||||
|                 } else { |                 } else { | ||||||
|                     // allocate memory for new client info |                     // allocate memory for new client info | ||||||
|                     pxClientInfo = calloc(1, sizeof(MbClientInfo_t)); |                     pxClientInfo = calloc(1, sizeof(MbClientInfo_t)); | ||||||
|                     if (!pxClientInfo) { |                     if (!pxClientInfo) { | ||||||
|                         ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Client info allocation fail."); |                         ESP_LOGE(TAG, "Client info allocation fail."); | ||||||
|                         vMBTCPPortFreeClientInfo(pxClientInfo); |                         vMBTCPPortFreeClientInfo(pxClientInfo); | ||||||
|                         pxClientInfo = NULL; |                         pxClientInfo = NULL; | ||||||
|                     } else { |                     } else { | ||||||
|                         // Accept new client connection |                         // Accept new client connection | ||||||
|                         pxClientInfo->xSockId = xMBTCPPortAcceptConnection(xListenSock, &pcClientIp); |                         pxClientInfo->xSockId = xMBTCPPortAcceptConnection(xListenSock, &pcClientIp); | ||||||
|                         if (pxClientInfo->xSockId < 0) { |                         if (pxClientInfo->xSockId < 0) { | ||||||
|                             ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Fail to accept connection for client %d.", (xConfig.usClientCount - 1)); |                             ESP_LOGE(TAG, "Fail to accept connection for client %d.", (xConfig.usClientCount - 1)); | ||||||
|                             // Accept connection fail, then free client info and continue polling. |                             // Accept connection fail, then free client info and continue polling. | ||||||
|                             vMBTCPPortFreeClientInfo(pxClientInfo); |                             vMBTCPPortFreeClientInfo(pxClientInfo); | ||||||
|                             pxClientInfo = NULL; |                             pxClientInfo = NULL; | ||||||
| @@ -517,7 +517,7 @@ static void vMBTCPPortServerTask(void *pvParameters) | |||||||
|                         } |                         } | ||||||
|                         pxClientInfo->pucTCPBuf = calloc(MB_TCP_BUF_SIZE, sizeof(UCHAR)); |                         pxClientInfo->pucTCPBuf = calloc(MB_TCP_BUF_SIZE, sizeof(UCHAR)); | ||||||
|                         if (!pxClientInfo->pucTCPBuf) { |                         if (!pxClientInfo->pucTCPBuf) { | ||||||
|                             ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Fail to allocate buffer for client %d.", (xConfig.usClientCount - 1)); |                             ESP_LOGE(TAG, "Fail to allocate buffer for client %d.", (xConfig.usClientCount - 1)); | ||||||
|                             vMBTCPPortFreeClientInfo(pxClientInfo); |                             vMBTCPPortFreeClientInfo(pxClientInfo); | ||||||
|                             pxClientInfo = NULL; |                             pxClientInfo = NULL; | ||||||
|                             continue; |                             continue; | ||||||
| @@ -551,17 +551,17 @@ static void vMBTCPPortServerTask(void *pvParameters) | |||||||
|                                 switch(xErr) |                                 switch(xErr) | ||||||
|                                 { |                                 { | ||||||
|                                     case ERR_TIMEOUT: |                                     case ERR_TIMEOUT: | ||||||
|                                         ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d)(%s), data receive timeout, time[us]: %d, close active connection.", |                                         ESP_LOGE(TAG, "Socket (#%d)(%s), data receive timeout, time[us]: %d, close active connection.", | ||||||
|                                                                             pxClientInfo->xSockId, pxClientInfo->pcIpAddr, |                                                                             pxClientInfo->xSockId, pxClientInfo->pcIpAddr, | ||||||
|                                                                             (int)(xTimeStamp - pxClientInfo->xRecvTimeStamp)); |                                                                             (int)(xTimeStamp - pxClientInfo->xRecvTimeStamp)); | ||||||
|                                         break; |                                         break; | ||||||
|                                     case ERR_CLSD: |                                     case ERR_CLSD: | ||||||
|                                         ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d)(%s), connection closed by peer.", |                                         ESP_LOGE(TAG, "Socket (#%d)(%s), connection closed by peer.", | ||||||
|                                                                             pxClientInfo->xSockId, pxClientInfo->pcIpAddr); |                                                                             pxClientInfo->xSockId, pxClientInfo->pcIpAddr); | ||||||
|                                         break; |                                         break; | ||||||
|                                     case ERR_BUF: |                                     case ERR_BUF: | ||||||
|                                     default: |                                     default: | ||||||
|                                         ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d)(%s), read data error: %d", |                                         ESP_LOGE(TAG, "Socket (#%d)(%s), read data error: %d", | ||||||
|                                                                             pxClientInfo->xSockId, pxClientInfo->pcIpAddr, xErr); |                                                                             pxClientInfo->xSockId, pxClientInfo->pcIpAddr, xErr); | ||||||
|                                         break; |                                         break; | ||||||
|                                 } |                                 } | ||||||
| @@ -586,26 +586,26 @@ static void vMBTCPPortServerTask(void *pvParameters) | |||||||
|                                 // Complete frame received, inform state machine to process frame |                                 // Complete frame received, inform state machine to process frame | ||||||
|                                 xMBPortEventPost(EV_FRAME_RECEIVED); |                                 xMBPortEventPost(EV_FRAME_RECEIVED); | ||||||
|  |  | ||||||
|                                 ESP_LOGD(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d)(%s), get packet TID=0x%X, %d bytes.", |                                 ESP_LOGD(TAG, "Socket (#%d)(%s), get packet TID=0x%X, %d bytes.", | ||||||
|                                                                     pxClientInfo->xSockId, pxClientInfo->pcIpAddr, |                                                                     pxClientInfo->xSockId, pxClientInfo->pcIpAddr, | ||||||
|                                                                     pxClientInfo->usTidCnt, xErr); |                                                                     pxClientInfo->usTidCnt, xErr); | ||||||
|  |  | ||||||
|                                 // Wait while response is not processed by stack by timeout |                                 // Wait while response is not processed by stack by timeout | ||||||
|                                 UCHAR* pucSentBuffer = vxMBTCPPortRespQueueRecv(xConfig.xRespQueueHandle); |                                 UCHAR* pucSentBuffer = vxMBTCPPortRespQueueRecv(xConfig.xRespQueueHandle); | ||||||
|                                 if (pucSentBuffer == NULL) { |                                 if (pucSentBuffer == NULL) { | ||||||
|                                     ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Response time exceeds configured %d [ms], ignore packet.", |                                     ESP_LOGE(TAG, "Response time exceeds configured %d [ms], ignore packet.", | ||||||
|                                                                         MB_TCP_RESP_TIMEOUT_MS); |                                                                         MB_TCP_RESP_TIMEOUT_MS); | ||||||
|                                 } else  { |                                 } else  { | ||||||
|                                     USHORT usSentTid = MB_TCP_GET_FIELD(pucSentBuffer, MB_TCP_TID); |                                     USHORT usSentTid = MB_TCP_GET_FIELD(pucSentBuffer, MB_TCP_TID); | ||||||
|                                     if (usSentTid != pxClientInfo->usTidCnt) { |                                     if (usSentTid != pxClientInfo->usTidCnt) { | ||||||
|                                         ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Sent TID(%x) != Recv TID(%x), ignore packet.", |                                         ESP_LOGE(TAG, "Sent TID(%x) != Recv TID(%x), ignore packet.", | ||||||
|                                                                             usSentTid, pxClientInfo->usTidCnt); |                                                                             usSentTid, pxClientInfo->usTidCnt); | ||||||
|                                     } |                                     } | ||||||
|                                 } |                                 } | ||||||
|  |  | ||||||
|                                 // Get time stamp of last data update |                                 // Get time stamp of last data update | ||||||
|                                 pxClientInfo->xSendTimeStamp = xMBTCPGetTimeStamp(); |                                 pxClientInfo->xSendTimeStamp = xMBTCPGetTimeStamp(); | ||||||
|                                 ESP_LOGD(MB_TCP_SLAVE_PORT_TAG, "Client %d, Socket(#%d), processing time = %d (us).", |                                 ESP_LOGD(TAG, "Client %d, Socket(#%d), processing time = %d (us).", | ||||||
|                                                             pxClientInfo->xIndex, pxClientInfo->xSockId, |                                                             pxClientInfo->xIndex, pxClientInfo->xSockId, | ||||||
|                                                             (int)(pxClientInfo->xSendTimeStamp - pxClientInfo->xRecvTimeStamp)); |                                                             (int)(pxClientInfo->xSendTimeStamp - pxClientInfo->xRecvTimeStamp)); | ||||||
|                             } |                             } | ||||||
| @@ -614,7 +614,7 @@ static void vMBTCPPortServerTask(void *pvParameters) | |||||||
|                                 // client is not ready to be read |                                 // client is not ready to be read | ||||||
|                                 int64_t xTime = xMBTCPGetTimeStamp() - pxClientInfo->xRecvTimeStamp; |                                 int64_t xTime = xMBTCPGetTimeStamp() - pxClientInfo->xRecvTimeStamp; | ||||||
|                                 if (xTime > MB_TCP_DISCONNECT_TIMEOUT) { |                                 if (xTime > MB_TCP_DISCONNECT_TIMEOUT) { | ||||||
|                                     ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Client %d, Socket(#%d) do not answer for %d (us). Drop connection...", |                                     ESP_LOGE(TAG, "Client %d, Socket(#%d) do not answer for %d (us). Drop connection...", | ||||||
|                                                                     pxClientInfo->xIndex, pxClientInfo->xSockId, (int)(xTime)); |                                                                     pxClientInfo->xIndex, pxClientInfo->xSockId, (int)(xTime)); | ||||||
|                                     xMBTCPPortCloseConnection(pxClientInfo); |                                     xMBTCPPortCloseConnection(pxClientInfo); | ||||||
|  |  | ||||||
| @@ -623,7 +623,7 @@ static void vMBTCPPortServerTask(void *pvParameters) | |||||||
|                                     xConfig.pxMbClientInfo[i] = NULL; |                                     xConfig.pxMbClientInfo[i] = NULL; | ||||||
|                                 } |                                 } | ||||||
|                             } else { |                             } else { | ||||||
|                                 ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Client %d is disconnected.", i); |                                 ESP_LOGE(TAG, "Client %d is disconnected.", i); | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                     } // if ((pxClientInfo != NULL) |                     } // if ((pxClientInfo != NULL) | ||||||
| @@ -693,7 +693,7 @@ xMBTCPPortSendResponse( UCHAR * pucMBTCPFrame, USHORT usTCPLength ) | |||||||
|         // Check if socket writable |         // Check if socket writable | ||||||
|         xErr = select(xConfig.pxCurClientInfo->xSockId + 1, NULL, &xWriteSet, &xErrorSet, &xTimeVal); |         xErr = select(xConfig.pxCurClientInfo->xSockId + 1, NULL, &xWriteSet, &xErrorSet, &xTimeVal); | ||||||
|         if ((xErr == -1) || FD_ISSET(xConfig.pxCurClientInfo->xSockId, &xErrorSet)) { |         if ((xErr == -1) || FD_ISSET(xConfig.pxCurClientInfo->xSockId, &xErrorSet)) { | ||||||
|             ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket(#%d) , send select() error = %d.", |             ESP_LOGE(TAG, "Socket(#%d) , send select() error = %d.", | ||||||
|                     xConfig.pxCurClientInfo->xSockId, errno); |                     xConfig.pxCurClientInfo->xSockId, errno); | ||||||
|             return FALSE; |             return FALSE; | ||||||
|         } |         } | ||||||
| @@ -705,7 +705,7 @@ xMBTCPPortSendResponse( UCHAR * pucMBTCPFrame, USHORT usTCPLength ) | |||||||
|         // Write message into socket and disable Nagle's algorithm |         // Write message into socket and disable Nagle's algorithm | ||||||
|         xErr = send(xConfig.pxCurClientInfo->xSockId, pucMBTCPFrame, usTCPLength, TCP_NODELAY); |         xErr = send(xConfig.pxCurClientInfo->xSockId, pucMBTCPFrame, usTCPLength, TCP_NODELAY); | ||||||
|         if (xErr < 0) { |         if (xErr < 0) { | ||||||
|             ESP_LOGE(MB_TCP_SLAVE_PORT_TAG, "Socket(#%d), fail to send data, errno = %d", |             ESP_LOGE(TAG, "Socket(#%d), fail to send data, errno = %d", | ||||||
|                     xConfig.pxCurClientInfo->xSockId, errno); |                     xConfig.pxCurClientInfo->xSockId, errno); | ||||||
|             xConfig.pxCurClientInfo->xError = xErr; |             xConfig.pxCurClientInfo->xError = xErr; | ||||||
|         } else { |         } else { | ||||||
| @@ -713,7 +713,7 @@ xMBTCPPortSendResponse( UCHAR * pucMBTCPFrame, USHORT usTCPLength ) | |||||||
|             vxMBTCPPortRespQueueSend(xConfig.xRespQueueHandle, (void*)pucMBTCPFrame); |             vxMBTCPPortRespQueueSend(xConfig.xRespQueueHandle, (void*)pucMBTCPFrame); | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         ESP_LOGD(MB_TCP_SLAVE_PORT_TAG, "Port is not active. Release lock."); |         ESP_LOGD(TAG, "Port is not active. Release lock."); | ||||||
|         vxMBTCPPortRespQueueSend(xConfig.xRespQueueHandle, (void*)pucMBTCPFrame); |         vxMBTCPPortRespQueueSend(xConfig.xRespQueueHandle, (void*)pucMBTCPFrame); | ||||||
|     } |     } | ||||||
|     return bFrameSent; |     return bFrameSent; | ||||||
|   | |||||||
| @@ -38,14 +38,6 @@ | |||||||
| #define POLL_TIMEOUT_MS                 (1) | #define POLL_TIMEOUT_MS                 (1) | ||||||
| #define POLL_TIMEOUT_TICS               (POLL_TIMEOUT_MS / portTICK_RATE_MS) | #define POLL_TIMEOUT_TICS               (POLL_TIMEOUT_MS / portTICK_RATE_MS) | ||||||
|  |  | ||||||
| #define MASTER_TAG "MASTER_TEST" |  | ||||||
|  |  | ||||||
| #define MASTER_CHECK(a, ret_val, str, ...) \ |  | ||||||
|     if (!(a)) { \ |  | ||||||
|         ESP_LOGE(MASTER_TAG, "%s(%u): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ |  | ||||||
|         return (ret_val); \ |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| // The macro to get offset for parameter in the appropriate structure | // The macro to get offset for parameter in the appropriate structure | ||||||
| #define HOLD_OFFSET(field) ((uint16_t)(offsetof(holding_reg_params_t, field) + 1)) | #define HOLD_OFFSET(field) ((uint16_t)(offsetof(holding_reg_params_t, field) + 1)) | ||||||
| #define INPUT_OFFSET(field) ((uint16_t)(offsetof(input_reg_params_t, field) + 1)) | #define INPUT_OFFSET(field) ((uint16_t)(offsetof(input_reg_params_t, field) + 1)) | ||||||
| @@ -57,6 +49,8 @@ | |||||||
| // Options can be used as bit masks or parameter limits | // Options can be used as bit masks or parameter limits | ||||||
| #define OPTS(min_val, max_val, step_val) { .opt1 = min_val, .opt2 = max_val, .opt3 = step_val } | #define OPTS(min_val, max_val, step_val) { .opt1 = min_val, .opt2 = max_val, .opt3 = step_val } | ||||||
|  |  | ||||||
|  | static const char *TAG = "MASTER_TEST"; | ||||||
|  |  | ||||||
| // Enumeration of modbus device addresses accessed by master device | // Enumeration of modbus device addresses accessed by master device | ||||||
| enum { | enum { | ||||||
|     MB_DEVICE_ADDR1 = 1 // Only one slave device used for the test (add other slave addresses here) |     MB_DEVICE_ADDR1 = 1 // Only one slave device used for the test (add other slave addresses here) | ||||||
| @@ -135,7 +129,7 @@ static void* master_get_param_data(const mb_parameter_descriptor_t* param_descri | |||||||
|                break; |                break; | ||||||
|        } |        } | ||||||
|     } else { |     } else { | ||||||
|         ESP_LOGE(MASTER_TAG, "Wrong parameter offset for CID #%d", param_descriptor->cid); |         ESP_LOGE(TAG, "Wrong parameter offset for CID #%d", param_descriptor->cid); | ||||||
|         assert(instance_ptr != NULL); |         assert(instance_ptr != NULL); | ||||||
|     } |     } | ||||||
|     return instance_ptr; |     return instance_ptr; | ||||||
| @@ -149,7 +143,7 @@ static void master_operation_func(void *arg) | |||||||
|     bool alarm_state = false; |     bool alarm_state = false; | ||||||
|     const mb_parameter_descriptor_t* param_descriptor = NULL; |     const mb_parameter_descriptor_t* param_descriptor = NULL; | ||||||
|  |  | ||||||
|     ESP_LOGI(MASTER_TAG, "Start modbus test..."); |     ESP_LOGI(TAG, "Start modbus test..."); | ||||||
|  |  | ||||||
|     for(uint16_t retry = 0; retry <= MASTER_MAX_RETRY && (!alarm_state); retry++) { |     for(uint16_t retry = 0; retry <= MASTER_MAX_RETRY && (!alarm_state); retry++) { | ||||||
|         // Read all found characteristics from slave(s) |         // Read all found characteristics from slave(s) | ||||||
| @@ -169,7 +163,7 @@ static void master_operation_func(void *arg) | |||||||
|                     err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key, |                     err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key, | ||||||
|                                                                             (uint8_t*)temp_data_ptr, &type); |                                                                             (uint8_t*)temp_data_ptr, &type); | ||||||
|                     if (err == ESP_OK) { |                     if (err == ESP_OK) { | ||||||
|                         ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = (0x%08x) read successful.", |                         ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%08x) read successful.", | ||||||
|                                                  param_descriptor->cid, |                                                  param_descriptor->cid, | ||||||
|                                                  (char*)param_descriptor->param_key, |                                                  (char*)param_descriptor->param_key, | ||||||
|                                                  (char*)param_descriptor->param_units, |                                                  (char*)param_descriptor->param_units, | ||||||
| @@ -181,13 +175,13 @@ static void master_operation_func(void *arg) | |||||||
|                             err = mbc_master_set_parameter(cid, (char*)param_descriptor->param_key, |                             err = mbc_master_set_parameter(cid, (char*)param_descriptor->param_key, | ||||||
|                                                               (uint8_t*)temp_data_ptr, &type); |                                                               (uint8_t*)temp_data_ptr, &type); | ||||||
|                             if (err == ESP_OK) { |                             if (err == ESP_OK) { | ||||||
|                                 ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = (0x%08x), write successful.", |                                 ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%08x), write successful.", | ||||||
|                                                             param_descriptor->cid, |                                                             param_descriptor->cid, | ||||||
|                                                             (char*)param_descriptor->param_key, |                                                             (char*)param_descriptor->param_key, | ||||||
|                                                             (char*)param_descriptor->param_units, |                                                             (char*)param_descriptor->param_units, | ||||||
|                                                             *(uint32_t*)temp_data_ptr); |                                                             *(uint32_t*)temp_data_ptr); | ||||||
|                             } else { |                             } else { | ||||||
|                                 ESP_LOGE(MASTER_TAG, "Characteristic #%d (%s) write fail, err = 0x%x (%s).", |                                 ESP_LOGE(TAG, "Characteristic #%d (%s) write fail, err = 0x%x (%s).", | ||||||
|                                                         param_descriptor->cid, |                                                         param_descriptor->cid, | ||||||
|                                                         (char*)param_descriptor->param_key, |                                                         (char*)param_descriptor->param_key, | ||||||
|                                                         (int)err, |                                                         (int)err, | ||||||
| @@ -195,7 +189,7 @@ static void master_operation_func(void *arg) | |||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                     } else { |                     } else { | ||||||
|                         ESP_LOGE(MASTER_TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).", |                         ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).", | ||||||
|                                                 param_descriptor->cid, |                                                 param_descriptor->cid, | ||||||
|                                                 (char*)param_descriptor->param_key, |                                                 (char*)param_descriptor->param_key, | ||||||
|                                                 (int)err, |                                                 (int)err, | ||||||
| @@ -208,7 +202,7 @@ static void master_operation_func(void *arg) | |||||||
|                         *(float*)temp_data_ptr = value; |                         *(float*)temp_data_ptr = value; | ||||||
|                         if ((param_descriptor->mb_param_type == MB_PARAM_HOLDING) || |                         if ((param_descriptor->mb_param_type == MB_PARAM_HOLDING) || | ||||||
|                             (param_descriptor->mb_param_type == MB_PARAM_INPUT)) { |                             (param_descriptor->mb_param_type == MB_PARAM_INPUT)) { | ||||||
|                             ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = %f (0x%x) read successful.", |                             ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = %f (0x%x) read successful.", | ||||||
|                                             param_descriptor->cid, |                                             param_descriptor->cid, | ||||||
|                                             (char*)param_descriptor->param_key, |                                             (char*)param_descriptor->param_key, | ||||||
|                                             (char*)param_descriptor->param_units, |                                             (char*)param_descriptor->param_units, | ||||||
| @@ -222,7 +216,7 @@ static void master_operation_func(void *arg) | |||||||
|                         } else { |                         } else { | ||||||
|                             uint16_t state = *(uint16_t*)temp_data_ptr; |                             uint16_t state = *(uint16_t*)temp_data_ptr; | ||||||
|                             const char* rw_str = (state & param_descriptor->param_opts.opt1) ? "ON" : "OFF"; |                             const char* rw_str = (state & param_descriptor->param_opts.opt1) ? "ON" : "OFF"; | ||||||
|                             ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = %s (0x%x) read successful.", |                             ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = %s (0x%x) read successful.", | ||||||
|                                             param_descriptor->cid, |                                             param_descriptor->cid, | ||||||
|                                             (char*)param_descriptor->param_key, |                                             (char*)param_descriptor->param_key, | ||||||
|                                             (char*)param_descriptor->param_units, |                                             (char*)param_descriptor->param_units, | ||||||
| @@ -234,7 +228,7 @@ static void master_operation_func(void *arg) | |||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                     } else { |                     } else { | ||||||
|                         ESP_LOGE(MASTER_TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).", |                         ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).", | ||||||
|                                             param_descriptor->cid, |                                             param_descriptor->cid, | ||||||
|                                             (char*)param_descriptor->param_key, |                                             (char*)param_descriptor->param_key, | ||||||
|                                             (int)err, |                                             (int)err, | ||||||
| @@ -248,13 +242,13 @@ static void master_operation_func(void *arg) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (alarm_state) { |     if (alarm_state) { | ||||||
|         ESP_LOGI(MASTER_TAG, "Alarm triggered by cid #%d.", |         ESP_LOGI(TAG, "Alarm triggered by cid #%d.", | ||||||
|                                         param_descriptor->cid); |                                         param_descriptor->cid); | ||||||
|     } else { |     } else { | ||||||
|         ESP_LOGE(MASTER_TAG, "Alarm is not triggered after %d retries.", |         ESP_LOGE(TAG, "Alarm is not triggered after %d retries.", | ||||||
|                                         MASTER_MAX_RETRY); |                                         MASTER_MAX_RETRY); | ||||||
|     } |     } | ||||||
|     ESP_LOGI(MASTER_TAG, "Destroy master..."); |     ESP_LOGI(TAG, "Destroy master..."); | ||||||
|     ESP_ERROR_CHECK(mbc_master_destroy()); |     ESP_ERROR_CHECK(mbc_master_destroy()); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -275,13 +269,13 @@ static esp_err_t master_init(void) | |||||||
|     void* master_handler = NULL; |     void* master_handler = NULL; | ||||||
|  |  | ||||||
|     esp_err_t err = mbc_master_init(MB_PORT_SERIAL_MASTER, &master_handler); |     esp_err_t err = mbc_master_init(MB_PORT_SERIAL_MASTER, &master_handler); | ||||||
|     MASTER_CHECK((master_handler != NULL), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((master_handler != NULL), ESP_ERR_INVALID_STATE, TAG, | ||||||
|                                 "mb controller initialization fail."); |                                 "mb controller initialization fail."); | ||||||
|     MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG, | ||||||
|                             "mb controller initialization fail, returns(0x%x).", |                             "mb controller initialization fail, returns(0x%x).", | ||||||
|                             (uint32_t)err); |                             (uint32_t)err); | ||||||
|     err = mbc_master_setup((void*)&comm); |     err = mbc_master_setup((void*)&comm); | ||||||
|     MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG, | ||||||
|                             "mb controller setup fail, returns(0x%x).", |                             "mb controller setup fail, returns(0x%x).", | ||||||
|                             (uint32_t)err); |                             (uint32_t)err); | ||||||
|  |  | ||||||
| @@ -290,23 +284,23 @@ static esp_err_t master_init(void) | |||||||
|                               CONFIG_MB_UART_RTS, UART_PIN_NO_CHANGE); |                               CONFIG_MB_UART_RTS, UART_PIN_NO_CHANGE); | ||||||
|  |  | ||||||
|     err = mbc_master_start(); |     err = mbc_master_start(); | ||||||
|     MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG, | ||||||
|                             "mb controller start fail, returns(0x%x).", |                             "mb controller start fail, returns(0x%x).", | ||||||
|                             (uint32_t)err); |                             (uint32_t)err); | ||||||
|  |  | ||||||
|     MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG, | ||||||
|             "mb serial set pin failure, uart_set_pin() returned (0x%x).", (uint32_t)err); |             "mb serial set pin failure, uart_set_pin() returned (0x%x).", (uint32_t)err); | ||||||
|     // Set driver mode to Half Duplex |     // Set driver mode to Half Duplex | ||||||
|     err = uart_set_mode(MB_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX); |     err = uart_set_mode(MB_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX); | ||||||
|     MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG, | ||||||
|             "mb serial set mode failure, uart_set_mode() returned (0x%x).", (uint32_t)err); |             "mb serial set mode failure, uart_set_mode() returned (0x%x).", (uint32_t)err); | ||||||
|  |  | ||||||
|     vTaskDelay(5); |     vTaskDelay(5); | ||||||
|     err = mbc_master_set_descriptor(&device_parameters[0], num_device_parameters); |     err = mbc_master_set_descriptor(&device_parameters[0], num_device_parameters); | ||||||
|     MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG, | ||||||
|                                 "mb controller set descriptor fail, returns(0x%x).", |                                 "mb controller set descriptor fail, returns(0x%x).", | ||||||
|                                 (uint32_t)err); |                                 (uint32_t)err); | ||||||
|     ESP_LOGI(MASTER_TAG, "Modbus master stack initialized..."); |     ESP_LOGI(TAG, "Modbus master stack initialized..."); | ||||||
|     return err; |     return err; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -40,7 +40,7 @@ | |||||||
|                                                 | MB_EVENT_COILS_WR) |                                                 | MB_EVENT_COILS_WR) | ||||||
| #define MB_READ_WRITE_MASK                  (MB_READ_MASK | MB_WRITE_MASK) | #define MB_READ_WRITE_MASK                  (MB_READ_MASK | MB_WRITE_MASK) | ||||||
|  |  | ||||||
| static const char *SLAVE_TAG = "SLAVE_TEST"; | static const char *TAG = "SLAVE_TEST"; | ||||||
|  |  | ||||||
| static portMUX_TYPE param_lock = portMUX_INITIALIZER_UNLOCKED; | static portMUX_TYPE param_lock = portMUX_INITIALIZER_UNLOCKED; | ||||||
|  |  | ||||||
| @@ -92,7 +92,7 @@ void app_main(void) | |||||||
|     mb_register_area_descriptor_t reg_area; // Modbus register area descriptor structure |     mb_register_area_descriptor_t reg_area; // Modbus register area descriptor structure | ||||||
|  |  | ||||||
|     // Set UART log level |     // Set UART log level | ||||||
|     esp_log_level_set(SLAVE_TAG, ESP_LOG_INFO); |     esp_log_level_set(TAG, ESP_LOG_INFO); | ||||||
|     void* mbc_slave_handler = NULL; |     void* mbc_slave_handler = NULL; | ||||||
|  |  | ||||||
|     ESP_ERROR_CHECK(mbc_slave_init(MB_PORT_SERIAL_SLAVE, &mbc_slave_handler)); // Initialization of Modbus controller |     ESP_ERROR_CHECK(mbc_slave_init(MB_PORT_SERIAL_SLAVE, &mbc_slave_handler)); // Initialization of Modbus controller | ||||||
| @@ -166,8 +166,8 @@ void app_main(void) | |||||||
|     // Set UART driver mode to Half Duplex |     // Set UART driver mode to Half Duplex | ||||||
|     ESP_ERROR_CHECK(uart_set_mode(MB_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX)); |     ESP_ERROR_CHECK(uart_set_mode(MB_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX)); | ||||||
|  |  | ||||||
|     ESP_LOGI(SLAVE_TAG, "Modbus slave stack initialized."); |     ESP_LOGI(TAG, "Modbus slave stack initialized."); | ||||||
|     ESP_LOGI(SLAVE_TAG, "Start modbus test..."); |     ESP_LOGI(TAG, "Start modbus test..."); | ||||||
|  |  | ||||||
|     // The cycle below will be terminated when parameter holdingRegParams.dataChan0 |     // The cycle below will be terminated when parameter holdingRegParams.dataChan0 | ||||||
|     // incremented each access cycle reaches the CHAN_DATA_MAX_VAL value. |     // incremented each access cycle reaches the CHAN_DATA_MAX_VAL value. | ||||||
| @@ -180,7 +180,7 @@ void app_main(void) | |||||||
|         if(event & (MB_EVENT_HOLDING_REG_WR | MB_EVENT_HOLDING_REG_RD)) { |         if(event & (MB_EVENT_HOLDING_REG_WR | MB_EVENT_HOLDING_REG_RD)) { | ||||||
|             // Get parameter information from parameter queue |             // Get parameter information from parameter queue | ||||||
|             ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); |             ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); | ||||||
|             ESP_LOGI(SLAVE_TAG, "HOLDING %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", |             ESP_LOGI(TAG, "HOLDING %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", | ||||||
|                     rw_str, |                     rw_str, | ||||||
|                     (uint32_t)reg_info.time_stamp, |                     (uint32_t)reg_info.time_stamp, | ||||||
|                     (uint32_t)reg_info.mb_offset, |                     (uint32_t)reg_info.mb_offset, | ||||||
| @@ -198,7 +198,7 @@ void app_main(void) | |||||||
|             } |             } | ||||||
|         } else if (event & MB_EVENT_INPUT_REG_RD) { |         } else if (event & MB_EVENT_INPUT_REG_RD) { | ||||||
|             ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); |             ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); | ||||||
|             ESP_LOGI(SLAVE_TAG, "INPUT READ (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", |             ESP_LOGI(TAG, "INPUT READ (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", | ||||||
|                     (uint32_t)reg_info.time_stamp, |                     (uint32_t)reg_info.time_stamp, | ||||||
|                     (uint32_t)reg_info.mb_offset, |                     (uint32_t)reg_info.mb_offset, | ||||||
|                     (uint32_t)reg_info.type, |                     (uint32_t)reg_info.type, | ||||||
| @@ -206,7 +206,7 @@ void app_main(void) | |||||||
|                     (uint32_t)reg_info.size); |                     (uint32_t)reg_info.size); | ||||||
|         } else if (event & MB_EVENT_DISCRETE_RD) { |         } else if (event & MB_EVENT_DISCRETE_RD) { | ||||||
|             ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); |             ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); | ||||||
|             ESP_LOGI(SLAVE_TAG, "DISCRETE READ (%u us): ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", |             ESP_LOGI(TAG, "DISCRETE READ (%u us): ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", | ||||||
|                                 (uint32_t)reg_info.time_stamp, |                                 (uint32_t)reg_info.time_stamp, | ||||||
|                                 (uint32_t)reg_info.mb_offset, |                                 (uint32_t)reg_info.mb_offset, | ||||||
|                                 (uint32_t)reg_info.type, |                                 (uint32_t)reg_info.type, | ||||||
| @@ -214,7 +214,7 @@ void app_main(void) | |||||||
|                                 (uint32_t)reg_info.size); |                                 (uint32_t)reg_info.size); | ||||||
|         } else if (event & (MB_EVENT_COILS_RD | MB_EVENT_COILS_WR)) { |         } else if (event & (MB_EVENT_COILS_RD | MB_EVENT_COILS_WR)) { | ||||||
|             ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); |             ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); | ||||||
|             ESP_LOGI(SLAVE_TAG, "COILS %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", |             ESP_LOGI(TAG, "COILS %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", | ||||||
|                                 rw_str, |                                 rw_str, | ||||||
|                                 (uint32_t)reg_info.time_stamp, |                                 (uint32_t)reg_info.time_stamp, | ||||||
|                                 (uint32_t)reg_info.mb_offset, |                                 (uint32_t)reg_info.mb_offset, | ||||||
| @@ -225,7 +225,7 @@ void app_main(void) | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     // Destroy of Modbus controller on alarm |     // Destroy of Modbus controller on alarm | ||||||
|     ESP_LOGI(SLAVE_TAG,"Modbus controller destroyed."); |     ESP_LOGI(TAG,"Modbus controller destroyed."); | ||||||
|     vTaskDelay(100); |     vTaskDelay(100); | ||||||
|     ESP_ERROR_CHECK(mbc_slave_destroy()); |     ESP_ERROR_CHECK(mbc_slave_destroy()); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,3 +1,6 @@ | |||||||
|  | # SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD | ||||||
|  | # SPDX-License-Identifier: Apache-2.0 | ||||||
|  |  | ||||||
| import logging | import logging | ||||||
| import os | import os | ||||||
| import re | import re | ||||||
| @@ -69,7 +72,7 @@ class DutTestThread(Thread): | |||||||
|         super(DutTestThread, self).__init__() |         super(DutTestThread, self).__init__() | ||||||
|  |  | ||||||
|     def __enter__(self): |     def __enter__(self): | ||||||
|         logger.debug('Restart %s.' % self.tname) |         logger.debug('Restart %s.', self.tname) | ||||||
|         # Reset DUT first |         # Reset DUT first | ||||||
|         self.dut.reset() |         self.dut.reset() | ||||||
|         # Capture output from the DUT |         # Capture output from the DUT | ||||||
| @@ -80,7 +83,7 @@ class DutTestThread(Thread): | |||||||
|         """ The exit method of context manager |         """ The exit method of context manager | ||||||
|         """ |         """ | ||||||
|         if exc_type is not None or exc_value is not None: |         if exc_type is not None or exc_value is not None: | ||||||
|             logger.info('Thread %s rised an exception type: %s, value: %s' % (self.tname, str(exc_type), str(exc_value))) |             logger.info('Thread %s rised an exception type: %s, value: %s', self.tname, str(exc_type), str(exc_value)) | ||||||
|  |  | ||||||
|     def run(self): |     def run(self): | ||||||
|         """ The function implements thread functionality |         """ The function implements thread functionality | ||||||
| @@ -95,7 +98,7 @@ class DutTestThread(Thread): | |||||||
|         # Check DUT exceptions |         # Check DUT exceptions | ||||||
|         dut_exceptions = self.dut.get_exceptions() |         dut_exceptions = self.dut.get_exceptions() | ||||||
|         if 'Guru Meditation Error:' in dut_exceptions: |         if 'Guru Meditation Error:' in dut_exceptions: | ||||||
|             raise Exception('%s generated an exception: %s\n' % (str(self.dut), dut_exceptions)) |             raise RuntimeError('%s generated an exception(s): %s\n' % (str(self.dut), dut_exceptions)) | ||||||
|  |  | ||||||
|         # Mark thread has run to completion without any exceptions |         # Mark thread has run to completion without any exceptions | ||||||
|         self.data = self.dut.stop_capture_raw_data(capture_id=self.dut.name) |         self.data = self.dut.stop_capture_raw_data(capture_id=self.dut.name) | ||||||
| @@ -106,15 +109,17 @@ class DutTestThread(Thread): | |||||||
|         message = r'.*Waiting IP([0-9]{1,2}) from stdin.*' |         message = r'.*Waiting IP([0-9]{1,2}) from stdin.*' | ||||||
|         # Read all data from previous restart to get prompt correctly |         # Read all data from previous restart to get prompt correctly | ||||||
|         self.dut.read() |         self.dut.read() | ||||||
|         result = self.dut.expect(re.compile(message), TEST_EXPECT_STR_TIMEOUT) |         result = self.dut.expect(re.compile(message), timeout=TEST_EXPECT_STR_TIMEOUT) | ||||||
|         if int(result[0]) != index: |         if int(result[0]) != index: | ||||||
|             raise Exception('Incorrect index of IP=%d for %s\n' % (int(result[0]), str(self.dut))) |             raise RuntimeError('Incorrect index of IP=%s for %s\n' % (result[0], str(self.dut))) | ||||||
|         message = 'IP%s=%s' % (result[0], self.ip_addr) |         # Use the same slave IP address for all characteristics during the test | ||||||
|         self.dut.write(message, '\r\n', False) |         self.dut.write('IP0=' + self.ip_addr, '\n', False) | ||||||
|         logger.debug('Sent message for %s: %s' % (self.tname, message)) |         self.dut.write('IP1=' + self.ip_addr, '\n', False) | ||||||
|  |         self.dut.write('IP2=' + self.ip_addr, '\n', False) | ||||||
|  |         logger.debug('Set IP address=%s for %s', self.ip_addr, self.tname) | ||||||
|         message = r'.*IP\([0-9]+\) = \[([0-9a-zA-Z\.\:]+)\] set from stdin.*' |         message = r'.*IP\([0-9]+\) = \[([0-9a-zA-Z\.\:]+)\] set from stdin.*' | ||||||
|         result = self.dut.expect(re.compile(message), TEST_EXPECT_STR_TIMEOUT) |         result = self.dut.expect(re.compile(message), timeout=TEST_EXPECT_STR_TIMEOUT) | ||||||
|         logger.debug('Thread %s initialized with slave IP (%s).' % (self.tname, result[0])) |         logger.debug('Thread %s initialized with slave IP=%s.', self.tname, self.ip_addr) | ||||||
|  |  | ||||||
|     def test_start(self, timeout_value): |     def test_start(self, timeout_value): | ||||||
|         """ The method to initialize and handle test stages |         """ The method to initialize and handle test stages | ||||||
| @@ -122,37 +127,37 @@ class DutTestThread(Thread): | |||||||
|         def handle_get_ip4(data): |         def handle_get_ip4(data): | ||||||
|             """ Handle get_ip v4 |             """ Handle get_ip v4 | ||||||
|             """ |             """ | ||||||
|             logger.debug('%s[STACK_IPV4]: %s' % (self.tname, str(data))) |             logger.debug('%s[STACK_IPV4]: %s', self.tname, str(data)) | ||||||
|             self.test_stage = STACK_IPV4 |             self.test_stage = STACK_IPV4 | ||||||
|  |  | ||||||
|         def handle_get_ip6(data): |         def handle_get_ip6(data): | ||||||
|             """ Handle get_ip v6 |             """ Handle get_ip v6 | ||||||
|             """ |             """ | ||||||
|             logger.debug('%s[STACK_IPV6]: %s' % (self.tname, str(data))) |             logger.debug('%s[STACK_IPV6]: %s', self.tname, str(data)) | ||||||
|             self.test_stage = STACK_IPV6 |             self.test_stage = STACK_IPV6 | ||||||
|  |  | ||||||
|         def handle_init(data): |         def handle_init(data): | ||||||
|             """ Handle init |             """ Handle init | ||||||
|             """ |             """ | ||||||
|             logger.debug('%s[STACK_INIT]: %s' % (self.tname, str(data))) |             logger.debug('%s[STACK_INIT]: %s', self.tname, str(data)) | ||||||
|             self.test_stage = STACK_INIT |             self.test_stage = STACK_INIT | ||||||
|  |  | ||||||
|         def handle_connect(data): |         def handle_connect(data): | ||||||
|             """ Handle connect |             """ Handle connect | ||||||
|             """ |             """ | ||||||
|             logger.debug('%s[STACK_CONNECT]: %s' % (self.tname, str(data))) |             logger.debug('%s[STACK_CONNECT]: %s', self.tname, str(data)) | ||||||
|             self.test_stage = STACK_CONNECT |             self.test_stage = STACK_CONNECT | ||||||
|  |  | ||||||
|         def handle_test_start(data): |         def handle_test_start(data): | ||||||
|             """ Handle connect |             """ Handle connect | ||||||
|             """ |             """ | ||||||
|             logger.debug('%s[STACK_START]: %s' % (self.tname, str(data))) |             logger.debug('%s[STACK_START]: %s', self.tname, str(data)) | ||||||
|             self.test_stage = STACK_START |             self.test_stage = STACK_START | ||||||
|  |  | ||||||
|         def handle_par_ok(data): |         def handle_par_ok(data): | ||||||
|             """ Handle parameter ok |             """ Handle parameter ok | ||||||
|             """ |             """ | ||||||
|             logger.debug('%s[READ_PAR_OK]: %s' % (self.tname, str(data))) |             logger.debug('%s[READ_PAR_OK]: %s', self.tname, str(data)) | ||||||
|             if self.test_stage >= STACK_START: |             if self.test_stage >= STACK_START: | ||||||
|                 self.param_ok_count += 1 |                 self.param_ok_count += 1 | ||||||
|             self.test_stage = STACK_PAR_OK |             self.test_stage = STACK_PAR_OK | ||||||
| @@ -160,14 +165,14 @@ class DutTestThread(Thread): | |||||||
|         def handle_par_fail(data): |         def handle_par_fail(data): | ||||||
|             """ Handle parameter fail |             """ Handle parameter fail | ||||||
|             """ |             """ | ||||||
|             logger.debug('%s[READ_PAR_FAIL]: %s' % (self.tname, str(data))) |             logger.debug('%s[READ_PAR_FAIL]: %s', self.tname, str(data)) | ||||||
|             self.param_fail_count += 1 |             self.param_fail_count += 1 | ||||||
|             self.test_stage = STACK_PAR_FAIL |             self.test_stage = STACK_PAR_FAIL | ||||||
|  |  | ||||||
|         def handle_destroy(data): |         def handle_destroy(data): | ||||||
|             """ Handle destroy |             """ Handle destroy | ||||||
|             """ |             """ | ||||||
|             logger.debug('%s[DESTROY]: %s' % (self.tname, str(data))) |             logger.debug('%s[DESTROY]: %s', self.tname, str(data)) | ||||||
|             self.test_stage = STACK_DESTROY |             self.test_stage = STACK_DESTROY | ||||||
|             self.test_finish = True |             self.test_finish = True | ||||||
|  |  | ||||||
| @@ -183,7 +188,7 @@ class DutTestThread(Thread): | |||||||
|                                     (re.compile(self.expected[STACK_DESTROY]), handle_destroy), |                                     (re.compile(self.expected[STACK_DESTROY]), handle_destroy), | ||||||
|                                     timeout=timeout_value) |                                     timeout=timeout_value) | ||||||
|             except DUT.ExpectTimeout: |             except DUT.ExpectTimeout: | ||||||
|                 logger.debug('%s, expect timeout on stage #%d (%s seconds)' % (self.tname, self.test_stage, timeout_value)) |                 logger.debug('%s, expect timeout on stage #%d (%s seconds)', self.tname, self.test_stage, timeout_value) | ||||||
|                 self.test_finish = True |                 self.test_finish = True | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -193,14 +198,14 @@ def test_check_mode(dut=None, mode_str=None, value=None): | |||||||
|     global logger |     global logger | ||||||
|     try: |     try: | ||||||
|         opt = dut.app.get_sdkconfig()[mode_str] |         opt = dut.app.get_sdkconfig()[mode_str] | ||||||
|         logger.debug('%s {%s} = %s.\n' % (str(dut), mode_str, opt)) |         logger.debug('%s {%s} = %s.\n', str(dut), mode_str, opt) | ||||||
|         return value == opt |         return value == opt | ||||||
|     except Exception: |     except Exception: | ||||||
|         logger.error('ENV_TEST_FAILURE: %s: Cannot find option %s in sdkconfig.' % (str(dut), mode_str)) |         logger.error('ENV_TEST_FAILURE: %s: Cannot find option %s in sdkconfig.', str(dut), mode_str) | ||||||
|     return False |     return False | ||||||
|  |  | ||||||
|  |  | ||||||
| @ttfw_idf.idf_example_test(env_tag='Example_Modbus_TCP') | @ttfw_idf.idf_example_test(env_tag='Example_Modbus_TCP', target=['esp32']) | ||||||
| def test_modbus_communication(env, comm_mode): | def test_modbus_communication(env, comm_mode): | ||||||
|     global logger |     global logger | ||||||
|  |  | ||||||
| @@ -235,7 +240,7 @@ def test_modbus_communication(env, comm_mode): | |||||||
|             master_name = TEST_MASTER_TCP |             master_name = TEST_MASTER_TCP | ||||||
|         else: |         else: | ||||||
|             logger.error('ENV_TEST_FAILURE: IP resolver mode do not match in the master and slave implementation.\n') |             logger.error('ENV_TEST_FAILURE: IP resolver mode do not match in the master and slave implementation.\n') | ||||||
|             raise Exception('ENV_TEST_FAILURE: IP resolver mode do not match in the master and slave implementation.\n') |             raise RuntimeError('ENV_TEST_FAILURE: IP resolver mode do not match in the master and slave implementation.\n') | ||||||
|         address = None |         address = None | ||||||
|         if test_check_mode(dut_master, 'CONFIG_MB_SLAVE_IP_FROM_STDIN', 'y'): |         if test_check_mode(dut_master, 'CONFIG_MB_SLAVE_IP_FROM_STDIN', 'y'): | ||||||
|             logger.info('ENV_TEST_INFO: Set slave IP address through STDIN.\n') |             logger.info('ENV_TEST_INFO: Set slave IP address through STDIN.\n') | ||||||
| @@ -249,9 +254,9 @@ def test_modbus_communication(env, comm_mode): | |||||||
|             if address is not None: |             if address is not None: | ||||||
|                     print('Found IP slave address: %s' % address[0]) |                     print('Found IP slave address: %s' % address[0]) | ||||||
|             else: |             else: | ||||||
|                 raise Exception('ENV_TEST_FAILURE: Slave IP address is not found in the output. Check network settings.\n') |                 raise RuntimeError('ENV_TEST_FAILURE: Slave IP address is not found in the output. Check network settings.\n') | ||||||
|         else: |         else: | ||||||
|             raise Exception('ENV_TEST_FAILURE: Slave IP resolver is not configured correctly.\n') |             raise RuntimeError('ENV_TEST_FAILURE: Slave IP resolver is not configured correctly.\n') | ||||||
|  |  | ||||||
|         # Create thread for each dut |         # Create thread for each dut | ||||||
|         with DutTestThread(dut=dut_master, name=master_name, ip_addr=address[0], expect=pattern_dict_master) as dut_master_thread: |         with DutTestThread(dut=dut_master, name=master_name, ip_addr=address[0], expect=pattern_dict_master) as dut_master_thread: | ||||||
| @@ -265,32 +270,32 @@ def test_modbus_communication(env, comm_mode): | |||||||
|                 dut_slave_thread.join(timeout=TEST_THREAD_JOIN_TIMEOUT) |                 dut_slave_thread.join(timeout=TEST_THREAD_JOIN_TIMEOUT) | ||||||
|                 dut_master_thread.join(timeout=TEST_THREAD_JOIN_TIMEOUT) |                 dut_master_thread.join(timeout=TEST_THREAD_JOIN_TIMEOUT) | ||||||
|  |  | ||||||
|                 if dut_slave_thread.isAlive(): |                 if dut_slave_thread.is_alive(): | ||||||
|                     logger.error('ENV_TEST_FAILURE: The thread %s is not completed successfully after %d seconds.\n' % |                     logger.error('ENV_TEST_FAILURE: The thread %s is not completed successfully after %d seconds.\n', | ||||||
|                                  (dut_slave_thread.tname, TEST_THREAD_JOIN_TIMEOUT)) |                                  dut_slave_thread.tname, TEST_THREAD_JOIN_TIMEOUT) | ||||||
|                     raise Exception('ENV_TEST_FAILURE: The thread %s is not completed successfully after %d seconds.\n' % |                     raise RuntimeError('ENV_TEST_FAILURE: The thread %s is not completed successfully after %d seconds.\n' % | ||||||
|                                     (dut_slave_thread.tname, TEST_THREAD_JOIN_TIMEOUT)) |                                        (dut_slave_thread.tname, TEST_THREAD_JOIN_TIMEOUT)) | ||||||
|  |  | ||||||
|                 if dut_master_thread.isAlive(): |                 if dut_master_thread.is_alive(): | ||||||
|                     logger.error('TEST_FAILURE: The thread %s is not completed successfully after %d seconds.\n' % |                     logger.error('TEST_FAILURE: The thread %s is not completed successfully after %d seconds.\n', | ||||||
|                                  (dut_master_thread.tname, TEST_THREAD_JOIN_TIMEOUT)) |                                  dut_master_thread.tname, TEST_THREAD_JOIN_TIMEOUT) | ||||||
|                     raise Exception('TEST_FAILURE: The thread %s is not completed successfully after %d seconds.\n' % |                     raise RuntimeError('TEST_FAILURE: The thread %s is not completed successfully after %d seconds.\n' % | ||||||
|                                     (dut_master_thread.tname, TEST_THREAD_JOIN_TIMEOUT)) |                                        (dut_master_thread.tname, TEST_THREAD_JOIN_TIMEOUT)) | ||||||
|  |  | ||||||
|                 logger.info('TEST_INFO: %s error count = %d, %s error count = %d.\n' % |                 logger.info('TEST_INFO: %s error count = %d, %s error count = %d.\n', | ||||||
|                             (dut_master_thread.tname, dut_master_thread.param_fail_count, |                             dut_master_thread.tname, dut_master_thread.param_fail_count, | ||||||
|                              dut_slave_thread.tname, dut_slave_thread.param_fail_count)) |                             dut_slave_thread.tname, dut_slave_thread.param_fail_count) | ||||||
|                 logger.info('TEST_INFO: %s ok count = %d, %s ok count = %d.\n' % |                 logger.info('TEST_INFO: %s ok count = %d, %s ok count = %d.\n', | ||||||
|                             (dut_master_thread.tname, dut_master_thread.param_ok_count, |                             dut_master_thread.tname, dut_master_thread.param_ok_count, | ||||||
|                              dut_slave_thread.tname, dut_slave_thread.param_ok_count)) |                             dut_slave_thread.tname, dut_slave_thread.param_ok_count) | ||||||
|  |  | ||||||
|                 if ((dut_master_thread.param_fail_count > TEST_READ_MAX_ERR_COUNT) or |                 if ((dut_master_thread.param_fail_count > TEST_READ_MAX_ERR_COUNT) or | ||||||
|                    (dut_slave_thread.param_fail_count > TEST_READ_MAX_ERR_COUNT) or |                    (dut_slave_thread.param_fail_count > TEST_READ_MAX_ERR_COUNT) or | ||||||
|                    (dut_slave_thread.param_ok_count == 0) or |                    (dut_slave_thread.param_ok_count == 0) or | ||||||
|                    (dut_master_thread.param_ok_count == 0)): |                    (dut_master_thread.param_ok_count == 0)): | ||||||
|                     raise Exception('TEST_FAILURE: %s parameter read error(ok) count = %d(%d), %s parameter read error(ok) count = %d(%d).\n' % |                     raise RuntimeError('TEST_FAILURE: %s parameter read error(ok) count = %d(%d), %s parameter read error(ok) count = %d(%d).\n' % | ||||||
|                                     (dut_master_thread.tname, dut_master_thread.param_fail_count, dut_master_thread.param_ok_count, |                                        (dut_master_thread.tname, dut_master_thread.param_fail_count, dut_master_thread.param_ok_count, | ||||||
|                                      dut_slave_thread.tname, dut_slave_thread.param_fail_count, dut_slave_thread.param_ok_count)) |                                         dut_slave_thread.tname, dut_slave_thread.param_fail_count, dut_slave_thread.param_ok_count)) | ||||||
|                 logger.info('TEST_SUCCESS: The Modbus parameter test is completed successfully.\n') |                 logger.info('TEST_SUCCESS: The Modbus parameter test is completed successfully.\n') | ||||||
|  |  | ||||||
|     finally: |     finally: | ||||||
|   | |||||||
| @@ -12,7 +12,10 @@ | |||||||
| // See the License for the specific language governing permissions and | // See the License for the specific language governing permissions and | ||||||
| // limitations under the License. | // limitations under the License. | ||||||
|  |  | ||||||
| #include "string.h" | // FreeModbus Master Example ESP32 | ||||||
|  |  | ||||||
|  | #include <string.h> | ||||||
|  | #include <sys/queue.h> | ||||||
| #include "esp_log.h" | #include "esp_log.h" | ||||||
| #include "esp_system.h" | #include "esp_system.h" | ||||||
| #include "esp_wifi.h" | #include "esp_wifi.h" | ||||||
| @@ -44,14 +47,6 @@ | |||||||
| #define POLL_TIMEOUT_TICS               (POLL_TIMEOUT_MS / portTICK_RATE_MS) | #define POLL_TIMEOUT_TICS               (POLL_TIMEOUT_MS / portTICK_RATE_MS) | ||||||
| #define MB_MDNS_PORT                    (502) | #define MB_MDNS_PORT                    (502) | ||||||
|  |  | ||||||
| #define MASTER_TAG "MASTER_TEST" |  | ||||||
|  |  | ||||||
| #define MASTER_CHECK(a, ret_val, str, ...) \ |  | ||||||
|     if (!(a)) { \ |  | ||||||
|         ESP_LOGE(MASTER_TAG, "%s(%u): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ |  | ||||||
|         return (ret_val); \ |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| // The macro to get offset for parameter in the appropriate structure | // The macro to get offset for parameter in the appropriate structure | ||||||
| #define HOLD_OFFSET(field) ((uint16_t)(offsetof(holding_reg_params_t, field) + 1)) | #define HOLD_OFFSET(field) ((uint16_t)(offsetof(holding_reg_params_t, field) + 1)) | ||||||
| #define INPUT_OFFSET(field) ((uint16_t)(offsetof(input_reg_params_t, field) + 1)) | #define INPUT_OFFSET(field) ((uint16_t)(offsetof(input_reg_params_t, field) + 1)) | ||||||
| @@ -76,12 +71,14 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #define MB_MDNS_INSTANCE(pref) pref"mb_master_tcp" | #define MB_MDNS_INSTANCE(pref) pref"mb_master_tcp" | ||||||
|  | static const char *TAG = "MASTER_TEST"; | ||||||
|  |  | ||||||
| // Enumeration of modbus device addresses accessed by master device | // Enumeration of modbus device addresses accessed by master device | ||||||
| // Each address in the table is a index of TCP slave ip address in mb_communication_info_t::tcp_ip_addr table | // Each address in the table is a index of TCP slave ip address in mb_communication_info_t::tcp_ip_addr table | ||||||
| enum { | enum { | ||||||
|     MB_DEVICE_ADDR1 = 1, // Slave address 1 |     MB_DEVICE_ADDR1 = 1, // Slave address 1 | ||||||
|     MB_DEVICE_COUNT |     MB_DEVICE_ADDR2 = 200, | ||||||
|  |     MB_DEVICE_ADDR3 = 35 | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // Enumeration of all supported CIDs for device (used in parameter definition table) | // Enumeration of all supported CIDs for device (used in parameter definition table) | ||||||
| @@ -114,11 +111,11 @@ const mb_parameter_descriptor_t device_parameters[] = { | |||||||
|             HOLD_OFFSET(holding_data0), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, |             HOLD_OFFSET(holding_data0), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, | ||||||
|     { CID_INP_DATA_1, STR("Temperature_1"), STR("C"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 2, 2, |     { CID_INP_DATA_1, STR("Temperature_1"), STR("C"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 2, 2, | ||||||
|             INPUT_OFFSET(input_data1), PARAM_TYPE_FLOAT, 4, OPTS( -40, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, |             INPUT_OFFSET(input_data1), PARAM_TYPE_FLOAT, 4, OPTS( -40, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, | ||||||
|     { CID_HOLD_DATA_1, STR("Humidity_2"), STR("%rH"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 2, 2, |     { CID_HOLD_DATA_1, STR("Humidity_2"), STR("%rH"), MB_DEVICE_ADDR2, MB_PARAM_HOLDING, 2, 2, | ||||||
|             HOLD_OFFSET(holding_data1), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, |             HOLD_OFFSET(holding_data1), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, | ||||||
|     { CID_INP_DATA_2, STR("Temperature_2"), STR("C"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 4, 2, |     { CID_INP_DATA_2, STR("Temperature_2"), STR("C"), MB_DEVICE_ADDR2, MB_PARAM_INPUT, 4, 2, | ||||||
|             INPUT_OFFSET(input_data2), PARAM_TYPE_FLOAT, 4, OPTS( -40, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, |             INPUT_OFFSET(input_data2), PARAM_TYPE_FLOAT, 4, OPTS( -40, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, | ||||||
|     { CID_HOLD_DATA_2, STR("Humidity_3"), STR("%rH"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 4, 2, |     { CID_HOLD_DATA_2, STR("Humidity_3"), STR("%rH"), MB_DEVICE_ADDR3, MB_PARAM_HOLDING, 4, 2, | ||||||
|             HOLD_OFFSET(holding_data2), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, |             HOLD_OFFSET(holding_data2), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, | ||||||
|     { CID_RELAY_P1, STR("RelayP1"), STR("on/off"), MB_DEVICE_ADDR1, MB_PARAM_COIL, 0, 8, |     { CID_RELAY_P1, STR("RelayP1"), STR("on/off"), MB_DEVICE_ADDR1, MB_PARAM_COIL, 0, 8, | ||||||
|             COIL_OFFSET(coils_port0), PARAM_TYPE_U16, 2, OPTS( BIT1, 0, 0 ), PAR_PERMS_READ_WRITE_TRIGGER }, |             COIL_OFFSET(coils_port0), PARAM_TYPE_U16, 2, OPTS( BIT1, 0, 0 ), PAR_PERMS_READ_WRITE_TRIGGER }, | ||||||
| @@ -127,20 +124,26 @@ const mb_parameter_descriptor_t device_parameters[] = { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| // Calculate number of parameters in the table | // Calculate number of parameters in the table | ||||||
| const uint16_t num_device_parameters = (sizeof(device_parameters)/sizeof(device_parameters[0])); | const uint16_t num_device_parameters = (sizeof(device_parameters) / sizeof(device_parameters[0])); | ||||||
|  |  | ||||||
| // This table represents slave IP addresses that correspond to the short address field of the slave in device_parameters structure | // This table represents slave IP addresses that correspond to the short address field of the slave in device_parameters structure | ||||||
| // Modbus TCP stack shall use these addresses to be able to connect and read parameters from slave | // Modbus TCP stack shall use these addresses to be able to connect and read parameters from slave | ||||||
| char* slave_ip_address_table[MB_DEVICE_COUNT] = { | char* slave_ip_address_table[] = { | ||||||
| #if CONFIG_MB_SLAVE_IP_FROM_STDIN | #if CONFIG_MB_SLAVE_IP_FROM_STDIN | ||||||
|     "FROM_STDIN",     // Address corresponds to MB_DEVICE_ADDR1 and set to predefined value by user |     "FROM_STDIN",     // Address corresponds to MB_DEVICE_ADDR1 and set to predefined value by user | ||||||
|     NULL |     "FROM_STDIN",     // Corresponds to characteristic MB_DEVICE_ADDR2 | ||||||
|  |     "FROM_STDIN",     // Corresponds to characteristic MB_DEVICE_ADDR3 | ||||||
|  |     NULL              // End of table condition (must be included) | ||||||
| #elif CONFIG_MB_MDNS_IP_RESOLVER | #elif CONFIG_MB_MDNS_IP_RESOLVER | ||||||
|  |     NULL, | ||||||
|  |     NULL, | ||||||
|     NULL, |     NULL, | ||||||
|     NULL |     NULL | ||||||
| #endif | #endif | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | const size_t ip_table_sz = (size_t)(sizeof(slave_ip_address_table) / sizeof(slave_ip_address_table[0])); | ||||||
|  |  | ||||||
| #if CONFIG_MB_SLAVE_IP_FROM_STDIN | #if CONFIG_MB_SLAVE_IP_FROM_STDIN | ||||||
|  |  | ||||||
| // Scan IP address according to IPV settings | // Scan IP address according to IPV settings | ||||||
| @@ -191,8 +194,8 @@ static int master_get_slave_ip_stdin(char** addr_table) | |||||||
|             fputc('\n', stdout); |             fputc('\n', stdout); | ||||||
|             ip_str = master_scan_addr(&index, buf); |             ip_str = master_scan_addr(&index, buf); | ||||||
|             if (ip_str != NULL) { |             if (ip_str != NULL) { | ||||||
|                 ESP_LOGI(MASTER_TAG, "IP(%d) = [%s] set from stdin.", ip_cnt, ip_str); |                 ESP_LOGI(TAG, "IP(%d) = [%s] set from stdin.", ip_cnt, ip_str); | ||||||
|                 if ((ip_cnt >= MB_DEVICE_COUNT) || (index != ip_cnt)) { |                 if ((ip_cnt >= ip_table_sz) || (index != ip_cnt)) { | ||||||
|                     addr_table[ip_cnt] = NULL; |                     addr_table[ip_cnt] = NULL; | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
| @@ -204,10 +207,10 @@ static int master_get_slave_ip_stdin(char** addr_table) | |||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             if (addr_table[ip_cnt]) { |             if (addr_table[ip_cnt]) { | ||||||
|                 ESP_LOGI(MASTER_TAG, "Leave IP(%d) = [%s] set manually.", ip_cnt, addr_table[ip_cnt]); |                 ESP_LOGI(TAG, "Leave IP(%d) = [%s] set manually.", ip_cnt, addr_table[ip_cnt]); | ||||||
|                 ip_cnt++; |                 ip_cnt++; | ||||||
|             } else { |             } else { | ||||||
|                 ESP_LOGI(MASTER_TAG, "IP(%d) is not set in the table.", ip_cnt); |                 ESP_LOGI(TAG, "IP(%d) is not set in the table.", ip_cnt); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -217,6 +220,16 @@ static int master_get_slave_ip_stdin(char** addr_table) | |||||||
|  |  | ||||||
| #elif CONFIG_MB_MDNS_IP_RESOLVER | #elif CONFIG_MB_MDNS_IP_RESOLVER | ||||||
|  |  | ||||||
|  | typedef struct slave_addr_entry_s { | ||||||
|  |     uint16_t index; | ||||||
|  |     char* ip_address; | ||||||
|  |     uint8_t slave_addr; | ||||||
|  |     void* p_data; | ||||||
|  |     LIST_ENTRY(slave_addr_entry_s) entries; | ||||||
|  | } slave_addr_entry_t; | ||||||
|  |  | ||||||
|  | LIST_HEAD(slave_addr_, slave_addr_entry_s) slave_addr_list = LIST_HEAD_INITIALIZER(slave_addr_list); | ||||||
|  |  | ||||||
| // convert MAC from binary format to string | // convert MAC from binary format to string | ||||||
| static inline char* gen_mac_str(const uint8_t* mac, char* pref, char* mac_str) | static inline char* gen_mac_str(const uint8_t* mac, char* pref, char* mac_str) | ||||||
| { | { | ||||||
| @@ -240,7 +253,7 @@ static void master_start_mdns_service() | |||||||
|     ESP_ERROR_CHECK(mdns_init()); |     ESP_ERROR_CHECK(mdns_init()); | ||||||
|     // set mDNS hostname (required if you want to advertise services) |     // set mDNS hostname (required if you want to advertise services) | ||||||
|     ESP_ERROR_CHECK(mdns_hostname_set(hostname)); |     ESP_ERROR_CHECK(mdns_hostname_set(hostname)); | ||||||
|     ESP_LOGI(MASTER_TAG, "mdns hostname set to: [%s]", hostname); |     ESP_LOGI(TAG, "mdns hostname set to: [%s]", hostname); | ||||||
|  |  | ||||||
|     // set default mDNS instance name |     // set default mDNS instance name | ||||||
|     ESP_ERROR_CHECK(mdns_instance_name_set(MB_MDNS_INSTANCE("esp32_"))); |     ESP_ERROR_CHECK(mdns_instance_name_set(MB_MDNS_INSTANCE("esp32_"))); | ||||||
| @@ -281,15 +294,21 @@ static char* master_get_slave_ip_str(mdns_ip_addr_t* address, mb_tcp_addr_type_t | |||||||
|     return slave_ip_str; |     return slave_ip_str; | ||||||
| } | } | ||||||
|  |  | ||||||
| static esp_err_t master_resolve_slave(const char* name, mdns_result_t* result, char** resolved_ip, | static esp_err_t master_resolve_slave(uint8_t short_addr, mdns_result_t* result, char** resolved_ip, | ||||||
|                                         mb_tcp_addr_type_t addr_type) |                                         mb_tcp_addr_type_t addr_type) | ||||||
| { | { | ||||||
|     if (!name || !result) { |     if (!short_addr || !result || !resolved_ip) { | ||||||
|         return ESP_ERR_INVALID_ARG; |         return ESP_ERR_INVALID_ARG; | ||||||
|     } |     } | ||||||
|     mdns_result_t* r = result; |     mdns_result_t* r = result; | ||||||
|     int t; |     int t; | ||||||
|     char* slave_ip = NULL; |     char* slave_ip = NULL; | ||||||
|  |     char slave_name[22] = {0}; | ||||||
|  |  | ||||||
|  |     if (sprintf(slave_name, "mb_slave_tcp_%02X", short_addr) < 0) { | ||||||
|  |         ESP_LOGE(TAG, "Fail to create instance name for index: %d", short_addr); | ||||||
|  |         abort(); | ||||||
|  |     } | ||||||
|     for (; r ; r = r->next) { |     for (; r ; r = r->next) { | ||||||
|         if ((r->ip_protocol == MDNS_IP_PROTOCOL_V4) && (addr_type == MB_IPV6)) { |         if ((r->ip_protocol == MDNS_IP_PROTOCOL_V4) && (addr_type == MB_IPV6)) { | ||||||
|             continue; |             continue; | ||||||
| @@ -298,7 +317,7 @@ static esp_err_t master_resolve_slave(const char* name, mdns_result_t* result, c | |||||||
|         } |         } | ||||||
|         // Check host name for Modbus short address and |         // Check host name for Modbus short address and | ||||||
|         // append it into slave ip address table |         // append it into slave ip address table | ||||||
|         if ((strcmp(r->instance_name, name) == 0) && (r->port == CONFIG_FMB_TCP_PORT_DEFAULT)) { |         if ((strcmp(r->instance_name, slave_name) == 0) && (r->port == CONFIG_FMB_TCP_PORT_DEFAULT)) { | ||||||
|             printf("  PTR : %s\n", r->instance_name); |             printf("  PTR : %s\n", r->instance_name); | ||||||
|             if (r->txt_count) { |             if (r->txt_count) { | ||||||
|                 printf("  TXT : [%u] ", r->txt_count); |                 printf("  TXT : [%u] ", r->txt_count); | ||||||
| @@ -309,92 +328,124 @@ static esp_err_t master_resolve_slave(const char* name, mdns_result_t* result, c | |||||||
|             } |             } | ||||||
|             slave_ip = master_get_slave_ip_str(r->addr, addr_type); |             slave_ip = master_get_slave_ip_str(r->addr, addr_type); | ||||||
|             if (slave_ip) { |             if (slave_ip) { | ||||||
|                 ESP_LOGI(MASTER_TAG, "Resolved slave %s[%s]:%u", r->hostname, slave_ip, r->port); |                 ESP_LOGI(TAG, "Resolved slave %s[%s]:%u", r->hostname, slave_ip, r->port); | ||||||
|                 *resolved_ip = slave_ip; |                 *resolved_ip = slave_ip; | ||||||
|                 return ESP_OK; |                 return ESP_OK; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     *resolved_ip = NULL; |     *resolved_ip = NULL; | ||||||
|     ESP_LOGD(MASTER_TAG, "Fail to resolve slave: %s", name); |     ESP_LOGD(TAG, "Fail to resolve slave: %s", slave_name); | ||||||
|     return ESP_ERR_NOT_FOUND; |     return ESP_ERR_NOT_FOUND; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int master_create_slave_list(mdns_result_t* results, char** addr_table, | static int master_create_slave_list(mdns_result_t* results, char** addr_table, | ||||||
|                                         mb_tcp_addr_type_t addr_type) |                                         int addr_table_size, mb_tcp_addr_type_t addr_type) | ||||||
| { | { | ||||||
|     if (!results) { |     if (!results) { | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|     int i, addr, resolved = 0; |     int i, slave_addr, cid_resolve_cnt = 0; | ||||||
|  |     int ip_index = 0; | ||||||
|     const mb_parameter_descriptor_t* pdescr = &device_parameters[0]; |     const mb_parameter_descriptor_t* pdescr = &device_parameters[0]; | ||||||
|     char** ip_table = addr_table; |     char** ip_table = addr_table; | ||||||
|     char slave_name[22] = {0}; |  | ||||||
|     char* slave_ip = NULL; |     char* slave_ip = NULL; | ||||||
|  |     slave_addr_entry_t *it; | ||||||
|  |  | ||||||
|     for (i = 0; (i < num_device_parameters && pdescr); i++, pdescr++) { |     for (i = 0; (i < num_device_parameters && pdescr); i++, pdescr++) | ||||||
|         addr = pdescr->mb_slave_addr; |     { | ||||||
|         if (-1 == sprintf(slave_name, "mb_slave_tcp_%02X", addr)) { |         slave_addr = pdescr->mb_slave_addr; | ||||||
|             ESP_LOGI(MASTER_TAG, "Fail to create instance name for index: %d", addr); |  | ||||||
|             abort(); |         it = NULL; | ||||||
|  |         // Is the slave address already registered? | ||||||
|  |         LIST_FOREACH(it, &slave_addr_list, entries) { | ||||||
|  |             if (slave_addr == it->slave_addr) { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         if (!ip_table[addr - 1]) { |         if (!it) { | ||||||
|             esp_err_t err = master_resolve_slave(slave_name, results, &slave_ip, addr_type); |             // Resolve new slave IP address using its short address | ||||||
|  |             esp_err_t err = master_resolve_slave(slave_addr, results, &slave_ip, addr_type); | ||||||
|             if (err != ESP_OK) { |             if (err != ESP_OK) { | ||||||
|                 ESP_LOGE(MASTER_TAG, "Index: %d, sl_addr: %d, name:%s, failed to resolve!", |                 ESP_LOGE(TAG, "Index: %d, sl_addr: %d, failed to resolve!", i, slave_addr); | ||||||
|                                         i, addr, slave_name); |  | ||||||
|                 // Set correspond index to NULL indicate host not resolved |                 // Set correspond index to NULL indicate host not resolved | ||||||
|                 ip_table[addr - 1] = NULL; |                 ip_table[ip_index] = NULL; | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|             ip_table[addr - 1] = slave_ip; //slave_name; |             // Register new slave address information | ||||||
|             ESP_LOGI(MASTER_TAG, "Index: %d, sl_addr: %d, name:%s, resolve to IP: [%s]", |             slave_addr_entry_t* new_slave_entry = (slave_addr_entry_t*) heap_caps_malloc(sizeof(slave_addr_entry_t), | ||||||
|                                     i, addr, slave_name, slave_ip); |                                                        MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); | ||||||
|             resolved++; |             MB_RETURN_ON_FALSE((new_slave_entry != NULL), ESP_ERR_NO_MEM, | ||||||
|  |                                                  TAG, "Can not allocate memory for slave entry."); | ||||||
|  |             new_slave_entry->index = i; | ||||||
|  |             new_slave_entry->ip_address = slave_ip; | ||||||
|  |             new_slave_entry->slave_addr = slave_addr; | ||||||
|  |             new_slave_entry->p_data = NULL; | ||||||
|  |             LIST_INSERT_HEAD(&slave_addr_list, new_slave_entry, entries); | ||||||
|  |             ip_table[ip_index] = slave_ip; | ||||||
|  |             ESP_LOGI(TAG, "Index: %d, sl_addr: %d, resolved to IP: [%s]", | ||||||
|  |                                                 i, slave_addr, slave_ip); | ||||||
|  |             cid_resolve_cnt++; | ||||||
|  |             if (ip_index < addr_table_size) { | ||||||
|  |                 ip_index++; | ||||||
|  |             } | ||||||
|         } else { |         } else { | ||||||
|             ESP_LOGI(MASTER_TAG, "Index: %d, sl_addr: %d, name:%s, set to IP: [%s]", |             ip_table[ip_index] = it ? it->ip_address : ip_table[ip_index]; | ||||||
|                                     i, addr, slave_name, ip_table[addr - 1]); |             ESP_LOGI(TAG, "Index: %d, sl_addr: %d, set to IP: [%s]", | ||||||
|             resolved++; |                                     i, slave_addr, ip_table[ip_index]); | ||||||
|         } |             cid_resolve_cnt++; | ||||||
|     } |  | ||||||
|     return resolved; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void master_destroy_slave_list(char** table) |  | ||||||
| { |  | ||||||
|     for (int i = 0; ((i < MB_DEVICE_COUNT) && table[i] != NULL); i++) { |  | ||||||
|         if (table[i]) { |  | ||||||
|             free(table[i]); |  | ||||||
|             table[i] = NULL; |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     ESP_LOGI(TAG, "Resolved %d cids, with %d IP addresses", cid_resolve_cnt, ip_index); | ||||||
|  |     return cid_resolve_cnt; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int master_query_slave_service(const char * service_name, const char * proto, | static int master_query_slave_service(const char * service_name, const char * proto, | ||||||
|                                         mb_tcp_addr_type_t addr_type) |                                         mb_tcp_addr_type_t addr_type) | ||||||
| { | { | ||||||
|     ESP_LOGI(MASTER_TAG, "Query PTR: %s.%s.local", service_name, proto); |     ESP_LOGI(TAG, "Query PTR: %s.%s.local", service_name, proto); | ||||||
|  |  | ||||||
|     mdns_result_t* results = NULL; |     mdns_result_t* results = NULL; | ||||||
|     int count = 0; |     int count = 0; | ||||||
|  |  | ||||||
|     esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20, &results); |     esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20, &results); | ||||||
|     if(err){ |     if(err){ | ||||||
|         ESP_LOGE(MASTER_TAG, "Query Failed: %s", esp_err_to_name(err)); |         ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); | ||||||
|         return count; |         return count; | ||||||
|     } |     } | ||||||
|     if(!results){ |     if(!results){ | ||||||
|         ESP_LOGW(MASTER_TAG, "No results found!"); |         ESP_LOGW(TAG, "No results found!"); | ||||||
|         return count; |         return count; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     count = master_create_slave_list(results, slave_ip_address_table, addr_type); |     count = master_create_slave_list(results, slave_ip_address_table, ip_table_sz, addr_type); | ||||||
|  |  | ||||||
|     mdns_query_results_free(results); |     mdns_query_results_free(results); | ||||||
|     return count; |     return count; | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | static void master_destroy_slave_list(char** table, size_t ip_table_size) | ||||||
|  | { | ||||||
|  | #if CONFIG_MB_MDNS_IP_RESOLVER | ||||||
|  |     slave_addr_entry_t *it; | ||||||
|  |     LIST_FOREACH(it, &slave_addr_list, entries) { | ||||||
|  |         LIST_REMOVE(it, entries); | ||||||
|  |         free(it); | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  |     for (int i = 0; ((i < ip_table_size) && table[i] != NULL); i++) { | ||||||
|  |         if (table[i]) { | ||||||
|  | #if CONFIG_MB_SLAVE_IP_FROM_STDIN | ||||||
|  |             free(table[i]); | ||||||
|  |             table[i] = "FROM_STDIN"; | ||||||
|  | #elif CONFIG_MB_MDNS_IP_RESOLVER | ||||||
|  |             table[i] = NULL; | ||||||
|  | #endif | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| // The function to get pointer to parameter storage (instance) according to parameter description table | // The function to get pointer to parameter storage (instance) according to parameter description table | ||||||
| static void* master_get_param_data(const mb_parameter_descriptor_t* param_descriptor) | static void* master_get_param_data(const mb_parameter_descriptor_t* param_descriptor) | ||||||
| { | { | ||||||
| @@ -420,7 +471,7 @@ static void* master_get_param_data(const mb_parameter_descriptor_t* param_descri | |||||||
|                break; |                break; | ||||||
|        } |        } | ||||||
|     } else { |     } else { | ||||||
|         ESP_LOGE(MASTER_TAG, "Wrong parameter offset for CID #%d", param_descriptor->cid); |         ESP_LOGE(TAG, "Wrong parameter offset for CID #%d", param_descriptor->cid); | ||||||
|         assert(instance_ptr != NULL); |         assert(instance_ptr != NULL); | ||||||
|     } |     } | ||||||
|     return instance_ptr; |     return instance_ptr; | ||||||
| @@ -434,7 +485,7 @@ static void master_operation_func(void *arg) | |||||||
|     bool alarm_state = false; |     bool alarm_state = false; | ||||||
|     const mb_parameter_descriptor_t* param_descriptor = NULL; |     const mb_parameter_descriptor_t* param_descriptor = NULL; | ||||||
|  |  | ||||||
|     ESP_LOGI(MASTER_TAG, "Start modbus test..."); |     ESP_LOGI(TAG, "Start modbus test..."); | ||||||
|  |  | ||||||
|     for(uint16_t retry = 0; retry <= MASTER_MAX_RETRY && (!alarm_state); retry++) { |     for(uint16_t retry = 0; retry <= MASTER_MAX_RETRY && (!alarm_state); retry++) { | ||||||
|         // Read all found characteristics from slave(s) |         // Read all found characteristics from slave(s) | ||||||
| @@ -454,7 +505,7 @@ static void master_operation_func(void *arg) | |||||||
|                     *(float*)temp_data_ptr = value; |                     *(float*)temp_data_ptr = value; | ||||||
|                     if ((param_descriptor->mb_param_type == MB_PARAM_HOLDING) || |                     if ((param_descriptor->mb_param_type == MB_PARAM_HOLDING) || | ||||||
|                         (param_descriptor->mb_param_type == MB_PARAM_INPUT)) { |                         (param_descriptor->mb_param_type == MB_PARAM_INPUT)) { | ||||||
|                         ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = %f (0x%x) read successful.", |                         ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = %f (0x%x) read successful.", | ||||||
|                                         param_descriptor->cid, |                                         param_descriptor->cid, | ||||||
|                                         (char*)param_descriptor->param_key, |                                         (char*)param_descriptor->param_key, | ||||||
|                                         (char*)param_descriptor->param_units, |                                         (char*)param_descriptor->param_units, | ||||||
| @@ -468,7 +519,7 @@ static void master_operation_func(void *arg) | |||||||
|                     } else { |                     } else { | ||||||
|                         uint16_t state = *(uint16_t*)temp_data_ptr; |                         uint16_t state = *(uint16_t*)temp_data_ptr; | ||||||
|                         const char* rw_str = (state & param_descriptor->param_opts.opt1) ? "ON" : "OFF"; |                         const char* rw_str = (state & param_descriptor->param_opts.opt1) ? "ON" : "OFF"; | ||||||
|                         ESP_LOGI(MASTER_TAG, "Characteristic #%d %s (%s) value = %s (0x%x) read successful.", |                         ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = %s (0x%x) read successful.", | ||||||
|                                         param_descriptor->cid, |                                         param_descriptor->cid, | ||||||
|                                         (char*)param_descriptor->param_key, |                                         (char*)param_descriptor->param_key, | ||||||
|                                         (char*)param_descriptor->param_units, |                                         (char*)param_descriptor->param_units, | ||||||
| @@ -480,7 +531,7 @@ static void master_operation_func(void *arg) | |||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } else { |                 } else { | ||||||
|                     ESP_LOGE(MASTER_TAG, "Characteristic #%d (%s) read fail, err = %d (%s).", |                     ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = %d (%s).", | ||||||
|                                         param_descriptor->cid, |                                         param_descriptor->cid, | ||||||
|                                         (char*)param_descriptor->param_key, |                                         (char*)param_descriptor->param_key, | ||||||
|                                         (int)err, |                                         (int)err, | ||||||
| @@ -493,13 +544,13 @@ static void master_operation_func(void *arg) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (alarm_state) { |     if (alarm_state) { | ||||||
|         ESP_LOGI(MASTER_TAG, "Alarm triggered by cid #%d.", |         ESP_LOGI(TAG, "Alarm triggered by cid #%d.", | ||||||
|                                         param_descriptor->cid); |                                         param_descriptor->cid); | ||||||
|     } else { |     } else { | ||||||
|         ESP_LOGE(MASTER_TAG, "Alarm is not triggered after %d retries.", |         ESP_LOGE(TAG, "Alarm is not triggered after %d retries.", | ||||||
|                                         MASTER_MAX_RETRY); |                                         MASTER_MAX_RETRY); | ||||||
|     } |     } | ||||||
|     ESP_LOGI(MASTER_TAG, "Destroy master..."); |     ESP_LOGI(TAG, "Destroy master..."); | ||||||
|     vTaskDelay(100); |     vTaskDelay(100); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -510,15 +561,18 @@ static esp_err_t init_services(mb_tcp_addr_type_t ip_addr_type) | |||||||
|       ESP_ERROR_CHECK(nvs_flash_erase()); |       ESP_ERROR_CHECK(nvs_flash_erase()); | ||||||
|       result = nvs_flash_init(); |       result = nvs_flash_init(); | ||||||
|     } |     } | ||||||
|     MASTER_CHECK((result == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                             TAG, | ||||||
|                             "nvs_flash_init fail, returns(0x%x).", |                             "nvs_flash_init fail, returns(0x%x).", | ||||||
|                             (uint32_t)result); |                             (uint32_t)result); | ||||||
|     result = esp_netif_init(); |     result = esp_netif_init(); | ||||||
|     MASTER_CHECK((result == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                             TAG, | ||||||
|                             "esp_netif_init fail, returns(0x%x).", |                             "esp_netif_init fail, returns(0x%x).", | ||||||
|                             (uint32_t)result); |                             (uint32_t)result); | ||||||
|     result = esp_event_loop_create_default(); |     result = esp_event_loop_create_default(); | ||||||
|     MASTER_CHECK((result == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                             TAG, | ||||||
|                             "esp_event_loop_create_default fail, returns(0x%x).", |                             "esp_event_loop_create_default fail, returns(0x%x).", | ||||||
|                             (uint32_t)result); |                             (uint32_t)result); | ||||||
| #if CONFIG_MB_MDNS_IP_RESOLVER | #if CONFIG_MB_MDNS_IP_RESOLVER | ||||||
| @@ -529,12 +583,14 @@ static esp_err_t init_services(mb_tcp_addr_type_t ip_addr_type) | |||||||
|     // Read "Establishing Wi-Fi or Ethernet Connection" section in |     // Read "Establishing Wi-Fi or Ethernet Connection" section in | ||||||
|     // examples/protocols/README.md for more information about this function. |     // examples/protocols/README.md for more information about this function. | ||||||
|     result = example_connect(); |     result = example_connect(); | ||||||
|     MASTER_CHECK((result == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                 TAG, | ||||||
|                                 "example_connect fail, returns(0x%x).", |                                 "example_connect fail, returns(0x%x).", | ||||||
|                                 (uint32_t)result); |                                 (uint32_t)result); | ||||||
| #if CONFIG_EXAMPLE_CONNECT_WIFI | #if CONFIG_EXAMPLE_CONNECT_WIFI | ||||||
|    result = esp_wifi_set_ps(WIFI_PS_NONE); |    result = esp_wifi_set_ps(WIFI_PS_NONE); | ||||||
|    MASTER_CHECK((result == ESP_OK), ESP_ERR_INVALID_STATE, |    MB_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                    TAG, | ||||||
|                                    "esp_wifi_set_ps fail, returns(0x%x).", |                                    "esp_wifi_set_ps fail, returns(0x%x).", | ||||||
|                                    (uint32_t)result); |                                    (uint32_t)result); | ||||||
| #endif | #endif | ||||||
| @@ -544,17 +600,17 @@ static esp_err_t init_services(mb_tcp_addr_type_t ip_addr_type) | |||||||
|         res = master_query_slave_service("_modbus", "_tcp", ip_addr_type); |         res = master_query_slave_service("_modbus", "_tcp", ip_addr_type); | ||||||
|     } |     } | ||||||
|     if (res < num_device_parameters) { |     if (res < num_device_parameters) { | ||||||
|         ESP_LOGE(MASTER_TAG, "Could not resolve one or more slave IP addresses, resolved: %d out of %d.", res, num_device_parameters ); |         ESP_LOGE(TAG, "Could not resolve one or more slave IP addresses, resolved: %d out of %d.", res, num_device_parameters ); | ||||||
|         ESP_LOGE(MASTER_TAG, "Make sure you configured all slaves according to device parameter table and they alive in the network."); |         ESP_LOGE(TAG, "Make sure you configured all slaves according to device parameter table and they alive in the network."); | ||||||
|         return ESP_ERR_NOT_FOUND; |         return ESP_ERR_NOT_FOUND; | ||||||
|     } |     } | ||||||
|     mdns_free(); |     mdns_free(); | ||||||
| #elif CONFIG_MB_SLAVE_IP_FROM_STDIN | #elif CONFIG_MB_SLAVE_IP_FROM_STDIN | ||||||
|     int ip_cnt = master_get_slave_ip_stdin(slave_ip_address_table); |     int ip_cnt = master_get_slave_ip_stdin(slave_ip_address_table); | ||||||
|     if (ip_cnt) { |     if (ip_cnt) { | ||||||
|         ESP_LOGI(MASTER_TAG, "Configured %d IP addresse(s).", ip_cnt); |         ESP_LOGI(TAG, "Configured %d IP addresse(s).", ip_cnt); | ||||||
|     } else { |     } else { | ||||||
|         ESP_LOGE(MASTER_TAG, "Fail to get IP address from stdin. Continue."); |         ESP_LOGE(TAG, "Fail to get IP address from stdin. Continue."); | ||||||
|         return ESP_ERR_NOT_FOUND; |         return ESP_ERR_NOT_FOUND; | ||||||
|     } |     } | ||||||
| #endif | #endif | ||||||
| @@ -564,23 +620,26 @@ static esp_err_t init_services(mb_tcp_addr_type_t ip_addr_type) | |||||||
| static esp_err_t destroy_services(void) | static esp_err_t destroy_services(void) | ||||||
| { | { | ||||||
|     esp_err_t err = ESP_OK; |     esp_err_t err = ESP_OK; | ||||||
| #if CONFIG_MB_MDNS_IP_RESOLVER |     master_destroy_slave_list(slave_ip_address_table, ip_table_sz); | ||||||
|     master_destroy_slave_list(slave_ip_address_table); |  | ||||||
| #endif |  | ||||||
|     err = example_disconnect(); |     err = example_disconnect(); | ||||||
|     MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                    TAG, | ||||||
|                                    "example_disconnect fail, returns(0x%x).", |                                    "example_disconnect fail, returns(0x%x).", | ||||||
|                                    (uint32_t)err); |                                    (uint32_t)err); | ||||||
|     err = esp_event_loop_delete_default(); |     err = esp_event_loop_delete_default(); | ||||||
|     MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                        TAG, | ||||||
|                                        "esp_event_loop_delete_default fail, returns(0x%x).", |                                        "esp_event_loop_delete_default fail, returns(0x%x).", | ||||||
|                                        (uint32_t)err); |                                        (uint32_t)err); | ||||||
|     err = esp_netif_deinit(); |     err = esp_netif_deinit(); | ||||||
|     MASTER_CHECK((err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED), ESP_ERR_INVALID_STATE, | ||||||
|  |                                         TAG, | ||||||
|                                         "esp_netif_deinit fail, returns(0x%x).", |                                         "esp_netif_deinit fail, returns(0x%x).", | ||||||
|                                         (uint32_t)err); |                                         (uint32_t)err); | ||||||
|     err = nvs_flash_deinit(); |     err = nvs_flash_deinit(); | ||||||
|     MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                 TAG, | ||||||
|                                 "nvs_flash_deinit fail, returns(0x%x).", |                                 "nvs_flash_deinit fail, returns(0x%x).", | ||||||
|                                 (uint32_t)err); |                                 (uint32_t)err); | ||||||
|     return err; |     return err; | ||||||
| @@ -592,25 +651,30 @@ static esp_err_t master_init(mb_communication_info_t* comm_info) | |||||||
|     void* master_handler = NULL; |     void* master_handler = NULL; | ||||||
|  |  | ||||||
|     esp_err_t err = mbc_master_init_tcp(&master_handler); |     esp_err_t err = mbc_master_init_tcp(&master_handler); | ||||||
|     MASTER_CHECK((master_handler != NULL), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((master_handler != NULL), ESP_ERR_INVALID_STATE, | ||||||
|  |                                 TAG, | ||||||
|                                 "mb controller initialization fail."); |                                 "mb controller initialization fail."); | ||||||
|     MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                             TAG, | ||||||
|                             "mb controller initialization fail, returns(0x%x).", |                             "mb controller initialization fail, returns(0x%x).", | ||||||
|                             (uint32_t)err); |                             (uint32_t)err); | ||||||
|  |  | ||||||
|     err = mbc_master_setup((void*)comm_info); |     err = mbc_master_setup((void*)comm_info); | ||||||
|     MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                             TAG, | ||||||
|                             "mb controller setup fail, returns(0x%x).", |                             "mb controller setup fail, returns(0x%x).", | ||||||
|                             (uint32_t)err); |                             (uint32_t)err); | ||||||
|  |  | ||||||
|     err = mbc_master_set_descriptor(&device_parameters[0], num_device_parameters); |     err = mbc_master_set_descriptor(&device_parameters[0], num_device_parameters); | ||||||
|     MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                 TAG, | ||||||
|                                 "mb controller set descriptor fail, returns(0x%x).", |                                 "mb controller set descriptor fail, returns(0x%x).", | ||||||
|                                 (uint32_t)err); |                                 (uint32_t)err); | ||||||
|     ESP_LOGI(MASTER_TAG, "Modbus master stack initialized..."); |     ESP_LOGI(TAG, "Modbus master stack initialized..."); | ||||||
|  |  | ||||||
|     err = mbc_master_start(); |     err = mbc_master_start(); | ||||||
|     MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                             TAG, | ||||||
|                             "mb controller start fail, returns(0x%x).", |                             "mb controller start fail, returns(0x%x).", | ||||||
|                             (uint32_t)err); |                             (uint32_t)err); | ||||||
|     vTaskDelay(5); |     vTaskDelay(5); | ||||||
| @@ -620,10 +684,11 @@ static esp_err_t master_init(mb_communication_info_t* comm_info) | |||||||
| static esp_err_t master_destroy(void) | static esp_err_t master_destroy(void) | ||||||
| { | { | ||||||
|     esp_err_t err = mbc_master_destroy(); |     esp_err_t err = mbc_master_destroy(); | ||||||
|     MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                 TAG, | ||||||
|                                 "mbc_master_destroy fail, returns(0x%x).", |                                 "mbc_master_destroy fail, returns(0x%x).", | ||||||
|                                 (uint32_t)err); |                                 (uint32_t)err); | ||||||
|     ESP_LOGI(MASTER_TAG, "Modbus master stack destroy..."); |     ESP_LOGI(TAG, "Modbus master stack destroy..."); | ||||||
|     return err; |     return err; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ menu "Modbus Example Configuration" | |||||||
|  |  | ||||||
|     config MB_SLAVE_ADDR |     config MB_SLAVE_ADDR | ||||||
|         int "Modbus slave address" |         int "Modbus slave address" | ||||||
|         range 1 127 |         range 1 255 | ||||||
|         default 1 |         default 1 | ||||||
|         help |         help | ||||||
|             This is the Modbus slave address in the network. |             This is the Modbus slave address in the network. | ||||||
|   | |||||||
| @@ -8,7 +8,6 @@ | |||||||
| #include "esp_err.h" | #include "esp_err.h" | ||||||
| #include "sdkconfig.h" | #include "sdkconfig.h" | ||||||
| #include "esp_log.h" | #include "esp_log.h" | ||||||
|  |  | ||||||
| #include "esp_system.h" | #include "esp_system.h" | ||||||
| #include "esp_wifi.h" | #include "esp_wifi.h" | ||||||
| #include "esp_event.h" | #include "esp_event.h" | ||||||
| @@ -47,13 +46,7 @@ | |||||||
|                                                 | MB_EVENT_COILS_WR) |                                                 | MB_EVENT_COILS_WR) | ||||||
| #define MB_READ_WRITE_MASK                  (MB_READ_MASK | MB_WRITE_MASK) | #define MB_READ_WRITE_MASK                  (MB_READ_MASK | MB_WRITE_MASK) | ||||||
|  |  | ||||||
| #define SLAVE_TAG "SLAVE_TEST" | static const char *TAG = "SLAVE_TEST"; | ||||||
|  |  | ||||||
| #define SLAVE_CHECK(a, ret_val, str, ...) \ |  | ||||||
|     if (!(a)) { \ |  | ||||||
|         ESP_LOGE(SLAVE_TAG, "%s(%u): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ |  | ||||||
|         return (ret_val); \ |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| static portMUX_TYPE param_lock = portMUX_INITIALIZER_UNLOCKED; | static portMUX_TYPE param_lock = portMUX_INITIALIZER_UNLOCKED; | ||||||
|  |  | ||||||
| @@ -167,8 +160,8 @@ static void slave_operation_func(void *arg) | |||||||
| { | { | ||||||
|     mb_param_info_t reg_info; // keeps the Modbus registers access information |     mb_param_info_t reg_info; // keeps the Modbus registers access information | ||||||
|  |  | ||||||
|     ESP_LOGI(SLAVE_TAG, "Modbus slave stack initialized."); |     ESP_LOGI(TAG, "Modbus slave stack initialized."); | ||||||
|     ESP_LOGI(SLAVE_TAG, "Start modbus test..."); |     ESP_LOGI(TAG, "Start modbus test..."); | ||||||
|     // The cycle below will be terminated when parameter holding_data0 |     // The cycle below will be terminated when parameter holding_data0 | ||||||
|     // incremented each access cycle reaches the CHAN_DATA_MAX_VAL value. |     // incremented each access cycle reaches the CHAN_DATA_MAX_VAL value. | ||||||
|     for(;holding_reg_params.holding_data0 < MB_CHAN_DATA_MAX_VAL;) { |     for(;holding_reg_params.holding_data0 < MB_CHAN_DATA_MAX_VAL;) { | ||||||
| @@ -179,7 +172,7 @@ static void slave_operation_func(void *arg) | |||||||
|         if(event & (MB_EVENT_HOLDING_REG_WR | MB_EVENT_HOLDING_REG_RD)) { |         if(event & (MB_EVENT_HOLDING_REG_WR | MB_EVENT_HOLDING_REG_RD)) { | ||||||
|             // Get parameter information from parameter queue |             // Get parameter information from parameter queue | ||||||
|             ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); |             ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); | ||||||
|             ESP_LOGI(SLAVE_TAG, "HOLDING %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", |             ESP_LOGI(TAG, "HOLDING %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", | ||||||
|                     rw_str, |                     rw_str, | ||||||
|                     (uint32_t)reg_info.time_stamp, |                     (uint32_t)reg_info.time_stamp, | ||||||
|                     (uint32_t)reg_info.mb_offset, |                     (uint32_t)reg_info.mb_offset, | ||||||
| @@ -197,7 +190,7 @@ static void slave_operation_func(void *arg) | |||||||
|             } |             } | ||||||
|         } else if (event & MB_EVENT_INPUT_REG_RD) { |         } else if (event & MB_EVENT_INPUT_REG_RD) { | ||||||
|             ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); |             ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); | ||||||
|             ESP_LOGI(SLAVE_TAG, "INPUT READ (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", |             ESP_LOGI(TAG, "INPUT READ (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", | ||||||
|                     (uint32_t)reg_info.time_stamp, |                     (uint32_t)reg_info.time_stamp, | ||||||
|                     (uint32_t)reg_info.mb_offset, |                     (uint32_t)reg_info.mb_offset, | ||||||
|                     (uint32_t)reg_info.type, |                     (uint32_t)reg_info.type, | ||||||
| @@ -205,7 +198,7 @@ static void slave_operation_func(void *arg) | |||||||
|                     (uint32_t)reg_info.size); |                     (uint32_t)reg_info.size); | ||||||
|         } else if (event & MB_EVENT_DISCRETE_RD) { |         } else if (event & MB_EVENT_DISCRETE_RD) { | ||||||
|             ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); |             ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); | ||||||
|             ESP_LOGI(SLAVE_TAG, "DISCRETE READ (%u us): ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", |             ESP_LOGI(TAG, "DISCRETE READ (%u us): ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", | ||||||
|                                 (uint32_t)reg_info.time_stamp, |                                 (uint32_t)reg_info.time_stamp, | ||||||
|                                 (uint32_t)reg_info.mb_offset, |                                 (uint32_t)reg_info.mb_offset, | ||||||
|                                 (uint32_t)reg_info.type, |                                 (uint32_t)reg_info.type, | ||||||
| @@ -213,7 +206,7 @@ static void slave_operation_func(void *arg) | |||||||
|                                 (uint32_t)reg_info.size); |                                 (uint32_t)reg_info.size); | ||||||
|         } else if (event & (MB_EVENT_COILS_RD | MB_EVENT_COILS_WR)) { |         } else if (event & (MB_EVENT_COILS_RD | MB_EVENT_COILS_WR)) { | ||||||
|             ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); |             ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); | ||||||
|             ESP_LOGI(SLAVE_TAG, "COILS %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", |             ESP_LOGI(TAG, "COILS %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", | ||||||
|                                 rw_str, |                                 rw_str, | ||||||
|                                 (uint32_t)reg_info.time_stamp, |                                 (uint32_t)reg_info.time_stamp, | ||||||
|                                 (uint32_t)reg_info.mb_offset, |                                 (uint32_t)reg_info.mb_offset, | ||||||
| @@ -224,7 +217,7 @@ static void slave_operation_func(void *arg) | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     // Destroy of Modbus controller on alarm |     // Destroy of Modbus controller on alarm | ||||||
|     ESP_LOGI(SLAVE_TAG,"Modbus controller destroyed."); |     ESP_LOGI(TAG,"Modbus controller destroyed."); | ||||||
|     vTaskDelay(100); |     vTaskDelay(100); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -235,15 +228,18 @@ static esp_err_t init_services(void) | |||||||
|       ESP_ERROR_CHECK(nvs_flash_erase()); |       ESP_ERROR_CHECK(nvs_flash_erase()); | ||||||
|       result = nvs_flash_init(); |       result = nvs_flash_init(); | ||||||
|     } |     } | ||||||
|     SLAVE_CHECK((result == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                             TAG, | ||||||
|                             "nvs_flash_init fail, returns(0x%x).", |                             "nvs_flash_init fail, returns(0x%x).", | ||||||
|                             (uint32_t)result); |                             (uint32_t)result); | ||||||
|     result = esp_netif_init(); |     result = esp_netif_init(); | ||||||
|     SLAVE_CHECK((result == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                             TAG, | ||||||
|                             "esp_netif_init fail, returns(0x%x).", |                             "esp_netif_init fail, returns(0x%x).", | ||||||
|                             (uint32_t)result); |                             (uint32_t)result); | ||||||
|     result = esp_event_loop_create_default(); |     result = esp_event_loop_create_default(); | ||||||
|     SLAVE_CHECK((result == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                             TAG, | ||||||
|                             "esp_event_loop_create_default fail, returns(0x%x).", |                             "esp_event_loop_create_default fail, returns(0x%x).", | ||||||
|                             (uint32_t)result); |                             (uint32_t)result); | ||||||
| #if CONFIG_MB_MDNS_IP_RESOLVER | #if CONFIG_MB_MDNS_IP_RESOLVER | ||||||
| @@ -254,12 +250,14 @@ static esp_err_t init_services(void) | |||||||
|     // Read "Establishing Wi-Fi or Ethernet Connection" section in |     // Read "Establishing Wi-Fi or Ethernet Connection" section in | ||||||
|     // examples/protocols/README.md for more information about this function. |     // examples/protocols/README.md for more information about this function. | ||||||
|     result = example_connect(); |     result = example_connect(); | ||||||
|     SLAVE_CHECK((result == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                 TAG, | ||||||
|                                 "example_connect fail, returns(0x%x).", |                                 "example_connect fail, returns(0x%x).", | ||||||
|                                 (uint32_t)result); |                                 (uint32_t)result); | ||||||
| #if CONFIG_EXAMPLE_CONNECT_WIFI | #if CONFIG_EXAMPLE_CONNECT_WIFI | ||||||
|     result = esp_wifi_set_ps(WIFI_PS_NONE); |     result = esp_wifi_set_ps(WIFI_PS_NONE); | ||||||
|     SLAVE_CHECK((result == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((result == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                    TAG, | ||||||
|                                    "esp_wifi_set_ps fail, returns(0x%x).", |                                    "esp_wifi_set_ps fail, returns(0x%x).", | ||||||
|                                    (uint32_t)result); |                                    (uint32_t)result); | ||||||
| #endif | #endif | ||||||
| @@ -271,19 +269,23 @@ static esp_err_t destroy_services(void) | |||||||
|     esp_err_t err = ESP_OK; |     esp_err_t err = ESP_OK; | ||||||
|  |  | ||||||
|     err = example_disconnect(); |     err = example_disconnect(); | ||||||
|     SLAVE_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                    TAG, | ||||||
|                                    "example_disconnect fail, returns(0x%x).", |                                    "example_disconnect fail, returns(0x%x).", | ||||||
|                                    (uint32_t)err); |                                    (uint32_t)err); | ||||||
|     err = esp_event_loop_delete_default(); |     err = esp_event_loop_delete_default(); | ||||||
|     SLAVE_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                        TAG, | ||||||
|                                        "esp_event_loop_delete_default fail, returns(0x%x).", |                                        "esp_event_loop_delete_default fail, returns(0x%x).", | ||||||
|                                        (uint32_t)err); |                                        (uint32_t)err); | ||||||
|     err = esp_netif_deinit(); |     err = esp_netif_deinit(); | ||||||
|     SLAVE_CHECK((err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED), ESP_ERR_INVALID_STATE, | ||||||
|  |                                         TAG, | ||||||
|                                         "esp_netif_deinit fail, returns(0x%x).", |                                         "esp_netif_deinit fail, returns(0x%x).", | ||||||
|                                         (uint32_t)err); |                                         (uint32_t)err); | ||||||
|     err = nvs_flash_deinit(); |     err = nvs_flash_deinit(); | ||||||
|     SLAVE_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                 TAG, | ||||||
|                                 "nvs_flash_deinit fail, returns(0x%x).", |                                 "nvs_flash_deinit fail, returns(0x%x).", | ||||||
|                                 (uint32_t)err); |                                 (uint32_t)err); | ||||||
| #if CONFIG_MB_MDNS_IP_RESOLVER | #if CONFIG_MB_MDNS_IP_RESOLVER | ||||||
| @@ -301,7 +303,8 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info) | |||||||
|  |  | ||||||
|     // Initialization of Modbus controller |     // Initialization of Modbus controller | ||||||
|     esp_err_t err = mbc_slave_init_tcp(&slave_handler); |     esp_err_t err = mbc_slave_init_tcp(&slave_handler); | ||||||
|     SLAVE_CHECK((err == ESP_OK && slave_handler != NULL), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK && slave_handler != NULL), ESP_ERR_INVALID_STATE, | ||||||
|  |                                 TAG, | ||||||
|                                 "mb controller initialization fail."); |                                 "mb controller initialization fail."); | ||||||
|  |  | ||||||
|     comm_info->ip_addr = NULL; // Bind to any address |     comm_info->ip_addr = NULL; // Bind to any address | ||||||
| @@ -309,7 +312,8 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info) | |||||||
|  |  | ||||||
|     // Setup communication parameters and start stack |     // Setup communication parameters and start stack | ||||||
|     err = mbc_slave_setup((void*)comm_info); |     err = mbc_slave_setup((void*)comm_info); | ||||||
|     SLAVE_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                         TAG, | ||||||
|                                         "mbc_slave_setup fail, returns(0x%x).", |                                         "mbc_slave_setup fail, returns(0x%x).", | ||||||
|                                         (uint32_t)err); |                                         (uint32_t)err); | ||||||
|  |  | ||||||
| @@ -324,7 +328,8 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info) | |||||||
|     reg_area.address = (void*)&holding_reg_params.holding_data0; // Set pointer to storage instance |     reg_area.address = (void*)&holding_reg_params.holding_data0; // Set pointer to storage instance | ||||||
|     reg_area.size = sizeof(float) << 2; // Set the size of register storage instance |     reg_area.size = sizeof(float) << 2; // Set the size of register storage instance | ||||||
|     err = mbc_slave_set_descriptor(reg_area); |     err = mbc_slave_set_descriptor(reg_area); | ||||||
|     SLAVE_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                     TAG, | ||||||
|                                     "mbc_slave_set_descriptor fail, returns(0x%x).", |                                     "mbc_slave_set_descriptor fail, returns(0x%x).", | ||||||
|                                     (uint32_t)err); |                                     (uint32_t)err); | ||||||
|  |  | ||||||
| @@ -333,7 +338,8 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info) | |||||||
|     reg_area.address = (void*)&holding_reg_params.holding_data4; // Set pointer to storage instance |     reg_area.address = (void*)&holding_reg_params.holding_data4; // Set pointer to storage instance | ||||||
|     reg_area.size = sizeof(float) << 2; // Set the size of register storage instance |     reg_area.size = sizeof(float) << 2; // Set the size of register storage instance | ||||||
|     err = mbc_slave_set_descriptor(reg_area); |     err = mbc_slave_set_descriptor(reg_area); | ||||||
|     SLAVE_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                     TAG, | ||||||
|                                     "mbc_slave_set_descriptor fail, returns(0x%x).", |                                     "mbc_slave_set_descriptor fail, returns(0x%x).", | ||||||
|                                     (uint32_t)err); |                                     (uint32_t)err); | ||||||
|  |  | ||||||
| @@ -343,7 +349,8 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info) | |||||||
|     reg_area.address = (void*)&input_reg_params.input_data0; |     reg_area.address = (void*)&input_reg_params.input_data0; | ||||||
|     reg_area.size = sizeof(float) << 2; |     reg_area.size = sizeof(float) << 2; | ||||||
|     err = mbc_slave_set_descriptor(reg_area); |     err = mbc_slave_set_descriptor(reg_area); | ||||||
|     SLAVE_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                         TAG, | ||||||
|                                         "mbc_slave_set_descriptor fail, returns(0x%x).", |                                         "mbc_slave_set_descriptor fail, returns(0x%x).", | ||||||
|                                         (uint32_t)err); |                                         (uint32_t)err); | ||||||
|     reg_area.type = MB_PARAM_INPUT; |     reg_area.type = MB_PARAM_INPUT; | ||||||
| @@ -351,7 +358,8 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info) | |||||||
|     reg_area.address = (void*)&input_reg_params.input_data4; |     reg_area.address = (void*)&input_reg_params.input_data4; | ||||||
|     reg_area.size = sizeof(float) << 2; |     reg_area.size = sizeof(float) << 2; | ||||||
|     err = mbc_slave_set_descriptor(reg_area); |     err = mbc_slave_set_descriptor(reg_area); | ||||||
|     SLAVE_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                         TAG, | ||||||
|                                         "mbc_slave_set_descriptor fail, returns(0x%x).", |                                         "mbc_slave_set_descriptor fail, returns(0x%x).", | ||||||
|                                         (uint32_t)err); |                                         (uint32_t)err); | ||||||
|  |  | ||||||
| @@ -361,7 +369,8 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info) | |||||||
|     reg_area.address = (void*)&coil_reg_params; |     reg_area.address = (void*)&coil_reg_params; | ||||||
|     reg_area.size = sizeof(coil_reg_params); |     reg_area.size = sizeof(coil_reg_params); | ||||||
|     err = mbc_slave_set_descriptor(reg_area); |     err = mbc_slave_set_descriptor(reg_area); | ||||||
|     SLAVE_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                     TAG, | ||||||
|                                     "mbc_slave_set_descriptor fail, returns(0x%x).", |                                     "mbc_slave_set_descriptor fail, returns(0x%x).", | ||||||
|                                     (uint32_t)err); |                                     (uint32_t)err); | ||||||
|  |  | ||||||
| @@ -371,7 +380,8 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info) | |||||||
|     reg_area.address = (void*)&discrete_reg_params; |     reg_area.address = (void*)&discrete_reg_params; | ||||||
|     reg_area.size = sizeof(discrete_reg_params); |     reg_area.size = sizeof(discrete_reg_params); | ||||||
|     err = mbc_slave_set_descriptor(reg_area); |     err = mbc_slave_set_descriptor(reg_area); | ||||||
|     SLAVE_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                     TAG, | ||||||
|                                     "mbc_slave_set_descriptor fail, returns(0x%x).", |                                     "mbc_slave_set_descriptor fail, returns(0x%x).", | ||||||
|                                     (uint32_t)err); |                                     (uint32_t)err); | ||||||
|  |  | ||||||
| @@ -380,7 +390,8 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info) | |||||||
|  |  | ||||||
|     // Starts of modbus controller and stack |     // Starts of modbus controller and stack | ||||||
|     err = mbc_slave_start(); |     err = mbc_slave_start(); | ||||||
|     SLAVE_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                         TAG, | ||||||
|                                         "mbc_slave_start fail, returns(0x%x).", |                                         "mbc_slave_start fail, returns(0x%x).", | ||||||
|                                         (uint32_t)err); |                                         (uint32_t)err); | ||||||
|     vTaskDelay(5); |     vTaskDelay(5); | ||||||
| @@ -390,7 +401,8 @@ static esp_err_t slave_init(mb_communication_info_t* comm_info) | |||||||
| static esp_err_t slave_destroy(void) | static esp_err_t slave_destroy(void) | ||||||
| { | { | ||||||
|     esp_err_t err = mbc_slave_destroy(); |     esp_err_t err = mbc_slave_destroy(); | ||||||
|     SLAVE_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, |     MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, | ||||||
|  |                                 TAG, | ||||||
|                                 "mbc_slave_destroy fail, returns(0x%x).", |                                 "mbc_slave_destroy fail, returns(0x%x).", | ||||||
|                                 (uint32_t)err); |                                 (uint32_t)err); | ||||||
|     return err; |     return err; | ||||||
| @@ -405,7 +417,7 @@ void app_main(void) | |||||||
|     ESP_ERROR_CHECK(init_services()); |     ESP_ERROR_CHECK(init_services()); | ||||||
|  |  | ||||||
|     // Set UART log level |     // Set UART log level | ||||||
|     esp_log_level_set(SLAVE_TAG, ESP_LOG_INFO); |     esp_log_level_set(TAG, ESP_LOG_INFO); | ||||||
|  |  | ||||||
|     mb_communication_info_t comm_info = { 0 }; |     mb_communication_info_t comm_info = { 0 }; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user