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

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску
(Новая страница: «{{Espruino/Панель перехода}} {{Перевод от Сubewriter}} {{Myagkij-редактор}} =<ref>[ www.espruino.com - ]</ref>= <syntaxhighlig...»)
 
Нет описания правки
Строка 3: Строка 3:
{{Myagkij-редактор}}
{{Myagkij-редактор}}


=<ref>[ www.espruino.com - ]</ref>=
=Расширение возможностей Espruino 1 – Создание собственного расширения прошивки<ref>[https://www.espruino.com/Extending+Espruino+1  www.espruino.com - Extending Espruino 1 - Making own firmware extension]</ref>=


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


Более подробно об этом можно почитать в [http://wikihandbk.com/wiki/Espruino:Примеры/Расширение_возможностей_Espruino_2_–_Создание_новой_версии_класса_Graphics этом руководстве] по созданию собственного класса.
'''ВНИМАНИЕ:''' Всё, что здесь описано, работает, но тестировалось это руководство недостаточно много.
'''ВНИМАНИЕ:''' Поскольку я всё это затеял для того, чтобы написать пару специальных функций для [[ESP8266-порт]]а [[Espruino]], пример ниже был протестирован именно на нём. Но, к счастью, в нём много общей информации, так что, надеюсь, это поможет при использовании на других портах.
'''Необходимые условия:''' Перед тем, как начать, у вас должно быть всё необходимое для разработки и компиляции собственной версии кода. Более подробно об этом читайте на [https://github.com/espruino/Espruino/blob/master/README_Building.md GitHub].
'''Необходимые условия:''' Полезно будет иметь некоторые знания в [[Linux]], программировании на C, компоновке и т.д. и т.п. Если же вы возьмётесь за эту задачу с моим уровнем знаний, то у вас по ходу будет возникать очень много вопросов и вы периодически будете утыкаться в тупик.
==Использование свободной flash-памяти для текста==
Идея в том, чтобы взять неиспользуемую [[flash-память]] и сохранить в эту область текстовые данные. [[HTTP-сервер]] использует много [[HTML-команд]], и их хранение в исходном [[JavaScript-код]]е требует много памяти. На маленьких чипах вроде [[ESP8266]] это быстро становится проблемой.
Несколько команд для работы с [[flash-память]]ю уже есть, так что идея в том, чтобы добавить дополнительную команду вроде...


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript" enclose="div">
readString(StartAddress of Flashpage, sequenceNumber inside this page)
</syntaxhighlight>


В этом руководстве мы пройдём следующие шаги:
* Создание файла обёртки
* Шаблон для [[.h]] и [[.c]]
* Добавление исходного кода функции на C
* Внесение изменений в файл сборки
* Запуск
== Создание файла обёртки ==
Основа для всего нашего мероприятия – это [[Espruino]]. Соответственно, нам нужно будет использовать уже устоявшиеся правила и соглашения для этого языка. К ним относится, например, то, как называть файлы исходного кода. В нашем случае это будет ''«jswrap_FlashExtension»''. Наш код тестировался только для [[ESP8266]], и он не является частью стандартного [[ESP8266]]-порта для [[Espruino]], и поэтому путём для хранения файлов исходного кода будет ''«/Esrpuino/targets/esp8266/myLibs»''. Нам понадобится один заголовочный файл и один файл с исходным кодом: ''«jswrap_FlashExtension.h»'' и ''«jswrap_FlashExtension.c»''.
== Шаблон для .h и .c ==
Давайте начнём с заголовочного файла. Часть с авторскими правами в этот раз можно пропустить. Лично я рекомендую подсмотреть, как устроены другие файлы, и делать что-то похожее. Помните, что [[Espruino]] – это язык с открытым кодом.
<syntaxhighlight lang="c" enclose="div">
#include "jsvar.h"
#include "jswrap_flash.h"
JsVar *jswrap_flash_readString(int addr, int pointer);
</syntaxhighlight>
</syntaxhighlight>
Подключать [[jsvar.h]] никогда не лишне, это одна из важнейших частей [[Espruino]]. Если ваше устройство работает только на [[JavaScript]], то с помощью [[jsvar.h]] в нём будет обрабатываться хранение всего – и переменных, и исходного кода. Заголовочный файл [[jswrap_flash.h]] отвечает за все функции, связанные с [[flash-память]]ю, и некоторые из них, скорее всего, будут для вас полезны. Наконец, третья строчка – это описание функции, более подробно об этом смотрите в следующем разделе.
== Добавление исходного кода функции на C ==
<syntaxhighlight lang="c" enclose="div">
#include "jswrap_FlashExtension.h"
#include "jshardware.h"
</syntaxhighlight>
Первая строчка добавляется для всего, что пишется на C. Со второй строчкой интереснее – это заголовочный файл для всех функций, связанных с ''«железом»''. К ним относится и считывание данных с [[flash-памяти]].
<syntaxhighlight lang="javascript" enclose="div">
/*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"]
}
*/
</syntaxhighlight>
На первый взгляд, эта часть закомментирована и никакого толка от неё нет. Но на самом деле эти комментарии сканируются фоновым скриптом. Как видите, некоторые данные здесь представлены в [[JSON-формат]]е. И они конвертируются в ещё один C-файл. В конце концов, этот сгенерированный файл будет связующим звеном между [[JavaScript-файл]]ом и скомпилированной C-функцией. Простите, если сумбурно, уверен, есть немало людей, которые объяснят это лучше меня.
Начнём давайте с краткого описания пути – текст хранится в [[flash-памяти]], и наше расширение, напоминаю, предназначено для его считывания. Начало каждой страницы [[flash-памяти]] – это набор указателей на сами данные. Начало и размер каждого текстового элемента хранятся в виде 16-битных значений. Сам текст начинается после части с указателями. Вариантов того, как сохранять данные, на самом деле много, но в нашем случае вполне хватит и этого.
<syntaxhighlight lang="c" enclose="div">
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);
}
</syntaxhighlight>
Считывание данных из [[flash-памяти]] – это функция, связанная с «железом» (jshFlashRead), которая выполняется в границах 4 байт. Значение [[Int32]] поделено на начало и размер. Наконец, нам остаётся лишь воспользоваться уже готовой функцией чтения из объекта [[Flash]], чтобы прочесть текст. Формат возвращаемых данных – это [[Uint8Array]], который можно без труда преобразовать в строку при помощи E.toString().
== Внесение изменений в файл сборки ==
Теперь, когда исходный код готов, настало время для компиляции и компоновки. Файлу сборки необходимо знать о дополнительных файлах. И это ответ на вопрос о том, зачем нам нужна поддиректория '''myLibs''' – чтобы не вносить изменения для каждого нового расширения, мы будем искать файлы только в этой директории.
<syntaxhighlight lang="bash" enclose="div">
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
</syntaxhighlight>
В файле сборки уже есть фрагмент, который добавляет во внутренний список файлы, специфичные для платы. Если в '''USE_MYLIB''' будет задано ''«1»'', шаблонная функция будет искать и добавлять дополнительные файлы. Строчки рядом с шаблонными функциями не являются частью стандартного файла сборки. Их нужно обязательно добавить перед следующим этапом.
== Запуск ==
Итак, все изменения внесены, теперь пора запустить файл сборки. В моём случае запись прошивки выполнялась при помощи программатора [[NodeMCU]] под [[Windows]]. В целях упрощения этого процесса у моей виртуальной машины и [[Windows]] есть общая папка. Сам файл сборки создаёт TAR-файл со всеми двоичными файлами. Для обработки TAR-файлов есть специальные приложения, но гораздо проще сделать это в самой виртуальной машине.
<syntaxhighlight lang="bash" enclose="div">
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
</syntaxhighlight>
Разумеется, всё никогда не работает идеально и со всем этим могут возникнуть проблемы. Вы всегда можете оставить обратную связь об этом руководстве и возникших проблемах на [http://forum.espruino.com/ форуме Espruino] или на [https://gitter.im/espruino/Espruino Gitter].


=См.также=
=См.также=

Версия от 19:00, 18 июля 2021

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


Расширение возможностей 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.

См.также

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