Кросс-компиляция 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 [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. ошибка сборки — похоже не находится библиотека libdl

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

    • 1. там же приведёт вывод ошибки сборки в котором линковщик говорит, что не может найти функцию dlopen и т.д. смотрим man dlopen и понимаем, что функции dl* используются для динамической подгрузки библиотек. Там же указано, что для сборки требуется указать параметр -ldl
      2. просто я не захотел использовать стандартный вариант сборки под linux
      см Makefile:

      linux:
      	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline -lncurses"

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

    • Спасибо за ответ.
      Блин, ну почему:

      print("Error open file!"); 

      неужели трудно будет:

      printf("Error while open file : %s\n", filename);

Добавить комментарий

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Arduino Bluetooth CraftDuino DIY Google IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд юмор

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение