MCS-51 系列系统模拟器
QEMU 为经典 MCS-51 CPU 及其 MCS-251 扩展提供独立的系统目标。它们共享 MCS-51 系列实现,而独立的可执行文件在构建时保留各自架构的地址宽度和指令模式。可通过以下命令同时构建两者:
./configure --target-list=mcs51-softmmu,mcs251-softmmu
ninja
生成的可执行文件及其模型如下:
qemu-system-mcs51提供
mcs51-cpuCPU 和stc8g1k08a机器。qemu-system-mcs251提供
mcs251-cpuCPU 和stc32g144k246机器。
运行固件
两种机器都通过 -bios 加载固件。不需要图形显示时可使用 -nographic:
qemu-system-mcs51 -M stc8g1k08a -bios firmware.hex -nographic
qemu-system-mcs251 -M stc32g144k246 -bios firmware.hex -nographic
中断和异常
经典 MCS-51 架构响应复位和向量化硬件中断。MCS-251 增加了可编程的四级中断优先级及嵌套。STC32 定时器 0 的模式 3 中断被建模为高于这四个可编程级别的优先级。RETI 恢复保存的 PC 和中断优先级状态;MCS-251 模型还会恢复保存的 PSW1。
这些 CPU 未定义通用的同步特权异常、对齐异常或非法指令异常。经典架构的保留编码和 MCS-251 的 TRAP 指令均按文档规定作为 NOP 执行。TFPU 算术异常在 TFPU 状态寄存器中报告,不通过 CPU 进行向量跳转。
STC8G1K08A 机器
stc8g1k08a 机器包含一个经典 MCS-51 CPU 和一个 STC8G1K08A MCU,具有 8 KiB 用户闪存、4 KiB EEPROM、256 字节内部数据 RAM 以及 1 KiB 扩展数据 RAM。EEPROM 在 Code 空间的 0x2000 至 0x2fff 可见。
启动固件
机器通过 -bios 接受原始固件和 Intel HEX 固件。原始镜像加载到代码地址 0x0000,最大可为 8 KiB。不区分大小写的 .hex 后缀会选择 Intel HEX 加载器;数据记录使用绝对 MCS-51 代码地址,且必须位于 8 KiB 用户闪存内。CPU 始终在 0x0000 复位。
例如:
qemu-system-mcs51 -M stc8g1k08a \
-bios firmware.hex -nographic
CPU 和内存
mcs51-cpu 实现了全部 256 个经典操作码编码,包括所有寻址形式、位操作、调用、返回和中断。操作码 0xa5 在此 CPU 上是架构保留的单字节 NOP。该架构具有重叠的 Code、IDATA、XDATA 和 SFR 地址空间:取指访问 64 KiB 代码空间,直接和间接访问寻址 256 字节内部 RAM 和 SFR 空间,而 MOVX 访问 1 KiB 扩展 RAM。MOVX @Ri 形式使用 P2 锁存器作为地址位 15:8。P_SW2.EAXFR 为 0xfa00 至 0xffff 的 MOVX 访问选择 STC 扩展寄存器窗口。
QEMU 地址空间表示
经典架构允许 Code、IDATA 和 XDATA 地址均从零开始,同时彼此独立。QEMU 将访问类型编码为系统地址空间内互不重叠的内部物理窗口。CPU 的 MMU 索引和指令辅助函数选择适当的窗口:
架构空间 |
客户机地址 |
QEMU 内部地址 |
|---|---|---|
Code |
|
|
IDATA |
|
|
XDATA |
|
|
XFR |
|
|
SFR |
|
|
监视器的 info mtree 命令报告的高地址是 QEMU 内部编码,而不是 STC8 硬件总线上的地址。stc8g.flash、stc8g.idata 和 stc8g.xdata 等区域名称标识各窗口表示的架构空间。
已建模的外设
- GPIO
P3.0 至 P3.3 以及 P5.4 至 P5.5 实现了数据锁存器、全部四种
PnM1/PnM0模式、上拉、施密特触发、压摆率、驱动强度和输入使能寄存器。引脚读取与读改写时的锁存器读取是不同的操作。P3.2/P3.3 接入 INT0/INT1,P5.4/P5.5 接入定时器 0/1 的计数器输入。- 定时器 0 和定时器 1
实现了模式 0、1、2,定时器 0 的模式 3,门控输入、外部下降沿计数、
x1/x12时钟选择、溢出标志和中断。- UART1
SCON、SBUF、SADDR和SADEN连接到 QEMU 的第一个串口字符设备。实现了接收使能、背压、RI、TI以及 UART 中断。发送在面向字节的字符设备边界完成。- 系统时钟和中断
建模了 HIRC、外部振荡器和 IRC32K 时钟选择、分频器、微调控制和 MCLKO 分频器。所得时钟驱动已建模的定时器 0/1、PCA、ADC、SPI、I2C 和 MDU 设备的时序。
PCON.IDL模式停止 CPU,但外设继续运行;PCON.PD则门控系统时钟,直至某个已使能中断唤醒 CPU。扩展中断控制器提供 ADC、LVD、PCA、SPI、INT2--INT4 和 I2C 向量、优先级控制,以及AUXINTIF写 1 清零标志。INT2--INT4 请求保持锁存,直到软件确认对应标志。- ADC 和低电压检测器
10 位 ADC 实现了六个外部提供的输入通道、内部参考通道、结果对齐、转换时序及中断。系统时钟变化时保留转换进度。
RSTCFG实现了四个低电压阈值、PCON.LVDF、LVD 中断模式和自动复位模式。设备的vdd-millivolts输入提供建模的电压。- PCA
三通道 PCA 实现了内部和外部时钟源、捕获边沿、比较和高速输出模式、6/7/8/10 位 PWM、影子重载、标志、中断及
ccp-out信号。选择相应配置时,定时器 0 溢出连接为 PCA 时钟源。- SPI 和 I2C
SPI 实现了通过 QEMU SSI 总线进行的主机传输、从机接收事件、状态标志及中断。I2C 实现了通过 QEMU I2C 总线进行的主机启动、地址、发送、接收、应答和停止命令,以及文档规定的从机状态标志和中断。系统时钟变化或停止时,两种控制器都会保留正在进行的传输。
- MDU16
MDU16 XFR 块实现了文档规定的归一化、16 位乘除法及 32 位除法运算,包括结果、余数、溢出和操作时序。
- 看门狗、IAP 和 EEPROM
看门狗实现了预分频器、清除操作、超时标志和标准 QEMU 看门狗动作。它按硬件规定在热复位后保留使能状态。IAP 控制器实现了
0x5a/0xa5触发序列、时序与校验、EEPROM 读取、编程和 512 字节擦除命令。EEPROM 初始为已擦除状态(0xff),并在热复位后保留内容。
STC8G 限制
此模型提供功能模拟,而非周期精确模拟。已建模控制器与 GPIO 引脚之间的引脚复用、MCLKO 引脚路由、UART 位时序、第九位传输和多处理器地址过滤、模拟 GPIO 和 ADC 效应、掉电模式唤醒源过滤,以及未建模的 STC8G 外设,均尚未实现。(所建模的 8 引脚 STC8G1K08A 不提供比较器。)IAP 不模拟由 SWBS 选择的出厂 ISP ROM。未实现和保留寄存器读取为零,并忽略写入。
STC32G144K246 机器
启动 Intel HEX 固件镜像
STC 工具链通常生成 Intel HEX-80 文件,用于编程 MCU 用户闪存。机器通过 -bios 接受后缀不区分大小写的 .hex 文件,并将其 Intel HEX 地址解释为绝对 MCS-251 地址。支持扩展段地址记录和扩展线性地址记录,但拒绝位于 0xfc2800 至 0xffffff 之外的数据记录。无论是否存在可选的起始地址记录,硬件复位向量始终为 0xff0000。
例如:
qemu-system-mcs251 -M stc32g144k246 \
-bios firmware.hex -nographic
启动原始闪存镜像
机器将原始 -bios 镜像加载到 246 KiB 用户闪存区域的起始位置,地址为 0xfc2800。CPU 复位向量为 0xff0000,因此复位向量字节位于文件偏移 0x2d800。完整镜像通常需要填充以保持这种地址关系,且不得超过 246 KiB。
例如:
qemu-system-mcs251 -M stc32g144k246 \
-bios firmware.bin -nographic
CPU 和指令集
CPU 实现了文档规定的完整 MCS-251 指令集和 STC32 指令映射行为:
兼容经典 MCS-51 的 Binary 操作码映射;
原生 MCS-251 Source 操作码映射,以及 8、16 和 32 位操作;
24 位代码和数据地址、四个寄存器组、扩展栈和双数据指针;
ESC前缀,为下一条指令选择相反的操作码映射(连续前缀会交替选择映射);四级中断优先级、嵌套,以及 STC32 的四字节中断帧。
复位默认采用 Source 模式。模型将 AUXR2.CPUMODE=1 解释为 Binary 模式。此极性是实现中的推断,因为厂商文档说明了复位模式,但未明确公布该位的极性。
DPS 选择两个 24 位数据指针之一,并对文档规定的指令形式实现自动递增、递减和选择切换。连续写入 TA=0xaa、TA=0x55 的序列可解锁 DPS.AU0 和 DPS.AU1 的独立编程。
内存映射
初始 SoC 提供以下内存:
地址范围 |
大小 |
功能 |
|---|---|---|
|
16 KiB |
内部扩展数据 RAM( |
|
128 KiB |
内部扩展 RAM( |
|
4 KiB |
|
|
64 KiB |
|
|
64 KiB |
|
|
4 KiB |
|
|
246 KiB |
只读用户闪存 |
两个可执行 RAM 范围是同一底层存储的别名。通过未启用窗口进行的访问读取为零,并忽略写入。直接地址 0x80 - 0xff 选择 SFR,而该范围内通过 @R0/@R1 进行的间接访问则像硬件一样选择 edata。
已建模的外设
- 定时器 0 和定时器 1
实现了模式 0、1、2,定时器 0 的模式 3,内部虚拟时钟运行、P3.4/P3.5 上的外部下降沿计数、P3.2/P3.3 门控输入、
x1/x12时钟选择、TM0PS/TM1PS预分频、溢出标志和中断。默认输入时钟为 24 MHz。通过IE.ET0使能后,定时器 0 的模式 3 按文档规定表现为最高优先级不可屏蔽中断源。- UART1
SCON以及SBUF独立的接收和发送端连接到 QEMU 的第一个串口字符设备。实现了接收使能、RI、TI和 UART 中断。发送在面向字节的字符设备边界立即完成。- GPIO
实现了 P0 至 P7 数据锁存器以及
PnM1/PnM0模式寄存器,包括引脚读取与读改写时锁存器读取的区别。P3.2 和 P3.3 接入 INT0 和 INT1;P3.4 和 P3.5 接入外部定时器 0 和定时器 1 的计数器输入。- DSP32
通过 SFR
0xd8处的DPUOP实现了文档规定的完整 DSP32 命令集,包括配置、二进制/BCD 转换、归一化、寄存器交换、算术、乘法、除法、一元运算、逻辑、移位、复合乘除法、插值和乘累加命令。SFR0x86处的DPUST提供零、除零和移位计数结果。- TFPU
实现了文档规定的全部 TFPU 命令。只有当 CPU 在 SFR
0xed处执行MOV DMAIR,#immediate时才会启动命令;其他写入只更新DMAIR,不会启动操作。基本 IEEE-754 binary32 算术和整数转换使用 QEMU softfloat。还建模了分类、比较、状态/控制访问、三角函数命令以及系统/PLL 时钟选择。
中断向量
来源 |
向量 |
|---|---|
INT0 |
|
定时器 0 |
|
INT1 |
|
定时器 1 |
|
UART1 |
|
限制
这是功能模型,并非周期精确模型。指令执行使用基于辅助函数的 TCG 前端,每个翻译块包含一条架构指令。Decodetree 和反汇编器覆盖完整的 Binary 和 Source 操作码映射,包括 Source 模式的 ESC 前缀。未建模缓存与流水线时序、文档规定的一条指令中断延迟、UART 位时序和第九位传输、时钟输出、功耗模式以及 GPIO 电气特性。
闪存擦除/编程操作、DMA、USB、CAN-FD、ADC/DAC、PWM、I2S、额外的定时器/UART,以及其他 STC32G 外设,不在此初始机器的范围内。DSP32 和 TFPU 命令同步完成,不模拟文档规定的命令延迟。由于厂商未公布位分配,TFPU 状态异常位和控制寄存器中的舍入字段采用从厂商示例推断出的 IEEE-754 布局。三角函数命令使用主机的单精度数学库。未实现和保留寄存器读取为零,并忽略写入。提供了 GDB 寄存器 XML,但标准 GDB 构建可能不识别 MCS-251 架构名称。