RIOT 操作系统 Arduino Nano ESP32 板级支持详解:引脚映射、烧录流程与 STDIO 配置
【免费下载链接】RIOTRIOT - The friendly OS for IoT项目地址: https://gitcode.com/GitHub_Trending/riot/RIOT
本文基于 RIOT 仓库中 Arduino Nano ESP32 的板级支持文档与源码,完整讲解该板在 RIOT 中的硬件能力、GPIO/外设默认配置表、USB Serial/JTAG 烧录流程(含下载模式手动进入方法),以及 STDIO 在 USB Serial/JTAG、tinyUSB 与 UART 三种通道间的自动选择机制。读完后,你可以在 RIOT 中正确配置该板的 ADC、PWM、SPI、I2C 与 UART 外设,独立完成固件烧录,并按需切换 STDIO 输出通道。
一、板子概述:Arduino Nano 形态的 ESP32-S3 开发板
Arduino Nano ESP32 是一块采用 Arduino Nano 板型的 ESP32-S3 开发板,其核心功能由板载的 u-Blox NORA-W106 模块提供。根据 boards/arduino-nano-esp32/doc.md 的描述,该板的主要特性包括:
- ESP32-S3 SoC,支持 2.4 GHz WiFi 802.11b/g/n 以及 Bluetooth 5 / BLE
- 8 MByte 嵌入式 QSPI RAM(PSRAM)
- 16 MByte Flash
- 带独立红、绿、蓝三色 LED 的 RGB 指示灯
- 原生 USB 接口与 USB Serial/JTAG 接口
在 RIOT 中,该板对应的 CPU 型号为esp32s3r8,即带 8 MB QSPI PSRAM 的 ESP32-S3 变体。这一点在 boards/arduino-nano-esp32/Makefile.features 中有明确定义:
# the board uses a ESP32-S3 with embedded 8MB QSPI PSRAM and a 16MB QSPI Flash CPU_MODEL = esp32s3r8 # common board and CPU features include $(RIOTBOARD)/common/esp32s3/Makefile.features同时,boards/arduino-nano-esp32/Kconfig 中的BOARD_ARDUINO_NANO_ESP32选项会自动选择BOARD_COMMON_ESP32S3与CPU_MODEL_ESP32S3_R8,保证了 Kconfig 体系下的默认 CPU 型号与 Make 系统一致。
板级提供的功能特性
从 boards/arduino-nano-esp32/Makefile.features 可以看到,RIOT 为该板声明了如下功能特性:
# peripherals provided by the board FEATURES_PROVIDED += periph_adc FEATURES_PROVIDED += periph_i2c FEATURES_PROVIDED += periph_pwm FEATURES_PROVIDED += periph_spi FEATURES_PROVIDED += periph_usbdev # other features provided by the board FEATURES_PROVIDED += arduino_analog FEATURES_PROVIDED += arduino_i2c FEATURES_PROVIDED += arduino_pins FEATURES_PROVIDED += arduino_pwm FEATURES_PROVIDED += arduino_spi FEATURES_PROVIDED += arduino_uart FEATURES_PROVIDED += esp_jtag FEATURES_PROVIDED += highlevel_stdio FEATURES_PROVIDED += tinyusb_device这些特性可以分成三类:
- 标准外设接口:
periph_adc、periph_i2c、periph_pwm、periph_spi、periph_usbdev,对应 RIOT 的统一外设抽象层; - Arduino 引脚兼容层:
arduino_analog、arduino_i2c、arduino_pins、arduino_pwm、arduino_spi、arduino_uart,使板级引脚可以按 Arduino 命名习惯使用,映射关系定义在 boards/arduino-nano-esp32/include/arduino_iomap.h; - USB 相关能力:
esp_jtag(USB Serial/JTAG 接口,即烧录与默认 STDIO 通道)、highlevel_stdio(高级 STDIO 抽象)、tinyusb_device(TinyUSB 设备栈支持)。
二、硬件与板级配置:默认引脚功能分配
2.1 MCU 与板级说明
文档中关于 MCU 的说明指出:该板的大部分功能由 ESP32-S3 SoC 提供,关于 ESP32-S3 SoC 家族(ESP32x SoC)的更详细信息应参阅 RIOT 文档中的 "ESP32 SoC Series" 章节。
板级硬件方面,Arduino Nano ESP32 除了 RGB 指示灯(红、绿、蓝各为独立 LED)之外没有其他特殊板载外设,因此板级配置的重心就是外设与 GPIO 的默认分配。文档给出的配置概览为:
- 8 路 ADC 通道(若启用
periph_i2c模块,则为 4 路) - 1 路 SPI
- 1 路 I2C
- 1 路 UART
- 2 路 PWM 设备(PWM_DEV(0) 含 4 个通道,PWM_DEV(1) 含 3 个 RGB LED 通道)
2.2 默认引脚配置表
文档给出了按 GPIO 功能分类的默认板级配置表(该表可被应用特定的板级配置覆盖):
| 功能 | GPIO | 备注 |
|---|---|---|
| ADC_LINE(0) | GPIO1 | |
| ADC_LINE(1) | GPIO2 | |
| ADC_LINE(2) | GPIO3 | |
| ADC_LINE(3) | GPIO4 | |
| ADC_LINE(4) | GPIO11 | 若使用periph_i2c则不可用 |
| ADC_LINE(5) | GPIO12 | 若使用periph_i2c则不可用 |
| ADC_LINE(6) | GPIO13 | |
| ADC_LINE(7) | GPIO14 | |
| PWM_DEV(0):0 | GPIO6 | |
| PWM_DEV(0):1 | GPIO8 | |
| PWM_DEV(0):2 | GPIO9 | |
| PWM_DEV(0):3 | GPIO18 | |
| PWM_DEV(1):0 | GPIO46 | 红色 LED |
| PWM_DEV(1):1 | GPIO0 | 绿色 LED |
| PWM_DEV(1):2 | GPIO45 | 蓝色 LED |
| I2C_DEV(0):SCL | GPIO12 | |
| I2C_DEV(0):SDA | GPIO11 | |
| SPI_DEV(0):CLK | GPIO48 | 使用 SPI2_HOST(FSPI) |
| SPI_DEV(0):MISO | GPIO47 | 使用 SPI2_HOST(FSPI) |
| SPI_DEV(0):MOSI | GPIO38 | 使用 SPI2_HOST(FSPI) |
| SPI_DEV(0):CS0 | GPIO21 | 使用 SPI2_HOST(FSPI) |
| UART_DEV(0):TxD | GPIO43 | 控制台(固定) |
| UART_DEV(0):RxD | GPIO44 | 控制台(固定) |
2.3 源码印证:periph_conf.h 中的实际定义
上述配置表在 boards/arduino-nano-esp32/include/periph_conf.h 中逐项落地,几个值得注意的实现细节:
ADC 通道与 I2C 的条件互斥。文档表中"若使用periph_i2c则不可用"的备注,在源码中通过宏条件直接实现:
#ifndef ADC_GPIOS # if !MODULE_PERIPH_I2C # define ADC_GPIOS { GPIO1, GPIO2, GPIO3, GPIO4, GPIO11, GPIO12, GPIO13, GPIO14 } # else /* !MODULE_PERIPH_I2C */ # define ADC_GPIOS { GPIO1, GPIO2, GPIO3, GPIO4 } # endif /* !MODULE_PERIPH_I2C */ #endif原因是 GPIO11/GPIO12 已分配给 I2C_DEV(0) 的 SDA/SCL 信号,为避免资源冲突,启用periph_i2c时仅保留连接 ADC1 的 4 路通道。源码注释还特别提示:GPIO3 在EFUSE_STRAP_JTAG_SEL置位时是 strapping 引脚,使用 ADC 时需要注意。
I2C 接口。I2C_DEV(0) 的 SCL/SDA 分别固定为 GPIO12/GPIO11,默认总线速度为快速模式:
#ifndef I2C0_SPEED # define I2C0_SPEED I2C_SPEED_FAST /**< I2C bus speed of I2C_DEV(0) */ #endif #ifndef I2C0_SCL # define I2C0_SCL GPIO12 /**< SCL signal of I2C_DEV(0) */ #endif #ifndef I2C0_SDA # define I2C0_SDA GPIO11 /**< SDA signal of I2C_DEV(0) */ #endifPWM 设备。两个 PWM 设备的通道分配如下:PWM_DEV(0) 使用经典 Arduino 数字引脚 D3、D5、D6、D9(对应 GPIO6、GPIO8、GPIO9、GPIO18)中未分配给 SPI 的引脚;PWM_DEV(1) 则专门承载 RGB 指示灯:
#ifndef PWM0_GPIOS # define PWM0_GPIOS { GPIO6, GPIO8, GPIO9, GPIO18 } #endif #ifndef PWM1_GPIOS # define PWM1_GPIOS { GPIO46, GPIO0, GPIO45 } #endif对应关系为:PWM1:0 红色 LED(GPIO46)、PWM1:1 绿色 LED(GPIO0)、PWM1:2 蓝色 LED(GPIO45)。
SPI 接口走 GPIO 矩阵。SPI_DEV(0) 使用 FSPI(SPI2_HOST)外设,四个信号线通过 GPIO 矩阵从普通 I/O 引脚路由到 FSPI 的对应信号:
#ifndef SPI0_CTRL # define SPI0_CTRL FSPI /**< FSPI is used as SPI_DEV(0) */ #endif #ifndef SPI0_SCK # define SPI0_SCK GPIO48 /**< Routed vio the GPIO matrix to FSPI CLK signal */ #endif #ifndef SPI0_MISO # define SPI0_MISO GPIO47 /**< Routed vio the GPIO matrix to FSPI MISO signal */ #endif #ifndef SPI0_MOSI # define SPI0_MOSI GPIO38 /**< Routed vio the GPIO matrix to FSPI MOSI signal */ #endif #ifndef SPI0_CS0 # define SPI0_CS0 GPIO21 /**< Routed vio the GPIO matrix to FSPI CS0 signal */ #endifUART 固定分配。ESP32-S3 最多提供 3 路 UART,但板上只配置了 UART_DEV(0),且 TxD/RxD 为固定直连 I/O 引脚,不可更改:
#define UART0_TXD GPIO43 /**< direct I/O pin for UART_DEV(0) TxD, can't be changed */ #define UART0_RXD GPIO44 /**< direct I/O pin for UART_DEV(0) RxD, can't be changed */此外,该文件所有#ifndef保护都意味着:应用侧可以通过"应用特定板级配置"覆盖任意默认值,这是 ESP32 板族统一的定制机制。
2.4 板载 LED 定义与 SAUL 设备
boards/arduino-nano-esp32/include/board.h 定义了三个板载 LED,均为低电平有效:
#define LED0_PIN GPIO46 /**< LED0 pin (red) */ #define LED0_ACTIVE (0) /**< LED0 is low active */ #define LED1_PIN GPIO0 /**< LED1 pin (green) */ #define LED1_ACTIVE (0) /**< LED1 is low active */ #define LED2_PIN GPIO45 /**< LED2 pin (blue) */ #define LED2_ACTIVE (0) /**< LED2 is low active */并进一步别名为LED_RED_PIN、LED_GREEN_PIN、LED_BLUE_PIN,方便按颜色引用。
这些 LED 同时被注册为 SAUL GPIO 设备。boards/arduino-nano-esp32/include/gpio_params.h 中的saul_gpio_params数组为三路 LED 配置了GPIO_OUT模式与SAUL_GPIO_INVERTED标志,从而自动处理低电平有效的极性反转:
static const saul_gpio_params_t saul_gpio_params[] = { { .name = "LED red", .pin = LED0_PIN, .mode = GPIO_OUT, .flags = SAUL_GPIO_INVERTED, }, ... };而 boards/arduino-nano-esp32/Makefile.dep 中可以看到,当应用启用了saul_default模块时会自动引入saul_gpio模块,使上述 SAUL GPIO 设备生效;同时该板无条件依赖 ESP32-S3 的公共板级模块:
ifneq (,$(filter saul_default,$(USEMODULE))) USEMODULE += saul_gpio endif USEMODULE += boards_common_esp32s3 include $(RIOTBOARD)/common/esp32s3/stdio_esp32s3_default.dep.mk三、烧录流程:USB Serial/JTAG 与外部串口适配器
3.1 通过 USB Serial/JTAG 接口烧录(推荐)
该板没有板载 USB-to-Serial 芯片,最方便的烧录方式就是直接使用芯片自带的 USB Serial/JTAG 接口:将板子通过 USB 连接到宿主机,然后执行:
BOARD=arduino-nano-esp32 make flash ...需要留意一个常见故障:RIOT 的 make 系统通常会在烧录前自动复位板子以启用 USB Serial/JTAG 接口。某些特殊情况下自动复位不生效,烧录程序无法连接板子,最终报超时错误:
Serial port /dev/ttyACM0 Connecting... ... serial.serialutil.SerialTimeoutException: Write timeout文档指出,这种情况例如发生在板子尚未烧录过 RIOT 固件、或 USB 接口正被其他用途占用时。解决方法是手动进入下载模式:按住 RESET 按键的同时拉低 GPIO0(B1)引脚,然后释放 RESET 按键。进入下载模式后,USB Serial/JTAG 接口始终可用。
3.2 使用外部 USB-to-Serial 适配器烧录
也可以使用外部 USB-to-Serial 适配器。适配器需接到 UART0 的 TxD(GPIO43)与 RxD(GPIO44)。烧录前同样需要先进入下载模式:按住 RESET 按键的同时拉低 GPIO0(B1)引脚。进入下载模式后执行相同命令:
BOARD=arduino-nano-esp32 make flash ...文档同时提示:关于 ESP32-S3 的更多细节以及如何为 ESP32-S3 板配置和编译 RIOT,应参阅 RIOT 文档中的esp32_riot相关章节。
四、STDIO 配置:三种通道的自动选择机制
4.1 默认行为:USB Serial/JTAG 作为 STDIO 通道
由于板上没有 USB-to-Serial 芯片,RIOT 默认使用 USB Serial/JTAG 接口作为 STDIO 通道,对应模块为stdio_usb_serial_jtag,其对外提供 USB CDC ACM 接口。
4.2 与 USB 设备栈的联动
文档说明:如果 USB 端口被 USBUS 协议栈或 TinyUSB 协议栈占用,则 STDIO 会隐式改用stdio_cdc_acm或stdio_tinyusb_cdc_acm模块,仍然经由 USB CDC ACM 接口输出。
这一隐式选择逻辑在 boards/common/esp32s3/stdio_esp32s3_default.dep.mk 中实现(该文件被板级Makefile.dep引入):
ifneq (,$(filter stdio_default,$(USEMODULE))) ifneq (,$(filter usbus,$(USEMODULE))) USEMODULE += stdio_cdc_acm FEATURES_REQUIRED += highlevel_stdio else ifneq (,$(filter tinyusb_device,$(USEMODULE))) USEMODULE += stdio_tinyusb_cdc_acm FEATURES_REQUIRED += highlevel_stdio else # Use stdio_usb_serial_jtag if no other stdio is requested explicitly # and neither USBUS nor tinyusb_device are used USEMODULE += stdio_usb_serial_jtag endif # Even if only stdio_usb_serial_jtag is enabled, usb_board_reset is enabled # since there should be a CDC ACM interface in any case. This is necessary, # for example, to reset the board if stdio_cdc_acm or stdio_tinyusb_cdc_acm # was previously used. USEMODULE += usb_board_reset include $(RIOTMAKE)/tools/usb_board_reset.mk endif从源码结构看,这段依赖脚本还有一层实用考量:即使最终只启用了stdio_usb_serial_jtag,系统也会同时启用usb_board_reset模块。这是因为板上始终应存在一个 CDC ACM 接口,这样当之前烧录的固件使用的是stdio_cdc_acm或stdio_tinyusb_cdc_acm时,新固件仍能通过 USB 将板子复位完成更新。
4.3 使用 UART + 外部串口适配器作为 STDIO
如果需要改用 UART 输出(例如配合外部 USB-to-Serial 适配器调试),只需在模块列表中显式加入stdio_uart:
BOARD=arduino-nano-esp32 USEMODULE=stdio_uart make flash ...此时控制台将走 UART_DEV(0),即固定连接到 GPIO43(TxD)与 GPIO44(RxD)。
五、小结与快速上手
- 板级标识:
BOARD=arduino-nano-esp32,CPU 型号esp32s3r8(8 MB QSPI PSRAM + 16 MB Flash),定义于 boards/arduino-nano-esp32/Makefile.features 与 boards/arduino-nano-esp32/Kconfig; - 引脚配置:8 路 ADC(启用 I2C 后为 4 路)、1 路 SPI(FSPI,经 GPIO 矩阵路由)、1 路 I2C(GPIO11/GPIO12,快速模式)、1 路固定 UART(GPIO43/GPIO44)、2 组共 7 路 PWM(含 RGB LED),全部可在 boards/arduino-nano-esp32/include/periph_conf.h 中核对,并支持应用侧覆盖;
- LED:红/绿/蓝三路独立 LED(GPIO46/GPIO0/GPIO45),低电平有效,且注册为带极性反转的 SAUL GPIO 设备,见 boards/arduino-nano-esp32/include/board.h 与 boards/arduino-nano-esp32/include/gpio_params.h;
- 烧录:默认走 USB Serial/JTAG(
BOARD=arduino-nano-esp32 make flash ...);若自动复位失败导致SerialTimeoutException,按住 RESET 同时拉低 GPIO0(B1)手动进入下载模式;也可用外部 USB-to-Serial 适配器接 GPIO43/GPIO44 烧录; - STDIO:默认
stdio_usb_serial_jtag;启用usbus时自动切换为stdio_cdc_acm,启用tinyusb_device时自动切换为stdio_tinyusb_cdc_acm;显式USEMODULE=stdio_uart可改用 UART 控制台,选择逻辑见 boards/common/esp32s3/stdio_esp32s3_default.dep.mk。
以上配置均以当前仓库中的板级支持代码为准;如需为特定应用修改默认引脚分配,可按文档所述的 ESP32 "application-specific configurations" 机制在应用侧覆盖periph_conf.h中的相关宏定义。
【免费下载链接】RIOTRIOT - The friendly OS for IoT项目地址: https://gitcode.com/GitHub_Trending/riot/RIOT
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考