This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Zephyr CustomBoard with NRF52840 and MCP23S17

Hello folks

I have been struggling for some time with the driver for the MCP23S17 in Zephyr.

I have already tried this code:
https://devzone.nordicsemi.com/f/nordic-q-a/64024/sample-mcp23s17-driver

But for me its not working!

I receive the following error:

/home/trug/zephyrproject/zephyr/include/devicetree.h:158:36: error: 'DT_N_NODELABEL_spi2gpio_P_label' undeclared (first use in this function); did you mean 'DT_N_NODELABEL_gpiote'?
  158 | #define DT_NODELABEL(label) DT_CAT(DT_N_NODELABEL_, label)
      |                                    ^~~~~~~~~~~~~~~
/home/trug/zephyrproject/zephyr/include/devicetree.h:1526:38: note: in definition of macro 'DT_CAT'
 1526 | #define DT_CAT(node_id, prop_suffix) node_id##prop_suffix
      |                                      ^~~~~~~
/home/trug/zephyrproject/zephyr/include/devicetree.h:390:27: note: in expansion of macro 'DT_PROP'
  390 | #define DT_LABEL(node_id) DT_PROP(node_id, label)
      |                           ^~~~~~~
../src/main.c:80:27: note: in expansion of macro 'DT_LABEL'
   80 | #define MCP23S17_DEV_NAME DT_LABEL(DT_NODELABEL(spi2gpio))
      |                           ^~~~~~~~
/home/trug/zephyrproject/zephyr/include/devicetree.h:158:29: note: in expansion of macro 'DT_CAT'
  158 | #define DT_NODELABEL(label) DT_CAT(DT_N_NODELABEL_, label)
      |                             ^~~~~~
../src/main.c:80:36: note: in expansion of macro 'DT_NODELABEL'
   80 | #define MCP23S17_DEV_NAME DT_LABEL(DT_NODELABEL(spi2gpio))
   
...
...
...
      |                                    ^~~~~~~~~~~~
../src/main.c:106:51: note: in expansion of macro 'MCP23S17_DEV_NAME'
  106 |  struct device *mcp23s17_dev = device_get_binding(MCP23S17_DEV_NAME);

This is my main.c

#include <zephyr.h>

#include <device.h>
#include <devicetree.h>
#include <drivers/gpio.h>        
 
#include <sys/printk.h>
#include <drivers/uart.h>

#include <logging/log.h>

#include "CustomBoard.h"

LOG_MODULE_REGISTER(net_google_iot_mqtt, LOG_LEVEL_DBG);

/* This comes from newlib. */
#include <time.h>
#include <inttypes.h>



#define	MCP23S17_DEV_NAME	DT_LABEL(DT_NODELABEL(spi2gpio))

void main(void)
{
	int ret;

	LOG_INF(">>> Test: Driver MCP23S17 <<<");

	// MCP23S17
	struct device *mcp23s17_dev = device_get_binding(MCP23S17_DEV_NAME);

	if (!mcp23s17_dev) {
		LOG_INF("Cannot find mcp23s17!\n");
		return;
	}

	ret = gpio_pin_configure(mcp23s17_dev, 1, GPIO_OUTPUT_ACTIVE);
	
	...
    ...
    ...
    
	while (1) {
		gpio_pin_set(mcp23s17_dev, 1, (int)true);

		k_msleep(125);

		gpio_pin_set(mcp23s17_dev, 1, (int)false);
	}
}

I compared it to some other drivers in zephyr and also tried the following defines in the main.c (but no of them are working)

//#define    MCP23S17_DEV_NAME    DT_LABEL(DT_NODELABEL("spi2gpio"))

//#define    MCP23S17_DEV_NAME    DT_LABEL(DT_NODELABEL(mcp23s17))

//#define    MCP23S17_DEV_NAME    DT_INST(0, spi2gpio)

//#define    MCP23S17_DEV_NAME    DT_LABEL(DT_INST(0, microchip_mcp23s17)
//#define    MCP23S17_DEV_NAME    DT_LABEL(DT_INST(0, mcp23s17)

//#define    MCP23S17_DEV_NAME    "GPIO_MCP23S17"
//#define    MCP23S17_DEV_NAME    "microchip_mcp23s17"

Here is my .overlay file:

/* GPIO Expander */
&spi2 {
    label="SPI2";
    status = "okay";
    sck-pin = <22>;
    mosi-pin = <23>;
    miso-pin = <24>;
    cs-gpios = <&gpio1 1 0>;

    spi2gpio: gpio@0 {	
    	label="mcp23s17";
        compatible="microchip,mcp23s17";
        gpio-controller;
        #gpio-cells = <2>;
        spi-max-frequency = <800000>;
        reg = <0>;
	    #ngpios = <16>;
    };
};

Here are my configs from my prj.confg

# Driver: GPIO
CONFIG_GPIO=y
CONFIG_GPIO_MCP23S17=y

# SPI
CONFIG_SPI=y
CONFIG_SPI_2=y

# UART support
CONFIG_SERIAL=y
CONFIG_UART_CONSOLE=n

# Print
CONFIG_PRINTK=y

# RTT Segger Debugger
CONFIG_USE_SEGGER_RTT=y
CONFIG_RTT_CONSOLE=y

 

What am I doing wrong? Can anyone help me or give me an example?

Regards
Dominique

  • What tag are you using? I tested your sample with NCS v1.3.0 and it built without any errors. The only change I made was to swap #ngpios with ngpios in the overlay file.

    Best regards,

    Simon

  • Thanks Simon

    I tried to build the firmware as nrf52840dk_nrf52840 and it worked fine.
    But it does not work with my customboard.

    Since my customboard is not in the Zephyr directory, it could be a CMake problem?!

    I will check it and as soon as I find a solution, I will post it here.

  • Since the Zephyr version of Nordic is lagging behind, I use the latest version of Zephyr (2.4). I use some drivers on my customboard that are not yet included in the NCS.

    Do you think this could also lead to further problems?

  • Could you upload your board folder in zipped format, then I can test it myself? Have you seen this guide? Try following that when creating your board folder.

    Best regards,

    Simon

  • Ok I found my problems:

    1.  Custom board error

    Between the Zephyr version 2.1.0 and version 2.4.0 are some differences.

    1.1 In XXX_defconfig the following configs aren't supported anymore:

    CONFIG_ARM=y
    CONFIG_SOC_FAMILY_NRF=y

    1.2 In XXX.dts

    compatible = "nordic,nrf52840-qiaa"; is not working!

    I use compatible = "nordic,nrf52840-dk-nrf52840"; instead.

    2. MCP23S17 pins

    The gpio expander mcp23s17 uses low active reset (nReset) and low active chip select (nCS).

    In my XYZ.overlay file I have to set the CS Pin to 1

    Wrong:

        cs-gpios = <&gpio1 1 0>;

    Correct:

        cs-gpios = <&gpio1 1 1>;

    3. My solution

    3.1 Here my .overlay file

    /* GPIO Expander */
    &spi2 {
        label="SPI2";
        status = "okay";
        sck-pin = <36>;
        mosi-pin = <37>;
        miso-pin = <38>;
        cs-gpios = <&gpio1 1 1>;
    
        spi2gpio: gpio@0 {	
        	label="mcp23s17";
    	compatible = "microchip,mcp23s17";
            gpio-controller;
            #gpio-cells = <2>;
            spi-max-frequency = <800000>;
            reg = <0>;
    	ngpios = <16>;
        };
    };

    3.2 Here my main.c for testing

    #include <zephyr.h>
    #include <device.h>
    #include <devicetree.h>
    #include <drivers/gpio.h>
    
    
    #include "CustomBoard.h"
    
    
    #include <sys/printk.h>
    #include <logging/log.h>
    LOG_MODULE_REGISTER(blinky_logging, LOG_LEVEL_DBG);
    
    /* 1000 msec = 1 sec */
    #define SLEEP_TIME_MS   1000
    
    /* The devicetree node identifier for the "led0" alias. */
    #define LED0_NODE DT_ALIAS(led0)
    
    #if DT_NODE_HAS_STATUS(LED0_NODE, okay)
    #define LED0		DT_GPIO_LABEL(LED0_NODE, gpios)
    #define PIN_LED0	DT_GPIO_PIN(LED0_NODE, gpios)
    #define FLAGS_LED0	DT_GPIO_FLAGS(LED0_NODE, gpios)
    #else
    /* A build error here means your board isn't set up to blink an LED. */
    #error "Unsupported board: led0 devicetree alias is not defined"
    #define LED0		""
    #define PIN_LED0	0
    #define FLAGS_LED0	0
    #endif
    
    
    
    /* The devicetree node identifier for the "led1" alias. */
    #define LED1_NODE DT_ALIAS(led1)
    
    #if DT_NODE_HAS_STATUS(LED1_NODE, okay)
    #define LED1		DT_GPIO_LABEL(LED1_NODE, gpios)
    #define PIN_LED1	DT_GPIO_PIN(LED1_NODE, gpios)
    #define FLAGS_LED1	DT_GPIO_FLAGS(LED1_NODE, gpios)
    #else
    /* A build error here means your board isn't set up to blink an LED. */
    #error "Unsupported board: led0 devicetree alias is not defined"
    #define LED0		""
    #define PIN_LED1	1
    #define FLAGS_LED1	1
    #endif
    
    
    
    #define	MCP23S17_DEV_NAME	DT_LABEL(DT_NODELABEL(spi2gpio))
    
    
    void main(void)
    {
    
    	k_msleep(1000);
    	LOG_INF(">>> [main]: Test Application <<<");
    	
    	const struct device *dev_led_0,*dev_led_1;
    	const struct device *mcp23s17_dev,*gpio_port0_dev;
    	bool led_is_on = true;
    	int ret,i;
    	
    	//-------------------------------------------------------------------------------
    	// MCP23S17
    	//-------------------------------------------------------------------------------
    	LOG_INF("[main]: MCP23S17_Init");
    	mcp23s17_dev = device_get_binding(MCP23S17_DEV_NAME);
    	
    	if (!mcp23s17_dev) {
    		LOG_INF("Cannot find mcp23s17!\n");
    		return;
    	}
    
    	for(i=0; i<16; i++){
    		ret = gpio_pin_configure(mcp23s17_dev, i, GPIO_OUTPUT_ACTIVE);
    		if (ret < 0) {
    			return;
    		}
    	}
    
    
    	//-------------------------------------------------------------------------------
    	// GPIO Port_0
    	//-------------------------------------------------------------------------------
    	LOG_INF("[main]: GPIO_Port0_Init");
    	gpio_port0_dev = device_get_binding(CONFIG_GPIO_PORT_0);
    	if (gpio_port0_dev == NULL) {
    		return;
    	}
    	ret = gpio_pin_configure(gpio_port0_dev, GPIO_EXP_RST, GPIO_OUTPUT_ACTIVE);
    	if (ret < 0) {
    		return;
    	}
    	gpio_pin_set(gpio_port0_dev, GPIO_EXP_RST, (int)true);
    	
    		
    	//-------------------------------------------------------------------------------
    	// LED
    	//-------------------------------------------------------------------------------
    	LOG_INF("[main]: LED_Init");
    	dev_led_0 = device_get_binding(LED0);
    	dev_led_1 = device_get_binding(LED1);
    	if (dev_led_0 == NULL && dev_led_1 == NULL) {
    		LOG_INF("LEDs not found!\n");
    		return;
    	}
    
    	ret = gpio_pin_configure(dev_led_0, PIN_LED0, GPIO_OUTPUT_ACTIVE | FLAGS_LED0);
    	if (ret < 0) {
    		return;
    	}
    
    	ret = gpio_pin_configure(dev_led_1, PIN_LED1, GPIO_OUTPUT_ACTIVE | FLAGS_LED1);
    	if (ret < 0) {
    		return;
    	}
    
    	//-------------------------------------------------------------------------------
    	// While
    	//-------------------------------------------------------------------------------
    	LOG_INF("[main]: while");
    	while (1) {
    		gpio_pin_set(dev_led_0, PIN_LED0, (int)led_is_on);
    		
    		for(i=0; i<16; i++){
    			//LOG_INF(">>> [main:while]: gpio[%i]=[%i]  <<<",i,(int)led_is_on);
    			gpio_pin_set(mcp23s17_dev, i, (int)led_is_on);
    		}
    		LOG_INF("[main:while]: gpio[XYZ]=[%i]",i,(int)led_is_on);
    		
    		led_is_on = !led_is_on;
    		k_msleep(SLEEP_TIME_MS);
    		
    		gpio_pin_set(dev_led_1, PIN_LED1, (int)led_is_on);
    		k_msleep(SLEEP_TIME_MS);
    
    	}
    }

Related