13 Commits

15 changed files with 154 additions and 89 deletions

View File

@ -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 = [

View File

@ -14,6 +14,8 @@ This workspace contains the following released crates:
crate containing basic low-level register definition. crate containing basic low-level register definition.
- The [`va108xx-hal`](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/va108xx-hal) - The [`va108xx-hal`](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/va108xx-hal)
HAL crate containing higher-level abstractions on top of the PAC register crate. HAL crate containing higher-level abstractions on top of the PAC register crate.
- The [`va108xx-embassy`](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/va108xx-embassy)
crate containing support for running the embassy-rs RTOS.
- The [`vorago-reb1`](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/vorago-reb1) - The [`vorago-reb1`](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/vorago-reb1)
BSP crate containing support for the REB1 development board. BSP crate containing support for the REB1 development board.
@ -58,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://github.com/probe-rs/probe-rs) 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 --example 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
@ -99,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.

View File

@ -15,10 +15,12 @@ num_enum = { version = "0.7", default-features = false }
static_assertions = "1" static_assertions = "1"
[dependencies.va108xx-hal] [dependencies.va108xx-hal]
path = "../va108xx-hal" version = "0.9"
# path = "../va108xx-hal"
[dependencies.vorago-reb1] [dependencies.vorago-reb1]
path = "../vorago-reb1" version = "0.7"
# path = "../vorago-reb1"
[features] [features]
default = [] default = []

View File

@ -27,8 +27,8 @@ embassy-executor = { version = "0.7", features = [
"executor-interrupt" "executor-interrupt"
]} ]}
va108xx-hal = { path = "../../va108xx-hal" } va108xx-hal = "0.9"
va108xx-embassy = { path = "../../va108xx-embassy", default-features = false } va108xx-embassy = "0.1"
[features] [features]
default = ["ticks-hz-1_000", "va108xx-embassy/irq-oc30-oc31"] default = ["ticks-hz-1_000", "va108xx-embassy/irq-oc30-oc31"]

View File

@ -22,5 +22,5 @@ rtic-sync = { version = "1.3", features = ["defmt-03"] }
once_cell = {version = "1", default-features = false, features = ["critical-section"]} once_cell = {version = "1", default-features = false, features = ["critical-section"]}
ringbuf = { version = "0.4.7", default-features = false, features = ["portable-atomic"] } ringbuf = { version = "0.4.7", default-features = false, features = ["portable-atomic"] }
va108xx-hal = { version = "0.9", path = "../../va108xx-hal" } va108xx-hal = "0.9"
vorago-reb1 = { path = "../../vorago-reb1" } vorago-reb1 = "0.7"

View File

@ -16,9 +16,8 @@ embedded-io = "0.6"
cortex-m-semihosting = "0.5.0" cortex-m-semihosting = "0.5.0"
[dependencies.va108xx-hal] [dependencies.va108xx-hal]
path = "../../va108xx-hal"
version = "0.9" version = "0.9"
features = ["rt", "defmt"] features = ["rt", "defmt"]
[dependencies.vorago-reb1] [dependencies.vorago-reb1]
path = "../../vorago-reb1" version = "0.7"

View File

@ -29,7 +29,9 @@ rtic-monotonics = { version = "2", features = ["cortex-m-systick"] }
rtic-sync = {version = "1", features = ["defmt-03"]} rtic-sync = {version = "1", features = ["defmt-03"]}
[dependencies.va108xx-hal] [dependencies.va108xx-hal]
path = "../va108xx-hal" version = "0.9"
# path = "../va108xx-hal"
[dependencies.vorago-reb1] [dependencies.vorago-reb1]
path = "../vorago-reb1" version = "0.7"
# path = "../vorago-reb1"

View File

@ -0,0 +1,17 @@
Change Log
=======
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [unreleased]
## [v0.1.2] and [v0.1.1] 2025-02-13
Docs patch
## [v0.1.0] 2025-02-13
Initial release

View File

@ -1,11 +1,17 @@
[package] [package]
name = "va108xx-embassy" name = "va108xx-embassy"
version = "0.1.0" version = "0.1.2"
edition = "2021" edition = "2021"
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
description = "Embassy-rs support for the Vorago VA108xx family of microcontrollers"
homepage = "https://egit.irs.uni-stuttgart.de/rust/va108xx-rs"
repository = "https://egit.irs.uni-stuttgart.de/rust/va108xx-rs"
license = "Apache-2.0"
keywords = ["no-std", "hal", "cortex-m", "vorago", "va108xx"]
categories = ["aerospace", "embedded", "no-std", "hardware-support"]
[dependencies] [dependencies]
critical-section = "1" critical-section = "1"
portable-atomic = { version = "1", features = ["unsafe-assume-single-core"]}
embassy-sync = "0.6" embassy-sync = "0.6"
embassy-executor = "0.7" embassy-executor = "0.7"
@ -14,8 +20,12 @@ embassy-time-queue-utils = "0.1"
once_cell = { version = "1", default-features = false, features = ["critical-section"] } once_cell = { version = "1", default-features = false, features = ["critical-section"] }
[dependencies.va108xx-hal] va108xx-hal = "0.9"
path = "../va108xx-hal"
[target.'cfg(all(target_arch = "arm", target_os = "none"))'.dependencies]
portable-atomic = { version = "1", features = ["unsafe-assume-single-core"] }
[target.'cfg(not(all(target_arch = "arm", target_os = "none")))'.dependencies]
portable-atomic = "1"
[features] [features]
default = ["irq-oc30-oc31"] default = ["irq-oc30-oc31"]
@ -25,3 +35,6 @@ irqs-in-lib = []
irq-oc28-oc29 = ["irqs-in-lib"] irq-oc28-oc29 = ["irqs-in-lib"]
irq-oc29-oc30 = ["irqs-in-lib"] irq-oc29-oc30 = ["irqs-in-lib"]
irq-oc30-oc31 = ["irqs-in-lib"] irq-oc30-oc31 = ["irqs-in-lib"]
[package.metadata.docs.rs]
rustdoc-args = ["--generate-link-to-definition"]

3
va108xx-embassy/docs.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash
export RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options"
cargo +nightly doc --open

View File

@ -23,17 +23,17 @@
//! //!
//! You can disable the default features and then specify one of the features above to use the //! You can disable the default features and then specify one of the features above to use the
//! documented combination of IRQs. It is also possible to specify custom IRQs by importing and //! documented combination of IRQs. It is also possible to specify custom IRQs by importing and
//! using the [embassy::embassy_time_driver_irqs] macro to declare the IRQ handlers in the //! using the [embassy_time_driver_irqs] macro to declare the IRQ handlers in the
//! application code. If this is done, [embassy::init_with_custom_irqs] must be used //! application code. If this is done, [embassy::init_with_custom_irqs] must be used
//! method to pass the IRQ numbers to the library. //! method to pass the IRQ numbers to the library.
//! //!
//! ## Examples //! ## Examples
//! //!
//! [embassy example project](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/examples/embassy) //! [embassy example projects](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/examples/embassy)
#![no_std] #![no_std]
#![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};
@ -45,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,
}; };
@ -62,7 +62,7 @@ time_driver_impl!(
/// the feature flags specified. However, the macro is exported to allow users to specify the /// the feature flags specified. However, the macro is exported to allow users to specify the
/// interrupt handlers themselves. /// interrupt handlers themselves.
/// ///
/// Please note that you have to explicitely import the [va108xx_hal::pac::interrupt] /// Please note that you have to explicitely import the [macro@va108xx_hal::pac::interrupt]
/// macro in the application code in case this macro is used there. /// macro in the application code in case this macro is used there.
#[macro_export] #[macro_export]
macro_rules! embassy_time_driver_irqs { macro_rules! embassy_time_driver_irqs {
@ -115,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,
@ -139,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,
) { ) {
@ -187,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();

View File

@ -8,6 +8,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [unreleased] ## [unreleased]
## [v0.7.0] 2025-02-13
- Bumped `va108xx-hal` dependency to 0.9
- Minor adjustments to `Button` API.
- `Button`, `Led` and `Leds` now simply wrap a type using a tuple struct.
## [v0.6.0] 2024-09-30 ## [v0.6.0] 2024-09-30
- Added M95M01 EEPROM module/API - Added M95M01 EEPROM module/API

View File

@ -1,6 +1,6 @@
[package] [package]
name = "vorago-reb1" name = "vorago-reb1"
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 = "Board Support Crate for the Vorago REB1 development board" description = "Board Support Crate for the Vorago REB1 development board"
@ -19,7 +19,6 @@ bitfield = ">=0.17, <=0.18"
max116xx-10bit = "0.3" max116xx-10bit = "0.3"
[dependencies.va108xx-hal] [dependencies.va108xx-hal]
path = "../va108xx-hal"
version = "0.9" version = "0.9"
features = ["rt"] features = ["rt"]

View File

@ -11,23 +11,21 @@ use va108xx_hal::{
}; };
#[derive(Debug)] #[derive(Debug)]
pub struct Button { pub struct Button(pub Pin<PA11, InputFloating>);
button: Pin<PA11, InputFloating>,
}
impl Button { impl Button {
pub fn new(pin: Pin<PA11, InputFloating>) -> Button { pub fn new(pin: Pin<PA11, InputFloating>) -> Button {
Button { button: pin } Button(pin)
} }
#[inline] #[inline]
pub fn pressed(&mut self) -> bool { pub fn pressed(&mut self) -> bool {
self.button.is_low().ok().unwrap() self.0.is_low().ok().unwrap()
} }
#[inline] #[inline]
pub fn released(&mut self) -> bool { pub fn released(&mut self) -> bool {
self.button.is_high().ok().unwrap() self.0.is_high().ok().unwrap()
} }
/// Configures an IRQ on edge. /// Configures an IRQ on edge.
@ -38,7 +36,7 @@ impl Button {
syscfg: Option<&mut pac::Sysconfig>, syscfg: Option<&mut pac::Sysconfig>,
irqsel: Option<&mut pac::Irqsel>, irqsel: Option<&mut pac::Irqsel>,
) { ) {
self.button self.0
.configure_edge_interrupt(edge_type, irq_cfg, syscfg, irqsel); .configure_edge_interrupt(edge_type, irq_cfg, syscfg, irqsel);
} }
@ -50,7 +48,7 @@ impl Button {
syscfg: Option<&mut pac::Sysconfig>, syscfg: Option<&mut pac::Sysconfig>,
irqsel: Option<&mut pac::Irqsel>, irqsel: Option<&mut pac::Irqsel>,
) { ) {
self.button self.0
.configure_level_interrupt(level, irq_cfg, syscfg, irqsel); .configure_level_interrupt(level, irq_cfg, syscfg, irqsel);
} }
@ -59,6 +57,6 @@ impl Button {
/// Please note that you still have to set a clock divisor yourself using the /// Please note that you still have to set a clock divisor yourself using the
/// [`va108xx_hal::clock::set_clk_div_register`] function in order for this to work. /// [`va108xx_hal::clock::set_clk_div_register`] function in order for this to work.
pub fn configure_filter_type(&mut self, filter: FilterType, clksel: FilterClkSel) { pub fn configure_filter_type(&mut self, filter: FilterType, clksel: FilterClkSel) {
self.button.configure_filter_type(filter, clksel); self.0.configure_filter_type(filter, clksel);
} }
} }

View File

@ -15,15 +15,12 @@ pub type LD2 = Pin<PA10, PushPullOutput>;
pub type LD3 = Pin<PA7, PushPullOutput>; pub type LD3 = Pin<PA7, PushPullOutput>;
pub type LD4 = Pin<PA6, PushPullOutput>; pub type LD4 = Pin<PA6, PushPullOutput>;
pub struct Leds { #[derive(Debug)]
leds: [Led; 3], pub struct Leds(pub [Led; 3]);
}
impl Leds { impl Leds {
pub fn new(led_pin1: LD2, led_pin2: LD3, led_pin3: LD4) -> Leds { pub fn new(led_pin1: LD2, led_pin2: LD3, led_pin3: LD4) -> Leds {
Leds { Leds([led_pin1.into(), led_pin2.into(), led_pin3.into()])
leds: [led_pin1.into(), led_pin2.into(), led_pin3.into()],
}
} }
} }
@ -31,13 +28,13 @@ impl core::ops::Deref for Leds {
type Target = [Led]; type Target = [Led];
fn deref(&self) -> &[Led] { fn deref(&self) -> &[Led] {
&self.leds &self.0
} }
} }
impl core::ops::DerefMut for Leds { impl core::ops::DerefMut for Leds {
fn deref_mut(&mut self) -> &mut [Led] { fn deref_mut(&mut self) -> &mut [Led] {
&mut self.leds &mut self.0
} }
} }
@ -45,28 +42,25 @@ impl core::ops::Index<usize> for Leds {
type Output = Led; type Output = Led;
fn index(&self, i: usize) -> &Led { fn index(&self, i: usize) -> &Led {
&self.leds[i] &self.0[i]
} }
} }
impl core::ops::IndexMut<usize> for Leds { impl core::ops::IndexMut<usize> for Leds {
fn index_mut(&mut self, i: usize) -> &mut Led { fn index_mut(&mut self, i: usize) -> &mut Led {
&mut self.leds[i] &mut self.0[i]
} }
} }
pub struct Led { #[derive(Debug)]
pin: DynPin, pub struct Led(pub DynPin);
}
macro_rules! ctor { macro_rules! ctor {
($($ldx:ident),+) => { ($($ldx:ident),+) => {
$( $(
impl From<$ldx> for Led { impl From<$ldx> for Led {
fn from(led: $ldx) -> Self { fn from(led: $ldx) -> Self {
Led { Led(led.into())
pin: led.into()
}
} }
} }
)+ )+
@ -79,18 +73,18 @@ impl Led {
/// Turns the LED off. Setting the pin high actually turns the LED off /// Turns the LED off. Setting the pin high actually turns the LED off
#[inline] #[inline]
pub fn off(&mut self) { pub fn off(&mut self) {
self.pin.set_high().ok(); self.0.set_high().ok();
} }
/// Turns the LED on. Setting the pin low actually turns the LED on /// Turns the LED on. Setting the pin low actually turns the LED on
#[inline] #[inline]
pub fn on(&mut self) { pub fn on(&mut self) {
self.pin.set_low().ok(); self.0.set_low().ok();
} }
/// Toggles the LED /// Toggles the LED
#[inline] #[inline]
pub fn toggle(&mut self) { pub fn toggle(&mut self) {
self.pin.toggle_with_toggle_reg().ok(); self.0.toggle_with_toggle_reg().ok();
} }
} }