嵌入式lua之多线程操作移植三 lua FreeRTOS

14 篇文章 10 订阅
5 篇文章 1 订阅

然而,使用前章方法移植到FreeRTOS上后却各种不尽人意。

来来回回搞了几个星期,最终还是实现了我的目的,先展示下效果吧!!!

压力测试11个线程。led间隔100ms闪烁,10个打印线程正常。

中途遇到的问题记录

执行lua文件频繁时会返回如下错误:

[#err : execute fail(1) cannot open 0:/TEST.LUA: No error (errno = 0)]

原因:打开文件过快,会造成文件读取冲突,所以文件操作需要加上互斥锁。顺便一提,lua的锁lua_lock,lua_unlock也必须实现,否则乱套。用一个独立的互斥信号量即可。

 

实现说明

单纯使用前面章节提到的函数是不能实现lua多线程的。

在gethua上找到了一份开源代码 Lua-RTOS-ESP32,很值得学习。我从中摘取了线程创建及调用部分代码。

源码参考其中的thread.c文件。

我的项目只需要简单的线程创建运行即可,考虑到线程参数的传递,我用了一个table作为传递介质。方便灵活的传递我们需要的参数。

lua底层驱动文件

文件:lua_task.c

#define STACK_DEFAULT 512 //堆栈默认大小
#define PRIORITY_DEFAULT 5 //线程优先级
#define TASKNAME_DEFAULT "task" //线程名

static void _task(void *arg)
{
    lthread_t *thread = (struct lthread *)arg;

    int inParamLen = lua_gettop(thread->L) - 1;//除去栈底函数的参数个数,其实创建时已限定总栈个数为2.

    int status = lua_pcall(thread->L, inParamLen, 0, 0);

    if (status != LUA_OK)
    {
        const char *msg = lua_tostring(thread->L, 1);
        printf(" thread pacll err:<%d> %s\r\n", status, msg);
    }

    free(thread);

    vTaskDelete(NULL);
}

static int TaskRun(lua_State *L)
{

    if (lua_isfunction(L, 1) == 0)
    {
        printf("err: TaskRun param don function\r\n");
        return 0;
    }

    struct lthread *thread;

    int stack = STACK_DEFAULT;
    int priority = PRIORITY_DEFAULT;   
    const char *name = TASKNAME_DEFAULT;

    if (lua_istable(L, 2)) //第一个参数是不是table 
    {
        lua_pushstring(L, "stack");
        lua_gettable(L, 2);
        stack = luaL_optinteger(L, -1, STACK_DEFAULT);

        lua_pushstring(L, "priority");
        lua_gettable(L, 2);
        priority = luaL_optinteger(L, -1, PRIORITY_DEFAULT);

        lua_pushstring(L, "name");
        lua_gettable(L, 2);
        name = luaL_optstring(L, -1, TASKNAME_DEFAULT);
    }

    //printf(" %d %d %s\r\n",stack,priority,name);

    //return 0;
    // Get stack size, priotity and cpu affinity

    if (stack < 512)
    {
        printf("err: task stack[%d] is small\r\n", stack);
        return 0;
    }

    // Allocate space for lthread info
    thread = (struct lthread *)malloc(sizeof(struct lthread));
    if (!thread)
    {
        printf("err: thread malloc fail\r\n");
        return 0;
    }

    // Check for argument is a function, and store it's reference
    //luaL_checktype(L, 1, LUA_TFUNCTION);
    thread->function_ref = luaL_ref(L, LUA_REGISTRYINDEX);

    // Create a new state, move function to it and store thread reference
    thread->PL = L;
    thread->L = lua_newthread(L);
    thread->thread_ref = luaL_ref(L, LUA_REGISTRYINDEX);

    lua_rawgeti(L, LUA_REGISTRYINDEX, thread->function_ref);

    int top = lua_gettop(L);
    if(top>2) top = 2;
    // Ensure that we have only the thread function in the lua stack prior to
    // move it to the lua thread stack
    lua_settop(L, top);//移除多余的传入参数

    lua_xmove(L, thread->L, top);//拷贝栈到子线程栈 thread->L

    //创建线程
    TaskHandle_t taskHandle;
    xTaskCreate(_task, name, stack, thread, priority, &taskHandle);

    lua_pushinteger(L, (int)taskHandle);//预留后续可以管理线程

    return 1;
}


const luaL_Reg ledLib[] =
    {
        {"run", TaskRun},
        {"led_on", led_on},
        {"led_off", led_off},
        {"tab", table_test},
        {NULL, NULL}};

lua测试脚本

文件:0:/test.lua

task.run(
    function()
        while true do
            os.sleep(100)
            task.led_on()
            os.sleep(100)
            task.led_off()
            print("led_task")
        end
    end
)

function task_fun(data)
    local a = 0
    while true do
        a = a + 1
        os.sleep(100)
        print("task" .. data.param .. " -run > " .. a)
    end
end

for i = 1, 10 do
    task.run(task_fun, {param = i})
end

 

执行结果:


task9 -run > 21086
task4 -run > 21086
task8 -run > 21086
task6 -run > 21086
task10 -run > 21086
led_task
task2 -run > 21087
task1 -run > 21087
task5 -run > 21087
task7 -run > 21087
task3 -run > 21087
task9 -run > 21087
task4 -run > 21087
task8 -run > 21087
task6 -run > 21087
task10 -run > 21087
task2 -run > 21088

。。。。。。

结束

至此,移植工作算是有突破性的进展,后续会多方面测试系统的稳定型。应该会有一些问题,希望大家能提示完善一下。

 

 

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值