• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Решено Изменить удаленно размер SPIFFS, чтобы по OTA обновить скетч.

Paul_B

Member
На ESP8266 установлен webServer и крутится довольно объемный проект. Для нужд проекта выделен SPIFFS для web-страниц и рабочих файлов проекта. Раньше было выделено 64 Кб все было замечательно - объема оставшейся памяти хватало, чтобы по OTA обновлять новые версии скетчей.

Потом потребовалось выделить 256 Кб под SPIFFS и оставшейся памяти стало не хватать, чтобы обновить по OTA скетч. Вопрос касается версий ESP8266 с объемом памяти 1МБ (для версии с 4МБ - 1 + 3МБ под SPIFFS все ОК).

Сам вопрос: можно ли как-то удаленно уменьшить объем памяти под SPIFFS (возможно совсем убрать), чтобы обновить скетч, потом опять удаленно выделить нужный размер SPIFFS и закачать файлы.

Пробовал удаленно запускать SPIFFS.end() - не помогает, т.е. внутренне SPIFFS отключается, т.к. web-страницы перестают грузится, а вот эта память не высвобождается для обновления скетча.

Удаленно могу с модулем делать через web-сервер с использованием записи в EEPROM все что угодно. Идеи приветствуются.
 

tretyakov_sa

Moderator
Команда форума
Сначала загрузи маленький скетч загрузчик, затем большой. Затем любую новую систему файловую систему которая определена новым скетчем. Все это проверено при обновлении с сайта. Что подразумевается под ОТА трудно понять.
 

Paul_B

Member
Сначала загрузи маленький скетч загрузчик, затем большой
Пробовал. Мой проект сейчас занимает 490 кб (скетч 5600 строк только моего текста, не считая подключаемых библиотек, необходимых для отправки e-mail, проверки пинга и т.д. и т.п.). Самый минимальный скетч, в котором есть OTA-загрузчик занимает 270 кб. С учетом того, что проект рисует графики с использованием html Highcharts, необходимо выделять минимум 512 кб под SPIFFS, т.к. только два файла с js-скриптами, необходимых для отрисовки графиков HIGHCHARTS занимают 150 кб.
При суммарной памяти в 1МБ на ESP 8266, как видим, такой фокус не пройдет. Просто я думал может как-нибудь удаленно можно отключить SPIFFS, включив его в общую память (можно выполнять какие-нибудь команды, реализовав из выполнение в Web-сервере. Но нет, так нет, буду пользовать 4МБ модули.
 
Последнее редактирование:

Paul_B

Member
А нельзя библиотеки highcharts подкачивать со стороннего ресурса?
Видите ли, проект универсальный, предполагается работать в модулях, которые могут быть связаны между собой сеткой, но выход в интернет может иметь только один из них, удаленный на несколько узлов (аналогичных модулей). Можно управлять ими, через друг друга (причем все настройки, включая передачу условных сообщений от каких-либо событий - уровень аналогового сигнала, значений температуры, влажности, напряжения питания, пинга до любого хоста, просто по таймеру) вводятся через web-страницы, повторюсь, не обязательно через тот модуль, для которого они предназначаются. Так же можно подключаться к каждому модулю через собственную точку доступа, если она в зоне доступа.
Поэтому хранить файлы, необходимые для работы надо внутри каждого модуля.

У меня вот идейка возникла, может файл-прошивку скетча заливать на SPIFFS, предварительно удалив оттуда файлы, прошивать со SPIFFS, а потом заливать заново необходимые файлы. Благо размер SPIFFS (минимум 512 Кб) позволяет это сделать.
 

Paul_B

Member
А если обновление через web или по http это OTA?
Это игра слов. Сформулирую вопрос прямо. Можно ли удаленно прошить bin-файл с прошивкой, который лежит в SPIFFS, при этом сразу "напрямую", т.е. не задействуя внутреннюю память, которой, собственно, нет.
 

Paul_B

Member
Как можно Вам объяснили.
Все эти способы подразумевают подгрузку файла с прошивкой в область памяти меджу уже установленной и SPIFFS. У меня этой памяти не хватает для подгрузки прошивки. Поэтому вопрос-то и состоял - можно ли как-то через Web-сервер, запущенный на ESP8266 либо убрать временно SPIFFS, освободив память для подгрузки прошивки, либо какой-то способ, чтобы записать прошивку сразу из SPIFFS.
 

Paul_B

Member
Вы сделайте две задачи.
Сами задачи будут храниться во флеш
Но в отличии от двух скетчей у них будут общими все библиотеки.
Запускает задачи по очереди. Память данных у них тоже общая.
Код библиотек хранится на флеш
Совсем ничего не понял....
 

Paul_B

Member
Короче, этот метод хоть и позволяет обновлять прошивку из файла в SPIFFS, но пишет ее в ту же область для OTA-обновлений. Которой если нет, то и не пишет, выдает ERROR[4]: Not Enough Space.
Можно как-то модифицировать Update.write, чтобы писать сразу на место прошивки? Или там на уровне ядра все зашито, что типа область для OTA-обновлений, если она не пустая, встает на место прошивки только при перезагрузке модуля...?
 

Paul_B

Member
Попутно поделюсь опытом как одновременно обновлять прошивку и SPIFFS через bin-файлы, получаемые при компиляции в Arduino IDE.
В bin-файле SPIFFS должно присутствовать "spiffs".
Добавил в файл уважаемого Гуру.

Код:
const char* serverIndex = "<form method='POST' action='/update' enctype='multipart/form-data'><input type='file' name='update'><input type='submit' value='Update'></form>";

// Инициализация FFS
void FS_init(void) {
  SPIFFS.begin();
  {
    Dir dir = SPIFFS.openDir("/");
    while (dir.next()) {
      String fileName = dir.fileName();
      size_t fileSize = dir.fileSize();
    }
  }
  //HTTP страницы для работы с FFS
  //list directory
  server.on("/list", HTTP_GET, handleFileList);
  //загрузка редактора editor
  server.on("/edit", HTTP_GET, []() {
    if (!handleFileRead("/editor.htm")) server.send(404, "text/plain", "FileNotFound");
  });
  //Создание файла
  server.on("/edit", HTTP_PUT, handleFileCreate);
  //Удаление файла
  server.on("/edit", HTTP_DELETE, handleFileDelete);
  //first callback is called after the request has ended with all parsed arguments
  //second callback handles file uploads at that location
  server.on("/edit", HTTP_POST, []() {
    server.send(200, "text/plain", "");
  }, handleFileUpload);
  //called when the url is not defined here
  //use it to load content from SPIFFS
   server.onNotFound([]() {
    if (!handleFileRead(server.uri()))
      server.send(404, "text/plain", "FileNotFound");
  });

   server.on("/refit", HTTP_GET, [](){
    server.sendHeader("Connection", "close");
    server.sendHeader("Access-Control-Allow-Origin", "*");
    server.send(200, "text/html", serverIndex);
  });
  server.on("/update", HTTP_POST, [](){
    server.sendHeader("Connection", "close");
    server.sendHeader("Access-Control-Allow-Origin", "*");
    server.send(200, "text/plain", (Update.hasError())?"FAIL":"OK");
    ESP.restart();
  },[](){
    HTTPUpload& upload = server.upload();
    if(upload.status == UPLOAD_FILE_START){
      Serial.setDebugOutput(true);
      WiFiUDP::stopAll();
      Serial.printf("Update: %s\n", upload.filename.c_str());
      uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
      byte cod=0;
      if(upload.filename.indexOf("spiffs")>=0) cod=100; 
      if(!Update.begin(maxSketchSpace,cod)){//start with max available size
              Update.printError(Serial);
            }
   
    } else if(upload.status == UPLOAD_FILE_WRITE){
      if(Update.write(upload.buf, upload.currentSize) != upload.currentSize){
        Update.printError(Serial);
      }
    } else if(upload.status == UPLOAD_FILE_END){
      if(Update.end(true)){ //true to set the size to the current progress
        Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
      } else {
        Update.printError(Serial);
      }
      Serial.setDebugOutput(false);
    }
    yield();
  });
}
 

Алексей.

Active member
Можно как-то модифицировать Update.write, чтобы писать сразу на место прошивки?
Вопросом на вопрос :)
Как должна повести себя прошивка после перезагрузки если обновление не завершено? Одну половину прошивки мы уже затерли, а другая половина осталась от прежней.
 

Paul_B

Member
Как должна повести себя прошивка после перезагрузки если обновление не завершено? Одну половину прошивки мы уже затерли, а другая половина осталась от прежней.
Риск есть, но если файл с прошивкой лежит в SPIFFS, то это практически в той же флэш памяти. И хотелось бы сразу файл из SPIFFS писать не в область OTA-обновлений, а на место прошивки.
 

Алексей.

Active member
Риск есть, но если файл с прошивкой лежит в SPIFFS, то это практически в той же флэш памяти. И хотелось бы сразу файл из SPIFFS писать не в область OTA-обновлений, а на место прошивки.
А какая разница? Ели то, что исполняется загрузилось на половину, как этот битый файл прошивку исполнять теперь, если это скрипт для lua, как его рваного интерпретировать?
 

Paul_B

Member
Вопрос решен.
Файл Updater.cpp модифицирован.
Можно писать bin-файл с прошивкой с адреса расположения SPIFFS (понятно, что SPIFFS затирается), поэтому после перезагрузки модуля сразу же накатывается bin-файл со SPIFFS)
Либо второй вариант - файл с прошивкой сразу писать с 0-го адреса. Какой оставить для себя пока не решил.

Кстати, писать во флеш с адреса расположения SPIFFS это проще (меньше телодвижений) по сравнению с тем, чтобы удалить все файлы из SPIFFS, закачать туда прошивку (т.е. размер SPIFFS в 512Кб практически совпадает с размером прошивки 495Кб)

В файле Updater.cpp меняем строку
Код:
    updateStartAddress = (updateEndAddress > roundedSize)? (updateEndAddress - roundedSize) : 0;
На ту же, что с для обновления SPIFFS:
Код:
updateStartAddress = (uint32_t)&_SPIFFS_start - 0x40200000;
А еще лучше на такую, чтобы запись велась сразу после имеющегося скетча:
Код:
    updateStartAddress = (ESP.getSketchSize() + FLASH_SECTOR_SIZE - 1)& (~(FLASH_SECTOR_SIZE - 1));
Ну и размер обновления выставляем на всю оставшуюся память
Код:
uint32_t maxSketchSpace = (ESP.getFlashChipRealSize()-ESP.getSketchSize()-16)&(~15);
Если обновляемая прошивка умещается между текущей и началом SPIFFS, то обновление пройдет ровно, а если она больше, то надо после будет подгрузить bin-файл SPIFFS
 
Последнее редактирование:

Paul_B

Member
Проверил все работает. Теперь бы еще научиться схранять все нужные фалы из SPIFFS (а не по одному через edit.htm) нажатием одной кнопки перед обновлением и такую же загрузку после обновления...

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

Алексей.

Active member
Paul_B,
Вы правите исходники в sdk, что нужно делать, когда выходят обновления sdk?
Например Updater.cpp последний раз обновлялся 2 месяца назад, при выходе обновления в ручную исходники мерджить будем или есть какие нибудь рекомендации по решение проблемы с обновлениями?
 
Сверху Снизу