Compare commits
5 Commits
va108xx-em
...
fc894bc421
Author | SHA1 | Date | |
---|---|---|---|
fc894bc421
|
|||
1a83f932b5 | |||
cdc4807686 | |||
62a4123f82 | |||
17f13fc4dc
|
@@ -4,10 +4,9 @@
|
|||||||
# runner = "arm-none-eabi-gdb -q -x openocd.gdb"
|
# runner = "arm-none-eabi-gdb -q -x openocd.gdb"
|
||||||
# runner = "gdb-multiarch -q -x openocd.gdb"
|
# runner = "gdb-multiarch -q -x openocd.gdb"
|
||||||
# runner = "gdb -q -x openocd.gdb"
|
# runner = "gdb -q -x openocd.gdb"
|
||||||
runner = "gdb-multiarch -q -x jlink.gdb"
|
# runner = "gdb-multiarch -q -x jlink.gdb"
|
||||||
|
|
||||||
# Probe-rs is currently problematic: https://github.com/probe-rs/probe-rs/issues/2567
|
runner = "probe-rs run --chip VA108xx_RAM --protocol jtag"
|
||||||
# runner = "probe-rs run --chip VA108xx --chip-description-path ./scripts/VA108xx_Series.yaml"
|
|
||||||
# runner = ["probe-rs", "run", "--chip", "$CHIP", "--log-format", "{L} {s}"]
|
# runner = ["probe-rs", "run", "--chip", "$CHIP", "--log-format", "{L} {s}"]
|
||||||
|
|
||||||
rustflags = [
|
rustflags = [
|
||||||
|
73
README.md
73
README.md
@@ -60,14 +60,56 @@ You can then adapt the files in `.vscode` to your needs.
|
|||||||
You can use CLI or VS Code for flashing, running and debugging. In any case, take
|
You can use CLI or VS Code for flashing, running and debugging. In any case, take
|
||||||
care of installing the pre-requisites first.
|
care of installing the pre-requisites first.
|
||||||
|
|
||||||
### Pre-Requisites
|
### Using CLI with probe-rs
|
||||||
|
|
||||||
|
Install [probe-rs](https://probe.rs/docs/getting-started/installation/) first.
|
||||||
|
|
||||||
|
You can use `probe-rs` to run the software and display RTT log output. However, debugging does not
|
||||||
|
work yet.
|
||||||
|
|
||||||
|
After installation, you can run the following command
|
||||||
|
|
||||||
|
```sh
|
||||||
|
probe-rs run --chip VA108xx_RAM --protocol jtag target/thumbv6m-none-eabi/debug/examples/blinky
|
||||||
|
```
|
||||||
|
|
||||||
|
to flash and run the blinky program on the RAM. There is also a `VA108xx` chip target
|
||||||
|
available for persistent flashing.
|
||||||
|
|
||||||
|
Runner configuration avilable in the `.cargo/def-config.toml` file to use `probe-rs` for
|
||||||
|
convenience.
|
||||||
|
|
||||||
|
### Using VS Code
|
||||||
|
|
||||||
|
Assuming a working debug connection to your VA108xx board, you can debug using VS Code with
|
||||||
|
the [`Cortex-Debug` plugin](https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug).
|
||||||
|
Please make sure that [`objdump-multiarch` and `nm-multiarch`](https://forums.raspberrypi.com/viewtopic.php?t=333146)
|
||||||
|
are installed as well.
|
||||||
|
|
||||||
|
Some sample configuration files for VS code were provided and can be used by running
|
||||||
|
`cp -rT vscode .vscode` like specified above. After that, you can use `Run and Debug`
|
||||||
|
to automatically rebuild and flash your application.
|
||||||
|
|
||||||
|
If you would like to use a custom GDB application, you can specify the gdb binary in the following
|
||||||
|
configuration variables in your `settings.json`:
|
||||||
|
|
||||||
|
- `"cortex-debug.gdbPath"`
|
||||||
|
- `"cortex-debug.gdbPath.linux"`
|
||||||
|
- `"cortex-debug.gdbPath.windows"`
|
||||||
|
- `"cortex-debug.gdbPath.osx"`
|
||||||
|
|
||||||
|
The provided VS Code configurations also provide an integrated RTT logger, which you can access
|
||||||
|
via the terminal at `RTT Ch:0 console`. In order for the RTT block address detection to
|
||||||
|
work properly, `objdump-multiarch` and `nm-multiarch` need to be installed.
|
||||||
|
|
||||||
|
### Using CLI with GDB and Segger J-Link Tools
|
||||||
|
|
||||||
|
Install the following two tools first:
|
||||||
|
|
||||||
1. [SEGGER J-Link tools](https://www.segger.com/downloads/jlink/) installed
|
1. [SEGGER J-Link tools](https://www.segger.com/downloads/jlink/) installed
|
||||||
2. [gdb-multiarch](https://packages.debian.org/sid/gdb-multiarch) or similar
|
2. [gdb-multiarch](https://packages.debian.org/sid/gdb-multiarch) or similar
|
||||||
cross-architecture debugger installed. All commands here assume `gdb-multiarch`.
|
cross-architecture debugger installed. All commands here assume `gdb-multiarch`.
|
||||||
|
|
||||||
### Using CLI
|
|
||||||
|
|
||||||
You can build the blinky example application with the following command
|
You can build the blinky example application with the following command
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
@@ -101,25 +143,8 @@ runner = "gdb-multiarch -q -x jlink/jlink.gdb"
|
|||||||
After that, you can simply use `cargo run --example blinky` to flash the blinky
|
After that, you can simply use `cargo run --example blinky` to flash the blinky
|
||||||
example.
|
example.
|
||||||
|
|
||||||
### Using VS Code
|
### Using the RTT Viewer
|
||||||
|
|
||||||
Assuming a working debug connection to your VA108xx board, you can debug using VS Code with
|
The Segger RTT viewer can be used to display log messages received from the target. The base
|
||||||
the [`Cortex-Debug` plugin](https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug).
|
address for the RTT block placement is 0x10000000. It is recommended to use a search range of
|
||||||
Please make sure that [`objdump-multiarch` and `nm-multiarch`](https://forums.raspberrypi.com/viewtopic.php?t=333146)
|
0x1000 around that base address when using the RTT viewer.
|
||||||
are installed as well.
|
|
||||||
|
|
||||||
Some sample configuration files for VS code were provided and can be used by running
|
|
||||||
`cp -rT vscode .vscode` like specified above. After that, you can use `Run and Debug`
|
|
||||||
to automatically rebuild and flash your application.
|
|
||||||
|
|
||||||
If you would like to use a custom GDB application, you can specify the gdb binary in the following
|
|
||||||
configuration variables in your `settings.json`:
|
|
||||||
|
|
||||||
- `"cortex-debug.gdbPath"`
|
|
||||||
- `"cortex-debug.gdbPath.linux"`
|
|
||||||
- `"cortex-debug.gdbPath.windows"`
|
|
||||||
- `"cortex-debug.gdbPath.osx"`
|
|
||||||
|
|
||||||
The provided VS Code configurations also provide an integrated RTT logger, which you can access
|
|
||||||
via the terminal at `RTT Ch:0 console`. In order for the RTT block address detection to
|
|
||||||
work properly, `objdump-multiarch` and `nm-multiarch` need to be installed.
|
|
||||||
|
@@ -122,14 +122,14 @@ fn main() -> ! {
|
|||||||
}
|
}
|
||||||
TestCase::Pulse => {
|
TestCase::Pulse => {
|
||||||
let mut output_pulsed = pinsa.pa0.into_push_pull_output();
|
let mut output_pulsed = pinsa.pa0.into_push_pull_output();
|
||||||
output_pulsed.pulse_mode(true, PinState::Low);
|
output_pulsed.configure_pulse_mode(true, PinState::Low);
|
||||||
rprintln!("Pulsing high 10 times..");
|
rprintln!("Pulsing high 10 times..");
|
||||||
output_pulsed.set_low().unwrap();
|
output_pulsed.set_low().unwrap();
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
output_pulsed.set_high().unwrap();
|
output_pulsed.set_high().unwrap();
|
||||||
cortex_m::asm::delay(25_000_000);
|
cortex_m::asm::delay(25_000_000);
|
||||||
}
|
}
|
||||||
output_pulsed.pulse_mode(true, PinState::High);
|
output_pulsed.configure_pulse_mode(true, PinState::High);
|
||||||
rprintln!("Pulsing low 10 times..");
|
rprintln!("Pulsing low 10 times..");
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
output_pulsed.set_low().unwrap();
|
output_pulsed.set_low().unwrap();
|
||||||
@@ -140,12 +140,12 @@ fn main() -> ! {
|
|||||||
let mut out_0 = pinsa
|
let mut out_0 = pinsa
|
||||||
.pa0
|
.pa0
|
||||||
.into_readable_push_pull_output()
|
.into_readable_push_pull_output()
|
||||||
.delay(true, false);
|
.configure_delay(true, false);
|
||||||
let mut out_1 = pinsa
|
let mut out_1 = pinsa
|
||||||
.pa1
|
.pa1
|
||||||
.into_readable_push_pull_output()
|
.into_readable_push_pull_output()
|
||||||
.delay(false, true);
|
.configure_delay(false, true);
|
||||||
let mut out_2 = pinsa.pa3.into_readable_push_pull_output().delay(true, true);
|
let mut out_2 = pinsa.pa3.into_readable_push_pull_output().configure_delay(true, true);
|
||||||
for _ in 0..20 {
|
for _ in 0..20 {
|
||||||
out_0.toggle().unwrap();
|
out_0.toggle().unwrap();
|
||||||
out_1.toggle().unwrap();
|
out_1.toggle().unwrap();
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
#!/bin/sh
|
#!/bin/bash
|
||||||
export RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options"
|
export RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options"
|
||||||
cargo +nightly doc --open
|
cargo +nightly doc --open
|
||||||
|
@@ -33,8 +33,7 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||||
use core::cell::{Cell, RefCell};
|
use core::cell::{Cell, RefCell};
|
||||||
use critical_section::CriticalSection;
|
use critical_section::{CriticalSection, Mutex};
|
||||||
use embassy_sync::blocking_mutex::CriticalSectionMutex as Mutex;
|
|
||||||
use portable_atomic::{AtomicU32, Ordering};
|
use portable_atomic::{AtomicU32, Ordering};
|
||||||
|
|
||||||
use embassy_time_driver::{time_driver_impl, Driver, TICK_HZ};
|
use embassy_time_driver::{time_driver_impl, Driver, TICK_HZ};
|
||||||
@@ -46,7 +45,7 @@ use va108xx_hal::{
|
|||||||
clock::enable_peripheral_clock,
|
clock::enable_peripheral_clock,
|
||||||
enable_nvic_interrupt, pac,
|
enable_nvic_interrupt, pac,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
timer::{enable_tim_clk, get_tim_raw, TimRegInterface},
|
timer::{enable_tim_clk, get_tim_raw, TimRegInterface, ValidTim},
|
||||||
PeripheralSelect,
|
PeripheralSelect,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -116,12 +115,15 @@ pub mod embassy {
|
|||||||
/// This has to be called once at initialization time to initiate the time driver for
|
/// This has to be called once at initialization time to initiate the time driver for
|
||||||
/// embassy.
|
/// embassy.
|
||||||
#[cfg(feature = "irqs-in-lib")]
|
#[cfg(feature = "irqs-in-lib")]
|
||||||
pub unsafe fn init(
|
pub unsafe fn init<
|
||||||
|
TimekeeperTim: TimRegInterface + ValidTim,
|
||||||
|
AlarmTim: TimRegInterface + ValidTim,
|
||||||
|
>(
|
||||||
syscfg: &mut pac::Sysconfig,
|
syscfg: &mut pac::Sysconfig,
|
||||||
irqsel: &pac::Irqsel,
|
irqsel: &pac::Irqsel,
|
||||||
sysclk: impl Into<Hertz>,
|
sysclk: impl Into<Hertz>,
|
||||||
timekeeper_tim: impl TimRegInterface,
|
timekeeper_tim: TimekeeperTim,
|
||||||
alarm_tim: impl TimRegInterface,
|
alarm_tim: AlarmTim,
|
||||||
) {
|
) {
|
||||||
TIME_DRIVER.init(
|
TIME_DRIVER.init(
|
||||||
syscfg,
|
syscfg,
|
||||||
@@ -140,12 +142,15 @@ pub mod embassy {
|
|||||||
///
|
///
|
||||||
/// This has to be called once at initialization time to initiate the time driver for
|
/// This has to be called once at initialization time to initiate the time driver for
|
||||||
/// embassy.
|
/// embassy.
|
||||||
pub unsafe fn init_with_custom_irqs(
|
pub unsafe fn init_with_custom_irqs<
|
||||||
|
TimekeeperTim: TimRegInterface + ValidTim,
|
||||||
|
AlarmTim: TimRegInterface + ValidTim,
|
||||||
|
>(
|
||||||
syscfg: &mut pac::Sysconfig,
|
syscfg: &mut pac::Sysconfig,
|
||||||
irqsel: &pac::Irqsel,
|
irqsel: &pac::Irqsel,
|
||||||
sysclk: impl Into<Hertz>,
|
sysclk: impl Into<Hertz>,
|
||||||
timekeeper_tim: impl TimRegInterface,
|
timekeeper_tim: TimekeeperTim,
|
||||||
alarm_tim: impl TimRegInterface,
|
alarm_tim: AlarmTim,
|
||||||
timekeeper_irq: pac::Interrupt,
|
timekeeper_irq: pac::Interrupt,
|
||||||
alarm_irq: pac::Interrupt,
|
alarm_irq: pac::Interrupt,
|
||||||
) {
|
) {
|
||||||
@@ -188,21 +193,21 @@ pub struct TimerDriver {
|
|||||||
|
|
||||||
impl TimerDriver {
|
impl TimerDriver {
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn init(
|
fn init<TimekeeperTim: TimRegInterface + ValidTim, AlarmTim: TimRegInterface + ValidTim>(
|
||||||
&self,
|
&self,
|
||||||
syscfg: &mut pac::Sysconfig,
|
syscfg: &mut pac::Sysconfig,
|
||||||
irqsel: &pac::Irqsel,
|
irqsel: &pac::Irqsel,
|
||||||
sysclk: impl Into<Hertz>,
|
sysclk: impl Into<Hertz>,
|
||||||
timekeeper_tim: impl TimRegInterface,
|
timekeeper_tim: TimekeeperTim,
|
||||||
alarm_tim: impl TimRegInterface,
|
alarm_tim: AlarmTim,
|
||||||
timekeeper_irq: pac::Interrupt,
|
timekeeper_irq: pac::Interrupt,
|
||||||
alarm_irq: pac::Interrupt,
|
alarm_irq: pac::Interrupt,
|
||||||
) {
|
) {
|
||||||
if ALARM_TIM.get().is_some() {
|
if ALARM_TIM.get().is_some() || TIMEKEEPER_TIM.get().is_some() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ALARM_TIM.set(alarm_tim.tim_id()).ok();
|
ALARM_TIM.set(AlarmTim::TIM_ID).ok();
|
||||||
TIMEKEEPER_TIM.set(timekeeper_tim.tim_id()).ok();
|
TIMEKEEPER_TIM.set(TimekeeperTim::TIM_ID).ok();
|
||||||
enable_peripheral_clock(syscfg, PeripheralSelect::Irqsel);
|
enable_peripheral_clock(syscfg, PeripheralSelect::Irqsel);
|
||||||
enable_tim_clk(syscfg, timekeeper_tim.tim_id());
|
enable_tim_clk(syscfg, timekeeper_tim.tim_id());
|
||||||
let timekeeper_reg_block = timekeeper_tim.reg_block();
|
let timekeeper_reg_block = timekeeper_tim.reg_block();
|
||||||
|
@@ -115,7 +115,7 @@ impl InputPinFuture {
|
|||||||
|
|
||||||
EDGE_DETECTION[pin_id_to_offset(pin.id())]
|
EDGE_DETECTION[pin_id_to_offset(pin.id())]
|
||||||
.store(false, core::sync::atomic::Ordering::Relaxed);
|
.store(false, core::sync::atomic::Ordering::Relaxed);
|
||||||
pin.interrupt_edge(
|
pin.configure_edge_interrupt(
|
||||||
edge,
|
edge,
|
||||||
InterruptConfig::new(irq, true, true),
|
InterruptConfig::new(irq, true, true),
|
||||||
Some(sys_cfg),
|
Some(sys_cfg),
|
||||||
|
@@ -181,6 +181,7 @@ pub struct DynPinId {
|
|||||||
/// This `struct` takes ownership of a [`DynPinId`] and provides an API to
|
/// This `struct` takes ownership of a [`DynPinId`] and provides an API to
|
||||||
/// access the corresponding regsiters.
|
/// access the corresponding regsiters.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub(crate) struct DynRegisters(DynPinId);
|
pub(crate) struct DynRegisters(DynPinId);
|
||||||
|
|
||||||
// [`DynRegisters`] takes ownership of the [`DynPinId`], and [`DynPin`]
|
// [`DynRegisters`] takes ownership of the [`DynPinId`], and [`DynPin`]
|
||||||
@@ -392,11 +393,15 @@ impl DynPin {
|
|||||||
/// - Delay 2: 2
|
/// - Delay 2: 2
|
||||||
/// - Delay 1 + Delay 2: 3
|
/// - Delay 1 + Delay 2: 3
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn delay(self, delay_1: bool, delay_2: bool) -> Result<Self, InvalidPinTypeError> {
|
pub fn configure_delay(
|
||||||
|
&mut self,
|
||||||
|
delay_1: bool,
|
||||||
|
delay_2: bool,
|
||||||
|
) -> Result<(), InvalidPinTypeError> {
|
||||||
match self.mode {
|
match self.mode {
|
||||||
DynPinMode::Output(_) => {
|
DynPinMode::Output(_) => {
|
||||||
self.regs.delay(delay_1, delay_2);
|
self.regs.configure_delay(delay_1, delay_2);
|
||||||
Ok(self)
|
Ok(())
|
||||||
}
|
}
|
||||||
_ => Err(InvalidPinTypeError(self.mode)),
|
_ => Err(InvalidPinTypeError(self.mode)),
|
||||||
}
|
}
|
||||||
@@ -406,7 +411,7 @@ impl DynPin {
|
|||||||
/// When configured for pulse mode, a given pin will set the non-default state for exactly
|
/// 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
|
/// one clock cycle before returning to the configured default state
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn pulse_mode(
|
pub fn configure_pulse_mode(
|
||||||
&mut self,
|
&mut self,
|
||||||
enable: bool,
|
enable: bool,
|
||||||
default_state: PinState,
|
default_state: PinState,
|
||||||
@@ -422,14 +427,14 @@ impl DynPin {
|
|||||||
|
|
||||||
/// See p.37 and p.38 of the programmers guide for more information.
|
/// See p.37 and p.38 of the programmers guide for more information.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn filter_type(
|
pub fn configure_filter_type(
|
||||||
&mut self,
|
&mut self,
|
||||||
filter: FilterType,
|
filter: FilterType,
|
||||||
clksel: FilterClkSel,
|
clksel: FilterClkSel,
|
||||||
) -> Result<(), InvalidPinTypeError> {
|
) -> Result<(), InvalidPinTypeError> {
|
||||||
match self.mode {
|
match self.mode {
|
||||||
DynPinMode::Input(_) => {
|
DynPinMode::Input(_) => {
|
||||||
self.regs.filter_type(filter, clksel);
|
self.regs.configure_filter_type(filter, clksel);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
_ => Err(InvalidPinTypeError(self.mode)),
|
_ => Err(InvalidPinTypeError(self.mode)),
|
||||||
@@ -437,7 +442,7 @@ impl DynPin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn interrupt_edge(
|
pub fn configure_edge_interrupt(
|
||||||
&mut self,
|
&mut self,
|
||||||
edge_type: InterruptEdge,
|
edge_type: InterruptEdge,
|
||||||
irq_cfg: InterruptConfig,
|
irq_cfg: InterruptConfig,
|
||||||
@@ -446,7 +451,7 @@ impl DynPin {
|
|||||||
) -> Result<(), InvalidPinTypeError> {
|
) -> Result<(), InvalidPinTypeError> {
|
||||||
match self.mode {
|
match self.mode {
|
||||||
DynPinMode::Input(_) | DynPinMode::Output(_) => {
|
DynPinMode::Input(_) | DynPinMode::Output(_) => {
|
||||||
self.regs.interrupt_edge(edge_type);
|
self.regs.configure_edge_interrupt(edge_type);
|
||||||
self.irq_enb(irq_cfg, syscfg, irqsel);
|
self.irq_enb(irq_cfg, syscfg, irqsel);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -455,7 +460,7 @@ impl DynPin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn interrupt_level(
|
pub fn configure_level_interrupt(
|
||||||
&mut self,
|
&mut self,
|
||||||
level_type: InterruptLevel,
|
level_type: InterruptLevel,
|
||||||
irq_cfg: InterruptConfig,
|
irq_cfg: InterruptConfig,
|
||||||
@@ -464,7 +469,7 @@ impl DynPin {
|
|||||||
) -> Result<(), InvalidPinTypeError> {
|
) -> Result<(), InvalidPinTypeError> {
|
||||||
match self.mode {
|
match self.mode {
|
||||||
DynPinMode::Input(_) | DynPinMode::Output(_) => {
|
DynPinMode::Input(_) | DynPinMode::Output(_) => {
|
||||||
self.regs.interrupt_level(level_type);
|
self.regs.configure_level_interrupt(level_type);
|
||||||
self.irq_enb(irq_cfg, syscfg, irqsel);
|
self.irq_enb(irq_cfg, syscfg, irqsel);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@@ -89,6 +89,7 @@ use paste::paste;
|
|||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum InterruptEdge {
|
pub enum InterruptEdge {
|
||||||
HighToLow,
|
HighToLow,
|
||||||
LowToHigh,
|
LowToHigh,
|
||||||
@@ -96,12 +97,14 @@ pub enum InterruptEdge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum InterruptLevel {
|
pub enum InterruptLevel {
|
||||||
Low = 0,
|
Low = 0,
|
||||||
High = 1,
|
High = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum PinState {
|
pub enum PinState {
|
||||||
Low = 0,
|
Low = 0,
|
||||||
High = 1,
|
High = 1,
|
||||||
@@ -353,6 +356,7 @@ impl<I: PinId, M: PinMode> Pin<I, M> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn id(&self) -> DynPinId {
|
pub fn id(&self) -> DynPinId {
|
||||||
self.inner.id()
|
self.inner.id()
|
||||||
}
|
}
|
||||||
@@ -599,7 +603,7 @@ impl<I: PinId, C: InputConfig> Pin<I, Input<C>> {
|
|||||||
syscfg: Option<&mut Sysconfig>,
|
syscfg: Option<&mut Sysconfig>,
|
||||||
irqsel: Option<&mut Irqsel>,
|
irqsel: Option<&mut Irqsel>,
|
||||||
) {
|
) {
|
||||||
self.inner.regs.interrupt_edge(edge_type);
|
self.inner.regs.configure_edge_interrupt(edge_type);
|
||||||
self.irq_enb(irq_cfg, syscfg, irqsel);
|
self.irq_enb(irq_cfg, syscfg, irqsel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -610,7 +614,7 @@ impl<I: PinId, C: InputConfig> Pin<I, Input<C>> {
|
|||||||
syscfg: Option<&mut Sysconfig>,
|
syscfg: Option<&mut Sysconfig>,
|
||||||
irqsel: Option<&mut Irqsel>,
|
irqsel: Option<&mut Irqsel>,
|
||||||
) {
|
) {
|
||||||
self.inner.regs.interrupt_level(level_type);
|
self.inner.regs.configure_level_interrupt(level_type);
|
||||||
self.irq_enb(irq_cfg, syscfg, irqsel);
|
self.irq_enb(irq_cfg, syscfg, irqsel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -622,9 +626,8 @@ impl<I: PinId, C: OutputConfig> Pin<I, Output<C>> {
|
|||||||
/// - Delay 2: 2
|
/// - Delay 2: 2
|
||||||
/// - Delay 1 + Delay 2: 3
|
/// - Delay 1 + Delay 2: 3
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn delay(self, delay_1: bool, delay_2: bool) -> Self {
|
pub fn configure_delay(&mut self, delay_1: bool, delay_2: bool) {
|
||||||
self.inner.regs.delay(delay_1, delay_2);
|
self.inner.regs.configure_delay(delay_1, delay_2);
|
||||||
self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -632,13 +635,25 @@ impl<I: PinId, C: OutputConfig> Pin<I, Output<C>> {
|
|||||||
self._toggle_with_toggle_reg()
|
self._toggle_with_toggle_reg()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.9.0",
|
||||||
|
note = "Please use the `configure_pulse_mode` method instead"
|
||||||
|
)]
|
||||||
|
pub fn pulse_mode(&mut self, enable: bool, default_state: PinState) {
|
||||||
|
self.configure_pulse_mode(enable, default_state);
|
||||||
|
}
|
||||||
|
|
||||||
/// See p.52 of the programmers guide for more information.
|
/// 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
|
/// 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
|
/// one clock cycle before returning to the configured default state
|
||||||
pub fn pulse_mode(&mut self, enable: bool, default_state: PinState) {
|
pub fn configure_pulse_mode(&mut self, enable: bool, default_state: PinState) {
|
||||||
self.inner.regs.pulse_mode(enable, default_state);
|
self.inner.regs.pulse_mode(enable, default_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.9.0",
|
||||||
|
note = "Please use the `configure_edge_interrupt` method instead"
|
||||||
|
)]
|
||||||
pub fn interrupt_edge(
|
pub fn interrupt_edge(
|
||||||
&mut self,
|
&mut self,
|
||||||
edge_type: InterruptEdge,
|
edge_type: InterruptEdge,
|
||||||
@@ -646,18 +661,43 @@ impl<I: PinId, C: OutputConfig> Pin<I, Output<C>> {
|
|||||||
syscfg: Option<&mut Sysconfig>,
|
syscfg: Option<&mut Sysconfig>,
|
||||||
irqsel: Option<&mut Irqsel>,
|
irqsel: Option<&mut Irqsel>,
|
||||||
) {
|
) {
|
||||||
self.inner.regs.interrupt_edge(edge_type);
|
self.inner.regs.configure_edge_interrupt(edge_type);
|
||||||
self.irq_enb(irq_cfg, syscfg, irqsel);
|
self.irq_enb(irq_cfg, syscfg, irqsel);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interrupt_level(
|
pub fn configure_edge_interrupt(
|
||||||
|
&mut self,
|
||||||
|
edge_type: InterruptEdge,
|
||||||
|
irq_cfg: InterruptConfig,
|
||||||
|
syscfg: Option<&mut Sysconfig>,
|
||||||
|
irqsel: Option<&mut Irqsel>,
|
||||||
|
) {
|
||||||
|
self.inner.regs.configure_edge_interrupt(edge_type);
|
||||||
|
self.irq_enb(irq_cfg, syscfg, irqsel);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.9.0",
|
||||||
|
note = "Please use the `configure_level_interrupt` method instead"
|
||||||
|
)]
|
||||||
|
pub fn level_interrupt(
|
||||||
&mut self,
|
&mut self,
|
||||||
level_type: InterruptLevel,
|
level_type: InterruptLevel,
|
||||||
irq_cfg: InterruptConfig,
|
irq_cfg: InterruptConfig,
|
||||||
syscfg: Option<&mut Sysconfig>,
|
syscfg: Option<&mut Sysconfig>,
|
||||||
irqsel: Option<&mut Irqsel>,
|
irqsel: Option<&mut Irqsel>,
|
||||||
) {
|
) {
|
||||||
self.inner.regs.interrupt_level(level_type);
|
self.configure_level_interrupt(level_type, irq_cfg, syscfg, irqsel);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn configure_level_interrupt(
|
||||||
|
&mut self,
|
||||||
|
level_type: InterruptLevel,
|
||||||
|
irq_cfg: InterruptConfig,
|
||||||
|
syscfg: Option<&mut Sysconfig>,
|
||||||
|
irqsel: Option<&mut Irqsel>,
|
||||||
|
) {
|
||||||
|
self.inner.regs.configure_level_interrupt(level_type);
|
||||||
self.irq_enb(irq_cfg, syscfg, irqsel);
|
self.irq_enb(irq_cfg, syscfg, irqsel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -666,7 +706,7 @@ impl<I: PinId, C: InputConfig> Pin<I, Input<C>> {
|
|||||||
/// See p.37 and p.38 of the programmers guide for more information.
|
/// See p.37 and p.38 of the programmers guide for more information.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn configure_filter_type(&mut self, filter: FilterType, clksel: FilterClkSel) {
|
pub fn configure_filter_type(&mut self, filter: FilterType, clksel: FilterClkSel) {
|
||||||
self.inner.regs.filter_type(filter, clksel);
|
self.inner.regs.configure_filter_type(filter, clksel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -240,7 +240,7 @@ pub(super) unsafe trait RegisterInterface {
|
|||||||
/// Only useful for interrupt pins. Configure whether to use edges or level as interrupt soure
|
/// Only useful for interrupt pins. Configure whether to use edges or level as interrupt soure
|
||||||
/// When using edge mode, it is possible to generate interrupts on both edges as well
|
/// When using edge mode, it is possible to generate interrupts on both edges as well
|
||||||
#[inline]
|
#[inline]
|
||||||
fn interrupt_edge(&mut self, edge_type: InterruptEdge) {
|
fn configure_edge_interrupt(&mut self, edge_type: InterruptEdge) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.port_reg()
|
self.port_reg()
|
||||||
.irq_sen()
|
.irq_sen()
|
||||||
@@ -267,7 +267,7 @@ pub(super) unsafe trait RegisterInterface {
|
|||||||
|
|
||||||
/// Configure which edge or level type triggers an interrupt
|
/// Configure which edge or level type triggers an interrupt
|
||||||
#[inline]
|
#[inline]
|
||||||
fn interrupt_level(&mut self, level: InterruptLevel) {
|
fn configure_level_interrupt(&mut self, level: InterruptLevel) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.port_reg()
|
self.port_reg()
|
||||||
.irq_sen()
|
.irq_sen()
|
||||||
@@ -286,7 +286,7 @@ pub(super) unsafe trait RegisterInterface {
|
|||||||
|
|
||||||
/// Only useful for input pins
|
/// Only useful for input pins
|
||||||
#[inline]
|
#[inline]
|
||||||
fn filter_type(&mut self, filter: FilterType, clksel: FilterClkSel) {
|
fn configure_filter_type(&mut self, filter: FilterType, clksel: FilterClkSel) {
|
||||||
self.iocfg_port().modify(|_, w| {
|
self.iocfg_port().modify(|_, w| {
|
||||||
// Safety: Only write to register for this Pin ID
|
// Safety: Only write to register for this Pin ID
|
||||||
unsafe {
|
unsafe {
|
||||||
@@ -349,7 +349,7 @@ pub(super) unsafe trait RegisterInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Only useful for output pins
|
/// Only useful for output pins
|
||||||
fn delay(&self, delay_1: bool, delay_2: bool) {
|
fn configure_delay(&mut self, delay_1: bool, delay_2: bool) {
|
||||||
let portreg = self.port_reg();
|
let portreg = self.port_reg();
|
||||||
unsafe {
|
unsafe {
|
||||||
if delay_1 {
|
if delay_1 {
|
||||||
|
Reference in New Issue
Block a user