Skip to content

Instantly share code, notes, and snippets.

@david-cermak
Created September 23, 2021 15:47
Show Gist options
  • Save david-cermak/87462309176722d6051ac2bd56e5d32b to your computer and use it in GitHub Desktop.
Save david-cermak/87462309176722d6051ac2bd56e5d32b to your computer and use it in GitHub Desktop.
eth_w5500_power_cycle_4.3.1.c
#include <string.h>
#include "sys/socket.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "freertos/task.h"
#include "esp_netif.h"
#include "esp_eth.h"
#include "esp_event.h"
#include "esp_log.h"
#include "sdkconfig.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"
#define PC_ADDR "...."
static const char *TAG = "eth_example";
esp_netif_t *eth_netif;
static EventGroupHandle_t event_group = NULL;
static const int CONNECT_BIT = BIT0;
/** Event handler for Ethernet events */
static void eth_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
uint8_t mac_addr[6] = {0};
/* we can get the ethernet driver handle from event data */
esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data;
switch (event_id) {
case ETHERNET_EVENT_CONNECTED:
esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
ESP_LOGI(TAG, "Ethernet Link Up");
ESP_LOGI(TAG, "Ethernet HW Addr %02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
break;
case ETHERNET_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "Ethernet Link Down");
break;
case ETHERNET_EVENT_START:
ESP_LOGI(TAG, "Ethernet Started");
break;
case ETHERNET_EVENT_STOP:
ESP_LOGI(TAG, "Ethernet Stopped");
break;
default:
break;
}
}
static void on_got_ipv6(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip);
ESP_LOGI(TAG, "Got IPv6 event: Interface \"%s\" address: " IPV6STR ", type: %d", esp_netif_get_desc(event->esp_netif),
IPV62STR(event->ip6_info.ip), ipv6_type);
xEventGroupSetBits(event_group, CONNECT_BIT);
}
/** Event handler for IP_EVENT_ETH_GOT_IP */
static void got_ip_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
const esp_netif_ip_info_t *ip_info = &event->ip_info;
ESP_LOGI(TAG, "Ethernet Got IP Address");
ESP_LOGI(TAG, "~~~~~~~~~~~");
ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip_info->ip));
ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask));
ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw));
ESP_LOGI(TAG, "~~~~~~~~~~~");
esp_netif_create_ip6_linklocal(eth_netif);
}
static void send_udp()
{
char rx_buffer[128];
char host_ip[] = PC_ADDR;
struct sockaddr_in6 dest_addr = { 0 };
inet6_aton(host_ip, &dest_addr.sin6_addr);
dest_addr.sin6_family = AF_INET6;
dest_addr.sin6_port = htons(3333);
dest_addr.sin6_scope_id = esp_netif_get_netif_impl_index(eth_netif);
int sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IPV6);
if (sock < 0) {
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
abort();
}
ESP_LOGI(TAG, "Sending data to %s", host_ip);
while (sendto(sock, "Command", 7, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)) < 0) {
ESP_LOGE(TAG, "Error occurred during sending: errno %d, retrying...", errno);
}
ESP_LOGI(TAG, "Message sent");
struct sockaddr_storage source_addr; // Large enough for both IPv4 or IPv6
socklen_t socklen = sizeof(source_addr);
int len = recvfrom(sock, rx_buffer, sizeof(rx_buffer) - 1, 0, (struct sockaddr *)&source_addr, &socklen);
if (len < 0) {
ESP_LOGE(TAG, "recvfrom failed: errno %d", errno);
abort();
} else {
rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
ESP_LOGI(TAG, "Received %d bytes from %s:", len, host_ip);
ESP_LOGI(TAG, "%s", rx_buffer);
if (strncmp(rx_buffer, "OK: ", 4) == 0) {
ESP_LOGI(TAG, "Received OK");
}
}
ESP_LOGI(TAG, "Shutting down the socket...");
shutdown(sock, 0);
close(sock);
}
void app_main(void) {
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
gpio_config_t io_conf = {0};
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.pin_bit_mask = BIT64(3);
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pull_up_en = 0;
io_conf.pull_down_en = 0;
gpio_config(&io_conf);
event_group = xEventGroupCreate();
gpio_install_isr_service(0);
spi_device_handle_t spi_handle = NULL;
spi_bus_config_t buscfg = {
.miso_io_num = CONFIG_EXAMPLE_ETH_SPI_MISO_GPIO,
.mosi_io_num = CONFIG_EXAMPLE_ETH_SPI_MOSI_GPIO,
.sclk_io_num = CONFIG_EXAMPLE_ETH_SPI_SCLK_GPIO,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
};
ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_ETH_SPI_HOST, &buscfg, 1));
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 = CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ * 1000 * 1000,
.spics_io_num = CONFIG_EXAMPLE_ETH_SPI_CS_GPIO,
.queue_size = 20
};
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle));
eth_netif = esp_netif_new(&cfg);
// Register user defined event handers
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL));
while (1) {
gpio_set_level(3, 0);
vTaskDelay(pdMS_TO_TICKS(1000));
ESP_ERROR_CHECK(esp_eth_set_default_handlers(eth_netif));
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR;
phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO;
/* w5500 ethernet driver is based on spi driver */
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle);
w5500_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO;
esp_eth_mac_t *mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
esp_eth_phy_t *phy = esp_eth_phy_new_w5500(&phy_config);
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
config.check_link_period_ms = 10;
esp_eth_handle_t eth_handle = NULL;
ESP_ERROR_CHECK(esp_eth_driver_install(&config, &eth_handle));
ESP_ERROR_CHECK(esp_eth_ioctl(eth_handle, ETH_CMD_S_MAC_ADDR, (uint8_t[]) {
0x02, 0x00, 0x00, 0x12, 0x34, 0x56
}));
/* attach Ethernet driver to TCP/IP stack */
void *glue = esp_eth_new_netif_glue(eth_handle);
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, glue));
ESP_ERROR_CHECK(esp_eth_start(eth_handle));
// wait for the IPv6 and send something
xEventGroupWaitBits(event_group, CONNECT_BIT, true, true, portMAX_DELAY);
send_udp();
vTaskDelay(pdMS_TO_TICKS(1000));
ESP_LOGI(TAG, "\nTurning OFF!!!\n");
ESP_ERROR_CHECK(esp_eth_stop(eth_handle));
ESP_ERROR_CHECK(esp_eth_del_netif_glue(glue));
ESP_ERROR_CHECK(esp_eth_clear_default_handlers(eth_netif));
ESP_ERROR_CHECK(esp_eth_driver_uninstall(eth_handle));
ESP_ERROR_CHECK(phy->del(phy));
ESP_ERROR_CHECK(mac->del(mac));
gpio_set_level(3, 1);
vTaskDelay(pdMS_TO_TICKS(10000));
ESP_LOGI(TAG, "\nTurning ON\n");
}
esp_netif_destroy(eth_netif);
vEventGroupDelete(event_group);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment