GPIO example works

This commit is contained in:
Robin Müller 2024-06-12 11:29:12 +02:00
parent 622c0573f7
commit cd7a6499d4
Signed by: muellerr
GPG Key ID: A649FB78196E3849
8 changed files with 49 additions and 43 deletions

View File

@ -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();
}
}

View File

@ -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(())),
}
}

View File

@ -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> {

View File

@ -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);

View File

@ -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)]

View File

@ -0,0 +1 @@

View File

@ -1,3 +1,6 @@
// Manually inserted.
#![allow(clippy::identity_op)]
#[repr(C)]
#[doc = "Register block"]
pub struct RegisterBlock {

View File

@ -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);