Zephyr GPIO trouble

As always the simplest thing in Zephyr is also the most complicated. I have a Laird module (the BL652) that originally used GPIO 0.19 as an LED driver in their device tree. I overlay that use in my device tree to produce an (active low) enable like so:

/delete-node/ &led2; // GPIO 19 repurposed to be vout enable

 /{
	lm5176_control {
		compatible = "gpio-leds";
		enable1: enable_1 {
			gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>;
			label = "VOUT Enable Low";
		};
	};
	aliases {
		cmvoutenable = &enable1;
		/delete-property/ led1; // This was GPIO 19
	};
 };
 

Then, in my C code, I set up a dt spec like this:

#define VOUT_ENABLE DT_ALIAS(cmvoutenable)
static const struct gpio_dt_spec vout_enable = GPIO_DT_SPEC_GET(VOUT_ENABLE, gpios);

And I try to set the state of the GPIO like this:

message_error_t lm5176_vout_set_enable( bool on )
{
    if (!device_is_ready(vout_enable.port)) {
        printk("VOUT GPIO enable not ready\n");
        return GPIO_ERROR;
    } else {
        if( gpio_pin_configure_dt(&vout_enable, GPIO_OUTPUT_ACTIVE) < 0 ) {
            printk("VOUT GPIO enable cannot be activated\n");
            return GPIO_ERROR;
        }
    }
    if ( on ) {
        printk("Enabling Vout\n");
    }
    else {
        printk("Disabling Vout\n");
    }
    // GPIO logic is reversed from pin function
    if( gpio_pin_set_dt(&vout_enable, on ? 0 : 1 ) < 0 ) {
        printk("Unable to set Vout enable");
        return GPIO_ERROR;
    }
    return MESSAGE_OK;
}

But the GPIO is forever high, regardless of what I try to set it to.

Am I misunderstanding the use of gpio_pin_set_dt?

Parents
  • Hi Bret,

    I found two issues in your code, but neither of which should lead to the result you observe.

    1. In your overlay, you are deleting node led2, but deleting the alias for led1.
      1. This should lead to a build failure, not a run time issue.
    2. In your function, you are configuring the pin again every time you want to set it.
      1. This is unnecessary but should not impact the behavior. I checked.

    Other than that, I tried your code, and it just works for me.

    I use the nRF52840 DK, so I changed the pin number to 14. Otherwise, it's pretty much exactly your code. I deleted node led1 in my test. I am not sure which board you are using. But if you use nrf52dk_nrf52832 and want to use P0.19. If so, you will need to delete node led2

    overlay:

     /delete-node/ &led1; // GPIO 14 repurposed to be vout enable
     /{
    	lm5176_control {
    		compatible = "gpio-leds";
    		enable1: enable_1 {
    			gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
    			label = "VOUT Enable Low";
    		};
    	};
    	aliases {
    		cmvoutenable = &enable1;
    		/delete-property/ led1; // This was GPIO 14
    	};
     };

    main.c modified from hello_world:

    /*
     * Copyright (c) 2012-2014 Wind River Systems, Inc.
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr/kernel.h>
    #include <zephyr/drivers/gpio.h>
    
    #define VOUT_ENABLE DT_ALIAS(cmvoutenable)
    static const struct gpio_dt_spec vout_enable = GPIO_DT_SPEC_GET(VOUT_ENABLE, gpios);
    
    typedef uint32_t message_error_t;
    #define GPIO_ERROR 1
    #define MESSAGE_OK 0
    
    uint32_t init(void)
    {
        if (!device_is_ready(vout_enable.port)) {
            printk("VOUT GPIO enable not ready\n");
            return GPIO_ERROR;
        } else {
            if( gpio_pin_configure_dt(&vout_enable, GPIO_OUTPUT_ACTIVE) < 0 ) {
                printk("VOUT GPIO enable cannot be activated\n");
                return GPIO_ERROR;
            }
        }
    	return 0;
    }
    
    message_error_t lm5176_vout_set_enable_no_init( bool on )
    {
        if ( on ) {
            printk("Enabling Vout\n");
        }
        else {
            printk("Disabling Vout\n");
        }
        // GPIO logic is reversed from pin function
        if( gpio_pin_set_dt(&vout_enable, on ? 0 : 1 ) < 0 ) {
            printk("Unable to set Vout enable");
            return GPIO_ERROR;
        }
        return MESSAGE_OK;
    }
    
    message_error_t lm5176_vout_set_enable_with_init( bool on )
    {
        if (!device_is_ready(vout_enable.port)) {
            printk("VOUT GPIO enable not ready\n");
            return GPIO_ERROR;
        } else {
            if( gpio_pin_configure_dt(&vout_enable, GPIO_OUTPUT_ACTIVE) < 0 ) {
                printk("VOUT GPIO enable cannot be activated\n");
                return GPIO_ERROR;
            }
        }
        if ( on ) {
            printk("Enabling Vout\n");
        }
        else {
            printk("Disabling Vout\n");
        }
        // GPIO logic is reversed from pin function
        if( gpio_pin_set_dt(&vout_enable, on ? 0 : 1 ) < 0 ) {
            printk("Unable to set Vout enable");
            return GPIO_ERROR;
        }
        return MESSAGE_OK;
    }
    
    #define lm5176_vout_set_enable lm5176_vout_set_enable_with_init
    
    int main(void)
    {
    	printk("Hello World! %s\n", CONFIG_BOARD);
    	init();
    	while(1)
    	{
    		lm5176_vout_set_enable(true);
    		k_sleep(K_SECONDS(1));
    		lm5176_vout_set_enable(false);
    		k_sleep(K_SECONDS(1));
    	}
    	return 0;
    }
    

    Could you please review your setup, including the hardware, to see if you missed anything?

    Hieu

Reply
  • Hi Bret,

    I found two issues in your code, but neither of which should lead to the result you observe.

    1. In your overlay, you are deleting node led2, but deleting the alias for led1.
      1. This should lead to a build failure, not a run time issue.
    2. In your function, you are configuring the pin again every time you want to set it.
      1. This is unnecessary but should not impact the behavior. I checked.

    Other than that, I tried your code, and it just works for me.

    I use the nRF52840 DK, so I changed the pin number to 14. Otherwise, it's pretty much exactly your code. I deleted node led1 in my test. I am not sure which board you are using. But if you use nrf52dk_nrf52832 and want to use P0.19. If so, you will need to delete node led2

    overlay:

     /delete-node/ &led1; // GPIO 14 repurposed to be vout enable
     /{
    	lm5176_control {
    		compatible = "gpio-leds";
    		enable1: enable_1 {
    			gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
    			label = "VOUT Enable Low";
    		};
    	};
    	aliases {
    		cmvoutenable = &enable1;
    		/delete-property/ led1; // This was GPIO 14
    	};
     };

    main.c modified from hello_world:

    /*
     * Copyright (c) 2012-2014 Wind River Systems, Inc.
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr/kernel.h>
    #include <zephyr/drivers/gpio.h>
    
    #define VOUT_ENABLE DT_ALIAS(cmvoutenable)
    static const struct gpio_dt_spec vout_enable = GPIO_DT_SPEC_GET(VOUT_ENABLE, gpios);
    
    typedef uint32_t message_error_t;
    #define GPIO_ERROR 1
    #define MESSAGE_OK 0
    
    uint32_t init(void)
    {
        if (!device_is_ready(vout_enable.port)) {
            printk("VOUT GPIO enable not ready\n");
            return GPIO_ERROR;
        } else {
            if( gpio_pin_configure_dt(&vout_enable, GPIO_OUTPUT_ACTIVE) < 0 ) {
                printk("VOUT GPIO enable cannot be activated\n");
                return GPIO_ERROR;
            }
        }
    	return 0;
    }
    
    message_error_t lm5176_vout_set_enable_no_init( bool on )
    {
        if ( on ) {
            printk("Enabling Vout\n");
        }
        else {
            printk("Disabling Vout\n");
        }
        // GPIO logic is reversed from pin function
        if( gpio_pin_set_dt(&vout_enable, on ? 0 : 1 ) < 0 ) {
            printk("Unable to set Vout enable");
            return GPIO_ERROR;
        }
        return MESSAGE_OK;
    }
    
    message_error_t lm5176_vout_set_enable_with_init( bool on )
    {
        if (!device_is_ready(vout_enable.port)) {
            printk("VOUT GPIO enable not ready\n");
            return GPIO_ERROR;
        } else {
            if( gpio_pin_configure_dt(&vout_enable, GPIO_OUTPUT_ACTIVE) < 0 ) {
                printk("VOUT GPIO enable cannot be activated\n");
                return GPIO_ERROR;
            }
        }
        if ( on ) {
            printk("Enabling Vout\n");
        }
        else {
            printk("Disabling Vout\n");
        }
        // GPIO logic is reversed from pin function
        if( gpio_pin_set_dt(&vout_enable, on ? 0 : 1 ) < 0 ) {
            printk("Unable to set Vout enable");
            return GPIO_ERROR;
        }
        return MESSAGE_OK;
    }
    
    #define lm5176_vout_set_enable lm5176_vout_set_enable_with_init
    
    int main(void)
    {
    	printk("Hello World! %s\n", CONFIG_BOARD);
    	init();
    	while(1)
    	{
    		lm5176_vout_set_enable(true);
    		k_sleep(K_SECONDS(1));
    		lm5176_vout_set_enable(false);
    		k_sleep(K_SECONDS(1));
    	}
    	return 0;
    }
    

    Could you please review your setup, including the hardware, to see if you missed anything?

    Hieu

Children
No Data
Related