RIOT 中 Blackpill STM32F103C8 开发板支持:板级配置、外设映射与烧录实战
【免费下载链接】RIOTRIOT - The friendly OS for IoT项目地址: https://gitcode.com/GitHub_Trending/riot/RIOT
本文围绕 RIOT 操作系统中 blackpill-stm32f103c8 开发板的板级支持文档展开,结合仓库中该板卡的 Kconfig、Makefile 与共享的 blxxxpill 板级公共代码,讲清这块基于 STM32F103C8 的廉价开发板在 RIOT 中的组织方式、外设引脚映射(UART/I2C/SPI/ADC/PWM/Timer/QDEC/DMA/USB)以及串口连接、SWD 烧录的实操要点。读完后,你可以正确选用blackpill-stm32f103c8与blackpill-stm32f103cb两种板名进行构建,并理解每一路外设落在哪些物理引脚上、为何会有引脚冲突取舍。
1. Blackpill 是什么:板卡概览
Blackpill(STM32F103C8T6)与 Bluepill 同属一类可以以极低价格购得(文档中提到大约 2 欧元)的 STM32F103 入门级开发板。RIOT 为它们提供了共享的板级支持代码,Blackpill C8 版本对应板名blackpill-stm32f103c8。
需要特别注意的硬件风险(直接引自板级文档的警告):
- 真假芯片问题:很多此类开发板上焊接的是假冒 STM32 芯片,能否配合 RIOT 正常工作并不确定,采购时务必留意;
- Flash 容量不确定:STM32F103C8 标称 64 KiB Flash,但多数实物实际带 128 KiB;也有部分版本报告 32 KiB、实际却是 64 KiB。因此 C8/CB 两种后缀(64 KiB / 128 KiB)与实物并不总是一一对应;
- USB 座焊接质量:Micro-USB 口有时焊接不良,且常配有错误的电阻,这是已知问题之一(详见第 7 节)。
MCU 关键规格(来自共享文档 boards/common/blxxxpill/doc.md 的 MCU 表):
| 项目 | 规格 |
|---|---|
| 型号 | STM32F103C8 / STM32F103CB |
| 内核 | ARM Cortex-M3 |
| 厂商 | STMicroelectronics |
| RAM | 20 KiB |
| Flash | 32 / 64 / 128 KiB |
| 主频 | 最高 72 MHz |
| 定时器 | 3 个 16 位 |
| ADC | 2 个 12 位、10 通道 |
| UART / SPI / I2C / CAN | 3 / 2 / 2 / 1 |
| 供电 Vcc | 2.0 ~ 3.6 V |
外设驱动实现状态(同一文档的 Implementation Status 表):
| 外设 | 是否支持 |
|---|---|
| GPIO | 是 |
| PWM | 是 |
| UART | 是 |
| ADC | 是 |
| I2C | 是 |
| SPI | 是 |
| USB | 否(见下文说明) |
| Timer | 是 |
| CAN | 否 |
补充说明:从源码结构看,共享配置里其实提供了
periph_usbdev特性(见第 4 节特性清单),STM32F103 自身带 USB FS 外设;文档表格中“USB: no”更多反映的是板级 USB 座焊接/电阻问题导致实际不可用。
2. 板级支持在 RIOT 仓库中的组织方式
RIOT 的板级支持遵循“板卡目录 + 公共目录”的分层结构。Blackpill C8 的目录非常精简:
- boards/blackpill-stm32f103c8/Kconfig
- boards/blackpill-stm32f103c8/Makefile
- boards/blackpill-stm32f103c8/Makefile.features
- boards/blackpill-stm32f103c8/include/board.h
板名与 CPU 型号在 Kconfig 中绑定:Kconfig 中BOARD_BLACKPILL_STM32F103C8选择公共板卡BOARD_COMMON_BLXXXPILL与 CPU 型号CPU_MODEL_STM32F103C8,并 source 公共 Kconfig。构建系统侧,Makefile 只有一行关键内容——把公共目录拉进编译路径:
MODULE = board DIRS = $(RIOTBOARD)/common/blxxxpill include $(RIOTBASE)/Makefile.base而 Makefile.features 声明该板属于stm32CPU 家族、具体型号为stm32f103c8,并复用公共 features 文件。这意味着 Blackpill 的几乎所有实质工作都集中在共享目录 boards/common/blxxxpill/ 中,该板卡目录只做了“型号 + LED 引脚”两处的差异化。CB 变体 boards/blackpill-stm32f103cb/Kconfig 的结构与之完全同构,仅把 CPU 型号换成CPU_MODEL_STM32F103CB。
提供的功能特性
公共 features 文件 boards/common/blxxxpill/Makefile.features 声明该板提供以下 RIOT 特性:
CPU = stm32 FEATURES_PROVIDED += periph_adc FEATURES_PROVIDED += periph_dma FEATURES_PROVIDED += periph_i2c FEATURES_PROVIDED += periph_pwm FEATURES_PROVIDED += periph_rtc FEATURES_PROVIDED += periph_rtt FEATURES_PROVIDED += periph_spi FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_uart FEATURES_PROVIDED += periph_qdec FEATURES_PROVIDED += periph_usbdev FEATURES_PROVIDED += riotboot即:ADC、DMA、I2C、PWM、RTC、RTT、SPI、Timer、UART、QDEC(正交编码器)、USB 设备驱动框架以及 riotboot 启动能力。其中 RTC/RTT 依赖板载晶振——boards/common/blxxxpill/Kconfig 通过select BOARD_HAS_HSE / BOARD_HAS_LSE声明板上同时具备高速(HSE)与低速(LSE)晶振,这对应外设配置中 RTT 使用 16384 Hz 的 LSE 作为时钟源。
3. 板级头文件:LED、STDIO 与 xtimer
LED0 引脚:Blackpill 与 Bluepill 的关键差异
Blackpill 板卡目录里唯一有“板级差异”语义的头文件是 board.h:
#define LED0_PORT GPIO_PORT_B /**< GPIO port of LED 0 */ #define LED0_PORT_NUM PORT_B /**< GPIO Port number the LED is connected to */ #define LED0_PIN_NUM 12 /**< Pin number the LED is connected to */即 Blackpill 的板载 LED 接在PB12。对比之下,Bluepill 的 LED 在 PC13——这一点由公共头文件 board_common.h 的默认值体现:只有当LED0_PORT_NUM未定义时才回落到PORT_C / 13,所以 Blackpill 的board.h先定义 PB12、再 include 公共头(注释特别强调“该 include 必须位于 LED0 参数定义之后”)。
公共头还声明了两个重要默认值:
LED0_IS_INVERTED 1:该板 LED 低电平点亮,GPIO 层会自动处理取反;STDIO_UART_DEV UART_DEV(0):标准输入输出绑定到 0 号 UART,也就是下一节会讲到的 USART1(PA9/PA10);XTIMER_WIDTH (16)与XTIMER_BACKOFF (19):xtimer 高精度定时器使用 16 位计数器、19 的退避参数,这决定了板上 xtimer 的溢出行为(16 位计数器溢出周期比 32 位时更短,对长睡眠场景需留意)。
SAUL 传感器抽象层也把板载 LED 注册成了一个 GPIO 外设,见 gpio_params.h:
static const saul_gpio_params_t saul_gpio_params[] = { { .name = "LED", .pin = LED0_PIN, .mode = GPIO_OUT, .flags = (SAUL_GPIO_INVERTED | SAUL_GPIO_INIT_CLEAR) }, };其中SAUL_GPIO_INVERTED与上文LED0_IS_INVERTED保持一致,初始化状态为 CLEAR(灭灯),在 Blackpill 上即 PB12 输出高电平为灭。
4. 外设引脚映射:periph_conf.h 逐项解析
所有外设与引脚的对应关系集中在 boards/common/blxxxpill/include/periph_conf.h。以下逐项说明,并标注 Blackpill 特有的取舍逻辑。
UART(3 路)
uart_config 定义了:
| 设备号 | 外设 | RX 引脚 | TX 引脚 | DMA(启用 periph_dma 时) |
|---|---|---|---|---|
| UART_DEV(0) | USART1(APB2) | PA10 | PA9 | DMA1 流 3 |
| UART_DEV(1) | USART2(APB1) | PA3 | PA2 | DMA1 流 6 |
| UART_DEV(2) | USART3(APB1) | PB11 | PB10 | DMA1 流 1 |
注意 0 号 UART(USART1)正是STDIO_UART_DEV绑定的端口,PA9/PA10 也是板上引出的串口针脚——这与文档“Connecting via Serial”一节完全对应。另外从配置结构看,USART3 的 PB10/PB11 与 I2C2 的 SCL/SDA 复用同一对引脚,两路不能同时启用。
I2C(2 路)
i2c_config:
| 设备号 | 外设 | SCL | SDA | 速度 |
|---|---|---|---|---|
| I2C_DEV(0) | I2C1(APB1) | PB8 | PB9 | I2C_SPEED_NORMAL |
| I2C_DEV(1) | I2C2(APB1) | PB10 | PB11 | I2C_SPEED_NORMAL |
源码注释特别指出:这块板子做 I2C 通信可能需要外部上拉电阻。
SPI(2 路,注意与 ADC 的互斥)
spi_config:
| 设备号 | 外设 | MOSI | MISO | SCLK | CS | DMA |
|---|---|---|---|---|---|---|
| SPI_DEV(0) | SPI2(APB1) | PB15 | PB14 | PB13 | PB12 | TX 流 3 / RX 流 2 |
| SPI_DEV(1) | SPI1(APB2) | PA7 | PA6 | PA5 | PA4 | TX 流 1 / RX 流 0 |
第二路 SPI1 被#ifndef MODULE_PERIPH_ADC包裹:SPI1 的四根引脚 PA4~PA7 恰好是 ADC 的 4 个通道,启用 ADC 模块时 SPI1 自动退出配置,SPI 只剩 SPI2 一路。这是典型的引脚复用取舍,由构建系统按模块依赖自动裁决。
ADC(6 通道 + 2 内部通道,Blackpill 少 2 路)
adc_config 默认提供 PA0、PA1、PA4~PA7 共 6 个外部通道,外加通道 16(片内温度传感器)与通道 17(VREF 内部参考)。Bluepill 还能再用 PB0/PB1 作 ADC 8/9 通道,但源码注释明确说明了对 Blackpill 的取舍:
/* The blackpill has a few pins less. PB0 and PB1 are among the GPIOs not * exposed due to the lower pincount. * * Also, this conflicts with PWM. We prefer PWM over ADC here to provide * 6 external ADC inputs, and 4 PWM outputs (instead of 8 ADC inputs and * 2 PWM outputs). */即 Blackpill 引脚较少,PB0/PB1 未引出,且它们与 PWM 冲突;RIOT 选择“牺牲 2 路 ADC、保住 4 路 PWM”的方案。因此 Blackpill 上ADC_NUMOF为 8(6 外部 + 2 内部),Bluepill 上为 10。
PWM(TIM3,AFIO 重映射到 PB4/PB5)
pwm_config 使用 TIM3,并通过.remap = AFIO_MAPR_TIM3_REMAP_1把输出引脚从默认的 PA6/PA7 重映射到PB4/PB5;Bluepill 变体(非 Blackpill 宏)还会追加 PB0/PB1 作为 cc_chan 2/3,凑满 4 路 PWM。共享文档的 “Using PWM” 一节写的是 A8~A11 可用,但从当前源码配置看,实际生效的 PWM 引脚是 PB4/PB5(Blackpill 只有这 2 路)——以源码为准。
定时器与 QDEC
timer_config 提供 3 个 16 位定时器:TIM2/TIM3/TIM4,均在 APB1 总线,max = 0xFFFF,中断分别为isr_tim2/3/4——与文档 MCU 表中“3x 16-Bit Timer”一致。
qdec_config(正交编码器)以 TIM4 为基础(PB6/PB7),并带有两个带冲突保护的可选项:TIM3 版本(PB4/PB5,与 PWM 互斥,#ifndef MODULE_PERIPH_PWM)和 TIM1 版本(PA8/PA9,与UART_DEV(0)互斥,#ifndef MODULE_PERIPH_UART)。再次体现了“按启用模块做引脚仲裁”的设计。
DMA(5 条流)
dma_config 配置了 DMA1 的 5 条流,注释标明了每路用途:
static const dma_conf_t dma_config[] = { { .stream = 1 }, /* DMA1 Channel 2 - SPI1_RX / USART3_TX */ { .stream = 2 }, /* DMA1 Channel 3 - SPI1_TX */ { .stream = 3 }, /* DMA1 Channel 4 - SPI2_RX / USART1_TX */ { .stream = 4 }, /* DMA1 Channel 5 - SPI2_TX */ { .stream = 6 }, /* DMA1 Channel 7 - USART2_TX */ };配合上文 UART/SPI 各配置项里的.dma字段(如 USART1 取流 3、USART2 取流 6、SPI2 TX 取流 3 / RX 取流 2),启用periph_dma模块后串口与 SPI 传输即可走 DMA。
RTT 与 RTT 时钟源
RTT_FREQUENCY 定义为 16384 Hz,对应 LSE 32.768 kHz 晶振的二分频,是 STM32 上 RTT(real time tick)的标准做法;这也是该板periph_rtt+periph_rtc特性的硬件基础。
USB 设备驱动框架
stm32_usbdev_fs_config 声明了 STM32F103 的 USB FS 外设:DM/DP 落在 PA11/PA12,中断为isr_usb_lp_can1_rx0。框架层面已就绪,但如第 1 节所述,板子 Micro-USB 座的焊接/电阻问题决定了 USB 口实际可用性存疑。
5. 构建与运行:两个板名的选择
共享文档给出了明确的构建指引:
- 板上是C8(64 KiB Flash)芯片 → 使用板名
blackpill-stm32f103c8; - 板上是CB(128 KiB Flash)芯片 → 使用板名
blackpill-stm32f103cb(对应目录 boards/blackpill-stm32f103cb/ 同构存在)。
由于实物 Flash 大小经常与丝印不符(C8 标 64 KiB 实际可能是 128 KiB),选错板名通常不会立刻失败,但链接脚本给出的 Flash 边界会影响应用空间。RIOT 应用构建的标准方式是以板名为参数调用 make,例如以经典示例 blinky 为例:
make -C examples/basic/blinky -j8 BOARD=blackpill-stm32f103c8 make -C examples/basic/blinky -j8 BOARD=blackpill-stm32f103c8 flash构建时BOARD=...会解析出上文第 2 节的 Kconfig 链(板卡 → common/blxxxpill → stm32 公共配置),并据此自动启用periph_*各模块。CI 中也有大量测试直接以blackpill-stm32f103c8为目标板构建,例如 tests/bench/xtimer/Makefile、tests/net/gnrc_netif/Makefile.ci 等,可作为该板名可用性的旁证。
6. 通过串口连接
共享文档 “Connecting via Serial” 一节的完整操作要点:
- 默认使用的串口是UART1(USART1),物理引脚PA9 = TX,PA10 = RX;
- 串口参数:115200 baud、1 stop bit、无校验(8N1)。
从源码侧验证:STDIO_UART_DEV UART_DEV(0)(board_common.h)把 stdio 绑到 0 号 UART,而 uart_config 中 0 号 UART 的tx_pin = PA9、rx_pin = PA10,与文档描述一一对应。因此用 TTL 串口线接 PA9/PA10 后即可看到 RIOT 的启动日志与riot:命令行提示符。
7. 烧录与已知问题
烧录
烧录流程在 RIOT 官方的板级指南(STM32 通用页)中有详细描述;就本文档而言,关键信息是板名:STM32F103C8 的 Blackpill 用blackpill-stm32f103c8,CB 变体用blackpill-stm32f103cb。配合make ... flash即可完成烧写(具体调试器选型与 OpenOCD 配置属于 RIOT STM32 通用烧录指南的范畴)。
已知问题一:USB 座
Micro-USB 口有时焊接不良,且通常配有错误的电阻,社区有若干修复方法(原文档链接至 Blue Pill Wiki 的 Hardware installation 章节)。如果你的 USB 口无法稳定供电或枚举,优先怀疑这一点。
已知问题二:烧录失败(SWD 接线对照表)
烧录失败时,先检查调试器是否连好——包括硬件复位(NRST)信号线。共享文档给出了完整的接线对照表:
| 调试器侧引脚 | 板子侧引脚 |
|---|---|
| SWDIO | DIO |
| SWCLK | DCLK |
| NRST | R |
| GND | GND |
| VDD(3.3V,注1) | 3.3 |
| Target VCC(注2) | 3.3 |
- 注1(*):多数调试器自带 3.3V 电源给板子上电;也可以改用 TTL 电平转换模块或 Micro-USB 给板子上电;
- 注2(**):部分调试器会监测目标电压,其 Target VCC 引脚需接到板子任一 3.3V 引脚。
另一个高频坑:极便宜的 SWD 调试器(约 2 欧元档)往往没有 Target VCC 引脚(无妨),但复位信号线经常缺失或失效。变通办法是:在 OpenOCD 试图连接时手动按一下板载复位键;烧录完成后再按一次复位键让新镜像启动。
选购提示
这类板子在市面上名字不一,可能叫bluepill/blue pill,也可能要用stm32f103c8或stm32f103c8t6关键字搜到(Blackpill 同理,认准 STM32F103C8T6 模块即可)。
8. 小结
Blackpill STM32F103C8 在 RIOT 中的支持体现了仓库板级架构的典型模式:板卡目录(boards/blackpill-stm32f103c8/)只承载差异化信息——Kconfig 绑定CPU_MODEL_STM32F103C8、board.h把 LED0 定义到 PB12;其余 GPIO、UART、I2C、SPI、ADC、PWM、Timer、QDEC、DMA、USB 的全部引脚映射与冲突仲裁逻辑都收敛在共享的 boards/common/blxxxpill/ 中,并通过FEATURES_PROVIDED暴露给构建系统。理解这张引脚映射表和 C8/CB 两个板名之后,再配合 115200 8N1 的串口参数与第 7 节的 SWD 接线/复位键技巧,就足以在这块廉价 Cortex-M3 板子上完成从构建、烧录到串口交互的完整闭环。
【免费下载链接】RIOTRIOT - The friendly OS for IoT项目地址: https://gitcode.com/GitHub_Trending/riot/RIOT
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考