你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

使用mbed在STM32上运行JavaScript

[复制链接]
STMCU-管管 发布时间:2019-2-25 15:16
主题! q2 c' `; B- y7 n

( S6 e3 i  T8 H3 u7 l为了让LED亮起来,编写一个小JavaScript脚本,整个过程主要通过ARM mbed C HAL函数的交互实现的。
2 B! N% \: u& l" d: e同时也适用于ARM mbed支持的其他系统。! m( \$ B; X! y! p6 {8 D
5 V  n1 s- `3 C8 ]: V
前提7 F* `- z. a/ `
" D6 `- w( m9 R( n& Y' j
在嵌入式MCU中添加脚本功能的原因有很多。 这次主要是想把JavaScript VM嵌入到他们现有的C固件,以便于快速定制核心业务逻辑,而不必重新包装设备。 这次我选择的嵌入式JavaScript VM是V7,这款是我和我在Cesanta的队友共同开发的。 V7库仅作为两个文件分发:V7 .c和V7 .h,你只需在项目中导入这两个文件就可以了。 V7是用可移植的C编写的,因此很容易从c++中使用。同时v7的平太是独立的,方便我们展示如何将其嵌入到ARM mbed项目中,以及如何在STM32F4设备上构建它,当然它也可以用于其他系统。
& [$ F6 h" v0 _$ ]# z+ V8 ?9 z9 Q$ n, F( ]- H  y( `, [, t# I
下面是完整的源代码:
" F6 i& C, v9 G* Z2 e! N( h7 P* c  e. e7 j; K
#include "mbed.h"
5 G. ?' u5 _9 S" G" g# c#include "v7.h" % X  i& P4 [' u1 o9 R

  ?2 m; @) T& {) Q7 FDigitalOut led_green(LED1); 8 v# q- H1 T0 I2 w
- K3 j8 N1 x: w) \3 E
enum v7_err js_set_led(struct v7 *v7, v7_val_t *res) { ) Q! W1 ]& H& P" Z$ d$ E+ V% X0 k# T
  led_green = !v7_get_bool(v7, v7_arg(v7, 0)); , B) h$ A' h. U9 R
  return V7_OK; - [2 [% z& y; S: Q. m' i7 G4 ?
} $ C* P0 [; ~( K5 ]! v

  T& N& w8 @3 Tenum v7_err js_wait(struct v7 *v7, v7_val_t *res) {
/ Z2 o) b; i+ V5 W5 g7 y  wait(v7_get_double(v7, v7_arg(v7, 0)));   F! ], O% h- z6 b; ~# M2 i
  return V7_OK;
' B# E! R5 A- \: ?/ f# `5 o+ d( b}
) y) X' ?3 Z- D0 N* x5 A ) G& w$ r8 W6 Z
int main() {
) R+ p0 g* \- m+ V2 Z/ T  F  struct v7 *v7 = v7_create(); ) N8 k: `6 {" F  d& N( }& W
  v7_set_method(v7, v7_get_global(v7), "setLed", &js_set_led);
4 }6 @6 e/ [( F  O% k+ o  v7_set_method(v7, v7_get_global(v7), "wait", &js_wait); % a8 [, D: x& Y$ y0 x$ ?
  v7_exec(v7,
# `5 J7 ]; s" ~4 N! k          "while(true) {" \ / A: a6 t5 h8 y- B, ?
          "  setLed(false);" \ " n* l; P0 O! E  ~; k9 T
          "  wait(0.5); " \ 1 {) T/ X5 ?, E, ^, o6 z
          "  setLed(true);" \
2 U% x" x5 V9 ^
你可以直接在ARM mbed在线编译器或命令行工具中复制这个代码,打开:http://developer.mbed.org/teams ... javascript_blinker/ 我们将逐步展示如何安装以及注意事项。
/ B6 Y$ A% a5 ]6 p8 j3 J
/ j; ~: p' g- J先看看如果没有脚本的话会是什么样子:4 W4 F  o; e, R
#include "mbed.h" . ^. u" h1 O" C7 k' ]5 b. y
+ {4 `4 P4 v: U1 b1 A
DigitalOut led_green(LED1);
  y; k6 ~" g- |( r: y8 t 7 F/ X- M: \$ r) y4 B
int main() { 2 B- e5 P; S; ]' U& @3 z
  while(true) {
. t: h( f; ]8 _5 R2 u3 T: @+ f    led_green = false;# H7 g3 p" i5 j1 y3 a
    wait(0.2);9 M9 N9 x. u, w, i# {' y4 W
    led_green = true;6 E4 k( b+ s* W; N* w
    wait(0.8);- j1 _4 ?+ ~" z: P/ B' ~
  }0 L' i6 q; [! D8 ~; a  z- |
}
0 {+ ]1 h( s9 n+ T, y+ P
可以在mbed在线编译器中编译这段代码,或者也可以使用mbed-cli工具。) l, ~- c' a; T* E4 V9 M* O: H
! T6 j# E! ^- @8 D& D0 P
进入JavaScript让我们首先添加V7库。2 }) s5 w: p' D. h# S" |5 g( [' F

8 r0 i  o: \, M2 n' J6 a! ?我已经将v7.c和v7.h文件打包在mbed代码库中,这样更方便。/ Q. J( `7 i0 _. r

2 C8 R: B/ H8 X$ W' [; G* j( n 1.jpg : B* `( r% Q# E. e/ Z( _& _9 D
0 k( h6 l' \  {  ~
或者,如果直接使用命令行工具:
' f3 @- r( K# z" Z
# v0 m# h" p, @  O. S4 Z. z1 t( n1 X& \& ]# J
现在,库已经被构建到固件中,但还需要它的数据头:
; I' j2 J/ q  ^& \; l1 A
#include "v7.h"
$ }3 B* x9 ~! z1 N% V5 a5 V; m
然后,在主函数中创建一个虚拟机的实例:
+ E% `6 I9 K) O5 Y4 j
struct v7 *v7 = v7_create();

/ y. K, R0 X1 w2 P# ]' E: o# k这个v7变量保存整个VM状态,在调用v7 API函数时需要传递,那如何运行脚本?
' R" [* b5 b( M  ?/ p* p6 u/ c
v7_exec(v7, "print('hello from javascript')", NULL);

$ \7 L/ |! k4 e( Vv7_exec的最后一个参数用于获取JavaScript表达式的结果。这点我们容易忘记。$ x/ G: q1 r" |& ~/ V% K# K

! g% \0 T4 a' }- q5 Q! j4 ^0 I  N& OJavaScript和设备 5 X/ W+ g1 e" ^& T

* F$ p9 L* R- [. I现在部份JavaScript代码已经成功运行了! 但是,我们如何让JavaScript代码在设备上做一些有用的事情呢?V7只是一个通用的JS VM库,它不知道任何关于你的嵌入式板,它的API等。 让我们先写一个简单的JS脚本,使用两个简单的函数,我们要从我们的设备的SDK导出:
- }* N3 B2 y# m7 F$ F$ ]- s# }, [# N
while(true) {
: l5 T9 L) \4 W2 U2 K  setLed(false);
; c0 t. S& }' \9 ^' D5 ], L6 f  wait(0.2);& q) L' b& U5 L5 o! a4 D
  setLed(true);
- ]% ?6 n: j- {, z7 E  wait(0.8);4 e4 u1 Z, @* T
}

6 o9 W+ z5 i- K) n我们可以使用v7_exec内联调用它,或者从闪存上的文件加载它,或者从网络下载它:4 k1 E. z9 c* @$ |. b( \: m9 d

: f* \* ^0 K2 \% \
v7_exec(v7, , R' t* V* f* r
         "while(true) {" \ # _* ]3 ~/ f1 L0 T6 F0 U6 `! c
         "  setLed(false);" \
7 y/ {. c7 l" l* l8 `         "  wait(0.2); " \
4 s7 m( M9 ]: g6 O6 o/ f         "  setLed(true);" \ ( K7 q1 F( r2 P2 x
         "  wait(0.8); " \ 3 p* r# D8 h& T- s7 X# v. ~
         "}",
  |- d7 X6 C9 H         NULL);

) e5 q+ V- T, P. F2 o! E现在注册几个函数使他可以与SDK进行交互:
v7_set_method(v7, v7_get_global(v7), "setLed", &js_set_led);
- Y1 T  T- L) r  G  jv7_set_method(v7, v7_get_global(v7), "wait", &js_wait);

" J) q  ?( N5 L4 s- C; Q5 M这段代码注册了两个全局JavaScript函数setLed和wait,可以像调用本地函数一样从脚本中调用它们。
8 ]3 L8 D% u/ s$ {$ w它们的实现是用c语言编写的。让我们仔细看看js_wait是如何实现的,看看它是如何工作的:
5 _7 C. d0 V9 W% C, a
+ ]. I- f/ N! l2 j. o
enum v7_err js_wait(struct v7 *v7, v7_val_t *res) {
6 a, P: o, s" U1 ?* G6 k wait(v7_get_double(v7, v7_arg(v7, 0))); * u9 b, Q  g2 s7 P. L
return V7_OK; 0 e/ A! Y  S, h
}
, L3 w) y+ s- [8 f' T
v7_arg(v7,0):获取传递给wait()的第一个参数。它返回一个v7_val_t值,该值表示一个通用JavaScript值。 ; w( p2 R+ ^9 s1 D' m& T+ U

  r* e8 M! r2 x# Y( r' K1 c' Qv7_get_double(v7, val):从v7_val_t中提取C双浮点值6 \6 }# t* R% Q7 ^' @7 R
' M$ U' p8 ?  ?( u# h( E/ E
一个物联网固件开发框架。支持单片机:ESP32, ESP8266, CC3220, CC3200, STM32F4, STM32L4, STM32F7。亚马逊AWS物联网、微软Azure、谷歌物联网核心集成。用C或JavaScript编写的代码。——阅读更多 http://mongoose-os.com
3 d( F* G. ?. X; Q$ z0 G+ v& Z
! h% }. M" }8 J. K9 x1 X) ?; Q+ l mongoose-os-master.zip (2.2 MB, 下载次数: 16)
收藏 评论1 发布时间:2019-2-25 15:16

举报

1个回答
JENKEY-152055 回答时间:2020-6-6 22:13:47
学习一下

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版