Files
STM32F4-Base/test/host/sb_proto/run_unit_test.py
T
wandering1 b25d70e962 feat(屏板): 协议层 sb_proto(帧 A 解析 / 帧 B 组帧 / CRC-16)
批 1 的 1-1:新建 Drivers/BSP/ScreenLink/sb_proto.c/h,纯逻辑、无 HAL 依赖,
可主机侧单测。屏板侧的协议事实源是 DTU-LCD 的 CRC16.c / MODBUS.c / rs485.h。

- CRC-16/MODBUS 用一张 16 位合并表(512 B,与屏板两张 8 位表同量)。可逐项
  验证的关系:s_crc_table[i] == (auchCRCLo[i] << 8) | auchCRCHi[i]——屏板把
  低字节表叫 Hi、高字节表叫 Lo,这正是下面那个字节序陷阱的根源。
- 帧 A 解析:先校 CRC 再看字段。地址/功能码/命令类型不符报 BSP_ERR_PARAM,
  CRC 不符报 BSP_ERR_CRC(调用方据此决定"计数"还是"静默丢")。RT_CMD 带
  非 0 key 不报错、按 0 收——为这一项丢一帧等于丢一次刷新,代价不对等。
- 帧 B 组帧:普通图(掩码小端)+ LOGO(宽高大端 + 魔数 0x89 0x45),整帧
  4208 B 重写(998 B 填充固定 0x00 且参与 CRC),组完即自校验。
  LOGO 容量按字节数判(((w+7)/8)*h <= 3200)而不是像素数:161x159 只有
  25599 像素,却要 3339 B 才装得下。
- 主机单测 59/59 PASSED(test/host/sb_proto/),覆盖率 74/74 行、6/6 函数。
  其中两条向量是屏板自己算出来的线上字节(01 03 01 00 F0 48 与
  01 03 00 09 31 DE),并按屏板 Check_CRC 的口径反查"它会认这一帧"。
- 双端注册:uvprojx 加 File + IncludePath;模拟器侧走 check_registration.py
  的 MCU-only 豁免(纯逻辑,模拟器无消费路径)。
- Keil 构建 0 错误 0 警告;Code 不变——尚无调用者,链接器按未用节丢弃。

文档侧的 CRC 字节序订正见下一个提交。
2026-10-29 19:17:28 +08:00

60 lines
3.0 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 -*-
"""屏板链路协议层(sb_proto)的主机侧纯逻辑单元测试运行器(纯标准库)。
做什么:
用本机 MSVC 编译 test/host/sb_proto/sb_proto_test.c(它以 #include 纳入**生产源文件**
Drivers/BSP/ScreenLink/sb_proto.c),在 PC 上离线验证帧 A 解析 / 帧 B 组帧 /
CRC-16/MODBUS:教科书校验值、屏板实测的召唤帧字节、坏帧分支、4208 B 帧的
点阵-掩码-填充-CRC 落位、LOGO 宽高容量守卫、以及"按屏板 Check_CRC 的口径复核
本模块组的帧会不会被屏板接受"。零硬件、零烧录、毫秒级。
工具链探测 / INCLUDE-LIB 拼接 / 编译运行 / 退出码判定全部委托给通用 harness
`test/host/common/unit_test_harness.py`(本文件只做声明)。
为什么要主机侧单测(而不是只用台架):
屏板不认帧时,它的超时判定只看"收没收到一整包"、不看 CRC,现场只表现为**画面不刷新**——
这条现象与波特率错、时序错、线接反完全同形,台架上无法归因。把 CRC 与字节序钉在主机侧,
台架上剩下的就只可能是物理层问题。另一处只能在这里测:CRC 的**字节序**口径。
屏板固件 Calculate_CRC() 返回的是高低互换后的「线上字」,它自己的注释把低字节叫"高字节";
照字面实现会让每一帧都差一次字节交换,而现象又是"画面不刷新"——这里钉了两条屏板实测向量。
本层为**纯逻辑**:无寄存器、无 RTOS、无文件/外设依赖,故**不需要任何桩目录**。
用法(仓库根目录):
python test/host/sb_proto/run_unit_test.py
或统一用 .venv: & '.venv\\Scripts\\python.exe' test/host/sb_proto/run_unit_test.py
退出码:0=PASS / 1=测试失败 / 2=环境错误(找不到编译器 / 编译失败 / 无汇总行)。
设计依据:docs/产品需求/产品需求设计文档.md §5.16.2(帧结构);
docs/任务规划/屏板链路.md §3 批 1(1-1 的判据);
协议事实源 = 屏板固件工程 D:\\Code\\DTU Code\\DTU-LCD 的 CRC16.c / MODBUS.c。
创建日期:2026-10-29
"""
import os
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
ROOT = os.path.dirname(os.path.dirname(os.path.dirname(HERE)))
# harness 位于 test/host/common/
sys.path.insert(0, os.path.join(ROOT, "test", "host", "common"))
from unit_test_harness import TestBuild, run_host_unit_test # noqa: E402
# 无桩目录:被测代码只依赖 stdint.h / string.h。
# 两个 include 目录各管一个头:ScreenLink 找 sb_proto.h,Drivers/BSP 找 bsp_err.h。
BUILD = TestBuild(
name="ScreenLink Proto Tests",
src=os.path.join(HERE, "sb_proto_test.c"),
include_dirs=[
os.path.join(ROOT, "Drivers", "BSP", "ScreenLink"),
os.path.join(ROOT, "Drivers", "BSP"),
HERE,
],
summary_marker="=== ScreenLink Proto Tests:",
)
if __name__ == "__main__":
sys.exit(run_host_unit_test(BUILD))