98 lines
2.8 KiB
Rust
98 lines
2.8 KiB
Rust
//! GPIO module.
|
|
|
|
use super::memory_map::gpio::*;
|
|
|
|
/// The number of pin for the raspberry 3.
|
|
const NUMBER_PIN: usize = 54;
|
|
|
|
/// Value to select the INPUT function of a PIN.
|
|
const FSEL_INPUT: u32 = 0b000;
|
|
/// Value to select the OUTPUT function of a PIN.
|
|
const FSEL_OUTPUT: u32 = 0b001;
|
|
/// Value to select the Alternate function 0 of a PIN.
|
|
const FSEL_ALTF0: u32 = 0b100;
|
|
/// Value to select the Alternate function 1 of a PIN.
|
|
const FSEL_ALTF1: u32 = 0b101;
|
|
/// Value to select the Alternate function 2 of a PIN.
|
|
const FSEL_ALTF2: u32 = 0b110;
|
|
/// Value to select the Alternate function 3 of a PIN.
|
|
const FSEL_ALTF3: u32 = 0b111;
|
|
/// Value to select the Alternate function 4 of a PIN.
|
|
const FSEL_ALTF4: u32 = 0b011;
|
|
/// Value to select the Alternate function 5 of a PIN.
|
|
const FSEL_ALTF5: u32 = 0b010;
|
|
|
|
/// The possible PIN functions.
|
|
pub enum PinFunction {
|
|
Input,
|
|
Output,
|
|
AltFunc0,
|
|
AltFunc1,
|
|
AltFunc2,
|
|
AltFunc3,
|
|
AltFunc4,
|
|
AltFunc5,
|
|
}
|
|
|
|
/// The possible PIN state when in Output mode.
|
|
pub enum PinOutputState {
|
|
High,
|
|
Low,
|
|
}
|
|
|
|
impl From<PinFunction> for u32 {
|
|
fn from(function: PinFunction) -> u32 {
|
|
match function {
|
|
PinFunction::Input => FSEL_INPUT,
|
|
PinFunction::Output => FSEL_OUTPUT,
|
|
PinFunction::AltFunc0 => FSEL_ALTF0,
|
|
PinFunction::AltFunc1 => FSEL_ALTF1,
|
|
PinFunction::AltFunc2 => FSEL_ALTF2,
|
|
PinFunction::AltFunc3 => FSEL_ALTF3,
|
|
PinFunction::AltFunc4 => FSEL_ALTF4,
|
|
PinFunction::AltFunc5 => FSEL_ALTF5,
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO: remove Result and use an enum instead of usize
|
|
/// Set the function of a Pin.
|
|
///
|
|
/// # Result
|
|
///
|
|
/// Return an error if the PIN does not exist.
|
|
pub fn set_pin_fonction(n: usize, function: PinFunction) -> Result<(), &'static str> {
|
|
if n >= NUMBER_PIN {
|
|
return Err("The pin does not exist.");
|
|
}
|
|
let field = get_fsel(n);
|
|
// TODO: SYNC
|
|
let address = field.get_address();
|
|
let mut val = unsafe { core::ptr::read_volatile(address as *mut u32) };
|
|
val &= !field.get_mask();
|
|
val |= Into::<u32>::into(function) << field.get_offset();
|
|
unsafe { core::ptr::write_volatile(address as *mut u32, val); }
|
|
Ok(())
|
|
}
|
|
|
|
// TODO: remove Result and use an enum instead of usize
|
|
/// Set the state of an output Pin.
|
|
///
|
|
/// # Result
|
|
///
|
|
/// Return an error if the PIN does not exist.
|
|
pub fn set_pin_output_state(n: usize, state: PinOutputState) -> Result<(), &'static str> {
|
|
if n >= NUMBER_PIN {
|
|
return Err("The pin does not exist.");
|
|
}
|
|
let field = match state {
|
|
PinOutputState::High => get_set(n),
|
|
PinOutputState::Low => get_clr(n),
|
|
};
|
|
let val = field.get_mask();
|
|
let address = field.get_address();
|
|
// 0 has no effect on this field: no nead to read-modify-write
|
|
unsafe { core::ptr::write_volatile(address as *mut u32, val); }
|
|
Ok(())
|
|
}
|