micro:bit GPIO read always returning 1


Martin Woolley <mwoolley@...>
 

Zephyr newbie question. I’m trying to poll an external pin on a micro:bit. I have a rocker switch with pull up resistor connected to it and the circuit works (tested with code written with microbit-dal APIs). My Zephyr GPIO reads always return 1, however. What am I doing wrong?

 

This video shows code which uses the microbit-dal APIs working... I want to achieve the same for Zephyr:

 

https://drive.google.com/open?id=1h3LWC_PPNBhBs2mAFJj0ZgRvkd9Dk1NB

 

Code fragments:

 

#define PIN_0 EXT_P0_GPIO_PIN

struct device *gpiob;

void poll(void)

{

     struct mb_display *disp = mb_display_get();

     while (1) {

       u32_t val = 0;

      gpio_pin_read(gpiob, PIN_0, &val);

       printk("%d\n",val);

     }

}

 

void main(void)

{

     gpiob = device_get_binding(GPIO_DRV_NAME);

     if (!gpiob)

     {

           printk("error\n");

           return;

     }

 

     // Pin 0 - simple input config - suitable for polling

     gpio_pin_configure(gpiob, PIN_0, GPIO_DIR_IN | GPIO_PUD_PULL_UP );

     printk("Sampling micro:bit pin P0\n");

     poll();

 

Thanks


Carles Cufi
 

Hi Martin,

 

I’ve only ever tested that GPIO driver in interrupt mode, but I don’t see why it shouldn’t work in polling mode.

Have you tried it in interrupt mode to see if it works?

 

Unfortunately our driver expert is away this week, I’m sure he’ll respond next week though.

 

Maybe Johan can give us some input as well.

 

Regards,

 

Carles

 

From: zephyr-users-bounces@... [mailto:zephyr-users-bounces@...] On Behalf Of Martin Woolley
Sent: 21 February 2018 14:08
To: zephyr-users@...
Subject: [Zephyr-users] micro:bit GPIO read always returning 1

 

Zephyr newbie question. I’m trying to poll an external pin on a micro:bit. I have a rocker switch with pull up resistor connected to it and the circuit works (tested with code written with microbit-dal APIs). My Zephyr GPIO reads always return 1, however. What am I doing wrong?

 

This video shows code which uses the microbit-dal APIs working... I want to achieve the same for Zephyr:

 

https://drive.google.com/open?id=1h3LWC_PPNBhBs2mAFJj0ZgRvkd9Dk1NB

 

Code fragments:

 

#define PIN_0 EXT_P0_GPIO_PIN

struct device *gpiob;

void poll(void)

{

     struct mb_display *disp = mb_display_get();

     while (1) {

       u32_t val = 0;

      gpio_pin_read(gpiob, PIN_0, &val);

       printk("%d\n",val);

     }

}

 

void main(void)

{

     gpiob = device_get_binding(GPIO_DRV_NAME);

     if (!gpiob)

     {

           printk("error\n");

           return;

     }

 

     // Pin 0 - simple input config - suitable for polling

     gpio_pin_configure(gpiob, PIN_0, GPIO_DIR_IN | GPIO_PUD_PULL_UP );

     printk("Sampling micro:bit pin P0\n");

     poll();

 

Thanks


Martin Woolley <mwoolley@...>
 

Hi Carles and thanks for the quick response 😊

 

micro:bit buttons, which are of course connected to GPIO pins work fine in interrupt mode:

 

#define PIN_A SW0_GPIO_PIN

#define PORT SW0_GPIO_NAME

#define EDGE (GPIO_INT_EDGE | GPIO_INT_ACTIVE_LOW | GPIO_INT_DEBOUNCE)

 

 

  gpiob = device_get_binding(PORT);

  if (!gpiob)

  {

    printk("error\n");

    return;

  }

 

  // Button A

  gpio_pin_configure(gpiob, PIN_A, GPIO_DIR_IN | GPIO_INT | EDGE);

  gpio_init_callback(&gpio_btnA_cb, button_A_pressed, BIT(PIN_A));

  gpio_add_callback(gpiob, &gpio_btnA_cb);

  gpio_pin_enable_callback(gpiob, PIN_A);

 

 

 

I haven’t tried interrupt mode with pins on the edge connector. I’ll try that next. Presumably the same pin configuration (apart from the pin number)  should be valid.

 

Do you see anything obviously wrong with the pin config I’m using for polling, though? I’ve tried various flags but none of them made any difference for me. This is doubtless user error.... but what that error is I don’t yet know.

 

I’ll try interrupt mode and report back.

 

Regards

 

Martin

 

 

From: Cufi, Carles [mailto:Carles.Cufi@...]
Sent: 21 February 2018 13:35
To: Martin Woolley <mwoolley@...>; zephyr-users@...
Subject: RE: micro:bit GPIO read always returning 1

 

Hi Martin,

 

I’ve only ever tested that GPIO driver in interrupt mode, but I don’t see why it shouldn’t work in polling mode.

Have you tried it in interrupt mode to see if it works?

 

Unfortunately our driver expert is away this week, I’m sure he’ll respond next week though.

 

Maybe Johan can give us some input as well.

 

Regards,

 

Carles

 

From: zephyr-users-bounces@... [mailto:zephyr-users-bounces@...] On Behalf Of Martin Woolley
Sent: 21 February 2018 14:08
To: zephyr-users@...
Subject: [Zephyr-users] micro:bit GPIO read always returning 1

 

Zephyr newbie question. I’m trying to poll an external pin on a micro:bit. I have a rocker switch with pull up resistor connected to it and the circuit works (tested with code written with microbit-dal APIs). My Zephyr GPIO reads always return 1, however. What am I doing wrong?

 

This video shows code which uses the microbit-dal APIs working... I want to achieve the same for Zephyr:

 

https://drive.google.com/open?id=1h3LWC_PPNBhBs2mAFJj0ZgRvkd9Dk1NB

 

Code fragments:

 

#define PIN_0 EXT_P0_GPIO_PIN

struct device *gpiob;

void poll(void)

{

     struct mb_display *disp = mb_display_get();

     while (1) {

       u32_t val = 0;

      gpio_pin_read(gpiob, PIN_0, &val);

       printk("%d\n",val);

     }

}

 

void main(void)

{

     gpiob = device_get_binding(GPIO_DRV_NAME);

     if (!gpiob)

     {

           printk("error\n");

           return;

     }

 

     // Pin 0 - simple input config - suitable for polling

     gpio_pin_configure(gpiob, PIN_0, GPIO_DIR_IN | GPIO_PUD_PULL_UP );

     printk("Sampling micro:bit pin P0\n");

     poll();

 

Thanks


Martin Woolley <mwoolley@...>
 

No sign of life in interrupt mode either, using either high or low triggering e.g.

 

#define PIN_0 EXT_P0_GPIO_PIN

#define GPIO_DRV_NAME "GPIO_0"

 

struct device *gpiob;

static struct gpio_callback gpio_trigger_cb;

 

void triggered(struct device *gpiob, struct gpio_callback *cb, u32_t pins)

{

  struct mb_display *disp = mb_display_get();

  printk("Triggered at %d\n", k_cycle_get_32());

  u32_t val = 0;

  gpio_pin_read(gpiob, PIN_0, &val);

  mb_display_image(disp, MB_DISPLAY_MODE_SINGLE, K_SECONDS(1),  &patterns[val], 1);

}

 

 

  gpiob = device_get_binding(GPIO_DRV_NAME);

  if (!gpiob)

  {

    printk("error\n");

    return;

  }

 

 

  gpio_pin_configure(gpiob, PIN_0, GPIO_DIR_IN | GPIO_INT_EDGE | GPIO_INT_ACTIVE_HIGH);

  gpio_init_callback(&gpio_trigger_cb, triggered, BIT(PIN_0));

  gpio_add_callback(gpiob, &gpio_trigger_cb);

  gpio_pin_enable_callback(gpiob, PIN_0);

 

I’m not at all confident I have the right flags... I was guided by the samples. AFAIK EXT_P0_GPIO_PIN is correct... I got that from board.h:

 

/* External edge connector pin mappings to nRF51 GPIO pin numbers.

* More information:

* https://www.microbit.co.uk/device/pins

* https://github.com/microbit-foundation/microbit-reference-design/tree/master/PDF/Schematic%20Print

*/

#define EXT_P0_GPIO_PIN     3   /* P0, Analog in */

 

 

From: Martin Woolley
Sent: 21 February 2018 13:41
To: 'Cufi, Carles' <Carles.Cufi@...>; zephyr-users@...
Subject: RE: micro:bit GPIO read always returning 1

 

Hi Carles and thanks for the quick response 😊

 

micro:bit buttons, which are of course connected to GPIO pins work fine in interrupt mode:

 

#define PIN_A SW0_GPIO_PIN

#define PORT SW0_GPIO_NAME

#define EDGE (GPIO_INT_EDGE | GPIO_INT_ACTIVE_LOW | GPIO_INT_DEBOUNCE)

 

 

  gpiob = device_get_binding(PORT);

  if (!gpiob)

  {

    printk("error\n");

    return;

  }

 

  // Button A

  gpio_pin_configure(gpiob, PIN_A, GPIO_DIR_IN | GPIO_INT | EDGE);

  gpio_init_callback(&gpio_btnA_cb, button_A_pressed, BIT(PIN_A));

  gpio_add_callback(gpiob, &gpio_btnA_cb);

  gpio_pin_enable_callback(gpiob, PIN_A);

 

 

 

I haven’t tried interrupt mode with pins on the edge connector. I’ll try that next. Presumably the same pin configuration (apart from the pin number)  should be valid.

 

Do you see anything obviously wrong with the pin config I’m using for polling, though? I’ve tried various flags but none of them made any difference for me. This is doubtless user error.... but what that error is I don’t yet know.

 

I’ll try interrupt mode and report back.

 

Regards

 

Martin

 

 

From: Cufi, Carles [mailto:Carles.Cufi@...]
Sent: 21 February 2018 13:35
To: Martin Woolley <mwoolley@...>; zephyr-users@...
Subject: RE: micro:bit GPIO read always returning 1

 

Hi Martin,

 

I’ve only ever tested that GPIO driver in interrupt mode, but I don’t see why it shouldn’t work in polling mode.

Have you tried it in interrupt mode to see if it works?

 

Unfortunately our driver expert is away this week, I’m sure he’ll respond next week though.

 

Maybe Johan can give us some input as well.

 

Regards,

 

Carles

 

From: zephyr-users-bounces@... [mailto:zephyr-users-bounces@...] On Behalf Of Martin Woolley
Sent: 21 February 2018 14:08
To: zephyr-users@...
Subject: [Zephyr-users] micro:bit GPIO read always returning 1

 

Zephyr newbie question. I’m trying to poll an external pin on a micro:bit. I have a rocker switch with pull up resistor connected to it and the circuit works (tested with code written with microbit-dal APIs). My Zephyr GPIO reads always return 1, however. What am I doing wrong?

 

This video shows code which uses the microbit-dal APIs working... I want to achieve the same for Zephyr:

 

https://drive.google.com/open?id=1h3LWC_PPNBhBs2mAFJj0ZgRvkd9Dk1NB

 

Code fragments:

 

#define PIN_0 EXT_P0_GPIO_PIN

struct device *gpiob;

void poll(void)

{

     struct mb_display *disp = mb_display_get();

     while (1) {

       u32_t val = 0;

      gpio_pin_read(gpiob, PIN_0, &val);

       printk("%d\n",val);

     }

}

 

void main(void)

{

     gpiob = device_get_binding(GPIO_DRV_NAME);

     if (!gpiob)

     {

           printk("error\n");

           return;

     }

 

     // Pin 0 - simple input config - suitable for polling

     gpio_pin_configure(gpiob, PIN_0, GPIO_DIR_IN | GPIO_PUD_PULL_UP );

     printk("Sampling micro:bit pin P0\n");

     poll();

 

Thanks


Vitor Massaru Iha
 

Hi Martin,

On Wed, Feb 21, 2018 at 10:08 AM, Martin Woolley <mwoolley@...> wrote:

Zephyr newbie question. I’m trying to poll an external pin on a micro:bit. I have a rocker switch with pull up resistor connected to it and the circuit works (tested with code written with microbit-dal APIs). My Zephyr GPIO reads always return 1, however. What am I doing wrong?



In order for the resistor to function as a pullup it must be placed before the switch, ie between PIN_0 and the VCC.
But note that you configured the GPIO port with the pullup flag, And the switch is connected between PIN_0 and VCC.
So the expected result is always 1.

Try to set the the GPIO port this way:

1)
gpio_pin_configure(gpiob, PIN_0, GPIO_DIR_IN | GPIO_PUD_PULL_DOWN );
Without the resistor, It should work with the resistor, but that way it's unnecessary.

2) or
gpio_pin_configure(gpiob, PIN_0, GPIO_DIR_IN);
And connect the resistor between PIN_0 and GND;

There're other options, but I think you understand.

BR,
iha


Vitor Massaru Iha
 

Hi Martin,


On Thu, Feb 22, 2018 at 6:06 AM, Martin Woolley <mwoolley@...> wrote:

thanks a lot for your guidance. Changing my pin config to

 

gpio_pin_configure(gpiob, PIN_0, GPIO_DIR_IN | GPIO_PUD_PULL_DOWN );

 

without changing the circuit, now produces the behaviour I wanted.


Great!
 

If instead of polling, I want to use interrupts to trigger a call back when the pin goes either high or low, what should my pin config be? I’m getting no call back with the following:

 

  gpio_pin_configure(gpiob, PIN_0, GPIO_DIR_IN | GPIO_INT_EDGE | GPIO_INT_ACTIVE_HIGH );

  gpio_init_callback(&gpio_trigger_cb, triggered, BIT(PIN_0));

  gpio_add_callback(gpiob, &gpio_trigger_cb);

  gpio_pin_enable_callback(gpiob, PIN_0);

 


Just add this flag GPIO_INT on gpio_pin_configure():

gpio_pin_configure(gpiob, PIN_0, GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | GPIO_INT_ACTIVE_HIGH );

BR,
iha




Martin Woolley <mwoolley@...>
 

As easy as that? 😊

 

OK, apparently I don’t understand what the documentation says for the flags:

 

GPIO_INT

GPIO pin to trigger interrupt.

GPIO_INT_EDGE

Do Edge trigger.

 

So, what I’m concluding is that you need to specify GPIO_INT to enable interrupts on the pin and then another flag like GPIO_INT_EDGE to say when in the signal processing you want the interrupt to occur? If so... makes sense (now). I thought saying GPIO_INT_EDGE was enough to enable interrupts *and* to say they should occur on edge. My bad.

 

Works anyway, thanks once again. Works even better with GPIO_INT_DEBOUNCE as well.

 

All the best

 

Martin

 

From: Vitor [mailto:vitor@...]
Sent: 22 February 2018 12:40
To: Martin Woolley <mwoolley@...>; zephyr-users@...
Subject: Re: [Zephyr-users] micro:bit GPIO read always returning 1

 

Hi Martin,

 

On Thu, Feb 22, 2018 at 6:06 AM, Martin Woolley <mwoolley@...> wrote:

thanks a lot for your guidance. Changing my pin config to

 

gpio_pin_configure(gpiob, PIN_0, GPIO_DIR_IN | GPIO_PUD_PULL_DOWN );

 

without changing the circuit, now produces the behaviour I wanted.

 

Great!

 

If instead of polling, I want to use interrupts to trigger a call back when the pin goes either high or low, what should my pin config be? I’m getting no call back with the following:

 

  gpio_pin_configure(gpiob, PIN_0, GPIO_DIR_IN | GPIO_INT_EDGE | GPIO_INT_ACTIVE_HIGH );

  gpio_init_callback(&gpio_trigger_cb, triggered, BIT(PIN_0));

  gpio_add_callback(gpiob, &gpio_trigger_cb);

  gpio_pin_enable_callback(gpiob, PIN_0);

 

 

Just add this flag GPIO_INT on gpio_pin_configure():

gpio_pin_configure(gpiob, PIN_0, GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | GPIO_INT_ACTIVE_HIGH );

BR,

iha