CraftDuino v2.0
  • - это CraftDuino - наш вариант полностью Arduino-совместимой платы.
  • CraftDuino - настоящий конструктор, для очень быстрого прототипирования и реализации идей.
  • Любая возможность автоматизировать что-то с лёгкостью реализуется с CraftDuino!
Просто добавьте CraftDuino!

Кросс-компиляция Lua для TP-LINK TL-MR3020


На роутере TP-LINK TL-MR3020 с прошивкой OR-WRT (0.70) установлен Lua старой версии
# lua -v
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio (double int32)

попробуем её обновить )

Тулчейн для для сборки программ под процессор, используемый на роутере (архитектуры MIPS) мы уже установили.
Напомню, что toolchain — это набор программ, необходимых для создания других программ. Т.е., это набор из нескольких исполняемых файлов:
препроцессор, компилятор, линкер и т.д.

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

Распакуем архив lua в свою директорию
~/dev/toolchains/tplink/

для сборки под TP-LINK TL-MR3020 нужно всего-лишь указать на наш mips-компилятор
например так:
cd ~/dev/toolchains/tplink/lua-5.2.1
make posix CC=mips-openwrt-linux-gcc


но чтобы lua мог подгружать библиотеки он должен быть собран с параметром -DLUA_USE_DLOPEN
судя по Makefile — нам подходит платформа bsd
make bsd CC=mips-openwrt-linux-gcc

ошибка сборки — похоже не находится библиотека libdl:
liblua.a(loadlib.o): In function `ll_loadfunc':
loadlib.c:(.text+0xa8c): undefined reference to `dlsym'
loadlib.c:(.text+0xb10): undefined reference to `dlopen'
loadlib.c:(.text+0xb8c): undefined reference to `dlerror'
loadlib.c:(.text+0xba8): undefined reference to `dlerror'
liblua.a(loadlib.o): In function `gctm':
loadlib.c:(.text+0x135c): undefined reference to `dlclose'


правим Makefile и добавляем -ldl
bsd:
	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-Wl,-E -ldl"


снова собираем и, на этот раз успешно :)
$ file ./src/lua
./src/lua: ELF 32-bit MSB executable, MIPS, MIPS32 rel2 version 1, dynamically linked (uses shared libs), with unknown capability 0x41000000 = 0xf676e75, with unknown capability 0x10000 = 0x70403, not stripped

проверим
scp ./src/lua root@192.168.217.1:/root/

# ./lua -v
Lua 5.2.1  Copyright (C) 1994-2012 Lua.org, PUC-Rio

# ./lua -e "print(\"hello \"..\"world!\");"
hello world!


работает!

соберём пример своей lua-библиотеки
mips-openwrt-linux-gcc mytest.c -shared -fpic -I./lua-5.2.1/src -o mytest.so


копируем
scp ./mytest.so root@192.168.217.1:/root/

проверяем:
# ./lua call.lua
start lua...
[i] test_add1(12.00)
13
end lua...

крутотень :)

Перепишем blink с использованием sleep()

для этого внесём изменения в нашу библиотеку mytest
//
// example of library for use in Lua
//
// compile:
//
// gcc mytest.c -shared -fpic -I/usr/src/lua-5.2.1/src -o mytest.so
// mips-openwrt-linux-gcc mytest.c -shared -fpic -I./lua-5.2.1/src -o mytest.so
//

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#ifdef __cplusplus
extern "C" {
#endif

#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"

#ifdef __cplusplus
}
#endif

int test_add1(lua_State *L)
{
    double d = luaL_checknumber(L, 1); // get item 1 (argument by position)
    printf("[i] test_add1(%0.2f)\n", d);
    lua_pushnumber(L, d + 1); // return the result
    return 1; // number of items returned
}

int test_sleep(lua_State *L)
{
    double d = luaL_checknumber(L, 1); // get item 1 (argument by position)
    usleep( (int)d * 1000 );
    return 0;
}

static const struct luaL_Reg mytestlib[] =
{
    {"add1", test_add1},
    {"sleep", test_sleep},
    {0, 0}
};

#ifdef __cplusplus
extern "C"
#endif
int luaopen_mytest (lua_State *L)
{
    //luaL_register(L, "mytest", mytestlib);
    luaL_openlib(L, "mytest", mytestlib, 0);
    return 1;
}

пересобираем
mips-openwrt-linux-gcc mytest.c -shared -fpic -I./lua-5.2.1/src -o mytest.so


и сам обновлённый blink

--[[ blink2 ]]--
led=io.open("/sys/devices/platform/leds-gpio/leds/tp-link:green:3g/brightness", "w"); 
if led==nil then 
	print("Error open file!"); 
	os.exit(-1); 
end 
val = 0; 
require('mytest');
while 1 do 
	mytest.sleep(1000);
	led:seek(beg, 0); 
	print(val); 
	led:write(val); 
	if val == 0 then  
		val = 1; 
	else 
		val = 0; 
	end 
end

заливаем и проверяем — светодиод моргает, а загрузка процессора существенно сократилась до нескольких процентов :)

соберём пример, считывающий lua-скрипт. переделаем его под C и добавим математическую библиотеку:
mips-openwrt-linux-gcc -I./lua-5.2.1/src -o luatest luatest.c -L./lua-5.2.1/src -llua -ldl -lm


копируем и проверяем
# ./luatest
[i] Start...
[i] file: my.lua
hello world!
123
123
357
var= hello world!
b= 123.000000
c= 234.000000
d= 357.000000
[i] End.


ну всё — теперь все роботы наши! :)

Далее: Lua — модуль для работы с последовательным портом

Ссылки:
Использование Lua в робототехнике
Исследование Wi-Fi-роутера TP-LINK TL-MR3020
Новогоднее исследование ADSL-роутера на базе Linux — 0x5 — пишем первую программу
  • +2
  • 19 ноября 2012, 19:10
  • noonv

Комментарии (5)

RSS свернуть / развернуть
+
0
ошибка сборки — похоже не находится библиотека libdl

Вот здесь можно подробнее —
1. КАК Вы определили причину ошибки сборки
2. Чей это косяк — в системе ил того кто делал make-файл?
avatar

mhimig

  • 20 ноября 2012, 08:46
+
0
1. там же приведёт вывод ошибки сборки в котором линковщик говорит, что не может найти функцию dlopen и т.д. смотрим man dlopen и понимаем, что функции dl* используются для динамической подгрузки библиотек. Там же указано, что для сборки требуется указать параметр -ldl
2. просто я не захотел использовать стандартный вариант сборки под linux
см Makefile:
linux:
	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline -lncurses"

который приводит к зависимостям от двух сторонних библиотек (хотя они и есть в сборке OR-WRT) поэтому и искал вариант сборки без этих зависимостей.
avatar

noonv

  • 20 ноября 2012, 18:29
+
0
Спасибо за ответ.
Блин, ну почему:
print("Error open file!"); 

неужели трудно будет:
printf("Error while open file : %s\n", filename);

avatar

mhimig

  • 21 ноября 2012, 05:29
+
0
Меня сильно интересует вопрос автозапуска…
У тамошних скриптов не очень прозрачный синтаксис… Сложно разобраться…
avatar

Mirmik

  • 22 ноября 2012, 22:52
+
0
В OpenWRT, само собой…
avatar

Mirmik

  • 22 ноября 2012, 22:52

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.