1. 环境准备与工具安装

在开始MicroROS的STM32移植之前,我们需要先搭建好开发环境。我选择的是Ubuntu 24.04系统,这个版本自带的CMake 3.28版本正好满足MicroROS的编译要求。如果你用的是其他Ubuntu版本,可能需要手动升级CMake,这点我后面会详细说明。

首先是ROS2 Jazzy的安装。我强烈推荐使用鱼香ROS的一键安装脚本,真的省心不少。安装完成后别忘了装上Colcon构建工具:

sudo apt-get install python3-colcon-common-extensions

接下来检查CMake版本,确保是3.28:

cmake --version

如果不是这个版本,可以通过添加官方仓库来升级。我之前用Ubuntu 20.04时就需要手动升级,过程有点折腾,所以直接使用24.04能省去不少麻烦。

STM32CubeMX的安装需要Java环境,先检查一下:

java -version

如果没有安装,运行:

sudo apt install default-jre

然后去ST官网下载Linux版本的STM32CubeMX,解压后直接运行安装脚本即可。记得给执行权限:

chmod +x SetupSTM32CubeMX
./SetupSTM32CubeMX

2. STM32工程配置详解

打开STM32CubeMX后,选择STM32F407ZGT6芯片。这里要特别注意,MicroROS需要较大的内存空间,建议选择RAM至少50KB的芯片。我之前试过STM32F103C8T6,只有20KB RAM,编译时直接报内存溢出错误。

关键配置步骤如下:

  • 使能SYS中的Debug为Serial Wire
  • 配置RCC为外部晶振
  • 设置时钟树到最大频率(对于F407是168MHz)
  • 启用USART3为异步模式并开启全局中断
  • 配置DMA:RX为Circular模式,TX为Normal模式,优先级都是Very High

FreeRTOS配置中,需要为MicroROS任务分配3000字节的堆栈空间。这个值不能太小,否则运行时会出问题。我建议任务名可以自定义,比如"microROS_task"。

在Project Manager中,选择Toolchain为Makefile。这点很重要,因为我们后面要手动修改Makefile来集成静态库。

生成代码前,建议勾选"Generate peripheral initialization as a pair of .c/.h files per peripheral",这样代码结构更清晰。

3. MicroROS构建系统安装

现在来安装micro_ros_setup功能包。这个包是构建静态库的关键,即使不用Docker也要靠它:

source /opt/ros/$ROS_DISTRO/setup.bash
mkdir microros_ws
cd microros_ws
git clone -b $ROS_DISTRO https://github.com/micro-ROS/micro_ros_setup.git src/micro_ros_setup
sudo apt update && rosdep update
rosdep install --from-paths src --ignore-src -y
sudo apt-get install python3-pip
colcon build
source install/local_setup.bash

这个过程可能会遇到网络问题,特别是rosdep update那步。如果失败,可以多试几次,或者换个网络环境。

4. 手动构建静态库的完整流程

4.1 获取工具库源码

在STM32工程目录下克隆工具库:

git clone https://github.com/micro-ROS/micro_ros_stm32cubemx_utils.git

这个库包含了我们需要的所有辅助文件和脚本。

4.2 定制构建脚本

这是最关键的一步。我们需要分析并修改library_generation.sh脚本,使其能在非Docker环境下工作。

先安装交叉编译工具链:

sudo apt update
sudo apt install -y gcc-arm-none-eabi

然后创建my_library_generation.sh,内容如下:

#!/bin/bash
set -e

export ROS_DISTRO=jazzy
export PROJECT=~/你的工程路径
export BASE_PATH=~/你的工程路径/micro_ros_stm32cubemx_utils/microros_static_library

source /opt/ros/$ROS_DISTRO/setup.bash
source install/local_setup.bash

ros2 run micro_ros_setup create_firmware_ws.sh generate_lib

# 后续内容保持原样...

注意要把PROJECT和BASE_PATH改成你的实际工程路径。这个脚本的核心是绕过了Docker,直接使用本地ROS2环境来构建。

4.3 修改工程Makefile

打开STM32工程的Makefile,在"build the application"之前添加:

#######################################
# micro-ROS addons
#######################################
LDFLAGS += micro_ros_stm32cubemx_utils/microros_static_library/libmicroros/libmicroros.a
C_INCLUDES += -Imicro_ros_stm32cubemx_utils/microros_static_library/libmicroros/microros_include

# Add micro-ROS utils
C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/custom_memory_manager.c
C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_allocators.c
C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_time.c

# Set here the custom transport implementation
C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_transports/dma_transport.c

print_cflags:
	@echo $(CFLAGS)

特别注意@echo前面必须是Tab缩进,不能是空格,否则会报错。

4.4 执行构建

在microros_ws目录下运行:

bash ~/你的工程路径/micro_ros_stm32cubemx_utils/microros_static_library/library_generation/my_library_generation.sh

这个过程比较耗时,第一次运行需要下载很多依赖包。如果网络不好可能会失败,多试几次就好。

构建成功后,静态库会生成在libmicroros目录下。你可以检查一下文件大小,正常的libmicroros.a应该在几MB左右。

5. 代码集成与调试

5.1 添加MicroROS支持

将sample_main.c中的头文件复制到freertos.c的适当位置:

#include <rcl/rcl.h>
#include <rcl/error_handling.h>
#include <rclc/rclc.h>
#include <rclc/executor.h>
#include <uxr/client/transport.h>
#include <rmw_microxrcedds_c/config.h>
#include <rmw_microros/rmw_microros.h>
#include <std_msgs/msg/int32.h>

接着复制传输函数声明:

bool cubemx_transport_open(struct uxrCustomTransport * transport);
bool cubemx_transport_close(struct uxrCustomTransport * transport);
size_t cubemx_transport_write(struct uxrCustomTransport* transport, const uint8_t * buf, size_t len, uint8_t * err);
size_t cubemx_transport_read(struct uxrCustomTransport* transport, uint8_t* buf, size_t len, int timeout, uint8_t* err);

然后在MicroROS任务中替换为以下代码:

rmw_uros_set_custom_transport(
    true,
    (void *) &huart3,
    cubemx_transport_open,
    cubemx_transport_close,
    cubemx_transport_write,
    cubemx_transport_read);

rcl_allocator_t freeRTOS_allocator = rcutils_get_zero_initialized_allocator();
freeRTOS_allocator.allocate = microros_allocate;
freeRTOS_allocator.deallocate = microros_deallocate;
freeRTOS_allocator.reallocate = microros_reallocate;
freeRTOS_allocator.zero_allocate = microros_zero_allocate;

if (!rcutils_set_default_allocator(&freeRTOS_allocator)) {
    printf("Error on default allocators (line %d)\n", __LINE__);
}

// micro-ROS应用程序初始化
rcl_publisher_t publisher;
std_msgs__msg__Int32 msg;
rclc_support_t support;
rcl_allocator_t allocator;
rcl_node_t node;

allocator = rcl_get_default_allocator();
rclc_support_init(&support, 0, NULL, &allocator);
rclc_node_init_default(&node, "cubemx_node", "", &support);
rclc_publisher_init_default(&publisher, &node, 
    ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Int32),
    "cubemx_publisher");

msg.data = 0;
for(;;) {
    rcl_ret_t ret = rcl_publish(&publisher, &msg, NULL);
    if (ret != RCL_RET_OK) {
        printf("Error publishing (line %d)\n", __LINE__);
    }
    msg.data++;
    osDelay(10);
}

最后别忘了在文件开头添加:

#include <stdbool.h>
#include "usart.h"

5.2 编译与烧录

使用make命令编译工程:

make -j8

如果编译成功,会生成firmware.bin文件。我推荐使用ST-Link进行烧录,先安装ST-Link工具:

sudo apt update
sudo apt install -y git make cmake gcc g++ libusb-1.0-0.dev
git clone https://github.com/stlink-org/stlink
cd stlink
make release
sudo make install
sudo ldconfig

烧录命令:

st-flash write build/firmware.bin 0x8000000

5.3 配置MicroROS Agent

烧录完成后,通过USB连接STM32和Ubuntu。首先给串口设备权限:

sudo chmod 777 /dev/ttyACM0

然后安装并启动micro_ros_agent:

source install/local_setup.sh
ros2 run micro_ros_setup create_agent_ws.sh
ros2 run micro_ros_setup build_agent.sh
source install/local_setup.sh
ros2 run micro_ros_agent micro_ros_agent serial -b 115200 --dev /dev/ttyACM0

现在应该能看到Agent成功启动的信息。打开另一个终端,测试通信是否正常:

ros2 topic list
ros2 topic echo /cubemx_publisher

如果能看到不断增长的整数输出,恭喜你,移植成功了!

6. 常见问题与解决方案

在实际操作中,我遇到过不少坑,这里分享几个典型问题的解决方法。

编译错误:CMake版本不兼容 如果遇到CMake版本问题,可以手动安装新版CMake:

wget https://github.com/Kitware/CMake/releases/download/v3.28.0/cmake-3.28.0.tar.gz
tar -xzf cmake-3.28.0.tar.gz
cd cmake-3.28.0
./bootstrap
make -j4
sudo make install

静态库构建失败 有时候因为网络问题,依赖包下载不全。可以尝试多次运行构建脚本,或者手动下载缺失的包。

内存不足错误 如果编译时提示内存不足,可能是STM32芯片选型问题。MicroROS需要至少50KB RAM,建议使用F4系列或更高性能的芯片。

串口通信失败 检查接线是否正确,串口设备权限是否足够。可以用minicom测试串口是否正常工作:

sudo apt install minicom
minicom -D /dev/ttyACM0 -b 115200

Agent连接超时 确保波特率设置正确(115200),并且STM32程序已经正确烧录。有时候重启一下Agent就能解决。

通过这次实践,我深刻体会到非Docker环境虽然前期配置麻烦一些,但对理解底层机制很有帮助。希望这份经验能帮你少走弯路,顺利实现MicroROS的移植。

更多推荐