Merge pull request 'Improve HAL' (#11) from improve-hal into main
All checks were successful
Rust/va108xx-rs/pipeline/head This commit looks good
All checks were successful
Rust/va108xx-rs/pipeline/head This commit looks good
Reviewed-on: #11
This commit is contained in:
commit
e2e3cc7020
@ -24,8 +24,7 @@ rustflags = [
|
|||||||
# "-C", "link-arg=-Tdefmt.x",
|
# "-C", "link-arg=-Tdefmt.x",
|
||||||
|
|
||||||
# Can be useful for debugging.
|
# Can be useful for debugging.
|
||||||
"-Clink-args=-Map=app.map"
|
# "-Clink-args=-Map=app.map"
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
|
@ -106,3 +106,6 @@ configuration variables in your `settings.json`:
|
|||||||
- `"cortex-debug.gdbPath.linux"`
|
- `"cortex-debug.gdbPath.linux"`
|
||||||
- `"cortex-debug.gdbPath.windows"`
|
- `"cortex-debug.gdbPath.windows"`
|
||||||
- `"cortex-debug.gdbPath.osx"`
|
- `"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`.
|
||||||
|
@ -15,7 +15,7 @@ embedded-hal-nb = "1"
|
|||||||
embedded-io = "0.6"
|
embedded-io = "0.6"
|
||||||
|
|
||||||
[dependencies.va108xx-hal]
|
[dependencies.va108xx-hal]
|
||||||
version = "0.6"
|
version = "0.7"
|
||||||
path = "../va108xx-hal"
|
path = "../va108xx-hal"
|
||||||
features = ["rt"]
|
features = ["rt"]
|
||||||
|
|
||||||
|
@ -28,6 +28,6 @@ version = "1"
|
|||||||
features = ["cortex-m-systick"]
|
features = ["cortex-m-systick"]
|
||||||
|
|
||||||
[dependencies.va108xx-hal]
|
[dependencies.va108xx-hal]
|
||||||
version = "0.6"
|
version = "0.7"
|
||||||
path = "../../va108xx-hal"
|
path = "../../va108xx-hal"
|
||||||
features = ["rt", "defmt"]
|
features = ["rt", "defmt"]
|
||||||
|
@ -21,9 +21,9 @@ fn main() -> ! {
|
|||||||
let mut dp = pac::Peripherals::take().unwrap();
|
let mut dp = pac::Peripherals::take().unwrap();
|
||||||
let pinsa = PinsA::new(&mut dp.sysconfig, None, dp.porta);
|
let pinsa = PinsA::new(&mut dp.sysconfig, None, dp.porta);
|
||||||
let mut pwm = pwm::PwmPin::new(
|
let mut pwm = pwm::PwmPin::new(
|
||||||
(pinsa.pa3.into_funsel_1(), dp.tim3),
|
|
||||||
50.MHz(),
|
|
||||||
&mut dp.sysconfig,
|
&mut dp.sysconfig,
|
||||||
|
50.MHz(),
|
||||||
|
(pinsa.pa3.into_funsel_1(), dp.tim3),
|
||||||
10.Hz(),
|
10.Hz(),
|
||||||
);
|
);
|
||||||
let mut delay = set_up_ms_delay_provider(&mut dp.sysconfig, 50.MHz(), dp.tim0);
|
let mut delay = set_up_ms_delay_provider(&mut dp.sysconfig, 50.MHz(), dp.tim0);
|
||||||
|
@ -3,12 +3,14 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
use cortex_m_rt::entry;
|
use cortex_m_rt::entry;
|
||||||
use panic_halt as _;
|
use panic_rtt_target as _;
|
||||||
use rtt_target::{rprintln, rtt_init_print};
|
use rtt_target::{rprintln, rtt_init_print};
|
||||||
|
use va108xx_hal as _;
|
||||||
|
|
||||||
#[entry]
|
#[entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
rtt_init_print!();
|
rtt_init_print!();
|
||||||
|
rprintln!("-- VA108XX RTT example --");
|
||||||
let mut counter = 0;
|
let mut counter = 0;
|
||||||
loop {
|
loop {
|
||||||
rprintln!("{}: Hello, world!", counter);
|
rprintln!("{}: Hello, world!", counter);
|
||||||
|
@ -73,12 +73,12 @@ fn main() -> ! {
|
|||||||
pinsa.pa30.into_funsel_1(),
|
pinsa.pa30.into_funsel_1(),
|
||||||
pinsa.pa29.into_funsel_1(),
|
pinsa.pa29.into_funsel_1(),
|
||||||
);
|
);
|
||||||
let mut spia = Spi::spia(
|
let mut spia = Spi::new(
|
||||||
|
&mut dp.sysconfig,
|
||||||
|
50.MHz(),
|
||||||
dp.spia,
|
dp.spia,
|
||||||
(sck, miso, mosi),
|
(sck, miso, mosi),
|
||||||
50.MHz(),
|
|
||||||
spi_cfg,
|
spi_cfg,
|
||||||
Some(&mut dp.sysconfig),
|
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
spia.set_fill_word(FILL_WORD);
|
spia.set_fill_word(FILL_WORD);
|
||||||
@ -90,12 +90,12 @@ fn main() -> ! {
|
|||||||
pinsb.pb8.into_funsel_2(),
|
pinsb.pb8.into_funsel_2(),
|
||||||
pinsb.pb7.into_funsel_2(),
|
pinsb.pb7.into_funsel_2(),
|
||||||
);
|
);
|
||||||
let mut spia = Spi::spia(
|
let mut spia = Spi::new(
|
||||||
|
&mut dp.sysconfig,
|
||||||
|
50.MHz(),
|
||||||
dp.spia,
|
dp.spia,
|
||||||
(sck, miso, mosi),
|
(sck, miso, mosi),
|
||||||
50.MHz(),
|
|
||||||
spi_cfg,
|
spi_cfg,
|
||||||
Some(&mut dp.sysconfig),
|
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
spia.set_fill_word(FILL_WORD);
|
spia.set_fill_word(FILL_WORD);
|
||||||
@ -107,12 +107,12 @@ fn main() -> ! {
|
|||||||
pinsb.pb4.into_funsel_1(),
|
pinsb.pb4.into_funsel_1(),
|
||||||
pinsb.pb3.into_funsel_1(),
|
pinsb.pb3.into_funsel_1(),
|
||||||
);
|
);
|
||||||
let mut spib = Spi::spib(
|
let mut spib = Spi::new(
|
||||||
|
&mut dp.sysconfig,
|
||||||
|
50.MHz(),
|
||||||
dp.spib,
|
dp.spib,
|
||||||
(sck, miso, mosi),
|
(sck, miso, mosi),
|
||||||
50.MHz(),
|
|
||||||
spi_cfg,
|
spi_cfg,
|
||||||
Some(&mut dp.sysconfig),
|
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
spib.set_fill_word(FILL_WORD);
|
spib.set_fill_word(FILL_WORD);
|
||||||
@ -195,6 +195,10 @@ fn main() -> ! {
|
|||||||
if EXAMPLE_SEL == ExampleSelect::Loopback {
|
if EXAMPLE_SEL == ExampleSelect::Loopback {
|
||||||
// Can't really verify correct reply here.
|
// Can't really verify correct reply here.
|
||||||
spi.write(&[0x42]).expect("write failed");
|
spi.write(&[0x42]).expect("write failed");
|
||||||
|
// Need small delay.. otherwise we will read back the sent byte (which we don't want here).
|
||||||
|
// The write function will return as soon as all bytes were shifted out, ignoring the
|
||||||
|
// reply bytes.
|
||||||
|
delay.delay_us(50);
|
||||||
// Because of the loopback mode, we should get back the fill word here.
|
// Because of the loopback mode, we should get back the fill word here.
|
||||||
spi.read(&mut reply_buf[0..1]).unwrap();
|
spi.read(&mut reply_buf[0..1]).unwrap();
|
||||||
assert_eq!(reply_buf[0], FILL_WORD);
|
assert_eq!(reply_buf[0], FILL_WORD);
|
||||||
|
@ -65,7 +65,7 @@ mod app {
|
|||||||
|
|
||||||
let irq_cfg = IrqCfg::new(pac::interrupt::OC3, true, true);
|
let irq_cfg = IrqCfg::new(pac::interrupt::OC3, true, true);
|
||||||
let (mut irq_uart, _) =
|
let (mut irq_uart, _) =
|
||||||
uart::Uart::uartb(dp.uartb, (tx, rx), 115200.Hz(), &mut dp.sysconfig, 50.MHz())
|
uart::Uart::new(&mut dp.sysconfig, 50.MHz(), dp.uartb, (tx, rx), 115200.Hz())
|
||||||
.into_uart_with_irq(irq_cfg, Some(&mut dp.sysconfig), Some(&mut dp.irqsel))
|
.into_uart_with_irq(irq_cfg, Some(&mut dp.sysconfig), Some(&mut dp.irqsel))
|
||||||
.downgrade();
|
.downgrade();
|
||||||
irq_uart
|
irq_uart
|
||||||
|
@ -28,7 +28,7 @@ fn main() -> ! {
|
|||||||
let tx = gpioa.pa9.into_funsel_2();
|
let tx = gpioa.pa9.into_funsel_2();
|
||||||
let rx = gpioa.pa8.into_funsel_2();
|
let rx = gpioa.pa8.into_funsel_2();
|
||||||
|
|
||||||
let uarta = uart::Uart::uarta(dp.uarta, (tx, rx), 115200.Hz(), &mut dp.sysconfig, 50.MHz());
|
let uarta = uart::Uart::new(&mut dp.sysconfig, 50.MHz(), dp.uarta, (tx, rx), 115200.Hz());
|
||||||
let (mut tx, mut rx) = uarta.split();
|
let (mut tx, mut rx) = uarta.split();
|
||||||
writeln!(tx, "Hello World\r").unwrap();
|
writeln!(tx, "Hello World\r").unwrap();
|
||||||
loop {
|
loop {
|
||||||
|
@ -6,6 +6,14 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## [v0.7.0] 2024-07-04
|
||||||
|
|
||||||
|
- Replace `uarta` and `uartb` `Uart` constructors by `new` constructor
|
||||||
|
- Replace SPI `spia`, `spib` and `spic` constructors by `new` constructor
|
||||||
|
- Replace I2C `i2ca`, `i2cb` constructors by `new` constructor. Update constructor
|
||||||
|
to fail on invalid fast I2C speed system clock values
|
||||||
|
- Renamed `gpio::pins` to `gpio::pin` and `gpio::dynpins` to `gpio::dynpin`
|
||||||
|
|
||||||
## [v0.6.0] 2024-06-16
|
## [v0.6.0] 2024-06-16
|
||||||
|
|
||||||
- Updated `embedded-hal` to v1
|
- Updated `embedded-hal` to v1
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "va108xx-hal"
|
name = "va108xx-hal"
|
||||||
version = "0.6.0"
|
version = "0.7.0"
|
||||||
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
|
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "HAL for the Vorago VA108xx family of microcontrollers"
|
description = "HAL for the Vorago VA108xx family of microcontrollers"
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
# HAL for the Vorago VA108xx MCU family
|
# HAL for the Vorago VA108xx MCU family
|
||||||
|
|
||||||
This repository contains the **H**ardware **A**bstraction **L**ayer (HAL), which is an additional
|
This repository contains the **H**ardware **A**bstraction **L**ayer (HAL), which is an additional
|
||||||
hardware abstraction on top of the [peripheral access API](https://egit.irs.uni-stuttgart.de/rust/va108xx).
|
hardware abstraction on top of the [peripheral access API](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/va108xx).
|
||||||
|
|
||||||
It is the result of reading the datasheet for the device and encoding a type-safe layer over the
|
It is the result of reading the datasheet for the device and encoding a type-safe layer over the
|
||||||
raw PAC. This crate also implements traits specified by the
|
raw PAC. This crate also implements traits specified by the
|
||||||
|
@ -57,7 +57,7 @@
|
|||||||
//! [InvalidPinTypeError].
|
//! [InvalidPinTypeError].
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
pins::{FilterType, InterruptEdge, InterruptLevel, Pin, PinId, PinMode, PinState},
|
pin::{FilterType, InterruptEdge, InterruptLevel, Pin, PinId, PinMode, PinState},
|
||||||
reg::RegisterInterface,
|
reg::RegisterInterface,
|
||||||
};
|
};
|
||||||
use crate::{clock::FilterClkSel, pac, FunSel, IrqCfg};
|
use crate::{clock::FilterClkSel, pac, FunSel, IrqCfg};
|
@ -3,10 +3,10 @@
|
|||||||
//! The implementation of this GPIO module is heavily based on the
|
//! The implementation of this GPIO module is heavily based on the
|
||||||
//! [ATSAMD HAL implementation](https://docs.rs/atsamd-hal/latest/atsamd_hal/gpio/index.html).
|
//! [ATSAMD HAL implementation](https://docs.rs/atsamd-hal/latest/atsamd_hal/gpio/index.html).
|
||||||
//!
|
//!
|
||||||
//! This API provides two different submodules, [`mod@pins`] and [`dynpins`],
|
//! This API provides two different submodules, [pin] and [dynpin],
|
||||||
//! representing two different ways to handle GPIO pins. The default, [`mod@pins`],
|
//! representing two different ways to handle GPIO pins. The default, [pin],
|
||||||
//! is a type-level API that tracks the state of each pin at compile-time. The
|
//! is a type-level API that tracks the state of each pin at compile-time. The
|
||||||
//! alternative, [`dynpins`] is a type-erased, value-level API that tracks the
|
//! alternative, [dynpin] is a type-erased, value-level API that tracks the
|
||||||
//! state of each pin at run-time.
|
//! state of each pin at run-time.
|
||||||
//!
|
//!
|
||||||
//! The type-level API is strongly preferred. By representing the state of each
|
//! The type-level API is strongly preferred. By representing the state of each
|
||||||
@ -14,7 +14,7 @@
|
|||||||
//! compile-time. Furthermore, the type-level API has absolutely zero run-time
|
//! compile-time. Furthermore, the type-level API has absolutely zero run-time
|
||||||
//! cost.
|
//! cost.
|
||||||
//!
|
//!
|
||||||
//! If needed, [`dynpins`] can be used to erase the type-level differences
|
//! If needed, [dynpin] can be used to erase the type-level differences
|
||||||
//! between pins. However, by doing so, pins must now be tracked at run-time,
|
//! between pins. However, by doing so, pins must now be tracked at run-time,
|
||||||
//! and each pin has a non-zero memory footprint.
|
//! and each pin has a non-zero memory footprint.
|
||||||
//!
|
//!
|
||||||
@ -101,10 +101,10 @@ macro_rules! common_reg_if_functions {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod dynpins;
|
pub mod dynpin;
|
||||||
pub use dynpins::*;
|
pub use dynpin::*;
|
||||||
|
|
||||||
pub mod pins;
|
pub mod pin;
|
||||||
pub use pins::*;
|
pub use pin::*;
|
||||||
|
|
||||||
mod reg;
|
mod reg;
|
||||||
|
@ -70,7 +70,7 @@
|
|||||||
//! This module implements all of the embedded HAL GPIO traits for each [`Pin`]
|
//! This module implements all of the embedded HAL GPIO traits for each [`Pin`]
|
||||||
//! in the corresponding [`PinMode`]s, namely: [`InputPin`], [`OutputPin`],
|
//! in the corresponding [`PinMode`]s, namely: [`InputPin`], [`OutputPin`],
|
||||||
//! and [`StatefulOutputPin`].
|
//! and [`StatefulOutputPin`].
|
||||||
use super::dynpins::{DynAlternate, DynGroup, DynInput, DynOutput, DynPinId, DynPinMode};
|
use super::dynpin::{DynAlternate, DynGroup, DynInput, DynOutput, DynPinId, DynPinMode};
|
||||||
use super::reg::RegisterInterface;
|
use super::reg::RegisterInterface;
|
||||||
use crate::{
|
use crate::{
|
||||||
pac::{Irqsel, Porta, Portb, Sysconfig},
|
pac::{Irqsel, Porta, Portb, Sysconfig},
|
@ -1,5 +1,5 @@
|
|||||||
use super::dynpins::{self, DynGroup, DynPinId, DynPinMode};
|
use super::dynpin::{self, DynGroup, DynPinId, DynPinMode};
|
||||||
use super::pins::{FilterType, InterruptEdge, InterruptLevel, PinState};
|
use super::pin::{FilterType, InterruptEdge, InterruptLevel, PinState};
|
||||||
use super::IsMaskedError;
|
use super::IsMaskedError;
|
||||||
use crate::clock::FilterClkSel;
|
use crate::clock::FilterClkSel;
|
||||||
use va108xx::{ioconfig, porta};
|
use va108xx::{ioconfig, porta};
|
||||||
@ -30,7 +30,7 @@ impl From<DynPinMode> for ModeFields {
|
|||||||
use DynPinMode::*;
|
use DynPinMode::*;
|
||||||
match mode {
|
match mode {
|
||||||
Input(config) => {
|
Input(config) => {
|
||||||
use dynpins::DynInput::*;
|
use dynpin::DynInput::*;
|
||||||
fields.dir = false;
|
fields.dir = false;
|
||||||
match config {
|
match config {
|
||||||
Floating => (),
|
Floating => (),
|
||||||
@ -44,7 +44,7 @@ impl From<DynPinMode> for ModeFields {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Output(config) => {
|
Output(config) => {
|
||||||
use dynpins::DynOutput::*;
|
use dynpin::DynOutput::*;
|
||||||
fields.dir = true;
|
fields.dir = true;
|
||||||
match config {
|
match config {
|
||||||
PushPull => (),
|
PushPull => (),
|
||||||
|
@ -2,26 +2,31 @@
|
|||||||
//!
|
//!
|
||||||
//! ## Examples
|
//! ## Examples
|
||||||
//!
|
//!
|
||||||
//! - [REB1 I2C temperature sensor example](https://egit.irs.uni-stuttgart.de/rust/vorago-reb1/src/branch/main/examples/adt75-temp-sensor.rs)
|
//! - [REB1 I2C temperature sensor example](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/vorago-reb1/examples/adt75-temp-sensor.rs
|
||||||
use crate::{
|
use crate::{
|
||||||
clock::{enable_peripheral_clock, PeripheralClocks},
|
clock::enable_peripheral_clock, pac, time::Hertz, typelevel::Sealed, PeripheralSelect,
|
||||||
pac,
|
|
||||||
time::Hertz,
|
|
||||||
typelevel::Sealed,
|
|
||||||
};
|
};
|
||||||
use core::marker::PhantomData;
|
use core::{marker::PhantomData, ops::Deref};
|
||||||
use embedded_hal::i2c::{self, Operation, SevenBitAddress, TenBitAddress};
|
use embedded_hal::i2c::{self, Operation, SevenBitAddress, TenBitAddress};
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// Defintions
|
// Defintions
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
||||||
|
const CLK_100K: Hertz = Hertz::from_raw(100_000);
|
||||||
|
const CLK_400K: Hertz = Hertz::from_raw(400_000);
|
||||||
|
const MIN_CLK_400K: Hertz = Hertz::from_raw(8_000_000);
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
pub enum FifoEmptyMode {
|
pub enum FifoEmptyMode {
|
||||||
Stall = 0,
|
Stall = 0,
|
||||||
EndTransaction = 1,
|
EndTransaction = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
pub struct ClockTooSlowForFastI2c;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@ -34,7 +39,21 @@ pub enum Error {
|
|||||||
InsufficientDataReceived,
|
InsufficientDataReceived,
|
||||||
/// Number of bytes in transfer too large (larger than 0x7fe)
|
/// Number of bytes in transfer too large (larger than 0x7fe)
|
||||||
DataTooLarge,
|
DataTooLarge,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
pub enum InitError {
|
||||||
|
/// Wrong address used in constructor
|
||||||
WrongAddrMode,
|
WrongAddrMode,
|
||||||
|
/// APB1 clock is too slow for fast I2C mode.
|
||||||
|
ClkTooSlow(ClockTooSlowForFastI2c),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ClockTooSlowForFastI2c> for InitError {
|
||||||
|
fn from(value: ClockTooSlowForFastI2c) -> Self {
|
||||||
|
Self::ClkTooSlow(value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl embedded_hal::i2c::Error for Error {
|
impl embedded_hal::i2c::Error for Error {
|
||||||
@ -47,10 +66,9 @@ impl embedded_hal::i2c::Error for Error {
|
|||||||
Error::NackData => {
|
Error::NackData => {
|
||||||
embedded_hal::i2c::ErrorKind::NoAcknowledge(i2c::NoAcknowledgeSource::Data)
|
embedded_hal::i2c::ErrorKind::NoAcknowledge(i2c::NoAcknowledgeSource::Data)
|
||||||
}
|
}
|
||||||
Error::DataTooLarge
|
Error::DataTooLarge | Error::InsufficientDataReceived | Error::InvalidTimingParams => {
|
||||||
| Error::WrongAddrMode
|
embedded_hal::i2c::ErrorKind::Other
|
||||||
| Error::InsufficientDataReceived
|
}
|
||||||
| Error::InvalidTimingParams => embedded_hal::i2c::ErrorKind::Other,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,6 +99,37 @@ pub enum I2cAddress {
|
|||||||
TenBit(u16),
|
TenBit(u16),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type I2cRegBlock = pac::i2ca::RegisterBlock;
|
||||||
|
|
||||||
|
/// Common trait implemented by all PAC peripheral access structures. The register block
|
||||||
|
/// format is the same for all SPI blocks.
|
||||||
|
pub trait Instance: Deref<Target = I2cRegBlock> {
|
||||||
|
const IDX: u8;
|
||||||
|
const PERIPH_SEL: PeripheralSelect;
|
||||||
|
|
||||||
|
fn ptr() -> *const I2cRegBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Instance for pac::I2ca {
|
||||||
|
const IDX: u8 = 0;
|
||||||
|
const PERIPH_SEL: PeripheralSelect = PeripheralSelect::I2c0;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn ptr() -> *const I2cRegBlock {
|
||||||
|
Self::ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Instance for pac::I2cb {
|
||||||
|
const IDX: u8 = 1;
|
||||||
|
const PERIPH_SEL: PeripheralSelect = PeripheralSelect::I2c1;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn ptr() -> *const I2cRegBlock {
|
||||||
|
Self::ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// Config
|
// Config
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
@ -242,24 +291,20 @@ impl<I2C> I2cBase<I2C> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! i2c_base {
|
impl<I2c: Instance> I2cBase<I2c> {
|
||||||
($($I2CX:path: ($i2cx:ident, $clk_enb:path),)+) => {
|
pub fn new(
|
||||||
$(
|
syscfg: &mut pac::Sysconfig,
|
||||||
impl I2cBase<$I2CX> {
|
sysclk: impl Into<Hertz>,
|
||||||
pub fn $i2cx(
|
i2c: I2c,
|
||||||
i2c: $I2CX,
|
|
||||||
sys_clk: impl Into<Hertz>,
|
|
||||||
speed_mode: I2cSpeed,
|
speed_mode: I2cSpeed,
|
||||||
ms_cfg: Option<&MasterConfig>,
|
ms_cfg: Option<&MasterConfig>,
|
||||||
sl_cfg: Option<&SlaveConfig>,
|
sl_cfg: Option<&SlaveConfig>,
|
||||||
sys_cfg: Option<&mut va108xx::Sysconfig>,
|
) -> Result<Self, ClockTooSlowForFastI2c> {
|
||||||
) -> Self {
|
enable_peripheral_clock(syscfg, I2c::PERIPH_SEL);
|
||||||
if let Some(sys_cfg) = sys_cfg {
|
|
||||||
enable_peripheral_clock(sys_cfg, $clk_enb);
|
|
||||||
}
|
|
||||||
let mut i2c_base = I2cBase {
|
let mut i2c_base = I2cBase {
|
||||||
i2c,
|
i2c,
|
||||||
sys_clk: sys_clk.into(),
|
sys_clk: sysclk.into(),
|
||||||
};
|
};
|
||||||
if let Some(ms_cfg) = ms_cfg {
|
if let Some(ms_cfg) = ms_cfg {
|
||||||
i2c_base.cfg_master(ms_cfg);
|
i2c_base.cfg_master(ms_cfg);
|
||||||
@ -268,8 +313,8 @@ macro_rules! i2c_base {
|
|||||||
if let Some(sl_cfg) = sl_cfg {
|
if let Some(sl_cfg) = sl_cfg {
|
||||||
i2c_base.cfg_slave(sl_cfg);
|
i2c_base.cfg_slave(sl_cfg);
|
||||||
}
|
}
|
||||||
i2c_base.cfg_clk_scale(speed_mode);
|
i2c_base.cfg_clk_scale(speed_mode)?;
|
||||||
i2c_base
|
Ok(i2c_base)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cfg_master(&mut self, ms_cfg: &MasterConfig) {
|
fn cfg_master(&mut self, ms_cfg: &MasterConfig) {
|
||||||
@ -286,7 +331,9 @@ macro_rules! i2c_base {
|
|||||||
w.algfilter().bit(ms_cfg.alg_filt)
|
w.algfilter().bit(ms_cfg.alg_filt)
|
||||||
});
|
});
|
||||||
if let Some(ref tm_cfg) = ms_cfg.tm_cfg {
|
if let Some(ref tm_cfg) = ms_cfg.tm_cfg {
|
||||||
self.i2c.tmconfig().write(|w| unsafe { w.bits(tm_cfg.reg()) });
|
self.i2c
|
||||||
|
.tmconfig()
|
||||||
|
.write(|w| unsafe { w.bits(tm_cfg.reg()) });
|
||||||
}
|
}
|
||||||
self.i2c.fifo_clr().write(|w| {
|
self.i2c.fifo_clr().write(|w| {
|
||||||
w.rxfifo().set_bit();
|
w.rxfifo().set_bit();
|
||||||
@ -355,19 +402,24 @@ macro_rules! i2c_base {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calc_clk_div(&self, speed_mode: I2cSpeed) -> u8 {
|
fn calc_clk_div(&self, speed_mode: I2cSpeed) -> Result<u8, ClockTooSlowForFastI2c> {
|
||||||
if speed_mode == I2cSpeed::Regular100khz {
|
if speed_mode == I2cSpeed::Regular100khz {
|
||||||
((self.sys_clk.raw() / (u32::pow(10, 5) * 20)) - 1) as u8
|
Ok(((self.sys_clk.raw() / CLK_100K.raw() / 20) - 1) as u8)
|
||||||
} else {
|
} else {
|
||||||
(((10 * self.sys_clk.raw()) / u32::pow(10, 8)) - 1) as u8
|
if self.sys_clk.raw() < MIN_CLK_400K.raw() {
|
||||||
|
return Err(ClockTooSlowForFastI2c);
|
||||||
|
}
|
||||||
|
Ok(((self.sys_clk.raw() / CLK_400K.raw() / 25) - 1) as u8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configures the clock scale for a given speed mode setting
|
/// Configures the clock scale for a given speed mode setting
|
||||||
pub fn cfg_clk_scale(&mut self, speed_mode: I2cSpeed) {
|
pub fn cfg_clk_scale(&mut self, speed_mode: I2cSpeed) -> Result<(), ClockTooSlowForFastI2c> {
|
||||||
self.i2c.clkscale().write(|w| unsafe {
|
let clk_div = self.calc_clk_div(speed_mode)?;
|
||||||
w.bits((speed_mode as u32) << 31 | self.calc_clk_div(speed_mode) as u32)
|
self.i2c
|
||||||
});
|
.clkscale()
|
||||||
|
.write(|w| unsafe { w.bits((speed_mode as u32) << 31 | clk_div as u32) });
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_address(&mut self, addr: u16) {
|
pub fn load_address(&mut self, addr: u16) {
|
||||||
@ -384,9 +436,6 @@ macro_rules! i2c_base {
|
|||||||
.write(|w| unsafe { w.bits(I2cCmd::Stop as u32) });
|
.write(|w| unsafe { w.bits(I2cCmd::Stop as u32) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)+
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unique mode to use the loopback functionality
|
// Unique mode to use the loopback functionality
|
||||||
// pub struct I2cLoopback<I2C> {
|
// pub struct I2cLoopback<I2C> {
|
||||||
@ -395,20 +444,218 @@ macro_rules! i2c_base {
|
|||||||
// slave_cfg: SlaveConfig,
|
// slave_cfg: SlaveConfig,
|
||||||
// }
|
// }
|
||||||
|
|
||||||
i2c_base!(
|
|
||||||
pac::I2ca: (i2ca, PeripheralClocks::I2c0),
|
|
||||||
pac::I2cb: (i2cb, PeripheralClocks::I2c1),
|
|
||||||
);
|
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// I2C Master
|
// I2C Master
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
||||||
pub struct I2cMaster<I2C, ADDR = SevenBitAddress> {
|
pub struct I2cMaster<I2c, Addr = SevenBitAddress> {
|
||||||
i2c_base: I2cBase<I2C>,
|
i2c_base: I2cBase<I2c>,
|
||||||
_addr: PhantomData<ADDR>,
|
addr: PhantomData<Addr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<I2c: Instance, Addr> I2cMaster<I2c, Addr> {
|
||||||
|
pub fn new(
|
||||||
|
syscfg: &mut pac::Sysconfig,
|
||||||
|
sysclk: impl Into<Hertz>,
|
||||||
|
i2c: I2c,
|
||||||
|
cfg: MasterConfig,
|
||||||
|
speed_mode: I2cSpeed,
|
||||||
|
) -> Result<Self, ClockTooSlowForFastI2c> {
|
||||||
|
Ok(I2cMaster {
|
||||||
|
i2c_base: I2cBase::new(syscfg, sysclk, i2c, speed_mode, Some(&cfg), None)?,
|
||||||
|
addr: PhantomData,
|
||||||
|
}
|
||||||
|
.enable_master())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn cancel_transfer(&self) {
|
||||||
|
self.i2c_base
|
||||||
|
.i2c
|
||||||
|
.cmd()
|
||||||
|
.write(|w| unsafe { w.bits(I2cCmd::Cancel as u32) });
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn clear_tx_fifo(&self) {
|
||||||
|
self.i2c_base.i2c.fifo_clr().write(|w| w.txfifo().set_bit());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn clear_rx_fifo(&self) {
|
||||||
|
self.i2c_base.i2c.fifo_clr().write(|w| w.rxfifo().set_bit());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn enable_master(self) -> Self {
|
||||||
|
self.i2c_base.i2c.ctrl().modify(|_, w| w.enable().set_bit());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn disable_master(self) -> Self {
|
||||||
|
self.i2c_base
|
||||||
|
.i2c
|
||||||
|
.ctrl()
|
||||||
|
.modify(|_, w| w.enable().clear_bit());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn load_fifo(&self, word: u8) {
|
||||||
|
self.i2c_base
|
||||||
|
.i2c
|
||||||
|
.data()
|
||||||
|
.write(|w| unsafe { w.bits(word as u32) });
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn read_fifo(&self) -> u8 {
|
||||||
|
self.i2c_base.i2c.data().read().bits() as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
fn error_handler_write(&mut self, init_cmd: &I2cCmd) {
|
||||||
|
self.clear_tx_fifo();
|
||||||
|
if *init_cmd == I2cCmd::Start {
|
||||||
|
self.i2c_base.stop_cmd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_base(
|
||||||
|
&mut self,
|
||||||
|
addr: I2cAddress,
|
||||||
|
init_cmd: I2cCmd,
|
||||||
|
bytes: impl IntoIterator<Item = u8>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let mut iter = bytes.into_iter();
|
||||||
|
// Load address
|
||||||
|
let (addr, addr_mode_bit) = I2cBase::<I2c>::unwrap_addr(addr);
|
||||||
|
self.i2c_base.i2c.address().write(|w| unsafe {
|
||||||
|
w.bits(I2cDirection::Send as u32 | (addr << 1) as u32 | addr_mode_bit)
|
||||||
|
});
|
||||||
|
|
||||||
|
self.i2c_base
|
||||||
|
.i2c
|
||||||
|
.cmd()
|
||||||
|
.write(|w| unsafe { w.bits(init_cmd as u32) });
|
||||||
|
let mut load_if_next_available = || {
|
||||||
|
if let Some(next_byte) = iter.next() {
|
||||||
|
self.load_fifo(next_byte);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
loop {
|
||||||
|
let status_reader = self.i2c_base.i2c.status().read();
|
||||||
|
if status_reader.arblost().bit_is_set() {
|
||||||
|
self.error_handler_write(&init_cmd);
|
||||||
|
return Err(Error::ArbitrationLost);
|
||||||
|
} else if status_reader.nackaddr().bit_is_set() {
|
||||||
|
self.error_handler_write(&init_cmd);
|
||||||
|
return Err(Error::NackAddr);
|
||||||
|
} else if status_reader.nackdata().bit_is_set() {
|
||||||
|
self.error_handler_write(&init_cmd);
|
||||||
|
return Err(Error::NackData);
|
||||||
|
} else if status_reader.idle().bit_is_set() {
|
||||||
|
return Ok(());
|
||||||
|
} else {
|
||||||
|
while !status_reader.txnfull().bit_is_set() {
|
||||||
|
load_if_next_available();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_from_buffer(
|
||||||
|
&mut self,
|
||||||
|
init_cmd: I2cCmd,
|
||||||
|
addr: I2cAddress,
|
||||||
|
output: &[u8],
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let len = output.len();
|
||||||
|
// It should theoretically possible to transfer larger data sizes by tracking
|
||||||
|
// the number of sent words and setting it to 0x7fe as soon as only that many
|
||||||
|
// bytes are remaining. However, large transfer like this are not common. This
|
||||||
|
// feature will therefore not be supported for now.
|
||||||
|
if len > 0x7fe {
|
||||||
|
return Err(Error::DataTooLarge);
|
||||||
|
}
|
||||||
|
// Load number of words
|
||||||
|
self.i2c_base
|
||||||
|
.i2c
|
||||||
|
.words()
|
||||||
|
.write(|w| unsafe { w.bits(len as u32) });
|
||||||
|
let mut bytes = output.iter();
|
||||||
|
// FIFO has a depth of 16. We load slightly above the trigger level
|
||||||
|
// but not all of it because the transaction might fail immediately
|
||||||
|
const FILL_DEPTH: usize = 12;
|
||||||
|
|
||||||
|
// load the FIFO
|
||||||
|
for _ in 0..core::cmp::min(FILL_DEPTH, len) {
|
||||||
|
self.load_fifo(*bytes.next().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
self.write_base(addr, init_cmd, output.iter().cloned())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_internal(&mut self, addr: I2cAddress, buffer: &mut [u8]) -> Result<(), Error> {
|
||||||
|
let len = buffer.len();
|
||||||
|
// It should theoretically possible to transfer larger data sizes by tracking
|
||||||
|
// the number of sent words and setting it to 0x7fe as soon as only that many
|
||||||
|
// bytes are remaining. However, large transfer like this are not common. This
|
||||||
|
// feature will therefore not be supported for now.
|
||||||
|
if len > 0x7fe {
|
||||||
|
return Err(Error::DataTooLarge);
|
||||||
|
}
|
||||||
|
// Clear the receive FIFO
|
||||||
|
self.clear_rx_fifo();
|
||||||
|
|
||||||
|
// Load number of words
|
||||||
|
self.i2c_base
|
||||||
|
.i2c
|
||||||
|
.words()
|
||||||
|
.write(|w| unsafe { w.bits(len as u32) });
|
||||||
|
let (addr, addr_mode_bit) = match addr {
|
||||||
|
I2cAddress::Regular(addr) => (addr as u16, 0 << 15),
|
||||||
|
I2cAddress::TenBit(addr) => (addr, 1 << 15),
|
||||||
|
};
|
||||||
|
// Load address
|
||||||
|
self.i2c_base.i2c.address().write(|w| unsafe {
|
||||||
|
w.bits(I2cDirection::Read as u32 | (addr << 1) as u32 | addr_mode_bit)
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut buf_iter = buffer.iter_mut();
|
||||||
|
let mut read_bytes = 0;
|
||||||
|
// Start receive transfer
|
||||||
|
self.i2c_base
|
||||||
|
.i2c
|
||||||
|
.cmd()
|
||||||
|
.write(|w| unsafe { w.bits(I2cCmd::StartWithStop as u32) });
|
||||||
|
let mut read_if_next_available = || {
|
||||||
|
if let Some(next_byte) = buf_iter.next() {
|
||||||
|
*next_byte = self.read_fifo();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
loop {
|
||||||
|
let status_reader = self.i2c_base.i2c.status().read();
|
||||||
|
if status_reader.arblost().bit_is_set() {
|
||||||
|
self.clear_rx_fifo();
|
||||||
|
return Err(Error::ArbitrationLost);
|
||||||
|
} else if status_reader.nackaddr().bit_is_set() {
|
||||||
|
self.clear_rx_fifo();
|
||||||
|
return Err(Error::NackAddr);
|
||||||
|
} else if status_reader.idle().bit_is_set() {
|
||||||
|
if read_bytes != len {
|
||||||
|
return Err(Error::InsufficientDataReceived);
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
} else if status_reader.rxnempty().bit_is_set() {
|
||||||
|
read_if_next_available();
|
||||||
|
read_bytes += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
macro_rules! i2c_master {
|
macro_rules! i2c_master {
|
||||||
($($I2CX:path: ($i2cx:ident, $clk_enb:path),)+) => {
|
($($I2CX:path: ($i2cx:ident, $clk_enb:path),)+) => {
|
||||||
$(
|
$(
|
||||||
@ -675,39 +922,80 @@ i2c_master!(
|
|||||||
pac::I2ca: (i2ca, PeripheralClocks::I2c0),
|
pac::I2ca: (i2ca, PeripheralClocks::I2c0),
|
||||||
pac::I2cb: (i2cb, PeripheralClocks::I2c1),
|
pac::I2cb: (i2cb, PeripheralClocks::I2c1),
|
||||||
);
|
);
|
||||||
|
*/
|
||||||
|
|
||||||
|
//======================================================================================
|
||||||
|
// Embedded HAL I2C implementations
|
||||||
|
//======================================================================================
|
||||||
|
|
||||||
|
impl<I2c> embedded_hal::i2c::ErrorType for I2cMaster<I2c, SevenBitAddress> {
|
||||||
|
type Error = Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I2c: Instance> embedded_hal::i2c::I2c for I2cMaster<I2c, SevenBitAddress> {
|
||||||
|
fn transaction(
|
||||||
|
&mut self,
|
||||||
|
address: SevenBitAddress,
|
||||||
|
operations: &mut [Operation<'_>],
|
||||||
|
) -> Result<(), Self::Error> {
|
||||||
|
for operation in operations {
|
||||||
|
match operation {
|
||||||
|
Operation::Read(buf) => self.read_internal(I2cAddress::Regular(address), buf)?,
|
||||||
|
Operation::Write(buf) => self.write_from_buffer(
|
||||||
|
I2cCmd::StartWithStop,
|
||||||
|
I2cAddress::Regular(address),
|
||||||
|
buf,
|
||||||
|
)?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I2c> embedded_hal::i2c::ErrorType for I2cMaster<I2c, TenBitAddress> {
|
||||||
|
type Error = Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I2c: Instance> embedded_hal::i2c::I2c<TenBitAddress> for I2cMaster<I2c, TenBitAddress> {
|
||||||
|
fn transaction(
|
||||||
|
&mut self,
|
||||||
|
address: TenBitAddress,
|
||||||
|
operations: &mut [Operation<'_>],
|
||||||
|
) -> Result<(), Self::Error> {
|
||||||
|
for operation in operations {
|
||||||
|
match operation {
|
||||||
|
Operation::Read(buf) => self.read_internal(I2cAddress::TenBit(address), buf)?,
|
||||||
|
Operation::Write(buf) => {
|
||||||
|
self.write_from_buffer(I2cCmd::StartWithStop, I2cAddress::TenBit(address), buf)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// I2C Slave
|
// I2C Slave
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
||||||
pub struct I2cSlave<I2C, ADDR = SevenBitAddress> {
|
pub struct I2cSlave<I2c, Addr = SevenBitAddress> {
|
||||||
i2c_base: I2cBase<I2C>,
|
i2c_base: I2cBase<I2c>,
|
||||||
_addr: PhantomData<ADDR>,
|
addr: PhantomData<Addr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! i2c_slave {
|
impl<I2c: Instance, Addr> I2cSlave<I2c, Addr> {
|
||||||
($($I2CX:path: ($i2cx:ident, $i2cx_slave:ident),)+) => {
|
fn new_generic(
|
||||||
$(
|
sys_cfg: &mut pac::Sysconfig,
|
||||||
impl<ADDR> I2cSlave<$I2CX, ADDR> {
|
|
||||||
fn $i2cx_slave(
|
|
||||||
i2c: $I2CX,
|
|
||||||
cfg: SlaveConfig,
|
|
||||||
sys_clk: impl Into<Hertz>,
|
sys_clk: impl Into<Hertz>,
|
||||||
|
i2c: I2c,
|
||||||
|
cfg: SlaveConfig,
|
||||||
speed_mode: I2cSpeed,
|
speed_mode: I2cSpeed,
|
||||||
sys_cfg: Option<&mut pac::Sysconfig>,
|
) -> Result<Self, ClockTooSlowForFastI2c> {
|
||||||
) -> Self {
|
Ok(I2cSlave {
|
||||||
I2cSlave {
|
i2c_base: I2cBase::new(sys_cfg, sys_clk, i2c, speed_mode, None, Some(&cfg))?,
|
||||||
i2c_base: I2cBase::$i2cx(
|
addr: PhantomData,
|
||||||
i2c,
|
|
||||||
sys_clk,
|
|
||||||
speed_mode,
|
|
||||||
None,
|
|
||||||
Some(&cfg),
|
|
||||||
sys_cfg
|
|
||||||
),
|
|
||||||
_addr: PhantomData,
|
|
||||||
}
|
}
|
||||||
.enable_slave()
|
.enable_slave())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -841,38 +1129,30 @@ macro_rules! i2c_slave {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<I2c: Instance> I2cSlave<I2c, SevenBitAddress> {
|
||||||
impl I2cSlave<$I2CX, SevenBitAddress> {
|
|
||||||
/// Create a new I2C slave for seven bit addresses
|
/// Create a new I2C slave for seven bit addresses
|
||||||
///
|
pub fn new(
|
||||||
/// Returns a [`Error::WrongAddrMode`] error if a ten bit address is passed
|
sys_cfg: &mut pac::Sysconfig,
|
||||||
pub fn i2ca(
|
|
||||||
i2c: $I2CX,
|
|
||||||
cfg: SlaveConfig,
|
|
||||||
sys_clk: impl Into<Hertz>,
|
sys_clk: impl Into<Hertz>,
|
||||||
|
i2c: I2c,
|
||||||
|
cfg: SlaveConfig,
|
||||||
speed_mode: I2cSpeed,
|
speed_mode: I2cSpeed,
|
||||||
sys_cfg: Option<&mut pac::Sysconfig>,
|
) -> Result<Self, InitError> {
|
||||||
) -> Result<Self, Error> {
|
|
||||||
if let I2cAddress::TenBit(_) = cfg.addr {
|
if let I2cAddress::TenBit(_) = cfg.addr {
|
||||||
return Err(Error::WrongAddrMode);
|
return Err(InitError::WrongAddrMode);
|
||||||
}
|
}
|
||||||
Ok(Self::$i2cx_slave(i2c, cfg, sys_clk, speed_mode, sys_cfg))
|
Ok(Self::new_generic(sys_cfg, sys_clk, i2c, cfg, speed_mode)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl I2cSlave<$I2CX, TenBitAddress> {
|
impl<I2c: Instance> I2cSlave<I2c, TenBitAddress> {
|
||||||
pub fn $i2cx(
|
pub fn new_ten_bit_addr(
|
||||||
i2c: $I2CX,
|
sys_cfg: &mut pac::Sysconfig,
|
||||||
cfg: SlaveConfig,
|
|
||||||
sys_clk: impl Into<Hertz>,
|
sys_clk: impl Into<Hertz>,
|
||||||
|
i2c: I2c,
|
||||||
|
cfg: SlaveConfig,
|
||||||
speed_mode: I2cSpeed,
|
speed_mode: I2cSpeed,
|
||||||
sys_cfg: Option<&mut pac::Sysconfig>,
|
) -> Result<Self, ClockTooSlowForFastI2c> {
|
||||||
) -> Self {
|
Self::new_generic(sys_cfg, sys_clk, i2c, cfg, speed_mode)
|
||||||
Self::$i2cx_slave(i2c, cfg, sys_clk, speed_mode, sys_cfg)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)+
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
i2c_slave!(pac::I2ca: (i2ca, i2ca_slave), pac::I2cb: (i2cb, i2cb_slave),);
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
//! Prelude
|
//! Prelude
|
||||||
pub use fugit::ExtU32 as _;
|
pub use fugit::ExtU32 as _;
|
||||||
pub use fugit::RateExtU32 as _;
|
pub use fugit::RateExtU32 as _;
|
||||||
|
|
||||||
|
pub use crate::time::*;
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
//!
|
//!
|
||||||
//! ## Examples
|
//! ## Examples
|
||||||
//!
|
//!
|
||||||
//! - [PWM example](https://egit.irs.uni-stuttgart.de/rust/va108xx-hal/src/branch/main/examples/pwm.rs)
|
//! - [PWM example](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/examples/simple/examples/pwm.rs)
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
@ -158,9 +158,9 @@ where
|
|||||||
{
|
{
|
||||||
/// Create a new stronlgy typed PWM pin
|
/// Create a new stronlgy typed PWM pin
|
||||||
pub fn new(
|
pub fn new(
|
||||||
vtp: (Pin, Tim),
|
|
||||||
sys_clk: impl Into<Hertz> + Copy,
|
|
||||||
sys_cfg: &mut pac::Sysconfig,
|
sys_cfg: &mut pac::Sysconfig,
|
||||||
|
sys_clk: impl Into<Hertz> + Copy,
|
||||||
|
tim_and_pin: (Pin, Tim),
|
||||||
initial_period: impl Into<Hertz> + Copy,
|
initial_period: impl Into<Hertz> + Copy,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut pin = PwmPin {
|
let mut pin = PwmPin {
|
||||||
@ -171,7 +171,7 @@ where
|
|||||||
current_rst_val: 0,
|
current_rst_val: 0,
|
||||||
sys_clk: sys_clk.into(),
|
sys_clk: sys_clk.into(),
|
||||||
},
|
},
|
||||||
reg: unsafe { TimAndPinRegister::new(vtp.0, vtp.1) },
|
reg: unsafe { TimAndPinRegister::new(tim_and_pin.0, tim_and_pin.1) },
|
||||||
mode: PhantomData,
|
mode: PhantomData,
|
||||||
};
|
};
|
||||||
enable_peripheral_clock(sys_cfg, crate::clock::PeripheralClocks::Gpio);
|
enable_peripheral_clock(sys_cfg, crate::clock::PeripheralClocks::Gpio);
|
||||||
@ -225,12 +225,13 @@ where
|
|||||||
(Pin, Tim): ValidTimAndPin<Pin, Tim>,
|
(Pin, Tim): ValidTimAndPin<Pin, Tim>,
|
||||||
{
|
{
|
||||||
pub fn pwma(
|
pub fn pwma(
|
||||||
vtp: (Pin, Tim),
|
|
||||||
sys_clk: impl Into<Hertz> + Copy,
|
|
||||||
sys_cfg: &mut pac::Sysconfig,
|
sys_cfg: &mut pac::Sysconfig,
|
||||||
|
sys_clk: impl Into<Hertz> + Copy,
|
||||||
|
pin_and_tim: (Pin, Tim),
|
||||||
initial_period: impl Into<Hertz> + Copy,
|
initial_period: impl Into<Hertz> + Copy,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut pin: PwmPin<Pin, Tim, PwmA> = Self::new(vtp, sys_clk, sys_cfg, initial_period);
|
let mut pin: PwmPin<Pin, Tim, PwmA> =
|
||||||
|
Self::new(sys_cfg, sys_clk, pin_and_tim, initial_period);
|
||||||
pin.enable_pwm_a();
|
pin.enable_pwm_a();
|
||||||
pin
|
pin
|
||||||
}
|
}
|
||||||
@ -241,12 +242,13 @@ where
|
|||||||
(Pin, Tim): ValidTimAndPin<Pin, Tim>,
|
(Pin, Tim): ValidTimAndPin<Pin, Tim>,
|
||||||
{
|
{
|
||||||
pub fn pwmb(
|
pub fn pwmb(
|
||||||
vtp: (Pin, Tim),
|
|
||||||
sys_clk: impl Into<Hertz> + Copy,
|
|
||||||
sys_cfg: &mut pac::Sysconfig,
|
sys_cfg: &mut pac::Sysconfig,
|
||||||
|
sys_clk: impl Into<Hertz> + Copy,
|
||||||
|
pin_and_tim: (Pin, Tim),
|
||||||
initial_period: impl Into<Hertz> + Copy,
|
initial_period: impl Into<Hertz> + Copy,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut pin: PwmPin<Pin, Tim, PwmB> = Self::new(vtp, sys_clk, sys_cfg, initial_period);
|
let mut pin: PwmPin<Pin, Tim, PwmB> =
|
||||||
|
Self::new(sys_cfg, sys_clk, pin_and_tim, initial_period);
|
||||||
pin.enable_pwm_b();
|
pin.enable_pwm_b();
|
||||||
pin
|
pin
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -11,14 +11,15 @@ use libm::floorf;
|
|||||||
|
|
||||||
pub use crate::IrqCfg;
|
pub use crate::IrqCfg;
|
||||||
use crate::{
|
use crate::{
|
||||||
clock::{self, enable_peripheral_clock, PeripheralClocks},
|
clock::{enable_peripheral_clock, PeripheralClocks},
|
||||||
gpio::pins::{
|
gpio::pin::{
|
||||||
AltFunc1, AltFunc2, AltFunc3, Pin, PA16, PA17, PA18, PA19, PA2, PA26, PA27, PA3, PA30,
|
AltFunc1, AltFunc2, AltFunc3, Pin, PA16, PA17, PA18, PA19, PA2, PA26, PA27, PA3, PA30,
|
||||||
PA31, PA8, PA9, PB18, PB19, PB20, PB21, PB22, PB23, PB6, PB7, PB8, PB9,
|
PA31, PA8, PA9, PB18, PB19, PB20, PB21, PB22, PB23, PB6, PB7, PB8, PB9,
|
||||||
},
|
},
|
||||||
pac::{self, uarta as uart_base},
|
pac::{self, uarta as uart_base},
|
||||||
time::Hertz,
|
time::Hertz,
|
||||||
utility::unmask_irq,
|
utility::unmask_irq,
|
||||||
|
PeripheralSelect,
|
||||||
};
|
};
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
@ -306,7 +307,7 @@ pub struct UartBase<Uart> {
|
|||||||
}
|
}
|
||||||
/// Serial abstraction. Entry point to create a new UART
|
/// Serial abstraction. Entry point to create a new UART
|
||||||
pub struct Uart<Uart, Pins> {
|
pub struct Uart<Uart, Pins> {
|
||||||
uart_base: UartBase<Uart>,
|
inner: UartBase<Uart>,
|
||||||
pins: Pins,
|
pins: Pins,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,6 +354,7 @@ impl<UART> Tx<UART> {
|
|||||||
pub trait Instance: Deref<Target = uart_base::RegisterBlock> {
|
pub trait Instance: Deref<Target = uart_base::RegisterBlock> {
|
||||||
fn ptr() -> *const uart_base::RegisterBlock;
|
fn ptr() -> *const uart_base::RegisterBlock;
|
||||||
const IDX: u8;
|
const IDX: u8;
|
||||||
|
const PERIPH_SEL: PeripheralSelect;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<UART: Instance> UartBase<UART> {
|
impl<UART: Instance> UartBase<UART> {
|
||||||
@ -483,14 +485,34 @@ impl<UART: Instance> UartBase<UART> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<UART, PINS> Uart<UART, PINS>
|
impl<UartInstance, PinsInstance> Uart<UartInstance, PinsInstance>
|
||||||
where
|
where
|
||||||
UART: Instance,
|
UartInstance: Instance,
|
||||||
|
PinsInstance: Pins<UartInstance>,
|
||||||
{
|
{
|
||||||
|
pub fn new(
|
||||||
|
syscfg: &mut va108xx::Sysconfig,
|
||||||
|
sys_clk: impl Into<Hertz>,
|
||||||
|
uart: UartInstance,
|
||||||
|
pins: PinsInstance,
|
||||||
|
config: impl Into<Config>,
|
||||||
|
) -> Self {
|
||||||
|
crate::clock::enable_peripheral_clock(syscfg, UartInstance::PERIPH_SEL);
|
||||||
|
Uart {
|
||||||
|
inner: UartBase {
|
||||||
|
uart,
|
||||||
|
tx: Tx::new(),
|
||||||
|
rx: Rx::new(),
|
||||||
|
},
|
||||||
|
pins,
|
||||||
|
}
|
||||||
|
.init(config.into(), sys_clk.into())
|
||||||
|
}
|
||||||
|
|
||||||
/// This function assumes that the peripheral clock was alredy enabled
|
/// This function assumes that the peripheral clock was alredy enabled
|
||||||
/// in the SYSCONFIG register
|
/// in the SYSCONFIG register
|
||||||
fn init(mut self, config: Config, sys_clk: Hertz) -> Self {
|
fn init(mut self, config: Config, sys_clk: Hertz) -> Self {
|
||||||
self.uart_base = self.uart_base.init(config, sys_clk);
|
self.inner = self.inner.init(config, sys_clk);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -501,7 +523,7 @@ where
|
|||||||
irq_cfg: IrqCfg,
|
irq_cfg: IrqCfg,
|
||||||
sys_cfg: Option<&mut pac::Sysconfig>,
|
sys_cfg: Option<&mut pac::Sysconfig>,
|
||||||
irq_sel: Option<&mut pac::Irqsel>,
|
irq_sel: Option<&mut pac::Irqsel>,
|
||||||
) -> UartWithIrq<UART, PINS> {
|
) -> UartWithIrq<UartInstance, PinsInstance> {
|
||||||
let (uart, pins) = self.downgrade_internal();
|
let (uart, pins) = self.downgrade_internal();
|
||||||
UartWithIrq {
|
UartWithIrq {
|
||||||
pins,
|
pins,
|
||||||
@ -520,75 +542,75 @@ where
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn enable_rx(&mut self) {
|
pub fn enable_rx(&mut self) {
|
||||||
self.uart_base.enable_rx();
|
self.inner.enable_rx();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn disable_rx(&mut self) {
|
pub fn disable_rx(&mut self) {
|
||||||
self.uart_base.enable_rx();
|
self.inner.enable_rx();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn enable_tx(&mut self) {
|
pub fn enable_tx(&mut self) {
|
||||||
self.uart_base.enable_tx();
|
self.inner.enable_tx();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn disable_tx(&mut self) {
|
pub fn disable_tx(&mut self) {
|
||||||
self.uart_base.disable_tx();
|
self.inner.disable_tx();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn clear_rx_fifo(&mut self) {
|
pub fn clear_rx_fifo(&mut self) {
|
||||||
self.uart_base.clear_rx_fifo();
|
self.inner.clear_rx_fifo();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn clear_tx_fifo(&mut self) {
|
pub fn clear_tx_fifo(&mut self) {
|
||||||
self.uart_base.clear_tx_fifo();
|
self.inner.clear_tx_fifo();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn clear_rx_status(&mut self) {
|
pub fn clear_rx_status(&mut self) {
|
||||||
self.uart_base.clear_rx_status();
|
self.inner.clear_rx_status();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn clear_tx_status(&mut self) {
|
pub fn clear_tx_status(&mut self) {
|
||||||
self.uart_base.clear_tx_status();
|
self.inner.clear_tx_status();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn listen(&self, event: Event) {
|
pub fn listen(&self, event: Event) {
|
||||||
self.uart_base.listen(event);
|
self.inner.listen(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unlisten(&self, event: Event) {
|
pub fn unlisten(&self, event: Event) {
|
||||||
self.uart_base.unlisten(event);
|
self.inner.unlisten(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn release(self) -> (UART, PINS) {
|
pub fn release(self) -> (UartInstance, PinsInstance) {
|
||||||
(self.uart_base.release(), self.pins)
|
(self.inner.release(), self.pins)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn downgrade_internal(self) -> (UartBase<UART>, PINS) {
|
fn downgrade_internal(self) -> (UartBase<UartInstance>, PinsInstance) {
|
||||||
let base = UartBase {
|
let base = UartBase {
|
||||||
uart: self.uart_base.uart,
|
uart: self.inner.uart,
|
||||||
tx: self.uart_base.tx,
|
tx: self.inner.tx,
|
||||||
rx: self.uart_base.rx,
|
rx: self.inner.rx,
|
||||||
};
|
};
|
||||||
(base, self.pins)
|
(base, self.pins)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn downgrade(self) -> UartBase<UART> {
|
pub fn downgrade(self) -> UartBase<UartInstance> {
|
||||||
UartBase {
|
UartBase {
|
||||||
uart: self.uart_base.uart,
|
uart: self.inner.uart,
|
||||||
tx: self.uart_base.tx,
|
tx: self.inner.tx,
|
||||||
rx: self.uart_base.rx,
|
rx: self.inner.rx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn split(self) -> (Tx<UART>, Rx<UART>) {
|
pub fn split(self) -> (Tx<UartInstance>, Rx<UartInstance>) {
|
||||||
self.uart_base.split()
|
self.inner.split()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -597,6 +619,8 @@ impl Instance for pac::Uarta {
|
|||||||
pac::Uarta::ptr() as *const _
|
pac::Uarta::ptr() as *const _
|
||||||
}
|
}
|
||||||
const IDX: u8 = 0;
|
const IDX: u8 = 0;
|
||||||
|
|
||||||
|
const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Uart0;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Instance for pac::Uartb {
|
impl Instance for pac::Uartb {
|
||||||
@ -604,36 +628,8 @@ impl Instance for pac::Uartb {
|
|||||||
pac::Uartb::ptr() as *const _
|
pac::Uartb::ptr() as *const _
|
||||||
}
|
}
|
||||||
const IDX: u8 = 1;
|
const IDX: u8 = 1;
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! uart_impl {
|
const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Uart1;
|
||||||
($($UARTX:path: ($uartx:ident, $clk_enb_enum:path),)+) => {
|
|
||||||
$(
|
|
||||||
|
|
||||||
impl<PINS: Pins<$UARTX>> Uart<$UARTX, PINS> {
|
|
||||||
pub fn $uartx(
|
|
||||||
uart: $UARTX,
|
|
||||||
pins: PINS,
|
|
||||||
config: impl Into<Config>,
|
|
||||||
syscfg: &mut pac::Sysconfig,
|
|
||||||
sys_clk: impl Into<Hertz>
|
|
||||||
) -> Self
|
|
||||||
{
|
|
||||||
enable_peripheral_clock(syscfg, $clk_enb_enum);
|
|
||||||
Uart {
|
|
||||||
uart_base: UartBase {
|
|
||||||
uart,
|
|
||||||
tx: Tx::new(),
|
|
||||||
rx: Rx::new(),
|
|
||||||
},
|
|
||||||
pins,
|
|
||||||
}
|
|
||||||
.init(config.into(), sys_clk.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
)+
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<UART: Instance> UartWithIrqBase<UART> {
|
impl<UART: Instance> UartWithIrqBase<UART> {
|
||||||
@ -871,10 +867,12 @@ impl<UART: Instance, PINS> UartWithIrq<UART, PINS> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
uart_impl! {
|
uart_impl! {
|
||||||
pac::Uarta: (uarta, clock::PeripheralClocks::Uart0),
|
pac::Uarta: (uarta, clock::PeripheralClocks::Uart0),
|
||||||
pac::Uartb: (uartb, clock::PeripheralClocks::Uart1),
|
pac::Uartb: (uartb, clock::PeripheralClocks::Uart1),
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
impl<Uart> Tx<Uart> where Uart: Instance {}
|
impl<Uart> Tx<Uart> where Uart: Instance {}
|
||||||
|
|
||||||
|
@ -19,14 +19,14 @@ embedded-hal = "1"
|
|||||||
version = "0.3"
|
version = "0.3"
|
||||||
|
|
||||||
[dependencies.va108xx-hal]
|
[dependencies.va108xx-hal]
|
||||||
version = "0.6"
|
path = "../va108xx-hal"
|
||||||
|
version = "0.7"
|
||||||
features = ["rt"]
|
features = ["rt"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
rt = ["va108xx-hal/rt"]
|
rt = ["va108xx-hal/rt"]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
cortex-m-rtic = "1.1"
|
|
||||||
panic-halt = "0.2"
|
panic-halt = "0.2"
|
||||||
nb = "1"
|
nb = "1"
|
||||||
|
|
||||||
@ -36,6 +36,14 @@ version = "0.5"
|
|||||||
[dev-dependencies.panic-rtt-target]
|
[dev-dependencies.panic-rtt-target]
|
||||||
version = "0.1"
|
version = "0.1"
|
||||||
|
|
||||||
|
[dev-dependencies.rtic]
|
||||||
|
version = "2"
|
||||||
|
features = ["thumbv6-backend"]
|
||||||
|
|
||||||
|
[dev-dependencies.rtic-monotonics]
|
||||||
|
version = "1"
|
||||||
|
features = ["cortex-m-systick"]
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
rustdoc-args = ["--generate-link-to-definition"]
|
rustdoc-args = ["--generate-link-to-definition"]
|
||||||
|
@ -13,7 +13,7 @@ fn main() -> ! {
|
|||||||
rprintln!("-- Vorago Temperature Sensor and I2C Example --");
|
rprintln!("-- Vorago Temperature Sensor and I2C Example --");
|
||||||
let mut dp = pac::Peripherals::take().unwrap();
|
let mut dp = pac::Peripherals::take().unwrap();
|
||||||
let mut delay = set_up_ms_delay_provider(&mut dp.sysconfig, 50.MHz(), dp.tim0);
|
let mut delay = set_up_ms_delay_provider(&mut dp.sysconfig, 50.MHz(), dp.tim0);
|
||||||
let mut temp_sensor = Adt75TempSensor::new(dp.i2ca, 50.MHz(), Some(&mut dp.sysconfig))
|
let mut temp_sensor = Adt75TempSensor::new(&mut dp.sysconfig, 50.MHz(), dp.i2ca)
|
||||||
.expect("Creating temperature sensor struct failed");
|
.expect("Creating temperature sensor struct failed");
|
||||||
loop {
|
loop {
|
||||||
let temp = temp_sensor
|
let temp = temp_sensor
|
||||||
|
@ -52,12 +52,12 @@ fn main() -> ! {
|
|||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
let mut spi = Spi::spib(
|
let mut spi = Spi::new(
|
||||||
|
&mut dp.sysconfig,
|
||||||
|
50.MHz(),
|
||||||
dp.spib,
|
dp.spib,
|
||||||
(sck, miso, mosi),
|
(sck, miso, mosi),
|
||||||
50.MHz(),
|
|
||||||
spi_cfg,
|
spi_cfg,
|
||||||
Some(&mut dp.sysconfig),
|
|
||||||
Some(&transfer_cfg.downgrade()),
|
Some(&transfer_cfg.downgrade()),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#[rtic::app(device = pac)]
|
#[rtic::app(device = pac)]
|
||||||
mod app {
|
mod app {
|
||||||
use panic_rtt_target as _;
|
use panic_rtt_target as _;
|
||||||
|
use rtic_monotonics::systick::Systick;
|
||||||
use rtt_target::{rprintln, rtt_init_default, set_print_channel};
|
use rtt_target::{rprintln, rtt_init_default, set_print_channel};
|
||||||
use va108xx_hal::{
|
use va108xx_hal::{
|
||||||
clock::{set_clk_div_register, FilterClkSel},
|
clock::{set_clk_div_register, FilterClkSel},
|
||||||
@ -43,10 +44,18 @@ mod app {
|
|||||||
struct Shared {}
|
struct Shared {}
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) {
|
fn init(ctx: init::Context) -> (Shared, Local) {
|
||||||
let channels = rtt_init_default!();
|
let channels = rtt_init_default!();
|
||||||
set_print_channel(channels.up.0);
|
set_print_channel(channels.up.0);
|
||||||
rprintln!("-- Vorago Button IRQ Example --");
|
rprintln!("-- Vorago Button IRQ Example --");
|
||||||
|
// Initialize the systick interrupt & obtain the token to prove that we did
|
||||||
|
let systick_mono_token = rtic_monotonics::create_systick_token!();
|
||||||
|
Systick::start(
|
||||||
|
ctx.core.SYST,
|
||||||
|
Hertz::from(50.MHz()).raw(),
|
||||||
|
systick_mono_token,
|
||||||
|
);
|
||||||
|
|
||||||
let mode = match CFG_MODE {
|
let mode = match CFG_MODE {
|
||||||
// Ask mode from user via RTT
|
// Ask mode from user via RTT
|
||||||
CfgMode::Prompt => prompt_mode(channels.down.0),
|
CfgMode::Prompt => prompt_mode(channels.down.0),
|
||||||
@ -90,7 +99,7 @@ mod app {
|
|||||||
50.MHz(),
|
50.MHz(),
|
||||||
dp.tim0,
|
dp.tim0,
|
||||||
);
|
);
|
||||||
(Shared {}, Local { leds, button, mode }, init::Monotonics())
|
(Shared {}, Local { leds, button, mode })
|
||||||
}
|
}
|
||||||
|
|
||||||
// `shared` cannot be accessed from this context
|
// `shared` cannot be accessed from this context
|
||||||
|
@ -10,7 +10,7 @@ use cortex_m_rt::entry;
|
|||||||
use embedded_hal::delay::DelayNs;
|
use embedded_hal::delay::DelayNs;
|
||||||
use embedded_hal::digital::{OutputPin, StatefulOutputPin};
|
use embedded_hal::digital::{OutputPin, StatefulOutputPin};
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
use va108xx_hal::{gpio::pins::PinsA, pac, prelude::*, timer::set_up_ms_delay_provider};
|
use va108xx_hal::{gpio::PinsA, pac, prelude::*, timer::set_up_ms_delay_provider};
|
||||||
use vorago_reb1::leds::Leds;
|
use vorago_reb1::leds::Leds;
|
||||||
|
|
||||||
// REB LED pin definitions. All on port A
|
// REB LED pin definitions. All on port A
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
//! MAX11619 ADC example applikcation
|
//! MAX11619 ADC example application.
|
||||||
|
//!
|
||||||
|
//! You can turn the potentiometer knob of the REB1 board to measure
|
||||||
|
//! different ADC values.
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
@ -139,12 +142,12 @@ fn main() -> ! {
|
|||||||
.expect("Setting accelerometer chip select high failed");
|
.expect("Setting accelerometer chip select high failed");
|
||||||
|
|
||||||
let transfer_cfg = TransferConfig::<NoneT>::new(3.MHz(), spi::MODE_0, None, true, false);
|
let transfer_cfg = TransferConfig::<NoneT>::new(3.MHz(), spi::MODE_0, None, true, false);
|
||||||
let spi = Spi::spib(
|
let spi = Spi::new(
|
||||||
|
&mut dp.sysconfig,
|
||||||
|
50.MHz(),
|
||||||
dp.spib,
|
dp.spib,
|
||||||
(sck, miso, mosi),
|
(sck, miso, mosi),
|
||||||
50.MHz(),
|
|
||||||
spi_cfg,
|
spi_cfg,
|
||||||
Some(&mut dp.sysconfig),
|
|
||||||
Some(&transfer_cfg.downgrade()),
|
Some(&transfer_cfg.downgrade()),
|
||||||
)
|
)
|
||||||
.downgrade();
|
.downgrade();
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
//!
|
//!
|
||||||
//! ## Examples
|
//! ## Examples
|
||||||
//!
|
//!
|
||||||
//! - [Button Blinky with IRQs](https://egit.irs.uni-stuttgart.de/rust/vorago-reb1/src/branch/main/examples/blinky-button-irq.rs)
|
//! - [Button Blinky with IRQs](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/vorago-reb1/examples/blinky-button-irq.rs)
|
||||||
//! - [Button Blinky with IRQs and RTIC](https://egit.irs.uni-stuttgart.de/rust/vorago-reb1/src/branch/main/examples/blinky-button-rtic.rs)
|
//! - [Button Blinky with IRQs and RTIC](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/vorago-reb1/examples/blinky-button-rtic.rs)
|
||||||
use embedded_hal::digital::InputPin;
|
use embedded_hal::digital::InputPin;
|
||||||
use va108xx_hal::{
|
use va108xx_hal::{
|
||||||
gpio::{FilterClkSel, FilterType, InputFloating, InterruptEdge, InterruptLevel, Pin, PA11},
|
gpio::{FilterClkSel, FilterType, InputFloating, InterruptEdge, InterruptLevel, Pin, PA11},
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
//!
|
//!
|
||||||
//! ## Examples
|
//! ## Examples
|
||||||
//!
|
//!
|
||||||
//! - [LED example](https://egit.irs.uni-stuttgart.de/rust/vorago-reb1/src/branch/main/examples/blinky-leds.rs)
|
//! - [LED example](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/vorago-reb1/examples/blinky-leds.rs)
|
||||||
//! - [Button Blinky using IRQs](https://egit.irs.uni-stuttgart.de/rust/vorago-reb1/src/branch/main/examples/blinky-button-irq.rs)
|
//! - [Button Blinky using IRQs](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/vorago-reb1/examples/blinky-button-irq.rs)
|
||||||
//! - [Button Blinky using IRQs and RTIC](https://egit.irs.uni-stuttgart.de/rust/vorago-reb1/src/branch/main/examples/blinky-button-rtic.rs)
|
//! - [Button Blinky using IRQs and RTIC](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/vorago-reb1/examples/blinky-button-rtic.rs)
|
||||||
use embedded_hal::digital::OutputPin;
|
use embedded_hal::digital::OutputPin;
|
||||||
use va108xx_hal::{
|
use va108xx_hal::{
|
||||||
gpio::dynpins::DynPin,
|
gpio::dynpin::DynPin,
|
||||||
gpio::pins::{Pin, PushPullOutput, PA10, PA6, PA7},
|
gpio::pin::{Pin, PushPullOutput, PA10, PA6, PA7},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type LD2 = Pin<PA10, PushPullOutput>;
|
pub type LD2 = Pin<PA10, PushPullOutput>;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
//!
|
//!
|
||||||
//! ## Examples
|
//! ## Examples
|
||||||
//!
|
//!
|
||||||
//! - [ADC example](https://egit.irs.uni-stuttgart.de/rust/vorago-reb1/src/branch/main/examples/max11619-adc.rs)
|
//! - [ADC example](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/vorago-reb1/examples/max11619-adc.rs)
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
use embedded_hal::spi::SpiDevice;
|
use embedded_hal::spi::SpiDevice;
|
||||||
use max116xx_10bit::{
|
use max116xx_10bit::{
|
||||||
|
@ -4,10 +4,10 @@
|
|||||||
//!
|
//!
|
||||||
//! ## Examples
|
//! ## Examples
|
||||||
//!
|
//!
|
||||||
//! - [Temperature Sensor example](https://egit.irs.uni-stuttgart.de/rust/vorago-reb1/src/branch/main/examples/adt75-temp-sensor.rs)
|
//! - [Temperature Sensor example](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/vorago-reb1/examples/adt75-temp-sensor.rs
|
||||||
use embedded_hal::i2c::{I2c, SevenBitAddress};
|
use embedded_hal::i2c::{I2c, SevenBitAddress};
|
||||||
use va108xx_hal::{
|
use va108xx_hal::{
|
||||||
i2c::{Error, I2cMaster, I2cSpeed, MasterConfig},
|
i2c::{Error, I2cMaster, I2cSpeed, InitError, MasterConfig},
|
||||||
pac,
|
pac,
|
||||||
time::Hertz,
|
time::Hertz,
|
||||||
};
|
};
|
||||||
@ -29,20 +29,40 @@ pub enum RegAddresses {
|
|||||||
OneShot = 0x04,
|
OneShot = 0x04,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum AdtInitError {
|
||||||
|
Init(InitError),
|
||||||
|
I2c(Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<InitError> for AdtInitError {
|
||||||
|
fn from(value: InitError) -> Self {
|
||||||
|
Self::Init(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Error> for AdtInitError {
|
||||||
|
fn from(value: Error) -> Self {
|
||||||
|
Self::I2c(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Adt75TempSensor {
|
impl Adt75TempSensor {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
i2ca: pac::I2ca,
|
sys_cfg: &mut pac::Sysconfig,
|
||||||
sys_clk: impl Into<Hertz> + Copy,
|
sys_clk: impl Into<Hertz> + Copy,
|
||||||
sys_cfg: Option<&mut pac::Sysconfig>,
|
i2ca: pac::I2ca,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let mut sensor = Adt75TempSensor {
|
let mut sensor = Adt75TempSensor {
|
||||||
sensor_if: I2cMaster::i2ca(
|
// The master construction can not fail for regular I2C speed.
|
||||||
|
sensor_if: I2cMaster::new(
|
||||||
|
sys_cfg,
|
||||||
|
sys_clk,
|
||||||
i2ca,
|
i2ca,
|
||||||
MasterConfig::default(),
|
MasterConfig::default(),
|
||||||
sys_clk,
|
|
||||||
I2cSpeed::Regular100khz,
|
I2cSpeed::Regular100khz,
|
||||||
sys_cfg,
|
)
|
||||||
),
|
.unwrap(),
|
||||||
cmd_buf: [RegAddresses::Temperature as u8],
|
cmd_buf: [RegAddresses::Temperature as u8],
|
||||||
current_reg: RegAddresses::Temperature,
|
current_reg: RegAddresses::Temperature,
|
||||||
};
|
};
|
||||||
|
@ -18,6 +18,17 @@
|
|||||||
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/blinky-leds",
|
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/blinky-leds",
|
||||||
"interface": "jtag",
|
"interface": "jtag",
|
||||||
"runToEntryPoint": "main",
|
"runToEntryPoint": "main",
|
||||||
|
"rttConfig": {
|
||||||
|
"enabled": true,
|
||||||
|
"address": "0x10000000",
|
||||||
|
"decoders": [
|
||||||
|
{
|
||||||
|
"port": 0,
|
||||||
|
"timestamp": true,
|
||||||
|
"type": "console"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "cortex-debug",
|
"type": "cortex-debug",
|
||||||
@ -28,9 +39,20 @@
|
|||||||
"device": "Cortex-M0",
|
"device": "Cortex-M0",
|
||||||
"svdFile": "./va108xx/svd/va108xx.svd.patched",
|
"svdFile": "./va108xx/svd/va108xx.svd.patched",
|
||||||
"preLaunchTask": "rust: cargo build hal tests",
|
"preLaunchTask": "rust: cargo build hal tests",
|
||||||
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/tests",
|
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/board-tests",
|
||||||
"interface": "jtag",
|
"interface": "jtag",
|
||||||
"runToEntryPoint": "main",
|
"runToEntryPoint": "main",
|
||||||
|
"rttConfig": {
|
||||||
|
"enabled": true,
|
||||||
|
"address": "0x10000000",
|
||||||
|
"decoders": [
|
||||||
|
{
|
||||||
|
"port": 0,
|
||||||
|
"timestamp": true,
|
||||||
|
"type": "console"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "cortex-debug",
|
"type": "cortex-debug",
|
||||||
@ -44,6 +66,17 @@
|
|||||||
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/rtt-log",
|
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/rtt-log",
|
||||||
"interface": "jtag",
|
"interface": "jtag",
|
||||||
"runToEntryPoint": "main",
|
"runToEntryPoint": "main",
|
||||||
|
"rttConfig": {
|
||||||
|
"enabled": true,
|
||||||
|
"address": "0x10000000",
|
||||||
|
"decoders": [
|
||||||
|
{
|
||||||
|
"port": 0,
|
||||||
|
"timestamp": true,
|
||||||
|
"type": "console"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "cortex-debug",
|
"type": "cortex-debug",
|
||||||
@ -57,6 +90,17 @@
|
|||||||
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/blinky-button-irq",
|
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/blinky-button-irq",
|
||||||
"interface": "jtag",
|
"interface": "jtag",
|
||||||
"runToEntryPoint": "main",
|
"runToEntryPoint": "main",
|
||||||
|
"rttConfig": {
|
||||||
|
"enabled": true,
|
||||||
|
"address": "0x10000000",
|
||||||
|
"decoders": [
|
||||||
|
{
|
||||||
|
"port": 0,
|
||||||
|
"timestamp": true,
|
||||||
|
"type": "console"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "cortex-debug",
|
"type": "cortex-debug",
|
||||||
@ -70,6 +114,17 @@
|
|||||||
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/timer-ticks",
|
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/timer-ticks",
|
||||||
"interface": "jtag",
|
"interface": "jtag",
|
||||||
"runToEntryPoint": "main",
|
"runToEntryPoint": "main",
|
||||||
|
"rttConfig": {
|
||||||
|
"enabled": true,
|
||||||
|
"address": "0x10000000",
|
||||||
|
"decoders": [
|
||||||
|
{
|
||||||
|
"port": 0,
|
||||||
|
"timestamp": true,
|
||||||
|
"type": "console"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "cortex-debug",
|
"type": "cortex-debug",
|
||||||
@ -83,6 +138,17 @@
|
|||||||
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/uart",
|
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/uart",
|
||||||
"interface": "jtag",
|
"interface": "jtag",
|
||||||
"runToEntryPoint": "main",
|
"runToEntryPoint": "main",
|
||||||
|
"rttConfig": {
|
||||||
|
"enabled": true,
|
||||||
|
"address": "0x10000000",
|
||||||
|
"decoders": [
|
||||||
|
{
|
||||||
|
"port": 0,
|
||||||
|
"timestamp": true,
|
||||||
|
"type": "console"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "cortex-debug",
|
"type": "cortex-debug",
|
||||||
@ -96,6 +162,17 @@
|
|||||||
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/spi",
|
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/spi",
|
||||||
"interface": "jtag",
|
"interface": "jtag",
|
||||||
"runToEntryPoint": "main",
|
"runToEntryPoint": "main",
|
||||||
|
"rttConfig": {
|
||||||
|
"enabled": true,
|
||||||
|
"address": "0x10000000",
|
||||||
|
"decoders": [
|
||||||
|
{
|
||||||
|
"port": 0,
|
||||||
|
"timestamp": true,
|
||||||
|
"type": "console"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "cortex-debug",
|
"type": "cortex-debug",
|
||||||
@ -109,11 +186,22 @@
|
|||||||
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/adt75-temp-sensor",
|
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/adt75-temp-sensor",
|
||||||
"interface": "jtag",
|
"interface": "jtag",
|
||||||
"runToEntryPoint": "main",
|
"runToEntryPoint": "main",
|
||||||
|
"rttConfig": {
|
||||||
|
"enabled": true,
|
||||||
|
"address": "0x10000000",
|
||||||
|
"decoders": [
|
||||||
|
{
|
||||||
|
"port": 0,
|
||||||
|
"timestamp": true,
|
||||||
|
"type": "console"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "cortex-debug",
|
"type": "cortex-debug",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Debug Button Blinky RTIC",
|
"name": "Button Blinky RTIC Example",
|
||||||
"servertype": "jlink",
|
"servertype": "jlink",
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"device": "Cortex-M0",
|
"device": "Cortex-M0",
|
||||||
@ -122,11 +210,22 @@
|
|||||||
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/blinky-button-rtic",
|
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/blinky-button-rtic",
|
||||||
"interface": "jtag",
|
"interface": "jtag",
|
||||||
"runToEntryPoint": "main",
|
"runToEntryPoint": "main",
|
||||||
|
"rttConfig": {
|
||||||
|
"enabled": true,
|
||||||
|
"address": "0x10000000",
|
||||||
|
"decoders": [
|
||||||
|
{
|
||||||
|
"port": 0,
|
||||||
|
"timestamp": true,
|
||||||
|
"type": "console"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "cortex-debug",
|
"type": "cortex-debug",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Debug PWM",
|
"name": "PWM Example",
|
||||||
"servertype": "jlink",
|
"servertype": "jlink",
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"device": "Cortex-M0",
|
"device": "Cortex-M0",
|
||||||
@ -135,11 +234,22 @@
|
|||||||
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/pwm",
|
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/pwm",
|
||||||
"interface": "jtag",
|
"interface": "jtag",
|
||||||
"runToEntryPoint": "main",
|
"runToEntryPoint": "main",
|
||||||
|
"rttConfig": {
|
||||||
|
"enabled": true,
|
||||||
|
"address": "0x10000000",
|
||||||
|
"decoders": [
|
||||||
|
{
|
||||||
|
"port": 0,
|
||||||
|
"timestamp": true,
|
||||||
|
"type": "console"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "cortex-debug",
|
"type": "cortex-debug",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Debug Cascade",
|
"name": "Cascade Example",
|
||||||
"servertype": "jlink",
|
"servertype": "jlink",
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"device": "Cortex-M0",
|
"device": "Cortex-M0",
|
||||||
@ -148,11 +258,22 @@
|
|||||||
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/cascade",
|
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/cascade",
|
||||||
"interface": "jtag",
|
"interface": "jtag",
|
||||||
"runToEntryPoint": "main",
|
"runToEntryPoint": "main",
|
||||||
|
"rttConfig": {
|
||||||
|
"enabled": true,
|
||||||
|
"address": "0x10000000",
|
||||||
|
"decoders": [
|
||||||
|
{
|
||||||
|
"port": 0,
|
||||||
|
"timestamp": true,
|
||||||
|
"type": "console"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "cortex-debug",
|
"type": "cortex-debug",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Debug Accelerometer",
|
"name": "Accelerometer Example",
|
||||||
"servertype": "jlink",
|
"servertype": "jlink",
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"device": "Cortex-M0",
|
"device": "Cortex-M0",
|
||||||
@ -161,6 +282,17 @@
|
|||||||
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/adxl343-accelerometer",
|
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/adxl343-accelerometer",
|
||||||
"interface": "jtag",
|
"interface": "jtag",
|
||||||
"runToEntryPoint": "main",
|
"runToEntryPoint": "main",
|
||||||
|
"rttConfig": {
|
||||||
|
"enabled": true,
|
||||||
|
"address": "0x10000000",
|
||||||
|
"decoders": [
|
||||||
|
{
|
||||||
|
"port": 0,
|
||||||
|
"timestamp": true,
|
||||||
|
"type": "console"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "cortex-debug",
|
"type": "cortex-debug",
|
||||||
@ -178,7 +310,7 @@
|
|||||||
{
|
{
|
||||||
"type": "cortex-debug",
|
"type": "cortex-debug",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Debug ADC",
|
"name": "ADC Example",
|
||||||
"servertype": "jlink",
|
"servertype": "jlink",
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"device": "Cortex-M0",
|
"device": "Cortex-M0",
|
||||||
@ -187,11 +319,22 @@
|
|||||||
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/max11619-adc",
|
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/max11619-adc",
|
||||||
"interface": "jtag",
|
"interface": "jtag",
|
||||||
"runToEntryPoint": "main",
|
"runToEntryPoint": "main",
|
||||||
|
"rttConfig": {
|
||||||
|
"enabled": true,
|
||||||
|
"address": "0x10000000",
|
||||||
|
"decoders": [
|
||||||
|
{
|
||||||
|
"port": 0,
|
||||||
|
"timestamp": true,
|
||||||
|
"type": "console"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "cortex-debug",
|
"type": "cortex-debug",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Debug UART IRQ",
|
"name": "UART IRQ Example",
|
||||||
"servertype": "jlink",
|
"servertype": "jlink",
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"device": "Cortex-M0",
|
"device": "Cortex-M0",
|
||||||
@ -200,6 +343,17 @@
|
|||||||
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/uart-irq-rtic",
|
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/examples/uart-irq-rtic",
|
||||||
"interface": "jtag",
|
"interface": "jtag",
|
||||||
"runToEntryPoint": "main",
|
"runToEntryPoint": "main",
|
||||||
|
"rttConfig": {
|
||||||
|
"enabled": true,
|
||||||
|
"address": "0x10000000",
|
||||||
|
"decoders": [
|
||||||
|
{
|
||||||
|
"port": 0,
|
||||||
|
"timestamp": true,
|
||||||
|
"type": "console"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -21,10 +21,8 @@
|
|||||||
"command": "~/.cargo/bin/cargo", // note: full path to the cargo
|
"command": "~/.cargo/bin/cargo", // note: full path to the cargo
|
||||||
"args": [
|
"args": [
|
||||||
"build",
|
"build",
|
||||||
"-p",
|
|
||||||
"va108xx-hal",
|
|
||||||
"--bin",
|
"--bin",
|
||||||
"tests",
|
"board-tests",
|
||||||
"--features",
|
"--features",
|
||||||
"rt"
|
"rt"
|
||||||
],
|
],
|
||||||
@ -39,8 +37,6 @@
|
|||||||
"command": "~/.cargo/bin/cargo", // note: full path to the cargo
|
"command": "~/.cargo/bin/cargo", // note: full path to the cargo
|
||||||
"args": [
|
"args": [
|
||||||
"build",
|
"build",
|
||||||
"-p",
|
|
||||||
"va108xx-hal",
|
|
||||||
"--example",
|
"--example",
|
||||||
"rtt-log",
|
"rtt-log",
|
||||||
],
|
],
|
||||||
@ -55,8 +51,6 @@
|
|||||||
"command": "~/.cargo/bin/cargo", // note: full path to the cargo
|
"command": "~/.cargo/bin/cargo", // note: full path to the cargo
|
||||||
"args": [
|
"args": [
|
||||||
"build",
|
"build",
|
||||||
"-p",
|
|
||||||
"va108xx-hal",
|
|
||||||
"--example",
|
"--example",
|
||||||
"timer-ticks",
|
"timer-ticks",
|
||||||
"--features",
|
"--features",
|
||||||
@ -89,8 +83,6 @@
|
|||||||
"command": "~/.cargo/bin/cargo", // note: full path to the cargo
|
"command": "~/.cargo/bin/cargo", // note: full path to the cargo
|
||||||
"args": [
|
"args": [
|
||||||
"build",
|
"build",
|
||||||
"-p",
|
|
||||||
"va108xx-hal",
|
|
||||||
"--example",
|
"--example",
|
||||||
"spi",
|
"spi",
|
||||||
],
|
],
|
||||||
@ -105,8 +97,6 @@
|
|||||||
"command": "~/.cargo/bin/cargo", // note: full path to the cargo
|
"command": "~/.cargo/bin/cargo", // note: full path to the cargo
|
||||||
"args": [
|
"args": [
|
||||||
"build",
|
"build",
|
||||||
"-p",
|
|
||||||
"va108xx-hal",
|
|
||||||
"--example",
|
"--example",
|
||||||
"pwm",
|
"pwm",
|
||||||
"--features",
|
"--features",
|
||||||
@ -123,8 +113,6 @@
|
|||||||
"command": "~/.cargo/bin/cargo", // note: full path to the cargo
|
"command": "~/.cargo/bin/cargo", // note: full path to the cargo
|
||||||
"args": [
|
"args": [
|
||||||
"build",
|
"build",
|
||||||
"-p",
|
|
||||||
"va108xx-hal",
|
|
||||||
"--example",
|
"--example",
|
||||||
"cascade",
|
"cascade",
|
||||||
"--features",
|
"--features",
|
||||||
@ -141,8 +129,6 @@
|
|||||||
"command": "~/.cargo/bin/cargo", // note: full path to the cargo
|
"command": "~/.cargo/bin/cargo", // note: full path to the cargo
|
||||||
"args": [
|
"args": [
|
||||||
"build",
|
"build",
|
||||||
"-p",
|
|
||||||
"va108xx-hal",
|
|
||||||
"--example",
|
"--example",
|
||||||
"uart-irq-rtic",
|
"uart-irq-rtic",
|
||||||
"--features",
|
"--features",
|
||||||
|
Loading…
Reference in New Issue
Block a user