本帖最后由 秋雪 于 2025-2-13 01:42 编辑
前言
看到选题我才第一次了解到MicroPython。MicroPython是一种专为微控制器和嵌入式设备设计的Python实现,能够在单片机非常有限的资源上运行python这太让我震惊了。由于python可以不经过编译就能直接运行,相比c语言更接近高级语言的书写习惯,同时又能直接控硬件接口(如GPIO、I2C、SPI等),降低了开发门槛,非常适合初学者或希望快速实现功能。
环境准备
根据直播资料,micropython建议在wsl/LINUX + PYTHON环境进行编译。而我常用操作系统为window;得益于AI技术的发展,有大量平台提供免费或者低价的Linux + python环境的jupyter notebook环境,因此尝试使用基于Linux + python环境的jupyter notebook进行开发和编译。与单纯shell交互和shell脚本环境不同,jupyter既是可以分段执行的代码,也是记录信息的笔记本,更加直观方便
本人使用了谷歌提供的免费colab(一种魔改的jupyter)作为实操。谷歌免费提供了约为2c12G的虚拟环境,可以通过直接挂载谷歌硬盘来读写文件。
(如运行时为GPU,建议点击更改运行时类型-切换为CPU环境,从而得到更高的配额)
安装GCC
(经确认)由于colab已经包含make和Python环境,只需要安装gcc工具链即可。
理论上可以通过sudo apt-get update和sudo apt-get install gcc-arm-none-eabi来更新软件源并安装工具链,实际测试发现安装好的工具链版本较旧,不使用apt安装gcc,使用了如下代码(作为colab的特色,左侧为可隐藏的代码,右侧为更为美观的面板),后续可以通过修改右侧文本框内的文件名来修改工具链版本
代码:
%cd /content/
toolchain_name = "arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi"
toolchain_ver = toolchain_name.split("-")[3]
print("toolchain_name: ",toolchain_name)
print("toolchain_ver: ",toolchain_ver)
!wget https://developer.arm.com/-/media/Files/downloads/gnu/{toolchain_ver}/binrel/arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi.tar.xz
!tar -xf {toolchain_name}.tar.xz
import os
os.environ['PATH'] += ":/content/"+toolchain_name+"/bin"
!echo $PATH
!ls -l /content/{toolchain_name}/bin 复制代码运行速度很快的,结果如下
/content
toolchain_name: arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi
toolchain_ver: 14.2.rel1
--2025-02-12 16:38:29-- https://developer.arm.com/-/media/Files/downloads/gnu/14.2.rel1/binrel/arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi.tar.xz
Resolving developer.arm.com (developer.arm.com)... 23.46.228.175, 23.46.228.165
Connecting to developer.arm.com (developer.arm.com)|23.46.228.175|:443... connected.
HTTP request sent, awaiting response... 302 Moved Temporarily
Location: https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu/14.2.rel1/binrel/arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi.tar.xz [following]
--2025-02-12 16:38:30-- https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu/14.2.rel1/binrel/arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi.tar.xz
Resolving armkeil.blob.core.windows.net (armkeil.blob.core.windows.net)... 20.209.15.139
Connecting to armkeil.blob.core.windows.net (armkeil.blob.core.windows.net)|20.209.15.139|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 149739784 (143M) [application/octet-stream]
Saving to: ‘arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi.tar.xz.1’
arm-gnu-toolchain-1 100%[===================>] 142.80M 5.60MB/s in 28s
2025-02-12 16:38:59 (5.06 MB/s) - ‘arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi.tar.xz.1’ saved [149739784/149739784]
/opt/bin:/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/tools/node/bin:/tools/google-cloud-sdk/bin:/content/arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi/bin:/content/arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi/bin
total 94940
-rwxr-xr-x 1 1297 1297 1073248 Dec 4 06:00 arm-none-eabi-addr2line
-rwxr-xr-x 2 1297 1297 1107032 Dec 4 06:00 arm-none-eabi-ar
-rwxr-xr-x 2 1297 1297 1880048 Dec 4 06:00 arm-none-eabi-as
-rwxr-xr-x 2 1297 1297 2425816 Dec 4 07:22 arm-none-eabi-c++
-rwxr-xr-x 1 1297 1297 1068064 Dec 4 06:00 arm-none-eabi-c++filt
-rwxr-xr-x 1 1297 1297 2425784 Dec 4 07:22 arm-none-eabi-cpp
-rwxr-xr-x 1 1297 1297 52624 Dec 4 06:00 arm-none-eabi-elfedit
-rwxr-xr-x 2 1297 1297 2425816 Dec 4 07:22 arm-none-eabi-g++
-rwxr-xr-x 2 1297 1297 2421640 Dec 4 07:22 arm-none-eabi-gcc
-rwxr-xr-x 2 1297 1297 2421640 Dec 4 07:22 arm-none-eabi-gcc-14.2.1
-rwxr-xr-x 1 1297 1297 60976 Dec 4 07:22 arm-none-eabi-gcc-ar
-rwxr-xr-x 1 1297 1297 60976 Dec 4 07:22 arm-none-eabi-gcc-nm
-rwxr-xr-x 1 1297 1297 60976 Dec 4 07:22 arm-none-eabi-gcc-ranlib
-rwxr-xr-x 1 1297 1297 1528184 Dec 4 07:22 arm-none-eabi-gcov
-rwxr-xr-x 1 1297 1297 1314568 Dec 4 07:22 arm-none-eabi-gcov-dump
-rwxr-xr-x 1 1297 1297 1340440 Dec 4 07:22 arm-none-eabi-gcov-tool
-rwxr-xr-x 1 1297 1297 10505880 Dec 4 06:02 arm-none-eabi-gdb
-rwxr-xr-x 1 1297 1297 4627 Dec 4 06:02 arm-none-eabi-gdb-add-index
-rwxr-xr-x 1 1297 1297 4627 Dec 4 06:04 arm-none-eabi-gdb-add-index-py
-rwxr-xr-x 1 1297 1297 11168760 Dec 4 06:04 arm-none-eabi-gdb-py
-rwxr-xr-x 1 1297 1297 2426200 Dec 4 07:22 arm-none-eabi-gfortran
-rwxr-xr-x 1 1297 1297 1140968 Dec 4 06:00 arm-none-eabi-gprof
-rwxr-xr-x 4 1297 1297 1892984 Dec 4 06:00 arm-none-eabi-ld
-rwxr-xr-x 4 1297 1297 1892984 Dec 4 06:00 arm-none-eabi-ld.bfd
-rwxr-xr-x 1 1297 1297 36625664 Dec 4 07:22 arm-none-eabi-lto-dump
-rwxr-xr-x 2 1297 1297 1093120 Dec 4 06:00 arm-none-eabi-nm
-rwxr-xr-x 2 1297 1297 1229912 Dec 4 06:00 arm-none-eabi-objcopy
-rwxr-xr-x 2 1297 1297 1905336 Dec 4 06:00 arm-none-eabi-objdump
-rwxr-xr-x 2 1297 1297 1107032 Dec 4 06:00 arm-none-eabi-ranlib
-rwxr-xr-x 2 1297 1297 1095536 Dec 4 06:00 arm-none-eabi-readelf
-rwxr-xr-x 1 1297 1297 1073344 Dec 4 06:00 arm-none-eabi-size
-rwxr-xr-x 1 1297 1297 1077544 Dec 4 06:00 arm-none-eabi-strings
-rwxr-xr-x 2 1297 1297 1229912 Dec 4 06:00 arm-none-eabi-strip 复制代码 复刻代码
官方提供了一份移植范例,http://gitee.com/gumpyang/micropython_freqchip.git
理论上可以通过git命令直接clone代码到colab,实际上12月也是可以这样操作的,但是2月我发现colab环境无法再从gitee clone代码(从经验判断是gitee直接屏蔽了国外连接,比较不要脸)
因此需要使用曲折的办法:colne代码到本地,再同步到谷歌硬盘,colab从谷歌硬盘加载代码。
(点击箭头指示的图标,可以挂载、卸载谷歌硬盘到运行环境中。运行环境在/content/目录下,挂载位置在运行环境的derive/MyDrive目录中)
目前我使用了直接打压缩包保存不含submodule的代码到谷歌硬盘的tmp目录,加载谷歌硬盘后解压代码再下载submodule的方式,从而节约宝贵的空间。
%cd /content/
!cp /content/drive/MyDrive/tmp/micropython_freqchip.zip ./
!unzip micropython_freqchip.zip
%cd /content/micropython_freqchip
!git submodule init
!git submodule update
%cd /content/micropython_freqchip/ports/freqchip 复制代码
检查环境
简单打印了环境信息
!echo === file path ===
!pwd
print("\n=== folder list ===")
!ls -ld boards/*/
print("\n=== git branch ===")
!git status
print("\n=== system info ===")
!uname -a
!echo
!lsb_release -a
print("\n=== make version ===")
!make --version
print("\n=== gcc version ===")
!arm-none-eabi-gcc --version 复制代码
打印结果
=== file path ===
/content/micropython_freqchip/ports/freqchip
=== folder list ===
drwxr-xr-x 2 root root 4096 Feb 11 21:01 boards/FR3068E-C_EVB1.0/
drwxr-xr-x 2 root root 4096 Feb 11 21:01 boards/fr8008gp/
=== git branch ===
On branch freqchip_v1.23.0
Your branch is up to date with 'origin/freqchip_v1.23.0'.
nothing to commit, working tree clean
=== system info ===
Linux 4bf935fc24fd 6.1.85+
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04.4 LTS
Release: 22.04
Codename: jammy
=== make version ===
GNU Make 4.3
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
=== gcc version ===
arm-none-eabi-gcc (Arm GNU Toolchain 14.2.Rel1 (Build arm-14.52)) 14.2.1 20241119
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
复制代码
编译
我写了简单的编译代码,同样提供了简单的文本框
board_name = "FR3068E-C_EVB1.0"
!make B0ARD={board_name} -j8 复制代码列出编译结果是不必要的动作,但是可以快速确认是否编译成功
生成烧录文件
编译结果不能直接用于烧录,需要经过后处理(这也是仓库需要Python的原因之一)
使用如下代码可以完成后处理,如果处理成功则浏览器自动弹出下载文件
!python mcu/fr30xx/post_process.py {binfile} .
from google.colab import files
if(os.path.exists(binfile+"_burn.bin")):
files.download(binfile+"_burn.bin")
print("Start download")
else:
print("No file") 复制代码
烧录
PDF说明文件讲解很详细,不再赘述。需要特别指出的是两个USB都必须连接才能完成烧录动作。micro只通讯,Type-C只供电
功能测试
查看资料得知micropython通常使用thonny进行调试Python代码。但是我实际使用发现这个软件并不好用,干脆直接使用sscom串口助手了。
上电直接输出启动信息,输入help()返回信息正常
简单测一下数学计算和字符串打印
由于micropython不会包含太多软件包,不好测试Python的其他功能,我在AI的帮助下写了输出高电平的代码尝试通过硬件基操点灯
[01:21:28.827]发→◇from machine import Pin
□
[01:21:28.832]收←◆from machine import Pin
[01:26:25.065]发→◇led = Pin(1, Pin.OUT)
□
[01:26:25.073]收←◆led = Pin(1, Pin.OUT)
Traceback (most recent call last):
File "", in
ValueError: Pin id must be tuple of ("GPIO_x", pin#)
>>>
[01:25:06.364]发→◇led = Pin(("GPIO_D", 15), Pin.OUT)
□
[01:25:06.372]收←◆led = Pin(("GPIO_D", 15), Pin.OUT)
Traceback (most recent call last):
File "", in
ValueError: invalid port
>>> 复制代码
根据错误信息ValueError: invalid port找到代码,发现wanted_port 直接赋值了 NULL 导致下一行直接返回错误信息。参考port目录下其他board的代码,发现各个board差异较大,板卡点灯不可一蹴而就
mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// get the wanted port
if (!mp_obj_is_type(args[0], &mp_type_tuple)) {
mp_raise_ValueError(MP_ERROR_TEXT("Pin id must be tuple of ("GPIO_x", pin#)"));
}
mp_obj_t *items;
mp_obj_get_array_fixed_n(args[0], 2, &items);
const char *drv_name = mp_obj_str_get_str(items[0]);
int wanted_pin = mp_obj_get_int(items[1]);
const struct device *wanted_port = NULL; // device_get_binding(drv_name);
if (!wanted_port) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid port"));
}
machine_pin_obj_t *pin = m_new_obj(machine_pin_obj_t);
pin->base = machine_pin_obj_template;
pin->port = wanted_port;
pin->pin = wanted_pin;
if (n_args > 1 || n_kw > 0) {
// pin mode given, so configure this GPIO
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
machine_pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args);
}
return (mp_obj_t)pin;
} 复制代码
总结
我知道有大佬通过移植micropython项目的代码到富芮坤的sdk中的方式已经实现了播放器的功能,但是这显然和常规移植是不一样的。所以说给新芯片移植microPython,后续还需要花大力才能完善。
在此非常感谢面包板社区和富芮坤举办的本次活动,能够有幸体验到本次国产芯片的使用,算是尝尝鲜了。希望国产芯越来越强,资料越来越完善,这也需要大家一同学习进步。
使用server和ci编译不是一个新的概念,在有限条件、有限成本下玩起来也是一个有意义的事情,希望大家一起交流经验呀