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

Существует ли с++ среда для esp8266?

Alex_S

New member
Продолжаем игры. Появились очередные вопросы )
1. При использовании стандартного вектора таки в некоторых случаях не хватает реализации `_sbrk_r':
Код:
c:/espressif/xtensa-lx106-elf/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-mallocr.o):(.literal+0x24): undefined reference to `_sbrk_r'
c:/espressif/xtensa-lx106-elf/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-mallocr.o): In function `malloc_extend_top':
d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdlib/../../../../../newlib/libc/stdlib/mallocr.c:2165: undefined reference to `_sbrk_r'
d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdlib/../../../../../newlib/libc/stdlib/mallocr.c:2202: undefined reference to `_sbrk_r'
c:/espressif/xtensa-lx106-elf/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-freer.o): In function `_malloc_trim_r':
d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdlib/../../../../../newlib/libc/stdlib/mallocr.c:3325: undefined reference to `_sbrk_r'
d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdlib/../../../../../newlib/libc/stdlib/mallocr.c:3332: undefined reference to `_sbrk_r'
c:/espressif/xtensa-lx106-elf/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-freer.o):d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdlib/../../../../../newlib/libc/stdlib/mallocr.c:3340: more undefined references to `_sbrk_r' follow
Можно ли как-то его реализовать или убрать?

2. Линкер кидает все наши функции в секцию iram1_0_seg, которой всего 32кб. Чтобы положить их в rom, есть аттрибут ICACHE_FLASH_ATTR. Туда же кладутся и все строковые константы.
А есть ли способ класть их в rom по-умолчанию, и использовать их оттуда?
 

jcmvbkbc

New member
Продолжаем игры. Появились очередные вопросы )
1. При использовании стандартного вектора таки в некоторых случаях не хватает реализации `_sbrk_r':
Можно ли как-то его реализовать или убрать?
По идее надо заменить реализацию malloc в newlib на вызов os_malloc, а free -- на os_free. Я завтра наверно сделаю.

2. Линкер кидает все наши функции в секцию iram1_0_seg, которой всего 32кб. Чтобы положить их в rom, есть аттрибут ICACHE_FLASH_ATTR. Туда же кладутся и все строковые константы.
А есть ли способ класть их в rom по-умолчанию, и использовать их оттуда?
Я вот такой способ предложил в своё время: http://www.esp8266.com/viewtopic.php?f=9&t=224&start=80#p1385
Есть минимум одно "но" с кодом во FLASH: туда нельзя класть код, который может быть вызван из прерывания.
 

Alex_S

New member
С _sbrk_r разобрался - моя вина была. В одном месте вместо os_free использовал просто free.
Надо быть внимательным.
 

anakod

Moderator
Команда форума
Я вот такой способ предложил в своё время: http://www.esp8266.com/viewtopic.php?f=9&t=224&start=80#p1385
Есть минимум одно "но" с кодом во FLASH: туда нельзя класть код, который может быть вызван из прерывания.
Огромное спасибо, это как раз то чего мне не хватало. А почему нельзя класть код вызываемый из прерывания? У меня вроде работало (или это просто не гарантируется)?
Второй вопрос можно ли объявить обратную константу явно кладущую код в ROM? Чтобы полностью исключить всю библиотеку из основной памяти, но некоторые функции оставить там.
 

jcmvbkbc

New member
Огромное спасибо, это как раз то чего мне не хватало. А почему нельзя класть код вызываемый из прерывания? У меня вроде работало (или это просто не гарантируется)?
Надо уточнить: если программа пишет во FLASH. Потому что при записи мэппинг FLASH в адресное пространство CPU отключается а после включается снова. Если в этот период прийдёт прерывание всё сломается.
Второй вопрос можно ли объявить обратную константу явно кладущую код в ROM? Чтобы полностью исключить всю библиотеку из основной памяти, но некоторые функции оставить там.
В смысле, в IRAM? Ну да, идея в том, чтобы поместить код для IRAM и FLASH в разные секции, а в скрипте линковщика положить разные входные секции в разные выходные регионы.
 

anakod

Moderator
Команда форума
1. В таком случае, получается можно просто запретить обработку прерываний на время записи данных во флеш?

2. А Вы могли бы подсказать как сделать так, чтобы основной код лег во флеш (тут я думаю достаточно будет примера по ссылке), но определённые функции (требовательные к производительности/вызываемые в прерываниях и т.д.) клались в IRAM? Т.е примерно как встроенный макрос cache flash, но наоборот.
 

jcmvbkbc

New member
1. В таком случае, получается можно просто запретить обработку прерываний на время записи данных во флеш?
Вариант, конечно, но не уверен, что это просто, и вообще хорошо.
2. А Вы могли бы подсказать как сделать так, чтобы основной код лег во флеш (тут я думаю достаточно будет примера по ссылке), но определённые функции (требовательные к производительности/вызываемые в прерываниях и т.д.) клались в IRAM? Т.е примерно как встроенный макрос cache flash, но наоборот.
Например так можно сделать:
Код:
--- eagle.app.v6.ld.orig  2014-12-19 18:07:44.000000000 +0300
+++ eagle.app.v6.ld  2015-02-02 06:13:22.726822114 +0300
@@ -96,11 +96,14 @@
  *(.gnu.linkonce.e.*)
  *(.gnu.version_r)
  *(.eh_frame)
+  . = (. + 3) & ~ 3;
  /*  C++ constructor and destructor tables, properly ordered:  */
+  __init_array_start = ABSOLUTE(.);
  KEEP (*crtbegin.o(.ctors))
  KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
  KEEP (*(SORT(.ctors.*)))
  KEEP (*(.ctors))
+  __init_array_end = ABSOLUTE(.);
  KEEP (*crtbegin.o(.dtors))
  KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
  KEEP (*(SORT(.dtors.*)))
@@ -145,6 +148,14 @@
  } >dram0_0_seg :dram0_0_bss_phdr
/* __stack = 0x3ffc8000; */
+  .irom0.text : ALIGN(4)
+  {
+  _irom0_text_start = ABSOLUTE(.);
+  *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text)
+  build/app_app.a:*_flash.o(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
+  _irom0_text_end = ABSOLUTE(.);
+  } >irom0_0_seg :irom0_0_phdr
+
  .text : ALIGN(4)
  {
  _stext = .;
@@ -153,6 +164,7 @@
  *(.init.literal)
  *(.init)
  *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
+  build/app_app.a:*_flash.o(.iram.literal .iram.text.literal .iram.text)
  *(.fini.literal)
  *(.fini)
  *(.gnu.version)
@@ -169,12 +181,6 @@
  _lit4_end = ABSOLUTE(.);
  } >iram1_0_seg :iram1_0_phdr
-  .irom0.text : ALIGN(4)
-  {
-  _irom0_text_start = ABSOLUTE(.);
-  *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text)
-  _irom0_text_end = ABSOLUTE(.);
-  } >irom0_0_seg :irom0_0_phdr
}
/* get ROM code address */
Файлы, содержимое которых должно идти по умолчанию во FLASH называть *_flash.* а функции которые должны пойти в IRAM помечать следующим атрибутом:
#define IRAM_ATTR __attribute__((section(".iram.text")))

P.S. что-то у меня не работает EXCLUDE_FILE, и я теперь даже не уверен, что он работал с самого начала.
 

Alex_S

New member
Чем дальше в лес - тем толще партизаны )))
Продолжил игры с stl, попробовал добавить в проект использование типа string. Вроде бы должно быть не особо накладно, и вроде бы реализовано все в виде шаблона.
Но и тут ждут грабли. Шаблон string не работает без либы libstdc++. Подключение этой либы сразу же превосходит все возможности по памяти )))

Вроде бы - реализуй зависимости у себя, и будет счастье. Но гугление принесло мало результатов. Как правило все упираются в то, что неправильно подключена либа stdc++, и как это исправить.
До того stl на малых системах не применял (не было необходимости), а тут хочется поиграться и подучиться ). Да и по идее не должно быть особенно накладно на простых типах..
В общем - ошибки такие выдает линковщик:
Код:
LD build/app.out
G:\Proj\ESP8266\WebSensor/user/HTTPClient.cpp:520: undefined reference to `std::string::_Rep::_S_empty_rep_storage'
G:\Proj\ESP8266\WebSensor/user/HTTPClient.cpp:521: undefined reference to `std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, unsigned int, std::allocator<char> const&)'
G:\Proj\ESP8266\WebSensor/user/HTTPClient.cpp:521: undefined reference to `std::string::assign(std::string const&)'
G:\Proj\ESP8266\WebSensor/user/HTTPClient.cpp:521: undefined reference to `std::string::_Rep::_M_destroy(std::allocator<char> const&)'
G:\Proj\ESP8266\WebSensor/user/HTTPClient.cpp:527: undefined reference to `std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&)'
c:\espressif\xtensa-lx106-elf\xtensa-lx106-elf\include\c++\4.8.2\bits/basic_string.h:539: undefined reference to `std::string::_Rep::_M_destroy(std::allocator<char> const&)'
(.text._ZNSt6vectorI7tHeaderSaIS0_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS0_S2_EERKS0_[_ZNSt6vectorI7tHeaderSaIS0_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS0_S2_EERKS0_]+0x8): undefined reference to `std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&)'
build/app_app.a(HTTPClient.o): In function `std::string::_Rep::_M_dispose(std::allocator<char> const&)':
c:\espressif\xtensa-lx106-elf\xtensa-lx106-elf\include\c++\4.8.2\bits/basic_string.h:240: undefined reference to `std::string::_Rep::_M_destroy(std::allocator<char> const&)'
Из того, что я понял: std::string::_Rep::_S_empty_rep_storage - это место в памяти, на которое ссылается пустая строка, чтобы не выделять для пустой строки память под каждый объект. Но в каком виде ее задать?
До остальных зависимостей я пока не дошел ))

И самый интересный вопрос - можно ли как-то сказать линкеру, чтобы он при включении какой-то либы не тянул ее всю, а выдергивал только нужные функции оттуда?
 

jcmvbkbc

New member
Чем дальше в лес - тем толще партизаны )))
Продолжил игры с stl, попробовал добавить в проект использование типа string. Вроде бы должно быть не особо накладно, и вроде бы реализовано все в виде шаблона.
Но и тут ждут грабли. Шаблон string не работает без либы libstdc++. Подключение этой либы сразу же превосходит все возможности по памяти )))

Вроде бы - реализуй зависимости у себя, и будет счастье.
Думаю, что тут счастья не найти.
Из того, что я понял: std::string::_Rep::_S_empty_rep_storage - это место в памяти, на которое ссылается пустая строка, чтобы не выделять для пустой строки память под каждый объект. Но в каком виде ее задать?
Проще всего было бы посмотреть в исходниках stl:
Код:
  template<typename _CharT, typename _Traits, typename _Alloc>
  typename basic_string<_CharT, _Traits, _Alloc>::size_type
  basic_string<_CharT, _Traits, _Alloc>::_Rep::_S_empty_rep_storage[
  (sizeof(_Rep_base) + sizeof(_CharT) + sizeof(size_type) - 1) /
  sizeof(size_type)];
И самый интересный вопрос - можно ли как-то сказать линкеру, чтобы он при включении какой-то либы не тянул ее всю, а выдергивал только нужные функции оттуда?
Обычно для этого компилируют с флагом -ffunction-sections и -fdata-sections, компилятор при этом заводит для каждой функции отдельную секцию. libstdc++ так и собрана. Потом линкуют с опцией --gc-sections и линкер выкидывает все секции (== функции и переменные) которые не были использованы явно или по зависимостям.
 

Alex_S

New member
Обычно для этого компилируют с флагом -ffunction-sections и -fdata-sections, компилятор при этом заводит для каждой функции отдельную секцию. libstdc++ так и собрана. Потом линкуют с опцией --gc-sections и линкер выкидывает все секции (== функции и переменные) которые не были использованы явно или по зависимостям.
Пробовал, но он все равно запихнул дофига всего (map в аттаче).
Флаги компиляции:
Код:
# libraries used in this project, mainly provided by the SDK
LIBS     = c gcc hal phy pp net80211 lwip wpa main stdc++

# compiler flags using during compilation of source files
CFLAGS     = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals  -D__ets__ -DICACHE_FLASH -ffunction-sections -fdata-sections
CXXFLAGS   = $(CFLAGS) -fno-rtti -fno-exceptions

# linker flags used to generate the main object file
LDFLAGS     = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,--gc-sections -Wl,-Map d:\map.txt
как видим - там есть и исключения, и маллок, и еще куча прочего..
Есть ли способ как-то уменьшить итоговый размер, выкинув лишнее?
 

Вложения

  • 47.7 KB Просмотры: 1

jcmvbkbc

New member
Пробовал, но он все равно запихнул дофига всего (map в аттаче).
как видим - там есть и исключения, и маллок, и еще куча прочего..
Есть ли способ как-то уменьшить итоговый размер, выкинув лишнее?
Если исключения пролезли -- пиши пропало :)
Мануал libstdc++ предлагает конфигурировать её с опцией --enable-cxx-flags=-fno-exceptions и другими интересными вариантами.
 

Alex_S

New member
А сконфигурировать либу под силу обычному человеку? Под виндой это можно сделать?
 

anakod

Moderator
Команда форума
Но и тут ждут грабли. Шаблон string не работает без либы libstdc++. Подключение этой либы сразу же превосходит все возможности по памяти )))
Я почти уверен что все вполне можно уместить, если грамотно все раскидать по разделам памяти. Но с этими разделами памяти просто какой-то ад. Вчера я честно достаточно упорно курил ман https://access.redhat.com/documenta..._GNU_Linker/sections.html#OUTPUT-SECTION-FILL но мало того что оно не делает того что нужно, там даже некоторые стандартные примеры собираться не хотят :( Может быть кто-нибудь посоветует что лучше почитать по этой теме?

Предложенный EXCLUDE_FILE тоже не заработал, я попробовал довольно много разных вариантов. Сегодня как только доберусь до железки попробую новый вариант с *_flash.* может быть он поможет.
Еще вчера я проводил любопытный тест - унес весь основной код в секцию FLAH. Компилируется нормально, запускается, размер получился просто восхитительный (примерно 9Кб из 32) но при запуске в UART сыпется какой-то треш :) Пробовал по-библиотечно переносить руками загрузочные модули обратно в IRAM но, к сожалению, тоже не помогло..

А есть ли возможность исключать не по файлам а по библиотекам целиком? Как-то в секциях описать какая либа должна упасть в ROM по умолчанию, чтобы не завязываться на множество отдельных классов/файлов. Это вдвойне актуально для сторонних библиотек.
 

jcmvbkbc

New member
А сконфигурировать либу под силу обычному человеку? Под виндой это можно сделать?
Проще всего это сделать при сборке компилятора, но по идее можно и просто отдельно собрать эту либу. Типичным процессом кросс-компиляции: configure - make - make install. configure надо дать опцию --host=xtensa-lx106-elf, а в качестве кросс-компилятора указать xtensa-lx106-elf-g++. configure конечно захочет шелл и другие плюшки...
 
Сверху Снизу