GPIO example works
This commit is contained in:
parent
622c0573f7
commit
cd7a6499d4
@ -3,7 +3,7 @@
|
||||
#![no_std]
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use embedded_hal::digital::{OutputPin, StatefulOutputPin};
|
||||
use embedded_hal::digital::StatefulOutputPin;
|
||||
use panic_halt as _;
|
||||
use va416xx_hal::{gpio::PinsG, pac};
|
||||
|
||||
@ -11,17 +11,11 @@ use va416xx_hal::{gpio::PinsG, pac};
|
||||
fn main() -> ! {
|
||||
// SAFETY: Peripherals are only stolen once here.
|
||||
let mut dp = unsafe { pac::Peripherals::steal() };
|
||||
// Enable all peripheral clocks
|
||||
dp.sysconfig
|
||||
.peripheral_clk_enable()
|
||||
.modify(|_, w| unsafe { w.bits(0xffffffff) });
|
||||
let portg = PinsG::new(&mut dp.sysconfig, Some(dp.ioconfig), dp.portg);
|
||||
let mut led = portg.pg5.into_readable_push_pull_output();
|
||||
//let mut delay = CountDownTimer::new(&mut dp.SYSCONFIG, 50.mhz(), dp.TIM0);
|
||||
loop {
|
||||
led.set_high().ok();
|
||||
cortex_m::asm::delay(2_000_000);
|
||||
led.set_low().ok();
|
||||
cortex_m::asm::delay(2_000_000);
|
||||
led.toggle().ok();
|
||||
}
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ impl DynRegisters {
|
||||
/// operations are fallible. This `enum` represents the corresponding errors.
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct InvalidPinTypeError(pub (crate) ());
|
||||
pub struct InvalidPinTypeError(pub(crate) ());
|
||||
|
||||
impl embedded_hal::digital::Error for InvalidPinTypeError {
|
||||
fn kind(&self) -> embedded_hal::digital::ErrorKind {
|
||||
@ -268,32 +268,40 @@ impl DynPin {
|
||||
self.regs.delay(delay_1, delay_2);
|
||||
Ok(self)
|
||||
}
|
||||
_ => Err(InvalidPinTypeError(()))
|
||||
_ => Err(InvalidPinTypeError(())),
|
||||
}
|
||||
}
|
||||
|
||||
/// See p.52 of the programmers guide for more information.
|
||||
/// When configured for pulse mode, a given pin will set the non-default state for exactly
|
||||
/// one clock cycle before returning to the configured default state
|
||||
pub fn pulse_mode(self, enable: bool, default_state: PinState) -> Result<Self, InvalidPinTypeError> {
|
||||
pub fn pulse_mode(
|
||||
self,
|
||||
enable: bool,
|
||||
default_state: PinState,
|
||||
) -> Result<Self, InvalidPinTypeError> {
|
||||
match self.mode {
|
||||
DynPinMode::Output(_) => {
|
||||
self.regs.pulse_mode(enable, default_state);
|
||||
Ok(self)
|
||||
}
|
||||
_ => Err(InvalidPinTypeError(()))
|
||||
_ => Err(InvalidPinTypeError(())),
|
||||
}
|
||||
}
|
||||
|
||||
/// See p.37 and p.38 of the programmers guide for more information.
|
||||
#[inline]
|
||||
pub fn filter_type(self, filter: FilterType, clksel: FilterClkSel) -> Result<Self, InvalidPinTypeError> {
|
||||
pub fn filter_type(
|
||||
self,
|
||||
filter: FilterType,
|
||||
clksel: FilterClkSel,
|
||||
) -> Result<Self, InvalidPinTypeError> {
|
||||
match self.mode {
|
||||
DynPinMode::Input(_) => {
|
||||
self.regs.filter_type(filter, clksel);
|
||||
Ok(self)
|
||||
}
|
||||
_ => Err(InvalidPinTypeError(()))
|
||||
_ => Err(InvalidPinTypeError(())),
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,18 +312,21 @@ impl DynPin {
|
||||
self.irq_enb();
|
||||
Ok(self)
|
||||
}
|
||||
_ => Err(InvalidPinTypeError(()))
|
||||
_ => Err(InvalidPinTypeError(())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn interrupt_level(mut self, level_type: InterruptLevel) -> Result<Self, InvalidPinTypeError> {
|
||||
pub fn interrupt_level(
|
||||
mut self,
|
||||
level_type: InterruptLevel,
|
||||
) -> Result<Self, InvalidPinTypeError> {
|
||||
match self.mode {
|
||||
DynPinMode::Input(_) | DynPinMode::Output(_) => {
|
||||
self.regs.interrupt_level(level_type);
|
||||
self.irq_enb();
|
||||
Ok(self)
|
||||
}
|
||||
_ => Err(InvalidPinTypeError(()))
|
||||
_ => Err(InvalidPinTypeError(())),
|
||||
}
|
||||
}
|
||||
|
||||
@ -325,7 +336,7 @@ impl DynPin {
|
||||
DynPinMode::Input(_) | DYN_RD_OPEN_DRAIN_OUTPUT | DYN_RD_PUSH_PULL_OUTPUT => {
|
||||
Ok(self.regs.read_pin())
|
||||
}
|
||||
_ => Err(InvalidPinTypeError(()))
|
||||
_ => Err(InvalidPinTypeError(())),
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
@ -335,7 +346,7 @@ impl DynPin {
|
||||
self.regs.write_pin(bit);
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(InvalidPinTypeError(()))
|
||||
_ => Err(InvalidPinTypeError(())),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,6 +97,8 @@ pub trait OutputConfig: Sealed {
|
||||
const DYN: DynOutput;
|
||||
}
|
||||
|
||||
pub trait ReadableOutput: Sealed {}
|
||||
|
||||
/// Type-level variant of [`OutputConfig`] for a push-pull configuration
|
||||
pub enum PushPull {}
|
||||
/// Type-level variant of [`OutputConfig`] for an open drain configuration
|
||||
@ -111,6 +113,8 @@ impl Sealed for PushPull {}
|
||||
impl Sealed for OpenDrain {}
|
||||
impl Sealed for ReadableOpenDrain {}
|
||||
impl Sealed for ReadablePushPull {}
|
||||
impl ReadableOutput for ReadableOpenDrain {}
|
||||
impl ReadableOutput for ReadablePushPull {}
|
||||
|
||||
impl OutputConfig for PushPull {
|
||||
const DYN: DynOutput = DynOutput::PushPull;
|
||||
@ -538,7 +542,7 @@ where
|
||||
impl<I, C> StatefulOutputPin for Pin<I, Output<C>>
|
||||
where
|
||||
I: PinId,
|
||||
C: OutputConfig,
|
||||
C: OutputConfig + ReadableOutput,
|
||||
{
|
||||
#[inline]
|
||||
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
|
||||
|
@ -76,11 +76,7 @@ impl From<DynPinMode> for ModeFields {
|
||||
// RegisterInterface
|
||||
//==============================================================================
|
||||
|
||||
pub type IocfgPort = ioconfig::Porta;
|
||||
#[repr(C)]
|
||||
pub(super) struct IocfgConfigGroupDefault {
|
||||
port: [IocfgPort; 16],
|
||||
}
|
||||
pub type PortReg = ioconfig::Porta;
|
||||
|
||||
/// Provide a safe register interface for pin objects
|
||||
///
|
||||
@ -124,7 +120,6 @@ pub(super) unsafe trait RegisterInterface {
|
||||
const PORTE: *const PortRegisterBlock = Porte::ptr();
|
||||
const PORTF: *const PortRegisterBlock = Portf::ptr();
|
||||
const PORTG: *const PortRegisterBlock = Portg::ptr();
|
||||
const PORT_CFG_BASE: *const IocfgConfigGroupDefault = Ioconfig::ptr() as *const _;
|
||||
|
||||
/// Change the pin mode
|
||||
#[inline]
|
||||
@ -138,7 +133,7 @@ pub(super) unsafe trait RegisterInterface {
|
||||
enb_input,
|
||||
} = mode.into();
|
||||
let (portreg, iocfg) = (self.port_reg(), self.iocfg_port());
|
||||
iocfg.port[self.id().num as usize].write(|w| {
|
||||
iocfg.write(|w| {
|
||||
w.opendrn().bit(opendrn);
|
||||
w.pen().bit(pull_en);
|
||||
w.plevel().bit(pull_dir);
|
||||
@ -170,15 +165,16 @@ pub(super) unsafe trait RegisterInterface {
|
||||
}
|
||||
}
|
||||
|
||||
fn iocfg_port(&self) -> &IocfgConfigGroupDefault {
|
||||
fn iocfg_port(&self) -> &PortReg {
|
||||
let ioconfig = unsafe { Ioconfig::ptr().as_ref().unwrap() };
|
||||
match self.id().group {
|
||||
DynGroup::A => unsafe { &*Self::PORT_CFG_BASE },
|
||||
DynGroup::B => unsafe { &*Self::PORT_CFG_BASE.add(1) },
|
||||
DynGroup::C => unsafe { &*Self::PORT_CFG_BASE.add(3) },
|
||||
DynGroup::D => unsafe { &*Self::PORT_CFG_BASE.add(4) },
|
||||
DynGroup::E => unsafe { &*Self::PORT_CFG_BASE.add(5) },
|
||||
DynGroup::F => unsafe { &*Self::PORT_CFG_BASE.add(6) },
|
||||
DynGroup::G => unsafe { &*Self::PORT_CFG_BASE.add(7) },
|
||||
DynGroup::A => ioconfig.porta(self.id().num as usize),
|
||||
DynGroup::B => ioconfig.portb0(self.id().num as usize),
|
||||
DynGroup::C => ioconfig.portc0(self.id().num as usize),
|
||||
DynGroup::D => ioconfig.portd0(self.id().num as usize),
|
||||
DynGroup::E => ioconfig.porte0(self.id().num as usize),
|
||||
DynGroup::F => ioconfig.portf0(self.id().num as usize),
|
||||
DynGroup::G => ioconfig.portg0(self.id().num as usize),
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,7 +299,7 @@ pub(super) unsafe trait RegisterInterface {
|
||||
/// Only useful for input pins
|
||||
#[inline]
|
||||
fn filter_type(&self, filter: FilterType, clksel: FilterClkSel) {
|
||||
self.iocfg_port().port[self.id().num as usize].modify(|_, w| {
|
||||
self.iocfg_port().modify(|_, w| {
|
||||
// Safety: Only write to register for this Pin ID
|
||||
unsafe {
|
||||
w.flttype().bits(filter as u8);
|
||||
|
@ -5,8 +5,8 @@ pub use va416xx as pac;
|
||||
pub mod prelude;
|
||||
|
||||
pub mod clock;
|
||||
pub mod time;
|
||||
pub mod gpio;
|
||||
pub mod time;
|
||||
pub mod typelevel;
|
||||
|
||||
#[derive(Debug, Eq, Copy, Clone, PartialEq)]
|
||||
|
@ -0,0 +1 @@
|
||||
|
@ -1,3 +1,6 @@
|
||||
// Manually inserted.
|
||||
#![allow(clippy::identity_op)]
|
||||
|
||||
#[repr(C)]
|
||||
#[doc = "Register block"]
|
||||
pub struct RegisterBlock {
|
||||
|
@ -3,12 +3,9 @@
|
||||
#![no_std]
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use embedded_hal::digital::v2::{OutputPin, ToggleableOutputPin};
|
||||
use panic_halt as _;
|
||||
use va416xx_hal::{
|
||||
pac,
|
||||
gpio::PinsG
|
||||
};
|
||||
use embedded_hal::digital::v2::{ToggleableOutputPin, OutputPin};
|
||||
use va416xx_hal::{gpio::PinsG, pac};
|
||||
|
||||
// Mask for the LED
|
||||
const LED_PG5: u32 = 1 << 5;
|
||||
@ -54,7 +51,7 @@ fn main() -> ! {
|
||||
led.set_low().ok();
|
||||
cortex_m::asm::delay(5_000_000);
|
||||
led.set_high().ok();
|
||||
};
|
||||
}
|
||||
loop {
|
||||
led.toggle().ok();
|
||||
cortex_m::asm::delay(25_000_000);
|
||||
|
Loading…
Reference in New Issue
Block a user