Skip to content

Commit 704d5e2

Browse files
committed
zz
1 parent c86b99d commit 704d5e2

File tree

2 files changed

+226
-0
lines changed

2 files changed

+226
-0
lines changed

docs/public/st0052-01.png

16.6 KB
Loading

docs/smalltalk/st0052.md

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
# 凹语言重新点亮 Arduino nano 33
2+
3+
- 时间:2024-09-22
4+
- 撰稿:凹语言 开发组
5+
- 转载请注明原文链接:[https://wa-lang.org/smalltalk/st0052.html](https://wa-lang.org/smalltalk/st0052.html)
6+
7+
---
8+
9+
凹语言是国内 Gopher 发起的纯社区构建的开源国产编程语言项目。凹语言最初在2022年底增加了对Arduino-wasm平台的支持,后来在2023年底因为聚焦MVP开发临时去掉了Arduino目标的支持。最近在下个发布的v0.17.0版本中将恢复对Arduino nano 33开发版的支持,相对于之前的版本现在的凹语言特性更加丰富。
10+
11+
- 例子代码:[https://gitee.com/wa-lang/wa/tree/master/waroot/examples/arduino](https://gitee.com/wa-lang/wa/tree/master/waroot/examples/arduino)
12+
- 安装凹语言版本:`go install wa-lang.org/master`
13+
14+
## 1. Arduino-wasm 是什么
15+
16+
Wasm3 是一个高性能的 WebAssembly 解释器,而 Arduino-wasm 则是 Wasm3 针对 Arduino 的定制版本。Wasm3 最小的硬件依赖是 ~64Kb Flash 和 ~10Kb RAM。
17+
18+
Github 仓库:[https://github.com/wasm3/wasm3-arduino](https://github.com/wasm3/wasm3-arduino)
19+
20+
下面是 Wasm3 运行在 iOS 的截图:
21+
22+
![](/st0015-01.png)
23+
24+
Arduino-wasm 则是运行在 Arduino Nano 33 等开发板上的 Wasm3。
25+
26+
27+
## 2. Arduino Nano 33 开发板介绍
28+
29+
Arduino Nano 33,是 Arduino Nano 的高配版本,是一款基于 nRF52840 SoC ARM 32 位处理器的微型开发板。其中 Arduino Nano BLE Sense 其主控芯片集成了蓝牙低功耗(BLE)。NANO 33 BLE 不仅保留了与经典款 NANO 同样的尺寸与管脚,且在此基础上配有多种高性能传感器等,当然最重要的是满足了 Arduino-wasm 的最低硬件要求。
30+
31+
![](/st0015-02.jpg)
32+
33+
目前(2024年底),淘宝的价格大约在200元以内。
34+
35+
## 3. 编写 Arduino 的闪灯例子
36+
37+
首先用`wa init`生成一个arduino例子:
38+
39+
```
40+
$ wa init -arduino
41+
$ cd hello/
42+
$ tree
43+
.
44+
├── README.
45+
├── src
46+
│ └── main.wa
47+
└── wa.mod
48+
```
49+
50+
其中 `main.wa` 内容如下:
51+
52+
```wa
53+
// 版权 @2024 arduino 作者。保留所有权利。
54+
55+
import "syscall/arduino"
56+
57+
global LED = arduino.GetPinLED()
58+
59+
func init {
60+
arduino.PinMode(LED, 1)
61+
arduino.Print("凹语言(Wa)/Arduino is running ...\n")
62+
arduino.Print("https://wa-lang.org\n")
63+
64+
for {
65+
arduino.DigitalWrite(LED, arduino.HIGH)
66+
arduino.Delay(100)
67+
arduino.DigitalWrite(LED, arduino.LOW)
68+
arduino.Delay(900)
69+
}
70+
}
71+
```
72+
73+
代码逻辑比较简单,只是换成了凹语言来写。我们直接使用了 `syscall/arduino` 包来使用 Arduino 的功能。
74+
75+
76+
## 4. `syscall/arduino` 包介绍
77+
78+
让我们看看 [`syscall/arduino` 包的代码](https://gitee.com/wa-lang/wa/tree/master/waroot/src/syscall/arduino)
79+
80+
```wa
81+
// 版权 @2022 凹语言 作者。保留所有权利。
82+
83+
const (
84+
LOW :i32 = 0
85+
HIGH :i32 = 1
86+
87+
INPUT :i32 = 0
88+
OUTPUT :i32 = 1
89+
INPUT_PULLUP :i32 = 2
90+
)
91+
92+
#wa:import arduino millis
93+
func Millis() => i32
94+
95+
#wa:import arduino delay
96+
func Delay(ms: i32)
97+
98+
#wa:import arduino pinMode
99+
func PinMode(pin, mode: i32)
100+
101+
#wa:import arduino digitalWrite
102+
func DigitalWrite(pin, value: i32)
103+
104+
#wa:import arduino getPinLED
105+
func GetPinLED() => i32
106+
107+
#wa:import arduino print
108+
func PrintRawString(ptr: i32, len: i32)
109+
110+
func Print(s: string) {
111+
print(s)
112+
}
113+
114+
func Println(s: string) {
115+
println(s)
116+
}
117+
```
118+
119+
主要是将常用的函数通过 WASM 方式导入到了代码空间,大部分函数并不在凹语言中实现。
120+
121+
## 5. 编译到 Arduino-wasm 平台
122+
123+
可以通过`wa build`命令构建程序:
124+
125+
```
126+
$ wa build
127+
$ tree
128+
.
129+
├── README.md
130+
├── output
131+
│ ├── arduino
132+
│ │ ├── app.wasm.h
133+
│ │ └── arduino.ino
134+
│ ├── hello.wasm
135+
│ └── hello.wat
136+
├── src
137+
│ └── main.wa
138+
└── wa.mod
139+
```
140+
141+
output目录存放编译的结果,`output/arduino/arduino.ino`是Arduino工程文件,`output/arduino/app.wasm.h``output/hello.wasm`文件对应的数据数组。
142+
143+
```c
144+
// Auto Generate by Wa language. See https://wa-lang.org
145+
146+
unsigned int app_wasm_len = 4608;
147+
148+
unsigned char app_wasm[] = {
149+
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x37,
150+
151+
0x03, 0x24, 0x74, 0x30, 0x17, 0x00, 0x18, 0x00,
152+
};
153+
```
154+
155+
然后 Arduino 工程就可以通过 `#include "app.wasm.h"` 方式引用这个 WASM 程序,最终和 Wasm3 一起编译。
156+
157+
## 6. Arduino 平台胶水代码初探
158+
159+
最终还需要一个 `arduino.ino` 代码(其实就是针对 Arduino 简化的 C++ 程序)。代码结构如下:
160+
161+
```c
162+
#include <wasm3.h>
163+
#include <m3_env.h>
164+
165+
// 定义 WASM 和 本地栈大小
166+
#define WASM_STACK_SLOTS 1024
167+
#define NATIVE_STACK_SIZE (32*1024)
168+
169+
// WASM 最大内存限制, 一般不得超过 64KB 大小
170+
#define WASM_MEMORY_LIMIT (32*1024)
171+
172+
// 导入 凹语言 生成的 WASM 文件对应的二进制头文件
173+
#include "app.wasm.h"
174+
```
175+
176+
开头保护 Wasm3 和 WASM 程序对应的头文件,同时定义以下栈的大小。
177+
178+
然后看看代码主体结构:
179+
180+
```cpp
181+
// 执行 WASM 的函数
182+
void wasm_task(void*) { ... }
183+
184+
// setup 作为 main 函数用户
185+
void setup() {
186+
// 串口初始化
187+
Serial.begin(115200);
188+
delay(100);
189+
190+
// 等待串口初始化完成, 必须是 USB 串口
191+
while(!Serial) {}
192+
193+
// 阻塞执行 wasm 程序, 不会返回
194+
wasm_task(NULL);
195+
}
196+
197+
// 该函数不会被执行
198+
// 定义该函数只是为了确保 Arduino 编译通过
199+
void loop() {
200+
delay(100);
201+
}
202+
```
203+
204+
Arduino 的常规代码只有 setup 和 loop 两个函数。不过这里只用到了 setup 函数。在 setup 函数中首先初始化串口(方便打印调试信息),最后调用 `wasm_task` 执行凹语言写的亮灯代码,其中会加载 WASM 模块并执行。`wasm_task` 看起来是一个比较复杂的程序,不过核心逻辑和普通的 WASM 执行流程类似,细节可以下次文章再展开。
205+
206+
总体来说,以上这些胶水代码是相对固定的。后面会自动生成全部这些代码,同时去掉对外部其他工具的依赖。目标是生成的 Arduino 工程文件可以直接打开构建。
207+
208+
## 7. Arduino 构建 & 执行
209+
210+
如果是第一次使用 Arduino Nano 33 开发板,打开 IDE 后会提示安装必要的工具。然后需要在库管理菜单手动安装 Wasm3 包:
211+
212+
![](/st0015-03.jpg)
213+
214+
然后编译后上传的效果:
215+
216+
![](/st0015-04.jpg)
217+
218+
执行的效果,除了可以看到 LED 闪烁,串口还可以看到输出信息:
219+
220+
![](/st0052-01.png)
221+
222+
一切正常!
223+
224+
## 9. 总结展望
225+
226+
目前流行 Arduino 单片机的配置还是比较低的,可能难以运行 WASM 程序。不过可以乐观估计 Arduino Nano 33 将会很快普及。而且,Wasm3 不仅仅可以支持 Arduino,还可以支持树莓派 Pico(淘宝价格30元)。因此,从长远看 WASM 是一个兼具灵活性和性价比的可选方案。

0 commit comments

Comments
 (0)