Luat 平台层#

为了跨平台, 需要一个”平台层”来隔离不同底层的实现

为什么需要”平台层”#

  • Lua的C语言实现, 代码基本上跨平台,但不是全部

  • Luat作为对硬件平台的封装,需要抽象为HAL

  • 还有一点, 就是对任务调度的抽象,包括定时器和消息队列


Lua 的跨平台#

这里讨论的是Lua 5.3.5.

Lua 基本上是跨平台, 可以认为是95%以上, 以下为需要抽象的平台功能


内存分配#

lua没有一个全局变量, 所有内存都是通过 lua_newstate(l_alloc, NULL)l_alloc参数(一个方法指针) 来分配.

原形如下

void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize)

所以, 我们需要定义一个抽象的C API

void* luat_heap_alloc(void *ud, void *ptr, size_t osize, size_t nsize);

详细的API设计, 在 内存池 中定义, 其中还有malloc的抽象形式 luat_heap_malloc


io 操作#

lua的io操作涉及4个方面

  • loadfile 加载lua文件, 涉及 fopen/fread/close 等方法

  • lua_writestring 原始实现是把数据传给标准输出(stdout)

  • io库, 涉及fopen/fread/fseek/close/feof/ferror 等POSIX常用方法

  • debug库, 涉及getc方法, 从标准输入(stdin)读取用户输入

Lua_FILE * luat_fs_fopen(char const* _FileName, char const* _Mode);

详细的API设计, 在 文件系统 中定义

这部分的修改, 是需要改动lua源码的, 替换原有的api调用


lua里面的系统API#

lua里面与系统密切相关的API, 分别是

time()    // os模块,获取系统时间, 需要支持
popen()   // io/os模块,启动一个新进程, 不需要支持,相关lua API删除
pclose()  // io/os模块, 关闭进程, 不需要支持,相关lua API删除
exit()    // 关闭lua所在的进程, 不需要支持,相关lua API删除

可见, 只有time方法是必须实现的, 而time的实现跟具体平台强相关, 所以必须抽象

uint8_t luat_os_get_time(*time_t);

Luat 的跨平台#

对设备接口和网络通信的封装, 本质上就是对厂商私有API的封装.


外设#

外设大多是同步API, 这C API 与 Lua API会非常相像

uint8_t luat_gpio_setup(LuatGpioPin pin, Lua_Value value, LuatGpioPULL pullup);
local LED = 33
gpio.setup(LED, gpio.LOW, gpio.PULLUP)

网络通信#

这部分非常依赖于厂商的SDK, 如果假设均提供lwip之类的通信封装,则这部分没有太多的内容.

如果假设不存在lwip之类的封装, 则需要非常详尽的API设计(照抄lwip也未尝不可)

TODO 待完成网络通信的API设计


任务调度#

那Luat依赖任务调度相关的API, rtos层

  • 定时器 timer – 单次/循环触发中断

  • 消息队列 queue – 消息排队处理

  • 信号量 sem – 预留

从原理上说, 即使没有rtos, 只要实现上述3组API, Luat跑着裸板上也是没有问题的.

能跑Luat的硬件, 其资源肯定能跑rtos. 是否使用rtos, 由厂商SDK决定.

所以, 上面3组API, 也有对应的抽象

  • 定时器

  • 消息总线

  • 信号量 暂无场景支撑,未设计

相关知识点#

  • 编码规范

  • 文件系统

  • 定时器

  • 消息总线

  • 内存池