Cygnus构建记录

固件开发环境设置

固件(Firmware)就是写入 ROM (只读存储器)中的程序,固件担任着一个系统最基础最底层工作,直接控制硬件。它位于硬件和应用软件之间。它是写入设备存储器(通常是闪存或 ROM)中的程序,负责控制硬件的基本功能和运行逻辑。

我这里使用的固件是ZMK,开发有什么问题,可以直接翻官方文档。使用ZMK主要是看重它支持无线能力,这对我构建一个无线分体键盘来说还挺关键的,可选的选项其实也不多,所以就使用ZMK咯。

ZMK环境配置

本地开发环境请参考官方原生开发环境构建指南,也有容器型的开发环境,但我觉得没必要。首先先把仓库克隆下来:

1
git clone https://github.com/zmkfirmware/zmk.git

然后进入仓库。

1
cd zmk

获取 Zephyr 并安装 Python 依赖项

  1. 使用 apt 安装 Python venv 包:

    1
    sudo apt install python3-venv
  2. 创建一个新的虚拟环境并激活它:

    1
    2
    python3 -m venv .venv
    source .venv/bin/activate

    一旦激活,你的 shell 将会有一个前缀为 (.venv) 的标识。随时可以通过运行 deactivate 来关闭虚拟环境。

  3. 安装west:

    1
    pip install west
  4. 初始化应用并更新包含Zephyr的模块:

    1
    2
    west init -l app/
    west update

    这个部分会下载若干个Github仓库,需要科学上网。

  5. 导出一个 Zephyr CMake 包。这使得 CMake 能够自动加载构建 Zephyr 应用程序所需的样板代码:

    1
    west zephyr-export
  6. 安装 Zephyr 所列出的额外依赖项:

    1
    pip install -r zephyr/scripts/requirements-base.txt

安装 Zephyr SDK

参考Zephyr SDK 安装指南

  1. 下载并验证 Zephyr SDK 包:

    1
    2
    3
    cd ~
    wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.3/zephyr-sdk-0.16.3_linux-x86_64.tar.xz
    wget -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.3/sha256.sum | shasum --check --ignore-missing

    如果主机架构是 64 位 ARM(例如,Raspberry Pi,但我感觉应该个人用户应该没有吧…),需要将 x86_64 替换为 aarch64 以下载 64 位 ARM Linux SDK。

  2. 提取 Zephyr SDK 包存档:

    1
    tar xvf zephyr-sdk-0.16.3_linux-x86_64.tar.xz
  3. 运行 Zephyr SDK 捆绑包设置脚本:

    1
    2
    cd zephyr-sdk-0.16.3
    ./setup.sh

    这个脚本只需要执行一次即可。如果后续移动了Zeohyr SDK的位置,那么需要重新运行setup脚本。

  4. 安装 udev 规则,以便您可以以普通用户身份刷写大多数 Zephyr 板

    1
    2
    sudo cp ~/zephyr-sdk-0.16.3/sysroots/x86_64-pokysdk-linux/usr/share/openocd/contrib/60-openocd.rules /etc/udev/rules.d
    sudo udevadm control --reload

固件编写

Cygnus是可以使用Corne的固件的。但是如果要进行个性化的相关设置,你可以自定义固件。首先复制一份app/boards/shields/corne的文件夹,然后把文件夹和corne相关的,都改成cygnus

文件修改

文件夹中的这几个文件需要额外修改:

  • cygnus.zmk.yml:修改idname即可:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    file_format: "1"
    id: cygnus
    name: Cygnus
    type: shield
    url: https://github.com/foostan/crkbd/
    requires: [pro_micro]
    exposes: [i2c_oled]
    features:
    - keys
    - display
    - underglow
    - studio
    siblings:
    - cygnus_left
    - cygnus_right
  • Kconfig.shield中的内容也需要修改:

    1
    2
    3
    4
    5
    6
    config SHIELD_CYGNUS_LEFT
    def_bool $(shields_list_contains,cygnus_left)

    config SHIELD_CYGNUS_RIGHT
    def_bool $(shields_list_contains,cygnus_right)

  • 还有最重要的cygnus.keymap的修改,不过我们这里先不过多展开,会在后面的使用体验中进行介绍与修改。

固件编译与下载

主要参考资料在这:Building and Flashing | ZMK Firmware。我们需要进入到zmk/app目录下进行操作。Cygnus由于是使用两块板子的附加形式,因此编译参考选择参考Addon MCU部分。我们使用的配置如下:

  • MCU板子: nice_nano_v2
  • 键盘PCB: cygnus_left & cygnus_left

编译左手固件的命令如下:

1
west build -b nice_nano_v2 -- -DSHIELD=cygnus_left

当在之前构建过板子和/或屏蔽后构建新的板子和/或屏蔽时,可能需要启用纯净构建选项。此选项会在重新生成文件之前删除构建目录中的所有现有文件,并可以通过在命令中添加 –pristine 或 -p 来启用:

1
west build -p -b nice_nano_v2 -- -DSHIELD=cygnus_left

默认情况下, build 命令会输出一个名为 zmk.uf2 的 .uf2 文件,因此连续构建左右两侧会覆盖左侧的固件。此外,还需要对每一侧进行 pristine 构建以确保使用正确的文件。为了避免每次都需要 pristine 构建并且分开左右两侧的构建文件,我们建议为每一半设置单独的构建目录。使用 -d 参数并在构建右侧时将其放入 build/right 中完成此操作。先编译右手:

1
west build -d build/right -b nice_nano_v2 -- -DSHIELD=cygnus_right

然后编译左手固件:

1
west build -d build/left -b nice_nano_v2 -- -DSHIELD=cygnus_left

这会在 build 目录下生成 leftright 子文件夹,并生成两个单独的 .uf2 文件。后续可以用一个脚本把编译成功的固件重命名+打包压缩:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/sh
echo "Start processing Firmware build."
mkdir -p zmk-firmware
cd ./app;

echo "Start processing left-hand Firmware.";
west build -d build/left -b nice_nano_v2 -- -DSHIELD=cygnus_left;
echo "Start processing right-hand Firmware.";
west build -d build/right -b nice_nano_v2 -- -DSHIELD=cygnus_right;

cd ../;
mv ./app/build/left/zephyr/zmk.uf2 ./zmk-firmware/left.uf2;
mv ./app/build/right/zephyr/zmk.uf2 ./zmk-firmware/right.uf2;
echo "Build tasks finished. See ./zmk-firmware for details."

这样就可以在zmk目录下运行指令,并在zmk-firmware文件夹下找到对应的左右固件的二进制文件了。

下载到NICENANO也很简单,短接RST和GND两次,然后就会在电脑上显示一个外部设备了。把刚刚的.uf2文件拖进去,等待文件传输完成,如果出现了如下异常:

{EFBDC695-E1E2-43D1-8695-D6B04E3E827C}

不用担心,直接跳过就好,这个时候外部设备应该也关闭了和主机的传输。

3x5键位的设置

参考这篇文章进行设置。具体的一些行为编写如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
td_mt_l: tap_dance_mod_tap {
compatible = "zmk,behavior-tap-dance";
#binding-cells = <0>;
tapping-term-ms = <200>;
bindings = <&mt LCTRL SPACE>, <&kp ESC>;
}

ls: layer_switch {
compatible = "zmk,behavior-hold-tap";
#binding-cells = <2>;
flavor = "tap-preferred";
tapping-term-ms = <200>;
quick-tap-ms = <200>;
require-prior-idle-ms = <125>;
bindings = <&mo>, <&kp>;
};