вівторок, 18 листопада 2014 р.

Екзотичні мови (як для мікроконтролерів)

PyBoard

Недавно прилетіла з теплих країв ось така платка (точніше, зразу 3):


Це мікроконтролер з Пітоном на борту. Що? Python?!. Ага, Python 3.
Тільки не зовсім так. Це спеціальна реалізація Пітону (а не просто порт), розроблена спеціально для МК. Вона містить зменшену бібліотеку функцій, і ще бібліотеку для керування периферією. А також ф-ції для "керування процесом", щоб користувач не почував себе загнаним в кут Garbage Collector-ом й іншими причудами. А ще він вміє виконувати код по-різному (є 4 способи кодогенерації):
  • bytecode (interpretation)
  • native (arm)
  • viper (optimized)
  • inline assembler (а-ля do it yourself :)
Чудово! Що у нас на борту?
  • STM32F405RGT6
    • 1MB Flash, 200KB RAM
    • 168MHz ARM 32-bit Cortex™-M4 CPU + FPU
    • RTC, True RNG
    • 16 ADC, 2 DAC (12-bit)
    • 5х UART, 2х SPI, 2х I2C, I2S, CAN, USB2.0+OTG
    • 96-bit unique ID, etc
  • MMA7660FC (3-осьовий акселерометр)
  • 4 LED (1 з PWM)
  • 2 кнопки (Reset і USR)
  • 30 GPIO, 20 PWM, 13 таймерів, 16 зовнішніх переривань
  • MicroSD слот, Micro USB порт
  • Можна підключати купу додаткових штук (оу єа)..
  • Якість збірки і упаковки - Британська аристократія)))
Все так круто! Але ціна кусається. Втім, це все відносно :)

Python (MicroPython)

Про те, як їм вдалося засунути пітон в цю малютку:
http://micropython.org/static/resources/pyconuk14-mpinternals.pdf

Як білдити і що робити з цією платкою на Пітоні - ітак ясно, і добре описано на офіційному сайті, тому покажу тільки ази і рухаємось далі ;)
Ось тут відяшка (10хв) як це все виглядає і працює на Python:
https://www.youtube.com/watch?v=5LbgyDmRu9s

При підключенні по USB розпізнається як флешка на 100Кб і CDC консоль.
Це реально класно виглядає! Ти можеш записувати скрипти у файли і складати на флешку, а також заходити через Putty (чи аналог) на інтерактивну консоль. На цій же флешці драйвер для вінди. Якщо 100Кб мало, можна втикнути MicroSD карту.

Тобто по суті, інтерпретатор пітона відіграє роль операційної системи (!!!).

Ох, як же приємно бачити зручні пітоновські інтерфейси для різної периферії... А, іще отут!!! Уже просто аж кортить щось попробувати.

Відкриваю Putty.
Вибираю Serial і /dev/ttyACM0. Speed тут значення мабуть не має (це віртуальний serial по USB). Open. Тидинць!
 
Далі можна бавитись з туторіалом в інтерактивному режимі, там все дуже весело... Один з прикладів - керування мишкою комп'ютера, нахиляючи pyboard в різні сторони (пам'ятаєте, на ній є акселерометр?). І ще багато різного.

Я розцінюю цю платформу, як оптимальну для:
  • Прототипіювання
  • Тренінгів (навчання)
  • Демошок (в тому числі інтерактивних)
  • Як приклад того, що не треба боятись використовувати динамічні мови для бізнес-логіки, від недавна навіть у вбудованих системах :)

Але все не так просто, мені цікаво, як на ній поведуть себе інші екзотичні середовища. На нас (уже в цій публікації!) чекає JavaScript і Lua. А що далі - хто зна :)

 

Налаштування середовища

Для того, щоб все спрацювало, потрібно як мінімум:
  • Працювати в Linux (в мене Ubuntu 14.10)
  • Проконфігурувати компілятор
    • Скачати з https://launchpad.net/gcc-arm-embedded/+download
      (я взяв  gcc-arm-none-eabi-4_8-2014q3-20140805-linux.tar.bz2)
    • Розпакувати, наприклад в /opt/
    • Прописати його в PATH
      export PATH=$PATH:/opt/gcc-arm-none-eabi-4_8-2014q3/bin/
  • Поставити dfu-util
    sudo apt-get install dfu-util
Хочу наголосити, якщо захочете попробувати "run on the host side", то всі ці проекти (lua, espruino, та micropython) можуть бути скомпільовані і для роботи в звичайній ОС (Linux, деякі навіть Windows). Ну що, вам уже страшно? )))

P.S. MicroPython можна прошити/оновити так:
sudo dfu-util --alt 0 -D <dfu файл з оф.сайту>
Компілюється тривіально.

Почнемо з JavaScript (Espruino)

Збірка

Спочатку скачав:
git clone https://github.com/espruino/Espruino.git ./espruino

Звичайно ж, вони ще не підтримують pyboard. Зате підтримують свою Espruino і STM32F4 Discovery. Можна це скомбінувати :)
Для цього прийшлось проглянути 3 документи:
Шляхом нехитрих порівнянь (що до чого підключено) я написав новий файлик конфігурації boards/PYBOARD.py

Далі, в Makefile додав (у секцію конфігурації платформ):
else ifdef PYBOARD
EMBEDDED=1
USE_DFU=1
USE_NET=1
USE_FILESYSTEM=1
USE_GRAPHICS=1
DEFINES += -DUSE_USB_OTG_FS=1
BOARD=PYBOARD
STLIB=STM32F40_41xxx
PRECOMPILED_OBJS+=$(ROOT)/targetlibs/stm32f4/lib/startup_stm32f40_41xxx.o
OPTIMIZEFLAGS+=-O3


Ну от і все, поїхали:
PYBOARD=1 RELEASE=1 make

Побігли буквочки і циферки, і от (в якості нагороди) ми отримали espruino_1v72_pyboard.bin.
Можна заливати. На плату. Але як?? Виявляється просто.
В pyboard є так-званий "DFU mode". Щоб його активувати, потрібно поставити джампер між контактами DFU і 3V3, і натиснути кнопку Reset.

 
На pyboard в цьому режимі легенько так світяться 3 діоди.
Тоді можна просто запустити:

PYBOARD=1 RELEASE=1 flash

Воно якийсь час подумає, а тоді перестане думати...
Це буде мабуть означати, що програма вже на мікроконтролері ;)
Натискаєм Reset, підключаємся Putty на serial /dev/ttyACM0 і...
 _____                 _
|   __|___ ___ ___ _ _|_|___ ___
|   __|_ -| . |  _| | | |   | . |
|_____|___|  _|_| |___|_|_|_|___|
          |_| http://espruino.com
 1v72 Copyright 2014 G.Williams

>1234+9876
=11110

>

О_о. Здається все правильно. Сам здивувався! )))
Попробуємо щось складніше....

>function onInit() {
:    digitalWrite([LED1, LED2, LED3, LED4], 0);
:    pinMode(BTN1, "input_pullup");
:}
=function () { ... }

>
>onInit()
=undefined
>function blinkAll() {
:  leds = [LED1,LED2,LED3,LED4];
:              digitalWrite(leds,0b1000);
:  setTimeout("digitalWrite(leds,0b0100);", 100);
:  setTimeout("digitalWrite(leds,0b0010);", 200);
:  setTimeout("digitalWrite(leds,0b0001);", 300);
:  setTimeout("digitalWrite(leds,0b0000);", 400);
:}
=function () { ... }
>

>setInterval(blinkAll, 3000);
=1


Тут (раптом) починаємо спостерігати отаке:



Ура! Здається працює :)
Збережемо все, щоб працювало навіть після перезавантаження плати.

>save()
=undefined
Erasing Flash....
Programming 87200 Bytes.........................................................
Checking...
Done!
Running onInit()...


Далі можна просто йти на сайт Espruino і вивчати деталі :) З невеликими змінами вдасться запустити практично будь-який туторіал.

Взагальному:
  • Espruino складає враження менш пропрацьованої. Вона не організує свою програму у вигляді файлів, а також не дає користувачу прямого доступу до скриптів на борту.
  • Хочеться більше ф-цій для аналізу системи, виводу статистик, і таке інше.
  • Espruino інтерпретує сам текст програми. Мікропітон же може працювати в різних режимах, але навіть в найгіршому випадку він інтерпретує байткод, що мабуть дуже сильно покаже себе на тестах швидкодії.
  • Оці постійно "=undefined" появляються (і вони ще гордяться)))
    Я думаю в такому разі краще просто нічого не виводити, якщо результату нема.
  • Впринципі, більшість цих пунктів поправимі, але ж це треба сідати і кодити...
  • Виглядає ніби для Espruino більше прикладів, ніж для MicroPython, але тут я ще не впевнений.

Тепер Lua (eLua)

Збираємо

  1. git clone https://github.com/elua/elua.git ./elua
  2. cd ./elua
  3. В boards/known/, створюєм pyboard.lua  на основі stm32f4discovery.lua
    1. тут треба поміняти назву чіпа на stm32f405rg
  4. В src/platform/stm32f4/ cтворюємо cpu_stm32f405rg.h на основі cpu_stm32f407vg.h (можна нічого не міняти)
  5. У build_data.lua, додаємо 'STM32F405RG' в platform_list.stm32f4.cpus
  6. Компілюємо:
    1. sudo apt-get install lua5.1 lua-filesystem lua-md5 luarocks
    2. sudo luarocks install lpack
    3. ./build_elua.lua board=pyboard
Повинен появитись elua_lua_pyboard.elf. Заливаємо, майже так само як JS :)

~/Projects/elua
arm-none-eabi-objcopy -O binary elua_lua_pyboard.elf elua_lua_pyboard.bin

~/Projects/elua
sudo dfu-util -a 0 -s 0x08000000 -D elua_lua_pyboard.bin
dfu-util 0.5
...
Opening DFU USB device... ID 0483:df11
Run-time device DFU version 011a
Found DFU: [0483:df11] devnum=0, cfg=1, intf=0, alt=0, name="@Internal Flash  /0x08000000/04*016Kg,01*064Kg,07*128Kg"
Claiming USB DFU Interface...
Setting Alternate Setting #0 ...
Determining device status: state = dfuERROR, status = 10
dfuERROR, clearing status
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 011a
Device returned transfer size 2048
No valid DFU suffix signature
Warning: File has no DFU suffix
DfuSe interface name: "Internal Flash  "

Перевіряємо

eLua# lua
Press CTRL+Z to exit Lua
Lua 5.1.4  Copyright (C) 1994-2011 Lua.org, PUC-Rio
> print(pd.board() .. "/" .. pd.platform() .. "/" .. pd.cpu())
PYBOARD/STM32F4/STM32F405RG
> ledpin = pio.PA_13
> pio.pin.setdir(pio.OUTPUT, ledpin)
> pio.pin.sethigh(ledpin)
> pio.pin.setlow(ledpin)


О! Нам вдалося помигати світлодіодом.


> pb = pio.PB_3
> pio.pin.setdir(pio.INPUT, pb)
> print( pio.pin.getval(pb) )
0

> print( pio.pin.getval(pb) )
1


І визначити, чи натиснута кнопка.
Я в Lua не спец, так що далі буду по трохи розбиратись. Як буде щось цікаве, обов'язково розкажу!

2 коментарі:

  1. Jolly good, тепер у тебе точно блог веселого ембедера.)

    ВідповістиВидалити
  2. Йошкін-кошкін! Дякую! Доберусь через тиждень до своєї борди і спробую на ній Луа поганяти ))

    ВідповістиВидалити