Espruino:Примеры/Расширение возможностей Espruino 1 – Создание собственного расширения прошивки

Материал из Онлайн справочника
Версия от 15:09, 28 мая 2023; Myagkij (обсуждение | вклад)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)
Перейти к навигацииПерейти к поиску

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Расширение возможностей Espruino 1 – Создание собственного расширения прошивки[1]

Это руководство служит кратким введением в написание ваших собственных расширений для Espruino, а также создание собственного двоичного кода.

Более подробно об этом можно почитать в этом руководстве по созданию собственного класса.

Внимание!

Всё, что здесь описано, работает, но тестировалось это руководство недостаточно много.

Внимание!

Поскольку я всё это затеял для того, чтобы написать пару специальных функций для ESP8266-порта Espruino, пример ниже был протестирован именно на нём. Но, к счастью, в нём много общей информации, так что, надеюсь, это поможет при использовании на других портах.

Для информации

Необходимые условия: Перед тем, как начать, у вас должно быть всё необходимое для разработки и компиляции собственной версии кода. Более подробно об этом читайте на GitHub.

Для информации

Необходимые условия: Полезно будет иметь некоторые знания в Linux, программировании на C, компоновке и т.д. и т.п. Если же вы возьмётесь за эту задачу с моим уровнем знаний, то у вас по ходу будет возникать очень много вопросов и вы периодически будете утыкаться в тупик.

Использование свободной flash-памяти для текста

Идея в том, чтобы взять неиспользуемую flash-память и сохранить в эту область текстовые данные. HTTP-сервер использует много HTML-команд, и их хранение в исходном JavaScript-коде требует много памяти. На маленьких чипах вроде ESP8266 это быстро становится проблемой.

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

readString(StartAddress of Flashpage, sequenceNumber inside this page)

В этом руководстве мы пройдём следующие шаги:

  • Создание файла обёртки
  • Шаблон для .h и .c
  • Добавление исходного кода функции на C
  • Внесение изменений в файл сборки
  • Запуск

Создание файла обёртки

Основа для всего нашего мероприятия – это Espruino. Соответственно, нам нужно будет использовать уже устоявшиеся правила и соглашения для этого языка. К ним относится, например, то, как называть файлы исходного кода. В нашем случае это будет «jswrap_FlashExtension». Наш код тестировался только для ESP8266, и он не является частью стандартного ESP8266-порта для Espruino, и поэтому путём для хранения файлов исходного кода будет «/Esrpuino/targets/esp8266/myLibs». Нам понадобится один заголовочный файл и один файл с исходным кодом: «jswrap_FlashExtension.h» и «jswrap_FlashExtension.c».

Шаблон для .h и .c

Давайте начнём с заголовочного файла. Часть с авторскими правами в этот раз можно пропустить. Лично я рекомендую подсмотреть, как устроены другие файлы, и делать что-то похожее. Помните, что Espruino – это язык с открытым кодом.

#include "jsvar.h"
#include "jswrap_flash.h"

JsVar *jswrap_flash_readString(int addr, int pointer);

Подключать jsvar.h никогда не лишне, это одна из важнейших частей Espruino. Если ваше устройство работает только на JavaScript, то с помощью jsvar.h в нём будет обрабатываться хранение всего – и переменных, и исходного кода. Заголовочный файл jswrap_flash.h отвечает за все функции, связанные с flash-памятью, и некоторые из них, скорее всего, будут для вас полезны. Наконец, третья строчка – это описание функции, более подробно об этом смотрите в следующем разделе.

Добавление исходного кода функции на C

#include "jswrap_FlashExtension.h"
#include "jshardware.h"

Первая строчка добавляется для всего, что пишется на C. Со второй строчкой интереснее – это заголовочный файл для всех функций, связанных с «железом». К ним относится и считывание данных с flash-памяти.

/*JSON{
  "type" : "staticmethod",
  "class" : "Flash",
  "name" : "readString",
  "generate" : "jswrap_flash_readString",
  "params" : [
    ["addr","int","An address in the page to store strings"],
    ["pointer","int","seqNr of string"]
  ],
  "return" : ["JsVar","A Uint8Array"]
}
 */

На первый взгляд, эта часть закомментирована и никакого толка от неё нет. Но на самом деле эти комментарии сканируются фоновым скриптом. Как видите, некоторые данные здесь представлены в JSON-формате. И они конвертируются в ещё один C-файл. В конце концов, этот сгенерированный файл будет связующим звеном между JavaScript-файлом и скомпилированной C-функцией. Простите, если сумбурно, уверен, есть немало людей, которые объяснят это лучше меня.

Начнём давайте с краткого описания пути – текст хранится в flash-памяти, и наше расширение, напоминаю, предназначено для его считывания. Начало каждой страницы flash-памяти – это набор указателей на сами данные. Начало и размер каждого текстового элемента хранятся в виде 16-битных значений. Сам текст начинается после части с указателями. Вариантов того, как сохранять данные, на самом деле много, но в нашем случае вполне хватит и этого.

JsVar *jswrap_flash_readString(int addr, int pointer){
  int startAddr, length, pnt,tmp;
  pnt = addr + pointer * 4;
  jshFlashRead(&tmp, (uint32_t)(pnt), 4);
  length = tmp >> 16;
  startAddr = tmp & 0xffff;
  return jswrap_flash_read(length,addr + startAddr);
}

Считывание данных из flash-памяти – это функция, связанная с «железом» (jshFlashRead), которая выполняется в границах 4 байт. Значение Int32 поделено на начало и размер. Наконец, нам остаётся лишь воспользоваться уже готовой функцией чтения из объекта Flash, чтобы прочесть текст. Формат возвращаемых данных – это Uint8Array, который можно без труда преобразовать в строку при помощи E.toString().

Внесение изменений в файл сборки

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

 ifdef USE_ESP8266
 DEFINES += -DUSE_ESP8266
 WRAPPERSOURCES += libs/network/esp8266/jswrap_esp8266_network.c \
   targets/esp8266/jswrap_esp8266.c
 INCLUDE += -I$(ROOT)/libs/network/esp8266
 SOURCES += \
 libs/network/esp8266/network_esp8266.c\
 libs/network/esp8266/pktbuf.c\
 libs/network/esp8266/ota.c
  ifdef USE_MYLIB
   WRAPPERSOURCES += $(wildcard targets/esp8266/myLibs/jswrap*.c)
   SOURCES += $(wildcard targets/esp8266/myLibs/lib*.c)
  endif
 endif

В файле сборки уже есть фрагмент, который добавляет во внутренний список файлы, специфичные для платы. Если в USE_MYLIB будет задано «1», шаблонная функция будет искать и добавлять дополнительные файлы. Строчки рядом с шаблонными функциями не являются частью стандартного файла сборки. Их нужно обязательно добавить перед следующим этапом.

Запуск

Итак, все изменения внесены, теперь пора запустить файл сборки. В моём случае запись прошивки выполнялась при помощи программатора NodeMCU под Windows. В целях упрощения этого процесса у моей виртуальной машины и Windows есть общая папка. Сам файл сборки создаёт TAR-файл со всеми двоичными файлами. Для обработки TAR-файлов есть специальные приложения, но гораздо проще сделать это в самой виртуальной машине.

ESP8266_BOARD=1 USE_MYLIB=1 make
tar -xzf espruino*.tgz -C /mnt/hgfs/C_tmp_VMWare
cd /mnt/hgfs/C_tmp_VMWare
rm -rvf espruino
mv espruino* espruino
cd

Разумеется, всё никогда не работает идеально и со всем этим могут возникнуть проблемы. Вы всегда можете оставить обратную связь об этом руководстве и возникших проблемах на форуме Espruino или на Gitter.

См.также

Внешние ссылки