# st-mem
[](https://crates.io/crates/st-mem)
[](https://github.com/cx693/st-mem)
[](https://docs.rs/st-mem)
嵌入式固件内存分析工具。解析 `memory.x` 链接脚本和 ELF 二进制文件,统计 FLASH / RAM 占用,以进度条方式直观展示。
```
[FIRMWARE SIZE]
+----------------------------------------------------------------+
+----------------------------------------------------------------+
```
## 功能
- 解析 GNU LD `memory.x` 链接脚本,提取 FLASH / RAM 区域定义
- 解析 ELF 二进制文件的 section headers,按地址范围归类到 FLASH / RAM
- 以进度条和百分比直观展示固件内存占用
- **Section 拆分统计**:单独展示每个 section 的占用、占比和进度条(`--sections`)
- **数据导出**:输出 JSON / Markdown 格式报告,适用于日志归档和 CI 流水线(`--export`)
- **版本信息**:`-V` 显示版本、作者和项目地址
- Runner 模式:分析完成后自动调用 [probe-rs](https://probe.rs/) 烧录固件
- 跨平台支持(macOS / Linux / Windows)
## 安装
### 从 crates.io 安装(推荐)
```bash
cargo install st-mem
```
### 从源码安装
```bash
git clone https://github.com/cx693/st-mem.git
cd st-mem
cargo install --path .
```
安装后获得 `st-mem` 命令。
## 使用
### 分析固件内存
```bash
st-mem <elf-path>
```
```bash
st-mem target/thumbv7m-none-eabi/release/firmware
```
指定 `memory.x` 路径:
```bash
st-mem target/thumbv7m-none-eabi/release/firmware --memory-x path/to/memory.x
```
### Section 拆分统计
使用 `--sections` 查看每个 section 的独立占用:
```bash
st-mem firmware.elf --sections
```
```
[FIRMWARE SIZE]
+----------------------------------------------------------------+
+----------------------------------------------------------------+
[FLASH Sections] (9 KB total)
NAME SIZE % BAR
.text 7 KB 11.8% [███░░░░░░░░░░░░░░░░░░░░░░░░░░░]
.rodata 1 KB 2.9% [█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░]
.vector_table 304 B 0.5% [█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░]
[RAM Sections] (4 B total)
NAME SIZE % BAR
.bss 4 B 0.0% [█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░]
```
### 数据导出
导出 JSON 格式(适用于程序解析和 CI 流水线):
```bash
st-mem firmware.elf --export json > report.json
```
导出 Markdown 格式(适用于文档归档):
```bash
st-mem firmware.elf --export md > report.md
```
### 查看版本
```bash
st-mem -V
```
```
st-mem v0.1.2
Parse embedded firmware memory layout from memory.x linker scripts and ELF binaries, display FLASH/RAM usage with progress bars
Author: cx693
License: MIT
Repository: https://github.com/cx693/st-mem
```
### Runner 模式(分析 + 烧录)
Runner 模式通过 [probe-rs](https://probe.rs/) 进行固件烧录。`st-mem runner` 在调用 probe-rs 之前先分析固件内存占用,然后将所有参数透传给 `probe-rs run`。
```bash
st-mem runner [probe-rs 参数] <elf-path>
```
```bash
st-mem runner --chip STM32F103C8 --protocol swd target/thumbv7m-none-eabi/release/firmware
```
实际等效于:
```bash
# 1. st-mem 先分析固件大小并显示
# 2. 然后执行:
probe-rs run --chip STM32F103C8 --protocol swd target/thumbv7m-none-eabi/release/firmware
```
### 前置依赖:probe-rs
Runner 模式需要先安装 [probe-rs](https://probe.rs/):
```bash
cargo install probe-rs-tools
```
probe-rs 支持的下载器与芯片:
| ST-Link | `--protocol swd` |
| J-Link | `--protocol jtag` / `--protocol swd` |
| CMSIS-DAP | `--protocol swd` |
芯片通过 `--chip` 参数指定,例如:
```bash
--chip STM32F103C8
--chip STM32F407VG
--chip nRF52840
```
完整芯片列表见 [probe-rs 目标支持](https://probe.rs/targets/)。
### 集成到 cargo
在项目的 `.cargo/config.toml` 中配置:
```toml
[target.thumbv7m-none-eabi]
runner = "st-mem runner --chip STM32F103C8 --protocol swd"
```
配置后 `cargo run` 会自动先显示固件大小再烧录:
```
[FIRMWARE SIZE]
+----------------------------------------------------------------+
+----------------------------------------------------------------+
[INFO] Firmware: target/thumbv7m-none-eabi/release/stm32dome
[FLASH] Programming via probe-rs...
Erasing ✔ 100%
Programming ✔ 100%
Finished in 0.86s
```
如果只需编译后查看大小,可在 `.cargo/config.toml` 添加 alias:
```toml
[alias]
r = "run --release"
```
```bash
cargo r # 编译 + 分析 + 烧录
```
## 命令行参数
| `--memory-x <path>` | memory.x 文件路径 | `memory.x` |
| `--elf <path>` | ELF 文件路径(也可直接用位置参数) | - |
| `--width <n>` | 进度条宽度(字符数) | `30` |
| `--sections` | 显示每个 section 的独立占用(默认关闭) | - |
| `--export <fmt>` | 导出报告:`json` 或 `md`(默认不导出) | - |
| `--version`, `-V` | 显示版本、作者和项目地址 | - |
| `--help`, `-h` | 显示帮助信息 | - |
## 库 API
`st-mem` 同时提供库 API,可在其他 Rust 项目中直接调用。
在 Cargo.toml 中添加依赖:
```toml
[dependencies]
st-mem = "0.1"
```
```rust
use st_mem::{MemoryConfig, analyze_elf, analyze_elf_detailed, format_report, format_sections, ExportReport};
let config = MemoryConfig::from_file("memory.x")?;
let usage = analyze_elf("firmware.elf", &config)?;
println!("{}", format_report(&usage, 30));
// 带 section 详情
let analysis = analyze_elf_detailed("firmware.elf", &config)?;
println!("{}", format_sections(&analysis, 30));
// 导出 JSON
let report = ExportReport::from_analysis(&analysis);
println!("{}", report.to_json());
```
### API 说明
| `MemoryConfig::from_file(path)` | 解析 memory.x 文件 |
| `MemoryConfig::parse(content)` | 从字符串解析 |
| `config.flash()` / `config.ram()` | 获取 FLASH / RAM 区域信息 |
| `analyze_elf(path, &config)` | 分析 ELF 文件,返回 `FirmwareUsage` |
| `analyze_elf_detailed(path, &config)` | 分析 ELF 文件,返回 `ElfAnalysis`(含 section 详情) |
| `format_report(&usage, width)` | 生成格式化的内存报告字符串 |
| `format_sections(&analysis, width)` | 生成 section 拆分统计表格 |
| `ExportReport::from_analysis(&analysis)` | 构建可导出的报告结构 |
| `report.to_json()` | 导出 JSON 格式字符串 |
| `report.to_markdown()` | 导出 Markdown 格式字符串 |
| `format_bytes(bytes)` | 字节数转可读格式(B / KB / MB) |
| `progress_bar(pct, width)` | 生成进度条字符串 |
| `print_report(elf_path, memory_x_path)` | 分析并打印报告到 stdout |
## memory.x 格式
工具解析标准 GNU LD 链接脚本格式:
```ld
MEMORY
{
FLASH : ORIGIN = 0x08000000, LENGTH = 64K
RAM : ORIGIN = 0x20000000, LENGTH = 20K
}
```
支持带属性标志的写法:
```ld
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
}
```
支持的长度单位:`K`(KB)、`M`(MB),也支持小数如 `0.5K`。
## 跨平台
`st-mem` 本身是纯 Rust 二进制,不依赖平台特定工具。Runner 模式依赖的 [probe-rs](https://probe.rs/) 同样跨平台:
| macOS (aarch64 / x86_64) | 支持 | 支持 |
| Linux (x86_64 / aarch64) | 支持 | 支持 |
| Windows (x86_64) | 支持 | 支持 |
Runner 配置无需区分平台,直接使用 `st-mem runner` 即可,所有平台配置一致。
## 配置模版
`.cargo/config.toml` 完整示例:
```toml
[target.thumbv7m-none-eabi]
# ============================================================
# Runner — st-mem runner (跨平台,先分析内存再烧录)
# ============================================================
# st-mem runner: 分析 FLASH/RAM 占用 → probe-rs 烧录
runner = "st-mem runner --chip STM32F103C8 --protocol swd"
# ============================================================
# 不使用内存分析时,直接用 probe-rs:
# runner = "probe-rs run --chip STM32F103C8 --protocol swd"
# ============================================================
rustflags = [
"-C", "link-arg=-Tlink.x",
# "-C", "link-arg=-Tdefmt.x",
]
[build]
target = "thumbv7m-none-eabi"
[env]
DEFMT_LOG = "info"
[alias]
r = "run --release"
```
## License
MIT