mirror of
https://github.com/italicsjenga/rp-hal-boards.git
synced 2024-12-23 20:51:31 +11:00
Implements interrupts for GPIO pins.
This commit is contained in:
parent
da89888ccb
commit
dbd4c7dfea
|
@ -63,6 +63,19 @@ pub enum OutputSlewRate {
|
|||
Fast,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
||||
/// Interrupt kind
|
||||
pub enum Interrupt {
|
||||
/// While low
|
||||
LevelLow,
|
||||
/// While high
|
||||
LevelHigh,
|
||||
/// On falling edge
|
||||
EdgeLow,
|
||||
/// On rising edge
|
||||
EdgeHigh,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
||||
/// Interrupt override state.
|
||||
pub enum InterruptOverride {
|
||||
|
|
|
@ -94,8 +94,8 @@
|
|||
//! [`AnyKind`]: crate::typelevel#anykind-trait-pattern
|
||||
use super::dynpin::{DynDisabled, DynInput, DynOutput, DynPinId, DynPinMode};
|
||||
use super::{
|
||||
InputOverride, InterruptOverride, OutputDriveStrength, OutputEnableOverride, OutputOverride,
|
||||
OutputSlewRate,
|
||||
InputOverride, Interrupt, InterruptOverride, OutputDriveStrength, OutputEnableOverride,
|
||||
OutputOverride, OutputSlewRate,
|
||||
};
|
||||
use crate::gpio::reg::RegisterInterface;
|
||||
use crate::typelevel::{Is, NoneT, Sealed};
|
||||
|
@ -547,6 +547,42 @@ where
|
|||
self.regs.write_slew_rate(rate)
|
||||
}
|
||||
|
||||
/// Clear interrupt.
|
||||
#[inline]
|
||||
pub fn clear_interrupt(&mut self, interrupt: Interrupt) {
|
||||
self.regs.clear_interrupt(interrupt);
|
||||
}
|
||||
|
||||
/// Interrupt status.
|
||||
#[inline]
|
||||
pub fn interrupt_status(&self, interrupt: Interrupt) -> bool {
|
||||
self.regs.interrupt_status(interrupt)
|
||||
}
|
||||
|
||||
/// Is interrupt enabled.
|
||||
#[inline]
|
||||
pub fn is_interrupt_enabled(&self, interrupt: Interrupt) -> bool {
|
||||
self.regs.is_interrupt_enabled(interrupt)
|
||||
}
|
||||
|
||||
/// Enable or disable interrupt.
|
||||
#[inline]
|
||||
pub fn set_interrupt_enabled(&self, interrupt: Interrupt, enabled: bool) {
|
||||
self.regs.set_interrupt_enabled(interrupt, enabled);
|
||||
}
|
||||
|
||||
/// Is interrupt forced.
|
||||
#[inline]
|
||||
pub fn is_interrupt_forced(&self, interrupt: Interrupt) -> bool {
|
||||
self.regs.is_interrupt_forced(interrupt)
|
||||
}
|
||||
|
||||
/// Force or release interrupt.
|
||||
#[inline]
|
||||
pub fn set_interrupt_forced(&self, interrupt: Interrupt, forced: bool) {
|
||||
self.regs.set_interrupt_forced(interrupt, forced);
|
||||
}
|
||||
|
||||
/// Set the interrupt override.
|
||||
#[inline]
|
||||
pub fn set_interrupt_override(&mut self, override_value: InterruptOverride) {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// Based heavily on and in some places copied from `atsamd-hal` gpio::v2
|
||||
use super::dynpin::{DynGroup, DynPinId};
|
||||
use super::{
|
||||
InputOverride, InterruptOverride, OutputDriveStrength, OutputEnableOverride, OutputOverride,
|
||||
OutputSlewRate,
|
||||
InputOverride, Interrupt, InterruptOverride, OutputDriveStrength, OutputEnableOverride,
|
||||
OutputOverride, OutputSlewRate,
|
||||
};
|
||||
use crate::gpio::dynpin::{DynDisabled, DynFunction, DynInput, DynOutput, DynPinMode};
|
||||
use crate::pac;
|
||||
|
@ -255,6 +255,101 @@ pub(super) unsafe trait RegisterInterface {
|
|||
}
|
||||
}
|
||||
|
||||
/// Clear interrupt.
|
||||
#[inline]
|
||||
fn clear_interrupt(&self, interrupt: Interrupt) {
|
||||
let num = self.id().num as usize;
|
||||
unsafe {
|
||||
let io = &(*pac::IO_BANK0::ptr());
|
||||
let reg = (&io.intr0).as_ptr().add(num / 8);
|
||||
let bit_in_reg = num % 8 * 4 + interrupt as usize;
|
||||
*reg |= 1 << bit_in_reg;
|
||||
}
|
||||
}
|
||||
|
||||
/// Interrupt status.
|
||||
#[inline]
|
||||
fn interrupt_status(&self, interrupt: Interrupt) -> bool {
|
||||
let num = self.id().num as usize;
|
||||
unsafe {
|
||||
let cpuid = *(pac::SIO::ptr() as *const u32);
|
||||
let io = &(*pac::IO_BANK0::ptr());
|
||||
let reg = (&io.proc0_ints0)
|
||||
.as_ptr()
|
||||
.add(num / 8 + cpuid as usize * 12);
|
||||
let bit_in_reg = num % 8 * 4 + interrupt as usize;
|
||||
(*reg & (1 << bit_in_reg)) != 0
|
||||
}
|
||||
}
|
||||
|
||||
/// Is interrupt enabled.
|
||||
#[inline]
|
||||
fn is_interrupt_enabled(&self, interrupt: Interrupt) -> bool {
|
||||
let num = self.id().num as usize;
|
||||
unsafe {
|
||||
let cpuid = *(pac::SIO::ptr() as *const u32);
|
||||
let io = &(*pac::IO_BANK0::ptr());
|
||||
let reg = (&io.proc0_inte0)
|
||||
.as_ptr()
|
||||
.add(num / 8 + cpuid as usize * 12);
|
||||
let bit_in_reg = num % 8 * 4 + interrupt as usize;
|
||||
(*reg & (1 << bit_in_reg)) != 0
|
||||
}
|
||||
}
|
||||
|
||||
/// Enable or disable interrupt.
|
||||
#[inline]
|
||||
fn set_interrupt_enabled(&self, interrupt: Interrupt, enabled: bool) {
|
||||
let num = self.id().num as usize;
|
||||
unsafe {
|
||||
let cpuid = *(pac::SIO::ptr() as *const u32);
|
||||
let io = &(*pac::IO_BANK0::ptr());
|
||||
let reg = (&io.proc0_inte0)
|
||||
.as_ptr()
|
||||
.add(num / 8 + cpuid as usize * 12);
|
||||
let bit_in_reg = num % 8 * 4 + interrupt as usize;
|
||||
if enabled {
|
||||
*reg |= 1 << bit_in_reg;
|
||||
} else {
|
||||
*reg &= !(1 << bit_in_reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Is interrupt forced.
|
||||
#[inline]
|
||||
fn is_interrupt_forced(&self, interrupt: Interrupt) -> bool {
|
||||
let num = self.id().num as usize;
|
||||
unsafe {
|
||||
let cpuid = *(pac::SIO::ptr() as *const u32);
|
||||
let io = &(*pac::IO_BANK0::ptr());
|
||||
let reg = (&io.proc0_intf0)
|
||||
.as_ptr()
|
||||
.add(num / 8 + cpuid as usize * 12);
|
||||
let bit_in_reg = num % 8 * 4 + interrupt as usize;
|
||||
(*reg & (1 << bit_in_reg)) != 0
|
||||
}
|
||||
}
|
||||
|
||||
/// Force or release interrupt.
|
||||
#[inline]
|
||||
fn set_interrupt_forced(&self, interrupt: Interrupt, forced: bool) {
|
||||
let num = self.id().num as usize;
|
||||
unsafe {
|
||||
let cpuid = *(pac::SIO::ptr() as *const u32);
|
||||
let io = &(*pac::IO_BANK0::ptr());
|
||||
let reg = (&io.proc0_intf0)
|
||||
.as_ptr()
|
||||
.add(num / 8 + cpuid as usize * 12);
|
||||
let bit_in_reg = num % 8 * 4 + interrupt as usize;
|
||||
if forced {
|
||||
*reg |= 1 << bit_in_reg;
|
||||
} else {
|
||||
*reg &= !(1 << bit_in_reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the interrupt override.
|
||||
#[inline]
|
||||
fn set_interrupt_override(&self, override_value: InterruptOverride) {
|
||||
|
|
Loading…
Reference in a new issue