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

Rethink how we accomplish pin muxing #46

Closed
mciantyre opened this issue Feb 5, 2020 · 0 comments
Closed

Rethink how we accomplish pin muxing #46

mciantyre opened this issue Feb 5, 2020 · 0 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@mciantyre
Copy link
Owner

If you want to configure peripherals that require processor pads, you need to set the pad into the correct 'alternative,' or mode. Pads have multiple alternatives, depending on their usage. (This is also called pin muxing.) The current approach puts the responsibility on users to know what alternative is necessary for a given peripheral. Although this could be identified from the method signatures, it's more overhead, and the user's code isn't as clean. We should be able to simplify this API.

Consider the initialization of a UART peripheral, using Teensy pins 14 and 15. The snippet below describes how it happens today.

let mut uart = uarts
        .uart2
        .init(
            peripherals.pins.p14.alt2(),
            peripherals.pins.p15.alt2(),
            BAUD,
        )
        .unwrap();

See those calls to alt2()? Those set the pins into the correct alternative for UART. They're required because the signature if init() looks like

pub fn init<TX, RX>(
        self,
        mut tx: TX,
        mut rx: RX,
        baud: u32,
    ) -> Result<UART<M>, ccm::uart::TimingsError>
    where
        TX: uart::Pin<Direction = uart::TX, Module = M>,
        RX: uart::Pin<Direction = uart::RX, Module = M>,

and the uart::Pin implementations resemble

impl uart::Pin for GPIO_AD_B1_02<Alt2> {
  type Direction = uart::TX;
  type Module = uart::module::_2;
}

impl uart::Pin for GPIO_AD_B1_03<Alt2> {
  type Direction = uart::RX;
  type Module = uart::module::_2;
}

If we follow that through, we see that GPIO_AD_B1_02 can only be the TX pin for UART 2 when it's in the second alternative. Same applies for GPIO_AD_B1_03 as an RX pin. The only way to get a pad in that state is to call alt2().

I want to remove the requirement for users to set the alternative. Remove the calls to alt2() so that the snippet simplifies to

let mut uart = uarts
        .uart2
        .init(
            peripherals.pins.p14, // no more alt2() call
            peripherals.pins.p15, // no more alt2() call
            BAUD,
        )
        .unwrap();

A solution should not sacrifice compile-time checking for a convenient API. You cannot provide the wrong pin to the UART module; if you tried to pass in p13, rather than p14, for the TX pin, it fails to compile. You also cannot put the pin into the wrong alternative; a call of alt3(), rather than alt2(), fails to compile. We should keep these kinds of guarantees in a new approach.

This will probably require changes throughout the HAL, including in the IOMUXC modules, and all peripheral modules that depend on processor pins.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

1 participant