Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compile time GPIO pin number access. #384

Open
luqasz opened this issue Jan 3, 2022 · 1 comment
Open

Compile time GPIO pin number access. #384

luqasz opened this issue Jan 3, 2022 · 1 comment

Comments

@luqasz
Copy link

luqasz commented Jan 3, 2022

Hi.

Based on some board, I can have same pin functionality but on different pins. Board A has a FAN output on PC7, while board B on PC6 and so on. Since pin numbers are hardcoded as a struct field, how can I declare which pin to use ? E.g. a separate file which defines all pins based on some feature (feature would be a board name and revision) to use.

I'd like to avoid this situation:

    #[cfg(feature = "board_a")]
    let mut fan_pwm = gpioc.pc7.into_push_pull_output(&mut gpioc.crl);
    #[cfg(feature = "board_b")]
    let mut fan_pwm = gpioc.pc6.into_push_pull_output(&mut gpioc.crl);
    #[cfg(feature = "board_c")]
    let mut fan_pwm = gpioc.pc5.into_push_pull_output(&mut gpioc.crl);
    #[cfg(feature = "board_d")]
    let mut fan_pwm = gpioc.pc4.into_push_pull_output(&mut gpioc.crl);
    #[cfg(feature = "board_e")]
    let mut fan_pwm = gpioc.pc3.into_push_pull_output(&mut gpioc.crl);

This is simplified as it assumes all pins use GPIOC. Situation gets complicated when using different GPIO ports as well as CRH, CRL.

What I am used to (as I did some C/C++ embedded programming) and find most elegant solution:

#if defined(BOARD_A)
    using FAN_PIN = GPIO::PC7;
#elif defined(BOARD_B)
    using FAN_PIN = GPIO::PC6;
#else
    error "Board not implemented"
#endif

// Or include a hwconfig header file in which all ifdef's are.
#include "hwconfig.h"

int main() {
    fan = GPIO::PIN(FAN_PIN);
}
@burrbull
Copy link
Contributor

burrbull commented Jan 4, 2022

All safety guaranties of GPIO API are based on idea that you can have only 1 pin instance each time.

Now it provided by collecting all pins in peripheral in 1 structure gpiox::Parts. Maybe there is some other way to provide it, I don't know.

You could try to partially decrease of cfg checks by manually restructuring of Parts. Something like:

    #[cfg(feature = "board_a")]
    let gpioc::Parts { pc7: fan_pwm, pcx: other_pin, crl: c_crl, crh: c_crh, .. } = gpioc;
    #[cfg(feature = "board_b")]
    let gpioc::Parts { pc6: fan_pwm, pcy: other_pin, crl: c_crl, crh: c_crh, .. } = gpioc;

    let mut fan_pwm = fan_pwm.into_push_pull_output(&mut c_crl);

or create some macro.

Alternatively we could make

const fn new(mode: MODE) -> Self {
pub unsafe but I don't think this is good way to give user such gun.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants