You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用check.h测试STM32寄存器裸机代码时遇段错误求助

STM32寄存器单元测试触发段错误的问题与解决方案

问题背景

使用check.h库对STM32F030F4的LED1_off函数做单元测试时触发段错误,移除函数内的寄存器操作语句后段错误消失。推测测试时程序试图访问PC自身的无效内存地址,需明确该测试需求是否可行,以及对应的解决或替代方案。

待测试函数代码

#define GPIOA_BASE      0x48000000 
#define GPIOA_ODR       (*(volatile uint32_t *)(GPIOA_BASE + 0x14))

#define LED1            (*(volatile uint32_t *)(0))
#define OFF             0UL

uint32_t LED1_off (void) {
    GPIOA_ODR |= (OFF << LED1);
    return GPIOA_ODR ;
}

测试代码

START_TEST (test_LED1_off) {
    ck_assert_int_eq(0x48000014, LED1_off());
}
END_TEST

错误信息

Running suite(s): FunctionsTests
66%: Checks: 3, Failures: 0, Errors: 1
tests/tests.c:31:E:Core:test_LED1_off:0: (after this point) Received signal 11 (Segmentation fault)

问题分析与解决方案

核心原因

PC的内存地址空间与STM32的外设地址空间完全独立:

  1. GPIOA_ODR直接映射到STM32的外设地址0x48000014,这个地址在PC的用户态内存中未分配且不可访问,读写操作直接触发段错误。
  2. LED1的定义*(volatile uint32_t*)(0)会读取PC的地址0,而PC系统中地址0属于受保护的无效区域,访问必然崩溃。

需求可行性与解决方法

该测试需求完全可行,只需通过模拟硬件寄存器的方式避免直接访问PC的无效内存,具体方案如下:

1. 本地模拟寄存器(最简方案)

在测试代码中重新定义寄存器宏,将其指向PC内存中的普通变量,替代硬件地址映射:

// 测试代码中添加模拟变量与重定义
uint32_t mock_gpioa_odr = 0;
#define GPIOA_ODR mock_gpioa_odr
#define LED1 0  // 修正LED1定义为实际引脚位号,比如假设LED对应GPIOA的第0位

START_TEST (test_LED1_off) {
    // 初始化模拟寄存器值
    mock_gpioa_odr = 0xFFFFFFFF; // 模拟初始状态
    uint32_t result = LED1_off();
    // 验证操作后寄存器值是否符合预期
    ck_assert_int_eq(0xFFFFFFFE, result);
}
END_TEST
  • 要点:必须修正LED1的定义,将其改为引脚对应的位号(而非读取无效地址),否则仍会触发段错误。

2. 封装硬件操作+Mock框架

将寄存器操作封装为独立的硬件抽象函数,测试时用Mock框架(如CMock)替换这些函数,验证调用逻辑:

// 封装后的硬件操作函数(生产代码)
void gpio_set_pin(uint32_t gpio_base, uint8_t pin, uint32_t state) {
    volatile uint32_t* odr = (volatile uint32_t*)(gpio_base + 0x14);
    if (state == OFF) {
        *odr &= ~(1UL << pin);
    } else {
        *odr |= (1UL << pin);
    }
}

uint32_t LED1_off(void) {
    gpio_set_pin(GPIOA_BASE, LED1_PIN, OFF);
    return *(volatile uint32_t*)(GPIOA_BASE + 0x14);
}

测试时用CMock生成gpio_set_pin的Mock函数,验证是否以正确的参数调用,同时模拟返回的寄存器值。

3. 硬件在环测试(HIL)

若需验证真实硬件上的行为,可将测试代码编译为ARM架构二进制,下载到STM32开发板运行,通过串口、SWD调试接口获取测试结果。这种方式更贴近真实环境,但测试效率低于PC端单元测试。

替代测试方案

若暂时无法实现PC端模拟,可采用:

  • 静态代码分析:检查寄存器操作的语法与逻辑正确性,比如位运算是否符合预期。
  • 开发板上的集成测试:直接在STM32硬件上运行测试逻辑,通过LED状态、串口输出验证函数行为。

内容的提问来源于stack exchange,提问作者Norronas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 18:41:00