跳到主要内容

NanoFW 开发环境搭建

核心概念澄清​

nanoFramework 是一个允许使用 C# 编写嵌入式应用程序的跨平台框架。开发流程分为两个层面:

  • 底层固件:nanoFramework 运行时,提供 C# 与硬件之间的桥梁(本文重点)
  • 应用层开发:使用 C# 编写业务逻辑

获取固件有两种方式:

  1. 官方预编译固件(推荐):使用 nanoff 工具一键下载刷入,适合大多数开发者
  2. 自行编译固件(高级):从 nf-interpreter 源码编译,适合需要定制底层功能的开发者

准备工作​

1. 安装 .NET SDK​

nanoff 是基于 .NET 的全局工具,必须先安装 .NET 环境。

  • 前往 微软官网 下载并安装 .NET 10.0 SDK(或其他版本)
  • 打开 PowerShell 验证安装:
dotnet --version

显示版本号(如 10.0.xxx)即表示安装成功。

2. 安装 nanoff 工具​

nanoff 是 nanoFramework 固件刷写和管理工具,执行以下命令安装:

dotnet tool install -g nanoff

验证安装:

nanoff --version

提示:如果提示 "nanoff 不是内部命令",请将 .NET 全局工具路径 添加到系统环境变量 PATH:

  • Windows: %USERPROFILE%\.dotnet\tools
  • Mac/Linux: ~/.dotnet/tools

固件获取方式​

方式一:使用官方预编译固件(推荐)​

此方法简单快捷,适合大多数开发者使用官方稳定版本。官方固件经过严格测试,稳定性有保障。

官方固件仓库:nanoFramework 官方预编译固件托管在 cloudsmith.io,你也可以直接访问该网站手动下载固件文件。

查看可用固件版本​

打开 PowerShell,执行以下命令查看支持的固件版本:

# 查看 ESP32 系列固件
nanoff --listtargets --platform esp32

# 查看所有平台的固件
nanoff --listtargets

步骤 1:进入下载模式​

ESP32 必须进入下载模式才能刷写固件:

  1. 按住开发板上的 BOOT 键不放
  2. 开发板上电,烧录程序
  3. 松开 BOOT 键

步骤 2:查看可用串口​

在刷写前,先查看当前可用的串口号:

nanoff --listports

重要提示:ESP32-S3 有两套运行模式,对应不同的串口:

  • 下载模式:按住 BOOT 键进入,显示一个 COM 端口(用于刷写固件)
  • 正常运行模式:正常启动,显示另一个 COM 端口(用于程序调试)

刷写固件时必须使用下载模式对应的串口。

步骤 3:刷写官方固件​

在 PowerShell 中执行以下命令(将 COM5 替换为你的下载模式串口号):

# 刷写完整功能版本,--masserase 选项会擦除所有数据,包括固件和配置
nanoff --target ESP32_S3_ALL --serialport COM5 --update --masserase

步骤 4:验证刷写结果​

底层固件下载

执行后 nanoff 会自动从 GitHub 下载最新固件并烧录到开发板。当看到 Flashing firmware...OK 提示时,表示刷写成功。

此时开发板会自动重启,已具备运行 C# 代码的能力。下次开发时无需再进入下载模式,直接连接即可。

方式二:自行编译底层固件(高级)​

适合需要定制底层功能、调试内核或学习底层原理的高级开发者。

步骤 1:克隆 nf-interpreter 源码​

git clone https://github.com/nanoframework/nf-interpreter.git
cd nf-interpreter
git submodule update --init --recursive

步骤 2:安装 ESP-IDF​

建议安装 ESP-IDF 5.5.4 版本,这是 nanoframework 官方编译 ESP32 固件时使用的版本。

版本依据来自官方 CI 配置文件:azure-pipelines.yml

ESP-IDF所需版本

步骤 3:安装 SRecord 工具​

下载并安装 SRecord 工具,请记住安装路径(默认安装路径通常为 C:\Program Files\SRecord\bin),后续配置编译环境时需要用到。

步骤 4:配置编译环境​

4.1 生成配置文件​

进入 config 目录,复制模板文件生成真实配置:

cd nf-interpreter\config
copy user-tools-repos.TEMPLATE.json user-tools-repos.json
copy user-prefs.TEMPLATE.json user-prefs.json
copy user-kconfig.conf.TEMPLATE user-kconfig.conf
4.2 配置编译工具​

使用 VS Code 打开 user-tools-repos.json,进行以下修改:

  1. 配置 SRecord 路径(添加到文件中):

    "TOOL_SRECORD_PREFIX": "C:/Program Files/SRecord/bin"
  2. 修改 ESP-IDF 路径:

    • 找到 "ESP32_IDF_PATH": "<absolute-path-to-the-IDF-folder-mind-the-forward-slashes>"
    • 替换为实际路径(注意使用正斜杠 /):
      "ESP32_IDF_PATH": "C:/Espressif/.espressif/v5.5.4/esp-idf"
  3. 修改配置名称:

    • 将第 5 行 "name": "user-tools-repos-local" 改为 "name": "user-tools-repos"
  4. 其他以 <path-to-... 开头的变量保持默认值或设置为 null 即可。

修改user-tools-repos.json文件

4.3 添加自定义板卡配置​

为 YF3300_ESP32S3 创建配置文件:

cd nf-interpreter
copy targets\ESP32\defconfig\ESP32_S3_ALL_defconfig targets\ESP32\defconfig\YF3300_ESP32S3_defconfig

打开 targets/ESP32/CMakePresets.json,在 configurePresets 数组末尾添加:

{
"name": "YF3300_ESP32S3",
"inherits": [ "xtensa-esp32s3-preset", "user-tools-repos", "user-prefs" ],
"hidden": false,
"cacheVariables": {
"TARGET_NAME": "${presetName}",
"NF_TARGET_DEFCONFIG": "targets/ESP32/defconfig/YF3300_ESP32S3_defconfig"
}
}

配置阶段的预设configurePresets.png

在 buildPresets 数组末尾添加:

{
"inherits": "base-user",
"name": "YF3300_ESP32S3",
"displayName": "YF3300_ESP32S3",
"configurePreset": "YF3300_ESP32S3"
}

编译阶段的预设buildPresets.png

步骤 5:编译固件​

5.1 激活 ESP-IDF 环境​

在开始编译前,请确保已激活 ESP-IDF 5.5.4 环境。打开 IDF_v5.5.4_Powershell 终端。

5.2 检查预设配置​
cd nf-interpreter
cmake --list-presets

确认输出中包含 YF3300_ESP32S3。

5.3 生成构建树​
cmake --preset YF3300_ESP32S3 -B build
5.4 修复 ESP-IDF v5.5.4 RAS 服务编译错误​

问题说明:ESP-IDF v5.5.4 中的 ble_svc_ras.c(RAS 服务,用于测距/信道探测)仅支持 ESP32-C6,并非普通蓝牙必需组件,ESP32-S3 编译时会报错。官方文档参考:ble_chan_sound_reflector

解决方案:在项目根目录的 CMakeLists.txt 文件末尾添加以下代码:

# Fix ESP-IDF v5.5.4 NimBLE RAS service compile error for ESP32-S3
if(TARGET __idf_bt)
get_target_property(BT_SRCS __idf_bt SOURCES)
list(FILTER BT_SRCS EXCLUDE REGEX ".*ble_svc_ras\\.c$")
set_target_properties(__idf_bt PROPERTIES SOURCES "${BT_SRCS}")
endif()

原理说明:

  • if(TARGET __idf_bt):判断蓝牙组件是否存在,关闭蓝牙时自动失效
  • list(FILTER ... EXCLUDE ...):从蓝牙组件源文件列表中剔除 ble_svc_ras.c
  • 此方法不修改 ESP-IDF 源码,仅对当前项目生效,升级 ESP-IDF 后自动兼容
5.5 执行编译​
# 清理旧构建(首次编译可跳过)
Remove-Item -Path sdkconfig -Force -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force build -ErrorAction SilentlyContinue

# 重新生成构建树
cmake --preset YF3300_ESP32S3 -B build

# 开始编译(耗时较长,请耐心等待)
cmake --build build

步骤 6:刷写自定义固件​

6.1 编译产物说明​

编译完成后,build 目录下会生成以下固件文件:

文件类型路径说明
Bootloaderbuild/bootloader/bootloader.bin引导程序
分区表build/partitions_*.bin根据 Flash 大小选择
主固件build/nanoCLR.binnanoFramework 核心固件

分区表选择建议:

  • 4MB 闪存:partitions_4mb.bin
  • 8MB 闪存:partitions_8mb.bin
  • 16MB 闪存:partitions_16mb.bin
  • 32MB 闪存:partitions_32mb.bin
6.2 烧录固件(推荐)​

将开发板进入下载模式后,执行以下命令烧录:

cd nf-interpreter
cmake --build build --target flash
6.3 手动使用 esptool(备选)​

若需手动控制,可参考 build 目录下的 flasher_args.json/flash_args,大致命令形式(以 COM4 为例):

esptool.py -p COM4 -b 460800 ^
--before default_reset --after hard_reset ^
-f esp32s3 ^
--flash_mode dio --flash_freq 80m --flash_size detect ^
0x0 build/bootloader/bootloader.bin ^
0x8000 build/partition_table/partition-table.bin ^
0x10000 build/nanoCLR.bin

配置 Visual Studio 开发环境​

1. 安装 Visual Studio​

  • 下载并安装 Visual Studio 2026(社区版免费):Visual Studio 官网
  • 安装时勾选以下工作负载:
    • .NET 桌面开发
    • 使用 C++ 的桌面开发(用于某些底层调试工具)

2. 安装 nanoFramework 扩展​

  1. 打开 Visual Studio
  2. 进入「扩展」→「管理扩展」
  3. 在搜索框中搜索 nanoFramework Visual Studio Extension

下载nanoFramework扩展

  1. 安装 nanoFramework Visual Studio Extension
  2. 重启 Visual Studio

创建 点亮LED 案例​

1. 创建 nanoFramework 项目​

  1. 打开 Visual Studio

  2. 选择「创建新项目」

  3. 搜索并选择 Blank Application 模板
    创建项目_步骤一

  4. 设置项目名称(如 BlinkLed)和保存路径

  5. 点击「创建」

  6. 打开 nanoFramework Visual Studio Extension 扩展,选择 ESP32-S3 作为目标平台。 打开Extension扩展窗口

2. 编写代码​

安装必要的 NuGet 包​

本项目需要使用 GPIO 控制功能,需安装 nanoFramework.System.Device.Gpio 包:

  1. 在 Visual Studio 中右键点击项目,选择「管理 NuGet 程序包」
  2. 在「浏览」选项卡中搜索 nanoFramework.System.Device.Gpio
  3. 选择最新稳定版本并点击「安装」

修改 Program.cs​

打开 Program.cs,替换为以下代码:

using System;
using System.Diagnostics;
using System.Threading;
using System.Device.Gpio;

namespace BlinkLed
{
// 硬件引脚定义类,方便集中管理
public class HardwarePins
{
public const int UserLED = 39; // 用户指示灯,低电平点亮
public const int ComLED = 40; // 通信灯,低电平点亮

}

public class Program
{
public static void Main()
{
Debug.WriteLine("YFESP32S3 点灯示例启动...");
// 1. 创建 GPIO 控制器
GpioController controller = new GpioController();

// 2. 打开 GPIO39 和 GPIO40 引脚,设置为输出模式
controller.OpenPin(HardwarePins.UserLED, PinMode.Output);
controller.OpenPin(HardwarePins.ComLED, PinMode.Output);

// 3. 循环执行
while (true)
{
controller.Write(HardwarePins.UserLED, PinValue.High);
controller.Write(HardwarePins.ComLED, PinValue.Low);
Thread.Sleep(1000);

controller.Write(HardwarePins.UserLED, PinValue.Low);
controller.Write(HardwarePins.ComLED, PinValue.High);
Thread.Sleep(1000);
}
}
}
}

3. 部署与调试​

确保开发板正常连接到电脑(不需要进入下载模式)。

在 .NET nanoFramework Extension 窗口中:

  1. 确保已选中目标设备
  2. 点击运行按钮

部署


进阶学习​