Search code examples
cmacrosembeddedarmcpu-registers

Faking register reads in C


I have an existing code base for an embedded system with no operating system. I'm trying to get it to build with the x86 gcc instead of just the cross compiler, as a first step toward being able to unit test on the host. Unfortunately there are direct register reads and writes all over the place, instead of using the provided abstraction layer. One option of course is to fix that; replace the direct register access with calls to the GPIO access functions. I'm hoping to get up to speed faster by introducing a macro (used in the x86 build only) to redefine pieces of the code like

myvar = (GPIOC->IDR >> 6) & 0x03;   // Read bits 6 and 7
GPIOD->CRL &= 0xFFFFFF0F;

to something like:

myvar = (myGpiocIdrReadFunc() >> 6) & 0x03;   // Read bits 6 and 7
myGpiodClrWriteFunc() &= 0xFFFFFF0F;

GPIOx's are #defined as pointers to a physical address. Of course if I try to read and write directly to addresses on my PC with an executable built with x86, that would be access violation. Unfortunately if I try something like this:

#define GPIOC->IDR { myGpiocIdrReadFunc() }

the compiler doesn't like that "->", saying "missing whitespace after the macro name."

If you've solved this kind of problem before, how did you do it?


Solution

  • typedef struct {
        int IDR;
        int CRL;
    } gpio_t;
    
    gpio_t c;
    gpio_t d;
    
    gpio_t * GPIOC = &c;
    gpio_t * GPIOD = &d;
    

    Just keep adding registers like IDR to the struct as the compiler screams at you.

    EDIT I edited the answer after I saw your comment that you actually want to simulate the values, this way you can, but bear in mind that you need to initialized them like in your hardware.