espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
12.93k stars 7.09k forks source link

TCP: Failed to send data to server. Error code: 5 (IDFGH-12666) #13658

Open arvind55555 opened 2 months ago

arvind55555 commented 2 months ago

Answers checklist.

General issue report

Hi all, I am currently working on a SPI code that receives data from a transmitter, stores the data in a buffer, and then sends the data to a TCP socket via Wi-Fi. Additionally, I am using dual-core functionality, where one core takes care of SPI transactions and another core takes care of TCP transactions. The problem is that the code without dual-core setup works absolutely fine, but when I implement it with dual-core, I am facing the error "TCP: Failed to send data to the server." Error code: 5". Below is my code

#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "freertos/task.h"

#include "lwip/dns.h"
#include "lwip/igmp.h"
#include "lwip/netdb.h"
#include "lwip/sockets.h"

#include "driver/gpio.h"
#include "driver/ledc.h"
#include "driver/spi_slave.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "nvs_flash.h"
#include "soc/rtc_periph.h"
#include "spi_flash_mmap.h"

#define core_0 0
#define core_1 1

const char *ssid = "***";
const char *pass = "****";

#define SERVER_IP "***"
#define SERVER_PORT ***

#define GPIO_MOSI 23
#define GPIO_MISO 19
#define GPIO_SCLK 18
#define GPIO_CS 5

#define BUFFER_SIZE 16384
#define HALF_BUFFER_SIZE (BUFFER_SIZE / 2)

int sock = -1;

uint32_t buffer1[BUFFER_SIZE];
uint32_t buffer2[BUFFER_SIZE];

volatile uint32_t *currentTxBuffer;
volatile uint32_t *currentRxBuffer;

SemaphoreHandle_t dataReadySemaphore;

void initialize_socket() {
  sock = socket(AF_INET, SOCK_STREAM, 0);
  if (sock < 0) {
    ESP_LOGE("TCP", "Unable to create socket");
    return;
  }

  struct sockaddr_in server_address;
  memset(&server_address, 0, sizeof(server_address));
  server_address.sin_family = AF_INET;
  server_address.sin_port = htons(SERVER_PORT);
  inet_pton(AF_INET, SERVER_IP, &(server_address.sin_addr));

  if (connect(sock, (struct sockaddr *)&server_address,
              sizeof(server_address)) < 0) {
    ESP_LOGE("TCP", "Connection to server failed. Error code: %d", errno);
    close(sock);
    sock = -1;
    return;
  }

  ESP_LOGI("TCP", "Socket initialized successfully");
}

void send_data_to_socket(const char *data, size_t data_length) {
  if (sock < 0) {
    ESP_LOGI("TCP", "Socket not initialized, attempting to initialize...");
    initialize_socket();
    if (sock < 0) {
      ESP_LOGE("TCP", "Socket initialization failed, cannot send data");
      return;
    }
  }

  int sent_bytes = send(sock, data, data_length, 0);
  if (sent_bytes < 0) {
    ESP_LOGE("TCP", "Failed to send data to server. Error code: %d", errno);
  } else {
    ESP_LOGI("TCP", "Sent %d bytes to server", sent_bytes);
  }
}

void close_socket() {
  if (sock >= 0) {
    close(sock);
    sock = -1;
    ESP_LOGI("TCP", "Socket closed");
  }
}

static void wifi_event_handler(void *event_handler_arg,
                               esp_event_base_t event_base, int32_t event_id,
                               void *event_data) {
  if (event_id == WIFI_EVENT_STA_START) {

  } else if (event_id == WIFI_EVENT_STA_CONNECTED) {

  } else if (event_id == WIFI_EVENT_STA_DISCONNECTED) {

    esp_wifi_connect();
  } else if (event_id == IP_EVENT_STA_GOT_IP) {
  }
}

void wifi_connection() {
  esp_netif_init();
  esp_event_loop_create_default();
  esp_netif_create_default_wifi_sta();
  wifi_init_config_t wifi_initiation = WIFI_INIT_CONFIG_DEFAULT();
  esp_wifi_init(&wifi_initiation);
  esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler,
                             NULL);
  esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, wifi_event_handler,
                             NULL);
  wifi_config_t wifi_configuration = {.sta = {
                                          .ssid = "***",
                                          .password = "***",
                                      }};
  strcpy((char *)wifi_configuration.sta.ssid, ssid);
  strcpy((char *)wifi_configuration.sta.password, pass);
  esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_configuration);
  esp_wifi_start();
  esp_wifi_set_mode(WIFI_MODE_STA);
  esp_wifi_connect();
  printf("wifi_init_softap finished. SSID:%s  password:%s", ssid, pass);
}

void hello_task_core_0(void *pvParameter) {
  spi_bus_config_t buscfg = {
      .mosi_io_num = GPIO_MOSI,
      .miso_io_num = GPIO_MISO,
      .sclk_io_num = GPIO_SCLK,
      .quadwp_io_num = -1,
      .quadhd_io_num = -1,
  };

  spi_slave_interface_config_t slvcfg = {
      .mode = 0,
      .spics_io_num = GPIO_CS,
      .queue_size = 3,
      .flags = 0,
  };

  spi_slave_initialize(HSPI_HOST, &buscfg, &slvcfg, SPI_DMA_CH_AUTO);

  spi_slave_transaction_t t;
  memset(&t, 0, sizeof(t));
  t.length = HALF_BUFFER_SIZE;
  t.rx_buffer = (void *)currentRxBuffer;
  t.tx_buffer = (void *)currentTxBuffer;
  while (1) {
    spi_slave_transmit(HSPI_HOST, &t, portMAX_DELAY);
    xSemaphoreGive(dataReadySemaphore); // Signal that data is ready
    vTaskDelay(pdMS_TO_TICKS(1));
  }
}

void hello_task_core_1(void *pvParameter) {
  while (1) {
    if (xSemaphoreTake(dataReadySemaphore, portMAX_DELAY) == pdTRUE) {
      send_data_to_socket((char *)currentTxBuffer, HALF_BUFFER_SIZE);
    } else {
      // Semaphore was not taken
      vTaskDelay(
          pdMS_TO_TICKS(10)); // Wait for 10 milliseconds before trying again
    }

    volatile uint32_t *temp = currentTxBuffer;
    currentTxBuffer = currentRxBuffer;
    currentRxBuffer = temp;
  }
}

void app_main() {
  nvs_flash_init();
  wifi_connection();
  initialize_socket();

  // Create semaphore
  dataReadySemaphore = xSemaphoreCreateBinary();
  if (dataReadySemaphore == NULL) {
    ESP_LOGE("APP_MAIN", "Failed to create semaphore");
    return;
  }

  xTaskCreatePinnedToCore(&hello_task_core_0, "core0_task", 8192, NULL,
                          configMAX_PRIORITIES - 1, NULL, core_0);

  xTaskCreatePinnedToCore(&hello_task_core_1, "core1_task", 8192, NULL,
                          configMAX_PRIORITIES - 1, NULL, core_1);

  close_socket();
}

the problem i think with this code is that

//  Send data to the server as binary
  int sent_bytes = send(sock, data, data_length, 0);
  if (sent_bytes < 0) {
    ESP_LOGE("TCP", "Failed to send data to server. Error code: %d", errno);
  } else {
    ESP_LOGI("TCP", "Sent %d bytes to server", sent_bytes);
  }
}

Here the sent_bytes is always < 0, but I am exactly not sure why, and I also think that due to the usage of different cores, one of the cores isn't able to access the buffer. If that were the case, I should be getting an error based on that, but I am getting a totally different error. I also think that it could be the way i have synchronized both the cores using semaphores but i am not sure how else to do it exactly. Can someone help me with this?

nopnop2002 commented 2 months ago

Incorrect use of semaphore. After taking a semaphore, you must give it.

  while (1) {
    xSemaphoreTake(dataReadySemaphore, portMAX_DELAY);
    spi_slave_transmit(HSPI_HOST, &t, portMAX_DELAY);
    xSemaphoreGive(dataReadySemaphore); // Signal that data is ready
  }
  while (1) {
    xSemaphoreTake(dataReadySemaphore, portMAX_DELAY);
    send_data_to_socket((char *)currentTxBuffer, HALF_BUFFER_SIZE);
    xSemaphoreGive(dataReadySemaphore);
  }

Stop PinnedToCore and lower the priority.

  xTaskCreate(&hello_task_core_0, "core0_task", 8192, NULL, 2, NULL):

  xTaskCreate(&hello_task_core_1, "core1_task", 8192, NULL, 2, NULL);
hansw123 commented 2 months ago

@nopnop2002 thank for your help

hansw123 commented 2 months ago

@arvind55555 feel free to reopen

arvind55555 commented 2 months ago

Hi @nopnop2002 , thank you for your help, i tried implementing what you have said, but it is showing an error that "TCP: Connection to server failed. Error code: 118". i am pretty sure my server_ip and server_port works fine. i double checked everything. but i am still not sure what seems to be the issue. i have also attached a picture of my terminal for your reference.

image

just for your reference i have also added how i have implemented my code below

// core_1
void hello_task_core_0(void *pvParameter) {
  spi_bus_config_t buscfg = {
      .mosi_io_num = GPIO_MOSI,
      .miso_io_num = GPIO_MISO,
      .sclk_io_num = GPIO_SCLK,
      .quadwp_io_num = -1,
      .quadhd_io_num = -1,
  };

  spi_slave_interface_config_t slvcfg = {
      .mode = 0,
      .spics_io_num = GPIO_CS,
      .queue_size = 3,
      .flags = 0,
  };

  spi_slave_initialize(HSPI_HOST, &buscfg, &slvcfg, SPI_DMA_CH_AUTO);

  spi_slave_transaction_t t;
  memset(&t, 0, sizeof(t));
  t.length = HALF_BUFFER_SIZE;
  t.rx_buffer = (void *)currentRxBuffer;
  t.tx_buffer = (void *)currentTxBuffer;
  while (1) {
    xSemaphoreTake(dataReadySemaphore, portMAX_DELAY);
    spi_slave_transmit(HSPI_HOST, &t, portMAX_DELAY);
    xSemaphoreGive(dataReadySemaphore); // Signal that data is ready
    vTaskDelay(pdMS_TO_TICKS(1));
  }
}

//core_2
void hello_task_core_1(void *pvParameter) {
  while (1) {
    xSemaphoreTake(dataReadySemaphore, portMAX_DELAY);
    send_data_to_socket((char *)currentTxBuffer, HALF_BUFFER_SIZE);
    xSemaphoreGive(dataReadySemaphore);

    volatile uint32_t *temp = currentTxBuffer;
    currentTxBuffer = currentRxBuffer;
    currentRxBuffer = temp;
  }
}
arvind55555 commented 2 months ago

@hansw123 i would like to reopen this issue

nopnop2002 commented 2 months ago

try with the steps below.

1.Test only hello_task_core_1 without using semaphores.

  1. Test hello_task_core_0 and hello_task_core_1 without using semaphores.
  2. Test hello_task_core_0 and hello_task_core_1 using semaphores.
hansw123 commented 2 months ago

@arvind55555 From the log, it looks like the wifi connection is not yet complete when the tcp connection is made, so it will report a timeout 118, make sure that the tcp connection is made after the IP_EVENT_STA_GOT_IP event is complete, you can refer to the https://github.com/espressif/esp-idf/blob/master/examples/wifi/getting_started/station/main/station_example_main.c

static void event_handler(void arg, esp_event_base_t event_base, int32_t event_id, void event_data)

arvind55555 commented 2 months ago

try with the steps below.

1.Test only hello_task_core_1 without using semaphores. 2. Test hello_task_core_0 and hello_task_core_1 without using semaphores. 3. Test hello_task_core_0 and hello_task_core_1 using semaphores.

hello @nopnop2002 i tried the way you wanted me to test and i have added screenshots for your reference. 1) 1

2) 2

3) 3

the first and second tests ended up giving me the same result with the Error code : 5 and when i did the test i am not able to connect to the tcp itself getting Error code : 118

arvind55555 commented 2 months ago

@arvind55555 From the log, it looks like the wifi connection is not yet complete when the tcp connection is made, so it will report a timeout 118, make sure that the tcp connection is made after the IP_EVENT_STA_GOT_IP event is complete, you can refer to the https://github.com/espressif/esp-idf/blob/master/examples/wifi/getting_started/station/main/station_example_main.c

static void event_handler(void arg, esp_event_base_t event_base, int32_t event_id, void event_data)

hello @hansw123, i tried the way how you asked me to change by setting the tcp connection after the IP_EVENT_STA_GOT_IP event is complete. But even after that I was getting the same error

hansw123 commented 2 months ago

@arvind55555 from the latest log,still creat tcp connection before sta_got_ip_event and using semaphore ,you can refer https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html

hansw123 commented 2 months ago

@arvind55555 @nopnop2002

  1. binary semaphores are only suitable for scenarios where data generation is slow, in your case you can use Counting Semaphores

2、nopnop2002 ‘ suggestion was to turn the binary semaphore into a mutual exclusion lock, but the original usage was not really incorrect

  1. you can refer https://www.freertos.org/Real-time-embedded-RTOS-Counting-Semaphores.html