Mosaaleb
Mosaaleb

Reputation: 1089

Why turning these macro-functions to functions didn't work correctly?

I'm using some macros that initializes & writes & reads port or port pin: (And it works fine)

/* GPIO port operations */
#define GPIO_InitPort(CONTROL, DIRECTION)   ((CONTROL) = ((DIRECTION)? (~GPIO_OUT):(GPIO_OUT)))
#define GPIO_WritePort(PORT, DATA)          ((PORT) = (DATA))
#define GPIO_ReadPort(PORT)                 (PORT)

/* GPIO port pin operations */
#define GPIO_InitPortPin(CONTROL, PIN, DIRECTION)   ((CONTROL) = (CONTROL & (~(1 << PIN)))|(DIRECTION << PIN))
#define GPIO_WritePortPin(PORT, PIN, DATA)          ((PORT) = (PORT & (~(1 << PIN)))|(DATA << PIN))
#define GPIO_ReadPortPin(PORT, PIN)                 (((PORT) & (1 << PIN)) >> (PIN))

And, i was thinking to make a GPIO module, its functions implemented as follows:

void GPIO_InitPort(uint8 PortControl, uint8 PortDir){
    PortControl = ((PortDir) ?  (~GPIO_OUT) : (GPIO_OUT));
}

void GPIO_WritePort(uint8 PortData, uint8 PortLevel){
    PortData = PortLevel;
}

uint8 GPIO_ReadPort(uint8 PortData){
    return PortData;
}
void GPIO_InitPortPin(uint8 PortControl, uint8 Pin, uint8 PinDir){
    PortControl &= ( ~(1<<Pin) | (PinDir<<Pin) );
}
uint8 GPIO_ReadPortPin(uint8 PortData, uint8 PinLevel){
    return (( PortData & (1<<PinLevel) ) >> PinLevel);
}
void GPIO_WritePortPin(uint8 PortData, uint8 Pin, uint8 PinLevel){
    PortData &= ( ~(1<<Pin) | (PinLevel<<Pin) );
}

Unfortunately, that doesn't work, although same logic used.

Upvotes: 0

Views: 101

Answers (2)

John Bode
John Bode

Reputation: 123448

Remember that macros are just text substitutions - macro arguments are not evaluated, they are simply expanded in place. If you write something like

GPIO_InitPort( foo, bar );

the preprocessor expands that to

((foo) = ((bar) ? (~GPIO_OUT) : (GPIO_OUT)));

Function arguments, OTOH, are evaluated, and the result of that evaluation is passed to the function. Remember that C uses pass-by-value semantics - the formal argument is a different object in memory than the actual argument, so updating one has no effect on the other. If you call the function

GPIO_InitPort( foo, bar );

the formal argument PortControl is a different object in memory from the actual argument foo, and similarly PortDir is a separate object from bar. Writing to PortControl has absolutely no effect on foo.

If you want a function to write to the actual parameter in the caller, then you must pass a pointer to that parameter. So GPIO_InitPort would need to be written as

void GPIO_InitPort( uint8 *PortControl, uint8 PortDir )
{
  *PortControl = PortDir ? ~GPIO_OUT : GPIO_OUT;
}

and called as

GPIO_InitPort( &foo, bar );

Upvotes: 4

L. Messing
L. Messing

Reputation: 70

You need to learn about pointers.

Example:

void changeVar(int *var, int source)
{
    *var = source;
}

int main()
{
    int foobar;

    changeVar(&foobar, 5);

    return 0;
}

Upvotes: 0

Related Questions