Lua على STM32

مرحبا!

في بعض الأحيان ترغب في تجربة شيء ما بسرعة على وحدة التحكم الدقيقة ، برمجة نموذج أولي صغير للفكرة. لهذه الأغراض ، كما تعلم ، فإن لغات البرمجة النصية مناسبة تمامًا. في هذه المقالة ، أريد أن أعرف كيفية استخدام Embox لتشغيل مترجم Lua (قياسي وليس eLua) على STM32. للتوضيح ، قمنا بوميض LED عبر الشبكة باستخدام مكتبة luasocket ، ونعمل أيضًا قليلاً مع http.



Lua هي لغة برمجة نصية يكون مترجمها خفيف الوزن بما يكفي ليتم دمجه بسهولة في مشاريع أخرى ، بالإضافة إلى ترخيص MIT مجاني. لقد كنا مهتمين بهذه اللغة لفترة طويلة ، لذلك ، تحت Embox ، هناك دعم Lua على qemu i386. وبما أن المترجم خفيف الوزن ومتوافق مع POSIX ، فقد ظهرت الفكرة لإطلاق Lua بنفس الطريقة التي فعلناها مع مكتبات أخرى مثل Pjsip و OpenCV و Qt .

سألاحظ على الفور أنه نظرًا لأننا سنعمل بدعم luasocket ، فسنختار ليس stm32f4-discovery (فلاش 1 ميجا بايت ، 192 كيلو بايت من ذاكرة الوصول العشوائي) ، ولكن أكثر قليلاً - stm32f7-discovery(فلاش سعة 1 ميجابايت ، وذاكرة وصول عشوائي تبلغ 320 كيلوبايت ، وبطاقة ذاكرة إضافية) في الوقت نفسه ، ليس هناك شك في أن الإصدار الأساسي من Lua بدون دعم الشبكة يمكن أن يبدأ بسهولة على stm32f4 (انظر أدناه).

للبدء ، دعنا نعد مثالًا بسيطًا - حساب رقم فيبوناتشي التاسع:

function fib(n)
    if n < 3 then
        return 1
    else
        return fib(n - 1) + fib(n - 2)
    end
end

print("fib(7) = " .. fib(7))

لنبدأ مع Linux أولاً ونرى مقدار الذاكرة التي استغرقتها. ثم سننقله إلى Embox بدون تغييرات. أولاً ، قم بتنزيل lua الطازج. لقد قمت بتنزيل 5.3.5 ، وقمت بتجميعه كـ "make linux". ولكن في الواقع ، لأغراضنا ، يمكنك وضعها من المستودع. بعد ذلك ، قم بتشغيل fib.lua لدينا:

$ valgrind --tool=massif --massif-out-file=fib.massif lua fib.lua
$ ms_print fib.massif > fib.out

الآن يمكنك البحث في fib.out ومعرفة أن الحد الأقصى لحجم الذاكرة المخصصة في كومة الذاكرة المؤقتة حوالي 30 كيلو بايت. هنا ، بالطبع ، لن أقول أن هذا هو الحد الأدنى للحجم. على سبيل المثال ، في المقالة في قسم "متطلبات ذاكرة الوصول العشوائي" ، يتم توفير متطلبات أقل بكثير ، ولكن فقط في وقت تشغيل جهاز Lua. ولكن على أي حال ، يبدو 30 كيلوبايت مشجعًا - لدينا 320 كيلوبايت.

الآن قم ببناء قالب الذراع / stm32f746g-discovery-lua لـ Embox:

$ make confload-arm/stm32f746g-discovery-lua
$ make -j $(nproc)

بناء البرامج الثابتة / القاعدة / الحاوية / embox على السبورة كما هو موضح في الويكي الخاص بنا وتشغيلها:

embox> lua fib.lua 
fib(7) = 13

رائع ، كل شيء يشبه تمامًا Linux (ليس من المستغرب :)).

دعونا نعقد المهمة ، ولكن الآن أصبحت الشبكة ضرورة في كل مكان تقريبًا. إرسال طلب HTTP / GET في مكان ما على الإنترنت. للقيام بذلك ، تحتاج إلى مكتبة luasocket . ثم لم أبدأ في التجميع من أكواد المصدر ، لكنني استخدمت الحزمة الجاهزة ("sudo apt-get install lua-socket").

لإرسال طلب HTTP ، استخدم هذا المثال البسيط:

local http = require("socket.http")

if not arg or not arg[1] then
    print("lua http_request.lua <url>")
    os.exit(0)
end

local body, code = http.request(arg[1])
print(code)
print(body)

os.exit(code == 200)

مرة أخرى ، يمكن التحقق من كل شيء على Linux:

lua http_request.lua http://example.com

سيعيد الرمز 200 ومحتوى الصفحة. دعونا نرى ذلك من الذاكرة. إذا قمت بتشغيل valgrind مرة أخرى ، يمكنك أن ترى أن ذروة استهلاك الذاكرة في كومة الذاكرة المؤقتة قد زادت إلى 242 كيلو بايت. لذلك اكتشفت أخيرًا أن stm32f4 لن يصلح بدون تحسينات إضافية. يبدو أنه من الممكن الحصول على stm32f7 - هناك 320 كيلوبايت ، ولكن مع الأخذ في الاعتبار أنه لا يزال هناك نظام تشغيل مع نظام ملفات وشبكة ، قررت قليلاً العبث باستخدام مجموعة من SDRAM الخارجية.

نقوم بتشغيل (في التكوين هذا موجود بالفعل) الكومة المعتادة في ذاكرة الوصول العشوائي ، والأخرى في SDRAM.

    include embox.mem.static_heap(heap_size=0x10000)
    include embox.mem.fixed_heap(heap_size=0x40000, heap_start=0x60000000)

نتحقق من stm32f7-discovery ، فهو يعمل مثل Linux.

دعونا أخيرا وميض الصمام "عن بعد".

local socket = require("socket")

port = arg[1] or 1027
udp = assert(socket.udp())
assert(udp:setsockname('*', port))
print("Lua UDP server started on port " .. port .. "...")
while 1 do
    cmd, ip, port = assert(udp:receivefrom())
    print("Execute '" .. cmd .. "' from " .. ip .. ":" .. port)
    os.execute(cmd)
end

هنا نحصل فقط على بيانات UDP من المنفذ المحدد ونقوم بتمريرها إلى os.execute (). كأمر سيتم تنفيذه ، سنرسل أمر دبوس من العميل. هذا أمر بسيط في Embox يتحكم في GPIO - على سبيل المثال ، بالنسبة إلى stm32f7-disco ، تحتاج إلى تنفيذ "pin gpioi 1 toggle" ، مما يعني تغيير الخط الأول إلى GPIOI.

سيتم أخذ مثال قياسي من luasocket كعميل:

echoclnt.lua
-----------------------------------------------------------------------------
-- UDP sample: echo protocol client
-- LuaSocket sample files
-- Author: Diego Nehab
-----------------------------------------------------------------------------
local socket = require("socket")

host = "localhost"
port = 1027
if arg then
    host = arg[1] or host
    port = arg[2] or port
end

udp = assert(socket.udp())
assert(udp:setpeername(host, port))
print("Using remote host '" ..host.. "' and port " .. port .. "...")
while 1 do
    line = io.read()
    if not line or line == "" then os.exit() end
    assert(udp:send(line))
end


كالعادة ، تحقق أولاً من Linux. يوضح Valgrind أن ذروة استهلاك الذاكرة في كومة الذاكرة المؤقتة حوالي 70 كيلو بايت ، وهو أكثر من مرتين مع الحالة مع Fibonacci (30 كيلو بايت) ، ولكن أقل بكثير من المثال في HTTP (242 كيلو بايت).

اعرض على الفور مثالًا على الإطلاق على Embox.

على Linux:

$ lua echoclnt.lua 192.168.0.128 1027
Using remote host '192.168.0.128' and port 1027...
pin gpioi 1 toggle
pin gpioi 1 toggle

على Embox:

embox>                                                   
embox>lua udp_server.lua                                                        
Lua UDP server started on port 1027...
Execute 'pin gpioi 1 toggle' from 192.168.0.102:34300
Execute 'pin gpioi 1 toggle' from 192.168.0.102:34300

استنتاج


تمكنا من تشغيل Lua + luasocket على stm32f7-discovery. وبمساعدتهم ، وميض LED عن بعد عبر الشبكة. واتضح أن الأمر بسيط للغاية ، لأنه كما لوحظ في البداية ، يمكن أن توفر لغات البرمجة النصية الوقت في النماذج الأولية.

أريد أيضًا أن أشير إلى أن هناك مشروع eLua يعمل على المعدن بدون نظام تشغيل. ولكن لديه العديد من الفروق الدقيقة. أولاً ، دعم محدود للشبكة: UDP غير موجود ، وتقول الوثائق أن الشبكة "قيد التقدم" في الوقت الحالي. ثانيًا ، لم أتمكن من العثور على دعم لأي نوع stm'ku F3 ، F4 (فقط F1). وبشكل عام ، يجب أن توافق ، من المفيد أكثر استخدام المشاريع المدعومة على نطاق واسع ، وفي هذا الصدد ، فإن elua أدنى بالتأكيد من المشروع الرئيسي.

جميع الأمثلة الموضحة في المقالة موجودة في مستودعنا.

يحتوي Embox أيضًا على لغات برمجة نصية أخرى - python (tinipy) و Ruby (mruby) و Tcl. ولكن هذا خارج نطاق هذا المقال :)

جهات الاتصال الخاصة بنا:
النشرة الإخبارية: embox-ru@googlegroups.com
دردشة Telegram: t.me/embox_chat

All Articles