Skip to content

Conversation

benpicco
Copy link
Contributor

Contribution description

Provide a way to init a GPIO as output with a set level.
Some platforms can to this on init already and will always just set
the GPIO to LOW which can be undesireable.

For all other platforms, provide a fall-back implementation.

The functions are also convenient when de-initializing a previously
otherwise configured Pin, e.g. when disconnecting the power on an external
sensor through a transistor and wanting to avoid current leaking through a
high idle UART TX line.

Testing procedure

The code is trivial, but you can check check that a pin is really HIGH after calling gpio_init_high(GPIO_PIN(0,1));

Issues/PRs references

Provides a clean solution for #12380

@benpicco benpicco added Type: new feature The issue requests / The PR implemements a new feature for RIOT Area: drivers Area: Device drivers CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Oct 30, 2019
@kaspar030
Copy link
Contributor

Some platforms can to this on init already and will always just set
the GPIO to LOW which can be undesireable.

That's probably a bug in that implementation. gpio_init() should not touch the currently configured level.

@basilfx
Copy link
Member

basilfx commented Nov 4, 2019

I created a feature branch where I changed the behaviour for EFM32 w.r.t. this issue. If that works in #12380 then it should fix this issue for EFM32.

@stale
Copy link

stale bot commented May 7, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you want me to ignore this issue, please mark it with the "State: don't stale" label. Thank you for your contributions.

@stale stale bot added the State: stale State: The issue / PR has no activity for >185 days label May 7, 2020
@basilfx basilfx added State: don't stale State: Tell state-bot to ignore this issue and removed State: stale State: The issue / PR has no activity for >185 days labels May 7, 2020
@benpicco benpicco requested a review from MrKevinWeiss as a code owner May 8, 2020 22:13
@benpicco benpicco removed the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label May 8, 2020
@benpicco benpicco requested a review from roberthartung May 8, 2020 22:17
@benpicco
Copy link
Contributor Author

benpicco commented May 9, 2020

@basilfx want to give this a review?

@basilfx basilfx added Reviewed: 2-code-design The code design of the PR was reviewed according to the maintainer guidelines Reviewed: 3-testing The PR was tested according to the maintainer guidelines Reviewed: 4-code-style The adherence to coding conventions by the PR were reviewed according to the maintainer guidelines labels Jun 16, 2020
@basilfx
Copy link
Member

basilfx commented Jun 16, 2020

@benpicco I gave this PR a review and I approve it partially.

Since this extends the GPIO API, I don' feel comfortable to ACK for that part. The change does make sense, and it is only a helper function that doesn't affect the rest.

Also, I think it needs at least a test that hits these two new functions.

@basilfx
Copy link
Member

basilfx commented Jun 16, 2020

@benpicco I think I got you covered for a test case: basilfx@173c05f.

Feel free to cherry-pick that one.

@benpicco benpicco added CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR and removed State: don't stale State: Tell state-bot to ignore this issue labels Jun 16, 2020
@benemorius
Copy link
Member

benemorius commented Jun 17, 2020

I feel strongly that the API should include a way to set the driven level of a GPIO in the same call as setting the mode to output, so I'm in favor of this PR.

Only the GPIO peripheral driver knows how to deterministically configure a pin as an output without unintentional momentary assertions of the wrong level. Consumers of the driver do not have a guaranteed way to do that with the current API. Most of them accomplish it by calling gpio_write() prior to ever calling gpio_init() which is an undocumented feature common to most platforms except notably efm32 as referenced in OP.

In fact I even feel that the API shouldn't include a way to set the mode to output without also defining the driven level in the same call, but of course that's outside the scope of this PR.

At a glance, the only thought I had about the specifics of the API is that perhaps it's preferable to have high/low passed as a parameter rather than having two separate functions to call. Then again, perhaps it isn't. Maybe both. Both would be consistent with the fact that we have both gpio_write() and gpio_set()/gpio_clear().

@kaspar030
Copy link
Contributor

I agree that from an API point of view this would be most consistent. However, we would have to touch a few GPIO implementations for that.

Is it that bad?

@kaspar030
Copy link
Contributor

Most of them accomplish it by calling gpio_write() prior to ever calling gpio_init() which is an undocumented feature common to most platforms except notably efm32 as referenced in OP.

This actually goes against documentation, periph "handles" are only allowed to be used after they have been init()ed correctly. That's our shortcut to not have to check the validity of e.g., a gpio_t parameter, on every set or clear.

basilfx and others added 2 commits August 11, 2020 16:16
@fjmolinas
Copy link
Contributor

This actually goes against documentation, periph "handles" are only allowed to be used after they have been init()ed correctly. That's our shortcut to not have to check the validity of e.g., a gpio_t parameter, on every set or clear.

@kaspar030 should we add the contested tag to this one then?

@kaspar030
Copy link
Contributor

@kaspar030 should we add the contested tag to this one then?

no, that was just for the workaround mentioned (first gpio_set(), then gpio_init()`).

I'm not happy with adding and calling these gpio_init_low/high(), as this is for configuring output. That's somewhat confusing, IMO. We'd uglify the API so we don't have to touch the implementations.

Would an alternative be wrapping the actual implementations?
Like, renaming the actual per-cpu gpio_init() to gpio_init_sth(), and then using this PR's gpio_init_high/low as a wrapper, but changed to use additional enum values?

@benemorius
Copy link
Member

I'm not happy with adding and calling these gpio_init_low/high(), as this is for configuring output. That's somewhat confusing, IMO.

I'm trying but I'm struggling to understand which aspect you object to. Are you saying you'd be happier with gpio_init(..., GPIO_OUT_HIGH)?

As a hardware designer I object to an API that permits telling the hardware to become an output without simultaneously telling it which level to output. It's the very definition of undefined behavior.

Perhaps we would be better off with separate functions to init GPIOs as input versus output? After all from a hardware perspective it is fundamentally different. Inputs need pull resistors specified whereas outputs need the driven level specified.

@kaspar030
Copy link
Contributor

I'm trying but I'm struggling to understand which aspect you object to. Are you saying you'd be happier with gpio_init(..., GPIO_OUT_HIGH)?

yes, I mean only from an API perspective.

As a hardware designer I object to an API that permits telling the hardware to become an output without simultaneously telling it which level to output. It's the very definition of undefined behavior.

👍

GPIO_OUT could be an alias for GPIO_OUT_LOW. That shouldn't be too hard to fix / confirm in the existing implementations?

@benpicco benpicco added State: waiting for CI update State: The PR requires an Update to CI to be performed first CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR and removed State: waiting for CI update State: The PR requires an Update to CI to be performed first CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Sep 10, 2020
@stale
Copy link

stale bot commented Mar 19, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you want me to ignore this issue, please mark it with the "State: don't stale" label. Thank you for your contributions.

@stale stale bot added the State: stale State: The issue / PR has no activity for >185 days label Mar 19, 2021
@maribu
Copy link
Member

maribu commented Mar 20, 2021

What was missing here to get this in?

@stale stale bot removed the State: stale State: The issue / PR has no activity for >185 days label Mar 20, 2021
@MrKevinWeiss MrKevinWeiss added this to the Release 2021.07 milestone Jun 22, 2021
@MrKevinWeiss MrKevinWeiss removed this from the Release 2021.07 milestone Jul 15, 2021
@fjmolinas
Copy link
Contributor

ping @maribu @benpicco @kaspar030

@kaspar030
Copy link
Contributor

What was missing here to get this in?

I was objecting the API clutter:

  • gpio_init(..., mode) initializing input, output not touching state
  • `gpio_init_low(...) initializing output, setting to low
  • `gpio_init_high(...) initializing output, setting to high

vs.

  • gpio_init(..., mode) initializing input, output not touching state
  • gpio_init(..., GPIO_OUT) initializing input, output not touching state
  • `gpio_init(...., GPIO_OUT_LOW) initializing output, setting to low
  • `gpio_init(..., GPIO_OUT_HIGH) initializing output, setting to high

gpio_init_low() kinda implies the initializiation of an output, but just kinda.

gpio_init_out_low() and gpio_init_out_high() would be a weird compromise, but why no gpio_init_in/out/in_pd/out_pd/...()?
Either the API is using a mode parameter, or distinct functions. Both are just inconsistend.
And I'd object changing towards non-overloaded init(). Too much change for too little benefit.

@maribu
Copy link
Member

maribu commented Nov 18, 2021

Note that gpio_ll would also scratch this itch and others ;-)

@benpicco benpicco added State: don't stale State: Tell state-bot to ignore this issue State: stale State: The issue / PR has no activity for >185 days and removed State: don't stale State: Tell state-bot to ignore this issue labels Nov 29, 2021
@stale stale bot removed the State: stale State: The issue / PR has no activity for >185 days label Nov 29, 2021
@stale
Copy link

stale bot commented Jun 12, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you want me to ignore this issue, please mark it with the "State: don't stale" label. Thank you for your contributions.

@stale stale bot added the State: stale State: The issue / PR has no activity for >185 days label Jun 12, 2022
@stale stale bot closed this Aug 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: drivers Area: Device drivers CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Reviewed: 2-code-design The code design of the PR was reviewed according to the maintainer guidelines Reviewed: 3-testing The PR was tested according to the maintainer guidelines Reviewed: 4-code-style The adherence to coding conventions by the PR were reviewed according to the maintainer guidelines State: stale State: The issue / PR has no activity for >185 days Type: new feature The issue requests / The PR implemements a new feature for RIOT
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants