在我的前一篇文章中,我谈到了物联网 (IoT) 以及将物理对象(“物”)连接到互联网。 我讨论了 Mongoose OS,一个用于 IoT 的开源操作系统,如何使新手和专业开发人员都能轻松地使用 JavaScript 编写微控制器程序。
您可能想知道为什么是 JavaScript,以及 JavaScript 引擎如何适应微控制器上有限的内存。 有许多项目旨在将脚本语言引入微控制器,其中包括其他 JavaScript 项目,例如 Duktape、Espruino、Jerryscript、MuJS 和 V7。 还有其他脚本语言,例如 MicroPython 和 Lua。
这些项目的一个共同点是都试图实现完整的语言规范以及完整的标准库。 这有利有弊。 优点是显而易见的,但缺点是什么?
缺点
首先,流行的脚本语言最初都不是为嵌入式环境设计的。 它们携带了一些晦涩的结构,这些结构占用了宝贵的空间,但在嵌入式环境中几乎没有实际用途。
其次,要将特定于硬件的功能导出到脚本环境中(例如,某个传感器 API 或某个 LCD 显示器 API),您需要编写胶水代码。 并且您需要维护该胶水代码,这会占用宝贵的空间并增加整体复杂性。
为了解决这些问题,引入了一个新的 JavaScript 引擎。
mJS
mJS 是 Mongoose OS 的一部分,并采取了完全不同的方法
- 它没有实现完整的语言,而是实现了一个有限的子集。
- 它没有标准库。
- 它没有胶水代码。
这些特性使 mJS 能够适应约 25K 的闪存空间和少于 1K 的 RAM。 这很难超越。 但是如何在没有标准库和任何胶水代码的情况下进行开发呢? mJS 的答案是通过直接调用 C SDK(软件开发工具包)函数的能力。
如何直接调用 C SDK 函数
外部函数接口 (FFI) 具有直接加载和调用 C 函数的能力。 为了执行这些步骤,mJS 必须知道两件事:C 函数的地址和 C 函数的签名。 然后,它将 JavaScript 参数编组为 C 值,将它们放到 ABI(应用程序二进制接口) 要求的位置(例如,在 CPU 堆栈上),然后跳转到函数的地址。 实际上,它看起来像这样
let f = ffi('int gpio_write(int, int)'); f(2, 1);
此代码段加载了一个 C SDK 函数 gpio_write(int pin, int value) 并调用它,将 GPIO 引脚 2 设置为高电压电平。 就这样。 需要来自 SDK 或第三方库的其他功能? 只需按需加载即可。 您甚至可以做这样的事情
let malloc = ffi('void *malloc(int)'); let mem = malloc(10);
不是说您应该这样做,而是说您可以这样做。 此外,您可以编组 C 回调
let Timer = { set: ffi('void timer(int, void (*)(int, userdata), userdata)') }; Timer.set(100, function(time) { print('Time now: ', time); }, true);
您需要嵌入 API 吗? 不,您不需要。 您也不需要任何胶水代码。 而且您也不需要标准库。
请参阅 mJS 如何在我们的 Mongoose OS 示例固件 中使用。 您可以将其与任何 C/C++ 软件一起使用,例如特定的固件。 有关更深入的介绍,请参阅 mJS GitHub 仓库 中的嵌入示例。
评论已关闭。