[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-libc-dev] [RFC] passing port info to a function
From: |
Theodore A. Roth |
Subject: |
Re: [avr-libc-dev] [RFC] passing port info to a function |
Date: |
Fri, 4 Oct 2002 10:18:06 -0700 (PDT) |
On Fri, 4 Oct 2002, E. Weddington wrote:
:) > 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? ;-)
Well, as I wrote the example, I didn't get any warnings. :-)
:)
:) 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.)
Ick! Probably not a good idea to hide the volatile in a typedef (or
#define for that matter).
I like the use of "&PORTB" in the call and volatile in the function
prototype since it gets rid of the use of _SFR_ADDR() macro in your code
(bad form to use internal library macros in your code since they _could_
change on you).
So here's the code for the example I'm working on:
cat <<EOF > example.c
#include <inttypes.h>
#include <avr/io.h>
void
set_bits_func_wrong (volatile uint8_t port, uint8_t mask)
{
port |= mask;
}
void
set_bits_func_correct (volatile uint8_t *port, uint8_t mask)
{
*port |= mask;
}
#define set_bits_macro(port,mask) ((port) |= (mask))
int main (void)
{
set_bits_func_wrong (PORTB, 0xaa);
set_bits_func_correct (&PORTB, 0x55);
set_bits_macro (PORTB, 0xf0);
return (0);
}
EOF
This seems to follow the correct C idioms more closely than the original.
Thanks for calling me on that Eric.
Ted Roth