На роутере 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 [email protected]:/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 [email protected]:/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 — пишем первую программу
5 комментариев на «“Кросс-компиляция Lua для TP-LINK TL-MR3020”»
Вот здесь можно подробнее —
1. КАК Вы определили причину ошибки сборки
2. Чей это косяк — в системе ил того кто делал make-файл?
1. там же приведёт вывод ошибки сборки в котором линковщик говорит, что не может найти функцию dlopen и т.д. смотрим man dlopen и понимаем, что функции dl* используются для динамической подгрузки библиотек. Там же указано, что для сборки требуется указать параметр -ldl
2. просто я не захотел использовать стандартный вариант сборки под linux
см Makefile:
который приводит к зависимостям от двух сторонних библиотек (хотя они и есть в сборке OR-WRT) поэтому и искал вариант сборки без этих зависимостей.
Спасибо за ответ.
Блин, ну почему:
неужели трудно будет:
Меня сильно интересует вопрос автозапуска…
У тамошних скриптов не очень прозрачный синтаксис… Сложно разобраться…
В OpenWRT, само собой…