zephyrproject-rtos / zephyr

Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
https://docs.zephyrproject.org
Apache License 2.0
10.5k stars 6.43k forks source link

GPIO Hogs enhancements #55617

Open keith-zephyr opened 1 year ago

keith-zephyr commented 1 year ago

GPIO Hogs Enhancements

Add features to the GPIO hogs implementation:

Application controlled configuration

A new Kconfig option, GPIO_HOGS_INITIALIZE_BY_APPLICATION, instructs the GPIO hogs driver to bypass GPIO configuration automatically at initialization. Instead the application code must call gpio_hogs_configure() manually, passing in a mask of GPIO flags to configure. The code snipped below demonstrates how the an application code can make a run-time decision affecting the GPIO hog configuration.

#define GPIO_SOFTWARE_JUMP_FLAGS \
    (GPIO_FLAGS_ALL & ~(GPIO_OUTPUT_INIT_LOW | GPIO_OUTPUT_INIT_HIGH | GPIO_OUTPUT_INIT_LOGICIAL))

void main(void)
{
    if (software_jump_detected) {
        /* During software jumps, don't update the output state of any pins*/
        gpio_hogs_configure(NULL, GPIO_SOFTWARE_JUMP_FLAGS);
    } else {
        gpio_hogs_configure(NULL, GPIO_FLAGS_ALL);
    }
} 

The gpio_hogs_configure() routine takes 2 parameters, allowing the application to filter on the GPIO controller port.

/* @param port Specifies the specific GPIO port to apply the GPIO hog
 *             configuration. If NULL, than all GPIO hogs are updated.
 * @param mask Specifies the mask of GPIO flags to apply during the GPIO hog
 *             configuration. Set to GPIO_FLAGS_ALL to apply all flags set
 *             by the devicetree configuration.
 */
int gpio_hogs_configure(const struct device *port, gpio_flags_t mask);

GPIO hogs shell

The current gpio shell commands are difficult to use, as the user must know the GPIO controller nodename and the pin number associated with the signal on the board. The current gpio shell command provides no tab completion, and will accept any valid nodename, regardless of whether it points to a GPIO controller.

The GPIO hogs driver provides the line-name a property, but this property is currently unused.

For this proposal, the line-name property is changed to lines-names as each GPIO hog can specify multiple GPIO pins.

    hog1 {
        gpio-hog;
        gpios = <1 GPIO_ACTIVE_LOW>, <4 GPIO_ACTIVE_HIGH>;
        line-names = "GPIO_EEPROM_RESET_L", "GPIO_WP_ENABLE";
        output-high;
    };

The shell commands use the line-names property as an argument for getting the state of GPIO inputs or setting the state of GPIO outputs.

An application can make a GPIO pin available to the GPIO shell commands, without the GPIO hogs driver configuring the pin, by omitting input, output-low, and output-high properties.

Benefits over the existing "gpio" shell command:

Implementation

A draft PR demonstrating the application driven initialization and a GPIO hogs shell command is on PR https://github.com/zephyrproject-rtos/zephyr/pull/54845.

keith-zephyr commented 1 year ago

@ElectricalPaul - The shell support proposed here could be used by your project.

ElectricalPaul commented 1 year ago

@ElectricalPaul - The shell support proposed here could be used by your project.

That would definitely help in the migration, thanks for opening the issue!

henrikbrixandersen commented 1 year ago

As mentioned in https://github.com/zephyrproject-rtos/zephyr/pull/54845#issuecomment-1433749509, I find this approach way too application specific to be included in upstream Zephyr.

Applications can already control GPIOs. GPIO hogs are not intended to be exposed to the application nor by the shell; they are simply a way of doing GPIO initialization at boot time.

The whole issue of "delayed" or "application-driven" driver initialization is not specific to the GPIO hogs "driver" and we should not add custom ways of working around it per driver/per driver class. A robust, generic solution needs to be found.

Furthermore, the change of exposing the GPIO hogs initialization function as a public API conflicts with my plans for addressing some of the concerns on the original GPIO hogs PR (#54110). To overcome these issues, each GPIO controller driver instance will handle its own GPIO hogs during driver initialization and thus there will be not only one configuration function. This initialization can still happen in generic GPIO controller driver code to avoid code duplication between drivers, but with one call per instance.

The proposed change to the binding (renaming the line-name property) break compatibility with the upstream binding, which was an explicit design goal of introducing GPIO hogs.

CC: @galak, @mbolivar, @cfriedt

jfischer-no commented 1 year ago

The whole issue of "delayed" or "application-driven" driver initialization is not specific to the GPIO hogs "driver" and we should not add custom ways of working around it per driver/per driver class. A robust, generic solution needs to be found.

btw, "The /zephyr,user node is a convenient place to store application-specific GPIOs that you want to be able to reconfigure with a devicetree overlay."

keith-zephyr commented 1 year ago

As mentioned in #54845 (comment), I find this approach way too application specific to be included in upstream Zephyr.

Applications can already control GPIOs. GPIO hogs are not intended to be exposed to the application nor by the shell; they are simply a way of doing GPIO initialization at boot time.

The whole issue of "delayed" or "application-driven" driver initialization is not specific to the GPIO hogs "driver" and we should not add custom ways of working around it per driver/per driver class. A robust, generic solution needs to be found.

Furthermore, the change of exposing the GPIO hogs initialization function as a public API conflicts with my plans for addressing some of the concerns on the original GPIO hogs PR (#54110). To overcome these issues, each GPIO controller driver instance will handle its own GPIO hogs during driver initialization and thus there will be not only one configuration function. This initialization can still happen in generic GPIO controller driver code to avoid code duplication between drivers, but with one call per instance.

The proposed change to the binding (renaming the line-name property) break compatibility with the upstream binding, which was an explicit design goal of introducing GPIO hogs.

CC: @galak, @mbolivar, @cfriedt

@henrikbrixandersen do you have a draft PR that can share that demonstrates your future work for the GPIO hogs?

The current GPIO shell command I find basically unusable in it's current form. Even if a user knows their desired GPIO signal is on port "GPIOA", pin 3, the user has no way to associate "GPIOA" with the GPIO controller name derived from the devicetree node name gpio@40095000. The gpio-line-names property could potentially solve this, but a user would have to assign names to all GPIO pins on a given controller, and there isn't a mechanism to allow-list just specific GPIOs.

I proposed adding a shell command to GPIO hogs because it's devicetree representation already has everything one needs: the GPIO controller, the pin, and a friendly name for the pin (derived from either the node name or the line-name). I want to avoid adding another devicetree entry to get a better shell.

henrikbrixandersen commented 1 year ago

@henrikbrixandersen do you have a draft PR that can share that demonstrates your future work for the GPIO hogs?

Not yet.