/* ethernet Example This example code is in the Public Domain (or CC0 licensed, at your option.) Unless required by applicable law or agreed to in writing, this software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ #include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_system.h" #include "esp_event_loop.h" #include "esp_event.h" #include "esp_log.h" #include "esp_eth.h" #include "rom/gpio.h" #include "tcpip_adapter.h" #include "driver/gpio.h" #include "driver/periph_ctrl.h" #include "driver/i2c.h" #define I2C_EXAMPLE_MASTER_NUM I2C_NUM_0 /*!< I2C port number for master dev */ #define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/ #define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */ #define LAST_NACK_VAL 0x2 /*!< I2C last_nack value */ #define KSZ8863_I2C_ADDRESS 0b10111110 //use register / bit definitions #define KSZ_REG_PORT1_STATUS0 30 #define KSZ_REG_PORT2_STATUS0 46 #define KSZ_REG_PORT3_STATUS_1 63 #define KSZ_REG_RESET 67 #define KSZ_BIT_LINK_GOOD 5 #define KSZ_BIT_SW_RESET 4 #define KSZ_BIT_SPEED 2 #define KSZ_BIT_DUPLEX 1 static const char *TAG = "eth_example"; /** * @brief gpio specific init * * @note RMII data pins are fixed in esp32: * TXD0 <=> GPIO19 * TXD1 <=> GPIO22 * TX_EN <=> GPIO21 * RXD0 <=> GPIO25 * RXD1 <=> GPIO26 * CLK <=> GPIO0 * */ static void eth_gpio_config_rmii(void) { //We cannot use SMI because not all registers are accessible using SMI, we use I2C instead } //Function to write multiple bytes to an I2C Device uint8_t i2c_write(uint8_t address, const uint8_t* data, uint8_t bytes, uint8_t startaddress) { uint8_t failed=0, i; i2c_cmd_handle_t cmd = i2c_cmd_link_create(); if(i2c_master_start(cmd) != ESP_OK ) { failed |= 1; ESP_LOGI("I2C", "i2c_master_start failed"); } if(i2c_master_write_byte(cmd, address | I2C_MASTER_WRITE, ACK_CHECK_EN) != ESP_OK ) { failed |= 1; ESP_LOGI("I2C", "i2c_master_write_byte failed"); } for (i = 0; i < bytes; i++){ if(i2c_master_write_byte(cmd, startaddress++, ACK_CHECK_EN)!= ESP_OK ) { failed |= 1; ESP_LOGI("I2C", "i2c_master_start 2 failed"); } if(i2c_master_write_byte(cmd, data[i], ACK_CHECK_EN)!= ESP_OK ) { failed |= 1; ESP_LOGI("I2C", "i2c_master_start 3 failed"); } } if(i2c_master_cmd_begin(I2C_EXAMPLE_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS)!= ESP_OK ) { failed |= 1; ESP_LOGI("I2C", "i2c_master_cmd_begin failed"); } i2c_cmd_link_delete(cmd); if(failed) ESP_LOGE("I2C","I2C_write failed"); return failed; } //Function to read multiple bytes from an I2C device uint8_t i2c_read(uint8_t address, uint8_t* data, uint8_t bytes, uint8_t startaddress) { uint8_t failed=0; i2c_cmd_handle_t cmd = i2c_cmd_link_create(); if(i2c_master_start(cmd) != ESP_OK ) { failed |= 1; ESP_LOGI("I2C", "i2c_master_start failed"); } if(i2c_master_write_byte(cmd, address | I2C_MASTER_WRITE, ACK_CHECK_EN) != ESP_OK ) { failed |= 1; ESP_LOGI("I2C", "i2c_master_write_byte 1 failed"); } //failed = i2c_start(address+I2C_WRITE); if(i2c_master_write_byte(cmd, startaddress, ACK_CHECK_EN) != ESP_OK ) { failed |= 1; ESP_LOGI("I2C", "i2c_master_write_byte 2 failed"); } //failed |= i2c_write(startaddress); //Registeradresse if(i2c_master_stop(cmd) != ESP_OK ) { failed |= 1; ESP_LOGI("I2C", "i2c_master_stop failed"); } if(i2c_master_cmd_begin(I2C_EXAMPLE_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS)!= ESP_OK ) { failed |= 1; ESP_LOGI("I2C", "i2c_master_cmd_begin failed"); } i2c_cmd_link_delete(cmd); cmd = i2c_cmd_link_create(); if(i2c_master_start(cmd)!= ESP_OK ) { failed |= 1; ESP_LOGI("I2C", "i2c_master_start 2 failed"); } if(i2c_master_write_byte(cmd, address | I2C_MASTER_READ, ACK_CHECK_EN)!= ESP_OK ) { failed |= 1; ESP_LOGI("I2C", "i2c_master_write_byte 3 failed"); } if(i2c_master_read(cmd, data, bytes, LAST_NACK_VAL)!= ESP_OK ) { failed |= 1; ESP_LOGI("I2C", "i2c_master_read failed"); } if(i2c_master_stop(cmd)!= ESP_OK ) { failed |= 1; ESP_LOGI("I2C", "i2c_master_stop 2 failed"); } if(i2c_master_cmd_begin(I2C_EXAMPLE_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS)!= ESP_OK ) { failed |= 1; ESP_LOGI("I2C", "i2c_master_cmd_begin 2 failed"); } i2c_cmd_link_delete(cmd); if(failed) ESP_LOGE("I2C","I2C_read failed"); return failed; } //Function to read a single 8Bit register from the KSZ8863 uint8_t ksz_read_reg(uint8_t reg) { uint8_t data; i2c_read(KSZ8863_I2C_ADDRESS, &data,1,reg); return data; } //Function to write a single 8Bit register to the KSZ8863 void ksz_write_reg(uint8_t reg, uint8_t value) { i2c_write(KSZ8863_I2C_ADDRESS, &value,1,reg); } bool ksz_phy_check_link(void) { // We cannot get a link status on Port 3 so we check Port 1 and Port 2 to see if any link is up uint8_t port1_status_0 = ksz_read_reg(KSZ_REG_PORT1_STATUS0); uint8_t port2_status_0 = ksz_read_reg(KSZ_REG_PORT2_STATUS0); bool linkOk= false; if(port1_status_0 & (1<event_id) { case SYSTEM_EVENT_ETH_CONNECTED: ESP_LOGI(TAG, "Ethernet Link Up"); break; case SYSTEM_EVENT_ETH_DISCONNECTED: ESP_LOGI(TAG, "Ethernet Link Down"); break; case SYSTEM_EVENT_ETH_START: ESP_LOGI(TAG, "Ethernet Started"); break; case SYSTEM_EVENT_ETH_GOT_IP: memset(&ip, 0, sizeof(tcpip_adapter_ip_info_t)); ESP_ERROR_CHECK(tcpip_adapter_get_ip_info(ESP_IF_ETH, &ip)); ESP_LOGI(TAG, "Ethernet Got IP Addr"); ESP_LOGI(TAG, "~~~~~~~~~~~"); ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip.ip)); ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip.netmask)); ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip.gw)); ESP_LOGI(TAG, "~~~~~~~~~~~"); break; case SYSTEM_EVENT_ETH_STOP: ESP_LOGI(TAG, "Ethernet Stopped"); break; default: break; } return ESP_OK; } void app_main() { //I2C init ESP_LOGI(TAG, "i2c_master_init started"); int i2c_master_port = I2C_EXAMPLE_MASTER_NUM; i2c_config_t conf; conf.mode = I2C_MODE_MASTER; conf.sda_io_num = 15; conf.sda_pullup_en = GPIO_PULLUP_ENABLE; conf.scl_io_num = 14; conf.scl_pullup_en = GPIO_PULLUP_ENABLE; conf.master.clk_speed = 100000; i2c_param_config(i2c_master_port, &conf); i2c_driver_install(i2c_master_port, conf.mode, 0, 0, 0); ESP_LOGI(TAG, "i2c_master_init finished"); //Dump all registers for(int i=0; i< 100; i++) { ESP_LOGI(TAG, "Read reg %d: 0x%02x", i, ksz_read_reg(i)); } tcpip_adapter_init(); ESP_ERROR_CHECK(esp_event_loop_init(eth_event_handler, NULL)); eth_config_t config; config.phy_addr = PHY0; config.mac_mode = ETH_MODE_RMII; config.clock_mode = ETH_CLOCK_GPIO0_OUT; config.tcpip_input = tcpip_adapter_eth_input; config.phy_init = ksz_phy_init; config.phy_check_link = ksz_phy_check_link; config.phy_check_init = ksz_phy_check_init; config.phy_get_speed_mode = ksz_phy_get_speed_mode; config.phy_get_duplex_mode = ksz_phy_get_duplex_mode; config.gpio_config = eth_gpio_config_rmii; config.flow_ctrl_enable = false; config.phy_get_partner_pause_enable = ksz_phy_get_partner_pause_enable; config.phy_power_enable = ksz_phy_power_enable; config.reset_timeout_ms = 1000; config.promiscuous_enable = false; ESP_ERROR_CHECK(esp_eth_init(&config)); ESP_ERROR_CHECK(esp_eth_enable()) ; }