RIOT 板级支持详解:STM32 Nucleo-F072RB(nucleo-f072rb)外设配置、烧录与开发实践
【免费下载链接】RIOTRIOT - The friendly OS for IoT项目地址: https://gitcode.com/GitHub_Trending/riot/RIOT
导读
本文基于 RIOT 操作系统仓库中 boards/nucleo-f072rb/doc.md 板级文档,系统讲解 STM32 Nucleo-F072RB 开发板在 RIOT 中的支持情况。Nucleo-F072RB 是 ST 官方 Nucleo64 家族中基于 ARM Cortex-M0 内核、内置 16KiB RAM 与 128KiB Flash 的入门级开发板,在 RIOT 中对应板名nucleo-f072rb。读完本文,你将掌握该板的硬件规格、RIOT 中的外设实现状态、periph_conf.h引脚复用细节、构建系统特性声明,以及如何烧录固件并通过 ST-Link 虚拟串口进入 RIOT shell 进行调试。
板卡概览:Nucleo64 家族的一员
Nucleo-F072RB 属于 ST 官方 Nucleo64(Nucleo-64)开发板系列。在 RIOT 的目录结构中,它被归入boards_common_nucleo64分组,与大量同为 64 引脚规格的 Nucleo 板卡共享一套公共板级配置(位于 boards/common/nucleo64 目录,包含board.h、Makefile.features、Makefile.include等公共文件)。
板卡核心信息一览:
| 项目 | 说明 |
|---|---|
| 板名(BOARD) | nucleo-f072rb |
| MCU | STM32F072RB(ST 出品) |
| 内核 | ARM Cortex-M0 |
| RAM | 16KiB |
| Flash | 128KiB |
| 主频 | 最高 48MHz |
| FPU | 无 |
| 工作电压 Vcc | 2.0V – 3.6V |
| 板级归属 | boards_common_nucleo64(Nucleo64 公共组) |
在 Kconfig 层面,boards/nucleo-f072rb/Kconfig 通过select BOARD_COMMON_NUCLEO64与select CPU_MODEL_STM32F072RB将板卡同时关联到 Nucleo64 公共配置组与stm32f072rbCPU 型号,并最终source引入公共的 Nucleo64 Kconfig 定义。
MCU 外设资源一览
STM32F072RB 这颗 MCU 本身的外设资源相当丰富,原文档给出了完整的规格表,逐项说明如下:
| 外设 | 数量/规格 |
|---|---|
| 定时器 | 12 个(含 2 个看门狗、1 个 SysTick、8 个 16 位定时器、1 个 32 位定时器) |
| ADC | 1 个 12 位 ADC(最多 16 通道) |
| UART | 4 个 |
| SPI | 2 个 |
| I2C | 2 个 |
| CAN | 1 个 |
| USB | 1 个 |
| RTC | 1 个 |
ST 官方为这颗芯片提供的数据手册(Datasheet)、参考手册(Reference Manual)、编程手册(Programming Manual)以及 Nucleo64 板卡用户手册(Board Manual,即 UM1724)是理解引脚定义与外设寄存器行为的第一手资料。Nucleo 板载 ST-Link 调试器布局、LSE 晶振安装位置(X2 槽)等细节均记录在 UM1724 用户手册中,RIOT 源码注释里也多次引用该手册章节。
RIOT 实现状态:哪些外设已可用
原文档以表格形式给出了该板在 RIOT 中的外设驱动实现状态,这是判断"这块板能跑什么应用"的关键依据:
| 设备/驱动 | ID | 支持状态 | 说明 |
|---|---|---|---|
| MCU | STM32F072RB | 部分支持 | 低功耗(Energy saving)模式未被充分利用 |
| GPIO | – | 支持 | – |
| PWM | – | 支持(4 个引脚) | 详见下文引脚说明 |
| UART | – | 3 个 UART | USART2 经 ST-Link/USB 或 D0(RX)/D1(TX);USART1 在 PA10(RX)/PA09(TX);USART3 在 PC11(RX)/PC10(TX) |
| ADC | – | 6 个引脚 | – |
| I2C | – | 不支持(no) | – |
| SPI | – | 支持(SPI1) | – |
| USB | – | 不支持(no) | – |
| 定时器 | TIM1 | 1 个 32 位定时器 | – |
需要特别说明两点:
- 文档表格与源码细节的差异:原文档的状态表是板级移植早期的粗略描述。从实际源码看,boards/nucleo-f072rb/include/periph_conf.h 中 SPI 实际配置了 SPI1 与 SPI2 两个控制器,PWM 实际配置了 3 个定时器共 7 个通道引脚。后文将以源码为准展开说明。
- I2C 的特殊情况:状态表写的是"no",但 boards/nucleo-f072rb/Makefile.features 中声明了
FEATURES_PROVIDED += periph_i2c,且periph_conf.h通过#include "cfg_i2c1_pb8_pb9.h"引入了 I2C1 的引脚配置(PB8/PB9)。这说明 I2C 能力已在特性层面声明并具备引脚配置,实际可用性以最新源码为准。
深入periph_conf.h:引脚复用与时钟总线详解
板级外设配置的核心文件是 boards/nucleo-f072rb/include/periph_conf.h。它定义了该板所有已接入 RIOT periph API 的外设实例,包括引脚号、复用功能(AF)、总线与时钟使能掩码。
时钟源:HSE 与 LSE 均可使用
/* HSE available on this board */ #define CONFIG_BOARD_HAS_HSE 1 /* This board provides an LSE */ #define CONFIG_BOARD_HAS_LSE 1Nucleo64 板默认带有 8MHz HSE 晶振;LSE(32.768kHz 低速晶振)则取决于板卡批次:仅在贴有 MB1136 C-02 或 MB1136 C-03 标识、且用户在 X2 槽位自行焊接了 LSE 晶振的板卡上可用(参见 Nucleo 用户手册 UM1724 第 5.6.2 节)。Makefile.features中periph_rtc特性的声明正依赖于此 LSE。
定时器:TIM1(文档与源码的差异点)
static const timer_conf_t timer_config[] = { { .dev = TIM1, .max = 0x0000ffff, .rcc_mask = RCC_APB2ENR_TIM1EN, .bus = APB2, .irqn = TIM1_CC_IRQn } }; #define TIMER_0_ISR isr_tim1_cc #define TIMER_NUMOF ARRAY_SIZE(timer_config)RIOT 的periph_timer仅暴露了 TIM1 一个定时器,max = 0x0000ffff说明其按 16 位计数范围使用(APB2 总线、TIM1_CC 中断)。原文档将其描述为"1 个 32 位定时器"是指 TIM1 硬件本身具备 32 位能力,但 RIOT 配置中按 16 位上限使用。
UART:三路串口对应关系
static const uart_conf_t uart_config[] = { { .dev = USART2, .rx_pin = GPIO_PIN(PORT_A, 3), .tx_pin = GPIO_PIN(PORT_A, 2), .rx_af = GPIO_AF1, .tx_af = GPIO_AF1, .bus = APB1, .irqn = USART2_IRQn }, { .dev = USART1, .rx_pin = GPIO_PIN(PORT_A, 10), .tx_pin = GPIO_PIN(PORT_A, 9), .rx_af = GPIO_AF1, .tx_af = GPIO_AF1, .bus = APB2, .irqn = USART1_IRQn }, { .dev = USART3, .rx_pin = GPIO_PIN(PORT_C, 11), .tx_pin = GPIO_PIN(PORT_C, 10), .rx_af = GPIO_AF1, .tx_af = GPIO_AF1, .bus = APB1, .irqn = USART3_8_IRQn } };与文档中的说明完全对应:
- USART2:PA3(RX)/PA2(TX),同时连到 ST-Link 虚拟串口与 Arduino 头 D0/D1,是默认控制台串口;
- USART1:PA10(RX)/PA09(TX);
- USART3:PC11(RX)/PC10(TX)。
MCU 本身有 4 个 UART(USART1–4),但 RIOT 板级配置只接出了 3 路,对应文档状态表中的"3 UARTs"。
PWM:三个定时器、七个可用引脚
static const pwm_conf_t pwm_config[] = { { .dev = TIM2, .chan = { { .pin = GPIO_PIN(PORT_B, 3), .cc_chan = 1 }, /* D3 */ { .pin = GPIO_PIN(PORT_B, 10), .cc_chan = 2 }, /* D6 */ { .pin = GPIO_PIN(PORT_B, 11), .cc_chan = 3 }, { .pin = GPIO_UNDEF, .cc_chan = 0 } }, .af = GPIO_AF2, .bus = APB1 }, { .dev = TIM3, .chan = { { .pin = GPIO_PIN(PORT_B, 4), .cc_chan = 0 }, /* D5 */ { .pin = GPIO_PIN(PORT_B, 5), .cc_chan = 1 }, /* D4 */ ... }, .af = GPIO_AF1, .bus = APB1 }, { .dev = TIM15, .chan = { { .pin = GPIO_PIN(PORT_B, 14), .cc_chan = 0 }, { .pin = GPIO_PIN(PORT_B, 15), .cc_chan = 1 }, ... }, .af = GPIO_AF1, .bus = APB2 } };实际可用 PWM 通道引脚共 7 个:PB3(Arduino D3,TIM2)、PB10(D6,TIM2)、PB11(TIM2)、PB4(D5,TIM3)、PB5(D4,TIM3)、PB14 与 PB15(TIM15)。使用时需注意不同通道分属不同定时器,同一 PWM 设备内的通道共享频率、仅占空比可独立调节。
SPI:SPI1 与 SPI2 均已配置
static const spi_conf_t spi_config[] = { { .dev = SPI1, .mosi_pin = GPIO_PIN(PORT_A, 7), .miso_pin = GPIO_PIN(PORT_A, 6), .sclk_pin = GPIO_PIN(PORT_A, 5), .cs_pin = GPIO_PIN(PORT_A, 4), .mosi_af = GPIO_AF0, .miso_af = GPIO_AF0, .sclk_af = GPIO_AF0, .cs_af = GPIO_AF0, .rccmask = RCC_APB2ENR_SPI1EN, .apbbus = APB2 }, { .dev = SPI2, .mosi_pin = GPIO_PIN(PORT_B, 15), .miso_pin = GPIO_PIN(PORT_B, 14), .sclk_pin = GPIO_PIN(PORT_B, 13), .cs_pin = GPIO_PIN(PORT_B, 12), .mosi_af = GPIO_AF0, .miso_af = GPIO_AF0, .sclk_af = GPIO_AF0, .cs_af = GPIO_AF0, .rccmask = RCC_APB1ENR_SPI2EN, .apbbus = APB1 } };SPI1 位于 PA7(MOSI)/PA6(MISO)/PA5(SCLK)/PA4(CS),对应 Arduino 头 D11/D12/D13/D10。由于 SPI1 的 SCLK(PA5)与板载 LED0(PA5)存在引脚冲突,Nucleo64 公共文档(boards/common/nucleo64/doc.md)明确警告:使用periph_spi会因引脚冲突禁用 LED0,编译时会输出如下警告:
Warning: Using periph_spi on Nucleo64 boards will disable LED0 due to pin conflicts.ADC:六个外部引脚加 VBAT 采样
static const adc_conf_t adc_config[] = { { GPIO_PIN(PORT_A, 0), 0 }, /* PA0 → ADC 通道 0 */ { GPIO_PIN(PORT_A, 1), 1 }, /* PA1 → ADC 通道 1 */ { GPIO_PIN(PORT_A, 4), 4 }, /* PA4 → ADC 通道 4 */ { GPIO_PIN(PORT_B, 0), 8 }, /* PB0 → ADC 通道 8 */ { GPIO_PIN(PORT_C, 1), 11 }, /* PC1 → ADC 通道 11 */ { GPIO_PIN(PORT_C, 0), 10 }, /* PC0 → ADC 通道 10 */ { GPIO_UNDEF, 18 }, /* VBAT */ }; #define VBAT_ADC ADC_LINE(6) /**< VBAT ADC line */6 个外部引脚(PA0、PA1、PA4、PB0、PC0、PC1)对应文档状态表中的"6 pins",另有一个内部 VBAT 采样通道(第 6 条 ADC 线),可通过VBAT_ADC宏在应用中读取电池电压。
板级构建系统:特性声明与依赖组织
RIOT 的板级目录采用"特性声明 + 公共组复用"的组织方式,boards/nucleo-f072rb/Makefile.features 声明了该板提供的外设特性:
CPU = stm32 CPU_MODEL = stm32f072rb FEATURES_PROVIDED += periph_adc FEATURES_PROVIDED += periph_i2c FEATURES_PROVIDED += periph_pwm FEATURES_PROVIDED += periph_rtc FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_uart FEATURES_PROVIDED += periph_spi # 加载 Nucleo64 公共 Makefile.features include $(RIOTBOARD)/common/nucleo64/Makefile.features其中periph_rtc的注释再次强调:只有带 MB1136 C-02/C-03 标识且在 X2 槽安装 LSE 晶振的板卡才具备 RTC 所需的 32.768kHz 时钟源。其余板级文件均为薄封装:Makefile 仅定义MODULE = board并引入公共 Nucleo 目录,Makefile.include 与 Makefile.dep 直接复用common/nucleo64的公共逻辑。
此外,Nucleo64 公共 board.h 给出了板载资源的默认定义,适用于该板:
- LED0:位于 PA5(即与 SPI1 SCLK 冲突的那个引脚),通过
LED0_PIN_NUM/LED0_PORT定义; - 用户按键 BTN0:PC13,默认上拉(
GPIO_IN_PU)模式; - MRF24J40 无线模块参数:默认挂接在
SPI_DEV(0)上,时钟 5MHz,CS 为 Arduino D10,中断与复位分别为 D7、D5。
编译、烧录与串口调试
指定板名编译
在 RIOT 中编译应用时,通过BOARD变量指定目标板:
make BOARD=nucleo-f072rbRIOT 的构建系统会根据Makefile.features中的CPU_MODEL = stm32f072rb自动选取对应的 CPU 移植层(cpu/stm32),并按periph_conf.h生成外设驱动配置。
烧录方式
Nucleo 板卡自带 ST-Link 调试器,RIOT 对该板使用 ST-Link 相关的烧录工具链(openocd 或 stlink 工具,取决于本地 makefile 的PROGRAMMER配置)。文档原文指向的详细烧录指南位于项目官方 guides 站点,其核心思路是:在板卡通过 USB 连接 ST-Link 后,直接执行:
make BOARD=nucleo-f072rb flashRIOT 会调用配置好的烧录后端将编译产物写入 MCU。若需在烧录前确认本机工具链,可执行make BOARD=nucleo-f072rb info等命令查看构建与烧录相关信息。
进入 RIOT shell
Nucleo 全系板卡都带有板载 ST-Link 虚拟串口(VCP),这是 RIOT 默认控制台的访问通道。对于nucleo-f072rb,与 ST-Link 相连的是USART2(PA3/PA2,即 Arduino 头的 D0/D1),默认参数为115200 波特率、8N1(8 数据位、无校验、1 停止位)。
连接方式:
- 用 USB 线连接板卡的 ST-Link USB 口;
- 使用串口工具(如 minicom、picocom、PuTTY 等)打开 ST-Link 枚举出的虚拟串口;
- 设置 115200、8N1,即可看到 RIOT shell 提示符并交互执行 shell 命令。
不同 Nucleo 变体使用的控制台 USART 并不相同,务必以各自include/periph_conf.h中的 UART 配置为准——这是 boards/common/nucleo64/doc.md 反复强调的注意事项。
已知限制与注意事项汇总
综合板级文档与源码,使用nucleo-f072rb时有几点需要特别留意:
- 低功耗支持不完整:MCU 支持状态为"部分支持",节能模式未被充分利用,低功耗应用需自行验证;
- SPI 与 LED0 冲突:启用
periph_spi后 PA5 被复用为 SPI1 SCLK,板载 LED0 失效,编译期会给出警告; - RTC 依赖 LSE 晶振:仅 MB1136 C-02/C-03 批次且 X2 槽已焊接 LSE 晶振的板卡可用
periph_rtc; - 控制台串口固定为 USART2:若应用需要占用 PA2/PA3,需在配置中调整 STDIO 串口映射;
- 文档状态表与源码的差异:SPI 实际已配置 SPI1 与 SPI2 两个实例,PWM 实际可用 7 个引脚(TIM2/TIM3/TIM15),I2C 已声明特性并具备 PB8/PB9 配置,开发时以 include/periph_conf.h 为准。
延伸阅读
- 板级完整定义:boards/nucleo-f072rb/doc.md(本文依据的原文档)
- 外设引脚配置:boards/nucleo-f072rb/include/periph_conf.h
- 特性声明与构建配置:boards/nucleo-f072rb/Makefile.features、boards/nucleo-f072rb/Kconfig
- Nucleo64 公共组文档(LED0/SPI 冲突、串口访问约定):boards/common/nucleo64/doc.md
- Nucleo64 公共板级头文件(LED0、BTN0、MRF24J40 默认参数):boards/common/nucleo64/include/board.h
- 对应的 STM32 CPU 移植层:cpu/stm32
借助以上文档与源码,开发者可以快速评估在nucleo-f072rb上运行何种 RIOT 应用(GPIO 点灯、UART 通信、PWM 调光、ADC 采样、SPI 外设扩展等),并据此规划自己的引脚分配方案。
【免费下载链接】RIOTRIOT - The friendly OS for IoT项目地址: https://gitcode.com/GitHub_Trending/riot/RIOT
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考