28 Commits

Author SHA1 Message Date
99631dbd03 va108xx v0.4.0: Regnerate PAC 2025-02-12 14:04:56 +01:00
698ed3a700 Merge pull request 'dynpin bugfix' (#34) from bugfix-dynpin into main
Reviewed-on: #34
2025-02-12 13:41:34 +01:00
f3d840ace7 dynpin bugfix 2025-02-12 13:41:06 +01:00
f781505ec5 Merge pull request 'Asynchronous GPIO support' (#30) from async-gpio into main
Reviewed-on: #30
2025-02-11 18:56:28 +01:00
c6e840a991 Asynchronous GPIO support 2025-02-11 18:56:11 +01:00
454635a473 Merge pull request 'update error handling' (#31) from update-error-types into main
Reviewed-on: #31
2025-02-11 16:19:47 +01:00
67ddba9c42 update error handling 2025-02-11 16:19:20 +01:00
6efc902e02 Merge pull request 'disable the unittests' (#32) from disable-empty-unittests into main
Reviewed-on: #32
2025-02-11 16:18:31 +01:00
b6e9a7f68e disable the unittests 2025-02-10 17:13:03 +01:00
6842e06bc6 Merge pull request 'Update for va108xx' (#28) from update-deps-add-embassy-lib into main
Reviewed-on: #28
2025-02-10 11:42:03 +01:00
5b614e1280 Update for va108xx
- New `va108xx-embassy` crate.
- Embassy library uses new crate
- Updated all dependencies

va108xx-hal

- Refactored and simplified PWM driver
- Added new raw getter API for TIM peripheral blocks
2025-02-10 11:40:37 +01:00
16e5a5f197 Merge pull request 'GPIO refactoring and API improvements' (#27) from gpio-refactoring into main
Reviewed-on: #27
2025-02-10 11:36:45 +01:00
da1f2902b2 GPIO refactoring and API improvements 2025-02-10 11:35:20 +01:00
b2d17e10ed Merge pull request 'bootloader tweak' (#26) from bootloader-tweak into main
Reviewed-on: #26
2025-01-14 10:30:08 +01:00
1412e1b7d1 bootloader tweak 2025-01-14 01:21:20 +01:00
88ee85a4cd Merge pull request 'new update for ringbuf' (#25) from update-for-ringbuf into main
Reviewed-on: #25
2025-01-11 11:39:59 +01:00
4b318ecc76 new update for ringbuf 2025-01-11 11:38:04 +01:00
badeea8071 Merge pull request 'fix memory x file' (#24) from fix-memory-x-file into main
Reviewed-on: #24
2025-01-10 17:49:45 +01:00
c95558ff55 Merge branch 'main' into fix-memory-x-file 2025-01-10 17:49:38 +01:00
cd222fd1e1 Merge pull request 'some clippy fixes' (#23) from some-clippy-fixes into main
Reviewed-on: #23
2025-01-10 17:49:20 +01:00
f438e7e40f some clippy fixes 2025-01-10 17:19:28 +01:00
9e547668c2 fix memory x file 2025-01-10 16:38:17 +01:00
cf55fe1504 Merge pull request 'bootloader and flashloader update' (#22) from bootloader-flashloader-update into main
Reviewed-on: #22
2025-01-10 16:31:39 +01:00
74eebdcc03 bootloader and flashloader update 2025-01-10 16:31:15 +01:00
35527f092a Merge pull request 'update probe-rs files' (#21) from probe-rs-update into main
Reviewed-on: #21
2024-11-26 10:23:37 +01:00
c6314f48d7 update probe-rs files 2024-11-26 10:23:27 +01:00
7189cb246b Merge pull request 'delete some more re-exports' (#20) from delete-some-re-exports into main
All checks were successful
Rust/va108xx-rs/pipeline/head This commit looks good
Reviewed-on: #20
2024-10-07 09:48:13 +02:00
39b8633065 delete some more re-exports
All checks were successful
Rust/va108xx-rs/pipeline/head This commit looks good
2024-10-07 09:47:24 +02:00
185 changed files with 2829 additions and 2172 deletions

View File

@ -10,8 +10,8 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
with:
targets: "thumbv6m-none-eabi"
- run: cargo check --target thumbv6m-none-eabi --release
- run: cargo check --target thumbv6m-none-eabi --examples --release
- run: cargo check --target thumbv6m-none-eabi
- run: cargo check --target thumbv6m-none-eabi --examples
test:
name: Run Tests
@ -21,7 +21,9 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
- name: Install nextest
uses: taiki-e/install-action@nextest
- run: cargo nextest run --all-features -p va108xx-hal
# There is not a single test, and the tests are brittle because some dependencies do not
# like being run on general purpose machines..
# - run: cargo nextest run --all-features -p va108xx-hal --no-tests=pass
# I think we can skip those on an embedded crate..
# - run: cargo test --doc -p va108xx-hal

2
.gitignore vendored
View File

@ -16,3 +16,5 @@ Cargo.lock
# JetBrains IDEs
/.idea
*.iml
/Embed.toml

View File

@ -1,9 +1,10 @@
[workspace]
resolver = "2"
members = [
"vorago-reb1",
"va108xx",
"va108xx-hal",
"vorago-reb1",
"va108xx",
"va108xx-hal",
"va108xx-embassy",
"examples/simple",
"examples/rtic",
"examples/embassy",
@ -22,7 +23,7 @@ codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
# 1 instead of 0, the flashloader is too larger otherwise..
# 1 instead of 0, the flashloader is too larger otherwise..
# opt-level = 1 # <-
overflow-checks = true # <-

12
Embed.toml.sample Normal file
View File

@ -0,0 +1,12 @@
[default.probe]
protocol = "Jtag"
[default.general]
chip = "VA108xx_RAM"
[default.rtt]
enabled = true
[default.gdb]
# Whether or not a GDB server should be opened after flashing.
enabled = false

View File

@ -6,9 +6,9 @@ edition = "2021"
[dependencies]
cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7"
panic-halt = "0.2"
rtt-target = "0.5"
panic-rtt-target = "0.1.3"
panic-halt = "1"
rtt-target = "0.6"
panic-rtt-target = "0.2"
embedded-hal = "1"
embedded-hal-nb = "1"
embedded-io = "0.6"

View File

@ -44,8 +44,8 @@ fn main() -> ! {
rprintln!("-- VA108xx Test Application --");
let mut dp = pac::Peripherals::take().unwrap();
let cp = cortex_m::Peripherals::take().unwrap();
let pinsa = PinsA::new(&mut dp.sysconfig, None, dp.porta);
let pinsb = PinsB::new(&mut dp.sysconfig, Some(dp.ioconfig), dp.portb);
let pinsa = PinsA::new(&mut dp.sysconfig, dp.porta);
let pinsb = PinsB::new(&mut dp.sysconfig, dp.portb);
let mut led1 = pinsa.pa10.into_readable_push_pull_output();
let test_case = TestCase::DelayMs;
@ -99,9 +99,11 @@ fn main() -> ! {
}
TestCase::TestMask => {
// Tie PORTA[0] to PORTA[1] for these tests!
let input = pinsa.pa1.into_pull_down_input().clear_datamask();
let mut input = pinsa.pa1.into_pull_down_input();
input.clear_datamask();
assert!(!input.datamask());
let mut out = pinsa.pa0.into_push_pull_output().clear_datamask();
let mut out = pinsa.pa0.into_push_pull_output();
out.clear_datamask();
assert!(input.is_low_masked().is_err());
assert!(out.set_high_masked().is_err());
}
@ -119,17 +121,15 @@ fn main() -> ! {
assert_eq!(PinsB::get_perid(), 0x004007e1);
}
TestCase::Pulse => {
let mut output_pulsed = pinsa
.pa0
.into_push_pull_output()
.pulse_mode(true, PinState::Low);
let mut output_pulsed = pinsa.pa0.into_push_pull_output();
output_pulsed.pulse_mode(true, PinState::Low);
rprintln!("Pulsing high 10 times..");
output_pulsed.set_low().unwrap();
for _ in 0..10 {
output_pulsed.set_high().unwrap();
cortex_m::asm::delay(25_000_000);
}
let mut output_pulsed = output_pulsed.pulse_mode(true, PinState::High);
output_pulsed.pulse_mode(true, PinState::High);
rprintln!("Pulsing low 10 times..");
for _ in 0..10 {
output_pulsed.set_low().unwrap();

View File

@ -7,10 +7,11 @@ edition = "2021"
cortex-m = "0.7"
cortex-m-rt = "0.7"
embedded-hal = "1"
panic-rtt-target = { version = "0.1.3" }
panic-halt = { version = "0.2" }
rtt-target = { version = "0.5" }
panic-rtt-target = "0.2"
panic-halt = "1"
rtt-target = "0.6"
crc = "3"
num_enum = { version = "0.7", default-features = false }
static_assertions = "1"
[dependencies.va108xx-hal]

View File

@ -9,14 +9,15 @@ The bootloader uses the following memory map:
| Address | Notes | Size |
| ------ | ---- | ---- |
| 0x0 | Bootloader start | code up to 0x3FFC bytes |
| 0x2FFE | Bootloader CRC | word |
| 0x3000 | App image A start | code up to 0xE7F8 (~58K) bytes |
| 0x0 | Bootloader start | code up to 0x2FFE bytes |
| 0x2FFE | Bootloader CRC | half-word |
| 0x3000 | App image A start | code up to 0xE7F4 (~59K) bytes |
| 0x117F8 | App image A CRC check length | word |
| 0x117FC | App image A CRC check value | word |
| 0x11800 | App image B start | code up to 0xE7F8 (~58K) bytes |
| 0x1FFF8 | App image B CRC check length | word |
| 0x1FFFC | App image B CRC check value | word |
| 0x117FC | App image B start | code up to 0xE7F4 (~59K) bytes |
| 0x1FFF0 | App image B CRC check length | word |
| 0x1FFF4 | App image B CRC check value | word |
| 0x1FFF8 | Reserved section, contains boot select parameter | 8 bytes |
| 0x20000 | End of NVM | end |
## Additional Information
@ -35,13 +36,15 @@ The bootloader performs the following steps:
1. The application will calculate the checksum of itself if the bootloader CRC is blank (all zeroes
or all ones). If the CRC is not blank and the checksum check fails, it will immediately boot
application image A. Otherwise, it proceeds to the next step.
2. Check the checksum of App A. If that checksum is valid, it will boot App A. If not, it will
proceed to the next step.
3. Check the checksum of App B. If that checksum is valid, it will boot App B. If not, it will
boot App A as the fallback image.
2. Read the boot slot from a reserved section at the end of the EEPROM. If no valid value is read,
select boot slot A.
3. Check the checksum of the boot slot. If that checksum is valid, it will boot that slot. If not,
it will proceed to the next step.
4. Check the checksum of the other slot . If that checksum is valid, it will boot that slot. If
not, it will boot App A as the fallback image.
You could adapt and combine this bootloader with a non-volatile memory to select a prefered app
image, which would be a first step towards an updatable flight software.
In your actual production application, a command to update the preferred boot slot could be exposed
to allow performing software updates in a safe way.
Please note that you *MUST* compile the application at slot A and slot B with an appropriate
`memory.x` file where the base address of the `FLASH` was adapted according to the base address

View File

@ -5,6 +5,7 @@ use bootloader::NvmInterface;
use cortex_m_rt::entry;
use crc::{Crc, CRC_16_IBM_3740};
use embedded_hal::delay::DelayNs;
use num_enum::TryFromPrimitive;
#[cfg(not(feature = "rtt-panic"))]
use panic_halt as _;
#[cfg(feature = "rtt-panic")]
@ -59,8 +60,9 @@ const APP_B_SIZE_ADDR: u32 = APP_B_END_ADDR - 8;
// Four bytes reserved, even when only 2 byte CRC is used. Leaves flexibility to switch to CRC32.
// 0x1FFFC
const APP_B_CRC_ADDR: u32 = APP_B_END_ADDR - 4;
// 0x20000
pub const APP_B_END_ADDR: u32 = NVM_SIZE;
// 0x20000. 8 bytes at end of EEPROM reserved for preferred image parameter. This reserved
// size should be a multiple of 8 due to alignment requirements.
pub const APP_B_END_ADDR: u32 = NVM_SIZE - 8;
pub const APP_IMG_SZ: u32 = (APP_B_END_ADDR - APP_A_START_ADDR) / 2;
static_assertions::const_assert!((APP_B_END_ADDR - BOOTLOADER_END_ADDR) % 2 == 0);
@ -68,13 +70,15 @@ static_assertions::const_assert!((APP_B_END_ADDR - BOOTLOADER_END_ADDR) % 2 == 0
pub const VECTOR_TABLE_OFFSET: u32 = 0x0;
pub const VECTOR_TABLE_LEN: u32 = 0xC0;
pub const RESET_VECTOR_OFFSET: u32 = 0x4;
pub const PREFERRED_SLOT_OFFSET: u32 = 0x20000 - 1;
const CRC_ALGO: Crc<u16> = Crc::<u16>::new(&CRC_16_IBM_3740);
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive)]
#[repr(u8)]
enum AppSel {
A,
B,
A = 0,
B = 1,
}
pub struct NvmWrapper(pub M95M01);
@ -154,10 +158,20 @@ fn main() -> ! {
// Check bootloader's CRC (and write it if blank)
check_own_crc(&dp.sysconfig, &cp, &mut nvm, &mut timer);
if check_app_crc(AppSel::A) {
boot_app(&dp.sysconfig, &cp, AppSel::A, &mut timer)
} else if check_app_crc(AppSel::B) {
boot_app(&dp.sysconfig, &cp, AppSel::B, &mut timer)
let mut preferred_app_raw = [0; 1];
nvm.read(PREFERRED_SLOT_OFFSET as usize, &mut preferred_app_raw)
.expect("reading preferred slot failed");
let preferred_app = AppSel::try_from(preferred_app_raw[0]).unwrap_or(AppSel::A);
let other_app = if preferred_app == AppSel::A {
AppSel::B
} else {
AppSel::A
};
if check_app_crc(preferred_app) {
boot_app(&dp.sysconfig, &cp, preferred_app, &mut timer)
} else if check_app_crc(other_app) {
boot_app(&dp.sysconfig, &cp, other_app, &mut timer)
} else {
if DEBUG_PRINTOUTS && RTT_PRINTOUT {
rprintln!("both images corrupt! booting image A");

View File

@ -20,6 +20,14 @@ cargo run --bin rtic-example
## Embassy example
Blinky with time driver IRQs in library
```rs
cargo run --bin embassy-example
```
Blinky with custom time driver IRQs
```rs
cargo run --bin embassy-example --no-default-features --features custom-irqs
```

View File

@ -4,37 +4,30 @@ version = "0.1.0"
edition = "2021"
[dependencies]
cfg-if = "1"
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7"
embedded-hal = "1"
embedded-hal-async = "1"
rtt-target = { version = "0.5" }
panic-rtt-target = { version = "0.1" }
rtt-target = "0.6"
panic-rtt-target = "0.2"
critical-section = "1"
portable-atomic = { version = "1", features = ["unsafe-assume-single-core"]}
embassy-sync = { version = "0.6.0" }
embassy-time = { version = "0.3.2" }
embassy-time-driver = { version = "0.1" }
embassy-sync = "0.6"
embassy-time = "0.4"
embassy-executor = { version = "0.7", features = [
"arch-cortex-m",
"executor-thread",
"executor-interrupt"
]}
[dependencies.once_cell]
version = "1"
default-features = false
features = ["critical-section"]
[dependencies.embassy-executor]
version = "0.6.0"
features = [
"arch-cortex-m",
"executor-thread",
"executor-interrupt",
"integrated-timers",
]
[dependencies.va108xx-hal]
path = "../../va108xx-hal"
va108xx-hal = { path = "../../va108xx-hal" }
va108xx-embassy = { path = "../../va108xx-embassy", default-features = false }
[features]
default = ["ticks-hz-1_000"]
default = ["ticks-hz-1_000", "va108xx-embassy/irq-oc30-oc31"]
custom-irqs = []
ticks-hz-1_000 = ["embassy-time/tick-hz-1_000"]
ticks-hz-32_768 = ["embassy-time/tick-hz-32_768"]

View File

@ -0,0 +1,258 @@
//! This example demonstrates the usage of async GPIO operations on VA108xx.
//!
//! You need to tie the PA0 to the PA1 pin for this example to work. You can optionally tie the PB22 to PB23 pins well
//! and then set the `CHECK_PB22_TO_PB23` to true to also test async operations on Port B.
#![no_std]
#![no_main]
use embassy_executor::Spawner;
use embassy_sync::channel::{Receiver, Sender};
use embassy_sync::{blocking_mutex::raw::ThreadModeRawMutex, channel::Channel};
use embassy_time::{Duration, Instant, Timer};
use embedded_hal::digital::{InputPin, OutputPin, StatefulOutputPin};
use embedded_hal_async::digital::Wait;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use va108xx_embassy::embassy;
use va108xx_hal::gpio::{handle_interrupt_for_async_gpio, InputDynPinAsync, InputPinAsync, PinsB};
use va108xx_hal::{
gpio::{DynPin, PinsA},
pac::{self, interrupt},
prelude::*,
};
const SYSCLK_FREQ: Hertz = Hertz::from_raw(50_000_000);
const CHECK_PA0_TO_PA1: bool = true;
const CHECK_PB22_TO_PB23: bool = false;
// Can also be set to OC10 and works as well.
const PB22_TO_PB23_IRQ: pac::Interrupt = pac::Interrupt::OC11;
#[derive(Clone, Copy)]
pub struct GpioCmd {
cmd_type: GpioCmdType,
after_delay: u32,
}
impl GpioCmd {
pub fn new(cmd_type: GpioCmdType, after_delay: u32) -> Self {
Self {
cmd_type,
after_delay,
}
}
}
#[derive(Clone, Copy)]
pub enum GpioCmdType {
SetHigh,
SetLow,
RisingEdge,
FallingEdge,
}
// Declare a bounded channel of 3 u32s.
static CHANNEL_PA0_PA1: Channel<ThreadModeRawMutex, GpioCmd, 3> = Channel::new();
static CHANNEL_PB22_TO_PB23: Channel<ThreadModeRawMutex, GpioCmd, 3> = Channel::new();
#[embassy_executor::main]
async fn main(spawner: Spawner) {
rtt_init_print!();
rprintln!("-- VA108xx Async GPIO Demo --");
let mut dp = pac::Peripherals::take().unwrap();
// Safety: Only called once here.
unsafe {
embassy::init(
&mut dp.sysconfig,
&dp.irqsel,
SYSCLK_FREQ,
dp.tim23,
dp.tim22,
)
};
let porta = PinsA::new(&mut dp.sysconfig, dp.porta);
let portb = PinsB::new(&mut dp.sysconfig, dp.portb);
let mut led0 = porta.pa10.into_readable_push_pull_output();
let out_pa0 = porta.pa0.into_readable_push_pull_output();
let in_pa1 = porta.pa1.into_floating_input();
let out_pb22 = portb.pb22.into_readable_push_pull_output();
let in_pb23 = portb.pb23.into_floating_input();
let in_pa1_async = InputPinAsync::new(in_pa1, pac::Interrupt::OC10);
let out_pa0_dyn = out_pa0.downgrade();
let in_pb23_async = InputDynPinAsync::new(in_pb23.downgrade(), PB22_TO_PB23_IRQ).unwrap();
let out_pb22_dyn = out_pb22.downgrade();
spawner
.spawn(output_task(
"PA0 to PA1",
out_pa0_dyn,
CHANNEL_PA0_PA1.receiver(),
))
.unwrap();
spawner
.spawn(output_task(
"PB22 to PB23",
out_pb22_dyn,
CHANNEL_PB22_TO_PB23.receiver(),
))
.unwrap();
if CHECK_PA0_TO_PA1 {
check_pin_to_pin_async_ops("PA0 to PA1", CHANNEL_PA0_PA1.sender(), in_pa1_async).await;
rprintln!("Example PA0 to PA1 done");
}
if CHECK_PB22_TO_PB23 {
check_pin_to_pin_async_ops("PB22 to PB23", CHANNEL_PB22_TO_PB23.sender(), in_pb23_async)
.await;
rprintln!("Example PB22 to PB23 done");
}
rprintln!("Example done, toggling LED0");
loop {
led0.toggle().unwrap();
Timer::after(Duration::from_millis(500)).await;
}
}
async fn check_pin_to_pin_async_ops(
ctx: &'static str,
sender: Sender<'static, ThreadModeRawMutex, GpioCmd, 3>,
mut async_input: impl Wait,
) {
rprintln!(
"{}: sending SetHigh command ({} ms)",
ctx,
Instant::now().as_millis()
);
sender.send(GpioCmd::new(GpioCmdType::SetHigh, 20)).await;
async_input.wait_for_high().await.unwrap();
rprintln!(
"{}: Input pin is high now ({} ms)",
ctx,
Instant::now().as_millis()
);
rprintln!(
"{}: sending SetLow command ({} ms)",
ctx,
Instant::now().as_millis()
);
sender.send(GpioCmd::new(GpioCmdType::SetLow, 20)).await;
async_input.wait_for_low().await.unwrap();
rprintln!(
"{}: Input pin is low now ({} ms)",
ctx,
Instant::now().as_millis()
);
rprintln!(
"{}: sending RisingEdge command ({} ms)",
ctx,
Instant::now().as_millis()
);
sender.send(GpioCmd::new(GpioCmdType::RisingEdge, 20)).await;
async_input.wait_for_rising_edge().await.unwrap();
rprintln!(
"{}: input pin had rising edge ({} ms)",
ctx,
Instant::now().as_millis()
);
rprintln!(
"{}: sending Falling command ({} ms)",
ctx,
Instant::now().as_millis()
);
sender
.send(GpioCmd::new(GpioCmdType::FallingEdge, 20))
.await;
async_input.wait_for_falling_edge().await.unwrap();
rprintln!(
"{}: input pin had a falling edge ({} ms)",
ctx,
Instant::now().as_millis()
);
rprintln!(
"{}: sending Falling command ({} ms)",
ctx,
Instant::now().as_millis()
);
sender
.send(GpioCmd::new(GpioCmdType::FallingEdge, 20))
.await;
async_input.wait_for_any_edge().await.unwrap();
rprintln!(
"{}: input pin had a falling (any) edge ({} ms)",
ctx,
Instant::now().as_millis()
);
rprintln!(
"{}: sending Falling command ({} ms)",
ctx,
Instant::now().as_millis()
);
sender.send(GpioCmd::new(GpioCmdType::RisingEdge, 20)).await;
async_input.wait_for_any_edge().await.unwrap();
rprintln!(
"{}: input pin had a rising (any) edge ({} ms)",
ctx,
Instant::now().as_millis()
);
}
#[embassy_executor::task(pool_size = 2)]
async fn output_task(
ctx: &'static str,
mut out: DynPin,
receiver: Receiver<'static, ThreadModeRawMutex, GpioCmd, 3>,
) {
loop {
let next_cmd = receiver.receive().await;
Timer::after(Duration::from_millis(next_cmd.after_delay.into())).await;
match next_cmd.cmd_type {
GpioCmdType::SetHigh => {
rprintln!("{}: Set output high", ctx);
out.set_high().unwrap();
}
GpioCmdType::SetLow => {
rprintln!("{}: Set output low", ctx);
out.set_low().unwrap();
}
GpioCmdType::RisingEdge => {
rprintln!("{}: Rising edge", ctx);
if !out.is_low().unwrap() {
out.set_low().unwrap();
}
out.set_high().unwrap();
}
GpioCmdType::FallingEdge => {
rprintln!("{}: Falling edge", ctx);
if !out.is_high().unwrap() {
out.set_high().unwrap();
}
out.set_low().unwrap();
}
}
}
}
// PB22 to PB23 can be handled by both OC10 and OC11 depending on configuration.
#[interrupt]
#[allow(non_snake_case)]
fn OC10() {
handle_interrupt_for_async_gpio();
}
#[interrupt]
#[allow(non_snake_case)]
fn OC11() {
handle_interrupt_for_async_gpio();
}

View File

@ -1,4 +0,0 @@
#![no_std]
pub mod time_driver;
pub use time_driver::init;

View File

@ -5,6 +5,16 @@ use embassy_time::{Duration, Instant, Ticker};
use embedded_hal::digital::StatefulOutputPin;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use va108xx_embassy::embassy;
cfg_if::cfg_if! {
if #[cfg(feature = "custom-irqs")] {
use va108xx_embassy::embassy_time_driver_irqs;
use va108xx_hal::pac::interrupt;
embassy_time_driver_irqs!(timekeeper_irq = OC23, alarm_irq = OC24);
}
}
use va108xx_hal::{gpio::PinsA, pac, prelude::*};
const SYSCLK_FREQ: Hertz = Hertz::from_raw(50_000_000);
@ -19,16 +29,30 @@ async fn main(_spawner: Spawner) {
// Safety: Only called once here.
unsafe {
embassy_example::init(
&mut dp.sysconfig,
&dp.irqsel,
SYSCLK_FREQ,
dp.tim23,
dp.tim22,
)
};
cfg_if::cfg_if! {
if #[cfg(not(feature = "custom-irqs"))] {
embassy::init(
&mut dp.sysconfig,
&dp.irqsel,
SYSCLK_FREQ,
dp.tim23,
dp.tim22,
);
} else {
embassy::init_with_custom_irqs(
&mut dp.sysconfig,
&dp.irqsel,
SYSCLK_FREQ,
dp.tim23,
dp.tim22,
pac::Interrupt::OC23,
pac::Interrupt::OC24,
);
}
}
}
let porta = PinsA::new(&mut dp.sysconfig, Some(dp.ioconfig), dp.porta);
let porta = PinsA::new(&mut dp.sysconfig, dp.porta);
let mut led0 = porta.pa10.into_readable_push_pull_output();
let mut led1 = porta.pa7.into_readable_push_pull_output();
let mut led2 = porta.pa6.into_readable_push_pull_output();

View File

@ -1,333 +0,0 @@
//! This is a sample time driver implementation for the VA108xx family of devices, supporting
//! one alarm and requiring/reserving 2 TIM peripherals. You could adapt this implementation to
//! support more alarms.
//!
//! This driver implementation reserves interrupts OC31 and OC30 for the timekeeping.
use core::{cell::Cell, mem, ptr};
use critical_section::CriticalSection;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::blocking_mutex::Mutex;
use portable_atomic::{AtomicU32, AtomicU8, Ordering};
use embassy_time_driver::{time_driver_impl, AlarmHandle, Driver, TICK_HZ};
use once_cell::sync::OnceCell;
use va108xx_hal::{
clock::enable_peripheral_clock,
enable_interrupt,
pac::{self, interrupt},
prelude::*,
timer::{enable_tim_clk, ValidTim},
PeripheralSelect,
};
pub type TimekeeperClk = pac::Tim23;
pub type AlarmClk0 = pac::Tim22;
pub type AlarmClk1 = pac::Tim21;
pub type AlarmClk2 = pac::Tim20;
const TIMEKEEPER_IRQ: pac::Interrupt = pac::Interrupt::OC31;
const ALARM_IRQ: pac::Interrupt = pac::Interrupt::OC30;
/// Initialization method for embassy
///
/// # Safety
/// This has to be called once at initialization time to initiate the time driver for
/// embassy.
pub unsafe fn init(
syscfg: &mut pac::Sysconfig,
irqsel: &pac::Irqsel,
sysclk: impl Into<Hertz>,
timekeeper: TimekeeperClk,
alarm_tim: AlarmClk0,
) {
DRIVER.init(syscfg, irqsel, sysclk, timekeeper, alarm_tim)
}
time_driver_impl!(
static DRIVER: TimerDriverEmbassy = TimerDriverEmbassy {
periods: AtomicU32::new(0),
alarm_count: AtomicU8::new(0),
alarms: Mutex::const_new(CriticalSectionRawMutex::new(), [AlarmState::new(); ALARM_COUNT])
});
/// Timekeeper interrupt.
#[interrupt]
#[allow(non_snake_case)]
fn OC31() {
DRIVER.on_interrupt_timekeeping()
}
/// Alarm timer interrupt.
#[interrupt]
#[allow(non_snake_case)]
fn OC30() {
DRIVER.on_interrupt_alarm(0)
}
#[inline(always)]
const fn alarm_tim(idx: usize) -> &'static pac::tim0::RegisterBlock {
// Safety: This is a static memory-mapped peripheral.
match idx {
0 => unsafe { &*AlarmClk0::ptr() },
1 => unsafe { &*AlarmClk1::ptr() },
2 => unsafe { &*AlarmClk2::ptr() },
_ => {
panic!("invalid alarm timer index")
}
}
}
#[inline(always)]
const fn timekeeping_tim() -> &'static pac::tim0::RegisterBlock {
// Safety: This is a memory-mapped peripheral.
unsafe { &*TimekeeperClk::ptr() }
}
struct AlarmState {
timestamp: Cell<u64>,
// This is really a Option<(fn(*mut ()), *mut ())>
// but fn pointers aren't allowed in const yet
callback: Cell<*const ()>,
ctx: Cell<*mut ()>,
}
impl AlarmState {
const fn new() -> Self {
Self {
timestamp: Cell::new(u64::MAX),
callback: Cell::new(ptr::null()),
ctx: Cell::new(ptr::null_mut()),
}
}
}
unsafe impl Send for AlarmState {}
const ALARM_COUNT: usize = 1;
static SCALE: OnceCell<u64> = OnceCell::new();
pub struct TimerDriverEmbassy {
periods: AtomicU32,
alarm_count: AtomicU8,
/// Timestamp at which to fire alarm. u64::MAX if no alarm is scheduled.
alarms: Mutex<CriticalSectionRawMutex, [AlarmState; ALARM_COUNT]>,
}
impl TimerDriverEmbassy {
fn init(
&self,
syscfg: &mut pac::Sysconfig,
irqsel: &pac::Irqsel,
sysclk: impl Into<Hertz>,
timekeeper: TimekeeperClk,
alarm_tim: AlarmClk0,
) {
enable_peripheral_clock(syscfg, PeripheralSelect::Irqsel);
enable_tim_clk(syscfg, TimekeeperClk::TIM_ID);
let sysclk = sysclk.into();
// Initiate scale value here. This is required to convert timer ticks back to a timestamp.
SCALE.set((sysclk.raw() / TICK_HZ as u32) as u64).unwrap();
timekeeper
.rst_value()
.write(|w| unsafe { w.bits(u32::MAX) });
// Decrementing counter.
timekeeper
.cnt_value()
.write(|w| unsafe { w.bits(u32::MAX) });
// Switch on. Timekeeping should always be done.
irqsel
.tim0(TimekeeperClk::TIM_ID as usize)
.write(|w| unsafe { w.bits(TIMEKEEPER_IRQ as u32) });
unsafe {
enable_interrupt(TIMEKEEPER_IRQ);
}
timekeeper.ctrl().modify(|_, w| w.irq_enb().set_bit());
timekeeper.enable().write(|w| unsafe { w.bits(1) });
enable_tim_clk(syscfg, AlarmClk0::TIM_ID);
// Explicitely disable alarm timer until needed.
alarm_tim.ctrl().modify(|_, w| {
w.irq_enb().clear_bit();
w.enable().clear_bit()
});
// Enable general interrupts. The IRQ enable of the peripheral remains cleared.
unsafe {
enable_interrupt(ALARM_IRQ);
}
irqsel
.tim0(AlarmClk0::TIM_ID as usize)
.write(|w| unsafe { w.bits(ALARM_IRQ as u32) });
}
// Should be called inside the IRQ of the timekeeper timer.
fn on_interrupt_timekeeping(&self) {
self.next_period();
}
// Should be called inside the IRQ of the alarm timer.
fn on_interrupt_alarm(&self, idx: usize) {
critical_section::with(|cs| {
if self.alarms.borrow(cs)[idx].timestamp.get() <= self.now() {
self.trigger_alarm(idx, cs)
}
})
}
fn next_period(&self) {
let period = self.periods.fetch_add(1, Ordering::AcqRel) + 1;
let t = (period as u64) << 32;
critical_section::with(|cs| {
for i in 0..ALARM_COUNT {
let alarm = &self.alarms.borrow(cs)[i];
let at = alarm.timestamp.get();
let alarm_tim = alarm_tim(0);
if at < t {
self.trigger_alarm(i, cs);
} else {
let remaining_ticks = (at - t) * *SCALE.get().unwrap();
if remaining_ticks <= u32::MAX as u64 {
alarm_tim.enable().write(|w| unsafe { w.bits(0) });
alarm_tim
.cnt_value()
.write(|w| unsafe { w.bits(remaining_ticks as u32) });
alarm_tim.ctrl().modify(|_, w| w.irq_enb().set_bit());
alarm_tim.enable().write(|w| unsafe { w.bits(1) })
}
}
}
})
}
fn get_alarm<'a>(&'a self, cs: CriticalSection<'a>, alarm: AlarmHandle) -> &'a AlarmState {
// safety: we're allowed to assume the AlarmState is created by us, and
// we never create one that's out of bounds.
unsafe { self.alarms.borrow(cs).get_unchecked(alarm.id() as usize) }
}
fn trigger_alarm(&self, n: usize, cs: CriticalSection) {
alarm_tim(n).ctrl().modify(|_, w| {
w.irq_enb().clear_bit();
w.enable().clear_bit()
});
let alarm = &self.alarms.borrow(cs)[n];
// Setting the maximum value disables the alarm.
alarm.timestamp.set(u64::MAX);
// Call after clearing alarm, so the callback can set another alarm.
// safety:
// - we can ignore the possiblity of `f` being unset (null) because of the safety contract of `allocate_alarm`.
// - other than that we only store valid function pointers into alarm.callback
let f: fn(*mut ()) = unsafe { mem::transmute(alarm.callback.get()) };
f(alarm.ctx.get());
}
}
impl Driver for TimerDriverEmbassy {
fn now(&self) -> u64 {
if SCALE.get().is_none() {
return 0;
}
let mut period1: u32;
let mut period2: u32;
let mut counter_val: u32;
loop {
// Acquire ensures that we get the latest value of `periods` and
// no instructions can be reordered before the load.
period1 = self.periods.load(Ordering::Acquire);
counter_val = u32::MAX - timekeeping_tim().cnt_value().read().bits();
// Double read to protect against race conditions when the counter is overflowing.
period2 = self.periods.load(Ordering::Relaxed);
if period1 == period2 {
let now = (((period1 as u64) << 32) | counter_val as u64) / *SCALE.get().unwrap();
return now;
}
}
}
unsafe fn allocate_alarm(&self) -> Option<AlarmHandle> {
let id = self
.alarm_count
.fetch_update(Ordering::AcqRel, Ordering::Acquire, |x| {
if x < ALARM_COUNT as u8 {
Some(x + 1)
} else {
None
}
});
match id {
Ok(id) => Some(AlarmHandle::new(id)),
Err(_) => None,
}
}
fn set_alarm_callback(
&self,
alarm: embassy_time_driver::AlarmHandle,
callback: fn(*mut ()),
ctx: *mut (),
) {
critical_section::with(|cs| {
let alarm = self.get_alarm(cs, alarm);
alarm.callback.set(callback as *const ());
alarm.ctx.set(ctx);
})
}
fn set_alarm(&self, alarm: embassy_time_driver::AlarmHandle, timestamp: u64) -> bool {
if SCALE.get().is_none() {
return false;
}
critical_section::with(|cs| {
let n = alarm.id();
let alarm_tim = alarm_tim(n.into());
alarm_tim.ctrl().modify(|_, w| {
w.irq_enb().clear_bit();
w.enable().clear_bit()
});
let alarm = self.get_alarm(cs, alarm);
alarm.timestamp.set(timestamp);
let t = self.now();
if timestamp <= t {
alarm.timestamp.set(u64::MAX);
return false;
}
// If it hasn't triggered yet, setup the relevant reset value, regardless of whether
// the interrupts are enabled or not. When they are enabled at a later point, the
// right value is already set.
// If the timestamp is in the next few ticks, add a bit of buffer to be sure the alarm
// is not missed.
//
// This means that an alarm can be delayed for up to 2 ticks (from t+1 to t+3), but this is allowed
// by the Alarm trait contract. What's not allowed is triggering alarms *before* their scheduled time,
// and we don't do that here.
let safe_timestamp = timestamp.max(t + 3);
let timer_ticks = (safe_timestamp - t) * *SCALE.get().unwrap();
alarm_tim.rst_value().write(|w| unsafe { w.bits(u32::MAX) });
if timer_ticks <= u32::MAX as u64 {
alarm_tim
.cnt_value()
.write(|w| unsafe { w.bits(timer_ticks as u32) });
alarm_tim.ctrl().modify(|_, w| w.irq_enb().set_bit());
alarm_tim.enable().write(|w| unsafe { w.bits(1) });
}
// If it's too far in the future, don't enable timer yet.
// It will be enabled later by `next_period`.
true
})
}
}

View File

@ -8,37 +8,19 @@ cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7"
embedded-hal = "1"
embedded-io = "0.6"
rtt-target = { version = "0.5" }
panic-rtt-target = { version = "0.1" }
rtt-target = "0.6"
panic-rtt-target = "0.2"
# Even though we do not use this directly, we need to activate this feature explicitely
# so that RTIC compiles because thumv6 does not have CAS operations natively.
portable-atomic = { version = "1", features = ["unsafe-assume-single-core"]}
[dependencies.rtic]
version = "2"
features = ["thumbv6-backend"]
rtic = { version = "2", features = ["thumbv6-backend"] }
rtic-monotonics = { version = "2", features = ["cortex-m-systick"] }
rtic-sync = { version = "1.3", features = ["defmt-03"] }
[dependencies.rtic-monotonics]
version = "2"
features = ["cortex-m-systick"]
once_cell = {version = "1", default-features = false, features = ["critical-section"]}
ringbuf = { version = "0.4.7", default-features = false, features = ["portable-atomic"] }
[dependencies.rtic-sync]
version = "1.3"
features = ["defmt-03"]
[dependencies.once_cell]
version = "1"
default-features = false
features = ["critical-section"]
[dependencies.ringbuf]
version = "0.4.7"
default-features = false
features = ["portable-atomic"]
[dependencies.va108xx-hal]
version = "0.8"
[dependencies.vorago-reb1]
path = "../../vorago-reb1"
va108xx-hal = "0.8"
vorago-reb1 = { path = "../../vorago-reb1" }

View File

@ -5,25 +5,17 @@
#![no_main]
#![no_std]
use once_cell::sync::Lazy;
use ringbuf::StaticRb;
// Larger buffer for TC to be able to hold the possibly large memory write packets.
const RX_RING_BUF_SIZE: usize = 1024;
// Ring buffers to handling variable sized telemetry
static mut RINGBUF: Lazy<StaticRb<u8, RX_RING_BUF_SIZE>> =
Lazy::new(StaticRb::<u8, RX_RING_BUF_SIZE>::default);
#[rtic::app(device = pac, dispatchers = [OC4])]
mod app {
use super::*;
use embedded_io::Write;
use panic_rtt_target as _;
use ringbuf::{
traits::{Consumer, Observer, Producer, SplitRef},
CachingCons, StaticProd,
};
use ringbuf::traits::{Consumer, Observer, Producer};
use rtic_example::SYSCLK_FREQ;
use rtic_monotonics::Monotonic;
use rtt_target::{rprintln, rtt_init_print};
@ -36,14 +28,14 @@ mod app {
#[local]
struct Local {
data_producer: StaticProd<'static, u8, RX_RING_BUF_SIZE>,
data_consumer: CachingCons<&'static StaticRb<u8, RX_RING_BUF_SIZE>>,
rx: RxWithIrq<pac::Uarta>,
tx: Tx<pac::Uarta>,
}
#[shared]
struct Shared {}
struct Shared {
rb: StaticRb<u8, RX_RING_BUF_SIZE>,
}
rtic_monotonics::systick_monotonic!(Mono, 1_000);
@ -71,16 +63,12 @@ mod app {
rx.start();
let (data_producer, data_consumer) = unsafe { RINGBUF.split_ref() };
echo_handler::spawn().unwrap();
(
Shared {},
Local {
data_producer,
data_consumer,
rx,
tx,
Shared {
rb: StaticRb::default(),
},
Local { rx, tx },
)
}
@ -94,24 +82,23 @@ mod app {
#[task(
binds = OC3,
shared = [],
shared = [rb],
local = [
rx,
data_producer
],
)]
fn reception_task(cx: reception_task::Context) {
fn reception_task(mut cx: reception_task::Context) {
let mut buf: [u8; 16] = [0; 16];
let mut ringbuf_full = false;
let result = cx.local.rx.irq_handler(&mut buf);
if result.bytes_read > 0 && result.errors.is_none() {
if cx.local.data_producer.vacant_len() < result.bytes_read {
ringbuf_full = true;
} else {
cx.local
.data_producer
.push_slice(&buf[0..result.bytes_read]);
}
cx.shared.rb.lock(|rb| {
if rb.vacant_len() < result.bytes_read {
ringbuf_full = true;
} else {
rb.push_slice(&buf[0..result.bytes_read]);
}
});
}
if ringbuf_full {
// Could also drop oldest data, but that would require the consumer to be shared.
@ -119,24 +106,23 @@ mod app {
}
}
#[task(shared = [], local = [
#[task(shared = [rb], local = [
buf: [u8; RX_RING_BUF_SIZE] = [0; RX_RING_BUF_SIZE],
data_consumer,
tx
], priority=1)]
async fn echo_handler(cx: echo_handler::Context) {
async fn echo_handler(mut cx: echo_handler::Context) {
loop {
let bytes_to_read = cx.local.data_consumer.occupied_len();
if bytes_to_read > 0 {
let actual_read_bytes = cx
.local
.data_consumer
.pop_slice(&mut cx.local.buf[0..bytes_to_read]);
cx.local
.tx
.write_all(&cx.local.buf[0..actual_read_bytes])
.expect("Failed to write to TX");
}
cx.shared.rb.lock(|rb| {
let bytes_to_read = rb.occupied_len();
if bytes_to_read > 0 {
let actual_read_bytes = rb.pop_slice(&mut cx.local.buf[0..bytes_to_read]);
cx.local
.tx
.write_all(&cx.local.buf[0..actual_read_bytes])
.expect("Failed to write to TX");
}
});
Mono::delay(50.millis()).await;
}
}

View File

@ -6,10 +6,10 @@ edition = "2021"
[dependencies]
cortex-m = {version = "0.7", features = ["critical-section-single-core"]}
cortex-m-rt = "0.7"
panic-halt = "0.2"
panic-rtt-target = "0.1"
panic-halt = "1"
panic-rtt-target = "0.2"
critical-section = "1"
rtt-target = "0.5"
rtt-target = "0.6"
embedded-hal = "1"
embedded-hal-nb = "1"
embedded-io = "0.6"

View File

@ -9,54 +9,24 @@ cortex-m-rt = "0.7"
embedded-hal = "1"
embedded-hal-nb = "1"
embedded-io = "0.6"
panic-rtt-target = { version = "0.1.3" }
rtt-target = { version = "0.5" }
panic-rtt-target = "0.2"
rtt-target = "0.6"
num_enum = { version = "0.7", default-features = false }
log = "0.4"
crc = "3"
[dependencies.satrs]
version = "0.2"
default-features = false
[dependencies.rtt-log]
version = "0.4"
[dependencies.ringbuf]
version = "0.4.7"
default-features = false
features = ["portable-atomic"]
[dependencies.once_cell]
version = "1"
default-features = false
features = ["critical-section"]
[dependencies.spacepackets]
version = "0.11"
default-features = false
[dependencies.cobs]
git = "https://github.com/robamu/cobs.rs.git"
branch = "all_features"
default-features = false
cobs = { version = "0.3", default-features = false }
satrs = { version = "0.2", default-features = false }
rtt-log = "0.5"
ringbuf = { version = "0.4.7", default-features = false, features = ["portable-atomic"] }
once_cell = { version = "1", default-features = false, features = ["critical-section"] }
spacepackets = { version = "0.11", default-features = false }
# Even though we do not use this directly, we need to activate this feature explicitely
# so that RTIC compiles because thumv6 does not have CAS operations natively.
[dependencies.portable-atomic]
version = "1"
features = ["unsafe-assume-single-core"]
portable-atomic = {version = "1", features = ["unsafe-assume-single-core"]}
[dependencies.rtic]
version = "2"
features = ["thumbv6-backend"]
[dependencies.rtic-monotonics]
version = "2"
features = ["cortex-m-systick"]
[dependencies.rtic-sync]
version = "1"
features = ["defmt-03"]
rtic = { version = "2", features = ["thumbv6-backend"] }
rtic-monotonics = { version = "2", features = ["cortex-m-systick"] }
rtic-sync = {version = "1", features = ["defmt-03"]}
[dependencies.va108xx-hal]
path = "../va108xx-hal"

View File

@ -59,6 +59,15 @@ to write it to slot A.
You can use
```sh
./image-loader.py -s a
```
to select the Slot A as a boot slot. The boot slot is stored in a reserved section in EEPROM
and will be read and used by the bootloader to determine which slot to boot.
You can use
```sh
./image-loader.py -c -t a
```

View File

@ -30,20 +30,21 @@ BOOTLOADER_CRC_ADDR = BOOTLOADER_END_ADDR - 2
BOOTLOADER_MAX_SIZE = BOOTLOADER_END_ADDR - BOOTLOADER_START_ADDR - 2
APP_A_START_ADDR = 0x3000
APP_A_END_ADDR = 0x11800
APP_B_END_ADDR = 0x20000 - 8
IMG_SLOT_SIZE = (APP_B_END_ADDR - APP_A_START_ADDR) // 2
APP_A_END_ADDR = APP_A_START_ADDR + IMG_SLOT_SIZE
# The actual size of the image which is relevant for CRC calculation.
APP_A_SIZE_ADDR = APP_A_END_ADDR - 8
APP_A_CRC_ADDR = APP_A_END_ADDR - 4
APP_A_MAX_SIZE = APP_A_END_ADDR - APP_A_START_ADDR - 8
APP_B_START_ADDR = APP_A_END_ADDR
APP_B_END_ADDR = 0x20000
# The actual size of the image which is relevant for CRC calculation.
APP_B_SIZE_ADDR = APP_B_END_ADDR - 8
APP_B_CRC_ADDR = APP_B_END_ADDR - 4
APP_B_MAX_SIZE = APP_A_END_ADDR - APP_A_START_ADDR - 8
APP_IMG_SZ = (APP_B_END_ADDR - APP_A_START_ADDR) // 2
CHUNK_SIZE = 400
@ -58,6 +59,7 @@ PING_PAYLOAD_SIZE = 0
class ActionId(enum.IntEnum):
CORRUPT_APP_A = 128
CORRUPT_APP_B = 129
SET_BOOT_SLOT = 130
_LOGGER = logging.getLogger(__name__)
@ -78,11 +80,37 @@ class Target(enum.Enum):
APP_B = 2
class AppSel(enum.IntEnum):
APP_A = 0
APP_B = 1
class ImageLoader:
def __init__(self, com_if: ComInterface, verificator: PusVerificator) -> None:
self.com_if = com_if
self.verificator = verificator
def handle_boot_sel_cmd(self, target: AppSel):
_LOGGER.info("Sending ping command")
action_tc = PusTc(
apid=0x00,
service=PusService.S8_FUNC_CMD,
subservice=ActionId.SET_BOOT_SLOT,
seq_count=SEQ_PROVIDER.get_and_increment(),
app_data=bytes([target]),
)
self.verificator.add_tc(action_tc)
self.com_if.send(bytes(action_tc.pack()))
data_available = self.com_if.data_available(0.4)
if not data_available:
_LOGGER.warning("no reply received for boot image selection command")
for reply in self.com_if.receive():
result = self.verificator.add_tm(
Service1Tm.from_tm(PusTm.unpack(reply, 0), UnpackParams(0))
)
if result is not None and result.completed:
_LOGGER.info("received boot image selection command confirmation")
def handle_ping_cmd(self):
_LOGGER.info("Sending ping command")
ping_tc = PusTc(
@ -106,7 +134,6 @@ class ImageLoader:
_LOGGER.info("received ping completion reply")
def handle_corruption_cmd(self, target: Target):
if target == Target.BOOTLOADER:
_LOGGER.error("can not corrupt bootloader")
if target == Target.APP_A:
@ -131,7 +158,8 @@ class ImageLoader:
_LOGGER.info("Parsing ELF file for loadable sections")
total_size = 0
loadable_segments, total_size = create_loadable_segments(target, file_path)
segments_info_str(target, loadable_segments, total_size, file_path)
check_segments(target, total_size)
print_segments_info(target, loadable_segments, total_size, file_path)
result = self._perform_flashing_algorithm(loadable_segments)
if result != 0:
return result
@ -251,6 +279,9 @@ def main() -> int:
prog="image-loader", description="Python VA416XX Image Loader Application"
)
parser.add_argument("-p", "--ping", action="store_true", help="Send ping command")
parser.add_argument(
"-s", "--sel", choices=["a", "b"], help="Set boot slot (Slot A or B)"
)
parser.add_argument("-c", "--corrupt", action="store_true", help="Corrupt a target")
parser.add_argument(
"-t",
@ -286,6 +317,14 @@ def main() -> int:
target = Target.APP_A
elif args.target == "b":
target = Target.APP_B
boot_sel = None
if args.sel:
if args.sel == "a":
boot_sel = AppSel.APP_A
elif args.sel == "b":
boot_sel = AppSel.APP_B
image_loader = ImageLoader(com_if, verificator)
file_path = None
result = -1
@ -293,6 +332,8 @@ def main() -> int:
image_loader.handle_ping_cmd()
com_if.close()
return 0
if args.sel and boot_sel is not None:
image_loader.handle_boot_sel_cmd(boot_sel)
if target:
if not args.corrupt:
if not args.path:
@ -307,9 +348,9 @@ def main() -> int:
return -1
image_loader.handle_corruption_cmd(target)
else:
assert file_path is not None
assert target is not None
result = image_loader.handle_flash_cmd(target, file_path)
if file_path is not None:
assert target is not None
result = image_loader.handle_flash_cmd(target, file_path)
com_if.close()
return result
@ -377,7 +418,22 @@ def create_loadable_segments(
return loadable_segments, total_size
def segments_info_str(
def check_segments(
target: Target,
total_size: int,
):
# Set context string and perform basic sanity checks.
if target == Target.BOOTLOADER and total_size > BOOTLOADER_MAX_SIZE:
raise ValueError(
f"provided bootloader app larger than allowed {total_size} bytes"
)
elif target == Target.APP_A and total_size > APP_A_MAX_SIZE:
raise ValueError(f"provided App A larger than allowed {total_size} bytes")
elif target == Target.APP_B and total_size > APP_B_MAX_SIZE:
raise ValueError(f"provided App B larger than allowed {total_size} bytes")
def print_segments_info(
target: Target,
loadable_segments: List[LoadableSegment],
total_size: int,
@ -385,21 +441,10 @@ def segments_info_str(
):
# Set context string and perform basic sanity checks.
if target == Target.BOOTLOADER:
if total_size > BOOTLOADER_MAX_SIZE:
_LOGGER.error(
f"provided bootloader app larger than allowed {total_size} bytes"
)
return -1
context_str = "Bootloader"
elif target == Target.APP_A:
if total_size > APP_A_MAX_SIZE:
_LOGGER.error(f"provided App A larger than allowed {total_size} bytes")
return -1
context_str = "App Slot A"
elif target == Target.APP_B:
if total_size > APP_B_MAX_SIZE:
_LOGGER.error(f"provided App B larger than allowed {total_size} bytes")
return -1
context_str = "App Slot B"
_LOGGER.info(f"Flashing {context_str} with image {file_path} (size {total_size})")
for idx, segment in enumerate(loadable_segments):

View File

@ -1,7 +1,7 @@
/* Special linker script for application slot A with an offset at address 0x3000 */
MEMORY
{
FLASH : ORIGIN = 0x00003000, LENGTH = 0xE800
FLASH : ORIGIN = 0x00003000, LENGTH = 0xE7FC
RAM : ORIGIN = 0x10000000, LENGTH = 0x08000 /* 32K */
}

View File

@ -1,7 +1,7 @@
/* Special linker script for application slot B with an offset at address 0x11800 */
/* Special linker script for application slot B */
MEMORY
{
FLASH : ORIGIN = 0x00011800, LENGTH = 0xE800
FLASH : ORIGIN = 0x000117FC, LENGTH = 0xE7FC
RAM : ORIGIN = 0x10000000, LENGTH = 0x08000 /* 32K */
}

View File

@ -3,11 +3,11 @@
#![no_main]
#![no_std]
use once_cell::sync::Lazy;
use num_enum::TryFromPrimitive;
use panic_rtt_target as _;
use ringbuf::{
traits::{Consumer, Observer, Producer, SplitRef},
CachingCons, StaticProd, StaticRb,
traits::{Consumer, Observer, Producer},
StaticRb,
};
use va108xx_hal::prelude::*;
@ -26,6 +26,14 @@ const RX_DEBUGGING: bool = false;
pub enum ActionId {
CorruptImageA = 128,
CorruptImageB = 129,
SetBootSlot = 130,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive)]
#[repr(u8)]
enum AppSel {
A = 0,
B = 1,
}
// Larger buffer for TC to be able to hold the possibly large memory write packets.
@ -35,33 +43,18 @@ const SIZES_RB_SIZE_TC: usize = 16;
const BUF_RB_SIZE_TM: usize = 256;
const SIZES_RB_SIZE_TM: usize = 16;
// Ring buffers to handling variable sized telemetry
static mut BUF_RB_TM: Lazy<StaticRb<u8, BUF_RB_SIZE_TM>> =
Lazy::new(StaticRb::<u8, BUF_RB_SIZE_TM>::default);
static mut SIZES_RB_TM: Lazy<StaticRb<usize, SIZES_RB_SIZE_TM>> =
Lazy::new(StaticRb::<usize, SIZES_RB_SIZE_TM>::default);
// Ring buffers to handling variable sized telecommands
static mut BUF_RB_TC: Lazy<StaticRb<u8, BUF_RB_SIZE_TC>> =
Lazy::new(StaticRb::<u8, BUF_RB_SIZE_TC>::default);
static mut SIZES_RB_TC: Lazy<StaticRb<usize, SIZES_RB_SIZE_TC>> =
Lazy::new(StaticRb::<usize, SIZES_RB_SIZE_TC>::default);
pub struct DataProducer<const BUF_SIZE: usize, const SIZES_LEN: usize> {
pub buf_prod: StaticProd<'static, u8, BUF_SIZE>,
pub sizes_prod: StaticProd<'static, usize, SIZES_LEN>,
}
pub struct DataConsumer<const BUF_SIZE: usize, const SIZES_LEN: usize> {
pub buf_cons: CachingCons<&'static StaticRb<u8, BUF_SIZE>>,
pub sizes_cons: CachingCons<&'static StaticRb<usize, SIZES_LEN>>,
pub struct RingBufWrapper<const BUF_SIZE: usize, const SIZES_LEN: usize> {
pub buf: StaticRb<u8, BUF_SIZE>,
pub sizes: StaticRb<usize, SIZES_LEN>,
}
pub const APP_A_START_ADDR: u32 = 0x3000;
pub const APP_A_END_ADDR: u32 = 0x11800;
pub const APP_A_END_ADDR: u32 = 0x117FC;
pub const APP_B_START_ADDR: u32 = APP_A_END_ADDR;
pub const APP_B_END_ADDR: u32 = 0x20000;
pub const PREFERRED_SLOT_OFFSET: u32 = 0x20000 - 1;
#[rtic::app(device = pac, dispatchers = [OC20, OC21, OC22])]
mod app {
use super::*;
@ -94,12 +87,6 @@ mod app {
uart_rx: uart::RxWithIrq<pac::Uarta>,
uart_tx: uart::Tx<pac::Uarta>,
rx_context: IrqContextTimeoutOrMaxSize,
// We handle all TM in one task.
tm_cons: DataConsumer<BUF_RB_SIZE_TM, SIZES_RB_SIZE_TM>,
// We consume all TC in one task.
tc_cons: DataConsumer<BUF_RB_SIZE_TC, SIZES_RB_SIZE_TC>,
// We produce all TC in one task.
tc_prod: DataProducer<BUF_RB_SIZE_TC, SIZES_RB_SIZE_TC>,
verif_reporter: VerificationReportCreator,
nvm: M95M01,
}
@ -107,7 +94,8 @@ mod app {
#[shared]
struct Shared {
// Having this shared allows multiple tasks to generate telemetry.
tm_prod: DataProducer<BUF_RB_SIZE_TM, SIZES_RB_SIZE_TM>,
tm_rb: RingBufWrapper<BUF_RB_SIZE_TM, SIZES_RB_SIZE_TM>,
tc_rb: RingBufWrapper<BUF_RB_SIZE_TC, SIZES_RB_SIZE_TC>,
}
rtic_monotonics::systick_monotonic!(Mono, 1000);
@ -122,7 +110,7 @@ mod app {
let mut dp = cx.device;
let nvm = M95M01::new(&mut dp.sysconfig, SYSCLK_FREQ, dp.spic);
let gpioa = PinsA::new(&mut dp.sysconfig, Some(dp.ioconfig), dp.porta);
let gpioa = PinsA::new(&mut dp.sysconfig, dp.porta);
let tx = gpioa.pa9.into_funsel_2();
let rx = gpioa.pa8.into_funsel_2();
@ -138,12 +126,6 @@ mod app {
let verif_reporter = VerificationReportCreator::new(0).unwrap();
let (buf_prod_tm, buf_cons_tm) = unsafe { BUF_RB_TM.split_ref() };
let (sizes_prod_tm, sizes_cons_tm) = unsafe { SIZES_RB_TM.split_ref() };
let (buf_prod_tc, buf_cons_tc) = unsafe { BUF_RB_TC.split_ref() };
let (sizes_prod_tc, sizes_cons_tc) = unsafe { SIZES_RB_TC.split_ref() };
let mut rx_context = IrqContextTimeoutOrMaxSize::new(MAX_TC_FRAME_SIZE);
rx.read_fixed_len_or_timeout_based_using_irq(&mut rx_context)
.expect("initiating UART RX failed");
@ -151,27 +133,19 @@ mod app {
pus_tm_tx_handler::spawn().unwrap();
(
Shared {
tm_prod: DataProducer {
buf_prod: buf_prod_tm,
sizes_prod: sizes_prod_tm,
tc_rb: RingBufWrapper {
buf: StaticRb::default(),
sizes: StaticRb::default(),
},
tm_rb: RingBufWrapper {
buf: StaticRb::default(),
sizes: StaticRb::default(),
},
},
Local {
uart_rx: rx,
uart_tx: tx,
rx_context,
tm_cons: DataConsumer {
buf_cons: buf_cons_tm,
sizes_cons: sizes_cons_tm,
},
tc_cons: DataConsumer {
buf_cons: buf_cons_tc,
sizes_cons: sizes_cons_tc,
},
tc_prod: DataProducer {
buf_prod: buf_prod_tc,
sizes_prod: sizes_prod_tc,
},
verif_reporter,
nvm,
},
@ -194,10 +168,10 @@ mod app {
rx_buf: [u8; MAX_TC_FRAME_SIZE] = [0; MAX_TC_FRAME_SIZE],
rx_context,
uart_rx,
tc_prod
],
shared = [tc_rb]
)]
fn uart_rx_irq(cx: uart_rx_irq::Context) {
fn uart_rx_irq(mut cx: uart_rx_irq::Context) {
match cx
.local
.uart_rx
@ -220,16 +194,17 @@ mod app {
log::warn!("COBS decoding failed");
} else {
let decoded_size = decoded_size.unwrap();
if cx.local.tc_prod.sizes_prod.vacant_len() >= 1
&& cx.local.tc_prod.buf_prod.vacant_len() >= decoded_size
{
// Should never fail, we checked there is enough space.
cx.local.tc_prod.sizes_prod.try_push(decoded_size).unwrap();
cx.local
.tc_prod
.buf_prod
.push_slice(&cx.local.rx_buf[1..1 + decoded_size]);
} else {
let mut tc_rb_full = false;
cx.shared.tc_rb.lock(|rb| {
if rb.sizes.vacant_len() >= 1 && rb.buf.vacant_len() >= decoded_size
{
rb.sizes.try_push(decoded_size).unwrap();
rb.buf.push_slice(&cx.local.rx_buf[1..1 + decoded_size]);
} else {
tc_rb_full = true;
}
});
if tc_rb_full {
log::warn!("COBS TC queue full");
}
}
@ -260,16 +235,15 @@ mod app {
readback_buf: [u8; MAX_TC_SIZE] = [0; MAX_TC_SIZE],
src_data_buf: [u8; 16] = [0; 16],
verif_buf: [u8; 32] = [0; 32],
tc_cons,
nvm,
verif_reporter
],
shared=[tm_prod]
shared=[tm_rb, tc_rb]
)]
async fn pus_tc_handler(mut cx: pus_tc_handler::Context) {
loop {
// Try to read a TC from the ring buffer.
let packet_len = cx.local.tc_cons.sizes_cons.try_pop();
let packet_len = cx.shared.tc_rb.lock(|rb| rb.sizes.try_pop());
if packet_len.is_none() {
// Small delay, TCs might arrive very quickly.
Mono::delay(20.millis()).await;
@ -277,13 +251,11 @@ mod app {
}
let packet_len = packet_len.unwrap();
log::info!(target: "TC Handler", "received packet with length {}", packet_len);
assert_eq!(
cx.local
.tc_cons
.buf_cons
.pop_slice(&mut cx.local.tc_buf[0..packet_len]),
packet_len
);
let popped_packet_len = cx
.shared
.tc_rb
.lock(|rb| rb.buf.pop_slice(&mut cx.local.tc_buf[0..packet_len]));
assert_eq!(popped_packet_len, packet_len);
// Read a telecommand, now handle it.
handle_valid_pus_tc(&mut cx);
}
@ -298,10 +270,9 @@ mod app {
let (pus_tc, _) = pus_tc.unwrap();
let mut write_and_send = |tm: &PusTmCreator| {
let written_size = tm.write_to_bytes(cx.local.verif_buf).unwrap();
cx.shared.tm_prod.lock(|prod| {
prod.sizes_prod.try_push(tm.len_written()).unwrap();
prod.buf_prod
.push_slice(&cx.local.verif_buf[0..written_size]);
cx.shared.tm_rb.lock(|prod| {
prod.sizes.try_push(tm.len_written()).unwrap();
prod.buf.push_slice(&cx.local.verif_buf[0..written_size]);
});
};
let token = cx.local.verif_reporter.add_tc(&pus_tc);
@ -346,6 +317,26 @@ mod app {
rprintln!("corrupting App Image B");
corrupt_image(APP_B_START_ADDR);
}
if pus_tc.subservice() == ActionId::SetBootSlot as u8 {
if pus_tc.app_data().is_empty() {
log::warn!(target: "TC Handler", "App data for preferred image command too short");
}
let app_sel_result = AppSel::try_from(pus_tc.app_data()[0]);
if app_sel_result.is_err() {
log::warn!("Invalid app selection value: {}", pus_tc.app_data()[0]);
}
log::info!(target: "TC Handler", "received boot selection command with app select: {:?}", app_sel_result.unwrap());
cx.local
.nvm
.write(PREFERRED_SLOT_OFFSET as usize, &[pus_tc.app_data()[0]])
.expect("writing to NVM failed");
let tm = cx
.local
.verif_reporter
.completion_success(cx.local.src_data_buf, started_token, 0, 0, &[])
.expect("completion success failed");
write_and_send(&tm);
}
}
if pus_tc.service() == PusServiceId::Test as u8 && pus_tc.subservice() == 1 {
log::info!(target: "TC Handler", "received ping TC");
@ -444,18 +435,18 @@ mod app {
read_buf: [u8;MAX_TM_SIZE] = [0; MAX_TM_SIZE],
encoded_buf: [u8;MAX_TM_FRAME_SIZE] = [0; MAX_TM_FRAME_SIZE],
uart_tx,
tm_cons
],
shared=[]
shared=[tm_rb]
)]
async fn pus_tm_tx_handler(cx: pus_tm_tx_handler::Context) {
async fn pus_tm_tx_handler(mut cx: pus_tm_tx_handler::Context) {
loop {
while cx.local.tm_cons.sizes_cons.occupied_len() > 0 {
let next_size = cx.local.tm_cons.sizes_cons.try_pop().unwrap();
cx.local
.tm_cons
.buf_cons
.pop_slice(&mut cx.local.read_buf[0..next_size]);
let mut occupied_len = cx.shared.tm_rb.lock(|rb| rb.sizes.occupied_len());
while occupied_len > 0 {
let next_size = cx.shared.tm_rb.lock(|rb| {
let next_size = rb.sizes.try_pop().unwrap();
rb.buf.pop_slice(&mut cx.local.read_buf[0..next_size]);
next_size
});
cx.local.encoded_buf[0] = 0;
let send_size = cobs::encode(
&cx.local.read_buf[0..next_size],
@ -466,6 +457,7 @@ mod app {
.uart_tx
.write(&cx.local.encoded_buf[0..send_size + 2])
.unwrap();
occupied_len -= 1;
Mono::delay(2.millis()).await;
}
Mono::delay(50.millis()).await;

View File

@ -1,3 +1,3 @@
#!/bin/bash
JLinkGDBServer -select USB -device Cortex-M0 -endian little -if JTAG-speed auto \
JLinkGDBServer -select USB -device Cortex-M0 -endian little -if JTAG -speed auto \
-LocalhostOnly

View File

@ -9,6 +9,7 @@ variants:
core_access_options: !Arm
ap: 0
psel: 0x0
jtag_tap: 1
memory_map:
- !Ram
name: DRAM
@ -22,9 +23,11 @@ variants:
range:
start: 0x0
end: 0x20000
is_boot_memory: true
cores:
- main
access:
write: false
boot: true
flash_algorithms:
- va108xx_fm25v20a_fram_128kb_prog
- va108xx_m95m01_128kb_prog
@ -37,6 +40,7 @@ variants:
core_access_options: !Arm
ap: 0
psel: 0x0
jtag_tap: 1
memory_map:
- !Ram
name: DRAM
@ -50,9 +54,11 @@ variants:
range:
start: 0x0
end: 0x20000
is_boot_memory: true
cores:
- main
access:
write: false
boot: true
flash_algorithms:
- name: va108xx_fm25v20a_fram_128kb_prog
description: VA108_FM25V20A_FRAM_128KB

View File

@ -0,0 +1,27 @@
[package]
name = "va108xx-embassy"
version = "0.1.0"
edition = "2021"
[dependencies]
critical-section = "1"
portable-atomic = { version = "1", features = ["unsafe-assume-single-core"]}
embassy-sync = "0.6"
embassy-executor = "0.7"
embassy-time-driver = "0.2"
embassy-time-queue-utils = "0.1"
once_cell = { version = "1", default-features = false, features = ["critical-section"] }
[dependencies.va108xx-hal]
path = "../va108xx-hal"
[features]
default = ["irq-oc30-oc31"]
irqs-in-lib = []
# This determines the reserved interrupt functions for the embassy time drivers. Only one
# is allowed to be selected!
irq-oc28-oc29 = ["irqs-in-lib"]
irq-oc29-oc30 = ["irqs-in-lib"]
irq-oc30-oc31 = ["irqs-in-lib"]

10
va108xx-embassy/README.md Normal file
View File

@ -0,0 +1,10 @@
[![Crates.io](https://img.shields.io/crates/v/va108xx-embassy)](https://crates.io/crates/va108xx-embassy)
[![docs.rs](https://img.shields.io/docsrs/va108xx-embassy)](https://docs.rs/va108xx-embassy)
# Embassy-rs support for the Vorago VA108xx MCU family
This repository contains the [embassy-rs](https://github.com/embassy-rs/embassy) support for the
VA108xx family. Currently, it contains the time driver to allow using embassy-rs. It uses the TIM
peripherals provided by the VA108xx family for this purpose.
The documentation contains more information on how to use this crate.

416
va108xx-embassy/src/lib.rs Normal file
View File

@ -0,0 +1,416 @@
//! # Embassy-rs support for the Vorago VA108xx MCU family
//!
//! This repository contains the [embassy-rs](https://github.com/embassy-rs/embassy) support for the
//! VA108xx family. Currently, it contains the time driver to allow using embassy-rs. It uses the TIM
//! peripherals provided by the VA108xx family for this purpose.
//!
//! ## Usage
//!
//! This library only exposes the [embassy::init] method which sets up the time driver. This
//! function must be called once at the start of the application.
//!
//! This implementation requires two TIM peripherals provided by the VA108xx device.
//! The user can freely specify the two used TIM peripheral by passing the concrete TIM instances
//! into the [embassy::init_with_custom_irqs] and [embassy::init] method.
//!
//! The application also requires two interrupt handlers to handle the timekeeper and alarm
//! interrupts. By default, this library will define the interrupt handler inside the library
//! itself by using the `irq-oc30-oc31` feature flag. This library exposes three combinations:
//!
//! - `irq-oc30-oc31`: Uses [pac::Interrupt::OC30] and [pac::Interrupt::OC31]
//! - `irq-oc29-oc30`: Uses [pac::Interrupt::OC29] and [pac::Interrupt::OC30]
//! - `irq-oc28-oc29`: Uses [pac::Interrupt::OC28] and [pac::Interrupt::OC20]
//!
//! 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
//! using the [embassy::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
//! method to pass the IRQ numbers to the library.
//!
//! ## Examples
//!
//! [embassy example project](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/examples/embassy)
#![no_std]
use core::cell::{Cell, RefCell};
use critical_section::CriticalSection;
use embassy_sync::blocking_mutex::CriticalSectionMutex as Mutex;
use portable_atomic::{AtomicU32, Ordering};
use embassy_time_driver::{time_driver_impl, Driver, TICK_HZ};
use embassy_time_queue_utils::Queue;
use once_cell::sync::OnceCell;
#[cfg(feature = "irqs-in-lib")]
use va108xx_hal::pac::interrupt;
use va108xx_hal::{
clock::enable_peripheral_clock,
enable_interrupt, pac,
prelude::*,
timer::{enable_tim_clk, get_tim_raw, TimRegInterface},
PeripheralSelect,
};
time_driver_impl!(
static TIME_DRIVER: TimerDriver = TimerDriver {
periods: AtomicU32::new(0),
alarms: Mutex::new(AlarmState::new()),
queue: Mutex::new(RefCell::new(Queue::new())),
});
/// Macro to define the IRQ handlers for the time driver.
///
/// By default, the code generated by this macro will be defined inside the library depending on
/// the feature flags specified. However, the macro is exported to allow users to specify the
/// interrupt handlers themselves.
///
/// Please note that you have to explicitely import the [va108xx_hal::pac::interrupt]
/// macro in the application code in case this macro is used there.
#[macro_export]
macro_rules! embassy_time_driver_irqs {
(
timekeeper_irq = $timekeeper_irq:ident,
alarm_irq = $alarm_irq:ident
) => {
const TIMEKEEPER_IRQ: pac::Interrupt = pac::Interrupt::$timekeeper_irq;
#[interrupt]
#[allow(non_snake_case)]
fn $timekeeper_irq() {
// Safety: We call it once here.
unsafe { $crate::embassy::time_driver().on_interrupt_timekeeping() }
}
const ALARM_IRQ: pac::Interrupt = pac::Interrupt::$alarm_irq;
#[interrupt]
#[allow(non_snake_case)]
fn $alarm_irq() {
// Safety: We call it once here.
unsafe { $crate::embassy::time_driver().on_interrupt_alarm() }
}
};
}
// Provide three combinations of IRQs for the time driver by default.
#[cfg(feature = "irq-oc30-oc31")]
embassy_time_driver_irqs!(timekeeper_irq = OC31, alarm_irq = OC30);
#[cfg(feature = "irq-oc29-oc30")]
embassy_time_driver_irqs!(timekeeper_irq = OC30, alarm_irq = OC29);
#[cfg(feature = "irq-oc28-oc29")]
embassy_time_driver_irqs!(timekeeper_irq = OC29, alarm_irq = OC28);
pub mod embassy {
use super::*;
use va108xx_hal::{pac, timer::TimRegInterface};
/// Expose the time driver so the user can specify the IRQ handlers themselves.
pub fn time_driver() -> &'static TimerDriver {
&TIME_DRIVER
}
/// Initialization method for embassy
///
/// # Safety
///
/// This has to be called once at initialization time to initiate the time driver for
/// embassy.
#[cfg(feature = "irqs-in-lib")]
pub unsafe fn init(
syscfg: &mut pac::Sysconfig,
irqsel: &pac::Irqsel,
sysclk: impl Into<Hertz>,
timekeeper_tim: impl TimRegInterface,
alarm_tim: impl TimRegInterface,
) {
TIME_DRIVER.init(
syscfg,
irqsel,
sysclk,
timekeeper_tim,
alarm_tim,
TIMEKEEPER_IRQ,
ALARM_IRQ,
)
}
/// Initialization method for embassy
///
/// # Safety
///
/// This has to be called once at initialization time to initiate the time driver for
/// embassy.
pub unsafe fn init_with_custom_irqs(
syscfg: &mut pac::Sysconfig,
irqsel: &pac::Irqsel,
sysclk: impl Into<Hertz>,
timekeeper_tim: impl TimRegInterface,
alarm_tim: impl TimRegInterface,
timekeeper_irq: pac::Interrupt,
alarm_irq: pac::Interrupt,
) {
TIME_DRIVER.init(
syscfg,
irqsel,
sysclk,
timekeeper_tim,
alarm_tim,
timekeeper_irq,
alarm_irq,
)
}
}
struct AlarmState {
timestamp: Cell<u64>,
}
impl AlarmState {
const fn new() -> Self {
Self {
timestamp: Cell::new(u64::MAX),
}
}
}
unsafe impl Send for AlarmState {}
static SCALE: OnceCell<u64> = OnceCell::new();
static TIMEKEEPER_TIM: OnceCell<u8> = OnceCell::new();
static ALARM_TIM: OnceCell<u8> = OnceCell::new();
pub struct TimerDriver {
periods: AtomicU32,
/// Timestamp at which to fire alarm. u64::MAX if no alarm is scheduled.
alarms: Mutex<AlarmState>,
queue: Mutex<RefCell<Queue>>,
}
impl TimerDriver {
#[allow(clippy::too_many_arguments)]
fn init(
&self,
syscfg: &mut pac::Sysconfig,
irqsel: &pac::Irqsel,
sysclk: impl Into<Hertz>,
timekeeper_tim: impl TimRegInterface,
alarm_tim: impl TimRegInterface,
timekeeper_irq: pac::Interrupt,
alarm_irq: pac::Interrupt,
) {
if ALARM_TIM.get().is_some() {
return;
}
ALARM_TIM.set(alarm_tim.tim_id()).ok();
TIMEKEEPER_TIM.set(timekeeper_tim.tim_id()).ok();
enable_peripheral_clock(syscfg, PeripheralSelect::Irqsel);
enable_tim_clk(syscfg, timekeeper_tim.tim_id());
let timekeeper_reg_block = timekeeper_tim.reg_block();
let alarm_tim_reg_block = alarm_tim.reg_block();
let sysclk = sysclk.into();
// Initiate scale value here. This is required to convert timer ticks back to a timestamp.
SCALE.set((sysclk.raw() / TICK_HZ as u32) as u64).unwrap();
timekeeper_reg_block
.rst_value()
.write(|w| unsafe { w.bits(u32::MAX) });
// Decrementing counter.
timekeeper_reg_block
.cnt_value()
.write(|w| unsafe { w.bits(u32::MAX) });
// Switch on. Timekeeping should always be done.
irqsel
.tim0(timekeeper_tim.tim_id() as usize)
.write(|w| unsafe { w.bits(timekeeper_irq as u32) });
unsafe {
enable_interrupt(timekeeper_irq);
}
timekeeper_reg_block
.ctrl()
.modify(|_, w| w.irq_enb().set_bit());
timekeeper_reg_block
.enable()
.write(|w| unsafe { w.bits(1) });
enable_tim_clk(syscfg, alarm_tim.tim_id());
// Explicitely disable alarm timer until needed.
alarm_tim_reg_block.ctrl().modify(|_, w| {
w.irq_enb().clear_bit();
w.enable().clear_bit()
});
// Enable general interrupts. The IRQ enable of the peripheral remains cleared.
unsafe {
enable_interrupt(alarm_irq);
}
irqsel
.tim0(alarm_tim.tim_id() as usize)
.write(|w| unsafe { w.bits(alarm_irq as u32) });
}
/// Should be called inside the IRQ of the timekeeper timer.
///
/// # Safety
///
/// This function has to be called once by the TIM IRQ used for the timekeeping.
pub unsafe fn on_interrupt_timekeeping(&self) {
self.next_period();
}
/// Should be called inside the IRQ of the alarm timer.
///
/// # Safety
///
///This function has to be called once by the TIM IRQ used for the timekeeping.
pub unsafe fn on_interrupt_alarm(&self) {
critical_section::with(|cs| {
if self.alarms.borrow(cs).timestamp.get() <= self.now() {
self.trigger_alarm(cs)
}
})
}
fn timekeeper_tim() -> &'static pac::tim0::RegisterBlock {
TIMEKEEPER_TIM
.get()
.map(|idx| unsafe { get_tim_raw(*idx as usize) })
.unwrap()
}
fn alarm_tim() -> &'static pac::tim0::RegisterBlock {
ALARM_TIM
.get()
.map(|idx| unsafe { get_tim_raw(*idx as usize) })
.unwrap()
}
fn next_period(&self) {
let period = self.periods.fetch_add(1, Ordering::AcqRel) + 1;
let t = (period as u64) << 32;
critical_section::with(|cs| {
let alarm = &self.alarms.borrow(cs);
let at = alarm.timestamp.get();
if at < t {
self.trigger_alarm(cs);
} else {
let alarm_tim = Self::alarm_tim();
let remaining_ticks = (at - t).checked_mul(*SCALE.get().unwrap());
if remaining_ticks.is_some_and(|v| v <= u32::MAX as u64) {
alarm_tim.enable().write(|w| unsafe { w.bits(0) });
alarm_tim
.cnt_value()
.write(|w| unsafe { w.bits(remaining_ticks.unwrap() as u32) });
alarm_tim.ctrl().modify(|_, w| w.irq_enb().set_bit());
alarm_tim.enable().write(|w| unsafe { w.bits(1) })
}
}
})
}
fn trigger_alarm(&self, cs: CriticalSection) {
Self::alarm_tim().ctrl().modify(|_, w| {
w.irq_enb().clear_bit();
w.enable().clear_bit()
});
let alarm = &self.alarms.borrow(cs);
// Setting the maximum value disables the alarm.
alarm.timestamp.set(u64::MAX);
// Call after clearing alarm, so the callback can set another alarm.
let mut next = self
.queue
.borrow(cs)
.borrow_mut()
.next_expiration(self.now());
while !self.set_alarm(cs, next) {
next = self
.queue
.borrow(cs)
.borrow_mut()
.next_expiration(self.now());
}
}
fn set_alarm(&self, cs: CriticalSection, timestamp: u64) -> bool {
if SCALE.get().is_none() {
return false;
}
let alarm_tim = Self::alarm_tim();
alarm_tim.ctrl().modify(|_, w| {
w.irq_enb().clear_bit();
w.enable().clear_bit()
});
let alarm = self.alarms.borrow(cs);
alarm.timestamp.set(timestamp);
let t = self.now();
if timestamp <= t {
alarm.timestamp.set(u64::MAX);
return false;
}
// If it hasn't triggered yet, setup the relevant reset value, regardless of whether
// the interrupts are enabled or not. When they are enabled at a later point, the
// right value is already set.
// If the timestamp is in the next few ticks, add a bit of buffer to be sure the alarm
// is not missed.
//
// This means that an alarm can be delayed for up to 2 ticks (from t+1 to t+3), but this is allowed
// by the Alarm trait contract. What's not allowed is triggering alarms *before* their scheduled time,
// and we don't do that here.
let safe_timestamp = timestamp.max(t + 3);
let timer_ticks = (safe_timestamp - t).checked_mul(*SCALE.get().unwrap());
alarm_tim.rst_value().write(|w| unsafe { w.bits(u32::MAX) });
if timer_ticks.is_some_and(|v| v <= u32::MAX as u64) {
alarm_tim
.cnt_value()
.write(|w| unsafe { w.bits(timer_ticks.unwrap() as u32) });
alarm_tim.ctrl().modify(|_, w| w.irq_enb().set_bit());
alarm_tim.enable().write(|w| unsafe { w.bits(1) });
}
// If it's too far in the future, don't enable timer yet.
// It will be enabled later by `next_period`.
true
}
}
impl Driver for TimerDriver {
fn now(&self) -> u64 {
if SCALE.get().is_none() {
return 0;
}
let mut period1: u32;
let mut period2: u32;
let mut counter_val: u32;
loop {
// Acquire ensures that we get the latest value of `periods` and
// no instructions can be reordered before the load.
period1 = self.periods.load(Ordering::Acquire);
counter_val = u32::MAX - Self::timekeeper_tim().cnt_value().read().bits();
// Double read to protect against race conditions when the counter is overflowing.
period2 = self.periods.load(Ordering::Relaxed);
if period1 == period2 {
let now = (((period1 as u64) << 32) | counter_val as u64) / *SCALE.get().unwrap();
return now;
}
}
}
fn schedule_wake(&self, at: u64, waker: &core::task::Waker) {
critical_section::with(|cs| {
let mut queue = self.queue.borrow(cs).borrow_mut();
if queue.schedule_wake(at, waker) {
let mut next = queue.next_expiration(self.now());
while !self.set_alarm(cs, next) {
next = queue.next_expiration(self.now());
}
}
})
}
}

View File

@ -8,6 +8,29 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [unreleased]
## [v0.9.0]
## Removed
- Deleted some HAL re-exports in the PWM module
## Changed
- GPIO API: Interrupt, pulse and filter and `set_datamask` and `clear_datamask` APIs are now
methods which mutable modify the pin instead of consuming and returning it.
- Simplified PWM module implementation.
- All error types now implement `core::error::Error` by using the `thiserror::Error` derive.
- `InvalidPinTypeError` now wraps the pin mode.
- I2C `TimingCfg` constructor now returns explicit error instead of generic Error.
Removed the timing configuration error type from the generic I2C error enumeration.
- `PinsA` and `PinsB` constructor do not expect an optional `pac::Ioconfig` argument anymore.
## Added
- Add `downgrade` method for `Pin` and `upgrade` method for `DynPin` as explicit conversion
methods.
- Add new `get_tim_raw` unsafe method to retrieve TIM peripheral blocks.
## [v0.8.0] 2024-09-30
## Changed

View File

@ -15,32 +15,22 @@ cortex-m = { version = "0.7", features = ["critical-section-single-core"]}
cortex-m-rt = "0.7"
nb = "1"
paste = "1"
embedded-hal = "1"
embedded-hal-async = "1"
embedded-hal-nb = "1"
embedded-io = "0.6"
fugit = "0.3"
typenum = "1"
critical-section = "1"
delegate = "0.12"
delegate = ">=0.12, <=0.13"
thiserror = { version = "2", default-features = false }
void = { version = "1", default-features = false }
once_cell = {version = "1", default-features = false }
va108xx = { version = "0.3", default-features = false, features = ["critical-section"]}
portable-atomic = { version = "1", features = ["unsafe-assume-single-core"]}
embassy-sync = "0.6"
[dependencies.va108xx]
version = "0.3"
default-features = false
features = ["critical-section"]
[dependencies.embedded-hal]
version = "1"
[dependencies.void]
version = "1"
default-features = false
[dependencies.once_cell]
version = "1.14"
default-features = false
[dependencies.defmt]
version = "0.3"
optional = true
defmt = { version = "0.3", optional = true }
[features]
default = ["rt"]

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

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

View File

@ -0,0 +1,449 @@
//! # Async GPIO functionality for the VA108xx family.
//!
//! This module provides the [InputPinAsync] and [InputDynPinAsync] which both implement
//! the [embedded_hal_async::digital::Wait] trait. These types allow for asynchronous waiting
//! on GPIO pins. Please note that this module does not specify/declare the interrupt handlers
//! which must be provided for async support to work. However, it provides one generic
//! [handler][handle_interrupt_for_async_gpio] which should be called in ALL user interrupt handlers
//! for which handle GPIO interrupts.
//!
//! # Example
//!
//! - [Async GPIO example](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/async-gpio/examples/embassy/src/bin/async-gpio.rs)
use core::future::Future;
use embassy_sync::waitqueue::AtomicWaker;
use embedded_hal::digital::InputPin;
use embedded_hal_async::digital::Wait;
use portable_atomic::AtomicBool;
use va108xx::{self as pac, Irqsel, Sysconfig};
use crate::IrqCfg;
use super::{
pin, DynGroup, DynPin, DynPinId, InputConfig, InterruptEdge, InvalidPinTypeError, Pin, PinId,
NUM_GPIO_PINS, NUM_PINS_PORT_A,
};
static WAKERS: [AtomicWaker; NUM_GPIO_PINS] = [const { AtomicWaker::new() }; NUM_GPIO_PINS];
static EDGE_DETECTION: [AtomicBool; NUM_GPIO_PINS] =
[const { AtomicBool::new(false) }; NUM_GPIO_PINS];
#[inline]
fn pin_id_to_offset(dyn_pin_id: DynPinId) -> usize {
match dyn_pin_id.group {
DynGroup::A => dyn_pin_id.num as usize,
DynGroup::B => NUM_PINS_PORT_A + dyn_pin_id.num as usize,
}
}
/// Generic interrupt handler for GPIO interrupts to support the async functionalities.
///
/// This handler will wake the correspoding wakers for the pins which triggered an interrupt
/// as well as updating the static edge detection structures. This allows the pin future to
/// complete async operations. The user should call this function in ALL interrupt handlers
/// which handle any GPIO interrupts.
#[inline]
pub fn handle_interrupt_for_async_gpio() {
let periphs = unsafe { pac::Peripherals::steal() };
handle_interrupt_for_gpio_and_port(
periphs.porta.irq_enb().read().bits(),
periphs.porta.edge_status().read().bits(),
0,
);
handle_interrupt_for_gpio_and_port(
periphs.portb.irq_enb().read().bits(),
periphs.portb.edge_status().read().bits(),
NUM_PINS_PORT_A,
);
}
// Uses the enabled interrupt register and the persistent edge status to capture all GPIO events.
#[inline]
fn handle_interrupt_for_gpio_and_port(mut irq_enb: u32, edge_status: u32, pin_base_offset: usize) {
while irq_enb != 0 {
let bit_pos = irq_enb.trailing_zeros() as usize;
let bit_mask = 1 << bit_pos;
WAKERS[pin_base_offset + bit_pos].wake();
if edge_status & bit_mask != 0 {
EDGE_DETECTION[pin_base_offset + bit_pos]
.store(true, core::sync::atomic::Ordering::Relaxed);
}
// Clear the processed bit
irq_enb &= !bit_mask;
}
}
/// Input pin future which implements the [Future] trait.
///
/// Generally, you want to use the [InputPinAsync] or [InputDynPinAsync] types instead of this
/// which also implements the [embedded_hal_async::digital::Wait] trait. However, access to this
/// struture is granted to allow writing custom async structures.
pub struct InputPinFuture {
pin_id: DynPinId,
}
impl InputPinFuture {
/// # Safety
///
/// This calls [Self::new] but uses [pac::Peripherals::steal] to get the system configuration
/// and IRQ selection peripherals. Users must ensure that the registers and configuration
/// related to this input pin are not being used elsewhere concurrently.
pub unsafe fn new_unchecked_with_dyn_pin(
pin: &mut DynPin,
irq: pac::Interrupt,
edge: InterruptEdge,
) -> Result<Self, InvalidPinTypeError> {
let mut periphs = pac::Peripherals::steal();
Self::new_with_dyn_pin(pin, irq, edge, &mut periphs.sysconfig, &mut periphs.irqsel)
}
pub fn new_with_dyn_pin(
pin: &mut DynPin,
irq: pac::Interrupt,
edge: InterruptEdge,
sys_cfg: &mut Sysconfig,
irq_sel: &mut Irqsel,
) -> Result<Self, InvalidPinTypeError> {
if !pin.is_input_pin() {
return Err(InvalidPinTypeError(pin.mode()));
}
EDGE_DETECTION[pin_id_to_offset(pin.id())]
.store(false, core::sync::atomic::Ordering::Relaxed);
pin.interrupt_edge(
edge,
IrqCfg::new(irq, true, true),
Some(sys_cfg),
Some(irq_sel),
)
.unwrap();
Ok(Self { pin_id: pin.id() })
}
/// # Safety
///
/// This calls [Self::new] but uses [pac::Peripherals::steal] to get the system configuration
/// and IRQ selection peripherals. Users must ensure that the registers and configuration
/// related to this input pin are not being used elsewhere concurrently.
pub unsafe fn new_unchecked_with_pin<I: PinId, C: InputConfig>(
pin: &mut Pin<I, pin::Input<C>>,
irq: pac::Interrupt,
edge: InterruptEdge,
) -> Self {
let mut periphs = pac::Peripherals::steal();
Self::new_with_pin(pin, irq, edge, &mut periphs.sysconfig, &mut periphs.irqsel)
}
pub fn new_with_pin<I: PinId, C: InputConfig>(
pin: &mut Pin<I, pin::Input<C>>,
irq: pac::Interrupt,
edge: InterruptEdge,
sys_cfg: &mut Sysconfig,
irq_sel: &mut Irqsel,
) -> Self {
EDGE_DETECTION[pin_id_to_offset(pin.id())]
.store(false, core::sync::atomic::Ordering::Relaxed);
pin.interrupt_edge(
edge,
IrqCfg::new(irq, true, true),
Some(sys_cfg),
Some(irq_sel),
);
Self { pin_id: pin.id() }
}
}
impl Drop for InputPinFuture {
fn drop(&mut self) {
let periphs = unsafe { pac::Peripherals::steal() };
if self.pin_id.group == DynGroup::A {
periphs
.porta
.irq_enb()
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.pin_id.num)) });
} else {
periphs
.porta
.irq_enb()
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.pin_id.num)) });
}
}
}
impl Future for InputPinFuture {
type Output = ();
fn poll(
self: core::pin::Pin<&mut Self>,
cx: &mut core::task::Context<'_>,
) -> core::task::Poll<Self::Output> {
let idx = pin_id_to_offset(self.pin_id);
WAKERS[idx].register(cx.waker());
if EDGE_DETECTION[idx].swap(false, core::sync::atomic::Ordering::Relaxed) {
return core::task::Poll::Ready(());
}
core::task::Poll::Pending
}
}
pub struct InputDynPinAsync {
pin: DynPin,
irq: pac::Interrupt,
}
impl InputDynPinAsync {
/// Create a new asynchronous input pin from a [DynPin]. The interrupt ID to be used must be
/// passed as well and is used to route and enable the interrupt.
///
/// Please note that the interrupt handler itself must be provided by the user and the
/// generic [handle_interrupt_for_async_gpio] function must be called inside that function for
/// the asynchronous functionality to work.
pub fn new(pin: DynPin, irq: pac::Interrupt) -> Result<Self, InvalidPinTypeError> {
if !pin.is_input_pin() {
return Err(InvalidPinTypeError(pin.mode()));
}
Ok(Self { pin, irq })
}
/// Asynchronously wait until the pin is high.
///
/// This returns immediately if the pin is already high.
pub async fn wait_for_high(&mut self) {
let fut = unsafe {
// Unwrap okay, checked pin in constructor.
InputPinFuture::new_unchecked_with_dyn_pin(
&mut self.pin,
self.irq,
InterruptEdge::LowToHigh,
)
.unwrap()
};
if self.pin.is_high().unwrap() {
return;
}
fut.await;
}
/// Asynchronously wait until the pin is low.
///
/// This returns immediately if the pin is already high.
pub async fn wait_for_low(&mut self) {
let fut = unsafe {
// Unwrap okay, checked pin in constructor.
InputPinFuture::new_unchecked_with_dyn_pin(
&mut self.pin,
self.irq,
InterruptEdge::HighToLow,
)
.unwrap()
};
if self.pin.is_low().unwrap() {
return;
}
fut.await;
}
/// Asynchronously wait until the pin sees a falling edge.
pub async fn wait_for_falling_edge(&mut self) {
unsafe {
// Unwrap okay, checked pin in constructor.
InputPinFuture::new_unchecked_with_dyn_pin(
&mut self.pin,
self.irq,
InterruptEdge::HighToLow,
)
.unwrap()
}
.await;
}
/// Asynchronously wait until the pin sees a rising edge.
pub async fn wait_for_rising_edge(&mut self) {
unsafe {
// Unwrap okay, checked pin in constructor.
InputPinFuture::new_unchecked_with_dyn_pin(
&mut self.pin,
self.irq,
InterruptEdge::LowToHigh,
)
.unwrap()
}
.await;
}
/// Asynchronously wait until the pin sees any edge (either rising or falling).
pub async fn wait_for_any_edge(&mut self) {
unsafe {
// Unwrap okay, checked pin in constructor.
InputPinFuture::new_unchecked_with_dyn_pin(
&mut self.pin,
self.irq,
InterruptEdge::BothEdges,
)
.unwrap()
}
.await;
}
pub fn release(self) -> DynPin {
self.pin
}
}
impl embedded_hal::digital::ErrorType for InputDynPinAsync {
type Error = core::convert::Infallible;
}
impl Wait for InputDynPinAsync {
async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
self.wait_for_high().await;
Ok(())
}
async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
self.wait_for_low().await;
Ok(())
}
async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
self.wait_for_rising_edge().await;
Ok(())
}
async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
self.wait_for_falling_edge().await;
Ok(())
}
async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
self.wait_for_any_edge().await;
Ok(())
}
}
pub struct InputPinAsync<I: PinId, C: InputConfig> {
pin: Pin<I, pin::Input<C>>,
irq: pac::Interrupt,
}
impl<I: PinId, C: InputConfig> InputPinAsync<I, C> {
/// Create a new asynchronous input pin from a typed [Pin]. The interrupt ID to be used must be
/// passed as well and is used to route and enable the interrupt.
///
/// Please note that the interrupt handler itself must be provided by the user and the
/// generic [handle_interrupt_for_async_gpio] function must be called inside that function for
/// the asynchronous functionality to work.
pub fn new(pin: Pin<I, pin::Input<C>>, irq: pac::Interrupt) -> Self {
Self { pin, irq }
}
/// Asynchronously wait until the pin is high.
///
/// This returns immediately if the pin is already high.
pub async fn wait_for_high(&mut self) {
let fut = unsafe {
InputPinFuture::new_unchecked_with_pin(
&mut self.pin,
self.irq,
InterruptEdge::LowToHigh,
)
};
if self.pin.is_high().unwrap() {
return;
}
fut.await;
}
/// Asynchronously wait until the pin is low.
///
/// This returns immediately if the pin is already high.
pub async fn wait_for_low(&mut self) {
let fut = unsafe {
InputPinFuture::new_unchecked_with_pin(
&mut self.pin,
self.irq,
InterruptEdge::HighToLow,
)
};
if self.pin.is_low().unwrap() {
return;
}
fut.await;
}
/// Asynchronously wait until the pin sees falling edge.
pub async fn wait_for_falling_edge(&mut self) {
unsafe {
// Unwrap okay, checked pin in constructor.
InputPinFuture::new_unchecked_with_pin(
&mut self.pin,
self.irq,
InterruptEdge::HighToLow,
)
}
.await;
}
/// Asynchronously wait until the pin sees rising edge.
pub async fn wait_for_rising_edge(&mut self) {
unsafe {
// Unwrap okay, checked pin in constructor.
InputPinFuture::new_unchecked_with_pin(
&mut self.pin,
self.irq,
InterruptEdge::LowToHigh,
)
}
.await;
}
/// Asynchronously wait until the pin sees any edge (either rising or falling).
pub async fn wait_for_any_edge(&mut self) {
unsafe {
InputPinFuture::new_unchecked_with_pin(
&mut self.pin,
self.irq,
InterruptEdge::BothEdges,
)
}
.await;
}
pub fn release(self) -> Pin<I, pin::Input<C>> {
self.pin
}
}
impl<I: PinId, C: InputConfig> embedded_hal::digital::ErrorType for InputPinAsync<I, C> {
type Error = core::convert::Infallible;
}
impl<I: PinId, C: InputConfig> Wait for InputPinAsync<I, C> {
async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
self.wait_for_high().await;
Ok(())
}
async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
self.wait_for_low().await;
Ok(())
}
async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
self.wait_for_rising_edge().await;
Ok(())
}
async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
self.wait_for_falling_edge().await;
Ok(())
}
async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
self.wait_for_any_edge().await;
Ok(())
}
}

View File

@ -59,8 +59,9 @@
use super::{
pin::{FilterType, InterruptEdge, InterruptLevel, Pin, PinId, PinMode, PinState},
reg::RegisterInterface,
InputDynPinAsync,
};
use crate::{clock::FilterClkSel, pac, FunSel, IrqCfg};
use crate::{clock::FilterClkSel, enable_interrupt, pac, FunSel, IrqCfg};
//==================================================================================================
// DynPinMode configurations
@ -75,7 +76,7 @@ pub enum DynDisabled {
}
/// Value-level `enum` for input configurations
#[derive(PartialEq, Eq, Clone, Copy)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum DynInput {
Floating,
PullDown,
@ -83,7 +84,7 @@ pub enum DynInput {
}
/// Value-level `enum` for output configurations
#[derive(PartialEq, Eq, Clone, Copy)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum DynOutput {
PushPull,
OpenDrain,
@ -101,9 +102,10 @@ pub type DynAlternate = FunSel;
///
/// [`DynPin`]s are not tracked and verified at compile-time, so run-time
/// operations are fallible. This `enum` represents the corresponding errors.
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct InvalidPinTypeError;
#[error("Invalid pin type for operation: {0:?}")]
pub struct InvalidPinTypeError(pub DynPinMode);
impl embedded_hal::digital::Error for InvalidPinTypeError {
fn kind(&self) -> embedded_hal::digital::ErrorKind {
@ -116,7 +118,7 @@ impl embedded_hal::digital::Error for InvalidPinTypeError {
//==================================================================================================
/// Value-level `enum` representing pin modes
#[derive(PartialEq, Eq, Clone, Copy)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum DynPinMode {
Input(DynInput),
Output(DynOutput),
@ -172,16 +174,14 @@ pub struct DynPinId {
///
/// This `struct` takes ownership of a [`DynPinId`] and provides an API to
/// access the corresponding regsiters.
struct DynRegisters {
id: DynPinId,
}
pub(crate) struct DynRegisters(DynPinId);
// [`DynRegisters`] takes ownership of the [`DynPinId`], and [`DynPin`]
// guarantees that each pin is a singleton, so this implementation is safe.
unsafe impl RegisterInterface for DynRegisters {
#[inline]
fn id(&self) -> DynPinId {
self.id
self.0
}
}
@ -194,7 +194,7 @@ impl DynRegisters {
/// the same [`DynPinId`]
#[inline]
unsafe fn new(id: DynPinId) -> Self {
DynRegisters { id }
DynRegisters(id)
}
}
@ -207,7 +207,7 @@ impl DynRegisters {
/// This type acts as a type-erased version of [`Pin`]. Every pin is represented
/// by the same type, and pins are tracked and distinguished at run-time.
pub struct DynPin {
regs: DynRegisters,
pub(crate) regs: DynRegisters,
mode: DynPinMode,
}
@ -220,7 +220,7 @@ impl DynPin {
/// must be at most one corresponding [`DynPin`] in existence at any given
/// time. Violating this requirement is `unsafe`.
#[inline]
unsafe fn new(id: DynPinId, mode: DynPinMode) -> Self {
pub(crate) unsafe fn new(id: DynPinId, mode: DynPinMode) -> Self {
DynPin {
regs: DynRegisters::new(id),
mode,
@ -230,7 +230,7 @@ impl DynPin {
/// Return a copy of the pin ID
#[inline]
pub fn id(&self) -> DynPinId {
self.regs.id
self.regs.0
}
/// Return a copy of the pin mode
@ -249,6 +249,11 @@ impl DynPin {
}
}
#[inline]
pub fn is_input_pin(&self) -> bool {
matches!(self.mode, DynPinMode::Input(_))
}
#[inline]
pub fn into_funsel_1(&mut self) {
self.into_mode(DYN_ALT_FUNC_1);
@ -306,7 +311,72 @@ impl DynPin {
self.into_mode(DYN_RD_OPEN_DRAIN_OUTPUT);
}
common_reg_if_functions!();
#[inline]
pub fn datamask(&self) -> bool {
self.regs.datamask()
}
#[inline]
pub fn clear_datamask(&mut self) {
self.regs.clear_datamask();
}
#[inline]
pub fn set_datamask(&mut self) {
self.regs.set_datamask();
}
#[inline]
pub fn is_high_masked(&self) -> Result<bool, crate::gpio::IsMaskedError> {
self.regs.read_pin_masked()
}
#[inline]
pub fn is_low_masked(&self) -> Result<bool, crate::gpio::IsMaskedError> {
self.regs.read_pin_masked().map(|v| !v)
}
#[inline]
pub fn set_high_masked(&mut self) -> Result<(), crate::gpio::IsMaskedError> {
self.regs.write_pin_masked(true)
}
#[inline]
pub fn set_low_masked(&mut self) -> Result<(), crate::gpio::IsMaskedError> {
self.regs.write_pin_masked(false)
}
pub(crate) fn irq_enb(
&mut self,
irq_cfg: crate::IrqCfg,
syscfg: Option<&mut va108xx::Sysconfig>,
irqsel: Option<&mut va108xx::Irqsel>,
) {
if let Some(syscfg) = syscfg {
crate::clock::enable_peripheral_clock(syscfg, crate::clock::PeripheralClocks::Irqsel);
}
self.regs.enable_irq();
if let Some(irqsel) = irqsel {
if irq_cfg.route {
match self.regs.id().group {
// Set the correct interrupt number in the IRQSEL register
DynGroup::A => {
irqsel
.porta0(self.regs.id().num as usize)
.write(|w| unsafe { w.bits(irq_cfg.irq as u32) });
}
DynGroup::B => {
irqsel
.portb0(self.regs.id().num as usize)
.write(|w| unsafe { w.bits(irq_cfg.irq as u32) });
}
}
}
}
if irq_cfg.enable {
unsafe { enable_interrupt(irq_cfg.irq) };
}
}
/// See p.53 of the programmers guide for more information.
/// Possible delays in clock cycles:
@ -320,74 +390,77 @@ impl DynPin {
self.regs.delay(delay_1, delay_2);
Ok(self)
}
_ => Err(InvalidPinTypeError),
_ => Err(InvalidPinTypeError(self.mode)),
}
}
/// See p.52 of the programmers guide for more information.
/// When configured for pulse mode, a given pin will set the non-default state for exactly
/// one clock cycle before returning to the configured default state
#[inline]
pub fn pulse_mode(
self,
&mut self,
enable: bool,
default_state: PinState,
) -> Result<Self, InvalidPinTypeError> {
) -> Result<(), InvalidPinTypeError> {
match self.mode {
DynPinMode::Output(_) => {
self.regs.pulse_mode(enable, default_state);
Ok(self)
Ok(())
}
_ => Err(InvalidPinTypeError),
_ => Err(InvalidPinTypeError(self.mode)),
}
}
/// See p.37 and p.38 of the programmers guide for more information.
#[inline]
pub fn filter_type(
self,
&mut self,
filter: FilterType,
clksel: FilterClkSel,
) -> Result<Self, InvalidPinTypeError> {
) -> Result<(), InvalidPinTypeError> {
match self.mode {
DynPinMode::Input(_) => {
self.regs.filter_type(filter, clksel);
Ok(self)
Ok(())
}
_ => Err(InvalidPinTypeError),
_ => Err(InvalidPinTypeError(self.mode)),
}
}
#[inline]
pub fn interrupt_edge(
mut self,
&mut self,
edge_type: InterruptEdge,
irq_cfg: IrqCfg,
syscfg: Option<&mut pac::Sysconfig>,
irqsel: Option<&mut pac::Irqsel>,
) -> Result<Self, InvalidPinTypeError> {
) -> Result<(), InvalidPinTypeError> {
match self.mode {
DynPinMode::Input(_) | DynPinMode::Output(_) => {
self.regs.interrupt_edge(edge_type);
self.irq_enb(irq_cfg, syscfg, irqsel);
Ok(self)
Ok(())
}
_ => Err(InvalidPinTypeError),
_ => Err(InvalidPinTypeError(self.mode)),
}
}
#[inline]
pub fn interrupt_level(
mut self,
&mut self,
level_type: InterruptLevel,
irq_cfg: IrqCfg,
syscfg: Option<&mut pac::Sysconfig>,
irqsel: Option<&mut pac::Irqsel>,
) -> Result<Self, InvalidPinTypeError> {
) -> Result<(), InvalidPinTypeError> {
match self.mode {
DynPinMode::Input(_) | DynPinMode::Output(_) => {
self.regs.interrupt_level(level_type);
self.irq_enb(irq_cfg, syscfg, irqsel);
Ok(self)
Ok(())
}
_ => Err(InvalidPinTypeError),
_ => Err(InvalidPinTypeError(self.mode)),
}
}
@ -398,7 +471,7 @@ impl DynPin {
self.regs.toggle();
Ok(())
}
_ => Err(InvalidPinTypeError),
_ => Err(InvalidPinTypeError(self.mode)),
}
}
@ -408,7 +481,7 @@ impl DynPin {
DynPinMode::Input(_) | DYN_RD_OPEN_DRAIN_OUTPUT | DYN_RD_PUSH_PULL_OUTPUT => {
Ok(self.regs.read_pin())
}
_ => Err(InvalidPinTypeError),
_ => Err(InvalidPinTypeError(self.mode)),
}
}
#[inline]
@ -418,7 +491,7 @@ impl DynPin {
self.regs.write_pin(bit);
Ok(())
}
_ => Err(InvalidPinTypeError),
_ => Err(InvalidPinTypeError(self.mode)),
}
}
@ -438,6 +511,30 @@ impl DynPin {
fn _set_high(&mut self) -> Result<(), InvalidPinTypeError> {
self._write(true)
}
/// Try to recreate a type-level [`Pin`] from a value-level [`DynPin`]
///
/// There is no way for the compiler to know if the conversion will be
/// successful at compile-time. We must verify the conversion at run-time
/// or refuse to perform it.
#[inline]
pub fn upgrade<I: PinId, M: PinMode>(self) -> Result<Pin<I, M>, InvalidPinTypeError> {
if self.regs.0 == I::DYN && self.mode == M::DYN {
// The `DynPin` is consumed, so it is safe to replace it with the
// corresponding `Pin`
return Ok(unsafe { Pin::new() });
}
Err(InvalidPinTypeError(self.mode))
}
/// Convert the pin into an async pin. The pin can be converted back by calling
/// [InputDynPinAsync::release]
pub fn into_async_input(
self,
irq: crate::pac::Interrupt,
) -> Result<InputDynPinAsync, InvalidPinTypeError> {
InputDynPinAsync::new(self, irq)
}
}
//==================================================================================================
@ -448,10 +545,8 @@ impl<I: PinId, M: PinMode> From<Pin<I, M>> for DynPin {
/// Erase the type-level information in a [`Pin`] and return a value-level
/// [`DynPin`]
#[inline]
fn from(_pin: Pin<I, M>) -> Self {
// The `Pin` is consumed, so it is safe to replace it with the
// corresponding `DynPin`
unsafe { DynPin::new(I::DYN, M::DYN) }
fn from(pin: Pin<I, M>) -> Self {
pin.downgrade()
}
}
@ -465,13 +560,7 @@ impl<I: PinId, M: PinMode> TryFrom<DynPin> for Pin<I, M> {
/// or refuse to perform it.
#[inline]
fn try_from(pin: DynPin) -> Result<Self, Self::Error> {
if pin.regs.id == I::DYN && pin.mode == M::DYN {
// The `DynPin` is consumed, so it is safe to replace it with the
// corresponding `Pin`
Ok(unsafe { Self::new() })
} else {
Err(InvalidPinTypeError)
}
pin.upgrade()
}
}
@ -506,10 +595,12 @@ impl embedded_hal::digital::InputPin for DynPin {
}
impl embedded_hal::digital::StatefulOutputPin for DynPin {
#[inline]
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
self._is_high()
}
#[inline]
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
self._is_low()
}

View File

@ -22,84 +22,14 @@
//!
//! - [Blinky example](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/examples/simple/examples/blinky.rs)
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[error("The pin is masked")]
pub struct IsMaskedError;
macro_rules! common_reg_if_functions {
() => {
paste::paste!(
#[inline]
pub fn datamask(&self) -> bool {
self.regs.datamask()
}
#[inline]
pub fn clear_datamask(self) -> Self {
self.regs.clear_datamask();
self
}
#[inline]
pub fn set_datamask(self) -> Self {
self.regs.set_datamask();
self
}
#[inline]
pub fn is_high_masked(&self) -> Result<bool, crate::gpio::IsMaskedError> {
self.regs.read_pin_masked()
}
#[inline]
pub fn is_low_masked(&self) -> Result<bool, crate::gpio::IsMaskedError> {
self.regs.read_pin_masked().map(|v| !v)
}
#[inline]
pub fn set_high_masked(&mut self) -> Result<(), crate::gpio::IsMaskedError> {
self.regs.write_pin_masked(true)
}
#[inline]
pub fn set_low_masked(&mut self) -> Result<(), crate::gpio::IsMaskedError> {
self.regs.write_pin_masked(false)
}
fn irq_enb(
&mut self,
irq_cfg: crate::IrqCfg,
syscfg: Option<&mut va108xx::Sysconfig>,
irqsel: Option<&mut va108xx::Irqsel>,
) {
if syscfg.is_some() {
crate::clock::enable_peripheral_clock(
syscfg.unwrap(),
crate::clock::PeripheralClocks::Irqsel,
);
}
self.regs.enable_irq();
if let Some(irqsel) = irqsel {
if irq_cfg.route {
match self.regs.id().group {
// Set the correct interrupt number in the IRQSEL register
DynGroup::A => {
irqsel
.porta0(self.regs.id().num as usize)
.write(|w| unsafe { w.bits(irq_cfg.irq as u32) });
}
DynGroup::B => {
irqsel
.portb0(self.regs.id().num as usize)
.write(|w| unsafe { w.bits(irq_cfg.irq as u32) });
}
}
}
}
}
);
};
}
pub const NUM_PINS_PORT_A: usize = 32;
pub const NUM_PINS_PORT_B: usize = 24;
pub const NUM_GPIO_PINS: usize = NUM_PINS_PORT_A + NUM_PINS_PORT_B;
pub mod dynpin;
pub use dynpin::*;
@ -107,4 +37,7 @@ pub use dynpin::*;
pub mod pin;
pub use pin::*;
pub mod asynch;
pub use asynch::*;
mod reg;

View File

@ -72,6 +72,7 @@
//! and [`StatefulOutputPin`].
use super::dynpin::{DynAlternate, DynGroup, DynInput, DynOutput, DynPinId, DynPinMode};
use super::reg::RegisterInterface;
use super::{DynPin, InputPinAsync};
use crate::{
pac::{Irqsel, Porta, Portb, Sysconfig},
typelevel::Sealed,
@ -320,10 +321,9 @@ macro_rules! pin_id {
//==================================================================================================
/// A type-level GPIO pin, parameterized by [PinId] and [PinMode] types
pub struct Pin<I: PinId, M: PinMode> {
pub(in crate::gpio) regs: Registers<I>,
mode: PhantomData<M>,
inner: DynPin,
phantom: PhantomData<(I, M)>,
}
impl<I: PinId, M: PinMode> Pin<I, M> {
@ -337,18 +337,22 @@ impl<I: PinId, M: PinMode> Pin<I, M> {
#[inline]
pub(crate) unsafe fn new() -> Pin<I, M> {
Pin {
regs: Registers::new(),
mode: PhantomData,
inner: DynPin::new(I::DYN, M::DYN),
phantom: PhantomData,
}
}
pub fn id(&self) -> DynPinId {
self.inner.id()
}
/// Convert the pin to the requested [`PinMode`]
#[inline]
pub fn into_mode<N: PinMode>(mut self) -> Pin<I, N> {
// Only modify registers if we are actually changing pin mode
// This check should compile away
if N::DYN != M::DYN {
self.regs.change_mode::<N>();
self.inner.regs.change_mode(N::DYN);
}
// Safe because we drop the existing Pin
unsafe { Pin::new() }
@ -408,31 +412,78 @@ impl<I: PinId, M: PinMode> Pin<I, M> {
self.into_mode()
}
common_reg_if_functions!();
#[inline]
pub fn datamask(&self) -> bool {
self.inner.datamask()
}
#[inline]
pub fn clear_datamask(&mut self) {
self.inner.clear_datamask()
}
#[inline]
pub fn set_datamask(&mut self) {
self.inner.set_datamask()
}
#[inline]
pub fn is_high_masked(&self) -> Result<bool, crate::gpio::IsMaskedError> {
self.inner.is_high_masked()
}
#[inline]
pub fn is_low_masked(&self) -> Result<bool, crate::gpio::IsMaskedError> {
self.inner.is_low_masked()
}
#[inline]
pub fn set_high_masked(&mut self) -> Result<(), crate::gpio::IsMaskedError> {
self.inner.set_high_masked()
}
#[inline]
pub fn set_low_masked(&mut self) -> Result<(), crate::gpio::IsMaskedError> {
self.inner.set_low_masked()
}
#[inline]
pub fn downgrade(self) -> DynPin {
self.inner
}
fn irq_enb(
&mut self,
irq_cfg: crate::IrqCfg,
syscfg: Option<&mut va108xx::Sysconfig>,
irqsel: Option<&mut va108xx::Irqsel>,
) {
self.inner.irq_enb(irq_cfg, syscfg, irqsel);
}
#[inline]
pub(crate) fn _set_high(&mut self) {
self.regs.write_pin(true)
self.inner.regs.write_pin(true)
}
#[inline]
pub(crate) fn _set_low(&mut self) {
self.regs.write_pin(false)
self.inner.regs.write_pin(false)
}
#[inline]
pub(crate) fn _toggle_with_toggle_reg(&mut self) {
self.regs.toggle();
self.inner.regs.toggle();
}
#[inline]
pub(crate) fn _is_low(&self) -> bool {
!self.regs.read_pin()
!self.inner.regs.read_pin()
}
#[inline]
pub(crate) fn _is_high(&self) -> bool {
self.regs.read_pin()
self.inner.regs.read_pin()
}
}
@ -524,28 +575,32 @@ impl<P: AnyPin> AsMut<P> for SpecificPin<P> {
//==================================================================================================
impl<I: PinId, C: InputConfig> Pin<I, Input<C>> {
/// Convert the pin into an async pin. The pin can be converted back by calling
/// [InputPinAsync::release]
pub fn into_async_input(self, irq: crate::pac::Interrupt) -> InputPinAsync<I, C> {
InputPinAsync::new(self, irq)
}
pub fn interrupt_edge(
mut self,
&mut self,
edge_type: InterruptEdge,
irq_cfg: IrqCfg,
syscfg: Option<&mut Sysconfig>,
irqsel: Option<&mut Irqsel>,
) -> Self {
self.regs.interrupt_edge(edge_type);
) {
self.inner.regs.interrupt_edge(edge_type);
self.irq_enb(irq_cfg, syscfg, irqsel);
self
}
pub fn interrupt_level(
mut self,
&mut self,
level_type: InterruptLevel,
irq_cfg: IrqCfg,
syscfg: Option<&mut Sysconfig>,
irqsel: Option<&mut Irqsel>,
) -> Self {
self.regs.interrupt_level(level_type);
) {
self.inner.regs.interrupt_level(level_type);
self.irq_enb(irq_cfg, syscfg, irqsel);
self
}
}
@ -557,7 +612,7 @@ impl<I: PinId, C: OutputConfig> Pin<I, Output<C>> {
/// - Delay 1 + Delay 2: 3
#[inline]
pub fn delay(self, delay_1: bool, delay_2: bool) -> Self {
self.regs.delay(delay_1, delay_2);
self.inner.regs.delay(delay_1, delay_2);
self
}
@ -569,42 +624,38 @@ impl<I: PinId, C: OutputConfig> Pin<I, Output<C>> {
/// See p.52 of the programmers guide for more information.
/// When configured for pulse mode, a given pin will set the non-default state for exactly
/// one clock cycle before returning to the configured default state
pub fn pulse_mode(self, enable: bool, default_state: PinState) -> Self {
self.regs.pulse_mode(enable, default_state);
self
pub fn pulse_mode(&mut self, enable: bool, default_state: PinState) {
self.inner.regs.pulse_mode(enable, default_state);
}
pub fn interrupt_edge(
mut self,
&mut self,
edge_type: InterruptEdge,
irq_cfg: IrqCfg,
syscfg: Option<&mut Sysconfig>,
irqsel: Option<&mut Irqsel>,
) -> Self {
self.regs.interrupt_edge(edge_type);
) {
self.inner.regs.interrupt_edge(edge_type);
self.irq_enb(irq_cfg, syscfg, irqsel);
self
}
pub fn interrupt_level(
mut self,
&mut self,
level_type: InterruptLevel,
irq_cfg: IrqCfg,
syscfg: Option<&mut Sysconfig>,
irqsel: Option<&mut Irqsel>,
) -> Self {
self.regs.interrupt_level(level_type);
) {
self.inner.regs.interrupt_level(level_type);
self.irq_enb(irq_cfg, syscfg, irqsel);
self
}
}
impl<I: PinId, C: InputConfig> Pin<I, Input<C>> {
/// See p.37 and p.38 of the programmers guide for more information.
#[inline]
pub fn filter_type(self, filter: FilterType, clksel: FilterClkSel) -> Self {
self.regs.filter_type(filter, clksel);
self
pub fn filter_type(&mut self, filter: FilterType, clksel: FilterClkSel) {
self.inner.regs.filter_type(filter, clksel);
}
}
@ -680,47 +731,6 @@ where
}
}
//==================================================================================================
// Registers
//==================================================================================================
/// Provide a safe register interface for [`Pin`]s
///
/// This `struct` takes ownership of a [`PinId`] and provides an API to
/// access the corresponding registers.
pub(in crate::gpio) struct Registers<I: PinId> {
id: PhantomData<I>,
}
// [`Registers`] takes ownership of the [`PinId`], and [`Pin`] guarantees that
// each pin is a singleton, so this implementation is safe.
unsafe impl<I: PinId> RegisterInterface for Registers<I> {
#[inline]
fn id(&self) -> DynPinId {
I::DYN
}
}
impl<I: PinId> Registers<I> {
/// Create a new instance of [`Registers`]
///
/// # Safety
///
/// Users must never create two simultaneous instances of this `struct` with
/// the same [`PinId`]
#[inline]
unsafe fn new() -> Self {
Registers { id: PhantomData }
}
/// Provide a type-level equivalent for the
/// [`RegisterInterface::change_mode`] method.
#[inline]
pub(in crate::gpio) fn change_mode<M: PinMode>(&mut self) {
RegisterInterface::change_mode(self, M::DYN);
}
}
//==================================================================================================
// Pin definitions
//==================================================================================================
@ -732,7 +742,6 @@ macro_rules! pins {
paste!(
/// Collection of all the individual [`Pin`]s for a given port (PORTA or PORTB)
pub struct $PinsName {
iocfg: Option<va108xx::Ioconfig>,
port: $Port,
$(
#[doc = "Pin " $Id]
@ -747,7 +756,6 @@ macro_rules! pins {
#[inline]
pub fn new(
syscfg: &mut va108xx::Sysconfig,
iocfg: Option<va108xx::Ioconfig>,
port: $Port
) -> $PinsName {
syscfg.peripheral_clk_enable().modify(|_, w| {
@ -756,7 +764,7 @@ macro_rules! pins {
w.ioconfig().set_bit()
});
$PinsName {
iocfg,
//iocfg,
port,
// Safe because we only create one `Pin` per `PinId`
$(
@ -773,8 +781,8 @@ macro_rules! pins {
}
/// Consumes the Pins struct and returns the port definitions
pub fn release(self) -> (Option<va108xx::Ioconfig>, $Port) {
(self.iocfg, self.port)
pub fn release(self) -> $Port {
self.port
}
}
);

View File

@ -73,13 +73,6 @@ impl From<DynPinMode> for ModeFields {
//==================================================================================================
pub type PortReg = ioconfig::Porta;
/*
pub type IocfgPort = ioconfig::Porta;
#[repr(C)]
pub(super) struct IocfgPortGroup {
port: [IocfgPort; 32],
}
*/
/// Provide a safe register interface for pin objects
///
@ -293,7 +286,7 @@ pub(super) unsafe trait RegisterInterface {
/// Only useful for input pins
#[inline]
fn filter_type(&self, filter: FilterType, clksel: FilterClkSel) {
fn filter_type(&mut self, filter: FilterType, clksel: FilterClkSel) {
self.iocfg_port().modify(|_, w| {
// Safety: Only write to register for this Pin ID
unsafe {
@ -331,7 +324,7 @@ pub(super) unsafe trait RegisterInterface {
/// See p.52 of the programmers guide for more information.
/// When configured for pulse mode, a given pin will set the non-default state for exactly
/// one clock cycle before returning to the configured default state
fn pulse_mode(&self, enable: bool, default_state: PinState) {
fn pulse_mode(&mut self, enable: bool, default_state: PinState) {
let portreg = self.port_reg();
unsafe {
if enable {

View File

@ -23,37 +23,44 @@ pub enum FifoEmptyMode {
EndTransaction = 1,
}
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct ClockTooSlowForFastI2c;
#[error("clock too slow for fast I2C mode")]
pub struct ClockTooSlowForFastI2cError;
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
#[error("invalid timing parameters")]
pub struct InvalidTimingParamsError;
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error {
InvalidTimingParams,
//#[error("Invalid timing parameters")]
//InvalidTimingParams,
#[error("arbitration lost")]
ArbitrationLost,
#[error("nack address")]
NackAddr,
/// Data not acknowledged in write operation
#[error("data not acknowledged in write operation")]
NackData,
/// Not enough data received in read operation
#[error("insufficient data received")]
InsufficientDataReceived,
/// Number of bytes in transfer too large (larger than 0x7fe)
#[error("data too large (larger than 0x7fe)")]
DataTooLarge,
}
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum InitError {
/// Wrong address used in constructor
#[error("wrong address mode")]
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)
}
#[error("clock too slow for fast I2C mode: {0}")]
ClkTooSlow(#[from] ClockTooSlowForFastI2cError),
}
impl embedded_hal::i2c::Error for Error {
@ -66,7 +73,7 @@ impl embedded_hal::i2c::Error for Error {
Error::NackData => {
embedded_hal::i2c::ErrorKind::NoAcknowledge(i2c::NoAcknowledgeSource::Data)
}
Error::DataTooLarge | Error::InsufficientDataReceived | Error::InvalidTimingParams => {
Error::DataTooLarge | Error::InsufficientDataReceived => {
embedded_hal::i2c::ErrorKind::Other
}
}
@ -160,7 +167,7 @@ impl TimingCfg {
pub fn new(
first_16_bits: TrTfThighTlow,
second_16_bits: TsuStoTsuStaThdStaTBuf,
) -> Result<Self, Error> {
) -> Result<Self, InvalidTimingParamsError> {
if first_16_bits.0 > 0xf
|| first_16_bits.1 > 0xf
|| first_16_bits.2 > 0xf
@ -170,7 +177,7 @@ impl TimingCfg {
|| second_16_bits.2 > 0xf
|| second_16_bits.3 > 0xf
{
return Err(Error::InvalidTimingParams);
return Err(InvalidTimingParamsError);
}
Ok(TimingCfg {
tr: first_16_bits.0,
@ -299,7 +306,7 @@ impl<I2c: Instance> I2cBase<I2c> {
speed_mode: I2cSpeed,
ms_cfg: Option<&MasterConfig>,
sl_cfg: Option<&SlaveConfig>,
) -> Result<Self, ClockTooSlowForFastI2c> {
) -> Result<Self, ClockTooSlowForFastI2cError> {
enable_peripheral_clock(syscfg, I2c::PERIPH_SEL);
let mut i2c_base = I2cBase {
@ -402,19 +409,22 @@ impl<I2c: Instance> I2cBase<I2c> {
});
}
fn calc_clk_div(&self, speed_mode: I2cSpeed) -> Result<u8, ClockTooSlowForFastI2c> {
fn calc_clk_div(&self, speed_mode: I2cSpeed) -> Result<u8, ClockTooSlowForFastI2cError> {
if speed_mode == I2cSpeed::Regular100khz {
Ok(((self.sys_clk.raw() / CLK_100K.raw() / 20) - 1) as u8)
} else {
if self.sys_clk.raw() < MIN_CLK_400K.raw() {
return Err(ClockTooSlowForFastI2c);
return Err(ClockTooSlowForFastI2cError);
}
Ok(((self.sys_clk.raw() / CLK_400K.raw() / 25) - 1) as u8)
}
}
/// Configures the clock scale for a given speed mode setting
pub fn cfg_clk_scale(&mut self, speed_mode: I2cSpeed) -> Result<(), ClockTooSlowForFastI2c> {
pub fn cfg_clk_scale(
&mut self,
speed_mode: I2cSpeed,
) -> Result<(), ClockTooSlowForFastI2cError> {
let clk_div = self.calc_clk_div(speed_mode)?;
self.i2c
.clkscale()
@ -460,7 +470,7 @@ impl<I2c: Instance, Addr> I2cMaster<I2c, Addr> {
i2c: I2c,
cfg: MasterConfig,
speed_mode: I2cSpeed,
) -> Result<Self, ClockTooSlowForFastI2c> {
) -> Result<Self, ClockTooSlowForFastI2cError> {
Ok(I2cMaster {
i2c_base: I2cBase::new(syscfg, sysclk, i2c, speed_mode, Some(&cfg), None)?,
addr: PhantomData,
@ -990,7 +1000,7 @@ impl<I2c: Instance, Addr> I2cSlave<I2c, Addr> {
i2c: I2c,
cfg: SlaveConfig,
speed_mode: I2cSpeed,
) -> Result<Self, ClockTooSlowForFastI2c> {
) -> Result<Self, ClockTooSlowForFastI2cError> {
Ok(I2cSlave {
i2c_base: I2cBase::new(sys_cfg, sys_clk, i2c, speed_mode, None, Some(&cfg))?,
addr: PhantomData,
@ -1152,7 +1162,7 @@ impl<I2c: Instance> I2cSlave<I2c, TenBitAddress> {
i2c: I2c,
cfg: SlaveConfig,
speed_mode: I2cSpeed,
) -> Result<Self, ClockTooSlowForFastI2c> {
) -> Result<Self, ClockTooSlowForFastI2cError> {
Self::new_generic(sys_cfg, sys_clk, i2c, cfg, speed_mode)
}
}

View File

@ -9,15 +9,13 @@ use core::convert::Infallible;
use core::marker::PhantomData;
use crate::pac;
use crate::timer::{
TimAndPinRegister, TimDynRegister, TimPin, TimRegInterface, ValidTim, ValidTimAndPin,
};
use crate::time::Hertz;
use crate::timer::{TimDynRegister, TimPin, TimRegInterface, ValidTim, ValidTimAndPin};
use crate::{clock::enable_peripheral_clock, gpio::DynPinId};
pub use crate::{gpio::PinId, time::Hertz};
const DUTY_MAX: u16 = u16::MAX;
pub struct PwmBase {
pub struct PwmCommon {
sys_clk: Hertz,
/// For PWMB, this is the upper limit
current_duty: u16,
@ -35,123 +33,13 @@ enum StatusSelPwm {
pub struct PwmA {}
pub struct PwmB {}
//==================================================================================================
// Common
//==================================================================================================
macro_rules! pwm_common_func {
() => {
#[inline]
fn enable_pwm_a(&mut self) {
self.reg
.reg()
.ctrl()
.modify(|_, w| unsafe { w.status_sel().bits(StatusSelPwm::PwmA as u8) });
}
#[inline]
fn enable_pwm_b(&mut self) {
self.reg
.reg()
.ctrl()
.modify(|_, w| unsafe { w.status_sel().bits(StatusSelPwm::PwmB as u8) });
}
#[inline]
pub fn get_period(&self) -> Hertz {
self.pwm_base.current_period
}
#[inline]
pub fn set_period(&mut self, period: impl Into<Hertz>) {
self.pwm_base.current_period = period.into();
// Avoid division by 0
if self.pwm_base.current_period.raw() == 0 {
return;
}
self.pwm_base.current_rst_val =
self.pwm_base.sys_clk.raw() / self.pwm_base.current_period.raw();
self.reg
.reg()
.rst_value()
.write(|w| unsafe { w.bits(self.pwm_base.current_rst_val) });
}
#[inline]
pub fn disable(&mut self) {
self.reg.reg().ctrl().modify(|_, w| w.enable().clear_bit());
}
#[inline]
pub fn enable(&mut self) {
self.reg.reg().ctrl().modify(|_, w| w.enable().set_bit());
}
#[inline]
pub fn period(&self) -> Hertz {
self.pwm_base.current_period
}
#[inline(always)]
pub fn duty(&self) -> u16 {
self.pwm_base.current_duty
}
};
}
macro_rules! pwmb_func {
() => {
pub fn pwmb_lower_limit(&self) -> u16 {
self.pwm_base.current_lower_limit
}
pub fn pwmb_upper_limit(&self) -> u16 {
self.pwm_base.current_duty
}
/// Set the lower limit for PWMB
///
/// The PWM signal will be 1 as long as the current RST counter is larger than
/// the lower limit. For example, with a lower limit of 0.5 and and an upper limit
/// of 0.7, Only a fixed period between 0.5 * period and 0.7 * period will be in a high
/// state
pub fn set_pwmb_lower_limit(&mut self, duty: u16) {
self.pwm_base.current_lower_limit = duty;
let pwmb_val: u64 = (self.pwm_base.current_rst_val as u64
* self.pwm_base.current_lower_limit as u64)
/ DUTY_MAX as u64;
self.reg
.reg()
.pwmb_value()
.write(|w| unsafe { w.bits(pwmb_val as u32) });
}
/// Set the higher limit for PWMB
///
/// The PWM signal will be 1 as long as the current RST counter is smaller than
/// the higher limit. For example, with a lower limit of 0.5 and and an upper limit
/// of 0.7, Only a fixed period between 0.5 * period and 0.7 * period will be in a high
/// state
pub fn set_pwmb_upper_limit(&mut self, duty: u16) {
self.pwm_base.current_duty = duty;
let pwma_val: u64 = (self.pwm_base.current_rst_val as u64
* self.pwm_base.current_duty as u64)
/ DUTY_MAX as u64;
self.reg
.reg()
.pwma_value()
.write(|w| unsafe { w.bits(pwma_val as u32) });
}
};
}
//==================================================================================================
// Strongly typed PWM pin
//==================================================================================================
pub struct PwmPin<Pin: TimPin, Tim: ValidTim, Mode = PwmA> {
reg: TimAndPinRegister<Pin, Tim>,
pwm_base: PwmBase,
pin_and_tim: (Pin, Tim),
inner: ReducedPwmPin<Mode>,
mode: PhantomData<Mode>,
}
@ -163,34 +51,82 @@ where
pub fn new(
sys_cfg: &mut pac::Sysconfig,
sys_clk: impl Into<Hertz> + Copy,
tim_and_pin: (Pin, Tim),
pin_and_tim: (Pin, Tim),
initial_period: impl Into<Hertz> + Copy,
) -> Self {
let mut pin = PwmPin {
pwm_base: PwmBase {
current_duty: 0,
current_lower_limit: 0,
current_period: initial_period.into(),
current_rst_val: 0,
sys_clk: sys_clk.into(),
},
reg: unsafe { TimAndPinRegister::new(tim_and_pin.0, tim_and_pin.1) },
pin_and_tim,
inner: ReducedPwmPin::<Mode>::new(
Tim::TIM_ID,
Pin::DYN,
PwmCommon {
current_duty: 0,
current_lower_limit: 0,
current_period: initial_period.into(),
current_rst_val: 0,
sys_clk: sys_clk.into(),
},
),
//unsafe { TimAndPin::new(tim_and_pin.0, tim_and_pin.1) },
mode: PhantomData,
};
enable_peripheral_clock(sys_cfg, crate::clock::PeripheralClocks::Gpio);
enable_peripheral_clock(sys_cfg, crate::clock::PeripheralClocks::Ioconfig);
sys_cfg
.tim_clk_enable()
.modify(|r, w| unsafe { w.bits(r.bits() | pin.reg.mask_32()) });
.modify(|r, w| unsafe { w.bits(r.bits() | pin.pin_and_tim.1.mask_32()) });
pin.enable_pwm_a();
pin.set_period(initial_period);
pin
}
pub fn release(self) -> (Pin, Tim) {
self.reg.release()
pub fn reduce(self) -> ReducedPwmPin<Mode> {
self.inner
}
pwm_common_func!();
pub fn release(self) -> (Pin, Tim) {
self.pin_and_tim
}
#[inline]
fn enable_pwm_a(&mut self) {
self.inner.enable_pwm_a();
}
#[inline]
fn enable_pwm_b(&mut self) {
self.inner.enable_pwm_b();
}
#[inline]
pub fn get_period(&self) -> Hertz {
self.inner.get_period()
}
#[inline]
pub fn set_period(&mut self, period: impl Into<Hertz>) {
self.inner.set_period(period);
}
#[inline]
pub fn disable(&mut self) {
self.inner.disable();
}
#[inline]
pub fn enable(&mut self) {
self.inner.enable();
}
#[inline]
pub fn period(&self) -> Hertz {
self.inner.period()
}
#[inline(always)]
pub fn duty(&self) -> u16 {
self.inner.duty()
}
}
impl<Pin: TimPin, Tim: ValidTim> From<PwmPin<Pin, Tim, PwmA>> for PwmPin<Pin, Tim, PwmB>
@ -199,9 +135,9 @@ where
{
fn from(other: PwmPin<Pin, Tim, PwmA>) -> Self {
let mut pwmb = Self {
reg: other.reg,
pwm_base: other.pwm_base,
mode: PhantomData,
pin_and_tim: other.pin_and_tim,
inner: other.inner.into(),
};
pwmb.enable_pwm_b();
pwmb
@ -213,13 +149,13 @@ where
(PIN, TIM): ValidTimAndPin<PIN, TIM>,
{
fn from(other: PwmPin<PIN, TIM, PwmB>) -> Self {
let mut pwmb = Self {
reg: other.reg,
pwm_base: other.pwm_base,
let mut pwma = Self {
mode: PhantomData,
pin_and_tim: other.pin_and_tim,
inner: other.inner.into(),
};
pwmb.enable_pwm_a();
pwmb
pwma.enable_pwm_a();
pwma
}
}
@ -263,33 +199,89 @@ where
/// Reduced version where type information is deleted
pub struct ReducedPwmPin<Mode = PwmA> {
reg: TimDynRegister,
pwm_base: PwmBase,
pin_id: DynPinId,
dyn_reg: TimDynRegister,
common: PwmCommon,
mode: PhantomData<Mode>,
}
impl<PIN: TimPin, TIM: ValidTim> From<PwmPin<PIN, TIM>> for ReducedPwmPin<PwmA> {
fn from(pwm_pin: PwmPin<PIN, TIM>) -> Self {
ReducedPwmPin {
reg: TimDynRegister::from(pwm_pin.reg),
pwm_base: pwm_pin.pwm_base,
pin_id: PIN::DYN,
impl<Mode> ReducedPwmPin<Mode> {
pub(crate) fn new(tim_id: u8, pin_id: DynPinId, common: PwmCommon) -> Self {
Self {
dyn_reg: TimDynRegister { tim_id, pin_id },
common,
mode: PhantomData,
}
}
}
impl<MODE> ReducedPwmPin<MODE> {
pwm_common_func!();
impl<Mode> ReducedPwmPin<Mode> {
#[inline]
fn enable_pwm_a(&mut self) {
self.dyn_reg
.reg_block()
.ctrl()
.modify(|_, w| unsafe { w.status_sel().bits(StatusSelPwm::PwmA as u8) });
}
#[inline]
fn enable_pwm_b(&mut self) {
self.dyn_reg
.reg_block()
.ctrl()
.modify(|_, w| unsafe { w.status_sel().bits(StatusSelPwm::PwmB as u8) });
}
#[inline]
pub fn get_period(&self) -> Hertz {
self.common.current_period
}
#[inline]
pub fn set_period(&mut self, period: impl Into<Hertz>) {
self.common.current_period = period.into();
// Avoid division by 0
if self.common.current_period.raw() == 0 {
return;
}
self.common.current_rst_val = self.common.sys_clk.raw() / self.common.current_period.raw();
self.dyn_reg
.reg_block()
.rst_value()
.write(|w| unsafe { w.bits(self.common.current_rst_val) });
}
#[inline]
pub fn disable(&mut self) {
self.dyn_reg
.reg_block()
.ctrl()
.modify(|_, w| w.enable().clear_bit());
}
#[inline]
pub fn enable(&mut self) {
self.dyn_reg
.reg_block()
.ctrl()
.modify(|_, w| w.enable().set_bit());
}
#[inline]
pub fn period(&self) -> Hertz {
self.common.current_period
}
#[inline(always)]
pub fn duty(&self) -> u16 {
self.common.current_duty
}
}
impl From<ReducedPwmPin<PwmA>> for ReducedPwmPin<PwmB> {
fn from(other: ReducedPwmPin<PwmA>) -> Self {
let mut pwmb = Self {
reg: other.reg,
pwm_base: other.pwm_base,
pin_id: other.pin_id,
dyn_reg: other.dyn_reg,
common: other.common,
mode: PhantomData,
};
pwmb.enable_pwm_b();
@ -300,9 +292,8 @@ impl From<ReducedPwmPin<PwmA>> for ReducedPwmPin<PwmB> {
impl From<ReducedPwmPin<PwmB>> for ReducedPwmPin<PwmA> {
fn from(other: ReducedPwmPin<PwmB>) -> Self {
let mut pwmb = Self {
reg: other.reg,
pwm_base: other.pwm_base,
pin_id: other.pin_id,
dyn_reg: other.dyn_reg,
common: other.common,
mode: PhantomData,
};
pwmb.enable_pwm_a();
@ -314,15 +305,83 @@ impl From<ReducedPwmPin<PwmB>> for ReducedPwmPin<PwmA> {
// PWMB implementations
//==================================================================================================
impl<PIN: TimPin, TIM: ValidTim> PwmPin<PIN, TIM, PwmB>
impl<Pin: TimPin, Tim: ValidTim> PwmPin<Pin, Tim, PwmB>
where
(PIN, TIM): ValidTimAndPin<PIN, TIM>,
(Pin, Tim): ValidTimAndPin<Pin, Tim>,
{
pwmb_func!();
pub fn pwmb_lower_limit(&self) -> u16 {
self.inner.pwmb_lower_limit()
}
pub fn pwmb_upper_limit(&self) -> u16 {
self.inner.pwmb_upper_limit()
}
/// Set the lower limit for PWMB
///
/// The PWM signal will be 1 as long as the current RST counter is larger than
/// the lower limit. For example, with a lower limit of 0.5 and and an upper limit
/// of 0.7, Only a fixed period between 0.5 * period and 0.7 * period will be in a high
/// state
pub fn set_pwmb_lower_limit(&mut self, duty: u16) {
self.inner.set_pwmb_lower_limit(duty);
}
/// Set the higher limit for PWMB
///
/// The PWM signal will be 1 as long as the current RST counter is smaller than
/// the higher limit. For example, with a lower limit of 0.5 and and an upper limit
/// of 0.7, Only a fixed period between 0.5 * period and 0.7 * period will be in a high
/// state
pub fn set_pwmb_upper_limit(&mut self, duty: u16) {
self.inner.set_pwmb_upper_limit(duty);
}
}
impl ReducedPwmPin<PwmB> {
pwmb_func!();
#[inline(always)]
pub fn pwmb_lower_limit(&self) -> u16 {
self.common.current_lower_limit
}
#[inline(always)]
pub fn pwmb_upper_limit(&self) -> u16 {
self.common.current_duty
}
/// Set the lower limit for PWMB
///
/// The PWM signal will be 1 as long as the current RST counter is larger than
/// the lower limit. For example, with a lower limit of 0.5 and and an upper limit
/// of 0.7, Only a fixed period between 0.5 * period and 0.7 * period will be in a high
/// state
#[inline(always)]
pub fn set_pwmb_lower_limit(&mut self, duty: u16) {
self.common.current_lower_limit = duty;
let pwmb_val: u64 = (self.common.current_rst_val as u64
* self.common.current_lower_limit as u64)
/ DUTY_MAX as u64;
self.dyn_reg
.reg_block()
.pwmb_value()
.write(|w| unsafe { w.bits(pwmb_val as u32) });
}
/// Set the higher limit for PWMB
///
/// The PWM signal will be 1 as long as the current RST counter is smaller than
/// the higher limit. For example, with a lower limit of 0.5 and and an upper limit
/// of 0.7, Only a fixed period between 0.5 * period and 0.7 * period will be in a high
/// state
pub fn set_pwmb_upper_limit(&mut self, duty: u16) {
self.common.current_duty = duty;
let pwma_val: u64 = (self.common.current_rst_val as u64 * self.common.current_duty as u64)
/ DUTY_MAX as u64;
self.dyn_reg
.reg_block()
.pwma_value()
.write(|w| unsafe { w.bits(pwma_val as u32) });
}
}
//==================================================================================================
@ -345,12 +404,12 @@ impl embedded_hal::pwm::SetDutyCycle for ReducedPwmPin {
#[inline]
fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> {
self.pwm_base.current_duty = duty;
let pwma_val: u64 = (self.pwm_base.current_rst_val as u64
* (DUTY_MAX as u64 - self.pwm_base.current_duty as u64))
self.common.current_duty = duty;
let pwma_val: u64 = (self.common.current_rst_val as u64
* (DUTY_MAX as u64 - self.common.current_duty as u64))
/ DUTY_MAX as u64;
self.reg
.reg()
self.dyn_reg
.reg_block()
.pwma_value()
.write(|w| unsafe { w.bits(pwma_val as u32) });
Ok(())
@ -365,15 +424,7 @@ impl<Pin: TimPin, Tim: ValidTim> embedded_hal::pwm::SetDutyCycle for PwmPin<Pin,
#[inline]
fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> {
self.pwm_base.current_duty = duty;
let pwma_val: u64 = (self.pwm_base.current_rst_val as u64
* (DUTY_MAX as u64 - self.pwm_base.current_duty as u64))
/ DUTY_MAX as u64;
self.reg
.reg()
.pwma_value()
.write(|w| unsafe { w.bits(pwma_val as u32) });
Ok(())
self.inner.set_duty_cycle(duty)
}
}

View File

@ -571,10 +571,13 @@ impl SpiClkConfig {
}
}
#[derive(Debug)]
#[derive(Debug, thiserror::Error)]
pub enum SpiClkConfigError {
#[error("division by zero")]
DivIsZero,
#[error("divide value is not even")]
DivideValueNotEven,
#[error("scrdv value is too large")]
ScrdvValueTooLarge,
}

View File

@ -26,6 +26,48 @@ use fugit::RateExtU32;
const IRQ_DST_NONE: u32 = 0xffffffff;
pub static MS_COUNTER: Mutex<Cell<u32>> = Mutex::new(Cell::new(0));
/// Get the peripheral block of a TIM peripheral given the index.
///
/// This function panics if the given index is greater than 23.
///
/// # Safety
///
/// This returns a direct handle to the peripheral block, which allows to circumvent ownership
/// rules for the peripheral block. You have to ensure that the retrieved peripheral block is not
/// used by any other software component.
#[inline(always)]
pub const unsafe fn get_tim_raw(tim_idx: usize) -> &'static pac::tim0::RegisterBlock {
match tim_idx {
0 => unsafe { &*pac::Tim0::ptr() },
1 => unsafe { &*pac::Tim1::ptr() },
2 => unsafe { &*pac::Tim2::ptr() },
3 => unsafe { &*pac::Tim3::ptr() },
4 => unsafe { &*pac::Tim4::ptr() },
5 => unsafe { &*pac::Tim5::ptr() },
6 => unsafe { &*pac::Tim6::ptr() },
7 => unsafe { &*pac::Tim7::ptr() },
8 => unsafe { &*pac::Tim8::ptr() },
9 => unsafe { &*pac::Tim9::ptr() },
10 => unsafe { &*pac::Tim10::ptr() },
11 => unsafe { &*pac::Tim11::ptr() },
12 => unsafe { &*pac::Tim12::ptr() },
13 => unsafe { &*pac::Tim13::ptr() },
14 => unsafe { &*pac::Tim14::ptr() },
15 => unsafe { &*pac::Tim15::ptr() },
16 => unsafe { &*pac::Tim16::ptr() },
17 => unsafe { &*pac::Tim17::ptr() },
18 => unsafe { &*pac::Tim18::ptr() },
19 => unsafe { &*pac::Tim19::ptr() },
20 => unsafe { &*pac::Tim20::ptr() },
21 => unsafe { &*pac::Tim21::ptr() },
22 => unsafe { &*pac::Tim22::ptr() },
23 => unsafe { &*pac::Tim23::ptr() },
_ => {
panic!("invalid alarm timer index")
}
}
}
//==================================================================================================
// Defintions
//==================================================================================================
@ -244,11 +286,11 @@ pub type TimRegBlock = tim0::RegisterBlock;
///
/// # Safety
///
/// Users should only implement the [`tim_id`] function. No default function
/// Users should only implement the [Self::tim_id] function. No default function
/// implementations should be overridden. The implementing type must also have
/// "control" over the corresponding pin ID, i.e. it must guarantee that a each
/// pin ID is a singleton.
pub(super) unsafe trait TimRegInterface {
pub unsafe trait TimRegInterface {
fn tim_id(&self) -> u8;
const PORT_BASE: *const tim0::RegisterBlock = pac::Tim0::ptr() as *const _;
@ -256,7 +298,7 @@ pub(super) unsafe trait TimRegInterface {
/// All 24 TIM blocks are identical. This helper functions returns the correct
/// memory mapped peripheral depending on the TIM ID.
#[inline(always)]
fn reg(&self) -> &TimRegBlock {
fn reg_block(&self) -> &TimRegBlock {
unsafe { &*Self::PORT_BASE.offset(self.tim_id() as isize) }
}
@ -293,70 +335,16 @@ pub(super) unsafe trait TimRegInterface {
}
}
/// Provide a safe register interface for [`ValidTimAndPin`]s
///
/// This `struct` takes ownership of a [`ValidTimAndPin`] and provides an API to
/// access the corresponding registers.
pub(super) struct TimAndPinRegister<Pin: TimPin, Tim: ValidTim> {
pin: Pin,
tim: Tim,
}
pub(super) struct TimRegister<TIM: ValidTim> {
tim: TIM,
}
impl<TIM: ValidTim> TimRegister<TIM> {
#[inline]
pub(super) unsafe fn new(tim: TIM) -> Self {
TimRegister { tim }
}
pub(super) fn release(self) -> TIM {
self.tim
}
}
unsafe impl<TIM: ValidTim> TimRegInterface for TimRegister<TIM> {
unsafe impl<Tim: ValidTim> TimRegInterface for Tim {
fn tim_id(&self) -> u8 {
TIM::TIM_ID
Tim::TIM_ID
}
}
impl<PIN: TimPin, TIM: ValidTim> TimAndPinRegister<PIN, TIM>
where
(PIN, TIM): ValidTimAndPin<PIN, TIM>,
{
#[inline]
pub(super) unsafe fn new(pin: PIN, tim: TIM) -> Self {
TimAndPinRegister { pin, tim }
}
pub(super) fn release(self) -> (PIN, TIM) {
(self.pin, self.tim)
}
}
unsafe impl<PIN: TimPin, TIM: ValidTim> TimRegInterface for TimAndPinRegister<PIN, TIM> {
#[inline(always)]
fn tim_id(&self) -> u8 {
TIM::TIM_ID
}
}
pub(super) struct TimDynRegister {
tim_id: u8,
pub(crate) struct TimDynRegister {
pub(crate) tim_id: u8,
#[allow(dead_code)]
pin_id: DynPinId,
}
impl<PIN: TimPin, TIM: ValidTim> From<TimAndPinRegister<PIN, TIM>> for TimDynRegister {
fn from(_reg: TimAndPinRegister<PIN, TIM>) -> Self {
Self {
tim_id: TIM::TIM_ID,
pin_id: PIN::DYN,
}
}
pub(crate) pin_id: DynPinId,
}
unsafe impl TimRegInterface for TimDynRegister {
@ -371,8 +359,8 @@ unsafe impl TimRegInterface for TimDynRegister {
//==================================================================================================
/// Hardware timers
pub struct CountdownTimer<TIM: ValidTim> {
tim: TimRegister<TIM>,
pub struct CountdownTimer<Tim: ValidTim> {
tim: Tim,
curr_freq: Hertz,
irq_cfg: Option<IrqCfg>,
sys_clk: Hertz,
@ -401,12 +389,12 @@ unsafe impl<TIM: ValidTim> TimRegInterface for CountdownTimer<TIM> {
}
}
impl<TIM: ValidTim> CountdownTimer<TIM> {
impl<Tim: ValidTim> CountdownTimer<Tim> {
/// Configures a TIM peripheral as a periodic count down timer
pub fn new(syscfg: &mut pac::Sysconfig, sys_clk: impl Into<Hertz>, tim: TIM) -> Self {
enable_tim_clk(syscfg, TIM::TIM_ID);
pub fn new(syscfg: &mut pac::Sysconfig, sys_clk: impl Into<Hertz>, tim: Tim) -> Self {
enable_tim_clk(syscfg, Tim::TIM_ID);
let cd_timer = CountdownTimer {
tim: unsafe { TimRegister::new(tim) },
tim,
sys_clk: sys_clk.into(),
irq_cfg: None,
rst_val: 0,
@ -416,7 +404,7 @@ impl<TIM: ValidTim> CountdownTimer<TIM> {
};
cd_timer
.tim
.reg()
.reg_block()
.ctrl()
.modify(|_, w| w.enable().set_bit());
cd_timer
@ -441,7 +429,7 @@ impl<TIM: ValidTim> CountdownTimer<TIM> {
}
if let Some(irq_sel) = irq_sel {
irq_sel
.tim0(TIM::TIM_ID as usize)
.tim0(Tim::TIM_ID as usize)
.write(|w| unsafe { w.bits(irq_cfg.irq as u32) });
}
}
@ -460,7 +448,7 @@ impl<TIM: ValidTim> CountdownTimer<TIM> {
Event::TimeOut => {
enable_peripheral_clock(syscfg, PeripheralClocks::Irqsel);
irqsel
.tim0(TIM::TIM_ID as usize)
.tim0(Tim::TIM_ID as usize)
.write(|w| unsafe { w.bits(IRQ_DST_NONE) });
self.disable_interrupt();
self.listening = false;
@ -470,25 +458,37 @@ impl<TIM: ValidTim> CountdownTimer<TIM> {
#[inline(always)]
pub fn enable_interrupt(&mut self) {
self.tim.reg().ctrl().modify(|_, w| w.irq_enb().set_bit());
self.tim
.reg_block()
.ctrl()
.modify(|_, w| w.irq_enb().set_bit());
}
#[inline(always)]
pub fn disable_interrupt(&mut self) {
self.tim.reg().ctrl().modify(|_, w| w.irq_enb().clear_bit());
self.tim
.reg_block()
.ctrl()
.modify(|_, w| w.irq_enb().clear_bit());
}
pub fn release(self, syscfg: &mut pac::Sysconfig) -> TIM {
self.tim.reg().ctrl().write(|w| w.enable().clear_bit());
pub fn release(self, syscfg: &mut pac::Sysconfig) -> Tim {
self.tim
.reg_block()
.ctrl()
.write(|w| w.enable().clear_bit());
syscfg
.tim_clk_enable()
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << TIM::TIM_ID)) });
self.tim.release()
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << Tim::TIM_ID)) });
self.tim
}
/// Load the count down timer with a timeout but do not start it.
pub fn load(&mut self, timeout: impl Into<Hertz>) {
self.tim.reg().ctrl().modify(|_, w| w.enable().clear_bit());
self.tim
.reg_block()
.ctrl()
.modify(|_, w| w.enable().clear_bit());
self.curr_freq = timeout.into();
self.rst_val = self.sys_clk.raw() / self.curr_freq.raw();
self.set_reload(self.rst_val);
@ -497,17 +497,23 @@ impl<TIM: ValidTim> CountdownTimer<TIM> {
#[inline(always)]
pub fn set_reload(&mut self, val: u32) {
self.tim.reg().rst_value().write(|w| unsafe { w.bits(val) });
self.tim
.reg_block()
.rst_value()
.write(|w| unsafe { w.bits(val) });
}
#[inline(always)]
pub fn set_count(&mut self, val: u32) {
self.tim.reg().cnt_value().write(|w| unsafe { w.bits(val) });
self.tim
.reg_block()
.cnt_value()
.write(|w| unsafe { w.bits(val) });
}
#[inline(always)]
pub fn count(&self) -> u32 {
self.tim.reg().cnt_value().read().bits()
self.tim.reg_block().cnt_value().read().bits()
}
#[inline(always)]
@ -518,24 +524,30 @@ impl<TIM: ValidTim> CountdownTimer<TIM> {
unsafe { enable_interrupt(irq_cfg.irq) };
}
}
self.tim.reg().enable().write(|w| unsafe { w.bits(1) });
self.tim
.reg_block()
.enable()
.write(|w| unsafe { w.bits(1) });
}
#[inline(always)]
pub fn disable(&mut self) {
self.tim.reg().enable().write(|w| unsafe { w.bits(0) });
self.tim
.reg_block()
.enable()
.write(|w| unsafe { w.bits(0) });
}
/// Disable the counter, setting both enable and active bit to 0
pub fn auto_disable(self, enable: bool) -> Self {
if enable {
self.tim
.reg()
.reg_block()
.ctrl()
.modify(|_, w| w.auto_disable().set_bit());
} else {
self.tim
.reg()
.reg_block()
.ctrl()
.modify(|_, w| w.auto_disable().clear_bit());
}
@ -549,12 +561,12 @@ impl<TIM: ValidTim> CountdownTimer<TIM> {
pub fn auto_deactivate(self, enable: bool) -> Self {
if enable {
self.tim
.reg()
.reg_block()
.ctrl()
.modify(|_, w| w.auto_deactivate().set_bit());
} else {
self.tim
.reg()
.reg_block()
.ctrl()
.modify(|_, w| w.auto_deactivate().clear_bit());
}
@ -563,7 +575,7 @@ impl<TIM: ValidTim> CountdownTimer<TIM> {
/// Configure the cascade parameters
pub fn cascade_control(&mut self, ctrl: CascadeCtrl) {
self.tim.reg().csd_ctrl().write(|w| {
self.tim.reg_block().csd_ctrl().write(|w| {
w.csden0().bit(ctrl.enb_start_src_csd0);
w.csdinv0().bit(ctrl.inv_csd0);
w.csden1().bit(ctrl.enb_start_src_csd1);
@ -580,7 +592,7 @@ impl<TIM: ValidTim> CountdownTimer<TIM> {
pub fn cascade_0_source(&mut self, src: CascadeSource) -> Result<(), InvalidCascadeSourceId> {
let id = src.id()?;
self.tim
.reg()
.reg_block()
.cascade0()
.write(|w| unsafe { w.cassel().bits(id) });
Ok(())
@ -589,7 +601,7 @@ impl<TIM: ValidTim> CountdownTimer<TIM> {
pub fn cascade_1_source(&mut self, src: CascadeSource) -> Result<(), InvalidCascadeSourceId> {
let id = src.id()?;
self.tim
.reg()
.reg_block()
.cascade1()
.write(|w| unsafe { w.cassel().bits(id) });
Ok(())
@ -598,7 +610,7 @@ impl<TIM: ValidTim> CountdownTimer<TIM> {
pub fn cascade_2_source(&mut self, src: CascadeSource) -> Result<(), InvalidCascadeSourceId> {
let id = src.id()?;
self.tim
.reg()
.reg_block()
.cascade2()
.write(|w| unsafe { w.cassel().bits(id) });
Ok(())
@ -627,7 +639,7 @@ impl<TIM: ValidTim> CountdownTimer<TIM> {
/// Return `Ok` if the timer has wrapped. Peripheral will automatically clear the
/// flag and restart the time if configured correctly
pub fn wait(&mut self) -> nb::Result<(), void::Void> {
let cnt = self.tim.reg().cnt_value().read().bits();
let cnt = self.tim.reg_block().cnt_value().read().bits();
if (cnt > self.last_cnt) || cnt == 0 {
self.last_cnt = self.rst_val;
Ok(())
@ -639,10 +651,13 @@ impl<TIM: ValidTim> CountdownTimer<TIM> {
/// Returns [false] if the timer was not active, and true otherwise.
pub fn cancel(&mut self) -> bool {
if !self.tim.reg().ctrl().read().enable().bit_is_set() {
if !self.tim.reg_block().ctrl().read().enable().bit_is_set() {
return false;
}
self.tim.reg().ctrl().write(|w| w.enable().clear_bit());
self.tim
.reg_block()
.ctrl()
.write(|w| w.enable().clear_bit());
true
}
}

View File

@ -48,30 +48,30 @@ impl Pins<pac::Uartb> for (Pin<PB21, AltFunc1>, Pin<PB20, AltFunc1>) {}
// Regular Definitions
//==================================================================================================
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[error("transer is pending")]
pub struct TransferPendingError;
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum RxError {
#[error("overrun error")]
Overrun,
#[error("framing error")]
Framing,
#[error("parity error")]
Parity,
}
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error {
Rx(RxError),
#[error("rx error: {0}")]
Rx(#[from] RxError),
#[error("break condition")]
BreakCondition,
}
impl From<RxError> for Error {
fn from(value: RxError) -> Self {
Self::Rx(value)
}
}
impl embedded_io::Error for Error {
fn kind(&self) -> embedded_io::ErrorKind {
embedded_io::ErrorKind::Other
@ -284,17 +284,17 @@ impl IrqResultMaxSizeOrTimeout {
#[inline]
pub fn overflow_error(&self) -> bool {
self.errors.map_or(false, |e| e.overflow)
self.errors.is_some_and(|e| e.overflow)
}
#[inline]
pub fn framing_error(&self) -> bool {
self.errors.map_or(false, |e| e.framing)
self.errors.is_some_and(|e| e.framing)
}
#[inline]
pub fn parity_error(&self) -> bool {
self.errors.map_or(false, |e| e.parity)
self.errors.is_some_and(|e| e.parity)
}
#[inline]
@ -1213,243 +1213,3 @@ impl<Uart: Instance> RxWithIrq<Uart> {
self.rx.release()
}
}
/*
impl<UART: Instance, PINS> UartWithIrq<UART, PINS> {
/// See [`UartWithIrqBase::read_fixed_len_using_irq`] doc
pub fn read_fixed_len_using_irq(
&mut self,
max_len: usize,
enb_timeout_irq: bool,
) -> Result<(), Error> {
self.irq_base
.read_fixed_len_using_irq(max_len, enb_timeout_irq)
}
pub fn cancel_transfer(&mut self) {
self.irq_base.cancel_transfer()
}
/// See [`UartWithIrqBase::irq_handler`] doc
pub fn irq_handler(&mut self, res: &mut IrqResult, buf: &mut [u8]) -> Result<(), Error> {
self.irq_base.irq_handler(res, buf)
}
pub fn release(self) -> (UART, PINS) {
(self.irq_base.release(), self.pins)
}
pub fn downgrade(self) -> (UartWithIrqBase<UART>, PINS) {
(self.irq_base, self.pins)
}
}
impl<Uart: Instance> UartWithIrqBase<Uart> {
fn init(self, sys_cfg: Option<&mut pac::Sysconfig>, irq_sel: Option<&mut pac::Irqsel>) -> Self {
if let Some(sys_cfg) = sys_cfg {
enable_peripheral_clock(sys_cfg, PeripheralClocks::Irqsel)
}
if let Some(irq_sel) = irq_sel {
if self.irq_info.irq_cfg.route {
irq_sel
.uart0(Uart::IDX as usize)
.write(|w| unsafe { w.bits(self.irq_info.irq_cfg.irq as u32) });
}
}
self
}
/// This initializes a non-blocking read transfer using the IRQ capabilities of the UART
/// peripheral.
///
/// The only required information is the maximum length for variable sized reception
/// or the expected length for fixed length reception. If variable sized packets are expected,
/// the timeout functionality of the IRQ should be enabled as well. After calling this function,
/// the [`irq_handler`](Self::irq_handler) function should be called in the user interrupt
/// handler to read the received packets and reinitiate another transfer if desired.
pub fn read_fixed_len_using_irq(
&mut self,
max_len: usize,
enb_timeout_irq: bool,
) -> Result<(), Error> {
if self.irq_info.mode != IrqReceptionMode::Idle {
return Err(Error::TransferPending);
}
self.irq_info.mode = IrqReceptionMode::Pending;
self.irq_info.rx_idx = 0;
self.irq_info.rx_len = max_len;
self.uart.enable_rx();
self.uart.enable_tx();
self.enable_rx_irq_sources(enb_timeout_irq);
if self.irq_info.irq_cfg.enable {
unsafe {
enable_interrupt(self.irq_info.irq_cfg.irq);
}
}
Ok(())
}
#[inline]
fn enable_rx_irq_sources(&mut self, timeout: bool) {
self.uart.uart.irq_enb().modify(|_, w| {
if timeout {
w.irq_rx_to().set_bit();
}
w.irq_rx_status().set_bit();
w.irq_rx().set_bit()
});
}
#[inline]
fn disable_rx_irq_sources(&mut self) {
self.uart.uart.irq_enb().modify(|_, w| {
w.irq_rx_to().clear_bit();
w.irq_rx_status().clear_bit();
w.irq_rx().clear_bit()
});
}
#[inline]
pub fn enable_tx(&mut self) {
self.uart.enable_tx()
}
#[inline]
pub fn disable_tx(&mut self) {
self.uart.disable_tx()
}
pub fn cancel_transfer(&mut self) {
// Disable IRQ
cortex_m::peripheral::NVIC::mask(self.irq_info.irq_cfg.irq);
self.disable_rx_irq_sources();
self.uart.clear_tx_fifo();
self.irq_info.rx_idx = 0;
self.irq_info.rx_len = 0;
}
/// Default IRQ handler which can be used to read the packets arriving on the UART peripheral.
///
/// If passed buffer is equal to or larger than the specified maximum length, an
/// [`Error::BufferTooShort`] will be returned
pub fn irq_handler(&mut self, res: &mut IrqResult, buf: &mut [u8]) -> Result<(), Error> {
if buf.len() < self.irq_info.rx_len {
return Err(Error::BufferTooShort);
}
let irq_end = self.uart.uart.irq_end().read();
let enb_status = self.uart.uart.enable().read();
let rx_enabled = enb_status.rxenable().bit_is_set();
let _tx_enabled = enb_status.txenable().bit_is_set();
let read_handler =
|res: &mut IrqResult, read_res: nb::Result<u8, Error>| -> Result<Option<u8>, Error> {
match read_res {
Ok(byte) => Ok(Some(byte)),
Err(nb::Error::WouldBlock) => Ok(None),
Err(nb::Error::Other(e)) => match e {
Error::Overrun => {
res.set_result(IrqResultMask::Overflow);
Err(Error::IrqError)
}
Error::FramingError => {
res.set_result(IrqResultMask::FramingError);
Err(Error::IrqError)
}
Error::ParityError => {
res.set_result(IrqResultMask::ParityError);
Err(Error::IrqError)
}
_ => {
res.set_result(IrqResultMask::Unknown);
Err(Error::IrqError)
}
},
}
};
if irq_end.irq_rx().bit_is_set() {
// If this interrupt bit is set, the trigger level is available at the very least.
// Read everything as fast as possible
for _ in 0..core::cmp::min(
self.uart.uart.rxfifoirqtrg().read().bits() as usize,
self.irq_info.rx_len,
) {
buf[self.irq_info.rx_idx] = (self.uart.uart.data().read().bits() & 0xff) as u8;
self.irq_info.rx_idx += 1;
}
// While there is data in the FIFO, write it into the reception buffer
loop {
if self.irq_info.rx_idx == self.irq_info.rx_len {
self.irq_completion_handler(res);
return Ok(());
}
if let Some(byte) = read_handler(res, self.uart.read())? {
buf[self.irq_info.rx_idx] = byte;
self.irq_info.rx_idx += 1;
} else {
break;
}
}
}
// RX transfer not complete, check for RX errors
if (self.irq_info.rx_idx < self.irq_info.rx_len) && rx_enabled {
// Read status register again, might have changed since reading received data
let rx_status = self.uart.uart.rxstatus().read();
res.clear_result();
if rx_status.rxovr().bit_is_set() {
res.set_result(IrqResultMask::Overflow);
}
if rx_status.rxfrm().bit_is_set() {
res.set_result(IrqResultMask::FramingError);
}
if rx_status.rxpar().bit_is_set() {
res.set_result(IrqResultMask::ParityError);
}
if rx_status.rxbrk().bit_is_set() {
res.set_result(IrqResultMask::Break);
}
if rx_status.rxto().bit_is_set() {
// A timeout has occured but there might be some leftover data in the FIFO,
// so read that data as well
while let Some(byte) = read_handler(res, self.uart.read())? {
buf[self.irq_info.rx_idx] = byte;
self.irq_info.rx_idx += 1;
}
self.irq_completion_handler(res);
res.set_result(IrqResultMask::Timeout);
return Ok(());
}
// If it is not a timeout, it's an error
if res.raw_res != 0 {
self.disable_rx_irq_sources();
return Err(Error::IrqError);
}
}
// Clear the interrupt status bits
self.uart
.uart
.irq_clr()
.write(|w| unsafe { w.bits(irq_end.bits()) });
Ok(())
}
fn irq_completion_handler(&mut self, res: &mut IrqResult) {
self.disable_rx_irq_sources();
self.uart.disable_rx();
res.bytes_read = self.irq_info.rx_idx;
res.clear_result();
res.set_result(IrqResultMask::Complete);
self.irq_info.mode = IrqReceptionMode::Idle;
self.irq_info.rx_idx = 0;
self.irq_info.rx_len = 0;
}
pub fn release(self) -> Uart {
self.uart.release()
}
}
*/

View File

@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [unreleased]
## [v0.4.0] 2025-02-12
- Re-generated PAC with `svd2rust` v0.35.0
## [v0.3.0] 2024-06-16
- Re-generated PAC with `svd2rust` v0.33.3

View File

@ -1,6 +1,6 @@
[package]
name = "va108xx"
version = "0.3.0"
version = "0.4.0"
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
edition = "2021"
description = "PAC for the Vorago VA108xx family of microcontrollers"

View File

@ -24,7 +24,7 @@ features = ["rt"]
The `rt` feature is optional and recommended. It brings in support for `cortex-m-rt`.
For full details on the autgenerated API, please see the
[svd2rust documentation](https://docs.rs/svd2rust/0.19.0/svd2rust/#peripheral-api).
[svd2rust documentation](https://docs.rs/svd2rust/latest/svd2rust/#peripheral-api).
## Regenerating the PAC

3
va108xx/docs.sh Executable file
View File

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

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
# Use installed tool by default
svd2rust_bin="svd2rust"

View File

@ -82,169 +82,6 @@ pub trait Resettable: RegisterSpec {
Self::RESET_VALUE
}
}
#[doc = " This structure provides volatile access to registers."]
#[repr(transparent)]
pub struct Reg<REG: RegisterSpec> {
register: vcell::VolatileCell<REG::Ux>,
_marker: marker::PhantomData<REG>,
}
unsafe impl<REG: RegisterSpec> Send for Reg<REG> where REG::Ux: Send {}
impl<REG: RegisterSpec> Reg<REG> {
#[doc = " Returns the underlying memory address of register."]
#[doc = ""]
#[doc = " ```ignore"]
#[doc = " let reg_ptr = periph.reg.as_ptr();"]
#[doc = " ```"]
#[inline(always)]
pub fn as_ptr(&self) -> *mut REG::Ux {
self.register.as_ptr()
}
}
impl<REG: Readable> Reg<REG> {
#[doc = " Reads the contents of a `Readable` register."]
#[doc = ""]
#[doc = " You can read the raw contents of a register by using `bits`:"]
#[doc = " ```ignore"]
#[doc = " let bits = periph.reg.read().bits();"]
#[doc = " ```"]
#[doc = " or get the content of a particular field of a register:"]
#[doc = " ```ignore"]
#[doc = " let reader = periph.reg.read();"]
#[doc = " let bits = reader.field1().bits();"]
#[doc = " let flag = reader.field2().bit_is_set();"]
#[doc = " ```"]
#[inline(always)]
pub fn read(&self) -> R<REG> {
R {
bits: self.register.get(),
_reg: marker::PhantomData,
}
}
}
impl<REG: Resettable + Writable> Reg<REG> {
#[doc = " Writes the reset value to `Writable` register."]
#[doc = ""]
#[doc = " Resets the register to its initial state."]
#[inline(always)]
pub fn reset(&self) {
self.register.set(REG::RESET_VALUE)
}
#[doc = " Writes bits to a `Writable` register."]
#[doc = ""]
#[doc = " You can write raw bits into a register:"]
#[doc = " ```ignore"]
#[doc = " periph.reg.write(|w| unsafe { w.bits(rawbits) });"]
#[doc = " ```"]
#[doc = " or write only the fields you need:"]
#[doc = " ```ignore"]
#[doc = " periph.reg.write(|w| w"]
#[doc = " .field1().bits(newfield1bits)"]
#[doc = " .field2().set_bit()"]
#[doc = " .field3().variant(VARIANT)"]
#[doc = " );"]
#[doc = " ```"]
#[doc = " or an alternative way of saying the same:"]
#[doc = " ```ignore"]
#[doc = " periph.reg.write(|w| {"]
#[doc = " w.field1().bits(newfield1bits);"]
#[doc = " w.field2().set_bit();"]
#[doc = " w.field3().variant(VARIANT)"]
#[doc = " });"]
#[doc = " ```"]
#[doc = " In the latter case, other fields will be set to their reset value."]
#[inline(always)]
pub fn write<F>(&self, f: F)
where
F: FnOnce(&mut W<REG>) -> &mut W<REG>,
{
self.register.set(
f(&mut W {
bits: REG::RESET_VALUE & !REG::ONE_TO_MODIFY_FIELDS_BITMAP
| REG::ZERO_TO_MODIFY_FIELDS_BITMAP,
_reg: marker::PhantomData,
})
.bits,
);
}
}
impl<REG: Writable> Reg<REG> {
#[doc = " Writes 0 to a `Writable` register."]
#[doc = ""]
#[doc = " Similar to `write`, but unused bits will contain 0."]
#[doc = ""]
#[doc = " # Safety"]
#[doc = ""]
#[doc = " Unsafe to use with registers which don't allow to write 0."]
#[inline(always)]
pub unsafe fn write_with_zero<F>(&self, f: F)
where
F: FnOnce(&mut W<REG>) -> &mut W<REG>,
{
self.register.set(
f(&mut W {
bits: REG::Ux::default(),
_reg: marker::PhantomData,
})
.bits,
);
}
}
impl<REG: Readable + Writable> Reg<REG> {
#[doc = " Modifies the contents of the register by reading and then writing it."]
#[doc = ""]
#[doc = " E.g. to do a read-modify-write sequence to change parts of a register:"]
#[doc = " ```ignore"]
#[doc = " periph.reg.modify(|r, w| unsafe { w.bits("]
#[doc = " r.bits() | 3"]
#[doc = " ) });"]
#[doc = " ```"]
#[doc = " or"]
#[doc = " ```ignore"]
#[doc = " periph.reg.modify(|_, w| w"]
#[doc = " .field1().bits(newfield1bits)"]
#[doc = " .field2().set_bit()"]
#[doc = " .field3().variant(VARIANT)"]
#[doc = " );"]
#[doc = " ```"]
#[doc = " or an alternative way of saying the same:"]
#[doc = " ```ignore"]
#[doc = " periph.reg.modify(|_, w| {"]
#[doc = " w.field1().bits(newfield1bits);"]
#[doc = " w.field2().set_bit();"]
#[doc = " w.field3().variant(VARIANT)"]
#[doc = " });"]
#[doc = " ```"]
#[doc = " Other fields will have the value they had before the call to `modify`."]
#[inline(always)]
pub fn modify<F>(&self, f: F)
where
for<'w> F: FnOnce(&R<REG>, &'w mut W<REG>) -> &'w mut W<REG>,
{
let bits = self.register.get();
self.register.set(
f(
&R {
bits,
_reg: marker::PhantomData,
},
&mut W {
bits: bits & !REG::ONE_TO_MODIFY_FIELDS_BITMAP
| REG::ZERO_TO_MODIFY_FIELDS_BITMAP,
_reg: marker::PhantomData,
},
)
.bits,
);
}
}
impl<REG: Readable> core::fmt::Debug for crate::generic::Reg<REG>
where
R<REG>: core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Debug::fmt(&self.read(), f)
}
}
#[doc(hidden)]
pub mod raw;
#[doc = " Register reader."]
@ -369,7 +206,7 @@ pub struct RangeTo<const MAX: u64>;
#[doc = " Write field Proxy"]
pub type FieldWriter<'a, REG, const WI: u8, FI = u8, Safety = Unsafe> =
raw::FieldWriter<'a, REG, WI, FI, Safety>;
impl<'a, REG, const WI: u8, FI, Safety> FieldWriter<'a, REG, WI, FI, Safety>
impl<REG, const WI: u8, FI, Safety> FieldWriter<'_, REG, WI, FI, Safety>
where
REG: Writable + RegisterSpec,
FI: FieldSpec,
@ -616,3 +453,278 @@ where
self.w
}
}
#[doc = " This structure provides volatile access to registers."]
#[repr(transparent)]
pub struct Reg<REG: RegisterSpec> {
register: vcell::VolatileCell<REG::Ux>,
_marker: marker::PhantomData<REG>,
}
unsafe impl<REG: RegisterSpec> Send for Reg<REG> where REG::Ux: Send {}
impl<REG: RegisterSpec> Reg<REG> {
#[doc = " Returns the underlying memory address of register."]
#[doc = ""]
#[doc = " ```ignore"]
#[doc = " let reg_ptr = periph.reg.as_ptr();"]
#[doc = " ```"]
#[inline(always)]
pub fn as_ptr(&self) -> *mut REG::Ux {
self.register.as_ptr()
}
}
impl<REG: Readable> Reg<REG> {
#[doc = " Reads the contents of a `Readable` register."]
#[doc = ""]
#[doc = " You can read the raw contents of a register by using `bits`:"]
#[doc = " ```ignore"]
#[doc = " let bits = periph.reg.read().bits();"]
#[doc = " ```"]
#[doc = " or get the content of a particular field of a register:"]
#[doc = " ```ignore"]
#[doc = " let reader = periph.reg.read();"]
#[doc = " let bits = reader.field1().bits();"]
#[doc = " let flag = reader.field2().bit_is_set();"]
#[doc = " ```"]
#[inline(always)]
pub fn read(&self) -> R<REG> {
R {
bits: self.register.get(),
_reg: marker::PhantomData,
}
}
}
impl<REG: Resettable + Writable> Reg<REG> {
#[doc = " Writes the reset value to `Writable` register."]
#[doc = ""]
#[doc = " Resets the register to its initial state."]
#[inline(always)]
pub fn reset(&self) {
self.register.set(REG::RESET_VALUE)
}
#[doc = " Writes bits to a `Writable` register."]
#[doc = ""]
#[doc = " You can write raw bits into a register:"]
#[doc = " ```ignore"]
#[doc = " periph.reg.write(|w| unsafe { w.bits(rawbits) });"]
#[doc = " ```"]
#[doc = " or write only the fields you need:"]
#[doc = " ```ignore"]
#[doc = " periph.reg.write(|w| w"]
#[doc = " .field1().bits(newfield1bits)"]
#[doc = " .field2().set_bit()"]
#[doc = " .field3().variant(VARIANT)"]
#[doc = " );"]
#[doc = " ```"]
#[doc = " or an alternative way of saying the same:"]
#[doc = " ```ignore"]
#[doc = " periph.reg.write(|w| {"]
#[doc = " w.field1().bits(newfield1bits);"]
#[doc = " w.field2().set_bit();"]
#[doc = " w.field3().variant(VARIANT)"]
#[doc = " });"]
#[doc = " ```"]
#[doc = " In the latter case, other fields will be set to their reset value."]
#[inline(always)]
pub fn write<F>(&self, f: F) -> REG::Ux
where
F: FnOnce(&mut W<REG>) -> &mut W<REG>,
{
let value = f(&mut W {
bits: REG::RESET_VALUE & !REG::ONE_TO_MODIFY_FIELDS_BITMAP
| REG::ZERO_TO_MODIFY_FIELDS_BITMAP,
_reg: marker::PhantomData,
})
.bits;
self.register.set(value);
value
}
#[doc = " Writes bits to a `Writable` register and produce a value."]
#[doc = ""]
#[doc = " You can write raw bits into a register:"]
#[doc = " ```ignore"]
#[doc = " periph.reg.write_and(|w| unsafe { w.bits(rawbits); });"]
#[doc = " ```"]
#[doc = " or write only the fields you need:"]
#[doc = " ```ignore"]
#[doc = " periph.reg.write_and(|w| {"]
#[doc = " w.field1().bits(newfield1bits)"]
#[doc = " .field2().set_bit()"]
#[doc = " .field3().variant(VARIANT);"]
#[doc = " });"]
#[doc = " ```"]
#[doc = " or an alternative way of saying the same:"]
#[doc = " ```ignore"]
#[doc = " periph.reg.write_and(|w| {"]
#[doc = " w.field1().bits(newfield1bits);"]
#[doc = " w.field2().set_bit();"]
#[doc = " w.field3().variant(VARIANT);"]
#[doc = " });"]
#[doc = " ```"]
#[doc = " In the latter case, other fields will be set to their reset value."]
#[doc = ""]
#[doc = " Values can be returned from the closure:"]
#[doc = " ```ignore"]
#[doc = " let state = periph.reg.write_and(|w| State::set(w.field1()));"]
#[doc = " ```"]
#[inline(always)]
pub fn from_write<F, T>(&self, f: F) -> T
where
F: FnOnce(&mut W<REG>) -> T,
{
let mut writer = W {
bits: REG::RESET_VALUE & !REG::ONE_TO_MODIFY_FIELDS_BITMAP
| REG::ZERO_TO_MODIFY_FIELDS_BITMAP,
_reg: marker::PhantomData,
};
let result = f(&mut writer);
self.register.set(writer.bits);
result
}
}
impl<REG: Writable> Reg<REG> {
#[doc = " Writes 0 to a `Writable` register."]
#[doc = ""]
#[doc = " Similar to `write`, but unused bits will contain 0."]
#[doc = ""]
#[doc = " # Safety"]
#[doc = ""]
#[doc = " Unsafe to use with registers which don't allow to write 0."]
#[inline(always)]
pub unsafe fn write_with_zero<F>(&self, f: F) -> REG::Ux
where
F: FnOnce(&mut W<REG>) -> &mut W<REG>,
{
let value = f(&mut W {
bits: REG::Ux::default(),
_reg: marker::PhantomData,
})
.bits;
self.register.set(value);
value
}
#[doc = " Writes 0 to a `Writable` register and produces a value."]
#[doc = ""]
#[doc = " Similar to `write`, but unused bits will contain 0."]
#[doc = ""]
#[doc = " # Safety"]
#[doc = ""]
#[doc = " Unsafe to use with registers which don't allow to write 0."]
#[inline(always)]
pub unsafe fn from_write_with_zero<F, T>(&self, f: F) -> T
where
F: FnOnce(&mut W<REG>) -> T,
{
let mut writer = W {
bits: REG::Ux::default(),
_reg: marker::PhantomData,
};
let result = f(&mut writer);
self.register.set(writer.bits);
result
}
}
impl<REG: Readable + Writable> Reg<REG> {
#[doc = " Modifies the contents of the register by reading and then writing it."]
#[doc = ""]
#[doc = " E.g. to do a read-modify-write sequence to change parts of a register:"]
#[doc = " ```ignore"]
#[doc = " periph.reg.modify(|r, w| unsafe { w.bits("]
#[doc = " r.bits() | 3"]
#[doc = " ) });"]
#[doc = " ```"]
#[doc = " or"]
#[doc = " ```ignore"]
#[doc = " periph.reg.modify(|_, w| w"]
#[doc = " .field1().bits(newfield1bits)"]
#[doc = " .field2().set_bit()"]
#[doc = " .field3().variant(VARIANT)"]
#[doc = " );"]
#[doc = " ```"]
#[doc = " or an alternative way of saying the same:"]
#[doc = " ```ignore"]
#[doc = " periph.reg.modify(|_, w| {"]
#[doc = " w.field1().bits(newfield1bits);"]
#[doc = " w.field2().set_bit();"]
#[doc = " w.field3().variant(VARIANT)"]
#[doc = " });"]
#[doc = " ```"]
#[doc = " Other fields will have the value they had before the call to `modify`."]
#[inline(always)]
pub fn modify<F>(&self, f: F) -> REG::Ux
where
for<'w> F: FnOnce(&R<REG>, &'w mut W<REG>) -> &'w mut W<REG>,
{
let bits = self.register.get();
let value = f(
&R {
bits,
_reg: marker::PhantomData,
},
&mut W {
bits: bits & !REG::ONE_TO_MODIFY_FIELDS_BITMAP | REG::ZERO_TO_MODIFY_FIELDS_BITMAP,
_reg: marker::PhantomData,
},
)
.bits;
self.register.set(value);
value
}
#[doc = " Modifies the contents of the register by reading and then writing it"]
#[doc = " and produces a value."]
#[doc = ""]
#[doc = " E.g. to do a read-modify-write sequence to change parts of a register:"]
#[doc = " ```ignore"]
#[doc = " let bits = periph.reg.modify(|r, w| {"]
#[doc = " let new_bits = r.bits() | 3;"]
#[doc = " unsafe {"]
#[doc = " w.bits(new_bits);"]
#[doc = " }"]
#[doc = ""]
#[doc = " new_bits"]
#[doc = " });"]
#[doc = " ```"]
#[doc = " or"]
#[doc = " ```ignore"]
#[doc = " periph.reg.modify(|_, w| {"]
#[doc = " w.field1().bits(newfield1bits)"]
#[doc = " .field2().set_bit()"]
#[doc = " .field3().variant(VARIANT);"]
#[doc = " });"]
#[doc = " ```"]
#[doc = " or an alternative way of saying the same:"]
#[doc = " ```ignore"]
#[doc = " periph.reg.modify(|_, w| {"]
#[doc = " w.field1().bits(newfield1bits);"]
#[doc = " w.field2().set_bit();"]
#[doc = " w.field3().variant(VARIANT);"]
#[doc = " });"]
#[doc = " ```"]
#[doc = " Other fields will have the value they had before the call to `modify`."]
#[inline(always)]
pub fn from_modify<F, T>(&self, f: F) -> T
where
for<'w> F: FnOnce(&R<REG>, &'w mut W<REG>) -> T,
{
let bits = self.register.get();
let mut writer = W {
bits: bits & !REG::ONE_TO_MODIFY_FIELDS_BITMAP | REG::ZERO_TO_MODIFY_FIELDS_BITMAP,
_reg: marker::PhantomData,
};
let result = f(
&R {
bits,
_reg: marker::PhantomData,
},
&mut writer,
);
self.register.set(writer.bits);
result
}
}
impl<REG: Readable> core::fmt::Debug for crate::generic::Reg<REG>
where
R<REG>: core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Debug::fmt(&self.read(), f)
}
}

View File

@ -41,6 +41,7 @@ impl<FI> BitReader<FI> {
}
}
}
#[must_use = "after creating `FieldWriter` you need to call field value setting method"]
pub struct FieldWriter<'a, REG, const WI: u8, FI = u8, Safety = Unsafe>
where
REG: Writable + RegisterSpec,
@ -66,6 +67,7 @@ where
}
}
}
#[must_use = "after creating `BitWriter` you need to call bit setting method"]
pub struct BitWriter<'a, REG, FI = bool, M = BitM>
where
REG: Writable + RegisterSpec,

View File

@ -240,67 +240,67 @@ impl RegisterBlock {
&self.perid
}
}
#[doc = "CTRL (rw) register accessor: Control Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`ctrl::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`ctrl::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@ctrl`]
#[doc = "CTRL (rw) register accessor: Control Register\n\nYou can [`read`](crate::Reg::read) this register and get [`ctrl::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`ctrl::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@ctrl`]
module"]
#[doc(alias = "CTRL")]
pub type Ctrl = crate::Reg<ctrl::CtrlSpec>;
#[doc = "Control Register"]
pub mod ctrl;
#[doc = "CLKSCALE (rw) register accessor: Clock Scale divide value\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`clkscale::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`clkscale::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@clkscale`]
#[doc = "CLKSCALE (rw) register accessor: Clock Scale divide value\n\nYou can [`read`](crate::Reg::read) this register and get [`clkscale::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`clkscale::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@clkscale`]
module"]
#[doc(alias = "CLKSCALE")]
pub type Clkscale = crate::Reg<clkscale::ClkscaleSpec>;
#[doc = "Clock Scale divide value"]
pub mod clkscale;
#[doc = "WORDS (rw) register accessor: Word Count value\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`words::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`words::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@words`]
#[doc = "WORDS (rw) register accessor: Word Count value\n\nYou can [`read`](crate::Reg::read) this register and get [`words::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`words::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@words`]
module"]
#[doc(alias = "WORDS")]
pub type Words = crate::Reg<words::WordsSpec>;
#[doc = "Word Count value"]
pub mod words;
#[doc = "ADDRESS (rw) register accessor: I2C Address value\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`address::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`address::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@address`]
#[doc = "ADDRESS (rw) register accessor: I2C Address value\n\nYou can [`read`](crate::Reg::read) this register and get [`address::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`address::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@address`]
module"]
#[doc(alias = "ADDRESS")]
pub type Address = crate::Reg<address::AddressSpec>;
#[doc = "I2C Address value"]
pub mod address;
#[doc = "DATA (rw) register accessor: Data Input/Output\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`data::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`data::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@data`]
#[doc = "DATA (rw) register accessor: Data Input/Output\n\nYou can [`read`](crate::Reg::read) this register and get [`data::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`data::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@data`]
module"]
#[doc(alias = "DATA")]
pub type Data = crate::Reg<data::DataSpec>;
#[doc = "Data Input/Output"]
pub mod data;
#[doc = "CMD (rw) register accessor: Command Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`cmd::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`cmd::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@cmd`]
#[doc = "CMD (rw) register accessor: Command Register\n\nYou can [`read`](crate::Reg::read) this register and get [`cmd::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`cmd::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@cmd`]
module"]
#[doc(alias = "CMD")]
pub type Cmd = crate::Reg<cmd::CmdSpec>;
#[doc = "Command Register"]
pub mod cmd;
#[doc = "STATUS (r) register accessor: I2C Controller Status Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`status::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@status`]
#[doc = "STATUS (r) register accessor: I2C Controller Status Register\n\nYou can [`read`](crate::Reg::read) this register and get [`status::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@status`]
module"]
#[doc(alias = "STATUS")]
pub type Status = crate::Reg<status::StatusSpec>;
#[doc = "I2C Controller Status Register"]
pub mod status;
#[doc = "STATE (r) register accessor: Internal STATE of I2C Master Controller\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`state::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@state`]
#[doc = "STATE (r) register accessor: Internal STATE of I2C Master Controller\n\nYou can [`read`](crate::Reg::read) this register and get [`state::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@state`]
module"]
#[doc(alias = "STATE")]
pub type State = crate::Reg<state::StateSpec>;
#[doc = "Internal STATE of I2C Master Controller"]
pub mod state;
#[doc = "TXCOUNT (r) register accessor: TX Count Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`txcount::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@txcount`]
#[doc = "TXCOUNT (r) register accessor: TX Count Register\n\nYou can [`read`](crate::Reg::read) this register and get [`txcount::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@txcount`]
module"]
#[doc(alias = "TXCOUNT")]
pub type Txcount = crate::Reg<txcount::TxcountSpec>;
#[doc = "TX Count Register"]
pub mod txcount;
#[doc = "RXCOUNT (r) register accessor: RX Count Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`rxcount::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@rxcount`]
#[doc = "RXCOUNT (r) register accessor: RX Count Register\n\nYou can [`read`](crate::Reg::read) this register and get [`rxcount::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@rxcount`]
module"]
#[doc(alias = "RXCOUNT")]
pub type Rxcount = crate::Reg<rxcount::RxcountSpec>;
#[doc = "RX Count Register"]
pub mod rxcount;
#[doc = "IRQ_ENB (rw) register accessor: Interrupt Enable Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`irq_enb::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`irq_enb::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@irq_enb`]
#[doc = "IRQ_ENB (rw) register accessor: Interrupt Enable Register\n\nYou can [`read`](crate::Reg::read) this register and get [`irq_enb::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`irq_enb::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@irq_enb`]
module"]
#[doc(alias = "IRQ_ENB")]
pub type IrqEnb = crate::Reg<irq_enb::IrqEnbSpec>;
@ -312,97 +312,97 @@ pub use irq_enb as irq_clr;
pub use IrqEnb as IrqRaw;
pub use IrqEnb as IrqEnd;
pub use IrqEnb as IrqClr;
#[doc = "RXFIFOIRQTRG (rw) register accessor: Rx FIFO IRQ Trigger Level\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`rxfifoirqtrg::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`rxfifoirqtrg::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@rxfifoirqtrg`]
#[doc = "RXFIFOIRQTRG (rw) register accessor: Rx FIFO IRQ Trigger Level\n\nYou can [`read`](crate::Reg::read) this register and get [`rxfifoirqtrg::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`rxfifoirqtrg::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@rxfifoirqtrg`]
module"]
#[doc(alias = "RXFIFOIRQTRG")]
pub type Rxfifoirqtrg = crate::Reg<rxfifoirqtrg::RxfifoirqtrgSpec>;
#[doc = "Rx FIFO IRQ Trigger Level"]
pub mod rxfifoirqtrg;
#[doc = "TXFIFOIRQTRG (rw) register accessor: Tx FIFO IRQ Trigger Level\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`txfifoirqtrg::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`txfifoirqtrg::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@txfifoirqtrg`]
#[doc = "TXFIFOIRQTRG (rw) register accessor: Tx FIFO IRQ Trigger Level\n\nYou can [`read`](crate::Reg::read) this register and get [`txfifoirqtrg::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`txfifoirqtrg::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@txfifoirqtrg`]
module"]
#[doc(alias = "TXFIFOIRQTRG")]
pub type Txfifoirqtrg = crate::Reg<txfifoirqtrg::TxfifoirqtrgSpec>;
#[doc = "Tx FIFO IRQ Trigger Level"]
pub mod txfifoirqtrg;
#[doc = "FIFO_CLR (w) register accessor: Clear FIFO Register\n\nYou can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`fifo_clr::W`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@fifo_clr`]
#[doc = "FIFO_CLR (w) register accessor: Clear FIFO Register\n\nYou can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`fifo_clr::W`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@fifo_clr`]
module"]
#[doc(alias = "FIFO_CLR")]
pub type FifoClr = crate::Reg<fifo_clr::FifoClrSpec>;
#[doc = "Clear FIFO Register"]
pub mod fifo_clr;
#[doc = "TMCONFIG (rw) register accessor: Timing Config Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`tmconfig::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`tmconfig::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@tmconfig`]
#[doc = "TMCONFIG (rw) register accessor: Timing Config Register\n\nYou can [`read`](crate::Reg::read) this register and get [`tmconfig::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`tmconfig::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@tmconfig`]
module"]
#[doc(alias = "TMCONFIG")]
pub type Tmconfig = crate::Reg<tmconfig::TmconfigSpec>;
#[doc = "Timing Config Register"]
pub mod tmconfig;
#[doc = "CLKTOLIMIT (rw) register accessor: Clock Low Timeout Limit Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`clktolimit::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`clktolimit::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@clktolimit`]
#[doc = "CLKTOLIMIT (rw) register accessor: Clock Low Timeout Limit Register\n\nYou can [`read`](crate::Reg::read) this register and get [`clktolimit::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`clktolimit::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@clktolimit`]
module"]
#[doc(alias = "CLKTOLIMIT")]
pub type Clktolimit = crate::Reg<clktolimit::ClktolimitSpec>;
#[doc = "Clock Low Timeout Limit Register"]
pub mod clktolimit;
#[doc = "S0_CTRL (rw) register accessor: Slave Control Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_ctrl::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_ctrl::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_ctrl`]
#[doc = "S0_CTRL (rw) register accessor: Slave Control Register\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_ctrl::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_ctrl::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_ctrl`]
module"]
#[doc(alias = "S0_CTRL")]
pub type S0Ctrl = crate::Reg<s0_ctrl::S0CtrlSpec>;
#[doc = "Slave Control Register"]
pub mod s0_ctrl;
#[doc = "S0_MAXWORDS (rw) register accessor: Slave MaxWords Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_maxwords::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_maxwords::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_maxwords`]
#[doc = "S0_MAXWORDS (rw) register accessor: Slave MaxWords Register\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_maxwords::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_maxwords::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_maxwords`]
module"]
#[doc(alias = "S0_MAXWORDS")]
pub type S0Maxwords = crate::Reg<s0_maxwords::S0MaxwordsSpec>;
#[doc = "Slave MaxWords Register"]
pub mod s0_maxwords;
#[doc = "S0_ADDRESS (rw) register accessor: Slave I2C Address Value\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_address::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_address::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_address`]
#[doc = "S0_ADDRESS (rw) register accessor: Slave I2C Address Value\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_address::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_address::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_address`]
module"]
#[doc(alias = "S0_ADDRESS")]
pub type S0Address = crate::Reg<s0_address::S0AddressSpec>;
#[doc = "Slave I2C Address Value"]
pub mod s0_address;
#[doc = "S0_ADDRESSMASK (rw) register accessor: Slave I2C Address Mask value\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_addressmask::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_addressmask::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_addressmask`]
#[doc = "S0_ADDRESSMASK (rw) register accessor: Slave I2C Address Mask value\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_addressmask::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_addressmask::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_addressmask`]
module"]
#[doc(alias = "S0_ADDRESSMASK")]
pub type S0Addressmask = crate::Reg<s0_addressmask::S0AddressmaskSpec>;
#[doc = "Slave I2C Address Mask value"]
pub mod s0_addressmask;
#[doc = "S0_DATA (rw) register accessor: Slave Data Input/Output\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_data::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_data::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_data`]
#[doc = "S0_DATA (rw) register accessor: Slave Data Input/Output\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_data::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_data::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_data`]
module"]
#[doc(alias = "S0_DATA")]
pub type S0Data = crate::Reg<s0_data::S0DataSpec>;
#[doc = "Slave Data Input/Output"]
pub mod s0_data;
#[doc = "S0_LASTADDRESS (r) register accessor: Slave I2C Last Address value\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_lastaddress::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_lastaddress`]
#[doc = "S0_LASTADDRESS (r) register accessor: Slave I2C Last Address value\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_lastaddress::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_lastaddress`]
module"]
#[doc(alias = "S0_LASTADDRESS")]
pub type S0Lastaddress = crate::Reg<s0_lastaddress::S0LastaddressSpec>;
#[doc = "Slave I2C Last Address value"]
pub mod s0_lastaddress;
#[doc = "S0_STATUS (r) register accessor: Slave I2C Controller Status Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_status::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_status`]
#[doc = "S0_STATUS (r) register accessor: Slave I2C Controller Status Register\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_status::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_status`]
module"]
#[doc(alias = "S0_STATUS")]
pub type S0Status = crate::Reg<s0_status::S0StatusSpec>;
#[doc = "Slave I2C Controller Status Register"]
pub mod s0_status;
#[doc = "S0_STATE (r) register accessor: Internal STATE of I2C Slave Controller\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_state::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_state`]
#[doc = "S0_STATE (r) register accessor: Internal STATE of I2C Slave Controller\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_state::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_state`]
module"]
#[doc(alias = "S0_STATE")]
pub type S0State = crate::Reg<s0_state::S0StateSpec>;
#[doc = "Internal STATE of I2C Slave Controller"]
pub mod s0_state;
#[doc = "S0_TXCOUNT (r) register accessor: Slave TX Count Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_txcount::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_txcount`]
#[doc = "S0_TXCOUNT (r) register accessor: Slave TX Count Register\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_txcount::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_txcount`]
module"]
#[doc(alias = "S0_TXCOUNT")]
pub type S0Txcount = crate::Reg<s0_txcount::S0TxcountSpec>;
#[doc = "Slave TX Count Register"]
pub mod s0_txcount;
#[doc = "S0_RXCOUNT (r) register accessor: Slave RX Count Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_rxcount::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_rxcount`]
#[doc = "S0_RXCOUNT (r) register accessor: Slave RX Count Register\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_rxcount::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_rxcount`]
module"]
#[doc(alias = "S0_RXCOUNT")]
pub type S0Rxcount = crate::Reg<s0_rxcount::S0RxcountSpec>;
#[doc = "Slave RX Count Register"]
pub mod s0_rxcount;
#[doc = "S0_IRQ_ENB (rw) register accessor: Slave Interrupt Enable Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_irq_enb::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_irq_enb::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_irq_enb`]
#[doc = "S0_IRQ_ENB (rw) register accessor: Slave Interrupt Enable Register\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_irq_enb::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_irq_enb::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_irq_enb`]
module"]
#[doc(alias = "S0_IRQ_ENB")]
pub type S0IrqEnb = crate::Reg<s0_irq_enb::S0IrqEnbSpec>;
@ -414,37 +414,37 @@ pub use s0_irq_enb as s0_irq_clr;
pub use S0IrqEnb as S0IrqRaw;
pub use S0IrqEnb as S0IrqEnd;
pub use S0IrqEnb as S0IrqClr;
#[doc = "S0_RXFIFOIRQTRG (rw) register accessor: Slave Rx FIFO IRQ Trigger Level\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_rxfifoirqtrg::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_rxfifoirqtrg::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_rxfifoirqtrg`]
#[doc = "S0_RXFIFOIRQTRG (rw) register accessor: Slave Rx FIFO IRQ Trigger Level\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_rxfifoirqtrg::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_rxfifoirqtrg::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_rxfifoirqtrg`]
module"]
#[doc(alias = "S0_RXFIFOIRQTRG")]
pub type S0Rxfifoirqtrg = crate::Reg<s0_rxfifoirqtrg::S0RxfifoirqtrgSpec>;
#[doc = "Slave Rx FIFO IRQ Trigger Level"]
pub mod s0_rxfifoirqtrg;
#[doc = "S0_TXFIFOIRQTRG (rw) register accessor: Slave Tx FIFO IRQ Trigger Level\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_txfifoirqtrg::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_txfifoirqtrg::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_txfifoirqtrg`]
#[doc = "S0_TXFIFOIRQTRG (rw) register accessor: Slave Tx FIFO IRQ Trigger Level\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_txfifoirqtrg::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_txfifoirqtrg::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_txfifoirqtrg`]
module"]
#[doc(alias = "S0_TXFIFOIRQTRG")]
pub type S0Txfifoirqtrg = crate::Reg<s0_txfifoirqtrg::S0TxfifoirqtrgSpec>;
#[doc = "Slave Tx FIFO IRQ Trigger Level"]
pub mod s0_txfifoirqtrg;
#[doc = "S0_FIFO_CLR (w) register accessor: Slave Clear FIFO Register\n\nYou can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_fifo_clr::W`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_fifo_clr`]
#[doc = "S0_FIFO_CLR (w) register accessor: Slave Clear FIFO Register\n\nYou can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_fifo_clr::W`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_fifo_clr`]
module"]
#[doc(alias = "S0_FIFO_CLR")]
pub type S0FifoClr = crate::Reg<s0_fifo_clr::S0FifoClrSpec>;
#[doc = "Slave Clear FIFO Register"]
pub mod s0_fifo_clr;
#[doc = "S0_ADDRESSB (rw) register accessor: Slave I2C Address B Value\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_addressb::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_addressb::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_addressb`]
#[doc = "S0_ADDRESSB (rw) register accessor: Slave I2C Address B Value\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_addressb::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_addressb::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_addressb`]
module"]
#[doc(alias = "S0_ADDRESSB")]
pub type S0Addressb = crate::Reg<s0_addressb::S0AddressbSpec>;
#[doc = "Slave I2C Address B Value"]
pub mod s0_addressb;
#[doc = "S0_ADDRESSMASKB (rw) register accessor: Slave I2C Address B Mask value\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_addressmaskb::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_addressmaskb::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_addressmaskb`]
#[doc = "S0_ADDRESSMASKB (rw) register accessor: Slave I2C Address B Mask value\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_addressmaskb::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_addressmaskb::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@s0_addressmaskb`]
module"]
#[doc(alias = "S0_ADDRESSMASKB")]
pub type S0Addressmaskb = crate::Reg<s0_addressmaskb::S0AddressmaskbSpec>;
#[doc = "Slave I2C Address B Mask value"]
pub mod s0_addressmaskb;
#[doc = "PERID (r) register accessor: Peripheral ID Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`perid::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@perid`]
#[doc = "PERID (r) register accessor: Peripheral ID Register\n\nYou can [`read`](crate::Reg::read) this register and get [`perid::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@perid`]
module"]
#[doc(alias = "PERID")]
pub type Perid = crate::Reg<perid::PeridSpec>;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "I2C Address value\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`address::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`address::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "I2C Address value\n\nYou can [`read`](crate::Reg::read) this register and get [`address::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`address::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct AddressSpec;
impl crate::RegisterSpec for AddressSpec {
type Ux = u32;

View File

@ -25,18 +25,16 @@ impl R {
impl W {
#[doc = "Bits 0:30 - Enable FastMode"]
#[inline(always)]
#[must_use]
pub fn value(&mut self) -> ValueW<ClkscaleSpec> {
ValueW::new(self, 0)
}
#[doc = "Bit 31 - Enable FastMode"]
#[inline(always)]
#[must_use]
pub fn fastmode(&mut self) -> FastmodeW<ClkscaleSpec> {
FastmodeW::new(self, 31)
}
}
#[doc = "Clock Scale divide value\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`clkscale::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`clkscale::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Clock Scale divide value\n\nYou can [`read`](crate::Reg::read) this register and get [`clkscale::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`clkscale::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct ClkscaleSpec;
impl crate::RegisterSpec for ClkscaleSpec {
type Ux = u32;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "Clock Low Timeout Limit Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`clktolimit::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`clktolimit::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Clock Low Timeout Limit Register\n\nYou can [`read`](crate::Reg::read) this register and get [`clktolimit::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`clktolimit::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct ClktolimitSpec;
impl crate::RegisterSpec for ClktolimitSpec {
type Ux = u32;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "Command Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`cmd::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`cmd::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Command Register\n\nYou can [`read`](crate::Reg::read) this register and get [`cmd::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`cmd::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct CmdSpec;
impl crate::RegisterSpec for CmdSpec {
type Ux = u32;

View File

@ -88,60 +88,51 @@ impl R {
impl W {
#[doc = "Bit 0 - I2C CLK Enabled"]
#[inline(always)]
#[must_use]
pub fn clkenabled(&mut self) -> ClkenabledW<CtrlSpec> {
ClkenabledW::new(self, 0)
}
#[doc = "Bit 1 - I2C Activated"]
#[inline(always)]
#[must_use]
pub fn enabled(&mut self) -> EnabledW<CtrlSpec> {
EnabledW::new(self, 1)
}
#[doc = "Bit 2 - I2C Active"]
#[inline(always)]
#[must_use]
pub fn enable(&mut self) -> EnableW<CtrlSpec> {
EnableW::new(self, 2)
}
#[doc = "Bit 3 - TX FIFIO Empty Mode"]
#[inline(always)]
#[must_use]
pub fn txfemd(&mut self) -> TxfemdW<CtrlSpec> {
TxfemdW::new(self, 3)
}
#[doc = "Bit 4 - RX FIFO Full Mode"]
#[inline(always)]
#[must_use]
pub fn rxffmd(&mut self) -> RxffmdW<CtrlSpec> {
RxffmdW::new(self, 4)
}
#[doc = "Bit 5 - Enable Input Analog Glitch Filter"]
#[inline(always)]
#[must_use]
pub fn algfilter(&mut self) -> AlgfilterW<CtrlSpec> {
AlgfilterW::new(self, 5)
}
#[doc = "Bit 6 - Enable Input Digital Glitch Filter"]
#[inline(always)]
#[must_use]
pub fn dlgfilter(&mut self) -> DlgfilterW<CtrlSpec> {
DlgfilterW::new(self, 6)
}
#[doc = "Bit 8 - Enable LoopBack Mode"]
#[inline(always)]
#[must_use]
pub fn loopback(&mut self) -> LoopbackW<CtrlSpec> {
LoopbackW::new(self, 8)
}
#[doc = "Bit 9 - Enable Timing Config Register"]
#[inline(always)]
#[must_use]
pub fn tmconfigenb(&mut self) -> TmconfigenbW<CtrlSpec> {
TmconfigenbW::new(self, 9)
}
}
#[doc = "Control Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`ctrl::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`ctrl::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Control Register\n\nYou can [`read`](crate::Reg::read) this register and get [`ctrl::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`ctrl::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct CtrlSpec;
impl crate::RegisterSpec for CtrlSpec {
type Ux = u32;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "Data Input/Output\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`data::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`data::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Data Input/Output\n\nYou can [`read`](crate::Reg::read) this register and get [`data::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`data::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct DataSpec;
impl crate::RegisterSpec for DataSpec {
type Ux = u32;

View File

@ -7,18 +7,16 @@ pub type TxfifoW<'a, REG> = crate::BitWriter<'a, REG>;
impl W {
#[doc = "Bit 0 - Clear Rx FIFO"]
#[inline(always)]
#[must_use]
pub fn rxfifo(&mut self) -> RxfifoW<FifoClrSpec> {
RxfifoW::new(self, 0)
}
#[doc = "Bit 1 - Clear Tx FIFO"]
#[inline(always)]
#[must_use]
pub fn txfifo(&mut self) -> TxfifoW<FifoClrSpec> {
TxfifoW::new(self, 1)
}
}
#[doc = "Clear FIFO Register\n\nYou can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`fifo_clr::W`](W). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Clear FIFO Register\n\nYou can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`fifo_clr::W`](W). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct FifoClrSpec;
impl crate::RegisterSpec for FifoClrSpec {
type Ux = u32;

View File

@ -133,90 +133,76 @@ impl R {
impl W {
#[doc = "Bit 0 - I2C Bus is Idle"]
#[inline(always)]
#[must_use]
pub fn i2cidle(&mut self) -> I2cidleW<IrqEnbSpec> {
I2cidleW::new(self, 0)
}
#[doc = "Bit 1 - Controller is Idle"]
#[inline(always)]
#[must_use]
pub fn idle(&mut self) -> IdleW<IrqEnbSpec> {
IdleW::new(self, 1)
}
#[doc = "Bit 2 - Controller is Waiting"]
#[inline(always)]
#[must_use]
pub fn waiting(&mut self) -> WaitingW<IrqEnbSpec> {
WaitingW::new(self, 2)
}
#[doc = "Bit 3 - Controller is Stalled"]
#[inline(always)]
#[must_use]
pub fn stalled(&mut self) -> StalledW<IrqEnbSpec> {
StalledW::new(self, 3)
}
#[doc = "Bit 4 - I2C Arbitration was lost"]
#[inline(always)]
#[must_use]
pub fn arblost(&mut self) -> ArblostW<IrqEnbSpec> {
ArblostW::new(self, 4)
}
#[doc = "Bit 5 - I2C Address was not Acknowledged"]
#[inline(always)]
#[must_use]
pub fn nackaddr(&mut self) -> NackaddrW<IrqEnbSpec> {
NackaddrW::new(self, 5)
}
#[doc = "Bit 6 - I2C Data was not Acknowledged"]
#[inline(always)]
#[must_use]
pub fn nackdata(&mut self) -> NackdataW<IrqEnbSpec> {
NackdataW::new(self, 6)
}
#[doc = "Bit 7 - I2C Clock Low Timeout"]
#[inline(always)]
#[must_use]
pub fn clkloto(&mut self) -> ClklotoW<IrqEnbSpec> {
ClklotoW::new(self, 7)
}
#[doc = "Bit 10 - TX FIFO Overflowed"]
#[inline(always)]
#[must_use]
pub fn txoverflow(&mut self) -> TxoverflowW<IrqEnbSpec> {
TxoverflowW::new(self, 10)
}
#[doc = "Bit 11 - TX FIFO Overflowed"]
#[inline(always)]
#[must_use]
pub fn rxoverflow(&mut self) -> RxoverflowW<IrqEnbSpec> {
RxoverflowW::new(self, 11)
}
#[doc = "Bit 12 - TX FIFO Ready"]
#[inline(always)]
#[must_use]
pub fn txready(&mut self) -> TxreadyW<IrqEnbSpec> {
TxreadyW::new(self, 12)
}
#[doc = "Bit 13 - RX FIFO Ready"]
#[inline(always)]
#[must_use]
pub fn rxready(&mut self) -> RxreadyW<IrqEnbSpec> {
RxreadyW::new(self, 13)
}
#[doc = "Bit 14 - TX FIFO Empty"]
#[inline(always)]
#[must_use]
pub fn txempty(&mut self) -> TxemptyW<IrqEnbSpec> {
TxemptyW::new(self, 14)
}
#[doc = "Bit 15 - RX FIFO Full"]
#[inline(always)]
#[must_use]
pub fn rxfull(&mut self) -> RxfullW<IrqEnbSpec> {
RxfullW::new(self, 15)
}
}
#[doc = "Interrupt Enable Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`irq_enb::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`irq_enb::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Interrupt Enable Register\n\nYou can [`read`](crate::Reg::read) this register and get [`irq_enb::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`irq_enb::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct IrqEnbSpec;
impl crate::RegisterSpec for IrqEnbSpec {
type Ux = u32;

View File

@ -5,7 +5,7 @@ impl core::fmt::Debug for R {
write!(f, "{}", self.bits())
}
}
#[doc = "Peripheral ID Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`perid::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Peripheral ID Register\n\nYou can [`read`](crate::Reg::read) this register and get [`perid::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct PeridSpec;
impl crate::RegisterSpec for PeridSpec {
type Ux = u32;

View File

@ -5,7 +5,7 @@ impl core::fmt::Debug for R {
write!(f, "{}", self.bits())
}
}
#[doc = "RX Count Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`rxcount::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "RX Count Register\n\nYou can [`read`](crate::Reg::read) this register and get [`rxcount::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct RxcountSpec;
impl crate::RegisterSpec for RxcountSpec {
type Ux = u32;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "Rx FIFO IRQ Trigger Level\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`rxfifoirqtrg::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`rxfifoirqtrg::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Rx FIFO IRQ Trigger Level\n\nYou can [`read`](crate::Reg::read) this register and get [`rxfifoirqtrg::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`rxfifoirqtrg::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct RxfifoirqtrgSpec;
impl crate::RegisterSpec for RxfifoirqtrgSpec {
type Ux = u32;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "Slave I2C Address Value\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_address::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_address::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Slave I2C Address Value\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_address::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_address::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct S0AddressSpec;
impl crate::RegisterSpec for S0AddressSpec {
type Ux = u32;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "Slave I2C Address B Value\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_addressb::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_addressb::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Slave I2C Address B Value\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_addressb::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_addressb::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct S0AddressbSpec;
impl crate::RegisterSpec for S0AddressbSpec {
type Ux = u32;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "Slave I2C Address Mask value\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_addressmask::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_addressmask::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Slave I2C Address Mask value\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_addressmask::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_addressmask::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct S0AddressmaskSpec;
impl crate::RegisterSpec for S0AddressmaskSpec {
type Ux = u32;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "Slave I2C Address B Mask value\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_addressmaskb::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_addressmaskb::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Slave I2C Address B Mask value\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_addressmaskb::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_addressmaskb::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct S0AddressmaskbSpec;
impl crate::RegisterSpec for S0AddressmaskbSpec {
type Ux = u32;

View File

@ -52,36 +52,31 @@ impl R {
impl W {
#[doc = "Bit 0 - I2C Enabled"]
#[inline(always)]
#[must_use]
pub fn clkenabled(&mut self) -> ClkenabledW<S0CtrlSpec> {
ClkenabledW::new(self, 0)
}
#[doc = "Bit 1 - I2C Activated"]
#[inline(always)]
#[must_use]
pub fn enabled(&mut self) -> EnabledW<S0CtrlSpec> {
EnabledW::new(self, 1)
}
#[doc = "Bit 2 - I2C Active"]
#[inline(always)]
#[must_use]
pub fn enable(&mut self) -> EnableW<S0CtrlSpec> {
EnableW::new(self, 2)
}
#[doc = "Bit 3 - TX FIFIO Empty Mode"]
#[inline(always)]
#[must_use]
pub fn txfemd(&mut self) -> TxfemdW<S0CtrlSpec> {
TxfemdW::new(self, 3)
}
#[doc = "Bit 4 - RX FIFO Full Mode"]
#[inline(always)]
#[must_use]
pub fn rxffmd(&mut self) -> RxffmdW<S0CtrlSpec> {
RxffmdW::new(self, 4)
}
}
#[doc = "Slave Control Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_ctrl::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_ctrl::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Slave Control Register\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_ctrl::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_ctrl::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct S0CtrlSpec;
impl crate::RegisterSpec for S0CtrlSpec {
type Ux = u32;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "Slave Data Input/Output\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_data::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_data::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Slave Data Input/Output\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_data::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_data::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct S0DataSpec;
impl crate::RegisterSpec for S0DataSpec {
type Ux = u32;

View File

@ -7,18 +7,16 @@ pub type TxfifoW<'a, REG> = crate::BitWriter<'a, REG>;
impl W {
#[doc = "Bit 0 - Clear Rx FIFO"]
#[inline(always)]
#[must_use]
pub fn rxfifo(&mut self) -> RxfifoW<S0FifoClrSpec> {
RxfifoW::new(self, 0)
}
#[doc = "Bit 1 - Clear Tx FIFO"]
#[inline(always)]
#[must_use]
pub fn txfifo(&mut self) -> TxfifoW<S0FifoClrSpec> {
TxfifoW::new(self, 1)
}
}
#[doc = "Slave Clear FIFO Register\n\nYou can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_fifo_clr::W`](W). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Slave Clear FIFO Register\n\nYou can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_fifo_clr::W`](W). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct S0FifoClrSpec;
impl crate::RegisterSpec for S0FifoClrSpec {
type Ux = u32;

View File

@ -151,102 +151,86 @@ impl R {
impl W {
#[doc = "Bit 0 - Controller Complted a Transaction"]
#[inline(always)]
#[must_use]
pub fn completed(&mut self) -> CompletedW<S0IrqEnbSpec> {
CompletedW::new(self, 0)
}
#[doc = "Bit 1 - Controller is Idle"]
#[inline(always)]
#[must_use]
pub fn idle(&mut self) -> IdleW<S0IrqEnbSpec> {
IdleW::new(self, 1)
}
#[doc = "Bit 2 - Controller is Waiting"]
#[inline(always)]
#[must_use]
pub fn waiting(&mut self) -> WaitingW<S0IrqEnbSpec> {
WaitingW::new(self, 2)
}
#[doc = "Bit 3 - Controller is Tx Stalled"]
#[inline(always)]
#[must_use]
pub fn txstalled(&mut self) -> TxstalledW<S0IrqEnbSpec> {
TxstalledW::new(self, 3)
}
#[doc = "Bit 4 - Controller is Rx Stalled"]
#[inline(always)]
#[must_use]
pub fn rxstalled(&mut self) -> RxstalledW<S0IrqEnbSpec> {
RxstalledW::new(self, 4)
}
#[doc = "Bit 5 - I2C Address Match"]
#[inline(always)]
#[must_use]
pub fn addressmatch(&mut self) -> AddressmatchW<S0IrqEnbSpec> {
AddressmatchW::new(self, 5)
}
#[doc = "Bit 6 - I2C Data was not Acknowledged"]
#[inline(always)]
#[must_use]
pub fn nackdata(&mut self) -> NackdataW<S0IrqEnbSpec> {
NackdataW::new(self, 6)
}
#[doc = "Bit 7 - Pending Data is first Byte following Address"]
#[inline(always)]
#[must_use]
pub fn rxdatafirst(&mut self) -> RxdatafirstW<S0IrqEnbSpec> {
RxdatafirstW::new(self, 7)
}
#[doc = "Bit 8 - I2C Start Condition"]
#[inline(always)]
#[must_use]
pub fn i2c_start(&mut self) -> I2cStartW<S0IrqEnbSpec> {
I2cStartW::new(self, 8)
}
#[doc = "Bit 9 - I2C Stop Condition"]
#[inline(always)]
#[must_use]
pub fn i2c_stop(&mut self) -> I2cStopW<S0IrqEnbSpec> {
I2cStopW::new(self, 9)
}
#[doc = "Bit 10 - TX FIFO Underflowed"]
#[inline(always)]
#[must_use]
pub fn txunderflow(&mut self) -> TxunderflowW<S0IrqEnbSpec> {
TxunderflowW::new(self, 10)
}
#[doc = "Bit 11 - TX FIFO Overflowed"]
#[inline(always)]
#[must_use]
pub fn rxoverflow(&mut self) -> RxoverflowW<S0IrqEnbSpec> {
RxoverflowW::new(self, 11)
}
#[doc = "Bit 12 - TX FIFO Ready"]
#[inline(always)]
#[must_use]
pub fn txready(&mut self) -> TxreadyW<S0IrqEnbSpec> {
TxreadyW::new(self, 12)
}
#[doc = "Bit 13 - RX FIFO Ready"]
#[inline(always)]
#[must_use]
pub fn rxready(&mut self) -> RxreadyW<S0IrqEnbSpec> {
RxreadyW::new(self, 13)
}
#[doc = "Bit 14 - TX FIFO Empty"]
#[inline(always)]
#[must_use]
pub fn txempty(&mut self) -> TxemptyW<S0IrqEnbSpec> {
TxemptyW::new(self, 14)
}
#[doc = "Bit 15 - RX FIFO Full"]
#[inline(always)]
#[must_use]
pub fn rxfull(&mut self) -> RxfullW<S0IrqEnbSpec> {
RxfullW::new(self, 15)
}
}
#[doc = "Slave Interrupt Enable Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_irq_enb::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_irq_enb::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Slave Interrupt Enable Register\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_irq_enb::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_irq_enb::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct S0IrqEnbSpec;
impl crate::RegisterSpec for S0IrqEnbSpec {
type Ux = u32;

View File

@ -5,7 +5,7 @@ impl core::fmt::Debug for R {
write!(f, "{}", self.bits())
}
}
#[doc = "Slave I2C Last Address value\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_lastaddress::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Slave I2C Last Address value\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_lastaddress::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct S0LastaddressSpec;
impl crate::RegisterSpec for S0LastaddressSpec {
type Ux = u32;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "Slave MaxWords Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_maxwords::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_maxwords::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Slave MaxWords Register\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_maxwords::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_maxwords::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct S0MaxwordsSpec;
impl crate::RegisterSpec for S0MaxwordsSpec {
type Ux = u32;

View File

@ -5,7 +5,7 @@ impl core::fmt::Debug for R {
write!(f, "{}", self.bits())
}
}
#[doc = "Slave RX Count Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_rxcount::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Slave RX Count Register\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_rxcount::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct S0RxcountSpec;
impl crate::RegisterSpec for S0RxcountSpec {
type Ux = u32;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "Slave Rx FIFO IRQ Trigger Level\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_rxfifoirqtrg::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_rxfifoirqtrg::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Slave Rx FIFO IRQ Trigger Level\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_rxfifoirqtrg::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_rxfifoirqtrg::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct S0RxfifoirqtrgSpec;
impl crate::RegisterSpec for S0RxfifoirqtrgSpec {
type Ux = u32;

View File

@ -5,7 +5,7 @@ impl core::fmt::Debug for R {
write!(f, "{}", self.bits())
}
}
#[doc = "Internal STATE of I2C Slave Controller\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_state::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Internal STATE of I2C Slave Controller\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_state::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct S0StateSpec;
impl crate::RegisterSpec for S0StateSpec {
type Ux = u32;

View File

@ -121,7 +121,7 @@ impl R {
RawSclR::new(((self.bits >> 31) & 1) != 0)
}
}
#[doc = "Slave I2C Controller Status Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_status::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Slave I2C Controller Status Register\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_status::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct S0StatusSpec;
impl crate::RegisterSpec for S0StatusSpec {
type Ux = u32;

View File

@ -5,7 +5,7 @@ impl core::fmt::Debug for R {
write!(f, "{}", self.bits())
}
}
#[doc = "Slave TX Count Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_txcount::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Slave TX Count Register\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_txcount::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct S0TxcountSpec;
impl crate::RegisterSpec for S0TxcountSpec {
type Ux = u32;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "Slave Tx FIFO IRQ Trigger Level\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`s0_txfifoirqtrg::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`s0_txfifoirqtrg::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Slave Tx FIFO IRQ Trigger Level\n\nYou can [`read`](crate::Reg::read) this register and get [`s0_txfifoirqtrg::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`s0_txfifoirqtrg::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct S0TxfifoirqtrgSpec;
impl crate::RegisterSpec for S0TxfifoirqtrgSpec {
type Ux = u32;

View File

@ -5,7 +5,7 @@ impl core::fmt::Debug for R {
write!(f, "{}", self.bits())
}
}
#[doc = "Internal STATE of I2C Master Controller\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`state::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Internal STATE of I2C Master Controller\n\nYou can [`read`](crate::Reg::read) this register and get [`state::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct StateSpec;
impl crate::RegisterSpec for StateSpec {
type Ux = u32;

View File

@ -107,7 +107,7 @@ impl R {
RawSclR::new(((self.bits >> 31) & 1) != 0)
}
}
#[doc = "I2C Controller Status Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`status::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "I2C Controller Status Register\n\nYou can [`read`](crate::Reg::read) this register and get [`status::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct StatusSpec;
impl crate::RegisterSpec for StatusSpec {
type Ux = u32;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "Timing Config Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`tmconfig::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`tmconfig::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Timing Config Register\n\nYou can [`read`](crate::Reg::read) this register and get [`tmconfig::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`tmconfig::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct TmconfigSpec;
impl crate::RegisterSpec for TmconfigSpec {
type Ux = u32;

View File

@ -5,7 +5,7 @@ impl core::fmt::Debug for R {
write!(f, "{}", self.bits())
}
}
#[doc = "TX Count Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`txcount::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "TX Count Register\n\nYou can [`read`](crate::Reg::read) this register and get [`txcount::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct TxcountSpec;
impl crate::RegisterSpec for TxcountSpec {
type Ux = u32;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "Tx FIFO IRQ Trigger Level\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`txfifoirqtrg::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`txfifoirqtrg::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Tx FIFO IRQ Trigger Level\n\nYou can [`read`](crate::Reg::read) this register and get [`txfifoirqtrg::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`txfifoirqtrg::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct TxfifoirqtrgSpec;
impl crate::RegisterSpec for TxfifoirqtrgSpec {
type Ux = u32;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "Word Count value\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`words::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`words::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Word Count value\n\nYou can [`read`](crate::Reg::read) this register and get [`words::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`words::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct WordsSpec;
impl crate::RegisterSpec for WordsSpec {
type Ux = u32;

View File

@ -35,7 +35,7 @@ impl RegisterBlock {
&self.perid
}
}
#[doc = "PORTA (rw) register accessor: PORTA Pin Configuration Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`porta::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`porta::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@porta`]
#[doc = "PORTA (rw) register accessor: PORTA Pin Configuration Register\n\nYou can [`read`](crate::Reg::read) this register and get [`porta::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`porta::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@porta`]
module"]
#[doc(alias = "PORTA")]
pub type Porta = crate::Reg<porta::PortaSpec>;
@ -43,7 +43,7 @@ pub type Porta = crate::Reg<porta::PortaSpec>;
pub mod porta;
pub use porta as portb;
pub use Porta as Portb;
#[doc = "PERID (r) register accessor: Peripheral ID Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`perid::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@perid`]
#[doc = "PERID (r) register accessor: Peripheral ID Register\n\nYou can [`read`](crate::Reg::read) this register and get [`perid::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@perid`]
module"]
#[doc(alias = "PERID")]
pub type Perid = crate::Reg<perid::PeridSpec>;

View File

@ -5,7 +5,7 @@ impl core::fmt::Debug for R {
write!(f, "{}", self.bits())
}
}
#[doc = "Peripheral ID Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`perid::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Peripheral ID Register\n\nYou can [`read`](crate::Reg::read) this register and get [`perid::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct PeridSpec;
impl crate::RegisterSpec for PeridSpec {
type Ux = u32;

View File

@ -214,72 +214,61 @@ impl R {
impl W {
#[doc = "Bits 0:2 - Input Filter Selectoin"]
#[inline(always)]
#[must_use]
pub fn flttype(&mut self) -> FlttypeW<PortaSpec> {
FlttypeW::new(self, 0)
}
#[doc = "Bits 3:5 - Input Filter Clock Selection"]
#[inline(always)]
#[must_use]
pub fn fltclk(&mut self) -> FltclkW<PortaSpec> {
FltclkW::new(self, 3)
}
#[doc = "Bit 6 - Input Invert Selection"]
#[inline(always)]
#[must_use]
pub fn invinp(&mut self) -> InvinpW<PortaSpec> {
InvinpW::new(self, 6)
}
#[doc = "Bit 7 - Input Enable While Output enabled"]
#[inline(always)]
#[must_use]
pub fn iewo(&mut self) -> IewoW<PortaSpec> {
IewoW::new(self, 7)
}
#[doc = "Bit 8 - Output Open Drain Mode"]
#[inline(always)]
#[must_use]
pub fn opendrn(&mut self) -> OpendrnW<PortaSpec> {
OpendrnW::new(self, 8)
}
#[doc = "Bit 9 - Output Invert Selection"]
#[inline(always)]
#[must_use]
pub fn invout(&mut self) -> InvoutW<PortaSpec> {
InvoutW::new(self, 9)
}
#[doc = "Bit 10 - Internal Pull up/down level"]
#[inline(always)]
#[must_use]
pub fn plevel(&mut self) -> PlevelW<PortaSpec> {
PlevelW::new(self, 10)
}
#[doc = "Bit 11 - Enable Internal Pull up/down"]
#[inline(always)]
#[must_use]
pub fn pen(&mut self) -> PenW<PortaSpec> {
PenW::new(self, 11)
}
#[doc = "Bit 12 - Enable Pull when output active"]
#[inline(always)]
#[must_use]
pub fn pwoa(&mut self) -> PwoaW<PortaSpec> {
PwoaW::new(self, 12)
}
#[doc = "Bits 13:15 - Pin Function Selection"]
#[inline(always)]
#[must_use]
pub fn funsel(&mut self) -> FunselW<PortaSpec> {
FunselW::new(self, 13)
}
#[doc = "Bit 16 - IO Pin Disable"]
#[inline(always)]
#[must_use]
pub fn iodis(&mut self) -> IodisW<PortaSpec> {
IodisW::new(self, 16)
}
}
#[doc = "PORTA Pin Configuration Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`porta::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`porta::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "PORTA Pin Configuration Register\n\nYou can [`read`](crate::Reg::read) this register and get [`porta::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`porta::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct PortaSpec;
impl crate::RegisterSpec for PortaSpec {
type Ux = u32;

View File

@ -169,7 +169,7 @@ impl RegisterBlock {
&self.perid
}
}
#[doc = "INT_RAM_SBE (rw) register accessor: Internal Memory RAM SBE Interrupt Redirect Selection\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`int_ram_sbe::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`int_ram_sbe::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@int_ram_sbe`]
#[doc = "INT_RAM_SBE (rw) register accessor: Internal Memory RAM SBE Interrupt Redirect Selection\n\nYou can [`read`](crate::Reg::read) this register and get [`int_ram_sbe::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`int_ram_sbe::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@int_ram_sbe`]
module"]
#[doc(alias = "INT_RAM_SBE")]
pub type IntRamSbe = crate::Reg<int_ram_sbe::IntRamSbeSpec>;
@ -197,7 +197,7 @@ pub use IntRamSbe as IntRamMbe;
pub use IntRamSbe as IntRomSbe;
pub use IntRamSbe as IntRomMbe;
pub use IntRamSbe as Txev;
#[doc = "NMI (r) register accessor: NMI Status Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`nmi::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@nmi`]
#[doc = "NMI (r) register accessor: NMI Status Register\n\nYou can [`read`](crate::Reg::read) this register and get [`nmi::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@nmi`]
module"]
#[doc(alias = "NMI")]
pub type Nmi = crate::Reg<nmi::NmiSpec>;
@ -213,7 +213,7 @@ pub use Nmi as Watchdog;
pub use Nmi as Mereset;
pub use Nmi as Edbgrq;
pub use Nmi as Irqs;
#[doc = "PERID (r) register accessor: Peripheral ID Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`perid::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@perid`]
#[doc = "PERID (r) register accessor: Peripheral ID Register\n\nYou can [`read`](crate::Reg::read) this register and get [`perid::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@perid`]
module"]
#[doc(alias = "PERID")]
pub type Perid = crate::Reg<perid::PeridSpec>;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "Internal Memory RAM SBE Interrupt Redirect Selection\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`int_ram_sbe::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`int_ram_sbe::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Internal Memory RAM SBE Interrupt Redirect Selection\n\nYou can [`read`](crate::Reg::read) this register and get [`int_ram_sbe::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`int_ram_sbe::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct IntRamSbeSpec;
impl crate::RegisterSpec for IntRamSbeSpec {
type Ux = u32;

View File

@ -9,7 +9,7 @@ impl R {
ActiveR::new((self.bits & 1) != 0)
}
}
#[doc = "NMI Status Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`nmi::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "NMI Status Register\n\nYou can [`read`](crate::Reg::read) this register and get [`nmi::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct NmiSpec;
impl crate::RegisterSpec for NmiSpec {
type Ux = u32;

View File

@ -5,7 +5,7 @@ impl core::fmt::Debug for R {
write!(f, "{}", self.bits())
}
}
#[doc = "Peripheral ID Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`perid::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Peripheral ID Register\n\nYou can [`read`](crate::Reg::read) this register and get [`perid::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct PeridSpec;
impl crate::RegisterSpec for PeridSpec {
type Ux = u32;

View File

@ -1,10 +1,8 @@
#![doc = "Peripheral access API for VA108XX microcontrollers (generated using svd2rust v0.33.3 ( ))\n\nYou can find an overview of the generated API [here].\n\nAPI features to be included in the [next]
svd2rust release can be generated by cloning the svd2rust [repository], checking out the above commit, and running `cargo doc --open`.\n\n[here]: https://docs.rs/svd2rust/0.33.3/svd2rust/#peripheral-api\n[next]: https://github.com/rust-embedded/svd2rust/blob/master/CHANGELOG.md#unreleased\n[repository]: https://github.com/rust-embedded/svd2rust"]
#![doc = "Peripheral access API for VA108XX microcontrollers (generated using svd2rust v0.35.0 (e10f920 2025-02-12))\n\nYou can find an overview of the generated API [here].\n\nAPI features to be included in the [next]
svd2rust release can be generated by cloning the svd2rust [repository], checking out the above commit, and running `cargo doc --open`.\n\n[here]: https://docs.rs/svd2rust/0.35.0/svd2rust/#peripheral-api\n[next]: https://github.com/rust-embedded/svd2rust/blob/master/CHANGELOG.md#unreleased\n[repository]: https://github.com/rust-embedded/svd2rust"]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![no_std]
// Manually inserted.
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
use core::marker::PhantomData;
use core::ops::Deref;
#[doc = r"Number available in the NVIC for configuring priority"]
@ -1974,117 +1972,43 @@ impl Peripherals {
pub unsafe fn steal() -> Self {
DEVICE_PERIPHERALS = true;
Peripherals {
sysconfig: Sysconfig {
_marker: PhantomData,
},
irqsel: Irqsel {
_marker: PhantomData,
},
ioconfig: Ioconfig {
_marker: PhantomData,
},
utility: Utility {
_marker: PhantomData,
},
porta: Porta {
_marker: PhantomData,
},
portb: Portb {
_marker: PhantomData,
},
tim0: Tim0 {
_marker: PhantomData,
},
tim1: Tim1 {
_marker: PhantomData,
},
tim2: Tim2 {
_marker: PhantomData,
},
tim3: Tim3 {
_marker: PhantomData,
},
tim4: Tim4 {
_marker: PhantomData,
},
tim5: Tim5 {
_marker: PhantomData,
},
tim6: Tim6 {
_marker: PhantomData,
},
tim7: Tim7 {
_marker: PhantomData,
},
tim8: Tim8 {
_marker: PhantomData,
},
tim9: Tim9 {
_marker: PhantomData,
},
tim10: Tim10 {
_marker: PhantomData,
},
tim11: Tim11 {
_marker: PhantomData,
},
tim12: Tim12 {
_marker: PhantomData,
},
tim13: Tim13 {
_marker: PhantomData,
},
tim14: Tim14 {
_marker: PhantomData,
},
tim15: Tim15 {
_marker: PhantomData,
},
tim16: Tim16 {
_marker: PhantomData,
},
tim17: Tim17 {
_marker: PhantomData,
},
tim18: Tim18 {
_marker: PhantomData,
},
tim19: Tim19 {
_marker: PhantomData,
},
tim20: Tim20 {
_marker: PhantomData,
},
tim21: Tim21 {
_marker: PhantomData,
},
tim22: Tim22 {
_marker: PhantomData,
},
tim23: Tim23 {
_marker: PhantomData,
},
uarta: Uarta {
_marker: PhantomData,
},
uartb: Uartb {
_marker: PhantomData,
},
spia: Spia {
_marker: PhantomData,
},
spib: Spib {
_marker: PhantomData,
},
spic: Spic {
_marker: PhantomData,
},
i2ca: I2ca {
_marker: PhantomData,
},
i2cb: I2cb {
_marker: PhantomData,
},
sysconfig: Sysconfig::steal(),
irqsel: Irqsel::steal(),
ioconfig: Ioconfig::steal(),
utility: Utility::steal(),
porta: Porta::steal(),
portb: Portb::steal(),
tim0: Tim0::steal(),
tim1: Tim1::steal(),
tim2: Tim2::steal(),
tim3: Tim3::steal(),
tim4: Tim4::steal(),
tim5: Tim5::steal(),
tim6: Tim6::steal(),
tim7: Tim7::steal(),
tim8: Tim8::steal(),
tim9: Tim9::steal(),
tim10: Tim10::steal(),
tim11: Tim11::steal(),
tim12: Tim12::steal(),
tim13: Tim13::steal(),
tim14: Tim14::steal(),
tim15: Tim15::steal(),
tim16: Tim16::steal(),
tim17: Tim17::steal(),
tim18: Tim18::steal(),
tim19: Tim19::steal(),
tim20: Tim20::steal(),
tim21: Tim21::steal(),
tim22: Tim22::steal(),
tim23: Tim23::steal(),
uarta: Uarta::steal(),
uartb: Uartb::steal(),
spia: Spia::steal(),
spib: Spib::steal(),
spic: Spic::steal(),
i2ca: I2ca::steal(),
i2cb: I2cb::steal(),
}
}
}

View File

@ -1,6 +1,3 @@
// Manually inserted.
#![allow(clippy::identity_op)]
#[repr(C)]
#[doc = "Register block"]
pub struct RegisterBlock {
@ -33,247 +30,246 @@ impl RegisterBlock {
pub const fn datainbyte(&self, n: usize) -> &Datainbyte {
#[allow(clippy::no_effect)]
[(); 4][n];
unsafe { &*(self as *const Self).cast::<u8>().add(0).add(1 * n).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(n).cast() }
}
#[doc = "Iterator for array of:"]
#[doc = "0x00 - Data In Register by Byte"]
#[inline(always)]
pub fn datainbyte_iter(&self) -> impl Iterator<Item = &Datainbyte> {
(0..4)
.map(move |n| unsafe { &*(self as *const Self).cast::<u8>().add(0).add(1 * n).cast() })
(0..4).map(move |n| unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(n).cast() })
}
#[doc = "0x00 - Data In Register"]
#[inline(always)]
pub const fn datain(&self) -> &Datain {
unsafe { &*(self as *const Self).cast::<u8>().add(0).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().cast() }
}
#[doc = "0x04 - Data In Raw Register by Byte"]
#[inline(always)]
pub const fn datainrawbyte0(&self, n: usize) -> &Datainrawbyte {
#[allow(clippy::no_effect)]
[(); 4][n];
unsafe { &*(self as *const Self).cast::<u8>().add(4).add(1 * n).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(4).add(n).cast() }
}
#[doc = "Iterator for array of:"]
#[doc = "0x04 - Data In Raw Register by Byte"]
#[inline(always)]
pub fn datainrawbyte0_iter(&self) -> impl Iterator<Item = &Datainrawbyte> {
(0..4)
.map(move |n| unsafe { &*(self as *const Self).cast::<u8>().add(4).add(1 * n).cast() })
.map(move |n| unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(4).add(n).cast() })
}
#[doc = "0x04 - Data In Raw Register"]
#[inline(always)]
pub const fn datainraw(&self) -> &Datainraw {
unsafe { &*(self as *const Self).cast::<u8>().add(4).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(4).cast() }
}
#[doc = "0x08 - Data Out Register by Byte"]
#[inline(always)]
pub const fn dataoutbyte(&self, n: usize) -> &Dataoutbyte {
#[allow(clippy::no_effect)]
[(); 4][n];
unsafe { &*(self as *const Self).cast::<u8>().add(8).add(1 * n).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(8).add(n).cast() }
}
#[doc = "Iterator for array of:"]
#[doc = "0x08 - Data Out Register by Byte"]
#[inline(always)]
pub fn dataoutbyte_iter(&self) -> impl Iterator<Item = &Dataoutbyte> {
(0..4)
.map(move |n| unsafe { &*(self as *const Self).cast::<u8>().add(8).add(1 * n).cast() })
.map(move |n| unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(8).add(n).cast() })
}
#[doc = "0x08 - Data Out Register"]
#[inline(always)]
pub const fn dataout(&self) -> &Dataout {
unsafe { &*(self as *const Self).cast::<u8>().add(8).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(8).cast() }
}
#[doc = "0x0c - Data Out Register by Byte"]
#[inline(always)]
pub const fn dataoutrawbyte0(&self, n: usize) -> &Dataoutrawbyte {
#[allow(clippy::no_effect)]
[(); 4][n];
unsafe { &*(self as *const Self).cast::<u8>().add(12).add(1 * n).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(12).add(n).cast() }
}
#[doc = "Iterator for array of:"]
#[doc = "0x0c - Data Out Register by Byte"]
#[inline(always)]
pub fn dataoutrawbyte0_iter(&self) -> impl Iterator<Item = &Dataoutrawbyte> {
(0..4)
.map(move |n| unsafe { &*(self as *const Self).cast::<u8>().add(12).add(1 * n).cast() })
.map(move |n| unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(12).add(n).cast() })
}
#[doc = "0x0c - Data Out Register"]
#[inline(always)]
pub const fn dataoutraw(&self) -> &Dataoutraw {
unsafe { &*(self as *const Self).cast::<u8>().add(12).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(12).cast() }
}
#[doc = "0x10 - Set Out Register by Byte"]
#[inline(always)]
pub const fn setoutbyte0(&self, n: usize) -> &Setoutbyte {
#[allow(clippy::no_effect)]
[(); 4][n];
unsafe { &*(self as *const Self).cast::<u8>().add(16).add(1 * n).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(16).add(n).cast() }
}
#[doc = "Iterator for array of:"]
#[doc = "0x10 - Set Out Register by Byte"]
#[inline(always)]
pub fn setoutbyte0_iter(&self) -> impl Iterator<Item = &Setoutbyte> {
(0..4)
.map(move |n| unsafe { &*(self as *const Self).cast::<u8>().add(16).add(1 * n).cast() })
.map(move |n| unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(16).add(n).cast() })
}
#[doc = "0x10 - Set Out Register"]
#[inline(always)]
pub const fn setout(&self) -> &Setout {
unsafe { &*(self as *const Self).cast::<u8>().add(16).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(16).cast() }
}
#[doc = "0x14 - Clear Out Register by Byte"]
#[inline(always)]
pub const fn clroutbyte0(&self, n: usize) -> &Clroutbyte {
#[allow(clippy::no_effect)]
[(); 4][n];
unsafe { &*(self as *const Self).cast::<u8>().add(20).add(1 * n).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(20).add(n).cast() }
}
#[doc = "Iterator for array of:"]
#[doc = "0x14 - Clear Out Register by Byte"]
#[inline(always)]
pub fn clroutbyte0_iter(&self) -> impl Iterator<Item = &Clroutbyte> {
(0..4)
.map(move |n| unsafe { &*(self as *const Self).cast::<u8>().add(20).add(1 * n).cast() })
.map(move |n| unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(20).add(n).cast() })
}
#[doc = "0x14 - Clear Out Register"]
#[inline(always)]
pub const fn clrout(&self) -> &Clrout {
unsafe { &*(self as *const Self).cast::<u8>().add(20).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(20).cast() }
}
#[doc = "0x18 - Toggle Out Register by Byte"]
#[inline(always)]
pub const fn togoutbyte0(&self, n: usize) -> &Togoutbyte {
#[allow(clippy::no_effect)]
[(); 4][n];
unsafe { &*(self as *const Self).cast::<u8>().add(24).add(1 * n).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(24).add(n).cast() }
}
#[doc = "Iterator for array of:"]
#[doc = "0x18 - Toggle Out Register by Byte"]
#[inline(always)]
pub fn togoutbyte0_iter(&self) -> impl Iterator<Item = &Togoutbyte> {
(0..4)
.map(move |n| unsafe { &*(self as *const Self).cast::<u8>().add(24).add(1 * n).cast() })
.map(move |n| unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(24).add(n).cast() })
}
#[doc = "0x18 - Toggle Out Register"]
#[inline(always)]
pub const fn togout(&self) -> &Togout {
unsafe { &*(self as *const Self).cast::<u8>().add(24).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(24).cast() }
}
#[doc = "0x1c - Data Out Register by Byte"]
#[inline(always)]
pub const fn datamaskbyte(&self, n: usize) -> &Datamaskbyte {
#[allow(clippy::no_effect)]
[(); 4][n];
unsafe { &*(self as *const Self).cast::<u8>().add(28).add(1 * n).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(28).add(n).cast() }
}
#[doc = "Iterator for array of:"]
#[doc = "0x1c - Data Out Register by Byte"]
#[inline(always)]
pub fn datamaskbyte_iter(&self) -> impl Iterator<Item = &Datamaskbyte> {
(0..4)
.map(move |n| unsafe { &*(self as *const Self).cast::<u8>().add(28).add(1 * n).cast() })
.map(move |n| unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(28).add(n).cast() })
}
#[doc = "0x1c - Data mask Register"]
#[inline(always)]
pub const fn datamask(&self) -> &Datamask {
unsafe { &*(self as *const Self).cast::<u8>().add(28).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(28).cast() }
}
#[doc = "0x20 - Direction Register by Byte"]
#[inline(always)]
pub const fn dirbyte0(&self, n: usize) -> &Dirbyte {
#[allow(clippy::no_effect)]
[(); 4][n];
unsafe { &*(self as *const Self).cast::<u8>().add(32).add(1 * n).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(32).add(n).cast() }
}
#[doc = "Iterator for array of:"]
#[doc = "0x20 - Direction Register by Byte"]
#[inline(always)]
pub fn dirbyte0_iter(&self) -> impl Iterator<Item = &Dirbyte> {
(0..4)
.map(move |n| unsafe { &*(self as *const Self).cast::<u8>().add(32).add(1 * n).cast() })
.map(move |n| unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(32).add(n).cast() })
}
#[doc = "0x20 - Direction Register (1:Output, 0:Input)"]
#[inline(always)]
pub const fn dir(&self) -> &Dir {
unsafe { &*(self as *const Self).cast::<u8>().add(32).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(32).cast() }
}
#[doc = "0x24 - Pulse Mode Register by Byte"]
#[inline(always)]
pub const fn pulsebyte0(&self, n: usize) -> &Pulsebyte {
#[allow(clippy::no_effect)]
[(); 4][n];
unsafe { &*(self as *const Self).cast::<u8>().add(36).add(1 * n).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(36).add(n).cast() }
}
#[doc = "Iterator for array of:"]
#[doc = "0x24 - Pulse Mode Register by Byte"]
#[inline(always)]
pub fn pulsebyte0_iter(&self) -> impl Iterator<Item = &Pulsebyte> {
(0..4)
.map(move |n| unsafe { &*(self as *const Self).cast::<u8>().add(36).add(1 * n).cast() })
.map(move |n| unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(36).add(n).cast() })
}
#[doc = "0x24 - Pulse Mode Register"]
#[inline(always)]
pub const fn pulse(&self) -> &Pulse {
unsafe { &*(self as *const Self).cast::<u8>().add(36).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(36).cast() }
}
#[doc = "0x28 - Pulse Base Mode Register by Byte"]
#[inline(always)]
pub const fn pulsebasebyte0(&self, n: usize) -> &Pulsebasebyte {
#[allow(clippy::no_effect)]
[(); 4][n];
unsafe { &*(self as *const Self).cast::<u8>().add(40).add(1 * n).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(40).add(n).cast() }
}
#[doc = "Iterator for array of:"]
#[doc = "0x28 - Pulse Base Mode Register by Byte"]
#[inline(always)]
pub fn pulsebasebyte0_iter(&self) -> impl Iterator<Item = &Pulsebasebyte> {
(0..4)
.map(move |n| unsafe { &*(self as *const Self).cast::<u8>().add(40).add(1 * n).cast() })
.map(move |n| unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(40).add(n).cast() })
}
#[doc = "0x28 - Pulse Base Value Register"]
#[inline(always)]
pub const fn pulsebase(&self) -> &Pulsebase {
unsafe { &*(self as *const Self).cast::<u8>().add(40).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(40).cast() }
}
#[doc = "0x2c - Delay1 Register by Byte"]
#[inline(always)]
pub const fn delay1byte0(&self, n: usize) -> &Delay1byte {
#[allow(clippy::no_effect)]
[(); 4][n];
unsafe { &*(self as *const Self).cast::<u8>().add(44).add(1 * n).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(44).add(n).cast() }
}
#[doc = "Iterator for array of:"]
#[doc = "0x2c - Delay1 Register by Byte"]
#[inline(always)]
pub fn delay1byte0_iter(&self) -> impl Iterator<Item = &Delay1byte> {
(0..4)
.map(move |n| unsafe { &*(self as *const Self).cast::<u8>().add(44).add(1 * n).cast() })
.map(move |n| unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(44).add(n).cast() })
}
#[doc = "0x2c - Delay1 Register"]
#[inline(always)]
pub const fn delay1(&self) -> &Delay1 {
unsafe { &*(self as *const Self).cast::<u8>().add(44).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(44).cast() }
}
#[doc = "0x30 - Delay2 Register by Byte"]
#[inline(always)]
pub const fn delay2byte0(&self, n: usize) -> &Delay2byte {
#[allow(clippy::no_effect)]
[(); 4][n];
unsafe { &*(self as *const Self).cast::<u8>().add(48).add(1 * n).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(48).add(n).cast() }
}
#[doc = "Iterator for array of:"]
#[doc = "0x30 - Delay2 Register by Byte"]
#[inline(always)]
pub fn delay2byte0_iter(&self) -> impl Iterator<Item = &Delay2byte> {
(0..4)
.map(move |n| unsafe { &*(self as *const Self).cast::<u8>().add(48).add(1 * n).cast() })
.map(move |n| unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(48).add(n).cast() })
}
#[doc = "0x30 - Delay2 Register"]
#[inline(always)]
pub const fn delay2(&self) -> &Delay2 {
unsafe { &*(self as *const Self).cast::<u8>().add(48).cast() }
unsafe { &*core::ptr::from_ref(self).cast::<u8>().add(48).cast() }
}
#[doc = "0x34 - Interrupt Sense Register (1:Level Sensitive, 0:Edge Sensitive)"]
#[inline(always)]
@ -316,13 +312,13 @@ impl RegisterBlock {
&self.perid
}
}
#[doc = "DATAIN (r) register accessor: Data In Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`datain::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@datain`]
#[doc = "DATAIN (r) register accessor: Data In Register\n\nYou can [`read`](crate::Reg::read) this register and get [`datain::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@datain`]
module"]
#[doc(alias = "DATAIN")]
pub type Datain = crate::Reg<datain::DatainSpec>;
#[doc = "Data In Register"]
pub mod datain;
#[doc = "DATAINBYTE (r) register accessor: Data In Register by Byte\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`datainbyte::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@datainbyte`]
#[doc = "DATAINBYTE (r) register accessor: Data In Register by Byte\n\nYou can [`read`](crate::Reg::read) this register and get [`datainbyte::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@datainbyte`]
module"]
#[doc(alias = "DATAINBYTE")]
pub type Datainbyte = crate::Reg<datainbyte::DatainbyteSpec>;
@ -332,13 +328,13 @@ pub use datain as datainraw;
pub use datainbyte as datainrawbyte;
pub use Datain as Datainraw;
pub use Datainbyte as Datainrawbyte;
#[doc = "DATAOUT (w) register accessor: Data Out Register\n\nYou can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`dataout::W`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@dataout`]
#[doc = "DATAOUT (w) register accessor: Data Out Register\n\nYou can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`dataout::W`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@dataout`]
module"]
#[doc(alias = "DATAOUT")]
pub type Dataout = crate::Reg<dataout::DataoutSpec>;
#[doc = "Data Out Register"]
pub mod dataout;
#[doc = "DATAOUTBYTE (w) register accessor: Data Out Register by Byte\n\nYou can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`dataoutbyte::W`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@dataoutbyte`]
#[doc = "DATAOUTBYTE (w) register accessor: Data Out Register by Byte\n\nYou can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`dataoutbyte::W`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@dataoutbyte`]
module"]
#[doc(alias = "DATAOUTBYTE")]
pub type Dataoutbyte = crate::Reg<dataoutbyte::DataoutbyteSpec>;
@ -360,13 +356,13 @@ pub use Dataoutbyte as Dataoutrawbyte;
pub use Dataoutbyte as Setoutbyte;
pub use Dataoutbyte as Clroutbyte;
pub use Dataoutbyte as Togoutbyte;
#[doc = "DATAMASK (rw) register accessor: Data mask Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`datamask::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`datamask::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@datamask`]
#[doc = "DATAMASK (rw) register accessor: Data mask Register\n\nYou can [`read`](crate::Reg::read) this register and get [`datamask::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`datamask::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@datamask`]
module"]
#[doc(alias = "DATAMASK")]
pub type Datamask = crate::Reg<datamask::DatamaskSpec>;
#[doc = "Data mask Register"]
pub mod datamask;
#[doc = "DATAMASKBYTE (rw) register accessor: Data Out Register by Byte\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`datamaskbyte::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`datamaskbyte::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@datamaskbyte`]
#[doc = "DATAMASKBYTE (rw) register accessor: Data Out Register by Byte\n\nYou can [`read`](crate::Reg::read) this register and get [`datamaskbyte::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`datamaskbyte::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@datamaskbyte`]
module"]
#[doc(alias = "DATAMASKBYTE")]
pub type Datamaskbyte = crate::Reg<datamaskbyte::DatamaskbyteSpec>;
@ -392,49 +388,49 @@ pub use Datamaskbyte as Pulsebyte;
pub use Datamaskbyte as Pulsebasebyte;
pub use Datamaskbyte as Delay1byte;
pub use Datamaskbyte as Delay2byte;
#[doc = "IRQ_SEN (rw) register accessor: Interrupt Sense Register (1:Level Sensitive, 0:Edge Sensitive)\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`irq_sen::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`irq_sen::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@irq_sen`]
#[doc = "IRQ_SEN (rw) register accessor: Interrupt Sense Register (1:Level Sensitive, 0:Edge Sensitive)\n\nYou can [`read`](crate::Reg::read) this register and get [`irq_sen::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`irq_sen::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@irq_sen`]
module"]
#[doc(alias = "IRQ_SEN")]
pub type IrqSen = crate::Reg<irq_sen::IrqSenSpec>;
#[doc = "Interrupt Sense Register (1:Level Sensitive, 0:Edge Sensitive)"]
pub mod irq_sen;
#[doc = "IRQ_EDGE (rw) register accessor: Interrupt Both Edge Register (1:Both Edges, 0:Single Edge)\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`irq_edge::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`irq_edge::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@irq_edge`]
#[doc = "IRQ_EDGE (rw) register accessor: Interrupt Both Edge Register (1:Both Edges, 0:Single Edge)\n\nYou can [`read`](crate::Reg::read) this register and get [`irq_edge::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`irq_edge::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@irq_edge`]
module"]
#[doc(alias = "IRQ_EDGE")]
pub type IrqEdge = crate::Reg<irq_edge::IrqEdgeSpec>;
#[doc = "Interrupt Both Edge Register (1:Both Edges, 0:Single Edge)"]
pub mod irq_edge;
#[doc = "IRQ_EVT (rw) register accessor: Interrupt Event Register (1:HighLevel/L->H Edge, 0:LowLevel/H->L Edge)\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`irq_evt::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`irq_evt::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@irq_evt`]
#[doc = "IRQ_EVT (rw) register accessor: Interrupt Event Register (1:HighLevel/L->H Edge, 0:LowLevel/H->L Edge)\n\nYou can [`read`](crate::Reg::read) this register and get [`irq_evt::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`irq_evt::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@irq_evt`]
module"]
#[doc(alias = "IRQ_EVT")]
pub type IrqEvt = crate::Reg<irq_evt::IrqEvtSpec>;
#[doc = "Interrupt Event Register (1:HighLevel/L->H Edge, 0:LowLevel/H->L Edge)"]
pub mod irq_evt;
#[doc = "IRQ_ENB (rw) register accessor: Interrupt Enable Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`irq_enb::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`irq_enb::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@irq_enb`]
#[doc = "IRQ_ENB (rw) register accessor: Interrupt Enable Register\n\nYou can [`read`](crate::Reg::read) this register and get [`irq_enb::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`irq_enb::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@irq_enb`]
module"]
#[doc(alias = "IRQ_ENB")]
pub type IrqEnb = crate::Reg<irq_enb::IrqEnbSpec>;
#[doc = "Interrupt Enable Register"]
pub mod irq_enb;
#[doc = "IRQ_RAW (r) register accessor: Raw Interrupt Status\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`irq_raw::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@irq_raw`]
#[doc = "IRQ_RAW (r) register accessor: Raw Interrupt Status\n\nYou can [`read`](crate::Reg::read) this register and get [`irq_raw::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@irq_raw`]
module"]
#[doc(alias = "IRQ_RAW")]
pub type IrqRaw = crate::Reg<irq_raw::IrqRawSpec>;
#[doc = "Raw Interrupt Status"]
pub mod irq_raw;
#[doc = "IRQ_END (r) register accessor: Masked Interrupt Status\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`irq_end::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@irq_end`]
#[doc = "IRQ_END (r) register accessor: Masked Interrupt Status\n\nYou can [`read`](crate::Reg::read) this register and get [`irq_end::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@irq_end`]
module"]
#[doc(alias = "IRQ_END")]
pub type IrqEnd = crate::Reg<irq_end::IrqEndSpec>;
#[doc = "Masked Interrupt Status"]
pub mod irq_end;
#[doc = "EDGE_STATUS (rw) register accessor: Edge Status Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`edge_status::R`]. You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`edge_status::W`]. You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@edge_status`]
#[doc = "EDGE_STATUS (rw) register accessor: Edge Status Register\n\nYou can [`read`](crate::Reg::read) this register and get [`edge_status::R`]. You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`edge_status::W`]. You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@edge_status`]
module"]
#[doc(alias = "EDGE_STATUS")]
pub type EdgeStatus = crate::Reg<edge_status::EdgeStatusSpec>;
#[doc = "Edge Status Register"]
pub mod edge_status;
#[doc = "PERID (r) register accessor: Peripheral ID Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`perid::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@perid`]
#[doc = "PERID (r) register accessor: Peripheral ID Register\n\nYou can [`read`](crate::Reg::read) this register and get [`perid::R`]. See [API](https://docs.rs/svd2rust/#read--modify--write-api).\n\nFor information about available fields see [`mod@perid`]
module"]
#[doc(alias = "PERID")]
pub type Perid = crate::Reg<perid::PeridSpec>;

View File

@ -5,7 +5,7 @@ impl core::fmt::Debug for R {
write!(f, "{}", self.bits())
}
}
#[doc = "Data In Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`datain::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Data In Register\n\nYou can [`read`](crate::Reg::read) this register and get [`datain::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct DatainSpec;
impl crate::RegisterSpec for DatainSpec {
type Ux = u32;

View File

@ -5,7 +5,7 @@ impl core::fmt::Debug for R {
write!(f, "{}", self.bits())
}
}
#[doc = "Data In Register by Byte\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`datainbyte::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Data In Register by Byte\n\nYou can [`read`](crate::Reg::read) this register and get [`datainbyte::R`](R). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct DatainbyteSpec;
impl crate::RegisterSpec for DatainbyteSpec {
type Ux = u8;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "Data mask Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`datamask::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`datamask::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Data mask Register\n\nYou can [`read`](crate::Reg::read) this register and get [`datamask::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`datamask::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct DatamaskSpec;
impl crate::RegisterSpec for DatamaskSpec {
type Ux = u32;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "Data Out Register by Byte\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`datamaskbyte::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`datamaskbyte::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Data Out Register by Byte\n\nYou can [`read`](crate::Reg::read) this register and get [`datamaskbyte::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`datamaskbyte::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct DatamaskbyteSpec;
impl crate::RegisterSpec for DatamaskbyteSpec {
type Ux = u8;

View File

@ -6,7 +6,7 @@ impl core::fmt::Debug for crate::generic::Reg<DataoutSpec> {
}
}
impl W {}
#[doc = "Data Out Register\n\nYou can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`dataout::W`](W). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Data Out Register\n\nYou can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`dataout::W`](W). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct DataoutSpec;
impl crate::RegisterSpec for DataoutSpec {
type Ux = u32;

View File

@ -6,7 +6,7 @@ impl core::fmt::Debug for crate::generic::Reg<DataoutbyteSpec> {
}
}
impl W {}
#[doc = "Data Out Register by Byte\n\nYou can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`dataoutbyte::W`](W). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Data Out Register by Byte\n\nYou can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`dataoutbyte::W`](W). See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct DataoutbyteSpec;
impl crate::RegisterSpec for DataoutbyteSpec {
type Ux = u8;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "Edge Status Register\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`edge_status::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`edge_status::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Edge Status Register\n\nYou can [`read`](crate::Reg::read) this register and get [`edge_status::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`edge_status::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct EdgeStatusSpec;
impl crate::RegisterSpec for EdgeStatusSpec {
type Ux = u32;

View File

@ -8,7 +8,7 @@ impl core::fmt::Debug for R {
}
}
impl W {}
#[doc = "Interrupt Both Edge Register (1:Both Edges, 0:Single Edge)\n\nYou can [`read`](crate::generic::Reg::read) this register and get [`irq_edge::R`](R). You can [`reset`](crate::generic::Reg::reset), [`write`](crate::generic::Reg::write), [`write_with_zero`](crate::generic::Reg::write_with_zero) this register using [`irq_edge::W`](W). You can also [`modify`](crate::generic::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
#[doc = "Interrupt Both Edge Register (1:Both Edges, 0:Single Edge)\n\nYou can [`read`](crate::Reg::read) this register and get [`irq_edge::R`](R). You can [`reset`](crate::Reg::reset), [`write`](crate::Reg::write), [`write_with_zero`](crate::Reg::write_with_zero) this register using [`irq_edge::W`](W). You can also [`modify`](crate::Reg::modify) this register. See [API](https://docs.rs/svd2rust/#read--modify--write-api)."]
pub struct IrqEdgeSpec;
impl crate::RegisterSpec for IrqEdgeSpec {
type Ux = u32;

Some files were not shown because too many files have changed in this diff Show More