gpio_configure_pin bug?

1 post / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have found a strange part in the asf (version ASF-2.7.0-21036.96)

It is the gpio_configure_pin function in the gpio.c file.

There is this part:

   /* Select interrupt level for group */
    if (flags & GPIO_INTERRUPT) {
            if (flags & GPIO_BOTHEDGES)
            {
                   gpio_port->imr0c = 1 << (pin & 0x1F);
                   gpio_port->imr1c = 1 << (pin & 0x1F);
            }
            else if (flags & GPIO_RISING)
            {
                   gpio_port->imr0s = 1 << (pin & 0x1F);
                   gpio_port->imr1c = 1 << (pin & 0x1F);
            }
            else if (flags & GPIO_FALLING)
            {
                   gpio_port->imr0c = 1 << (pin & 0x1F);
                   gpio_port->imr1s = 1 << (pin & 0x1F);
            }
    }

The define are as follows:

#define GPIO_INTERRUPT  (1 << 7) //!< Enable Pin/Group Interrupt
#define GPIO_BOTHEDGES  (3 << 7) //!< Sense Both Edges
#define GPIO_RISING     (5 << 7) //!< Sense Risign Edge
#define GPIO_FALLING    (7 << 7) //!< Sense Falling Edge

Now lets say that (flags & GPIO_INTERRUPT) will evaluate true. In this case the else if statements could never be reached, because the first if statement: if (flags & GPIO_BOTHEDGES) will always evaluate as true.

Am I missing here something, or is it realy the asf programmer, who don't understand the basics of bit manipulation?

Just to make it easy:
(1 << 7) : 0010000000 : GPIO_INTERRUPT
(3 << 7) : 0110000000 : GPIO_BOTHEDGES
(5 << 7) : 1010000000 : GPIO_RISING
(7 << 7) : 1110000000 : GPIO_FALLING

If (flags & GPIO_INTERRUPT) is true, then flags must be something like this:
xx1xxxxxxx
and if so then:
xx1xxxxxxx &
0110000000
is true, as the C language evaluates everything as true, which is not 0.

Just for the record there is a function, which seems more functional for the same purpose:
gpio_configure_edge_detector

static int gpio_configure_edge_detector(uint32_t pin, uint32_t mode)
{
  volatile avr32_gpio_port_t *gpio_port = &GPIO.port[pin >> 5];
  
  // Configure the edge detector.
  switch (mode)
  {
  case GPIO_PIN_CHANGE:
    gpio_port->imr0c = 1 << (pin & 0x1F);
    gpio_port->imr1c = 1 << (pin & 0x1F);
    break;

  case GPIO_RISING_EDGE:
    gpio_port->imr0s = 1 << (pin & 0x1F);
    gpio_port->imr1c = 1 << (pin & 0x1F);
    break;

  case GPIO_FALLING_EDGE:
    gpio_port->imr0c = 1 << (pin & 0x1F);
    gpio_port->imr1s = 1 << (pin & 0x1F);
    break;

  default:
    return GPIO_INVALID_ARGUMENT;
  }

defines:

#define GPIO_PIN_CHANGE         0 //!< Interrupt triggered upon pin change.
#define GPIO_RISING_EDGE        1 //!< Interrupt triggered upon rising edge.
#define GPIO_FALLING_EDGE       2 //!< Interrupt triggered upon falling edge.

This however has to be called manualy.