ctestingcpu-registerscortex-mbare-metal

Unit tests on registers with bare metal programming


I'm trying to do a unit test by using the library "check.h" on a register containing a hexadecimal number to check if the return value is correct. The registers are for programming an STM32F030F4 ARM Cortex M0 microcontroller. However when running my test, I have a segmentation fault.

Here is the function I want to test :

#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 ;
}

And here is my test :

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

For information, the ck_assert_int_eq function works with a uint32_t, I have another test that works with a return value of this type.

Even though the return value is not necessarily equal to what I want to test, I get a segmentation fault when I run my tests. Here is the error :

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)

By removing the following line: "GPIOA_ODR |= (OFF << LED1);" and by setting the return value to "1", I no longer have a segmentation fault. I have the impression that when I run my tests, my computer understands that I am trying to access its own memory.

Is what I'm trying possible ? If so how ? If not, what kind of tests can I try ? I've been struggling with this for several hours. Thanks.


Solution

  • By removing the following line: "GPIOA_ODR |= (OFF << LED1);" and by setting the return value to "1", I no longer have a segmentation fault. I have the impression that when I run my tests, my computer understands that I am trying to access its own memory.

    On your PC you try to modify the memory at the address GPIOA_BASE + 0x14 (more precisely you dereference pointer assigned with GPIOA_BASE + 0x14 converted to pointer). It is definitely not memory which belongs to you and invoke segfault.

    The whole test of the STM32 registers on the PC makes no sense at all.

    Also:

    If you want to run it on the PC you need a real object to be referenced by the pointer

    #if defined(__x86_64__) || defined(_M_X64)
    static  uint32_t GPIOA_ODR;
    #else
    #define GPIOA_BASE      0x48000000 
    #define GPIOA_ODR       (*(volatile uint32_t *)(GPIOA_BASE + 0x14))
    #endif
    
    #define LED1            0
    #define OFF             1UL
    
    
    uint32_t LED1_off (void) {
        GPIOA_ODR &= ~(OFF << LED1);
        return GPIOA_ODR ;
    }