资讯动态

嵌入式软件单元测试(五十五)——微控制器内存保护单元(MPU)对单元测试的影响及模拟方案

发布时间:2026/9/17 7:17:26 来源:尧图企业网站定制
❄️ 我的个人专栏《智能软件工程AI4SE》《嵌入式面试总结》《嵌入式处理器架构解析》《嵌入式与虚拟化》《嵌入式软件测试》 Simplicity is the ultimate sophistication摘要本文聚焦微控制器内存保护单元MPU对嵌入式软件单元测试的影响从测试环境差异、内存访问约束、异常处理路径和用例可移植性四个方面展开分析并给出宿主机与目标板两种环境下的模拟方案。宿主机侧通过寄存器层、访问检查层和异常处理层的分层模拟复现 MPU 行为目标板侧则借助区域配置注入与异常处理打桩构造可控测试场景最后结合方案对比给出以宿主机模拟为主、目标板验证为辅的实践建议。1. 引言在嵌入式软件单元测试系列的前几篇文章中我们分别讨论了桩函数、插桩、覆盖率统计、静态分析等话题。随着被测系统越来越复杂微控制器上的内存保护单元MPUMemory Protection Unit逐渐成为单元测试中不可忽视的变量。MPU 本身是硬件特性但它会改变软件运行时的内存访问行为进而影响测试用例的设计、执行和结果判定。本文聚焦 MPU 对单元测试的具体影响并给出在宿主机Host与目标板Target两种环境下可行的模拟方案帮助测试工程师在引入 MPU 的工程中依然能够稳定、高效地开展单元测试。2. MPU 基础回顾MPU 是微控制器中用于内存访问控制的硬件模块。它允许软件通常是操作系统或裸机调度框架将物理内存划分为若干区域并为每个区域配置独立的访问权限例如只读、读写、不可执行等。当 CPU 访问某个内存地址时MPU 会依据当前配置的区域属性进行校验一旦发现越权访问就会触发异常如 MemManage Fault。从单元测试的角度看MPU 带来的核心变化是被测函数对内存的访问不再是无约束的而是受到区域权限和边界条件的限制。这意味着测试用例不仅要验证功能逻辑还要验证内存访问是否符合 MPU 配置的约束。3. MPU 对单元测试的影响MPU 对单元测试的影响主要体现在以下几个方面。3.1 测试环境差异单元测试通常在宿主机上编译运行而 MPU 是目标板上的硬件资源。宿主机默认没有 MPU 行为因此被测代码中与 MPU 相关的寄存器操作、异常处理路径在宿主机上无法直接执行。如果被测函数内部直接读写 MPU 寄存器测试用例在宿主机上会因非法地址访问而崩溃。3.2 内存访问约束在目标板上MPU 会限制被测函数对特定内存区域的访问。例如某个缓冲区被配置为只读区域被测函数若尝试写入该缓冲区就会触发异常。单元测试需要覆盖这类越权访问场景验证异常处理逻辑是否正确。3.3 异常处理路径MPU 触发异常后系统会跳转到异常处理函数。该路径在普通单元测试中往往被忽略但在启用 MPU 的工程中异常处理路径的正确性直接影响系统稳定性。测试用例需要构造触发条件验证异常处理函数的行为。3.4 测试用例可移植性同一份被测代码在宿主机和目标板上的内存布局不同MPU 区域配置也不同。这导致测试用例难以直接复用需要针对不同环境维护不同的配置和预期结果。4. 模拟方案总体思路针对上述影响模拟方案的核心思路是在宿主机上通过软件方式模拟 MPU 的区域配置和访问检查逻辑使被测代码在宿主机上也能表现出与目标板一致的内存访问行为。具体分为三个层次寄存器层模拟、访问检查层模拟、异常处理层模拟。5. 宿主机模拟方案5.1 寄存器层模拟寄存器层模拟是最基础的方案。通过宏定义或桩函数将 MPU 寄存器操作映射为宿主机上的普通变量操作。例如#ifdef UNIT_TEST #define MPU_CTRL_REG test_mpu_ctrl_reg #define MPU_RBAR_REG test_mpu_rbar_reg #define MPU_RASR_REG test_mpu_rasr_reg uint32_t test_mpu_ctrl_reg; uint32_t test_mpu_rbar_reg; uint32_t test_mpu_rasr_reg; #else #define MPU_CTRL_REG (*(volatile uint32_t *)0xE000ED94) #define MPU_RBAR_REG (*(volatile uint32_t *)0xE000ED9C) #define MPU_RASR_REG (*(volatile uint32_t *)0xE000EDA0) #endif这样被测代码中的寄存器读写操作在宿主机上就变成了对普通全局变量的访问测试用例可以方便地设置和检查寄存器值。5.2 访问检查层模拟访问检查层模拟用于模拟 MPU 的区域匹配和权限校验逻辑。可以设计一个软件模拟器维护一张区域配置表并提供访问检查接口typedef struct { uint32_t base; uint32_t size; uint32_t access_permission; } mpu_region_t; static mpu_region_t test_mpu_regions[8]; static uint32_t test_mpu_region_count; int test_mpu_check_access(uint32_t addr, uint32_t size, uint32_t access) { for (uint32_t i 0; i test_mpu_region_count; i) { mpu_region_t *region test_mpu_regions[i]; if (addr region-base (addr size) (region-base region-size)) { if ((region-access_permission access) access) { return 0; } return -1; } } return -1; }被测代码中原本直接访问内存的位置可以改为调用该检查接口从而在宿主机上复现 MPU 的越权行为。5.3 异常处理层模拟异常处理层模拟用于验证 MPU 触发异常后的处理路径。在宿主机上可以通过函数指针或回调机制模拟异常跳转void (*test_mpu_fault_handler)(void); void test_mpu_trigger_fault(void) { if (test_mpu_fault_handler ! NULL) { test_mpu_fault_handler(); } }测试用例可以注册自定义的异常处理函数验证被测代码在异常发生后的行为是否符合预期。6. 目标板模拟方案在目标板上MPU 是真实存在的硬件模拟的重点不再是替代硬件而是如何构造可控的测试场景。常见做法包括配置隔离区域在测试模式下将部分内存区域配置为特殊权限用于验证被测函数的越权访问行为。异常处理打桩将 MPU 异常处理函数替换为测试专用版本记录异常发生时的现场信息便于断言。区域配置注入通过测试框架在运行时动态修改 MPU 区域配置模拟不同的内存布局场景。7. 模拟方案对比对比维度宿主机模拟目标板模拟执行速度快适合大批量用例慢受硬件限制环境依赖无硬件依赖易于集成到 CI依赖目标板环境搭建复杂真实性模拟逻辑与真实硬件存在差异真实硬件行为结果可信度高异常路径覆盖通过回调模拟覆盖有限可覆盖真实异常处理流程适用场景逻辑验证、回归测试硬件相关验证、集成测试实际工程中建议采用宿主机模拟为主、目标板验证为辅的组合策略兼顾测试效率与结果可信度。8. 实践建议在引入 MPU 模拟方案时建议关注以下几点抽象硬件访问将被测代码中的 MPU 寄存器操作封装为独立接口便于在宿主机和目标板之间切换实现。统一配置描述使用结构体或配置文件描述 MPU 区域属性避免在测试用例中散落硬编码地址。异常路径纳入覆盖统计将 MPU 异常处理函数纳入覆盖率统计范围避免遗漏关键分支。分层验证先在宿主机上完成逻辑验证再在目标板上进行关键场景的确认测试。9. 总结MPU 的引入为嵌入式单元测试带来了新的挑战主要体现在环境差异、内存访问约束、异常处理路径和用例可移植性四个方面。通过寄存器层、访问检查层和异常处理层的分层模拟可以在宿主机上较为真实地复现 MPU 行为在目标板上则通过区域配置注入和异常处理打桩构造可控测试场景。两者结合能够在保证测试效率的同时提升测试结果的可信度。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价