esp_netif_ip_info_t info_ip;
// Initialize TCP/IP network interface (should be called only once in application)
ESP_ERROR_CHECK(esp_netif_init());
// Create default event loop that running in background
ESP_ERROR_CHECK(esp_event_loop_create_default());
// Create instance(s) of esp-netif for SPI Ethernet(s)
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
esp_netif_config.if_desc = "eth0";
esp_netif_config_t cfg_spi = {
.base = &esp_netif_config,
.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH
};
esp_netif_t *eth_netif_spi = { NULL };
char if_key_str[10];
char if_desc_str[10];
char num_str[3];
itoa(0, num_str, 10);
strcat(strcpy(if_key_str, "ETH_SPI_"), num_str);
strcat(strcpy(if_desc_str, "eth"), num_str);
esp_netif_config.if_key = if_key_str;
esp_netif_config.if_desc = if_desc_str;
esp_netif_config.route_prio = 30;
eth_netif_spi = esp_netif_new(&cfg_spi);
ESP_ERROR_CHECK(esp_netif_dhcpc_stop(eth_netif_spi));
char* ip= "10.25.10.2";
char* gateway = "10.25.0.1";
char* netmask = "255.255.0.0";
esp_netif_ip_info_t info_t;
memset(&info_t, 0, sizeof(esp_netif_ip_info_t));
info_t.ip.addr = esp_ip4addr_aton((const char *)ip);
info_t.gw.addr = esp_ip4addr_aton((const char *)gateway);
info_t.netmask.addr = esp_ip4addr_aton((const char *)netmask);
esp_netif_set_ip_info(eth_netif_spi, &info_t);
// Init MAC and PHY configs to default
eth_mac_config_t mac_config_spi = ETH_MAC_DEFAULT_CONFIG();
eth_phy_config_t phy_config_spi = ETH_PHY_DEFAULT_CONFIG();
// Init SPI bus
spi_device_handle_t spi_handle = { NULL };
spi_bus_config_t buscfg = {
.miso_io_num = GPIO_NUM_36,
.mosi_io_num = GPIO_NUM_19,
.sclk_io_num = GPIO_NUM_18,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
};
// Install GPIO ISR handler to be able to service SPI Eth modlues interrupts
gpio_install_isr_service(0);
ESP_ERROR_CHECK(spi_bus_initialize(SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
// Init specific SPI Ethernet module configuration from Kconfig (CS GPIO, Interrupt GPIO, etc.)
spi_eth_module_config_t spi_eth_module_config = {
.spi_cs_gpio = GPIO_NUM_5,
.phy_reset_gpio = GPIO_NUM_27,
.int_gpio = GPIO_NUM_4,
.phy_addr = 10
};
// Configure SPI interface and Ethernet driver for specific SPI module
esp_eth_mac_t *mac_spi;
esp_eth_phy_t *phy_spi;
esp_eth_handle_t eth_handle_spi = { NULL };
spi_device_interface_config_t devcfg = {
.command_bits = 16, // Actually it's the address phase in W5500 SPI frame
.address_bits = 8, // Actually it's the control phase in W5500 SPI frame
.mode = 0,
.clock_speed_hz = 10 * 1000 * 1000,
.queue_size = 20
};
// Set SPI module Chip Select GPIO
devcfg.spics_io_num = spi_eth_module_config.spi_cs_gpio;
ESP_ERROR_CHECK(spi_bus_add_device(SPI_HOST, &devcfg, &spi_handle));
// w5500 ethernet driver is based on spi driver
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle);
// Set remaining GPIO numbers and configuration used by the SPI module
w5500_config.int_gpio_num = spi_eth_module_config.int_gpio;
phy_config_spi.phy_addr = spi_eth_module_config.phy_addr;
phy_config_spi.reset_gpio_num = spi_eth_module_config.phy_reset_gpio;
mac_spi = esp_eth_mac_new_w5500(&w5500_config, &mac_config_spi);
phy_spi = esp_eth_phy_new_w5500(&phy_config_spi);
esp_eth_config_t eth_config_spi = ETH_DEFAULT_CONFIG(mac_spi, phy_spi);
ESP_ERROR_CHECK(esp_eth_driver_install(ð_config_spi, ð_handle_spi));
/* The SPI Ethernet module might not have a burned factory MAC address, we cat to set it manually.
02:00:00 is a Locally Administered OUI range so should not be used except when testing on a LAN under your control.*/
ESP_ERROR_CHECK(esp_eth_ioctl(eth_handle_spi, ETH_CMD_S_MAC_ADDR, (uint8_t[]) {
0x00, 0x12, 0xCF, 0xC1, 0x55, 0xE2
}));
// attach Ethernet driver to TCP/IP stack
ESP_ERROR_CHECK(esp_netif_attach(eth_netif_spi, esp_eth_new_netif_glue(eth_handle_spi)));
// Register user defined event handers
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
/* start Ethernet driver state machine */
ESP_ERROR_CHECK(esp_eth_start(eth_handle_spi));
mb_register_area_descriptor_t reg_area; // Modbus register area descriptor structure
void* slave_handler = NULL;
// Initialization of Modbus controller
esp_err_t err = mbc_slave_init_tcp(&slave_handler);
MB_RETURN_ON_FALSE((err == ESP_OK && slave_handler != NULL), ESP_ERR_INVALID_STATE,
SLAVE_TAG,
"mb controller initialization fail.");
mb_communication_info_t comm_info = {
.ip_port = MB_TCP_SLAVE_PORT, // Modbus TCP port number (default = 502)
.ip_addr_type = MB_IPV4, // version of IP protocol
.ip_mode = MB_MODE_TCP, // Port communication mode
.ip_addr = NULL, // This field keeps the client IP address to bind, NULL - bind to any client
.ip_netif_ptr = (void*)eth_handle_spi // esp_netif_ptr - pointer to the corresponding network interface
};
// Setup communication parameters and start stack
err = mbc_slave_setup((void*)&comm_info);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
SLAVE_TAG,
"mbc_slave_setup fail, returns(0x%x).",
(uint32_t)err);
reg_area.type = MB_PARAM_HOLDING; // Set type of register area
reg_area.start_offset = MB_REG_HOLDING_START_AREA0; // Offset of register area in Modbus protocol
reg_area.address = (void*)&holding_reg_area[0]; // Set pointer to storage instance
reg_area.size = sizeof(holding_reg_area) << 1; // Set the size of register storage area in bytes
ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
SLAVE_TAG,
"mbc_slave_set_descriptor fail, returns(0x%x).",
(uint32_t)err);
// Starts of modbus controller and stack
err = mbc_slave_start();
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE,
SLAVE_TAG,
"mbc_slave_start fail, returns(0x%x).",
(uint32_t)err);
vTaskDelay(5);
printf("modbusTCP initialized\n");
esp_netif_get_ip_info(eth_handle_spi, &ip_info);
ESP_LOGI(SLAVE_TAG, "ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR,
IP2STR(&ip_info.ip),
IP2STR(&ip_info.netmask),
IP2STR(&ip_info.gw));
esp_netif_get_ip_info(eth_netif_spi, &ip_info);
ESP_LOGI(SLAVE_TAG, "ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR,
IP2STR(&ip_info.ip),
IP2STR(&ip_info.netmask),
IP2STR(&ip_info.gw));
holding_reg_area[0] = 0x01;
holding_reg_area[1] = 0x02;
return err;