Программирование ARM espressif.com FAQ ESP8266 Thu, March 28 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

espressif.com FAQ ESP8266 Печать
Добавил(а) microsin   

Здесь приведен перевод FAQ [1] с сайта espressif.com. Все непонятные сокращения и термины см. в разделе "Словарик" в конце статьи.

ESP-01 module PCB top ESP-01 module PCB bottom

[Приложение (Application)]

Вы можете запустить скрипт gen_mish.sh в окне терминала, чтобы сгенерировать по отдельности файлы user1.bin и user2.bin. Выполняйте следующие шаги:

1. Скомпилируйте user1.bin, используя корректные установки Flash и boot.

2. Выполните команду "make clean", которая очистит файлы, сгенерированные на первом шаге. Скомпилируйте user2.bin, и гарантируйте при этом, что используете для него те же самые опции, что использовали для генерации user1.bin.

Файлы user1.bin и user2.bin это два разные файла. Они должны быть сгенерированы для одинаковой конфигурации flash/boot, чтобы перепрошивка по технологии OTA могла работать правильно. Два отдельных файла нужны потому, что программа user1.bin может загрузить user2.bin, и подобным образом user2.bin может загрузить user1.bin через OTA. Это гарантирует, что процесс обновления не будет необратимо прерван из-за разных случайных событий наподобие пропадания питания или обрыва соединения канала связи.

Причин отказа OTA может быть множество. Рекомендуется обратиться к документу "ESP8266 FOTA Guide" [2] перед использованием функций FOTA API.

Быстрый список проверки для устранения проблем с отказами OTA:

• Убедитесь, что правильно выбран размер Flash, когда загружаете firmware в память Flash.
• Когда Вы первый раз загружаете новое firmware, также всегда загружайте blank.bin.
• Убедитесь, что файлы user1.bin и (опционально) user2.bin загружены в правильные места.
• Убедитесь, что генерируете user1.bin и user2.bin с одинаковыми конфигурационными опциями Flash/boot!

Если Вы хотите обслуживать обновления OTA через свой сервер, то должны убедиться, что сервер может понимать запросы обновления прошивки (firmware upgrade requests) и отвечать на них.

Обработку запроса обновления можно обозначить следующим образом:

1. В облако посылается HEAD, запрашивающий длину BIN. Сервер отвечает пакетом HTTP (где информация о длине BIN включена в HTTP HEAD).

2. На основе полученной таким образом информации о длине BIN, очищаются сектора ESP8266 Flash, чтобы обновить прошивку с помощью API (spi_flash_erase_sector).

3. Посылается запрос GET, чтобы получить BIN-файл с сервера. Очищенная область может быть запрограммирована новым файлом BIN.

Пользователи могут предоставлять обновления через свой собственный сервер. Этот сервер должен быть в состоянии обслуживать запросы HTTP, и у него должны быть функции управления устройством (device control features).

Для справки по API см. [3].

Для подключения с серверу обновления может использоваться стандартный протокол HTTP. Например, когда устройство ESP8266 запускает сокет и отправляет запрос Вашему пользовательскому серверу:

GET /your-bin-file-path.bin HTTP/1.1
Host: yourdomain.com
Connection: keep-alive Cache-Control: max-age=0
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent:
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) 
Chrome/39.0.2171.95 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language:
en-US,en;q=0.8,ja;q=0.6,zh-CN;q=0.4,zh-TW;q=0.2

Обратите внимание, что протокол HTTP задает, что запросы оканчиваются на "\r\n\r\n", поэтому пожалуйста не используйте эту комбинацию внутри всей фразы запроса.

Вы можете отлаживать свой сервер через консоль telnet (перед этим убедитесь, что сервис telnet разрешен на Вашем PC):

telnet имя_или_IP_сервера номер_порта

Также Вы можете использовать стандартные эмуляторы терминала (TeraTerm, SecureCRT, putty и т. д.), которые поддерживают протокол telnet.

Вот несколько возможных причин SmartConfig fail:

• Версия APP не соответствует SDK или версии SmartConfig.
• Роутер, участвующий в конфигурации, работает только на частоте 5 ГГц.
• Были вызваны некоторые другие функции API во время работы SmartConfig (пожалуйста, не вызывайте никакие API-функции, пока SmartConfig не завершит работу).
• Когда используются команды AT, не останавливайте SmartConfig до того, как устройство получит IP от роутера.

Если ни один из этих советов не решил Вашу проблему, то пожалуйста пришлите лог отладки (debug log) службе поддержки espressif.com, чтобы она могла проанализировать проблему.

Если пользователь вызовет API smartconfig_start(), то будет выведена строка наподобие "SC version: vX.X.X". В таблице ниже перечислены связанные версии SDK и APP для версий SmartConfig:

sdk v1.2.0 smartconfig v2.4 app v0.3.4.x
sdk v1.3.0 smartconfig v2.5
smartconfig v2.5.1
sdk v1.4.0 smartconfig v2.5.2
sdk v1.5.0 smartconfig v2.5.3
sdk v1.5.4 smartconfig v2.5.4

Да, поддерживает. ESP8266 может быть запущен как сервер в обоих режимах SoftAP (точка доступа Wi-Fi) и Station (клиент Wi-Fi).    

• Когда сервер запускается в режиме SoftAP, клиенты могут напрямую подключаться к хосту ESP8266 или серверу по IP-адресу (по умолчанию) 192.168.4.1.
• Когда к серверу осуществляется подключение через роутер, то этим роутером будет выделен IP-адрес сервера для ESP8266.
• Когда используется SDK для написания native-кода, используйте структуру espconn и связанное с ней API.
• Когда используются команды AT, запускайте сервер командой AT+CIPSERVER.

1. Для конфигурирования режима SoftAP + Station используйте команду: AT+CWMODE=3.

2. Для подключения к роутеру используйте команду: AT+CWJAP="SSID","password".

3. Создайте соединение TCP и передайте данные в соответствии с форматом пакета HTTP, как показано на рисунке ниже. Имейте в виду, что символы перевода строки [(0x0d 0x0a) или (CR LF)] важны для завершения строки, и они не должны быть опущены.

espressif FAQ fig01

4. Принимайте возвращенное сообщение из пакетов HTTP.

espressif FAQ fig02

Пример, как определить AT-команду AT "AT+TEST" можно найти в папке демонстрационных AT-примеров Non-OS SDK (\ESP8266_NONOS_SDK\examples\at\user\user_main.c). Для определения одного из 4 вариантов AT-команды используется структура at_funcationType. Мы используем команду AT+TEST в качестве примера того, как это может быть реализовано.

1. Введите at_testCmd: команда теста в формате AT+TEST=?. В AT demo зарегистрированной callback-функцией будет at_testCmdTest. Запрос на тест может быть запрограммирован, чтобы вернуть диапазон значения параметра. Если at_testCmd зарегистрирована как NULL, то она не реализована.

2. Введите at_queryCmd: команда запроса в формате AT+TEST=?. В AT demo зарегистрированной callback-функцией будет at_queryCmdTest. Запрос на тест должен быть запрограммирован для возврата текущего значения. Если at_queryCmdTest зарегистрирована как NULL, то она не реализована.

3. Введите at_setupCmd: команда установки имеет формат AT+TEST=parameter1,parameter2,...,. В AT demo зарегистрированной callback-функцией будет at_setupCmdTest. Команда установки может быть запрограммирована для установки значения параметра. Если at_setupCmdTest зарегистрирована как NULL, то она не реализована.

4. Введите at_exeCmd: команда выполнения в формате AT+TEST. В AT demo зарегистрированной callback-функцией будет at_exeCmdTest. Команда выполнения может быть запрограммирована, чтобы запустить какую-либо операцию. Если at_exeCmdTest зарегистрирована как NULL, то она не реализована.

Пользователю нужно установить идентификатор устройства (device ID). Например, device ID=1234 требуется для установки для устройства, использующего клиентский аккаунт WeChat. Используйте следующую команду:

curl -q "https://api.weixin.qq.com/cgi-bin/token? 
grant_type=client_credential&appid=wx0f74f861897f84b5&secret
=your_We Chatname_32characters_please"

Примечание: это используется для получения токена доступа. Здесь "your_WeChatname_32characters_please" представляет клиентский WeChat API App Secret, который может быть получен через приложение, и должен быть длиной 32 символа.

Возврат:

curl -d '{"device_num":"1","device_list":[{"id":"1234","mac":"18fe3497d500","connect_protocol":"4",
"auth_key":"00000000000000000000000000000000",
"close_strategy":"1","conn_strategy":"1","crypt_method":"0","auth_ver":"0","manu_mac_pos":"-2",
"ser_mac_pos":"-2"}],"op_type":"0", "product_id": 5157}'
"https://api.weixin.qq.com/device/authorize_device?access_token=L2_2V1E98Vk-jTXenXDZjDT0GaudUn_VGTRa7O98
hdfT0lTZa2B7nj6YvXN01gssQa3ZraRgjALuCvxd-SamuPR885KJabaw1EYLA0kns-Yglr4ryolEhHb-QcnWMaNqSEDjACANZY"

Примечание: это установка device ID=1234.

Далее нужно использовать AT-команду:

AT+CWSTARTDISCOVER="gh_9e2cff3dfa51","1234",1

Здесь в "gh_9e2cff3dfa51", "9e2cff3dfa51" задается Ваш официальный аккаунт WeChat.

Пользователи могут добавить свою AT-команду на основе AT-команд ESP8266, используя код примера ESP8266_NONOS_SDK\examples\at. Максимальная длина строки команды AT, поддерживаемая SDK, равна 128 байтам (включая терминатор "\r\n"). Длина AT-команды и параметров не имеют индивидуальных ограничений.

Например, есть команда:

AT+CMDTEST=param1,param2,param3,...,paramN\r\n

Тогда значение, возвращенное strlen(“AT+CMDTEST=param1,param2,param3,....paramN\r\n”), должно быть меньше или равно 128.   

Дополнительную информацию см. в ESP8266 SDKs & Demos [5].

Для обоих SDK, Non-OS SDK и RTOS SDK, место размещения двоичных файлов firmware определяется содержимым подходящего скрипта линкера. В случае не-FOTA firmware код пользователя содержится в eagle.irom0.text.bin. Место для этого двоичного файла во flash определяется скриптом линкера eagle.app.v6.ld, который находится в SDK/ld.

Имейте в виду, что место по умолчанию eagle.irom0.text.bin НЕ БУДЕТ одинаковым для всех версий ESP8266 SDK. Вы можете определить адрес flash для Вашего SDK следующим образом:

espressif FAQ fig03

Адрес, помеченный голубой рамкой, является адресом flash для eagle.irom0.text.bin. В этом примере он равен 0x10000.

[Облако (Cloud)]

1. Как только загружен master-device-key, устройство ESP8266 готово к использованию.

2. Конечный пользователь может использовать Airkiss/ESP-TOUCH для подключения через сеть к устройству ESP8266. В то же время устройство посылает случайный символьный токен, сгенерированный App в качестве идентификатора разрешения доступа (permission identifier). Затем устройство вызывает /v1/device/activate, и посылает токен в облако.

3. Конечный пользователь использует App, вызывает интерфейс /v1/device/authorize (с использованием случайного токена, сгенерированного перед этим), и подтверждает владение устройством (например, становится владельцем, и получает ключ владельца, owner key).

4. Владение устройством ESP8266 то же самое, что и владение ключом устройства, с помощью которого пользователь может управлять устройством.

5. Конечный пользователь может вызвать /v1/user/devices, чтобы получить список устройств, которыми он завладел, и соответствующие им ключи устройств.

6. В качестве владельца устройства конечный пользователь может вызвать /v1/device/share, чтобы предоставить устройство в общий доступ для других пользователей, кто может вызвать /v1/device/authorize, чтобы получить авторизацию.

[Аппаратура (Hardware)]

1. Напряжение питания цифровой части: 1.8V - 3.3V.

2. Напряжение питания аналоговой части: 3.0V - 3.6V (самое низкое возможное напряжение 2.7V).

3. Пиковое потребление тока аналоговой схемы: 350 mA.

4. Пиковое потребление тока цифровой схемы: 200 mA.

Примечание: CHIP_EN работает на напряжении 3.0V - 3.6V, пожалуйста используйте преобразователь уровня, чтобы гарантировать совместимость с цифровой логикой 1.8V.

Проектирование источников питания для радиочастотных схем (RF) само по себе является искусством и требует рассмотрения многих тем. Однако здесь приведен краткий список для гарантии, что учтены важные компоненты:

1. Если Вы используете регулятор LDO, то убедитесь, что разница у его Vin и Vout достаточна велика для нормальной (по паспорту) работы этого регулятора.

2. Развязывающий конденсатор шины питания должен находиться максимально близко к ESP8266, и должен иметь низкий ESR.

3. Никогда не подключайте напрямую к ESP8266 периферийные устройства с уровнями логики 5V.

4. Если ESP8266 питается от преобразователя DC-DC, то гарантируйте, то преобразователь правильным образом спроектирован. Пульсации и помехи должны быть тщательно отфильтрованы каскадными LC-фильтрами, если это необходимо.

ESP8266 является высоко-интегрированной микросхемой, в которой сосредоточены как аналоговые RF-схемы (радио), так и цифровые узлы. При загрузке (booting) такие функции, как калибровка радиочастоты, могут потреблять заметное количество энергии. Максимальная (мгновенная) аналоговая мощность может считаться на уровне потребляемого тока 500 mA, и цифровые схемы на пике могут потреблять около 200 mA. Нормальный рабочий ток потребления обычно составляет около 100 mA, в зависимости от приложения и дизайна схемы. Таким образом, Ваша разработка схемы должна предоставить регулятор напряжения, который может дать ток 500 mA без чрезмерного падения выходного напряжения, выходящего за пределы рабочих спецификаций.

Две батарейки AA, соединенные последовательно, могут предоставить питание для ESP8266. У ячейки Li-Po слишком велико колебание напряжения от напряжения полного заряда до напряжения рабочего разряда, поэтому ячейку Li-Po нельзя напрямую подключать к питанию ESP8266.  

ESP8266 содержит прецизионную схему RF (радиотракт), на которую влияют изменения температуры или напряжения. Прямое подключение схемы RF к нерегулируемому источнику питания не рекомендуется.

Настоятельно рекомендуется использовать преобразователь DC-DC или регулятор LDO, чтобы гарантировать работу ESP8266 согласно её спецификации.

Память SPI flash является интегральной частью системы, так как в ней хранятся программа и данные пользователя. Чтобы гарантировать совместимость с цифровой логикой, напряжение SPI flash должно соответствовать уровню логики GPIO.

Вывод микросхемы CHIP_EN (chip enable) не имеет встроенного верхнего подтягивающего резистора (pull-up). Он должен быть подтянут снаружи к уровню лог. 1, чтобы разрешить работу микросхемы. CHIP_EN должен быть подтянут к высокому уровню после или одновременно с напряжением VDD33. После истечения 60 мс от момента, когда CHIP_EN получил уровень лог. 1, устройство будет определять режим загрузки на основе состояния выводов GPIO15, GPIO0, GPIO2, и затем установит соединение через UART.  

EXT_RSTB: вывод внешнего сброса. Этот вывод имеет внутренний верхний подтягивающий резистор (internal pull-up), поэтому если его оставить не подключенным, то на нем автоматически установится уровень лог. 1. Подача лог. 0 на этот вывод приведет к срабатыванию сброса чипа. Сигнал сброса должен быть 0.25 IO + 100 мкс. Диаграмма сигналов должна быть следующая:

espressif FAQ fig04

  Описание интервала времени MIN MAX Ед.
t1 Время нарастания VDD33 10 2000 мкс
t2 Время нарастания EXT_RSTB 0 2 мс
t3 EXT_RSTB переходит в лог. 1 после VDD33 0.1 - мс
t4 Время нарастания CHIP_EN 0 2 мс
t5 CHIP_EN переходит в лог. 1 после EXT_RSTB 0.1 - мс

ESP8266 имеет внутреннее ОЗУ (IRAM) 64 килобайта и DRAM 96 килобайт.

IRAM делится на 2 блока: первый блок на 32 килобайта хранит код, и не помечается ICACHE_FLASH_ATTR (.text). Следующие 32 килобайт это iCache, который хранит код, помеченный ICACHE_FLASH_ATTR.  

Когда используется Non-OS SDK, начальные 80 килобайт DRAM используются для хранения .data/.bss/.rodata/heap, и оставшиеся 16 килобайт используются для кода ROM. Когда используется RTOS SDK, то .data/.bss/.rodata/heap занимает все 96 килобайт DRAM.

[Периферийные устройства]

Один канал, частота оцифровки 100k выборок/сек при выключенном модеме Wi-Fi, и 1k выборок при нормально-активном модеме Wi-Fi. Разрешающая способность 12 бит (10 бит при чтении через вызов system_adc_read()).

ADC тесно интегрирован с внутренними схемами радиотракта (RF) и поэтому назначение бит и информация о регистрах недоступны для открытого использования. Разработчики выражают сожаление из-за этих неудобств, и приглашают обращаться в техподдержку для получения дополнительной информации.

Когда ESP8266 подключена к роутерам, она войдет в modem_sleep только в режиме клиента Wi-Fi (только в STA mode), что приведет к изменению внутренних токов потребления кристалла и значений опорных напряжений, в результате чего оцифровка ADC будет работать в ненормальном режиме.  

Если требуется высокая точность, используйте API-вызов system_adc_fast_read. Однако при этом RF-узлы чипа должны быть выключены перед измерениями ADC, и следовательно должно произойти отключение Wi-Fi. Для относительно низкой точности, когда допустима разница между чтениями 1 или 2, блок Wi-Fi может быть сконфигурирован для режима non_sleep.  

Для меньшей точности пользователь может ввести микросхему в режим сна (sleep mode). В этом случае потребление энергии снизится.

Внутренний ADC (АЦП) микросхемы ESP8266 может использоваться для измерения температуры или для приблизительной оценки тока, потребляемого внешними устройствами. Имейте в виду, поскольку на работу ADC влияет шум, ADC должен использоваться только для тех приложений, где не нужна высокая точность (например, термореле, и т. п.).

tx_addr адрес отправки
tx_cmd отправляемая команда
tx_rep время повторения

С кварцевым резонатором 26 МГц скорость по умолчанию ESP8266 при включении питания составляет 74880 для UART0. Из-за этого при включении могут появляться "не читаемые" символы.

Пользователи могут поменять конфигурацию UART в теле функции user_main(). Например, поменяйте скорость (baud rate) следующим образом:

void ICACHE_FLASH_ATTR uart_init(UartBautRate uart0_br, UartBautRate uart1_br)
{
   // rom использует 74880 baut_rate, здесь повторная инициализация
   UartDev.baut_rate = uart0_br; 
   uart_config(UART0);
   UartDev.baut_rate = uart1_br; 
   uart_config(UART1);
}

Для конфигурирования формата данных обмена UART обратитесь к файлу uart.c в SDK/driver_lib/driver/.

Для конфигурирования аппаратного управления потоком (hardware flow control) при обмене данными UART выполняют следующие шаги:

1. Установите следующие атрибуты в 1 путем правки uart.h:

// Разрешает для UART0 hw flow control RTS, вывод MTDO:
#define UART_HW_RTS 1
// Разрешает для UART0 hw flow control CTS, вывод MTCK:
#define UART_HW_CTS 1

2. Сконфигурируйте порог для hardware flow control. Как это делается, показано красным контуром на скриншоте ниже. Когда количество байт в RXFIFO становится больше 110, сигнал RTS переводится в лог. 1.

espressif FAQ fig05

UART1 предоставляет только вывод TxD для вывода данных лога. Это можно использовать как альтернативу выводу через главный последовательный порт UART0, когда он используется для других целей.

См. следующий пример кода для конфигурирования UART1:

void ICACHE_FLASH_ATTR uart_init_new(void) 
{ 
   // Ожидание опустошения стеков FIFO:
   UART_WaitTxFifoEmpty(UART0); 
   UART_WaitTxFifoEmpty(UART1); 
   // Конфигурирование настроек UART:
   UART_ConfigTypeDef uart_config; 
   uart_config.baud_rate = BIT_RATE_74880; 
   uart_config.data_bits = UART_WordLength_8b; 
   uart_config.parity    = USART_Parity_None; 
   uart_config.stop_bits = USART_StopBits_1; 
   uart_config.flow_ctrl = USART_HardwareFlowControl_None; 
   uart_config.UART_RxFlowThresh = 120; 
   uart_config.UART_InverseMask = UART_None_Inverse; 
   UART_ParamConfig(UART0, &uart_config); 
        
   UART_IntrConfTypeDef uart_intr; 
   uart_intr.UART_IntrEnMask = UART_RXFIFO_TOUT_INT_ENA
                             | UART_FRM_ERR_INT_ENA
                             | UART_RXFIFO_FULL_INT_ENA; 
   uart_intr.UART_RX_FifoFullIntrThresh = 100; 
   uart_intr.UART_RX_TimeOutIntrThresh = 2; 
   uart_intr.UART_TX_FifoEmptyIntrThresh = 20; 
   UART_IntrConfig(UART0, &uart_intr); 
   // Назначение UART1 для печати:
   UART_SetPrintPort(UART1);
   // Регистрация обработчика прерывания:
   UART_intr_handler_register(uart0_rx_intr_handler);
   ETS_UART_INTR_ENABLE();
}

Нет, не поддерживает. Аппаратура SDIO может работать только в режиме устройства, т. е. поддерживает только подчиненный профиль. Поэтому SDIO микросхемы ESP8266 не может работать как хост, управляя другими устройствами SDIO, такими как карты SD.

Hardware SDIO slave module поддерживает максимальную тактовую частоту 50 МГц. Так как SDIO задает использование 4 линий для данных, то в результате эффективная максимальная скорость передачи данных составляет 50*4 = 200 Mbps.

В любом случае проблемы не зависят от дизайна драйвера LED. Если на LED подается ток от лог. 0, и подключенная к нему ножка GPIO программно переводится в уровень лог. 0 при подаче питания, то LED может зажигаться или мерцать. Если светодиод зажигается от лог. 1, то причина может быть в том, что на всех ножках GPIO разрешены внутренние резисторы pull-up (кроме ножек GPIO4 и GPIO5, связанных с Flash).  

Решение проблемы:

1. Запретите все внутренние резисторы pull-up в функции user_init, которая запускается при включении питания.

2. Если первый метод не сработал, то свяжитесь со службой поддержки Espressif для получения специально скомпилированного файла boot.bin. В нем GPIO pull-up будут запрещены, когда boot.bin загрузится в RAM, что произойдет раньше, чем будет вызван код в user.bin.

3. Подключайте светодиоды таким образом, чтобы они зажигались от лог. 0, тогда внутренние резисторы pull-up, когда они разрешены, не будут подавать в них ток.

Имейте в виду, что PWM генерируется программно, и малый выброс может быть вызван в результате измерения разрешающей способности, которой может достичь PWM. В режиме высокой точности (high accuracy) разрешающая способность может быть до 22222 отсчетов. Однако скважность никогда не может достичь 100%.

Если Вы используете программное API, как в примере из SDK demo (light_set_aim и light_set_aim_r), то эти API оптимизированы для приложений освещения, и поэтому в них реализованы плавные переходы скважности.

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

Нет, не являются. Однако многие приложения могут обходить это ограничение путем использования резисторного делителя напряжения или последовательного включенного резистора, разработчики настоятельно рекомендуют использовать подходящую микросхему преобразователя уровня (как например GTL2003 или MAX3002) для организации интерфейса 5V-логикой. Невыполнение этой рекомендации в конечном счете может повредить ESP8266.

Ниже приведены два примера операций с GPIO.

Например, для Non-OS SDK, конфигурируется вход для MTDO в режиме срабатывания по спаду уровня (falling-edge-triggered mode):

void ICACHE_FLASH_ATTR gpio_init(void)
{
   // Включение альтернативной функции GPIO:
   PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U,FUNC_GPIO15); 
   // Конфигурирование в режиме входа:
   GPIO_DIS_OUTPUT(GPIO_ID_PIN(15));
   // Закрытие прерывания GPIO:
   ETS_GPIO_INTR_DISABLE();
   // Регистрация функции прерывания:
   ETS_GPIO_INTR_ATTACH(GPIO_INTERRUPT,NULL);
   // Срабатывание будет по спаду:
   gpio_pin_intr_state_set(GPIO_ID_PIN(15),GPIO_PIN_INTR_NEGEDGE);
   // Разрешение прерывания GPIO:
   ETS_GPIO_INTR_ENABLE() ;
}

То же самое для RTOS SDK:

void ICACHE_FLASH_ATTR gpio_init(void)
{
   // Определение переменной для структуры GPIO Init:
   GPIO_ConfigTypeDef gpio_in_cfg;
   // Триггер по спаду:
   gpio_in_cfg.GPIO_IntrType = GPIO_PIN_INTR_NEGEDGE;
   // Режим входа:
   gpio_in_cfg.GPIO_Mode = GPIO_Mode_Input;
   // Какой вывод будет разрешен:
   gpio_in_cfg.GPIO_Pin = GPIO_Pin_15;
   // Вызов функции инициализации:
   gpio_config(&gpio_in_cfg);
   GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, BIT(GPIO_UART_IN_NUM));
   // Регистрация функции прерывания:
   gpio_intr_handler_register(interrupt_GPIO_UART);
   // Разрешение прерывания GPIO:
   _xt_isr_unmask(1 << ETS_GPIO_INUM);
}

Обратите внимание, что для программирования одного и того же функционала могут быть незначительные различия в кода для приложений RTOS и приложений без операционной системы (Non-OS applications).

Буфер данных периферийного устройства HSPI состоит из 16 слов (или 64 байта). На карте памяти он доступен словами как непрерывный блок. Буфер очень гибок в плане того, что содержащиеся в нем данные могут быть переданы либо младшим (LSB), либо старшим (MSB) битом вперед, и также к нему может осуществляться доступ с разным порядком байт - либо little-endian, либо big-endian. Это устраняет необходимость в лишних программных манипуляциях над содержимым буфера. Когда задействован буфер HSPI, загрузка канала может превышать 90% на умеренных тактовых частотах.

В отличие от интерфейса I2C (или TWI) тактовую частоту интерфейса HSPI не нужно делать медленнее, чем самое медленное устройство в сети интерфейса. Скорость можно динамически изменять в соответствии с текущим активным внешним периферийным устройством, подключенным через SPI. 

Вывод HSPI_CS0 может быть подключен к интерфейсу HSPI, и он может управляться автоматически. Это должно использоваться для устройств наподобие LCD, которые требуют частой активности сигнала выборки CS. 

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

Используйте CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MISO_HIGHPART);, чтобы разрешить использование верхней части буфера данных для передачи.

wifi_station_set_auto_connect
wifi_station_ap_number_set
wifi_set_phy_mode
wifi_softap_set_config
wifi_station_set_config
wifi_set_opmode
system_restart_enhance
system_restore
system_upgrade_reboot

Последние 3 сектора главной памяти flash (primary Flash memory) назначены под хранилище системных параметров (system parameter area). Первые 2 являются копиями, поэтому как минимум одна копия останется в целости, когда случайно пропадет питание при записи одного сектора. Последний сектор используется флага, показывающего, какой из первых двух секторов нужно использовать. Этот механизм гарантирует, что важные данные конфигурации никогда не будут повреждены из-за отказа питания во время операций стирания/записи (erase/write).

Нет, все операции чтения/записи должны быть выровнены по границе 4 байт (на слово). Разработчики настоятельно рекомендуют применять редкие блочные операции вместо часто повторяющихся манипуляций с малыми объемами данных (использовать буфер для Flash во внутренней оперативной памяти).

Имейте в виду, что память flash это отдельная микросхема, подключаемая к ESP8266 снаружи. Если Ваш код предназначен для работы в системах с разными конфигурациями памяти, то имейте в виду, что начальная загрузка firmware осуществляется при правильном выборе размера flash. Таким образом, в зоне ответственности кода находится определение диапазона адресов Flash, чтобы не позволять запись/чтение адресов, которые физически недоступны. 

Например, для размера flash 8 мегабит операции чтения/записи по адресам свыше 0xFFFFF будут недопустимыми.

Ниже дан пример подпрограммы теста flash. Здесь входные параметры: uint32 sector задает начальный сектор, и uint32 задает количество секторов для стирания (erase).

#define FLASH_WRITE_LEN_BYTE (1024*4)
#define FLASH_WRITE_CONTENT (0X10)
 
// Входные параметры: uint32 sector задает начальный сектор,
// и uint32 задает количество секторов для стирания (erase).
void flash_sector_rw_test(uint32 sector, uint32 cnt)
{
   char* w_data=(char*)os_malloc(FLASH_WRITE_LEN_BYTE);
   uint32 flash_operate=0;
   uint32 i=0;
   uint8 status=0;
   os_printf("Test Sector is 0x%x\n",sector);
   if(NULL==w_data){
   os_printf("Memory little\n");
   return;
}
 
os_memset(w_data,FLASH_WRITE_CONTENT,FLASH_WRITE_LEN_BYTE);
for(i=0; i < cnt; i++)
{
   if(spi_flash_erase_sector(sector+i)==0)
   {
      os_printf("erase sector0x%x ok\n",sector+i);
   }
   else
   {
      os_printf("Err:erase sector0x%x err\n",sector+i);
   }
}
for(i=0; i < cnt; i++)
{
   if(spi_flash_write((sector+i)*(FLASH_WRITE_LEN_BYTE),
                      (uint32*)w_data,FLASH_WRITE_LEN_BYTE)==0)
   {
      os_printf("write sector 0x%x ok\n",sector+i);
   }
   else
   {
      os_printf("Err:write sector 0x%x err\n",sector+i);
   }
}
for(i=0; i < cnt; i++)
{
   os_memset(w_data,0x00,FLASH_WRITE_LEN_BYTE);
   if(spi_flash_read((sector+i)*(FLASH_WRITE_LEN_BYTE),
                     (uint32*)w_data,FLASH_WRITE_LEN_BYTE)==0)
   {
      uint32 j=0;
      for(j=0; j < FLASH_WRITE_LEN_BYTE; j++)
      {
         if(*(w_data+j)!=FLASH_WRITE_CONTENT)
         {
            os_printf("Err Flash read w_data[%d]=0x%x\n",j,w_data[j]);
            //status=1;
         }
         if(*(w_data+j)==FLASH_WRITE_CONTENT&&j==FLASH_WRITE_LEN_BYTE-1)
         {
            os_printf("Sector0x%x Test Ok\n",sector+i);
         }
      }
   }
}

Чтобы проверить, поддерживает ли чип flash режим QIO:

1. QE (Quad Enable) соответствует биту BIT(9) в регистре состояния памяти flash (flash status register).

2. Формат регистра состояния записи (write status register) следующий: 01H + StatusReg1 + StatusReg2.

3. Должны поддерживаться специфические команды:

• Flash должна поддерживать команду EBh, чтобы работал режим QIO.
• Flash должна поддерживать команду 6Bh, чтобы работал режим QOUT.

Чтобы проверить, поддерживает ли чип flash режим DIO, нужно проверить, что поддерживаются команды:

• Flash должна поддерживать команду BBh, чтобы работал режим DIO.
• Flash должна поддерживать команду 3Bh, чтобы работал режим DOUT.

Имейте в виду, что ISSI flash может поддерживать режим QIO.

Примечание: здесь под "прозрачным" понимается режим transparent transmission mode, когда все данные, проходящие через UART в обоих направлениях, передаются без изменений, как есть, по радиоканалу Wi-Fi (см. описание входа в "прозрачный" режим в статье [7]).

Причина пропадания данных в том, что не разрешено аппаратное управление потоком (hardware flow control). Режим прозрачной передачи использует протокол TCP, размер данных каждого пакета у которого обычно 1460 байт (что зависит от стека протоколов). Пока состояние сети хорошее, и буфер не занят, данные передаются постоянно, без задержек. Когда в прозрачном режиме интервал времени приема последовательных данных превышает 20 мс, то считается, что передача завершена, и принятые данные передаются по сети. В результате не согласованности пакетов, если сетевое соединение не очень качественное, некоторые данные могут потеряться. Чтобы этого не происходило, разрешите функцию flow control.

Таких портов два, UART0 и UART1. Порт UART0 полноценный, у него есть в наличии вывод Tx для передачи и Rx для приема. Однако у порта UART1 есть только вывод передачи Tx, который можно использовать для вывода в лог отладки (его вывод Rx занят подключением к памяти SPI-Flash).

Кроме ножки XPD_DCDC, другие выводы GPIO могут быть сконфигурированы для лог. 1.  

Состояние уровня по умолчанию для выводов GPIO после загрузки: кроме 6 SDIO + GPIO4 + GPIO5 + GPIO16, все другие ножки GPIO имеют встроенные внутренние верхние подтягивающие резисторы (pull-up), которые переводят висящий уровень входа в состояние лог. 1. Чтобы подтянуть висящий вывод GPIO к лог. 0, требуется внешний резистор pull-down или схема инвертора.

Примечание: внешний уровень напряжения для ножки GPIO не может быть +5V. Ножки GPIO4, GPIO5 не могут быть подтянуты к лог. 1 внешним резистором 1 МОм, вместо этого используйте резистор 100 кОм.

espressif FAQ fig06

По умолчания ножка U0TXD (выход порта UART0) будет печатать сообщения кода ROM при старте ESP8266, что можно запретить для чувствительных приложений путем функции UART pin exchange. Пользователи могут вызвать функцию system_uart_swap для обмена выводов U0TXD и U0RXD на U0RTS (MTDO/ GPIO15) и U0CTS (MTCK/GPIO13). После этого изменения выводы U0TXD+U0RXD все еще можно аппаратно использовать для загрузки. Подключите MTDO к MCU RXD и MTCK к MCU TXD для осуществления обмена данными (под MCU понимается внешний микроконтроллер, например AVR).

[Протокол]

TCP: 1460 байт
UDP: 1472 байт

[Система]

Для повышения надежности системы в условиях высоких помех, в микросхему ESP8266 интегрирован двухуровневый сторожевой механизм (watchdog) включающий программный watchdog и аппаратный watchdog. По умолчанию оба этих сторожевых таймера разрешены.

Интервал прерывания hardware watchdog составляет 0.8*2048 мс (1638.4 мс). Интервал обработки прерывания составляет 0.8*8192 мс (6553.6 мс). Интервал обработки прерывания это предел времени, когда нужно сбросить watchdog после того, как произошло прерывание. Если истек интервал обработки прерывания, и аппаратный сторожевой таймер не был сброшен, то срабатывает аппаратный сброс (hardware watchdog reset). Таким образом, если программа не выполнила сброс сторожевого таймера в течение 6553.6 мс, то может привести к аппаратному сбросу системы. Если же программа в течение 8192 не выполнила сброс аппаратного сторожевого таймера, то это гарантированно приведет к watchdog reset.

Программный сторожевой таймер (software watchdog) основан на таймере MAC и управлении задачами (task arrangement). Интервал прерывания составляет 1600 мс, и он равен интервалу обработки прерывания. В результате, когда работают оба сторожевых таймера, и программа работала в течение 1600 мс, то это может привести к программному сбросу (software watchdog). Если же программа работала свыше 3200 мс, то это приведет к гарантированному сбросу от сторожевого таймера.

Текущая версия SDK позволяет запретить только software watchdog. Могут быть предприняты следующие способы избежать watchdog reset, когда программа пользователя занимает CPU слишком долго:

1. Если Ваша подпрограмма нуждается в окне времени между software watchdog reset и hardware watchdog reset, то Вы можете использовать функцию system_soft_wdt_stop(), чтобы запретить software watchdog. После выполнения Вашего кода можно перезапустить software watchdog с помощью функции system_soft_wdt_restart().

2. Вы можете сбрасывать watchdog в циклах своего кода с помощью функции system_soft_wdt_feed(), чтобы watchdog обновлялся до того, как сгенерирует сброс.

Таймер watchdog не позволяет выполнить пустые бесконечные циклы. Как упоминалось выше, переполнение watchdog приведет к сбросу, если программа пользователя слишком долго зависнет на опросе какого-то события, или будет использовать циклы для формирования задержек. Разработчики рекомендуют для формирования задержек использовать callback-функции (так называемые функции обратного вызова) и API таймера.   

Для опроса события, если это возможно, всегда используйте прерывания или функции API таймера, чтобы осуществлять частые проверки. Большинство событий можно привязать к callback-функциям из SDK, и таким образом опроса почти всегда можно избежать.

Для пользователей Non-OS SDK выявление мест утечки памяти можно произвести путем определения MEMLEAK_DEBUG, чтобы разрешить соответствующую функцию отладки.

Вызовите os_malloc, os_zalloc, os_calloc, os_realloc, os_free вместо обычных функций для работы с кучей. Эти отладочные функции выделения/освобождения памяти записывают дополнительную информацию, которую можно распечатать вызовом API-функции system_print_meminfo(). В лог будет выведена информация по использованию кучи.

Для отладки утечки памяти выполните следующие шаги:

1. Измените основной makefile в проекте, и определите в нем DMEMLEAK_DEBUG после CONFIGURATION_DEFINES

Например:

CONFIGURATION_DEFINES = -DMEMLEAK_DEBUG

2. В коде пользователя, таком как user_main.c, добавьте подключение заголовка mem.h и функцию:

#include “mem.h"
 
bool ICACHE_FLASH_ATTR check_memleak_debug_enable ()
{
   return MEMLEAK_DEBUG_ENABLE;
}

3. Вызовите system_print_meminfo() API, где возможно происходит утечка памяти. Разработчики рекомендуют использовать эту API-функцию только в ключевых местах программы.

Замечание: RTOS SDK не поддерживает тот же метод выявления утечек памяти при работе с кучей, как и в приложении Non-OS SDK. Про техники поиска и отслеживания утечек памяти см. документацию по FreeRTOS.

Fatal exceptions (неисправимая ошибка, фатальное исключение) может быть отслежено, если у Вас есть файл ассемблера (*.S), который использовался для генерации двоичного кода. Например, Вы обнаружили исключение при работе user1.bin:

Fatal exception (28):
epc1=0x4025bfa6, epc2=0x00000000, epc3=0x00000000, 
excvaddr=0x0000000f, depc=0x00000000

В этом случае Вы должны проинспектировать адрес 0x4025bfa6 в файле user1.S, чтобы найти причину исключения. 

Когда работают flash.bin и irom0text.bin, причину исключения можно найти в файле eagle.S.

ESP8266 реализует аппаратный и программный таймер. К таймеру можно получить доступ через os_timer API, и это программный таймер, который не генерирует "прерывание", генерируя вместо этого задачу (task), которая может использоваться для блокировки обычной задачи на очереди. Однако аппаратный таймер генерирует прерывание, которое может использоваться для срабатывания запуска определенной задачи. Имейте в виду, что прерывания не предназначены для выполнения высоконагруженных (потребляющих много тактов процессора) задач.

За подробностями обратитесь к документации "ESP8266 Non-OS SDK API Reference" или "ESP8266 RTOS SDK API Reference" (см. [2]), в зависимости от SDK, который используете. Однако в качестве главного правила следует иметь в виду, что функции, декларированные с ICACHE_FLASH_ATTR, не должны вызываться их обработчика аппаратного прерывания, когда используется Non-OS SDK. Также не занимайте слишком много время CPU внутри обработчика прерывания.

Для установки максимальной мощности передачи тракта RF можно использовать API-функцию system_phy_set_max_tpw. Разработчики рекомендуют использовать утилиту flash download tool для изменения настроек в соответствии с Вашими требованиями. Кликните в ней на кнопку GenInitBin для генерации файла esp_init_data_default.bin и последующей его прошивки в SPI Flash.

• LowPowerEn: установите мощности передатчика (Tx Power) для каждого режима.
• BackOffEn: выберите снижение того же значения Tx Power для каждого режима.
• PowerLimiten: установите предел на максимальное значение Tx Power.
• Кликните GenInitBin для генерации файла esp_init_data_default.bin, и замените им файл по умолчанию.

espressif FAQ fig07

Для приложений ESP8266_Non-OS SDK: функции, которые получили атрибут ICACHE_FLASH_ATTR, размещаются в секции IROM. Они будут работать из кэша, когда вызываются CPU. С другой стороны, функции без атрибута ICACHE_FLASH_ATTR загружаются в IRAM при включении питания. Из-за того, что размер IRAM ограничен, мы не можем загрузить все коды в IRAM одновременно. Поэтому большинство функций снабжены атрибутом ICACHE_FLASH_ATTR, и загружаются в IROM.

Примечание: не используйте ICACHE_FLASH_ATTR-функции в обработчике прерывания, поскольку это может вызвать конфликт с операциями чтения/записи Flash.  

Для приложений ESP8266_RTOS SDK: функции размещены в секции IROM по умолчанию, и не нуждаются для этого в снабжении атрибутом ICACHE_FLASH_ATTR. Обработчики прерывания также работают из IROM. Поэтому если функции вызываются часто, то они должны работать из IRAM, для этого они должны декларироваться с атрибутом IRAM_ATTR.

В приложении Non-OS SDK по умолчанию функции присваивается атрибут IRAM_ATTR. Таким образом, если Вы хотите, чтобы функция была размещена в IRAM, то просто не указывайте атрибут ICACHE_FLASH_ATTR в определении/декларации функции.

Это означает, что размер кода слишком велик, чтобы поместиться в IROM. Ниже приведено несколько советов для решения этой проблемы:   

Для SDK_v0.9.5 или более новых версий:

1. Скомпилируйте конфигурацию по умолчанию, чтобы сгенерировать eagle.flash.bin и eagle.irom0text.bin.

(a) Если общий размер eagle.flash.bin и eagle.irom0text.bin превышает 236 килобайт, то нужен чип микросхемы Flash, у которой размер больше 512 килобайт.
(b) Если общий размер eagle.flash.bin и eagle.irom0text.bin меньше 236 килобайт, то продолжайте с шага 2.

2. Сделайте ревизию eagle.app.v6.new.512.app1.ld в SDK/ld следующим образом: в строке

rom0_0_seg: org = 0x40201010, len = 0x2B000

поменяйте значение len в соответствии с Вашим eagle.irom0text.bin. Например, если размер eagle.irom0text.bin равен 179 килобайт, поменяйте конфигурацию следующим образом:

irom0_0_seg: org = 0x40201010, len = 0x2D000

3. Скомпилируйте и сгенерируйте user1.bin путем выбора boot_v.1.2+.

P.S.: в исходном коде определяйте функции IRAM без атрибута ICACHE_FLASH_ATTR, которые могут занимать самое большее 32 килобайта; снабжайте функции IROM атрибутом ICACHE_FLASH_ATTR, и они будут размещены в irom0_0_seg.

Из-за ограниченного размера RAM функции в IRAM будут загружены в ОЗУ и будут доступны для запуска при включении питания; функции из IROM будут загружаться в кэш из памяти Flash, и будут запускаться оттуда только при их вызове.

Нет. Точка входа кода пользователя находится в функции user_init.

Чтение и запись при доступе к RAM должны быть выровнены по границе в 4 байта (на слово, т. е. байтовый адрес доступа должен нацело делиться на 4), это должно учитываться при доступе к памяти с помощью указателя. Иначе произойдет отказ разыменования указателя и сбой. Например, используйте os_memcpy(или memcpy) для копирования данных по указателю вместо float temp = *((float*)data).

Основные отличия следующие:

[Non-OS SDK]

Non-OS SDK использует таймеры и callback-функции как основной способ выполнения различных функций - вложенных событий (nested events) и функций, которые запускаются при определенных событиях. Non-OS SDK использует сетевой интерфейс espconn; пользователям нужно разрабатывать свое ПО с учетом правил интерфейса espconn. Для получения информации обращайтесь к руководствам SDK [2].

[RTOS SDK]

1. RTOS SDK основан на FreeRTOS, это многозадачная операционная система реального времени (ОСРВ). Вы можете использовать стандартные интерфейсы FreeRTOS [8] для управления ресурсами, операций recycling, задержки выполнения, обмена сообщениями между задачами (inter-task messaging) и синхронизации между ними, и другие основанные на задачах (в терминах FreeRTOS элементарная единица выполнения называется Task, т. е. задача) обработки алгоритмов Вашего приложения. Про применение методов интерфейса FreeRTOS см. документацию на официальном сайте FreeRTOS, или очень хорошую книжку "USING THE FreeRTOS REAL TIME KERNEL - A Practical Guide" (её перевод на русский язык см. в [8]).

2. Работа сети в RTOS SDK основана на ставшем уже стандартным API стека lwIP. RTOS SDK предоставляет пакет, где реализован интерфейс BSD Socket API. Пользователи могут напрямую использовать API сокетов для разработки программ приложений, и портировать различные приложения с других платформ, используя API сокетов для ESP8266. Это значительно снижает затраты времени на обучение и разработку, возникающие при переключении на другую платформу.

3. RTOS SDK предоставляет библиотеку cJSON функции которой упрощают парсинг пакетов JSON.

4. RTOS при использовании Wi-Fi совместима с интерфейсами Non-OS SDK, SmartConfig, с интерфейсами для Sniffer, системными интерфейсами, интерфейсом таймера, интерфейсами FOTA и интерфейсами драйверов периферийных устройств, однако не поддерживает реализацию AT-команд.

1. Вызовы wifi_set_ip_info и wifi_set_macaddr допустимо вызывать только из user_init.

2. Рекомендуется вызывать system_timer_reinit из user_init, иначе все таймеры должны быть взведены.

3. Если wifi_station_set_config вызвана из user_init, нижний слой будет автоматически соединяться с соответствующим роутером без вызова wifi_station_connect.

4. Вызов wifi_station_set_auto_connect используется для конфигурирования устройства, чтобы оно всякий раз при старте автоматически подключалось к сохраненному роутеру. Например, если был вызван интерфейс из user_init с запретом автоматического подключения к роутеру, то устройство в это время не будет автоматически подключаться к роутеру. Если интерфейс будет вызван в другом месте, то устройство не будет в следующий раз автоматически подключаться к роутеру.

В режиме легкого сна (Light-sleep mode) работа CPU приостанавливается, и он не отвечает на сигналы или прерывания, поступающие от периферийных устройств. Таким образом, сигналы GPIO должны быть настроены специальным образом, чтобы разбудить устройство. Процесс выхода из сна требует менее 3 мс.

wifi_station_disconnect();
// Установка нулевого режима WiFi (null mode):
wifi_set_opmode(NULL_MODE);
wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
wifi_fpm_open();
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13);
// Рекомендуется срабатывание выхода из сна по перепаду в лог. 0!
gpio_pin_wakeup_enable(13, GPIO_PIN_INTR_LOLEVEL);
wifi_fpm_set_wakeup_cb(ssc_fpm_wakup_call);
wifi_fpm_do_sleep(FPM_SLEEP_MAX_TIME);

espressif FAQ fig08

Опорной для FRC1 является частота 80 МГц. Коэффициент деления (DIV) может быть сконфигурирован в 1, 16 и 256. Различные коэффициенты деления будут влиять на длительность каждого тика.  

FRC1 считает вниз, при этом значение COUNT_VALUE с каждым тиком уменьшается на 1.  

FRC1 можно сконфигурировать в режимах auto-feed-mode или non-auto-feed-mode. Auto-feed-mode: когда сработало прерывание, регистр COUNT_VALUE автоматически получит значение из FRC1_LOAD_VALUE, и начнет операцию декрементирования. Non-auto-feed-mode: когда сработает прерывание, регистр COUNT_VALUE будет установлен в максимальное значение 0x7fffff, и операция декремента продолжится.  

Могут быть сконфигурированы прерывания FRC от источников FRC1 и NMI interrupt source. Прерывание NMI не может быть маскировано (запрещено) кодом CPU. Прерывание NMI имеет уровень прерывания LEVEL3 в системе прерываний ESP8266, в то время как другие прерывания имеют уровень LEVEL1. Прерывание NMI по приоритету преобладает на любыми другими прерываниями.

Замечание по поводу SDK HW_TIMER: коэффициент деления SDK равен 16, поэтому длительность каждого тика составляет 0.2 мкс. Параметр hw_timer_arm может быть сконфигурирован до микросекунд, с максимальным значением 1677000 мкс.

[1. Сохраняйте строки в памяти Flash]

(1) Разместите некоторые строки во flash, особенно длинные, такие как запросы HTML и шаблоны ответов. Например, строка изначально была определена так:

#define test_string "hello world"

Вы можете определить эту строку следующим способом, и тогда она будет размещена во flash:

static const char test_string[] ICACHE_RODATA_ATTR = "hello world";

(2) Когда определяете строковые константы с ICACHE_RODATA_ATTR, пользователи должны получать доступ к её содержимому операциями чтения, выровненными по размеру слова (байтовый адрес доступа должен нацело делиться на 4). Так как данные во flash должны быть прочитаны порциями по 4 байта, пользователи должны определить макрос для получения выровненной длины строки:

#define GET_ALIGN_STRING_LEN(str) ((strlen(str) + 3) & ~3)

Когда используются строки, выделите динамически новый объект массива, чтобы прочитать туда данные строки из flash. Затем используйте os_memcpy API для копирования содержимого строки:

unsigned int str_len = GET_ALIGN_STRING_LEN(test_string);
char *tmp_string = (char *)os_malloc(str_len);
os_memcpy(tmp_string, test_string, str_len);

(3) В коде приложения используйте test_string. Это также решит проблему исключений, вызванных приложениями при не выровненном доступе с содержимому памяти flash, одновременно снижая объем RAM, занимаемый Вашим приложением.

(4) Когда код пользователя использует метод получения данных, описанный выше, то нужно освобождать память с помощью вызова:

os_free(tmp_string);

Имейте в виду, что если этого не делать, то постоянные выделения памяти уменьшат её количество в куче, и для функционала ядра может не хватить памяти, что приведет к неправильной работе и отказу вызовов API.

[2. Сохраняйте данные констант во flash]

(1) Напрямую размещайте массивы unit32 в памяти flash. Пример:

const uint32 array[4] ICACHE_RODATA_ATTR =
{
   0x11111111, 0x22222222, 0x33333333, 0x44444444
};

Пользователи могут напрямую использовать ячейки этого массива без каких-либо проблем (array[0], и т. п.).

(2) Однако доступы на чтение к массивам unit8 и unit16 должны быть выровнены по границе 4 байта. Пример:

const uint8 array[7] ICACHE_RODATA_ATTR = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};

Если Вам нужно прочитать элементы в массиве char по байтам, попробуйте программно читать в память RAM элементы порциями по 4 байта, и затем читайте каждый байт по его смещению 0..3.. Прямой доступ к отдельным элементам байтового массива этого примера (array[1], и т. п.) приведет к отказу приложения.

(3) Для структур памяти общим принципом доступа к ним является выделение достаточного количества памяти в RAM, которое больше размера памяти структуры, которую Вы хотите прочитать. Читайте данные из порциями, размер которых делится на 4 байта, и сохраняйте их в RAM. Используйте указатель на объект в коде как обычно, что показано в предыдущем примере. Просто измените код для чтения структуры вместо чтения массива.   

[3. Сохраняйте строки отладки в памяти flash]

Строки, выводимые на печать встроенной функцией printf, по умолчанию находятся в RAM. Если Вам не нужно часто печатать в лог строки отладки, или если эти строки слишком длинные, то используйте оптимизированное os_printf API для загрузки строк отладки во flash вместо RAM.   

[4. Старайтесь избегать глобальных переменных]

Глобальные переменные часто занимают излишнее место, поскольку используются они скорее всего не во все время жизни приложения. Espressif предоставляет API для динамического выделения памяти, что можно применять для снижения использования глобальных переменных. Для программирования на основе событий всегда используйте os_malloc и os_free для динамического выделения места в памяти, когда это необходимо. Однако разработчики не рекомендуют использовать частое выделение/освобождение памяти порциями разного размера.

Когда ESP8266 подключается к AP, она сохраняет информацию о канале AP в памяти RTC.   

• Когда Вы сбрасываете ESP8266 программно, или когда ESP8266 выходит из режима глубокого сна (Deep-sleep mode), то она читает информацию о канале AP из памяти RTC, после чего пытается подключиться к AP на этом канале.
• Но если ESP8266 проходит цикл выключение - включение питания, или цикл аппаратного сброса (hardware reset), то память RTC будет очищена, и соответственно информация о радиоканале потеряна. Тогда ESP8266 при подключении будет сканировать все каналы, что занимает некоторое время.   

Вы можете попробовать следующее решение для сохранения и восстановления информации о канале AP, когда включается питание или происходит аппаратный сброс ESP8266. Для этого Вы можете избежать ситуации, где ESP8266 сканирует все доступные каналы для поиска AP, к которой было подключение в последний раз. Это поможет ускорить подключение при старте.

1. После того, как ESP8266 подключилась к AP, используйте функцию wifi_get_channel для того, чтобы прочитать информацию от текущем канале AP, затем Вы можете сохранить эту информацию в SPI Flash. Перед записью информации о канале нужно проверить, что информация о канале допустимая.

2. Когда ESP8266 получает аппаратный сброс или проходит цикл включения питания, пользовательское firmware может прочитать сохраненную информацию канала из flash. Путем вызова WRITE_PERI_REG(0x600011f4, 1 << 16 | channel), информация о канале AP может быть записана в память RTC. Информация о канале может быть получена напрямую из памяти RTC, чтобы помочь снизить время подключения.

3. Имейте в виду, что должна быть разрешена функция автоматического подключения (auto connection), чтобы ESP8266 прочитала информацию о канале AP и подключилась к AP на этом канале.

В памяти RTC кэшируется только информация о канале. Другая информация для подключения (такая как SSID и Password) сохраняется во Flash, когда Вы вызываете функцию wifi_station_set_config.

Примечание: если Ваше приложение требует очень частых сбросов или часто проходит циклы выключения/включения питания, то рекомендуется использовать внешнюю память RTC для сохранения информации о канале. Очень частые записи в память flash не рекомендуются, потому что количество циклов записи для памяти flash ограничено.

Убедитесь, что когда загружается ESP8266, то выводы управления режимом загрузки (strapping pins) удерживаются на требуемых логических уровнях. Если подключенные снаружи периферийные устройства переводят strapping-выводы в нежелательные уровни логики, то ESP8266 может загрузиться в неправильном режиме работы. Тогда при отсутствии правильно работающей программы таймер watchdog может сбросить чип.

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

При включении питания или сбросе ESP8266 оценивает состояние специальных выводов, которые задают режим загрузки (boot mode). Это так называемые выводы boot strapping pins. Они определяют, как будет загружаться ESP8266. Вот пример информации boot mode, которая печатается при включении питания:

ets Jan 8 2013,rst cause:1, boot mode:(3,2)

Первая цифра 3 в скобках после "boot mode:" обозначает текущий режим загрузки ESP8266. Как показывает таблица ниже, режим загрузки определяется 3-битным значением логических уровней на выводах strapping pins [GPIO15, GPIO0, GPIO2].

Уровни GPIO15, GPIO0, GPIO2 Boot Mode
7 (111) SDIO HighSpeed V2 IO
6 (110) SDIO LowSpeed V1 IO
5 (101) SDIO HighSpeed V1 IO
4 (100) SDIO LowSpeed V2 IO
3 (011) Flash Boot
2 (010) Jump Boot
1 (001) UART Boot
0 (000) Remapping

[Инструментарий]

[Фаза разработки]

Память Flash может быть запрограммирована путем подключения ESP8266 к компьютеру через UART. Это делается через преобразователь USB - TTL UART (которые в обилии продаются на сайтах aliexpress и dx.com). Для получения инструкций, как использовать официальный инструментарий перепрошивки (Espressif official Flash download tool), обращайтесь к документу "ESP8266 SDK Getting Started Guide" [2].   

Download tool: http://espressif.com/zh-hans/support/download/other-tools
Download method: http://espressif.com/zh-hans/support/download/documents   

[Фаза массового производства]

Не очень удобно программировать ESP8266 через UART при больших объемах выпуска устройств, может быть удобнее использовать прямое программирование чипов Flash с помощью специальных программаторов.

Чтобы сгенерировать двоичный файл, который может быть записан в память SPI Flash перед сборкой платы, используйте Espressif Flash download tool для генерации комбинированного файла для Flash. Убедитесь, что Вы корректно сконфигурировали размер Flash перед генерацией комбинированного двоичного образа микросхемы памяти SPI Flash.

[Wi-Fi]

IP-адрес по умолчанию ESP8266 SoftAP равен 192.168.4.1.

ESP8266 не может обработать ситуацию, когда IP-адрес SoftAP и Station принадлежат одной подсети, в нашем случае это подсеть 192.168.4.x. Чтобы подключение сработало, нужно поменять подсеть у роутера, к которому происходит подключение (когда ESP8266 работает как клиент), или нужно поменять подсеть у ESP8266, когда она выступает в качестве AP.

Если предположить, что Вы правильно ввели SSID, то возможны 2 причины проблемы.

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

2. Вторая и более вероятная причина - параметр bssid_set. Установите stationConf.bssid_set = 0, если хотите подключиться к роутеру, у которого не нужно указывать MAC-адрес.

ESP8266 поддерживает совместное существование режимов SoftAP + Station, однако у ESP8266 есть только один аппаратный канал, который используется совместно интерфейсом Station и интерфейсом SoftAP. В результате ESP8266 SoftAP будет динамически подстраивать значение канала в соответствии с ESP8266 Station, что может привести к следующим вариантам поведения.

[Вариант 1]

1. ESP8266 Station подключена к роутеру (предположим, что номер канала 6).

2. Режим ESP8266 SoftAP активирован с использованием wifi_softap_set_config.

3. API вернет true, если конфигурация корректна, однако номер канала автоматически подстроится к тому же значению, что и у интерфейса ESP8266 Station (в нашем случае 6).

[Вариант 2]

1. Был вызов wifi_softap_set_config, и ESP8266 сконфигурирован в режиме SoftAP (предположим, что номер канала 5).

2. К ESP8266 SoftAP подключились другие станции.

3. ESP8266 Station подключилась к роутеру (предположим, что канал роутера 6).

4. ESP8266 SoftAP автоматически подстроит номер канала к тому же значению, что и у ESP8266 Station (в нашем случае 6);

5. Поскольку канал RF поменялся, то станция, которая была подключена к ESP8266 SoftAP, потеряет коннект Wi-Fi.

[Вариант 3]

1. К ESP8266 SoftAP подключились другие станции.

2. Если ESP8266 Station попытается выполнить сканирование или подключение к роутеру, то ESP8266 SoftAP может потерять связь, и могут наблюдаться потери пакетов UDP или ping.

Это происходит потому, что ESP8266 Station будет осуществлять сканирование по всем каналам в поиске целевого роутера. Поэтому ESP8266 SoftAP также поменяет канал, что приведет к проблемам в существующих соединениях.

В такой ситуации пользователи могут установить таймер и вызвать wifi_station_disconnect по истечению задержки таймера, чтобы остановить попытки ESP8266 Station подключиться к роутеру. Другой метод - вызывать wifi_station_set_reconnect_policy и wifi_station_set_auto_connect в начале конфигурации, чтобы запретить ESP8266 Station переподключаться к роутеру.

Здесь канал относится к определенной частоте в допустимом диапазоне частот, выделенном для систем Wi-Fi. Технически Вы можете использовать любой канал по своему выбору. Однако в Вашей стране некоторые каналы могут быть нелегальны!

Проконсультируйтесь с документом "ESP8266 Wi-Fi Channel Selection Guidelines" [2] для получения информации о выборе лучшего канала для своего приложения.

Методы для подключения устройства ESP8266 к беспроводному роутеру по Wi-Fi:

1. Разрешите ESP8266 Smartconfig. Устройство ESP8266 может сканировать атрибут пакетов в режиме сниффера, и подключится к роутеру.

2. Разрешите режим SoftAP для устройства ESP8266, чтобы к нему мог подключиться смартфон, и установилось стабильное соединение TCP/UDP. После этого смартфон может передать SSID (это идентификатор точки доступа ESP8266) и password (пароль для получения доступа).

3. Разрешите конфигурацию WPS, которая требует добавление кнопок к устройству ESP8266, или используйте мобильное приложение для управления WPS после подключения устройства к SoftAP.

Изменения конфигурации для ESP8266 SoftAP путем вызова wifi_softap_set_config() могут быть иногда неудачными в контексте ввода их в действие, если вызов API был произведен из callback-функции. Подобные ситуации могут возникать например, когда приложение пытается переключиться в режим Station из режима SoftAP внутри callback-функции, привязанной к событиям SoftAP.

Чтобы гарантировать, чтобы изменение, сделанное wifi_softap_set_config(), немедленно вступило в действие, используйте API-функцию system_os_task() для создания задачи, которая поменяет настройки SoftAP. Также убедитесь, что ESP8266 успешно переключилась в режим SoftAP перед любым вызовом API-функций SoftAP. Пример:

LOCAL void ICACHE_FLASH_ATTR some_callback_function (void)
{
   unsigned char res;
   os_event_t *testQueue;
 
   // Убедитесь, что ESP8266 в режиме SoftAP!
   res = wifi_set_opmode_current (0x02);
   os_printf ("\r\nSet op mode returned: %d", res);
 
   testQueue = (os_event_t *)os_malloc(sizeof(os_event_t)*4);
   system_os_task (set_ap_config, USER_TASK_PRIO_1, testQueue, 4);
   
   // Продолжение настройки сервера, и т. п.
   ap_server_setup (AP_PORT);
}
 
void set_ap_config (os_event_t *e)
{  
   struct softap_config ap;
 
   // Сначала получение конфигурации.
   wifi_softap_get_config(&ap);
 
   os_memset(ap.ssid, 0, 32);
   os_memset(ap.password, 0, 64);
 
   os_memcpy(ap.ssid, "SSIDhere", 8);
   os_memcpy(ap.password, "PASSWDhere", 10);
 
   ap.authmode = AUTH_WPA2_PSK;
   ap.ssid_len = 0;              // Или это действительная длина
   ap.max_connection = 1;        // MAX возможное количество станций
   wifi_softap_set_config (&ap); // Обновление конфигурации ESP8266 SoftAP!
}

[Словарик]

AP access Point, имеется в виду точка доступа Wi-Fi.

APP сокращение от application (приложение).

FOTA Firmware Over The Air. Облачная технология Espressif Systems, предназначенная для обновления прошивки через Wi-Fi.

LDO Low Drop-Out. Имеется в виду линейный регулятор с низким проходным падением напряжения.

OTA over the air. Означает передача чего-нибудь, например обновление прошивки (firmware) "по воздуху", т. е. по радиоканалу Wi-Fi.

RTC Real Time Clock, часы реального времени.

SmartConfig протокол ESP-TOUCH компании Espressif реализует технологию Smart Config, которая помогает пользователям подключить устройства на основе ESP8266EX к сети Wi-Fi через простое ПО конфигурирования, установленное на смартфоне. Подробности см. в документе [4].

SoftAP режим чипа ESP8266, когда он работает как точка доступа Wi-Fi (AP).

Station режим чипа ESP8266, когда он работает как клиент точки доступа Wi-Fi (подключается к ней).

WeChat популярное приложение для общения, может использоваться для конфигурирования ESP8266.

WPS Wi-Fi Protected Setup. Из "Википедии": Wi-Fi Protected Setup (защищённая установка), WPS - стандарт (и одноимённый протокол) полуавтоматического создания беспроводной сети Wi-Fi, созданный Wi-Fi Alliance. Официально запущен 8 января 2007 года. Целью протокола WPS является упрощение процесса настройки беспроводной сети, поэтому изначально он назывался Wi-Fi Simple Config. Протокол призван оказать помощь пользователям, которые не обладают широкими знаниями о безопасности в беспроводных сетях, и как следствие, имеют сложности при осуществлении настроек. WPS автоматически обозначает имя сети и задает шифрование для защиты беспроводной Wi-Fi сети от несанкционированного доступа в сеть, при этом нет необходимости вручную задавать все параметры.

[Ссылки]

1. FAQ ESP8266 site:espressif.com.
2. Download Documents site:espressif.com.
3. Iot Espressif API DOCUMENTATION.
4. ESP-TOUCH User Guide site:espressif.com.
5. ESP8266 SDKs & Demos.
6. ESP8266 Technical Reference site:espressif.com.
7. ESP8266: пример тестирования команд AT.
8. FreeRTOS: практическое применение, часть 1 (управление задачами).

 

Добавить комментарий


Защитный код
Обновить

Top of Page