Сбой при обслуживании файлов статической ширины ESP8266WebServer
Последние два дня я пытался настроить ESP8266WebServer для обслуживания моих статических файлов веб-приложений из SPIFFS. Но как только я вызываю serveStatic
, ESP падает. Это точный код, который я запускаю:
#include <FS.h>
#include <ESP8266WebServer.h>
ESP8266WebServer s;
void setup() {
Serial.begin(115200);
if(!SPIFFS.begin()){
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
s.serveStatic("/", SPIFFS, "/static/");
s.begin();
}
void loop() {
s.handleClient();
}
Я знаю, что этот пример не позволяет мне каким-либо образом получить доступ к файлам, потому что у меня не настроен WiFi, но этого достаточно для того, чтобы ESP вышел из строя. Это ошибка, которую я постоянно вижу:
SPIFFSImpl: allocating 512+240+1400=2152 bytes
SPIFFSImpl: mounting fs @100000, size=2fa000, block=2000, page=100
SPIFFSImpl: mount rc=0
Fatal exception 28(LoadProhibitedCause):
epc1=0x4021407a, epc2=0x00000000, epc3=0x00000000, excvaddr=0x00000000, depc=0x00000000
Exception (28):
epc1=0x4021407a epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
>>>stack>>>
ctx: cont
sp: 3ffffca0 end: 3fffffc0 offset: 01a0
3ffffe40: 3ffefaf8 00000000 3ffffea0 402127b1
3ffffe50: 00000001 ffffffff 4020a9dc 00000000
3ffffe60: 3ffe8304 00000000 0000000a 40216e21
3ffffe70: 402497e1 00000000 00000000 4020b414
3ffffe80: 3ffffee0 3ffffed0 00000008 402497e3
3ffffe90: 402497e2 3ffe8304 3ffefaf8 402171ec
3ffffea0: 00000000 ffffffff 00000000 00000000
3ffffeb0: 00000001 00000041 3f302073 40212d8e
3ffffec0: 3ffffee0 3ffffed0 00000004 40209c90
3ffffed0: 3fffff10 00000000 00000017 3fff0580
3ffffee0: 00308658 3fffff20 3ffef85c 4020a3e9
3ffffef0: 000018c0 3ffee6b0 00000000 40208120
3fffff00: 3fffff60 3fffff50 00000014 00000001
3fffff10: 00000009 00000001 00000001 40207c65
3fffff20: 40100b04 00001000 00002000 3fff0580
3fffff30: 3ffe8658 402497a4 3ffe8304 40212d8e
3fffff40: 3fffff60 3fffff50 00000004 40100476
3fffff50: 3ffe8658 3ffe8658 3ffe865f 00000000
3fffff60: 00000000 00000000 3fff056c 4020ffa5
3fffff70: 3fffdad0 3ffee690 3fff056c 40201325
3fffff80: 3ffe865f feefeffe feefeffe feefeffe
3fffff90: feefeffe feefeffe feefeffe 3ffee610
3fffffa0: 3fffdad0 00000000 3ffee5d0 40206aa0
3fffffb0: feefeffe feefeffe 3ffe84f4 40101245
<<<stack<<<
ets Jan 8 2013,rst cause:2, boot mode:(3,6)
load 0x4010f000, len 1392, room 16
tail 0
chksum 0xd0
csum 0xd0
v3d128e5c
~ld
Я также проанализировал трассировку стека с помощью декодера исключений ESP, но это не помогло мне. Вот результат работы этого инструмента:
Exception 28: LoadProhibited: A load referenced a page mapped with an attribute that does not permit loads
PC: 0x4021407a: pgm_read_byte_inlined at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/sys/xtensa/sys/pgmspace.h line 72
EXCVADDR: 0x00000000
Decoding stack results
0x402127b1: _printf_i at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf_i.c line 226
0x4020a9dc: spiffs_object_find_object_index_header_by_name_v(spiffs*, spiffs_obj_id, spiffs_block_ix, int, void const*, void*) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/spiffs/spiffs_nucleus.cpp line 1664
0x40216e21: __sfputs_r at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf.c line 433
0x4020b414: spiffs_obj_lu_scan(spiffs*) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/spiffs/spiffs_nucleus.cpp line 439
0x402171ec: _vfprintf_r at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf.c line 667
0x40212d8e: printf at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/printf.c line 61
0x40209c90: SPIFFS_mount(spiffs*, spiffs_config*, u8_t*, u8_t*, u32_t, void*, u32_t, spiffs_check_callback) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/spiffs/spiffs_hydrogen.cpp line 138
0x4020a3e9: SPIFFS_stat(spiffs*, char const*, spiffs_stat*) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/spiffs/spiffs_hydrogen.cpp line 769
0x40208120: spiffs_impl::SPIFFSImpl::_tryMount() at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/spiffs_api.h line 320
0x40207c65: spiffs_impl::SPIFFSImpl::exists(char const*) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/spiffs_api.cpp line 80
0x40100b04: get_poisoned(void*, size_t) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/umm_malloc/umm_poison.c line 112
0x40212d8e: printf at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/printf.c line 61
0x40100476: pvPortMalloc(size_t, char const*, int) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/heap.cpp line 267
0x4020ffa5: fs::FS::exists(char const*) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/FS.cpp line 363
0x40201325: setup() at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h line 75
0x40206aa0: loop_wrapper() at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/core_esp8266_main.cpp line 177
Вот мои настройки в Arduino IDE:
Чтобы записать данные в ESP, я использую последнюю версию этого инструмента для Arduino-IDE: https:/ /github.com/esp8266/arduino-esp8266fs-плагин
Возможно, я совершаю глупую ошибку, но уже несколько часов ломаю голову и не могу понять, в чем может быть проблема. Мы будем очень признательны за любую помощь!
Обновление №1:
Данные определенно доступны в ESP, так как этот фрагмент работает нормально:
Exception 28: LoadProhibited: A load referenced a page mapped with an attribute that does not permit loads
PC: 0x4021407a: pgm_read_byte_inlined at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/sys/xtensa/sys/pgmspace.h line 72
EXCVADDR: 0x00000000
Decoding stack results
0x402127b1: _printf_i at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf_i.c line 226
0x4020a9dc: spiffs_object_find_object_index_header_by_name_v(spiffs*, spiffs_obj_id, spiffs_block_ix, int, void const*, void*) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/spiffs/spiffs_nucleus.cpp line 1664
0x40216e21: __sfputs_r at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf.c line 433
0x4020b414: spiffs_obj_lu_scan(spiffs*) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/spiffs/spiffs_nucleus.cpp line 439
0x402171ec: _vfprintf_r at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf.c line 667
0x40212d8e: printf at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/printf.c line 61
0x40209c90: SPIFFS_mount(spiffs*, spiffs_config*, u8_t*, u8_t*, u32_t, void*, u32_t, spiffs_check_callback) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/spiffs/spiffs_hydrogen.cpp line 138
0x4020a3e9: SPIFFS_stat(spiffs*, char const*, spiffs_stat*) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/spiffs/spiffs_hydrogen.cpp line 769
0x40208120: spiffs_impl::SPIFFSImpl::_tryMount() at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/spiffs_api.h line 320
0x40207c65: spiffs_impl::SPIFFSImpl::exists(char const*) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/spiffs_api.cpp line 80
0x40100b04: get_poisoned(void*, size_t) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/umm_malloc/umm_poison.c line 112
0x40212d8e: printf at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/printf.c line 61
0x40100476: pvPortMalloc(size_t, char const*, int) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/heap.cpp line 267
0x4020ffa5: fs::FS::exists(char const*) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/FS.cpp line 363
0x40201325: setup() at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h line 75
0x40206aa0: loop_wrapper() at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/core_esp8266_main.cpp line 177
Обновление №2
Обслуживание файлов путем регистрации приведенной ниже функции в качестве обработчика (server.on("/", myHandler)
работает:
#include <FS.h>
#include <ESP8266WebServer.h>
ESP8266WebServer s;
void setup() {
Serial.begin(115200);
if(!SPIFFS.begin()){
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
/*s.serveStatic("/", SPIFFS, "/static/");
s.begin();*/
}
void loop() {
//s.handleClient();
delay(5000);
File f = SPIFFS.open("/static/index.html", "r");
String s = f.readString();
Serial.println(s);
f.close();
}
2 ответа
Лучший ответ:
Оказывается, сбой ESP вызван настройками отладки в Arduino IDE. Как только CORE-уровень включается, возникает ошибка. Кажется, где-то в прошивке ошибка. Включение других уровней, кажется, нормально.
Огромное спасибо Юраю за помощь в обнаружении этого.
Возможно, вы не загрузили SPIFFS.
Поэтому после прошивки программы вы должны использовать ESP8266DataUpload, а в вашем каталоге, содержащем *.ino, должен быть каталог «data», в котором должен находиться файл, который вы обслуживаете, или каталог в вашем случае «/static/». существует.
EDIT Нет, файл не существует ;-) используйте
serveStatic("/", SPIFFS, "/static"); //=> без завершающего '/'
или используйте (имейте в виду, что обслуживание статических каталогов не работает должным образом. У меня есть каждый большой файл в одном статическом выражении, включая старение
serveStatic("/", SPIFFS, "/static/index.html");
Не зная размера ваших статических файлов, флэш-память с 2 МБ FS / или 1 МБ FS / проблема в том, что если вам не нужен OTA, вы всегда теряете место. Я создал свои личные схемы разделов, например, 2MB Spiffs/2MB flash/No OTA для проги.
Размер вашей памяти должен быть следующим: размер программы + размер переменной (видимый в среде IDE) + размер самых больших (статических) файлов * 1,2 (запас прочности) должен заполнять «память приложения» примерно на 80%.
В качестве примера вашего использования на данный момент выглядит следующим образом:
На данный момент у вас есть максимум 400 КБ для приложения И обслуживания (статических) файлов. Вы используете
- 3 МБ для файловой системы SPIFFS,
- 512 для ОТА,
- минимум 100 КБ для уровня отладки
=> как он может сохранить/загрузить, например, файл размером 300 КБ во флэш-память?
Ваш код ошибки 28 обычно связан с проблемами нехватки памяти, вторая строка сообщения об ошибке указывает на то, что что-то должно быть загружено в память и не может, мы исключили все другие причины, поэтому ...
Это именно то, что у меня есть. Я знаю, что файлы есть и доступны для чтения, потому что чтение файлов по отдельности из SPIFFS работает. См. мое редактирование выше., @Alexander Richter
Я только что изменил свой код, чтобы определить файл отдельно, но ошибка все еще существует :(, @Alexander Richter
Это хороший совет, я рассмотрю возможность его настройки перед развертыванием. Однако мои статические файлы (все внутри каталога данных) в настоящее время имеют размер 1,4 МБ. Это должно быть совместимо с моими текущими настройками IDE, верно?, @Alexander Richter
Нет, это не так - на данный момент у вас есть максимум 400 КБ для приложения И обслуживания статических файлов (вы используете 3 МБ для файловой системы SPIFFS, 512 для OTA, минимум 100 КБ для вашего уровня отладки) - как он может хранить/загружать, например, файл размером 300 КБ в prgmem - ваша строка сообщения об ошибке вторая указывает на то, что что-то должно быть загружено в prgmem и не может Мы исключили все другие причины, поэтому ..., @Codebreaker007
Но если это было проблемой, почему обработка статического файла читается не через `
server.serveStatic()`
, а через `
server.on(...)`
с пользовательской функцией-обработчиком, которая передает файл над работает? См. мое второе редактирование для справки., @Alexander Richter
Кроме того, не могли бы вы предоставить мне ссылку на ресурс, который показывает мне, как удалить пространство раздела OTA? Я просто некоторое время гуглил, и я не могу найти ничего полезного..., @Alexander Richter
Это был бы новый вопрос, @Codebreaker007
- Как читать и записывать EEPROM в ESP8266
- Как исправить: Invalid conversion from 'const char*' to 'char*' [-fpermissive]
- ошибка: espcomm_upload_mem failed при загрузке скетча
- Как определить размер Flash?
- Несколько клиентских серверов через Wi-Fi
- Передача функции-члена класса в качестве аргумента
- В ESP-12E NodeMCU, какой выход PIN A0?
- Esp8266 Vin контакт
попробуйте отключить журналы отладки с помощью «Уровня отладки» Нет, @Juraj
уже пробовал, не помогло к сожалению, @Alexander Richter
вы уверены? у вас такая же трассировка стека? отключить отладочный порт тоже, @Juraj
Ничего себе, я только что попробовал еще раз - и вы были правы! Теперь работает! Может быть, я просто понизил уровень раньше... Но почему? Означает ли это, что я не могу просматривать свои WiFi-Debug-Messages при использовании
`
serveStatic()`
?, @Alexander RichterЯ только что провел некоторое тестирование и выяснил, что как только я включаю CORE в меню отладки, он начинает падать. Я бы никогда не догадался, что это проблема., @Alexander Richter
должна быть какая-то ошибка с ведением журнала. printf в трассировке стека был подсказкой, @Juraj
Отличная находка! Позор, я не могу проголосовать за вас!, @Alexander Richter