Re: Max Callbacks? and other GPIO problems - nrf52840-MDK board (fix for dead GPIOs)
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 { (END)
Problems 1) and 2) still exist…
Lawrence King Principal Developer +1(416)627-7302
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(416)627-7302
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 * irdeto.com * */
#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_CONTROLLER SW0_GPIO_CONTROLLER #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("SW0_GPIO_CONTROLLER=\"%s\".\n",SW0_GPIO_CONTROLLER); printk("LED0_GPIO_CONTROLLER=\"%s\".\n",LED0_GPIO_CONTROLLER); 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); n=0;
// 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) { gpio_pin_read(in_device,setup_gpios[i].gpio,&val); if (val != setup_gpios[i].state) { // input changed state, print it out printk("input GPIO_%02d=%d\n",setup_gpios[i].gpio, val); setup_gpios[i].state=val; } } k_sleep(300); 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); } } } }
|
|