nrf5x/pinmux.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.
//! An abstraction over the pin multiplexer, nRF5X-family
//!
//! Controller drivers should use the `Pinmux` type (instead of a `u32`) for
//! fields that determine which pins are used by the hardware. The board
//! configuration should create `Pinmux`s and pass them into controller drivers
//! during initialization.
use kernel::utilities::cells::VolatileCell;
// Note: only the nrf52840 has two ports, but we create two ports to avoid
// gating this code by a feature.
const NUM_PORTS: usize = 2;
const PIN_PER_PORT: usize = 32;
// Keep track of which pins has a `Pinmux` been created for.
static mut USED_PINS: [VolatileCell<u32>; NUM_PORTS] = [VolatileCell::new(0), VolatileCell::new(0)];
/// An opaque wrapper around a configurable pin.
#[derive(Copy, Clone)]
pub struct Pinmux(u32);
impl Pinmux {
/// Creates a new `Pinmux` wrapping the numbered pin.
///
/// # Panics
///
/// If a `Pinmux` for this pin has already
/// been created.
///
pub unsafe fn new(pin: u32) -> Pinmux {
let port: usize = (pin as usize) / PIN_PER_PORT;
let pin_idx: usize = (pin as usize) % PIN_PER_PORT;
let used_pins = USED_PINS[port].get();
if used_pins & (1 << pin_idx) != 0 {
panic!("Pin {} is already in use!", pin);
} else {
USED_PINS[port].set(used_pins | 1 << pin_idx);
Pinmux(pin)
}
}
}
impl From<Pinmux> for u32 {
fn from(val: Pinmux) -> Self {
val.0
}
}