• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Ускорение esp8266

mishgan

Member
Недавно задумался над вопросом, а быстро ли работает мой код. Стал делать измерения. Результат меня немного шокировал.
Например
1. Отправка сериал сообщения из 16 символов в порт при скорости 9600 занимает 60-80 микросекунд.
2. Выполнение функции digitalWrite() занимает 5 микросекунд.

Стал искать информацию по ускорению работы esp8266 и никакой информации не нашел. Стал копать глубже и нашел информацию о том что можно заменить digitalWrite() записью в порт например PORTA=B00001010 но это на ардуино.... Вот и у меня возник вопрос.... можно както разогнать esp8266 аналогичными действиями?
 

kab

New member
Отправка сериал сообщения из 16 символов в порт при скорости 9600 занимает 60-80 микросекунд.
Давайте уточним, о чем речь?:
- 9600 бит/с - это примерно 1000 симв/с. Т. е. передача 1 символа - примерно 1 миллисекунда. Если же речь о том, с какой скоростью программа записывает данные в буфер передачи - то при чем здесь скорость передачи? Зачем она упомянута?
- насчет функции digitalWrite() - если эта функция, кроме записи в порт, делает еще какие-то действия - даже не вдаваясь в подробности, можно предположить, что эти действия необходимы. Если есть основания считать, что какие-то действия функции излишни, - излагайте эти основания - тогда разговор будет предметный. А то Вы собираетесь заменить "штатную" функцию какой-то более быстрой, но, возможно, подверженной при работе каким-то неизвестным рискам. Оно Вам надо?
 

mishgan

Member
А то Вы собираетесь заменить "штатную" функцию какой-то более быстрой, но, возможно, подверженной при работе каким-то неизвестным рискам. Оно Вам надо?
А почему вы решили, что стандартные функции идеальны? Так библиотека cyberlib не вчера появилась и протестирована многими людьми.
 

mishgan

Member
Кстати а где лежат стандартные функции digitalWrite() и сериал в Arduino IDE ?
 

kab

New member
А почему вы решили, что стандартные функции идеальны? Так библиотека cyberlib не вчера появилась и протестирована многими людьми.
Я думаю, что функцию digitalWrite() "протестировали" на неск. порядков человек больше, чем библиотеку cyberlib. Хотя подчеркиваю, что рассуждаю исходя из общих соображений. Есть исходники этой библиотеки cyberlib? Их можно сравнить с исходниками "родных" функций? А остальное - философия (в худшем значении этого слова)...
 

CodeNameHawk

Moderator
Команда форума
1. Отправка сериал сообщения из 16 символов в порт при скорости 9600 занимает 60-80 микросекунд.
Откуда вы взяли такие цифры? Для скорости 9600 бод должно передаваться 960 байт/с.
Скорость передачи данных через UART
т.е. 16 символов передадутся за 16 мс.
Тут ограничение стандартом сериала, используйте скорость 115200 или выше(у меня работает и на 2000000).
2. Выполнение функции digitalWrite() занимает 5 микросекунд.
У меня получаются другие результаты :
upload_2017-10-4_17-43-59.png
100000 digitalWrite() за 46 мс или один digitalWrite() за 0,46 мкс.
Посмотрел осциллографом, на две операции
digitalWrite(2, LOW);
digitalWrite(2, HIGH);
тратится меньше 1 мкс.
Сразу повысил вам скорость в 10 раз, даже не благодарите :)
 
Последнее редактирование:

kab

New member
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\ соответственно wiring_digital.c и HardwareSerial*.*
А разве для ESP8266 не какие-то свои функции используются?
Нашёл какую-то
C:\Users\admin\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266\
core_esp8266_wiring_digital.c

Может, она?


Юрий, и еще вопрос, пожалуйста - указанные файлы при создании прошивок каждый раз компилируются заново? Т.е. если их доработать, то изменения попадут в прошивку? (Я понимаю, что это неправильно и в таком случае функции надо переопределять) Или эти файлы так - "посмотреть"?
 
Последнее редактирование:

pvvx

Активный участник сообщества
Стал искать информацию по ускорению работы esp8266 и никакой информации не нашел. Стал копать глубже и нашел информацию о том что можно заменить digitalWrite() записью в порт например PORTA=B00001010 но это на ардуино.... Вот и у меня возник вопрос.... можно както разогнать esp8266 аналогичными действиями?
Всё можно. Скорость GPIO (и его контроллера) ограничена внутренней шиной ESP8266 тактируемой от кварца (26 MHz). На шине работает FIFO. При передаче кодов управления регистрами GPIO процессор успевает сделать несколько тактов (исполнить более 6 команд на asm при 160 MHz) пока отрабатывает только очередь FIFO шины. Сам контролер GPIO тоже тактируется низкой частотой и имеет разные времена отрабатывания команд записи непосредственно в выходной регистр или в регистры Set/Clear оперирующими с уже выходным регистром управления пинами.
По умолчанию компилятор, при обращении к volatile переменным (с ней объявлены все обращения к портам в ESP8266) вставляет команду memw, которая ждет завершений/опустошений FIFO и операций кэша, но процессорного кеша команд у ESP8266 нет (есть буфер в IARM для работы c последовательной Flash, названный в постонародии так-же - "кэшем", но это совершенно другой "кэш"). Т.е. эта команда просто тормозит работу в случае ESP8266 и сильно увеличивает размер кода, да время отработки во всех драйверах. У компилятора есть опция отключения автоматической вставки данной команды.

Частично, по ранее собранным данным вот тут автор дает замеры I/O операций: ESP8266 GPIO output performance « collector {dt.:Sammler} |
Но там автор не всё собрал и разобрал... На форуме есть и более точные, уточняющие измерения и что надо проделать, чтобы ускорить работу операций с GPIO.
Но всё это не для Arduino поклонников и давалось несколько лет назад.
Концепция Arduino IDE для ESP8266 не рассчитывает на качество и скорость - её задачи другие и ограничены медленными операциями, типа переключения светодиода или лампочки один раз в секунду.
2. Выполнение функции digitalWrite() занимает 5 микросекунд.
Это зависит и от "кеша" контроллера Flash. Первое обращение к функциям в flash происходит с задержкой на чтение Flash в буфер "кэша" IRAM. И если у вас ещё вставлены медленные установки для Flash, типа DIO и 40 MHz, то может выйти и больше 5 мкс, вместо вполне возможных и реализуемых коммутаций пинов с дискретностью в 26 MHz контроллером GPIO в ESP8266 (но это не для Arduino IDE). :) Для более быстрых шевелений GPIO используют не медленный GPIO контролер, а SPI или I2S. Там уже ограничения строба переключения пина к сотне MHz.
На то есть примеры генерации видео сигнала с модуляцией на FM частоте канала около 100 MHz телевидения на GPIO ESP8266, как и обработка считывания и передачи на пинах ESP8266 сигналов USB1.1 :)
Чтобы этого достичь, необходимо отказаться от концепций Arduino.
Ну а т.к. ардуинщики привыкли к кормлению самыми ужасными реализациями кода и библиотек, то вы не в том разделе задаете такие вопросы. Тем более паровоз ESP8266 уже ушел давно на свалку истории, никто из более грамотных не будет ничего переписывать в Arduino IDE.
Эта возможность предоставляется вам, в качестве обучения, т.к. всё необходимое уже описано и разобрано ранее, но никому из более грамотных разработчиков не потребовалось и не потребуется Arduino, тем более на устаревший чип.
 
Последнее редактирование:

Alex0335

New member
@mishgan
Может кому пригодится. Если глянуть в код функции можно отбросить лишнее.
Код:
extern void ICACHE_RAM_ATTR __digitalWrite(uint8_t pin, uint8_t val) {
  pwm_stop_pin(pin);
  if(pin < 16){
    if(val) GPOS = (1 << pin);
    else GPOC = (1 << pin);
  } else if(pin == 16){
    if(val) GP16O |= 1;
    else GP16O &= ~1;
  }
}
Время отъедает функция pwm_stop_pin и прочие сравнения. Если точно известно что для порта не нужно отключать ШИМ, то думаю можно ограничится командами:
Установить 1: "GPOS = (1 << pin);"
Установить 0: "GPOC = (1 << pin);"

При настройках ESP: Crystal Freq=26MHz; Flash Freq = 40 MHz; CPU Freq = 80 MHz;
Этот код дает 5.5 MHz против ~560 KHz на функции DigitalWrite

Код:
  while (true){
    GPOS = (1 << 5);
    GPOC = (1 << 5);
  }
 
Сверху Снизу