Паника ядра в esp32

skipinkd
Offline
Зарегистрирован: 21.08.2022

Всем добрый вечер. Помогите пожалуйста с кодом. Я полный новичок в программирование, поэтому простите за код.

#include <GyverPortal.h>
#include <FS.h>
#include <SPIFFS.h>
#include <ArduinoJson.h>

#define FORMAT_SPIFFS_IF_FAILED true

struct config_wifi_struct {
  char* ssid;
  char* pass;
  bool DHCP;
  char* ip;
  char* gt;
  char* mac;
  char* dns;
};

config_wifi_struct str;

//===================================================================
//spiffs functions
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
    Serial.printf("Listing directory: %s\r\n", dirname);

    File root = fs.open(dirname);
    if(!root){
        Serial.println("- failed to open directory");
        return;
    }
    if(!root.isDirectory()){
        Serial.println(" - not a directory");
        return;
    }

    File file = root.openNextFile();
    while(file){
        if(file.isDirectory()){
            Serial.print("  DIR : ");
            Serial.println(file.name());
            if(levels){
                listDir(fs, file.name(), levels -1);
            }
        } else {
            Serial.print("  FILE: ");
            Serial.print(file.name());
            Serial.print("\tSIZE: ");
            Serial.println(file.size());
        }
        file = root.openNextFile();
    }
}

String readFile(fs::FS &fs, const char * path){
    Serial.printf("Reading file: %s\r\n", path);
    String return_err = "error";
    File file = fs.open(path);
    if(!file || file.isDirectory()){
        Serial.println("- failed to open file for reading");
        return return_err;
    }
    
    String msg_string;
    while(file.available()){
        //Serial.write(file.read());
        msg_string += char(file.read());
    }
    file.close();
    return msg_string;
}

void writeFile(fs::FS &fs, const char * path, String message){
    Serial.printf("Writing file: %s\r\n", path);

    File file = fs.open(path, FILE_WRITE);
    if(!file){
        Serial.println("- failed to open file for writing");
        return;
    }
    if(file.print(message)){
        Serial.println("- file written");
    } else {
        Serial.println("- write failed");
    }
    file.close();
}

void appendFile(fs::FS &fs, const char * path, const char * message){
    Serial.printf("Appending to file: %s\r\n", path);

    File file = fs.open(path, FILE_APPEND);
    if(!file){
        Serial.println("- failed to open file for appending");
        return;
    }
    if(file.print(message)){
        Serial.println("- message appended");
    } else {
        Serial.println("- append failed");
    }
    file.close();
}


//========================================================================
//gyver portal functions
void build_login() {
  BUILD_BEGIN();
  GP.THEME(GP_DARK);
  
  GP.FORM_BEGIN("/login");
  GP.TEXT("lg", "Login");
  GP.BREAK();
  GP.TEXT("ps", "Password", str.pass);
  GP.BREAK();
  GP.LABEL("DHCP: ");
  GP.BREAK();
  GP.CHECK("DHCP", str.DHCP);
  GP.BREAK();
  GP.TEXT("ip", "ip", str.ip);
  GP.BREAK();
  GP.TEXT("gt", "gt", str.gt);
  GP.BREAK();
  GP.TEXT("mac", "mac", str.mac);
  GP.BREAK();
  GP.TEXT("dns", "dns", str.dns);
  GP.BREAK();
  GP.SUBMIT("Submit");
  GP.FORM_END();

  BUILD_END();
}

void action_login(GyverPortal& p) {
  if (p.form("/login")) {
    p.copyStr("lg", str.ssid);
    p.copyStr("ps", str.pass);
    str.DHCP = p.getCheck("DHCP");
    p.copyStr("ip", str.ip);
    p.copyStr("gt", str.gt);
    p.copyStr("mac", str.mac);
    p.copyStr("dns", str.dns);
    WiFi.softAPdisconnect();
    load_config_wifi();
    
  }
}

void loginPortal() {
  Serial.println("Portal start");

  // запускаем точку доступа
  WiFi.mode(WIFI_AP);
  WiFi.softAP("WiFi Config");

  // запускаем портал
  Serial.println("Запуск портала");
  GyverPortal portal;
  portal.attachBuild(build_login);
  Serial.println("Запуск build_login");
  portal.start(WIFI_AP);
  Serial.println("Запуск WIFI_AP");
  portal.attach(action_login);
  Serial.println("Запуск action_login");

  // работа портала
  while (portal.tick());
}

bool read_config_wifi(String msg_json_wifi_config){
  config_wifi_struct str;
  StaticJsonDocument<300> doc;
      
  DeserializationError error = deserializeJson(doc, msg_json_wifi_config);

  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
    return false;
  }
  str.ssid = strdup(doc["ssid"]);
  str.pass = strdup(doc["pass"]);
  str.DHCP = strdup(doc["DHCP"]) == "1";
  str.gt = strdup(doc["gt"]);
  str.mac = strdup(doc["mac"]);
  str.dns = strdup(doc["dns"]);
  str.ip = strdup(doc["ip"]);
  Serial.println(str.ssid);
  Serial.println(str.pass);
  Serial.println(str.DHCP);
  Serial.println(str.ip);
  Serial.println(str.gt);
  Serial.println(str.mac);
  Serial.println(str.dns);
  
  return true;
}

bool load_config_wifi(){
  StaticJsonDocument<300> doc;
  
  
  doc["ssid"] = str.ssid;
  doc["pass"] = str.pass;
  doc["DHCP"] = str.DHCP;
  doc["ip"] = str.ip;
  doc["gt"] = str.gt;
  doc["mac"] = str.mac;
  doc["dns"] = str.dns;
  
  String msg_return;
  
  serializeJson(doc, msg_return);

  Serial.print(msg_return);
  writeFile(SPIFFS, "/config_wifi.json", msg_return);
  
  return true;
}

//========================================================================
//wifi functions
bool DHCP_switch (){
  if(!str.DHCP){
    IPAddress local_IP(ipaddr_addr(str.ip));
    IPAddress gateway(ipaddr_addr(str.gt));
    IPAddress subnet(ipaddr_addr(str.mac));
    IPAddress primaryDNS(ipaddr_addr(str.dns));

    if (WiFi.config(local_IP, gateway, subnet, primaryDNS) == false) {
      Serial.println("Configuration failed.");
      return false;
    }
  }
  return true;
}

void wifi_connect(){
  Serial.print("Connect to: ");
  Serial.println(str.ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(str.ssid, str.pass);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.print("Connected! Local IP: ");

  Serial.println(WiFi.localIP());
  Serial.print("DHCP: ");
  Serial.println(str.DHCP);
}

//========================================================================
//arduino functions

void setup() {
  Serial.begin(115200);
  Serial.println();

  if(!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)){
        Serial.println("SPIFFS Mount Failed");
  }
  
  pinMode(27, INPUT_PULLUP);
  delay(500);
  Serial.println(read_config_wifi(readFile(SPIFFS, "/config_wifi.json")));
  delay(500);
  if (!digitalRead(27)){ 
    loginPortal();
  }
  DHCP_switch();
  wifi_connect();
}

void loop() {
}

 

Думаю, тут все дело в том, что я плохо использую переменные и функции для перезаписи массивов. Заранее огромное спасибо.

rkit
Offline
Зарегистрирован: 23.11.2016

А стектрейс я сам должен выяснить?

skipinkd
Offline
Зарегистрирован: 21.08.2022

Извините, не совсем понял что вам нужно 

sadman41
Offline
Зарегистрирован: 19.10.2016

GyverPortal?

Ну, это пусть пейсатель библиотеки разбирается.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

skipinkd пишет:

Думаю, тут все дело в том, что я ...

забыл написать в чём именно состоит моя проблема и выложить сообщения об ошибках.

skipinkd
Offline
Зарегистрирован: 21.08.2022

понял 

сейчас всё напишу 

skipinkd
Offline
Зарегистрирован: 21.08.2022
bool read_config_wifi(String msg_json_wifi_config){
  config_wifi_struct str;
  StaticJsonDocument<300> doc;
      
  DeserializationError error = deserializeJson(doc, msg_json_wifi_config);

  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
    return false;
  }
  str.ssid = strdup(doc["ssid"]);
  str.pass = strdup(doc["pass"]);
  str.DHCP = strdup(doc["DHCP"]) == "1";
  str.gt = strdup(doc["gt"]);
  str.mac = strdup(doc["mac"]);
  str.dns = strdup(doc["dns"]);
  str.ip = strdup(doc["ip"]);
  Serial.println(str.ssid);
  Serial.println(str.pass);
  Serial.println(str.DHCP);
  Serial.println(str.ip);
  Serial.println(str.gt);
  Serial.println(str.mac);
  Serial.println(str.dns);
  
  return true;
}

Думаю, все дело в этой функции. Без нее, код работает исправно. Остальные функции были взяты с примеров к библиотекам.

Ошибки в логах при запуске этой функции:

ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10124
load:0x40080400,len:5856
entry 0x400806a8

Reading file: /config_wifi.json
111
111
0
255.255.255.255
255.255.255.255
255.255.255.255
255.255.255.255
1
Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x401350f3  PS      : 0x00060330  A0      : 0x80135358  A1      : 0x3ffb1ea0  
A2      : 0x00000000  A3      : 0x3ffb1edc  A4      : 0x00000001  A5      : 0x00000001  
A6      : 0x00060320  A7      : 0x00000000  A8      : 0x80085450  A9      : 0x3ffb1ef0  
A10     : 0x3ff000e0  A11     : 0x00000001  A12     : 0x3ffbe958  A13     : 0x0000ff00  
A14     : 0x00ff0000  A15     : 0xff000000  SAR     : 0x0000001b  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000000  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xffffffff  

ELF file SHA256: 0000000000000000

Backtrace: 0x401350f3:0x3ffb1ea0 0x40135355:0x3ffb1ed0 0x400d1b33:0x3ffb1f00 0x400d368f:0x3ffb1f70 0x400dc6ca:0x3ffb1fb0 0x40089966:0x3ffb1fd0

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

В строка №№12-18 производится запрос памяти (strdup вызывает malloc).

Вопрос: кто, где, когда и при каких обстоятельствах эту память освобождает?

Если никто и никогда, то память со временем переполняется и "приплыли", тем более, что в программе даже не проверяется удачно отработала strdup или её памяти не хватило.

skipinkd
Offline
Зарегистрирован: 21.08.2022

Спасибо, так и думал 

Только я не знаю как сделать то, что вы написали 

Если не трудно, пришлите пожалуйста какой нибудь пример

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015
skipinkd
Offline
Зарегистрирован: 21.08.2022
bool read_config_wifi(String msg_json_wifi_config){
  StaticJsonDocument<300> doc;
      
  DeserializationError error = deserializeJson(doc, msg_json_wifi_config);

  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
    return false;
  }
  
  str.ssid = strdup(doc["ssid"]);
  str.pass = strdup(doc["pass"]);
  str.DHCP = strdup(doc["DHCP"]);
  str.gt = strdup(doc["gt"]);
  str.mac = strdup(doc["mac"]);
  str.dns = strdup(doc["dns"]);
  str.ip = strdup(doc["ip"]);
  
  Serial.println(str.ssid);
  Serial.println(str.pass);
  Serial.println(str.DHCP);
  Serial.println(str.ip);
  Serial.println(str.gt);
  Serial.println(str.mac);
  Serial.println(str.dns);
  
  free (str.ssid);
  free (str.pass);
  free (str.DHCP);
  free (str.gt);
  free (str.mac);
  free (str.dns);
  free (str.ip);
  
  return true;
}

Стало лучше работать. При первом запуске этой функции, все нормально, но при повторном опять ошибка ядра.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Раньше str был описан в этой функции. А сейчас ...

skipinkd
Offline
Зарегистрирован: 21.08.2022

Я же его за функцию вытащил
или лучше обратно его засунуть ?

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

skipinkd пишет:

Я же его за функцию вытащил

А мне это, простите откуда, знать? Что Вы вытащили, куда, зачем и как именно? Вы же мне только огрызок кода выложили, весь не доверяете.

К тому же, по-прежнему

ЕвгенийП пишет:
в программе даже не проверяется удачно отработала strdup или её памяти не хватило.

Вы до этого не дочитали? Или решили проигнорировать?

skipinkd
Offline
Зарегистрирован: 21.08.2022

Весь код я выложил в первом вопросе

skipinkd
Offline
Зарегистрирован: 21.08.2022
bool read_config_wifi(String msg_json_wifi_config){
  StaticJsonDocument<300> doc;
      
  DeserializationError error = deserializeJson(doc, msg_json_wifi_config);

  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
    return false;
  }

  str.ssid = strdup(doc["ssid"]);
  free (str.ssid);
  
  str.pass = strdup(doc["pass"]);
  free (str.pass);
  
  str.DHCP = strdup(doc["DHCP"]);
  free (str.DHCP);
  
  str.ip = strdup(doc["ip"]);
  free (str.ip);
  
  str.gt = strdup(doc["gt"]);
  free (str.gt);
  
  str.mac = strdup(doc["mac"]);
  free (str.mac);
  
  str.dns = strdup(doc["dns"]);
  free (str.dns);
  
  Serial.println(str.ssid);
  Serial.println(str.pass);
  Serial.println(str.DHCP);
  Serial.println(str.ip);
  Serial.println(str.gt);
  Serial.println(str.mac);
  Serial.println(str.dns);

  return true;
}

Поменял код. Теперь не вылезает ошибка ядра, но появилась другая проблема. Функция не корректно записывает данные в структуру.
Лог:

16:42:42.574 -> ets Jun  8 2016 00:22:57
16:42:42.574 ->
16:42:42.574 -> rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
16:42:42.574 -> configsip: 0, SPIWP:0xee
16:42:42.574 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
16:42:42.574 -> mode:DIO, clock div:1
16:42:42.574 -> load:0x3fff0018,len:4
16:42:42.574 -> load:0x3fff001c,len:1044
16:42:42.574 -> load:0x40078000,len:10124
16:42:42.574 -> load:0x40080400,len:5856
16:42:42.574 -> entry 0x400806a8
16:42:42.901 ->
16:42:43.508 -> Reading file: /config_wifi.json
16:42:43.508 -> <⸮⸮?xV⸮⸮
16:42:43.508 -> <⸮⸮?xV⸮⸮
16:42:43.508 -> <⸮⸮?xV⸮⸮
16:42:43.508 ->
16:42:43.508 ->
16:42:43.508 ->
16:42:43.508 ->
16:42:43.508 -> 1
16:42:43.973 -> Portal start
16:42:44.113 -> Запуск портала
16:42:44.113 -> Запуск build_login
16:42:44.113 -> Запуск WIFI_AP
16:42:44.113 -> Запуск action_login
16:43:19.375 -> {"ssid":" ","pass":" ","DHCP":" ","ip":"Ԩ⸮?xV⸮⸮","gt":"Ԩ⸮?xV⸮⸮","mac":"Ԩ⸮?xV⸮⸮","dns":"Ԩ⸮?xV⸮⸮"}Writing file: /config_wifi.json
16:43:19.375 -> - file written

 

skipinkd
Offline
Зарегистрирован: 21.08.2022

в программе даже не проверяется удачно отработала strdup или её памяти не хватило.
Насчет этого я помню. Но в интернета не нашел, как правильно это сделать. А реализовать самому не получается. Если есть пример, скиньте пожалуйста

sadman41
Offline
Зарегистрирован: 19.10.2016

Возвращаемое значение

Указатель на копию строки. Если выделение памяти закончилось неудачей, то создания копии не происходит и *функция возвращает NULL*.

skipinkd
Offline
Зарегистрирован: 21.08.2022

Понял, спасибо. Но мне обязательно нужно выполнить создание копии. Как можно это реализовать, что бы 100% происходило создание копии.

 

skipinkd
Offline
Зарегистрирован: 21.08.2022

Или же можно обойтись без функции strdup? Просто, я ее использую из-за того, что мне нужно преобразовать значение из const char* в char*.

sadman41
Offline
Зарегистрирован: 19.10.2016

Все зависит от того, где использовать поля данной структуры...

skipinkd
Offline
Зарегистрирован: 21.08.2022

Мне нужно передать значение в структуру. JSON функция отдает мне их в const char*, а мне нужно хранить их в структуре с переменными char.

sadman41
Offline
Зарегистрирован: 19.10.2016

То, что нужно - видно из кода. А вот какова должна быть область видимости - неочевидно. Это же основополагающий вопрос.

rkit
Offline
Зарегистрирован: 23.11.2016

Нужно прочитать учебник по языку и написать нормальную RAII-структуру вместо этого мусора.