enc28j60: no mem for receive buffer
Posted: Tue Jul 18, 2023 6:33 am
I am using esp-idf 4.4.4 version and I have used the component files of enc28j60 from the example of same version and updated version as well but still getting this error E (15177429) enc28j60: no mem for receive buffer after 1 or 2 days.
This is my ethernet.c
I have used the esp_eth_phy_enc28j60.c and esp_eth_mac_enc28j60.c from the examples.
Any advice will be appreciated.
This is my ethernet.c
Code: Select all
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "driver/gpio.h"
#include "nvs_flash.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "esp_eth.h"
#include "esp_eth_phy.h" //v6
#include "esp_event.h"
#include "./include/ethernet.h"
#include "./include/io.h"
#include "./include/nvs_read_write.h"
#include "./include/rtc.h"
#include "./include/mqtt.h"
#define TAG "ETHERNET"
//++ MODES
#define STATIC 0
#define DHCP 1
// Default Values
#define MODE DHCP
#define STATIC_IP "192.168.0.111" // v6
#define STATIC_GW "192.168.0.1" // v6
#define STATIC_SN "255.255.255.0" // v6
#define STATIC_DNS1 "8.8.8.8" // v6
#define STATIC_DNS2 "8.8.2.2" // v6
extern bool mqtt_connected;
extern char mac_id[18]; //++ TO GET THE DEVICE MAC ID //v6
bool eth_con_flag = false;
// esp_netif_t *eth_netif;
static EventGroupHandle_t ethernet_events;
static const int CONNECTED_GOT_IP = BIT0;
static const int DISCONNECTED = BIT1;
char ethernet_dynamic_ip[20]; //++ to store ethernet ip when network is in dynamin mode
void eth_credential_read_nvs()
{
memset(ethernet_dynamic_ip, 0, sizeof(ethernet_dynamic_ip));
strcpy(ethernet_dynamic_ip, "-");
eth_configure.nvs_eth_dhcp = read_nvs_u8("network_page", "dhcp", MODE);
if (eth_configure.nvs_eth_dhcp == STATIC)
{
eth_configure.nvs_eth_ip = read_nvs_str("network_page", "static_ip", STATIC_IP);
eth_configure.nvs_eth_gw = read_nvs_str("network_page", "static_gw", STATIC_GW);
eth_configure.nvs_eth_snt = read_nvs_str("network_page", "static_snt", STATIC_SN);
eth_configure.nvs_eth_dns1 = read_nvs_str("network_page", "static_dns1", STATIC_DNS1);
eth_configure.nvs_eth_dns2 = read_nvs_str("network_page", "static_dns2", STATIC_DNS2);
}
vTaskDelay(50 / portTICK_PERIOD_MS);
}
static esp_err_t example_set_dns_server(esp_netif_t *netif, uint32_t addr, esp_netif_dns_type_t type)
{
if (addr && (addr != IPADDR_NONE))
{
esp_netif_dns_info_t dns;
dns.ip.u_addr.ip4.addr = addr;
dns.ip.type = IPADDR_TYPE_V4;
esp_netif_set_dns_info(netif, type, &dns);
}
return ESP_OK;
}
static void ethernet_set_static_ip(esp_netif_t *netif)
{
if (esp_netif_dhcpc_stop(netif) != ESP_OK)
{
ESP_LOGE(TAG, "Failed to stop dhcp client");
return;
}
esp_netif_ip_info_t ip;
memset(&ip, 0, sizeof(esp_netif_ip_info_t));
ip.ip.addr = ipaddr_addr(eth_configure.nvs_eth_ip);
ip.netmask.addr = ipaddr_addr(eth_configure.nvs_eth_snt);
ip.gw.addr = ipaddr_addr(eth_configure.nvs_eth_gw);
if (esp_netif_set_ip_info(netif, &ip) != ESP_OK)
{
ESP_LOGE(TAG, "Failed to set ip info");
return;
}
ESP_ERROR_CHECK(example_set_dns_server(netif, ipaddr_addr(eth_configure.nvs_eth_dns1), ESP_NETIF_DNS_MAIN));
ESP_ERROR_CHECK(example_set_dns_server(netif, ipaddr_addr(eth_configure.nvs_eth_dns2), ESP_NETIF_DNS_BACKUP));
}
/** Event handler for Ethernet events */
void event_handler_for_ethernet(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]);
if (eth_configure.nvs_eth_dhcp == STATIC)
ethernet_set_static_ip(arg); // v6
break;
case ETHERNET_EVENT_DISCONNECTED:
ESP_LOGE(TAG, "Ethernet Link Down");
eth_con_flag = false;
xEventGroupSetBits(ethernet_events, DISCONNECTED);
if (mqtt_connected == true)
{
mqtt_app_stop();
mqtt_connected = false;
}
break;
case ETHERNET_EVENT_START:
ESP_LOGI(TAG, "Ethernet Started");
break;
case ETHERNET_EVENT_STOP:
ESP_LOGI(TAG, "Ethernet Stopped");
break;
case IP_EVENT_ETH_GOT_IP:
eth_con_flag = true;
eth_conn_count++;
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_netif_dns_info_t dns1, dns2;
// esp_netif_get_dns_info(eth_netif, ESP_NETIF_DNS_MAIN, &dns1);
// esp_netif_get_dns_info(eth_netif, ESP_NETIF_DNS_BACKUP, &dns2);
ESP_LOGI(TAG, "\n\nxx -- ETHERNET CONNECTED -- xx\n");
ESP_LOGI(TAG, "ethernet connection count: %d", eth_conn_count);
ESP_LOGI(TAG, "IP :" IPSTR, IP2STR(&ip_info->ip));
ESP_LOGI(TAG, "GATEWAY :" IPSTR, IP2STR(&ip_info->gw));
ESP_LOGI(TAG, "SUBNET :" IPSTR, IP2STR(&ip_info->netmask));
memset(ethernet_dynamic_ip, 0, sizeof(ethernet_dynamic_ip));
memset(eth_gw, 0, sizeof(eth_gw));
memset(eth_snt, 0, sizeof(eth_snt));
memset(eth_dns, 0, sizeof(eth_dns));
sprintf(ethernet_dynamic_ip, "" IPSTR, IP2STR(&ip_info->ip));
sprintf(eth_gw, "" IPSTR, IP2STR(&ip_info->gw));
sprintf(eth_snt, "" IPSTR, IP2STR(&ip_info->netmask));
// sprintf(eth_dns, "" IPSTR, IP2STR(&dns1.ip.u_addr.ip4));
eth_configure.nvs_eth_ip = ethernet_dynamic_ip;
eth_configure.nvs_eth_gw = eth_gw;
eth_configure.nvs_eth_snt = eth_snt;
eth_configure.nvs_eth_dns1 = eth_dns;
memset(eth_dns, 0, sizeof(eth_dns));
// sprintf(eth_dns, "" IPSTR, IP2STR(&dns2.ip.u_addr.ip4));
eth_configure.nvs_eth_dns2 = eth_dns;
if (eth_configure.nvs_eth_dhcp == STATIC)
{
// ESP_LOGI(TAG, "DNS1 :" IPSTR, IP2STR(&dns1.ip.u_addr.ip4));
// ESP_LOGI(TAG, "DNS2 :" IPSTR, IP2STR(&dns2.ip.u_addr.ip4));
ESP_LOGI(TAG, "MODE : STATIC");
}
else
{
ESP_LOGI(TAG, "MODE : DHCP");
}
ESP_LOGI(TAG, "\n\nxx -- ETHERNET CONNECTED -- xx\n");
vTaskDelay(50 / portTICK_PERIOD_MS);
get_sntp_time();
mqtt_app_start(mac_id);
xEventGroupSetBits(ethernet_events, CONNECTED_GOT_IP);
break;
default:
break;
}
}
void ethernet_init(uint8_t mac_addr[])
{
ESP_LOGI(TAG, "\n\nxx -- INITIALISING ETHERNET -- xx\n");
eth_credential_read_nvs();
ethernet_events = xEventGroupCreate();
ESP_ERROR_CHECK(esp_netif_init());
// Create default event loop that running in background
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH();
esp_netif_t *eth_netif = esp_netif_new(&netif_cfg);
spi_bus_config_t buscfg = {
.miso_io_num = ETH_SPI_MISO,
.mosi_io_num = ETH_SPI_MOSI,
.sclk_io_num = ETH_SPI_SCK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
};
ESP_ERROR_CHECK(spi_bus_initialize(ETH_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
/* ENC28J60 ethernet driver is based on spi driver */
spi_device_interface_config_t devcfg = {
.command_bits = 3,
.address_bits = 5,
.mode = 0,
.clock_speed_hz = ETH_SPI_CLOCK_MHZ * 1000 * 1000,
.spics_io_num = 5,
.queue_size = 20,
.cs_ena_posttrans = enc28j60_cal_spi_cs_hold_time(ETH_SPI_CLOCK_MHZ),
};
spi_device_handle_t spi_handle = NULL;
ESP_ERROR_CHECK(spi_bus_add_device(ETH_SPI_HOST, &devcfg, &spi_handle));
eth_enc28j60_config_t enc28j60_config = ETH_ENC28J60_DEFAULT_CONFIG(spi_handle);
enc28j60_config.int_gpio_num = ETH_INT_GPIO;
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
mac_config.smi_mdc_gpio_num = -1; // ENC28J60 doesn't have SMI interface
mac_config.smi_mdio_gpio_num = -1;
esp_eth_mac_t *mac = esp_eth_mac_new_enc28j60(&enc28j60_config, &mac_config);
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
phy_config.autonego_timeout_ms = 0; // ENC28J60 doesn't support auto-negotiation
phy_config.reset_gpio_num = -1; // ENC28J60 doesn't have a pin to reset internal PHY
esp_eth_phy_t *phy = esp_eth_phy_new_enc28j60(&phy_config);
esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy);
esp_eth_handle_t eth_handle = NULL;
ESP_ERROR_CHECK(esp_eth_driver_install(ð_config, ð_handle));
/* ENC28J60 doesn't burn any factory MAC address, we need 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.
*/
mac->set_addr(mac, (uint8_t[]){
base_mac_addr[0], base_mac_addr[1], base_mac_addr[2], base_mac_addr[3], base_mac_addr[4], base_mac_addr[5]});
// ENC28J60 Errata #1 check
if (emac_enc28j60_get_chip_info(mac) < ENC28J60_REV_B5 && 8 < 8)
{
ESP_LOGE(TAG, "SPI frequency must be at least 8 MHz for chip revision less than 5");
ESP_ERROR_CHECK(ESP_FAIL);
}
/* attach Ethernet driver to TCP/IP stack */
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)));
// Register user defined event handers
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &event_handler_for_ethernet, eth_netif));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &event_handler_for_ethernet, eth_netif));
/* start Ethernet driver state machine */
ESP_ERROR_CHECK(esp_eth_start(eth_handle));
/* Set duplex needs to be called after esp_eth_start since the driver is started with auto-negotiation by default */
esp_err_t duplex_mode_status = enc28j60_set_phy_duplex(phy, ETH_DUPLEX_FULL);
if (duplex_mode_status == ESP_OK)
{
ESP_LOGI(TAG, "[ ETHERNET TRANSMISSION MODE SET TO FULL DUPLEX ]");
}
xEventGroupWaitBits(ethernet_events, CONNECTED_GOT_IP | DISCONNECTED, pdTRUE, pdFALSE, pdMS_TO_TICKS(10000));
esp_netif_dhcp_status_t status;
esp_netif_dhcpc_get_status(eth_netif, &status);
ESP_LOGW(TAG, " DHCPC (state=%u)", status);
if (status == 0x0)
{
// esp_err_t err_dhcp = esp_netif_dhcpc_start(eth_netif); // commented
ESP_LOGI(TAG, "DHCP client status : %s", esp_err_to_name(status));
ESP_LOGI(TAG, "[ Restarting ESP32 ]");
esp_restart();
}
}
Any advice will be appreciated.