Files
STM32F4-Base/tools/arch_diagram/gen_partition_svg.py
T

139 lines
5.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""生成 docs/images/物理分区布局.svg —— GD5F2GQ5UE 全片分区布局图(纯标准库)。
由 gen_frame_svg.py 复制而来(build() 与数据解耦,通用):协议帧图按"字节"计量
(字段宽 ∝ 字节数),本图按"MB"计量(分区宽 ∝ MB 数),其余约定一致——
分段矩形 + 偏移标尺 + 逐段标注,连续布局无假箭头。
用法(仓库根目录,任意 python3):
python tools/arch_diagram/gen_partition_svg.py
输出:
docs/images/物理分区布局.svg
改分区时:编辑本文件顶部的 FIELDS / TITLE / SUB / FOOT 后重跑。
"""
import html
import os
ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
OUT = os.path.join(ROOT, "docs", "images", "物理分区布局.svg")
# ----------------------------- 画布与尺寸参数 -----------------------------
PAD = 40 # 左右留白
PX_PER_MB = 4 # 每 MB 像素宽(分区宽 ∝ MB 数)
BAR_Y = 116 # 分区盒顶 y(标题 / 副标题 / 偏移标尺在其上方)
BAR_H = 74 # 分区盒高
NAME_DY = 30 # 分区名在盒内的 y 偏移
SIZE_DY = 54 # 尺寸标注在盒内的 y 偏移
RULER_DY = 20 # 偏移标尺线在盒顶上方
TITLE_FONT = 20
SUB_FONT = 13
NAME_FONT = 15
SIZE_FONT = 12
RULER_FONT = 12
FOOT_FONT = 12
FONT = "Microsoft YaHei, Segoe UI, PingFang SC, sans-serif"
# ----------------------------- 分区数据(改这里) -----------------------------
# name=分区名 mb=MB 数(None=变长段,按 DATA_UNITS 画) label=尺寸标注 color/bg=配色
DATA_UNITS = 5 # 变长段的"代表宽度"(按 N MB 画,仅示意)
FIELDS = [
dict(name="ftl_fatfs", mb=256, label="256 MB · Block 0~2047", color="#2563eb", bg="#eff6ff"),
]
TITLE = "GD5F2GQ5UE 物理分区布局(256MB)"
SUB = "单分区:全片划给 FTL(无静态分区)· 块 = 128KB(64 页 × 2KB)· 共 2048 块"
FOOT = ("ftl_fatfs:dhara FTL + FatFS 占用全部 2048 块(偏移 0 ~ 256MB)· "
"详见 docs/STM32F4-Base存储架构说明.md §1")
# ----------------------------- 工具函数 -----------------------------
def esc(s):
return html.escape(s, quote=True)
def field_w(f):
return (f["mb"] if f["mb"] is not None else DATA_UNITS) * PX_PER_MB
def offset_labels(fields):
"""按分区 MB 数累计边界偏移;偏移标注统一带 MB 单位。"""
labs, off = ["0"], 0
for f in fields:
off += f["mb"] if f["mb"] is not None else DATA_UNITS
labs.append("%d MB" % off)
return labs
# ----------------------------- 生成 -----------------------------
def build():
out = []
add = out.append
frame_w = sum(field_w(f) for f in FIELDS)
W = frame_w + 2 * PAD
# 预计算各分区 x / 宽
segs, x = [], PAD
for f in FIELDS:
w = field_w(f)
segs.append([f, x, w])
x += w
labels = offset_labels(FIELDS)
total_h = BAR_Y + BAR_H + 56
add('<rect x="0" y="0" width="%d" height="%d" fill="#ffffff"/>' % (W, total_h))
# 标题 + 副标题
add('<text x="%d" y="40" font-size="%d" font-weight="700" fill="#0f172a">%s</text>'
% (PAD, TITLE_FONT, esc(TITLE)))
add('<text x="%d" y="64" font-size="%d" fill="#64748b">%s</text>'
% (PAD, SUB_FONT, esc(SUB)))
# 偏移标尺(每个分区边界一个刻度 + 偏移标注)
ruler_y = BAR_Y - RULER_DY
add('<line x1="%d" y1="%d" x2="%d" y2="%d" stroke="#cbd5e1" stroke-width="1"/>'
% (PAD, ruler_y, PAD + frame_w, ruler_y))
bounds = [PAD] + [s[1] + s[2] for s in segs]
for i, bx in enumerate(bounds):
add('<line x1="%d" y1="%d" x2="%d" y2="%d" stroke="#94a3b8" stroke-width="1.5"/>'
% (bx, ruler_y - 4, bx, ruler_y + 4))
lab = labels[i] if i < len(labels) else "?"
add('<text x="%d" y="%d" font-size="%d" fill="#94a3b8" text-anchor="middle">%s</text>'
% (bx, ruler_y - 8, RULER_FONT, esc(lab)))
# 分区盒(名在上、尺寸在下)
for (f, bx, bw) in segs:
add('<rect x="%d" y="%d" width="%d" height="%d" fill="%s" stroke="%s" stroke-width="1.5"/>'
% (bx, BAR_Y, bw, BAR_H, f["bg"], f["color"]))
cx = bx + bw / 2.0
add('<text x="%.1f" y="%d" font-size="%d" font-weight="700" fill="#0f172a" '
'text-anchor="middle">%s</text>'
% (cx, BAR_Y + NAME_DY, NAME_FONT, esc(f["name"])))
add('<text x="%.1f" y="%d" font-size="%d" fill="%s" text-anchor="middle">%s</text>'
% (cx, BAR_Y + SIZE_DY, SIZE_FONT, f["color"], esc(f["label"])))
# 脚注
add('<text x="%d" y="%d" font-size="%d" fill="#94a3b8">%s</text>'
% (PAD, total_h - 16, FOOT_FONT, esc(FOOT)))
svg = ('<svg xmlns="http://www.w3.org/2000/svg" width="%d" height="%d" '
'viewBox="0 0 %d %d" font-family="%s">\n%s\n</svg>\n'
% (W, total_h, W, total_h, FONT, "\n".join(out)))
return svg, W, total_h
def main():
svg, W, h = build()
with open(OUT, "w", encoding="utf-8", newline="\n") as f:
f.write(svg)
import xml.etree.ElementTree as ET
ET.fromstring(svg)
print("OK %d bytes, canvas %dx%d -> %s" % (len(svg.encode("utf-8")), W, h, OUT))
if __name__ == "__main__":
main()