[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-libc-dev] [RFC] passing port info to a function
From: |
E. Weddington |
Subject: |
Re: [avr-libc-dev] [RFC] passing port info to a function |
Date: |
Fri, 04 Oct 2002 10:57:27 -0600 |
On 4 Oct 2002 at 9:22, Theodore A. Roth wrote:
>
>
> On Fri, 4 Oct 2002, E. Weddington wrote:
>
> :) Caveat, add volatile:
> :) #define PORTB_ADDR ((volatile uint8_t *)_SFR_ADDR(PORTB))
> :)
> :)
> :) > void
> :) > set_bits_func_correct (uint8_t *port, uint8_t mask)
> :) > {
> :) > *port |= mask;
> :) > }
> :)
> :) And here:
> :) set_bits_func_correct (volatile uint8_t *port, uint8_t mask)
> :)
>
> I don't think "volatile" is needed in this instance. The reason is you
> are passing the reference to the port, not the port. The compiler will
> not optimize this away because it's smart enough to know that you are
> changing what the pointer refers to which could affect the caller of
> the function.
>
> The volatile is needed in set_bits_func_wrong() because port is passed
> by value, the local _copy_ is changed, and the change can never make
> it out of the function. Thus, the compiler thinks that the func does
> nothing which can affect the caller, so just optimizes out the func
> completely. Making port volatile, tells the compiler not to do that.
>
> This is my interpretation of what happens when using various
> optimization levels and looking at the disassembly of the object file.
> Feel free to prove me wrong. ;-)
>
> Ted Roth
If you take the address of PORTB like this:
&PORTB
or the equivalent of the macro PORTB_ADDR you have a type that is a
pointer to volatile uint8_t.
If you pass this pointer to the port parameter in:
set_bits_func_correct (uint8_t *port, uint8_t mask)
you will get a compiler warning about discarding qualifier from
pointer target type.
You wouldn't want to provide examples to users that cause compiler
warnings would you? ;-)
So to get around that, you'd have to change the definition of the
function:
set_bits_func_correct (volatile uint8_t *port, uint8_t mask)
or typecast the passed parameter.
Or, which would be more work, typedef an AVR register type and use
that type everywhere (example):
typedef avrreg8 volatile uint8_t;
typedef avrreg16 volatile uint16_t;
(Don't treat the above as an argument for doing it. It's just one
possible solution.)
Eric