本帖最后由 秋雪 于 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的虚拟环境,可以通过直接挂载谷歌硬盘来读写文件。

image.png
(如运行时为GPU,建议点击更改运行时类型-切换为CPU环境,从而得到更高的配额)

image.png




安装GCC
(经确认)由于colab已经包含make和Python环境,只需要安装gcc工具链即可。
理论上可以通过sudo apt-get update和sudo apt-get install gcc-arm-none-eabi来更新软件源并安装工具链,实际测试发现安装好的工具链版本较旧,不使用apt安装gcc,使用了如下代码(作为colab的特色,左侧为可隐藏的代码,右侧为更为美观的面板),后续可以通过修改右侧文本框内的文件名来修改工具链版本
image.png

代码:
# @title 安装gcc
  • # @markdown 从 [https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads#panel1a](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads#panel1a) 下载工具链
  • %cd /content/
  • toolchain_name = "arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi" # @param {"type":"string"}
  • 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

  • # $ tar xJf arm-gnu-toolchain-14.2.rel1-x86_64-<TRIPLE>.tar.xz -C /path/to/install/dir

  • # 设置路径,然后调用工具链,如下所示:
  • import os
  • os.environ['PATH'] += ":/content/"+toolchain_name+"/bin"
  • # %env PATH=$PATH:/content/$toolchain_name/bin

  • # $ export PATH=$PATH:<install-dir>/arm-gnu-toolchain-14.2.rel1-<HOST_ARCH>-aarch64-none-elf/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直接屏蔽了国外连接,比较不要脸)
    image.png
    因此需要使用曲折的办法:colne代码到本地,再同步到谷歌硬盘,colab从谷歌硬盘加载代码。
    (点击箭头指示的图标,可以挂载、卸载谷歌硬盘到运行环境中。运行环境在/content/目录下,挂载位置在运行环境的derive/MyDrive目录中)




    目前我使用了直接打压缩包保存不含submodule的代码到谷歌硬盘的tmp目录,加载谷歌硬盘后解压代码再下载submodule的方式,从而节约宝贵的空间。
    # @title 复制和解压micropython
  • %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
  • 复制代码


    检查环境
    简单打印了环境信息
    # @title 打印信息
  • !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+ #1 SMP PREEMPT_DYNAMIC Thu Jun 27 21:05:47 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux

  • 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.
  • 复制代码


    编译
    我写了简单的编译代码,同样提供了简单的文本框
    # @title 编译
  • board_name = "FR3068E-C_EVB1.0" # @param {"type":"string","placeholder":"FR3068E-C_EVB1.0"}

  • !make B0ARD={board_name} -j8
  • 复制代码
    列出编译结果是不必要的动作,但是可以快速确认是否编译成功
    image.png

    生成烧录文件
    编译结果不能直接用于烧录,需要经过后处理(这也是仓库需要Python的原因之一)
    使用如下代码可以完成后处理,如果处理成功则浏览器自动弹出下载文件

    image.png
    # @title 生成烧录文件
  • !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()返回信息正常
    image.png

    简单测一下数学计算和字符串打印
    image.png

    由于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编译不是一个新的概念,在有限条件、有限成本下玩起来也是一个有意义的事情,希望大家一起交流经验呀