Topics

GPIO support on nRF52840 DK

Leonardo Molina <leonardomt@...>
 

Hello everyone,

Can I access (read/write) a GPIO that is not an LED or button listed in the "Connections and IOs" section of link below?

I read in that page that "Other hardware features are not supported by the Zephyr kernel." but (since I am a newbie in embedded devices) I am not sure if that means that "only buttons 1 to 4 are supported and no other GPIO" or else refers to more abstract features (e.g. Enhanced ShockBurst).

Here's the context of my question:
I am editing the example code samples/basic/button to use a GPIO pin that is different from BUTTON 1, 2, 3 or 4 to trigger the button_pressed callback.

I changed
#define PIN DT_ALIAS_SW0_GPIOS_PIN
... to ...
#define PIN 33
and the callback is never called when I toggle the logical state of that pin in the board (from ground to 3.3V nor VDD).

I am not sure if this makes sense if I am using Zephyr, but in the nRF's SDK, GPIO P1.01 of the development board is mapped to 33:
nRF5_SDK_15/components/boards/pca10056.h
#define ARDUINO_0_PINĀ 

This is my very first question on a public list/forum ever (...as far as I recall) so please forgive any mistakes in terms of posting rules, etc.

Thanks for your help!

Bolivar, Marti
 

Hi,

" via Lists.Zephyrproject.Org"
<leonardomt=gmail.com@...> writes:

Hello everyone,

Can I access (read/write) a GPIO that is not an LED or button listed in the
"Connections and IOs" section of link below?
https://docs.zephyrproject.org/latest/boards/arm/nrf52840_pca10056/doc/index.html#push-buttons

I read in that page that "Other hardware features are not supported by the
Zephyr kernel." but (since I am a newbie in embedded devices) I am not sure
if that means that "only buttons 1 to 4 are supported and no other GPIO" or
else refers to more abstract features (e.g. Enhanced ShockBurst).
All GPIOs are supported and accessible, not just the LEDs and
buttons. This includes all GPIOs pinned out to the expansion headers.


Here's the context of my question:
I am editing the example code samples/basic/button to use a GPIO pin that
is different from BUTTON 1, 2, 3 or 4 to trigger the button_pressed
callback.

I changed
#define PIN DT_ALIAS_SW0_GPIOS_PIN
... to ...
#define PIN 33
and the callback is never called when I toggle the logical state of that
pin in the board (from ground to 3.3V nor VDD).

I am not sure if this makes sense if I am using Zephyr, but in the nRF's
SDK, GPIO P1.01 of the development board is mapped to 33:
nRF5_SDK_15/components/boards/pca10056.h
#define ARDUINO_0_PIN
I think this is likely to be a common question for beginners, so I'll
provide various details here that hopefully will be google-able for
others later :). There is a TL;DR for this specific question below.

Zephyr's GPIO API works differently than Arduino's.

Instead of a single, linear pin numbering from 0 to N-1 for all the pins
(or the D0, D1, ... "digital" and A0, A1, ... "analog" pin
macros), Zephyr identifies a GPIO with two pieces of information:

1. The GPIO "controller", which is a struct device implementing the GPIO
API. For all the gory details on the device model, see:

https://docs.zephyrproject.org/latest/reference/drivers/index.html

2. The pin number, which is specific to each controller. For example,
pin 0 on one controller is different than pin 0 on another
controller.

On nRF SoCs, there are two separate GPIO controller devices: one for the
P0.x pins, and another for the P1.x pins.

So, to use pin P1.01 in the button sample, you need to set PORT to use
the P1.x controller, and PIN to 1.

To set PORT, you need the "label" for the P1.x controller, which in this
case is DT_ALIAS_GPIO_1_LABEL.

This define is generated by device tree. See
zephyr/include/generated/generated_dts_board_unfixed.h in your build
directory for all the available defines, and
https://docs.zephyrproject.org/latest/guides/dts/index.html for more
information on DT.

It works the exact same way on other SoCs. Only the label defines from
DT vary.

TL;DR here's a patch that does what you want:

diff --git zephyr/samples/basic/button/src/main.c zephyr/samples/basic/button/src/main.c
index d55147c171..c1e94767a7 100644
--- zephyr/samples/basic/button/src/main.c
+++ zephyr/samples/basic/button/src/main.c
@@ -52,6 +52,10 @@
/* Sleep time */
#define SLEEP_TIME 500

+#undef PORT
+#undef PIN
+#define PORT DT_ALIAS_GPIO_1_LABEL
+#define PIN 1

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



This is my very first question on a public list/forum ever (...as far as I
recall) so please forgive any mistakes in terms of posting rules, etc.
You did great! Your question was clear.


Thanks for your help!
Hope this helps,
Marti


leonardomt@...
 

This worked, although this pin in particular did not trigger the interrupt function but required calling gpio_pin_read(...) inside a loop to detect changes in its state.
Thanks for the fix and the walk-thru!

What thought process or what resource/documentation makes one realize that pin P1.0 belongs to port DT_ALIAS_GPIO_1_LABEL?

For example, I found that P1.0 (D1) belongs to port "gpio1" by looking at the gpio-map definition in nrf52840_pca10056.dts; as you suggested, generated_dts_board_unfixed.h lists that "GPIO_1" is assigned to DT_NORDIC_NRF_GPIO_50000300_LABEL and finally that DT_ALIAS_GPIO_1_LABEL = DT_NORDIC_NRF_GPIO_50000300_LABEL... but is this the only way to know what's where?

Thanks

Bolivar, Marti
 

"leonardomt via Lists.Zephyrproject.Org"
<leonardomt=gmail.com@...> writes:

This worked, although this pin in particular did not trigger the interrupt function but required calling gpio_pin_read(...) inside a loop to detect changes in its state.
Thanks for the fix and the walk-thru!
Sure thing!


What thought process or what resource/documentation makes one realize
that pin P1.0 belongs to port DT_ALIAS_GPIO_1_LABEL?

For example, I found that P1.0 (D1) belongs to port "gpio1" by looking at the gpio-map definition in nrf52840_pca10056.dts; as you suggested, generated_dts_board_unfixed.h lists that "GPIO_1" is assigned to DT_NORDIC_NRF_GPIO_50000300_LABEL and finally that DT_ALIAS_GPIO_1_LABEL = DT_NORDIC_NRF_GPIO_50000300_LABEL... but is this the only way to know what's where?
Port 1 is the GPIO controller; the .0 is a pin number it
controls. You want the device label for the controller -- as
you've seen, the pin number is a separate piece of data.

You can look at the DTS files to know what nodes are available:

https://github.com/zephyrproject-rtos/zephyr/blob/master/dts/arm/nordic/nrf52840.dtsi#L126

This dtsi (Device Tree Source Include) is included from the .dts
file for the board, which you can find by searching for its name
in boards/*/:

https://github.com/zephyrproject-rtos/zephyr/blob/master/boards/arm/nrf52840_pca10056/nrf52840_pca10056.dts

The nodes have the addresses of the hardware peripherals they
correspond to, so you can find the one you want by comparing your
chip memory map with the DT reg property. (But usually, they're
numbered according to the same peripheral numbering in the chip
reference manual, so P1 means you're looking for GPIO_1. And
similarly for other types of peripheral, like SPI_1, I2C_3, etc.)

Marti


Thanks

leonardomt@...
 

That makes sense!

I stand corrected; the interrupt is raised just as it is in the button example!
I am not quite sure why it didn't trigger before but it must have been a result of playing around with these files.

Thanks,
Leo