Re: Max Callbacks? and other GPIO problems - nrf52840-MDK board (fix for dead GPIOs)

Lawrence King

I managed to get Problem 3) below resolved. It turns out that the serial port is ‘stealing’ these two pins for RTS and CTS. This is incorrectly set in the file boarts/arm/nrf52840_mds/nrf52840_mdk.dts in the uart0 section. Uart0 is hardwired on the board as 2-wire uart and does not use RTS/CTS. The correction should be:


index aff71d60b9..b46618591f 100644

--- a/boards/arm/nrf52840_mdk/nrf52840_mdk.dts

+++ b/boards/arm/nrf52840_mdk/nrf52840_mdk.dts

@@ -75,8 +75,18 @@

        status = "ok";

        tx-pin = <20>;

        rx-pin = <19>;

-       rts-pin = <5>;

-       cts-pin = <7>;

+/*     rts-pin = <5>;

+       cts-pin = <7>; */



 &i2c0 {



Problems 1) and 2) still exist…


Lawrence King

Principal Developer



From: users@... <users@...> On Behalf Of Lawrence King
Sent: Friday, March 8, 2019 10:40 AM
To: users@...
Subject: [Zephyr-users] Max Callbacks? and other GPIO problems - nrf52840-MDK board


I am developing a piece of code for nrf52840 that uses 24 GPIOs. Conveniently the NRF52840-MDK board brings out exactly 24 GPIOs so I have enough hardware on hand. The application needs 12 inputs and 12 outputs. The inputs are based on a used pushing one of 12 switches, and the output is based on proprietary logic based on the 12 inputs (for simplicity just think of it as a 1:1 operation). After working around Problem 1 (see below) I got all of my code running correctly with a small table of 2 inputs and 2 outputs, the call backs work, the logic works, all is good, then I expanded the table to 12 inputs and 12 outputs. This is where things get weird….


Problem 1) GPIO Group


The NRF52840 has two groups of GPIO ports, controller 0 has 32 GPIOs and controller 1 has fewer. All of the 24 GPIOs that go to pins on the nrf52840-MDK board are on controller 0 (along with the button and the LEDs). I had thought that I could call get_device_binding(SW0_GPIO_CONTROLLER) and get a single handle to all 32 bits on the port. Unfortunately when I start  setting them to either input or output if I try to set pins as outputs (assuming I set one pin as input first) they don’t work (with no error return codes). I ended up getting two device handles, with the second being get_device_binding(LED0_GPIO_CONTROLLER). Once I assigned all of the inputs to the first handle, and the outputs to the second handle I was able to configure and operate all of the 24 pins (with exception to the problems below).


Problem 2) Max Callbacks

Next I added callbacks to all 12 of the inputs. The first 8 callbacks add with no issues, the last 4 return error -19. I couldn’t find a kernel configuration parameter for the max number of callbacks. Is it hard coded to 8 somewhere? Of maybe I need to make a memory region larger, which CONFIG do I need to expand?


Problem 3) GPIOs that don’t.

Now the strangest problem. The gpios at P0.05 andP0.07 don’t work. I can program them as outputs, and they drive low once programmed, but I can’t set them high. All the other gpios work as expected. I thought maybe I had damaged the board, but I took a brand new nfr52840-MDK out of the antistatic bag, loaded the same code and I have the same problem. I suspect there is some vestigial setting somewhere in the device tree that causes these two gpios to behave differently. Any hint where I should look? I generated very simplified code to demonstrate the problem (see below). Gpios 4 6 and 8 work, but 5 and 7 don’t.


Lawrence King

Principal Developer

Connected Transport Market Unit



1  2 - linkedin  3 - instagram  4 - youtube  6 - facebook  7


CONFIDENTIAL: This e-mail and any attachments are confidential and intended solely for the use of the individual(s) to whom it is addressed. It can contain proprietary confidential information and be subject to legal privilege and/or subject to a non-disclosure Agreement. Unauthorized use, disclosure or copying is strictly prohibited. If you are not the/an addressee and are in possession of this e-mail, please delete the message and notify us immediately. Please consider the environment before printing this e-mail. Thank you.




*  Irdeto Excavator App


 *           main.c


 *           Lawrence King





#include <zephyr.h>

#include <misc/printk.h>

#include <device.h>

#include <gpio.h>


// These should be defined somewhere in Zephyr, but I couldn't find them hence I took this from the MDK schematic


#define GPIO_00                           0            // P0.00              Button input

#define GPIO_01                           1            // P0.01

#define GPIO_02                           2            // P0.02

#define GPIO_03                           3            // P0.03

#define GPIO_04                           4            // P0.04

#define GPIO_05                           5            // P0.05

#define GPIO_06                           6            // P0.06

#define GPIO_07                           7            // P0.07

#define GPIO_08                           8            // P0.08

#define GPIO_09                           9            // P0.09

#define GPIO_10                           10          // P0.10

#define GPIO_11                           11          // P0.11

#define GPIO_12                           12          // P0.12

#define GPIO_13                           13          // P0.13

#define GPIO_14                           14          // P0.14

#define GPIO_15                           15          // P0.15

#define GPIO_16                           16          // P0.16

#define GPIO_17                           17          // P0.17

#define GPIO_18                           18          // P0.18

#define GPIO_19                           19          // P0.19

#define GPIO_20                           20          // P0.20

#define GPIO_21                           21          // P0.21

#define GPIO_22                           22          // P0.22              Green LED

#define GPIO_23                           23          // P0.23              Red LED

#define GPIO_24                           24          // P0.24              Blue LED

#define GPIO_25                           25          // P0.25

#define GPIO_26                           26          // P0.26

#define GPIO_27                           27          // P0.27

#define GPIO_28                           28          // P0.28

#define GPIO_29                           29          // P0.29

#define GPIO_30                           30          // P0.30

#define GPIO_31                           31          // P0.31

#define NUM_GPIOS      32          // Max for controller P0 on nrf52840


#define RED_LED                          GPIO_23

#define GREEN_LED       GPIO_22

#define BLUE_LED          GPIO_24

#define BUTTON                           GPIO_00



void main(void)


              int         i,j,n;

              u32_t    val;

              struct device                    *in_device, *out_device;



struct    foo {

              int         gpio;

              int         state;

              int         dir;        // 0=input, 1=output

} setup_gpios[] = {

                            // gpio                state     dir

                            {BUTTON,          0,           0},         // the button 00

                            {GPIO_04,          0,           1},         // temp foo

                            {GPIO_05,          0,           1},         //3B

                            {GPIO_06,          0,           1},         //1B

                            {GPIO_07,          0,           1},         //5A

                            {GPIO_08,          0,           1}           //5B


#define SETUP_GPIOS              (sizeof(setup_gpios)/sizeof(setup_gpios[0]))




              printk("SETUP_MODE with %d setup_gpios\n", SETUP_GPIOS);


              in_device  = device_get_binding(SW0_GPIO_CONTROLLER);

              out_device  = device_get_binding(LED0_GPIO_CONTROLLER);


              for (i=0; i<SETUP_GPIOS; i++) {

                            if (setup_gpios[i].dir==0) { // input

                                          gpio_pin_configure(in_device, setup_gpios[i].gpio,

                                                        (GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | GPIO_PUD_PULL_UP | GPIO_INT_DEBOUNCE | GPIO_INT_DOUBLE_EDGE ));

                            } else { // output

                                          gpio_pin_configure(out_device, setup_gpios[i].gpio, GPIO_DIR_OUT | GPIO_DS_DFLT_HIGH);


                            setup_gpios[i].state=5;  // all inputs will print out initially

                            printk("\tinitialized GPIO_%02d.\n",setup_gpios[i].gpio);


              gpio_pin_configure(out_device, GREEN_LED, GPIO_DIR_OUT);



              // scan and look for state changes, and slowly pulse the GPIOs so we can look at hem with a voltmeter

              while (1) {

                            for (i=0; i<SETUP_GPIOS; i++) {

                                          if (setup_gpios[i].dir==0) {


                                                        if (val != setup_gpios[i].state) {

                                                                      // input changed state, print it out

                                                                      printk("input GPIO_%02d=%d\n",setup_gpios[i].gpio, val);





                                          if(i==0) {

                                                        gpio_pin_write(out_device, GREEN_LED, (n++)&1); //toggle to show life

                                                        for (j=1; j<SETUP_GPIOS; j++) {

                                                                      if ((setup_gpios[j].gpio == ((n>>1) & 0x07)) && (setup_gpios[j].dir==1) && (setup_gpios[j].gpio!=0)) {

                                                                                    printk("output GPIO_%02d=%d\n",setup_gpios[j].gpio, !(n&1));

                                                                                    gpio_pin_write(out_device, setup_gpios[j].gpio, !(n&1) ); //toggle slowly




                                          gpio_pin_read(in_device,setup_gpios[0].gpio,&val);              //button

                                          if (val != setup_gpios[0].state) {

                                                        gpio_pin_write(out_device, setup_gpios[4].gpio, val ); // GPIO_07 is supposed to track the button

                                                        setup_gpios[0].state=val;            // remember the button state

                                                        printk("GPIO_07 set to %d\n",val);







Join { to automatically receive all group messages.