LibXR_CppCodeGenerator
LibXR 代码生成工具 / Code generator for LibXR
LibXR_CppCodeGenerator 由各平台开发工具的工程生成使用 LibXR
的 C++ 代码,以 pip 包 libxr 发布,命令为 libxr。目前支持三个平台:STM32 读取 STM32CubeMX 工程的
.ioc 文件,MSPM0 读取 SysConfig 工程的 .syscfg,HPM 读取 HPM Pinmux Tool 工程的 .hpmpc;三者都
生成外设对象和入口函数 app_main,STM32 的命令另外把 LibXR 接入工程的 CMake 构建。
LibXR_CppCodeGenerator generates C++ code that uses LibXR
from the projects of each platform's development tool. It is published as the pip package
libxr, with the command libxr. Three platforms are supported: STM32 reads the .ioc file of
an STM32CubeMX project, MSPM0 reads the .syscfg of a SysConfig project, and HPM reads the
.hpmpc of an HPM Pinmux Tool project; all three generate the peripheral objects and the entry
function app_main, and the STM32 commands also add LibXR to the project's CMake build.
🔧 安装 / Installation
需要 Python 3.10 或更高版本。
Requires Python 3.10 or later.
使用 pipx 安装 (Install via pipx)
Windows
python -m pip install --user pipx
python -m pipx ensurepath
python -m pipx install libxr
# 重新打开终端 / Restart your terminal
Linux
sudo apt install pipx
pipx ensurepath
pipx install libxr
# 重新打开终端 / Restart your terminal
使用 pip 安装 (Install via pip)
pip 用于 Windows 或虚拟环境。Debian、Ubuntu 等发行版的系统 Python 由包管理器管理,直接运行
pip install 会报 externally-managed-environment;在这类系统上使用 pipx,或先建立虚拟环境再用 pip
安装。
pip is for Windows or a virtual environment. On Debian, Ubuntu and similar distributions the
package manager owns the system Python, and a plain pip install fails with
externally-managed-environment; there, use pipx, or create a virtual environment first and
install with pip.
Windows
pip install libxr
Linux
sudo apt install python3-venv
python3 -m venv ~/.venvs/libxr
. ~/.venvs/libxr/bin/activate
pip install libxr
# 在激活了虚拟环境的终端中使用 libxr / Use libxr in a terminal with the environment activated
从源码安装 (Install from source)
git clone https://github.com/xrobot-org/LibXR_CppCodeGenerator.git
cd LibXR_CppCodeGenerator
python ./scripts/gen_libxr_version.py
pip install .
scripts/gen_libxr_version.py 记录 LibXR master 当前的提交,libxr stm32 setup 新加入 LibXR 时检出这个
提交。
scripts/gen_libxr_version.py records the current commit of LibXR master, which
libxr stm32 setup checks out when it adds LibXR.
以上三种方式只选其一,不要混用。系统中有多份安装时,命令行实际调用的版本可能与预期不同,而不同版本
生成的代码并不一致。当前使用的版本可通过 libxr --version 查看。BSP 所用的版本由
User/libxr_config.yaml 顶层的 generator: 6.0.1 固定:生成器新建这个文件时写入当前的版本,重新
生成时保留这个键;安装的版本应与之一致,例如 pipx install libxr==6.0.1。
Use only one of these methods. With several installations present, the command line may run a
different version than expected, and different versions generate different code.
libxr --version shows the version in use. The version a BSP uses is pinned by
generator: 6.0.1 at the top level of User/libxr_config.yaml: the generator writes the
current version when it creates this file, and regeneration keeps the key; install the same
version, e.g. pipx install libxr==6.0.1.
📚 基本概念 / Concepts
以一个 STM32F103 的 CubeMX 工程为例:串口 USART1 用作终端,另有 SPI1、I2C1、ADC1、USB、一路 PWM 和
一个标签为 LED 的 GPIO,HAL 时基使用 TIM3,系统为 FreeRTOS。各个概念的对应关系如下:
Take an STM32CubeMX project for an STM32F103: USART1 serves as the terminal, and there are SPI1,
I2C1, ADC1, USB, a PWM channel and a GPIO labeled LED; the HAL timebase is TIM3 and the system
is FreeRTOS. The concepts correspond as follows:
| 概念 Concept | 在这个例子里 | In this example |
|---|---|---|
| CubeMX 工程 CubeMX project | STM32F103RC.ioc、Core/、Drivers/ 和 CMakeLists.txt(Toolchain / IDE 选择 CMake) |
STM32F103RC.ioc, Core/, Drivers/ and CMakeLists.txt (Toolchain / IDE set to CMake) |
| 工程 YAML Project YAML | .config.yaml,libxr parse 从 .ioc 读出的芯片、引脚、外设、DMA 和 RTOS |
.config.yaml, the chip, pins, peripherals, DMA and RTOS that libxr parse reads from the .ioc file |
| 入口源文件 Entry source | User/app_main.cpp,libxr gen 生成的外设对象和 app_main();User Code 区域中的代码在重新生成时保留 |
User/app_main.cpp, the peripheral objects and app_main() generated by libxr gen; the code in its User Code regions is kept on regeneration |
| 生成设置 Generation settings | User/libxr_config.yaml,缓冲区大小、USB 的 CDC、数据库、终端设备、线程优先级等参数 |
User/libxr_config.yaml, parameters such as buffer sizes, the CDCs of USB, the database, the terminal device and thread priorities |
| LibXR 子模块 LibXR submodule | Middlewares/Third_Party/LibXR,工程的 gitlink 固定所用的提交 |
Middlewares/Third_Party/LibXR, pinned to a commit by the project's gitlink |
| CMake 接入 CMake integration | cmake/LibXR.CMake,固定结构,设置块供用户修改,由 CMakeLists.txt include |
cmake/LibXR.CMake, a fixed structure with a settings block for the user to edit, included by CMakeLists.txt |
| 换行符规则 Line endings | .gitattributes,仓库内的文本文件为 LF,签出时按平台转换 |
.gitattributes, text files are LF in the repository and converted on checkout by platform |
🚀 配置工程 / Setting Up a Project
libxr stm32 setup 依次加入 LibXR 子模块、解析 .ioc、生成代码,并接入 CMake。改动工程之前先检查
工程是否有 Core/、一个 .ioc 文件和 CMakeLists.txt,不满足时报错,工程保持原样。-t 指定终端使用的
设备:
libxr stm32 setup adds the LibXR submodule, parses the .ioc file, generates the code and
integrates CMake, in that order. Before changing anything it checks that the project has
Core/, one .ioc file and CMakeLists.txt, and otherwise stops with an error and leaves the
project as it is. -t names the device the terminal uses:
$ libxr stm32 setup -t usart1
[INFO] Default LibXR commit: 4e9670164541b6af6b600a6d544115a9b3e49d98
[INFO] Cloning LibXR from https://github.com/xrobot-org/libxr.git
[INFO] Added the LibXR submodule (https://github.com/xrobot-org/libxr.git).
[INFO] Initializing new LibXR submodule to default commit 4e9670164541b6af6b600a6d544115a9b3e49d98
[INFO] Found .ioc file: .\STM32F103RC.ioc
[INFO] Creating .gitignore file...
[INFO] Creating .gitattributes file...
[INFO] Set terminal_source to usart1 in .\User\libxr_config.yaml
[INFO] Parsing .ioc file...
[INFO] Processing STM32F103RC.ioc...
[INFO] Configuration exported to: .\.config.yaml
[INFO] Generating C++ code...
[INFO] System: FreeRTOS
[INFO] Generated User: wrote app_main.cpp, app_main.h, flash_map.hpp, libxr_config.yaml
[INFO] Generated LibXR.CMake at: cmake\LibXR.CMake
[INFO] LibXR.CMake included in CMakeLists.txt.
[INFO] [Pass] All tasks completed.
[INFO] Next: #include "app_main.h" and call app_main() in the default task StartDefaultTask (Core/Src/main.c), inside USER CODE sections, which CubeMX keeps when it regenerates the code.
[INFO] Build: cmake --preset debug && cmake --build --preset debug
克隆 LibXR 时,libxr 在 GitHub 和镜像中选择响应最快的源。工程中已有的 LibXR 检出保持在原来的提交,
切换版本时使用 --commit。最后两行是接下来的步骤:Core/Src 中还没有源文件调用 app_main() 时,
Next 写出调用的位置,FreeRTOS 工程为默认任务,裸机工程为 main();Build 是 CMakePresets.json
中第一个 preset 的构建命令。工程要求和各项参数见 STM32 代码生成。
.gitattributes 写入 * text=auto、*.sh text eol=lf 和 *.bat text eol=crlf:仓库内的文本文件为
LF,签出时按平台转换,所以在 Windows 和 Linux 上用 CubeMX 重新生成,提交的差异里都只有真实的改动。
已有的 .gitattributes 只补上缺少的行。
When LibXR is cloned, libxr picks the fastest of GitHub and the mirrors. A LibXR checkout
already in the project stays at its commit; --commit switches it. The last two lines are the
next steps: while no source file in Core/Src calls app_main(), Next names where to call
it, the default task in a FreeRTOS project and main() in a bare-metal one; Build is the
build command of the first preset in CMakePresets.json. Project requirements and all options
are described in STM32 code generation.
.gitattributes gets * text=auto, *.sh text eol=lf and *.bat text eol=crlf: text files are
LF in the repository and converted on checkout by platform, so regenerating with CubeMX on
Windows or on Linux shows only real changes in the commit. An existing .gitattributes only
gets the missing lines.
🧩 从 .ioc 到代码 / From .ioc to Code
libxr parse 读出 .ioc 中的外设并打印摘要:
libxr parse reads the peripherals from the .ioc file and prints a summary:
$ libxr parse
[INFO] Processing STM32F103RC.ioc...
[INFO] Configuration exported to: .\.config.yaml
===== [Configuration Summary] =====
MCU: STM32F1 STM32F103RCT6
GPIO (2 pins):
Outputs: 1
Inputs: 1
External Interrupts: 0
Active Peripherals:
TIM: 1 instance(s)
TIM2: Channels=CH3
ADC: 1 instance(s)
ADC1: Channels=1
SPI: 1 instance(s)
SPI1: BaudRate=562.5 KBits/s
USART: 1 instance(s)
USART1
I2C: 1 instance(s)
I2C1
USB: 1 instance(s)
USB
libxr gen 为每个外设生成一个静态对象,CubeMX 中的引脚标签成为对象名。入口源文件按这些部分排列:
include 和 extern 声明只列出用到的驱动头文件和 HAL 句柄,DMA 缓冲区每个一行,app_main() 中每组
外设前有一行说明注释。串口为开启了 DMA 的方向分配缓冲区,例子中的 USART1 两个方向都开启了 DMA。
SPI 总是有发送和接收缓冲区,两个方向都开启 DMA 时才使用 DMA;其他情况下最后一个参数(DMA 切换阈值)
为 UINT32_MAX,传输总是走轮询路径。例子中的 SPI1 没有 DMA:
libxr gen generates one static object per peripheral, and the pin labels set in CubeMX become
object names. The entry source is arranged in these parts: the includes and the extern
declarations list only the driver headers and HAL handles that are used, each DMA buffer takes
one line, and every group of peripherals in app_main() has a comment line. UARTs get buffers
for the directions with DMA; in the example USART1 has DMA in both directions. An SPI always has
transmit and receive buffers and uses DMA only with DMA in both directions; otherwise the last
argument (the DMA threshold) is UINT32_MAX and transfers always take the polling path. SPI1 in
the example has no DMA:
// User/app_main.cpp(节选 / excerpt)
// DMA buffers (STM32F103RC: no D-cache)
alignas(4) static uint16_t adc1_buf[16];
alignas(4) static uint8_t i2c1_buf[32];
alignas(4) static uint8_t spi1_rx_buf[32];
alignas(4) static uint8_t spi1_tx_buf[32];
alignas(4) static uint8_t usart1_rx_buf[128];
alignas(4) static uint8_t usart1_tx_buf[128];
// ...
extern "C" void app_main(void)
{
/* User Code Begin 2 */
/* User Code End 2 */
// Timebase and platform
static STM32TimerTimebase timebase(&htim3);
PlatformInit(static_cast<uint32_t>(Thread::Priority::MEDIUM), 1024);
static STM32PowerManager power_manager;
// GPIO
static STM32GPIO PA8(GPIOA, GPIO_PIN_8);
static STM32GPIO LED(LED_GPIO_Port, LED_Pin);
// ADC
static STM32ADC adc1(&hadc1, adc1_buf, {ADC_CHANNEL_0}, 3.3);
// ...
// PWM
static STM32PWM pwm_tim2_ch3(&htim2, TIM_CHANNEL_3, false);
// SPI, UART, I2C
static STM32SPI spi1(&hspi1, spi1_rx_buf, spi1_tx_buf, UINT32_MAX);
static STM32UART usart1(&huart1, usart1_rx_buf, usart1_tx_buf, 5);
static STM32I2C i2c1(&hi2c1, i2c1_buf, 3);
// USB FS: 1 CDC
// ...
/* User Code Begin 3 */
while (true)
{
Thread::Sleep(UINT32_MAX);
}
/* User Code End 3 */
}
生成的部分已按 LibXR 的 .clang-format(Google 风格、列宽 90、Allman 大括号)排版,clang-format 不会
改动它们。缓冲区的对齐取决于芯片:没有数据 cache 的芯片(F1、F4 等)为 alignas(4);有数据 cache 的
F7、H7 和 N6 按 32 字节的 cache 行对齐,数组大小向上取整到整行,传给驱动的大小仍是配置的值。
libxr_config.yaml 给出 dma_section 时,缓冲区放在这个段:
The generated parts are laid out by the .clang-format of LibXR (Google style, column limit 90,
Allman braces), and clang-format leaves them as they are. The alignment of a buffer depends on
the chip: a chip without a data cache (F1, F4 and others) gets alignas(4); F7, H7 and N6, which
have one, align to the 32-byte cache line and round the array up to a whole line, while the size
a driver is told stays the configured one. With dma_section in libxr_config.yaml, the buffers
go into that section:
// DMA buffers (STM32H723VG: D-cache, 32-byte lines)
alignas(32) static uint8_t usart1_rx_buf[128] __attribute__((section(".axi_ram")));
/* User Code Begin N */ 与 /* User Code End N */ 之间的代码在重新生成时保留,生成结果没有变化的文件
保持原样。区域中的手写代码用到驱动类(如 STM32Flash)、FLASH_REGIONS 或工程的 HAL 句柄(如
htim5)时,生成的文件保留对应的 include 和 extern 声明:
The code between /* User Code Begin N */ and /* User Code End N */ is kept on regeneration,
and files whose content does not change are left as they are. When hand-written code in a region
uses a driver class such as STM32Flash, FLASH_REGIONS or a HAL handle of the project such as
htim5, the generated file keeps the include and the extern declaration for it:
$ libxr gen -i .config.yaml -o User/app_main.cpp
[INFO] System: FreeRTOS
[INFO] Generated User: unchanged app_main.cpp, app_main.h, flash_map.hpp, libxr_config.yaml
各外设的生成规则见 STM32 代码生成 下的各个页面。
The generation rules of each peripheral are described in the pages under STM32 code generation.
⚙️ 生成设置 / Generation Settings
User/libxr_config.yaml 在第一次生成时按默认值创建,记录各外设的缓冲区大小、终端设备、软件定时器和
终端的参数等。修改其中的值后,重新运行 libxr gen 即按新值生成,文件中的修改和注释在重新生成时保留:
User/libxr_config.yaml is created with the defaults on the first generation and records the
buffer sizes of each peripheral, the terminal device, and the parameters of the software timer
and the terminal, among others. After a value is changed, running libxr gen again generates
with the new value; the changes and comments in the file are kept on regeneration:
# User/libxr_config.yaml(节选 / excerpt)
generator: 6.0.1
terminal_source: usart1
software_timer:
priority: 2
stack_depth: 1024
# ...
USART:
usart1:
tx_buffer_size: 128
rx_buffer_size: 128
dma_section: ''
tx_queue_size: 5
# ...
USB:
usb_fs:
enable: true
ep0_packet_size: 8
cdc:
- {tx_fifo_size: 128, rx_fifo_size: 128, queue_size: 3}
# ...
database:
enable: false
block_size: auto
software_timer.priority 以及终端和看门狗的 thread_priority 取 0 到 4 或等级名,0 到 4 依次为
IDLE、LOW、MEDIUM、HIGH、REALTIME。LibXR 按 RTOS 的优先级数把等级换算为 RTOS 优先级,步长
LIBXR_PRIORITY_STEP 为(优先级数 - 1)/ 5:FreeRTOS 的第 n 级为 n 倍步长,configMAX_PRIORITIES 为
56 时 MEDIUM 是 22;ThreadX 数值越小优先级越高,TX_MAX_PRIORITIES 为 32 时 MEDIUM 是 12。
libxr 5.x 把这个数原样作为 RTOS 优先级,步长为 1 的 FreeRTOS 工程两者相同。
software_timer.priority and the thread_priority of the terminal and the watchdog take 0 to 4
or a level name; 0 to 4 are IDLE, LOW, MEDIUM, HIGH and REALTIME in that order. LibXR
converts the levels to RTOS priorities by the RTOS priority count, with the step
LIBXR_PRIORITY_STEP being (priority count - 1) / 5: level n on FreeRTOS is n steps, so MEDIUM
is 22 with configMAX_PRIORITIES 56; on ThreadX lower numbers are higher priorities, and
MEDIUM is 12 with TX_MAX_PRIORITIES 32. libxr 5.x passed the number to the RTOS as it was,
which gives the same priority on a FreeRTOS project with a step of 1.
CubeMX 中处于设备模式的 USB 生成 USB 设备和 CDC 串口 usb_fs_cdc。USB.usb_fs.enable 为 false 时
不生成;工程启用了 CubeMX 的 USB 中间件(如 USB_DEVICE)时,enable 的默认值为 false。设备对象
以 USB 实例命名,例如 USB(FSDEV)为 usb_fs,OTG 为 usb_otg_fs 和 usb_otg_hs。libxr 5.x 按速度
把 OTG 的设备对象命名为 usb_fs 和 usb_hs,CDC 串口的名字没有变化。
A USB in device mode in CubeMX produces a USB device and the CDC serial port usb_fs_cdc. With
USB.usb_fs.enable set to false it is not generated; when the project enables a CubeMX USB
middleware such as USB_DEVICE, enable defaults to false. The device object is named after
the USB instance, such as usb_fs for USB (FSDEV) and usb_otg_fs and usb_otg_hs for OTG.
libxr 5.x named the OTG device objects usb_fs and usb_hs after their speed; the names of the
CDC serial ports are unchanged.
cdc 每路 CDC 写一项,一个 USB 设备可以有几路 CDC。第 N 路(N 从 1 起)生成 usb_otg_hs_cdc、
usb_otg_hs_cdc2 这样的 USB::CDCUart 对象,按顺序分配端点:数据 IN 端点为 EP(2N-1),通知端点为
EP(2N),OTG 的数据 OUT 端点为 EP(N)。端点缓冲区随路数增减,terminal_source 可以指向任意一路,例如
usb_otg_hs_cdc2。cdc_tx_fifo_size、cdc_rx_fifo_size 和 cdc_queue_size 转换为 cdc 的一项,
写回时使用 cdc 的形式:
cdc has one item per CDC, and a USB device can have several. The N-th CDC (N from 1) produces a
USB::CDCUart object such as usb_otg_hs_cdc or usb_otg_hs_cdc2 and takes the endpoints in
order: the data IN endpoint is EP(2N-1), the notification endpoint EP(2N), and on OTG the data
OUT endpoint EP(N). The endpoint buffers follow the number of CDCs, and terminal_source can
name any of them, such as usb_otg_hs_cdc2. cdc_tx_fifo_size, cdc_rx_fifo_size and
cdc_queue_size convert to one item of cdc and are written back in the form of cdc:
USB:
usb_otg_hs:
enable: true
cdc:
- {tx_fifo_size: 128, rx_fifo_size: 128, queue_size: 3}
- {tx_fifo_size: 128, rx_fifo_size: 128, queue_size: 3}
每一项可以加上 interface,作为这路 CDC 控制接口和数据接口的名字。几路 CDC 的 VID:PID 相同,主机按接口名
区分它们;没有 interface 的一路使用 LibXR 的默认名 XRUSB CDC Control 和 XRUSB CDC Data:
Each item can add interface, the name of the control and data interfaces of that CDC. The CDCs
share VID:PID, and the host tells them apart by the interface name; a CDC without interface
keeps the LibXR default names XRUSB CDC Control and XRUSB CDC Data:
USB:
usb_otg_hs:
enable: true
cdc:
- {tx_fifo_size: 128, rx_fifo_size: 128, queue_size: 3, interface: Console}
- {tx_fifo_size: 128, rx_fifo_size: 128, queue_size: 3, interface: Telemetry}
database.enable 为 true 时,app_main() 生成 STM32Flash flash(FLASH_REGIONS, FLASH_REGION_NUMBER)
和 DatabaseRaw<N> database(flash),数据库以 database 注册;FLASH_REGIONS 来自
User/flash_map.hpp,数据库使用 Flash 末尾的两个扇区。模板参数 N 是 Flash 的最小写入单元,单位为
字节,由 block_size 决定:写成正整数时使用这个数,例如 block_size: 32 生成 DatabaseRaw<32>;
默认值 auto 生成 STM32Flash::MIN_WRITE_SIZE,即 LibXR 按芯片的 HAL 得出的值:
With database.enable set to true, app_main() generates STM32Flash flash(FLASH_REGIONS, FLASH_REGION_NUMBER) and DatabaseRaw<N> database(flash), and the database is registered as
database; FLASH_REGIONS comes from User/flash_map.hpp, and the database uses the last two
sectors of the Flash. The template argument N is the minimum write unit of the Flash in bytes
and follows block_size: a positive integer is used as it is, e.g. block_size: 32 generates
DatabaseRaw<32>, and the default auto generates STM32Flash::MIN_WRITE_SIZE, the value LibXR
derives from the HAL of the chip:
// Flash and database
static STM32Flash flash(FLASH_REGIONS, FLASH_REGION_NUMBER);
static DatabaseRaw<STM32Flash::MIN_WRITE_SIZE> database(flash);
数值在生成时检查,不合要求时生成停止,报错写出文件、键和值:
Values are checked during generation; an invalid one stops generation with an error naming the file, the key and the value:
$ libxr gen -i .config.yaml -o User/app_main.cpp
[INFO] System: FreeRTOS
[ERROR] Generation failed: User\libxr_config.yaml: USART.usart1.tx_queue_size 'five' is not a positive integer
🤖 XRobot 集成 / XRobot Integration
--xrobot 在入口源文件中以 XR_REGISTER 注册生成的对象,并在 User Code 区域之后调用
XROBOT_MAIN()。XRobot 的模块按这些名字使用外设。之后的
libxr gen 和 libxr stm32 setup 沿用入口源文件现在的选择,--no-xrobot 取消注册:
With --xrobot, the entry source registers the generated objects with XR_REGISTER and calls
XROBOT_MAIN() after the User Code regions. The Modules of
XRobot use the peripherals by these names. Later runs of
libxr gen and libxr stm32 setup keep the entry source's current choice, and --no-xrobot
removes the registrations:
$ libxr gen -i .config.yaml -o User/app_main.cpp --xrobot
[INFO] System: FreeRTOS
[INFO] Generated User: wrote app_main.cpp; unchanged app_main.h, flash_map.hpp, libxr_config.yaml
XR_REGISTER 按种类分组,每组之间空一行;已注册的对象不再写 UNUSED(...):
XR_REGISTER lines are grouped by kind with a blank line between groups, and registered
objects need no UNUSED(...):
// User/app_main.cpp(节选 / excerpt)
// Hardware registration
XR_REGISTER(power_manager, LibXR::PowerManager);
XR_REGISTER(PA8, LibXR::GPIO);
XR_REGISTER(LED, LibXR::GPIO);
XR_REGISTER(adc1_adc_channel_0, LibXR::ADC);
XR_REGISTER(pwm_tim2_ch3, LibXR::PWM);
XR_REGISTER(spi1, LibXR::SPI);
XR_REGISTER(usart1, LibXR::UART);
XR_REGISTER(usb_fs_cdc, LibXR::UART);
XR_REGISTER(i2c1, LibXR::I2C);
// ...
/* User Code Begin 3 */
/* User Code End 3 */
XROBOT_MAIN();
}
已有入口源文件的 User Code 3 仍是不带 --xrobot 时生成的默认循环时,加上 --xrobot 重新生成会清空
这个循环,使其后的 XROBOT_MAIN() 能够执行;User Code 3 的其他内容保持不变。
When User Code 3 of an existing entry source still holds the default loop generated without
--xrobot, regenerating with --xrobot empties the loop, so that the XROBOT_MAIN() after it
runs; any other content of User Code 3 is kept.
libxr stm32 cmake 和 libxr stm32 setup 按入口源文件的选择在 cmake/LibXR.CMake 的设置块中加入或
删除 XROBOT_MODULES_DIR,XRobot 的模块随之参与构建:
libxr stm32 cmake and libxr stm32 setup add or remove XROBOT_MODULES_DIR in the settings
block of cmake/LibXR.CMake according to the entry source's choice, so that the XRobot Modules
are built with the project:
$ libxr stm32 cmake
[INFO] LibXR.CMake: added set(XROBOT_MODULES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Modules"), as User/app_main.cpp uses XRobot
[INFO] Updated existing LibXR.CMake for system: FreeRTOS
[INFO] LibXR.CMake already included in CMakeLists.txt.
使用 XRobot 的工程,libxr stm32 setup、libxr mspm0 setup 和 libxr hpm setup 在最后给出 XRobot 的
下一步:BSP 根目录还没有 Modules/modules.yaml 时,依次列出 XRobot 的设置命令 xrobot init、
xrobot module add、xrobot setup 和 xrobot instance add;已经有了时,提醒运行 xrobot gen,
因为 User/xrobot_main.hpp 由 XRobot 生成,libxr 的 setup 不更新它。
For a project that uses XRobot, libxr stm32 setup, libxr mspm0 setup and libxr hpm setup end
with the next XRobot step: while the BSP root has no Modules/modules.yaml yet, they list the
XRobot setup commands in order, xrobot init, xrobot module add, xrobot setup and
xrobot instance add; once it exists, they remind to run xrobot gen, since XRobot generates
User/xrobot_main.hpp and the libxr setup does not update it.
详见 与 XRobot 集成。
See XRobot integration.
🔨 CMake 与工具链 / CMake and Toolchains
libxr stm32 cmake 整体生成 cmake/LibXR.CMake,并在 CMakeLists.txt 中 include 它;libxr stm32 setup
已包含这一步。文件的结构固定,设置块在最前,其后依次是 LibXR、Application、库的优化设置和固件镜像:
libxr stm32 cmake generates cmake/LibXR.CMake as a whole and includes it from
CMakeLists.txt; libxr stm32 setup already does this. The structure of the file is fixed: the
settings block comes first, followed by LibXR, Application, the optimization of the libraries
and the firmware images:
# Generated by `libxr stm32 setup`; edit the values in the "Project settings" block only.
# ---- Project settings --------------------------------------------------------
set(LIBXR_SYSTEM FreeRTOS)
set(LIBXR_DRIVER st)
set(XROBOT_MODULES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Modules")
# User sources of the application; "" when CMakeLists.txt adds them itself.
set(LIBXR_USER_SOURCES_GLOB "${CMAKE_CURRENT_SOURCE_DIR}/User/*.cpp")
# Optimization level of the application in Debug builds and of everything in Release builds;
# "" keeps the level of the toolchain file.
set(LIBXR_OPT_DEBUG "-Og")
set(LIBXR_OPT_RELEASE "")
# ---- LibXR -------------------------------------------------------------------
# ...
重写时设置块中用户改过的值和增加的内容保留,LIBXR_SYSTEM 取 Core/Inc 中的
FreeRTOSConfig.h 或 app_threadx.h 所决定的系统,XROBOT_MODULES_DIR 与入口源文件的选择一致,其余
各块重新生成。已有的 LibXR.CMake 按这个结构重写:设置的值保留,LIBXR_OPT_DEBUG 和
LIBXR_OPT_RELEASE 取已用的优化级别(工具链文件中的 CMAKE_CXX_FLAGS_DEBUG 和
CMAKE_CXX_FLAGS_RELEASE,两个工具链文件不同时留空),重新生成的语句之外的内容保留在
Kept from the earlier LibXR.CMake 块中;旧文件 Debug 块中用户改过的库优化选项也原样放在这里,
包在同样的 if(CMAKE_BUILD_TYPE STREQUAL "Debug") 中,排在库的 -O2 之后,因此仍然生效。
LIBXR_OPT_DEBUG 是应用的 Debug 优化级别,LIBXR_OPT_RELEASE 是应用、xr 和 CubeMX 生成的库在
Release 构建中的优化级别;Debug 构建中 xr 和 CubeMX 生成的全部库目标使用 -O2(libxr 5.x 只包括
FreeRTOS、STM32_Drivers 和 USB_Device_Library,ThreadX 等其他库目标使用工具链的 Debug 级别)。
目标的编译选项排在工具链的 CMAKE_<LANG>_FLAGS_<CONFIG> 之后,所以最后一个 -O 就是这里设置的级别。
值为 "" 时沿用工具链文件中的级别,CubeMX 写出的 GCC 为 -Os、ST Arm Clang 为 -Oz;新工程的
LIBXR_OPT_RELEASE 为 ""。
On a rewrite the values the user changed in the settings block, and what the user added there,
stay; LIBXR_SYSTEM takes the system that FreeRTOSConfig.h or app_threadx.h in Core/Inc
decides, XROBOT_MODULES_DIR agrees with the entry source's choice, and the other blocks are
generated again. An existing LibXR.CMake is rewritten in this structure: the values of the
settings stay, LIBXR_OPT_DEBUG and LIBXR_OPT_RELEASE take the optimization levels in use (the
CMAKE_CXX_FLAGS_DEBUG and CMAKE_CXX_FLAGS_RELEASE of the toolchain files, empty when the two
toolchain files differ), and what is not among the regenerated statements stays in the
Kept from the earlier LibXR.CMake block; the library optimization options the user changed
in the Debug block of the old file go there as written too, inside the same
if(CMAKE_BUILD_TYPE STREQUAL "Debug") and after the -O2 of the libraries, so they still apply.
LIBXR_OPT_DEBUG is the Debug optimization level of the application, and LIBXR_OPT_RELEASE
the Release level of the application, xr and the libraries CubeMX generates; in Debug builds
xr and every library target CubeMX generates use -O2 (libxr 5.x covered only FreeRTOS,
STM32_Drivers and USB_Device_Library, and other library targets such as ThreadX used the
Debug level of the toolchain). Target compile options come after the toolchain's
CMAKE_<LANG>_FLAGS_<CONFIG>, so the last -O is the level set here. With "" the level of the
toolchain file applies, -Os for GCC and -Oz for ST Arm Clang as CubeMX writes them; a new
project has LIBXR_OPT_RELEASE set to "".
应用每次链接之后,固件镜像块用工具链文件中的 CMAKE_OBJCOPY 由 ELF 生成 <工程名>.hex(Intel HEX)
和 <工程名>.bin(二进制镜像),三个文件位于同一目录,用 CubeMX 的 preset 构建时为 build/<preset>/。
After each link of the application, the firmware image block makes <project>.hex (Intel HEX)
and <project>.bin (binary image) from the ELF with the CMAKE_OBJCOPY of the toolchain file;
the three files are in the same directory, build/<preset>/ when built with a CubeMX preset.
cmake/starm-clang.cmake 和 cmake/gcc-arm-none-eabi.cmake 保持 CubeMX 写出的内容。libxr stm32 toolchain
切换 CMakePresets.json 中默认的工具链,在 GCC 与 ST Arm Clang 之间切换时删除以前的构建目录,下次
构建重新配置;ST Arm Clang 还可以选择标准库,这时只改写 CubeMX 在 starm-clang.cmake 中写出的
set(STARM_TOOLCHAIN_CONFIG ...) 一行:
cmake/starm-clang.cmake and cmake/gcc-arm-none-eabi.cmake keep what CubeMX wrote.
libxr stm32 toolchain switches the default toolchain in CMakePresets.json; switching between
GCC and ST Arm Clang removes the old build directories, and the next build configures again. ST
Arm Clang can also select its standard library, which rewrites only the
set(STARM_TOOLCHAIN_CONFIG ...) line that CubeMX wrote in starm-clang.cmake:
$ libxr stm32 toolchain gcc
[INFO] Switched the default preset to cmake/gcc-arm-none-eabi.cmake
[INFO] Removed build, configured with the previous toolchain
[INFO] Done.
$ libxr stm32 toolchain clang --newlib
[INFO] Switched the default preset to cmake/starm-clang.cmake
[INFO] Set STARM_TOOLCHAIN_CONFIG to "STARM_NEWLIB" in cmake\starm-clang.cmake
[INFO] Done.
💾 Flash 布局 / Flash Layout
libxr stm32 flash-info 按型号推算 Flash 扇区表,libxr gen 据此生成 User/flash_map.hpp:
libxr stm32 flash-info derives the flash sector table of a model, from which libxr gen
generates User/flash_map.hpp:
$ libxr stm32 flash-info STM32F103RCT6
model: STM32F103RCT6
flash_base: '0x08000000'
flash_size_kb: 256
sectors:
- index: 0
address: '0x08000000'
size_kb: 2.0
- index: 1
address: '0x08000800'
size_kb: 2.0
# ...
- index: 127
address: '0x0803F800'
size_kb: 2.0
🧩 从 .syscfg 到代码 / From .syscfg to Code
libxr mspm0 setup 面向 SysConfig 工程:根目录有一份 .syscfg 文件,main.c 调用 SysConfig 生成的
SYSCFG_DL_init() 后进入 app_main()。命令写 .gitignore(已有的不动),解析工程到 .config.yaml,
生成 User/app_main.cpp、app_main.h 和 libxr_config.yaml。设置了环境变量 SYSCONFIG_TOOL 和
MSPM0_SDK_INSTALL_DIR 时,解析运行一次 SysConfig;没有设置时复用构建目录中比 .syscfg 新的 SysConfig
输出。下例设置了这两个变量:
libxr mspm0 setup works on a SysConfig project: one .syscfg file at the root, and a main.c
that calls the SysConfig-generated SYSCFG_DL_init() before entering app_main(). The command
writes .gitignore (an existing one stays), parses the project into .config.yaml, and generates
User/app_main.cpp, app_main.h and libxr_config.yaml. With the environment variables SYSCONFIG_TOOL
and MSPM0_SDK_INSTALL_DIR set, parsing runs SysConfig once; without them it reuses a SysConfig output
newer than the .syscfg in the build directories. The example has both variables set:
$ libxr mspm0 setup
[INFO] Processing mspm0g3507_minidb48.syscfg...
[INFO] Running SysConfig on mspm0g3507_minidb48.syscfg
[INFO] Configuration exported to: .\.config.yaml
[INFO] System: bare metal
[INFO] .\User\libxr_config.yaml does not exist; creating it with the default settings
[INFO] terminal_source is not set; using uart0
[INFO] Generated User: wrote app_main.cpp, app_main.h, libxr_config.yaml
[INFO] Next: run `xrobot gen` to bring User/xrobot_main.hpp up to date; libxr setup does not update it
===== [Configuration Summary] =====
MCU: MSPM0 MSPM0G3507
GPIO (4 pins):
LED1: PB8, OUTPUT
LED2: PA16, OUTPUT
KEY1: PB24, INPUT, FALL interrupt
KEY2: PB20, INPUT, FALL interrupt
Active Peripherals:
UART: 2 instance(s)
UART_0
UART_1
I2C: 2 instance(s)
I2C_0
I2C_1
SPI: 1 instance(s)
SPI_1
PWM: 1 instance(s)
PWM_TIMA1
Other: 5 instance(s)
ADC12_0
ADC12_1
DAC0
MCAN_0
QEI_TIMG8
缓冲区大小等设置在 libxr_config.yaml 中。GPIO 以引脚标签命名(LED1),UART、I2C、SPI 以小写的外设名
命名(uart0、i2c0),PWM 为 pwm_tima1_c0;terminal_source 指定终端使用的串口,未设置时用第一个 UART。
生成总是包含 static MSPM0PowerManager power_manager;,使用 XRobot 时把它登记为 PowerManager。
流程、设置与约束的完整说明见 MSPM0 代码生成。
The settings such as the buffer sizes live in libxr_config.yaml. GPIO objects are named after
the pin labels (LED1), UART, I2C and SPI after their lowercase peripheral names (uart0, i2c0),
and a PWM is pwm_tima1_c0; terminal_source names the UART the terminal uses, the first one when it is not
set. The generation always emits static MSPM0PowerManager power_manager;, registered as a
PowerManager with XRobot. The flow, the settings and their constraints are described in
MSPM0 code generation.
🧩 从 .hpmpc 到代码 / From .hpmpc to Code
libxr hpm setup 面向 HPM SDK 工程:根目录有 app.yaml,boards/<board>/ 下有唯一的 .hpmpc 文件。
步骤与 MSPM0 相同,输出也是同样的三个文件;引脚从 .hpmpc 中 selectPins 的信号和 main.c 在预处理
条件之外调用的引脚函数读出,main 完全没有调用引脚函数时用 boards/<board>/pinmux.c 的 init_bsp_pins()。
生成的对象按平台命名:GPIO 为 pa10 这样的引脚名,其余为小写的实例(i2c3);GPTMR 输出为
pwm_gptmr0_ch1,在 SoC 没有 PWM 外设时生成(HPM5301 生成,HPM5361 归入 Other):
libxr hpm setup works on an HPM SDK project: app.yaml at the root and the single .hpmpc file
of boards/<board>/. The steps are the ones of MSPM0, and the output is the same three files; the
pins are read from the signals selectPins selects in the .hpmpc and from the pinmux functions
main.c calls outside preprocessor conditions, falling back to the init_bsp_pins() of
boards/<board>/pinmux.c when main calls no pinmux function at all. The generated objects are named after
the platform: GPIO takes the pin name (pa10) and the others the lowercase instance (i2c3), and
a GPTMR output becomes pwm_gptmr0_ch1, generated when the SoC has no PWM peripheral (HPM5301
generates it, on HPM5361 it is listed under Other):
$ libxr hpm setup
[INFO] Configuration exported to: .\.config.yaml
[INFO] System: bare metal
[INFO] .\User\libxr_config.yaml does not exist; creating it with the default settings
[INFO] Generated User: wrote app_main.cpp, app_main.h, libxr_config.yaml
[INFO] Next: run `xrobot gen` to bring User/xrobot_main.hpp up to date; libxr setup does not update it
===== [Configuration Summary] =====
SoC: HPM5301 (QFN48)
GPIO (2 pins):
pa10: PA10
pa3: PA03
Active Peripherals:
I2C: 1 instance(s)
I2C3
PWM: 1 instance(s)
GPTMR0
Other: 7 instance(s)
UART0
UART3
SPI1
ADC0
ACMP
USBPHY
USB0
支持 HPM5301(QFN48)和 HPM5361(LQFP100、LQFP64、QFN48)。UART、SPI 等外设目前只识别,生成时列入
Other。生成总是包含 static HPMPowerManager power_manager;,使用 XRobot 时把它登记为
PowerManager。流程、命名与设置的完整说明见 HPM 代码生成。
HPM5301 (QFN48) and HPM5361 (LQFP100, LQFP64, QFN48) are supported. Peripherals such as UART and
SPI are recognized for now and listed under Other in the generation. The generation always emits
static HPMPowerManager power_manager;, registered as a PowerManager with XRobot. The flow, the
naming and the settings are described in HPM code generation.
📌 引脚布局 / Pin Layout
libxr pins 按型号给出芯片的封装和引脚布局:每个引脚的封装位置、名称、类型和全部可选信号。型号的前缀决定平台,目前支持 STM32、MSPM0 和 HPM;HPM 的型号就是 SoC 名(HPM5301),有多个封装的 SoC(HPM5361)用 --package 选择(LQFP100、LQFP64、QFN48)。输出为 YAML,--format json 输出 JSON。
libxr pins prints the package and pin layout of a chip model: for each pin its position on the package, name, type and all selectable signals. The prefix of the model chooses the platform; STM32, MSPM0 and HPM are supported. The model of an HPM is the SoC name (HPM5301), and a SoC with several packages (HPM5361) selects one with --package (LQFP100, LQFP64, QFN48). The output is YAML, or JSON with --format json.
$ libxr pins MSPM0G3507SPMR
model: MSPM0G3507SPMR
platform: mspm0
part: MSPM0G3507
package: LQFP-64(PM)
pin_count: 64
# ...
- position: '33'
name: PA0
type: Default
signals:
- PA0
- UART0.TX
- I2C0.SDA
# ...
iomux_pincm: 1
modes:
PA0: 1
UART0.TX: 2
I2C0.SDA: 3
# ...
-
libxr pins -d <工程目录>叠加工程已选的信号:STM32 读 CubeMX 的.ioc,MSPM0 读根目录的.syscfg(型号取自工程,封装取自 SysConfig 的--package或--board对应的 LaunchPad),HPM 读boards/下的.hpmpc和main.c在预处理条件之外调用的引脚函数(封装由工程解析得到,也可用--package指定)。输出多一个project段:assignments是每个引脚选了什么(信号、外设、功能、GPIO 标签和是否在器件数据中匹配),peripherals是每个外设用到的引脚和它在libxr_config.yaml中的设置条目(config是列表,每项有段、键、文件中是否已存在和当前参数);文件默认为User/libxr_config.yaml,可用-c指定。HPM 的 GPIO 是整段改名:config一项的键为null,params是段内引脚名到新名的映射。 -
STM32 的封装由型号决定(
STM32H723VGT6为 LQFP100);MSPM0 的封装取自型号后缀中的代码(MSPM0G3507SPMR的PM),型号中没有时用--package给出(LQFP-64、PM或LQFP-64(PM));HPM 的型号是 SoC 名,只有一种封装的 SoC(HPM5301)不必给出封装,-d时封装取自.hpmpc。 -
pin_count是封装上的位置数。一个位置可以有多个条目:STM32G0 的 PA9 和 PA11 可以互换,共用一个位置。 -
peripherals列出从信号名识别出的全部外设和每个功能可选的引脚(USART1的TX可以接PA9、PB6、PB14)。识别只看信号名,ETH、FMC、OctoSPI 这些 LibXR 没有对应抽象的外设也会列出。普通 GPIO 按端口列出(GPIOA的P9是PA9);STM32 的外部中断列为EXTI,LINE9可以来自任一端口的第 9 脚,STM32 的引脚另有gpio_modes(Input、Output、Analog、EXTI 等);有输出通道的定时器带capabilities: [pwm]。TI 的器件数据没有中断信息,所以 MSPM0 不列EXTI。 -
MSPM0 的引脚还有
iomux_pincm和每个信号的模式号modes。 -
MSPM0 外设的设置取自
.syscfg(SysConfig 的配置脚本):每个已选外设的sysconfig有它的模块、名字(UART_0)和参数(targetBaudRate、enabledInterrupts等),project.sysconfig_file是读取的文件。只读,修改在 SysConfig 里进行;表达式原样保留为字符串,引脚的指定和求解器内部的项不收。 -
数据来自厂商:STM32 来自 ST 的 STM32_open_pin_data(BSD-3-Clause),MSPM0 来自 TI SysConfig 的器件数据(TI 有限许可,只可用于 TI 器件),HPM 来自 HPM SDK 的
hpm_iomux.h、hpm_soc_ip.h(BSD-3-Clause)和 HPM5300 数据手册的引脚表。数据文件和各份许可证文本在src/libxr/pin_data/,随包分发;用scripts/build_pin_data.py重新生成。 MSPM0 的.syscfg里可能只写了--board(LaunchPad),封装由 MSPM0 SDK 的板子定义得到(mspm0_boards.json,BSD-3-Clause,许可证文本为LICENSE-TI-BOARDS.txt)。 -
libxr pins -d <project directory>overlays the signals a project has selected: the CubeMX.iocfor an STM32, the.syscfgat the root for an MSPM0 (the model comes from the project, and the package from SysConfig's--packageor the LaunchPad its--boardnames), and the.hpmpcunderboards/plus the pinmux functionsmain.ccalls outside preprocessor conditions for an HPM (the package comes from the project, or from--package). The output gets aprojectsection:assignmentsis what each pin selected (signal, peripheral, function, GPIO label and whether it matched the device data), andperipheralsthe pins each peripheral uses and its entries inlibxr_config.yaml(configis a list whose items carry the section, the key, whether the file already has it and the current parameters); the file isUser/libxr_config.yamlby default or the one given with-c. The GPIO rename of an HPM is one whole section: theconfigitem has the keynull, andparamsmaps the pin names of the section to their new names. -
The package of an STM32 is part of the model (
STM32H723VGT6is LQFP100); that of an MSPM0 comes from the code in the model suffix (PMofMSPM0G3507SPMR), or from--packagewhen the model has none (LQFP-64,PMorLQFP-64(PM)); the model of an HPM is the SoC name, a SoC with one package (HPM5301) needs no package, and with-dthe package comes from the.hpmpc. -
pin_countis the number of positions on the package. A position can have several entries: PA9 and PA11 of an STM32G0 can be swapped and share one position. -
peripheralslists every peripheral recognized from the signal names, with the pins that can carry each function (TXofUSART1can usePA9,PB6orPB14). Recognition looks at the signal names only, so peripherals LibXR has no abstraction for, such as ETH, FMC and OctoSPI, are listed too. Plain GPIO is listed by port (P9ofGPIOAisPA9); the external interrupts of an STM32 are listed asEXTI, whereLINE9can come from pin 9 of any port, and an STM32 pin also hasgpio_modes(Input, Output, Analog, EXTI, ...); a timer with output channels carriescapabilities: [pwm]. TI's device data has no interrupt information, so an MSPM0 lists noEXTI. -
An MSPM0 pin also has
iomux_pincmandmodes, the mode of each signal. -
The settings of an MSPM0 peripheral come from the
.syscfg, the configuration script of SysConfig: each selected peripheral has asysconfigwith its module, its name (UART_0) and its parameters (targetBaudRate,enabledInterrupts, ...), andproject.sysconfig_fileis the file read. They are read-only, edited in SysConfig; an expression is kept as written, as a string, and pin assignments and the solver's own items are left out. -
The data comes from the vendors: STM32 from ST's STM32_open_pin_data (BSD-3-Clause), MSPM0 from the device data of TI SysConfig (TI limited license, for TI devices only), and HPM from the
hpm_iomux.handhpm_soc_ip.hof the HPM SDK (BSD-3-Clause) and the pin tables of the HPM5300 datasheet. The data files and the license texts are insrc/libxr/pin_data/and are distributed with the package;scripts/build_pin_data.pyrebuilds them. A.syscfgof an MSPM0 may name only a--board(a LaunchPad); the package then comes from the board definitions of the MSPM0 SDK (mspm0_boards.json, BSD-3-Clause, license text inLICENSE-TI-BOARDS.txt).
🚀 命令一览 / Commands
parse 和 gen 按工程所属的平台选择解析器和生成器,只属于某个平台的命令放在平台名之下。
parse and gen choose the parser and the generator by the project's platform; commands that
belong to one platform sit under its name.
| 命令 Command | 说明 | Description |
|---|---|---|
libxr parse |
解析工程,写出工程 YAML | Parse a project into the project YAML |
libxr gen |
由工程 YAML 生成入口源文件 | Generate the entry source from the project YAML |
libxr pins |
打印某个型号的封装和引脚布局 | Print the package and pin layout of a model |
libxr stm32 setup |
为 CubeMX 工程加入 LibXR,生成代码并接入 CMake | Add LibXR to a CubeMX project, generate the code and integrate CMake |
libxr mspm0 setup |
为 SysConfig 工程生成 LibXR 代码 | Generate LibXR code for a SysConfig project |
libxr hpm setup |
为 HPM 工程生成 LibXR 代码 | Generate LibXR code for an HPM project |
libxr stm32 cubemx-gen |
以脚本模式运行 STM32CubeMX,由 .ioc 重新生成 CubeMX 工程 |
Run STM32CubeMX in script mode to regenerate the CubeMX project from the .ioc file |
libxr stm32 cmake |
把 LibXR 接入 CubeMX 的 CMake 工程 | Integrate LibXR into the CubeMX CMake project |
libxr stm32 flash-info |
打印某个型号的 Flash 布局 | Print the flash layout of a model |
libxr stm32 toolchain |
切换工具链和 ST Arm Clang 的标准库 | Switch the toolchain and the ST Arm Clang standard library |
入门教程和完整说明见文档 / Tutorials and reference: https://xrobot.work/docs/code_gen · https://xrobot.work/en/docs/code_gen
旧命令 / Old commands
6.0.0 之前的 xr_* 命令仍可使用,参数与原来相同,运行时提示对应的新命令,将在 7.0.0 删除。以下几处
行为与 libxr 5.2.4 不同:xr_gen_code 和 xr_gen_code_stm32 收到 --hw-cntr 时报错退出,它生成的
HardwareContainer 已从 LibXR 删除,XRobot 工程改用 --xrobot;xr_parse 和 xr_parse_ioc 在含有
多个 .ioc 文件的目录中报错退出,不再逐个解析;xr_stm32_toolchain_switch clang 不带 -g、-n 或
-p 时保持当前的标准库,不再报错;xr_stm32_toolchain_switch 在 GCC 与 ST Arm Clang 之间切换时删除
build/ 和 cmake-build*,xr_stm32_cmake 则不再删除它们,CMake 在下次构建时重新配置。
The xr_* commands of versions before 6.0.0 still work with the same arguments; they name their
new command when run and are removed in 7.0.0. A few behaviors differ from libxr 5.2.4:
xr_gen_code and xr_gen_code_stm32 stop with an error on --hw-cntr, as LibXR no longer has
the HardwareContainer it generated, and XRobot projects use --xrobot instead; xr_parse and
xr_parse_ioc stop with an error in a directory with several .ioc files instead of parsing
each; xr_stm32_toolchain_switch clang without -g, -n or -p keeps the current standard
library instead of failing; xr_stm32_toolchain_switch removes build/ and cmake-build* when
it switches between GCC and ST Arm Clang, while xr_stm32_cmake no longer removes them, and
CMake configures again on the next build.
| 旧命令 Old | 新命令 New |
|---|---|
xr_parse、xr_parse_ioc |
libxr parse |
xr_gen_code、xr_gen_code_stm32 |
libxr gen |
xr_cubemx_cfg |
libxr stm32 setup |
xr_cubemx_generate |
libxr stm32 cubemx-gen |
xr_stm32_cmake |
libxr stm32 cmake |
xr_stm32_flash |
libxr stm32 flash-info |
xr_stm32_toolchain_switch |
libxr stm32 toolchain |
🧪 测试 / Tests
pip install clang-format==21.1.8
python -m unittest discover -s tests -v
生成的 C++ 文件按 LibXR 的风格排版,测试用固定版本 21.1.8 的 clang-format 核对 DevC、MC02 和随机工程的 输出;没有安装这个版本时,这些测试被跳过。
The generated C++ files follow the style of LibXR, and the tests check the output for DevC, MC02 and random projects against clang-format 21.1.8; they are skipped without that version.
📖 更多信息 / More Information
Metadata
Release files for libxr 6.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| libxr-6.0.1.tar.gz | 1.4 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| libxr-6.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.6 MB
Release files / libxr-6.0.1.tar.gz
| Download URL | libxr-6.0.1.tar.gz |
|---|---|
| Size | 1.4 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3df17894fe597c5dff8d6337a5cdcc99bee1f7a819a4232b35db31a15def3faa
|
|
BLAKE2b-256 checksum How to use checksums |
c48b0b8c471de383a7205144d1c60c8efbc8405a0d7955e76b6241a4b5eba74c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.
Transparency logRelease files / libxr-6.0.1-py3-none-any.whl
| Download URL | libxr-6.0.1-py3-none-any.whl |
|---|---|
| Size | 1.2 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a577f553523cd4eeda99d72d22ad39362c4e0d8f0c44cd051800b75e74f362a2
|
|
BLAKE2b-256 checksum How to use checksums |
a047db7150c0a89ef191eeaabdbff343b93d7afd3bf2dfe8e2580def18101c47
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.
Transparency log