RIOT 中的 Olimexino-stm32 板级支持:硬件外设、SAUL 映射与 stm32flash 烧录实战
【免费下载链接】RIOTRIOT - The friendly OS for IoT项目地址: https://gitcode.com/GitHub_Trending/riot/RIOT
导读
本文围绕 RIOT 操作系统对Olimexino-stm32开发板的板级支持展开,系统梳理其基于 STM32F103RB(ARM Cortex-M3)的硬件资源、外设驱动实现状态、GPIO/LED/按键引脚定义、SAUL 传感器抽象映射,以及使用 stm32flash 完成编译烧录与串口终端连接的完整流程。读完本文,你将掌握如何用BOARD=olimexino-stm32 make flash烧录固件、如何根据 periph_conf.h 定位 UART/SPI/I2C/PWM/ADC 引脚,以及如何复用 SAUL 直接访问板载 LED 与按键。
板卡概览
Olimexino-stm32 是 Olimex 公司 Olimexino 系列中的一块开发板,核心是一颗意法半导体的STM32F103RB微控制器。在 RIOT 中,它的板级支持位于 boards/olimexino-stm32,属于boards_olimexino-stm32这个 defgroup,文档主体即 boards/olimexino-stm32/doc.md。
从硬件定位看,这是一块面向 IoT 原型验证的经典 STM32F1 平台:RAM 仅 20KB、Flash 128KB,但外设接口非常齐全,板载 UART、SPI、I2C、ADC、PWM、CAN、USB 与 RTC,适合驱动各类传感器与执行器。
MCU 核心参数
| 项目 | 参数 |
|---|---|
| MCU | STM32F103RB |
| 内核家族 | ARM Cortex-M3 |
| 厂商 | ST Microelectronics |
| RAM | 20Kb |
| Flash | 128Kb |
| 最高主频 | 72MHz |
| FPU | 无 |
| 定时器 | 7(2 个看门狗、1 个 SysTick、4 个 16 位定时器) |
| ADC | 1 路 12 位(16 通道) |
| UART | 3 个 |
| SPI | 2 个 |
| I2C | 2 个 |
| RTC | 1 个 |
| USB | 1 个 |
| CAN | 1 个 |
| 工作电压 Vcc | 2.0V - 3.6V |
说明:以上表格内容直接取自 boards/olimexino-stm32/doc.md 的 Hardware 一节;其中 "Kb" 为原文档表述,对应 20KB SRAM 与 128KB 程序 Flash。数据手册、参考手册、编程手册与板卡手册的链接均为 ST 与 Olimex 官方文档,本文不再另行转载。
板级标识与晶振选型
在 RIOT 的构建系统中,这块板由 boards/olimexino-stm32/Makefile.features 声明:
CPU = stm32 CPU_MODEL = stm32f103rb # Put defined MCU peripherals here (in alphabetical order) FEATURES_PROVIDED += periph_adc FEATURES_PROVIDED += periph_can 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可以看到该板提供了 ADC、CAN、I2C、PWM、RTC、RTT、SPI、TIMER、UART 九类外设特性,这是 RIOT 依赖解析与FEATURES_REQUIRED检查的基础。对应地,Kconfig 菜单(boards/olimexino-stm32/Kconfig)声明了BOARD_OLIMEXINO_STM32,并select CPU_MODEL_STM32F103RB、BOARD_HAS_HSE、BOARD_HAS_LSE——即板卡提供了 HSE(外部高速晶振)与 LSE(外部低速晶振)。这两个符号在 boards/common/stm32/Kconfig 中定义,并在 periph_conf.h 顶部以CONFIG_BOARD_HAS_HSE/CONFIG_BOARD_HAS_LSE宏形式确认,供 STM32 时钟配置(clk_conf.h)选用外部晶振作为时钟源。
外设驱动实现状态
RIOT 对 Olimexino-stm32 的外设支持情况,在 doc.md 的 "Implementation Status" 一节中有明确清单:
| 设备 | ID | 支持情况 | 备注 |
|---|---|---|---|
| MCU | STM32F103RB | 部分支持 | 低功耗模式未完全利用 |
| 底层驱动 | GPIO | 支持 | |
| PWM | 支持(4 个引脚可用) | ||
| UART | 3 个 | USART2 走 D0(RX)/D1(TX),USART1 走 PA10(RX)/PA09(TX),USART3 走 PB11(RX)/PB10(TX) | |
| ADC | 6 路 | ||
| I2C | 支持(I2C1 与 I2C2) | ||
| SPI | 支持(SPI1 与 SPI2) | ||
| USB | 不支持 | ||
| 定时器 | 3 个 16 位定时器(TIM2、TIM3、TIM4) |
这段状态表是 RIOT 开发者评估该板可用性的第一手依据:核心 MCU 已可用但低功耗(Energy saving modes)没有充分利用;USB 外设暂未支持;其余常用外设基本齐全。
外设引脚映射的源码级对照
"Implementation Status" 表中提到的引脚分配,在 boards/olimexino-stm32/include/periph_conf.h 中有完整的静态配置数组可以逐一核对。
UART
uart_config[]定义了 3 个串口,与文档描述完全一致:
| 串口 | TX 引脚 | RX 引脚 | 总线 | 中断 |
|---|---|---|---|---|
| USART2(UART 0) | PA2 | PA3 | APB1 | USART2_IRQn |
| USART1(UART 1) | PA9 | PA10 | APB2 | USART1_IRQn |
| USART3(UART 2) | PB10 | PB11 | APB1 | USART3_IRQn |
其中 USART2 对应文档所说的 D1(TX)/D0(RX),是默认串口输出;USART1(PA9/PA10)同时被用于烧录(详见下文烧录章节);USART3 位于 PB10/PB11。中断服务函数分别映射为isr_usart2、isr_usart1、isr_usart3。
SPI 与 I2C
SPI 与 I2C 各两个,配置如下:
- SPI1:MOSI=PA7、MISO=PA6、SCLK=PA5,挂在 APB2 总线(
RCC_APB2ENR_SPI1EN); - SPI2:MOSI=PB15、MISO=PB14、SCLK=PB13,挂在 APB1 总线(
RCC_APB1ENR_SPI2EN); - I2C1:SCL=PB8、SDA=PB9,
I2C_SPEED_NORMAL速度; - I2C2:SCL=PB10、SDA=PB11,同样为
I2C_SPEED_NORMAL。
值得注意的细节:SPI 配置中cs_pin = GPIO_UNDEF,说明片选信号交由用户代码自行管理;而 I2C 配置的注释明确提示 "This board may require external pullup resistors for i2c operation",即板卡 I2C 可能没有集成上拉电阻,接入 I2C 外设时需要外部上拉才能稳定工作。这两点对实际焊接/接线排障很有参考价值。
ADC 与 PWM
ADC 配置暴露了 6 个通道,全部位于 PORTC:
| ADC 通道 | 引脚 |
|---|---|
| 0 | PC0 |
| 1 | PC1 |
| 2 | PC2 |
| 3 | PC3 |
| 4 | PC4 |
| 5 | PC5 |
PWM 则提供了 4 个定时器组、共 16 个可用输出通道:
| PWM 设备 | 通道 0 | 通道 1 | 通道 2 | 通道 3 | 总线 |
|---|---|---|---|---|---|
| TIM1 | PA8 | PA9 | PA10 | PA11 | APB2 |
| TIM2 | PA0 | PA1 | PA2 | PA3 | APB1 |
| TIM3 | PA6 | PA7 | PB0 | PB1 | APB1 |
| TIM4 | PB6 | PB7 | PB8 | PB9 | APB1 |
这里可以观察到引脚复用策略:PA9/PA10 同时出现在 USART1 与 TIM1 的 PWM 通道中,PA2/PA3 同时是 USART2 与 TIM2 的 PWM 通道,PB8/PB9 同时是 I2C1 与 TIM4 的 PWM 通道——实际使用任一外设时,必须注意 RIOT 的引脚复用保护,避免同时使能相互冲突的引脚功能。
定时器与 RTT
timer_config[]将 TIM2、TIM3、TIM4 三个 16 位定时器注册为 RIOT 定时器(TIMER_NUMOF= 3),最大计数值0x0000ffff,对应 ISR 为isr_tim2/3/4。RTT(实时计数器)频率定义为RTT_FREQUENCY (16384)Hz,即使用 LSE 32.768kHz 经二分频后的 16.384kHz 作为 RTT 时钟,这正好印证了板卡提供 LSE 晶振的配置。
LED、按键与 SAUL 抽象
板载 LED 与按键定义
boards/olimexino-stm32/include/board.h 定义了板级的基础资源:
- LED0:PA1(GPIO_PORT_A / PORT_A);
- LED1:PA5;
- LED_PANIC:LED0,用于内核 panic 指示;
- BTN0 用户按键:PC9,输入模式
GPIO_IN; - XTIMER 配置:
XTIMER_WIDTH为 16 位,XTIMER_BACKOFF为 19。
LED 的LED0_ON/OFF/TOGGLE系列宏并非在该板单独实现,而是由公共头文件 boards/common/stm32/include/stm32_leds.h 根据LEDn_PORT_NUM、LEDn_PIN_NUM自动展开:板级只声明引脚号与端口,公共头通过GPIO_PIN()拼出LEDn_PIN,再基于periph/gpio_ll.h的gpio_ll_set/clear/toggle提供开关与翻转操作。这是 STM32 系列板卡共享配置片段的典型用法。
SAUL GPIO 映射
RIOT 的 SAUL(Sensor Actuator Uber Layer)子系统允许把外设直接映射为统一的传感器/执行器接口。Olimexino-stm32 在 boards/olimexino-stm32/include/gpio_params.h 中注册了三个 SAUL 节点:
| SAUL 名称 | 引脚 | 模式 |
|---|---|---|
| LED2 | LED0_PIN(PA1) | GPIO_OUT |
| LED1 | LED1_PIN(PA5) | GPIO_OUT |
| BUT | BTN0_PIN(PC9) | GPIO_IN |
这些条目填充在saul_gpio_params_t数组中,其结构定义位于 drivers/include/saul/periph.h(包含name、pin、mode、flags字段)。同时 boards/olimexino-stm32/Makefile.dep 做了依赖联动:只要应用USEMODULE中包含saul_default,就会自动追加saul_gpio,从而在saulshell 命令下可以直接按名称操作 LED1/LED2 与读取按键 BUT。
从源码结构看,gpio_params.h中命名 "LED2" 对应的是物理 LED0(PA1),"LED1" 对应物理 LED1(PA5),命名与板卡丝印可能存在的差异在使用 SAUL 时需留意。
编译、烧录与串口终端
烧录工具链:stm32flash
与其他 STM32 板卡不同,Olimexino-stm32 没有板载调试器,文档明确要求使用stm32flash(一款基于串口 bootloader 的 STM32 烧录工具)进行烧录。RIOT 的构建系统已经内置了完整的 stm32flash 支持:
boards/olimexino-stm32/Makefile.include 中:
# set default port depending on operating system PORT_LINUX ?= /dev/ttyUSB0 PROGRAMMER=stm32flash # Setup of programmer and serial is shared between STM32 based boards include $(RIOTMAKE)/boards/stm32.inc.mkPROGRAMMER=stm32flash直接固定了烧录器;默认串口在 Linux 下为/dev/ttyUSB0(通过 USB-TTL 适配器枚举出的设备节点)。stm32flash 的具体参数由公共的 makefiles/boards/stm32.inc.mk 提供:
PROG_BAUD ?= 57600:烧录波特率;FLASHER = stm32flash,FLASHFILE ?= $(BINFILE):烧录的是 .bin 文件;BIN_ADDR由ROM_START_ADDR + ROM_OFFSET(此处ROM_OFFSET = 0x0)计算得到,即从 Flash 起始地址写入;FFLAGS汇总为-v -b $(PROG_BAUD) -w $(FLASHFILE) -S $(BIN_ADDR) -g $(BIN_ADDR) $(PORT):-v冗余输出、-b设置波特率、-w写 Flash、-S指定起始地址、-g烧录后从该地址启动;- 若启用
STM32FLASH_RESET,还可以通过 TTL 适配器的 RTS/DTR 引脚控制 BOOT0 与 RST,实现一键进入 bootloader 再自动复位运行。
烧录与串口命令
安装好 stm32flash 后,在应用目录下执行:
BOARD=olimexino-stm32 make flash即可编译并烧录。打开串口终端查看输出:
BOARD=olimexino-stm32 make term文档特别强调了一条关键约束:USART1 用于烧录,USART2 才是串口输出。从 periph_conf.h 可以看到,USART2(PA2/PA3)是uart_config[]中的第 0 项,因此也是 RIOT 默认的STDIO串口;而烧录走的是 USART1(PA9/PA10)上的 STM32 系统 bootloader。因此接线时请把 USB-TTL 的 TX/RX 接到 USART2 的 D0(D3)/D1(TX)(PA3/PA2)用于终端,把烧录线接到 USART1 的 PA9/PA10(并配合 BOOT0 拉高进入 bootloader)。
如果默认的/dev/ttyUSB0与设备实际节点不符,可显式覆盖:
PORT=/dev/ttyUSB1 BOARD=olimexino-stm32 make flash BOARD=olimexino-stm32 make termmake term在 Linux 下默认调用miniterm(可通过TERMPROG/TERMFLAGS调整),波特率由串口配置决定。
快速上手示例
结合上述板级资源,一个最小应用可以这样组织:
- 新建应用目录(例如
examples/hello-olimexino),Makefile中声明:
BOARD ?= olimexino-stm32 USEMODULE += saul_default include $(RIOTBASE)/Makefile.includemain.c中使用标准输出与 LED:
#include "board.h" #include "periph/gpio.h" #include "xtimer.h" int main(void) { while (1) { LED0_TOGGLE; printf("Hello from Olimexino-stm32\n"); xtimer_sleep(1); } return 0; }- 编译烧录:
BOARD=olimexino-stm32 make flash BOARD=olimexino-stm32 make term加入saul_default后,终端里还可直接使用saul命令读取 BUT(PC9)电平、控制 LED1/LED2 输出,验证 gpio_params.h 中的映射是否生效。
小结
Olimexino-stm32 是 RIOT 中一块外设丰富、成本友好的 STM32F103RB 开发板。本文从板级文档出发,结合 boards/olimexino-stm32 目录下的 Makefile.features、Kconfig、board.h、periph_conf.h 与 gpio_params.h,完整还原了其 MCU 参数、外设实现状态、引脚映射、SAUL 抽象以及 stm32flash 烧录链路。实践中最需要记住的两点:烧录用 USART1、终端输出用 USART2;I2C 使用前需自备上拉电阻。基于这份板级支持,你可以直接在这块板上开展传感器接入、PWM 电机控制、CAN 通信等 RIOT 应用开发。
【免费下载链接】RIOTRIOT - The friendly OS for IoT项目地址: https://gitcode.com/GitHub_Trending/riot/RIOT
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考