news 2026/9/28 17:28:55

在 Mbed OS 上运行 JerryScript:FRDM-K64F 从零构建、烧录与串口验证实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
在 Mbed OS 上运行 JerryScript:FRDM-K64F 从零构建、烧录与串口验证实战指南
  • 语言运行时
  • 嵌入式
  • 物联网
  • 编译器

【免费下载链接】jerryscript

Ultra-lightweight JavaScript engine for the Internet of Things.

项目地址:https://gitcode.com/gh_mirrors/je/jerryscript
点击查看免费下载

本篇指南围绕 JerryScript 仓库中的 Mbed OS 移植目标(targets/os/mbedos)展开,完整讲解如何在 Ubuntu 20.04 环境下,把超轻量级 JavaScript 引擎 JerryScript 与 ARM Mbed OS 6.15.0 组合编译为 FRDM-K64F 开发板固件,并通过 ST-Link 烧录、串口终端运行出第一行Hello, World!。读完本文,你将掌握 Mbed OS 移植目标的目录结构、构建参数(板型 / 工具链 / 堆大小)的调整方法、make构建与烧录的完整命令链,以及移植层jerry-port.cpp与主程序jerry-main.cpp的底层实现原理。

一、目标平台与整体思路

targets/os/mbedos是 JerryScript 官方为FRDM-K64F 开发板 + Mbed OS 实时操作系统提供的移植目标目录。FRDM-K64F 是恩智浦(NXP)推出的 Kinetis K64F(ARM Cortex-M4F)评估板,通过板载 OpenSDA 调试器以 USB 直连主机;Mbed OS 则是 ARM 主导的物联网嵌入式操作系统,提供串口、定时器等抽象层。

整个移植思路分三步:

  1. 将 JerryScript 引擎源码与 Mbed OS 源码放在同一工作目录(如jerry-mbedos)下;
  2. 用仓库自带的移植层文件(jerry-main.cpp、jerry-port.cpp)把引擎“接”到 Mbed OS 的串口与时间服务上;
  3. 通过mbed-tools compile产出.bin固件,烧录进开发板后用串口终端观察 JS 执行结果。

该目录包含 7 个文件,职责划分如下:

文件作用
Makefile封装mbed-tools compile,提供make/make flash/make clean目标及板型、工具链、堆大小等参数
Makefile.travis供 CI(Travis)验证用的构建目标,也适合在本地复现自动化构建
jerry-main.cpp移植目标的主程序:初始化引擎、注册print、解析并执行 JS 脚本
jerry-port.cpp引擎移植层(Port API)实现:致命错误、日志输出、本地时区、当前时间
mbed_lib.jsonMbed 库配置,向编译期注入 JerryScript 全局堆大小宏
mbedignore.txtMbed 构建排除清单,避免把无关目录编入固件
README.md官方构建与烧录说明(本文主体)

二、搭建构建环境(Step 1)

官方文档验证于Ubuntu 20.04操作系统。首先在工作目录下建立jerry-mbedos文件夹,并克隆两个项目:JerryScript 本体,以及指定版本分支的 Mbed OS。文档明确给出的最新测试可用版本为mbed-os-6.15.0。

mkdir jerry-mbedos && cd jerry-mbedos git clone https://github.com/jerryscript-project/jerryscript.git git clone https://github.com/ARMmbed/mbed-os.git -b mbed-os-6.15.0

克隆完成后应得到如下目录结构:

jerry-mbedos + jerryscript | + targets | + os | + mbedos + mbed-os

需要说明的是,克隆 JerryScript 时若使用本仓库(gh_mirrors/je/jerryscript)作为源码根目录,构建时其路径即对应上述结构中的jerryscript目录;Makefile 通过JERRY_ROOT_DIR = $(realpath $(JERRY_TARGET_DIR)/../../..)(见 Makefile)自动定位引擎根目录,因此目录相对位置必须保持:targets/os/mbedos位于引擎根目录之下,且与mbed-os平级。

三、安装构建依赖(Step 2)

在jerry-mbedos目录下依次执行依赖安装。首先是 JerryScript 自带的依赖脚本,然后是 ST-Link 烧录工具与 Mbed 命令行工具链:

# Assuming you are in jerry-mbedos folder. jerryscript/tools/apt-get-install-deps.sh sudo apt install stlink-tools pip install --user mbed-cli # Install Python dependencies of Mbed OS. pip install --user -r mbed-os/requirements.txt

各依赖的作用如下:

  • tools/apt-get-install-deps.sh:JerryScript 仓库自带的 Ubuntu 依赖安装脚本(位于 tools/apt-get-install-deps.sh),负责安装构建所需的编译工具链等基础软件;
  • stlink-tools:ST-Link / OpenSDA 烧录工具,FRDM-K64F 板载调试器即 OpenSDA,通过该工具完成固件写入;
  • mbed-cli:Mbed 命令行工具(老版本mbed-cli;新版本项目亦使用mbed-tools,见 Makefile 中的mbed-tools compile);
  • mbed-os/requirements.txt:Mbed OS 的 Python 依赖清单,包含编译配置所需的jsonschema、pyyaml等包。

此外,CI 流程(Makefile.travis)展示了等效的依赖安装方式:pip3 install mbed-tools setuptools并安装../mbed-os/requirements.txt,可作为脚本化部署的参考。

四、编译固件(Step 3)

依赖就绪后,在jerry-mbedos目录下执行:

# Assuming you are in jerry-mbedos folder. make -C jerryscript/targets/os/mbedos MBED_OS_DIR=${PWD}/mbed-os

MBED_OS_DIR用于告知 Makefile 去哪里找 Mbed OS 源码。整个构建链路在 Makefile 中清晰可见:

  1. .extra-files-copy:把mbedignore.txt复制为引擎根目录下的.mbedignore、把mbed_lib.json复制为根目录下的mbed_lib.json,让 Mbed 构建系统读取这些配置;
  2. .mbed-build:调用mbed-tools compile,并携带--clean --mbed-os-path $(MBED_OS_DIR) --program-path $(JERRY_ROOT_DIR) --toolchain $(TOOLCHAIN) --mbed-target $(BOARD) --app-config $(JERRY_ROOT_DIR)/mbed_lib.json参数;
  3. .extra-files-remove:构建结束后清理临时复制的两个文件。

构建完成后,固件输出为jerryscript/build/mbed-os目录下的mbedos.bin文件,可直接用于烧录。

4.1 可调构建参数

Makefile 顶部定义了四个可用变量(Makefile):

变量默认值含义
BOARDK64FMbed 目标板型号,默认 FRDM-K64F,可替换为其他 Mbed 支持板型
TOOLCHAINGCC_ARM编译工具链,默认 ARM GCC
BUILD_DIR$(JERRY_ROOT_DIR)/build/mbed-os构建产物输出目录,可通过命令行覆盖
JERRY_HEAP_SIZE70JerryScript 全局内存堆大小(单位 KB)

JERRY_HEAP_SIZE通过 mbed_lib.json 中的"macros": ["JERRY_GLOBAL_HEAP_SIZE=70"]注入编译宏。从引擎侧看,config.h 中该宏的默认值是512(KB),而 Mbed 移植目标将其缩减为70KB,这是为适应 K64F 的 256 KB SRAM 所做的内存预算。修改堆大小时只需更改mbed_lib.json中的宏值,注意引擎在 config.h 中会校验该宏必须大于 0,堆大小最终通过CONFIG_MEM_HEAP_SIZE (JERRY_GLOBAL_HEAP_SIZE * 1024)(见 jcontext.h)换算为字节数参与内存分配。

4.2 mbedignore.txt 的作用

Mbed 构建系统默认会扫描程序根目录(即 JerryScript 引擎根目录)下的全部源码,而 JerryScript 仓库含有大量与 Mbed 无关的目录(cmake、docs、tests、tools 等)。mbedignore.txt 通过cmake/*、docs/*、jerry-main/*、jerry-math/*、targets/*、tests/*、third-party/*、tools/*这 8 条规则将这些目录排除出编译范围,从而显著缩短编译时间、避免无关代码进入固件。

五、烧录固件(Step 5)

用 Micro-USB 线连接开发板(该接口同时承担充电与烧录功能),在jerry-mbedos目录下执行:

# Assuming you are in jerry-mbedos folder. make -C jerryscript/targets/os/mbedos MBED_OS_DIR=${PWD}/mbed-os flash

flash目标在 Makefile 中实现:先通过.mbed-set-flash-flag给MBED_CLI_FLAGS追加--flash参数,再执行正常构建;mbed-tools compile --flash会调用stlink-tools把mbedos.bin写入板载调试器连接的 K64F 芯片。

六、串口连接与运行验证(Step 5)

烧录完成后,开发板会在宿主机上显示为串口设备/dev/ttyACM0。使用minicom以115200波特率连接:

sudo minicom --device=/dev/ttyACM0 --baud=115200

连接后需要做两件事:

  1. 在 minicom 中按组合键CTRL-A -> Z -> U,打开Add Carriage Ret(回车符自动追加)选项——由于移植层日志输出只发送\n,终端需要该选项才能正确换行;
  2. 按下开发板上的RESET按钮,触发固件重新运行。

复位后,串口终端将打印 JerryScript 应用输出:

This test run the following script code: [print ('Hello, World!');] Hello, World!

第一行是主程序用调试级别日志打印的待执行脚本源码,第二行Hello, World!则是脚本中print调用在串口上的真实输出,证明 JS 引擎已在 Cortex-M4F 上完整跑通。

七、源码级解析:Hello World 背后的移植实现

7.1 主程序 jerry-main.cpp

jerry-main.cpp 演示了在嵌入式平台上使用 JerryScript C API 的完整生命周期,可视为最小可运行的引擎调用范式:

  1. jerry_init (JERRY_INIT_EMPTY):初始化引擎(空初始化,不启用快照等特性);
  2. jerry_log (JERRY_LOG_LEVEL_DEBUG, "This test run the following script code: [%s]\n\n", script):打印待执行脚本;
  3. jerryx_register_global ("print", jerryx_handler_print):调用 jerry-ext 扩展层(jerryscript-ext/handlers.h)把print注册为全局函数,其实现会把参数转成字符串输出;
  4. jerry_parse+jerry_run:先解析脚本生成可执行代码,再在全局作用域执行;
  5. 用jerry_value_is_exception判断执行是否出错,据此返回0(成功)或1(失败);
  6. jerry_value_free释放返回值,最后jerry_cleanup ()清理引擎。

串口输出最终落到 stderr 上——这是由移植层的jerry_port_log决定的(见下节),因此在 minicom 中看到的就是print与jerry_log混排的输出。

另外,jerry-main.cpp 中根据MBED_MAJOR_VERSION区分了 Mbed OS 5 与 6 的串口类:版本 5 使用Serial,版本 6 使用BufferedSerial,均以 115200 波特率初始化,未支持版本会触发#error编译失败。

7.2 移植层 jerry-port.cpp

jerry-port.cpp 实现了 JerryScript 要求宿主机提供的 Port API(接口定义见 jerryscript-port.h),共四个函数:

  • jerry_port_fatal:致命错误处理,直接以错误码调用exit;
  • jerry_port_log:日志输出实现——逐字符写入 stderr,并在每个\n前追加\r,这正是文档要求在 minicom 中开启Add Carriage Ret的原因;若终端侧不补\r,\n会被终端解释为仅换行不回车,导致输出错位;
  • jerry_port_local_tza:本地时区偏移,嵌入式环境固定返回 0(即 UTC);
  • jerry_port_current_time:当前时间(毫秒级),是移植中最精妙的部分——它以time(NULL)提供秒级基准,以us_ticker_read()提供微秒级增量;由于us_ticker_read()约每 71 分钟(UINT_MAX微秒)溢出一次,代码用静态变量记录上一次的 tick 与 time,检测到 tick 回绕时累计33ms的校正量skew(见 jerry-port.cpp),从而在无独立定时器线程的 MCU 上维持可用的毫秒级时钟。

正是jerry_port_current_time等底层服务,支撑起 JS 侧Date对象、setTimeout类功能(若上层脚本使用)的时间来源。

八、自动化构建参考(CI 流程)

如需在脚本或 CI 中复现整个流程,可参考 Makefile.travis 的目标拆解:

  • install-mbedos:克隆指定分支的 Mbed OS(示例中使用mbed-os-6.17.0,README 主体则以6.15.0为准),clone 到../mbed-os;
  • install-mbedos-deps:安装mbed-tools、setuptools及 Mbed OS 的 Python 依赖;
  • script:执行make -C targets/os/mbedos MBED_OS_DIR=$(realpath ../mbed-os)完成编译。

注意 CI 使用的是新版mbed-tools(pip3 install mbed-tools),而 README 中安装的是旧版mbed-cli;Makefile 的构建命令始终是mbed-tools compile,因此若你的环境同时存在两者,建议优先使用mbed-tools以保证与 Makefile 调用一致。

九、常见问题与调参建议

  • 固件找不到:确认构建命令带有MBED_OS_DIR=${PWD}/mbed-os且目录结构符合第二节;产物固定输出在jerryscript/build/mbed-os/mbedos.bin。
  • 串口无输出:检查是否开启了 minicom 的Add Carriage Ret(CTRL-A -> Z -> U),并确认波特率为 115200;jerry_port_log输出走 stderr,某些串口工具需开启“合并 stderr”或直接观察全部输出。
  • 编译缓慢 / 无关代码被编译:确认.mbedignore已由 Makefile 自动复制到引擎根目录(mbedignore.txt内容见 mbedignore.txt);make clean会清理build/mbed-os及临时复制文件。
  • 内存不足 / 脚本过大:调整 mbed_lib.json 中的JERRY_GLOBAL_HEAP_SIZE(单位 KB,须大于 0,见 config.h),同时权衡 K64F 的 256 KB SRAM 预算。
  • 更换开发板:通过make ... BOARD=<板型>覆盖默认的K64F,并确保该板型在 Mbed OS 中被支持。

至此,你已经完成了从源码克隆、依赖安装、固件编译、烧录到串口运行的全部闭环,并且在源码层面理解了 Mbed OS 移植目标中主程序、移植层与构建脚本的协作方式——这套流程同样适用于后续在 Mbed OS 平台上接入其他 JerryScript 应用逻辑(如 GPIO 控制、传感器读取等物联网场景)的二次开发。

  • 语言运行时
  • 嵌入式
  • 物联网
  • 编译器

【免费下载链接】jerryscript

Ultra-lightweight JavaScript engine for the Internet of Things.

项目地址:https://gitcode.com/gh_mirrors/je/jerryscript
点击查看免费下载

相关推荐

上一篇:NssMPClib的安装与使用教程
下一篇:【热门开源项目下载】ClkLog用户行为分析系统全指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 17:28:48

CLI-Anything:将零散脚本变成标准命令行命令的轻量框架

如果你跟我一样&#xff0c;日常要在终端里敲一堆维护脚本&#xff0c;那你大概率经历过这种场景&#xff1a;项目目录里有scripts/、tools/、ops/至少三四个放脚本的文件夹&#xff0c;里面躺着各种.sh和.py&#xff0c;每个脚本的参数规则又都不一样。有的用--date 2025-01-0…

作者头像 李华
网站建设 2026/9/28 17:28:16

Claude插件与托管Agent:金融场景落地实践

1. 从"financial-services"这个标题说起&#xff1a;一个被低估的插件化落地场景第一次看到financial-services这个项目标题时&#xff0c;我脑子里冒出来的第一个念头不是"又一个金融类 Demo"&#xff0c;而是——这大概率是一个围绕Claude 生态的插件&am…

作者头像 李华
网站建设 2026/9/28 17:26:32

金融智能体插件化落地:基于托管Agent与Cowork的工程实践

1. 从"financial-services"这个标题说起&#xff1a;一个被低估的插件化落地场景第一次看到financial-services这个项目名&#xff0c;很多人会下意识觉得它是个业务系统——账户、交易、风控、报表那一套。但结合关键词里的Claude、Cowork、Managed Agents API、plu…

作者头像 李华
网站建设 2026/9/28 17:26:01

FPGA驱动Si570时钟配置实战:I2C通信与AXI IP核避坑指南

1. 为什么Si570的I2C配置让FPGA新手频频翻车Si570这颗芯片在FPGA圈子里出镜率极高&#xff0c;尤其是做高速收发器、SerDes参考时钟或者需要动态可编程时钟的板卡上&#xff0c;几乎绕不开它。但很多新手第一次用Xilinx FPGA通过AXI I2C去配置Si570时&#xff0c;往往会卡在几个…

作者头像 李华